summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore15
-rw-r--r--SConstruct4
-rw-r--r--core/SCsub5
-rw-r--r--core/bind/core_bind.cpp538
-rw-r--r--core/bind/core_bind.h8
-rw-r--r--core/class_db.cpp26
-rw-r--r--core/class_db.h28
-rw-r--r--core/compressed_translation.cpp2
-rw-r--r--core/core_string_names.cpp2
-rw-r--r--core/dvector.h11
-rw-r--r--core/func_ref.cpp4
-rw-r--r--core/global_config.cpp1018
-rw-r--r--core/global_config.h160
-rw-r--r--core/globals.cpp1049
-rw-r--r--core/globals.h160
-rw-r--r--core/hash_map.h61
-rw-r--r--core/hashfuncs.h42
-rw-r--r--core/helper/SCsub7
-rw-r--r--core/helper/math_fieldwise.cpp171
-rw-r--r--core/helper/math_fieldwise.h40
-rw-r--r--core/input_map.cpp28
-rw-r--r--core/io/config_file.cpp18
-rw-r--r--core/io/file_access_memory.cpp2
-rw-r--r--core/io/file_access_network.cpp2
-rw-r--r--core/io/file_access_pack.cpp6
-rw-r--r--core/io/http_client.cpp59
-rw-r--r--core/io/http_client.h2
-rw-r--r--core/io/ip.cpp16
-rw-r--r--core/io/ip_address.cpp27
-rw-r--r--core/io/ip_address.h9
-rw-r--r--core/io/json.cpp4
-rw-r--r--core/io/marshalls.cpp4
-rw-r--r--core/io/networked_multiplayer_peer.cpp16
-rw-r--r--core/io/packet_peer.cpp16
-rw-r--r--core/io/packet_peer_udp.cpp28
-rw-r--r--core/io/packet_peer_udp.h7
-rw-r--r--core/io/pck_packer.cpp6
-rw-r--r--core/io/resource_format_binary.cpp51
-rw-r--r--core/io/resource_format_binary.h2
-rw-r--r--core/io/resource_import.cpp35
-rw-r--r--core/io/resource_import.h28
-rw-r--r--core/io/resource_loader.cpp20
-rw-r--r--core/io/resource_saver.cpp2
-rw-r--r--core/io/stream_peer.cpp92
-rw-r--r--core/io/stream_peer_ssl.cpp8
-rw-r--r--core/io/stream_peer_tcp.cpp23
-rw-r--r--core/io/stream_peer_tcp.h3
-rw-r--r--core/io/tcp_server.cpp26
-rw-r--r--core/io/tcp_server.h6
-rw-r--r--core/io/xml_parser.cpp34
-rw-r--r--core/math/a_star.cpp26
-rw-r--r--core/math/audio_frame.cpp28
-rw-r--r--core/math/audio_frame.h28
-rw-r--r--core/math/geometry.h28
-rw-r--r--core/math/math_funcs.h4
-rw-r--r--core/message_queue.cpp2
-rw-r--r--core/method_ptrcall.h28
-rw-r--r--core/object.cpp76
-rw-r--r--core/object.h14
-rw-r--r--core/os/dir_access.cpp2
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/input.cpp70
-rw-r--r--core/os/main_loop.cpp12
-rw-r--r--core/os/os.cpp12
-rw-r--r--core/os/os.h6
-rw-r--r--core/os/power.h44
-rw-r--r--core/os/rw_lock.cpp31
-rw-r--r--core/os/rw_lock.h28
-rw-r--r--core/packed_data_container.cpp28
-rw-r--r--core/pool_allocator.cpp4
-rw-r--r--core/reference.cpp8
-rw-r--r--core/register_core_types.cpp2
-rw-r--r--core/resource.cpp30
-rw-r--r--core/script_debugger_remote.cpp2
-rw-r--r--core/script_language.cpp14
-rw-r--r--core/string_db.h3
-rw-r--r--core/translation.cpp38
-rw-r--r--core/undo_redo.cpp22
-rw-r--r--core/ustring.cpp47
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant.cpp192
-rw-r--r--core/variant.h7
-rw-r--r--core/variant_call.cpp12
-rw-r--r--core/variant_op.cpp4
-rw-r--r--core/variant_parser.cpp2
-rw-r--r--doc/base/classes.xml42
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp2
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp2
-rw-r--r--drivers/gles2/shader_gles2.h2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp39
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h28
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp38
-rw-r--r--drivers/gles3/rasterizer_gles3.h28
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp73
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h28
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp150
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h51
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp30
-rw-r--r--drivers/gles3/shader_compiler_gles3.h28
-rw-r--r--drivers/gles3/shader_gles3.cpp4
-rw-r--r--drivers/gles3/shader_gles3.h6
-rw-r--r--drivers/gles3/shaders/scene.glsl24
-rw-r--r--drivers/gles3/shaders/ssao.glsl18
-rw-r--r--drivers/gles3/shaders/ssao_minify.glsl2
-rw-r--r--drivers/png/resource_saver_png.cpp2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp2
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp2
-rw-r--r--drivers/unix/memory_pool_static_malloc.cpp2
-rw-r--r--drivers/unix/memory_pool_static_malloc.h0
-rw-r--r--drivers/unix/os_unix.cpp18
-rw-r--r--drivers/unix/packet_peer_udp_posix.cpp40
-rw-r--r--drivers/unix/packet_peer_udp_posix.h3
-rw-r--r--drivers/unix/rw_lock_posix.cpp32
-rw-r--r--drivers/unix/rw_lock_posix.h28
-rw-r--r--drivers/unix/socket_helpers.h44
-rw-r--r--drivers/unix/stream_peer_tcp_posix.cpp21
-rw-r--r--drivers/unix/stream_peer_tcp_posix.h4
-rw-r--r--drivers/unix/tcp_server_posix.cpp26
-rw-r--r--drivers/unix/tcp_server_posix.h3
-rw-r--r--drivers/windows/rw_lock_windows.cpp32
-rw-r--r--drivers/windows/rw_lock_windows.h28
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.cpp2
-rw-r--r--editor/SCsub205
-rw-r--r--editor/animation_editor.cpp4331
-rw-r--r--editor/animation_editor.h (renamed from tools/editor/animation_editor.h)0
-rw-r--r--editor/array_property_edit.cpp310
-rw-r--r--editor/array_property_edit.h (renamed from tools/editor/array_property_edit.h)0
-rw-r--r--editor/asset_library_editor_plugin.cpp1553
-rw-r--r--editor/asset_library_editor_plugin.h (renamed from tools/editor/asset_library_editor_plugin.h)0
-rw-r--r--editor/call_dialog.cpp (renamed from tools/editor/call_dialog.cpp)0
-rw-r--r--editor/call_dialog.h85
-rw-r--r--editor/code_editor.cpp1323
-rw-r--r--editor/code_editor.h261
-rw-r--r--editor/collada/SCsub (renamed from tools/editor/collada/SCsub)0
-rw-r--r--editor/collada/collada.cpp2801
-rw-r--r--editor/collada/collada.h663
-rw-r--r--editor/connections_dialog.cpp (renamed from tools/editor/connections_dialog.cpp)0
-rw-r--r--editor/connections_dialog.h134
-rw-r--r--editor/create_dialog.cpp961
-rw-r--r--editor/create_dialog.h (renamed from tools/editor/create_dialog.h)0
-rw-r--r--editor/dependency_editor.cpp725
-rw-r--r--editor/dependency_editor.h (renamed from tools/editor/dependency_editor.h)0
-rw-r--r--editor/doc/SCsub (renamed from tools/editor/doc/SCsub)0
-rw-r--r--editor/doc/doc_data.cpp1148
-rw-r--r--editor/doc/doc_data.h111
-rw-r--r--editor/doc/doc_dump.cpp (renamed from tools/editor/doc/doc_dump.cpp)0
-rw-r--r--editor/doc/doc_dump.h (renamed from tools/editor/doc/doc_dump.h)0
-rw-r--r--editor/doc_code_font.h (renamed from tools/editor/doc_code_font.h)0
-rw-r--r--editor/doc_font.h (renamed from tools/editor/doc_font.h)0
-rw-r--r--editor/doc_title_font.h (renamed from tools/editor/doc_title_font.h)0
-rw-r--r--editor/editor_asset_installer.cpp (renamed from tools/editor/editor_asset_installer.cpp)0
-rw-r--r--editor/editor_asset_installer.h (renamed from tools/editor/editor_asset_installer.h)0
-rw-r--r--editor/editor_audio_buses.cpp1221
-rw-r--r--editor/editor_audio_buses.h214
-rw-r--r--editor/editor_autoload_settings.cpp610
-rw-r--r--editor/editor_autoload_settings.h (renamed from tools/editor/editor_autoload_settings.h)0
-rw-r--r--editor/editor_data.cpp979
-rw-r--r--editor/editor_data.h269
-rw-r--r--editor/editor_dir_dialog.cpp276
-rw-r--r--editor/editor_dir_dialog.h (renamed from tools/editor/editor_dir_dialog.h)0
-rw-r--r--editor/editor_export.cpp3231
-rw-r--r--editor/editor_export.h297
-rw-r--r--editor/editor_file_dialog.cpp1531
-rw-r--r--editor/editor_file_dialog.h (renamed from tools/editor/editor_file_dialog.h)0
-rw-r--r--editor/editor_file_system.cpp1550
-rw-r--r--editor/editor_file_system.h (renamed from tools/editor/editor_file_system.h)0
-rw-r--r--editor/editor_fonts.cpp (renamed from tools/editor/editor_fonts.cpp)0
-rw-r--r--editor/editor_fonts.h (renamed from tools/editor/editor_fonts.h)0
-rw-r--r--editor/editor_help.cpp1929
-rw-r--r--editor/editor_help.h222
-rw-r--r--editor/editor_icons.h (renamed from tools/editor/editor_icons.h)0
-rw-r--r--editor/editor_initialize_ssl.cpp (renamed from tools/editor/editor_initialize_ssl.cpp)0
-rw-r--r--editor/editor_initialize_ssl.h (renamed from tools/editor/editor_initialize_ssl.h)0
-rw-r--r--editor/editor_log.cpp242
-rw-r--r--editor/editor_log.h (renamed from tools/editor/editor_log.h)0
-rw-r--r--editor/editor_name_dialog.cpp (renamed from tools/editor/editor_name_dialog.cpp)0
-rw-r--r--editor/editor_name_dialog.h (renamed from tools/editor/editor_name_dialog.h)0
-rw-r--r--editor/editor_node.cpp6587
-rw-r--r--editor/editor_node.h833
-rw-r--r--editor/editor_path.cpp (renamed from tools/editor/editor_path.cpp)0
-rw-r--r--editor/editor_path.h (renamed from tools/editor/editor_path.h)0
-rw-r--r--editor/editor_plugin.cpp432
-rw-r--r--editor/editor_plugin.h201
-rw-r--r--editor/editor_plugin_settings.cpp216
-rw-r--r--editor/editor_plugin_settings.h (renamed from tools/editor/editor_plugin_settings.h)0
-rw-r--r--editor/editor_profiler.cpp784
-rw-r--r--editor/editor_profiler.h (renamed from tools/editor/editor_profiler.h)0
-rw-r--r--editor/editor_reimport_dialog.cpp (renamed from tools/editor/editor_reimport_dialog.cpp)0
-rw-r--r--editor/editor_reimport_dialog.h (renamed from tools/editor/editor_reimport_dialog.h)0
-rw-r--r--editor/editor_resource_preview.cpp439
-rw-r--r--editor/editor_resource_preview.h (renamed from tools/editor/editor_resource_preview.h)0
-rw-r--r--editor/editor_run.cpp211
-rw-r--r--editor/editor_run.h67
-rw-r--r--editor/editor_run_native.cpp189
-rw-r--r--editor/editor_run_native.h (renamed from tools/editor/editor_run_native.h)0
-rw-r--r--editor/editor_run_script.cpp97
-rw-r--r--editor/editor_run_script.h (renamed from tools/editor/editor_run_script.h)0
-rw-r--r--editor/editor_scale.cpp (renamed from tools/editor/editor_scale.cpp)0
-rw-r--r--editor/editor_scale.h (renamed from tools/editor/editor_scale.h)0
-rw-r--r--editor/editor_settings.cpp1158
-rw-r--r--editor/editor_settings.h180
-rw-r--r--editor/editor_sub_scene.cpp238
-rw-r--r--editor/editor_sub_scene.h69
-rw-r--r--editor/editor_themes.cpp (renamed from tools/editor/editor_themes.cpp)0
-rw-r--r--editor/editor_themes.h (renamed from tools/editor/editor_themes.h)0
-rw-r--r--editor/file_type_cache.cpp108
-rw-r--r--editor/file_type_cache.h (renamed from tools/editor/file_type_cache.h)0
-rw-r--r--editor/fileserver/SCsub (renamed from tools/editor/fileserver/SCsub)0
-rw-r--r--editor/fileserver/editor_file_server.cpp (renamed from tools/editor/fileserver/editor_file_server.cpp)0
-rw-r--r--editor/fileserver/editor_file_server.h (renamed from tools/editor/fileserver/editor_file_server.h)0
-rw-r--r--editor/filesystem_dock.cpp1891
-rw-r--r--editor/filesystem_dock.h217
-rw-r--r--editor/groups_editor.cpp (renamed from tools/editor/groups_editor.cpp)0
-rw-r--r--editor/groups_editor.h (renamed from tools/editor/groups_editor.h)0
-rw-r--r--editor/icons/2x/icon_accept_dialog.png (renamed from tools/editor/icons/2x/icon_accept_dialog.png)bin581 -> 581 bytes
-rw-r--r--editor/icons/2x/icon_add.png (renamed from tools/editor/icons/2x/icon_add.png)bin151 -> 151 bytes
-rw-r--r--editor/icons/2x/icon_add_track.png (renamed from tools/editor/icons/2x/icon_add_track.png)bin151 -> 151 bytes
-rw-r--r--editor/icons/2x/icon_anchor.png (renamed from tools/editor/icons/2x/icon_anchor.png)bin828 -> 828 bytes
-rw-r--r--editor/icons/2x/icon_animated_sprite.png (renamed from tools/editor/icons/2x/icon_animated_sprite.png)bin1212 -> 1212 bytes
-rw-r--r--editor/icons/2x/icon_animated_sprite_3d.png (renamed from tools/editor/icons/2x/icon_animated_sprite_3d.png)bin1125 -> 1125 bytes
-rw-r--r--editor/icons/2x/icon_animation.png (renamed from tools/editor/icons/2x/icon_animation.png)bin912 -> 912 bytes
-rw-r--r--editor/icons/2x/icon_animation_player.png (renamed from tools/editor/icons/2x/icon_animation_player.png)bin174 -> 174 bytes
-rw-r--r--editor/icons/2x/icon_animation_tree.png (renamed from tools/editor/icons/2x/icon_animation_tree.png)bin471 -> 471 bytes
-rw-r--r--editor/icons/2x/icon_animation_tree_player.png (renamed from tools/editor/icons/2x/icon_animation_tree_player.png)bin471 -> 471 bytes
-rw-r--r--editor/icons/2x/icon_area.png (renamed from tools/editor/icons/2x/icon_area.png)bin209 -> 209 bytes
-rw-r--r--editor/icons/2x/icon_area_2d.png (renamed from tools/editor/icons/2x/icon_area_2d.png)bin211 -> 211 bytes
-rw-r--r--editor/icons/2x/icon_arrow_left.png (renamed from tools/editor/icons/2x/icon_arrow_left.png)bin333 -> 333 bytes
-rw-r--r--editor/icons/2x/icon_arrow_right.png (renamed from tools/editor/icons/2x/icon_arrow_right.png)bin308 -> 308 bytes
-rw-r--r--editor/icons/2x/icon_arrow_up.png (renamed from tools/editor/icons/2x/icon_arrow_up.png)bin293 -> 293 bytes
-rw-r--r--editor/icons/2x/icon_atlas_texture.png (renamed from tools/editor/icons/2x/icon_atlas_texture.png)bin382 -> 382 bytes
-rw-r--r--editor/icons/2x/icon_audio_stream_gibberish.png (renamed from tools/editor/icons/2x/icon_audio_stream_gibberish.png)bin437 -> 437 bytes
-rw-r--r--editor/icons/2x/icon_auto_play.png (renamed from tools/editor/icons/2x/icon_auto_play.png)bin699 -> 699 bytes
-rw-r--r--editor/icons/2x/icon_back.png (renamed from tools/editor/icons/2x/icon_back.png)bin323 -> 323 bytes
-rw-r--r--editor/icons/2x/icon_back_buffer_copy.png (renamed from tools/editor/icons/2x/icon_back_buffer_copy.png)bin190 -> 190 bytes
-rw-r--r--editor/icons/2x/icon_bake.png (renamed from tools/editor/icons/2x/icon_bake.png)bin267 -> 267 bytes
-rw-r--r--editor/icons/2x/icon_baked_light.png (renamed from tools/editor/icons/2x/icon_baked_light.png)bin267 -> 267 bytes
-rw-r--r--editor/icons/2x/icon_baked_light_instance.png (renamed from tools/editor/icons/2x/icon_baked_light_instance.png)bin264 -> 264 bytes
-rw-r--r--editor/icons/2x/icon_baked_light_sampler.png (renamed from tools/editor/icons/2x/icon_baked_light_sampler.png)bin391 -> 391 bytes
-rw-r--r--editor/icons/2x/icon_bit_map.png (renamed from tools/editor/icons/2x/icon_bit_map.png)bin148 -> 148 bytes
-rw-r--r--editor/icons/2x/icon_bitmap_font.png (renamed from tools/editor/icons/2x/icon_bitmap_font.png)bin191 -> 191 bytes
-rw-r--r--editor/icons/2x/icon_blend.png (renamed from tools/editor/icons/2x/icon_blend.png)bin1091 -> 1091 bytes
-rw-r--r--editor/icons/2x/icon_bone.png (renamed from tools/editor/icons/2x/icon_bone.png)bin597 -> 597 bytes
-rw-r--r--editor/icons/2x/icon_bone_attachment.png (renamed from tools/editor/icons/2x/icon_bone_attachment.png)bin576 -> 576 bytes
-rw-r--r--editor/icons/2x/icon_bone_track.png (renamed from tools/editor/icons/2x/icon_bone_track.png)bin565 -> 565 bytes
-rw-r--r--editor/icons/2x/icon_bool.png (renamed from tools/editor/icons/2x/icon_bool.png)bin171 -> 171 bytes
-rw-r--r--editor/icons/2x/icon_box_shape.png (renamed from tools/editor/icons/2x/icon_box_shape.png)bin597 -> 597 bytes
-rw-r--r--editor/icons/2x/icon_button.png (renamed from tools/editor/icons/2x/icon_button.png)bin186 -> 186 bytes
-rw-r--r--editor/icons/2x/icon_button_group.png (renamed from tools/editor/icons/2x/icon_button_group.png)bin251 -> 251 bytes
-rw-r--r--editor/icons/2x/icon_camera.png (renamed from tools/editor/icons/2x/icon_camera.png)bin352 -> 352 bytes
-rw-r--r--editor/icons/2x/icon_camera_2d.png (renamed from tools/editor/icons/2x/icon_camera_2d.png)bin364 -> 364 bytes
-rw-r--r--editor/icons/2x/icon_canvas_item.png (renamed from tools/editor/icons/2x/icon_canvas_item.png)bin709 -> 709 bytes
-rw-r--r--editor/icons/2x/icon_canvas_item_material.png (renamed from tools/editor/icons/2x/icon_canvas_item_material.png)bin640 -> 640 bytes
-rw-r--r--editor/icons/2x/icon_canvas_item_shader.png (renamed from tools/editor/icons/2x/icon_canvas_item_shader.png)bin716 -> 716 bytes
-rw-r--r--editor/icons/2x/icon_canvas_item_shader_graph.png (renamed from tools/editor/icons/2x/icon_canvas_item_shader_graph.png)bin707 -> 707 bytes
-rw-r--r--editor/icons/2x/icon_canvas_layer.png (renamed from tools/editor/icons/2x/icon_canvas_layer.png)bin860 -> 860 bytes
-rw-r--r--editor/icons/2x/icon_canvas_modulate.png (renamed from tools/editor/icons/2x/icon_canvas_modulate.png)bin273 -> 273 bytes
-rw-r--r--editor/icons/2x/icon_capsule_shape.png (renamed from tools/editor/icons/2x/icon_capsule_shape.png)bin372 -> 372 bytes
-rw-r--r--editor/icons/2x/icon_capsule_shape_2d.png (renamed from tools/editor/icons/2x/icon_capsule_shape_2d.png)bin552 -> 552 bytes
-rw-r--r--editor/icons/2x/icon_center_container.png (renamed from tools/editor/icons/2x/icon_center_container.png)bin478 -> 478 bytes
-rw-r--r--editor/icons/2x/icon_check_box.png (renamed from tools/editor/icons/2x/icon_check_box.png)bin565 -> 565 bytes
-rw-r--r--editor/icons/2x/icon_check_button.png (renamed from tools/editor/icons/2x/icon_check_button.png)bin528 -> 528 bytes
-rw-r--r--editor/icons/2x/icon_circle_shape_2d.png (renamed from tools/editor/icons/2x/icon_circle_shape_2d.png)bin838 -> 838 bytes
-rw-r--r--editor/icons/2x/icon_class_list.png (renamed from tools/editor/icons/2x/icon_class_list.png)bin192 -> 192 bytes
-rw-r--r--editor/icons/2x/icon_close.png (renamed from tools/editor/icons/2x/icon_close.png)bin461 -> 461 bytes
-rw-r--r--editor/icons/2x/icon_collapse.png (renamed from tools/editor/icons/2x/icon_collapse.png)bin383 -> 383 bytes
-rw-r--r--editor/icons/2x/icon_collision_2d.png (renamed from tools/editor/icons/2x/icon_collision_2d.png)bin407 -> 407 bytes
-rw-r--r--editor/icons/2x/icon_collision_polygon.png (renamed from tools/editor/icons/2x/icon_collision_polygon.png)bin397 -> 397 bytes
-rw-r--r--editor/icons/2x/icon_collision_polygon_2d.png (renamed from tools/editor/icons/2x/icon_collision_polygon_2d.png)bin407 -> 407 bytes
-rw-r--r--editor/icons/2x/icon_collision_shape.png (renamed from tools/editor/icons/2x/icon_collision_shape.png)bin439 -> 439 bytes
-rw-r--r--editor/icons/2x/icon_collision_shape_2d.png (renamed from tools/editor/icons/2x/icon_collision_shape_2d.png)bin235 -> 235 bytes
-rw-r--r--editor/icons/2x/icon_color.png (renamed from tools/editor/icons/2x/icon_color.png)bin1406 -> 1406 bytes
-rw-r--r--editor/icons/2x/icon_color_pick.png (renamed from tools/editor/icons/2x/icon_color_pick.png)bin822 -> 822 bytes
-rw-r--r--editor/icons/2x/icon_color_picker.png (renamed from tools/editor/icons/2x/icon_color_picker.png)bin837 -> 837 bytes
-rw-r--r--editor/icons/2x/icon_color_picker_button.png (renamed from tools/editor/icons/2x/icon_color_picker_button.png)bin942 -> 942 bytes
-rw-r--r--editor/icons/2x/icon_color_ramp.png (renamed from tools/editor/icons/2x/icon_color_ramp.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/2x/icon_color_rect.png (renamed from tools/editor/icons/2x/icon_color_rect.png)bin289 -> 289 bytes
-rw-r--r--editor/icons/2x/icon_concave_polygon_shape.png (renamed from tools/editor/icons/2x/icon_concave_polygon_shape.png)bin709 -> 709 bytes
-rw-r--r--editor/icons/2x/icon_concave_polygon_shape_2d.png (renamed from tools/editor/icons/2x/icon_concave_polygon_shape_2d.png)bin436 -> 436 bytes
-rw-r--r--editor/icons/2x/icon_cone_twist_joint.png (renamed from tools/editor/icons/2x/icon_cone_twist_joint.png)bin906 -> 906 bytes
-rw-r--r--editor/icons/2x/icon_confirmation_dialog.png (renamed from tools/editor/icons/2x/icon_confirmation_dialog.png)bin694 -> 694 bytes
-rw-r--r--editor/icons/2x/icon_connect.png (renamed from tools/editor/icons/2x/icon_connect.png)bin251 -> 251 bytes
-rw-r--r--editor/icons/2x/icon_connection_and_groups.png (renamed from tools/editor/icons/2x/icon_connection_and_groups.png)bin397 -> 397 bytes
-rw-r--r--editor/icons/2x/icon_container.png (renamed from tools/editor/icons/2x/icon_container.png)bin319 -> 319 bytes
-rw-r--r--editor/icons/2x/icon_control.png (renamed from tools/editor/icons/2x/icon_control.png)bin825 -> 825 bytes
-rw-r--r--editor/icons/2x/icon_control_align_bottom_center.png (renamed from tools/editor/icons/2x/icon_control_align_bottom_center.png)bin156 -> 156 bytes
-rw-r--r--editor/icons/2x/icon_control_align_bottom_left.png (renamed from tools/editor/icons/2x/icon_control_align_bottom_left.png)bin154 -> 154 bytes
-rw-r--r--editor/icons/2x/icon_control_align_bottom_right.png (renamed from tools/editor/icons/2x/icon_control_align_bottom_right.png)bin155 -> 155 bytes
-rw-r--r--editor/icons/2x/icon_control_align_bottom_wide.png (renamed from tools/editor/icons/2x/icon_control_align_bottom_wide.png)bin160 -> 160 bytes
-rw-r--r--editor/icons/2x/icon_control_align_center.png (renamed from tools/editor/icons/2x/icon_control_align_center.png)bin171 -> 171 bytes
-rw-r--r--editor/icons/2x/icon_control_align_center_left.png (renamed from tools/editor/icons/2x/icon_control_align_center_left.png)bin130 -> 130 bytes
-rw-r--r--editor/icons/2x/icon_control_align_center_right.png (renamed from tools/editor/icons/2x/icon_control_align_center_right.png)bin127 -> 127 bytes
-rw-r--r--editor/icons/2x/icon_control_align_left_center.png (renamed from tools/editor/icons/2x/icon_control_align_left_center.png)bin169 -> 169 bytes
-rw-r--r--editor/icons/2x/icon_control_align_left_wide.png (renamed from tools/editor/icons/2x/icon_control_align_left_wide.png)bin143 -> 143 bytes
-rw-r--r--editor/icons/2x/icon_control_align_right_center.png (renamed from tools/editor/icons/2x/icon_control_align_right_center.png)bin171 -> 171 bytes
-rw-r--r--editor/icons/2x/icon_control_align_right_wide.png (renamed from tools/editor/icons/2x/icon_control_align_right_wide.png)bin144 -> 144 bytes
-rw-r--r--editor/icons/2x/icon_control_align_top_center.png (renamed from tools/editor/icons/2x/icon_control_align_top_center.png)bin165 -> 165 bytes
-rw-r--r--editor/icons/2x/icon_control_align_top_left.png (renamed from tools/editor/icons/2x/icon_control_align_top_left.png)bin159 -> 159 bytes
-rw-r--r--editor/icons/2x/icon_control_align_top_right.png (renamed from tools/editor/icons/2x/icon_control_align_top_right.png)bin167 -> 167 bytes
-rw-r--r--editor/icons/2x/icon_control_align_top_wide.png (renamed from tools/editor/icons/2x/icon_control_align_top_wide.png)bin160 -> 160 bytes
-rw-r--r--editor/icons/2x/icon_control_align_wide.png (renamed from tools/editor/icons/2x/icon_control_align_wide.png)bin145 -> 145 bytes
-rw-r--r--editor/icons/2x/icon_control_hcenter_wide.png (renamed from tools/editor/icons/2x/icon_control_hcenter_wide.png)bin169 -> 169 bytes
-rw-r--r--editor/icons/2x/icon_control_vcenter_wide.png (renamed from tools/editor/icons/2x/icon_control_vcenter_wide.png)bin148 -> 148 bytes
-rw-r--r--editor/icons/2x/icon_convex_polygon_shape.png (renamed from tools/editor/icons/2x/icon_convex_polygon_shape.png)bin648 -> 648 bytes
-rw-r--r--editor/icons/2x/icon_convex_polygon_shape_2d.png (renamed from tools/editor/icons/2x/icon_convex_polygon_shape_2d.png)bin373 -> 373 bytes
-rw-r--r--editor/icons/2x/icon_copy_node_path.png (renamed from tools/editor/icons/2x/icon_copy_node_path.png)bin356 -> 356 bytes
-rw-r--r--editor/icons/2x/icon_create_new_scene_from.png (renamed from tools/editor/icons/2x/icon_create_new_scene_from.png)bin639 -> 639 bytes
-rw-r--r--editor/icons/2x/icon_cube_map.png (renamed from tools/editor/icons/2x/icon_cube_map.png)bin159 -> 159 bytes
-rw-r--r--editor/icons/2x/icon_curve_2d.png (renamed from tools/editor/icons/2x/icon_curve_2d.png)bin591 -> 591 bytes
-rw-r--r--editor/icons/2x/icon_curve_3d.png (renamed from tools/editor/icons/2x/icon_curve_3d.png)bin522 -> 522 bytes
-rw-r--r--editor/icons/2x/icon_curve_close.png (renamed from tools/editor/icons/2x/icon_curve_close.png)bin610 -> 610 bytes
-rw-r--r--editor/icons/2x/icon_curve_constant.png (renamed from tools/editor/icons/2x/icon_curve_constant.png)bin162 -> 162 bytes
-rw-r--r--editor/icons/2x/icon_curve_create.png (renamed from tools/editor/icons/2x/icon_curve_create.png)bin698 -> 698 bytes
-rw-r--r--editor/icons/2x/icon_curve_curve.png (renamed from tools/editor/icons/2x/icon_curve_curve.png)bin744 -> 744 bytes
-rw-r--r--editor/icons/2x/icon_curve_delete.png (renamed from tools/editor/icons/2x/icon_curve_delete.png)bin926 -> 926 bytes
-rw-r--r--editor/icons/2x/icon_curve_edit.png (renamed from tools/editor/icons/2x/icon_curve_edit.png)bin954 -> 954 bytes
-rw-r--r--editor/icons/2x/icon_curve_in.png (renamed from tools/editor/icons/2x/icon_curve_in.png)bin449 -> 449 bytes
-rw-r--r--editor/icons/2x/icon_curve_in_out.png (renamed from tools/editor/icons/2x/icon_curve_in_out.png)bin494 -> 494 bytes
-rw-r--r--editor/icons/2x/icon_curve_linear.png (renamed from tools/editor/icons/2x/icon_curve_linear.png)bin283 -> 283 bytes
-rw-r--r--editor/icons/2x/icon_curve_out.png (renamed from tools/editor/icons/2x/icon_curve_out.png)bin459 -> 459 bytes
-rw-r--r--editor/icons/2x/icon_curve_out_in.png (renamed from tools/editor/icons/2x/icon_curve_out_in.png)bin489 -> 489 bytes
-rw-r--r--editor/icons/2x/icon_damped_spring_joint_2d.png (renamed from tools/editor/icons/2x/icon_damped_spring_joint_2d.png)bin496 -> 496 bytes
-rw-r--r--editor/icons/2x/icon_debug_continue.png (renamed from tools/editor/icons/2x/icon_debug_continue.png)bin525 -> 525 bytes
-rw-r--r--editor/icons/2x/icon_debug_next.png (renamed from tools/editor/icons/2x/icon_debug_next.png)bin284 -> 284 bytes
-rw-r--r--editor/icons/2x/icon_debug_step.png (renamed from tools/editor/icons/2x/icon_debug_step.png)bin317 -> 317 bytes
-rw-r--r--editor/icons/2x/icon_dependency_changed.png (renamed from tools/editor/icons/2x/icon_dependency_changed.png)bin731 -> 731 bytes
-rw-r--r--editor/icons/2x/icon_dependency_changed_hl.png (renamed from tools/editor/icons/2x/icon_dependency_changed_hl.png)bin601 -> 601 bytes
-rw-r--r--editor/icons/2x/icon_dependency_local_changed.png (renamed from tools/editor/icons/2x/icon_dependency_local_changed.png)bin1104 -> 1104 bytes
-rw-r--r--editor/icons/2x/icon_dependency_local_changed_hl.png (renamed from tools/editor/icons/2x/icon_dependency_local_changed_hl.png)bin926 -> 926 bytes
-rw-r--r--editor/icons/2x/icon_dependency_ok.png (renamed from tools/editor/icons/2x/icon_dependency_ok.png)bin1015 -> 1015 bytes
-rw-r--r--editor/icons/2x/icon_dependency_ok_hl.png (renamed from tools/editor/icons/2x/icon_dependency_ok_hl.png)bin836 -> 836 bytes
-rw-r--r--editor/icons/2x/icon_directional_light.png (renamed from tools/editor/icons/2x/icon_directional_light.png)bin756 -> 756 bytes
-rw-r--r--editor/icons/2x/icon_distraction_free.png (renamed from tools/editor/icons/2x/icon_distraction_free.png)bin575 -> 575 bytes
-rw-r--r--editor/icons/2x/icon_duplicate.png (renamed from tools/editor/icons/2x/icon_duplicate.png)bin225 -> 225 bytes
-rw-r--r--editor/icons/2x/icon_dynamic_font.png (renamed from tools/editor/icons/2x/icon_dynamic_font.png)bin383 -> 383 bytes
-rw-r--r--editor/icons/2x/icon_dynamic_font_data.png (renamed from tools/editor/icons/2x/icon_dynamic_font_data.png)bin379 -> 379 bytes
-rw-r--r--editor/icons/2x/icon_edit.png (renamed from tools/editor/icons/2x/icon_edit.png)bin525 -> 525 bytes
-rw-r--r--editor/icons/2x/icon_edit_key.png (renamed from tools/editor/icons/2x/icon_edit_key.png)bin641 -> 641 bytes
-rw-r--r--editor/icons/2x/icon_edit_pivot.png (renamed from tools/editor/icons/2x/icon_edit_pivot.png)bin595 -> 595 bytes
-rw-r--r--editor/icons/2x/icon_edit_resource.png (renamed from tools/editor/icons/2x/icon_edit_resource.png)bin396 -> 396 bytes
-rw-r--r--editor/icons/2x/icon_editor_3d_handle.png (renamed from tools/editor/icons/2x/icon_editor_3d_handle.png)bin705 -> 705 bytes
-rw-r--r--editor/icons/2x/icon_editor_handle.png (renamed from tools/editor/icons/2x/icon_editor_handle.png)bin427 -> 427 bytes
-rw-r--r--editor/icons/2x/icon_editor_pivot.png (renamed from tools/editor/icons/2x/icon_editor_pivot.png)bin198 -> 198 bytes
-rw-r--r--editor/icons/2x/icon_editor_plugin.png (renamed from tools/editor/icons/2x/icon_editor_plugin.png)bin469 -> 469 bytes
-rw-r--r--editor/icons/2x/icon_enum.png (renamed from tools/editor/icons/2x/icon_enum.png)bin137 -> 137 bytes
-rw-r--r--editor/icons/2x/icon_environment.png (renamed from tools/editor/icons/2x/icon_environment.png)bin1270 -> 1270 bytes
-rw-r--r--editor/icons/2x/icon_error.png (renamed from tools/editor/icons/2x/icon_error.png)bin155 -> 155 bytes
-rw-r--r--editor/icons/2x/icon_error_sign.png (renamed from tools/editor/icons/2x/icon_error_sign.png)bin441 -> 441 bytes
-rw-r--r--editor/icons/2x/icon_event_player.png (renamed from tools/editor/icons/2x/icon_event_player.png)bin167 -> 167 bytes
-rw-r--r--editor/icons/2x/icon_favorites.png (renamed from tools/editor/icons/2x/icon_favorites.png)bin702 -> 702 bytes
-rw-r--r--editor/icons/2x/icon_file.png (renamed from tools/editor/icons/2x/icon_file.png)bin196 -> 196 bytes
-rw-r--r--editor/icons/2x/icon_file_big.png (renamed from tools/editor/icons/2x/icon_file_big.png)bin505 -> 505 bytes
-rw-r--r--editor/icons/2x/icon_file_dialog.png (renamed from tools/editor/icons/2x/icon_file_dialog.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/2x/icon_file_list.png (renamed from tools/editor/icons/2x/icon_file_list.png)bin137 -> 137 bytes
-rw-r--r--editor/icons/2x/icon_file_server.png (renamed from tools/editor/icons/2x/icon_file_server.png)bin172 -> 172 bytes
-rw-r--r--editor/icons/2x/icon_file_server_active.png (renamed from tools/editor/icons/2x/icon_file_server_active.png)bin173 -> 173 bytes
-rw-r--r--editor/icons/2x/icon_file_thumbnail.png (renamed from tools/editor/icons/2x/icon_file_thumbnail.png)bin137 -> 137 bytes
-rw-r--r--editor/icons/2x/icon_filesystem.png (renamed from tools/editor/icons/2x/icon_filesystem.png)bin192 -> 192 bytes
-rw-r--r--editor/icons/2x/icon_fixed_material.png (renamed from tools/editor/icons/2x/icon_fixed_material.png)bin736 -> 736 bytes
-rw-r--r--editor/icons/2x/icon_fixed_spatial_material.png (renamed from tools/editor/icons/2x/icon_fixed_spatial_material.png)bin768 -> 768 bytes
-rw-r--r--editor/icons/2x/icon_folder.png (renamed from tools/editor/icons/2x/icon_folder.png)bin228 -> 228 bytes
-rw-r--r--editor/icons/2x/icon_folder_big.png (renamed from tools/editor/icons/2x/icon_folder_big.png)bin991 -> 991 bytes
-rw-r--r--editor/icons/2x/icon_font.png (renamed from tools/editor/icons/2x/icon_font.png)bin369 -> 369 bytes
-rw-r--r--editor/icons/2x/icon_forward.png (renamed from tools/editor/icons/2x/icon_forward.png)bin326 -> 326 bytes
-rw-r--r--editor/icons/2x/icon_g_d_script.png (renamed from tools/editor/icons/2x/icon_g_d_script.png)bin759 -> 759 bytes
-rw-r--r--editor/icons/2x/icon_g_i_probe.png (renamed from tools/editor/icons/2x/icon_g_i_probe.png)bin680 -> 680 bytes
-rw-r--r--editor/icons/2x/icon_g_i_probe_data.png (renamed from tools/editor/icons/2x/icon_g_i_probe_data.png)bin662 -> 662 bytes
-rw-r--r--editor/icons/2x/icon_generic_6_d_o_f_joint.png (renamed from tools/editor/icons/2x/icon_generic_6_d_o_f_joint.png)bin535 -> 535 bytes
-rw-r--r--editor/icons/2x/icon_gizmo_directional_light.png (renamed from tools/editor/icons/2x/icon_gizmo_directional_light.png)bin8264 -> 8264 bytes
-rw-r--r--editor/icons/2x/icon_gizmo_light.png (renamed from tools/editor/icons/2x/icon_gizmo_light.png)bin6282 -> 6282 bytes
-rw-r--r--editor/icons/2x/icon_gizmo_listener.png (renamed from tools/editor/icons/2x/icon_gizmo_listener.png)bin7636 -> 7636 bytes
-rw-r--r--editor/icons/2x/icon_gizmo_spatial_sample_player.png (renamed from tools/editor/icons/2x/icon_gizmo_spatial_sample_player.png)bin2831 -> 2831 bytes
-rw-r--r--editor/icons/2x/icon_gizmo_spatial_stream_player.png (renamed from tools/editor/icons/2x/icon_gizmo_spatial_stream_player.png)bin3649 -> 3649 bytes
-rw-r--r--editor/icons/2x/icon_godot.png (renamed from tools/editor/icons/2x/icon_godot.png)bin1842 -> 1842 bytes
-rw-r--r--editor/icons/2x/icon_graph_color_ramp.png (renamed from tools/editor/icons/2x/icon_graph_color_ramp.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/2x/icon_graph_comment.png (renamed from tools/editor/icons/2x/icon_graph_comment.png)bin152 -> 152 bytes
-rw-r--r--editor/icons/2x/icon_graph_cube_uniform.png (renamed from tools/editor/icons/2x/icon_graph_cube_uniform.png)bin795 -> 795 bytes
-rw-r--r--editor/icons/2x/icon_graph_curve_map.png (renamed from tools/editor/icons/2x/icon_graph_curve_map.png)bin587 -> 587 bytes
-rw-r--r--editor/icons/2x/icon_graph_default_texture.png (renamed from tools/editor/icons/2x/icon_graph_default_texture.png)bin254 -> 254 bytes
-rw-r--r--editor/icons/2x/icon_graph_edit.png (renamed from tools/editor/icons/2x/icon_graph_edit.png)bin815 -> 815 bytes
-rw-r--r--editor/icons/2x/icon_graph_input.png (renamed from tools/editor/icons/2x/icon_graph_input.png)bin521 -> 521 bytes
-rw-r--r--editor/icons/2x/icon_graph_node.png (renamed from tools/editor/icons/2x/icon_graph_node.png)bin710 -> 710 bytes
-rw-r--r--editor/icons/2x/icon_graph_rgb.png (renamed from tools/editor/icons/2x/icon_graph_rgb.png)bin951 -> 951 bytes
-rw-r--r--editor/icons/2x/icon_graph_rgb_op.png (renamed from tools/editor/icons/2x/icon_graph_rgb_op.png)bin219 -> 219 bytes
-rw-r--r--editor/icons/2x/icon_graph_rgb_uniform.png (renamed from tools/editor/icons/2x/icon_graph_rgb_uniform.png)bin696 -> 696 bytes
-rw-r--r--editor/icons/2x/icon_graph_scalar.png (renamed from tools/editor/icons/2x/icon_graph_scalar.png)bin461 -> 461 bytes
-rw-r--r--editor/icons/2x/icon_graph_scalar_interp.png (renamed from tools/editor/icons/2x/icon_graph_scalar_interp.png)bin307 -> 307 bytes
-rw-r--r--editor/icons/2x/icon_graph_scalar_op.png (renamed from tools/editor/icons/2x/icon_graph_scalar_op.png)bin390 -> 390 bytes
-rw-r--r--editor/icons/2x/icon_graph_scalar_uniform.png (renamed from tools/editor/icons/2x/icon_graph_scalar_uniform.png)bin570 -> 570 bytes
-rw-r--r--editor/icons/2x/icon_graph_scalars_to_vec.png (renamed from tools/editor/icons/2x/icon_graph_scalars_to_vec.png)bin255 -> 255 bytes
-rw-r--r--editor/icons/2x/icon_graph_texscreen.png (renamed from tools/editor/icons/2x/icon_graph_texscreen.png)bin217 -> 217 bytes
-rw-r--r--editor/icons/2x/icon_graph_texture_uniform.png (renamed from tools/editor/icons/2x/icon_graph_texture_uniform.png)bin394 -> 394 bytes
-rw-r--r--editor/icons/2x/icon_graph_time.png (renamed from tools/editor/icons/2x/icon_graph_time.png)bin819 -> 819 bytes
-rw-r--r--editor/icons/2x/icon_graph_vec_dp.png (renamed from tools/editor/icons/2x/icon_graph_vec_dp.png)bin482 -> 482 bytes
-rw-r--r--editor/icons/2x/icon_graph_vec_interp.png (renamed from tools/editor/icons/2x/icon_graph_vec_interp.png)bin307 -> 307 bytes
-rw-r--r--editor/icons/2x/icon_graph_vec_length.png (renamed from tools/editor/icons/2x/icon_graph_vec_length.png)bin513 -> 513 bytes
-rw-r--r--editor/icons/2x/icon_graph_vec_op.png (renamed from tools/editor/icons/2x/icon_graph_vec_op.png)bin387 -> 387 bytes
-rw-r--r--editor/icons/2x/icon_graph_vec_scalar_op.png (renamed from tools/editor/icons/2x/icon_graph_vec_scalar_op.png)bin431 -> 431 bytes
-rw-r--r--editor/icons/2x/icon_graph_vec_to_scalars.png (renamed from tools/editor/icons/2x/icon_graph_vec_to_scalars.png)bin257 -> 257 bytes
-rw-r--r--editor/icons/2x/icon_graph_vecs_to_xform.png (renamed from tools/editor/icons/2x/icon_graph_vecs_to_xform.png)bin282 -> 282 bytes
-rw-r--r--editor/icons/2x/icon_graph_vector.png (renamed from tools/editor/icons/2x/icon_graph_vector.png)bin620 -> 620 bytes
-rw-r--r--editor/icons/2x/icon_graph_vector_uniform.png (renamed from tools/editor/icons/2x/icon_graph_vector_uniform.png)bin718 -> 718 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform.png (renamed from tools/editor/icons/2x/icon_graph_xform.png)bin380 -> 380 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform_mult.png (renamed from tools/editor/icons/2x/icon_graph_xform_mult.png)bin321 -> 321 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform_scalar_func.png (renamed from tools/editor/icons/2x/icon_graph_xform_scalar_func.png)bin467 -> 467 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform_to_vecs.png (renamed from tools/editor/icons/2x/icon_graph_xform_to_vecs.png)bin277 -> 277 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform_uniform.png (renamed from tools/editor/icons/2x/icon_graph_xform_uniform.png)bin526 -> 526 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform_vec_func.png (renamed from tools/editor/icons/2x/icon_graph_xform_vec_func.png)bin476 -> 476 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform_vec_imult.png (renamed from tools/editor/icons/2x/icon_graph_xform_vec_imult.png)bin601 -> 601 bytes
-rw-r--r--editor/icons/2x/icon_graph_xform_vec_mult.png (renamed from tools/editor/icons/2x/icon_graph_xform_vec_mult.png)bin600 -> 600 bytes
-rw-r--r--editor/icons/2x/icon_grid.png (renamed from tools/editor/icons/2x/icon_grid.png)bin194 -> 194 bytes
-rw-r--r--editor/icons/2x/icon_grid_container.png (renamed from tools/editor/icons/2x/icon_grid_container.png)bin329 -> 329 bytes
-rw-r--r--editor/icons/2x/icon_grid_map.png (renamed from tools/editor/icons/2x/icon_grid_map.png)bin138 -> 138 bytes
-rw-r--r--editor/icons/2x/icon_groove_joint_2d.png (renamed from tools/editor/icons/2x/icon_groove_joint_2d.png)bin179 -> 179 bytes
-rw-r--r--editor/icons/2x/icon_group.png (renamed from tools/editor/icons/2x/icon_group.png)bin207 -> 207 bytes
-rw-r--r--editor/icons/2x/icon_groups.png (renamed from tools/editor/icons/2x/icon_groups.png)bin353 -> 353 bytes
-rw-r--r--editor/icons/2x/icon_h_box_container.png (renamed from tools/editor/icons/2x/icon_h_box_container.png)bin307 -> 307 bytes
-rw-r--r--editor/icons/2x/icon_h_button_array.png (renamed from tools/editor/icons/2x/icon_h_button_array.png)bin224 -> 224 bytes
-rw-r--r--editor/icons/2x/icon_h_scroll_bar.png (renamed from tools/editor/icons/2x/icon_h_scroll_bar.png)bin324 -> 324 bytes
-rw-r--r--editor/icons/2x/icon_h_separator.png (renamed from tools/editor/icons/2x/icon_h_separator.png)bin148 -> 148 bytes
-rw-r--r--editor/icons/2x/icon_h_slider.png (renamed from tools/editor/icons/2x/icon_h_slider.png)bin360 -> 360 bytes
-rw-r--r--editor/icons/2x/icon_h_split_container.png (renamed from tools/editor/icons/2x/icon_h_split_container.png)bin399 -> 399 bytes
-rw-r--r--editor/icons/2x/icon_h_t_t_p_request.png (renamed from tools/editor/icons/2x/icon_h_t_t_p_request.png)bin425 -> 425 bytes
-rw-r--r--editor/icons/2x/icon_headphones.png (renamed from tools/editor/icons/2x/icon_headphones.png)bin620 -> 620 bytes
-rw-r--r--editor/icons/2x/icon_help.png (renamed from tools/editor/icons/2x/icon_help.png)bin1126 -> 1126 bytes
-rw-r--r--editor/icons/2x/icon_hidden.png (renamed from tools/editor/icons/2x/icon_hidden.png)bin640 -> 640 bytes
-rw-r--r--editor/icons/2x/icon_hinge_joint.png (renamed from tools/editor/icons/2x/icon_hinge_joint.png)bin663 -> 663 bytes
-rw-r--r--editor/icons/2x/icon_history.png (renamed from tools/editor/icons/2x/icon_history.png)bin814 -> 814 bytes
-rw-r--r--editor/icons/2x/icon_hsize.png (renamed from tools/editor/icons/2x/icon_hsize.png)bin247 -> 247 bytes
-rw-r--r--editor/icons/2x/icon_image.png (renamed from tools/editor/icons/2x/icon_image.png)bin404 -> 404 bytes
-rw-r--r--editor/icons/2x/icon_image_sky_box.png (renamed from tools/editor/icons/2x/icon_image_sky_box.png)bin904 -> 904 bytes
-rw-r--r--editor/icons/2x/icon_image_texture.png (renamed from tools/editor/icons/2x/icon_image_texture.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/2x/icon_immediate_geometry.png (renamed from tools/editor/icons/2x/icon_immediate_geometry.png)bin706 -> 706 bytes
-rw-r--r--editor/icons/2x/icon_import_check.png (renamed from tools/editor/icons/2x/icon_import_check.png)bin386 -> 386 bytes
-rw-r--r--editor/icons/2x/icon_import_fail.png (renamed from tools/editor/icons/2x/icon_import_fail.png)bin464 -> 464 bytes
-rw-r--r--editor/icons/2x/icon_instance.png (renamed from tools/editor/icons/2x/icon_instance.png)bin817 -> 817 bytes
-rw-r--r--editor/icons/2x/icon_instance_options.png (renamed from tools/editor/icons/2x/icon_instance_options.png)bin708 -> 708 bytes
-rw-r--r--editor/icons/2x/icon_integer.png (renamed from tools/editor/icons/2x/icon_integer.png)bin147 -> 147 bytes
-rw-r--r--editor/icons/2x/icon_interp_cubic.png (renamed from tools/editor/icons/2x/icon_interp_cubic.png)bin483 -> 483 bytes
-rw-r--r--editor/icons/2x/icon_interp_linear.png (renamed from tools/editor/icons/2x/icon_interp_linear.png)bin398 -> 398 bytes
-rw-r--r--editor/icons/2x/icon_interp_raw.png (renamed from tools/editor/icons/2x/icon_interp_raw.png)bin221 -> 221 bytes
-rw-r--r--editor/icons/2x/icon_interp_wrap_clamp.png (renamed from tools/editor/icons/2x/icon_interp_wrap_clamp.png)bin348 -> 348 bytes
-rw-r--r--editor/icons/2x/icon_interp_wrap_loop.png (renamed from tools/editor/icons/2x/icon_interp_wrap_loop.png)bin548 -> 548 bytes
-rw-r--r--editor/icons/2x/icon_interpolated_camera.png (renamed from tools/editor/icons/2x/icon_interpolated_camera.png)bin454 -> 454 bytes
-rw-r--r--editor/icons/2x/icon_invalid_key.png (renamed from tools/editor/icons/2x/icon_invalid_key.png)bin385 -> 385 bytes
-rw-r--r--editor/icons/2x/icon_inverse_kinematics.png (renamed from tools/editor/icons/2x/icon_inverse_kinematics.png)bin459 -> 459 bytes
-rw-r--r--editor/icons/2x/icon_item_list.png (renamed from tools/editor/icons/2x/icon_item_list.png)bin338 -> 338 bytes
-rw-r--r--editor/icons/2x/icon_joy_axis.png (renamed from tools/editor/icons/2x/icon_joy_axis.png)bin425 -> 425 bytes
-rw-r--r--editor/icons/2x/icon_joy_button.png (renamed from tools/editor/icons/2x/icon_joy_button.png)bin499 -> 499 bytes
-rw-r--r--editor/icons/2x/icon_joypad.png (renamed from tools/editor/icons/2x/icon_joypad.png)bin380 -> 380 bytes
-rw-r--r--editor/icons/2x/icon_key.png (renamed from tools/editor/icons/2x/icon_key.png)bin572 -> 572 bytes
-rw-r--r--editor/icons/2x/icon_key_hover.png (renamed from tools/editor/icons/2x/icon_key_hover.png)bin376 -> 376 bytes
-rw-r--r--editor/icons/2x/icon_key_invalid.png (renamed from tools/editor/icons/2x/icon_key_invalid.png)bin385 -> 385 bytes
-rw-r--r--editor/icons/2x/icon_key_next.png (renamed from tools/editor/icons/2x/icon_key_next.png)bin579 -> 579 bytes
-rw-r--r--editor/icons/2x/icon_key_selected.png (renamed from tools/editor/icons/2x/icon_key_selected.png)bin353 -> 353 bytes
-rw-r--r--editor/icons/2x/icon_key_value.png (renamed from tools/editor/icons/2x/icon_key_value.png)bin380 -> 380 bytes
-rw-r--r--editor/icons/2x/icon_key_xform.png (renamed from tools/editor/icons/2x/icon_key_xform.png)bin388 -> 388 bytes
-rw-r--r--editor/icons/2x/icon_keyboard.png (renamed from tools/editor/icons/2x/icon_keyboard.png)bin486 -> 486 bytes
-rw-r--r--editor/icons/2x/icon_kinematic_body.png (renamed from tools/editor/icons/2x/icon_kinematic_body.png)bin197 -> 197 bytes
-rw-r--r--editor/icons/2x/icon_kinematic_body_2d.png (renamed from tools/editor/icons/2x/icon_kinematic_body_2d.png)bin204 -> 204 bytes
-rw-r--r--editor/icons/2x/icon_label.png (renamed from tools/editor/icons/2x/icon_label.png)bin370 -> 370 bytes
-rw-r--r--editor/icons/2x/icon_large_texture.png (renamed from tools/editor/icons/2x/icon_large_texture.png)bin211 -> 211 bytes
-rw-r--r--editor/icons/2x/icon_light_2d.png (renamed from tools/editor/icons/2x/icon_light_2d.png)bin669 -> 669 bytes
-rw-r--r--editor/icons/2x/icon_light_occluder_2d.png (renamed from tools/editor/icons/2x/icon_light_occluder_2d.png)bin175 -> 175 bytes
-rw-r--r--editor/icons/2x/icon_line_2d.pngbin0 -> 795 bytes
-rw-r--r--editor/icons/2x/icon_line_edit.png (renamed from tools/editor/icons/2x/icon_line_edit.png)bin323 -> 323 bytes
-rw-r--r--editor/icons/2x/icon_line_shape_2d.png (renamed from tools/editor/icons/2x/icon_line_shape_2d.png)bin597 -> 597 bytes
-rw-r--r--editor/icons/2x/icon_link_button.png (renamed from tools/editor/icons/2x/icon_link_button.png)bin774 -> 774 bytes
-rw-r--r--editor/icons/2x/icon_list_select.png (renamed from tools/editor/icons/2x/icon_list_select.png)bin653 -> 653 bytes
-rw-r--r--editor/icons/2x/icon_listener.png (renamed from tools/editor/icons/2x/icon_listener.png)bin885 -> 885 bytes
-rw-r--r--editor/icons/2x/icon_load.png (renamed from tools/editor/icons/2x/icon_load.png)bin523 -> 523 bytes
-rw-r--r--editor/icons/2x/icon_lock.png (renamed from tools/editor/icons/2x/icon_lock.png)bin441 -> 441 bytes
-rw-r--r--editor/icons/2x/icon_loop.png (renamed from tools/editor/icons/2x/icon_loop.png)bin806 -> 806 bytes
-rw-r--r--editor/icons/2x/icon_loop_interpolation.png (renamed from tools/editor/icons/2x/icon_loop_interpolation.png)bin709 -> 709 bytes
-rw-r--r--editor/icons/2x/icon_main_play.png (renamed from tools/editor/icons/2x/icon_main_play.png)bin359 -> 359 bytes
-rw-r--r--editor/icons/2x/icon_main_stop.png (renamed from tools/editor/icons/2x/icon_main_stop.png)bin197 -> 197 bytes
-rw-r--r--editor/icons/2x/icon_margin_container.png (renamed from tools/editor/icons/2x/icon_margin_container.png)bin365 -> 365 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_cube.png (renamed from tools/editor/icons/2x/icon_material_preview_cube.png)bin562 -> 562 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_cube_off.png (renamed from tools/editor/icons/2x/icon_material_preview_cube_off.png)bin598 -> 598 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_light_1.png (renamed from tools/editor/icons/2x/icon_material_preview_light_1.png)bin724 -> 724 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_light_1_off.png (renamed from tools/editor/icons/2x/icon_material_preview_light_1_off.png)bin596 -> 596 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_light_2.png (renamed from tools/editor/icons/2x/icon_material_preview_light_2.png)bin740 -> 740 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_light_2_off.png (renamed from tools/editor/icons/2x/icon_material_preview_light_2_off.png)bin843 -> 843 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_sphere.png (renamed from tools/editor/icons/2x/icon_material_preview_sphere.png)bin704 -> 704 bytes
-rw-r--r--editor/icons/2x/icon_material_preview_sphere_off.png (renamed from tools/editor/icons/2x/icon_material_preview_sphere_off.png)bin518 -> 518 bytes
-rw-r--r--editor/icons/2x/icon_material_shader.png (renamed from tools/editor/icons/2x/icon_material_shader.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/2x/icon_material_shader_graph.png (renamed from tools/editor/icons/2x/icon_material_shader_graph.png)bin707 -> 707 bytes
-rw-r--r--editor/icons/2x/icon_matrix.png (renamed from tools/editor/icons/2x/icon_matrix.png)bin185 -> 185 bytes
-rw-r--r--editor/icons/2x/icon_menu_button.png (renamed from tools/editor/icons/2x/icon_menu_button.png)bin296 -> 296 bytes
-rw-r--r--editor/icons/2x/icon_mesh.png (renamed from tools/editor/icons/2x/icon_mesh.png)bin582 -> 582 bytes
-rw-r--r--editor/icons/2x/icon_mesh_instance.png (renamed from tools/editor/icons/2x/icon_mesh_instance.png)bin563 -> 563 bytes
-rw-r--r--editor/icons/2x/icon_mesh_library.png (renamed from tools/editor/icons/2x/icon_mesh_library.png)bin631 -> 631 bytes
-rw-r--r--editor/icons/2x/icon_mini_aabb.png (renamed from tools/editor/icons/2x/icon_mini_aabb.png)bin695 -> 695 bytes
-rw-r--r--editor/icons/2x/icon_mini_array.png (renamed from tools/editor/icons/2x/icon_mini_array.png)bin326 -> 326 bytes
-rw-r--r--editor/icons/2x/icon_mini_boolean.png (renamed from tools/editor/icons/2x/icon_mini_boolean.png)bin434 -> 434 bytes
-rw-r--r--editor/icons/2x/icon_mini_color.png (renamed from tools/editor/icons/2x/icon_mini_color.png)bin411 -> 411 bytes
-rw-r--r--editor/icons/2x/icon_mini_color_array.png (renamed from tools/editor/icons/2x/icon_mini_color_array.png)bin445 -> 445 bytes
-rw-r--r--editor/icons/2x/icon_mini_dictionary.png (renamed from tools/editor/icons/2x/icon_mini_dictionary.png)bin371 -> 371 bytes
-rw-r--r--editor/icons/2x/icon_mini_float.png (renamed from tools/editor/icons/2x/icon_mini_float.png)bin355 -> 355 bytes
-rw-r--r--editor/icons/2x/icon_mini_float_array.png (renamed from tools/editor/icons/2x/icon_mini_float_array.png)bin451 -> 451 bytes
-rw-r--r--editor/icons/2x/icon_mini_image.png (renamed from tools/editor/icons/2x/icon_mini_image.png)bin450 -> 450 bytes
-rw-r--r--editor/icons/2x/icon_mini_input.png (renamed from tools/editor/icons/2x/icon_mini_input.png)bin409 -> 409 bytes
-rw-r--r--editor/icons/2x/icon_mini_int_array.png (renamed from tools/editor/icons/2x/icon_mini_int_array.png)bin384 -> 384 bytes
-rw-r--r--editor/icons/2x/icon_mini_integer.png (renamed from tools/editor/icons/2x/icon_mini_integer.png)bin367 -> 367 bytes
-rw-r--r--editor/icons/2x/icon_mini_matrix3.png (renamed from tools/editor/icons/2x/icon_mini_matrix3.png)bin391 -> 391 bytes
-rw-r--r--editor/icons/2x/icon_mini_matrix32.png (renamed from tools/editor/icons/2x/icon_mini_matrix32.png)bin573 -> 573 bytes
-rw-r--r--editor/icons/2x/icon_mini_object.png (renamed from tools/editor/icons/2x/icon_mini_object.png)bin507 -> 507 bytes
-rw-r--r--editor/icons/2x/icon_mini_path.png (renamed from tools/editor/icons/2x/icon_mini_path.png)bin435 -> 435 bytes
-rw-r--r--editor/icons/2x/icon_mini_plane.png (renamed from tools/editor/icons/2x/icon_mini_plane.png)bin424 -> 424 bytes
-rw-r--r--editor/icons/2x/icon_mini_quat.png (renamed from tools/editor/icons/2x/icon_mini_quat.png)bin509 -> 509 bytes
-rw-r--r--editor/icons/2x/icon_mini_raw_array.png (renamed from tools/editor/icons/2x/icon_mini_raw_array.png)bin382 -> 382 bytes
-rw-r--r--editor/icons/2x/icon_mini_rect2.png (renamed from tools/editor/icons/2x/icon_mini_rect2.png)bin431 -> 431 bytes
-rw-r--r--editor/icons/2x/icon_mini_rid.png (renamed from tools/editor/icons/2x/icon_mini_rid.png)bin349 -> 349 bytes
-rw-r--r--editor/icons/2x/icon_mini_string.png (renamed from tools/editor/icons/2x/icon_mini_string.png)bin437 -> 437 bytes
-rw-r--r--editor/icons/2x/icon_mini_string_array.png (renamed from tools/editor/icons/2x/icon_mini_string_array.png)bin479 -> 479 bytes
-rw-r--r--editor/icons/2x/icon_mini_transform.png (renamed from tools/editor/icons/2x/icon_mini_transform.png)bin539 -> 539 bytes
-rw-r--r--editor/icons/2x/icon_mini_variant.png (renamed from tools/editor/icons/2x/icon_mini_variant.png)bin405 -> 405 bytes
-rw-r--r--editor/icons/2x/icon_mini_vector2.png (renamed from tools/editor/icons/2x/icon_mini_vector2.png)bin541 -> 541 bytes
-rw-r--r--editor/icons/2x/icon_mini_vector2_array.png (renamed from tools/editor/icons/2x/icon_mini_vector2_array.png)bin485 -> 485 bytes
-rw-r--r--editor/icons/2x/icon_mini_vector3.png (renamed from tools/editor/icons/2x/icon_mini_vector3.png)bin509 -> 509 bytes
-rw-r--r--editor/icons/2x/icon_mini_vector3_array.png (renamed from tools/editor/icons/2x/icon_mini_vector3_array.png)bin416 -> 416 bytes
-rw-r--r--editor/icons/2x/icon_mirror_x.png (renamed from tools/editor/icons/2x/icon_mirror_x.png)bin247 -> 247 bytes
-rw-r--r--editor/icons/2x/icon_mirror_y.png (renamed from tools/editor/icons/2x/icon_mirror_y.png)bin240 -> 240 bytes
-rw-r--r--editor/icons/2x/icon_mouse.png (renamed from tools/editor/icons/2x/icon_mouse.png)bin476 -> 476 bytes
-rw-r--r--editor/icons/2x/icon_move_down.png (renamed from tools/editor/icons/2x/icon_move_down.png)bin357 -> 357 bytes
-rw-r--r--editor/icons/2x/icon_move_point.png (renamed from tools/editor/icons/2x/icon_move_point.png)bin1205 -> 1205 bytes
-rw-r--r--editor/icons/2x/icon_move_up.png (renamed from tools/editor/icons/2x/icon_move_up.png)bin346 -> 346 bytes
-rw-r--r--editor/icons/2x/icon_multi_edit.png (renamed from tools/editor/icons/2x/icon_multi_edit.png)bin558 -> 558 bytes
-rw-r--r--editor/icons/2x/icon_multi_line.png (renamed from tools/editor/icons/2x/icon_multi_line.png)bin166 -> 166 bytes
-rw-r--r--editor/icons/2x/icon_multi_mesh.png (renamed from tools/editor/icons/2x/icon_multi_mesh.png)bin591 -> 591 bytes
-rw-r--r--editor/icons/2x/icon_multi_mesh_instance.png (renamed from tools/editor/icons/2x/icon_multi_mesh_instance.png)bin653 -> 653 bytes
-rw-r--r--editor/icons/2x/icon_multi_node_edit.png (renamed from tools/editor/icons/2x/icon_multi_node_edit.png)bin558 -> 558 bytes
-rw-r--r--editor/icons/2x/icon_navigation.png (renamed from tools/editor/icons/2x/icon_navigation.png)bin534 -> 534 bytes
-rw-r--r--editor/icons/2x/icon_navigation_2d.png (renamed from tools/editor/icons/2x/icon_navigation_2d.png)bin558 -> 558 bytes
-rw-r--r--editor/icons/2x/icon_navigation_mesh.png (renamed from tools/editor/icons/2x/icon_navigation_mesh.png)bin806 -> 806 bytes
-rw-r--r--editor/icons/2x/icon_navigation_mesh_instance.png (renamed from tools/editor/icons/2x/icon_navigation_mesh_instance.png)bin867 -> 867 bytes
-rw-r--r--editor/icons/2x/icon_navigation_polygon.png (renamed from tools/editor/icons/2x/icon_navigation_polygon.png)bin640 -> 640 bytes
-rw-r--r--editor/icons/2x/icon_navigation_polygon_instance.png (renamed from tools/editor/icons/2x/icon_navigation_polygon_instance.png)bin712 -> 712 bytes
-rw-r--r--editor/icons/2x/icon_new.png (renamed from tools/editor/icons/2x/icon_new.png)bin196 -> 196 bytes
-rw-r--r--editor/icons/2x/icon_nine_patch_rect.png (renamed from tools/editor/icons/2x/icon_nine_patch_rect.png)bin162 -> 162 bytes
-rw-r--r--editor/icons/2x/icon_node.png (renamed from tools/editor/icons/2x/icon_node.png)bin788 -> 788 bytes
-rw-r--r--editor/icons/2x/icon_node_2d.png (renamed from tools/editor/icons/2x/icon_node_2d.png)bin864 -> 864 bytes
-rw-r--r--editor/icons/2x/icon_node_warning.png (renamed from tools/editor/icons/2x/icon_node_warning.png)bin443 -> 443 bytes
-rw-r--r--editor/icons/2x/icon_non_favorite.png (renamed from tools/editor/icons/2x/icon_non_favorite.png)bin946 -> 946 bytes
-rw-r--r--editor/icons/2x/icon_object.png (renamed from tools/editor/icons/2x/icon_object.png)bin500 -> 500 bytes
-rw-r--r--editor/icons/2x/icon_occluder_polygon_2d.png (renamed from tools/editor/icons/2x/icon_occluder_polygon_2d.png)bin384 -> 384 bytes
-rw-r--r--editor/icons/2x/icon_omni_light.png (renamed from tools/editor/icons/2x/icon_omni_light.png)bin659 -> 659 bytes
-rw-r--r--editor/icons/2x/icon_open.png (renamed from tools/editor/icons/2x/icon_open.png)bin228 -> 228 bytes
-rw-r--r--editor/icons/2x/icon_option_button.png (renamed from tools/editor/icons/2x/icon_option_button.png)bin366 -> 366 bytes
-rw-r--r--editor/icons/2x/icon_override.png (renamed from tools/editor/icons/2x/icon_override.png)bin488 -> 488 bytes
-rw-r--r--editor/icons/2x/icon_p_hash_translation.png (renamed from tools/editor/icons/2x/icon_p_hash_translation.png)bin285 -> 285 bytes
-rw-r--r--editor/icons/2x/icon_packed_data_container.png (renamed from tools/editor/icons/2x/icon_packed_data_container.png)bin253 -> 253 bytes
-rw-r--r--editor/icons/2x/icon_packed_scene.png (renamed from tools/editor/icons/2x/icon_packed_scene.png)bin569 -> 569 bytes
-rw-r--r--editor/icons/2x/icon_panel.png (renamed from tools/editor/icons/2x/icon_panel.png)bin277 -> 277 bytes
-rw-r--r--editor/icons/2x/icon_panel_container.png (renamed from tools/editor/icons/2x/icon_panel_container.png)bin309 -> 309 bytes
-rw-r--r--editor/icons/2x/icon_panels_1.png (renamed from tools/editor/icons/2x/icon_panels_1.png)bin117 -> 117 bytes
-rw-r--r--editor/icons/2x/icon_panels_2.png (renamed from tools/editor/icons/2x/icon_panels_2.png)bin127 -> 127 bytes
-rw-r--r--editor/icons/2x/icon_panels_2_alt.png (renamed from tools/editor/icons/2x/icon_panels_2_alt.png)bin134 -> 134 bytes
-rw-r--r--editor/icons/2x/icon_panels_3.png (renamed from tools/editor/icons/2x/icon_panels_3.png)bin141 -> 141 bytes
-rw-r--r--editor/icons/2x/icon_panels_3_alt.png (renamed from tools/editor/icons/2x/icon_panels_3_alt.png)bin152 -> 152 bytes
-rw-r--r--editor/icons/2x/icon_panels_4.png (renamed from tools/editor/icons/2x/icon_panels_4.png)bin136 -> 136 bytes
-rw-r--r--editor/icons/2x/icon_parallax_background.png (renamed from tools/editor/icons/2x/icon_parallax_background.png)bin335 -> 335 bytes
-rw-r--r--editor/icons/2x/icon_parallax_layer.png (renamed from tools/editor/icons/2x/icon_parallax_layer.png)bin469 -> 469 bytes
-rw-r--r--editor/icons/2x/icon_particle_attractor_2d.png (renamed from tools/editor/icons/2x/icon_particle_attractor_2d.png)bin1578 -> 1578 bytes
-rw-r--r--editor/icons/2x/icon_particles.png (renamed from tools/editor/icons/2x/icon_particles.png)bin686 -> 686 bytes
-rw-r--r--editor/icons/2x/icon_particles_2d.png (renamed from tools/editor/icons/2x/icon_particles_2d.png)bin728 -> 728 bytes
-rw-r--r--editor/icons/2x/icon_particles_shader.png (renamed from tools/editor/icons/2x/icon_particles_shader.png)bin657 -> 657 bytes
-rw-r--r--editor/icons/2x/icon_patch_9_rect.png (renamed from tools/editor/icons/2x/icon_patch_9_rect.png)bin162 -> 162 bytes
-rw-r--r--editor/icons/2x/icon_path.png (renamed from tools/editor/icons/2x/icon_path.png)bin666 -> 666 bytes
-rw-r--r--editor/icons/2x/icon_path_2d.png (renamed from tools/editor/icons/2x/icon_path_2d.png)bin687 -> 687 bytes
-rw-r--r--editor/icons/2x/icon_path_follow.png (renamed from tools/editor/icons/2x/icon_path_follow.png)bin725 -> 725 bytes
-rw-r--r--editor/icons/2x/icon_path_follow_2d.png (renamed from tools/editor/icons/2x/icon_path_follow_2d.png)bin725 -> 725 bytes
-rw-r--r--editor/icons/2x/icon_pause.png (renamed from tools/editor/icons/2x/icon_pause.png)bin194 -> 194 bytes
-rw-r--r--editor/icons/2x/icon_pin.png (renamed from tools/editor/icons/2x/icon_pin.png)bin322 -> 322 bytes
-rw-r--r--editor/icons/2x/icon_pin_joint.png (renamed from tools/editor/icons/2x/icon_pin_joint.png)bin686 -> 686 bytes
-rw-r--r--editor/icons/2x/icon_pin_joint_2d.png (renamed from tools/editor/icons/2x/icon_pin_joint_2d.png)bin719 -> 719 bytes
-rw-r--r--editor/icons/2x/icon_pin_pressed.png (renamed from tools/editor/icons/2x/icon_pin_pressed.png)bin322 -> 322 bytes
-rw-r--r--editor/icons/2x/icon_plane.png (renamed from tools/editor/icons/2x/icon_plane.png)bin306 -> 306 bytes
-rw-r--r--editor/icons/2x/icon_plane_shape.png (renamed from tools/editor/icons/2x/icon_plane_shape.png)bin316 -> 316 bytes
-rw-r--r--editor/icons/2x/icon_play.png (renamed from tools/editor/icons/2x/icon_play.png)bin395 -> 395 bytes
-rw-r--r--editor/icons/2x/icon_play_backwards.png (renamed from tools/editor/icons/2x/icon_play_backwards.png)bin424 -> 424 bytes
-rw-r--r--editor/icons/2x/icon_play_custom.png (renamed from tools/editor/icons/2x/icon_play_custom.png)bin572 -> 572 bytes
-rw-r--r--editor/icons/2x/icon_play_scene.png (renamed from tools/editor/icons/2x/icon_play_scene.png)bin686 -> 686 bytes
-rw-r--r--editor/icons/2x/icon_play_start.png (renamed from tools/editor/icons/2x/icon_play_start.png)bin463 -> 463 bytes
-rw-r--r--editor/icons/2x/icon_play_start_backwards.png (renamed from tools/editor/icons/2x/icon_play_start_backwards.png)bin497 -> 497 bytes
-rw-r--r--editor/icons/2x/icon_polygon_2d.png (renamed from tools/editor/icons/2x/icon_polygon_2d.png)bin407 -> 407 bytes
-rw-r--r--editor/icons/2x/icon_polygon_path_finder.png (renamed from tools/editor/icons/2x/icon_polygon_path_finder.png)bin491 -> 491 bytes
-rw-r--r--editor/icons/2x/icon_popup.png (renamed from tools/editor/icons/2x/icon_popup.png)bin329 -> 329 bytes
-rw-r--r--editor/icons/2x/icon_popup_dialog.png (renamed from tools/editor/icons/2x/icon_popup_dialog.png)bin347 -> 347 bytes
-rw-r--r--editor/icons/2x/icon_popup_menu.png (renamed from tools/editor/icons/2x/icon_popup_menu.png)bin301 -> 301 bytes
-rw-r--r--editor/icons/2x/icon_popup_panel.png (renamed from tools/editor/icons/2x/icon_popup_panel.png)bin279 -> 279 bytes
-rw-r--r--editor/icons/2x/icon_portal.png (renamed from tools/editor/icons/2x/icon_portal.png)bin855 -> 855 bytes
-rw-r--r--editor/icons/2x/icon_position_2d.png (renamed from tools/editor/icons/2x/icon_position_2d.png)bin152 -> 152 bytes
-rw-r--r--editor/icons/2x/icon_position_3d.png (renamed from tools/editor/icons/2x/icon_position_3d.png)bin151 -> 151 bytes
-rw-r--r--editor/icons/2x/icon_progress_1.png (renamed from tools/editor/icons/2x/icon_progress_1.png)bin781 -> 781 bytes
-rw-r--r--editor/icons/2x/icon_progress_2.png (renamed from tools/editor/icons/2x/icon_progress_2.png)bin785 -> 785 bytes
-rw-r--r--editor/icons/2x/icon_progress_3.png (renamed from tools/editor/icons/2x/icon_progress_3.png)bin800 -> 800 bytes
-rw-r--r--editor/icons/2x/icon_progress_4.png (renamed from tools/editor/icons/2x/icon_progress_4.png)bin808 -> 808 bytes
-rw-r--r--editor/icons/2x/icon_progress_5.png (renamed from tools/editor/icons/2x/icon_progress_5.png)bin807 -> 807 bytes
-rw-r--r--editor/icons/2x/icon_progress_6.png (renamed from tools/editor/icons/2x/icon_progress_6.png)bin793 -> 793 bytes
-rw-r--r--editor/icons/2x/icon_progress_7.png (renamed from tools/editor/icons/2x/icon_progress_7.png)bin815 -> 815 bytes
-rw-r--r--editor/icons/2x/icon_progress_8.png (renamed from tools/editor/icons/2x/icon_progress_8.png)bin791 -> 791 bytes
-rw-r--r--editor/icons/2x/icon_progress_bar.png (renamed from tools/editor/icons/2x/icon_progress_bar.png)bin328 -> 328 bytes
-rw-r--r--editor/icons/2x/icon_proximity_group.png (renamed from tools/editor/icons/2x/icon_proximity_group.png)bin326 -> 326 bytes
-rw-r--r--editor/icons/2x/icon_quad.png (renamed from tools/editor/icons/2x/icon_quad.png)bin289 -> 289 bytes
-rw-r--r--editor/icons/2x/icon_quat.png (renamed from tools/editor/icons/2x/icon_quat.png)bin668 -> 668 bytes
-rw-r--r--editor/icons/2x/icon_range.png (renamed from tools/editor/icons/2x/icon_range.png)bin177 -> 177 bytes
-rw-r--r--editor/icons/2x/icon_rating_no_star.png (renamed from tools/editor/icons/2x/icon_rating_no_star.png)bin1077 -> 1077 bytes
-rw-r--r--editor/icons/2x/icon_rating_star.png (renamed from tools/editor/icons/2x/icon_rating_star.png)bin696 -> 696 bytes
-rw-r--r--editor/icons/2x/icon_ray_cast.png (renamed from tools/editor/icons/2x/icon_ray_cast.png)bin308 -> 308 bytes
-rw-r--r--editor/icons/2x/icon_ray_cast_2d.png (renamed from tools/editor/icons/2x/icon_ray_cast_2d.png)bin337 -> 337 bytes
-rw-r--r--editor/icons/2x/icon_ray_shape.png (renamed from tools/editor/icons/2x/icon_ray_shape.png)bin541 -> 541 bytes
-rw-r--r--editor/icons/2x/icon_ray_shape_2d.png (renamed from tools/editor/icons/2x/icon_ray_shape_2d.png)bin330 -> 330 bytes
-rw-r--r--editor/icons/2x/icon_rayito.png (renamed from tools/editor/icons/2x/icon_rayito.png)bin449 -> 449 bytes
-rw-r--r--editor/icons/2x/icon_real.png (renamed from tools/editor/icons/2x/icon_real.png)bin423 -> 423 bytes
-rw-r--r--editor/icons/2x/icon_rectangle_shape_2d.png (renamed from tools/editor/icons/2x/icon_rectangle_shape_2d.png)bin213 -> 213 bytes
-rw-r--r--editor/icons/2x/icon_reference_rect.png (renamed from tools/editor/icons/2x/icon_reference_rect.png)bin160 -> 160 bytes
-rw-r--r--editor/icons/2x/icon_reflection_probe.png (renamed from tools/editor/icons/2x/icon_reflection_probe.png)bin533 -> 533 bytes
-rw-r--r--editor/icons/2x/icon_region_edit.png (renamed from tools/editor/icons/2x/icon_region_edit.png)bin158 -> 158 bytes
-rw-r--r--editor/icons/2x/icon_reload.png (renamed from tools/editor/icons/2x/icon_reload.png)bin786 -> 786 bytes
-rw-r--r--editor/icons/2x/icon_reload_small.png (renamed from tools/editor/icons/2x/icon_reload_small.png)bin756 -> 756 bytes
-rw-r--r--editor/icons/2x/icon_remote.png (renamed from tools/editor/icons/2x/icon_remote.png)bin824 -> 824 bytes
-rw-r--r--editor/icons/2x/icon_remote_transform.png (renamed from tools/editor/icons/2x/icon_remote_transform.png)bin1140 -> 1140 bytes
-rw-r--r--editor/icons/2x/icon_remote_transform_2d.png (renamed from tools/editor/icons/2x/icon_remote_transform_2d.png)bin1197 -> 1197 bytes
-rw-r--r--editor/icons/2x/icon_remove.png (renamed from tools/editor/icons/2x/icon_remove.png)bin271 -> 271 bytes
-rw-r--r--editor/icons/2x/icon_rename.png (renamed from tools/editor/icons/2x/icon_rename.png)bin215 -> 215 bytes
-rw-r--r--editor/icons/2x/icon_reparent.png (renamed from tools/editor/icons/2x/icon_reparent.png)bin741 -> 741 bytes
-rw-r--r--editor/icons/2x/icon_resource_preloader.png (renamed from tools/editor/icons/2x/icon_resource_preloader.png)bin609 -> 609 bytes
-rw-r--r--editor/icons/2x/icon_rich_text_label.png (renamed from tools/editor/icons/2x/icon_rich_text_label.png)bin313 -> 313 bytes
-rw-r--r--editor/icons/2x/icon_rigid_body.png (renamed from tools/editor/icons/2x/icon_rigid_body.png)bin1139 -> 1139 bytes
-rw-r--r--editor/icons/2x/icon_rigid_body_2d.png (renamed from tools/editor/icons/2x/icon_rigid_body_2d.png)bin1206 -> 1206 bytes
-rw-r--r--editor/icons/2x/icon_room.png (renamed from tools/editor/icons/2x/icon_room.png)bin567 -> 567 bytes
-rw-r--r--editor/icons/2x/icon_room_bounds.png (renamed from tools/editor/icons/2x/icon_room_bounds.png)bin631 -> 631 bytes
-rw-r--r--editor/icons/2x/icon_rotate_0.png (renamed from tools/editor/icons/2x/icon_rotate_0.png)bin878 -> 878 bytes
-rw-r--r--editor/icons/2x/icon_rotate_180.png (renamed from tools/editor/icons/2x/icon_rotate_180.png)bin713 -> 713 bytes
-rw-r--r--editor/icons/2x/icon_rotate_270.png (renamed from tools/editor/icons/2x/icon_rotate_270.png)bin666 -> 666 bytes
-rw-r--r--editor/icons/2x/icon_rotate_90.png (renamed from tools/editor/icons/2x/icon_rotate_90.png)bin805 -> 805 bytes
-rw-r--r--editor/icons/2x/icon_sample.png (renamed from tools/editor/icons/2x/icon_sample.png)bin197 -> 197 bytes
-rw-r--r--editor/icons/2x/icon_sample_library.png (renamed from tools/editor/icons/2x/icon_sample_library.png)bin568 -> 568 bytes
-rw-r--r--editor/icons/2x/icon_sample_player.png (renamed from tools/editor/icons/2x/icon_sample_player.png)bin345 -> 345 bytes
-rw-r--r--editor/icons/2x/icon_sample_player_2d.png (renamed from tools/editor/icons/2x/icon_sample_player_2d.png)bin376 -> 376 bytes
-rw-r--r--editor/icons/2x/icon_save.png (renamed from tools/editor/icons/2x/icon_save.png)bin466 -> 466 bytes
-rw-r--r--editor/icons/2x/icon_script.png (renamed from tools/editor/icons/2x/icon_script.png)bin465 -> 465 bytes
-rw-r--r--editor/icons/2x/icon_script_create.png (renamed from tools/editor/icons/2x/icon_script_create.png)bin491 -> 491 bytes
-rw-r--r--editor/icons/2x/icon_script_remove.png (renamed from tools/editor/icons/2x/icon_script_remove.png)bin787 -> 787 bytes
-rw-r--r--editor/icons/2x/icon_scroll_bar.png (renamed from tools/editor/icons/2x/icon_scroll_bar.png)bin324 -> 324 bytes
-rw-r--r--editor/icons/2x/icon_scroll_container.png (renamed from tools/editor/icons/2x/icon_scroll_container.png)bin483 -> 483 bytes
-rw-r--r--editor/icons/2x/icon_segment_shape_2d.png (renamed from tools/editor/icons/2x/icon_segment_shape_2d.png)bin320 -> 320 bytes
-rw-r--r--editor/icons/2x/icon_shader.png (renamed from tools/editor/icons/2x/icon_shader.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/2x/icon_shader_material.png (renamed from tools/editor/icons/2x/icon_shader_material.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/2x/icon_short_cut.png (renamed from tools/editor/icons/2x/icon_short_cut.png)bin473 -> 473 bytes
-rw-r--r--editor/icons/2x/icon_signal.png (renamed from tools/editor/icons/2x/icon_signal.png)bin327 -> 327 bytes
-rw-r--r--editor/icons/2x/icon_skeleton.png (renamed from tools/editor/icons/2x/icon_skeleton.png)bin649 -> 649 bytes
-rw-r--r--editor/icons/2x/icon_slider_joint.png (renamed from tools/editor/icons/2x/icon_slider_joint.png)bin180 -> 180 bytes
-rw-r--r--editor/icons/2x/icon_slot.png (renamed from tools/editor/icons/2x/icon_slot.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/2x/icon_snap.png (renamed from tools/editor/icons/2x/icon_snap.png)bin424 -> 424 bytes
-rw-r--r--editor/icons/2x/icon_sound_room_params.png (renamed from tools/editor/icons/2x/icon_sound_room_params.png)bin375 -> 375 bytes
-rw-r--r--editor/icons/2x/icon_spatial.png (renamed from tools/editor/icons/2x/icon_spatial.png)bin835 -> 835 bytes
-rw-r--r--editor/icons/2x/icon_spatial_sample_player.png (renamed from tools/editor/icons/2x/icon_spatial_sample_player.png)bin353 -> 353 bytes
-rw-r--r--editor/icons/2x/icon_spatial_shader.png (renamed from tools/editor/icons/2x/icon_spatial_shader.png)bin704 -> 704 bytes
-rw-r--r--editor/icons/2x/icon_spatial_stream_player.png (renamed from tools/editor/icons/2x/icon_spatial_stream_player.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/2x/icon_sphere_shape.png (renamed from tools/editor/icons/2x/icon_sphere_shape.png)bin712 -> 712 bytes
-rw-r--r--editor/icons/2x/icon_spin_box.png (renamed from tools/editor/icons/2x/icon_spin_box.png)bin436 -> 436 bytes
-rw-r--r--editor/icons/2x/icon_spot_light.png (renamed from tools/editor/icons/2x/icon_spot_light.png)bin669 -> 669 bytes
-rw-r--r--editor/icons/2x/icon_sprite.png (renamed from tools/editor/icons/2x/icon_sprite.png)bin841 -> 841 bytes
-rw-r--r--editor/icons/2x/icon_sprite_3d.png (renamed from tools/editor/icons/2x/icon_sprite_3d.png)bin838 -> 838 bytes
-rw-r--r--editor/icons/2x/icon_sprite_frames.png (renamed from tools/editor/icons/2x/icon_sprite_frames.png)bin691 -> 691 bytes
-rw-r--r--editor/icons/2x/icon_static_body.png (renamed from tools/editor/icons/2x/icon_static_body.png)bin397 -> 397 bytes
-rw-r--r--editor/icons/2x/icon_static_body_2d.png (renamed from tools/editor/icons/2x/icon_static_body_2d.png)bin417 -> 417 bytes
-rw-r--r--editor/icons/2x/icon_stream_player.png (renamed from tools/editor/icons/2x/icon_stream_player.png)bin263 -> 263 bytes
-rw-r--r--editor/icons/2x/icon_string.png (renamed from tools/editor/icons/2x/icon_string.png)bin217 -> 217 bytes
-rw-r--r--editor/icons/2x/icon_style_box_empty.png (renamed from tools/editor/icons/2x/icon_style_box_empty.png)bin555 -> 555 bytes
-rw-r--r--editor/icons/2x/icon_style_box_flat.png (renamed from tools/editor/icons/2x/icon_style_box_flat.png)bin695 -> 695 bytes
-rw-r--r--editor/icons/2x/icon_style_box_texture.png (renamed from tools/editor/icons/2x/icon_style_box_texture.png)bin693 -> 693 bytes
-rw-r--r--editor/icons/2x/icon_tab_container.png (renamed from tools/editor/icons/2x/icon_tab_container.png)bin334 -> 334 bytes
-rw-r--r--editor/icons/2x/icon_tabs.png (renamed from tools/editor/icons/2x/icon_tabs.png)bin222 -> 222 bytes
-rw-r--r--editor/icons/2x/icon_test_cube.png (renamed from tools/editor/icons/2x/icon_test_cube.png)bin596 -> 596 bytes
-rw-r--r--editor/icons/2x/icon_text_edit.png (renamed from tools/editor/icons/2x/icon_text_edit.png)bin329 -> 329 bytes
-rw-r--r--editor/icons/2x/icon_texture.png (renamed from tools/editor/icons/2x/icon_texture.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/2x/icon_texture_button.png (renamed from tools/editor/icons/2x/icon_texture_button.png)bin190 -> 190 bytes
-rw-r--r--editor/icons/2x/icon_texture_progress.png (renamed from tools/editor/icons/2x/icon_texture_progress.png)bin344 -> 344 bytes
-rw-r--r--editor/icons/2x/icon_texture_rect.png (renamed from tools/editor/icons/2x/icon_texture_rect.png)bin201 -> 201 bytes
-rw-r--r--editor/icons/2x/icon_theme.png (renamed from tools/editor/icons/2x/icon_theme.png)bin809 -> 809 bytes
-rw-r--r--editor/icons/2x/icon_tile_map.png (renamed from tools/editor/icons/2x/icon_tile_map.png)bin139 -> 139 bytes
-rw-r--r--editor/icons/2x/icon_tile_set.png (renamed from tools/editor/icons/2x/icon_tile_set.png)bin242 -> 242 bytes
-rw-r--r--editor/icons/2x/icon_timer.png (renamed from tools/editor/icons/2x/icon_timer.png)bin909 -> 909 bytes
-rw-r--r--editor/icons/2x/icon_tool_button.png (renamed from tools/editor/icons/2x/icon_tool_button.png)bin425 -> 425 bytes
-rw-r--r--editor/icons/2x/icon_tool_move.png (renamed from tools/editor/icons/2x/icon_tool_move.png)bin353 -> 353 bytes
-rw-r--r--editor/icons/2x/icon_tool_pan.png (renamed from tools/editor/icons/2x/icon_tool_pan.png)bin479 -> 479 bytes
-rw-r--r--editor/icons/2x/icon_tool_rotate.png (renamed from tools/editor/icons/2x/icon_tool_rotate.png)bin786 -> 786 bytes
-rw-r--r--editor/icons/2x/icon_tool_scale.png (renamed from tools/editor/icons/2x/icon_tool_scale.png)bin562 -> 562 bytes
-rw-r--r--editor/icons/2x/icon_tool_select.png (renamed from tools/editor/icons/2x/icon_tool_select.png)bin659 -> 659 bytes
-rw-r--r--editor/icons/2x/icon_tools.png (renamed from tools/editor/icons/2x/icon_tools.png)bin759 -> 759 bytes
-rw-r--r--editor/icons/2x/icon_touch_screen_button.png (renamed from tools/editor/icons/2x/icon_touch_screen_button.png)bin511 -> 511 bytes
-rw-r--r--editor/icons/2x/icon_track_add_key.png (renamed from tools/editor/icons/2x/icon_track_add_key.png)bin127 -> 127 bytes
-rw-r--r--editor/icons/2x/icon_track_add_key_hl.png (renamed from tools/editor/icons/2x/icon_track_add_key_hl.png)bin128 -> 128 bytes
-rw-r--r--editor/icons/2x/icon_track_continuous.png (renamed from tools/editor/icons/2x/icon_track_continuous.png)bin434 -> 434 bytes
-rw-r--r--editor/icons/2x/icon_track_discrete.png (renamed from tools/editor/icons/2x/icon_track_discrete.png)bin196 -> 196 bytes
-rw-r--r--editor/icons/2x/icon_track_trigger.png (renamed from tools/editor/icons/2x/icon_track_trigger.png)bin214 -> 214 bytes
-rw-r--r--editor/icons/2x/icon_translation.png (renamed from tools/editor/icons/2x/icon_translation.png)bin285 -> 285 bytes
-rw-r--r--editor/icons/2x/icon_transparent.png (renamed from tools/editor/icons/2x/icon_transparent.png)bin177 -> 177 bytes
-rw-r--r--editor/icons/2x/icon_transpose.png (renamed from tools/editor/icons/2x/icon_transpose.png)bin210 -> 210 bytes
-rw-r--r--editor/icons/2x/icon_tree.png (renamed from tools/editor/icons/2x/icon_tree.png)bin417 -> 417 bytes
-rw-r--r--editor/icons/2x/icon_tween.png (renamed from tools/editor/icons/2x/icon_tween.png)bin315 -> 315 bytes
-rw-r--r--editor/icons/2x/icon_unbone.png (renamed from tools/editor/icons/2x/icon_unbone.png)bin661 -> 661 bytes
-rw-r--r--editor/icons/2x/icon_ungroup.png (renamed from tools/editor/icons/2x/icon_ungroup.png)bin202 -> 202 bytes
-rw-r--r--editor/icons/2x/icon_uninstance.png (renamed from tools/editor/icons/2x/icon_uninstance.png)bin883 -> 883 bytes
-rw-r--r--editor/icons/2x/icon_unlock.png (renamed from tools/editor/icons/2x/icon_unlock.png)bin388 -> 388 bytes
-rw-r--r--editor/icons/2x/icon_uv.png (renamed from tools/editor/icons/2x/icon_uv.png)bin502 -> 502 bytes
-rw-r--r--editor/icons/2x/icon_v_box_container.png (renamed from tools/editor/icons/2x/icon_v_box_container.png)bin327 -> 327 bytes
-rw-r--r--editor/icons/2x/icon_v_button_array.png (renamed from tools/editor/icons/2x/icon_v_button_array.png)bin231 -> 231 bytes
-rw-r--r--editor/icons/2x/icon_v_scroll_bar.png (renamed from tools/editor/icons/2x/icon_v_scroll_bar.png)bin328 -> 328 bytes
-rw-r--r--editor/icons/2x/icon_v_separator.png (renamed from tools/editor/icons/2x/icon_v_separator.png)bin154 -> 154 bytes
-rw-r--r--editor/icons/2x/icon_v_slider.png (renamed from tools/editor/icons/2x/icon_v_slider.png)bin391 -> 391 bytes
-rw-r--r--editor/icons/2x/icon_v_split_container.png (renamed from tools/editor/icons/2x/icon_v_split_container.png)bin425 -> 425 bytes
-rw-r--r--editor/icons/2x/icon_vector.png (renamed from tools/editor/icons/2x/icon_vector.png)bin270 -> 270 bytes
-rw-r--r--editor/icons/2x/icon_vector2.png (renamed from tools/editor/icons/2x/icon_vector2.png)bin141 -> 141 bytes
-rw-r--r--editor/icons/2x/icon_vehicle_body.png (renamed from tools/editor/icons/2x/icon_vehicle_body.png)bin410 -> 410 bytes
-rw-r--r--editor/icons/2x/icon_vehicle_wheel.png (renamed from tools/editor/icons/2x/icon_vehicle_wheel.png)bin1269 -> 1269 bytes
-rw-r--r--editor/icons/2x/icon_video_player.png (renamed from tools/editor/icons/2x/icon_video_player.png)bin501 -> 501 bytes
-rw-r--r--editor/icons/2x/icon_viewport.png (renamed from tools/editor/icons/2x/icon_viewport.png)bin349 -> 349 bytes
-rw-r--r--editor/icons/2x/icon_viewport_container.png (renamed from tools/editor/icons/2x/icon_viewport_container.png)bin528 -> 528 bytes
-rw-r--r--editor/icons/2x/icon_viewport_sprite.png (renamed from tools/editor/icons/2x/icon_viewport_sprite.png)bin403 -> 403 bytes
-rw-r--r--editor/icons/2x/icon_viewport_texture.png (renamed from tools/editor/icons/2x/icon_viewport_texture.png)bin404 -> 404 bytes
-rw-r--r--editor/icons/2x/icon_visibility_enabler.png (renamed from tools/editor/icons/2x/icon_visibility_enabler.png)bin1106 -> 1106 bytes
-rw-r--r--editor/icons/2x/icon_visibility_enabler_2d.png (renamed from tools/editor/icons/2x/icon_visibility_enabler_2d.png)bin1114 -> 1114 bytes
-rw-r--r--editor/icons/2x/icon_visibility_notifier.png (renamed from tools/editor/icons/2x/icon_visibility_notifier.png)bin832 -> 832 bytes
-rw-r--r--editor/icons/2x/icon_visibility_notifier_2d.png (renamed from tools/editor/icons/2x/icon_visibility_notifier_2d.png)bin844 -> 844 bytes
-rw-r--r--editor/icons/2x/icon_visible.png (renamed from tools/editor/icons/2x/icon_visible.png)bin994 -> 994 bytes
-rw-r--r--editor/icons/2x/icon_visual_script.png (renamed from tools/editor/icons/2x/icon_visual_script.png)bin707 -> 707 bytes
-rw-r--r--editor/icons/2x/icon_visual_shader_port.png (renamed from tools/editor/icons/2x/icon_visual_shader_port.png)bin338 -> 338 bytes
-rw-r--r--editor/icons/2x/icon_vu_empty.png (renamed from tools/editor/icons/2x/icon_vu_empty.png)bin452 -> 452 bytes
-rw-r--r--editor/icons/2x/icon_vu_full.png (renamed from tools/editor/icons/2x/icon_vu_full.png)bin350 -> 350 bytes
-rw-r--r--editor/icons/2x/icon_warning.png (renamed from tools/editor/icons/2x/icon_warning.png)bin154 -> 154 bytes
-rw-r--r--editor/icons/2x/icon_window_dialog.png (renamed from tools/editor/icons/2x/icon_window_dialog.png)bin311 -> 311 bytes
-rw-r--r--editor/icons/2x/icon_world.png (renamed from tools/editor/icons/2x/icon_world.png)bin502 -> 502 bytes
-rw-r--r--editor/icons/2x/icon_world_2d.png (renamed from tools/editor/icons/2x/icon_world_2d.png)bin584 -> 584 bytes
-rw-r--r--editor/icons/2x/icon_world_environment.png (renamed from tools/editor/icons/2x/icon_world_environment.png)bin1371 -> 1371 bytes
-rw-r--r--editor/icons/2x/icon_y_sort.png (renamed from tools/editor/icons/2x/icon_y_sort.png)bin293 -> 293 bytes
-rw-r--r--editor/icons/2x/icon_zoom.png (renamed from tools/editor/icons/2x/icon_zoom.png)bin762 -> 762 bytes
-rw-r--r--editor/icons/2x/icon_zoom_less.png (renamed from tools/editor/icons/2x/icon_zoom_less.png)bin162 -> 162 bytes
-rw-r--r--editor/icons/2x/icon_zoom_more.png (renamed from tools/editor/icons/2x/icon_zoom_more.png)bin290 -> 290 bytes
-rw-r--r--editor/icons/2x/icon_zoom_reset.png (renamed from tools/editor/icons/2x/icon_zoom_reset.png)bin689 -> 689 bytes
-rw-r--r--editor/icons/SCsub96
-rw-r--r--editor/icons/icon_accept_dialog.png (renamed from tools/editor/icons/icon_accept_dialog.png)bin338 -> 338 bytes
-rw-r--r--editor/icons/icon_add.png (renamed from tools/editor/icons/icon_add.png)bin129 -> 129 bytes
-rw-r--r--editor/icons/icon_add_track.png (renamed from tools/editor/icons/icon_add_track.png)bin129 -> 129 bytes
-rw-r--r--editor/icons/icon_anchor.png (renamed from tools/editor/icons/icon_anchor.png)bin451 -> 451 bytes
-rw-r--r--editor/icons/icon_anim_export.png (renamed from tools/editor/icons/icon_anim_export.png)bin552 -> 552 bytes
-rw-r--r--editor/icons/icon_anim_export_all.png (renamed from tools/editor/icons/icon_anim_export_all.png)bin566 -> 566 bytes
-rw-r--r--editor/icons/icon_anim_get.png (renamed from tools/editor/icons/icon_anim_get.png)bin276 -> 276 bytes
-rw-r--r--editor/icons/icon_anim_get_hl.png (renamed from tools/editor/icons/icon_anim_get_hl.png)bin270 -> 270 bytes
-rw-r--r--editor/icons/icon_anim_import.png (renamed from tools/editor/icons/icon_anim_import.png)bin572 -> 572 bytes
-rw-r--r--editor/icons/icon_anim_import_all.png (renamed from tools/editor/icons/icon_anim_import_all.png)bin586 -> 586 bytes
-rw-r--r--editor/icons/icon_anim_set.png (renamed from tools/editor/icons/icon_anim_set.png)bin287 -> 287 bytes
-rw-r--r--editor/icons/icon_anim_set_hl.png (renamed from tools/editor/icons/icon_anim_set_hl.png)bin268 -> 268 bytes
-rw-r--r--editor/icons/icon_animated_sprite.png (renamed from tools/editor/icons/icon_animated_sprite.png)bin584 -> 584 bytes
-rw-r--r--editor/icons/icon_animated_sprite_3d.png (renamed from tools/editor/icons/icon_animated_sprite_3d.png)bin552 -> 552 bytes
-rw-r--r--editor/icons/icon_animation.png (renamed from tools/editor/icons/icon_animation.png)bin399 -> 399 bytes
-rw-r--r--editor/icons/icon_animation_node.png (renamed from tools/editor/icons/icon_animation_node.png)bin261 -> 261 bytes
-rw-r--r--editor/icons/icon_animation_play.png (renamed from tools/editor/icons/icon_animation_play.png)bin593 -> 593 bytes
-rw-r--r--editor/icons/icon_animation_player.png (renamed from tools/editor/icons/icon_animation_player.png)bin153 -> 153 bytes
-rw-r--r--editor/icons/icon_animation_set.png (renamed from tools/editor/icons/icon_animation_set.png)bin529 -> 529 bytes
-rw-r--r--editor/icons/icon_animation_tree.png (renamed from tools/editor/icons/icon_animation_tree.png)bin279 -> 279 bytes
-rw-r--r--editor/icons/icon_animation_tree_player.png (renamed from tools/editor/icons/icon_animation_tree_player.png)bin279 -> 279 bytes
-rw-r--r--editor/icons/icon_area.png (renamed from tools/editor/icons/icon_area.png)bin176 -> 176 bytes
-rw-r--r--editor/icons/icon_area_2d.png (renamed from tools/editor/icons/icon_area_2d.png)bin182 -> 182 bytes
-rw-r--r--editor/icons/icon_array_data.png (renamed from tools/editor/icons/icon_array_data.png)bin176 -> 176 bytes
-rw-r--r--editor/icons/icon_array_float.png (renamed from tools/editor/icons/icon_array_float.png)bin177 -> 177 bytes
-rw-r--r--editor/icons/icon_array_int.png (renamed from tools/editor/icons/icon_array_int.png)bin172 -> 172 bytes
-rw-r--r--editor/icons/icon_array_string.png (renamed from tools/editor/icons/icon_array_string.png)bin178 -> 178 bytes
-rw-r--r--editor/icons/icon_array_variant.png (renamed from tools/editor/icons/icon_array_variant.png)bin172 -> 172 bytes
-rw-r--r--editor/icons/icon_arrow_left.png (renamed from tools/editor/icons/icon_arrow_left.png)bin211 -> 211 bytes
-rw-r--r--editor/icons/icon_arrow_left_disabled.png (renamed from tools/editor/icons/icon_arrow_left_disabled.png)bin244 -> 244 bytes
-rw-r--r--editor/icons/icon_arrow_right.png (renamed from tools/editor/icons/icon_arrow_right.png)bin215 -> 215 bytes
-rw-r--r--editor/icons/icon_arrow_right_disabled.png (renamed from tools/editor/icons/icon_arrow_right_disabled.png)bin252 -> 252 bytes
-rw-r--r--editor/icons/icon_arrow_up.png (renamed from tools/editor/icons/icon_arrow_up.png)bin223 -> 223 bytes
-rw-r--r--editor/icons/icon_arrow_up_disabled.png (renamed from tools/editor/icons/icon_arrow_up_disabled.png)bin275 -> 275 bytes
-rw-r--r--editor/icons/icon_atlas_texture.png (renamed from tools/editor/icons/icon_atlas_texture.png)bin286 -> 286 bytes
-rw-r--r--editor/icons/icon_audio_effect_amplify.png (renamed from tools/editor/icons/icon_audio_effect_amplify.png)bin379 -> 379 bytes
-rw-r--r--editor/icons/icon_audio_stream_gibberish.png (renamed from tools/editor/icons/icon_audio_stream_gibberish.png)bin250 -> 250 bytes
-rw-r--r--editor/icons/icon_audio_stream_m_p_c.png (renamed from tools/editor/icons/icon_audio_stream_m_p_c.png)bin832 -> 832 bytes
-rw-r--r--editor/icons/icon_audio_stream_o_g_g_vorbis.png (renamed from tools/editor/icons/icon_audio_stream_o_g_g_vorbis.png)bin774 -> 774 bytes
-rw-r--r--editor/icons/icon_audio_stream_opus.png (renamed from tools/editor/icons/icon_audio_stream_opus.png)bin559 -> 559 bytes
-rw-r--r--editor/icons/icon_audio_stream_speex.png (renamed from tools/editor/icons/icon_audio_stream_speex.png)bin1080 -> 1080 bytes
-rw-r--r--editor/icons/icon_auto_play.png (renamed from tools/editor/icons/icon_auto_play.png)bin370 -> 370 bytes
-rw-r--r--editor/icons/icon_b_c_s_f_x.png (renamed from tools/editor/icons/icon_b_c_s_f_x.png)bin451 -> 451 bytes
-rw-r--r--editor/icons/icon_b_g_color_f_x.png (renamed from tools/editor/icons/icon_b_g_color_f_x.png)bin367 -> 367 bytes
-rw-r--r--editor/icons/icon_b_g_image_f_x.png (renamed from tools/editor/icons/icon_b_g_image_f_x.png)bin753 -> 753 bytes
-rw-r--r--editor/icons/icon_back.png (renamed from tools/editor/icons/icon_back.png)bin223 -> 223 bytes
-rw-r--r--editor/icons/icon_back_buffer_copy.png (renamed from tools/editor/icons/icon_back_buffer_copy.png)bin158 -> 158 bytes
-rw-r--r--editor/icons/icon_back_disabled.png (renamed from tools/editor/icons/icon_back_disabled.png)bin175 -> 175 bytes
-rw-r--r--editor/icons/icon_back_no.png (renamed from tools/editor/icons/icon_back_no.png)bin213 -> 213 bytes
-rw-r--r--editor/icons/icon_bake.png (renamed from tools/editor/icons/icon_bake.png)bin180 -> 180 bytes
-rw-r--r--editor/icons/icon_baked_light.png (renamed from tools/editor/icons/icon_baked_light.png)bin180 -> 180 bytes
-rw-r--r--editor/icons/icon_baked_light_instance.png (renamed from tools/editor/icons/icon_baked_light_instance.png)bin179 -> 179 bytes
-rw-r--r--editor/icons/icon_baked_light_sampler.png (renamed from tools/editor/icons/icon_baked_light_sampler.png)bin230 -> 230 bytes
-rw-r--r--editor/icons/icon_bit_map.png (renamed from tools/editor/icons/icon_bit_map.png)bin113 -> 113 bytes
-rw-r--r--editor/icons/icon_bitmap_font.png (renamed from tools/editor/icons/icon_bitmap_font.png)bin160 -> 160 bytes
-rw-r--r--editor/icons/icon_blend.png (renamed from tools/editor/icons/icon_blend.png)bin578 -> 578 bytes
-rw-r--r--editor/icons/icon_bone.png (renamed from tools/editor/icons/icon_bone.png)bin349 -> 349 bytes
-rw-r--r--editor/icons/icon_bone_attachment.png (renamed from tools/editor/icons/icon_bone_attachment.png)bin333 -> 333 bytes
-rw-r--r--editor/icons/icon_bone_track.png (renamed from tools/editor/icons/icon_bone_track.png)bin343 -> 343 bytes
-rw-r--r--editor/icons/icon_bool.png (renamed from tools/editor/icons/icon_bool.png)bin154 -> 154 bytes
-rw-r--r--editor/icons/icon_box_shape.png (renamed from tools/editor/icons/icon_box_shape.png)bin392 -> 392 bytes
-rw-r--r--editor/icons/icon_bus_vu_db.png (renamed from tools/editor/icons/icon_bus_vu_db.png)bin1136 -> 1136 bytes
-rw-r--r--editor/icons/icon_bus_vu_empty.png (renamed from tools/editor/icons/icon_bus_vu_empty.png)bin1631 -> 1631 bytes
-rw-r--r--editor/icons/icon_bus_vu_frozen.png (renamed from tools/editor/icons/icon_bus_vu_frozen.png)bin267 -> 267 bytes
-rw-r--r--editor/icons/icon_bus_vu_full.png (renamed from tools/editor/icons/icon_bus_vu_full.png)bin2463 -> 2463 bytes
-rw-r--r--editor/icons/icon_button.png (renamed from tools/editor/icons/icon_button.png)bin163 -> 163 bytes
-rw-r--r--editor/icons/icon_button_group.png (renamed from tools/editor/icons/icon_button_group.png)bin165 -> 165 bytes
-rw-r--r--editor/icons/icon_camera.png (renamed from tools/editor/icons/icon_camera.png)bin225 -> 225 bytes
-rw-r--r--editor/icons/icon_camera_2d.png (renamed from tools/editor/icons/icon_camera_2d.png)bin229 -> 229 bytes
-rw-r--r--editor/icons/icon_canvas_item.png (renamed from tools/editor/icons/icon_canvas_item.png)bin411 -> 411 bytes
-rw-r--r--editor/icons/icon_canvas_item_material.png (renamed from tools/editor/icons/icon_canvas_item_material.png)bin350 -> 350 bytes
-rw-r--r--editor/icons/icon_canvas_item_shader.png (renamed from tools/editor/icons/icon_canvas_item_shader.png)bin416 -> 416 bytes
-rw-r--r--editor/icons/icon_canvas_item_shader_graph.png (renamed from tools/editor/icons/icon_canvas_item_shader_graph.png)bin440 -> 440 bytes
-rw-r--r--editor/icons/icon_canvas_layer.png (renamed from tools/editor/icons/icon_canvas_layer.png)bin474 -> 474 bytes
-rw-r--r--editor/icons/icon_canvas_modulate.png (renamed from tools/editor/icons/icon_canvas_modulate.png)bin213 -> 213 bytes
-rw-r--r--editor/icons/icon_capsule_shape.png (renamed from tools/editor/icons/icon_capsule_shape.png)bin225 -> 225 bytes
-rw-r--r--editor/icons/icon_capsule_shape_2d.png (renamed from tools/editor/icons/icon_capsule_shape_2d.png)bin309 -> 309 bytes
-rw-r--r--editor/icons/icon_center_container.png (renamed from tools/editor/icons/icon_center_container.png)bin294 -> 294 bytes
-rw-r--r--editor/icons/icon_character_body.png (renamed from tools/editor/icons/icon_character_body.png)bin559 -> 559 bytes
-rw-r--r--editor/icons/icon_character_camera.png (renamed from tools/editor/icons/icon_character_camera.png)bin477 -> 477 bytes
-rw-r--r--editor/icons/icon_check_box.png (renamed from tools/editor/icons/icon_check_box.png)bin404 -> 404 bytes
-rw-r--r--editor/icons/icon_check_button.png (renamed from tools/editor/icons/icon_check_button.png)bin283 -> 283 bytes
-rw-r--r--editor/icons/icon_checkerboard.png (renamed from tools/editor/icons/icon_checkerboard.png)bin253 -> 253 bytes
-rw-r--r--editor/icons/icon_circle_shape_2d.png (renamed from tools/editor/icons/icon_circle_shape_2d.png)bin425 -> 425 bytes
-rw-r--r--editor/icons/icon_class_list.png (renamed from tools/editor/icons/icon_class_list.png)bin157 -> 157 bytes
-rw-r--r--editor/icons/icon_click2edit.png (renamed from tools/editor/icons/icon_click2edit.png)bin294 -> 294 bytes
-rw-r--r--editor/icons/icon_close.png (renamed from tools/editor/icons/icon_close.png)bin325 -> 325 bytes
-rw-r--r--editor/icons/icon_close_hover.png (renamed from tools/editor/icons/icon_close_hover.png)bin391 -> 391 bytes
-rw-r--r--editor/icons/icon_collapse.png (renamed from tools/editor/icons/icon_collapse.png)bin230 -> 230 bytes
-rw-r--r--editor/icons/icon_collapse_hl.png (renamed from tools/editor/icons/icon_collapse_hl.png)bin338 -> 338 bytes
-rw-r--r--editor/icons/icon_collision.png (renamed from tools/editor/icons/icon_collision.png)bin320 -> 320 bytes
-rw-r--r--editor/icons/icon_collision_2d.png (renamed from tools/editor/icons/icon_collision_2d.png)bin281 -> 281 bytes
-rw-r--r--editor/icons/icon_collision_polygon.png (renamed from tools/editor/icons/icon_collision_polygon.png)bin287 -> 287 bytes
-rw-r--r--editor/icons/icon_collision_polygon_2d.png (renamed from tools/editor/icons/icon_collision_polygon_2d.png)bin281 -> 281 bytes
-rw-r--r--editor/icons/icon_collision_shape.png (renamed from tools/editor/icons/icon_collision_shape.png)bin278 -> 278 bytes
-rw-r--r--editor/icons/icon_collision_shape_2d.png (renamed from tools/editor/icons/icon_collision_shape_2d.png)bin164 -> 164 bytes
-rw-r--r--editor/icons/icon_color.png (renamed from tools/editor/icons/icon_color.png)bin582 -> 582 bytes
-rw-r--r--editor/icons/icon_color_pick.png (renamed from tools/editor/icons/icon_color_pick.png)bin416 -> 416 bytes
-rw-r--r--editor/icons/icon_color_picker.png (renamed from tools/editor/icons/icon_color_picker.png)bin432 -> 432 bytes
-rw-r--r--editor/icons/icon_color_picker_button.png (renamed from tools/editor/icons/icon_color_picker_button.png)bin548 -> 548 bytes
-rw-r--r--editor/icons/icon_color_ramp.png (renamed from tools/editor/icons/icon_color_ramp.png)bin222 -> 222 bytes
-rw-r--r--editor/icons/icon_color_rect.png (renamed from tools/editor/icons/icon_color_rect.png)bin214 -> 214 bytes
-rw-r--r--editor/icons/icon_concave_polygon_shape.png (renamed from tools/editor/icons/icon_concave_polygon_shape.png)bin449 -> 449 bytes
-rw-r--r--editor/icons/icon_concave_polygon_shape_2d.png (renamed from tools/editor/icons/icon_concave_polygon_shape_2d.png)bin321 -> 321 bytes
-rw-r--r--editor/icons/icon_cone_twist_joint.png (renamed from tools/editor/icons/icon_cone_twist_joint.png)bin497 -> 497 bytes
-rw-r--r--editor/icons/icon_confirmation_dialog.png (renamed from tools/editor/icons/icon_confirmation_dialog.png)bin330 -> 330 bytes
-rw-r--r--editor/icons/icon_connect.png (renamed from tools/editor/icons/icon_connect.png)bin170 -> 170 bytes
-rw-r--r--editor/icons/icon_connection_and_groups.png (renamed from tools/editor/icons/icon_connection_and_groups.png)bin228 -> 228 bytes
-rw-r--r--editor/icons/icon_console.png (renamed from tools/editor/icons/icon_console.png)bin640 -> 640 bytes
-rw-r--r--editor/icons/icon_container.png (renamed from tools/editor/icons/icon_container.png)bin188 -> 188 bytes
-rw-r--r--editor/icons/icon_control.png (renamed from tools/editor/icons/icon_control.png)bin414 -> 414 bytes
-rw-r--r--editor/icons/icon_control_align_bottom_center.png (renamed from tools/editor/icons/icon_control_align_bottom_center.png)bin134 -> 134 bytes
-rw-r--r--editor/icons/icon_control_align_bottom_left.png (renamed from tools/editor/icons/icon_control_align_bottom_left.png)bin134 -> 134 bytes
-rw-r--r--editor/icons/icon_control_align_bottom_right.png (renamed from tools/editor/icons/icon_control_align_bottom_right.png)bin134 -> 134 bytes
-rw-r--r--editor/icons/icon_control_align_bottom_wide.png (renamed from tools/editor/icons/icon_control_align_bottom_wide.png)bin135 -> 135 bytes
-rw-r--r--editor/icons/icon_control_align_center.png (renamed from tools/editor/icons/icon_control_align_center.png)bin142 -> 142 bytes
-rw-r--r--editor/icons/icon_control_align_center_left.png (renamed from tools/editor/icons/icon_control_align_center_left.png)bin116 -> 116 bytes
-rw-r--r--editor/icons/icon_control_align_center_right.png (renamed from tools/editor/icons/icon_control_align_center_right.png)bin117 -> 117 bytes
-rw-r--r--editor/icons/icon_control_align_left_center.png (renamed from tools/editor/icons/icon_control_align_left_center.png)bin141 -> 141 bytes
-rw-r--r--editor/icons/icon_control_align_left_wide.png (renamed from tools/editor/icons/icon_control_align_left_wide.png)bin123 -> 123 bytes
-rw-r--r--editor/icons/icon_control_align_right_center.png (renamed from tools/editor/icons/icon_control_align_right_center.png)bin142 -> 142 bytes
-rw-r--r--editor/icons/icon_control_align_right_wide.png (renamed from tools/editor/icons/icon_control_align_right_wide.png)bin124 -> 124 bytes
-rw-r--r--editor/icons/icon_control_align_top_center.png (renamed from tools/editor/icons/icon_control_align_top_center.png)bin141 -> 141 bytes
-rw-r--r--editor/icons/icon_control_align_top_left.png (renamed from tools/editor/icons/icon_control_align_top_left.png)bin136 -> 136 bytes
-rw-r--r--editor/icons/icon_control_align_top_right.png (renamed from tools/editor/icons/icon_control_align_top_right.png)bin141 -> 141 bytes
-rw-r--r--editor/icons/icon_control_align_top_wide.png (renamed from tools/editor/icons/icon_control_align_top_wide.png)bin136 -> 136 bytes
-rw-r--r--editor/icons/icon_control_align_wide.png (renamed from tools/editor/icons/icon_control_align_wide.png)bin123 -> 123 bytes
-rw-r--r--editor/icons/icon_control_hcenter_wide.png (renamed from tools/editor/icons/icon_control_hcenter_wide.png)bin142 -> 142 bytes
-rw-r--r--editor/icons/icon_control_vcenter_wide.png (renamed from tools/editor/icons/icon_control_vcenter_wide.png)bin128 -> 128 bytes
-rw-r--r--editor/icons/icon_convex_polygon_shape.png (renamed from tools/editor/icons/icon_convex_polygon_shape.png)bin404 -> 404 bytes
-rw-r--r--editor/icons/icon_convex_polygon_shape_2d.png (renamed from tools/editor/icons/icon_convex_polygon_shape_2d.png)bin297 -> 297 bytes
-rw-r--r--editor/icons/icon_copy_node_path.png (renamed from tools/editor/icons/icon_copy_node_path.png)bin248 -> 248 bytes
-rw-r--r--editor/icons/icon_create_new_scene_from.png (renamed from tools/editor/icons/icon_create_new_scene_from.png)bin349 -> 349 bytes
-rw-r--r--editor/icons/icon_cube_grid_map.png (renamed from tools/editor/icons/icon_cube_grid_map.png)bin607 -> 607 bytes
-rw-r--r--editor/icons/icon_cube_map.png (renamed from tools/editor/icons/icon_cube_map.png)bin134 -> 134 bytes
-rw-r--r--editor/icons/icon_curve.png (renamed from tools/editor/icons/icon_curve.png)bin315 -> 315 bytes
-rw-r--r--editor/icons/icon_curve_2d.png (renamed from tools/editor/icons/icon_curve_2d.png)bin342 -> 342 bytes
-rw-r--r--editor/icons/icon_curve_3d.png (renamed from tools/editor/icons/icon_curve_3d.png)bin336 -> 336 bytes
-rw-r--r--editor/icons/icon_curve_close.png (renamed from tools/editor/icons/icon_curve_close.png)bin351 -> 351 bytes
-rw-r--r--editor/icons/icon_curve_constant.png (renamed from tools/editor/icons/icon_curve_constant.png)bin114 -> 114 bytes
-rw-r--r--editor/icons/icon_curve_create.png (renamed from tools/editor/icons/icon_curve_create.png)bin375 -> 375 bytes
-rw-r--r--editor/icons/icon_curve_curve.png (renamed from tools/editor/icons/icon_curve_curve.png)bin412 -> 412 bytes
-rw-r--r--editor/icons/icon_curve_delete.png (renamed from tools/editor/icons/icon_curve_delete.png)bin457 -> 457 bytes
-rw-r--r--editor/icons/icon_curve_edit.png (renamed from tools/editor/icons/icon_curve_edit.png)bin488 -> 488 bytes
-rw-r--r--editor/icons/icon_curve_in.png (renamed from tools/editor/icons/icon_curve_in.png)bin257 -> 257 bytes
-rw-r--r--editor/icons/icon_curve_in_out.png (renamed from tools/editor/icons/icon_curve_in_out.png)bin282 -> 282 bytes
-rw-r--r--editor/icons/icon_curve_linear.png (renamed from tools/editor/icons/icon_curve_linear.png)bin219 -> 219 bytes
-rw-r--r--editor/icons/icon_curve_out.png (renamed from tools/editor/icons/icon_curve_out.png)bin263 -> 263 bytes
-rw-r--r--editor/icons/icon_curve_out_in.png (renamed from tools/editor/icons/icon_curve_out_in.png)bin288 -> 288 bytes
-rw-r--r--editor/icons/icon_cylinder_shape.png (renamed from tools/editor/icons/icon_cylinder_shape.png)bin673 -> 673 bytes
-rw-r--r--editor/icons/icon_d_o_f_blur_f_x.png (renamed from tools/editor/icons/icon_d_o_f_blur_f_x.png)bin796 -> 796 bytes
-rw-r--r--editor/icons/icon_damped_spring_joint_2d.png (renamed from tools/editor/icons/icon_damped_spring_joint_2d.png)bin316 -> 316 bytes
-rw-r--r--editor/icons/icon_debug.png (renamed from tools/editor/icons/icon_debug.png)bin659 -> 659 bytes
-rw-r--r--editor/icons/icon_debug_continue.png (renamed from tools/editor/icons/icon_debug_continue.png)bin302 -> 302 bytes
-rw-r--r--editor/icons/icon_debug_next.png (renamed from tools/editor/icons/icon_debug_next.png)bin220 -> 220 bytes
-rw-r--r--editor/icons/icon_debug_step.png (renamed from tools/editor/icons/icon_debug_step.png)bin219 -> 219 bytes
-rw-r--r--editor/icons/icon_default_project_icon.png (renamed from tools/editor/icons/icon_default_project_icon.png)bin2713 -> 2713 bytes
-rw-r--r--editor/icons/icon_del.png (renamed from tools/editor/icons/icon_del.png)bin398 -> 398 bytes
-rw-r--r--editor/icons/icon_dependency_changed.png (renamed from tools/editor/icons/icon_dependency_changed.png)bin392 -> 392 bytes
-rw-r--r--editor/icons/icon_dependency_changed_hl.png (renamed from tools/editor/icons/icon_dependency_changed_hl.png)bin330 -> 330 bytes
-rw-r--r--editor/icons/icon_dependency_local_changed.png (renamed from tools/editor/icons/icon_dependency_local_changed.png)bin571 -> 571 bytes
-rw-r--r--editor/icons/icon_dependency_local_changed_hl.png (renamed from tools/editor/icons/icon_dependency_local_changed_hl.png)bin460 -> 460 bytes
-rw-r--r--editor/icons/icon_dependency_ok.png (renamed from tools/editor/icons/icon_dependency_ok.png)bin518 -> 518 bytes
-rw-r--r--editor/icons/icon_dependency_ok_hl.png (renamed from tools/editor/icons/icon_dependency_ok_hl.png)bin413 -> 413 bytes
-rw-r--r--editor/icons/icon_directional_light.png (renamed from tools/editor/icons/icon_directional_light.png)bin426 -> 426 bytes
-rw-r--r--editor/icons/icon_distraction_free.png (renamed from tools/editor/icons/icon_distraction_free.png)bin397 -> 397 bytes
-rw-r--r--editor/icons/icon_doc_code_font.png (renamed from tools/editor/icons/icon_doc_code_font.png)bin8123 -> 8123 bytes
-rw-r--r--editor/icons/icon_doc_font.png (renamed from tools/editor/icons/icon_doc_font.png)bin8213 -> 8213 bytes
-rw-r--r--editor/icons/icon_doc_title_font.png (renamed from tools/editor/icons/icon_doc_title_font.png)bin10222 -> 10222 bytes
-rw-r--r--editor/icons/icon_down.png (renamed from tools/editor/icons/icon_down.png)bin186 -> 186 bytes
-rw-r--r--editor/icons/icon_dummy.png (renamed from tools/editor/icons/icon_dummy.png)bin217 -> 217 bytes
-rw-r--r--editor/icons/icon_duplicate.png (renamed from tools/editor/icons/icon_duplicate.png)bin167 -> 167 bytes
-rw-r--r--editor/icons/icon_dynamic_character_body.png (renamed from tools/editor/icons/icon_dynamic_character_body.png)bin559 -> 559 bytes
-rw-r--r--editor/icons/icon_dynamic_custom_body.png (renamed from tools/editor/icons/icon_dynamic_custom_body.png)bin556 -> 556 bytes
-rw-r--r--editor/icons/icon_dynamic_font.png (renamed from tools/editor/icons/icon_dynamic_font.png)bin239 -> 239 bytes
-rw-r--r--editor/icons/icon_dynamic_font_data.png (renamed from tools/editor/icons/icon_dynamic_font_data.png)bin246 -> 246 bytes
-rw-r--r--editor/icons/icon_dynamic_rigid_body.png (renamed from tools/editor/icons/icon_dynamic_rigid_body.png)bin546 -> 546 bytes
-rw-r--r--editor/icons/icon_edit.png (renamed from tools/editor/icons/icon_edit.png)bin346 -> 346 bytes
-rw-r--r--editor/icons/icon_edit_key.png (renamed from tools/editor/icons/icon_edit_key.png)bin405 -> 405 bytes
-rw-r--r--editor/icons/icon_edit_pivot.png (renamed from tools/editor/icons/icon_edit_pivot.png)bin327 -> 327 bytes
-rw-r--r--editor/icons/icon_edit_resource.png (renamed from tools/editor/icons/icon_edit_resource.png)bin232 -> 232 bytes
-rw-r--r--editor/icons/icon_edit_small.png (renamed from tools/editor/icons/icon_edit_small.png)bin365 -> 365 bytes
-rw-r--r--editor/icons/icon_editor_2d.png (renamed from tools/editor/icons/icon_editor_2d.png)bin197 -> 197 bytes
-rw-r--r--editor/icons/icon_editor_3d_handle.png (renamed from tools/editor/icons/icon_editor_3d_handle.png)bin350 -> 350 bytes
-rw-r--r--editor/icons/icon_editor_focus.png (renamed from tools/editor/icons/icon_editor_focus.png)bin629 -> 629 bytes
-rw-r--r--editor/icons/icon_editor_handle.png (renamed from tools/editor/icons/icon_editor_handle.png)bin214 -> 214 bytes
-rw-r--r--editor/icons/icon_editor_node.png (renamed from tools/editor/icons/icon_editor_node.png)bin311 -> 311 bytes
-rw-r--r--editor/icons/icon_editor_pivot.png (renamed from tools/editor/icons/icon_editor_pivot.png)bin177 -> 177 bytes
-rw-r--r--editor/icons/icon_editor_plugin.png (renamed from tools/editor/icons/icon_editor_plugin.png)bin248 -> 248 bytes
-rw-r--r--editor/icons/icon_editor_rect_2d.png (renamed from tools/editor/icons/icon_editor_rect_2d.png)bin222 -> 222 bytes
-rw-r--r--editor/icons/icon_empty_control.png (renamed from tools/editor/icons/icon_empty_control.png)bin233 -> 233 bytes
-rw-r--r--editor/icons/icon_enum.png (renamed from tools/editor/icons/icon_enum.png)bin123 -> 123 bytes
-rw-r--r--editor/icons/icon_environment.png (renamed from tools/editor/icons/icon_environment.png)bin588 -> 588 bytes
-rw-r--r--editor/icons/icon_error.png (renamed from tools/editor/icons/icon_error.png)bin121 -> 121 bytes
-rw-r--r--editor/icons/icon_error_sign.png (renamed from tools/editor/icons/icon_error_sign.png)bin255 -> 255 bytes
-rw-r--r--editor/icons/icon_event_player.png (renamed from tools/editor/icons/icon_event_player.png)bin142 -> 142 bytes
-rw-r--r--editor/icons/icon_expand.png (renamed from tools/editor/icons/icon_expand.png)bin322 -> 322 bytes
-rw-r--r--editor/icons/icon_expand_hl.png (renamed from tools/editor/icons/icon_expand_hl.png)bin320 -> 320 bytes
-rw-r--r--editor/icons/icon_favorites.png (renamed from tools/editor/icons/icon_favorites.png)bin385 -> 385 bytes
-rw-r--r--editor/icons/icon_file.png (renamed from tools/editor/icons/icon_file.png)bin157 -> 157 bytes
-rw-r--r--editor/icons/icon_file_big.png (renamed from tools/editor/icons/icon_file_big.png)bin317 -> 317 bytes
-rw-r--r--editor/icons/icon_file_dialog.png (renamed from tools/editor/icons/icon_file_dialog.png)bin220 -> 220 bytes
-rw-r--r--editor/icons/icon_file_list.png (renamed from tools/editor/icons/icon_file_list.png)bin123 -> 123 bytes
-rw-r--r--editor/icons/icon_file_server.png (renamed from tools/editor/icons/icon_file_server.png)bin145 -> 145 bytes
-rw-r--r--editor/icons/icon_file_server_active.png (renamed from tools/editor/icons/icon_file_server_active.png)bin145 -> 145 bytes
-rw-r--r--editor/icons/icon_file_thumbnail.png (renamed from tools/editor/icons/icon_file_thumbnail.png)bin116 -> 116 bytes
-rw-r--r--editor/icons/icon_filesystem.png (renamed from tools/editor/icons/icon_filesystem.png)bin157 -> 157 bytes
-rw-r--r--editor/icons/icon_fixed_material.png (renamed from tools/editor/icons/icon_fixed_material.png)bin377 -> 377 bytes
-rw-r--r--editor/icons/icon_fixed_spatial_material.png (renamed from tools/editor/icons/icon_fixed_spatial_material.png)bin409 -> 409 bytes
-rw-r--r--editor/icons/icon_fog_f_x.png (renamed from tools/editor/icons/icon_fog_f_x.png)bin540 -> 540 bytes
-rw-r--r--editor/icons/icon_folder.png (renamed from tools/editor/icons/icon_folder.png)bin170 -> 170 bytes
-rw-r--r--editor/icons/icon_folder_big.png (renamed from tools/editor/icons/icon_folder_big.png)bin482 -> 482 bytes
-rw-r--r--editor/icons/icon_folder_scene.png (renamed from tools/editor/icons/icon_folder_scene.png)bin644 -> 644 bytes
-rw-r--r--editor/icons/icon_font.png (renamed from tools/editor/icons/icon_font.png)bin215 -> 215 bytes
-rw-r--r--editor/icons/icon_forward.png (renamed from tools/editor/icons/icon_forward.png)bin224 -> 224 bytes
-rw-r--r--editor/icons/icon_forward_no.png (renamed from tools/editor/icons/icon_forward_no.png)bin217 -> 217 bytes
-rw-r--r--editor/icons/icon_func.png (renamed from tools/editor/icons/icon_func.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/icon_g_d_script.png (renamed from tools/editor/icons/icon_g_d_script.png)bin392 -> 392 bytes
-rw-r--r--editor/icons/icon_g_i_probe.png (renamed from tools/editor/icons/icon_g_i_probe.png)bin341 -> 341 bytes
-rw-r--r--editor/icons/icon_g_i_probe_data.png (renamed from tools/editor/icons/icon_g_i_probe_data.png)bin350 -> 350 bytes
-rw-r--r--editor/icons/icon_gamma_f_x.png (renamed from tools/editor/icons/icon_gamma_f_x.png)bin461 -> 461 bytes
-rw-r--r--editor/icons/icon_generic_6_d_o_f_joint.png (renamed from tools/editor/icons/icon_generic_6_d_o_f_joint.png)bin390 -> 390 bytes
-rw-r--r--editor/icons/icon_gizmo_directional_light.png (renamed from tools/editor/icons/icon_gizmo_directional_light.png)bin3628 -> 3628 bytes
-rw-r--r--editor/icons/icon_gizmo_light.png (renamed from tools/editor/icons/icon_gizmo_light.png)bin3064 -> 3064 bytes
-rw-r--r--editor/icons/icon_gizmo_listener.png (renamed from tools/editor/icons/icon_gizmo_listener.png)bin3613 -> 3613 bytes
-rw-r--r--editor/icons/icon_gizmo_spatial_sample_player.png (renamed from tools/editor/icons/icon_gizmo_spatial_sample_player.png)bin1297 -> 1297 bytes
-rw-r--r--editor/icons/icon_gizmo_spatial_stream_player.png (renamed from tools/editor/icons/icon_gizmo_spatial_stream_player.png)bin1720 -> 1720 bytes
-rw-r--r--editor/icons/icon_glow_f_x.png (renamed from tools/editor/icons/icon_glow_f_x.png)bin676 -> 676 bytes
-rw-r--r--editor/icons/icon_godot.png (renamed from tools/editor/icons/icon_godot.png)bin769 -> 769 bytes
-rw-r--r--editor/icons/icon_godot_asset_default.png (renamed from tools/editor/icons/icon_godot_asset_default.png)bin4167 -> 4167 bytes
-rw-r--r--editor/icons/icon_graph_color_ramp.png (renamed from tools/editor/icons/icon_graph_color_ramp.png)bin222 -> 222 bytes
-rw-r--r--editor/icons/icon_graph_comment.png (renamed from tools/editor/icons/icon_graph_comment.png)bin125 -> 125 bytes
-rw-r--r--editor/icons/icon_graph_cube_uniform.png (renamed from tools/editor/icons/icon_graph_cube_uniform.png)bin445 -> 445 bytes
-rw-r--r--editor/icons/icon_graph_curve_map.png (renamed from tools/editor/icons/icon_graph_curve_map.png)bin330 -> 330 bytes
-rw-r--r--editor/icons/icon_graph_default_texture.png (renamed from tools/editor/icons/icon_graph_default_texture.png)bin196 -> 196 bytes
-rw-r--r--editor/icons/icon_graph_edit.png (renamed from tools/editor/icons/icon_graph_edit.png)bin467 -> 467 bytes
-rw-r--r--editor/icons/icon_graph_input.png (renamed from tools/editor/icons/icon_graph_input.png)bin268 -> 268 bytes
-rw-r--r--editor/icons/icon_graph_node.png (renamed from tools/editor/icons/icon_graph_node.png)bin397 -> 397 bytes
-rw-r--r--editor/icons/icon_graph_rgb.png (renamed from tools/editor/icons/icon_graph_rgb.png)bin443 -> 443 bytes
-rw-r--r--editor/icons/icon_graph_rgb_op.png (renamed from tools/editor/icons/icon_graph_rgb_op.png)bin165 -> 165 bytes
-rw-r--r--editor/icons/icon_graph_rgb_uniform.png (renamed from tools/editor/icons/icon_graph_rgb_uniform.png)bin346 -> 346 bytes
-rw-r--r--editor/icons/icon_graph_scalar.png (renamed from tools/editor/icons/icon_graph_scalar.png)bin269 -> 269 bytes
-rw-r--r--editor/icons/icon_graph_scalar_interp.png (renamed from tools/editor/icons/icon_graph_scalar_interp.png)bin236 -> 236 bytes
-rw-r--r--editor/icons/icon_graph_scalar_op.png (renamed from tools/editor/icons/icon_graph_scalar_op.png)bin266 -> 266 bytes
-rw-r--r--editor/icons/icon_graph_scalar_uniform.png (renamed from tools/editor/icons/icon_graph_scalar_uniform.png)bin307 -> 307 bytes
-rw-r--r--editor/icons/icon_graph_scalars_to_vec.png (renamed from tools/editor/icons/icon_graph_scalars_to_vec.png)bin172 -> 172 bytes
-rw-r--r--editor/icons/icon_graph_texscreen.png (renamed from tools/editor/icons/icon_graph_texscreen.png)bin151 -> 151 bytes
-rw-r--r--editor/icons/icon_graph_texture_uniform.png (renamed from tools/editor/icons/icon_graph_texture_uniform.png)bin237 -> 237 bytes
-rw-r--r--editor/icons/icon_graph_time.png (renamed from tools/editor/icons/icon_graph_time.png)bin398 -> 398 bytes
-rw-r--r--editor/icons/icon_graph_vec_dp.png (renamed from tools/editor/icons/icon_graph_vec_dp.png)bin258 -> 258 bytes
-rw-r--r--editor/icons/icon_graph_vec_interp.png (renamed from tools/editor/icons/icon_graph_vec_interp.png)bin229 -> 229 bytes
-rw-r--r--editor/icons/icon_graph_vec_length.png (renamed from tools/editor/icons/icon_graph_vec_length.png)bin305 -> 305 bytes
-rw-r--r--editor/icons/icon_graph_vec_op.png (renamed from tools/editor/icons/icon_graph_vec_op.png)bin266 -> 266 bytes
-rw-r--r--editor/icons/icon_graph_vec_scalar_op.png (renamed from tools/editor/icons/icon_graph_vec_scalar_op.png)bin299 -> 299 bytes
-rw-r--r--editor/icons/icon_graph_vec_to_scalars.png (renamed from tools/editor/icons/icon_graph_vec_to_scalars.png)bin181 -> 181 bytes
-rw-r--r--editor/icons/icon_graph_vecs_to_xform.png (renamed from tools/editor/icons/icon_graph_vecs_to_xform.png)bin178 -> 178 bytes
-rw-r--r--editor/icons/icon_graph_vector.png (renamed from tools/editor/icons/icon_graph_vector.png)bin345 -> 345 bytes
-rw-r--r--editor/icons/icon_graph_vector_uniform.png (renamed from tools/editor/icons/icon_graph_vector_uniform.png)bin390 -> 390 bytes
-rw-r--r--editor/icons/icon_graph_xform.png (renamed from tools/editor/icons/icon_graph_xform.png)bin241 -> 241 bytes
-rw-r--r--editor/icons/icon_graph_xform_mult.png (renamed from tools/editor/icons/icon_graph_xform_mult.png)bin223 -> 223 bytes
-rw-r--r--editor/icons/icon_graph_xform_scalar_func.png (renamed from tools/editor/icons/icon_graph_xform_scalar_func.png)bin275 -> 275 bytes
-rw-r--r--editor/icons/icon_graph_xform_to_vecs.png (renamed from tools/editor/icons/icon_graph_xform_to_vecs.png)bin195 -> 195 bytes
-rw-r--r--editor/icons/icon_graph_xform_uniform.png (renamed from tools/editor/icons/icon_graph_xform_uniform.png)bin310 -> 310 bytes
-rw-r--r--editor/icons/icon_graph_xform_vec_func.png (renamed from tools/editor/icons/icon_graph_xform_vec_func.png)bin277 -> 277 bytes
-rw-r--r--editor/icons/icon_graph_xform_vec_imult.png (renamed from tools/editor/icons/icon_graph_xform_vec_imult.png)bin327 -> 327 bytes
-rw-r--r--editor/icons/icon_graph_xform_vec_mult.png (renamed from tools/editor/icons/icon_graph_xform_vec_mult.png)bin336 -> 336 bytes
-rw-r--r--editor/icons/icon_grid.png (renamed from tools/editor/icons/icon_grid.png)bin165 -> 165 bytes
-rw-r--r--editor/icons/icon_grid_container.png (renamed from tools/editor/icons/icon_grid_container.png)bin216 -> 216 bytes
-rw-r--r--editor/icons/icon_grid_map.png (renamed from tools/editor/icons/icon_grid_map.png)bin122 -> 122 bytes
-rw-r--r--editor/icons/icon_grid_map_floor.png (renamed from tools/editor/icons/icon_grid_map_floor.png)bin169 -> 169 bytes
-rw-r--r--editor/icons/icon_groove_joint_2d.png (renamed from tools/editor/icons/icon_groove_joint_2d.png)bin150 -> 150 bytes
-rw-r--r--editor/icons/icon_group.png (renamed from tools/editor/icons/icon_group.png)bin177 -> 177 bytes
-rw-r--r--editor/icons/icon_groups.png (renamed from tools/editor/icons/icon_groups.png)bin194 -> 194 bytes
-rw-r--r--editor/icons/icon_h_box_container.png (renamed from tools/editor/icons/icon_h_box_container.png)bin201 -> 201 bytes
-rw-r--r--editor/icons/icon_h_button_array.png (renamed from tools/editor/icons/icon_h_button_array.png)bin163 -> 163 bytes
-rw-r--r--editor/icons/icon_h_scroll_bar.png (renamed from tools/editor/icons/icon_h_scroll_bar.png)bin205 -> 205 bytes
-rw-r--r--editor/icons/icon_h_separator.png (renamed from tools/editor/icons/icon_h_separator.png)bin131 -> 131 bytes
-rw-r--r--editor/icons/icon_h_slider.png (renamed from tools/editor/icons/icon_h_slider.png)bin204 -> 204 bytes
-rw-r--r--editor/icons/icon_h_split_container.png (renamed from tools/editor/icons/icon_h_split_container.png)bin259 -> 259 bytes
-rw-r--r--editor/icons/icon_h_t_t_p_request.png (renamed from tools/editor/icons/icon_h_t_t_p_request.png)bin301 -> 301 bytes
-rw-r--r--editor/icons/icon_headphones.png (renamed from tools/editor/icons/icon_headphones.png)bin350 -> 350 bytes
-rw-r--r--editor/icons/icon_help.png (renamed from tools/editor/icons/icon_help.png)bin578 -> 578 bytes
-rw-r--r--editor/icons/icon_hidden.png (renamed from tools/editor/icons/icon_hidden.png)bin345 -> 345 bytes
-rw-r--r--editor/icons/icon_hinge_joint.png (renamed from tools/editor/icons/icon_hinge_joint.png)bin353 -> 353 bytes
-rw-r--r--editor/icons/icon_history.png (renamed from tools/editor/icons/icon_history.png)bin437 -> 437 bytes
-rw-r--r--editor/icons/icon_hsize.png (renamed from tools/editor/icons/icon_hsize.png)bin166 -> 166 bytes
-rw-r--r--editor/icons/icon_iapi.png (renamed from tools/editor/icons/icon_iapi.png)bin277 -> 277 bytes
-rw-r--r--editor/icons/icon_image.png (renamed from tools/editor/icons/icon_image.png)bin263 -> 263 bytes
-rw-r--r--editor/icons/icon_image_sky_box.png (renamed from tools/editor/icons/icon_image_sky_box.png)bin434 -> 434 bytes
-rw-r--r--editor/icons/icon_image_texture.png (renamed from tools/editor/icons/icon_image_texture.png)bin200 -> 200 bytes
-rw-r--r--editor/icons/icon_immediate_geometry.png (renamed from tools/editor/icons/icon_immediate_geometry.png)bin411 -> 411 bytes
-rw-r--r--editor/icons/icon_import_check.png (renamed from tools/editor/icons/icon_import_check.png)bin266 -> 266 bytes
-rw-r--r--editor/icons/icon_import_fail.png (renamed from tools/editor/icons/icon_import_fail.png)bin346 -> 346 bytes
-rw-r--r--editor/icons/icon_influence_zone.png (renamed from tools/editor/icons/icon_influence_zone.png)bin303 -> 303 bytes
-rw-r--r--editor/icons/icon_instance.png (renamed from tools/editor/icons/icon_instance.png)bin442 -> 442 bytes
-rw-r--r--editor/icons/icon_instance_options.png (renamed from tools/editor/icons/icon_instance_options.png)bin365 -> 365 bytes
-rw-r--r--editor/icons/icon_integer.png (renamed from tools/editor/icons/icon_integer.png)bin126 -> 126 bytes
-rw-r--r--editor/icons/icon_interp_cubic.png (renamed from tools/editor/icons/icon_interp_cubic.png)bin281 -> 281 bytes
-rw-r--r--editor/icons/icon_interp_linear.png (renamed from tools/editor/icons/icon_interp_linear.png)bin271 -> 271 bytes
-rw-r--r--editor/icons/icon_interp_raw.png (renamed from tools/editor/icons/icon_interp_raw.png)bin156 -> 156 bytes
-rw-r--r--editor/icons/icon_interp_wrap_clamp.png (renamed from tools/editor/icons/icon_interp_wrap_clamp.png)bin233 -> 233 bytes
-rw-r--r--editor/icons/icon_interp_wrap_loop.png (renamed from tools/editor/icons/icon_interp_wrap_loop.png)bin309 -> 309 bytes
-rw-r--r--editor/icons/icon_interpolated_camera.png (renamed from tools/editor/icons/icon_interpolated_camera.png)bin279 -> 279 bytes
-rw-r--r--editor/icons/icon_invalid_key.png (renamed from tools/editor/icons/icon_invalid_key.png)bin205 -> 205 bytes
-rw-r--r--editor/icons/icon_inverse_kinematics.png (renamed from tools/editor/icons/icon_inverse_kinematics.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/icon_item_list.png (renamed from tools/editor/icons/icon_item_list.png)bin216 -> 216 bytes
-rw-r--r--editor/icons/icon_joy_axis.png (renamed from tools/editor/icons/icon_joy_axis.png)bin260 -> 260 bytes
-rw-r--r--editor/icons/icon_joy_button.png (renamed from tools/editor/icons/icon_joy_button.png)bin272 -> 272 bytes
-rw-r--r--editor/icons/icon_joypad.png (renamed from tools/editor/icons/icon_joypad.png)bin239 -> 239 bytes
-rw-r--r--editor/icons/icon_key.png (renamed from tools/editor/icons/icon_key.png)bin285 -> 285 bytes
-rw-r--r--editor/icons/icon_key_call.png (renamed from tools/editor/icons/icon_key_call.png)bin265 -> 265 bytes
-rw-r--r--editor/icons/icon_key_hover.png (renamed from tools/editor/icons/icon_key_hover.png)bin206 -> 206 bytes
-rw-r--r--editor/icons/icon_key_invalid.png (renamed from tools/editor/icons/icon_key_invalid.png)bin205 -> 205 bytes
-rw-r--r--editor/icons/icon_key_invalid_hover.png (renamed from tools/editor/icons/icon_key_invalid_hover.png)bin239 -> 239 bytes
-rw-r--r--editor/icons/icon_key_next.png (renamed from tools/editor/icons/icon_key_next.png)bin321 -> 321 bytes
-rw-r--r--editor/icons/icon_key_selected.png (renamed from tools/editor/icons/icon_key_selected.png)bin203 -> 203 bytes
-rw-r--r--editor/icons/icon_key_value.png (renamed from tools/editor/icons/icon_key_value.png)bin210 -> 210 bytes
-rw-r--r--editor/icons/icon_key_xform.png (renamed from tools/editor/icons/icon_key_xform.png)bin213 -> 213 bytes
-rw-r--r--editor/icons/icon_keyboard.png (renamed from tools/editor/icons/icon_keyboard.png)bin299 -> 299 bytes
-rw-r--r--editor/icons/icon_keying.png (renamed from tools/editor/icons/icon_keying.png)bin1603 -> 1603 bytes
-rw-r--r--editor/icons/icon_kinematic_body.png (renamed from tools/editor/icons/icon_kinematic_body.png)bin145 -> 145 bytes
-rw-r--r--editor/icons/icon_kinematic_body_2d.png (renamed from tools/editor/icons/icon_kinematic_body_2d.png)bin147 -> 147 bytes
-rw-r--r--editor/icons/icon_label.png (renamed from tools/editor/icons/icon_label.png)bin240 -> 240 bytes
-rw-r--r--editor/icons/icon_large_texture.png (renamed from tools/editor/icons/icon_large_texture.png)bin156 -> 156 bytes
-rw-r--r--editor/icons/icon_light_2d.png (renamed from tools/editor/icons/icon_light_2d.png)bin362 -> 362 bytes
-rw-r--r--editor/icons/icon_light_map.png (renamed from tools/editor/icons/icon_light_map.png)bin406 -> 406 bytes
-rw-r--r--editor/icons/icon_light_occluder_2d.png (renamed from tools/editor/icons/icon_light_occluder_2d.png)bin146 -> 146 bytes
-rw-r--r--editor/icons/icon_lightr.png (renamed from tools/editor/icons/icon_lightr.png)bin272 -> 272 bytes
-rw-r--r--editor/icons/icon_line_2d.pngbin0 -> 474 bytes
-rw-r--r--editor/icons/icon_line_edit.png (renamed from tools/editor/icons/icon_line_edit.png)bin201 -> 201 bytes
-rw-r--r--editor/icons/icon_line_shape_2d.png (renamed from tools/editor/icons/icon_line_shape_2d.png)bin379 -> 379 bytes
-rw-r--r--editor/icons/icon_link_button.png (renamed from tools/editor/icons/icon_link_button.png)bin409 -> 409 bytes
-rw-r--r--editor/icons/icon_list_select.png (renamed from tools/editor/icons/icon_list_select.png)bin349 -> 349 bytes
-rw-r--r--editor/icons/icon_listener.png (renamed from tools/editor/icons/icon_listener.png)bin448 -> 448 bytes
-rw-r--r--editor/icons/icon_live_debug.png (renamed from tools/editor/icons/icon_live_debug.png)bin583 -> 583 bytes
-rw-r--r--editor/icons/icon_load.png (renamed from tools/editor/icons/icon_load.png)bin271 -> 271 bytes
-rw-r--r--editor/icons/icon_lock.png (renamed from tools/editor/icons/icon_lock.png)bin271 -> 271 bytes
-rw-r--r--editor/icons/icon_logo.png (renamed from tools/editor/icons/icon_logo.png)bin6211 -> 6211 bytes
-rw-r--r--editor/icons/icon_logo_small.png (renamed from tools/editor/icons/icon_logo_small.png)bin1825 -> 1825 bytes
-rw-r--r--editor/icons/icon_loop.png (renamed from tools/editor/icons/icon_loop.png)bin412 -> 412 bytes
-rw-r--r--editor/icons/icon_loop_interpolation.png (renamed from tools/editor/icons/icon_loop_interpolation.png)bin374 -> 374 bytes
-rw-r--r--editor/icons/icon_main_play.png (renamed from tools/editor/icons/icon_main_play.png)bin234 -> 234 bytes
-rw-r--r--editor/icons/icon_main_stop.png (renamed from tools/editor/icons/icon_main_stop.png)bin144 -> 144 bytes
-rw-r--r--editor/icons/icon_margin_container.png (renamed from tools/editor/icons/icon_margin_container.png)bin233 -> 233 bytes
-rw-r--r--editor/icons/icon_material_preview_cube.png (renamed from tools/editor/icons/icon_material_preview_cube.png)bin374 -> 374 bytes
-rw-r--r--editor/icons/icon_material_preview_cube_off.png (renamed from tools/editor/icons/icon_material_preview_cube_off.png)bin401 -> 401 bytes
-rw-r--r--editor/icons/icon_material_preview_light_1.png (renamed from tools/editor/icons/icon_material_preview_light_1.png)bin359 -> 359 bytes
-rw-r--r--editor/icons/icon_material_preview_light_1_off.png (renamed from tools/editor/icons/icon_material_preview_light_1_off.png)bin305 -> 305 bytes
-rw-r--r--editor/icons/icon_material_preview_light_2.png (renamed from tools/editor/icons/icon_material_preview_light_2.png)bin354 -> 354 bytes
-rw-r--r--editor/icons/icon_material_preview_light_2_off.png (renamed from tools/editor/icons/icon_material_preview_light_2_off.png)bin443 -> 443 bytes
-rw-r--r--editor/icons/icon_material_preview_sphere.png (renamed from tools/editor/icons/icon_material_preview_sphere.png)bin359 -> 359 bytes
-rw-r--r--editor/icons/icon_material_preview_sphere_off.png (renamed from tools/editor/icons/icon_material_preview_sphere_off.png)bin283 -> 283 bytes
-rw-r--r--editor/icons/icon_material_shader.png (renamed from tools/editor/icons/icon_material_shader.png)bin254 -> 254 bytes
-rw-r--r--editor/icons/icon_material_shader_graph.png (renamed from tools/editor/icons/icon_material_shader_graph.png)bin440 -> 440 bytes
-rw-r--r--editor/icons/icon_matrix.png (renamed from tools/editor/icons/icon_matrix.png)bin138 -> 138 bytes
-rw-r--r--editor/icons/icon_menu_button.png (renamed from tools/editor/icons/icon_menu_button.png)bin213 -> 213 bytes
-rw-r--r--editor/icons/icon_mesh.png (renamed from tools/editor/icons/icon_mesh.png)bin343 -> 343 bytes
-rw-r--r--editor/icons/icon_mesh_instance.png (renamed from tools/editor/icons/icon_mesh_instance.png)bin314 -> 314 bytes
-rw-r--r--editor/icons/icon_mesh_library.png (renamed from tools/editor/icons/icon_mesh_library.png)bin349 -> 349 bytes
-rw-r--r--editor/icons/icon_mesh_old.png (renamed from tools/editor/icons/icon_mesh_old.png)bin615 -> 615 bytes
-rw-r--r--editor/icons/icon_meshr.png (renamed from tools/editor/icons/icon_meshr.png)bin744 -> 744 bytes
-rw-r--r--editor/icons/icon_mini_aabb.png (renamed from tools/editor/icons/icon_mini_aabb.png)bin360 -> 360 bytes
-rw-r--r--editor/icons/icon_mini_array.png (renamed from tools/editor/icons/icon_mini_array.png)bin210 -> 210 bytes
-rw-r--r--editor/icons/icon_mini_boolean.png (renamed from tools/editor/icons/icon_mini_boolean.png)bin256 -> 256 bytes
-rw-r--r--editor/icons/icon_mini_color.png (renamed from tools/editor/icons/icon_mini_color.png)bin253 -> 253 bytes
-rw-r--r--editor/icons/icon_mini_color_array.png (renamed from tools/editor/icons/icon_mini_color_array.png)bin337 -> 337 bytes
-rw-r--r--editor/icons/icon_mini_dictionary.png (renamed from tools/editor/icons/icon_mini_dictionary.png)bin230 -> 230 bytes
-rw-r--r--editor/icons/icon_mini_float.png (renamed from tools/editor/icons/icon_mini_float.png)bin233 -> 233 bytes
-rw-r--r--editor/icons/icon_mini_float_array.png (renamed from tools/editor/icons/icon_mini_float_array.png)bin275 -> 275 bytes
-rw-r--r--editor/icons/icon_mini_image.png (renamed from tools/editor/icons/icon_mini_image.png)bin257 -> 257 bytes
-rw-r--r--editor/icons/icon_mini_input.png (renamed from tools/editor/icons/icon_mini_input.png)bin236 -> 236 bytes
-rw-r--r--editor/icons/icon_mini_int_array.png (renamed from tools/editor/icons/icon_mini_int_array.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/icon_mini_integer.png (renamed from tools/editor/icons/icon_mini_integer.png)bin228 -> 228 bytes
-rw-r--r--editor/icons/icon_mini_matrix3.png (renamed from tools/editor/icons/icon_mini_matrix3.png)bin236 -> 236 bytes
-rw-r--r--editor/icons/icon_mini_matrix32.png (renamed from tools/editor/icons/icon_mini_matrix32.png)bin320 -> 320 bytes
-rw-r--r--editor/icons/icon_mini_object.png (renamed from tools/editor/icons/icon_mini_object.png)bin289 -> 289 bytes
-rw-r--r--editor/icons/icon_mini_path.png (renamed from tools/editor/icons/icon_mini_path.png)bin254 -> 254 bytes
-rw-r--r--editor/icons/icon_mini_plane.png (renamed from tools/editor/icons/icon_mini_plane.png)bin249 -> 249 bytes
-rw-r--r--editor/icons/icon_mini_quat.png (renamed from tools/editor/icons/icon_mini_quat.png)bin309 -> 309 bytes
-rw-r--r--editor/icons/icon_mini_raw_array.png (renamed from tools/editor/icons/icon_mini_raw_array.png)bin248 -> 248 bytes
-rw-r--r--editor/icons/icon_mini_rect2.png (renamed from tools/editor/icons/icon_mini_rect2.png)bin267 -> 267 bytes
-rw-r--r--editor/icons/icon_mini_rid.png (renamed from tools/editor/icons/icon_mini_rid.png)bin222 -> 222 bytes
-rw-r--r--editor/icons/icon_mini_string.png (renamed from tools/editor/icons/icon_mini_string.png)bin258 -> 258 bytes
-rw-r--r--editor/icons/icon_mini_string_array.png (renamed from tools/editor/icons/icon_mini_string_array.png)bin296 -> 296 bytes
-rw-r--r--editor/icons/icon_mini_transform.png (renamed from tools/editor/icons/icon_mini_transform.png)bin321 -> 321 bytes
-rw-r--r--editor/icons/icon_mini_variant.png (renamed from tools/editor/icons/icon_mini_variant.png)bin240 -> 240 bytes
-rw-r--r--editor/icons/icon_mini_vector2.png (renamed from tools/editor/icons/icon_mini_vector2.png)bin301 -> 301 bytes
-rw-r--r--editor/icons/icon_mini_vector2_array.png (renamed from tools/editor/icons/icon_mini_vector2_array.png)bin284 -> 284 bytes
-rw-r--r--editor/icons/icon_mini_vector3.png (renamed from tools/editor/icons/icon_mini_vector3.png)bin285 -> 285 bytes
-rw-r--r--editor/icons/icon_mini_vector3_array.png (renamed from tools/editor/icons/icon_mini_vector3_array.png)bin264 -> 264 bytes
-rw-r--r--editor/icons/icon_mirror_x.png (renamed from tools/editor/icons/icon_mirror_x.png)bin166 -> 166 bytes
-rw-r--r--editor/icons/icon_mirror_y.png (renamed from tools/editor/icons/icon_mirror_y.png)bin168 -> 168 bytes
-rw-r--r--editor/icons/icon_mouse.png (renamed from tools/editor/icons/icon_mouse.png)bin256 -> 256 bytes
-rw-r--r--editor/icons/icon_move_down.png (renamed from tools/editor/icons/icon_move_down.png)bin268 -> 268 bytes
-rw-r--r--editor/icons/icon_move_down_hl.png (renamed from tools/editor/icons/icon_move_down_hl.png)bin234 -> 234 bytes
-rw-r--r--editor/icons/icon_move_point.png (renamed from tools/editor/icons/icon_move_point.png)bin542 -> 542 bytes
-rw-r--r--editor/icons/icon_move_up.png (renamed from tools/editor/icons/icon_move_up.png)bin269 -> 269 bytes
-rw-r--r--editor/icons/icon_move_up_hl.png (renamed from tools/editor/icons/icon_move_up_hl.png)bin224 -> 224 bytes
-rw-r--r--editor/icons/icon_multi_edit.png (renamed from tools/editor/icons/icon_multi_edit.png)bin358 -> 358 bytes
-rw-r--r--editor/icons/icon_multi_line.png (renamed from tools/editor/icons/icon_multi_line.png)bin140 -> 140 bytes
-rw-r--r--editor/icons/icon_multi_mesh.png (renamed from tools/editor/icons/icon_multi_mesh.png)bin347 -> 347 bytes
-rw-r--r--editor/icons/icon_multi_mesh_instance.png (renamed from tools/editor/icons/icon_multi_mesh_instance.png)bin376 -> 376 bytes
-rw-r--r--editor/icons/icon_multi_node_edit.png (renamed from tools/editor/icons/icon_multi_node_edit.png)bin358 -> 358 bytes
-rw-r--r--editor/icons/icon_navigation.png (renamed from tools/editor/icons/icon_navigation.png)bin344 -> 344 bytes
-rw-r--r--editor/icons/icon_navigation_2d.png (renamed from tools/editor/icons/icon_navigation_2d.png)bin363 -> 363 bytes
-rw-r--r--editor/icons/icon_navigation_mesh.png (renamed from tools/editor/icons/icon_navigation_mesh.png)bin450 -> 450 bytes
-rw-r--r--editor/icons/icon_navigation_mesh_instance.png (renamed from tools/editor/icons/icon_navigation_mesh_instance.png)bin480 -> 480 bytes
-rw-r--r--editor/icons/icon_navigation_polygon.png (renamed from tools/editor/icons/icon_navigation_polygon.png)bin384 -> 384 bytes
-rw-r--r--editor/icons/icon_navigation_polygon_instance.png (renamed from tools/editor/icons/icon_navigation_polygon_instance.png)bin409 -> 409 bytes
-rw-r--r--editor/icons/icon_new.png (renamed from tools/editor/icons/icon_new.png)bin157 -> 157 bytes
-rw-r--r--editor/icons/icon_nine_patch_rect.png (renamed from tools/editor/icons/icon_nine_patch_rect.png)bin128 -> 128 bytes
-rw-r--r--editor/icons/icon_node.png (renamed from tools/editor/icons/icon_node.png)bin403 -> 403 bytes
-rw-r--r--editor/icons/icon_node_2d.png (renamed from tools/editor/icons/icon_node_2d.png)bin427 -> 427 bytes
-rw-r--r--editor/icons/icon_node_real_slot.png (renamed from tools/editor/icons/icon_node_real_slot.png)bin239 -> 239 bytes
-rw-r--r--editor/icons/icon_node_vec_slot.png (renamed from tools/editor/icons/icon_node_vec_slot.png)bin240 -> 240 bytes
-rw-r--r--editor/icons/icon_node_warning.png (renamed from tools/editor/icons/icon_node_warning.png)bin320 -> 320 bytes
-rw-r--r--editor/icons/icon_non_favorite.png (renamed from tools/editor/icons/icon_non_favorite.png)bin475 -> 475 bytes
-rw-r--r--editor/icons/icon_object.png (renamed from tools/editor/icons/icon_object.png)bin354 -> 354 bytes
-rw-r--r--editor/icons/icon_occluder_polygon_2d.png (renamed from tools/editor/icons/icon_occluder_polygon_2d.png)bin274 -> 274 bytes
-rw-r--r--editor/icons/icon_omni_light.png (renamed from tools/editor/icons/icon_omni_light.png)bin347 -> 347 bytes
-rw-r--r--editor/icons/icon_open.png (renamed from tools/editor/icons/icon_open.png)bin170 -> 170 bytes
-rw-r--r--editor/icons/icon_option_button.png (renamed from tools/editor/icons/icon_option_button.png)bin218 -> 218 bytes
-rw-r--r--editor/icons/icon_override.png (renamed from tools/editor/icons/icon_override.png)bin281 -> 281 bytes
-rw-r--r--editor/icons/icon_p_hash_translation.png (renamed from tools/editor/icons/icon_p_hash_translation.png)bin194 -> 194 bytes
-rw-r--r--editor/icons/icon_packed_data_container.png (renamed from tools/editor/icons/icon_packed_data_container.png)bin176 -> 176 bytes
-rw-r--r--editor/icons/icon_packed_scene.png (renamed from tools/editor/icons/icon_packed_scene.png)bin289 -> 289 bytes
-rw-r--r--editor/icons/icon_pane_drag.png (renamed from tools/editor/icons/icon_pane_drag.png)bin620 -> 620 bytes
-rw-r--r--editor/icons/icon_pane_drag_hover.png (renamed from tools/editor/icons/icon_pane_drag_hover.png)bin637 -> 637 bytes
-rw-r--r--editor/icons/icon_panel.png (renamed from tools/editor/icons/icon_panel.png)bin175 -> 175 bytes
-rw-r--r--editor/icons/icon_panel_container.png (renamed from tools/editor/icons/icon_panel_container.png)bin198 -> 198 bytes
-rw-r--r--editor/icons/icon_panel_top.png (renamed from tools/editor/icons/icon_panel_top.png)bin195 -> 195 bytes
-rw-r--r--editor/icons/icon_panels_1.png (renamed from tools/editor/icons/icon_panels_1.png)bin100 -> 100 bytes
-rw-r--r--editor/icons/icon_panels_2.png (renamed from tools/editor/icons/icon_panels_2.png)bin108 -> 108 bytes
-rw-r--r--editor/icons/icon_panels_2_alt.png (renamed from tools/editor/icons/icon_panels_2_alt.png)bin116 -> 116 bytes
-rw-r--r--editor/icons/icon_panels_3.png (renamed from tools/editor/icons/icon_panels_3.png)bin123 -> 123 bytes
-rw-r--r--editor/icons/icon_panels_3_alt.png (renamed from tools/editor/icons/icon_panels_3_alt.png)bin130 -> 130 bytes
-rw-r--r--editor/icons/icon_panels_4.png (renamed from tools/editor/icons/icon_panels_4.png)bin120 -> 120 bytes
-rw-r--r--editor/icons/icon_parallax_background.png (renamed from tools/editor/icons/icon_parallax_background.png)bin218 -> 218 bytes
-rw-r--r--editor/icons/icon_parallax_layer.png (renamed from tools/editor/icons/icon_parallax_layer.png)bin282 -> 282 bytes
-rw-r--r--editor/icons/icon_particle_attractor_2d.png (renamed from tools/editor/icons/icon_particle_attractor_2d.png)bin629 -> 629 bytes
-rw-r--r--editor/icons/icon_particles.png (renamed from tools/editor/icons/icon_particles.png)bin370 -> 370 bytes
-rw-r--r--editor/icons/icon_particles_2d.png (renamed from tools/editor/icons/icon_particles_2d.png)bin391 -> 391 bytes
-rw-r--r--editor/icons/icon_particles_frame.png (renamed from tools/editor/icons/icon_particles_frame.png)bin254 -> 254 bytes
-rw-r--r--editor/icons/icon_particles_shader.png (renamed from tools/editor/icons/icon_particles_shader.png)bin367 -> 367 bytes
-rw-r--r--editor/icons/icon_patch_9_rect.png (renamed from tools/editor/icons/icon_patch_9_rect.png)bin128 -> 128 bytes
-rw-r--r--editor/icons/icon_path.png (renamed from tools/editor/icons/icon_path.png)bin353 -> 353 bytes
-rw-r--r--editor/icons/icon_path_2d.png (renamed from tools/editor/icons/icon_path_2d.png)bin359 -> 359 bytes
-rw-r--r--editor/icons/icon_path_follow.png (renamed from tools/editor/icons/icon_path_follow.png)bin387 -> 387 bytes
-rw-r--r--editor/icons/icon_path_follow_2d.png (renamed from tools/editor/icons/icon_path_follow_2d.png)bin392 -> 392 bytes
-rw-r--r--editor/icons/icon_pause.png (renamed from tools/editor/icons/icon_pause.png)bin147 -> 147 bytes
-rw-r--r--editor/icons/icon_pe_edit.png (renamed from tools/editor/icons/icon_pe_edit.png)bin403 -> 403 bytes
-rw-r--r--editor/icons/icon_physics_joint_pin.png (renamed from tools/editor/icons/icon_physics_joint_pin.png)bin454 -> 454 bytes
-rw-r--r--editor/icons/icon_pin.png (renamed from tools/editor/icons/icon_pin.png)bin227 -> 227 bytes
-rw-r--r--editor/icons/icon_pin_joint.png (renamed from tools/editor/icons/icon_pin_joint.png)bin418 -> 418 bytes
-rw-r--r--editor/icons/icon_pin_joint_2d.png (renamed from tools/editor/icons/icon_pin_joint_2d.png)bin428 -> 428 bytes
-rw-r--r--editor/icons/icon_pin_pressed.png (renamed from tools/editor/icons/icon_pin_pressed.png)bin227 -> 227 bytes
-rw-r--r--editor/icons/icon_plane.png (renamed from tools/editor/icons/icon_plane.png)bin235 -> 235 bytes
-rw-r--r--editor/icons/icon_plane_shape.png (renamed from tools/editor/icons/icon_plane_shape.png)bin229 -> 229 bytes
-rw-r--r--editor/icons/icon_play.png (renamed from tools/editor/icons/icon_play.png)bin237 -> 237 bytes
-rw-r--r--editor/icons/icon_play_backwards.png (renamed from tools/editor/icons/icon_play_backwards.png)bin245 -> 245 bytes
-rw-r--r--editor/icons/icon_play_custom.png (renamed from tools/editor/icons/icon_play_custom.png)bin282 -> 282 bytes
-rw-r--r--editor/icons/icon_play_scene.png (renamed from tools/editor/icons/icon_play_scene.png)bin350 -> 350 bytes
-rw-r--r--editor/icons/icon_play_start.png (renamed from tools/editor/icons/icon_play_start.png)bin269 -> 269 bytes
-rw-r--r--editor/icons/icon_play_start_backwards.png (renamed from tools/editor/icons/icon_play_start_backwards.png)bin279 -> 279 bytes
-rw-r--r--editor/icons/icon_polygon_2d.png (renamed from tools/editor/icons/icon_polygon_2d.png)bin281 -> 281 bytes
-rw-r--r--editor/icons/icon_polygon_path_finder.png (renamed from tools/editor/icons/icon_polygon_path_finder.png)bin307 -> 307 bytes
-rw-r--r--editor/icons/icon_popup.png (renamed from tools/editor/icons/icon_popup.png)bin210 -> 210 bytes
-rw-r--r--editor/icons/icon_popup_dialog.png (renamed from tools/editor/icons/icon_popup_dialog.png)bin221 -> 221 bytes
-rw-r--r--editor/icons/icon_popup_menu.png (renamed from tools/editor/icons/icon_popup_menu.png)bin216 -> 216 bytes
-rw-r--r--editor/icons/icon_popup_panel.png (renamed from tools/editor/icons/icon_popup_panel.png)bin198 -> 198 bytes
-rw-r--r--editor/icons/icon_portal.png (renamed from tools/editor/icons/icon_portal.png)bin452 -> 452 bytes
-rw-r--r--editor/icons/icon_position_2d.png (renamed from tools/editor/icons/icon_position_2d.png)bin132 -> 132 bytes
-rw-r--r--editor/icons/icon_position_3d.png (renamed from tools/editor/icons/icon_position_3d.png)bin131 -> 131 bytes
-rw-r--r--editor/icons/icon_prev_scene.png (renamed from tools/editor/icons/icon_prev_scene.png)bin229 -> 229 bytes
-rw-r--r--editor/icons/icon_progress_1.png (renamed from tools/editor/icons/icon_progress_1.png)bin468 -> 468 bytes
-rw-r--r--editor/icons/icon_progress_2.png (renamed from tools/editor/icons/icon_progress_2.png)bin455 -> 455 bytes
-rw-r--r--editor/icons/icon_progress_3.png (renamed from tools/editor/icons/icon_progress_3.png)bin462 -> 462 bytes
-rw-r--r--editor/icons/icon_progress_4.png (renamed from tools/editor/icons/icon_progress_4.png)bin475 -> 475 bytes
-rw-r--r--editor/icons/icon_progress_5.png (renamed from tools/editor/icons/icon_progress_5.png)bin454 -> 454 bytes
-rw-r--r--editor/icons/icon_progress_6.png (renamed from tools/editor/icons/icon_progress_6.png)bin465 -> 465 bytes
-rw-r--r--editor/icons/icon_progress_7.png (renamed from tools/editor/icons/icon_progress_7.png)bin461 -> 461 bytes
-rw-r--r--editor/icons/icon_progress_8.png (renamed from tools/editor/icons/icon_progress_8.png)bin463 -> 463 bytes
-rw-r--r--editor/icons/icon_progress_bar.png (renamed from tools/editor/icons/icon_progress_bar.png)bin208 -> 208 bytes
-rw-r--r--editor/icons/icon_property_editor.png (renamed from tools/editor/icons/icon_property_editor.png)bin248 -> 248 bytes
-rw-r--r--editor/icons/icon_proximity_group.png (renamed from tools/editor/icons/icon_proximity_group.png)bin223 -> 223 bytes
-rw-r--r--editor/icons/icon_quad.png (renamed from tools/editor/icons/icon_quad.png)bin251 -> 251 bytes
-rw-r--r--editor/icons/icon_quat.png (renamed from tools/editor/icons/icon_quat.png)bin341 -> 341 bytes
-rw-r--r--editor/icons/icon_range.png (renamed from tools/editor/icons/icon_range.png)bin151 -> 151 bytes
-rw-r--r--editor/icons/icon_rating_no_star.png (renamed from tools/editor/icons/icon_rating_no_star.png)bin515 -> 515 bytes
-rw-r--r--editor/icons/icon_rating_star.png (renamed from tools/editor/icons/icon_rating_star.png)bin383 -> 383 bytes
-rw-r--r--editor/icons/icon_ray_cast.png (renamed from tools/editor/icons/icon_ray_cast.png)bin216 -> 216 bytes
-rw-r--r--editor/icons/icon_ray_cast_2d.png (renamed from tools/editor/icons/icon_ray_cast_2d.png)bin214 -> 214 bytes
-rw-r--r--editor/icons/icon_ray_shape.png (renamed from tools/editor/icons/icon_ray_shape.png)bin363 -> 363 bytes
-rw-r--r--editor/icons/icon_ray_shape_2d.png (renamed from tools/editor/icons/icon_ray_shape_2d.png)bin233 -> 233 bytes
-rw-r--r--editor/icons/icon_rayito.png (renamed from tools/editor/icons/icon_rayito.png)bin300 -> 300 bytes
-rw-r--r--editor/icons/icon_real.png (renamed from tools/editor/icons/icon_real.png)bin265 -> 265 bytes
-rw-r--r--editor/icons/icon_rect2.png (renamed from tools/editor/icons/icon_rect2.png)bin193 -> 193 bytes
-rw-r--r--editor/icons/icon_rect3.png (renamed from tools/editor/icons/icon_rect3.png)bin202 -> 202 bytes
-rw-r--r--editor/icons/icon_rectangle_shape_2d.png (renamed from tools/editor/icons/icon_rectangle_shape_2d.png)bin159 -> 159 bytes
-rw-r--r--editor/icons/icon_reference_rect.png (renamed from tools/editor/icons/icon_reference_rect.png)bin128 -> 128 bytes
-rw-r--r--editor/icons/icon_reflection_probe.png (renamed from tools/editor/icons/icon_reflection_probe.png)bin370 -> 370 bytes
-rw-r--r--editor/icons/icon_region_edit.png (renamed from tools/editor/icons/icon_region_edit.png)bin141 -> 141 bytes
-rw-r--r--editor/icons/icon_reload.png (renamed from tools/editor/icons/icon_reload.png)bin420 -> 420 bytes
-rw-r--r--editor/icons/icon_reload_empty.png (renamed from tools/editor/icons/icon_reload_empty.png)bin251 -> 251 bytes
-rw-r--r--editor/icons/icon_reload_small.png (renamed from tools/editor/icons/icon_reload_small.png)bin409 -> 409 bytes
-rw-r--r--editor/icons/icon_remote.png (renamed from tools/editor/icons/icon_remote.png)bin394 -> 394 bytes
-rw-r--r--editor/icons/icon_remote_transform.png (renamed from tools/editor/icons/icon_remote_transform.png)bin530 -> 530 bytes
-rw-r--r--editor/icons/icon_remote_transform_2d.png (renamed from tools/editor/icons/icon_remote_transform_2d.png)bin552 -> 552 bytes
-rw-r--r--editor/icons/icon_remove.png (renamed from tools/editor/icons/icon_remove.png)bin184 -> 184 bytes
-rw-r--r--editor/icons/icon_remove_hl.png (renamed from tools/editor/icons/icon_remove_hl.png)bin385 -> 385 bytes
-rw-r--r--editor/icons/icon_remove_small.png (renamed from tools/editor/icons/icon_remove_small.png)bin297 -> 297 bytes
-rw-r--r--editor/icons/icon_rename.png (renamed from tools/editor/icons/icon_rename.png)bin160 -> 160 bytes
-rw-r--r--editor/icons/icon_reparent.png (renamed from tools/editor/icons/icon_reparent.png)bin390 -> 390 bytes
-rw-r--r--editor/icons/icon_replace.png (renamed from tools/editor/icons/icon_replace.png)bin435 -> 435 bytes
-rw-r--r--editor/icons/icon_resource_preloader.png (renamed from tools/editor/icons/icon_resource_preloader.png)bin391 -> 391 bytes
-rw-r--r--editor/icons/icon_rich_text_label.png (renamed from tools/editor/icons/icon_rich_text_label.png)bin236 -> 236 bytes
-rw-r--r--editor/icons/icon_rid.png (renamed from tools/editor/icons/icon_rid.png)bin468 -> 468 bytes
-rw-r--r--editor/icons/icon_rigid_body.png (renamed from tools/editor/icons/icon_rigid_body.png)bin531 -> 531 bytes
-rw-r--r--editor/icons/icon_rigid_body_2_d.png (renamed from tools/editor/icons/icon_rigid_body_2_d.png)bin501 -> 501 bytes
-rw-r--r--editor/icons/icon_rigid_body_2d.png (renamed from tools/editor/icons/icon_rigid_body_2d.png)bin559 -> 559 bytes
-rw-r--r--editor/icons/icon_room.png (renamed from tools/editor/icons/icon_room.png)bin375 -> 375 bytes
-rw-r--r--editor/icons/icon_room_bounds.png (renamed from tools/editor/icons/icon_room_bounds.png)bin363 -> 363 bytes
-rw-r--r--editor/icons/icon_room_instance.png (renamed from tools/editor/icons/icon_room_instance.png)bin392 -> 392 bytes
-rw-r--r--editor/icons/icon_rotate_0.png (renamed from tools/editor/icons/icon_rotate_0.png)bin436 -> 436 bytes
-rw-r--r--editor/icons/icon_rotate_180.png (renamed from tools/editor/icons/icon_rotate_180.png)bin376 -> 376 bytes
-rw-r--r--editor/icons/icon_rotate_270.png (renamed from tools/editor/icons/icon_rotate_270.png)bin357 -> 357 bytes
-rw-r--r--editor/icons/icon_rotate_90.png (renamed from tools/editor/icons/icon_rotate_90.png)bin412 -> 412 bytes
-rw-r--r--editor/icons/icon_run.png (renamed from tools/editor/icons/icon_run.png)bin800 -> 800 bytes
-rw-r--r--editor/icons/icon_s_s_a_o_f_x.png (renamed from tools/editor/icons/icon_s_s_a_o_f_x.png)bin564 -> 564 bytes
-rw-r--r--editor/icons/icon_sample.png (renamed from tools/editor/icons/icon_sample.png)bin152 -> 152 bytes
-rw-r--r--editor/icons/icon_sample_library.png (renamed from tools/editor/icons/icon_sample_library.png)bin333 -> 333 bytes
-rw-r--r--editor/icons/icon_sample_player.png (renamed from tools/editor/icons/icon_sample_player.png)bin234 -> 234 bytes
-rw-r--r--editor/icons/icon_sample_player_2d.png (renamed from tools/editor/icons/icon_sample_player_2d.png)bin252 -> 252 bytes
-rw-r--r--editor/icons/icon_save.png (renamed from tools/editor/icons/icon_save.png)bin252 -> 252 bytes
-rw-r--r--editor/icons/icon_scene.png (renamed from tools/editor/icons/icon_scene.png)bin476 -> 476 bytes
-rw-r--r--editor/icons/icon_scene_instance.png (renamed from tools/editor/icons/icon_scene_instance.png)bin488 -> 488 bytes
-rw-r--r--editor/icons/icon_scene_tree_editor.png (renamed from tools/editor/icons/icon_scene_tree_editor.png)bin294 -> 294 bytes
-rw-r--r--editor/icons/icon_script.png (renamed from tools/editor/icons/icon_script.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/icon_script_control.png (renamed from tools/editor/icons/icon_script_control.png)bin452 -> 452 bytes
-rw-r--r--editor/icons/icon_script_create.png (renamed from tools/editor/icons/icon_script_create.png)bin288 -> 288 bytes
-rw-r--r--editor/icons/icon_script_error.png (renamed from tools/editor/icons/icon_script_error.png)bin220 -> 220 bytes
-rw-r--r--editor/icons/icon_script_list.png (renamed from tools/editor/icons/icon_script_list.png)bin213 -> 213 bytes
-rw-r--r--editor/icons/icon_script_node.png (renamed from tools/editor/icons/icon_script_node.png)bin455 -> 455 bytes
-rw-r--r--editor/icons/icon_script_remove.png (renamed from tools/editor/icons/icon_script_remove.png)bin411 -> 411 bytes
-rw-r--r--editor/icons/icon_scroll_bar.png (renamed from tools/editor/icons/icon_scroll_bar.png)bin205 -> 205 bytes
-rw-r--r--editor/icons/icon_scroll_container.png (renamed from tools/editor/icons/icon_scroll_container.png)bin304 -> 304 bytes
-rw-r--r--editor/icons/icon_segment_shape_2d.png (renamed from tools/editor/icons/icon_segment_shape_2d.png)bin241 -> 241 bytes
-rw-r--r--editor/icons/icon_shader.png (renamed from tools/editor/icons/icon_shader.png)bin254 -> 254 bytes
-rw-r--r--editor/icons/icon_shader_material.png (renamed from tools/editor/icons/icon_shader_material.png)bin254 -> 254 bytes
-rw-r--r--editor/icons/icon_short_cut.png (renamed from tools/editor/icons/icon_short_cut.png)bin272 -> 272 bytes
-rw-r--r--editor/icons/icon_signal.png (renamed from tools/editor/icons/icon_signal.png)bin246 -> 246 bytes
-rw-r--r--editor/icons/icon_skeleton.png (renamed from tools/editor/icons/icon_skeleton.png)bin346 -> 346 bytes
-rw-r--r--editor/icons/icon_skeletonr.png (renamed from tools/editor/icons/icon_skeletonr.png)bin362 -> 362 bytes
-rw-r--r--editor/icons/icon_sky_box_f_x.png (renamed from tools/editor/icons/icon_sky_box_f_x.png)bin740 -> 740 bytes
-rw-r--r--editor/icons/icon_slider_joint.png (renamed from tools/editor/icons/icon_slider_joint.png)bin150 -> 150 bytes
-rw-r--r--editor/icons/icon_slot.png (renamed from tools/editor/icons/icon_slot.png)bin246 -> 246 bytes
-rw-r--r--editor/icons/icon_small_next.png (renamed from tools/editor/icons/icon_small_next.png)bin191 -> 191 bytes
-rw-r--r--editor/icons/icon_snap.png (renamed from tools/editor/icons/icon_snap.png)bin269 -> 269 bytes
-rw-r--r--editor/icons/icon_sound_room_params.png (renamed from tools/editor/icons/icon_sound_room_params.png)bin248 -> 248 bytes
-rw-r--r--editor/icons/icon_spatial.png (renamed from tools/editor/icons/icon_spatial.png)bin419 -> 419 bytes
-rw-r--r--editor/icons/icon_spatial_add.png (renamed from tools/editor/icons/icon_spatial_add.png)bin429 -> 429 bytes
-rw-r--r--editor/icons/icon_spatial_sample_player.png (renamed from tools/editor/icons/icon_spatial_sample_player.png)bin239 -> 239 bytes
-rw-r--r--editor/icons/icon_spatial_shader.png (renamed from tools/editor/icons/icon_spatial_shader.png)bin483 -> 483 bytes
-rw-r--r--editor/icons/icon_spatial_stream_player.png (renamed from tools/editor/icons/icon_spatial_stream_player.png)bin183 -> 183 bytes
-rw-r--r--editor/icons/icon_sphere_shape.png (renamed from tools/editor/icons/icon_sphere_shape.png)bin362 -> 362 bytes
-rw-r--r--editor/icons/icon_spin_box.png (renamed from tools/editor/icons/icon_spin_box.png)bin289 -> 289 bytes
-rw-r--r--editor/icons/icon_spline.png (renamed from tools/editor/icons/icon_spline.png)bin244 -> 244 bytes
-rw-r--r--editor/icons/icon_spot_light.png (renamed from tools/editor/icons/icon_spot_light.png)bin341 -> 341 bytes
-rw-r--r--editor/icons/icon_sprite.png (renamed from tools/editor/icons/icon_sprite.png)bin419 -> 419 bytes
-rw-r--r--editor/icons/icon_sprite_3d.png (renamed from tools/editor/icons/icon_sprite_3d.png)bin408 -> 408 bytes
-rw-r--r--editor/icons/icon_sprite_frames.png (renamed from tools/editor/icons/icon_sprite_frames.png)bin332 -> 332 bytes
-rw-r--r--editor/icons/icon_squirrel_script.png (renamed from tools/editor/icons/icon_squirrel_script.png)bin283 -> 283 bytes
-rw-r--r--editor/icons/icon_static_body.png (renamed from tools/editor/icons/icon_static_body.png)bin229 -> 229 bytes
-rw-r--r--editor/icons/icon_static_body_2_d.png (renamed from tools/editor/icons/icon_static_body_2_d.png)bin368 -> 368 bytes
-rw-r--r--editor/icons/icon_static_body_2d.png (renamed from tools/editor/icons/icon_static_body_2d.png)bin237 -> 237 bytes
-rw-r--r--editor/icons/icon_stop.png (renamed from tools/editor/icons/icon_stop.png)bin236 -> 236 bytes
-rw-r--r--editor/icons/icon_stream_player.png (renamed from tools/editor/icons/icon_stream_player.png)bin183 -> 183 bytes
-rw-r--r--editor/icons/icon_string.png (renamed from tools/editor/icons/icon_string.png)bin160 -> 160 bytes
-rw-r--r--editor/icons/icon_style_box_empty.png (renamed from tools/editor/icons/icon_style_box_empty.png)bin333 -> 333 bytes
-rw-r--r--editor/icons/icon_style_box_flat.png (renamed from tools/editor/icons/icon_style_box_flat.png)bin398 -> 398 bytes
-rw-r--r--editor/icons/icon_style_box_texture.png (renamed from tools/editor/icons/icon_style_box_texture.png)bin411 -> 411 bytes
-rw-r--r--editor/icons/icon_surface.png (renamed from tools/editor/icons/icon_surface.png)bin212 -> 212 bytes
-rw-r--r--editor/icons/icon_tab_container.png (renamed from tools/editor/icons/icon_tab_container.png)bin214 -> 214 bytes
-rw-r--r--editor/icons/icon_tab_menu.png (renamed from tools/editor/icons/icon_tab_menu.png)bin251 -> 251 bytes
-rw-r--r--editor/icons/icon_tabs.png (renamed from tools/editor/icons/icon_tabs.png)bin146 -> 146 bytes
-rw-r--r--editor/icons/icon_test_cube.png (renamed from tools/editor/icons/icon_test_cube.png)bin435 -> 435 bytes
-rw-r--r--editor/icons/icon_text_edit.png (renamed from tools/editor/icons/icon_text_edit.png)bin207 -> 207 bytes
-rw-r--r--editor/icons/icon_texture.png (renamed from tools/editor/icons/icon_texture.png)bin200 -> 200 bytes
-rw-r--r--editor/icons/icon_texture_button.png (renamed from tools/editor/icons/icon_texture_button.png)bin159 -> 159 bytes
-rw-r--r--editor/icons/icon_texture_progress.png (renamed from tools/editor/icons/icon_texture_progress.png)bin213 -> 213 bytes
-rw-r--r--editor/icons/icon_texture_rect.png (renamed from tools/editor/icons/icon_texture_rect.png)bin158 -> 158 bytes
-rw-r--r--editor/icons/icon_theme.png (renamed from tools/editor/icons/icon_theme.png)bin451 -> 451 bytes
-rw-r--r--editor/icons/icon_thumbnail_wait.png (renamed from tools/editor/icons/icon_thumbnail_wait.png)bin2616 -> 2616 bytes
-rw-r--r--editor/icons/icon_tile_map.png (renamed from tools/editor/icons/icon_tile_map.png)bin113 -> 113 bytes
-rw-r--r--editor/icons/icon_tile_set.png (renamed from tools/editor/icons/icon_tile_set.png)bin174 -> 174 bytes
-rw-r--r--editor/icons/icon_time.png (renamed from tools/editor/icons/icon_time.png)bin557 -> 557 bytes
-rw-r--r--editor/icons/icon_timer.png (renamed from tools/editor/icons/icon_timer.png)bin447 -> 447 bytes
-rw-r--r--editor/icons/icon_tool_button.png (renamed from tools/editor/icons/icon_tool_button.png)bin263 -> 263 bytes
-rw-r--r--editor/icons/icon_tool_move.png (renamed from tools/editor/icons/icon_tool_move.png)bin217 -> 217 bytes
-rw-r--r--editor/icons/icon_tool_pan.png (renamed from tools/editor/icons/icon_tool_pan.png)bin281 -> 281 bytes
-rw-r--r--editor/icons/icon_tool_rotate.png (renamed from tools/editor/icons/icon_tool_rotate.png)bin420 -> 420 bytes
-rw-r--r--editor/icons/icon_tool_scale.png (renamed from tools/editor/icons/icon_tool_scale.png)bin349 -> 349 bytes
-rw-r--r--editor/icons/icon_tool_select.png (renamed from tools/editor/icons/icon_tool_select.png)bin376 -> 376 bytes
-rw-r--r--editor/icons/icon_tools.png (renamed from tools/editor/icons/icon_tools.png)bin392 -> 392 bytes
-rw-r--r--editor/icons/icon_touch_screen_button.png (renamed from tools/editor/icons/icon_touch_screen_button.png)bin313 -> 313 bytes
-rw-r--r--editor/icons/icon_track_add_key.png (renamed from tools/editor/icons/icon_track_add_key.png)bin113 -> 113 bytes
-rw-r--r--editor/icons/icon_track_add_key_hl.png (renamed from tools/editor/icons/icon_track_add_key_hl.png)bin113 -> 113 bytes
-rw-r--r--editor/icons/icon_track_continuous.png (renamed from tools/editor/icons/icon_track_continuous.png)bin265 -> 265 bytes
-rw-r--r--editor/icons/icon_track_discrete.png (renamed from tools/editor/icons/icon_track_discrete.png)bin125 -> 125 bytes
-rw-r--r--editor/icons/icon_track_method.png (renamed from tools/editor/icons/icon_track_method.png)bin283 -> 283 bytes
-rw-r--r--editor/icons/icon_track_prop.png (renamed from tools/editor/icons/icon_track_prop.png)bin285 -> 285 bytes
-rw-r--r--editor/icons/icon_track_trigger.png (renamed from tools/editor/icons/icon_track_trigger.png)bin158 -> 158 bytes
-rw-r--r--editor/icons/icon_track_value.png (renamed from tools/editor/icons/icon_track_value.png)bin300 -> 300 bytes
-rw-r--r--editor/icons/icon_translation.png (renamed from tools/editor/icons/icon_translation.png)bin194 -> 194 bytes
-rw-r--r--editor/icons/icon_transparent.png (renamed from tools/editor/icons/icon_transparent.png)bin158 -> 158 bytes
-rw-r--r--editor/icons/icon_transpose.png (renamed from tools/editor/icons/icon_transpose.png)bin165 -> 165 bytes
-rw-r--r--editor/icons/icon_tree.png (renamed from tools/editor/icons/icon_tree.png)bin243 -> 243 bytes
-rw-r--r--editor/icons/icon_tween.png (renamed from tools/editor/icons/icon_tween.png)bin248 -> 248 bytes
-rw-r--r--editor/icons/icon_unbone.png (renamed from tools/editor/icons/icon_unbone.png)bin383 -> 383 bytes
-rw-r--r--editor/icons/icon_ungroup.png (renamed from tools/editor/icons/icon_ungroup.png)bin170 -> 170 bytes
-rw-r--r--editor/icons/icon_uninstance.png (renamed from tools/editor/icons/icon_uninstance.png)bin525 -> 525 bytes
-rw-r--r--editor/icons/icon_unlock.png (renamed from tools/editor/icons/icon_unlock.png)bin262 -> 262 bytes
-rw-r--r--editor/icons/icon_up.png (renamed from tools/editor/icons/icon_up.png)bin185 -> 185 bytes
-rw-r--r--editor/icons/icon_updown.png (renamed from tools/editor/icons/icon_updown.png)bin180 -> 180 bytes
-rw-r--r--editor/icons/icon_uv.png (renamed from tools/editor/icons/icon_uv.png)bin282 -> 282 bytes
-rw-r--r--editor/icons/icon_v_box_container.png (renamed from tools/editor/icons/icon_v_box_container.png)bin207 -> 207 bytes
-rw-r--r--editor/icons/icon_v_button_array.png (renamed from tools/editor/icons/icon_v_button_array.png)bin147 -> 147 bytes
-rw-r--r--editor/icons/icon_v_scroll_bar.png (renamed from tools/editor/icons/icon_v_scroll_bar.png)bin218 -> 218 bytes
-rw-r--r--editor/icons/icon_v_separator.png (renamed from tools/editor/icons/icon_v_separator.png)bin130 -> 130 bytes
-rw-r--r--editor/icons/icon_v_slider.png (renamed from tools/editor/icons/icon_v_slider.png)bin231 -> 231 bytes
-rw-r--r--editor/icons/icon_v_split_container.png (renamed from tools/editor/icons/icon_v_split_container.png)bin277 -> 277 bytes
-rw-r--r--editor/icons/icon_variant.png (renamed from tools/editor/icons/icon_variant.png)bin240 -> 240 bytes
-rw-r--r--editor/icons/icon_vector.png (renamed from tools/editor/icons/icon_vector.png)bin208 -> 208 bytes
-rw-r--r--editor/icons/icon_vector2.png (renamed from tools/editor/icons/icon_vector2.png)bin122 -> 122 bytes
-rw-r--r--editor/icons/icon_vehicle_body.png (renamed from tools/editor/icons/icon_vehicle_body.png)bin236 -> 236 bytes
-rw-r--r--editor/icons/icon_vehicle_wheel.png (renamed from tools/editor/icons/icon_vehicle_wheel.png)bin537 -> 537 bytes
-rw-r--r--editor/icons/icon_video_player.png (renamed from tools/editor/icons/icon_video_player.png)bin302 -> 302 bytes
-rw-r--r--editor/icons/icon_video_stream_theora.png (renamed from tools/editor/icons/icon_video_stream_theora.png)bin925 -> 925 bytes
-rw-r--r--editor/icons/icon_view.png (renamed from tools/editor/icons/icon_view.png)bin386 -> 386 bytes
-rw-r--r--editor/icons/icon_viewport.png (renamed from tools/editor/icons/icon_viewport.png)bin198 -> 198 bytes
-rw-r--r--editor/icons/icon_viewport_container.png (renamed from tools/editor/icons/icon_viewport_container.png)bin284 -> 284 bytes
-rw-r--r--editor/icons/icon_viewport_sprite.png (renamed from tools/editor/icons/icon_viewport_sprite.png)bin239 -> 239 bytes
-rw-r--r--editor/icons/icon_viewport_texture.png (renamed from tools/editor/icons/icon_viewport_texture.png)bin227 -> 227 bytes
-rw-r--r--editor/icons/icon_visibility_area.png (renamed from tools/editor/icons/icon_visibility_area.png)bin422 -> 422 bytes
-rw-r--r--editor/icons/icon_visibility_enabler.png (renamed from tools/editor/icons/icon_visibility_enabler.png)bin549 -> 549 bytes
-rw-r--r--editor/icons/icon_visibility_enabler_2d.png (renamed from tools/editor/icons/icon_visibility_enabler_2d.png)bin550 -> 550 bytes
-rw-r--r--editor/icons/icon_visibility_notifier.png (renamed from tools/editor/icons/icon_visibility_notifier.png)bin427 -> 427 bytes
-rw-r--r--editor/icons/icon_visibility_notifier_2d.png (renamed from tools/editor/icons/icon_visibility_notifier_2d.png)bin431 -> 431 bytes
-rw-r--r--editor/icons/icon_visible.png (renamed from tools/editor/icons/icon_visible.png)bin497 -> 497 bytes
-rw-r--r--editor/icons/icon_visual_script.png (renamed from tools/editor/icons/icon_visual_script.png)bin388 -> 388 bytes
-rw-r--r--editor/icons/icon_visual_shader_port.png (renamed from tools/editor/icons/icon_visual_shader_port.png)bin255 -> 255 bytes
-rw-r--r--editor/icons/icon_volume.png (renamed from tools/editor/icons/icon_volume.png)bin295 -> 295 bytes
-rw-r--r--editor/icons/icon_vu_db.png (renamed from tools/editor/icons/icon_vu_db.png)bin1015 -> 1015 bytes
-rw-r--r--editor/icons/icon_vu_empty.png (renamed from tools/editor/icons/icon_vu_empty.png)bin283 -> 283 bytes
-rw-r--r--editor/icons/icon_vu_full.png (renamed from tools/editor/icons/icon_vu_full.png)bin224 -> 224 bytes
-rw-r--r--editor/icons/icon_wait_no_preview.png (renamed from tools/editor/icons/icon_wait_no_preview.png)bin1041 -> 1041 bytes
-rw-r--r--editor/icons/icon_wait_preview_1.png (renamed from tools/editor/icons/icon_wait_preview_1.png)bin1208 -> 1208 bytes
-rw-r--r--editor/icons/icon_wait_preview_2.png (renamed from tools/editor/icons/icon_wait_preview_2.png)bin1270 -> 1270 bytes
-rw-r--r--editor/icons/icon_wait_preview_3.png (renamed from tools/editor/icons/icon_wait_preview_3.png)bin1190 -> 1190 bytes
-rw-r--r--editor/icons/icon_wait_preview_4.png (renamed from tools/editor/icons/icon_wait_preview_4.png)bin1269 -> 1269 bytes
-rw-r--r--editor/icons/icon_wait_preview_5.png (renamed from tools/editor/icons/icon_wait_preview_5.png)bin1191 -> 1191 bytes
-rw-r--r--editor/icons/icon_wait_preview_6.png (renamed from tools/editor/icons/icon_wait_preview_6.png)bin1278 -> 1278 bytes
-rw-r--r--editor/icons/icon_wait_preview_7.png (renamed from tools/editor/icons/icon_wait_preview_7.png)bin1192 -> 1192 bytes
-rw-r--r--editor/icons/icon_wait_preview_8.png (renamed from tools/editor/icons/icon_wait_preview_8.png)bin1341 -> 1341 bytes
-rw-r--r--editor/icons/icon_warning.png (renamed from tools/editor/icons/icon_warning.png)bin120 -> 120 bytes
-rw-r--r--editor/icons/icon_window_dialog.png (renamed from tools/editor/icons/icon_window_dialog.png)bin200 -> 200 bytes
-rw-r--r--editor/icons/icon_world.png (renamed from tools/editor/icons/icon_world.png)bin254 -> 254 bytes
-rw-r--r--editor/icons/icon_world_2d.png (renamed from tools/editor/icons/icon_world_2d.png)bin328 -> 328 bytes
-rw-r--r--editor/icons/icon_world_environment.png (renamed from tools/editor/icons/icon_world_environment.png)bin578 -> 578 bytes
-rw-r--r--editor/icons/icon_y_sort.png (renamed from tools/editor/icons/icon_y_sort.png)bin230 -> 230 bytes
-rw-r--r--editor/icons/icon_zoom.png (renamed from tools/editor/icons/icon_zoom.png)bin404 -> 404 bytes
-rw-r--r--editor/icons/icon_zoom_less.png (renamed from tools/editor/icons/icon_zoom_less.png)bin149 -> 149 bytes
-rw-r--r--editor/icons/icon_zoom_more.png (renamed from tools/editor/icons/icon_zoom_more.png)bin232 -> 232 bytes
-rw-r--r--editor/icons/icon_zoom_reset.png (renamed from tools/editor/icons/icon_zoom_reset.png)bin430 -> 430 bytes
-rw-r--r--editor/icons/source/icon_accept_dialog.svg (renamed from tools/editor/icons/source/icon_accept_dialog.svg)0
-rw-r--r--editor/icons/source/icon_add_track.svg (renamed from tools/editor/icons/source/icon_add_track.svg)0
-rw-r--r--editor/icons/source/icon_anchor.svg (renamed from tools/editor/icons/source/icon_anchor.svg)0
-rw-r--r--editor/icons/source/icon_animated_sprite.svg (renamed from tools/editor/icons/source/icon_animated_sprite.svg)0
-rw-r--r--editor/icons/source/icon_animated_sprite_3d.svg (renamed from tools/editor/icons/source/icon_animated_sprite_3d.svg)0
-rw-r--r--editor/icons/source/icon_animation.svg (renamed from tools/editor/icons/source/icon_animation.svg)0
-rw-r--r--editor/icons/source/icon_animation_player.svg (renamed from tools/editor/icons/source/icon_animation_player.svg)0
-rw-r--r--editor/icons/source/icon_animation_tree_player.svg (renamed from tools/editor/icons/source/icon_animation_tree_player.svg)0
-rw-r--r--editor/icons/source/icon_area.svg (renamed from tools/editor/icons/source/icon_area.svg)0
-rw-r--r--editor/icons/source/icon_area_2d.svg (renamed from tools/editor/icons/source/icon_area_2d.svg)0
-rw-r--r--editor/icons/source/icon_arrow_left.svg (renamed from tools/editor/icons/source/icon_arrow_left.svg)0
-rw-r--r--editor/icons/source/icon_arrow_right.svg (renamed from tools/editor/icons/source/icon_arrow_right.svg)0
-rw-r--r--editor/icons/source/icon_arrow_up.svg (renamed from tools/editor/icons/source/icon_arrow_up.svg)0
-rw-r--r--editor/icons/source/icon_atlas_texture.svg (renamed from tools/editor/icons/source/icon_atlas_texture.svg)0
-rw-r--r--editor/icons/source/icon_audio_stream_gibberish.svg (renamed from tools/editor/icons/source/icon_audio_stream_gibberish.svg)0
-rw-r--r--editor/icons/source/icon_auto_play.svg (renamed from tools/editor/icons/source/icon_auto_play.svg)0
-rw-r--r--editor/icons/source/icon_back.svg (renamed from tools/editor/icons/source/icon_back.svg)0
-rw-r--r--editor/icons/source/icon_back_buffer_copy.svg (renamed from tools/editor/icons/source/icon_back_buffer_copy.svg)0
-rw-r--r--editor/icons/source/icon_bake.svg (renamed from tools/editor/icons/source/icon_bake.svg)0
-rw-r--r--editor/icons/source/icon_baked_light.svg (renamed from tools/editor/icons/source/icon_baked_light.svg)0
-rw-r--r--editor/icons/source/icon_baked_light_instance.svg (renamed from tools/editor/icons/source/icon_baked_light_instance.svg)0
-rw-r--r--editor/icons/source/icon_baked_light_sampler.svg (renamed from tools/editor/icons/source/icon_baked_light_sampler.svg)0
-rw-r--r--editor/icons/source/icon_bit_map.svg (renamed from tools/editor/icons/source/icon_bit_map.svg)0
-rw-r--r--editor/icons/source/icon_bitmap_font.svg (renamed from tools/editor/icons/source/icon_bitmap_font.svg)0
-rw-r--r--editor/icons/source/icon_blend.svg (renamed from tools/editor/icons/source/icon_blend.svg)0
-rw-r--r--editor/icons/source/icon_bone.svg (renamed from tools/editor/icons/source/icon_bone.svg)0
-rw-r--r--editor/icons/source/icon_bone_attachment.svg (renamed from tools/editor/icons/source/icon_bone_attachment.svg)0
-rw-r--r--editor/icons/source/icon_bone_track.svg (renamed from tools/editor/icons/source/icon_bone_track.svg)0
-rw-r--r--editor/icons/source/icon_bool.svg (renamed from tools/editor/icons/source/icon_bool.svg)0
-rw-r--r--editor/icons/source/icon_box_shape.svg (renamed from tools/editor/icons/source/icon_box_shape.svg)0
-rw-r--r--editor/icons/source/icon_button.svg (renamed from tools/editor/icons/source/icon_button.svg)0
-rw-r--r--editor/icons/source/icon_button_group.svg (renamed from tools/editor/icons/source/icon_button_group.svg)0
-rw-r--r--editor/icons/source/icon_camera.svg (renamed from tools/editor/icons/source/icon_camera.svg)0
-rw-r--r--editor/icons/source/icon_camera_2d.svg (renamed from tools/editor/icons/source/icon_camera_2d.svg)0
-rw-r--r--editor/icons/source/icon_canvas_item.svg (renamed from tools/editor/icons/source/icon_canvas_item.svg)0
-rw-r--r--editor/icons/source/icon_canvas_item_material.svg (renamed from tools/editor/icons/source/icon_canvas_item_material.svg)0
-rw-r--r--editor/icons/source/icon_canvas_item_shader.svg (renamed from tools/editor/icons/source/icon_canvas_item_shader.svg)0
-rw-r--r--editor/icons/source/icon_canvas_item_shader_graph.svg (renamed from tools/editor/icons/source/icon_canvas_item_shader_graph.svg)0
-rw-r--r--editor/icons/source/icon_canvas_layer.svg (renamed from tools/editor/icons/source/icon_canvas_layer.svg)0
-rw-r--r--editor/icons/source/icon_canvas_modulate.svg (renamed from tools/editor/icons/source/icon_canvas_modulate.svg)0
-rw-r--r--editor/icons/source/icon_capsule_shape.svg (renamed from tools/editor/icons/source/icon_capsule_shape.svg)0
-rw-r--r--editor/icons/source/icon_capsule_shape_2d.svg (renamed from tools/editor/icons/source/icon_capsule_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_center_container.svg (renamed from tools/editor/icons/source/icon_center_container.svg)0
-rw-r--r--editor/icons/source/icon_check_box.svg (renamed from tools/editor/icons/source/icon_check_box.svg)0
-rw-r--r--editor/icons/source/icon_check_button.svg (renamed from tools/editor/icons/source/icon_check_button.svg)0
-rw-r--r--editor/icons/source/icon_circle_shape_2d.svg (renamed from tools/editor/icons/source/icon_circle_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_class_list.svg (renamed from tools/editor/icons/source/icon_class_list.svg)0
-rw-r--r--editor/icons/source/icon_close.svg (renamed from tools/editor/icons/source/icon_close.svg)0
-rw-r--r--editor/icons/source/icon_collapse.svg (renamed from tools/editor/icons/source/icon_collapse.svg)0
-rw-r--r--editor/icons/source/icon_collision_2d.svg (renamed from tools/editor/icons/source/icon_collision_2d.svg)0
-rw-r--r--editor/icons/source/icon_collision_polygon.svg (renamed from tools/editor/icons/source/icon_collision_polygon.svg)0
-rw-r--r--editor/icons/source/icon_collision_shape.svg (renamed from tools/editor/icons/source/icon_collision_shape.svg)0
-rw-r--r--editor/icons/source/icon_collision_shape_2d.svg (renamed from tools/editor/icons/source/icon_collision_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_color.svg (renamed from tools/editor/icons/source/icon_color.svg)0
-rw-r--r--editor/icons/source/icon_color_pick.svg (renamed from tools/editor/icons/source/icon_color_pick.svg)0
-rw-r--r--editor/icons/source/icon_color_picker.svg (renamed from tools/editor/icons/source/icon_color_picker.svg)0
-rw-r--r--editor/icons/source/icon_color_picker_button.svg (renamed from tools/editor/icons/source/icon_color_picker_button.svg)0
-rw-r--r--editor/icons/source/icon_color_ramp.svg (renamed from tools/editor/icons/source/icon_color_ramp.svg)0
-rw-r--r--editor/icons/source/icon_color_rect.svg (renamed from tools/editor/icons/source/icon_color_rect.svg)0
-rw-r--r--editor/icons/source/icon_concave_polygon_shape.svg (renamed from tools/editor/icons/source/icon_concave_polygon_shape.svg)0
-rw-r--r--editor/icons/source/icon_concave_polygon_shape_2d.svg (renamed from tools/editor/icons/source/icon_concave_polygon_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_cone_twist_joint.svg (renamed from tools/editor/icons/source/icon_cone_twist_joint.svg)0
-rw-r--r--editor/icons/source/icon_confirmation_dialog.svg (renamed from tools/editor/icons/source/icon_confirmation_dialog.svg)0
-rw-r--r--editor/icons/source/icon_connect.svg (renamed from tools/editor/icons/source/icon_connect.svg)0
-rw-r--r--editor/icons/source/icon_connection_and_groups.svg (renamed from tools/editor/icons/source/icon_connection_and_groups.svg)0
-rw-r--r--editor/icons/source/icon_container.svg (renamed from tools/editor/icons/source/icon_container.svg)0
-rw-r--r--editor/icons/source/icon_control.svg (renamed from tools/editor/icons/source/icon_control.svg)0
-rw-r--r--editor/icons/source/icon_control_align_bottom_center.svg (renamed from tools/editor/icons/source/icon_control_align_bottom_center.svg)0
-rw-r--r--editor/icons/source/icon_control_align_bottom_left.svg (renamed from tools/editor/icons/source/icon_control_align_bottom_left.svg)0
-rw-r--r--editor/icons/source/icon_control_align_bottom_right.svg (renamed from tools/editor/icons/source/icon_control_align_bottom_right.svg)0
-rw-r--r--editor/icons/source/icon_control_align_bottom_wide.svg (renamed from tools/editor/icons/source/icon_control_align_bottom_wide.svg)0
-rw-r--r--editor/icons/source/icon_control_align_center.svg (renamed from tools/editor/icons/source/icon_control_align_center.svg)0
-rw-r--r--editor/icons/source/icon_control_align_center_left.svg (renamed from tools/editor/icons/source/icon_control_align_center_left.svg)0
-rw-r--r--editor/icons/source/icon_control_align_center_right.svg (renamed from tools/editor/icons/source/icon_control_align_center_right.svg)0
-rw-r--r--editor/icons/source/icon_control_align_left_center.svg (renamed from tools/editor/icons/source/icon_control_align_left_center.svg)0
-rw-r--r--editor/icons/source/icon_control_align_left_wide.svg (renamed from tools/editor/icons/source/icon_control_align_left_wide.svg)0
-rw-r--r--editor/icons/source/icon_control_align_right_center.svg (renamed from tools/editor/icons/source/icon_control_align_right_center.svg)0
-rw-r--r--editor/icons/source/icon_control_align_right_wide.svg (renamed from tools/editor/icons/source/icon_control_align_right_wide.svg)0
-rw-r--r--editor/icons/source/icon_control_align_top_center.svg (renamed from tools/editor/icons/source/icon_control_align_top_center.svg)0
-rw-r--r--editor/icons/source/icon_control_align_top_left.svg (renamed from tools/editor/icons/source/icon_control_align_top_left.svg)0
-rw-r--r--editor/icons/source/icon_control_align_top_right.svg (renamed from tools/editor/icons/source/icon_control_align_top_right.svg)0
-rw-r--r--editor/icons/source/icon_control_align_top_wide.svg (renamed from tools/editor/icons/source/icon_control_align_top_wide.svg)0
-rw-r--r--editor/icons/source/icon_control_align_wide.svg (renamed from tools/editor/icons/source/icon_control_align_wide.svg)0
-rw-r--r--editor/icons/source/icon_control_hcenter_wide.svg (renamed from tools/editor/icons/source/icon_control_hcenter_wide.svg)0
-rw-r--r--editor/icons/source/icon_control_vcenter_wide.svg (renamed from tools/editor/icons/source/icon_control_vcenter_wide.svg)0
-rw-r--r--editor/icons/source/icon_convex_polygon_shape.svg (renamed from tools/editor/icons/source/icon_convex_polygon_shape.svg)0
-rw-r--r--editor/icons/source/icon_convex_polygon_shape_2d.svg (renamed from tools/editor/icons/source/icon_convex_polygon_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_copy_node_path.svg (renamed from tools/editor/icons/source/icon_copy_node_path.svg)0
-rw-r--r--editor/icons/source/icon_create_new_scene_from.svg (renamed from tools/editor/icons/source/icon_create_new_scene_from.svg)0
-rw-r--r--editor/icons/source/icon_cube_map.svg (renamed from tools/editor/icons/source/icon_cube_map.svg)0
-rw-r--r--editor/icons/source/icon_curve_2d.svg (renamed from tools/editor/icons/source/icon_curve_2d.svg)0
-rw-r--r--editor/icons/source/icon_curve_3d.svg (renamed from tools/editor/icons/source/icon_curve_3d.svg)0
-rw-r--r--editor/icons/source/icon_curve_close.svg (renamed from tools/editor/icons/source/icon_curve_close.svg)0
-rw-r--r--editor/icons/source/icon_curve_constant.svg (renamed from tools/editor/icons/source/icon_curve_constant.svg)0
-rw-r--r--editor/icons/source/icon_curve_create.svg (renamed from tools/editor/icons/source/icon_curve_create.svg)0
-rw-r--r--editor/icons/source/icon_curve_curve.svg (renamed from tools/editor/icons/source/icon_curve_curve.svg)0
-rw-r--r--editor/icons/source/icon_curve_delete.svg (renamed from tools/editor/icons/source/icon_curve_delete.svg)0
-rw-r--r--editor/icons/source/icon_curve_edit.svg (renamed from tools/editor/icons/source/icon_curve_edit.svg)0
-rw-r--r--editor/icons/source/icon_curve_in.svg (renamed from tools/editor/icons/source/icon_curve_in.svg)0
-rw-r--r--editor/icons/source/icon_curve_in_out.svg (renamed from tools/editor/icons/source/icon_curve_in_out.svg)0
-rw-r--r--editor/icons/source/icon_curve_linear.svg (renamed from tools/editor/icons/source/icon_curve_linear.svg)0
-rw-r--r--editor/icons/source/icon_curve_out.svg (renamed from tools/editor/icons/source/icon_curve_out.svg)0
-rw-r--r--editor/icons/source/icon_curve_out_in.svg (renamed from tools/editor/icons/source/icon_curve_out_in.svg)0
-rw-r--r--editor/icons/source/icon_damped_spring_joint_2d.svg (renamed from tools/editor/icons/source/icon_damped_spring_joint_2d.svg)0
-rw-r--r--editor/icons/source/icon_debug_continue.svg (renamed from tools/editor/icons/source/icon_debug_continue.svg)0
-rw-r--r--editor/icons/source/icon_debug_next.svg (renamed from tools/editor/icons/source/icon_debug_next.svg)0
-rw-r--r--editor/icons/source/icon_debug_step.svg (renamed from tools/editor/icons/source/icon_debug_step.svg)0
-rw-r--r--editor/icons/source/icon_dependency_changed.svg (renamed from tools/editor/icons/source/icon_dependency_changed.svg)0
-rw-r--r--editor/icons/source/icon_dependency_changed_hl.svg (renamed from tools/editor/icons/source/icon_dependency_changed_hl.svg)0
-rw-r--r--editor/icons/source/icon_dependency_local_changed.svg (renamed from tools/editor/icons/source/icon_dependency_local_changed.svg)0
-rw-r--r--editor/icons/source/icon_dependency_local_changed_hl.svg (renamed from tools/editor/icons/source/icon_dependency_local_changed_hl.svg)0
-rw-r--r--editor/icons/source/icon_dependency_ok.svg (renamed from tools/editor/icons/source/icon_dependency_ok.svg)0
-rw-r--r--editor/icons/source/icon_dependency_ok_hl.svg (renamed from tools/editor/icons/source/icon_dependency_ok_hl.svg)0
-rw-r--r--editor/icons/source/icon_directional_light.svg (renamed from tools/editor/icons/source/icon_directional_light.svg)0
-rw-r--r--editor/icons/source/icon_distraction_free.svg (renamed from tools/editor/icons/source/icon_distraction_free.svg)0
-rw-r--r--editor/icons/source/icon_duplicate.svg (renamed from tools/editor/icons/source/icon_duplicate.svg)0
-rw-r--r--editor/icons/source/icon_dynamic_font.svg (renamed from tools/editor/icons/source/icon_dynamic_font.svg)0
-rw-r--r--editor/icons/source/icon_dynamic_font_data.svg (renamed from tools/editor/icons/source/icon_dynamic_font_data.svg)0
-rw-r--r--editor/icons/source/icon_edit.svg (renamed from tools/editor/icons/source/icon_edit.svg)0
-rw-r--r--editor/icons/source/icon_edit_key.svg (renamed from tools/editor/icons/source/icon_edit_key.svg)0
-rw-r--r--editor/icons/source/icon_edit_pivot.svg (renamed from tools/editor/icons/source/icon_edit_pivot.svg)0
-rw-r--r--editor/icons/source/icon_edit_resource.svg (renamed from tools/editor/icons/source/icon_edit_resource.svg)0
-rw-r--r--editor/icons/source/icon_editor_3d_handle.svg (renamed from tools/editor/icons/source/icon_editor_3d_handle.svg)0
-rw-r--r--editor/icons/source/icon_editor_handle.svg (renamed from tools/editor/icons/source/icon_editor_handle.svg)0
-rw-r--r--editor/icons/source/icon_editor_pivot.svg (renamed from tools/editor/icons/source/icon_editor_pivot.svg)0
-rw-r--r--editor/icons/source/icon_editor_plugin.svg (renamed from tools/editor/icons/source/icon_editor_plugin.svg)0
-rw-r--r--editor/icons/source/icon_environment.svg (renamed from tools/editor/icons/source/icon_environment.svg)0
-rw-r--r--editor/icons/source/icon_error.svg (renamed from tools/editor/icons/source/icon_error.svg)0
-rw-r--r--editor/icons/source/icon_error_sign.svg (renamed from tools/editor/icons/source/icon_error_sign.svg)0
-rw-r--r--editor/icons/source/icon_event_player.svg (renamed from tools/editor/icons/source/icon_event_player.svg)0
-rw-r--r--editor/icons/source/icon_favorites.svg (renamed from tools/editor/icons/source/icon_favorites.svg)0
-rw-r--r--editor/icons/source/icon_file_big.svg (renamed from tools/editor/icons/source/icon_file_big.svg)0
-rw-r--r--editor/icons/source/icon_file_dialog.svg (renamed from tools/editor/icons/source/icon_file_dialog.svg)0
-rw-r--r--editor/icons/source/icon_file_list.svg (renamed from tools/editor/icons/source/icon_file_list.svg)0
-rw-r--r--editor/icons/source/icon_file_server.svg (renamed from tools/editor/icons/source/icon_file_server.svg)0
-rw-r--r--editor/icons/source/icon_file_server_active.svg (renamed from tools/editor/icons/source/icon_file_server_active.svg)0
-rw-r--r--editor/icons/source/icon_file_thumbnail.svg (renamed from tools/editor/icons/source/icon_file_thumbnail.svg)0
-rw-r--r--editor/icons/source/icon_fixed_material.svg (renamed from tools/editor/icons/source/icon_fixed_material.svg)0
-rw-r--r--editor/icons/source/icon_fixed_spatial_material.svg (renamed from tools/editor/icons/source/icon_fixed_spatial_material.svg)0
-rw-r--r--editor/icons/source/icon_folder.svg (renamed from tools/editor/icons/source/icon_folder.svg)0
-rw-r--r--editor/icons/source/icon_folder_big.svg (renamed from tools/editor/icons/source/icon_folder_big.svg)0
-rw-r--r--editor/icons/source/icon_font.svg (renamed from tools/editor/icons/source/icon_font.svg)0
-rw-r--r--editor/icons/source/icon_forward.svg (renamed from tools/editor/icons/source/icon_forward.svg)0
-rw-r--r--editor/icons/source/icon_g_d_script.svg (renamed from tools/editor/icons/source/icon_g_d_script.svg)0
-rw-r--r--editor/icons/source/icon_g_i_probe.svg (renamed from tools/editor/icons/source/icon_g_i_probe.svg)0
-rw-r--r--editor/icons/source/icon_g_i_probe_data.svg (renamed from tools/editor/icons/source/icon_g_i_probe_data.svg)0
-rw-r--r--editor/icons/source/icon_generic_6_d_o_f_joint.svg (renamed from tools/editor/icons/source/icon_generic_6_d_o_f_joint.svg)0
-rw-r--r--editor/icons/source/icon_gizmo_directional_light.svg (renamed from tools/editor/icons/source/icon_gizmo_directional_light.svg)0
-rw-r--r--editor/icons/source/icon_gizmo_light.svg (renamed from tools/editor/icons/source/icon_gizmo_light.svg)0
-rw-r--r--editor/icons/source/icon_gizmo_listener.svg (renamed from tools/editor/icons/source/icon_gizmo_listener.svg)0
-rw-r--r--editor/icons/source/icon_gizmo_spatial_sample_player.svg (renamed from tools/editor/icons/source/icon_gizmo_spatial_sample_player.svg)0
-rw-r--r--editor/icons/source/icon_gizmo_spatial_stream_player.svg (renamed from tools/editor/icons/source/icon_gizmo_spatial_stream_player.svg)0
-rw-r--r--editor/icons/source/icon_godot.svg (renamed from tools/editor/icons/source/icon_godot.svg)0
-rw-r--r--editor/icons/source/icon_graph_comment.svg (renamed from tools/editor/icons/source/icon_graph_comment.svg)0
-rw-r--r--editor/icons/source/icon_graph_cube_uniform.svg (renamed from tools/editor/icons/source/icon_graph_cube_uniform.svg)0
-rw-r--r--editor/icons/source/icon_graph_curve_map.svg (renamed from tools/editor/icons/source/icon_graph_curve_map.svg)0
-rw-r--r--editor/icons/source/icon_graph_default_texture.svg (renamed from tools/editor/icons/source/icon_graph_default_texture.svg)0
-rw-r--r--editor/icons/source/icon_graph_edit.svg (renamed from tools/editor/icons/source/icon_graph_edit.svg)0
-rw-r--r--editor/icons/source/icon_graph_input.svg (renamed from tools/editor/icons/source/icon_graph_input.svg)0
-rw-r--r--editor/icons/source/icon_graph_node.svg (renamed from tools/editor/icons/source/icon_graph_node.svg)0
-rw-r--r--editor/icons/source/icon_graph_rgb.svg (renamed from tools/editor/icons/source/icon_graph_rgb.svg)0
-rw-r--r--editor/icons/source/icon_graph_rgb_op.svg (renamed from tools/editor/icons/source/icon_graph_rgb_op.svg)0
-rw-r--r--editor/icons/source/icon_graph_rgb_uniform.svg (renamed from tools/editor/icons/source/icon_graph_rgb_uniform.svg)0
-rw-r--r--editor/icons/source/icon_graph_scalar.svg (renamed from tools/editor/icons/source/icon_graph_scalar.svg)0
-rw-r--r--editor/icons/source/icon_graph_scalar_interp.svg (renamed from tools/editor/icons/source/icon_graph_scalar_interp.svg)0
-rw-r--r--editor/icons/source/icon_graph_scalar_op.svg (renamed from tools/editor/icons/source/icon_graph_scalar_op.svg)0
-rw-r--r--editor/icons/source/icon_graph_scalar_uniform.svg (renamed from tools/editor/icons/source/icon_graph_scalar_uniform.svg)0
-rw-r--r--editor/icons/source/icon_graph_scalars_to_vec.svg (renamed from tools/editor/icons/source/icon_graph_scalars_to_vec.svg)0
-rw-r--r--editor/icons/source/icon_graph_texscreen.svg (renamed from tools/editor/icons/source/icon_graph_texscreen.svg)0
-rw-r--r--editor/icons/source/icon_graph_texture_uniform.svg (renamed from tools/editor/icons/source/icon_graph_texture_uniform.svg)0
-rw-r--r--editor/icons/source/icon_graph_time.svg (renamed from tools/editor/icons/source/icon_graph_time.svg)0
-rw-r--r--editor/icons/source/icon_graph_vec_dp.svg (renamed from tools/editor/icons/source/icon_graph_vec_dp.svg)0
-rw-r--r--editor/icons/source/icon_graph_vec_interp.svg (renamed from tools/editor/icons/source/icon_graph_vec_interp.svg)0
-rw-r--r--editor/icons/source/icon_graph_vec_length.svg (renamed from tools/editor/icons/source/icon_graph_vec_length.svg)0
-rw-r--r--editor/icons/source/icon_graph_vec_op.svg (renamed from tools/editor/icons/source/icon_graph_vec_op.svg)0
-rw-r--r--editor/icons/source/icon_graph_vec_scalar_op.svg (renamed from tools/editor/icons/source/icon_graph_vec_scalar_op.svg)0
-rw-r--r--editor/icons/source/icon_graph_vec_to_scalars.svg (renamed from tools/editor/icons/source/icon_graph_vec_to_scalars.svg)0
-rw-r--r--editor/icons/source/icon_graph_vecs_to_xform.svg (renamed from tools/editor/icons/source/icon_graph_vecs_to_xform.svg)0
-rw-r--r--editor/icons/source/icon_graph_vector.svg (renamed from tools/editor/icons/source/icon_graph_vector.svg)0
-rw-r--r--editor/icons/source/icon_graph_vector_uniform.svg (renamed from tools/editor/icons/source/icon_graph_vector_uniform.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform.svg (renamed from tools/editor/icons/source/icon_graph_xform.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform_mult.svg (renamed from tools/editor/icons/source/icon_graph_xform_mult.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform_scalar_func.svg (renamed from tools/editor/icons/source/icon_graph_xform_scalar_func.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform_to_vecs.svg (renamed from tools/editor/icons/source/icon_graph_xform_to_vecs.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform_uniform.svg (renamed from tools/editor/icons/source/icon_graph_xform_uniform.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform_vec_func.svg (renamed from tools/editor/icons/source/icon_graph_xform_vec_func.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform_vec_imult.svg (renamed from tools/editor/icons/source/icon_graph_xform_vec_imult.svg)0
-rw-r--r--editor/icons/source/icon_graph_xform_vec_mult.svg (renamed from tools/editor/icons/source/icon_graph_xform_vec_mult.svg)0
-rw-r--r--editor/icons/source/icon_grid.svg (renamed from tools/editor/icons/source/icon_grid.svg)0
-rw-r--r--editor/icons/source/icon_grid_container.svg (renamed from tools/editor/icons/source/icon_grid_container.svg)0
-rw-r--r--editor/icons/source/icon_grid_map.svg (renamed from tools/editor/icons/source/icon_grid_map.svg)0
-rw-r--r--editor/icons/source/icon_groove_joint_2d.svg (renamed from tools/editor/icons/source/icon_groove_joint_2d.svg)0
-rw-r--r--editor/icons/source/icon_group.svg (renamed from tools/editor/icons/source/icon_group.svg)0
-rw-r--r--editor/icons/source/icon_groups.svg (renamed from tools/editor/icons/source/icon_groups.svg)0
-rw-r--r--editor/icons/source/icon_h_box_container.svg (renamed from tools/editor/icons/source/icon_h_box_container.svg)0
-rw-r--r--editor/icons/source/icon_h_button_array.svg (renamed from tools/editor/icons/source/icon_h_button_array.svg)0
-rw-r--r--editor/icons/source/icon_h_scroll_bar.svg (renamed from tools/editor/icons/source/icon_h_scroll_bar.svg)0
-rw-r--r--editor/icons/source/icon_h_separator.svg (renamed from tools/editor/icons/source/icon_h_separator.svg)0
-rw-r--r--editor/icons/source/icon_h_slider.svg (renamed from tools/editor/icons/source/icon_h_slider.svg)0
-rw-r--r--editor/icons/source/icon_h_split_container.svg (renamed from tools/editor/icons/source/icon_h_split_container.svg)0
-rw-r--r--editor/icons/source/icon_h_t_t_p_request.svg (renamed from tools/editor/icons/source/icon_h_t_t_p_request.svg)0
-rw-r--r--editor/icons/source/icon_headphones.svg (renamed from tools/editor/icons/source/icon_headphones.svg)0
-rw-r--r--editor/icons/source/icon_help.svg (renamed from tools/editor/icons/source/icon_help.svg)0
-rw-r--r--editor/icons/source/icon_hidden.svg (renamed from tools/editor/icons/source/icon_hidden.svg)0
-rw-r--r--editor/icons/source/icon_hinge_joint.svg (renamed from tools/editor/icons/source/icon_hinge_joint.svg)0
-rw-r--r--editor/icons/source/icon_history.svg (renamed from tools/editor/icons/source/icon_history.svg)0
-rw-r--r--editor/icons/source/icon_hsize.svg (renamed from tools/editor/icons/source/icon_hsize.svg)0
-rw-r--r--editor/icons/source/icon_image.svg (renamed from tools/editor/icons/source/icon_image.svg)0
-rw-r--r--editor/icons/source/icon_image_sky_box.svg (renamed from tools/editor/icons/source/icon_image_sky_box.svg)0
-rw-r--r--editor/icons/source/icon_image_texture.svg (renamed from tools/editor/icons/source/icon_image_texture.svg)0
-rw-r--r--editor/icons/source/icon_immediate_geometry.svg (renamed from tools/editor/icons/source/icon_immediate_geometry.svg)0
-rw-r--r--editor/icons/source/icon_import_check.svg (renamed from tools/editor/icons/source/icon_import_check.svg)0
-rw-r--r--editor/icons/source/icon_import_fail.svg (renamed from tools/editor/icons/source/icon_import_fail.svg)0
-rw-r--r--editor/icons/source/icon_instance.svg (renamed from tools/editor/icons/source/icon_instance.svg)0
-rw-r--r--editor/icons/source/icon_instance_options.svg (renamed from tools/editor/icons/source/icon_instance_options.svg)0
-rw-r--r--editor/icons/source/icon_integer.svg (renamed from tools/editor/icons/source/icon_integer.svg)0
-rw-r--r--editor/icons/source/icon_interp_cubic.svg (renamed from tools/editor/icons/source/icon_interp_cubic.svg)0
-rw-r--r--editor/icons/source/icon_interp_linear.svg (renamed from tools/editor/icons/source/icon_interp_linear.svg)0
-rw-r--r--editor/icons/source/icon_interp_raw.svg (renamed from tools/editor/icons/source/icon_interp_raw.svg)0
-rw-r--r--editor/icons/source/icon_interp_wrap_clamp.svg (renamed from tools/editor/icons/source/icon_interp_wrap_clamp.svg)0
-rw-r--r--editor/icons/source/icon_interp_wrap_loop.svg (renamed from tools/editor/icons/source/icon_interp_wrap_loop.svg)0
-rw-r--r--editor/icons/source/icon_interpolated_camera.svg (renamed from tools/editor/icons/source/icon_interpolated_camera.svg)0
-rw-r--r--editor/icons/source/icon_invalid_key.svg (renamed from tools/editor/icons/source/icon_invalid_key.svg)0
-rw-r--r--editor/icons/source/icon_inverse_kinematics.svg (renamed from tools/editor/icons/source/icon_inverse_kinematics.svg)0
-rw-r--r--editor/icons/source/icon_item_list.svg (renamed from tools/editor/icons/source/icon_item_list.svg)0
-rw-r--r--editor/icons/source/icon_joy_axis.svg (renamed from tools/editor/icons/source/icon_joy_axis.svg)0
-rw-r--r--editor/icons/source/icon_joy_button.svg (renamed from tools/editor/icons/source/icon_joy_button.svg)0
-rw-r--r--editor/icons/source/icon_joypad.svg (renamed from tools/editor/icons/source/icon_joypad.svg)0
-rw-r--r--editor/icons/source/icon_key.svg (renamed from tools/editor/icons/source/icon_key.svg)0
-rw-r--r--editor/icons/source/icon_key_hover.svg (renamed from tools/editor/icons/source/icon_key_hover.svg)0
-rw-r--r--editor/icons/source/icon_key_invalid.svg (renamed from tools/editor/icons/source/icon_key_invalid.svg)0
-rw-r--r--editor/icons/source/icon_key_next.svg (renamed from tools/editor/icons/source/icon_key_next.svg)0
-rw-r--r--editor/icons/source/icon_key_selected.svg (renamed from tools/editor/icons/source/icon_key_selected.svg)0
-rw-r--r--editor/icons/source/icon_key_value.svg (renamed from tools/editor/icons/source/icon_key_value.svg)0
-rw-r--r--editor/icons/source/icon_key_xform.svg (renamed from tools/editor/icons/source/icon_key_xform.svg)0
-rw-r--r--editor/icons/source/icon_keyboard.svg (renamed from tools/editor/icons/source/icon_keyboard.svg)0
-rw-r--r--editor/icons/source/icon_kinematic_body.svg (renamed from tools/editor/icons/source/icon_kinematic_body.svg)0
-rw-r--r--editor/icons/source/icon_kinematic_body_2d.svg (renamed from tools/editor/icons/source/icon_kinematic_body_2d.svg)0
-rw-r--r--editor/icons/source/icon_label.svg (renamed from tools/editor/icons/source/icon_label.svg)0
-rw-r--r--editor/icons/source/icon_large_texture.svg (renamed from tools/editor/icons/source/icon_large_texture.svg)0
-rw-r--r--editor/icons/source/icon_light_2d.svg (renamed from tools/editor/icons/source/icon_light_2d.svg)0
-rw-r--r--editor/icons/source/icon_light_occluder_2d.svg (renamed from tools/editor/icons/source/icon_light_occluder_2d.svg)0
-rw-r--r--editor/icons/source/icon_line_2d.svg82
-rw-r--r--editor/icons/source/icon_line_edit.svg (renamed from tools/editor/icons/source/icon_line_edit.svg)0
-rw-r--r--editor/icons/source/icon_line_shape_2d.svg (renamed from tools/editor/icons/source/icon_line_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_link_button.svg (renamed from tools/editor/icons/source/icon_link_button.svg)0
-rw-r--r--editor/icons/source/icon_list_select.svg (renamed from tools/editor/icons/source/icon_list_select.svg)0
-rw-r--r--editor/icons/source/icon_listener.svg (renamed from tools/editor/icons/source/icon_listener.svg)0
-rw-r--r--editor/icons/source/icon_load.svg (renamed from tools/editor/icons/source/icon_load.svg)0
-rw-r--r--editor/icons/source/icon_lock.svg (renamed from tools/editor/icons/source/icon_lock.svg)0
-rw-r--r--editor/icons/source/icon_loop.svg (renamed from tools/editor/icons/source/icon_loop.svg)0
-rw-r--r--editor/icons/source/icon_loop_interpolation.svg (renamed from tools/editor/icons/source/icon_loop_interpolation.svg)0
-rw-r--r--editor/icons/source/icon_main_play.svg (renamed from tools/editor/icons/source/icon_main_play.svg)0
-rw-r--r--editor/icons/source/icon_main_stop.svg (renamed from tools/editor/icons/source/icon_main_stop.svg)0
-rw-r--r--editor/icons/source/icon_margin_container.svg (renamed from tools/editor/icons/source/icon_margin_container.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_cube.svg (renamed from tools/editor/icons/source/icon_material_preview_cube.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_cube_off.svg (renamed from tools/editor/icons/source/icon_material_preview_cube_off.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_light_1.svg (renamed from tools/editor/icons/source/icon_material_preview_light_1.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_light_1_off.svg (renamed from tools/editor/icons/source/icon_material_preview_light_1_off.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_light_2.svg (renamed from tools/editor/icons/source/icon_material_preview_light_2.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_light_2_off.svg (renamed from tools/editor/icons/source/icon_material_preview_light_2_off.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_sphere.svg (renamed from tools/editor/icons/source/icon_material_preview_sphere.svg)0
-rw-r--r--editor/icons/source/icon_material_preview_sphere_off.svg (renamed from tools/editor/icons/source/icon_material_preview_sphere_off.svg)0
-rw-r--r--editor/icons/source/icon_matrix.svg (renamed from tools/editor/icons/source/icon_matrix.svg)0
-rw-r--r--editor/icons/source/icon_menu_button.svg (renamed from tools/editor/icons/source/icon_menu_button.svg)0
-rw-r--r--editor/icons/source/icon_mesh.svg (renamed from tools/editor/icons/source/icon_mesh.svg)0
-rw-r--r--editor/icons/source/icon_mesh_instance.svg (renamed from tools/editor/icons/source/icon_mesh_instance.svg)0
-rw-r--r--editor/icons/source/icon_mesh_library.svg (renamed from tools/editor/icons/source/icon_mesh_library.svg)0
-rw-r--r--editor/icons/source/icon_mini_aabb.svg (renamed from tools/editor/icons/source/icon_mini_aabb.svg)0
-rw-r--r--editor/icons/source/icon_mini_array.svg (renamed from tools/editor/icons/source/icon_mini_array.svg)0
-rw-r--r--editor/icons/source/icon_mini_boolean.svg (renamed from tools/editor/icons/source/icon_mini_boolean.svg)0
-rw-r--r--editor/icons/source/icon_mini_color.svg (renamed from tools/editor/icons/source/icon_mini_color.svg)0
-rw-r--r--editor/icons/source/icon_mini_color_array.svg (renamed from tools/editor/icons/source/icon_mini_color_array.svg)0
-rw-r--r--editor/icons/source/icon_mini_dictionary.svg (renamed from tools/editor/icons/source/icon_mini_dictionary.svg)0
-rw-r--r--editor/icons/source/icon_mini_float.svg (renamed from tools/editor/icons/source/icon_mini_float.svg)0
-rw-r--r--editor/icons/source/icon_mini_float_array.svg (renamed from tools/editor/icons/source/icon_mini_float_array.svg)0
-rw-r--r--editor/icons/source/icon_mini_image.svg (renamed from tools/editor/icons/source/icon_mini_image.svg)0
-rw-r--r--editor/icons/source/icon_mini_input.svg (renamed from tools/editor/icons/source/icon_mini_input.svg)0
-rw-r--r--editor/icons/source/icon_mini_int_array.svg (renamed from tools/editor/icons/source/icon_mini_int_array.svg)0
-rw-r--r--editor/icons/source/icon_mini_integer.svg (renamed from tools/editor/icons/source/icon_mini_integer.svg)0
-rw-r--r--editor/icons/source/icon_mini_matrix3.svg (renamed from tools/editor/icons/source/icon_mini_matrix3.svg)0
-rw-r--r--editor/icons/source/icon_mini_matrix32.svg (renamed from tools/editor/icons/source/icon_mini_matrix32.svg)0
-rw-r--r--editor/icons/source/icon_mini_object.svg (renamed from tools/editor/icons/source/icon_mini_object.svg)0
-rw-r--r--editor/icons/source/icon_mini_path.svg (renamed from tools/editor/icons/source/icon_mini_path.svg)0
-rw-r--r--editor/icons/source/icon_mini_plane.svg (renamed from tools/editor/icons/source/icon_mini_plane.svg)0
-rw-r--r--editor/icons/source/icon_mini_quat.svg (renamed from tools/editor/icons/source/icon_mini_quat.svg)0
-rw-r--r--editor/icons/source/icon_mini_raw_array.svg (renamed from tools/editor/icons/source/icon_mini_raw_array.svg)0
-rw-r--r--editor/icons/source/icon_mini_rect2.svg (renamed from tools/editor/icons/source/icon_mini_rect2.svg)0
-rw-r--r--editor/icons/source/icon_mini_rid.svg (renamed from tools/editor/icons/source/icon_mini_rid.svg)0
-rw-r--r--editor/icons/source/icon_mini_string.svg (renamed from tools/editor/icons/source/icon_mini_string.svg)0
-rw-r--r--editor/icons/source/icon_mini_string_array.svg (renamed from tools/editor/icons/source/icon_mini_string_array.svg)0
-rw-r--r--editor/icons/source/icon_mini_transform.svg (renamed from tools/editor/icons/source/icon_mini_transform.svg)0
-rw-r--r--editor/icons/source/icon_mini_variant.svg (renamed from tools/editor/icons/source/icon_mini_variant.svg)0
-rw-r--r--editor/icons/source/icon_mini_vector2.svg (renamed from tools/editor/icons/source/icon_mini_vector2.svg)0
-rw-r--r--editor/icons/source/icon_mini_vector2_array.svg (renamed from tools/editor/icons/source/icon_mini_vector2_array.svg)0
-rw-r--r--editor/icons/source/icon_mini_vector3.svg (renamed from tools/editor/icons/source/icon_mini_vector3.svg)0
-rw-r--r--editor/icons/source/icon_mini_vector3_array.svg (renamed from tools/editor/icons/source/icon_mini_vector3_array.svg)0
-rw-r--r--editor/icons/source/icon_mirror_x.svg (renamed from tools/editor/icons/source/icon_mirror_x.svg)0
-rw-r--r--editor/icons/source/icon_mirror_y.svg (renamed from tools/editor/icons/source/icon_mirror_y.svg)0
-rw-r--r--editor/icons/source/icon_mouse.svg (renamed from tools/editor/icons/source/icon_mouse.svg)0
-rw-r--r--editor/icons/source/icon_move_down.svg (renamed from tools/editor/icons/source/icon_move_down.svg)0
-rw-r--r--editor/icons/source/icon_move_point.svg (renamed from tools/editor/icons/source/icon_move_point.svg)0
-rw-r--r--editor/icons/source/icon_move_up.svg (renamed from tools/editor/icons/source/icon_move_up.svg)0
-rw-r--r--editor/icons/source/icon_multi_edit.svg (renamed from tools/editor/icons/source/icon_multi_edit.svg)0
-rw-r--r--editor/icons/source/icon_multi_line.svg (renamed from tools/editor/icons/source/icon_multi_line.svg)0
-rw-r--r--editor/icons/source/icon_multi_mesh.svg (renamed from tools/editor/icons/source/icon_multi_mesh.svg)0
-rw-r--r--editor/icons/source/icon_multi_mesh_instance.svg (renamed from tools/editor/icons/source/icon_multi_mesh_instance.svg)0
-rw-r--r--editor/icons/source/icon_navigation.svg (renamed from tools/editor/icons/source/icon_navigation.svg)0
-rw-r--r--editor/icons/source/icon_navigation_2d.svg (renamed from tools/editor/icons/source/icon_navigation_2d.svg)0
-rw-r--r--editor/icons/source/icon_navigation_mesh.svg (renamed from tools/editor/icons/source/icon_navigation_mesh.svg)0
-rw-r--r--editor/icons/source/icon_navigation_mesh_instance.svg (renamed from tools/editor/icons/source/icon_navigation_mesh_instance.svg)0
-rw-r--r--editor/icons/source/icon_navigation_polygon.svg (renamed from tools/editor/icons/source/icon_navigation_polygon.svg)0
-rw-r--r--editor/icons/source/icon_navigation_polygon_instance.svg (renamed from tools/editor/icons/source/icon_navigation_polygon_instance.svg)0
-rw-r--r--editor/icons/source/icon_new.svg (renamed from tools/editor/icons/source/icon_new.svg)0
-rw-r--r--editor/icons/source/icon_nine_patch_rect.svg (renamed from tools/editor/icons/source/icon_nine_patch_rect.svg)0
-rw-r--r--editor/icons/source/icon_node.svg (renamed from tools/editor/icons/source/icon_node.svg)0
-rw-r--r--editor/icons/source/icon_node_2d.svg (renamed from tools/editor/icons/source/icon_node_2d.svg)0
-rw-r--r--editor/icons/source/icon_node_warning.svg (renamed from tools/editor/icons/source/icon_node_warning.svg)0
-rw-r--r--editor/icons/source/icon_non_favorite.svg (renamed from tools/editor/icons/source/icon_non_favorite.svg)0
-rw-r--r--editor/icons/source/icon_object.svg (renamed from tools/editor/icons/source/icon_object.svg)0
-rw-r--r--editor/icons/source/icon_occluder_polygon_2d.svg (renamed from tools/editor/icons/source/icon_occluder_polygon_2d.svg)0
-rw-r--r--editor/icons/source/icon_omni_light.svg (renamed from tools/editor/icons/source/icon_omni_light.svg)0
-rw-r--r--editor/icons/source/icon_option_button.svg (renamed from tools/editor/icons/source/icon_option_button.svg)0
-rw-r--r--editor/icons/source/icon_override.svg (renamed from tools/editor/icons/source/icon_override.svg)0
-rw-r--r--editor/icons/source/icon_packed_data_container.svg (renamed from tools/editor/icons/source/icon_packed_data_container.svg)0
-rw-r--r--editor/icons/source/icon_packed_scene.svg (renamed from tools/editor/icons/source/icon_packed_scene.svg)0
-rw-r--r--editor/icons/source/icon_panel.svg (renamed from tools/editor/icons/source/icon_panel.svg)0
-rw-r--r--editor/icons/source/icon_panel_container.svg (renamed from tools/editor/icons/source/icon_panel_container.svg)0
-rw-r--r--editor/icons/source/icon_panels_1.svg (renamed from tools/editor/icons/source/icon_panels_1.svg)0
-rw-r--r--editor/icons/source/icon_panels_2.svg (renamed from tools/editor/icons/source/icon_panels_2.svg)0
-rw-r--r--editor/icons/source/icon_panels_2_alt.svg (renamed from tools/editor/icons/source/icon_panels_2_alt.svg)0
-rw-r--r--editor/icons/source/icon_panels_3.svg (renamed from tools/editor/icons/source/icon_panels_3.svg)0
-rw-r--r--editor/icons/source/icon_panels_3_alt.svg (renamed from tools/editor/icons/source/icon_panels_3_alt.svg)0
-rw-r--r--editor/icons/source/icon_panels_4.svg (renamed from tools/editor/icons/source/icon_panels_4.svg)0
-rw-r--r--editor/icons/source/icon_parallax_background.svg (renamed from tools/editor/icons/source/icon_parallax_background.svg)0
-rw-r--r--editor/icons/source/icon_parallax_layer.svg (renamed from tools/editor/icons/source/icon_parallax_layer.svg)0
-rw-r--r--editor/icons/source/icon_particle_attractor_2d.svg (renamed from tools/editor/icons/source/icon_particle_attractor_2d.svg)0
-rw-r--r--editor/icons/source/icon_particles.svg (renamed from tools/editor/icons/source/icon_particles.svg)0
-rw-r--r--editor/icons/source/icon_particles_2d.svg (renamed from tools/editor/icons/source/icon_particles_2d.svg)0
-rw-r--r--editor/icons/source/icon_particles_shader.svg (renamed from tools/editor/icons/source/icon_particles_shader.svg)0
-rw-r--r--editor/icons/source/icon_patch_9_rect.svg (renamed from tools/editor/icons/source/icon_patch_9_rect.svg)0
-rw-r--r--editor/icons/source/icon_path.svg (renamed from tools/editor/icons/source/icon_path.svg)0
-rw-r--r--editor/icons/source/icon_path_2d.svg (renamed from tools/editor/icons/source/icon_path_2d.svg)0
-rw-r--r--editor/icons/source/icon_path_follow.svg (renamed from tools/editor/icons/source/icon_path_follow.svg)0
-rw-r--r--editor/icons/source/icon_path_follow_2d.svg (renamed from tools/editor/icons/source/icon_path_follow_2d.svg)0
-rw-r--r--editor/icons/source/icon_pause.svg (renamed from tools/editor/icons/source/icon_pause.svg)0
-rw-r--r--editor/icons/source/icon_pin.svg (renamed from tools/editor/icons/source/icon_pin.svg)0
-rw-r--r--editor/icons/source/icon_pin_joint.svg (renamed from tools/editor/icons/source/icon_pin_joint.svg)0
-rw-r--r--editor/icons/source/icon_pin_joint_2d.svg (renamed from tools/editor/icons/source/icon_pin_joint_2d.svg)0
-rw-r--r--editor/icons/source/icon_pin_pressed.svg (renamed from tools/editor/icons/source/icon_pin_pressed.svg)0
-rw-r--r--editor/icons/source/icon_plane.svg (renamed from tools/editor/icons/source/icon_plane.svg)0
-rw-r--r--editor/icons/source/icon_plane_shape.svg (renamed from tools/editor/icons/source/icon_plane_shape.svg)0
-rw-r--r--editor/icons/source/icon_play.svg (renamed from tools/editor/icons/source/icon_play.svg)0
-rw-r--r--editor/icons/source/icon_play_backwards.svg (renamed from tools/editor/icons/source/icon_play_backwards.svg)0
-rw-r--r--editor/icons/source/icon_play_custom.svg (renamed from tools/editor/icons/source/icon_play_custom.svg)0
-rw-r--r--editor/icons/source/icon_play_scene.svg (renamed from tools/editor/icons/source/icon_play_scene.svg)0
-rw-r--r--editor/icons/source/icon_play_start.svg (renamed from tools/editor/icons/source/icon_play_start.svg)0
-rw-r--r--editor/icons/source/icon_play_start_backwards.svg (renamed from tools/editor/icons/source/icon_play_start_backwards.svg)0
-rw-r--r--editor/icons/source/icon_polygon_path_finder.svg (renamed from tools/editor/icons/source/icon_polygon_path_finder.svg)0
-rw-r--r--editor/icons/source/icon_popup.svg (renamed from tools/editor/icons/source/icon_popup.svg)0
-rw-r--r--editor/icons/source/icon_popup_dialog.svg (renamed from tools/editor/icons/source/icon_popup_dialog.svg)0
-rw-r--r--editor/icons/source/icon_popup_menu.svg (renamed from tools/editor/icons/source/icon_popup_menu.svg)0
-rw-r--r--editor/icons/source/icon_popup_panel.svg (renamed from tools/editor/icons/source/icon_popup_panel.svg)0
-rw-r--r--editor/icons/source/icon_portal.svg (renamed from tools/editor/icons/source/icon_portal.svg)0
-rw-r--r--editor/icons/source/icon_position_2d.svg (renamed from tools/editor/icons/source/icon_position_2d.svg)0
-rw-r--r--editor/icons/source/icon_position_3d.svg (renamed from tools/editor/icons/source/icon_position_3d.svg)0
-rw-r--r--editor/icons/source/icon_progress_1.svg (renamed from tools/editor/icons/source/icon_progress_1.svg)0
-rw-r--r--editor/icons/source/icon_progress_2.svg (renamed from tools/editor/icons/source/icon_progress_2.svg)0
-rw-r--r--editor/icons/source/icon_progress_3.svg (renamed from tools/editor/icons/source/icon_progress_3.svg)0
-rw-r--r--editor/icons/source/icon_progress_4.svg (renamed from tools/editor/icons/source/icon_progress_4.svg)0
-rw-r--r--editor/icons/source/icon_progress_5.svg (renamed from tools/editor/icons/source/icon_progress_5.svg)0
-rw-r--r--editor/icons/source/icon_progress_6.svg (renamed from tools/editor/icons/source/icon_progress_6.svg)0
-rw-r--r--editor/icons/source/icon_progress_7.svg (renamed from tools/editor/icons/source/icon_progress_7.svg)0
-rw-r--r--editor/icons/source/icon_progress_8.svg (renamed from tools/editor/icons/source/icon_progress_8.svg)0
-rw-r--r--editor/icons/source/icon_progress_bar.svg (renamed from tools/editor/icons/source/icon_progress_bar.svg)0
-rw-r--r--editor/icons/source/icon_proximity_group.svg (renamed from tools/editor/icons/source/icon_proximity_group.svg)0
-rw-r--r--editor/icons/source/icon_quad.svg (renamed from tools/editor/icons/source/icon_quad.svg)0
-rw-r--r--editor/icons/source/icon_quat.svg (renamed from tools/editor/icons/source/icon_quat.svg)0
-rw-r--r--editor/icons/source/icon_range.svg (renamed from tools/editor/icons/source/icon_range.svg)0
-rw-r--r--editor/icons/source/icon_rating_no_star.svg (renamed from tools/editor/icons/source/icon_rating_no_star.svg)0
-rw-r--r--editor/icons/source/icon_rating_star.svg (renamed from tools/editor/icons/source/icon_rating_star.svg)0
-rw-r--r--editor/icons/source/icon_ray_cast.svg (renamed from tools/editor/icons/source/icon_ray_cast.svg)0
-rw-r--r--editor/icons/source/icon_ray_cast_2d.svg (renamed from tools/editor/icons/source/icon_ray_cast_2d.svg)0
-rw-r--r--editor/icons/source/icon_ray_shape.svg (renamed from tools/editor/icons/source/icon_ray_shape.svg)0
-rw-r--r--editor/icons/source/icon_ray_shape_2d.svg (renamed from tools/editor/icons/source/icon_ray_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_rayito.svg (renamed from tools/editor/icons/source/icon_rayito.svg)0
-rw-r--r--editor/icons/source/icon_real.svg (renamed from tools/editor/icons/source/icon_real.svg)0
-rw-r--r--editor/icons/source/icon_rectangle_shape_2d.svg (renamed from tools/editor/icons/source/icon_rectangle_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_reference_rect.svg (renamed from tools/editor/icons/source/icon_reference_rect.svg)0
-rw-r--r--editor/icons/source/icon_reflection_probe.svg (renamed from tools/editor/icons/source/icon_reflection_probe.svg)0
-rw-r--r--editor/icons/source/icon_region_edit.svg (renamed from tools/editor/icons/source/icon_region_edit.svg)0
-rw-r--r--editor/icons/source/icon_reload_small.svg (renamed from tools/editor/icons/source/icon_reload_small.svg)0
-rw-r--r--editor/icons/source/icon_remote.svg (renamed from tools/editor/icons/source/icon_remote.svg)0
-rw-r--r--editor/icons/source/icon_remote_transform.svg (renamed from tools/editor/icons/source/icon_remote_transform.svg)0
-rw-r--r--editor/icons/source/icon_remote_transform_2d.svg (renamed from tools/editor/icons/source/icon_remote_transform_2d.svg)0
-rw-r--r--editor/icons/source/icon_remove.svg (renamed from tools/editor/icons/source/icon_remove.svg)0
-rw-r--r--editor/icons/source/icon_rename.svg (renamed from tools/editor/icons/source/icon_rename.svg)0
-rw-r--r--editor/icons/source/icon_reparent.svg (renamed from tools/editor/icons/source/icon_reparent.svg)0
-rw-r--r--editor/icons/source/icon_resource_preloader.svg (renamed from tools/editor/icons/source/icon_resource_preloader.svg)0
-rw-r--r--editor/icons/source/icon_rich_text_label.svg (renamed from tools/editor/icons/source/icon_rich_text_label.svg)0
-rw-r--r--editor/icons/source/icon_rigid_body.svg (renamed from tools/editor/icons/source/icon_rigid_body.svg)0
-rw-r--r--editor/icons/source/icon_rigid_body_2d.svg (renamed from tools/editor/icons/source/icon_rigid_body_2d.svg)0
-rw-r--r--editor/icons/source/icon_room.svg (renamed from tools/editor/icons/source/icon_room.svg)0
-rw-r--r--editor/icons/source/icon_room_bounds.svg (renamed from tools/editor/icons/source/icon_room_bounds.svg)0
-rw-r--r--editor/icons/source/icon_rotate_0.svg (renamed from tools/editor/icons/source/icon_rotate_0.svg)0
-rw-r--r--editor/icons/source/icon_rotate_180.svg (renamed from tools/editor/icons/source/icon_rotate_180.svg)0
-rw-r--r--editor/icons/source/icon_rotate_270.svg (renamed from tools/editor/icons/source/icon_rotate_270.svg)0
-rw-r--r--editor/icons/source/icon_rotate_90.svg (renamed from tools/editor/icons/source/icon_rotate_90.svg)0
-rw-r--r--editor/icons/source/icon_sample.svg (renamed from tools/editor/icons/source/icon_sample.svg)0
-rw-r--r--editor/icons/source/icon_sample_library.svg (renamed from tools/editor/icons/source/icon_sample_library.svg)0
-rw-r--r--editor/icons/source/icon_sample_player.svg (renamed from tools/editor/icons/source/icon_sample_player.svg)0
-rw-r--r--editor/icons/source/icon_sample_player_2d.svg (renamed from tools/editor/icons/source/icon_sample_player_2d.svg)0
-rw-r--r--editor/icons/source/icon_save.svg (renamed from tools/editor/icons/source/icon_save.svg)0
-rw-r--r--editor/icons/source/icon_script.svg (renamed from tools/editor/icons/source/icon_script.svg)0
-rw-r--r--editor/icons/source/icon_script_create.svg (renamed from tools/editor/icons/source/icon_script_create.svg)0
-rw-r--r--editor/icons/source/icon_script_remove.svg (renamed from tools/editor/icons/source/icon_script_remove.svg)0
-rw-r--r--editor/icons/source/icon_scroll_bar.svg (renamed from tools/editor/icons/source/icon_scroll_bar.svg)0
-rw-r--r--editor/icons/source/icon_scroll_container.svg (renamed from tools/editor/icons/source/icon_scroll_container.svg)0
-rw-r--r--editor/icons/source/icon_segment_shape_2d.svg (renamed from tools/editor/icons/source/icon_segment_shape_2d.svg)0
-rw-r--r--editor/icons/source/icon_shader.svg (renamed from tools/editor/icons/source/icon_shader.svg)0
-rw-r--r--editor/icons/source/icon_short_cut.svg (renamed from tools/editor/icons/source/icon_short_cut.svg)0
-rw-r--r--editor/icons/source/icon_signal.svg (renamed from tools/editor/icons/source/icon_signal.svg)0
-rw-r--r--editor/icons/source/icon_skeleton.svg (renamed from tools/editor/icons/source/icon_skeleton.svg)0
-rw-r--r--editor/icons/source/icon_slider_joint.svg (renamed from tools/editor/icons/source/icon_slider_joint.svg)0
-rw-r--r--editor/icons/source/icon_slot.svg (renamed from tools/editor/icons/source/icon_slot.svg)0
-rw-r--r--editor/icons/source/icon_snap.svg (renamed from tools/editor/icons/source/icon_snap.svg)0
-rw-r--r--editor/icons/source/icon_sound_room_params.svg (renamed from tools/editor/icons/source/icon_sound_room_params.svg)0
-rw-r--r--editor/icons/source/icon_spatial.svg (renamed from tools/editor/icons/source/icon_spatial.svg)0
-rw-r--r--editor/icons/source/icon_spatial_sample_player.svg (renamed from tools/editor/icons/source/icon_spatial_sample_player.svg)0
-rw-r--r--editor/icons/source/icon_spatial_shader.svg (renamed from tools/editor/icons/source/icon_spatial_shader.svg)0
-rw-r--r--editor/icons/source/icon_spatial_stream_player.svg (renamed from tools/editor/icons/source/icon_spatial_stream_player.svg)0
-rw-r--r--editor/icons/source/icon_sphere_shape.svg (renamed from tools/editor/icons/source/icon_sphere_shape.svg)0
-rw-r--r--editor/icons/source/icon_spin_box.svg (renamed from tools/editor/icons/source/icon_spin_box.svg)0
-rw-r--r--editor/icons/source/icon_spot_light.svg (renamed from tools/editor/icons/source/icon_spot_light.svg)0
-rw-r--r--editor/icons/source/icon_sprite.svg (renamed from tools/editor/icons/source/icon_sprite.svg)0
-rw-r--r--editor/icons/source/icon_sprite_3d.svg (renamed from tools/editor/icons/source/icon_sprite_3d.svg)0
-rw-r--r--editor/icons/source/icon_sprite_frames.svg (renamed from tools/editor/icons/source/icon_sprite_frames.svg)0
-rw-r--r--editor/icons/source/icon_static_body.svg (renamed from tools/editor/icons/source/icon_static_body.svg)0
-rw-r--r--editor/icons/source/icon_static_body_2d.svg (renamed from tools/editor/icons/source/icon_static_body_2d.svg)0
-rw-r--r--editor/icons/source/icon_stream_player.svg (renamed from tools/editor/icons/source/icon_stream_player.svg)0
-rw-r--r--editor/icons/source/icon_string.svg (renamed from tools/editor/icons/source/icon_string.svg)0
-rw-r--r--editor/icons/source/icon_style_box_empty.svg (renamed from tools/editor/icons/source/icon_style_box_empty.svg)0
-rw-r--r--editor/icons/source/icon_style_box_flat.svg (renamed from tools/editor/icons/source/icon_style_box_flat.svg)0
-rw-r--r--editor/icons/source/icon_style_box_texture.svg (renamed from tools/editor/icons/source/icon_style_box_texture.svg)0
-rw-r--r--editor/icons/source/icon_tab_container.svg (renamed from tools/editor/icons/source/icon_tab_container.svg)0
-rw-r--r--editor/icons/source/icon_tabs.svg (renamed from tools/editor/icons/source/icon_tabs.svg)0
-rw-r--r--editor/icons/source/icon_test_cube.svg (renamed from tools/editor/icons/source/icon_test_cube.svg)0
-rw-r--r--editor/icons/source/icon_text_edit.svg (renamed from tools/editor/icons/source/icon_text_edit.svg)0
-rw-r--r--editor/icons/source/icon_texture.svg (renamed from tools/editor/icons/source/icon_texture.svg)0
-rw-r--r--editor/icons/source/icon_texture_button.svg (renamed from tools/editor/icons/source/icon_texture_button.svg)0
-rw-r--r--editor/icons/source/icon_texture_progress.svg (renamed from tools/editor/icons/source/icon_texture_progress.svg)0
-rw-r--r--editor/icons/source/icon_texture_rect.svg (renamed from tools/editor/icons/source/icon_texture_rect.svg)0
-rw-r--r--editor/icons/source/icon_theme.svg (renamed from tools/editor/icons/source/icon_theme.svg)0
-rw-r--r--editor/icons/source/icon_tile_map.svg (renamed from tools/editor/icons/source/icon_tile_map.svg)0
-rw-r--r--editor/icons/source/icon_tile_set.svg (renamed from tools/editor/icons/source/icon_tile_set.svg)0
-rw-r--r--editor/icons/source/icon_timer.svg (renamed from tools/editor/icons/source/icon_timer.svg)0
-rw-r--r--editor/icons/source/icon_tool_button.svg (renamed from tools/editor/icons/source/icon_tool_button.svg)0
-rw-r--r--editor/icons/source/icon_tool_move.svg (renamed from tools/editor/icons/source/icon_tool_move.svg)0
-rw-r--r--editor/icons/source/icon_tool_pan.svg (renamed from tools/editor/icons/source/icon_tool_pan.svg)0
-rw-r--r--editor/icons/source/icon_tool_rotate.svg (renamed from tools/editor/icons/source/icon_tool_rotate.svg)0
-rw-r--r--editor/icons/source/icon_tool_scale.svg (renamed from tools/editor/icons/source/icon_tool_scale.svg)0
-rw-r--r--editor/icons/source/icon_tool_select.svg (renamed from tools/editor/icons/source/icon_tool_select.svg)0
-rw-r--r--editor/icons/source/icon_tools.svg (renamed from tools/editor/icons/source/icon_tools.svg)0
-rw-r--r--editor/icons/source/icon_touch_screen_button.svg (renamed from tools/editor/icons/source/icon_touch_screen_button.svg)0
-rw-r--r--editor/icons/source/icon_track_add_key.svg (renamed from tools/editor/icons/source/icon_track_add_key.svg)0
-rw-r--r--editor/icons/source/icon_track_add_key_hl.svg (renamed from tools/editor/icons/source/icon_track_add_key_hl.svg)0
-rw-r--r--editor/icons/source/icon_track_continuous.svg (renamed from tools/editor/icons/source/icon_track_continuous.svg)0
-rw-r--r--editor/icons/source/icon_track_discrete.svg (renamed from tools/editor/icons/source/icon_track_discrete.svg)0
-rw-r--r--editor/icons/source/icon_track_trigger.svg (renamed from tools/editor/icons/source/icon_track_trigger.svg)0
-rw-r--r--editor/icons/source/icon_translation.svg (renamed from tools/editor/icons/source/icon_translation.svg)0
-rw-r--r--editor/icons/source/icon_transpose.svg (renamed from tools/editor/icons/source/icon_transpose.svg)0
-rw-r--r--editor/icons/source/icon_tree.svg (renamed from tools/editor/icons/source/icon_tree.svg)0
-rw-r--r--editor/icons/source/icon_tween.svg (renamed from tools/editor/icons/source/icon_tween.svg)0
-rw-r--r--editor/icons/source/icon_unbone.svg (renamed from tools/editor/icons/source/icon_unbone.svg)0
-rw-r--r--editor/icons/source/icon_ungroup.svg (renamed from tools/editor/icons/source/icon_ungroup.svg)0
-rw-r--r--editor/icons/source/icon_unlock.svg (renamed from tools/editor/icons/source/icon_unlock.svg)0
-rw-r--r--editor/icons/source/icon_uv.svg (renamed from tools/editor/icons/source/icon_uv.svg)0
-rw-r--r--editor/icons/source/icon_v_box_container.svg (renamed from tools/editor/icons/source/icon_v_box_container.svg)0
-rw-r--r--editor/icons/source/icon_v_button_array.svg (renamed from tools/editor/icons/source/icon_v_button_array.svg)0
-rw-r--r--editor/icons/source/icon_v_scroll_bar.svg (renamed from tools/editor/icons/source/icon_v_scroll_bar.svg)0
-rw-r--r--editor/icons/source/icon_v_separator.svg (renamed from tools/editor/icons/source/icon_v_separator.svg)0
-rw-r--r--editor/icons/source/icon_v_slider.svg (renamed from tools/editor/icons/source/icon_v_slider.svg)0
-rw-r--r--editor/icons/source/icon_v_split_container.svg (renamed from tools/editor/icons/source/icon_v_split_container.svg)0
-rw-r--r--editor/icons/source/icon_vector.svg (renamed from tools/editor/icons/source/icon_vector.svg)0
-rw-r--r--editor/icons/source/icon_vector2.svg (renamed from tools/editor/icons/source/icon_vector2.svg)0
-rw-r--r--editor/icons/source/icon_vehicle_body.svg (renamed from tools/editor/icons/source/icon_vehicle_body.svg)0
-rw-r--r--editor/icons/source/icon_vehicle_wheel.svg (renamed from tools/editor/icons/source/icon_vehicle_wheel.svg)0
-rw-r--r--editor/icons/source/icon_video_player.svg (renamed from tools/editor/icons/source/icon_video_player.svg)0
-rw-r--r--editor/icons/source/icon_viewport.svg (renamed from tools/editor/icons/source/icon_viewport.svg)0
-rw-r--r--editor/icons/source/icon_viewport_container.svg (renamed from tools/editor/icons/source/icon_viewport_container.svg)0
-rw-r--r--editor/icons/source/icon_viewport_sprite.svg (renamed from tools/editor/icons/source/icon_viewport_sprite.svg)0
-rw-r--r--editor/icons/source/icon_viewport_texture.svg (renamed from tools/editor/icons/source/icon_viewport_texture.svg)0
-rw-r--r--editor/icons/source/icon_visibility_enabler.svg (renamed from tools/editor/icons/source/icon_visibility_enabler.svg)0
-rw-r--r--editor/icons/source/icon_visibility_enabler_2d.svg (renamed from tools/editor/icons/source/icon_visibility_enabler_2d.svg)0
-rw-r--r--editor/icons/source/icon_visibility_notifier.svg (renamed from tools/editor/icons/source/icon_visibility_notifier.svg)0
-rw-r--r--editor/icons/source/icon_visibility_notifier_2d.svg (renamed from tools/editor/icons/source/icon_visibility_notifier_2d.svg)0
-rw-r--r--editor/icons/source/icon_visible.svg (renamed from tools/editor/icons/source/icon_visible.svg)0
-rw-r--r--editor/icons/source/icon_visual_script.svg (renamed from tools/editor/icons/source/icon_visual_script.svg)0
-rw-r--r--editor/icons/source/icon_visual_shader_port.svg (renamed from tools/editor/icons/source/icon_visual_shader_port.svg)0
-rw-r--r--editor/icons/source/icon_vu_empty.svg (renamed from tools/editor/icons/source/icon_vu_empty.svg)0
-rw-r--r--editor/icons/source/icon_vu_full.svg (renamed from tools/editor/icons/source/icon_vu_full.svg)0
-rw-r--r--editor/icons/source/icon_warning.svg (renamed from tools/editor/icons/source/icon_warning.svg)0
-rw-r--r--editor/icons/source/icon_window_dialog.svg (renamed from tools/editor/icons/source/icon_window_dialog.svg)0
-rw-r--r--editor/icons/source/icon_world.svg (renamed from tools/editor/icons/source/icon_world.svg)0
-rw-r--r--editor/icons/source/icon_world_2d.svg (renamed from tools/editor/icons/source/icon_world_2d.svg)0
-rw-r--r--editor/icons/source/icon_world_environment.svg (renamed from tools/editor/icons/source/icon_world_environment.svg)0
-rw-r--r--editor/icons/source/icon_y_sort.svg (renamed from tools/editor/icons/source/icon_y_sort.svg)0
-rw-r--r--editor/icons/source/icon_zoom.svg (renamed from tools/editor/icons/source/icon_zoom.svg)0
-rw-r--r--editor/icons/source/icon_zoom_less.svg (renamed from tools/editor/icons/source/icon_zoom_less.svg)0
-rw-r--r--editor/icons/source/icon_zoom_more.svg (renamed from tools/editor/icons/source/icon_zoom_more.svg)0
-rw-r--r--editor/icons/source/icon_zoom_reset.svg (renamed from tools/editor/icons/source/icon_zoom_reset.svg)0
-rwxr-xr-xeditor/icons/xpmfix.sh (renamed from tools/editor/icons/xpmfix.sh)0
-rw-r--r--editor/import/SCsub (renamed from tools/editor/import/SCsub)0
-rw-r--r--editor/import/editor_import_collada.cpp2508
-rw-r--r--editor/import/editor_import_collada.h51
-rw-r--r--editor/import/resource_importer_csv_translation.cpp154
-rw-r--r--editor/import/resource_importer_csv_translation.h55
-rw-r--r--editor/import/resource_importer_obj.cpp259
-rw-r--r--editor/import/resource_importer_obj.h56
-rw-r--r--editor/import/resource_importer_scene.cpp1356
-rw-r--r--editor/import/resource_importer_scene.h121
-rw-r--r--editor/import/resource_importer_texture.cpp422
-rw-r--r--editor/import/resource_importer_texture.h98
-rw-r--r--editor/import/resource_importer_wav.cpp647
-rw-r--r--editor/import/resource_importer_wav.h58
-rw-r--r--editor/import_dock.cpp359
-rw-r--r--editor/import_dock.h70
-rw-r--r--editor/inspector_dock.cpp (renamed from tools/editor/inspector_dock.cpp)0
-rw-r--r--editor/inspector_dock.h (renamed from tools/editor/inspector_dock.h)0
-rw-r--r--editor/io_plugins/SCsub (renamed from tools/editor/io_plugins/SCsub)0
-rw-r--r--editor/io_plugins/editor_atlas.cpp (renamed from tools/editor/io_plugins/editor_atlas.cpp)0
-rw-r--r--editor/io_plugins/editor_atlas.h (renamed from tools/editor/io_plugins/editor_atlas.h)0
-rw-r--r--editor/io_plugins/editor_bitmask_import_plugin.cpp387
-rw-r--r--editor/io_plugins/editor_bitmask_import_plugin.h70
-rw-r--r--editor/io_plugins/editor_export_scene.cpp142
-rw-r--r--editor/io_plugins/editor_export_scene.h44
-rw-r--r--editor/io_plugins/editor_font_import_plugin.cpp1704
-rw-r--r--editor/io_plugins/editor_font_import_plugin.h58
-rw-r--r--editor/io_plugins/editor_mesh_import_plugin.cpp593
-rw-r--r--editor/io_plugins/editor_mesh_import_plugin.h59
-rw-r--r--editor/io_plugins/editor_sample_import_plugin.cpp929
-rw-r--r--editor/io_plugins/editor_sample_import_plugin.h74
-rw-r--r--editor/io_plugins/editor_scene_import_plugin.cpp2992
-rw-r--r--editor/io_plugins/editor_scene_import_plugin.h200
-rw-r--r--editor/io_plugins/editor_scene_importer_fbxconv.cpp1136
-rw-r--r--editor/io_plugins/editor_scene_importer_fbxconv.h111
-rw-r--r--editor/io_plugins/editor_texture_import_plugin.cpp1893
-rw-r--r--editor/io_plugins/editor_texture_import_plugin.h179
-rw-r--r--editor/io_plugins/editor_translation_import_plugin.cpp479
-rw-r--r--editor/io_plugins/editor_translation_import_plugin.h56
-rw-r--r--editor/multi_node_edit.cpp191
-rw-r--r--editor/multi_node_edit.h65
-rw-r--r--editor/node_dock.cpp133
-rw-r--r--editor/node_dock.h (renamed from tools/editor/node_dock.h)0
-rw-r--r--editor/output_strings.cpp (renamed from tools/editor/output_strings.cpp)0
-rw-r--r--editor/output_strings.h (renamed from tools/editor/output_strings.h)0
-rw-r--r--editor/pane_drag.cpp (renamed from tools/editor/pane_drag.cpp)0
-rw-r--r--editor/pane_drag.h (renamed from tools/editor/pane_drag.h)0
-rw-r--r--editor/plugins/SCsub (renamed from tools/editor/plugins/SCsub)0
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp1604
-rw-r--r--editor/plugins/animation_player_editor_plugin.h219
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp1536
-rw-r--r--editor/plugins/animation_tree_editor_plugin.h194
-rw-r--r--editor/plugins/baked_light_baker.cpp2731
-rw-r--r--editor/plugins/baked_light_baker.h (renamed from tools/editor/plugins/baked_light_baker.h)0
-rw-r--r--editor/plugins/baked_light_baker_cmpxchg.cpp (renamed from tools/editor/plugins/baked_light_baker_cmpxchg.cpp)0
-rw-r--r--editor/plugins/baked_light_editor_plugin.cpp (renamed from tools/editor/plugins/baked_light_editor_plugin.cpp)0
-rw-r--r--editor/plugins/baked_light_editor_plugin.h120
-rw-r--r--editor/plugins/camera_editor_plugin.cpp150
-rw-r--r--editor/plugins/camera_editor_plugin.h79
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp4063
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h503
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.cpp482
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.h111
-rw-r--r--editor/plugins/collision_polygon_editor_plugin.cpp648
-rw-r--r--editor/plugins/collision_polygon_editor_plugin.h123
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp (renamed from tools/editor/plugins/collision_shape_2d_editor_plugin.cpp)0
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h101
-rw-r--r--editor/plugins/color_ramp_editor_plugin.cpp112
-rw-r--r--editor/plugins/color_ramp_editor_plugin.h62
-rw-r--r--editor/plugins/cube_grid_theme_editor_plugin.cpp357
-rw-r--r--editor/plugins/cube_grid_theme_editor_plugin.h96
-rw-r--r--editor/plugins/editor_preview_plugins.cpp907
-rw-r--r--editor/plugins/editor_preview_plugins.h128
-rw-r--r--editor/plugins/gi_probe_editor_plugin.cpp83
-rw-r--r--editor/plugins/gi_probe_editor_plugin.h65
-rw-r--r--editor/plugins/item_list_editor_plugin.cpp (renamed from tools/editor/plugins/item_list_editor_plugin.cpp)0
-rw-r--r--editor/plugins/item_list_editor_plugin.h230
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.cpp518
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.h115
-rw-r--r--editor/plugins/line_2d_editor_plugin.cpp311
-rw-r--r--editor/plugins/line_2d_editor_plugin.h118
-rw-r--r--editor/plugins/material_editor_plugin.cpp413
-rw-r--r--editor/plugins/material_editor_plugin.h100
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp245
-rw-r--r--editor/plugins/mesh_editor_plugin.h98
-rw-r--r--editor/plugins/mesh_instance_editor_plugin.cpp (renamed from tools/editor/plugins/mesh_instance_editor_plugin.cpp)0
-rw-r--r--editor/plugins/mesh_instance_editor_plugin.h97
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp (renamed from tools/editor/plugins/multimesh_editor_plugin.cpp)0
-rw-r--r--editor/plugins/multimesh_editor_plugin.h107
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.cpp566
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.h118
-rw-r--r--editor/plugins/particles_2d_editor_plugin.cpp199
-rw-r--r--editor/plugins/particles_2d_editor_plugin.h82
-rw-r--r--editor/plugins/particles_editor_plugin.cpp461
-rw-r--r--editor/plugins/particles_editor_plugin.h116
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp718
-rw-r--r--editor/plugins/path_2d_editor_plugin.h126
-rw-r--r--editor/plugins/path_editor_plugin.cpp604
-rw-r--r--editor/plugins/path_editor_plugin.h100
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp1028
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h167
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp507
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.h108
-rw-r--r--editor/plugins/rich_text_editor_plugin.cpp164
-rw-r--r--editor/plugins/rich_text_editor_plugin.h91
-rw-r--r--editor/plugins/sample_editor_plugin.cpp451
-rw-r--r--editor/plugins/sample_editor_plugin.h92
-rw-r--r--editor/plugins/sample_library_editor_plugin.cpp546
-rw-r--r--editor/plugins/sample_library_editor_plugin.h108
-rw-r--r--editor/plugins/sample_player_editor_plugin.cpp203
-rw-r--r--editor/plugins/sample_player_editor_plugin.h90
-rw-r--r--editor/plugins/script_editor_plugin.cpp2491
-rw-r--r--editor/plugins/script_editor_plugin.h394
-rw-r--r--editor/plugins/script_text_editor.cpp1401
-rw-r--r--editor/plugins/script_text_editor.h (renamed from tools/editor/plugins/script_text_editor.h)0
-rw-r--r--editor/plugins/shader_editor_plugin.cpp584
-rw-r--r--editor/plugins/shader_editor_plugin.h156
-rw-r--r--editor/plugins/shader_graph_editor_plugin.cpp2948
-rw-r--r--editor/plugins/shader_graph_editor_plugin.h242
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp4131
-rw-r--r--editor/plugins/spatial_editor_plugin.h574
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp969
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h138
-rw-r--r--editor/plugins/stream_editor_plugin.cpp149
-rw-r--r--editor/plugins/stream_editor_plugin.h84
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp (renamed from tools/editor/plugins/style_box_editor_plugin.cpp)0
-rw-r--r--editor/plugins/style_box_editor_plugin.h83
-rw-r--r--editor/plugins/texture_editor_plugin.cpp169
-rw-r--r--editor/plugins/texture_editor_plugin.h77
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp1012
-rw-r--r--editor/plugins/texture_region_editor_plugin.h153
-rw-r--r--editor/plugins/theme_editor_plugin.cpp (renamed from tools/editor/plugins/theme_editor_plugin.cpp)0
-rw-r--r--editor/plugins/theme_editor_plugin.h125
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp1593
-rw-r--r--editor/plugins/tile_map_editor_plugin.h207
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp (renamed from tools/editor/plugins/tile_set_editor_plugin.cpp)0
-rw-r--r--editor/plugins/tile_set_editor_plugin.h101
-rw-r--r--editor/progress_dialog.cpp (renamed from tools/editor/progress_dialog.cpp)0
-rw-r--r--editor/progress_dialog.h (renamed from tools/editor/progress_dialog.h)0
-rw-r--r--editor/project_export.cpp828
-rw-r--r--editor/project_export.h142
-rw-r--r--editor/project_manager.cpp1516
-rw-r--r--editor/project_manager.h148
-rw-r--r--editor/project_settings.cpp1603
-rw-r--r--editor/project_settings.h164
-rw-r--r--editor/property_editor.cpp4960
-rw-r--r--editor/property_editor.h352
-rw-r--r--editor/property_selector.cpp626
-rw-r--r--editor/property_selector.h83
-rw-r--r--editor/pvrtc_compress.cpp (renamed from tools/editor/pvrtc_compress.cpp)0
-rw-r--r--editor/pvrtc_compress.h (renamed from tools/editor/pvrtc_compress.h)0
-rw-r--r--editor/quick_open.cpp285
-rw-r--r--editor/quick_open.h (renamed from tools/editor/quick_open.h)0
-rw-r--r--editor/register_exporters.h (renamed from tools/editor/register_exporters.h)0
-rw-r--r--editor/reparent_dialog.cpp (renamed from tools/editor/reparent_dialog.cpp)0
-rw-r--r--editor/reparent_dialog.h68
-rw-r--r--editor/resources_dock.cpp409
-rw-r--r--editor/resources_dock.h (renamed from tools/editor/resources_dock.h)0
-rw-r--r--editor/run_settings_dialog.cpp (renamed from tools/editor/run_settings_dialog.cpp)0
-rw-r--r--editor/run_settings_dialog.h (renamed from tools/editor/run_settings_dialog.h)0
-rw-r--r--editor/scene_tree_dock.cpp2061
-rw-r--r--editor/scene_tree_dock.h (renamed from tools/editor/scene_tree_dock.h)0
-rw-r--r--editor/scene_tree_editor.cpp1316
-rw-r--r--editor/scene_tree_editor.h (renamed from tools/editor/scene_tree_editor.h)0
-rw-r--r--editor/script_create_dialog.cpp437
-rw-r--r--editor/script_create_dialog.h79
-rw-r--r--editor/script_editor_debugger.cpp1998
-rw-r--r--editor/script_editor_debugger.h (renamed from tools/editor/script_editor_debugger.h)0
-rw-r--r--editor/settings_config_dialog.cpp415
-rw-r--r--editor/settings_config_dialog.h (renamed from tools/editor/settings_config_dialog.h)0
-rw-r--r--editor/spatial_editor_gizmos.cpp3483
-rw-r--r--editor/spatial_editor_gizmos.h521
-rw-r--r--editor/translations/Makefile20
-rw-r--r--editor/translations/README.md (renamed from tools/editor/translations/README.md)0
-rw-r--r--editor/translations/ar.po (renamed from tools/editor/translations/ar.po)0
-rw-r--r--editor/translations/bg.po (renamed from tools/editor/translations/bg.po)0
-rw-r--r--editor/translations/bn.po (renamed from tools/editor/translations/bn.po)0
-rw-r--r--editor/translations/ca.po (renamed from tools/editor/translations/ca.po)0
-rw-r--r--editor/translations/cs.po (renamed from tools/editor/translations/cs.po)0
-rw-r--r--editor/translations/da.po (renamed from tools/editor/translations/da.po)0
-rw-r--r--editor/translations/de.po (renamed from tools/editor/translations/de.po)0
-rw-r--r--editor/translations/de_CH.po (renamed from tools/editor/translations/de_CH.po)0
-rw-r--r--editor/translations/editor.pot (renamed from tools/editor/translations/tools.pot)0
-rw-r--r--editor/translations/es.po (renamed from tools/editor/translations/es.po)0
-rw-r--r--editor/translations/es_AR.po (renamed from tools/editor/translations/es_AR.po)0
-rwxr-xr-xeditor/translations/extract.py121
-rw-r--r--editor/translations/fa.po (renamed from tools/editor/translations/fa.po)0
-rw-r--r--editor/translations/fr.po (renamed from tools/editor/translations/fr.po)0
-rw-r--r--editor/translations/hu.po (renamed from tools/editor/translations/hu.po)0
-rw-r--r--editor/translations/id.po (renamed from tools/editor/translations/id.po)0
-rw-r--r--editor/translations/it.po (renamed from tools/editor/translations/it.po)0
-rw-r--r--editor/translations/ja.po (renamed from tools/editor/translations/ja.po)0
-rw-r--r--editor/translations/ko.po (renamed from tools/editor/translations/ko.po)0
-rw-r--r--editor/translations/nb.po (renamed from tools/editor/translations/nb.po)0
-rw-r--r--editor/translations/pl.po (renamed from tools/editor/translations/pl.po)0
-rw-r--r--editor/translations/pr.po (renamed from tools/editor/translations/pr.po)0
-rw-r--r--editor/translations/pt_BR.po (renamed from tools/editor/translations/pt_BR.po)0
-rw-r--r--editor/translations/pt_PT.po (renamed from tools/editor/translations/pt_PT.po)0
-rw-r--r--editor/translations/ru.po (renamed from tools/editor/translations/ru.po)0
-rw-r--r--editor/translations/sk.po (renamed from tools/editor/translations/sk.po)0
-rw-r--r--editor/translations/sl.po (renamed from tools/editor/translations/sl.po)0
-rw-r--r--editor/translations/tr.po (renamed from tools/editor/translations/tr.po)0
-rw-r--r--editor/translations/ur_PK.po (renamed from tools/editor/translations/ur_PK.po)0
-rw-r--r--editor/translations/zh_CN.po (renamed from tools/editor/translations/zh_CN.po)0
-rw-r--r--editor/translations/zh_HK.po (renamed from tools/editor/translations/zh_HK.po)0
-rw-r--r--editor/translations/zh_TW.po (renamed from tools/editor/translations/zh_TW.po)0
-rw-r--r--main/input_default.cpp9
-rw-r--r--main/input_default.h7
-rw-r--r--main/main.cpp19
-rw-r--r--main/performance.cpp2
-rw-r--r--main/tests/test_containers.cpp3
-rw-r--r--main/tests/test_containers.h2
-rw-r--r--main/tests/test_gdscript.cpp2
-rw-r--r--main/tests/test_gdscript.h2
-rw-r--r--main/tests/test_gui.cpp2
-rw-r--r--main/tests/test_gui.h2
-rw-r--r--main/tests/test_image.cpp4
-rw-r--r--main/tests/test_image.h2
-rw-r--r--main/tests/test_io.cpp4
-rw-r--r--main/tests/test_io.h2
-rw-r--r--main/tests/test_main.cpp2
-rw-r--r--main/tests/test_main.h2
-rw-r--r--main/tests/test_math.cpp7
-rw-r--r--main/tests/test_math.h2
-rw-r--r--main/tests/test_physics.cpp2
-rw-r--r--main/tests/test_physics.h2
-rw-r--r--main/tests/test_physics_2d.cpp7
-rw-r--r--main/tests/test_physics_2d.h2
-rw-r--r--main/tests/test_render.cpp3
-rw-r--r--main/tests/test_render.h2
-rw-r--r--main/tests/test_shader_lang.cpp2
-rw-r--r--main/tests/test_shader_lang.h2
-rw-r--r--main/tests/test_sound.cpp2
-rw-r--r--main/tests/test_sound.h2
-rw-r--r--main/tests/test_string.cpp3
-rw-r--r--main/tests/test_string.h2
-rwxr-xr-xmisc/dist/appimage/AppRun3
-rw-r--r--misc/dist/appimage/godot.desktop9
-rw-r--r--misc/dist/appimage/godot.pngbin0 -> 12525 bytes
-rw-r--r--modules/cscript/godot_c.cpp28
-rw-r--r--modules/cscript/godot_c.h28
-rw-r--r--modules/dds/texture_loader_dds.cpp10
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp12
-rw-r--r--modules/etc1/texture_loader_pkm.cpp29
-rw-r--r--modules/etc1/texture_loader_pkm.h28
-rw-r--r--modules/gdscript/gd_compiler.h2
-rw-r--r--modules/gdscript/gd_editor.cpp13
-rw-r--r--modules/gdscript/gd_function.cpp37
-rw-r--r--modules/gdscript/gd_function.h28
-rw-r--r--modules/gdscript/gd_parser.cpp54
-rw-r--r--modules/gdscript/gd_script.cpp10
-rw-r--r--modules/gdscript/gd_tokenizer.cpp6
-rw-r--r--modules/gdscript/gd_tokenizer.h2
-rw-r--r--modules/gdscript/register_types.cpp6
-rw-r--r--modules/gridmap/config.py3
-rw-r--r--modules/gridmap/grid_map.cpp597
-rw-r--r--modules/gridmap/grid_map.h22
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp98
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h15
-rw-r--r--modules/openssl/stream_peer_openssl.h2
-rw-r--r--modules/regex/regex.cpp36
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.cpp42
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.h28
-rw-r--r--modules/stb_vorbis/resource_importer_ogg_vorbis.cpp28
-rw-r--r--modules/stb_vorbis/resource_importer_ogg_vorbis.h28
-rw-r--r--modules/theora/video_stream_theora.cpp2
-rw-r--r--modules/theora/yuv2rgb.h3
-rw-r--r--modules/visual_script/visual_script.cpp145
-rw-r--r--modules/visual_script/visual_script.h28
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp37
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.h28
-rw-r--r--modules/visual_script/visual_script_editor.cpp33
-rw-r--r--modules/visual_script/visual_script_editor.h44
-rw-r--r--modules/visual_script/visual_script_expression.cpp34
-rw-r--r--modules/visual_script/visual_script_expression.h28
-rw-r--r--modules/visual_script/visual_script_flow_control.cpp61
-rw-r--r--modules/visual_script/visual_script_flow_control.h28
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp199
-rw-r--r--modules/visual_script/visual_script_func_nodes.h28
-rw-r--r--modules/visual_script/visual_script_nodes.cpp217
-rw-r--r--modules/visual_script/visual_script_nodes.h32
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp65
-rw-r--r--modules/visual_script/visual_script_yield_nodes.h28
-rw-r--r--modules/webm/video_stream_webm.cpp2
-rw-r--r--modules/webp/SCsub188
-rw-r--r--platform/android/SCsub1
-rw-r--r--platform/android/audio_driver_jandroid.cpp2
-rw-r--r--platform/android/export/export.cpp14
-rw-r--r--platform/android/globals/global_defaults.cpp2
-rw-r--r--platform/android/godot_android.cpp2
-rw-r--r--platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java49
-rw-r--r--platform/android/java_class_wrapper.cpp2
-rw-r--r--platform/android/java_glue.cpp2
-rw-r--r--platform/android/os_android.cpp4
-rw-r--r--platform/android/os_android.h3
-rw-r--r--platform/android/power_android.cpp238
-rw-r--r--platform/android/power_android.h82
-rw-r--r--platform/bb10/export/export.cpp16
-rw-r--r--platform/bb10/os_bb10.cpp16
-rw-r--r--platform/bb10/os_bb10.h6
-rw-r--r--platform/bb10/payment_service.cpp8
-rw-r--r--platform/bb10/power_bb10.cpp76
-rw-r--r--platform/bb10/power_bb10.h49
-rw-r--r--platform/haiku/audio_driver_media_kit.cpp2
-rw-r--r--platform/haiku/os_haiku.cpp2
-rw-r--r--platform/haiku/os_haiku.h6
-rw-r--r--platform/haiku/power_haiku.cpp74
-rw-r--r--platform/haiku/power_haiku.h49
-rw-r--r--platform/iphone/Appirater.h200
-rw-r--r--platform/iphone/Appirater.m732
-rw-r--r--platform/iphone/AppiraterDelegate.h23
-rw-r--r--platform/iphone/SCsub5
-rw-r--r--platform/iphone/app_delegate.mm11
-rw-r--r--platform/iphone/detect.py1
-rw-r--r--platform/iphone/game_center.mm24
-rwxr-xr-xplatform/iphone/gl_view.mm2
-rwxr-xr-xplatform/iphone/globals/global_defaults.cpp2
-rw-r--r--platform/iphone/icloud.mm16
-rw-r--r--platform/iphone/in_app_store.mm12
-rw-r--r--platform/iphone/ios.mm2
-rw-r--r--platform/iphone/os_iphone.cpp2
-rw-r--r--platform/iphone/power_iphone.cpp71
-rw-r--r--platform/iphone/power_iphone.h50
-rw-r--r--platform/iphone/rasterizer_iphone.cpp2
-rw-r--r--platform/javascript/SCsub41
-rw-r--r--platform/javascript/audio_server_javascript.cpp3
-rw-r--r--platform/javascript/audio_server_javascript.h3
-rw-r--r--platform/javascript/detect.py52
-rw-r--r--platform/javascript/export/export.cpp16
-rw-r--r--platform/javascript/javascript_eval.cpp2
-rw-r--r--platform/javascript/javascript_main.cpp7
-rw-r--r--platform/javascript/os_javascript.cpp19
-rw-r--r--platform/javascript/os_javascript.h7
-rw-r--r--platform/javascript/power_javascript.cpp76
-rw-r--r--platform/javascript/power_javascript.h51
-rw-r--r--platform/osx/SCsub1
-rw-r--r--platform/osx/detect.py1
-rw-r--r--platform/osx/export/export.cpp16
-rw-r--r--platform/osx/joypad_osx.cpp17
-rw-r--r--platform/osx/joypad_osx.h3
-rw-r--r--platform/osx/os_osx.h7
-rw-r--r--platform/osx/os_osx.mm18
-rw-r--r--platform/osx/power_osx.cpp233
-rw-r--r--platform/osx/power_osx.h57
-rw-r--r--platform/server/os_server.cpp12
-rw-r--r--platform/server/os_server.h7
-rw-r--r--platform/uwp/export/export.cpp13
-rw-r--r--platform/uwp/os_uwp.cpp17
-rw-r--r--platform/uwp/os_uwp.h8
-rw-r--r--platform/windows/SCsub1
-rw-r--r--platform/windows/export/export.cpp9
-rw-r--r--platform/windows/joypad.cpp14
-rw-r--r--platform/windows/joypad.h1
-rw-r--r--platform/windows/os_windows.cpp45
-rw-r--r--platform/windows/os_windows.h10
-rw-r--r--platform/windows/packet_peer_udp_winsock.cpp35
-rw-r--r--platform/windows/packet_peer_udp_winsock.h3
-rw-r--r--platform/windows/power_windows.cpp108
-rw-r--r--platform/windows/power_windows.h57
-rw-r--r--platform/windows/stream_peer_winsock.cpp21
-rw-r--r--platform/windows/stream_peer_winsock.h4
-rw-r--r--platform/windows/tcp_server_winsock.cpp21
-rw-r--r--platform/windows/tcp_server_winsock.h3
-rw-r--r--platform/x11/SCsub1
-rw-r--r--platform/x11/export/export.cpp23
-rw-r--r--platform/x11/godot_x11.cpp10
-rw-r--r--platform/x11/joypad_linux.cpp11
-rw-r--r--platform/x11/joypad_linux.h1
-rw-r--r--platform/x11/os_x11.cpp19
-rw-r--r--platform/x11/os_x11.h7
-rw-r--r--platform/x11/power_x11.cpp575
-rw-r--r--platform/x11/power_x11.h68
-rw-r--r--prop_renames.txt524
-rw-r--r--scene/2d/animated_sprite.cpp98
-rw-r--r--scene/2d/area_2d.cpp113
-rw-r--r--scene/2d/back_buffer_copy.cpp12
-rw-r--r--scene/2d/camera_2d.cpp116
-rw-r--r--scene/2d/canvas_item.cpp194
-rw-r--r--scene/2d/canvas_modulate.cpp6
-rw-r--r--scene/2d/collision_object_2d.cpp32
-rw-r--r--scene/2d/collision_polygon_2d.cpp30
-rw-r--r--scene/2d/collision_shape_2d.cpp24
-rw-r--r--scene/2d/joints_2d.cpp66
-rw-r--r--scene/2d/light_2d.cpp120
-rw-r--r--scene/2d/light_occluder_2d.cpp30
-rw-r--r--scene/2d/line_2d.cpp336
-rw-r--r--scene/2d/line_2d.h108
-rw-r--r--scene/2d/line_builder.cpp591
-rw-r--r--scene/2d/line_builder.h104
-rw-r--r--scene/2d/navigation2d.cpp12
-rw-r--r--scene/2d/navigation_polygon.cpp66
-rw-r--r--scene/2d/node_2d.cpp94
-rw-r--r--scene/2d/parallax_background.cpp38
-rw-r--r--scene/2d/parallax_layer.cpp18
-rw-r--r--scene/2d/particles_2d.cpp250
-rw-r--r--scene/2d/particles_2d.h14
-rw-r--r--scene/2d/path_2d.cpp36
-rw-r--r--scene/2d/physics_body_2d.cpp230
-rw-r--r--scene/2d/polygon_2d.cpp70
-rw-r--r--scene/2d/ray_cast_2d.cpp52
-rw-r--r--scene/2d/remote_transform_2d.cpp6
-rw-r--r--scene/2d/screen_button.cpp249
-rw-r--r--scene/2d/screen_button.h15
-rw-r--r--scene/2d/sprite.cpp84
-rw-r--r--scene/2d/tile_map.cpp159
-rw-r--r--scene/2d/tile_map.h7
-rw-r--r--scene/2d/visibility_notifier_2d.cpp26
-rw-r--r--scene/2d/y_sort.cpp6
-rw-r--r--scene/3d/area.cpp100
-rw-r--r--scene/3d/baked_light_instance.cpp46
-rw-r--r--scene/3d/body_shape.cpp26
-rw-r--r--scene/3d/bone_attachment.cpp4
-rw-r--r--scene/3d/camera.cpp56
-rw-r--r--scene/3d/character_camera.cpp48
-rw-r--r--scene/3d/collision_object.cpp37
-rw-r--r--scene/3d/collision_polygon.cpp30
-rw-r--r--scene/3d/gi_probe.cpp267
-rw-r--r--scene/3d/gi_probe.h35
-rw-r--r--scene/3d/immediate_geometry.cpp20
-rw-r--r--scene/3d/interpolated_camera.cpp20
-rw-r--r--scene/3d/light.cpp98
-rw-r--r--scene/3d/listener.cpp36
-rw-r--r--scene/3d/listener.h28
-rw-r--r--scene/3d/mesh_instance.cpp18
-rw-r--r--scene/3d/multimesh_instance.cpp6
-rw-r--r--scene/3d/navigation.cpp22
-rw-r--r--scene/3d/navigation_mesh.cpp32
-rw-r--r--scene/3d/particles.cpp132
-rw-r--r--scene/3d/path.cpp36
-rw-r--r--scene/3d/physics_body.cpp214
-rw-r--r--scene/3d/physics_joint.cpp348
-rw-r--r--scene/3d/portal.cpp22
-rw-r--r--scene/3d/proximity_group.cpp16
-rw-r--r--scene/3d/quad.cpp24
-rw-r--r--scene/3d/ray_cast.cpp46
-rw-r--r--scene/3d/reflection_probe.cpp100
-rw-r--r--scene/3d/reflection_probe.h28
-rw-r--r--scene/3d/remote_transform.cpp6
-rw-r--r--scene/3d/remote_transform.h28
-rw-r--r--scene/3d/room_instance.cpp8
-rw-r--r--scene/3d/scenario_fx.cpp6
-rw-r--r--scene/3d/skeleton.cpp46
-rw-r--r--scene/3d/spatial.cpp110
-rw-r--r--scene/3d/spatial_indexer.cpp2
-rw-r--r--scene/3d/sprite_3d.cpp148
-rw-r--r--scene/3d/vehicle_body.cpp94
-rw-r--r--scene/3d/visibility_notifier.cpp18
-rw-r--r--scene/3d/visual_instance.cpp70
-rw-r--r--scene/animation/animation_cache.cpp4
-rw-r--r--scene/animation/animation_player.cpp111
-rw-r--r--scene/animation/animation_tree_player.cpp132
-rw-r--r--scene/animation/tween.cpp76
-rw-r--r--scene/animation/tween_interpolaters.cpp3
-rw-r--r--scene/audio/audio_player.cpp76
-rw-r--r--scene/audio/audio_player.h28
-rw-r--r--scene/gui/base_button.cpp56
-rw-r--r--scene/gui/box_container.cpp8
-rw-r--r--scene/gui/button.cpp30
-rw-r--r--scene/gui/button_array.cpp52
-rw-r--r--scene/gui/button_array.h1
-rw-r--r--scene/gui/button_group.cpp12
-rw-r--r--scene/gui/center_container.cpp6
-rw-r--r--scene/gui/color_picker.cpp52
-rw-r--r--scene/gui/color_ramp_edit.cpp4
-rw-r--r--scene/gui/color_rect.cpp6
-rw-r--r--scene/gui/container.cpp8
-rw-r--r--scene/gui/control.cpp242
-rw-r--r--scene/gui/dialogs.cpp285
-rw-r--r--scene/gui/dialogs.h20
-rw-r--r--scene/gui/file_dialog.cpp88
-rw-r--r--scene/gui/graph_edit.cpp56
-rw-r--r--scene/gui/graph_node.cpp90
-rw-r--r--scene/gui/grid_container.cpp6
-rw-r--r--scene/gui/input_action.cpp40
-rw-r--r--scene/gui/input_action.h28
-rw-r--r--scene/gui/item_list.cpp122
-rw-r--r--scene/gui/item_list.h1
-rw-r--r--scene/gui/label.cpp68
-rw-r--r--scene/gui/line_edit.cpp86
-rw-r--r--scene/gui/link_button.cpp12
-rw-r--r--scene/gui/menu_button.cpp10
-rw-r--r--scene/gui/option_button.cpp58
-rw-r--r--scene/gui/patch_9_rect.cpp30
-rw-r--r--scene/gui/popup.cpp22
-rw-r--r--scene/gui/popup.h4
-rw-r--r--scene/gui/popup_menu.cpp116
-rw-r--r--scene/gui/progress_bar.cpp6
-rw-r--r--scene/gui/range.cpp52
-rw-r--r--scene/gui/rich_text_label.cpp127
-rw-r--r--scene/gui/rich_text_label.h4
-rw-r--r--scene/gui/scroll_bar.cpp12
-rw-r--r--scene/gui/scroll_container.cpp26
-rw-r--r--scene/gui/slider.cpp16
-rw-r--r--scene/gui/spin_box.cpp38
-rw-r--r--scene/gui/split_container.cpp20
-rw-r--r--scene/gui/tab_container.cpp803
-rw-r--r--scene/gui/tab_container.h9
-rw-r--r--scene/gui/tabs.cpp70
-rw-r--r--scene/gui/tabs.h4
-rw-r--r--scene/gui/text_edit.cpp163
-rw-r--r--scene/gui/texture_button.cpp174
-rw-r--r--scene/gui/texture_button.h26
-rw-r--r--scene/gui/texture_progress.cpp42
-rw-r--r--scene/gui/texture_rect.cpp30
-rw-r--r--scene/gui/texture_rect.h2
-rw-r--r--scene/gui/tree.cpp188
-rw-r--r--scene/gui/tree.h1
-rw-r--r--scene/gui/video_player.cpp58
-rw-r--r--scene/gui/viewport_container.cpp37
-rw-r--r--scene/gui/viewport_container.h28
-rw-r--r--scene/io/resource_format_image.cpp2
-rw-r--r--scene/main/canvas_layer.cpp46
-rw-r--r--scene/main/http_request.cpp41
-rw-r--r--scene/main/http_request.h1
-rw-r--r--scene/main/instance_placeholder.cpp6
-rw-r--r--scene/main/node.cpp230
-rw-r--r--scene/main/node.h14
-rw-r--r--scene/main/resource_preloader.cpp18
-rw-r--r--scene/main/scene_main_loop.cpp113
-rw-r--r--scene/main/scene_main_loop.h7
-rw-r--r--scene/main/timer.cpp34
-rw-r--r--scene/main/viewport.cpp184
-rw-r--r--scene/register_scene_types.cpp5
-rw-r--r--scene/resources/animation.cpp80
-rw-r--r--scene/resources/audio_stream_resampled.cpp2
-rw-r--r--scene/resources/audio_stream_sample.cpp70
-rw-r--r--scene/resources/audio_stream_sample.h28
-rw-r--r--scene/resources/bit_mask.cpp20
-rw-r--r--scene/resources/bounds.cpp6
-rw-r--r--scene/resources/box_shape.cpp6
-rw-r--r--scene/resources/capsule_shape.cpp12
-rw-r--r--scene/resources/capsule_shape_2d.cpp12
-rw-r--r--scene/resources/circle_shape_2d.cpp6
-rw-r--r--scene/resources/color_ramp.cpp36
-rw-r--r--scene/resources/concave_polygon_shape.cpp4
-rw-r--r--scene/resources/concave_polygon_shape_2d.cpp6
-rw-r--r--scene/resources/convex_polygon_shape.cpp6
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp8
-rw-r--r--scene/resources/curve.cpp162
-rw-r--r--scene/resources/default_theme/default_theme.cpp33
-rw-r--r--scene/resources/default_theme/theme_data.h4
-rw-r--r--scene/resources/dynamic_font.cpp52
-rw-r--r--scene/resources/dynamic_font_stb.cpp40
-rw-r--r--scene/resources/dynamic_font_stb.h28
-rw-r--r--scene/resources/environment.cpp356
-rw-r--r--scene/resources/font.cpp70
-rw-r--r--scene/resources/gibberish_stream.cpp24
-rw-r--r--scene/resources/material.cpp248
-rw-r--r--scene/resources/mesh.cpp54
-rw-r--r--scene/resources/mesh_data_tool.cpp76
-rw-r--r--scene/resources/mesh_library.cpp26
-rw-r--r--scene/resources/multimesh.cpp56
-rw-r--r--scene/resources/packed_scene.cpp66
-rw-r--r--scene/resources/packed_scene.h4
-rw-r--r--scene/resources/plane_shape.cpp6
-rw-r--r--scene/resources/polygon_path_finder.cpp26
-rw-r--r--scene/resources/ray_shape.cpp6
-rw-r--r--scene/resources/rectangle_shape_2d.cpp6
-rw-r--r--scene/resources/room.cpp8
-rw-r--r--scene/resources/scene_format_text.cpp2
-rw-r--r--scene/resources/segment_shape_2d.cpp18
-rw-r--r--scene/resources/shader.cpp16
-rw-r--r--scene/resources/shader_graph.cpp154
-rw-r--r--scene/resources/shape_2d.cpp16
-rw-r--r--scene/resources/shape_line_2d.cpp12
-rw-r--r--scene/resources/sky_box.cpp50
-rw-r--r--scene/resources/sky_box.h28
-rw-r--r--scene/resources/space_2d.cpp6
-rw-r--r--scene/resources/sphere_shape.cpp6
-rw-r--r--scene/resources/style_box.cpp114
-rw-r--r--scene/resources/surface_tool.cpp38
-rw-r--r--scene/resources/texture.cpp141
-rw-r--r--scene/resources/texture.h4
-rw-r--r--scene/resources/theme.cpp62
-rw-r--r--scene/resources/tile_set.cpp62
-rw-r--r--scene/resources/world.cpp12
-rw-r--r--scene/resources/world_2d.cpp12
-rw-r--r--scene/resources/world_2d.h2
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--scene/scene_string_names.h1
-rw-r--r--servers/audio/audio_driver_dummy.cpp2
-rw-r--r--servers/audio/audio_effect.cpp28
-rw-r--r--servers/audio/audio_effect.h28
-rw-r--r--servers/audio/effects/audio_effect_amplify.cpp34
-rw-r--r--servers/audio/effects/audio_effect_amplify.h28
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp118
-rw-r--r--servers/audio/effects/audio_effect_chorus.h28
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp70
-rw-r--r--servers/audio/effects/audio_effect_compressor.h28
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp106
-rw-r--r--servers/audio/effects/audio_effect_delay.h34
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp58
-rw-r--r--servers/audio/effects/audio_effect_distortion.h28
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp34
-rw-r--r--servers/audio/effects/audio_effect_eq.h28
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp52
-rw-r--r--servers/audio/effects/audio_effect_filter.h28
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp52
-rw-r--r--servers/audio/effects/audio_effect_limiter.h28
-rw-r--r--servers/audio/effects/audio_effect_panner.cpp34
-rw-r--r--servers/audio/effects/audio_effect_panner.h28
-rw-r--r--servers/audio/effects/audio_effect_phaser.cpp58
-rw-r--r--servers/audio/effects/audio_effect_phaser.h28
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp44
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.h28
-rw-r--r--servers/audio/effects/audio_effect_reverb.cpp76
-rw-r--r--servers/audio/effects/audio_effect_reverb.h28
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.cpp46
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.h28
-rw-r--r--servers/audio/effects/eq.cpp42
-rw-r--r--servers/audio/effects/eq.h40
-rw-r--r--servers/audio/effects/reverb.cpp39
-rw-r--r--servers/audio/effects/reverb.h40
-rw-r--r--servers/audio_server.cpp66
-rw-r--r--servers/physics/area_pair_sw.cpp8
-rw-r--r--servers/physics/area_pair_sw.h8
-rw-r--r--servers/physics/area_sw.h30
-rw-r--r--servers/physics/body_pair_sw.cpp18
-rw-r--r--servers/physics/body_pair_sw.h6
-rw-r--r--servers/physics/body_sw.cpp20
-rw-r--r--servers/physics/body_sw.h22
-rw-r--r--servers/physics/collision_solver_sat.cpp42
-rw-r--r--servers/physics/collision_solver_sat.h2
-rw-r--r--servers/physics/collision_solver_sw.cpp18
-rw-r--r--servers/physics/collision_solver_sw.h4
-rw-r--r--servers/physics/constraint_sw.h4
-rw-r--r--servers/physics/joints/cone_twist_joint_sw.cpp6
-rw-r--r--servers/physics/joints/cone_twist_joint_sw.h8
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.cpp56
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.h8
-rw-r--r--servers/physics/joints/hinge_joint_sw.cpp8
-rw-r--r--servers/physics/joints/hinge_joint_sw.h8
-rw-r--r--servers/physics/joints/pin_joint_sw.cpp8
-rw-r--r--servers/physics/joints/pin_joint_sw.h8
-rw-r--r--servers/physics/joints/slider_joint_sw.cpp6
-rw-r--r--servers/physics/joints/slider_joint_sw.h8
-rw-r--r--servers/physics/physics_server_sw.cpp36
-rw-r--r--servers/physics/physics_server_sw.h30
-rw-r--r--servers/physics/shape_sw.cpp108
-rw-r--r--servers/physics/shape_sw.h40
-rw-r--r--servers/physics/space_sw.cpp24
-rw-r--r--servers/physics/space_sw.h18
-rw-r--r--servers/physics/step_sw.cpp8
-rw-r--r--servers/physics/step_sw.h8
-rw-r--r--servers/physics_2d/area_2d_sw.h30
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp8
-rw-r--r--servers/physics_2d/area_pair_2d_sw.h8
-rw-r--r--servers/physics_2d/body_2d_sw.cpp10
-rw-r--r--servers/physics_2d/body_2d_sw.h24
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp12
-rw-r--r--servers/physics_2d/body_pair_2d_sw.h8
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp2
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp42
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.h2
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp8
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.h4
-rw-r--r--servers/physics_2d/constraint_2d_sw.h4
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp18
-rw-r--r--servers/physics_2d/joints_2d_sw.h16
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp28
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h22
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.cpp4
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h24
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp42
-rw-r--r--servers/physics_2d/shape_2d_sw.h26
-rw-r--r--servers/physics_2d/space_2d_sw.cpp60
-rw-r--r--servers/physics_2d/space_2d_sw.h18
-rw-r--r--servers/physics_2d/step_2d_sw.cpp8
-rw-r--r--servers/physics_2d/step_2d_sw.h8
-rw-r--r--servers/physics_2d_server.cpp310
-rw-r--r--servers/physics_server.cpp344
-rw-r--r--servers/register_server_types.cpp2
-rw-r--r--servers/visual/rasterizer.h5
-rw-r--r--servers/visual/shader_language.cpp4
-rw-r--r--servers/visual/shader_types.cpp28
-rw-r--r--servers/visual/shader_types.h28
-rw-r--r--servers/visual/visual_server_canvas.cpp28
-rw-r--r--servers/visual/visual_server_canvas.h28
-rw-r--r--servers/visual/visual_server_global.cpp28
-rw-r--r--servers/visual/visual_server_global.h28
-rw-r--r--servers/visual/visual_server_light_baker.cpp28
-rw-r--r--servers/visual/visual_server_light_baker.h28
-rw-r--r--servers/visual/visual_server_raster.cpp2
-rw-r--r--servers/visual/visual_server_raster.h3
-rw-r--r--servers/visual/visual_server_scene.cpp36
-rw-r--r--servers/visual/visual_server_scene.h28
-rw-r--r--servers/visual/visual_server_viewport.cpp30
-rw-r--r--servers/visual/visual_server_viewport.h28
-rw-r--r--servers/visual_server.cpp24
-rw-r--r--servers/visual_server.h3
-rw-r--r--thirdparty/README.md6
-rw-r--r--thirdparty/libwebp/dec/alpha.c232
-rw-r--r--thirdparty/libwebp/dec/alpha_dec.c232
-rw-r--r--thirdparty/libwebp/dec/alphai.h54
-rw-r--r--thirdparty/libwebp/dec/alphai_dec.h54
-rw-r--r--thirdparty/libwebp/dec/buffer.c300
-rw-r--r--thirdparty/libwebp/dec/buffer_dec.c300
-rw-r--r--thirdparty/libwebp/dec/common_dec.h (renamed from thirdparty/libwebp/dec/common.h)0
-rw-r--r--thirdparty/libwebp/dec/frame.c812
-rw-r--r--thirdparty/libwebp/dec/frame_dec.c812
-rw-r--r--thirdparty/libwebp/dec/idec.c892
-rw-r--r--thirdparty/libwebp/dec/idec_dec.c892
-rw-r--r--thirdparty/libwebp/dec/io.c624
-rw-r--r--thirdparty/libwebp/dec/io_dec.c645
-rw-r--r--thirdparty/libwebp/dec/quant.c110
-rw-r--r--thirdparty/libwebp/dec/quant_dec.c110
-rw-r--r--thirdparty/libwebp/dec/tree.c525
-rw-r--r--thirdparty/libwebp/dec/tree_dec.c528
-rw-r--r--thirdparty/libwebp/dec/vp8.c667
-rw-r--r--thirdparty/libwebp/dec/vp8_dec.c721
-rw-r--r--thirdparty/libwebp/dec/vp8_dec.h (renamed from thirdparty/libwebp/dec/decode_vp8.h)0
-rw-r--r--thirdparty/libwebp/dec/vp8i.h320
-rw-r--r--thirdparty/libwebp/dec/vp8i_dec.h320
-rw-r--r--thirdparty/libwebp/dec/vp8l.c1660
-rw-r--r--thirdparty/libwebp/dec/vp8l_dec.c1671
-rw-r--r--thirdparty/libwebp/dec/vp8li.h135
-rw-r--r--thirdparty/libwebp/dec/vp8li_dec.h135
-rw-r--r--thirdparty/libwebp/dec/webp.c846
-rw-r--r--thirdparty/libwebp/dec/webp_dec.c843
-rw-r--r--thirdparty/libwebp/dec/webpi.h142
-rw-r--r--thirdparty/libwebp/dec/webpi_dec.h133
-rw-r--r--thirdparty/libwebp/demux/demux.c5
-rw-r--r--thirdparty/libwebp/dsp/alpha_processing.c38
-rw-r--r--thirdparty/libwebp/dsp/alpha_processing_neon.c191
-rw-r--r--thirdparty/libwebp/dsp/alpha_processing_sse2.c141
-rw-r--r--thirdparty/libwebp/dsp/common_sse2.h85
-rw-r--r--thirdparty/libwebp/dsp/cost.c2
-rw-r--r--thirdparty/libwebp/dsp/cost_mips32.c2
-rw-r--r--thirdparty/libwebp/dsp/cost_mips_dsp_r2.c2
-rw-r--r--thirdparty/libwebp/dsp/cost_sse2.c4
-rw-r--r--thirdparty/libwebp/dsp/cpu.c45
-rw-r--r--thirdparty/libwebp/dsp/dec.c2
-rw-r--r--thirdparty/libwebp/dsp/dec_clip_tables.c8
-rw-r--r--thirdparty/libwebp/dsp/dec_msa.c847
-rw-r--r--thirdparty/libwebp/dsp/dec_neon.c40
-rw-r--r--thirdparty/libwebp/dsp/dec_sse2.c4
-rw-r--r--thirdparty/libwebp/dsp/dec_sse41.c2
-rw-r--r--thirdparty/libwebp/dsp/dsp.h57
-rw-r--r--thirdparty/libwebp/dsp/enc.c178
-rw-r--r--thirdparty/libwebp/dsp/enc_mips32.c4
-rw-r--r--thirdparty/libwebp/dsp/enc_mips_dsp_r2.c4
-rw-r--r--thirdparty/libwebp/dsp/enc_msa.c892
-rw-r--r--thirdparty/libwebp/dsp/enc_neon.c42
-rw-r--r--thirdparty/libwebp/dsp/enc_sse2.c182
-rw-r--r--thirdparty/libwebp/dsp/enc_sse41.c2
-rw-r--r--thirdparty/libwebp/dsp/filters.c12
-rw-r--r--thirdparty/libwebp/dsp/filters_msa.c202
-rw-r--r--thirdparty/libwebp/dsp/filters_neon.c327
-rw-r--r--thirdparty/libwebp/dsp/lossless.c186
-rw-r--r--thirdparty/libwebp/dsp/lossless.h225
-rw-r--r--thirdparty/libwebp/dsp/lossless_common.h210
-rw-r--r--thirdparty/libwebp/dsp/lossless_enc.c953
-rw-r--r--thirdparty/libwebp/dsp/lossless_enc_mips32.c47
-rw-r--r--thirdparty/libwebp/dsp/lossless_enc_msa.c147
-rw-r--r--thirdparty/libwebp/dsp/lossless_enc_sse2.c320
-rw-r--r--thirdparty/libwebp/dsp/lossless_enc_sse41.c4
-rw-r--r--thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c79
-rw-r--r--thirdparty/libwebp/dsp/lossless_msa.c355
-rw-r--r--thirdparty/libwebp/dsp/lossless_neon.c395
-rw-r--r--thirdparty/libwebp/dsp/lossless_sse2.c389
-rw-r--r--thirdparty/libwebp/dsp/msa_macro.h1097
-rw-r--r--thirdparty/libwebp/dsp/neon.h18
-rw-r--r--thirdparty/libwebp/dsp/rescaler.c8
-rw-r--r--thirdparty/libwebp/dsp/rescaler_mips32.c2
-rw-r--r--thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c2
-rw-r--r--thirdparty/libwebp/dsp/rescaler_msa.c444
-rw-r--r--thirdparty/libwebp/dsp/rescaler_neon.c2
-rw-r--r--thirdparty/libwebp/dsp/rescaler_sse2.c2
-rw-r--r--thirdparty/libwebp/dsp/upsampling.c6
-rw-r--r--thirdparty/libwebp/dsp/upsampling_msa.c678
-rw-r--r--thirdparty/libwebp/dsp/upsampling_neon.c77
-rw-r--r--thirdparty/libwebp/dsp/yuv.c57
-rw-r--r--thirdparty/libwebp/dsp/yuv.h2
-rw-r--r--thirdparty/libwebp/dsp/yuv_sse2.c304
-rw-r--r--thirdparty/libwebp/dsp/yuv_tables_sse2.h536
-rw-r--r--thirdparty/libwebp/enc/alpha.c433
-rw-r--r--thirdparty/libwebp/enc/alpha_enc.c433
-rw-r--r--thirdparty/libwebp/enc/analysis.c506
-rw-r--r--thirdparty/libwebp/enc/analysis_enc.c533
-rw-r--r--thirdparty/libwebp/enc/backward_references.c1715
-rw-r--r--thirdparty/libwebp/enc/backward_references.h206
-rw-r--r--thirdparty/libwebp/enc/backward_references_enc.c1800
-rw-r--r--thirdparty/libwebp/enc/backward_references_enc.h207
-rw-r--r--thirdparty/libwebp/enc/config.c173
-rw-r--r--thirdparty/libwebp/enc/config_enc.c152
-rw-r--r--thirdparty/libwebp/enc/cost.c342
-rw-r--r--thirdparty/libwebp/enc/cost.h82
-rw-r--r--thirdparty/libwebp/enc/cost_enc.c342
-rw-r--r--thirdparty/libwebp/enc/cost_enc.h82
-rw-r--r--thirdparty/libwebp/enc/delta_palettization.c455
-rw-r--r--thirdparty/libwebp/enc/delta_palettization.h25
-rw-r--r--thirdparty/libwebp/enc/delta_palettization_enc.c455
-rw-r--r--thirdparty/libwebp/enc/delta_palettization_enc.h25
-rw-r--r--thirdparty/libwebp/enc/filter.c306
-rw-r--r--thirdparty/libwebp/enc/filter_enc.c219
-rw-r--r--thirdparty/libwebp/enc/frame.c852
-rw-r--r--thirdparty/libwebp/enc/frame_enc.c854
-rw-r--r--thirdparty/libwebp/enc/histogram.c938
-rw-r--r--thirdparty/libwebp/enc/histogram.h123
-rw-r--r--thirdparty/libwebp/enc/histogram_enc.c990
-rw-r--r--thirdparty/libwebp/enc/histogram_enc.h123
-rw-r--r--thirdparty/libwebp/enc/iterator.c456
-rw-r--r--thirdparty/libwebp/enc/iterator_enc.c453
-rw-r--r--thirdparty/libwebp/enc/near_lossless.c122
-rw-r--r--thirdparty/libwebp/enc/near_lossless_enc.c122
-rw-r--r--thirdparty/libwebp/enc/picture.c293
-rw-r--r--thirdparty/libwebp/enc/picture_csp.c1192
-rw-r--r--thirdparty/libwebp/enc/picture_csp_enc.c1175
-rw-r--r--thirdparty/libwebp/enc/picture_enc.c293
-rw-r--r--thirdparty/libwebp/enc/picture_psnr.c177
-rw-r--r--thirdparty/libwebp/enc/picture_psnr_enc.c213
-rw-r--r--thirdparty/libwebp/enc/picture_rescale.c264
-rw-r--r--thirdparty/libwebp/enc/picture_rescale_enc.c264
-rw-r--r--thirdparty/libwebp/enc/picture_tools.c226
-rw-r--r--thirdparty/libwebp/enc/picture_tools_enc.c226
-rw-r--r--thirdparty/libwebp/enc/predictor_enc.c750
-rw-r--r--thirdparty/libwebp/enc/quant.c1284
-rw-r--r--thirdparty/libwebp/enc/quant_enc.c1283
-rw-r--r--thirdparty/libwebp/enc/syntax.c383
-rw-r--r--thirdparty/libwebp/enc/syntax_enc.c382
-rw-r--r--thirdparty/libwebp/enc/token.c293
-rw-r--r--thirdparty/libwebp/enc/token_enc.c294
-rw-r--r--thirdparty/libwebp/enc/tree.c504
-rw-r--r--thirdparty/libwebp/enc/tree_enc.c504
-rw-r--r--thirdparty/libwebp/enc/vp8enci.h529
-rw-r--r--thirdparty/libwebp/enc/vp8i_enc.h520
-rw-r--r--thirdparty/libwebp/enc/vp8l.c1602
-rw-r--r--thirdparty/libwebp/enc/vp8l_enc.c1667
-rw-r--r--thirdparty/libwebp/enc/vp8li.h81
-rw-r--r--thirdparty/libwebp/enc/vp8li_enc.h95
-rw-r--r--thirdparty/libwebp/enc/webp_enc.c398
-rw-r--r--thirdparty/libwebp/enc/webpenc.c395
-rw-r--r--thirdparty/libwebp/mux/anim_encode.c51
-rw-r--r--thirdparty/libwebp/mux/animi.h43
-rw-r--r--thirdparty/libwebp/mux/muxedit.c157
-rw-r--r--thirdparty/libwebp/mux/muxi.h16
-rw-r--r--thirdparty/libwebp/mux/muxinternal.c21
-rw-r--r--thirdparty/libwebp/mux/muxread.c48
-rw-r--r--thirdparty/libwebp/utils/bit_reader.c229
-rw-r--r--thirdparty/libwebp/utils/bit_reader_inl.h173
-rw-r--r--thirdparty/libwebp/utils/bit_reader_inl_utils.h190
-rw-r--r--thirdparty/libwebp/utils/bit_reader_utils.c229
-rw-r--r--thirdparty/libwebp/utils/bit_reader_utils.h (renamed from thirdparty/libwebp/utils/bit_reader.h)0
-rw-r--r--thirdparty/libwebp/utils/bit_writer.c319
-rw-r--r--thirdparty/libwebp/utils/bit_writer.h145
-rw-r--r--thirdparty/libwebp/utils/bit_writer_utils.c319
-rw-r--r--thirdparty/libwebp/utils/bit_writer_utils.h146
-rw-r--r--thirdparty/libwebp/utils/color_cache.c49
-rw-r--r--thirdparty/libwebp/utils/color_cache.h80
-rw-r--r--thirdparty/libwebp/utils/color_cache_utils.c49
-rw-r--r--thirdparty/libwebp/utils/color_cache_utils.h85
-rw-r--r--thirdparty/libwebp/utils/endian_inl_utils.h (renamed from thirdparty/libwebp/utils/endian_inl.h)0
-rw-r--r--thirdparty/libwebp/utils/filters.c76
-rw-r--r--thirdparty/libwebp/utils/filters_utils.c76
-rw-r--r--thirdparty/libwebp/utils/filters_utils.h (renamed from thirdparty/libwebp/utils/filters.h)0
-rw-r--r--thirdparty/libwebp/utils/huffman.c205
-rw-r--r--thirdparty/libwebp/utils/huffman_encode.c417
-rw-r--r--thirdparty/libwebp/utils/huffman_encode_utils.c417
-rw-r--r--thirdparty/libwebp/utils/huffman_encode_utils.h (renamed from thirdparty/libwebp/utils/huffman_encode.h)0
-rw-r--r--thirdparty/libwebp/utils/huffman_utils.c223
-rw-r--r--thirdparty/libwebp/utils/huffman_utils.h (renamed from thirdparty/libwebp/utils/huffman.h)0
-rw-r--r--thirdparty/libwebp/utils/quant_levels.c140
-rw-r--r--thirdparty/libwebp/utils/quant_levels_dec.c284
-rw-r--r--thirdparty/libwebp/utils/quant_levels_dec_utils.c284
-rw-r--r--thirdparty/libwebp/utils/quant_levels_dec_utils.h (renamed from thirdparty/libwebp/utils/quant_levels_dec.h)0
-rw-r--r--thirdparty/libwebp/utils/quant_levels_utils.c140
-rw-r--r--thirdparty/libwebp/utils/quant_levels_utils.h (renamed from thirdparty/libwebp/utils/quant_levels.h)0
-rw-r--r--thirdparty/libwebp/utils/random.c43
-rw-r--r--thirdparty/libwebp/utils/random_utils.c43
-rw-r--r--thirdparty/libwebp/utils/random_utils.h (renamed from thirdparty/libwebp/utils/random.h)0
-rw-r--r--thirdparty/libwebp/utils/rescaler.c146
-rw-r--r--thirdparty/libwebp/utils/rescaler_utils.c146
-rw-r--r--thirdparty/libwebp/utils/rescaler_utils.h (renamed from thirdparty/libwebp/utils/rescaler.h)0
-rw-r--r--thirdparty/libwebp/utils/thread.c358
-rw-r--r--thirdparty/libwebp/utils/thread_utils.c356
-rw-r--r--thirdparty/libwebp/utils/thread_utils.h (renamed from thirdparty/libwebp/utils/thread.h)0
-rw-r--r--thirdparty/libwebp/utils/utils.c37
-rw-r--r--thirdparty/libwebp/utils/utils.h50
-rw-r--r--thirdparty/libwebp/webp/config.h150
-rw-r--r--thirdparty/libwebp/webp/encode.h35
-rw-r--r--thirdparty/libwebp/webp/format_constants.h3
-rw-r--r--thirdparty/libwebp/webp/mux.h50
-rw-r--r--thirdparty/libwebp/webp/mux_types.h5
-rw-r--r--tools/editor/SCsub186
-rw-r--r--tools/editor/animation_editor.cpp4331
-rw-r--r--tools/editor/array_property_edit.cpp310
-rw-r--r--tools/editor/asset_library_editor_plugin.cpp1553
-rw-r--r--tools/editor/call_dialog.h85
-rw-r--r--tools/editor/code_editor.cpp1323
-rw-r--r--tools/editor/code_editor.h261
-rw-r--r--tools/editor/collada/collada.cpp2801
-rw-r--r--tools/editor/collada/collada.h663
-rw-r--r--tools/editor/connections_dialog.h134
-rw-r--r--tools/editor/create_dialog.cpp961
-rw-r--r--tools/editor/dependency_editor.cpp725
-rw-r--r--tools/editor/doc/doc_data.cpp1141
-rw-r--r--tools/editor/doc/doc_data.h110
-rw-r--r--tools/editor/editor_audio_buses.cpp1192
-rw-r--r--tools/editor/editor_audio_buses.h186
-rw-r--r--tools/editor/editor_autoload_settings.cpp610
-rw-r--r--tools/editor/editor_data.cpp979
-rw-r--r--tools/editor/editor_data.h269
-rw-r--r--tools/editor/editor_dir_dialog.cpp276
-rw-r--r--tools/editor/editor_file_dialog.cpp1531
-rw-r--r--tools/editor/editor_file_system.cpp1550
-rw-r--r--tools/editor/editor_help.cpp1929
-rw-r--r--tools/editor/editor_help.h222
-rw-r--r--tools/editor/editor_import_export.cpp2306
-rw-r--r--tools/editor/editor_import_export.h425
-rw-r--r--tools/editor/editor_log.cpp242
-rw-r--r--tools/editor/editor_node.cpp6573
-rw-r--r--tools/editor/editor_node.h832
-rw-r--r--tools/editor/editor_plugin.cpp432
-rw-r--r--tools/editor/editor_plugin.h201
-rw-r--r--tools/editor/editor_plugin_settings.cpp216
-rw-r--r--tools/editor/editor_profiler.cpp784
-rw-r--r--tools/editor/editor_resource_preview.cpp439
-rw-r--r--tools/editor/editor_run.cpp207
-rw-r--r--tools/editor/editor_run.h67
-rw-r--r--tools/editor/editor_run_native.cpp189
-rw-r--r--tools/editor/editor_run_script.cpp97
-rw-r--r--tools/editor/editor_settings.cpp1154
-rw-r--r--tools/editor/editor_settings.h180
-rw-r--r--tools/editor/editor_sub_scene.cpp238
-rw-r--r--tools/editor/editor_sub_scene.h69
-rw-r--r--tools/editor/file_type_cache.cpp108
-rw-r--r--tools/editor/filesystem_dock.cpp1858
-rw-r--r--tools/editor/filesystem_dock.h216
-rw-r--r--tools/editor/icons/SCsub96
-rw-r--r--tools/editor/import/editor_import_collada.cpp2508
-rw-r--r--tools/editor/import/editor_import_collada.h51
-rw-r--r--tools/editor/import/resource_importer_csv_translation.cpp126
-rw-r--r--tools/editor/import/resource_importer_csv_translation.h27
-rw-r--r--tools/editor/import/resource_importer_obj.cpp231
-rw-r--r--tools/editor/import/resource_importer_obj.h28
-rw-r--r--tools/editor/import/resource_importer_scene.cpp1328
-rw-r--r--tools/editor/import/resource_importer_scene.h93
-rw-r--r--tools/editor/import/resource_importer_texture.cpp393
-rw-r--r--tools/editor/import/resource_importer_texture.h70
-rw-r--r--tools/editor/import/resource_importer_wav.cpp619
-rw-r--r--tools/editor/import/resource_importer_wav.h30
-rw-r--r--tools/editor/import_dock.cpp331
-rw-r--r--tools/editor/import_dock.h42
-rw-r--r--tools/editor/io_plugins/editor_bitmask_import_plugin.cpp387
-rw-r--r--tools/editor/io_plugins/editor_bitmask_import_plugin.h70
-rw-r--r--tools/editor/io_plugins/editor_export_scene.cpp142
-rw-r--r--tools/editor/io_plugins/editor_export_scene.h44
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.cpp1704
-rw-r--r--tools/editor/io_plugins/editor_font_import_plugin.h58
-rw-r--r--tools/editor/io_plugins/editor_mesh_import_plugin.cpp593
-rw-r--r--tools/editor/io_plugins/editor_mesh_import_plugin.h59
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.cpp929
-rw-r--r--tools/editor/io_plugins/editor_sample_import_plugin.h74
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.cpp2992
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.h200
-rw-r--r--tools/editor/io_plugins/editor_scene_importer_fbxconv.cpp1136
-rw-r--r--tools/editor/io_plugins/editor_scene_importer_fbxconv.h111
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp1893
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.h179
-rw-r--r--tools/editor/io_plugins/editor_translation_import_plugin.cpp479
-rw-r--r--tools/editor/io_plugins/editor_translation_import_plugin.h56
-rw-r--r--tools/editor/multi_node_edit.cpp172
-rw-r--r--tools/editor/multi_node_edit.h61
-rw-r--r--tools/editor/node_dock.cpp133
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.cpp1604
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.h219
-rw-r--r--tools/editor/plugins/animation_tree_editor_plugin.cpp1536
-rw-r--r--tools/editor/plugins/animation_tree_editor_plugin.h194
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp2731
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h120
-rw-r--r--tools/editor/plugins/camera_editor_plugin.cpp150
-rw-r--r--tools/editor/plugins/camera_editor_plugin.h79
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp4063
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.h503
-rw-r--r--tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp482
-rw-r--r--tools/editor/plugins/collision_polygon_2d_editor_plugin.h111
-rw-r--r--tools/editor/plugins/collision_polygon_editor_plugin.cpp648
-rw-r--r--tools/editor/plugins/collision_polygon_editor_plugin.h123
-rw-r--r--tools/editor/plugins/collision_shape_2d_editor_plugin.h101
-rw-r--r--tools/editor/plugins/color_ramp_editor_plugin.cpp112
-rw-r--r--tools/editor/plugins/color_ramp_editor_plugin.h62
-rw-r--r--tools/editor/plugins/cube_grid_theme_editor_plugin.cpp357
-rw-r--r--tools/editor/plugins/cube_grid_theme_editor_plugin.h96
-rw-r--r--tools/editor/plugins/editor_preview_plugins.cpp907
-rw-r--r--tools/editor/plugins/editor_preview_plugins.h128
-rw-r--r--tools/editor/plugins/gi_probe_editor_plugin.cpp85
-rw-r--r--tools/editor/plugins/gi_probe_editor_plugin.h65
-rw-r--r--tools/editor/plugins/item_list_editor_plugin.h230
-rw-r--r--tools/editor/plugins/light_occluder_2d_editor_plugin.cpp518
-rw-r--r--tools/editor/plugins/light_occluder_2d_editor_plugin.h115
-rw-r--r--tools/editor/plugins/material_editor_plugin.cpp413
-rw-r--r--tools/editor/plugins/material_editor_plugin.h100
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp245
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.h98
-rw-r--r--tools/editor/plugins/mesh_instance_editor_plugin.h97
-rw-r--r--tools/editor/plugins/multimesh_editor_plugin.h107
-rw-r--r--tools/editor/plugins/navigation_polygon_editor_plugin.cpp566
-rw-r--r--tools/editor/plugins/navigation_polygon_editor_plugin.h118
-rw-r--r--tools/editor/plugins/particles_2d_editor_plugin.cpp199
-rw-r--r--tools/editor/plugins/particles_2d_editor_plugin.h82
-rw-r--r--tools/editor/plugins/particles_editor_plugin.cpp461
-rw-r--r--tools/editor/plugins/particles_editor_plugin.h116
-rw-r--r--tools/editor/plugins/path_2d_editor_plugin.cpp718
-rw-r--r--tools/editor/plugins/path_2d_editor_plugin.h126
-rw-r--r--tools/editor/plugins/path_editor_plugin.cpp604
-rw-r--r--tools/editor/plugins/path_editor_plugin.h100
-rw-r--r--tools/editor/plugins/polygon_2d_editor_plugin.cpp1028
-rw-r--r--tools/editor/plugins/polygon_2d_editor_plugin.h167
-rw-r--r--tools/editor/plugins/resource_preloader_editor_plugin.cpp507
-rw-r--r--tools/editor/plugins/resource_preloader_editor_plugin.h108
-rw-r--r--tools/editor/plugins/rich_text_editor_plugin.cpp164
-rw-r--r--tools/editor/plugins/rich_text_editor_plugin.h91
-rw-r--r--tools/editor/plugins/sample_editor_plugin.cpp451
-rw-r--r--tools/editor/plugins/sample_editor_plugin.h92
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.cpp546
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.h108
-rw-r--r--tools/editor/plugins/sample_player_editor_plugin.cpp203
-rw-r--r--tools/editor/plugins/sample_player_editor_plugin.h90
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp2487
-rw-r--r--tools/editor/plugins/script_editor_plugin.h394
-rw-r--r--tools/editor/plugins/script_text_editor.cpp1401
-rw-r--r--tools/editor/plugins/shader_editor_plugin.cpp584
-rw-r--r--tools/editor/plugins/shader_editor_plugin.h156
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.cpp2948
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.h242
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp4131
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.h574
-rw-r--r--tools/editor/plugins/sprite_frames_editor_plugin.cpp969
-rw-r--r--tools/editor/plugins/sprite_frames_editor_plugin.h138
-rw-r--r--tools/editor/plugins/stream_editor_plugin.cpp149
-rw-r--r--tools/editor/plugins/stream_editor_plugin.h84
-rw-r--r--tools/editor/plugins/style_box_editor_plugin.h83
-rw-r--r--tools/editor/plugins/texture_editor_plugin.cpp169
-rw-r--r--tools/editor/plugins/texture_editor_plugin.h77
-rw-r--r--tools/editor/plugins/texture_region_editor_plugin.cpp1011
-rw-r--r--tools/editor/plugins/texture_region_editor_plugin.h153
-rw-r--r--tools/editor/plugins/theme_editor_plugin.h125
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.cpp1593
-rw-r--r--tools/editor/plugins/tile_map_editor_plugin.h207
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.h101
-rw-r--r--tools/editor/project_export.cpp2130
-rw-r--r--tools/editor/project_export.h246
-rw-r--r--tools/editor/project_manager.cpp1516
-rw-r--r--tools/editor/project_manager.h148
-rw-r--r--tools/editor/project_settings.cpp1588
-rw-r--r--tools/editor/project_settings.h164
-rw-r--r--tools/editor/property_editor.cpp4916
-rw-r--r--tools/editor/property_editor.h347
-rw-r--r--tools/editor/property_selector.cpp626
-rw-r--r--tools/editor/property_selector.h83
-rw-r--r--tools/editor/quick_open.cpp285
-rw-r--r--tools/editor/reparent_dialog.h68
-rw-r--r--tools/editor/resources_dock.cpp409
-rw-r--r--tools/editor/scene_tree_dock.cpp2057
-rw-r--r--tools/editor/scene_tree_editor.cpp1316
-rw-r--r--tools/editor/script_create_dialog.cpp437
-rw-r--r--tools/editor/script_create_dialog.h79
-rw-r--r--tools/editor/script_editor_debugger.cpp1998
-rw-r--r--tools/editor/settings_config_dialog.cpp406
-rw-r--r--tools/editor/spatial_editor_gizmos.cpp3483
-rw-r--r--tools/editor/spatial_editor_gizmos.h521
-rw-r--r--tools/editor/translations/Makefile20
-rwxr-xr-xtools/editor/translations/extract.py121
2991 files changed, 172112 insertions, 159346 deletions
diff --git a/.gitignore b/.gitignore
index f7eac1122d..cdf277dd71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,12 +16,12 @@ 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/certs_compressed.h
-tools/editor/editor_icons.cpp
-tools/editor/translations.h
-tools/editor/builtin_fonts.h
+editor/register_exporters.cpp
+editor/doc_data_compressed.h
+editor/certs_compressed.h
+editor/editor_icons.cpp
+editor/translations.h
+editor/builtin_fonts.h
.fscache
make.bat
log.txt
@@ -246,6 +246,9 @@ node_modules/
#Kdevelop project files
*.kdev4
+# xCode
+xcuserdata
+
# RIA/Silverlight projects
Generated_Code/
diff --git a/SConstruct b/SConstruct
index 4c79304ef2..2e7683d17a 100644
--- a/SConstruct
+++ b/SConstruct
@@ -179,7 +179,7 @@ Help(opts.GenerateHelpText(env_base)) # generate help
# add default include paths
-env_base.Append(CPPPATH=['#core', '#core/math', '#tools', '#drivers', '#'])
+env_base.Append(CPPPATH=['#core', '#core/math', '#editor', '#drivers', '#'])
# configure ENV for platform
env_base.platform_exporters = platform_exporters
@@ -358,7 +358,7 @@ if selected_platform in platform_list:
SConscript("core/SCsub")
SConscript("servers/SCsub")
SConscript("scene/SCsub")
- SConscript("tools/editor/SCsub")
+ SConscript("editor/SCsub")
SConscript("drivers/SCsub")
SConscript("modules/SCsub")
diff --git a/core/SCsub b/core/SCsub
index 8d89f6427b..77c8288846 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -13,7 +13,7 @@ for x in env.global_defaults:
gd_inc += '#include "platform/' + x + '/globals/global_defaults.h"\n'
gd_call += "\tregister_" + x + "_global_defaults();\n"
-gd_cpp = '#include "globals.h"\n'
+gd_cpp = '#include "global_config.h"\n'
gd_cpp += gd_inc
gd_cpp += "void GlobalConfig::register_global_defaults() {\n" + gd_call + "\n}\n"
@@ -45,7 +45,7 @@ if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ):
print("Invalid AES256 encryption key, not 64 bits hex: " + e)
f = open("script_encryption_key.cpp", "wb")
-f.write("#include \"globals.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
+f.write("#include \"global_config.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n")
f.close()
@@ -61,6 +61,7 @@ SConscript('os/SCsub')
SConscript('math/SCsub')
SConscript('io/SCsub')
SConscript('bind/SCsub')
+SConscript('helper/SCsub')
lib = env.Library("core", env.core_sources)
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 636a3f07c1..08e1a311fa 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -31,7 +31,7 @@
#include "geometry.h"
#include "io/marshalls.h"
#include "io/base64.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#include "io/file_access_encrypted.h"
#include "os/keyboard.h"
@@ -110,12 +110,12 @@ bool _ResourceLoader::has(const String &p_path) {
void _ResourceLoader::_bind_methods() {
- ClassDB::bind_method(_MD("load_interactive:ResourceInteractiveLoader","path","type_hint"),&_ResourceLoader::load_interactive,DEFVAL(""));
- ClassDB::bind_method(_MD("load:Resource","path","type_hint", "p_no_cache"),&_ResourceLoader::load,DEFVAL(""), DEFVAL(false));
- ClassDB::bind_method(_MD("get_recognized_extensions_for_type","type"),&_ResourceLoader::get_recognized_extensions_for_type);
- ClassDB::bind_method(_MD("set_abort_on_missing_resources","abort"),&_ResourceLoader::set_abort_on_missing_resources);
- ClassDB::bind_method(_MD("get_dependencies","path"),&_ResourceLoader::get_dependencies);
- ClassDB::bind_method(_MD("has","path"),&_ResourceLoader::has);
+ ClassDB::bind_method(D_METHOD("load_interactive:ResourceInteractiveLoader","path","type_hint"),&_ResourceLoader::load_interactive,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("load:Resource","path","type_hint", "p_no_cache"),&_ResourceLoader::load,DEFVAL(""), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_recognized_extensions_for_type","type"),&_ResourceLoader::get_recognized_extensions_for_type);
+ ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources","abort"),&_ResourceLoader::set_abort_on_missing_resources);
+ ClassDB::bind_method(D_METHOD("get_dependencies","path"),&_ResourceLoader::get_dependencies);
+ ClassDB::bind_method(D_METHOD("has","path"),&_ResourceLoader::has);
}
_ResourceLoader::_ResourceLoader() {
@@ -148,8 +148,8 @@ _ResourceSaver *_ResourceSaver::singleton=NULL;
void _ResourceSaver::_bind_methods() {
- ClassDB::bind_method(_MD("save","path","resource:Resource","flags"),&_ResourceSaver::save,DEFVAL(0));
- ClassDB::bind_method(_MD("get_recognized_extensions","type"),&_ResourceSaver::get_recognized_extensions);
+ ClassDB::bind_method(D_METHOD("save","path","resource:Resource","flags"),&_ResourceSaver::save,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_recognized_extensions","type"),&_ResourceSaver::get_recognized_extensions);
BIND_CONSTANT(FLAG_RELATIVE_PATHS);
BIND_CONSTANT(FLAG_BUNDLE_RESOURCES);
@@ -450,6 +450,17 @@ bool _OS::is_vsync_enabled() const {
return OS::get_singleton()->is_vsync_enabled();
}
+PowerState _OS::get_power_state() {
+ return OS::get_singleton()->get_power_state();
+}
+
+int _OS::get_power_seconds_left() {
+ return OS::get_singleton()->get_power_seconds_left();
+}
+
+int _OS::get_power_percent_left() {
+ return OS::get_singleton()->get_power_percent_left();
+}
/*
enum Weekday {
@@ -973,145 +984,149 @@ _OS *_OS::singleton=NULL;
void _OS::_bind_methods() {
- //ClassDB::bind_method(_MD("get_mouse_pos"),&_OS::get_mouse_pos);
- //ClassDB::bind_method(_MD("is_mouse_grab_enabled"),&_OS::is_mouse_grab_enabled);
+ //ClassDB::bind_method(D_METHOD("get_mouse_pos"),&_OS::get_mouse_pos);
+ //ClassDB::bind_method(D_METHOD("is_mouse_grab_enabled"),&_OS::is_mouse_grab_enabled);
- ClassDB::bind_method(_MD("set_clipboard","clipboard"),&_OS::set_clipboard);
- ClassDB::bind_method(_MD("get_clipboard"),&_OS::get_clipboard);
+ ClassDB::bind_method(D_METHOD("set_clipboard","clipboard"),&_OS::set_clipboard);
+ ClassDB::bind_method(D_METHOD("get_clipboard"),&_OS::get_clipboard);
//will not delete for now, just unexpose
- //ClassDB::bind_method(_MD("set_video_mode","size","fullscreen","resizable","screen"),&_OS::set_video_mode,DEFVAL(0));
- //ClassDB::bind_method(_MD("get_video_mode_size","screen"),&_OS::get_video_mode,DEFVAL(0));
- //ClassDB::bind_method(_MD("is_video_mode_fullscreen","screen"),&_OS::is_video_mode_fullscreen,DEFVAL(0));
- //ClassDB::bind_method(_MD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
- //ClassDB::bind_method(_MD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
-
-
- ClassDB::bind_method(_MD("get_screen_count"),&_OS::get_screen_count);
- ClassDB::bind_method(_MD("get_current_screen"),&_OS::get_current_screen);
- ClassDB::bind_method(_MD("set_current_screen","screen"),&_OS::set_current_screen);
- ClassDB::bind_method(_MD("get_screen_position","screen"),&_OS::get_screen_position,DEFVAL(0));
- ClassDB::bind_method(_MD("get_screen_size","screen"),&_OS::get_screen_size,DEFVAL(0));
- ClassDB::bind_method(_MD("get_screen_dpi","screen"),&_OS::get_screen_dpi,DEFVAL(0));
- ClassDB::bind_method(_MD("get_window_position"),&_OS::get_window_position);
- ClassDB::bind_method(_MD("set_window_position","position"),&_OS::set_window_position);
- ClassDB::bind_method(_MD("get_window_size"),&_OS::get_window_size);
- ClassDB::bind_method(_MD("set_window_size","size"),&_OS::set_window_size);
- ClassDB::bind_method(_MD("set_window_fullscreen","enabled"),&_OS::set_window_fullscreen);
- ClassDB::bind_method(_MD("is_window_fullscreen"),&_OS::is_window_fullscreen);
- ClassDB::bind_method(_MD("set_window_resizable","enabled"),&_OS::set_window_resizable);
- ClassDB::bind_method(_MD("is_window_resizable"),&_OS::is_window_resizable);
- ClassDB::bind_method(_MD("set_window_minimized", "enabled"),&_OS::set_window_minimized);
- ClassDB::bind_method(_MD("is_window_minimized"),&_OS::is_window_minimized);
- ClassDB::bind_method(_MD("set_window_maximized", "enabled"),&_OS::set_window_maximized);
- ClassDB::bind_method(_MD("is_window_maximized"),&_OS::is_window_maximized);
- ClassDB::bind_method(_MD("request_attention"), &_OS::request_attention);
-
- ClassDB::bind_method(_MD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
- ClassDB::bind_method(_MD("get_borderless_window"), &_OS::get_borderless_window);
-
- ClassDB::bind_method(_MD("set_screen_orientation","orientation"),&_OS::set_screen_orientation);
- ClassDB::bind_method(_MD("get_screen_orientation"),&_OS::get_screen_orientation);
-
- ClassDB::bind_method(_MD("set_keep_screen_on","enabled"),&_OS::set_keep_screen_on);
- ClassDB::bind_method(_MD("is_keep_screen_on"),&_OS::is_keep_screen_on);
-
-
- ClassDB::bind_method(_MD("has_touchscreen_ui_hint"),&_OS::has_touchscreen_ui_hint);
-
- ClassDB::bind_method(_MD("set_window_title","title"),&_OS::set_window_title);
-
- ClassDB::bind_method(_MD("set_low_processor_usage_mode","enable"),&_OS::set_low_processor_usage_mode);
- ClassDB::bind_method(_MD("is_in_low_processor_usage_mode"),&_OS::is_in_low_processor_usage_mode);
-
- ClassDB::bind_method(_MD("get_processor_count"),&_OS::get_processor_count);
-
- ClassDB::bind_method(_MD("get_executable_path"),&_OS::get_executable_path);
- ClassDB::bind_method(_MD("execute","path","arguments","blocking","output"),&_OS::execute,DEFVAL(Array()));
- ClassDB::bind_method(_MD("kill","pid"),&_OS::kill);
- ClassDB::bind_method(_MD("shell_open","uri"),&_OS::shell_open);
- ClassDB::bind_method(_MD("get_process_ID"),&_OS::get_process_ID);
-
- ClassDB::bind_method(_MD("get_environment","environment"),&_OS::get_environment);
- ClassDB::bind_method(_MD("has_environment","environment"),&_OS::has_environment);
-
- ClassDB::bind_method(_MD("get_name"),&_OS::get_name);
- ClassDB::bind_method(_MD("get_cmdline_args"),&_OS::get_cmdline_args);
-
- ClassDB::bind_method(_MD("get_datetime","utc"),&_OS::get_datetime,DEFVAL(false));
- ClassDB::bind_method(_MD("get_date","utc"),&_OS::get_date,DEFVAL(false));
- ClassDB::bind_method(_MD("get_time","utc"),&_OS::get_time,DEFVAL(false));
- ClassDB::bind_method(_MD("get_time_zone_info"),&_OS::get_time_zone_info);
- ClassDB::bind_method(_MD("get_unix_time"),&_OS::get_unix_time);
- ClassDB::bind_method(_MD("get_datetime_from_unix_time", "unix_time_val"),
+ //ClassDB::bind_method(D_METHOD("set_video_mode","size","fullscreen","resizable","screen"),&_OS::set_video_mode,DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("get_video_mode_size","screen"),&_OS::get_video_mode,DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("is_video_mode_fullscreen","screen"),&_OS::is_video_mode_fullscreen,DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
+
+
+ ClassDB::bind_method(D_METHOD("get_screen_count"),&_OS::get_screen_count);
+ ClassDB::bind_method(D_METHOD("get_current_screen"),&_OS::get_current_screen);
+ ClassDB::bind_method(D_METHOD("set_current_screen","screen"),&_OS::set_current_screen);
+ ClassDB::bind_method(D_METHOD("get_screen_position","screen"),&_OS::get_screen_position,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_screen_size","screen"),&_OS::get_screen_size,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_screen_dpi","screen"),&_OS::get_screen_dpi,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_window_position"),&_OS::get_window_position);
+ ClassDB::bind_method(D_METHOD("set_window_position","position"),&_OS::set_window_position);
+ ClassDB::bind_method(D_METHOD("get_window_size"),&_OS::get_window_size);
+ ClassDB::bind_method(D_METHOD("set_window_size","size"),&_OS::set_window_size);
+ ClassDB::bind_method(D_METHOD("set_window_fullscreen","enabled"),&_OS::set_window_fullscreen);
+ ClassDB::bind_method(D_METHOD("is_window_fullscreen"),&_OS::is_window_fullscreen);
+ ClassDB::bind_method(D_METHOD("set_window_resizable","enabled"),&_OS::set_window_resizable);
+ ClassDB::bind_method(D_METHOD("is_window_resizable"),&_OS::is_window_resizable);
+ ClassDB::bind_method(D_METHOD("set_window_minimized", "enabled"),&_OS::set_window_minimized);
+ ClassDB::bind_method(D_METHOD("is_window_minimized"),&_OS::is_window_minimized);
+ ClassDB::bind_method(D_METHOD("set_window_maximized", "enabled"),&_OS::set_window_maximized);
+ ClassDB::bind_method(D_METHOD("is_window_maximized"),&_OS::is_window_maximized);
+ ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention);
+
+ ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
+ ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window);
+
+ ClassDB::bind_method(D_METHOD("set_screen_orientation","orientation"),&_OS::set_screen_orientation);
+ ClassDB::bind_method(D_METHOD("get_screen_orientation"),&_OS::get_screen_orientation);
+
+ ClassDB::bind_method(D_METHOD("set_keep_screen_on","enabled"),&_OS::set_keep_screen_on);
+ ClassDB::bind_method(D_METHOD("is_keep_screen_on"),&_OS::is_keep_screen_on);
+
+
+ ClassDB::bind_method(D_METHOD("has_touchscreen_ui_hint"),&_OS::has_touchscreen_ui_hint);
+
+ ClassDB::bind_method(D_METHOD("set_window_title","title"),&_OS::set_window_title);
+
+ ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode","enable"),&_OS::set_low_processor_usage_mode);
+ ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"),&_OS::is_in_low_processor_usage_mode);
+
+ ClassDB::bind_method(D_METHOD("get_processor_count"),&_OS::get_processor_count);
+
+ ClassDB::bind_method(D_METHOD("get_executable_path"),&_OS::get_executable_path);
+ ClassDB::bind_method(D_METHOD("execute","path","arguments","blocking","output"),&_OS::execute,DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("kill","pid"),&_OS::kill);
+ ClassDB::bind_method(D_METHOD("shell_open","uri"),&_OS::shell_open);
+ ClassDB::bind_method(D_METHOD("get_process_ID"),&_OS::get_process_ID);
+
+ ClassDB::bind_method(D_METHOD("get_environment","environment"),&_OS::get_environment);
+ ClassDB::bind_method(D_METHOD("has_environment","environment"),&_OS::has_environment);
+
+ ClassDB::bind_method(D_METHOD("get_name"),&_OS::get_name);
+ ClassDB::bind_method(D_METHOD("get_cmdline_args"),&_OS::get_cmdline_args);
+
+ ClassDB::bind_method(D_METHOD("get_datetime","utc"),&_OS::get_datetime,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_date","utc"),&_OS::get_date,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_time","utc"),&_OS::get_time,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_time_zone_info"),&_OS::get_time_zone_info);
+ ClassDB::bind_method(D_METHOD("get_unix_time"),&_OS::get_unix_time);
+ ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"),
&_OS::get_datetime_from_unix_time);
- ClassDB::bind_method(_MD("get_unix_time_from_datetime", "datetime"),
+ ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"),
&_OS::get_unix_time_from_datetime);
- ClassDB::bind_method(_MD("get_system_time_secs"), &_OS::get_system_time_secs);
+ ClassDB::bind_method(D_METHOD("get_system_time_secs"), &_OS::get_system_time_secs);
+
+ ClassDB::bind_method(D_METHOD("set_icon","icon"),&_OS::set_icon);
- ClassDB::bind_method(_MD("set_icon","icon"),&_OS::set_icon);
+ ClassDB::bind_method(D_METHOD("get_exit_code"),&_OS::get_exit_code);
+ ClassDB::bind_method(D_METHOD("set_exit_code","code"),&_OS::set_exit_code);
- ClassDB::bind_method(_MD("get_exit_code"),&_OS::get_exit_code);
- ClassDB::bind_method(_MD("set_exit_code","code"),&_OS::set_exit_code);
+ ClassDB::bind_method(D_METHOD("delay_usec","usec"),&_OS::delay_usec);
+ ClassDB::bind_method(D_METHOD("delay_msec","msec"),&_OS::delay_msec);
+ ClassDB::bind_method(D_METHOD("get_ticks_msec"),&_OS::get_ticks_msec);
+ ClassDB::bind_method(D_METHOD("get_splash_tick_msec"),&_OS::get_splash_tick_msec);
+ ClassDB::bind_method(D_METHOD("get_locale"),&_OS::get_locale);
+ ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"),&_OS::get_latin_keyboard_variant);
+ ClassDB::bind_method(D_METHOD("get_model_name"),&_OS::get_model_name);
- ClassDB::bind_method(_MD("delay_usec","usec"),&_OS::delay_usec);
- ClassDB::bind_method(_MD("delay_msec","msec"),&_OS::delay_msec);
- ClassDB::bind_method(_MD("get_ticks_msec"),&_OS::get_ticks_msec);
- ClassDB::bind_method(_MD("get_splash_tick_msec"),&_OS::get_splash_tick_msec);
- ClassDB::bind_method(_MD("get_locale"),&_OS::get_locale);
- ClassDB::bind_method(_MD("get_latin_keyboard_variant"),&_OS::get_latin_keyboard_variant);
- ClassDB::bind_method(_MD("get_model_name"),&_OS::get_model_name);
+ ClassDB::bind_method(D_METHOD("can_draw"),&_OS::can_draw);
+ ClassDB::bind_method(D_METHOD("is_stdout_verbose"),&_OS::is_stdout_verbose);
- ClassDB::bind_method(_MD("can_draw"),&_OS::can_draw);
- ClassDB::bind_method(_MD("is_stdout_verbose"),&_OS::is_stdout_verbose);
+ ClassDB::bind_method(D_METHOD("can_use_threads"),&_OS::can_use_threads);
- ClassDB::bind_method(_MD("can_use_threads"),&_OS::can_use_threads);
+ ClassDB::bind_method(D_METHOD("is_debug_build"),&_OS::is_debug_build);
- ClassDB::bind_method(_MD("is_debug_build"),&_OS::is_debug_build);
+ //ClassDB::bind_method(D_METHOD("get_mouse_button_state"),&_OS::get_mouse_button_state);
- //ClassDB::bind_method(_MD("get_mouse_button_state"),&_OS::get_mouse_button_state);
+ ClassDB::bind_method(D_METHOD("dump_memory_to_file","file"),&_OS::dump_memory_to_file);
+ ClassDB::bind_method(D_METHOD("dump_resources_to_file","file"),&_OS::dump_resources_to_file);
+ ClassDB::bind_method(D_METHOD("has_virtual_keyboard"),&_OS::has_virtual_keyboard);
+ ClassDB::bind_method(D_METHOD("show_virtual_keyboard", "existing_text"),&_OS::show_virtual_keyboard,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("hide_virtual_keyboard"),&_OS::hide_virtual_keyboard);
+ ClassDB::bind_method(D_METHOD("print_resources_in_use","short"),&_OS::print_resources_in_use,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("print_all_resources","tofile"),&_OS::print_all_resources,DEFVAL(""));
- ClassDB::bind_method(_MD("dump_memory_to_file","file"),&_OS::dump_memory_to_file);
- ClassDB::bind_method(_MD("dump_resources_to_file","file"),&_OS::dump_resources_to_file);
- ClassDB::bind_method(_MD("has_virtual_keyboard"),&_OS::has_virtual_keyboard);
- ClassDB::bind_method(_MD("show_virtual_keyboard", "existing_text"),&_OS::show_virtual_keyboard,DEFVAL(""));
- ClassDB::bind_method(_MD("hide_virtual_keyboard"),&_OS::hide_virtual_keyboard);
- ClassDB::bind_method(_MD("print_resources_in_use","short"),&_OS::print_resources_in_use,DEFVAL(false));
- ClassDB::bind_method(_MD("print_all_resources","tofile"),&_OS::print_all_resources,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_static_memory_usage"),&_OS::get_static_memory_usage);
+ ClassDB::bind_method(D_METHOD("get_static_memory_peak_usage"),&_OS::get_static_memory_peak_usage);
+ ClassDB::bind_method(D_METHOD("get_dynamic_memory_usage"),&_OS::get_dynamic_memory_usage);
- ClassDB::bind_method(_MD("get_static_memory_usage"),&_OS::get_static_memory_usage);
- ClassDB::bind_method(_MD("get_static_memory_peak_usage"),&_OS::get_static_memory_peak_usage);
- ClassDB::bind_method(_MD("get_dynamic_memory_usage"),&_OS::get_dynamic_memory_usage);
+ ClassDB::bind_method(D_METHOD("get_data_dir"),&_OS::get_data_dir);
+ ClassDB::bind_method(D_METHOD("get_system_dir","dir"),&_OS::get_system_dir);
+ ClassDB::bind_method(D_METHOD("get_unique_ID"),&_OS::get_unique_ID);
- ClassDB::bind_method(_MD("get_data_dir"),&_OS::get_data_dir);
- ClassDB::bind_method(_MD("get_system_dir","dir"),&_OS::get_system_dir);
- ClassDB::bind_method(_MD("get_unique_ID"),&_OS::get_unique_ID);
+ ClassDB::bind_method(D_METHOD("is_ok_left_and_cancel_right"),&_OS::is_ok_left_and_cancel_right);
- ClassDB::bind_method(_MD("is_ok_left_and_cancel_right"),&_OS::is_ok_left_and_cancel_right);
+ ClassDB::bind_method(D_METHOD("print_all_textures_by_size"),&_OS::print_all_textures_by_size);
+ ClassDB::bind_method(D_METHOD("print_resources_by_type","types"),&_OS::print_resources_by_type);
- ClassDB::bind_method(_MD("print_all_textures_by_size"),&_OS::print_all_textures_by_size);
- ClassDB::bind_method(_MD("print_resources_by_type","types"),&_OS::print_resources_by_type);
+ ClassDB::bind_method(D_METHOD("native_video_play","path","volume","audio_track","subtitle_track"),&_OS::native_video_play);
+ ClassDB::bind_method(D_METHOD("native_video_is_playing"),&_OS::native_video_is_playing);
+ ClassDB::bind_method(D_METHOD("native_video_stop"),&_OS::native_video_stop);
+ ClassDB::bind_method(D_METHOD("native_video_pause"),&_OS::native_video_pause);
+ ClassDB::bind_method(D_METHOD("native_video_unpause"),&_OS::native_video_unpause);
- ClassDB::bind_method(_MD("native_video_play","path","volume","audio_track","subtitle_track"),&_OS::native_video_play);
- ClassDB::bind_method(_MD("native_video_is_playing"),&_OS::native_video_is_playing);
- ClassDB::bind_method(_MD("native_video_stop"),&_OS::native_video_stop);
- ClassDB::bind_method(_MD("native_video_pause"),&_OS::native_video_pause);
- ClassDB::bind_method(_MD("native_video_unpause"),&_OS::native_video_unpause);
+ ClassDB::bind_method(D_METHOD("get_scancode_string","code"),&_OS::get_scancode_string);
+ ClassDB::bind_method(D_METHOD("is_scancode_unicode","code"),&_OS::is_scancode_unicode);
+ ClassDB::bind_method(D_METHOD("find_scancode_from_string","string"),&_OS::find_scancode_from_string);
- ClassDB::bind_method(_MD("get_scancode_string","code"),&_OS::get_scancode_string);
- ClassDB::bind_method(_MD("is_scancode_unicode","code"),&_OS::is_scancode_unicode);
- ClassDB::bind_method(_MD("find_scancode_from_string","string"),&_OS::find_scancode_from_string);
+ ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap","enabled"),&_OS::set_use_file_access_save_and_swap);
- ClassDB::bind_method(_MD("set_use_file_access_save_and_swap","enabled"),&_OS::set_use_file_access_save_and_swap);
+ ClassDB::bind_method(D_METHOD("alert","text","title"),&_OS::alert,DEFVAL("Alert!"));
- ClassDB::bind_method(_MD("alert","text","title"),&_OS::alert,DEFVAL("Alert!"));
+ ClassDB::bind_method(D_METHOD("set_thread_name","name"),&_OS::set_thread_name);
- ClassDB::bind_method(_MD("set_thread_name","name"),&_OS::set_thread_name);
+ ClassDB::bind_method(D_METHOD("set_use_vsync","enable"),&_OS::set_use_vsync);
+ ClassDB::bind_method(D_METHOD("is_vsync_enabled"),&_OS::is_vsync_enabled);
- ClassDB::bind_method(_MD("set_use_vsync","enable"),&_OS::set_use_vsync);
- ClassDB::bind_method(_MD("is_vsync_enabled"),&_OS::is_vsync_enabled);
+ ClassDB::bind_method(D_METHOD("get_power_state"),&_OS::get_power_state);
+ ClassDB::bind_method(D_METHOD("get_power_seconds_left"),&_OS::get_power_seconds_left);
+ ClassDB::bind_method(D_METHOD("get_power_percent_left"),&_OS::get_power_percent_left);
BIND_CONSTANT( DAY_SUNDAY );
BIND_CONSTANT( DAY_MONDAY );
@@ -1150,6 +1165,12 @@ void _OS::_bind_methods() {
BIND_CONSTANT( SYSTEM_DIR_MUSIC );
BIND_CONSTANT( SYSTEM_DIR_PICTURES );
BIND_CONSTANT( SYSTEM_DIR_RINGTONES );
+
+ BIND_CONSTANT( POWERSTATE_UNKNOWN );
+ BIND_CONSTANT( POWERSTATE_ON_BATTERY );
+ BIND_CONSTANT( POWERSTATE_NO_BATTERY );
+ BIND_CONSTANT( POWERSTATE_CHARGING );
+ BIND_CONSTANT( POWERSTATE_CHARGED );
}
@@ -1221,11 +1242,26 @@ PoolVector<Vector3> _Geometry::get_closest_points_between_segments(const Vector3
return r;
}
+Vector2 _Geometry::get_closest_point_to_segment_2d(const Vector2& p_point, const Vector2& p_a,const Vector2& p_b) {
+
+ Vector2 s[2]={p_a,p_b};
+ return Geometry::get_closest_point_to_segment_2d(p_point,s);
+}
Vector3 _Geometry::get_closest_point_to_segment(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b) {
Vector3 s[2]={p_a,p_b};
return Geometry::get_closest_point_to_segment(p_point,s);
}
+Vector2 _Geometry::get_closest_point_to_segment_uncapped_2d(const Vector2& p_point, const Vector2& p_a,const Vector2& p_b) {
+
+ Vector2 s[2]={p_a,p_b};
+ return Geometry::get_closest_point_to_segment_uncapped_2d(p_point,s);
+}
+Vector3 _Geometry::get_closest_point_to_segment_uncapped(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b) {
+
+ Vector3 s[2]={p_a,p_b};
+ return Geometry::get_closest_point_to_segment_uncapped(p_point,s);
+}
Variant _Geometry::ray_intersects_triangle( const Vector3& p_from, const Vector3& p_dir, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2) {
Vector3 res;
@@ -1333,29 +1369,33 @@ int _Geometry::get_uv84_normal_bit(const Vector3& p_vector) {
void _Geometry::_bind_methods() {
- ClassDB::bind_method(_MD("build_box_planes","extents"),&_Geometry::build_box_planes);
- ClassDB::bind_method(_MD("build_cylinder_planes","radius","height","sides","axis"),&_Geometry::build_cylinder_planes,DEFVAL(Vector3::AXIS_Z));
- ClassDB::bind_method(_MD("build_capsule_planes","radius","height","sides","lats","axis"),&_Geometry::build_capsule_planes,DEFVAL(Vector3::AXIS_Z));
- ClassDB::bind_method(_MD("segment_intersects_circle","segment_from","segment_to","circle_pos","circle_radius"),&_Geometry::segment_intersects_circle);
- ClassDB::bind_method(_MD("segment_intersects_segment_2d","from_a","to_a","from_b","to_b"),&_Geometry::segment_intersects_segment_2d);
+ ClassDB::bind_method(D_METHOD("build_box_planes","extents"),&_Geometry::build_box_planes);
+ ClassDB::bind_method(D_METHOD("build_cylinder_planes","radius","height","sides","axis"),&_Geometry::build_cylinder_planes,DEFVAL(Vector3::AXIS_Z));
+ ClassDB::bind_method(D_METHOD("build_capsule_planes","radius","height","sides","lats","axis"),&_Geometry::build_capsule_planes,DEFVAL(Vector3::AXIS_Z));
+ ClassDB::bind_method(D_METHOD("segment_intersects_circle","segment_from","segment_to","circle_pos","circle_radius"),&_Geometry::segment_intersects_circle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_segment_2d","from_a","to_a","from_b","to_b"),&_Geometry::segment_intersects_segment_2d);
+
+ ClassDB::bind_method(D_METHOD("get_closest_points_between_segments_2d","p1","q1","p2","q2"),&_Geometry::get_closest_points_between_segments_2d);
+ ClassDB::bind_method(D_METHOD("get_closest_points_between_segments","p1","p2","q1","q2"),&_Geometry::get_closest_points_between_segments);
- ClassDB::bind_method(_MD("get_closest_points_between_segments_2d","p1","q1","p2","q2"),&_Geometry::get_closest_points_between_segments_2d);
- ClassDB::bind_method(_MD("get_closest_points_between_segments","p1","p2","q1","q2"),&_Geometry::get_closest_points_between_segments);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_2d","point","s1","s2"),&_Geometry::get_closest_point_to_segment_2d);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment","point","s1","s2"),&_Geometry::get_closest_point_to_segment);
- ClassDB::bind_method(_MD("get_closest_point_to_segment","point","s1","s2"),&_Geometry::get_closest_point_to_segment);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped_2d","point","s1","s2"),&_Geometry::get_closest_point_to_segment_uncapped_2d);
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped","point","s1","s2"),&_Geometry::get_closest_point_to_segment_uncapped);
- ClassDB::bind_method(_MD("get_uv84_normal_bit","normal"),&_Geometry::get_uv84_normal_bit);
+ ClassDB::bind_method(D_METHOD("get_uv84_normal_bit","normal"),&_Geometry::get_uv84_normal_bit);
- ClassDB::bind_method(_MD("ray_intersects_triangle","from","dir","a","b","c"),&_Geometry::ray_intersects_triangle);
- ClassDB::bind_method(_MD("segment_intersects_triangle","from","to","a","b","c"),&_Geometry::segment_intersects_triangle);
- ClassDB::bind_method(_MD("segment_intersects_sphere","from","to","spos","sradius"),&_Geometry::segment_intersects_sphere);
- ClassDB::bind_method(_MD("segment_intersects_cylinder","from","to","height","radius"),&_Geometry::segment_intersects_cylinder);
- ClassDB::bind_method(_MD("segment_intersects_convex","from","to","planes"),&_Geometry::segment_intersects_convex);
- ClassDB::bind_method(_MD("point_is_inside_triangle","point","a","b","c"),&_Geometry::point_is_inside_triangle);
+ ClassDB::bind_method(D_METHOD("ray_intersects_triangle","from","dir","a","b","c"),&_Geometry::ray_intersects_triangle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_triangle","from","to","a","b","c"),&_Geometry::segment_intersects_triangle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_sphere","from","to","spos","sradius"),&_Geometry::segment_intersects_sphere);
+ ClassDB::bind_method(D_METHOD("segment_intersects_cylinder","from","to","height","radius"),&_Geometry::segment_intersects_cylinder);
+ ClassDB::bind_method(D_METHOD("segment_intersects_convex","from","to","planes"),&_Geometry::segment_intersects_convex);
+ ClassDB::bind_method(D_METHOD("point_is_inside_triangle","point","a","b","c"),&_Geometry::point_is_inside_triangle);
- ClassDB::bind_method(_MD("triangulate_polygon","polygon"),&_Geometry::triangulate_polygon);
+ ClassDB::bind_method(D_METHOD("triangulate_polygon","polygon"),&_Geometry::triangulate_polygon);
- ClassDB::bind_method(_MD("make_atlas","sizes"),&_Geometry::make_atlas);
+ ClassDB::bind_method(D_METHOD("make_atlas","sizes"),&_Geometry::make_atlas);
}
@@ -1735,52 +1775,52 @@ uint64_t _File::get_modified_time(const String &p_file) const {
void _File::_bind_methods() {
- ClassDB::bind_method(_MD("open_encrypted","path","mode_flags","key"),&_File::open_encrypted);
- ClassDB::bind_method(_MD("open_encrypted_with_pass","path","mode_flags","pass"),&_File::open_encrypted_pass);
-
- ClassDB::bind_method(_MD("open","path","flags"),&_File::open);
- ClassDB::bind_method(_MD("close"),&_File::close);
- ClassDB::bind_method(_MD("is_open"),&_File::is_open);
- ClassDB::bind_method(_MD("seek","pos"),&_File::seek);
- ClassDB::bind_method(_MD("seek_end","pos"),&_File::seek_end,DEFVAL(0));
- ClassDB::bind_method(_MD("get_pos"),&_File::get_pos);
- ClassDB::bind_method(_MD("get_len"),&_File::get_len);
- ClassDB::bind_method(_MD("eof_reached"),&_File::eof_reached);
- ClassDB::bind_method(_MD("get_8"),&_File::get_8);
- ClassDB::bind_method(_MD("get_16"),&_File::get_16);
- ClassDB::bind_method(_MD("get_32"),&_File::get_32);
- ClassDB::bind_method(_MD("get_64"),&_File::get_64);
- ClassDB::bind_method(_MD("get_float"),&_File::get_float);
- ClassDB::bind_method(_MD("get_double"),&_File::get_double);
- ClassDB::bind_method(_MD("get_real"),&_File::get_real);
- ClassDB::bind_method(_MD("get_buffer","len"),&_File::get_buffer);
- ClassDB::bind_method(_MD("get_line"),&_File::get_line);
- ClassDB::bind_method(_MD("get_as_text"),&_File::get_as_text);
- ClassDB::bind_method(_MD("get_md5","path"),&_File::get_md5);
- ClassDB::bind_method(_MD("get_sha256","path"),&_File::get_sha256);
- ClassDB::bind_method(_MD("get_endian_swap"),&_File::get_endian_swap);
- ClassDB::bind_method(_MD("set_endian_swap","enable"),&_File::set_endian_swap);
- ClassDB::bind_method(_MD("get_error:Error"),&_File::get_error);
- ClassDB::bind_method(_MD("get_var"),&_File::get_var);
- ClassDB::bind_method(_MD("get_csv_line","delim"),&_File::get_csv_line,DEFVAL(","));
-
- ClassDB::bind_method(_MD("store_8","value"),&_File::store_8);
- ClassDB::bind_method(_MD("store_16","value"),&_File::store_16);
- ClassDB::bind_method(_MD("store_32","value"),&_File::store_32);
- ClassDB::bind_method(_MD("store_64","value"),&_File::store_64);
- ClassDB::bind_method(_MD("store_float","value"),&_File::store_float);
- ClassDB::bind_method(_MD("store_double","value"),&_File::store_double);
- ClassDB::bind_method(_MD("store_real","value"),&_File::store_real);
- ClassDB::bind_method(_MD("store_buffer","buffer"),&_File::store_buffer);
- ClassDB::bind_method(_MD("store_line","line"),&_File::store_line);
- ClassDB::bind_method(_MD("store_string","string"),&_File::store_string);
- ClassDB::bind_method(_MD("store_var","value"),&_File::store_var);
-
- ClassDB::bind_method(_MD("store_pascal_string","string"),&_File::store_pascal_string);
- ClassDB::bind_method(_MD("get_pascal_string"),&_File::get_pascal_string);
-
- ClassDB::bind_method(_MD("file_exists","path"),&_File::file_exists);
- ClassDB::bind_method(_MD("get_modified_time", "file"),&_File::get_modified_time);
+ ClassDB::bind_method(D_METHOD("open_encrypted","path","mode_flags","key"),&_File::open_encrypted);
+ ClassDB::bind_method(D_METHOD("open_encrypted_with_pass","path","mode_flags","pass"),&_File::open_encrypted_pass);
+
+ ClassDB::bind_method(D_METHOD("open","path","flags"),&_File::open);
+ ClassDB::bind_method(D_METHOD("close"),&_File::close);
+ ClassDB::bind_method(D_METHOD("is_open"),&_File::is_open);
+ ClassDB::bind_method(D_METHOD("seek","pos"),&_File::seek);
+ ClassDB::bind_method(D_METHOD("seek_end","pos"),&_File::seek_end,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_pos"),&_File::get_pos);
+ ClassDB::bind_method(D_METHOD("get_len"),&_File::get_len);
+ ClassDB::bind_method(D_METHOD("eof_reached"),&_File::eof_reached);
+ ClassDB::bind_method(D_METHOD("get_8"),&_File::get_8);
+ ClassDB::bind_method(D_METHOD("get_16"),&_File::get_16);
+ ClassDB::bind_method(D_METHOD("get_32"),&_File::get_32);
+ ClassDB::bind_method(D_METHOD("get_64"),&_File::get_64);
+ ClassDB::bind_method(D_METHOD("get_float"),&_File::get_float);
+ ClassDB::bind_method(D_METHOD("get_double"),&_File::get_double);
+ ClassDB::bind_method(D_METHOD("get_real"),&_File::get_real);
+ ClassDB::bind_method(D_METHOD("get_buffer","len"),&_File::get_buffer);
+ ClassDB::bind_method(D_METHOD("get_line"),&_File::get_line);
+ ClassDB::bind_method(D_METHOD("get_as_text"),&_File::get_as_text);
+ ClassDB::bind_method(D_METHOD("get_md5","path"),&_File::get_md5);
+ ClassDB::bind_method(D_METHOD("get_sha256","path"),&_File::get_sha256);
+ ClassDB::bind_method(D_METHOD("get_endian_swap"),&_File::get_endian_swap);
+ ClassDB::bind_method(D_METHOD("set_endian_swap","enable"),&_File::set_endian_swap);
+ ClassDB::bind_method(D_METHOD("get_error:Error"),&_File::get_error);
+ ClassDB::bind_method(D_METHOD("get_var"),&_File::get_var);
+ ClassDB::bind_method(D_METHOD("get_csv_line","delim"),&_File::get_csv_line,DEFVAL(","));
+
+ ClassDB::bind_method(D_METHOD("store_8","value"),&_File::store_8);
+ ClassDB::bind_method(D_METHOD("store_16","value"),&_File::store_16);
+ ClassDB::bind_method(D_METHOD("store_32","value"),&_File::store_32);
+ ClassDB::bind_method(D_METHOD("store_64","value"),&_File::store_64);
+ ClassDB::bind_method(D_METHOD("store_float","value"),&_File::store_float);
+ ClassDB::bind_method(D_METHOD("store_double","value"),&_File::store_double);
+ ClassDB::bind_method(D_METHOD("store_real","value"),&_File::store_real);
+ ClassDB::bind_method(D_METHOD("store_buffer","buffer"),&_File::store_buffer);
+ ClassDB::bind_method(D_METHOD("store_line","line"),&_File::store_line);
+ ClassDB::bind_method(D_METHOD("store_string","string"),&_File::store_string);
+ ClassDB::bind_method(D_METHOD("store_var","value"),&_File::store_var);
+
+ ClassDB::bind_method(D_METHOD("store_pascal_string","string"),&_File::store_pascal_string);
+ ClassDB::bind_method(D_METHOD("get_pascal_string"),&_File::get_pascal_string);
+
+ ClassDB::bind_method(D_METHOD("file_exists","path"),&_File::file_exists);
+ ClassDB::bind_method(D_METHOD("get_modified_time", "file"),&_File::get_modified_time);
BIND_CONSTANT( READ );
BIND_CONSTANT( WRITE );
@@ -1970,25 +2010,25 @@ Error _Directory::remove(String p_name){
void _Directory::_bind_methods() {
- ClassDB::bind_method(_MD("open:Error","path"),&_Directory::open);
- ClassDB::bind_method(_MD("list_dir_begin", "skip_navigational", "skip_hidden"), &_Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
- ClassDB::bind_method(_MD("get_next"),&_Directory::get_next);
- ClassDB::bind_method(_MD("current_is_dir"),&_Directory::current_is_dir);
- ClassDB::bind_method(_MD("list_dir_end"),&_Directory::list_dir_end);
- ClassDB::bind_method(_MD("get_drive_count"),&_Directory::get_drive_count);
- ClassDB::bind_method(_MD("get_drive","idx"),&_Directory::get_drive);
- ClassDB::bind_method(_MD("get_current_drive"),&_Directory::get_current_drive);
- ClassDB::bind_method(_MD("change_dir:Error","todir"),&_Directory::change_dir);
- ClassDB::bind_method(_MD("get_current_dir"),&_Directory::get_current_dir);
- ClassDB::bind_method(_MD("make_dir:Error","path"),&_Directory::make_dir);
- ClassDB::bind_method(_MD("make_dir_recursive:Error","path"),&_Directory::make_dir_recursive);
- ClassDB::bind_method(_MD("file_exists","path"),&_Directory::file_exists);
- ClassDB::bind_method(_MD("dir_exists","path"),&_Directory::dir_exists);
- //ClassDB::bind_method(_MD("get_modified_time","file"),&_Directory::get_modified_time);
- ClassDB::bind_method(_MD("get_space_left"),&_Directory::get_space_left);
- ClassDB::bind_method(_MD("copy:Error","from","to"),&_Directory::copy);
- ClassDB::bind_method(_MD("rename:Error","from","to"),&_Directory::rename);
- ClassDB::bind_method(_MD("remove:Error","path"),&_Directory::remove);
+ ClassDB::bind_method(D_METHOD("open:Error","path"),&_Directory::open);
+ ClassDB::bind_method(D_METHOD("list_dir_begin", "skip_navigational", "skip_hidden"), &_Directory::list_dir_begin, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_next"),&_Directory::get_next);
+ ClassDB::bind_method(D_METHOD("current_is_dir"),&_Directory::current_is_dir);
+ ClassDB::bind_method(D_METHOD("list_dir_end"),&_Directory::list_dir_end);
+ ClassDB::bind_method(D_METHOD("get_drive_count"),&_Directory::get_drive_count);
+ ClassDB::bind_method(D_METHOD("get_drive","idx"),&_Directory::get_drive);
+ ClassDB::bind_method(D_METHOD("get_current_drive"),&_Directory::get_current_drive);
+ ClassDB::bind_method(D_METHOD("change_dir:Error","todir"),&_Directory::change_dir);
+ ClassDB::bind_method(D_METHOD("get_current_dir"),&_Directory::get_current_dir);
+ ClassDB::bind_method(D_METHOD("make_dir:Error","path"),&_Directory::make_dir);
+ ClassDB::bind_method(D_METHOD("make_dir_recursive:Error","path"),&_Directory::make_dir_recursive);
+ ClassDB::bind_method(D_METHOD("file_exists","path"),&_Directory::file_exists);
+ ClassDB::bind_method(D_METHOD("dir_exists","path"),&_Directory::dir_exists);
+ //ClassDB::bind_method(D_METHOD("get_modified_time","file"),&_Directory::get_modified_time);
+ ClassDB::bind_method(D_METHOD("get_space_left"),&_Directory::get_space_left);
+ ClassDB::bind_method(D_METHOD("copy:Error","from","to"),&_Directory::copy);
+ ClassDB::bind_method(D_METHOD("rename:Error","from","to"),&_Directory::rename);
+ ClassDB::bind_method(D_METHOD("remove:Error","path"),&_Directory::remove);
}
@@ -2128,14 +2168,14 @@ String _Marshalls::base64_to_utf8(const String& p_str) {
void _Marshalls::_bind_methods() {
- ClassDB::bind_method(_MD("variant_to_base64:String","variant"),&_Marshalls::variant_to_base64);
- ClassDB::bind_method(_MD("base64_to_variant:Variant","base64_str"),&_Marshalls::base64_to_variant);
+ ClassDB::bind_method(D_METHOD("variant_to_base64:String","variant"),&_Marshalls::variant_to_base64);
+ ClassDB::bind_method(D_METHOD("base64_to_variant:Variant","base64_str"),&_Marshalls::base64_to_variant);
- ClassDB::bind_method(_MD("raw_to_base64:String","array"),&_Marshalls::raw_to_base64);
- ClassDB::bind_method(_MD("base64_to_raw:RawArray","base64_str"),&_Marshalls::base64_to_raw);
+ ClassDB::bind_method(D_METHOD("raw_to_base64:String","array"),&_Marshalls::raw_to_base64);
+ ClassDB::bind_method(D_METHOD("base64_to_raw:RawArray","base64_str"),&_Marshalls::base64_to_raw);
- ClassDB::bind_method(_MD("utf8_to_base64:String","utf8_str"),&_Marshalls::utf8_to_base64);
- ClassDB::bind_method(_MD("base64_to_utf8:String","base64_str"),&_Marshalls::base64_to_utf8);
+ ClassDB::bind_method(D_METHOD("utf8_to_base64:String","utf8_str"),&_Marshalls::utf8_to_base64);
+ ClassDB::bind_method(D_METHOD("base64_to_utf8:String","base64_str"),&_Marshalls::base64_to_utf8);
};
@@ -2159,8 +2199,8 @@ Error _Semaphore::post() {
void _Semaphore::_bind_methods() {
- ClassDB::bind_method(_MD("wait:Error"),&_Semaphore::wait);
- ClassDB::bind_method(_MD("post:Error"),&_Semaphore::post);
+ ClassDB::bind_method(D_METHOD("wait:Error"),&_Semaphore::wait);
+ ClassDB::bind_method(D_METHOD("post:Error"),&_Semaphore::post);
}
@@ -2196,9 +2236,9 @@ void _Mutex::unlock(){
void _Mutex::_bind_methods() {
- ClassDB::bind_method(_MD("lock"),&_Mutex::lock);
- ClassDB::bind_method(_MD("try_lock:Error"),&_Mutex::try_lock);
- ClassDB::bind_method(_MD("unlock"),&_Mutex::unlock);
+ ClassDB::bind_method(D_METHOD("lock"),&_Mutex::lock);
+ ClassDB::bind_method(D_METHOD("try_lock:Error"),&_Mutex::try_lock);
+ ClassDB::bind_method(D_METHOD("unlock"),&_Mutex::unlock);
}
@@ -2318,10 +2358,10 @@ Variant _Thread::wait_to_finish() {
void _Thread::_bind_methods() {
- ClassDB::bind_method(_MD("start:Error","instance","method","userdata","priority"),&_Thread::start,DEFVAL(Variant()),DEFVAL(PRIORITY_NORMAL));
- ClassDB::bind_method(_MD("get_id"),&_Thread::get_id);
- ClassDB::bind_method(_MD("is_active"),&_Thread::is_active);
- ClassDB::bind_method(_MD("wait_to_finish:Variant"),&_Thread::wait_to_finish);
+ ClassDB::bind_method(D_METHOD("start:Error","instance","method","userdata","priority"),&_Thread::start,DEFVAL(Variant()),DEFVAL(PRIORITY_NORMAL));
+ ClassDB::bind_method(D_METHOD("get_id"),&_Thread::get_id);
+ ClassDB::bind_method(D_METHOD("is_active"),&_Thread::is_active);
+ ClassDB::bind_method(D_METHOD("wait_to_finish:Variant"),&_Thread::wait_to_finish);
BIND_CONSTANT( PRIORITY_LOW );
BIND_CONSTANT( PRIORITY_NORMAL );
@@ -2506,31 +2546,31 @@ bool _ClassDB::is_class_enabled(StringName p_class) const {
void _ClassDB::_bind_methods() {
- ClassDB::bind_method(_MD("get_class_list"),&_ClassDB::get_class_list);
- ClassDB::bind_method(_MD("get_inheriters_from_class","class"),&_ClassDB::get_inheriters_from_class);
- ClassDB::bind_method(_MD("get_parent_class","class"),&_ClassDB::get_parent_class);
- ClassDB::bind_method(_MD("class_exists","class"),&_ClassDB::class_exists);
- ClassDB::bind_method(_MD("is_parent_class","class","inherits"),&_ClassDB::is_parent_class);
- ClassDB::bind_method(_MD("can_instance","class"),&_ClassDB::can_instance);
- ClassDB::bind_method(_MD("instance:Variant","class"),&_ClassDB::instance);
+ ClassDB::bind_method(D_METHOD("get_class_list"),&_ClassDB::get_class_list);
+ ClassDB::bind_method(D_METHOD("get_inheriters_from_class","class"),&_ClassDB::get_inheriters_from_class);
+ ClassDB::bind_method(D_METHOD("get_parent_class","class"),&_ClassDB::get_parent_class);
+ ClassDB::bind_method(D_METHOD("class_exists","class"),&_ClassDB::class_exists);
+ ClassDB::bind_method(D_METHOD("is_parent_class","class","inherits"),&_ClassDB::is_parent_class);
+ ClassDB::bind_method(D_METHOD("can_instance","class"),&_ClassDB::can_instance);
+ ClassDB::bind_method(D_METHOD("instance:Variant","class"),&_ClassDB::instance);
- ClassDB::bind_method(_MD("class_has_signal","class","signal"),&_ClassDB::has_signal);
- ClassDB::bind_method(_MD("class_get_signal","class","signal"),&_ClassDB::get_signal);
- ClassDB::bind_method(_MD("class_get_signal_list","class","no_inheritance"),&_ClassDB::get_signal_list,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("class_has_signal","class","signal"),&_ClassDB::has_signal);
+ ClassDB::bind_method(D_METHOD("class_get_signal","class","signal"),&_ClassDB::get_signal);
+ ClassDB::bind_method(D_METHOD("class_get_signal_list","class","no_inheritance"),&_ClassDB::get_signal_list,DEFVAL(false));
- ClassDB::bind_method(_MD("class_get_property_list","class","no_inheritance"),&_ClassDB::get_property_list,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("class_get_property_list","class","no_inheritance"),&_ClassDB::get_property_list,DEFVAL(false));
- ClassDB::bind_method(_MD("class_has_method","class","method","no_inheritance"),&_ClassDB::has_method,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("class_has_method","class","method","no_inheritance"),&_ClassDB::has_method,DEFVAL(false));
- ClassDB::bind_method(_MD("class_get_method_list","class","no_inheritance"),&_ClassDB::get_method_list,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("class_get_method_list","class","no_inheritance"),&_ClassDB::get_method_list,DEFVAL(false));
- ClassDB::bind_method(_MD("class_get_integer_constant_list","class","no_inheritance"),&_ClassDB::get_integer_constant_list,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("class_get_integer_constant_list","class","no_inheritance"),&_ClassDB::get_integer_constant_list,DEFVAL(false));
- ClassDB::bind_method(_MD("class_has_integer_constant","class","name"),&_ClassDB::has_integer_constant);
- ClassDB::bind_method(_MD("class_get_integer_constant","class","name"),&_ClassDB::get_integer_constant);
+ ClassDB::bind_method(D_METHOD("class_has_integer_constant","class","name"),&_ClassDB::has_integer_constant);
+ ClassDB::bind_method(D_METHOD("class_get_integer_constant","class","name"),&_ClassDB::get_integer_constant);
- ClassDB::bind_method(_MD("class_get_category","class"),&_ClassDB::get_category);
- ClassDB::bind_method(_MD("is_class_enabled","class"),&_ClassDB::is_class_enabled);
+ ClassDB::bind_method(D_METHOD("class_get_category","class"),&_ClassDB::get_category);
+ ClassDB::bind_method(D_METHOD("is_class_enabled","class"),&_ClassDB::is_class_enabled);
}
@@ -2604,22 +2644,22 @@ Dictionary _Engine::get_version_info() const {
void _Engine::_bind_methods() {
- ClassDB::bind_method(_MD("set_iterations_per_second","iterations_per_second"),&_Engine::set_iterations_per_second);
- ClassDB::bind_method(_MD("get_iterations_per_second"),&_Engine::get_iterations_per_second);
- ClassDB::bind_method(_MD("set_target_fps","target_fps"),&_Engine::set_target_fps);
- ClassDB::bind_method(_MD("get_target_fps"),&_Engine::get_target_fps);
+ ClassDB::bind_method(D_METHOD("set_iterations_per_second","iterations_per_second"),&_Engine::set_iterations_per_second);
+ ClassDB::bind_method(D_METHOD("get_iterations_per_second"),&_Engine::get_iterations_per_second);
+ ClassDB::bind_method(D_METHOD("set_target_fps","target_fps"),&_Engine::set_target_fps);
+ ClassDB::bind_method(D_METHOD("get_target_fps"),&_Engine::get_target_fps);
- ClassDB::bind_method(_MD("set_time_scale","time_scale"),&_Engine::set_time_scale);
- ClassDB::bind_method(_MD("get_time_scale"),&_Engine::get_time_scale);
+ ClassDB::bind_method(D_METHOD("set_time_scale","time_scale"),&_Engine::set_time_scale);
+ ClassDB::bind_method(D_METHOD("get_time_scale"),&_Engine::get_time_scale);
- ClassDB::bind_method(_MD("get_custom_level"),&_Engine::get_custom_level);
+ ClassDB::bind_method(D_METHOD("get_custom_level"),&_Engine::get_custom_level);
- ClassDB::bind_method(_MD("get_frames_drawn"),&_Engine::get_frames_drawn);
- ClassDB::bind_method(_MD("get_frames_per_second"),&_Engine::get_frames_per_second);
+ ClassDB::bind_method(D_METHOD("get_frames_drawn"),&_Engine::get_frames_drawn);
+ ClassDB::bind_method(D_METHOD("get_frames_per_second"),&_Engine::get_frames_per_second);
- ClassDB::bind_method(_MD("get_main_loop:MainLoop"),&_Engine::get_main_loop);
+ ClassDB::bind_method(D_METHOD("get_main_loop:MainLoop"),&_Engine::get_main_loop);
- ClassDB::bind_method(_MD("get_version_info"),&_Engine::get_version_info);
+ ClassDB::bind_method(D_METHOD("get_version_info"),&_Engine::get_version_info);
}
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 00cbb254d6..6b9ae198ef 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -35,6 +35,7 @@
#include "os/dir_access.h"
#include "os/thread.h"
#include "os/semaphore.h"
+#include "os/power.h"
class _ResourceLoader : public Object {
@@ -308,6 +309,10 @@ public:
void set_use_vsync(bool p_enable);
bool is_vsync_enabled() const;
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+
static _OS *get_singleton() { return singleton; }
_OS();
@@ -334,7 +339,10 @@ public:
Variant segment_intersects_segment_2d(const Vector2& p_from_a,const Vector2& p_to_a,const Vector2& p_from_b,const Vector2& p_to_b);
PoolVector<Vector2> get_closest_points_between_segments_2d( const Vector2& p1,const Vector2& q1, const Vector2& p2,const Vector2& q2);
PoolVector<Vector3> get_closest_points_between_segments(const Vector3& p1,const Vector3& p2,const Vector3& q1,const Vector3& q2);
+ Vector2 get_closest_point_to_segment_2d(const Vector2& p_point, const Vector2& p_a,const Vector2& p_b);
Vector3 get_closest_point_to_segment(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b);
+ Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2& p_point, const Vector2& p_a,const Vector2& p_b);
+ Vector3 get_closest_point_to_segment_uncapped(const Vector3& p_point, const Vector3& p_a,const Vector3& p_b);
Variant ray_intersects_triangle( const Vector3& p_from, const Vector3& p_dir, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
Variant segment_intersects_triangle( const Vector3& p_from, const Vector3& p_to, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2);
bool point_is_inside_triangle(const Vector2& s, const Vector2& a, const Vector2& b, const Vector2& c) const;
diff --git a/core/class_db.cpp b/core/class_db.cpp
index 2a3a12b127..4bdae45fb9 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -47,14 +47,14 @@
ParamDef::ParamDef(const Variant& p_variant) { used=true; val=p_variant; }
-MethodDefinition _MD(const char* p_name) {
+MethodDefinition D_METHOD(const char* p_name) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -62,7 +62,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1) {
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -72,7 +72,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2) {
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -83,7 +83,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -95,7 +95,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -109,7 +109,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -123,7 +123,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -138,7 +138,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -154,7 +154,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -171,7 +171,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
return md;
}
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9,const char *p_arg10) {
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9,const char *p_arg10) {
MethodDefinition md;
md.name=StaticCString::create(p_name);
@@ -295,7 +295,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
OBJTYPE_RLOCK;
#ifdef DEBUG_METHODS_ENABLED
- uint64_t hash = hash_djb2_one_64(HashMapHahserDefault::hash(VERSION_FULL_NAME));
+ uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_NAME));
List<StringName> names;
@@ -1256,7 +1256,7 @@ void ClassDB::get_extensions_for_type(const StringName& p_class,List<String> *p_
while((K=resource_base_extensions.next(K))) {
StringName cmp = resource_base_extensions[*K];
- if (is_parent_class(cmp,p_class))
+ if (is_parent_class(p_class,cmp))
p_extensions->push_back(*K);
}
}
diff --git a/core/class_db.h b/core/class_db.h
index a09a42423b..6e02d0bf46 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -81,17 +81,17 @@ struct MethodDefinition {
-MethodDefinition _MD(const char* p_name);
-MethodDefinition _MD(const char* p_name,const char *p_arg1);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9);
-MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9,const char *p_arg10);
+MethodDefinition D_METHOD(const char* p_name);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9);
+MethodDefinition D_METHOD(const char* p_name,const char *p_arg1,const char *p_arg2,const char *p_arg3,const char *p_arg4,const char *p_arg5,const char *p_arg6,const char *p_arg7,const char *p_arg8,const char *p_arg9,const char *p_arg10);
#else
@@ -99,11 +99,13 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
#ifdef NO_VARIADIC_MACROS
-static _FORCE_INLINE_ const char* _MD(const char* m_name, ...) { return m_name; }
+static _FORCE_INLINE_ const char* D_METHOD(const char* m_name, ...) { return m_name; }
#else
-#define _MD(m_c, ...) m_c
+// When DEBUG_METHODS_ENABLED is set this will let the engine know
+// the argument names for easier debugging.
+#define D_METHOD(m_c, ...) m_c
#endif
diff --git a/core/compressed_translation.cpp b/core/compressed_translation.cpp
index d39db5044b..570cf114f7 100644
--- a/core/compressed_translation.cpp
+++ b/core/compressed_translation.cpp
@@ -527,7 +527,7 @@ void PHashTranslation::_get_property_list( List<PropertyInfo> *p_list) const{
}
void PHashTranslation::_bind_methods() {
- ClassDB::bind_method(_MD("generate","from:Translation"),&PHashTranslation::generate);
+ ClassDB::bind_method(D_METHOD("generate","from:Translation"),&PHashTranslation::generate);
}
PHashTranslation::PHashTranslation()
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index a173f98602..f8c6f47797 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -35,7 +35,7 @@ CoreStringNames::CoreStringNames() {
_free=StaticCString::create("free");
changed=StaticCString::create("changed");
_meta=StaticCString::create("__meta__");
- _script=StaticCString::create("script/script");
+ _script=StaticCString::create("script");
script_changed=StaticCString::create("script_changed");
___pdcdata=StaticCString::create("___pdcdata");
__getvar=StaticCString::create("__getvar");
diff --git a/core/dvector.h b/core/dvector.h
index 53a29738f7..456be41289 100644
--- a/core/dvector.h
+++ b/core/dvector.h
@@ -34,6 +34,7 @@
#include "pool_allocator.h"
#include "safe_refcount.h"
#include "os/rw_lock.h"
+#include "ustring.h"
struct MemoryPool {
@@ -466,6 +467,16 @@ public:
return OK;
}
+ String join(String delimiter) {
+ String rs = "";
+ int s = size();
+ Read r = read();
+ for(int i=0;i<s;i++) {
+ rs += r[i] + delimiter;
+ }
+ rs.erase( rs.length()-delimiter.length(), delimiter.length());
+ return rs;
+ }
bool is_locked() const { return alloc && alloc->lock>0; }
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 1e8c229810..2233615e25 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -65,8 +65,8 @@ void FuncRef::_bind_methods() {
}
- ClassDB::bind_method(_MD("set_instance","instance"),&FuncRef::set_instance);
- ClassDB::bind_method(_MD("set_function","name"),&FuncRef::set_function);
+ ClassDB::bind_method(D_METHOD("set_instance","instance"),&FuncRef::set_instance);
+ ClassDB::bind_method(D_METHOD("set_function","name"),&FuncRef::set_function);
}
diff --git a/core/global_config.cpp b/core/global_config.cpp
new file mode 100644
index 0000000000..b76991c04e
--- /dev/null
+++ b/core/global_config.cpp
@@ -0,0 +1,1018 @@
+/*************************************************************************/
+/* globals.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "global_config.h"
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/keyboard.h"
+#include "io/marshalls.h"
+#include "bind/core_bind.h"
+#include "os/os.h"
+#include "io/file_access_pack.h"
+#include "io/file_access_network.h"
+#include "variant_parser.h"
+
+#define FORMAT_VERSION 3
+
+GlobalConfig *GlobalConfig::singleton=NULL;
+
+GlobalConfig *GlobalConfig::get_singleton() {
+
+ return singleton;
+}
+
+String GlobalConfig::get_resource_path() const {
+
+ return resource_path;
+};
+
+String GlobalConfig::localize_path(const String& p_path) const {
+
+ if (resource_path=="")
+ return p_path; //not initialied yet
+
+ if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
+ (p_path.is_abs_path() && !p_path.begins_with(resource_path)))
+ return p_path.simplify_path();
+
+
+ DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ String path = p_path.replace("\\","/").simplify_path();
+
+ if (dir->change_dir(path)==OK) {
+
+ String cwd = dir->get_current_dir();
+ cwd = cwd.replace("\\","/");
+
+ memdelete(dir);
+
+ if (!cwd.begins_with(resource_path)) {
+ return p_path;
+ };
+
+ return cwd.replace_first(resource_path, "res:/");
+ } else {
+
+ memdelete(dir);
+
+ int sep = path.find_last("/");
+ if (sep == -1) {
+ return "res://"+path;
+ };
+
+
+ String parent = path.substr(0, sep);
+
+ String plocal = localize_path(parent);
+ if (plocal == "") {
+ return "";
+ };
+ return plocal + path.substr(sep, path.size() - sep);
+ };
+
+}
+
+void GlobalConfig::set_initial_value(const String& p_name, const Variant & p_value) {
+
+ ERR_FAIL_COND(!props.has(p_name));
+ props[p_name].initial=p_value;
+}
+
+
+String GlobalConfig::globalize_path(const String& p_path) const {
+
+ if (p_path.begins_with("res://")) {
+
+ if (resource_path != "") {
+
+ return p_path.replace("res:/",resource_path);
+ };
+ return p_path.replace("res://", "");
+ };
+
+ return p_path;
+}
+
+
+bool GlobalConfig::_set(const StringName& p_name, const Variant& p_value) {
+
+ _THREAD_SAFE_METHOD_
+
+
+ if (p_value.get_type()==Variant::NIL)
+ props.erase(p_name);
+ else {
+ 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++ + (registering_order?0:NO_ORDER_BASE));
+ }
+ }
+
+ if (!disable_platform_override) {
+
+ String s=String(p_name);
+ int sl = s.find("/");
+ int p = s.find(".");
+ if (p!=-1 && sl!=-1 && p < sl) {
+
+ Vector<String> ps = s.substr(0,sl).split(".");
+ String prop=s.substr(sl,s.length()-sl);
+ for(int i=1;i<ps.size();i++) {
+
+ if (ps[i]==OS::get_singleton()->get_name()) {
+
+ String fullprop=ps[0]+prop;
+
+ set(fullprop,p_value);
+ props[fullprop].overrided=true;
+ }
+ }
+ }
+
+ }
+
+ return true;
+}
+bool GlobalConfig::_get(const StringName& p_name,Variant &r_ret) const {
+
+ _THREAD_SAFE_METHOD_
+
+ if (!props.has(p_name)) {
+ print_line("WARNING: not found: "+String(p_name));
+ return false;
+ }
+ r_ret=props[p_name].variant;
+ return true;
+
+}
+
+struct _VCSort {
+
+ String name;
+ Variant::Type type;
+ int order;
+ int flags;
+
+ bool operator<(const _VCSort& p_vcs) const{ return order==p_vcs.order?name<p_vcs.name:order< p_vcs.order; }
+};
+
+void GlobalConfig::_get_property_list(List<PropertyInfo> *p_list) const {
+
+ _THREAD_SAFE_METHOD_
+
+ Set<_VCSort> vclist;
+
+ for(Map<StringName,VariantContainer>::Element *E=props.front();E;E=E->next()) {
+
+ const VariantContainer *v=&E->get();
+
+ if (v->hide_from_editor)
+ continue;
+
+ _VCSort vc;
+ vc.name=E->key();
+ vc.order=v->order;
+ vc.type=v->variant.get_type();
+ if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload"))
+ vc.flags=PROPERTY_USAGE_STORAGE;
+ else
+ vc.flags=PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_STORAGE;
+
+ vclist.insert(vc);
+ }
+
+ for(Set<_VCSort>::Element *E=vclist.front();E;E=E->next()) {
+
+ if (custom_prop_info.has(E->get().name)) {
+ PropertyInfo pi=custom_prop_info[E->get().name];
+ pi.name=E->get().name;
+ pi.usage=E->get().flags;
+ p_list->push_back( pi );
+ } else
+ p_list->push_back( PropertyInfo(E->get().type, E->get().name,PROPERTY_HINT_NONE,"",E->get().flags) );
+ }
+}
+
+
+
+bool GlobalConfig::_load_resource_pack(const String& p_pack) {
+
+ if (PackedData::get_singleton()->is_disabled())
+ return false;
+
+ bool ok = PackedData::get_singleton()->add_pack(p_pack)==OK;
+
+ if (!ok)
+ return false;
+
+ //if data.pck is found, all directory access will be from here
+ DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES);
+ using_datapack=true;
+
+ return true;
+}
+
+Error GlobalConfig::setup(const String& p_path,const String & p_main_pack) {
+
+ //If looking for files in network, just use network!
+
+ if (FileAccessNetworkClient::get_singleton()) {
+
+ if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
+
+ _load_settings("res://override.cfg");
+
+ }
+
+ return OK;
+ }
+
+ String exec_path = OS::get_singleton()->get_executable_path();
+
+ //Attempt with a passed main pack first
+
+ if (p_main_pack!="") {
+
+ bool ok = _load_resource_pack(p_main_pack);
+ ERR_FAIL_COND_V(!ok,ERR_CANT_OPEN);
+
+ if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
+ //load override from location of the main pack
+ _load_settings(p_main_pack.get_base_dir().plus_file("override.cfg"));
+
+ }
+
+ return OK;
+
+ }
+
+ //Attempt with execname.pck
+ if (exec_path!="") {
+
+
+ if (_load_resource_pack(exec_path.get_basename()+".pck")) {
+
+ if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
+ //load override from location of executable
+ _load_settings(exec_path.get_base_dir().plus_file("override.cfg"));
+
+ }
+
+
+
+ return OK;
+ }
+
+ }
+
+
+ //Try to use the filesystem for files, according to OS. (only Android -when reading from pck- and iOS use this)
+ 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.
+
+ resource_path=OS::get_singleton()->get_resource_dir().replace("\\","/");
+ if (resource_path.length() && resource_path[ resource_path.length()-1]=='/')
+ resource_path=resource_path.substr(0,resource_path.length()-1); // chop end
+
+ // data.pck and data.zip are deprecated and no longer supported, apologies.
+ // make sure this is loaded from the resource path
+
+ if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
+ _load_settings("res://override.cfg");
+
+ }
+
+ return OK;
+ }
+
+ //Nothing was found, try to find a godot.cfg somewhere!
+
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(!d,ERR_CANT_CREATE);
+
+ d->change_dir(p_path);
+
+ String candidate = d->get_current_dir();
+ String current_dir = d->get_current_dir();
+ bool found = false;
+
+ while(true) {
+ //try to load settings in ascending through dirs shape!
+
+ if (_load_settings(current_dir+"/godot.cfg")==OK || _load_settings_binary(current_dir+"/godot.cfb")==OK) {
+
+ _load_settings(current_dir+"/override.cfg");
+ candidate=current_dir;
+ found=true;
+ break;
+ }
+
+ d->change_dir("..");
+ if (d->get_current_dir()==current_dir)
+ break; //not doing anything useful
+ current_dir=d->get_current_dir();
+ }
+
+
+ resource_path=candidate;
+ resource_path = resource_path.replace("\\","/"); // windows path to unix path just in case
+ memdelete(d);
+
+ if (!found)
+ return ERR_FILE_NOT_FOUND;
+
+ if (resource_path.length() && resource_path[ resource_path.length()-1]=='/')
+ resource_path=resource_path.substr(0,resource_path.length()-1); // chop end
+
+ return OK;
+}
+
+bool GlobalConfig::has(String p_var) const {
+
+ _THREAD_SAFE_METHOD_
+
+ return props.has(p_var);
+}
+
+
+void GlobalConfig::set_registering_order(bool p_enable) {
+
+ registering_order=p_enable;
+}
+
+Error GlobalConfig::_load_settings_binary(const String p_path) {
+
+ Error err;
+ FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
+ if (err!=OK) {
+ return err;
+ }
+
+
+ uint8_t hdr[4];
+ f->get_buffer(hdr,4);
+ if (hdr[0]!='E'|| hdr[1]!='C' || hdr[2]!='F' || hdr[3]!='G') {
+
+ memdelete(f);
+ ERR_EXPLAIN("Corrupted header in binary godot.cfb (not ECFG)");
+ ERR_FAIL_V(ERR_FILE_CORRUPT;)
+ }
+
+ set_registering_order(false);
+
+ uint32_t count=f->get_32();
+
+ for(uint32_t i=0;i<count;i++) {
+
+ uint32_t slen=f->get_32();
+ CharString cs;
+ cs.resize(slen+1);
+ cs[slen]=0;
+ f->get_buffer((uint8_t*)cs.ptr(),slen);
+ String key;
+ key.parse_utf8(cs.ptr());
+
+ uint32_t vlen=f->get_32();
+ Vector<uint8_t> d;
+ d.resize(vlen);
+ f->get_buffer(d.ptr(),vlen);
+ Variant value;
+ Error err = decode_variant(value,d.ptr(),d.size());
+ ERR_EXPLAIN("Error decoding property: "+key);
+ ERR_CONTINUE(err!=OK);
+ set(key,value);
+
+ }
+
+ set_registering_order(true);
+
+
+ return OK;
+}
+Error GlobalConfig::_load_settings(const String p_path) {
+
+
+
+ Error err;
+ FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
+
+ if (!f)
+ return ERR_CANT_OPEN;
+
+ VariantParser::StreamFile stream;
+ stream.f=f;
+
+ String assign;
+ Variant value;
+ VariantParser::Tag next_tag;
+
+ int lines=0;
+ String error_text;
+
+ String section;
+
+ 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("GlobalConfig::load - "+p_path+":"+itos(lines)+" error: "+error_text);
+ memdelete(f);
+ return err;
+ }
+
+ if (assign!=String()) {
+ if (section==String() && assign=="config_version") {
+ int config_version = value;
+ if (config_version > FORMAT_VERSION) {
+ memdelete(f);
+ ERR_FAIL_COND_V(config_version > FORMAT_VERSION,ERR_FILE_CANT_OPEN);
+ }
+
+ }
+ set(section+"/"+assign,value);
+ } else if (next_tag.name!=String()) {
+ section=next_tag.name;
+ }
+ }
+
+ memdelete(f);
+
+ return OK;
+
+}
+
+
+
+int GlobalConfig::get_order(const String& p_name) const {
+
+ ERR_FAIL_COND_V(!props.has(p_name),-1);
+ return props[p_name].order;
+}
+
+
+void GlobalConfig::set_order(const String& p_name, int p_order){
+
+ ERR_FAIL_COND(!props.has(p_name));
+ props[p_name].order=p_order;
+}
+
+void GlobalConfig::clear(const String& p_name) {
+
+ ERR_FAIL_COND(!props.has(p_name));
+ props.erase(p_name);
+}
+
+Error GlobalConfig::save() {
+
+ return save_custom(get_resource_path()+"/godot.cfg");
+}
+
+Error GlobalConfig::_save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom) {
+
+
+ Error err;
+ FileAccess *file = FileAccess::open(p_file,FileAccess::WRITE,&err);
+ if (err!=OK) {
+
+ ERR_EXPLAIN("Coudln't save godot.cfb at "+p_file);
+ ERR_FAIL_COND_V(err,err)
+ }
+
+ uint8_t hdr[4]={'E','C','F','G'};
+ file->store_buffer(hdr,4);
+
+ int count=0;
+
+ for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
+
+ for(List<String>::Element *F=E->get().front();F;F=F->next()) {
+
+ count++;
+ }
+ }
+
+ file->store_32(count); //store how many properties are saved
+
+
+ for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
+
+ for(List<String>::Element *F=E->get().front();F;F=F->next()) {
+
+ String key = F->get();
+ if (E->key()!="")
+ key=E->key()+"/"+key;
+ Variant value;
+ if (p_custom.has(key))
+ value=p_custom[key];
+ else
+ value = get(key);
+
+ file->store_32(key.length());
+ file->store_string(key);
+
+ int len;
+ Error err = encode_variant(value,NULL,len);
+ if (err!=OK)
+ memdelete(file);
+ ERR_FAIL_COND_V( err != OK, ERR_INVALID_DATA );
+
+ Vector<uint8_t> buff;
+ buff.resize(len);
+
+ err = encode_variant(value,&buff[0],len);
+ if (err!=OK)
+ memdelete(file);
+ ERR_FAIL_COND_V( err != OK, ERR_INVALID_DATA );
+ file->store_32(len);
+ file->store_buffer(buff.ptr(),buff.size());
+ }
+ }
+
+ file->close();
+ memdelete(file);
+
+
+ return OK;
+}
+
+
+Error GlobalConfig::_save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom) {
+
+ Error err;
+ FileAccess *file = FileAccess::open(p_file,FileAccess::WRITE,&err);
+
+ if (err) {
+ ERR_EXPLAIN("Coudln't save godot.cfg - "+p_file);
+ ERR_FAIL_COND_V(err,err)
+ }
+
+ file->store_string("config_version="+itos(FORMAT_VERSION)+"\n");
+
+
+ for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
+
+ if (E!=props.front())
+ file->store_string("\n");
+
+ if (E->key()!="")
+ file->store_string("["+E->key()+"]\n\n");
+ for(List<String>::Element *F=E->get().front();F;F=F->next()) {
+
+ String key = F->get();
+ if (E->key()!="")
+ key=E->key()+"/"+key;
+ Variant value;
+ if (p_custom.has(key))
+ value=p_custom[key];
+ else
+ value = get(key);
+
+
+ String vstr;
+ VariantWriter::write_to_string(value,vstr);
+ file->store_string(F->get()+"="+vstr+"\n");
+
+ }
+ }
+
+ file->close();
+ memdelete(file);
+
+ return OK;
+}
+
+Error GlobalConfig::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
+
+ return save_custom(p_file);
+};
+
+Error GlobalConfig::save_custom(const String& p_path,const CustomMap& p_custom,const Set<String>& p_ignore_masks) {
+
+ ERR_FAIL_COND_V(p_path=="",ERR_INVALID_PARAMETER);
+
+ Set<_VCSort> vclist;
+
+ for(Map<StringName,VariantContainer>::Element *G=props.front();G;G=G->next()) {
+
+ const VariantContainer *v=&G->get();
+
+ if (v->hide_from_editor)
+ continue;
+
+ if (p_custom.has(G->key()))
+ continue;
+
+ bool discard=false;
+
+ for(const Set<String>::Element *E=p_ignore_masks.front();E;E=E->next()) {
+
+ if ( String(G->key()).match(E->get())) {
+ discard=true;
+ break;
+ }
+ }
+
+ if (discard)
+ continue;
+
+ _VCSort vc;
+ vc.name=G->key();//*k;
+ vc.order=v->order;
+ vc.type=v->variant.get_type();
+ vc.flags=PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_STORAGE;
+ if (v->variant==v->initial)
+ continue;
+
+
+ vclist.insert(vc);
+ }
+
+ for(const Map<String,Variant>::Element *E=p_custom.front();E;E=E->next()) {
+
+
+ _VCSort vc;
+ vc.name=E->key();
+ vc.order=0xFFFFFFF;
+ vc.type=E->get().get_type();
+ vc.flags=PROPERTY_USAGE_STORAGE;
+ vclist.insert(vc);
+ }
+
+ Map<String,List<String> > props;
+
+ for(Set<_VCSort>::Element *E=vclist.front();E;E=E->next()) {
+
+ String category = E->get().name;
+ String name = E->get().name;
+
+ int div = category.find("/");
+
+ if (div<0)
+ category="";
+ else {
+
+ category=category.substr(0,div);
+ name=name.substr(div+1,name.size());
+ }
+ props[category].push_back(name);
+ }
+
+
+
+ if (p_path.ends_with(".cfg"))
+ return _save_settings_text(p_path,props,p_custom);
+ else if (p_path.ends_with(".cfb"))
+ return _save_settings_binary(p_path,props,p_custom);
+ else {
+
+ ERR_EXPLAIN("Unknown config file format: "+p_path);
+ ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
+ }
+
+ return OK;
+
+#if 0
+ Error err = file->open(dst_file,FileAccess::WRITE);
+ if (err) {
+ memdelete(file);
+ ERR_EXPLAIN("Coudln't save godot.cfg");
+ ERR_FAIL_COND_V(err,err)
+ }
+
+
+ for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
+
+ if (E!=props.front())
+ file->store_string("\n");
+
+ if (E->key()!="")
+ file->store_string("["+E->key()+"]\n\n");
+ for(List<String>::Element *F=E->get().front();F;F=F->next()) {
+
+ String key = F->get();
+ if (E->key()!="")
+ key=E->key()+"/"+key;
+ Variant value;
+
+ if (p_custom.has(key))
+ value=p_custom[key];
+ else
+ value = get(key);
+
+ file->store_string(F->get()+"="+_encode_variant(value)+"\n");
+
+ }
+ }
+
+ file->close();
+ memdelete(file);
+
+
+ return OK;
+#endif
+}
+
+Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default) {
+
+ if (GlobalConfig::get_singleton()->has(p_var)) {
+ GlobalConfig::get_singleton()->set_initial_value(p_var,p_default);
+ return GlobalConfig::get_singleton()->get(p_var);
+ }
+ GlobalConfig::get_singleton()->set(p_var,p_default);
+ GlobalConfig::get_singleton()->set_initial_value(p_var,p_default);
+ return p_default;
+
+}
+
+void GlobalConfig::add_singleton(const Singleton &p_singleton) {
+
+ singletons.push_back(p_singleton);
+ singleton_ptrs[p_singleton.name]=p_singleton.ptr;
+}
+
+Object* GlobalConfig::get_singleton_object(const String& p_name) const {
+
+
+ const Map<StringName,Object*>::Element *E=singleton_ptrs.find(p_name);
+ if (!E)
+ return NULL;
+ else
+ return E->get();
+
+};
+
+bool GlobalConfig::has_singleton(const String& p_name) const {
+
+ return get_singleton_object(p_name) != NULL;
+};
+
+void GlobalConfig::get_singletons(List<Singleton> *p_singletons) {
+
+ for(List<Singleton>::Element *E=singletons.front();E;E=E->next())
+ p_singletons->push_back(E->get());
+}
+
+Vector<String> GlobalConfig::get_optimizer_presets() const {
+
+ List<PropertyInfo> pi;
+ GlobalConfig::get_singleton()->get_property_list(&pi);
+ Vector<String> names;
+
+ for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
+
+ if (!E->get().name.begins_with("optimizer_presets/"))
+ continue;
+ names.push_back(E->get().name.get_slicec('/',1));
+ }
+
+ names.sort();
+
+ return names;
+
+}
+
+void GlobalConfig::_add_property_info_bind(const Dictionary& p_info) {
+
+ ERR_FAIL_COND(!p_info.has("name"));
+ ERR_FAIL_COND(!p_info.has("type"));
+
+ PropertyInfo pinfo;
+ pinfo.name = p_info["name"];
+ ERR_FAIL_COND(!props.has(pinfo.name));
+ pinfo.type = Variant::Type(p_info["type"].operator int());
+ ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX);
+
+ if (p_info.has("hint"))
+ pinfo.hint = PropertyHint(p_info["hint"].operator int());
+ if (p_info.has("hint_string"))
+ pinfo.hint_string = p_info["hint_string"];
+
+ set_custom_property_info(pinfo.name, pinfo);
+}
+
+void GlobalConfig::set_custom_property_info(const String& p_prop,const PropertyInfo& p_info) {
+
+ ERR_FAIL_COND(!props.has(p_prop));
+ custom_prop_info[p_prop]=p_info;
+ custom_prop_info[p_prop].name=p_prop;
+
+}
+
+void GlobalConfig::set_disable_platform_override(bool p_disable) {
+
+ disable_platform_override=p_disable;
+}
+
+bool GlobalConfig::is_using_datapack() const {
+
+ return using_datapack;
+}
+
+bool GlobalConfig::property_can_revert(const String& p_name) {
+
+ if (!props.has(p_name))
+ return false;
+
+ return props[p_name].initial!=props[p_name].variant;
+
+}
+
+Variant GlobalConfig::property_get_revert(const String& p_name) {
+
+ if (!props.has(p_name))
+ return Variant();
+
+ return props[p_name].initial;
+}
+
+void GlobalConfig::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("has","name"),&GlobalConfig::has);
+ ClassDB::bind_method(D_METHOD("set_order","name","pos"),&GlobalConfig::set_order);
+ ClassDB::bind_method(D_METHOD("get_order","name"),&GlobalConfig::get_order);
+ ClassDB::bind_method(D_METHOD("set_initial_value","name","value"),&GlobalConfig::set_initial_value);
+ ClassDB::bind_method(D_METHOD("add_property_info", "hint"),&GlobalConfig::_add_property_info_bind);
+ ClassDB::bind_method(D_METHOD("clear","name"),&GlobalConfig::clear);
+ ClassDB::bind_method(D_METHOD("localize_path","path"),&GlobalConfig::localize_path);
+ ClassDB::bind_method(D_METHOD("globalize_path","path"),&GlobalConfig::globalize_path);
+ ClassDB::bind_method(D_METHOD("save"),&GlobalConfig::save);
+ ClassDB::bind_method(D_METHOD("has_singleton","name"),&GlobalConfig::has_singleton);
+ ClassDB::bind_method(D_METHOD("get_singleton","name"),&GlobalConfig::get_singleton_object);
+ ClassDB::bind_method(D_METHOD("load_resource_pack","pack"),&GlobalConfig::_load_resource_pack);
+ ClassDB::bind_method(D_METHOD("property_can_revert","name"),&GlobalConfig::property_can_revert);
+ ClassDB::bind_method(D_METHOD("property_get_revert","name"),&GlobalConfig::property_get_revert);
+
+ ClassDB::bind_method(D_METHOD("save_custom","file"),&GlobalConfig::_save_custom_bnd);
+
+}
+
+GlobalConfig::GlobalConfig() {
+
+
+ singleton=this;
+ last_order=0;
+ disable_platform_override=false;
+ registering_order=true;
+
+
+ Array va;
+ InputEvent key;
+ key.type=InputEvent::KEY;
+ InputEvent joyb;
+ joyb.type=InputEvent::JOYPAD_BUTTON;
+
+
+ GLOBAL_DEF("application/name","" );
+ GLOBAL_DEF("application/main_scene","");
+ custom_prop_info["application/main_scene"]=PropertyInfo(Variant::STRING,"application/main_scene",PROPERTY_HINT_FILE,"tscn,scn,xscn,xml,res");
+ GLOBAL_DEF("application/disable_stdout",false);
+ GLOBAL_DEF("application/disable_stderr",false);
+ GLOBAL_DEF("application/use_shared_user_dir",true);
+
+
+ key.key.scancode=KEY_RETURN;
+ va.push_back(key);
+ key.key.scancode=KEY_ENTER;
+ va.push_back(key);
+ key.key.scancode=KEY_SPACE;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_BUTTON_0;
+ va.push_back(joyb);
+ GLOBAL_DEF("input/ui_accept",va);
+ input_presets.push_back("input/ui_accept");
+
+ va=Array();
+ key.key.scancode=KEY_SPACE;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_BUTTON_3;
+ va.push_back(joyb);
+ GLOBAL_DEF("input/ui_select",va);
+ input_presets.push_back("input/ui_select");
+
+ va=Array();
+ key.key.scancode=KEY_ESCAPE;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_BUTTON_1;
+ va.push_back(joyb);
+ GLOBAL_DEF("input/ui_cancel",va);
+ input_presets.push_back("input/ui_cancel");
+
+ va=Array();
+ key.key.scancode=KEY_TAB;
+ va.push_back(key);
+ GLOBAL_DEF("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);
+ GLOBAL_DEF("input/ui_focus_prev",va);
+ input_presets.push_back("input/ui_focus_prev");
+ key.key.mod.shift=false;
+
+ va=Array();
+ key.key.scancode=KEY_LEFT;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_DPAD_LEFT;
+ va.push_back(joyb);
+ GLOBAL_DEF("input/ui_left",va);
+ input_presets.push_back("input/ui_left");
+
+ va=Array();
+ key.key.scancode=KEY_RIGHT;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_DPAD_RIGHT;
+ va.push_back(joyb);
+ GLOBAL_DEF("input/ui_right",va);
+ input_presets.push_back("input/ui_right");
+
+ va=Array();
+ key.key.scancode=KEY_UP;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_DPAD_UP;
+ va.push_back(joyb);
+ GLOBAL_DEF("input/ui_up",va);
+ input_presets.push_back("input/ui_up");
+
+ va=Array();
+ key.key.scancode=KEY_DOWN;
+ va.push_back(key);
+ joyb.joy_button.button_index=JOY_DPAD_DOWN;
+ va.push_back(joyb);
+ GLOBAL_DEF("input/ui_down",va);
+ input_presets.push_back("input/ui_down");
+
+
+ va=Array();
+ key.key.scancode=KEY_PAGEUP;
+ va.push_back(key);
+ GLOBAL_DEF("input/ui_page_up",va);
+ input_presets.push_back("input/ui_page_up");
+
+ va=Array();
+ key.key.scancode=KEY_PAGEDOWN;
+ va.push_back(key);
+ GLOBAL_DEF("input/ui_page_down",va);
+ input_presets.push_back("input/ui_page_down");
+
+ //GLOBAL_DEF("display/handheld/orientation", "landscape");
+
+
+ custom_prop_info["display/handheld/orientation"]=PropertyInfo(Variant::STRING,"display/handheld/orientation",PROPERTY_HINT_ENUM,"landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
+ custom_prop_info["rendering/threads/thread_model"]=PropertyInfo(Variant::INT,"rendering/threads/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
+ custom_prop_info["physics/2d/thread_model"]=PropertyInfo(Variant::INT,"physics/2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
+
+ GLOBAL_DEF("debug/profiler/max_functions",16384);
+ using_datapack=false;
+}
+
+
+GlobalConfig::~GlobalConfig() {
+
+ singleton=NULL;
+}
+
+
diff --git a/core/global_config.h b/core/global_config.h
new file mode 100644
index 0000000000..471f1ff885
--- /dev/null
+++ b/core/global_config.h
@@ -0,0 +1,160 @@
+/*************************************************************************/
+/* globals.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 GLOBAL_CONFIG_H
+#define GLOBAL_CONFIG_H
+
+#include "object.h"
+#include "set.h"
+#include "os/thread_safe.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+
+class GlobalConfig : public Object {
+
+ GDCLASS( GlobalConfig, Object );
+ _THREAD_SAFE_CLASS_
+
+public:
+
+ typedef Map<String,Variant> CustomMap;
+
+ struct Singleton {
+ StringName name;
+ Object *ptr;
+ Singleton(const StringName& p_name=StringName(), Object *p_ptr=NULL) { name=p_name; ptr=p_ptr; }
+ };
+
+protected:
+
+ enum {
+ NO_ORDER_BASE=1<<18
+ };
+
+ struct VariantContainer {
+ int order;
+ bool persist;
+ Variant variant;
+ Variant initial;
+ bool hide_from_editor;
+ bool overrided;
+ VariantContainer(){ order=0; hide_from_editor=false; persist=false; overrided=false; }
+ 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);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ static GlobalConfig *singleton;
+
+ Error _load_settings(const String p_path);
+ Error _load_settings_binary(const String p_path);
+
+ Error _save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
+ Error _save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
+
+ List<Singleton> singletons;
+ Map<StringName,Object*> singleton_ptrs;
+
+ Error _save_custom_bnd(const String& p_file);
+
+ bool _load_resource_pack(const String& p_pack);
+
+ void _add_property_info_bind(const Dictionary& p_info);
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ bool has(String p_var) const;
+ String localize_path(const String& p_path) const;
+ String globalize_path(const String& p_path) const;
+
+
+ void set_initial_value(const String& p_name, const Variant & p_value);
+ bool property_can_revert(const String& p_name);
+ Variant property_get_revert(const String& p_name);
+
+ String get_resource_path() const;
+
+ static GlobalConfig *get_singleton();
+
+ void clear(const String& p_name);
+ int get_order(const String& p_name) const;
+ void set_order(const String& p_name, int p_order);
+
+ Error setup(const String& p_path, const String &p_main_pack);
+
+ Error save_custom(const String& p_path="",const CustomMap& p_custom=CustomMap(),const Set<String>& p_ignore_masks=Set<String>());
+ Error save();
+ void set_custom_property_info(const String& p_prop,const PropertyInfo& p_info);
+
+ void add_singleton(const Singleton &p_singleton);
+ void get_singletons(List<Singleton> *p_singletons);
+
+ bool has_singleton(const String& p_name) const;
+
+ 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;
+
+ void register_global_defaults();
+
+ bool is_using_datapack() const;
+
+ void set_registering_order(bool p_registering);
+
+ GlobalConfig();
+ ~GlobalConfig();
+
+};
+
+//not a macro any longer
+Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default);
+#define GLOBAL_DEF(m_var,m_value) _GLOBAL_DEF(m_var,m_value)
+#define GLOBAL_GET(m_var) GlobalConfig::get_singleton()->get(m_var)
+
+#endif
diff --git a/core/globals.cpp b/core/globals.cpp
deleted file mode 100644
index ed0b6f6d8b..0000000000
--- a/core/globals.cpp
+++ /dev/null
@@ -1,1049 +0,0 @@
-/*************************************************************************/
-/* globals.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "globals.h"
-
-#include "os/dir_access.h"
-#include "os/file_access.h"
-#include "os/keyboard.h"
-#include "io/marshalls.h"
-#include "bind/core_bind.h"
-#include "os/os.h"
-#include "io/file_access_pack.h"
-#include "io/file_access_network.h"
-#include "variant_parser.h"
-
-#define FORMAT_VERSION 3
-
-GlobalConfig *GlobalConfig::singleton=NULL;
-
-GlobalConfig *GlobalConfig::get_singleton() {
-
- return singleton;
-}
-
-String GlobalConfig::get_resource_path() const {
-
- return resource_path;
-};
-
-String GlobalConfig::localize_path(const String& p_path) const {
-
- if (resource_path=="")
- return p_path; //not initialied yet
-
- if (p_path.begins_with("res://") || p_path.begins_with("user://") ||
- (p_path.is_abs_path() && !p_path.begins_with(resource_path)))
- return p_path.simplify_path();
-
-
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-
- String path = p_path.replace("\\","/").simplify_path();
-
- if (dir->change_dir(path)==OK) {
-
- String cwd = dir->get_current_dir();
- cwd = cwd.replace("\\","/");
-
- memdelete(dir);
-
- if (!cwd.begins_with(resource_path)) {
- return p_path;
- };
-
- return cwd.replace_first(resource_path, "res:/");
- } else {
-
- memdelete(dir);
-
- int sep = path.find_last("/");
- if (sep == -1) {
- return "res://"+path;
- };
-
-
- String parent = path.substr(0, sep);
-
- String plocal = localize_path(parent);
- if (plocal == "") {
- return "";
- };
- return plocal + path.substr(sep, path.size() - sep);
- };
-
-}
-
-void GlobalConfig::set_initial_value(const String& p_name, const Variant & p_value) {
-
- ERR_FAIL_COND(!props.has(p_name));
- props[p_name].initial=p_value;
-}
-
-
-String GlobalConfig::globalize_path(const String& p_path) const {
-
- if (p_path.begins_with("res://")) {
-
- if (resource_path != "") {
-
- return p_path.replace("res:/",resource_path);
- };
- return p_path.replace("res://", "");
- };
-
- return p_path;
-}
-
-
-bool GlobalConfig::_set(const StringName& p_name, const Variant& p_value) {
-
- _THREAD_SAFE_METHOD_
-
-
- if (p_value.get_type()==Variant::NIL)
- props.erase(p_name);
- else {
- 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++ + (registering_order?0:NO_ORDER_BASE));
- }
- }
-
- if (!disable_platform_override) {
-
- String s=String(p_name);
- int sl = s.find("/");
- int p = s.find(".");
- if (p!=-1 && sl!=-1 && p < sl) {
-
- Vector<String> ps = s.substr(0,sl).split(".");
- String prop=s.substr(sl,s.length()-sl);
- for(int i=1;i<ps.size();i++) {
-
- if (ps[i]==OS::get_singleton()->get_name()) {
-
- String fullprop=ps[0]+prop;
-
- set(fullprop,p_value);
- props[fullprop].overrided=true;
- }
- }
- }
-
- }
-
- return true;
-}
-bool GlobalConfig::_get(const StringName& p_name,Variant &r_ret) const {
-
- _THREAD_SAFE_METHOD_
-
- if (!props.has(p_name)) {
- print_line("WARNING: not found: "+String(p_name));
- return false;
- }
- r_ret=props[p_name].variant;
- return true;
-
-}
-
-struct _VCSort {
-
- String name;
- Variant::Type type;
- int order;
- int flags;
-
- bool operator<(const _VCSort& p_vcs) const{ return order==p_vcs.order?name<p_vcs.name:order< p_vcs.order; }
-};
-
-void GlobalConfig::_get_property_list(List<PropertyInfo> *p_list) const {
-
- _THREAD_SAFE_METHOD_
-
- Set<_VCSort> vclist;
-
- for(Map<StringName,VariantContainer>::Element *E=props.front();E;E=E->next()) {
-
- const VariantContainer *v=&E->get();
-
- if (v->hide_from_editor)
- continue;
-
- _VCSort vc;
- vc.name=E->key();
- vc.order=v->order;
- vc.type=v->variant.get_type();
- if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload"))
- vc.flags=PROPERTY_USAGE_STORAGE;
- else
- vc.flags=PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_STORAGE;
-
- vclist.insert(vc);
- }
-
- for(Set<_VCSort>::Element *E=vclist.front();E;E=E->next()) {
-
- if (custom_prop_info.has(E->get().name)) {
- PropertyInfo pi=custom_prop_info[E->get().name];
- pi.name=E->get().name;
- pi.usage=E->get().flags;
- p_list->push_back( pi );
- } else
- p_list->push_back( PropertyInfo(E->get().type, E->get().name,PROPERTY_HINT_NONE,"",E->get().flags) );
- }
-}
-
-
-
-bool GlobalConfig::_load_resource_pack(const String& p_pack) {
-
- if (PackedData::get_singleton()->is_disabled())
- return false;
-
- bool ok = PackedData::get_singleton()->add_pack(p_pack)==OK;
-
- if (!ok)
- return false;
-
- //if data.pck is found, all directory access will be from here
- DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES);
- using_datapack=true;
-
- return true;
-}
-
-Error GlobalConfig::setup(const String& p_path,const String & p_main_pack) {
-
- //an absolute mess of a function, must be cleaned up and reorganized somehow at some point
-
- //_load_settings(p_path+"/override.cfg");
-
- if (p_main_pack!="") {
-
- bool ok = _load_resource_pack(p_main_pack);
- ERR_FAIL_COND_V(!ok,ERR_CANT_OPEN);
-
- if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
-
- _load_settings("res://override.cfg");
-
- }
-
- return OK;
-
- }
-
- if (OS::get_singleton()->get_executable_path()!="") {
-
- if (_load_resource_pack(OS::get_singleton()->get_executable_path())) {
-
- if (p_path!="") {
- resource_path=p_path;
- } else {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- resource_path=d->get_current_dir();
- memdelete(d);
-
- }
- if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
-
- _load_settings("res://override.cfg");
-
- }
-
-
-
- return OK;
- }
-
- }
-
-
- if (FileAccessNetworkClient::get_singleton()) {
-
- if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
-
- _load_settings("res://override.cfg");
-
- }
-
- 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.
- resource_path=OS::get_singleton()->get_resource_dir().replace("\\","/");
- if (resource_path.length() && resource_path[ resource_path.length()-1]=='/')
- resource_path=resource_path.substr(0,resource_path.length()-1); // chop end
-
- print_line("has res dir: "+resource_path);
- if (!_load_resource_pack("res://data.pck"))
- _load_resource_pack("res://data.zip");
- // make sure this is load from the resource path
- print_line("exists engine cfg? "+itos(FileAccess::exists("/godot.cfg")));
- if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
- print_line("loaded godot.cfg");
- _load_settings("res://override.cfg");
-
- }
-
- return OK;
- }
-
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (!d) {
-
- resource_path = p_path;
-
- } else {
-
- d->change_dir(p_path);
-
- String candidate = d->get_current_dir();
- String current_dir = d->get_current_dir();
- String exec_name = OS::get_singleton()->get_executable_path().get_file().get_basename();
- bool found = false;
- bool first_time=true;
-
- while(true) {
- //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+".zip") )) {
- if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
-
- _load_settings("res://override.cfg");
- found=true;
-
-
- }
- break;
- } else if (first_time && (_load_resource_pack(current_dir+"/data.pck") || _load_resource_pack(current_dir+"/data.zip") )) {
- if (_load_settings("res://godot.cfg")==OK || _load_settings_binary("res://godot.cfb")==OK) {
-
- _load_settings("res://override.cfg");
- found=true;
-
-
- }
- break;
- } else if (_load_settings(current_dir+"/godot.cfg")==OK || _load_settings_binary(current_dir+"/godot.cfb")==OK) {
-
- _load_settings(current_dir+"/override.cfg");
- candidate=current_dir;
- found=true;
- break;
- }
-
- d->change_dir("..");
- if (d->get_current_dir()==current_dir)
- break; //not doing anything useful
- current_dir=d->get_current_dir();
- first_time=false;
- }
-
-
- resource_path=candidate;
- resource_path = resource_path.replace("\\","/"); // windows path to unix path just in case
- memdelete(d);
-
- if (!found)
- return ERR_FILE_NOT_FOUND;
- };
-
-
- if (resource_path.length() && resource_path[ resource_path.length()-1]=='/')
- resource_path=resource_path.substr(0,resource_path.length()-1); // chop end
-
- return OK;
-}
-
-bool GlobalConfig::has(String p_var) const {
-
- _THREAD_SAFE_METHOD_
-
- return props.has(p_var);
-}
-
-
-void GlobalConfig::set_registering_order(bool p_enable) {
-
- registering_order=p_enable;
-}
-
-Error GlobalConfig::_load_settings_binary(const String p_path) {
-
- Error err;
- FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
- if (err!=OK) {
- return err;
- }
-
-
- uint8_t hdr[4];
- f->get_buffer(hdr,4);
- if (hdr[0]!='E'|| hdr[1]!='C' || hdr[2]!='F' || hdr[3]!='G') {
-
- memdelete(f);
- ERR_EXPLAIN("Corrupted header in binary godot.cfb (not ECFG)");
- ERR_FAIL_V(ERR_FILE_CORRUPT;)
- }
-
- set_registering_order(false);
-
- uint32_t count=f->get_32();
-
- for(uint32_t i=0;i<count;i++) {
-
- uint32_t slen=f->get_32();
- CharString cs;
- cs.resize(slen+1);
- cs[slen]=0;
- f->get_buffer((uint8_t*)cs.ptr(),slen);
- String key;
- key.parse_utf8(cs.ptr());
-
- uint32_t vlen=f->get_32();
- Vector<uint8_t> d;
- d.resize(vlen);
- f->get_buffer(d.ptr(),vlen);
- Variant value;
- Error err = decode_variant(value,d.ptr(),d.size());
- ERR_EXPLAIN("Error decoding property: "+key);
- ERR_CONTINUE(err!=OK);
- set(key,value);
-
- }
-
- set_registering_order(true);
-
-
- return OK;
-}
-Error GlobalConfig::_load_settings(const String p_path) {
-
-
-
- Error err;
- FileAccess *f= FileAccess::open(p_path,FileAccess::READ,&err);
-
- if (!f)
- return ERR_CANT_OPEN;
-
- VariantParser::StreamFile stream;
- stream.f=f;
-
- String assign;
- Variant value;
- VariantParser::Tag next_tag;
-
- int lines=0;
- String error_text;
-
- String section;
-
- 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("GlobalConfig::load - "+p_path+":"+itos(lines)+" error: "+error_text);
- memdelete(f);
- return err;
- }
-
- if (assign!=String()) {
- if (section==String() && assign=="config_version") {
- int config_version = value;
- if (config_version > FORMAT_VERSION) {
- memdelete(f);
- ERR_FAIL_COND_V(config_version > FORMAT_VERSION,ERR_FILE_CANT_OPEN);
- }
-
- }
- set(section+"/"+assign,value);
- } else if (next_tag.name!=String()) {
- section=next_tag.name;
- }
- }
-
- memdelete(f);
-
- return OK;
-
-}
-
-
-
-int GlobalConfig::get_order(const String& p_name) const {
-
- ERR_FAIL_COND_V(!props.has(p_name),-1);
- return props[p_name].order;
-}
-
-
-void GlobalConfig::set_order(const String& p_name, int p_order){
-
- ERR_FAIL_COND(!props.has(p_name));
- props[p_name].order=p_order;
-}
-
-void GlobalConfig::clear(const String& p_name) {
-
- ERR_FAIL_COND(!props.has(p_name));
- props.erase(p_name);
-}
-
-Error GlobalConfig::save() {
-
- return save_custom(get_resource_path()+"/godot.cfg");
-}
-
-Error GlobalConfig::_save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom) {
-
-
- Error err;
- FileAccess *file = FileAccess::open(p_file,FileAccess::WRITE,&err);
- if (err!=OK) {
-
- ERR_EXPLAIN("Coudln't save godot.cfb at "+p_file);
- ERR_FAIL_COND_V(err,err)
- }
-
- uint8_t hdr[4]={'E','C','F','G'};
- file->store_buffer(hdr,4);
-
- int count=0;
-
- for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
-
- for(List<String>::Element *F=E->get().front();F;F=F->next()) {
-
- count++;
- }
- }
-
- file->store_32(count); //store how many properties are saved
-
-
- for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
-
- for(List<String>::Element *F=E->get().front();F;F=F->next()) {
-
- String key = F->get();
- if (E->key()!="")
- key=E->key()+"/"+key;
- Variant value;
- if (p_custom.has(key))
- value=p_custom[key];
- else
- value = get(key);
-
- file->store_32(key.length());
- file->store_string(key);
-
- int len;
- Error err = encode_variant(value,NULL,len);
- if (err!=OK)
- memdelete(file);
- ERR_FAIL_COND_V( err != OK, ERR_INVALID_DATA );
-
- Vector<uint8_t> buff;
- buff.resize(len);
-
- err = encode_variant(value,&buff[0],len);
- if (err!=OK)
- memdelete(file);
- ERR_FAIL_COND_V( err != OK, ERR_INVALID_DATA );
- file->store_32(len);
- file->store_buffer(buff.ptr(),buff.size());
- }
- }
-
- file->close();
- memdelete(file);
-
-
- return OK;
-}
-
-
-Error GlobalConfig::_save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom) {
-
- Error err;
- FileAccess *file = FileAccess::open(p_file,FileAccess::WRITE,&err);
-
- if (err) {
- ERR_EXPLAIN("Coudln't save godot.cfg - "+p_file);
- ERR_FAIL_COND_V(err,err)
- }
-
- file->store_string("config_version="+itos(FORMAT_VERSION)+"\n");
-
-
- for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
-
- if (E!=props.front())
- file->store_string("\n");
-
- if (E->key()!="")
- file->store_string("["+E->key()+"]\n\n");
- for(List<String>::Element *F=E->get().front();F;F=F->next()) {
-
- String key = F->get();
- if (E->key()!="")
- key=E->key()+"/"+key;
- Variant value;
- if (p_custom.has(key))
- value=p_custom[key];
- else
- value = get(key);
-
-
- String vstr;
- VariantWriter::write_to_string(value,vstr);
- file->store_string(F->get()+"="+vstr+"\n");
-
- }
- }
-
- file->close();
- memdelete(file);
-
- return OK;
-}
-
-Error GlobalConfig::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
-
- return save_custom(p_file);
-};
-
-Error GlobalConfig::save_custom(const String& p_path,const CustomMap& p_custom,const Set<String>& p_ignore_masks) {
-
- ERR_FAIL_COND_V(p_path=="",ERR_INVALID_PARAMETER);
-
- Set<_VCSort> vclist;
-
- for(Map<StringName,VariantContainer>::Element *G=props.front();G;G=G->next()) {
-
- const VariantContainer *v=&G->get();
-
- if (v->hide_from_editor)
- continue;
-
- if (p_custom.has(G->key()))
- continue;
-
- bool discard=false;
-
- for(const Set<String>::Element *E=p_ignore_masks.front();E;E=E->next()) {
-
- if ( String(G->key()).match(E->get())) {
- discard=true;
- break;
- }
- }
-
- if (discard)
- continue;
-
- _VCSort vc;
- vc.name=G->key();//*k;
- vc.order=v->order;
- vc.type=v->variant.get_type();
- vc.flags=PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_STORAGE;
- if (v->variant==v->initial)
- continue;
-
-
- vclist.insert(vc);
- }
-
- for(const Map<String,Variant>::Element *E=p_custom.front();E;E=E->next()) {
-
-
- _VCSort vc;
- vc.name=E->key();
- vc.order=0xFFFFFFF;
- vc.type=E->get().get_type();
- vc.flags=PROPERTY_USAGE_STORAGE;
- vclist.insert(vc);
- }
-
- Map<String,List<String> > props;
-
- for(Set<_VCSort>::Element *E=vclist.front();E;E=E->next()) {
-
- String category = E->get().name;
- String name = E->get().name;
-
- int div = category.find("/");
-
- if (div<0)
- category="";
- else {
-
- category=category.substr(0,div);
- name=name.substr(div+1,name.size());
- }
- props[category].push_back(name);
- }
-
-
-
- if (p_path.ends_with(".cfg"))
- return _save_settings_text(p_path,props,p_custom);
- else if (p_path.ends_with(".cfb"))
- return _save_settings_binary(p_path,props,p_custom);
- else {
-
- ERR_EXPLAIN("Unknown config file format: "+p_path);
- ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
- }
-
- return OK;
-
-#if 0
- Error err = file->open(dst_file,FileAccess::WRITE);
- if (err) {
- memdelete(file);
- ERR_EXPLAIN("Coudln't save godot.cfg");
- ERR_FAIL_COND_V(err,err)
- }
-
-
- for(Map<String,List<String> >::Element *E=props.front();E;E=E->next()) {
-
- if (E!=props.front())
- file->store_string("\n");
-
- if (E->key()!="")
- file->store_string("["+E->key()+"]\n\n");
- for(List<String>::Element *F=E->get().front();F;F=F->next()) {
-
- String key = F->get();
- if (E->key()!="")
- key=E->key()+"/"+key;
- Variant value;
-
- if (p_custom.has(key))
- value=p_custom[key];
- else
- value = get(key);
-
- file->store_string(F->get()+"="+_encode_variant(value)+"\n");
-
- }
- }
-
- file->close();
- memdelete(file);
-
-
- return OK;
-#endif
-}
-
-Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default) {
-
- if (GlobalConfig::get_singleton()->has(p_var)) {
- GlobalConfig::get_singleton()->set_initial_value(p_var,p_default);
- return GlobalConfig::get_singleton()->get(p_var);
- }
- GlobalConfig::get_singleton()->set(p_var,p_default);
- GlobalConfig::get_singleton()->set_initial_value(p_var,p_default);
- return p_default;
-
-}
-
-void GlobalConfig::add_singleton(const Singleton &p_singleton) {
-
- singletons.push_back(p_singleton);
- singleton_ptrs[p_singleton.name]=p_singleton.ptr;
-}
-
-Object* GlobalConfig::get_singleton_object(const String& p_name) const {
-
-
- const Map<StringName,Object*>::Element *E=singleton_ptrs.find(p_name);
- if (!E)
- return NULL;
- else
- return E->get();
-
-};
-
-bool GlobalConfig::has_singleton(const String& p_name) const {
-
- return get_singleton_object(p_name) != NULL;
-};
-
-void GlobalConfig::get_singletons(List<Singleton> *p_singletons) {
-
- for(List<Singleton>::Element *E=singletons.front();E;E=E->next())
- p_singletons->push_back(E->get());
-}
-
-Vector<String> GlobalConfig::get_optimizer_presets() const {
-
- List<PropertyInfo> pi;
- GlobalConfig::get_singleton()->get_property_list(&pi);
- Vector<String> names;
-
- for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
-
- if (!E->get().name.begins_with("optimizer_presets/"))
- continue;
- names.push_back(E->get().name.get_slicec('/',1));
- }
-
- names.sort();
-
- return names;
-
-}
-
-void GlobalConfig::_add_property_info_bind(const Dictionary& p_info) {
-
- ERR_FAIL_COND(!p_info.has("name"));
- ERR_FAIL_COND(!p_info.has("type"));
-
- PropertyInfo pinfo;
- pinfo.name = p_info["name"];
- ERR_FAIL_COND(!props.has(pinfo.name));
- pinfo.type = Variant::Type(p_info["type"].operator int());
- ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX);
-
- if (p_info.has("hint"))
- pinfo.hint = PropertyHint(p_info["hint"].operator int());
- if (p_info.has("hint_string"))
- pinfo.hint_string = p_info["hint_string"];
-
- set_custom_property_info(pinfo.name, pinfo);
-}
-
-void GlobalConfig::set_custom_property_info(const String& p_prop,const PropertyInfo& p_info) {
-
- ERR_FAIL_COND(!props.has(p_prop));
- custom_prop_info[p_prop]=p_info;
- custom_prop_info[p_prop].name=p_prop;
-
-}
-
-void GlobalConfig::set_disable_platform_override(bool p_disable) {
-
- disable_platform_override=p_disable;
-}
-
-bool GlobalConfig::is_using_datapack() const {
-
- return using_datapack;
-}
-
-bool GlobalConfig::property_can_revert(const String& p_name) {
-
- if (!props.has(p_name))
- return false;
-
- return props[p_name].initial!=props[p_name].variant;
-
-}
-
-Variant GlobalConfig::property_get_revert(const String& p_name) {
-
- if (!props.has(p_name))
- return Variant();
-
- return props[p_name].initial;
-}
-
-void GlobalConfig::_bind_methods() {
-
- ClassDB::bind_method(_MD("has","name"),&GlobalConfig::has);
- ClassDB::bind_method(_MD("set_order","name","pos"),&GlobalConfig::set_order);
- ClassDB::bind_method(_MD("get_order","name"),&GlobalConfig::get_order);
- ClassDB::bind_method(_MD("set_initial_value","name","value"),&GlobalConfig::set_initial_value);
- ClassDB::bind_method(_MD("add_property_info", "hint"),&GlobalConfig::_add_property_info_bind);
- ClassDB::bind_method(_MD("clear","name"),&GlobalConfig::clear);
- ClassDB::bind_method(_MD("localize_path","path"),&GlobalConfig::localize_path);
- ClassDB::bind_method(_MD("globalize_path","path"),&GlobalConfig::globalize_path);
- ClassDB::bind_method(_MD("save"),&GlobalConfig::save);
- ClassDB::bind_method(_MD("has_singleton","name"),&GlobalConfig::has_singleton);
- ClassDB::bind_method(_MD("get_singleton","name"),&GlobalConfig::get_singleton_object);
- ClassDB::bind_method(_MD("load_resource_pack","pack"),&GlobalConfig::_load_resource_pack);
- ClassDB::bind_method(_MD("property_can_revert","name"),&GlobalConfig::property_can_revert);
- ClassDB::bind_method(_MD("property_get_revert","name"),&GlobalConfig::property_get_revert);
-
- ClassDB::bind_method(_MD("save_custom","file"),&GlobalConfig::_save_custom_bnd);
-
-}
-
-GlobalConfig::GlobalConfig() {
-
-
- singleton=this;
- last_order=0;
- disable_platform_override=false;
- registering_order=true;
-
-
- Array va;
- InputEvent key;
- key.type=InputEvent::KEY;
- InputEvent joyb;
- joyb.type=InputEvent::JOYPAD_BUTTON;
-
-
- GLOBAL_DEF("application/name","" );
- GLOBAL_DEF("application/main_scene","");
- custom_prop_info["application/main_scene"]=PropertyInfo(Variant::STRING,"application/main_scene",PROPERTY_HINT_FILE,"tscn,scn,xscn,xml,res");
- GLOBAL_DEF("application/disable_stdout",false);
- GLOBAL_DEF("application/disable_stderr",false);
- GLOBAL_DEF("application/use_shared_user_dir",true);
-
-
- key.key.scancode=KEY_RETURN;
- va.push_back(key);
- key.key.scancode=KEY_ENTER;
- va.push_back(key);
- key.key.scancode=KEY_SPACE;
- va.push_back(key);
- joyb.joy_button.button_index=JOY_BUTTON_0;
- va.push_back(joyb);
- GLOBAL_DEF("input/ui_accept",va);
- input_presets.push_back("input/ui_accept");
-
- va=Array();
- key.key.scancode=KEY_SPACE;
- va.push_back(key);
- joyb.joy_button.button_index=JOY_BUTTON_3;
- va.push_back(joyb);
- GLOBAL_DEF("input/ui_select",va);
- input_presets.push_back("input/ui_select");
-
- va=Array();
- key.key.scancode=KEY_ESCAPE;
- va.push_back(key);
- joyb.joy_button.button_index=JOY_BUTTON_1;
- va.push_back(joyb);
- GLOBAL_DEF("input/ui_cancel",va);
- input_presets.push_back("input/ui_cancel");
-
- va=Array();
- key.key.scancode=KEY_TAB;
- va.push_back(key);
- GLOBAL_DEF("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);
- GLOBAL_DEF("input/ui_focus_prev",va);
- input_presets.push_back("input/ui_focus_prev");
- key.key.mod.shift=false;
-
- va=Array();
- key.key.scancode=KEY_LEFT;
- va.push_back(key);
- joyb.joy_button.button_index=JOY_DPAD_LEFT;
- va.push_back(joyb);
- GLOBAL_DEF("input/ui_left",va);
- input_presets.push_back("input/ui_left");
-
- va=Array();
- key.key.scancode=KEY_RIGHT;
- va.push_back(key);
- joyb.joy_button.button_index=JOY_DPAD_RIGHT;
- va.push_back(joyb);
- GLOBAL_DEF("input/ui_right",va);
- input_presets.push_back("input/ui_right");
-
- va=Array();
- key.key.scancode=KEY_UP;
- va.push_back(key);
- joyb.joy_button.button_index=JOY_DPAD_UP;
- va.push_back(joyb);
- GLOBAL_DEF("input/ui_up",va);
- input_presets.push_back("input/ui_up");
-
- va=Array();
- key.key.scancode=KEY_DOWN;
- va.push_back(key);
- joyb.joy_button.button_index=JOY_DPAD_DOWN;
- va.push_back(joyb);
- GLOBAL_DEF("input/ui_down",va);
- input_presets.push_back("input/ui_down");
-
-
- va=Array();
- key.key.scancode=KEY_PAGEUP;
- va.push_back(key);
- GLOBAL_DEF("input/ui_page_up",va);
- input_presets.push_back("input/ui_page_up");
-
- va=Array();
- key.key.scancode=KEY_PAGEDOWN;
- va.push_back(key);
- GLOBAL_DEF("input/ui_page_down",va);
- input_presets.push_back("input/ui_page_down");
-
- //GLOBAL_DEF("display/handheld/orientation", "landscape");
-
-
- custom_prop_info["display/handheld/orientation"]=PropertyInfo(Variant::STRING,"display/handheld/orientation",PROPERTY_HINT_ENUM,"landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor");
- custom_prop_info["rendering/threads/thread_model"]=PropertyInfo(Variant::INT,"rendering/threads/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
- custom_prop_info["physics/2d/thread_model"]=PropertyInfo(Variant::INT,"physics/2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
-
- GLOBAL_DEF("debug/profiler/max_functions",16384);
- using_datapack=false;
-}
-
-
-GlobalConfig::~GlobalConfig() {
-
- singleton=NULL;
-}
-
-
diff --git a/core/globals.h b/core/globals.h
deleted file mode 100644
index faf077f2a5..0000000000
--- a/core/globals.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*************************************************************************/
-/* globals.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 GLOBALS_H
-#define GLOBALS_H
-
-#include "object.h"
-#include "set.h"
-#include "os/thread_safe.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-
-class GlobalConfig : public Object {
-
- GDCLASS( GlobalConfig, Object );
- _THREAD_SAFE_CLASS_
-
-public:
-
- typedef Map<String,Variant> CustomMap;
-
- struct Singleton {
- StringName name;
- Object *ptr;
- Singleton(const StringName& p_name=StringName(), Object *p_ptr=NULL) { name=p_name; ptr=p_ptr; }
- };
-
-protected:
-
- enum {
- NO_ORDER_BASE=1<<18
- };
-
- struct VariantContainer {
- int order;
- bool persist;
- Variant variant;
- Variant initial;
- bool hide_from_editor;
- bool overrided;
- VariantContainer(){ order=0; hide_from_editor=false; persist=false; overrided=false; }
- 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);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
- static GlobalConfig *singleton;
-
- Error _load_settings(const String p_path);
- Error _load_settings_binary(const String p_path);
-
- Error _save_settings_text(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
- Error _save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap());
-
- List<Singleton> singletons;
- Map<StringName,Object*> singleton_ptrs;
-
- Error _save_custom_bnd(const String& p_file);
-
- bool _load_resource_pack(const String& p_pack);
-
- void _add_property_info_bind(const Dictionary& p_info);
-
-protected:
-
- static void _bind_methods();
-public:
-
-
- bool has(String p_var) const;
- String localize_path(const String& p_path) const;
- String globalize_path(const String& p_path) const;
-
-
- void set_initial_value(const String& p_name, const Variant & p_value);
- bool property_can_revert(const String& p_name);
- Variant property_get_revert(const String& p_name);
-
- String get_resource_path() const;
-
- static GlobalConfig *get_singleton();
-
- void clear(const String& p_name);
- int get_order(const String& p_name) const;
- void set_order(const String& p_name, int p_order);
-
- Error setup(const String& p_path, const String &p_main_pack);
-
- Error save_custom(const String& p_path="",const CustomMap& p_custom=CustomMap(),const Set<String>& p_ignore_masks=Set<String>());
- Error save();
- void set_custom_property_info(const String& p_prop,const PropertyInfo& p_info);
-
- void add_singleton(const Singleton &p_singleton);
- void get_singletons(List<Singleton> *p_singletons);
-
- bool has_singleton(const String& p_name) const;
-
- 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;
-
- void register_global_defaults();
-
- bool is_using_datapack() const;
-
- void set_registering_order(bool p_registering);
-
- GlobalConfig();
- ~GlobalConfig();
-
-};
-
-//not a macro any longer
-Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default);
-#define GLOBAL_DEF(m_var,m_value) _GLOBAL_DEF(m_var,m_value)
-#define GLOBAL_GET(m_var) GlobalConfig::get_singleton()->get(m_var)
-
-#endif
diff --git a/core/hash_map.h b/core/hash_map.h
index 0d55206935..515fc6c4fe 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -30,40 +30,45 @@
#define HASH_MAP_H
#include "hashfuncs.h"
+#include "math_funcs.h"
#include "error_macros.h"
#include "ustring.h"
#include "os/memory.h"
#include "list.h"
-
-class HashMapHahserDefault {
-public:
-
+struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
- static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) {
- uint64_t v=p_int;
- v = (~v) + (v << 18); // v = (v << 18) - v - 1;
- v = v ^ (v >> 31);
- v = v * 21; // v = (v + (v << 2)) + (v << 4);
- v = v ^ (v >> 11);
- v = v + (v << 6);
- v = v ^ (v >> 22);
- return (int) v;
- }
- static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
+ static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
-
- static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
+ static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
+ static _FORCE_INLINE_ uint32_t hash(const double p_double){ return hash_djb2_one_float(p_double); }
+ static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
- static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
+ static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar){ return (uint32_t)p_wchar; }
//static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
};
+template <typename T>
+struct HashMapComparatorDefault {
+ static bool compare(const T& p_lhs, const T& p_rhs) {
+ return p_lhs == p_rhs;
+ }
+
+ bool compare(const float& p_lhs, const float& p_rhs) {
+ return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
+ }
+
+ bool compare(const double& p_lhs, const double& p_rhs) {
+ return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
+ }
+};
+
/**
* @class HashMap
* @author Juan Linietsky <reduzio@gmail.com>
@@ -74,13 +79,14 @@ public:
* @param TKey Key, search is based on it, needs to be hasheable. It is unique in this container.
* @param TData Data, data associated with the key
* @param Hasher Hasher object, needs to provide a valid static hash function for TKey
+ * @param Comparator comparator object, needs to be able to safely compare two TKey values. It needs to ensure that x == x for any items inserted in the map. Bear in mind that nan != nan when implementing an equality check.
* @param MIN_HASH_TABLE_POWER Miminum size of the hash table, as a power of two. You rarely need to change this parameter.
* @param RELATIONSHIP Relationship at which the hash table is resized. if amount of elements is RELATIONSHIP
* times bigger than the hash table, table is resized to solve this condition. if RELATIONSHIP is zero, table is always MIN_HASH_TABLE_POWER.
*
*/
-template<class TKey, class TData, class Hasher=HashMapHahserDefault,uint8_t MIN_HASH_TABLE_POWER=3,uint8_t RELATIONSHIP=8>
+template<class TKey, class TData, class Hasher=HashMapHasherDefault, class Comparator=HashMapComparatorDefault<TKey>, uint8_t MIN_HASH_TABLE_POWER=3,uint8_t RELATIONSHIP=8>
class HashMap {
public:
@@ -194,7 +200,6 @@ private:
}
-
/* I want to have only one function.. */
_FORCE_INLINE_ const Entry * get_entry( const TKey& p_key ) const {
@@ -206,7 +211,7 @@ private:
while (e) {
/* checking hash first avoids comparing key, which may take longer */
- if (e->hash == hash && e->pair.key == p_key ) {
+ if (e->hash == hash && Comparator::compare(e->pair.key,p_key) ) {
/* the pair exists in this hashtable, so just update data */
return e;
@@ -253,7 +258,6 @@ private:
for (int i=0;i<( 1<<p_t.hash_table_power );i++) {
hash_table[i]=NULL;
- /* elements will be in the reverse order, but it doesn't matter */
const Entry *e = p_t.hash_table[i];
@@ -385,7 +389,7 @@ public:
while (e) {
/* checking hash first avoids comparing key, which may take longer */
- if (e->hash == hash && e->pair.key == p_custom_key ) {
+ if (e->hash == hash && Comparator::compare(e->pair.key,p_custom_key) ) {
/* the pair exists in this hashtable, so just update data */
return &e->pair.data;
@@ -411,7 +415,7 @@ public:
while (e) {
/* checking hash first avoids comparing key, which may take longer */
- if (e->hash == hash && e->pair.key == p_custom_key ) {
+ if (e->hash == hash && Comparator::compare(e->pair.key,p_custom_key) ) {
/* the pair exists in this hashtable, so just update data */
return &e->pair.data;
@@ -442,7 +446,7 @@ public:
while (e) {
/* checking hash first avoids comparing key, which may take longer */
- if (e->hash == hash && e->pair.key == p_key ) {
+ if (e->hash == hash && Comparator::compare(e->pair.key,p_key) ) {
if (p) {
@@ -637,7 +641,8 @@ public:
clear();
}
-
};
+
+
#endif
diff --git a/core/hashfuncs.h b/core/hashfuncs.h
index e9e57d8b42..121d7e8c59 100644
--- a/core/hashfuncs.h
+++ b/core/hashfuncs.h
@@ -29,7 +29,8 @@
#ifndef HASHFUNCS_H
#define HASHFUNCS_H
-
+#include "math_funcs.h"
+#include "math_defs.h"
#include "typedefs.h"
/**
@@ -69,19 +70,52 @@ static inline uint32_t hash_djb2_one_32(uint32_t p_in,uint32_t p_prev=5381) {
return ((p_prev<<5)+p_prev)+p_in;
}
+static inline uint32_t hash_one_uint64(const uint64_t p_int) {
+ uint64_t v=p_int;
+ v = (~v) + (v << 18); // v = (v << 18) - v - 1;
+ v = v ^ (v >> 31);
+ v = v * 21; // v = (v + (v << 2)) + (v << 4);
+ v = v ^ (v >> 11);
+ v = v + (v << 6);
+ v = v ^ (v >> 22);
+ return (int) v;
+}
+
static inline uint32_t hash_djb2_one_float(float p_in,uint32_t p_prev=5381) {
union {
float f;
uint32_t i;
} u;
- // handle -0 case
- if (p_in==0.0f) u.f=0.0f;
- else u.f=p_in;
+ // Normalize +/- 0.0 and NaN values so they hash the same.
+ if (p_in==0.0f)
+ u.f=0.0;
+ else if (Math::is_nan(p_in))
+ u.f=Math_NAN;
+ else
+ u.f=p_in;
return ((p_prev<<5)+p_prev)+u.i;
}
+// Overload for real_t size changes
+static inline uint32_t hash_djb2_one_float(double p_in,uint32_t p_prev=5381) {
+ union {
+ double d;
+ uint64_t i;
+ } u;
+
+ // Normalize +/- 0.0 and NaN values so they hash the same.
+ if (p_in==0.0f)
+ u.d=0.0;
+ else if (Math::is_nan(p_in))
+ u.d=Math_NAN;
+ else
+ u.d=p_in;
+
+ return ((p_prev<<5)+p_prev) + hash_one_uint64(u.i);
+}
+
template<class T>
static inline uint32_t make_uint32_t(T p_in) {
diff --git a/core/helper/SCsub b/core/helper/SCsub
new file mode 100644
index 0000000000..4efc902717
--- /dev/null
+++ b/core/helper/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import('env')
+
+env.add_source_files(env.core_sources, "*.cpp")
+
+Export('env')
diff --git a/core/helper/math_fieldwise.cpp b/core/helper/math_fieldwise.cpp
new file mode 100644
index 0000000000..204c431e1d
--- /dev/null
+++ b/core/helper/math_fieldwise.cpp
@@ -0,0 +1,171 @@
+/*************************************************************************/
+/* fieldwise.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef TOOLS_ENABLED
+
+#include "core/helper/math_fieldwise.h"
+
+#define SETUP_TYPE(m_type) m_type source=p_source; m_type target=p_target;
+#define TRY_TRANSFER_FIELD(m_name,m_member) if (p_field==m_name) { target.m_member=source.m_member; }
+
+Variant fieldwise_assign(const Variant& p_target, const Variant& p_source, const String& p_field) {
+
+ ERR_FAIL_COND_V(p_target.get_type()!=p_source.get_type(),p_target);
+
+ switch (p_source.get_type()) {
+
+ case Variant::VECTOR2: {
+
+ SETUP_TYPE(Vector2)
+
+ /**/ TRY_TRANSFER_FIELD("x",x)
+ else TRY_TRANSFER_FIELD("y",y)
+
+ return target;
+ }
+
+ case Variant::RECT2: {
+
+ SETUP_TYPE(Rect2)
+
+ /**/ TRY_TRANSFER_FIELD("x",pos.x)
+ else TRY_TRANSFER_FIELD("y",pos.y)
+ else TRY_TRANSFER_FIELD("w",size.x)
+ else TRY_TRANSFER_FIELD("h",size.y)
+
+ return target;
+ }
+
+ case Variant::VECTOR3: {
+
+ SETUP_TYPE(Vector3)
+
+ /**/ TRY_TRANSFER_FIELD("x",x)
+ else TRY_TRANSFER_FIELD("y",y)
+ else TRY_TRANSFER_FIELD("z",z)
+
+ return target;
+ }
+
+ case Variant::PLANE: {
+
+ SETUP_TYPE(Plane)
+
+ /**/ TRY_TRANSFER_FIELD("x",normal.x)
+ else TRY_TRANSFER_FIELD("y",normal.y)
+ else TRY_TRANSFER_FIELD("z",normal.z)
+ else TRY_TRANSFER_FIELD("d",d)
+
+ return target;
+ }
+
+ case Variant::QUAT: {
+
+ SETUP_TYPE(Quat)
+
+ /**/ TRY_TRANSFER_FIELD("x",x)
+ else TRY_TRANSFER_FIELD("y",y)
+ else TRY_TRANSFER_FIELD("z",z)
+ else TRY_TRANSFER_FIELD("w",w)
+
+ return target;
+ }
+
+ case Variant::RECT3: {
+
+ SETUP_TYPE(Rect3)
+
+ /**/ TRY_TRANSFER_FIELD("px",pos.x)
+ else TRY_TRANSFER_FIELD("py",pos.y)
+ else TRY_TRANSFER_FIELD("pz",pos.z)
+ else TRY_TRANSFER_FIELD("sx",size.x)
+ else TRY_TRANSFER_FIELD("sy",size.y)
+ else TRY_TRANSFER_FIELD("sz",size.z)
+
+ return target;
+ }
+
+ case Variant::TRANSFORM2D: {
+
+ SETUP_TYPE(Transform2D)
+
+ /**/ TRY_TRANSFER_FIELD("xx",elements[0][0])
+ else TRY_TRANSFER_FIELD("xy",elements[0][1])
+ else TRY_TRANSFER_FIELD("yx",elements[1][0])
+ else TRY_TRANSFER_FIELD("yy",elements[1][1])
+ else TRY_TRANSFER_FIELD("ox",elements[2][0])
+ else TRY_TRANSFER_FIELD("oy",elements[2][1])
+
+ return target;
+ }
+
+ case Variant::BASIS: {
+
+ SETUP_TYPE(Basis)
+
+ /**/ TRY_TRANSFER_FIELD("xx",elements[0][0])
+ else TRY_TRANSFER_FIELD("xy",elements[0][1])
+ else TRY_TRANSFER_FIELD("xz",elements[0][2])
+ else TRY_TRANSFER_FIELD("yx",elements[1][0])
+ else TRY_TRANSFER_FIELD("yy",elements[1][1])
+ else TRY_TRANSFER_FIELD("yz",elements[1][2])
+ else TRY_TRANSFER_FIELD("zx",elements[2][0])
+ else TRY_TRANSFER_FIELD("zy",elements[2][1])
+ else TRY_TRANSFER_FIELD("zz",elements[2][2])
+
+ return target;
+ }
+
+ case Variant::TRANSFORM: {
+
+ SETUP_TYPE(Transform)
+
+ /**/ TRY_TRANSFER_FIELD("xx",basis.elements[0][0])
+ else TRY_TRANSFER_FIELD("xy",basis.elements[0][1])
+ else TRY_TRANSFER_FIELD("xz",basis.elements[0][2])
+ else TRY_TRANSFER_FIELD("yx",basis.elements[1][0])
+ else TRY_TRANSFER_FIELD("yy",basis.elements[1][1])
+ else TRY_TRANSFER_FIELD("yz",basis.elements[1][2])
+ else TRY_TRANSFER_FIELD("zx",basis.elements[2][0])
+ else TRY_TRANSFER_FIELD("zy",basis.elements[2][1])
+ else TRY_TRANSFER_FIELD("zz",basis.elements[2][2])
+ else TRY_TRANSFER_FIELD("xo",origin.x)
+ else TRY_TRANSFER_FIELD("yo",origin.y)
+ else TRY_TRANSFER_FIELD("zo",origin.z)
+
+ return target;
+ }
+
+ default: {
+ ERR_FAIL_V(p_target);
+ }
+ }
+}
+
+#endif // TOOLS_ENABLED
diff --git a/core/helper/math_fieldwise.h b/core/helper/math_fieldwise.h
new file mode 100644
index 0000000000..31f9af8d0b
--- /dev/null
+++ b/core/helper/math_fieldwise.h
@@ -0,0 +1,40 @@
+/*************************************************************************/
+/* fieldwise.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 MATH_FIELDWISE_H
+#define MATH_FIELDWISE_H
+
+#ifdef TOOLS_ENABLED
+
+#include "core/variant.h"
+
+Variant fieldwise_assign(const Variant& p_target, const Variant& p_source, const String& p_field);
+
+#endif // TOOLS_ENABLED
+
+#endif // MATH_FIELDWISE_H
diff --git a/core/input_map.cpp b/core/input_map.cpp
index dcce13ba1b..444c55cac6 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -28,26 +28,26 @@
/*************************************************************************/
#include "input_map.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/keyboard.h"
InputMap *InputMap::singleton=NULL;
void InputMap::_bind_methods() {
- ClassDB::bind_method(_MD("has_action","action"),&InputMap::has_action);
- ClassDB::bind_method(_MD("get_action_id","action"),&InputMap::get_action_id);
- ClassDB::bind_method(_MD("get_action_from_id","id"),&InputMap::get_action_from_id);
- ClassDB::bind_method(_MD("get_actions"),&InputMap::_get_actions);
- ClassDB::bind_method(_MD("add_action","action"),&InputMap::add_action);
- ClassDB::bind_method(_MD("erase_action","action"),&InputMap::erase_action);
-
- ClassDB::bind_method(_MD("action_add_event","action","event"),&InputMap::action_add_event);
- ClassDB::bind_method(_MD("action_has_event","action","event"),&InputMap::action_has_event);
- ClassDB::bind_method(_MD("action_erase_event","action","event"),&InputMap::action_erase_event);
- ClassDB::bind_method(_MD("get_action_list","action"),&InputMap::_get_action_list);
- ClassDB::bind_method(_MD("event_is_action","event","action"),&InputMap::event_is_action);
- ClassDB::bind_method(_MD("load_from_globals"),&InputMap::load_from_globals);
+ ClassDB::bind_method(D_METHOD("has_action","action"),&InputMap::has_action);
+ ClassDB::bind_method(D_METHOD("get_action_id","action"),&InputMap::get_action_id);
+ ClassDB::bind_method(D_METHOD("get_action_from_id","id"),&InputMap::get_action_from_id);
+ ClassDB::bind_method(D_METHOD("get_actions"),&InputMap::_get_actions);
+ ClassDB::bind_method(D_METHOD("add_action","action"),&InputMap::add_action);
+ ClassDB::bind_method(D_METHOD("erase_action","action"),&InputMap::erase_action);
+
+ ClassDB::bind_method(D_METHOD("action_add_event","action","event"),&InputMap::action_add_event);
+ ClassDB::bind_method(D_METHOD("action_has_event","action","event"),&InputMap::action_has_event);
+ ClassDB::bind_method(D_METHOD("action_erase_event","action","event"),&InputMap::action_erase_event);
+ ClassDB::bind_method(D_METHOD("get_action_list","action"),&InputMap::_get_action_list);
+ ClassDB::bind_method(D_METHOD("event_is_action","event","action"),&InputMap::event_is_action);
+ ClassDB::bind_method(D_METHOD("load_from_globals"),&InputMap::load_from_globals);
}
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index b944906e78..fdfcc3ae3a 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -209,19 +209,19 @@ Error ConfigFile::load(const String& p_path) {
void ConfigFile::_bind_methods(){
- ClassDB::bind_method(_MD("set_value","section","key","value"),&ConfigFile::set_value);
- ClassDB::bind_method(_MD("get_value:Variant","section","key","default"),&ConfigFile::get_value,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("set_value","section","key","value"),&ConfigFile::set_value);
+ ClassDB::bind_method(D_METHOD("get_value:Variant","section","key","default"),&ConfigFile::get_value,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("has_section","section"),&ConfigFile::has_section);
- ClassDB::bind_method(_MD("has_section_key","section","key"),&ConfigFile::has_section_key);
+ ClassDB::bind_method(D_METHOD("has_section","section"),&ConfigFile::has_section);
+ ClassDB::bind_method(D_METHOD("has_section_key","section","key"),&ConfigFile::has_section_key);
- ClassDB::bind_method(_MD("get_sections"),&ConfigFile::_get_sections);
- ClassDB::bind_method(_MD("get_section_keys","section"),&ConfigFile::_get_section_keys);
+ ClassDB::bind_method(D_METHOD("get_sections"),&ConfigFile::_get_sections);
+ ClassDB::bind_method(D_METHOD("get_section_keys","section"),&ConfigFile::_get_section_keys);
- ClassDB::bind_method(_MD("erase_section","section"),&ConfigFile::erase_section);
+ ClassDB::bind_method(D_METHOD("erase_section","section"),&ConfigFile::erase_section);
- ClassDB::bind_method(_MD("load:Error","path"),&ConfigFile::load);
- ClassDB::bind_method(_MD("save:Error","path"),&ConfigFile::save);
+ ClassDB::bind_method(D_METHOD("load:Error","path"),&ConfigFile::load);
+ ClassDB::bind_method(D_METHOD("save:Error","path"),&ConfigFile::save);
}
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 32eb003228..b4ba14ddc9 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -30,7 +30,7 @@
#include "os/dir_access.h"
#include "os/copymem.h"
-#include "globals.h"
+#include "global_config.h"
#include "map.h"
static Map<String, Vector<uint8_t> >* files = NULL;
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 7bf750f6e1..d9fdc9cedc 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "file_access_network.h"
#include "marshalls.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
#include "io/ip.h"
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index d63539a7a5..fa1bebde16 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -31,7 +31,7 @@
#include <stdio.h>
-#define PACK_VERSION 0
+#define PACK_VERSION 1
Error PackedData::add_pack(const String& p_path) {
@@ -167,8 +167,8 @@ bool PackedSourcePCK::try_open_pack(const String& p_path) {
uint32_t ver_minor = f->get_32();
uint32_t ver_rev = f->get_32();
- ERR_EXPLAIN("Pack version newer than supported by engine: "+itos(version));
- ERR_FAIL_COND_V( version > PACK_VERSION, ERR_INVALID_DATA);
+ ERR_EXPLAIN("Pack version unsupported: "+itos(version));
+ ERR_FAIL_COND_V( version != PACK_VERSION, ERR_INVALID_DATA);
ERR_EXPLAIN("Pack created with a newer version of the engine: "+itos(ver_major)+"."+itos(ver_minor)+"."+itos(ver_rev));
ERR_FAIL_COND_V( ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), ERR_INVALID_DATA);
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 63c8abbbad..ae14f8fa38 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -29,14 +29,9 @@
#include "http_client.h"
#include "io/stream_peer_ssl.h"
-void HTTPClient::set_ip_type(IP::Type p_type) {
- ip_type = p_type;
-}
-
Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,bool p_verify_host){
close();
- tcp_connection->set_ip_type(ip_type);
conn_port=p_port;
conn_host=p_host;
@@ -66,7 +61,7 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl,b
status=STATUS_CONNECTING;
} else {
//is hostname
- resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, ip_type);
+ resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host);
status=STATUS_RESOLVING;
}
@@ -345,7 +340,7 @@ Error HTTPClient::poll(){
int rs = response_str.size();
if (
(rs>=2 && response_str[rs-2]=='\n' && response_str[rs-1]=='\n') ||
- (rs>=4 && response_str[rs-4]=='\r' && response_str[rs-3]=='\n' && rs>=4 && response_str[rs-2]=='\r' && response_str[rs-1]=='\n')
+ (rs>=4 && response_str[rs-4]=='\r' && response_str[rs-3]=='\n' && response_str[rs-2]=='\r' && response_str[rs-1]=='\n')
) {
@@ -566,11 +561,13 @@ PoolByteArray HTTPClient::read_response_body_chunk() {
int to_read = MIN(body_left,read_chunk_size);
PoolByteArray ret;
ret.resize(to_read);
- PoolByteArray::Write w = ret.write();
int _offset = 0;
while (to_read > 0) {
int rec=0;
- err = _get_http_data(w.ptr()+_offset,to_read,rec);
+ {
+ PoolByteArray::Write w = ret.write();
+ err = _get_http_data(w.ptr()+_offset,to_read,rec);
+ }
if (rec>0) {
body_left-=rec;
to_read-=rec;
@@ -639,32 +636,31 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received)
void HTTPClient::_bind_methods() {
- ClassDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPClient::set_ip_type);
- ClassDB::bind_method(_MD("connect_to_host:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect_to_host,DEFVAL(false),DEFVAL(true));
- ClassDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection);
- ClassDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection);
- ClassDB::bind_method(_MD("request_raw","method","url","headers","body"),&HTTPClient::request_raw);
- ClassDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String()));
- ClassDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text);
- ClassDB::bind_method(_MD("send_body_data","body"),&HTTPClient::send_body_data);
- ClassDB::bind_method(_MD("close"),&HTTPClient::close);
+ ClassDB::bind_method(D_METHOD("connect_to_host:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect_to_host,DEFVAL(false),DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection);
+ ClassDB::bind_method(D_METHOD("get_connection:StreamPeer"),&HTTPClient::get_connection);
+ ClassDB::bind_method(D_METHOD("request_raw","method","url","headers","body"),&HTTPClient::request_raw);
+ ClassDB::bind_method(D_METHOD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("send_body_text","body"),&HTTPClient::send_body_text);
+ ClassDB::bind_method(D_METHOD("send_body_data","body"),&HTTPClient::send_body_data);
+ ClassDB::bind_method(D_METHOD("close"),&HTTPClient::close);
- ClassDB::bind_method(_MD("has_response"),&HTTPClient::has_response);
- ClassDB::bind_method(_MD("is_response_chunked"),&HTTPClient::is_response_chunked);
- ClassDB::bind_method(_MD("get_response_code"),&HTTPClient::get_response_code);
- ClassDB::bind_method(_MD("get_response_headers"),&HTTPClient::_get_response_headers);
- ClassDB::bind_method(_MD("get_response_headers_as_dictionary"),&HTTPClient::_get_response_headers_as_dictionary);
- ClassDB::bind_method(_MD("get_response_body_length"),&HTTPClient::get_response_body_length);
- ClassDB::bind_method(_MD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk);
- ClassDB::bind_method(_MD("set_read_chunk_size","bytes"),&HTTPClient::set_read_chunk_size);
+ ClassDB::bind_method(D_METHOD("has_response"),&HTTPClient::has_response);
+ ClassDB::bind_method(D_METHOD("is_response_chunked"),&HTTPClient::is_response_chunked);
+ ClassDB::bind_method(D_METHOD("get_response_code"),&HTTPClient::get_response_code);
+ ClassDB::bind_method(D_METHOD("get_response_headers"),&HTTPClient::_get_response_headers);
+ ClassDB::bind_method(D_METHOD("get_response_headers_as_dictionary"),&HTTPClient::_get_response_headers_as_dictionary);
+ ClassDB::bind_method(D_METHOD("get_response_body_length"),&HTTPClient::get_response_body_length);
+ ClassDB::bind_method(D_METHOD("read_response_body_chunk"),&HTTPClient::read_response_body_chunk);
+ ClassDB::bind_method(D_METHOD("set_read_chunk_size","bytes"),&HTTPClient::set_read_chunk_size);
- ClassDB::bind_method(_MD("set_blocking_mode","enabled"),&HTTPClient::set_blocking_mode);
- ClassDB::bind_method(_MD("is_blocking_mode_enabled"),&HTTPClient::is_blocking_mode_enabled);
+ ClassDB::bind_method(D_METHOD("set_blocking_mode","enabled"),&HTTPClient::set_blocking_mode);
+ ClassDB::bind_method(D_METHOD("is_blocking_mode_enabled"),&HTTPClient::is_blocking_mode_enabled);
- ClassDB::bind_method(_MD("get_status"),&HTTPClient::get_status);
- ClassDB::bind_method(_MD("poll:Error"),&HTTPClient::poll);
+ ClassDB::bind_method(D_METHOD("get_status"),&HTTPClient::get_status);
+ ClassDB::bind_method(D_METHOD("poll:Error"),&HTTPClient::poll);
- ClassDB::bind_method(_MD("query_string_from_dict:String","fields"),&HTTPClient::query_string_from_dict);
+ ClassDB::bind_method(D_METHOD("query_string_from_dict:String","fields"),&HTTPClient::query_string_from_dict);
BIND_CONSTANT( METHOD_GET );
@@ -766,7 +762,6 @@ String HTTPClient::query_string_from_dict(const Dictionary& p_dict) {
HTTPClient::HTTPClient(){
- ip_type = IP::TYPE_ANY;
tcp_connection = StreamPeerTCP::create_ref();
resolving = IP::RESOLVER_INVALID_ID;
status=STATUS_DISCONNECTED;
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 496d22530b..4b0c1b730f 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -132,7 +132,6 @@ public:
private:
- IP::Type ip_type;
Status status;
IP::ResolverID resolving;
int conn_port;
@@ -165,7 +164,6 @@ private:
public:
- void set_ip_type(IP::Type p_type);
//Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request
Error connect_to_host(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true);
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 0eb1f221c9..d820273a14 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -82,7 +82,7 @@ struct _IP_ResolverPrivate {
continue;
queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type);
- if (queue[i].response==IP_Address())
+ if (!queue[i].response.is_valid())
queue[i].status=IP::RESOLVER_STATUS_ERROR;
else
queue[i].status=IP::RESOLVER_STATUS_DONE;
@@ -218,13 +218,13 @@ Array IP::_get_local_addresses() const {
void IP::_bind_methods() {
- ClassDB::bind_method(_MD("resolve_hostname","host","ip_type"),&IP::resolve_hostname,DEFVAL(IP::TYPE_ANY));
- ClassDB::bind_method(_MD("resolve_hostname_queue_item","host","ip_type"),&IP::resolve_hostname_queue_item,DEFVAL(IP::TYPE_ANY));
- ClassDB::bind_method(_MD("get_resolve_item_status","id"),&IP::get_resolve_item_status);
- ClassDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address);
- ClassDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item);
- ClassDB::bind_method(_MD("get_local_addresses"),&IP::_get_local_addresses);
- ClassDB::bind_method(_MD("clear_cache"),&IP::clear_cache, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("resolve_hostname","host","ip_type"),&IP::resolve_hostname,DEFVAL(IP::TYPE_ANY));
+ ClassDB::bind_method(D_METHOD("resolve_hostname_queue_item","host","ip_type"),&IP::resolve_hostname_queue_item,DEFVAL(IP::TYPE_ANY));
+ ClassDB::bind_method(D_METHOD("get_resolve_item_status","id"),&IP::get_resolve_item_status);
+ ClassDB::bind_method(D_METHOD("get_resolve_item_address","id"),&IP::get_resolve_item_address);
+ ClassDB::bind_method(D_METHOD("erase_resolve_item","id"),&IP::erase_resolve_item);
+ ClassDB::bind_method(D_METHOD("get_local_addresses"),&IP::_get_local_addresses);
+ ClassDB::bind_method(D_METHOD("clear_cache"),&IP::clear_cache, DEFVAL(""));
BIND_CONSTANT( RESOLVER_STATUS_NONE );
BIND_CONSTANT( RESOLVER_STATUS_WAITING );
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 1fda7fed7b..69c7df619d 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -38,6 +38,9 @@ IP_Address::operator Variant() const {
IP_Address::operator String() const {
+ if(!valid)
+ return "";
+
if(is_ipv4())
// IPv4 address mapped to IPv6
return itos(field8[12])+"."+itos(field8[13])+"."+itos(field8[14])+"."+itos(field8[15]);
@@ -171,6 +174,8 @@ void IP_Address::_parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret
void IP_Address::clear() {
memset(&field8[0], 0, sizeof(field8));
+ valid = false;
+ wildcard = false;
};
bool IP_Address::is_ipv4() const{
@@ -184,6 +189,7 @@ const uint8_t *IP_Address::get_ipv4() const{
void IP_Address::set_ipv4(const uint8_t *p_ip) {
clear();
+ valid = true;
field16[5]=0xffff;
field32[3]=*((const uint32_t *)p_ip);
}
@@ -194,6 +200,7 @@ const uint8_t *IP_Address::get_ipv6() const{
void IP_Address::set_ipv6(const uint8_t *p_buf) {
clear();
+ valid = true;
for (int i=0; i<16; i++)
field8[i] = p_buf[i];
}
@@ -201,14 +208,25 @@ void IP_Address::set_ipv6(const uint8_t *p_buf) {
IP_Address::IP_Address(const String& p_string) {
clear();
- if (p_string.find(":") >= 0) {
+ if (p_string == "*") {
+ // Wildcard (not a vaild IP)
+ wildcard = true;
+
+ } else if (p_string.find(":") >= 0) {
+ // IPv6
_parse_ipv6(p_string);
- } else {
- // Mapped to IPv6
+ valid = true;
+
+ } else if (p_string.get_slice_count(".") == 4) {
+ // IPv4 (mapped to IPv6 internally)
field16[5] = 0xffff;
_parse_ipv4(p_string, 0, &field8[12]);
- };
+ valid = true;
+
+ } else {
+ ERR_PRINT("Invalid IP address");
+ }
}
_FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) {
@@ -222,6 +240,7 @@ _FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) {
IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6) {
clear();
+ valid = true;
if (!is_v6) {
// Mapped to IPv6
field16[5]=0xffff;
diff --git a/core/io/ip_address.h b/core/io/ip_address.h
index 87f32b0ac2..257836601a 100644
--- a/core/io/ip_address.h
+++ b/core/io/ip_address.h
@@ -41,6 +41,9 @@ private:
uint32_t field32[4];
};
+ bool valid;
+ bool wildcard;
+
protected:
void _parse_ipv6(const String& p_string);
void _parse_ipv4(const String& p_string, int p_start, uint8_t* p_ret);
@@ -48,12 +51,16 @@ protected:
public:
//operator Variant() const;
bool operator==(const IP_Address& p_ip) const {
+ if (p_ip.valid != valid) return false;
+ if (!valid) return false;
for (int i=0; i<4; i++)
if (field32[i] != p_ip.field32[i])
return false;
return true;
}
bool operator!=(const IP_Address& p_ip) const {
+ if (p_ip.valid != valid) return true;
+ if (!valid) return true;
for (int i=0; i<4; i++)
if (field32[i] != p_ip.field32[i])
return true;
@@ -61,6 +68,8 @@ public:
}
void clear();
+ bool is_wildcard() const {return wildcard;}
+ bool is_valid() const {return valid;}
bool is_ipv4() const;
const uint8_t *get_ipv4() const;
void set_ipv4(const uint8_t *p_ip);
diff --git a/core/io/json.cpp b/core/io/json.cpp
index ac5b8f1e5f..5ade25aab4 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -374,7 +374,7 @@ Error JSON::_parse_array(Array &array,const CharType *p_str,int &index, int p_le
}
- return OK;
+ return ERR_PARSE_ERROR;
}
@@ -446,7 +446,7 @@ Error JSON::_parse_object(Dictionary &object,const CharType *p_str,int &index, i
}
}
- return OK;
+ return ERR_PARSE_ERROR;
}
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index e958edc93e..a8c1cd0a10 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -641,7 +641,6 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *
ERR_FAIL_COND_V(len<4,ERR_INVALID_DATA);
uint32_t count = decode_uint32(buf);
- ERR_FAIL_COND_V(count<0,ERR_INVALID_DATA);
PoolVector<String> strings;
buf+=4;
@@ -691,7 +690,6 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *
ERR_FAIL_COND_V(len<4,ERR_INVALID_DATA);
uint32_t count = decode_uint32(buf);
- ERR_FAIL_COND_V(count<0,ERR_INVALID_DATA);
buf+=4;
len-=4;
@@ -729,7 +727,6 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *
ERR_FAIL_COND_V(len<4,ERR_INVALID_DATA);
uint32_t count = decode_uint32(buf);
- ERR_FAIL_COND_V(count<0,ERR_INVALID_DATA);
buf+=4;
len-=4;
@@ -768,7 +765,6 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int *
ERR_FAIL_COND_V(len<4,ERR_INVALID_DATA);
uint32_t count = decode_uint32(buf);
- ERR_FAIL_COND_V(count<0,ERR_INVALID_DATA);
buf+=4;
len-=4;
diff --git a/core/io/networked_multiplayer_peer.cpp b/core/io/networked_multiplayer_peer.cpp
index 2981307af6..fb81a806e2 100644
--- a/core/io/networked_multiplayer_peer.cpp
+++ b/core/io/networked_multiplayer_peer.cpp
@@ -31,18 +31,18 @@
void NetworkedMultiplayerPeer::_bind_methods() {
- ClassDB::bind_method(_MD("set_transfer_mode","mode"), &NetworkedMultiplayerPeer::set_transfer_mode );
- ClassDB::bind_method(_MD("set_target_peer","id"), &NetworkedMultiplayerPeer::set_target_peer );
+ ClassDB::bind_method(D_METHOD("set_transfer_mode","mode"), &NetworkedMultiplayerPeer::set_transfer_mode );
+ ClassDB::bind_method(D_METHOD("set_target_peer","id"), &NetworkedMultiplayerPeer::set_target_peer );
- ClassDB::bind_method(_MD("get_packet_peer"), &NetworkedMultiplayerPeer::get_packet_peer );
+ ClassDB::bind_method(D_METHOD("get_packet_peer"), &NetworkedMultiplayerPeer::get_packet_peer );
- ClassDB::bind_method(_MD("poll"), &NetworkedMultiplayerPeer::poll );
+ ClassDB::bind_method(D_METHOD("poll"), &NetworkedMultiplayerPeer::poll );
- ClassDB::bind_method(_MD("get_connection_status"), &NetworkedMultiplayerPeer::get_connection_status );
- ClassDB::bind_method(_MD("get_unique_id"), &NetworkedMultiplayerPeer::get_unique_id );
+ ClassDB::bind_method(D_METHOD("get_connection_status"), &NetworkedMultiplayerPeer::get_connection_status );
+ ClassDB::bind_method(D_METHOD("get_unique_id"), &NetworkedMultiplayerPeer::get_unique_id );
- ClassDB::bind_method(_MD("set_refuse_new_connections","enable"), &NetworkedMultiplayerPeer::set_refuse_new_connections );
- ClassDB::bind_method(_MD("is_refusing_new_connections"), &NetworkedMultiplayerPeer::is_refusing_new_connections );
+ ClassDB::bind_method(D_METHOD("set_refuse_new_connections","enable"), &NetworkedMultiplayerPeer::set_refuse_new_connections );
+ ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &NetworkedMultiplayerPeer::is_refusing_new_connections );
BIND_CONSTANT( TRANSFER_MODE_UNRELIABLE );
BIND_CONSTANT( TRANSFER_MODE_UNRELIABLE_ORDERED );
diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp
index 5ff09f9fb0..cf5883121f 100644
--- a/core/io/packet_peer.cpp
+++ b/core/io/packet_peer.cpp
@@ -29,7 +29,7 @@
#include "packet_peer.h"
#include "io/marshalls.h"
-#include "globals.h"
+#include "global_config.h"
/* helpers / binders */
@@ -126,12 +126,12 @@ Error PacketPeer::_get_packet_error() const {
void PacketPeer::_bind_methods() {
- ClassDB::bind_method(_MD("get_var:Variant"),&PacketPeer::_bnd_get_var);
- ClassDB::bind_method(_MD("put_var", "var:Variant"),&PacketPeer::put_var);
- ClassDB::bind_method(_MD("get_packet"),&PacketPeer::_get_packet);
- ClassDB::bind_method(_MD("put_packet:Error", "buffer"),&PacketPeer::_put_packet);
- ClassDB::bind_method(_MD("get_packet_error:Error"),&PacketPeer::_get_packet_error);
- ClassDB::bind_method(_MD("get_available_packet_count"),&PacketPeer::get_available_packet_count);
+ ClassDB::bind_method(D_METHOD("get_var:Variant"),&PacketPeer::_bnd_get_var);
+ ClassDB::bind_method(D_METHOD("put_var", "var:Variant"),&PacketPeer::put_var);
+ ClassDB::bind_method(D_METHOD("get_packet"),&PacketPeer::_get_packet);
+ ClassDB::bind_method(D_METHOD("put_packet:Error", "buffer"),&PacketPeer::_put_packet);
+ ClassDB::bind_method(D_METHOD("get_packet_error:Error"),&PacketPeer::_get_packet_error);
+ ClassDB::bind_method(D_METHOD("get_available_packet_count"),&PacketPeer::get_available_packet_count);
};
/***************/
@@ -145,7 +145,7 @@ void PacketPeerStream::_set_stream_peer(REF p_peer) {
void PacketPeerStream::_bind_methods() {
- ClassDB::bind_method(_MD("set_stream_peer","peer:StreamPeer"),&PacketPeerStream::_set_stream_peer);
+ ClassDB::bind_method(D_METHOD("set_stream_peer","peer:StreamPeer"),&PacketPeerStream::_set_stream_peer);
}
Error PacketPeerStream::_poll_buffer() const {
diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp
index 9fec807bfb..c4a6fd79a8 100644
--- a/core/io/packet_peer_udp.cpp
+++ b/core/io/packet_peer_udp.cpp
@@ -42,8 +42,8 @@ Error PacketPeerUDP::_set_dest_address(const String& p_address, int p_port) {
if (p_address.is_valid_ip_address()) {
ip=p_address;
} else {
- ip=IP::get_singleton()->resolve_hostname(p_address, ip_type);
- if (ip==IP_Address())
+ ip=IP::get_singleton()->resolve_hostname(p_address);
+ if (!ip.is_valid())
return ERR_CANT_RESOLVE;
}
@@ -51,22 +51,16 @@ Error PacketPeerUDP::_set_dest_address(const String& p_address, int p_port) {
return OK;
}
-void PacketPeerUDP::set_ip_type(IP::Type p_type) {
- close();
- ip_type = p_type;
-}
-
void PacketPeerUDP::_bind_methods() {
- ClassDB::bind_method(_MD("set_ip_type","ip_type"),&PacketPeerUDP::set_ip_type);
- ClassDB::bind_method(_MD("listen:Error","port", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536));
- ClassDB::bind_method(_MD("close"),&PacketPeerUDP::close);
- ClassDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait);
- ClassDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening);
- ClassDB::bind_method(_MD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip);
- //ClassDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address);
- ClassDB::bind_method(_MD("get_packet_port"),&PacketPeerUDP::get_packet_port);
- ClassDB::bind_method(_MD("set_dest_address","host","port"),&PacketPeerUDP::_set_dest_address);
+ ClassDB::bind_method(D_METHOD("listen:Error","port", "bind_address", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL("*"),DEFVAL(65536));
+ ClassDB::bind_method(D_METHOD("close"),&PacketPeerUDP::close);
+ ClassDB::bind_method(D_METHOD("wait:Error"),&PacketPeerUDP::wait);
+ ClassDB::bind_method(D_METHOD("is_listening"),&PacketPeerUDP::is_listening);
+ ClassDB::bind_method(D_METHOD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip);
+ //ClassDB::bind_method(D_METHOD("get_packet_address"),&PacketPeerUDP::_get_packet_address);
+ ClassDB::bind_method(D_METHOD("get_packet_port"),&PacketPeerUDP::get_packet_port);
+ ClassDB::bind_method(D_METHOD("set_dest_address","host","port"),&PacketPeerUDP::_set_dest_address);
}
@@ -87,5 +81,5 @@ PacketPeerUDP* PacketPeerUDP::create() {
PacketPeerUDP::PacketPeerUDP()
{
- ip_type = IP::TYPE_ANY;
+
}
diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h
index 17952b4ac1..726406887c 100644
--- a/core/io/packet_peer_udp.h
+++ b/core/io/packet_peer_udp.h
@@ -38,19 +38,16 @@ class PacketPeerUDP : public PacketPeer {
protected:
- IP::Type ip_type;
-
static PacketPeerUDP* (*_create)();
static void _bind_methods();
String _get_packet_ip() const;
- virtual Error _set_dest_address(const String& p_address,int p_port);
+ Error _set_dest_address(const String& p_address,int p_port);
public:
- virtual void set_ip_type(IP::Type p_type);
- virtual Error listen(int p_port, int p_recv_buffer_size=65536)=0;
+ virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), int p_recv_buffer_size=65536)=0;
virtual void close()=0;
virtual Error wait()=0;
virtual bool is_listening() const=0;
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index fb5875e4cc..2cd46843e8 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -52,9 +52,9 @@ static void _pad(FileAccess* p_file, int p_bytes) {
void PCKPacker::_bind_methods() {
- ClassDB::bind_method(_MD("pck_start","pck_name","alignment"),&PCKPacker::pck_start);
- ClassDB::bind_method(_MD("add_file","pck_path","source_path"),&PCKPacker::add_file);
- ClassDB::bind_method(_MD("flush","verbose"),&PCKPacker::flush);
+ ClassDB::bind_method(D_METHOD("pck_start","pck_name","alignment"),&PCKPacker::pck_start);
+ ClassDB::bind_method(D_METHOD("add_file","pck_path","source_path"),&PCKPacker::add_file);
+ ClassDB::bind_method(D_METHOD("flush","verbose"),&PCKPacker::flush);
};
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index c75e476764..2d733842fa 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "version.h"
#include "resource_format_binary.h"
-#include "globals.h"
+#include "global_config.h"
#include "io/file_access_compressed.h"
#include "io/marshalls.h"
#include "os/dir_access.h"
@@ -98,6 +98,27 @@ void ResourceInteractiveLoaderBinary::_advance_padding(uint32_t p_len) {
}
+
+StringName ResourceInteractiveLoaderBinary::_get_string() {
+
+ uint32_t id = f->get_32();
+ if (id&0x80000000) {
+ uint32_t len = id&0x7FFFFFFF;
+ if (len>str_buf.size()) {
+ str_buf.resize(len);
+ }
+ if (len==0)
+ return StringName();
+ f->get_buffer((uint8_t*)&str_buf[0],len);
+ String s;
+ s.parse_utf8(&str_buf[0]);
+ return s;
+ }
+
+ return string_map[id];
+
+}
+
Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
@@ -272,8 +293,8 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
Image::Format fmt=Image::Format(format&format_version_mask); //if format changes, we can add a compatibility bit on top
-
uint32_t datalen = f->get_32();
+ print_line("image format: "+String(Image::get_format_name(fmt))+" datalen "+itos(datalen));
PoolVector<uint8_t> imgdata;
imgdata.resize(datalen);
@@ -282,6 +303,14 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
_advance_padding(datalen);
w=PoolVector<uint8_t>::Write();
+#ifdef TOOLS_ENABLED
+//compatibility
+ int correct_size = Image::get_image_data_size(width,height,fmt,mipmaps?-1:0);
+ if (correct_size < datalen) {
+ WARN_PRINT("Image data was too large, shrinking for compatibility")
+ imgdata.resize(correct_size);
+ }
+#endif
r_v=Image(width,height,mipmaps,fmt,imgdata);
} else {
@@ -323,10 +352,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant& r_v) {
for(int i=0;i<name_count;i++)
- names.push_back(string_map[f->get_32()]);
+ names.push_back(_get_string());
for(uint32_t i=0;i<subname_count;i++)
- subnames.push_back(string_map[f->get_32()]);
- property=string_map[f->get_32()];
+ subnames.push_back(_get_string());
+ property=_get_string();
NodePath np = NodePath(names,subnames,absolute,property);
//print_line("got path: "+String(np));
@@ -641,6 +670,8 @@ Error ResourceInteractiveLoaderBinary::poll(){
if (s<external_resources.size()) {
String path = external_resources[s].path;
+
+ print_line("load external res: "+path);
if (remaps.has(path)) {
path=remaps[path];
}
@@ -711,6 +742,8 @@ Error ResourceInteractiveLoaderBinary::poll(){
String t = get_unicode_string();
+// print_line("loading resource of type "+t+" path is "+path);
+
Object *obj = ClassDB::instance(t);
if (!obj) {
error=ERR_FILE_CORRUPT;
@@ -737,8 +770,8 @@ Error ResourceInteractiveLoaderBinary::poll(){
for(int i=0;i<pc;i++) {
- uint32_t name_idx = f->get_32();
- if (name_idx>=(uint32_t)string_map.size()) {
+ StringName name = _get_string();
+ if (name==StringName()) {
error=ERR_FILE_CORRUPT;
ERR_FAIL_V(ERR_FILE_CORRUPT);
}
@@ -749,7 +782,7 @@ Error ResourceInteractiveLoaderBinary::poll(){
if (error)
return error;
- res->set(string_map[name_idx],value);
+ res->set(name,value);
}
#ifdef TOOLS_ENABLED
res->set_edited(false);
@@ -2143,6 +2176,8 @@ void ResourceFormatSaverBinary::get_recognized_extensions(const RES& p_resource,
String base = p_resource->get_base_extension().to_lower();
p_extensions->push_back(base);
+ if (base!="res")
+ p_extensions->push_back("res");
}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 1dac51cc5c..1fab6144d5 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -54,6 +54,8 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
//Map<int,StringName> string_map;
Vector<StringName> string_map;
+ StringName _get_string();
+
struct ExtResoucre {
String path;
String type;
diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp
index 556dff3125..41245db173 100644
--- a/core/io/resource_import.cpp
+++ b/core/io/resource_import.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* resource_import.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_import.h"
+
#include "variant_parser.h"
#include "os/os.h"
@@ -81,8 +110,10 @@ RES ResourceFormatImporter::load(const String &p_path,const String& p_original_p
RES res = ResourceLoader::load(pat.path,pat.type,false,r_error);
#ifdef TOOLS_ENABLED
- res->set_import_last_modified_time( res->get_last_modified_time() ); //pass this, if used
- res->set_import_path(pat.path);
+ if (res.is_valid()) {
+ res->set_import_last_modified_time( res->get_last_modified_time() ); //pass this, if used
+ res->set_import_path(pat.path);
+ }
#endif
return res;
diff --git a/core/io/resource_import.h b/core/io/resource_import.h
index 387b3902fe..dd7a82fe75 100644
--- a/core/io/resource_import.h
+++ b/core/io/resource_import.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* resource_import.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCE_IMPORT_H
#define RESOURCE_IMPORT_H
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index fbf6a2cea2..c14389eefa 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "resource_loader.h"
#include "print_string.h"
-#include "globals.h"
+#include "global_config.h"
#include "path_remap.h"
#include "os/file_access.h"
#include "os/os.h"
@@ -61,6 +61,7 @@ bool ResourceFormatLoader::recognize_path(const String& p_path,const String& p_f
for (List<String>::Element *E=extensions.front();E;E=E->next()) {
+
if (E->get().nocasecmp_to(extension)==0)
return true;
}
@@ -86,11 +87,11 @@ void ResourceLoader::get_recognized_extensions_for_type(const String& p_type,Lis
void ResourceInteractiveLoader::_bind_methods() {
- ClassDB::bind_method(_MD("get_resource"),&ResourceInteractiveLoader::get_resource);
- ClassDB::bind_method(_MD("poll"),&ResourceInteractiveLoader::poll);
- ClassDB::bind_method(_MD("wait"),&ResourceInteractiveLoader::wait);
- ClassDB::bind_method(_MD("get_stage"),&ResourceInteractiveLoader::get_stage);
- ClassDB::bind_method(_MD("get_stage_count"),&ResourceInteractiveLoader::get_stage_count);
+ ClassDB::bind_method(D_METHOD("get_resource"),&ResourceInteractiveLoader::get_resource);
+ ClassDB::bind_method(D_METHOD("poll"),&ResourceInteractiveLoader::poll);
+ ClassDB::bind_method(D_METHOD("wait"),&ResourceInteractiveLoader::wait);
+ ClassDB::bind_method(D_METHOD("get_stage"),&ResourceInteractiveLoader::get_stage);
+ ClassDB::bind_method(D_METHOD("get_stage_count"),&ResourceInteractiveLoader::get_stage_count);
}
class ResourceInteractiveLoaderDefault : public ResourceInteractiveLoader {
@@ -191,12 +192,15 @@ RES ResourceLoader::load(const String &p_path, const String& p_type_hint, bool p
for (int i=0;i<loader_count;i++) {
- if (!loader[i]->recognize_path(local_path,p_type_hint))
+ if (!loader[i]->recognize_path(local_path,p_type_hint)) {
+ print_line("path not recognized");
continue;
+ }
found=true;
RES res = loader[i]->load(local_path,local_path,r_error);
- if (res.is_null())
+ if (res.is_null()) {
continue;
+ }
if (!p_no_cache)
res->set_path(local_path);
#ifdef TOOLS_ENABLED
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 222d3e6bc0..f0bea30051 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "resource_saver.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
#include "script_language.h"
#include "resource_loader.h"
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index a2812edb81..3c4719269f 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -389,57 +389,57 @@ Variant StreamPeer::get_var(){
void StreamPeer::_bind_methods() {
- ClassDB::bind_method(_MD("put_data","data"),&StreamPeer::_put_data);
- ClassDB::bind_method(_MD("put_partial_data","data"),&StreamPeer::_put_partial_data);
-
- ClassDB::bind_method(_MD("get_data","bytes"),&StreamPeer::_get_data);
- ClassDB::bind_method(_MD("get_partial_data","bytes"),&StreamPeer::_get_partial_data);
-
- ClassDB::bind_method(_MD("get_available_bytes"),&StreamPeer::get_available_bytes);
-
- ClassDB::bind_method(_MD("set_big_endian","enable"),&StreamPeer::set_big_endian);
- ClassDB::bind_method(_MD("is_big_endian_enabled"),&StreamPeer::is_big_endian_enabled);
-
- ClassDB::bind_method(_MD("put_8","val"),&StreamPeer::put_8);
- ClassDB::bind_method(_MD("put_u8","val"),&StreamPeer::put_u8);
- ClassDB::bind_method(_MD("put_16","val"),&StreamPeer::put_16);
- ClassDB::bind_method(_MD("put_u16","val"),&StreamPeer::put_u16);
- ClassDB::bind_method(_MD("put_32","val"),&StreamPeer::put_32);
- ClassDB::bind_method(_MD("put_u32","val"),&StreamPeer::put_u32);
- ClassDB::bind_method(_MD("put_64","val"),&StreamPeer::put_64);
- ClassDB::bind_method(_MD("put_u64","val"),&StreamPeer::put_u64);
- ClassDB::bind_method(_MD("put_float","val"),&StreamPeer::put_float);
- ClassDB::bind_method(_MD("put_double","val"),&StreamPeer::put_double);
- ClassDB::bind_method(_MD("put_utf8_string","val"),&StreamPeer::put_utf8_string);
- ClassDB::bind_method(_MD("put_var","val:Variant"),&StreamPeer::put_var);
-
- ClassDB::bind_method(_MD("get_8"),&StreamPeer::get_8);
- ClassDB::bind_method(_MD("get_u8"),&StreamPeer::get_u8);
- ClassDB::bind_method(_MD("get_16"),&StreamPeer::get_16);
- ClassDB::bind_method(_MD("get_u16"),&StreamPeer::get_u16);
- ClassDB::bind_method(_MD("get_32"),&StreamPeer::get_32);
- ClassDB::bind_method(_MD("get_u32"),&StreamPeer::get_u32);
- ClassDB::bind_method(_MD("get_64"),&StreamPeer::get_64);
- ClassDB::bind_method(_MD("get_u64"),&StreamPeer::get_u64);
- ClassDB::bind_method(_MD("get_float"),&StreamPeer::get_float);
- ClassDB::bind_method(_MD("get_double"),&StreamPeer::get_double);
- ClassDB::bind_method(_MD("get_string","bytes"),&StreamPeer::get_string);
- ClassDB::bind_method(_MD("get_utf8_string","bytes"),&StreamPeer::get_utf8_string);
- ClassDB::bind_method(_MD("get_var:Variant"),&StreamPeer::get_var);
+ ClassDB::bind_method(D_METHOD("put_data","data"),&StreamPeer::_put_data);
+ ClassDB::bind_method(D_METHOD("put_partial_data","data"),&StreamPeer::_put_partial_data);
+
+ ClassDB::bind_method(D_METHOD("get_data","bytes"),&StreamPeer::_get_data);
+ ClassDB::bind_method(D_METHOD("get_partial_data","bytes"),&StreamPeer::_get_partial_data);
+
+ ClassDB::bind_method(D_METHOD("get_available_bytes"),&StreamPeer::get_available_bytes);
+
+ ClassDB::bind_method(D_METHOD("set_big_endian","enable"),&StreamPeer::set_big_endian);
+ ClassDB::bind_method(D_METHOD("is_big_endian_enabled"),&StreamPeer::is_big_endian_enabled);
+
+ ClassDB::bind_method(D_METHOD("put_8","val"),&StreamPeer::put_8);
+ ClassDB::bind_method(D_METHOD("put_u8","val"),&StreamPeer::put_u8);
+ ClassDB::bind_method(D_METHOD("put_16","val"),&StreamPeer::put_16);
+ ClassDB::bind_method(D_METHOD("put_u16","val"),&StreamPeer::put_u16);
+ ClassDB::bind_method(D_METHOD("put_32","val"),&StreamPeer::put_32);
+ ClassDB::bind_method(D_METHOD("put_u32","val"),&StreamPeer::put_u32);
+ ClassDB::bind_method(D_METHOD("put_64","val"),&StreamPeer::put_64);
+ ClassDB::bind_method(D_METHOD("put_u64","val"),&StreamPeer::put_u64);
+ ClassDB::bind_method(D_METHOD("put_float","val"),&StreamPeer::put_float);
+ ClassDB::bind_method(D_METHOD("put_double","val"),&StreamPeer::put_double);
+ ClassDB::bind_method(D_METHOD("put_utf8_string","val"),&StreamPeer::put_utf8_string);
+ ClassDB::bind_method(D_METHOD("put_var","val:Variant"),&StreamPeer::put_var);
+
+ ClassDB::bind_method(D_METHOD("get_8"),&StreamPeer::get_8);
+ ClassDB::bind_method(D_METHOD("get_u8"),&StreamPeer::get_u8);
+ ClassDB::bind_method(D_METHOD("get_16"),&StreamPeer::get_16);
+ ClassDB::bind_method(D_METHOD("get_u16"),&StreamPeer::get_u16);
+ ClassDB::bind_method(D_METHOD("get_32"),&StreamPeer::get_32);
+ ClassDB::bind_method(D_METHOD("get_u32"),&StreamPeer::get_u32);
+ ClassDB::bind_method(D_METHOD("get_64"),&StreamPeer::get_64);
+ ClassDB::bind_method(D_METHOD("get_u64"),&StreamPeer::get_u64);
+ ClassDB::bind_method(D_METHOD("get_float"),&StreamPeer::get_float);
+ ClassDB::bind_method(D_METHOD("get_double"),&StreamPeer::get_double);
+ ClassDB::bind_method(D_METHOD("get_string","bytes"),&StreamPeer::get_string);
+ ClassDB::bind_method(D_METHOD("get_utf8_string","bytes"),&StreamPeer::get_utf8_string);
+ ClassDB::bind_method(D_METHOD("get_var:Variant"),&StreamPeer::get_var);
}
////////////////////////////////
void StreamPeerBuffer::_bind_methods() {
- ClassDB::bind_method(_MD("seek","pos"),&StreamPeerBuffer::seek);
- ClassDB::bind_method(_MD("get_size"),&StreamPeerBuffer::get_size);
- ClassDB::bind_method(_MD("get_pos"),&StreamPeerBuffer::get_pos);
- ClassDB::bind_method(_MD("resize","size"),&StreamPeerBuffer::resize);
- ClassDB::bind_method(_MD("set_data_array","data"),&StreamPeerBuffer::set_data_array);
- ClassDB::bind_method(_MD("get_data_array"),&StreamPeerBuffer::get_data_array);
- ClassDB::bind_method(_MD("clear"),&StreamPeerBuffer::clear);
- ClassDB::bind_method(_MD("duplicate:StreamPeerBuffer"),&StreamPeerBuffer::duplicate);
+ ClassDB::bind_method(D_METHOD("seek","pos"),&StreamPeerBuffer::seek);
+ ClassDB::bind_method(D_METHOD("get_size"),&StreamPeerBuffer::get_size);
+ ClassDB::bind_method(D_METHOD("get_pos"),&StreamPeerBuffer::get_pos);
+ ClassDB::bind_method(D_METHOD("resize","size"),&StreamPeerBuffer::resize);
+ ClassDB::bind_method(D_METHOD("set_data_array","data"),&StreamPeerBuffer::set_data_array);
+ ClassDB::bind_method(D_METHOD("get_data_array"),&StreamPeerBuffer::get_data_array);
+ ClassDB::bind_method(D_METHOD("clear"),&StreamPeerBuffer::clear);
+ ClassDB::bind_method(D_METHOD("duplicate:StreamPeerBuffer"),&StreamPeerBuffer::duplicate);
}
@@ -492,6 +492,8 @@ Error StreamPeerBuffer::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_r
PoolVector<uint8_t>::Read r = data.read();
copymem(p_buffer,r.ptr(),r_received);
+
+ // FIXME: return what? OK or ERR_*
}
int StreamPeerBuffer::get_available_bytes() const {
diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp
index fc535e94b0..5f7247bd7a 100644
--- a/core/io/stream_peer_ssl.cpp
+++ b/core/io/stream_peer_ssl.cpp
@@ -57,10 +57,10 @@ bool StreamPeerSSL::is_available() {
void StreamPeerSSL::_bind_methods() {
- ClassDB::bind_method(_MD("accept_stream:Error","stream:StreamPeer"),&StreamPeerSSL::accept_stream);
- ClassDB::bind_method(_MD("connect_to_stream:Error","stream:StreamPeer","validate_certs","for_hostname"),&StreamPeerSSL::connect_to_stream,DEFVAL(false),DEFVAL(String()));
- ClassDB::bind_method(_MD("get_status"),&StreamPeerSSL::get_status);
- ClassDB::bind_method(_MD("disconnect_from_stream"),&StreamPeerSSL::disconnect_from_stream);
+ ClassDB::bind_method(D_METHOD("accept_stream:Error","stream:StreamPeer"),&StreamPeerSSL::accept_stream);
+ ClassDB::bind_method(D_METHOD("connect_to_stream:Error","stream:StreamPeer","validate_certs","for_hostname"),&StreamPeerSSL::connect_to_stream,DEFVAL(false),DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("get_status"),&StreamPeerSSL::get_status);
+ ClassDB::bind_method(D_METHOD("disconnect_from_stream"),&StreamPeerSSL::disconnect_from_stream);
BIND_CONSTANT( STATUS_DISCONNECTED );
BIND_CONSTANT( STATUS_CONNECTED );
BIND_CONSTANT( STATUS_ERROR_NO_CERTIFICATE );
diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp
index 0a59c32995..cedc33079e 100644
--- a/core/io/stream_peer_tcp.cpp
+++ b/core/io/stream_peer_tcp.cpp
@@ -36,8 +36,8 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port) {
if (p_address.is_valid_ip_address()) {
ip=p_address;
} else {
- ip=IP::get_singleton()->resolve_hostname(p_address, ip_type);
- if (ip==IP_Address())
+ ip=IP::get_singleton()->resolve_hostname(p_address);
+ if (!ip.is_valid())
return ERR_CANT_RESOLVE;
}
@@ -45,20 +45,14 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port) {
return OK;
}
-void StreamPeerTCP::set_ip_type(IP::Type p_type) {
- disconnect_from_host();
- ip_type = p_type;
-}
-
void StreamPeerTCP::_bind_methods() {
- ClassDB::bind_method(_MD("set_ip_type","ip_type"),&StreamPeerTCP::set_ip_type);
- ClassDB::bind_method(_MD("connect_to_host","host","port"),&StreamPeerTCP::_connect);
- ClassDB::bind_method(_MD("is_connected_to_host"),&StreamPeerTCP::is_connected_to_host);
- ClassDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status);
- ClassDB::bind_method(_MD("get_connected_host"),&StreamPeerTCP::get_connected_host);
- ClassDB::bind_method(_MD("get_connected_port"),&StreamPeerTCP::get_connected_port);
- ClassDB::bind_method(_MD("disconnect_from_host"),&StreamPeerTCP::disconnect_from_host);
+ ClassDB::bind_method(D_METHOD("connect_to_host","host","port"),&StreamPeerTCP::_connect);
+ ClassDB::bind_method(D_METHOD("is_connected_to_host"),&StreamPeerTCP::is_connected_to_host);
+ ClassDB::bind_method(D_METHOD("get_status"),&StreamPeerTCP::get_status);
+ ClassDB::bind_method(D_METHOD("get_connected_host"),&StreamPeerTCP::get_connected_host);
+ ClassDB::bind_method(D_METHOD("get_connected_port"),&StreamPeerTCP::get_connected_port);
+ ClassDB::bind_method(D_METHOD("disconnect_from_host"),&StreamPeerTCP::disconnect_from_host);
BIND_CONSTANT( STATUS_NONE );
BIND_CONSTANT( STATUS_CONNECTING );
@@ -83,7 +77,6 @@ StreamPeerTCP* StreamPeerTCP::create() {
StreamPeerTCP::StreamPeerTCP() {
- ip_type = IP::TYPE_ANY;
}
StreamPeerTCP::~StreamPeerTCP() {
diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h
index 2b25f31739..4401378743 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -51,15 +51,12 @@ public:
protected:
- IP::Type ip_type;
-
virtual Error _connect(const String& p_address, int p_port);
static StreamPeerTCP* (*_create)();
static void _bind_methods();
public:
- virtual void set_ip_type(IP::Type p_type);
virtual Error connect_to_host(const IP_Address& p_host, uint16_t p_port)=0;
//read/write from streampeer
diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp
index bfa5dce58f..5127bd6e3b 100644
--- a/core/io/tcp_server.cpp
+++ b/core/io/tcp_server.cpp
@@ -44,33 +44,17 @@ TCP_Server* TCP_Server::create() {
return _create();
}
-Error TCP_Server::_listen(uint16_t p_port, PoolVector<String> p_accepted_hosts) {
-
- List<String> hosts;
- for(int i=0;i<p_accepted_hosts.size();i++)
- hosts.push_back(p_accepted_hosts.get(i));
-
- return listen(p_port, hosts.size()?&hosts:NULL);
-
-}
-
-void TCP_Server::set_ip_type(IP::Type p_type) {
- stop();
- ip_type = p_type;
-}
-
void TCP_Server::_bind_methods() {
- ClassDB::bind_method(_MD("set_ip_type","ip_type"),&TCP_Server::set_ip_type);
- ClassDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(PoolVector<String>()));
- ClassDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available);
- ClassDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection);
- ClassDB::bind_method(_MD("stop"),&TCP_Server::stop);
+ ClassDB::bind_method(D_METHOD("listen","port","bind_address"),&TCP_Server::listen,DEFVAL("*"));
+ ClassDB::bind_method(D_METHOD("is_connection_available"),&TCP_Server::is_connection_available);
+ ClassDB::bind_method(D_METHOD("take_connection"),&TCP_Server::take_connection);
+ ClassDB::bind_method(D_METHOD("stop"),&TCP_Server::stop);
}
TCP_Server::TCP_Server()
{
- ip_type = IP::TYPE_ANY;
+
}
diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h
index 3d7b3ddd8d..3cbd8c58cf 100644
--- a/core/io/tcp_server.h
+++ b/core/io/tcp_server.h
@@ -38,17 +38,13 @@ class TCP_Server : public Reference {
GDCLASS( TCP_Server, Reference );
protected:
- IP::Type ip_type;
-
static TCP_Server* (*_create)();
//bind helper
- Error _listen(uint16_t p_port, PoolVector<String> p_accepted_hosts=PoolVector<String>());
static void _bind_methods();
public:
- virtual void set_ip_type(IP::Type p_type);
- virtual Error listen(uint16_t p_port, const List<String> *p_accepted_hosts=NULL)=0;
+ virtual Error listen(uint16_t p_port, const IP_Address p_bind_address=IP_Address("*"))=0;
virtual bool is_connection_available() const=0;
virtual Ref<StreamPeerTCP> take_connection()=0;
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 0322f23056..1a4ff1a8d4 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -379,23 +379,23 @@ Error XMLParser::seek(uint64_t p_pos) {
void XMLParser::_bind_methods() {
- ClassDB::bind_method(_MD("read"),&XMLParser::read);
- ClassDB::bind_method(_MD("get_node_type"),&XMLParser::get_node_type);
- ClassDB::bind_method(_MD("get_node_name"),&XMLParser::get_node_name);
- ClassDB::bind_method(_MD("get_node_data"),&XMLParser::get_node_data);
- ClassDB::bind_method(_MD("get_node_offset"),&XMLParser::get_node_offset);
- ClassDB::bind_method(_MD("get_attribute_count"),&XMLParser::get_attribute_count);
- ClassDB::bind_method(_MD("get_attribute_name","idx"),&XMLParser::get_attribute_name);
- ClassDB::bind_method(_MD("get_attribute_value","idx"),(String (XMLParser::*)(int) const) &XMLParser::get_attribute_value);
- ClassDB::bind_method(_MD("has_attribute","name"),&XMLParser::has_attribute);
- ClassDB::bind_method(_MD("get_named_attribute_value","name"), (String (XMLParser::*)(const String&) const) &XMLParser::get_attribute_value);
- ClassDB::bind_method(_MD("get_named_attribute_value_safe","name"), &XMLParser::get_attribute_value_safe);
- ClassDB::bind_method(_MD("is_empty"),&XMLParser::is_empty);
- ClassDB::bind_method(_MD("get_current_line"),&XMLParser::get_current_line);
- ClassDB::bind_method(_MD("skip_section"),&XMLParser::skip_section);
- ClassDB::bind_method(_MD("seek","pos"),&XMLParser::seek);
- ClassDB::bind_method(_MD("open","file"),&XMLParser::open);
- ClassDB::bind_method(_MD("open_buffer","buffer"),&XMLParser::open_buffer);
+ ClassDB::bind_method(D_METHOD("read"),&XMLParser::read);
+ ClassDB::bind_method(D_METHOD("get_node_type"),&XMLParser::get_node_type);
+ ClassDB::bind_method(D_METHOD("get_node_name"),&XMLParser::get_node_name);
+ ClassDB::bind_method(D_METHOD("get_node_data"),&XMLParser::get_node_data);
+ ClassDB::bind_method(D_METHOD("get_node_offset"),&XMLParser::get_node_offset);
+ ClassDB::bind_method(D_METHOD("get_attribute_count"),&XMLParser::get_attribute_count);
+ ClassDB::bind_method(D_METHOD("get_attribute_name","idx"),&XMLParser::get_attribute_name);
+ ClassDB::bind_method(D_METHOD("get_attribute_value","idx"),(String (XMLParser::*)(int) const) &XMLParser::get_attribute_value);
+ ClassDB::bind_method(D_METHOD("has_attribute","name"),&XMLParser::has_attribute);
+ ClassDB::bind_method(D_METHOD("get_named_attribute_value","name"), (String (XMLParser::*)(const String&) const) &XMLParser::get_attribute_value);
+ ClassDB::bind_method(D_METHOD("get_named_attribute_value_safe","name"), &XMLParser::get_attribute_value_safe);
+ ClassDB::bind_method(D_METHOD("is_empty"),&XMLParser::is_empty);
+ ClassDB::bind_method(D_METHOD("get_current_line"),&XMLParser::get_current_line);
+ ClassDB::bind_method(D_METHOD("skip_section"),&XMLParser::skip_section);
+ ClassDB::bind_method(D_METHOD("seek","pos"),&XMLParser::seek);
+ ClassDB::bind_method(D_METHOD("open","file"),&XMLParser::open);
+ ClassDB::bind_method(D_METHOD("open_buffer","buffer"),&XMLParser::open_buffer);
BIND_CONSTANT( NODE_NONE );
BIND_CONSTANT( NODE_ELEMENT );
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index a1f471ebe3..7e31957e3e 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -407,23 +407,23 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
void AStar::_bind_methods() {
- ClassDB::bind_method(_MD("get_available_point_id"),&AStar::get_available_point_id);
- ClassDB::bind_method(_MD("add_point","id","pos","weight_scale"),&AStar::add_point,DEFVAL(1.0));
- ClassDB::bind_method(_MD("get_point_pos","id"),&AStar::get_point_pos);
- ClassDB::bind_method(_MD("get_point_weight_scale","id"),&AStar::get_point_weight_scale);
- ClassDB::bind_method(_MD("remove_point","id"),&AStar::remove_point);
+ ClassDB::bind_method(D_METHOD("get_available_point_id"),&AStar::get_available_point_id);
+ ClassDB::bind_method(D_METHOD("add_point","id","pos","weight_scale"),&AStar::add_point,DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("get_point_pos","id"),&AStar::get_point_pos);
+ ClassDB::bind_method(D_METHOD("get_point_weight_scale","id"),&AStar::get_point_weight_scale);
+ ClassDB::bind_method(D_METHOD("remove_point","id"),&AStar::remove_point);
- ClassDB::bind_method(_MD("connect_points","id","to_id"),&AStar::connect_points);
- ClassDB::bind_method(_MD("disconnect_points","id","to_id"),&AStar::disconnect_points);
- ClassDB::bind_method(_MD("are_points_connected","id","to_id"),&AStar::are_points_connected);
+ ClassDB::bind_method(D_METHOD("connect_points","id","to_id"),&AStar::connect_points);
+ ClassDB::bind_method(D_METHOD("disconnect_points","id","to_id"),&AStar::disconnect_points);
+ ClassDB::bind_method(D_METHOD("are_points_connected","id","to_id"),&AStar::are_points_connected);
- ClassDB::bind_method(_MD("clear"),&AStar::clear);
+ ClassDB::bind_method(D_METHOD("clear"),&AStar::clear);
- ClassDB::bind_method(_MD("get_closest_point","to_pos"),&AStar::get_closest_point);
- ClassDB::bind_method(_MD("get_closest_pos_in_segment","to_pos"),&AStar::get_closest_pos_in_segment);
+ ClassDB::bind_method(D_METHOD("get_closest_point","to_pos"),&AStar::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_pos_in_segment","to_pos"),&AStar::get_closest_pos_in_segment);
- ClassDB::bind_method(_MD("get_point_path","from_id","to_id"),&AStar::get_point_path);
- ClassDB::bind_method(_MD("get_id_path","from_id","to_id"),&AStar::get_id_path);
+ ClassDB::bind_method(D_METHOD("get_point_path","from_id","to_id"),&AStar::get_point_path);
+ ClassDB::bind_method(D_METHOD("get_id_path","from_id","to_id"),&AStar::get_id_path);
}
diff --git a/core/math/audio_frame.cpp b/core/math/audio_frame.cpp
index 566ba23992..aae1561a84 100644
--- a/core/math/audio_frame.cpp
+++ b/core/math/audio_frame.cpp
@@ -1,2 +1,30 @@
+/*************************************************************************/
+/* audio_frame.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_frame.h"
diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h
index acd74903bb..e4e93f34fa 100644
--- a/core/math/audio_frame.h
+++ b/core/math/audio_frame.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_frame.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOFRAME_H
#define AUDIOFRAME_H
diff --git a/core/math/geometry.h b/core/math/geometry.h
index 13cbbdce6f..1dd7df038d 100644
--- a/core/math/geometry.h
+++ b/core/math/geometry.h
@@ -109,6 +109,7 @@ public:
static void get_closest_points_between_segments(const Vector3& p1,const Vector3& p2,const Vector3& q1,const Vector3& q2,Vector3& c1, Vector3& c2)
{
+#if 0
//do the function 'd' as defined by pb. I think is is dot product of some sort
#define d_of(m,n,o,p) ( (m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z) )
@@ -123,6 +124,33 @@ public:
if (mub > 1) mub = 1;
c1 = p1.linear_interpolate(p2,mua);
c2 = q1.linear_interpolate(q2,mub);
+#endif
+
+ Vector3 u = p2 - p1;
+ Vector3 v = q2 - q1;
+ Vector3 w = p1 - q1;
+ float a = u.dot(u);
+ float b = u.dot(v);
+ float c = v.dot(v); // always >= 0
+ float d = u.dot(w);
+ float e = v.dot(w);
+ float D = a*c - b*b; // always >= 0
+ float sc, tc;
+
+ // compute the line parameters of the two closest points
+ if (D < CMP_EPSILON) { // the lines are almost parallel
+ sc = 0.0;
+ tc = (b>c ? d/b : e/c); // use the largest denominator
+ }
+ else {
+ sc = (b*e - c*d) / D;
+ tc = (a*e - b*d) / D;
+ }
+
+ c1 = w + sc * u;
+ c2 = w + tc * v;
+ // get the difference of the two closest points
+ //Vector dP = w + (sc * u) - (tc * v); // = L1(sc) - L2(tc)
}
static real_t get_closest_distance_between_segments( const Vector3& p_from_a,const Vector3& p_to_a, const Vector3& p_from_b,const Vector3& p_to_b) {
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 511af91835..ae461eda2e 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -39,6 +39,8 @@
#define Math_PI 3.14159265358979323846
#define Math_SQRT12 0.7071067811865475244008443621048490
#define Math_LN2 0.693147180559945309417
+#define Math_INF INFINITY
+#define Math_NAN NAN
class Math {
@@ -48,7 +50,7 @@ public:
Math() {} // useless to instance
enum {
- RANDOM_MAX=2147483647L
+ RANDOM_MAX=4294967295L
};
diff --git a/core/message_queue.cpp b/core/message_queue.cpp
index 668d321e05..50b52e4970 100644
--- a/core/message_queue.cpp
+++ b/core/message_queue.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "message_queue.h"
-#include "globals.h"
+#include "global_config.h"
#include "script_language.h"
MessageQueue *MessageQueue::singleton=NULL;
diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h
index a35e44b66c..e175a10156 100644
--- a/core/method_ptrcall.h
+++ b/core/method_ptrcall.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* method_ptrcall.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 METHOD_PTRCALL_H
#define METHOD_PTRCALL_H
diff --git a/core/object.cpp b/core/object.cpp
index 26308dc64f..79905a6be6 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -383,7 +383,7 @@ void Object::set(const String& p_name, const Variant& p_value) {
if (p_name=="__meta__") {
metadata=p_value;
- } else if (p_name=="script/script") {
+ } else if (p_name=="script") {
set_script(p_value);
} else if (script_instance) {
script_instance->set(p_name,p_value);
@@ -516,7 +516,7 @@ Variant Object::get(const String& p_name) const {
if (p_name=="__meta__")
return metadata;
- else if (p_name=="script/script")
+ else if (p_name=="script")
return script;
if (script_instance) {
@@ -539,7 +539,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list,bool p_reversed) const
if (!is_class("Script")) // can still be set, but this is for userfriendlyness
- p_list->push_back( PropertyInfo( Variant::OBJECT, "script/script", PROPERTY_HINT_RESOURCE_TYPE, "Script",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_STORE_IF_NONZERO));
+ p_list->push_back( PropertyInfo( Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_STORE_IF_NONZERO));
if (!metadata.empty())
p_list->push_back( PropertyInfo( Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_STORE_IF_NONZERO));
if (script_instance && !p_reversed) {
@@ -1041,7 +1041,7 @@ void Object::set_script(const RefPtr& p_script) {
}
- _change_notify("script/script");
+ _change_notify("script");
emit_signal(CoreStringNames::get_singleton()->script_changed);
}
@@ -1675,31 +1675,31 @@ void Object::clear_internal_resource_paths() {
void Object::_bind_methods() {
- ClassDB::bind_method(_MD("get_class"),&Object::get_class);
- ClassDB::bind_method(_MD("is_class","type"),&Object::is_class);
- ClassDB::bind_method(_MD("set","property","value"),&Object::_set_bind);
- ClassDB::bind_method(_MD("get","property"),&Object::_get_bind);
- ClassDB::bind_method(_MD("get_property_list"),&Object::_get_property_list_bind);
- ClassDB::bind_method(_MD("get_method_list"),&Object::_get_method_list_bind);
- ClassDB::bind_method(_MD("notification","what","reversed"),&Object::notification,DEFVAL(false));
- ClassDB::bind_method(_MD("get_instance_ID"),&Object::get_instance_ID);
+ ClassDB::bind_method(D_METHOD("get_class"),&Object::get_class);
+ ClassDB::bind_method(D_METHOD("is_class","type"),&Object::is_class);
+ ClassDB::bind_method(D_METHOD("set","property","value"),&Object::_set_bind);
+ ClassDB::bind_method(D_METHOD("get","property"),&Object::_get_bind);
+ ClassDB::bind_method(D_METHOD("get_property_list"),&Object::_get_property_list_bind);
+ ClassDB::bind_method(D_METHOD("get_method_list"),&Object::_get_method_list_bind);
+ ClassDB::bind_method(D_METHOD("notification","what","reversed"),&Object::notification,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_instance_ID"),&Object::get_instance_ID);
- ClassDB::bind_method(_MD("set_script","script:Script"),&Object::set_script);
- ClassDB::bind_method(_MD("get_script:Script"),&Object::get_script);
+ ClassDB::bind_method(D_METHOD("set_script","script:Script"),&Object::set_script);
+ ClassDB::bind_method(D_METHOD("get_script:Script"),&Object::get_script);
- ClassDB::bind_method(_MD("set_meta","name","value"),&Object::set_meta);
- ClassDB::bind_method(_MD("get_meta","name","value"),&Object::get_meta);
- ClassDB::bind_method(_MD("has_meta","name"),&Object::has_meta);
- ClassDB::bind_method(_MD("get_meta_list"),&Object::_get_meta_list_bind);
+ ClassDB::bind_method(D_METHOD("set_meta","name","value"),&Object::set_meta);
+ ClassDB::bind_method(D_METHOD("get_meta","name","value"),&Object::get_meta);
+ ClassDB::bind_method(D_METHOD("has_meta","name"),&Object::has_meta);
+ ClassDB::bind_method(D_METHOD("get_meta_list"),&Object::_get_meta_list_bind);
//todo reimplement this per language so all 5 arguments can be called
- //ClassDB::bind_method(_MD("call","method","arg1","arg2","arg3","arg4"),&Object::_call_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
- //ClassDB::bind_method(_MD("call_deferred","method","arg1","arg2","arg3","arg4"),&Object::_call_deferred_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
+ //ClassDB::bind_method(D_METHOD("call","method","arg1","arg2","arg3","arg4"),&Object::_call_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
+ //ClassDB::bind_method(D_METHOD("call_deferred","method","arg1","arg2","arg3","arg4"),&Object::_call_deferred_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
- ClassDB::bind_method(_MD("add_user_signal","signal","arguments"),&Object::_add_user_signal,DEFVAL(Array()));
- ClassDB::bind_method(_MD("has_user_signal","signal"),&Object::_has_user_signal);
- //ClassDB::bind_method(_MD("emit_signal","signal","arguments"),&Object::_emit_signal,DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("add_user_signal","signal","arguments"),&Object::_add_user_signal,DEFVAL(Array()));
+ ClassDB::bind_method(D_METHOD("has_user_signal","signal"),&Object::_has_user_signal);
+ //ClassDB::bind_method(D_METHOD("emit_signal","signal","arguments"),&Object::_emit_signal,DEFVAL(Array()));
{
@@ -1728,27 +1728,27 @@ void Object::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi);
}
- ClassDB::bind_method(_MD("callv:Variant","method","arg_array"),&Object::callv);
+ ClassDB::bind_method(D_METHOD("callv:Variant","method","arg_array"),&Object::callv);
- ClassDB::bind_method(_MD("has_method","method"),&Object::has_method);
+ ClassDB::bind_method(D_METHOD("has_method","method"),&Object::has_method);
- ClassDB::bind_method(_MD("get_signal_list"),&Object::_get_signal_list);
- ClassDB::bind_method(_MD("get_signal_connection_list","signal"),&Object::_get_signal_connection_list);
+ ClassDB::bind_method(D_METHOD("get_signal_list"),&Object::_get_signal_list);
+ ClassDB::bind_method(D_METHOD("get_signal_connection_list","signal"),&Object::_get_signal_connection_list);
- ClassDB::bind_method(_MD("connect","signal","target:Object","method","binds","flags"),&Object::connect,DEFVAL(Array()),DEFVAL(0));
- ClassDB::bind_method(_MD("disconnect","signal","target:Object","method"),&Object::disconnect);
- ClassDB::bind_method(_MD("is_connected","signal","target:Object","method"),&Object::is_connected);
+ ClassDB::bind_method(D_METHOD("connect","signal","target:Object","method","binds","flags"),&Object::connect,DEFVAL(Array()),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("disconnect","signal","target:Object","method"),&Object::disconnect);
+ ClassDB::bind_method(D_METHOD("is_connected","signal","target:Object","method"),&Object::is_connected);
- ClassDB::bind_method(_MD("set_block_signals","enable"),&Object::set_block_signals);
- ClassDB::bind_method(_MD("is_blocking_signals"),&Object::is_blocking_signals);
- ClassDB::bind_method(_MD("set_message_translation","enable"),&Object::set_message_translation);
- ClassDB::bind_method(_MD("can_translate_messages"),&Object::can_translate_messages);
- ClassDB::bind_method(_MD("property_list_changed_notify"),&Object::property_list_changed_notify);
+ ClassDB::bind_method(D_METHOD("set_block_signals","enable"),&Object::set_block_signals);
+ ClassDB::bind_method(D_METHOD("is_blocking_signals"),&Object::is_blocking_signals);
+ ClassDB::bind_method(D_METHOD("set_message_translation","enable"),&Object::set_message_translation);
+ ClassDB::bind_method(D_METHOD("can_translate_messages"),&Object::can_translate_messages);
+ ClassDB::bind_method(D_METHOD("property_list_changed_notify"),&Object::property_list_changed_notify);
- ClassDB::bind_method(_MD("XL_MESSAGE","message"),&Object::XL_MESSAGE);
- ClassDB::bind_method(_MD("tr","message"),&Object::tr);
+ ClassDB::bind_method(D_METHOD("XL_MESSAGE","message"),&Object::XL_MESSAGE);
+ ClassDB::bind_method(D_METHOD("tr","message"),&Object::tr);
- ClassDB::bind_method(_MD("is_queued_for_deletion"),&Object::is_queued_for_deletion);
+ ClassDB::bind_method(D_METHOD("is_queued_for_deletion"),&Object::is_queued_for_deletion);
ClassDB::add_virtual_method("Object",MethodInfo("free"),false);
diff --git a/core/object.h b/core/object.h
index 3032452ccf..3fe31bee6b 100644
--- a/core/object.h
+++ b/core/object.h
@@ -114,12 +114,12 @@ enum PropertyUsageFlags {
#define ADD_SIGNAL( m_signal ) ClassDB::add_signal( get_class_static(), m_signal )
-#define ADD_PROPERTY( m_property, m_setter, m_getter ) ClassDB::add_property( get_class_static(), m_property, m_setter, m_getter )
-#define ADD_PROPERTYI( m_property, m_setter, m_getter, m_index ) ClassDB::add_property( get_class_static(), m_property, m_setter, m_getter, m_index )
-#define ADD_PROPERTYNZ( m_property, m_setter, m_getter ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter )
-#define ADD_PROPERTYINZ( m_property, m_setter, m_getter, m_index ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter, m_index )
-#define ADD_PROPERTYNO( m_property, m_setter, m_getter ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter )
-#define ADD_PROPERTYINO( m_property, m_setter, m_getter, m_index ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter, m_index )
+#define ADD_PROPERTY( m_property, m_setter, m_getter ) ClassDB::add_property( get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter) )
+#define ADD_PROPERTYI( m_property, m_setter, m_getter, m_index ) ClassDB::add_property( get_class_static(), m_property, _scs_create(m_setter), _scs_create(m_getter), m_index )
+#define ADD_PROPERTYNZ( m_property, m_setter, m_getter ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), _scs_create(m_setter), _scs_create(m_getter) )
+#define ADD_PROPERTYINZ( m_property, m_setter, m_getter, m_index ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), _scs_create(m_setter), _scs_create(m_getter), m_index )
+#define ADD_PROPERTYNO( m_property, m_setter, m_getter ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), _scs_create(m_setter), _scs_create(m_getter) )
+#define ADD_PROPERTYINO( m_property, m_setter, m_getter, m_index ) ClassDB::add_property( get_class_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), _scs_create(m_setter), _scs_create(m_getter), m_index )
#define ADD_GROUP( m_name, m_prefix ) ClassDB::add_property_group( get_class_static(), m_name, m_prefix )
struct PropertyInfo {
@@ -680,7 +680,7 @@ class ObjectDB {
unsigned long i;
} u;
u.p=p_obj;
- return HashMapHahserDefault::hash((uint64_t)u.i);
+ return HashMapHasherDefault::hash((uint64_t)u.i);
}
};
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 804fe15c39..974225a3e8 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -30,7 +30,7 @@
#include "os/file_access.h"
#include "os/memory.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
String DirAccess::_get_root_path() const {
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 06723c5131..ae592720e8 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "file_access.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
#include "core/io/marshalls.h"
#include "io/md5.h"
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 4e7b037453..34883e63ba 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -29,7 +29,7 @@
#include "input.h"
#include "input_map.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
Input *Input::singleton=NULL;
Input *Input::get_singleton() {
@@ -49,40 +49,40 @@ Input::MouseMode Input::get_mouse_mode() const {
void Input::_bind_methods() {
- ClassDB::bind_method(_MD("is_key_pressed","scancode"),&Input::is_key_pressed);
- ClassDB::bind_method(_MD("is_mouse_button_pressed","button"),&Input::is_mouse_button_pressed);
- ClassDB::bind_method(_MD("is_joy_button_pressed","device","button"),&Input::is_joy_button_pressed);
- ClassDB::bind_method(_MD("is_action_pressed","action"),&Input::is_action_pressed);
- ClassDB::bind_method(_MD("is_action_just_pressed","action"),&Input::is_action_just_pressed);
- ClassDB::bind_method(_MD("is_action_just_released","action"),&Input::is_action_just_released);
- ClassDB::bind_method(_MD("add_joy_mapping","mapping", "update_existing"),&Input::add_joy_mapping, DEFVAL(false));
- ClassDB::bind_method(_MD("remove_joy_mapping","guid"),&Input::remove_joy_mapping);
- ClassDB::bind_method(_MD("is_joy_known","device"),&Input::is_joy_known);
- ClassDB::bind_method(_MD("get_joy_axis","device","axis"),&Input::get_joy_axis);
- ClassDB::bind_method(_MD("get_joy_name","device"),&Input::get_joy_name);
- ClassDB::bind_method(_MD("get_joy_guid","device"),&Input::get_joy_guid);
- ClassDB::bind_method(_MD("get_connected_joypads"),&Input::get_connected_joypads);
- ClassDB::bind_method(_MD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
- ClassDB::bind_method(_MD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
- ClassDB::bind_method(_MD("get_joy_button_string", "button_index"), &Input::get_joy_button_string);
- ClassDB::bind_method(_MD("get_joy_button_index_from_string", "button"), &Input::get_joy_button_index_from_string);
- ClassDB::bind_method(_MD("get_joy_axis_string", "axis_index"), &Input::get_joy_axis_string);
- ClassDB::bind_method(_MD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string);
- ClassDB::bind_method(_MD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0));
- ClassDB::bind_method(_MD("stop_joy_vibration", "device"), &Input::stop_joy_vibration);
- ClassDB::bind_method(_MD("get_gravity"),&Input::get_gravity);
- ClassDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer);
- ClassDB::bind_method(_MD("get_magnetometer"),&Input::get_magnetometer);
- ClassDB::bind_method(_MD("get_gyroscope"),&Input::get_gyroscope);
- //ClassDB::bind_method(_MD("get_mouse_pos"),&Input::get_mouse_pos); - this is not the function you want
- ClassDB::bind_method(_MD("get_last_mouse_speed"),&Input::get_last_mouse_speed);
- ClassDB::bind_method(_MD("get_mouse_button_mask"),&Input::get_mouse_button_mask);
- ClassDB::bind_method(_MD("set_mouse_mode","mode"),&Input::set_mouse_mode);
- ClassDB::bind_method(_MD("get_mouse_mode"),&Input::get_mouse_mode);
- ClassDB::bind_method(_MD("warp_mouse_pos","to"),&Input::warp_mouse_pos);
- ClassDB::bind_method(_MD("action_press","action"),&Input::action_press);
- ClassDB::bind_method(_MD("action_release","action"),&Input::action_release);
- ClassDB::bind_method(_MD("set_custom_mouse_cursor","image:Texture","hotspot"),&Input::set_custom_mouse_cursor,DEFVAL(Vector2()));
+ ClassDB::bind_method(D_METHOD("is_key_pressed","scancode"),&Input::is_key_pressed);
+ ClassDB::bind_method(D_METHOD("is_mouse_button_pressed","button"),&Input::is_mouse_button_pressed);
+ ClassDB::bind_method(D_METHOD("is_joy_button_pressed","device","button"),&Input::is_joy_button_pressed);
+ ClassDB::bind_method(D_METHOD("is_action_pressed","action"),&Input::is_action_pressed);
+ ClassDB::bind_method(D_METHOD("is_action_just_pressed","action"),&Input::is_action_just_pressed);
+ ClassDB::bind_method(D_METHOD("is_action_just_released","action"),&Input::is_action_just_released);
+ ClassDB::bind_method(D_METHOD("add_joy_mapping","mapping", "update_existing"),&Input::add_joy_mapping, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("remove_joy_mapping","guid"),&Input::remove_joy_mapping);
+ ClassDB::bind_method(D_METHOD("is_joy_known","device"),&Input::is_joy_known);
+ ClassDB::bind_method(D_METHOD("get_joy_axis","device","axis"),&Input::get_joy_axis);
+ ClassDB::bind_method(D_METHOD("get_joy_name","device"),&Input::get_joy_name);
+ ClassDB::bind_method(D_METHOD("get_joy_guid","device"),&Input::get_joy_guid);
+ ClassDB::bind_method(D_METHOD("get_connected_joypads"),&Input::get_connected_joypads);
+ ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
+ ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
+ ClassDB::bind_method(D_METHOD("get_joy_button_string", "button_index"), &Input::get_joy_button_string);
+ ClassDB::bind_method(D_METHOD("get_joy_button_index_from_string", "button"), &Input::get_joy_button_index_from_string);
+ ClassDB::bind_method(D_METHOD("get_joy_axis_string", "axis_index"), &Input::get_joy_axis_string);
+ ClassDB::bind_method(D_METHOD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string);
+ ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration);
+ ClassDB::bind_method(D_METHOD("get_gravity"),&Input::get_gravity);
+ ClassDB::bind_method(D_METHOD("get_accelerometer"),&Input::get_accelerometer);
+ ClassDB::bind_method(D_METHOD("get_magnetometer"),&Input::get_magnetometer);
+ ClassDB::bind_method(D_METHOD("get_gyroscope"),&Input::get_gyroscope);
+ //ClassDB::bind_method(D_METHOD("get_mouse_pos"),&Input::get_mouse_pos); - this is not the function you want
+ ClassDB::bind_method(D_METHOD("get_last_mouse_speed"),&Input::get_last_mouse_speed);
+ ClassDB::bind_method(D_METHOD("get_mouse_button_mask"),&Input::get_mouse_button_mask);
+ ClassDB::bind_method(D_METHOD("set_mouse_mode","mode"),&Input::set_mouse_mode);
+ ClassDB::bind_method(D_METHOD("get_mouse_mode"),&Input::get_mouse_mode);
+ ClassDB::bind_method(D_METHOD("warp_mouse_pos","to"),&Input::warp_mouse_pos);
+ ClassDB::bind_method(D_METHOD("action_press","action"),&Input::action_press);
+ ClassDB::bind_method(D_METHOD("action_release","action"),&Input::action_release);
+ ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor","image:Texture","hotspot"),&Input::set_custom_mouse_cursor,DEFVAL(Vector2()));
BIND_CONSTANT( MOUSE_MODE_VISIBLE );
BIND_CONSTANT( MOUSE_MODE_HIDDEN );
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 11396666d2..dcda8e8952 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -31,12 +31,12 @@
void MainLoop::_bind_methods() {
- ClassDB::bind_method(_MD("input_event","ev"),&MainLoop::input_event);
- ClassDB::bind_method(_MD("input_text","text"),&MainLoop::input_text);
- ClassDB::bind_method(_MD("init"),&MainLoop::init);
- ClassDB::bind_method(_MD("iteration","delta"),&MainLoop::iteration);
- ClassDB::bind_method(_MD("idle","delta"),&MainLoop::idle);
- ClassDB::bind_method(_MD("finish"),&MainLoop::finish);
+ ClassDB::bind_method(D_METHOD("input_event","ev"),&MainLoop::input_event);
+ ClassDB::bind_method(D_METHOD("input_text","text"),&MainLoop::input_text);
+ ClassDB::bind_method(D_METHOD("init"),&MainLoop::init);
+ ClassDB::bind_method(D_METHOD("iteration","delta"),&MainLoop::iteration);
+ ClassDB::bind_method(D_METHOD("idle","delta"),&MainLoop::idle);
+ ClassDB::bind_method(D_METHOD("finish"),&MainLoop::finish);
BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) );
BIND_VMETHOD( MethodInfo("_input_text",PropertyInfo(Variant::STRING,"text")) );
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 3a8e15a692..1d670b4466 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -29,7 +29,7 @@
#include "os.h"
#include "dir_access.h"
-#include "globals.h"
+#include "global_config.h"
#include "input.h"
#include "os/file_access.h"
@@ -513,6 +513,16 @@ bool OS::is_vsync_enabled() const{
}
+PowerState OS::get_power_state() {
+ return POWERSTATE_UNKNOWN;
+}
+int OS::get_power_seconds_left() {
+ return -1;
+}
+int OS::get_power_percent_left() {
+ return -1;
+}
+
OS::OS() {
last_error=NULL;
singleton=this;
diff --git a/core/os/os.h b/core/os/os.h
index e179b82dae..7c8100679a 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -34,8 +34,10 @@
#include "vector.h"
#include "engine.h"
#include "os/main_loop.h"
+#include "power.h"
#include <stdarg.h>
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -402,6 +404,10 @@ public:
virtual void set_use_vsync(bool p_enable);
virtual bool is_vsync_enabled() const;
+
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
virtual bool check_feature_support(const String& p_feature)=0;
diff --git a/core/os/power.h b/core/os/power.h
new file mode 100644
index 0000000000..c92348ff50
--- /dev/null
+++ b/core/os/power.h
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* power.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 CORE_OS_POWER_H_
+#define CORE_OS_POWER_H_
+
+
+typedef enum
+{
+ POWERSTATE_UNKNOWN, /**< cannot determine power status */
+ POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
+ POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
+ POWERSTATE_CHARGING, /**< Plugged in, charging battery */
+ POWERSTATE_CHARGED /**< Plugged in, battery charged */
+} PowerState;
+
+
+#endif /* CORE_OS_POWER_H_ */
diff --git a/core/os/rw_lock.cpp b/core/os/rw_lock.cpp
index 9b2d1f8a46..3af62aa8da 100644
--- a/core/os/rw_lock.cpp
+++ b/core/os/rw_lock.cpp
@@ -1,7 +1,36 @@
+/*************************************************************************/
+/* rw_lock.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "rw_lock.h"
+
#include "error_macros.h"
-#include <stddef.h>
+#include <stddef.h>
RWLock* (*RWLock::create_func)()=0;
diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h
index c513e6d636..6b4af83bf9 100644
--- a/core/os/rw_lock.h
+++ b/core/os/rw_lock.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* rw_lock.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RWLOCK_H
#define RWLOCK_H
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index d3bb03ab5e..803a217fca 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -382,15 +382,15 @@ Variant PackedDataContainer::_iter_get(const Variant& p_iter){
void PackedDataContainer::_bind_methods() {
- ClassDB::bind_method(_MD("_set_data"),&PackedDataContainer::_set_data);
- ClassDB::bind_method(_MD("_get_data"),&PackedDataContainer::_get_data);
- ClassDB::bind_method(_MD("_iter_init"),&PackedDataContainer::_iter_init);
- ClassDB::bind_method(_MD("_iter_get"),&PackedDataContainer::_iter_get);
- ClassDB::bind_method(_MD("_iter_next"),&PackedDataContainer::_iter_next);
- ClassDB::bind_method(_MD("pack:Error","value"),&PackedDataContainer::pack);
- ClassDB::bind_method(_MD("size"),&PackedDataContainer::size);
-
- ADD_PROPERTY( PropertyInfo(Variant::POOL_BYTE_ARRAY,"__data__"),_SCS("_set_data"),_SCS("_get_data"));
+ ClassDB::bind_method(D_METHOD("_set_data"),&PackedDataContainer::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"),&PackedDataContainer::_get_data);
+ ClassDB::bind_method(D_METHOD("_iter_init"),&PackedDataContainer::_iter_init);
+ ClassDB::bind_method(D_METHOD("_iter_get"),&PackedDataContainer::_iter_get);
+ ClassDB::bind_method(D_METHOD("_iter_next"),&PackedDataContainer::_iter_next);
+ ClassDB::bind_method(D_METHOD("pack:Error","value"),&PackedDataContainer::pack);
+ ClassDB::bind_method(D_METHOD("size"),&PackedDataContainer::size);
+
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_BYTE_ARRAY,"__data__"),"_set_data","_get_data");
}
@@ -426,11 +426,11 @@ bool PackedDataContainerRef::_is_dictionary() const {
void PackedDataContainerRef::_bind_methods() {
- ClassDB::bind_method(_MD("size"),&PackedDataContainerRef::size);
- ClassDB::bind_method(_MD("_iter_init"),&PackedDataContainerRef::_iter_init);
- ClassDB::bind_method(_MD("_iter_get"),&PackedDataContainerRef::_iter_get);
- ClassDB::bind_method(_MD("_iter_next"),&PackedDataContainerRef::_iter_next);
- ClassDB::bind_method(_MD("_is_dictionary"),&PackedDataContainerRef::_is_dictionary);
+ ClassDB::bind_method(D_METHOD("size"),&PackedDataContainerRef::size);
+ ClassDB::bind_method(D_METHOD("_iter_init"),&PackedDataContainerRef::_iter_init);
+ ClassDB::bind_method(D_METHOD("_iter_get"),&PackedDataContainerRef::_iter_get);
+ ClassDB::bind_method(D_METHOD("_iter_next"),&PackedDataContainerRef::_iter_next);
+ ClassDB::bind_method(D_METHOD("_is_dictionary"),&PackedDataContainerRef::_is_dictionary);
}
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index b1417dd107..3260225ac3 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -504,7 +504,7 @@ const void *PoolAllocator::get(ID p_mem) const {
return NULL;
}
- if (e->pos<0 || (int)e->pos>=pool_size) {
+ if ((int)e->pos>=pool_size) {
mt_unlock();
ERR_PRINT("e->pos<0 || e->pos>=pool_size");
@@ -546,7 +546,7 @@ void *PoolAllocator::get(ID p_mem) {
return NULL;
}
- if (e->pos<0 || (int)e->pos>=pool_size) {
+ if ((int)e->pos>=pool_size) {
mt_unlock();
ERR_PRINT("e->pos<0 || e->pos>=pool_size");
diff --git a/core/reference.cpp b/core/reference.cpp
index d21caf0839..5e8244d2ca 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -55,9 +55,9 @@ bool Reference::init_ref() {
void Reference::_bind_methods() {
- ClassDB::bind_method(_MD("init_ref"),&Reference::init_ref);
- ClassDB::bind_method(_MD("reference"),&Reference::reference);
- ClassDB::bind_method(_MD("unreference"),&Reference::unreference);
+ ClassDB::bind_method(D_METHOD("init_ref"),&Reference::init_ref);
+ ClassDB::bind_method(D_METHOD("reference"),&Reference::reference);
+ ClassDB::bind_method(D_METHOD("unreference"),&Reference::unreference);
}
int Reference::reference_get_count() const {
@@ -127,7 +127,7 @@ WeakRef::WeakRef() {
void WeakRef::_bind_methods() {
- ClassDB::bind_method(_MD("get_ref:Object"),&WeakRef::get_ref);
+ ClassDB::bind_method(D_METHOD("get_ref:Object"),&WeakRef::get_ref);
}
#if 0
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index ab94b56cdc..00f6f8662f 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -35,7 +35,7 @@
#include "io/packet_peer.h"
#include "math/a_star.h"
#include "math/triangle_mesh.h"
-#include "globals.h"
+#include "global_config.h"
#include "class_db.h"
#include "geometry.h"
#include "bind/core_bind.h"
diff --git a/core/resource.cpp b/core/resource.cpp
index 9b5bac5f32..fe3cb2df92 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -327,23 +327,23 @@ Node* (*Resource::_get_local_scene_func)()=NULL;
void Resource::_bind_methods() {
- ClassDB::bind_method(_MD("set_path","path"),&Resource::_set_path);
- ClassDB::bind_method(_MD("take_over_path","path"),&Resource::_take_over_path);
- ClassDB::bind_method(_MD("get_path"),&Resource::get_path);
- ClassDB::bind_method(_MD("set_name","name"),&Resource::set_name);
- ClassDB::bind_method(_MD("get_name"),&Resource::get_name);
- ClassDB::bind_method(_MD("get_rid"),&Resource::get_rid);
- ClassDB::bind_method(_MD("set_local_to_scene","enable"),&Resource::set_local_to_scene);
- ClassDB::bind_method(_MD("is_local_to_scene"),&Resource::is_local_to_scene);
- ClassDB::bind_method(_MD("get_local_scene:Node"),&Resource::get_local_scene);
- ClassDB::bind_method(_MD("setup_local_to_scene"),&Resource::setup_local_to_scene);
-
- ClassDB::bind_method(_MD("duplicate","subresources"),&Resource::duplicate,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_path","path"),&Resource::_set_path);
+ ClassDB::bind_method(D_METHOD("take_over_path","path"),&Resource::_take_over_path);
+ ClassDB::bind_method(D_METHOD("get_path"),&Resource::get_path);
+ ClassDB::bind_method(D_METHOD("set_name","name"),&Resource::set_name);
+ ClassDB::bind_method(D_METHOD("get_name"),&Resource::get_name);
+ ClassDB::bind_method(D_METHOD("get_rid"),&Resource::get_rid);
+ ClassDB::bind_method(D_METHOD("set_local_to_scene","enable"),&Resource::set_local_to_scene);
+ ClassDB::bind_method(D_METHOD("is_local_to_scene"),&Resource::is_local_to_scene);
+ ClassDB::bind_method(D_METHOD("get_local_scene:Node"),&Resource::get_local_scene);
+ ClassDB::bind_method(D_METHOD("setup_local_to_scene"),&Resource::setup_local_to_scene);
+
+ ClassDB::bind_method(D_METHOD("duplicate","subresources"),&Resource::duplicate,DEFVAL(false));
ADD_SIGNAL( MethodInfo("changed") );
ADD_GROUP("Resource","resource_");
- ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"resource_local_to_scene" ), _SCS("set_local_to_scene"),_SCS("is_local_to_scene"));
- 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"));
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"resource_local_to_scene" ), "set_local_to_scene","is_local_to_scene");
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"resource_path",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR ), "set_path","get_path");
+ ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"resource_name"), "set_name","get_name");
BIND_VMETHOD( MethodInfo("_setup_local_to_scene") );
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 62d14c4e5a..b14eb51b6c 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -30,7 +30,7 @@
#include "os/os.h"
#include "io/ip.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/input.h"
void ScriptDebuggerRemote::_send_video_memory() {
diff --git a/core/script_language.cpp b/core/script_language.cpp
index 52ae181c32..32db35d018 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -46,13 +46,13 @@ void Script::_notification( int p_what) {
void Script::_bind_methods() {
- ClassDB::bind_method(_MD("can_instance"),&Script::can_instance);
- //ClassDB::bind_method(_MD("instance_create","base_object"),&Script::instance_create);
- ClassDB::bind_method(_MD("instance_has","base_object"),&Script::instance_has);
- ClassDB::bind_method(_MD("has_source_code"),&Script::has_source_code);
- ClassDB::bind_method(_MD("get_source_code"),&Script::get_source_code);
- ClassDB::bind_method(_MD("set_source_code","source"),&Script::set_source_code);
- ClassDB::bind_method(_MD("reload","keep_state"),&Script::reload,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("can_instance"),&Script::can_instance);
+ //ClassDB::bind_method(D_METHOD("instance_create","base_object"),&Script::instance_create);
+ ClassDB::bind_method(D_METHOD("instance_has","base_object"),&Script::instance_has);
+ ClassDB::bind_method(D_METHOD("has_source_code"),&Script::has_source_code);
+ ClassDB::bind_method(D_METHOD("get_source_code"),&Script::get_source_code);
+ ClassDB::bind_method(D_METHOD("set_source_code","source"),&Script::set_source_code);
+ ClassDB::bind_method(D_METHOD("reload","keep_state"),&Script::reload,DEFVAL(false));
}
diff --git a/core/string_db.h b/core/string_db.h
index a14cdbc7ba..2c5262adaa 100644
--- a/core/string_db.h
+++ b/core/string_db.h
@@ -155,7 +155,4 @@ struct StringNameHasher {
StringName _scs_create(const char *p_chr);
-//#define _SCS(m_cstr) (m_cstr[0]?StringName(StaticCString::create(m_cstr)):StringName())
-#define _SCS(m_cstr) _scs_create(m_cstr)
-
#endif
diff --git a/core/translation.cpp b/core/translation.cpp
index 2fee0e6550..d9d4fe7784 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "translation.h"
-#include "globals.h"
+#include "global_config.h"
#include "io/resource_loader.h"
#include "os/os.h"
@@ -915,18 +915,18 @@ int Translation::get_message_count() const {
void Translation::_bind_methods() {
- ClassDB::bind_method(_MD("set_locale","locale"),&Translation::set_locale);
- ClassDB::bind_method(_MD("get_locale"),&Translation::get_locale);
- ClassDB::bind_method(_MD("add_message","src_message","xlated_message"),&Translation::add_message);
- ClassDB::bind_method(_MD("get_message","src_message"),&Translation::get_message);
- ClassDB::bind_method(_MD("erase_message","src_message"),&Translation::erase_message);
- ClassDB::bind_method(_MD("get_message_list"),&Translation::_get_message_list);
- ClassDB::bind_method(_MD("get_message_count"),&Translation::get_message_count);
- ClassDB::bind_method(_MD("_set_messages"),&Translation::_set_messages);
- ClassDB::bind_method(_MD("_get_messages"),&Translation::_get_messages);
-
- ADD_PROPERTY( PropertyInfo(Variant::POOL_STRING_ARRAY,"messages",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_messages"), _SCS("_get_messages") );
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"locale"), _SCS("set_locale"), _SCS("get_locale") );
+ ClassDB::bind_method(D_METHOD("set_locale","locale"),&Translation::set_locale);
+ ClassDB::bind_method(D_METHOD("get_locale"),&Translation::get_locale);
+ ClassDB::bind_method(D_METHOD("add_message","src_message","xlated_message"),&Translation::add_message);
+ ClassDB::bind_method(D_METHOD("get_message","src_message"),&Translation::get_message);
+ ClassDB::bind_method(D_METHOD("erase_message","src_message"),&Translation::erase_message);
+ ClassDB::bind_method(D_METHOD("get_message_list"),&Translation::_get_message_list);
+ ClassDB::bind_method(D_METHOD("get_message_count"),&Translation::get_message_count);
+ ClassDB::bind_method(D_METHOD("_set_messages"),&Translation::_set_messages);
+ ClassDB::bind_method(D_METHOD("_get_messages"),&Translation::_get_messages);
+
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_STRING_ARRAY,"messages",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_messages", "_get_messages") ;
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"locale"), "set_locale", "get_locale") ;
}
Translation::Translation() {
@@ -1137,15 +1137,15 @@ StringName TranslationServer::tool_translate(const StringName& p_message) const
void TranslationServer::_bind_methods() {
- ClassDB::bind_method(_MD("set_locale","locale"),&TranslationServer::set_locale);
- ClassDB::bind_method(_MD("get_locale"),&TranslationServer::get_locale);
+ ClassDB::bind_method(D_METHOD("set_locale","locale"),&TranslationServer::set_locale);
+ ClassDB::bind_method(D_METHOD("get_locale"),&TranslationServer::get_locale);
- ClassDB::bind_method(_MD("translate","message"),&TranslationServer::translate);
+ ClassDB::bind_method(D_METHOD("translate","message"),&TranslationServer::translate);
- ClassDB::bind_method(_MD("add_translation","translation:Translation"),&TranslationServer::add_translation);
- ClassDB::bind_method(_MD("remove_translation","translation:Translation"),&TranslationServer::remove_translation);
+ ClassDB::bind_method(D_METHOD("add_translation","translation:Translation"),&TranslationServer::add_translation);
+ ClassDB::bind_method(D_METHOD("remove_translation","translation:Translation"),&TranslationServer::remove_translation);
- ClassDB::bind_method(_MD("clear"),&TranslationServer::clear);
+ ClassDB::bind_method(D_METHOD("clear"),&TranslationServer::clear);
}
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 1a0ccc4a7e..f91f1aa14b 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -485,11 +485,11 @@ Variant UndoRedo::_add_undo_method(const Variant** p_args, int p_argcount, Varia
void UndoRedo::_bind_methods() {
- ClassDB::bind_method(_MD("create_action","name","merge_mode"),&UndoRedo::create_action, DEFVAL(MERGE_DISABLE) );
- ClassDB::bind_method(_MD("commit_action"),&UndoRedo::commit_action);
+ ClassDB::bind_method(D_METHOD("create_action","name","merge_mode"),&UndoRedo::create_action, DEFVAL(MERGE_DISABLE) );
+ ClassDB::bind_method(D_METHOD("commit_action"),&UndoRedo::commit_action);
- //ClassDB::bind_method(_MD("add_do_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_do_method);
- //ClassDB::bind_method(_MD("add_undo_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_undo_method);
+ //ClassDB::bind_method(D_METHOD("add_do_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_do_method);
+ //ClassDB::bind_method(D_METHOD("add_undo_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_undo_method);
{
MethodInfo mi;
@@ -511,13 +511,13 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi);
}
- ClassDB::bind_method(_MD("add_do_property","object", "property", "value:Variant"),&UndoRedo::add_do_property);
- ClassDB::bind_method(_MD("add_undo_property","object", "property", "value:Variant"),&UndoRedo::add_undo_property);
- ClassDB::bind_method(_MD("add_do_reference","object"),&UndoRedo::add_do_reference);
- ClassDB::bind_method(_MD("add_undo_reference","object"),&UndoRedo::add_undo_reference);
- ClassDB::bind_method(_MD("clear_history"),&UndoRedo::clear_history);
- ClassDB::bind_method(_MD("get_current_action_name"),&UndoRedo::get_current_action_name);
- ClassDB::bind_method(_MD("get_version"),&UndoRedo::get_version);
+ ClassDB::bind_method(D_METHOD("add_do_property","object", "property", "value:Variant"),&UndoRedo::add_do_property);
+ ClassDB::bind_method(D_METHOD("add_undo_property","object", "property", "value:Variant"),&UndoRedo::add_undo_property);
+ ClassDB::bind_method(D_METHOD("add_do_reference","object"),&UndoRedo::add_do_reference);
+ ClassDB::bind_method(D_METHOD("add_undo_reference","object"),&UndoRedo::add_undo_reference);
+ ClassDB::bind_method(D_METHOD("clear_history"),&UndoRedo::clear_history);
+ ClassDB::bind_method(D_METHOD("get_current_action_name"),&UndoRedo::get_current_action_name);
+ ClassDB::bind_method(D_METHOD("get_version"),&UndoRedo::get_version);
BIND_CONSTANT(MERGE_DISABLE);
BIND_CONSTANT(MERGE_ENDS);
diff --git a/core/ustring.cpp b/core/ustring.cpp
index a0d26ea0af..7d88989d04 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -52,8 +52,40 @@
#define UPPERCASE(m_c) (((m_c)>='a' && (m_c)<='z')?((m_c)-('a'-'A')):(m_c))
#define LOWERCASE(m_c) (((m_c)>='A' && (m_c)<='Z')?((m_c)+('a'-'A')):(m_c))
+
+
+
/** STRING **/
+bool CharString::operator<(const CharString& p_right) const {
+
+ if (length()==0) {
+ return p_right.length()!=0;
+ }
+
+
+ const char *this_str=get_data();
+ const char *that_str=get_data();
+ while (true) {
+
+ if (*that_str==0 && *this_str==0)
+ return false; //this can't be equal, sadly
+ else if (*this_str==0)
+ return true; //if this is empty, and the other one is not, then we're less.. I think?
+ else if (*that_str==0)
+ return false; //otherwise the other one is smaller..
+ else if (*this_str < *that_str ) //more than
+ return true;
+ else if (*this_str > *that_str ) //less than
+ return false;
+
+ this_str++;
+ that_str++;
+ }
+
+ return false; //should never reach here anyway
+}
+
const char *CharString::get_data() const {
if (size())
@@ -4069,12 +4101,8 @@ String String::sprintf(const Array& values, bool* error) const {
case 'X': base = 16; capitalize = true; break;
}
// Get basic number.
- String str = String::num_int64(value, base, capitalize);
-
- // Sign.
- if (show_sign && value >= 0) {
- str = str.insert(0, "+");
- }
+ String str = String::num_int64(ABS(value), base, capitalize);
+ int number_len = str.length();
// Padding.
String pad_char = pad_with_zeroes ? String("0") : String(" ");
@@ -4084,6 +4112,13 @@ String String::sprintf(const Array& values, bool* error) const {
str = str.lpad(min_chars, pad_char);
}
+ // Sign.
+ if (show_sign && value >= 0) {
+ str = str.insert(pad_with_zeroes?0:str.length()-number_len, "+");
+ } else if (value < 0) {
+ str = str.insert(pad_with_zeroes?0:str.length()-number_len, "-");
+ }
+
formatted += str;
++value_index;
in_format = false;
diff --git a/core/ustring.h b/core/ustring.h
index 5665a23112..87289f9e16 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -41,6 +41,8 @@
class CharString : public Vector<char> {
public:
+
+ bool operator<(const CharString& p_right) const;
int length() const { return size() ? size()-1 : 0; }
const char *get_data() const;
operator const char*() {return get_data();};
diff --git a/core/variant.cpp b/core/variant.cpp
index 103c8f6746..f19dacf26b 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -28,6 +28,7 @@
/*************************************************************************/
#include "variant.h"
+#include "math_funcs.h"
#include "resource.h"
#include "print_string.h"
#include "scene/main/node.h"
@@ -2177,6 +2178,11 @@ Variant::operator IP_Address() const {
return IP_Address( operator String() );
}
+Variant::operator PowerState() const
+{
+ return (PowerState) operator int();
+}
+
Variant::Variant(bool p_bool) {
type=BOOL;
@@ -2674,14 +2680,10 @@ uint32_t Variant::hash() const {
case INT: {
return _data._int;
-
} break;
case REAL: {
- MarshallFloat mf;
- mf.f=_data._real;
- return mf.i;
-
+ return hash_djb2_one_float(_data._real);
} break;
case STRING: {
@@ -2921,6 +2923,186 @@ uint32_t Variant::hash() const {
}
+#define hash_compare_scalar(p_lhs, p_rhs)\
+ ((p_lhs) == (p_rhs)) || (Math::is_nan(p_lhs) == Math::is_nan(p_rhs))
+
+#define hash_compare_vector2(p_lhs, p_rhs)\
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
+ (hash_compare_scalar((p_lhs).y, (p_rhs).y))
+
+#define hash_compare_vector3(p_lhs, p_rhs)\
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
+ (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
+ (hash_compare_scalar((p_lhs).z, (p_rhs).z))
+
+#define hash_compare_quat(p_lhs, p_rhs)\
+ (hash_compare_scalar((p_lhs).x, (p_rhs).x)) && \
+ (hash_compare_scalar((p_lhs).y, (p_rhs).y)) && \
+ (hash_compare_scalar((p_lhs).z, (p_rhs).z)) && \
+ (hash_compare_scalar((p_lhs).w, (p_rhs).w))
+
+#define hash_compare_color(p_lhs, p_rhs)\
+ (hash_compare_scalar((p_lhs).r, (p_rhs).r)) && \
+ (hash_compare_scalar((p_lhs).g, (p_rhs).g)) && \
+ (hash_compare_scalar((p_lhs).b, (p_rhs).b)) && \
+ (hash_compare_scalar((p_lhs).a, (p_rhs).a))
+
+#define hash_compare_pool_array(p_lhs, p_rhs, p_type, p_compare_func)\
+ const PoolVector<p_type>& l = *reinterpret_cast<const PoolVector<p_type>*>(p_lhs);\
+ const PoolVector<p_type>& r = *reinterpret_cast<const PoolVector<p_type>*>(p_rhs);\
+ \
+ if(l.size() != r.size()) \
+ return false; \
+ \
+ PoolVector<p_type>::Read lr = l.read(); \
+ PoolVector<p_type>::Read rr = r.read(); \
+ \
+ for(int i = 0; i < l.size(); ++i) { \
+ if(! p_compare_func((lr[i]), (rr[i]))) \
+ return false; \
+ }\
+ \
+ return true
+
+bool Variant::hash_compare(const Variant& p_variant) const {
+ if (type != p_variant.type)
+ return false;
+
+ switch( type ) {
+ case REAL: {
+ return hash_compare_scalar(_data._real, p_variant._data._real);
+ } break;
+
+ case VECTOR2: {
+ const Vector2* l = reinterpret_cast<const Vector2*>(_data._mem);
+ const Vector2* r = reinterpret_cast<const Vector2*>(p_variant._data._mem);
+
+ return hash_compare_vector2(*l, *r);
+ } break;
+
+ case RECT2: {
+ const Rect2* l = reinterpret_cast<const Rect2*>(_data._mem);
+ const Rect2* r = reinterpret_cast<const Rect2*>(p_variant._data._mem);
+
+ return (hash_compare_vector2(l->pos, r->pos)) &&
+ (hash_compare_vector2(l->size, r->size));
+ } break;
+
+ case TRANSFORM2D: {
+ Transform2D* l = _data._transform2d;
+ Transform2D* r = p_variant._data._transform2d;
+
+ for(int i=0;i<3;i++) {
+ if (! (hash_compare_vector2(l->elements[i], r->elements[i])))
+ return false;
+ }
+
+ return true;
+ } break;
+
+ case VECTOR3: {
+ const Vector3* l = reinterpret_cast<const Vector3*>(_data._mem);
+ const Vector3* r = reinterpret_cast<const Vector3*>(p_variant._data._mem);
+
+ return hash_compare_vector3(*l, *r);
+ } break;
+
+ case PLANE: {
+ const Plane* l = reinterpret_cast<const Plane*>(_data._mem);
+ const Plane* r = reinterpret_cast<const Plane*>(p_variant._data._mem);
+
+ return (hash_compare_vector3(l->normal, r->normal)) &&
+ (hash_compare_scalar(l->d, r->d));
+ } break;
+
+ case RECT3: {
+ const Rect3* l = _data._rect3;
+ const Rect3* r = p_variant._data._rect3;
+
+ return (hash_compare_vector3(l->pos, r->pos) &&
+ (hash_compare_vector3(l->size, r->size)));
+
+ } break;
+
+ case QUAT: {
+ const Quat* l = reinterpret_cast<const Quat*>(_data._mem);
+ const Quat* r = reinterpret_cast<const Quat*>(p_variant._data._mem);
+
+ return hash_compare_quat(*l, *r);
+ } break;
+
+ case BASIS: {
+ const Basis* l = _data._basis;
+ const Basis* r = p_variant._data._basis;
+
+ for(int i=0;i<3;i++) {
+ if (! (hash_compare_vector3(l->elements[i], r->elements[i])))
+ return false;
+ }
+
+ return true;
+ } break;
+
+ case TRANSFORM: {
+ const Transform* l = _data._transform;
+ const Transform* r = p_variant._data._transform;
+
+ for(int i=0;i<3;i++) {
+ if (! (hash_compare_vector3(l->basis.elements[i], r->basis.elements[i])))
+ return false;
+ }
+
+ return hash_compare_vector3(l->origin, r->origin);
+ } break;
+
+ case COLOR: {
+ const Color* l = reinterpret_cast<const Color*>(_data._mem);
+ const Color* r = reinterpret_cast<const Color*>(p_variant._data._mem);
+
+ return hash_compare_color(*l, *r);
+ } break;
+
+ case ARRAY: {
+ const Array& l = *(reinterpret_cast<const Array*>(_data._mem));
+ const Array& r = *(reinterpret_cast<const Array*>(p_variant._data._mem));
+
+ if(l.size() != r.size())
+ return false;
+
+ for(int i = 0; i < l.size(); ++i) {
+ if(! l[i].hash_compare(r[i]))
+ return false;
+ }
+
+ return true;
+ } break;
+
+ case POOL_REAL_ARRAY: {
+ hash_compare_pool_array(_data._mem, p_variant._data._mem, real_t, hash_compare_scalar);
+ } break;
+
+ case POOL_VECTOR2_ARRAY: {
+ hash_compare_pool_array(_data._mem, p_variant._data._mem, Vector2, hash_compare_vector2);
+ } break;
+
+ case POOL_VECTOR3_ARRAY: {
+ hash_compare_pool_array(_data._mem, p_variant._data._mem, Vector3, hash_compare_vector3);
+ } break;
+
+ case POOL_COLOR_ARRAY: {
+ hash_compare_pool_array(_data._mem, p_variant._data._mem, Color, hash_compare_color);
+ } break;
+
+ default:
+ bool v;
+ Variant r;
+ evaluate(OP_EQUAL,*this,p_variant,r,v);
+ return r;
+ }
+
+ return false;
+}
+
bool Variant::is_ref() const {
diff --git a/core/variant.h b/core/variant.h
index 5936325c1b..1251189314 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -45,6 +45,7 @@
#include "path_db.h"
#include "simple_type.h"
#include "os/input_event.h"
+#include "os/power.h"
#include "color.h"
#include "face3.h"
#include "ref_ptr.h"
@@ -254,6 +255,7 @@ public:
operator Orientation() const;
operator IP_Address() const;
+ operator PowerState() const;
Variant(bool p_bool);
@@ -421,6 +423,7 @@ public:
bool operator<(const Variant& p_variant) const;
uint32_t hash() const;
+ bool hash_compare(const Variant& p_variant) const;
bool booleanize(bool &valid) const;
void static_assign(const Variant& p_variant);
@@ -459,6 +462,10 @@ struct VariantHasher {
static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); }
};
+struct VariantComparator {
+
+ static _FORCE_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) { return p_lhs.hash_compare(p_rhs); }
+};
Variant::ObjData& Variant::_get_obj() {
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 022faede1e..376e646fc2 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -564,6 +564,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM1(PoolStringArray,append);
VCALL_LOCALMEM1(PoolStringArray,append_array);
VCALL_LOCALMEM0(PoolStringArray,invert);
+ VCALL_LOCALMEM1R(PoolStringArray,join);
VCALL_LOCALMEM0R(PoolVector2Array,size);
VCALL_LOCALMEM2(PoolVector2Array,set);
@@ -1362,15 +1363,15 @@ void register_variant_methods() {
_VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX);
#define ADDFUNC0(m_vtype,m_ret,m_class,m_method,m_defarg)\
-_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_class,m_method),m_defarg);
+_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_scs_create(#m_method),VCALL(m_class,m_method),m_defarg);
#define ADDFUNC1(m_vtype,m_ret,m_class,m_method,m_arg1,m_argname1,m_defarg)\
-_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_SCS(m_argname1)) );
+_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_scs_create(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_scs_create(m_argname1)) );
#define ADDFUNC2(m_vtype,m_ret,m_class,m_method,m_arg1,m_argname1,m_arg2,m_argname2,m_defarg)\
-_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_SCS(m_argname1)),_VariantCall::Arg(Variant::m_arg2,_SCS(m_argname2)));
+_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_scs_create(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_scs_create(m_argname1)),_VariantCall::Arg(Variant::m_arg2,_scs_create(m_argname2)));
#define ADDFUNC3(m_vtype,m_ret,m_class,m_method,m_arg1,m_argname1,m_arg2,m_argname2,m_arg3,m_argname3,m_defarg)\
-_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_SCS(m_argname1)),_VariantCall::Arg(Variant::m_arg2,_SCS(m_argname2)),_VariantCall::Arg(Variant::m_arg3,_SCS(m_argname3)));
+_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_scs_create(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_scs_create(m_argname1)),_VariantCall::Arg(Variant::m_arg2,_scs_create(m_argname2)),_VariantCall::Arg(Variant::m_arg3,_scs_create(m_argname3)));
#define ADDFUNC4(m_vtype,m_ret,m_class,m_method,m_arg1,m_argname1,m_arg2,m_argname2,m_arg3,m_argname3,m_arg4,m_argname4,m_defarg)\
-_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_SCS(m_argname1)),_VariantCall::Arg(Variant::m_arg2,_SCS(m_argname2)),_VariantCall::Arg(Variant::m_arg3,_SCS(m_argname3)),_VariantCall::Arg(Variant::m_arg4,_SCS(m_argname4)));
+_VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_scs_create(#m_method),VCALL(m_class,m_method),m_defarg,_VariantCall::Arg(Variant::m_arg1,_scs_create(m_argname1)),_VariantCall::Arg(Variant::m_arg2,_scs_create(m_argname2)),_VariantCall::Arg(Variant::m_arg3,_scs_create(m_argname3)),_VariantCall::Arg(Variant::m_arg4,_scs_create(m_argname4)));
/* STRING */
@@ -1637,6 +1638,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC2(POOL_STRING_ARRAY,INT,PoolStringArray,insert,INT,"idx",STRING,"string",varray());
ADDFUNC1(POOL_STRING_ARRAY,NIL,PoolStringArray,resize,INT,"idx",varray());
ADDFUNC0(POOL_STRING_ARRAY,NIL,PoolStringArray,invert,varray());
+ ADDFUNC1(POOL_STRING_ARRAY,STRING,PoolStringArray,join,STRING,"string",varray());
ADDFUNC0(POOL_VECTOR2_ARRAY,INT,PoolVector2Array,size,varray());
ADDFUNC2(POOL_VECTOR2_ARRAY,NIL,PoolVector2Array,set,INT,"idx",VECTOR2,"vector2",varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 6ed8a3dd85..28e804b5bf 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -1393,7 +1393,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid)
v->basis.set_axis(index,p_value);
return;
}
- } if (p_index.get_type()==Variant::STRING) {
+ } else if (p_index.get_type()==Variant::STRING) {
Transform *v=_data._transform;
const String *str=reinterpret_cast<const String*>(p_index._data._mem);
@@ -2150,7 +2150,7 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
valid=true;
return index==3?v->origin:v->basis.get_axis(index);
}
- } if (p_index.get_type()==Variant::STRING) {
+ } else if (p_index.get_type()==Variant::STRING) {
const Transform *v=_data._transform;
const String *str=reinterpret_cast<const String*>(p_index._data._mem);
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 3507501f27..a2ecb1516d 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1414,7 +1414,7 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
return OK;
} else if (id=="img") { // compatibility with godot.cfg
- Token token;
+ Token token; // FIXME: no need for this declaration? the first argument in line 509 is a Token& token.
get_token(p_stream,token,line,r_err_str);
if (token.type!=TK_PARENTHESIS_OPEN) {
r_err_str="Expected '(' in old-style godot.cfg construct";
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 8204af9fd4..71594887fc 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -25394,10 +25394,15 @@
</return>
<argument index="0" name="port" type="int">
</argument>
- <argument index="1" name="recv_buf_size" type="int" default="65536">
+ <argument index="1" name="bind_address" type="String" default="*">
+ </argument>
+ <argument index="2" name="recv_buf_size" type="int" default="65536">
</argument>
<description>
- Make this [PacketPeerUDP] listen on the "port" with a buffer size "recv_buf_size". Listens on all available addresses.
+ Make this [PacketPeerUDP] listen on the "port" binding to "bind_address" with a buffer size "recv_buf_size".
+ If "bind_address" is set as "*" (default), the peer will listen on all available addresses (both IPv4 and IPv6).
+ If "bind_address" is set as "0.0.0.0" (for IPv4) or "::" (for IPv6), the peer will listen on all available addresses matching that IP type.
+ If "bind_address" is set to any valid address (e.g. "192.168.1.101", "::1", etc), the peer will only listen on the interface with that addresses (or fail if no interface with the given address exists).
</description>
</method>
<method name="set_send_address">
@@ -35446,6 +35451,13 @@
Returns true if this SceneTree's [NetworkedMultiplayerPeer] is in server mode (listening for connections).
</description>
</method>
+ <method name="has_network_peer" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ Returns true if there is a [NetworkedMultiplayerPeer] set (with [method SceneTree.set_network_peer]).
+ </description>
+ </method>
<method name="is_paused" qualifiers="const">
<return type="bool">
</return>
@@ -40576,10 +40588,13 @@
</return>
<argument index="0" name="port" type="int">
</argument>
- <argument index="1" name="accepted_hosts" type="StringArray" default="StringArray([])">
+ <argument index="1" name="bind_address" type="String" default="*">
</argument>
<description>
- Listen on a port using protocol, alternatively give a white-list of accepted hosts.
+ Listen on the "port" binding to "bind_address".
+ If "bind_address" is set as "*" (default), the server will listen on all available addresses (both IPv4 and IPv6).
+ If "bind_address" is set as "0.0.0.0" (for IPv4) or "::" (for IPv6), the server will listen on all available addresses matching that IP type.
+ If "bind_address" is set to any valid address (e.g. "192.168.1.101", "::1", etc), the server will only listen on the interface with that addresses (or fail if no interface with the given address exists).
</description>
</method>
<method name="stop">
@@ -40618,9 +40633,16 @@
<return type="int">
</return>
<description>
- Return the current tab that is being showed.
+ Return the current tab index that is being shown.
</description>
</method>
+ <method name="get_previous_tab" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Return the previous tab index that was being shown.
+ </description>
+ </method>
<method name="get_current_tab_control" qualifiers="const">
<return type="Control">
</return>
@@ -40646,6 +40668,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
+ Return the current tab control that is being shown.
</description>
</method>
<method name="get_tab_count" qualifiers="const">
@@ -40727,7 +40750,14 @@
<argument index="0" name="tab" type="int">
</argument>
<description>
- Emitted when the current tab changes.
+ Emitted only when the current tab changes.
+ </description>
+ </signal>
+ <signal name="tab_selected">
+ <argument index="0" name="tab" type="int">
+ </argument>
+ <description>
+ Emitted when a tab is being selected, even if it is the same tab.
</description>
</signal>
</signals>
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 8984d412a3..f2616b11b8 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -30,7 +30,7 @@
#ifdef ALSA_ENABLED
-#include "globals.h"
+#include "global_config.h"
#include <errno.h>
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 1486e85a04..94c5ecdec1 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -30,7 +30,7 @@
#include "rasterizer_gles2.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include <stdio.h>
#include "servers/visual/shader_language.h"
#include "servers/visual/particle_system_sw.h"
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index 509f9a82b4..004d636c1e 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -134,7 +134,7 @@ private:
struct VersionKeyHash {
- static _FORCE_INLINE_ uint32_t hash( const VersionKey& p_key) { return HashMapHahserDefault::hash(p_key.key); };
+ static _FORCE_INLINE_ uint32_t hash( const VersionKey& p_key) { return HashMapHasherDefault::hash(p_key.key); };
};
//this should use a way more cachefriendly version..
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 2923dfff9f..2526aad074 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* rasterizer_canvas_gles3.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "rasterizer_canvas_gles3.h"
+
#include "os/os.h"
#ifndef GLES_OVER_GL
@@ -382,7 +411,7 @@ void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_v
}
- float b[(2+2+4)];
+ float b[(2+2+4)*4];
for(int i=0;i<p_points;i++) {
@@ -646,7 +675,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr
state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size);
}
- _draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
+ //_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
} break;
case Item::Command::TYPE_CIRCLE: {
@@ -666,7 +695,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr
indices[i*3+1]=(i+1)%numpoints;
indices[i*3+2]=numpoints;
}
- _draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true);
+ //_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true);
//canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1);
} break;
case Item::Command::TYPE_TRANSFORM: {
@@ -1010,7 +1039,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
if (unshaded || (state.canvas_item_modulate.a>0.001 && (!shader_cache || shader_cache->canvas_item.light_mode!=RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked ))
_canvas_item_render_commands(ci,current_clip,reclip);
- if ((blend_mode==RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) {
+ if ((blend_mode==RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || blend_mode==RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) {
Light *light = p_light;
bool light_used=false;
@@ -1459,7 +1488,7 @@ void RasterizerCanvasGLES3::initialize() {
glGenBuffers(1,&data.primitive_quad_buffer);
glBindBuffer(GL_ARRAY_BUFFER,data.primitive_quad_buffer);
- glBufferData(GL_ARRAY_BUFFER,sizeof(float)*2+sizeof(float)*2+sizeof(float)*4,NULL,GL_DYNAMIC_DRAW); //allocate max size
+ glBufferData(GL_ARRAY_BUFFER,(2+2+4)*4*sizeof(float),NULL,GL_DYNAMIC_DRAW); //allocate max size
glBindBuffer(GL_ARRAY_BUFFER,0);
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 6630ec38c4..1273e5f35d 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* rasterizer_canvas_gles3.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RASTERIZERCANVASGLES3_H
#define RASTERIZERCANVASGLES3_H
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index e1ddad0dc9..05558a39ba 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -1,6 +1,35 @@
+/*************************************************************************/
+/* rasterizer_gles3.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "rasterizer_gles3.h"
+
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include "gl_context/context_gl.h"
#include <string.h>
RasterizerStorage *RasterizerGLES3::get_storage() {
@@ -167,7 +196,6 @@ void RasterizerGLES3::initialize() {
void RasterizerGLES3::begin_frame(){
-
uint64_t tick = OS::get_singleton()->get_ticks_usec();
double time_total = double(tick)/1000000.0;
@@ -186,12 +214,8 @@ void RasterizerGLES3::begin_frame(){
storage->frame.prev_tick=tick;
+ storage->update_dirty_resources();
- storage->update_dirty_multimeshes();
- storage->update_dirty_skeletons();
- storage->update_dirty_shaders();
- storage->update_dirty_materials();
- storage->update_particles();
storage->info.render_object_count=0;
storage->info.render_material_switch_count=0;
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index f70dac506d..21e16b3bba 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* rasterizer_gles3.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RASTERIZERGLES3_H
#define RASTERIZERGLES3_H
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index b504ef819f..f09e6ce904 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1,5 +1,34 @@
+/*************************************************************************/
+/* rasterizer_storage_gles3.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "rasterizer_scene_gles3.h"
-#include "globals.h"
+
+#include "global_config.h"
#include "os/os.h"
#include "rasterizer_canvas_gles3.h"
@@ -133,7 +162,7 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &shadow_atlas->depth);
glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadow_atlas->size, shadow_atlas->size, 0,
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadow_atlas->size, shadow_atlas->size, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -1386,6 +1415,8 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
int amount = MAX(multi_mesh->size,multi_mesh->visible_instances);
+
+
if (s->index_array_len>0) {
glDrawElementsInstanced(gl_primitive[s->primitive],s->index_array_len, (s->array_len>=(1<<16))?GL_UNSIGNED_INT:GL_UNSIGNED_SHORT,0,amount);
@@ -1609,6 +1640,7 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform&
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER1, gipi->probe?gipi->probe->dynamic_range*gipi->probe->energy:0.0);
+ state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS1, gipi->probe?gipi->probe->bias:0.0);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT1, gipi->probe?!gipi->probe->interior:false);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache);
if (gi_probe_count>1) {
@@ -1621,6 +1653,7 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform&
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_MULTIPLIER2, gipi2->probe?gipi2->probe->dynamic_range*gipi2->probe->energy:0.0);
+ state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BIAS2, gipi2->probe?gipi2->probe->bias:0.0);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT2, gipi2->probe?!gipi2->probe->interior:false);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true );
} else {
@@ -1746,6 +1779,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
RasterizerStorageGLES3::Material* prev_material=NULL;
RasterizerStorageGLES3::Geometry* prev_geometry=NULL;
+ RasterizerStorageGLES3::GeometryOwner* prev_owner=NULL;
VS::InstanceType prev_base_type = VS::INSTANCE_MAX;
int current_blend_mode=-1;
@@ -1765,6 +1799,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
RasterizerStorageGLES3::Material* material= e->material;
RID skeleton = e->instance->skeleton;
+
bool rebind=first;
int shading = (e->sort_key>>RenderList::SORT_KEY_SHADING_SHIFT)&RenderList::SORT_KEY_SHADING_MASK;
@@ -1934,7 +1969,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
}
- if (prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) {
+ if (e->owner != prev_owner || prev_base_type != e->instance->base_type || prev_geometry!=e->geometry) {
+
_setup_geometry(e);
storage->info.render_surface_switch_count++;
@@ -1952,6 +1988,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
prev_material=material;
prev_base_type=e->instance->base_type;
prev_geometry=e->geometry;
+ prev_owner=e->owner;
prev_shading=shading;
prev_skeleton=skeleton;
first=false;
@@ -2654,19 +2691,19 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result,int p_light_cu
glBindBuffer(GL_UNIFORM_BUFFER, state.omni_array_ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0, state.omni_light_count*state.ubo_light_size, state.omni_array_tmp);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
-
- glBindBufferBase(GL_UNIFORM_BUFFER,4,state.omni_array_ubo);
}
+ glBindBufferBase(GL_UNIFORM_BUFFER,4,state.omni_array_ubo);
+
if (state.spot_light_count) {
glBindBuffer(GL_UNIFORM_BUFFER, state.spot_array_ubo);
glBufferSubData(GL_UNIFORM_BUFFER, 0, state.spot_light_count*state.ubo_light_size, state.spot_array_tmp);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
- glBindBufferBase(GL_UNIFORM_BUFFER,5,state.spot_array_ubo);
}
+ glBindBufferBase(GL_UNIFORM_BUFFER,5,state.spot_array_ubo);
}
@@ -2762,9 +2799,10 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul
glBufferSubData(GL_UNIFORM_BUFFER, 0, state.reflection_probe_count*sizeof(ReflectionProbeDataUBO), state.reflection_array_tmp);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
- glBindBufferBase(GL_UNIFORM_BUFFER,6,state.reflection_array_ubo);
}
+ glBindBufferBase(GL_UNIFORM_BUFFER,6,state.reflection_array_ubo);
+
}
@@ -2797,6 +2835,7 @@ void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
//no environment, simply convert from linear to srgb
storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,true);
} else {
+ /* FIXME: Why are both statements equal? */
storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,true);
}
@@ -2877,6 +2916,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_
RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getptr(inst->base);
ERR_CONTINUE(!multi_mesh);
+
if (multi_mesh->size==0 || multi_mesh->visible_instances==0)
continue;
@@ -2892,6 +2932,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_
_add_geometry(s,inst,multi_mesh,-1,p_shadow);
}
+
} break;
case VS::INSTANCE_IMMEDIATE: {
@@ -3773,7 +3814,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
state.used_contact_shadows=true;
- if (storage->frame.current_rt && true) { //detect with state.used_contact_shadows too
+ if ( storage->frame.current_rt && true) { //detect with state.used_contact_shadows too
//pre z pass
@@ -4092,11 +4133,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
if (false && env_radiance_tex) {
- //_copy_texture_to_front_buffer(shadow_atlas->depth);
- storage->canvas->canvas_begin();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D,env_radiance_tex);
- storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/2,storage->frame.current_rt->height/2),Rect2(0,0,1,1));
+ //_copy_texture_to_front_buffer(shadow_atlas->depth);
+ storage->canvas->canvas_begin();
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D,env_radiance_tex);
+ storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/2,storage->frame.current_rt->height/2),Rect2(0,0,1,1));
}
@@ -4794,7 +4835,7 @@ void RasterizerSceneGLES3::initialize() {
//gen cubemap first
for(int i=0;i<6;i++) {
- glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ glTexImage2D(_cube_side_enum[i], 0, GL_DEPTH_COMPONENT24, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -4828,7 +4869,7 @@ void RasterizerSceneGLES3::initialize() {
glBindFramebuffer(GL_FRAMEBUFFER,directional_shadow.fbo);
glGenTextures(1,&directional_shadow.depth);
glBindTexture(GL_TEXTURE_2D,directional_shadow.depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -4918,7 +4959,7 @@ void RasterizerSceneGLES3::initialize() {
glGenTextures(1,&cube.depth);
glBindTexture(GL_TEXTURE_2D,cube.depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, cube.size, cube.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index 81dfa1bf46..b21ef8317f 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* rasterizer_scene_gles3.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RASTERIZERSCENEGLES3_H
#define RASTERIZERSCENEGLES3_H
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 06daebbf82..4fea28ddb7 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1,7 +1,35 @@
+/*************************************************************************/
+/* rasterizer_storage_gles3.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "rasterizer_storage_gles3.h"
#include "rasterizer_canvas_gles3.h"
#include "rasterizer_scene_gles3.h"
-#include "globals.h"
+#include "global_config.h"
/* TEXTURE API */
@@ -93,16 +121,26 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image& p_image, Ima
switch(p_format) {
case Image::FORMAT_L8: {
+#ifdef GLES_OVER_GL
r_gl_internal_format=GL_R8;
r_gl_format=GL_RED;
r_gl_type=GL_UNSIGNED_BYTE;
-
+#else
+ r_gl_internal_format=GL_LUMINANCE;
+ r_gl_format=GL_LUMINANCE;
+ r_gl_type=GL_UNSIGNED_BYTE;
+#endif
} break;
case Image::FORMAT_LA8: {
-
+#ifdef GLES_OVER_GL
r_gl_internal_format=GL_RG8;
r_gl_format=GL_RG;
r_gl_type=GL_UNSIGNED_BYTE;
+#else
+ r_gl_internal_format=GL_LUMINANCE_ALPHA;
+ r_gl_format=GL_LUMINANCE_ALPHA;
+ r_gl_type=GL_UNSIGNED_BYTE;
+#endif
} break;
case Image::FORMAT_R8: {
@@ -734,6 +772,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image
}
//set swizle for older format compatibility
+#ifdef GLES_OVER_GL
switch(texture->format) {
case Image::FORMAT_L8: {
@@ -759,6 +798,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture,const Image& p_image
} break;
}
+#endif
if (config.use_anisotropic_filter) {
if (texture->flags&VS::TEXTURE_FLAG_ANISOTROPIC_FILTER) {
@@ -1096,7 +1136,7 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source,int p_r
ERR_FAIL_COND_V(!texture,RID());
ERR_FAIL_COND_V(!(texture->flags&VS::TEXTURE_FLAG_CUBEMAP),RID());
- bool use_float=true;
+ bool use_float=config.hdr_supported;
if (p_resolution<0) {
p_resolution=texture->width;
@@ -1316,7 +1356,7 @@ void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, in
int mm_level=mipmaps;
- bool use_float=true;
+ bool use_float=config.hdr_supported;
GLenum internal_format = use_float?GL_RGBA16F:GL_RGB10_A2;
GLenum format = GL_RGBA;
@@ -2320,6 +2360,7 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
bool is_animated = false;
if (material->shader && material->shader->mode==VS::SHADER_SPATIAL) {
+
if (!material->shader->spatial.uses_alpha && material->shader->spatial.blend_mode==Shader::Spatial::BLEND_MODE_MIX) {
can_cast_shadow=true;
}
@@ -2332,20 +2373,19 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
is_animated=true;
}
- }
+ if (can_cast_shadow!=material->can_cast_shadow_cache || is_animated!=material->is_animated_cache) {
+ material->can_cast_shadow_cache=can_cast_shadow;
+ material->is_animated_cache=is_animated;
- if (can_cast_shadow!=material->can_cast_shadow_cache || is_animated!=material->is_animated_cache) {
- material->can_cast_shadow_cache=can_cast_shadow;
- material->is_animated_cache=is_animated;
+ for(Map<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) {
+ E->key()->material_changed_notify();
+ }
- for(Map<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) {
- E->key()->material_changed_notify();
- }
+ for(Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) {
+ E->key()->base_material_changed();
+ }
- for(Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) {
- E->key()->base_material_changed();
}
-
}
}
@@ -3619,8 +3659,23 @@ void RasterizerStorageGLES3::multimesh_set_mesh(RID p_multimesh,RID p_mesh){
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
+ if (multimesh->mesh.is_valid()) {
+ Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
+ if (mesh) {
+ mesh->multimeshes.remove(&multimesh->mesh_list);
+ }
+ }
+
multimesh->mesh=p_mesh;
+
+ if (multimesh->mesh.is_valid()) {
+ Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
+ if (mesh) {
+ mesh->multimeshes.add(&multimesh->mesh_list);
+ }
+ }
+
multimesh->dirty_aabb=true;
if (!multimesh->update_list.in_list()) {
@@ -4778,6 +4833,7 @@ RID RasterizerStorageGLES3::gi_probe_create() {
gip->dynamic_range=1.0;
gip->energy=1.0;
gip->propagation=1.0;
+ gip->bias=0.4;
gip->interior=false;
gip->compress=false;
gip->version=1;
@@ -4883,6 +4939,16 @@ void RasterizerStorageGLES3::gi_probe_set_energy(RID p_probe,float p_range){
}
+
+void RasterizerStorageGLES3::gi_probe_set_bias(RID p_probe,float p_range){
+
+ GIProbe *gip = gi_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!gip);
+
+ gip->bias=p_range;
+
+}
+
void RasterizerStorageGLES3::gi_probe_set_propagation(RID p_probe,float p_range){
GIProbe *gip = gi_probe_owner.getornull(p_probe);
@@ -4936,6 +5002,15 @@ float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const{
return gip->energy;
}
+float RasterizerStorageGLES3::gi_probe_get_bias(RID p_probe) const{
+
+ const GIProbe *gip = gi_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!gip,0);
+
+ return gip->bias;
+}
+
+
float RasterizerStorageGLES3::gi_probe_get_propagation(RID p_probe) const{
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
@@ -5535,9 +5610,10 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
GLuint color_type;
Image::Format image_format;
+ bool hdr = rt->flags[RENDER_TARGET_HDR] && config.hdr_supported;
+ hdr=false;
-
- if (!rt->flags[RENDER_TARGET_HDR] || rt->flags[RENDER_TARGET_NO_3D]) {
+ if (!hdr || rt->flags[RENDER_TARGET_NO_3D]) {
color_internal_format=GL_RGBA8;
color_format=GL_RGBA;
@@ -5562,7 +5638,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
glGenTextures(1, &rt->depth);
glBindTexture(GL_TEXTURE_2D, rt->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->width, rt->height, 0,
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->width, rt->height, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -5586,6 +5662,10 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ printf("framebuffer fail, status: %x\n",status);
+ }
+
ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
Texture *tex = texture_owner.get(rt->texture);
@@ -5633,7 +5713,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
if (msaa==0)
glRenderbufferStorage(GL_RENDERBUFFER,color_internal_format,rt->width,rt->height);
else
- glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_RGBA16F,rt->width,rt->height);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,color_internal_format,rt->width,rt->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,rt->buffers.diffuse);
@@ -5641,7 +5721,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.specular);
if (msaa==0)
- glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA16F,rt->width,rt->height);
+ glRenderbufferStorage(GL_RENDERBUFFER,color_internal_format,rt->width,rt->height);
else
glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,color_internal_format,rt->width,rt->height);
@@ -6265,6 +6345,18 @@ bool RasterizerStorageGLES3::free(RID p_rid){
mesh->instance_remove_deps();
mesh_clear(p_rid);
+ while(mesh->multimeshes.first()) {
+ MultiMesh *multimesh = mesh->multimeshes.first()->self();
+ multimesh->mesh=RID();
+ multimesh->dirty_aabb=true;
+ mesh->multimeshes.remove(mesh->multimeshes.first());
+
+ if (!multimesh->update_list.in_list()) {
+ multimesh_update_list.add(&multimesh->update_list);
+ }
+
+ }
+
mesh_owner.free(p_rid);
memdelete(mesh);
@@ -6274,9 +6366,17 @@ bool RasterizerStorageGLES3::free(RID p_rid){
MultiMesh *multimesh = multimesh_owner.get(p_rid);
multimesh->instance_remove_deps();
+ if (multimesh->mesh.is_valid()) {
+ Mesh *mesh = mesh_owner.getornull(multimesh->mesh);
+ if (mesh) {
+ mesh->multimeshes.remove(&multimesh->mesh_list);
+ }
+ }
+
multimesh_allocate(p_rid,0,VS::MULTIMESH_TRANSFORM_2D,VS::MULTIMESH_COLOR_NONE); //frees multimesh
update_dirty_multimeshes();
+
multimesh_owner.free(p_rid);
memdelete(multimesh);
} else if (immediate_owner.owns(p_rid)) {
@@ -6405,9 +6505,11 @@ void RasterizerStorageGLES3::initialize() {
config.latc_supported=config.extensions.has("GL_EXT_texture_compression_latc");
config.bptc_supported=config.extensions.has("GL_ARB_texture_compression_bptc");
#ifdef GLES_OVER_GL
+ config.hdr_supported=true;
config.etc2_supported=false;
#else
config.etc2_supported=true;
+ config.hdr_supported=false;
#endif
config.pvrtc_supported=config.extensions.has("GL_IMG_texture_compression_pvrtc");
config.srgb_decode_supported=config.extensions.has("GL_EXT_texture_sRGB_decode");
@@ -6568,6 +6670,14 @@ void RasterizerStorageGLES3::finalize() {
}
+void RasterizerStorageGLES3::update_dirty_resources() {
+
+ update_dirty_multimeshes();
+ update_dirty_skeletons();
+ update_dirty_shaders();
+ update_dirty_materials();
+ update_particles();
+}
RasterizerStorageGLES3::RasterizerStorageGLES3()
{
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 07998886a8..1fa15538de 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* rasterizer_storage_gles3.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RASTERIZERSTORAGEGLES3_H
#define RASTERIZERSTORAGEGLES3_H
@@ -46,6 +74,8 @@ public:
bool etc2_supported;
bool pvrtc_supported;
+ bool hdr_supported;
+
bool srgb_decode_supported;
bool use_rgba_2d_shadows;
@@ -567,6 +597,7 @@ public:
virtual void material_changed_notify() {
mesh->instance_material_change_notify();
+ mesh->update_multimeshes();
}
Surface() {
@@ -591,6 +622,7 @@ public:
}
};
+ class MultiMesh;
struct Mesh : public GeometryOwner {
@@ -600,6 +632,17 @@ public:
VS::BlendShapeMode blend_shape_mode;
Rect3 custom_aabb;
mutable uint64_t last_pass;
+ SelfList<MultiMesh>::List multimeshes;
+
+ _FORCE_INLINE_ void update_multimeshes() {
+
+ SelfList<MultiMesh> *mm = multimeshes.first();
+ while(mm) {
+ mm->self()->instance_material_change_notify();
+ mm=mm->next();
+ }
+ }
+
Mesh() {
blend_shape_mode=VS::BLEND_SHAPE_MODE_NORMALIZED;
blend_shape_count=0;
@@ -659,6 +702,7 @@ public:
Vector<float> data;
Rect3 aabb;
SelfList<MultiMesh> update_list;
+ SelfList<MultiMesh> mesh_list;
GLuint buffer;
int visible_instances;
@@ -668,7 +712,7 @@ public:
bool dirty_aabb;
bool dirty_data;
- MultiMesh() : update_list(this) {
+ MultiMesh() : update_list(this), mesh_list(this) {
dirty_aabb=true;
dirty_data=true;
xform_floats=0;
@@ -921,6 +965,7 @@ public:
int dynamic_range;
float energy;
+ float bias;
float propagation;
bool interior;
bool compress;
@@ -954,6 +999,9 @@ public:
virtual void gi_probe_set_energy(RID p_probe,float p_range);
virtual float gi_probe_get_energy(RID p_probe) const;
+ virtual void gi_probe_set_bias(RID p_probe,float p_range);
+ virtual float gi_probe_get_bias(RID p_probe) const;
+
virtual void gi_probe_set_propagation(RID p_probe,float p_range);
virtual float gi_probe_get_propagation(RID p_probe) const;
@@ -1259,6 +1307,7 @@ public:
virtual bool has_os_feature(const String& p_feature) const;
+ virtual void update_dirty_resources();
RasterizerStorageGLES3();
};
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 12aac79912..260f1787c4 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* shader_compiler_gles3.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "shader_compiler_gles3.h"
+
#include "os/os.h"
#define SL ShaderLanguage
@@ -401,6 +430,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
String scode = _dump_node_code(bnode->statements[i],p_level,r_gen_code,p_actions,p_default_actions);
if (bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW) {
+ // FIXME: if (A || A) ? I am hesitant to delete one of them, could be copy-paste error.
code+=scode; //use directly
} else {
code+=_mktab(p_level)+scode+";\n";
diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h
index 1beee66ad7..bbdfc7865f 100644
--- a/drivers/gles3/shader_compiler_gles3.h
+++ b/drivers/gles3/shader_compiler_gles3.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* shader_compiler_gles3.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SHADERCOMPILERGLES3_H
#define SHADERCOMPILERGLES3_H
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 42a9f19671..a148d68a91 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -1,11 +1,11 @@
/*************************************************************************/
-/* shader_gles2.cpp */
+/* shader_gles3.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index ee8db2ac8c..464f359d51 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -1,11 +1,11 @@
/*************************************************************************/
-/* shader_gles2.h */
+/* shader_gles3.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan 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 @@ private:
struct VersionKeyHash {
- static _FORCE_INLINE_ uint32_t hash( const VersionKey& p_key) { return HashMapHahserDefault::hash(p_key.key); };
+ static _FORCE_INLINE_ uint32_t hash( const VersionKey& p_key) { return HashMapHasherDefault::hash(p_key.key); };
};
//this should use a way more cachefriendly version..
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 200c0c0cac..a0bf6cd58b 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -533,8 +533,8 @@ float contact_shadow_compute(vec3 pos, vec3 dir, float max_distance) {
float ratio_incr = 1.0/steps;
do {
- source += incr*2;
- bias+=incr*2;
+ source += incr*2.0;
+ bias+=incr*2.0;
vec3 uv_depth = (source.xyz / source.w) * 0.5 + 0.5;
float depth = texture(depth_buffer,uv_depth.xy).r;
@@ -931,6 +931,7 @@ uniform highp mat4 gi_probe_xform1;
uniform highp vec3 gi_probe_bounds1;
uniform highp vec3 gi_probe_cell_size1;
uniform highp float gi_probe_multiplier1;
+uniform highp float gi_probe_bias1;
uniform bool gi_probe_blend_ambient1;
uniform mediump sampler3D gi_probe2; //texunit:-7
@@ -938,13 +939,14 @@ uniform highp mat4 gi_probe_xform2;
uniform highp vec3 gi_probe_bounds2;
uniform highp vec3 gi_probe_cell_size2;
uniform highp float gi_probe_multiplier2;
+uniform highp float gi_probe_bias2;
uniform bool gi_probe2_enabled;
uniform bool gi_probe_blend_ambient2;
-vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, vec3 direction, float tan_half_angle, float max_distance) {
+vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
- float dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0;
+ float dist = p_bias;//1.0; //dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0;
float alpha=0.0;
vec3 color = vec3(0.0);
@@ -957,12 +959,14 @@ vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, b
dist += diameter * 0.5;
}
- //color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient);
+ if (blend_ambient) {
+ color.rgb = mix(ambient,color.rgb,min(1.0,alpha/0.95));
+ }
return color;
}
-void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) {
+void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness,float p_bias, out vec4 out_spec, out vec4 out_diff) {
@@ -1023,7 +1027,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
for(int i=0;i<MAX_CONE_DIRS;i++) {
vec3 dir = normalize( (probe_xform * vec4(pos + normal_mtx * cone_dirs[i],1.0)).xyz - probe_pos);
- light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,ambient,blend_ambient,dir,cone_angle_tan,max_distance);
+ light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,ambient,blend_ambient,dir,cone_angle_tan,max_distance,p_bias);
}
@@ -1033,7 +1037,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
//irradiance
- vec3 irr_light = voxel_cone_trace(probe,cell_size,probe_pos,environment,blend_ambient,ref_vec,max(min_ref_tan,tan(roughness * 0.5 * M_PI)) ,max_distance);
+ vec3 irr_light = voxel_cone_trace(probe,cell_size,probe_pos,environment,blend_ambient,ref_vec,max(min_ref_tan,tan(roughness * 0.5 * M_PI)) ,max_distance,p_bias);
irr_light *= multiplier;
//irr_light=vec3(0.0);
@@ -1064,11 +1068,11 @@ void gi_probes_compute(vec3 pos, vec3 normal, float roughness, vec3 specular, in
out_specular = vec3(0.0);
- gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,ambient,environment,gi_probe_blend_ambient1,gi_probe_multiplier1,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
+ gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,ambient,environment,gi_probe_blend_ambient1,gi_probe_multiplier1,normal_mat,ref_vec,roughness,gi_probe_bias1,spec_accum,diff_accum);
if (gi_probe2_enabled) {
- gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,ambient,environment,gi_probe_blend_ambient2,gi_probe_multiplier2,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
+ gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,ambient,environment,gi_probe_blend_ambient2,gi_probe_multiplier2,normal_mat,ref_vec,roughness,gi_probe_bias2,spec_accum,diff_accum);
}
if (diff_accum.a>0.0) {
diff --git a/drivers/gles3/shaders/ssao.glsl b/drivers/gles3/shaders/ssao.glsl
index 75f49ef37a..ba29ec52c7 100644
--- a/drivers/gles3/shaders/ssao.glsl
+++ b/drivers/gles3/shaders/ssao.glsl
@@ -29,7 +29,7 @@ void main() {
uniform sampler2D source_depth; //texunit:0
-uniform usampler2D source_depth_mipmaps; //texunit:1
+uniform highp usampler2D source_depth_mipmaps; //texunit:1
uniform sampler2D source_normal; //texunit:2
uniform ivec2 screen_size;
@@ -78,8 +78,8 @@ vec3 reconstructCSFaceNormal(vec3 C) {
/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){
// Radius relative to ssR
- float alpha = float(sampleNumber + 0.5) * (1.0 / NUM_SAMPLES);
- float angle = alpha * (NUM_SPIRAL_TURNS * 6.28) + spinAngle;
+ float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES));
+ float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle;
ssR = alpha;
return vec2(cos(angle), sin(angle));
@@ -193,7 +193,7 @@ void main() {
// Hash function used in the HPG12 AlchemyAO paper
- float randomPatternRotationAngle = (3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10;
+ float randomPatternRotationAngle = float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10);
// Reconstruct normals from positions. These will lead to 1-pixel black lines
// at depth discontinuities, however the blur will wipe those out so they are not visible
@@ -208,12 +208,12 @@ void main() {
sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle);
}
- float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / NUM_SAMPLES));
+ float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / float(NUM_SAMPLES)));
#ifdef ENABLE_RADIUS2
//go again for radius2
- randomPatternRotationAngle = (5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11;
+ randomPatternRotationAngle = float((5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11);
// Reconstruct normals from positions. These will lead to 1-pixel black lines
// at depth discontinuities, however the blur will wipe those out so they are not visible
@@ -228,15 +228,15 @@ void main() {
sum += sampleAO(ssC, C, n_C, ssDiskRadius,radius2, i, randomPatternRotationAngle);
}
- A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / NUM_SAMPLES)));
+ A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES))));
#endif
// Bilateral box-filter over a quad for free, respecting depth edges
// (the difference that this makes is subtle)
if (abs(dFdx(C.z)) < 0.02) {
- A -= dFdx(A) * ((ssC.x & 1) - 0.5);
+ A -= dFdx(A) * (float(ssC.x & 1) - 0.5);
}
if (abs(dFdy(C.z)) < 0.02) {
- A -= dFdy(A) * ((ssC.y & 1) - 0.5);
+ A -= dFdy(A) * (float(ssC.y & 1) - 0.5);
}
visibility = A;
diff --git a/drivers/gles3/shaders/ssao_minify.glsl b/drivers/gles3/shaders/ssao_minify.glsl
index df9045c28a..6e46a1842c 100644
--- a/drivers/gles3/shaders/ssao_minify.glsl
+++ b/drivers/gles3/shaders/ssao_minify.glsl
@@ -43,7 +43,7 @@ void main() {
fdepth = fdepth * 2.0 - 1.0;
fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near));
fdepth /= camera_z_far;
- depth = uint(clamp(fdepth*65535,0.0,65535.0));
+ depth = uint(clamp(fdepth*65535.0,0.0,65535.0));
#else
depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp
index a9a199bb59..f55b089ded 100644
--- a/drivers/png/resource_saver_png.cpp
+++ b/drivers/png/resource_saver_png.cpp
@@ -29,7 +29,7 @@
#include "resource_saver_png.h"
#include "core/image.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
#include "scene/resources/texture.h"
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 5f0e647545..f5268f3ebd 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -32,7 +32,7 @@
#include <pulse/error.h>
-#include "globals.h"
+#include "global_config.h"
Error AudioDriverPulseAudio::init() {
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index 6ada0aaa68..cc715545bd 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "audio_driver_rtaudio.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
#ifdef RTAUDIO_ENABLED
diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp
deleted file mode 100644
index 139597f9cb..0000000000
--- a/drivers/unix/memory_pool_static_malloc.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/drivers/unix/memory_pool_static_malloc.h b/drivers/unix/memory_pool_static_malloc.h
deleted file mode 100644
index e69de29bb2..0000000000
--- a/drivers/unix/memory_pool_static_malloc.h
+++ /dev/null
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index cc69283f97..fe49501328 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -61,7 +61,7 @@
#include <poll.h>
#include <errno.h>
#include <assert.h>
-#include "globals.h"
+#include "global_config.h"
extern bool _print_error_enabled;
@@ -117,7 +117,13 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
return 0;
}
-
+// Very simple signal handler to reap processes where ::execute was called with
+// !p_blocking
+void handle_sigchld(int sig) {
+ int saved_errno = errno;
+ while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {}
+ errno = saved_errno;
+}
void OS_Unix::initialize_core() {
@@ -148,6 +154,14 @@ void OS_Unix::initialize_core() {
ticks_start=0;
ticks_start=get_ticks_usec();
+
+ struct sigaction sa;
+ sa.sa_handler = &handle_sigchld;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+ if (sigaction(SIGCHLD, &sa, 0) == -1) {
+ perror("ERROR sigaction() failed:");
+ }
}
void OS_Unix::finalize_core() {
diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp
index 6adb3eea70..7696a5fcb5 100644
--- a/drivers/unix/packet_peer_udp_posix.cpp
+++ b/drivers/unix/packet_peer_udp_posix.cpp
@@ -96,12 +96,15 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size
}
Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){
- ERR_FAIL_COND_V(peer_addr == IP_Address(), ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED);
+
+ if (sock_type==IP::TYPE_NONE)
+ sock_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
int sock = _get_socket();
ERR_FAIL_COND_V( sock == -1, FAILED );
struct sockaddr_storage addr;
- size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, ip_type);
+ size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type);
errno = 0;
int err;
@@ -121,16 +124,27 @@ int PacketPeerUDPPosix::get_max_packet_size() const{
return 512; // uhm maybe not
}
-Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size) {
+Error PacketPeerUDPPosix::listen(int p_port, IP_Address p_bind_address, int p_recv_buffer_size) {
+
+ ERR_FAIL_COND_V(sockfd!=-1,ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(),ERR_INVALID_PARAMETER);
+
+#ifdef __OpenBSD__
+ sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only.
+#else
+ sock_type = IP::TYPE_ANY;
+#endif
+
+ if(p_bind_address.is_valid())
+ sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
- close();
int sock = _get_socket();
if (sock == -1 )
return ERR_CANT_CREATE;
sockaddr_storage addr = {0};
- size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL);
+ size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, IP_Address());
if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) {
close();
@@ -145,7 +159,8 @@ void PacketPeerUDPPosix::close(){
if (sockfd != -1)
::close(sockfd);
sockfd=-1;
- rb.resize(8);
+ sock_type = IP::TYPE_NONE;
+ rb.resize(16);
queue_count=0;
}
@@ -157,10 +172,14 @@ Error PacketPeerUDPPosix::wait() {
Error PacketPeerUDPPosix::_poll(bool p_wait) {
+ if (sockfd==-1) {
+ return FAILED;
+ }
+
struct sockaddr_storage from = {0};
socklen_t len = sizeof(struct sockaddr_storage);
int ret;
- while ( (ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) {
+ while ( (ret = recvfrom(sockfd, recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-24, 0)), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) {
uint32_t port = 0;
@@ -221,10 +240,12 @@ int PacketPeerUDPPosix::get_packet_port() const{
int PacketPeerUDPPosix::_get_socket() {
+ ERR_FAIL_COND_V(sock_type==IP::TYPE_NONE, -1);
+
if (sockfd != -1)
return sockfd;
- sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP);
+ sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
return sockfd;
}
@@ -253,7 +274,8 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() {
packet_port=0;
queue_count=0;
peer_port=0;
- ip_type = IP::TYPE_ANY;
+ sock_type = IP::TYPE_NONE;
+ rb.resize(16);
}
PacketPeerUDPPosix::~PacketPeerUDPPosix() {
diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h
index ead7174a9d..ac68344d78 100644
--- a/drivers/unix/packet_peer_udp_posix.h
+++ b/drivers/unix/packet_peer_udp_posix.h
@@ -48,6 +48,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
mutable int packet_port;
mutable int queue_count;
int sockfd;
+ IP::Type sock_type;
IP_Address peer_addr;
int peer_port;
@@ -65,7 +66,7 @@ public:
virtual int get_max_packet_size() const;
- virtual Error listen(int p_port, int p_recv_buffer_size=65536);
+ virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), int p_recv_buffer_size=65536);
virtual void close();
virtual Error wait();
virtual bool is_listening() const;
diff --git a/drivers/unix/rw_lock_posix.cpp b/drivers/unix/rw_lock_posix.cpp
index b51e5fd420..455dde73b1 100644
--- a/drivers/unix/rw_lock_posix.cpp
+++ b/drivers/unix/rw_lock_posix.cpp
@@ -1,8 +1,36 @@
-
+/*************************************************************************/
+/* rw_lock_posix.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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. */
+/*************************************************************************/
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
-#include "os/memory.h"
#include "rw_lock_posix.h"
+
+#include "os/memory.h"
#include "error_macros.h"
#include <stdio.h>
diff --git a/drivers/unix/rw_lock_posix.h b/drivers/unix/rw_lock_posix.h
index bcc102f6a6..35a686b15c 100644
--- a/drivers/unix/rw_lock_posix.h
+++ b/drivers/unix/rw_lock_posix.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* rw_lock_posix.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RWLOCKPOSIX_H
#define RWLOCKPOSIX_H
diff --git a/drivers/unix/socket_helpers.h b/drivers/unix/socket_helpers.h
index 6d4f7e7519..fd5fa618ca 100644
--- a/drivers/unix/socket_helpers.h
+++ b/drivers/unix/socket_helpers.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* socket_helpers.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SOCKET_HELPERS_H
#define SOCKET_HELPERS_H
@@ -16,7 +44,7 @@ static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p
memset(p_addr, 0, sizeof(struct sockaddr_storage));
- ERR_FAIL_COND_V(p_ip==IP_Address(),0);
+ ERR_FAIL_COND_V(!p_ip.is_valid(),0);
// IPv6 socket
if (p_sock_type == IP::TYPE_IPV6 || p_sock_type == IP::TYPE_ANY) {
@@ -44,21 +72,29 @@ static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p
};
};
-static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP::Type p_sock_type, const List<String> *p_accepted_hosts) {
+static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP::Type p_sock_type, const IP_Address p_bind_address) {
memset(p_addr, 0, sizeof(struct sockaddr_storage));
if (p_sock_type == IP::TYPE_IPV4) {
struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(p_port);
- addr4->sin_addr.s_addr = INADDR_ANY; // TODO: use accepted hosts list
+ if(p_bind_address.is_valid()) {
+ copymem(&addr4->sin_addr.s_addr, p_bind_address.get_ipv4(), 4);
+ } else {
+ addr4->sin_addr.s_addr = INADDR_ANY;
+ }
return sizeof(sockaddr_in);
} else {
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr;
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(p_port);
- addr6->sin6_addr = in6addr_any; // TODO: use accepted hosts list
+ if(p_bind_address.is_valid()) {
+ copymem(&addr6->sin6_addr.s6_addr, p_bind_address.get_ipv6(), 16);
+ } else {
+ addr6->sin6_addr = in6addr_any;
+ }
return sizeof(sockaddr_in6);
};
};
diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp
index ae4bf77c36..08a2954617 100644
--- a/drivers/unix/stream_peer_tcp_posix.cpp
+++ b/drivers/unix/stream_peer_tcp_posix.cpp
@@ -88,15 +88,10 @@ Error StreamPeerTCPPosix::_block(int p_sockfd, bool p_read, bool p_write) const
return ret < 0 ? FAILED : OK;
};
-Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
+Error StreamPeerTCPPosix::_poll_connection() const {
ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == -1, FAILED);
- if (p_block) {
-
- _block(sockfd, false, true);
- };
-
struct sockaddr_storage their_addr;
size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type);
@@ -122,10 +117,9 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
return OK;
};
-void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) {
+void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) {
- ip_type = p_ip_type;
- sock_type = p_ip_type;
+ sock_type = p_sock_type;
sockfd = p_sockfd;
#ifndef NO_FCNTL
fcntl(sockfd, F_SETFL, O_NONBLOCK);
@@ -142,7 +136,7 @@ void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port,
Error StreamPeerTCPPosix::connect_to_host(const IP_Address& p_host, uint16_t p_port) {
- ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V( !p_host.is_valid(), ERR_INVALID_PARAMETER);
sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
@@ -192,7 +186,7 @@ Error StreamPeerTCPPosix::write(const uint8_t* p_data,int p_bytes, int &r_sent,
if (status != STATUS_CONNECTED) {
- if (_poll_connection(p_block) != OK) {
+ if (_poll_connection() != OK) {
return FAILED;
};
@@ -252,7 +246,7 @@ Error StreamPeerTCPPosix::read(uint8_t* p_buffer, int p_bytes,int &r_received, b
if (status == STATUS_CONNECTING) {
- if (_poll_connection(p_block) != OK) {
+ if (_poll_connection() != OK) {
return FAILED;
};
@@ -331,7 +325,7 @@ bool StreamPeerTCPPosix::is_connected_to_host() const {
StreamPeerTCP::Status StreamPeerTCPPosix::get_status() const {
if (status == STATUS_CONNECTING) {
- _poll_connection(false);
+ _poll_connection();
};
return status;
@@ -398,7 +392,6 @@ StreamPeerTCPPosix::StreamPeerTCPPosix() {
sockfd = -1;
status = STATUS_NONE;
peer_port = 0;
- ip_type = IP::TYPE_ANY;
};
StreamPeerTCPPosix::~StreamPeerTCPPosix() {
diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h
index d33883b159..7f8d90a448 100644
--- a/drivers/unix/stream_peer_tcp_posix.h
+++ b/drivers/unix/stream_peer_tcp_posix.h
@@ -46,7 +46,7 @@ protected:
Error _block(int p_sockfd, bool p_read, bool p_write) const;
- Error _poll_connection(bool p_block) const;
+ Error _poll_connection() const;
IP_Address peer_host;
int peer_port;
@@ -68,7 +68,7 @@ public:
virtual int get_available_bytes() const;
- void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type);
+ void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type);
virtual IP_Address get_connected_host() const;
virtual uint16_t get_connected_port() const;
diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp
index 0178f08b8c..7e9970453f 100644
--- a/drivers/unix/tcp_server_posix.cpp
+++ b/drivers/unix/tcp_server_posix.cpp
@@ -68,10 +68,23 @@ void TCPServerPosix::make_default() {
TCP_Server::_create = TCPServerPosix::_create;
};
-Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
+Error TCPServerPosix::listen(uint16_t p_port,const IP_Address p_bind_address) {
+
+ ERR_FAIL_COND_V(listen_sockfd!=-1,ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
int sockfd;
- sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP);
+#ifdef __OpenBSD__
+ sock_type = IP::TYPE_IPV4; // OpenBSD does not support dual stacking, fallback to IPv4 only.
+#else
+ sock_type = IP::TYPE_ANY;
+#endif
+
+ // If the bind address is valid use its type as the socket type
+ if (p_bind_address.is_valid())
+ sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
+
+ sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
ERR_FAIL_COND_V(sockfd == -1, FAILED);
@@ -88,9 +101,7 @@ Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_host
}
struct sockaddr_storage addr;
- size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, p_accepted_hosts);
-
- // automatically fill with my IP TODO: use p_accepted_hosts
+ size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, p_bind_address);
if (bind(sockfd, (struct sockaddr *)&addr, addr_size) != -1) {
@@ -157,7 +168,7 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
int port;
_set_ip_addr_port(ip, port, &their_addr);
- conn->set_socket(fd, ip, port, ip_type);
+ conn->set_socket(fd, ip, port, sock_type);
return conn;
};
@@ -170,13 +181,14 @@ void TCPServerPosix::stop() {
};
listen_sockfd = -1;
+ sock_type = IP::TYPE_NONE;
};
TCPServerPosix::TCPServerPosix() {
listen_sockfd = -1;
- ip_type = IP::TYPE_ANY;
+ sock_type = IP::TYPE_NONE;
};
TCPServerPosix::~TCPServerPosix() {
diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h
index 6f9fa8cb5b..ea42d0fc0c 100644
--- a/drivers/unix/tcp_server_posix.h
+++ b/drivers/unix/tcp_server_posix.h
@@ -35,12 +35,13 @@
class TCPServerPosix : public TCP_Server {
int listen_sockfd;
+ IP::Type sock_type;
static TCP_Server* _create();
public:
- virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
+ virtual Error listen(uint16_t p_port, IP_Address p_bind_address=IP_Address("*"));
virtual bool is_connection_available() const;
virtual Ref<StreamPeerTCP> take_connection();
diff --git a/drivers/windows/rw_lock_windows.cpp b/drivers/windows/rw_lock_windows.cpp
index 0da7bf4bd5..edbd7b6a0f 100644
--- a/drivers/windows/rw_lock_windows.cpp
+++ b/drivers/windows/rw_lock_windows.cpp
@@ -1,8 +1,36 @@
-
+/*************************************************************************/
+/* rw_lock_windows.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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. */
+/*************************************************************************/
#if defined(WINDOWS_ENABLED)
-#include "os/memory.h"
#include "rw_lock_windows.h"
+
+#include "os/memory.h"
#include "error_macros.h"
#include <stdio.h>
diff --git a/drivers/windows/rw_lock_windows.h b/drivers/windows/rw_lock_windows.h
index c089c31c33..059704e5c7 100644
--- a/drivers/windows/rw_lock_windows.h
+++ b/drivers/windows/rw_lock_windows.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* rw_lock_windows.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RWLOCKWINDOWS_H
#define RWLOCKWINDOWS_H
diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp
index fa55c97325..cd61fefd91 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.cpp
+++ b/drivers/xaudio2/audio_driver_xaudio2.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "audio_driver_xaudio2.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
const char * AudioDriverXAudio2::get_name() const
diff --git a/editor/SCsub b/editor/SCsub
new file mode 100644
index 0000000000..d7392f8249
--- /dev/null
+++ b/editor/SCsub
@@ -0,0 +1,205 @@
+#!/usr/bin/env python
+
+Import('env')
+env.editor_sources = []
+
+import os
+
+
+def make_certs_header(target, source, env):
+
+ src = source[0].srcnode().abspath
+ dst = target[0].srcnode().abspath
+ f = open(src, "rb")
+ g = open(dst, "wb")
+ buf = f.read()
+ decomp_size = len(buf)
+ import zlib
+ buf = zlib.compress(buf)
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _CERTS_RAW_H\n")
+ g.write("#define _CERTS_RAW_H\n")
+ g.write("static const int _certs_compressed_size=" + str(len(buf)) + ";\n")
+ g.write("static const int _certs_uncompressed_size=" + str(decomp_size) + ";\n")
+ g.write("static const unsigned char _certs_compressed[]={\n")
+ for i in range(len(buf)):
+ g.write(str(ord(buf[i])) + ",\n")
+ g.write("};\n")
+ g.write("#endif")
+
+
+def make_doc_header(target, source, env):
+
+ dst = target[0].srcnode().abspath
+ g = open(dst, "wb")
+ buf = ""
+ docbegin = ""
+ docend = ""
+ for s in source:
+ src = s.srcnode().abspath
+ f = open(src, "rb")
+ content = f.read()
+ buf += content[content.find("<class"): content.rfind("</doc>")]
+ if len(docbegin) == 0:
+ docbegin = content[0: content.find("<class")]
+ if len(docend) == 0:
+ docend = content[content.rfind("</doc>"): len(buf)]
+ buf = docbegin + buf + docend
+ decomp_size = len(buf)
+ import zlib
+ buf = zlib.compress(buf)
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _DOC_DATA_RAW_H\n")
+ g.write("#define _DOC_DATA_RAW_H\n")
+ g.write("static const int _doc_data_compressed_size=" + str(len(buf)) + ";\n")
+ g.write("static const int _doc_data_uncompressed_size=" + str(decomp_size) + ";\n")
+ g.write("static const unsigned char _doc_data_compressed[]={\n")
+ for i in range(len(buf)):
+ g.write(str(ord(buf[i])) + ",\n")
+ g.write("};\n")
+ g.write("#endif")
+
+
+def make_fonts_header(target, source, env):
+
+ dst = target[0].srcnode().abspath
+
+ g = open(dst, "wb")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _EDITOR_FONTS_H\n")
+ g.write("#define _EDITOR_FONTS_H\n")
+
+ # saving uncompressed, since freetype will reference from memory pointer
+ xl_names = []
+ for i in range(len(source)):
+ print("Appending font: " + source[i].srcnode().abspath)
+ f = open(source[i].srcnode().abspath, "rb")
+ buf = f.read()
+ import os.path
+
+ name = os.path.splitext(os.path.basename(source[i].srcnode().abspath))[0]
+
+ g.write("static const int _font_" + name + "_size=" + str(len(buf)) + ";\n")
+ g.write("static const unsigned char _font_" + name + "[]={\n")
+ for i in range(len(buf)):
+ g.write(str(ord(buf[i])) + ",\n")
+
+ g.write("};\n")
+
+ g.write("#endif")
+
+
+def make_translations_header(target, source, env):
+
+ dst = target[0].srcnode().abspath
+
+ g = open(dst, "wb")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _EDITOR_TRANSLATIONS_H\n")
+ g.write("#define _EDITOR_TRANSLATIONS_H\n")
+
+ import zlib
+ import os.path
+
+ paths = [node.srcnode().abspath for node in source]
+ sorted_paths = sorted(paths, key=lambda path: os.path.splitext(os.path.basename(path))[0])
+
+ xl_names = []
+ for i in range(len(sorted_paths)):
+ print("Appending translation: " + sorted_paths[i])
+ f = open(sorted_paths[i], "rb")
+ buf = f.read()
+ decomp_size = len(buf)
+ buf = zlib.compress(buf)
+ name = os.path.splitext(os.path.basename(sorted_paths[i]))[0]
+
+ #g.write("static const int _translation_"+name+"_compressed_size="+str(len(buf))+";\n")
+ #g.write("static const int _translation_"+name+"_uncompressed_size="+str(decomp_size)+";\n")
+ g.write("static const unsigned char _translation_" + name + "_compressed[]={\n")
+ for i in range(len(buf)):
+ g.write(str(ord(buf[i])) + ",\n")
+
+ g.write("};\n")
+
+ xl_names.append([name, len(buf), str(decomp_size)])
+
+ g.write("struct EditorTranslationList {\n")
+ g.write("\tconst char* lang;\n")
+ g.write("\tint comp_size;\n")
+ g.write("\tint uncomp_size;\n")
+ g.write("\tconst unsigned char* data;\n")
+ g.write("};\n\n")
+ g.write("static EditorTranslationList _editor_translations[]={\n")
+ for x in xl_names:
+ g.write("\t{ \"" + x[0] + "\", " + str(x[1]) + ", " + str(x[2]) + ",_translation_" + x[0] + "_compressed},\n")
+ g.write("\t{NULL,0,0,NULL}\n")
+ g.write("};\n")
+
+ g.write("#endif")
+
+
+if (env["tools"] == "yes"):
+
+ # Register exporters
+ reg_exporters_inc = '#include "register_exporters.h"\n'
+ reg_exporters = 'void register_exporters() {\n'
+ for e in env.platform_exporters:
+ env.editor_sources.append("#platform/" + e + "/export/export.cpp")
+ reg_exporters += '\tregister_' + e + '_exporter();\n'
+ reg_exporters_inc += '#include "platform/' + e + '/export/export.h"\n'
+ reg_exporters += '}\n'
+ f = open("register_exporters.cpp", "wb")
+ f.write(reg_exporters_inc)
+ f.write(reg_exporters)
+ f.close()
+
+ # API documentation
+ docs = ["#doc/base/classes.xml"]
+ moduledir = os.path.join(os.getcwd(), "..", "modules")
+ for m in os.listdir(moduledir):
+ curmodle = os.path.join(moduledir, m)
+ docfile = os.path.join(curmodle, "classes.xml")
+ if os.path.isdir(curmodle) and os.path.isfile(docfile):
+ docs.append(docfile)
+ env.Depends("#editor/doc_data_compressed.h", docs)
+ env.Command("#editor/doc_data_compressed.h", docs, make_doc_header)
+
+ # Certificates
+ env.Depends("#editor/certs_compressed.h", "#thirdparty/certs/ca-certificates.crt")
+ env.Command("#editor/certs_compressed.h", "#thirdparty/certs/ca-certificates.crt", make_certs_header)
+
+ import glob
+ path = env.Dir('.').abspath
+
+ # Translations
+ tlist = glob.glob(path + "/translations/*.po")
+ print("translations: ", tlist)
+ env.Depends('#editor/translations.h', tlist)
+ env.Command('#editor/translations.h', tlist, make_translations_header)
+
+ # Fonts
+ flist = glob.glob(path + "/../thirdparty/fonts/*.ttf")
+ flist.append(glob.glob(path + "/../thirdparty/fonts/*.otf"))
+ print("fonts: ", flist)
+ env.Depends('#editor/builtin_fonts.h', flist)
+ env.Command('#editor/builtin_fonts.h', flist, make_fonts_header)
+
+
+ env.add_source_files(env.editor_sources, "*.cpp")
+
+ SConscript('collada/SCsub')
+ SConscript('doc/SCsub')
+ SConscript('fileserver/SCsub')
+ SConscript('icons/SCsub')
+ SConscript('import/SCsub')
+ SConscript('io_plugins/SCsub')
+ SConscript('plugins/SCsub')
+
+ lib = env.Library("editor", env.editor_sources)
+ env.Prepend(LIBS=[lib])
+
+ Export('env')
diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp
new file mode 100644
index 0000000000..d65f229fca
--- /dev/null
+++ b/editor/animation_editor.cpp
@@ -0,0 +1,4331 @@
+/*************************************************************************/
+/* animation_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "animation_editor.h"
+
+#include "editor_settings.h"
+#include "os/keyboard.h"
+#include "os/os.h"
+#include "io/resource_saver.h"
+#include "pair.h"
+#include "scene/gui/separator.h"
+#include "editor_node.h"
+#include "editor/plugins/animation_player_editor_plugin.h"
+#include "scene/main/viewport.h"
+/* Missing to fix:
+
+ *Set
+ *Find better source for hint for edited value keys
+ * + button on track to add a key
+ * when clicked for first time, erase selection of not selected at first
+ * automatically create discrete/continuous tracks!!
+ *when create track do undo/redo
+*/
+
+
+class AnimationCurveEdit : public Control {
+ GDCLASS( AnimationCurveEdit, Control );
+public:
+ enum Mode {
+ MODE_DISABLED,
+ MODE_SINGLE,
+ MODE_MULTIPLE
+ };
+private:
+
+ Set<float> multiples;
+ float transition;
+ Mode mode;
+
+ void _notification(int p_what) {
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+
+ RID ci = get_canvas_item();
+
+ Size2 s = get_size();
+ Rect2 r(Point2(),s);
+
+ //r=r.grow(3);
+ Ref<StyleBox> sb = get_stylebox("normal","LineEdit");
+ sb->draw(ci,r);
+ r.size-=sb->get_minimum_size();
+ r.pos+=sb->get_offset();
+ //VisualServer::get_singleton()->canvas_item_add
+
+ Ref<Font> f = get_font("font","Label");
+ r=r.grow(-2);
+ Color color = get_color("font_color","Label");
+
+ int points = 48;
+ if (mode==MODE_MULTIPLE) {
+
+ Color mcolor=color;
+ mcolor.a*=0.3;
+
+ Set<float>::Element *E=multiples.front();
+ for(int j=0;j<16;j++) {
+
+ if (!E)
+ break;
+
+ float prev=1.0;
+ float exp=E->get();
+ bool flip=false;//hint_text=="attenuation";
+
+
+ for(int i=1;i<=points;i++) {
+
+ float ifl = i/float(points);
+ float iflp = (i-1)/float(points);
+
+ float h = 1.0-Math::ease(ifl,exp);
+
+ if (flip) {
+ ifl=1.0-ifl;
+ iflp=1.0-iflp;
+ }
+
+ VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),mcolor);
+ prev=h;
+ }
+
+ E=E->next();
+ }
+ }
+
+ float exp=transition;
+ if (mode!=MODE_DISABLED) {
+
+
+ float prev=1.0;
+
+ bool flip=false;//hint_text=="attenuation";
+
+
+ for(int i=1;i<=points;i++) {
+
+ float ifl = i/float(points);
+ float iflp = (i-1)/float(points);
+
+ float h = 1.0-Math::ease(ifl,exp);
+
+ if (flip) {
+ ifl=1.0-ifl;
+ iflp=1.0-iflp;
+ }
+
+ VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),color);
+ prev=h;
+ }
+ }
+
+ String txt=String::num(exp,2);
+ if (mode==MODE_DISABLED) {
+ txt=TTR("Disabled");
+ } else if (mode==MODE_MULTIPLE) {
+ txt+=" - "+TTR("All Selection");
+ }
+
+ f->draw(ci,Point2(10,10+f->get_ascent()),txt,color);
+
+ }
+ }
+
+ void _gui_input(const InputEvent& p_ev) {
+ if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
+
+ if (mode==MODE_DISABLED)
+ return;
+
+ float rel = p_ev.mouse_motion.relative_x;
+ if (rel==0)
+ return;
+
+ bool flip=false;
+
+ if (flip)
+ rel=-rel;
+
+ float val = transition;
+ if (val==0)
+ return;
+ bool sg = val < 0;
+ val = Math::absf(val);
+
+ val = Math::log(val)/Math::log((float)2.0);
+ //logspace
+ val+=rel*0.05;
+ //
+
+ val = Math::pow((float)2.0,val);
+ if (sg)
+ val=-val;
+
+ transition=val;
+ update();
+ //emit_signal("variant_changed");
+ emit_signal("transition_changed",transition);
+ }
+ }
+
+public:
+
+ static void _bind_methods() {
+
+ //ClassDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj);
+ ClassDB::bind_method("_gui_input",&AnimationCurveEdit::_gui_input);
+ ADD_SIGNAL(MethodInfo("transition_changed"));
+ }
+
+ void set_mode(Mode p_mode) {
+
+ mode=p_mode;
+ update();
+ }
+
+ void clear_multiples() { multiples.clear(); update();}
+ void set_multiple(float p_transition) {
+
+ multiples.insert(p_transition);
+ }
+
+ void set_transition(float p_transition) {
+ transition=p_transition;
+ update();
+ }
+
+ float get_transition() const {
+ return transition;
+ }
+
+ void force_transition(float p_value) {
+ if (mode==MODE_DISABLED)
+ return;
+ transition=p_value;
+ emit_signal("transition_changed",p_value);
+ update();
+ }
+
+ AnimationCurveEdit() {
+
+ transition=1.0;
+ set_default_cursor_shape(CURSOR_HSPLIT);
+ mode=MODE_DISABLED;
+ }
+
+};
+
+class AnimationKeyEdit : public Object {
+
+ GDCLASS(AnimationKeyEdit,Object);
+public:
+ bool setting;
+ bool hidden;
+
+ static void _bind_methods() {
+
+ ClassDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj);
+ ClassDB::bind_method("_key_ofs_changed",&AnimationKeyEdit::_key_ofs_changed);
+ }
+
+ //PopupDialog *ke_dialog;
+
+ void _fix_node_path(Variant &value) {
+
+
+ NodePath np=value;
+
+ if (np==NodePath())
+ return;
+
+ Node* root = EditorNode::get_singleton()->get_tree()->get_root();
+
+ Node* np_node = root->get_node(np);
+ ERR_FAIL_COND(!np_node);
+
+ Node* edited_node = root->get_node(base);
+ ERR_FAIL_COND(!edited_node);
+
+
+
+ value = edited_node->get_path_to(np_node);
+ }
+
+
+ void _update_obj(const Ref<Animation> &p_anim) {
+ if (setting)
+ return;
+ if (hidden)
+ return;
+ if (!(animation==p_anim))
+ return;
+ notify_change();
+ }
+
+ void _key_ofs_changed(const Ref<Animation> &p_anim,float from, float to) {
+ if (hidden)
+ return;
+ if (!(animation==p_anim))
+ return;
+ if (from!=key_ofs)
+ return;
+ key_ofs=to;
+ if (setting)
+ return;
+ notify_change();
+ }
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ int key = animation->track_find_key(track,key_ofs,true);
+ ERR_FAIL_COND_V(key==-1,false);
+
+ String name=p_name;
+ if (name=="time") {
+
+ float new_time = p_value;
+ if (new_time==key_ofs)
+ return true;
+
+ int existing = animation->track_find_key(track,new_time,true);
+
+ setting=true;
+ undo_redo->create_action(TTR("Move Add Key"),UndoRedo::MERGE_ENDS);
+
+ Variant val = animation->track_get_key_value(track,key);
+ float trans = animation->track_get_key_transition(track,key);
+
+ undo_redo->add_do_method(animation.ptr(),"track_remove_key",track,key);
+ undo_redo->add_do_method(animation.ptr(),"track_insert_key",track,new_time,val,trans);
+ undo_redo->add_do_method(this,"_key_ofs_changed",animation,key_ofs,new_time);
+ undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",track,new_time);
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",track,key_ofs,val,trans);
+ undo_redo->add_undo_method(this,"_key_ofs_changed",animation,new_time,key_ofs);
+
+
+ if (existing!=-1) {
+ Variant v = animation->track_get_key_value(track,existing);
+ float trans = animation->track_get_key_transition(track,existing);
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",track,new_time,v,trans);
+ }
+
+ undo_redo->commit_action();
+ setting=false;
+
+ return true;
+ } else if (name=="easing") {
+
+ float val = p_value;
+ float prev_val = animation->track_get_key_transition(track,key);
+ setting=true;
+ undo_redo->create_action(TTR("Anim Change Transition"),UndoRedo::MERGE_ENDS);
+ undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,val);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val);
+ undo_redo->add_do_method(this,"_update_obj",animation);
+ undo_redo->add_undo_method(this,"_update_obj",animation);
+ undo_redo->commit_action();
+ setting=false;
+ return true;
+ }
+
+
+
+ switch(animation->track_get_type(track)) {
+
+
+ case Animation::TYPE_TRANSFORM: {
+
+ Dictionary d_old = animation->track_get_key_value(track,key);
+ Dictionary d_new = d_old;
+ d_new[p_name]=p_value;
+ setting=true;
+ undo_redo->create_action(TTR("Anim Change Transform"));
+ undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,d_new);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,d_old);
+ undo_redo->add_do_method(this,"_update_obj",animation);
+ undo_redo->add_undo_method(this,"_update_obj",animation);
+ undo_redo->commit_action();
+ setting=false;
+ return true;
+
+ } break;
+ case Animation::TYPE_VALUE: {
+
+ if (name=="value") {
+
+ Variant value = p_value;
+
+ if (value.get_type()==Variant::NODE_PATH) {
+
+ _fix_node_path(value);
+ }
+
+ setting=true;
+ undo_redo->create_action(TTR("Anim Change Value"),UndoRedo::MERGE_ENDS);
+ Variant prev = animation->track_get_key_value(track,key);
+ undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,value);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,prev);
+ undo_redo->add_do_method(this,"_update_obj",animation);
+ undo_redo->add_undo_method(this,"_update_obj",animation);
+ undo_redo->commit_action();
+ setting=false;
+ return true;
+ }
+
+
+
+ } break;
+ case Animation::TYPE_METHOD: {
+
+ Dictionary d_old = animation->track_get_key_value(track,key);
+ Dictionary d_new = d_old;
+
+ bool change_notify_deserved=false;
+ bool mergeable=false;
+
+ if (name=="name") {
+
+ d_new["method"]=p_value;
+
+ }
+
+ if (name=="arg_count") {
+
+ Vector<Variant> args = d_old["args"];
+ args.resize(p_value);
+ d_new["args"]=args;
+ change_notify_deserved=true;
+ }
+
+ if (name.begins_with("args/")) {
+
+
+ Vector<Variant> args = d_old["args"];
+ int idx = name.get_slice("/",1).to_int();
+ ERR_FAIL_INDEX_V(idx,args.size(),false);
+
+ String what = name.get_slice("/",2);
+ if (what=="type") {
+ Variant::Type t = Variant::Type(int(p_value));
+
+ if (t!=args[idx].get_type()) {
+ Variant::CallError err;
+ if (Variant::can_convert(args[idx].get_type(),t)) {
+ Variant old=args[idx];
+ Variant *ptrs[1]={&old};
+ args[idx]=Variant::construct(t,(const Variant**)ptrs,1,err);
+ } else {
+
+ args[idx]=Variant::construct(t,NULL,0,err);
+ }
+ change_notify_deserved=true;
+ d_new["args"]=args;
+ }
+
+ }
+ if (what=="value") {
+
+ Variant value=p_value;
+ if (value.get_type()==Variant::NODE_PATH) {
+
+ _fix_node_path(value);
+ }
+
+ args[idx]=value;
+ d_new["args"]=args;
+ mergeable=true;
+ }
+ }
+
+ if (mergeable)
+ undo_redo->create_action(TTR("Anim Change Call"),UndoRedo::MERGE_ENDS);
+ else
+ undo_redo->create_action(TTR("Anim Change Call"));
+
+ Variant prev = animation->track_get_key_value(track,key);
+ setting=true;
+ undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,d_new);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,d_old);
+ undo_redo->add_do_method(this,"_update_obj",animation);
+ undo_redo->add_undo_method(this,"_update_obj",animation);
+ undo_redo->commit_action();
+ setting=false;
+ if (change_notify_deserved)
+ notify_change();
+ return true;
+ } break;
+ }
+
+
+
+ return false;
+
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const {
+
+ int key = animation->track_find_key(track,key_ofs,true);
+ ERR_FAIL_COND_V(key==-1,false);
+
+ String name=p_name;
+ if (name=="time") {
+ r_ret = key_ofs;
+ return true;
+ } else if (name=="easing") {
+ r_ret = animation->track_get_key_transition(track,key);
+ return true;
+ }
+
+
+
+ switch(animation->track_get_type(track)) {
+
+
+ case Animation::TYPE_TRANSFORM: {
+
+ Dictionary d = animation->track_get_key_value(track,key);
+ ERR_FAIL_COND_V(!d.has(name),false);
+ r_ret = d[p_name];
+ return true;
+
+ } break;
+ case Animation::TYPE_VALUE: {
+
+ if (name=="value") {
+ r_ret = animation->track_get_key_value(track,key);
+ return true;
+ }
+
+
+
+ } break;
+ case Animation::TYPE_METHOD: {
+
+ Dictionary d = animation->track_get_key_value(track,key);
+
+ if (name=="name") {
+
+ ERR_FAIL_COND_V(!d.has("method"),false);
+ r_ret=d["method"];
+ return true;
+ }
+
+ ERR_FAIL_COND_V(!d.has("args"),false);
+
+ Vector<Variant> args = d["args"];
+
+
+ if (name=="arg_count") {
+
+ r_ret=args.size();
+ return true;
+ }
+
+
+ if (name.begins_with("args/")) {
+
+ int idx = name.get_slice("/",1).to_int();
+ ERR_FAIL_INDEX_V(idx,args.size(),false);
+
+ String what = name.get_slice("/",2);
+ if (what=="type") {
+ r_ret=args[idx].get_type();
+ return true;
+ }
+ if (what=="value") {
+ r_ret=args[idx];
+ return true;
+ }
+ }
+
+ } break;
+ }
+
+ return false;
+ }
+ void _get_property_list( List<PropertyInfo> *p_list) const {
+
+ if (animation.is_null())
+ return;
+
+ ERR_FAIL_INDEX(track,animation->get_track_count());
+ int key = animation->track_find_key(track,key_ofs,true);
+ ERR_FAIL_COND(key==-1);
+
+ p_list->push_back( PropertyInfo( Variant::REAL, "time", PROPERTY_HINT_RANGE,"0,"+rtos(animation->get_length())+",0.01") );
+
+ switch(animation->track_get_type(track)) {
+
+
+ case Animation::TYPE_TRANSFORM: {
+
+ p_list->push_back( PropertyInfo( Variant::VECTOR3, "loc"));
+ p_list->push_back( PropertyInfo( Variant::QUAT, "rot"));
+ p_list->push_back( PropertyInfo( Variant::VECTOR3, "scale"));
+
+ } break;
+ case Animation::TYPE_VALUE: {
+
+ Variant v = animation->track_get_key_value(track,key);
+
+
+
+ if (hint.type!=Variant::NIL) {
+
+ PropertyInfo pi=hint;
+ pi.name="value";
+ p_list->push_back( pi );
+ } else {
+
+ PropertyHint hint= PROPERTY_HINT_NONE;
+ String hint_string;
+
+ if (v.get_type()==Variant::OBJECT) {
+ //could actually check the object property if exists..? yes i will!
+ Ref<Resource> res = v;
+ if (res.is_valid()) {
+
+ hint=PROPERTY_HINT_RESOURCE_TYPE;
+ hint_string=res->get_class();
+ }
+ }
+
+ if (v.get_type()!=Variant::NIL)
+ p_list->push_back( PropertyInfo( v.get_type(), "value", hint,hint_string));
+ }
+
+ } break;
+ case Animation::TYPE_METHOD: {
+
+ p_list->push_back( PropertyInfo( Variant::STRING, "name"));
+ p_list->push_back( PropertyInfo( Variant::INT, "arg_count",PROPERTY_HINT_RANGE,"0,5,1"));
+
+ Dictionary d = animation->track_get_key_value(track,key);
+ ERR_FAIL_COND(!d.has("args"));
+ Vector<Variant> args=d["args"];
+ String vtypes;
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+
+ if (i>0)
+ vtypes+=",";
+ vtypes+=Variant::get_type_name( Variant::Type(i) );
+ }
+
+ for(int i=0;i<args.size();i++) {
+
+ p_list->push_back( PropertyInfo( Variant::INT, "args/"+itos(i)+"/type", PROPERTY_HINT_ENUM,vtypes));
+ if (args[i].get_type()!=Variant::NIL)
+ p_list->push_back( PropertyInfo( args[i].get_type(), "args/"+itos(i)+"/value"));
+ }
+
+ } break;
+ }
+
+ /*
+ if (animation->track_get_type(track)!=Animation::TYPE_METHOD)
+ p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING));
+ */
+ }
+
+ UndoRedo *undo_redo;
+ Ref<Animation> animation;
+ int track;
+ float key_ofs;
+
+ PropertyInfo hint;
+ NodePath base;
+
+
+ void notify_change() {
+
+ _change_notify();
+ }
+
+ AnimationKeyEdit() { hidden=true; key_ofs=0; track=-1; setting=false; }
+
+};
+
+
+void AnimationKeyEditor::_menu_add_track(int p_type) {
+
+ ERR_FAIL_COND(!animation.is_valid());
+
+
+ switch(p_type) {
+
+ case ADD_TRACK_MENU_ADD_CALL_TRACK: {
+ if (root) {
+ call_select->popup_centered_ratio();
+ break;
+ }
+ } break;
+ case ADD_TRACK_MENU_ADD_VALUE_TRACK:
+ case ADD_TRACK_MENU_ADD_TRANSFORM_TRACK: {
+
+ undo_redo->create_action(TTR("Anim Add Track"));
+ undo_redo->add_do_method(animation.ptr(),"add_track",p_type);
+ undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),".");
+ undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
+ undo_redo->commit_action();
+
+
+ } break;
+ }
+}
+
+void AnimationKeyEditor::_anim_duplicate_keys(bool transpose) {
+ //duplicait!
+ if (selection.size() && animation.is_valid() && selected_track>=0 && selected_track<animation->get_track_count()) {
+
+ int top_track=0x7FFFFFFF;
+ float top_time = 1e10;
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ const SelectedKey &sk = E->key();
+
+ float t = animation->track_get_key_time(sk.track,sk.key);
+ if (t<top_time)
+ top_time=t;
+ if (sk.track<top_track)
+ top_track=sk.track;
+
+ }
+ ERR_FAIL_COND( top_track == 0x7FFFFFFF || top_time==1e10 );
+
+ //
+
+ int start_track = transpose ? selected_track : top_track;
+
+ undo_redo->create_action(TTR("Anim Duplicate Keys"));
+
+ List<Pair<int,float> > new_selection_values;
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ const SelectedKey &sk = E->key();
+
+ float t = animation->track_get_key_time(sk.track,sk.key);
+
+ float dst_time = t+(timeline_pos - top_time);
+ int dst_track = sk.track + (start_track - top_track);
+
+ if (dst_track < 0 || dst_track>= animation->get_track_count())
+ continue;
+
+ if (animation->track_get_type(dst_track) != animation->track_get_type(sk.track))
+ continue;
+
+ int existing_idx = animation->track_find_key(dst_track,dst_time,true);
+
+ undo_redo->add_do_method(animation.ptr(),"track_insert_key",dst_track,dst_time,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
+ undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",dst_track,dst_time);
+
+ Pair<int,float> p;
+ p.first=dst_track;
+ p.second=dst_time;
+ new_selection_values.push_back( p );
+
+ if (existing_idx!=-1) {
+
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",dst_track,dst_time,animation->track_get_key_value(dst_track,existing_idx),animation->track_get_key_transition(dst_track,existing_idx));
+
+ }
+
+ }
+
+ undo_redo->commit_action();
+
+ //reselect duplicated
+
+ Map<SelectedKey,KeyInfo> new_selection;
+ for (List<Pair<int,float> >::Element *E=new_selection_values.front();E;E=E->next()) {
+
+ int track=E->get().first;
+ float time = E->get().second;
+
+ int existing_idx = animation->track_find_key(track,time,true);
+
+ if (existing_idx==-1)
+ continue;
+ SelectedKey sk2;
+ sk2.track=track;
+ sk2.key=existing_idx;
+
+ KeyInfo ki;
+ ki.pos=time;
+
+ new_selection[sk2]=ki;
+
+ }
+
+
+ selection=new_selection;
+ track_editor->update();
+ _edit_if_single_selection();
+
+ }
+}
+
+void AnimationKeyEditor::_menu_track(int p_type) {
+
+ ERR_FAIL_COND(!animation.is_valid());
+
+ last_menu_track_opt=p_type;
+ switch(p_type) {
+
+ case TRACK_MENU_SCALE:
+ case TRACK_MENU_SCALE_PIVOT: {
+
+ scale_dialog->popup_centered(Size2(200,100));
+ } break;
+ case TRACK_MENU_MOVE_UP: {
+
+ int idx=selected_track;
+ if (idx>0 && idx<animation->get_track_count()) {
+ undo_redo->create_action(TTR("Move Anim Track Up"));
+ undo_redo->add_do_method(animation.ptr(),"track_move_down",idx);
+ undo_redo->add_undo_method(animation.ptr(),"track_move_up",idx-1);
+ undo_redo->commit_action();
+ selected_track=idx-1;
+ }
+
+ } break;
+ case TRACK_MENU_MOVE_DOWN: {
+
+
+ int idx=selected_track;
+ if (idx>=0 && idx<animation->get_track_count()-1) {
+ undo_redo->create_action(TTR("Move Anim Track Down"));
+ undo_redo->add_do_method(animation.ptr(),"track_move_up",idx);
+ undo_redo->add_undo_method(animation.ptr(),"track_move_down",idx+1);
+ undo_redo->commit_action();
+ selected_track=idx+1;
+ }
+
+ } break;
+ case TRACK_MENU_REMOVE: {
+
+ int idx=selected_track;
+ if (idx>=0 && idx<animation->get_track_count()) {
+ undo_redo->create_action(TTR("Remove Anim Track"));
+ undo_redo->add_do_method(animation.ptr(),"remove_track",idx);
+ undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(idx),idx);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_path",idx,animation->track_get_path(idx));
+ //todo interpolation
+ for(int i=0;i<animation->track_get_key_count(idx);i++) {
+
+ Variant v = animation->track_get_key_value(idx,i);
+ float time = animation->track_get_key_time(idx,i);
+ float trans = animation->track_get_key_transition(idx,i);
+
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,time,v);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",idx,i,trans);
+
+ }
+
+ undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",idx,animation->track_get_interpolation_type(idx));
+ if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
+ undo_redo->add_undo_method(animation.ptr(),"value_track_set_update_mode",idx,animation->value_track_get_update_mode(idx));
+
+ }
+
+ undo_redo->commit_action();
+ }
+
+
+ } break;
+ case TRACK_MENU_DUPLICATE:
+ case TRACK_MENU_DUPLICATE_TRANSPOSE: {
+
+ _anim_duplicate_keys(p_type==TRACK_MENU_DUPLICATE_TRANSPOSE);
+ } break;
+ case TRACK_MENU_SET_ALL_TRANS_LINEAR:
+ case TRACK_MENU_SET_ALL_TRANS_CONSTANT:
+ case TRACK_MENU_SET_ALL_TRANS_OUT:
+ case TRACK_MENU_SET_ALL_TRANS_IN:
+ case TRACK_MENU_SET_ALL_TRANS_INOUT:
+ case TRACK_MENU_SET_ALL_TRANS_OUTIN: {
+
+ if (!selection.size() || !animation.is_valid())
+ break;
+
+ float t=0;
+ switch(p_type) {
+ case TRACK_MENU_SET_ALL_TRANS_LINEAR: t=1.0; break;
+ case TRACK_MENU_SET_ALL_TRANS_CONSTANT: t=0.0; break;
+ case TRACK_MENU_SET_ALL_TRANS_OUT: t=0.5; break;
+ case TRACK_MENU_SET_ALL_TRANS_IN: t=2.0; break;
+ case TRACK_MENU_SET_ALL_TRANS_INOUT: t=-0.5; break;
+ case TRACK_MENU_SET_ALL_TRANS_OUTIN: t=-2.0; break;
+ }
+
+ undo_redo->create_action(TTR("Set Transitions to:")+" "+rtos(t));
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ const SelectedKey &sk = E->key();
+
+ undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",sk.track,sk.key,t);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",sk.track,sk.key,animation->track_get_key_transition(sk.track,sk.key));
+
+ }
+
+ undo_redo->commit_action();
+
+ } break;
+ case TRACK_MENU_NEXT_STEP: {
+
+ if (animation.is_null())
+ break;
+ float step = animation->get_step();
+ if (step==0)
+ step=1;
+
+ float pos=timeline_pos;
+
+ pos=Math::stepify(pos+step,step);
+ if (pos>animation->get_length())
+ pos=animation->get_length();
+ timeline_pos=pos;
+ track_pos->update();
+ emit_signal("timeline_changed",pos,true);
+
+ } break;
+ case TRACK_MENU_PREV_STEP: {
+ if (animation.is_null())
+ break;
+ float step = animation->get_step();
+ if (step==0)
+ step=1;
+
+ float pos=timeline_pos;
+ pos=Math::stepify(pos-step,step);
+ if (pos<0)
+ pos=0;
+ timeline_pos=pos;
+ track_pos->update();
+ emit_signal("timeline_changed",pos,true);
+
+
+ } break;
+
+ case TRACK_MENU_OPTIMIZE: {
+
+ 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);
+
+ } break;
+ case CURVE_SET_IN: {
+
+ curve_edit->force_transition(4.0);
+
+ } break;
+ case CURVE_SET_OUT: {
+
+ curve_edit->force_transition(0.25);
+ } break;
+ case CURVE_SET_INOUT: {
+ curve_edit->force_transition(-4);
+
+ } break;
+ case CURVE_SET_OUTIN: {
+
+ curve_edit->force_transition(-0.25);
+ } break;
+ case CURVE_SET_CONSTANT: {
+
+ curve_edit->force_transition(0);
+ } break;
+
+ }
+
+}
+
+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() {
+
+
+
+ animation->optimize(optimize_linear_error->get_value(),optimize_angular_error->get_value(),optimize_max_angle->get_value());
+ track_editor->update();
+ undo_redo->clear_history();
+
+}
+
+
+float AnimationKeyEditor::_get_zoom_scale() const {
+
+ float zv = zoom->get_value();
+ if (zv<1) {
+ zv = 1.0-zv;
+ return Math::pow(1.0f+zv,8.0f)*100;
+ } else {
+ return 1.0/Math::pow(zv,8.0f)*100;
+ }
+}
+
+void AnimationKeyEditor::_track_pos_draw() {
+
+ if (!animation.is_valid()) {
+ return;
+ }
+
+
+ Ref<StyleBox> style = get_stylebox("normal","TextEdit");
+ Size2 size= track_editor->get_size() - style->get_minimum_size();
+ Size2 ofs = style->get_offset();
+
+ int settings_limit = size.width - right_data_size_cache;
+ int name_limit = settings_limit * name_column_ratio;
+
+ float keys_from= h_scroll->get_value();
+ float zoom_scale = _get_zoom_scale();
+ float keys_to=keys_from+(settings_limit-name_limit) / zoom_scale;
+
+
+
+ //will move to separate control! (for speedup)
+ if (timeline_pos >= keys_from && timeline_pos<keys_to) {
+ //draw position
+ int pixel = (timeline_pos - h_scroll->get_value()) * zoom_scale;
+ pixel+=name_limit;
+ track_pos->draw_line(ofs+Point2(pixel,0),ofs+Point2(pixel,size.height),Color(1,0.3,0.3,0.8));
+
+ }
+}
+
+void AnimationKeyEditor::_track_editor_draw() {
+
+
+ if (animation.is_valid() && animation->get_track_count()) {
+ if (selected_track < 0)
+ selected_track=0;
+ else if (selected_track>=animation->get_track_count())
+ selected_track=animation->get_track_count()-1;
+ }
+
+ track_pos->update();
+ Control *te=track_editor;
+ Ref<StyleBox> style = get_stylebox("normal","TextEdit");
+ te->draw_style_box(style,Rect2(Point2(),track_editor->get_size()));
+
+ if (te->has_focus()) {
+ te->draw_style_box(get_stylebox("bg_focus","Tree"),Rect2(Point2(),track_editor->get_size()));
+ }
+
+ if (!animation.is_valid()) {
+ v_scroll->hide();
+ h_scroll->hide();
+ menu_add_track->set_disabled(true);
+ menu_track->set_disabled(true);
+ edit_button->set_disabled(true);
+ key_editor_tab->hide();
+ move_up_button->set_disabled(true);
+ move_down_button->set_disabled(true);
+ remove_button->set_disabled(true);
+
+ return;
+ }
+
+ menu_add_track->set_disabled(false);
+ menu_track->set_disabled(false);
+ edit_button->set_disabled(false);
+ move_up_button->set_disabled(false);
+ move_down_button->set_disabled(false);
+ remove_button->set_disabled(false);
+ if (edit_button->is_pressed())
+ key_editor_tab->show();
+
+ te_drawing=true;
+
+ Size2 size= te->get_size() - style->get_minimum_size();
+ Size2 ofs = style->get_offset();
+
+ Ref<Font> font = te->get_font("font","Tree");
+ int sep = get_constant("vseparation","Tree");
+ int hsep = get_constant("hseparation","Tree");
+ Color color = get_color("font_color","Tree");
+ Color sepcolor = get_color("guide_color","Tree");
+ Color timecolor = get_color("prop_subsection","Editor");
+ 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");
+ Ref<Texture> move_up_icon = get_icon("MoveUp","EditorIcons");
+ Ref<Texture> move_down_icon = get_icon("MoveDown","EditorIcons");
+ Ref<Texture> remove_icon_hl = get_icon("RemoveHl","EditorIcons");
+ Ref<Texture> move_up_icon_hl = get_icon("MoveUpHl","EditorIcons");
+ Ref<Texture> move_down_icon_hl = get_icon("MoveDownHl","EditorIcons");
+ Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
+ Ref<Texture> add_key_icon_hl = get_icon("TrackAddKeyHl","EditorIcons");
+ Ref<Texture> down_icon = get_icon("select_arrow","Tree");
+
+ Ref<Texture> wrap_icon[2]={
+ get_icon("InterpWrapClamp","EditorIcons"),
+ get_icon("InterpWrapLoop","EditorIcons"),
+ };
+
+ Ref<Texture> interp_icon[3]={
+ get_icon("InterpRaw","EditorIcons"),
+ get_icon("InterpLinear","EditorIcons"),
+ get_icon("InterpCubic","EditorIcons")
+ };
+ Ref<Texture> cont_icon[3]={
+ get_icon("TrackContinuous","EditorIcons"),
+ get_icon("TrackDiscrete","EditorIcons"),
+ get_icon("TrackTrigger","EditorIcons")
+ };
+ Ref<Texture> type_icon[3]={
+ get_icon("KeyValue","EditorIcons"),
+ get_icon("KeyXform","EditorIcons"),
+ 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");
+ Ref<Texture> type_selected=get_icon("KeySelected","EditorIcons");
+
+ int right_separator_ofs = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*9;
+
+ int h = font->get_height()+sep;
+
+
+ int fit = (size.height / h)-1;
+ int total = animation->get_track_count();
+ if (total < fit) {
+ v_scroll->hide();
+ v_scroll->set_max( total );
+ v_scroll->set_page( fit );
+ } else {
+ v_scroll->show();
+ v_scroll->set_max( total );
+ v_scroll->set_page( fit );
+ }
+
+
+ int settings_limit = size.width - right_separator_ofs;
+ int name_limit = settings_limit * name_column_ratio;
+
+ te->draw_line(ofs+Point2(name_limit,0),ofs+Point2(name_limit,size.height),color);
+ te->draw_line(ofs+Point2(settings_limit,0),ofs+Point2(settings_limit,size.height),color);
+ te->draw_texture(hsize_icon,ofs+Point2(name_limit-hsize_icon->get_width()-hsep,(h-hsize_icon->get_height())/2));
+
+ te->draw_line(ofs+Point2(0,h),ofs+Point2(size.width,h),color);
+ // draw time
+
+ float keys_from;
+ float keys_to;
+ float zoom_scale;
+
+
+ {
+
+ int zoomw = settings_limit-name_limit;
+
+
+ float scale = _get_zoom_scale();
+ zoom_scale=scale;
+
+
+ float l = animation->get_length();
+ if (l<=0)
+ l=0.001; //avoid crashor
+
+ int end_px = (l - h_scroll->get_value()) * scale;
+ int begin_px = -h_scroll->get_value() * scale;
+ Color notimecol;
+ notimecol.r=timecolor.gray();
+ notimecol.g=notimecol.r;
+ notimecol.b=notimecol.r;
+ notimecol.a=timecolor.a;
+
+ {
+
+ te->draw_rect(Rect2( ofs + Point2(name_limit,0), Point2(zoomw-1,h)), notimecol);
+
+
+ if (begin_px < zoomw && end_px >0) {
+
+ if (begin_px<0)
+ begin_px=0;
+ if (end_px>zoomw)
+ end_px=zoomw;
+
+ te->draw_rect(Rect2( ofs + Point2(name_limit+begin_px,0), Point2(end_px-begin_px-1,h)), timecolor);
+ }
+
+ }
+
+
+
+ keys_from= h_scroll->get_value();
+ keys_to=keys_from+zoomw / scale;
+
+ {
+ float time_min=0;
+ float time_max=animation->get_length();
+ for(int i=0;i<animation->get_track_count();i++) {
+
+ if (animation->track_get_key_count(i)>0) {
+
+ float beg = animation->track_get_key_time(i,0);
+ if (beg<time_min)
+ time_min=beg;
+ float end = animation->track_get_key_time(i,animation->track_get_key_count(i)-1);
+ if (end>time_max)
+ time_max=end;
+ }
+ }
+
+
+
+
+
+ float extra = (zoomw / scale)*0.5;
+
+ if (time_min<-0.001)
+ time_min-=extra;
+ time_max+=extra;
+ h_scroll->set_min(time_min);
+ h_scroll->set_max(time_max);
+
+ if (zoomw / scale < (time_max-time_min)) {
+ h_scroll->show();
+
+ } else {
+
+ h_scroll->hide();
+ }
+
+
+ }
+
+ h_scroll->set_page(zoomw / scale);
+
+ Color color_time_sec = color;
+ Color color_time_dec = color;
+ color_time_dec.a*=0.5;
+#define SC_ADJ 100
+ int min=30;
+ int dec=1;
+ int step=1;
+ int decimals=2;
+ bool step_found=false;
+
+ while(!step_found) {
+
+ static const int _multp[3]={1,2,5};
+ for(int i=0;i<3;i++) {
+
+ step = (_multp[i] * dec);
+ if (step*scale/SC_ADJ> min) {
+ step_found=true;
+ break;
+ }
+
+ }
+ if (step_found)
+ break;
+ dec*=10;
+ decimals--;
+ if (decimals<0)
+ decimals=0;
+ }
+
+
+ for(int i=0;i<zoomw;i++) {
+
+ float pos = h_scroll->get_value() + double(i)/scale;
+ float prev = h_scroll->get_value() + (double(i)-1.0)/scale;
+
+
+ int sc = int(Math::floor(pos*SC_ADJ));
+ int prev_sc = int(Math::floor(prev*SC_ADJ));
+ bool sub = (sc % SC_ADJ);
+
+ if ((sc/step)!=(prev_sc/step) || (prev_sc<0 && sc>=0)) {
+
+ int scd = sc < 0 ? prev_sc : sc;
+ te->draw_line( ofs + Point2(name_limit+i,0), ofs+Point2(name_limit+i,h), color);
+ te->draw_string( font,ofs + Point2(name_limit+i+3,(h-font->get_height())/2+font->get_ascent()).floor(),String::num((scd-(scd%step))/double(SC_ADJ),decimals),sub?color_time_dec:color_time_sec,zoomw-i);
+ }
+
+
+ }
+ }
+
+ color.a*=0.5;
+
+ for(int i=0;i<fit;i++) {
+
+ //this code sucks, i always forget how it works
+
+ int idx = v_scroll->get_value() + i;
+ if (idx>=animation->get_track_count())
+ 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;
+ te->draw_rect(Rect2(ofs+Point2(0,y),Size2(size.width,h-1)),sepc);
+ }
+
+ if (selected_track==idx) {
+ Color tc = select_color;
+ //tc.a*=0.7;
+ te->draw_rect(Rect2(ofs+Point2(0,y),Size2(size.width-1,h-1)),tc);
+ }
+
+ te->draw_texture(type_icon[animation->track_get_type(idx)],ofs+Point2(0,y+(h-type_icon[0]->get_height())/2).floor());
+ NodePath np = animation->track_get_path(idx);
+ Node *n = root->get_node(np);
+ Color ncol = color;
+ if (n && editor_selection->is_selected(n))
+ 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);
+
+ Point2 icon_ofs = ofs + Point2( size.width, y + (h - remove_icon->get_height() )/2).floor();
+ icon_ofs.y+=4;
+
+
+/* icon_ofs.x-=remove_icon->get_width();
+
+ te->draw_texture((mouse_over.over==MouseOver::OVER_REMOVE && mouse_over.track==idx)?remove_icon_hl:remove_icon,icon_ofs);
+ icon_ofs.x-=hsep;
+ icon_ofs.x-=move_down_icon->get_width();
+ te->draw_texture((mouse_over.over==MouseOver::OVER_DOWN && mouse_over.track==idx)?move_down_icon_hl:move_down_icon,icon_ofs);
+ icon_ofs.x-=hsep;
+ icon_ofs.x-=move_up_icon->get_width();
+ te->draw_texture((mouse_over.over==MouseOver::OVER_UP && mouse_over.track==idx)?move_up_icon_hl:move_up_icon,icon_ofs);
+ icon_ofs.x-=hsep;
+ te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
+
+ icon_ofs.x-=hsep;
+ */
+ track_ofs[0]=size.width-icon_ofs.x;
+ icon_ofs.x-=down_icon->get_width();
+ te->draw_texture(down_icon,icon_ofs);
+
+ int wrap_type = animation->track_get_interpolation_loop_wrap(idx)?1:0;
+ icon_ofs.x-=hsep;
+ icon_ofs.x-=wrap_icon[wrap_type]->get_width();
+ te->draw_texture(wrap_icon[wrap_type],icon_ofs);
+
+ icon_ofs.x-=hsep;
+ te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
+
+ track_ofs[1]=size.width-icon_ofs.x;
+
+ icon_ofs.x-=down_icon->get_width();
+ te->draw_texture(down_icon,icon_ofs);
+
+ int interp_type = animation->track_get_interpolation_type(idx);
+ ERR_CONTINUE(interp_type<0 || interp_type>=3);
+ icon_ofs.x-=hsep;
+ icon_ofs.x-=interp_icon[interp_type]->get_width();
+ te->draw_texture(interp_icon[interp_type],icon_ofs);
+
+ icon_ofs.x-=hsep;
+ te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
+
+ track_ofs[2]=size.width-icon_ofs.x;
+
+ if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
+
+
+ int umode = animation->value_track_get_update_mode(idx);
+
+ icon_ofs.x-=hsep;
+ icon_ofs.x-=down_icon->get_width();
+ te->draw_texture(down_icon,icon_ofs);
+
+ icon_ofs.x-=hsep;
+ icon_ofs.x-=cont_icon[umode]->get_width();
+ te->draw_texture(cont_icon[umode],icon_ofs);
+ } else {
+
+ icon_ofs.x -= hsep*2 + cont_icon[0]->get_width() + down_icon->get_width();
+ }
+
+ icon_ofs.x-=hsep;
+ te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
+
+ track_ofs[3]=size.width-icon_ofs.x;
+
+ icon_ofs.x-=hsep;
+ icon_ofs.x-=add_key_icon->get_width();
+ te->draw_texture((mouse_over.over==MouseOver::OVER_ADD_KEY && mouse_over.track==idx)?add_key_icon_hl:add_key_icon,icon_ofs);
+
+ track_ofs[4]=size.width-icon_ofs.x;
+
+ //draw the keys;
+ int tt = animation->track_get_type(idx);
+ float key_vofs = Math::floor((float)(h - type_icon[tt]->get_height())/2);
+ float key_hofs = -Math::floor((float)type_icon[tt]->get_height()/2);
+
+ int kc=animation->track_get_key_count(idx);
+ bool first=true;
+
+
+
+ for(int i=0;i<kc;i++) {
+
+
+ float time = animation->track_get_key_time(idx,i);
+ if (time<keys_from)
+ continue;
+ if (time>keys_to) {
+
+ if (first && i>0 && animation->track_get_key_value(idx,i)==animation->track_get_key_value(idx,i-1)) {
+ //draw whole line
+ te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(settings_limit,y+h/2),color);
+ }
+
+ break;
+ }
+
+ float x = key_hofs + name_limit + (time-keys_from)*zoom_scale;
+
+ Ref<Texture> tex = type_icon[tt];
+
+ SelectedKey sk;
+ sk.key=i;
+ sk.track=idx;
+ if (selection.has(sk)) {
+
+ if (click.click==ClickOver::CLICK_MOVE_KEYS)
+ continue;
+ tex=type_selected;
+ }
+
+ if (mouse_over.over==MouseOver::OVER_KEY && mouse_over.track==idx && mouse_over.over_key==i)
+ tex=type_hover;
+
+ Variant value = animation->track_get_key_value(idx,i);
+ if (first && i>0 && value==animation->track_get_key_value(idx,i-1)) {
+
+ te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(x,y+h/2),color);
+ }
+
+ if (i<kc-1 && value==animation->track_get_key_value(idx,i+1)) {
+ float x_n = key_hofs + name_limit + (animation->track_get_key_time(idx,i+1)-keys_from)*zoom_scale;
+
+ x_n = MIN( x_n, settings_limit);
+ te->draw_line(ofs+Point2(x_n,y+h/2),ofs+Point2(x,y+h/2),color);
+
+ }
+
+ 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;
+ }
+
+ }
+
+ switch(click.click) {
+ case ClickOver::CLICK_SELECT_KEYS: {
+
+ te->draw_rect(Rect2(click.at,click.to-click.at),Color(0.7,0.7,1.0,0.5));
+
+ } break;
+ case ClickOver::CLICK_MOVE_KEYS: {
+
+ float from_t = 1e20;
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
+ float t = animation->track_get_key_time(E->key().track,E->key().key);
+ if (t<from_t)
+ from_t=t;
+
+ }
+
+ float motion = from_t+(click.to.x - click.at.x)/zoom_scale;
+ if (step->get_value())
+ motion = Math::stepify(motion,step->get_value());
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
+
+
+ int idx = E->key().track;
+ int i = idx-v_scroll->get_value();
+ if (i<0 || i>=fit)
+ continue;
+ int y = h+i*h+sep;
+
+ float key_vofs = Math::floor((float)(h - type_selected->get_height())/2);
+ float key_hofs = -Math::floor((float)type_selected->get_height()/2);
+
+ float time = animation->track_get_key_time(idx,E->key().key);
+ float diff = time-from_t;
+
+ float t = motion + diff;
+
+ float x = (t-keys_from)*zoom_scale;
+ //x+=click.to.x - click.at.x;
+ if (x<0 || x>=(settings_limit-name_limit))
+ continue;
+
+ x+=name_limit;
+
+ te->draw_texture(type_selected,ofs+Point2(x+key_hofs,y+key_vofs).floor());
+
+ }
+ } break;
+ default: {};
+ }
+
+
+ te_drawing=false;
+}
+
+void AnimationKeyEditor::_track_name_changed(const String& p_name) {
+
+ ERR_FAIL_COND(!animation.is_valid());
+ undo_redo->create_action(TTR("Anim Track Rename"));
+ undo_redo->add_do_method(animation.ptr(),"track_set_path",track_name_editing,p_name);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_path",track_name_editing,animation->track_get_path(track_name_editing));
+ undo_redo->commit_action();
+ track_name->hide();
+
+}
+
+void AnimationKeyEditor::_track_menu_selected(int p_idx) {
+
+
+ ERR_FAIL_COND(!animation.is_valid());
+
+ if (interp_editing!=-1) {
+
+ ERR_FAIL_INDEX(interp_editing,animation->get_track_count());
+ undo_redo->create_action(TTR("Anim Track Change Interpolation"));
+ undo_redo->add_do_method(animation.ptr(),"track_set_interpolation_type",interp_editing,p_idx);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",interp_editing,animation->track_get_interpolation_type(interp_editing));
+ undo_redo->commit_action();
+ } else if (cont_editing!=-1) {
+
+ ERR_FAIL_INDEX(cont_editing,animation->get_track_count());
+
+ undo_redo->create_action(TTR("Anim Track Change Value Mode"));
+ undo_redo->add_do_method(animation.ptr(),"value_track_set_update_mode",cont_editing,p_idx);
+ undo_redo->add_undo_method(animation.ptr(),"value_track_set_update_mode",cont_editing,animation->value_track_get_update_mode(cont_editing));
+ undo_redo->commit_action();
+ } else if (wrap_editing!=-1) {
+
+ ERR_FAIL_INDEX(wrap_editing,animation->get_track_count());
+
+ undo_redo->create_action(TTR("Anim Track Change Wrap Mode"));
+ undo_redo->add_do_method(animation.ptr(),"track_set_interpolation_loop_wrap",wrap_editing,p_idx?true:false);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_loop_wrap",wrap_editing,animation->track_get_interpolation_loop_wrap(wrap_editing));
+ undo_redo->commit_action();
+ } else {
+ switch (p_idx) {
+
+ case RIGHT_MENU_DUPLICATE:
+ _anim_duplicate_keys(); break;
+ case RIGHT_MENU_DUPLICATE_TRANSPOSE:
+ _anim_duplicate_keys(true); break;
+ case RIGHT_MENU_REMOVE:
+ _anim_delete_keys(); break;
+ }
+ }
+
+}
+
+struct _AnimMoveRestore {
+
+ int track;
+ float time;
+ Variant key;
+ float transition;
+};
+
+void AnimationKeyEditor::_clear_selection_for_anim(const Ref<Animation>& p_anim) {
+
+ if (!(animation==p_anim))
+ return;
+ //selection.clear();
+ _clear_selection();
+
+}
+
+void AnimationKeyEditor::_select_at_anim(const Ref<Animation>& p_anim,int p_track,float p_pos){
+
+ if (!(animation==p_anim))
+ return;
+
+ int idx = animation->track_find_key(p_track,p_pos,true);
+ ERR_FAIL_COND(idx<0);
+
+ SelectedKey sk;
+ sk.track=p_track;
+ sk.key=idx;
+ KeyInfo ki;
+ ki.pos=p_pos;
+
+ selection.insert(sk,ki);
+
+}
+
+
+PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx,NodePath& r_base_path) {
+
+ r_base_path=NodePath();
+ ERR_FAIL_COND_V(!animation.is_valid(),PropertyInfo());
+ ERR_FAIL_INDEX_V(p_idx,animation->get_track_count(),PropertyInfo());
+
+ if (!root)
+ return PropertyInfo();
+
+ NodePath path = animation->track_get_path(p_idx);
+
+
+ if (!root->has_node_and_resource(path))
+ return PropertyInfo();
+
+ RES res;
+ Node *node = root->get_node_and_resource(path,res);
+
+
+ if (node) {
+ r_base_path=node->get_path();
+ }
+
+ String property = path.get_property();
+ if (property=="")
+ return PropertyInfo();
+
+ List<PropertyInfo> pinfo;
+ if (res.is_valid())
+ res->get_property_list(&pinfo);
+ else
+ node->get_property_list(&pinfo);
+
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ if (E->get().name==property)
+ return E->get();
+ }
+
+ return PropertyInfo();
+}
+
+
+void AnimationKeyEditor::_curve_transition_changed(float p_what) {
+
+ if (selection.size()==0)
+ return;
+ if (selection.size()==1)
+ undo_redo->create_action(TTR("Edit Node Curve"),UndoRedo::MERGE_ENDS);
+ else
+ undo_redo->create_action(TTR("Edit Selection Curve"),UndoRedo::MERGE_ENDS);
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
+
+ int track = E->key().track;
+ int key = E->key().key;
+ float prev_val = animation->track_get_key_transition(track,key);
+ undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,p_what);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val);
+ }
+
+ undo_redo->commit_action();
+
+}
+
+void AnimationKeyEditor::_toggle_edit_curves() {
+
+ if (edit_button->is_pressed())
+ key_editor_tab->show();
+ else
+ key_editor_tab->hide();
+}
+
+
+bool AnimationKeyEditor::_edit_if_single_selection() {
+
+ if (selection.size()!=1) {
+
+ if (selection.size()==0) {
+ curve_edit->set_mode(AnimationCurveEdit::MODE_DISABLED);
+ //print_line("disable");
+ } else {
+
+ curve_edit->set_mode(AnimationCurveEdit::MODE_MULTIPLE);
+ curve_edit->set_transition(1.0);
+ curve_edit->clear_multiples();
+ //add all
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
+
+ curve_edit->set_multiple(animation->track_get_key_transition(E->key().track,E->key().key));
+ }
+ //print_line("multiple");
+
+ }
+ return false;
+ }
+ curve_edit->set_mode(AnimationCurveEdit::MODE_SINGLE);
+ //print_line("regular");
+
+ int idx = selection.front()->key().track;
+ int key = selection.front()->key().key;
+ {
+
+ key_edit->animation=animation;
+ key_edit->track=idx;
+ key_edit->key_ofs=animation->track_get_key_time(idx,key);
+ key_edit->hint=_find_hint_for_track(idx,key_edit->base);
+ key_edit->notify_change();
+
+ curve_edit->set_transition(animation->track_get_key_transition(idx,key));
+
+ /*key_edit_dialog->set_size( Size2( 200,200) );
+ key_edit_dialog->set_pos( track_editor->get_global_pos() + ofs + mpos +Point2(-100,20));
+ key_edit_dialog->popup();*/
+
+ }
+
+ return true;
+
+}
+
+void AnimationKeyEditor::_anim_delete_keys() {
+ if (selection.size()) {
+ undo_redo->create_action(TTR("Anim Delete Keys"));
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ undo_redo->add_do_method(animation.ptr(),"track_remove_key",E->key().track,E->key().key);
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
+
+ }
+ undo_redo->add_do_method(this,"_clear_selection_for_anim",animation);
+ undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation);
+ undo_redo->commit_action();
+ //selection.clear();
+ accept_event();
+ _edit_if_single_selection();
+ }
+}
+
+void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
+
+ Control *te=track_editor;
+ Ref<StyleBox> style = get_stylebox("normal","TextEdit");
+
+ if (!animation.is_valid()) {
+ return;
+ }
+
+ Size2 size= te->get_size() - style->get_minimum_size();
+ Size2 ofs = style->get_offset();
+
+ Ref<Font> font = te->get_font("font","Tree");
+ int sep = get_constant("vseparation","Tree");
+ int hsep = get_constant("hseparation","Tree");
+ Ref<Texture> remove_icon = get_icon("Remove","EditorIcons");
+ Ref<Texture> move_up_icon = get_icon("MoveUp","EditorIcons");
+ Ref<Texture> move_down_icon = get_icon("MoveDown","EditorIcons");
+ Ref<Texture> down_icon = get_icon("select_arrow","Tree");
+ Ref<Texture> hsize_icon = get_icon("Hsize","EditorIcons");
+ Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
+
+ Ref<Texture> wrap_icon[2]={
+ get_icon("InterpWrapClamp","EditorIcons"),
+ get_icon("InterpWrapLoop","EditorIcons"),
+ };
+ Ref<Texture> interp_icon[3]={
+ get_icon("InterpRaw","EditorIcons"),
+ get_icon("InterpLinear","EditorIcons"),
+ get_icon("InterpCubic","EditorIcons")
+ };
+ Ref<Texture> cont_icon[3]={
+ get_icon("TrackContinuous","EditorIcons"),
+ get_icon("TrackDiscrete","EditorIcons"),
+ get_icon("TrackTrigger","EditorIcons")
+ };
+ Ref<Texture> type_icon[3]={
+ get_icon("KeyValue","EditorIcons"),
+ get_icon("KeyXform","EditorIcons"),
+ get_icon("KeyCall","EditorIcons")
+ };
+ int right_separator_ofs = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*9;
+
+ int h = font->get_height()+sep;
+
+ int fit = (size.height / h)-1;
+ int total = animation->get_track_count();
+ if (total < fit) {
+ v_scroll->hide();
+ } else {
+ v_scroll->show();
+ v_scroll->set_max( total );
+ v_scroll->set_page( fit );
+ }
+
+ int settings_limit = size.width - right_separator_ofs;
+ int name_limit = settings_limit * name_column_ratio;
+
+
+ switch(p_input.type) {
+
+ case InputEvent::KEY: {
+
+ if (p_input.key.scancode==KEY_D && p_input.key.pressed && p_input.key.mod.command) {
+
+ if (p_input.key.mod.shift)
+ _menu_track(TRACK_MENU_DUPLICATE_TRANSPOSE);
+ else
+ _menu_track(TRACK_MENU_DUPLICATE);
+
+ accept_event();
+
+ } else if (p_input.key.scancode==KEY_DELETE && p_input.key.pressed && click.click==ClickOver::CLICK_NONE) {
+
+ _anim_delete_keys();
+ } else if (animation.is_valid() && animation->get_track_count()>0) {
+
+ if (p_input.is_pressed() && (p_input.is_action("ui_up") || p_input.is_action("ui_page_up"))) {
+
+ if (p_input.is_action("ui_up"))
+ selected_track--;
+ if (v_scroll->is_visible_in_tree() && p_input.is_action("ui_page_up"))
+ selected_track--;
+
+ if (selected_track<0)
+ selected_track=0;
+
+
+ if (v_scroll->is_visible_in_tree()) {
+ if (v_scroll->get_value() > selected_track)
+ v_scroll->set_value(selected_track);
+
+ }
+
+ track_editor->update();
+ accept_event();
+
+ }
+
+ if (p_input.is_pressed() && (p_input.is_action("ui_down") || p_input.is_action("ui_page_down"))) {
+
+ if (p_input.is_action("ui_down"))
+ selected_track++;
+ else if (v_scroll->is_visible_in_tree() && p_input.is_action("ui_page_down"))
+ selected_track+=v_scroll->get_page();
+
+ if (selected_track >= animation->get_track_count())
+ selected_track=animation->get_track_count()-1;
+
+ if (v_scroll->is_visible_in_tree() && v_scroll->get_page()+v_scroll->get_value() < selected_track+1) {
+ v_scroll->set_value(selected_track-v_scroll->get_page()+1);
+ }
+
+ track_editor->update();
+ accept_event();
+ }
+ }
+
+
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb = p_input.mouse_button;
+
+ if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) {
+
+ if (mb.mod.command) {
+ zoom->set_value(zoom->get_value() + zoom->get_step());
+ } else {
+ v_scroll->set_value( v_scroll->get_value() - v_scroll->get_page() / 8 );
+ }
+ }
+
+ if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) {
+
+ if (mb.mod.command) {
+ zoom->set_value(zoom->get_value() - zoom->get_step());
+ } else {
+ v_scroll->set_value( v_scroll->get_value() + v_scroll->get_page() / 8 );
+ }
+ }
+
+ if (mb.button_index==BUTTON_RIGHT && mb.pressed) {
+
+ Point2 mpos = Point2(mb.x,mb.y)-ofs;
+
+ if (selection.size() == 0) {
+ // Auto-select on right-click if nothing is selected
+ // Note: This code is pretty much duplicated from the left click code,
+ // both codes could be moved into a function to avoid the duplicated code.
+ Point2 mpos = Point2(mb.x,mb.y)-ofs;
+
+ if (mpos.y < h ) {
+ return;
+ }
+
+ mpos.y -= h;
+
+ int idx = mpos.y / h;
+ idx+=v_scroll->get_value();
+ if (idx <0 || idx>=animation->get_track_count())
+ break;
+
+ if (mpos.x < name_limit) {
+ } else if (mpos.x < settings_limit) {
+ float pos = mpos.x - name_limit;
+ pos/=_get_zoom_scale();
+ pos+=h_scroll->get_value();
+ float w_time = (type_icon[0]->get_width() / _get_zoom_scale())/2.0;
+
+ int kidx = animation->track_find_key(idx,pos);
+ int kidx_n = kidx+1;
+ int key=-1;
+
+ if (kidx>=0 && kidx<animation->track_get_key_count(idx)) {
+
+ float kpos = animation->track_get_key_time(idx,kidx);
+ if (ABS(pos-kpos)<=w_time) {
+
+ key=kidx;
+ }
+ }
+
+ if (key==-1 && kidx_n>=0 && kidx_n<animation->track_get_key_count(idx)) {
+
+ float kpos = animation->track_get_key_time(idx,kidx_n);
+ if (ABS(pos-kpos)<=w_time) {
+
+ key=kidx_n;
+ }
+ }
+
+ if (key==-1) {
+
+ click.click=ClickOver::CLICK_SELECT_KEYS;
+ click.at=Point2(mb.x,mb.y);
+ click.to=click.at;
+ click.shift=mb.mod.shift;
+ selected_track=idx;
+ track_editor->update();
+ //drag select region
+ return;
+
+ }
+
+
+
+ SelectedKey sk;
+ sk.track=idx;
+ sk.key=key;
+ KeyInfo ki;
+ ki.pos= animation->track_get_key_time(idx,key);
+ click.shift=mb.mod.shift;
+ click.selk=sk;
+
+
+ if (!mb.mod.shift && !selection.has(sk))
+ _clear_selection();
+
+ selection.insert(sk,ki);
+
+ click.click=ClickOver::CLICK_MOVE_KEYS;
+ click.at=Point2(mb.x,mb.y);
+ click.to=click.at;
+ update();
+ selected_track=idx;
+ track_editor->update();
+
+ if (_edit_if_single_selection() && mb.mod.command) {
+ edit_button->set_pressed(true);
+ key_editor_tab->show();
+ }
+ }
+ }
+
+ if (selection.size()) {
+ // User has right clicked and we have a selection, show a popup menu with options
+ track_menu->clear();
+ track_menu->set_size(Point2(1,1));
+ track_menu->add_item(TTR("Duplicate Selection"), RIGHT_MENU_DUPLICATE);
+ track_menu->add_item(TTR("Duplicate Transposed"), RIGHT_MENU_DUPLICATE_TRANSPOSE);
+ track_menu->add_item(TTR("Remove Selection"), RIGHT_MENU_REMOVE);
+
+ track_menu->set_pos(te->get_global_pos()+mpos);
+
+ interp_editing=-1;
+ cont_editing=-1;
+ wrap_editing=-1;
+
+ track_menu->popup();
+ }
+ }
+
+ if (mb.button_index==BUTTON_LEFT && !(mb.button_mask&~BUTTON_MASK_LEFT)) {
+
+
+ if (mb.pressed) {
+
+ Point2 mpos = Point2(mb.x,mb.y)-ofs;
+
+ if (mpos.y < h ) {
+
+
+ if (mpos.x<name_limit && mpos.x > (name_limit - hsep - hsize_icon->get_width())) {
+
+
+ click.click=ClickOver::CLICK_RESIZE_NAMES;
+ click.at=Point2(mb.x,mb.y);
+ click.to=click.at;
+ click.at.y=name_limit;
+
+ }
+
+ if (mpos.x>=name_limit && mpos.x<settings_limit) {
+ //seek
+ //int zoomw = settings_limit-name_limit;
+ float scale = _get_zoom_scale();
+ float pos = h_scroll->get_value() + (mpos.x-name_limit) / scale;
+ if (animation->get_step())
+ pos=Math::stepify(pos,animation->get_step());
+
+ if (pos<0 )
+ pos=0;
+ if (pos>=animation->get_length())
+ pos=animation->get_length();
+ timeline_pos=pos;
+ click.click=ClickOver::CLICK_DRAG_TIMELINE;
+ click.at=Point2(mb.x,mb.y);
+ click.to=click.at;
+ emit_signal("timeline_changed",pos,false);
+
+ }
+
+ return;
+ }
+
+ mpos.y -= h;
+
+ int idx = mpos.y / h;
+ idx+=v_scroll->get_value();
+ if (idx <0)
+ break;
+
+ if (idx>=animation->get_track_count()) {
+
+ if (mpos.x >= name_limit && mpos.x<settings_limit) {
+
+ click.click=ClickOver::CLICK_SELECT_KEYS;
+ click.at=Point2(mb.x,mb.y);
+ click.to=click.at;
+ //drag select region
+ }
+
+ break;
+ }
+
+ if (mpos.x < name_limit) {
+ //name column
+
+ // area
+ if (idx!=selected_track) {
+
+ selected_track=idx;
+ track_editor->update();
+ break;
+ }
+
+ Rect2 area(ofs.x,ofs.y+((int(mpos.y)/h)+1)*h,name_limit, h );
+ track_name->set_text(animation->track_get_path(idx));
+ track_name->set_pos( te->get_global_pos() + area.pos);
+ track_name->set_size(area.size);
+ track_name->show_modal();
+ track_name->grab_focus();
+ track_name->select_all();
+ track_name_editing=idx;
+
+ } else if (mpos.x < settings_limit) {
+
+ float pos = mpos.x - name_limit;
+ pos/=_get_zoom_scale();
+ pos+=h_scroll->get_value();
+ float w_time = (type_icon[0]->get_width() / _get_zoom_scale())/2.0;
+
+ int kidx = animation->track_find_key(idx,pos);
+ int kidx_n = kidx+1;
+ int key=-1;
+
+ if (kidx>=0 && kidx<animation->track_get_key_count(idx)) {
+
+ float kpos = animation->track_get_key_time(idx,kidx);
+ if (ABS(pos-kpos)<=w_time) {
+
+ key=kidx;
+ }
+ }
+
+ if (key==-1 && kidx_n>=0 && kidx_n<animation->track_get_key_count(idx)) {
+
+ float kpos = animation->track_get_key_time(idx,kidx_n);
+ if (ABS(pos-kpos)<=w_time) {
+
+ key=kidx_n;
+ }
+ }
+
+ if (key==-1) {
+
+ click.click=ClickOver::CLICK_SELECT_KEYS;
+ click.at=Point2(mb.x,mb.y);
+ click.to=click.at;
+ click.shift=mb.mod.shift;
+ selected_track=idx;
+ track_editor->update();
+ //drag select region
+ return;
+
+ }
+
+
+
+ SelectedKey sk;
+ sk.track=idx;
+ sk.key=key;
+ KeyInfo ki;
+ ki.pos= animation->track_get_key_time(idx,key);
+ click.shift=mb.mod.shift;
+ click.selk=sk;
+
+
+ if (!mb.mod.shift && !selection.has(sk))
+ _clear_selection();
+
+ selection.insert(sk,ki);
+
+ click.click=ClickOver::CLICK_MOVE_KEYS;
+ click.at=Point2(mb.x,mb.y);
+ click.to=click.at;
+ update();
+ selected_track=idx;
+ track_editor->update();
+
+ if (_edit_if_single_selection() && mb.mod.command) {
+ edit_button->set_pressed(true);
+ key_editor_tab->show();
+ }
+ } else {
+ //button column
+ int ofsx = size.width - mpos.x;
+ if (ofsx < 0)
+ break;
+/*
+ if (ofsx < remove_icon->get_width()) {
+
+ undo_redo->create_action("Remove Anim Track");
+ undo_redo->add_do_method(animation.ptr(),"remove_track",idx);
+ undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(idx),idx);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_path",idx,animation->track_get_path(idx));
+ //todo interpolation
+ for(int i=0;i<animation->track_get_key_count(idx);i++) {
+
+ Variant v = animation->track_get_key_value(idx,i);
+ float time = animation->track_get_key_time(idx,i);
+ float trans = animation->track_get_key_transition(idx,i);
+
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,time,v);
+ undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",idx,i,trans);
+
+ }
+
+ undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",idx,animation->track_get_interpolation_type(idx));
+ if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
+ undo_redo->add_undo_method(animation.ptr(),"value_track_set_continuous",idx,animation->value_track_is_continuous(idx));
+
+ }
+
+ undo_redo->commit_action();
+
+
+ return;
+ }
+
+ ofsx-=hsep+remove_icon->get_width();
+
+ if (ofsx < move_down_icon->get_width()) {
+
+ if (idx < animation->get_track_count() -1) {
+ undo_redo->create_action("Move Anim Track Down");
+ undo_redo->add_do_method(animation.ptr(),"track_move_up",idx);
+ undo_redo->add_undo_method(animation.ptr(),"track_move_down",idx+1);
+ undo_redo->commit_action();
+ }
+ return;
+ }
+
+ ofsx-=hsep+move_down_icon->get_width();
+
+ if (ofsx < move_up_icon->get_width()) {
+
+ if (idx >0) {
+ undo_redo->create_action("Move Anim Track Up");
+ undo_redo->add_do_method(animation.ptr(),"track_move_down",idx);
+ undo_redo->add_undo_method(animation.ptr(),"track_move_up",idx-1);
+ undo_redo->commit_action();
+ }
+ return;
+ }
+
+
+ ofsx-=hsep*3+move_up_icon->get_width();
+ */
+
+
+ if (ofsx < track_ofs[1]) {
+
+ track_menu->clear();
+ track_menu->set_size(Point2(1,1));
+ static const char *interp_name[2]={"Clamp Loop Interp","Wrap Loop Interp"};
+ for(int i=0;i<2;i++) {
+ track_menu->add_icon_item(wrap_icon[i],interp_name[i]);
+ }
+
+ int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
+ int popup_x = size.width-track_ofs[1];
+
+ track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
+
+
+ wrap_editing=idx;
+ interp_editing=-1;
+ cont_editing=-1;
+
+ track_menu->popup();
+
+ return;
+ }
+
+
+ if (ofsx < track_ofs[2]) {
+
+ track_menu->clear();
+ track_menu->set_size(Point2(1,1));
+ static const char *interp_name[3]={"Nearest","Linear","Cubic"};
+ for(int i=0;i<3;i++) {
+ track_menu->add_icon_item(interp_icon[i],interp_name[i]);
+ }
+
+ int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
+ int popup_x = size.width-track_ofs[2];
+
+ track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
+
+
+ interp_editing=idx;
+ cont_editing=-1;
+ wrap_editing=-1;
+
+ track_menu->popup();
+
+ return;
+ }
+
+ if (ofsx < track_ofs[3]) {
+
+ track_menu->clear();
+ track_menu->set_size(Point2(1,1));
+ String cont_name[3]={TTR("Continuous"),TTR("Discrete"),TTR("Trigger")};
+ for(int i=0;i<3;i++) {
+ track_menu->add_icon_item(cont_icon[i],cont_name[i]);
+ }
+
+
+ int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
+ int popup_x = size.width-track_ofs[3];
+
+ track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
+
+ interp_editing=-1;
+ wrap_editing=-1;
+ cont_editing=idx;
+
+ track_menu->popup();
+
+ return;
+ }
+
+ if (ofsx < track_ofs[4]) {
+
+ Animation::TrackType tt = animation->track_get_type(idx);
+
+ float pos = timeline_pos;
+ int existing = animation->track_find_key(idx,pos,true);
+
+
+
+ Variant newval;
+
+ if (tt==Animation::TYPE_TRANSFORM) {
+ Dictionary d;
+ d["loc"]=Vector3();
+ d["rot"]=Quat();
+ d["scale"]=Vector3();
+ newval=d;
+
+ } else if (tt==Animation::TYPE_METHOD) {
+
+ Dictionary d;
+ d["method"]="";
+ d["args"]=Vector<Variant>();
+
+
+ newval=d;
+ } else if (tt==Animation::TYPE_VALUE) {
+
+ NodePath np;
+ PropertyInfo inf = _find_hint_for_track(idx,np);
+ if (inf.type!=Variant::NIL) {
+
+ Variant::CallError err;
+ newval=Variant::construct(inf.type,NULL,0,err);
+
+ }
+
+ if (newval.get_type()==Variant::NIL) {
+ //popup a new type
+ cvi_track=idx;
+ cvi_pos=pos;
+
+ type_menu->set_pos( get_global_pos() + mpos +ofs );
+ type_menu->popup();
+ return;
+ }
+
+ }
+
+ undo_redo->create_action(TTR("Anim Add Key"));
+
+ undo_redo->add_do_method(animation.ptr(),"track_insert_key",idx,pos,newval,1);
+ undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",idx,pos);
+
+ if (existing!=-1) {
+ Variant v = animation->track_get_key_value(idx,existing);
+ float trans = animation->track_get_key_transition(idx,existing);
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,pos,v,trans);
+ }
+
+ undo_redo->commit_action();
+
+
+ return;
+ }
+
+ }
+
+ } else {
+
+ switch(click.click) {
+ case ClickOver::CLICK_SELECT_KEYS: {
+
+
+ float zoom_scale=_get_zoom_scale();
+ float keys_from = h_scroll->get_value();
+ float keys_to = keys_from + (settings_limit-name_limit) / zoom_scale;
+
+ float from_time = keys_from + ( click.at.x - (name_limit+ofs.x)) / zoom_scale;
+ float to_time = keys_from + (click.to.x - (name_limit+ofs.x)) / zoom_scale;
+
+
+ if (to_time < from_time)
+ SWAP(from_time,to_time);
+
+ if (from_time > keys_to || to_time < keys_from)
+ break;
+
+ if (from_time < keys_from)
+ from_time = keys_from;
+
+ if (to_time >= keys_to)
+ to_time = keys_to;
+
+
+ int from_track = int(click.at.y-ofs.y-h-sep) / h + v_scroll->get_value();
+ int to_track = int(click.to.y-ofs.y-h-sep) / h + v_scroll->get_value();
+ int from_mod = int(click.at.y-ofs.y-sep) % h;
+ int to_mod = int(click.to.y-ofs.y-sep) % h;
+
+ if (to_track < from_track) {
+
+ SWAP(from_track,to_track);
+ SWAP(from_mod,to_mod);
+ }
+
+
+
+
+ if ((from_mod > (h/2)) && ((click.at.y-ofs.y)>=(h+sep))) {
+ from_track++;
+ }
+
+ if (to_mod < h/2) {
+ to_track--;
+ }
+
+ if (from_track>to_track) {
+ if (!click.shift)
+ _clear_selection();
+ _edit_if_single_selection();
+ break;
+ }
+
+ int tracks_from = v_scroll->get_value();
+ int tracks_to = v_scroll->get_value()+fit-1;
+ if (tracks_to>=animation->get_track_count())
+ tracks_to=animation->get_track_count()-1;
+
+ tracks_from=0;
+ tracks_to=animation->get_track_count()-1;
+ if (to_track >tracks_to)
+ to_track = tracks_to;
+ if (from_track<tracks_from)
+ from_track=tracks_from;
+
+ if (from_track > tracks_to || to_track < tracks_from) {
+ if (!click.shift)
+ _clear_selection();
+ _edit_if_single_selection();
+ break;
+ }
+
+ if (!click.shift)
+ _clear_selection();
+
+
+ int higher_track=0x7FFFFFFF;
+ for(int i=from_track;i<=to_track;i++) {
+
+ int kc=animation->track_get_key_count(i);
+ for(int j=0;j<kc;j++) {
+
+ float t = animation->track_get_key_time(i,j);
+ if (t<from_time)
+ continue;
+ if (t>to_time)
+ break;
+
+ if (i<higher_track)
+ higher_track=i;
+
+ SelectedKey sk;
+ sk.track=i;
+ sk.key=j;
+ KeyInfo ki;
+ ki.pos=t;
+ selection[sk]=ki;
+ }
+ }
+
+ if (higher_track!=0x7FFFFFFF) {
+ selected_track=higher_track;
+ track_editor->update();
+ }
+
+
+ _edit_if_single_selection();
+
+
+ } break;
+ case ClickOver::CLICK_MOVE_KEYS: {
+
+ if (selection.empty())
+ break;
+ if (click.at==click.to) {
+
+ if (!click.shift) {
+
+ KeyInfo ki=selection[click.selk];
+ _clear_selection();
+ selection[click.selk]=ki;
+ _edit_if_single_selection();
+ }
+
+ break;
+ }
+
+ float from_t = 1e20;
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
+ float t = animation->track_get_key_time(E->key().track,E->key().key);
+ if (t<from_t)
+ from_t=t;
+
+ }
+
+ float motion = from_t+(click.to.x - click.at.x)/_get_zoom_scale();
+ if (step->get_value())
+ motion = Math::stepify(motion,step->get_value());
+
+
+
+
+ undo_redo->create_action(TTR("Anim Move Keys"));
+
+ List<_AnimMoveRestore> to_restore;
+
+ // 1-remove the keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ undo_redo->add_do_method(animation.ptr(),"track_remove_key",E->key().track,E->key().key);
+ }
+ // 2- remove overlapped keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float newtime = E->get().pos-from_t+motion;
+ int idx = animation->track_find_key(E->key().track,newtime,true);
+ if (idx==-1)
+ continue;
+ SelectedKey sk;
+ sk.key=idx;
+ sk.track=E->key().track;
+ if (selection.has(sk))
+ continue; //already in selection, don't save
+
+ undo_redo->add_do_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newtime);
+ _AnimMoveRestore amr;
+
+ amr.key=animation->track_get_key_value(E->key().track,idx);
+ amr.track=E->key().track;
+ amr.time=newtime;
+ amr.transition=animation->track_get_key_transition(E->key().track,idx);
+
+ to_restore.push_back(amr);
+
+ }
+
+ // 3-move the keys (re insert them)
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float newpos=E->get().pos-from_t+motion;
+ /*
+ if (newpos<0)
+ continue; //no add at the begining
+ */
+ undo_redo->add_do_method(animation.ptr(),"track_insert_key",E->key().track,newpos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
+
+ }
+
+ // 4-(undo) remove inserted keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float newpos=E->get().pos+-from_t+motion;
+ /*
+ if (newpos<0)
+ continue; //no remove what no inserted
+ */
+ undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newpos);
+
+ }
+
+ // 5-(undo) reinsert keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
+
+ }
+
+ // 6-(undo) reinsert overlapped keys
+ for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
+
+ _AnimMoveRestore &amr = E->get();
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
+
+ }
+
+ // 6-(undo) reinsert overlapped keys
+ for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
+
+ _AnimMoveRestore &amr = E->get();
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
+
+ }
+
+ undo_redo->add_do_method(this,"_clear_selection_for_anim",animation);
+ undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation);
+
+ // 7-reselect
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float oldpos=E->get().pos;
+ float newpos=oldpos-from_t+motion;
+ //if (newpos>=0)
+ undo_redo->add_do_method(this,"_select_at_anim",animation,E->key().track,newpos);
+ undo_redo->add_undo_method(this,"_select_at_anim",animation,E->key().track,oldpos);
+
+ }
+
+ undo_redo->commit_action();
+ _edit_if_single_selection();
+
+ } break;
+ default: {}
+ }
+
+ //button released
+ click.click=ClickOver::CLICK_NONE;
+ track_editor->update();
+
+
+ }
+ }
+
+ } break;
+
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mb = p_input.mouse_motion;
+
+ mouse_over.over=MouseOver::OVER_NONE;
+ mouse_over.track=-1;
+ te->update();
+ track_editor->set_tooltip("");
+
+ if (!track_editor->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
+ track_editor->call_deferred("grab_focus");
+
+
+ if (click.click!=ClickOver::CLICK_NONE) {
+
+ switch(click.click) {
+ case ClickOver::CLICK_RESIZE_NAMES: {
+
+
+ float base = click.at.y;
+ float clickp = click.at.x-ofs.x;
+ float dif = base - clickp;
+
+ float target = mb.x+dif-ofs.x;
+
+ float ratio = target / settings_limit;
+
+ if (ratio>0.9)
+ ratio=0.9;
+ else if (ratio<0.2)
+ ratio=0.2;
+
+ name_column_ratio=ratio;
+
+
+ } break;
+ case ClickOver::CLICK_DRAG_TIMELINE: {
+
+ Point2 mpos = Point2(mb.x,mb.y)-ofs;
+ /*
+ if (mpos.x<name_limit)
+ mpos.x=name_limit;
+ if (mpos.x>settings_limit)
+ mpos.x=settings_limit;
+ */
+
+
+ //int zoomw = settings_limit-name_limit;
+ float scale = _get_zoom_scale();
+ float pos = h_scroll->get_value() + (mpos.x-name_limit) / scale;
+ if (animation->get_step()) {
+ pos=Math::stepify(pos,animation->get_step());
+
+ }
+ if (pos<0)
+ pos=0;
+ if (pos>=animation->get_length())
+ pos=animation->get_length();
+
+ if (pos < h_scroll->get_value()) {
+ h_scroll->set_value(pos);
+ } else if (pos > h_scroll->get_value() + (settings_limit - name_limit) / scale) {
+ h_scroll->set_value( pos - (settings_limit - name_limit) / scale );
+ }
+
+ timeline_pos=pos;
+ emit_signal("timeline_changed",pos,true);
+
+
+
+ } break;
+ case ClickOver::CLICK_SELECT_KEYS: {
+
+ click.to=Point2(mb.x,mb.y);
+ if (click.to.y<h && click.at.y>h && mb.relative_y<0) {
+
+ float prev = v_scroll->get_value();
+ v_scroll->set_value( v_scroll->get_value() -1 );
+ if (prev!=v_scroll->get_value())
+ click.at.y+=h;
+
+
+ }
+ if (click.to.y>size.height && click.at.y<size.height && mb.relative_y>0) {
+
+ float prev = v_scroll->get_value();
+ v_scroll->set_value( v_scroll->get_value() +1 );
+ if (prev!=v_scroll->get_value())
+ click.at.y-=h;
+ }
+
+ } break;
+ case ClickOver::CLICK_MOVE_KEYS: {
+
+ click.to=Point2(mb.x,mb.y);
+ } break;
+ default: {}
+ }
+
+ return;
+ } else if (mb.button_mask&BUTTON_MASK_MIDDLE) {
+
+ int rel = mb.relative_x;
+ float relf = rel / _get_zoom_scale();
+ h_scroll->set_value( h_scroll->get_value() - relf );
+ }
+
+ if (mb.button_mask==0) {
+
+
+ Point2 mpos = Point2(mb.x,mb.y)-ofs;
+
+ if (mpos.y < h ) {
+#if 0
+ //seek
+ //int zoomw = settings_limit-name_limit;
+ float scale = _get_zoom_scale();
+ float pos = h_scroll->get_val() + (mpos.y-name_limit) / scale;
+ if (pos<0 )
+ pos=0;
+ if (pos>=animation->get_length())
+ pos=animation->get_length();
+ timeline->set_val(pos);
+#endif
+ return;
+ }
+
+ mpos.y -= h;
+
+ int idx = mpos.y / h;
+ idx+=v_scroll->get_value();
+ if (idx <0 || idx>=animation->get_track_count())
+ break;
+
+ mouse_over.track=idx;
+
+ if (mpos.x < name_limit) {
+ //name column
+
+
+ mouse_over.over=MouseOver::OVER_NAME;
+
+ } else if (mpos.x < settings_limit) {
+
+ float pos = mpos.x - name_limit;
+ pos/=_get_zoom_scale();
+ pos+=h_scroll->get_value();
+ float w_time = (type_icon[0]->get_width() / _get_zoom_scale())/2.0;
+
+ int kidx = animation->track_find_key(idx,pos);
+ int kidx_n = kidx+1;
+
+ bool found = false;
+
+ if (kidx>=0 && kidx<animation->track_get_key_count(idx)) {
+
+ float kpos = animation->track_get_key_time(idx,kidx);
+ if (ABS(pos-kpos)<=w_time) {
+
+ mouse_over.over=MouseOver::OVER_KEY;
+ mouse_over.track=idx;
+ mouse_over.over_key=kidx;
+ found=true;
+ }
+ }
+
+ if (!found && kidx_n>=0 && kidx_n<animation->track_get_key_count(idx)) {
+
+ float kpos = animation->track_get_key_time(idx,kidx_n);
+ if (ABS(pos-kpos)<=w_time) {
+
+ mouse_over.over=MouseOver::OVER_KEY;
+ mouse_over.track=idx;
+ mouse_over.over_key=kidx_n;
+ found=true;
+ }
+ }
+
+
+ if (found) {
+
+ 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: {
+
+ Dictionary d = animation->track_get_key_value(idx,mouse_over.over_key);
+ if (d.has("loc"))
+ text+="loc: "+String(d["loc"])+"\n";
+ if (d.has("rot"))
+ text+="rot: "+String(d["rot"])+"\n";
+ if (d.has("scale"))
+ text+="scale: "+String(d["scale"])+"\n";
+ } break;
+ case Animation::TYPE_VALUE: {
+
+ 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: {
+
+
+ Dictionary d = animation->track_get_key_value(idx,mouse_over.over_key);
+ if (d.has("method"))
+ text+=String(d["method"]);
+ text+="(";
+ Vector<Variant> args;
+ if (d.has("args"))
+ args=d["args"];
+ for(int i=0;i<args.size();i++) {
+
+ if (i>0)
+ text+=", ";
+ text+=String(args[i]);
+ }
+ text+=")\n";
+
+ } break;
+ }
+ text+="easing: "+rtos(animation->track_get_key_transition(idx,mouse_over.over_key));
+
+
+
+ track_editor->set_tooltip(text);
+ return;
+
+ }
+
+ } else {
+ //button column
+ int ofsx = size.width - mpos.x;
+ if (ofsx < 0)
+ break;
+/*
+ if (ofsx < remove_icon->get_width()) {
+
+ mouse_over.over=MouseOver::OVER_REMOVE;
+
+ return;
+ }
+
+ ofsx-=hsep+remove_icon->get_width();
+
+ if (ofsx < move_down_icon->get_width()) {
+
+ mouse_over.over=MouseOver::OVER_DOWN;
+ return;
+ }
+
+ ofsx-=hsep+move_down_icon->get_width();
+
+ if (ofsx < move_up_icon->get_width()) {
+
+ mouse_over.over=MouseOver::OVER_UP;
+ return;
+ }
+
+ ofsx-=hsep*3+move_up_icon->get_width();
+
+ */
+
+ if (ofsx < down_icon->get_width() + wrap_icon[0]->get_width() + hsep*3) {
+
+ mouse_over.over=MouseOver::OVER_WRAP;
+ return;
+ }
+
+ ofsx-=hsep*3+wrap_icon[0]->get_width() + down_icon->get_width();
+
+ if (ofsx < down_icon->get_width() + interp_icon[0]->get_width() + hsep*3) {
+
+ mouse_over.over=MouseOver::OVER_INTERP;
+ return;
+ }
+
+
+ ofsx-=hsep*2+interp_icon[0]->get_width() + down_icon->get_width();
+
+ if (ofsx < down_icon->get_width() + cont_icon[0]->get_width() +hsep*3) {
+
+ mouse_over.over=MouseOver::OVER_VALUE;
+ return;
+ }
+
+ ofsx-=hsep*3+cont_icon[0]->get_width() + down_icon->get_width();
+
+ if (ofsx < add_key_icon->get_width()) {
+
+ mouse_over.over=MouseOver::OVER_ADD_KEY;
+ return;
+ }
+
+
+ }
+
+ }
+
+ } break;
+
+ }
+}
+
+void AnimationKeyEditor::_notification(int p_what) {
+
+
+ switch(p_what) {
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+
+ EditorNode::get_singleton()->update_keying();
+ emit_signal("keying_changed");
+ } 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"));
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue","EditorIcons"),"Add Normal Track",ADD_TRACK_MENU_ADD_VALUE_TRACK);
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform","EditorIcons"),"Add Transform Track",ADD_TRACK_MENU_ADD_TRANSFORM_TRACK);
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall","EditorIcons"),"Add Call Func Track",ADD_TRACK_MENU_ADD_CALL_TRACK);
+
+ menu_track->set_icon(get_icon("Tools","EditorIcons"));
+ menu_track->get_popup()->add_item(TTR("Scale Selection"),TRACK_MENU_SCALE);
+ menu_track->get_popup()->add_item(TTR("Scale From Cursor"),TRACK_MENU_SCALE_PIVOT);
+ menu_track->get_popup()->add_separator();
+ menu_track->get_popup()->add_item(TTR("Duplicate Selection"),TRACK_MENU_DUPLICATE);
+ menu_track->get_popup()->add_item(TTR("Duplicate Transposed"),TRACK_MENU_DUPLICATE_TRANSPOSE);
+ menu_track->get_popup()->add_separator();
+ menu_track->get_popup()->add_item(TTR("Goto Next Step"),TRACK_MENU_NEXT_STEP,KEY_MASK_CMD|KEY_RIGHT);
+ menu_track->get_popup()->add_item(TTR("Goto Prev Step"),TRACK_MENU_PREV_STEP,KEY_MASK_CMD|KEY_LEFT);
+ menu_track->get_popup()->add_separator();
+ PopupMenu *tpp = memnew( PopupMenu );
+ tpp->add_item(TTR("Linear"),TRACK_MENU_SET_ALL_TRANS_LINEAR);
+ tpp->add_item(TTR("Constant"),TRACK_MENU_SET_ALL_TRANS_CONSTANT);
+ tpp->add_item(TTR("In"),TRACK_MENU_SET_ALL_TRANS_IN);
+ tpp->add_item(TTR("Out"),TRACK_MENU_SET_ALL_TRANS_OUT);
+ tpp->add_item(TTR("In-Out"),TRACK_MENU_SET_ALL_TRANS_INOUT);
+ tpp->add_item(TTR("Out-In"),TRACK_MENU_SET_ALL_TRANS_OUTIN);
+ tpp->set_name(TTR("Transitions"));
+ tpp->connect("id_pressed",this,"_menu_track");
+ optimize_dialog->connect("confirmed",this,"_animation_optimize");
+
+ menu_track->get_popup()->add_child(tpp);
+ //menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
+ //menu_track->get_popup()->add_separator();
+ menu_track->get_popup()->add_item(TTR("Optimize Animation"),TRACK_MENU_OPTIMIZE);
+ menu_track->get_popup()->add_item(TTR("Clean-Up Animation"),TRACK_MENU_CLEAN_UP);
+
+ curve_linear->set_icon(get_icon("CurveLinear","EditorIcons"));
+ curve_in->set_icon(get_icon("CurveIn","EditorIcons"));
+ curve_out->set_icon(get_icon("CurveOut","EditorIcons"));
+ curve_inout->set_icon(get_icon("CurveInOut","EditorIcons"));
+ curve_outin->set_icon(get_icon("CurveOutIn","EditorIcons"));
+ curve_constant->set_icon(get_icon("CurveConstant","EditorIcons"));
+
+ curve_linear->connect("pressed",this,"_menu_track",varray(CURVE_SET_LINEAR));
+ curve_in->connect("pressed",this,"_menu_track",varray(CURVE_SET_IN));
+ curve_out->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUT));
+ curve_inout->connect("pressed",this,"_menu_track",varray(CURVE_SET_INOUT));
+ curve_outin->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUTIN));
+ curve_constant->connect("pressed",this,"_menu_track",varray(CURVE_SET_CONSTANT));
+
+
+ move_up_button->set_icon(get_icon("MoveUp","EditorIcons"));
+ move_down_button->set_icon(get_icon("MoveDown","EditorIcons"));
+ remove_button->set_icon(get_icon("Remove","EditorIcons"));
+ edit_button->set_icon(get_icon("EditKey","EditorIcons"));
+ edit_button->connect("pressed",this,"_toggle_edit_curves");
+
+ loop->set_icon(get_icon("Loop","EditorIcons"));
+ curve_edit->connect("transition_changed",this,"_curve_transition_changed");
+
+ //edit_button->add_color_override("font_color",get_color("font_color","Tree"));
+ //edit_button->add_color_override("font_color_hover",get_color("font_color","Tree"));
+
+ {
+
+ right_data_size_cache=0;
+ int hsep = get_constant("hseparation","Tree");
+ Ref<Texture> remove_icon = get_icon("Remove","EditorIcons");
+ Ref<Texture> move_up_icon = get_icon("MoveUp","EditorIcons");
+ Ref<Texture> move_down_icon = get_icon("MoveDown","EditorIcons");
+ Ref<Texture> down_icon = get_icon("select_arrow","Tree");
+ Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
+ Ref<Texture> interp_icon[3]={
+ get_icon("InterpRaw","EditorIcons"),
+ get_icon("InterpLinear","EditorIcons"),
+ get_icon("InterpCubic","EditorIcons")
+ };
+ Ref<Texture> cont_icon[3]={
+ get_icon("TrackContinuous","EditorIcons"),
+ get_icon("TrackDiscrete","EditorIcons"),
+ get_icon("TrackTrigger","EditorIcons")
+ };
+
+ Ref<Texture> wrap_icon[2]={
+ get_icon("InterpWrapClamp","EditorIcons"),
+ get_icon("InterpWrapLoop","EditorIcons"),
+ };
+
+ //right_data_size_cache = remove_icon->get_width() + move_up_icon->get_width() + move_down_icon->get_width() + down_icon->get_width() *2 + interp_icon[0]->get_width() + cont_icon[0]->get_width() + add_key_icon->get_width() + hsep*11;
+ right_data_size_cache = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + wrap_icon[0]->get_width() + hsep*8;
+
+
+ }
+ call_select->connect("selected",this,"_add_call_track");
+ //rename_anim->set_icon( get_icon("Rename","EditorIcons") );
+/*
+ edit_anim->set_icon( get_icon("Edit","EditorIcons") );
+ blend_anim->set_icon( get_icon("Blend","EditorIcons") );
+ play->set_icon( get_icon("Play","EditorIcons") );
+ stop->set_icon( get_icon("Stop","EditorIcons") );
+ pause->set_icon( get_icon("Pause","EditorIcons") );
+*/
+ //menu->set_icon(get_icon("Animation","EditorIcons"));
+ //play->set_icon(get_icon("AnimationPlay","EditorIcons"));
+ //menu->set_icon(get_icon("Animation","EditorIcons"));
+ _update_menu();
+
+ } break;
+
+
+ }
+
+}
+
+
+
+void AnimationKeyEditor::_scroll_changed(double) {
+
+ if (te_drawing)
+ return;
+
+ track_editor->update();
+}
+
+
+
+void AnimationKeyEditor::_update_paths() {
+
+ if (animation.is_valid()) {
+ //timeline->set_max(animation->get_length());
+ //timeline->set_step(0.01);
+ track_editor->update();
+ length->set_value(animation->get_length());
+ step->set_value(animation->get_step());
+ }
+}
+
+
+void AnimationKeyEditor::_root_removed() {
+
+ root=NULL;
+}
+
+void AnimationKeyEditor::_update_menu() {
+
+
+ updating=true;
+
+ if (animation.is_valid()) {
+
+ length->set_value(animation->get_length());
+ loop->set_pressed(animation->has_loop());
+ step->set_value(animation->get_step());
+ }
+
+ track_editor->update();
+ updating=false;
+
+}
+void AnimationKeyEditor::_clear_selection() {
+
+ selection.clear();
+ key_edit->animation=Ref<Animation>();
+ key_edit->track=0;
+ key_edit->key_ofs=0;
+ key_edit->hint=PropertyInfo();
+ key_edit->base=NodePath();
+ key_edit->notify_change();
+
+}
+
+
+void AnimationKeyEditor::set_animation(const Ref<Animation>& p_anim) {
+
+ if (animation.is_valid())
+ animation->disconnect("changed",this,"_update_paths");
+ animation=p_anim;
+ if (animation.is_valid())
+ animation->connect("changed",this,"_update_paths");
+
+ timeline_pos=0;
+ _clear_selection();
+ _update_paths();
+
+ _update_menu();
+ selected_track=-1;
+ _edit_if_single_selection();
+
+ EditorNode::get_singleton()->update_keying();
+}
+
+void AnimationKeyEditor::set_root(Node *p_root) {
+
+ if (root)
+ root->disconnect("tree_exited",this,"_root_removed");
+
+ root=p_root;
+
+ if (root)
+ root->connect("tree_exited",this,"_root_removed",make_binds(),CONNECT_ONESHOT);
+
+
+}
+
+Node *AnimationKeyEditor::get_root() const {
+
+ return root;
+}
+
+
+
+
+
+
+void AnimationKeyEditor::update_keying() {
+
+ bool keying_enabled=is_visible_in_tree() && animation.is_valid();
+
+ if (keying_enabled==keying)
+ return;
+
+ keying=keying_enabled;
+ _update_menu();
+ emit_signal("keying_changed");
+
+}
+
+bool AnimationKeyEditor::has_keying() const {
+
+ return keying;
+}
+
+void AnimationKeyEditor::_query_insert(const InsertData& p_id) {
+
+
+ if (insert_frame!=Engine::get_singleton()->get_frames_drawn()) {
+ //clear insert list for the frame if frame changed
+ if (insert_confirm->is_visible_in_tree())
+ return; //do nothing
+ insert_data.clear();
+ insert_query=false;
+ }
+ insert_frame=Engine::get_singleton()->get_frames_drawn();
+
+ for (List<InsertData>::Element *E=insert_data.front();E;E=E->next()) {
+ //prevent insertion of multiple tracks
+ if (E->get().path==p_id.path)
+ return; //already inserted a track for this on this frame
+ }
+
+ insert_data.push_back(p_id);
+
+ if (p_id.track_idx==-1) {
+ if (bool(EDITOR_DEF("editors/animation/confirm_insert_track",true))) {
+ //potential new key, does not exist
+ if (insert_data.size()==1)
+ insert_confirm->set_text(vformat(TTR("Create NEW track for %s and insert key?"),p_id.query));
+ else
+ insert_confirm->set_text(vformat(TTR("Create %d NEW tracks and insert keys?"),insert_data.size()));
+
+ insert_confirm->get_ok()->set_text(TTR("Create"));
+ insert_confirm->popup_centered_minsize();
+ insert_query=true;
+ } else {
+ call_deferred("_insert_delay");
+ insert_queue=true;
+ }
+
+ } else {
+ if (!insert_query && !insert_queue) {
+ call_deferred("_insert_delay");
+ insert_queue=true;
+ }
+ }
+
+}
+
+void AnimationKeyEditor::insert_transform_key(Spatial *p_node,const String& p_sub,const Transform& p_xform) {
+
+ if (!keying)
+ return;
+ if (!animation.is_valid())
+ return;
+
+
+ ERR_FAIL_COND(!root);
+ //let's build a node path
+ String path = root->get_path_to(p_node);
+ if (p_sub!="")
+ path+=":"+p_sub;
+
+ NodePath np=path;
+
+ int track_idx=-1;
+
+ for(int i=0;i<animation->get_track_count();i++) {
+
+ if (animation->track_get_type(i)!=Animation::TYPE_TRANSFORM)
+ continue;
+ if (animation->track_get_path(i)!=np)
+ continue;
+
+ track_idx=i;
+ break;
+ }
+
+ InsertData id;
+ Dictionary val;
+
+ id.path=np;
+ id.track_idx=track_idx;
+ id.value=p_xform;
+ id.type=Animation::TYPE_TRANSFORM;
+ id.query="node '"+p_node->get_name()+"'";
+ id.advance=false;
+
+ //dialog insert
+
+ _query_insert(id);
+
+}
+
+
+void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_property,const Variant& p_value,bool p_only_if_exists) {
+
+ ERR_FAIL_COND(!root);
+ //let's build a node path
+
+ Node *node = p_node;
+
+ String path = root->get_path_to(node);
+
+ for(int i=1;i<history->get_path_size();i++) {
+
+ String prop = history->get_path_property(i);
+ ERR_FAIL_COND(prop=="");
+ path+=":"+prop;
+ }
+
+
+ path+=":"+p_property;
+
+ NodePath np = path;
+
+ //locate track
+
+ int track_idx=-1;
+
+ for(int i=0;i<animation->get_track_count();i++) {
+
+ if (animation->track_get_type(i)!=Animation::TYPE_VALUE)
+ continue;
+ if (animation->track_get_path(i)!=np)
+ continue;
+
+ track_idx=i;
+ break;
+ }
+
+ if (p_only_if_exists && track_idx==-1)
+ return;
+ InsertData id;
+ id.path=np;
+ id.track_idx=track_idx;
+ id.value=p_value;
+ id.type=Animation::TYPE_VALUE;
+ id.query="property '"+p_property+"'";
+ id.advance=false;
+ //dialog insert
+ _query_insert(id);
+
+
+
+}
+
+void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value,bool p_advance) {
+
+ ERR_FAIL_COND(!root);
+ //let's build a node path
+ ERR_FAIL_COND(history->get_path_size()==0);
+ Object *obj = ObjectDB::get_instance(history->get_path_object(0));
+ ERR_FAIL_COND(!obj || !obj->cast_to<Node>());
+
+ Node *node = obj->cast_to<Node>();
+
+ String path = root->get_path_to(node);
+
+ for(int i=1;i<history->get_path_size();i++) {
+
+ String prop = history->get_path_property(i);
+ ERR_FAIL_COND(prop=="");
+ path+=":"+prop;
+ }
+
+
+
+ path+=":"+p_property;
+
+ NodePath np = path;
+
+ //locate track
+
+ int track_idx=-1;
+
+ for(int i=0;i<animation->get_track_count();i++) {
+
+ if (animation->track_get_type(i)!=Animation::TYPE_VALUE)
+ continue;
+ if (animation->track_get_path(i)!=np)
+ continue;
+
+ track_idx=i;
+ break;
+ }
+
+ InsertData id;
+ id.path=np;
+ id.track_idx=track_idx;
+ id.value=p_value;
+ id.type=Animation::TYPE_VALUE;
+ id.query="property '"+p_property+"'";
+ id.advance=p_advance;
+ //dialog insert
+ _query_insert(id);
+
+
+
+}
+
+void AnimationKeyEditor::_confirm_insert_list() {
+
+
+ undo_redo->create_action(TTR("Anim Create & Insert"));
+
+ int last_track = animation->get_track_count();
+ while(insert_data.size()) {
+
+ last_track=_confirm_insert(insert_data.front()->get(),last_track);
+ insert_data.pop_front();
+ }
+
+ undo_redo->commit_action();
+}
+
+int AnimationKeyEditor::_confirm_insert(InsertData p_id,int p_last_track) {
+
+ if (p_last_track==-1)
+ p_last_track=animation->get_track_count();
+
+ bool created=false;
+ if (p_id.track_idx<0) {
+
+ created=true;
+ undo_redo->create_action(TTR("Anim Insert Track & Key"));
+ Animation::UpdateMode update_mode=Animation::UPDATE_DISCRETE;
+
+ if (p_id.type==Animation::TYPE_VALUE) {
+ //wants a new tack
+
+ {
+ //shitty hack
+ NodePath np;
+ animation->add_track(p_id.type);
+ animation->track_set_path(animation->get_track_count()-1,p_id.path);
+ PropertyInfo h = _find_hint_for_track(animation->get_track_count()-1,np);
+ animation->remove_track(animation->get_track_count()-1); //hack
+
+ if ( h.type==Variant::REAL ||
+ h.type==Variant::VECTOR2 ||
+ h.type==Variant::RECT2 ||
+ h.type==Variant::VECTOR3 ||
+ h.type==Variant::RECT3 ||
+ h.type==Variant::QUAT ||
+ h.type==Variant::COLOR ||
+ h.type==Variant::TRANSFORM ) {
+
+ update_mode=Animation::UPDATE_CONTINUOUS;
+ }
+
+ if (h.usage&PROPERTY_USAGE_ANIMATE_AS_TRIGGER) {
+ update_mode=Animation::UPDATE_TRIGGER;
+ }
+ }
+ }
+
+ p_id.track_idx=p_last_track;
+
+ undo_redo->add_do_method(animation.ptr(),"add_track",p_id.type);
+ undo_redo->add_do_method(animation.ptr(),"track_set_path",p_id.track_idx,p_id.path);
+ if (p_id.type==Animation::TYPE_VALUE)
+ undo_redo->add_do_method(animation.ptr(),"value_track_set_update_mode",p_id.track_idx,update_mode);
+
+ } else {
+ undo_redo->create_action(TTR("Anim Insert Key"));
+ }
+
+ float time = timeline_pos;
+ Variant value;
+
+
+ switch(p_id.type) {
+
+ case Animation::TYPE_VALUE: {
+
+ value = p_id.value;
+
+
+ } break;
+ case Animation::TYPE_TRANSFORM: {
+
+
+ Transform tr = p_id.value;
+ Dictionary d;
+ d["loc"]=tr.origin;
+ d["scale"]=tr.basis.get_scale();
+ d["rot"]=Quat(tr.basis);//.orthonormalized();
+ value=d;
+ } break;
+ default:{}
+ }
+
+
+
+ undo_redo->add_do_method(animation.ptr(),"track_insert_key",p_id.track_idx,time,value);
+
+ if (created) {
+
+ //just remove the track
+ undo_redo->add_undo_method(animation.ptr(),"remove_track",p_last_track);
+ p_last_track++;
+ } else {
+
+ undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",p_id.track_idx,time);
+ int existing = animation->track_find_key(p_id.track_idx,time,true);
+ if (existing!=-1) {
+ Variant v = animation->track_get_key_value(p_id.track_idx,existing);
+ float trans = animation->track_get_key_transition(p_id.track_idx,existing);
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",p_id.track_idx,time,v,trans);
+ }
+ }
+
+ undo_redo->add_do_method(this,"update");
+ undo_redo->add_undo_method(this,"update");
+ undo_redo->add_do_method(track_editor,"update");
+ undo_redo->add_undo_method(track_editor,"update");
+ undo_redo->add_do_method(track_pos,"update");
+ undo_redo->add_undo_method(track_pos,"update");
+
+ undo_redo->commit_action();
+
+ return p_last_track;
+
+}
+
+
+
+
+Ref<Animation> AnimationKeyEditor::get_current_animation() const {
+
+ return animation;
+}
+
+void AnimationKeyEditor::_animation_len_changed(float p_len) {
+
+
+ if (updating)
+ return;
+
+ if (!animation.is_null()) {
+
+ undo_redo->create_action(TTR("Change Anim Len"));
+ undo_redo->add_do_method(animation.ptr(),"set_length",p_len);
+ undo_redo->add_undo_method(animation.ptr(),"set_length",animation->get_length());
+ undo_redo->add_do_method(this,"_animation_len_update");
+ undo_redo->add_undo_method(this,"_animation_len_update");
+ undo_redo->commit_action();
+ }
+}
+
+void AnimationKeyEditor::_animation_len_update() {
+
+ if (!animation.is_null())
+ emit_signal(alc,animation->get_length());
+}
+
+void AnimationKeyEditor::_animation_changed() {
+ if (updating)
+ return;
+ _update_menu();
+
+}
+
+void AnimationKeyEditor::_animation_loop_changed() {
+
+ if (updating)
+ return;
+
+ if (!animation.is_null()) {
+
+ undo_redo->create_action(TTR("Change Anim Loop"));
+ undo_redo->add_do_method(animation.ptr(),"set_loop",loop->is_pressed());
+ undo_redo->add_undo_method(animation.ptr(),"set_loop",!loop->is_pressed());
+ undo_redo->commit_action();
+ }
+
+}
+
+
+void AnimationKeyEditor::_create_value_item(int p_type) {
+
+ undo_redo->create_action(TTR("Anim Create Typed Value Key"));
+
+ Variant::CallError ce;
+ Variant v = Variant::construct(Variant::Type(p_type),NULL,0,ce);
+ undo_redo->add_do_method(animation.ptr(),"track_insert_key",cvi_track,cvi_pos,v);
+ undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",cvi_track,cvi_pos);
+
+ int existing = animation->track_find_key(cvi_track,cvi_pos,true);
+
+ if (existing!=-1) {
+ Variant v = animation->track_get_key_value(cvi_track,existing);
+ float trans = animation->track_get_key_transition(cvi_track,existing);
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",cvi_track,cvi_pos,v,trans);
+ }
+
+ undo_redo->commit_action();
+
+}
+
+
+void AnimationKeyEditor::set_anim_pos(float p_pos) {
+
+ if (animation.is_null())
+ return;
+ timeline_pos=p_pos;
+ update();
+ track_pos->update();
+ track_editor->update();
+}
+
+void AnimationKeyEditor::_pane_drag(const Point2& p_delta) {
+
+ Size2 ecs = ec->get_custom_minimum_size();
+ ecs.y-=p_delta.y;
+ if (ecs.y<100)
+ ecs.y=100;
+ ec->set_custom_minimum_size(ecs);
+
+}
+
+void AnimationKeyEditor::_insert_delay() {
+
+ if (insert_query) {
+ //discard since it's entered into query mode
+ insert_queue=false;
+ return;
+ }
+
+ undo_redo->create_action(TTR("Anim Insert"));
+
+ int last_track = animation->get_track_count();
+ bool advance=false;
+ while(insert_data.size()) {
+
+ if (insert_data.front()->get().advance)
+ advance=true;
+ last_track=_confirm_insert(insert_data.front()->get(),last_track);
+ insert_data.pop_front();
+ }
+
+ undo_redo->commit_action();
+
+ if (advance) {
+ float step = animation->get_step();
+ if (step==0)
+ step=1;
+
+ float pos=timeline_pos;
+
+ pos=Math::stepify(pos+step,step);
+ if (pos>animation->get_length())
+ pos=animation->get_length();
+ timeline_pos=pos;
+ track_pos->update();
+ emit_signal("timeline_changed",pos,true);
+ }
+ insert_queue=false;
+}
+
+void AnimationKeyEditor::_step_changed(float p_len) {
+
+ updating=true;
+ if (!animation.is_null()) {
+ animation->set_step(p_len);
+ emit_signal("animation_step_changed",animation->get_step());
+ }
+ updating=false;
+}
+
+void AnimationKeyEditor::_scale() {
+
+
+ if (selection.empty())
+ return;
+
+
+ float from_t = 1e20;
+ float to_t = -1e20;
+ float len = -1e20;
+ float pivot=0;
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
+ float t = animation->track_get_key_time(E->key().track,E->key().key);
+ if (t<from_t)
+ from_t=t;
+ if (t>to_t)
+ to_t=t;
+
+ }
+
+ len=to_t-from_t;
+ if (last_menu_track_opt==TRACK_MENU_SCALE_PIVOT) {
+ pivot = timeline_pos;
+
+ } else {
+
+ pivot=from_t;
+
+ }
+
+ float s = scale->get_value();
+ if (s==0) {
+ ERR_PRINT("Can't scale to 0");
+ }
+
+
+
+ undo_redo->create_action(TTR("Anim Scale Keys"));
+
+ List<_AnimMoveRestore> to_restore;
+
+ // 1-remove the keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ undo_redo->add_do_method(animation.ptr(),"track_remove_key",E->key().track,E->key().key);
+ }
+ // 2- remove overlapped keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float newtime = (E->get().pos-from_t)*s+from_t;
+ int idx = animation->track_find_key(E->key().track,newtime,true);
+ if (idx==-1)
+ continue;
+ SelectedKey sk;
+ sk.key=idx;
+ sk.track=E->key().track;
+ if (selection.has(sk))
+ continue; //already in selection, don't save
+
+ undo_redo->add_do_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newtime);
+ _AnimMoveRestore amr;
+
+ amr.key=animation->track_get_key_value(E->key().track,idx);
+ amr.track=E->key().track;
+ amr.time=newtime;
+ amr.transition=animation->track_get_key_transition(E->key().track,idx);
+
+ to_restore.push_back(amr);
+
+ }
+
+#define _NEW_POS(m_ofs) (((s>0)?m_ofs:from_t+(len-(m_ofs-from_t)))-pivot)*ABS(s)+from_t
+ // 3-move the keys (re insert them)
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float newpos=_NEW_POS(E->get().pos);
+ undo_redo->add_do_method(animation.ptr(),"track_insert_key",E->key().track,newpos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
+
+ }
+
+ // 4-(undo) remove inserted keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float newpos=_NEW_POS(E->get().pos);
+ undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newpos);
+
+ }
+
+ // 5-(undo) reinsert keys
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
+
+ }
+
+ // 6-(undo) reinsert overlapped keys
+ for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
+
+ _AnimMoveRestore &amr = E->get();
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
+
+ }
+
+ // 6-(undo) reinsert overlapped keys
+ for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
+
+ _AnimMoveRestore &amr = E->get();
+ undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
+
+ }
+
+ undo_redo->add_do_method(this,"_clear_selection_for_anim",animation);
+ undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation);
+
+ // 7-reselect
+
+ for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
+
+ float oldpos=E->get().pos;
+ float newpos=_NEW_POS(oldpos);
+ if (newpos>=0)
+ undo_redo->add_do_method(this,"_select_at_anim",animation,E->key().track,newpos);
+ undo_redo->add_undo_method(this,"_select_at_anim",animation,E->key().track,oldpos);
+
+ }
+#undef _NEW_POS
+ undo_redo->commit_action();
+
+}
+
+
+void AnimationKeyEditor::_add_call_track(const NodePath& p_base) {
+
+
+ Node* base = EditorNode::get_singleton()->get_edited_scene();
+ if (!base)
+ return;
+ Node* from=base->get_node(p_base);
+ if (!from || !root)
+ return;
+
+ NodePath path = root->get_path_to(from);
+
+ //print_line("root: "+String(root->get_path()));
+ //print_line("path: "+String(path));
+
+ undo_redo->create_action(TTR("Anim Add Call Track"));
+ undo_redo->add_do_method(animation.ptr(),"add_track",Animation::TYPE_METHOD);
+ undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),path);
+ undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
+ undo_redo->commit_action();
+
+}
+
+void AnimationKeyEditor::cleanup() {
+
+ set_animation(Ref<Animation>());
+}
+
+void AnimationKeyEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_root_removed"),&AnimationKeyEditor::_root_removed);
+ ClassDB::bind_method(D_METHOD("_scale"),&AnimationKeyEditor::_scale);
+ ClassDB::bind_method(D_METHOD("set_root"),&AnimationKeyEditor::set_root);
+
+
+ //ClassDB::bind_method(D_METHOD("_confirm_insert"),&AnimationKeyEditor::_confirm_insert);
+ ClassDB::bind_method(D_METHOD("_confirm_insert_list"),&AnimationKeyEditor::_confirm_insert_list);
+
+
+
+ ClassDB::bind_method(D_METHOD("_update_paths"),&AnimationKeyEditor::_update_paths);
+ ClassDB::bind_method(D_METHOD("_track_editor_draw"),&AnimationKeyEditor::_track_editor_draw);
+
+
+
+
+ ClassDB::bind_method(D_METHOD("_animation_changed"),&AnimationKeyEditor::_animation_changed);
+ ClassDB::bind_method(D_METHOD("_scroll_changed"),&AnimationKeyEditor::_scroll_changed);
+ ClassDB::bind_method(D_METHOD("_track_editor_gui_input"),&AnimationKeyEditor::_track_editor_gui_input);
+ ClassDB::bind_method(D_METHOD("_track_name_changed"),&AnimationKeyEditor::_track_name_changed);
+ ClassDB::bind_method(D_METHOD("_track_menu_selected"),&AnimationKeyEditor::_track_menu_selected);
+ ClassDB::bind_method(D_METHOD("_menu_add_track"),&AnimationKeyEditor::_menu_add_track);
+ ClassDB::bind_method(D_METHOD("_menu_track"),&AnimationKeyEditor::_menu_track);
+ ClassDB::bind_method(D_METHOD("_clear_selection_for_anim"),&AnimationKeyEditor::_clear_selection_for_anim);
+ ClassDB::bind_method(D_METHOD("_select_at_anim"),&AnimationKeyEditor::_select_at_anim);
+ ClassDB::bind_method(D_METHOD("_track_pos_draw"),&AnimationKeyEditor::_track_pos_draw);
+ ClassDB::bind_method(D_METHOD("_insert_delay"),&AnimationKeyEditor::_insert_delay);
+ ClassDB::bind_method(D_METHOD("_step_changed"),&AnimationKeyEditor::_step_changed);
+
+
+ ClassDB::bind_method(D_METHOD("_animation_loop_changed"),&AnimationKeyEditor::_animation_loop_changed);
+ ClassDB::bind_method(D_METHOD("_animation_len_changed"),&AnimationKeyEditor::_animation_len_changed);
+ ClassDB::bind_method(D_METHOD("_create_value_item"),&AnimationKeyEditor::_create_value_item);
+ ClassDB::bind_method(D_METHOD("_pane_drag"),&AnimationKeyEditor::_pane_drag);
+
+ ClassDB::bind_method(D_METHOD("_animation_len_update"),&AnimationKeyEditor::_animation_len_update);
+
+ ClassDB::bind_method(D_METHOD("set_animation"),&AnimationKeyEditor::set_animation);
+ ClassDB::bind_method(D_METHOD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize);
+ ClassDB::bind_method(D_METHOD("_curve_transition_changed"),&AnimationKeyEditor::_curve_transition_changed);
+ ClassDB::bind_method(D_METHOD("_toggle_edit_curves"),&AnimationKeyEditor::_toggle_edit_curves);
+ ClassDB::bind_method(D_METHOD("_add_call_track"),&AnimationKeyEditor::_add_call_track);
+
+
+ ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
+ ADD_SIGNAL( MethodInfo("keying_changed" ) );
+ ADD_SIGNAL( MethodInfo("timeline_changed", PropertyInfo(Variant::REAL,"pos"), PropertyInfo(Variant::BOOL,"drag") ) );
+ 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() {
+
+ alc="animation_len_changed";
+ editor_selection=EditorNode::get_singleton()->get_editor_selection();
+
+ selected_track=-1;
+ updating=false;
+ te_drawing=false;
+ 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_value(0);
+
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ add_child(hb);
+
+
+ root=NULL;
+ //menu = memnew( MenuButton );
+ //menu->set_flat(true);
+ //menu->set_pos(Point2());
+ //add_child(menu);
+
+ zoomicon = memnew( TextureRect );
+ hb->add_child(zoomicon);
+ zoomicon->set_tooltip(TTR("Animation zoom."));
+
+ zoom = memnew( HSlider );
+ //hb->add_child(zoom);
+ zoom->set_step(0.01);
+ zoom->set_min(0.0);
+ zoom->set_max(2.0);
+ zoom->set_value(1.0);
+ zoom->set_h_size_flags(SIZE_EXPAND_FILL);
+ zoom->set_stretch_ratio(2);
+ hb->add_child(zoom);
+ zoom->connect("value_changed",this,"_scroll_changed");
+ zoom->set_tooltip(TTR("Animation zoom."));
+
+ hb->add_child( memnew( VSeparator ) );
+
+ Label *l = memnew( Label );
+ l->set_text(TTR("Length (s):"));
+ hb->add_child(l);
+
+ length = memnew( SpinBox );
+ length->set_min(0.01);
+ length->set_max(10000);
+ length->set_step(0.01);
+ length->set_h_size_flags(SIZE_EXPAND_FILL);
+ length->set_stretch_ratio(1);
+ length->set_tooltip(TTR("Animation length (in seconds)."));
+
+ hb->add_child(length);
+ length->connect("value_changed",this,"_animation_len_changed");
+
+ l = memnew( Label );
+ l->set_text(TTR("Step (s):"));
+ hb->add_child(l);
+
+ step = memnew( SpinBox );
+ step->set_min(0.00);
+ step->set_max(128);
+ step->set_step(0.01);
+ step->set_value(0.0);
+ step->set_h_size_flags(SIZE_EXPAND_FILL);
+ step->set_stretch_ratio(1);
+ step->set_tooltip(TTR("Cursor step snap (in seconds)."));
+
+ hb->add_child(step);
+ step->connect("value_changed",this,"_step_changed");
+
+ loop = memnew( ToolButton );
+ loop->set_toggle_mode(true);
+ loop->connect("pressed",this,"_animation_loop_changed");
+ hb->add_child(loop);
+ loop->set_tooltip(TTR("Enable/Disable looping in animation."));
+
+ hb->add_child( memnew( VSeparator ) );
+
+ menu_add_track = memnew( MenuButton );
+ hb->add_child(menu_add_track);
+ menu_add_track->get_popup()->connect("id_pressed",this,"_menu_add_track");
+ menu_add_track->set_tooltip(TTR("Add new tracks."));
+
+ move_up_button = memnew( ToolButton );
+ hb->add_child(move_up_button);
+ move_up_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_MOVE_UP));
+ move_up_button->set_focus_mode(FOCUS_NONE);
+ move_up_button->set_disabled(true);
+ move_up_button->set_tooltip(TTR("Move current track up."));
+
+ move_down_button = memnew( ToolButton );
+ hb->add_child(move_down_button);
+ move_down_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_MOVE_DOWN));
+ move_down_button->set_focus_mode(FOCUS_NONE);
+ move_down_button->set_disabled(true);
+ move_down_button->set_tooltip(TTR("Move current track down."));
+
+ remove_button = memnew( ToolButton );
+ hb->add_child(remove_button);
+ remove_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_REMOVE));
+ remove_button->set_focus_mode(FOCUS_NONE);
+ remove_button->set_disabled(true);
+ remove_button->set_tooltip(TTR("Remove selected track."));
+
+ hb->add_child(memnew( VSeparator ));
+
+ menu_track = memnew( MenuButton );
+ hb->add_child(menu_track);
+ menu_track->get_popup()->connect("id_pressed",this,"_menu_track");
+ menu_track->set_tooltip(TTR("Track tools"));
+
+ edit_button = memnew( ToolButton );
+ edit_button->set_toggle_mode(true);
+ edit_button->set_focus_mode(FOCUS_NONE);
+ edit_button->set_disabled(true);
+
+ hb->add_child(edit_button);
+ edit_button->set_tooltip(TTR("Enable editing of individual keys by clicking them."));
+
+ optimize_dialog = memnew( ConfirmationDialog );
+ add_child(optimize_dialog);
+ optimize_dialog->set_title(TTR("Anim. Optimizer"));
+ VBoxContainer *optimize_vb = memnew( VBoxContainer );
+ optimize_dialog->add_child(optimize_vb);
+
+ optimize_linear_error = memnew( SpinBox );
+ optimize_linear_error->set_max(1.0);
+ optimize_linear_error->set_min(0.001);
+ optimize_linear_error->set_step(0.001);
+ optimize_linear_error->set_value(0.05);
+ optimize_vb->add_margin_child(TTR("Max. Linear Error:"),optimize_linear_error);
+ optimize_angular_error = memnew( SpinBox );
+ optimize_angular_error->set_max(1.0);
+ optimize_angular_error->set_min(0.001);
+ optimize_angular_error->set_step(0.001);
+ optimize_angular_error->set_value(0.01);
+
+ optimize_vb->add_margin_child(TTR("Max. Angular Error:"),optimize_angular_error);
+ optimize_max_angle = memnew( SpinBox );
+ optimize_vb->add_margin_child(TTR("Max Optimizable Angle:"),optimize_max_angle);
+ optimize_max_angle->set_max(360.0);
+ optimize_max_angle->set_min(0.0);
+ optimize_max_angle->set_step(0.1);
+ optimize_max_angle->set_value(22);
+
+ optimize_dialog->get_ok()->set_text(TTR("Optimize"));
+
+
+
+ /*keying = memnew( Button );
+ keying->set_toggle_mode(true);
+ //keying->set_text("Keys");
+ keying->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,60);
+ keying->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,10);
+ keying->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,55);
+ keying->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,10);
+ //add_child(keying);
+ keying->connect("pressed",this,"_keying_toggled");
+ */
+
+/* l = memnew( Label );
+ l->set_text("Base: ");
+ l->set_pos(Point2(0,3));
+ //dr_panel->add_child(l);*/
+
+ //menu->get_popup()->connect("id_pressed",this,"_menu_callback");
+
+
+ hb = memnew( HBoxContainer);
+ hb->set_area_as_parent_rect();
+ ec->add_child(hb);
+ hb->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ track_editor = memnew( Control );
+ track_editor->connect("draw",this,"_track_editor_draw");
+ hb->add_child(track_editor);
+ track_editor->connect("gui_input",this,"_track_editor_gui_input");
+ track_editor->set_focus_mode(Control::FOCUS_ALL);
+ track_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+
+
+
+ track_pos = memnew( Control );
+ track_pos->set_area_as_parent_rect();
+ track_pos->set_mouse_filter(MOUSE_FILTER_IGNORE);
+ track_editor->add_child(track_pos);
+ track_pos->connect("draw",this,"_track_pos_draw");
+
+ select_anim_warning = memnew( Label );
+ track_editor->add_child(select_anim_warning);
+ select_anim_warning->set_area_as_parent_rect();
+ select_anim_warning->set_text(TTR("Select an AnimationPlayer from the Scene Tree to edit animations."));
+ select_anim_warning->set_autowrap(true);
+ select_anim_warning->set_align(Label::ALIGN_CENTER);
+ select_anim_warning->set_valign(Label::VALIGN_CENTER);
+
+
+
+ v_scroll = memnew( VScrollBar );
+ hb->add_child(v_scroll);
+ v_scroll->connect("value_changed",this,"_scroll_changed");
+ v_scroll->set_value(0);
+
+ key_editor_tab = memnew(TabContainer);
+ hb->add_child(key_editor_tab);
+ key_editor_tab->set_custom_minimum_size(Size2(200,0));
+
+ key_editor = memnew( PropertyEditor );
+ key_editor->set_area_as_parent_rect();
+ key_editor->hide_top_label();
+ key_editor->set_name(TTR("Key"));
+ key_editor_tab->add_child(key_editor);
+
+ key_edit = memnew( AnimationKeyEdit );
+ key_edit->undo_redo=undo_redo;
+ //key_edit->ke_dialog=key_edit_dialog;
+
+ type_menu = memnew( PopupMenu );
+ add_child(type_menu);
+ for(int i=0;i<Variant::VARIANT_MAX;i++)
+ type_menu->add_item(Variant::get_type_name(Variant::Type(i)),i);
+ type_menu->connect("id_pressed",this,"_create_value_item");
+
+ VBoxContainer *curve_vb = memnew( VBoxContainer );
+ curve_vb->set_name(TTR("Transition"));
+ HBoxContainer *curve_hb = memnew( HBoxContainer );
+ curve_vb->add_child(curve_hb);
+
+ curve_linear = memnew( ToolButton );
+ curve_linear->set_focus_mode(FOCUS_NONE);
+ curve_hb->add_child(curve_linear);
+ curve_in = memnew( ToolButton );
+ curve_in->set_focus_mode(FOCUS_NONE);
+ curve_hb->add_child(curve_in);
+ curve_out = memnew( ToolButton );
+ curve_out->set_focus_mode(FOCUS_NONE);
+ curve_hb->add_child(curve_out);
+ curve_inout = memnew( ToolButton );
+ curve_inout->set_focus_mode(FOCUS_NONE);
+ curve_hb->add_child(curve_inout);
+ curve_outin = memnew( ToolButton );
+ curve_outin->set_focus_mode(FOCUS_NONE);
+ curve_hb->add_child(curve_outin);
+ curve_constant = memnew( ToolButton );
+ curve_constant->set_focus_mode(FOCUS_NONE);
+ curve_hb->add_child(curve_constant);
+
+
+ curve_edit = memnew( AnimationCurveEdit );
+ curve_vb->add_child(curve_edit);
+ curve_edit->set_v_size_flags(SIZE_EXPAND_FILL);
+ key_editor_tab->add_child(curve_vb);
+
+ track_name = memnew( LineEdit );
+ track_name->set_as_toplevel(true);
+ track_name->hide();
+ add_child(track_name);
+ track_name->connect("text_entered",this,"_track_name_changed");
+ track_menu = memnew( PopupMenu );
+ add_child(track_menu);
+ track_menu->connect("id_pressed",this,"_track_menu_selected");
+
+ key_editor_tab->hide();
+
+ last_idx =1;
+
+ _update_menu();
+
+
+
+ insert_confirm = memnew( ConfirmationDialog );
+ add_child(insert_confirm);
+ insert_confirm->connect("confirmed",this,"_confirm_insert_list");
+
+ click.click=ClickOver::CLICK_NONE;
+
+
+ name_column_ratio=0.3;
+ timeline_pos=0;
+
+
+ keying=false;
+ insert_frame=0;
+ insert_query=false;
+ insert_queue=false;
+
+ editor_selection->connect("selection_changed",track_editor,"update");
+
+
+ scale_dialog = memnew( ConfirmationDialog );
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ scale_dialog->add_child(vbc);
+
+ scale = memnew( SpinBox );
+ scale->set_min(-99999);
+ scale->set_max(99999);
+ scale->set_step(0.001);
+ vbc->add_margin_child(TTR("Scale Ratio:"),scale);
+ scale_dialog->connect("confirmed",this,"_scale");
+ add_child(scale_dialog);
+
+ call_select = memnew( SceneTreeDialog );
+ add_child(call_select);
+ call_select->set_title(TTR("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_keys = memnew( CheckButton );
+ cleanup_keys->set_text(TTR("Remove invalid keys"));
+ cleanup_keys->set_pressed(true);
+ cleanup_vb->add_child(cleanup_keys);
+
+ cleanup_tracks = memnew( CheckButton );
+ cleanup_tracks->set_text(TTR("Remove unresolved and empty tracks"));
+ cleanup_tracks->set_pressed(true);
+ cleanup_vb->add_child(cleanup_tracks);
+
+ cleanup_all = memnew( CheckButton );
+ cleanup_all->set_text(TTR("Clean-up all animations"));
+ cleanup_vb->add_child(cleanup_all);
+
+ cleanup_dialog->set_title(TTR("Clean-Up Animation(s) (NO UNDO!)"));
+ cleanup_dialog->get_ok()->set_text(TTR("Clean-Up"));
+
+ cleanup_dialog->connect("confirmed",this,"_menu_track",varray(TRACK_MENU_CLEAN_UP_CONFIRM));
+
+ add_constant_override("separation",get_constant("separation","VBoxContainer"));
+
+ track_editor->set_clip_contents(true);
+
+}
+
+AnimationKeyEditor::~AnimationKeyEditor() {
+
+
+
+ memdelete( key_edit );
+
+}
diff --git a/tools/editor/animation_editor.h b/editor/animation_editor.h
index c4539cd763..c4539cd763 100644
--- a/tools/editor/animation_editor.h
+++ b/editor/animation_editor.h
diff --git a/editor/array_property_edit.cpp b/editor/array_property_edit.cpp
new file mode 100644
index 0000000000..7304d8dddf
--- /dev/null
+++ b/editor/array_property_edit.cpp
@@ -0,0 +1,310 @@
+/*************************************************************************/
+/* array_property_edit.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "array_property_edit.h"
+
+#include "editor_node.h"
+
+#define ITEMS_PER_PAGE 100
+
+Variant ArrayPropertyEdit::get_array() const{
+
+ Object*o = ObjectDB::get_instance(obj);
+ if (!o)
+ return Array();
+ Variant arr=o->get(property);
+ if (!arr.is_array()) {
+ Variant::CallError ce;
+ arr=Variant::construct(default_type,NULL,0,ce);
+ }
+ return arr;
+}
+
+void ArrayPropertyEdit::_notif_change() {
+ _change_notify();
+}
+void ArrayPropertyEdit::_notif_changev(const String& p_v) {
+
+ _change_notify(p_v.utf8().get_data());
+}
+
+void ArrayPropertyEdit::_set_size(int p_size) {
+
+ Variant arr = get_array();
+ arr.call("resize",p_size);
+ Object*o = ObjectDB::get_instance(obj);
+ if (!o)
+ return;
+
+ o->set(property,arr);
+
+}
+
+void ArrayPropertyEdit::_set_value(int p_idx,const Variant& p_value) {
+
+ Variant arr = get_array();
+ arr.set(p_idx,p_value);
+ Object*o = ObjectDB::get_instance(obj);
+ if (!o)
+ return;
+
+ o->set(property,arr);
+}
+
+bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){
+
+ String pn=p_name;
+
+ if (pn.begins_with("array/")) {
+
+ if (pn=="array/size") {
+
+ Variant arr = get_array();
+ int size = arr.call("size");
+
+ int newsize=p_value;
+ if (newsize==size)
+ return true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Resize Array"));
+ ur->add_do_method(this,"_set_size",newsize);
+ ur->add_undo_method(this,"_set_size",size);
+ if (newsize<size) {
+ for(int i=newsize;i<size;i++) {
+ ur->add_undo_method(this,"_set_value",i,arr.get(i));
+
+ }
+ } else if (newsize>size) {
+
+ Variant init;
+ Variant::CallError ce;
+ Variant::Type new_type = subtype;
+ if(new_type==Variant::NIL && size) {
+ new_type = arr.get(size-1).get_type();
+ }
+ if(new_type!=Variant::NIL) {
+ init = Variant::construct(new_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");
+ ur->commit_action();
+ return true;
+ }
+ if (pn=="array/page") {
+ page=p_value;
+ _change_notify();
+ return true;
+ }
+
+ } else if (pn.begins_with("indices")) {
+
+ if (pn.find("_")!=-1) {
+ //type
+ int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
+
+ int type = p_value;
+
+ Variant arr = get_array();
+
+ Variant value = arr.get(idx);
+ if (value.get_type()!=type && type>=0 && type<Variant::VARIANT_MAX) {
+ Variant::CallError ce;
+ Variant new_value=Variant::construct(Variant::Type(type),NULL,0,ce);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("Change Array Value Type"));
+ ur->add_do_method(this,"_set_value",idx,new_value);
+ ur->add_undo_method(this,"_set_value",idx,value);
+ ur->add_do_method(this,"_notif_change");
+ ur->add_undo_method(this,"_notif_change");
+ ur->commit_action();
+
+ }
+ return true;
+
+ } else {
+ int idx=pn.get_slicec('/',1).to_int();
+ Variant arr = get_array();
+
+ Variant value = arr.get(idx);
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("Change Array Value"));
+ ur->add_do_method(this,"_set_value",idx,p_value);
+ ur->add_undo_method(this,"_set_value",idx,value);
+ ur->add_do_method(this,"_notif_changev",p_name);
+ ur->add_undo_method(this,"_notif_changev",p_name);
+ ur->commit_action();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ArrayPropertyEdit::_get(const StringName& p_name,Variant &r_ret) const {
+
+ Variant arr = get_array();
+ //int size = arr.call("size");
+
+ String pn=p_name;
+ if (pn.begins_with("array/")) {
+
+ if (pn=="array/size") {
+ r_ret=arr.call("size");
+ return true;
+ }
+ if (pn=="array/page") {
+ r_ret=page;
+ return true;
+ }
+ } else if (pn.begins_with("indices")) {
+
+ if (pn.find("_")!=-1) {
+ //type
+ int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
+ bool valid;
+ r_ret=arr.get(idx,&valid);
+ if (valid)
+ r_ret=r_ret.get_type();
+ return valid;
+
+ } else {
+ int idx=pn.get_slicec('/',1).to_int();
+ bool valid;
+ r_ret=arr.get(idx,&valid);
+ return valid;
+ }
+ }
+
+ return false;
+}
+
+void ArrayPropertyEdit::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ Variant arr = get_array();
+ int size = arr.call("size");
+
+ p_list->push_back( PropertyInfo(Variant::INT,"array/size",PROPERTY_HINT_RANGE,"0,100000,1") );
+ int pages = size/ITEMS_PER_PAGE;
+ if (pages>0)
+ p_list->push_back( PropertyInfo(Variant::INT,"array/page",PROPERTY_HINT_RANGE,"0,"+itos(pages)+",1") );
+
+ int offset=page*ITEMS_PER_PAGE;
+
+ int items=MIN(size-offset,ITEMS_PER_PAGE);
+
+
+ for(int i=0;i<items;i++) {
+
+ Variant v=arr.get(i+offset);
+ bool is_typed = arr.get_type()!=Variant::ARRAY || subtype!=Variant::NIL;
+
+ if (!is_typed) {
+ p_list->push_back(PropertyInfo(Variant::INT,"indices/"+itos(i+offset)+"_type",PROPERTY_HINT_ENUM,vtypes));
+ }
+
+ if (is_typed || v.get_type()!=Variant::NIL ) {
+ PropertyInfo pi(v.get_type(),"indices/"+itos(i+offset));
+ if(subtype!=Variant::NIL) {
+ pi.type = Variant::Type(subtype);
+ pi.hint = PropertyHint(subtype_hint);
+ pi.hint_string = subtype_hint_string;
+ } else if (v.get_type()==Variant::OBJECT) {
+ pi.hint=PROPERTY_HINT_RESOURCE_TYPE;
+ pi.hint_string="Resource";
+ }
+
+ p_list->push_back(pi);
+ }
+ }
+
+}
+
+void ArrayPropertyEdit::edit(Object* p_obj,const StringName& p_prop,const String& p_hint_string,Variant::Type p_deftype) {
+
+ page=0;
+ property=p_prop;
+ obj=p_obj->get_instance_ID();
+ default_type=p_deftype;
+
+ if(!p_hint_string.empty()) {
+ int hint_subtype_seperator = p_hint_string.find(":");
+ if(hint_subtype_seperator >= 0) {
+ String subtype_string = p_hint_string.substr(0,hint_subtype_seperator);
+
+ int slash_pos = subtype_string.find("/");
+ if(slash_pos >= 0) {
+ subtype_hint = PropertyHint(subtype_string.substr(slash_pos+1, subtype_string.size()-slash_pos-1).to_int());
+ subtype_string = subtype_string.substr(0,slash_pos);
+ }
+
+ subtype_hint_string = p_hint_string.substr(hint_subtype_seperator+1, p_hint_string.size() - hint_subtype_seperator-1);
+ subtype=Variant::Type(subtype_string.to_int());
+ }
+ }
+
+}
+
+Node *ArrayPropertyEdit::get_node() {
+
+ Object *o = ObjectDB::get_instance(obj);
+ if (!o)
+ return NULL;
+
+ return o->cast_to<Node>();
+}
+
+void ArrayPropertyEdit::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_set_size"),&ArrayPropertyEdit::_set_size);
+ ClassDB::bind_method(D_METHOD("_set_value"),&ArrayPropertyEdit::_set_value);
+ ClassDB::bind_method(D_METHOD("_notif_change"),&ArrayPropertyEdit::_notif_change);
+ ClassDB::bind_method(D_METHOD("_notif_changev"),&ArrayPropertyEdit::_notif_changev);
+}
+
+ArrayPropertyEdit::ArrayPropertyEdit()
+{
+ page=0;
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+
+ if (i>0)
+ vtypes+=",";
+ vtypes+=Variant::get_type_name( Variant::Type(i) );
+ }
+ default_type=Variant::NIL;
+ subtype=Variant::NIL;
+ subtype_hint=PROPERTY_HINT_NONE;
+ subtype_hint_string="";
+}
diff --git a/tools/editor/array_property_edit.h b/editor/array_property_edit.h
index 6ca700bf80..6ca700bf80 100644
--- a/tools/editor/array_property_edit.h
+++ b/editor/array_property_edit.h
diff --git a/editor/asset_library_editor_plugin.cpp b/editor/asset_library_editor_plugin.cpp
new file mode 100644
index 0000000000..1c1b6c91e3
--- /dev/null
+++ b/editor/asset_library_editor_plugin.cpp
@@ -0,0 +1,1553 @@
+/*************************************************************************/
+/* asset_library_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "asset_library_editor_plugin.h"
+
+#include "editor_node.h"
+#include "editor_settings.h"
+#include "io/json.h"
+
+
+void EditorAssetLibraryItem::configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost) {
+
+ title->set_text(p_title);
+ asset_id=p_asset_id;
+ category->set_text(p_category);
+ category_id=p_category_id;
+ author->set_text(p_author);
+ author_id=p_author_id;
+ price->set_text(p_cost);
+
+ for(int i=0;i<5;i++) {
+ if (i<p_rating)
+ stars[i]->set_texture(get_icon("RatingStar","EditorIcons"));
+ else
+ stars[i]->set_texture(get_icon("RatingNoStar","EditorIcons"));
+ }
+
+
+}
+
+void EditorAssetLibraryItem::set_image(int p_type,int p_index,const Ref<Texture>& p_image) {
+
+ ERR_FAIL_COND(p_type!=EditorAssetLibrary::IMAGE_QUEUE_ICON);
+ ERR_FAIL_COND(p_index!=0);
+
+ icon->set_normal_texture(p_image);
+}
+
+void EditorAssetLibraryItem::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ icon->set_normal_texture(get_icon("GodotAssetDefault","EditorIcons"));
+ category->add_color_override("font_color", Color(0.5,0.5,0.5) );
+ author->add_color_override("font_color", Color(0.5,0.5,0.5) );
+
+ }
+}
+
+void EditorAssetLibraryItem::_asset_clicked() {
+
+ emit_signal("asset_selected",asset_id);
+}
+
+void EditorAssetLibraryItem::_category_clicked(){
+
+ emit_signal("category_selected",category_id);
+}
+void EditorAssetLibraryItem::_author_clicked(){
+
+ emit_signal("author_selected",author_id);
+
+}
+
+void EditorAssetLibraryItem::_bind_methods() {
+
+ ClassDB::bind_method("set_image",&EditorAssetLibraryItem::set_image);
+ ClassDB::bind_method("_asset_clicked",&EditorAssetLibraryItem::_asset_clicked);
+ ClassDB::bind_method("_category_clicked",&EditorAssetLibraryItem::_category_clicked);
+ ClassDB::bind_method("_author_clicked",&EditorAssetLibraryItem::_author_clicked);
+ ADD_SIGNAL( MethodInfo("asset_selected"));
+ ADD_SIGNAL( MethodInfo("category_selected"));
+ ADD_SIGNAL( MethodInfo("author_selected"));
+
+
+}
+
+EditorAssetLibraryItem::EditorAssetLibraryItem() {
+
+ Ref<StyleBoxEmpty> border;
+ border.instance();
+ /*border->set_default_margin(MARGIN_LEFT,5);
+ border->set_default_margin(MARGIN_RIGHT,5);
+ border->set_default_margin(MARGIN_BOTTOM,5);
+ border->set_default_margin(MARGIN_TOP,5);*/
+ add_style_override("panel",border);
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ add_child(hb);
+
+ icon = memnew( TextureButton );
+ icon->set_default_cursor_shape(CURSOR_POINTING_HAND);
+ icon->connect("pressed",this,"_asset_clicked");
+
+ hb->add_child(icon);
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+
+ hb->add_child(vb);
+ vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ title = memnew( LinkButton );
+ title->set_text("My Awesome Addon");
+ title->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ title->connect("pressed",this,"_asset_clicked");
+ vb->add_child(title);
+
+
+ category = memnew( LinkButton );
+ category->set_text("Editor Tools");
+ category->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ category->connect("pressed",this,"_category_clicked");
+ vb->add_child(category);
+
+ author = memnew( LinkButton );
+ author->set_text("Johny Tolengo");
+ author->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ author->connect("pressed",this,"_author_clicked");
+ vb->add_child(author);
+
+ HBoxContainer *rating_hb = memnew( HBoxContainer );
+ vb->add_child(rating_hb);
+
+ for(int i=0;i<5;i++) {
+ stars[i]=memnew(TextureRect);
+ rating_hb->add_child(stars[i]);
+ }
+ price = memnew( Label );
+ price->set_text("Free");
+ vb->add_child(price);
+
+ set_custom_minimum_size(Size2(250,100));
+ set_h_size_flags(SIZE_EXPAND_FILL);
+
+ set_mouse_filter(MOUSE_FILTER_PASS);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+void EditorAssetLibraryItemDescription::set_image(int p_type,int p_index,const Ref<Texture>& p_image) {
+
+ switch(p_type) {
+
+ case EditorAssetLibrary::IMAGE_QUEUE_ICON: {
+
+ item->call("set_image",p_type,p_index,p_image);
+ icon=p_image;
+ } break;
+ case EditorAssetLibrary::IMAGE_QUEUE_THUMBNAIL: {
+
+ for(int i=0;i<preview_images.size();i++) {
+ if (preview_images[i].id==p_index) {
+ preview_images[i].button->set_icon(p_image);
+ break;
+ }
+ }
+ //item->call("set_image",p_type,p_index,p_image);
+ } break;
+ case EditorAssetLibrary::IMAGE_QUEUE_SCREENSHOT: {
+
+ for(int i=0;i<preview_images.size();i++) {
+ if (preview_images[i].id==p_index) {
+ preview_images[i].image = p_image;
+ if(preview_images[i].button->is_pressed()) {
+ _preview_click(p_index);
+ }
+ break;
+ }
+ }
+ //item->call("set_image",p_type,p_index,p_image);
+ } break;
+ }
+}
+
+void EditorAssetLibraryItemDescription::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_image"),&EditorAssetLibraryItemDescription::set_image);
+ ClassDB::bind_method(D_METHOD("_link_click"),&EditorAssetLibraryItemDescription::_link_click);
+ ClassDB::bind_method(D_METHOD("_preview_click"),&EditorAssetLibraryItemDescription::_preview_click);
+
+}
+
+void EditorAssetLibraryItemDescription::_link_click(const String& p_url) {
+ ERR_FAIL_COND(!p_url.begins_with("http"));
+ OS::get_singleton()->shell_open(p_url);
+}
+
+void EditorAssetLibraryItemDescription::_preview_click(int p_id) {
+ for(int i=0;i<preview_images.size();i++) {
+ if(preview_images[i].id==p_id) {
+ preview_images[i].button->set_pressed(true);
+ if(!preview_images[i].is_video) {
+ if(preview_images[i].image.is_valid()) {
+ preview->set_texture(preview_images[i].image);
+ }
+ } else {
+ _link_click(preview_images[i].video_link);
+ }
+ } else {
+ preview_images[i].button->set_pressed(false);
+ }
+ }
+}
+
+void EditorAssetLibraryItemDescription::configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost,int p_version,const String& p_version_string,const String& p_description,const String& p_download_url,const String& p_browse_url,const String& p_sha256_hash) {
+
+ asset_id=p_asset_id;
+ title=p_title;
+ download_url=p_download_url;
+ sha256=p_sha256_hash;
+ item->configure(p_title,p_asset_id,p_category,p_category_id,p_author,p_author_id,p_rating,p_cost);
+ description->clear();
+ description->add_text("Version: "+p_version_string+"\n");
+ description->add_text("Contents: ");
+ description->push_meta(p_browse_url);
+ description->add_text("View Files");
+ description->pop();
+ description->add_text("\nDescription:\n\n");
+ description->append_bbcode(p_description);
+ set_title(p_title);
+}
+
+void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video,const String& p_url){
+
+ Preview preview;
+ preview.id=p_id;
+ preview.video_link=p_url;
+ preview.is_video=p_video;
+ preview.button = memnew( Button );
+ preview.button->set_flat(true);
+ preview.button->set_icon(get_icon("ThumbnailWait","EditorIcons"));
+ preview.button->set_toggle_mode(true);
+ preview.button->connect("pressed", this, "_preview_click", varray(p_id));
+ preview_hb->add_child(preview.button);
+ if(!p_video) {
+ preview.image=get_icon("ThumbnailWait","EditorIcons");
+ }
+ if(preview_images.size()==0 && !p_video) {
+ _preview_click(p_id);
+ }
+ preview_images.push_back(preview);
+}
+
+EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
+
+ VBoxContainer *vbox = memnew( VBoxContainer );
+ add_child(vbox);
+
+
+
+ HBoxContainer *hbox = memnew( HBoxContainer);
+ vbox->add_child(hbox);
+ vbox->add_constant_override("separation",15);
+ VBoxContainer *desc_vbox = memnew( VBoxContainer );
+ hbox->add_child(desc_vbox);
+ hbox->add_constant_override("separation",15);
+
+ item = memnew( EditorAssetLibraryItem );
+
+ desc_vbox->add_child(item);
+ desc_vbox->set_custom_minimum_size(Size2(300,0));
+
+
+ PanelContainer * desc_bg = memnew( PanelContainer );
+ desc_vbox->add_child(desc_bg);
+ desc_bg->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ description = memnew( RichTextLabel );
+ description->connect("meta_clicked",this,"_link_click");
+ //desc_vbox->add_child(description);
+ desc_bg->add_child(description);
+ desc_bg->add_style_override("panel",get_stylebox("normal","TextEdit"));
+
+ preview = memnew( TextureRect );
+ preview->set_custom_minimum_size(Size2(640,345));
+ hbox->add_child(preview);
+
+ PanelContainer * previews_bg = memnew( PanelContainer );
+ vbox->add_child(previews_bg);
+ previews_bg->set_custom_minimum_size(Size2(0,85));
+ previews_bg->add_style_override("panel",get_stylebox("normal","TextEdit"));
+
+ previews = memnew( ScrollContainer );
+ previews_bg->add_child(previews);
+ previews->set_enable_v_scroll(false);
+ previews->set_enable_h_scroll(true);
+ preview_hb = memnew( HBoxContainer );
+ preview_hb->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ previews->add_child(preview_hb);
+ get_ok()->set_text("Install");
+ get_cancel()->set_text("Close");
+
+
+
+}
+///////////////////////////////////////////////////////////////////////////////////
+
+void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int p_code, const PoolStringArray& headers, const PoolByteArray& p_data) {
+
+
+ String error_text;
+ print_line("COMPLETED: "+itos(p_status)+" code: "+itos(p_code)+" data size: "+itos(p_data.size()));
+
+ switch(p_status) {
+
+ case HTTPRequest::RESULT_CANT_RESOLVE: {
+ error_text=("Can't resolve hostname: "+host);
+ status->set_text("Can't resolve.");
+ } break;
+ case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
+ case HTTPRequest::RESULT_CONNECTION_ERROR:
+ case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: {
+ error_text=("Connection error, please try again.");
+ status->set_text("Can't connect.");
+ } break;
+ case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
+ case HTTPRequest::RESULT_CANT_CONNECT: {
+ error_text=("Can't connect to host: "+host);
+ status->set_text("Can't connect.");
+ } break;
+ case HTTPRequest::RESULT_NO_RESPONSE: {
+ error_text=("No response from host: "+host);
+ status->set_text("No response.");
+ } break;
+ case HTTPRequest::RESULT_REQUEST_FAILED: {
+ error_text=("Request failed, return code: "+itos(p_code));
+ status->set_text("Req. Failed.");
+ } break;
+ case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
+ error_text=("Request failed, too many redirects");
+ status->set_text("Redirect Loop.");
+ } break;
+ default: {
+ if (p_code!=200) {
+ error_text=("Request failed, return code: "+itos(p_code));
+ status->set_text("Failed: "+itos(p_code));
+ } else if(sha256 != "") {
+ String download_sha256 = FileAccess::get_sha256(download->get_download_file());
+ if(sha256 != download_sha256) {
+ error_text="Bad download hash, assuming file has been tampered with.\nExpected: " + sha256 + "\nGot: " + download_sha256;
+ status->set_text("Failed sha256 hash check");
+ }
+ }
+ } break;
+
+ }
+
+ if (error_text!=String()) {
+ download_error->set_text("Asset Download Error:\n"+error_text);
+ download_error->popup_centered_minsize();
+ return;
+
+ }
+
+ progress->set_max( download->get_body_size() );
+ progress->set_value(download->get_downloaded_bytes());
+
+ print_line("max: "+itos(download->get_body_size())+" bytes: "+itos(download->get_downloaded_bytes()));
+ install->set_disabled(false);
+
+ progress->set_value(download->get_downloaded_bytes());
+
+ status->set_text("Success! ("+String::humanize_size(download->get_downloaded_bytes())+")");
+ set_process(false);
+}
+
+
+void EditorAssetLibraryItemDownload::configure(const String& p_title,int p_asset_id,const Ref<Texture>& p_preview, const String& p_download_url, const String& p_sha256_hash) {
+
+ title->set_text(p_title);
+ icon->set_texture(p_preview);
+ asset_id=p_asset_id;
+ if (!p_preview.is_valid())
+ icon->set_texture(get_icon("GodotAssetDefault","EditorIcons"));
+ host=p_download_url;
+ sha256=p_sha256_hash;
+ asset_installer->connect("confirmed",this,"_close");
+ dismiss->set_normal_texture( get_icon("Close","EditorIcons"));
+ _make_request();
+}
+
+
+void EditorAssetLibraryItemDownload::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ progress->set_max( download->get_body_size() );
+ progress->set_value(download->get_downloaded_bytes());
+
+ int cstatus = download->get_http_client_status();
+
+ if (cstatus==HTTPClient::STATUS_BODY)
+ status->set_text("Fetching: "+String::humanize_size(download->get_downloaded_bytes()));
+
+ if (cstatus!=prev_status) {
+ switch(cstatus) {
+
+ case HTTPClient::STATUS_RESOLVING: {
+ status->set_text("Resolving..");
+ } break;
+ case HTTPClient::STATUS_CONNECTING: {
+ status->set_text("Connecting..");
+ } break;
+ case HTTPClient::STATUS_REQUESTING: {
+ status->set_text("Requesting..");
+ } break;
+ default: {}
+ }
+ prev_status=cstatus;
+ }
+
+ }
+}
+void EditorAssetLibraryItemDownload::_close() {
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->remove(download->get_download_file()); //clean up removed file
+ memdelete(da);
+ queue_delete();
+}
+
+void EditorAssetLibraryItemDownload::_install() {
+
+ String file = download->get_download_file();
+
+ if (external_install) {
+ emit_signal("install_asset",file,title->get_text());
+ return;
+ }
+
+
+ asset_installer->open(file,1);
+}
+
+void EditorAssetLibraryItemDownload::_make_request() {
+ download->cancel_request();
+ download->set_download_file(EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_asset_"+itos(asset_id))+".zip");
+
+ Error err = download->request(host);
+ if(err!=OK) {
+ status->set_text("Error making request");
+ } else {
+ set_process(true);
+ }
+}
+
+void EditorAssetLibraryItemDownload::_bind_methods() {
+
+ ClassDB::bind_method("_http_download_completed",&EditorAssetLibraryItemDownload::_http_download_completed);
+ ClassDB::bind_method("_install",&EditorAssetLibraryItemDownload::_install);
+ ClassDB::bind_method("_close",&EditorAssetLibraryItemDownload::_close);
+ ClassDB::bind_method("_make_request",&EditorAssetLibraryItemDownload::_make_request);
+
+ ADD_SIGNAL(MethodInfo("install_asset",PropertyInfo(Variant::STRING,"zip_path"),PropertyInfo(Variant::STRING,"name")));
+
+}
+
+EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() {
+
+ HBoxContainer *hb = memnew( HBoxContainer);
+ add_child(hb);
+ icon = memnew( TextureRect );
+ hb->add_child(icon);
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ hb->add_child(vb);
+ vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *title_hb = memnew( HBoxContainer);
+ vb->add_child(title_hb);
+ title = memnew( Label );
+ title_hb->add_child(title);
+ title->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ dismiss = memnew( TextureButton );
+ dismiss->connect("pressed",this,"_close");
+ title_hb->add_child(dismiss);
+
+ title->set_clip_text(true);
+
+ vb->add_spacer();
+
+ status = memnew (Label("Idle"));
+ vb->add_child(status);
+ status->add_color_override("font_color", Color(0.5,0.5,0.5) );
+ progress = memnew( ProgressBar );
+ vb->add_child(progress);
+
+
+
+ HBoxContainer *hb2 = memnew( HBoxContainer );
+ vb->add_child(hb2);
+ hb2->add_spacer();
+
+ install = memnew( Button );
+ install->set_text("Install");
+ install->set_disabled(true);
+ install->connect("pressed",this,"_install");
+
+ retry = memnew( Button );
+ retry->set_text("Retry");
+ retry->connect("pressed",this,"_make_request");
+
+ hb2->add_child(retry);
+ hb2->add_child(install);
+ set_custom_minimum_size(Size2(250,0));
+
+ download = memnew( HTTPRequest );
+ add_child(download);
+ download->connect("request_completed",this,"_http_download_completed");
+
+ download_error = memnew( AcceptDialog );
+ add_child(download_error);
+ download_error->set_title("Download Error");
+
+ asset_installer = memnew( EditorAssetInstaller );
+ add_child(asset_installer);
+
+ prev_status=-1;
+
+ external_install=false;
+
+
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+void EditorAssetLibrary::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+ TextureRect *tf = memnew(TextureRect);
+ tf->set_texture(get_icon("Error","EditorIcons"));
+ reverse->set_icon(get_icon("Updown","EditorIcons"));
+
+ error_hb->add_child(tf);
+ error_label->raise();
+ }
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+ if(is_visible()) {
+ _repository_changed(0); // Update when shown for the first time
+ }
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ HTTPClient::Status s = request->get_http_client_status();
+ bool visible = s!=HTTPClient::STATUS_DISCONNECTED;
+
+ if (visible != load_status->is_visible()) {
+ load_status->set_visible(visible);
+ }
+
+ if (visible) {
+ switch(s) {
+
+ case HTTPClient::STATUS_RESOLVING: {
+ load_status->set_value(0.1);
+ } break;
+ case HTTPClient::STATUS_CONNECTING: {
+ load_status->set_value(0.2);
+ } break;
+ case HTTPClient::STATUS_REQUESTING: {
+ load_status->set_value(0.3);
+ } break;
+ case HTTPClient::STATUS_BODY: {
+ load_status->set_value(0.4);
+ } break;
+ default: {}
+
+ }
+ }
+
+ bool no_downloads = downloads_hb->get_child_count()==0;
+ if (no_downloads == downloads_scroll->is_visible()) {
+ downloads_scroll->set_visible(!no_downloads);
+ }
+ }
+
+}
+
+
+void EditorAssetLibrary::_install_asset() {
+
+ ERR_FAIL_COND(!description);
+
+ for(int i=0;i<downloads_hb->get_child_count();i++) {
+
+ EditorAssetLibraryItemDownload *d = downloads_hb->get_child(i)->cast_to<EditorAssetLibraryItemDownload>();
+ if (d && d->get_asset_id() == description->get_asset_id()) {
+
+ if (EditorNode::get_singleton() != NULL)
+ EditorNode::get_singleton()->show_warning("Download for this asset is already in progress!");
+ return;
+ }
+ }
+
+
+ EditorAssetLibraryItemDownload * download = memnew( EditorAssetLibraryItemDownload );
+ downloads_hb->add_child(download);
+ download->configure(description->get_title(),description->get_asset_id(),description->get_preview_icon(),description->get_download_url(),description->get_sha256());
+
+ if (templates_only) {
+ download->set_external_install(true);
+ download->connect("install_asset",this,"_install_external_asset");
+ }
+
+}
+
+const char* EditorAssetLibrary::sort_key[SORT_MAX]={
+ "rating",
+ "downloads",
+ "name",
+ "cost",
+ "updated"
+};
+
+const char* EditorAssetLibrary::sort_text[SORT_MAX]={
+ "Rating",
+ "Downloads",
+ "Name",
+ "Cost",
+ "Updated"
+};
+
+const char* EditorAssetLibrary::support_key[SUPPORT_MAX]={
+ "official",
+ "community",
+ "testing"
+};
+
+
+void EditorAssetLibrary::_select_author(int p_id) {
+
+ //opemn author window
+}
+
+void EditorAssetLibrary::_select_category(int p_id){
+
+ for(int i=0;i<categories->get_item_count();i++) {
+
+ if (i==0)
+ continue;
+ int id = categories->get_item_metadata(i);
+ if (id==p_id) {
+ categories->select(i);
+ _search();
+ break;
+ }
+ }
+}
+void EditorAssetLibrary::_select_asset(int p_id){
+
+ _api_request("asset/"+itos(p_id), REQUESTING_ASSET);
+
+ /*
+ if (description) {
+ memdelete(description);
+ }
+
+
+ description = memnew( EditorAssetLibraryItemDescription );
+ add_child(description);
+ description->popup_centered_minsize();*/
+}
+
+void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByteArray& p_data, int p_queue_id) {
+ Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
+
+ if (obj) {
+ bool image_set = false;
+ PoolByteArray image_data = p_data;
+
+ if(use_cache) {
+ String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+image_queue[p_queue_id].image_url.md5_text());
+
+ FileAccess* file = FileAccess::open(cache_filename_base+".data", FileAccess::READ);
+
+ if(file) {
+ PoolByteArray cached_data;
+ int len=file->get_32();
+ cached_data.resize(len);
+
+ PoolByteArray::Write w=cached_data.write();
+ file->get_buffer(w.ptr(), len);
+
+ image_data = cached_data;
+ file->close();
+ }
+ }
+
+ int len=image_data.size();
+ PoolByteArray::Read r=image_data.read();
+ Image image(r.ptr(),len);
+ if (!image.empty()) {
+ float max_height = 10000;
+ switch(image_queue[p_queue_id].image_type) {
+ case IMAGE_QUEUE_ICON: max_height=80; break;
+ case IMAGE_QUEUE_THUMBNAIL: max_height=80; break;
+ case IMAGE_QUEUE_SCREENSHOT: max_height=345; break;
+ }
+ float scale_ratio = max_height / image.get_height();
+ if(scale_ratio < 1) {
+ image.resize(image.get_width() * scale_ratio, image.get_height() * scale_ratio, Image::INTERPOLATE_CUBIC);
+ }
+
+ Ref<ImageTexture> tex;
+ tex.instance();
+ tex->create_from_image(image);
+
+ obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,tex);
+ image_set = true;
+ }
+
+ if(!image_set && final) {
+ obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,get_icon("ErrorSign","EditorIcons"));
+ }
+ }
+}
+
+void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, const PoolStringArray& headers, const PoolByteArray& p_data,int p_queue_id) {
+
+ ERR_FAIL_COND( !image_queue.has(p_queue_id) );
+
+ if (p_status==HTTPRequest::RESULT_SUCCESS) {
+
+ print_line("GOT IMAGE YAY!");
+
+ if(p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
+ for(int i=0;i<headers.size();i++) {
+ if (headers[i].findn("ETag:")==0) { // Save etag
+ String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+image_queue[p_queue_id].image_url.md5_text());
+ String new_etag = headers[i].substr(headers[i].find(":")+1,headers[i].length()).strip_edges();
+ FileAccess* file;
+
+ file = FileAccess::open(cache_filename_base+".etag", FileAccess::WRITE);
+ if(file) {
+ file->store_line(new_etag);
+ file->close();
+ }
+
+ int len=p_data.size();
+ PoolByteArray::Read r=p_data.read();
+ file = FileAccess::open(cache_filename_base+".data", FileAccess::WRITE);
+ if(file) {
+ file->store_32(len);
+ file->store_buffer(r.ptr(),len);
+ file->close();
+ }
+
+ break;
+ }
+ }
+ }
+ _image_update(p_code == HTTPClient::RESPONSE_NOT_MODIFIED, true, p_data, p_queue_id);
+
+ } else {
+ WARN_PRINTS("Error getting PNG file for asset id "+itos(image_queue[p_queue_id].asset_id));
+ Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
+ if (obj) {
+ obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,get_icon("ErrorSign","EditorIcons"));
+ }
+ }
+
+ image_queue[p_queue_id].request->queue_delete();
+ image_queue.erase(p_queue_id);
+
+ _update_image_queue();
+
+}
+
+void EditorAssetLibrary::_update_image_queue() {
+
+ int max_images=2;
+ int current_images=0;
+
+ List<int> to_delete;
+ for (Map<int,ImageQueue>::Element *E=image_queue.front();E;E=E->next()) {
+ if (!E->get().active && current_images<max_images) {
+
+ String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+E->get().image_url.md5_text());
+ Vector<String> headers;
+
+ if(FileAccess::exists(cache_filename_base+".etag") && FileAccess::exists(cache_filename_base+".data")) {
+ FileAccess* file = FileAccess::open(cache_filename_base+".etag", FileAccess::READ);
+ if (file) {
+ headers.push_back("If-None-Match: " + file->get_line());
+ file->close();
+ }
+ }
+
+ print_line("REQUEST ICON FOR: "+itos(E->get().asset_id));
+ Error err = E->get().request->request(E->get().image_url, headers);
+ if (err!=OK) {
+ to_delete.push_back(E->key());
+ } else {
+ E->get().active=true;
+ }
+ current_images++;
+ } else if (E->get().active) {
+ current_images++;
+ }
+ }
+
+ while(to_delete.size()) {
+ image_queue[to_delete.front()->get()].request->queue_delete();
+ image_queue.erase(to_delete.front()->get());
+ to_delete.pop_front();
+ }
+}
+
+void EditorAssetLibrary::_request_image(ObjectID p_for,String p_image_url,ImageType p_type,int p_image_index) {
+
+
+ ImageQueue iq;
+ iq.image_url=p_image_url;
+ iq.image_index=p_image_index;
+ iq.image_type=p_type;
+ iq.request = memnew( HTTPRequest );
+
+ iq.target=p_for;
+ iq.queue_id=++last_queue_id;
+ iq.active=false;
+
+ iq.request->connect("request_completed",this,"_image_request_completed",varray(iq.queue_id));
+
+ image_queue[iq.queue_id]=iq;
+
+ add_child(iq.request);
+
+ _image_update(true, false, PoolByteArray(), iq.queue_id);
+ _update_image_queue();
+
+
+}
+
+void EditorAssetLibrary::_repository_changed(int p_repository_id) {
+ host=repository->get_item_metadata(p_repository_id);
+ print_line(".." + host);
+ if(templates_only) {
+ _api_request("configure", REQUESTING_CONFIG, "?type=project");
+ } else {
+ _api_request("configure", REQUESTING_CONFIG);
+ }
+}
+
+void EditorAssetLibrary::_support_toggled(int p_support) {
+ support->get_popup()->set_item_checked(p_support, !support->get_popup()->is_item_checked(p_support));
+ _search();
+}
+
+void EditorAssetLibrary::_rerun_search(int p_ignore) {
+ _search();
+}
+
+void EditorAssetLibrary::_search(int p_page) {
+
+ String args;
+
+ if(templates_only) {
+ args += "?type=project&";
+ } else {
+ args += "?";
+ }
+ args+=String()+"sort="+sort_key[sort->get_selected()];
+
+
+ String support_list;
+ for(int i = 0; i < SUPPORT_MAX; i++) {
+ if(support->get_popup()->is_item_checked(i)) {
+ support_list += String(support_key[i]) + "+";
+ }
+ }
+ if(support_list != String()) {
+ args += "&support=" + support_list.substr(0, support_list.length() - 1);
+ }
+
+ if (categories->get_selected()>0) {
+
+ args+="&category="+itos(categories->get_item_metadata(categories->get_selected()));
+ }
+
+ if (reverse->is_pressed()) {
+
+ args+="&reverse=true";
+ }
+
+ if (filter->get_text()!=String()) {
+ args+="&filter="+filter->get_text().http_escape();
+ }
+
+ if (p_page>0) {
+ args+="&page="+itos(p_page);
+ }
+
+ _api_request("asset",REQUESTING_SEARCH,args);
+}
+
+HBoxContainer* EditorAssetLibrary::_make_pages(int p_page,int p_page_count,int p_page_len,int p_total_items,int p_current_items) {
+
+ HBoxContainer * hbc = memnew( HBoxContainer );
+
+ //do the mario
+ int from = p_page-5;
+ if (from<0)
+ from=0;
+ int to = from+10;
+ if (to>p_page_count)
+ to=p_page_count;
+
+ Color gray = Color(0.65,0.65,0.65);
+
+ hbc->add_spacer();
+ hbc->add_constant_override("separation",10);
+
+ if(p_page != 0) {
+ LinkButton *first = memnew( LinkButton );
+ first->set_text("first");
+ first->add_color_override("font_color", gray );
+ first->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ first->connect("pressed",this,"_search",varray(0));
+ hbc->add_child(first);
+ }
+
+ if (p_page>0) {
+ LinkButton *prev = memnew( LinkButton );
+ prev->set_text("prev");
+ prev->add_color_override("font_color", gray );
+ prev->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ prev->connect("pressed",this,"_search",varray(p_page-1));
+ hbc->add_child(prev);
+ }
+
+ for(int i=from;i<to;i++) {
+
+ if (i==p_page) {
+
+ Label *current = memnew(Label);
+ current->set_text(itos(i+1));
+ hbc->add_child(current);
+ } else {
+
+ LinkButton *current = memnew( LinkButton );
+ current->add_color_override("font_color", gray );
+ current->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ current->set_text(itos(i+1));
+ current->connect("pressed",this,"_search",varray(i));
+
+ hbc->add_child(current);
+
+ }
+ }
+
+ if (p_page<p_page_count-1) {
+ LinkButton *next = memnew( LinkButton );
+ next->set_text("next");
+ next->add_color_override("font_color", gray );
+ next->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ next->connect("pressed",this,"_search",varray(p_page+1));
+
+ hbc->add_child(next);
+ }
+
+ if(p_page != p_page_count-1) {
+ LinkButton *last = memnew( LinkButton );
+ last->set_text("last");
+ last->add_color_override("font_color", gray );
+ last->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+ hbc->add_child(last);
+ last->connect("pressed",this,"_search",varray(p_page_count-1));
+ }
+
+ Label *totals = memnew( Label );
+ totals->set_text("( "+itos(from*p_page_len)+" - "+itos(from*p_page_len+p_current_items-1)+" / "+itos(p_total_items)+" )");
+ hbc->add_child(totals);
+
+ hbc->add_spacer();
+
+ return hbc;
+}
+
+
+void EditorAssetLibrary::_api_request(const String& p_request, RequestType p_request_type, const String& p_arguments) {
+
+ if (requesting!=REQUESTING_NONE) {
+ request->cancel_request();
+ }
+
+ requesting=p_request_type;
+
+ error_hb->hide();
+ request->request(host+"/"+p_request+p_arguments);
+}
+
+
+
+void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const PoolStringArray& headers, const PoolByteArray& p_data) {
+
+
+ String str;
+
+ {
+ int datalen=p_data.size();
+ PoolByteArray::Read r = p_data.read();
+ str.parse_utf8((const char*)r.ptr(),datalen);
+ }
+
+ bool error_abort=true;
+
+ switch(p_status) {
+
+ case HTTPRequest::RESULT_CANT_RESOLVE: {
+ error_label->set_text("Can't resolve hostname: "+host);
+ } break;
+ case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
+ case HTTPRequest::RESULT_CONNECTION_ERROR:
+ case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: {
+ error_label->set_text("Connection error, please try again.");
+ } break;
+ case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
+ case HTTPRequest::RESULT_CANT_CONNECT: {
+ error_label->set_text("Can't connect to host: "+host);
+ } break;
+ case HTTPRequest::RESULT_NO_RESPONSE: {
+ error_label->set_text("No response from host: "+host);
+ } break;
+ case HTTPRequest::RESULT_REQUEST_FAILED: {
+ error_label->set_text("Request failed, return code: "+itos(p_code));
+ } break;
+ case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
+ error_label->set_text("Request failed, too many redirects");
+
+ } break;
+ default: {
+ if (p_code!=200) {
+ error_label->set_text("Request failed, return code: "+itos(p_code));
+ } else {
+
+ error_abort=false;
+ }
+ } break;
+
+ }
+
+
+ if (error_abort) {
+ error_hb->show();
+ return;
+ }
+
+ print_line("response: "+itos(p_status)+" code: "+itos(p_code));
+
+ Dictionary d;
+ {
+ Variant js;
+ String errs;
+ int errl;
+ JSON::parse(str,js,errs,errl);
+ d=js;
+ }
+
+
+ print_line(Variant(d).get_construct_string());
+
+ RequestType requested = requesting;
+ requesting=REQUESTING_NONE;
+
+ switch(requested) {
+ case REQUESTING_CONFIG: {
+
+ categories->clear();
+ categories->add_item("All");
+ categories->set_item_metadata(0,0);
+ if (d.has("categories")) {
+ Array clist = d["categories"];
+ for(int i=0;i<clist.size();i++) {
+ Dictionary cat = clist[i];
+ if (!cat.has("name") || !cat.has("id"))
+ continue;
+ String name=cat["name"];
+ int id=cat["id"];
+ categories->add_item(name);
+ categories->set_item_metadata( categories->get_item_count() -1, id);
+ category_map[cat["id"]] = name;
+ }
+ }
+
+ _search();
+ } break;
+ case REQUESTING_SEARCH: {
+ if (asset_items) {
+ memdelete(asset_items);
+ }
+
+ if (asset_top_page) {
+ memdelete(asset_top_page);
+ }
+
+ if (asset_bottom_page) {
+ memdelete(asset_bottom_page);
+ }
+
+ int page=0;
+ int pages=1;
+ int page_len=10;
+ int total_items=1;
+ Array result;
+
+
+ if (d.has("page")) {
+ page=d["page"];
+ }
+ if (d.has("pages")) {
+ pages=d["pages"];
+ }
+ if (d.has("page_length")) {
+ page_len=d["page_length"];
+ }
+ if (d.has("total")) {
+ total_items=d["total"];
+ }
+ if (d.has("result")) {
+ result=d["result"];
+ }
+
+ asset_top_page = _make_pages(page,pages,page_len,total_items,result.size());
+ library_vb->add_child(asset_top_page);
+
+ asset_items = memnew( GridContainer );
+ asset_items->set_columns(2);
+ asset_items->add_constant_override("hseparation",10);
+ asset_items->add_constant_override("vseparation",10);
+
+ library_vb->add_child(asset_items);
+
+ asset_bottom_page = _make_pages(page,pages,page_len,total_items,result.size());
+ library_vb->add_child(asset_bottom_page);
+
+ for(int i=0;i<result.size();i++) {
+
+ Dictionary r = result[i];
+
+ ERR_CONTINUE(!r.has("title"));
+ ERR_CONTINUE(!r.has("asset_id"));
+ ERR_CONTINUE(!r.has("author"));
+ ERR_CONTINUE(!r.has("author_id"));
+ ERR_CONTINUE(!r.has("category_id"));
+ ERR_FAIL_COND(!category_map.has(r["category_id"]));
+ ERR_CONTINUE(!r.has("rating"));
+ ERR_CONTINUE(!r.has("cost"));
+
+
+ EditorAssetLibraryItem *item = memnew( EditorAssetLibraryItem );
+ asset_items->add_child(item);
+ item->configure(r["title"],r["asset_id"],category_map[r["category_id"]],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"]);
+ item->connect("asset_selected",this,"_select_asset");
+ item->connect("author_selected",this,"_select_author");
+ item->connect("category_selected",this,"_select_category");
+
+ if(r.has("icon_url") && r["icon_url"] != "") {
+ _request_image(item->get_instance_ID(),r["icon_url"],IMAGE_QUEUE_ICON,0);
+ }
+ }
+ } break;
+ case REQUESTING_ASSET: {
+ Dictionary r = d;
+
+ ERR_FAIL_COND(!r.has("title"));
+ ERR_FAIL_COND(!r.has("asset_id"));
+ ERR_FAIL_COND(!r.has("author"));
+ ERR_FAIL_COND(!r.has("author_id"));
+ ERR_FAIL_COND(!r.has("version"));
+ ERR_FAIL_COND(!r.has("version_string"));
+ ERR_FAIL_COND(!r.has("category_id"));
+ ERR_FAIL_COND(!category_map.has(r["category_id"]));
+ ERR_FAIL_COND(!r.has("rating"));
+ ERR_FAIL_COND(!r.has("cost"));
+ ERR_FAIL_COND(!r.has("description"));
+ ERR_FAIL_COND(!r.has("download_url"));
+ ERR_FAIL_COND(!r.has("download_hash"));
+ ERR_FAIL_COND(!r.has("browse_url"));
+
+ if (description) {
+ memdelete(description);
+ }
+
+ description = memnew( EditorAssetLibraryItemDescription );
+ add_child(description);
+ description->popup_centered_minsize();
+ description->connect("confirmed",this,"_install_asset");
+
+ description->configure(r["title"],r["asset_id"],category_map[r["category_id"]],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"],r["version"],r["version_string"],r["description"],r["download_url"],r["browse_url"], r["download_hash"]);
+ /*item->connect("asset_selected",this,"_select_asset");
+ item->connect("author_selected",this,"_select_author");
+ item->connect("category_selected",this,"_category_selected");*/
+
+ if(r.has("icon_url") && r["icon_url"] != "") {
+ _request_image(description->get_instance_ID(),r["icon_url"],IMAGE_QUEUE_ICON,0);
+ }
+
+ if (d.has("previews")) {
+ Array previews = d["previews"];
+
+ for(int i=0;i<previews.size();i++) {
+
+
+ Dictionary p=previews[i];
+
+ ERR_CONTINUE(!p.has("type"));
+ ERR_CONTINUE(!p.has("link"));
+
+ bool is_video=p.has("type") && String(p["type"])=="video";
+ String video_url;
+ if (is_video && p.has("link")) {
+ video_url=p["link"];
+ }
+
+ description->add_preview(i,is_video,video_url);
+
+ if(p.has("thumbnail")) {
+ _request_image(description->get_instance_ID(),p["thumbnail"],IMAGE_QUEUE_THUMBNAIL,i);
+ }
+ if(is_video) {
+ //_request_image(description->get_instance_ID(),p["link"],IMAGE_QUEUE_SCREENSHOT,i);
+ } else {
+ _request_image(description->get_instance_ID(),p["link"],IMAGE_QUEUE_SCREENSHOT,i);
+ }
+
+ }
+ }
+ } break;
+ default: break;
+ }
+
+}
+
+
+void EditorAssetLibrary::_asset_file_selected(const String& p_file) {
+
+ if (asset_installer) {
+ memdelete( asset_installer );
+ asset_installer=NULL;
+ }
+
+ asset_installer = memnew( EditorAssetInstaller );
+ add_child(asset_installer);
+ asset_installer->open(p_file);
+
+
+}
+
+void EditorAssetLibrary::_asset_open() {
+
+ asset_open->popup_centered_ratio();
+}
+
+void EditorAssetLibrary::_manage_plugins() {
+
+ ProjectSettings::get_singleton()->popup_project_settings();
+ ProjectSettings::get_singleton()->set_plugins_page();
+}
+
+
+
+void EditorAssetLibrary::_install_external_asset(String p_zip_path,String p_title) {
+
+ emit_signal("install_asset",p_zip_path,p_title);
+}
+
+void EditorAssetLibrary::_bind_methods() {
+
+ ClassDB::bind_method("_http_request_completed",&EditorAssetLibrary::_http_request_completed);
+ ClassDB::bind_method("_select_asset",&EditorAssetLibrary::_select_asset);
+ ClassDB::bind_method("_select_author",&EditorAssetLibrary::_select_author);
+ ClassDB::bind_method("_select_category",&EditorAssetLibrary::_select_category);
+ ClassDB::bind_method("_image_request_completed",&EditorAssetLibrary::_image_request_completed);
+ ClassDB::bind_method("_search",&EditorAssetLibrary::_search,DEFVAL(0));
+ ClassDB::bind_method("_install_asset",&EditorAssetLibrary::_install_asset);
+ ClassDB::bind_method("_manage_plugins",&EditorAssetLibrary::_manage_plugins);
+ ClassDB::bind_method("_asset_open",&EditorAssetLibrary::_asset_open);
+ ClassDB::bind_method("_asset_file_selected",&EditorAssetLibrary::_asset_file_selected);
+ ClassDB::bind_method("_repository_changed",&EditorAssetLibrary::_repository_changed);
+ ClassDB::bind_method("_support_toggled",&EditorAssetLibrary::_support_toggled);
+ ClassDB::bind_method("_rerun_search",&EditorAssetLibrary::_rerun_search);
+ ClassDB::bind_method("_install_external_asset",&EditorAssetLibrary::_install_external_asset);
+
+
+
+ ADD_SIGNAL(MethodInfo("install_asset",PropertyInfo(Variant::STRING,"zip_path"),PropertyInfo(Variant::STRING,"name")));
+
+}
+
+EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
+
+ templates_only=p_templates_only;
+
+ Ref<StyleBoxEmpty> border;
+ border.instance();
+ border->set_default_margin(MARGIN_LEFT,15);
+ border->set_default_margin(MARGIN_RIGHT,15);
+ border->set_default_margin(MARGIN_BOTTOM,5);
+ border->set_default_margin(MARGIN_TOP,5);
+
+ add_style_override("panel",border);
+
+ VBoxContainer *library_main = memnew( VBoxContainer );
+
+ add_child(library_main);
+
+ HBoxContainer *search_hb = memnew( HBoxContainer );
+
+ library_main->add_child(search_hb);
+ library_main->add_constant_override("separation",10);
+
+
+
+ search_hb->add_child( memnew( Label(TTR("Search:")+" ")));
+ filter =memnew( LineEdit );
+ search_hb->add_child(filter);
+ filter->set_h_size_flags(SIZE_EXPAND_FILL);
+ filter->connect("text_entered",this,"_search");
+ search = memnew( Button("Search"));
+ search->connect("pressed",this,"_search");
+ search_hb->add_child(search);
+
+ if (!p_templates_only)
+ search_hb->add_child(memnew( VSeparator ));
+
+ Button * open_asset = memnew( Button );
+ open_asset->set_text("Import");
+ search_hb->add_child(open_asset);
+ open_asset->connect("pressed",this,"_asset_open");
+
+ Button * plugins = memnew( Button );
+ plugins->set_text("Plugins");
+ search_hb->add_child(plugins);
+ plugins->connect("pressed",this,"_manage_plugins");
+
+ if (p_templates_only) {
+ open_asset->hide();
+ plugins->hide();
+ }
+
+
+ HBoxContainer *search_hb2 = memnew( HBoxContainer );
+ library_main->add_child(search_hb2);
+
+ search_hb2->add_child( memnew( Label(TTR("Sort:")+" ")));
+ sort = memnew( OptionButton );
+ for(int i=0;i<SORT_MAX;i++) {
+ sort->add_item(sort_text[i]);
+ }
+
+ search_hb2->add_child(sort);
+
+ sort->set_h_size_flags(SIZE_EXPAND_FILL);
+ sort->connect("item_selected", this, "_rerun_search");
+
+ reverse = memnew( ToolButton );
+ reverse->set_toggle_mode(true);
+ reverse->connect("toggled", this, "_rerun_search");
+ //reverse->set_text(TTR("Reverse"));
+ search_hb2->add_child(reverse);
+
+ search_hb2->add_child(memnew(VSeparator));
+
+ //search_hb2->add_spacer();
+
+ search_hb2->add_child( memnew( Label(TTR("Category:")+" ")));
+ categories = memnew( OptionButton );
+ categories->add_item(TTR("All"));
+ search_hb2->add_child(categories);
+ categories->set_h_size_flags(SIZE_EXPAND_FILL);
+ //search_hb2->add_spacer();
+ categories->connect("item_selected", this, "_rerun_search");
+
+ search_hb2->add_child(memnew(VSeparator));
+
+ search_hb2->add_child( memnew( Label(TTR("Site:")+" ")));
+ repository = memnew( OptionButton );
+
+ repository->add_item("Godot");
+ repository->set_item_metadata(0, "https://godotengine.org/asset-library/api");
+ repository->add_item("Localhost"); // TODO: Maybe remove?
+ repository->set_item_metadata(1, "http://127.0.0.1/asset-library/api");
+ repository->connect("item_selected",this,"_repository_changed");
+
+ search_hb2->add_child(repository);
+ repository->set_h_size_flags(SIZE_EXPAND_FILL);
+
+
+ search_hb2->add_child(memnew(VSeparator));
+
+ support = memnew( MenuButton );
+ search_hb2->add_child(support);
+ support->set_text(TTR("Support.."));
+ support->get_popup()->add_check_item(TTR("Official"),SUPPORT_OFFICIAL);
+ support->get_popup()->add_check_item(TTR("Community"),SUPPORT_COMMUNITY);
+ support->get_popup()->add_check_item(TTR("Testing"),SUPPORT_TESTING);
+ support->get_popup()->set_item_checked(SUPPORT_OFFICIAL,true);
+ support->get_popup()->set_item_checked(SUPPORT_COMMUNITY,true);
+ support->get_popup()->connect("id_pressed",this,"_support_toggled");
+
+ /////////
+
+ PanelContainer * library_scroll_bg = memnew( PanelContainer );
+ library_main->add_child(library_scroll_bg);
+ library_scroll_bg->add_style_override("panel",get_stylebox("normal","TextEdit"));
+ library_scroll_bg->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ library_scroll = memnew( ScrollContainer );
+ library_scroll->set_enable_v_scroll(true);
+ library_scroll->set_enable_h_scroll(false);
+
+ library_scroll_bg->add_child(library_scroll);
+
+
+ Ref<StyleBoxEmpty> border2;
+ border2.instance();
+ border2->set_default_margin(MARGIN_LEFT,15);
+ border2->set_default_margin(MARGIN_RIGHT,35);
+ border2->set_default_margin(MARGIN_BOTTOM,15);
+ border2->set_default_margin(MARGIN_TOP,15);
+
+
+ PanelContainer * library_vb_border = memnew( PanelContainer );
+ library_scroll->add_child(library_vb_border);
+ library_vb_border->add_style_override("panel",border2);
+ library_vb_border->set_h_size_flags(SIZE_EXPAND_FILL);
+ library_vb_border->set_mouse_filter(MOUSE_FILTER_PASS);
+
+
+
+ library_vb = memnew( VBoxContainer );
+ library_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ library_vb_border->add_child(library_vb);
+ //margin_panel->set_stop_mouse(false);
+
+ asset_top_page = memnew( HBoxContainer );
+ library_vb->add_child(asset_top_page);
+
+ asset_items = memnew( GridContainer );
+ asset_items->set_columns(2);
+ asset_items->add_constant_override("hseparation",10);
+ asset_items->add_constant_override("vseparation",10);
+
+ library_vb->add_child(asset_items);
+
+ asset_bottom_page = memnew( HBoxContainer );
+ library_vb->add_child(asset_bottom_page);
+
+ request = memnew( HTTPRequest );
+ add_child(request);
+ request->set_use_threads(EDITOR_DEF("asset_library/use_threads",true));
+ request->connect("request_completed",this,"_http_request_completed");
+
+ last_queue_id=0;
+
+ library_vb->add_constant_override("separation",20);
+
+ load_status = memnew( ProgressBar );
+ load_status->set_min(0);
+ load_status->set_max(1);
+ load_status->set_step(0.001);
+ library_main->add_child(load_status);
+
+ error_hb = memnew( HBoxContainer );
+ library_main->add_child(error_hb);
+ error_label = memnew( Label );
+ error_label->add_color_override("color",Color(1,0.4,0.3));
+ error_hb->add_child(error_label);
+
+ description = NULL;
+
+ set_process(true);
+
+ downloads_scroll = memnew( ScrollContainer );
+ downloads_scroll->set_enable_h_scroll(true);
+ downloads_scroll->set_enable_v_scroll(false);
+ library_main->add_child(downloads_scroll);
+ downloads_hb = memnew( HBoxContainer );
+ downloads_scroll->add_child(downloads_hb);
+
+ asset_open = memnew( EditorFileDialog );
+
+ asset_open->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ asset_open->add_filter("*.zip ; "+TTR("Assets ZIP File"));
+ asset_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ add_child(asset_open);
+ asset_open->connect("file_selected",this,"_asset_file_selected");
+
+ asset_installer=NULL;
+
+}
+
+
+///////
+
+
+void AssetLibraryEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ addon_library->show();
+ } else {
+
+ addon_library->hide();
+ }
+
+}
+
+AssetLibraryEditorPlugin::AssetLibraryEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ addon_library = memnew( EditorAssetLibrary );
+ addon_library->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ editor->get_viewport()->add_child(addon_library);
+ addon_library->set_area_as_parent_rect();
+ addon_library->hide();
+
+}
+
+AssetLibraryEditorPlugin::~AssetLibraryEditorPlugin() {
+
+}
diff --git a/tools/editor/asset_library_editor_plugin.h b/editor/asset_library_editor_plugin.h
index 0598ea90ea..0598ea90ea 100644
--- a/tools/editor/asset_library_editor_plugin.h
+++ b/editor/asset_library_editor_plugin.h
diff --git a/tools/editor/call_dialog.cpp b/editor/call_dialog.cpp
index 6dfeb87dfd..6dfeb87dfd 100644
--- a/tools/editor/call_dialog.cpp
+++ b/editor/call_dialog.cpp
diff --git a/editor/call_dialog.h b/editor/call_dialog.h
new file mode 100644
index 0000000000..56fc07c3df
--- /dev/null
+++ b/editor/call_dialog.h
@@ -0,0 +1,85 @@
+/*************************************************************************/
+/* call_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 CALL_DIALOG_H
+#define CALL_DIALOG_H
+
+#include "scene/gui/popup.h"
+#include "scene/gui/button.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/label.h"
+#include "scene/gui/line_edit.h"
+#include "editor/property_editor.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+#if 0
+
+class CallDialogParams;
+
+class CallDialog : public Popup {
+
+ GDCLASS( CallDialog, Popup );
+
+
+ Label* method_label;
+ Tree *tree;
+ Button *call;
+ Button *cancel;
+
+ CallDialogParams *call_params;
+ PropertyEditor *property_editor;
+
+ Label *return_label;
+ LineEdit *return_value;
+ Object *object;
+ StringName selected;
+
+ Vector<MethodInfo> methods;
+
+
+ void _item_selected();
+ void _update_method_list();
+ void _call();
+ void _cancel();
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+ void set_object(Object *p_object,StringName p_selected="");
+
+ CallDialog();
+ ~CallDialog();
+
+};
+
+#endif
+#endif
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
new file mode 100644
index 0000000000..8e9925a0d3
--- /dev/null
+++ b/editor/code_editor.cpp
@@ -0,0 +1,1323 @@
+/*************************************************************************/
+/* code_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "code_editor.h"
+
+#include "editor_settings.h"
+#include "scene/gui/margin_container.h"
+#include "scene/gui/separator.h"
+#include "scene/resources/dynamic_font.h"
+#include "os/keyboard.h"
+#include "editor/editor_scale.h"
+
+void GotoLineDialog::popup_find_line(TextEdit *p_edit) {
+
+ text_editor=p_edit;
+
+ line->set_text(itos(text_editor->cursor_get_line()));
+ line->select_all();
+ popup_centered(Size2(180,80));
+ line->grab_focus();
+}
+
+
+int GotoLineDialog::get_line() const {
+
+ return line->get_text().to_int();
+}
+
+
+void GotoLineDialog::ok_pressed() {
+
+ if (get_line()<1 || get_line()>text_editor->get_line_count())
+ return;
+ text_editor->cursor_set_line(get_line()-1);
+ hide();
+}
+
+GotoLineDialog::GotoLineDialog() {
+
+ set_title(TTR("Go to Line"));
+ Label *l = memnew(Label);
+ l->set_text(TTR("Line Number:"));
+ l->set_pos(Point2(5,5));
+ add_child(l);
+
+ line = memnew( LineEdit );
+ line->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ line->set_begin( Point2(15,22) );
+ line->set_end( Point2(15,35) );
+ add_child(line);
+ register_text_enter(line);
+ text_editor=NULL;
+
+ set_hide_on_ok(false);
+}
+
+
+void FindReplaceBar::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_READY) {
+
+ find_prev->set_icon(get_icon("MoveUp", "EditorIcons"));
+ find_next->set_icon(get_icon("MoveDown", "EditorIcons"));
+ hide_button->set_normal_texture(get_icon("Close","EditorIcons"));
+ hide_button->set_hover_texture(get_icon("CloseHover","EditorIcons"));
+ hide_button->set_pressed_texture(get_icon("Close","EditorIcons"));
+
+ } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+
+ set_process_unhandled_input(is_visible_in_tree());
+ }
+}
+
+void FindReplaceBar::_unhandled_input(const InputEvent &p_event) {
+
+ if (p_event.type == InputEvent::KEY) {
+
+ const InputEventKey& k = p_event.key;
+
+ if (k.pressed && (text_edit->has_focus() || text_vbc->is_a_parent_of(get_focus_owner()))) {
+
+ bool accepted = true;
+
+ switch (k.scancode) {
+
+ case KEY_ESCAPE: {
+
+ _hide_bar();
+ } break;
+ default: {
+
+ accepted = false;
+ } break;
+ }
+
+ if (accepted) {
+ accept_event();
+ }
+ }
+ }
+}
+
+bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) {
+
+ int line, col;
+ String text=get_search_text();
+
+ bool found=text_edit->search(text,p_flags,p_from_line,p_from_col,line,col);
+
+ if (found) {
+ if (!preserve_cursor) {
+ text_edit->cursor_set_line(line, false);
+ text_edit->cursor_set_column(col+text.length(), false);
+ text_edit->center_viewport_to_cursor();
+ }
+
+ text_edit->set_search_text(text);
+ text_edit->set_search_flags(p_flags);
+ text_edit->set_current_search_result(line,col);
+
+ result_line=line;
+ result_col=col;
+
+ set_error("");
+ } else {
+ result_line=-1;
+ result_col=-1;
+ text_edit->set_search_text("");
+ set_error(text.empty()?"":TTR("No Matches"));
+ }
+
+ return found;
+}
+
+void FindReplaceBar::_replace() {
+
+ if (result_line!=-1 && result_col!=-1) {
+ text_edit->begin_complex_operation();
+
+ text_edit->select(result_line,result_col,result_line,result_col+get_search_text().length());
+ text_edit->insert_text_at_cursor(get_replace_text());
+
+ text_edit->end_complex_operation();
+ }
+
+ search_current();
+}
+
+void FindReplaceBar::_replace_all() {
+
+ // line as x so it gets priority in comparison, column as y
+ Point2i orig_cursor(text_edit->cursor_get_line(),text_edit->cursor_get_column());
+ Point2i prev_match=Point2(-1,-1);
+
+ bool selection_enabled = text_edit->is_selection_active();
+ Point2i selection_begin,selection_end;
+ if (selection_enabled) {
+ selection_begin=Point2i(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
+ selection_end=Point2i(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
+ }
+
+ int vsval = text_edit->get_v_scroll();
+
+ text_edit->cursor_set_line(0);
+ text_edit->cursor_set_column(0);
+
+ String replace_text=get_replace_text();
+ int search_text_len=get_search_text().length();
+
+ int rc=0;
+
+ replace_all_mode = true;
+
+ text_edit->begin_complex_operation();
+
+ while (search_next()) {
+
+ // replace area
+ Point2i match_from(result_line,result_col);
+ Point2i match_to(result_line,result_col+search_text_len);
+
+ if (match_from < prev_match)
+ break; // done
+
+ prev_match=Point2i(result_line,result_col+replace_text.length());
+
+ text_edit->select(result_line,result_col,result_line,match_to.y);
+
+ if (selection_enabled && is_selection_only()) {
+
+ if (match_from<selection_begin || match_to>selection_end)
+ continue;
+
+ // replace but adjust selection bounds
+ text_edit->insert_text_at_cursor(replace_text);
+ if (match_to.x==selection_end.x)
+ selection_end.y+=replace_text.length()-search_text_len;
+ } else {
+ // just replace
+ text_edit->insert_text_at_cursor(replace_text);
+ }
+
+ rc++;
+ }
+
+ text_edit->end_complex_operation();
+
+ replace_all_mode = false;
+
+ // restore editor state (selection, cursor, scroll)
+ text_edit->cursor_set_line(orig_cursor.x);
+ text_edit->cursor_set_column(orig_cursor.y);
+
+ if (selection_enabled && is_selection_only()) {
+ // reselect
+ text_edit->select(selection_begin.x,selection_begin.y,selection_end.x,selection_end.y);
+ } else {
+ text_edit->deselect();
+ }
+
+ text_edit->set_v_scroll(vsval);
+ set_error(vformat(TTR("Replaced %d Ocurrence(s)."), rc));
+}
+
+void FindReplaceBar::_get_search_from(int& r_line, int& r_col) {
+
+ r_line=text_edit->cursor_get_line();
+ r_col=text_edit->cursor_get_column();
+
+ if (text_edit->is_selection_active() && !replace_all_mode) {
+
+ int selection_line=text_edit->get_selection_from_line();
+
+ if (text_edit->get_selection_text()==get_search_text() && r_line==selection_line) {
+
+ int selection_from_col=text_edit->get_selection_from_column();
+
+ if (r_col>=selection_from_col && r_col<=text_edit->get_selection_to_column()) {
+ r_col=selection_line;
+ r_col=selection_from_col;
+ }
+ }
+ }
+
+ if (r_line==result_line && r_col>=result_col && r_col<=result_col+get_search_text().length()) {
+ r_col=result_col;
+ }
+}
+
+bool FindReplaceBar::search_current() {
+
+ uint32_t flags=0;
+
+ if (is_whole_words())
+ flags|=TextEdit::SEARCH_WHOLE_WORDS;
+ if (is_case_sensitive())
+ flags|=TextEdit::SEARCH_MATCH_CASE;
+
+ int line, col;
+ _get_search_from(line, col);
+
+ return _search(flags,line,col);
+}
+
+bool FindReplaceBar::search_prev() {
+
+ uint32_t flags=0;
+ String text = get_search_text();
+
+ if (is_whole_words())
+ flags|=TextEdit::SEARCH_WHOLE_WORDS;
+ if (is_case_sensitive())
+ flags|=TextEdit::SEARCH_MATCH_CASE;
+
+ flags|=TextEdit::SEARCH_BACKWARDS;
+
+ int line, col;
+ _get_search_from(line, col);
+
+ col-=text.length();
+ if (col<0) {
+ line-=1;
+ if (line<0)
+ line=text_edit->get_line_count()-1;
+ col=text_edit->get_line(line).length();
+ }
+
+ return _search(flags,line,col);
+}
+
+bool FindReplaceBar::search_next() {
+
+ uint32_t flags=0;
+ String text = get_search_text();
+
+ if (is_whole_words())
+ flags|=TextEdit::SEARCH_WHOLE_WORDS;
+ if (is_case_sensitive())
+ flags|=TextEdit::SEARCH_MATCH_CASE;
+
+ int line, col;
+ _get_search_from(line, col);
+
+ if (line==result_line && col==result_col) {
+ col+=text.length();
+ if (col>text_edit->get_line(line).length()) {
+ line+=1;
+ if (line>=text_edit->get_line_count())
+ line=0;
+ col=0;
+ }
+ }
+
+ return _search(flags,line,col);
+}
+
+void FindReplaceBar::_hide_bar() {
+
+ if (replace_text->has_focus() || search_text->has_focus())
+ text_edit->grab_focus();
+
+ text_edit->set_search_text("");
+ result_line = -1;
+ result_col = -1;
+ replace_hbc->hide();
+ replace_options_hbc->hide();
+ hide();
+}
+
+void FindReplaceBar::_show_search() {
+
+ show();
+ search_text->grab_focus();
+
+ if (text_edit->is_selection_active() && !selection_only->is_pressed()) {
+ search_text->set_text(text_edit->get_selection_text());
+ }
+
+ if (!get_search_text().empty()) {
+ search_text->select_all();
+ search_text->set_cursor_pos(search_text->get_text().length());
+ search_current();
+ }
+}
+
+void FindReplaceBar::popup_search() {
+
+ replace_hbc->hide();
+ replace_options_hbc->hide();
+ _show_search();
+}
+
+void FindReplaceBar::popup_replace() {
+
+
+ if (!replace_hbc->is_visible_in_tree() || !replace_options_hbc->is_visible_in_tree()) {
+ replace_text->clear();
+ replace_hbc->show();
+ replace_options_hbc->show();
+
+ }
+
+ selection_only->set_pressed( (text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line()) );
+
+ _show_search();
+}
+
+void FindReplaceBar::_search_options_changed(bool p_pressed) {
+
+ search_current();
+}
+
+void FindReplaceBar::_editor_text_changed() {
+
+ if (is_visible_in_tree()) {
+ preserve_cursor=true;
+ search_current();
+ preserve_cursor=false;
+ }
+}
+
+void FindReplaceBar::_search_text_changed(const String& p_text) {
+
+ search_current();
+}
+
+void FindReplaceBar::_search_text_entered(const String& p_text) {
+
+ search_next();
+}
+
+void FindReplaceBar::_replace_text_entered(const String& p_text) {
+
+ if (selection_only->is_pressed() && text_edit->is_selection_active()) {
+ _replace_all();
+ _hide_bar();
+ }
+}
+
+String FindReplaceBar::get_search_text() const {
+
+ return search_text->get_text();
+}
+
+String FindReplaceBar::get_replace_text() const {
+
+ return replace_text->get_text();
+}
+
+bool FindReplaceBar::is_case_sensitive() const {
+
+ return case_sensitive->is_pressed();
+}
+
+bool FindReplaceBar::is_whole_words() const {
+
+ return whole_words->is_pressed();
+}
+
+bool FindReplaceBar::is_selection_only() const {
+
+ return selection_only->is_pressed();
+}
+
+void FindReplaceBar::set_error(const String &p_label) {
+
+ error_label->set_text(p_label);
+}
+
+void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) {
+
+ text_edit = p_text_edit;
+ text_edit->connect("text_changed",this,"_editor_text_changed");
+}
+
+void FindReplaceBar::_bind_methods() {
+
+ ClassDB::bind_method("_unhandled_input",&FindReplaceBar::_unhandled_input);
+
+ ClassDB::bind_method("_editor_text_changed",&FindReplaceBar::_editor_text_changed);
+ ClassDB::bind_method("_search_text_changed",&FindReplaceBar::_search_text_changed);
+ ClassDB::bind_method("_search_text_entered",&FindReplaceBar::_search_text_entered);
+ ClassDB::bind_method("_replace_text_entered",&FindReplaceBar::_replace_text_entered);
+ ClassDB::bind_method("_search_current",&FindReplaceBar::search_current);
+ ClassDB::bind_method("_search_next",&FindReplaceBar::search_next);
+ ClassDB::bind_method("_search_prev",&FindReplaceBar::search_prev);
+ ClassDB::bind_method("_replace_pressed",&FindReplaceBar::_replace);
+ ClassDB::bind_method("_replace_all_pressed",&FindReplaceBar::_replace_all);
+ ClassDB::bind_method("_search_options_changed",&FindReplaceBar::_search_options_changed);
+ ClassDB::bind_method("_hide_pressed",&FindReplaceBar::_hide_bar);
+
+ ADD_SIGNAL(MethodInfo("search"));
+}
+
+FindReplaceBar::FindReplaceBar() {
+
+ replace_all_mode=false;
+ preserve_cursor=false;
+
+ text_vbc = memnew(VBoxContainer);
+ add_child(text_vbc);
+
+ HBoxContainer *search_hbc = memnew(HBoxContainer);
+ text_vbc->add_child(search_hbc);
+
+ search_text = memnew(LineEdit);
+ search_hbc->add_child(search_text);
+ search_text->set_custom_minimum_size(Size2(200, 0));
+ search_text->connect("text_changed",this,"_search_text_changed");
+ search_text->connect("text_entered",this,"_search_text_entered");
+
+ find_prev = memnew(ToolButton);
+ search_hbc->add_child(find_prev);
+ find_prev->set_focus_mode(FOCUS_NONE);
+ find_prev->connect("pressed",this,"_search_prev");
+
+ find_next = memnew(ToolButton);
+ search_hbc->add_child(find_next);
+ find_next->set_focus_mode(FOCUS_NONE);
+ find_next->connect("pressed",this,"_search_next");
+
+ replace_hbc = memnew(HBoxContainer);
+ text_vbc->add_child(replace_hbc);
+ replace_hbc->hide();
+
+ replace_text = memnew(LineEdit);
+ replace_hbc->add_child(replace_text);
+ replace_text->set_custom_minimum_size(Size2(200, 0));
+ replace_text->connect("text_entered",this,"_replace_text_entered");
+
+
+ replace = memnew(Button);
+ replace_hbc->add_child(replace);
+ replace->set_text(TTR("Replace"));
+ //replace->set_focus_mode(FOCUS_NONE);
+ replace->connect("pressed",this,"_replace_pressed");
+
+ replace_all = memnew(Button);
+ replace_hbc->add_child(replace_all);
+ replace_all->set_text(TTR("Replace All"));
+ //replace_all->set_focus_mode(FOCUS_NONE);
+ replace_all->connect("pressed",this,"_replace_all_pressed");
+
+ Control *spacer_split = memnew( Control );
+ spacer_split->set_custom_minimum_size(Size2(0, 1));
+ text_vbc->add_child(spacer_split);
+
+ VBoxContainer *options_vbc = memnew(VBoxContainer);
+ add_child(options_vbc);
+ options_vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *search_options = memnew(HBoxContainer);
+ options_vbc->add_child(search_options);
+
+ case_sensitive = memnew(CheckBox);
+ search_options->add_child(case_sensitive);
+ case_sensitive->set_text(TTR("Match Case"));
+ case_sensitive->set_focus_mode(FOCUS_NONE);
+ case_sensitive->connect("toggled",this,"_search_options_changed");
+
+ whole_words = memnew(CheckBox);
+ search_options->add_child(whole_words);
+ whole_words->set_text(TTR("Whole Words"));
+ whole_words->set_focus_mode(FOCUS_NONE);
+ whole_words->connect("toggled",this,"_search_options_changed");
+
+ error_label = memnew(Label);
+ search_options->add_child(error_label);
+ error_label->add_color_override("font_color", Color(1,1,0,1));
+ error_label->add_color_override("font_color_shadow", Color(0,0,0,1));
+ error_label->add_constant_override("shadow_as_outline", 1);
+
+ search_options->add_spacer();
+
+ hide_button = memnew(TextureButton);
+ search_options->add_child(hide_button);
+ hide_button->set_focus_mode(FOCUS_NONE);
+ hide_button->connect("pressed",this,"_hide_pressed");
+
+ replace_options_hbc = memnew(HBoxContainer);
+ options_vbc->add_child(replace_options_hbc);
+ replace_options_hbc->hide();
+
+ selection_only = memnew(CheckBox);
+ replace_options_hbc->add_child(selection_only);
+ selection_only->set_text(TTR("Selection Only"));
+ selection_only->set_focus_mode(FOCUS_NONE);
+ selection_only->connect("toggled",this,"_search_options_changed");
+}
+
+
+void FindReplaceDialog::popup_search() {
+
+ set_title(TTR("Search"));
+ replace_mc->hide();
+ replace_label->hide();
+ replace_vb->hide();
+ skip->hide();
+ popup_centered(Point2(300,190));
+ get_ok()->set_text(TTR("Find"));
+ search_text->grab_focus();
+ if (text_edit->is_selection_active() && ( text_edit->get_selection_from_line() == text_edit->get_selection_to_line())) {
+
+ search_text->set_text( text_edit->get_selection_text() );
+ }
+ search_text->select_all();
+
+ error_label->set_text("");
+
+}
+
+void FindReplaceDialog::popup_replace() {
+
+
+ set_title(TTR("Replace"));
+ bool do_selection=(text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line());
+
+ set_replace_selection_only(do_selection);
+
+ if (!do_selection && text_edit->is_selection_active()) {
+ search_text->set_text(text_edit->get_selection_text());
+ }
+
+ replace_mc->show();
+ replace_label->show();
+ replace_vb->show();
+ popup_centered(Point2(300,300));
+ if (search_text->get_text()!="" && replace_text->get_text()=="") {
+ search_text->select(0,0);
+ replace_text->grab_focus();
+ } else {
+ search_text->grab_focus();
+ search_text->select_all();
+ }
+ error_label->set_text("");
+
+ if (prompt->is_pressed()) {
+ skip->show();
+ get_ok()->set_text(TTR("Next"));
+ selection_only->set_disabled(true);
+
+ } else {
+ skip->hide();
+ get_ok()->set_text(TTR("Replace"));
+ selection_only->set_disabled(false);
+ }
+
+}
+
+void FindReplaceDialog::_search_callback() {
+
+ if (is_replace_mode())
+ _replace();
+ else
+ _search();
+
+}
+
+void FindReplaceDialog::_replace_skip_callback() {
+
+ _search();
+}
+
+void FindReplaceDialog::_replace() {
+
+ text_edit->begin_complex_operation();
+ if (is_replace_all_mode()) {
+
+ //line as x so it gets priority in comparison, column as y
+ Point2i orig_cursor(text_edit->cursor_get_line(),text_edit->cursor_get_column());
+ Point2i prev_match=Point2(-1,-1);
+
+
+ bool selection_enabled = text_edit->is_selection_active();
+ Point2i selection_begin,selection_end;
+ if (selection_enabled) {
+ selection_begin=Point2i(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
+ selection_end=Point2i(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
+ }
+ int vsval = text_edit->get_v_scroll();
+ //int hsval = text_edit->get_h_scroll();
+
+ text_edit->cursor_set_line(0);
+ text_edit->cursor_set_column(0);
+
+ int rc=0;
+
+ while(_search()) {
+
+ if (!text_edit->is_selection_active()) {
+ //search selects
+ break;
+ }
+
+ //replace area
+ Point2i match_from(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
+ Point2i match_to(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
+
+ if (match_from < prev_match)
+ break; //done
+
+ prev_match=match_to;
+
+ if (selection_enabled && is_replace_selection_only()) {
+
+ if (match_from<selection_begin || match_to>selection_end)
+ continue;
+
+ //replace but adjust selection bounds
+
+ text_edit->insert_text_at_cursor(get_replace_text());
+ if (match_to.x==selection_end.x)
+ selection_end.y+=get_replace_text().length() - get_search_text().length();
+ } else {
+ //just replace
+ text_edit->insert_text_at_cursor(get_replace_text());
+ }
+ rc++;
+
+ }
+ //restore editor state (selection, cursor, scroll)
+ text_edit->cursor_set_line(orig_cursor.x);
+ text_edit->cursor_set_column(orig_cursor.y);
+
+ if (selection_enabled && is_replace_selection_only()) {
+ //reselect
+ text_edit->select(selection_begin.x,selection_begin.y,selection_end.x,selection_end.y);
+ } else {
+ text_edit->deselect();
+ }
+
+ text_edit->set_v_scroll(vsval);
+ //text_edit->set_h_scroll(hsval);
+ error_label->set_text(vformat(TTR("Replaced %d ocurrence(s)."),rc));
+
+
+ //hide();
+ } else {
+
+ if (text_edit->get_selection_text()==get_search_text()) {
+
+ text_edit->insert_text_at_cursor(get_replace_text());
+ }
+
+ _search();
+ }
+ text_edit->end_complex_operation();
+}
+
+
+
+bool FindReplaceDialog::_search() {
+
+
+ String text=get_search_text();
+ uint32_t flags=0;
+
+ if (is_whole_words())
+ flags|=TextEdit::SEARCH_WHOLE_WORDS;
+ if (is_case_sensitive())
+ flags|=TextEdit::SEARCH_MATCH_CASE;
+ if (is_backwards())
+ flags|=TextEdit::SEARCH_BACKWARDS;
+
+ int line=text_edit->cursor_get_line(),col=text_edit->cursor_get_column();
+
+ if (is_backwards()) {
+ col-=1;
+ if (col<0) {
+ line-=1;
+ if (line<0) {
+ line=text_edit->get_line_count()-1;
+ }
+ col=text_edit->get_line(line).length();
+ }
+ }
+ bool found = text_edit->search(text,flags,line,col,line,col);
+
+
+ if (found) {
+ // print_line("found");
+ text_edit->cursor_set_line(line);
+ if (is_backwards())
+ text_edit->cursor_set_column(col);
+ else
+ text_edit->cursor_set_column(col+text.length());
+ text_edit->select(line,col,line,col+text.length());
+ set_error("");
+ return true;
+ } else {
+
+ set_error(TTR("Not found!"));
+ return false;
+ }
+
+}
+
+void FindReplaceDialog::_prompt_changed() {
+
+ if (prompt->is_pressed()) {
+ skip->show();
+ get_ok()->set_text(TTR("Next"));
+ selection_only->set_disabled(true);
+
+ } else {
+ skip->hide();
+ get_ok()->set_text(TTR("Replace"));
+ selection_only->set_disabled(false);
+ }
+}
+
+
+void FindReplaceDialog::_skip_pressed() {
+
+ _replace_skip_callback();
+}
+
+bool FindReplaceDialog::is_replace_mode() const {
+
+ return replace_text->is_visible_in_tree();
+}
+
+bool FindReplaceDialog::is_replace_all_mode() const {
+
+ return !prompt->is_pressed();
+}
+
+bool FindReplaceDialog::is_replace_selection_only() const {
+
+ return selection_only->is_pressed();
+}
+void FindReplaceDialog::set_replace_selection_only(bool p_enable){
+
+ selection_only->set_pressed(p_enable);
+}
+
+
+void FindReplaceDialog::ok_pressed() {
+
+ _search_callback();
+}
+
+void FindReplaceDialog::_search_text_entered(const String& p_text) {
+
+ if (replace_text->is_visible_in_tree())
+ return;
+ emit_signal("search");
+ _search();
+
+}
+
+void FindReplaceDialog::_replace_text_entered(const String& p_text) {
+
+ if (!replace_text->is_visible_in_tree())
+ return;
+
+ emit_signal("search");
+ _replace();
+
+}
+
+
+String FindReplaceDialog::get_search_text() const {
+
+ return search_text->get_text();
+}
+String FindReplaceDialog::get_replace_text() const {
+
+ return replace_text->get_text();
+}
+bool FindReplaceDialog::is_whole_words() const {
+
+ return whole_words->is_pressed();
+}
+bool FindReplaceDialog::is_case_sensitive() const {
+
+ return case_sensitive->is_pressed();
+
+}
+bool FindReplaceDialog::is_backwards() const {
+
+ return backwards->is_pressed();
+
+}
+
+void FindReplaceDialog::set_error(const String& p_error) {
+
+ error_label->set_text(p_error);
+}
+
+void FindReplaceDialog::set_text_edit(TextEdit *p_text_edit) {
+
+ text_edit=p_text_edit;
+}
+
+void FindReplaceDialog::search_next() {
+ _search();
+}
+
+
+void FindReplaceDialog::_bind_methods() {
+
+ ClassDB::bind_method("_search_text_entered",&FindReplaceDialog::_search_text_entered);
+ ClassDB::bind_method("_replace_text_entered",&FindReplaceDialog::_replace_text_entered);
+ ClassDB::bind_method("_prompt_changed",&FindReplaceDialog::_prompt_changed);
+ ClassDB::bind_method("_skip_pressed",&FindReplaceDialog::_skip_pressed);
+ ADD_SIGNAL(MethodInfo("search"));
+ ADD_SIGNAL(MethodInfo("skip"));
+
+}
+
+FindReplaceDialog::FindReplaceDialog() {
+
+ set_self_modulate(Color(1,1,1,0.8));
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+
+
+
+ search_text = memnew( LineEdit );
+ vb->add_margin_child(TTR("Search"),search_text);
+ search_text->connect("text_entered", this,"_search_text_entered");
+ //search_text->set_self_opacity(0.7);
+
+
+
+ replace_label = memnew( Label);
+ replace_label->set_text(TTR("Replace By"));
+ vb->add_child(replace_label);
+ replace_mc= memnew( MarginContainer);
+ vb->add_child(replace_mc);
+
+ replace_text = memnew( LineEdit );
+ replace_text->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ replace_text->set_begin( Point2(15,132) );
+ replace_text->set_end( Point2(15,135) );
+ //replace_text->set_self_opacity(0.7);
+ replace_mc->add_child(replace_text);
+
+
+ replace_text->connect("text_entered", this,"_replace_text_entered");
+
+
+
+ MarginContainer *opt_mg = memnew( MarginContainer );
+ vb->add_child(opt_mg);
+ VBoxContainer *svb = memnew( VBoxContainer);
+ opt_mg->add_child(svb);
+
+ svb ->add_child(memnew(Label));
+
+ whole_words = memnew( CheckButton );
+ whole_words->set_text(TTR("Whole Words"));
+ svb->add_child(whole_words);
+
+ case_sensitive = memnew( CheckButton );
+ case_sensitive->set_text(TTR("Case Sensitive"));
+ svb->add_child(case_sensitive);
+
+ backwards = memnew( CheckButton );
+ backwards->set_text(TTR("Backwards"));
+ svb->add_child(backwards);
+
+ opt_mg = memnew( MarginContainer );
+ vb->add_child(opt_mg);
+ VBoxContainer *rvb = memnew( VBoxContainer);
+ opt_mg->add_child(rvb);
+ replace_vb=rvb;
+ //rvb ->add_child(memnew(HSeparator));
+ rvb ->add_child(memnew(Label));
+
+ prompt = memnew( CheckButton );
+ prompt->set_text(TTR("Prompt On Replace"));
+ rvb->add_child(prompt);
+ prompt->connect("pressed", this,"_prompt_changed");
+
+ selection_only = memnew( CheckButton );
+ selection_only->set_text(TTR("Selection Only"));
+ rvb->add_child(selection_only);
+
+
+ int margin = get_constant("margin","Dialogs");
+ int button_margin = get_constant("button_margin","Dialogs");
+
+ skip = memnew( Button );
+ skip->set_anchor( MARGIN_LEFT, ANCHOR_END );
+ skip->set_anchor( MARGIN_TOP, ANCHOR_END );
+ skip->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ skip->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
+ skip->set_begin( Point2( 70, button_margin ) );
+ skip->set_end( Point2( 10, margin ) );
+ skip->set_text(TTR("Skip"));
+ add_child(skip);
+ skip->connect("pressed", this,"_skip_pressed");
+
+
+ error_label = memnew( Label );
+ error_label->set_align(Label::ALIGN_CENTER);
+ error_label->add_color_override("font_color",Color(1,0.4,0.3));
+ error_label->add_color_override("font_color_shadow",Color(0,0,0,0.2));
+ error_label->add_constant_override("shadow_as_outline",1);
+
+ vb->add_child(error_label);
+
+
+ set_hide_on_ok(false);
+
+}
+
+
+/*** CODE EDITOR ****/
+
+void CodeTextEditor::_text_editor_gui_input(const InputEvent& p_event) {
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON) {
+
+ const InputEventMouseButton& mb=p_event.mouse_button;
+
+ if (mb.pressed && mb.mod.command) {
+
+ if (mb.button_index==BUTTON_WHEEL_UP) {
+ _zoom_in();
+ } else if (mb.button_index==BUTTON_WHEEL_DOWN) {
+ _zoom_out();
+ }
+ }
+ } else if (p_event.type==InputEvent::KEY) {
+
+ if (p_event.key.pressed) {
+ if (ED_IS_SHORTCUT("script_editor/zoom_in", p_event)) {
+ _zoom_in();
+ }
+ if (ED_IS_SHORTCUT("script_editor/zoom_out", p_event)) {
+ _zoom_out();
+ }
+ if (ED_IS_SHORTCUT("script_editor/reset_zoom", p_event)) {
+ _reset_zoom();
+ }
+ }
+ }
+}
+
+void CodeTextEditor::_zoom_in() {
+ font_resize_val+=1;
+
+ if (font_resize_timer->get_time_left()==0)
+ font_resize_timer->start();
+}
+
+void CodeTextEditor::_zoom_out() {
+ font_resize_val-=1;
+
+ if (font_resize_timer->get_time_left()==0)
+ font_resize_timer->start();
+}
+
+void CodeTextEditor::_reset_zoom() {
+ Ref<DynamicFont> font = text_editor->get_font("font"); // reset source font size to default
+
+ if (font.is_valid()) {
+ EditorSettings::get_singleton()->set("interface/source_font_size",14);
+ font->set_size(14);
+ }
+}
+
+void CodeTextEditor::_line_col_changed() {
+
+ line_nb->set_text(itos(text_editor->cursor_get_line() + 1));
+ col_nb->set_text(itos(text_editor->cursor_get_column() + 1));
+}
+
+void CodeTextEditor::_text_changed() {
+
+ code_complete_timer->start();
+ idle->start();
+}
+
+void CodeTextEditor::_code_complete_timer_timeout() {
+ if (!is_visible_in_tree())
+ return;
+ if (enable_complete_timer)
+ text_editor->query_code_comple();
+}
+
+void CodeTextEditor::_complete_request() {
+
+ List<String> entries;
+ String ctext = text_editor->get_text_for_completion();
+ _code_complete_script(ctext,&entries);
+ if (code_complete_func) {
+ code_complete_func(code_complete_ud,ctext,&entries);
+ }
+ // print_line("COMPLETE: "+p_request);
+ if (entries.size()==0)
+ return;
+ Vector<String> strs;
+ strs.resize(entries.size());
+ int i=0;
+ for(List<String>::Element *E=entries.front();E;E=E->next()) {
+
+ strs[i++]=E->get();
+ }
+
+ text_editor->code_complete(strs);
+}
+
+void CodeTextEditor::_font_resize_timeout() {
+
+ Ref<DynamicFont> font = text_editor->get_font("font");
+
+ if (font.is_valid()) {
+ int size=font->get_size()+font_resize_val;
+
+ if (size>=8 && size<=96) {
+ EditorSettings::get_singleton()->set("interface/source_font_size",size);
+ font->set_size(size);
+ }
+
+ font_resize_val=0;
+ }
+}
+
+void CodeTextEditor::update_editor_settings() {
+
+ text_editor->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
+ text_editor->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
+ text_editor->set_tab_size(EditorSettings::get_singleton()->get("text_editor/indent/tab_size"));
+ text_editor->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
+ text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers"));
+ text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/line_numbers/line_numbers_zero_padded"));
+ text_editor->set_show_line_length_guideline(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_length_guideline"));
+ text_editor->set_line_length_guideline_column(EditorSettings::get_singleton()->get("text_editor/line_numbers/line_length_guideline_column"));
+ text_editor->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
+ text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
+ text_editor->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
+ text_editor->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
+ text_editor->set_draw_breakpoint_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_breakpoint_gutter"));
+ text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
+}
+
+void CodeTextEditor::set_error(const String& p_error) {
+
+ if (p_error!="") {
+ error->set_text(p_error);
+ error->show();
+ } else {
+ error->hide();
+ }
+
+}
+
+void CodeTextEditor::_update_font() {
+
+ // FONTS
+ String editor_font = EDITOR_DEF("text_editor/theme/font", "");
+ bool font_overridden = false;
+ if (editor_font!="") {
+ Ref<Font> fnt = ResourceLoader::load(editor_font);
+ if (fnt.is_valid()) {
+ text_editor->add_font_override("font",fnt);
+ font_overridden = true;
+ }
+ }
+ if(!font_overridden) {
+
+ text_editor->add_font_override("font",get_font("source","EditorFonts"));
+ }
+}
+
+void CodeTextEditor::_on_settings_change() {
+
+ _update_font();
+
+ // AUTO BRACE COMPLETION
+ text_editor->set_auto_brace_completion(
+ EDITOR_DEF("text_editor/completion/auto_brace_complete", true)
+ );
+
+ code_complete_timer->set_wait_time(
+ EDITOR_DEF("text_editor/completion/code_complete_delay",.3f)
+ );
+
+ enable_complete_timer = EDITOR_DEF("text_editor/completion/enable_code_completion_delay",true);
+
+ // call hint settings
+ text_editor->set_callhint_settings(
+ EDITOR_DEF("text_editor/completion/put_callhint_tooltip_below_current_line", true),
+ EDITOR_DEF("text_editor/completion/callhint_tooltip_offset", Vector2())
+ );
+}
+
+void CodeTextEditor::_text_changed_idle_timeout() {
+
+
+ _validate_script();
+ emit_signal("validate_script");
+}
+
+void CodeTextEditor::_notification(int p_what) {
+
+
+ if (p_what==EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
+ _load_theme_settings();
+ emit_signal("load_theme_settings");
+ }
+ if (p_what==NOTIFICATION_THEME_CHANGED) {
+ _update_font();
+ }
+}
+
+void CodeTextEditor::_bind_methods() {
+
+ ClassDB::bind_method("_text_editor_gui_input",&CodeTextEditor::_text_editor_gui_input);
+ ClassDB::bind_method("_line_col_changed",&CodeTextEditor::_line_col_changed);
+ ClassDB::bind_method("_text_changed",&CodeTextEditor::_text_changed);
+ ClassDB::bind_method("_on_settings_change",&CodeTextEditor::_on_settings_change);
+ ClassDB::bind_method("_text_changed_idle_timeout",&CodeTextEditor::_text_changed_idle_timeout);
+ ClassDB::bind_method("_code_complete_timer_timeout",&CodeTextEditor::_code_complete_timer_timeout);
+ ClassDB::bind_method("_complete_request",&CodeTextEditor::_complete_request);
+ ClassDB::bind_method("_font_resize_timeout",&CodeTextEditor::_font_resize_timeout);
+
+ ADD_SIGNAL(MethodInfo("validate_script"));
+ ADD_SIGNAL(MethodInfo("load_theme_settings"));
+
+}
+
+void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func,void * p_ud) {
+ code_complete_func=p_code_complete_func;
+ code_complete_ud=p_ud;
+}
+
+
+CodeTextEditor::CodeTextEditor() {
+
+ code_complete_func=NULL;
+ ED_SHORTCUT("script_editor/zoom_in", TTR("Zoom In"), KEY_MASK_CMD|KEY_EQUAL);
+ ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD|KEY_MINUS);
+ ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD|KEY_0);
+
+ find_replace_bar = memnew( FindReplaceBar );
+ add_child(find_replace_bar);
+ find_replace_bar->set_h_size_flags(SIZE_EXPAND_FILL);
+ find_replace_bar->hide();
+
+ text_editor = memnew( TextEdit );
+ add_child(text_editor);
+ text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ find_replace_bar->set_text_edit(text_editor);
+
+ text_editor->set_show_line_numbers(true);
+ text_editor->set_brace_matching(true);
+ text_editor->set_auto_indent(true);
+
+ MarginContainer *status_mc = memnew( MarginContainer );
+ add_child(status_mc);
+ status_mc->set("custom_constants/margin_left", 2);
+ status_mc->set("custom_constants/margin_top", 5);
+ status_mc->set("custom_constants/margin_right", 2);
+ status_mc->set("custom_constants/margin_bottom", 1);
+
+ HBoxContainer *status_bar = memnew( HBoxContainer );
+ status_mc->add_child(status_bar);
+ status_bar->set_h_size_flags(SIZE_EXPAND_FILL);
+ status_bar->add_child( memnew( Label ) ); //to keep the height if the other labels are not visible
+
+ idle = memnew( Timer );
+ add_child(idle);
+ idle->set_one_shot(true);
+ idle->set_wait_time(EDITOR_DEF("text_editor/completion/idle_parse_delay",2));
+
+ code_complete_timer = memnew(Timer);
+ add_child(code_complete_timer);
+ code_complete_timer->set_one_shot(true);
+ enable_complete_timer = EDITOR_DEF("text_editor/completion/enable_code_completion_delay",true);
+
+ code_complete_timer->set_wait_time(EDITOR_DEF("text_editor/completion/code_complete_delay",.3f));
+
+ error = memnew( Label );
+ status_bar->add_child(error);
+ error->hide();
+ error->set_valign(Label::VALIGN_CENTER);
+ error->add_color_override("font_color",Color(1,0.7,0.6,0.9));
+
+ status_bar->add_spacer();
+
+ Label *line_txt = memnew( Label );
+ status_bar->add_child(line_txt);
+ line_txt->set_align(Label::ALIGN_RIGHT);
+ line_txt->set_valign(Label::VALIGN_CENTER);
+ line_txt->set_v_size_flags(SIZE_FILL);
+ line_txt->set_text(TTR("Line:"));
+
+ line_nb = memnew( Label );
+ status_bar->add_child(line_nb);
+ line_nb->set_valign(Label::VALIGN_CENTER);
+ line_nb->set_v_size_flags(SIZE_FILL);
+ line_nb->set_autowrap(true); // workaround to prevent resizing the label on each change
+ line_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE);
+
+ Label *col_txt = memnew( Label );
+ status_bar->add_child(col_txt);
+ col_txt->set_align(Label::ALIGN_RIGHT);
+ col_txt->set_valign(Label::VALIGN_CENTER);
+ col_txt->set_v_size_flags(SIZE_FILL);
+ col_txt->set_text(TTR("Col:"));
+
+ col_nb = memnew( Label );
+ status_bar->add_child(col_nb);
+ col_nb->set_valign(Label::VALIGN_CENTER);
+ col_nb->set_v_size_flags(SIZE_FILL);
+ col_nb->set_autowrap(true); // workaround to prevent resizing the label on each change
+ col_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE);
+
+ text_editor->connect("gui_input", this,"_text_editor_gui_input");
+ text_editor->connect("cursor_changed", this,"_line_col_changed");
+ text_editor->connect("text_changed", this,"_text_changed");
+ text_editor->connect("request_completion", this,"_complete_request");
+ Vector<String> cs;
+ cs.push_back(".");
+ cs.push_back(",");
+ cs.push_back("(");
+ cs.push_back("$");
+ text_editor->set_completion(true,cs);
+ idle->connect("timeout", this,"_text_changed_idle_timeout");
+
+ code_complete_timer->connect("timeout", this,"_code_complete_timer_timeout");
+
+ font_resize_val=0;
+ font_resize_timer = memnew(Timer);
+ add_child(font_resize_timer);
+ font_resize_timer->set_one_shot(true);
+ font_resize_timer->set_wait_time(0.07);
+ font_resize_timer->connect("timeout", this, "_font_resize_timeout");
+
+ EditorSettings::get_singleton()->connect("settings_changed",this,"_on_settings_change");
+}
diff --git a/editor/code_editor.h b/editor/code_editor.h
new file mode 100644
index 0000000000..7582985d4c
--- /dev/null
+++ b/editor/code_editor.h
@@ -0,0 +1,261 @@
+/*************************************************************************/
+/* code_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 CODE_EDITOR_H
+#define CODE_EDITOR_H
+
+#include "editor/editor_plugin.h"
+#include "scene/gui/text_edit.h"
+#include "scene/gui/dialogs.h"
+#include "scene/main/timer.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/line_edit.h"
+
+
+
+class GotoLineDialog : public ConfirmationDialog {
+
+ GDCLASS(GotoLineDialog,ConfirmationDialog);
+
+ Label *line_label;
+ LineEdit *line;
+
+ TextEdit *text_editor;
+
+ virtual void ok_pressed();
+public:
+
+ void popup_find_line(TextEdit *p_edit);
+ int get_line() const;
+
+
+ void set_text_editor(TextEdit *p_text_editor);
+ GotoLineDialog();
+};
+
+class FindReplaceBar : public HBoxContainer {
+
+ GDCLASS(FindReplaceBar,HBoxContainer);
+
+ LineEdit *search_text;
+ ToolButton *find_prev;
+ ToolButton *find_next;
+ CheckBox *case_sensitive;
+ CheckBox *whole_words;
+ Label *error_label;
+ TextureButton *hide_button;
+
+ LineEdit *replace_text;
+ Button *replace;
+ Button *replace_all;
+ CheckBox *selection_only;
+
+ VBoxContainer *text_vbc;
+ HBoxContainer *replace_hbc;
+ HBoxContainer *replace_options_hbc;
+
+ TextEdit *text_edit;
+
+ int result_line;
+ int result_col;
+
+ bool replace_all_mode;
+ bool preserve_cursor;
+
+ void _get_search_from(int& r_line, int& r_col);
+
+ void _show_search();
+ void _hide_bar();
+
+ void _editor_text_changed();
+ void _search_options_changed(bool p_pressed);
+ void _search_text_changed(const String& p_text);
+ void _search_text_entered(const String& p_text);
+ void _replace_text_entered(const String& p_text);
+
+protected:
+ void _notification(int p_what);
+ void _unhandled_input(const InputEvent &p_event);
+
+ bool _search(uint32_t p_flags, int p_from_line, int p_from_col);
+
+ void _replace();
+ void _replace_all();
+
+ static void _bind_methods();
+
+public:
+ String get_search_text() const;
+ String get_replace_text() const;
+
+ bool is_case_sensitive() const;
+ bool is_whole_words() const;
+ bool is_selection_only() const;
+ void set_error(const String& p_label);
+
+ void set_text_edit(TextEdit *p_text_edit);
+
+ void popup_search();
+ void popup_replace();
+
+ bool search_current();
+ bool search_prev();
+ bool search_next();
+
+ FindReplaceBar();
+};
+
+class FindReplaceDialog : public ConfirmationDialog {
+
+ GDCLASS(FindReplaceDialog,ConfirmationDialog);
+
+ LineEdit *search_text;
+ LineEdit *replace_text;
+ CheckButton *whole_words;
+ CheckButton *case_sensitive;
+ CheckButton *backwards;
+ CheckButton *prompt;
+ CheckButton *selection_only;
+ Button *skip;
+ Label *error_label;
+ MarginContainer *replace_mc;
+ Label *replace_label;
+ VBoxContainer *replace_vb;
+
+ void _search_text_entered(const String& p_text);
+ void _replace_text_entered(const String& p_text);
+ void _prompt_changed();
+ void _skip_pressed();
+
+
+ TextEdit *text_edit;
+protected:
+
+ void _search_callback();
+ void _replace_skip_callback();
+
+ bool _search();
+ void _replace();
+
+ virtual void ok_pressed();
+ static void _bind_methods();
+public:
+
+ String get_search_text() const;
+ String get_replace_text() const;
+ bool is_whole_words() const;
+ bool is_case_sensitive() const;
+ bool is_backwards() const;
+ bool is_replace_mode() const;
+ bool is_replace_all_mode() const;
+ bool is_replace_selection_only() const;
+ void set_replace_selection_only(bool p_enable);
+
+ void set_error(const String& p_error);
+
+ void popup_search();
+ void popup_replace();
+
+ void set_text_edit(TextEdit *p_text_edit);
+
+ void search_next();
+ FindReplaceDialog();
+};
+
+
+typedef void (*CodeTextEditorCodeCompleteFunc)(void* p_ud,const String& p_code, List<String>* r_options);
+
+class CodeTextEditor : public VBoxContainer {
+
+ GDCLASS(CodeTextEditor,VBoxContainer);
+
+ TextEdit *text_editor;
+ FindReplaceBar *find_replace_bar;
+
+ Label *line_nb;
+ Label *col_nb;
+ Label *info;
+ Timer *idle;
+ Timer *code_complete_timer;
+ bool enable_complete_timer;
+
+ Timer *font_resize_timer;
+ int font_resize_val;
+
+ Label *error;
+
+ void _on_settings_change();
+
+ void _update_font();
+ void _complete_request();
+ void _font_resize_timeout();
+
+ void _text_editor_gui_input(const InputEvent& p_event);
+ void _zoom_in();
+ void _zoom_out();
+ void _reset_zoom();
+
+
+ CodeTextEditorCodeCompleteFunc code_complete_func;
+ void *code_complete_ud;
+
+protected:
+
+
+ virtual void _load_theme_settings() {}
+ virtual void _validate_script() {}
+ virtual void _code_complete_script(const String& p_code, List<String>* r_options) {}
+
+ void _text_changed_idle_timeout();
+ void _code_complete_timer_timeout();
+ void _text_changed();
+ void _line_col_changed();
+ void _notification(int);
+ static void _bind_methods();
+
+public:
+
+ void update_editor_settings();
+ void set_error(const String& p_error);
+ void update_line_and_column() { _line_col_changed(); }
+ TextEdit *get_text_edit() { return text_editor; }
+ FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
+ virtual void apply_code() {}
+
+
+ void set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void * p_ud);
+
+
+ CodeTextEditor();
+};
+
+
+
+#endif // CODE_EDITOR_H
diff --git a/tools/editor/collada/SCsub b/editor/collada/SCsub
index 04c9a827ef..04c9a827ef 100644
--- a/tools/editor/collada/SCsub
+++ b/editor/collada/SCsub
diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp
new file mode 100644
index 0000000000..2ba4f648a3
--- /dev/null
+++ b/editor/collada/collada.cpp
@@ -0,0 +1,2801 @@
+/*************************************************************************/
+/* collada.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifdef TOOLS_ENABLED
+
+#include "collada.h"
+
+#include "stdio.h"
+
+//#define DEBUG_DEFAULT_ANIMATION
+//#define DEBUG_COLLADA
+#ifdef DEBUG_COLLADA
+#define COLLADA_PRINT(m_what) print_line(m_what)
+#else
+#define COLLADA_PRINT(m_what)
+#endif
+
+#define COLLADA_IMPORT_SCALE_SCENE
+
+/* HELPERS */
+
+
+
+String Collada::Effect::get_texture_path(const String& p_source,Collada& state) const {
+
+ String image=p_source;
+ ERR_FAIL_COND_V(!state.state.image_map.has(image),"");
+ return state.state.image_map[image].path;
+}
+
+Transform Collada::get_root_transform() const {
+
+ Transform unit_scale_transform;
+#ifndef COLLADA_IMPORT_SCALE_SCENE
+ unit_scale_transform.scale(Vector3(state.unit_scale,state.unit_scale,state.unit_scale));
+#endif
+ return unit_scale_transform;
+}
+
+
+
+void Collada::Vertex::fix_unit_scale(Collada &state) {
+#ifdef COLLADA_IMPORT_SCALE_SCENE
+ vertex*=state.state.unit_scale;
+#endif
+}
+
+static String _uri_to_id(const String& p_uri) {
+
+ if (p_uri.begins_with("#"))
+ return p_uri.substr(1,p_uri.size()-1);
+ else
+ return p_uri;
+
+}
+
+/** HELPER FUNCTIONS **/
+
+Transform Collada::fix_transform(const Transform& p_transform) {
+
+ Transform tr=p_transform;
+
+#ifndef NO_UP_AXIS_SWAP
+
+ if (state.up_axis!=Vector3::AXIS_Y) {
+
+ for(int i=0;i<3;i++)
+ SWAP(tr.basis[1][i],tr.basis[state.up_axis][i]);
+ for(int i=0;i<3;i++)
+ SWAP(tr.basis[i][1],tr.basis[i][state.up_axis]);
+
+ SWAP(tr.origin[1],tr.origin[state.up_axis]);
+
+ tr.basis[state.up_axis][0]=-tr.basis[state.up_axis][0];
+ tr.basis[state.up_axis][1]=-tr.basis[state.up_axis][1];
+ tr.basis[0][state.up_axis]=-tr.basis[0][state.up_axis];
+ tr.basis[1][state.up_axis]=-tr.basis[1][state.up_axis];
+ tr.origin[state.up_axis]=-tr.origin[state.up_axis];
+ }
+#endif
+
+ //tr.scale(Vector3(state.unit_scale.unit_scale.unit_scale));
+ return tr;
+ //return state.matrix_fix * p_transform;
+}
+
+
+static Transform _read_transform_from_array(const Vector<float>& array, int ofs=0) {
+
+ Transform tr;
+ // i wonder why collada matrices are transposed, given that's opposed to opengl..
+ tr.basis.elements[0][0]=array[0+ofs];
+ tr.basis.elements[0][1]=array[1+ofs];
+ tr.basis.elements[0][2]=array[2+ofs];
+ tr.basis.elements[1][0]=array[4+ofs];
+ tr.basis.elements[1][1]=array[5+ofs];
+ tr.basis.elements[1][2]=array[6+ofs];
+ tr.basis.elements[2][0]=array[8+ofs];
+ tr.basis.elements[2][1]=array[9+ofs];
+ tr.basis.elements[2][2]=array[10+ofs];
+ tr.origin.x=array[3+ofs];
+ tr.origin.y=array[7+ofs];
+ tr.origin.z=array[11+ofs];
+ return tr;
+
+}
+
+/* STRUCTURES */
+
+Transform Collada::Node::compute_transform(Collada &state) const {
+
+ Transform xform;
+
+ for(int i=0;i<xform_list.size();i++) {
+
+ Transform xform_step;
+ const XForm& xf = xform_list[i];
+ switch(xf.op) {
+
+ case XForm::OP_ROTATE: {
+ if (xf.data.size()>=4) {
+
+ xform_step.rotate(Vector3(xf.data[0],xf.data[1],xf.data[2]),Math::deg2rad(xf.data[3]));
+ }
+ } break;
+ case XForm::OP_SCALE: {
+
+ if (xf.data.size()>=3) {
+
+ xform_step.scale(Vector3(xf.data[0],xf.data[1],xf.data[2]));
+ }
+
+ } break;
+ case XForm::OP_TRANSLATE: {
+
+ if (xf.data.size()>=3) {
+
+ xform_step.origin=Vector3(xf.data[0],xf.data[1],xf.data[2]);
+ }
+
+ } break;
+ case XForm::OP_MATRIX: {
+
+ if (xf.data.size()>=16) {
+ xform_step = _read_transform_from_array(xf.data,0);
+ }
+
+ } break;
+ default: {}
+
+ }
+
+ xform = xform * xform_step;
+ }
+
+#ifdef COLLADA_IMPORT_SCALE_SCENE
+ xform.origin*=state.state.unit_scale;
+#endif
+ return xform;
+}
+
+Transform Collada::Node::get_transform() const {
+
+ return default_transform;
+}
+
+Transform Collada::Node::get_global_transform() const {
+
+ if (parent)
+ return parent->get_global_transform() * default_transform;
+ else
+ return default_transform;
+
+}
+
+Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) {
+
+ ERR_FAIL_COND_V(keys.size()==0,Vector<float>());
+ int i=0;
+
+ for(i=0;i<keys.size();i++) {
+
+ if (keys[i].time>p_time)
+ break;
+ }
+
+ if (i==0)
+ return keys[0].data;
+ if (i==keys.size())
+ return keys[keys.size()-1].data;
+
+ switch(keys[i].interp_type) {
+
+ case INTERP_BEZIER: //wait for bezier
+ case INTERP_LINEAR: {
+
+ float c = (p_time-keys[i-1].time)/(keys[i].time-keys[i-1].time);
+
+ if (keys[i].data.size()==16) {
+ //interpolate a matrix
+ Transform src = _read_transform_from_array(keys[i-1].data);
+ Transform dst = _read_transform_from_array(keys[i].data);
+
+
+ Transform interp = c<0.001 ? src : src.interpolate_with(dst,c);
+
+ Vector<float> ret;
+ ret.resize(16);
+ Transform tr;
+ // i wonder why collada matrices are transposed, given that's opposed to opengl..
+ ret[0]=interp.basis.elements[0][0];
+ ret[1]=interp.basis.elements[0][1];
+ ret[2]=interp.basis.elements[0][2];
+ ret[4]=interp.basis.elements[1][0];
+ ret[5]=interp.basis.elements[1][1];
+ ret[6]=interp.basis.elements[1][2];
+ ret[8]=interp.basis.elements[2][0];
+ ret[9]=interp.basis.elements[2][1];
+ ret[10]=interp.basis.elements[2][2];
+ ret[3]=interp.origin.x;
+ ret[7]=interp.origin.y;
+ ret[11]=interp.origin.z;
+ ret[12]=0;
+ ret[13]=0;
+ ret[14]=0;
+ ret[15]=1;
+
+ return ret;
+ } else {
+
+ Vector<float> dest;
+ dest.resize(keys[i].data.size());
+ for(int j=0;j<dest.size();j++) {
+
+ dest[j]=keys[i].data[j]*c+keys[i-1].data[j]*(1.0-c);
+ }
+ return dest;
+ //interpolate one by one
+ }
+ } break;
+ }
+
+ ERR_FAIL_V(Vector<float>());
+}
+
+
+
+
+void Collada::_parse_asset(XMLParser& parser) {
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+
+ if (name=="up_axis") {
+
+ parser.read();
+ if (parser.get_node_data()=="X_UP")
+ state.up_axis=Vector3::AXIS_X;
+ if (parser.get_node_data()=="Y_UP")
+ state.up_axis=Vector3::AXIS_Y;
+ if (parser.get_node_data()=="Z_UP")
+ state.up_axis=Vector3::AXIS_Z;
+
+ COLLADA_PRINT("up axis: "+parser.get_node_data());
+ } else if (name=="unit") {
+
+ state.unit_scale = parser.get_attribute_value("meter").to_double();
+ COLLADA_PRINT("unit scale: "+rtos(state.unit_scale));
+ }
+
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="asset")
+ break; //end of <asset>
+ }
+}
+
+
+void Collada::_parse_image(XMLParser& parser) {
+
+ String id=parser.get_attribute_value("id");
+
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+
+ Image image;
+
+
+ if (state.version<State::Version(1,4,0)) {
+ /* <1.4 */
+ String path = parser.get_attribute_value("source").strip_edges();
+ if (path.find("://")==-1 && path.is_rel_path()) {
+ // path is relative to file being loaded, so convert to a resource path
+ image.path=GlobalConfig::get_singleton()->localize_path(state.local_path.get_base_dir()+"/"+path.percent_decode());
+
+ }
+ } else {
+
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+
+ if (name=="init_from") {
+
+ parser.read();
+ String path = parser.get_node_data().strip_edges().percent_decode();
+
+ if (path.find("://")==-1 && path.is_rel_path()) {
+ // path is relative to file being loaded, so convert to a resource path
+ path=GlobalConfig::get_singleton()->localize_path(state.local_path.get_base_dir()+"/"+path);
+
+ } else if (path.find("file:///")==0) {
+ path=path.replace_first("file:///","");
+ path=GlobalConfig::get_singleton()->localize_path(path);
+ }
+
+ image.path=path;
+
+ } else if (name=="data") {
+
+ ERR_PRINT("COLLADA Embedded image data not supported!");
+
+ } else if (name=="extra" && !parser.is_empty())
+ parser.skip_section();
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="image")
+ break; //end of <asset>
+
+ }
+ }
+
+ state.image_map[id]=image;
+}
+
+void Collada::_parse_material(XMLParser& parser) {
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+ Material material;
+
+ String id=parser.get_attribute_value("id");
+ if (parser.has_attribute("name"))
+ material.name=parser.get_attribute_value("name");
+
+ if (state.version<State::Version(1,4,0)) {
+ /* <1.4 */
+ ERR_PRINT("Collada Materials < 1.4 are not supported (yet)");
+ } else {
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT && parser.get_node_name()=="instance_effect") {
+
+ material.instance_effect=_uri_to_id(parser.get_attribute_value("url"));
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="material")
+ break; //end of <asset>
+ }
+ }
+
+ state.material_map[id]=material;
+}
+
+//! reads floats from inside of xml element until end of xml element
+Vector<float> Collada::_read_float_array(XMLParser& parser) {
+
+ if (parser.is_empty())
+ return Vector<float>();
+
+ Vector<String> splitters;
+ splitters.push_back(" ");
+ splitters.push_back("\n");
+ splitters.push_back("\r");
+ splitters.push_back("\t");
+
+ Vector<float> array;
+ while(parser.read()==OK) {
+ // TODO: check for comments inside the element
+ // and ignore them.
+
+ if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+ // parse float data
+ String str = parser.get_node_data();
+ array=str.split_floats_mk(splitters,false);
+ //array=str.split_floats(" ",false);
+ }
+ else
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
+ break; // end parsing text
+ }
+
+ return array;
+}
+
+Vector<String> Collada::_read_string_array(XMLParser& parser) {
+
+ if (parser.is_empty())
+ return Vector<String>();
+
+ Vector<String> array;
+ while(parser.read()==OK) {
+ // TODO: check for comments inside the element
+ // and ignore them.
+
+ if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+ // parse String data
+ String str = parser.get_node_data();
+ array=str.split_spaces();
+ /*
+ for(int i=0;i<array.size();i++) {
+ print_line(itos(i)+": "+array[i]);
+ }
+ */
+ }
+ else
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
+ break; // end parsing text
+ }
+
+ return array;
+}
+
+
+
+Transform Collada::_read_transform(XMLParser& parser) {
+
+ if (parser.is_empty())
+ return Transform();
+
+ Vector<String> array;
+ while(parser.read()==OK) {
+ // TODO: check for comments inside the element
+ // and ignore them.
+
+ if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+ // parse float data
+ String str = parser.get_node_data();
+ array=str.split_spaces();
+ }
+ else
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
+ break; // end parsing text
+ }
+
+ ERR_FAIL_COND_V(array.size()!=16,Transform());
+ Vector<float> farr;
+ farr.resize(16);
+ for(int i=0;i<16;i++) {
+ farr[i]=array[i].to_double();
+ }
+
+ return _read_transform_from_array(farr);
+}
+
+String Collada::_read_empty_draw_type(XMLParser& parser) {
+
+ String empty_draw_type = "";
+
+ if (parser.is_empty())
+ return empty_draw_type;
+
+ while (parser.read()==OK) {
+ if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+ empty_draw_type = parser.get_node_data();
+ }
+ else
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
+ break; // end parsing text
+ }
+ return empty_draw_type;
+}
+
+Variant Collada::_parse_param(XMLParser& parser) {
+
+ if (parser.is_empty())
+ return Variant();
+
+ String from = parser.get_node_name();
+ Variant data;
+
+ while(parser.read()==OK) {
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name() == "float") {
+
+ parser.read();
+ if (parser.get_node_type()==XMLParser::NODE_TEXT) {
+
+ data=parser.get_node_data().to_double();
+ }
+ } else if (parser.get_node_name() == "float2") {
+
+ Vector<float> v2 = _read_float_array(parser);
+
+ if (v2.size()>=2) {
+
+ data=Vector2(v2[0],v2[1]);
+ }
+ } else if (parser.get_node_name() == "float3") {
+
+ Vector<float> v3 = _read_float_array(parser);
+
+ if (v3.size()>=3) {
+
+ data=Vector3(v3[0],v3[1],v3[2]);
+ }
+ } else if (parser.get_node_name() == "float4") {
+
+ Vector<float> v4 = _read_float_array(parser);
+
+ if (v4.size()>=4) {
+
+ data=Color(v4[0],v4[1],v4[2],v4[3]);
+ }
+ } else if (parser.get_node_name() == "sampler2D") {
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="source") {
+
+ parser.read();
+
+ if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+
+ data=parser.get_node_data();
+ }
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="sampler2D")
+ break;
+
+ }
+ } else if (parser.get_node_name() == "surface") {
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="init_from") {
+
+ parser.read();
+
+ if (parser.get_node_type() == XMLParser::NODE_TEXT) {
+
+ data=parser.get_node_data();
+ }
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="surface")
+ break;
+
+ }
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==from)
+ break;
+ }
+
+ COLLADA_PRINT("newparam ending "+parser.get_node_name());
+ return data;
+
+}
+
+
+
+void Collada::_parse_effect_material(XMLParser& parser,Effect &effect,String &id) {
+
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ // first come the tags we descend, but ignore the top-levels
+
+ COLLADA_PRINT("node name: "+parser.get_node_name());
+
+ if (!parser.is_empty() && (parser.get_node_name() == "profile_COMMON" || parser.get_node_name() == "technique" || parser.get_node_name() == "extra")) {
+
+ _parse_effect_material(parser,effect,id); // try again
+
+ } else if (parser.get_node_name() == "newparam") {
+ String name = parser.get_attribute_value("sid");
+ Variant value = _parse_param(parser);
+ effect.params[name]=value;
+ COLLADA_PRINT("param: "+name+" value:"+String(value));
+
+ } else if (parser.get_node_name() == "constant" ||
+ parser.get_node_name() == "lambert" ||
+ parser.get_node_name() == "phong" ||
+ parser.get_node_name() == "blinn" )
+ {
+
+ COLLADA_PRINT("shade model: "+parser.get_node_name());
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String what = parser.get_node_name();
+
+ if ( what=="emission" ||
+ what=="diffuse" ||
+ what=="specular" ||
+ what=="reflective") {
+
+
+
+ // color or texture types
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="color") {
+
+ Vector<float> colorarr = _read_float_array(parser);
+ COLLADA_PRINT("colorarr size: "+rtos(colorarr.size()));
+
+ if (colorarr.size()>=3) {
+
+ // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
+ Color color(colorarr[0],colorarr[1],colorarr[2],1.0);
+ if (what=="diffuse")
+ effect.diffuse.color=color;
+ if (what=="specular")
+ effect.specular.color=color;
+ if (what=="emission")
+ effect.emission.color=color;
+
+ COLLADA_PRINT(what+" color: "+color);
+
+ }
+
+ } else if (parser.get_node_name()=="texture") {
+
+ String sampler = parser.get_attribute_value("texture");
+ if (!effect.params.has(sampler)) {
+ ERR_PRINT(String("Couldn't find sampler: "+sampler+" in material:"+id).utf8().get_data());
+ } else {
+ String surface = effect.params[sampler];
+
+ if (!effect.params.has(surface)) {
+ ERR_PRINT(String("Couldn't find surface: "+surface+" in material:"+id).utf8().get_data());
+ } else {
+ String uri = effect.params[surface];
+
+
+ if (what=="diffuse") {
+ effect.diffuse.texture=uri;
+ } else if (what=="specular") {
+ effect.specular.texture=uri;
+ } else if (what=="emission") {
+ effect.emission.texture=uri;
+ } else if (what=="bump") {
+ if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype")!="NORMALMAP") {
+ WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
+ }
+
+ effect.bump.texture=uri;
+ }
+
+ COLLADA_PRINT(what+" texture: "+uri);
+ }
+
+ }
+ } else if (!parser.is_empty())
+ parser.skip_section();
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == what)
+ break;
+ }
+
+ } else if (what=="shininess") {
+#if 1
+ effect.shininess=_parse_param(parser);
+#else
+
+ parser.read();
+ float shininess = parser.get_node_data().to_double();
+ effect.shininess=shininess;
+ COLLADA_PRINT("shininess: "+rtos(shininess));
+#endif
+
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && (
+ parser.get_node_name()=="constant" ||
+ parser.get_node_name()=="lambert" ||
+ parser.get_node_name()=="phong" ||
+ parser.get_node_name()=="blinn"))
+ break;
+ }
+ } else if (parser.get_node_name()=="double_sided" || parser.get_node_name()=="show_double_sided") { // colladamax / google earth
+
+ // 3DS Max / Google Earth double sided extension
+ parser.read();
+ effect.found_double_sided=true;
+ effect.double_sided=parser.get_node_data().to_int();
+ COLLADA_PRINT("double sided: "+itos(parser.get_node_data().to_int()));
+ } else if (parser.get_node_name()=="unshaded") {
+ parser.read();
+ effect.unshaded=parser.get_node_data().to_int();
+ } else if (parser.get_node_name()=="bump") {
+
+ // color or texture types
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="texture") {
+
+ String sampler = parser.get_attribute_value("texture");
+ if (!effect.params.has(sampler)) {
+ ERR_PRINT(String("Couldn't find sampler: "+sampler+" in material:"+id).utf8().get_data());
+ } else {
+ String surface = effect.params[sampler];
+
+ if (!effect.params.has(surface)) {
+ ERR_PRINT(String("Couldn't find surface: "+surface+" in material:"+id).utf8().get_data());
+ } else {
+ String uri = effect.params[surface];
+
+ if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype")!="NORMALMAP") {
+ WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
+ }
+
+ effect.bump.texture=uri;
+ COLLADA_PRINT(" bump: "+uri);
+ }
+
+ }
+ } else if (!parser.is_empty())
+ parser.skip_section();
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "bump")
+ break;
+ }
+
+ } else if (!parser.is_empty())
+ parser.skip_section();
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
+ (parser.get_node_name() == "effect" ||
+ parser.get_node_name() == "profile_COMMON" ||
+ parser.get_node_name() == "technique" ||
+ parser.get_node_name() == "extra"))
+ break;
+ }
+
+}
+
+void Collada::_parse_effect(XMLParser& parser) {
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+ String id=parser.get_attribute_value("id");
+
+ Effect effect;
+ if (parser.has_attribute("name"))
+ effect.name=parser.get_attribute_value("name");
+ _parse_effect_material(parser,effect,id);
+
+
+
+ state.effect_map[id]=effect;
+
+ COLLADA_PRINT("Effect ID:"+id);
+
+}
+
+void Collada::_parse_camera(XMLParser& parser) {
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+ String id=parser.get_attribute_value("id");
+
+
+ state.camera_data_map[id]=CameraData();
+ CameraData &camera=state.camera_data_map[id];
+
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+
+ if (name=="perspective") {
+
+ camera.mode=CameraData::MODE_PERSPECTIVE;
+ } else if (name=="orthographic") {
+
+ camera.mode=CameraData::MODE_ORTHOGONAL;
+ } else if (name=="xfov") {
+
+ parser.read();
+ camera.perspective.x_fov = parser.get_node_data().to_double();
+
+ } else if (name=="yfov") {
+
+ parser.read();
+ camera.perspective.y_fov = parser.get_node_data().to_double();
+ } else if (name=="xmag") {
+
+ parser.read();
+ camera.orthogonal.x_mag = parser.get_node_data().to_double();
+
+ } else if (name=="ymag") {
+
+ parser.read();
+ camera.orthogonal.y_mag = parser.get_node_data().to_double();
+ } else if (name=="aspect_ratio") {
+
+ parser.read();
+ camera.aspect = parser.get_node_data().to_double();
+
+ } else if (name=="znear") {
+
+ parser.read();
+ camera.z_near = parser.get_node_data().to_double();
+
+ } else if (name=="zfar") {
+
+ parser.read();
+ camera.z_far = parser.get_node_data().to_double();
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="camera")
+ break; //end of <asset>
+ }
+
+ COLLADA_PRINT("Camera ID:"+id);
+
+}
+
+void Collada::_parse_light(XMLParser& parser) {
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+ String id=parser.get_attribute_value("id");
+
+
+ state.light_data_map[id]=LightData();
+ LightData &light=state.light_data_map[id];
+
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+
+ if (name=="ambient") {
+
+ light.mode=LightData::MODE_AMBIENT;
+ } else if (name=="directional") {
+
+ light.mode=LightData::MODE_DIRECTIONAL;
+ } else if (name=="point") {
+
+ light.mode=LightData::MODE_OMNI;
+ } else if (name=="spot") {
+
+ light.mode=LightData::MODE_SPOT;
+ } else if (name=="color") {
+
+ parser.read();
+ Vector<float> colorarr = _read_float_array(parser);
+ COLLADA_PRINT("colorarr size: "+rtos(colorarr.size()));
+
+ if (colorarr.size()>=4) {
+ // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
+ Color color(colorarr[0],colorarr[1],colorarr[2],1.0);
+ light.color=color;
+ }
+
+ } else if (name=="constant_attenuation") {
+
+ parser.read();
+ light.constant_att=parser.get_node_data().to_double();
+ } else if (name=="linear_attenuation") {
+
+ parser.read();
+ light.linear_att=parser.get_node_data().to_double();
+ } else if (name=="quadratic_attenuation") {
+
+ parser.read();
+ light.quad_att=parser.get_node_data().to_double();
+ } else if (name=="falloff_angle") {
+
+ parser.read();
+ light.spot_angle= parser.get_node_data().to_double();
+
+ } else if (name=="falloff_exponent") {
+
+ parser.read();
+ light.spot_exp= parser.get_node_data().to_double();
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="light")
+ break; //end of <asset>
+ }
+
+ COLLADA_PRINT("Light ID:"+id);
+
+}
+
+
+void Collada::_parse_curve_geometry(XMLParser& parser,String p_id,String p_name) {
+
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+ //load everything into a pre dictionary
+
+ state.curve_data_map[p_id]=CurveData();
+
+ CurveData &curvedata = state.curve_data_map[p_id];
+ curvedata.name=p_name;
+
+ COLLADA_PRINT("curve name: "+p_name);
+
+
+ String current_source;
+ // handles geometry node and the curve childs in this loop
+ // read sources with arrays and accessor for each curve
+ if (parser.is_empty()) {
+ return;
+ }
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String section = parser.get_node_name();
+
+ if (section == "source") {
+
+ String id=parser.get_attribute_value("id");
+ curvedata.sources[id]=CurveData::Source();
+ current_source=id;
+ COLLADA_PRINT("source data: "+id);
+
+ } else if (section=="float_array" || section=="array") {
+ // create a new array and read it.
+ if (curvedata.sources.has(current_source)) {
+
+ curvedata.sources[current_source].array = _read_float_array(parser);
+ COLLADA_PRINT("section: "+current_source+" read "+itos(curvedata.sources[current_source].array.size())+" values.");
+ }
+ } else if (section=="Name_array") {
+ // create a new array and read it.
+ if (curvedata.sources.has(current_source)) {
+
+ curvedata.sources[current_source].sarray = _read_string_array(parser);
+ COLLADA_PRINT("section: "+current_source+" read "+itos(curvedata.sources[current_source].array.size())+" values.");
+ }
+
+ } else if (section == "technique_common") {
+ //skip it
+ } else if (section == "accessor") { // child of source (below a technique tag)
+
+ if (curvedata.sources.has(current_source)) {
+ curvedata.sources[current_source].stride=parser.get_attribute_value("stride").to_int();
+ COLLADA_PRINT("section: "+current_source+" stride "+itos(curvedata.sources[current_source].stride));
+ }
+ } else if (section == "control_vertices") {
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="input") {
+
+ String semantic = parser.get_attribute_value("semantic");
+ String source =_uri_to_id( parser.get_attribute_value("source") );
+
+ curvedata.control_vertices[semantic]=source;
+
+ COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
+
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
+ break;
+ }
+
+ } else if (!parser.is_empty()){
+
+ parser.skip_section();
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="spline")
+ break;
+ }
+
+
+
+}
+
+
+
+void Collada::_parse_mesh_geometry(XMLParser& parser,String p_id,String p_name) {
+
+
+ if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+ return;
+ }
+
+ //load everything into a pre dictionary
+
+ state.mesh_data_map[p_id]=MeshData();
+
+ MeshData &meshdata = state.mesh_data_map[p_id];
+ meshdata.name=p_name;
+
+ COLLADA_PRINT("mesh name: "+p_name);
+
+
+ String current_source;
+ // handles geometry node and the mesh childs in this loop
+ // read sources with arrays and accessor for each mesh
+ if (parser.is_empty()) {
+ return;
+ }
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String section = parser.get_node_name();
+
+
+ if (section == "source") {
+
+ String id=parser.get_attribute_value("id");
+ meshdata.sources[id]=MeshData::Source();
+ current_source=id;
+ COLLADA_PRINT("source data: "+id);
+
+ } else if (section=="float_array" || section=="array") {
+ // create a new array and read it.
+ if (meshdata.sources.has(current_source)) {
+
+ meshdata.sources[current_source].array = _read_float_array(parser);
+ COLLADA_PRINT("section: "+current_source+" read "+itos(meshdata.sources[current_source].array.size())+" values.");
+ }
+ } else if (section == "technique_common") {
+ //skip it
+ } else if (section == "accessor") { // child of source (below a technique tag)
+
+ if (meshdata.sources.has(current_source)) {
+ meshdata.sources[current_source].stride=parser.get_attribute_value("stride").to_int();
+ COLLADA_PRINT("section: "+current_source+" stride "+itos(meshdata.sources[current_source].stride));
+ }
+ } else if (section == "vertices") {
+
+ MeshData::Vertices vert;
+ String id = parser.get_attribute_value("id");
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="input") {
+
+ String semantic = parser.get_attribute_value("semantic");
+ String source =_uri_to_id( parser.get_attribute_value("source") );
+
+ vert.sources[semantic]=source;
+
+ COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
+
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
+ break;
+ }
+
+ meshdata.vertices[id]=vert;
+
+ } else if (section =="triangles" || section=="polylist" || section=="polygons") {
+
+ bool polygons=(section=="polygons");
+ if (polygons) {
+ WARN_PRINT("Primitive type \"polygons\" is not well supported (concave shapes may fail). To ensure that the geometry is properly imported, please re-export using \"triangles\" or \"polylist\".");
+ }
+ MeshData::Primitives prim;
+
+ if (parser.has_attribute("material"))
+ prim.material=parser.get_attribute_value("material");
+ prim.count=parser.get_attribute_value("count").to_int();
+ prim.vertex_size=0;
+ int last_ref=0;
+
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="input") {
+
+ String semantic = parser.get_attribute_value("semantic");
+ String source =_uri_to_id( parser.get_attribute_value("source") );
+
+ if (semantic=="TEXCOORD") {
+ /*
+ if (parser.has_attribute("set"))// a texcoord
+ semantic+=parser.get_attribute_value("set");
+ else
+ semantic="TEXCOORD0";*/
+ semantic="TEXCOORD"+itos(last_ref++);
+ }
+ int offset = parser.get_attribute_value("offset").to_int();
+
+
+ MeshData::Primitives::SourceRef sref;
+ sref.source=source;
+ sref.offset=offset;
+ prim.sources[semantic]=sref;
+ prim.vertex_size=MAX(prim.vertex_size,offset+1);
+
+ COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source+" offset: "+itos(offset));
+
+
+ } else if (parser.get_node_name()=="p") { //indices
+
+ Vector<float> values = _read_float_array(parser);
+ if (polygons) {
+
+ prim.polygons.push_back(values.size()/prim.vertex_size);
+ int from = prim.indices.size();
+ prim.indices.resize(from+values.size());
+ for(int i=0;i<values.size();i++)
+ prim.indices[from+i]=values[i];
+
+ } else if (prim.vertex_size>0){
+ prim.indices=values;
+ }
+
+ COLLADA_PRINT("read "+itos(values.size())+" index values");
+
+ } else if (parser.get_node_name()=="vcount") { // primitive
+
+ Vector<float> values = _read_float_array(parser);
+ prim.polygons=values;
+ COLLADA_PRINT("read "+itos(values.size())+" polygon values");
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
+ break;
+
+ }
+
+ meshdata.primitives.push_back(prim);
+
+ } else if (parser.get_node_name() == "double_sided") {
+
+ parser.read();
+ meshdata.found_double_sided=true;
+ meshdata.double_sided=parser.get_node_data().to_int();
+
+ } else if (parser.get_node_name() == "polygons") {
+ ERR_PRINT("Primitive type \"polygons\" not supported, re-export using \"polylist\" or \"triangles\".");
+ } else if (!parser.is_empty()){
+
+ parser.skip_section();
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="mesh")
+ break;
+ }
+
+
+
+}
+
+void Collada::_parse_skin_controller(XMLParser& parser,String p_id) {
+
+ state.skin_controller_data_map[p_id]=SkinControllerData();
+ SkinControllerData &skindata = state.skin_controller_data_map[p_id];
+
+ skindata.base=_uri_to_id(parser.get_attribute_value("source"));
+
+ String current_source;
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT){
+
+ String section = parser.get_node_name();
+
+ if (section=="bind_shape_matrix") {
+
+ skindata.bind_shape=_read_transform(parser);
+#ifdef COLLADA_IMPORT_SCALE_SCENE
+ skindata.bind_shape.origin *= state.unit_scale;
+
+#endif
+ COLLADA_PRINT("skeleton bind shape transform: "+skindata.bind_shape);
+
+
+ } else if (section == "source") {
+
+ String id=parser.get_attribute_value("id");
+ skindata.sources[id]=SkinControllerData::Source();
+ current_source=id;
+ COLLADA_PRINT("source data: "+id);
+
+ } else if (section=="float_array" || section=="array") {
+ // create a new array and read it.
+ if (skindata.sources.has(current_source)) {
+
+ skindata.sources[current_source].array = _read_float_array(parser);
+ COLLADA_PRINT("section: "+current_source+" read "+itos(skindata.sources[current_source].array.size())+" values.");
+ }
+ } else if (section=="Name_array" || section=="IDREF_array") {
+ // create a new array and read it.
+
+ if (section=="IDREF_array")
+ skindata.use_idrefs=true;
+ if (skindata.sources.has(current_source)) {
+
+ skindata.sources[current_source].sarray = _read_string_array(parser);
+ if (section=="IDREF_array") {
+ Vector<String> sa = skindata.sources[current_source].sarray;
+ for(int i=0;i<sa.size();i++)
+ state.idref_joints.insert(sa[i]);
+ }
+ COLLADA_PRINT("section: "+current_source+" read "+itos(skindata.sources[current_source].array.size())+" values.");
+ }
+ } else if (section == "technique_common") {
+ //skip it
+ } else if (section == "accessor") { // child of source (below a technique tag)
+
+ if (skindata.sources.has(current_source)) {
+
+ int stride=1;
+ if (parser.has_attribute("stride"))
+ stride=parser.get_attribute_value("stride").to_int();
+
+ skindata.sources[current_source].stride=stride;
+ COLLADA_PRINT("section: "+current_source+" stride "+itos(skindata.sources[current_source].stride));
+ }
+
+ } else if (section == "joints") {
+
+ SkinControllerData::Joints joint;
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="input") {
+
+ String semantic = parser.get_attribute_value("semantic");
+ String source =_uri_to_id( parser.get_attribute_value("source") );
+
+ joint.sources[semantic]=source;
+
+ COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
+
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
+ break;
+ }
+
+ skindata.joints=joint;
+
+ } else if (section=="vertex_weights") {
+
+ SkinControllerData::Weights weights;
+
+ weights.count=parser.get_attribute_value("count").to_int();
+
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="input") {
+
+ String semantic = parser.get_attribute_value("semantic");
+ String source =_uri_to_id( parser.get_attribute_value("source") );
+
+ int offset = parser.get_attribute_value("offset").to_int();
+
+ SkinControllerData::Weights::SourceRef sref;
+ sref.source=source;
+ sref.offset=offset;
+ weights.sources[semantic]=sref;
+
+ COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source+" offset: "+itos(offset));
+
+ } else if (parser.get_node_name()=="v") { //indices
+
+ Vector<float> values = _read_float_array(parser);
+ weights.indices=values;
+ COLLADA_PRINT("read "+itos(values.size())+" index values");
+
+ } else if (parser.get_node_name()=="vcount") { // weightsitive
+
+ Vector<float> values = _read_float_array(parser);
+ weights.sets=values;
+ COLLADA_PRINT("read "+itos(values.size())+" polygon values");
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
+ break;
+
+ }
+
+ skindata.weights=weights;
+
+ }
+ /*
+ else if (!parser.is_empty())
+ parser.skip_section();
+ */
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="skin")
+ break;
+ }
+
+ /* STORE REST MATRICES */
+
+ Vector<Transform> rests;
+ ERR_FAIL_COND(!skindata.joints.sources.has("JOINT"));
+ ERR_FAIL_COND(!skindata.joints.sources.has("INV_BIND_MATRIX"));
+
+ String joint_arr = skindata.joints.sources["JOINT"];
+ String ibm = skindata.joints.sources["INV_BIND_MATRIX"];
+
+ ERR_FAIL_COND(!skindata.sources.has(joint_arr));
+ ERR_FAIL_COND(!skindata.sources.has(ibm));
+
+ SkinControllerData::Source &joint_source = skindata.sources[joint_arr];
+ SkinControllerData::Source &ibm_source = skindata.sources[ibm];
+
+
+
+ ERR_FAIL_COND(joint_source.sarray.size() != ibm_source.array.size()/16);
+
+ for(int i=0;i<joint_source.sarray.size();i++) {
+
+ String name = joint_source.sarray[i];
+ Transform xform = _read_transform_from_array(ibm_source.array,i*16); //<- this is a mistake, it must be applied to vertices
+ xform.affine_invert(); // inverse for rest, because it's an inverse
+#ifdef COLLADA_IMPORT_SCALE_SCENE
+ xform.origin*=state.unit_scale;
+#endif
+ skindata.bone_rest_map[name]=xform;
+ }
+
+
+}
+
+void Collada::_parse_morph_controller(XMLParser& parser, String p_id) {
+
+ state.morph_controller_data_map[p_id]=MorphControllerData();
+ MorphControllerData &morphdata = state.morph_controller_data_map[p_id];
+
+ print_line("morph source: "+parser.get_attribute_value("source")+" id: "+p_id);
+ morphdata.mesh=_uri_to_id(parser.get_attribute_value("source"));
+ print_line("morph source2: "+morphdata.mesh);
+ morphdata.mode=parser.get_attribute_value("method");
+ printf("JJmorph: %p\n",&morphdata);
+ String current_source;
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT){
+
+ String section = parser.get_node_name();
+
+ if (section == "source") {
+
+ String id=parser.get_attribute_value("id");
+ morphdata.sources[id]=MorphControllerData::Source();
+ current_source=id;
+ COLLADA_PRINT("source data: "+id);
+
+ } else if (section=="float_array" || section=="array") {
+ // create a new array and read it.
+ if (morphdata.sources.has(current_source)) {
+
+ morphdata.sources[current_source].array = _read_float_array(parser);
+ COLLADA_PRINT("section: "+current_source+" read "+itos(morphdata.sources[current_source].array.size())+" values.");
+ }
+ } else if (section=="Name_array" || section=="IDREF_array") {
+ // create a new array and read it.
+
+ /*
+ if (section=="IDREF_array")
+ morphdata.use_idrefs=true;
+ */
+ if (morphdata.sources.has(current_source)) {
+
+ morphdata.sources[current_source].sarray = _read_string_array(parser);
+ /*
+ if (section=="IDREF_array") {
+ Vector<String> sa = morphdata.sources[current_source].sarray;
+ for(int i=0;i<sa.size();i++)
+ state.idref_joints.insert(sa[i]);
+ }*/
+ COLLADA_PRINT("section: "+current_source+" read "+itos(morphdata.sources[current_source].array.size())+" values.");
+ }
+ } else if (section == "technique_common") {
+ //skip it
+ } else if (section == "accessor") { // child of source (below a technique tag)
+
+ if (morphdata.sources.has(current_source)) {
+
+ int stride=1;
+ if (parser.has_attribute("stride"))
+ stride=parser.get_attribute_value("stride").to_int();
+
+ morphdata.sources[current_source].stride=stride;
+ COLLADA_PRINT("section: "+current_source+" stride "+itos(morphdata.sources[current_source].stride));
+ }
+
+ } else if (section == "targets") {
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="input") {
+
+ String semantic = parser.get_attribute_value("semantic");
+ String source =_uri_to_id( parser.get_attribute_value("source") );
+
+ morphdata.targets[semantic]=source;
+
+ COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
+
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
+ break;
+ }
+
+
+ }
+ /*
+ else if (!parser.is_empty())
+ parser.skip_section();
+ */
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="morph")
+ break;
+ }
+
+
+ if (morphdata.targets.has("MORPH_WEIGHT")) {
+
+ state.morph_name_map[ morphdata.targets["MORPH_WEIGHT"] ] = p_id;
+ }
+
+}
+
+void Collada::_parse_controller(XMLParser& parser) {
+
+ String id=parser.get_attribute_value("id");
+
+ if (parser.is_empty()) {
+ return;
+ }
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT){
+
+ String section = parser.get_node_name();
+
+ if (section=="skin") {
+ _parse_skin_controller(parser,id);
+ } else if (section == "morph") {
+ _parse_morph_controller(parser,id);
+ }
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="controller")
+ break;
+ }
+
+
+}
+
+
+Collada::Node* Collada::_parse_visual_instance_geometry(XMLParser& parser) {
+
+ String type = parser.get_node_name();
+ NodeGeometry *geom=memnew( NodeGeometry );
+ geom->controller=type=="instance_controller";
+ geom->source = _uri_to_id(parser.get_attribute_value_safe("url"));
+
+
+
+ if (parser.is_empty()) //nothing else to parse...
+ return geom;
+ // try to find also many materials and skeletons!
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="instance_material") {
+
+ String symbol=parser.get_attribute_value("symbol");
+ String target=_uri_to_id(parser.get_attribute_value("target"));
+
+ NodeGeometry::Material mat;
+ mat.target=target;
+ geom->material_map[symbol]=mat;
+ COLLADA_PRINT("uses material: '"+target+"' on primitive'"+symbol+"'");
+ } else if (parser.get_node_name()=="skeleton") {
+
+ parser.read();
+ String uri = _uri_to_id(parser.get_node_data());
+ if (uri!="") {
+ geom->skeletons.push_back(uri);
+ }
+
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==type)
+ break;
+
+
+ }
+
+ if (geom->controller) {
+
+ if (geom->skeletons.empty()) {
+ //XSI style
+
+ if (state.skin_controller_data_map.has(geom->source)) {
+ SkinControllerData *skin = &state.skin_controller_data_map[geom->source];
+ //case where skeletons reference bones with IDREF (XSI)
+ ERR_FAIL_COND_V(!skin->joints.sources.has("JOINT"),geom);
+ String joint_arr = skin->joints.sources["JOINT"];
+ ERR_FAIL_COND_V(!skin->sources.has(joint_arr),geom);
+ Collada::SkinControllerData::Source &joint_source = skin->sources[joint_arr];
+ geom->skeletons=joint_source.sarray; //quite crazy, but should work.
+ }
+
+ }
+
+ }
+
+ return geom;
+}
+
+
+Collada::Node* Collada::_parse_visual_instance_camera(XMLParser& parser) {
+
+ String type = parser.get_node_name();
+ NodeCamera *cam=memnew( NodeCamera );
+ cam->camera= _uri_to_id(parser.get_attribute_value_safe("url"));
+
+ if (state.up_axis==Vector3::AXIS_Z) //collada weirdness
+ cam->post_transform.basis.rotate(Vector3(1,0,0),-Math_PI*0.5);
+
+ if (parser.is_empty()) //nothing else to parse...
+ return cam;
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="instance_camera")
+ break;
+ }
+
+ return cam;
+}
+
+Collada::Node* Collada::_parse_visual_instance_light(XMLParser& parser) {
+
+ String type = parser.get_node_name();
+ NodeLight *cam=memnew( NodeLight );
+ cam->light= _uri_to_id(parser.get_attribute_value_safe("url"));
+
+ if (state.up_axis==Vector3::AXIS_Z) //collada weirdness
+ cam->post_transform.basis.rotate(Vector3(1,0,0),-Math_PI*0.5);
+
+ if (parser.is_empty()) //nothing else to parse...
+ return cam;
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="instance_light")
+ break;
+ }
+
+ return cam;
+}
+
+
+Collada::Node* Collada::_parse_visual_node_instance_data(XMLParser& parser) {
+
+ String instance_type = parser.get_node_name();
+
+
+ if (instance_type=="instance_geometry" || instance_type=="instance_controller") {
+ return _parse_visual_instance_geometry(parser);
+ } else if (instance_type=="instance_camera") {
+
+ return _parse_visual_instance_camera(parser);
+ } else if (instance_type=="instance_light") {
+ return _parse_visual_instance_light(parser);
+ }
+
+
+ if (parser.is_empty()) //nothing else to parse...
+ return NULL;
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==instance_type)
+ break;
+ }
+
+ return NULL;
+}
+
+Collada::Node* Collada::_parse_visual_scene_node(XMLParser& parser) {
+
+ String name;
+
+ String id = parser.get_attribute_value_safe("id");
+
+ bool found_name=false;
+
+ if (id=="") {
+
+ id="%NODEID%"+itos(Math::rand());
+
+ } else {
+ found_name=true;
+ }
+
+ Vector<Node::XForm> xform_list;
+ Vector<Node*> children;
+
+ String empty_draw_type="";
+
+ Node *node=NULL;
+
+ name=parser.has_attribute("name")?parser.get_attribute_value_safe("name"):parser.get_attribute_value_safe("id");
+ if (name=="") {
+
+ name=id;
+ } else {
+ found_name=true;
+ }
+
+ if ((parser.has_attribute("type") && parser.get_attribute_value("type")=="JOINT") || state.idref_joints.has(name)) {
+ // handle a bone
+
+ NodeJoint *joint = memnew( NodeJoint );
+
+ 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)) {
+ 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;
+ }
+
+ node=joint;
+
+
+ }
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String section = parser.get_node_name();
+
+ if (section=="translate") {
+ Node::XForm xf;
+ if (parser.has_attribute("sid")) {
+ xf.id=parser.get_attribute_value("sid");
+ }
+ xf.op=Node::XForm::OP_TRANSLATE;
+
+ Vector<float> xlt = _read_float_array(parser);
+ xf.data=xlt;
+ xform_list.push_back(xf);
+
+ } else if (section=="rotate") {
+ Node::XForm xf;
+ if (parser.has_attribute("sid")) {
+ xf.id=parser.get_attribute_value("sid");
+ }
+ xf.op=Node::XForm::OP_ROTATE;
+
+ Vector<float> rot = _read_float_array(parser);
+ xf.data=rot;
+
+ xform_list.push_back(xf);
+
+ } else if (section=="scale") {
+ Node::XForm xf;
+ if (parser.has_attribute("sid")) {
+ xf.id=parser.get_attribute_value("sid");
+ }
+
+ xf.op=Node::XForm::OP_SCALE;
+
+ Vector<float> scale = _read_float_array(parser);
+
+ xf.data=scale;
+
+ xform_list.push_back(xf);
+
+ } else if (section=="matrix") {
+ Node::XForm xf;
+ if (parser.has_attribute("sid")) {
+ xf.id=parser.get_attribute_value("sid");
+ }
+ xf.op=Node::XForm::OP_MATRIX;
+
+ Vector<float> matrix = _read_float_array(parser);
+
+ xf.data=matrix;
+ String mtx;
+ for(int i=0;i<matrix.size();i++)
+ mtx+=" "+rtos(matrix[i]);
+
+ xform_list.push_back(xf);
+
+ } else if (section=="visibility") {
+ Node::XForm xf;
+ if (parser.has_attribute("sid")) {
+ xf.id=parser.get_attribute_value("sid");
+ }
+ xf.op=Node::XForm::OP_VISIBILITY;
+
+ Vector<float> visible = _read_float_array(parser);
+
+ xf.data=visible;
+
+ xform_list.push_back(xf);
+
+ } else if (section=="empty_draw_type") {
+ empty_draw_type = _read_empty_draw_type(parser);
+ } else if (section == "technique" || section=="extra") {
+
+ } else if (section!="node") {
+ //usually what defines the type of node
+ //print_line(" dont know what to do with "+section);
+ if (section.begins_with("instance_")) {
+
+ if (!node) {
+
+ node = _parse_visual_node_instance_data(parser);
+
+ } else {
+ ERR_PRINT("Multiple instance_* not supported.");
+ }
+
+ }
+
+ } else if (section=="node") {
+
+ /* Found a child node!! what to do..*/
+
+ Node *child = _parse_visual_scene_node(parser);
+ children.push_back(child);
+
+
+
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="node")
+ break;
+ }
+
+ if (!node) {
+
+ node = memnew( Node ); //generic node, nothing of relevance found
+ }
+
+ node->noname=!found_name;
+ node->xform_list=xform_list;
+ node->children=children;
+ for(int i=0;i<children.size();i++) {
+ node->children[i]->parent=node;
+ }
+
+ node->name=name;
+ node->id=id;
+ node->empty_draw_type=empty_draw_type;
+
+ if (node->children.size()==1) {
+ if (node->children[0]->noname && !node->noname) {
+ node->children[0]->name=node->name;
+ node->name=node->name+"-base";
+ }
+ }
+
+
+
+ node->default_transform = node->compute_transform(*this);
+ state.scene_map[id]=node;
+
+
+ return node;
+}
+
+void Collada::_parse_visual_scene(XMLParser& parser) {
+
+ String id=parser.get_attribute_value("id");
+
+ if (parser.is_empty()) {
+ return;
+ }
+
+ state.visual_scene_map[id]=VisualScene();
+ VisualScene &vscene = state.visual_scene_map[id];
+
+ if (parser.has_attribute("name"))
+ vscene.name=parser.get_attribute_value("name");
+
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String section = parser.get_node_name();
+
+ if (section=="node") {
+ vscene.root_nodes.push_back(_parse_visual_scene_node(parser));
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="visual_scene")
+ break;
+ }
+
+
+ COLLADA_PRINT("Scene ID:"+id);
+
+
+}
+
+void Collada::_parse_animation(XMLParser& parser) {
+
+ if (!(state.import_flags&IMPORT_FLAG_ANIMATION)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+
+
+ return;
+ }
+
+ Map<String,Vector<float> > float_sources;
+ Map<String,Vector<String> > string_sources;
+ Map<String,int > source_strides;
+ Map<String, Map<String,String> > samplers;
+ Map<String,Vector<String> > source_param_names;
+ Map<String,Vector<String> > source_param_types;
+
+ String id="";
+ if (parser.has_attribute("id"))
+ id=parser.get_attribute_value("id");
+
+ String current_source;
+ String current_sampler;
+ Vector<String> channel_sources;
+ Vector<String> channel_targets;
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+ if (name=="source") {
+
+ current_source=parser.get_attribute_value("id");
+ source_param_names[current_source]=Vector<String>();
+ source_param_types[current_source]=Vector<String>();
+
+ } else if (name=="float_array") {
+
+ if (current_source!="") {
+ float_sources[current_source]=_read_float_array(parser);
+ }
+
+ } else if (name=="Name_array") {
+
+ if (current_source!="") {
+ string_sources[current_source]=_read_string_array(parser);
+ }
+ } else if (name=="accessor") {
+
+ if (current_source!="" && parser.has_attribute("stride")) {
+ source_strides[current_source]=parser.get_attribute_value("stride").to_int();
+ }
+ } else if (name=="sampler") {
+
+ current_sampler=parser.get_attribute_value("id");
+ samplers[current_sampler]=Map<String,String>();
+ } else if (name=="param") {
+
+ if (parser.has_attribute("name"))
+ source_param_names[current_source].push_back(parser.get_attribute_value("name"));
+ else
+ source_param_names[current_source].push_back("");
+
+ if (parser.has_attribute("type"))
+ source_param_types[current_source].push_back(parser.get_attribute_value("type"));
+ else
+ source_param_types[current_source].push_back("");
+
+ } else if (name=="input") {
+
+ if (current_sampler!="") {
+
+ samplers[current_sampler][parser.get_attribute_value("semantic")]=parser.get_attribute_value("source");
+ }
+
+ } else if (name=="channel") {
+
+ channel_sources.push_back(parser.get_attribute_value("source"));
+ channel_targets.push_back(parser.get_attribute_value("target"));
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="animation")
+ break; //end of <asset>
+
+
+ }
+
+
+ for(int i=0;i<channel_sources.size();i++) {
+
+ String source=_uri_to_id(channel_sources[i]);
+ String target=channel_targets[i];
+ if (!samplers.has(source)) {
+ print_line("channel lacks source: "+source);
+ }
+ ERR_CONTINUE(!samplers.has(source));
+ Map<String,String>& sampler=samplers[source];
+
+ ERR_CONTINUE(!sampler.has("INPUT")); //no input semantic? wtf?
+ String input_id=_uri_to_id(sampler["INPUT"]);
+ COLLADA_PRINT("input id is "+input_id);
+ ERR_CONTINUE(!float_sources.has(input_id));
+
+ ERR_CONTINUE(!sampler.has("OUTPUT"));
+ String output_id=_uri_to_id(sampler["OUTPUT"]);
+ ERR_CONTINUE(!float_sources.has(output_id));
+
+ ERR_CONTINUE(!source_param_names.has(output_id));
+
+ Vector<String> &names = source_param_names[output_id];
+
+ for(int l=0;l<names.size();l++) {
+
+ String name = names[l];
+
+ Vector<float> &time_keys=float_sources[input_id];
+ int key_count = time_keys.size();
+
+ AnimationTrack track; //begin crating track
+ track.id=id;
+
+ track.keys.resize(key_count);
+
+ for(int j=0;j<key_count;j++) {
+ track.keys[j].time=time_keys[j];
+ state.animation_length = MAX(state.animation_length,time_keys[j] );
+ }
+
+ //now read actual values
+
+ int stride=1;
+
+ if (source_strides.has(output_id))
+ stride=source_strides[output_id];
+ int output_len=stride / names.size();
+
+ ERR_CONTINUE(output_len==0);
+ ERR_CONTINUE(!float_sources.has(output_id));
+
+ Vector<float> &output = float_sources[output_id];
+
+ ERR_EXPLAIN("Wrong number of keys in output");
+ ERR_CONTINUE( (output.size()/stride) != key_count );
+
+ for(int j=0;j<key_count;j++) {
+ track.keys[j].data.resize(output_len);
+ for(int k=0;k<output_len;k++)
+ track.keys[j].data[k]=output[l+j*stride+k]; //super weird but should work
+ }
+
+ if(sampler.has("INTERPOLATION")) {
+
+ String interp_id=_uri_to_id(sampler["INTERPOLATION"]);
+ ERR_CONTINUE(!string_sources.has(interp_id));
+ Vector<String> &interps=string_sources[interp_id];
+ ERR_CONTINUE(interps.size()!=key_count);
+
+ for(int j=0;j<key_count;j++) {
+ if (interps[j]=="BEZIER")
+ track.keys[j].interp_type=AnimationTrack::INTERP_BEZIER;
+ else
+ track.keys[j].interp_type=AnimationTrack::INTERP_LINEAR;
+ }
+ }
+
+ if (sampler.has("IN_TANGENT") && sampler.has("OUT_TANGENT")) {
+ //bezier control points..
+ String intangent_id=_uri_to_id(sampler["IN_TANGENT"]);
+ ERR_CONTINUE(!float_sources.has(intangent_id));
+ Vector<float> &intangents=float_sources[intangent_id];
+
+
+
+
+ ERR_CONTINUE(intangents.size()!=key_count*2*names.size());
+
+ String outangent_id=_uri_to_id(sampler["OUT_TANGENT"]);
+ ERR_CONTINUE(!float_sources.has(outangent_id));
+ Vector<float> &outangents=float_sources[outangent_id];
+ ERR_CONTINUE(outangents.size()!=key_count*2*names.size());
+
+ for(int j=0;j<key_count;j++) {
+ track.keys[j].in_tangent=Vector2( intangents[j*2*names.size()+0+l*2],intangents[j*2*names.size()+1+l*2] );
+ track.keys[j].out_tangent=Vector2( outangents[j*2*names.size()+0+l*2],outangents[j*2*names.size()+1+l*2] );
+ }
+ }
+
+ if (target.find("/")!=-1) { //transform component
+ track.target=target.get_slicec('/',0);
+ track.param=target.get_slicec('/',1);
+ if (track.param.find(".")!=-1)
+ track.component=track.param.get_slice(".",1).to_upper();
+ track.param=track.param.get_slice(".",0);
+ if (names.size()>1 && track.component=="") {
+ //this is a guess because the collada spec is ambiguous here...
+ //i suppose if you have many names (outputs) you can't use a component and i should abide to that.
+ track.component=name;
+
+ }
+ } else {
+ track.target=target;
+ }
+
+ print_line("TARGET: "+track.target);
+
+ state.animation_tracks.push_back(track);
+
+ if (!state.referenced_tracks.has(target))
+ state.referenced_tracks[target]=Vector<int>();
+
+ state.referenced_tracks[target].push_back(state.animation_tracks.size()-1);
+
+ if (id!="") {
+ if (!state.by_id_tracks.has(id))
+ state.by_id_tracks[id]=Vector<int>();
+
+ state.by_id_tracks[id].push_back(state.animation_tracks.size()-1);
+ }
+
+ COLLADA_PRINT("loaded animation with "+itos(key_count)+" keys");
+ }
+
+ }
+}
+
+void Collada::_parse_animation_clip(XMLParser& parser) {
+
+ if (!(state.import_flags&IMPORT_FLAG_ANIMATION)) {
+ if (!parser.is_empty())
+ parser.skip_section();
+
+
+ return;
+ }
+
+
+ AnimationClip clip;
+
+ if (parser.has_attribute("name"))
+ clip.name=parser.get_attribute_value("name");
+ else if (parser.has_attribute("id"))
+ clip.name=parser.get_attribute_value("id");
+ if (parser.has_attribute("start"))
+ clip.begin=parser.get_attribute_value("start").to_double();
+ if (parser.has_attribute("end"))
+ clip.end=parser.get_attribute_value("end").to_double();
+
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+ if (name=="instance_animation") {
+
+ String url = _uri_to_id(parser.get_attribute_value("url"));
+ clip.tracks.push_back(url);
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="animation_clip")
+ break; //end of <asset>
+
+ }
+
+ state.animation_clips.push_back(clip);
+ print_line("found anim clip: "+clip.name);
+
+}
+void Collada::_parse_scene(XMLParser& parser) {
+
+ if (parser.is_empty()) {
+ return;
+ }
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+
+ if (name=="instance_visual_scene") {
+
+ state.root_visual_scene=_uri_to_id(parser.get_attribute_value("url"));
+ print_line("***ROOT VISUAL SCENE: "+state.root_visual_scene);
+ } else if (name=="instance_physics_scene") {
+
+ state.root_physics_scene=_uri_to_id(parser.get_attribute_value("url"));
+
+ }
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="scene")
+ break; //end of <asset>
+ }
+}
+
+void Collada::_parse_library(XMLParser& parser) {
+
+
+ if (parser.is_empty()) {
+ return;
+ }
+
+ while(parser.read()==OK) {
+
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser.get_node_name();
+ COLLADA_PRINT("library name is: "+name);
+ if (name=="image") {
+
+ _parse_image(parser);
+ } else if (name=="material") {
+
+ _parse_material(parser);
+ } else if (name=="effect") {
+
+ _parse_effect(parser);
+ } else if (name=="camera") {
+
+ _parse_camera(parser);
+ } else if (name=="light") {
+
+ _parse_light(parser);
+ } else if (name=="geometry") {
+
+ String id = parser.get_attribute_value("id");
+ String name = parser.get_attribute_value_safe("name");
+ while(parser.read()==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name()=="mesh") {
+ state.mesh_name_map[id]=(name!="")?name:id;
+ _parse_mesh_geometry(parser,id,name);
+ } else if (parser.get_node_name()=="spline") {
+ state.mesh_name_map[id]=(name!="")?name:id;
+ _parse_curve_geometry(parser,id,name);
+ } else if (!parser.is_empty())
+ parser.skip_section();
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="geometry")
+ break;
+ }
+
+ } else if (name=="controller") {
+
+ _parse_controller(parser);
+ } else if (name=="animation") {
+
+ _parse_animation(parser);
+ } else if (name=="animation_clip") {
+
+ _parse_animation_clip(parser);
+ } else if (name=="visual_scene") {
+
+ COLLADA_PRINT("visual scene");
+ _parse_visual_scene(parser);
+ } else if (!parser.is_empty())
+ parser.skip_section();
+
+ } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name().begins_with("library_"))
+ break; //end of <asset>
+
+
+ }
+
+}
+
+void Collada::_joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner) {
+
+ if (p_node->type==Node::TYPE_JOINT) {
+
+ NodeJoint *nj = static_cast<NodeJoint*>(p_node);
+ nj->owner=p_owner;
+
+ for(int i=0;i<nj->children.size();i++) {
+
+ _joint_set_owner(nj->children[i],p_owner);
+ }
+ }
+}
+
+void Collada::_create_skeletons(Collada::Node **p_node,NodeSkeleton *p_skeleton) {
+
+
+ Node *node = *p_node;
+
+ if (node->type==Node::TYPE_JOINT) {
+
+ if (!p_skeleton) {
+
+ // ohohohoohoo it's a joint node, time to work!
+ NodeSkeleton *sk = memnew( NodeSkeleton );
+ *p_node=sk;
+ sk->children.push_back(node);
+ sk->parent=node->parent;
+ node->parent=sk;
+ p_skeleton=sk;
+ }
+
+ NodeJoint *nj = static_cast<NodeJoint*>(node);
+ nj->owner=p_skeleton;
+ } else {
+ p_skeleton=NULL;
+ }
+
+
+ for(int i=0;i<node->children.size();i++) {
+ _create_skeletons(&node->children[i],p_skeleton);
+ }
+
+}
+
+bool Collada::_remove_node(Node *p_parent,Node *p_node) {
+
+ for(int i=0;i<p_parent->children.size();i++) {
+
+ if (p_parent->children[i]==p_node) {
+ p_parent->children.remove(i);
+ return true;
+ }
+ if (_remove_node(p_parent->children[i],p_node))
+ return true;
+ }
+
+ return false;
+}
+
+void Collada::_remove_node(VisualScene *p_vscene,Node *p_node) {
+
+ for(int i=0;i<p_vscene->root_nodes.size();i++) {
+ if (p_vscene->root_nodes[i]==p_node) {
+
+ p_vscene->root_nodes.remove(i);
+ return;
+ }
+ if (_remove_node(p_vscene->root_nodes[i],p_node))
+ return;
+ }
+
+ ERR_PRINT("ERROR: Not found node to remove?");
+
+}
+
+
+void Collada::_merge_skeletons(VisualScene *p_vscene,Node *p_node) {
+
+ if (p_node->type==Node::TYPE_GEOMETRY) {
+
+ NodeGeometry *gnode = static_cast<NodeGeometry*>(p_node);
+ if (gnode->controller) {
+
+ // recount skeletons used
+ Set<NodeSkeleton*> skeletons;
+
+ for(int i=0;i<gnode->skeletons.size();i++) {
+
+ String nodeid = gnode->skeletons[i];
+
+ ERR_CONTINUE( !state.scene_map.has( nodeid )); //weird, it should have it...
+
+
+ NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
+ if (!nj->owner) {
+ print_line("no owner for: "+String(nodeid));
+ }
+ ERR_CONTINUE( !nj->owner ); //weird, node should have a skeleton owner
+
+ skeletons.insert(nj->owner);
+ }
+
+ if (skeletons.size()>1) {
+
+ //do the merger!!
+ Set<NodeSkeleton*>::Element *E=skeletons.front();
+ NodeSkeleton *base = E->get();
+
+ for(E=E->next();E;E=E->next() ) {
+
+ NodeSkeleton *merged = E->get();
+ _remove_node(p_vscene,merged);
+ for(int i=0;i<merged->children.size();i++) {
+
+ _joint_set_owner(merged->children[i],base);
+ base->children.push_back( merged->children[i] );
+ merged->children[i]->parent=base;
+
+
+ }
+
+ merged->children.clear(); //take children from it
+ memdelete( merged );
+ }
+
+ }
+ }
+ }
+
+ for(int i=0;i<p_node->children.size();i++) {
+ _merge_skeletons(p_vscene,p_node->children[i]);
+ }
+
+}
+
+
+void Collada::_merge_skeletons2(VisualScene *p_vscene) {
+
+ for (Map<String,SkinControllerData>::Element *E=state.skin_controller_data_map.front();E;E=E->next()) {
+
+ SkinControllerData &cd=E->get();
+
+ NodeSkeleton *skeleton=NULL;
+
+ for (Map<String,Transform>::Element *F=cd.bone_rest_map.front();F;F=F->next()) {
+
+ String name;
+
+ if (!state.sid_to_node_map.has(F->key())) {
+ continue;
+ }
+
+ name = state.sid_to_node_map[F->key()];
+
+ if (!state.scene_map.has(name)) {
+ print_line("no foundie node for: "+name);
+ }
+
+ ERR_CONTINUE( !state.scene_map.has(name) );
+
+ Node *node=state.scene_map[name];
+ ERR_CONTINUE( node->type!=Node::TYPE_JOINT );
+ if (node->type!=Node::TYPE_JOINT)
+ continue;
+ NodeSkeleton *sk=NULL;
+
+ while(node && !sk) {
+
+ if (node->type==Node::TYPE_SKELETON) {
+ sk=static_cast<NodeSkeleton*>(node);
+ }
+ node=node->parent;
+ }
+ ERR_CONTINUE( !sk );
+
+ if (!sk)
+ continue; //bleh
+
+ if (!skeleton) {
+ skeleton=sk;
+ continue;
+ }
+
+ if (skeleton!=sk) {
+ //whoa.. wtf, merge.
+ print_line("MERGED BONES!!");
+
+ //NodeSkeleton *merged = E->get();
+ _remove_node(p_vscene,sk);
+ for(int i=0;i<sk->children.size();i++) {
+
+ _joint_set_owner(sk->children[i],skeleton);
+ skeleton->children.push_back( sk->children[i] );
+ sk->children[i]->parent=skeleton;
+
+
+ }
+
+ sk->children.clear(); //take children from it
+ memdelete( sk );
+ }
+ }
+ }
+
+
+
+}
+
+bool Collada::_optimize_skeletons(VisualScene *p_vscene,Node *p_node) {
+
+ Node *node=p_node;
+
+ if (node->type==Node::TYPE_SKELETON && node->parent && node->parent->type==Node::TYPE_NODE && node->parent->children.size()==1) {
+ //replace parent by this...
+ Node *parent = node->parent;
+
+ //i wonder if this is allright.. i think it is since created skeleton (first joint) is already animated by bone..
+ node->id=parent->id;
+ node->name=parent->name;
+ node->xform_list=parent->xform_list;
+ node->default_transform=parent->default_transform;
+
+ state.scene_map[node->id]=node;
+ node->parent=parent->parent;
+
+ if (parent->parent) {
+ Node *gp = parent->parent;
+ bool found=false;
+ for(int i=0;i<gp->children.size();i++) {
+
+ if (gp->children[i]==parent) {
+ gp->children[i]=node;
+ found=true;
+ break;
+ }
+ }
+ if (!found) {
+ ERR_PRINT("BUG");
+ }
+ } else {
+
+ bool found=false;
+
+ for(int i=0;i<p_vscene->root_nodes.size();i++) {
+
+ if (p_vscene->root_nodes[i]==parent) {
+
+ p_vscene->root_nodes[i]=node;
+ found=true;
+ break;
+ }
+ }
+ if (!found) {
+ ERR_PRINT("BUG");
+ }
+
+ }
+
+ parent->children.clear();
+ memdelete(parent);
+ return true;
+ }
+
+ for(int i=0;i<node->children.size();i++) {
+
+ if (_optimize_skeletons(p_vscene,node->children[i]))
+ return false; //stop processing, go up
+ }
+
+ return false;
+
+}
+
+
+bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene,Node *p_node,List<Node*> *p_mgeom) {
+
+ // bind shape matrix escala los huesos y los hace gigantes, asi la matriz despues achica
+ // al modelo?
+ // solucion: aplicarle la bind shape matrix a los VERTICES, y si el objeto viene con escala, se la dejo me parece!
+
+ if (p_node->type==Node::TYPE_GEOMETRY) {
+
+ NodeGeometry *ng = static_cast<NodeGeometry*>(p_node);
+ if (ng->ignore_anim)
+ return false; //already made child of skeleton and processeg
+
+ if (ng->controller && ng->skeletons.size()) {
+
+ String nodeid = ng->skeletons[0];
+
+ ERR_FAIL_COND_V( !state.scene_map.has( nodeid ), false); //weird, it should have it...
+ NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
+ ERR_FAIL_COND_V(!nj,false);
+ if (!nj->owner) {
+ print_line("Has no owner: "+nj->name);
+ }
+ ERR_FAIL_COND_V( !nj->owner,false ); //weird, node should have a skeleton owner
+
+ NodeSkeleton *sk = nj->owner;
+
+ Node *p =sk->parent;
+ bool node_is_parent_of_skeleton=false;
+
+ while (p) {
+ if (p==p_node) {
+ node_is_parent_of_skeleton=true;
+ break;
+ }
+ p=p->parent; // try again
+ }
+
+ ERR_FAIL_COND_V( node_is_parent_of_skeleton, false);
+
+ //this should be correct
+ ERR_FAIL_COND_V( !state.skin_controller_data_map.has(ng->source), false);
+ SkinControllerData &skin=state.skin_controller_data_map[ng->source];
+ Transform skel_inv = sk->get_global_transform().affine_inverse();
+ p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it
+
+ //make rests relative to the skeleton (they seem to be always relative to world)
+ for(Map<String,Transform>::Element *E=skin.bone_rest_map.front();E;E=E->next()) {
+
+ E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton
+ state.bone_rest_map[E->key()]=E->get(); // make it remember where the bone is globally, now that it's relative
+ }
+
+ //but most exporters seem to work only if i do this..
+ //p_node->default_transform = p_node->get_global_transform();
+
+
+
+ //p_node->default_transform=Transform(); //this seems to be correct, because bind shape makes the object local to the skeleton
+ p_node->ignore_anim=true; // collada may animate this later, if it does, then this is not supported (redo your original asset and don't animate the base mesh)
+ p_node->parent=sk;
+ //sk->children.push_back(0,p_node); //avoid INFINIT loop
+ p_mgeom->push_back(p_node);
+ return true;
+ }
+ }
+
+ for(int i=0;i<p_node->children.size();i++) {
+
+ if (_move_geometry_to_skeletons(p_vscene,p_node->children[i],p_mgeom)) {
+ p_node->children.remove(i);
+ i--;
+ }
+ }
+
+ return false;
+}
+
+void Collada::_find_morph_nodes(VisualScene *p_vscene,Node *p_node) {
+
+ if (p_node->type==Node::TYPE_GEOMETRY) {
+
+ NodeGeometry *nj = static_cast<NodeGeometry*>(p_node);
+
+ if (nj->controller) {
+
+ String base = nj->source;
+
+ while(base!="" && !state.mesh_data_map.has(base)) {
+
+ if (state.skin_controller_data_map.has(base)) {
+
+ SkinControllerData &sk = state.skin_controller_data_map[base];
+ base=sk.base;
+ } else if (state.morph_controller_data_map.has(base)) {
+
+ state.morph_ownership_map[base]=nj->id;
+ break;
+ } else {
+ ERR_EXPLAIN("Invalid scene");
+ ERR_FAIL();
+ }
+ }
+
+ }
+ }
+
+ for(int i=0;i<p_node->children.size();i++) {
+
+ _find_morph_nodes(p_vscene,p_node->children[i]);
+ }
+
+}
+
+void Collada::_optimize() {
+
+
+ for(Map<String,VisualScene>::Element *E=state.visual_scene_map.front();E;E=E->next()) {
+
+ VisualScene &vs = E->get();
+ for(int i=0;i<vs.root_nodes.size();i++) {
+ _create_skeletons(&vs.root_nodes[i]);
+
+ }
+#if 1
+ for(int i=0;i<vs.root_nodes.size();i++) {
+ _merge_skeletons(&vs,vs.root_nodes[i]);
+ }
+
+ _merge_skeletons2(&vs);
+
+
+ for(int i=0;i<vs.root_nodes.size();i++) {
+ _optimize_skeletons(&vs,vs.root_nodes[i]);
+ }
+
+ for(int i=0;i<vs.root_nodes.size();i++) {
+
+ List<Node*> mgeom;
+ if (_move_geometry_to_skeletons(&vs,vs.root_nodes[i],&mgeom)) {
+ vs.root_nodes.remove(i);
+ i--;
+ }
+
+ while(!mgeom.empty()) {
+
+ Node * n= mgeom.front()->get();
+ n->parent->children.push_back(n);
+ mgeom.pop_front();
+ }
+
+ }
+#endif
+ for(int i=0;i<vs.root_nodes.size();i++) {
+ _find_morph_nodes(&vs,vs.root_nodes[i]);
+ }
+
+ }
+}
+
+
+int Collada::get_uv_channel(String p_name) {
+
+ if (!channel_map.has(p_name)) {
+
+ ERR_FAIL_COND_V(channel_map.size()==2,0);
+
+ channel_map[p_name]=channel_map.size();
+ }
+
+ return channel_map[p_name];
+}
+
+Error Collada::load(const String& p_path, int p_flags) {
+
+ Ref<XMLParser> parserr = memnew( XMLParser );
+ XMLParser &parser = *parserr.ptr();
+ Error err = parser.open(p_path);
+ ERR_FAIL_COND_V(err,err);
+
+ state.local_path = GlobalConfig::get_singleton()->localize_path(p_path);
+ state.import_flags=p_flags;
+ /* Skip headers */
+ err=OK;
+ while((err=parser.read())==OK) {
+
+ if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser.get_node_name() == "COLLADA") {
+ break;
+ } else if (!parser.is_empty())
+ parser.skip_section();// unknown section, likely headers
+ }
+ }
+
+ ERR_FAIL_COND_V(err!=OK, ERR_FILE_CORRUPT);
+
+ /* Start loading Collada */
+
+ {
+ //version
+ String version = parser.get_attribute_value("version");
+ state.version.major=version.get_slice(".",0).to_int();
+ state.version.minor=version.get_slice(".",1).to_int();
+ state.version.rev=version.get_slice(".",2).to_int();
+ COLLADA_PRINT("Collada VERSION: "+version);
+ }
+
+
+
+ while((err=parser.read())==OK) {
+
+ /* Read all the main sections.. */
+
+ if (parser.get_node_type() != XMLParser::NODE_ELEMENT)
+ continue; //no idea what this may be, but skipping anyway
+
+ String section = parser.get_node_name();
+
+ COLLADA_PRINT("section: "+section);
+
+ if (section=="asset") {
+ _parse_asset(parser);
+
+ } else if (section.begins_with("library_")) {
+
+ _parse_library(parser);
+ } else if (section=="scene") {
+
+ _parse_scene(parser);
+ } else if (!parser.is_empty()) {
+ parser.skip_section(); // unknown section, likely headers
+ }
+
+ }
+
+ _optimize();
+ return OK;
+}
+
+
+
+
+Collada::Collada() {
+
+
+}
+
+#endif
diff --git a/editor/collada/collada.h b/editor/collada/collada.h
new file mode 100644
index 0000000000..2de2d22935
--- /dev/null
+++ b/editor/collada/collada.h
@@ -0,0 +1,663 @@
+/*************************************************************************/
+/* collada.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifdef TOOLS_ENABLED
+
+#ifndef COLLADA_H
+#define COLLADA_H
+
+
+#include "scene/resources/material.h"
+#include "global_config.h"
+#include "io/xml_parser.h"
+#include "map.h"
+
+class Collada {
+public:
+
+ enum ImportFlags {
+ IMPORT_FLAG_SCENE=1,
+ IMPORT_FLAG_ANIMATION=2
+ };
+
+
+ struct Image {
+
+ String path;
+ };
+
+ struct Material {
+
+ String name;
+ String instance_effect;
+ };
+
+
+ struct Effect {
+
+ String name;
+ Map<String, Variant> params;
+
+ struct Channel {
+
+ int uv_idx;
+ String texture;
+ Color color;
+ Channel() { uv_idx=0; }
+ };
+
+ Channel diffuse,specular,emission,bump;
+ float shininess;
+ bool found_double_sided;
+ bool double_sided;
+ bool unshaded;
+
+ String get_texture_path(const String& p_source,Collada& state) const;
+
+ Effect() {
+ diffuse.color=Color(1,1,1,1);
+ double_sided=true;
+ found_double_sided=false;
+ shininess=40;
+ unshaded=false;
+ }
+ };
+
+ struct CameraData {
+
+ enum Mode {
+ MODE_PERSPECTIVE,
+ MODE_ORTHOGONAL
+ };
+
+ Mode mode;
+
+ union {
+ struct {
+ float x_fov;
+ float y_fov;
+ } perspective;
+ struct {
+ float x_mag;
+ float y_mag;
+ } orthogonal;
+ };
+
+ float aspect;
+ float z_near;
+ float z_far;
+
+ CameraData() {
+
+ mode=MODE_PERSPECTIVE;
+ perspective.y_fov=0;
+ perspective.x_fov=0;
+ aspect=1;
+ z_near=0.1;
+ z_far=100;
+ }
+ };
+
+ struct LightData {
+
+ enum Mode {
+ MODE_AMBIENT,
+ MODE_DIRECTIONAL,
+ MODE_OMNI,
+ MODE_SPOT
+ };
+
+ Mode mode;
+
+ Color color;
+
+ float constant_att;
+ float linear_att;
+ float quad_att;
+
+ float spot_angle;
+ float spot_exp;
+
+ LightData() {
+
+ mode=MODE_AMBIENT;
+ color=Color(1,1,1,1);
+ constant_att=0;
+ linear_att=0;
+ quad_att=0;
+
+ spot_angle=45;
+ spot_exp=1;
+ }
+ };
+
+
+ struct MeshData {
+
+
+ String name;
+ struct Source {
+
+ Vector<float> array;
+ int stride;
+
+ };
+
+ Map<String,Source> sources;
+
+ struct Vertices {
+
+ Map<String,String> sources;
+ };
+
+ Map<String,Vertices> vertices;
+
+ struct Primitives {
+
+ struct SourceRef {
+
+ String source;
+ int offset;
+
+
+ };
+
+ String material;
+ Map<String,SourceRef> sources;
+ Vector<float> polygons;
+ Vector<float> indices;
+ int count;
+ int vertex_size;
+ };
+
+ Vector<Primitives> primitives;
+
+ bool found_double_sided;
+ bool double_sided;
+
+ MeshData() { found_double_sided=false; double_sided=true; }
+ };
+
+ struct CurveData {
+
+
+ String name;
+ bool closed;
+
+ struct Source {
+
+ Vector<String> sarray;
+ Vector<float> array;
+ int stride;
+ };
+
+ Map<String,Source> sources;
+
+
+ Map<String,String> control_vertices;
+
+ CurveData() {
+
+ closed=false;
+ }
+
+ };
+ struct SkinControllerData {
+
+ String base;
+ bool use_idrefs;
+
+ Transform bind_shape;
+
+ struct Source {
+
+ Vector<String> sarray; //maybe for names
+ Vector<float> array;
+ int stride;
+ Source() {
+ stride=1;
+ }
+ };
+
+ Map<String,Source> sources;
+
+ struct Joints {
+
+ Map<String,String> sources;
+ } joints;
+
+ struct Weights {
+
+ struct SourceRef {
+
+ String source;
+ int offset;
+
+
+ };
+
+ String material;
+ Map<String,SourceRef> sources;
+ Vector<float> sets;
+ Vector<float> indices;
+ int count;
+ } weights;
+
+ Map<String,Transform> bone_rest_map;
+
+ SkinControllerData() { use_idrefs=false; }
+ };
+
+
+ struct MorphControllerData {
+
+ String mesh;
+ String mode;
+
+ struct Source {
+
+ int stride;
+ Vector<String> sarray; //maybe for names
+ Vector<float> array;
+ Source() { stride=1; }
+ };
+
+ Map<String,Source> sources;
+
+ Map<String,String> targets;
+ MorphControllerData() { }
+ };
+
+
+ struct Vertex {
+
+ int idx;
+ Vector3 vertex;
+ Vector3 normal;
+ Vector3 uv;
+ Vector3 uv2;
+ Plane tangent;
+ Color color;
+ int uid;
+ struct Weight {
+ int bone_idx;
+ float weight;
+ bool operator<(const Weight w) const { return weight>w.weight; } //heaviest first
+
+ };
+
+ Vector<Weight> weights;
+
+ void fix_weights() {
+
+ weights.sort();
+ if (weights.size()>4) {
+ //cap to 4 and make weights add up 1
+ weights.resize(4);
+ float total=0;
+ for(int i=0;i<4;i++)
+ total+=weights[i].weight;
+ if (total)
+ for(int i=0;i<4;i++)
+ weights[i].weight/=total;
+
+ }
+ }
+
+ void fix_unit_scale(Collada &state);
+
+ bool operator<(const Vertex& p_vert) const {
+
+ if (uid==p_vert.uid) {
+ if (vertex==p_vert.vertex) {
+ if(normal==p_vert.normal) {
+ if(uv==p_vert.uv) {
+ if(uv2==p_vert.uv2) {
+
+ if (!weights.empty() || !p_vert.weights.empty()) {
+
+ if (weights.size()==p_vert.weights.size()) {
+
+ for(int i=0;i<weights.size();i++) {
+ if (weights[i].bone_idx!=p_vert.weights[i].bone_idx)
+ return weights[i].bone_idx<p_vert.weights[i].bone_idx;
+
+ if (weights[i].weight!=p_vert.weights[i].weight)
+ return weights[i].weight<p_vert.weights[i].weight;
+ }
+ } else {
+ return weights.size() < p_vert.weights.size();
+ }
+
+ }
+
+ return (color<p_vert.color);
+ } else
+ return (uv2<p_vert.uv2);
+ } else
+ return (uv<p_vert.uv);
+ } else
+ return (normal<p_vert.normal);
+ } else
+ return vertex<p_vert.vertex;
+ } else
+ return uid < p_vert.uid;
+
+ }
+
+ Vertex() { uid=0; idx=0; }
+ };
+ struct Node {
+
+ enum Type {
+
+ TYPE_NODE,
+ TYPE_JOINT,
+ TYPE_SKELETON, //this bone is not collada, it's added afterwards as optimization
+ TYPE_LIGHT,
+ TYPE_CAMERA,
+ TYPE_GEOMETRY
+ };
+
+
+ struct XForm {
+
+ enum Op {
+ OP_ROTATE,
+ OP_SCALE,
+ OP_TRANSLATE,
+ OP_MATRIX,
+ OP_VISIBILITY
+ };
+
+ String id;
+ Op op;
+ Vector<float> data;
+ };
+
+ Type type;
+
+ String name;
+ String id;
+ String empty_draw_type;
+ bool noname;
+ Vector<XForm> xform_list;
+ Transform default_transform;
+ Transform post_transform;
+ Vector<Node*> children;
+
+ Node* parent;
+
+ Transform compute_transform(Collada &state) const;
+ Transform get_global_transform() const;
+ Transform get_transform() const;
+
+ bool ignore_anim;
+
+
+ Node() {noname=false; type=TYPE_NODE; parent=NULL; ignore_anim=false; }
+ virtual ~Node() { for(int i=0;i<children.size();i++) memdelete( children[i] ); };
+
+ };
+
+ struct NodeSkeleton : public Node {
+
+
+ NodeSkeleton() { type=TYPE_SKELETON; }
+ };
+
+ struct NodeJoint : public Node {
+
+ NodeSkeleton *owner;
+ String sid;
+ NodeJoint() { type=TYPE_JOINT; owner=NULL; }
+ };
+
+
+ struct NodeGeometry : public Node {
+
+ bool controller;
+ String source;
+
+ struct Material {
+ String target;
+ };
+
+ Map<String,Material> material_map;
+ Vector<String> skeletons;
+
+ NodeGeometry() { type=TYPE_GEOMETRY; }
+ };
+
+ struct NodeCamera : public Node {
+
+ String camera;
+
+ NodeCamera() { type=TYPE_CAMERA; }
+ };
+
+ struct NodeLight : public Node {
+
+ String light;
+
+ NodeLight() { type=TYPE_LIGHT; }
+ };
+
+
+ struct VisualScene {
+
+ String name;
+ Vector<Node*> root_nodes;
+
+ ~VisualScene() { for(int i=0;i<root_nodes.size();i++) memdelete( root_nodes[i] ); }
+ };
+
+
+ struct AnimationClip {
+
+ String name;
+ float begin;
+ float end;
+ Vector<String> tracks;
+
+ AnimationClip() { begin=0; end=1; }
+ };
+
+ struct AnimationTrack {
+
+ String id;
+ String target;
+ String param;
+ String component;
+ bool property;
+
+ enum InterpolationType {
+ INTERP_LINEAR,
+ INTERP_BEZIER
+ };
+
+ struct Key {
+
+ enum Type {
+ TYPE_FLOAT,
+ TYPE_MATRIX
+ };
+
+ float time;
+ Vector<float> data;
+ Point2 in_tangent;
+ Point2 out_tangent;
+ InterpolationType interp_type;
+
+ Key() { interp_type=INTERP_LINEAR; }
+ };
+
+
+ Vector<float> get_value_at_time(float p_time);
+
+ Vector<Key> keys;
+
+ AnimationTrack() { property=false; }
+ };
+
+
+ /****************/
+ /* IMPORT STATE */
+ /****************/
+
+
+ struct State {
+
+
+ int import_flags;
+
+ float unit_scale;
+ Vector3::Axis up_axis;
+ bool z_up;
+
+ struct Version {
+
+ int major,minor,rev;
+
+ bool operator<(const Version& p_ver) const { return (major==p_ver.major)?((minor==p_ver.minor)?(rev<p_ver.rev):minor<p_ver.minor):major<p_ver.major; }
+ Version(int p_major=0,int p_minor=0,int p_rev=0) { major=p_major; minor=p_minor; rev=p_rev; }
+ } version;
+
+
+ Map<String,CameraData> camera_data_map;
+ Map<String,MeshData> mesh_data_map;
+ Map<String,LightData> light_data_map;
+ Map<String,CurveData> curve_data_map;
+
+
+ Map<String,String> mesh_name_map;
+ Map<String,String> morph_name_map;
+ Map<String,String> morph_ownership_map;
+ Map<String,SkinControllerData> skin_controller_data_map;
+ Map<String,MorphControllerData> morph_controller_data_map;
+
+
+
+ Map<String,Image > image_map;
+ Map<String,Material> material_map;
+ Map<String,Effect> effect_map;
+
+ Map<String,VisualScene> visual_scene_map;
+ Map<String,Node*> scene_map;
+ Set<String> idref_joints;
+ Map<String,String> sid_to_node_map;
+ //Map<String,NodeJoint*> bone_map;
+
+ Map<String,Transform> bone_rest_map;
+
+ String local_path;
+ String root_visual_scene;
+ String root_physics_scene;
+
+ Vector<AnimationClip> animation_clips;
+ Vector<AnimationTrack> animation_tracks;
+ Map<String,Vector<int> > referenced_tracks;
+ Map<String,Vector<int> > by_id_tracks;
+
+ float animation_length;
+
+ State() { unit_scale=1.0; up_axis=Vector3::AXIS_Y; import_flags=0; animation_length=0; }
+ } state;
+
+
+ Error load(const String& p_path, int p_flags=0);
+
+ Collada();
+
+ Transform fix_transform(const Transform& p_transform);
+
+ Transform get_root_transform() const;
+
+ int get_uv_channel(String p_name);
+
+private: // private stuff
+
+ Map<String,int> channel_map;
+
+ void _parse_asset(XMLParser& parser);
+ void _parse_image(XMLParser& parser);
+ void _parse_material(XMLParser& parser);
+ void _parse_effect_material(XMLParser& parser,Effect &effect,String &id);
+ void _parse_effect(XMLParser& parser);
+ void _parse_camera(XMLParser& parser);
+ void _parse_light(XMLParser& parser);
+ void _parse_animation_clip(XMLParser& parser);
+
+ void _parse_mesh_geometry(XMLParser& parser,String p_id,String p_name);
+ void _parse_curve_geometry(XMLParser& parser,String p_id,String p_name);
+
+ void _parse_skin_controller(XMLParser& parser,String p_id);
+ void _parse_morph_controller(XMLParser& parser, String id);
+ void _parse_controller(XMLParser& parser);
+
+ Node* _parse_visual_instance_geometry(XMLParser& parser);
+ Node* _parse_visual_instance_camera(XMLParser& parser);
+ Node* _parse_visual_instance_light(XMLParser& parser);
+
+ Node* _parse_visual_node_instance_data(XMLParser& parser);
+ Node* _parse_visual_scene_node(XMLParser& parser);
+ void _parse_visual_scene(XMLParser& parser);
+
+ void _parse_animation(XMLParser& parser);
+ void _parse_scene(XMLParser& parser);
+ void _parse_library(XMLParser& parser);
+
+
+ Variant _parse_param(XMLParser& parser);
+ Vector<float> _read_float_array(XMLParser& parser);
+ Vector<String> _read_string_array(XMLParser& parser);
+ Transform _read_transform(XMLParser& parser);
+ String _read_empty_draw_type(XMLParser& parser);
+
+ void _joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner);
+ void _create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton=NULL);
+ void _find_morph_nodes(VisualScene *p_vscene,Node *p_node);
+ bool _remove_node(Node *p_parent,Node *p_node);
+ void _remove_node(VisualScene *p_vscene,Node *p_node);
+ void _merge_skeletons2(VisualScene *p_vscene);
+ void _merge_skeletons(VisualScene *p_vscene,Node *p_node);
+ bool _optimize_skeletons(VisualScene *p_vscene,Node *p_node);
+
+
+ bool _move_geometry_to_skeletons(VisualScene *p_vscene,Node *p_node,List<Node*> *p_mgeom);
+
+
+
+ void _optimize();
+
+
+};
+
+#endif // COLLADA_H
+
+#endif
diff --git a/tools/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 91ba419c97..91ba419c97 100644
--- a/tools/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
new file mode 100644
index 0000000000..6407b83f6e
--- /dev/null
+++ b/editor/connections_dialog.h
@@ -0,0 +1,134 @@
+/*************************************************************************/
+/* connections_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 CONNECTIONS_DIALOG_H
+#define CONNECTIONS_DIALOG_H
+
+#include "scene/gui/popup.h"
+#include "scene/gui/button.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/line_edit.h"
+#include "editor/scene_tree_editor.h"
+#include "editor/property_editor.h"
+#include "undo_redo.h"
+
+/**
+@author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class ConnectDialogBinds;
+
+class ConnectDialog : public ConfirmationDialog {
+
+ GDCLASS( ConnectDialog, ConfirmationDialog );
+
+
+ ConfirmationDialog *error;
+ LineEdit *dst_path;
+ LineEdit *dst_method;
+ SceneTreeEditor *tree;
+ //MenuButton *dst_method_list;
+ OptionButton *type_list;
+ CheckButton *deferred;
+ CheckButton *oneshot;
+ CheckButton *make_callback;
+ PropertyEditor *bind_editor;
+ Node *node;
+ ConnectDialogBinds *cdbinds;
+ void ok_pressed();
+ void _cancel_pressed();
+ void _tree_node_selected();
+ void _dst_method_list_selected(int p_idx);
+ void _add_bind();
+ void _remove_bind();
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+
+ bool get_make_callback() { return make_callback->is_visible() && make_callback->is_pressed(); }
+ NodePath get_dst_path() const;
+ StringName get_dst_method() const;
+ bool get_deferred() const;
+ bool get_oneshot() const;
+ Vector<Variant> get_binds() const;
+ void set_dst_method(const StringName& p_method);
+ void set_dst_node(Node* p_node);
+
+ //Button *get_ok() { return ok; }
+ //Button *get_cancel() { return cancel; }
+ void edit(Node *p_node);
+
+ ConnectDialog();
+ ~ConnectDialog();
+
+};
+
+class ConnectionsDock : public VBoxContainer {
+
+ GDCLASS( ConnectionsDock , VBoxContainer );
+
+ Button *connect_button;
+ EditorNode *editor;
+ Node *node;
+ Tree *tree;
+ ConfirmationDialog *remove_confirm;
+ ConnectDialog *connect_dialog;
+
+ void update_tree();
+
+ void _close();
+ void _connect();
+ void _something_selected();
+ void _something_activated();
+ UndoRedo *undo_redo;
+
+protected:
+
+ void _connect_pressed();
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_undoredo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
+
+ void set_node(Node* p_node);
+ String get_selected_type();
+
+ ConnectionsDock(EditorNode *p_editor=NULL);
+ ~ConnectionsDock();
+
+};
+
+#endif
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
new file mode 100644
index 0000000000..58bb148ce1
--- /dev/null
+++ b/editor/create_dialog.cpp
@@ -0,0 +1,961 @@
+/*************************************************************************/
+/* create_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "create_dialog.h"
+
+#include "class_db.h"
+#include "print_string.h"
+#include "scene/gui/box_container.h"
+#include "editor_node.h"
+
+#if 1
+
+#include "os/keyboard.h"
+#include "editor_settings.h"
+#include "editor_help.h"
+
+
+void CreateDialog::popup(bool p_dontclear) {
+
+ recent->clear();
+
+ FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent."+base_type), FileAccess::READ );
+
+ if (f) {
+
+ TreeItem *root = recent->create_item();
+
+ while(!f->eof_reached()) {
+ String l = f->get_line().strip_edges();
+
+ if (l!=String()) {
+
+ TreeItem *ti = recent->create_item(root);
+ ti->set_text(0,l);
+ if (has_icon(l,"EditorIcons")) {
+
+ ti->set_icon(0,get_icon(l,"EditorIcons"));
+ } else {
+ ti->set_icon(0,get_icon("Object","EditorIcons"));
+ }
+ }
+ }
+
+ memdelete(f);
+ }
+
+ favorites->clear();
+
+ f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites."+base_type), FileAccess::READ );
+
+ favorite_list.clear();
+
+ if (f) {
+
+
+ while(!f->eof_reached()) {
+ String l = f->get_line().strip_edges();
+
+ if (l!=String()) {
+ favorite_list.push_back(l);
+ }
+ }
+
+ memdelete(f);
+ } else {
+#if 0
+// I think this was way too confusing
+ if (base_type=="Node") {
+ //harcode some favorites :D
+ favorite_list.push_back("Panel");
+ favorite_list.push_back("Button");
+ favorite_list.push_back("Label");
+ favorite_list.push_back("LineEdit");
+ favorite_list.push_back("Node2D");
+ favorite_list.push_back("Sprite");
+ favorite_list.push_back("Camera2D");
+ favorite_list.push_back("Area2D");
+ favorite_list.push_back("CollisionShape2D");
+ favorite_list.push_back("Spatial");
+ favorite_list.push_back("Camera");
+ favorite_list.push_back("Area");
+ favorite_list.push_back("CollisionShape");
+ favorite_list.push_back("TestCube");
+ favorite_list.push_back("AnimationPlayer");
+
+ }
+#endif
+ }
+
+ _update_favorite_list();
+
+ popup_centered_ratio();
+ if (p_dontclear)
+ search_box->select_all();
+ else {
+ search_box->clear();
+ }
+ search_box->grab_focus();
+
+ _update_search();
+
+
+}
+
+
+void CreateDialog::_text_changed(const String& p_newtext) {
+
+ _update_search();
+}
+
+void CreateDialog::_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 ) ) {
+
+ search_options->call("_gui_input",p_ie);
+ search_box->accept_event();
+ }
+
+}
+
+void CreateDialog::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root,TreeItem **to_select) {
+
+ if (p_types.has(p_type))
+ return;
+ if (!ClassDB::is_parent_class(p_type,base_type) || p_type==base_type)
+ return;
+
+ String inherits=ClassDB::get_parent_class(p_type);
+
+ TreeItem *parent=p_root;
+
+
+ if (inherits.length()) {
+
+ if (!p_types.has(inherits)) {
+
+ add_type(inherits,p_types,p_root,to_select);
+ }
+
+ if (p_types.has(inherits) )
+ parent=p_types[inherits];
+ }
+
+ TreeItem *item = search_options->create_item(parent);
+ item->set_text(0,p_type);
+ if (!ClassDB::can_instance(p_type)) {
+ item->set_custom_color(0, Color(0.5,0.5,0.5) );
+ item->set_selectable(0,false);
+ } else {
+
+ if ((!*to_select && (search_box->get_text().is_subsequence_ofi(p_type))) || search_box->get_text()==p_type) {
+ *to_select=item;
+ }
+
+ }
+
+ if (bool(EditorSettings::get_singleton()->get("docks/scene_tree/start_create_dialog_fully_expanded"))) {
+ item->set_collapsed(false);
+ } else {
+ // don't collapse search results
+ bool collapse = (search_box->get_text() == "");
+ // don't collapse the root node
+ collapse &= (item != p_root);
+ // don't collapse abstract nodes on the first tree level
+ collapse &= ((parent != p_root) || (ClassDB::can_instance(p_type)));
+ item->set_collapsed(collapse);
+ }
+
+ const String& description = EditorHelp::get_doc_data()->class_list[p_type].brief_description;
+ item->set_tooltip(0,description);
+
+
+ if (has_icon(p_type,"EditorIcons")) {
+
+ item->set_icon(0, get_icon(p_type,"EditorIcons"));
+ }
+
+
+
+ p_types[p_type]=item;
+}
+
+void CreateDialog::_update_search() {
+
+
+ search_options->clear();
+ favorite->set_disabled(true);
+
+ help_bit->set_text("");
+ /*
+ TreeItem *root = search_options->create_item();
+ _parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
+*/
+
+ List<StringName> type_list;
+ ClassDB::get_class_list(&type_list);
+
+ HashMap<String,TreeItem*> types;
+
+ TreeItem *root = search_options->create_item();
+
+ root->set_text(0,base_type);
+ if (has_icon(base_type,"EditorIcons")) {
+ root->set_icon(0,get_icon(base_type,"EditorIcons"));
+ }
+
+ List<StringName>::Element *I=type_list.front();
+ TreeItem *to_select=NULL;
+
+ for(;I;I=I->next()) {
+
+
+
+ String type=I->get();
+
+ if (base_type=="Node" && type.begins_with("Editor"))
+ continue; // do not show editor nodes
+
+ if (!ClassDB::can_instance(type))
+ continue; // cant create what can't be instanced
+
+ if (search_box->get_text()=="") {
+ add_type(type,types,root,&to_select);
+ } else {
+
+ bool found=false;
+ String type=I->get();
+ while(type!="" && ClassDB::is_parent_class(type,base_type) && type!=base_type) {
+ if (search_box->get_text().is_subsequence_ofi(type)) {
+
+ found=true;
+ break;
+ }
+
+ type=ClassDB::get_parent_class(type);
+ }
+
+
+ if (found)
+ add_type(I->get(),types,root,&to_select);
+ }
+
+ if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) {
+ //there are custom types based on this... cool.
+ //print_line("there are custom types");
+
+
+ const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[type];
+ for(int i=0;i<ct.size();i++) {
+
+ bool show = search_box->get_text().is_subsequence_ofi(ct[i].name);
+
+ if (!show)
+ continue;
+
+ if (!types.has(type))
+ add_type(type,types,root,&to_select);
+
+ TreeItem *ti;
+ if (types.has(type) )
+ ti=types[type];
+ else
+ ti=search_options->get_root();
+
+
+ TreeItem *item = search_options->create_item(ti);
+ item->set_metadata(0,type);
+ item->set_text(0,ct[i].name);
+ if (ct[i].icon.is_valid()) {
+ item->set_icon(0,ct[i].icon);
+
+ }
+
+ if (!to_select || ct[i].name==search_box->get_text()) {
+ to_select=item;
+ }
+
+ }
+
+ }
+ }
+
+ if (to_select) {
+ to_select->select(0);
+ favorite->set_disabled(false);
+ favorite->set_pressed(favorite_list.find(to_select->get_text(0))!=-1);
+ }
+
+ get_ok()->set_disabled(root->get_children()==NULL);
+
+}
+
+void CreateDialog::_confirmed() {
+
+ TreeItem *ti = search_options->get_selected();
+ if (!ti)
+ return;
+
+ FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent."+base_type), FileAccess::WRITE );
+
+ if (f) {
+ f->store_line(get_selected_type());
+ TreeItem *t = recent->get_root();
+ if (t)
+ t=t->get_children();
+ int count=0;
+ while(t) {
+ if (t->get_text(0)!=get_selected_type()) {
+
+ f->store_line(t->get_text(0));
+ }
+
+ if (count>32) {
+ //limit it to 32 entries..
+ break;
+ }
+ t=t->get_next();
+ count++;
+ }
+
+ memdelete(f);
+ }
+
+ emit_signal("create");
+ hide();
+}
+
+void CreateDialog::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ connect("confirmed",this,"_confirmed");
+ favorite->set_icon(get_icon("Favorites","EditorIcons"));
+ }
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ disconnect("confirmed",this,"_confirmed");
+
+ }
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ if (is_visible_in_tree()) {
+
+ search_box->call_deferred("grab_focus"); // still not visible
+ search_box->select_all();
+ }
+ }
+
+}
+
+void CreateDialog::set_base_type(const String& p_base) {
+
+ base_type=p_base;
+ set_title(TTR("Create New")+" "+p_base);
+ _update_search();
+}
+
+String CreateDialog::get_selected_type() {
+
+ TreeItem *selected = search_options->get_selected();
+ if (selected)
+ return selected->get_text(0);
+ else
+ return String();
+}
+
+Object *CreateDialog::instance_selected() {
+
+ TreeItem *selected = search_options->get_selected();
+
+ if (selected) {
+
+ Variant md = selected->get_metadata(0);
+
+ String custom;
+ if (md.get_type()!=Variant::NIL)
+ custom=md;
+
+ if (custom!=String()) {
+ if (EditorNode::get_editor_data().get_custom_types().has(custom)) {
+
+ for(int i=0;i<EditorNode::get_editor_data().get_custom_types()[custom].size();i++) {
+ if (EditorNode::get_editor_data().get_custom_types()[custom][i].name==selected->get_text(0)) {
+ Ref<Texture> icon = EditorNode::get_editor_data().get_custom_types()[custom][i].icon;
+ Ref<Script> script = EditorNode::get_editor_data().get_custom_types()[custom][i].script;
+ String name = selected->get_text(0);
+
+ Object *ob = ClassDB::instance(custom);
+ ERR_FAIL_COND_V(!ob,NULL);
+ if (ob->is_class("Node")) {
+ ob->call("set_name",name);
+ }
+ ob->set_script(script.get_ref_ptr());
+ if (icon.is_valid())
+ ob->set_meta("_editor_icon",icon);
+ return ob;
+
+ }
+ }
+
+ }
+ } else {
+ return ClassDB::instance(selected->get_text(0));
+ }
+ }
+
+
+ return NULL;
+}
+
+
+String CreateDialog::get_base_type() const {
+
+ return base_type;
+}
+
+void CreateDialog::_item_selected() {
+
+ TreeItem *item = search_options->get_selected();
+ if (!item)
+ return;
+
+ String name = item->get_text(0);
+
+ favorite->set_disabled(false);
+ favorite->set_pressed(favorite_list.find(name)!=-1);
+
+ if (!EditorHelp::get_doc_data()->class_list.has(name))
+ return;
+
+ help_bit->set_text(EditorHelp::get_doc_data()->class_list[name].brief_description);
+
+}
+
+
+void CreateDialog::_favorite_toggled() {
+
+ TreeItem *item = search_options->get_selected();
+ if (!item)
+ return;
+
+ String name = item->get_text(0);
+
+ if (favorite_list.find(name)==-1) {
+ favorite_list.push_back(name);
+ favorite->set_pressed(true);
+ } else {
+ favorite_list.erase(name);
+ favorite->set_pressed(false);
+ }
+
+ _save_favorite_list();
+ _update_favorite_list();
+}
+
+void CreateDialog::_save_favorite_list() {
+
+ FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites."+base_type), FileAccess::WRITE );
+
+ if (f) {
+
+ for(int i=0;i<favorite_list.size();i++) {
+
+ f->store_line(favorite_list[i]);
+ }
+ memdelete(f);
+ }
+}
+
+void CreateDialog::_update_favorite_list() {
+
+ favorites->clear();
+ TreeItem *root = favorites->create_item();
+ for(int i=0;i<favorite_list.size();i++) {
+ TreeItem *ti = favorites->create_item(root);
+ String l = favorite_list[i];
+ ti->set_text(0,l);
+
+ if (has_icon(l,"EditorIcons")) {
+
+ ti->set_icon(0,get_icon(l,"EditorIcons"));
+ } else {
+ ti->set_icon(0,get_icon("Object","EditorIcons"));
+ }
+ }
+}
+
+
+void CreateDialog::_history_selected() {
+
+ TreeItem *item = recent->get_selected();
+ if (!item)
+ return;
+
+ search_box->set_text(item->get_text(0));
+ _update_search();
+
+}
+
+void CreateDialog::_favorite_selected(){
+
+ TreeItem *item = favorites->get_selected();
+ if (!item)
+ return;
+
+ search_box->set_text(item->get_text(0));
+ _update_search();
+
+}
+
+void CreateDialog::_history_activated() {
+
+ _confirmed();
+}
+
+void CreateDialog::_favorite_activated(){
+
+ _confirmed();
+}
+
+Variant CreateDialog::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ TreeItem *ti = favorites->get_item_at_pos(p_point);
+ if (ti) {
+ Dictionary d;
+ d["type"]="create_favorite_drag";
+ d["class"]=ti->get_text(0);
+
+ ToolButton *tb = memnew( ToolButton );
+ tb->set_icon(ti->get_icon(0));
+ tb->set_text(ti->get_text(0));
+ set_drag_preview(tb);
+
+ return d;
+ }
+
+ return Variant();
+}
+
+bool CreateDialog::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ Dictionary d = p_data;
+ if (d.has("type") && String(d["type"])=="create_favorite_drag") {
+ favorites->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+ return true;
+ }
+
+ return false;
+}
+void CreateDialog::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ Dictionary d = p_data;
+
+ TreeItem *ti = favorites->get_item_at_pos(p_point);
+ if (!ti)
+ return;
+
+ String drop_at = ti->get_text(0);
+ int ds = favorites->get_drop_section_at_pos(p_point);
+
+ int drop_idx = favorite_list.find(drop_at);
+ if (drop_idx<0)
+ return;
+
+ String type = d["class"];
+
+ int from_idx = favorite_list.find(type);
+ if (from_idx<0)
+ return;
+
+ if (drop_idx==from_idx) {
+ ds=-1; //cause it will be gone
+ } else if (drop_idx>from_idx) {
+ drop_idx--;
+ }
+
+ favorite_list.remove(from_idx);
+
+ if (ds<0) {
+ favorite_list.insert(drop_idx,type);
+ } else {
+ if (drop_idx>=favorite_list.size()-1) {
+ favorite_list.push_back(type);
+ } else {
+ favorite_list.insert(drop_idx+1,type);
+ }
+ }
+
+ _save_favorite_list();
+ _update_favorite_list();
+
+
+}
+
+void CreateDialog::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_text_changed"),&CreateDialog::_text_changed);
+ ClassDB::bind_method(D_METHOD("_confirmed"),&CreateDialog::_confirmed);
+ ClassDB::bind_method(D_METHOD("_sbox_input"),&CreateDialog::_sbox_input);
+ ClassDB::bind_method(D_METHOD("_item_selected"),&CreateDialog::_item_selected);
+ ClassDB::bind_method(D_METHOD("_favorite_toggled"),&CreateDialog::_favorite_toggled);
+ ClassDB::bind_method(D_METHOD("_history_selected"),&CreateDialog::_history_selected);
+ ClassDB::bind_method(D_METHOD("_favorite_selected"),&CreateDialog::_favorite_selected);
+ ClassDB::bind_method(D_METHOD("_history_activated"),&CreateDialog::_history_activated);
+ ClassDB::bind_method(D_METHOD("_favorite_activated"),&CreateDialog::_favorite_activated);
+
+
+ ClassDB::bind_method("get_drag_data_fw",&CreateDialog::get_drag_data_fw);
+ ClassDB::bind_method("can_drop_data_fw",&CreateDialog::can_drop_data_fw);
+ ClassDB::bind_method("drop_data_fw",&CreateDialog::drop_data_fw);
+
+ ADD_SIGNAL(MethodInfo("create"));
+
+}
+
+
+CreateDialog::CreateDialog() {
+
+ HSplitContainer *hbc = memnew( HSplitContainer );
+
+ add_child(hbc);
+
+
+ VBoxContainer *lvbc = memnew( VBoxContainer);
+ hbc->add_child(lvbc);
+ lvbc->set_custom_minimum_size(Size2(150,0)*EDSCALE);
+
+ favorites = memnew (Tree );
+ lvbc->add_margin_child(TTR("Favorites:"),favorites,true);
+ favorites->set_hide_root(true);
+ favorites->set_hide_folding(true);
+ favorites->connect("cell_selected",this,"_favorite_selected");
+ favorites->connect("item_activated",this,"_favorite_activated");
+ favorites->set_drag_forwarding(this);
+
+
+ recent = memnew (Tree );
+ lvbc->add_margin_child(TTR("Recent:"),recent,true);
+ recent->set_hide_root(true);
+ recent->set_hide_folding(true);
+ recent->connect("cell_selected",this,"_history_selected");
+ recent->connect("item_activated",this,"_history_activated");
+
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ hbc->add_child(vbc);
+ vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+ HBoxContainer *search_hb = memnew( HBoxContainer );
+ search_box = memnew( LineEdit );
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ search_hb->add_child(search_box);
+ favorite = memnew( Button );
+ favorite->set_toggle_mode(true);
+ search_hb->add_child(favorite);
+ favorite->connect("pressed",this,"_favorite_toggled");
+ vbc->add_margin_child(TTR("Search:"),search_hb);
+ search_box->connect("text_changed",this,"_text_changed");
+ search_box->connect("gui_input",this,"_sbox_input");
+ search_options = memnew( Tree );
+ vbc->add_margin_child(TTR("Matches:"),search_options,true);
+ get_ok()->set_text(TTR("Create"));
+ get_ok()->set_disabled(true);
+ register_text_enter(search_box);
+ set_hide_on_ok(false);
+ search_options->connect("item_activated",this,"_confirmed");
+ search_options->connect("cell_selected",this,"_item_selected");
+ //search_options->set_hide_root(true);
+ base_type="Object";
+
+ help_bit = memnew( EditorHelpBit );
+ vbc->add_margin_child(TTR("Description:"),help_bit);
+ help_bit->connect("request_hide",this,"_closed");
+
+}
+
+
+#else
+
+//old create dialog, disabled
+
+void CreateDialog::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+ connect("confirmed",this,"_create");
+ update_tree();
+ }
+ if (p_what==NOTIFICATION_DRAW) {
+
+ //RID ci = get_canvas_item();
+ //get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
+ }
+}
+
+
+void CreateDialog::_create() {
+
+ if (tree->get_selected())
+ emit_signal("create");
+ hide();
+}
+
+void CreateDialog::_cancel() {
+
+ hide();
+}
+
+void CreateDialog::_text_changed(String p_text) {
+
+ update_tree();
+}
+
+void CreateDialog::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root) {
+
+ if (p_types.has(p_type))
+ return;
+ if (!ClassDB::is_type(p_type,base) || p_type==base)
+ return;
+
+ String inherits=ClassDB::type_inherits_from(p_type);
+
+ TreeItem *parent=p_root;
+
+
+ if (inherits.length()) {
+
+ if (!p_types.has(inherits)) {
+
+ add_type(inherits,p_types,p_root);
+ }
+
+ if (p_types.has(inherits) )
+ parent=p_types[inherits];
+ }
+
+ TreeItem *item = tree->create_item(parent);
+ item->set_text(0,p_type);
+ if (!ClassDB::can_instance(p_type)) {
+ item->set_custom_color(0, Color(0.5,0.5,0.5) );
+ item->set_selectable(0,false);
+ }
+
+
+ if (has_icon(p_type,"EditorIcons")) {
+
+ item->set_icon(0, get_icon(p_type,"EditorIcons"));
+ }
+
+
+
+ p_types[p_type]=item;
+}
+
+void CreateDialog::update_tree() {
+
+ tree->clear();
+
+ List<String> type_list;
+ ClassDB::get_type_list(&type_list);
+
+ HashMap<String,TreeItem*> types;
+
+ TreeItem *root = tree->create_item();
+
+ root->set_text(0,base);
+
+ List<String>::Element *I=type_list.front();
+
+ for(;I;I=I->next()) {
+
+
+ String type=I->get();
+
+
+ if (!ClassDB::can_instance(type))
+ continue; // cant create what can't be instanced
+ if (filter->get_text()=="")
+ add_type(type,types,root);
+ else {
+
+ bool found=false;
+ String type=I->get();
+ while(type!="" && ClassDB::is_type(type,base) && type!=base) {
+ if (type.findn(filter->get_text())!=-1) {
+
+ found=true;
+ break;
+ }
+
+ type=ClassDB::type_inherits_from(type);
+ }
+
+
+ if (found)
+ add_type(I->get(),types,root);
+ }
+
+ if (EditorNode::get_editor_data().get_custom_types().has(type)) {
+ //there are custom types based on this... cool.
+
+
+ const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[type];
+ for(int i=0;i<ct.size();i++) {
+
+ bool show = filter->get_text()=="" || ct[i].name.findn(filter->get_text())!=-1;
+
+ if (!show)
+ continue;
+ if (!types.has(type))
+ add_type(type,types,root);
+
+ TreeItem *ti;
+ if (types.has(type) )
+ ti=types[type];
+ else
+ ti=tree->get_root();
+
+
+ TreeItem *item = tree->create_item(ti);
+ item->set_metadata(0,type);
+ item->set_text(0,ct[i].name);
+ if (ct[i].icon.is_valid()) {
+ item->set_icon(0,ct[i].icon);
+
+ }
+ }
+
+ }
+ }
+
+
+}
+
+
+Object *CreateDialog::instance_selected() {
+
+ if (!tree->get_selected())
+ return NULL;
+
+ String base = String(tree->get_selected()->get_metadata(0));
+ if (base!="") {
+
+
+ String name = tree->get_selected()->get_text(0);
+ if (EditorNode::get_editor_data().get_custom_types().has(base)) {
+
+ const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[base];
+ for(int i=0;i<ct.size();i++) {
+
+ if (ct[i].name==name) {
+
+ Object* obj = ClassDB::instance(base);
+ ERR_FAIL_COND_V(!obj,NULL);
+ obj->set_script(ct[i].script.get_ref_ptr());
+ if (ct[i].icon.is_valid())
+ obj->set_meta("_editor_icon",ct[i].icon);
+ return obj;
+
+
+ }
+ }
+ }
+
+ ERR_FAIL_V(NULL);
+
+ }
+
+ return ClassDB::instance(tree->get_selected()->get_text(0));
+
+}
+
+
+void CreateDialog::_bind_methods() {
+
+ ClassDB::bind_method("_create",&CreateDialog::_create);
+ ClassDB::bind_method("_cancel",&CreateDialog::_cancel);
+ ClassDB::bind_method("_text_changed", &CreateDialog::_text_changed);
+ ADD_SIGNAL( MethodInfo("create"));
+
+}
+
+
+
+
+void CreateDialog::set_base_type(const String& p_base) {
+
+ set_title(vformat("Create %s Type",p_base));
+
+ if (base==p_base)
+ return;
+ base=p_base;
+ if (is_inside_scene())
+ update_tree();
+}
+
+String CreateDialog::get_base_type() const {
+
+ return base;
+}
+
+CreateDialog::CreateDialog() {
+
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+
+
+ get_ok()->set_text("Create");
+
+ tree = memnew( Tree );
+ vbc->add_margin_child("Type:",tree,true);
+ //tree->set_hide_root(true);
+
+ filter = memnew( LineEdit );
+ vbc->add_margin_child("Filter:",filter);
+
+ base="Node";
+ set_as_toplevel(true);
+
+
+ tree->connect("item_activated", this, "_create");
+ filter->connect("text_changed", this,"_text_changed");
+
+}
+
+
+CreateDialog::~CreateDialog()
+{
+}
+
+
+#endif
diff --git a/tools/editor/create_dialog.h b/editor/create_dialog.h
index 5ecb4db2c3..5ecb4db2c3 100644
--- a/tools/editor/create_dialog.h
+++ b/editor/create_dialog.h
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
new file mode 100644
index 0000000000..d7e04db86e
--- /dev/null
+++ b/editor/dependency_editor.cpp
@@ -0,0 +1,725 @@
+/*************************************************************************/
+/* dependency_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "dependency_editor.h"
+
+#include "os/file_access.h"
+#include "scene/gui/margin_container.h"
+#include "io/resource_loader.h"
+#include "editor_node.h"
+
+void DependencyEditor::_notification(int p_what){
+
+
+}
+
+void DependencyEditor::_searched(const String& p_path) {
+
+ Map<String,String> dep_rename;
+ dep_rename[replacing]=p_path;
+
+
+ ResourceLoader::rename_dependencies(editing,dep_rename);
+
+ _update_list();
+ _update_file();
+}
+
+void DependencyEditor::_load_pressed(Object* p_item,int p_cell,int p_button){
+
+ TreeItem *ti=p_item->cast_to<TreeItem>();
+ String fname = ti->get_text(0);
+ replacing = ti->get_text(1);
+
+ search->set_title(TTR("Search Replacement For:")+" "+replacing.get_file());
+
+ search->clear_filters();
+ List<String> ext;
+ ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0),&ext);
+ for (List<String>::Element *E=ext.front();E;E=E->next()) {
+ search->add_filter("*"+E->get());
+ }
+ search->popup_centered_ratio();
+
+}
+
+void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates){
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _fix_and_find(efsd->get_subdir(i),candidates);
+ }
+
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ String file = efsd->get_file(i);
+ if (!candidates.has(file))
+ continue;
+
+ String path = efsd->get_file_path(i);
+
+ for(Map<String,String>::Element *E=candidates[file].front();E;E=E->next()) {
+
+ if (E->get()==String()) {
+ E->get()=path;
+ continue;
+ }
+
+ //must match the best, using subdirs
+ String existing=E->get().replace_first("res://","");
+ String current=path.replace_first("res://","");
+ String lost=E->key().replace_first("res://","");
+
+ Vector<String> existingv=existing.split("/");
+ existingv.invert();
+ Vector<String> currentv=current.split("/");
+ currentv.invert();
+ Vector<String> lostv=lost.split("/");
+ lostv.invert();
+
+ int existing_score=0;
+ int current_score=0;
+
+ for(int j=0;j<lostv.size();j++) {
+
+ if (j<existingv.size() && lostv[j]==existingv[j]) {
+ existing_score++;
+ }
+ if (j<currentv.size() && lostv[j]==currentv[j]) {
+ current_score++;
+ }
+ }
+
+ if (current_score > existing_score) {
+
+ //if it was the same, could track distance to new path but..
+
+ E->get()=path; //replace by more accurate
+ }
+
+ }
+
+ }
+
+}
+
+
+void DependencyEditor::_fix_all(){
+
+ if (!EditorFileSystem::get_singleton()->get_filesystem())
+ return;
+
+ Map<String,Map<String,String> > candidates;
+
+ for (List<String>::Element *E=missing.front();E;E=E->next()) {
+
+ String base = E->get().get_file();
+ if (!candidates.has(base)) {
+ candidates[base]=Map<String,String>();
+ }
+
+ candidates[base][E->get()]="";
+ }
+
+ _fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(),candidates);
+
+ Map<String,String> remaps;
+
+ for (Map<String,Map<String,String> >::Element *E=candidates.front();E;E=E->next()) {
+
+ for (Map<String,String>::Element *F=E->get().front();F;F=F->next()) {
+
+ if (F->get()!=String()) {
+ remaps[F->key()]=F->get();
+ }
+ }
+
+ }
+
+ if (remaps.size()) {
+
+ ResourceLoader::rename_dependencies(editing,remaps);
+
+ _update_list();
+ _update_file();
+ }
+}
+
+void DependencyEditor::_update_file() {
+
+ EditorFileSystem::get_singleton()->update_file(editing);
+
+}
+
+void DependencyEditor::_update_list() {
+
+ List<String> deps;
+ ResourceLoader::get_dependencies(editing,&deps,true);
+
+ tree->clear();
+ missing.clear();
+
+ TreeItem *root = tree->create_item();
+
+ Ref<Texture> folder = get_icon("folder","FileDialog");
+
+ bool broken=false;
+
+ for(List<String>::Element *E=deps.front();E;E=E->next()) {
+
+ TreeItem *item = tree->create_item(root);
+
+ String n = E->get();
+ String path;
+ String type;
+
+ if (n.find("::")!=-1) {
+ path = n.get_slice("::",0);
+ type = n.get_slice("::",1);
+ } else {
+ path=n;
+ type="Resource";
+ }
+ String name = path.get_file();
+
+ Ref<Texture> icon;
+ if (has_icon(type,"EditorIcons")) {
+ icon=get_icon(type,"EditorIcons");
+ } else {
+ icon=get_icon("Object","EditorIcons");
+ }
+ item->set_text(0,name);
+ item->set_icon(0,icon);
+ item->set_metadata(0,type);
+ item->set_text(1,path);
+
+ if (!FileAccess::exists(path)) {
+ item->set_custom_color(1,Color(1,0.4,0.3));
+ missing.push_back(path);
+ broken=true;
+ }
+
+ item->add_button(1,folder,0);
+ }
+
+ fixdeps->set_disabled(!broken);
+
+}
+
+
+
+void DependencyEditor::edit(const String& p_path) {
+
+
+ editing=p_path;
+ set_title(TTR("Dependencies For:")+" "+p_path.get_file());
+
+ _update_list();
+ popup_centered_ratio();
+
+ if (EditorNode::get_singleton()->is_scene_open(p_path)) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Scene '%s' is currently being edited.\nChanges will not take effect unless reloaded."),p_path.get_file()));
+ } else if (ResourceCache::has(p_path)) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Resource '%s' is in use.\nChanges will take effect when reloaded."),p_path.get_file()));
+ }
+}
+
+
+void DependencyEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_searched"),&DependencyEditor::_searched);
+ ClassDB::bind_method(D_METHOD("_load_pressed"),&DependencyEditor::_load_pressed);
+ ClassDB::bind_method(D_METHOD("_fix_all"),&DependencyEditor::_fix_all);
+
+}
+
+DependencyEditor::DependencyEditor() {
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ vb->set_name(TTR("Dependencies"));
+ add_child(vb);
+
+
+ tree = memnew( Tree );
+ tree->set_columns(2);
+ tree->set_column_titles_visible(true);
+ tree->set_column_title(0,TTR("Resource"));
+ tree->set_column_title(1,TTR("Path"));
+ tree->set_hide_root(true);
+ tree->connect("button_pressed",this,"_load_pressed");
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ Label *label = memnew( Label(TTR("Dependencies:")));
+ hbc->add_child(label);
+ hbc->add_spacer();
+ fixdeps = memnew( Button(TTR("Fix Broken")));
+ hbc->add_child(fixdeps);
+ fixdeps->connect("pressed",this,"_fix_all");
+
+ vb->add_child(hbc);
+
+ MarginContainer *mc = memnew( MarginContainer );
+ mc->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ mc->add_child(tree);
+ vb->add_child(mc);
+
+ set_title(TTR("Dependency Editor"));
+ search = memnew( EditorFileDialog );
+ search->connect("file_selected",this,"_searched");
+ search->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ search->set_title(TTR("Search Replacement Resource:"));
+ add_child(search);
+
+}
+
+/////////////////////////////////////
+
+
+
+void DependencyEditorOwners::_fill_owners(EditorFileSystemDirectory *efsd) {
+
+ if (!efsd)
+ return;
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _fill_owners(efsd->get_subdir(i));
+ }
+
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ Vector<String> deps = efsd->get_file_deps(i);
+ //print_line(":::"+efsd->get_file_path(i));
+ bool found=false;
+ for(int j=0;j<deps.size();j++) {
+ //print_line("\t"+deps[j]+" vs "+editing);
+ if (deps[j]==editing) {
+ //print_line("found");
+ found=true;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+
+ Ref<Texture> icon;
+ String type=efsd->get_file_type(i);
+ if (!has_icon(type,"EditorIcons")) {
+ icon=get_icon("Object","EditorIcons");
+ } else {
+ icon=get_icon(type,"EditorIcons");
+ }
+
+ owners->add_item(efsd->get_file_path(i),icon);
+ }
+
+}
+
+void DependencyEditorOwners::show(const String& p_path) {
+
+ editing=p_path;
+ owners->clear();
+ _fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
+ popup_centered_ratio();
+
+ set_title(TTR("Owners Of:")+" "+p_path.get_file());
+
+}
+
+DependencyEditorOwners::DependencyEditorOwners() {
+
+
+ owners = memnew( ItemList );
+ add_child(owners);
+
+
+
+}
+
+///////////////////////
+
+
+void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) {
+
+ if (!efsd)
+ return;
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _fill_owners(efsd->get_subdir(i));
+ }
+
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ Vector<String> deps = efsd->get_file_deps(i);
+ //print_line(":::"+efsd->get_file_path(i));
+ Set<String> met;
+ for(int j=0;j<deps.size();j++) {
+ if (files.has(deps[j])) {
+ met.insert(deps[j]);
+ }
+ }
+ if (!met.size())
+ continue;
+
+ exist=true;
+
+ Ref<Texture> icon;
+ String type=efsd->get_file_type(i);
+ if (!has_icon(type,"EditorIcons")) {
+ icon=get_icon("Object","EditorIcons");
+ } else {
+ icon=get_icon(type,"EditorIcons");
+ }
+
+
+ for(Set<String>::Element *E=met.front();E;E=E->next()) {
+
+ String which = E->get();
+ if (!files[which]) {
+ TreeItem *ti=owners->create_item(owners->get_root());
+ ti->set_text(0,which.get_file());
+ files[which]=ti;
+
+ }
+ TreeItem *ti=owners->create_item(files[which]);
+ ti->set_text(0,efsd->get_file_path(i));
+ ti->set_icon(0,icon);
+ }
+
+ }
+
+}
+
+void DependencyRemoveDialog::show(const Vector<String> &to_erase) {
+
+ exist=false;
+ owners->clear();
+ files.clear();
+ owners->create_item(); // root
+ for(int i=0;i<to_erase.size();i++) {
+ files[to_erase[i]]=NULL;
+ }
+
+ _fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
+
+
+ if (exist) {
+ owners->show();
+ text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"));
+ popup_centered_minsize(Size2(500,220));
+ } else {
+ owners->hide();
+ text->set_text(TTR("Remove selected files from the project? (no undo)"));
+ popup_centered_minsize(Size2(400,100));
+ }
+
+}
+
+void DependencyRemoveDialog::ok_pressed() {
+
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ for (Map<String,TreeItem*>::Element *E=files.front();E;E=E->next()) {
+
+ if (ResourceCache::has(E->key())) {
+ Resource *res = ResourceCache::get(E->key());
+ res->set_path(""); //clear reference to path
+ }
+ da->remove(E->key());
+ EditorFileSystem::get_singleton()->update_file(E->key());
+ }
+ memdelete(da);
+
+}
+
+DependencyRemoveDialog::DependencyRemoveDialog() {
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+
+
+ text = memnew( Label );
+ vb->add_child(text);
+
+ owners = memnew( Tree );
+ owners->set_hide_root(true);
+ vb->add_child(owners);
+ owners->set_v_size_flags(SIZE_EXPAND_FILL);
+ get_ok()->set_text(TTR("Remove"));
+}
+
+
+//////////////
+
+
+void DependencyErrorDialog::show(const String& p_for_file,const Vector<String> &report) {
+
+
+ for_file=p_for_file;
+ set_title(TTR("Error loading:")+" "+p_for_file.get_file());
+ files->clear();
+
+ TreeItem *root = files->create_item(NULL);
+ for(int i=0;i<report.size();i++) {
+
+ String dep;
+ String type="Object";
+ dep=report[i].get_slice("::",0);
+ if (report[i].get_slice_count("::")>0)
+ type=report[i].get_slice("::",1);
+
+ Ref<Texture> icon;
+ if (!has_icon(type,"EditorIcons")) {
+ icon=get_icon("Object","EditorIcons");
+ } else {
+ icon=get_icon(type,"EditorIcons");
+ }
+
+ TreeItem *ti=files->create_item(root);
+ ti->set_text(0,dep);
+ ti->set_icon(0,icon);
+
+ }
+
+ popup_centered_minsize(Size2(500,220));
+
+}
+
+void DependencyErrorDialog::ok_pressed() {
+
+ EditorNode::get_singleton()->load_scene(for_file,true);
+}
+
+void DependencyErrorDialog::custom_action(const String&) {
+
+ EditorNode::get_singleton()->fix_dependencies(for_file);
+}
+
+DependencyErrorDialog::DependencyErrorDialog() {
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+
+
+
+ files = memnew( Tree );
+ files->set_hide_root(true);
+ vb->add_margin_child(TTR("Scene failed to load due to missing dependencies:"),files,true);
+ files->set_v_size_flags(SIZE_EXPAND_FILL);
+ get_ok()->set_text(TTR("Open Anyway"));
+
+ text = memnew( Label );
+ vb->add_child(text);
+ text->set_text(TTR("Which action should be taken?"));
+
+
+ fdep=add_button(TTR("Fix Dependencies"),true,"fixdeps");
+
+ set_title(TTR("Errors loading!"));
+
+}
+
+//////////////////////////////////////////////////////////////////////
+
+
+
+void OrphanResourcesDialog::ok_pressed() {
+
+ paths.clear();
+
+ _find_to_delete(files->get_root(),paths);
+ if (paths.empty())
+ return;
+
+ delete_confirm->set_text(vformat(TTR("Permanently delete %d item(s)? (No undo!)"),paths.size()));
+ delete_confirm->popup_centered_minsize();
+}
+
+bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd,HashMap<String,int>& refs,TreeItem* p_parent){
+
+
+ if (!efsd)
+ return false;
+
+ bool has_childs=false;
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+
+ TreeItem *dir_item=NULL;
+ if (p_parent) {
+ dir_item = files->create_item(p_parent);
+ dir_item->set_text(0,efsd->get_subdir(i)->get_name());
+ dir_item->set_icon(0,get_icon("folder","FileDialog"));
+
+ }
+ bool children = _fill_owners(efsd->get_subdir(i),refs,dir_item);
+
+ if (p_parent) {
+ if (!children) {
+ memdelete(dir_item);
+ } else {
+ has_childs=true;
+ }
+ }
+
+ }
+
+
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ if (!p_parent) {
+ Vector<String> deps = efsd->get_file_deps(i);
+ //print_line(":::"+efsd->get_file_path(i));
+ for(int j=0;j<deps.size();j++) {
+
+ if (!refs.has(deps[j])) {
+ refs[deps[j]]=1;
+ }
+ }
+ } else {
+
+ String path = efsd->get_file_path(i);
+ if (!refs.has(path)) {
+ TreeItem *ti=files->create_item(p_parent);
+ ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ ti->set_text(0,efsd->get_file(i));
+ ti->set_editable(0,true);
+
+ String type=efsd->get_file_type(i);
+
+ Ref<Texture> icon;
+ if (has_icon(type,"EditorIcons")) {
+ icon=get_icon(type,"EditorIcons");
+ } else {
+ icon=get_icon("Object","EditorIcons");
+ }
+ ti->set_icon(0,icon);
+ int ds = efsd->get_file_deps(i).size();
+ ti->set_text(1,itos(ds));
+ if (ds) {
+ ti->add_button(1,get_icon("Visible","EditorIcons"));
+ }
+ ti->set_metadata(0,path);
+ has_childs=true;
+ }
+ }
+
+ }
+
+ return has_childs;
+}
+
+
+void OrphanResourcesDialog::refresh() {
+ HashMap<String,int> refs;
+ _fill_owners(EditorFileSystem::get_singleton()->get_filesystem(),refs,NULL);
+ files->clear();
+ TreeItem *root=files->create_item();
+ _fill_owners(EditorFileSystem::get_singleton()->get_filesystem(),refs,root);
+}
+
+
+void OrphanResourcesDialog::show(){
+
+ refresh();
+ popup_centered_ratio();
+}
+
+
+void OrphanResourcesDialog::_find_to_delete(TreeItem* p_item,List<String>& paths) {
+
+ while(p_item) {
+
+ if (p_item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK && p_item->is_checked(0)) {
+ paths.push_back(p_item->get_metadata(0));
+ }
+
+ if (p_item->get_children()) {
+ _find_to_delete(p_item->get_children(),paths);
+ }
+
+ p_item=p_item->get_next();
+ }
+
+
+}
+
+void OrphanResourcesDialog::_delete_confirm() {
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ for (List<String>::Element *E=paths.front();E;E=E->next()) {
+
+ da->remove(E->get());
+ EditorFileSystem::get_singleton()->update_file(E->get());
+ }
+ memdelete(da);
+ refresh();
+}
+
+void OrphanResourcesDialog::_button_pressed(Object *p_item,int p_column, int p_id) {
+
+ TreeItem *ti=p_item->cast_to<TreeItem>();
+
+ String path = ti->get_metadata(0);
+ dep_edit->edit(path);
+
+}
+
+void OrphanResourcesDialog::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_delete_confirm"),&OrphanResourcesDialog::_delete_confirm);
+ ClassDB::bind_method(D_METHOD("_button_pressed"),&OrphanResourcesDialog::_button_pressed);
+
+}
+
+OrphanResourcesDialog::OrphanResourcesDialog(){
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+
+ files = memnew( Tree );
+ files->set_columns(2);
+ files->set_column_titles_visible(true);
+ files->set_column_min_width(1,100);
+ files->set_column_expand(0,true);
+ files->set_column_expand(1,false);
+ files->set_column_title(0,TTR("Resource"));
+ files->set_column_title(1,TTR("Owns"));
+ files->set_hide_root(true);
+ vbc->add_margin_child(TTR("Resources Without Explicit Ownership:"),files,true);
+ set_title(TTR("Orphan Resource Explorer"));
+ delete_confirm = memnew( ConfirmationDialog );
+ delete_confirm->set_text(TTR("Delete selected files?"));
+ get_ok()->set_text(TTR("Delete"));
+ add_child(delete_confirm);
+ dep_edit = memnew( DependencyEditor );
+ add_child(dep_edit);
+ files->connect("button_pressed",this,"_button_pressed");
+ delete_confirm->connect("confirmed",this,"_delete_confirm");
+ set_hide_on_ok(false);
+
+}
diff --git a/tools/editor/dependency_editor.h b/editor/dependency_editor.h
index a96ffe5fcf..a96ffe5fcf 100644
--- a/tools/editor/dependency_editor.h
+++ b/editor/dependency_editor.h
diff --git a/tools/editor/doc/SCsub b/editor/doc/SCsub
index 04c9a827ef..04c9a827ef 100644
--- a/tools/editor/doc/SCsub
+++ b/editor/doc/SCsub
diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp
new file mode 100644
index 0000000000..47b8edfa04
--- /dev/null
+++ b/editor/doc/doc_data.cpp
@@ -0,0 +1,1148 @@
+/*************************************************************************/
+/* doc_data.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "doc_data.h"
+
+#include "version.h"
+#include "global_constants.h"
+#include "global_config.h"
+#include "script_language.h"
+#include "io/marshalls.h"
+#include "io/compression.h"
+#include "scene/resources/theme.h"
+
+void DocData::merge_from(const DocData& p_data) {
+
+ for( Map<String,ClassDoc>::Element *E=class_list.front();E;E=E->next()) {
+
+
+ ClassDoc &c = E->get();
+
+ if (!p_data.class_list.has(c.name))
+ continue;
+
+ const ClassDoc &cf = p_data.class_list[c.name];
+
+ c.description=cf.description;
+ c.brief_description=cf.brief_description;
+
+ for(int i=0;i<c.methods.size();i++) {
+
+ MethodDoc &m = c.methods[i];
+
+ for(int j=0;j<cf.methods.size();j++) {
+
+ if (cf.methods[j].name!=m.name)
+ continue;
+ if (cf.methods[j].arguments.size()!=m.arguments.size())
+ continue;
+ // since polymorphic functions are allowed we need to check the type of
+ // the arguments so we make sure they are different.
+ int arg_count = cf.methods[j].arguments.size();
+ Vector<bool> arg_used;
+ arg_used.resize(arg_count);
+ for (int l = 0; l < arg_count; ++l) arg_used[l] = false;
+ // also there is no guarantee that argument ordering will match, so we
+ // have to check one by one so we make sure we have an exact match
+ for (int k = 0; k < arg_count; ++k) {
+ for (int l = 0; l < arg_count; ++l)
+ if (cf.methods[j].arguments[k].type == m.arguments[l].type && !arg_used[l]) {
+ arg_used[l] = true;
+ break;
+ }
+ }
+ bool not_the_same = false;
+ for (int l = 0; l < arg_count; ++l)
+ if (!arg_used[l]) // at least one of the arguments was different
+ not_the_same = true;
+ if (not_the_same)
+ continue;
+
+ const MethodDoc &mf = cf.methods[j];
+
+ m.description=mf.description;
+ break;
+ }
+ }
+
+
+ for(int i=0;i<c.signals.size();i++) {
+
+ MethodDoc &m = c.signals[i];
+
+ for(int j=0;j<cf.signals.size();j++) {
+
+ if (cf.signals[j].name!=m.name)
+ continue;
+ const MethodDoc &mf = cf.signals[j];
+
+ m.description=mf.description;
+ break;
+ }
+ }
+
+ for(int i=0;i<c.constants.size();i++) {
+
+ ConstantDoc &m = c.constants[i];
+
+ for(int j=0;j<cf.constants.size();j++) {
+
+ if (cf.constants[j].name!=m.name)
+ continue;
+ const ConstantDoc &mf = cf.constants[j];
+
+ m.description=mf.description;
+ break;
+ }
+ }
+
+ for(int i=0;i<c.properties.size();i++) {
+
+ PropertyDoc &p = c.properties[i];
+
+ for(int j=0;j<cf.properties.size();j++) {
+
+ if (cf.properties[j].name!=p.name)
+ continue;
+ const PropertyDoc &pf = cf.properties[j];
+
+ p.description=pf.description;
+ p.setter=pf.setter;
+ p.getter=pf.getter;
+
+ break;
+ }
+ }
+
+ for(int i=0;i<c.theme_properties.size();i++) {
+
+ PropertyDoc &p = c.theme_properties[i];
+
+ for(int j=0;j<cf.theme_properties.size();j++) {
+
+ if (cf.theme_properties[j].name!=p.name)
+ continue;
+ const PropertyDoc &pf = cf.theme_properties[j];
+
+ p.description=pf.description;
+ break;
+ }
+ }
+
+ }
+
+}
+
+void DocData::remove_from(const DocData &p_data) {
+ for(Map<String,ClassDoc>::Element* E=p_data.class_list.front(); E; E=E->next()) {
+ if(class_list.has(E->key()))
+ class_list.erase(E->key());
+ }
+}
+
+void DocData::generate(bool p_basic_types) {
+
+
+ List<StringName> classes;
+ ClassDB::get_class_list(&classes);
+ classes.sort_custom<StringName::AlphCompare>();
+
+ while(classes.size()) {
+
+ String name=classes.front()->get();
+ String cname=name;
+ if (cname.begins_with("_")) //proxy class
+ cname=cname.substr(1,name.length());
+
+ class_list[cname]=ClassDoc();
+ ClassDoc& c = class_list[cname];
+ c.name=cname;
+ c.inherits=ClassDB::get_parent_class(name);
+ c.category=ClassDB::get_category(name);
+
+
+ List<PropertyInfo> properties;
+ ClassDB::get_property_list(name,&properties,true);
+
+ for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
+ if (E->get().usage& PROPERTY_USAGE_GROUP || E->get().usage& PROPERTY_USAGE_CATEGORY)
+ continue;
+
+ PropertyDoc prop;
+ StringName setter = ClassDB::get_property_setter(name,E->get().name);
+ StringName getter = ClassDB::get_property_getter(name,E->get().name);
+
+ prop.name=E->get().name;
+ prop.setter=setter;
+ prop.getter=getter;
+ if (E->get().type==Variant::OBJECT && E->get().hint==PROPERTY_HINT_RESOURCE_TYPE)
+ prop.type=E->get().hint_string;
+ else
+ prop.type=Variant::get_type_name(E->get().type);
+
+ c.properties.push_back(prop);
+ }
+
+
+ List<MethodInfo> method_list;
+ ClassDB::get_method_list(name,&method_list,true);
+ method_list.sort();
+
+
+ for(List<MethodInfo>::Element *E=method_list.front();E;E=E->next()) {
+
+ if (E->get().name=="" || (E->get().name[0]=='_' && !(E->get().flags&METHOD_FLAG_VIRTUAL)))
+ continue; //hiden, dont count
+
+ MethodDoc method;
+
+ method.name=E->get().name;
+
+ MethodBind *m = ClassDB::get_method(name,E->get().name);
+
+
+ if (E->get().flags&METHOD_FLAG_VIRTUAL)
+ method.qualifiers="virtual";
+ if (E->get().flags&METHOD_FLAG_CONST) {
+ if (method.qualifiers!="")
+ method.qualifiers+=" ";
+ method.qualifiers+="const";
+
+ } else if (E->get().flags&METHOD_FLAG_VARARG) {
+ if (method.qualifiers!="")
+ method.qualifiers+=" ";
+ method.qualifiers+="vararg";
+ }
+
+ for(int i=-1;i<E->get().arguments.size();i++) {
+
+ PropertyInfo arginfo;
+
+ if (i==-1) {
+
+
+ arginfo=E->get().return_val;
+#ifdef DEBUG_METHODS_ENABLED
+ if (m && m->get_return_type()!=StringName())
+ method.return_type=m->get_return_type();
+ else if (method.name.find(":")!=-1) {
+ method.return_type=method.name.get_slice(":",1);
+ method.name=method.name.get_slice(":",0);
+
+ } 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 {
+
+ ArgumentDoc argument;
+
+ arginfo=E->get().arguments[i];
+
+ String type_name;
+
+ if (arginfo.name.find(":")!=-1) {
+ type_name=arginfo.name.get_slice(":",1);
+ arginfo.name=arginfo.name.get_slice(":",0);
+
+ } else if (arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE) {
+ type_name=arginfo.hint_string;
+ } else if (arginfo.type==Variant::NIL)
+ type_name="Variant";
+ else
+ type_name=Variant::get_type_name(arginfo.type);
+
+ if (arginfo.type==Variant::OBJECT) {
+
+ //print_line("validate: "+cname+"::"+method.name);
+ }
+
+ if (m && m->has_default_argument(i)) {
+ Variant default_arg=m->get_default_argument(i);
+ String default_arg_text=m->get_default_argument(i);
+
+ switch(default_arg.get_type()) {
+
+ case Variant::NIL:
+ default_arg_text="NULL";
+ break;
+ // atomic types
+ case Variant::BOOL:
+ if (bool(default_arg))
+ default_arg_text="true";
+ else
+ default_arg_text="false";
+ break;
+ case Variant::INT:
+ case Variant::REAL:
+ //keep it
+ break;
+ case Variant::STRING: // 15
+ case Variant::NODE_PATH: // 15
+ default_arg_text="\""+default_arg_text+"\"";
+ break;
+ case Variant::TRANSFORM:
+ if (default_arg.operator Transform()==Transform()) {
+ default_arg_text="";
+ }
+
+ default_arg_text=Variant::get_type_name(default_arg.get_type())+"("+default_arg_text+")";
+ break;
+
+ case Variant::RECT3: //sorry naming convention fail :( not like it's used often // 10
+ case Variant::COLOR:
+ case Variant::PLANE:
+ case Variant::POOL_BYTE_ARRAY:
+ case Variant::POOL_INT_ARRAY:
+ case Variant::POOL_REAL_ARRAY:
+ case Variant::POOL_STRING_ARRAY: //25
+ case Variant::POOL_VECTOR2_ARRAY:
+ case Variant::POOL_VECTOR3_ARRAY:
+ case Variant::POOL_COLOR_ARRAY:
+ default_arg_text=Variant::get_type_name(default_arg.get_type())+"("+default_arg_text+")";
+ break;
+ case Variant::VECTOR2: // 5
+ case Variant::RECT2:
+ case Variant::VECTOR3:
+ case Variant::QUAT:
+ case Variant::BASIS:
+ default_arg_text=Variant::get_type_name(default_arg.get_type())+default_arg_text;
+ break;
+ case Variant::OBJECT:
+ if (default_arg.is_zero()) {
+ default_arg_text="NULL";
+ break;
+ }
+ case Variant::INPUT_EVENT:
+ case Variant::DICTIONARY: // 20
+ case Variant::ARRAY:
+ case Variant::_RID:
+ case Variant::IMAGE:
+ //case Variant::RESOURCE:
+
+ default_arg_text=Variant::get_type_name(default_arg.get_type())+"()";
+ break;
+ default: {}
+
+ }
+
+
+ argument.type=type_name;
+ argument.name=arginfo.name;
+ argument.default_value=default_arg_text;
+ } else {
+
+ argument.type=type_name;
+ argument.name=arginfo.name;
+ }
+
+ if (arginfo.type==Variant::OBJECT) {
+
+ //print_line("validate: "+cname+"::"+method.name);
+ }
+
+ method.arguments.push_back(argument);
+ }
+
+/*
+ String hint;
+ switch(arginfo.hint) {
+ case PROPERTY_HINT_DIR: hint="A directory."; break;
+ case PROPERTY_HINT_RANGE: hint="Range - min: "+arginfo.hint_string.get_slice(",",0)+" max: "+arginfo.hint_string.get_slice(",",1)+" step: "+arginfo.hint_string.get_slice(",",2); break;
+ case PROPERTY_HINT_ENUM: hint="Values: "; for(int j=0;j<arginfo.hint_string.get_slice_count(",");j++) { if (j>0) hint+=", "; hint+=arginfo.hint_string.get_slice(",",j)+"="+itos(j); } break;
+ case PROPERTY_HINT_LENGTH: hint="Length: "+arginfo.hint_string; break;
+ case PROPERTY_HINT_FLAGS: hint="Values: "; for(int j=0;j<arginfo.hint_string.get_slice_count(",");j++) { if (j>0) hint+=", "; hint+=arginfo.hint_string.get_slice(",",j)+"="+itos(1<<j); } break;
+ case PROPERTY_HINT_FILE: hint="A file:"; break;
+ //case PROPERTY_HINT_RESOURCE_TYPE: hint="Type: "+arginfo.hint_string; break;
+ };
+ if (hint!="")
+ _write_string(f,4,hint);
+*/
+
+
+ }
+
+ c.methods.push_back(method);
+ }
+
+ List<MethodInfo> signal_list;
+ ClassDB::get_signal_list(name,&signal_list,true);
+
+ if (signal_list.size()) {
+
+
+ for(List<MethodInfo>::Element *EV=signal_list.front();EV;EV=EV->next()) {
+
+ MethodDoc signal;
+ signal.name=EV->get().name;
+ for(int i=0;i<EV->get().arguments.size();i++) {
+
+ PropertyInfo arginfo=EV->get().arguments[i];
+ ArgumentDoc argument;
+ argument.name=arginfo.name;
+ argument.type=Variant::get_type_name(arginfo.type);
+ signal.arguments.push_back(argument);
+ }
+
+ c.signals.push_back(signal);
+ }
+
+
+ }
+
+ List<String> constant_list;
+ ClassDB::get_integer_constant_list(name, &constant_list, true);
+
+ for(List<String>::Element *E=constant_list.front();E;E=E->next()) {
+
+ ConstantDoc constant;
+ constant.name=E->get();
+ constant.value=itos(ClassDB::get_integer_constant(name, E->get()));
+ c.constants.push_back(constant);
+ }
+
+ //theme stuff
+
+ {
+ List<StringName> l;
+ Theme::get_default()->get_constant_list(cname,&l);
+ for (List<StringName>::Element*E=l.front();E;E=E->next()) {
+
+ PropertyDoc pd;
+ pd.name=E->get();
+ pd.type="int";
+ c.theme_properties.push_back(pd);
+ }
+
+ l.clear();
+ Theme::get_default()->get_color_list(cname,&l);
+ for (List<StringName>::Element*E=l.front();E;E=E->next()) {
+
+ PropertyDoc pd;
+ pd.name=E->get();
+ pd.type="Color";
+ c.theme_properties.push_back(pd);
+ }
+
+ l.clear();
+ Theme::get_default()->get_icon_list(cname,&l);
+ for (List<StringName>::Element*E=l.front();E;E=E->next()) {
+
+ PropertyDoc pd;
+ pd.name=E->get();
+ pd.type="Texture";
+ c.theme_properties.push_back(pd);
+ }
+ l.clear();
+ Theme::get_default()->get_font_list(cname,&l);
+ for (List<StringName>::Element*E=l.front();E;E=E->next()) {
+
+ PropertyDoc pd;
+ pd.name=E->get();
+ pd.type="Font";
+ c.theme_properties.push_back(pd);
+ }
+ l.clear();
+ Theme::get_default()->get_stylebox_list(cname,&l);
+ for (List<StringName>::Element*E=l.front();E;E=E->next()) {
+
+ PropertyDoc pd;
+ pd.name=E->get();
+ pd.type="StyleBox";
+ c.theme_properties.push_back(pd);
+ }
+
+ }
+
+
+ classes.pop_front();
+ }
+
+
+ {
+ //so it can be documented that it does not exist
+ class_list["Variant"]=ClassDoc();
+ class_list["Variant"].name="Variant";
+ }
+
+ if (!p_basic_types)
+ return;
+
+ for (int i=0;i<Variant::VARIANT_MAX;i++) {
+
+ if (i==Variant::OBJECT)
+ continue; //use the core type instead
+
+ int loops=1;
+
+ if (i==Variant::INPUT_EVENT)
+ loops=InputEvent::TYPE_MAX;
+
+ for(int j=0;j<loops;j++) {
+
+ String cname=Variant::get_type_name(Variant::Type(i));
+
+ if (i==Variant::INPUT_EVENT) {
+ static const char* ie_type[InputEvent::TYPE_MAX]={
+ "","Key","MouseMotion","MouseButton","JoypadMotion","JoypadButton","ScreenTouch","ScreenDrag","Action"
+ };
+ cname+=ie_type[j];
+ }
+
+
+ class_list[cname]=ClassDoc();
+ ClassDoc& c = class_list[cname];
+ c.name=cname;
+ c.category="Built-In Types";
+
+ Variant::CallError cerror;
+ Variant v=Variant::construct(Variant::Type(i),NULL,0,cerror);
+
+ if (i==Variant::INPUT_EVENT) {
+ v.set("type",j);
+ }
+
+ List<MethodInfo> method_list;
+ v.get_method_list(&method_list);
+ method_list.sort();
+ Variant::get_constructor_list(Variant::Type(i),&method_list);
+
+
+ for(List<MethodInfo>::Element *E=method_list.front();E;E=E->next()) {
+
+ MethodInfo &mi=E->get();
+ MethodDoc method;
+
+ method.name=mi.name;
+
+ for(int i=0;i<mi.arguments.size();i++) {
+
+ ArgumentDoc arg;
+ PropertyInfo pi=mi.arguments[i];
+
+ arg.name=pi.name;
+ //print_line("arg name: "+arg.name);
+ if (pi.type==Variant::NIL)
+ arg.type="var";
+ else
+ arg.type=Variant::get_type_name(pi.type);
+ int defarg = mi.default_arguments.size() - mi.arguments.size() + i;
+ if (defarg >=0)
+ arg.default_value=mi.default_arguments[defarg];
+
+ method.arguments.push_back(arg);
+ }
+
+ if (mi.return_val.type==Variant::NIL) {
+ if (mi.return_val.name!="")
+ method.return_type="var";
+
+ } else {
+ method.return_type=Variant::get_type_name(mi.return_val.type);
+ }
+
+ c.methods.push_back(method);
+ }
+
+
+ List<PropertyInfo> properties;
+ v.get_property_list(&properties);
+ for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
+
+ PropertyInfo pi=E->get();
+ PropertyDoc property;
+ property.name=pi.name;
+ property.type=Variant::get_type_name(pi.type);
+
+ c.properties.push_back(property);
+ }
+
+ List<StringName> constants;
+ Variant::get_numeric_constants_for_type(Variant::Type(i),&constants);
+
+ for(List<StringName>::Element *E=constants.front();E;E=E->next()) {
+
+ ConstantDoc constant;
+ constant.name=E->get();
+ constant.value=itos(Variant::get_numeric_constant_value(Variant::Type(i),E->get()));
+ c.constants.push_back(constant);
+ }
+ }
+
+ }
+
+ //built in constants and functions
+
+ {
+
+ String cname="@Global Scope";
+ class_list[cname]=ClassDoc();
+ ClassDoc& c = class_list[cname];
+ c.name=cname;
+
+
+ for(int i=0;i<GlobalConstants::get_global_constant_count();i++) {
+
+ ConstantDoc cd;
+ cd.name=GlobalConstants::get_global_constant_name(i);
+ cd.value=itos(GlobalConstants::get_global_constant_value(i));
+ c.constants.push_back(cd);
+ }
+
+ List<GlobalConfig::Singleton> singletons;
+ GlobalConfig::get_singleton()->get_singletons(&singletons);
+
+ //servers (this is kind of hackish)
+ for(List<GlobalConfig::Singleton>::Element *E=singletons.front();E;E=E->next()) {
+
+ PropertyDoc pd;
+ GlobalConfig::Singleton &s=E->get();
+ pd.name=s.name;
+ pd.type=s.ptr->get_class();
+ while (String(ClassDB::get_parent_class(pd.type))!="Object")
+ pd.type=ClassDB::get_parent_class(pd.type);
+ if (pd.type.begins_with("_"))
+ pd.type=pd.type.substr(1,pd.type.length());
+ c.properties.push_back(pd);
+
+ }
+
+ }
+
+ //built in script reference
+
+ {
+
+
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+
+
+ ScriptLanguage *lang = ScriptServer::get_language(i);
+ String cname="@"+lang->get_name();
+ class_list[cname]=ClassDoc();
+ ClassDoc& c = class_list[cname];
+ c.name=cname;
+
+ List<MethodInfo> minfo;
+
+ lang->get_public_functions(&minfo);
+
+
+ for(List<MethodInfo>::Element *E=minfo.front();E;E=E->next()) {
+
+ MethodInfo &mi=E->get();
+ MethodDoc md;
+ md.name=mi.name;
+ if (mi.return_val.name!="")
+ md.return_type=mi.return_val.name;
+ 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++) {
+
+ PropertyInfo &pi=mi.arguments[i];
+
+ ArgumentDoc ad;
+ ad.name=pi.name;
+
+
+ if (pi.type==Variant::NIL)
+ ad.type="Variant";
+ else
+ ad.type=Variant::get_type_name( pi.type );
+
+ md.arguments.push_back(ad);
+ }
+
+ c.methods.push_back(md);
+
+ }
+
+ List<Pair<String,Variant> > cinfo;
+ lang->get_public_constants(&cinfo);
+
+
+ for(List<Pair<String,Variant> >::Element *E=cinfo.front();E;E=E->next()) {
+
+ ConstantDoc cd;
+ cd.name=E->get().first;
+ cd.value=E->get().second;
+ c.constants.push_back(cd);
+ }
+ }
+ }
+
+
+}
+
+
+static Error _parse_methods(Ref<XMLParser>& parser,Vector<DocData::MethodDoc>& methods) {
+
+ String section=parser->get_node_name();
+ String element=section.substr(0,section.length()-1);
+
+ while(parser->read()==OK) {
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser->get_node_name()==element) {
+
+ DocData::MethodDoc method;
+ ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
+ method.name=parser->get_attribute_value("name");
+ if (parser->has_attribute("qualifiers"))
+ method.qualifiers=parser->get_attribute_value("qualifiers");
+
+
+ while(parser->read()==OK) {
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name=parser->get_node_name();
+ if (name=="return") {
+
+ ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
+ method.return_type=parser->get_attribute_value("type");
+ } else if (name=="argument") {
+
+ DocData::ArgumentDoc argument;
+ ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
+ argument.name=parser->get_attribute_value("name");
+ ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
+ argument.type=parser->get_attribute_value("type");
+
+ method.arguments.push_back(argument);
+
+ } else if (name=="description") {
+
+ parser->read();
+ if (parser->get_node_type()==XMLParser::NODE_TEXT)
+ method.description=parser->get_node_data().strip_edges();
+ }
+
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()==element)
+ break;
+ }
+
+ methods.push_back(method);
+
+ } else {
+ ERR_EXPLAIN("Invalid tag in doc file: "+parser->get_node_name());
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
+ }
+
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()==section)
+ break;
+ }
+
+ return OK;
+}
+
+Error DocData::load(const String& p_path) {
+
+ Ref<XMLParser> parser=memnew(XMLParser);
+ Error err = parser->open(p_path);
+ if (err)
+ return err;
+ return _load(parser);
+
+}
+Error DocData::_load(Ref<XMLParser> parser) {
+
+ Error err=OK;
+
+ while((err=parser->read())==OK) {
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ if (parser->get_node_name() == "doc") {
+ break;
+ } else if (!parser->is_empty())
+ parser->skip_section();// unknown section, likely headers
+ }
+ }
+
+ if (parser->has_attribute("version"))
+ version=parser->get_attribute_value("version");
+
+
+ while((err=parser->read())==OK) {
+
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="doc")
+ break; //end of <doc>
+
+ if (parser->get_node_type() != XMLParser::NODE_ELEMENT)
+ continue; //no idea what this may be, but skipping anyway
+
+ ERR_FAIL_COND_V( parser->get_node_name()!="class", ERR_FILE_CORRUPT );
+
+ ERR_FAIL_COND_V( !parser->has_attribute("name"), ERR_FILE_CORRUPT);
+ String name = parser->get_attribute_value("name");
+ class_list[name]=ClassDoc();
+ ClassDoc& c = class_list[name];
+
+ //print_line("class: "+name);
+ c.name=name;
+ if (parser->has_attribute("inherits"))
+ c.inherits = parser->get_attribute_value("inherits");
+ if (parser->has_attribute("category"))
+ c.category = parser->get_attribute_value("category");
+
+ while(parser->read()==OK) {
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser->get_node_name();
+
+ if (name=="brief_description") {
+
+ parser->read();
+ if (parser->get_node_type()==XMLParser::NODE_TEXT)
+ c.brief_description=parser->get_node_data().strip_edges();
+
+ } else if (name=="description") {
+ parser->read();
+ if (parser->get_node_type()==XMLParser::NODE_TEXT)
+ c.description=parser->get_node_data().strip_edges();
+ } else if (name=="methods") {
+
+ Error err = _parse_methods(parser,c.methods);
+ ERR_FAIL_COND_V(err,err);
+
+ } else if (name=="signals") {
+
+ Error err = _parse_methods(parser,c.signals);
+ ERR_FAIL_COND_V(err,err);
+ } else if (name=="members") {
+
+ while(parser->read()==OK) {
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser->get_node_name();
+
+ if (name=="member") {
+
+ PropertyDoc prop;
+
+ ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
+ prop.name=parser->get_attribute_value("name");
+ ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
+ prop.type=parser->get_attribute_value("type");
+ if (parser->has_attribute("setter"))
+ prop.setter=parser->get_attribute_value("setter");
+ if (parser->has_attribute("getter"))
+ prop.getter=parser->get_attribute_value("getter");
+ if (parser->has_attribute("brief"))
+ prop.brief_description=parser->get_attribute_value("brief").xml_unescape();
+
+ parser->read();
+ if (parser->get_node_type()==XMLParser::NODE_TEXT)
+ prop.description=parser->get_node_data().strip_edges();
+ c.properties.push_back(prop);
+ } else {
+ ERR_EXPLAIN("Invalid tag in doc file: "+name);
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
+ }
+
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="members")
+ break; //end of <constants>
+ }
+
+ } else if (name=="theme_items") {
+
+ while(parser->read()==OK) {
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name = parser->get_node_name();
+
+ if (name=="theme_item") {
+
+ PropertyDoc prop;
+
+ ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
+ prop.name=parser->get_attribute_value("name");
+ ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
+ prop.type=parser->get_attribute_value("type");
+ parser->read();
+ if (parser->get_node_type()==XMLParser::NODE_TEXT)
+ prop.description=parser->get_node_data().strip_edges();
+ c.theme_properties.push_back(prop);
+ } else {
+ ERR_EXPLAIN("Invalid tag in doc file: "+name);
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
+ }
+
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="theme_items")
+ break; //end of <constants>
+ }
+
+ } else if (name=="constants") {
+
+ while(parser->read()==OK) {
+
+ if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
+
+ String name=parser->get_node_name();
+
+ if (name=="constant") {
+
+ ConstantDoc constant;
+ ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
+ constant.name=parser->get_attribute_value("name");
+ ERR_FAIL_COND_V(!parser->has_attribute("value"),ERR_FILE_CORRUPT);
+ constant.value=parser->get_attribute_value("value");
+ parser->read();
+ if (parser->get_node_type()==XMLParser::NODE_TEXT)
+ constant.description=parser->get_node_data().strip_edges();
+ c.constants.push_back(constant);
+ } else {
+ ERR_EXPLAIN("Invalid tag in doc file: "+name);
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
+ }
+
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="constants")
+ break; //end of <constants>
+ }
+
+ } else {
+
+ ERR_EXPLAIN("Invalid tag in doc file: "+name);
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
+ }
+
+
+ } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="class")
+ break; //end of <asset>
+ }
+
+
+ }
+
+ return OK;
+}
+
+
+static void _write_string(FileAccess *f,int p_tablevel,const String& p_string) {
+
+ String tab;
+ for(int i=0;i<p_tablevel;i++) tab+="\t";
+ f->store_string(tab+p_string+"\n");
+}
+
+Error DocData::save(const String& p_path) {
+
+ Error err;
+ FileAccess *f = FileAccess::open(p_path,FileAccess::WRITE,&err);
+
+ if (err) {
+ ERR_EXPLAIN("Can't write doc file: "+p_path);
+
+ ERR_FAIL_V(err);
+
+ }
+
+ _write_string(f,0,"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
+ _write_string(f,0,"<doc version=\""+String(VERSION_MKSTRING)+"\" name=\"Engine Types\">");
+
+ for( Map<String,ClassDoc>::Element *E=class_list.front();E;E=E->next()) {
+
+ ClassDoc &c=E->get();
+
+ String header="<class name=\""+c.name+"\"";
+ if (c.inherits!="")
+ header+=" inherits=\""+c.inherits+"\"";
+
+ String category=c.category;
+ if (c.category=="")
+ category="Core";
+ header+=" category=\""+category+"\"";
+ header+=">";
+ _write_string(f,0,header);
+ _write_string(f,1,"<brief_description>");
+ if (c.brief_description!="")
+ _write_string(f,2,c.brief_description.xml_escape());
+ _write_string(f,1,"</brief_description>");
+ _write_string(f,1,"<description>");
+ if (c.description!="")
+ _write_string(f,2,c.description.xml_escape());
+ _write_string(f,1,"</description>");
+ _write_string(f,1,"<methods>");
+
+ c.methods.sort();
+
+ for(int i=0;i<c.methods.size();i++) {
+
+ MethodDoc &m=c.methods[i];
+
+ String qualifiers;
+ if (m.qualifiers!="")
+ qualifiers+=" qualifiers=\""+m.qualifiers.xml_escape()+"\"";
+
+ _write_string(f,2,"<method name=\""+m.name+"\""+qualifiers+">");
+
+ if (m.return_type!="") {
+
+ _write_string(f,3,"<return type=\""+m.return_type+"\">");
+ _write_string(f,3,"</return>");
+ }
+
+ for(int j=0;j<m.arguments.size();j++) {
+
+ ArgumentDoc &a = m.arguments[j];
+ if (a.default_value!="")
+ _write_string(f,3,"<argument index=\""+itos(j)+"\" name=\""+a.name.xml_escape()+"\" type=\""+a.type.xml_escape()+"\" default=\""+a.default_value.xml_escape(true)+"\">");
+ else
+ _write_string(f,3,"<argument index=\""+itos(j)+"\" name=\""+a.name.xml_escape()+"\" type=\""+a.type.xml_escape()+"\">");
+
+ _write_string(f,3,"</argument>");
+
+ }
+
+ _write_string(f,3,"<description>");
+ if (m.description!="")
+ _write_string(f,4,m.description.xml_escape());
+ _write_string(f,3,"</description>");
+
+ _write_string(f,2,"</method>");
+
+ }
+
+ _write_string(f,1,"</methods>");
+
+ if (c.properties.size()) {
+ _write_string(f,1,"<members>");
+
+ c.properties.sort();
+
+ for(int i=0;i<c.properties.size();i++) {
+
+
+ PropertyDoc &p=c.properties[i];
+ _write_string(f,2,"<member name=\""+p.name+"\" type=\""+p.type+"\" setter=\""+p.setter+"\" getter=\""+p.getter+"\" brief=\""+p.brief_description.xml_escape(true)+"\">");
+ if (p.description!="")
+ _write_string(f,3,p.description.xml_escape());
+ _write_string(f,2,"</member>");
+
+ }
+ _write_string(f,1,"</members>");
+ }
+
+ if (c.signals.size()) {
+
+ c.signals.sort();
+
+ _write_string(f,1,"<signals>");
+ for(int i=0;i<c.signals.size();i++) {
+
+ MethodDoc &m=c.signals[i];
+ _write_string(f,2,"<signal name=\""+m.name+"\">");
+ for(int j=0;j<m.arguments.size();j++) {
+
+ ArgumentDoc &a = m.arguments[j];
+ _write_string(f,3,"<argument index=\""+itos(j)+"\" name=\""+a.name.xml_escape()+"\" type=\""+a.type.xml_escape()+"\">");
+ _write_string(f,3,"</argument>");
+
+ }
+
+ _write_string(f,3,"<description>");
+ if (m.description!="")
+ _write_string(f,4,m.description.xml_escape());
+ _write_string(f,3,"</description>");
+
+ _write_string(f,2,"</signal>");
+ }
+
+ _write_string(f,1,"</signals>");
+ }
+
+ _write_string(f,1,"<constants>");
+
+
+ for(int i=0;i<c.constants.size();i++) {
+
+ ConstantDoc &k=c.constants[i];
+ _write_string(f,2,"<constant name=\""+k.name+"\" value=\""+k.value+"\">");
+ if (k.description!="")
+ _write_string(f,3,k.description.xml_escape());
+ _write_string(f,2,"</constant>");
+ }
+
+ _write_string(f,1,"</constants>");
+
+ if (c.theme_properties.size()) {
+
+ c.theme_properties.sort();
+
+ _write_string(f,1,"<theme_items>");
+ for(int i=0;i<c.theme_properties.size();i++) {
+
+
+ PropertyDoc &p=c.theme_properties[i];
+ _write_string(f,2,"<theme_item name=\""+p.name+"\" type=\""+p.type+"\">");
+ _write_string(f,2,"</theme_item>");
+
+ }
+ _write_string(f,1,"</theme_items>");
+ }
+
+ _write_string(f,0,"</class>");
+
+ }
+
+ _write_string(f,0,"</doc>");
+ f->close();
+ memdelete(f);
+
+ return OK;
+}
+
+
+Error DocData::load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size) {
+
+ Vector<uint8_t> data;
+ data.resize(p_uncompressed_size);
+ Compression::decompress(data.ptr(),p_uncompressed_size,p_data,p_compressed_size,Compression::MODE_DEFLATE);
+ class_list.clear();
+
+ Ref<XMLParser> parser = memnew( XMLParser );
+ Error err = parser->open_buffer(data);
+ if (err)
+ return err;
+
+ _load(parser);
+
+ return OK;
+
+}
diff --git a/editor/doc/doc_data.h b/editor/doc/doc_data.h
new file mode 100644
index 0000000000..7601013979
--- /dev/null
+++ b/editor/doc/doc_data.h
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* doc_data.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 DOC_DATA_H
+#define DOC_DATA_H
+
+
+#include "variant.h"
+#include "map.h"
+#include "io/xml_parser.h"
+
+class DocData {
+public:
+ struct ArgumentDoc {
+
+ String name;
+ String type;
+ String default_value;
+ };
+
+ struct MethodDoc {
+
+ String name;
+ String return_type;
+ String qualifiers;
+ String description;
+ Vector<ArgumentDoc> arguments;
+ bool operator<(const MethodDoc& p_md) const {
+ return name<p_md.name;
+ }
+ };
+
+ struct ConstantDoc {
+
+ String name;
+ String value;
+ String description;
+ };
+
+ struct PropertyDoc {
+
+ String name;
+ String type;
+ String brief_description;
+ String description;
+ String setter,getter;
+ bool operator<(const PropertyDoc& p_prop) const {
+ return name<p_prop.name;
+ }
+ };
+
+ struct ClassDoc {
+
+ String name;
+ String inherits;
+ String category;
+ String brief_description;
+ String description;
+ Vector<MethodDoc> methods;
+ Vector<MethodDoc> signals;
+ Vector<ConstantDoc> constants;
+ Vector<PropertyDoc> properties;
+ Vector<PropertyDoc> theme_properties;
+
+ };
+
+ String version;
+
+ Map<String,ClassDoc> class_list;
+ Error _load(Ref<XMLParser> parser);
+
+
+public:
+
+ void merge_from(const DocData& p_data);
+ void remove_from(const DocData& p_data);
+ void generate(bool p_basic_types=false);
+ Error load(const String& p_path);
+ Error save(const String& p_path);
+
+ Error load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size);
+
+
+};
+
+#endif // DOC_DATA_H
diff --git a/tools/editor/doc/doc_dump.cpp b/editor/doc/doc_dump.cpp
index 5ebba596e9..5ebba596e9 100644
--- a/tools/editor/doc/doc_dump.cpp
+++ b/editor/doc/doc_dump.cpp
diff --git a/tools/editor/doc/doc_dump.h b/editor/doc/doc_dump.h
index 84629b89c8..84629b89c8 100644
--- a/tools/editor/doc/doc_dump.h
+++ b/editor/doc/doc_dump.h
diff --git a/tools/editor/doc_code_font.h b/editor/doc_code_font.h
index 55f335ab78..55f335ab78 100644
--- a/tools/editor/doc_code_font.h
+++ b/editor/doc_code_font.h
diff --git a/tools/editor/doc_font.h b/editor/doc_font.h
index b598ee26f8..b598ee26f8 100644
--- a/tools/editor/doc_font.h
+++ b/editor/doc_font.h
diff --git a/tools/editor/doc_title_font.h b/editor/doc_title_font.h
index afa0f61eda..afa0f61eda 100644
--- a/tools/editor/doc_title_font.h
+++ b/editor/doc_title_font.h
diff --git a/tools/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 8af01012a4..8af01012a4 100644
--- a/tools/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
diff --git a/tools/editor/editor_asset_installer.h b/editor/editor_asset_installer.h
index 2d0486a6f6..2d0486a6f6 100644
--- a/tools/editor/editor_asset_installer.h
+++ b/editor/editor_asset_installer.h
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
new file mode 100644
index 0000000000..8643644950
--- /dev/null
+++ b/editor/editor_audio_buses.cpp
@@ -0,0 +1,1221 @@
+/*************************************************************************/
+/* editor_audio_buses.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_audio_buses.h"
+
+#include "editor_node.h"
+#include "servers/audio_server.h"
+#include "os/keyboard.h"
+#include "io/resource_saver.h"
+#include "filesystem_dock.h"
+
+void EditorAudioBus::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+
+ vu_l->set_under_texture(get_icon("BusVuEmpty","EditorIcons"));
+ vu_l->set_progress_texture(get_icon("BusVuFull","EditorIcons"));
+ vu_r->set_under_texture(get_icon("BusVuEmpty","EditorIcons"));
+ vu_r->set_progress_texture(get_icon("BusVuFull","EditorIcons"));
+ scale->set_texture( get_icon("BusVuDb","EditorIcons"));
+
+ disabled_vu = get_icon("BusVuFrozen","EditorIcons");
+
+ prev_active=true;
+ update_bus();
+ set_process(true);
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ if (has_focus()) {
+ draw_style_box(get_stylebox("focus","Button"),Rect2(Vector2(),get_size()));
+ }
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ float real_peak[2]={-100,-100};
+ bool activity_found=false;
+
+ int cc;
+ switch(AudioServer::get_singleton()->get_speaker_mode()) {
+ case AudioServer::SPEAKER_MODE_STEREO: cc = 1; break;
+ case AudioServer::SPEAKER_SURROUND_51: cc = 4; break;
+ case AudioServer::SPEAKER_SURROUND_71: cc = 5; break;
+ }
+
+ for(int i=0;i<cc;i++) {
+ if (AudioServer::get_singleton()->is_bus_channel_active(get_index(),i)) {
+ activity_found=true;
+ real_peak[0]=MAX(real_peak[0],AudioServer::get_singleton()->get_bus_peak_volume_left_db(get_index(),i));
+ real_peak[1]=MAX(real_peak[1],AudioServer::get_singleton()->get_bus_peak_volume_right_db(get_index(),i));
+ }
+ }
+
+
+ if (real_peak[0]>peak_l) {
+ peak_l = real_peak[0];
+ } else {
+ peak_l-=get_process_delta_time()*60.0;
+ }
+
+ if (real_peak[1]>peak_r) {
+ peak_r = real_peak[1];
+ } else {
+ peak_r-=get_process_delta_time()*60.0;
+
+ }
+
+ vu_l->set_value(peak_l);
+ vu_r->set_value(peak_r);
+
+ if (activity_found!=prev_active) {
+ if (activity_found) {
+ vu_l->set_over_texture(Ref<Texture>());
+ vu_r->set_over_texture(Ref<Texture>());
+ } else {
+ vu_l->set_over_texture(disabled_vu);
+ vu_r->set_over_texture(disabled_vu);
+
+ }
+
+ prev_active=activity_found;
+ }
+
+ }
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ peak_l=-100;
+ peak_r=-100;
+ prev_active=true;
+
+ set_process(is_visible_in_tree());
+ }
+
+}
+
+void EditorAudioBus::update_send() {
+
+ send->clear();
+ if (get_index()==0) {
+ send->set_disabled(true);
+ send->set_text("Speakers");
+ } else {
+ send->set_disabled(false);
+ StringName current_send = AudioServer::get_singleton()->get_bus_send(get_index());
+ int current_send_index=0; //by default to master
+
+ for(int i=0;i<get_index();i++) {
+ StringName send_name = AudioServer::get_singleton()->get_bus_name(i);
+ send->add_item(send_name);
+ if (send_name==current_send) {
+ current_send_index=i;
+ }
+ }
+
+ send->select(current_send_index);
+ }
+}
+
+void EditorAudioBus::update_bus() {
+
+ if (updating_bus)
+ return;
+
+ updating_bus=true;
+
+ int index = get_index();
+
+ slider->set_value(AudioServer::get_singleton()->get_bus_volume_db(index));
+ track_name->set_text(AudioServer::get_singleton()->get_bus_name(index));
+ if (get_index()==0)
+ track_name->set_editable(false);
+
+ solo->set_pressed( AudioServer::get_singleton()->is_bus_solo(index));
+ mute->set_pressed( AudioServer::get_singleton()->is_bus_mute(index));
+ bypass->set_pressed( AudioServer::get_singleton()->is_bus_bypassing_effects(index));
+ // effects..
+ effects->clear();
+
+ TreeItem *root = effects->create_item();
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(index);i++) {
+
+ Ref<AudioEffect> afx = AudioServer::get_singleton()->get_bus_effect(index,i);
+
+ TreeItem *fx = effects->create_item(root);
+ fx->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ fx->set_editable(0,true);
+ fx->set_checked(0,AudioServer::get_singleton()->is_bus_effect_enabled(index,i));
+ fx->set_text(0,afx->get_name());
+ fx->set_metadata(0,i);
+
+ }
+
+ TreeItem *add = effects->create_item(root);
+ add->set_cell_mode(0,TreeItem::CELL_MODE_CUSTOM);
+ add->set_editable(0,true);
+ add->set_selectable(0,false);
+ add->set_text(0,"Add Effect");
+
+ update_send();
+
+ updating_bus=false;
+
+}
+
+
+void EditorAudioBus::_name_changed(const String& p_new_name) {
+
+ if (p_new_name==AudioServer::get_singleton()->get_bus_name(get_index()))
+ return;
+
+ String attempt=p_new_name;
+ int attempts=1;
+
+ while(true) {
+
+ bool name_free=true;
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+
+ if (AudioServer::get_singleton()->get_bus_name(i)==attempt) {
+ name_free=false;
+ break;
+ }
+ }
+
+ if (name_free) {
+ break;
+ }
+
+ attempts++;
+ attempt=p_new_name+" "+itos(attempts);
+ }
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ StringName current = AudioServer::get_singleton()->get_bus_name(get_index());
+ ur->create_action("Rename Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_name",get_index(),attempt);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_name",get_index(),current);
+
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+ if (AudioServer::get_singleton()->get_bus_send(i)==current) {
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",i,attempt);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",i,current);
+ }
+ }
+
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+
+
+ ur->add_do_method(buses,"_update_sends");
+ ur->add_undo_method(buses,"_update_sends");
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+
+void EditorAudioBus::_volume_db_changed(float p_db){
+
+ if (updating_bus)
+ return;
+
+ updating_bus=true;
+
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Audio Bus Volume",UndoRedo::MERGE_ENDS);
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_volume_db",get_index(),p_db);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_volume_db",get_index(),AudioServer::get_singleton()->get_bus_volume_db(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+void EditorAudioBus::_solo_toggled(){
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Toggle Audio Bus Solo");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_solo",get_index(),solo->is_pressed());
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_solo",get_index(),AudioServer::get_singleton()->is_bus_solo(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+void EditorAudioBus::_mute_toggled(){
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Toggle Audio Bus Mute");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_mute",get_index(),mute->is_pressed());
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_mute",get_index(),AudioServer::get_singleton()->is_bus_mute(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+}
+void EditorAudioBus::_bypass_toggled(){
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Toggle Audio Bus Bypass Effects");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_bypass_effects",get_index(),bypass->is_pressed());
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_bypass_effects",get_index(),AudioServer::get_singleton()->is_bus_bypassing_effects(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+
+}
+
+void EditorAudioBus::_send_selected(int p_which) {
+
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Select Audio Bus Send");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",get_index(),send->get_item_text(p_which));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",get_index(),AudioServer::get_singleton()->get_bus_send(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+}
+
+void EditorAudioBus::_effect_selected() {
+
+ TreeItem *effect = effects->get_selected();
+ if (!effect)
+ return;
+ updating_bus=true;
+
+ if (effect->get_metadata(0)!=Variant()) {
+
+ int index = effect->get_metadata(0);
+ Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(get_index(),index);
+ if (effect.is_valid()) {
+ EditorNode::get_singleton()->push_item(effect.ptr());
+ }
+ }
+
+ updating_bus=false;
+
+}
+
+void EditorAudioBus::_effect_edited() {
+
+ if (updating_bus)
+ return;
+
+ TreeItem *effect = effects->get_edited();
+ if (!effect)
+ return;
+
+ if (effect->get_metadata(0)==Variant()) {
+ Rect2 area = effects->get_item_rect(effect);
+
+ effect_options->set_pos(effects->get_global_pos()+area.pos+Vector2(0,area.size.y));
+ effect_options->popup();
+ //add effect
+ } else {
+ int index = effect->get_metadata(0);
+ updating_bus=true;
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Select Audio Bus Send");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,effect->is_checked(0));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,AudioServer::get_singleton()->is_bus_effect_enabled(get_index(),index));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+ updating_bus=false;
+
+ }
+
+}
+
+void EditorAudioBus::_effect_add(int p_which) {
+
+ if (updating_bus)
+ return;
+
+ StringName name = effect_options->get_item_metadata(p_which);
+
+ Object *fx = ClassDB::instance(name);
+ ERR_FAIL_COND(!fx);
+ AudioEffect *afx = fx->cast_to<AudioEffect>();
+ ERR_FAIL_COND(!afx);
+ Ref<AudioEffect> afxr = Ref<AudioEffect>(afx);
+
+ afxr->set_name(effect_options->get_item_text(p_which));
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Add Audio Bus Effect");
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),afxr,-1);
+ ur->add_undo_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect_count(get_index()));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+}
+
+void EditorAudioBus::_gui_input(const InputEvent& p_event) {
+
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && !p_event.key.echo) {
+ accept_event();
+ emit_signal("delete_request");
+ }
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==2 && p_event.mouse_button.pressed) {
+
+ Vector2 pos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y);
+ delete_popup->set_pos(get_global_pos()+pos);
+ delete_popup->popup();
+ }
+}
+
+void EditorAudioBus::_delete_pressed(int p_option) {
+
+ if (p_option==1) {
+ emit_signal("delete_request");
+ } else if (p_option==0) {
+ //duplicate
+ emit_signal("duplicate_request",get_index());
+ }
+
+}
+
+
+Variant EditorAudioBus::get_drag_data(const Point2& p_point) {
+
+ if (get_index()==0) {
+ return Variant();
+ }
+
+ Control *c = memnew(Control);
+ Panel *p = memnew( Panel );
+ c->add_child(p);
+ p->add_style_override("panel",get_stylebox("focus","Button"));
+ p->set_size(get_size());
+ p->set_pos(-p_point);
+ set_drag_preview(c);
+ Dictionary d;
+ d["type"]="move_audio_bus";
+ d["index"]=get_index();
+ emit_signal("drop_end_request");
+ return d;
+}
+
+bool EditorAudioBus::can_drop_data(const Point2& p_point,const Variant& p_data) const {
+
+ if (get_index()==0)
+ return false;
+ Dictionary d=p_data;
+ if (d.has("type") && String(d["type"])=="move_audio_bus") {
+ return true;
+ }
+
+ return false;
+}
+void EditorAudioBus::drop_data(const Point2& p_point,const Variant& p_data) {
+
+ Dictionary d=p_data;
+ emit_signal("dropped",d["index"],get_index());
+
+}
+
+Variant EditorAudioBus::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ print_line("drag fw");
+ TreeItem *item = effects->get_item_at_pos(p_point);
+ if (!item) {
+ print_line("no item");
+ return Variant();
+ }
+
+ Variant md = item->get_metadata(0);
+
+ if (md.get_type()==Variant::INT) {
+ Dictionary fxd;
+ fxd["type"]="audio_bus_effect";
+ fxd["bus"]=get_index();
+ fxd["effect"]=md;
+
+ Label *l = memnew( Label );
+ l->set_text(item->get_text(0));
+ effects->set_drag_preview(l);
+
+ return fxd;
+ }
+
+ return Variant();
+
+}
+
+bool EditorAudioBus::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ Dictionary d = p_data;
+ if (!d.has("type") || String(d["type"])!="audio_bus_effect")
+ return false;
+
+ TreeItem *item = effects->get_item_at_pos(p_point);
+ if (!item)
+ return false;
+
+ effects->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+
+ return true;
+}
+
+void EditorAudioBus::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ Dictionary d = p_data;
+
+ TreeItem *item = effects->get_item_at_pos(p_point);
+ if (!item)
+ return;
+ int pos=effects->get_drop_section_at_pos(p_point);
+ Variant md = item->get_metadata(0);
+
+ int paste_at;
+ int bus = d["bus"];
+ int effect = d["effect"];
+
+ if (md.get_type()==Variant::INT) {
+ paste_at=md;
+ if (pos>0)
+ paste_at++;
+
+ if (bus==get_index() && paste_at >effect) {
+ paste_at--;
+ }
+ } else {
+ paste_at=-1;
+ }
+
+
+ bool enabled = AudioServer::get_singleton()->is_bus_effect_enabled(bus,effect);
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Move Bus Effect");
+ ur->add_do_method(AudioServer::get_singleton(),"remove_bus_effect",bus,effect);
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect(bus,effect),paste_at);
+
+ if (paste_at==-1) {
+ paste_at = AudioServer::get_singleton()->get_bus_effect_count(get_index());
+ if (bus==get_index()) {
+ paste_at--;
+ }
+ }
+ if (!enabled) {
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),paste_at,false);
+ }
+
+ ur->add_undo_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),paste_at);
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",bus,AudioServer::get_singleton()->get_bus_effect(bus,effect),effect);
+ if (!enabled) {
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",bus,effect,false);
+ }
+
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ if (get_index()!=bus) {
+ ur->add_do_method(buses,"_update_bus",bus);
+ ur->add_undo_method(buses,"_update_bus",bus);
+ }
+ ur->commit_action();
+
+
+
+}
+
+void EditorAudioBus::_delete_effect_pressed(int p_option) {
+
+ TreeItem * item = effects->get_selected();
+ if (!item)
+ return;
+
+ if (item->get_metadata(0).get_type()!=Variant::INT)
+ return;
+
+ int index = item->get_metadata(0);
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Delete Bus Effect");
+ ur->add_do_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),index);
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect(get_index(),index),index);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,AudioServer::get_singleton()->is_bus_effect_enabled(get_index(),index));
+ ur->add_do_method(buses,"_update_bus",get_index());
+ ur->add_undo_method(buses,"_update_bus",get_index());
+ ur->commit_action();
+
+
+}
+
+void EditorAudioBus::_effect_rmb(const Vector2& p_pos) {
+
+ TreeItem * item = effects->get_selected();
+ if (!item)
+ return;
+
+ if (item->get_metadata(0).get_type()!=Variant::INT)
+ return;
+
+ delete_effect_popup->set_pos(get_global_mouse_pos());
+ delete_effect_popup->popup();
+}
+
+void EditorAudioBus::_bind_methods() {
+
+ ClassDB::bind_method("update_bus",&EditorAudioBus::update_bus);
+ ClassDB::bind_method("update_send",&EditorAudioBus::update_send);
+ ClassDB::bind_method("_name_changed",&EditorAudioBus::_name_changed);
+ ClassDB::bind_method("_volume_db_changed",&EditorAudioBus::_volume_db_changed);
+ ClassDB::bind_method("_solo_toggled",&EditorAudioBus::_solo_toggled);
+ ClassDB::bind_method("_mute_toggled",&EditorAudioBus::_mute_toggled);
+ ClassDB::bind_method("_bypass_toggled",&EditorAudioBus::_bypass_toggled);
+ ClassDB::bind_method("_name_focus_exit",&EditorAudioBus::_name_focus_exit);
+ ClassDB::bind_method("_send_selected",&EditorAudioBus::_send_selected);
+ ClassDB::bind_method("_effect_edited",&EditorAudioBus::_effect_edited);
+ ClassDB::bind_method("_effect_selected",&EditorAudioBus::_effect_selected);
+ ClassDB::bind_method("_effect_add",&EditorAudioBus::_effect_add);
+ ClassDB::bind_method("_gui_input",&EditorAudioBus::_gui_input);
+ ClassDB::bind_method("_delete_pressed",&EditorAudioBus::_delete_pressed);
+ ClassDB::bind_method("get_drag_data_fw",&EditorAudioBus::get_drag_data_fw);
+ ClassDB::bind_method("can_drop_data_fw",&EditorAudioBus::can_drop_data_fw);
+ ClassDB::bind_method("drop_data_fw",&EditorAudioBus::drop_data_fw);
+ ClassDB::bind_method("_delete_effect_pressed",&EditorAudioBus::_delete_effect_pressed);
+ ClassDB::bind_method("_effect_rmb",&EditorAudioBus::_effect_rmb);
+
+
+
+ ADD_SIGNAL(MethodInfo("duplicate_request"));
+ ADD_SIGNAL(MethodInfo("delete_request"));
+ ADD_SIGNAL(MethodInfo("drop_end_request"));
+ ADD_SIGNAL(MethodInfo("dropped"));
+
+}
+
+EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
+
+ buses=p_buses;
+ updating_bus=false;
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+
+ set_v_size_flags(SIZE_EXPAND_FILL);
+
+ track_name = memnew( LineEdit );
+ vb->add_child(track_name);
+ track_name->connect("text_entered",this,"_name_changed");
+ track_name->connect("focus_exited",this,"_name_focus_exit");
+
+ HBoxContainer *hbc = memnew( HBoxContainer);
+ vb->add_child(hbc);
+ hbc->add_spacer();
+ solo = memnew( ToolButton );
+ solo->set_text("S");
+ solo->set_toggle_mode(true);
+ solo->set_modulate(Color(0.8,1.2,0.8));
+ solo->set_focus_mode(FOCUS_NONE);
+ solo->connect("pressed",this,"_solo_toggled");
+ hbc->add_child(solo);
+ mute = memnew( ToolButton );
+ mute->set_text("M");
+ mute->set_toggle_mode(true);
+ mute->set_modulate(Color(1.2,0.8,0.8));
+ mute->set_focus_mode(FOCUS_NONE);
+ mute->connect("pressed",this,"_mute_toggled");
+ hbc->add_child(mute);
+ bypass = memnew( ToolButton );
+ bypass->set_text("B");
+ bypass->set_toggle_mode(true);
+ bypass->set_modulate(Color(1.1,1.1,0.8));
+ bypass->set_focus_mode(FOCUS_NONE);
+ bypass->connect("pressed",this,"_bypass_toggled");
+ hbc->add_child(bypass);
+ hbc->add_spacer();
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ vb->add_child(hb);
+ slider = memnew( VSlider );
+ slider->set_min(-80);
+ slider->set_max(24);
+ slider->set_step(0.1);
+
+ slider->connect("value_changed",this,"_volume_db_changed");
+ hb->add_child(slider);
+ vu_l = memnew( TextureProgress );
+ vu_l->set_fill_mode(TextureProgress::FILL_BOTTOM_TO_TOP);
+ hb->add_child(vu_l);
+ vu_l->set_min(-80);
+ vu_l->set_max(24);
+ vu_l->set_step(0.1);
+
+ vu_r = memnew( TextureProgress );
+ vu_r->set_fill_mode(TextureProgress::FILL_BOTTOM_TO_TOP);
+ hb->add_child(vu_r);
+ vu_r->set_min(-80);
+ vu_r->set_max(24);
+ vu_r->set_step(0.1);
+
+ scale = memnew( TextureRect );
+ hb->add_child(scale);
+
+ //add_child(hb);
+
+ effects = memnew( Tree );
+ effects->set_hide_root(true);
+ effects->set_custom_minimum_size(Size2(0,90)*EDSCALE);
+ effects->set_hide_folding(true);
+ vb->add_child(effects);
+ effects->connect("item_edited",this,"_effect_edited");
+ effects->connect("cell_selected",this,"_effect_selected");
+ effects->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
+ effects->set_drag_forwarding(this);
+ effects->connect("item_rmb_selected",this,"_effect_rmb");
+ effects->set_allow_rmb_select(true);
+
+ send = memnew( OptionButton );
+ send->set_clip_text(true);
+ send->connect("item_selected",this,"_send_selected");
+ vb->add_child(send);
+
+ set_focus_mode(FOCUS_CLICK);
+
+ effect_options = memnew( PopupMenu );
+ effect_options->connect("index_pressed",this,"_effect_add");
+ add_child(effect_options);
+ List<StringName> effects;
+ ClassDB::get_inheriters_from_class("AudioEffect",&effects);
+ effects.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *E=effects.front();E;E=E->next()) {
+ if (!ClassDB::can_instance(E->get()))
+ continue;
+
+ Ref<Texture> icon;
+ if (has_icon(E->get(),"EditorIcons")) {
+ icon = get_icon(E->get(),"EditorIcons");
+ }
+ String name = E->get().operator String().replace("AudioEffect","");
+ effect_options->add_item(name);
+ effect_options->set_item_metadata(effect_options->get_item_count()-1,E->get());
+ effect_options->set_item_icon(effect_options->get_item_count()-1,icon);
+ }
+
+ delete_popup = memnew( PopupMenu );
+ delete_popup->add_item("Duplicate");
+ delete_popup->add_item("Delete");
+ add_child(delete_popup);
+ delete_popup->connect("index_pressed",this,"_delete_pressed");
+
+ delete_effect_popup = memnew( PopupMenu );
+ delete_effect_popup->add_item("Delete Effect");
+ add_child(delete_effect_popup);
+ delete_effect_popup->connect("index_pressed",this,"_delete_effect_pressed");
+
+}
+
+
+
+bool EditorAudioBusDrop::can_drop_data(const Point2& p_point,const Variant& p_data) const {
+
+ Dictionary d=p_data;
+ if (d.has("type") && String(d["type"])=="move_audio_bus") {
+ return true;
+ }
+
+ return false;
+}
+void EditorAudioBusDrop::drop_data(const Point2& p_point,const Variant& p_data){
+
+ Dictionary d=p_data;
+ emit_signal("dropped",d["index"],-1);
+
+}
+
+void EditorAudioBusDrop::_bind_methods() {
+
+ ADD_SIGNAL(MethodInfo("dropped"));
+}
+
+EditorAudioBusDrop::EditorAudioBusDrop() {
+
+
+}
+
+
+void EditorAudioBuses::_update_buses() {
+
+ while(bus_hb->get_child_count()>0) {
+ memdelete(bus_hb->get_child(0));
+ }
+
+ drop_end=NULL;
+
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+
+ EditorAudioBus *audio_bus = memnew( EditorAudioBus(this) );
+ if (i==0) {
+ audio_bus->set_self_modulate(Color(1,0.9,0.9));
+ }
+ bus_hb->add_child(audio_bus);
+ audio_bus->connect("delete_request",this,"_delete_bus",varray(audio_bus),CONNECT_DEFERRED);
+ audio_bus->connect("duplicate_request",this,"_duplicate_bus",varray(),CONNECT_DEFERRED);
+ audio_bus->connect("drop_end_request",this,"_request_drop_end");
+ audio_bus->connect("dropped",this,"_drop_at_index",varray(),CONNECT_DEFERRED);
+
+
+
+ }
+}
+
+EditorAudioBuses *EditorAudioBuses::register_editor() {
+
+ EditorAudioBuses * audio_buses = memnew( EditorAudioBuses );
+ EditorNode::get_singleton()->add_bottom_panel_item("Audio",audio_buses);
+ return audio_buses;
+}
+
+void EditorAudioBuses::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+ _update_buses();
+ }
+
+ if (p_what==NOTIFICATION_DRAG_END) {
+ if (drop_end) {
+ drop_end->queue_delete();
+ drop_end=NULL;
+ }
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ //check if anything was edited
+ bool edited = AudioServer::get_singleton()->is_edited();
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+ for(int j=0;j<AudioServer::get_singleton()->get_bus_effect_count(i);j++) {
+ Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(i,j);
+ if (effect->is_edited()) {
+ edited=true;
+ effect->set_edited(false);
+ }
+ }
+ }
+
+ AudioServer::get_singleton()->set_edited(false);
+
+ if (edited) {
+
+ save_timer->start();
+ }
+ }
+
+}
+
+
+void EditorAudioBuses::_add_bus() {
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ //need to simulate new name, so we can undi :(
+ ur->create_action("Add Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_count",AudioServer::get_singleton()->get_bus_count()+1);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_count",AudioServer::get_singleton()->get_bus_count());
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+
+}
+
+void EditorAudioBuses::_update_bus(int p_index) {
+
+ if (p_index>=bus_hb->get_child_count())
+ return;
+
+ bus_hb->get_child(p_index)->call("update_bus");
+}
+
+void EditorAudioBuses::_update_sends() {
+
+ for(int i=0;i<bus_hb->get_child_count();i++) {
+ bus_hb->get_child(i)->call("update_send");
+ }
+}
+
+void EditorAudioBuses::_delete_bus(Object* p_which) {
+
+ EditorAudioBus *bus = p_which->cast_to<EditorAudioBus>();
+ int index = bus->get_index();
+ if (index==0) {
+ EditorNode::get_singleton()->show_warning("Master bus can't be deleted!");
+ return;
+ }
+
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action("Delete Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"remove_bus",index);
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus",index);
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_name",index,AudioServer::get_singleton()->get_bus_name(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_volume_db",index,AudioServer::get_singleton()->get_bus_volume_db(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",index,AudioServer::get_singleton()->get_bus_send(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_solo",index,AudioServer::get_singleton()->is_bus_solo(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_mute",index,AudioServer::get_singleton()->is_bus_mute(index));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_bypass_effects",index,AudioServer::get_singleton()->is_bus_bypassing_effects(index));
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(index);i++) {
+
+ ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",index,AudioServer::get_singleton()->get_bus_effect(index,i));
+ ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",index,i,AudioServer::get_singleton()->is_bus_effect_enabled(index,i));
+ }
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+
+}
+
+
+void EditorAudioBuses::_duplicate_bus(int p_which) {
+
+ int add_at_pos = p_which+1;
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Duplicate Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus",add_at_pos);
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_name",add_at_pos,AudioServer::get_singleton()->get_bus_name(p_which)+" Copy");
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_volume_db",add_at_pos,AudioServer::get_singleton()->get_bus_volume_db(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",add_at_pos,AudioServer::get_singleton()->get_bus_send(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_solo",add_at_pos,AudioServer::get_singleton()->is_bus_solo(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_mute",add_at_pos,AudioServer::get_singleton()->is_bus_mute(p_which));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_bypass_effects",add_at_pos,AudioServer::get_singleton()->is_bus_bypassing_effects(p_which));
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(p_which);i++) {
+
+ ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",add_at_pos,AudioServer::get_singleton()->get_bus_effect(p_which,i));
+ ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",add_at_pos,i,AudioServer::get_singleton()->is_bus_effect_enabled(p_which,i));
+ }
+ ur->add_undo_method(AudioServer::get_singleton(),"remove_bus",add_at_pos);
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+
+}
+
+void EditorAudioBuses::_request_drop_end() {
+
+ if (!drop_end && bus_hb->get_child_count()) {
+ drop_end = memnew( EditorAudioBusDrop );
+
+ bus_hb->add_child(drop_end);
+ drop_end->set_custom_minimum_size(bus_hb->get_child(0)->cast_to<Control>()->get_size());
+ drop_end->connect("dropped",this,"_drop_at_index",varray(),CONNECT_DEFERRED);
+ }
+}
+
+void EditorAudioBuses::_drop_at_index(int p_bus,int p_index) {
+
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+ //need to simulate new name, so we can undi :(
+ ur->create_action("Move Audio Bus");
+ ur->add_do_method(AudioServer::get_singleton(),"move_bus",p_bus,p_index);
+ int final_pos;
+ if (p_index==p_bus) {
+ final_pos=p_bus;
+ } else if (p_index==-1) {
+ final_pos = AudioServer::get_singleton()->get_bus_count()-1;
+ } else if (p_index<p_bus) {
+ final_pos = p_index;
+ } else {
+ final_pos = p_index -1;
+ }
+ ur->add_undo_method(AudioServer::get_singleton(),"move_bus",final_pos,p_bus);
+
+ ur->add_do_method(this,"_update_buses");
+ ur->add_undo_method(this,"_update_buses");
+ ur->commit_action();
+}
+
+void EditorAudioBuses::_server_save() {
+
+ Ref<AudioBusLayout> state = AudioServer::get_singleton()->generate_bus_layout();
+ ResourceSaver::save(edited_path,state);
+
+}
+
+void EditorAudioBuses::_select_layout() {
+
+ EditorNode::get_singleton()->get_filesystem_dock()->select_file(edited_path);
+}
+
+void EditorAudioBuses::_save_as_layout() {
+
+ file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ file_dialog->set_title(TTR("Save Audio Bus Layout As.."));
+ file_dialog->set_current_path(edited_path);
+ file_dialog->popup_centered_ratio();
+ new_layout=false;
+}
+
+
+void EditorAudioBuses::_new_layout() {
+
+ file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ file_dialog->set_title(TTR("Location for New Layout.."));
+ file_dialog->set_current_path(edited_path);
+ file_dialog->popup_centered_ratio();
+ new_layout=true;
+}
+
+void EditorAudioBuses::_load_layout() {
+
+ file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_dialog->set_title(TTR("Open Audio Bus Layout"));
+ file_dialog->set_current_path(edited_path);
+ file_dialog->popup_centered_ratio();
+ new_layout=false;
+}
+
+
+void EditorAudioBuses::_load_default_layout() {
+
+
+ Ref<AudioBusLayout> state = ResourceLoader::load("res://default_bus_layout.tres");
+ if (state.is_null()) {
+ EditorNode::get_singleton()->show_warning("There is no 'res://default_bus_layout.tres' file.");
+ return;
+ }
+
+ edited_path="res://default_bus_layout.tres";
+ file->set_text(edited_path.get_file());
+ AudioServer::get_singleton()->set_bus_layout(state);
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+}
+
+void EditorAudioBuses::_file_dialog_callback(const String& p_string) {
+
+ if (file_dialog->get_mode()==EditorFileDialog::MODE_OPEN_FILE) {
+ Ref<AudioBusLayout> state = ResourceLoader::load(p_string);
+ if (state.is_null()) {
+ EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout.");
+ return;
+ }
+
+ edited_path=p_string;
+ file->set_text(p_string.get_file());
+ AudioServer::get_singleton()->set_bus_layout(state);
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+
+ } else if (file_dialog->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
+
+ if (new_layout) {
+ Ref<AudioBusLayout> empty_state;
+ empty_state.instance();
+ AudioServer::get_singleton()->set_bus_layout(empty_state);
+ }
+
+ Error err = ResourceSaver::save(p_string,AudioServer::get_singleton()->generate_bus_layout());
+
+ if (err!=OK) {
+ EditorNode::get_singleton()->show_warning("Error saving file: "+p_string);
+ return;
+ }
+
+ edited_path=p_string;
+ file->set_text(p_string.get_file());
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+ }
+
+}
+
+void EditorAudioBuses::_bind_methods() {
+
+ ClassDB::bind_method("_add_bus",&EditorAudioBuses::_add_bus);
+ ClassDB::bind_method("_update_buses",&EditorAudioBuses::_update_buses);
+ ClassDB::bind_method("_update_bus",&EditorAudioBuses::_update_bus);
+ ClassDB::bind_method("_update_sends",&EditorAudioBuses::_update_sends);
+ ClassDB::bind_method("_delete_bus",&EditorAudioBuses::_delete_bus);
+ ClassDB::bind_method("_request_drop_end",&EditorAudioBuses::_request_drop_end);
+ ClassDB::bind_method("_drop_at_index",&EditorAudioBuses::_drop_at_index);
+ ClassDB::bind_method("_server_save",&EditorAudioBuses::_server_save);
+ ClassDB::bind_method("_select_layout",&EditorAudioBuses::_select_layout);
+ ClassDB::bind_method("_save_as_layout",&EditorAudioBuses::_save_as_layout);
+ ClassDB::bind_method("_load_layout",&EditorAudioBuses::_load_layout);
+ ClassDB::bind_method("_load_default_layout",&EditorAudioBuses::_load_default_layout);
+ ClassDB::bind_method("_new_layout",&EditorAudioBuses::_new_layout);
+ ClassDB::bind_method("_duplicate_bus",&EditorAudioBuses::_duplicate_bus);
+
+ ClassDB::bind_method("_file_dialog_callback",&EditorAudioBuses::_file_dialog_callback);
+}
+
+EditorAudioBuses::EditorAudioBuses()
+{
+
+ drop_end = NULL;
+ top_hb = memnew( HBoxContainer );
+ add_child(top_hb);
+
+ add = memnew( Button );
+ top_hb->add_child(add);;
+ add->set_text(TTR("Add Bus"));
+
+ add->connect("pressed",this,"_add_bus");
+
+
+
+ top_hb->add_spacer();
+
+ file = memnew( ToolButton );
+ file->set_text("default_bus_layout.tres");
+ top_hb->add_child(file);
+ file->connect("pressed",this,"_select_layout");
+
+ load = memnew( Button );
+ load->set_text(TTR("Load"));
+ top_hb->add_child(load);
+ load->connect("pressed",this,"_load_layout");
+
+ save_as = memnew( Button );
+ save_as->set_text(TTR("Save As"));
+ top_hb->add_child(save_as);
+ save_as->connect("pressed",this,"_save_as_layout");
+
+ _default = memnew( Button );
+ _default->set_text(TTR("Default"));
+ top_hb->add_child(_default);
+ _default->connect("pressed",this,"_load_default_layout");
+
+ _new = memnew( Button );
+ _new->set_text(TTR("Create"));
+ top_hb->add_child(_new);
+ _new->connect("pressed",this,"_new_layout");
+
+ bus_scroll = memnew( ScrollContainer );
+ bus_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
+ bus_scroll->set_enable_h_scroll(true);
+ bus_scroll->set_enable_v_scroll(false);
+ add_child(bus_scroll);
+ bus_hb = memnew( HBoxContainer );
+ bus_scroll->add_child(bus_hb);
+
+ save_timer=memnew(Timer);
+ save_timer->set_wait_time(0.8);
+ save_timer->set_one_shot(true);
+ add_child(save_timer);
+ save_timer->connect("timeout",this,"_server_save");
+
+ set_v_size_flags(SIZE_EXPAND_FILL);
+
+
+ edited_path = "res://default_bus_layout.tres";
+
+ file_dialog = memnew( EditorFileDialog );
+ List<String> ext;
+ ResourceLoader::get_recognized_extensions_for_type("AudioServerState",&ext);
+ for (List<String>::Element *E=ext.front();E;E=E->next()) {
+ file_dialog->add_filter("*."+E->get()+"; Audio Bus State");
+ }
+ add_child(file_dialog);
+ file_dialog->connect("file_selected",this,"_file_dialog_callback");
+
+ set_process(true);
+
+}
+void EditorAudioBuses::open_layout(const String& p_path) {
+
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+
+ Ref<AudioBusLayout> state = ResourceLoader::load(p_path);
+ if (state.is_null()) {
+ EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout.");
+ return;
+ }
+
+ edited_path=p_path;
+ file->set_text(p_path.get_file());
+ AudioServer::get_singleton()->set_bus_layout(state);
+ _update_buses();
+ EditorNode::get_singleton()->get_undo_redo()->clear_history();
+ call_deferred("_select_layout");
+}
+
+void AudioBusesEditorPlugin::edit(Object *p_node) {
+
+ if (p_node->cast_to<AudioBusLayout>()) {
+
+ String path = p_node->cast_to<AudioBusLayout>()->get_path();
+ if (path.is_resource_file()) {
+ audio_bus_editor->open_layout(path);
+ }
+ }
+}
+
+bool AudioBusesEditorPlugin::handles(Object *p_node) const {
+
+ return (p_node->cast_to<AudioBusLayout>()!=NULL);
+}
+
+void AudioBusesEditorPlugin::make_visible(bool p_visible){
+
+
+}
+
+AudioBusesEditorPlugin::AudioBusesEditorPlugin(EditorAudioBuses *p_node) {
+
+ audio_bus_editor=p_node;
+}
+
+AudioBusesEditorPlugin::~AudioBusesEditorPlugin() {
+
+}
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
new file mode 100644
index 0000000000..8f9e327368
--- /dev/null
+++ b/editor/editor_audio_buses.h
@@ -0,0 +1,214 @@
+/*************************************************************************/
+/* editor_audio_buses.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 EDITORAUDIOBUSES_H
+#define EDITORAUDIOBUSES_H
+
+
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/slider.h"
+#include "scene/gui/texture_progress.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/panel.h"
+#include "editor/editor_file_dialog.h"
+#include "editor_plugin.h"
+
+class EditorAudioBuses;
+
+class EditorAudioBus : public PanelContainer {
+
+ GDCLASS( EditorAudioBus, PanelContainer )
+
+ bool prev_active;
+ float peak_l;
+ float peak_r;
+
+ Ref<Texture> disabled_vu;
+ LineEdit *track_name;
+ VSlider *slider;
+ TextureProgress *vu_l;
+ TextureProgress *vu_r;
+ TextureRect *scale;
+ OptionButton *send;
+
+ PopupMenu *effect_options;
+ PopupMenu *delete_popup;
+ PopupMenu *delete_effect_popup;
+
+ Button *solo;
+ Button *mute;
+ Button *bypass;
+
+ Tree *effects;
+
+ bool updating_bus;
+
+ void _gui_input(const InputEvent& p_event);
+ void _delete_pressed(int p_option);
+
+ void _name_changed(const String& p_new_name);
+ void _name_focus_exit() { _name_changed(track_name->get_text()); }
+ void _volume_db_changed(float p_db);
+ void _solo_toggled();
+ void _mute_toggled();
+ void _bypass_toggled();
+ void _send_selected(int p_which);
+ void _effect_edited();
+ void _effect_add(int p_which);
+ void _effect_selected();
+ void _delete_effect_pressed(int p_option);
+ void _effect_rmb(const Vector2& p_pos);
+
+
+ virtual Variant get_drag_data(const Point2& p_point);
+ virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
+ virtual void drop_data(const Point2& p_point,const Variant& p_data);
+
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+friend class EditorAudioBuses;
+
+ EditorAudioBuses *buses;
+
+protected:
+
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+ void update_bus();
+ void update_send();
+
+ EditorAudioBus(EditorAudioBuses *p_buses=NULL);
+};
+
+
+class EditorAudioBusDrop : public Panel {
+
+ GDCLASS(EditorAudioBusDrop,Panel);
+
+ virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
+ virtual void drop_data(const Point2& p_point,const Variant& p_data);
+protected:
+
+ static void _bind_methods();
+public:
+
+ EditorAudioBusDrop();
+};
+
+class EditorAudioBuses : public VBoxContainer {
+
+ GDCLASS(EditorAudioBuses,VBoxContainer)
+
+ HBoxContainer *top_hb;
+
+ Button *add;
+ ScrollContainer *bus_scroll;
+ HBoxContainer *bus_hb;
+
+ EditorAudioBusDrop *drop_end;
+
+ Button *file;
+ Button *load;
+ Button *save_as;
+ Button *_default;
+ Button *_new;
+
+ Timer *save_timer;
+ String edited_path;
+
+ void _add_bus();
+ void _update_buses();
+ void _update_bus(int p_index);
+ void _update_sends();
+
+ void _delete_bus(Object* p_which);
+ void _duplicate_bus(int p_which);
+
+
+ void _request_drop_end();
+ void _drop_at_index(int p_bus,int p_index);
+
+ void _server_save();
+
+ void _select_layout();
+ void _load_layout();
+ void _save_as_layout();
+ void _load_default_layout();
+ void _new_layout();
+
+ EditorFileDialog *file_dialog;
+ bool new_layout;
+
+ void _file_dialog_callback(const String& p_string);
+
+protected:
+
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+ void open_layout(const String& p_path);
+
+ static EditorAudioBuses* register_editor();
+
+ EditorAudioBuses();
+};
+
+
+
+class AudioBusesEditorPlugin : public EditorPlugin {
+
+ GDCLASS( AudioBusesEditorPlugin, EditorPlugin );
+
+ EditorAudioBuses *audio_bus_editor;
+public:
+
+ virtual String get_name() const { return "SampleLibrary"; }
+ 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);
+
+ AudioBusesEditorPlugin(EditorAudioBuses *p_node);
+ ~AudioBusesEditorPlugin();
+
+};
+
+#endif // EDITORAUDIOBUSES_H
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
new file mode 100644
index 0000000000..3e3362f515
--- /dev/null
+++ b/editor/editor_autoload_settings.cpp
@@ -0,0 +1,610 @@
+/*************************************************************************/
+/* editor_autoload_settings.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_autoload_settings.h"
+
+#include "global_config.h"
+#include "global_constants.h"
+#include "editor_node.h"
+
+#define PREVIEW_LIST_MAX_SIZE 10
+
+void EditorAutoloadSettings::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+
+ List<String> afn;
+ ResourceLoader::get_recognized_extensions_for_type("Script", &afn);
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene", &afn);
+
+ EditorFileDialog *file_dialog = autoload_add_path->get_file_dialog();
+
+ for (List<String>::Element *E = afn.front(); E; E = E->next()) {
+
+ file_dialog->add_filter("*." + E->get());
+ }
+ }
+}
+
+bool EditorAutoloadSettings::_autoload_name_is_valid(const String& p_name, String* r_error) {
+
+ if (!p_name.is_valid_identifier()) {
+ if (r_error)
+ *r_error = TTR("Invalid name.") + "\n" + TTR("Valid characters:")+" a-z, A-Z, 0-9 or _";
+
+ return false;
+ }
+
+ if (ClassDB::class_exists(p_name)) {
+ if (r_error)
+ *r_error = TTR("Invalid name. Must not collide with an existing engine class name.");
+
+ return false;
+ }
+
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ if (Variant::get_type_name( Variant::Type(i) ) == p_name) {
+ if (r_error)
+ *r_error = TTR("Invalid name. Must not collide with an existing buit-in type name.");
+
+ return false;
+ }
+ }
+
+ for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
+ if (GlobalConstants::get_global_constant_name(i) == p_name) {
+ if (r_error)
+ *r_error = TTR("Invalid name. Must not collide with an existing global constant name.");
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void EditorAutoloadSettings::_autoload_add() {
+
+ String name = autoload_add_name->get_text();
+
+ String error;
+ if (!_autoload_name_is_valid(name, &error)) {
+ EditorNode::get_singleton()->show_warning(error);
+ return;
+ }
+
+ String path = autoload_add_path->get_line_edit()->get_text();
+ if (!FileAccess::exists(path)) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n" + TTR("File does not exist."));
+ return;
+ }
+
+ if (!path.begins_with("res://")) {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n"+ TTR("Not in resource path."));
+ return;
+ }
+
+ name = "autoload/" + name;
+
+ UndoRedo* undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ undo_redo->create_action(TTR("Add AutoLoad"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(), name, "*" + path);
+
+ if (GlobalConfig::get_singleton()->has(name)) {
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
+ } else {
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, Variant());
+ }
+
+ undo_redo->add_do_method(this, "update_autoload");
+ undo_redo->add_undo_method(this, "update_autoload");
+
+ undo_redo->add_do_method(this, "emit_signal", autoload_changed);
+ undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
+
+ undo_redo->commit_action();
+
+ autoload_add_path->get_line_edit()->set_text("");
+ autoload_add_name->set_text("");
+}
+
+void EditorAutoloadSettings::_autoload_selected() {
+
+ TreeItem *ti = tree->get_selected();
+
+ if (!ti)
+ return;
+
+ selected_autoload = "autoload/" + ti->get_text(0);
+}
+
+void EditorAutoloadSettings::_autoload_edited() {
+
+ if (updating_autoload)
+ return;
+
+ TreeItem *ti = tree->get_edited();
+ int column = tree->get_edited_column();
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ if (column == 0) {
+ String name = ti->get_text(0);
+ String old_name = selected_autoload.get_slice("/", 1);
+
+ if (name == old_name)
+ return;
+
+ String error;
+ if (!_autoload_name_is_valid(name, &error)) {
+ ti->set_text(0, old_name);
+ EditorNode::get_singleton()->show_warning(error);
+ return;
+ }
+
+ if (GlobalConfig::get_singleton()->has("autoload/" + name)) {
+ ti->set_text(0, old_name);
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Autoload '%s' already exists!"), name));
+ return;
+ }
+
+ updating_autoload = true;
+
+ name = "autoload/" + name;
+
+ int order = GlobalConfig::get_singleton()->get_order(selected_autoload);
+ String path = GlobalConfig::get_singleton()->get(selected_autoload);
+
+ undo_redo->create_action(TTR("Rename Autoload"));
+
+ undo_redo->add_do_property(GlobalConfig::get_singleton(), name, path);
+ undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", name, order);
+ undo_redo->add_do_method(GlobalConfig::get_singleton(), "clear", selected_autoload);
+
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), selected_autoload, path);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", selected_autoload, order);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(), "clear", name);
+
+ undo_redo->add_do_method(this, "update_autoload");
+ undo_redo->add_undo_method(this, "update_autoload");
+
+ undo_redo->add_do_method(this, "emit_signal", autoload_changed);
+ undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
+
+ undo_redo->commit_action();
+
+ selected_autoload = name;
+ } else if (column == 2) {
+ updating_autoload = true;
+
+ bool checked = ti->is_checked(2);
+ String base = "autoload/" + ti->get_text(0);
+
+ int order = GlobalConfig::get_singleton()->get_order(base);
+ String path = GlobalConfig::get_singleton()->get(base);
+
+ if (path.begins_with("*"))
+ path = path.substr(1, path.length());
+
+ if (checked)
+ path = "*" + path;
+
+ undo_redo->create_action(TTR("Toggle AutoLoad Globals"));
+
+ undo_redo->add_do_property(GlobalConfig::get_singleton(), base, path);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), base, GlobalConfig::get_singleton()->get(base));
+
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"set_order", base, order);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set_order", base, order);
+
+ undo_redo->add_do_method(this, "update_autoload");
+ undo_redo->add_undo_method(this, "update_autoload");
+
+ undo_redo->add_do_method(this, "emit_signal", autoload_changed);
+ undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
+
+ undo_redo->commit_action();
+ }
+
+ updating_autoload = false;
+}
+
+void EditorAutoloadSettings::_autoload_button_pressed(Object *p_item, int p_column, int p_button) {
+
+ TreeItem *ti = p_item->cast_to<TreeItem>();
+
+ String name = "autoload/" + ti->get_text(0);
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ switch (p_button) {
+
+ case BUTTON_MOVE_UP:
+ case BUTTON_MOVE_DOWN: {
+
+ TreeItem *swap = NULL;
+
+ if (p_button == BUTTON_MOVE_UP) {
+ swap = ti->get_prev();
+ } else {
+ swap = ti->get_next();
+ }
+
+ if (!swap)
+ return;
+
+ String swap_name = "autoload/" + swap->get_text(0);
+
+ int order = GlobalConfig::get_singleton()->get_order(name);
+ int swap_order = GlobalConfig::get_singleton()->get_order(swap_name);
+
+ undo_redo->create_action(TTR("Move Autoload"));
+
+ undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", name, swap_order);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", name, order);
+
+ undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", swap_name, order);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", swap_name, swap_order);
+
+ undo_redo->add_do_method(this, "update_autoload");
+ undo_redo->add_undo_method(this, "update_autoload");
+
+ undo_redo->add_do_method(this, "emit_signal", autoload_changed);
+ undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
+
+ undo_redo->commit_action();
+ } break;
+ case BUTTON_DELETE: {
+
+ int order = GlobalConfig::get_singleton()->get_order(name);
+
+ undo_redo->create_action(TTR("Remove Autoload"));
+
+ undo_redo->add_do_property(GlobalConfig::get_singleton(), name, Variant());
+
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_persisting", name, true);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", order);
+
+ undo_redo->add_do_method(this, "update_autoload");
+ undo_redo->add_undo_method(this, "update_autoload");
+
+ undo_redo->add_do_method(this, "emit_signal", autoload_changed);
+ undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
+
+ undo_redo->commit_action();
+ } break;
+ }
+}
+
+void EditorAutoloadSettings::_autoload_file_callback(const String& p_path) {
+
+ autoload_add_name->set_text(p_path.get_file().get_basename());
+}
+
+void EditorAutoloadSettings::update_autoload() {
+
+ if (updating_autoload)
+ return;
+
+ updating_autoload = true;
+
+ autoload_cache.clear();
+
+ tree->clear();
+ TreeItem *root = tree->create_item();
+
+ List<PropertyInfo> props;
+ GlobalConfig::get_singleton()->get_property_list(&props);
+
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+
+ const PropertyInfo &pi = E->get();
+
+ if (!pi.name.begins_with("autoload/"))
+ continue;
+
+ String name = pi.name.get_slice("/", 1);
+ String path = GlobalConfig::get_singleton()->get(pi.name);
+
+ if (name.empty())
+ continue;
+
+ AutoLoadInfo info;
+ info.name = pi.name;
+ info.order = GlobalConfig::get_singleton()->get_order(pi.name);
+
+ autoload_cache.push_back(info);
+
+ bool global = false;
+
+ if (path.begins_with("*")) {
+ global = true;
+ path = path.substr(1, path.length());
+ }
+
+ TreeItem *item = tree->create_item(root);
+ item->set_text(0, name);
+ item->set_editable(0, true);
+
+ item->set_text(1, path);
+ item->set_selectable(1, false);
+
+ item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK);
+ item->set_editable(2, true);
+ item->set_text(2, TTR("Enable"));
+ item->set_checked(2, global);
+
+ item->add_button(3, get_icon("MoveUp","EditorIcons"), BUTTON_MOVE_UP);
+ item->add_button(3, get_icon("MoveDown","EditorIcons"), BUTTON_MOVE_DOWN);
+ item->add_button(3, get_icon("Del","EditorIcons"), BUTTON_DELETE);
+ item->set_selectable(3, false);
+ }
+
+ updating_autoload = false;
+}
+
+Variant EditorAutoloadSettings::get_drag_data_fw(const Point2& p_point, Control *p_control) {
+
+ if (autoload_cache.size() <= 1)
+ return false;
+
+ PoolStringArray autoloads;
+
+ TreeItem *next = tree->get_next_selected(NULL);
+
+ while (next) {
+ autoloads.push_back(next->get_text(0));
+ next = tree->get_next_selected(next);
+ }
+
+ if (autoloads.size() == 0 || autoloads.size() == autoload_cache.size())
+ return Variant();
+
+ VBoxContainer *preview = memnew( VBoxContainer );
+
+ int max_size = MIN(PREVIEW_LIST_MAX_SIZE, autoloads.size());
+
+ for (int i = 0; i < max_size; i++) {
+ Label *label = memnew( Label(autoloads[i]) );
+ label->set_self_modulate(Color(1,1,1,Math::lerp(1, 0, float(i)/PREVIEW_LIST_MAX_SIZE)));
+
+ preview->add_child(label);
+ }
+
+ tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+ tree->set_drag_preview(preview);
+
+ Dictionary drop_data;
+ drop_data["type"] = "autoload";
+ drop_data["autoloads"] = autoloads;
+
+ return drop_data;
+}
+
+bool EditorAutoloadSettings::can_drop_data_fw(const Point2& p_point, const Variant& p_data, Control *p_control) const {
+ if (updating_autoload)
+ return false;
+
+ Dictionary drop_data = p_data;
+
+ if (!drop_data.has("type"))
+ return false;
+
+ if (drop_data.has("type")) {
+ TreeItem *ti = tree->get_item_at_pos(p_point);
+
+ if (!ti)
+ return false;
+
+ int section = tree->get_drop_section_at_pos(p_point);
+
+ if (section < -1)
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+void EditorAutoloadSettings::drop_data_fw(const Point2& p_point, const Variant& p_data, Control *p_control) {
+
+ TreeItem *ti = tree->get_item_at_pos(p_point);
+
+ if (!ti)
+ return;
+
+ int section = tree->get_drop_section_at_pos(p_point);
+
+ if (section < -1)
+ return;
+
+ String name;
+ bool move_to_back = false;
+
+ if (section < 0) {
+ name = ti->get_text(0);
+ } else if (ti->get_next()) {
+ name = ti->get_next()->get_text(0);
+ } else {
+ name = ti->get_text(0);
+ move_to_back = true;
+ }
+
+ int order = GlobalConfig::get_singleton()->get_order("autoload/" + name);
+
+ AutoLoadInfo aux;
+ List<AutoLoadInfo>::Element *E = NULL;
+
+ if (!move_to_back) {
+ aux.order = order;
+ E = autoload_cache.find(aux);
+ }
+
+ Dictionary drop_data = p_data;
+ PoolStringArray autoloads = drop_data["autoloads"];
+
+ Vector<int> orders;
+ orders.resize(autoload_cache.size());
+
+ for (int i = 0; i < autoloads.size(); i++) {
+ aux.order = GlobalConfig::get_singleton()->get_order("autoload/" + autoloads[i]);
+
+ List<AutoLoadInfo>::Element *I = autoload_cache.find(aux);
+
+ if (move_to_back) {
+ autoload_cache.move_to_back(I);
+ } else if (E != I) {
+ autoload_cache.move_before(I, E);
+ } else if (E->next()) {
+ E = E->next();
+ } else {
+ break;
+ }
+ }
+
+ int i = 0;
+
+ for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
+ orders[i++] = E->get().order;
+ }
+
+ orders.sort();
+
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
+
+ undo_redo->create_action(TTR("Rearrange Autoloads"));
+
+ i = 0;
+
+ for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
+ undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", E->get().name, orders[i++]);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", E->get().name, E->get().order);
+ }
+
+ orders.clear();
+
+ undo_redo->add_do_method(this, "update_autoload");
+ undo_redo->add_undo_method(this, "update_autoload");
+
+ undo_redo->add_do_method(this, "emit_signal", autoload_changed);
+ undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
+
+ undo_redo->commit_action();
+}
+
+void EditorAutoloadSettings::_bind_methods() {
+
+ ClassDB::bind_method("_autoload_add", &EditorAutoloadSettings::_autoload_add);
+ ClassDB::bind_method("_autoload_selected", &EditorAutoloadSettings::_autoload_selected);
+ ClassDB::bind_method("_autoload_edited", &EditorAutoloadSettings::_autoload_edited);
+ ClassDB::bind_method("_autoload_button_pressed", &EditorAutoloadSettings::_autoload_button_pressed);
+ ClassDB::bind_method("_autoload_file_callback", &EditorAutoloadSettings::_autoload_file_callback);
+
+ ClassDB::bind_method("get_drag_data_fw", &EditorAutoloadSettings::get_drag_data_fw);
+ ClassDB::bind_method("can_drop_data_fw", &EditorAutoloadSettings::can_drop_data_fw);
+ ClassDB::bind_method("drop_data_fw", &EditorAutoloadSettings::drop_data_fw);
+
+ ClassDB::bind_method("update_autoload", &EditorAutoloadSettings::update_autoload);
+
+ ADD_SIGNAL(MethodInfo("autoload_changed"));
+}
+
+EditorAutoloadSettings::EditorAutoloadSettings() {
+
+ autoload_changed = "autoload_changed";
+
+ updating_autoload = false;
+ selected_autoload = "";
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ add_child(hbc);
+
+ VBoxContainer *vbc_path = memnew( VBoxContainer );
+ vbc_path->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ autoload_add_path = memnew( EditorLineEditFileChooser );
+ autoload_add_path->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ autoload_add_path->get_file_dialog()->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ autoload_add_path->get_file_dialog()->connect("file_selected", this, "_autoload_file_callback");
+
+ vbc_path->add_margin_child(TTR("Path:"), autoload_add_path);
+ hbc->add_child(vbc_path);
+
+ VBoxContainer *vbc_name = memnew( VBoxContainer );
+ vbc_name->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *hbc_name = memnew( HBoxContainer );
+
+ autoload_add_name = memnew( LineEdit );
+ autoload_add_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc_name->add_child(autoload_add_name);
+
+ Button *add_autoload = memnew( Button );
+ add_autoload->set_text(TTR("Add"));
+ hbc_name->add_child(add_autoload);
+ add_autoload->connect("pressed", this, "_autoload_add");
+
+ vbc_name->add_margin_child(TTR("Node Name:"), hbc_name);
+ hbc->add_child(vbc_name);
+
+ tree = memnew( Tree );
+ tree->set_hide_root(true);
+ tree->set_select_mode(Tree::SELECT_MULTI);
+ tree->set_single_select_cell_editing_only_when_already_selected(true);
+
+ tree->set_drag_forwarding(this);
+
+ tree->set_columns(4);
+ tree->set_column_titles_visible(true);
+
+ tree->set_column_title(0,TTR("Name"));
+ tree->set_column_expand(0,true);
+ tree->set_column_min_width(0,100);
+
+ tree->set_column_title(1,TTR("Path"));
+ tree->set_column_expand(1,true);
+ tree->set_column_min_width(1,100);
+
+ tree->set_column_title(2,TTR("Singleton"));
+ tree->set_column_expand(2,false);
+ tree->set_column_min_width(2,80);
+
+ tree->set_column_expand(3,false);
+ tree->set_column_min_width(3,80);
+
+ tree->connect("cell_selected", this, "_autoload_selected");
+ tree->connect("item_edited", this, "_autoload_edited");
+ tree->connect("button_pressed", this, "_autoload_button_pressed");
+
+ add_margin_child(TTR("List:"), tree, true);
+}
+
diff --git a/tools/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h
index 2afe239000..2afe239000 100644
--- a/tools/editor/editor_autoload_settings.h
+++ b/editor/editor_autoload_settings.h
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
new file mode 100644
index 0000000000..d2fa40e08c
--- /dev/null
+++ b/editor/editor_data.cpp
@@ -0,0 +1,979 @@
+/*************************************************************************/
+/* editor_data.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_data.h"
+
+#include "global_config.h"
+#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() {
+
+ for(int i=0;i<history.size();i++) {
+
+ bool fail=false;
+
+ for(int j=0;j<history[i].path.size();j++) {
+ if (!history[i].path[j].ref.is_null())
+ continue;
+
+ if (ObjectDB::get_instance(history[i].path[j].object))
+ continue; //has isntance, try next
+
+ if (j<=history[i].level) {
+ //before or equal level, complete fail
+ fail=true;
+ } else {
+ //after level, clip
+ history[i].path.resize(j);
+ }
+
+ break;
+ }
+
+ if (fail) {
+ history.remove(i);
+ i--;
+ }
+ }
+
+ if (current>=history.size())
+ current=history.size()-1;
+}
+
+void EditorHistory::_add_object(ObjectID p_object,const String& p_property,int p_level_change) {
+
+ Object *obj = ObjectDB::get_instance(p_object);
+ ERR_FAIL_COND(!obj);
+ Reference *r = obj->cast_to<Reference>();
+ Obj o;
+ if (r)
+ o.ref=REF(r);
+ o.object=p_object;
+ o.property=p_property;
+
+ History h;
+
+ bool has_prev = current>=0 && current<history.size();
+
+ if (has_prev) {
+ history.resize(current+1); //clip history to next
+ }
+
+ if (p_property!="" && has_prev) {
+ //add a sub property
+ History &pr = history[current];
+ h=pr;
+ h.path.resize(h.level+1);
+ h.path.push_back(o);
+ h.level++;
+ } else if (p_level_change!=-1 && has_prev) {
+ //add a sub property
+ History &pr = history[current];
+ h=pr;
+ ERR_FAIL_INDEX(p_level_change,h.path.size());
+ h.level=p_level_change;
+ } else {
+ //add a new node
+ h.path.push_back(o);
+ h.level=0;
+ }
+
+ history.push_back(h);
+ current++;
+}
+
+void EditorHistory::add_object(ObjectID p_object) {
+
+ _add_object(p_object,"",-1);
+}
+
+void EditorHistory::add_object(ObjectID p_object,const String& p_subprop) {
+
+ _add_object(p_object,p_subprop,-1);
+}
+
+void EditorHistory::add_object(ObjectID p_object,int p_relevel){
+
+ _add_object(p_object,"",p_relevel);
+}
+
+int EditorHistory::get_history_len() {
+ return history.size();
+}
+int EditorHistory::get_history_pos() {
+ return current;
+}
+
+ObjectID EditorHistory::get_history_obj(int p_obj) const {
+ ERR_FAIL_INDEX_V(p_obj,history.size(),0);
+ ERR_FAIL_INDEX_V(history[p_obj].level,history[p_obj].path.size(),0);
+ return history[p_obj].path[history[p_obj].level].object;
+}
+
+bool EditorHistory::is_at_begining() const {
+ return current<=0;
+}
+bool EditorHistory::is_at_end() const {
+
+ return ((current+1)>=history.size());
+}
+
+
+bool EditorHistory::next() {
+
+
+ _cleanup_history();
+
+ if ((current+1)<history.size())
+ current++;
+ else
+ return false;
+
+ return true;
+}
+
+bool EditorHistory::previous() {
+
+
+ _cleanup_history();
+
+ if (current>0)
+ current--;
+ else
+ return false;
+
+ return true;
+}
+
+ObjectID EditorHistory::get_current() {
+
+
+ if (current<0 || current >=history.size())
+ return 0;
+
+ History &h=history[current];
+ Object *obj = ObjectDB::get_instance(h.path[h.level].object);
+ if (!obj)
+ return 0;
+
+ return obj->get_instance_ID();
+}
+
+int EditorHistory::get_path_size() const {
+
+ if (current<0 || current >=history.size())
+ return 0;
+
+ const History &h=history[current];
+ return h.path.size();
+
+}
+
+ObjectID EditorHistory::get_path_object(int p_index) const {
+
+ if (current<0 || current >=history.size())
+ return 0;
+
+ const History &h=history[current];
+
+ ERR_FAIL_INDEX_V(p_index,h.path.size(),0);
+
+ Object *obj = ObjectDB::get_instance(h.path[p_index].object);
+ if (!obj)
+ return 0;
+
+ return obj->get_instance_ID();
+}
+
+String EditorHistory::get_path_property(int p_index) const {
+
+ if (current<0 || current >=history.size())
+ return "";
+
+ const History &h=history[current];
+
+ ERR_FAIL_INDEX_V(p_index,h.path.size(),"");
+
+ return h.path[p_index].property;
+
+}
+
+void EditorHistory::clear() {
+
+ history.clear();
+ current=-1;
+}
+
+EditorHistory::EditorHistory() {
+
+ current=-1;
+}
+
+EditorPlugin* EditorData::get_editor(Object *p_object) {
+
+ for (int i=0;i<editor_plugins.size();i++) {
+
+ if (editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object))
+ return editor_plugins[i];
+ }
+
+ return NULL;
+}
+
+EditorPlugin* EditorData::get_subeditor(Object *p_object) {
+
+ for (int i=0;i<editor_plugins.size();i++) {
+
+ if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object))
+ return editor_plugins[i];
+ }
+
+ return NULL;
+}
+
+Vector<EditorPlugin*> EditorData::get_subeditors(Object* p_object) {
+ Vector<EditorPlugin*> sub_plugins;
+ for (int i = 0; i < editor_plugins.size(); i++) {
+ if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object)) {
+ sub_plugins.push_back(editor_plugins[i]);
+ }
+ }
+ return sub_plugins;
+}
+
+EditorPlugin* EditorData::get_editor(String p_name) {
+
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ if (editor_plugins[i]->get_name()==p_name)
+ return editor_plugins[i];
+ }
+
+ return NULL;
+}
+
+void EditorData::copy_object_params(Object *p_object) {
+
+ clipboard.clear();
+
+ List<PropertyInfo> pinfo;
+ p_object->get_property_list(&pinfo);
+
+ for( List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ if (!(E->get().usage&PROPERTY_USAGE_EDITOR))
+ continue;
+
+ PropertyData pd;
+ pd.name=E->get().name;
+ pd.value=p_object->get(pd.name);
+ clipboard.push_back(pd);
+ }
+}
+
+void EditorData::get_editor_breakpoints(List<String> *p_breakpoints) {
+
+
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ editor_plugins[i]->get_breakpoints(p_breakpoints);
+ }
+
+
+}
+
+Dictionary EditorData::get_editor_states() const {
+
+ Dictionary metadata;
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ Dictionary state=editor_plugins[i]->get_state();
+ if (state.empty())
+ continue;
+ metadata[editor_plugins[i]->get_name()]=state;
+ }
+
+ return metadata;
+
+}
+
+Dictionary EditorData::get_scene_editor_states(int p_idx) const
+{
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),Dictionary());
+ EditedScene es = edited_scene[p_idx];
+ return es.editor_states;
+}
+
+void EditorData::set_editor_states(const Dictionary& p_states) {
+
+ List<Variant> keys;
+ p_states.get_key_list(&keys);
+
+ List<Variant>::Element *E=keys.front();
+ for(;E;E=E->next()) {
+
+ String name = E->get();
+ int idx=-1;
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ if (editor_plugins[i]->get_name()==name) {
+ idx=i;
+ break;
+ }
+ }
+
+ if (idx==-1)
+ continue;
+ editor_plugins[idx]->set_state(p_states[name]);
+ }
+
+}
+
+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++) {
+
+ editor_plugins[i]->clear();
+ }
+
+}
+
+void EditorData::save_editor_external_data() {
+
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ editor_plugins[i]->save_external_data();
+ }
+}
+
+void EditorData::apply_changes_in_editors() {
+
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ editor_plugins[i]->apply_changes();
+ }
+
+}
+
+void EditorData::save_editor_global_states() {
+
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ editor_plugins[i]->save_global_state();
+ }
+}
+
+void EditorData::restore_editor_global_states(){
+
+ for(int i=0;i<editor_plugins.size();i++) {
+
+ editor_plugins[i]->restore_global_state();
+ }
+
+}
+
+
+void EditorData::paste_object_params(Object *p_object) {
+
+
+ for( List<PropertyData>::Element *E=clipboard.front();E;E=E->next()) {
+
+ p_object->set( E->get().name, E->get().value);
+ }
+
+}
+
+
+UndoRedo &EditorData::get_undo_redo() {
+
+ return undo_redo;
+}
+
+void EditorData::remove_editor_plugin(EditorPlugin *p_plugin) {
+
+ p_plugin->undo_redo=NULL;
+ editor_plugins.erase(p_plugin);
+
+}
+
+void EditorData::add_editor_plugin(EditorPlugin *p_plugin) {
+
+ p_plugin->undo_redo=&undo_redo;
+ editor_plugins.push_back(p_plugin);
+}
+
+int EditorData::get_editor_plugin_count() const {
+ return editor_plugins.size();
+}
+EditorPlugin *EditorData::get_editor_plugin(int p_idx) {
+
+ ERR_FAIL_INDEX_V(p_idx,editor_plugins.size(),NULL);
+ return editor_plugins[p_idx];
+}
+
+
+void EditorData::add_custom_type(const String& p_type, const String& p_inherits,const Ref<Script>& p_script,const Ref<Texture>& p_icon ) {
+
+ ERR_FAIL_COND(p_script.is_null());
+ CustomType ct;
+ ct.name=p_type;
+ ct.icon=p_icon;
+ ct.script=p_script;
+ if (!custom_types.has(p_inherits)) {
+ custom_types[p_inherits]=Vector<CustomType>();
+ }
+
+ custom_types[p_inherits].push_back(ct);
+}
+
+void EditorData::remove_custom_type(const String& p_type){
+
+
+ for (Map<String,Vector<CustomType> >::Element *E=custom_types.front();E;E=E->next()) {
+
+ for(int i=0;i<E->get().size();i++) {
+ if (E->get()[i].name==p_type) {
+ E->get().remove(i);
+ if (E->get().empty()) {
+ custom_types.erase(E->key());
+ }
+ return;
+ }
+ }
+ }
+
+}
+
+int EditorData::add_edited_scene(int p_at_pos) {
+
+ if (p_at_pos<0)
+ p_at_pos=edited_scene.size();
+ EditedScene es;
+ es.root=NULL;
+ es.history_current=-1;
+ es.version=0;
+ es.live_edit_root=NodePath(String("/root"));
+
+ if (p_at_pos==edited_scene.size())
+ edited_scene.push_back(es);
+ else
+ edited_scene.insert(p_at_pos,es);
+
+ if (current_edited_scene<0)
+ current_edited_scene=0;
+ return p_at_pos;
+}
+
+void EditorData::move_edited_scene_index(int p_idx,int p_to_idx){
+
+ ERR_FAIL_INDEX(p_idx,edited_scene.size());
+ ERR_FAIL_INDEX(p_to_idx,edited_scene.size());
+ SWAP(edited_scene[p_idx],edited_scene[p_to_idx]);
+}
+void EditorData::remove_scene(int p_idx){
+ ERR_FAIL_INDEX(p_idx,edited_scene.size());
+ if (edited_scene[p_idx].root)
+ memdelete(edited_scene[p_idx].root);
+
+ if (current_edited_scene>p_idx)
+ current_edited_scene--;
+ else if (current_edited_scene==p_idx && current_edited_scene>0) {
+ current_edited_scene--;
+ }
+
+ 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);
+
+ print_line("MUST RELOAD? "+itos(must_reload));
+
+ if (must_reload) {
+ Ref<PackedScene> pscene;
+ pscene.instance();
+
+ EditorProgress ep("update_scene",TTR("Updating Scene"),2);
+ ep.step(TTR("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(TTR("Updating scene.."),1);
+ Node *new_scene = pscene->instance(PackedScene::GEN_EDIT_STATE_MAIN);
+ 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;
+}
+void EditorData::set_edited_scene(int p_idx){
+
+ ERR_FAIL_INDEX(p_idx,edited_scene.size());
+ current_edited_scene=p_idx;
+ //swap
+}
+Node* EditorData::get_edited_scene_root(int p_idx){
+ if (p_idx < 0) {
+ ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),NULL);
+ return edited_scene[current_edited_scene].root;
+ } else {
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),NULL);
+ return edited_scene[p_idx].root;
+ }
+}
+void EditorData::set_edited_scene_root(Node* p_root) {
+
+ ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+ edited_scene[current_edited_scene].root=p_root;
+}
+
+int EditorData::get_edited_scene_count() const {
+
+ return edited_scene.size();
+}
+
+void EditorData::set_edited_scene_version(uint64_t version, int scene_idx) {
+ ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+ if (scene_idx < 0) {
+ edited_scene[current_edited_scene].version=version;
+ } else {
+ ERR_FAIL_INDEX(scene_idx,edited_scene.size());
+ edited_scene[scene_idx].version=version;
+ }
+
+}
+
+uint64_t EditorData::get_edited_scene_version() const{
+
+ ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),0);
+ return edited_scene[current_edited_scene].version;
+
+}
+uint64_t EditorData::get_scene_version(int p_idx) const{
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),false);
+ return edited_scene[p_idx].version;
+}
+
+String EditorData::get_scene_type(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
+ if (!edited_scene[p_idx].root)
+ return "";
+ return edited_scene[p_idx].root->get_class();
+
+}
+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 {
+
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),Ref<Script>());
+ if (!edited_scene[p_idx].root)
+ return Ref<Script>();
+ Ref<Script> s=edited_scene[p_idx].root->get_script();
+ if (!s.is_valid() && edited_scene[p_idx].root->get_child_count()) {
+ Node *n = edited_scene[p_idx].root->get_child(0);
+ while(!s.is_valid() && n && n->get_filename()==String()) {
+ s=n->get_script();
+ n=n->get_parent();
+ }
+ }
+ return s;
+}
+
+String EditorData::get_scene_title(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
+ if (!edited_scene[p_idx].root)
+ return "[empty]";
+ if (edited_scene[p_idx].root->get_filename()=="")
+ return "[unsaved]";
+ return edited_scene[p_idx].root->get_filename().get_file();
+}
+
+
+String EditorData::get_scene_path(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
+
+ if (!edited_scene[p_idx].root)
+ return "";
+ return edited_scene[p_idx].root->get_filename();
+
+}
+
+void EditorData::set_edited_scene_live_edit_root(const NodePath& p_root) {
+ ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+
+ edited_scene[current_edited_scene].live_edit_root=p_root;
+
+}
+NodePath EditorData::get_edited_scene_live_edit_root() {
+
+ ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),String());
+
+ return edited_scene[current_edited_scene].live_edit_root;
+
+
+
+}
+
+
+void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history, const Dictionary& p_custom) {
+
+ ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
+
+ EditedScene &es=edited_scene[current_edited_scene];
+ es.selection = p_selection->get_selected_node_list();
+ es.history_current=p_history->current;
+ es.history_stored=p_history->history;
+ es.editor_states=get_editor_states();
+ es.custom_state=p_custom;
+
+}
+
+Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history) {
+ ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),Dictionary());
+
+ EditedScene &es=edited_scene[current_edited_scene];
+
+ p_history->current=es.history_current;
+ p_history->history=es.history_stored;
+
+
+ p_selection->clear();
+ for(List<Node*>::Element *E=es.selection.front();E;E=E->next()) {
+ p_selection->add_node(E->get());
+ }
+ set_editor_states(es.editor_states);
+
+ return es.custom_state;
+}
+
+
+void EditorData::clear_edited_scenes() {
+
+ for(int i=0;i<edited_scene.size();i++) {
+ if (edited_scene[i].root) {
+ memdelete( edited_scene[i].root );
+ }
+ }
+ edited_scene.clear();
+}
+
+
+
+void EditorData::set_plugin_window_layout(Ref<ConfigFile> p_layout) {
+ for(int i=0;i<editor_plugins.size();i++) {
+ editor_plugins[i]->set_window_layout(p_layout);
+ }
+}
+
+void EditorData::get_plugin_window_layout(Ref<ConfigFile> p_layout) {
+ for(int i=0;i<editor_plugins.size();i++) {
+ editor_plugins[i]->get_window_layout(p_layout);
+ }
+}
+
+EditorData::EditorData() {
+
+ current_edited_scene=-1;
+
+ //load_imported_scenes_from_globals();
+}
+
+///////////
+void EditorSelection::_node_removed(Node *p_node) {
+
+ if (!selection.has(p_node))
+ return;
+
+ Object *meta = selection[p_node];
+ if (meta)
+ memdelete(meta);
+ selection.erase(p_node);
+ changed=true;
+ nl_changed=true;
+}
+
+void EditorSelection::add_node(Node *p_node) {
+
+ ERR_FAIL_NULL(p_node);
+ ERR_FAIL_COND(!p_node->is_inside_tree());
+ if (selection.has(p_node))
+ return;
+
+ changed=true;
+ nl_changed=true;
+ Object *meta=NULL;
+ for(List<Object*>::Element *E=editor_plugins.front();E;E=E->next()) {
+
+ meta = E->get()->call("_get_editor_data",p_node);
+ if (meta) {
+ break;
+ }
+
+ }
+ selection[p_node]=meta;
+
+ p_node->connect("tree_exited",this,"_node_removed",varray(p_node),CONNECT_ONESHOT);
+
+ //emit_signal("selection_changed");
+}
+
+void EditorSelection::remove_node(Node *p_node) {
+
+ ERR_FAIL_NULL(p_node);
+
+ if (!selection.has(p_node))
+ return;
+
+ changed=true;
+ nl_changed=true;
+ Object *meta = selection[p_node];
+ if (meta)
+ memdelete(meta);
+ selection.erase(p_node);
+ p_node->disconnect("tree_exited",this,"_node_removed");
+ //emit_signal("selection_changed");
+}
+bool EditorSelection::is_selected(Node * p_node) const {
+
+ return selection.has(p_node);
+}
+
+Array EditorSelection::_get_transformable_selected_nodes() {
+
+ Array ret;
+
+ for (List<Node*>::Element *E=selected_node_list.front();E;E=E->next()) {
+
+ ret.push_back(E->get());
+ }
+
+ return ret;
+}
+
+Array EditorSelection::_get_selected_nodes() {
+
+ Array ret;
+
+ for (Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ ret.push_back(E->key());
+ }
+
+ return ret;
+}
+
+void EditorSelection::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_node_removed"),&EditorSelection::_node_removed);
+ ClassDB::bind_method(D_METHOD("clear"),&EditorSelection::clear);
+ ClassDB::bind_method(D_METHOD("add_node","node:Node"),&EditorSelection::add_node);
+ ClassDB::bind_method(D_METHOD("remove_node","node:Node"),&EditorSelection::remove_node);
+ ClassDB::bind_method(D_METHOD("get_selected_nodes"),&EditorSelection::_get_selected_nodes);
+ ClassDB::bind_method(D_METHOD("get_transformable_selected_nodes"),&EditorSelection::_get_transformable_selected_nodes);
+ ADD_SIGNAL( MethodInfo("selection_changed") );
+
+}
+
+void EditorSelection::add_editor_plugin(Object *p_object) {
+
+ editor_plugins.push_back(p_object);
+}
+
+void EditorSelection::_update_nl() {
+
+ if (!nl_changed)
+ return;
+
+ selected_node_list.clear();
+
+ for (Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+
+ Node *parent = E->key();
+ parent=parent->get_parent();
+ bool skip=false;
+ while (parent) {
+ if (selection.has(parent)) {
+ skip=true;
+ break;
+ }
+ parent=parent->get_parent();
+ }
+
+ if (skip)
+ continue;
+ selected_node_list.push_back(E->key());
+ }
+
+ nl_changed=true;
+}
+
+void EditorSelection::update() {
+
+ _update_nl();
+
+ if (!changed)
+ return;
+ emit_signal("selection_changed");
+ changed=false;
+
+
+}
+
+List<Node*>& EditorSelection::get_selected_node_list() {
+
+ if (changed)
+ update();
+ else
+ _update_nl();
+ return selected_node_list;
+}
+
+
+
+
+void EditorSelection::clear() {
+
+ while( !selection.empty() ) {
+
+ remove_node(selection.front()->key());
+ }
+
+
+ changed=true;
+ nl_changed=true;
+
+}
+EditorSelection::EditorSelection() {
+
+ changed=false;
+ nl_changed=false;
+
+}
+
+EditorSelection::~EditorSelection() {
+
+ clear();
+}
diff --git a/editor/editor_data.h b/editor/editor_data.h
new file mode 100644
index 0000000000..4622791653
--- /dev/null
+++ b/editor/editor_data.h
@@ -0,0 +1,269 @@
+/*************************************************************************/
+/* editor_data.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_DATA_H
+#define EDITOR_DATA_H
+
+#include "editor/editor_plugin.h"
+#include "scene/resources/texture.h"
+#include "list.h"
+#include "undo_redo.h"
+#include "pair.h"
+
+class EditorHistory {
+
+ enum {
+
+ HISTORY_MAX=64
+ };
+
+ struct Obj {
+
+ REF ref;
+ ObjectID object;
+ String property;
+ };
+
+ struct History {
+
+ Vector<Obj> path;
+ int level;
+ };
+friend class EditorData;
+
+ Vector<History> history;
+ int current;
+
+ //Vector<EditorPlugin*> editor_plugins;
+
+ struct PropertyData {
+
+ String name;
+ Variant value;
+ };
+
+
+ void _cleanup_history();
+
+ void _add_object(ObjectID p_object,const String& p_property,int p_level_change);
+
+public:
+
+ bool is_at_begining() const;
+ bool is_at_end() const;
+
+ void add_object(ObjectID p_object);
+ void add_object(ObjectID p_object,const String& p_subprop);
+ void add_object(ObjectID p_object,int p_relevel);
+
+ int get_history_len();
+ int get_history_pos();
+ ObjectID get_history_obj(int p_obj) const;
+
+ bool next();
+ bool previous();
+ ObjectID get_current();
+
+ int get_path_size() const;
+ ObjectID get_path_object(int p_index) const;
+ String get_path_property(int p_index) const;
+
+ void clear();
+
+ EditorHistory();
+};
+
+class EditorSelection;
+
+class EditorData {
+
+public:
+ struct CustomType {
+
+ String name;
+ Ref<Script> script;
+ Ref<Texture> icon;
+ };
+private:
+
+ Vector<EditorPlugin*> editor_plugins;
+
+ struct PropertyData {
+
+ String name;
+ Variant value;
+ };
+ Map<String,Vector<CustomType> > custom_types;
+
+ List<PropertyData> clipboard;
+ UndoRedo undo_redo;
+
+
+ void _cleanup_history();
+
+ struct EditedScene {
+ Node* root;
+ Dictionary editor_states;
+ List<Node*> selection;
+ Vector<EditorHistory::History> history_stored;
+ int history_current;
+ Dictionary custom_state;
+ uint64_t version;
+ NodePath live_edit_root;
+
+
+ };
+
+ 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);
+ EditorPlugin* get_subeditor(Object *p_object);
+ Vector<EditorPlugin*> get_subeditors(Object *p_object);
+ EditorPlugin* get_editor(String p_name);
+
+ void copy_object_params(Object *p_object);
+ void paste_object_params(Object *p_object);
+
+ Dictionary get_editor_states() const;
+ Dictionary get_scene_editor_states(int p_idx) const;
+ void set_editor_states(const Dictionary& p_states);
+ void get_editor_breakpoints(List<String> *p_breakpoints);
+ void clear_editor_states();
+ void save_editor_external_data();
+ void apply_changes_in_editors();
+
+ void add_editor_plugin(EditorPlugin *p_plugin);
+ void remove_editor_plugin(EditorPlugin *p_plugin);
+
+ int get_editor_plugin_count() const;
+ EditorPlugin *get_editor_plugin(int p_idx);
+
+ UndoRedo &get_undo_redo();
+
+ void save_editor_global_states();
+ void restore_editor_global_states();
+
+ void add_custom_type(const String& p_type, const String& p_inherits,const Ref<Script>& p_script,const Ref<Texture>& p_icon );
+ void remove_custom_type(const String& p_type);
+ const Map<String,Vector<CustomType> >& get_custom_types() const { return custom_types; }
+
+
+ int add_edited_scene(int p_at_pos);
+ void move_edited_scene_index(int p_idx,int p_to_idx);
+ void remove_scene(int p_idx);
+ void set_edited_scene(int p_idx);
+ void set_edited_scene_root(Node* p_root);
+ int get_edited_scene() const;
+ Node* get_edited_scene_root(int p_idx = -1);
+ int get_edited_scene_count() const;
+ String get_scene_title(int p_idx) const;
+ String get_scene_path(int p_idx) const;
+ String get_scene_type(int p_idx) const;
+ Ref<Script> get_scene_root_script(int p_idx) const;
+ void set_edited_scene_version(uint64_t version, int p_scene_idx = -1);
+ uint64_t get_edited_scene_version() const;
+ uint64_t get_scene_version(int p_idx) const;
+ 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);
+ void get_plugin_window_layout(Ref<ConfigFile> p_layout);
+
+ 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();
+};
+
+
+
+class EditorSelection : public Object {
+
+ GDCLASS(EditorSelection,Object);
+public:
+
+ Map<Node*,Object*> selection;
+
+ bool changed;
+ bool nl_changed;
+
+ void _node_removed(Node *p_node);
+
+ List<Object*> editor_plugins;
+ List<Node*> selected_node_list;
+
+ void _update_nl();
+ Array _get_selected_nodes();
+ Array _get_transformable_selected_nodes();
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ void add_node(Node *p_node);
+ void remove_node(Node *p_node);
+ bool is_selected(Node *) const;
+
+ template<class T>
+ T* get_node_editor_data(Node *p_node) {
+ if (!selection.has(p_node))
+ return NULL;
+ Object *obj = selection[p_node];
+ if (!obj)
+ return NULL;
+ return obj->cast_to<T>();
+ }
+
+ void add_editor_plugin(Object *p_object);
+
+ void update();
+ void clear();
+
+
+ List<Node*>& get_selected_node_list();
+ Map<Node*,Object*>& get_selection() { return selection; }
+
+
+ EditorSelection();
+ ~EditorSelection();
+};
+
+
+#endif // EDITOR_DATA_H
diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp
new file mode 100644
index 0000000000..235d1f06ba
--- /dev/null
+++ b/editor/editor_dir_dialog.cpp
@@ -0,0 +1,276 @@
+/*************************************************************************/
+/* editor_dir_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_dir_dialog.h"
+
+#include "os/os.h"
+#include "os/keyboard.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_file_system.h"
+
+
+void EditorDirDialog::_update_dir(TreeItem* p_item) {
+
+ updating=true;
+ p_item->clear_children();
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ String cdir = p_item->get_metadata(0);
+
+ da->change_dir(cdir);
+ da->list_dir_begin();
+ String p=da->get_next();
+
+ List<String> dirs;
+ bool ishidden;
+ bool show_hidden = EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files");
+
+ while(p!="") {
+
+ ishidden = da->current_is_hidden();
+
+ if (show_hidden || !ishidden) {
+ if (da->current_is_dir() && !p.begins_with(".")) {
+ dirs.push_back(p);
+ }
+ }
+ p=da->get_next();
+ }
+
+ dirs.sort();
+
+ for(List<String>::Element *E=dirs.front();E;E=E->next()) {
+ TreeItem *ti = tree->create_item(p_item);
+ ti->set_text(0,E->get());
+ ti->set_icon(0,get_icon("Folder","EditorIcons"));
+ ti->set_collapsed(true);
+
+ }
+
+ memdelete(da);
+ updating=false;
+
+}
+
+
+void EditorDirDialog::reload() {
+
+ if (!is_visible_in_tree()) {
+ must_reload=true;
+ return;
+ }
+
+ tree->clear();
+ TreeItem *root = tree->create_item();
+ root->set_metadata(0,"res://");
+ root->set_icon(0,get_icon("Folder","EditorIcons"));
+ root->set_text(0,"/");
+ _update_dir(root);
+ _item_collapsed(root);
+ must_reload=false;
+
+}
+
+
+void EditorDirDialog::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ reload();
+
+ if (!tree->is_connected("item_collapsed",this,"_item_collapsed")) {
+ tree->connect("item_collapsed",this,"_item_collapsed",varray(),CONNECT_DEFERRED);
+ }
+
+ if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed",this,"reload")) {
+ EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"reload");
+ }
+
+ }
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+ if (must_reload && is_visible_in_tree()) {
+ reload();
+ }
+ }
+}
+
+void EditorDirDialog::_item_collapsed(Object* _p_item){
+
+ TreeItem *p_item=_p_item->cast_to<TreeItem>();
+
+ if (updating || p_item->is_collapsed())
+ return;
+
+ TreeItem *ci = p_item->get_children();
+ while(ci) {
+
+ String p =ci->get_metadata(0);
+ if (p=="") {
+ String pp = p_item->get_metadata(0);
+ ci->set_metadata(0,pp.plus_file(ci->get_text(0)));
+ _update_dir(ci);
+ }
+ ci=ci->get_next();
+ }
+
+}
+
+void EditorDirDialog::set_current_path(const String& p_path) {
+
+ reload();
+ String p = p_path;
+ if (p.begins_with("res://"))
+ p = p.replace_first("res://","");
+
+ Vector<String> dirs = p.split("/",false);
+
+ TreeItem *r=tree->get_root();
+ for(int i=0;i<dirs.size();i++) {
+
+ String d = dirs[i];
+ TreeItem *p = r->get_children();
+ while(p) {
+
+ if (p->get_text(0)==d)
+ break;
+ p=p->get_next();
+ }
+
+ ERR_FAIL_COND(!p);
+ String pp = p->get_metadata(0);
+ if (pp=="") {
+ p->set_metadata(0,String(r->get_metadata(0)).plus_file(d));
+ _update_dir(p);
+ }
+ updating=true;
+ p->set_collapsed(false);
+ updating=false;
+ _item_collapsed(p);
+ r=p;
+ }
+
+ r->select(0);
+
+}
+
+void EditorDirDialog::ok_pressed() {
+
+ TreeItem *ti=tree->get_selected();
+ if (!ti)
+ return;
+
+ String dir = ti->get_metadata(0);
+ emit_signal("dir_selected",dir);
+ hide();
+}
+
+
+void EditorDirDialog::_make_dir() {
+
+ TreeItem *ti=tree->get_selected();
+ if (!ti) {
+ mkdirerr->set_text("Please select a base directory first");
+ mkdirerr->popup_centered_minsize();
+ return;
+ }
+
+ makedialog->popup_centered_minsize(Size2(250,80));
+ makedirname->grab_focus();
+}
+
+void EditorDirDialog::_make_dir_confirm() {
+
+ TreeItem *ti=tree->get_selected();
+ if (!ti)
+ return;
+
+ String dir = ti->get_metadata(0);
+
+ DirAccess *d = DirAccess::open(dir);
+ ERR_FAIL_COND(!d);
+ Error err = d->make_dir(makedirname->get_text());
+
+ if (err!=OK) {
+ mkdirerr->popup_centered_minsize(Size2(250,80));
+ } else {
+ set_current_path(dir.plus_file(makedirname->get_text()));
+ }
+ makedirname->set_text(""); // reset label
+}
+
+
+void EditorDirDialog::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_item_collapsed"),&EditorDirDialog::_item_collapsed);
+ ClassDB::bind_method(D_METHOD("_make_dir"),&EditorDirDialog::_make_dir);
+ ClassDB::bind_method(D_METHOD("_make_dir_confirm"),&EditorDirDialog::_make_dir_confirm);
+ ClassDB::bind_method(D_METHOD("reload"),&EditorDirDialog::reload);
+
+ ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo(Variant::STRING,"dir")));
+}
+
+
+
+EditorDirDialog::EditorDirDialog() {
+
+ updating=false;
+
+ set_title(TTR("Choose a Directory"));
+ set_hide_on_ok(false);
+
+ tree = memnew( Tree );
+ add_child(tree);
+
+ tree->connect("item_activated",this,"_ok");
+
+ makedir = add_button(TTR("Create Folder"),OS::get_singleton()->get_swap_ok_cancel()?true:false,"makedir");
+ makedir->connect("pressed",this,"_make_dir");
+
+ makedialog = memnew( ConfirmationDialog );
+ makedialog->set_title(TTR("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(TTR("Name:"),makedirname);
+ makedialog->register_text_enter(makedirname);
+ makedialog->connect("confirmed",this,"_make_dir_confirm");
+
+ mkdirerr = memnew( AcceptDialog );
+ mkdirerr->set_text(TTR("Could not create folder."));
+ add_child(mkdirerr);
+
+ get_ok()->set_text(TTR("Choose"));
+
+ must_reload=false;
+
+
+
+}
diff --git a/tools/editor/editor_dir_dialog.h b/editor/editor_dir_dialog.h
index 0577ff0442..0577ff0442 100644
--- a/tools/editor/editor_dir_dialog.h
+++ b/editor/editor_dir_dialog.h
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
new file mode 100644
index 0000000000..f5840d00fb
--- /dev/null
+++ b/editor/editor_export.cpp
@@ -0,0 +1,3231 @@
+/*************************************************************************/
+/* editor_import_export.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_export.h"
+#include "version.h"
+#include "script_language.h"
+#include "global_config.h"
+#include "os/file_access.h"
+#include "os/dir_access.h"
+#include "editor/editor_file_system.h"
+#include "io/resource_loader.h"
+#include "editor_node.h"
+#include "editor_settings.h"
+#include "io/config_file.h"
+#include "io/resource_saver.h"
+#include "io/md5.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "io/zip_io.h"
+
+static int _get_pad(int p_alignment, int p_n) {
+
+ int rest = p_n % p_alignment;
+ int pad = 0;
+ if (rest > 0) {
+ pad = p_alignment - rest;
+ };
+
+ return pad;
+};
+
+#define PCK_PADDING 16
+
+bool EditorExportPreset::_set(const StringName& p_name, const Variant& p_value) {
+
+ if (values.has(p_name)) {
+ values[p_name]=p_value;
+ EditorExport::singleton->save_presets();
+ return true;
+ }
+
+ return false;
+}
+
+bool EditorExportPreset::_get(const StringName& p_name,Variant &r_ret) const{
+
+ if (values.has(p_name)) {
+ r_ret=values[p_name];
+ return true;
+ }
+
+ return false;
+}
+void EditorExportPreset::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ for (const List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
+
+ p_list->push_back(E->get());
+ }
+}
+
+Ref<EditorExportPlatform> EditorExportPreset::get_platform() const {
+
+ return platform;
+}
+
+Vector<String> EditorExportPreset::get_files_to_export() const {
+
+ Vector<String> files;
+ for(Set<String>::Element *E=selected_files.front();E;E=E->next()) {
+ files.push_back(E->get());
+ }
+ return files;
+}
+
+void EditorExportPreset::set_name(const String& p_name) {
+ name=p_name;
+ EditorExport::singleton->save_presets();
+
+}
+
+String EditorExportPreset::get_name() const {
+ return name;
+
+}
+
+void EditorExportPreset::set_runnable(bool p_enable) {
+
+ runnable=p_enable;
+ EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::is_runnable() const {
+
+ return runnable;
+}
+
+void EditorExportPreset::set_export_filter(ExportFilter p_filter) {
+
+ export_filter=p_filter;
+ EditorExport::singleton->save_presets();
+
+}
+
+EditorExportPreset::ExportFilter EditorExportPreset::get_export_filter() const {
+ return export_filter;
+}
+
+void EditorExportPreset::set_include_filter(const String& p_include) {
+
+ include_filter=p_include;
+ EditorExport::singleton->save_presets();
+
+}
+
+String EditorExportPreset::get_include_filter() const {
+
+ return include_filter;
+}
+
+void EditorExportPreset::set_exclude_filter(const String& p_exclude) {
+
+ exclude_filter=p_exclude;
+ EditorExport::singleton->save_presets();
+}
+
+String EditorExportPreset::get_exclude_filter() const {
+
+ return exclude_filter;
+}
+
+void EditorExportPreset::add_export_file(const String& p_path) {
+
+ selected_files.insert(p_path);
+ EditorExport::singleton->save_presets();
+}
+
+void EditorExportPreset::remove_export_file(const String& p_path) {
+ selected_files.erase(p_path);
+ EditorExport::singleton->save_presets();
+}
+
+bool EditorExportPreset::has_export_file(const String& p_path) {
+
+ return selected_files.has(p_path);
+}
+
+void EditorExportPreset::add_patch(const String& p_path,int p_at_pos) {
+
+ if (p_at_pos<0)
+ patches.push_back(p_path);
+ else
+ patches.insert(p_at_pos,p_path);
+ EditorExport::singleton->save_presets();
+}
+
+void EditorExportPreset::remove_patch(int p_idx) {
+ patches.remove(p_idx);
+ EditorExport::singleton->save_presets();
+}
+
+void EditorExportPreset::set_patch(int p_index,const String& p_path) {
+ ERR_FAIL_INDEX(p_index,patches.size());
+ patches[p_index]=p_path;
+ EditorExport::singleton->save_presets();
+}
+String EditorExportPreset::get_patch(int p_index) {
+
+ ERR_FAIL_INDEX_V(p_index,patches.size(),String());
+ return patches[p_index];
+}
+
+Vector<String> EditorExportPreset::get_patches() const {
+ return patches;
+}
+
+EditorExportPreset::EditorExportPreset() {
+
+ export_filter=EXPORT_ALL_RESOURCES;
+ runnable=false;
+}
+
+
+///////////////////////////////////
+
+void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags) {
+
+ String host = EditorSettings::get_singleton()->get("network/debug_host");
+
+ if (p_flags&DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST)
+ host="localhost";
+
+ if (p_flags&DEBUG_FLAG_DUMB_CLIENT) {
+ int port = EditorSettings::get_singleton()->get("filesystem/file_server/port");
+ String passwd = EditorSettings::get_singleton()->get("filesystem/file_server/password");
+ r_flags.push_back("-rfs");
+ r_flags.push_back(host+":"+itos(port));
+ if (passwd!="") {
+ r_flags.push_back("-rfs_pass");
+ r_flags.push_back(passwd);
+ }
+ }
+
+ if (p_flags&DEBUG_FLAG_REMOTE_DEBUG) {
+
+ r_flags.push_back("-rdebug");
+
+ r_flags.push_back(host+":"+String::num(GLOBAL_DEF("network/debug/remote_port", 6007)));
+
+ List<String> breakpoints;
+ ScriptEditor::get_singleton()->get_breakpoints(&breakpoints);
+
+
+ if (breakpoints.size()) {
+
+ r_flags.push_back("-bp");
+ String bpoints;
+ for(const List<String>::Element *E=breakpoints.front();E;E=E->next()) {
+
+ bpoints+=E->get().replace(" ","%20");
+ if (E->next())
+ bpoints+=",";
+ }
+
+ r_flags.push_back(bpoints);
+ }
+
+ }
+
+ if (p_flags&DEBUG_FLAG_VIEW_COLLISONS) {
+
+ r_flags.push_back("-debugcol");
+ }
+
+ if (p_flags&DEBUG_FLAG_VIEW_NAVIGATION) {
+
+ r_flags.push_back("-debugnav");
+ }
+}
+
+Error EditorExportPlatform::_save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
+
+ PackData *pd = (PackData*)p_userdata;
+
+ SavedData sd;
+ sd.path_utf8=p_path.utf8();
+ sd.ofs = pd->f->get_pos();
+ sd.size = p_data.size();
+
+ pd->f->store_buffer(p_data.ptr(),p_data.size());
+ int pad = _get_pad(PCK_PADDING,sd.size);
+ for(int i=0;i<pad;i++) {
+ pd->f->store_8(0);
+ }
+
+ {
+ MD5_CTX ctx;
+ MD5Init(&ctx);
+ MD5Update(&ctx,(unsigned char*)p_data.ptr(),p_data.size());
+ MD5Final(&ctx);
+ sd.md5.resize(16);
+ for(int i=0;i<16;i++) {
+ sd.md5[i]=ctx.digest[i];
+ }
+ }
+
+ pd->file_ofs.push_back(sd);
+
+ pd->ep->step(TTR("Storing File:")+" "+p_path,2+p_file*100/p_total,false);
+
+ return OK;
+}
+
+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(TTR("Storing File:")+" "+p_path,2+p_file*100/p_total,false);
+
+ return OK;
+}
+
+String EditorExportPlatform::find_export_template(String template_file_name, String *err) const {
+
+ String user_file = EditorSettings::get_singleton()->get_settings_path()
+ +"/templates/"+itos(VERSION_MAJOR)+"."+itos(VERSION_MINOR)+"."+_MKSTR(VERSION_STATUS)+"/"+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 "";
+}
+
+Ref<EditorExportPreset> EditorExportPlatform::create_preset() {
+
+ Ref<EditorExportPreset> preset;
+ preset.instance();
+ preset->platform=Ref<EditorExportPlatform>(this);
+
+ List<ExportOption> options;
+ get_export_options(&options);
+
+ for (List<ExportOption>::Element *E=options.front();E;E=E->next()) {
+
+ preset->properties.push_back(E->get().option);
+ preset->values[E->get().option.name]=E->get().default_value;
+ }
+
+ return preset;
+
+}
+
+void EditorExportPlatform::_export_find_resources(EditorFileSystemDirectory *p_dir,Set<String>& p_paths) {
+
+ for(int i=0;i<p_dir->get_subdir_count();i++) {
+ _export_find_resources(p_dir->get_subdir(i),p_paths);
+ }
+
+ for(int i=0;i<p_dir->get_file_count();i++) {
+ p_paths.insert(p_dir->get_file_path(i));
+ }
+}
+
+
+void EditorExportPlatform::_export_find_dependencies(const String& p_path,Set<String>& p_paths) {
+
+ if (p_paths.has(p_path))
+ return;
+
+ p_paths.insert(p_path);
+
+ EditorFileSystemDirectory *dir;
+ int file_idx;
+ dir = EditorFileSystem::get_singleton()->find_file(p_path,&file_idx);
+ if (!dir)
+ return;
+
+ Vector<String> deps = dir->get_file_deps(file_idx);
+
+ for(int i=0;i<deps.size();i++) {
+
+ _export_find_dependencies(deps[i],p_paths);
+ }
+}
+
+
+Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset>& p_preset,EditorExportSaveFunction p_func, void* p_udata) {
+
+ Ref<EditorExportPlatform> platform = p_preset->get_platform();
+ List<String> feature_list;
+ platform->get_preset_features(p_preset,&feature_list);
+ //figure out features
+ Set<String> features;
+ for (List<String>::Element *E=feature_list.front();E;E=E->next()) {
+ features.insert(E->get());
+ }
+
+ //figure out paths of files that will be exported
+ Set<String> paths;
+
+ if (p_preset->get_export_filter()==EditorExportPreset::EXPORT_ALL_RESOURCES) {
+ //find stuff
+ _export_find_resources(EditorFileSystem::get_singleton()->get_filesystem(),paths);
+ } else {
+ bool scenes_only = p_preset->get_export_filter()==EditorExportPreset::EXPORT_SELECTED_SCENES;
+
+ Vector<String> files = p_preset->get_files_to_export();
+ for(int i=0;i<files.size();i++) {
+ if (scenes_only && ResourceLoader::get_resource_type(files[i])!="PackedScene")
+ continue;
+
+ _export_find_dependencies(files[i],paths);
+ }
+ }
+
+ //store everything in the export medium
+ int idx = 0;
+ int total=paths.size();
+
+ for(Set<String>::Element *E=paths.front();E;E=E->next()) {
+
+ String path = E->get();
+
+ if (FileAccess::exists(path+".import")) {
+ //file is imported, replace by what it imports
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(path+".import");
+ if (err!=OK) {
+ ERR_PRINTS("Could not parse: '"+path+"', not exported.");
+ continue;
+ }
+
+ List<String> remaps;
+ config->get_section_keys("remap",&remaps);
+
+ for(List<String>::Element *F=remaps.front();F;F=F->next()) {
+
+ String remap=F->get();
+ if (remap=="path") {
+ String remapped_path=config->get_value("remap",remap);
+ Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path);
+ p_func(p_udata,remapped_path,array,idx,total);
+ } else if (remap.begins_with("path.")) {
+ String feature = remap.get_slice(".",1);
+ if (features.has(feature)) {
+ String remapped_path=config->get_value("remap",remap);
+ Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path);
+ p_func(p_udata,remapped_path,array,idx,total);
+ }
+ }
+ }
+
+ //also save the .import file
+ Vector<uint8_t> array = FileAccess::get_file_as_array(path+".import");
+ p_func(p_udata,path+".import",array,idx,total);
+
+ } else {
+ //just store it as it comes
+ Vector<uint8_t> array = FileAccess::get_file_as_array(path);
+ p_func(p_udata,path,array,idx,total);
+ }
+
+ idx++;
+ }
+
+ //save config!
+
+ String config_file="godot.cfb";
+ String engine_cfb =EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp"+config_file;
+ GlobalConfig::get_singleton()->save_custom(engine_cfb);
+ Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
+
+ p_func(p_udata,"res://"+config_file,data,idx,total);
+
+ return OK;
+}
+
+Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset>& p_preset,const String& p_path) {
+
+ EditorProgress ep("savepack",TTR("Packing"),102);
+
+ String tmppath = EditorSettings::get_singleton()->get_settings_path()+"/tmp/packtmp";
+ FileAccess *ftmp = FileAccess::open(tmppath,FileAccess::WRITE);
+ ERR_FAIL_COND_V(!ftmp,ERR_CANT_CREATE)
+
+ PackData pd;
+ pd.ep=&ep;
+ pd.f=ftmp;
+
+ Error err = export_project_files(p_preset,_save_pack_file,&pd);
+
+ memdelete(ftmp); //close tmp file
+
+ if (err)
+ return err;
+
+ pd.file_ofs.sort(); //do sort, so we can do binary search later
+
+
+ FileAccess *f = FileAccess::open(p_path,FileAccess::WRITE);
+ ERR_FAIL_COND_V(!f,ERR_CANT_CREATE)
+ f->store_32(0x43504447); //GDPK
+ f->store_32(1); //pack version
+ f->store_32(VERSION_MAJOR);
+ f->store_32(VERSION_MINOR);
+ f->store_32(0); //hmph
+ for(int i=0;i<16;i++) {
+ //reserved
+ f->store_32(0);
+ }
+
+ f->store_32(pd.file_ofs.size()); //amount of files
+
+ size_t header_size = f->get_pos();
+
+ //precalculate header size
+
+ for(int i=0;i<pd.file_ofs.size();i++) {
+ header_size += 4; // size of path string (32 bits is enough)
+ uint32_t string_len = pd.file_ofs[i].path_utf8.length();
+ header_size += string_len + _get_pad(4,string_len); ///size of path string
+ header_size += 8; // offset to file _with_ header size included
+ header_size += 8; // size of file
+ header_size +=16; // md5
+
+ }
+
+ size_t header_padding = _get_pad(PCK_PADDING,header_size);
+
+
+ for(int i=0;i<pd.file_ofs.size();i++) {
+
+ uint32_t string_len = pd.file_ofs[i].path_utf8.length();
+ uint32_t pad = _get_pad(4,string_len);;
+ f->store_32(string_len+pad);
+ f->store_buffer((const uint8_t*)pd.file_ofs[i].path_utf8.get_data(),string_len);
+ for(uint32_t j=0;j<pad;j++) {
+ f->store_8(0);
+ }
+
+ f->store_64(pd.file_ofs[i].ofs + header_padding + header_size);
+ f->store_64(pd.file_ofs[i].size); // pay attention here, this is where file is
+ f->store_buffer(pd.file_ofs[i].md5.ptr(),16); //also save md5 for file
+ }
+
+ for(uint32_t j=0;j<header_padding;j++) {
+ f->store_8(0);
+ }
+
+ //save the rest of the data
+
+ ftmp = FileAccess::open(tmppath,FileAccess::READ);
+ if (!ftmp) {
+ memdelete(f);
+ ERR_FAIL_COND_V(!ftmp,ERR_CANT_CREATE)
+ }
+
+ const int bufsize=16384;
+ uint8_t buf[bufsize];
+
+ while(true) {
+
+ int got = ftmp->get_buffer(buf,bufsize);
+ if (got<=0)
+ break;
+ f->store_buffer(buf,got);
+ }
+
+ memdelete(ftmp);
+
+ f->store_32(0x43504447); //GDPK
+ memdelete(f);
+
+ return OK;
+}
+
+Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset>& p_preset,const String& p_path) {
+
+ EditorProgress ep("savezip",TTR("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.ep=&ep;
+ zd.zip=zip;
+
+
+ Error err = export_project_files(p_preset,_save_zip_file,&zd);
+
+ zipClose(zip,NULL);
+
+ return OK;
+}
+
+EditorExportPlatform::EditorExportPlatform() {
+
+
+}
+
+
+////
+
+EditorExport *EditorExport::singleton=NULL;
+
+
+void EditorExport::_save() {
+
+
+ Ref<ConfigFile> config;
+ config.instance();
+ for(int i=0;i<export_presets.size();i++) {
+
+ Ref<EditorExportPreset> preset = export_presets[i];
+ String section="preset."+itos(i);
+
+ config->set_value(section,"name",preset->get_name());
+ config->set_value(section,"platform",preset->get_platform()->get_name());
+ config->set_value(section,"runnable",preset->is_runnable());
+ bool save_files=false;
+ switch(preset->get_export_filter()) {
+ case EditorExportPreset::EXPORT_ALL_RESOURCES: {
+ config->set_value(section,"export_filter","all_resources");
+ } break;
+ case EditorExportPreset::EXPORT_SELECTED_SCENES: {
+ config->set_value(section,"export_filter","scenes");
+ save_files=true;
+ } break;
+ case EditorExportPreset::EXPORT_SELECTED_RESOURCES: {
+ config->set_value(section,"export_filter","resources");
+ save_files=true;
+ } break;
+
+
+ }
+
+ if (save_files) {
+ Vector<String> export_files = preset->get_files_to_export();
+ config->set_value(section,"export_files",export_files);
+ }
+ config->set_value(section,"include_filter",preset->get_include_filter());
+ config->set_value(section,"exclude_filter",preset->get_exclude_filter());
+ config->set_value(section,"patch_list",preset->get_patches());
+
+ String option_section="preset."+itos(i)+".options";
+
+ for (const List<PropertyInfo>::Element *E=preset->get_properties().front();E;E=E->next()) {
+ config->set_value(option_section,E->get().name,preset->get(E->get().name));
+ }
+ }
+
+ config->save("res://export_presets.cfg");
+
+ print_line("saved ok");
+
+}
+
+
+void EditorExport::save_presets() {
+
+ print_line("save presets");
+ if (block_save)
+ return;
+ save_timer->start();
+}
+
+void EditorExport::_bind_methods() {
+
+ ClassDB::bind_method("_save",&EditorExport::_save);
+}
+
+void EditorExport::add_export_platform(const Ref<EditorExportPlatform>& p_platform) {
+
+ export_platforms.push_back(p_platform);
+}
+
+int EditorExport::get_export_platform_count() {
+
+ return export_platforms.size();
+}
+
+Ref<EditorExportPlatform> EditorExport::get_export_platform(int p_idx) {
+
+ ERR_FAIL_INDEX_V(p_idx,export_platforms.size(),Ref<EditorExportPlatform>());
+
+ return export_platforms[p_idx];
+}
+
+
+void EditorExport::add_export_preset(const Ref<EditorExportPreset>& p_preset,int p_at_pos) {
+
+ if (p_at_pos<0)
+ export_presets.push_back(p_preset);
+ else
+ export_presets.insert(p_at_pos,p_preset);
+
+
+}
+
+int EditorExport::get_export_preset_count() const {
+
+ return export_presets.size();
+}
+
+Ref<EditorExportPreset> EditorExport::get_export_preset(int p_idx) {
+
+ ERR_FAIL_INDEX_V( p_idx, export_presets.size(),Ref<EditorExportPreset>() );
+ return export_presets[p_idx];
+}
+
+void EditorExport::remove_export_preset(int p_idx) {
+
+ export_presets.remove(p_idx);
+}
+
+void EditorExport::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ load_config();
+ }
+}
+
+void EditorExport::load_config() {
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load("res://export_presets.cfg");
+ if (err!=OK)
+ return;
+
+ block_save=true;
+
+ int index=0;
+ while(true) {
+
+ String section = "preset."+itos(index);
+ if (!config->has_section(section))
+ break;
+
+ String platform=config->get_value(section,"platform");
+
+ Ref<EditorExportPreset> preset;
+
+ for(int i=0;i<export_platforms.size();i++) {
+ if (export_platforms[i]->get_name()==platform) {
+ preset = export_platforms[i]->create_preset();
+ break;
+ }
+ }
+
+ if (!preset.is_valid()) {
+ index++;
+ ERR_CONTINUE(!preset.is_valid());
+ }
+
+ preset->set_name( config->get_value(section,"name") );
+ preset->set_runnable( config->get_value(section,"runnable") );
+
+ String export_filter = config->get_value(section,"export_filter");
+
+ bool get_files=false;
+
+ if (export_filter=="all_resources") {
+ preset->set_export_filter(EditorExportPreset::EXPORT_ALL_RESOURCES);
+ } else if (export_filter=="scenes") {
+ preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_SCENES);
+ get_files=true;
+ } else if (export_filter=="resources") {
+ preset->set_export_filter(EditorExportPreset::EXPORT_SELECTED_RESOURCES);
+ get_files=true;
+ }
+
+ if (get_files) {
+
+ Vector<String> files = config->get_value(section,"export_files");
+
+ for(int i=0;i<files.size();i++) {
+ preset->add_export_file(files[i]);
+ }
+ }
+
+ preset->set_include_filter( config->get_value(section,"include_filter") );
+ preset->set_exclude_filter( config->get_value(section,"exclude_filter") );
+
+
+ Vector<String> patch_list = config->get_value(section,"patch_list");
+
+ for(int i=0;i<patch_list.size();i++) {
+ preset->add_patch(patch_list[i]);
+ }
+
+ String option_section="preset."+itos(index)+".options";
+
+ List<String> options;
+
+ config->get_section_keys(option_section,&options);
+
+ for (List<String>::Element *E=options.front();E;E=E->next()) {
+
+ Variant value = config->get_value(option_section,E->get());
+
+ preset->set(E->get(),value);
+ }
+
+ add_export_preset(preset);
+ index++;
+ }
+
+ block_save=false;
+
+}
+
+
+
+EditorExport::EditorExport() {
+
+ save_timer = memnew( Timer );
+ add_child(save_timer);
+ save_timer->set_wait_time(0.8);
+ save_timer->set_one_shot(true);
+ save_timer->connect("timeout",this,"_save");
+ block_save=false;
+
+ singleton=this;
+}
+
+EditorExport::~EditorExport() {
+
+
+}
+
+
+//////////
+
+void EditorExportPlatformPC::get_preset_features(const Ref<EditorExportPreset>& p_preset,List<String>* r_features) {
+
+ if (p_preset->get("texture_format/s3tc")) {
+ r_features->push_back("s3tc");
+ }
+ if (p_preset->get("texture_format/etc")) {
+ r_features->push_back("etc");
+ }
+ if (p_preset->get("texture_format/etc2")) {
+ r_features->push_back("etc2");
+ }
+}
+
+void EditorExportPlatformPC::get_export_options(List<ExportOption> *r_options) {
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL,"texture_format/s3tc"),true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL,"texture_format/etc"),false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL,"texture_format/etc2"),false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL,"binary_format/64_bits"),true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING,"custom_template/release",PROPERTY_HINT_GLOBAL_FILE),""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING,"custom_template/debug",PROPERTY_HINT_GLOBAL_FILE),""));
+}
+
+String EditorExportPlatformPC::get_name() const {
+
+ return name;
+}
+Ref<Texture> EditorExportPlatformPC::get_logo() const {
+
+ return logo;
+}
+
+bool EditorExportPlatformPC::can_export(const Ref<EditorExportPreset>& p_preset,String &r_error, bool &r_missing_templates) const {
+
+ r_missing_templates=false;
+
+ if (find_export_template(release_file_32)==String()) {
+ r_missing_templates=true;
+ } else if (find_export_template(debug_file_32)==String()) {
+ r_missing_templates=true;
+ } else if (find_export_template(release_file_64)==String()) {
+ r_missing_templates=true;
+ } else if (find_export_template(debug_file_64)==String()) {
+ r_missing_templates=true;
+ }
+ return !r_missing_templates;
+}
+
+String EditorExportPlatformPC::get_binary_extension() const {
+ return extension;
+}
+
+Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset>& p_preset, bool p_debug, const String& p_path, int p_flags) {
+
+ return OK;
+}
+
+void EditorExportPlatformPC::set_extension(const String& p_extension) {
+ extension=p_extension;
+}
+
+void EditorExportPlatformPC::set_name(const String& p_name) {
+ name=p_name;
+}
+
+void EditorExportPlatformPC::set_logo(const Ref<Texture>& p_logo) {
+ logo=p_logo;
+}
+
+void EditorExportPlatformPC::set_release_64(const String& p_file) {
+
+ release_file_64=p_file;
+}
+
+void EditorExportPlatformPC::set_release_32(const String& p_file){
+
+ release_file_32=p_file;
+}
+void EditorExportPlatformPC::set_debug_64(const String& p_file){
+
+ debug_file_64=p_file;
+}
+void EditorExportPlatformPC::set_debug_32(const String& p_file){
+
+ debug_file_32=p_file;
+
+}
+
+EditorExportPlatformPC::EditorExportPlatformPC() {
+
+}
+
+////////
+
+#if 0
+#include "version.h"
+#include "script_language.h"
+#include "global_config.h"
+#include "os/file_access.h"
+#include "os/dir_access.h"
+#include "editor/editor_file_system.h"
+#include "io/resource_loader.h"
+#include "editor_node.h"
+#include "editor_settings.h"
+#include "io/config_file.h"
+#include "io/resource_saver.h"
+#include "io/md5.h"
+#include "io_plugins/editor_texture_import_plugin.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "io/zip_io.h"
+
+
+String EditorImportPlugin::validate_source_path(const String& p_path) {
+
+ String gp = GlobalConfig::get_singleton()->globalize_path(p_path);
+ String rp = GlobalConfig::get_singleton()->get_resource_path();
+ if (!rp.ends_with("/"))
+ rp+="/";
+
+ return rp.path_to_file(gp);
+}
+
+String EditorImportPlugin::expand_source_path(const String& p_path) {
+
+ if (p_path.is_rel_path()) {
+ return GlobalConfig::get_singleton()->get_resource_path().plus_file(p_path).simplify_path();
+ } else {
+ return p_path;
+ }
+}
+
+
+String EditorImportPlugin::_validate_source_path(const String& p_path) {
+
+ return validate_source_path(p_path);
+}
+
+String EditorImportPlugin::_expand_source_path(const String& p_path) {
+
+ return expand_source_path(p_path);
+}
+
+void EditorImportPlugin::_bind_methods() {
+
+
+ ClassDB::bind_method(D_METHOD("validate_source_path","path"),&EditorImportPlugin::_validate_source_path);
+ ClassDB::bind_method(D_METHOD("expand_source_path","path"),&EditorImportPlugin::_expand_source_path);
+
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::STRING,"get_name"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::STRING,"get_visible_name"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("import_dialog",PropertyInfo(Variant::STRING,"from")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::INT,"import",PropertyInfo(Variant::STRING,"path"),PropertyInfo(Variant::OBJECT,"from",PROPERTY_HINT_RESOURCE_TYPE,"ResourceImportMetadata")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::POOL_BYTE_ARRAY,"custom_export",PropertyInfo(Variant::STRING,"path"),PropertyInfo(Variant::OBJECT,"platform",PROPERTY_HINT_RESOURCE_TYPE,"EditorExportPlatform")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("import_from_drop",PropertyInfo(Variant::POOL_STRING_ARRAY,"files"),PropertyInfo(Variant::STRING,"dest_path")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("reimport_multiple_files",PropertyInfo(Variant::POOL_STRING_ARRAY,"files")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"can_reimport_multiple_files"));
+
+ //BIND_VMETHOD( mi );
+}
+
+String EditorImportPlugin::get_name() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("get_name")) {
+ return get_script_instance()->call("get_name");
+ }
+
+ ERR_FAIL_V("");
+}
+
+String EditorImportPlugin::get_visible_name() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("get_visible_name")) {
+ return get_script_instance()->call("get_visible_name");
+ }
+
+ ERR_FAIL_V("");
+}
+
+
+void EditorImportPlugin::import_dialog(const String& p_from) {
+
+ if (get_script_instance() && get_script_instance()->has_method("import_dialog")) {
+ get_script_instance()->call("import_dialog",p_from);
+ return;
+ }
+
+ ERR_FAIL();
+
+}
+
+Error EditorImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
+
+ if (get_script_instance() && get_script_instance()->has_method("import")) {
+ return Error(get_script_instance()->call("import",p_path,p_from).operator int());
+ }
+
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+}
+
+Vector<uint8_t> EditorImportPlugin::custom_export(const String& p_path, const Ref<EditorExportPlatform> &p_platform) {
+
+ if (get_script_instance() && get_script_instance()->has_method("custom_export")) {
+ get_script_instance()->call("custom_export",p_path,p_platform);
+ }
+
+ return Vector<uint8_t>();
+}
+
+bool EditorImportPlugin::can_reimport_multiple_files() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("can_reimport_multiple_files")) {
+ return get_script_instance()->call("can_reimport_multiple_files");
+ }
+
+ return false;
+}
+void EditorImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
+
+ if (get_script_instance() && get_script_instance()->has_method("reimport_multiple_files")) {
+ get_script_instance()->call("reimport_multiple_files",p_list);
+ }
+
+}
+
+void EditorImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
+
+ if (get_script_instance() && get_script_instance()->has_method("import_from_drop")) {
+ get_script_instance()->call("import_from_drop",p_drop,p_dest_path);
+ }
+
+}
+
+EditorImportPlugin::EditorImportPlugin() {
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void EditorExportPlugin::_bind_methods() {
+
+ MethodInfo mi = MethodInfo("custom_export:Variant",PropertyInfo(Variant::STRING,"name"),PropertyInfo(Variant::OBJECT,"platform",PROPERTY_HINT_RESOURCE_TYPE,"EditorExportPlatform"));
+ mi.return_val.type=Variant::POOL_BYTE_ARRAY;
+
+ BIND_VMETHOD( mi );
+}
+
+
+Vector<uint8_t> EditorExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
+
+ if (get_script_instance()) {
+
+ Variant d = get_script_instance()->call("custom_export",p_path,p_platform);
+ if (d.get_type()==Variant::NIL)
+ return Vector<uint8_t>();
+ if (d.get_type()==Variant::POOL_BYTE_ARRAY)
+ return d;
+
+ ERR_FAIL_COND_V(d.get_type()!=Variant::DICTIONARY,Vector<uint8_t>());
+ Dictionary dict=d;
+ ERR_FAIL_COND_V(!dict.has("name"),Vector<uint8_t>());
+ ERR_FAIL_COND_V(!dict.has("data"),Vector<uint8_t>());
+ p_path=dict["name"];
+ return dict["data"];
+ }
+
+ return Vector<uint8_t>();
+
+}
+
+
+EditorExportPlugin::EditorExportPlugin() {
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+static void _add_to_list(EditorFileSystemDirectory *p_efsd,Set<StringName>& r_list) {
+
+ for(int i=0;i<p_efsd->get_subdir_count();i++) {
+
+ _add_to_list(p_efsd->get_subdir(i),r_list);
+ }
+
+ for(int i=0;i<p_efsd->get_file_count();i++) {
+ r_list.insert(p_efsd->get_file_path(i));
+ }
+}
+
+
+struct __EESortDepCmp {
+
+ _FORCE_INLINE_ bool operator()(const StringName& p_l,const StringName& p_r) const {
+ return p_l.operator String() < p_r.operator String();
+ }
+};
+
+
+
+
+static void _edit_files_with_filter(DirAccess *da,const List<String>& p_filters,Set<StringName>& r_list,bool exclude) {
+
+
+ List<String> files;
+ List<String> dirs;
+
+ da->list_dir_begin();
+
+ String f = da->get_next();
+ while(f!="") {
+
+ print_line("HOHO: "+f);
+ if (da->current_is_dir())
+ dirs.push_back(f);
+ else
+ files.push_back(f);
+
+ f=da->get_next();
+ }
+
+ String r = da->get_current_dir().replace("\\","/");
+ if (!r.ends_with("/"))
+ r+="/";
+
+ print_line("AT: "+r);
+
+ for(List<String>::Element *E=files.front();E;E=E->next()) {
+ String fullpath=r+E->get();
+ for(const List<String>::Element *F=p_filters.front();F;F=F->next()) {
+
+ if (fullpath.matchn(F->get())) {
+ String act = TTR("Added:")+" ";
+
+ if (!exclude) {
+ r_list.insert(fullpath);
+ } else {
+ act = TTR("Removed:")+" ";
+ r_list.erase(fullpath);
+ }
+
+
+ print_line(act+fullpath);
+ }
+ }
+ }
+
+ da->list_dir_end();
+
+ for(List<String>::Element *E=dirs.front();E;E=E->next()) {
+ if (E->get().begins_with("."))
+ continue;
+ da->change_dir(E->get());
+ _edit_files_with_filter(da,p_filters,r_list,exclude);
+ da->change_dir("..");
+ }
+
+}
+
+static void _edit_filter_list(Set<StringName>& r_list,const String& p_filter,bool exclude) {
+
+ if (p_filter=="")
+ return;
+ Vector<String> split = p_filter.split(",");
+ List<String> filters;
+ for(int i=0;i<split.size();i++) {
+ String f = split[i].strip_edges();
+ if (f.empty())
+ continue;
+ filters.push_back(f);
+ }
+
+ DirAccess *da = DirAccess::open("res://");
+ ERR_FAIL_NULL(da);
+ _edit_files_with_filter(da,filters,r_list,exclude);
+ memdelete(da);
+}
+
+static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) {
+ _edit_filter_list(r_list,p_filter,false);
+}
+
+static void _remove_filter_from_list(Set<StringName>& r_list,const String& p_filter) {
+ _edit_filter_list(r_list,p_filter,true);
+}
+
+bool EditorExportPlatform::_set(const StringName& p_name, const Variant& p_value) {
+
+ String n = p_name;
+
+ if (n=="debug/debugging_enabled") {
+ set_debugging_enabled(p_value);
+ } else {
+ return false;
+ }
+
+ return true;
+
+}
+
+bool EditorExportPlatform::_get(const StringName& p_name,Variant &r_ret) const {
+
+ String n = p_name;
+
+ if (n=="debug/debugging_enabled") {
+ r_ret=is_debugging_enabled();
+ } else {
+ return false;
+ }
+
+ return true;
+
+}
+
+void EditorExportPlatform::_get_property_list( List<PropertyInfo> *p_list) const {
+
+ p_list->push_front( PropertyInfo( Variant::BOOL, "debug/debugging_enabled"));
+}
+
+Vector<uint8_t> EditorExportPlatform::get_exported_file_default(String& p_fname) const {
+
+ FileAccess *f = FileAccess::open(p_fname,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,Vector<uint8_t>());
+ Vector<uint8_t> ret;
+ ret.resize(f->get_len());
+ int rbs = f->get_buffer(ret.ptr(),ret.size());
+ memdelete(f);
+ return ret;
+}
+
+Vector<uint8_t> EditorExportPlatform::get_exported_file(String& p_fname) const {
+
+ Ref<EditorExportPlatform> ep=EditorImportExport::get_singleton()->get_export_platform(get_name());
+
+ for(int i=0;i<EditorImportExport::get_singleton()->get_export_plugin_count();i++) {
+
+ Vector<uint8_t> data = EditorImportExport::get_singleton()->get_export_plugin(i)->custom_export(p_fname,ep);
+ if (data.size())
+ return data;
+
+ }
+
+
+ return get_exported_file_default(p_fname);
+
+
+}
+
+Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const {
+
+
+ Set<StringName> exported;
+
+ if (FileAccess::exists("res://godot.cfg"))
+ exported.insert("res://godot.cfg");
+
+ if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED) {
+
+ String filter;
+ if (EditorImportExport::get_singleton()->get_export_filter()==EditorImportExport::EXPORT_ALL) {
+ _add_filter_to_list(exported,"*");
+ } else {
+ _add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported);
+ String cf = EditorImportExport::get_singleton()->get_export_custom_filter();
+ if (cf!="")
+ cf+=",";
+ cf+="*.flags";
+ _add_filter_to_list(exported,cf);
+
+ cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude();
+ _remove_filter_from_list(exported,cf);
+ }
+
+
+ } else {
+
+
+ Map<String,Map<String,String> > remapped_paths;
+
+ Set<String> scene_extensions;
+ Set<String> resource_extensions;
+
+ {
+
+ List<String> l;
+ /*
+ SceneLoader::get_recognized_extensions(&l);
+ for(List<String>::Element *E=l.front();E;E=E->next()) {
+ scene_extensions.insert(E->get());
+ }
+ */
+ ResourceLoader::get_recognized_extensions_for_type("",&l);
+ for(List<String>::Element *E=l.front();E;E=E->next()) {
+
+ resource_extensions.insert(E->get());
+ }
+ }
+
+
+ List<StringName> toexport;
+
+ EditorImportExport::get_singleton()->get_export_file_list(&toexport);
+
+ print_line("TO EXPORT: "+itos(toexport.size()));
+
+
+ for (List<StringName>::Element *E=toexport.front();E;E=E->next()) {
+
+ print_line("DEP: "+String(E->get()));
+ exported.insert(E->get());
+ if (p_bundles && EditorImportExport::get_singleton()->get_export_file_action(E->get())==EditorImportExport::ACTION_BUNDLE) {
+ print_line("NO BECAUSE OF BUNDLE!");
+ continue; //no dependencies needed to be copied
+ }
+
+ List<String> testsubs;
+ testsubs.push_back(E->get());
+
+ while(testsubs.size()) {
+ //recursive subdep search!
+ List<String> deplist;
+ ResourceLoader::get_dependencies(testsubs.front()->get(),&deplist);
+ testsubs.pop_front();
+
+ List<String> subdeps;
+
+ for (List<String>::Element *F=deplist.front();F;F=F->next()) {
+
+ StringName dep = F->get();
+
+ if (exported.has(dep) || EditorImportExport::get_singleton()->get_export_file_action(dep)!=EditorImportExport::ACTION_NONE)
+ continue; //dependency added or to be added
+ print_line(" SUBDEP: "+String(dep));
+
+ exported.insert(dep);
+ testsubs.push_back(dep);
+ }
+ }
+ }
+ String cf = EditorImportExport::get_singleton()->get_export_custom_filter();
+ if (cf!="")
+ cf+=",";
+ cf+="*.flags";
+ _add_filter_to_list(exported,cf);
+
+ cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude();
+ _remove_filter_from_list(exported,cf);
+
+
+ }
+
+ Vector<StringName> ret;
+ ret.resize(exported.size());
+
+
+ int idx=0;
+ for(Set<StringName>::Element *E=exported.front();E;E=E->next()) {
+
+ ret[idx++]=E->get();
+
+ }
+
+ SortArray<StringName,__EESortDepCmp> sort; //some platforms work better if this is sorted
+ sort.sort(ret.ptr(),ret.size());
+
+ return ret;
+
+}
+
+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)!="";
+}
+
+///////////////////////////////////////
+
+
+
+bool EditorExportPlatform::is_debugging_enabled() const {
+
+ return debugging_enabled;
+}
+
+void EditorExportPlatform::set_debugging_enabled(bool p_enabled) {
+
+ debugging_enabled = p_enabled;
+}
+
+bool EditorExportPlatformPC::_set(const StringName& p_name, const Variant& p_value) {
+
+ String n = p_name;
+
+ if (n=="custom_binary/release") {
+
+ custom_release_binary=p_value;
+ } else if (n=="custom_binary/debug") {
+
+ custom_debug_binary=p_value;
+ } 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;
+ } else
+ return false;
+
+ return true;
+
+}
+
+bool EditorExportPlatformPC::_get(const StringName& p_name,Variant &r_ret) const {
+
+ String n = p_name;
+
+ if (n=="custom_binary/release") {
+
+ r_ret=custom_release_binary;
+ } else if (n=="custom_binary/debug") {
+
+ r_ret=custom_debug_binary;
+ } 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;
+ } else
+ return false;
+
+ return true;
+
+}
+
+void EditorExportPlatformPC::_get_property_list( List<PropertyInfo> *p_list) const {
+
+ 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,"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"));
+}
+
+
+
+static void _exp_add_dep(Map<StringName,List<StringName> > &deps,const StringName& p_path) {
+
+
+ if (deps.has(p_path))
+ return; //already done
+
+ deps.insert(p_path,List<StringName>());
+
+ List<StringName> &deplist=deps[p_path];
+ Set<StringName> depset;
+
+ List<String> dl;
+ ResourceLoader::get_dependencies(p_path,&dl);
+
+ //added in order so child dependencies are always added bfore parent dependencies
+ for (List<String>::Element *E=dl.front();E;E=E->next()) {
+
+
+ if (!deps.has(E->get()))
+ _exp_add_dep(deps,E->get());
+
+ for(List<StringName>::Element *F=deps[E->get()].front();F;F=F->next()) {
+
+
+ if (!depset.has(F->get())) {
+ depset.insert(F->get());
+ deplist.push_back(F->get());
+ }
+ }
+
+ if (!depset.has(E->get())) {
+ depset.insert(E->get());
+ deplist.push_back(E->get());
+ }
+
+ }
+}
+
+
+
+Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles) {
+
+/* ALL FILES AND DEPENDENCIES */
+
+ Vector<StringName> files=get_dependencies(p_make_bundles);
+
+ Map<StringName,List<StringName> > deps;
+
+ if (false) {
+ for(int i=0;i<files.size();i++) {
+
+ _exp_add_dep(deps,files[i]);
+
+ }
+ }
+
+
+
+/* GROUP ATLAS */
+
+
+ List<StringName> groups;
+
+ EditorImportExport::get_singleton()->image_export_get_groups(&groups);
+
+ Map<StringName,StringName> remap_files;
+ Set<StringName> saved;
+
+ int counter=0;
+
+ for(List<StringName>::Element *E=groups.front();E;E=E->next()) {
+
+ if (!EditorImportExport::get_singleton()->image_export_group_get_make_atlas(E->get()))
+ continue; //uninterested, only process for atlas!
+
+ List<StringName> atlas_images;
+ EditorImportExport::get_singleton()->image_export_get_images_in_group(E->get(),&atlas_images);
+ atlas_images.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=atlas_images.front();F;) {
+
+ List<StringName>::Element *N=F->next();
+
+ if (!FileAccess::exists(F->get())) {
+ atlas_images.erase(F);
+ }
+
+ F=N;
+
+ }
+
+ if (atlas_images.size()<=1)
+ continue;
+
+ int group_format=0;
+ float group_lossy_quality=EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(E->get());
+ int group_shrink=EditorImportExport::get_singleton()->image_export_group_get_shrink(E->get());
+ group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink();
+
+ switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(E->get())) {
+ case EditorImportExport::IMAGE_ACTION_KEEP:
+ case EditorImportExport::IMAGE_ACTION_NONE: {
+
+ switch(EditorImportExport::get_singleton()->get_export_image_action()) {
+ case EditorImportExport::IMAGE_ACTION_NONE: {
+
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS; //?
+
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
+ } break; //use default
+ }
+
+ group_lossy_quality=EditorImportExport::get_singleton()->get_export_image_quality();
+
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
+ } break; //use default
+ }
+
+ String image_listD_METHOD5;
+
+ {
+ MD5_CTX ctx;
+ MD5Init(&ctx);
+ for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
+
+ String p = F->get();
+ MD5Update(&ctx,(unsigned char*)p.utf8().get_data(),p.utf8().length());
+
+ }
+
+ MD5Final(&ctx);
+ image_listD_METHOD5=String::md5(ctx.digest);
+ }
+ //ok see if cached
+ String md5;
+ bool atlas_valid=true;
+ String atlas_name;
+
+ {
+ MD5_CTX ctx;
+ MD5Init(&ctx);
+ String path = GlobalConfig::get_singleton()->get_resource_path()+"::"+String(E->get())+"::"+get_name();
+ MD5Update(&ctx,(unsigned char*)path.utf8().get_data(),path.utf8().length());
+ MD5Final(&ctx);
+ md5 = String::md5(ctx.digest);
+ }
+
+ FileAccess *f=NULL;
+
+ if (!FileAccess::exists(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5)) {
+ print_line("NO MD5 INVALID");
+ atlas_valid=false;
+ }
+
+ if (atlas_valid)
+ f=FileAccess::open(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5,FileAccess::READ);
+
+ if (atlas_valid) {
+ //compare options
+ /*Dictionary options;
+ options.parse_json(f->get_line());
+ if (!options.has("lossy_quality") || float(options["lossy_quality"])!=group_lossy_quality)
+ atlas_valid=false;
+ else if (!options.has("shrink") || int(options["shrink"])!=group_shrink)
+ atlas_valid=false;
+ else if (!options.has("image_format") || int(options["image_format"])!=group_format)
+ atlas_valid=false;
+
+ if (!atlas_valid)
+ print_line("JSON INVALID");
+*/
+ }
+
+
+ if (atlas_valid) {
+ //check md5 of list of image /names/
+ if (f->get_line().strip_edges()!=image_listD_METHOD5) {
+ atlas_valid=false;
+ print_line("IMAGE MD5 INVALID!");
+ }
+
+ }
+
+ Vector<Rect2> rects;
+ bool resave_deps=false;
+
+ if (atlas_valid) {
+
+ //check if images were not modified
+ for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
+
+ Vector<String> slices = f->get_line().strip_edges().split("::");
+
+ if (slices.size()!=10) {
+ atlas_valid=false;
+ print_line("CANT SLICE IN 10");
+ break;
+ }
+ uint64_t mod_time = slices[0].to_int64();
+ uint64_t file_mod_time = FileAccess::get_modified_time(F->get());
+ if (mod_time!=file_mod_time) {
+
+ String imageD_METHOD5 = slices[1];
+ String fileD_METHOD5 = FileAccess::getD_METHOD5(F->get());
+
+ if (imageD_METHOD5!=fileD_METHOD5) {
+ atlas_valid=false;
+ print_line("IMAGE INVALID "+slices[0]);
+ break;
+ } else {
+ resave_deps=true;
+ }
+ }
+
+ if (atlas_valid) {
+ //push back region and margin
+ rects.push_back(Rect2(slices[2].to_float(),slices[3].to_float(),slices[4].to_float(),slices[5].to_float()));
+ rects.push_back(Rect2(slices[6].to_float(),slices[7].to_float(),slices[8].to_float(),slices[9].to_float()));
+ }
+ }
+
+ }
+
+ if (f) {
+ memdelete(f);
+ f=NULL;
+ }
+
+ print_line("ATLAS VALID? "+itos(atlas_valid)+" RESAVE DEPS? "+itos(resave_deps));
+ if (!atlas_valid) {
+ rects.clear();
+ //oh well, atlas is not valid. need to make new one....
+
+ String dst_file = EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5+".tex";
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+ //imd->set_editor();
+
+
+ for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
+
+ imd->add_source(EditorImportPlugin::validate_source_path(F->get()),FileAccess::getD_METHOD5(F->get()));
+
+ }
+
+
+ imd->set_option("format",group_format);
+
+
+ int flags=0;
+
+ if (GlobalConfig::get_singleton()->get("image_loader/filter"))
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_FILTER;
+ if (!GlobalConfig::get_singleton()->get("image_loader/gen_mipmaps"))
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS;
+ if (!GlobalConfig::get_singleton()->get("image_loader/repeat"))
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_REPEAT;
+
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA;
+
+ imd->set_option("flags",flags);
+ imd->set_option("quality",group_lossy_quality);
+ imd->set_option("atlas",true);
+ imd->set_option("crop",true);
+ imd->set_option("shrink",group_shrink);
+
+
+
+ Ref<EditorTextureImportPlugin> plugin = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture");
+ Error err = plugin->import2(dst_file,imd,get_image_compression(),true);
+ if (err) {
+
+ EditorNode::add_io_error(TTR("Error saving atlas:")+" "+dst_file.get_file());
+ return ERR_CANT_CREATE;
+ }
+
+ ERR_FAIL_COND_V(imd->get_option("rects")==Variant(),ERR_BUG);
+
+ Array r_rects=imd->get_option("rects");
+ rects.resize(r_rects.size());
+ for(int i=0;i<r_rects.size();i++) {
+ //get back region and margins
+ rects[i]=r_rects[i];
+ }
+
+
+ resave_deps=true;
+ }
+
+
+ //atlas is valid (or it was just saved i guess), create the atex files and save them
+
+ if (resave_deps) {
+ f=FileAccess::open(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5,FileAccess::WRITE);
+ Dictionary options;
+ options["lossy_quality"]=group_lossy_quality;
+ options["shrink"]=EditorImportExport::get_singleton()->image_export_group_get_shrink(E->get());
+ options["image_format"]=group_format;
+ //f->store_line(options.to_json());
+ f->store_line(image_listD_METHOD5);
+ }
+
+ //go through all ATEX files
+
+ {
+ Ref<ImageTexture> atlas = memnew( ImageTexture ); //fake atlas!
+ String atlas_path="res://atlas-"+md5+".tex";
+ atlas->set_path(atlas_path);
+ int idx=0;
+ for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
+
+ String p = F->get();
+ Ref<AtlasTexture> atex = memnew(AtlasTexture);
+ atex->set_atlas(atlas);
+ Rect2 region=rects[idx++];
+ Rect2 margin=rects[idx++];
+ atex->set_region(region);
+ atex->set_margin(margin);
+
+ String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpatlas.atex";
+ Error err = ResourceSaver::save(path,atex);
+ if (err!=OK) {
+ EditorNode::add_io_error(TTR("Could not save atlas subtexture:")+" "+path);
+ return ERR_CANT_CREATE;
+ }
+ Vector<uint8_t> data = FileAccess::get_file_as_array(path);
+ String dst_path = F->get().operator String().get_basename()+".atex";
+ err = p_func(p_udata,dst_path,data,counter++,files.size());
+ saved.insert(dst_path);
+ if (err)
+ return err;
+
+ if (f) {
+ //recreating deps..
+ String depline;
+ //depline=String(F->get())+"::"+itos(FileAccess::get_modified_time(F->get()))+"::"+FileAccess::getD_METHOD5(F->get()); name unneccesary by top md5
+ depline=itos(FileAccess::get_modified_time(F->get()))+"::"+FileAccess::getD_METHOD5(F->get());
+ depline+="::"+itos(region.pos.x)+"::"+itos(region.pos.y)+"::"+itos(region.size.x)+"::"+itos(region.size.y);
+ depline+="::"+itos(margin.pos.x)+"::"+itos(margin.pos.y)+"::"+itos(margin.size.x)+"::"+itos(margin.size.y);
+ f->store_line(depline);
+ }
+
+ remap_files[F->get()]=dst_path;
+ }
+
+ Vector<uint8_t> atlas_data = FileAccess::get_file_as_array(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5+".tex");
+ Error err = p_func(p_udata,atlas_path,atlas_data,counter,files.size());
+ saved.insert(atlas_path);
+ if (err)
+ return err;
+
+ }
+
+
+ if (f) {
+ memdelete(f);
+ }
+
+ }
+
+
+ StringName engine_cfg="res://godot.cfg";
+ StringName boot_splash;
+ {
+ String splash=GlobalConfig::get_singleton()->get("application/boot_splash"); //avoid splash from being converted
+ splash=splash.strip_edges();
+ if (splash!=String()) {
+ if (!splash.begins_with("res://"))
+ splash="res://"+splash;
+ splash=splash.simplify_path();
+ boot_splash=splash;
+ }
+ }
+ StringName custom_cursor;
+ {
+ String splash=GlobalConfig::get_singleton()->get("display/custom_mouse_cursor"); //avoid splash from being converted
+ splash=splash.strip_edges();
+ if (splash!=String()) {
+ if (!splash.begins_with("res://"))
+ splash="res://"+splash;
+ splash=splash.simplify_path();
+ custom_cursor=splash;
+ }
+ }
+
+
+
+
+ for(int i=0;i<files.size();i++) {
+
+ if (remap_files.has(files[i]) || files[i]==engine_cfg) //gonna be remapped (happened before!)
+ continue; //from atlas?
+ String src=files[i];
+ Vector<uint8_t> buf;
+
+ if (src==boot_splash || src==custom_cursor)
+ buf = get_exported_file_default(src); //bootsplash must be kept if used
+ else
+ buf = get_exported_file(src);
+
+ ERR_CONTINUE( saved.has(src) );
+
+ Error err = p_func(p_udata,src,buf,counter++,files.size());
+ if (err)
+ return err;
+
+ saved.insert(src);
+ if (src!=String(files[i]))
+ remap_files[files[i]]=src;
+
+ }
+
+
+ {
+
+ //make binary godot.cfg config
+ Map<String,Variant> custom;
+
+
+ if (remap_files.size()) {
+ Vector<String> remapsprop;
+ for(Map<StringName,StringName>::Element *E=remap_files.front();E;E=E->next()) {
+ print_line("REMAP: "+String(E->key())+" -> "+E->get());
+ remapsprop.push_back(E->key());
+ remapsprop.push_back(E->get());
+ }
+
+ custom["remap/all"]=remapsprop;
+ }
+
+ //add presaved dependencies
+ for(Map<StringName,List<StringName> >::Element *E=deps.front();E;E=E->next()) {
+
+ if (E->get().size()==0)
+ continue; //no deps
+ String key;
+ Vector<StringName> deps;
+ //if bundle continue (when bundles supported obviously)
+
+ if (remap_files.has(E->key())) {
+ key=remap_files[E->key()];
+ } else {
+ key=E->key();
+ }
+
+ deps.resize(E->get().size());
+ int i=0;
+
+ for(List<StringName>::Element *F=E->get().front();F;F=F->next()) {
+ deps[i++]=F->get();
+ print_line(" -"+String(F->get()));
+ }
+
+ NodePath prop(deps,true,String()); //seems best to use this for performance
+
+ custom["deps/"+key.md5_text()]=prop;
+
+ }
+
+ String remap_file="godot.cfb";
+ String engine_cfb =EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp"+remap_file;
+ GlobalConfig::get_singleton()->save_custom(engine_cfb,custom);
+ Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
+
+ Error err = p_func(p_udata,"res://"+remap_file,data,counter,files.size());
+ if (err)
+ return err;
+
+ }
+
+ return OK;
+}
+
+static int _get_pad(int p_alignment, int p_n) {
+
+ int rest = p_n % p_alignment;
+ int pad = 0;
+ if (rest > 0) {
+ pad = p_alignment - rest;
+ };
+
+ return pad;
+};
+
+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("filesystem/file_server/port");
+ String passwd = EditorSettings::get_singleton()->get("filesystem/file_server/password");
+ r_flags.push_back("-rfs");
+ r_flags.push_back(host+":"+itos(port));
+ if (passwd!="") {
+ r_flags.push_back("-rfs_pass");
+ r_flags.push_back(passwd);
+ }
+ }
+
+ if (p_flags&EXPORT_REMOTE_DEBUG) {
+
+ r_flags.push_back("-rdebug");
+
+ r_flags.push_back(host+":"+String::num(GLOBAL_DEF("network/debug/remote_port", 6007)));
+
+ List<String> breakpoints;
+ ScriptEditor::get_singleton()->get_breakpoints(&breakpoints);
+
+
+ if (breakpoints.size()) {
+
+ r_flags.push_back("-bp");
+ String bpoints;
+ for(const List<String>::Element *E=breakpoints.front();E;E=E->next()) {
+
+ bpoints+=E->get().replace(" ","%20");
+ if (E->next())
+ bpoints+=",";
+ }
+
+ r_flags.push_back(bpoints);
+ }
+
+ }
+
+ if (p_flags&EXPORT_VIEW_COLLISONS) {
+
+ r_flags.push_back("-debugcol");
+ }
+
+ if (p_flags&EXPORT_VIEW_NAVIGATION) {
+
+ r_flags.push_back("-debugnav");
+ }
+
+
+}
+
+Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
+
+
+ PackData *pd = (PackData*)p_userdata;
+
+ CharString cs=p_path.utf8();
+ pd->f->store_32(cs.length());
+ pd->f->store_buffer((uint8_t*)cs.get_data(),cs.length());
+ TempData td;
+ td.pos=pd->f->get_pos();
+ td.ofs=pd->ftmp->get_pos();
+ td.size=p_data.size();
+ pd->file_ofs.push_back(td);
+ pd->f->store_64(0); //ofs
+ pd->f->store_64(0); //size
+ {
+ MD5_CTX ctx;
+ MD5Init(&ctx);
+ MD5Update(&ctx,(unsigned char*)p_data.ptr(),p_data.size());
+ MD5Final(&ctx);
+ pd->f->store_buffer(ctx.digest,16);
+ }
+ pd->ep->step(TTR("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) {
+
+ int pad = _get_pad(pd->alignment, pd->ftmp->get_pos());
+ for (int i=0; i<pad; i++) {
+
+ pd->ftmp->store_8(0);
+ };
+ };
+ return OK;
+
+}
+
+Error EditorExportPlatform::save_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(TTR("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",TTR("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",TTR("Packing"),102);
+
+ String tmppath = EditorSettings::get_singleton()->get_settings_path()+"/tmp/packtmp";
+ FileAccess *tmp = FileAccess::open(tmppath,FileAccess::WRITE);
+ uint64_t ofs_begin = dst->get_pos();
+
+ dst->store_32(0x43504447); //GDPK
+ dst->store_32(0); //pack version
+ dst->store_32(VERSION_MAJOR);
+ dst->store_32(VERSION_MINOR);
+ dst->store_32(0); //hmph
+ for(int i=0;i<16;i++) {
+ //reserved
+ dst->store_32(0);
+ }
+
+ size_t fcountpos = dst->get_pos();
+ dst->store_32(0);
+
+ PackData pd;
+ pd.ep=&ep;
+ pd.f=dst;
+ pd.ftmp=tmp;
+ pd.count=0;
+ pd.alignment = p_alignment;
+ Error err = export_project_files(save_pack_file,&pd,p_make_bundles);
+ memdelete(tmp);
+ if (err)
+ return err;
+
+ if (p_alignment > 1) {
+ int pad = _get_pad(p_alignment, dst->get_pos());
+ for (int i=0; i<pad; i++) {
+
+ dst->store_8(0);
+ };
+ };
+
+ size_t ofsplus = dst->get_pos();
+ //append file
+
+ tmp = FileAccess::open(tmppath,FileAccess::READ);
+
+ ERR_FAIL_COND_V(!tmp,ERR_CANT_OPEN;)
+ const int bufsize=16384;
+ uint8_t buf[bufsize];
+
+ while(true) {
+
+ int got = tmp->get_buffer(buf,bufsize);
+ if (got<=0)
+ break;
+ dst->store_buffer(buf,got);
+ }
+
+ memdelete(tmp);
+
+ dst->store_64(dst->get_pos()-ofs_begin);
+ dst->store_32(0x43504447); //GDPK
+
+ //fix offsets
+
+ dst->seek(fcountpos);
+ dst->store_32(pd.count);
+ for(int i=0;i<pd.file_ofs.size();i++) {
+
+ dst->seek(pd.file_ofs[i].pos);
+ dst->store_64(pd.file_ofs[i].ofs+ofsplus);
+ dst->store_64(pd.file_ofs[i].size);
+ }
+
+ return OK;
+}
+
+EditorExportPlatform::EditorExportPlatform() {
+
+ debugging_enabled = true;
+}
+
+Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug, int p_flags) {
+
+
+
+ EditorProgress ep("export",vformat(TTR("Exporting for %s"),get_name()),102);
+
+ const int BUFSIZE = 32768;
+
+
+
+ ep.step(TTR("Setting Up.."),0);
+
+ String exe_path="";
+
+ 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);
+ if (!src_exe) {
+
+ EditorNode::add_io_error("Couldn't read source executable at:\n "+exe_path);
+ return ERR_FILE_CANT_READ;
+ }
+
+ FileAccess *dst=FileAccess::open(p_path,FileAccess::WRITE);
+ if (!dst) {
+
+ EditorNode::add_io_error("Can't copy executable file to:\n "+p_path);
+ return ERR_FILE_CANT_WRITE;
+ }
+
+ uint8_t buff[32768];
+
+ while(true) {
+
+ int c = src_exe->get_buffer(buff,BUFSIZE);
+ if (c>0) {
+
+ dst->store_buffer(buff,c);
+ } else {
+ break;
+ }
+ }
+
+ String dstfile = p_path.replace_first("res://","").replace("\\","/");
+ if (export_mode!=EXPORT_EXE) {
+
+ String dstfile_extension=export_mode==EXPORT_ZIP?".zip":".pck";
+ if (dstfile.find("/")!=-1)
+ dstfile=dstfile.get_base_dir()+"/data"+dstfile_extension;
+ else
+ dstfile="data"+dstfile_extension;
+ if (export_mode==EXPORT_PACK) {
+
+ memdelete(dst);
+
+ 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 = export_mode==EXPORT_ZIP?save_zip(dstfile,bundle):save_pack(dst,bundle);
+ memdelete(dst);
+ return err;
+}
+
+void EditorExportPlatformPC::set_binary_extension(const String& p_extension) {
+
+ binary_extension=p_extension;
+}
+
+bool EditorExportPlatformPC::can_export(String *r_error) const {
+
+ String err;
+ bool valid=true;
+
+ 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 && (!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";
+ }
+
+ if(custom_debug_binary=="" && custom_release_binary=="") {
+ if (r_error) *r_error=err;
+ return valid;
+ }
+
+ bool dvalid = true;
+ bool rvalid = true;
+
+ if(!FileAccess::exists(custom_debug_binary)) {
+ dvalid = false;
+ err = "Custom debug binary not found.\n";
+ }
+
+ if(!FileAccess::exists(custom_release_binary)) {
+ rvalid = false;
+ err = "Custom release binary not found.\n";
+ }
+
+ if (dvalid || rvalid)
+ valid = true;
+ else
+ valid = false;
+
+ if (r_error)
+ *r_error=err;
+ return valid;
+}
+
+
+EditorExportPlatformPC::EditorExportPlatformPC() {
+
+ export_mode=EXPORT_PACK;
+ use64=true;
+}
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+EditorImportExport* EditorImportExport::singleton=NULL;
+
+void EditorImportExport::add_import_plugin(const Ref<EditorImportPlugin>& p_plugin) {
+
+ // Need to make sure the name is unique if we are going to lookup by it
+ ERR_FAIL_COND(by_idx.has(p_plugin->get_name()));
+
+ by_idx[ p_plugin->get_name() ]=plugins.size();
+ plugins.push_back(p_plugin);
+}
+
+void EditorImportExport::remove_import_plugin(const Ref<EditorImportPlugin>& p_plugin) {
+
+ String plugin_name = p_plugin->get_name();
+
+ // Keep the indices the same
+ // Find the index of the target plugin
+ ERR_FAIL_COND(!by_idx.has(plugin_name));
+ int idx = by_idx[plugin_name];
+ int last_idx = plugins.size() - 1;
+
+ // Swap the last plugin and the target one
+ SWAP(plugins[idx], plugins[last_idx]);
+
+ // Update the index of the old last one
+ by_idx[plugins[idx]->get_name()] = idx;
+
+ // Remove the target plugin's by_idx entry
+ by_idx.erase(plugin_name);
+
+ // Erase the plugin
+ plugins.remove(last_idx);
+}
+
+int EditorImportExport::get_import_plugin_count() const{
+
+ return plugins.size();
+}
+Ref<EditorImportPlugin> EditorImportExport::get_import_plugin(int p_idx) const{
+
+ ERR_FAIL_INDEX_V(p_idx,plugins.size(),Ref<EditorImportPlugin>());
+ return plugins[p_idx];
+
+}
+
+
+
+Ref<EditorImportPlugin> EditorImportExport::get_import_plugin_by_name(const String& p_string) const{
+
+ ERR_FAIL_COND_V( !by_idx.has(p_string), Ref<EditorImportPlugin>());
+ return plugins[ by_idx[p_string] ];
+}
+
+void EditorImportExport::add_export_plugin(const Ref<EditorExportPlugin>& p_plugin) {
+
+ ERR_FAIL_COND( p_plugin.is_null() );
+
+ export_plugins.push_back(p_plugin);
+}
+
+void EditorImportExport::remove_export_plugin(const Ref<EditorExportPlugin>& p_plugin) {
+
+ ERR_FAIL_COND( p_plugin.is_null() );
+ export_plugins.erase(p_plugin);
+}
+
+int EditorImportExport::get_export_plugin_count() const{
+
+ return export_plugins.size();
+}
+Ref<EditorExportPlugin> EditorImportExport::get_export_plugin(int p_idx) const{
+
+ ERR_FAIL_INDEX_V(p_idx,export_plugins.size(),Ref<EditorExportPlugin>());
+ return export_plugins[p_idx];
+}
+
+void EditorImportExport::set_export_file_action(const StringName& p_file, FileAction p_action) {
+
+ if (p_action==ACTION_NONE) {
+
+ files.erase(p_file);
+ } else {
+
+ files[p_file]=p_action;
+ }
+
+}
+
+EditorImportExport::FileAction EditorImportExport::get_export_file_action(const StringName& p_file) const{
+
+
+ if (files.has(p_file))
+ return files[p_file];
+
+
+ return ACTION_NONE;
+}
+
+void EditorImportExport::get_export_file_list(List<StringName> *p_files){
+
+
+ for (Map<StringName,FileAction>::Element *E=files.front();E;E=E->next()) {
+
+ p_files->push_back(E->key());
+ }
+
+}
+
+void EditorImportExport::add_export_platform(const Ref<EditorExportPlatform>& p_export) {
+
+ exporters[p_export->get_name()]=p_export;
+}
+
+
+void EditorImportExport::get_export_platforms(List<StringName> *r_platforms) {
+
+ for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
+
+ r_platforms->push_back(E->key());
+ }
+}
+
+Ref<EditorExportPlatform> EditorImportExport::get_export_platform(const StringName& p_platform) {
+
+ if (exporters.has(p_platform)) {
+ return exporters[p_platform];
+ } else {
+ return Ref<EditorExportPlatform>();
+ }
+}
+
+
+bool EditorImportExport::poll_export_platforms() {
+
+ bool changed=false;
+ for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
+
+ if (E->get()->poll_devices())
+ changed=true;
+ }
+
+ return changed;
+
+}
+
+void EditorImportExport::set_export_filter(ExportFilter p_enable) {
+
+ export_filter=p_enable;
+}
+
+EditorImportExport::ExportFilter EditorImportExport::get_export_filter() const{
+
+ return export_filter;
+}
+
+void EditorImportExport::set_export_custom_filter(const String& p_custom_filter){
+ export_custom_filter=p_custom_filter;
+}
+void EditorImportExport::set_export_custom_filter_exclude(const String& p_custom_filter){
+ export_custom_filter_exclude=p_custom_filter;
+}
+String EditorImportExport::get_export_custom_filter() const{
+ return export_custom_filter;
+}
+String EditorImportExport::get_export_custom_filter_exclude() const{
+ return export_custom_filter_exclude;
+}
+
+void EditorImportExport::set_export_image_action(ImageAction p_action) {
+
+ image_action=p_action;
+}
+
+EditorImportExport::ImageAction EditorImportExport::get_export_image_action() const{
+
+ return image_action;
+}
+
+void EditorImportExport::set_export_image_shrink(float p_shrink) {
+
+ image_shrink=p_shrink;
+}
+
+float EditorImportExport::get_export_image_shrink() const{
+
+ return image_shrink;
+}
+
+
+void EditorImportExport::set_export_image_quality(float p_quality){
+
+ image_action_compress_quality=p_quality;
+}
+
+float EditorImportExport::get_export_image_quality() const{
+
+ return image_action_compress_quality;
+}
+
+void EditorImportExport::image_export_group_create(const StringName& p_name) {
+
+ ERR_FAIL_COND(image_groups.has(p_name));
+ ImageGroup ig;
+ ig.action=IMAGE_ACTION_NONE; //default
+ ig.make_atlas=false;
+ ig.shrink=1;
+ ig.lossy_quality=0.7;
+ image_groups[p_name]=ig;
+
+
+}
+
+
+bool EditorImportExport::image_export_has_group(const StringName& p_name) const {
+
+ return image_groups.has(p_name);
+}
+void EditorImportExport::image_export_get_groups(List<StringName> *r_name) const {
+
+ for (Map<StringName,ImageGroup>::Element *E=image_groups.front();E;E=E->next()) {
+
+ r_name->push_back(E->key());
+ }
+}
+
+void EditorImportExport::image_export_group_remove(const StringName& p_name){
+
+ ERR_FAIL_COND(!image_groups.has(p_name));
+ image_groups.erase(p_name);
+}
+void EditorImportExport::image_export_group_set_image_action(const StringName& p_export_group,ImageAction p_action){
+
+ ERR_FAIL_COND(!image_groups.has(p_export_group));
+ image_groups[p_export_group].action=p_action;
+
+}
+EditorImportExport::ImageAction EditorImportExport::image_export_group_get_image_action(const StringName& p_export_group) const{
+
+ ERR_FAIL_COND_V(!image_groups.has(p_export_group),IMAGE_ACTION_NONE);
+ return image_groups[p_export_group].action;
+
+}
+void EditorImportExport::image_export_group_set_make_atlas(const StringName& p_export_group,bool p_make){
+
+ ERR_FAIL_COND(!image_groups.has(p_export_group));
+ image_groups[p_export_group].make_atlas=p_make;
+
+}
+bool EditorImportExport::image_export_group_get_make_atlas(const StringName& p_export_group) const{
+
+ ERR_FAIL_COND_V(!image_groups.has(p_export_group),false);
+ return image_groups[p_export_group].make_atlas;
+
+}
+void EditorImportExport::image_export_group_set_shrink(const StringName& p_export_group,float p_amount){
+ ERR_FAIL_COND(!image_groups.has(p_export_group));
+ image_groups[p_export_group].shrink=p_amount;
+
+}
+float EditorImportExport::image_export_group_get_shrink(const StringName& p_export_group) const{
+
+ ERR_FAIL_COND_V(!image_groups.has(p_export_group),1);
+ return image_groups[p_export_group].shrink;
+
+}
+
+void EditorImportExport::image_export_group_set_lossy_quality(const StringName& p_export_group,float p_amount){
+ ERR_FAIL_COND(!image_groups.has(p_export_group));
+ image_groups[p_export_group].lossy_quality=p_amount;
+
+}
+float EditorImportExport::image_export_group_get_lossy_quality(const StringName& p_export_group) const{
+
+ ERR_FAIL_COND_V(!image_groups.has(p_export_group),1);
+ return image_groups[p_export_group].lossy_quality;
+
+}
+
+StringName EditorImportExport::image_get_export_group(const StringName& p_image) const {
+
+ if (image_group_files.has(p_image))
+ return image_group_files[p_image];
+ else
+ return StringName();
+
+}
+
+void EditorImportExport::image_add_to_export_group(const StringName& p_image,const StringName& p_export_group) {
+
+
+ bool emptygroup = String(p_export_group)==String();
+ ERR_FAIL_COND(!emptygroup && !image_groups.has(p_export_group));
+
+ if (emptygroup)
+ image_group_files.erase(p_image);
+ else
+ image_group_files[p_image]=p_export_group;
+}
+
+void EditorImportExport::image_export_get_images_in_group(const StringName& p_group,List<StringName> *r_images) const {
+
+ for (Map<StringName,StringName>::Element *E=image_group_files.front();E;E=E->next()) {
+
+ if (p_group==E->get())
+ r_images->push_back(E->key());
+ }
+}
+
+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 );
+
+ Error err = cf->load("res://export.cfg");
+ if (err!=OK)
+ return; //no export config to be loaded!
+
+
+ export_custom_filter=cf->get_value("export_filter","filter");
+ export_custom_filter_exclude=cf->get_value("export_filter","filter_exclude");
+ String t=cf->get_value("export_filter","type");
+ if (t=="selected")
+ export_filter=EXPORT_SELECTED;
+ else if (t=="resources")
+ export_filter=EXPORT_RESOURCES;
+ else if (t=="all")
+ export_filter=EXPORT_ALL;
+
+ if (cf->has_section("convert_images")) {
+
+ String ci = "convert_images";
+ String action = cf->get_value(ci,"action");
+ if (action=="none")
+ image_action=IMAGE_ACTION_NONE;
+ else if (action=="compress_ram")
+ image_action=IMAGE_ACTION_COMPRESS_RAM;
+ else if (action=="compress_disk")
+ image_action=IMAGE_ACTION_COMPRESS_DISK;
+
+ image_action_compress_quality = cf->get_value(ci,"compress_quality");
+ if (cf->has_section_key(ci,"shrink"))
+ image_shrink = cf->get_value(ci,"shrink");
+ else
+ image_shrink=1;
+ String formats=cf->get_value(ci,"formats");
+ Vector<String> f = formats.split(",");
+ image_formats.clear();
+ for(int i=0;i<f.size();i++) {
+ image_formats.insert(f[i].strip_edges());
+ }
+ }
+
+ if (cf->has_section("convert_scenes")) {
+
+ convert_text_scenes = cf->get_value("convert_scenes","convert_text_scenes");
+ }
+
+
+ if (cf->has_section("export_filter_files")) {
+
+
+ String eff = "export_filter_files";
+ List<String> k;
+ cf->get_section_keys(eff,&k);
+ for(List<String>::Element *E=k.front();E;E=E->next()) {
+
+ String val = cf->get_value(eff,E->get());
+ if (val=="copy") {
+ files[E->get()]=ACTION_COPY;
+ } else if (val=="bundle") {
+ files[E->get()]=ACTION_BUNDLE;
+ }
+ }
+ }
+
+ List<String> sect;
+
+ cf->get_sections(&sect);
+
+ for(List<String>::Element *E=sect.front();E;E=E->next()) {
+
+ String s = E->get();
+ if (!s.begins_with("platform:"))
+ continue;
+ String p = s.substr(s.find(":")+1,s.length());
+
+ if (!exporters.has(p))
+ continue;
+
+ Ref<EditorExportPlatform> ep = exporters[p];
+ if (!ep.is_valid()) {
+ continue;
+ }
+ List<String> keys;
+ cf->get_section_keys(s,&keys);
+ for(List<String>::Element *F=keys.front();F;F=F->next()) {
+ ep->set(F->get(),cf->get_value(s,F->get()));
+ }
+ }
+
+ //save image groups
+
+ if (cf->has_section("image_groups")) {
+
+ sect.clear();
+ cf->get_section_keys("image_groups",&sect);
+ for(List<String>::Element *E=sect.front();E;E=E->next()) {
+
+ Dictionary d = cf->get_value("image_groups",E->get());
+ ImageGroup g;
+ g.action=IMAGE_ACTION_NONE;
+ g.make_atlas=false;
+ g.lossy_quality=0.7;
+ g.shrink=1;
+
+ if (d.has("action")) {
+ String action=d["action"];
+ if (action=="compress_ram")
+ g.action=IMAGE_ACTION_COMPRESS_RAM;
+ else if (action=="compress_disk")
+ g.action=IMAGE_ACTION_COMPRESS_DISK;
+ else if (action=="keep")
+ g.action=IMAGE_ACTION_KEEP;
+ }
+
+ if (d.has("atlas"))
+ g.make_atlas=d["atlas"];
+ if (d.has("lossy_quality"))
+ g.lossy_quality=d["lossy_quality"];
+ if (d.has("shrink")) {
+
+ g.shrink=d["shrink"];
+ g.shrink=CLAMP(g.shrink,1,8);
+ }
+
+ image_groups[E->get()]=g;
+
+ }
+
+ if (cf->has_section_key("image_group_files","files")) {
+
+ Vector<String> sa=cf->get_value("image_group_files","files");
+ if (sa.size()%2==0) {
+ for(int i=0;i<sa.size();i+=2) {
+ image_group_files[sa[i]]=sa[i+1];
+ }
+ }
+ }
+
+ }
+
+
+ if (cf->has_section("script")) {
+
+ if (cf->has_section_key("script","action")) {
+
+ String action = cf->get_value("script","action");
+ if (action=="compile")
+ script_action=SCRIPT_ACTION_COMPILE;
+ else if (action=="encrypt")
+ script_action=SCRIPT_ACTION_ENCRYPT;
+ else
+ script_action=SCRIPT_ACTION_NONE;
+
+ }
+
+ if (cf->has_section_key("script","encrypt_key")) {
+
+ script_key = cf->get_value("script","encrypt_key");
+ }
+ }
+
+ 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");
+
+ if (cf->has_section_key("convert_samples","trim"))
+ sample_action_trim=cf->get_value("convert_samples","trim");
+ }
+
+
+
+}
+
+
+
+
+
+void EditorImportExport::save_config() {
+
+ Ref<ConfigFile> cf = memnew( ConfigFile );
+
+ switch(export_filter) {
+ case EXPORT_SELECTED: cf->set_value("export_filter","type","selected"); break;
+ case EXPORT_RESOURCES: cf->set_value("export_filter","type","resources"); break;
+ case EXPORT_ALL: cf->set_value("export_filter","type","all"); break;
+ }
+
+ cf->set_value("export_filter","filter",export_custom_filter);
+ cf->set_value("export_filter", "filter_exclude",export_custom_filter_exclude);
+
+ String file_action_section = "export_filter_files";
+
+ for (Map<StringName,FileAction>::Element *E=files.front();E;E=E->next()) {
+
+ String f=E->key();
+ String a;
+ switch (E->get()) {
+ case ACTION_NONE: {}
+ case ACTION_COPY: a="copy"; break;
+ case ACTION_BUNDLE: a="bundle"; break;
+ }
+
+ cf->set_value(file_action_section,f,a);
+ }
+
+
+ for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
+
+ String pname = "platform:"+String(E->key());
+
+ Ref<EditorExportPlatform> ep = E->get();
+
+ List<PropertyInfo> pl;
+ ep->get_property_list(&pl);
+
+ for (List<PropertyInfo>::Element *F=pl.front();F;F=F->next()) {
+
+ cf->set_value(pname,F->get().name,ep->get(F->get().name));
+ }
+
+ }
+
+ switch(image_action) {
+ case IMAGE_ACTION_NONE: cf->set_value("convert_images","action","none"); break;
+ case IMAGE_ACTION_COMPRESS_RAM: cf->set_value("convert_images","action","compress_ram"); break;
+ case IMAGE_ACTION_COMPRESS_DISK: cf->set_value("convert_images","action","compress_disk"); break;
+ }
+
+ cf->set_value("convert_images","shrink",image_shrink);
+ cf->set_value("convert_images","compress_quality",image_action_compress_quality);
+
+ String formats;
+ for(Set<String>::Element *E=image_formats.front();E;E=E->next()) {
+
+ if (E!=image_formats.front())
+ formats+=",";
+ formats+=E->get();
+ }
+
+ cf->set_value("convert_images","formats",formats);
+
+ //save image groups
+
+ for(Map<StringName,ImageGroup>::Element *E=image_groups.front();E;E=E->next()) {
+
+ Dictionary d;
+ switch(E->get().action) {
+ case IMAGE_ACTION_NONE: d["action"]="default"; break;
+ case IMAGE_ACTION_COMPRESS_RAM: d["action"]="compress_ram"; break;
+ case IMAGE_ACTION_COMPRESS_DISK: d["action"]="compress_disk"; break;
+ case IMAGE_ACTION_KEEP: d["action"]="keep"; break;
+ }
+
+
+ d["atlas"]=E->get().make_atlas;
+ d["shrink"]=E->get().shrink;
+ d["lossy_quality"]=E->get().lossy_quality;
+ cf->set_value("image_groups",E->key(),d);
+
+ }
+
+ if (image_groups.size() && image_group_files.size()){
+
+ Vector<String> igfkeys;
+ igfkeys.resize(image_group_files.size());
+ int idx=0;
+ for (Map<StringName,StringName>::Element *E=image_group_files.front();E;E=E->next()) {
+ igfkeys[idx++]=E->key();
+ }
+ igfkeys.sort();
+
+ Vector<String> igfsave;
+ igfsave.resize(image_group_files.size()*2);
+ idx=0;
+ for (int i=0;i<igfkeys.size();++i) {
+
+ igfsave[idx++]=igfkeys[i];
+ igfsave[idx++]=image_group_files[igfkeys[i]];
+ }
+ cf->set_value("image_group_files","files",igfsave);
+ }
+
+ switch(script_action) {
+ case SCRIPT_ACTION_NONE: cf->set_value("script","action","none"); break;
+ case SCRIPT_ACTION_COMPILE: cf->set_value("script","action","compile"); break;
+ 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) {
+ case SAMPLE_ACTION_NONE: cf->set_value("convert_samples","action","none"); break;
+ case SAMPLE_ACTION_COMPRESS_RAM: cf->set_value("convert_samples","action","compress_ram"); break;
+ }
+
+ cf->set_value("convert_samples","max_hz",sample_action_max_hz);
+ cf->set_value("convert_samples","trim",sample_action_trim);
+
+ cf->save("res://export.cfg");
+
+}
+
+
+void EditorImportExport::script_set_action(ScriptAction p_action) {
+
+ script_action=p_action;
+}
+
+EditorImportExport::ScriptAction EditorImportExport::script_get_action() const{
+
+ return script_action;
+}
+
+void EditorImportExport::script_set_encryption_key(const String& p_key){
+
+ script_key=p_key;
+}
+String EditorImportExport::script_get_encryption_key() const{
+
+ return script_key;
+}
+
+
+void EditorImportExport::sample_set_action(SampleAction p_action) {
+
+ sample_action=p_action;
+}
+
+EditorImportExport::SampleAction EditorImportExport::sample_get_action() const{
+
+ return sample_action;
+}
+
+void EditorImportExport::sample_set_max_hz(int p_hz){
+
+ sample_action_max_hz=p_hz;
+}
+int EditorImportExport::sample_get_max_hz() const{
+
+ return sample_action_max_hz;
+}
+
+void EditorImportExport::sample_set_trim(bool p_trim){
+
+ sample_action_trim=p_trim;
+}
+bool EditorImportExport::sample_get_trim() const{
+
+ return sample_action_trim;
+}
+
+PoolVector<String> EditorImportExport::_get_export_file_list() {
+
+ PoolVector<String> fl;
+ for (Map<StringName,FileAction>::Element *E=files.front();E;E=E->next()) {
+
+ fl.push_back(E->key());
+ }
+
+ return fl;
+}
+
+PoolVector<String> EditorImportExport::_get_export_platforms() {
+
+ PoolVector<String> ep;
+ for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
+
+ ep.push_back(E->key());
+ }
+
+ return ep;
+
+}
+
+void EditorImportExport::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("add_import_plugin","plugin:EditorImportPlugin"),&EditorImportExport::add_import_plugin);
+ ClassDB::bind_method(D_METHOD("remove_import_plugin","plugin:EditorImportPlugin"),&EditorImportExport::remove_import_plugin);
+ ClassDB::bind_method(D_METHOD("get_import_plugin_count"),&EditorImportExport::get_import_plugin_count);
+ ClassDB::bind_method(D_METHOD("get_import_plugin:EditorImportPlugin","idx"),&EditorImportExport::get_import_plugin);
+ ClassDB::bind_method(D_METHOD("get_import_plugin_by_name:EditorImportPlugin","name"),&EditorImportExport::get_import_plugin_by_name);
+
+ ClassDB::bind_method(D_METHOD("add_export_plugin","plugin:EditorExportPlugin"),&EditorImportExport::add_export_plugin);
+ ClassDB::bind_method(D_METHOD("remove_export_plugin","plugin:EditorExportPlugin"),&EditorImportExport::remove_export_plugin);
+ ClassDB::bind_method(D_METHOD("get_export_plugin_count"),&EditorImportExport::get_export_plugin_count);
+ ClassDB::bind_method(D_METHOD("get_export_plugin:EditorExportPlugin","idx"),&EditorImportExport::get_export_plugin);
+
+ ClassDB::bind_method(D_METHOD("set_export_file_action","file","action"),&EditorImportExport::set_export_file_action);
+ ClassDB::bind_method(D_METHOD("get_export_file_action","file"),&EditorImportExport::get_export_file_action);
+ ClassDB::bind_method(D_METHOD("get_export_file_list"),&EditorImportExport::_get_export_file_list);
+
+ ClassDB::bind_method(D_METHOD("add_export_platform","platform:EditorExportplatform"),&EditorImportExport::add_export_platform);
+ //ClassDB::bind_method(D_METHOD("remove_export_platform","platform:EditorExportplatform"),&EditorImportExport::add_export_platform);
+ ClassDB::bind_method(D_METHOD("get_export_platform:EditorExportPlatform","name"),&EditorImportExport::get_export_platform);
+ ClassDB::bind_method(D_METHOD("get_export_platforms"),&EditorImportExport::_get_export_platforms);
+
+ ClassDB::bind_method(D_METHOD("set_export_filter","filter"),&EditorImportExport::set_export_filter);
+ ClassDB::bind_method(D_METHOD("get_export_filter"),&EditorImportExport::get_export_filter);
+
+ ClassDB::bind_method(D_METHOD("set_export_custom_filter","filter"),&EditorImportExport::set_export_custom_filter);
+ ClassDB::bind_method(D_METHOD("get_export_custom_filter"),&EditorImportExport::get_export_custom_filter);
+
+ ClassDB::bind_method(D_METHOD("set_export_custom_filter_exclude","filter_exclude"),&EditorImportExport::set_export_custom_filter_exclude);
+ ClassDB::bind_method(D_METHOD("get_export_custom_filter_exclude"),&EditorImportExport::get_export_custom_filter_exclude);
+
+
+ ClassDB::bind_method(D_METHOD("image_export_group_create"),&EditorImportExport::image_export_group_create);
+ ClassDB::bind_method(D_METHOD("image_export_group_remove"),&EditorImportExport::image_export_group_remove);
+ ClassDB::bind_method(D_METHOD("image_export_group_set_image_action"),&EditorImportExport::image_export_group_set_image_action);
+ ClassDB::bind_method(D_METHOD("image_export_group_set_make_atlas"),&EditorImportExport::image_export_group_set_make_atlas);
+ ClassDB::bind_method(D_METHOD("image_export_group_set_shrink"),&EditorImportExport::image_export_group_set_shrink);
+ ClassDB::bind_method(D_METHOD("image_export_group_get_image_action"),&EditorImportExport::image_export_group_get_image_action);
+ ClassDB::bind_method(D_METHOD("image_export_group_get_make_atlas"),&EditorImportExport::image_export_group_get_make_atlas);
+ ClassDB::bind_method(D_METHOD("image_export_group_get_shrink"),&EditorImportExport::image_export_group_get_shrink);
+ ClassDB::bind_method(D_METHOD("image_add_to_export_group"),&EditorImportExport::image_add_to_export_group);
+ ClassDB::bind_method(D_METHOD("script_set_action"),&EditorImportExport::script_set_action);
+ ClassDB::bind_method(D_METHOD("script_set_encryption_key"),&EditorImportExport::script_set_encryption_key);
+ ClassDB::bind_method(D_METHOD("script_get_action"),&EditorImportExport::script_get_action);
+ ClassDB::bind_method(D_METHOD("script_get_encryption_key"),&EditorImportExport::script_get_encryption_key);
+
+
+
+ BIND_CONSTANT( ACTION_NONE );
+ BIND_CONSTANT( ACTION_COPY );
+ BIND_CONSTANT( ACTION_BUNDLE );
+
+ BIND_CONSTANT( EXPORT_SELECTED );
+ BIND_CONSTANT( EXPORT_RESOURCES );
+ BIND_CONSTANT( EXPORT_ALL );
+
+ BIND_CONSTANT( IMAGE_ACTION_NONE );
+ BIND_CONSTANT( IMAGE_ACTION_COMPRESS_DISK );
+ BIND_CONSTANT( IMAGE_ACTION_COMPRESS_RAM );
+ BIND_CONSTANT( IMAGE_ACTION_KEEP );
+
+ BIND_CONSTANT( SCRIPT_ACTION_NONE );
+ BIND_CONSTANT( SCRIPT_ACTION_COMPILE );
+ BIND_CONSTANT( SCRIPT_ACTION_ENCRYPT );
+};
+
+
+
+EditorImportExport::EditorImportExport() {
+
+ export_filter=EXPORT_RESOURCES;
+ singleton=this;
+ image_action=IMAGE_ACTION_NONE;
+ image_action_compress_quality=0.7;
+ image_formats.insert("png");
+ image_shrink=1;
+
+
+ script_action=SCRIPT_ACTION_COMPILE;
+
+ sample_action=SAMPLE_ACTION_NONE;
+ sample_action_max_hz=44100;
+ sample_action_trim=false;
+
+ convert_text_scenes=true;
+
+}
+
+
+
+EditorImportExport::~EditorImportExport() {
+
+
+
+}
+#endif
diff --git a/editor/editor_export.h b/editor/editor_export.h
new file mode 100644
index 0000000000..8a9dc965e5
--- /dev/null
+++ b/editor/editor_export.h
@@ -0,0 +1,297 @@
+/*************************************************************************/
+/* editor_import_export.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_EXPORT_H
+#define EDITOR_EXPORT_H
+
+
+
+#include "resource.h"
+#include "scene/main/node.h"
+#include "scene/resources/texture.h"
+#include "scene/main/timer.h"
+
+class EditorProgress;
+class FileAccess;
+class EditorExportPlatform;
+class EditorFileSystemDirectory;
+
+class EditorExportPreset : public Reference {
+
+ GDCLASS( EditorExportPreset,Reference )
+public:
+ enum ExportFilter {
+ EXPORT_ALL_RESOURCES,
+ EXPORT_SELECTED_SCENES,
+ EXPORT_SELECTED_RESOURCES,
+ };
+
+private:
+
+ Ref<EditorExportPlatform> platform;
+ ExportFilter export_filter;
+ String include_filter;
+ String exclude_filter;
+
+ String exporter;
+ Set<String> selected_files;
+ bool runnable;
+
+ Vector<String> patches;
+
+
+friend class EditorExport;
+friend class EditorExportPlatform;
+
+ List<PropertyInfo> properties;
+ Map<StringName,Variant> values;
+
+ String name;
+protected:
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+ Ref<EditorExportPlatform> get_platform() const;
+ bool has(const StringName& p_property) const { return values.has(p_property); }
+
+ Vector<String> get_files_to_export() const;
+
+ void add_export_file(const String& p_path);
+ void remove_export_file(const String& p_path);
+ bool has_export_file(const String& p_path);
+
+ void set_name(const String& p_name);
+ String get_name() const;
+
+ void set_runnable(bool p_enable);
+ bool is_runnable() const;
+
+ void set_export_filter(ExportFilter p_filter);
+ ExportFilter get_export_filter() const;
+
+ void set_include_filter(const String& p_include);
+ String get_include_filter() const;
+
+ void set_exclude_filter(const String& p_exclude);
+ String get_exclude_filter() const;
+
+ void add_patch(const String& p_path,int p_at_pos=-1);
+ void set_patch(int p_index,const String& p_path);
+ String get_patch(int p_index);
+ void remove_patch(int p_idx);
+ Vector<String> get_patches() const;
+
+ const List<PropertyInfo>& get_properties() const { return properties; }
+
+ EditorExportPreset();
+};
+
+
+class EditorExportPlatform : public Reference {
+
+ GDCLASS( EditorExportPlatform,Reference )
+
+public:
+
+ typedef Error (*EditorExportSaveFunction)(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
+
+private:
+
+ struct SavedData {
+
+ uint64_t ofs;
+ uint64_t size;
+ Vector<uint8_t> md5;
+ CharString path_utf8;
+
+ bool operator<(const SavedData& p_data) const {
+ return path_utf8 < p_data.path_utf8;
+ }
+ };
+
+ struct PackData {
+
+ FileAccess *f;
+ Vector<SavedData> file_ofs;
+ EditorProgress *ep;
+ };
+
+ struct ZipData {
+
+ void* zip;
+ EditorProgress *ep;
+
+ };
+
+ void _export_find_resources(EditorFileSystemDirectory *p_dir,Set<String>& p_paths);
+ void _export_find_dependencies(const String& p_path,Set<String>& p_paths);
+
+ void gen_debug_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);
+
+
+protected:
+
+ virtual void get_preset_features(const Ref<EditorExportPreset>& p_preset,List<String> *r_features)=0;
+ String find_export_template(String template_file_name, String *err=NULL) const;
+
+public:
+
+
+ struct ExportOption {
+ PropertyInfo option;
+ Variant default_value;
+
+ ExportOption(const PropertyInfo& p_info,const Variant& p_default) { option=p_info; default_value=p_default; }
+ ExportOption() {}
+ };
+
+ virtual Ref<EditorExportPreset> create_preset();
+
+ virtual void get_export_options(List<ExportOption> *r_options)=0;
+ virtual String get_name() const =0;
+ virtual Ref<Texture> get_logo() const =0;
+
+
+ Error export_project_files(const Ref<EditorExportPreset>& p_preset,EditorExportSaveFunction p_func, void* p_udata);
+
+ Error save_pack(const Ref<EditorExportPreset>& p_preset,const String& p_path);
+ Error save_zip(const Ref<EditorExportPreset>& p_preset,const String& p_path);
+
+
+ virtual bool poll_devices() { return false; }
+ virtual int get_device_count() const { return 0; }
+ virtual String get_device_name(int p_device) const { return ""; }
+ virtual String get_device_info(int p_device) const { return ""; }
+
+ enum DebugFlags {
+ DEBUG_FLAG_DUMB_CLIENT=1,
+ DEBUG_FLAG_REMOTE_DEBUG=2,
+ DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST=4,
+ DEBUG_FLAG_VIEW_COLLISONS=8,
+ DEBUG_FLAG_VIEW_NAVIGATION=16,
+ };
+
+ virtual Error run(int p_device,int p_debug_flags) { return OK; }
+
+ virtual bool can_export(const Ref<EditorExportPreset>& p_preset,String &r_error,bool &r_missing_templates) const=0;
+
+ virtual String get_binary_extension() const=0;
+ virtual Error export_project(const Ref<EditorExportPreset>& p_preset,bool p_debug,const String& p_path,int p_flags=0)=0;
+
+ EditorExportPlatform();
+};
+
+
+class EditorExport : public Node {
+ GDCLASS(EditorExport,Node);
+
+ Vector<Ref<EditorExportPlatform> > export_platforms;
+ Vector<Ref<EditorExportPreset> > export_presets;
+
+ Timer *save_timer;
+ bool block_save;
+
+ static EditorExport *singleton;
+
+ void _save();
+protected:
+
+friend class EditorExportPreset;
+ void save_presets();
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ static EditorExport * get_singleton() { return singleton; }
+
+ void add_export_platform(const Ref<EditorExportPlatform>& p_platform);
+ int get_export_platform_count();
+ Ref<EditorExportPlatform> get_export_platform(int p_idx);
+
+
+ void add_export_preset(const Ref<EditorExportPreset>& p_preset,int p_at_pos=-1);
+ int get_export_preset_count() const;
+ Ref<EditorExportPreset> get_export_preset(int p_idx);
+ void remove_export_preset(int p_idx);
+
+ void load_config();
+
+ EditorExport();
+ ~EditorExport();
+};
+
+
+
+
+class EditorExportPlatformPC : public EditorExportPlatform {
+
+ GDCLASS( EditorExportPlatformPC,EditorExportPlatform )
+
+ Ref<ImageTexture> logo;
+ String name;
+ String extension;
+
+ String release_file_32;
+ String release_file_64;
+ String debug_file_32;
+ String debug_file_64;
+
+public:
+
+ virtual void get_preset_features(const Ref<EditorExportPreset>& p_preset,List<String>* r_features);
+
+ virtual void get_export_options(List<ExportOption> *r_options);
+
+ virtual String get_name() const;
+ virtual Ref<Texture> get_logo() const;
+
+ virtual bool can_export(const Ref<EditorExportPreset>& p_preset,String &r_error,bool &r_missing_templates) const;
+ virtual String get_binary_extension() const;
+ virtual Error export_project(const Ref<EditorExportPreset>& p_preset,bool p_debug,const String& p_path,int p_flags=0);
+
+ void set_extension(const String& p_extension);
+ void set_name(const String& p_name);
+
+ void set_logo(const Ref<Texture>& p_loco);
+
+ void set_release_64(const String& p_file);
+ void set_release_32(const String& p_file);
+ void set_debug_64(const String& p_file);
+ void set_debug_32(const String& p_file);
+
+ EditorExportPlatformPC();
+};
+
+
+#endif // EDITOR_IMPORT_EXPORT_H
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
new file mode 100644
index 0000000000..bfaf1906d8
--- /dev/null
+++ b/editor/editor_file_dialog.cpp
@@ -0,0 +1,1531 @@
+/*************************************************************************/
+/* editor_file_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_file_dialog.h"
+
+#include "scene/gui/label.h"
+#include "scene/gui/center_container.h"
+#include "print_string.h"
+#include "os/keyboard.h"
+#include "editor_resource_preview.h"
+#include "editor_settings.h"
+#include "scene/gui/margin_container.h"
+#include "os/file_access.h"
+#include "editor_scale.h"
+
+EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func=NULL;
+EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func=NULL;
+
+EditorFileDialog::RegisterFunc EditorFileDialog::register_func=NULL;
+EditorFileDialog::RegisterFunc EditorFileDialog::unregister_func=NULL;
+
+
+VBoxContainer *EditorFileDialog::get_vbox() {
+ return vbox;
+
+}
+
+void EditorFileDialog::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ mode_thumbnails->set_icon(get_icon("FileThumbnail","EditorIcons"));
+ mode_list->set_icon(get_icon("FileList","EditorIcons"));
+ 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"));
+
+ } else if (p_what==NOTIFICATION_PROCESS) {
+
+ if (preview_waiting) {
+ preview_wheel_timeout-=get_process_delta_time();
+ if (preview_wheel_timeout<=0) {
+ preview_wheel_index++;
+ if (preview_wheel_index>=8)
+ preview_wheel_index=0;
+ Ref<Texture> frame = get_icon("WaitPreview"+itos(preview_wheel_index+1),"EditorIcons");
+ preview->set_texture(frame);
+ preview_wheel_timeout=0.1;
+ }
+ }
+ } 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("filesystem/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("filesystem/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()) {
+
+ if (p_event.key.pressed) {
+
+ bool handled=false;
+
+ if (ED_IS_SHORTCUT("file_dialog/go_back", p_event)) {
+ _go_back();
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/go_forward", p_event)) {
+ _go_forward();
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/go_up", p_event)) {
+ _go_up();
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/refresh", p_event)) {
+ invalidate();
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/toggle_hidden_files", p_event)) {
+ bool show=!show_hidden_files;
+ set_show_hidden_files(show);
+ EditorSettings::get_singleton()->set("filesystem/file_dialog/show_hidden_files",show);
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/toggle_favorite", p_event)) {
+ _favorite_toggled(favorite->is_pressed());
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/toggle_mode", p_event)) {
+ if (mode_thumbnails->is_pressed()) {
+ set_display_mode(DISPLAY_LIST);
+ } else {
+ set_display_mode(DISPLAY_THUMBNAILS);
+ }
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/create_folder", p_event)) {
+ _make_dir();
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) {
+ dir->grab_focus();
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/move_favorite_up", p_event)) {
+ _favorite_move_up();
+ handled=true;
+ }
+ if (ED_IS_SHORTCUT("file_dialog/move_favorite_down", p_event)) {
+ _favorite_move_down();
+ handled=true;
+ }
+
+ if (handled) {
+ accept_event();
+ }
+ }
+ }
+}
+
+void EditorFileDialog::set_enable_multiple_selection(bool p_enable) {
+
+ item_list->set_select_mode(p_enable?ItemList::SELECT_MULTI:ItemList::SELECT_SINGLE);
+
+};
+
+Vector<String> EditorFileDialog::get_selected_files() const {
+
+ Vector<String> list;
+ for(int i=0;i<item_list->get_item_count();i++) {
+ if (item_list->is_selected(i))
+ list.push_back(item_list->get_item_text(i));
+ }
+ return list;
+
+};
+
+void EditorFileDialog::update_dir() {
+
+ dir->set_text(dir_access->get_current_dir());
+}
+
+void EditorFileDialog::_dir_entered(String p_dir) {
+
+
+ dir_access->change_dir(p_dir);
+ file->set_text("");
+ invalidate();
+ update_dir();
+ _push_history();
+
+
+}
+
+void EditorFileDialog::_file_entered(const String& p_file) {
+
+ _action_pressed();
+}
+
+void EditorFileDialog::_save_confirm_pressed() {
+ String f=dir_access->get_current_dir().plus_file(file->get_text());
+ _save_to_recent();
+ emit_signal("file_selected",f);
+ hide();
+}
+
+void EditorFileDialog::_post_popup() {
+
+ ConfirmationDialog::_post_popup();
+ if (invalidated) {
+ update_file_list();
+ invalidated=false;
+ }
+ if (mode==MODE_SAVE_FILE)
+ file->grab_focus();
+ else
+ item_list->grab_focus();
+
+ if (is_visible_in_tree() && get_current_file()!="")
+ _request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
+
+ if (is_visible_in_tree()) {
+ Ref<Texture> folder = get_icon("folder","FileDialog");
+ recent->clear();
+
+
+ bool res = access==ACCESS_RESOURCES;
+ Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
+ for(int i=0;i<recentd.size();i++) {
+ bool cres = recentd[i].begins_with("res://");
+ if (cres!=res)
+ continue;
+ String name = recentd[i];
+ if (res && name=="res://") {
+ name="/";
+ } else {
+ name=name.get_file()+"/";
+ }
+
+ //print_line("file: "+name);
+ recent->add_item(name,folder);
+ recent->set_item_metadata( recent->get_item_count()-1,recentd[i]);
+ }
+
+ local_history.clear();
+ local_history_pos=-1;
+ _push_history();
+
+ _update_favorites();
+ }
+
+ set_process_unhandled_input(true);
+
+}
+
+void EditorFileDialog::_thumbnail_result(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
+
+ if (display_mode==DISPLAY_LIST || p_preview.is_null())
+ return;
+
+ for(int i=0;i<item_list->get_item_count();i++) {
+ Dictionary d = item_list->get_item_metadata(i);
+ String pname = d["path"];
+ if (pname==p_path) {
+ item_list->set_item_icon(i,p_preview);
+ item_list->set_item_tag_icon(i,Ref<Texture>());
+ }
+ }
+}
+
+void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
+
+ set_process(false);
+ preview_waiting=false;
+
+ if (p_preview.is_valid() && get_current_path()==p_path) {
+
+
+ preview->set_texture(p_preview);
+ if (display_mode==DISPLAY_THUMBNAILS) {
+ preview_vb->hide();
+ } else {
+ preview_vb->show();
+ }
+
+ } else {
+ preview_vb->hide();
+ preview->set_texture(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);
+ preview_waiting=true;
+ preview_wheel_timeout=0;
+
+}
+
+void EditorFileDialog::_action_pressed() {
+
+ if (mode==MODE_OPEN_FILES) {
+
+
+ String fbase=dir_access->get_current_dir();
+
+ PoolVector<String> files;
+ for(int i=0;i<item_list->get_item_count();i++) {
+ if (item_list->is_selected(i))
+ files.push_back( fbase.plus_file(item_list->get_item_text(i) ));
+ }
+
+ if (files.size()) {
+ _save_to_recent();
+ emit_signal("files_selected",files);
+ hide();
+ }
+
+ return;
+ }
+
+ String f=dir_access->get_current_dir().plus_file(file->get_text());
+
+ if ((mode==MODE_OPEN_ANY || mode==MODE_OPEN_FILE) && dir_access->file_exists(f)) {
+ _save_to_recent();
+ emit_signal("file_selected",f);
+ hide();
+ }else if (mode==MODE_OPEN_ANY || mode==MODE_OPEN_DIR) {
+
+ String path=dir_access->get_current_dir();
+
+ path=path.replace("\\","/");
+
+ for(int i=0;i<item_list->get_item_count();i++) {
+ if (item_list->is_selected(i)) {
+ Dictionary d=item_list->get_item_metadata(i);
+ if (d["dir"]) {
+ path=path.plus_file(d["name"]);
+
+ break;
+ }
+ }
+ }
+
+ _save_to_recent();
+ emit_signal("dir_selected",path);
+ hide();
+ }
+
+ if (mode==MODE_SAVE_FILE) {
+
+ bool valid=false;
+
+ if (filter->get_selected()==filter->get_item_count()-1) {
+ valid=true; //match none
+ } else if (filters.size()>1 && filter->get_selected()==0) {
+ // match all filters
+ for (int i=0;i<filters.size();i++) {
+
+ String flt=filters[i].get_slice(";",0);
+ for (int j=0;j<flt.get_slice_count(",");j++) {
+
+ String str = flt.get_slice(",",j).strip_edges();
+ if (f.match(str)) {
+ valid=true;
+ break;
+ }
+ }
+ if (valid)
+ break;
+ }
+ } else {
+ int idx=filter->get_selected();
+ if (filters.size()>1)
+ idx--;
+ if (idx>=0 && idx<filters.size()) {
+
+ String flt=filters[idx].get_slice(";",0);
+ int filterSliceCount=flt.get_slice_count(",");
+ for (int j=0;j<filterSliceCount;j++) {
+
+ String str = (flt.get_slice(",",j).strip_edges());
+ if (f.match(str)) {
+ valid=true;
+ break;
+ }
+ }
+
+ if (!valid && filterSliceCount>0) {
+ String str = (flt.get_slice(",",0).strip_edges());
+ f+=str.substr(1, str.length()-1);
+ _request_single_thumbnail(get_current_dir().plus_file(f.get_file()));
+ file->set_text(f.get_file());
+ valid=true;
+ }
+ } else {
+ valid=true;
+ }
+ }
+
+
+ if (!valid) {
+
+ exterr->popup_centered_minsize(Size2(250,80)*EDSCALE);
+ return;
+
+ }
+
+ if (dir_access->file_exists(f) && !disable_overwrite_warning) {
+ confirm_save->set_text(TTR("File Exists, Overwrite?"));
+ confirm_save->popup_centered(Size2(200,80));
+ } else {
+
+ _save_to_recent();
+ emit_signal("file_selected",f);
+ hide();
+ }
+ }
+}
+
+void EditorFileDialog::_cancel_pressed() {
+
+ file->set_text("");
+ invalidate();
+ hide();
+}
+
+void EditorFileDialog::_item_selected(int p_item) {
+
+ int current = p_item;
+ if (current<0 || current>=item_list->get_item_count())
+ return;
+
+ Dictionary d=item_list->get_item_metadata(current);
+
+ if (!d["dir"]) {
+
+ file->set_text(d["name"]);
+ _request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
+ }
+}
+
+void EditorFileDialog::_push_history() {
+
+ local_history.resize(local_history_pos+1);
+ String new_path = dir_access->get_current_dir();
+ if (local_history.size()==0 || new_path!=local_history[local_history_pos]) {
+ local_history.push_back(new_path);
+ local_history_pos++;
+ dir_prev->set_disabled(local_history_pos==0);
+ dir_next->set_disabled(true);
+ }
+
+}
+void EditorFileDialog::_item_dc_selected(int p_item) {
+
+
+ int current = p_item;
+ if (current<0 || current>=item_list->get_item_count())
+ return;
+
+ Dictionary d=item_list->get_item_metadata(current);
+
+ if (d["dir"]) {
+
+ dir_access->change_dir(d["name"]);
+ call_deferred("_update_file_list");
+ call_deferred("_update_dir");
+
+ _push_history();
+
+
+ } else {
+
+ _action_pressed();
+ }
+}
+
+
+
+void EditorFileDialog::update_file_list() {
+
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ Ref<Texture> folder_thumbnail;
+ Ref<Texture> file_thumbnail;
+
+ item_list->clear();
+
+ if (display_mode==DISPLAY_THUMBNAILS) {
+
+ item_list->set_max_columns(0);
+ item_list->set_icon_mode(ItemList::ICON_MODE_TOP);
+ item_list->set_fixed_column_width(thumbnail_size*3/2);
+ item_list->set_max_text_lines(2);
+ item_list->set_fixed_icon_size(Size2(thumbnail_size,thumbnail_size));
+
+ if (!has_icon("ResizedFolder","EditorIcons")) {
+ Ref<ImageTexture> folder = get_icon("FolderBig","EditorIcons");
+ Image img = folder->get_data();
+ img.resize(thumbnail_size,thumbnail_size);
+ Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture));
+ resized_folder->create_from_image(img,0);
+ Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder);
+ }
+
+ folder_thumbnail = get_icon("ResizedFolder","EditorIcons");
+
+ if (!has_icon("ResizedFile","EditorIcons")) {
+ Ref<ImageTexture> file = get_icon("FileBig","EditorIcons");
+ Image img = file->get_data();
+ img.resize(thumbnail_size,thumbnail_size);
+ Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture));
+ resized_file->create_from_image(img,0);
+ Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file);
+ }
+
+ file_thumbnail = get_icon("ResizedFile","EditorIcons");
+
+ preview_vb->hide();
+
+ } else {
+
+ item_list->set_icon_mode(ItemList::ICON_MODE_LEFT);
+ item_list->set_max_columns(1);
+ item_list->set_max_text_lines(1);
+ item_list->set_fixed_column_width(0);
+ item_list->set_fixed_icon_size(Size2());
+ if (preview->get_texture().is_valid())
+ preview_vb->show();
+
+ }
+
+ String cdir = dir_access->get_current_dir();
+ bool skip_pp = access==ACCESS_RESOURCES && cdir=="res://";
+
+ dir_access->list_dir_begin();
+
+
+ Ref<Texture> folder = get_icon("folder","FileDialog");
+ List<String> files;
+ List<String> dirs;
+
+ bool isdir;
+ bool ishidden;
+ bool show_hidden = show_hidden_files;
+ String item;
+
+ while ((item=dir_access->get_next(&isdir))!="") {
+
+ ishidden = dir_access->current_is_hidden();
+
+ if (show_hidden || !ishidden) {
+ if (!isdir)
+ files.push_back(item);
+ else if (item!=".." || !skip_pp)
+ dirs.push_back(item);
+ }
+ }
+
+ if (dirs.find("..")==NULL) {
+ //may happen if lacking permissions
+ dirs.push_back("..");
+ }
+
+ dirs.sort_custom<NoCaseComparator>();
+ files.sort_custom<NoCaseComparator>();
+
+ while(!dirs.empty()) {
+ const String& dir_name=dirs.front()->get();
+
+ item_list->add_item(dir_name+"/");
+
+ if (display_mode==DISPLAY_THUMBNAILS) {
+
+ item_list->set_item_icon(item_list->get_item_count()-1,folder_thumbnail);
+ } else {
+
+ item_list->set_item_icon(item_list->get_item_count()-1,folder);
+ }
+
+ Dictionary d;
+ d["name"]=dir_name;
+ d["path"]=String();
+ d["dir"]=true;
+
+ item_list->set_item_metadata( item_list->get_item_count() -1, d);
+
+ dirs.pop_front();
+ }
+
+ dirs.clear();
+
+ List<String> patterns;
+ // build filter
+ if (filter->get_selected()==filter->get_item_count()-1) {
+
+ // match all
+ } else if (filters.size()>1 && filter->get_selected()==0) {
+ // match all filters
+ for (int i=0;i<filters.size();i++) {
+
+ String f=filters[i].get_slice(";",0);
+ for (int j=0;j<f.get_slice_count(",");j++) {
+
+ patterns.push_back(f.get_slice(",",j).strip_edges());
+ }
+ }
+ } else {
+ int idx=filter->get_selected();
+ if (filters.size()>1)
+ idx--;
+
+ if (idx>=0 && idx<filters.size()) {
+
+ String f=filters[idx].get_slice(";",0);
+ for (int j=0;j<f.get_slice_count(",");j++) {
+
+ patterns.push_back(f.get_slice(",",j).strip_edges());
+ }
+ }
+ }
+
+
+ String base_dir = dir_access->get_current_dir();
+
+
+ while(!files.empty()) {
+
+ bool match=patterns.empty();
+
+ for(List<String>::Element *E=patterns.front();E;E=E->next()) {
+
+ if (files.front()->get().matchn(E->get())) {
+
+ match=true;
+ break;
+ }
+ }
+
+ if (match) {
+ //TreeItem *ti=tree->create_item(root);
+ //ti->set_text(0,files.front()->get());
+ item_list->add_item(files.front()->get());
+
+ if (get_icon_func) {
+
+
+ Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
+ //ti->set_icon(0,icon);
+ if (display_mode==DISPLAY_THUMBNAILS) {
+
+ item_list->set_item_icon(item_list->get_item_count()-1,file_thumbnail);
+ item_list->set_item_tag_icon(item_list->get_item_count()-1,icon);
+ } else {
+ item_list->set_item_icon(item_list->get_item_count()-1,icon);
+ }
+ }
+
+ if (mode==MODE_OPEN_DIR) {
+ //disabled mode?
+ //ti->set_custom_color(0,get_color("files_disabled"));
+ //ti->set_selectable(0,false);
+ }
+ Dictionary d;
+ d["name"]=files.front()->get();
+ d["dir"]=false;
+ String fullpath = base_dir.plus_file(files.front()->get());
+
+ if (display_mode==DISPLAY_THUMBNAILS) {
+ EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath,this,"_thumbnail_result",fullpath);
+ }
+ d["path"]=base_dir.plus_file(files.front()->get());
+ //ti->set_metadata(0,d);
+ item_list->set_item_metadata(item_list->get_item_count()-1,d);
+
+ if (file->get_text()==files.front()->get())
+ item_list->set_current(item_list->get_item_count()-1);
+ }
+
+ files.pop_front();
+ }
+
+ if (favorites->get_current()>=0) {
+ favorites->unselect(favorites->get_current());
+ }
+
+ favorite->set_pressed(false);
+ fav_up->set_disabled(true);
+ fav_down->set_disabled(true);
+ for(int i=0;i<favorites->get_item_count();i++) {
+ if (favorites->get_item_metadata(i)==base_dir) {
+ favorites->select(i);
+ favorite->set_pressed(true);
+ if (i>0) {
+ fav_up->set_disabled(false);
+ }
+ if (i<favorites->get_item_count()-1) {
+ fav_down->set_disabled(false);
+ }
+ break;
+ }
+
+ }
+ // ??
+ /*
+ if (tree->get_root() && tree->get_root()->get_children())
+ tree->get_root()->get_children()->select(0);
+ */
+
+ files.clear();
+
+}
+
+void EditorFileDialog::_filter_selected(int) {
+
+ update_file_list();
+}
+
+void EditorFileDialog::update_filters() {
+
+ filter->clear();
+
+ if (filters.size()>1) {
+ String all_filters;
+
+ const int max_filters=5;
+
+ for(int i=0;i<MIN( max_filters, filters.size()) ;i++) {
+ String flt=filters[i].get_slice(";",0);
+ if (i>0)
+ all_filters+=",";
+ all_filters+=flt;
+ }
+
+ if (max_filters<filters.size())
+ all_filters+=", ...";
+
+ filter->add_item(TTR("All Recognized")+" ( "+all_filters+" )");
+ }
+ for(int i=0;i<filters.size();i++) {
+
+ String flt=filters[i].get_slice(";",0).strip_edges();
+ String desc=filters[i].get_slice(";",1).strip_edges();
+ if (desc.length())
+ filter->add_item(desc+" ( "+flt+" )");
+ else
+ filter->add_item("( "+flt+" )");
+ }
+
+ filter->add_item(TTR("All Files (*)"));
+
+}
+
+void EditorFileDialog::clear_filters() {
+
+ filters.clear();
+ update_filters();
+ invalidate();
+}
+void EditorFileDialog::add_filter(const String& p_filter) {
+
+ filters.push_back(p_filter);
+ update_filters();
+ invalidate();
+
+}
+
+String EditorFileDialog::get_current_dir() const {
+
+ return dir->get_text();
+}
+String EditorFileDialog::get_current_file() const {
+
+ return file->get_text();
+}
+String EditorFileDialog::get_current_path() const {
+
+ return dir->get_text().plus_file(file->get_text());
+}
+void EditorFileDialog::set_current_dir(const String& p_dir) {
+
+ dir_access->change_dir(p_dir);
+ update_dir();
+ invalidate();
+ //_push_history();
+
+
+}
+void EditorFileDialog::set_current_file(const String& p_file) {
+
+ file->set_text(p_file);
+ update_dir();
+ invalidate();
+ int lp = p_file.find_last(".");
+ if (lp!=-1) {
+ file->select(0,lp);
+ file->grab_focus();
+ }
+
+ if (is_visible_in_tree())
+ _request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
+
+
+}
+void EditorFileDialog::set_current_path(const String& p_path) {
+
+ if (!p_path.size())
+ return;
+ int pos=MAX( p_path.find_last("/"), p_path.find_last("\\") );
+ if (pos==-1) {
+
+ set_current_file(p_path);
+ } else {
+
+ String dir=p_path.substr(0,pos);
+ String file=p_path.substr(pos+1,p_path.length());
+ set_current_dir(dir);
+ set_current_file(file);
+ }
+}
+
+
+void EditorFileDialog::set_mode(Mode p_mode) {
+
+ mode=p_mode;
+ switch(mode) {
+
+ case MODE_OPEN_FILE: get_ok()->set_text(TTR("Open")); set_title("Open a File"); makedir->hide(); break;
+ case MODE_OPEN_FILES: get_ok()->set_text(TTR("Open")); set_title("Open File(s)"); makedir->hide(); break;
+ case MODE_OPEN_DIR: get_ok()->set_text(TTR("Open")); set_title("Open a Directory"); makedir->show(); break;
+ case MODE_OPEN_ANY: get_ok()->set_text(TTR("Open")); set_title("Open a File or Directory"); makedir->show(); break;
+ case MODE_SAVE_FILE: get_ok()->set_text(TTR("Save")); set_title("Save a File"); makedir->show(); break;
+ }
+
+ if (mode==MODE_OPEN_FILES) {
+ item_list->set_select_mode(ItemList::SELECT_MULTI);
+ } else {
+ item_list->set_select_mode(ItemList::SELECT_SINGLE);
+ }
+}
+
+EditorFileDialog::Mode EditorFileDialog::get_mode() const {
+
+ return mode;
+}
+
+void EditorFileDialog::set_access(Access p_access) {
+
+ ERR_FAIL_INDEX(p_access,3);
+ if (access==p_access)
+ return;
+ memdelete( dir_access );
+ switch(p_access) {
+ case ACCESS_FILESYSTEM: {
+
+ dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ } break;
+ case ACCESS_RESOURCES: {
+
+ dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ } break;
+ case ACCESS_USERDATA: {
+
+ dir_access = DirAccess::create(DirAccess::ACCESS_USERDATA);
+ } break;
+ }
+ access=p_access;
+ _update_drives();
+ invalidate();
+ update_filters();
+ update_dir();
+}
+
+void EditorFileDialog::invalidate() {
+
+ if (is_visible_in_tree()) {
+ update_file_list();
+ invalidated=false;
+ } else {
+ invalidated=true;
+ }
+
+}
+
+EditorFileDialog::Access EditorFileDialog::get_access() const{
+
+ return access;
+}
+
+void EditorFileDialog::_make_dir_confirm() {
+
+ Error err = dir_access->make_dir( makedirname->get_text() );
+ if (err==OK) {
+ dir_access->change_dir(makedirname->get_text());
+ invalidate();
+ update_filters();
+ update_dir();
+ _push_history();
+
+ } else {
+ mkdirerr->popup_centered_minsize(Size2(250,50)*EDSCALE);
+ }
+ makedirname->set_text(""); // reset label
+}
+
+
+void EditorFileDialog::_make_dir() {
+
+ makedialog->popup_centered_minsize(Size2(250,80)*EDSCALE);
+ makedirname->grab_focus();
+
+}
+
+void EditorFileDialog::_select_drive(int p_idx) {
+
+ String d = drives->get_item_text(p_idx);
+ dir_access->change_dir(d);
+ file->set_text("");
+ invalidate();
+ update_dir();
+ _push_history();
+
+
+}
+
+void EditorFileDialog::_update_drives() {
+
+
+ int dc = dir_access->get_drive_count();
+ if (dc==0 || access!=ACCESS_FILESYSTEM) {
+ drives->hide();
+ } else {
+ drives->clear();
+ drives->show();
+
+ for(int i=0;i<dir_access->get_drive_count();i++) {
+ String d = dir_access->get_drive(i);
+ drives->add_item(dir_access->get_drive(i));
+ }
+
+ drives->select(dir_access->get_current_drive());
+
+ }
+}
+
+
+void EditorFileDialog::_favorite_selected(int p_idx) {
+
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+ ERR_FAIL_INDEX(p_idx,favorited.size());
+
+ dir_access->change_dir(favorited[p_idx]);
+ file->set_text("");
+ invalidate();
+ update_dir();
+ _push_history();
+}
+
+void EditorFileDialog::_favorite_move_up(){
+
+ int current = favorites->get_current();
+
+ if (current>0 && current<favorites->get_item_count()) {
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+
+ int a_idx=favorited.find(String(favorites->get_item_metadata(current-1)));
+ int b_idx=favorited.find(String(favorites->get_item_metadata(current)));
+
+ if (a_idx==-1 || b_idx==-1)
+ return;
+ SWAP(favorited[a_idx],favorited[b_idx]);
+
+ EditorSettings::get_singleton()->set_favorite_dirs(favorited);
+
+ _update_favorites();
+ update_file_list();
+
+ }
+}
+void EditorFileDialog::_favorite_move_down(){
+
+ int current = favorites->get_current();
+
+ if (current>=0 && current<favorites->get_item_count()-1) {
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+
+ int a_idx=favorited.find(String(favorites->get_item_metadata(current+1)));
+ int b_idx=favorited.find(String(favorites->get_item_metadata(current)));
+
+ if (a_idx==-1 || b_idx==-1)
+ return;
+ SWAP(favorited[a_idx],favorited[b_idx]);
+
+ EditorSettings::get_singleton()->set_favorite_dirs(favorited);
+
+ _update_favorites();
+ update_file_list();
+
+ }
+}
+
+
+void EditorFileDialog::_update_favorites() {
+
+ bool res = access==ACCESS_RESOURCES;
+
+ String current = get_current_dir();
+ Ref<Texture> star = get_icon("Favorites","EditorIcons");
+ favorites->clear();
+
+ favorite->set_pressed(false);
+
+
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+ for(int i=0;i<favorited.size();i++) {
+ bool cres = favorited[i].begins_with("res://");
+ if (cres!=res)
+ continue;
+ String name = favorited[i];
+
+ bool setthis = name==current;
+
+ if (res && name=="res://") {
+ name="/";
+ } else {
+ name=name.get_file()+"/";
+ }
+
+
+ //print_line("file: "+name);
+ favorites->add_item(name,star);
+ favorites->set_item_metadata( favorites->get_item_count()-1,favorited[i]);
+
+ if (setthis) {
+ favorite->set_pressed(true);
+ favorites->set_current(favorites->get_item_count()-1);
+ }
+ }
+
+
+}
+
+void EditorFileDialog::_favorite_toggled(bool p_toggle) {
+ bool res = access==ACCESS_RESOURCES;
+
+ String cd = get_current_dir();
+
+ Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
+
+ bool found = false;
+ for(int i=0;i<favorited.size();i++) {
+ bool cres = favorited[i].begins_with("res://");
+ if (cres!=res)
+ continue;
+
+ if (favorited[i]==cd) {
+ found=true;
+ break;
+ }
+ }
+
+ if (found) {
+ favorited.erase(cd);
+ favorite->set_pressed(false);
+ } else {
+ favorited.push_back(cd);
+ favorite->set_pressed(true);
+ }
+
+ EditorSettings::get_singleton()->set_favorite_dirs(favorited);
+
+ _update_favorites();
+
+}
+
+void EditorFileDialog::_recent_selected(int p_idx) {
+
+ Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
+ ERR_FAIL_INDEX(p_idx,recentd.size());
+
+ dir_access->change_dir(recent->get_item_metadata(p_idx));
+ update_file_list();
+ update_dir();
+ _push_history();
+}
+
+void EditorFileDialog::_go_up() {
+
+ dir_access->change_dir("..");
+ update_file_list();
+ update_dir();
+ _push_history();
+
+}
+
+void EditorFileDialog::_go_back(){
+
+ if (local_history_pos<=0) {
+ return;
+ }
+
+ local_history_pos--;
+ dir_access->change_dir(local_history[local_history_pos]);
+ update_file_list();
+ update_dir();
+
+ dir_prev->set_disabled(local_history_pos==0);
+ dir_next->set_disabled(local_history_pos==local_history.size()-1);
+}
+void EditorFileDialog::_go_forward(){
+
+ if (local_history_pos==local_history.size()-1) {
+ return;
+ }
+
+ local_history_pos++;
+ dir_access->change_dir(local_history[local_history_pos]);
+ update_file_list();
+ update_dir();
+
+ dir_prev->set_disabled(local_history_pos==0);
+ dir_next->set_disabled(local_history_pos==local_history.size()-1);
+
+}
+
+bool EditorFileDialog::default_show_hidden_files=false;
+
+EditorFileDialog::DisplayMode EditorFileDialog::default_display_mode=DISPLAY_THUMBNAILS;
+
+void EditorFileDialog::set_display_mode(DisplayMode p_mode) {
+
+ if (display_mode==p_mode)
+ return;
+ if (p_mode==DISPLAY_THUMBNAILS) {
+ mode_list->set_pressed(false);
+ mode_thumbnails->set_pressed(true);
+ } else {
+ mode_thumbnails->set_pressed(false);
+ mode_list->set_pressed(true);
+ }
+ display_mode=p_mode;
+ invalidate();
+}
+
+EditorFileDialog::DisplayMode EditorFileDialog::get_display_mode() const{
+
+ return display_mode;
+}
+
+
+
+void EditorFileDialog::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_unhandled_input"),&EditorFileDialog::_unhandled_input);
+
+ ClassDB::bind_method(D_METHOD("_item_selected"),&EditorFileDialog::_item_selected);
+ ClassDB::bind_method(D_METHOD("_item_db_selected"),&EditorFileDialog::_item_dc_selected);
+ ClassDB::bind_method(D_METHOD("_dir_entered"),&EditorFileDialog::_dir_entered);
+ ClassDB::bind_method(D_METHOD("_file_entered"),&EditorFileDialog::_file_entered);
+ ClassDB::bind_method(D_METHOD("_action_pressed"),&EditorFileDialog::_action_pressed);
+ ClassDB::bind_method(D_METHOD("_cancel_pressed"),&EditorFileDialog::_cancel_pressed);
+ ClassDB::bind_method(D_METHOD("_filter_selected"),&EditorFileDialog::_filter_selected);
+ ClassDB::bind_method(D_METHOD("_save_confirm_pressed"),&EditorFileDialog::_save_confirm_pressed);
+
+ ClassDB::bind_method(D_METHOD("clear_filters"),&EditorFileDialog::clear_filters);
+ ClassDB::bind_method(D_METHOD("add_filter","filter"),&EditorFileDialog::add_filter);
+ ClassDB::bind_method(D_METHOD("get_current_dir"),&EditorFileDialog::get_current_dir);
+ ClassDB::bind_method(D_METHOD("get_current_file"),&EditorFileDialog::get_current_file);
+ ClassDB::bind_method(D_METHOD("get_current_path"),&EditorFileDialog::get_current_path);
+ ClassDB::bind_method(D_METHOD("set_current_dir","dir"),&EditorFileDialog::set_current_dir);
+ ClassDB::bind_method(D_METHOD("set_current_file","file"),&EditorFileDialog::set_current_file);
+ ClassDB::bind_method(D_METHOD("set_current_path","path"),&EditorFileDialog::set_current_path);
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&EditorFileDialog::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&EditorFileDialog::get_mode);
+ ClassDB::bind_method(D_METHOD("get_vbox:VBoxContainer"),&EditorFileDialog::get_vbox);
+ ClassDB::bind_method(D_METHOD("set_access","access"),&EditorFileDialog::set_access);
+ ClassDB::bind_method(D_METHOD("get_access"),&EditorFileDialog::get_access);
+ ClassDB::bind_method(D_METHOD("set_show_hidden_files","show"),&EditorFileDialog::set_show_hidden_files);
+ ClassDB::bind_method(D_METHOD("is_showing_hidden_files"),&EditorFileDialog::is_showing_hidden_files);
+ ClassDB::bind_method(D_METHOD("_select_drive"),&EditorFileDialog::_select_drive);
+ ClassDB::bind_method(D_METHOD("_make_dir"),&EditorFileDialog::_make_dir);
+ ClassDB::bind_method(D_METHOD("_make_dir_confirm"),&EditorFileDialog::_make_dir_confirm);
+ ClassDB::bind_method(D_METHOD("_update_file_list"),&EditorFileDialog::update_file_list);
+ ClassDB::bind_method(D_METHOD("_update_dir"),&EditorFileDialog::update_dir);
+ ClassDB::bind_method(D_METHOD("_thumbnail_done"),&EditorFileDialog::_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("set_display_mode","mode"),&EditorFileDialog::set_display_mode);
+ ClassDB::bind_method(D_METHOD("get_display_mode"),&EditorFileDialog::get_display_mode);
+ ClassDB::bind_method(D_METHOD("_thumbnail_result"),&EditorFileDialog::_thumbnail_result);
+ ClassDB::bind_method(D_METHOD("set_disable_overwrite_warning","disable"),&EditorFileDialog::set_disable_overwrite_warning);
+ ClassDB::bind_method(D_METHOD("is_overwrite_warning_disabled"),&EditorFileDialog::is_overwrite_warning_disabled);
+
+ ClassDB::bind_method(D_METHOD("_recent_selected"),&EditorFileDialog::_recent_selected);
+ ClassDB::bind_method(D_METHOD("_go_back"),&EditorFileDialog::_go_back);
+ ClassDB::bind_method(D_METHOD("_go_forward"),&EditorFileDialog::_go_forward);
+ ClassDB::bind_method(D_METHOD("_go_up"),&EditorFileDialog::_go_up);
+
+ ClassDB::bind_method(D_METHOD("_favorite_toggled"),&EditorFileDialog::_favorite_toggled);
+ ClassDB::bind_method(D_METHOD("_favorite_selected"),&EditorFileDialog::_favorite_selected);
+ ClassDB::bind_method(D_METHOD("_favorite_move_up"),&EditorFileDialog::_favorite_move_up);
+ ClassDB::bind_method(D_METHOD("_favorite_move_down"),&EditorFileDialog::_favorite_move_down);
+
+ ClassDB::bind_method(D_METHOD("invalidate"),&EditorFileDialog::invalidate);
+
+ ADD_SIGNAL(MethodInfo("file_selected",PropertyInfo( Variant::STRING,"path")));
+ ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::POOL_STRING_ARRAY,"paths")));
+ ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo( Variant::STRING,"dir")));
+
+ BIND_CONSTANT( MODE_OPEN_FILE );
+ BIND_CONSTANT( MODE_OPEN_FILES );
+ BIND_CONSTANT( MODE_OPEN_DIR );
+ BIND_CONSTANT( MODE_OPEN_ANY );
+ BIND_CONSTANT( MODE_SAVE_FILE );
+
+ BIND_CONSTANT( ACCESS_RESOURCES );
+ BIND_CONSTANT( ACCESS_USERDATA );
+ BIND_CONSTANT( ACCESS_FILESYSTEM );
+
+}
+
+
+void EditorFileDialog::set_show_hidden_files(bool p_show) {
+ show_hidden_files=p_show;
+ invalidate();
+}
+
+bool EditorFileDialog::is_showing_hidden_files() const {
+ return show_hidden_files;
+}
+
+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();
+ Vector<String> recent = EditorSettings::get_singleton()->get_recent_dirs();
+
+ const int max=20;
+ int count=0;
+ bool res=dir.begins_with("res://");
+
+ for(int i=0;i<recent.size();i++) {
+ bool cres=recent[i].begins_with("res://");
+ if (recent[i]==dir || (res==cres && count>max)) {
+ recent.remove(i);
+ i--;
+ } else {
+ count++;
+ }
+ }
+
+ recent.insert(0,dir);
+
+ EditorSettings::get_singleton()->set_recent_dirs(recent);
+
+
+}
+
+void EditorFileDialog::set_disable_overwrite_warning(bool p_disable) {
+
+ disable_overwrite_warning=p_disable;
+}
+
+bool EditorFileDialog::is_overwrite_warning_disabled() const{
+
+ return disable_overwrite_warning;
+}
+
+
+EditorFileDialog::EditorFileDialog() {
+
+ show_hidden_files=default_show_hidden_files;
+ display_mode=default_display_mode;
+ local_history_pos=0;
+ disable_overwrite_warning=false;
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+
+ mode=MODE_SAVE_FILE;
+ set_title(TTR("Save a File"));
+
+ ED_SHORTCUT("file_dialog/go_back", TTR("Go Back"), KEY_MASK_ALT|KEY_LEFT);
+ ED_SHORTCUT("file_dialog/go_forward", TTR("Go Forward"), KEY_MASK_ALT|KEY_RIGHT);
+ ED_SHORTCUT("file_dialog/go_up", TTR("Go Up"), KEY_MASK_ALT|KEY_UP);
+ ED_SHORTCUT("file_dialog/refresh", TTR("Refresh"), KEY_F5);
+ ED_SHORTCUT("file_dialog/toggle_hidden_files", TTR("Toggle Hidden Files"), KEY_MASK_CMD|KEY_H);
+ ED_SHORTCUT("file_dialog/toggle_favorite", TTR("Toggle Favorite"), KEY_MASK_ALT|KEY_F);
+ ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KEY_MASK_ALT|KEY_V);
+ ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KEY_MASK_CMD|KEY_N);
+ ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KEY_MASK_CMD|KEY_D);
+ ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KEY_MASK_CMD|KEY_UP);
+ ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KEY_MASK_CMD|KEY_DOWN);
+
+ HBoxContainer *pathhb = memnew( HBoxContainer );
+
+ dir_prev = memnew( ToolButton );
+ dir_next = memnew( ToolButton );
+ dir_up = memnew( ToolButton );
+
+ pathhb->add_child(dir_prev);
+ pathhb->add_child(dir_next);
+ pathhb->add_child(dir_up);
+
+ dir_prev->connect("pressed",this,"_go_back");
+ dir_next->connect("pressed",this,"_go_forward");
+ dir_up->connect("pressed",this,"_go_up");
+
+ dir = memnew(LineEdit);
+ 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");
+ pathhb->add_child(favorite);
+
+ 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(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 );
+ pathhb->add_child(drives);
+ drives->connect("item_selected",this,"_select_drive");
+
+ makedir = memnew( Button );
+ makedir->set_text(TTR("Create Folder"));
+ makedir->connect("pressed",this,"_make_dir");
+ pathhb->add_child(makedir);
+
+ list_hb = memnew( HBoxContainer );
+
+ vbc->add_margin_child(TTR("Path:"),pathhb);
+ vbc->add_child(list_hb);
+ list_hb->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ VBoxContainer *fav_vb = memnew( VBoxContainer );
+ list_hb->add_child(fav_vb);
+ HBoxContainer *fav_hb = memnew( HBoxContainer );
+ fav_vb->add_child(fav_hb);
+ fav_hb->add_child(memnew(Label(TTR("Favorites:"))));
+ fav_hb->add_spacer();
+ fav_up = memnew( ToolButton );
+ fav_hb->add_child(fav_up);
+ fav_up->connect("pressed",this,"_favorite_move_up");
+ fav_down = memnew( ToolButton );
+ fav_hb->add_child(fav_down);
+ fav_down->connect("pressed",this,"_favorite_move_down");
+ fav_rm = memnew( ToolButton );
+ fav_hb->add_child(fav_rm);
+ fav_rm->hide(); // redundant
+
+ MarginContainer *fav_mv = memnew( MarginContainer );
+ fav_vb->add_child(fav_mv);
+ fav_mv->set_v_size_flags(SIZE_EXPAND_FILL);
+ favorites = memnew( ItemList );
+ fav_mv->add_child(favorites);
+ favorites->connect("item_selected",this,"_favorite_selected");
+
+ recent = memnew( ItemList );
+ fav_vb->add_margin_child(TTR("Recent:"),recent,true);
+ recent->connect("item_selected",this,"_recent_selected");
+
+ VBoxContainer *item_vb = memnew( VBoxContainer );
+ list_hb->add_child(item_vb);
+ item_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ item_list = memnew( ItemList );
+ item_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ item_vb->add_margin_child(TTR("Directories & Files:"),item_list,true);
+
+ HBoxContainer* filter_hb = memnew( HBoxContainer );
+ item_vb->add_child(filter_hb);
+
+ VBoxContainer *filter_vb = memnew( VBoxContainer );
+ filter_hb->add_child(filter_vb);
+ filter_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ preview_vb = memnew( VBoxContainer );
+ filter_hb->add_child(preview_vb);
+ CenterContainer *prev_cc = memnew( CenterContainer );
+ preview_vb->add_margin_child(TTR("Preview:"),prev_cc);
+ preview = memnew( TextureRect );
+ prev_cc->add_child(preview);
+ preview_vb->hide();
+
+
+ file = memnew(LineEdit);
+ //add_child(file);
+ filter_vb->add_margin_child(TTR("File:"),file);
+
+
+ filter = memnew( OptionButton );
+ //add_child(filter);
+ filter_vb->add_margin_child(TTR("Filter:"),filter);
+ filter->set_clip_text(true);//too many extensions overflow it
+
+ dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ access=ACCESS_RESOURCES;
+ _update_drives();
+
+
+ connect("confirmed", this,"_action_pressed");
+ //cancel->connect("pressed", this,"_cancel_pressed");
+ item_list->connect("item_selected", this,"_item_selected",varray(),CONNECT_DEFERRED);
+ item_list->connect("item_activated", this,"_item_db_selected",varray());
+ dir->connect("text_entered", this,"_dir_entered");
+ file->connect("text_entered", this,"_file_entered");
+ filter->connect("item_selected", this,"_filter_selected");
+
+
+ confirm_save = memnew( ConfirmationDialog );
+ confirm_save->set_as_toplevel(true);
+ add_child(confirm_save);
+
+
+ confirm_save->connect("confirmed", this,"_save_confirm_pressed");
+
+ makedialog = memnew( ConfirmationDialog );
+ makedialog->set_title(TTR("Create Folder"));
+ VBoxContainer *makevb= memnew( VBoxContainer );
+ makedialog->add_child(makevb);
+
+ makedirname = memnew( LineEdit );
+ makevb->add_margin_child(TTR("Name:"),makedirname);
+ add_child(makedialog);
+ makedialog->register_text_enter(makedirname);
+ makedialog->connect("confirmed",this,"_make_dir_confirm");
+ mkdirerr = memnew( AcceptDialog );
+ mkdirerr->set_text(TTR("Could not create folder."));
+ add_child(mkdirerr);
+
+ exterr = memnew( AcceptDialog );
+ exterr->set_text(TTR("Must use a valid extension."));
+ add_child(exterr);
+
+
+ //update_file_list();
+ update_filters();
+ update_dir();
+
+ set_hide_on_ok(false);
+ vbox=vbc;
+
+
+ invalidated=true;
+ if (register_func)
+ register_func(this);
+
+ preview_wheel_timeout=0;
+ preview_wheel_index=0;
+ preview_waiting=false;
+
+}
+
+
+EditorFileDialog::~EditorFileDialog() {
+
+ if (unregister_func)
+ unregister_func(this);
+ memdelete(dir_access);
+}
+
+
+void EditorLineEditFileChooser::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_browse"),&EditorLineEditFileChooser::_browse);
+ ClassDB::bind_method(D_METHOD("_chosen"),&EditorLineEditFileChooser::_chosen);
+ ClassDB::bind_method(D_METHOD("get_button:Button"),&EditorLineEditFileChooser::get_button);
+ ClassDB::bind_method(D_METHOD("get_line_edit:LineEdit"),&EditorLineEditFileChooser::get_line_edit);
+ ClassDB::bind_method(D_METHOD("get_file_dialog:EditorFileDialog"),&EditorLineEditFileChooser::get_file_dialog);
+
+}
+
+void EditorLineEditFileChooser::_chosen(const String& p_text){
+
+ line_edit->set_text(p_text);
+ line_edit->emit_signal("text_entered",p_text);
+}
+
+void EditorLineEditFileChooser::_browse() {
+
+ dialog->popup_centered_ratio();
+}
+
+EditorLineEditFileChooser::EditorLineEditFileChooser() {
+
+ line_edit = memnew( LineEdit );
+ add_child(line_edit);
+ line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ button = memnew( Button );
+ button->set_text(" .. ");
+ add_child(button);
+ button->connect("pressed",this,"_browse");
+ dialog = memnew( EditorFileDialog);
+ add_child(dialog);
+ dialog->connect("file_selected",this,"_chosen");
+ dialog->connect("dir_selected",this,"_chosen");
+ dialog->connect("files_selected",this,"_chosen");
+
+
+}
diff --git a/tools/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 193cbc513c..193cbc513c 100644
--- a/tools/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
new file mode 100644
index 0000000000..cd151cd90b
--- /dev/null
+++ b/editor/editor_file_system.cpp
@@ -0,0 +1,1550 @@
+/*************************************************************************/
+/* editor_file_system.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_file_system.h"
+
+#include "global_config.h"
+#include "io/resource_loader.h"
+#include "os/os.h"
+#include "os/file_access.h"
+#include "editor_node.h"
+#include "io/resource_saver.h"
+#include "io/resource_import.h"
+#include "editor_settings.h"
+#include "editor_resource_preview.h"
+#include "variant_parser.h"
+
+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 {
+
+ return subdirs.size();
+}
+
+EditorFileSystemDirectory *EditorFileSystemDirectory::get_subdir(int p_idx){
+
+ ERR_FAIL_INDEX_V(p_idx,subdirs.size(),NULL);
+ return subdirs[p_idx];
+
+}
+
+int EditorFileSystemDirectory::get_file_count() const{
+
+ return files.size();
+}
+
+String EditorFileSystemDirectory::get_file(int p_idx) const{
+
+ ERR_FAIL_INDEX_V(p_idx,files.size(),"");
+
+ return files[p_idx]->file;
+}
+
+String EditorFileSystemDirectory::get_path() const {
+
+ String p;
+ const EditorFileSystemDirectory *d=this;
+ while(d->parent) {
+ p=d->name+"/"+p;
+ d=d->parent;
+ }
+
+ return "res://"+p;
+
+}
+
+
+String EditorFileSystemDirectory::get_file_path(int p_idx) const {
+
+ String file = get_file(p_idx);
+ const EditorFileSystemDirectory *d=this;
+ while(d->parent) {
+ file=d->name+"/"+file;
+ d=d->parent;
+ }
+
+ return "res://"+file;
+}
+
+
+Vector<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
+ return files[p_idx]->deps;
+
+}
+
+
+StringName EditorFileSystemDirectory::get_file_type(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,files.size(),"");
+ return files[p_idx]->type;
+}
+
+String EditorFileSystemDirectory::get_name() {
+
+ return name;
+}
+
+EditorFileSystemDirectory *EditorFileSystemDirectory::get_parent() {
+
+ return parent;
+}
+
+void EditorFileSystemDirectory::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("get_subdir_count"),&EditorFileSystemDirectory::get_subdir_count);
+ ClassDB::bind_method(D_METHOD("get_subdir","idx"),&EditorFileSystemDirectory::get_subdir);
+ ClassDB::bind_method(D_METHOD("get_file_count"),&EditorFileSystemDirectory::get_file_count);
+ ClassDB::bind_method(D_METHOD("get_file","idx"),&EditorFileSystemDirectory::get_file);
+ ClassDB::bind_method(D_METHOD("get_file_path","idx"),&EditorFileSystemDirectory::get_file_path);
+ ClassDB::bind_method(D_METHOD("get_file_type","idx"),&EditorFileSystemDirectory::get_file_type);
+ ClassDB::bind_method(D_METHOD("get_name"),&EditorFileSystemDirectory::get_name);
+ ClassDB::bind_method(D_METHOD("get_path"),&EditorFileSystemDirectory::get_path);
+ ClassDB::bind_method(D_METHOD("get_parent:EditorFileSystemDirectory"),&EditorFileSystemDirectory::get_parent);
+ ClassDB::bind_method(D_METHOD("find_file_index","name"),&EditorFileSystemDirectory::find_file_index);
+ ClassDB::bind_method(D_METHOD("find_dir_index","name"),&EditorFileSystemDirectory::find_dir_index);
+
+
+}
+
+
+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]);
+ }
+}
+
+
+
+
+
+void EditorFileSystem::_scan_filesystem() {
+
+ ERR_FAIL_COND(!scanning || new_filesystem);
+
+ //read .fscache
+ String cpath;
+
+ sources_changed.clear();
+ file_cache.clear();
+
+ String project=GlobalConfig::get_singleton()->get_resource_path();
+
+ String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2");
+ FileAccess *f =FileAccess::open(fscache,FileAccess::READ);
+
+ if (f) {
+ //read the disk cache
+ while(!f->eof_reached()) {
+
+ String l = f->get_line().strip_edges();
+ if (l==String())
+ continue;
+
+ if (l.begins_with("::")) {
+ Vector<String> split = l.split("::");
+ ERR_CONTINUE( split.size() != 3);
+ String name = split[1];
+
+ cpath=name;
+
+ } else {
+ Vector<String> split = l.split("::");
+ ERR_CONTINUE( split.size() != 5);
+ String name = split[0];
+ String file;
+
+ file=name;
+ name=cpath.plus_file(name);
+
+ FileCache fc;
+ fc.type=split[1];
+ fc.modification_time=split[2].to_int64();
+ fc.import_modification_time = split[3].to_int64();
+
+ String deps = split[4].strip_edges();
+ if (deps.length()) {
+ Vector<String> dp = deps.split("<>");
+ for(int i=0;i<dp.size();i++) {
+ String path=dp[i];
+ fc.deps.push_back(path);
+ }
+ }
+
+ file_cache[name]=fc;
+
+ }
+
+ }
+
+ f->close();
+ memdelete(f);
+ }
+
+
+
+ EditorProgressBG scan_progress("efs","ScanFS",1000);
+
+ ScanProgress sp;
+ sp.low=0;
+ sp.hi=1;
+ sp.progress=&scan_progress;
+
+
+ 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);
+
+ file_cache.clear(); //clear caches, no longer needed
+
+ 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_filesystem_cache(new_filesystem,f);
+ f->close();
+ memdelete(f);
+
+ scanning=false;
+
+}
+
+void EditorFileSystem::_save_filesystem_cache() {
+ String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2");
+
+ FileAccess *f=FileAccess::open(fscache,FileAccess::WRITE);
+ _save_filesystem_cache(filesystem,f);
+ f->close();
+ memdelete(f);
+}
+
+void EditorFileSystem::_thread_func(void *_userdata) {
+
+ EditorFileSystem *sd = (EditorFileSystem*)_userdata;
+ sd->_scan_filesystem();
+
+}
+
+bool EditorFileSystem::_update_scan_actions() {
+
+ sources_changed.clear();
+
+ bool fs_changed=false;
+
+ Vector<String> reimports;
+
+ 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_REIMPORT: {
+
+
+ int idx = ia.dir->find_file_index(ia.file);
+ ERR_CONTINUE(idx==-1);
+ String full_path = ia.dir->get_file_path(idx);
+ reimports.push_back(full_path);
+
+ fs_changed=true;
+ } break;
+
+ }
+ }
+
+
+ if (reimports.size()) {
+ reimport_files(reimports);
+
+ }
+ scan_actions.clear();
+
+ return fs_changed;
+
+}
+
+void EditorFileSystem::scan() {
+
+ if (false /*&& bool(Globals::get_singleton()->get("debug/disable_scan"))*/)
+ return;
+
+ if (scanning || scanning_changes|| thread)
+ return;
+
+ _update_extensions();
+
+ abort_scan=false;
+ if (!use_threads) {
+ scanning=true;
+ scan_total=0;
+ _scan_filesystem();
+ if (filesystem)
+ memdelete(filesystem);
+ //file_type_cache.clear();
+ filesystem=new_filesystem;
+ new_filesystem=NULL;
+ _update_scan_actions();
+ scanning=false;
+ emit_signal("filesystem_changed");
+ emit_signal("sources_changed",sources_changed.size()>0);
+
+ } else {
+
+ ERR_FAIL_COND(thread);
+ 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();
+ //progress->show();
+
+ }
+
+
+
+}
+
+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;
+
+}
+
+bool EditorFileSystem::_check_missing_imported_files(const String& p_path) {
+
+ if (!reimport_on_missing_imported_files)
+ return true;
+
+ Error err;
+ FileAccess *f= FileAccess::open(p_path+".import",FileAccess::READ,&err);
+
+ if (!f) {
+ print_line("could not open import for "+p_path);
+ return false;
+ }
+
+ VariantParser::StreamFile stream;
+ stream.f=f;
+
+ String assign;
+ Variant value;
+ VariantParser::Tag next_tag;
+
+ int lines=0;
+ String error_text;
+
+ List<String> to_check;
+
+ 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("ResourceFormatImporter::load - "+p_path+".import:"+itos(lines)+" error: "+error_text);
+ memdelete(f);
+ return false;
+ }
+
+ if (assign!=String()) {
+ if (assign.begins_with("path")) {
+ to_check.push_back(value);
+ } else if (assign=="files") {
+ Array fa = value;
+ for(int i=0;i<fa.size();i++) {
+ to_check.push_back(fa[i]);
+ }
+ }
+
+ } else if (next_tag.name!="remap" && next_tag.name!="deps") {
+ break;
+ }
+ }
+
+ memdelete(f);
+
+ for (List<String>::Element *E=to_check.front();E;E=E->next()) {
+ if (!FileAccess::exists(E->get())) {
+ print_line("missing "+E->get()+", reimport" );
+ return false;
+ }
+ }
+ return true;
+}
+
+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("godot.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) {
+
+ String d = da->get_current_dir();
+
+ if (d==cd || !d.begins_with(cd)) {
+ da->change_dir(cd); //avoid recursion
+ } else {
+
+
+ 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("Cannot 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().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 (import_extensions.has(ext)) {
+
+ //is imported
+ uint64_t import_mt=0;
+ if (FileAccess::exists(path+".import")) {
+ import_mt=FileAccess::get_modified_time(path+".import");
+ }
+
+
+ if (fc && fc->modification_time==mt && fc->import_modification_time==import_mt && _check_missing_imported_files(path)) {
+
+ fi->type=fc->type;
+ fi->modified_time=fc->modification_time;
+ fi->import_modified_time=fc->import_modification_time;
+
+ } else {
+
+ if (!fc) {
+ print_line("REIMPORT BECAUSE: not previously found");
+ } else if (fc->modification_time!=mt) {
+ print_line("REIMPORT BECAUSE: modified resource time "+itos(fc->modification_time)+" vs "+itos(mt));
+
+ } else if (fc->import_modification_time!=import_mt) {
+ print_line("REIMPORT BECAUSE: modified .import time"+itos(fc->import_modification_time)+" vs "+itos(import_mt));
+
+ } else {
+
+ print_line("REIMPORT BECAUSE: missing imported files");
+ }
+
+
+ fi->type=ResourceFormatImporter::get_singleton()->get_resource_type(path);
+ fi->modified_time=0;
+ fi->import_modified_time=0;
+
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_REIMPORT;
+ ia.dir=p_dir;
+ ia.file=E->get();
+ scan_actions.push_back(ia);
+ }
+ } else {
+ //not imported, so just update type if changed
+ if (fc && fc->modification_time == mt) {
+
+ fi->type=fc->type;
+ fi->modified_time=fc->modification_time;
+ fi->import_modified_time=0;
+ } else {
+ fi->type=ResourceLoader::get_resource_type(path);
+ fi->modified_time=mt;
+ fi->import_modified_time=0;
+ }
+ }
+
+ 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;
+ String cd = p_dir->get_path();
+
+ //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);
+
+ 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("godot.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.get_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->import_modified_time=0;
+ 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);
+
+
+ }
+
+ if (import_extensions.has(ext)) {
+ //if it can be imported, and it was added, it needs to be reimported
+ print_line("REIMPORT: file was not found before, reimport");
+ print_line("at dir: "+p_dir->get_path()+" file: "+f);
+ for(int i=0;i<p_dir->files.size();i++) {
+ print_line(itos(i)+": "+p_dir->files[i]->file);
+ }
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_REIMPORT;
+ 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 (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 (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) {
+ //check here if file must be imported or not
+
+ String path = cd.plus_file(p_dir->files[i]->file);
+
+ uint64_t mt = FileAccess::get_modified_time(path);
+
+ bool reimport=false;
+
+ if (mt!=p_dir->files[i]->modified_time) {
+ print_line("REIMPORT: modified time changed, reimport");
+ reimport=true; //it was modified, must be reimported.
+ } else if (!FileAccess::exists(path+".import")) {
+ print_line("REIMPORT: no .import exists, reimport");
+ reimport=true; //no .import file, obviously reimport
+ } else {
+
+ uint64_t import_mt=FileAccess::get_modified_time(path+".import");
+ print_line(itos(import_mt)+" vs "+itos(p_dir->files[i]->import_modified_time));
+ if (import_mt!=p_dir->files[i]->import_modified_time) {
+ print_line("REIMPORT: import modified changed, reimport");
+ reimport=true;
+ } else if (!_check_missing_imported_files(path)) {
+ print_line("REIMPORT: imported files removed");
+ reimport=true;
+ }
+ }
+
+ if (reimport) {
+
+ ItemAction ia;
+ ia.action=ItemAction::ACTION_FILE_REIMPORT;
+ ia.dir=p_dir;
+ ia.file=p_dir->files[i]->file;
+ scan_actions.push_back(ia);
+ }
+
+ }
+
+ EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i));
+ }
+
+ for(int i=0;i<p_dir->subdirs.size();i++) {
+
+ 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);
+ }
+
+}
+
+void EditorFileSystem::_thread_func_sources(void *_userdata) {
+
+ EditorFileSystem *efs = (EditorFileSystem*)_userdata;
+ if (efs->filesystem) {
+ EditorProgressBG pr("sources",TTR("ScanSources"),1000);
+ ScanProgress sp;
+ sp.progress=&pr;
+ sp.hi=1;
+ sp.low=0;
+ efs->_scan_fs_changes(efs->filesystem,sp);
+ }
+ efs->scanning_changes_done=true;
+}
+
+void EditorFileSystem::get_changed_sources(List<String> *r_changed) {
+
+ *r_changed=sources_changed;
+}
+
+void EditorFileSystem::scan_changes() {
+
+ if (scanning || scanning_changes|| thread)
+ return;
+
+ _update_extensions();
+ sources_changed.clear();
+ scanning_changes=true;
+ scanning_changes_done=false;
+
+ abort_scan=false;
+
+ if (!use_threads) {
+ if (filesystem) {
+ EditorProgressBG pr("sources",TTR("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_changes=false;
+ scanning_changes_done=true;
+ emit_signal("sources_changed",sources_changed.size()>0);
+ } else {
+
+ ERR_FAIL_COND(thread_sources);
+ set_process(true);
+ scan_total=0;
+ Thread::Settings s;
+ s.priority=Thread::PRIORITY_LOW;
+ thread_sources = Thread::create(_thread_func_sources,this,s);
+ //tree->hide();
+ //print_line("SCAN BEGIN!");
+ //progress->show();
+ }
+
+
+
+}
+
+void EditorFileSystem::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_ENTER_TREE: {
+
+
+ scan();
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ if (use_threads && thread) {
+ //abort thread if in progress
+ abort_scan=true;
+ while(scanning) {
+ OS::get_singleton()->delay_usec(1000);
+ }
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+ thread=NULL;
+ WARN_PRINTS("Scan thread aborted...");
+ set_process(false);
+
+ }
+
+ if (filesystem)
+ memdelete(filesystem);
+ if (new_filesystem)
+ memdelete(new_filesystem);
+ filesystem=NULL;
+ new_filesystem=NULL;
+
+ } break;
+ case NOTIFICATION_PROCESS: {
+
+ if (use_threads) {
+
+ if (scanning_changes) {
+
+ if (scanning_changes_done) {
+
+ scanning_changes=false;
+
+ set_process(false);
+
+ 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);
+ }
+ } else if (!scanning) {
+
+ set_process(false);
+
+ if (filesystem)
+ memdelete(filesystem);
+ 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()));
+
+
+
+ } else {
+ //progress->set_text("Scanning...\n"+itos(total*100)+"%");
+ }
+ }
+ } break;
+ }
+
+}
+
+bool EditorFileSystem::is_scanning() const {
+
+ return scanning || scanning_changes;
+}
+float EditorFileSystem::get_scanning_progress() const {
+
+ return scan_total;
+}
+
+EditorFileSystemDirectory *EditorFileSystem::get_filesystem() {
+
+ return filesystem;
+}
+
+void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory*p_dir,FileAccess *p_file) {
+
+
+ if (!p_dir)
+ return; //none
+ p_file->store_line("::"+p_dir->get_path()+"::"+String::num(p_dir->modified_time));
+
+ for(int i=0;i<p_dir->files.size();i++) {
+
+ String s=p_dir->files[i]->file+"::"+p_dir->files[i]->type+"::"+itos(p_dir->files[i]->modified_time)+"::"+itos(p_dir->files[i]->import_modified_time);
+ s+="::";
+ for(int j=0;j<p_dir->files[i]->deps.size();j++) {
+
+ if (j>0)
+ s+="<>";
+ s+=p_dir->files[i]->deps[j];
+ }
+
+ p_file->store_line(s);
+ }
+
+ for(int i=0;i<p_dir->subdirs.size();i++) {
+
+ _save_filesystem_cache(p_dir->subdirs[i],p_file);
+ }
+
+}
+
+
+
+
+
+
+bool EditorFileSystem::_find_file(const String& p_file,EditorFileSystemDirectory ** r_d, int &r_file_pos) const {
+ //todo make faster
+
+ if (!filesystem || scanning)
+ return false;
+
+
+ String f = GlobalConfig::get_singleton()->localize_path(p_file);
+
+ if (!f.begins_with("res://"))
+ return false;
+ f=f.substr(6,f.length());
+ f=f.replace("\\","/");
+
+ Vector<String> path = f.split("/");
+
+ if (path.size()==0)
+ return false;
+ String file=path[path.size()-1];
+ path.resize(path.size()-1);
+
+ EditorFileSystemDirectory *fs=filesystem;
+
+ for(int i=0;i<path.size();i++) {
+
+ if (path[i].begins_with("."))
+ return false;
+
+ 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 (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 (idx2==fs->get_subdir_count())
+ fs->subdirs.push_back(efsd);
+ else
+ fs->subdirs.insert(idx2,efsd);
+ fs=efsd;
+ } else {
+
+ fs=fs->get_subdir(idx);
+ }
+ }
+
+
+ int cpos=-1;
+ for(int i=0;i<fs->files.size();i++) {
+
+ if (fs->files[i]->file==file) {
+ cpos=i;
+ break;
+ }
+ }
+
+ r_file_pos=cpos;
+ *r_d=fs;
+
+ if (cpos!=-1) {
+
+ return true;
+ } else {
+
+ return false;
+ }
+
+
+}
+
+String EditorFileSystem::get_file_type(const String& p_file) const {
+
+ EditorFileSystemDirectory *fs=NULL;
+ int cpos=-1;
+
+ if (!_find_file(p_file,&fs,cpos)) {
+
+ return "";
+ }
+
+
+ return fs->files[cpos]->type;
+
+}
+
+EditorFileSystemDirectory* EditorFileSystem::find_file(const String& p_file,int* r_index) const {
+
+ if (!filesystem || scanning)
+ return NULL;
+
+ EditorFileSystemDirectory *fs=NULL;
+ int cpos=-1;
+ if (!_find_file(p_file,&fs,cpos)) {
+
+ return NULL;
+ }
+
+
+ if (r_index)
+ *r_index=cpos;
+
+ return fs;
+}
+
+
+EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String& p_path) {
+
+ if (!filesystem || scanning)
+ return NULL;
+
+
+ String f = GlobalConfig::get_singleton()->localize_path(p_path);
+
+ if (!f.begins_with("res://"))
+ return NULL;
+
+
+ f=f.substr(6,f.length());
+ f=f.replace("\\","/");
+ if (f==String())
+ return filesystem;
+
+ if (f.ends_with("/"))
+ f=f.substr(0,f.length()-1);
+
+ Vector<String> path = f.split("/");
+
+ if (path.size()==0)
+ return NULL;
+
+ EditorFileSystemDirectory *fs=filesystem;
+
+ for(int i=0;i<path.size();i++) {
+
+
+ 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 (idx==-1) {
+ return NULL;
+ } else {
+
+ fs=fs->get_subdir(idx);
+ }
+ }
+
+ return fs;
+}
+
+void EditorFileSystem::_resource_saved(const String& p_path){
+
+
+ //print_line("resource saved: "+p_path);
+ EditorFileSystem::get_singleton()->update_file(p_path);
+
+}
+
+
+
+
+void EditorFileSystem::update_file(const String& p_file) {
+
+ EditorFileSystemDirectory *fs=NULL;
+ int cpos=-1;
+
+ if (!_find_file(p_file,&fs,cpos)) {
+
+ if (!fs)
+ return;
+ }
+
+ if (!FileAccess::exists(p_file)) {
+ //was removed
+ memdelete( fs->files[cpos] );
+ fs->files.remove(cpos);
+ call_deferred("emit_signal","filesystem_changed"); //update later
+ return;
+
+ }
+
+ String type = ResourceLoader::get_resource_type(p_file);
+
+ if (cpos==-1) {
+
+ int idx=0;
+
+ for(int i=0;i<fs->files.size();i++) {
+ if (p_file<fs->files[i]->file)
+ break;
+ idx++;
+ }
+
+ EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo );
+ fi->file=p_file.get_file();
+ fi->import_modified_time=0;
+
+ if (idx==fs->files.size()) {
+ fs->files.push_back(fi);
+ } else {
+
+ fs->files.insert(idx,fi);
+ }
+ cpos=idx;
+
+
+ }
+
+ //print_line("UPDATING: "+p_file);
+ fs->files[cpos]->type=type;
+ fs->files[cpos]->modified_time=FileAccess::get_modified_time(p_file);
+ //if (FileAccess::exists(p_file+".import")) {
+ // fs->files[cpos]->import_modified_time=FileAccess::get_modified_time(p_file+".import");
+ //}
+
+ EditorResourcePreview::get_singleton()->call_deferred("check_for_invalidation",p_file);
+ call_deferred("emit_signal","filesystem_changed"); //update later
+
+}
+
+
+void EditorFileSystem::_reimport_file(const String& p_file) {
+
+ print_line("REIMPORTING: "+p_file);
+
+ EditorFileSystemDirectory *fs=NULL;
+ int cpos=-1;
+ bool found = _find_file(p_file,&fs,cpos);
+ ERR_FAIL_COND(!found);
+
+ //try to obtain existing params
+
+ Map<StringName,Variant> params;
+ String importer_name;
+
+ if (FileAccess::exists(p_file+".import")) {
+
+ Ref<ConfigFile> cf;
+ cf.instance();
+ Error err = cf->load(p_file+".import");
+ if (err==OK) {
+ List<String> sk;
+ cf->get_section_keys("params",&sk);
+ for(List<String>::Element *E=sk.front();E;E=E->next()) {
+ params[E->get()]=cf->get_value("params",E->get());
+ }
+ importer_name = cf->get_value("remap","importer");
+ }
+ }
+
+ Ref<ResourceImporter> importer;
+ //find the importer
+ if (importer_name!="") {
+ importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
+ }
+
+ if (importer.is_null()) {
+ //not found by name, find by extension
+ importer = ResourceFormatImporter::get_singleton()->get_importer_by_extension(p_file.get_extension());
+ if (importer.is_null()) {
+ ERR_PRINT("BUG: File queued for import, but can't be imported!");
+ ERR_FAIL();
+
+ }
+ }
+
+ //mix with default params, in case a parameter is missing
+
+ List<ResourceImporter::ImportOption> opts;
+ importer->get_import_options(&opts);
+ for (List<ResourceImporter::ImportOption>::Element *E=opts.front();E;E=E->next()) {
+ if (!params.has(E->get().option.name)) { //this one is not present
+ params[E->get().option.name]=E->get().default_value;
+ }
+ }
+
+ //finally, perform import!!
+ String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_file);
+
+ List<String> import_variants;
+ List<String> gen_files;
+
+ Error err = importer->import(p_file,base_path,params,&import_variants,&gen_files);
+
+ if (err!=OK) {
+ ERR_PRINTS("Error importing: "+p_file);
+ }
+
+ //as import is complete, save the .import file
+
+ FileAccess *f = FileAccess::open(p_file+".import",FileAccess::WRITE);
+ ERR_FAIL_COND(!f);
+
+ //write manually, as order matters ([remap] has to go first for performance).
+ f->store_line("[remap]");
+ f->store_line("");
+ f->store_line("importer=\""+importer->get_importer_name()+"\"");
+ if (importer->get_resource_type()!="") {
+ f->store_line("type=\""+importer->get_resource_type()+"\"");
+ }
+
+
+ if (importer->get_save_extension()=="") {
+ //no path
+ } else if (import_variants.size()) {
+ //import with variants
+ for(List<String>::Element *E=import_variants.front();E;E=E->next()) {
+
+
+ String path = base_path.c_escape()+"."+E->get()+"."+importer->get_save_extension();
+
+ f->store_line("path."+E->get()+"=\""+path+"\"");
+
+ }
+ } else {
+
+ f->store_line("path=\""+base_path+"."+importer->get_save_extension()+"\"");
+ }
+
+ f->store_line("");
+ if (gen_files.size()) {
+ f->store_line("[gen]");
+ Array genf;
+ for (List<String>::Element *E=gen_files.front();E;E=E->next()) {
+ genf.push_back(E->get());
+ }
+
+ String value;
+ VariantWriter::write_to_string(genf,value);
+ f->store_line("files="+value);
+ f->store_line("");
+ }
+
+
+ f->store_line("[params]");
+ f->store_line("");
+
+ //store options in provided order, to avoid file changing
+
+
+ for (List<ResourceImporter::ImportOption>::Element *E=opts.front();E;E=E->next()) {
+
+ String base = E->get().option.name;
+ String value;
+ VariantWriter::write_to_string(params[base],value);
+ f->store_line(base+"="+value);
+
+
+ }
+
+ f->close();
+ memdelete(f);
+
+ //update modified times, to avoid reimport
+ fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
+ fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file+".import");
+
+ //if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it
+ //to reload properly
+ if (ResourceCache::has(p_file)) {
+
+ Resource *r = ResourceCache::get(p_file);
+
+ if (r->get_import_path()!=String()) {
+
+ String dst_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_file);
+ r->set_import_path(dst_path);
+ r->set_import_last_modified_time(0);
+ }
+ }
+}
+
+void EditorFileSystem::reimport_files(const Vector<String>& p_files) {
+
+ importing=true;
+ EditorProgress pr("reimport",TTR("(Re)Importing Assets"),p_files.size());
+ for(int i=0;i<p_files.size();i++) {
+ pr.step(p_files[i].get_file(),i);
+
+ _reimport_file(p_files[i]);
+ }
+
+ _save_filesystem_cache();
+ importing=false;
+ if (!is_scanning()) {
+ emit_signal("filesystem_changed");
+ }
+}
+
+void EditorFileSystem::_bind_methods() {
+
+
+ ClassDB::bind_method(D_METHOD("get_filesystem:EditorFileSystemDirectory"),&EditorFileSystem::get_filesystem);
+ ClassDB::bind_method(D_METHOD("is_scanning"),&EditorFileSystem::is_scanning);
+ ClassDB::bind_method(D_METHOD("get_scanning_progress"),&EditorFileSystem::get_scanning_progress);
+ ClassDB::bind_method(D_METHOD("scan"),&EditorFileSystem::scan);
+ ClassDB::bind_method(D_METHOD("scan_sources"),&EditorFileSystem::scan_changes);
+ ClassDB::bind_method(D_METHOD("update_file","path"),&EditorFileSystem::update_file);
+ ClassDB::bind_method(D_METHOD("get_filesystem_path:EditorFileSystemDirectory","path"),&EditorFileSystem::get_filesystem_path);
+ ClassDB::bind_method(D_METHOD("get_file_type","path"),&EditorFileSystem::get_file_type);
+
+ ADD_SIGNAL( MethodInfo("filesystem_changed") );
+ ADD_SIGNAL( MethodInfo("sources_changed",PropertyInfo(Variant::BOOL,"exist")) );
+
+}
+
+void EditorFileSystem::_update_extensions() {
+
+ valid_extensions.clear();
+ import_extensions.clear();
+
+ 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());
+ }
+
+ extensionsl.clear();
+ ResourceFormatImporter::get_singleton()->get_recognized_extensions(&extensionsl);
+ for(List<String>::Element *E = extensionsl.front();E;E=E->next()) {
+
+ import_extensions.insert(E->get());
+ }
+}
+
+EditorFileSystem::EditorFileSystem() {
+
+ reimport_on_missing_imported_files = GLOBAL_DEF("editor/reimport_missing_imported_files",true);
+
+ singleton=this;
+ filesystem=memnew( EditorFileSystemDirectory ); //like, empty
+
+ thread = NULL;
+ scanning=false;
+ importing=false;
+ use_threads=true;
+ thread_sources=NULL;
+ new_filesystem=NULL;
+
+ scanning_changes=false;
+ ResourceSaver::set_save_callback(_resource_saved);
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->change_dir("res://.import")!=OK) {
+ da->make_dir("res://.import");
+ }
+ memdelete(da);
+
+ scan_total=0;
+}
+
+EditorFileSystem::~EditorFileSystem() {
+
+
+}
diff --git a/tools/editor/editor_file_system.h b/editor/editor_file_system.h
index 10d9b919fc..10d9b919fc 100644
--- a/tools/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
diff --git a/tools/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 3652a59978..3652a59978 100644
--- a/tools/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
diff --git a/tools/editor/editor_fonts.h b/editor/editor_fonts.h
index 0e8ce20609..0e8ce20609 100644
--- a/tools/editor/editor_fonts.h
+++ b/editor/editor_fonts.h
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
new file mode 100644
index 0000000000..7ef7658132
--- /dev/null
+++ b/editor/editor_help.cpp
@@ -0,0 +1,1929 @@
+/*************************************************************************/
+/* editor_help.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_help.h"
+
+#include "editor_node.h"
+#include "editor_settings.h"
+#include "os/keyboard.h"
+#include "doc_data_compressed.h"
+#include "editor/plugins/script_editor_plugin.h"
+
+void EditorHelpSearch::popup() {
+ popup_centered_ratio(0.6);
+ if (search_box->get_text()!="") {
+ search_box->select_all();
+ _update_search();
+ }
+ search_box->grab_focus();
+}
+
+void EditorHelpSearch::popup(const String& p_term) {
+
+ popup_centered_ratio(0.6);
+ if (p_term!="") {
+ search_box->set_text(p_term);
+ search_box->select_all();
+ _update_search();
+ } else
+ search_box->clear();
+ search_box->grab_focus();
+}
+
+
+void EditorHelpSearch::_text_changed(const String& p_newtext) {
+
+ _update_search();
+}
+
+void EditorHelpSearch::_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 ) ) {
+
+ search_options->call("_gui_input",p_ie);
+ search_box->accept_event();
+ }
+
+}
+
+void EditorHelpSearch::_update_search() {
+
+ search_options->clear();
+ search_options->set_hide_root(true);
+
+ /*
+ TreeItem *root = search_options->create_item();
+ _parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
+*/
+
+ List<StringName> type_list;
+ ClassDB::get_class_list(&type_list);
+
+ DocData *doc=EditorHelp::get_doc_data();
+ String term = search_box->get_text();
+ if (term.length()<2)
+ return;
+
+ TreeItem *root = search_options->create_item();
+
+
+
+ Ref<Texture> def_icon = get_icon("Node","EditorIcons");
+ //classes first
+ for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
+
+ if (E->key().findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_name:"+E->key());
+ item->set_text(0,E->key()+" (Class)");
+ if (has_icon(E->key(),"EditorIcons"))
+ item->set_icon(0,get_icon(E->key(),"EditorIcons"));
+ else
+ item->set_icon(0,def_icon);
+
+
+ }
+
+ }
+
+ //class methods, etc second
+ for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
+
+
+ DocData::ClassDoc & c = E->get();
+
+ Ref<Texture> cicon;
+ if (has_icon(E->key(),"EditorIcons"))
+ cicon=get_icon(E->key(),"EditorIcons");
+ else
+ cicon=def_icon;
+
+
+ for(int i=0;i<c.methods.size();i++) {
+ if( (term.begins_with(".") && c.methods[i].name.begins_with(term.right(1)))
+ || (term.ends_with("(") && c.methods[i].name.ends_with(term.left(term.length()-1).strip_edges()))
+ || (term.begins_with(".") && term.ends_with("(") && c.methods[i].name==term.substr(1,term.length()-2).strip_edges())
+ || c.methods[i].name.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_method:"+E->key()+":"+c.methods[i].name);
+ item->set_text(0,E->key()+"."+c.methods[i].name+" (Method)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ for(int i=0;i<c.signals.size();i++) {
+
+ if (c.signals[i].name.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_signal:"+E->key()+":"+c.signals[i].name);
+ item->set_text(0,E->key()+"."+c.signals[i].name+" (Signal)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ for(int i=0;i<c.constants.size();i++) {
+
+ if (c.constants[i].name.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_constant:"+E->key()+":"+c.constants[i].name);
+ item->set_text(0,E->key()+"."+c.constants[i].name+" (Constant)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ for(int i=0;i<c.properties.size();i++) {
+
+ if (c.properties[i].name.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_property:"+E->key()+":"+c.properties[i].name);
+ item->set_text(0,E->key()+"."+c.properties[i].name+" (Property)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ for(int i=0;i<c.theme_properties.size();i++) {
+
+ if (c.theme_properties[i].name.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_theme_item:"+E->key()+":"+c.theme_properties[i].name);
+ item->set_text(0,E->key()+"."+c.theme_properties[i].name+" (Theme Item)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+
+ }
+
+ //same but descriptions
+
+ for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
+
+
+ DocData::ClassDoc & c = E->get();
+
+ Ref<Texture> cicon;
+ if (has_icon(E->key(),"EditorIcons"))
+ cicon=get_icon(E->key(),"EditorIcons");
+ else
+ cicon=def_icon;
+
+ if (c.description.findn(term)!=-1) {
+
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_desc:"+E->key());
+ item->set_text(0,E->key()+" (Class Description)");
+ item->set_icon(0,cicon);
+
+ }
+
+ for(int i=0;i<c.methods.size();i++) {
+
+ if (c.methods[i].description.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_method_desc:"+E->key()+":"+c.methods[i].name);
+ item->set_text(0,E->key()+"."+c.methods[i].name+" (Method Description)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ for(int i=0;i<c.signals.size();i++) {
+
+ if (c.signals[i].description.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_signal:"+E->key()+":"+c.signals[i].name);
+ item->set_text(0,E->key()+"."+c.signals[i].name+" (Signal Description)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ for(int i=0;i<c.constants.size();i++) {
+
+ if (c.constants[i].description.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_constant:"+E->key()+":"+c.constants[i].name);
+ item->set_text(0,E->key()+"."+c.constants[i].name+" (Constant Description)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ for(int i=0;i<c.properties.size();i++) {
+
+ if (c.properties[i].description.findn(term)!=-1) {
+
+ TreeItem *item = search_options->create_item(root);
+ item->set_metadata(0,"class_property_desc:"+E->key()+":"+c.properties[i].name);
+ item->set_text(0,E->key()+"."+c.properties[i].name+" (Property Description)");
+ item->set_icon(0,cicon);
+ }
+ }
+
+ }
+
+ get_ok()->set_disabled(root->get_children()==NULL);
+
+}
+
+void EditorHelpSearch::_confirmed() {
+
+ TreeItem *ti = search_options->get_selected();
+ if (!ti)
+ return;
+
+ String mdata=ti->get_metadata(0);
+ emit_signal("go_to_help",mdata);
+ editor->call("_editor_select",EditorNode::EDITOR_SCRIPT); // in case EditorHelpSearch beeen invoked on top of other editor window
+ // go to that
+ hide();
+}
+
+void EditorHelpSearch::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ connect("confirmed",this,"_confirmed");
+ _update_search();
+ }
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ if (is_visible_in_tree()) {
+
+ search_box->call_deferred("grab_focus"); // still not visible
+ search_box->select_all();
+ }
+ }
+
+}
+
+
+void EditorHelpSearch::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_text_changed"),&EditorHelpSearch::_text_changed);
+ ClassDB::bind_method(D_METHOD("_confirmed"),&EditorHelpSearch::_confirmed);
+ ClassDB::bind_method(D_METHOD("_sbox_input"),&EditorHelpSearch::_sbox_input);
+ ClassDB::bind_method(D_METHOD("_update_search"),&EditorHelpSearch::_update_search);
+
+ ADD_SIGNAL(MethodInfo("go_to_help"));
+
+}
+
+
+EditorHelpSearch::EditorHelpSearch() {
+
+ editor=EditorNode::get_singleton();
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+
+ HBoxContainer *sb_hb = memnew( HBoxContainer);
+ search_box = memnew( LineEdit );
+ sb_hb->add_child(search_box);
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *sb = memnew( Button(TTR("Search")));
+ sb->connect("pressed",this,"_update_search");
+ sb_hb->add_child(sb);
+ vbc->add_margin_child(TTR("Search:"),sb_hb);
+ search_box->connect("text_changed",this,"_text_changed");
+ search_box->connect("gui_input",this,"_sbox_input");
+ search_options = memnew( Tree );
+ vbc->add_margin_child(TTR("Matches:"),search_options,true);
+ get_ok()->set_text(TTR("Open"));
+ get_ok()->set_disabled(true);
+ register_text_enter(search_box);
+ set_hide_on_ok(false);
+ search_options->connect("item_activated",this,"_confirmed");
+ set_title(TTR("Search Help"));
+
+ //search_options->set_hide_root(true);
+
+}
+
+/////////////////////////////////
+
+////////////////////////////////////
+/// /////////////////////////////////
+
+
+
+void EditorHelpIndex::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root) {
+
+ if (p_types.has(p_type))
+ return;
+ /*
+ if (!ClassDB::is_type(p_type,base) || p_type==base)
+ return;
+ */
+
+ String inherits=EditorHelp::get_doc_data()->class_list[p_type].inherits;
+
+ TreeItem *parent=p_root;
+
+
+ if (inherits.length()) {
+
+ if (!p_types.has(inherits)) {
+
+ add_type(inherits,p_types,p_root);
+ }
+
+ if (p_types.has(inherits) )
+ parent=p_types[inherits];
+ }
+
+ TreeItem *item = class_list->create_item(parent);
+ item->set_metadata(0,p_type);
+ item->set_tooltip(0,EditorHelp::get_doc_data()->class_list[p_type].brief_description);
+ item->set_text(0,p_type);
+
+
+ if (has_icon(p_type,"EditorIcons")) {
+
+ item->set_icon(0, get_icon(p_type,"EditorIcons"));
+ }
+
+ p_types[p_type]=item;
+}
+
+
+void EditorHelpIndex::_tree_item_selected() {
+
+
+ TreeItem *s=class_list->get_selected();
+ if (!s)
+ return;
+
+ emit_signal("open_class",s->get_text(0));
+
+ hide();
+
+ //_goto_desc(s->get_text(0));
+
+}
+
+void EditorHelpIndex::select_class(const String& p_class) {
+
+ if (!tree_item_map.has(p_class))
+ return;
+ tree_item_map[p_class]->select(0);
+ class_list->ensure_cursor_is_visible();
+}
+
+void EditorHelpIndex::popup() {
+
+ popup_centered_ratio(0.6);
+
+ search_box->set_text("");
+ _update_class_list();
+}
+
+void EditorHelpIndex::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ _update_class_list();
+
+ connect("confirmed",this,"_tree_item_selected");
+
+ } else if (p_what==NOTIFICATION_POST_POPUP) {
+
+ search_box->call_deferred("grab_focus");
+ }
+}
+
+void EditorHelpIndex::_text_changed(const String& p_text) {
+
+ _update_class_list();
+}
+
+void EditorHelpIndex::_update_class_list() {
+
+ class_list->clear();
+ tree_item_map.clear();
+ TreeItem *root = class_list->create_item();
+ class_list->set_hide_root(true);
+
+ String filter = search_box->get_text().strip_edges();
+ String to_select = "";
+
+ for(Map<String,DocData::ClassDoc>::Element *E=EditorHelp::get_doc_data()->class_list.front();E;E=E->next()) {
+
+ if (filter == "") {
+ add_type(E->key(),tree_item_map,root);
+ } else {
+
+ bool found = false;
+ String type = E->key();
+
+ while(type != "") {
+ if (filter.is_subsequence_ofi(type)) {
+
+ if (to_select.empty()) {
+ to_select = type;
+ }
+
+ found=true;
+ break;
+ }
+
+ type = EditorHelp::get_doc_data()->class_list[type].inherits;
+ }
+
+ if (found) {
+ add_type(E->key(),tree_item_map,root);
+ }
+ }
+ }
+
+ if (tree_item_map.has(filter)) {
+ select_class(filter);
+ } else if (to_select != "") {
+ select_class(to_select);
+ }
+}
+
+
+void EditorHelpIndex::_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 ) ) {
+
+ class_list->call("_gui_input",p_ie);
+ search_box->accept_event();
+ }
+}
+
+void EditorHelpIndex::_bind_methods() {
+
+ ClassDB::bind_method("_tree_item_selected",&EditorHelpIndex::_tree_item_selected);
+ ClassDB::bind_method("_text_changed",&EditorHelpIndex::_text_changed);
+ ClassDB::bind_method("_sbox_input",&EditorHelpIndex::_sbox_input);
+ ClassDB::bind_method("select_class",&EditorHelpIndex::select_class);
+ ADD_SIGNAL( MethodInfo("open_class"));
+}
+
+
+
+EditorHelpIndex::EditorHelpIndex() {
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+
+ search_box = memnew( LineEdit );
+ vbc->add_margin_child(TTR("Search:"), search_box);
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ register_text_enter(search_box);
+
+ search_box->connect("text_changed", this, "_text_changed");
+ search_box->connect("gui_input", this, "_sbox_input");
+
+ class_list = memnew( Tree );
+ vbc->add_margin_child(TTR("Class List:")+" ", class_list, true);
+ class_list->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ class_list->connect("item_activated",this,"_tree_item_selected");
+
+ get_ok()->set_text(TTR("Open"));
+ set_title(TTR("Search Classes"));
+}
+
+
+
+/////////////////////////////////
+
+////////////////////////////////////
+/// /////////////////////////////////
+DocData *EditorHelp::doc=NULL;
+
+void EditorHelp::_unhandled_key_input(const InputEvent& p_ev) {
+
+ if (!is_visible_in_tree())
+ return;
+ if ( p_ev.key.mod.control && p_ev.key.scancode==KEY_F) {
+
+ search->grab_focus();
+ search->select_all();
+ }
+}
+
+void EditorHelp::_search(const String&) {
+
+ if (search->get_text()=="")
+ return;
+
+
+ String stext=search->get_text();
+ bool keep = prev_search==stext;
+
+ bool ret = class_desc->search(stext, keep);
+ if (!ret) {
+ class_desc->search(stext, false);
+ }
+
+ prev_search=stext;
+
+
+}
+
+#if 0
+void EditorHelp::_button_pressed(int p_idx) {
+
+ if (p_idx==PAGE_CLASS_LIST) {
+
+ //edited_class->set_pressed(false);
+ //class_list_button->set_pressed(true);
+ //tabs->set_current_tab(PAGE_CLASS_LIST);
+
+ } else if (p_idx==PAGE_CLASS_DESC) {
+
+ //edited_class->set_pressed(true);
+ //class_list_button->set_pressed(false);
+ //tabs->set_current_tab(PAGE_CLASS_DESC);
+
+ } else if (p_idx==PAGE_CLASS_PREV) {
+
+ if (history_pos<2)
+ return;
+ history_pos--;
+ ERR_FAIL_INDEX(history_pos-1,history.size());
+ _goto_desc(history[history_pos-1].c,false,history[history_pos-1].scroll);
+ _update_history_buttons();
+
+
+ } else if (p_idx==PAGE_CLASS_NEXT) {
+
+ if (history_pos>=history.size())
+ return;
+
+ history_pos++;
+ ERR_FAIL_INDEX(history_pos-1,history.size());
+ _goto_desc(history[history_pos-1].c,false,history[history_pos-1].scroll);
+ _update_history_buttons();
+
+ } else if (p_idx==PAGE_SEARCH) {
+
+ _search("");
+ }
+}
+
+
+#endif
+
+void EditorHelp::_class_list_select(const String& p_select) {
+
+ _goto_desc(p_select);
+}
+
+void EditorHelp::_class_desc_select(const String& p_select) {
+
+
+
+ //print_line("LINK: "+p_select);
+ if (p_select.begins_with("#")) {
+ //_goto_desc(p_select.substr(1,p_select.length()));
+ emit_signal("go_to_help","class_name:"+p_select.substr(1,p_select.length()));
+ return;
+ } else if (p_select.begins_with("@")) {
+
+ String m = p_select.substr(1,p_select.length());
+
+ if (m.find(".")!=-1) {
+ //must go somewhere else
+
+ emit_signal("go_to_help","class_method:"+m.get_slice(".",0)+":"+m.get_slice(".",0));
+ } else {
+
+ if (!method_line.has(m))
+ return;
+ class_desc->scroll_to_line(method_line[m]);
+ }
+
+ }
+
+
+}
+
+void EditorHelp::_class_desc_input(const InputEvent& p_input) {
+ if (p_input.type==InputEvent::MOUSE_BUTTON && p_input.mouse_button.pressed && p_input.mouse_button.button_index==1) {
+ class_desc->set_selection_enabled(false);
+ class_desc->set_selection_enabled(true);
+ }
+ set_focused();
+}
+
+void EditorHelp::_add_type(const String& p_type) {
+
+ String t = p_type;
+ if (t=="")
+ t="void";
+ bool can_ref = (t!="int" && t!="real" && t!="bool" && t!="void");
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color"));
+ if (can_ref)
+ class_desc->push_meta("#"+t); //class
+ class_desc->add_text(t);
+ if (can_ref)
+ class_desc->pop();
+ class_desc->pop();
+
+}
+
+void EditorHelp::_scroll_changed(double p_scroll) {
+
+ if (scroll_locked)
+ return;
+
+ if (!class_desc->get_v_scroll()->is_visible())
+ p_scroll=0;
+
+ //history[p].scroll=p_scroll;
+}
+
+Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
+
+ //ERR_FAIL_COND(!doc->class_list.has(p_class));
+ if (!doc->class_list.has(p_class))
+ return ERR_DOES_NOT_EXIST;
+
+
+ //if (tree_item_map.has(p_class)) {
+ select_locked = true;
+ //}
+
+ class_desc->show();
+ //tabs->set_current_tab(PAGE_CLASS_DESC);
+ description_line=0;
+
+ if (p_class==edited_class)
+ return OK; //already there
+
+ scroll_locked=true;
+
+ class_desc->clear();
+ method_line.clear();
+ edited_class=p_class;
+ //edited_class->show();
+
+
+ DocData::ClassDoc cd=doc->class_list[p_class]; //make a copy, so we can sort without worrying
+
+ Color h_color;
+
+ Ref<Font> doc_font = get_font("doc","EditorFonts");
+ Ref<Font> doc_title_font = get_font("doc_title","EditorFonts");
+ Ref<Font> doc_code_font = get_font("doc_source","EditorFonts");
+
+
+ h_color=Color(1,1,1,1);
+
+ class_desc->push_font(doc_title_font);
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->add_text(TTR("Class:")+" ");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color"));
+ _add_text(p_class);
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+
+ if (cd.inherits!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Inherits:")+" ");
+ class_desc->pop();
+ class_desc->pop();
+
+ String inherits = cd.inherits;
+
+ class_desc->push_font(doc_font);
+
+ while (inherits != "") {
+ _add_type(inherits);
+
+ inherits = doc->class_list[inherits].inherits;
+
+ if (inherits != "") {
+ class_desc->add_text(" , ");
+ }
+ }
+
+ class_desc->pop();
+ class_desc->add_newline();
+ }
+
+ if (ClassDB::class_exists(cd.name)) {
+
+ bool found = false;
+ bool prev = false;
+
+ for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
+
+ if (E->get().inherits == cd.name) {
+
+ if (!found) {
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Inherited by:")+" ");
+ class_desc->pop();
+ class_desc->pop();
+
+ found = true;
+ class_desc->push_font(doc_font);
+ }
+
+ if (prev) {
+
+ class_desc->add_text(" , ");
+ prev = false;
+ }
+
+ _add_type(E->get().name);
+ prev = true;
+ }
+ }
+
+ if (found)
+ class_desc->pop();
+
+ class_desc->add_newline();
+ }
+
+ class_desc->add_newline();
+
+ if (cd.brief_description!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Brief Description:"));
+ class_desc->pop();
+ class_desc->pop();
+
+ //class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->push_font( doc_font );
+ class_desc->push_indent(1);
+ _add_text(cd.brief_description);
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
+ Set<String> skip_methods;
+ bool property_descr=false;
+
+ if (cd.properties.size()) {
+
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Members:"));
+ class_desc->pop();
+ class_desc->pop();
+ //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.properties.size();i++) {
+ property_line[cd.properties[i].name]=class_desc->get_line_count()-2; //gets overriden if description
+
+ class_desc->push_cell();
+ class_desc->push_align(RichTextLabel::ALIGN_RIGHT);
+ class_desc->push_font(doc_code_font);
+ _add_type(cd.properties[i].type);
+ class_desc->add_text(" ");
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+
+ bool describe=false;
+
+ if (cd.properties[i].setter!="") {
+ skip_methods.insert(cd.properties[i].setter);
+ describe=true;
+
+ }
+ if (cd.properties[i].getter!="") {
+ skip_methods.insert(cd.properties[i].getter);
+ describe=true;
+ }
+
+ if (cd.properties[i].description!="") {
+ describe=true;
+
+ }
+ class_desc->push_cell();
+ if (describe) {
+ class_desc->push_meta("@"+cd.properties[i].name);
+ }
+
+ class_desc->push_font(doc_code_font);
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ _add_text(cd.properties[i].name);
+
+ if (describe) {
+ class_desc->pop();
+ }
+
+
+ if (cd.properties[i].brief_description!="") {
+ class_desc->push_font(doc_font);
+ class_desc->add_text(" ");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
+ _add_text(cd.properties[i].description);
+ class_desc->pop();
+ class_desc->pop();
+
+ }
+
+ if (describe) {
+ property_descr=true;
+ }
+
+
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+
+ }
+
+
+ class_desc->pop(); //table
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
+
+ bool method_descr=false;
+ bool sort_methods = EditorSettings::get_singleton()->get("text_editor/help/sort_functions_alphabetically");
+
+ Vector<DocData::MethodDoc> methods;
+
+ for(int i=0;i<cd.methods.size();i++) {
+ if (skip_methods.has(cd.methods[i].name))
+ continue;
+ methods.push_back(cd.methods[i]);
+ }
+
+ if (methods.size()) {
+
+ if (sort_methods)
+ methods.sort();
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Public Methods:"));
+ class_desc->pop();
+ class_desc->pop();
+
+ //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<methods.size();i++) {
+
+ class_desc->push_cell();
+
+
+ method_line[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(methods[i].return_type);
+ //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 (methods[i].description!="") {
+ method_descr=true;
+ class_desc->push_meta("@"+methods[i].name);
+ }
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ _add_text(methods[i].name);
+ class_desc->pop();
+ if (methods[i].description!="")
+ class_desc->pop();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(methods[i].arguments.size()?"( ":"(");
+ class_desc->pop();
+ for(int j=0;j<methods[i].arguments.size();j++) {
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ if (j>0)
+ class_desc->add_text(", ");
+ _add_type(methods[i].arguments[j].type);
+ class_desc->add_text(" ");
+ _add_text(methods[i].arguments[j].name);
+ if (methods[i].arguments[j].default_value!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text("=");
+ class_desc->pop();
+ _add_text(methods[i].arguments[j].default_value);
+ }
+
+ class_desc->pop();
+ }
+
+ if (methods[i].qualifiers.find("vararg")!=-1) {
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->add_text(",");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(" ... ");
+ class_desc->pop();
+ class_desc->pop();
+ }
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(methods[i].arguments.size()?" )":")");
+ class_desc->pop();
+ if (methods[i].qualifiers!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->add_text(" ");
+ _add_text(methods[i].qualifiers);
+ class_desc->pop();
+
+ }
+ class_desc->pop();//monofont
+ //class_desc->add_newline();
+ class_desc->pop(); //cell
+
+ }
+ class_desc->pop(); //table
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+
+ }
+
+
+ if (cd.theme_properties.size()) {
+
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("GUI Theme Items:"));
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+
+ class_desc->push_indent(1);
+
+ //class_desc->add_newline();
+
+ for(int i=0;i<cd.theme_properties.size();i++) {
+
+ theme_property_line[cd.theme_properties[i].name]=class_desc->get_line_count()-2; //gets overriden if description
+ class_desc->push_font(doc_code_font);
+ _add_type(cd.theme_properties[i].type);
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->add_text(" ");
+ _add_text(cd.theme_properties[i].name);
+ class_desc->pop();
+ class_desc->pop();
+
+ if (cd.theme_properties[i].description!="") {
+ class_desc->push_font(doc_font);
+ class_desc->add_text(" ");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
+ _add_text(cd.theme_properties[i].description);
+ class_desc->pop();
+ class_desc->pop();
+
+ }
+
+ class_desc->add_newline();
+ }
+
+ class_desc->pop();
+ class_desc->add_newline();
+ }
+
+ if (cd.signals.size()) {
+
+ if (sort_methods) {
+ cd.signals.sort();
+ }
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Signals:"));
+ class_desc->pop();
+ class_desc->pop();
+
+ class_desc->add_newline();
+ //class_desc->add_newline();
+
+ class_desc->push_indent(1);
+
+ for(int i=0;i<cd.signals.size();i++) {
+
+ signal_line[cd.signals[i].name]=class_desc->get_line_count()-2; //gets overriden if description
+ class_desc->push_font(doc_code_font); // monofont
+ //_add_type("void");
+ //class_desc->add_text(" ");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ _add_text(cd.signals[i].name);
+ class_desc->pop();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(cd.signals[i].arguments.size()?"( ":"(");
+ class_desc->pop();
+ for(int j=0;j<cd.signals[i].arguments.size();j++) {
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ if (j>0)
+ class_desc->add_text(", ");
+ _add_type(cd.signals[i].arguments[j].type);
+ class_desc->add_text(" ");
+ _add_text(cd.signals[i].arguments[j].name);
+ if (cd.signals[i].arguments[j].default_value!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text("=");
+ class_desc->pop();
+ _add_text(cd.signals[i].arguments[j].default_value);
+ }
+
+ class_desc->pop();
+ }
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(cd.signals[i].arguments.size()?" )":")");
+ class_desc->pop();
+ class_desc->pop(); // end monofont
+ if (cd.signals[i].description!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
+ class_desc->add_text(" ");
+ _add_text(cd.signals[i].description);
+ class_desc->pop();
+
+ }
+ class_desc->add_newline();
+
+ }
+
+ class_desc->pop();
+ class_desc->add_newline();
+
+ }
+
+ if (cd.constants.size()) {
+
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Constants:"));
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->push_indent(1);
+
+ class_desc->add_newline();
+ //class_desc->add_newline();
+
+ for(int i=0;i<cd.constants.size();i++) {
+
+ constant_line[cd.constants[i].name]=class_desc->get_line_count()-2;
+ class_desc->push_font(doc_code_font);
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color"));
+ _add_text(cd.constants[i].name);
+ class_desc->pop();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(" = ");
+ class_desc->pop();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ _add_text(cd.constants[i].value);
+ class_desc->pop();
+ class_desc->pop();
+ if (cd.constants[i].description!="") {
+ class_desc->push_font(doc_font);
+ class_desc->add_text(" ");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
+ _add_text(cd.constants[i].description);
+ class_desc->pop();
+ class_desc->pop();
+ }
+
+ class_desc->add_newline();
+ }
+
+ class_desc->pop();
+ class_desc->add_newline();
+
+
+ }
+
+ if (cd.description!="") {
+
+ description_line=class_desc->get_line_count()-2;
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Description:"));
+ class_desc->pop();
+ class_desc->pop();
+
+ class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->push_font( doc_font );
+ class_desc->push_indent(1);
+ _add_text(cd.description);
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ }
+
+ if (property_descr) {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Property Description:"));
+ class_desc->pop();
+ class_desc->pop();
+
+ class_desc->add_newline();
+ class_desc->add_newline();
+
+
+ for(int i=0;i<cd.properties.size();i++) {
+
+ method_line[cd.properties[i].name]=class_desc->get_line_count()-2;
+
+ class_desc->push_font(doc_code_font);
+ _add_type(cd.properties[i].type);
+
+ class_desc->add_text(" ");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ _add_text(cd.properties[i].name);
+ class_desc->pop(); //color
+
+ class_desc->add_text(" ");
+
+ class_desc->pop(); //font
+
+ if (cd.properties[i].setter!="") {
+
+ class_desc->push_font( doc_font );
+
+ class_desc->push_indent(2);
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->add_text("Setter: ");
+ class_desc->pop();
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->add_text(cd.properties[i].setter+"(value)");
+ class_desc->pop(); //color
+
+ class_desc->pop(); //indent
+
+ class_desc->pop(); //font
+
+ }
+
+ if (cd.properties[i].getter!="") {
+
+ class_desc->push_font( doc_font );
+
+ class_desc->push_indent(2);
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->add_text("Getter: ");
+ class_desc->pop();
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->add_text(cd.properties[i].getter+"()");
+ class_desc->pop(); //color
+
+ class_desc->pop(); //indent
+
+ class_desc->pop(); //font
+
+ }
+
+ class_desc->add_newline();
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->push_font( doc_font );
+ class_desc->push_indent(1);
+ _add_text(cd.properties[i].description);
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->add_newline();
+
+ }
+
+ }
+
+ if (method_descr) {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->push_font(doc_title_font);
+ class_desc->add_text(TTR("Method Description:"));
+ class_desc->pop();
+ class_desc->pop();
+
+ class_desc->add_newline();
+ class_desc->add_newline();
+
+
+ for(int i=0;i<methods.size();i++) {
+
+ method_line[methods[i].name]=class_desc->get_line_count()-2;
+
+ class_desc->push_font(doc_code_font);
+ _add_type(methods[i].return_type);
+
+ class_desc->add_text(" ");
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ _add_text(methods[i].name);
+ class_desc->pop();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(methods[i].arguments.size()?"( ":"(");
+ class_desc->pop();
+ for(int j=0;j<methods[i].arguments.size();j++) {
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ if (j>0)
+ class_desc->add_text(", ");
+ _add_type(methods[i].arguments[j].type);
+ class_desc->add_text(" ");
+ _add_text(methods[i].arguments[j].name);
+ if (methods[i].arguments[j].default_value!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text("=");
+ class_desc->pop();
+ _add_text(methods[i].arguments[j].default_value);
+ }
+
+ class_desc->pop();
+ }
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
+ class_desc->add_text(methods[i].arguments.size()?" )":")");
+ class_desc->pop();
+ if (methods[i].qualifiers!="") {
+
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ class_desc->add_text(" ");
+ _add_text(methods[i].qualifiers);
+ class_desc->pop();
+
+ }
+
+ class_desc->pop();
+
+ class_desc->add_newline();
+ class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ class_desc->push_font( doc_font );
+ class_desc->push_indent(1);
+ _add_text(methods[i].description);
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->pop();
+ class_desc->add_newline();
+ class_desc->add_newline();
+ class_desc->add_newline();
+
+ }
+
+
+
+
+
+ }
+
+
+
+ scroll_locked=false;
+
+ return OK;
+}
+
+void EditorHelp::_request_help(const String& p_string) {
+ Error err = _goto_desc(p_string);
+ if (err==OK) {
+ editor->call("_editor_select",EditorNode::EDITOR_SCRIPT);
+ }
+ //100 palabras
+}
+
+
+void EditorHelp::_help_callback(const String& p_topic) {
+
+ String what = p_topic.get_slice(":",0);
+ String clss = p_topic.get_slice(":",1);
+ String name;
+ if (p_topic.get_slice_count(":")==3)
+ name=p_topic.get_slice(":",2);
+
+ _request_help(clss); //first go to class
+
+ int line=0;
+
+ if (what=="class_desc") {
+ line=description_line;
+ } else if (what=="class_signal") {
+ if (signal_line.has(name))
+ line=signal_line[name];
+ } else if (what=="class_method" || what=="class_method_desc") {
+ if (method_line.has(name))
+ line=method_line[name];
+ } else if (what=="class_property") {
+
+ if (property_line.has(name))
+ line=property_line[name];
+ } else if (what=="class_theme_item") {
+
+ if (theme_property_line.has(name))
+ line=theme_property_line[name];
+ } else if (what=="class_constant") {
+
+ if (constant_line.has(name))
+ line=constant_line[name];
+ }
+
+ class_desc->call_deferred("scroll_to_line", line);
+
+}
+
+
+
+static void _add_text_to_rt(const String& p_bbcode,RichTextLabel *p_rt) {
+
+ DocData *doc = EditorHelp::get_doc_data();
+ String base_path;
+
+ /*p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
+ p_rt->push_font( get_font("normal","Fonts") );
+ p_rt->push_indent(1);*/
+ int pos = 0;
+
+ Ref<Font> doc_font = p_rt->get_font("doc","EditorFonts");
+ Ref<Font> doc_code_font = p_rt->get_font("doc_source","EditorFonts");
+
+ String bbcode=p_bbcode.replace("\t"," ").replace("\r"," ").strip_edges();
+
+ //change newlines for double newlines
+ for(int i=0;i<bbcode.length();i++) {
+
+ //find valid newlines (double)
+ if (bbcode[i]=='\n') {
+ bool dnl=false;
+ int j=i+1;
+ for(;j<p_bbcode.length();j++) {
+ if (bbcode[j]==' ')
+ continue;
+ if (bbcode[j]=='\n') {
+ dnl=true;
+ break;
+ }
+ break;
+ }
+
+ if (dnl) {
+ bbcode[i]=0xFFFF;
+ //keep
+ i=j;
+ } else {
+ bbcode=bbcode.insert(i,"\n");
+ i++;
+ //bbcode[i]=' ';
+ //i=j-1;
+ }
+ }
+ }
+
+ //remove double spaces or spaces after newlines
+ for(int i=0;i<bbcode.length();i++) {
+
+ if (bbcode[i]==' ' || bbcode[i]=='\n' || bbcode[i]==0xFFFF) {
+
+ for(int j=i+1;j<p_bbcode.length();j++) {
+ if (bbcode[j]==' ') {
+ bbcode.remove(j);
+ j--;
+ continue;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ //change newlines to double newlines
+
+ CharType dnls[2]={0xFFFF,0};
+ bbcode=bbcode.replace(dnls,"\n");
+
+
+ List<String> tag_stack;
+
+ while(pos < bbcode.length()) {
+
+
+ int brk_pos = bbcode.find("[",pos);
+
+ if (brk_pos<0)
+ brk_pos=bbcode.length();
+
+ if (brk_pos > pos) {
+ p_rt->add_text(bbcode.substr(pos,brk_pos-pos));
+
+ }
+
+ if (brk_pos==bbcode.length())
+ break; //nothing else o add
+
+ int brk_end = bbcode.find("]",brk_pos+1);
+
+ if (brk_end==-1) {
+ //no close, add the rest
+ p_rt->add_text(bbcode.substr(brk_pos,bbcode.length()-brk_pos));
+
+ break;
+ }
+
+
+ String tag = bbcode.substr(brk_pos+1,brk_end-brk_pos-1);
+
+
+ if (tag.begins_with("/")) {
+ bool tag_ok = tag_stack.size() && tag_stack.front()->get()==tag.substr(1,tag.length());
+ if (tag_stack.size()) {
+
+
+
+ }
+ if (!tag_ok) {
+
+ p_rt->add_text("[");
+ pos++;
+ continue;
+ }
+
+ tag_stack.pop_front();
+ pos=brk_end+1;
+ if (tag!="/img")
+ p_rt->pop();
+
+ } else if (tag.begins_with("method ")) {
+
+ String m = tag.substr(7,tag.length());
+ p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ p_rt->push_meta("@"+m);
+ p_rt->add_text(m+"()");
+ p_rt->pop();
+ p_rt->pop();
+ pos=brk_end+1;
+
+ } else if (doc->class_list.has(tag)) {
+
+
+ p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
+ p_rt->push_meta("#"+tag);
+ p_rt->add_text(tag);
+ p_rt->pop();
+ p_rt->pop();
+ pos=brk_end+1;
+
+ } else if (tag=="b") {
+
+ //use bold font
+ p_rt->push_font(doc_code_font);
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+ } else if (tag=="i") {
+
+ //use italics font
+ Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
+ //no italics so emphasize with color
+ text_color.r*=1.1;
+ text_color.g*=1.1;
+ text_color.b*=1.1;
+ p_rt->push_color(text_color);
+ //p_rt->push_font(get_font("italic","Fonts"));
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+ } else if (tag=="code" || tag=="codeblock") {
+
+ //use monospace font
+ p_rt->push_font(doc_code_font);
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+ } else if (tag=="center") {
+
+ //use monospace font
+ p_rt->push_align(RichTextLabel::ALIGN_CENTER);
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+ } else if (tag=="br") {
+
+ //use monospace font
+ p_rt->add_newline();
+ pos=brk_end+1;
+ } else if (tag=="u") {
+
+ //use underline
+ p_rt->push_underline();
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+ } else if (tag=="s") {
+
+ //use strikethrough (not supported underline instead)
+ p_rt->push_underline();
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+
+ } else if (tag=="url") {
+
+ //use strikethrough (not supported underline instead)
+ int end=bbcode.find("[",brk_end);
+ if (end==-1)
+ end=bbcode.length();
+ String url = bbcode.substr(brk_end+1,end-brk_end-1);
+ p_rt->push_meta(url);
+
+ pos=brk_end+1;
+ tag_stack.push_front(tag);
+ } else if (tag.begins_with("url=")) {
+
+ String url = tag.substr(4,tag.length());
+ p_rt->push_meta(url);
+ pos=brk_end+1;
+ tag_stack.push_front("url");
+ } else if (tag=="img") {
+
+ //use strikethrough (not supported underline instead)
+ int end=bbcode.find("[",brk_end);
+ if (end==-1)
+ end=bbcode.length();
+ String image = bbcode.substr(brk_end+1,end-brk_end-1);
+
+ Ref<Texture> texture = ResourceLoader::load(base_path+"/"+image,"Texture");
+ if (texture.is_valid())
+ p_rt->add_image(texture);
+
+ pos=end;
+ tag_stack.push_front(tag);
+ } else if (tag.begins_with("color=")) {
+
+ String col = tag.substr(6,tag.length());
+ Color color;
+
+ if (col.begins_with("#"))
+ color=Color::html(col);
+ else if (col=="aqua")
+ color=Color::html("#00FFFF");
+ else if (col=="black")
+ color=Color::html("#000000");
+ else if (col=="blue")
+ color=Color::html("#0000FF");
+ else if (col=="fuchsia")
+ color=Color::html("#FF00FF");
+ else if (col=="gray" || col=="grey")
+ color=Color::html("#808080");
+ else if (col=="green")
+ color=Color::html("#008000");
+ else if (col=="lime")
+ color=Color::html("#00FF00");
+ else if (col=="maroon")
+ color=Color::html("#800000");
+ else if (col=="navy")
+ color=Color::html("#000080");
+ else if (col=="olive")
+ color=Color::html("#808000");
+ else if (col=="purple")
+ color=Color::html("#800080");
+ else if (col=="red")
+ color=Color::html("#FF0000");
+ else if (col=="silver")
+ color=Color::html("#C0C0C0");
+ else if (col=="teal")
+ color=Color::html("#008008");
+ else if (col=="white")
+ color=Color::html("#FFFFFF");
+ else if (col=="yellow")
+ color=Color::html("#FFFF00");
+ else
+ color=Color(0,0,0,1); //base_color;
+
+
+
+ p_rt->push_color(color);
+ pos=brk_end+1;
+ tag_stack.push_front("color");
+
+ } else if (tag.begins_with("font=")) {
+
+ String fnt = tag.substr(5,tag.length());
+
+
+ Ref<Font> font = ResourceLoader::load(base_path+"/"+fnt,"Font");
+ if (font.is_valid())
+ p_rt->push_font(font);
+ else {
+ p_rt->push_font(doc_font);
+ }
+
+ pos=brk_end+1;
+ tag_stack.push_front("font");
+
+
+ } else {
+
+ p_rt->add_text("["); //ignore
+ pos=brk_pos+1;
+
+ }
+ }
+
+ /*p_rt->pop();
+ p_rt->pop();
+ p_rt->pop();*/
+
+}
+
+
+void EditorHelp::_add_text(const String& p_bbcode) {
+
+
+ _add_text_to_rt(p_bbcode,class_desc);
+
+}
+
+
+
+
+void EditorHelp::_update_doc() {
+
+
+
+}
+
+
+void EditorHelp::generate_doc() {
+
+ doc = memnew( DocData );
+ doc->generate(true);
+ DocData compdoc;
+ compdoc.load_compressed(_doc_data_compressed,_doc_data_compressed_size,_doc_data_uncompressed_size);
+ doc->merge_from(compdoc); //ensure all is up to date
+
+
+}
+
+void EditorHelp::_notification(int p_what) {
+
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+
+ //forward->set_icon(get_icon("Forward","EditorIcons"));
+ //back->set_icon(get_icon("Back","EditorIcons"));
+ _update_doc();
+
+ } break;
+ }
+}
+
+void EditorHelp::go_to_help(const String& p_help) {
+
+ _help_callback(p_help);
+}
+
+void EditorHelp::go_to_class(const String& p_class,int p_scroll) {
+
+ _goto_desc(p_class,p_scroll);
+}
+
+void EditorHelp::popup_search() {
+
+
+ search_dialog->popup_centered(Size2(250,80));
+ search->grab_focus();
+}
+
+void EditorHelp::_search_cbk() {
+
+ _search(search->get_text());
+}
+
+String EditorHelp::get_class() {
+
+ return edited_class;
+}
+
+void EditorHelp::search_again() {
+ _search(prev_search);
+}
+
+int EditorHelp::get_scroll() const {
+
+ return class_desc->get_v_scroll()->get_value();
+}
+void EditorHelp::set_scroll(int p_scroll) {
+
+
+ class_desc->get_v_scroll()->set_value(p_scroll);
+
+}
+
+void EditorHelp::_bind_methods() {
+
+ ClassDB::bind_method("_class_list_select",&EditorHelp::_class_list_select);
+ ClassDB::bind_method("_class_desc_select",&EditorHelp::_class_desc_select);
+ ClassDB::bind_method("_class_desc_input",&EditorHelp::_class_desc_input);
+ //ClassDB::bind_method("_button_pressed",&EditorHelp::_button_pressed);
+ ClassDB::bind_method("_scroll_changed",&EditorHelp::_scroll_changed);
+ ClassDB::bind_method("_request_help",&EditorHelp::_request_help);
+ ClassDB::bind_method("_unhandled_key_input",&EditorHelp::_unhandled_key_input);
+ ClassDB::bind_method("_search",&EditorHelp::_search);
+ ClassDB::bind_method("_search_cbk",&EditorHelp::_search_cbk);
+ ClassDB::bind_method("_help_callback",&EditorHelp::_help_callback);
+
+ ADD_SIGNAL(MethodInfo("go_to_help"));
+
+}
+
+EditorHelp::EditorHelp() {
+
+ editor=EditorNode::get_singleton();
+
+ VBoxContainer *vbc = this;
+
+ EDITOR_DEF("text_editor/help/sort_functions_alphabetically",true);
+
+ //class_list->connect("meta_clicked",this,"_class_list_select");
+ //class_list->set_selection_enabled(true);
+
+ {
+ Panel *pc = memnew( Panel );
+ Ref<StyleBoxFlat> style( memnew( StyleBoxFlat ) );
+ style->set_bg_color( EditorSettings::get_singleton()->get("text_editor/highlighting/background_color") );
+ pc->set_v_size_flags(SIZE_EXPAND_FILL);
+ pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
+ vbc->add_child(pc);
+ class_desc = memnew( RichTextLabel );
+ pc->add_child(class_desc);
+ class_desc->set_area_as_parent_rect(8);
+ class_desc->connect("meta_clicked",this,"_class_desc_select");
+ class_desc->connect("gui_input",this,"_class_desc_input");
+ }
+
+ class_desc->get_v_scroll()->connect("value_changed",this,"_scroll_changed");
+ class_desc->set_selection_enabled(true);
+
+ scroll_locked=false;
+ select_locked=false;
+ set_process_unhandled_key_input(true);
+ class_desc->hide();
+
+ search_dialog = memnew( ConfirmationDialog );
+ add_child(search_dialog);
+ VBoxContainer *search_vb = memnew( VBoxContainer );
+ search_dialog->add_child(search_vb);
+
+ search = memnew( LineEdit );
+ search_dialog->register_text_enter(search);
+ search_vb->add_margin_child(TTR("Search Text"),search);
+ search_dialog->get_ok()->set_text(TTR("Find"));
+ search_dialog->connect("confirmed",this,"_search_cbk");
+ search_dialog->set_hide_on_ok(false);
+ search_dialog->set_self_modulate(Color(1,1,1,0.8));
+
+
+ /*class_search = memnew( EditorHelpSearch(editor) );
+ editor->get_gui_base()->add_child(class_search);
+ class_search->connect("go_to_help",this,"_help_callback");*/
+
+ //prev_search_page=-1;
+}
+
+EditorHelp::~EditorHelp() {
+
+}
+
+/////////////
+
+
+
+void EditorHelpBit::_go_to_help(String p_what) {
+
+ EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
+ ScriptEditor::get_singleton()->goto_help(p_what);
+ emit_signal("request_hide");
+}
+
+void EditorHelpBit::_meta_clicked(String p_select) {
+
+ //print_line("LINK: "+p_select);
+ if (p_select.begins_with("#")) {
+ //_goto_desc(p_select.substr(1,p_select.length()));
+ _go_to_help("class_name:"+p_select.substr(1,p_select.length()));
+ return;
+ } else if (p_select.begins_with("@")) {
+
+ String m = p_select.substr(1,p_select.length());
+
+ if (m.find(".")!=-1) {
+ //must go somewhere else
+
+ _go_to_help("class_method:"+m.get_slice(".",0)+":"+m.get_slice(".",0));
+ } else {
+ /*
+ if (!method_line.has(m))
+ return;
+ class_desc->scroll_to_line(method_line[m]);
+ */
+ }
+
+ }
+
+
+}
+
+void EditorHelpBit::_bind_methods() {
+
+ ClassDB::bind_method("_meta_clicked",&EditorHelpBit::_meta_clicked);
+ ADD_SIGNAL(MethodInfo("request_hide"));
+}
+
+void EditorHelpBit::_notification(int p_what){
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ add_style_override("panel",get_stylebox("normal","TextEdit"));
+ }
+}
+
+
+void EditorHelpBit::set_text(const String& p_text) {
+
+ rich_text->clear();
+ _add_text_to_rt(p_text,rich_text);
+}
+
+EditorHelpBit::EditorHelpBit() {
+
+ rich_text = memnew( RichTextLabel );
+ add_child(rich_text);
+ rich_text->set_area_as_parent_rect(8*EDSCALE);
+ rich_text->connect("meta_clicked",this,"_meta_clicked");
+ set_custom_minimum_size(Size2(0,70*EDSCALE));
+
+}
diff --git a/editor/editor_help.h b/editor/editor_help.h
new file mode 100644
index 0000000000..909226f403
--- /dev/null
+++ b/editor/editor_help.h
@@ -0,0 +1,222 @@
+/*************************************************************************/
+/* editor_help.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_HELP_H
+#define EDITOR_HELP_H
+
+#include "editor/editor_plugin.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/text_edit.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/rich_text_label.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/tree.h"
+
+#include "scene/main/timer.h"
+#include "editor/code_editor.h"
+#include "editor/doc/doc_data.h"
+
+
+class EditorNode;
+
+class EditorHelpSearch : public ConfirmationDialog {
+
+ GDCLASS(EditorHelpSearch,ConfirmationDialog )
+
+ EditorNode *editor;
+ LineEdit *search_box;
+ Tree *search_options;
+ String base_type;
+
+ void _update_search();
+
+ void _sbox_input(const InputEvent& p_ie);
+
+ void _confirmed();
+ void _text_changed(const String& p_newtext);
+
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void popup();
+ void popup(const String& p_term);
+
+ EditorHelpSearch();
+};
+
+class EditorHelpIndex : public ConfirmationDialog {
+ GDCLASS( EditorHelpIndex, ConfirmationDialog );
+
+ LineEdit *search_box;
+ Tree *class_list;
+ HashMap<String,TreeItem*> tree_item_map;
+
+ void _tree_item_selected();
+ void _text_changed(const String& p_text);
+ void _sbox_input(const InputEvent& p_ie);
+
+ void _update_class_list();
+
+ void add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root);
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+
+ void select_class(const String& p_class);
+
+ void popup();
+
+ EditorHelpIndex();
+};
+
+
+class EditorHelp : public VBoxContainer {
+ GDCLASS( EditorHelp, VBoxContainer );
+
+
+ enum Page {
+
+ PAGE_CLASS_LIST,
+ PAGE_CLASS_DESC,
+ PAGE_CLASS_PREV,
+ PAGE_CLASS_NEXT,
+ PAGE_SEARCH,
+ CLASS_SEARCH,
+
+ };
+
+
+ bool select_locked;
+
+ String prev_search;
+
+ String edited_class;
+
+ EditorNode *editor;
+ Map<String,int> method_line;
+ Map<String,int> signal_line;
+ Map<String,int> property_line;
+ Map<String,int> theme_property_line;
+ Map<String,int> constant_line;
+ int description_line;
+
+
+ RichTextLabel *class_desc;
+ HSplitContainer *h_split;
+ static DocData *doc;
+
+
+ ConfirmationDialog *search_dialog;
+ LineEdit *search;
+
+
+ String base_path;
+
+
+ void _help_callback(const String& p_topic);
+
+ void _add_text(const String& p_text);
+ bool scroll_locked;
+
+ //void _button_pressed(int p_idx);
+ void _add_type(const String& p_type);
+
+ void _scroll_changed(double p_scroll);
+ void _class_list_select(const String& p_select);
+ void _class_desc_select(const String& p_select);
+ void _class_desc_input(const InputEvent& p_input);
+
+ Error _goto_desc(const String& p_class, int p_vscr=-1);
+ //void _update_history_buttons();
+ void _update_doc();
+
+ void _request_help(const String& p_string);
+ void _search(const String& p_str);
+ void _search_cbk();
+
+ void _unhandled_key_input(const InputEvent& p_ev);
+
+
+
+protected:
+
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ static void generate_doc();
+ static DocData *get_doc_data() { return doc; }
+
+ void go_to_help(const String& p_help);
+ void go_to_class(const String& p_class,int p_scroll=0);
+
+ void popup_search();
+ void search_again();
+
+ String get_class();
+
+ void set_focused() { class_desc->grab_focus(); }
+
+ int get_scroll() const;
+ void set_scroll(int p_scroll);
+
+ EditorHelp();
+ ~EditorHelp();
+};
+
+
+
+class EditorHelpBit : public Panel {
+
+ GDCLASS( EditorHelpBit, Panel);
+
+ RichTextLabel *rich_text;
+ void _go_to_help(String p_what);
+ void _meta_clicked(String p_what);
+
+
+protected:
+
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+ void set_text(const String& p_text);
+ EditorHelpBit();
+};
+
+#endif // EDITOR_HELP_H
diff --git a/tools/editor/editor_icons.h b/editor/editor_icons.h
index 7e8d8c0828..7e8d8c0828 100644
--- a/tools/editor/editor_icons.h
+++ b/editor/editor_icons.h
diff --git a/tools/editor/editor_initialize_ssl.cpp b/editor/editor_initialize_ssl.cpp
index c08dcc6656..c08dcc6656 100644
--- a/tools/editor/editor_initialize_ssl.cpp
+++ b/editor/editor_initialize_ssl.cpp
diff --git a/tools/editor/editor_initialize_ssl.h b/editor/editor_initialize_ssl.h
index 0b34ac1d7e..0b34ac1d7e 100644
--- a/tools/editor/editor_initialize_ssl.h
+++ b/editor/editor_initialize_ssl.h
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
new file mode 100644
index 0000000000..850d9273f8
--- /dev/null
+++ b/editor/editor_log.cpp
@@ -0,0 +1,242 @@
+/*************************************************************************/
+/* editor_log.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_log.h"
+
+#include "version.h"
+#include "scene/gui/center_container.h"
+#include "editor_node.h"
+
+void EditorLog::_error_handler(void *p_self, const char*p_func, const char*p_file,int p_line, const char*p_error,const char*p_errorexp,ErrorHandlerType p_type ) {
+
+ EditorLog *self=(EditorLog *)p_self;
+ if (self->current!=Thread::get_caller_ID())
+ return;
+
+ String err_str;
+ if (p_errorexp && p_errorexp[0]) {
+ err_str=p_errorexp;
+ } else {
+ err_str=String(p_file)+":"+itos(p_line)+" - "+String(p_error);
+ }
+
+ /*
+ if (!self->is_visible_in_tree())
+ self->emit_signal("show_request");
+ */
+
+ err_str=" "+err_str;
+ self->log->add_newline();
+
+ Ref<Texture> icon;
+
+ switch(p_type) {
+ case ERR_HANDLER_ERROR: {
+
+ icon = self->get_icon("Error","EditorIcons");
+ return; // these are confusing
+ } break;
+ case ERR_HANDLER_WARNING: {
+
+ icon = self->get_icon("Error","EditorIcons");
+
+ } break;
+ case ERR_HANDLER_SCRIPT: {
+
+ icon = self->get_icon("ScriptError","EditorIcons");
+ } break;
+ case ERR_HANDLER_SHADER: {
+
+ icon = self->get_icon("Shader","EditorIcons");
+ } break;
+
+ }
+
+ self->add_message(err_str,true);
+
+}
+
+void EditorLog::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ log->add_color_override("default_color",get_color("font_color","Tree"));
+ //button->set_icon(get_icon("Console","EditorIcons"));
+
+ }
+
+ /*if (p_what==NOTIFICATION_DRAW) {
+
+ RID ci = get_canvas_item();
+ get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
+ int top_ofs = 20;
+ int border_ofs=4;
+ Ref<StyleBox> style = get_stylebox("normal","TextEdit");
+
+ style->draw(ci,Rect2( Point2(border_ofs,top_ofs),get_size()-Size2(border_ofs*2,top_ofs+border_ofs)));
+ }*/
+}
+
+
+
+
+void EditorLog::_clear_request() {
+
+ log->clear();
+
+}
+
+void EditorLog::clear() {
+ _clear_request();
+}
+
+
+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);
+ log->push_color(get_color("fg_error","Editor"));
+ } else {
+ //button->set_icon(Ref<Texture>());
+
+ }
+
+
+ log->add_newline();
+ log->add_text(p_msg);
+ //button->set_text(p_msg);
+
+ if (p_error)
+ log->pop();
+
+
+}
+
+/*
+void EditorLog::_dragged(const Point2& p_ofs) {
+
+ int ofs = ec->get_minsize().height;
+ ofs = ofs-p_ofs.y;
+ if (ofs<50)
+ ofs=50;
+ if (ofs>300)
+ ofs=300;
+ ec->set_minsize(Size2(ec->get_minsize().width,ofs));
+ minimum_size_changed();
+
+}
+*/
+
+
+
+
+void EditorLog::_undo_redo_cbk(void *p_self,const String& p_name) {
+
+ EditorLog *self=(EditorLog *)p_self;
+ self->add_message(p_name);
+
+}
+
+void EditorLog::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_clear_request"),&EditorLog::_clear_request );
+ ClassDB::bind_method("_override_logger_styles",&EditorLog::_override_logger_styles );
+ //ClassDB::bind_method(D_METHOD("_dragged"),&EditorLog::_dragged );
+ ADD_SIGNAL( MethodInfo("clear_request"));
+}
+
+EditorLog::EditorLog() {
+
+ VBoxContainer *vb = this;
+ add_constant_override("separation",get_constant("separation","VBoxContainer"));
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ vb->add_child(hb);
+ title = memnew( Label );
+ title->set_text(TTR(" Output:"));
+ title->set_h_size_flags(SIZE_EXPAND_FILL);
+ hb->add_child(title);
+
+ //pd = memnew( PaneDrag );
+ //hb->add_child(pd);
+ //pd->connect("dragged",this,"_dragged");
+ //pd->set_default_cursor_shape(Control::CURSOR_MOVE);
+
+ clearbutton = memnew( Button );
+ hb->add_child(clearbutton);
+ clearbutton->set_text(TTR("Clear"));
+ clearbutton->connect("pressed", this,"_clear_request");
+
+ ec = memnew( Control);
+ vb->add_child(ec);
+ ec->set_custom_minimum_size(Size2(0,180));
+ ec->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ pc = memnew( PanelContainer );
+ ec->add_child(pc);
+ pc->set_area_as_parent_rect();
+ pc->connect("tree_entered", this, "_override_logger_styles");
+
+ log = memnew( RichTextLabel );
+ log->set_scroll_follow(true);
+ log->set_selection_enabled(true);
+ log->set_focus_mode(FOCUS_CLICK);
+ pc->add_child(log);
+ add_message(VERSION_FULL_NAME" (c) 2008-2017 Juan Linietsky, Ariel Manzur.");
+ //log->add_text("Initialization Complete.\n"); //because it looks cool.
+
+ eh.errfunc=_error_handler;
+ eh.userdata=this;
+ add_error_handler(&eh);
+
+ current=Thread::get_caller_ID();
+
+ EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk,this);
+
+
+}
+
+void EditorLog::deinit() {
+
+ remove_error_handler(&eh);
+
+}
+
+void EditorLog::_override_logger_styles() {
+
+ pc->add_style_override("panel",get_stylebox("normal","TextEdit"));
+
+}
+
+EditorLog::~EditorLog() {
+
+
+}
diff --git a/tools/editor/editor_log.h b/editor/editor_log.h
index 965d8d6420..965d8d6420 100644
--- a/tools/editor/editor_log.h
+++ b/editor/editor_log.h
diff --git a/tools/editor/editor_name_dialog.cpp b/editor/editor_name_dialog.cpp
index da9f25f1e3..da9f25f1e3 100644
--- a/tools/editor/editor_name_dialog.cpp
+++ b/editor/editor_name_dialog.cpp
diff --git a/tools/editor/editor_name_dialog.h b/editor/editor_name_dialog.h
index d6bc7eca94..d6bc7eca94 100644
--- a/tools/editor/editor_name_dialog.h
+++ b/editor/editor_name_dialog.h
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
new file mode 100644
index 0000000000..7a85941b0d
--- /dev/null
+++ b/editor/editor_node.cpp
@@ -0,0 +1,6587 @@
+/*************************************************************************/
+/* editor_node.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_node.h"
+
+#include "version.h"
+#include "print_string.h"
+#include "editor_themes.h"
+#include "editor_help.h"
+#include "core/io/resource_saver.h"
+#include "core/io/resource_loader.h"
+#include "servers/physics_2d_server.h"
+#include "scene/resources/packed_scene.h"
+#include "editor_settings.h"
+#include "global_config.h"
+#include <stdio.h>
+#include "class_db.h"
+#include "os/keyboard.h"
+#include "os/os.h"
+#include "os/file_access.h"
+#include "message_queue.h"
+#include "path_remap.h"
+#include "translation.h"
+#include "pvrtc_compress.h"
+#include "editor_file_system.h"
+#include "register_exporters.h"
+#include "bind/core_bind.h"
+#include "io/zip_io.h"
+#include "io/config_file.h"
+#include "animation_editor.h"
+#include "io/stream_peer_ssl.h"
+#include "main/input_default.h"
+#include "os/input.h"
+// plugins
+#include "plugins/sprite_frames_editor_plugin.h"
+#include "plugins/texture_region_editor_plugin.h"
+#include "plugins/canvas_item_editor_plugin.h"
+#include "asset_library_editor_plugin.h"
+#include "plugins/spatial_editor_plugin.h"
+#include "plugins/sample_editor_plugin.h"
+#include "plugins/texture_editor_plugin.h"
+#include "plugins/material_editor_plugin.h"
+#include "plugins/sample_library_editor_plugin.h"
+#include "plugins/sample_player_editor_plugin.h"
+#include "plugins/camera_editor_plugin.h"
+#include "plugins/style_box_editor_plugin.h"
+#include "plugins/resource_preloader_editor_plugin.h"
+#include "plugins/item_list_editor_plugin.h"
+#include "plugins/stream_editor_plugin.h"
+#include "plugins/multimesh_editor_plugin.h"
+#include "plugins/mesh_instance_editor_plugin.h"
+#include "plugins/mesh_editor_plugin.h"
+#include "plugins/theme_editor_plugin.h"
+#include "plugins/tile_map_editor_plugin.h"
+#include "plugins/cube_grid_theme_editor_plugin.h"
+#include "plugins/shader_editor_plugin.h"
+#include "plugins/shader_graph_editor_plugin.h"
+#include "plugins/path_editor_plugin.h"
+#include "plugins/rich_text_editor_plugin.h"
+#include "plugins/collision_polygon_editor_plugin.h"
+#include "plugins/collision_polygon_2d_editor_plugin.h"
+#include "plugins/script_editor_plugin.h"
+#include "plugins/script_text_editor.h"
+#include "plugins/path_2d_editor_plugin.h"
+#include "plugins/line_2d_editor_plugin.h"
+#include "plugins/particles_editor_plugin.h"
+#include "plugins/particles_2d_editor_plugin.h"
+#include "plugins/animation_tree_editor_plugin.h"
+#include "plugins/tile_set_editor_plugin.h"
+#include "plugins/animation_player_editor_plugin.h"
+#include "plugins/baked_light_editor_plugin.h"
+#include "plugins/polygon_2d_editor_plugin.h"
+#include "plugins/navigation_polygon_editor_plugin.h"
+#include "plugins/light_occluder_2d_editor_plugin.h"
+#include "plugins/color_ramp_editor_plugin.h"
+#include "plugins/collision_shape_2d_editor_plugin.h"
+#include "plugins/gi_probe_editor_plugin.h"
+#include "import/resource_importer_texture.h"
+#include "import/resource_importer_csv_translation.h"
+#include "import/resource_importer_wav.h"
+#include "import/resource_importer_obj.h"
+#include "import/resource_importer_scene.h"
+// end
+#include "editor_settings.h"
+#include "io_plugins/editor_texture_import_plugin.h"
+#include "io_plugins/editor_scene_import_plugin.h"
+#include "io_plugins/editor_font_import_plugin.h"
+#include "io_plugins/editor_sample_import_plugin.h"
+#include "io_plugins/editor_translation_import_plugin.h"
+#include "io_plugins/editor_bitmask_import_plugin.h"
+#include "io_plugins/editor_mesh_import_plugin.h"
+#include "io_plugins/editor_export_scene.h"
+#include "import/editor_import_collada.h"
+#include "io_plugins/editor_scene_importer_fbxconv.h"
+
+#include "plugins/editor_preview_plugins.h"
+#include "editor_initialize_ssl.h"
+#include "editor_audio_buses.h"
+#include "script_editor_debugger.h"
+
+EditorNode *EditorNode::singleton=NULL;
+
+void EditorNode::_update_scene_tabs() {
+
+ bool show_rb = EditorSettings::get_singleton()->get("interface/show_script_in_scene_tabs");
+
+ scene_tabs->clear_tabs();
+ Ref<Texture> script_icon = gui_base->get_icon("Script","EditorIcons");
+ for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+
+ String type=editor_data.get_scene_type(i);
+ Ref<Texture> icon;
+ if (type!=String()) {
+
+ if (!gui_base->has_icon(type,"EditorIcons")) {
+ type="Node";
+ }
+
+ icon=gui_base->get_icon(type,"EditorIcons");
+
+ }
+
+
+
+ int current = editor_data.get_edited_scene();
+ bool unsaved = (i==current)?saved_version!=editor_data.get_undo_redo().get_version():editor_data.get_scene_version(i)!=0;
+ scene_tabs->add_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":""),icon);
+
+ if (show_rb && editor_data.get_scene_root_script(i).is_valid()) {
+ scene_tabs->set_tab_right_button(i,script_icon);
+ }
+
+ }
+
+ scene_tabs->set_current_tab(editor_data.get_edited_scene());
+ scene_tabs->ensure_tab_visible(editor_data.get_edited_scene());
+
+}
+
+void EditorNode::_update_title() {
+
+ String appname = GlobalConfig::get_singleton()->get("application/name");
+ String title = appname.empty()?String(VERSION_FULL_NAME):String(_MKSTR(VERSION_NAME) + String(" - ") + appname);
+ String edited = editor_data.get_edited_scene_root()?editor_data.get_edited_scene_root()->get_filename():String();
+ if (!edited.empty())
+ title+=" - " + String(edited.get_file());
+ if (unsaved_cache)
+ title+=" (*)";
+
+ OS::get_singleton()->set_window_title(title);
+
+}
+
+void EditorNode::_unhandled_input(const InputEvent& p_event) {
+
+ if (Node::get_viewport()->get_modal_stack_top())
+ return; //ignore because of modal window
+
+
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && !p_event.key.echo && !gui_base->get_viewport()->gui_has_modal_stack()) {
+
+
+ if (ED_IS_SHORTCUT("editor/next_tab", p_event)) {
+ int next_tab = editor_data.get_edited_scene() + 1;
+ next_tab %= editor_data.get_edited_scene_count();
+ _scene_tab_changed(next_tab);
+ }
+ if (ED_IS_SHORTCUT("editor/prev_tab", p_event)) {
+ int next_tab = editor_data.get_edited_scene() - 1;
+ next_tab = next_tab >= 0 ? next_tab : editor_data.get_edited_scene_count() - 1;
+ _scene_tab_changed(next_tab);
+ }
+ if (ED_IS_SHORTCUT("editor/filter_files", p_event)) {
+ filesystem_dock->focus_on_filter();
+ }
+
+ switch(p_event.key.scancode) {
+
+ /*case KEY_F1:
+ if (!p_event.key.mod.shift && !p_event.key.mod.command)
+ _editor_select(EDITOR_SCRIPT);
+ break;*/
+ case KEY_F1:
+ if (!p_event.key.mod.shift && !p_event.key.mod.command)
+ _editor_select(EDITOR_2D);
+ break;
+ case KEY_F2:
+ if (!p_event.key.mod.shift && !p_event.key.mod.command)
+ _editor_select(EDITOR_3D);
+ break;
+ case KEY_F3:
+ if (!p_event.key.mod.shift && !p_event.key.mod.command)
+ _editor_select(EDITOR_SCRIPT);
+ break;
+ /* case KEY_F5: _menu_option_confirm((p_event.key.mod.control&&p_event.key.mod.shift)?RUN_PLAY_CUSTOM_SCENE:RUN_PLAY,true); break;
+ case KEY_F6: _menu_option_confirm(RUN_PLAY_SCENE,true); break;
+ //case KEY_F7: _menu_option_confirm(RUN_PAUSE,true); break;
+ case KEY_F8: _menu_option_confirm(RUN_STOP,true); break;*/
+
+ }
+
+ }
+}
+
+
+
+void EditorNode::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ editor_data.save_editor_external_data();
+ FileAccess::set_file_close_fail_notify_callback(NULL);
+ log->deinit(); // do not get messages anymore
+ }
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ //force the whole tree viewport
+#if 0
+ {
+ Rect2 grect = scene_root_base->get_global_rect();
+ Rect2 grectsrp = scene_root_parent->get_global_rect();
+ if (grect!=grectsrp) {
+ scene_root_parent->set_pos(grect.pos);
+ scene_root_parent->set_size(grect.size);
+ }
+ }
+
+#endif
+ if (opening_prev && !confirmation->is_visible())
+ opening_prev=false;
+
+ if (unsaved_cache != (saved_version!=editor_data.get_undo_redo().get_version())) {
+
+ unsaved_cache = (saved_version!=editor_data.get_undo_redo().get_version());
+ _update_title();
+ }
+
+ if (last_checked_version!=editor_data.get_undo_redo().get_version()) {
+ _update_scene_tabs();
+ last_checked_version=editor_data.get_undo_redo().get_version();
+ }
+
+ //get_root_node()->set_rect(viewport->get_global_rect());
+
+ //update the circle
+ uint64_t frame = Engine::get_singleton()->get_frames_drawn();
+ uint32_t tick = OS::get_singleton()->get_ticks_msec();
+
+ if (frame!=circle_step_frame && (tick-circle_step_msec)>(1000/8)) {
+
+ circle_step++;
+ if (circle_step>=8)
+ circle_step=0;
+
+ circle_step_msec=tick;
+ circle_step_frame=frame+1;
+
+ // update the circle itself only when its enabled
+ if (!update_menu->get_popup()->is_item_checked(3)){
+ update_menu->set_icon(gui_base->get_icon("Progress"+itos(circle_step+1),"EditorIcons"));
+ }
+ }
+
+ editor_selection->update();
+
+ {
+ uint32_t p32 = 0;//AudioServer::get_singleton()->read_output_peak()>>8;
+
+ float peak = p32==0? -80 : Math::linear2db(p32 / 65535.0);
+
+ if (peak<-80)
+ peak=-80;
+ float vu = audio_vu->get_value();
+
+ if (peak > vu) {
+ audio_vu->set_value(peak);
+ } else {
+ float new_vu = vu - get_process_delta_time()*70.0;
+ if (new_vu<-80)
+ new_vu=-80;
+ if (new_vu !=-80 && vu !=-80)
+ audio_vu->set_value(new_vu);
+ }
+
+ }
+
+ ResourceImporterTexture::get_singleton()->update_imports();
+
+ }
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ get_tree()->get_root()->set_disable_3d(true);
+ //MessageQueue::get_singleton()->push_call(this,"_get_scene_metadata");
+ get_tree()->set_editor_hint(true);
+ get_tree()->get_root()->set_as_audio_listener(false);
+ get_tree()->get_root()->set_as_audio_listener_2d(false);
+ get_tree()->set_auto_accept_quit(false);
+ get_tree()->connect("files_dropped",this,"_dropped_files");
+ //VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport(),false);
+
+ //import_monitor->scan_changes();
+ }
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+
+ editor_data.clear_edited_scenes();
+
+ }
+ if (p_what==NOTIFICATION_READY) {
+
+ VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(),true);
+ VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(),true);
+ VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(),true);
+
+ _editor_select(EDITOR_3D);
+ _update_debug_options();
+
+/*
+ if (defer_optimize!="") {
+ Error ok = save_optimized_copy(defer_optimize,defer_optimize_preset);
+ defer_optimize_preset="";
+ if (ok!=OK)
+ OS::get_singleton()->set_exit_code(255);
+ get_scene()->quit();
+ }
+*/
+
+ /* // moved to "_sources_changed"
+ if (export_defer.platform!="") {
+
+ project_export_settings->export_platform(export_defer.platform,export_defer.path,export_defer.debug,export_defer.password,true);
+ export_defer.platform="";
+ }
+
+ */
+ }
+
+ if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) {
+
+ EditorFileSystem::get_singleton()->scan_changes();
+ }
+
+ if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) {
+
+ _menu_option_confirm(FILE_QUIT, false);
+ };
+
+ if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
+ scene_tabs->set_tab_close_display_policy( (bool(EDITOR_DEF("interface/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY) );
+ }
+
+}
+
+void EditorNode::_fs_changed() {
+
+ for(Set<FileDialog*>::Element *E=file_dialogs.front();E;E=E->next()) {
+
+ E->get()->invalidate();
+ }
+
+ for(Set<EditorFileDialog*>::Element *E=editor_file_dialogs.front();E;E=E->next()) {
+
+ E->get()->invalidate();
+ }
+
+ if (export_defer.platform!="") {
+
+ //project_export_settings->export_platform(export_defer.platform,export_defer.path,export_defer.debug,export_defer.password,true);
+ export_defer.platform="";
+ }
+
+ {
+
+ //reload changed resources
+ List<Ref<Resource> > changed;
+
+ List<Ref<Resource> > cached;
+ ResourceCache::get_cached_resources(&cached);
+ //this should probably be done in a thread..
+ for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) {
+
+ if (!E->get()->editor_can_reload_from_file())
+ continue;
+ if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path())
+ continue;
+ if (!FileAccess::exists(E->get()->get_path()))
+ continue;
+
+ if (E->get()->get_import_path()!=String()) {
+ //imported resource
+ uint64_t mt = FileAccess::get_modified_time(E->get()->get_import_path());
+ print_line("testing modified: "+E->get()->get_import_path()+" "+itos(mt)+" vs "+itos(E->get()->get_import_last_modified_time()));
+
+ if (mt!=E->get()->get_import_last_modified_time()) {
+ print_line("success");
+ changed.push_back(E->get());
+ }
+
+ } else {
+ uint64_t mt = FileAccess::get_modified_time(E->get()->get_path());
+
+ if (mt!=E->get()->get_last_modified_time()) {
+ changed.push_back(E->get());
+ }
+ }
+ }
+
+ if (changed.size()) {
+ //EditorProgress ep("reload_res","Reload Modified Resources",changed.size());
+ int idx=0;
+ for(List<Ref<Resource> >::Element *E=changed.front();E;E=E->next()) {
+
+ //ep.step(E->get()->get_path(),idx++);
+ E->get()->reload_from_file();
+ }
+ }
+
+
+ }
+}
+
+
+void EditorNode::_sources_changed(bool p_exist) {
+
+ if (waiting_for_first_scan) {
+
+ if (defer_load_scene!="") {
+
+ print_line("loading scene DEFERED");
+ load_scene(defer_load_scene);
+ defer_load_scene="";
+ }
+
+ waiting_for_first_scan=false;
+ }
+
+
+}
+
+void EditorNode::_vp_resized() {
+
+
+}
+
+void EditorNode::_rebuild_import_menu()
+{
+ PopupMenu* p = import_menu->get_popup();
+ p->clear();
+ //p->add_item(TTR("Node From Scene"), FILE_IMPORT_SUBSCENE);
+ //p->add_separator();
+#if 0
+ 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);
+ }
+#endif
+}
+
+void EditorNode::_node_renamed() {
+
+ if (property_editor)
+ property_editor->update_tree();
+}
+
+
+Error EditorNode::load_resource(const String& p_scene) {
+
+ RES res = ResourceLoader::load(p_scene);
+ ERR_FAIL_COND_V(!res.is_valid(),ERR_CANT_OPEN);
+
+ edit_resource(res);
+
+ return OK;
+}
+
+
+void EditorNode::edit_resource(const Ref<Resource>& p_resource) {
+
+ _resource_selected(p_resource,"");
+}
+
+void EditorNode::edit_node(Node *p_node) {
+
+ push_item(p_node);
+}
+
+void EditorNode::open_resource(const String& p_type) {
+
+
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type(p_type,&extensions);
+
+ file->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+ //file->set_current_path(current_path);
+
+ file->popup_centered_ratio();
+ current_option=RESOURCE_LOAD;
+}
+
+
+void EditorNode::save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path) {
+
+ editor_data.apply_changes_in_editors();
+ int flg=0;
+ if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
+ flg|=ResourceSaver::FLAG_COMPRESS;
+ /*
+ if (EditorSettings::get_singleton()->get("filesystem/on_save/save_paths_as_relative"))
+ flg|=ResourceSaver::FLAG_RELATIVE_PATHS;
+ */
+
+ String path = GlobalConfig::get_singleton()->localize_path(p_path);
+ Error err = ResourceSaver::save(path,p_resource,flg|ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
+
+ if (err!=OK) {
+ accept->set_text(TTR("Error saving resource!"));
+ accept->popup_centered_minsize();
+ return;
+ }
+ //EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
+
+ ((Resource*)p_resource.ptr())->set_path(path);
+ emit_signal("resource_saved",p_resource);
+
+}
+
+void EditorNode::save_resource(const Ref<Resource>& p_resource) {
+
+ if (p_resource->get_path().is_resource_file()) {
+ save_resource_in_path(p_resource,p_resource->get_path());
+ } else {
+ save_resource_as(p_resource);
+ }
+}
+
+void EditorNode::save_resource_as(const Ref<Resource>& p_resource,const String& p_at_path) {
+
+ file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+
+ 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_class("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);
+
+ if (p_at_path!=String()) {
+
+ file->set_current_dir(p_at_path);
+ if (p_resource->get_path().is_resource_file()) {
+ file->set_current_file(p_resource->get_path().get_file());
+ } else {
+ if (extensions.size()) {
+ file->set_current_file("new_"+p_resource->get_class().to_lower()+"."+preferred.front()->get().to_lower());
+ } else {
+ file->set_current_file(String());
+ }
+ }
+ } else if (p_resource->get_path()!="") {
+
+ file->set_current_path(p_resource->get_path());
+ if (extensions.size()) {
+ String ext=p_resource->get_path().get_extension().to_lower();
+ if (extensions.find(ext)==NULL) {
+ file->set_current_path(p_resource->get_path().replacen("."+ext,"."+extensions.front()->get()));
+ }
+ }
+ } else if (preferred.size()) {
+
+ String existing;
+ if (extensions.size()) {
+ existing="new_"+p_resource->get_class().to_lower()+"."+preferred.front()->get().to_lower();
+ }
+ file->set_current_path(existing);
+
+ }
+ file->popup_centered_ratio();
+ file->set_title(TTR("Save Resource As.."));
+}
+
+
+void EditorNode::_menu_option(int p_option) {
+
+ _menu_option_confirm(p_option,false);
+}
+
+void EditorNode::_menu_confirm_current() {
+
+ _menu_option_confirm(current_option,true);
+}
+
+
+void EditorNode::_dialog_display_file_error(String p_file,Error p_error) {
+
+
+ if (p_error) {
+
+ current_option=-1;
+ //accept->"()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+
+ switch(p_error) {
+
+ case ERR_FILE_CANT_WRITE: {
+
+ accept->set_text(TTR("Can't open file for writing:")+" "+p_file.get_extension());
+ } break;
+ case ERR_FILE_UNRECOGNIZED: {
+
+ accept->set_text(TTR("Requested file format unknown:")+" "+p_file.get_extension());
+ } break;
+ default: {
+
+ accept->set_text(TTR("Error while saving."));
+ }break;
+ }
+
+ accept->popup_centered_minsize();
+ }
+
+}
+
+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");
+
+ Ref<ConfigFile> cf;
+ cf.instance();
+
+ Error err = cf->load(path);
+ if (err!=OK || !cf->has_section("editor_states"))
+ return; //must not exist
+
+ List<String> esl;
+ cf->get_section_keys("editor_states",&esl);
+
+ Dictionary md;
+ for (List<String>::Element *E=esl.front();E;E=E->next()) {
+
+ 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(const String& p_file, int p_idx) {
+
+ Node *scene = editor_data.get_edited_scene_root(p_idx);
+
+ if (!scene)
+ return;
+
+ scene->set_meta("__editor_run_settings__",Variant()); //clear it (no point in keeping it)
+ scene->set_meta("__editor_plugin_states__",Variant());
+
+ 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;
+
+ if (p_idx<0 || editor_data.get_edited_scene()==p_idx) {
+ md = editor_data.get_editor_states();
+ } else {
+ md = editor_data.get_scene_editor_states(p_idx);
+ }
+
+ 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);
+
+}
+
+
+bool EditorNode::_find_and_save_resource(RES res,Map<RES,bool>& processed,int32_t flags) {
+
+ if (res.is_null())
+ return false;
+
+ if (processed.has(res)) {
+
+ return processed[res];
+ }
+
+
+ bool changed = res->is_edited();
+ res->set_edited(false);
+
+ bool subchanged = _find_and_save_edited_subresources(res.ptr(),processed,flags);
+
+ //print_line("checking if edited: "+res->get_type()+" :: "+res->get_name()+" :: "+res->get_path()+" :: "+itos(changed)+" :: SR "+itos(subchanged));
+
+ if (res->get_path().is_resource_file()) {
+ if (changed || subchanged) {
+ //save
+ print_line("Also saving modified external resource: "+res->get_path());
+ ResourceSaver::save(res->get_path(),res,flags);
+
+ }
+ processed[res]=false; //because it's a file
+ return false;
+ } else {
+
+
+ processed[res]=changed;
+ return changed;
+ }
+}
+
+bool EditorNode::_find_and_save_edited_subresources(Object *obj,Map<RES,bool>& processed,int32_t flags) {
+
+ bool ret_changed=false;
+ List<PropertyInfo> pi;
+ obj->get_property_list(&pi);
+ for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
+
+ if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
+ continue;
+
+
+
+ switch(E->get().type) {
+ case Variant::OBJECT: {
+
+ RES res = obj->get(E->get().name);
+
+ if (_find_and_save_resource(res,processed,flags))
+ ret_changed=true;
+
+ } break;
+ case Variant::ARRAY: {
+
+ Array varray= obj->get(E->get().name);
+ int len=varray.size();
+ for(int i=0;i<len;i++) {
+
+ Variant v=varray.get(i);
+ RES res=v;
+ if (_find_and_save_resource(res,processed,flags))
+ ret_changed=true;
+
+ //_find_resources(v);
+ }
+
+ } break;
+ case Variant::DICTIONARY: {
+
+
+ Dictionary d=obj->get(E->get().name);
+ List<Variant> keys;
+ d.get_key_list(&keys);
+ for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
+
+ Variant v = d[E->get()];
+ RES res=v;
+ if (_find_and_save_resource(res,processed,flags))
+ ret_changed=true;
+ }
+ } break;
+ default: {}
+ }
+
+ }
+
+ return ret_changed;
+
+}
+
+void EditorNode::_save_edited_subresources(Node* scene,Map<RES,bool>& processed,int32_t flags) {
+
+ _find_and_save_edited_subresources(scene,processed,flags);
+
+ for(int i=0;i<scene->get_child_count();i++) {
+
+ Node *n = scene->get_child(i);
+ if (n->get_owner()!=editor_data.get_edited_scene_root())
+ continue;
+ _save_edited_subresources(n,processed,flags);
+ }
+
+}
+
+void EditorNode::_find_node_types(Node* p_node, int&count_2d, int&count_3d) {
+
+ if (p_node->is_class("Viewport") || (p_node!=editor_data.get_edited_scene_root() && p_node->get_owner()!=editor_data.get_edited_scene_root()))
+ return;
+
+ if (p_node->is_class("CanvasItem"))
+ count_2d++;
+ else if (p_node->is_class("Spatial"))
+ count_3d++;
+
+ for(int i=0;i<p_node->get_child_count();i++)
+ _find_node_types(p_node->get_child(i),count_2d,count_3d);
+
+}
+
+
+void EditorNode::_save_scene_with_preview(String p_file) {
+
+ int c2d=0;
+ int c3d=0;
+
+ EditorProgress save("save",TTR("Saving Scene"),4);
+ save.step(TTR("Analyzing"),0);
+ _find_node_types(editor_data.get_edited_scene_root(),c2d,c3d);
+
+ RID viewport;
+ bool is2d;
+ if (c3d<c2d) {
+ viewport=scene_root->get_viewport_rid();
+ is2d=true;
+ } else {
+ viewport=SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_viewport_rid();
+ is2d=false;
+
+ }
+ save.step(TTR("Creating Thumbnail"),1);
+ //current view?
+ int screen =-1;
+ for(int i=0;i<editor_table.size();i++) {
+ if (editor_plugin_screen==editor_table[i]) {
+ screen=i;
+ break;
+ }
+ }
+
+ _editor_select(is2d?EDITOR_2D:EDITOR_3D);
+
+
+ save.step(TTR("Creating Thumbnail"),2);
+ save.step(TTR("Creating Thumbnail"),3);
+#if 0
+ Image img = VS::get_singleton()->viewport_texture(scree_capture(viewport);
+ int preview_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ preview_size*=EDSCALE;
+ int width,height;
+ if (img.get_width() > preview_size && img.get_width() >= img.get_height()) {
+
+ width=preview_size;
+ height = img.get_height() * preview_size / img.get_width();
+ } else if (img.get_height() > preview_size && img.get_height() >= img.get_width()) {
+
+ height=preview_size;
+ width = img.get_width() * preview_size / img.get_height();
+ } else {
+
+ width=img.get_width();
+ height=img.get_height();
+ }
+
+ img.convert(Image::FORMAT_RGB8);
+ img.resize(width,height);
+
+ String pfile = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/last_scene_preview.png");
+ img.save_png(pfile);
+ Vector<uint8_t> imgdata = FileAccess::get_file_as_array(pfile);
+
+ //print_line("img data is "+itos(imgdata.size()));
+
+ if (editor_data.get_edited_scene_import_metadata().is_null())
+ editor_data.set_edited_scene_import_metadata(Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) ) );
+ editor_data.get_edited_scene_import_metadata()->set_option("thumbnail",imgdata);
+#endif
+ //tamanio tel thumbnail
+ if (screen!=-1) {
+ _editor_select(screen);
+ }
+ save.step(TTR("Saving Scene"),4);
+ _save_scene(p_file);
+
+}
+
+
+void EditorNode::_save_scene(String p_file, int idx) {
+
+ Node *scene = editor_data.get_edited_scene_root(idx);
+
+ if (!scene) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text("This operation can't be done without a tree root.");
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ editor_data.apply_changes_in_editors();
+
+ _set_scene_metadata(p_file,idx);
+
+
+ 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);
+
+
+ if (err!=OK) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Couldn't save scene. Likely dependencies (instances) couldn't be satisfied."));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ int flg=0;
+ if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
+ flg|=ResourceSaver::FLAG_COMPRESS;
+ /*
+ if (EditorSettings::get_singleton()->get("filesystem/on_save/save_paths_as_relative"))
+ flg|=ResourceSaver::FLAG_RELATIVE_PATHS;
+ */
+ flg|=ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
+
+
+ err = ResourceSaver::save(p_file,sdata,flg);
+ Map<RES,bool> processed;
+ _save_edited_subresources(scene,processed,flg);
+ editor_data.save_editor_external_data();
+ if (err==OK) {
+ scene->set_filename( GlobalConfig::get_singleton()->localize_path(p_file) );
+ //EditorFileSystem::get_singleton()->update_file(p_file,sdata->get_type());
+ if (idx < 0 || idx == editor_data.get_edited_scene())
+ set_current_version(editor_data.get_undo_redo().get_version());
+ else
+ editor_data.set_edited_scene_version(0,idx);
+ _update_title();
+ _update_scene_tabs();
+ } else {
+
+ _dialog_display_file_error(p_file,err);
+ }
+
+
+};
+
+
+
+
+void EditorNode::_import_action(const String& p_action) {
+#if 0
+ import_confirmation->hide();
+
+ if (p_action=="re-import") {
+ _import(_tmp_import_path);
+ }
+ if (p_action=="update") {
+
+ Node *src = EditorImport::import_scene(_tmp_import_path);
+
+ if (!src) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text("Ugh");
+ accept->set_text("Error importing scene.");
+ accept->popup_centered(Size2(300,70));
+ return;
+ }
+
+ //as soon as the scene is imported, version hashes must be generated for comparison against saved scene
+ EditorImport::generate_version_hashes(src);
+
+
+ Node *dst = SceneLoader::load(editor_data.get_imported_scene(GlobalConfig::get_singleton()->localize_path(_tmp_import_path)));
+
+ if (!dst) {
+
+ memdelete(src);
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text("Ugh");
+ accept->set_text("Error load scene to update.");
+ accept->popup_centered(Size2(300,70));
+ return;
+ }
+
+ List<EditorImport::Conflict> conflicts;
+ EditorImport::check_conflicts(src,dst,&conflicts);
+
+ bool conflicted=false;
+ for (List<EditorImport::Conflict>::Element *E=conflicts.front();E;E=E->next()) {
+
+
+ if (E->get().status==EditorImport::Conflict::STATUS_CONFLICT) {
+
+ conflicted=true;
+ break;
+ }
+ }
+
+ if (conflicted) {
+ import_conflicts_dialog->popup(src,dst,conflicts);
+ return;
+ }
+
+ _import_with_conflicts(src,dst,conflicts);
+ //not conflicted, just reimport!
+
+ }
+#endif
+}
+
+void EditorNode::_import(const String &p_file) {
+
+#if 0
+ Node *new_scene = EditorImport::import_scene(p_file);
+
+ if (!new_scene) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text("Ugh");
+ accept->set_text("Error importing scene.");
+ accept->popup_centered(Size2(300,70));
+ return;
+ }
+
+ //as soon as the scene is imported, version hashes must be generated for comparison against saved scene
+ EditorImport::generate_version_hashes(new_scene);
+
+ Node *old_scene = edited_scene;
+ _hide_top_editors();
+ set_edited_scene(NULL);
+ editor_data.clear_editor_states();
+ if (old_scene) {
+ memdelete(old_scene);
+ }
+
+ set_edited_scene(new_scene);
+ scene_tree_dock->set_selected(new_scene);
+ //_get_scene_metadata();
+
+ editor_data.get_undo_redo().clear_history();
+ saved_version=editor_data.get_undo_redo().get_version();
+ _update_title();
+
+
+#endif
+}
+
+void EditorNode::_dialog_action(String p_file) {
+
+
+ switch(current_option) {
+
+ case RESOURCE_LOAD: {
+
+ RES res = ResourceLoader::load(p_file);
+ if (res.is_null()) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text("ok :(");
+ accept->set_text(TTR("Failed to load resource."));
+ return;
+ };
+
+
+ push_item(res.operator->() );
+ } break;
+ case FILE_NEW_INHERITED_SCENE: {
+
+
+ load_scene(p_file,false,true);
+ } break;
+ case FILE_OPEN_SCENE: {
+
+
+ load_scene(p_file);
+ } break;
+ case SETTINGS_PICK_MAIN_SCENE: {
+
+ GlobalConfig::get_singleton()->set("application/main_scene",p_file);
+ GlobalConfig::get_singleton()->save();
+ //would be nice to show the project manager opened with the hilighted field..
+ } break;
+ case FILE_SAVE_OPTIMIZED: {
+
+
+
+ } break;
+ case FILE_RUN_SCRIPT: {
+
+ Ref<Script> scr = ResourceLoader::load(p_file,"Script",true);
+ if (scr.is_null()) {
+ add_io_error("Script Failed to Load:\n"+p_file);
+ return;
+ }
+ if (!scr->is_tool()) {
+
+ add_io_error("Script is not tool, will not be able to run:\n"+p_file);
+ return;
+ }
+
+ Ref<EditorScript> es = memnew( EditorScript );
+ es->set_script(scr.get_ref_ptr());
+ es->set_editor(this);
+ es->_run();
+
+ get_undo_redo()->clear_history();
+ } break;
+ case FILE_SAVE_SCENE:
+ case FILE_SAVE_AS_SCENE: {
+
+ if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
+
+ //_save_scene(p_file);
+ _save_scene_with_preview(p_file);
+
+ }
+
+ } break;
+
+ case FILE_SAVE_AND_RUN: {
+ if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
+
+ //_save_scene(p_file);
+ _save_scene_with_preview(p_file);
+ _call_build();
+ _run(true);
+ }
+ } break;
+
+ case FILE_EXPORT_MESH_LIBRARY: {
+
+ Ref<MeshLibrary> ml;
+ if (file_export_lib_merge->is_pressed() && FileAccess::exists(p_file)) {
+ ml=ResourceLoader::load(p_file,"MeshLibrary");
+
+ if (ml.is_null()) {
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Can't load MeshLibrary for merging!"));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ }
+
+ if (ml.is_null()) {
+ ml = Ref<MeshLibrary>( memnew( MeshLibrary ));
+ }
+
+ //MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true);
+
+ Error err = ResourceSaver::save(p_file,ml);
+ if (err) {
+
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Error saving MeshLibrary!"));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+
+ } break;
+ case FILE_EXPORT_TILESET: {
+
+ Ref<TileSet> ml;
+ if (FileAccess::exists(p_file)) {
+ ml=ResourceLoader::load(p_file,"TileSet");
+
+ if (ml.is_null()) {
+ if (file_export_lib_merge->is_pressed()) {
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Can't load TileSet for merging!"));
+ accept->popup_centered_minsize();
+ return;
+ }
+ } else if (!file_export_lib_merge->is_pressed()) {
+ ml->clear();
+ }
+
+ } else {
+ ml = Ref<TileSet>( memnew( TileSet ));
+ }
+
+ TileSetEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true);
+
+ Error err = ResourceSaver::save(p_file,ml);
+ if (err) {
+
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Error saving TileSet!"));
+ accept->popup_centered_minsize();
+ return;
+ }
+ } break;
+
+ case SETTINGS_LOAD_EXPORT_TEMPLATES: {
+
+ FileAccess *fa=NULL;
+ zlib_filefunc_def io = zipio_create_io_from_file(&fa);
+
+ unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
+ if (!pkg) {
+
+ current_option=-1;
+ //confirmation->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Can't open export templates zip."));
+ accept->popup_centered_minsize();
+ return;
+
+ }
+ int ret = unzGoToFirstFile(pkg);
+
+ int fc=0; //count them
+
+ while(ret==UNZ_OK) {
+ fc++;
+ ret = unzGoToNextFile(pkg);
+
+ }
+
+ ret = unzGoToFirstFile(pkg);
+
+ EditorProgress p("ltask",TTR("Loading Export Templates"),fc);
+
+ fc=0;
+
+ while(ret==UNZ_OK) {
+
+ //get filename
+ unz_file_info info;
+ char fname[16384];
+ ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
+
+
+ String file=fname;
+
+ Vector<uint8_t> data;
+ data.resize(info.uncompressed_size);
+
+ //read
+ ret = unzOpenCurrentFile(pkg);
+ ret = unzReadCurrentFile(pkg,data.ptr(),data.size());
+ unzCloseCurrentFile(pkg);
+
+ print_line(fname);
+ /*
+ for(int i=0;i<512;i++) {
+ print_line(itos(data[i]));
+ }
+ */
+
+ file=file.get_file();
+
+ p.step(TTR("Importing:")+" "+file,fc);
+
+ FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_settings_path()+"/templates/"+file,FileAccess::WRITE);
+
+ ERR_CONTINUE(!f);
+ f->store_buffer(data.ptr(),data.size());
+
+ memdelete(f);
+
+ ret = unzGoToNextFile(pkg);
+ fc++;
+ }
+
+ unzClose(pkg);
+
+ } break;
+
+ case RESOURCE_SAVE:
+ case RESOURCE_SAVE_AS: {
+
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ 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(TTR("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(TTR("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(TTR("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(TTR("Restored default layout to base settings."));
+ }
+
+ } break;
+ default: { //save scene?
+
+ if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
+
+ //_save_scene(p_file);
+ _save_scene_with_preview(p_file);
+ }
+
+ } break;
+ }
+}
+
+
+
+void EditorNode::push_item(Object *p_object,const String& p_property) {
+
+
+ if (!p_object) {
+ property_editor->edit(NULL);
+ node_dock->set_node(NULL);
+ scene_tree_dock->set_selected(NULL);
+ return;
+ }
+
+ uint32_t id = p_object->get_instance_ID();
+ if (id!=editor_history.get_current()) {
+
+ if (p_property=="")
+ editor_history.add_object(id);
+ else
+ editor_history.add_object(id,p_property);
+ }
+
+ _edit_current();
+
+}
+
+void EditorNode::_select_history(int p_idx) {
+
+ //push it to the top, it is not correct, but it's more useful
+ ObjectID id=editor_history.get_history_obj(p_idx);
+ Object* obj=ObjectDB::get_instance(id);
+ if (!obj)
+ return;
+ push_item(obj);
+}
+
+void EditorNode::_prepare_history() {
+
+ int history_to = MAX(0,editor_history.get_history_len()-25);
+
+ editor_history_menu->get_popup()->clear();
+
+ Ref<Texture> base_icon = gui_base->get_icon("Object","EditorIcons");
+ Set<ObjectID> already;
+ for(int i=editor_history.get_history_len()-1;i>=history_to;i--) {
+
+
+ ObjectID id=editor_history.get_history_obj(i);
+ Object* obj=ObjectDB::get_instance(id);
+ if (!obj || already.has(id)) {
+ if (history_to>0) {
+ history_to--;
+ }
+ continue;
+ }
+
+ already.insert(id);
+
+ Ref<Texture> icon = gui_base->get_icon("Object","EditorIcons");
+ if (gui_base->has_icon(obj->get_class(),"EditorIcons"))
+ icon=gui_base->get_icon(obj->get_class(),"EditorIcons");
+ else
+ icon=base_icon;
+
+ String text;
+ if (obj->cast_to<Resource>()) {
+ Resource *r=obj->cast_to<Resource>();
+ if (r->get_path().is_resource_file())
+ text=r->get_path().get_file();
+ else if (r->get_name()!=String()) {
+ text=r->get_name();
+ } else {
+ text=r->get_class();
+ }
+ } else if (obj->cast_to<Node>()) {
+ text=obj->cast_to<Node>()->get_name();
+ } else {
+ text=obj->get_class();
+ }
+
+ if (i==editor_history.get_history_pos()) {
+ text="["+text+"]";
+ }
+ editor_history_menu->get_popup()->add_icon_item(icon,text,i);
+ }
+}
+
+void EditorNode::_property_editor_forward() {
+
+ if (editor_history.next())
+ _edit_current();
+
+}
+void EditorNode::_property_editor_back() {
+
+ if (editor_history.previous())
+ _edit_current();
+
+}
+
+
+void EditorNode::_imported(Node *p_node) {
+
+/*
+ Node *scene = editor_data.get_edited_scene_root();
+ add_edited_scene(p_node);
+
+ if (scene) {
+ String path = scene->get_filename();
+ p_node->set_filename(path);
+ memdelete(scene);
+ }
+*/
+
+
+}
+
+
+void EditorNode::_hide_top_editors() {
+
+ _display_top_editors(false);
+
+ editor_plugins_over->clear();
+}
+
+void EditorNode::_display_top_editors(bool p_display) {
+ editor_plugins_over->make_visible(p_display);
+}
+
+void EditorNode::_set_top_editors(Vector<EditorPlugin*> p_editor_plugins_over) {
+ editor_plugins_over->set_plugins_list(p_editor_plugins_over);
+}
+
+void EditorNode::_set_editing_top_editors(Object* p_current_object) {
+ editor_plugins_over->edit(p_current_object);
+}
+
+
+
+void EditorNode::_edit_current() {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ property_back->set_disabled( editor_history.is_at_begining() );
+ property_forward->set_disabled( editor_history.is_at_end() );
+
+ this->current=current_obj;
+ editor_path->update_path();
+
+
+ if (!current_obj) {
+
+ scene_tree_dock->set_selected(NULL);
+ property_editor->edit( NULL );
+ node_dock->set_node(NULL);
+ object_menu->set_disabled(true);
+
+ _display_top_editors(false);
+
+ return;
+ }
+
+ object_menu->set_disabled(true);
+
+ bool is_resource = current_obj->is_class("Resource");
+ bool is_node = current_obj->is_class("Node");
+ resource_save_button->set_disabled(!is_resource);
+
+ if (is_resource) {
+
+
+ Resource *current_res = current_obj->cast_to<Resource>();
+ ERR_FAIL_COND(!current_res);
+ scene_tree_dock->set_selected(NULL);
+ property_editor->edit( current_res );
+ node_dock->set_node(NULL);
+ object_menu->set_disabled(false);
+
+ //resources_dock->add_resource(Ref<Resource>(current_res));
+
+
+ //top_pallete->set_current_tab(1);
+ } else if (is_node) {
+
+ Node * current_node = current_obj->cast_to<Node>();
+ ERR_FAIL_COND(!current_node);
+ ERR_FAIL_COND(!current_node->is_inside_tree());
+
+
+
+
+ property_editor->edit( current_node );
+ node_dock->set_node( current_node );
+ scene_tree_dock->set_selected(current_node);
+ object_menu->get_popup()->clear();
+
+ //top_pallete->set_current_tab(0);
+
+ } else {
+
+ property_editor->edit( current_obj );
+ node_dock->set_node(NULL);
+ //scene_tree_dock->set_selected(current_node);
+ //object_menu->get_popup()->clear();
+
+ }
+
+ /* Take care of PLUGIN EDITOR */
+
+
+ EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
+
+ if (main_plugin) {
+
+ // special case if use of external editor is true
+ if (main_plugin->get_name() == "Script" && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))){
+ main_plugin->edit(current_obj);
+ }
+
+ else if (main_plugin!=editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) {
+ // update screen main_plugin
+
+ if (!changing_scene) {
+ if (editor_plugin_screen)
+ editor_plugin_screen->make_visible(false);
+ editor_plugin_screen=main_plugin;
+ editor_plugin_screen->edit(current_obj);
+
+ editor_plugin_screen->make_visible(true);
+
+
+ for(int i=0;i<editor_table.size();i++) {
+
+ main_editor_buttons[i]->set_pressed(editor_table[i]==main_plugin);
+ }
+ }
+
+ } else {
+
+ editor_plugin_screen->edit(current_obj);
+ }
+
+ }
+
+ Vector<EditorPlugin*> sub_plugins = editor_data.get_subeditors(current_obj);
+
+ if (!sub_plugins.empty()) {
+ _display_top_editors(false);
+
+ _set_top_editors(sub_plugins);
+ _set_editing_top_editors(current_obj);
+ _display_top_editors(true);
+
+ } else if (!editor_plugins_over->get_plugins_list().empty()) {
+
+ _hide_top_editors();
+
+ }
+/*
+ if (!plugin || plugin->has_main_screen()) {
+ // remove the OVER plugin if exists
+ if (editor_plugin_over)
+ editor_plugin_over->make_visible(false);
+ editor_plugin_over=NULL;
+ }
+*/
+ /* Take care of OBJECT MENU */
+
+ object_menu->set_disabled(false);
+
+ PopupMenu *p=object_menu->get_popup();
+
+ p->clear();
+ p->add_shortcut(ED_SHORTCUT("property_editor/copy_params",TTR("Copy Params")),OBJECT_COPY_PARAMS);
+ p->add_shortcut(ED_SHORTCUT("property_editor/paste_params",TTR("Paste Params")),OBJECT_PASTE_PARAMS);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource",TTR("Paste Resource")),RESOURCE_PASTE);
+ if (is_resource) {
+ p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource",TTR("Copy Resource")),RESOURCE_COPY);
+ p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource",TTR("Make Built-In")),RESOURCE_UNREF);
+ }
+
+ if (is_resource || is_node) {
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique",TTR("Make Sub-Resources Unique")),OBJECT_UNIQUE_RESOURCES);
+ p->add_separator();
+ p->add_icon_shortcut(gui_base->get_icon("Help","EditorIcons"),ED_SHORTCUT("property_editor/open_help",TTR("Open in Help")),OBJECT_REQUEST_HELP);
+ }
+
+ List<MethodInfo> methods;
+ current_obj->get_method_list(&methods);
+
+
+ if (!methods.empty()) {
+
+ bool found=false;
+ List<MethodInfo>::Element *I=methods.front();
+ int i=0;
+ while(I) {
+
+ if (I->get().flags&METHOD_FLAG_EDITOR) {
+ if (!found) {
+ p->add_separator();
+ found=true;
+ }
+ p->add_item(I->get().name.capitalize(),OBJECT_METHOD_BASE+i);
+ }
+ i++;
+ I=I->next();
+ }
+ }
+
+ //p->add_separator();
+ //p->add_item("All Methods",OBJECT_CALL_METHOD);
+
+
+ update_keying();
+}
+
+void EditorNode::_resource_created() {
+
+ Object *c = create_dialog->instance_selected();
+
+ ERR_FAIL_COND(!c);
+ Resource *r = c->cast_to<Resource>();
+ ERR_FAIL_COND(!r);
+
+ REF res( r );
+
+ push_item(c);
+
+}
+
+void EditorNode::_resource_selected(const RES& p_res,const String& p_property) {
+
+
+ if (p_res.is_null())
+ return;
+
+ RES r=p_res;
+ push_item(r.operator->(),p_property);
+
+}
+
+
+void EditorNode::_run(bool p_current,const String& p_custom) {
+
+ if (editor_run.get_status()==EditorRun::STATUS_PLAY) {
+
+ play_button->set_pressed(!_playing_edited);
+ play_scene_button->set_pressed(_playing_edited);
+ return;
+ }
+
+ play_button->set_pressed(false);
+ 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"));
+ play_custom_scene_button->set_pressed(false);
+ play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
+
+ String main_scene;
+ String run_filename;
+ String args;
+
+
+ if (p_current || (editor_data.get_edited_scene_root() && p_custom==editor_data.get_edited_scene_root()->get_filename())) {
+
+ Node *scene = editor_data.get_edited_scene_root();
+
+ if (!scene) {
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("There is no defined scene to run."));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ if (scene->get_filename()=="") {
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ /**/
+ _menu_option_confirm(FILE_SAVE_BEFORE_RUN, false);
+ return;
+
+ }
+
+ run_filename=scene->get_filename();
+ } else if (p_custom!="") {
+ run_filename = p_custom;
+ }
+
+ if (run_filename=="") {
+
+ //evidently, run the scene
+ main_scene=GLOBAL_DEF("application/main_scene","");
+ if (main_scene=="") {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in later in \"Project Settings\" under the 'application' category."));
+ pick_main_scene->popup_centered_minsize();
+ return;
+ }
+
+ if (!FileAccess::exists(main_scene)) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ pick_main_scene->set_text(vformat(TTR("Selected scene '%s' does not exist, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
+ pick_main_scene->popup_centered_minsize();
+ return;
+
+ }
+
+ if (ResourceLoader::get_resource_type(main_scene)!="PackedScene") {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ pick_main_scene->set_text(vformat(TTR("Selected scene '%s' is not a scene file, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), main_scene));
+ pick_main_scene->popup_centered_minsize();
+ return;
+
+ }
+
+ }
+
+
+ if (bool(EDITOR_DEF("run/auto_save/save_before_running",true))) {
+
+ if (unsaved_cache) {
+
+ Node *scene = editor_data.get_edited_scene_root();
+
+ if (scene) { //only autosave if there is a scene obviously
+
+ if (scene->get_filename()=="") {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Current scene was never saved, please save it prior to running."));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ //_save_scene(scene->get_filename());
+ _save_scene_with_preview(scene->get_filename());
+ }
+ }
+ _menu_option(FILE_SAVE_ALL_SCENES);
+ editor_data.save_editor_external_data();
+ }
+
+ if (bool(EDITOR_DEF("run/output/always_clear_output_on_play", true))) {
+ log->clear();
+ }
+
+ if (bool(EDITOR_DEF("run/output/always_open_output_on_play", true))) {
+ make_bottom_panel_item_visible(log);
+ }
+
+ List<String> breakpoints;
+ editor_data.get_editor_breakpoints(&breakpoints);
+
+ args = GlobalConfig::get_singleton()->get("editor/main_run_args");
+
+ Error error = editor_run.run(run_filename,args,breakpoints);
+
+ if (error!=OK) {
+
+ current_option=-1;
+ //confirmation->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Could not start subprocess!"));
+ accept->popup_centered_minsize();
+ return;
+
+ }
+
+ emit_signal("play_pressed");
+ if (p_current) {
+ play_scene_button->set_pressed(true);
+ play_scene_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
+ } else if (p_custom!="") {
+ run_custom_filename=p_custom;
+ play_custom_scene_button->set_pressed(true);
+ play_custom_scene_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
+ } else {
+ play_button->set_pressed(true);
+ play_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
+ }
+
+ _playing_edited=p_current;
+
+}
+
+void EditorNode::_cleanup_scene() {
+
+#if 0
+ Node *scene = editor_data.get_edited_scene_root();
+ editor_selection->clear();
+ editor_data.clear_editor_states();
+ editor_history.clear();
+ _hide_top_editors();
+ animation_editor->cleanup();
+ property_editor->edit(NULL);
+ resources_dock->cleanup();
+ scene_import_metadata.unref();
+ //set_edited_scene(NULL);
+ if (scene) {
+ if (scene->get_filename()!="") {
+ previous_scenes.push_back(scene->get_filename());
+ }
+
+ memdelete(scene);
+ }
+ editor_data.get_undo_redo().clear_history();
+ saved_version=editor_data.get_undo_redo().get_version();
+ run_settings_dialog->set_run_mode(0);
+ run_settings_dialog->set_custom_arguments("-l $scene");
+
+ List<Ref<Resource> > cached;
+ ResourceCache::get_cached_resources(&cached);
+
+ for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) {
+
+ String path = E->get()->get_path();
+ if (path.is_resource_file()) {
+ ERR_PRINT(("Stray resource not cleaned:"+path).utf8().get_data());
+ }
+
+ }
+
+ _update_title();
+#endif
+}
+
+void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
+
+ //print_line("option "+itos(p_option)+" confirm "+itos(p_confirmed));
+ if (!p_confirmed) //this may be a hack..
+ current_option=(MenuOptions)p_option;
+
+
+ switch( p_option ) {
+ case FILE_NEW_SCENE: {
+
+ // TODO: Drop such obsolete commented code
+ /*
+ if (!p_confirmed) {
+ confirmation->get_ok()->set_text("Yes");
+ //confirmation->get_cancel()->show();
+ confirmation->set_text("Start a New Scene? (Current will be lost)");
+ confirmation->popup_centered_minsize();
+ break;
+ }*/
+
+
+ int idx = editor_data.add_edited_scene(-1);
+ _scene_tab_changed(idx);
+ editor_data.clear_editor_states();
+
+ //_cleanup_scene();
+
+
+ } break;
+ case FILE_NEW_INHERITED_SCENE:
+ case FILE_OPEN_SCENE: {
+
+
+ //print_tree();
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ //not for now?
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
+ file->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+
+ //file->set_current_path(current_path);
+ Node *scene = editor_data.get_edited_scene_root();
+ if (scene) {
+ file->set_current_path(scene->get_filename());
+ };
+ file->set_title(p_option==FILE_OPEN_SCENE?TTR("Open Scene"):TTR("Open Base Scene"));
+ file->popup_centered_ratio();
+
+ } break;
+ case FILE_QUICK_OPEN_SCENE: {
+
+ quick_open->popup("PackedScene", true);
+ quick_open->set_title(TTR("Quick Open Scene.."));
+
+ } break;
+ case FILE_QUICK_OPEN_SCRIPT: {
+
+
+ quick_open->popup("Script", true);
+ quick_open->set_title(TTR("Quick Open Script.."));
+
+ } break;
+ case FILE_RUN_SCRIPT: {
+
+ file_script->popup_centered_ratio();
+ } break;
+ case FILE_OPEN_PREV: {
+
+ if (previous_scenes.empty())
+ break;
+ opening_prev=true;
+ open_request(previous_scenes.back()->get());
+
+ } break;
+ case FILE_CLOSE: {
+
+ if (!p_confirmed && unsaved_cache) {
+ confirmation->get_ok()->set_text(TTR("Yes"));
+ //confirmation->get_cancel()->show();
+ confirmation->set_text(TTR("Close scene? (Unsaved changes will be lost)"));
+ confirmation->popup_centered_minsize();
+ break;
+ }
+
+ _remove_edited_scene();
+
+
+
+ } break;
+ case SCENE_TAB_CLOSE: {
+ _remove_scene(tab_closing);
+ _update_scene_tabs();
+ current_option = -1;
+ } break;
+ case FILE_SAVE_SCENE: {
+
+
+ Node *scene = editor_data.get_edited_scene_root();
+ if (scene && scene->get_filename()!="") {
+
+ // save in background if in the script editor
+ if (_get_current_main_editor() == EDITOR_SCRIPT) {
+ _save_scene(scene->get_filename());
+ } else {
+ _save_scene_with_preview(scene->get_filename());
+ }
+ return;
+ };
+ // fallthrough to save_as
+ };
+ case FILE_SAVE_AS_SCENE: {
+
+ Node *scene = editor_data.get_edited_scene_root();
+
+ if (!scene) {
+
+ current_option=-1;
+ //confirmation->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text("This operation can't be done without a tree root.");
+ 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());
+ }
+
+ //file->set_current_path(current_path);
+ if (scene->get_filename()!="") {
+ file->set_current_path(scene->get_filename());
+ if (extensions.size()) {
+ String ext=scene->get_filename().get_extension().to_lower();
+ if (extensions.find(ext)==NULL) {
+ file->set_current_path(scene->get_filename().replacen("."+ext,"."+extensions.front()->get()));
+ }
+ }
+ } else {
+
+ String existing;
+ if (extensions.size()) {
+ String root_name(get_edited_scene()->get_name());
+ existing=root_name+"."+extensions.front()->get().to_lower();
+ }
+ file->set_current_path(existing);
+
+ }
+ file->popup_centered_ratio();
+ file->set_title(TTR("Save Scene As.."));
+
+ } break;
+
+ case FILE_SAVE_ALL_SCENES: {
+ for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
+ Node *scene = editor_data.get_edited_scene_root(i);
+ if (scene && scene->get_filename()!="") {
+ // save in background if in the script editor
+ if (i != editor_data.get_edited_scene() || _get_current_main_editor() == EDITOR_SCRIPT) {
+ _save_scene(scene->get_filename(), i);
+ } else {
+ _save_scene_with_preview(scene->get_filename());
+ }
+ }// else: ignore new scenes
+ }
+ } break;
+ case FILE_SAVE_BEFORE_RUN: {
+ if (!p_confirmed) {
+ accept->get_ok()->set_text(TTR("Yes"));
+ accept->set_text(TTR("This scene has never been saved. Save before running?"));
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ _menu_option(FILE_SAVE_AS_SCENE);
+ _menu_option_confirm(FILE_SAVE_AND_RUN, true);
+ } break;
+
+ case FILE_SAVE_OPTIMIZED: {
+#if 0
+ 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 tree root.");
+ accept->popup_centered(Size2(300,70));
+ break;
+ }
+
+
+
+ //file->set_current_path(current_path);
+
+ String cpath;
+ if (scene->get_filename()!="") {
+ cpath = scene->get_filename();
+
+ String fn = cpath.substr(0,cpath.length() - cpath.extension().size());
+ String ext=cpath.extension();
+ cpath=fn+".optimized.scn";
+ optimized_save->set_optimized_scene(cpath);
+ optimized_save->popup_centered(Size2(500,143));
+ } else {
+ current_option=-1;
+ //confirmation->get_cancel()->hide();
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("Please save the scene first.");
+ accept->popup_centered(Size2(300,70));
+ break;
+
+ }
+#endif
+ } break;
+
+ case FILE_EXPORT_PROJECT: {
+
+ project_export->popup_export();
+ } break;
+
+ case FILE_EXPORT_MESH_LIBRARY: {
+
+ if (!editor_data.get_edited_scene_root()) {
+
+ current_option=-1;
+ //confirmation->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text("This operation can't be done without a scene.");
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ List<String> extensions;
+ Ref<MeshLibrary> ml( memnew( MeshLibrary) );
+ ResourceSaver::get_recognized_extensions(ml,&extensions);
+ file_export_lib->clear_filters();
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+ file_export_lib->add_filter("*."+E->get());
+ }
+
+ file_export_lib->popup_centered_ratio();
+ file_export_lib->set_title(TTR("Export Mesh Library"));
+
+ } break;
+ case FILE_EXPORT_TILESET: {
+
+ List<String> extensions;
+ Ref<TileSet> ml( memnew( TileSet) );
+ ResourceSaver::get_recognized_extensions(ml,&extensions);
+ file_export_lib->clear_filters();
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+ file_export_lib->add_filter("*."+E->get());
+ }
+
+ file_export_lib->popup_centered_ratio();
+ file_export_lib->set_title(TTR("Export Tile Set"));
+
+ } break;
+
+ case SETTINGS_EXPORT_PREFERENCES: {
+
+ //project_export_settings->popup_centered_ratio();
+ } break;
+ case FILE_IMPORT_SUBSCENE: {
+
+ //import_subscene->popup_centered_ratio();
+
+ if (!editor_data.get_edited_scene_root()) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text("This operation can't be done without a selected node.");
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ scene_tree_dock->import_subscene();
+
+ } break;
+
+ case FILE_QUIT: {
+
+
+ if (!p_confirmed) {
+
+ confirmation->get_ok()->set_text(TTR("Quit"));
+ //confirmation->get_cancel()->show();
+ confirmation->set_text(TTR("Exit the editor?"));
+ confirmation->popup_centered(Size2(180,70)*EDSCALE);
+ break;
+ }
+
+
+ _menu_option_confirm(RUN_STOP,true);
+ exiting=true;
+ get_tree()->quit();
+
+ } break;
+ case FILE_EXTERNAL_OPEN_SCENE: {
+
+ if (unsaved_cache && !p_confirmed) {
+
+ confirmation->get_ok()->set_text(TTR("Open"));
+ //confirmation->get_cancel()->show();
+ confirmation->set_text(TTR("Current scene not saved. Open anyway?"));
+ confirmation->popup_centered_minsize();
+ break;
+
+ }
+
+ bool oprev=opening_prev;
+ Error err = load_scene(external_file);
+ if (err == OK && oprev) {
+ previous_scenes.pop_back();
+ opening_prev=false;
+ }
+
+ } break;
+
+ case EDIT_UNDO: {
+
+
+
+ if (Input::get_singleton()->get_mouse_button_mask()&0x7) {
+ print_line("no because state");
+ break; // can't undo while mouse buttons are pressed
+ }
+
+ String action = editor_data.get_undo_redo().get_current_action_name();
+ if (action!="")
+ log->add_message("UNDO: "+action);
+
+ editor_data.get_undo_redo().undo();
+ } break;
+ case EDIT_REDO: {
+
+ if (Input::get_singleton()->get_mouse_button_mask()&0x7)
+ break; // can't redo while mouse buttons are pressed
+
+ editor_data.get_undo_redo().redo();
+ String action = editor_data.get_undo_redo().get_current_action_name();
+ if (action!="")
+ log->add_message("REDO: "+action);
+
+ } break;
+ case TOOLS_ORPHAN_RESOURCES: {
+
+ orphan_resources->show();
+ } break;
+
+ case EDIT_REVERT: {
+
+ Node *scene = get_edited_scene();
+
+ if (!scene)
+ break;
+
+ String filename = scene->get_filename();
+
+ if (filename==String()) {
+ show_warning(TTR("Can't reload a scene that was never saved."));
+ break;
+ }
+
+ if (unsaved_cache && !p_confirmed) {
+ confirmation->get_ok()->set_text(TTR("Revert"));
+ confirmation->set_text(TTR("This action cannot be undone. Revert anyway?"));
+ confirmation->popup_centered_minsize();
+ break;
+ }
+
+
+ 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;
+
+#if 0
+ case NODE_EXTERNAL_INSTANCE: {
+
+
+ if (!edited_scene) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("This operation can't be done without a selected node.");
+ accept->popup_centered(Size2(300,70));
+ break;
+ }
+
+ Node *parent = scene_tree_editor->get_selected();
+
+ if (!parent) {
+
+ 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 selected node.");
+ accept->popup_centered(Size2(300,70));
+ break;
+ }
+
+ Node*instanced_scene=SceneLoader::load(external_file,true);
+
+ if (!instanced_scene) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text("Ugh");
+ accept->set_text("Error loading scene from "+external_file);
+ accept->popup_centered(Size2(300,70));
+ return;
+ }
+
+ instanced_scene->generate_instance_state();
+ instanced_scene->set_filename( GlobalConfig::get_singleton()->localize_path(external_file) );
+
+ editor_data.get_undo_redo().create_action("Instance Scene");
+ editor_data.get_undo_redo().add_do_method(parent,"add_child",instanced_scene);
+ editor_data.get_undo_redo().add_do_method(instanced_scene,"set_owner",edited_scene);
+ editor_data.get_undo_redo().add_do_reference(instanced_scene);
+ editor_data.get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene);
+ editor_data.get_undo_redo().commit_action();
+
+ //parent->add_child(instanced_scene);
+ //instanced_scene->set_owner(edited_scene);
+ _last_instanced_scene=instanced_scene;
+
+ } break;
+#endif
+ case RESOURCE_NEW: {
+
+ create_dialog->popup(true);
+ } break;
+ case RESOURCE_LOAD: {
+
+ open_resource();
+ } break;
+ case RESOURCE_SAVE: {
+
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ save_resource(current_res);
+
+ } break;
+ case RESOURCE_SAVE_AS: {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ save_resource_as(current_res);
+
+ } break;
+ case RESOURCE_UNREF: {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+ current_res->set_path("");
+ _edit_current();
+ } break;
+ case RESOURCE_COPY: {
+
+ uint32_t current = editor_history.get_current();
+ Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
+
+ ERR_FAIL_COND(!current_obj->cast_to<Resource>())
+
+ RES current_res = RES(current_obj->cast_to<Resource>());
+
+ EditorSettings::get_singleton()->set_resource_clipboard(current_res);
+
+ } break;
+ case RESOURCE_PASTE: {
+
+ RES r = EditorSettings::get_singleton()->get_resource_clipboard();
+ if (r.is_valid()) {
+ push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(),String());
+ }
+
+ } break;
+ case OBJECT_REQUEST_HELP: {
+
+ if (current) {
+ _editor_select(EDITOR_SCRIPT);
+ emit_signal("request_help",current->get_class());
+ }
+
+
+ } break;
+ case OBJECT_COPY_PARAMS: {
+
+ editor_data.apply_changes_in_editors();
+ if (current)
+ editor_data.copy_object_params(current);
+ } break;
+ case OBJECT_PASTE_PARAMS: {
+
+ editor_data.apply_changes_in_editors();
+ if (current)
+ editor_data.paste_object_params(current);
+ editor_data.get_undo_redo().clear_history();
+ } break;
+ case OBJECT_UNIQUE_RESOURCES: {
+
+ editor_data.apply_changes_in_editors();
+ if (current) {
+ List<PropertyInfo> props;
+ current->get_property_list(&props);
+ Map<RES,RES> duplicates;
+ for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+
+ if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
+ continue;
+
+ Variant v = current->get(E->get().name);
+ if (v.is_ref()) {
+ REF ref = v;
+ if (ref.is_valid()) {
+
+ RES res = ref;
+ if (res.is_valid()) {
+
+ if (!duplicates.has(res)) {
+ duplicates[res]=res->duplicate();
+ }
+ res=duplicates[res];
+
+ current->set(E->get().name,res);
+ }
+
+ }
+ }
+
+ }
+ }
+
+ editor_data.get_undo_redo().clear_history();
+
+ _set_editing_top_editors(NULL);
+ _set_editing_top_editors(current);
+
+ } break;
+ case RUN_PLAY: {
+ _menu_option_confirm(RUN_STOP,true);
+ _call_build();
+ _run(false);
+
+ } break;
+ case RUN_PLAY_CUSTOM_SCENE: {
+ if (run_custom_filename.empty() || editor_run.get_status()==EditorRun::STATUS_STOP) {
+ _menu_option_confirm(RUN_STOP,true);
+ quick_run->popup("PackedScene",true);
+ quick_run->set_title(TTR("Quick Run Scene.."));
+ play_custom_scene_button->set_pressed(false);
+ } else {
+ String last_custom_scene=run_custom_filename;
+ _menu_option_confirm(RUN_STOP,true);
+ _run(false,last_custom_scene);
+ }
+
+ } break;
+ case RUN_STOP: {
+
+ if (editor_run.get_status()==EditorRun::STATUS_STOP)
+ break;
+
+ editor_run.stop();
+ run_custom_filename.clear();
+ play_button->set_pressed(false);
+ 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"));
+ play_custom_scene_button->set_pressed(false);
+ play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
+ //pause_button->set_pressed(false);
+ if (bool(EDITOR_DEF("run/output/always_close_output_on_stop", true))) {
+ for(int i=0;i<bottom_panel_items.size();i++) {
+ if (bottom_panel_items[i].control==log) {
+ _bottom_panel_switch(false,i);
+ break;
+ }
+ }
+ }
+ emit_signal("stop_pressed");
+
+ } break;
+ case RUN_PLAY_SCENE: {
+ _menu_option_confirm(RUN_STOP,true);
+ _call_build();
+ _run(true);
+
+ } break;
+ case RUN_PLAY_NATIVE: {
+
+ bool autosave = EDITOR_DEF("run/auto_save/save_before_running",true);
+ if (autosave) {
+ _menu_option_confirm(FILE_SAVE_ALL_SCENES, false);
+ }
+ if (run_native->is_deploy_debug_remote_enabled()){
+ _menu_option_confirm(RUN_STOP,true);
+ _call_build();
+ emit_signal("play_pressed");
+ editor_run.run_native_notify();
+ }
+ } break;
+ case RUN_SCENE_SETTINGS: {
+
+ run_settings_dialog->popup_run_settings();
+ } break;
+ case RUN_SETTINGS: {
+
+ project_settings->popup_project_settings();
+ } break;
+ case RUN_PROJECT_MANAGER: {
+
+ if (!p_confirmed) {
+ confirmation->get_ok()->set_text(TTR("Yes"));
+ confirmation->set_text(TTR("Open Project Manager? \n(Unsaved changes will be lost)"));
+ confirmation->popup_centered_minsize();
+ break;
+ }
+
+ _menu_option_confirm(RUN_STOP,true);
+ exiting=true;
+ get_tree()->quit();
+ String exec = OS::get_singleton()->get_executable_path();
+
+ List<String> args;
+ args.push_back("-path");
+ args.push_back(exec.get_base_dir());
+ args.push_back("-pm");
+
+ OS::ProcessID pid=0;
+ Error err = OS::get_singleton()->execute(exec,args,false,&pid);
+ ERR_FAIL_COND(err);
+ } break;
+ case RUN_FILE_SERVER: {
+
+ //file_server
+ bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER));
+
+ if (ischecked) {
+ file_server->stop();
+ run_native->set_deploy_dumb(false);
+ //debug_button->set_icon(gui_base->get_icon("FileServer","EditorIcons"));
+ //debug_button->get_popup()->set_item_text( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER),"Enable File Server");
+ } else {
+ file_server->start();
+ run_native->set_deploy_dumb(true);
+ //debug_button->set_icon(gui_base->get_icon("FileServerActive","EditorIcons"));
+ //debug_button->get_popup()->set_item_text( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER),"Disable File Server");
+ }
+
+ debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER),!ischecked);
+ EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_file_server", !ischecked);
+ } break;
+ case RUN_LIVE_DEBUG: {
+
+ bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_LIVE_DEBUG));
+
+ debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_LIVE_DEBUG),!ischecked);
+ ScriptEditor::get_singleton()->get_debugger()->set_live_debugging(!ischecked);
+ EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_live_debug", !ischecked);
+
+ } break;
+
+ /*case RUN_DEPLOY_DUMB_CLIENTS: {
+
+ bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS));
+ debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),!ischecked);
+ run_native->set_deploy_dumb(!ischecked);
+
+ } break;*/
+ case RUN_DEPLOY_REMOTE_DEBUG: {
+
+ bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG));
+ debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG),!ischecked);
+ run_native->set_deploy_debug_remote(!ischecked);
+ EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_deploy_remote_debug", !ischecked);
+
+ } break;
+ case RUN_DEBUG_COLLISONS: {
+
+ bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_COLLISONS));
+ debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_COLLISONS),!ischecked);
+ run_native->set_debug_collisions(!ischecked);
+ editor_run.set_debug_collisions(!ischecked);
+ EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_collisons", !ischecked);
+
+ } break;
+ case RUN_DEBUG_NAVIGATION: {
+
+ bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION));
+ debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION),!ischecked);
+ run_native->set_debug_navigation(!ischecked);
+ editor_run.set_debug_navigation(!ischecked);
+ EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_navigation", !ischecked);
+
+ } break;
+ case RUN_RELOAD_SCRIPTS: {
+
+
+ bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS));
+ debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS),!ischecked);
+
+ ScriptEditor::get_singleton()->set_live_auto_reload_running_scripts(!ischecked);
+ EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_reload_scripts", !ischecked);
+
+ } break;
+ case SETTINGS_UPDATE_ALWAYS: {
+
+ update_menu->get_popup()->set_item_checked(0,true);
+ update_menu->get_popup()->set_item_checked(1,false);
+ OS::get_singleton()->set_low_processor_usage_mode(false);
+ } break;
+ case SETTINGS_UPDATE_CHANGES: {
+
+ update_menu->get_popup()->set_item_checked(0,false);
+ update_menu->get_popup()->set_item_checked(1,true);
+ OS::get_singleton()->set_low_processor_usage_mode(true);
+ } break;
+ case SETTINGS_UPDATE_SPINNER_HIDE: {
+ update_menu->set_icon(gui_base->get_icon("Collapse","EditorIcons"));
+ update_menu->get_popup()->toggle_item_checked(3);
+ } break;
+ case SETTINGS_PREFERENCES: {
+
+ settings_config_dialog->popup_edit_settings();
+ } break;
+ case SETTINGS_OPTIMIZED_PRESETS: {
+
+ //optimized_presets->popup_centered_ratio();
+ } break;
+ case SETTINGS_LOAD_EXPORT_TEMPLATES: {
+
+
+ file_templates->popup_centered_ratio();
+
+ } break;
+ case SETTINGS_TOGGLE_FULLSCREN: {
+
+ OS::get_singleton()->set_window_fullscreen( !OS::get_singleton()->is_window_fullscreen() );
+
+
+ } break;
+ case SETTINGS_PICK_MAIN_SCENE: {
+
+
+ //print_tree();
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ //not for now?
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
+ file->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+
+ //file->set_current_path(current_path);
+ Node *scene = editor_data.get_edited_scene_root();
+ if (scene) {
+ file->set_current_path(scene->get_filename());
+ };
+ file->set_title(TTR("Pick a Main Scene"));
+ file->popup_centered_ratio();
+
+ } break;
+ case SETTINGS_ABOUT: {
+
+ about->popup_centered_minsize(Size2(500,130)*EDSCALE);
+ } break;
+ case SOURCES_REIMPORT: {
+
+ //reimport_dialog->popup_reimport();
+ } break;
+ case DEPENDENCY_LOAD_CHANGED_IMAGES: {
+
+
+
+ } break;
+ case DEPENDENCY_UPDATE_IMPORTED: {
+
+/*
+ bool editing_changed = _find_editing_changed_scene(get_edited_scene());
+
+ import_reload_fn="";
+
+ if (editing_changed) {
+ if (unsaved_cache && !bool(EDITOR_DEF("import/ask_save_before_reimport",false))) {
+ if (!p_confirmed) {
+
+
+ confirmation->get_ok()->set_text("Open");
+ //confirmation->get_cancel()->show();
+ confirmation->set_text("Current scene changed, save and re-import ?");
+ confirmation->popup_centered(Size2(300,70));
+ break;
+
+ }
+ }
+
+ Node *scene = get_edited_scene();
+
+ if (scene->get_filename()=="") {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("Can't import if edited scene was not saved."); //i dont think this code will ever run
+ accept->popup_centered(Size2(300,70));
+ break;
+
+ }
+
+
+ import_reload_fn = scene->get_filename();
+ _save_scene(import_reload_fn);
+ _cleanup_scene();
+
+
+ }
+
+*/
+
+
+ } break;
+
+ default: {
+
+ if (p_option>=OBJECT_METHOD_BASE) {
+
+ ERR_FAIL_COND(!current);
+
+ int idx=p_option-OBJECT_METHOD_BASE;
+
+ List<MethodInfo> methods;
+ current->get_method_list(&methods);
+
+ ERR_FAIL_INDEX( idx, methods.size() );
+ String name=methods[idx].name;
+
+ if (current)
+ current->call(name);
+ } else if (p_option>=IMPORT_PLUGIN_BASE) {
+
+
+ }
+ }
+ }
+}
+
+void EditorNode::_update_debug_options() {
+
+ bool check_deploy_remote = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_deploy_remote_debug", false);
+ bool check_file_server = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_file_server", false);
+ bool check_debug_collisons = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_collisons", false);
+ bool check_debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false);
+ bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", false);
+ bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", false);
+
+ if (check_deploy_remote) _menu_option_confirm(RUN_DEPLOY_REMOTE_DEBUG, true);
+ if (check_file_server) _menu_option_confirm(RUN_FILE_SERVER, true);
+ if (check_debug_collisons) _menu_option_confirm(RUN_DEBUG_COLLISONS, true);
+ if (check_debug_navigation) _menu_option_confirm(RUN_DEBUG_NAVIGATION, true);
+ if (check_live_debug) _menu_option_confirm(RUN_LIVE_DEBUG, true);
+ if (check_reload_scripts) _menu_option_confirm(RUN_RELOAD_SCRIPTS, true);
+
+}
+
+Control* EditorNode::get_viewport() {
+
+ return viewport;
+}
+
+
+
+void EditorNode::_editor_select(int p_which) {
+
+ static bool selecting=false;
+ if (selecting || changing_scene)
+ return;
+
+ selecting=true;
+
+
+ ERR_FAIL_INDEX(p_which,editor_table.size());
+
+ for(int i=0;i<main_editor_buttons.size();i++) {
+ main_editor_buttons[i]->set_pressed(i==p_which);
+ }
+
+ selecting=false;
+
+
+ EditorPlugin *new_editor = editor_table[p_which];
+ ERR_FAIL_COND(!new_editor);
+
+ if (editor_plugin_screen==new_editor)
+ return;
+
+ if (editor_plugin_screen) {
+ editor_plugin_screen->make_visible(false);
+ }
+
+ editor_plugin_screen=new_editor;
+ editor_plugin_screen->make_visible(true);
+ editor_plugin_screen->selected_notify();
+
+
+}
+
+void EditorNode::add_editor_plugin(EditorPlugin *p_editor) {
+
+
+ if (p_editor->has_main_screen()) {
+
+ ToolButton *tb = memnew( ToolButton );
+ tb->set_toggle_mode(true);
+ tb->connect("pressed",singleton,"_editor_select",varray(singleton->main_editor_buttons.size()));
+ tb->set_text(p_editor->get_name());
+ singleton->main_editor_buttons.push_back(tb);
+ singleton->main_editor_button_vb->add_child(tb);
+ singleton->editor_table.push_back(p_editor);
+
+ singleton->distraction_free->raise();
+ }
+ singleton->editor_data.add_editor_plugin( p_editor );
+ singleton->add_child(p_editor);
+}
+
+
+void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) {
+
+ if (p_editor->has_main_screen()) {
+
+ for(int i=0;i<singleton->main_editor_buttons.size();i++) {
+
+ if (p_editor->get_name()==singleton->main_editor_buttons[i]->get_text()) {
+
+ if (singleton->main_editor_buttons[i]->is_pressed()) {
+ singleton->_editor_select(EDITOR_SCRIPT);
+ }
+
+ memdelete( singleton->main_editor_buttons[i] );
+ singleton->main_editor_buttons.remove(i);
+
+ break;
+ }
+ }
+
+ //singleton->main_editor_tabs->add_tab(p_editor->get_name());
+ singleton->editor_table.erase(p_editor);
+ }
+ p_editor->make_visible(false);
+ p_editor->clear();
+ singleton->editor_plugins_over->get_plugins_list().erase(p_editor);
+ singleton->remove_child(p_editor);
+ singleton->editor_data.remove_editor_plugin( p_editor );
+
+}
+
+
+
+void EditorNode::_update_addon_config() {
+
+ if (_initializing_addons)
+ return;
+
+ Vector<String> enabled_addons;
+
+ for(Map<String,EditorPlugin*>::Element *E=plugin_addons.front();E;E=E->next()) {
+ enabled_addons.push_back(E->key());
+ }
+
+ if (enabled_addons.size()==0) {
+ GlobalConfig::get_singleton()->set("editor_plugins/enabled",Variant());
+ } else {
+ GlobalConfig::get_singleton()->set("editor_plugins/enabled",enabled_addons);
+ }
+
+ project_settings->queue_save();
+
+}
+
+void EditorNode::set_addon_plugin_enabled(const String& p_addon,bool p_enabled) {
+
+ ERR_FAIL_COND(p_enabled && plugin_addons.has(p_addon));
+ ERR_FAIL_COND(!p_enabled && !plugin_addons.has(p_addon));
+
+ if (!p_enabled) {
+
+ EditorPlugin *addon = plugin_addons[p_addon];
+ remove_editor_plugin(addon);
+ memdelete(addon); //bye
+ plugin_addons.erase(p_addon);
+ _update_addon_config();
+ return;
+ }
+
+
+ Ref<ConfigFile> cf;
+ cf.instance();
+ String addon_path = "res://addons/"+p_addon+"/plugin.cfg";
+ Error err = cf->load(addon_path);
+ if (err!=OK) {
+ show_warning("Unable to enable addon plugin at: '"+addon_path+"' parsing of config failed.");
+ return;
+ }
+
+ if (!cf->has_section_key("plugin","script")) {
+ show_warning("Unable to find script field for addon plugin at: 'res://addons/"+p_addon+"''.");
+ return;
+ }
+
+ String path = cf->get_value("plugin","script");
+ path="res://addons/"+p_addon+"/"+path;
+
+ Ref<Script> script = ResourceLoader::load(path);
+
+
+ if (script.is_null()) {
+ show_warning("Unable to load addon script from path: '"+path+"'.");
+ return;
+ }
+
+ //could check inheritance..
+ if (String(script->get_instance_base_type())!="EditorPlugin") {
+ show_warning("Unable to load addon script from path: '"+path+"' Base type is not EditorPlugin.");
+ return;
+ }
+
+ if (!script->is_tool()) {
+ show_warning("Unable to load addon script from path: '"+path+"' Script is does not support tool mode.");
+ return;
+ }
+
+ EditorPlugin *ep = memnew( EditorPlugin );
+ ep->set_script(script.get_ref_ptr());
+ plugin_addons[p_addon]=ep;
+ add_editor_plugin(ep);
+
+ _update_addon_config();
+
+
+}
+
+bool EditorNode::is_addon_plugin_enabled(const String& p_addon) const {
+
+ return plugin_addons.has(p_addon);
+}
+
+
+void EditorNode::_remove_edited_scene() {
+ int new_index = editor_data.get_edited_scene();
+ int old_index=new_index;
+
+ if (new_index>0) {
+ new_index=new_index-1;
+ } else if (editor_data.get_edited_scene_count()>1) {
+ new_index=1;
+ } else {
+ editor_data.add_edited_scene(-1);
+ new_index=1;
+ }
+
+
+
+ if (editor_data.get_scene_path(old_index)!=String()) {
+ ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(editor_data.get_scene_path(old_index));
+ }
+ _scene_tab_changed(new_index);
+ editor_data.remove_scene(old_index);
+ editor_data.get_undo_redo().clear_history();
+ _update_title();
+ _update_scene_tabs();
+
+ /*
+ if (editor_data.get_edited_scene_count()==1) {
+ //make new scene appear saved
+ set_current_version(editor_data.get_undo_redo().get_version());
+ unsaved_cache=false;
+ }
+ */
+}
+
+void EditorNode::_remove_scene(int index) {
+ //printf("Attempting to remove scene %d (current is %d)\n", index, editor_data.get_edited_scene());
+
+ if (editor_data.get_edited_scene() == index) {
+ //Scene to remove is current scene
+ _remove_edited_scene();
+ }
+ else {
+ // Scene to remove is not active scene
+ editor_data.remove_scene(index);
+ }
+}
+
+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());
+
+ }
+ get_editor_data().set_edited_scene_root(p_scene);
+
+ if (p_scene && p_scene->cast_to<Popup>())
+ p_scene->cast_to<Popup>()->show(); //show popups
+ scene_tree_dock->set_edited_scene(p_scene);
+ if (get_tree())
+ get_tree()->set_edited_scene_root(p_scene);
+
+ if (p_scene) {
+ if (p_scene->get_parent()!=scene_root)
+ scene_root->add_child(p_scene);
+
+ }
+}
+
+
+
+
+int EditorNode::_get_current_main_editor() {
+
+ for(int i=0;i<editor_table.size();i++) {
+ if (editor_table[i]==editor_plugin_screen)
+ return i;
+ }
+
+ return 0;
+}
+
+Dictionary EditorNode::_get_main_scene_state() {
+
+ Dictionary state;
+ state["main_tab"]=_get_current_main_editor();
+ state["scene_tree_offset"]=scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
+ state["property_edit_offset"]=get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
+ state["saved_version"]=saved_version;
+ state["node_filter"]=scene_tree_dock->get_filter();
+ //print_line(" getting main tab: "+itos(state["main_tab"]));
+ return state;
+}
+
+void EditorNode::_set_main_scene_state(Dictionary p_state,Node* p_for_scene) {
+
+ if (get_edited_scene()!=p_for_scene && p_for_scene!=NULL)
+ return; //not for this scene
+
+ //print_line("set current 7 ");
+ changing_scene=false;
+
+#if 0
+ if (p_state.has("main_tab")) {
+ int idx = p_state["main_tab"];
+
+
+ print_line("comes with tab: "+itos(idx));
+ int current=-1;
+ for(int i=0;i<editor_table.size();i++) {
+ if (editor_plugin_screen==editor_table[i]) {
+ current=i;
+ break;
+ }
+ }
+
+
+ if (idx<2 && current<2) {
+ //only set tab for 2D and 3D
+ _editor_select(idx);
+ //print_line(" setting main tab: "+itos(p_state["main_tab"]));
+ }
+ }
+#else
+
+ if (get_edited_scene()) {
+
+ int current=-1;
+ for(int i=0;i<editor_table.size();i++) {
+ if (editor_plugin_screen==editor_table[i]) {
+ current=i;
+ break;
+ }
+ }
+
+ if (current<2) {
+ //use heuristic instead
+
+ int n2d=0,n3d=0;
+ _find_node_types(get_edited_scene(),n2d,n3d);
+ if (n2d>n3d) {
+ _editor_select(EDITOR_2D);
+ } else if (n3d>n2d) {
+ _editor_select(EDITOR_3D);
+
+ }
+ }
+
+ }
+#endif
+
+
+ if (p_state.has("scene_tree_offset"))
+ scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_value(p_state["scene_tree_offset"]);
+ if (p_state.has("property_edit_offset"))
+ get_property_editor()->get_scene_tree()->get_vscroll_bar()->set_value(p_state["property_edit_offset"]);
+
+ if (p_state.has("node_filter"))
+ scene_tree_dock->set_filter(p_state["node_filter"]);
+ //print_line("set current 8 ");
+
+ //this should only happen at the very end
+
+ //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;
+
+}
+
+void EditorNode::set_current_version(uint64_t p_version) {
+
+ saved_version=p_version;
+ editor_data.set_edited_scene_version(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());
+
+ }
+
+ //print_line("set current 2 ");
+
+ editor_selection->clear();
+ editor_data.set_edited_scene(p_idx);
+
+ Node* new_scene = editor_data.get_edited_scene_root();
+
+ if (new_scene && new_scene->cast_to<Popup>())
+ new_scene->cast_to<Popup>()->show(); //show popups
+
+ //print_line("set current 3 ");
+
+ scene_tree_dock->set_edited_scene(new_scene);
+ if (get_tree())
+ get_tree()->set_edited_scene_root(new_scene);
+
+ if (new_scene) {
+ if (new_scene->get_parent()!=scene_root)
+ scene_root->add_child(new_scene);
+
+ }
+ //print_line("set current 4 ");
+
+
+ Dictionary state = editor_data.restore_edited_scene_state(editor_selection,&editor_history);
+ _edit_current();
+
+ /*if (!unsaved) {
+ saved_version=editor_data.get_undo_redo().get_version();
+ if (p_backwards)
+ saved_version--;
+ else
+ saved_version++;
+ print_line("was saved, updating version");
+ } else {
+ saved_version=state["saved_version"];
+ }*/
+ //_set_main_scene_state(state);
+
+ call_deferred("_set_main_scene_state",state,get_edited_scene()); //do after everything else is done setting up
+ //print_line("set current 6 ");
+
+
+}
+
+bool EditorNode::is_scene_open(const String& p_path) {
+
+ for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+ if (editor_data.get_scene_path(i)==p_path)
+ return true;
+ }
+
+ return false;
+}
+
+void EditorNode::fix_dependencies(const String& p_for_file) {
+ dependency_fixer->edit(p_for_file);
+}
+
+
+
+
+Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_clear_errors, bool p_force_open_imported) {
+
+ if (!is_inside_tree()) {
+ defer_load_scene = p_scene;
+ return OK;
+ }
+
+
+ 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 (!p_force_open_imported && FileAccess::exists(p_scene+".import")) {
+ open_imported->set_text(vformat(TTR("Scene '%s' was automatically imported, so it can't be modified.\nTo make changes to it, a new inherited scene can be created."),p_scene.get_file()));
+ open_imported->popup_centered_minsize();
+ new_inherited_button->grab_focus();
+ open_import_request=p_scene;
+ return OK;
+ }
+
+ }
+
+
+
+ if (p_clear_errors)
+ load_errors->clear();
+
+ String lpath = GlobalConfig::get_singleton()->localize_path(p_scene);
+
+ if (!lpath.begins_with("res://")) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(TTR("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path."));
+ accept->popup_centered_minsize();
+ opening_prev=false;
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ int prev = editor_data.get_edited_scene();
+ int idx = editor_data.add_edited_scene(-1);
+ //print_line("load scene callback");
+ //set_current_scene(idx);
+
+ if (!editor_data.get_edited_scene_root() && editor_data.get_edited_scene_count()==2) {
+ _remove_edited_scene();
+ } else {
+ _scene_tab_changed(idx);
+ }
+
+
+
+ //_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded.
+
+ dependency_errors.clear();
+
+ Ref<PackedScene> sdata = ResourceLoader::load(lpath,"",true);
+ if (!sdata.is_valid()) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(TTR("Error loading scene."));
+ accept->popup_centered_minsize();
+ opening_prev=false;
+
+ if (prev!=-1) {
+ set_current_scene(prev);
+ editor_data.remove_scene(idx);
+ }
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ if (!p_ignore_broken_deps && dependency_errors.has(lpath)) {
+
+ current_option=-1;
+ Vector<String> errors;
+ for(Set<String>::Element *E=dependency_errors[lpath].front();E;E=E->next()) {
+
+ errors.push_back(E->get());
+ }
+ dependency_error->show(lpath,errors);
+ opening_prev=false;
+
+ if (prev!=-1) {
+ set_current_scene(prev);
+ editor_data.remove_scene(idx);
+ }
+ return ERR_FILE_MISSING_DEPENDENCIES;
+ }
+
+ dependency_errors.erase(lpath); //at least not self path
+
+ for (Map<String,Set<String> >::Element *E=dependency_errors.front();E;E=E->next()) {
+
+ String txt=vformat(TTR("Scene '%s' has broken dependencies:"),E->key())+"\n";
+ for(Set<String>::Element *F=E->get().front();F;F=F->next()) {
+ txt+="\t"+F->get()+"\n";
+ }
+ add_io_error(txt);
+ }
+
+ 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(PackedScene::GEN_EDIT_STATE_MAIN);
+
+ if (!new_scene) {
+
+ sdata.unref();
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(TTR("Error loading scene."));
+ accept->popup_centered_minsize();
+ opening_prev=false;
+ if (prev!=-1) {
+ set_current_scene(prev);
+ editor_data.remove_scene(idx);
+ }
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ //guess not needed in the end?
+ //new_scene->clear_internal_tree_resource_paths(); //make sure no internal tree paths to internal resources exist
+
+ /*
+ Node *old_scene = edited_scene;
+ _hide_top_editors();
+ set_edited_scene(NULL);
+ editor_data.clear_editor_states();
+ if (old_scene) {
+ if (!opening_prev && old_scene->get_filename()!="") {
+ previous_scenes.push_back(old_scene->get_filename());
+ }
+ memdelete(old_scene);
+ }
+*/
+
+ if (p_set_inherited) {
+ Ref<SceneState> state = sdata->get_state();
+ state->set_path(lpath);
+ new_scene->set_scene_inherited_state(state);
+ new_scene->set_filename(String());
+ /*
+ if (new_scene->get_scene_instance_state().is_valid())
+ new_scene->get_scene_instance_state()->set_path(String());
+ */
+ }
+
+ new_scene->set_scene_instance_state(Ref<SceneState>());
+
+ set_edited_scene(new_scene);
+ _get_scene_metadata(p_scene);
+ /*
+ editor_data.set_edited_scene_root(new_scene);
+
+ scene_tree_dock->set_selected(new_scene, true);
+ property_editor->edit(new_scene);
+ editor_data.set_edited_scene_root(new_scene);
+*/
+
+ //editor_data.get_undo_redo().clear_history();
+ saved_version=editor_data.get_undo_redo().get_version();
+ _update_title();
+ _update_scene_tabs();
+ _add_to_recent_scenes(lpath);
+
+ prev_scene->set_disabled(previous_scenes.size()==0);
+ opening_prev=false;
+
+ ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
+
+ //top_pallete->set_current_tab(0); //always go to scene
+
+ push_item(new_scene);
+
+ return OK;
+}
+
+
+
+void EditorNode::open_request(const String& p_path) {
+
+ load_scene(p_path); // as it will be opened in separate tab
+ //external_file=p_path;
+ //_menu_option_confirm(FILE_EXTERNAL_OPEN_SCENE,false);
+}
+
+void EditorNode::request_instance_scene(const String &p_path) {
+
+ scene_tree_dock->instance(p_path);
+
+}
+
+void EditorNode::request_instance_scenes(const Vector<String>& p_files) {
+
+ scene_tree_dock->instance_scenes(p_files);
+}
+
+ImportDock *EditorNode::get_import_dock() {
+ return import_dock;
+}
+
+FileSystemDock *EditorNode::get_filesystem_dock() {
+
+ return filesystem_dock;
+}
+SceneTreeDock *EditorNode::get_scene_tree_dock() {
+
+ return scene_tree_dock;
+}
+
+void EditorNode::_instance_request(const Vector<String>& p_files) {
+
+ request_instance_scenes(p_files);
+}
+
+void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool 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) {
+
+ Spatial *s=sp->cast_to<Spatial>();
+ if (!s)
+ return;
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s,p_sub,p_key);
+}
+
+void EditorNode::update_keying() {
+
+ //print_line("KR: "+itos(p_enabled));
+
+ bool valid=false;
+
+ if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
+
+ if (editor_history.get_path_size()>=1) {
+
+ Object *obj = ObjectDB::get_instance(editor_history.get_path_object(0));
+ if (obj && obj->cast_to<Node>()) {
+
+ valid=true;
+ }
+ }
+
+ }
+
+ property_editor->set_keying(valid);
+
+ AnimationPlayerEditor::singleton->get_key_editor()->update_keying();
+}
+
+
+void EditorNode::_close_messages() {
+
+ //left_split->set_dragger_visible(false);
+ old_split_ofs = center_split->get_split_offset();
+ center_split->set_split_offset(0);
+ //scene_root_parent->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_END,0);
+}
+
+void EditorNode::_show_messages() {
+
+ //left_split->set_dragger_visible(true);
+ center_split->set_split_offset(old_split_ofs);
+ //scene_root_parent->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_END,log->get_margin(MARGIN_TOP));
+
+}
+
+#if 0
+void EditorNode::animation_panel_make_visible(bool p_visible) {
+
+ if (!p_visible) {
+ animation_panel->hide();
+ } else {
+ animation_panel->show();
+ }
+
+ int idx = settings_menu->get_popup()->get_item_index(SETTINGS_SHOW_ANIMATION);
+ settings_menu->get_popup()->set_item_checked(idx,p_visible);
+}
+
+
+void EditorNode::animation_editor_make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ animation_editor->show();
+ animation_vb->get_parent_control()->minimum_size_changed();
+ //pd_anim->show();
+ top_split->set_collapsed(false);
+
+ //scene_root_parent->set_margin(MARGIN_TOP,animation_editor->get_margin(MARGIN_BOTTOM));
+ } else {
+ //pd_anim->hide();
+ animation_editor->hide();
+ //scene_root_parent->set_margin(MARGIN_TOP,0);
+ if (!animation_vb->get_parent_control())
+ return;
+ animation_vb->get_parent_control()->minimum_size_changed();
+ top_split->set_collapsed(true);
+ }
+
+ animation_editor->set_keying(p_visible);
+
+}
+#endif
+void EditorNode::_add_to_recent_scenes(const String& p_scene) {
+
+ String base="_"+GlobalConfig::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
+ Vector<String> rc = EDITOR_DEF(base+"/_recent_scenes",Array());
+ String name = p_scene;
+ name=name.replace("res://","");
+ if (rc.find(name)!=-1)
+ rc.erase(name);
+ rc.insert(0,name);
+ if (rc.size()>10)
+ rc.resize(10);
+
+ EditorSettings::get_singleton()->set(base+"/_recent_scenes",rc);
+ EditorSettings::get_singleton()->save();
+ _update_recent_scenes();
+
+}
+
+void EditorNode::_open_recent_scene(int p_idx) {
+
+ String base="_"+GlobalConfig::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
+ Vector<String> rc = EDITOR_DEF(base+"/_recent_scenes",Array());
+
+ ERR_FAIL_INDEX(p_idx,rc.size());
+
+ String path = "res://"+rc[p_idx];
+
+
+ /*if (unsaved_cache) {
+ _recent_scene=rc[p_idx];
+ open_recent_confirmation->set_text("Discard current scene and open:\n'"+rc[p_idx]+"'");
+ open_recent_confirmation->get_label()->set_align(Label::ALIGN_CENTER);
+ open_recent_confirmation->popup_centered(Size2(400,100));
+ return;
+ }*/
+
+ load_scene(path);
+
+
+}
+
+void EditorNode::_save_optimized() {
+
+
+ //save_optimized_copy(optimized_save->get_optimized_scene(),optimized_save->get_preset());
+#if 0
+ String path = optimized_save->get_optimized_scene();
+
+ uint32_t flags=0;
+
+ String platform="all";
+ Ref<EditorOptimizedSaver> saver=editor_data.get_optimized_saver(optimized_save->get_preset());
+
+ if (saver->is_bundle_scenes_enabled())
+ flags|=SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES;
+ if (saver->is_bundle_resources_enabled())
+ flags|=SceneSaver::FLAG_BUNDLE_RESOURCES;
+ if (saver->is_remove_editor_data_enabled())
+ flags|=SceneSaver::FLAG_OMIT_EDITOR_PROPERTIES;
+ if (saver->is_big_endian_data_enabled())
+ flags|=SceneSaver::FLAG_SAVE_BIG_ENDIAN;
+
+ platform=saver->get_target_platform();
+
+ Error err = SceneSaver::save(path,get_edited_scene(),flags,saver);
+
+ if (err) {
+
+ //accept->"()->hide();
+ accept->get_ok()->set_text("I see..");
+ accept->set_text("Error saving optimized scene: "+path);
+ accept->popup_centered(Size2(300,70));
+ return;
+
+ }
+
+ project_settings->add_remapped_path(GlobalConfig::get_singleton()->localize_path(get_edited_scene()->get_filename()),GlobalConfig::get_singleton()->localize_path(path),platform);
+#endif
+}
+
+void EditorNode::_update_recent_scenes() {
+
+ String base="_"+GlobalConfig::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
+ Vector<String> rc = EDITOR_DEF(base+"/_recent_scenes",Array());
+ recent_scenes->clear();
+ for(int i=0;i<rc.size();i++) {
+
+ recent_scenes->add_item(rc[i],i);
+ }
+
+}
+
+void EditorNode::_quick_opened() {
+
+
+ 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() {
+
+ _call_build();
+ _run(false,quick_run->get_selected());
+}
+
+
+void EditorNode::notify_child_process_exited() {
+
+ _menu_option_confirm(RUN_STOP,false);
+ stop_button->set_pressed(false);
+ editor_run.stop();
+
+}
+
+
+bool EditorNode::_find_editing_changed_scene(Node *p_from) {
+/*
+ if (!p_from)
+ return false;
+
+ if (p_from->get_filename()!="") {
+
+ StringName fn = p_from->get_filename();
+ for(int i=0;i<import_monitor->get_changes().size();i++) {
+
+ if (fn==import_monitor->get_changes()[i])
+ return true;
+ }
+ }
+
+ for(int i=0;i<p_from->get_child_count();i++) {
+
+ if (_find_editing_changed_scene(p_from->get_child(i)))
+ return true;
+ }
+*/
+ return false;
+}
+
+
+
+
+void EditorNode::add_io_error(const String& p_error) {
+ //CharString err_ut = p_error.utf8();
+ //ERR_PRINT(!err_ut.get_data());
+ _load_error_notify(singleton,p_error);
+}
+
+void EditorNode::_load_error_notify(void* p_ud,const String& p_text) {
+
+
+ EditorNode*en=(EditorNode*)p_ud;
+ en->load_errors->add_image(en->gui_base->get_icon("Error","EditorIcons"));
+ en->load_errors->add_text(p_text+"\n");
+ en->load_error_dialog->popup_centered_ratio(0.5);
+
+}
+
+
+bool EditorNode::_find_scene_in_use(Node* p_node,const String& p_path) const {
+
+ if (p_node->get_filename()==p_path) {
+ return true;
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ if (_find_scene_in_use(p_node->get_child(i),p_path)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool EditorNode::is_scene_in_use(const String& p_path) {
+
+ Node *es = get_edited_scene();
+ if (es)
+ return _find_scene_in_use(es,p_path);
+ return false;
+
+}
+
+void EditorNode::register_editor_types() {
+
+ ClassDB::register_class<EditorPlugin>();
+// ClassDB::register_class<EditorImportPlugin>();
+// ClassDB::register_class<EditorExportPlugin>();
+// ClassDB::register_class<EditorScenePostImport>();
+ ClassDB::register_class<EditorScript>();
+ ClassDB::register_class<EditorSelection>();
+ ClassDB::register_class<EditorFileDialog>();
+ //ClassDB::register_type<EditorImportExport>();
+ ClassDB::register_class<EditorSettings>();
+ ClassDB::register_class<EditorSpatialGizmo>();
+ ClassDB::register_class<EditorResourcePreview>();
+ ClassDB::register_class<EditorResourcePreviewGenerator>();
+ ClassDB::register_class<EditorFileSystem>();
+ ClassDB::register_class<EditorFileSystemDirectory>();
+
+
+
+ //ClassDB::register_type<EditorImporter>();
+ //ClassDB::register_type<EditorPostImport>();
+}
+
+void EditorNode::unregister_editor_types() {
+
+ _init_callbacks.clear();
+}
+
+
+void EditorNode::stop_child_process() {
+
+ _menu_option_confirm(RUN_STOP,false);
+}
+
+
+
+
+
+void EditorNode::progress_add_task(const String& p_task,const String& p_label, int p_steps) {
+
+ 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,bool p_force_redraw) {
+
+ singleton->progress_dialog->task_step(p_task,p_state,p_step,p_force_redraw);
+
+}
+
+void EditorNode::progress_end_task(const String& p_task) {
+
+ singleton->progress_dialog->end_task(p_task);
+
+}
+
+
+void EditorNode::progress_add_task_bg(const String& p_task,const String& p_label, int p_steps) {
+
+ singleton->progress_hb->add_task(p_task,p_label,p_steps);
+}
+
+void EditorNode::progress_task_step_bg(const String& p_task, int p_step) {
+
+ singleton->progress_hb->task_step(p_task,p_step);
+
+}
+
+void EditorNode::progress_end_task_bg(const String& p_task) {
+
+ singleton->progress_hb->end_task(p_task);
+
+}
+
+
+
+Ref<Texture> EditorNode::_file_dialog_get_icon(const String& p_path) {
+
+
+ EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem_path(p_path.get_base_dir());
+ if (efsd) {
+
+ String file = p_path.get_file();
+ for(int i=0;i<efsd->get_file_count();i++) {
+ if (efsd->get_file(i)==file) {
+
+ String type = efsd->get_file_type(i);
+
+ if (singleton->icon_type_cache.has(type)) {
+ return singleton->icon_type_cache[type];
+ } else {
+ return singleton->icon_type_cache["Object"];
+ }
+
+ }
+ }
+ }
+
+ return singleton->icon_type_cache["Object"];
+}
+
+void EditorNode::_file_dialog_register(FileDialog *p_dialog) {
+
+ singleton->file_dialogs.insert(p_dialog);
+}
+
+void EditorNode::_file_dialog_unregister(FileDialog *p_dialog){
+
+ singleton->file_dialogs.erase(p_dialog);
+}
+
+void EditorNode::_editor_file_dialog_register(EditorFileDialog *p_dialog) {
+
+ singleton->editor_file_dialogs.insert(p_dialog);
+}
+
+void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog){
+
+ singleton->editor_file_dialogs.erase(p_dialog);
+}
+
+Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
+
+Error EditorNode::export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after) {
+
+ export_defer.platform=p_platform;
+ export_defer.path=p_path;
+ export_defer.debug=p_debug;
+ export_defer.password=p_password;
+
+ return OK;
+}
+
+void EditorNode::show_warning(const String& p_text, const String &p_title) {
+
+ warning->set_text(p_text);
+ warning->set_title(p_title);
+ warning->popup_centered_minsize();
+}
+
+void EditorNode::_dock_select_input(const InputEvent& p_input) {
+
+ if (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION) {
+
+ Vector2 point(p_input.mouse_motion.x,p_input.mouse_motion.y);
+
+ int nrect = -1;
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+ if (dock_select_rect[i].has_point(point)) {
+ nrect=i;
+ break;
+ }
+ }
+
+
+ if (nrect!=dock_select_rect_over) {
+ dock_select->update();
+ dock_select_rect_over=nrect;
+
+ }
+
+
+ if (nrect==-1)
+ return;
+
+ if (p_input.type==InputEvent::MOUSE_BUTTON && p_input.mouse_button.button_index==1 && p_input.mouse_button.pressed && dock_popup_selected!=nrect) {
+ Control *dock = dock_slot[dock_popup_selected]->get_current_tab_control();
+ if (dock) {
+ dock_slot[dock_popup_selected]->remove_child(dock);
+ }
+ if (dock_slot[dock_popup_selected]->get_tab_count()==0) {
+ dock_slot[dock_popup_selected]->hide();
+
+ } else {
+
+ dock_slot[dock_popup_selected]->set_current_tab(0);
+ }
+
+ dock_slot[nrect]->add_child(dock);
+ dock_popup_selected=nrect;
+ dock_slot[nrect]->set_current_tab(dock_slot[nrect]->get_tab_count()-1);
+ dock_slot[nrect]->show();
+ dock_select->update();
+
+ VSplitContainer*splits[DOCK_SLOT_MAX/2]={
+ left_l_vsplit,
+ left_r_vsplit,
+ right_l_vsplit,
+ right_r_vsplit,
+ };
+
+ for(int i=0;i<4;i++) {
+ bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count();
+ if (in_use)
+ splits[i]->show();
+ else
+ splits[i]->hide();
+ }
+
+ _save_docks();
+ }
+ }
+}
+
+void EditorNode::_dock_popup_exit() {
+
+ dock_select_rect_over=-1;
+ dock_select->update();
+}
+
+void EditorNode::_dock_pre_popup(int p_which) {
+
+
+ dock_popup_selected=p_which;
+}
+
+void EditorNode::_dock_move_left() {
+
+ if (dock_popup_selected<0 || dock_popup_selected>=DOCK_SLOT_MAX)
+ return;
+ Control *current = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab() );
+ Control *prev = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab()-1 );
+ if (!current || !prev)
+ return;
+ dock_slot[dock_popup_selected]->move_child(current,prev->get_index());
+ dock_slot[dock_popup_selected]->set_current_tab( dock_slot[dock_popup_selected]->get_current_tab()-1 );
+ dock_select->update();
+ _save_docks();
+
+
+}
+
+void EditorNode::_dock_move_right() {
+
+ Control *current = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab() );
+ Control *next = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab()+1 );
+ if (!current || !next)
+ return;
+ dock_slot[dock_popup_selected]->move_child(next,current->get_index());
+ dock_slot[dock_popup_selected]->set_current_tab( dock_slot[dock_popup_selected]->get_current_tab()+1 );
+ dock_select->update();
+ _save_docks();
+}
+
+void EditorNode::_dock_select_draw(){
+ Size2 s = dock_select->get_size();
+ s.y/=2.0;
+ s.x/=6.0;
+
+ Color used=Color(0.6,0.6,0.6,0.8);
+ Color used_selected=Color(0.8,0.8,0.8,0.8);
+ Color tab_selected=Color(1,1,1,1);
+ Color unused=used;
+ unused.a=0.4;
+ Color unusable=unused;
+ unusable.a=0.1;
+
+ Rect2 unr(s.x*2,0,s.x*2,s.y*2);
+ unr.pos+=Vector2(2,5);
+ unr.size-=Vector2(4,7);
+
+ dock_select->draw_rect(unr,unusable);
+
+ dock_tab_move_left->set_disabled(true);
+ dock_tab_move_right->set_disabled(true);
+
+ if (dock_popup_selected!=-1 && dock_slot[dock_popup_selected]->get_tab_count()) {
+
+ dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected]->get_current_tab()==0);
+ dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected]->get_current_tab()>=dock_slot[dock_popup_selected]->get_tab_count()-1);
+ }
+
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+
+ Vector2 ofs;
+
+ switch(i) {
+ case DOCK_SLOT_LEFT_UL: {
+
+ } break;
+ case DOCK_SLOT_LEFT_BL: {
+ ofs.y+=s.y;
+ } break;
+ case DOCK_SLOT_LEFT_UR: {
+ ofs.x+=s.x;
+ } break;
+ case DOCK_SLOT_LEFT_BR: {
+ ofs+=s;
+ } break;
+ case DOCK_SLOT_RIGHT_UL: {
+ ofs.x+=s.x*4;
+ } break;
+ case DOCK_SLOT_RIGHT_BL: {
+ ofs.x+=s.x*4;
+ ofs.y+=s.y;
+
+ } break;
+ case DOCK_SLOT_RIGHT_UR: {
+ ofs.x+=s.x*4;
+ ofs.x+=s.x;
+
+ } break;
+ case DOCK_SLOT_RIGHT_BR: {
+ ofs.x+=s.x*4;
+ ofs+=s;
+
+ } break;
+ }
+
+ Rect2 r(ofs,s);
+ dock_select_rect[i]=r;
+ r.pos+=Vector2(2,5);
+ r.size-=Vector2(4,7);
+
+
+ if (i==dock_select_rect_over) {
+ dock_select->draw_rect(r,used_selected);
+ } else if (dock_slot[i]->get_child_count()==0) {
+ dock_select->draw_rect(r,unused);
+ } else {
+
+ dock_select->draw_rect(r,used);
+ }
+
+ for(int j=0;j<MIN(3,dock_slot[i]->get_child_count());j++) {
+ int xofs = (r.size.width/3)*j;
+ Color c = used;
+ if (i==dock_popup_selected && (dock_slot[i]->get_current_tab()>3 || dock_slot[i]->get_current_tab()==j))
+ c=tab_selected;
+ dock_select->draw_rect(Rect2(2+ofs.x+xofs,ofs.y,r.size.width/3-1,3),c);
+ }
+
+ }
+}
+
+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++) {
+ String name = dock_slot[i]->get_tab_control(j)->get_name();
+ if (names!="")
+ names+=",";
+ names+=name;
+ }
+
+ if (names!="") {
+ p_layout->set_value(p_section,"dock_"+itos(i+1),names);
+ }
+ }
+
+ p_layout->set_value(p_section,"dock_filesystem_split",filesystem_dock->get_split_offset());
+
+ VSplitContainer*splits[DOCK_SLOT_MAX/2]={
+ left_l_vsplit,
+ left_r_vsplit,
+ right_l_vsplit,
+ right_r_vsplit,
+ };
+
+ for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
+
+ if (splits[i]->is_visible_in_tree()) {
+ p_layout->set_value(p_section,"dock_split_"+itos(i+1),splits[i]->get_split_offset());
+ }
+ }
+
+
+ HSplitContainer *h_splits[4]={
+ left_l_hsplit,
+ left_r_hsplit,
+ main_hsplit,
+ right_hsplit,
+ };
+
+ for(int i=0;i<4;i++) {
+
+ p_layout->set_value(p_section,"dock_hsplit_"+itos(i+1),h_splits[i]->get_split_offset());
+ }
+
+}
+
+void EditorNode::save_layout() {
+
+ dock_drag_timer->start();
+}
+
+void EditorNode::_dock_split_dragged(int ofs) {
+
+ dock_drag_timer->start();
+}
+
+void EditorNode::_load_docks() {
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
+ if (err!=OK) {
+ //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::_update_dock_slots_visibility() {
+
+ VSplitContainer*splits[DOCK_SLOT_MAX/2]={
+ left_l_vsplit,
+ left_r_vsplit,
+ right_l_vsplit,
+ right_r_vsplit,
+ };
+
+
+ HSplitContainer*h_splits[4]={
+ left_l_hsplit,
+ left_r_hsplit,
+ main_hsplit,
+ right_hsplit,
+ };
+
+ if (!docks_visible) {
+
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+ dock_slot[i]->hide();
+ }
+
+ for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
+ splits[i]->hide();
+ }
+
+ right_hsplit->hide();
+ bottom_panel->hide();
+ } else {
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+
+ if (dock_slot[i]->get_tab_count())
+ dock_slot[i]->show();
+ else
+ dock_slot[i]->hide();
+
+ }
+
+
+ for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
+ bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count();
+ if (in_use)
+ splits[i]->show();
+ else
+ splits[i]->hide();
+ }
+
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+
+ if (dock_slot[i]->is_visible() && dock_slot[i]->get_tab_count()) {
+ dock_slot[i]->set_current_tab(0);
+ }
+ }
+ bottom_panel->show();
+ right_hsplit->show();
+ }
+}
+
+void EditorNode::_update_top_menu_visibility() {
+
+ return; // I think removing top menu is too much
+ /*
+ if (distraction_free->is_pressed()) {
+ play_cc->hide();
+ menu_hb->hide();
+ scene_tabs->hide();
+ } else {
+ play_cc->show();
+ menu_hb->show();
+ scene_tabs->show();
+ }*/
+}
+
+void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String& p_section) {
+
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+
+ if (!p_layout->has_section_key(p_section,"dock_"+itos(i+1)))
+ continue;
+
+ Vector<String> names = String(p_layout->get_value(p_section,"dock_"+itos(i+1))).split(",");
+
+ for(int j=0;j<names.size();j++) {
+
+ String name=names[j];
+ //find it, in a horribly inefficient way
+ int atidx=-1;
+ Control *node=NULL;
+ for(int k=0;k<DOCK_SLOT_MAX;k++) {
+ if (!dock_slot[k]->has_node(name))
+ continue;
+ node=dock_slot[k]->get_node(name)->cast_to<Control>();
+ if (!node)
+ continue;
+ atidx=k;
+ break;
+ }
+ if (atidx==-1) //well, it's not anywhere
+ continue;
+
+ if (atidx==i) {
+ node->raise();
+ continue;
+ }
+
+
+ dock_slot[atidx]->remove_child(node);
+
+ if (dock_slot[atidx]->get_tab_count()==0) {
+ dock_slot[atidx]->hide();
+
+ }
+ dock_slot[i]->add_child(node);
+ dock_slot[i]->show();
+ }
+ }
+
+ int fs_split_ofs = 0;
+ if (p_layout->has_section_key(p_section,"dock_filesystem_split")) {
+ fs_split_ofs = p_layout->get_value(p_section,"dock_filesystem_split");
+ }
+ filesystem_dock->set_split_offset(fs_split_ofs);
+
+ VSplitContainer*splits[DOCK_SLOT_MAX/2]={
+ left_l_vsplit,
+ left_r_vsplit,
+ right_l_vsplit,
+ right_r_vsplit,
+ };
+
+ for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
+
+ if (!p_layout->has_section_key(p_section,"dock_split_"+itos(i+1)))
+ continue;
+
+ int ofs = p_layout->get_value(p_section,"dock_split_"+itos(i+1));
+ splits[i]->set_split_offset(ofs);
+ }
+
+ HSplitContainer*h_splits[4]={
+ left_l_hsplit,
+ left_r_hsplit,
+ main_hsplit,
+ right_hsplit,
+ };
+
+ for(int i=0;i<4;i++) {
+ if (!p_layout->has_section_key(p_section,"dock_hsplit_"+itos(i+1)))
+ continue;
+ int ofs = p_layout->get_value(p_section,"dock_hsplit_"+itos(i+1));
+ h_splits[i]->set_split_offset(ofs);
+ }
+
+ for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
+ bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count();
+ if (in_use)
+ splits[i]->show();
+ else
+ splits[i]->hide();
+ }
+
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+
+ if (dock_slot[i]->is_visible() && dock_slot[i]->get_tab_count()) {
+ dock_slot[i]->set_current_tab(0);
+ }
+ }
+}
+
+
+void EditorNode::_update_layouts_menu() {
+
+ editor_layouts->clear();
+ overridden_default_layout=-1;
+
+ editor_layouts->set_size(Vector2());
+ editor_layouts->add_shortcut(ED_SHORTCUT("layout/save",TTR("Save Layout")), SETTINGS_LAYOUT_SAVE);
+ editor_layouts->add_shortcut(ED_SHORTCUT("layout/delete",TTR("Delete Layout")), SETTINGS_LAYOUT_DELETE);
+ editor_layouts->add_separator();
+ editor_layouts->add_shortcut(ED_SHORTCUT("layout/default",TTR("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==TTR("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(TTR("Save Layout"));
+ layout_dialog->get_ok()->set_text(TTR("Save"));
+ layout_dialog->popup_centered();
+ } break;
+ case SETTINGS_LAYOUT_DELETE: {
+
+ current_option=p_id;
+ layout_dialog->set_title(TTR("Delete Layout"));
+ layout_dialog->get_ok()->set_text(TTR("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();
+ }
+ }
+
+}
+
+
+void EditorNode::_scene_tab_script_edited(int p_tab) {
+
+ Ref<Script> script = editor_data.get_scene_root_script(p_tab);
+ if (script.is_valid())
+ edit_resource(script);
+}
+
+void EditorNode::_scene_tab_closed(int p_tab) {
+ current_option = SCENE_TAB_CLOSE;
+ tab_closing = p_tab;
+
+ bool unsaved = (p_tab==editor_data.get_edited_scene()) ?
+ saved_version!=editor_data.get_undo_redo().get_version() :
+ editor_data.get_scene_version(p_tab)!=0;
+ if (unsaved) {
+ confirmation->get_ok()->set_text(TTR("Yes"));
+
+ //confirmation->get_cancel()->show();
+ confirmation->set_text(TTR("Close scene? (Unsaved changes will be lost)"));
+ confirmation->popup_centered_minsize();
+ }
+ else {
+ _remove_scene(p_tab);
+ _update_scene_tabs();
+ }
+
+}
+
+
+void EditorNode::_scene_tab_changed(int p_tab) {
+
+
+ //print_line("set current 1 ");
+ bool unsaved = (saved_version!=editor_data.get_undo_redo().get_version());
+ //print_line("version: "+itos(editor_data.get_undo_redo().get_version())+", saved "+itos(saved_version));
+
+ if (p_tab==editor_data.get_edited_scene())
+ return; //pointless
+
+ uint64_t next_scene_version = editor_data.get_scene_version(p_tab);
+
+
+
+ //print_line("scene tab changed???");
+ editor_data.get_undo_redo().create_action(TTR("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,"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,"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();
+
+}
+
+void EditorNode::_toggle_search_bar(bool p_pressed) {
+
+ property_editor->set_use_filter(p_pressed);
+
+ if (p_pressed) {
+
+ search_bar->show();
+ search_box->grab_focus();
+ search_box->select_all();
+ } else {
+
+ search_bar->hide();
+ }
+}
+
+void EditorNode::_clear_search_box() {
+
+ if (search_box->get_text()=="")
+ return;
+
+ search_box->clear();
+ 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;
+
+}
+
+bool EditorNode::are_bottom_panels_hidden() const {
+
+ for(int i=0;i<bottom_panel_items.size();i++) {
+ if (bottom_panel_items[i].button->is_pressed())
+ return false;
+ }
+
+ return true;
+}
+
+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::remove_bottom_panel_item(Control *p_item) {
+
+ for(int i=0;i<bottom_panel_items.size();i++) {
+
+ if (bottom_panel_items[i].control==p_item) {
+ if (p_item->is_visible_in_tree()) {
+ _bottom_panel_switch(false,0);
+ }
+ bottom_panel_vb->remove_child(bottom_panel_items[i].control);
+ bottom_panel_hb->remove_child(bottom_panel_items[i].button);
+ memdelete( bottom_panel_items[i].button );
+ bottom_panel_items.remove(i);
+ 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_visible(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_visible(false);
+ }
+ center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
+ center_split->set_collapsed(true);
+ }
+}
+
+void EditorNode::set_docks_visible(bool p_show) {
+ docks_visible = p_show;
+ _update_dock_slots_visibility();
+}
+
+bool EditorNode::get_docks_visible() const {
+ return docks_visible;
+}
+
+void EditorNode::_toggle_distraction_free_mode() {
+
+ set_distraction_free_mode( distraction_free->is_pressed() );
+}
+
+void EditorNode::set_distraction_free_mode(bool p_enter) {
+
+ distraction_free->set_pressed(p_enter);
+
+ if (p_enter) {
+ if (docks_visible) {
+ set_docks_visible(false);
+ }
+ } else {
+ set_docks_visible(true);
+ }
+ _update_top_menu_visibility();
+}
+
+bool EditorNode::get_distraction_free_mode() const {
+ return distraction_free->is_pressed();
+}
+
+void EditorNode::add_control_to_dock(DockSlot p_slot,Control* p_control) {
+ ERR_FAIL_INDEX(p_slot,DOCK_SLOT_MAX);
+ dock_slot[p_slot]->add_child(p_control);
+ _update_dock_slots_visibility();
+
+}
+
+void EditorNode::remove_control_from_dock(Control* p_control) {
+
+ Control *dock=NULL;
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+ if (p_control->get_parent()==dock_slot[i]) {
+ dock=dock_slot[i];
+ break;
+ }
+ }
+
+ ERR_EXPLAIN("Control was not in dock");
+ ERR_FAIL_COND(!dock);
+
+ dock->remove_child(p_control);
+ _update_dock_slots_visibility();
+}
+
+Variant EditorNode::drag_resource(const Ref<Resource>& p_res,Control* p_from) {
+
+
+ Control *drag_control = memnew( Control );
+ TextureRect *drag_preview = memnew( TextureRect );
+ Label* label=memnew( Label );
+
+ Ref<Texture> preview;
+
+ {
+ //todo make proper previews
+ Ref<ImageTexture> pic = gui_base->get_icon("FileBig","EditorIcons");
+ Image img = pic->get_data();
+ img.resize(48,48); //meh
+ Ref<ImageTexture> resized_pic = Ref<ImageTexture>( memnew( ImageTexture) );
+ resized_pic->create_from_image(img);
+ preview=resized_pic;
+ }
+
+ drag_preview->set_texture(preview);
+ drag_control->add_child(drag_preview);
+ if (p_res->get_path().is_resource_file()) {
+ label->set_text(p_res->get_path().get_file());
+ } else if (p_res->get_name()!="") {
+ label->set_text(p_res->get_name());
+ } else {
+ label->set_text(p_res->get_class());
+
+ }
+
+ drag_control->add_child(label);
+
+ p_from->set_drag_preview(drag_control); //wait until it enters scene
+
+ label->set_pos( Point2((preview->get_width()-label->get_minimum_size().width)/2,preview->get_height()) );
+
+ Dictionary drag_data;
+ drag_data["type"]="resource";
+ drag_data["resource"]=p_res;
+ drag_data["from"]=p_from;
+
+
+ return drag_data;
+
+}
+
+Variant EditorNode::drag_files(const Vector<String>& p_files, Control *p_from){
+
+ VBoxContainer *files = memnew( VBoxContainer );
+
+ int max_files=6;
+
+ for(int i=0;i<MIN(max_files,p_files.size());i++) {
+
+ Label* label=memnew( Label );
+ label->set_text(p_files[i].get_file());
+ files->add_child(label);
+ }
+
+ if (p_files.size()>max_files) {
+
+ Label* label=memnew( Label );
+ label->set_text(vformat(TTR("%d more file(s)"), p_files.size()-max_files));
+ files->add_child(label);
+
+ }
+ Dictionary drag_data;
+ drag_data["type"]="files";
+ drag_data["files"]=p_files;
+ drag_data["from"]=p_from;
+
+ p_from->set_drag_preview(files); //wait until it enters scene
+
+ return drag_data;
+
+}
+
+Variant EditorNode::drag_files_and_dirs(const Vector<String>& p_files, Control *p_from){
+
+ VBoxContainer *files = memnew( VBoxContainer );
+
+ int max_files=6;
+
+ for(int i=0;i<MIN(max_files,p_files.size());i++) {
+
+ Label* label=memnew( Label );
+ label->set_text(p_files[i].get_file());
+ files->add_child(label);
+ }
+
+ if (p_files.size()>max_files) {
+
+ Label* label=memnew( Label );
+ label->set_text(vformat(TTR("%d more file(s) or folder(s)"), p_files.size()-max_files));
+ files->add_child(label);
+
+ }
+ Dictionary drag_data;
+ drag_data["type"]="files_and_dirs";
+ drag_data["files"]=p_files;
+ drag_data["from"]=p_from;
+
+ p_from->set_drag_preview(files); //wait until it enters scene
+
+ return drag_data;
+
+}
+
+
+void EditorNode::_dropped_files(const Vector<String>& p_files,int p_screen) {
+
+ String cur_path = filesystem_dock->get_current_path();
+// for(int i=0;i<EditorImportExport::get_singleton()->get_import_plugin_count();i++) {
+// EditorImportExport::get_singleton()->get_import_plugin(i)->import_from_drop(p_files,cur_path);
+// }
+}
+void EditorNode::_file_access_close_error_notify(const String& p_str) {
+
+ add_io_error("Unable to write to file '"+p_str+"', file in use, locked or lacking permissions.");
+}
+
+
+void EditorNode::reload_scene(const String& p_path) {
+
+
+ //first of all, reload textures as they might have changed on disk
+
+ List<Ref<Resource> > cached;
+ ResourceCache::get_cached_resources(&cached);
+ List<Ref<Resource> > to_clear; //clear internal resources from previous scene from being used
+ for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) {
+
+ if (E->get()->get_path().begins_with(p_path+"::")) //subresources of existing scene
+ to_clear.push_back(E->get());
+
+ if (!E->get()->cast_to<Texture>())
+ continue;
+ if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path())
+ continue;
+ if (!FileAccess::exists(E->get()->get_path()))
+ continue;
+ uint64_t mt = FileAccess::get_modified_time(E->get()->get_path());
+ if (mt!=E->get()->get_last_modified_time()) {
+ E->get()->reload_from_file();
+ }
+ }
+
+ //so reload reloads everything, clear subresources of previous scene
+ while(to_clear.front()) {
+ to_clear.front()->get()->set_path("");
+ to_clear.pop_front();
+ }
+
+ int scene_idx=-1;
+ for(int i=0;i<editor_data.get_edited_scene_count();i++) {
+
+ if (editor_data.get_scene_path(i)==p_path) {
+ scene_idx=i;
+ break;
+ }
+ }
+
+ int current_tab = editor_data.get_edited_scene();
+
+
+ if (scene_idx==-1) {
+ if (get_edited_scene()) {
+ //scene is not open, so at it might be instanced, just refresh, set tab to itself and it will reload
+ set_current_scene(current_tab);
+ editor_data.get_undo_redo().clear_history();
+ }
+ return;
+ }
+
+
+ if (current_tab==scene_idx) {
+ editor_data.apply_changes_in_editors();
+ _set_scene_metadata(p_path);
+
+ }
+ //remove scene
+ _remove_scene(scene_idx);
+ //reload scene
+ load_scene(p_path);
+ //adjust index so tab is back a the previous position
+ editor_data.move_edited_scene_to_index(scene_idx);
+ get_undo_redo()->clear_history();
+ //recover the tab
+ scene_tabs->set_current_tab(current_tab);
+ _scene_tab_changed(current_tab);
+}
+
+int EditorNode::plugin_init_callback_count=0;
+
+void EditorNode::add_plugin_init_callback(EditorPluginInitializeCallback p_callback) {
+
+ ERR_FAIL_COND(plugin_init_callback_count==MAX_INIT_CALLBACKS);
+
+ plugin_init_callbacks[plugin_init_callback_count++]=p_callback;
+}
+
+EditorPluginInitializeCallback EditorNode::plugin_init_callbacks[EditorNode::MAX_INIT_CALLBACKS];
+
+
+int EditorNode::build_callback_count=0;
+
+void EditorNode::add_build_callback(EditorBuildCallback p_callback) {
+
+ ERR_FAIL_COND(build_callback_count==MAX_INIT_CALLBACKS);
+
+ build_callbacks[build_callback_count++]=p_callback;
+}
+
+EditorPluginInitializeCallback EditorNode::build_callbacks[EditorNode::MAX_BUILD_CALLBACKS];
+
+void EditorNode::_call_build() {
+
+ for(int i=0;i<build_callback_count;i++) {
+ build_callbacks[i]();
+ }
+}
+
+
+void EditorNode::_inherit_imported(const String& p_action) {
+
+ open_imported->hide();
+ load_scene(open_import_request,true,true);
+
+}
+
+void EditorNode::_open_imported() {
+
+ load_scene(open_import_request,true,false,true,true);
+}
+
+void EditorNode::_bind_methods() {
+
+
+ ClassDB::bind_method("_menu_option",&EditorNode::_menu_option);
+ ClassDB::bind_method("_menu_confirm_current",&EditorNode::_menu_confirm_current);
+ ClassDB::bind_method("_dialog_action",&EditorNode::_dialog_action);
+ ClassDB::bind_method("_resource_selected",&EditorNode::_resource_selected,DEFVAL(""));
+ ClassDB::bind_method("_property_editor_forward",&EditorNode::_property_editor_forward);
+ ClassDB::bind_method("_property_editor_back",&EditorNode::_property_editor_back);
+ ClassDB::bind_method("_editor_select",&EditorNode::_editor_select);
+ ClassDB::bind_method("_node_renamed",&EditorNode::_node_renamed);
+ ClassDB::bind_method("edit_node",&EditorNode::edit_node);
+ ClassDB::bind_method("_imported",&EditorNode::_imported);
+ ClassDB::bind_method("_unhandled_input",&EditorNode::_unhandled_input);
+
+ ClassDB::bind_method("_get_scene_metadata",&EditorNode::_get_scene_metadata);
+ ClassDB::bind_method("set_edited_scene",&EditorNode::set_edited_scene);
+ ClassDB::bind_method("open_request",&EditorNode::open_request);
+ ClassDB::bind_method("_instance_request",&EditorNode::_instance_request);
+ ClassDB::bind_method("update_keying",&EditorNode::update_keying);
+ ClassDB::bind_method("_property_keyed",&EditorNode::_property_keyed);
+ ClassDB::bind_method("_transform_keyed",&EditorNode::_transform_keyed);
+ ClassDB::bind_method("_close_messages",&EditorNode::_close_messages);
+ ClassDB::bind_method("_show_messages",&EditorNode::_show_messages);
+ ClassDB::bind_method("_vp_resized",&EditorNode::_vp_resized);
+ ClassDB::bind_method("_quick_opened",&EditorNode::_quick_opened);
+ ClassDB::bind_method("_quick_run",&EditorNode::_quick_run);
+
+ ClassDB::bind_method("_resource_created",&EditorNode::_resource_created);
+
+ ClassDB::bind_method("_import_action",&EditorNode::_import_action);
+ //ClassDB::bind_method("_import",&EditorNode::_import);
+ //ClassDB::bind_method("_import_conflicts_solved",&EditorNode::_import_conflicts_solved);
+ ClassDB::bind_method("_open_recent_scene",&EditorNode::_open_recent_scene);
+ //ClassDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm);
+
+ ClassDB::bind_method("_save_optimized",&EditorNode::_save_optimized);
+
+ ClassDB::bind_method("stop_child_process",&EditorNode::stop_child_process);
+
+ ClassDB::bind_method("_sources_changed",&EditorNode::_sources_changed);
+ ClassDB::bind_method("_fs_changed",&EditorNode::_fs_changed);
+ ClassDB::bind_method("_dock_select_draw",&EditorNode::_dock_select_draw);
+ ClassDB::bind_method("_dock_select_input",&EditorNode::_dock_select_input);
+ ClassDB::bind_method("_dock_pre_popup",&EditorNode::_dock_pre_popup);
+ ClassDB::bind_method("_dock_split_dragged",&EditorNode::_dock_split_dragged);
+ ClassDB::bind_method("_save_docks",&EditorNode::_save_docks);
+ ClassDB::bind_method("_dock_popup_exit",&EditorNode::_dock_popup_exit);
+ ClassDB::bind_method("_dock_move_left",&EditorNode::_dock_move_left);
+ ClassDB::bind_method("_dock_move_right",&EditorNode::_dock_move_right);
+
+ ClassDB::bind_method("_layout_menu_option",&EditorNode::_layout_menu_option);
+
+ ClassDB::bind_method("set_current_scene",&EditorNode::set_current_scene);
+ ClassDB::bind_method("set_current_version",&EditorNode::set_current_version);
+ ClassDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed);
+ ClassDB::bind_method("_scene_tab_closed",&EditorNode::_scene_tab_closed);
+ ClassDB::bind_method("_scene_tab_script_edited",&EditorNode::_scene_tab_script_edited);
+ ClassDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
+ ClassDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
+
+ ClassDB::bind_method("_prepare_history",&EditorNode::_prepare_history);
+ ClassDB::bind_method("_select_history",&EditorNode::_select_history);
+
+ ClassDB::bind_method("_toggle_search_bar",&EditorNode::_toggle_search_bar);
+ ClassDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box);
+ ClassDB::bind_method("_clear_undo_history",&EditorNode::_clear_undo_history);
+ ClassDB::bind_method("_dropped_files",&EditorNode::_dropped_files);
+ ClassDB::bind_method("_toggle_distraction_free_mode",&EditorNode::_toggle_distraction_free_mode);
+
+
+
+// ClassDB::bind_method(D_METHOD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
+ //ClassDB::bind_method(D_METHOD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin);
+ ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base);
+ ClassDB::bind_method(D_METHOD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch);
+
+ ClassDB::bind_method(D_METHOD("_open_imported"), &EditorNode::_open_imported);
+ ClassDB::bind_method(D_METHOD("_inherit_imported"), &EditorNode::_inherit_imported);
+
+ 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::POOL_STRING_ARRAY,"args")) );
+ ADD_SIGNAL( MethodInfo("resource_saved",PropertyInfo(Variant::OBJECT,"obj")) );
+
+
+
+}
+
+static Node* _resource_get_edited_scene() {
+
+ return EditorNode::get_singleton()->get_edited_scene();
+}
+
+EditorNode::EditorNode() {
+
+ Resource::_get_local_scene_func=_resource_get_edited_scene;
+
+ VisualServer::get_singleton()->textures_keep_original(true);
+
+ EditorHelp::generate_doc(); //before any editor classes are crated
+ SceneState::set_disable_placeholders(true);
+ editor_initialize_certificates(); //for asset sharing
+
+ InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
+
+ if (id) {
+
+ if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
+ //only if no touchscreen ui hint, set emulation
+ id->set_emulate_touch(false); //just disable just in case
+ }
+ id->set_custom_mouse_cursor(RES());
+ }
+
+
+ singleton=this;
+ exiting=false;
+ last_checked_version=0;
+ changing_scene=false;
+ _initializing_addons=false;
+ docks_visible = true;
+
+
+ FileAccess::set_backup_save(true);
+
+ TranslationServer::get_singleton()->set_enabled(false);
+ // load settings
+ if (!EditorSettings::get_singleton())
+ EditorSettings::create();
+
+ bool use_single_dock_column = false;
+ {
+ int dpi_mode = EditorSettings::get_singleton()->get("interface/hidpi_mode");
+ if (dpi_mode==0) {
+ editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 );
+
+ use_single_dock_column = OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x<1200;
+
+ } else if (dpi_mode==1) {
+ editor_set_scale(0.75);
+ } else if (dpi_mode==2) {
+ editor_set_scale(1.0);
+ } else if (dpi_mode==3) {
+ editor_set_scale(1.5);
+ } else if (dpi_mode==4) {
+ editor_set_scale(2.0);
+ }
+ }
+
+
+ ResourceLoader::set_abort_on_missing_resources(false);
+ FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
+ EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
+ EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EditorSettings::get_singleton()->get("filesystem/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);
+
+ ResourceLoader::set_timestamp_on_load(true);
+ ResourceSaver::set_timestamp_on_save(true);
+
+
+ { //register importers at the begining, so dialogs are created with the right extensions
+ Ref<ResourceImporterTexture> import_texture;
+ import_texture.instance();
+ ResourceFormatImporter::get_singleton()->add_importer(import_texture);
+
+ Ref<ResourceImporterCSVTranslation> import_csv_translation;
+ import_csv_translation.instance();
+ ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation);
+
+ Ref<ResourceImporterWAV> import_wav;
+ import_wav.instance();
+ ResourceFormatImporter::get_singleton()->add_importer(import_wav);
+
+
+ Ref<ResourceImporterOBJ> import_obj;
+ import_obj.instance();
+ ResourceFormatImporter::get_singleton()->add_importer(import_obj);
+
+ Ref<ResourceImporterScene> import_scene;
+ import_scene.instance();
+ ResourceFormatImporter::get_singleton()->add_importer(import_scene);
+
+ {
+ Ref<EditorSceneImporterCollada> import_collada;
+ import_collada.instance();
+ import_scene->add_importer(import_collada);
+ }
+
+ }
+
+ _pvrtc_register_compressors();
+
+ editor_selection = memnew( EditorSelection );
+
+ EditorFileSystem *efs = memnew( EditorFileSystem );
+ add_child(efs);
+
+ //used for previews
+ FileDialog::get_icon_func=_file_dialog_get_icon;
+ FileDialog::register_func=_file_dialog_register;
+ FileDialog::unregister_func=_file_dialog_unregister;
+
+ EditorFileDialog::get_icon_func=_file_dialog_get_icon;
+ EditorFileDialog::register_func=_editor_file_dialog_register;
+ EditorFileDialog::unregister_func=_editor_file_dialog_unregister;
+
+ editor_export = memnew( EditorExport );
+ add_child(editor_export);
+
+
+ register_exporters();
+
+ GLOBAL_DEF("editor/main_run_args","");
+
+ ClassDB::set_class_enabled("CollisionShape",true);
+ ClassDB::set_class_enabled("CollisionShape2D",true);
+ ClassDB::set_class_enabled("CollisionPolygon2D",true);
+
+ Control *theme_base = memnew( Control );
+ add_child(theme_base);
+ theme_base->set_area_as_parent_rect();
+
+ gui_base = memnew( Panel );
+ theme_base->add_child(gui_base);
+ gui_base->set_area_as_parent_rect();
+
+ Ref<Theme> theme = create_editor_theme();
+ theme_base->set_theme( theme );
+ gui_base->set_theme(create_custom_theme());
+
+ resource_preview = memnew( EditorResourcePreview );
+ add_child(resource_preview);
+ progress_dialog = memnew( ProgressDialog );
+ gui_base->add_child(progress_dialog);
+
+ // take up all screen
+ gui_base->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
+ gui_base->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END );
+ gui_base->set_end( Point2(0,0) );
+
+ main_vbox = memnew( VBoxContainer );
+ gui_base->add_child(main_vbox);
+ main_vbox->set_area_as_parent_rect(8);
+
+#if 0
+ PanelContainer *top_dark_panel = memnew( PanelContainer );
+ Ref<StyleBoxTexture> top_dark_sb;
+ top_dark_sb.instance();
+ top_dark_sb->set_texture(theme->get_icon("PanelTop","EditorIcons"));
+ for(int i=0;i<4;i++) {
+ top_dark_sb->set_margin_size(Margin(i),3);
+ top_dark_sb->set_default_margin(Margin(i),0);
+ }
+ top_dark_sb->set_expand_margin_size(MARGIN_LEFT,20);
+ top_dark_sb->set_expand_margin_size(MARGIN_RIGHT,20);
+
+ top_dark_panel->add_style_override("panel",top_dark_sb);
+ VBoxContainer *top_dark_vb = memnew( VBoxContainer );
+ main_vbox->add_child(top_dark_panel);
+ top_dark_panel->add_child(top_dark_vb);
+#endif
+
+
+
+ menu_hb = memnew( HBoxContainer );
+ main_vbox->add_child(menu_hb);
+
+ //top_dark_vb->add_child(scene_tabs);
+ //left
+ left_l_hsplit = memnew( HSplitContainer );
+ main_vbox->add_child(left_l_hsplit);
+
+ left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ left_l_vsplit = memnew( VSplitContainer );
+ left_l_hsplit->add_child(left_l_vsplit);
+ dock_slot[DOCK_SLOT_LEFT_UL]=memnew( TabContainer );
+ left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]);
+ dock_slot[DOCK_SLOT_LEFT_BL]=memnew( TabContainer );
+ left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]);
+ left_l_vsplit->hide();
+ dock_slot[DOCK_SLOT_LEFT_UL]->hide();
+ dock_slot[DOCK_SLOT_LEFT_BL]->hide();
+
+ left_r_hsplit = memnew( HSplitContainer );
+ left_l_hsplit->add_child(left_r_hsplit);
+ left_r_vsplit = memnew( VSplitContainer );
+ left_r_hsplit->add_child(left_r_vsplit);
+ dock_slot[DOCK_SLOT_LEFT_UR]=memnew( TabContainer );
+ left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UR]);
+ dock_slot[DOCK_SLOT_LEFT_BR]=memnew( TabContainer );
+ left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BR]);
+ //left_r_vsplit->hide();
+ //dock_slot[DOCK_SLOT_LEFT_UR]->hide();
+ //dock_slot[DOCK_SLOT_LEFT_BR]->hide();
+
+
+ main_hsplit = memnew( HSplitContainer );
+ left_r_hsplit->add_child(main_hsplit);
+ //main_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ VBoxContainer * center_vb = memnew( VBoxContainer);
+ main_hsplit->add_child(center_vb);
+ center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ center_split = memnew( VSplitContainer );
+ //main_hsplit->add_child(center_split);
+ center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ center_split->set_collapsed(false);
+ center_vb->add_child(center_split);
+
+ right_hsplit = memnew( HSplitContainer );
+ main_hsplit->add_child(right_hsplit);
+
+ right_l_vsplit = memnew( VSplitContainer );
+ right_hsplit->add_child(right_l_vsplit);
+ dock_slot[DOCK_SLOT_RIGHT_UL]=memnew( TabContainer );
+ right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UL]);
+ dock_slot[DOCK_SLOT_RIGHT_BL]=memnew( TabContainer );
+ right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BL]);
+ //right_l_vsplit->hide();
+ //dock_slot[DOCK_SLOT_RIGHT_UL]->hide();
+ //dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
+
+ right_r_vsplit = memnew( VSplitContainer );
+ right_hsplit->add_child(right_r_vsplit);
+ dock_slot[DOCK_SLOT_RIGHT_UR]=memnew( TabContainer );
+ right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]);
+ dock_slot[DOCK_SLOT_RIGHT_BR]=memnew( TabContainer );
+ right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]);
+ right_r_vsplit->hide();
+ dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
+ dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
+
+ left_l_vsplit->connect("dragged",this,"_dock_split_dragged");
+ left_r_vsplit->connect("dragged",this,"_dock_split_dragged");
+ right_l_vsplit->connect("dragged",this,"_dock_split_dragged");
+ right_r_vsplit->connect("dragged",this,"_dock_split_dragged");
+
+ left_l_hsplit->connect("dragged",this,"_dock_split_dragged");
+ left_r_hsplit->connect("dragged",this,"_dock_split_dragged");
+ main_hsplit->connect("dragged",this,"_dock_split_dragged");
+ right_hsplit->connect("dragged",this,"_dock_split_dragged");
+
+
+
+ dock_select_popoup = memnew( PopupPanel );
+ gui_base->add_child(dock_select_popoup);
+ VBoxContainer *dock_vb = memnew( VBoxContainer );
+ dock_select_popoup->add_child(dock_vb);
+
+ HBoxContainer *dock_hb = memnew( HBoxContainer);
+ dock_tab_move_left = memnew( ToolButton );
+ dock_tab_move_left->set_icon(theme->get_icon("Back","EditorIcons"));
+ dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
+ dock_tab_move_left->connect("pressed",this,"_dock_move_left");
+ //dock_tab_move_left->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ dock_hb->add_child(dock_tab_move_left);
+ dock_hb->add_spacer();
+ dock_tab_move_right = memnew( ToolButton );
+ dock_tab_move_right->set_icon(theme->get_icon("Forward","EditorIcons"));
+ dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
+ dock_tab_move_right->connect("pressed",this,"_dock_move_right");
+
+ //dock_tab_move_right->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ dock_hb->add_child(dock_tab_move_right);
+ dock_vb->add_child(dock_hb);
+
+ dock_select = memnew( Control );
+ dock_select->set_custom_minimum_size(Size2(128,64)*EDSCALE);
+ dock_select->connect("gui_input",this,"_dock_select_input");
+ dock_select->connect("draw",this,"_dock_select_draw");
+ dock_select->connect("mouse_exited",this,"_dock_popup_exit");
+ dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ dock_vb->add_child(dock_select);
+
+
+
+ dock_select_popoup->set_as_minsize();
+ dock_select_rect_over=-1;
+ dock_popup_selected=-1;
+ //dock_select_popoup->set_(Size2(20,20));
+
+ for(int i=0;i<DOCK_SLOT_MAX;i++) {
+ dock_slot[i]->set_custom_minimum_size(Size2(230,220)*EDSCALE);
+ dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ dock_slot[i]->set_popup(dock_select_popoup);
+ dock_slot[i]->connect("pre_popup_pressed",this,"_dock_pre_popup",varray(i));
+
+ //dock_slot[i]->set_tab_align(TabContainer::ALIGN_LEFT);
+ }
+
+ dock_drag_timer = memnew( Timer );
+ add_child(dock_drag_timer);
+ dock_drag_timer->set_wait_time(0.5);
+ dock_drag_timer->set_one_shot(true);
+ dock_drag_timer->connect("timeout",this,"_save_docks");
+
+ top_split = memnew( VSplitContainer );
+ center_split->add_child(top_split);
+ top_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ top_split->set_collapsed(true);
+
+ VBoxContainer *srt = memnew( VBoxContainer );
+ srt->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ top_split->add_child(srt);
+ srt->add_constant_override("separation",0);
+
+
+/* main_editor_tabs = memnew( Tabs );
+ main_editor_tabs->connect("tab_changed",this,"_editor_select");
+ main_editor_tabs->set_tab_close_display_policy(Tabs::SHOW_NEVER);
+*/
+ scene_tabs=memnew( Tabs );
+ scene_tabs->add_tab("unsaved");
+ scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
+ scene_tabs->set_tab_close_display_policy( (bool(EDITOR_DEF("interface/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : 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");
+
+ srt->add_child(scene_tabs);
+
+ scene_root_parent = memnew( PanelContainer );
+ scene_root_parent->set_custom_minimum_size(Size2(0,80)*EDSCALE);
+
+
+
+ //Ref<StyleBox> sp = scene_root_parent->get_stylebox("panel","TabContainer");
+ //scene_root_parent->add_style_override("panel",sp);
+
+
+ /*scene_root_parent->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
+ scene_root_parent->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END );
+ scene_root_parent->set_begin( Point2( 0, 0) );
+ scene_root_parent->set_end( Point2( 0,80 ) );*/
+ srt->add_child(scene_root_parent);
+ scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+
+ scene_root = memnew( Viewport );
+ scene_root->set_disable_3d(true);
+
+
+
+ //scene_root_base->add_child(scene_root);
+ //scene_root->set_meta("_editor_disable_input",true);
+ VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(),true);
+ scene_root->set_disable_input(true);
+ scene_root->set_as_audio_listener_2d(true);
+ //scene_root->set_size_override(true,Size2(GlobalConfig::get_singleton()->get("display/width"),GlobalConfig::get_singleton()->get("display/height")));
+
+ //scene_root->set_world_2d( Ref<World2D>( memnew( World2D )) );
+
+
+ viewport = memnew( VBoxContainer );
+ viewport->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ /*for(int i=0;i<4;i++) {
+ viewport->set_margin(Margin(i),sp->get_margin(Margin(i)));
+ }*/
+ scene_root_parent->add_child(viewport);
+
+
+
+ PanelContainer *top_region = memnew( PanelContainer );
+ top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
+ HBoxContainer *left_menu_hb = memnew( HBoxContainer );
+ top_region->add_child(left_menu_hb);
+ menu_hb->add_child(top_region);
+
+ PopupMenu *p;
+
+
+
+ file_menu = memnew( MenuButton );
+ file_menu->set_text(TTR("Scene"));
+ //file_menu->set_icon(gui_base->get_icon("Save","EditorIcons"));
+ left_menu_hb->add_child( file_menu );
+
+ prev_scene = memnew( ToolButton );
+ prev_scene->set_icon(gui_base->get_icon("PrevScene","EditorIcons"));
+ prev_scene->set_tooltip(TTR("Go to previously opened scene."));
+ prev_scene->set_disabled(true);
+ //left_menu_hb->add_child( prev_scene );
+ prev_scene->connect("pressed",this,"_menu_option",make_binds(FILE_OPEN_PREV));
+ gui_base->add_child(prev_scene);
+ prev_scene->set_pos(Point2(3,24));
+ prev_scene->hide();
+
+
+
+ ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD+KEY_TAB);
+ ED_SHORTCUT("editor/prev_tab", TTR("Previous tab"), KEY_MASK_CMD+KEY_MASK_SHIFT+KEY_TAB);
+ ED_SHORTCUT("editor/filter_files", TTR("Filter Files.."), KEY_MASK_ALT+KEY_MASK_CMD+KEY_P);
+
+
+ file_menu->set_tooltip(TTR("Operations with scene files."));
+ p=file_menu->get_popup();
+ p->add_shortcut(ED_SHORTCUT("editor/new_scene",TTR("New Scene")),FILE_NEW_SCENE);
+ p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene",TTR("New Inherited Scene..")),FILE_NEW_INHERITED_SCENE);
+ p->add_shortcut(ED_SHORTCUT("editor/open_scene",TTR("Open Scene.."),KEY_MASK_CMD+KEY_O),FILE_OPEN_SCENE);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("editor/save_scene",TTR("Save Scene"),KEY_MASK_CMD+KEY_S),FILE_SAVE_SCENE);
+ p->add_shortcut(ED_SHORTCUT("editor/save_scene_as",TTR("Save Scene As.."),KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S),FILE_SAVE_AS_SCENE);
+ p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes",TTR("Save all Scenes"),KEY_MASK_ALT+KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S),FILE_SAVE_ALL_SCENES);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("editor/close_scene",TTR("Close Scene"),KEY_MASK_SHIFT+KEY_MASK_CTRL+KEY_W),FILE_CLOSE);
+ p->add_separator();
+ //p->add_shortcut(ED_SHORTCUT("editor/save_scene",TTR("Close Goto Prev. Scene")),FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P);
+ p->add_submenu_item(TTR("Open Recent"),"RecentScenes",FILE_OPEN_RECENT);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene",TTR("Quick Open Scene.."),KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O),FILE_QUICK_OPEN_SCENE);
+ p->add_shortcut(ED_SHORTCUT("editor/quick_open_script",TTR("Quick Open Script.."),KEY_MASK_ALT+KEY_MASK_CMD+KEY_O),FILE_QUICK_OPEN_SCRIPT);
+ p->add_separator();
+
+ PopupMenu *pm_export = memnew(PopupMenu );
+ pm_export->set_name("Export");
+ p->add_child(pm_export);
+ p->add_submenu_item(TTR("Convert To.."),"Export");
+ pm_export->add_separator();
+ pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_MeshLibrary", TTR("MeshLibrary..")), FILE_EXPORT_MESH_LIBRARY);
+ pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_TileSet", TTR("TileSet..")), FILE_EXPORT_TILESET);
+ pm_export->connect("id_pressed",this,"_menu_option");
+
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"),KEY_MASK_CMD+KEY_Z),EDIT_UNDO,true);
+ p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"),KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_Z),EDIT_REDO,true);
+ p->add_separator();
+ p->add_item(TTR("Run Script"),FILE_RUN_SCRIPT,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_R);
+ p->add_separator();
+ p->add_item(TTR("Project Settings"),RUN_SETTINGS);
+ p->add_separator();
+ p->add_item(TTR("Revert Scene"),EDIT_REVERT);
+ p->add_separator();
+#ifdef OSX_ENABLED
+ p->add_item(TTR("Quit to Project List"),RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_Q);
+#else
+ p->add_item(TTR("Quit to Project List"),RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_CTRL+KEY_Q);
+#endif
+ p->add_item(TTR("Quit"),FILE_QUIT,KEY_MASK_CMD+KEY_Q);
+
+ recent_scenes = memnew( PopupMenu );
+ recent_scenes->set_name("RecentScenes");
+ p->add_child(recent_scenes);
+ recent_scenes->connect("id_pressed",this,"_open_recent_scene");
+
+ {
+ Control *sp = memnew( Control );
+ sp->set_custom_minimum_size(Size2(30,0)*EDSCALE);
+ menu_hb->add_child(sp);
+ }
+
+ PanelContainer *editor_region = memnew( PanelContainer );
+ editor_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
+ main_editor_button_vb = memnew( HBoxContainer );
+ editor_region->add_child(main_editor_button_vb);
+ menu_hb->add_child(editor_region);
+
+ distraction_free = memnew( ToolButton );
+ main_editor_button_vb->add_child(distraction_free);
+ distraction_free->set_shortcut( ED_SHORTCUT("editor/distraction_free_mode",TTR("Distraction Free Mode"),KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F11) );
+ distraction_free->connect("pressed",this,"_toggle_distraction_free_mode");
+ distraction_free->set_icon(gui_base->get_icon("DistractionFree","EditorIcons"));
+ distraction_free->set_toggle_mode(true);
+
+ //menu_hb->add_spacer();
+#if 0
+ node_menu = memnew( MenuButton );
+ node_menu->set_text("Node");
+ node_menu->set_pos( Point2( 50,0) );
+ menu_panel->add_child( node_menu );
+
+ p=node_menu->get_popup();
+ p->add_item("Create",NODE_CREATE);
+ p->add_item("Instance",NODE_INSTANCE);
+ p->add_separator();
+ p->add_item("Reparent",NODE_REPARENT);
+ p->add_item("Move Up",NODE_MOVE_UP);
+ p->add_item("Move Down",NODE_MOVE_DOWN);
+ p->add_separator();
+ p->add_item("Duplicate",NODE_DUPLICATE);
+ p->add_separator();
+ p->add_item("Remove (Branch)",NODE_REMOVE_BRANCH);
+ p->add_item("Remove (Element)",NODE_REMOVE_ELEMENT);
+ p->add_separator();
+ p->add_item("Edit Subscriptions..",NODE_CONNECTIONS);
+ p->add_item("Edit Groups..",NODE_GROUPS);
+
+ resource_menu = memnew( MenuButton );
+ resource_menu->set_text("Resource");
+ resource_menu->set_pos( Point2( 90,0) );
+ menu_panel->add_child( resource_menu );
+#endif
+
+ import_menu = memnew( MenuButton );
+ import_menu->set_tooltip(TTR("Import assets to the project."));
+ import_menu->set_text(TTR("Import"));
+ //import_menu->set_icon(gui_base->get_icon("Save","EditorIcons"));
+ left_menu_hb->add_child( import_menu );
+
+ p=import_menu->get_popup();
+ p->connect("id_pressed",this,"_menu_option");
+
+ tool_menu = memnew( MenuButton );
+ tool_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools."));
+ tool_menu->set_text(TTR("Tools"));
+
+ //tool_menu->set_icon(gui_base->get_icon("Save","EditorIcons"));
+ left_menu_hb->add_child( tool_menu );
+
+ p=tool_menu->get_popup();
+ p->connect("id_pressed",this,"_menu_option");
+ p->add_item(TTR("Orphan Resource Explorer"),TOOLS_ORPHAN_RESOURCES);
+
+ export_button = memnew( ToolButton );
+ export_button->set_tooltip(TTR("Export the project to many platforms."));
+ export_button->set_text(TTR("Export"));
+ export_button->connect("pressed",this,"_menu_option",varray(FILE_EXPORT_PROJECT));
+ export_button->set_focus_mode(Control::FOCUS_NONE);
+ left_menu_hb->add_child(export_button);
+
+ menu_hb->add_spacer();
+
+ //Separator *s1 = memnew( VSeparator );
+ //menu_panel->add_child(s1);
+ //s1->set_pos(Point2(210,4));
+ //s1->set_size(Point2(10,15));
+
+
+ play_cc = memnew( CenterContainer );
+ play_cc->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
+ gui_base->add_child( play_cc );
+ play_cc->set_area_as_parent_rect();
+ play_cc->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,10);
+ play_cc->set_margin(MARGIN_TOP,5);
+
+ top_region = memnew( PanelContainer );
+ top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
+ play_cc->add_child(top_region);
+
+ HBoxContainer *play_hb = memnew( HBoxContainer );
+ top_region->add_child(play_hb);
+
+ play_button = memnew( ToolButton );
+ play_hb->add_child(play_button);
+ play_button->set_toggle_mode(true);
+ play_button->set_icon(gui_base->get_icon("MainPlay","EditorIcons"));
+ play_button->set_focus_mode(Control::FOCUS_NONE);
+ play_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY));
+ play_button->set_tooltip(TTR("Play the project."));
+ play_button->set_shortcut(ED_SHORTCUT("editor/play",TTR("Play"),KEY_F5));
+
+
+
+ pause_button = memnew( ToolButton );
+ //menu_panel->add_child(pause_button); - not needed for now?
+ pause_button->set_toggle_mode(true);
+ pause_button->set_icon(gui_base->get_icon("Pause","EditorIcons"));
+ pause_button->set_focus_mode(Control::FOCUS_NONE);
+ //pause_button->connect("pressed", this,"_menu_option",make_binds(RUN_PAUSE));
+ pause_button->set_tooltip(TTR("Pause the scene"));
+ pause_button->set_disabled(true);
+ play_hb->add_child(pause_button);
+ pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene",TTR("Pause Scene"),KEY_F7));
+
+
+ stop_button = memnew( ToolButton );
+ play_hb->add_child(stop_button);
+ //stop_button->set_toggle_mode(true);
+ stop_button->set_focus_mode(Control::FOCUS_NONE);
+ stop_button->set_icon(gui_base->get_icon("MainStop","EditorIcons"));
+ stop_button->connect("pressed", this,"_menu_option",make_binds(RUN_STOP));
+ stop_button->set_tooltip(TTR("Stop the scene."));
+ stop_button->set_shortcut(ED_SHORTCUT("editor/stop",TTR("Stop"),KEY_F8));
+
+ run_native = memnew( EditorRunNative);
+ play_hb->add_child(run_native);
+ native_play_button = memnew( MenuButton );
+ native_play_button->set_text("NTV");
+ menu_hb->add_child(native_play_button);
+ native_play_button->hide();
+ native_play_button->get_popup()->connect("id_pressed",this,"_run_in_device");
+ run_native->connect("native_run",this,"_menu_option",varray(RUN_PLAY_NATIVE));
+
+ //VSeparator *s1 = memnew( VSeparator );
+ //play_hb->add_child(s1);
+
+ play_scene_button = memnew( ToolButton );
+ play_hb->add_child(play_scene_button);
+ play_scene_button->set_toggle_mode(true);
+ play_scene_button->set_focus_mode(Control::FOCUS_NONE);
+ play_scene_button->set_icon(gui_base->get_icon("PlayScene","EditorIcons"));
+ play_scene_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY_SCENE));
+ play_scene_button->set_tooltip(TTR("Play the edited scene."));
+ play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene",TTR("Play Scene"),KEY_F6));
+
+ play_custom_scene_button = memnew( ToolButton );
+ play_hb->add_child(play_custom_scene_button);
+ play_custom_scene_button->set_toggle_mode(true);
+ play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE);
+ play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
+ play_custom_scene_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY_CUSTOM_SCENE));
+ play_custom_scene_button->set_tooltip(TTR("Play custom scene"));
+ play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene",TTR("Play Custom Scene"),KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F5));
+
+ debug_button = memnew( MenuButton );
+ debug_button->set_flat(true);
+ play_hb->add_child(debug_button);
+ //debug_button->set_toggle_mode(true);
+ debug_button->set_focus_mode(Control::FOCUS_NONE);
+ debug_button->set_icon(gui_base->get_icon("Remote","EditorIcons"));
+ //debug_button->connect("pressed", this,"_menu_option",make_binds(RUN_LIVE_DEBUG));
+ debug_button->set_tooltip(TTR("Debug options"));
+
+ p=debug_button->get_popup();
+ p->set_hide_on_item_selection(false);
+ p->add_check_item(TTR("Deploy with Remote Debug"),RUN_DEPLOY_REMOTE_DEBUG);
+ p->set_item_tooltip(p->get_item_count()-1,TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged."));
+ p->add_check_item(TTR("Small Deploy with Network FS"),RUN_FILE_SERVER);
+ p->set_item_tooltip(p->get_item_count()-1,TTR("When this option is enabled, export or deploy will produce a minimal executable.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploy will use the USB cable for faster performance. This option speeds up testing for games with a large footprint."));
+ p->add_separator();
+ p->add_check_item(TTR("Visible Collision Shapes"),RUN_DEBUG_COLLISONS);
+ p->set_item_tooltip(p->get_item_count()-1,TTR("Collision shapes and raycast nodes (for 2D and 3D) will be visible on the running game if this option is turned on."));
+ p->add_check_item(TTR("Visible Navigation"),RUN_DEBUG_NAVIGATION);
+ p->set_item_tooltip(p->get_item_count()-1,TTR("Navigation meshes and polygons will be visible on the running game if this option is turned on."));
+ p->add_separator();
+ p->add_check_item(TTR("Sync Scene Changes"),RUN_LIVE_DEBUG);
+ p->set_item_tooltip(p->get_item_count()-1,TTR("When this option is turned on, any changes made to the scene in the editor will be replicated in the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
+ p->add_check_item(TTR("Sync Script Changes"),RUN_RELOAD_SCRIPTS);
+ p->set_item_tooltip(p->get_item_count()-1,TTR("When this option is turned on, any script that is saved will be reloaded on the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
+ p->connect("id_pressed",this,"_menu_option");
+
+ /*
+ run_settings_button = memnew( ToolButton );
+ //menu_hb->add_child(run_settings_button);
+ //run_settings_button->set_toggle_mode(true);
+ run_settings_button->set_focus_mode(Control::FOCUS_NONE);
+ run_settings_button->set_icon(gui_base->get_icon("Run","EditorIcons"));
+ run_settings_button->connect("pressed", this,"_menu_option",make_binds(RUN_SCENE_SETTINGS));
+*/
+
+ /*
+ run_settings_button = memnew( ToolButton );
+ menu_panel->add_child(run_settings_button);
+ run_settings_button->set_pos(Point2(305,0));
+ run_settings_button->set_focus_mode(Control::FOCUS_NONE);
+ run_settings_button->set_icon(gui_base->get_icon("Run","EditorIcons"));
+ run_settings_button->connect("pressed", this,"_menu_option",make_binds(RUN_SETTINGS));
+*/
+
+
+ progress_hb = memnew( BackgroundProgress );
+ menu_hb->add_child(progress_hb);
+
+ {
+ Control *sp = memnew( Control );
+ sp->set_custom_minimum_size(Size2(30,0)*EDSCALE);
+ menu_hb->add_child(sp);
+ }
+
+
+ PanelContainer *vu_cont = memnew( PanelContainer );
+ vu_cont->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
+ menu_hb->add_child(vu_cont);
+
+ audio_vu = memnew( TextureProgress );
+ CenterContainer *vu_cc = memnew( CenterContainer );
+ vu_cc->add_child(audio_vu);
+ vu_cont->add_child(vu_cc);
+ audio_vu->set_under_texture(gui_base->get_icon("VuEmpty","EditorIcons"));
+ audio_vu->set_progress_texture(gui_base->get_icon("VuFull","EditorIcons"));
+ audio_vu->set_max(24);
+ audio_vu->set_min(-80);
+ audio_vu->set_step(0.01);
+ audio_vu->set_value(0);
+
+ {
+ Control *sp = memnew( Control );
+ sp->set_custom_minimum_size(Size2(30,0)*EDSCALE);
+ menu_hb->add_child(sp);
+ }
+
+
+
+ top_region = memnew( PanelContainer );
+ top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
+ HBoxContainer *right_menu_hb = memnew( HBoxContainer );
+ top_region->add_child(right_menu_hb);
+ menu_hb->add_child(top_region);
+
+
+ settings_menu = memnew( MenuButton );
+ settings_menu->set_text(TTR("Settings"));
+ //settings_menu->set_anchor(MARGIN_RIGHT,ANCHOR_END);
+ right_menu_hb->add_child( settings_menu );
+ p=settings_menu->get_popup();
+
+ //p->add_item("Export Settings",SETTINGS_EXPORT_PREFERENCES);
+ p->add_item(TTR("Editor Settings"),SETTINGS_PREFERENCES);
+ //p->add_item("Optimization Presets",SETTINGS_OPTIMIZED_PRESETS);
+ p->add_separator();
+ editor_layouts = memnew( PopupMenu );
+ editor_layouts->set_name("Layouts");
+ p->add_child(editor_layouts);
+ editor_layouts->connect("id_pressed",this,"_layout_menu_option");
+ p->add_submenu_item(TTR("Editor Layout"), "Layouts");
+
+ p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode",TTR("Toggle Fullscreen"),KEY_MASK_SHIFT|KEY_F11),SETTINGS_TOGGLE_FULLSCREN);
+
+ p->add_separator();
+ p->add_item(TTR("Install Export Templates"),SETTINGS_LOAD_EXPORT_TEMPLATES);
+ p->add_separator();
+ p->add_item(TTR("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)*EDSCALE);
+ layout_dialog->connect("name_confirmed", this,"_dialog_action");
+
+ sources_button = memnew( ToolButton );
+ right_menu_hb->add_child(sources_button);
+ sources_button->set_icon(gui_base->get_icon("DependencyOk","EditorIcons"));
+ sources_button->connect("pressed",this,"_menu_option",varray(SOURCES_REIMPORT));
+ sources_button->set_tooltip(TTR("Alerts when an external resource has changed."));
+
+ update_menu = memnew( MenuButton );
+ update_menu->set_tooltip(TTR("Spins when the editor window repaints!"));
+ right_menu_hb->add_child(update_menu);
+ update_menu->set_icon(gui_base->get_icon("Progress1","EditorIcons"));
+ p=update_menu->get_popup();
+ p->add_check_item(TTR("Update Always"),SETTINGS_UPDATE_ALWAYS);
+ p->add_check_item(TTR("Update Changes"),SETTINGS_UPDATE_CHANGES);
+ p->add_separator();
+ p->add_check_item(TTR("Disable Update Spinner"),SETTINGS_UPDATE_SPINNER_HIDE);
+ p->set_item_checked(1,true);
+
+ //sources_button->connect();
+
+/*
+ Separator *s2 = memnew( VSeparator );
+ menu_panel->add_child(s2);
+ s2->set_pos(Point2(338,4));
+ s2->set_size(Point2(10,15));
+*/
+
+
+
+ //editor_hsplit = memnew( HSplitContainer );
+ //main_split->add_child(editor_hsplit);
+ //editor_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ //editor_vsplit = memnew( VSplitContainer );
+ //editor_hsplit->add_child(editor_vsplit);
+
+ //top_pallete = memnew( TabContainer );
+ scene_tree_dock = memnew( SceneTreeDock(this,scene_root,editor_selection,editor_data) );
+ scene_tree_dock->set_name(TTR("Scene"));
+ //top_pallete->add_child(scene_tree_dock);
+ dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(scene_tree_dock);
+#if 0
+ resources_dock = memnew( ResourcesDock(this) );
+ resources_dock->set_name("Resources");
+ //top_pallete->add_child(resources_dock);
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(resources_dock);
+ //top_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+#endif
+ dock_slot[DOCK_SLOT_LEFT_BR]->hide();
+ /*Control *editor_spacer = memnew( Control );
+ editor_spacer->set_custom_minimum_size(Size2(260,200));
+ editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ editor_vsplit->add_child( editor_spacer );
+ editor_spacer->add_child( top_pallete );
+ top_pallete->set_area_as_parent_rect();*/
+
+
+ //prop_pallete = memnew( TabContainer );
+
+ //prop_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ /*editor_spacer = memnew( Control );
+ editor_spacer->set_custom_minimum_size(Size2(260,200));
+ editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ editor_vsplit->add_child( editor_spacer );
+ editor_spacer->add_child( prop_pallete );
+ prop_pallete->set_area_as_parent_rect();*/
+
+ VBoxContainer *prop_editor_base = memnew( VBoxContainer );
+ prop_editor_base->set_name(TTR("Inspector")); // Properties?
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(prop_editor_base);
+
+ HBoxContainer *prop_editor_hb = memnew( HBoxContainer );
+
+ prop_editor_base->add_child(prop_editor_hb);
+ prop_editor_vb=prop_editor_base;
+
+ resource_new_button = memnew( ToolButton );
+ resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it."));
+ resource_new_button->set_icon(gui_base->get_icon("New","EditorIcons"));
+ prop_editor_hb->add_child(resource_new_button);
+ resource_new_button->connect("pressed",this,"_menu_option",varray(RESOURCE_NEW));
+ resource_new_button->set_focus_mode(Control::FOCUS_NONE);
+
+ resource_load_button = memnew( ToolButton );
+ resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it."));
+ resource_load_button->set_icon(gui_base->get_icon("Load","EditorIcons"));
+ prop_editor_hb->add_child(resource_load_button);
+ resource_load_button->connect("pressed",this,"_menu_option",varray(RESOURCE_LOAD));
+ resource_load_button->set_focus_mode(Control::FOCUS_NONE);
+
+ resource_save_button = memnew( MenuButton );
+ resource_save_button->set_tooltip(TTR("Save the currently edited resource."));
+ resource_save_button->set_icon(gui_base->get_icon("Save","EditorIcons"));
+ prop_editor_hb->add_child(resource_save_button);
+ resource_save_button->get_popup()->add_item(TTR("Save"),RESOURCE_SAVE);
+ resource_save_button->get_popup()->add_item(TTR("Save As.."),RESOURCE_SAVE_AS);
+ resource_save_button->get_popup()->connect("id_pressed",this,"_menu_option");
+ resource_save_button->set_focus_mode(Control::FOCUS_NONE);
+ resource_save_button->set_disabled(true);
+
+ prop_editor_hb->add_spacer();
+
+ property_back = memnew( ToolButton );
+ property_back->set_icon( gui_base->get_icon("Back","EditorIcons") );
+ property_back->set_flat(true);
+ property_back->set_tooltip(TTR("Go to the previous edited object in history."));
+ property_back->set_disabled(true);
+
+ prop_editor_hb->add_child( property_back );
+
+ property_forward = memnew( ToolButton );
+ property_forward->set_icon( gui_base->get_icon("Forward","EditorIcons") );
+ property_forward->set_flat(true);
+ property_forward->set_tooltip(TTR("Go to the next edited object in history."));
+ property_forward->set_disabled(true);
+
+ prop_editor_hb->add_child( property_forward );
+
+
+ editor_history_menu = memnew( MenuButton );
+ editor_history_menu->set_tooltip(TTR("History of recently edited objects."));
+ editor_history_menu->set_icon( gui_base->get_icon("History","EditorIcons"));
+ prop_editor_hb->add_child(editor_history_menu);
+ editor_history_menu->connect("about_to_show",this,"_prepare_history");
+ editor_history_menu->get_popup()->connect("id_pressed",this,"_select_history");
+
+
+ prop_editor_hb = memnew( HBoxContainer ); //again...
+
+ prop_editor_base->add_child(prop_editor_hb);
+ editor_path = memnew( EditorPath(&editor_history) );
+ editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ prop_editor_hb->add_child(editor_path);
+
+ search_button = memnew( ToolButton );
+ search_button->set_toggle_mode(true);
+ search_button->set_pressed(false);
+ search_button->set_icon(gui_base->get_icon("Zoom","EditorIcons"));
+ prop_editor_hb->add_child(search_button);
+ search_button->connect("toggled",this,"_toggle_search_bar");
+
+ object_menu = memnew( MenuButton );
+ object_menu->set_icon(gui_base->get_icon("Tools","EditorIcons"));
+ prop_editor_hb->add_child( object_menu );
+ object_menu->set_tooltip(TTR("Object properties."));
+
+ create_dialog = memnew( CreateDialog );
+ gui_base->add_child(create_dialog);
+ create_dialog->set_base_type("Resource");
+ create_dialog->connect("create",this,"_resource_created");
+
+ search_bar = memnew( HBoxContainer );
+ search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ prop_editor_base->add_child(search_bar);
+ search_bar->hide();
+
+ Label *l = memnew( Label(TTR("Search:")+" ") );
+ search_bar->add_child(l);
+
+ search_box = memnew( LineEdit );
+ search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ search_bar->add_child(search_box);
+
+ ToolButton *clear_button = memnew( ToolButton );
+ clear_button->set_icon(gui_base->get_icon("Close","EditorIcons"));
+ search_bar->add_child(clear_button);
+ clear_button->connect("pressed",this,"_clear_search_box");
+
+ property_editor = memnew( PropertyEditor );
+ property_editor->set_autoclear(true);
+ property_editor->set_show_categories(true);
+ property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ property_editor->set_use_doc_hints(true);
+
+ property_editor->hide_top_label();
+ property_editor->register_text_enter(search_box);
+
+ prop_editor_base->add_child( property_editor );
+ property_editor->set_undo_redo(&editor_data.get_undo_redo());
+
+
+ import_dock = memnew( ImportDock );
+ dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock);
+ import_dock->set_name(TTR("Import"));
+
+
+ node_dock = memnew( NodeDock );
+ //node_dock->set_undoredo(&editor_data.get_undo_redo());
+ if (use_single_dock_column) {
+ dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
+ } else {
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock);
+ }
+
+ filesystem_dock = memnew( FileSystemDock(this) );
+ filesystem_dock->set_name(TTR("FileSystem"));
+ filesystem_dock->set_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")));
+
+ if (use_single_dock_column) {
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock);
+ left_r_vsplit->hide();
+ dock_slot[DOCK_SLOT_LEFT_UR]->hide();
+ dock_slot[DOCK_SLOT_LEFT_BR]->hide();
+ } else {
+ dock_slot[DOCK_SLOT_LEFT_UR]->add_child(filesystem_dock);
+ }
+ //prop_pallete->add_child(filesystem_dock);
+ filesystem_dock->connect("open",this,"open_request");
+ filesystem_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", TTR("FileSystem"));
+ default_layout->set_value(docks_section, "dock_5", TTR("Scene"));
+ default_layout->set_value(docks_section, "dock_6", TTR("Inspector")+","+TTR("Node"));
+
+ 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();
+
+ 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);
+
+ bottom_panel_hb = memnew( HBoxContainer );
+ bottom_panel_vb->add_child(bottom_panel_hb);
+
+
+
+ log = memnew( EditorLog );
+
+ add_bottom_panel_item(TTR("Output"),log);
+
+ //left_split->set_dragger_visible(false);
+
+
+ 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);
+
+
+ //progress_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+
+
+ /*
+ animation_menu = memnew( ToolButton );
+ animation_menu->set_pos(Point2(500,0));
+ animation_menu->set_size(Size2(20,20));
+ animation_menu->set_toggle_mode(true);
+ animation_menu->set_focus_mode(Control::FOCUS_NONE);
+ menu_panel->add_child(animation_menu);
+ animation_menu->set_icon(gui_base->get_icon("Animation","EditorIcons"));
+ animation_menu->connect("pressed",this,"_animation_visibility_toggle");
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+ orphan_resources = memnew( OrphanResourcesDialog );
+ gui_base->add_child(orphan_resources);
+
+
+
+
+
+ confirmation = memnew( ConfirmationDialog );
+ gui_base->add_child(confirmation);
+ confirmation->connect("confirmed", this,"_menu_confirm_current");
+
+ accept = memnew( AcceptDialog );
+ gui_base->add_child(accept);
+ accept->connect("confirmed", this,"_menu_confirm_current");
+
+
+
+
+
+ //optimized_save = memnew( OptimizedSaveDialog(&editor_data) );
+ //gui_base->add_child(optimized_save);
+ //optimized_save->connect("confirmed",this,"_save_optimized");
+
+ project_export = memnew( ProjectExportDialog );
+ gui_base->add_child(project_export);
+
+ //project_export_settings = memnew( ProjectExportDialog(this) );
+ //gui_base->add_child(project_export_settings);
+
+ //optimized_presets = memnew( OptimizedPresetsDialog(&editor_data) );
+ //gui_base->add_child(optimized_presets);
+ //optimized_presets->connect("confirmed",this,"_presets_optimized");
+
+
+
+ //import_subscene = memnew( EditorSubScene );
+ //gui_base->add_child(import_subscene);
+
+
+
+ dependency_error = memnew( DependencyErrorDialog );
+ gui_base->add_child(dependency_error);
+
+ dependency_fixer = memnew( DependencyEditor );
+ gui_base->add_child( dependency_fixer );
+
+ settings_config_dialog = memnew( EditorSettingsDialog );
+ gui_base->add_child(settings_config_dialog);
+
+ project_settings = memnew( ProjectSettings(&editor_data) );
+ gui_base->add_child(project_settings);
+
+ import_confirmation = memnew( ConfirmationDialog );
+ import_confirmation->get_ok()->set_text(TTR("Re-Import"));
+ import_confirmation->add_button(TTR("Update"),!OS::get_singleton()->get_swap_ok_cancel(),"update");
+ import_confirmation->get_label()->set_align(Label::ALIGN_CENTER);
+ import_confirmation->connect("confirmed",this,"_import_action",make_binds("re-import"));
+ import_confirmation->connect("custom_action",this,"_import_action");
+ gui_base->add_child(import_confirmation);
+
+ open_recent_confirmation = memnew( ConfirmationDialog );
+ add_child(open_recent_confirmation);
+ open_recent_confirmation->connect("confirmed",this,"_open_recent_scene_confirm");
+
+
+ run_settings_dialog = memnew( RunSettingsDialog );
+ gui_base->add_child( run_settings_dialog );
+
+
+
+ about = memnew( AcceptDialog );
+ about->set_title(TTR("Thanks from the Godot community!"));
+ //about->get_cancel()->hide();
+ about->get_ok()->set_text(TTR("Thanks!"));
+ about->set_hide_on_ok(true);
+ Label *about_text = memnew( Label );
+ about_text->set_text(VERSION_FULL_NAME"\n(c) 2008-2017 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);
+ TextureRect *logo = memnew( TextureRect );
+ about->add_child(logo);
+ logo->set_pos(Point2(20,20));
+ logo->set_texture(gui_base->get_icon("Logo","EditorIcons") );
+
+ warning = memnew( AcceptDialog );
+ gui_base->add_child(warning);
+
+
+
+ file_templates = memnew( FileDialog );
+ file_templates->set_title(TTR("Import Templates From ZIP File"));
+
+ gui_base->add_child( file_templates );
+ file_templates->set_mode(FileDialog::MODE_OPEN_FILE);
+ file_templates->set_access(FileDialog::ACCESS_FILESYSTEM);
+ file_templates->clear_filters();
+ file_templates->add_filter("*.tpz ; Template Package");
+
+
+ file = memnew( EditorFileDialog );
+ gui_base->add_child(file);
+ file->set_current_dir("res://");
+
+ file_export = memnew( FileDialog );
+ file_export->set_access(FileDialog::ACCESS_FILESYSTEM);
+ gui_base->add_child(file_export);
+ file_export->set_title(TTR("Export Project"));
+ file_export->connect("file_selected", this,"_dialog_action");
+
+ file_export_lib = memnew( FileDialog );
+ file_export_lib->set_title(TTR("Export Library"));
+ file_export_lib->set_mode(FileDialog::MODE_SAVE_FILE);
+ file_export_lib->connect("file_selected", this,"_dialog_action");
+ file_export_lib_merge = memnew( CheckButton );
+ file_export_lib_merge->set_text(TTR("Merge With Existing"));
+ file_export_lib_merge->set_pressed(true);
+ file_export_lib->get_vbox()->add_child(file_export_lib_merge);
+ gui_base->add_child(file_export_lib);
+
+
+
+
+ file_export_password = memnew( LineEdit );
+ file_export_password->set_secret(true);
+ file_export_password->set_editable(false);
+ file_export->get_vbox()->add_margin_child(TTR("Password:"),file_export_password);
+
+
+ file_script = memnew( FileDialog );
+ file_script->set_title(TTR("Open & Run a Script"));
+ file_script->set_access(FileDialog::ACCESS_FILESYSTEM);
+ file_script->set_mode(FileDialog::MODE_OPEN_FILE);
+ List<String> sexts;
+ ResourceLoader::get_recognized_extensions_for_type("Script",&sexts);
+ for (List<String>::Element*E=sexts.front();E;E=E->next()) {
+ file_script->add_filter("*."+E->get());
+ }
+ gui_base->add_child(file_script);
+ file_script->connect("file_selected",this,"_dialog_action");
+
+ //reimport_dialog = memnew( EditorReImportDialog );
+ //gui_base->add_child(reimport_dialog);
+
+
+
+ property_forward->connect("pressed", this,"_property_editor_forward");
+ property_back->connect("pressed", this,"_property_editor_back");
+
+
+
+ file_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+ object_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+
+ update_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+ settings_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+
+
+ file->connect("file_selected", this,"_dialog_action");
+ file_templates->connect("file_selected", this,"_dialog_action");
+ property_editor->connect("resource_selected", this,"_resource_selected");
+ property_editor->connect("property_keyed", this,"_property_keyed");
+
+ //plugin stuff
+
+ file_server = memnew( EditorFileServer );
+
+
+
+
+ add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
+ add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) );
+ add_editor_plugin( memnew( SpatialEditorPlugin(this) ) );
+ add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
+
+
+ EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor();
+
+ ScriptTextEditor::register_editor(); //register one for text scripts
+
+ if (StreamPeerSSL::is_available()) {
+ add_editor_plugin( memnew( AssetLibraryEditorPlugin(this) ) );
+ } else {
+ WARN_PRINT("Asset Library not available, as it requires SSL to work.");
+ }
+ //more visually meaningful to have this later
+ raise_bottom_panel_item(AnimationPlayerEditor::singleton);
+
+ add_editor_plugin( memnew( ShaderEditorPlugin(this) ) );
+/* add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,true) ) );
+ add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,false) ) );
+
+ add_editor_plugin( memnew( ShaderEditorPlugin(this,false) ) );*/
+ add_editor_plugin( memnew( CameraEditorPlugin(this) ) );
+// add_editor_plugin( memnew( SampleEditorPlugin(this) ) );
+// add_editor_plugin( memnew( SampleLibraryEditorPlugin(this) ) );
+ add_editor_plugin( memnew( ThemeEditorPlugin(this) ) );
+ add_editor_plugin( memnew( MultiMeshEditorPlugin(this) ) );
+ add_editor_plugin( memnew( MeshInstanceEditorPlugin(this) ) );
+ add_editor_plugin( memnew( AnimationTreeEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( SamplePlayerEditorPlugin(this) ) ); - this is kind of useless at this point
+ //add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( StreamEditorPlugin(this) ) );
+ add_editor_plugin( memnew( StyleBoxEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( ParticlesEditorPlugin(this) ) );
+ add_editor_plugin( memnew( ResourcePreloaderEditorPlugin(this) ) );
+ add_editor_plugin( memnew( ItemListEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( RichTextEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( CollisionPolygonEditorPlugin(this) ) );
+ add_editor_plugin( memnew( CollisionPolygon2DEditorPlugin(this) ) );
+ add_editor_plugin( memnew( TileSetEditorPlugin(this) ) );
+ add_editor_plugin( memnew( TileMapEditorPlugin(this) ) );
+ add_editor_plugin( memnew( SpriteFramesEditorPlugin(this) ) );
+ add_editor_plugin( memnew( TextureRegionEditorPlugin(this) ) );
+ add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) );
+ add_editor_plugin( memnew( GIProbeEditorPlugin(this) ) );
+ add_editor_plugin( memnew( Path2DEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( PathEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) );
+ add_editor_plugin( memnew( Line2DEditorPlugin(this) ) );
+ 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( CollisionShape2DEditorPlugin(this) ) );
+ add_editor_plugin( memnew( TextureEditorPlugin(this) ) );
+ add_editor_plugin( memnew( AudioBusesEditorPlugin(audio_bus_editor) ) );
+ //add_editor_plugin( memnew( MaterialEditorPlugin(this) ) );
+ //add_editor_plugin( memnew( MeshEditorPlugin(this) ) );
+
+ for(int i=0;i<EditorPlugins::get_plugin_count();i++)
+ add_editor_plugin( EditorPlugins::create(i,this) );
+
+ for(int i=0;i<plugin_init_callback_count;i++) {
+ plugin_init_callbacks[i]();
+ }
+
+
+
+
+ /*resource_preview->add_preview_generator( Ref<EditorTexturePreviewPlugin>( memnew(EditorTexturePreviewPlugin )));
+ resource_preview->add_preview_generator( Ref<EditorPackedScenePreviewPlugin>( memnew(EditorPackedScenePreviewPlugin )));
+ resource_preview->add_preview_generator( Ref<EditorMaterialPreviewPlugin>( memnew(EditorMaterialPreviewPlugin )));
+ 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=Engine::get_singleton()->get_frames_drawn();
+ circle_step=0;
+
+ _rebuild_import_menu();
+
+ editor_plugin_screen=NULL;
+ editor_plugins_over = memnew(EditorPluginList);
+
+ //force_top_viewport(true);
+ _edit_current();
+ current=NULL;
+
+ PhysicsServer::get_singleton()->set_active(false); // no physics by default if editor
+ Physics2DServer::get_singleton()->set_active(false); // no physics by default if editor
+ ScriptServer::set_scripting_enabled(false); // no scripting by default if editor
+
+
+ //GlobalConfig::get_singleton()->set("render/room_cull_enabled",false);
+
+ reference_resource_mem=true;
+ save_external_resources_mem=true;
+
+ set_process(true);
+ OS::get_singleton()->set_low_processor_usage_mode(true);
+
+
+ if (0) { //not sure if i want this to happen after all
+
+ //store project name in ssettings
+ String project_name;
+ //figure it out from path
+ project_name=GlobalConfig::get_singleton()->get_resource_path().replace("\\","/");
+ print_line("path: "+project_name);
+ if (project_name.length() && project_name[project_name.length()-1]=='/')
+ project_name=project_name.substr(0,project_name.length()-1);
+
+ project_name=project_name.replace("/","::");
+
+ if (project_name!="") {
+ EditorSettings::get_singleton()->set("projects/"+project_name,GlobalConfig::get_singleton()->get_resource_path());
+ EditorSettings::get_singleton()->raise_order("projects/"+project_name);
+ EditorSettings::get_singleton()->save();
+ }
+ }
+
+ open_imported = memnew( ConfirmationDialog );
+ open_imported->get_ok()->set_text(TTR("Open Anyway"));
+ new_inherited_button=open_imported->add_button("New Inherited",!OS::get_singleton()->get_swap_ok_cancel(),"inherit");
+ open_imported->connect("confirmed",this,"_open_imported");
+ open_imported->connect("custom_action",this,"_inherit_imported");
+ gui_base->add_child(open_imported);
+
+
+
+ //edited_scene=NULL;
+ saved_version=1;
+ unsaved_cache=true;
+ _last_instanced_scene=NULL;
+
+
+ quick_open = memnew( EditorQuickOpen );
+ gui_base->add_child(quick_open);
+ quick_open->connect("quick_open",this,"_quick_opened");
+
+ quick_run = memnew( EditorQuickOpen );
+ gui_base->add_child(quick_run);
+ quick_run->connect("quick_open",this,"_quick_run");
+
+
+ _update_recent_scenes();
+
+
+ editor_data.restore_editor_global_states();
+ convert_old=false;
+ opening_prev=false;
+ set_process_unhandled_input(true);
+ _playing_edited=false;
+
+ //Panel *errors = memnew( Panel );
+ load_errors = memnew( RichTextLabel );
+ //load_errors->set_readonly(true);
+ load_error_dialog = memnew( AcceptDialog );
+ load_error_dialog->add_child(load_errors);
+ load_error_dialog->set_title(TTR("Load Errors"));
+ //load_error_dialog->set_child_rect(load_errors);
+ gui_base->add_child(load_error_dialog);
+
+
+ //EditorImport::add_importer( Ref<EditorImporterCollada>( memnew(EditorImporterCollada )));
+
+ EditorFileSystem::get_singleton()->connect("sources_changed",this,"_sources_changed");
+ EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_fs_changed");
+
+
+ {
+ List<StringName> tl;
+ StringName ei = "EditorIcons";
+ theme_base->get_theme()->get_icon_list(ei,&tl);
+ for(List<StringName>::Element *E=tl.front();E;E=E->next()) {
+
+ if (!ClassDB::class_exists(E->get()))
+ continue;
+ icon_type_cache[E->get()]=theme_base->get_theme()->get_icon(E->get(),ei);
+ }
+ }
+
+
+
+ Node::set_human_readable_collision_renaming(true);
+
+
+ pick_main_scene = memnew( ConfirmationDialog );
+ gui_base->add_child(pick_main_scene);
+ pick_main_scene->get_ok()->set_text("Select");
+ pick_main_scene->connect("confirmed",this,"_menu_option",varray(SETTINGS_PICK_MAIN_SCENE));
+
+ //Ref<ImageTexture> it = gui_base->get_icon("logo","Icons");
+ //OS::get_singleton()->set_icon( it->get_data() );
+
+ for(int i=0;i<_init_callbacks.size();i++)
+ _init_callbacks[i]();
+
+ editor_data.add_edited_scene(-1);
+ editor_data.set_edited_scene(0);
+ _update_scene_tabs();
+
+ {
+
+ _initializing_addons=true;
+ Vector<String> addons = GlobalConfig::get_singleton()->get("editor_plugins/enabled");
+
+ for(int i=0;i<addons.size();i++) {
+ set_addon_plugin_enabled(addons[i],true);
+ }
+ _initializing_addons=false;
+ }
+
+
+
+ _load_docks();
+
+ FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
+
+ waiting_for_first_scan=true;
+
+}
+
+
+EditorNode::~EditorNode() {
+
+
+ memdelete( EditorHelp::get_doc_data() );
+ memdelete(editor_selection);
+ memdelete(editor_plugins_over);
+ memdelete(file_server);
+ EditorSettings::destroy();
+}
+
+/*
+ * EDITOR PLUGIN LIST
+ */
+
+
+void EditorPluginList::make_visible(bool p_visible) {
+
+ for (int i = 0; i < plugins_list.size(); i++) {
+ plugins_list[i]->make_visible(p_visible);
+ }
+
+}
+
+void EditorPluginList::edit(Object* p_object) {
+
+ for (int i = 0; i < plugins_list.size(); i++) {
+ plugins_list[i]->edit(p_object);
+ }
+
+}
+
+bool EditorPluginList::forward_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) {
+
+ bool discard = false;
+
+ for (int i = 0; i < plugins_list.size(); i++) {
+ if (plugins_list[i]->forward_canvas_gui_input(p_canvas_xform,p_event)) {
+ discard = true;
+ }
+ }
+
+ return discard;
+}
+
+bool EditorPluginList::forward_spatial_gui_input(Camera* p_camera, const InputEvent& p_event) {
+ bool discard = false;
+
+ for (int i = 0; i < plugins_list.size(); i++) {
+ if (plugins_list[i]->forward_spatial_gui_input(p_camera, p_event)) {
+ discard = true;
+ }
+ }
+
+ return discard;
+}
+
+void EditorPluginList::forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control* p_canvas) {
+
+ for (int i = 0; i < plugins_list.size(); i++) {
+ plugins_list[i]->forward_draw_over_canvas(p_canvas_xform,p_canvas);
+ }
+
+}
+
+bool EditorPluginList::empty() {
+ return plugins_list.empty();
+}
+
+void EditorPluginList::clear() {
+ plugins_list.clear();
+}
+
+EditorPluginList::EditorPluginList() {
+}
+
+EditorPluginList::~EditorPluginList() {
+}
diff --git a/editor/editor_node.h b/editor/editor_node.h
new file mode 100644
index 0000000000..fb0b5c4c25
--- /dev/null
+++ b/editor/editor_node.h
@@ -0,0 +1,833 @@
+/*************************************************************************/
+/* editor_node.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_NODE_H
+#define EDITOR_NODE_H
+
+#include "scene/gui/control.h"
+#include "scene/gui/panel.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/center_container.h"
+#include "scene/gui/texture_progress.h"
+#include "editor/filesystem_dock.h"
+#include "editor/scene_tree_editor.h"
+#include "editor/property_editor.h"
+#include "editor/create_dialog.h"
+#include "editor/call_dialog.h"
+#include "editor/reparent_dialog.h"
+#include "editor/connections_dialog.h"
+#include "editor/node_dock.h"
+#include "editor/import_dock.h"
+#include "editor/settings_config_dialog.h"
+#include "editor/groups_editor.h"
+#include "editor/editor_data.h"
+#include "editor/editor_path.h"
+#include "editor/editor_run.h"
+
+#include "editor/pane_drag.h"
+
+#include "editor/script_create_dialog.h"
+#include "editor/run_settings_dialog.h"
+#include "editor/project_settings.h"
+#include "editor/project_export.h"
+#include "editor/editor_log.h"
+#include "editor/scene_tree_dock.h"
+#include "editor/resources_dock.h"
+#include "editor/editor_run_script.h"
+
+#include "editor/editor_run_native.h"
+#include "scene/gui/tabs.h"
+#include "editor/quick_open.h"
+#include "editor/project_export.h"
+#include "editor/editor_sub_scene.h"
+#include "editor_export.h"
+#include "editor_reimport_dialog.h"
+#include "editor/editor_plugin.h"
+#include "editor/editor_name_dialog.h"
+
+#include "fileserver/editor_file_server.h"
+#include "editor_resource_preview.h"
+#include "scene/gui/viewport_container.h"
+
+
+#include "progress_dialog.h"
+
+#include "editor_scale.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+
+
+
+
+typedef void (*EditorNodeInitCallback)();
+typedef void (*EditorPluginInitializeCallback)();
+typedef void (*EditorBuildCallback)();
+
+class EditorPluginList;
+
+class EditorNode : public Node {
+
+ GDCLASS( EditorNode, Node );
+
+public:
+ enum DockSlot {
+ DOCK_SLOT_LEFT_UL,
+ DOCK_SLOT_LEFT_BL,
+ DOCK_SLOT_LEFT_UR,
+ DOCK_SLOT_LEFT_BR,
+ DOCK_SLOT_RIGHT_UL,
+ DOCK_SLOT_RIGHT_BL,
+ DOCK_SLOT_RIGHT_UR,
+ DOCK_SLOT_RIGHT_BR,
+ DOCK_SLOT_MAX
+ };
+private:
+ enum {
+ HISTORY_SIZE=64
+ };
+
+ enum MenuOptions {
+ FILE_NEW_SCENE,
+ FILE_NEW_INHERITED_SCENE,
+ FILE_OPEN_SCENE,
+ FILE_SAVE_SCENE,
+ FILE_SAVE_AS_SCENE,
+ FILE_SAVE_ALL_SCENES,
+ FILE_SAVE_BEFORE_RUN,
+ FILE_SAVE_AND_RUN,
+ FILE_IMPORT_SUBSCENE,
+ FILE_EXPORT_PROJECT,
+ FILE_EXPORT_MESH_LIBRARY,
+ FILE_EXPORT_TILESET,
+ FILE_SAVE_OPTIMIZED,
+ FILE_OPEN_RECENT,
+ FILE_OPEN_OLD_SCENE,
+ FILE_QUICK_OPEN_SCENE,
+ FILE_QUICK_OPEN_SCRIPT,
+ FILE_RUN_SCRIPT,
+ FILE_OPEN_PREV,
+ FILE_CLOSE,
+ FILE_QUIT,
+ FILE_EXTERNAL_OPEN_SCENE,
+ EDIT_UNDO,
+ EDIT_REDO,
+ EDIT_REVERT,
+ TOOLS_ORPHAN_RESOURCES,
+ RESOURCE_NEW,
+ RESOURCE_LOAD,
+ RESOURCE_SAVE,
+ RESOURCE_SAVE_AS,
+ RESOURCE_UNREF,
+ RESOURCE_COPY,
+ RESOURCE_PASTE,
+ OBJECT_COPY_PARAMS,
+ OBJECT_PASTE_PARAMS,
+ OBJECT_UNIQUE_RESOURCES,
+ OBJECT_REQUEST_HELP,
+ RUN_PLAY,
+
+ RUN_STOP,
+ RUN_PLAY_SCENE,
+ RUN_PLAY_NATIVE,
+ RUN_PLAY_CUSTOM_SCENE,
+ RUN_SCENE_SETTINGS,
+ RUN_SETTINGS,
+ RUN_PROJECT_MANAGER,
+ RUN_FILE_SERVER,
+ //RUN_DEPLOY_DUMB_CLIENTS,
+ RUN_LIVE_DEBUG,
+ RUN_DEBUG_COLLISONS,
+ RUN_DEBUG_NAVIGATION,
+ RUN_DEPLOY_REMOTE_DEBUG,
+ RUN_RELOAD_SCRIPTS,
+ SETTINGS_UPDATE_ALWAYS,
+ SETTINGS_UPDATE_CHANGES,
+ SETTINGS_UPDATE_SPINNER_HIDE,
+ SETTINGS_EXPORT_PREFERENCES,
+ SETTINGS_PREFERENCES,
+ SETTINGS_OPTIMIZED_PRESETS,
+ SETTINGS_LAYOUT_SAVE,
+ SETTINGS_LAYOUT_DELETE,
+ SETTINGS_LAYOUT_DEFAULT,
+ SETTINGS_LOAD_EXPORT_TEMPLATES,
+ SETTINGS_PICK_MAIN_SCENE,
+ SETTINGS_TOGGLE_FULLSCREN,
+ SETTINGS_HELP,
+ SETTINGS_ABOUT,
+ SOURCES_REIMPORT,
+ DEPENDENCY_LOAD_CHANGED_IMAGES,
+ DEPENDENCY_UPDATE_IMPORTED,
+ SCENE_TAB_CLOSE,
+
+ IMPORT_PLUGIN_BASE=100,
+
+ OBJECT_METHOD_BASE=500,
+
+ TOOL_MENU_BASE=1000
+ };
+
+
+
+ //Node *edited_scene; //scene being edited
+ Viewport *scene_root; //root of the scene being edited
+
+ //Ref<ResourceImportMetadata> scene_import_metadata;
+
+ PanelContainer* scene_root_parent;
+ Control *gui_base;
+ VBoxContainer *main_vbox;
+
+ //split
+
+ HSplitContainer *left_l_hsplit;
+ VSplitContainer *left_l_vsplit;
+ HSplitContainer *left_r_hsplit;
+ VSplitContainer *left_r_vsplit;
+ HSplitContainer *main_hsplit;
+ HSplitContainer *right_hsplit;
+ VSplitContainer *right_l_vsplit;
+ VSplitContainer *right_r_vsplit;
+
+ VSplitContainer *center_split;
+
+ //main tabs
+
+ Tabs *scene_tabs;
+ int tab_closing;
+
+ bool exiting;
+
+ int old_split_ofs;
+ VSplitContainer *top_split;
+ HBoxContainer *bottom_hb;
+ Control *vp_base;
+ PaneDrag *pd;
+ //PaneDrag *pd_anim;
+ Panel *menu_panel;
+
+
+ //HSplitContainer *editor_hsplit;
+ //VSplitContainer *editor_vsplit;
+ CenterContainer *play_cc;
+ HBoxContainer *menu_hb;
+ Control *viewport;
+ MenuButton *file_menu;
+ MenuButton *import_menu;
+ MenuButton *tool_menu;
+ ToolButton *export_button;
+ ToolButton *prev_scene;
+ MenuButton *object_menu;
+ MenuButton *settings_menu;
+ ToolButton *play_button;
+ MenuButton *native_play_button;
+ ToolButton *pause_button;
+ ToolButton *stop_button;
+ ToolButton *run_settings_button;
+ ToolButton *play_scene_button;
+ ToolButton *play_custom_scene_button;
+ MenuButton *debug_button;
+ ToolButton *search_button;
+ TextureProgress *audio_vu;
+ //MenuButton *fileserver_menu;
+
+ RichTextLabel *load_errors;
+ AcceptDialog *load_error_dialog;
+
+ //Control *scene_root_base;
+ Ref<Theme> theme;
+
+ PopupMenu *recent_scenes;
+ Button *property_back;
+ Button *property_forward;
+ SceneTreeDock *scene_tree_dock;
+ //ResourcesDock *resources_dock;
+ PropertyEditor *property_editor;
+ NodeDock *node_dock;
+ ImportDock *import_dock;
+ VBoxContainer *prop_editor_vb;
+ FileSystemDock *filesystem_dock;
+ EditorRunNative *run_native;
+
+ HBoxContainer *search_bar;
+ LineEdit *search_box;
+
+ CreateDialog *create_dialog;
+
+ //CallDialog *call_dialog;
+ ConfirmationDialog *confirmation;
+ ConfirmationDialog *import_confirmation;
+ ConfirmationDialog *open_recent_confirmation;
+ ConfirmationDialog *pick_main_scene;
+ AcceptDialog *accept;
+ 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;
+ ProjectSettings *project_settings;
+ EditorFileDialog *file;
+ FileDialog *file_templates;
+ FileDialog *file_export;
+ FileDialog *file_export_lib;
+ FileDialog *file_script;
+ CheckButton *file_export_lib_merge;
+ LineEdit *file_export_password;
+ String current_path;
+ MenuButton *update_menu;
+ ToolButton *sources_button;
+ //TabContainer *prop_pallete;
+ //TabContainer *top_pallete;
+ String defer_load_scene;
+ String defer_export;
+ String defer_export_platform;
+ bool defer_export_debug;
+ Node *_last_instanced_scene;
+ EditorPath *editor_path;
+ ToolButton *resource_new_button;
+ ToolButton *resource_load_button;
+ MenuButton *resource_save_button;
+ MenuButton *editor_history_menu;
+
+ EditorLog *log;
+ CenterContainer *tabs_center;
+ EditorQuickOpen *quick_open;
+ EditorQuickOpen *quick_run;
+
+ HBoxContainer *main_editor_button_vb;
+ Vector<ToolButton*> main_editor_buttons;
+ Vector<EditorPlugin*> editor_table;
+
+// EditorReImportDialog *reimport_dialog;
+
+ ProgressDialog *progress_dialog;
+ BackgroundProgress *progress_hb;
+
+ DependencyErrorDialog *dependency_error;
+ DependencyEditor *dependency_fixer;
+ OrphanResourcesDialog *orphan_resources;
+ ConfirmationDialog *open_imported;
+ Button *new_inherited_button;
+ String open_import_request;
+
+
+ TabContainer *dock_slot[DOCK_SLOT_MAX];
+ Rect2 dock_select_rect[DOCK_SLOT_MAX];
+ int dock_select_rect_over;
+ PopupPanel *dock_select_popoup;
+ Control *dock_select;
+ ToolButton *dock_tab_move_left;
+ ToolButton *dock_tab_move_right;
+ int dock_popup_selected;
+ Timer *dock_drag_timer;
+ bool docks_visible;
+ ToolButton *distraction_free;
+
+ String _tmp_import_path;
+
+ EditorExport *editor_export;
+
+ Object *current;
+
+ bool _playing_edited;
+ String run_custom_filename;
+ bool reference_resource_mem;
+ bool save_external_resources_mem;
+ uint64_t saved_version;
+ uint64_t last_checked_version;
+ bool unsaved_cache;
+ String open_navigate;
+ bool changing_scene;
+ bool waiting_for_first_scan;
+
+ bool waiting_for_sources_changed;
+
+ uint32_t circle_step_msec;
+ uint64_t circle_step_frame;
+ int circle_step;
+
+ Vector<EditorPlugin*> editor_plugins;
+ EditorPlugin *editor_plugin_screen;
+ EditorPluginList *editor_plugins_over;
+
+ EditorHistory editor_history;
+ EditorData editor_data;
+ EditorRun editor_run;
+ EditorSelection *editor_selection;
+// ProjectExport *project_export;
+ ProjectExportDialog *project_export;
+ EditorResourcePreview *resource_preview;
+
+ 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;
+
+ void _dialog_action(String p_file);
+
+
+ void _edit_current();
+ void _dialog_display_file_error(String p_file,Error p_error);
+
+ int current_option;
+ //void _animation_visibility_toggle();
+ void _resource_created();
+ void _resource_selected(const RES& p_res,const String& p_property="");
+ void _menu_option(int p_option);
+ void _menu_confirm_current();
+ void _menu_option_confirm(int p_option,bool p_confirmed);
+ void _update_debug_options();
+
+ void _property_editor_forward();
+ void _property_editor_back();
+
+ void _select_history(int p_idx);
+ void _prepare_history();
+
+
+ void _fs_changed();
+ void _sources_changed(bool p_exist);
+ void _imported(Node *p_node);
+
+ void _node_renamed();
+ void _editor_select(int p_which);
+ void _set_scene_metadata(const String &p_file, int p_idx=-1);
+ void _get_scene_metadata(const String& p_file);
+ void _update_title();
+ void _update_scene_tabs();
+ void _close_messages();
+ void _show_messages();
+ void _vp_resized();
+
+ void _rebuild_import_menu();
+
+ void _save_scene(String p_file, int idx = -1);
+
+
+ void _instance_request(const Vector<String>& p_files);
+
+ 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 _hide_top_editors();
+ void _display_top_editors(bool p_display);
+ void _set_top_editors(Vector<EditorPlugin*> p_editor_plugins_over);
+ void _set_editing_top_editors(Object * p_current_object);
+
+ void _quick_opened();
+ void _quick_run();
+
+ void _run(bool p_current=false, const String &p_custom="");
+
+ void _save_optimized();
+ void _import_action(const String& p_action);
+ void _import(const String &p_file);
+ void _add_to_recent_scenes(const String& p_scene);
+ void _update_recent_scenes();
+ void _open_recent_scene(int p_idx);
+ void _dropped_files(const Vector<String>& p_files,int p_screen);
+ //void _open_recent_scene_confirm();
+ String _recent_scene;
+
+ bool convert_old;
+
+ void _unhandled_input(const InputEvent& p_event);
+
+ static void _load_error_notify(void* p_ud,const String& p_text);
+
+ bool has_main_screen() const { return true; }
+
+ bool _find_editing_changed_scene(Node *p_from);
+
+ String import_reload_fn;
+
+ Set<FileDialog*> file_dialogs;
+ Set<EditorFileDialog*> editor_file_dialogs;
+
+ Map<String,Ref<Texture> > icon_type_cache;
+
+ bool _initializing_addons;
+ Map<String,EditorPlugin*> plugin_addons;
+
+
+ static Ref<Texture> _file_dialog_get_icon(const String& p_path);
+ static void _file_dialog_register(FileDialog *p_dialog);
+ static void _file_dialog_unregister(FileDialog *p_dialog);
+ static void _editor_file_dialog_register(EditorFileDialog *p_dialog);
+ static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog);
+
+
+ void _cleanup_scene();
+ void _remove_edited_scene();
+ void _remove_scene(int index);
+ bool _find_and_save_resource(RES p_res,Map<RES,bool>& processed,int32_t flags);
+ bool _find_and_save_edited_subresources(Object *obj,Map<RES,bool>& processed,int32_t flags);
+ void _save_edited_subresources(Node* scene,Map<RES,bool>& processed,int32_t flags);
+
+ void _find_node_types(Node* p_node, int&count_2d, int&count_3d);
+ void _save_scene_with_preview(String p_file);
+
+
+ Map<String,Set<String> > dependency_errors;
+
+ static void _dependency_error_report(void *ud,const String& p_path,const String& p_dep,const String& p_type) {
+ EditorNode*en=(EditorNode*)ud;
+ if (!en->dependency_errors.has(p_path))
+ en->dependency_errors[p_path]=Set<String>();
+ en->dependency_errors[p_path].insert(p_dep+"::"+p_type);
+
+ }
+
+ struct ExportDefer {
+ String platform;
+ String path;
+ bool debug;
+ String password;
+
+ } export_defer;
+
+ static EditorNode *singleton;
+
+ static Vector<EditorNodeInitCallback> _init_callbacks;
+
+ bool _find_scene_in_use(Node* p_node,const String& p_path) const;
+
+ void _dock_select_input(const InputEvent& p_input);
+ void _dock_move_left();
+ void _dock_move_right();
+ void _dock_select_draw();
+ void _dock_pre_popup(int p_which);
+ void _dock_split_dragged(int ofs);
+ void _dock_popup_exit();
+ void _scene_tab_changed(int p_tab);
+ void _scene_tab_closed(int p_tab);
+ void _scene_tab_script_edited(int p_tab);
+
+ Dictionary _get_main_scene_state();
+ void _set_main_scene_state(Dictionary p_state,Node* p_for_scene);
+
+ int _get_current_main_editor();
+
+ 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_dock_slots_visibility();
+ void _update_top_menu_visibility();
+
+ 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();
+
+ void _update_addon_config();
+
+ static void _file_access_close_error_notify(const String& p_str);
+
+ void _toggle_distraction_free_mode();
+
+ enum {
+ MAX_INIT_CALLBACKS=128,
+ MAX_BUILD_CALLBACKS=128
+ };
+
+ void _inherit_imported(const String &p_action);
+ void _open_imported();
+
+
+ static int plugin_init_callback_count;
+ static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS];
+
+ void _call_build();
+ static int build_callback_count;
+ static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS];
+
+ bool _initializing_tool_menu;
+
+ struct ToolMenuItem {
+ String name;
+ String submenu;
+ Variant ud;
+ ObjectID handler;
+ String callback;
+ };
+
+ Vector<ToolMenuItem> tool_menu_items;
+
+ void _tool_menu_insert_item(const ToolMenuItem& p_item);
+ void _rebuild_tool_menu() const;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ static void add_plugin_init_callback(EditorPluginInitializeCallback p_callback);
+
+ enum EditorTable {
+ EDITOR_2D = 0,
+ EDITOR_3D,
+ EDITOR_SCRIPT
+ };
+
+ void set_visible_editor(EditorTable p_table) { _editor_select(p_table); }
+ static EditorNode* get_singleton() { return singleton; }
+
+
+ EditorPlugin *get_editor_plugin_screen() { return editor_plugin_screen; }
+ EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; }
+ PropertyEditor *get_property_editor() { return property_editor; }
+ VBoxContainer *get_property_editor_vb() { return prop_editor_vb; }
+
+ static void add_editor_plugin(EditorPlugin *p_editor);
+ static void remove_editor_plugin(EditorPlugin *p_editor);
+
+ void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE,false); }
+
+
+ void set_docks_visible(bool p_show);
+ bool get_docks_visible() const;
+
+ void set_distraction_free_mode(bool p_enter);
+ bool get_distraction_free_mode() const;
+
+ void add_control_to_dock(DockSlot p_slot,Control* p_control);
+ void remove_control_from_dock(Control* p_control);
+
+ void set_addon_plugin_enabled(const String& p_addon,bool p_enabled);
+ bool is_addon_plugin_enabled(const String &p_addon) const;
+
+ void edit_node(Node *p_node);
+ void edit_resource(const Ref<Resource>& p_resource);
+ void open_resource(const String& p_type="");
+
+ void save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path);
+ void save_resource(const Ref<Resource>& p_resource);
+ void save_resource_as(const Ref<Resource>& p_resource, const String &p_at_path=String());
+
+ void merge_from_scene() { _menu_option_confirm(FILE_IMPORT_SUBSCENE,false); }
+
+ static bool has_unsaved_changes() { return singleton->unsaved_cache; }
+
+ static HBoxContainer *get_menu_hb() { return singleton->menu_hb; }
+
+ void push_item(Object *p_object,const String& p_property="");
+
+ void open_request(const String& p_path);
+
+ bool is_changing_scene() const;
+
+
+ static EditorLog *get_log() { return singleton->log; }
+ Control* get_viewport();
+
+ //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);
+
+ Node *get_edited_scene() { return editor_data.get_edited_scene_root(); }
+
+ Viewport *get_scene_root() { return scene_root; } //root of the scene being edited
+
+ void fix_dependencies(const String& p_for_file);
+ void clear_scene() { _cleanup_scene(); }
+ Error load_scene(const String& p_scene, bool p_ignore_broken_deps=false, bool p_set_inherited=false, bool p_clear_errors=true,bool p_force_open_imported=false);
+ Error load_resource(const String& p_scene);
+
+ bool is_scene_open(const String& p_path);
+
+ void set_current_version(uint64_t p_version);
+ 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; }
+
+ void request_instance_scene(const String &p_path);
+ void request_instance_scenes(const Vector<String>& p_files);
+ FileSystemDock *get_filesystem_dock();
+ ImportDock *get_import_dock();
+ SceneTreeDock *get_scene_tree_dock();
+ static UndoRedo* get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
+
+ EditorSelection *get_editor_selection() { return editor_selection; }
+
+ void set_convert_old_scene(bool p_old) { convert_old=p_old; }
+
+ void notify_child_process_exited();
+
+ OS::ProcessID get_child_process_id() const { return editor_run.get_pid(); }
+ void stop_child_process();
+
+ Ref<Theme> get_editor_theme() const { return theme; }
+
+
+ void show_warning(const String& p_text,const String& p_title="Warning!");
+
+
+ Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false);
+
+ static void register_editor_types();
+ static void unregister_editor_types();
+
+ Control *get_gui_base() { return gui_base; }
+ Control *get_theme_base() { return gui_base->get_parent_control(); }
+
+ 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,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);
+ static void progress_task_step_bg(const String& p_task,int p_step=-1);
+ static void progress_end_task_bg(const String& p_task);
+
+ void save_scene(String p_file) { _save_scene(p_file); }
+
+ bool is_scene_in_use(const String& p_path);
+
+ void scan_import_changes();
+
+ void save_layout();
+
+ void update_keying();
+
+ void reload_scene(const String& p_path);
+
+ bool is_exiting() const { return exiting; }
+
+ ToolButton *get_pause_button() { return pause_button; }
+
+
+ ToolButton* add_bottom_panel_item(String p_text,Control *p_item);
+ bool are_bottom_panels_hidden() const;
+ void make_bottom_panel_item_visible(Control *p_item);
+ void raise_bottom_panel_item(Control *p_item);
+ void hide_bottom_panel();
+ void remove_bottom_panel_item(Control *p_item);
+
+ Variant drag_resource(const Ref<Resource>& p_res,Control* p_from);
+ Variant drag_files(const Vector<String>& p_files,Control* p_from);
+ Variant drag_files_and_dirs(const Vector<String>& p_files,Control* p_from);
+
+ void add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud = Variant());
+ void add_tool_submenu_item(const String& p_name, PopupMenu *p_submenu);
+ void remove_tool_menu_item(const String& p_name);
+
+ EditorNode();
+ ~EditorNode();
+ void get_singleton(const char* arg1, bool arg2);
+
+ static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); }
+ static void add_build_callback(EditorBuildCallback p_callback);
+
+
+
+};
+
+struct EditorProgress {
+
+ String task;
+ 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); }
+};
+
+class EditorPluginList : public Object {
+private:
+ Vector<EditorPlugin*> plugins_list;
+
+public:
+
+ void set_plugins_list(Vector<EditorPlugin*> p_plugins_list) {
+ plugins_list = p_plugins_list;
+ }
+
+ Vector<EditorPlugin*>& get_plugins_list() {
+ return plugins_list;
+ }
+
+ void make_visible(bool p_visible);
+ void edit(Object *p_object);
+ bool forward_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event);
+ bool forward_spatial_gui_input(Camera* p_camera, const InputEvent& p_event);
+ void forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control* p_canvas);
+ void clear();
+ bool empty();
+
+ EditorPluginList();
+ ~EditorPluginList();
+
+} ;
+
+struct EditorProgressBG {
+
+ String task;
+ void step(int p_step=-1) { EditorNode::progress_task_step_bg(task,p_step); }
+ EditorProgressBG(const String& p_task,const String& p_label,int p_amount) { EditorNode::progress_add_task_bg(p_task,p_label,p_amount); task=p_task; }
+ ~EditorProgressBG() { EditorNode::progress_end_task_bg(task); }
+};
+
+#endif
diff --git a/tools/editor/editor_path.cpp b/editor/editor_path.cpp
index 8cd31c4bcc..8cd31c4bcc 100644
--- a/tools/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
diff --git a/tools/editor/editor_path.h b/editor/editor_path.h
index fd5b469d07..fd5b469d07 100644
--- a/tools/editor/editor_path.h
+++ b/editor/editor_path.h
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
new file mode 100644
index 0000000000..85ef96fcc3
--- /dev/null
+++ b/editor/editor_plugin.cpp
@@ -0,0 +1,432 @@
+/*************************************************************************/
+/* editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_plugin.h"
+
+#include "scene/gui/popup_menu.h"
+#include "scene/3d/camera.h"
+#include "plugins/canvas_item_editor_plugin.h"
+#include "plugins/spatial_editor_plugin.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor_resource_preview.h"
+
+void EditorPlugin::add_custom_type(const String& p_type, const String& p_base,const Ref<Script>& p_script, const Ref<Texture>& p_icon) {
+
+ EditorNode::get_editor_data().add_custom_type(p_type,p_base,p_script,p_icon);
+}
+
+void EditorPlugin::remove_custom_type(const String& p_type){
+
+ EditorNode::get_editor_data().remove_custom_type(p_type);
+}
+
+
+ToolButton * EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) {
+
+ return EditorNode::get_singleton()->add_bottom_panel_item(p_title,p_control);
+}
+
+void EditorPlugin::add_control_to_dock(DockSlot p_slot,Control *p_control) {
+
+ ERR_FAIL_NULL(p_control);
+ EditorNode::get_singleton()->add_control_to_dock(EditorNode::DockSlot(p_slot),p_control);
+
+}
+
+void EditorPlugin::remove_control_from_docks(Control *p_control) {
+
+ ERR_FAIL_NULL(p_control);
+ EditorNode::get_singleton()->remove_control_from_dock(p_control);
+
+}
+
+void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) {
+
+ ERR_FAIL_NULL(p_control);
+ EditorNode::get_singleton()->remove_bottom_panel_item(p_control);
+
+}
+
+Control * EditorPlugin::get_editor_viewport() {
+
+ return EditorNode::get_singleton()->get_viewport();
+}
+
+void EditorPlugin::edit_resource(const Ref<Resource>& p_resource){
+
+ EditorNode::get_singleton()->edit_resource(p_resource);
+}
+
+void EditorPlugin::add_control_to_container(CustomControlContainer p_location,Control *p_control) {
+
+ switch(p_location) {
+
+ case CONTAINER_TOOLBAR: {
+
+ EditorNode::get_menu_hb()->add_child(p_control);
+ } break;
+
+ case CONTAINER_SPATIAL_EDITOR_MENU: {
+
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(p_control);
+
+ } break;
+ case CONTAINER_SPATIAL_EDITOR_SIDE: {
+
+ SpatialEditor::get_singleton()->get_palette_split()->add_child(p_control);
+ SpatialEditor::get_singleton()->get_palette_split()->move_child(p_control,0);
+
+ } break;
+ case CONTAINER_SPATIAL_EDITOR_BOTTOM: {
+
+ SpatialEditor::get_singleton()->get_shader_split()->add_child(p_control);
+
+ } break;
+ case CONTAINER_CANVAS_EDITOR_MENU: {
+
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(p_control);
+
+ } break;
+ case CONTAINER_CANVAS_EDITOR_SIDE: {
+
+ CanvasItemEditor::get_singleton()->get_palette_split()->add_child(p_control);
+ CanvasItemEditor::get_singleton()->get_palette_split()->move_child(p_control,0);
+
+ } break;
+ case CONTAINER_CANVAS_EDITOR_BOTTOM: {
+
+ CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(p_control);
+
+ } break;
+ case CONTAINER_PROPERTY_EDITOR_BOTTOM: {
+
+ EditorNode::get_singleton()->get_property_editor_vb()->add_child(p_control);
+
+ } break;
+
+
+ }
+}
+
+void EditorPlugin::add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud) {
+
+ //EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud);
+}
+
+void EditorPlugin::add_tool_submenu_item(const String& p_name, Object *p_submenu) {
+
+ ERR_FAIL_NULL(p_submenu);
+ PopupMenu *submenu = p_submenu->cast_to<PopupMenu>();
+ ERR_FAIL_NULL(submenu);
+ //EditorNode::get_singleton()->add_tool_submenu_item(p_name, submenu);
+}
+
+void EditorPlugin::remove_tool_menu_item(const String& p_name) {
+
+ //EditorNode::get_singleton()->remove_tool_menu_item(p_name);
+}
+
+Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial* p_spatial) {
+ //??
+ if (get_script_instance() && get_script_instance()->has_method("create_spatial_gizmo")) {
+ return get_script_instance()->call("create_spatial_gizmo",p_spatial);
+ }
+
+ return Ref<SpatialEditorGizmo>();
+}
+
+bool EditorPlugin::forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) {
+
+ if (get_script_instance() && get_script_instance()->has_method("forward_canvas_gui_input")) {
+ return get_script_instance()->call("forward_canvas_gui_input",p_canvas_xform,p_event);
+ }
+ return false;
+}
+
+void EditorPlugin::forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control *p_canvas) {
+
+ if (get_script_instance() && get_script_instance()->has_method("forward_draw_over_canvas")) {
+ get_script_instance()->call("forward_draw_over_canvas",p_canvas_xform,p_canvas);
+ }
+}
+
+void EditorPlugin::update_canvas() {
+ CanvasItemEditor::get_singleton()->get_viewport_control()->update();
+}
+
+bool EditorPlugin::forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) {
+
+ if (get_script_instance() && get_script_instance()->has_method("forward_spatial_gui_input")) {
+ return get_script_instance()->call("forward_spatial_gui_input",p_camera,p_event);
+ }
+
+ return false;
+}
+String EditorPlugin::get_name() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("get_name")) {
+ return get_script_instance()->call("get_name");
+ }
+
+ return String();
+
+}
+bool EditorPlugin::has_main_screen() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("has_main_screen")) {
+ return get_script_instance()->call("has_main_screen");
+ }
+
+ return false;
+
+}
+void EditorPlugin::make_visible(bool p_visible) {
+
+ if (get_script_instance() && get_script_instance()->has_method("make_visible")) {
+ get_script_instance()->call("make_visible",p_visible);
+ }
+}
+
+
+void EditorPlugin::edit(Object *p_object) {
+
+ if (get_script_instance() && get_script_instance()->has_method("edit")) {
+ get_script_instance()->call("edit",p_object);
+ }
+
+}
+
+bool EditorPlugin::handles(Object *p_object) const {
+
+ if (get_script_instance() && get_script_instance()->has_method("handles")) {
+ return get_script_instance()->call("handles",p_object);
+ }
+
+ return false;
+}
+Dictionary EditorPlugin::get_state() const {
+
+ if (get_script_instance() && get_script_instance()->has_method("get_state")) {
+ return get_script_instance()->call("get_state");
+ }
+
+ return Dictionary();
+}
+
+void EditorPlugin::set_state(const Dictionary& p_state) {
+
+ if (get_script_instance() && get_script_instance()->has_method("set_state")) {
+ get_script_instance()->call("set_state",p_state);
+ }
+}
+
+void EditorPlugin::clear() {
+
+ if (get_script_instance() && get_script_instance()->has_method("clear")) {
+ get_script_instance()->call("clear");
+ }
+
+}
+
+// if editor references external resources/scenes, save them
+void EditorPlugin::save_external_data() {
+
+ if (get_script_instance() && get_script_instance()->has_method("save_external_data")) {
+ get_script_instance()->call("save_external_data");
+ }
+}
+
+// if changes are pending in editor, apply them
+void EditorPlugin::apply_changes() {
+
+ if (get_script_instance() && get_script_instance()->has_method("apply_changes")) {
+ get_script_instance()->call("apply_changes");
+ }
+}
+
+void EditorPlugin::get_breakpoints(List<String> *p_breakpoints) {
+
+ if (get_script_instance() && get_script_instance()->has_method("get_breakpoints")) {
+ PoolStringArray arr = get_script_instance()->call("get_breakpoints");
+ for(int i=0;i<arr.size();i++)
+ p_breakpoints->push_back(arr[i]);
+ }
+
+}
+bool EditorPlugin::get_remove_list(List<Node*> *p_list) {
+
+ return false;
+}
+
+void EditorPlugin::restore_global_state() {}
+void EditorPlugin::save_global_state() {}
+
+void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
+
+ if (get_script_instance() && get_script_instance()->has_method("set_window_layout")) {
+ get_script_instance()->call("set_window_layout", p_layout);
+ }
+}
+
+void EditorPlugin::get_window_layout(Ref<ConfigFile> p_layout){
+
+ if (get_script_instance() && get_script_instance()->has_method("get_window_layout")) {
+ get_script_instance()->call("get_window_layout", p_layout);
+ }
+}
+
+void EditorPlugin::queue_save_layout() const {
+
+ EditorNode::get_singleton()->save_layout();
+}
+
+EditorSelection* EditorPlugin::get_selection() {
+ return EditorNode::get_singleton()->get_editor_selection();
+}
+
+
+EditorSettings *EditorPlugin::get_editor_settings() {
+ return EditorSettings::get_singleton();
+}
+
+EditorResourcePreview *EditorPlugin::get_resource_previewer() {
+ return EditorResourcePreview::get_singleton();
+}
+
+Control *EditorPlugin::get_base_control() {
+
+ return EditorNode::get_singleton()->get_gui_base();
+}
+
+void EditorPlugin::make_bottom_panel_item_visible(Control * p_item) {
+
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(p_item);
+}
+
+void EditorPlugin::hide_bottom_panel() {
+
+ EditorNode::get_singleton()->hide_bottom_panel();
+}
+
+void EditorPlugin::inspect_object(Object *p_obj,const String& p_for_property) {
+
+ EditorNode::get_singleton()->push_item(p_obj,p_for_property);
+}
+
+EditorFileSystem *EditorPlugin::get_resource_file_system() {
+ return EditorFileSystem::get_singleton();
+}
+
+void EditorPlugin::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("add_control_to_container","container","control:Control"),&EditorPlugin::add_control_to_container);
+ ClassDB::bind_method(D_METHOD("add_control_to_bottom_panel:ToolButton","control:Control","title"),&EditorPlugin::add_control_to_bottom_panel);
+ ClassDB::bind_method(D_METHOD("add_control_to_dock","slot","control:Control"),&EditorPlugin::add_control_to_dock);
+ ClassDB::bind_method(D_METHOD("remove_control_from_docks","control:Control"),&EditorPlugin::remove_control_from_docks);
+ ClassDB::bind_method(D_METHOD("remove_control_from_bottom_panel","control:Control"),&EditorPlugin::remove_control_from_bottom_panel);
+ //ClassDB::bind_method(D_METHOD("add_tool_menu_item", "name", "handler", "callback", "ud"),&EditorPlugin::add_tool_menu_item,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("add_tool_submenu_item", "name", "submenu:PopupMenu"),&EditorPlugin::add_tool_submenu_item);
+ //ClassDB::bind_method(D_METHOD("remove_tool_menu_item", "name"),&EditorPlugin::remove_tool_menu_item);
+ ClassDB::bind_method(D_METHOD("add_custom_type","type","base","script:Script","icon:Texture"),&EditorPlugin::add_custom_type);
+ ClassDB::bind_method(D_METHOD("remove_custom_type","type"),&EditorPlugin::remove_custom_type);
+ ClassDB::bind_method(D_METHOD("get_editor_viewport:Control"), &EditorPlugin::get_editor_viewport);
+
+ ClassDB::bind_method(D_METHOD("get_resource_previewer:EditorResourcePreview"),&EditorPlugin::get_resource_previewer);
+ ClassDB::bind_method(D_METHOD("get_resource_filesystem:EditorFileSystem"),&EditorPlugin::get_resource_file_system);
+
+ ClassDB::bind_method(D_METHOD("inspect_object","object","for_property"),&EditorPlugin::inspect_object,DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("update_canvas"),&EditorPlugin::update_canvas);
+
+ ClassDB::bind_method(D_METHOD("make_bottom_panel_item_visible","item:Control"), &EditorPlugin::make_bottom_panel_item_visible);
+ ClassDB::bind_method(D_METHOD("hide_bottom_panel"), &EditorPlugin::hide_bottom_panel);
+
+ ClassDB::bind_method(D_METHOD("get_base_control:Control"),&EditorPlugin::get_base_control);
+ ClassDB::bind_method(D_METHOD("get_undo_redo:UndoRedo"),&EditorPlugin::_get_undo_redo);
+ ClassDB::bind_method(D_METHOD("get_selection:EditorSelection"),&EditorPlugin::get_selection);
+ ClassDB::bind_method(D_METHOD("get_editor_settings:EditorSettings"),&EditorPlugin::get_editor_settings);
+ ClassDB::bind_method(D_METHOD("queue_save_layout"),&EditorPlugin::queue_save_layout);
+ ClassDB::bind_method(D_METHOD("edit_resource"),&EditorPlugin::edit_resource);
+
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"forward_canvas_gui_input",PropertyInfo(Variant::TRANSFORM2D,"canvas_xform"),PropertyInfo(Variant::INPUT_EVENT,"event")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("forward_draw_over_canvas",PropertyInfo(Variant::TRANSFORM2D,"canvas_xform"),PropertyInfo(Variant::OBJECT,"canvas:Control")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"forward_spatial_gui_input",PropertyInfo(Variant::OBJECT,"camera",PROPERTY_HINT_RESOURCE_TYPE,"Camera"),PropertyInfo(Variant::INPUT_EVENT,"event")));
+ MethodInfo gizmo = MethodInfo(Variant::OBJECT,"create_spatial_gizmo",PropertyInfo(Variant::OBJECT,"for_spatial:Spatial"));
+ gizmo.return_val.hint=PROPERTY_HINT_RESOURCE_TYPE;
+ gizmo.return_val.hint_string="EditorSpatialGizmo";
+ ClassDB::add_virtual_method(get_class_static(),gizmo);
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::STRING,"get_name"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"has_main_screen"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("make_visible",PropertyInfo(Variant::BOOL,"visible")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("edit",PropertyInfo(Variant::OBJECT,"object")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"handles",PropertyInfo(Variant::OBJECT,"object")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::DICTIONARY,"get_state"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("set_state",PropertyInfo(Variant::DICTIONARY,"state")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("clear"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("save_external_data"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("apply_changes"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::POOL_STRING_ARRAY,"get_breakpoints"));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("set_window_layout",PropertyInfo(Variant::OBJECT,"layout",PROPERTY_HINT_RESOURCE_TYPE,"ConfigFile")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo("get_window_layout",PropertyInfo(Variant::OBJECT,"layout",PROPERTY_HINT_RESOURCE_TYPE,"ConfigFile")));
+
+ BIND_CONSTANT( CONTAINER_TOOLBAR );
+ BIND_CONSTANT( CONTAINER_SPATIAL_EDITOR_MENU );
+ BIND_CONSTANT( CONTAINER_SPATIAL_EDITOR_SIDE );
+ BIND_CONSTANT( CONTAINER_SPATIAL_EDITOR_BOTTOM );
+ BIND_CONSTANT( CONTAINER_CANVAS_EDITOR_MENU );
+ BIND_CONSTANT( CONTAINER_CANVAS_EDITOR_SIDE );
+ BIND_CONSTANT( CONTAINER_PROPERTY_EDITOR_BOTTOM );
+
+
+ BIND_CONSTANT( DOCK_SLOT_LEFT_UL );
+ BIND_CONSTANT( DOCK_SLOT_LEFT_BL );
+ BIND_CONSTANT( DOCK_SLOT_LEFT_UR );
+ BIND_CONSTANT( DOCK_SLOT_LEFT_BR );
+ BIND_CONSTANT( DOCK_SLOT_RIGHT_UL );
+ BIND_CONSTANT( DOCK_SLOT_RIGHT_BL );
+ BIND_CONSTANT( DOCK_SLOT_RIGHT_UR );
+ BIND_CONSTANT( DOCK_SLOT_RIGHT_BR );
+ BIND_CONSTANT( DOCK_SLOT_MAX );
+
+}
+
+EditorPlugin::EditorPlugin()
+{
+ undo_redo=NULL;
+}
+
+
+EditorPlugin::~EditorPlugin()
+{
+}
+
+
+
+EditorPluginCreateFunc EditorPlugins::creation_funcs[MAX_CREATE_FUNCS];
+
+int EditorPlugins::creation_func_count=0;
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
new file mode 100644
index 0000000000..13d8ab0343
--- /dev/null
+++ b/editor/editor_plugin.h
@@ -0,0 +1,201 @@
+/*************************************************************************/
+/* editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_PLUGIN_H
+#define EDITOR_PLUGIN_H
+
+#include "scene/gui/tool_button.h"
+#include "scene/main/node.h"
+#include "scene/resources/texture.h"
+#include "undo_redo.h"
+#include "io/config_file.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class EditorNode;
+class Spatial;
+class Camera;
+class EditorSelection;
+class EditorExport;
+class EditorSettings;
+class SpatialEditorGizmo;
+class EditorImportPlugin;
+class EditorExportPlugin;
+class EditorResourcePreview;
+class EditorFileSystem;
+
+class EditorPlugin : public Node {
+
+ GDCLASS( EditorPlugin, Node );
+friend class EditorData;
+ UndoRedo *undo_redo;
+
+ UndoRedo* _get_undo_redo() { return undo_redo; }
+
+protected:
+
+ static void _bind_methods();
+ UndoRedo& get_undo_redo() { return *undo_redo; }
+
+ void add_custom_type(const String& p_type, const String& p_base,const Ref<Script>& p_script, const Ref<Texture>& p_icon);
+ void remove_custom_type(const String& p_type);
+
+
+public:
+
+ enum CustomControlContainer {
+ CONTAINER_TOOLBAR,
+ CONTAINER_SPATIAL_EDITOR_MENU,
+ CONTAINER_SPATIAL_EDITOR_SIDE,
+ CONTAINER_SPATIAL_EDITOR_BOTTOM,
+ CONTAINER_CANVAS_EDITOR_MENU,
+ CONTAINER_CANVAS_EDITOR_SIDE,
+ CONTAINER_CANVAS_EDITOR_BOTTOM,
+ CONTAINER_PROPERTY_EDITOR_BOTTOM
+ };
+
+ enum DockSlot {
+ DOCK_SLOT_LEFT_UL,
+ DOCK_SLOT_LEFT_BL,
+ DOCK_SLOT_LEFT_UR,
+ DOCK_SLOT_LEFT_BR,
+ DOCK_SLOT_RIGHT_UL,
+ DOCK_SLOT_RIGHT_BL,
+ DOCK_SLOT_RIGHT_UR,
+ DOCK_SLOT_RIGHT_BR,
+ DOCK_SLOT_MAX
+ };
+
+ //TODO: send a resoucre for editing to the editor node?
+
+ void add_control_to_container(CustomControlContainer p_location, Control *p_control);
+ ToolButton *add_control_to_bottom_panel(Control *p_control, const String &p_title);
+ void add_control_to_dock(DockSlot p_slot,Control *p_control);
+ void remove_control_from_docks(Control *p_control);
+ void remove_control_from_bottom_panel(Control *p_control);
+ Control* get_editor_viewport();
+ void edit_resource(const Ref<Resource>& p_resource);
+
+ void add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud = Variant());
+ void add_tool_submenu_item(const String& p_name, Object *p_submenu);
+ void remove_tool_menu_item(const String& p_name);
+
+ virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial* p_spatial);
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform, const InputEvent& p_event);
+ virtual void forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control *p_canvas);
+ virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event);
+ virtual String get_name() const;
+ virtual bool has_main_screen() const;
+ virtual void make_visible(bool p_visible);
+ virtual void selected_notify() {}//notify that it was raised by the user, not the editor
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_node) const;
+ virtual Dictionary get_state() const; //save editor state so it can't be reloaded when reloading scene
+ virtual void set_state(const Dictionary& p_state) ; //restore editor state (likely was saved with the scene)
+ virtual void clear() ; // clear any temporary data in te editor, reset it (likely new scene or load another scene)
+ virtual void save_external_data() ; // if editor references external resources/scenes, save them
+ virtual void apply_changes() ; // if changes are pending in editor, apply them
+ virtual void get_breakpoints(List<String> *p_breakpoints);
+ 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
+
+ void update_canvas();
+
+ virtual void inspect_object(Object *p_obj,const String& p_for_property=String());
+
+ void queue_save_layout() const;
+
+ Control *get_base_control();
+
+ void make_bottom_panel_item_visible(Control *p_item);
+ void hide_bottom_panel();
+
+ EditorSelection* get_selection();
+ //EditorImportExport *get_import_export();
+ EditorSettings *get_editor_settings();
+ EditorResourcePreview *get_resource_previewer();
+ EditorFileSystem *get_resource_file_system();
+
+ virtual void restore_global_state();
+ virtual void save_global_state();
+
+ EditorPlugin();
+ virtual ~EditorPlugin();
+
+};
+
+VARIANT_ENUM_CAST( EditorPlugin::CustomControlContainer );
+VARIANT_ENUM_CAST( EditorPlugin::DockSlot );
+
+
+typedef EditorPlugin* (*EditorPluginCreateFunc)(EditorNode *);
+
+class EditorPlugins {
+
+ enum {
+ MAX_CREATE_FUNCS=64
+ };
+
+ static EditorPluginCreateFunc creation_funcs[MAX_CREATE_FUNCS];
+ static int creation_func_count;
+
+ template<class T>
+ static EditorPlugin *creator(EditorNode *p_node) {
+ return memnew( T(p_node) );
+ }
+
+public:
+
+ static int get_plugin_count() { return creation_func_count; }
+ static EditorPlugin* create(int p_idx,EditorNode* p_editor) { ERR_FAIL_INDEX_V(p_idx,creation_func_count,NULL); return creation_funcs[p_idx](p_editor); }
+
+ template<class T>
+ static void add_by_type() {
+ add_create_func(creator<T>);
+ }
+
+ static void add_create_func(EditorPluginCreateFunc p_func) {
+
+ ERR_FAIL_COND(creation_func_count>=MAX_CREATE_FUNCS);
+ creation_funcs[creation_func_count++]=p_func;
+ }
+
+};
+
+
+
+
+
+
+
+
+#endif
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
new file mode 100644
index 0000000000..2d879e38cf
--- /dev/null
+++ b/editor/editor_plugin_settings.cpp
@@ -0,0 +1,216 @@
+/*************************************************************************/
+/* editor_plugin_settings.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_plugin_settings.h"
+
+#include "scene/gui/margin_container.h"
+#include "io/config_file.h"
+#include "os/file_access.h"
+#include "os/main_loop.h"
+#include "global_config.h"
+#include "editor_node.h"
+
+void EditorPluginSettings::_notification(int p_what) {
+
+ if (p_what==MainLoop::NOTIFICATION_WM_FOCUS_IN) {
+ update_plugins();
+ }
+}
+
+void EditorPluginSettings::update_plugins() {
+
+
+ plugin_list->clear();
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Error err = da->change_dir("res://addons");
+ if (err!=OK) {
+ memdelete(da);
+ return;
+ }
+
+ updating=true;
+
+ TreeItem *root = plugin_list->create_item();
+
+ da->list_dir_begin();
+
+ String d = da->get_next();
+
+ Vector<String> plugins;
+
+ while(d!=String()) {
+
+ bool dir = da->current_is_dir();
+ String path = "res://addons/"+d+"/plugin.cfg";
+
+ if (dir && FileAccess::exists(path)) {
+
+ plugins.push_back(d);
+ }
+
+ d = da->get_next();
+ }
+
+ da->list_dir_end();
+ memdelete(da);
+
+ plugins.sort();
+
+ Vector<String> active_plugins = GlobalConfig::get_singleton()->get("plugins/active");
+
+ for(int i=0;i<plugins.size();i++) {
+
+ Ref<ConfigFile> cf;
+ cf.instance();
+ String path = "res://addons/"+plugins[i]+"/plugin.cfg";
+
+ Error err = cf->load(path);
+
+ if (err!=OK) {
+ WARN_PRINTS("Can't load plugin config: "+path);
+ } else if (!cf->has_section_key("plugin","name")) {
+ WARN_PRINTS("Plugin misses plugin/name: "+path);
+ } else if (!cf->has_section_key("plugin","author")) {
+ WARN_PRINTS("Plugin misses plugin/author: "+path);
+ } else if (!cf->has_section_key("plugin","version")) {
+ WARN_PRINTS("Plugin misses plugin/version: "+path);
+ } else if (!cf->has_section_key("plugin","description")) {
+ WARN_PRINTS("Plugin misses plugin/description: "+path);
+ } else if (!cf->has_section_key("plugin","script")) {
+ WARN_PRINTS("Plugin misses plugin/script: "+path);
+ } else {
+
+ String d = plugins[i];
+ String name = cf->get_value("plugin","name");
+ String author = cf->get_value("plugin","author");
+ String version = cf->get_value("plugin","version");
+ String description = cf->get_value("plugin","description");
+ String script = cf->get_value("plugin","script");
+
+ TreeItem *item = plugin_list->create_item(root);
+ item->set_text(0,name);
+ item->set_tooltip(0,"Name: "+name+"\nPath: "+path+"\nMain Script: "+script);
+ item->set_metadata(0,d);
+ item->set_text(1,version);
+ item->set_metadata(1,script);
+ item->set_text(2,author);
+ item->set_metadata(2,description);
+ item->set_cell_mode(3,TreeItem::CELL_MODE_RANGE);
+ item->set_range_config(3,0,1,1);
+ item->set_text(3,"Inactive,Active");
+ item->set_editable(3,true);
+
+ if (EditorNode::get_singleton()->is_addon_plugin_enabled(d)) {
+ item->set_custom_color(3,Color(0.2,1,0.2));
+ item->set_range(3,1);
+ } else {
+ item->set_custom_color(3,Color(1,0.2,0.2));
+ item->set_range(3,0);
+ }
+ }
+
+ }
+
+ updating=false;
+
+}
+
+
+void EditorPluginSettings::_plugin_activity_changed() {
+
+ if (updating)
+ return;
+
+ TreeItem *ti=plugin_list->get_edited();
+ ERR_FAIL_COND(!ti);
+ bool active = ti->get_range(3);
+ String name = ti->get_metadata(0);
+
+ EditorNode::get_singleton()->set_addon_plugin_enabled(name,active);
+
+ bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(name);
+
+ if (is_active!=active) {
+ updating=true;
+ ti->set_range(3,is_active?1:0);
+ updating=false;
+ }
+
+ if (is_active)
+ ti->set_custom_color(3,Color(0.2,1,0.2));
+ else
+ ti->set_custom_color(3,Color(1,0.2,0.2));
+
+
+}
+
+void EditorPluginSettings::_bind_methods() {
+
+ ClassDB::bind_method("update_plugins",&EditorPluginSettings::update_plugins);
+ ClassDB::bind_method("_plugin_activity_changed",&EditorPluginSettings::_plugin_activity_changed);
+}
+
+EditorPluginSettings::EditorPluginSettings() {
+
+ HBoxContainer *title_hb = memnew( HBoxContainer );
+ title_hb->add_child(memnew( Label(TTR("Installed Plugins:"))));
+ title_hb->add_spacer();
+ update_list = memnew( Button(TTR("Update")) );
+ update_list->connect("pressed",this,"update_plugins");
+ title_hb->add_child(update_list);
+ add_child(title_hb);
+
+ plugin_list = memnew( Tree );
+ plugin_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ plugin_list->set_columns(4);
+ plugin_list->set_column_titles_visible(true);
+ plugin_list->set_column_title(0,TTR("Name:"));
+ plugin_list->set_column_title(1,TTR("Version:"));
+ plugin_list->set_column_title(2,TTR("Author:"));
+ plugin_list->set_column_title(3,TTR("Status:"));
+ plugin_list->set_column_expand(0,true);
+ plugin_list->set_column_expand(1,false);
+ plugin_list->set_column_expand(2,false);
+ plugin_list->set_column_expand(3,false);
+ plugin_list->set_column_min_width(1,100);
+ plugin_list->set_column_min_width(2,250);
+ plugin_list->set_column_min_width(3,80);
+ plugin_list->set_hide_root(true);
+ plugin_list->connect("item_edited",this,"_plugin_activity_changed");
+
+
+ MarginContainer *mc = memnew( MarginContainer );
+ mc->add_child(plugin_list);
+ mc->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ add_child(mc);
+
+ updating=false;
+
+}
diff --git a/tools/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h
index e24880a21d..e24880a21d 100644
--- a/tools/editor/editor_plugin_settings.h
+++ b/editor/editor_plugin_settings.h
diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp
new file mode 100644
index 0000000000..d9a4174246
--- /dev/null
+++ b/editor/editor_profiler.cpp
@@ -0,0 +1,784 @@
+/*************************************************************************/
+/* editor_profiler.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_profiler.h"
+
+#include "editor_settings.h"
+#include "os/os.h"
+
+void EditorProfiler::_make_metric_ptrs(Metric& m) {
+
+ for(int i=0;i<m.categories.size();i++) {
+ m.category_ptrs[m.categories[i].signature]=&m.categories[i];
+ for(int j=0;j<m.categories[i].items.size();j++) {
+ m.item_ptrs[m.categories[i].items[j].signature]=&m.categories[i].items[j];
+ }
+ }
+}
+
+void EditorProfiler::add_frame_metric(const Metric& p_metric,bool p_final) {
+
+ ++last_metric;
+ if (last_metric>=frame_metrics.size())
+ last_metric=0;
+
+
+ frame_metrics[last_metric]=p_metric;
+ _make_metric_ptrs(frame_metrics[last_metric]);
+
+ updating_frame=true;
+ cursor_metric_edit->set_max(frame_metrics[last_metric].frame_number);
+ cursor_metric_edit->set_min(MAX(frame_metrics[last_metric].frame_number-frame_metrics.size(),0));
+
+
+ if (!seeking) {
+ cursor_metric_edit->set_value(frame_metrics[last_metric].frame_number);
+ if (hover_metric!=-1) {
+ hover_metric++;
+ if (hover_metric>=frame_metrics.size()) {
+ hover_metric=0;
+ }
+ }
+
+ }
+ updating_frame=false;
+
+ if (!frame_delay->is_processing()) {
+
+ frame_delay->set_wait_time(p_final?0.1:1);
+ frame_delay->start();
+ }
+
+ if (!plot_delay->is_processing()) {
+ plot_delay->set_wait_time(0.1);
+ plot_delay->start();
+ }
+
+}
+
+
+
+void EditorProfiler::clear() {
+
+ int metric_size=EditorSettings::get_singleton()->get("debugger/profiler_frame_history_size");
+ metric_size = CLAMP(metric_size,60,1024);
+ frame_metrics.clear();
+ frame_metrics.resize(metric_size);
+ last_metric=-1;
+ variables->clear();
+ //activate->set_pressed(false);
+ plot_sigs.clear();
+ plot_sigs.insert("fixed_frame_time");
+ plot_sigs.insert("category_frame_time");
+
+ updating_frame=true;
+ cursor_metric_edit->set_min(0);
+ cursor_metric_edit->set_max(0);
+ cursor_metric_edit->set_value(0);
+ updating_frame=false;
+ hover_metric=-1;
+ seeking=false;
+}
+
+static String _get_percent_txt(float p_value,float p_total) {
+ if (p_total==0)
+ p_total=0.00001;
+ return String::num((p_value/p_total)*100,1)+"%";
+}
+
+
+String EditorProfiler::_get_time_as_text(Metric &m,float p_time,int p_calls) {
+
+ int dmode = display_mode->get_selected();
+
+
+ if (dmode==DISPLAY_FRAME_TIME) {
+ return rtos(p_time);
+ } else if (dmode==DISPLAY_AVERAGE_TIME) {
+ if (p_calls==0)
+ return "0";
+ else
+ return rtos(p_time/p_calls);
+ } else if (dmode==DISPLAY_FRAME_PERCENT) {
+ return _get_percent_txt(p_time,m.frame_time);
+ } else if (dmode==DISPLAY_FIXED_FRAME_PERCENT) {
+
+ return _get_percent_txt(p_time,m.fixed_frame_time);
+ }
+
+ return "err";
+}
+
+Color EditorProfiler::_get_color_from_signature(const StringName& p_signature) const {
+
+ double rot = ABS(double(p_signature.hash())/double(0x7FFFFFFF));
+ Color c;
+ c.set_hsv(rot,1,1);
+ return c;
+
+}
+
+void EditorProfiler::_item_edited() {
+
+ if (updating_frame)
+ return;
+
+ TreeItem *item=variables->get_edited();
+ if (!item)
+ return;
+ StringName signature=item->get_metadata(0);
+ bool checked=item->is_checked(0);
+
+
+ if (checked)
+ plot_sigs.insert(signature);
+ else
+ plot_sigs.erase(signature);
+
+ if (!frame_delay->is_processing()) {
+ frame_delay->set_wait_time(0.1);
+ frame_delay->start();
+ }
+
+ _update_plot();
+}
+
+void EditorProfiler::_update_plot() {
+
+ int w = graph->get_size().width;
+ int h = graph->get_size().height;
+
+ bool reset_texture=false;
+
+ int desired_len = w * h * 4;
+
+ if (graph_image.size()!=desired_len) {
+ reset_texture=true;
+ graph_image.resize(desired_len);
+ }
+
+
+ PoolVector<uint8_t>::Write wr = graph_image.write();
+
+
+
+ //clear
+ for(int i=0;i<desired_len;i+=4) {
+ wr[i+0]=0;
+ wr[i+1]=0;
+ wr[i+2]=0;
+ wr[i+3]=255;
+ }
+
+
+ //find highest value
+
+ bool use_self = display_time->get_selected()==DISPLAY_SELF_TIME;
+ float highest=0;
+
+ for(int i=0;i<frame_metrics.size();i++) {
+ Metric &m = frame_metrics[i];
+ if (!m.valid)
+ continue;
+
+ for (Set<StringName>::Element *E=plot_sigs.front();E;E=E->next()) {
+
+ Map<StringName,Metric::Category*>::Element *F=m.category_ptrs.find(E->get());
+ if (F) {
+ highest=MAX(F->get()->total_time,highest);
+ }
+
+ Map<StringName,Metric::Category::Item*>::Element *G=m.item_ptrs.find(E->get());
+ if (G) {
+ if (use_self) {
+ highest=MAX(G->get()->self,highest);
+ } else {
+ highest=MAX(G->get()->total,highest);
+ }
+ }
+ }
+ }
+
+ if (highest>0) {
+ //means some data exists..
+ highest*=1.2; //leave some upper room
+ graph_height=highest;
+
+ Vector<int> columnv;
+ columnv.resize(h*4);
+
+ int *column = columnv.ptr();
+
+ Map<StringName,int> plot_prev;
+ //Map<StringName,int> plot_max;
+
+ uint64_t time = OS::get_singleton()->get_ticks_usec();
+
+ for(int i=0;i<w;i++) {
+
+
+ for(int j=0;j<h*4;j++) {
+ column[j]=0;
+ }
+
+ int current = i*frame_metrics.size()/w;
+ int next = (i+1)*frame_metrics.size()/w;
+ if (next>frame_metrics.size()) {
+ next=frame_metrics.size();
+ }
+ if (next==current)
+ next=current+1; //just because for loop must work
+
+ for (Set<StringName>::Element *E=plot_sigs.front();E;E=E->next()) {
+
+ int plot_pos=-1;
+
+ for(int j=current;j<next;j++) {
+
+ //wrap
+ int idx = last_metric+1+j;
+ while( idx >= frame_metrics.size() ) {
+ idx-=frame_metrics.size();
+ }
+
+ //get
+ Metric &m = frame_metrics[idx];
+ if (m.valid==false)
+ continue; //skip because invalid
+
+
+ float value=0;
+
+ Map<StringName,Metric::Category*>::Element *F=m.category_ptrs.find(E->get());
+ if (F) {
+ value=F->get()->total_time;
+ }
+
+ Map<StringName,Metric::Category::Item*>::Element *G=m.item_ptrs.find(E->get());
+ if (G) {
+ if (use_self) {
+ value=G->get()->self;
+ } else {
+ value=G->get()->total;
+ }
+ }
+
+
+ plot_pos = MAX( CLAMP(int(value*h/highest),0,h-1), plot_pos );
+
+
+ }
+
+ int prev_plot=plot_pos;
+ Map<StringName,int>::Element *H=plot_prev.find(E->get());
+ if (H) {
+ prev_plot=H->get();
+ H->get()=plot_pos;
+ } else {
+ plot_prev[E->get()]=plot_pos;
+ }
+
+ if (plot_pos==-1 && prev_plot==-1) {
+ //don't bother drawing
+ continue;
+ }
+
+ if (prev_plot!=-1 && plot_pos==-1) {
+
+ plot_pos=prev_plot;
+ }
+
+ if (prev_plot==-1 && plot_pos!=-1) {
+ prev_plot=plot_pos;
+ }
+
+ plot_pos = h- plot_pos -1;
+ prev_plot = h- prev_plot -1;
+
+ if (prev_plot > plot_pos) {
+ SWAP(prev_plot,plot_pos);
+ }
+
+ Color col = _get_color_from_signature(E->get());
+
+ for(int j=prev_plot;j<=plot_pos;j++) {
+
+ column[j*4+0]+=Math::fast_ftoi(CLAMP(col.r*255,0,255));
+ column[j*4+1]+=Math::fast_ftoi(CLAMP(col.g*255,0,255));
+ column[j*4+2]+=Math::fast_ftoi(CLAMP(col.b*255,0,255));
+ column[j*4+3]+=1;
+
+ }
+ }
+
+
+ for(int j=0;j<h*4;j+=4) {
+
+ int a = column[j+3];
+ if (a>0) {
+ column[j+0]/=a;
+ column[j+1]/=a;
+ column[j+2]/=a;
+
+ }
+
+ uint8_t r = uint8_t(column[j+0]);
+ uint8_t g = uint8_t(column[j+1]);
+ uint8_t b = uint8_t(column[j+2]);
+
+ int widx = ((j>>2)*w+i)*4;
+ wr[widx+0]=r;
+ wr[widx+1]=g;
+ wr[widx+2]=b;
+ wr[widx+3]=255;
+ }
+ }
+
+ time = OS::get_singleton()->get_ticks_usec() - time;
+ //print_line("Taken: "+rtos(USEC_TO_SEC(time)));
+
+ }
+
+
+ wr = PoolVector<uint8_t>::Write();
+
+ Image img(w,h,0,Image::FORMAT_RGBA8,graph_image);
+
+ if (reset_texture) {
+
+ if (graph_texture.is_null()) {
+ graph_texture.instance();
+ }
+ graph_texture->create(img.get_width(),img.get_height(),img.get_format(),Texture::FLAG_VIDEO_SURFACE);
+
+ }
+
+ graph_texture->set_data(img);
+
+
+ graph->set_texture(graph_texture);
+ graph->update();
+
+}
+
+void EditorProfiler::_update_frame() {
+
+ int cursor_metric = _get_cursor_index();
+
+
+ ERR_FAIL_INDEX(cursor_metric,frame_metrics.size());
+
+ updating_frame=true;
+ variables->clear();
+
+ TreeItem* root = variables->create_item();
+ Metric &m = frame_metrics[cursor_metric];
+
+
+ int dtime = display_time->get_selected();
+
+
+ for(int i=0;i<m.categories.size();i++) {
+
+ TreeItem *category = variables->create_item(root);
+ category->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ category->set_editable(0,true);
+ category->set_metadata(0,m.categories[i].signature);
+ category->set_text(0,String(m.categories[i].name));
+ category->set_text(1,_get_time_as_text(m,m.categories[i].total_time,1));
+
+ if (plot_sigs.has(m.categories[i].signature)) {
+ category->set_checked(0,true);
+ category->set_custom_bg_color(0,Color(0,0,0));
+ category->set_custom_color(0,_get_color_from_signature(m.categories[i].signature));
+ }
+
+
+ for(int j=0;j<m.categories[i].items.size();j++) {
+ Metric::Category::Item &it = m.categories[i].items[j];
+
+ TreeItem *item = variables->create_item(category);
+ item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ item->set_editable(0,true);
+ item->set_text(0,it.name);
+ item->set_metadata(0,it.signature);
+ item->set_metadata(1,it.script);
+ item->set_metadata(2,it.line);
+ item->set_tooltip(0,it.script+":"+itos(it.line));
+
+ float time = dtime == DISPLAY_SELF_TIME ? it.self : it.total;
+
+ item->set_text(1,_get_time_as_text(m,time,it.calls));
+
+ item->set_text(2,itos(it.calls));
+
+ if (plot_sigs.has(it.signature)) {
+ item->set_checked(0,true);
+ item->set_custom_bg_color(0,Color(0,0,0));
+ item->set_custom_color(0,_get_color_from_signature(it.signature));
+ }
+
+ }
+ }
+
+ updating_frame=false;
+
+}
+
+
+void EditorProfiler::_activate_pressed() {
+
+ if (activate->is_pressed()) {
+ clear();
+ activate->set_icon(get_icon("Stop","EditorIcons"));
+ activate->set_text(TTR("Stop Profiling"));
+ } else {
+ activate->set_icon(get_icon("Play","EditorIcons"));
+ activate->set_text(TTR("Start Profiling"));
+
+
+ }
+ emit_signal("enable_profiling",activate->is_pressed());
+
+}
+
+
+void EditorProfiler::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ activate->set_icon(get_icon("Play","EditorIcons"));
+ }
+}
+
+void EditorProfiler::_graph_tex_draw() {
+
+ if (last_metric<0)
+ return;
+ if (seeking) {
+
+ int max_frames = frame_metrics.size();
+ int frame = cursor_metric_edit->get_value() - (frame_metrics[last_metric].frame_number-max_frames+1);
+ if (frame<0)
+ frame=0;
+
+ int cur_x = frame * graph->get_size().x / max_frames;
+
+
+ graph->draw_line(Vector2(cur_x,0),Vector2(cur_x,graph->get_size().y),Color(1,1,1,0.8));
+ }
+
+
+ if (hover_metric!=-1 && frame_metrics[hover_metric].valid) {
+
+
+
+ int max_frames = frame_metrics.size();
+ int frame = frame_metrics[hover_metric].frame_number - (frame_metrics[last_metric].frame_number-max_frames+1);
+ if (frame<0)
+ frame=0;
+
+ int cur_x = frame * graph->get_size().x / max_frames;
+
+ graph->draw_line(Vector2(cur_x,0),Vector2(cur_x,graph->get_size().y),Color(1,1,1,0.4));
+
+
+ }
+
+}
+
+void EditorProfiler::_graph_tex_mouse_exit() {
+
+ hover_metric=-1;
+ graph->update();
+}
+
+
+void EditorProfiler::_cursor_metric_changed(double) {
+ if (updating_frame)
+ return;
+
+
+ graph->update();
+ _update_frame();
+
+}
+
+void EditorProfiler::_graph_tex_input(const InputEvent& p_ev){
+
+ if (last_metric<0)
+ return;
+
+ if (
+ (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) ||
+ (p_ev.type==InputEvent::MOUSE_MOTION) ) {
+
+ int x = p_ev.mouse_button.x;
+ x=x*frame_metrics.size()/graph->get_size().width;
+
+ bool show_hover = x>=0 && x<frame_metrics.size();
+
+ if (x<0) {
+ x=0;
+ }
+
+ if (x>=frame_metrics.size()) {
+ x=frame_metrics.size()-1;
+ }
+
+
+
+ int metric=frame_metrics.size()-x-1;
+ metric = last_metric-metric;
+ while(metric<0) {
+ metric+=frame_metrics.size();
+ }
+
+
+
+ if (show_hover) {
+
+ hover_metric=metric;
+
+ } else {
+ hover_metric=-1;
+ }
+
+
+ if (p_ev.type==InputEvent::MOUSE_BUTTON || p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
+ //cursor_metric=x;
+ updating_frame=true;
+
+ //metric may be invalid, so look for closest metric that is valid, this makes snap feel better
+ bool valid=false;
+ for(int i=0;i<frame_metrics.size();i++) {
+
+ if (frame_metrics[metric].valid) {
+ valid=true;
+ break;
+ }
+
+ metric++;
+ if (metric>=frame_metrics.size())
+ metric=0;
+ }
+
+ if (valid)
+ cursor_metric_edit->set_value(frame_metrics[metric].frame_number);
+
+ updating_frame=false;
+
+ if (activate->is_pressed()) {
+ if (!seeking) {
+ emit_signal("break_request");
+ }
+ }
+
+ seeking=true;
+
+ if (!frame_delay->is_processing()) {
+ frame_delay->set_wait_time(0.1);
+ frame_delay->start();
+ }
+ }
+
+ graph->update();
+
+ }
+
+}
+
+int EditorProfiler::_get_cursor_index() const {
+
+ if (last_metric<0)
+ return 0;
+ if (!frame_metrics[last_metric].valid)
+ return 0;
+
+ int diff = (frame_metrics[last_metric].frame_number-cursor_metric_edit->get_value());
+
+ int idx = last_metric - diff;
+ while (idx<0) {
+ idx+=frame_metrics.size();
+ }
+
+
+ return idx;
+
+}
+
+void EditorProfiler::disable_seeking() {
+
+ seeking=false;
+ graph->update();
+
+}
+
+void EditorProfiler::_combo_changed(int) {
+
+ _update_frame();
+ _update_plot();
+}
+
+void EditorProfiler::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_update_frame"),&EditorProfiler::_update_frame);
+ ClassDB::bind_method(D_METHOD("_update_plot"),&EditorProfiler::_update_plot);
+ ClassDB::bind_method(D_METHOD("_activate_pressed"),&EditorProfiler::_activate_pressed);
+ ClassDB::bind_method(D_METHOD("_graph_tex_draw"),&EditorProfiler::_graph_tex_draw);
+ ClassDB::bind_method(D_METHOD("_graph_tex_input"),&EditorProfiler::_graph_tex_input);
+ ClassDB::bind_method(D_METHOD("_graph_tex_mouse_exit"),&EditorProfiler::_graph_tex_mouse_exit);
+ ClassDB::bind_method(D_METHOD("_cursor_metric_changed"),&EditorProfiler::_cursor_metric_changed);
+ ClassDB::bind_method(D_METHOD("_combo_changed"),&EditorProfiler::_combo_changed);
+
+ ClassDB::bind_method(D_METHOD("_item_edited"),&EditorProfiler::_item_edited);
+ ADD_SIGNAL( MethodInfo("enable_profiling",PropertyInfo(Variant::BOOL,"enable")));
+ ADD_SIGNAL( MethodInfo("break_request"));
+
+}
+
+void EditorProfiler::set_enabled(bool p_enable) {
+
+ activate->set_disabled(!p_enable);
+}
+
+bool EditorProfiler::is_profiling() {
+ return activate->is_pressed();
+}
+
+EditorProfiler::EditorProfiler()
+{
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ add_child(hb);
+ activate = memnew( Button );
+ activate->set_toggle_mode(true);
+ activate->set_text(TTR("Start Profiling"));
+ activate->connect("pressed",this,"_activate_pressed");
+ hb->add_child(activate);
+
+ hb->add_child( memnew( Label(TTR("Measure:") ) ) );
+
+ display_mode = memnew( OptionButton );
+ display_mode->add_item(TTR("Frame Time (sec)"));
+ display_mode->add_item(TTR("Average Time (sec)"));
+ display_mode->add_item(TTR("Frame %"));
+ display_mode->add_item(TTR("Fixed Frame %"));
+ display_mode->connect("item_selected",this,"_combo_changed");
+
+ hb->add_child( display_mode );
+
+ hb->add_child( memnew( Label(TTR("Time:") ) ) );
+
+ display_time = memnew( OptionButton );
+ display_time->add_item(TTR("Inclusive"));
+ display_time->add_item(TTR("Self"));
+ display_time->connect("item_selected",this,"_combo_changed");
+
+ hb->add_child(display_time);
+
+ hb->add_spacer();
+
+ hb->add_child( memnew( Label(TTR("Frame #:") ) ) );
+
+ cursor_metric_edit = memnew( SpinBox );
+ cursor_metric_edit->set_h_size_flags(SIZE_FILL);
+ hb->add_child(cursor_metric_edit);
+ cursor_metric_edit->connect("value_changed",this,"_cursor_metric_changed");
+
+ hb->add_constant_override("separation",8);
+
+
+
+ h_split = memnew( HSplitContainer );
+ add_child(h_split);
+ h_split->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ variables = memnew( Tree );
+ variables->set_custom_minimum_size(Size2(300,0));
+ variables->set_hide_folding(true);
+ h_split->add_child(variables);
+ variables->set_hide_root(true);
+ variables->set_columns(3);
+ variables->set_column_titles_visible(true);
+ variables->set_column_title(0,"Name");
+ variables->set_column_expand(0,true);
+ variables->set_column_min_width(0,60);
+ variables->set_column_title(1,"Time");
+ variables->set_column_expand(1,false);
+ variables->set_column_min_width(1,60);
+ variables->set_column_title(2,"Calls");
+ variables->set_column_expand(2,false);
+ variables->set_column_min_width(2,60);
+ variables->connect("item_edited",this,"_item_edited");
+
+
+ graph = memnew( TextureRect );
+ graph->set_expand(true);
+ graph->set_mouse_filter(MOUSE_FILTER_STOP);
+ //graph->set_ignore_mouse(false);
+ graph->connect("draw",this,"_graph_tex_draw");
+ graph->connect("gui_input",this,"_graph_tex_input");
+ graph->connect("mouse_exited",this,"_graph_tex_mouse_exit");
+
+ h_split->add_child(graph);
+ graph->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ add_constant_override("separation",3);
+
+ int metric_size=CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size",600)),60,1024);
+ frame_metrics.resize(metric_size);
+ last_metric=-1;
+ //cursor_metric=-1;
+ hover_metric=-1;
+
+
+ EDITOR_DEF("debugger/profiler_frame_max_functions",64);
+
+ //display_mode=DISPLAY_FRAME_TIME;
+
+ frame_delay = memnew( Timer );
+ frame_delay->set_wait_time(0.1);
+ frame_delay->set_one_shot(true);
+ add_child(frame_delay);
+ frame_delay->connect("timeout",this,"_update_frame");
+
+ plot_delay = memnew( Timer );
+ plot_delay->set_wait_time(0.1);
+ plot_delay->set_one_shot(true);
+ add_child(plot_delay);
+ plot_delay->connect("timeout",this,"_update_plot");
+
+ plot_sigs.insert("fixed_frame_time");
+ plot_sigs.insert("category_frame_time");
+
+ seeking=false;
+ graph_height=1;
+
+ //activate->set_disabled(true);
+
+}
diff --git a/tools/editor/editor_profiler.h b/editor/editor_profiler.h
index bf89e3939c..bf89e3939c 100644
--- a/tools/editor/editor_profiler.h
+++ b/editor/editor_profiler.h
diff --git a/tools/editor/editor_reimport_dialog.cpp b/editor/editor_reimport_dialog.cpp
index 5904070230..5904070230 100644
--- a/tools/editor/editor_reimport_dialog.cpp
+++ b/editor/editor_reimport_dialog.cpp
diff --git a/tools/editor/editor_reimport_dialog.h b/editor/editor_reimport_dialog.h
index 7379c70c5e..7379c70c5e 100644
--- a/tools/editor/editor_reimport_dialog.h
+++ b/editor/editor_reimport_dialog.h
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
new file mode 100644
index 0000000000..ab2226e79a
--- /dev/null
+++ b/editor/editor_resource_preview.cpp
@@ -0,0 +1,439 @@
+/*************************************************************************/
+/* editor_resource_preview.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_resource_preview.h"
+
+#include "editor_settings.h"
+#include "os/file_access.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "global_config.h"
+#include "editor_scale.h"
+#include "message_queue.h"
+
+bool EditorResourcePreviewGenerator::handles(const String& p_type) const {
+
+ if (get_script_instance() && get_script_instance()->has_method("handles")) {
+ return get_script_instance()->call("handles",p_type);
+ }
+ ERR_EXPLAIN("EditorResourcePreviewGenerator::handles needs to be overriden");
+ ERR_FAIL_V(false);
+}
+Ref<Texture> EditorResourcePreviewGenerator::generate(const RES& p_from){
+
+ if (get_script_instance() && get_script_instance()->has_method("generate")) {
+ return get_script_instance()->call("generate",p_from);
+ }
+ ERR_EXPLAIN("EditorResourcePreviewGenerator::generate needs to be overriden");
+ ERR_FAIL_V(Ref<Texture>());
+
+}
+
+
+Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String& p_path) {
+
+ if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) {
+ return get_script_instance()->call("generate_from_path",p_path);
+ }
+
+ RES res = ResourceLoader::load(p_path);
+ if (!res.is_valid())
+ return res;
+ return generate(res);
+}
+
+
+void EditorResourcePreviewGenerator::_bind_methods() {
+
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"handles",PropertyInfo(Variant::STRING,"type")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::OBJECT,"generate:Texture",PropertyInfo(Variant::OBJECT,"from",PROPERTY_HINT_RESOURCE_TYPE,"Resource")));
+ ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::OBJECT,"generate_from_path:Texture",PropertyInfo(Variant::STRING,"path",PROPERTY_HINT_FILE)));
+
+}
+
+EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
+
+
+}
+
+
+EditorResourcePreview* EditorResourcePreview::singleton=NULL;
+
+
+void EditorResourcePreview::_thread_func(void *ud) {
+
+ EditorResourcePreview *erp=(EditorResourcePreview*)ud;
+ erp->_thread();
+
+}
+
+
+void EditorResourcePreview::_preview_ready(const String& p_str,const Ref<Texture>& p_texture,ObjectID id,const StringName& p_func,const Variant& p_ud) {
+
+ //print_line("preview is ready");
+ preview_mutex->lock();
+
+ String path = p_str;
+ uint32_t hash=0;
+ uint64_t modified_time=0;
+
+ if (p_str.begins_with("ID:")) {
+ hash=p_str.get_slicec(':',2).to_int();
+ path="ID:"+p_str.get_slicec(':',1);
+ } else {
+ modified_time = FileAccess::get_modified_time(path);
+ }
+
+ Item item;
+ item.order=order++;
+ item.preview=p_texture;
+ item.last_hash=hash;
+ item.modified_time=modified_time;
+
+ cache[path]=item;
+
+ preview_mutex->unlock();
+
+ MessageQueue::get_singleton()->push_call(id,p_func,path,p_texture,p_ud);
+
+}
+
+Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem& p_item,const String& cache_base) {
+
+ String type;
+
+ if (p_item.resource.is_valid())
+ type=p_item.resource->get_class();
+ else
+ type=ResourceLoader::get_resource_type(p_item.path);
+ //print_line("resource type is: "+type);
+
+ if (type=="")
+ return Ref<Texture>(); //could not guess type
+
+ Ref<Texture> generated;
+
+ for(int i=0;i<preview_generators.size();i++) {
+
+ if (!preview_generators[i]->handles(type))
+ continue;
+ if (p_item.resource.is_valid()) {
+ generated = preview_generators[i]->generate(p_item.resource);
+ } else {
+ generated = preview_generators[i]->generate_from_path(p_item.path);
+ }
+
+ break;
+ }
+
+ if (!p_item.resource.is_valid()) {
+ // cache the preview in case it's a resource on disk
+ if (generated.is_valid()) {
+ //print_line("was generated");
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ //wow it generated a preview... save cache
+ ResourceSaver::save(cache_base+".png",generated);
+ FileAccess *f=FileAccess::open(cache_base+".txt",FileAccess::WRITE);
+ f->store_line(itos(thumbnail_size));
+ f->store_line(itos(FileAccess::get_modified_time(p_item.path)));
+ f->store_line(FileAccess::get_md5(p_item.path));
+ memdelete(f);
+ } else {
+ //print_line("was not generated");
+
+ }
+ }
+
+ return generated;
+}
+
+void EditorResourcePreview::_thread() {
+
+ //print_line("begin thread");
+ while(!exit) {
+
+ //print_line("wait for semaphore");
+ preview_sem->wait();
+ preview_mutex->lock();
+
+ //print_line("blue team go");
+
+ if (queue.size()) {
+
+
+
+ QueueItem item = queue.front()->get();
+ queue.pop_front();
+
+ if (cache.has(item.path)) {
+ //already has it because someone loaded it, just let it know it's ready
+ if (item.resource.is_valid()) {
+ item.path+=":"+itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below)
+ }
+
+ _preview_ready(item.path,cache[item.path].preview,item.id,item.function,item.userdata);
+
+ preview_mutex->unlock();
+ } else {
+ preview_mutex->unlock();
+
+
+ Ref<Texture> texture;
+
+ //print_line("pop from queue "+item.path);
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+
+
+ if (item.resource.is_valid()){
+
+ texture=_generate_preview(item,String());
+ //adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred
+ _preview_ready(item.path+":"+itos(item.resource->hash_edited_version()),texture,item.id,item.function,item.userdata);
+
+ } else {
+
+
+ String temp_path=EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
+ String cache_base = GlobalConfig::get_singleton()->globalize_path(item.path).md5_text();
+ cache_base = temp_path.plus_file("resthumb-"+cache_base);
+
+ //does not have it, try to load a cached thumbnail
+
+ String file = cache_base+".txt";
+ //print_line("cachetxt at "+file);
+ FileAccess *f=FileAccess::open(file,FileAccess::READ);
+ if (!f) {
+
+ //print_line("generate because not cached");
+
+ //generate
+ texture=_generate_preview(item,cache_base);
+ } else {
+
+ uint64_t modtime = FileAccess::get_modified_time(item.path);
+ int tsize = f->get_line().to_int64();
+ uint64_t last_modtime = f->get_line().to_int64();
+
+ bool cache_valid = true;
+
+ if (tsize!=thumbnail_size) {
+ cache_valid=false;
+ memdelete(f);
+ } else if (last_modtime!=modtime) {
+
+ String last_md5 = f->get_line();
+ String md5 = FileAccess::get_md5(item.path);
+ memdelete(f);
+
+ if (last_md5!=md5) {
+
+ cache_valid=false;
+ } else {
+ //update modified time
+
+ f=FileAccess::open(file,FileAccess::WRITE);
+ f->store_line(itos(modtime));
+ f->store_line(md5);
+ memdelete(f);
+ }
+ } else {
+ memdelete(f);
+ }
+
+ cache_valid=false;
+
+ if (cache_valid) {
+
+ texture = ResourceLoader::load(cache_base+".png","ImageTexture",true);
+ if (!texture.is_valid()) {
+ //well fuck
+ cache_valid=false;
+ }
+ }
+
+ if (!cache_valid) {
+
+ texture=_generate_preview(item,cache_base);
+ }
+
+ }
+
+ //print_line("notify of preview ready");
+ _preview_ready(item.path,texture,item.id,item.function,item.userdata);
+
+ }
+ }
+
+
+ } else {
+ preview_mutex->unlock();
+ }
+
+ }
+}
+
+
+
+void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource>& p_res, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) {
+
+ ERR_FAIL_NULL(p_receiver);
+ ERR_FAIL_COND(!p_res.is_valid());
+
+ preview_mutex->lock();
+
+ String path_id = "ID:"+itos(p_res->get_instance_ID());
+
+
+ if (cache.has(path_id) && cache[path_id].last_hash==p_res->hash_edited_version()) {
+
+ cache[path_id].order=order++;
+ p_receiver->call_deferred(p_receiver_func,path_id,cache[path_id].preview,p_userdata);
+ preview_mutex->unlock();
+ return;
+
+ }
+
+ cache.erase(path_id); //erase if exists, since it will be regen
+
+ //print_line("send to thread "+p_path);
+ QueueItem item;
+ item.function=p_receiver_func;
+ item.id=p_receiver->get_instance_ID();
+ item.resource=p_res;
+ item.path=path_id;
+ item.userdata=p_userdata;
+
+ queue.push_back(item);
+ preview_mutex->unlock();
+ preview_sem->post();
+}
+
+void EditorResourcePreview::queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) {
+
+ ERR_FAIL_NULL(p_receiver);
+ preview_mutex->lock();
+ if (cache.has(p_path)) {
+ cache[p_path].order=order++;
+ p_receiver->call_deferred(p_receiver_func,p_path,cache[p_path].preview,p_userdata);
+ preview_mutex->unlock();
+ return;
+ }
+
+ //print_line("send to thread "+p_path);
+ QueueItem item;
+ item.function=p_receiver_func;
+ item.id=p_receiver->get_instance_ID();
+ item.path=p_path;
+ item.userdata=p_userdata;
+
+ queue.push_back(item);
+ preview_mutex->unlock();
+ preview_sem->post();
+
+}
+
+void EditorResourcePreview::add_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator) {
+
+ preview_generators.push_back(p_generator);
+}
+
+void EditorResourcePreview::remove_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator) {
+
+ preview_generators.erase(p_generator);
+}
+
+EditorResourcePreview* EditorResourcePreview::get_singleton() {
+
+ return singleton;
+}
+
+void EditorResourcePreview::_bind_methods() {
+
+ ClassDB::bind_method("_preview_ready",&EditorResourcePreview::_preview_ready);
+
+ ClassDB::bind_method(D_METHOD("queue_resource_preview","path","receiver","receiver_func","userdata:Variant"),&EditorResourcePreview::queue_resource_preview);
+ ClassDB::bind_method(D_METHOD("queue_edited_resource_preview","resource:Resource","receiver","receiver_func","userdata:Variant"),&EditorResourcePreview::queue_edited_resource_preview);
+ ClassDB::bind_method(D_METHOD("add_preview_generator","generator:EditorResourcePreviewGenerator"),&EditorResourcePreview::add_preview_generator);
+ ClassDB::bind_method(D_METHOD("remove_preview_generator","generator:EditorResourcePreviewGenerator"),&EditorResourcePreview::remove_preview_generator);
+ ClassDB::bind_method(D_METHOD("check_for_invalidation","path"),&EditorResourcePreview::check_for_invalidation);
+
+
+ ADD_SIGNAL(MethodInfo("preview_invalidated",PropertyInfo(Variant::STRING,"path")));
+}
+
+void EditorResourcePreview::check_for_invalidation(const String& p_path) {
+
+ preview_mutex->lock();
+
+ bool call_invalidated=false;
+ if (cache.has(p_path)) {
+
+ uint64_t modified_time = FileAccess::get_modified_time(p_path);
+ if (modified_time!=cache[p_path].modified_time) {
+ cache.erase(p_path);
+ call_invalidated=true;
+ }
+ }
+
+ preview_mutex->unlock();
+
+ if (call_invalidated) {//do outside mutex
+ call_deferred("emit_signal","preview_invalidated",p_path);
+ }
+
+
+
+}
+
+EditorResourcePreview::EditorResourcePreview() {
+ singleton=this;
+ preview_mutex = Mutex::create();
+ preview_sem = Semaphore::create();
+ order=0;
+ exit=false;
+
+ thread = Thread::create(_thread_func,this);
+}
+
+
+EditorResourcePreview::~EditorResourcePreview()
+{
+
+ exit=true;
+ preview_sem->post();
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+ memdelete(preview_mutex);
+ memdelete(preview_sem);
+
+
+}
+
diff --git a/tools/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index e4a593330d..e4a593330d 100644
--- a/tools/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
new file mode 100644
index 0000000000..46e400ae7f
--- /dev/null
+++ b/editor/editor_run.cpp
@@ -0,0 +1,211 @@
+/*************************************************************************/
+/* editor_run.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_run.h"
+
+#include "global_config.h"
+#include "editor_settings.h"
+
+EditorRun::Status EditorRun::get_status() const {
+
+ return status;
+}
+Error EditorRun::run(const String& p_scene,const String p_custom_args,const List<String>& p_breakpoints) {
+
+ List<String> args;
+
+
+ String resource_path = GlobalConfig::get_singleton()->get_resource_path();
+
+ if (resource_path!="") {
+ args.push_back("-path");
+ args.push_back(resource_path.replace(" ","%20"));
+
+ }
+
+ if (true) {
+ args.push_back("-rdebug");
+ args.push_back("localhost:"+String::num(GLOBAL_GET("network/debug/remote_port")));
+ }
+
+ args.push_back("-epid");
+ args.push_back(String::num(OS::get_singleton()->get_process_ID()));
+
+ if (debug_collisions) {
+ args.push_back("-debugcol");
+ }
+
+ if (debug_navigation) {
+ args.push_back("-debugnav");
+ }
+
+ int screen = EditorSettings::get_singleton()->get("run/window_placement/screen");
+
+ if (screen==0) {
+ screen=OS::get_singleton()->get_current_screen();
+ } else {
+ screen--;
+ }
+
+ Rect2 screen_rect;
+ screen_rect.pos=OS::get_singleton()->get_screen_position(screen);
+ screen_rect.size=OS::get_singleton()->get_screen_size(screen);
+
+
+ Size2 desired_size;
+
+ desired_size.x=GlobalConfig::get_singleton()->get("display/width");
+ desired_size.y=GlobalConfig::get_singleton()->get("display/height");
+
+ Size2 test_size;
+ test_size.x=GlobalConfig::get_singleton()->get("display/test_width");
+ test_size.y=GlobalConfig::get_singleton()->get("display/test_height");
+ if (test_size.x>0 && test_size.y>0) {
+
+ desired_size=test_size;
+ }
+
+
+ int window_placement=EditorSettings::get_singleton()->get("run/window_placement/rect");
+
+ switch(window_placement) {
+ case 0: { // default
+
+ args.push_back("-p");
+ args.push_back(itos(screen_rect.pos.x)+"x"+itos(screen_rect.pos.y));
+ } break;
+ case 1: { // centered
+ Vector2 pos=screen_rect.pos+((screen_rect.size-desired_size)/2).floor();
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ } break;
+ case 2: { // custom pos
+ Vector2 pos = EditorSettings::get_singleton()->get("run/window_placement/rect_custom_position");
+ pos+=screen_rect.pos;
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ } break;
+ case 3: { // force maximized
+ Vector2 pos=screen_rect.pos;
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ args.push_back("-mx");
+
+ } break;
+ case 4: { // force fullscreen
+
+ Vector2 pos=screen_rect.pos;
+ args.push_back("-p");
+ args.push_back(itos(pos.x)+"x"+itos(pos.y));
+ args.push_back("-f");
+ } break;
+ }
+
+
+
+ if (p_breakpoints.size()) {
+
+ args.push_back("-bp");
+ String bpoints;
+ for(const List<String>::Element *E=p_breakpoints.front();E;E=E->next()) {
+
+ bpoints+=E->get().replace(" ","%20");
+ if (E->next())
+ bpoints+=",";
+ }
+
+ args.push_back(bpoints);
+ }
+
+ if (p_scene!="") {
+ args.push_back(p_scene);
+ }
+
+ if (p_custom_args!="") {
+ Vector<String> cargs=p_custom_args.split(" ",false);
+ for(int i=0;i<cargs.size();i++) {
+ args.push_back(cargs[i].replace(" ","%20"));
+ }
+ }
+
+ String exec = OS::get_singleton()->get_executable_path();
+
+ printf("running: %ls", exec.c_str());
+ for (List<String>::Element* E = args.front(); E ; E = E->next()) {
+
+ printf(" %ls", E->get().c_str());
+ };
+ printf("\n");
+
+ pid=0;
+ Error err = OS::get_singleton()->execute(exec,args,false,&pid);
+ ERR_FAIL_COND_V(err,err);
+
+ status = STATUS_PLAY;
+
+ return OK;
+}
+
+void EditorRun::stop() {
+
+ if (status!=STATUS_STOP && pid!=0) {
+
+ OS::get_singleton()->kill(pid);
+ }
+
+ status=STATUS_STOP;
+}
+
+void EditorRun::set_debug_collisions(bool p_debug) {
+
+ debug_collisions=p_debug;
+}
+
+bool EditorRun::get_debug_collisions() const{
+
+ return debug_collisions;
+}
+
+void EditorRun::set_debug_navigation(bool p_debug) {
+
+ debug_navigation=p_debug;
+}
+
+bool EditorRun::get_debug_navigation() const{
+
+ return debug_navigation;
+}
+
+
+EditorRun::EditorRun() {
+
+ status=STATUS_STOP;
+ debug_collisions=false;
+ debug_navigation=false;
+
+}
diff --git a/editor/editor_run.h b/editor/editor_run.h
new file mode 100644
index 0000000000..46c5dc7521
--- /dev/null
+++ b/editor/editor_run.h
@@ -0,0 +1,67 @@
+/*************************************************************************/
+/* editor_run.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_RUN_H
+#define EDITOR_RUN_H
+
+#include "scene/main/node.h"
+#include "os/os.h"
+class EditorRun {
+public:
+ enum Status {
+
+ STATUS_PLAY,
+ STATUS_PAUSED,
+ STATUS_STOP
+ };
+
+ OS::ProcessID pid;
+private:
+
+ bool debug_collisions;
+ bool debug_navigation;
+ Status status;
+public:
+
+ Status get_status() const;
+ Error run(const String& p_scene,const String p_custom_args,const List<String>& p_breakpoints);
+ void run_native_notify() { status=STATUS_PLAY; }
+ void stop();
+
+ OS::ProcessID get_pid() const { return pid; }
+
+ void set_debug_collisions(bool p_debug);
+ bool get_debug_collisions() const;
+
+ void set_debug_navigation(bool p_debug);
+ bool get_debug_navigation() const;
+
+ EditorRun();
+};
+
+#endif // EDITOR_RUN_H
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
new file mode 100644
index 0000000000..60a9f53b94
--- /dev/null
+++ b/editor/editor_run_native.cpp
@@ -0,0 +1,189 @@
+/*************************************************************************/
+/* editor_run_native.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_run_native.h"
+
+#include "editor_export.h"
+
+void EditorRunNative::_notification(int p_what) {
+
+#if 0
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ List<StringName> ep;
+ EditorImportExport::get_singleton()->get_export_platforms(&ep);
+ ep.sort_custom<StringName::AlphCompare>();
+ for(List<StringName>::Element *E=ep.front();E;E=E->next()) {
+
+ Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(E->get());
+ if (eep.is_null())
+ continue;
+ Ref<ImageTexture> icon = eep->get_logo();
+ if (!icon.is_null()) {
+ Image im = icon->get_data();
+ im.clear_mipmaps();
+ if (!im.empty()) {
+
+ im.resize(16,16);
+
+ Ref<ImageTexture> small_icon = memnew( ImageTexture);
+ small_icon->create_from_image(im);
+ MenuButton *mb = memnew( MenuButton );
+ mb->get_popup()->connect("id_pressed",this,"_run_native",varray(E->get()));
+ mb->connect("pressed",this,"_run_native",varray(-1, E->get()));
+ mb->set_icon(small_icon);
+ add_child(mb);
+ menus[E->get()]=mb;
+ }
+ }
+ }
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+
+ bool changed = EditorImportExport::get_singleton()->poll_export_platforms() || first;
+
+ if (changed) {
+
+ for(Map<StringName,MenuButton*>::Element *E=menus.front();E;E=E->next()) {
+
+ Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(E->key());
+ MenuButton *mb = E->get();
+ int dc = eep->get_device_count();
+
+ if (dc==0) {
+ mb->hide();
+ } else {
+ mb->get_popup()->clear();
+ mb->show();
+ if (dc == 1) {
+ mb->set_tooltip(eep->get_device_name(0) + "\n\n" + eep->get_device_info(0).strip_edges());
+ } else {
+ mb->set_tooltip("Select device from the list");
+ for(int i=0;i<dc;i++) {
+ mb->get_popup()->add_icon_item(get_icon("Play","EditorIcons"),eep->get_device_name(i));
+ mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() -1,eep->get_device_info(i).strip_edges());
+ }
+ }
+ }
+ }
+
+ first=false;
+ }
+ }
+#endif
+}
+
+void EditorRunNative::_run_native(int p_idx,const String& p_platform) {
+
+#if 0
+ Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(p_platform);
+ ERR_FAIL_COND(eep.is_null());
+ if (p_idx == -1) {
+ if (eep->get_device_count() == 1) {
+ menus[p_platform]->get_popup()->hide();
+ p_idx = 0;
+ } else {
+ return;
+ }
+ }
+ emit_signal("native_run");
+
+ int flags=0;
+ if (deploy_debug_remote)
+ flags|=EditorExportPlatform::EXPORT_REMOTE_DEBUG;
+ if (deploy_dumb)
+ flags|=EditorExportPlatform::EXPORT_DUMB_CLIENT;
+ if (debug_collisions)
+ flags|=EditorExportPlatform::EXPORT_VIEW_COLLISONS;
+ if (debug_navigation)
+ flags|=EditorExportPlatform::EXPORT_VIEW_NAVIGATION;
+
+ eep->run(p_idx,flags);
+
+#endif
+}
+
+void EditorRunNative::_bind_methods() {
+
+ ClassDB::bind_method("_run_native",&EditorRunNative::_run_native);
+
+ ADD_SIGNAL(MethodInfo("native_run"));
+}
+
+void EditorRunNative::set_deploy_dumb(bool p_enabled) {
+
+ deploy_dumb=p_enabled;
+}
+
+bool EditorRunNative::is_deploy_dumb_enabled() const{
+
+ return deploy_dumb;
+}
+
+void EditorRunNative::set_deploy_debug_remote(bool p_enabled) {
+
+ deploy_debug_remote=p_enabled;
+}
+
+bool EditorRunNative::is_deploy_debug_remote_enabled() const{
+
+ return deploy_debug_remote;
+}
+
+void EditorRunNative::set_debug_collisions(bool p_debug) {
+
+ debug_collisions=p_debug;
+}
+
+bool EditorRunNative::get_debug_collisions() const{
+
+ return debug_collisions;
+}
+
+void EditorRunNative::set_debug_navigation(bool p_debug) {
+
+ debug_navigation=p_debug;
+}
+
+bool EditorRunNative::get_debug_navigation() const{
+
+ return debug_navigation;
+}
+
+EditorRunNative::EditorRunNative()
+{
+ set_process(true);
+ first=true;
+ deploy_dumb=false;
+ deploy_debug_remote=false;
+ debug_collisions=false;
+ debug_navigation=false;
+
+}
diff --git a/tools/editor/editor_run_native.h b/editor/editor_run_native.h
index c62021148b..c62021148b 100644
--- a/tools/editor/editor_run_native.h
+++ b/editor/editor_run_native.h
diff --git a/editor/editor_run_script.cpp b/editor/editor_run_script.cpp
new file mode 100644
index 0000000000..77dc7bd4bf
--- /dev/null
+++ b/editor/editor_run_script.cpp
@@ -0,0 +1,97 @@
+/*************************************************************************/
+/* editor_run_script.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_run_script.h"
+
+#include "editor_node.h"
+
+
+void EditorScript::add_root_node(Node *p_node) {
+
+ if (!editor) {
+ EditorNode::add_io_error("EditorScript::add_root_node: "+TTR("Write your logic in the _run() method."));
+ return;
+ }
+
+ if (editor->get_edited_scene()) {
+ EditorNode::add_io_error("EditorScript::add_root_node: "+TTR("There is an edited scene already."));
+ return;
+ }
+
+ //editor->set_edited_scene(p_node);
+}
+
+Node *EditorScript::get_scene() {
+
+ if (!editor) {
+ EditorNode::add_io_error("EditorScript::get_scene: "+TTR("Write your logic in the _run() method."));
+ return NULL;
+ }
+
+ return editor->get_edited_scene();
+}
+
+void EditorScript::_run() {
+
+ Ref<Script> s = get_script();
+ ERR_FAIL_COND(!s.is_valid());
+ if (!get_script_instance()) {
+ EditorNode::add_io_error(TTR("Couldn't instance script:")+"\n "+s->get_path()+"\n"+TTR("Did you forget the 'tool' keyword?"));
+ return;
+
+ }
+
+ Variant::CallError ce;
+ ce.error=Variant::CallError::CALL_OK;
+ get_script_instance()->call("_run",NULL,0,ce);
+ if (ce.error!=Variant::CallError::CALL_OK) {
+
+ EditorNode::add_io_error(TTR("Couldn't run script:")+"\n "+s->get_path()+"\n"+TTR("Did you forget the '_run' method?"));
+ }
+}
+
+void EditorScript::set_editor(EditorNode *p_editor) {
+
+ editor=p_editor;
+}
+
+
+void EditorScript::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("add_root_node","node"),&EditorScript::add_root_node);
+ ClassDB::bind_method(D_METHOD("get_scene"),&EditorScript::get_scene);
+ BIND_VMETHOD( MethodInfo("_run") );
+
+
+}
+
+EditorScript::EditorScript() {
+
+ editor=NULL;
+}
+
diff --git a/tools/editor/editor_run_script.h b/editor/editor_run_script.h
index 3ab8525cc6..3ab8525cc6 100644
--- a/tools/editor/editor_run_script.h
+++ b/editor/editor_run_script.h
diff --git a/tools/editor/editor_scale.cpp b/editor/editor_scale.cpp
index 5687f97b22..5687f97b22 100644
--- a/tools/editor/editor_scale.cpp
+++ b/editor/editor_scale.cpp
diff --git a/tools/editor/editor_scale.h b/editor/editor_scale.h
index 035a5056c1..035a5056c1 100644
--- a/tools/editor/editor_scale.h
+++ b/editor/editor_scale.h
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
new file mode 100644
index 0000000000..f977a40243
--- /dev/null
+++ b/editor/editor_settings.cpp
@@ -0,0 +1,1158 @@
+/*************************************************************************/
+/* editor_settings.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http:/www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_settings.h"
+
+#include "os/os.h"
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "version.h"
+#include "scene/main/scene_main_loop.h"
+#include "scene/main/node.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "scene/main/viewport.h"
+#include "io/config_file.h"
+#include "editor_node.h"
+#include "global_config.h"
+#include "translations.h"
+#include "io/file_access_memory.h"
+#include "io/translation_loader_po.h"
+#include "io/compression.h"
+#include "os/keyboard.h"
+
+
+
+
+Ref<EditorSettings> EditorSettings::singleton=NULL;
+
+EditorSettings *EditorSettings::get_singleton() {
+
+ return singleton.ptr();
+}
+
+
+bool EditorSettings::_set(const StringName& p_name, const Variant& p_value) {
+
+ _THREAD_SAFE_METHOD_
+
+ if (p_name.operator String()=="shortcuts") {
+
+ Array arr=p_value;
+ ERR_FAIL_COND_V(arr.size() && arr.size()&1,true);
+ for(int i=0;i<arr.size();i+=2) {
+
+ String name = arr[i];
+ InputEvent shortcut = arr[i+1];
+
+ Ref<ShortCut> sc;
+ sc.instance();
+ sc->set_shortcut(shortcut);
+ add_shortcut(name,sc);
+ }
+
+ return true;
+ }
+
+ if (p_value.get_type()==Variant::NIL)
+ props.erase(p_name);
+ else {
+
+ if (props.has(p_name))
+ props[p_name].variant=p_value;
+ else
+ props[p_name]=VariantContainer(p_value,last_order++);
+
+ if (save_changed_setting) {
+ props[p_name].save=true;
+ }
+ }
+
+ emit_signal("settings_changed");
+ return true;
+}
+bool EditorSettings::_get(const StringName& p_name,Variant &r_ret) const {
+
+ _THREAD_SAFE_METHOD_
+
+ if (p_name.operator String()=="shortcuts") {
+
+ Array arr;
+ for (const Map<String,Ref<ShortCut> >::Element *E=shortcuts.front();E;E=E->next()) {
+
+ Ref<ShortCut> sc=E->get();
+
+ if (optimize_save) {
+ if (!sc->has_meta("original")) {
+ continue; //this came from settings but is not any longer used
+ }
+
+ InputEvent original = sc->get_meta("original");
+ if (sc->is_shortcut(original) || (original.type==InputEvent::NONE && sc->get_shortcut().type==InputEvent::NONE))
+ continue; //not changed from default, don't save
+ }
+
+ arr.push_back(E->key());
+ arr.push_back(sc->get_shortcut());
+ }
+ r_ret=arr;
+ return true;
+ }
+
+ const VariantContainer *v=props.getptr(p_name);
+ if (!v) {
+ print_line("EditorSettings::_get - Warning, not found: "+String(p_name));
+ return false;
+ }
+ r_ret = v->variant;
+ return true;
+}
+
+struct _EVCSort {
+
+ String name;
+ Variant::Type type;
+ int order;
+ bool save;
+
+ bool operator<(const _EVCSort& p_vcs) const{ return order< p_vcs.order; }
+};
+
+void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const {
+
+ _THREAD_SAFE_METHOD_
+
+ const String *k=NULL;
+ Set<_EVCSort> vclist;
+
+ while ((k=props.next(k))) {
+
+ const VariantContainer *v=props.getptr(*k);
+
+ if (v->hide_from_editor)
+ continue;
+
+ _EVCSort vc;
+ vc.name=*k;
+ vc.order=v->order;
+ vc.type=v->variant.get_type();
+ vc.save=v->save;
+
+
+ vclist.insert(vc);
+ }
+
+ for(Set<_EVCSort>::Element *E=vclist.front();E;E=E->next()) {
+
+ int pinfo = 0;
+ if (E->get().save || !optimize_save) {
+ pinfo|=PROPERTY_USAGE_STORAGE;
+ }
+
+ if (!E->get().name.begins_with("_") && !E->get().name.begins_with("projects/")) {
+ pinfo|=PROPERTY_USAGE_EDITOR;
+ } else {
+ pinfo|=PROPERTY_USAGE_STORAGE; //hiddens must always be saved
+ }
+
+ PropertyInfo pi(E->get().type, E->get().name);
+ pi.usage=pinfo;
+ if (hints.has(E->get().name))
+ pi=hints[E->get().name];
+
+
+ p_list->push_back( pi );
+ }
+
+ p_list->push_back(PropertyInfo(Variant::ARRAY,"shortcuts",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); //do not edit
+}
+
+bool EditorSettings::has(String p_var) const {
+
+ _THREAD_SAFE_METHOD_
+
+ return props.has(p_var);
+}
+
+void EditorSettings::erase(String p_var) {
+
+ _THREAD_SAFE_METHOD_
+
+ props.erase(p_var);
+}
+
+void EditorSettings::raise_order(const String& p_name) {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND(!props.has(p_name));
+ props[p_name].order=++last_order;
+
+
+}
+
+
+Variant _EDITOR_DEF( const String& p_var, const Variant& p_default) {
+
+ if (EditorSettings::get_singleton()->has(p_var))
+ return EditorSettings::get_singleton()->get(p_var);
+ EditorSettings::get_singleton()->set(p_var,p_default);
+ return p_default;
+
+}
+
+
+void EditorSettings::create() {
+
+
+ if (singleton.ptr())
+ return; //pointless
+
+ DirAccess *dir=NULL;
+ Variant meta;
+
+ String config_path;
+ String config_dir;
+ //String config_file="editor_settings.xml";
+ Ref<ConfigFile> extra_config = memnew(ConfigFile);
+
+ String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
+ DirAccess* d = DirAccess::create_for_path(exe_path);
+ bool self_contained = false;
+
+ if (d->file_exists(exe_path + "/._sc_")) {
+ self_contained = true;
+ extra_config->load(exe_path + "/._sc_");
+ } else if (d->file_exists(exe_path + "/_sc_")) {
+ self_contained = true;
+ extra_config->load(exe_path + "/_sc_");
+ }
+
+ if (self_contained) {
+ // editor is self contained
+ config_path = exe_path;
+ config_dir = "editor_data";
+ } else {
+
+ if (OS::get_singleton()->has_environment("APPDATA")) {
+ // Most likely under windows, save here
+ config_path=OS::get_singleton()->get_environment("APPDATA");
+ config_dir=String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
+ } else if (OS::get_singleton()->has_environment("HOME")) {
+
+ config_path=OS::get_singleton()->get_environment("HOME");
+ config_dir="."+String(_MKSTR(VERSION_SHORT_NAME)).to_lower();
+ }
+ };
+
+ ClassDB::register_class<EditorSettings>(); //otherwise it can't be unserialized
+ String config_file_path;
+
+ if (config_path!=""){
+
+ dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (dir->change_dir(config_path)!=OK) {
+ ERR_PRINT("Cannot find path for config directory!");
+ memdelete(dir);
+ goto fail;
+ }
+
+ if (dir->change_dir(config_dir)!=OK) {
+ dir->make_dir(config_dir);
+ if (dir->change_dir(config_dir)!=OK) {
+ ERR_PRINT("Cannot create config directory!");
+ memdelete(dir);
+ goto fail;
+ }
+ }
+
+ if (dir->change_dir("templates")!=OK) {
+ dir->make_dir("templates");
+ } else {
+
+ dir->change_dir("..");
+ }
+
+ if (dir->change_dir("text_editor_themes")!=OK) {
+ dir->make_dir("text_editor_themes");
+ } else {
+ dir->change_dir("..");
+ }
+
+ if (dir->change_dir("tmp")!=OK) {
+ dir->make_dir("tmp");
+ } else {
+
+ dir->change_dir("..");
+ }
+
+ if (dir->change_dir("config")!=OK) {
+ dir->make_dir("config");
+ } else {
+
+ dir->change_dir("..");
+ }
+
+ dir->change_dir("config");
+
+ String pcp=GlobalConfig::get_singleton()->get_resource_path();
+ if (pcp.ends_with("/"))
+ pcp=config_path.substr(0,pcp.size()-1);
+ pcp=pcp.get_file()+"-"+pcp.md5_text();
+
+ if (dir->change_dir(pcp)) {
+ dir->make_dir(pcp);
+ } else {
+ dir->change_dir("..");
+ }
+
+ dir->change_dir("..");
+
+ // path at least is validated, so validate config file
+
+ String config_file_name = "editor_settings-" + String(_MKSTR(VERSION_MAJOR)) + ".tres";
+ config_file_path = config_path + "/" + config_dir + "/" + config_file_name;
+
+ String open_path = config_file_path;
+
+ if (!dir->file_exists(config_file_name)) {
+
+ goto fail;
+ }
+
+ memdelete(dir);
+
+ singleton = ResourceLoader::load(open_path,"EditorSettings");
+
+ if (singleton.is_null()) {
+ WARN_PRINT("Could not open config file.");
+ goto fail;
+ }
+
+ singleton->save_changed_setting=true;
+ singleton->config_file_path=config_file_path;
+ singleton->project_config_path=pcp;
+ singleton->settings_path=config_path+"/"+config_dir;
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+
+ print_line("EditorSettings: Load OK!");
+ }
+
+ singleton->setup_language();
+ singleton->setup_network();
+ singleton->load_favorites();
+ singleton->list_text_editor_themes();
+
+ return;
+
+ }
+
+
+
+ fail:
+
+ // patch init projects
+ if (extra_config->has_section("init_projects")) {
+ Vector<String> list = extra_config->get_value("init_projects", "list");
+ for (int i=0; i<list.size(); i++) {
+
+ list[i] = exe_path + "/" + list[i];
+ };
+ extra_config->set_value("init_projects", "list", list);
+ };
+
+ singleton = Ref<EditorSettings>( memnew( EditorSettings ) );
+ singleton->save_changed_setting=true;
+ singleton->config_file_path=config_file_path;
+ singleton->settings_path=config_path+"/"+config_dir;
+ singleton->_load_defaults(extra_config);
+ singleton->setup_language();
+ singleton->setup_network();
+ singleton->list_text_editor_themes();
+
+
+}
+
+String EditorSettings::get_settings_path() const {
+
+ return settings_path;
+}
+
+
+
+void EditorSettings::setup_language() {
+
+ String lang = get("interface/editor_language");
+ if (lang=="en")
+ return;//none to do
+
+ for(int i=0;i<translations.size();i++) {
+ if (translations[i]->get_locale()==lang) {
+ TranslationServer::get_singleton()->set_tool_translation(translations[i]);
+ break;
+ }
+ }
+}
+
+void EditorSettings::setup_network() {
+
+ List<IP_Address> local_ip;
+ IP::get_singleton()->get_local_addresses(&local_ip);
+ String lip;
+ String hint;
+ String current=get("network/debug_host");
+
+ for(List<IP_Address>::Element *E=local_ip.front();E;E=E->next()) {
+
+ String ip = E->get();
+ if (ip=="127.0.0.1")
+ continue;
+
+ if (lip=="")
+ lip=ip;
+ if (ip==current)
+ lip=current; //so it saves
+ if (hint!="")
+ hint+=",";
+ hint+=ip;
+
+ }
+
+ set("network/debug_host",lip);
+ add_property_hint(PropertyInfo(Variant::STRING,"network/debug_host",PROPERTY_HINT_ENUM,hint));
+
+}
+
+
+void EditorSettings::save() {
+
+ //_THREAD_SAFE_METHOD_
+
+ if (!singleton.ptr())
+ return;
+
+ if (singleton->config_file_path=="") {
+ ERR_PRINT("Cannot save EditorSettings config, no valid path");
+ return;
+ }
+
+ Error err = ResourceSaver::save(singleton->config_file_path,singleton);
+
+ if (err!=OK) {
+ ERR_PRINT("Can't Save!");
+ return;
+ }
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ print_line("EditorSettings Save OK!");
+ }
+
+}
+
+void EditorSettings::destroy() {
+
+ if (!singleton.ptr())
+ return;
+ save();
+ singleton=Ref<EditorSettings>();
+}
+
+void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
+
+ _THREAD_SAFE_METHOD_
+
+
+ {
+ String lang_hint="en";
+ String host_lang = OS::get_singleton()->get_locale();
+
+ String best;
+
+ for(int i=0;i<translations.size();i++) {
+ String locale = translations[i]->get_locale();
+ lang_hint+=",";
+ lang_hint+=locale;
+
+ if (host_lang==locale) {
+ best=locale;
+ }
+
+ if (best==String() && host_lang.begins_with(locale)) {
+ best=locale;
+ }
+ }
+
+ if (best==String()) {
+ best="en";
+ }
+
+ set("interface/editor_language",best);
+ hints["interface/editor_language"]=PropertyInfo(Variant::STRING,"interface/editor_language",PROPERTY_HINT_ENUM,lang_hint,PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
+ }
+
+ set("interface/hidpi_mode",0);
+ hints["interface/hidpi_mode"]=PropertyInfo(Variant::INT,"interface/hidpi_mode",PROPERTY_HINT_ENUM,"Auto,VeryLoDPI,LoDPI,MidDPI,HiDPI",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
+ set("interface/show_script_in_scene_tabs",false);
+ set("interface/font_size",14);
+ hints["interface/font_size"]=PropertyInfo(Variant::INT,"interface/font_size",PROPERTY_HINT_RANGE,"10,40,1",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
+ set("interface/source_font_size",14);
+ hints["interface/source_font_size"]=PropertyInfo(Variant::INT,"interface/source_font_size",PROPERTY_HINT_RANGE,"8,96,1",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
+ set("interface/custom_font","");
+ hints["interface/custom_font"]=PropertyInfo(Variant::STRING,"interface/custom_font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
+ set("interface/custom_theme","");
+ hints["interface/custom_theme"]=PropertyInfo(Variant::STRING,"interface/custom_theme",PROPERTY_HINT_GLOBAL_FILE,"*.res,*.tres,*.theme",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
+
+
+ set("filesystem/directories/autoscan_project_path","");
+ hints["filesystem/directories/autoscan_project_path"]=PropertyInfo(Variant::STRING,"filesystem/directories/autoscan_project_path",PROPERTY_HINT_GLOBAL_DIR);
+ set("filesystem/directories/default_project_path","");
+ hints["filesystem/directories/default_project_path"]=PropertyInfo(Variant::STRING,"filesystem/directories/default_project_path",PROPERTY_HINT_GLOBAL_DIR);
+ set("filesystem/directories/default_project_export_path","");
+ hints["global/default_project_export_path"]=PropertyInfo(Variant::STRING,"global/default_project_export_path",PROPERTY_HINT_GLOBAL_DIR);
+ set("interface/show_script_in_scene_tabs",false);
+
+
+ set("text_editor/theme/color_theme","Default");
+ hints["text_editor/theme/color_theme"]=PropertyInfo(Variant::STRING,"text_editor/theme/color_theme",PROPERTY_HINT_ENUM,"Default");
+
+ set("text_editor/theme/line_spacing",4);
+
+
+ _load_default_text_editor_theme();
+
+ set("text_editor/highlighting/syntax_highlighting", true);
+
+ set("text_editor/highlighting/highlight_all_occurrences", true);
+ set("text_editor/cursor/scroll_past_end_of_file", false);
+
+ set("text_editor/indent/tab_size", 4);
+ hints["text_editor/indent/tab_size"]=PropertyInfo(Variant::INT,"text_editor/indent/tab_size",PROPERTY_HINT_RANGE,"1, 64, 1"); // size of 0 crashes.
+ set("text_editor/indent/draw_tabs", true);
+
+ set("text_editor/line_numbers/show_line_numbers", true);
+ set("text_editor/line_numbers/line_numbers_zero_padded", false);
+ set("text_editor/line_numbers/show_breakpoint_gutter", true);
+ set("text_editor/line_numbers/show_line_length_guideline", false);
+ set("text_editor/line_numbers/line_length_guideline_column", 80);
+ hints["text_editor/line_numbers/line_length_guideline_column"]=PropertyInfo(Variant::INT,"text_editor/line_numbers/line_length_guideline_column",PROPERTY_HINT_RANGE,"20, 160, 10");
+
+ set("text_editor/files/trim_trailing_whitespace_on_save", false);
+ set("text_editor/completion/idle_parse_delay",2);
+ set("text_editor/tools/create_signal_callbacks",true);
+ set("text_editor/files/autosave_interval_secs",0);
+
+ set("text_editor/cursor/block_caret", false);
+ set("text_editor/cursor/caret_blink", false);
+ set("text_editor/cursor/caret_blink_speed", 0.65);
+ hints["text_editor/cursor/caret_blink_speed"]=PropertyInfo(Variant::REAL,"text_editor/cursor/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1, 10, 0.1");
+
+ set("text_editor/theme/font","");
+ hints["text_editor/theme/font"]=PropertyInfo(Variant::STRING,"text_editor/theme/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt");
+ set("text_editor/completion/auto_brace_complete", false);
+ set("text_editor/files/restore_scripts_on_load",true);
+
+
+ //set("docks/scene_tree/display_old_action_buttons",false);
+ set("docks/scene_tree/start_create_dialog_fully_expanded",false);
+ set("docks/scene_tree/draw_relationship_lines",false);
+ set("docks/scene_tree/relationship_line_color",Color::html("464646"));
+
+ set("editors/grid_map/pick_distance", 5000.0);
+
+ set("editors/3d/grid_color",Color(0,1,0,0.2));
+ hints["editors/3d/grid_color"]=PropertyInfo(Variant::COLOR,"editors/3d/grid_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
+
+ set("editors/3d/default_fov",45.0);
+ set("editors/3d/default_z_near",0.1);
+ set("editors/3d/default_z_far",500.0);
+
+ set("editors/3d/navigation_scheme",0);
+ hints["editors/3d/navigation_scheme"]=PropertyInfo(Variant::INT,"editors/3d/navigation_scheme",PROPERTY_HINT_ENUM,"Godot,Maya,Modo");
+ set("editors/3d/zoom_style",0);
+ hints["editors/3d/zoom_style"]=PropertyInfo(Variant::INT,"editors/3d/zoom_style",PROPERTY_HINT_ENUM,"Vertical, Horizontal");
+ set("editors/3d/orbit_modifier",0);
+ hints["editors/3d/orbit_modifier"]=PropertyInfo(Variant::INT,"editors/3d/orbit_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
+ set("editors/3d/pan_modifier",1);
+ hints["editors/3d/pan_modifier"]=PropertyInfo(Variant::INT,"editors/3d/pan_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
+ set("editors/3d/zoom_modifier",4);
+ hints["editors/3d/zoom_modifier"]=PropertyInfo(Variant::INT,"editors/3d/zoom_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
+ set("editors/3d/emulate_numpad",false);
+ set("editors/3d/emulate_3_button_mouse", false);
+
+ set("editors/2d/bone_width",5);
+ set("editors/2d/bone_color1",Color(1.0,1.0,1.0,0.9));
+ set("editors/2d/bone_color2",Color(0.75,0.75,0.75,0.9));
+ set("editors/2d/bone_selected_color",Color(0.9,0.45,0.45,0.9));
+ set("editors/2d/bone_ik_color",Color(0.9,0.9,0.45,0.9));
+
+ set("editors/2d/keep_margins_when_changing_anchors", false);
+
+ set("run/window_placement/rect",0);
+ hints["run/window_placement/rect"]=PropertyInfo(Variant::INT,"run/window_placement/rect",PROPERTY_HINT_ENUM,"Default,Centered,Custom Position,Force Maximized,Force Full Screen");
+ String screen_hints=TTR("Default (Same as Editor)");
+ for(int i=0;i<OS::get_singleton()->get_screen_count();i++) {
+ screen_hints+=",Monitor "+itos(i+1);
+ }
+ set("run/window_placement/rect_custom_position",Vector2());
+ set("run/window_placement/screen",0);
+ hints["run/window_placement/screen"]=PropertyInfo(Variant::INT,"run/window_placement/screen",PROPERTY_HINT_ENUM,screen_hints);
+
+ set("filesystem/on_save/compress_binary_resources",true);
+ set("filesystem/on_save/save_modified_external_resources",true);
+ //set("filesystem/on_save/save_paths_as_relative",false);
+ //set("filesystem/on_save/save_paths_without_extension",false);
+
+ set("text_editor/tools/create_signal_callbacks",true);
+
+ set("filesystem/file_dialog/show_hidden_files", false);
+ set("filesystem/file_dialog/display_mode", 0);
+ hints["filesystem/file_dialog/display_mode"]=PropertyInfo(Variant::INT,"filesystem/file_dialog/display_mode",PROPERTY_HINT_ENUM,"Thumbnails,List");
+ set("filesystem/file_dialog/thumbnail_size", 64);
+ hints["filesystem/file_dialog/thumbnail_size"]=PropertyInfo(Variant::INT,"filesystem/file_dialog/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16");
+
+ set("docks/filesystem/display_mode", 0);
+ hints["docks/filesystem/display_mode"]=PropertyInfo(Variant::INT,"docks/filesystem/display_mode",PROPERTY_HINT_ENUM,"Thumbnails,List");
+ set("docks/filesystem/thumbnail_size", 64);
+ hints["docks/filesystem/thumbnail_size"]=PropertyInfo(Variant::INT,"docks/filesystem/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16");
+
+ set("editors/animation/autorename_animation_tracks",true);
+ set("editors/animation/confirm_insert_track",true);
+
+ set("docks/property_editor/texture_preview_width",48);
+ set("docks/property_editor/auto_refresh_interval",0.3);
+ set("text_editor/help/doc_path","");
+
+ set("filesystem/import/ask_save_before_reimport",false);
+
+ set("filesystem/import/pvrtc_texture_tool","");
+#ifdef WINDOWS_ENABLED
+ hints["filesystem/import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_GLOBAL_FILE,"*.exe");
+#else
+ hints["import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_GLOBAL_FILE,"");
+#endif
+ // TODO: Rename to "filesystem/import/pvrtc_fast_conversion" to match other names?
+ set("filesystem/import/pvrtc_fast_conversion",false);
+
+
+ set("run/auto_save/save_before_running",true);
+ set("run/output/always_clear_output_on_play",true);
+ set("run/output/always_open_output_on_play",true);
+ set("run/output/always_close_output_on_stop",false);
+ set("filesystem/resources/save_compressed_resources",true);
+ set("filesystem/resources/auto_reload_modified_images",true);
+
+ set("filesystem/import/automatic_reimport_on_sources_changed",true);
+
+ if (p_extra_config.is_valid()) {
+
+ if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) {
+
+ Vector<String> list = p_extra_config->get_value("init_projects", "list");
+ for (int i=0; i<list.size(); i++) {
+
+ String name = list[i].replace("/", "::");
+ set("projects/"+name, list[i]);
+ };
+ };
+
+ if (p_extra_config->has_section("presets")) {
+
+ List<String> keys;
+ p_extra_config->get_section_keys("presets", &keys);
+
+ for (List<String>::Element *E=keys.front();E;E=E->next()) {
+
+ String key = E->get();
+ Variant val = p_extra_config->get_value("presets", key);
+ set(key, val);
+ };
+ };
+ };
+
+
+
+
+}
+
+void EditorSettings::_load_default_text_editor_theme() {
+ set("text_editor/highlighting/background_color",Color::html("3b000000"));
+ set("text_editor/highlighting/completion_background_color", Color::html("2C2A32"));
+ set("text_editor/highlighting/completion_selected_color", Color::html("434244"));
+ set("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"));
+ set("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"));
+ set("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"));
+ set("text_editor/highlighting/caret_color",Color::html("aaaaaa"));
+ set("text_editor/highlighting/caret_background_color", Color::html("000000"));
+ set("text_editor/highlighting/line_number_color",Color::html("66aaaaaa"));
+ set("text_editor/highlighting/text_color",Color::html("aaaaaa"));
+ set("text_editor/highlighting/text_selected_color",Color::html("000000"));
+ set("text_editor/highlighting/keyword_color",Color::html("ffffb3"));
+ set("text_editor/highlighting/base_type_color",Color::html("a4ffd4"));
+ set("text_editor/highlighting/engine_type_color",Color::html("83d3ff"));
+ set("text_editor/highlighting/function_color",Color::html("66a2ce"));
+ set("text_editor/highlighting/member_variable_color",Color::html("e64e59"));
+ set("text_editor/highlighting/comment_color",Color::html("676767"));
+ set("text_editor/highlighting/string_color",Color::html("ef6ebe"));
+ set("text_editor/highlighting/number_color",Color::html("EB9532"));
+ set("text_editor/highlighting/symbol_color",Color::html("badfff"));
+ set("text_editor/highlighting/selection_color",Color::html("7b5dbe"));
+ set("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2));
+ set("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15));
+ set("text_editor/highlighting/line_length_guideline_color",Color(0.3,0.5,0.8,0.1));
+ set("text_editor/highlighting/mark_color", Color(1.0,0.4,0.4,0.4));
+ set("text_editor/highlighting/breakpoint_color", Color(0.8,0.8,0.4,0.2));
+ set("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15));
+ set("text_editor/highlighting/search_result_color",Color(0.05,0.25,0.05,1));
+ set("text_editor/highlighting/search_result_border_color",Color(0.1,0.45,0.1,1));
+}
+
+void EditorSettings::notify_changes() {
+
+ _THREAD_SAFE_METHOD_
+
+ SceneTree *sml=NULL;
+
+ if (OS::get_singleton()->get_main_loop())
+ sml = OS::get_singleton()->get_main_loop()->cast_to<SceneTree>();
+
+ if (!sml) {
+ return;
+ }
+
+ Node *root = sml->get_root()->get_child(0);
+
+ if (!root) {
+ return;
+ }
+ root->propagate_notification(NOTIFICATION_EDITOR_SETTINGS_CHANGED);
+
+}
+
+void EditorSettings::_add_property_info_bind(const Dictionary& p_info) {
+
+ ERR_FAIL_COND(!p_info.has("name"));
+ ERR_FAIL_COND(!p_info.has("type"));
+
+ PropertyInfo pinfo;
+ pinfo.name = p_info["name"];
+ ERR_FAIL_COND(!props.has(pinfo.name));
+ pinfo.type = Variant::Type(p_info["type"].operator int());
+ ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX);
+
+ if (p_info.has("hint"))
+ pinfo.hint = PropertyHint(p_info["hint"].operator int());
+ if (p_info.has("hint_string"))
+ pinfo.hint_string = p_info["hint_string"];
+
+ add_property_hint(pinfo);
+}
+
+void EditorSettings::add_property_hint(const PropertyInfo& p_hint) {
+
+ _THREAD_SAFE_METHOD_
+
+ hints[p_hint.name]=p_hint;
+}
+
+
+
+
+
+
+void EditorSettings::set_favorite_dirs(const Vector<String>& p_favorites) {
+
+ favorite_dirs=p_favorites;
+ FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"),FileAccess::WRITE);
+ if (f) {
+ for(int i=0;i<favorite_dirs.size();i++)
+ f->store_line(favorite_dirs[i]);
+ memdelete(f);
+ }
+
+}
+
+Vector<String> EditorSettings::get_favorite_dirs() const {
+
+ return favorite_dirs;
+}
+
+
+void EditorSettings::set_recent_dirs(const Vector<String>& p_recent) {
+
+ recent_dirs=p_recent;
+ FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"),FileAccess::WRITE);
+ if (f) {
+ for(int i=0;i<recent_dirs.size();i++)
+ f->store_line(recent_dirs[i]);
+ memdelete(f);
+ }
+}
+
+Vector<String> EditorSettings::get_recent_dirs() const {
+
+ return recent_dirs;
+}
+
+String EditorSettings::get_project_settings_path() const {
+
+
+ return get_settings_path().plus_file("config").plus_file(project_config_path);
+}
+
+
+void EditorSettings::load_favorites() {
+
+ FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"),FileAccess::READ);
+ if (f) {
+ String line = f->get_line().strip_edges();
+ while(line!="") {
+ favorite_dirs.push_back(line);
+ line = f->get_line().strip_edges();
+ }
+ memdelete(f);
+ }
+
+ f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"),FileAccess::READ);
+ if (f) {
+ String line = f->get_line().strip_edges();
+ while(line!="") {
+ recent_dirs.push_back(line);
+ line = f->get_line().strip_edges();
+ }
+ memdelete(f);
+ }
+
+}
+
+void EditorSettings::list_text_editor_themes() {
+ String themes="Default";
+ DirAccess *d = DirAccess::open(settings_path + "/text_editor_themes");
+ if (d) {
+ d->list_dir_begin();
+ String file = d->get_next();
+ while(file != String()) {
+ if (file.get_extension() == "tet" && file.get_basename().to_lower() != "default") {
+ themes += "," + file.get_basename();
+ }
+ file = d->get_next();
+ }
+ d->list_dir_end();
+ memdelete(d);
+ }
+ add_property_hint(PropertyInfo(Variant::STRING,"text_editor/theme/color_theme",PROPERTY_HINT_ENUM,themes));
+}
+
+void EditorSettings::load_text_editor_theme() {
+ if (get("text_editor/theme/color_theme") == "Default") {
+ _load_default_text_editor_theme(); // sorry for "Settings changed" console spam
+ return;
+ }
+
+ String theme_path = get_settings_path() + "/text_editor_themes/" + get("text_editor/theme/color_theme") + ".tet";
+
+ Ref<ConfigFile> cf = memnew( ConfigFile );
+ Error err = cf->load(theme_path);
+
+ if (err != OK) {
+ return;
+ }
+
+ List<String> keys;
+ cf->get_section_keys("color_theme", &keys);
+
+ for(List<String>::Element *E=keys.front();E;E=E->next()) {
+ String key = E->get();
+ String val = cf->get_value("color_theme", key);
+
+ // don't load if it's not already there!
+ if (has("text_editor/highlighting/" + key)) {
+
+ // make sure it is actually a color
+ if (val.is_valid_html_color() && key.find("color") >= 0) {
+ props["text_editor/highlighting/"+key].variant = Color::html(val); // change manually to prevent "Settings changed" console spam
+ }
+ }
+ }
+ emit_signal("settings_changed");
+ // if it doesn't load just use what is currently loaded
+}
+
+bool EditorSettings::import_text_editor_theme(String p_file) {
+
+ if (!p_file.ends_with(".tet")) {
+ return false;
+ } else {
+ if (p_file.get_file().to_lower() == "default.tet") {
+ return false;
+ }
+
+ DirAccess *d = DirAccess::open(settings_path + "/text_editor_themes");
+ if (d) {
+ d->copy(p_file, settings_path + "/text_editor_themes/" + p_file.get_file());
+ memdelete(d);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool EditorSettings::save_text_editor_theme() {
+
+ String p_file = get("text_editor/theme/color_theme");
+
+ if (p_file.get_file().to_lower() == "default") {
+ return false;
+ }
+ String theme_path = get_settings_path() + "/text_editor_themes/" + p_file + ".tet";
+ return _save_text_editor_theme(theme_path);
+}
+
+bool EditorSettings::save_text_editor_theme_as(String p_file) {
+ if (!p_file.ends_with(".tet")) {
+ p_file += ".tet";
+ }
+
+ if (p_file.get_file().to_lower() == "default.tet") {
+ return false;
+ }
+ if(_save_text_editor_theme(p_file)) {
+
+ // switch to theme is saved in the theme directory
+ list_text_editor_themes();
+ String theme_name = p_file.substr(0, p_file.length() - 4).get_file();
+
+ if (p_file.get_base_dir() == get_settings_path() + "/text_editor_themes") {
+ set("text_editor/theme/color_theme", theme_name);
+ load_text_editor_theme();
+ }
+ return true;
+ }
+ return false;
+}
+
+bool EditorSettings::_save_text_editor_theme(String p_file) {
+ String theme_section = "color_theme";
+ Ref<ConfigFile> cf = memnew( ConfigFile ); // hex is better?
+ cf->set_value(theme_section, "background_color", ((Color)get("text_editor/highlighting/background_color")).to_html());
+ cf->set_value(theme_section, "completion_background_color", ((Color)get("text_editor/highlighting/completion_background_color")).to_html());
+ cf->set_value(theme_section, "completion_selected_color", ((Color)get("text_editor/highlighting/completion_selected_color")).to_html());
+ cf->set_value(theme_section, "completion_existing_color", ((Color)get("text_editor/highlighting/completion_existing_color")).to_html());
+ cf->set_value(theme_section, "completion_scroll_color", ((Color)get("text_editor/highlighting/completion_scroll_color")).to_html());
+ cf->set_value(theme_section, "completion_font_color", ((Color)get("text_editor/highlighting/completion_font_color")).to_html());
+ cf->set_value(theme_section, "caret_color", ((Color)get("text_editor/highlighting/caret_color")).to_html());
+ cf->set_value(theme_section, "caret_background_color", ((Color)get("text_editor/highlighting/caret_background_color")).to_html());
+ cf->set_value(theme_section, "line_number_color", ((Color)get("text_editor/highlighting/line_number_color")).to_html());
+ cf->set_value(theme_section, "text_color", ((Color)get("text_editor/highlighting/text_color")).to_html());
+ cf->set_value(theme_section, "text_selected_color", ((Color)get("text_editor/highlighting/text_selected_color")).to_html());
+ cf->set_value(theme_section, "keyword_color", ((Color)get("text_editor/highlighting/keyword_color")).to_html());
+ cf->set_value(theme_section, "base_type_color", ((Color)get("text_editor/highlighting/base_type_color")).to_html());
+ cf->set_value(theme_section, "engine_type_color", ((Color)get("text_editor/highlighting/engine_type_color")).to_html());
+ cf->set_value(theme_section, "function_color", ((Color)get("text_editor/highlighting/function_color")).to_html());
+ cf->set_value(theme_section, "member_variable_color", ((Color)get("text_editor/highlighting/member_variable_color")).to_html());
+ cf->set_value(theme_section, "comment_color", ((Color)get("text_editor/highlighting/comment_color")).to_html());
+ cf->set_value(theme_section, "string_color", ((Color)get("text_editor/highlighting/string_color")).to_html());
+ cf->set_value(theme_section, "number_color", ((Color)get("text_editor/highlighting/number_color")).to_html());
+ cf->set_value(theme_section, "symbol_color", ((Color)get("text_editor/highlighting/symbol_color")).to_html());
+ cf->set_value(theme_section, "selection_color", ((Color)get("text_editor/highlighting/selection_color")).to_html());
+ cf->set_value(theme_section, "brace_mismatch_color", ((Color)get("text_editor/highlighting/brace_mismatch_color")).to_html());
+ cf->set_value(theme_section, "current_line_color", ((Color)get("text_editor/highlighting/current_line_color")).to_html());
+ cf->set_value(theme_section, "line_length_guideline_color", ((Color)get("text_editor/highlighting/line_length_guideline_color")).to_html());
+ cf->set_value(theme_section, "mark_color", ((Color)get("text_editor/highlighting/mark_color")).to_html());
+ cf->set_value(theme_section, "breakpoint_color", ((Color)get("text_editor/highlighting/breakpoint_color")).to_html());
+ cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/highlighting/word_highlighted_color")).to_html());
+ cf->set_value(theme_section, "search_result_color", ((Color)get("text_editor/highlighting/search_result_color")).to_html());
+ cf->set_value(theme_section, "search_result_border_color", ((Color)get("text_editor/highlighting/search_result_border_color")).to_html());
+
+
+ Error err = cf->save(p_file);
+
+ if (err == OK) {
+ return true;
+ }
+ return false;
+}
+
+
+void EditorSettings::add_shortcut(const String& p_name, Ref<ShortCut> &p_shortcut) {
+
+ shortcuts[p_name]=p_shortcut;
+}
+
+bool EditorSettings::is_shortcut(const String&p_name, const InputEvent &p_event) const{
+
+ const Map<String,Ref<ShortCut> >::Element *E=shortcuts.find(p_name);
+ if (!E) {
+ ERR_EXPLAIN("Unknown Shortcut: "+p_name);
+ ERR_FAIL_V(false);
+ }
+
+ return E->get()->is_shortcut(p_event);
+
+}
+
+Ref<ShortCut> EditorSettings::get_shortcut(const String&p_name) const{
+
+ const Map<String,Ref<ShortCut> >::Element *E=shortcuts.find(p_name);
+ if (!E)
+ return Ref<ShortCut>();
+
+ return E->get();
+}
+
+void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) {
+
+ for (const Map<String,Ref<ShortCut> >::Element*E=shortcuts.front();E;E=E->next()) {
+
+ r_shortcuts->push_back(E->key());
+ }
+}
+
+void EditorSettings::set_optimize_save(bool p_optimize) {
+
+ optimize_save=p_optimize;
+}
+
+Variant EditorSettings::get_project_metadata(const String& p_section, const String& p_key, Variant p_default) {
+ Ref<ConfigFile> cf = memnew( ConfigFile );
+ String path = get_project_settings_path().plus_file("project_metadata.cfg");
+ Error err = cf->load(path);
+ if (err != OK) {
+ return p_default;
+ }
+ return cf->get_value(p_section, p_key, p_default);
+}
+
+void EditorSettings::set_project_metadata(const String& p_section, const String& p_key, Variant p_data)
+{
+ Ref<ConfigFile> cf = memnew( ConfigFile );
+ String path = get_project_settings_path().plus_file("project_metadata.cfg");
+ cf->load(path);
+ cf->set_value(p_section, p_key, p_data);
+ cf->save(path);
+}
+
+void EditorSettings::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("erase","property"),&EditorSettings::erase);
+ ClassDB::bind_method(D_METHOD("get_settings_path"),&EditorSettings::get_settings_path);
+ ClassDB::bind_method(D_METHOD("get_project_settings_path"),&EditorSettings::get_project_settings_path);
+
+ ClassDB::bind_method(D_METHOD("add_property_info", "info"),&EditorSettings::_add_property_info_bind);
+
+ ClassDB::bind_method(D_METHOD("set_favorite_dirs","dirs"),&EditorSettings::set_favorite_dirs);
+ ClassDB::bind_method(D_METHOD("get_favorite_dirs"),&EditorSettings::get_favorite_dirs);
+
+ ClassDB::bind_method(D_METHOD("set_recent_dirs","dirs"),&EditorSettings::set_recent_dirs);
+ ClassDB::bind_method(D_METHOD("get_recent_dirs"),&EditorSettings::get_recent_dirs);
+
+ ADD_SIGNAL(MethodInfo("settings_changed"));
+
+}
+
+EditorSettings::EditorSettings() {
+
+
+ //singleton=this;
+ last_order=0;
+ optimize_save=true;
+ save_changed_setting=true;
+
+ EditorTranslationList *etl=_editor_translations;
+
+ while(etl->data) {
+
+ Vector<uint8_t> data;
+ data.resize(etl->uncomp_size);
+ Compression::decompress(data.ptr(),etl->uncomp_size,etl->data,etl->comp_size,Compression::MODE_DEFLATE);
+
+ FileAccessMemory *fa = memnew (FileAccessMemory);
+ fa->open_custom(data.ptr(),data.size());
+
+ Ref<Translation> tr = TranslationLoaderPO::load_translation(fa,NULL,"translation_"+String(etl->lang));
+
+ if (tr.is_valid()) {
+ tr->set_locale(etl->lang);
+ translations.push_back(tr);
+ }
+
+ etl++;
+
+ }
+
+ _load_defaults();
+
+
+}
+
+
+EditorSettings::~EditorSettings() {
+
+ //singleton=NULL;
+}
+
+Ref<ShortCut> ED_GET_SHORTCUT(const String& p_path) {
+
+ Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
+ if (!sc.is_valid()) {
+ ERR_EXPLAIN("Used ED_GET_SHORTCUT with invalid shortcut: "+p_path);
+ ERR_FAIL_COND_V(!sc.is_valid(),sc);
+ }
+
+ return sc;
+}
+
+Ref<ShortCut> ED_SHORTCUT(const String& p_path,const String& p_name,uint32_t p_keycode) {
+
+ InputEvent ie;
+ if (p_keycode) {
+ ie.type=InputEvent::KEY;
+ ie.key.unicode=p_keycode&KEY_CODE_MASK;
+ ie.key.scancode=p_keycode&KEY_CODE_MASK;
+ ie.key.mod.shift=bool(p_keycode&KEY_MASK_SHIFT);
+ ie.key.mod.alt=bool(p_keycode&KEY_MASK_ALT);
+ ie.key.mod.control=bool(p_keycode&KEY_MASK_CTRL);
+ ie.key.mod.meta=bool(p_keycode&KEY_MASK_META);
+
+ }
+
+ Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
+ if (sc.is_valid()) {
+
+ sc->set_name(p_name); //keep name (the ones that come from disk have no name)
+ sc->set_meta("original",ie); //to compare against changes
+ return sc;
+ }
+
+ sc.instance();
+ sc->set_name(p_name);
+ sc->set_shortcut(ie);
+ sc->set_meta("original",ie); //to compare against changes
+ EditorSettings::get_singleton()->add_shortcut(p_path,sc);
+
+ return sc;
+}
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
new file mode 100644
index 0000000000..809389eb40
--- /dev/null
+++ b/editor/editor_settings.h
@@ -0,0 +1,180 @@
+/*************************************************************************/
+/* editor_settings.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_SETTINGS_H
+#define EDITOR_SETTINGS_H
+
+#include "object.h"
+
+#include "resource.h"
+#include "os/thread_safe.h"
+#include "core/io/config_file.h"
+#include "translation.h"
+#include "scene/gui/input_action.h"
+
+class EditorPlugin;
+
+class EditorSettings : public Resource {
+
+ GDCLASS( EditorSettings, Resource );
+private:
+ _THREAD_SAFE_CLASS_
+
+public:
+ struct Plugin {
+
+ EditorPlugin *instance;
+ String path;
+ String name;
+ String author;
+ String version;
+ String description;
+ bool installs;
+ String script;
+ Vector<String> install_files;
+ };
+private:
+
+ struct VariantContainer {
+ int order;
+ Variant variant;
+ bool hide_from_editor;
+ bool save;
+ VariantContainer(){ order=0; hide_from_editor=false; save=false;}
+ VariantContainer(const Variant& p_variant, int p_order) { variant=p_variant; order=p_order; hide_from_editor=false; }
+ };
+
+ HashMap<String,PropertyInfo> hints;
+ int last_order;
+ HashMap<String,VariantContainer> props;
+ String resource_path;
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+
+ static Ref<EditorSettings> singleton;
+
+ String config_file_path;
+ String settings_path;
+
+ Ref<Resource> clipboard;
+
+
+ bool save_changed_setting;
+
+ bool optimize_save; //do not save stuff that came from config but was not set from engine
+
+ void _load_defaults(Ref<ConfigFile> p_extra_config = NULL);
+ void _load_default_text_editor_theme();
+
+ bool _save_text_editor_theme(String p_file);
+
+ String project_config_path;
+
+ Vector<String> favorite_dirs;
+ Vector<String> recent_dirs;
+
+ Vector<Ref<Translation> > translations;
+
+ Map<String,Ref<ShortCut> > shortcuts;
+
+ void _add_property_info_bind(const Dictionary& p_info);
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ enum {
+ NOTIFICATION_EDITOR_SETTINGS_CHANGED=10000
+ };
+
+
+ bool has(String p_var) const;
+ 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;
+
+
+ void setup_language();
+ void setup_network();
+
+ void raise_order(const String& p_name);
+ static void create();
+ static void save();
+ static void destroy();
+
+ void notify_changes();
+
+ void set_resource_clipboard(const Ref<Resource>& p_resource) { clipboard=p_resource; }
+ Ref<Resource> get_resource_clipboard() const { return clipboard; }
+
+ void add_property_hint(const PropertyInfo& p_hint);
+
+ void set_favorite_dirs(const Vector<String>& p_favorite_dirs);
+ Vector<String> get_favorite_dirs() const;
+
+ void set_recent_dirs(const Vector<String>& p_recent_dirs);
+ Vector<String> get_recent_dirs() const;
+
+ void load_favorites();
+
+ void list_text_editor_themes();
+ void load_text_editor_theme();
+ bool import_text_editor_theme(String p_file);
+ bool save_text_editor_theme();
+ bool save_text_editor_theme_as(String p_file);
+
+ void add_shortcut(const String& p_name,Ref<ShortCut>& p_shortcut);
+ bool is_shortcut(const String&p_name,const InputEvent& p_event) const;
+ Ref<ShortCut> get_shortcut(const String&p_name) const;
+ void get_shortcut_list(List<String> *r_shortcuts);
+
+ void set_optimize_save(bool p_optimize);
+
+ Variant get_project_metadata(const String& p_section, const String& p_key, Variant p_default);
+ void set_project_metadata(const String& p_section, const String& p_key, Variant p_data);
+
+ EditorSettings();
+ ~EditorSettings();
+
+};
+
+//not a macro any longer
+
+#define EDITOR_DEF(m_var,m_val) _EDITOR_DEF(m_var,Variant(m_val))
+Variant _EDITOR_DEF( const String& p_var, const Variant& p_default);
+
+#define ED_IS_SHORTCUT(p_name,p_ev) (EditorSettings::get_singleton()->is_shortcut(p_name,p_ev))
+Ref<ShortCut> ED_SHORTCUT(const String& p_path,const String& p_name,uint32_t p_keycode=0);
+Ref<ShortCut> ED_GET_SHORTCUT(const String& p_path);
+
+#endif // EDITOR_SETTINGS_H
diff --git a/editor/editor_sub_scene.cpp b/editor/editor_sub_scene.cpp
new file mode 100644
index 0000000000..917560b540
--- /dev/null
+++ b/editor/editor_sub_scene.cpp
@@ -0,0 +1,238 @@
+/*************************************************************************/
+/* editor_sub_scene.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_sub_scene.h"
+
+#include "scene/gui/margin_container.h"
+#include "scene/resources/packed_scene.h"
+
+void EditorSubScene::_path_selected(const String& p_path) {
+
+ path->set_text(p_path);
+ _path_changed(p_path);
+
+}
+
+void EditorSubScene::_path_changed(const String& p_path) {
+
+ tree->clear();
+
+
+ if (scene) {
+ memdelete(scene);
+ scene=NULL;
+ }
+
+ if (p_path=="")
+ return;
+
+ Ref<PackedScene> ps = ResourceLoader::load(p_path,"PackedScene");
+
+ if (ps.is_null())
+ return;
+
+ scene = ps->instance();
+ if (!scene)
+ return;
+
+ _fill_tree(scene,NULL);
+
+
+
+}
+
+void EditorSubScene::_path_browse() {
+
+ file_dialog->popup_centered_ratio();
+}
+
+
+void EditorSubScene::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ if (!is_visible_in_tree()) {
+
+
+ }
+ }
+}
+
+
+void EditorSubScene::_fill_tree(Node* p_node,TreeItem *p_parent) {
+
+ TreeItem *it = tree->create_item(p_parent);
+ it->set_metadata(0,p_node);
+ it->set_text(0,p_node->get_name());
+ it->set_editable(0,false);
+ it->set_selectable(0,true);
+ if (has_icon(p_node->get_class(),"EditorIcons")) {
+ it->set_icon(0,get_icon(p_node->get_class(),"EditorIcons"));
+
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ Node *c = p_node->get_child(i);
+ if (c->get_owner()!=scene)
+ continue;
+ _fill_tree(c,it);
+ }
+
+}
+
+
+void EditorSubScene::ok_pressed() {
+
+
+ TreeItem *s = tree->get_selected();
+ if (!s)
+ return;
+ Node *selnode = s->get_metadata(0);
+ if (!selnode)
+ return;
+ emit_signal("subscene_selected");
+ hide();
+ clear();
+
+
+}
+
+
+void EditorSubScene::_reown(Node* p_node,List<Node*> *p_to_reown) {
+
+ if (p_node==scene) {
+
+ scene->set_filename("");
+ p_to_reown->push_back(p_node);
+ } else if (p_node->get_owner()==scene){
+
+ p_to_reown->push_back(p_node);
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+ Node *c=p_node->get_child(i);
+ _reown(c,p_to_reown);
+ }
+}
+
+void EditorSubScene::move(Node* p_new_parent, Node* p_new_owner) {
+
+ if (!scene) {
+ return;
+ }
+ TreeItem *s = tree->get_selected();
+ if (!s) {
+ return;
+ }
+
+ Node *selnode = s->get_metadata(0);
+ if (!selnode) {
+ return;
+ }
+
+ List<Node*> to_reown;
+ _reown(selnode,&to_reown);
+
+ if (selnode!=scene) {
+ selnode->get_parent()->remove_child(selnode);
+ }
+
+ p_new_parent->add_child(selnode);
+ for (List<Node*>::Element *E=to_reown.front();E;E=E->next()) {
+ E->get()->set_owner(p_new_owner);
+ }
+
+ if (selnode!=scene) {
+ memdelete(scene);
+ }
+ scene=NULL;
+
+
+ //return selnode;
+
+
+}
+
+void EditorSubScene::clear() {
+
+ path->set_text("");
+ _path_changed("");
+}
+
+void EditorSubScene::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_path_selected"),&EditorSubScene::_path_selected);
+ ClassDB::bind_method(D_METHOD("_path_changed"),&EditorSubScene::_path_changed);
+ ClassDB::bind_method(D_METHOD("_path_browse"),&EditorSubScene::_path_browse);
+ ADD_SIGNAL( MethodInfo("subscene_selected"));
+
+}
+
+
+EditorSubScene::EditorSubScene() {
+
+ scene=NULL;
+
+ set_title(TTR("Select Node(s) to Import"));
+ set_hide_on_ok(false);
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+ //set_child_rect(vb);
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ path = memnew( LineEdit );
+ path->connect("text_entered",this,"_path_changed");
+ hb->add_child(path);
+ path->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *b = memnew( Button );
+ b->set_text(" .. ");
+ hb->add_child(b);
+ b->connect("pressed",this,"_path_browse");
+ vb->add_margin_child(TTR("Scene Path:"),hb);
+
+ tree = memnew( Tree );
+ tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ vb->add_margin_child(TTR("Import From Node:"),tree,true);
+ tree->connect("item_activated",this,"_ok",make_binds(),CONNECT_DEFERRED);
+
+ file_dialog = memnew( EditorFileDialog );
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
+
+ for(List<String>::Element *E = extensions.front();E;E=E->next() ) {
+
+ file_dialog->add_filter("*."+E->get());
+ }
+
+ file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ add_child(file_dialog);
+ file_dialog->connect("file_selected",this,"_path_selected");
+
+}
diff --git a/editor/editor_sub_scene.h b/editor/editor_sub_scene.h
new file mode 100644
index 0000000000..46cdceafa5
--- /dev/null
+++ b/editor/editor_sub_scene.h
@@ -0,0 +1,69 @@
+/*************************************************************************/
+/* editor_sub_scene.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_SUB_SCENE_H
+#define EDITOR_SUB_SCENE_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+#include "editor/editor_file_dialog.h"
+
+class EditorSubScene : public ConfirmationDialog {
+
+ GDCLASS(EditorSubScene,ConfirmationDialog);
+
+
+ LineEdit *path;
+ Tree *tree;
+ Node *scene;
+
+ EditorFileDialog *file_dialog;
+
+ void _fill_tree(Node* p_node,TreeItem *p_parent);
+ void _reown(Node* p_node,List<Node*> *p_to_reown);
+
+ void ok_pressed();
+
+
+protected:
+
+
+ void _notification(int p_what);
+ static void _bind_methods();
+ void _path_browse();
+ void _path_selected(const String& p_path);
+ void _path_changed(const String& p_path);
+
+public:
+
+ void move(Node* p_new_parent, Node* p_new_owner);
+ void clear();
+ EditorSubScene();
+};
+
+#endif // EDITOR_SUB_SCENE_H
diff --git a/tools/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 7657996b81..7657996b81 100644
--- a/tools/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
diff --git a/tools/editor/editor_themes.h b/editor/editor_themes.h
index bf15420917..bf15420917 100644
--- a/tools/editor/editor_themes.h
+++ b/editor/editor_themes.h
diff --git a/editor/file_type_cache.cpp b/editor/file_type_cache.cpp
new file mode 100644
index 0000000000..891669db13
--- /dev/null
+++ b/editor/file_type_cache.cpp
@@ -0,0 +1,108 @@
+/*************************************************************************/
+/* file_type_cache.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "file_type_cache.h"
+
+#include "global_config.h"
+#include "os/file_access.h"
+
+FileTypeCache* FileTypeCache::singleton=NULL;
+
+bool FileTypeCache::has_file(const String& p_path) const {
+
+ GLOBAL_LOCK_FUNCTION
+ return file_type_map.has(p_path);
+}
+
+String FileTypeCache::get_file_type(const String& p_path) const{
+
+ GLOBAL_LOCK_FUNCTION
+ ERR_FAIL_COND_V(!file_type_map.has(p_path),"");
+ return file_type_map[p_path];
+
+}
+void FileTypeCache::set_file_type(const String& p_path,const String& p_type){
+
+ GLOBAL_LOCK_FUNCTION
+ file_type_map[p_path]=p_type;
+}
+
+void FileTypeCache::load() {
+
+ GLOBAL_LOCK_FUNCTION
+ String project=GlobalConfig::get_singleton()->get_resource_path();
+ FileAccess *f =FileAccess::open(project+"/file_type_cache.cch",FileAccess::READ);
+
+ if (!f) {
+
+ WARN_PRINT("Can't open file_type_cache.cch.");
+ return;
+ }
+
+ file_type_map.clear();
+ while(!f->eof_reached()) {
+
+ String path=f->get_line();
+ if (f->eof_reached())
+ break;
+ String type=f->get_line();
+ set_file_type(path,type);
+ }
+
+ memdelete(f);
+
+}
+
+void FileTypeCache::save() {
+
+ GLOBAL_LOCK_FUNCTION
+ String project=GlobalConfig::get_singleton()->get_resource_path();
+ FileAccess *f =FileAccess::open(project+"/file_type_cache.cch",FileAccess::WRITE);
+ if (!f) {
+
+ ERR_EXPLAIN(TTR("Can't open file_type_cache.cch for writing, not saving file type cache!"));
+ ERR_FAIL();
+ }
+
+ const String *K=NULL;
+
+ while((K=file_type_map.next(K))) {
+
+ f->store_line(*K);
+ f->store_line(file_type_map[*K]);
+ }
+
+ memdelete(f);
+
+}
+
+FileTypeCache::FileTypeCache() {
+
+ ERR_FAIL_COND(singleton);
+ singleton=this;
+}
diff --git a/tools/editor/file_type_cache.h b/editor/file_type_cache.h
index 25755f168c..25755f168c 100644
--- a/tools/editor/file_type_cache.h
+++ b/editor/file_type_cache.h
diff --git a/tools/editor/fileserver/SCsub b/editor/fileserver/SCsub
index f1fa50148f..f1fa50148f 100644
--- a/tools/editor/fileserver/SCsub
+++ b/editor/fileserver/SCsub
diff --git a/tools/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp
index 2e5dbf6248..2e5dbf6248 100644
--- a/tools/editor/fileserver/editor_file_server.cpp
+++ b/editor/fileserver/editor_file_server.cpp
diff --git a/tools/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h
index 31f8ae84b8..31f8ae84b8 100644
--- a/tools/editor/fileserver/editor_file_server.h
+++ b/editor/fileserver/editor_file_server.h
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
new file mode 100644
index 0000000000..bce0e9148a
--- /dev/null
+++ b/editor/filesystem_dock.cpp
@@ -0,0 +1,1891 @@
+/*************************************************************************/
+/* filesystem_dock.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "filesystem_dock.h"
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "global_config.h"
+#include "io/resource_loader.h"
+#include "os/os.h"
+#include "editor_node.h"
+#include "editor_settings.h"
+#include "scene/main/viewport.h"
+
+bool FileSystemDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir) {
+
+ TreeItem *item = tree->create_item(p_parent);
+ String dname=p_dir->get_name();
+ if (dname=="")
+ dname="res://";
+ else {
+ // collapse every tree item but the root folder
+ item->set_collapsed(true);
+ }
+
+ item->set_text(0,dname);
+ item->set_icon(0,get_icon("Folder","EditorIcons"));
+ item->set_selectable(0,true);
+ String lpath = p_dir->get_path();
+ if (lpath!="res://" && lpath.ends_with("/")) {
+ lpath=lpath.substr(0,lpath.length()-1);
+ }
+ item->set_metadata(0,lpath);
+ if (lpath==path) {
+ item->select(0);
+ }
+
+ for(int i=0;i<p_dir->get_subdir_count();i++)
+ _create_tree(item,p_dir->get_subdir(i));
+
+ return true;
+}
+
+
+void FileSystemDock::_update_tree() {
+
+ tree->clear();
+ updating_tree=true;
+ TreeItem *root = tree->create_item();
+ TreeItem *favorites = tree->create_item(root);
+ favorites->set_icon(0, get_icon("Favorites","EditorIcons") );
+ favorites->set_text(0,TTR("Favorites:"));
+ favorites->set_selectable(0,false);
+ Vector<String> faves = EditorSettings::get_singleton()->get_favorite_dirs();
+ for(int i=0;i<faves.size();i++) {
+ if (!faves[i].begins_with("res://"))
+ continue;
+
+ TreeItem *ti = tree->create_item(favorites);
+ String fv = faves[i];
+ if (fv=="res://")
+ ti->set_text(0,"/");
+ else
+ ti->set_text(0,faves[i].get_file());
+ ti->set_icon(0,get_icon("Folder","EditorIcons"));
+ ti->set_selectable(0,true);
+ ti->set_metadata(0,faves[i]);
+ }
+
+ _create_tree(root,EditorFileSystem::get_singleton()->get_filesystem());
+ updating_tree=false;
+
+}
+
+
+void FileSystemDock::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_RESIZED: {
+
+
+ bool new_mode = get_size().height < get_viewport_rect().size.height*3/4;
+
+ if (new_mode != split_mode ) {
+
+ split_mode=new_mode;
+
+ //print_line("SPLIT MODE? "+itos(split_mode));
+ if (split_mode) {
+
+ file_list_vb->hide();
+ tree->set_custom_minimum_size(Size2(0,0));
+ tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ button_back->show();
+ } else {
+
+ tree->show();
+ file_list_vb->show();
+ tree->set_custom_minimum_size(Size2(0,200)*EDSCALE);
+ tree->set_v_size_flags(SIZE_FILL);
+ button_back->hide();
+ if (!EditorFileSystem::get_singleton()->is_scanning()) {
+ _fs_changed();
+ }
+ }
+ }
+
+
+ } break;
+ case NOTIFICATION_ENTER_TREE: {
+
+ if (initialized)
+ return;
+ initialized=true;
+
+ EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_fs_changed");
+ EditorResourcePreview::get_singleton()->connect("preview_invalidated",this,"_preview_invalidated");
+
+ button_reload->set_icon( get_icon("Reload","EditorIcons"));
+ button_favorite->set_icon( get_icon("Favorites","EditorIcons"));
+ //button_instance->set_icon( get_icon("Add","EditorIcons"));
+ //button_open->set_icon( get_icon("Folder","EditorIcons"));
+ button_back->set_icon( get_icon("Filesystem","EditorIcons"));
+ if (display_mode == DISPLAY_THUMBNAILS) {
+ button_display_mode->set_icon(get_icon("FileList","EditorIcons"));
+ } else {
+ button_display_mode->set_icon(get_icon("FileThumbnail","EditorIcons"));
+ }
+ button_display_mode->connect("pressed",this,"_change_file_display");
+ //file_options->set_icon( get_icon("Tools","EditorIcons"));
+ files->connect("item_activated",this,"_select_file");
+ button_hist_next->connect("pressed",this,"_fw_history");
+ button_hist_prev->connect("pressed",this,"_bw_history");
+ search_icon->set_texture( get_icon("Zoom","EditorIcons"));
+
+ button_hist_next->set_icon( get_icon("Forward","EditorIcons"));
+ button_hist_prev->set_icon( get_icon("Back","EditorIcons"));
+ file_options->connect("id_pressed",this,"_file_option");
+ folder_options->connect("id_pressed",this,"_folder_option");
+
+
+ button_back->connect("pressed",this,"_go_to_tree",varray(),CONNECT_DEFERRED);
+ current_path->connect("text_entered",this,"_go_to_dir");
+ _update_tree(); //maybe it finished already
+
+ if (EditorFileSystem::get_singleton()->is_scanning()) {
+ _set_scanning_mode();
+ }
+
+ } break;
+ case NOTIFICATION_PROCESS: {
+ if (EditorFileSystem::get_singleton()->is_scanning()) {
+ scanning_progress->set_value(EditorFileSystem::get_singleton()->get_scanning_progress()*100);
+ }
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+
+ } break;
+ case NOTIFICATION_DRAG_BEGIN: {
+
+ Dictionary dd = get_viewport()->gui_get_drag_data();
+ if (tree->is_visible_in_tree() && dd.has("type") ) {
+ if ( (String(dd["type"])=="files") || (String(dd["type"])=="files_and_dirs") || (String(dd["type"])=="resource")) {
+ tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
+ }
+ if ( (String(dd["type"])=="favorite") ) {
+ tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
+ }
+ }
+
+
+ } break;
+ case NOTIFICATION_DRAG_END: {
+
+ tree->set_drop_mode_flags(0);
+
+ } break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+
+ int new_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"));
+
+ if (new_mode != display_mode) {
+ set_display_mode(new_mode);
+ } else {
+ _update_files(true);
+ }
+ } break;
+ }
+
+}
+
+
+
+
+void FileSystemDock::_dir_selected() {
+
+ TreeItem *ti = tree->get_selected();
+ if (!ti)
+ return;
+ String dir = ti->get_metadata(0);
+ bool found=false;
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
+ for(int i=0;i<favorites.size();i++) {
+
+ if (favorites[i]==dir) {
+ found=true;
+ break;
+ }
+ }
+
+
+ button_favorite->set_pressed(found);
+
+ if (!split_mode) {
+ _open_pressed(); //go directly to dir
+ }
+
+}
+
+
+void FileSystemDock::_favorites_pressed() {
+
+ TreeItem *sel = tree->get_selected();
+ if (!sel)
+ return ;
+ String dir = sel->get_metadata(0);
+
+ int idx = -1;
+ Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
+ for(int i=0;i<favorites.size();i++) {
+
+ if (favorites[i]==dir) {
+ idx=i;
+ break;
+ }
+ }
+
+ if (button_favorite->is_pressed() && idx==-1) {
+ favorites.push_back(dir);
+ EditorSettings::get_singleton()->set_favorite_dirs(favorites);
+ _update_tree();
+ } else if (!button_favorite->is_pressed() && idx!=-1) {
+ favorites.remove(idx);
+ EditorSettings::get_singleton()->set_favorite_dirs(favorites);
+ _update_tree();
+ }
+
+}
+
+String FileSystemDock::get_selected_path() const {
+
+ TreeItem *sel = tree->get_selected();
+ if (!sel)
+ return "";
+ String path = sel->get_metadata(0);
+ return "res://"+path;
+}
+
+String FileSystemDock::get_current_path() const {
+
+ return path;
+}
+
+void FileSystemDock::navigate_to_path(const String& p_path) {
+ // If the path is a file, do not only go to the directory in the tree, also select the file in the file list.
+ String dir_path="";
+ String file_name="";
+ DirAccess* dirAccess=DirAccess::open("res://");
+ if (dirAccess->file_exists(p_path)) {
+ dir_path=p_path.get_base_dir();
+ file_name=p_path.get_file();
+ } else if (dirAccess->dir_exists(p_path)) {
+ dir_path=p_path;
+ } else {
+ ERR_EXPLAIN(TTR("Cannot navigate to '" + p_path + "' as it has not been found in the file system!"));
+ ERR_FAIL();
+ }
+
+ path=dir_path;
+ _update_tree();
+ tree->ensure_cursor_is_visible();
+
+ if (!file_name.empty()) {
+ _open_pressed(); // Seems to be the only way to get into the file view. This also pushes to history.
+
+ // Focus the given file.
+ for (int i=0; i<files->get_item_count(); i++) {
+ if (files->get_item_text(i) == file_name) {
+ files->select(i,true);
+ files->ensure_current_is_visible();
+ break;
+ }
+ }
+ }
+}
+
+void FileSystemDock::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
+
+ bool valid=false;
+
+ if (search_box->is_visible()) {
+ valid=true;
+ } else {
+ valid=(path==p_path.get_base_dir());
+ }
+
+ if (p_preview.is_valid() && valid) {
+
+ Array uarr=p_udata;
+ int idx=uarr[0];
+ String file=uarr[1];
+ if (idx>=files->get_item_count())
+ return;
+ if (files->get_item_text(idx)!=file)
+ return;
+ String fpath = files->get_item_metadata(idx);
+ if (fpath!=p_path)
+ return;
+ files->set_item_icon(idx,p_preview);
+
+ }
+
+}
+
+void FileSystemDock::_change_file_display() {
+
+ if (button_display_mode->is_pressed()) {
+ display_mode = DISPLAY_LIST;
+ button_display_mode->set_icon( get_icon("FileThumbnail","EditorIcons"));
+ } else {
+ display_mode = DISPLAY_THUMBNAILS;
+ button_display_mode->set_icon( get_icon("FileList","EditorIcons"));
+ }
+
+ EditorSettings::get_singleton()->set("docks/filesystem/display_mode", display_mode);
+
+ _update_files(true);
+}
+
+void FileSystemDock::_search(EditorFileSystemDirectory *p_path,List<FileInfo>* matches,int p_max_items) {
+
+ if (matches->size()>p_max_items)
+ return;
+
+ for(int i=0;i<p_path->get_subdir_count();i++) {
+ _search(p_path->get_subdir(i),matches,p_max_items);
+
+ }
+
+ String match = search_box->get_text();
+
+ for(int i=0;i<p_path->get_file_count();i++) {
+ String file = p_path->get_file(i);
+
+ if (file.find(match)!=-1) {
+
+ FileInfo fi;
+ fi.name=file;
+ fi.type=p_path->get_file_type(i);
+ fi.path=p_path->get_file_path(i);
+ fi.import_status=0;
+
+
+ matches->push_back(fi);
+ if (matches->size()>p_max_items)
+ return;
+ }
+ }
+}
+
+void FileSystemDock::_update_files(bool p_keep_selection) {
+
+ Set<String> cselection;
+
+ if (p_keep_selection) {
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ if (files->is_selected(i))
+ cselection.insert(files->get_item_text(i));
+ }
+ }
+
+ files->clear();
+
+ current_path->set_text(path);
+
+
+ EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_filesystem_path(path);
+ if (!efd)
+ return;
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("docks/filesystem/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ Ref<Texture> folder_thumbnail;
+ Ref<Texture> file_thumbnail;
+
+ bool use_thumbnails = (display_mode == DISPLAY_THUMBNAILS);
+ bool use_folders = search_box->get_text().length()==0 && split_mode;
+
+ if (use_thumbnails) { //thumbnails
+
+ files->set_max_columns(0);
+ files->set_icon_mode(ItemList::ICON_MODE_TOP);
+ files->set_fixed_column_width(thumbnail_size*3/2);
+ files->set_max_text_lines(2);
+ files->set_fixed_icon_size(Size2(thumbnail_size,thumbnail_size));
+
+ if (!has_icon("ResizedFolder","EditorIcons")) {
+ Ref<ImageTexture> folder = get_icon("FolderBig","EditorIcons");
+ Image img = folder->get_data();
+ img.resize(thumbnail_size,thumbnail_size);
+ Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture));
+ resized_folder->create_from_image(img,0);
+ Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder);
+ }
+
+ folder_thumbnail = get_icon("ResizedFolder","EditorIcons");
+
+ if (!has_icon("ResizedFile","EditorIcons")) {
+ Ref<ImageTexture> file = get_icon("FileBig","EditorIcons");
+ Image img = file->get_data();
+ img.resize(thumbnail_size,thumbnail_size);
+ Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture));
+ resized_file->create_from_image(img,0);
+ Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file);
+ }
+
+ file_thumbnail = get_icon("ResizedFile","EditorIcons");
+
+ } else {
+
+ files->set_icon_mode(ItemList::ICON_MODE_LEFT);
+ files->set_max_columns(1);
+ files->set_max_text_lines(1);
+ files->set_fixed_column_width(0);
+ files->set_fixed_icon_size(Size2());
+
+ }
+
+ if (use_folders) {
+
+ if (path!="res://") {
+
+ if (use_thumbnails) {
+ files->add_item("..",folder_thumbnail,true);
+ } else {
+ files->add_item("..",get_icon("folder","FileDialog"),true);
+ }
+
+ String bd = path.get_base_dir();
+ if (bd!="res://" && !bd.ends_with("/"))
+ bd+="/";
+
+ files->set_item_metadata(files->get_item_count()-1,bd);
+ }
+
+ for(int i=0;i<efd->get_subdir_count();i++) {
+
+ String dname=efd->get_subdir(i)->get_name();
+
+
+ if (use_thumbnails) {
+ files->add_item(dname,folder_thumbnail,true);
+ } else {
+ files->add_item(dname,get_icon("folder","FileDialog"),true);
+ }
+
+ files->set_item_metadata(files->get_item_count()-1,path.plus_file(dname)+"/");
+
+ if (cselection.has(dname))
+ files->select(files->get_item_count()-1,false);
+ }
+ }
+
+
+ List<FileInfo> filelist;
+
+ if (search_box->get_text().length()) {
+
+ if (search_box->get_text().length()>1) {
+ _search(EditorFileSystem::get_singleton()->get_filesystem(),&filelist,128);
+ }
+
+ filelist.sort();
+ } else {
+
+ for(int i=0;i<efd->get_file_count();i++) {
+
+ FileInfo fi;
+ fi.name=efd->get_file(i);
+ fi.path=path.plus_file(fi.name);
+ fi.type=efd->get_file_type(i);
+ fi.import_status=0;
+
+
+
+ filelist.push_back(fi);
+ }
+ }
+
+ StringName ei="EditorIcons"; //make it faster..
+ StringName oi="Object";
+
+
+ for(List<FileInfo>::Element *E=filelist.front();E;E=E->next()) {
+ String fname=E->get().name;
+ String fp = E->get().path;
+ StringName type = E->get().type;
+
+ Ref<Texture> type_icon;
+
+ String tooltip=fname;
+
+ if (E->get().import_status==0) {
+
+ if (has_icon(type,ei)) {
+ type_icon=get_icon(type,ei);
+ } else {
+ type_icon=get_icon(oi,ei);
+ }
+ } else if (E->get().import_status==1) {
+ type_icon=get_icon("DependencyOk","EditorIcons");
+ } else if (E->get().import_status==2) {
+ type_icon=get_icon("DependencyChanged","EditorIcons");
+ tooltip+"\nStatus: Needs Re-Import";
+ } else if (E->get().import_status==3) {
+ type_icon=get_icon("ImportFail","EditorIcons");
+ tooltip+"\nStatus: Missing Dependencies";
+ }
+
+ if (E->get().sources.size()) {
+ for(int i=0;i<E->get().sources.size();i++) {
+ tooltip+="\nSource: "+E->get().sources[i];
+ }
+ }
+
+
+
+ if (use_thumbnails) {
+ files->add_item(fname,file_thumbnail,true);
+ files->set_item_metadata(files->get_item_count()-1,fp);
+ files->set_item_tag_icon(files->get_item_count()-1,type_icon);
+ Array udata;
+ udata.resize(2);
+ udata[0]=files->get_item_count()-1;
+ udata[1]=fname;
+ EditorResourcePreview::get_singleton()->queue_resource_preview(fp,this,"_thumbnail_done",udata);
+ } else {
+ files->add_item(fname,type_icon,true);
+ files->set_item_metadata(files->get_item_count()-1,fp);
+
+ }
+
+ if (cselection.has(fname))
+ files->select(files->get_item_count()-1,false);
+
+ files->set_item_tooltip(files->get_item_count()-1,tooltip);
+
+
+ }
+
+
+}
+
+void FileSystemDock::_select_file(int p_idx) {
+
+ files->select(p_idx,true);
+ _file_option(FILE_OPEN);
+}
+
+void FileSystemDock::_go_to_tree() {
+
+ tree->show();
+ file_list_vb->hide();
+ _update_tree();
+ tree->grab_focus();
+ tree->ensure_cursor_is_visible();
+ button_favorite->show();
+ //button_open->hide();
+ //file_options->hide();
+}
+
+void FileSystemDock::_go_to_dir(const String& p_dir){
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->change_dir(p_dir)==OK) {
+ path=da->get_current_dir();
+ _update_files(false);
+ }
+ current_path->set_text(path);
+ memdelete(da);
+
+
+}
+
+void FileSystemDock::_preview_invalidated(const String& p_path) {
+
+ if (p_path.get_base_dir()==path && search_box->get_text()==String() && file_list_vb->is_visible_in_tree()) {
+
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ if (files->get_item_metadata(i)==p_path) {
+ //re-request preview
+ Array udata;
+ udata.resize(2);
+ udata[0]=i;
+ udata[1]=files->get_item_text(i);
+ EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",udata);
+ break;
+ }
+ }
+ }
+}
+
+void FileSystemDock::_fs_changed() {
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+ scanning_vb->hide();
+ split_box->show();
+
+ if (tree->is_visible()) {
+ button_favorite->show();
+ _update_tree();
+
+ }
+
+ if (file_list_vb->is_visible()) {
+
+ _update_files(true);
+ }
+
+ set_process(false);
+}
+
+void FileSystemDock::_set_scanning_mode() {
+
+ split_box->hide();
+ button_hist_prev->set_disabled(true);
+ button_hist_next->set_disabled(true);
+ scanning_vb->show();
+ set_process(true);
+ if (EditorFileSystem::get_singleton()->is_scanning()) {
+ scanning_progress->set_value(EditorFileSystem::get_singleton()->get_scanning_progress()*100);
+ } else {
+ scanning_progress->set_value(0);
+ }
+
+}
+
+void FileSystemDock::_fw_history() {
+
+ if (history_pos<history.size()-1)
+ history_pos++;
+
+ path=history[history_pos];
+
+ if (tree->is_visible()) {
+ _update_tree();
+ tree->grab_focus();
+ tree->ensure_cursor_is_visible();
+
+ }
+
+ if (file_list_vb->is_visible()) {
+ _update_files(false);
+ current_path->set_text(path);
+ }
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+
+}
+
+void FileSystemDock::_bw_history() {
+
+ if (history_pos>0)
+ history_pos--;
+
+ path=history[history_pos];
+
+
+ if (tree->is_visible()) {
+ _update_tree();
+ tree->grab_focus();
+ tree->ensure_cursor_is_visible();
+ }
+
+ if (file_list_vb->is_visible()) {
+ _update_files(false);
+ current_path->set_text(path);
+ }
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+
+}
+
+void FileSystemDock::_push_to_history() {
+
+ history.resize(history_pos+1);
+ if (history[history_pos]!=path) {
+ history.push_back(path);
+ history_pos++;
+ }
+
+ button_hist_prev->set_disabled(history_pos==0);
+ button_hist_next->set_disabled(history_pos+1==history.size());
+
+}
+
+
+void FileSystemDock::_find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files) {
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _find_inside_move_files(efsd->get_subdir(i),files);
+ }
+ for(int i=0;i<efsd->get_file_count();i++) {
+ files.push_back(efsd->get_file_path(i));
+ }
+
+}
+
+void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps) {
+
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+ _find_remaps(efsd->get_subdir(i),renames,to_remaps);
+ }
+ for(int i=0;i<efsd->get_file_count();i++) {
+ Vector<String> deps=efsd->get_file_deps(i);
+ for(int j=0;j<deps.size();j++) {
+ if (renames.has(deps[j])) {
+ to_remaps.push_back(efsd->get_file_path(i));
+ break;
+ }
+ }
+ }
+}
+
+
+void FileSystemDock::_rename_operation(const String& p_to_path) {
+
+ if (move_files[0]==p_to_path) {
+ EditorNode::get_singleton()->show_warning(TTR("Same source and destination files, doing nothing."));
+ return;
+ }
+ if (FileAccess::exists(p_to_path)) {
+ EditorNode::get_singleton()->show_warning("Target file exists, can't overwrite. Delete first.");
+ return;
+ }
+
+ Map<String,String> renames;
+ renames[move_files[0]]=p_to_path;
+
+ List<String> remap;
+
+ _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap);
+ print_line("found files to remap: "+itos(remap.size()));
+
+ //perform remaps
+ for(List<String>::Element *E=remap.front();E;E=E->next()) {
+
+ Error err = ResourceLoader::rename_dependencies(E->get(),renames);
+ print_line("remapping: "+E->get());
+
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n");
+ }
+ }
+
+ //finally, perform moves
+
+ DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES);
+
+ Error err = da->rename(move_files[0],p_to_path);
+ print_line("moving file "+move_files[0]+" to "+p_to_path);
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[0]+"\n");
+ }
+
+ //rescan everything
+ memdelete(da);
+ print_line("call rescan!");
+ _rescan();
+}
+
+
+void FileSystemDock::_move_operation(const String& p_to_path) {
+
+ if (p_to_path==path) {
+ EditorNode::get_singleton()->show_warning(TTR("Same source and destination paths, doing nothing."));
+ return;
+ }
+
+ //find files inside dirs to be moved
+
+ Vector<String> inside_files;
+
+ for(int i=0;i<move_dirs.size();i++) {
+ if (p_to_path.begins_with(move_dirs[i])) {
+ EditorNode::get_singleton()->show_warning(TTR("Can't move directories to within themselves."));
+ return;
+ }
+
+ EditorFileSystemDirectory *efsd=EditorFileSystem::get_singleton()->get_filesystem_path(move_dirs[i]);
+ if (!efsd)
+ continue;
+ _find_inside_move_files(efsd,inside_files);
+ }
+
+ //make list of remaps
+ Map<String,String> renames;
+ String repfrom=path=="res://"?path:String(path+"/");
+ String repto=p_to_path=="res://"?p_to_path:String(p_to_path+"/");
+
+ for(int i=0;i<move_files.size();i++) {
+ renames[move_files[i]]=move_files[i].replace_first(repfrom,repto);
+ print_line("move file "+move_files[i]+" -> "+renames[move_files[i]]);
+ }
+ for(int i=0;i<inside_files.size();i++) {
+ renames[inside_files[i]]=inside_files[i].replace_first(repfrom,repto);
+ print_line("inside file "+inside_files[i]+" -> "+renames[inside_files[i]]);
+ }
+
+ //make list of files that will be run the remapping
+ List<String> remap;
+
+ _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap);
+ print_line("found files to remap: "+itos(remap.size()));
+
+ //perform remaps
+ for(List<String>::Element *E=remap.front();E;E=E->next()) {
+
+ Error err = ResourceLoader::rename_dependencies(E->get(),renames);
+ print_line("remapping: "+E->get());
+
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n");
+ }
+ }
+
+ //finally, perform moves
+
+ DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES);
+
+ for(int i=0;i<move_files.size();i++) {
+
+ String to = move_files[i].replace_first(repfrom,repto);
+ Error err = da->rename(move_files[i],to);
+ print_line("moving file "+move_files[i]+" to "+to);
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[i]+"\n");
+ }
+ }
+
+ for(int i=0;i<move_dirs.size();i++) {
+
+ String mdir = move_dirs[i];
+ if (mdir=="res://")
+ continue;
+
+ if (mdir.ends_with("/")) {
+ mdir=mdir.substr(0,mdir.length()-1);
+ }
+
+ String to = p_to_path.plus_file(mdir.get_file());
+ Error err = da->rename(mdir,to);
+ print_line("moving dir "+mdir+" to "+to);
+ if (err!=OK) {
+ EditorNode::get_singleton()->add_io_error("Error moving dir:\n"+move_dirs[i]+"\n");
+ }
+ }
+
+ memdelete(da);
+ //rescan everything
+ print_line("call rescan!");
+ _rescan();
+
+}
+
+void FileSystemDock::_file_option(int p_option) {
+
+ switch(p_option) {
+
+
+ case FILE_SHOW_IN_EXPLORER:
+ case FILE_OPEN: {
+ int idx=-1;
+ for(int i=0;i<files->get_item_count();i++) {
+ if (files->is_selected(i)) {
+ idx=i;
+ break;
+ }
+ }
+
+ if (idx<0)
+ return;
+
+
+
+ String path = files->get_item_metadata(idx);
+ if (p_option == FILE_SHOW_IN_EXPLORER) {
+ String dir = GlobalConfig::get_singleton()->globalize_path(path);
+ dir = dir.substr(0, dir.find_last("/"));
+ OS::get_singleton()->shell_open(String("file://")+dir);
+ return;
+ }
+
+ if (path.ends_with("/")) {
+ if (path!="res://") {
+ path=path.substr(0,path.length()-1);
+ }
+ this->path=path;
+ _update_files(false);
+ current_path->set_text(path);
+ _push_to_history();
+ } else {
+
+ if (ResourceLoader::get_resource_type(path)=="PackedScene") {
+
+ editor->open_request(path);
+ } else {
+
+ editor->load_resource(path);
+ }
+ }
+ } break;
+ case FILE_INSTANCE: {
+
+ Vector<String> paths;
+
+ for (int i = 0; i<files->get_item_count(); i++) {
+ if (!files->is_selected(i))
+ continue;
+ String path =files->get_item_metadata(i);
+ if (EditorFileSystem::get_singleton()->get_file_type(path)=="PackedScene") {
+ paths.push_back(path);
+ }
+ }
+
+ if (!paths.empty()) {
+ emit_signal("instance", paths);
+ }
+ } break;
+ case FILE_DEPENDENCIES: {
+
+ int idx = files->get_current();
+ if (idx<0 || idx>=files->get_item_count())
+ break;
+ String path = files->get_item_metadata(idx);
+ deps_editor->edit(path);
+ } break;
+ case FILE_OWNERS: {
+
+ int idx = files->get_current();
+ if (idx<0 || idx>=files->get_item_count())
+ break;
+ String path = files->get_item_metadata(idx);
+ owners_editor->show(path);
+ } break;
+ case FILE_MOVE: {
+
+ move_dirs.clear();
+ move_files.clear();
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ String path = files->get_item_metadata(i);
+ if (!files->is_selected(i))
+ continue;
+
+ if (files->get_item_text(i)=="..") {
+ EditorNode::get_singleton()->show_warning(TTR("Can't operate on '..'"));
+ return;
+ }
+
+ if (path.ends_with("/")) {
+ move_dirs.push_back(path.substr(0,path.length()-1));
+ } else {
+ move_files.push_back(path);
+ }
+ }
+
+
+ if (move_dirs.empty() && move_files.size()==1) {
+
+ rename_dialog->clear_filters();
+ rename_dialog->add_filter("*."+move_files[0].get_extension());
+ rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ rename_dialog->set_current_path(move_files[0]);
+ rename_dialog->popup_centered_ratio();
+ rename_dialog->set_title(TTR("Pick New Name and Location For:")+" "+move_files[0].get_file());
+
+
+ } else {
+ //just move
+ move_dialog->popup_centered_ratio();
+ }
+
+
+ } break;
+ case FILE_REMOVE: {
+
+ Vector<String> torem;
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ String path = files->get_item_metadata(i);
+ if (path.ends_with("/") || !files->is_selected(i))
+ continue;
+ torem.push_back(path);
+
+ }
+
+ if (torem.empty()) {
+ EditorNode::get_singleton()->show_warning(TTR("No files selected!"));
+ break;
+ }
+
+ remove_dialog->show(torem);
+ //1) find if used
+ //2) warn
+
+ } break;
+ case FILE_INFO: {
+
+ } break;
+ case FILE_REIMPORT: {
+
+
+ Vector<String> reimport;
+ for(int i=0;i<files->get_item_count();i++) {
+
+ if (!files->is_selected(i))
+ continue;
+
+ String path = files->get_item_metadata(i);
+ reimport.push_back(path);
+ }
+
+ ERR_FAIL_COND(reimport.size()==0);
+/*
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(reimport[0]);
+ ERR_FAIL_COND(!rimd.is_valid());
+ String editor=rimd->get_editor();
+
+ if (editor.begins_with("texture_")) { //compatibility fix for old texture format
+ editor="texture";
+ }
+
+ Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(editor);
+ ERR_FAIL_COND(!rimp.is_valid());
+
+ if (reimport.size()==1) {
+ rimp->import_dialog(reimport[0]);
+ } else {
+ rimp->reimport_multiple_files(reimport);
+
+ }
+ */
+
+ } break;
+ case FILE_COPY_PATH:
+
+ int idx = files->get_current();
+ if (idx<0 || idx>=files->get_item_count())
+ break;
+ String path = files->get_item_metadata(idx);
+ OS::get_singleton()->set_clipboard(path);
+ }
+}
+
+void FileSystemDock::_folder_option(int p_option) {
+
+ TreeItem *item = tree->get_selected();
+ TreeItem *child = item->get_children();
+
+ switch(p_option) {
+
+ case FOLDER_EXPAND_ALL:
+ item->set_collapsed(false);
+ while(child) {
+ child->set_collapsed(false);
+ child = child->get_next();
+ }
+ break;
+
+ case FOLDER_COLLAPSE_ALL:
+ while(child) {
+ child->set_collapsed(true);
+ child = child->get_next();
+ }
+ break;
+ }
+}
+
+void FileSystemDock::_open_pressed(){
+
+
+ TreeItem *sel = tree->get_selected();
+ if (!sel) {
+ return;
+ }
+ path = sel->get_metadata(0);
+ /*if (path!="res://" && path.ends_with("/")) {
+ path=path.substr(0,path.length()-1);
+ }*/
+
+ //tree_mode=false;
+
+ if (split_mode) {
+ tree->hide();
+ file_list_vb->show();
+ button_favorite->hide();
+ }
+
+ //file_options->show();
+
+ _update_files(false);
+ current_path->set_text(path);
+ _push_to_history();
+
+ //emit_signal("open",path);
+
+}
+
+void FileSystemDock::_dir_rmb_pressed(const Vector2& p_pos) {
+ folder_options->clear();
+ folder_options->set_size(Size2(1,1));
+
+ folder_options->add_item(TTR("Expand all"),FOLDER_EXPAND_ALL);
+ folder_options->add_item(TTR("Collapse all"),FOLDER_COLLAPSE_ALL);
+
+ folder_options->set_pos(files->get_global_pos() + p_pos);
+ folder_options->popup();
+}
+
+
+void FileSystemDock::_search_changed(const String& p_text) {
+
+ if (!search_box->is_visible_in_tree())
+ return; //wtf
+
+ _update_files(false);
+}
+
+void FileSystemDock::_rescan() {
+
+ _set_scanning_mode();
+ EditorFileSystem::get_singleton()->scan();
+
+}
+
+void FileSystemDock::fix_dependencies(const String& p_for_file) {
+ deps_editor->edit(p_for_file);
+}
+
+
+void FileSystemDock::focus_on_filter() {
+
+ if (!search_box->is_visible_in_tree()) {
+ // Tree mode, switch to files list with search box
+ tree->hide();
+ file_list_vb->show();
+ button_favorite->hide();
+ }
+
+ search_box->grab_focus();
+}
+
+void FileSystemDock::set_display_mode(int p_mode) {
+
+ if (p_mode == display_mode)
+ return;
+
+ button_display_mode->set_pressed(p_mode == DISPLAY_LIST);
+ _change_file_display();
+}
+
+
+Variant FileSystemDock::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ if (p_from==tree) {
+
+ TreeItem *selected = tree->get_selected();
+ if (!selected)
+ return Variant();
+
+ String path = selected->get_metadata(0);
+ if (path==String())
+ return Variant();
+ if (!path.ends_with("/"))
+ path=path+"/";
+ Vector<String> paths;
+ paths.push_back(path);
+ Dictionary d = EditorNode::get_singleton()->drag_files(paths,p_from);
+
+ if (selected->get_parent() && tree->get_root()->get_children()==selected->get_parent()) {
+ //a favorite.. treat as such
+ d["type"]="favorite";
+ }
+
+ return d;
+
+ }
+
+ if (p_from==files) {
+
+ List<int> seldirs;
+ List<int> selfiles;
+
+ for (int i = 0; i<files->get_item_count(); i++) {
+ if (files->is_selected(i)) {
+ String path = files->get_item_metadata(i);
+ if (path.ends_with("/"))
+ seldirs.push_back(i);
+ else
+ selfiles.push_back(i);
+ }
+ }
+
+ if (seldirs.empty() && selfiles.empty())
+ return Variant();
+ /*
+ if (seldirs.size() && selfiles.size())
+ return Variant(); //can't really mix files and dirs (i think?) - yes you can, commenting
+ */
+
+ /*if (selfiles.size()==1) {
+ Ref<Resource> resource = ResourceLoader::load(files->get_item_metadata(selfiles.front()->get()));
+ if (resource.is_valid()) {
+ return EditorNode::get_singleton()->drag_resource(resource,p_from);
+ }
+ }*/
+
+ if (selfiles.size()>0 && seldirs.size()==0) {
+ Vector<String> fnames;
+ for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
+ fnames.push_back(files->get_item_metadata(E->get()));
+ }
+ return EditorNode::get_singleton()->drag_files(fnames,p_from);
+ }
+
+ if (selfiles.size()>0 || seldirs.size()>0) {
+ Vector<String> fnames;
+ for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
+ fnames.push_back(files->get_item_metadata(E->get()));
+ }
+ for(List<int>::Element *E=seldirs.front();E;E=E->next()) {
+ fnames.push_back(files->get_item_metadata(E->get()));
+ }
+ return EditorNode::get_singleton()->drag_files_and_dirs(fnames,p_from);
+ }
+
+ }
+
+ return Variant();
+}
+
+bool FileSystemDock::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ Dictionary drag_data = p_data;
+
+ if (drag_data.has("type") && String(drag_data["type"])=="favorite") {
+
+ //moving favorite around
+ TreeItem *ti = tree->get_item_at_pos(p_point);
+ if (!ti)
+ return false;
+
+ int what = tree->get_drop_section_at_pos(p_point);
+
+ if (ti==tree->get_root()->get_children()) {
+ return (what==1); //the parent, first fav
+ }
+ if (ti->get_parent() && tree->get_root()->get_children()==ti->get_parent()) {
+ return true; // a favorite
+ }
+
+ if (ti==tree->get_root()->get_children()->get_next()) {
+ return (what==-1); //the tree, last fav
+ }
+
+ return false;
+
+ }
+
+
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ return true;
+ }
+
+ if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
+
+ Vector<String> fnames = drag_data["files"];
+
+ if (p_from==files) {
+
+ int at_pos = files->get_item_at_pos(p_point);
+ if (at_pos!=-1) {
+
+ String dir = files->get_item_metadata(at_pos);
+ if (dir.ends_with("/"))
+ return true;
+ }
+ }
+
+ if (p_from==tree) {
+
+ TreeItem *ti = tree->get_item_at_pos(p_point);
+ if (!ti)
+ return false;
+ String path = ti->get_metadata(0);
+
+ if (path==String())
+ return false;
+
+ return true;
+ }
+
+ }
+
+ return false;
+}
+
+void FileSystemDock::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ if (!can_drop_data_fw(p_point,p_data,p_from))
+ return;
+ Dictionary drag_data = p_data;
+
+ if (drag_data.has("type") && String(drag_data["type"])=="favorite") {
+
+ //moving favorite around
+ TreeItem *ti = tree->get_item_at_pos(p_point);
+ if (!ti)
+ return;
+
+ Vector<String> files = drag_data["files"];
+
+ ERR_FAIL_COND(files.size()!=1);
+
+ String swap = files[0];
+ if (swap!="res://" && swap.ends_with("/")) {
+ swap=swap.substr(0,swap.length()-1);
+ }
+
+ int what = tree->get_drop_section_at_pos(p_point);
+
+ TreeItem *swap_item=NULL;
+
+ if (ti==tree->get_root()->get_children()) {
+ swap_item=tree->get_root()->get_children()->get_children();
+
+ } else if (ti->get_parent() && tree->get_root()->get_children()==ti->get_parent()) {
+ if (what==-1) {
+ swap_item=ti;
+ } else {
+ swap_item=ti->get_next();
+ }
+ }
+
+ String swap_with;
+
+ if (swap_item) {
+ swap_with=swap_item->get_metadata(0);
+ if (swap_with!="res://" && swap_with.ends_with("/")) {
+ swap_with=swap_with.substr(0,swap_with.length()-1);
+ }
+ }
+
+ if (swap==swap_with)
+ return;
+
+ Vector<String> dirs = EditorSettings::get_singleton()->get_favorite_dirs();
+
+ ERR_FAIL_COND(dirs.find(swap)==-1);
+ ERR_FAIL_COND(swap_with!=String() && dirs.find(swap_with)==-1);
+
+ dirs.erase(swap);
+
+ if (swap_with==String()) {
+ dirs.push_back(swap);
+ } else {
+ int idx = dirs.find(swap_with);
+ dirs.insert(idx,swap);
+ }
+
+ EditorSettings::get_singleton()->set_favorite_dirs(dirs);
+ _update_tree();
+ return;
+
+ }
+
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ Ref<Resource> res = drag_data["resource"];
+
+ if (!res.is_valid()) {
+ return;
+ }
+
+
+ if (p_from==tree) {
+
+ TreeItem *ti = tree->get_item_at_pos(p_point);
+ if (!ti)
+ return;
+ String path = ti->get_metadata(0);
+
+ if (path==String())
+ return;
+
+ EditorNode::get_singleton()->save_resource_as(res,path);
+ return;
+
+ }
+
+ if (p_from==files) {
+ String save_path=path;
+
+ int at_pos = files->get_item_at_pos(p_point);
+ if (at_pos!=-1) {
+ String to_dir = files->get_item_metadata(at_pos);
+ if (to_dir.ends_with("/")) {
+ save_path=to_dir;
+ if (save_path!="res://")
+ save_path=save_path.substr(0,save_path.length()-1);
+ }
+
+ }
+
+ EditorNode::get_singleton()->save_resource_as(res,save_path);
+ return;
+ }
+ }
+
+ if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
+
+ if (p_from==files || p_from==tree) {
+
+ String to_dir;
+
+ if (p_from==files) {
+
+ int at_pos = files->get_item_at_pos(p_point);
+ ERR_FAIL_COND(at_pos==-1);
+ to_dir = files->get_item_metadata(at_pos);
+ } else {
+ TreeItem *ti = tree->get_item_at_pos(p_point);
+ if (!ti)
+ return;
+ to_dir = ti->get_metadata(0);
+ ERR_FAIL_COND(to_dir==String());
+
+ }
+
+ if (to_dir!="res://" && to_dir.ends_with("/")) {
+ to_dir=to_dir.substr(0,to_dir.length()-1);
+ }
+
+ Vector<String> fnames = drag_data["files"];
+ move_files.clear();
+ move_dirs.clear();
+
+ for(int i=0;i<fnames.size();i++) {
+ if (fnames[i].ends_with("/"))
+ move_dirs.push_back(fnames[i]);
+ else
+ move_files.push_back(fnames[i]);
+ }
+
+ _move_operation(to_dir);
+ }
+ }
+
+}
+
+void FileSystemDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) {
+
+ Vector<String> filenames;
+
+ bool all_scenes=true;
+ bool all_can_reimport=true;
+ Set<String> types;
+
+ for(int i=0;i<files->get_item_count();i++) {
+
+ if (!files->is_selected(i))
+ continue;
+
+ String path = files->get_item_metadata(i);
+
+ if (files->get_item_text(i)=="..") {
+ // no operate on ..
+ return;
+ }
+
+ if (path.ends_with("/")) {
+ //no operate on dirs
+ return;
+ }
+
+
+ EditorFileSystemDirectory *efsd=NULL;
+ int pos;
+
+ efsd = EditorFileSystem::get_singleton()->find_file(path,&pos);
+
+ if (efsd) {
+
+
+ } else {
+ all_can_reimport=false;
+
+ }
+
+ filenames.push_back(path);
+ if (EditorFileSystem::get_singleton()->get_file_type(path)!="PackedScene")
+ all_scenes=false;
+ }
+
+
+ if (filenames.size()==0)
+ return;
+
+ file_options->clear();
+ file_options->set_size(Size2(1,1));
+
+ file_options->add_item(TTR("Open"),FILE_OPEN);
+ if (all_scenes) {
+ file_options->add_item(TTR("Instance"),FILE_INSTANCE);
+ }
+
+ file_options->add_separator();
+
+ if (filenames.size()==1) {
+ file_options->add_item(TTR("Edit Dependencies.."),FILE_DEPENDENCIES);
+ file_options->add_item(TTR("View Owners.."),FILE_OWNERS);
+ file_options->add_separator();
+ }
+
+ if (filenames.size()==1) {
+ file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH);
+ file_options->add_item(TTR("Rename or Move.."),FILE_MOVE);
+ } else {
+ file_options->add_item(TTR("Move To.."),FILE_MOVE);
+ }
+
+
+ file_options->add_item(TTR("Delete"),FILE_REMOVE);
+
+ //file_options->add_item(TTR("Info"),FILE_INFO);
+
+ file_options->add_separator();
+ file_options->add_item(TTR("Show In File Manager"),FILE_SHOW_IN_EXPLORER);
+
+ if (all_can_reimport && types.size()==1) { //all can reimport and are of the same type
+
+/*
+ bool valid=true;
+ Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(types.front()->get());
+ if (rimp.is_valid()) {
+
+ if (filenames.size()>1 && !rimp->can_reimport_multiple_files()) {
+ valid=false;
+ }
+ } else {
+ valid=false;
+ }
+
+ if (valid) {
+ file_options->add_separator();
+ file_options->add_item(TTR("Re-Import.."),FILE_REIMPORT);
+ }
+ */
+ }
+
+ file_options->set_pos(files->get_global_pos() + p_pos);
+ file_options->popup();
+
+}
+
+void FileSystemDock::select_file(const String& p_file) {
+
+ _go_to_dir(p_file.get_base_dir());
+ for(int i=0;i<files->get_item_count();i++) {
+ if (files->get_item_metadata(i)==p_file) {
+ files->select(i);
+ files->ensure_current_is_visible();
+ break;
+ }
+ }
+
+}
+
+void FileSystemDock::_file_multi_selected(int p_index,bool p_selected) {
+
+
+ _file_selected();
+}
+
+void FileSystemDock::_file_selected() {
+
+ //check import
+ Vector<String> imports;
+ String import_type;
+
+ for(int i=0;i<files->get_item_count();i++) {
+ if (!files->is_selected(i))
+ continue;
+
+ String p = files->get_item_metadata(i);
+ if (!FileAccess::exists(p+".import")) {
+ imports.clear();
+ break;
+ }
+ Ref<ConfigFile> cf;
+ cf.instance();
+ Error err = cf->load(p+".import");
+ if (err!=OK) {
+ imports.clear();
+ break;
+ }
+
+ String type = cf->get_value("remap","type");
+ if (import_type=="") {
+ import_type=type;
+ } else if (import_type!=type) {
+ //all should be the same type
+ imports.clear();
+ break;
+ }
+ imports.push_back(p);
+ }
+
+
+ if (imports.size()==0) {
+ EditorNode::get_singleton()->get_import_dock()->clear();
+ } else if (imports.size()==1) {
+ EditorNode::get_singleton()->get_import_dock()->set_edit_path(imports[0]);
+ } else {
+ EditorNode::get_singleton()->get_import_dock()->set_edit_multiple_paths(imports);
+ }
+}
+
+
+void FileSystemDock::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_update_tree"),&FileSystemDock::_update_tree);
+ ClassDB::bind_method(D_METHOD("_rescan"),&FileSystemDock::_rescan);
+ ClassDB::bind_method(D_METHOD("_favorites_pressed"),&FileSystemDock::_favorites_pressed);
+ //ClassDB::bind_method(D_METHOD("_instance_pressed"),&ScenesDock::_instance_pressed);
+ ClassDB::bind_method(D_METHOD("_open_pressed"),&FileSystemDock::_open_pressed);
+ ClassDB::bind_method(D_METHOD("_dir_rmb_pressed"),&FileSystemDock::_dir_rmb_pressed);
+
+ ClassDB::bind_method(D_METHOD("_thumbnail_done"),&FileSystemDock::_thumbnail_done);
+ ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file);
+ ClassDB::bind_method(D_METHOD("_go_to_tree"), &FileSystemDock::_go_to_tree);
+ ClassDB::bind_method(D_METHOD("_go_to_dir"), &FileSystemDock::_go_to_dir);
+ ClassDB::bind_method(D_METHOD("_change_file_display"), &FileSystemDock::_change_file_display);
+ ClassDB::bind_method(D_METHOD("_fw_history"), &FileSystemDock::_fw_history);
+ ClassDB::bind_method(D_METHOD("_bw_history"), &FileSystemDock::_bw_history);
+ ClassDB::bind_method(D_METHOD("_fs_changed"), &FileSystemDock::_fs_changed);
+ ClassDB::bind_method(D_METHOD("_dir_selected"), &FileSystemDock::_dir_selected);
+ ClassDB::bind_method(D_METHOD("_file_option"), &FileSystemDock::_file_option);
+ ClassDB::bind_method(D_METHOD("_folder_option"), &FileSystemDock::_folder_option);
+ ClassDB::bind_method(D_METHOD("_move_operation"), &FileSystemDock::_move_operation);
+ ClassDB::bind_method(D_METHOD("_rename_operation"), &FileSystemDock::_rename_operation);
+
+ ClassDB::bind_method(D_METHOD("_search_changed"), &FileSystemDock::_search_changed);
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &FileSystemDock::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &FileSystemDock::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &FileSystemDock::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("_files_list_rmb_select"),&FileSystemDock::_files_list_rmb_select);
+
+ ClassDB::bind_method(D_METHOD("_preview_invalidated"),&FileSystemDock::_preview_invalidated);
+ ClassDB::bind_method(D_METHOD("_file_selected"),&FileSystemDock::_file_selected);
+ ClassDB::bind_method(D_METHOD("_file_multi_selected"),&FileSystemDock::_file_multi_selected);
+
+
+ ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files")));
+ ADD_SIGNAL(MethodInfo("open"));
+
+}
+
+FileSystemDock::FileSystemDock(EditorNode *p_editor) {
+
+ editor=p_editor;
+
+
+ HBoxContainer *toolbar_hbc = memnew( HBoxContainer );
+ add_child(toolbar_hbc);
+
+ button_hist_prev = memnew( ToolButton );
+ toolbar_hbc->add_child(button_hist_prev);
+ button_hist_prev->set_disabled(true);
+ button_hist_prev->set_tooltip(TTR("Previous Directory"));
+
+ button_hist_next = memnew( ToolButton );
+ toolbar_hbc->add_child(button_hist_next);
+ button_hist_next->set_disabled(true);
+ button_hist_prev->set_focus_mode(FOCUS_NONE);
+ button_hist_next->set_focus_mode(FOCUS_NONE);
+ button_hist_next->set_tooltip(TTR("Next Directory"));
+
+ current_path=memnew( LineEdit );
+ current_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ toolbar_hbc->add_child(current_path);
+
+
+ button_reload = memnew( Button );
+ button_reload->set_flat(true);
+ button_reload->connect("pressed",this,"_rescan");
+ toolbar_hbc->add_child(button_reload);
+ button_reload->set_focus_mode(FOCUS_NONE);
+ button_reload->set_tooltip(TTR("Re-Scan Filesystem"));
+ button_reload->hide();
+
+ //toolbar_hbc->add_spacer();
+
+
+ button_favorite = memnew( Button );
+ button_favorite->set_flat(true);
+ button_favorite->set_toggle_mode(true);
+ button_favorite->connect("pressed",this,"_favorites_pressed");
+ toolbar_hbc->add_child(button_favorite);
+ button_favorite->set_tooltip(TTR("Toggle folder status as Favorite"));
+
+ button_favorite->set_focus_mode(FOCUS_NONE);
+
+ //Control *spacer = memnew( Control);
+
+
+
+/*
+ button_open = memnew( Button );
+ button_open->set_flat(true);
+ button_open->connect("pressed",this,"_open_pressed");
+ toolbar_hbc->add_child(button_open);
+ button_open->hide();
+ button_open->set_focus_mode(FOCUS_NONE);
+ button_open->set_tooltip("Open the selected file.\nOpen as scene if a scene, or as resource otherwise.");
+
+
+ button_instance = memnew( Button );
+ button_instance->set_flat(true);
+ button_instance->connect("pressed",this,"_instance_pressed");
+ toolbar_hbc->add_child(button_instance);
+ button_instance->hide();
+ button_instance->set_focus_mode(FOCUS_NONE);
+ button_instance->set_tooltip(TTR("Instance the selected scene(s) as child of the selected node."));
+
+*/
+ file_options = memnew( PopupMenu );
+ add_child(file_options);
+
+ folder_options = memnew ( PopupMenu );
+ add_child(folder_options);
+
+ split_box = memnew( VSplitContainer );
+ add_child(split_box);
+ split_box->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ tree = memnew( Tree );
+
+ tree->set_hide_root(true);
+ split_box->add_child(tree);
+ tree->set_drag_forwarding(this);
+ tree->set_allow_rmb_select(true);
+
+
+ //tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ tree->connect("item_edited",this,"_favorite_toggled");
+ tree->connect("item_activated",this,"_open_pressed");
+ tree->connect("cell_selected",this,"_dir_selected");
+ tree->connect("item_rmb_selected",this,"_dir_rmb_pressed");
+
+ files = memnew( ItemList );
+ files->set_v_size_flags(SIZE_EXPAND_FILL);
+ files->set_select_mode(ItemList::SELECT_MULTI);
+ files->set_drag_forwarding(this);
+ files->connect("item_rmb_selected",this,"_files_list_rmb_select");
+ files->connect("item_selected",this,"_file_selected");
+ files->connect("multi_selected",this,"_file_multi_selected");
+ files->set_allow_rmb_select(true);
+
+ file_list_vb = memnew( VBoxContainer );
+ split_box->add_child(file_list_vb);
+ file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ path_hb = memnew( HBoxContainer );
+ file_list_vb->add_child(path_hb);
+
+ button_back = memnew( ToolButton );
+ path_hb->add_child(button_back);
+ button_back->hide();
+
+ search_box = memnew( LineEdit );
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ path_hb->add_child(search_box);
+ search_box->connect("text_changed",this,"_search_changed");
+
+ search_icon = memnew( TextureRect );
+ search_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ path_hb->add_child(search_icon);
+
+ button_display_mode = memnew( ToolButton );
+ path_hb->add_child(button_display_mode);
+ button_display_mode->set_toggle_mode(true);
+
+ file_list_vb->add_child(files);
+
+
+ scanning_vb = memnew( VBoxContainer );
+ Label *slabel = memnew( Label );
+ slabel->set_text("Scanning Files,\nPlease Wait..");
+ slabel->set_align(Label::ALIGN_CENTER);
+ scanning_vb->add_child(slabel);
+ scanning_progress = memnew( ProgressBar );
+ scanning_vb->add_child(scanning_progress);
+ add_child(scanning_vb);
+ scanning_vb->hide();
+
+
+
+ deps_editor = memnew( DependencyEditor );
+ add_child(deps_editor);
+
+ owners_editor = memnew( DependencyEditorOwners);
+ add_child(owners_editor);
+
+ remove_dialog = memnew( DependencyRemoveDialog);
+ add_child(remove_dialog);
+
+ move_dialog = memnew( EditorDirDialog );
+ add_child(move_dialog);
+ move_dialog->connect("dir_selected",this,"_move_operation");
+ move_dialog->get_ok()->set_text(TTR("Move"));
+
+ rename_dialog = memnew( EditorFileDialog );
+ rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ rename_dialog->connect("file_selected",this,"_rename_operation");
+ add_child(rename_dialog);
+
+ updating_tree=false;
+ initialized=false;
+
+ history.push_back("res://");
+ history_pos=0;
+
+ split_mode=false;
+ display_mode = DISPLAY_THUMBNAILS;
+
+ path="res://";
+
+
+ add_constant_override("separation",3);
+}
+
+FileSystemDock::~FileSystemDock() {
+
+}
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
new file mode 100644
index 0000000000..916321d8fd
--- /dev/null
+++ b/editor/filesystem_dock.h
@@ -0,0 +1,217 @@
+/*************************************************************************/
+/* filesystem_dock.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 FILESYSTEM_DOCK_H
+#define FILESYSTEM_DOCK_H
+
+#include "scene/main/timer.h"
+#include "scene/gui/control.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/label.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/progress_bar.h"
+#include "scene/gui/split_container.h"
+
+#include "os/dir_access.h"
+#include "os/thread.h"
+
+#include "editor_file_system.h"
+#include "editor_dir_dialog.h"
+#include "dependency_editor.h"
+
+class EditorNode;
+
+
+class FileSystemDock : public VBoxContainer {
+ GDCLASS( FileSystemDock, VBoxContainer );
+
+public:
+ enum DisplayMode {
+ DISPLAY_THUMBNAILS,
+ DISPLAY_LIST
+ };
+private:
+ enum FileMenu {
+ FILE_OPEN,
+ FILE_INSTANCE,
+ FILE_DEPENDENCIES,
+ FILE_OWNERS,
+ FILE_MOVE,
+ FILE_REMOVE,
+ FILE_REIMPORT,
+ FILE_INFO,
+ FILE_SHOW_IN_EXPLORER,
+ FILE_COPY_PATH
+ };
+
+ enum FolderMenu {
+ FOLDER_EXPAND_ALL,
+ FOLDER_COLLAPSE_ALL
+ };
+
+
+ VBoxContainer *scanning_vb;
+ ProgressBar *scanning_progress;
+ VSplitContainer *split_box;
+ VBoxContainer *file_list_vb;
+
+ EditorNode *editor;
+ Set<String> favorites;
+
+ Button *button_reload;
+ Button *button_favorite;
+ Button *button_back;
+ Button *button_display_mode;
+ Button *button_hist_next;
+ Button *button_hist_prev;
+ LineEdit *current_path;
+ LineEdit *search_box;
+ TextureRect *search_icon;
+ HBoxContainer *path_hb;
+
+ bool split_mode;
+ DisplayMode display_mode;
+
+ PopupMenu *file_options;
+ PopupMenu *folder_options;
+
+ DependencyEditor *deps_editor;
+ DependencyEditorOwners *owners_editor;
+ DependencyRemoveDialog *remove_dialog;
+
+ EditorDirDialog *move_dialog;
+ EditorFileDialog *rename_dialog;
+
+ Vector<String> move_dirs;
+ Vector<String> move_files;
+
+
+ Vector<String> history;
+ int history_pos;
+
+ String path;
+
+ bool initialized;
+
+ bool updating_tree;
+ Tree * tree; //directories
+ ItemList *files;
+
+
+ void _file_multi_selected(int p_index, bool p_selected);
+ void _file_selected();
+
+
+ void _go_to_tree();
+ void _go_to_dir(const String& p_dir);
+ void _select_file(int p_idx);
+
+ bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir);
+ void _thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata);
+ void _find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files);
+ void _find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps);
+
+ void _rename_operation(const String& p_to_path);
+ void _move_operation(const String& p_to_path);
+
+
+ void _file_option(int p_option);
+ void _folder_option(int p_option);
+ void _update_files(bool p_keep_selection);
+ void _change_file_display();
+
+ void _fs_changed();
+ void _fw_history();
+ void _bw_history();
+ void _push_to_history();
+
+
+ void _dir_selected();
+ void _update_tree();
+ void _rescan();
+ void _set_scanning_mode();
+
+
+ void _favorites_pressed();
+ void _open_pressed();
+ void _dir_rmb_pressed(const Vector2& local_mouse_pos);
+ void _search_changed(const String& p_text);
+
+
+ void _files_list_rmb_select(int p_item,const Vector2& p_pos);
+
+
+ struct FileInfo {
+ String name;
+ String path;
+ StringName type;
+ int import_status; //0 not imported, 1 - ok, 2- must reimport, 3- broken
+ Vector<String> sources;
+
+ bool operator<(const FileInfo& fi) const {
+ return name < fi.name;
+ }
+ };
+
+ void _search(EditorFileSystemDirectory *p_path, List<FileInfo>* matches, int p_max_items);
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+ void _preview_invalidated(const String& p_path);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ String get_selected_path() const;
+
+ String get_current_path() const;
+ void navigate_to_path(const String& p_path);
+ void focus_on_filter();
+
+ void fix_dependencies(const String& p_for_file);
+
+ void set_display_mode(int p_mode);
+
+ int get_split_offset() { return split_box->get_split_offset(); }
+ void set_split_offset(int p_offset) { split_box->set_split_offset(p_offset); }
+ void select_file(const String& p_file);
+
+ FileSystemDock(EditorNode *p_editor);
+ ~FileSystemDock();
+};
+
+
+#endif // SCENES_DOCK_H
diff --git a/tools/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 90f0bab6dd..90f0bab6dd 100644
--- a/tools/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
diff --git a/tools/editor/groups_editor.h b/editor/groups_editor.h
index 9ab75c6cfd..9ab75c6cfd 100644
--- a/tools/editor/groups_editor.h
+++ b/editor/groups_editor.h
diff --git a/tools/editor/icons/2x/icon_accept_dialog.png b/editor/icons/2x/icon_accept_dialog.png
index fca344aefc..fca344aefc 100644
--- a/tools/editor/icons/2x/icon_accept_dialog.png
+++ b/editor/icons/2x/icon_accept_dialog.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_add.png b/editor/icons/2x/icon_add.png
index a46c521f2a..a46c521f2a 100644
--- a/tools/editor/icons/2x/icon_add.png
+++ b/editor/icons/2x/icon_add.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_add_track.png b/editor/icons/2x/icon_add_track.png
index a46c521f2a..a46c521f2a 100644
--- a/tools/editor/icons/2x/icon_add_track.png
+++ b/editor/icons/2x/icon_add_track.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_anchor.png b/editor/icons/2x/icon_anchor.png
index 7e9e259c13..7e9e259c13 100644
--- a/tools/editor/icons/2x/icon_anchor.png
+++ b/editor/icons/2x/icon_anchor.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_animated_sprite.png b/editor/icons/2x/icon_animated_sprite.png
index 461dac8f13..461dac8f13 100644
--- a/tools/editor/icons/2x/icon_animated_sprite.png
+++ b/editor/icons/2x/icon_animated_sprite.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_animated_sprite_3d.png b/editor/icons/2x/icon_animated_sprite_3d.png
index 6c79c38875..6c79c38875 100644
--- a/tools/editor/icons/2x/icon_animated_sprite_3d.png
+++ b/editor/icons/2x/icon_animated_sprite_3d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_animation.png b/editor/icons/2x/icon_animation.png
index ef18959a74..ef18959a74 100644
--- a/tools/editor/icons/2x/icon_animation.png
+++ b/editor/icons/2x/icon_animation.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_animation_player.png b/editor/icons/2x/icon_animation_player.png
index 4a3209ab70..4a3209ab70 100644
--- a/tools/editor/icons/2x/icon_animation_player.png
+++ b/editor/icons/2x/icon_animation_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_animation_tree.png b/editor/icons/2x/icon_animation_tree.png
index a213ab6e5e..a213ab6e5e 100644
--- a/tools/editor/icons/2x/icon_animation_tree.png
+++ b/editor/icons/2x/icon_animation_tree.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_animation_tree_player.png b/editor/icons/2x/icon_animation_tree_player.png
index a213ab6e5e..a213ab6e5e 100644
--- a/tools/editor/icons/2x/icon_animation_tree_player.png
+++ b/editor/icons/2x/icon_animation_tree_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_area.png b/editor/icons/2x/icon_area.png
index d9cefe8fc4..d9cefe8fc4 100644
--- a/tools/editor/icons/2x/icon_area.png
+++ b/editor/icons/2x/icon_area.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_area_2d.png b/editor/icons/2x/icon_area_2d.png
index 22616cc754..22616cc754 100644
--- a/tools/editor/icons/2x/icon_area_2d.png
+++ b/editor/icons/2x/icon_area_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_arrow_left.png b/editor/icons/2x/icon_arrow_left.png
index bc3995f70b..bc3995f70b 100644
--- a/tools/editor/icons/2x/icon_arrow_left.png
+++ b/editor/icons/2x/icon_arrow_left.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_arrow_right.png b/editor/icons/2x/icon_arrow_right.png
index 045b390e0d..045b390e0d 100644
--- a/tools/editor/icons/2x/icon_arrow_right.png
+++ b/editor/icons/2x/icon_arrow_right.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_arrow_up.png b/editor/icons/2x/icon_arrow_up.png
index 524ab934e2..524ab934e2 100644
--- a/tools/editor/icons/2x/icon_arrow_up.png
+++ b/editor/icons/2x/icon_arrow_up.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_atlas_texture.png b/editor/icons/2x/icon_atlas_texture.png
index bd5bdc3148..bd5bdc3148 100644
--- a/tools/editor/icons/2x/icon_atlas_texture.png
+++ b/editor/icons/2x/icon_atlas_texture.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_audio_stream_gibberish.png b/editor/icons/2x/icon_audio_stream_gibberish.png
index da200740a4..da200740a4 100644
--- a/tools/editor/icons/2x/icon_audio_stream_gibberish.png
+++ b/editor/icons/2x/icon_audio_stream_gibberish.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_auto_play.png b/editor/icons/2x/icon_auto_play.png
index ec31dee958..ec31dee958 100644
--- a/tools/editor/icons/2x/icon_auto_play.png
+++ b/editor/icons/2x/icon_auto_play.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_back.png b/editor/icons/2x/icon_back.png
index 648c440928..648c440928 100644
--- a/tools/editor/icons/2x/icon_back.png
+++ b/editor/icons/2x/icon_back.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_back_buffer_copy.png b/editor/icons/2x/icon_back_buffer_copy.png
index 8b5c37b7e5..8b5c37b7e5 100644
--- a/tools/editor/icons/2x/icon_back_buffer_copy.png
+++ b/editor/icons/2x/icon_back_buffer_copy.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bake.png b/editor/icons/2x/icon_bake.png
index 3c1cba5586..3c1cba5586 100644
--- a/tools/editor/icons/2x/icon_bake.png
+++ b/editor/icons/2x/icon_bake.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_baked_light.png b/editor/icons/2x/icon_baked_light.png
index 3c1cba5586..3c1cba5586 100644
--- a/tools/editor/icons/2x/icon_baked_light.png
+++ b/editor/icons/2x/icon_baked_light.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_baked_light_instance.png b/editor/icons/2x/icon_baked_light_instance.png
index 9b13ed8ff1..9b13ed8ff1 100644
--- a/tools/editor/icons/2x/icon_baked_light_instance.png
+++ b/editor/icons/2x/icon_baked_light_instance.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_baked_light_sampler.png b/editor/icons/2x/icon_baked_light_sampler.png
index 8dfc1793f1..8dfc1793f1 100644
--- a/tools/editor/icons/2x/icon_baked_light_sampler.png
+++ b/editor/icons/2x/icon_baked_light_sampler.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bit_map.png b/editor/icons/2x/icon_bit_map.png
index 7372b85944..7372b85944 100644
--- a/tools/editor/icons/2x/icon_bit_map.png
+++ b/editor/icons/2x/icon_bit_map.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bitmap_font.png b/editor/icons/2x/icon_bitmap_font.png
index c533b5f40e..c533b5f40e 100644
--- a/tools/editor/icons/2x/icon_bitmap_font.png
+++ b/editor/icons/2x/icon_bitmap_font.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_blend.png b/editor/icons/2x/icon_blend.png
index 8dd30d1a04..8dd30d1a04 100644
--- a/tools/editor/icons/2x/icon_blend.png
+++ b/editor/icons/2x/icon_blend.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bone.png b/editor/icons/2x/icon_bone.png
index 0a8ceb4ce1..0a8ceb4ce1 100644
--- a/tools/editor/icons/2x/icon_bone.png
+++ b/editor/icons/2x/icon_bone.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bone_attachment.png b/editor/icons/2x/icon_bone_attachment.png
index 4e9333d3d1..4e9333d3d1 100644
--- a/tools/editor/icons/2x/icon_bone_attachment.png
+++ b/editor/icons/2x/icon_bone_attachment.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bone_track.png b/editor/icons/2x/icon_bone_track.png
index a956923a07..a956923a07 100644
--- a/tools/editor/icons/2x/icon_bone_track.png
+++ b/editor/icons/2x/icon_bone_track.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_bool.png b/editor/icons/2x/icon_bool.png
index 47103538bd..47103538bd 100644
--- a/tools/editor/icons/2x/icon_bool.png
+++ b/editor/icons/2x/icon_bool.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_box_shape.png b/editor/icons/2x/icon_box_shape.png
index 7d5356ad94..7d5356ad94 100644
--- a/tools/editor/icons/2x/icon_box_shape.png
+++ b/editor/icons/2x/icon_box_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_button.png b/editor/icons/2x/icon_button.png
index 210b0da486..210b0da486 100644
--- a/tools/editor/icons/2x/icon_button.png
+++ b/editor/icons/2x/icon_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_button_group.png b/editor/icons/2x/icon_button_group.png
index 47f62005b9..47f62005b9 100644
--- a/tools/editor/icons/2x/icon_button_group.png
+++ b/editor/icons/2x/icon_button_group.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_camera.png b/editor/icons/2x/icon_camera.png
index ea17779784..ea17779784 100644
--- a/tools/editor/icons/2x/icon_camera.png
+++ b/editor/icons/2x/icon_camera.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_camera_2d.png b/editor/icons/2x/icon_camera_2d.png
index c5c881c435..c5c881c435 100644
--- a/tools/editor/icons/2x/icon_camera_2d.png
+++ b/editor/icons/2x/icon_camera_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_item.png b/editor/icons/2x/icon_canvas_item.png
index 42863020f0..42863020f0 100644
--- a/tools/editor/icons/2x/icon_canvas_item.png
+++ b/editor/icons/2x/icon_canvas_item.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_item_material.png b/editor/icons/2x/icon_canvas_item_material.png
index a9f7948060..a9f7948060 100644
--- a/tools/editor/icons/2x/icon_canvas_item_material.png
+++ b/editor/icons/2x/icon_canvas_item_material.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_item_shader.png b/editor/icons/2x/icon_canvas_item_shader.png
index 5091a947c0..5091a947c0 100644
--- a/tools/editor/icons/2x/icon_canvas_item_shader.png
+++ b/editor/icons/2x/icon_canvas_item_shader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_item_shader_graph.png b/editor/icons/2x/icon_canvas_item_shader_graph.png
index a26a9754fe..a26a9754fe 100644
--- a/tools/editor/icons/2x/icon_canvas_item_shader_graph.png
+++ b/editor/icons/2x/icon_canvas_item_shader_graph.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_layer.png b/editor/icons/2x/icon_canvas_layer.png
index 8a4b31cd7d..8a4b31cd7d 100644
--- a/tools/editor/icons/2x/icon_canvas_layer.png
+++ b/editor/icons/2x/icon_canvas_layer.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_canvas_modulate.png b/editor/icons/2x/icon_canvas_modulate.png
index 6cc15e2655..6cc15e2655 100644
--- a/tools/editor/icons/2x/icon_canvas_modulate.png
+++ b/editor/icons/2x/icon_canvas_modulate.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_capsule_shape.png b/editor/icons/2x/icon_capsule_shape.png
index f8844ecef4..f8844ecef4 100644
--- a/tools/editor/icons/2x/icon_capsule_shape.png
+++ b/editor/icons/2x/icon_capsule_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_capsule_shape_2d.png b/editor/icons/2x/icon_capsule_shape_2d.png
index e449ce4985..e449ce4985 100644
--- a/tools/editor/icons/2x/icon_capsule_shape_2d.png
+++ b/editor/icons/2x/icon_capsule_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_center_container.png b/editor/icons/2x/icon_center_container.png
index c715f0959e..c715f0959e 100644
--- a/tools/editor/icons/2x/icon_center_container.png
+++ b/editor/icons/2x/icon_center_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_check_box.png b/editor/icons/2x/icon_check_box.png
index bade572304..bade572304 100644
--- a/tools/editor/icons/2x/icon_check_box.png
+++ b/editor/icons/2x/icon_check_box.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_check_button.png b/editor/icons/2x/icon_check_button.png
index 4f498bb9ad..4f498bb9ad 100644
--- a/tools/editor/icons/2x/icon_check_button.png
+++ b/editor/icons/2x/icon_check_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_circle_shape_2d.png b/editor/icons/2x/icon_circle_shape_2d.png
index feb84d2f1c..feb84d2f1c 100644
--- a/tools/editor/icons/2x/icon_circle_shape_2d.png
+++ b/editor/icons/2x/icon_circle_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_class_list.png b/editor/icons/2x/icon_class_list.png
index 4ae0b3edab..4ae0b3edab 100644
--- a/tools/editor/icons/2x/icon_class_list.png
+++ b/editor/icons/2x/icon_class_list.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_close.png b/editor/icons/2x/icon_close.png
index 62ab763fec..62ab763fec 100644
--- a/tools/editor/icons/2x/icon_close.png
+++ b/editor/icons/2x/icon_close.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_collapse.png b/editor/icons/2x/icon_collapse.png
index 18486c03f5..18486c03f5 100644
--- a/tools/editor/icons/2x/icon_collapse.png
+++ b/editor/icons/2x/icon_collapse.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_collision_2d.png b/editor/icons/2x/icon_collision_2d.png
index 491ebfaa78..491ebfaa78 100644
--- a/tools/editor/icons/2x/icon_collision_2d.png
+++ b/editor/icons/2x/icon_collision_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_collision_polygon.png b/editor/icons/2x/icon_collision_polygon.png
index ef786f6a3d..ef786f6a3d 100644
--- a/tools/editor/icons/2x/icon_collision_polygon.png
+++ b/editor/icons/2x/icon_collision_polygon.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_collision_polygon_2d.png b/editor/icons/2x/icon_collision_polygon_2d.png
index 491ebfaa78..491ebfaa78 100644
--- a/tools/editor/icons/2x/icon_collision_polygon_2d.png
+++ b/editor/icons/2x/icon_collision_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_collision_shape.png b/editor/icons/2x/icon_collision_shape.png
index 23bec8cdd9..23bec8cdd9 100644
--- a/tools/editor/icons/2x/icon_collision_shape.png
+++ b/editor/icons/2x/icon_collision_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_collision_shape_2d.png b/editor/icons/2x/icon_collision_shape_2d.png
index c91456b58e..c91456b58e 100644
--- a/tools/editor/icons/2x/icon_collision_shape_2d.png
+++ b/editor/icons/2x/icon_collision_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_color.png b/editor/icons/2x/icon_color.png
index 125dd86ec0..125dd86ec0 100644
--- a/tools/editor/icons/2x/icon_color.png
+++ b/editor/icons/2x/icon_color.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_color_pick.png b/editor/icons/2x/icon_color_pick.png
index c61f2d4174..c61f2d4174 100644
--- a/tools/editor/icons/2x/icon_color_pick.png
+++ b/editor/icons/2x/icon_color_pick.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_color_picker.png b/editor/icons/2x/icon_color_picker.png
index 2b683c75ea..2b683c75ea 100644
--- a/tools/editor/icons/2x/icon_color_picker.png
+++ b/editor/icons/2x/icon_color_picker.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_color_picker_button.png b/editor/icons/2x/icon_color_picker_button.png
index 8d9bd17ccc..8d9bd17ccc 100644
--- a/tools/editor/icons/2x/icon_color_picker_button.png
+++ b/editor/icons/2x/icon_color_picker_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_color_ramp.png b/editor/icons/2x/icon_color_ramp.png
index d0056f0c7d..d0056f0c7d 100644
--- a/tools/editor/icons/2x/icon_color_ramp.png
+++ b/editor/icons/2x/icon_color_ramp.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_color_rect.png b/editor/icons/2x/icon_color_rect.png
index 153029ac20..153029ac20 100644
--- a/tools/editor/icons/2x/icon_color_rect.png
+++ b/editor/icons/2x/icon_color_rect.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_concave_polygon_shape.png b/editor/icons/2x/icon_concave_polygon_shape.png
index 82a67ca4d0..82a67ca4d0 100644
--- a/tools/editor/icons/2x/icon_concave_polygon_shape.png
+++ b/editor/icons/2x/icon_concave_polygon_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_concave_polygon_shape_2d.png b/editor/icons/2x/icon_concave_polygon_shape_2d.png
index 1ad3f30950..1ad3f30950 100644
--- a/tools/editor/icons/2x/icon_concave_polygon_shape_2d.png
+++ b/editor/icons/2x/icon_concave_polygon_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_cone_twist_joint.png b/editor/icons/2x/icon_cone_twist_joint.png
index 3aeba5855d..3aeba5855d 100644
--- a/tools/editor/icons/2x/icon_cone_twist_joint.png
+++ b/editor/icons/2x/icon_cone_twist_joint.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_confirmation_dialog.png b/editor/icons/2x/icon_confirmation_dialog.png
index a0df7fcd1e..a0df7fcd1e 100644
--- a/tools/editor/icons/2x/icon_confirmation_dialog.png
+++ b/editor/icons/2x/icon_confirmation_dialog.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_connect.png b/editor/icons/2x/icon_connect.png
index e3f4b8fd12..e3f4b8fd12 100644
--- a/tools/editor/icons/2x/icon_connect.png
+++ b/editor/icons/2x/icon_connect.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_connection_and_groups.png b/editor/icons/2x/icon_connection_and_groups.png
index e7619327f6..e7619327f6 100644
--- a/tools/editor/icons/2x/icon_connection_and_groups.png
+++ b/editor/icons/2x/icon_connection_and_groups.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_container.png b/editor/icons/2x/icon_container.png
index baa09bbea9..baa09bbea9 100644
--- a/tools/editor/icons/2x/icon_container.png
+++ b/editor/icons/2x/icon_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control.png b/editor/icons/2x/icon_control.png
index 82d7457f3b..82d7457f3b 100644
--- a/tools/editor/icons/2x/icon_control.png
+++ b/editor/icons/2x/icon_control.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_bottom_center.png b/editor/icons/2x/icon_control_align_bottom_center.png
index 9dc738c746..9dc738c746 100644
--- a/tools/editor/icons/2x/icon_control_align_bottom_center.png
+++ b/editor/icons/2x/icon_control_align_bottom_center.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_bottom_left.png b/editor/icons/2x/icon_control_align_bottom_left.png
index a11a13528d..a11a13528d 100644
--- a/tools/editor/icons/2x/icon_control_align_bottom_left.png
+++ b/editor/icons/2x/icon_control_align_bottom_left.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_bottom_right.png b/editor/icons/2x/icon_control_align_bottom_right.png
index 7fee3f0752..7fee3f0752 100644
--- a/tools/editor/icons/2x/icon_control_align_bottom_right.png
+++ b/editor/icons/2x/icon_control_align_bottom_right.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_bottom_wide.png b/editor/icons/2x/icon_control_align_bottom_wide.png
index 573619ccbb..573619ccbb 100644
--- a/tools/editor/icons/2x/icon_control_align_bottom_wide.png
+++ b/editor/icons/2x/icon_control_align_bottom_wide.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_center.png b/editor/icons/2x/icon_control_align_center.png
index 9850ecd775..9850ecd775 100644
--- a/tools/editor/icons/2x/icon_control_align_center.png
+++ b/editor/icons/2x/icon_control_align_center.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_center_left.png b/editor/icons/2x/icon_control_align_center_left.png
index 2c48b889ad..2c48b889ad 100644
--- a/tools/editor/icons/2x/icon_control_align_center_left.png
+++ b/editor/icons/2x/icon_control_align_center_left.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_center_right.png b/editor/icons/2x/icon_control_align_center_right.png
index 4f87a68ad3..4f87a68ad3 100644
--- a/tools/editor/icons/2x/icon_control_align_center_right.png
+++ b/editor/icons/2x/icon_control_align_center_right.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_left_center.png b/editor/icons/2x/icon_control_align_left_center.png
index c4250dcb37..c4250dcb37 100644
--- a/tools/editor/icons/2x/icon_control_align_left_center.png
+++ b/editor/icons/2x/icon_control_align_left_center.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_left_wide.png b/editor/icons/2x/icon_control_align_left_wide.png
index 5436397189..5436397189 100644
--- a/tools/editor/icons/2x/icon_control_align_left_wide.png
+++ b/editor/icons/2x/icon_control_align_left_wide.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_right_center.png b/editor/icons/2x/icon_control_align_right_center.png
index b1fd9a075d..b1fd9a075d 100644
--- a/tools/editor/icons/2x/icon_control_align_right_center.png
+++ b/editor/icons/2x/icon_control_align_right_center.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_right_wide.png b/editor/icons/2x/icon_control_align_right_wide.png
index 0ce81d3a50..0ce81d3a50 100644
--- a/tools/editor/icons/2x/icon_control_align_right_wide.png
+++ b/editor/icons/2x/icon_control_align_right_wide.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_top_center.png b/editor/icons/2x/icon_control_align_top_center.png
index baa2601531..baa2601531 100644
--- a/tools/editor/icons/2x/icon_control_align_top_center.png
+++ b/editor/icons/2x/icon_control_align_top_center.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_top_left.png b/editor/icons/2x/icon_control_align_top_left.png
index 90f3cb6105..90f3cb6105 100644
--- a/tools/editor/icons/2x/icon_control_align_top_left.png
+++ b/editor/icons/2x/icon_control_align_top_left.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_top_right.png b/editor/icons/2x/icon_control_align_top_right.png
index 040b7b27ee..040b7b27ee 100644
--- a/tools/editor/icons/2x/icon_control_align_top_right.png
+++ b/editor/icons/2x/icon_control_align_top_right.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_top_wide.png b/editor/icons/2x/icon_control_align_top_wide.png
index 5c14782fc2..5c14782fc2 100644
--- a/tools/editor/icons/2x/icon_control_align_top_wide.png
+++ b/editor/icons/2x/icon_control_align_top_wide.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_align_wide.png b/editor/icons/2x/icon_control_align_wide.png
index 383b63d069..383b63d069 100644
--- a/tools/editor/icons/2x/icon_control_align_wide.png
+++ b/editor/icons/2x/icon_control_align_wide.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_hcenter_wide.png b/editor/icons/2x/icon_control_hcenter_wide.png
index 840ac557f5..840ac557f5 100644
--- a/tools/editor/icons/2x/icon_control_hcenter_wide.png
+++ b/editor/icons/2x/icon_control_hcenter_wide.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_control_vcenter_wide.png b/editor/icons/2x/icon_control_vcenter_wide.png
index a9e406d4b5..a9e406d4b5 100644
--- a/tools/editor/icons/2x/icon_control_vcenter_wide.png
+++ b/editor/icons/2x/icon_control_vcenter_wide.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_convex_polygon_shape.png b/editor/icons/2x/icon_convex_polygon_shape.png
index 40dd40f299..40dd40f299 100644
--- a/tools/editor/icons/2x/icon_convex_polygon_shape.png
+++ b/editor/icons/2x/icon_convex_polygon_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_convex_polygon_shape_2d.png b/editor/icons/2x/icon_convex_polygon_shape_2d.png
index 6d46a96f9d..6d46a96f9d 100644
--- a/tools/editor/icons/2x/icon_convex_polygon_shape_2d.png
+++ b/editor/icons/2x/icon_convex_polygon_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_copy_node_path.png b/editor/icons/2x/icon_copy_node_path.png
index 056748d20b..056748d20b 100644
--- a/tools/editor/icons/2x/icon_copy_node_path.png
+++ b/editor/icons/2x/icon_copy_node_path.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_create_new_scene_from.png b/editor/icons/2x/icon_create_new_scene_from.png
index cc3be48033..cc3be48033 100644
--- a/tools/editor/icons/2x/icon_create_new_scene_from.png
+++ b/editor/icons/2x/icon_create_new_scene_from.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_cube_map.png b/editor/icons/2x/icon_cube_map.png
index 0edf82a88e..0edf82a88e 100644
--- a/tools/editor/icons/2x/icon_cube_map.png
+++ b/editor/icons/2x/icon_cube_map.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_2d.png b/editor/icons/2x/icon_curve_2d.png
index 69a6f9a9dc..69a6f9a9dc 100644
--- a/tools/editor/icons/2x/icon_curve_2d.png
+++ b/editor/icons/2x/icon_curve_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_3d.png b/editor/icons/2x/icon_curve_3d.png
index e989df4769..e989df4769 100644
--- a/tools/editor/icons/2x/icon_curve_3d.png
+++ b/editor/icons/2x/icon_curve_3d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_close.png b/editor/icons/2x/icon_curve_close.png
index bd2de0edc8..bd2de0edc8 100644
--- a/tools/editor/icons/2x/icon_curve_close.png
+++ b/editor/icons/2x/icon_curve_close.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_constant.png b/editor/icons/2x/icon_curve_constant.png
index a6e32e0467..a6e32e0467 100644
--- a/tools/editor/icons/2x/icon_curve_constant.png
+++ b/editor/icons/2x/icon_curve_constant.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_create.png b/editor/icons/2x/icon_curve_create.png
index 39f10fd8db..39f10fd8db 100644
--- a/tools/editor/icons/2x/icon_curve_create.png
+++ b/editor/icons/2x/icon_curve_create.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_curve.png b/editor/icons/2x/icon_curve_curve.png
index 6476579a64..6476579a64 100644
--- a/tools/editor/icons/2x/icon_curve_curve.png
+++ b/editor/icons/2x/icon_curve_curve.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_delete.png b/editor/icons/2x/icon_curve_delete.png
index 60c081bbd0..60c081bbd0 100644
--- a/tools/editor/icons/2x/icon_curve_delete.png
+++ b/editor/icons/2x/icon_curve_delete.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_edit.png b/editor/icons/2x/icon_curve_edit.png
index f9701e05cb..f9701e05cb 100644
--- a/tools/editor/icons/2x/icon_curve_edit.png
+++ b/editor/icons/2x/icon_curve_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_in.png b/editor/icons/2x/icon_curve_in.png
index a018d28035..a018d28035 100644
--- a/tools/editor/icons/2x/icon_curve_in.png
+++ b/editor/icons/2x/icon_curve_in.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_in_out.png b/editor/icons/2x/icon_curve_in_out.png
index 8b8b8d7d8a..8b8b8d7d8a 100644
--- a/tools/editor/icons/2x/icon_curve_in_out.png
+++ b/editor/icons/2x/icon_curve_in_out.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_linear.png b/editor/icons/2x/icon_curve_linear.png
index 9733ec6f49..9733ec6f49 100644
--- a/tools/editor/icons/2x/icon_curve_linear.png
+++ b/editor/icons/2x/icon_curve_linear.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_out.png b/editor/icons/2x/icon_curve_out.png
index 49e62ef471..49e62ef471 100644
--- a/tools/editor/icons/2x/icon_curve_out.png
+++ b/editor/icons/2x/icon_curve_out.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_curve_out_in.png b/editor/icons/2x/icon_curve_out_in.png
index cc716cdbe8..cc716cdbe8 100644
--- a/tools/editor/icons/2x/icon_curve_out_in.png
+++ b/editor/icons/2x/icon_curve_out_in.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_damped_spring_joint_2d.png b/editor/icons/2x/icon_damped_spring_joint_2d.png
index a51081efca..a51081efca 100644
--- a/tools/editor/icons/2x/icon_damped_spring_joint_2d.png
+++ b/editor/icons/2x/icon_damped_spring_joint_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_debug_continue.png b/editor/icons/2x/icon_debug_continue.png
index be460bd61d..be460bd61d 100644
--- a/tools/editor/icons/2x/icon_debug_continue.png
+++ b/editor/icons/2x/icon_debug_continue.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_debug_next.png b/editor/icons/2x/icon_debug_next.png
index b52e276f36..b52e276f36 100644
--- a/tools/editor/icons/2x/icon_debug_next.png
+++ b/editor/icons/2x/icon_debug_next.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_debug_step.png b/editor/icons/2x/icon_debug_step.png
index e06a1ad56b..e06a1ad56b 100644
--- a/tools/editor/icons/2x/icon_debug_step.png
+++ b/editor/icons/2x/icon_debug_step.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dependency_changed.png b/editor/icons/2x/icon_dependency_changed.png
index 3ec13e0e3b..3ec13e0e3b 100644
--- a/tools/editor/icons/2x/icon_dependency_changed.png
+++ b/editor/icons/2x/icon_dependency_changed.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dependency_changed_hl.png b/editor/icons/2x/icon_dependency_changed_hl.png
index 630ea40554..630ea40554 100644
--- a/tools/editor/icons/2x/icon_dependency_changed_hl.png
+++ b/editor/icons/2x/icon_dependency_changed_hl.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dependency_local_changed.png b/editor/icons/2x/icon_dependency_local_changed.png
index 9bc2545439..9bc2545439 100644
--- a/tools/editor/icons/2x/icon_dependency_local_changed.png
+++ b/editor/icons/2x/icon_dependency_local_changed.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dependency_local_changed_hl.png b/editor/icons/2x/icon_dependency_local_changed_hl.png
index 385371df9f..385371df9f 100644
--- a/tools/editor/icons/2x/icon_dependency_local_changed_hl.png
+++ b/editor/icons/2x/icon_dependency_local_changed_hl.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dependency_ok.png b/editor/icons/2x/icon_dependency_ok.png
index 80fe7f573a..80fe7f573a 100644
--- a/tools/editor/icons/2x/icon_dependency_ok.png
+++ b/editor/icons/2x/icon_dependency_ok.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dependency_ok_hl.png b/editor/icons/2x/icon_dependency_ok_hl.png
index 9d496688cc..9d496688cc 100644
--- a/tools/editor/icons/2x/icon_dependency_ok_hl.png
+++ b/editor/icons/2x/icon_dependency_ok_hl.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_directional_light.png b/editor/icons/2x/icon_directional_light.png
index 9a35325aec..9a35325aec 100644
--- a/tools/editor/icons/2x/icon_directional_light.png
+++ b/editor/icons/2x/icon_directional_light.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_distraction_free.png b/editor/icons/2x/icon_distraction_free.png
index 034239a4e7..034239a4e7 100644
--- a/tools/editor/icons/2x/icon_distraction_free.png
+++ b/editor/icons/2x/icon_distraction_free.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_duplicate.png b/editor/icons/2x/icon_duplicate.png
index 37996482ae..37996482ae 100644
--- a/tools/editor/icons/2x/icon_duplicate.png
+++ b/editor/icons/2x/icon_duplicate.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dynamic_font.png b/editor/icons/2x/icon_dynamic_font.png
index 1f1dc52dfb..1f1dc52dfb 100644
--- a/tools/editor/icons/2x/icon_dynamic_font.png
+++ b/editor/icons/2x/icon_dynamic_font.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_dynamic_font_data.png b/editor/icons/2x/icon_dynamic_font_data.png
index 6d76303c81..6d76303c81 100644
--- a/tools/editor/icons/2x/icon_dynamic_font_data.png
+++ b/editor/icons/2x/icon_dynamic_font_data.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_edit.png b/editor/icons/2x/icon_edit.png
index b9ed2c3e58..b9ed2c3e58 100644
--- a/tools/editor/icons/2x/icon_edit.png
+++ b/editor/icons/2x/icon_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_edit_key.png b/editor/icons/2x/icon_edit_key.png
index 58b9a6e749..58b9a6e749 100644
--- a/tools/editor/icons/2x/icon_edit_key.png
+++ b/editor/icons/2x/icon_edit_key.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_edit_pivot.png b/editor/icons/2x/icon_edit_pivot.png
index ac5a2cafb9..ac5a2cafb9 100644
--- a/tools/editor/icons/2x/icon_edit_pivot.png
+++ b/editor/icons/2x/icon_edit_pivot.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_edit_resource.png b/editor/icons/2x/icon_edit_resource.png
index 5ba9b36b0a..5ba9b36b0a 100644
--- a/tools/editor/icons/2x/icon_edit_resource.png
+++ b/editor/icons/2x/icon_edit_resource.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_editor_3d_handle.png b/editor/icons/2x/icon_editor_3d_handle.png
index f76af85cc1..f76af85cc1 100644
--- a/tools/editor/icons/2x/icon_editor_3d_handle.png
+++ b/editor/icons/2x/icon_editor_3d_handle.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_editor_handle.png b/editor/icons/2x/icon_editor_handle.png
index 355d8fe155..355d8fe155 100644
--- a/tools/editor/icons/2x/icon_editor_handle.png
+++ b/editor/icons/2x/icon_editor_handle.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_editor_pivot.png b/editor/icons/2x/icon_editor_pivot.png
index e1666e38de..e1666e38de 100644
--- a/tools/editor/icons/2x/icon_editor_pivot.png
+++ b/editor/icons/2x/icon_editor_pivot.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_editor_plugin.png b/editor/icons/2x/icon_editor_plugin.png
index f6411bb323..f6411bb323 100644
--- a/tools/editor/icons/2x/icon_editor_plugin.png
+++ b/editor/icons/2x/icon_editor_plugin.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_enum.png b/editor/icons/2x/icon_enum.png
index d9df3a3ec3..d9df3a3ec3 100644
--- a/tools/editor/icons/2x/icon_enum.png
+++ b/editor/icons/2x/icon_enum.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_environment.png b/editor/icons/2x/icon_environment.png
index 4c4c30b0e5..4c4c30b0e5 100644
--- a/tools/editor/icons/2x/icon_environment.png
+++ b/editor/icons/2x/icon_environment.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_error.png b/editor/icons/2x/icon_error.png
index a6d79ab41b..a6d79ab41b 100644
--- a/tools/editor/icons/2x/icon_error.png
+++ b/editor/icons/2x/icon_error.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_error_sign.png b/editor/icons/2x/icon_error_sign.png
index f1d16ea669..f1d16ea669 100644
--- a/tools/editor/icons/2x/icon_error_sign.png
+++ b/editor/icons/2x/icon_error_sign.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_event_player.png b/editor/icons/2x/icon_event_player.png
index 2482c576db..2482c576db 100644
--- a/tools/editor/icons/2x/icon_event_player.png
+++ b/editor/icons/2x/icon_event_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_favorites.png b/editor/icons/2x/icon_favorites.png
index 7a63835b3d..7a63835b3d 100644
--- a/tools/editor/icons/2x/icon_favorites.png
+++ b/editor/icons/2x/icon_favorites.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_file.png b/editor/icons/2x/icon_file.png
index 683f1141fd..683f1141fd 100644
--- a/tools/editor/icons/2x/icon_file.png
+++ b/editor/icons/2x/icon_file.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_file_big.png b/editor/icons/2x/icon_file_big.png
index 8c86c6b958..8c86c6b958 100644
--- a/tools/editor/icons/2x/icon_file_big.png
+++ b/editor/icons/2x/icon_file_big.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_file_dialog.png b/editor/icons/2x/icon_file_dialog.png
index f19b4d7507..f19b4d7507 100644
--- a/tools/editor/icons/2x/icon_file_dialog.png
+++ b/editor/icons/2x/icon_file_dialog.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_file_list.png b/editor/icons/2x/icon_file_list.png
index d9df3a3ec3..d9df3a3ec3 100644
--- a/tools/editor/icons/2x/icon_file_list.png
+++ b/editor/icons/2x/icon_file_list.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_file_server.png b/editor/icons/2x/icon_file_server.png
index d8021a4067..d8021a4067 100644
--- a/tools/editor/icons/2x/icon_file_server.png
+++ b/editor/icons/2x/icon_file_server.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_file_server_active.png b/editor/icons/2x/icon_file_server_active.png
index f503fe406b..f503fe406b 100644
--- a/tools/editor/icons/2x/icon_file_server_active.png
+++ b/editor/icons/2x/icon_file_server_active.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_file_thumbnail.png b/editor/icons/2x/icon_file_thumbnail.png
index 5a8d282fe1..5a8d282fe1 100644
--- a/tools/editor/icons/2x/icon_file_thumbnail.png
+++ b/editor/icons/2x/icon_file_thumbnail.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_filesystem.png b/editor/icons/2x/icon_filesystem.png
index 4ae0b3edab..4ae0b3edab 100644
--- a/tools/editor/icons/2x/icon_filesystem.png
+++ b/editor/icons/2x/icon_filesystem.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_fixed_material.png b/editor/icons/2x/icon_fixed_material.png
index 21bfb15838..21bfb15838 100644
--- a/tools/editor/icons/2x/icon_fixed_material.png
+++ b/editor/icons/2x/icon_fixed_material.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_fixed_spatial_material.png b/editor/icons/2x/icon_fixed_spatial_material.png
index 65509a590e..65509a590e 100644
--- a/tools/editor/icons/2x/icon_fixed_spatial_material.png
+++ b/editor/icons/2x/icon_fixed_spatial_material.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_folder.png b/editor/icons/2x/icon_folder.png
index 2e797c448b..2e797c448b 100644
--- a/tools/editor/icons/2x/icon_folder.png
+++ b/editor/icons/2x/icon_folder.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_folder_big.png b/editor/icons/2x/icon_folder_big.png
index b89600619a..b89600619a 100644
--- a/tools/editor/icons/2x/icon_folder_big.png
+++ b/editor/icons/2x/icon_folder_big.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_font.png b/editor/icons/2x/icon_font.png
index b78c95a827..b78c95a827 100644
--- a/tools/editor/icons/2x/icon_font.png
+++ b/editor/icons/2x/icon_font.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_forward.png b/editor/icons/2x/icon_forward.png
index 11fd444a04..11fd444a04 100644
--- a/tools/editor/icons/2x/icon_forward.png
+++ b/editor/icons/2x/icon_forward.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_g_d_script.png b/editor/icons/2x/icon_g_d_script.png
index 6143191fc7..6143191fc7 100644
--- a/tools/editor/icons/2x/icon_g_d_script.png
+++ b/editor/icons/2x/icon_g_d_script.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_g_i_probe.png b/editor/icons/2x/icon_g_i_probe.png
index 921f1cca42..921f1cca42 100644
--- a/tools/editor/icons/2x/icon_g_i_probe.png
+++ b/editor/icons/2x/icon_g_i_probe.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_g_i_probe_data.png b/editor/icons/2x/icon_g_i_probe_data.png
index 69c4ed7184..69c4ed7184 100644
--- a/tools/editor/icons/2x/icon_g_i_probe_data.png
+++ b/editor/icons/2x/icon_g_i_probe_data.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_generic_6_d_o_f_joint.png b/editor/icons/2x/icon_generic_6_d_o_f_joint.png
index 506c873376..506c873376 100644
--- a/tools/editor/icons/2x/icon_generic_6_d_o_f_joint.png
+++ b/editor/icons/2x/icon_generic_6_d_o_f_joint.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_gizmo_directional_light.png b/editor/icons/2x/icon_gizmo_directional_light.png
index 0d02788040..0d02788040 100644
--- a/tools/editor/icons/2x/icon_gizmo_directional_light.png
+++ b/editor/icons/2x/icon_gizmo_directional_light.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_gizmo_light.png b/editor/icons/2x/icon_gizmo_light.png
index 2ba9689107..2ba9689107 100644
--- a/tools/editor/icons/2x/icon_gizmo_light.png
+++ b/editor/icons/2x/icon_gizmo_light.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_gizmo_listener.png b/editor/icons/2x/icon_gizmo_listener.png
index bc2908824d..bc2908824d 100644
--- a/tools/editor/icons/2x/icon_gizmo_listener.png
+++ b/editor/icons/2x/icon_gizmo_listener.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_gizmo_spatial_sample_player.png b/editor/icons/2x/icon_gizmo_spatial_sample_player.png
index 78a88c55c1..78a88c55c1 100644
--- a/tools/editor/icons/2x/icon_gizmo_spatial_sample_player.png
+++ b/editor/icons/2x/icon_gizmo_spatial_sample_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_gizmo_spatial_stream_player.png b/editor/icons/2x/icon_gizmo_spatial_stream_player.png
index 631f03e874..631f03e874 100644
--- a/tools/editor/icons/2x/icon_gizmo_spatial_stream_player.png
+++ b/editor/icons/2x/icon_gizmo_spatial_stream_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_godot.png b/editor/icons/2x/icon_godot.png
index 94d87e23cc..94d87e23cc 100644
--- a/tools/editor/icons/2x/icon_godot.png
+++ b/editor/icons/2x/icon_godot.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_color_ramp.png b/editor/icons/2x/icon_graph_color_ramp.png
index d0056f0c7d..d0056f0c7d 100644
--- a/tools/editor/icons/2x/icon_graph_color_ramp.png
+++ b/editor/icons/2x/icon_graph_color_ramp.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_comment.png b/editor/icons/2x/icon_graph_comment.png
index 3dedbfab52..3dedbfab52 100644
--- a/tools/editor/icons/2x/icon_graph_comment.png
+++ b/editor/icons/2x/icon_graph_comment.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_cube_uniform.png b/editor/icons/2x/icon_graph_cube_uniform.png
index 43ec1fa6d6..43ec1fa6d6 100644
--- a/tools/editor/icons/2x/icon_graph_cube_uniform.png
+++ b/editor/icons/2x/icon_graph_cube_uniform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_curve_map.png b/editor/icons/2x/icon_graph_curve_map.png
index f29086e503..f29086e503 100644
--- a/tools/editor/icons/2x/icon_graph_curve_map.png
+++ b/editor/icons/2x/icon_graph_curve_map.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_default_texture.png b/editor/icons/2x/icon_graph_default_texture.png
index 45e4470502..45e4470502 100644
--- a/tools/editor/icons/2x/icon_graph_default_texture.png
+++ b/editor/icons/2x/icon_graph_default_texture.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_edit.png b/editor/icons/2x/icon_graph_edit.png
index bd4386839d..bd4386839d 100644
--- a/tools/editor/icons/2x/icon_graph_edit.png
+++ b/editor/icons/2x/icon_graph_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_input.png b/editor/icons/2x/icon_graph_input.png
index 3eeb29a3e7..3eeb29a3e7 100644
--- a/tools/editor/icons/2x/icon_graph_input.png
+++ b/editor/icons/2x/icon_graph_input.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_node.png b/editor/icons/2x/icon_graph_node.png
index 7ce633af4d..7ce633af4d 100644
--- a/tools/editor/icons/2x/icon_graph_node.png
+++ b/editor/icons/2x/icon_graph_node.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_rgb.png b/editor/icons/2x/icon_graph_rgb.png
index a9c39f0222..a9c39f0222 100644
--- a/tools/editor/icons/2x/icon_graph_rgb.png
+++ b/editor/icons/2x/icon_graph_rgb.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_rgb_op.png b/editor/icons/2x/icon_graph_rgb_op.png
index 44812d8dd8..44812d8dd8 100644
--- a/tools/editor/icons/2x/icon_graph_rgb_op.png
+++ b/editor/icons/2x/icon_graph_rgb_op.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_rgb_uniform.png b/editor/icons/2x/icon_graph_rgb_uniform.png
index b06f1d4d8d..b06f1d4d8d 100644
--- a/tools/editor/icons/2x/icon_graph_rgb_uniform.png
+++ b/editor/icons/2x/icon_graph_rgb_uniform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_scalar.png b/editor/icons/2x/icon_graph_scalar.png
index 382c429d35..382c429d35 100644
--- a/tools/editor/icons/2x/icon_graph_scalar.png
+++ b/editor/icons/2x/icon_graph_scalar.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_scalar_interp.png b/editor/icons/2x/icon_graph_scalar_interp.png
index 430e35470f..430e35470f 100644
--- a/tools/editor/icons/2x/icon_graph_scalar_interp.png
+++ b/editor/icons/2x/icon_graph_scalar_interp.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_scalar_op.png b/editor/icons/2x/icon_graph_scalar_op.png
index b90b6a6190..b90b6a6190 100644
--- a/tools/editor/icons/2x/icon_graph_scalar_op.png
+++ b/editor/icons/2x/icon_graph_scalar_op.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_scalar_uniform.png b/editor/icons/2x/icon_graph_scalar_uniform.png
index dff850df03..dff850df03 100644
--- a/tools/editor/icons/2x/icon_graph_scalar_uniform.png
+++ b/editor/icons/2x/icon_graph_scalar_uniform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_scalars_to_vec.png b/editor/icons/2x/icon_graph_scalars_to_vec.png
index 266c84e5ae..266c84e5ae 100644
--- a/tools/editor/icons/2x/icon_graph_scalars_to_vec.png
+++ b/editor/icons/2x/icon_graph_scalars_to_vec.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_texscreen.png b/editor/icons/2x/icon_graph_texscreen.png
index 8b1d250129..8b1d250129 100644
--- a/tools/editor/icons/2x/icon_graph_texscreen.png
+++ b/editor/icons/2x/icon_graph_texscreen.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_texture_uniform.png b/editor/icons/2x/icon_graph_texture_uniform.png
index ee211b6c03..ee211b6c03 100644
--- a/tools/editor/icons/2x/icon_graph_texture_uniform.png
+++ b/editor/icons/2x/icon_graph_texture_uniform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_time.png b/editor/icons/2x/icon_graph_time.png
index 3cf9bf2035..3cf9bf2035 100644
--- a/tools/editor/icons/2x/icon_graph_time.png
+++ b/editor/icons/2x/icon_graph_time.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vec_dp.png b/editor/icons/2x/icon_graph_vec_dp.png
index e339f6a1e8..e339f6a1e8 100644
--- a/tools/editor/icons/2x/icon_graph_vec_dp.png
+++ b/editor/icons/2x/icon_graph_vec_dp.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vec_interp.png b/editor/icons/2x/icon_graph_vec_interp.png
index 02e7915748..02e7915748 100644
--- a/tools/editor/icons/2x/icon_graph_vec_interp.png
+++ b/editor/icons/2x/icon_graph_vec_interp.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vec_length.png b/editor/icons/2x/icon_graph_vec_length.png
index 857e006b6e..857e006b6e 100644
--- a/tools/editor/icons/2x/icon_graph_vec_length.png
+++ b/editor/icons/2x/icon_graph_vec_length.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vec_op.png b/editor/icons/2x/icon_graph_vec_op.png
index 282336f9d0..282336f9d0 100644
--- a/tools/editor/icons/2x/icon_graph_vec_op.png
+++ b/editor/icons/2x/icon_graph_vec_op.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vec_scalar_op.png b/editor/icons/2x/icon_graph_vec_scalar_op.png
index 38d355ef06..38d355ef06 100644
--- a/tools/editor/icons/2x/icon_graph_vec_scalar_op.png
+++ b/editor/icons/2x/icon_graph_vec_scalar_op.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vec_to_scalars.png b/editor/icons/2x/icon_graph_vec_to_scalars.png
index 1b8254b3c6..1b8254b3c6 100644
--- a/tools/editor/icons/2x/icon_graph_vec_to_scalars.png
+++ b/editor/icons/2x/icon_graph_vec_to_scalars.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vecs_to_xform.png b/editor/icons/2x/icon_graph_vecs_to_xform.png
index a9ed5052be..a9ed5052be 100644
--- a/tools/editor/icons/2x/icon_graph_vecs_to_xform.png
+++ b/editor/icons/2x/icon_graph_vecs_to_xform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vector.png b/editor/icons/2x/icon_graph_vector.png
index eb4e94acee..eb4e94acee 100644
--- a/tools/editor/icons/2x/icon_graph_vector.png
+++ b/editor/icons/2x/icon_graph_vector.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_vector_uniform.png b/editor/icons/2x/icon_graph_vector_uniform.png
index 94cde72904..94cde72904 100644
--- a/tools/editor/icons/2x/icon_graph_vector_uniform.png
+++ b/editor/icons/2x/icon_graph_vector_uniform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform.png b/editor/icons/2x/icon_graph_xform.png
index 4d823e2aa9..4d823e2aa9 100644
--- a/tools/editor/icons/2x/icon_graph_xform.png
+++ b/editor/icons/2x/icon_graph_xform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform_mult.png b/editor/icons/2x/icon_graph_xform_mult.png
index a6d41e43a4..a6d41e43a4 100644
--- a/tools/editor/icons/2x/icon_graph_xform_mult.png
+++ b/editor/icons/2x/icon_graph_xform_mult.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform_scalar_func.png b/editor/icons/2x/icon_graph_xform_scalar_func.png
index 06826a1ca2..06826a1ca2 100644
--- a/tools/editor/icons/2x/icon_graph_xform_scalar_func.png
+++ b/editor/icons/2x/icon_graph_xform_scalar_func.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform_to_vecs.png b/editor/icons/2x/icon_graph_xform_to_vecs.png
index 22125df573..22125df573 100644
--- a/tools/editor/icons/2x/icon_graph_xform_to_vecs.png
+++ b/editor/icons/2x/icon_graph_xform_to_vecs.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform_uniform.png b/editor/icons/2x/icon_graph_xform_uniform.png
index b87f9936b8..b87f9936b8 100644
--- a/tools/editor/icons/2x/icon_graph_xform_uniform.png
+++ b/editor/icons/2x/icon_graph_xform_uniform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform_vec_func.png b/editor/icons/2x/icon_graph_xform_vec_func.png
index 007555ff7b..007555ff7b 100644
--- a/tools/editor/icons/2x/icon_graph_xform_vec_func.png
+++ b/editor/icons/2x/icon_graph_xform_vec_func.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform_vec_imult.png b/editor/icons/2x/icon_graph_xform_vec_imult.png
index 39e25ef9b3..39e25ef9b3 100644
--- a/tools/editor/icons/2x/icon_graph_xform_vec_imult.png
+++ b/editor/icons/2x/icon_graph_xform_vec_imult.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_graph_xform_vec_mult.png b/editor/icons/2x/icon_graph_xform_vec_mult.png
index 32802fa1ed..32802fa1ed 100644
--- a/tools/editor/icons/2x/icon_graph_xform_vec_mult.png
+++ b/editor/icons/2x/icon_graph_xform_vec_mult.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_grid.png b/editor/icons/2x/icon_grid.png
index 99d896c012..99d896c012 100644
--- a/tools/editor/icons/2x/icon_grid.png
+++ b/editor/icons/2x/icon_grid.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_grid_container.png b/editor/icons/2x/icon_grid_container.png
index b83b1f4347..b83b1f4347 100644
--- a/tools/editor/icons/2x/icon_grid_container.png
+++ b/editor/icons/2x/icon_grid_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_grid_map.png b/editor/icons/2x/icon_grid_map.png
index 5bbd16d3df..5bbd16d3df 100644
--- a/tools/editor/icons/2x/icon_grid_map.png
+++ b/editor/icons/2x/icon_grid_map.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_groove_joint_2d.png b/editor/icons/2x/icon_groove_joint_2d.png
index ab9cd4f3eb..ab9cd4f3eb 100644
--- a/tools/editor/icons/2x/icon_groove_joint_2d.png
+++ b/editor/icons/2x/icon_groove_joint_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_group.png b/editor/icons/2x/icon_group.png
index 158efa5fe4..158efa5fe4 100644
--- a/tools/editor/icons/2x/icon_group.png
+++ b/editor/icons/2x/icon_group.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_groups.png b/editor/icons/2x/icon_groups.png
index 203d36071b..203d36071b 100644
--- a/tools/editor/icons/2x/icon_groups.png
+++ b/editor/icons/2x/icon_groups.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_box_container.png b/editor/icons/2x/icon_h_box_container.png
index 3767cab1cf..3767cab1cf 100644
--- a/tools/editor/icons/2x/icon_h_box_container.png
+++ b/editor/icons/2x/icon_h_box_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_button_array.png b/editor/icons/2x/icon_h_button_array.png
index 750eef8267..750eef8267 100644
--- a/tools/editor/icons/2x/icon_h_button_array.png
+++ b/editor/icons/2x/icon_h_button_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_scroll_bar.png b/editor/icons/2x/icon_h_scroll_bar.png
index d15a36bb16..d15a36bb16 100644
--- a/tools/editor/icons/2x/icon_h_scroll_bar.png
+++ b/editor/icons/2x/icon_h_scroll_bar.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_separator.png b/editor/icons/2x/icon_h_separator.png
index 7dd7e1e314..7dd7e1e314 100644
--- a/tools/editor/icons/2x/icon_h_separator.png
+++ b/editor/icons/2x/icon_h_separator.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_slider.png b/editor/icons/2x/icon_h_slider.png
index 50bad1cc18..50bad1cc18 100644
--- a/tools/editor/icons/2x/icon_h_slider.png
+++ b/editor/icons/2x/icon_h_slider.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_split_container.png b/editor/icons/2x/icon_h_split_container.png
index 33e18946c1..33e18946c1 100644
--- a/tools/editor/icons/2x/icon_h_split_container.png
+++ b/editor/icons/2x/icon_h_split_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_t_t_p_request.png b/editor/icons/2x/icon_h_t_t_p_request.png
index a334dea4e2..a334dea4e2 100644
--- a/tools/editor/icons/2x/icon_h_t_t_p_request.png
+++ b/editor/icons/2x/icon_h_t_t_p_request.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_headphones.png b/editor/icons/2x/icon_headphones.png
index eca62b9372..eca62b9372 100644
--- a/tools/editor/icons/2x/icon_headphones.png
+++ b/editor/icons/2x/icon_headphones.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_help.png b/editor/icons/2x/icon_help.png
index f16a34c918..f16a34c918 100644
--- a/tools/editor/icons/2x/icon_help.png
+++ b/editor/icons/2x/icon_help.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_hidden.png b/editor/icons/2x/icon_hidden.png
index 09d38c5bef..09d38c5bef 100644
--- a/tools/editor/icons/2x/icon_hidden.png
+++ b/editor/icons/2x/icon_hidden.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_hinge_joint.png b/editor/icons/2x/icon_hinge_joint.png
index b888102573..b888102573 100644
--- a/tools/editor/icons/2x/icon_hinge_joint.png
+++ b/editor/icons/2x/icon_hinge_joint.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_history.png b/editor/icons/2x/icon_history.png
index 153a2b4edf..153a2b4edf 100644
--- a/tools/editor/icons/2x/icon_history.png
+++ b/editor/icons/2x/icon_history.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_hsize.png b/editor/icons/2x/icon_hsize.png
index 3b096dce88..3b096dce88 100644
--- a/tools/editor/icons/2x/icon_hsize.png
+++ b/editor/icons/2x/icon_hsize.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_image.png b/editor/icons/2x/icon_image.png
index 951b2242f1..951b2242f1 100644
--- a/tools/editor/icons/2x/icon_image.png
+++ b/editor/icons/2x/icon_image.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_image_sky_box.png b/editor/icons/2x/icon_image_sky_box.png
index 487178afab..487178afab 100644
--- a/tools/editor/icons/2x/icon_image_sky_box.png
+++ b/editor/icons/2x/icon_image_sky_box.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_image_texture.png b/editor/icons/2x/icon_image_texture.png
index ad5d04dfee..ad5d04dfee 100644
--- a/tools/editor/icons/2x/icon_image_texture.png
+++ b/editor/icons/2x/icon_image_texture.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_immediate_geometry.png b/editor/icons/2x/icon_immediate_geometry.png
index 5fafecadc3..5fafecadc3 100644
--- a/tools/editor/icons/2x/icon_immediate_geometry.png
+++ b/editor/icons/2x/icon_immediate_geometry.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_import_check.png b/editor/icons/2x/icon_import_check.png
index 98e76e2640..98e76e2640 100644
--- a/tools/editor/icons/2x/icon_import_check.png
+++ b/editor/icons/2x/icon_import_check.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_import_fail.png b/editor/icons/2x/icon_import_fail.png
index f89c2f5c75..f89c2f5c75 100644
--- a/tools/editor/icons/2x/icon_import_fail.png
+++ b/editor/icons/2x/icon_import_fail.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_instance.png b/editor/icons/2x/icon_instance.png
index 9b4731de03..9b4731de03 100644
--- a/tools/editor/icons/2x/icon_instance.png
+++ b/editor/icons/2x/icon_instance.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_instance_options.png b/editor/icons/2x/icon_instance_options.png
index 28e2db25f2..28e2db25f2 100644
--- a/tools/editor/icons/2x/icon_instance_options.png
+++ b/editor/icons/2x/icon_instance_options.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_integer.png b/editor/icons/2x/icon_integer.png
index 7ad2f62458..7ad2f62458 100644
--- a/tools/editor/icons/2x/icon_integer.png
+++ b/editor/icons/2x/icon_integer.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_interp_cubic.png b/editor/icons/2x/icon_interp_cubic.png
index e33bb65577..e33bb65577 100644
--- a/tools/editor/icons/2x/icon_interp_cubic.png
+++ b/editor/icons/2x/icon_interp_cubic.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_interp_linear.png b/editor/icons/2x/icon_interp_linear.png
index 205f7febd5..205f7febd5 100644
--- a/tools/editor/icons/2x/icon_interp_linear.png
+++ b/editor/icons/2x/icon_interp_linear.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_interp_raw.png b/editor/icons/2x/icon_interp_raw.png
index 848ef07be6..848ef07be6 100644
--- a/tools/editor/icons/2x/icon_interp_raw.png
+++ b/editor/icons/2x/icon_interp_raw.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_interp_wrap_clamp.png b/editor/icons/2x/icon_interp_wrap_clamp.png
index 93a5bc56ee..93a5bc56ee 100644
--- a/tools/editor/icons/2x/icon_interp_wrap_clamp.png
+++ b/editor/icons/2x/icon_interp_wrap_clamp.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_interp_wrap_loop.png b/editor/icons/2x/icon_interp_wrap_loop.png
index 3e656f7b07..3e656f7b07 100644
--- a/tools/editor/icons/2x/icon_interp_wrap_loop.png
+++ b/editor/icons/2x/icon_interp_wrap_loop.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_interpolated_camera.png b/editor/icons/2x/icon_interpolated_camera.png
index e4551a84ce..e4551a84ce 100644
--- a/tools/editor/icons/2x/icon_interpolated_camera.png
+++ b/editor/icons/2x/icon_interpolated_camera.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_invalid_key.png b/editor/icons/2x/icon_invalid_key.png
index c34f2bc276..c34f2bc276 100644
--- a/tools/editor/icons/2x/icon_invalid_key.png
+++ b/editor/icons/2x/icon_invalid_key.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_inverse_kinematics.png b/editor/icons/2x/icon_inverse_kinematics.png
index 3b10c9590c..3b10c9590c 100644
--- a/tools/editor/icons/2x/icon_inverse_kinematics.png
+++ b/editor/icons/2x/icon_inverse_kinematics.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_item_list.png b/editor/icons/2x/icon_item_list.png
index 11a375caac..11a375caac 100644
--- a/tools/editor/icons/2x/icon_item_list.png
+++ b/editor/icons/2x/icon_item_list.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_joy_axis.png b/editor/icons/2x/icon_joy_axis.png
index 90f3d7a444..90f3d7a444 100644
--- a/tools/editor/icons/2x/icon_joy_axis.png
+++ b/editor/icons/2x/icon_joy_axis.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_joy_button.png b/editor/icons/2x/icon_joy_button.png
index a6b911ba1b..a6b911ba1b 100644
--- a/tools/editor/icons/2x/icon_joy_button.png
+++ b/editor/icons/2x/icon_joy_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_joypad.png b/editor/icons/2x/icon_joypad.png
index 285d048544..285d048544 100644
--- a/tools/editor/icons/2x/icon_joypad.png
+++ b/editor/icons/2x/icon_joypad.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key.png b/editor/icons/2x/icon_key.png
index d0c07bb1ea..d0c07bb1ea 100644
--- a/tools/editor/icons/2x/icon_key.png
+++ b/editor/icons/2x/icon_key.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key_hover.png b/editor/icons/2x/icon_key_hover.png
index c9894ad8bf..c9894ad8bf 100644
--- a/tools/editor/icons/2x/icon_key_hover.png
+++ b/editor/icons/2x/icon_key_hover.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key_invalid.png b/editor/icons/2x/icon_key_invalid.png
index c34f2bc276..c34f2bc276 100644
--- a/tools/editor/icons/2x/icon_key_invalid.png
+++ b/editor/icons/2x/icon_key_invalid.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key_next.png b/editor/icons/2x/icon_key_next.png
index d35b52d3c7..d35b52d3c7 100644
--- a/tools/editor/icons/2x/icon_key_next.png
+++ b/editor/icons/2x/icon_key_next.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key_selected.png b/editor/icons/2x/icon_key_selected.png
index 243dacb604..243dacb604 100644
--- a/tools/editor/icons/2x/icon_key_selected.png
+++ b/editor/icons/2x/icon_key_selected.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key_value.png b/editor/icons/2x/icon_key_value.png
index 3863403706..3863403706 100644
--- a/tools/editor/icons/2x/icon_key_value.png
+++ b/editor/icons/2x/icon_key_value.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_key_xform.png b/editor/icons/2x/icon_key_xform.png
index 70c49b5b5f..70c49b5b5f 100644
--- a/tools/editor/icons/2x/icon_key_xform.png
+++ b/editor/icons/2x/icon_key_xform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_keyboard.png b/editor/icons/2x/icon_keyboard.png
index a7daa06cc2..a7daa06cc2 100644
--- a/tools/editor/icons/2x/icon_keyboard.png
+++ b/editor/icons/2x/icon_keyboard.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_kinematic_body.png b/editor/icons/2x/icon_kinematic_body.png
index 59298dfa72..59298dfa72 100644
--- a/tools/editor/icons/2x/icon_kinematic_body.png
+++ b/editor/icons/2x/icon_kinematic_body.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_kinematic_body_2d.png b/editor/icons/2x/icon_kinematic_body_2d.png
index 5fd3b319ac..5fd3b319ac 100644
--- a/tools/editor/icons/2x/icon_kinematic_body_2d.png
+++ b/editor/icons/2x/icon_kinematic_body_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_label.png b/editor/icons/2x/icon_label.png
index c5e3bc844d..c5e3bc844d 100644
--- a/tools/editor/icons/2x/icon_label.png
+++ b/editor/icons/2x/icon_label.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_large_texture.png b/editor/icons/2x/icon_large_texture.png
index dd1ec86d39..dd1ec86d39 100644
--- a/tools/editor/icons/2x/icon_large_texture.png
+++ b/editor/icons/2x/icon_large_texture.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_light_2d.png b/editor/icons/2x/icon_light_2d.png
index d441659354..d441659354 100644
--- a/tools/editor/icons/2x/icon_light_2d.png
+++ b/editor/icons/2x/icon_light_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_light_occluder_2d.png b/editor/icons/2x/icon_light_occluder_2d.png
index 90e4387297..90e4387297 100644
--- a/tools/editor/icons/2x/icon_light_occluder_2d.png
+++ b/editor/icons/2x/icon_light_occluder_2d.png
Binary files differ
diff --git a/editor/icons/2x/icon_line_2d.png b/editor/icons/2x/icon_line_2d.png
new file mode 100644
index 0000000000..27299a2b69
--- /dev/null
+++ b/editor/icons/2x/icon_line_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_line_edit.png b/editor/icons/2x/icon_line_edit.png
index d0c987388f..d0c987388f 100644
--- a/tools/editor/icons/2x/icon_line_edit.png
+++ b/editor/icons/2x/icon_line_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_line_shape_2d.png b/editor/icons/2x/icon_line_shape_2d.png
index 490db5ca5b..490db5ca5b 100644
--- a/tools/editor/icons/2x/icon_line_shape_2d.png
+++ b/editor/icons/2x/icon_line_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_link_button.png b/editor/icons/2x/icon_link_button.png
index 20f300a553..20f300a553 100644
--- a/tools/editor/icons/2x/icon_link_button.png
+++ b/editor/icons/2x/icon_link_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_list_select.png b/editor/icons/2x/icon_list_select.png
index 9f7fa5b865..9f7fa5b865 100644
--- a/tools/editor/icons/2x/icon_list_select.png
+++ b/editor/icons/2x/icon_list_select.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_listener.png b/editor/icons/2x/icon_listener.png
index 1441a81bdd..1441a81bdd 100644
--- a/tools/editor/icons/2x/icon_listener.png
+++ b/editor/icons/2x/icon_listener.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_load.png b/editor/icons/2x/icon_load.png
index 759381d636..759381d636 100644
--- a/tools/editor/icons/2x/icon_load.png
+++ b/editor/icons/2x/icon_load.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_lock.png b/editor/icons/2x/icon_lock.png
index 912eaf9eb9..912eaf9eb9 100644
--- a/tools/editor/icons/2x/icon_lock.png
+++ b/editor/icons/2x/icon_lock.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_loop.png b/editor/icons/2x/icon_loop.png
index bd1322ae00..bd1322ae00 100644
--- a/tools/editor/icons/2x/icon_loop.png
+++ b/editor/icons/2x/icon_loop.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_loop_interpolation.png b/editor/icons/2x/icon_loop_interpolation.png
index 6009b50300..6009b50300 100644
--- a/tools/editor/icons/2x/icon_loop_interpolation.png
+++ b/editor/icons/2x/icon_loop_interpolation.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_main_play.png b/editor/icons/2x/icon_main_play.png
index 1f69ce6f17..1f69ce6f17 100644
--- a/tools/editor/icons/2x/icon_main_play.png
+++ b/editor/icons/2x/icon_main_play.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_main_stop.png b/editor/icons/2x/icon_main_stop.png
index 5048141485..5048141485 100644
--- a/tools/editor/icons/2x/icon_main_stop.png
+++ b/editor/icons/2x/icon_main_stop.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_margin_container.png b/editor/icons/2x/icon_margin_container.png
index 10eda265e0..10eda265e0 100644
--- a/tools/editor/icons/2x/icon_margin_container.png
+++ b/editor/icons/2x/icon_margin_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_cube.png b/editor/icons/2x/icon_material_preview_cube.png
index 2507c969c3..2507c969c3 100644
--- a/tools/editor/icons/2x/icon_material_preview_cube.png
+++ b/editor/icons/2x/icon_material_preview_cube.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_cube_off.png b/editor/icons/2x/icon_material_preview_cube_off.png
index 079b3a6645..079b3a6645 100644
--- a/tools/editor/icons/2x/icon_material_preview_cube_off.png
+++ b/editor/icons/2x/icon_material_preview_cube_off.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_light_1.png b/editor/icons/2x/icon_material_preview_light_1.png
index f1d0ccdaca..f1d0ccdaca 100644
--- a/tools/editor/icons/2x/icon_material_preview_light_1.png
+++ b/editor/icons/2x/icon_material_preview_light_1.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_light_1_off.png b/editor/icons/2x/icon_material_preview_light_1_off.png
index 5a42b7f2a1..5a42b7f2a1 100644
--- a/tools/editor/icons/2x/icon_material_preview_light_1_off.png
+++ b/editor/icons/2x/icon_material_preview_light_1_off.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_light_2.png b/editor/icons/2x/icon_material_preview_light_2.png
index 934e696b51..934e696b51 100644
--- a/tools/editor/icons/2x/icon_material_preview_light_2.png
+++ b/editor/icons/2x/icon_material_preview_light_2.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_light_2_off.png b/editor/icons/2x/icon_material_preview_light_2_off.png
index 1aa4c0bb79..1aa4c0bb79 100644
--- a/tools/editor/icons/2x/icon_material_preview_light_2_off.png
+++ b/editor/icons/2x/icon_material_preview_light_2_off.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_sphere.png b/editor/icons/2x/icon_material_preview_sphere.png
index f5cc7f7819..f5cc7f7819 100644
--- a/tools/editor/icons/2x/icon_material_preview_sphere.png
+++ b/editor/icons/2x/icon_material_preview_sphere.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_preview_sphere_off.png b/editor/icons/2x/icon_material_preview_sphere_off.png
index 7ccef62553..7ccef62553 100644
--- a/tools/editor/icons/2x/icon_material_preview_sphere_off.png
+++ b/editor/icons/2x/icon_material_preview_sphere_off.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_shader.png b/editor/icons/2x/icon_material_shader.png
index f8c2e15fcb..f8c2e15fcb 100644
--- a/tools/editor/icons/2x/icon_material_shader.png
+++ b/editor/icons/2x/icon_material_shader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_material_shader_graph.png b/editor/icons/2x/icon_material_shader_graph.png
index a26a9754fe..a26a9754fe 100644
--- a/tools/editor/icons/2x/icon_material_shader_graph.png
+++ b/editor/icons/2x/icon_material_shader_graph.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_matrix.png b/editor/icons/2x/icon_matrix.png
index 0ac4ae170b..0ac4ae170b 100644
--- a/tools/editor/icons/2x/icon_matrix.png
+++ b/editor/icons/2x/icon_matrix.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_menu_button.png b/editor/icons/2x/icon_menu_button.png
index abf9b490e3..abf9b490e3 100644
--- a/tools/editor/icons/2x/icon_menu_button.png
+++ b/editor/icons/2x/icon_menu_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mesh.png b/editor/icons/2x/icon_mesh.png
index 19b9095619..19b9095619 100644
--- a/tools/editor/icons/2x/icon_mesh.png
+++ b/editor/icons/2x/icon_mesh.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mesh_instance.png b/editor/icons/2x/icon_mesh_instance.png
index 02f3f5ffaa..02f3f5ffaa 100644
--- a/tools/editor/icons/2x/icon_mesh_instance.png
+++ b/editor/icons/2x/icon_mesh_instance.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mesh_library.png b/editor/icons/2x/icon_mesh_library.png
index 2495e4a037..2495e4a037 100644
--- a/tools/editor/icons/2x/icon_mesh_library.png
+++ b/editor/icons/2x/icon_mesh_library.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_aabb.png b/editor/icons/2x/icon_mini_aabb.png
index 25603eec49..25603eec49 100644
--- a/tools/editor/icons/2x/icon_mini_aabb.png
+++ b/editor/icons/2x/icon_mini_aabb.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_array.png b/editor/icons/2x/icon_mini_array.png
index 5c7bde2639..5c7bde2639 100644
--- a/tools/editor/icons/2x/icon_mini_array.png
+++ b/editor/icons/2x/icon_mini_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_boolean.png b/editor/icons/2x/icon_mini_boolean.png
index a7d00056bb..a7d00056bb 100644
--- a/tools/editor/icons/2x/icon_mini_boolean.png
+++ b/editor/icons/2x/icon_mini_boolean.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_color.png b/editor/icons/2x/icon_mini_color.png
index f4059bfb91..f4059bfb91 100644
--- a/tools/editor/icons/2x/icon_mini_color.png
+++ b/editor/icons/2x/icon_mini_color.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_color_array.png b/editor/icons/2x/icon_mini_color_array.png
index 26f1d9fce4..26f1d9fce4 100644
--- a/tools/editor/icons/2x/icon_mini_color_array.png
+++ b/editor/icons/2x/icon_mini_color_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_dictionary.png b/editor/icons/2x/icon_mini_dictionary.png
index 241e0587b4..241e0587b4 100644
--- a/tools/editor/icons/2x/icon_mini_dictionary.png
+++ b/editor/icons/2x/icon_mini_dictionary.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_float.png b/editor/icons/2x/icon_mini_float.png
index 6edf76ece1..6edf76ece1 100644
--- a/tools/editor/icons/2x/icon_mini_float.png
+++ b/editor/icons/2x/icon_mini_float.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_float_array.png b/editor/icons/2x/icon_mini_float_array.png
index 5a79fab721..5a79fab721 100644
--- a/tools/editor/icons/2x/icon_mini_float_array.png
+++ b/editor/icons/2x/icon_mini_float_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_image.png b/editor/icons/2x/icon_mini_image.png
index 98faebeef2..98faebeef2 100644
--- a/tools/editor/icons/2x/icon_mini_image.png
+++ b/editor/icons/2x/icon_mini_image.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_input.png b/editor/icons/2x/icon_mini_input.png
index 48536e156c..48536e156c 100644
--- a/tools/editor/icons/2x/icon_mini_input.png
+++ b/editor/icons/2x/icon_mini_input.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_int_array.png b/editor/icons/2x/icon_mini_int_array.png
index 790ed44c30..790ed44c30 100644
--- a/tools/editor/icons/2x/icon_mini_int_array.png
+++ b/editor/icons/2x/icon_mini_int_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_integer.png b/editor/icons/2x/icon_mini_integer.png
index cd9118f024..cd9118f024 100644
--- a/tools/editor/icons/2x/icon_mini_integer.png
+++ b/editor/icons/2x/icon_mini_integer.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_matrix3.png b/editor/icons/2x/icon_mini_matrix3.png
index 93783177e1..93783177e1 100644
--- a/tools/editor/icons/2x/icon_mini_matrix3.png
+++ b/editor/icons/2x/icon_mini_matrix3.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_matrix32.png b/editor/icons/2x/icon_mini_matrix32.png
index c2f7ea3817..c2f7ea3817 100644
--- a/tools/editor/icons/2x/icon_mini_matrix32.png
+++ b/editor/icons/2x/icon_mini_matrix32.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_object.png b/editor/icons/2x/icon_mini_object.png
index 7987f750ff..7987f750ff 100644
--- a/tools/editor/icons/2x/icon_mini_object.png
+++ b/editor/icons/2x/icon_mini_object.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_path.png b/editor/icons/2x/icon_mini_path.png
index 2e60a46086..2e60a46086 100644
--- a/tools/editor/icons/2x/icon_mini_path.png
+++ b/editor/icons/2x/icon_mini_path.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_plane.png b/editor/icons/2x/icon_mini_plane.png
index 12b5cd26cc..12b5cd26cc 100644
--- a/tools/editor/icons/2x/icon_mini_plane.png
+++ b/editor/icons/2x/icon_mini_plane.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_quat.png b/editor/icons/2x/icon_mini_quat.png
index 9a33902e59..9a33902e59 100644
--- a/tools/editor/icons/2x/icon_mini_quat.png
+++ b/editor/icons/2x/icon_mini_quat.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_raw_array.png b/editor/icons/2x/icon_mini_raw_array.png
index 629b01e72a..629b01e72a 100644
--- a/tools/editor/icons/2x/icon_mini_raw_array.png
+++ b/editor/icons/2x/icon_mini_raw_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_rect2.png b/editor/icons/2x/icon_mini_rect2.png
index 88b12e3a3a..88b12e3a3a 100644
--- a/tools/editor/icons/2x/icon_mini_rect2.png
+++ b/editor/icons/2x/icon_mini_rect2.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_rid.png b/editor/icons/2x/icon_mini_rid.png
index 5388c19817..5388c19817 100644
--- a/tools/editor/icons/2x/icon_mini_rid.png
+++ b/editor/icons/2x/icon_mini_rid.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_string.png b/editor/icons/2x/icon_mini_string.png
index 2264451c73..2264451c73 100644
--- a/tools/editor/icons/2x/icon_mini_string.png
+++ b/editor/icons/2x/icon_mini_string.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_string_array.png b/editor/icons/2x/icon_mini_string_array.png
index fa8109b88a..fa8109b88a 100644
--- a/tools/editor/icons/2x/icon_mini_string_array.png
+++ b/editor/icons/2x/icon_mini_string_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_transform.png b/editor/icons/2x/icon_mini_transform.png
index 5144871c5c..5144871c5c 100644
--- a/tools/editor/icons/2x/icon_mini_transform.png
+++ b/editor/icons/2x/icon_mini_transform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_variant.png b/editor/icons/2x/icon_mini_variant.png
index ae0aad16cf..ae0aad16cf 100644
--- a/tools/editor/icons/2x/icon_mini_variant.png
+++ b/editor/icons/2x/icon_mini_variant.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_vector2.png b/editor/icons/2x/icon_mini_vector2.png
index 9e608e61c1..9e608e61c1 100644
--- a/tools/editor/icons/2x/icon_mini_vector2.png
+++ b/editor/icons/2x/icon_mini_vector2.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_vector2_array.png b/editor/icons/2x/icon_mini_vector2_array.png
index 247c0e2592..247c0e2592 100644
--- a/tools/editor/icons/2x/icon_mini_vector2_array.png
+++ b/editor/icons/2x/icon_mini_vector2_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_vector3.png b/editor/icons/2x/icon_mini_vector3.png
index 0b84b4628f..0b84b4628f 100644
--- a/tools/editor/icons/2x/icon_mini_vector3.png
+++ b/editor/icons/2x/icon_mini_vector3.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mini_vector3_array.png b/editor/icons/2x/icon_mini_vector3_array.png
index 68058e4232..68058e4232 100644
--- a/tools/editor/icons/2x/icon_mini_vector3_array.png
+++ b/editor/icons/2x/icon_mini_vector3_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mirror_x.png b/editor/icons/2x/icon_mirror_x.png
index 3b096dce88..3b096dce88 100644
--- a/tools/editor/icons/2x/icon_mirror_x.png
+++ b/editor/icons/2x/icon_mirror_x.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mirror_y.png b/editor/icons/2x/icon_mirror_y.png
index 4c89b167b5..4c89b167b5 100644
--- a/tools/editor/icons/2x/icon_mirror_y.png
+++ b/editor/icons/2x/icon_mirror_y.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_mouse.png b/editor/icons/2x/icon_mouse.png
index 9c4a76bd4f..9c4a76bd4f 100644
--- a/tools/editor/icons/2x/icon_mouse.png
+++ b/editor/icons/2x/icon_mouse.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_move_down.png b/editor/icons/2x/icon_move_down.png
index 97bbeea631..97bbeea631 100644
--- a/tools/editor/icons/2x/icon_move_down.png
+++ b/editor/icons/2x/icon_move_down.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_move_point.png b/editor/icons/2x/icon_move_point.png
index 5d135ae294..5d135ae294 100644
--- a/tools/editor/icons/2x/icon_move_point.png
+++ b/editor/icons/2x/icon_move_point.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_move_up.png b/editor/icons/2x/icon_move_up.png
index f8f31baeb1..f8f31baeb1 100644
--- a/tools/editor/icons/2x/icon_move_up.png
+++ b/editor/icons/2x/icon_move_up.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_multi_edit.png b/editor/icons/2x/icon_multi_edit.png
index 93360b93f7..93360b93f7 100644
--- a/tools/editor/icons/2x/icon_multi_edit.png
+++ b/editor/icons/2x/icon_multi_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_multi_line.png b/editor/icons/2x/icon_multi_line.png
index 5d43b79e8a..5d43b79e8a 100644
--- a/tools/editor/icons/2x/icon_multi_line.png
+++ b/editor/icons/2x/icon_multi_line.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_multi_mesh.png b/editor/icons/2x/icon_multi_mesh.png
index 35b99d6698..35b99d6698 100644
--- a/tools/editor/icons/2x/icon_multi_mesh.png
+++ b/editor/icons/2x/icon_multi_mesh.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_multi_mesh_instance.png b/editor/icons/2x/icon_multi_mesh_instance.png
index f69768c6e3..f69768c6e3 100644
--- a/tools/editor/icons/2x/icon_multi_mesh_instance.png
+++ b/editor/icons/2x/icon_multi_mesh_instance.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_multi_node_edit.png b/editor/icons/2x/icon_multi_node_edit.png
index 93360b93f7..93360b93f7 100644
--- a/tools/editor/icons/2x/icon_multi_node_edit.png
+++ b/editor/icons/2x/icon_multi_node_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_navigation.png b/editor/icons/2x/icon_navigation.png
index 3cd838d2fc..3cd838d2fc 100644
--- a/tools/editor/icons/2x/icon_navigation.png
+++ b/editor/icons/2x/icon_navigation.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_navigation_2d.png b/editor/icons/2x/icon_navigation_2d.png
index 9efbeaaef0..9efbeaaef0 100644
--- a/tools/editor/icons/2x/icon_navigation_2d.png
+++ b/editor/icons/2x/icon_navigation_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_navigation_mesh.png b/editor/icons/2x/icon_navigation_mesh.png
index 35b893c3bb..35b893c3bb 100644
--- a/tools/editor/icons/2x/icon_navigation_mesh.png
+++ b/editor/icons/2x/icon_navigation_mesh.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_navigation_mesh_instance.png b/editor/icons/2x/icon_navigation_mesh_instance.png
index 404fad2d31..404fad2d31 100644
--- a/tools/editor/icons/2x/icon_navigation_mesh_instance.png
+++ b/editor/icons/2x/icon_navigation_mesh_instance.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_navigation_polygon.png b/editor/icons/2x/icon_navigation_polygon.png
index 3f4845e206..3f4845e206 100644
--- a/tools/editor/icons/2x/icon_navigation_polygon.png
+++ b/editor/icons/2x/icon_navigation_polygon.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_navigation_polygon_instance.png b/editor/icons/2x/icon_navigation_polygon_instance.png
index 5556835d76..5556835d76 100644
--- a/tools/editor/icons/2x/icon_navigation_polygon_instance.png
+++ b/editor/icons/2x/icon_navigation_polygon_instance.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_new.png b/editor/icons/2x/icon_new.png
index 683f1141fd..683f1141fd 100644
--- a/tools/editor/icons/2x/icon_new.png
+++ b/editor/icons/2x/icon_new.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_nine_patch_rect.png b/editor/icons/2x/icon_nine_patch_rect.png
index 5762a0392e..5762a0392e 100644
--- a/tools/editor/icons/2x/icon_nine_patch_rect.png
+++ b/editor/icons/2x/icon_nine_patch_rect.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_node.png b/editor/icons/2x/icon_node.png
index e487f988a2..e487f988a2 100644
--- a/tools/editor/icons/2x/icon_node.png
+++ b/editor/icons/2x/icon_node.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_node_2d.png b/editor/icons/2x/icon_node_2d.png
index 967d4b7da6..967d4b7da6 100644
--- a/tools/editor/icons/2x/icon_node_2d.png
+++ b/editor/icons/2x/icon_node_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_node_warning.png b/editor/icons/2x/icon_node_warning.png
index 397a57bf1f..397a57bf1f 100644
--- a/tools/editor/icons/2x/icon_node_warning.png
+++ b/editor/icons/2x/icon_node_warning.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_non_favorite.png b/editor/icons/2x/icon_non_favorite.png
index 18aa94e6b9..18aa94e6b9 100644
--- a/tools/editor/icons/2x/icon_non_favorite.png
+++ b/editor/icons/2x/icon_non_favorite.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_object.png b/editor/icons/2x/icon_object.png
index dc0a94aacd..dc0a94aacd 100644
--- a/tools/editor/icons/2x/icon_object.png
+++ b/editor/icons/2x/icon_object.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_occluder_polygon_2d.png b/editor/icons/2x/icon_occluder_polygon_2d.png
index e5e27dda32..e5e27dda32 100644
--- a/tools/editor/icons/2x/icon_occluder_polygon_2d.png
+++ b/editor/icons/2x/icon_occluder_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_omni_light.png b/editor/icons/2x/icon_omni_light.png
index 2c44252b9c..2c44252b9c 100644
--- a/tools/editor/icons/2x/icon_omni_light.png
+++ b/editor/icons/2x/icon_omni_light.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_open.png b/editor/icons/2x/icon_open.png
index 2e797c448b..2e797c448b 100644
--- a/tools/editor/icons/2x/icon_open.png
+++ b/editor/icons/2x/icon_open.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_option_button.png b/editor/icons/2x/icon_option_button.png
index f4438f9efd..f4438f9efd 100644
--- a/tools/editor/icons/2x/icon_option_button.png
+++ b/editor/icons/2x/icon_option_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_override.png b/editor/icons/2x/icon_override.png
index d735a1c734..d735a1c734 100644
--- a/tools/editor/icons/2x/icon_override.png
+++ b/editor/icons/2x/icon_override.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_p_hash_translation.png b/editor/icons/2x/icon_p_hash_translation.png
index 0ddc1da282..0ddc1da282 100644
--- a/tools/editor/icons/2x/icon_p_hash_translation.png
+++ b/editor/icons/2x/icon_p_hash_translation.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_packed_data_container.png b/editor/icons/2x/icon_packed_data_container.png
index 958e41ede2..958e41ede2 100644
--- a/tools/editor/icons/2x/icon_packed_data_container.png
+++ b/editor/icons/2x/icon_packed_data_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_packed_scene.png b/editor/icons/2x/icon_packed_scene.png
index 00778e8c0a..00778e8c0a 100644
--- a/tools/editor/icons/2x/icon_packed_scene.png
+++ b/editor/icons/2x/icon_packed_scene.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panel.png b/editor/icons/2x/icon_panel.png
index 23491a7358..23491a7358 100644
--- a/tools/editor/icons/2x/icon_panel.png
+++ b/editor/icons/2x/icon_panel.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panel_container.png b/editor/icons/2x/icon_panel_container.png
index fb2980ee8b..fb2980ee8b 100644
--- a/tools/editor/icons/2x/icon_panel_container.png
+++ b/editor/icons/2x/icon_panel_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panels_1.png b/editor/icons/2x/icon_panels_1.png
index b8386daa2e..b8386daa2e 100644
--- a/tools/editor/icons/2x/icon_panels_1.png
+++ b/editor/icons/2x/icon_panels_1.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panels_2.png b/editor/icons/2x/icon_panels_2.png
index 4d9f3ef724..4d9f3ef724 100644
--- a/tools/editor/icons/2x/icon_panels_2.png
+++ b/editor/icons/2x/icon_panels_2.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panels_2_alt.png b/editor/icons/2x/icon_panels_2_alt.png
index 69aeecce34..69aeecce34 100644
--- a/tools/editor/icons/2x/icon_panels_2_alt.png
+++ b/editor/icons/2x/icon_panels_2_alt.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panels_3.png b/editor/icons/2x/icon_panels_3.png
index e889504f15..e889504f15 100644
--- a/tools/editor/icons/2x/icon_panels_3.png
+++ b/editor/icons/2x/icon_panels_3.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panels_3_alt.png b/editor/icons/2x/icon_panels_3_alt.png
index 1e9a17ca75..1e9a17ca75 100644
--- a/tools/editor/icons/2x/icon_panels_3_alt.png
+++ b/editor/icons/2x/icon_panels_3_alt.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_panels_4.png b/editor/icons/2x/icon_panels_4.png
index 62e77e417a..62e77e417a 100644
--- a/tools/editor/icons/2x/icon_panels_4.png
+++ b/editor/icons/2x/icon_panels_4.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_parallax_background.png b/editor/icons/2x/icon_parallax_background.png
index a81046e805..a81046e805 100644
--- a/tools/editor/icons/2x/icon_parallax_background.png
+++ b/editor/icons/2x/icon_parallax_background.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_parallax_layer.png b/editor/icons/2x/icon_parallax_layer.png
index 285999df61..285999df61 100644
--- a/tools/editor/icons/2x/icon_parallax_layer.png
+++ b/editor/icons/2x/icon_parallax_layer.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_particle_attractor_2d.png b/editor/icons/2x/icon_particle_attractor_2d.png
index b985a0ba57..b985a0ba57 100644
--- a/tools/editor/icons/2x/icon_particle_attractor_2d.png
+++ b/editor/icons/2x/icon_particle_attractor_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_particles.png b/editor/icons/2x/icon_particles.png
index 68f30b4213..68f30b4213 100644
--- a/tools/editor/icons/2x/icon_particles.png
+++ b/editor/icons/2x/icon_particles.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_particles_2d.png b/editor/icons/2x/icon_particles_2d.png
index 13fc8a35e6..13fc8a35e6 100644
--- a/tools/editor/icons/2x/icon_particles_2d.png
+++ b/editor/icons/2x/icon_particles_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_particles_shader.png b/editor/icons/2x/icon_particles_shader.png
index 26ce8f6809..26ce8f6809 100644
--- a/tools/editor/icons/2x/icon_particles_shader.png
+++ b/editor/icons/2x/icon_particles_shader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_patch_9_rect.png b/editor/icons/2x/icon_patch_9_rect.png
index 5762a0392e..5762a0392e 100644
--- a/tools/editor/icons/2x/icon_patch_9_rect.png
+++ b/editor/icons/2x/icon_patch_9_rect.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_path.png b/editor/icons/2x/icon_path.png
index d10cb37bcd..d10cb37bcd 100644
--- a/tools/editor/icons/2x/icon_path.png
+++ b/editor/icons/2x/icon_path.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_path_2d.png b/editor/icons/2x/icon_path_2d.png
index dabf5ccc49..dabf5ccc49 100644
--- a/tools/editor/icons/2x/icon_path_2d.png
+++ b/editor/icons/2x/icon_path_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_path_follow.png b/editor/icons/2x/icon_path_follow.png
index 8538b1f3b9..8538b1f3b9 100644
--- a/tools/editor/icons/2x/icon_path_follow.png
+++ b/editor/icons/2x/icon_path_follow.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_path_follow_2d.png b/editor/icons/2x/icon_path_follow_2d.png
index a83ed837ba..a83ed837ba 100644
--- a/tools/editor/icons/2x/icon_path_follow_2d.png
+++ b/editor/icons/2x/icon_path_follow_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_pause.png b/editor/icons/2x/icon_pause.png
index 35e6b25294..35e6b25294 100644
--- a/tools/editor/icons/2x/icon_pause.png
+++ b/editor/icons/2x/icon_pause.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_pin.png b/editor/icons/2x/icon_pin.png
index d19fe7afef..d19fe7afef 100644
--- a/tools/editor/icons/2x/icon_pin.png
+++ b/editor/icons/2x/icon_pin.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_pin_joint.png b/editor/icons/2x/icon_pin_joint.png
index 304cb39724..304cb39724 100644
--- a/tools/editor/icons/2x/icon_pin_joint.png
+++ b/editor/icons/2x/icon_pin_joint.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_pin_joint_2d.png b/editor/icons/2x/icon_pin_joint_2d.png
index a2302c4756..a2302c4756 100644
--- a/tools/editor/icons/2x/icon_pin_joint_2d.png
+++ b/editor/icons/2x/icon_pin_joint_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_pin_pressed.png b/editor/icons/2x/icon_pin_pressed.png
index d19fe7afef..d19fe7afef 100644
--- a/tools/editor/icons/2x/icon_pin_pressed.png
+++ b/editor/icons/2x/icon_pin_pressed.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_plane.png b/editor/icons/2x/icon_plane.png
index a096e30065..a096e30065 100644
--- a/tools/editor/icons/2x/icon_plane.png
+++ b/editor/icons/2x/icon_plane.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_plane_shape.png b/editor/icons/2x/icon_plane_shape.png
index 8ebd38fe83..8ebd38fe83 100644
--- a/tools/editor/icons/2x/icon_plane_shape.png
+++ b/editor/icons/2x/icon_plane_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_play.png b/editor/icons/2x/icon_play.png
index b84ed23091..b84ed23091 100644
--- a/tools/editor/icons/2x/icon_play.png
+++ b/editor/icons/2x/icon_play.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_play_backwards.png b/editor/icons/2x/icon_play_backwards.png
index 42aeca74e5..42aeca74e5 100644
--- a/tools/editor/icons/2x/icon_play_backwards.png
+++ b/editor/icons/2x/icon_play_backwards.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_play_custom.png b/editor/icons/2x/icon_play_custom.png
index 299ac3ffbc..299ac3ffbc 100644
--- a/tools/editor/icons/2x/icon_play_custom.png
+++ b/editor/icons/2x/icon_play_custom.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_play_scene.png b/editor/icons/2x/icon_play_scene.png
index 948a2e9ba5..948a2e9ba5 100644
--- a/tools/editor/icons/2x/icon_play_scene.png
+++ b/editor/icons/2x/icon_play_scene.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_play_start.png b/editor/icons/2x/icon_play_start.png
index 227e1b6f19..227e1b6f19 100644
--- a/tools/editor/icons/2x/icon_play_start.png
+++ b/editor/icons/2x/icon_play_start.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_play_start_backwards.png b/editor/icons/2x/icon_play_start_backwards.png
index e9a46325f6..e9a46325f6 100644
--- a/tools/editor/icons/2x/icon_play_start_backwards.png
+++ b/editor/icons/2x/icon_play_start_backwards.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_polygon_2d.png b/editor/icons/2x/icon_polygon_2d.png
index 491ebfaa78..491ebfaa78 100644
--- a/tools/editor/icons/2x/icon_polygon_2d.png
+++ b/editor/icons/2x/icon_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_polygon_path_finder.png b/editor/icons/2x/icon_polygon_path_finder.png
index ee6423c265..ee6423c265 100644
--- a/tools/editor/icons/2x/icon_polygon_path_finder.png
+++ b/editor/icons/2x/icon_polygon_path_finder.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_popup.png b/editor/icons/2x/icon_popup.png
index 7bcfb114da..7bcfb114da 100644
--- a/tools/editor/icons/2x/icon_popup.png
+++ b/editor/icons/2x/icon_popup.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_popup_dialog.png b/editor/icons/2x/icon_popup_dialog.png
index 6920fa27bf..6920fa27bf 100644
--- a/tools/editor/icons/2x/icon_popup_dialog.png
+++ b/editor/icons/2x/icon_popup_dialog.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_popup_menu.png b/editor/icons/2x/icon_popup_menu.png
index 4e0246879b..4e0246879b 100644
--- a/tools/editor/icons/2x/icon_popup_menu.png
+++ b/editor/icons/2x/icon_popup_menu.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_popup_panel.png b/editor/icons/2x/icon_popup_panel.png
index 15d977cc81..15d977cc81 100644
--- a/tools/editor/icons/2x/icon_popup_panel.png
+++ b/editor/icons/2x/icon_popup_panel.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_portal.png b/editor/icons/2x/icon_portal.png
index c934e65fc4..c934e65fc4 100644
--- a/tools/editor/icons/2x/icon_portal.png
+++ b/editor/icons/2x/icon_portal.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_position_2d.png b/editor/icons/2x/icon_position_2d.png
index 176a2300ef..176a2300ef 100644
--- a/tools/editor/icons/2x/icon_position_2d.png
+++ b/editor/icons/2x/icon_position_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_position_3d.png b/editor/icons/2x/icon_position_3d.png
index ed19f011b0..ed19f011b0 100644
--- a/tools/editor/icons/2x/icon_position_3d.png
+++ b/editor/icons/2x/icon_position_3d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_1.png b/editor/icons/2x/icon_progress_1.png
index b73dded521..b73dded521 100644
--- a/tools/editor/icons/2x/icon_progress_1.png
+++ b/editor/icons/2x/icon_progress_1.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_2.png b/editor/icons/2x/icon_progress_2.png
index 19d89bd369..19d89bd369 100644
--- a/tools/editor/icons/2x/icon_progress_2.png
+++ b/editor/icons/2x/icon_progress_2.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_3.png b/editor/icons/2x/icon_progress_3.png
index ca6b270ef7..ca6b270ef7 100644
--- a/tools/editor/icons/2x/icon_progress_3.png
+++ b/editor/icons/2x/icon_progress_3.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_4.png b/editor/icons/2x/icon_progress_4.png
index 3afa1f845e..3afa1f845e 100644
--- a/tools/editor/icons/2x/icon_progress_4.png
+++ b/editor/icons/2x/icon_progress_4.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_5.png b/editor/icons/2x/icon_progress_5.png
index 8230048771..8230048771 100644
--- a/tools/editor/icons/2x/icon_progress_5.png
+++ b/editor/icons/2x/icon_progress_5.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_6.png b/editor/icons/2x/icon_progress_6.png
index 6c21a5d053..6c21a5d053 100644
--- a/tools/editor/icons/2x/icon_progress_6.png
+++ b/editor/icons/2x/icon_progress_6.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_7.png b/editor/icons/2x/icon_progress_7.png
index 96316b54ca..96316b54ca 100644
--- a/tools/editor/icons/2x/icon_progress_7.png
+++ b/editor/icons/2x/icon_progress_7.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_8.png b/editor/icons/2x/icon_progress_8.png
index 95133b380d..95133b380d 100644
--- a/tools/editor/icons/2x/icon_progress_8.png
+++ b/editor/icons/2x/icon_progress_8.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_progress_bar.png b/editor/icons/2x/icon_progress_bar.png
index f9a243032e..f9a243032e 100644
--- a/tools/editor/icons/2x/icon_progress_bar.png
+++ b/editor/icons/2x/icon_progress_bar.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_proximity_group.png b/editor/icons/2x/icon_proximity_group.png
index 6602afa7ce..6602afa7ce 100644
--- a/tools/editor/icons/2x/icon_proximity_group.png
+++ b/editor/icons/2x/icon_proximity_group.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_quad.png b/editor/icons/2x/icon_quad.png
index a4074cd5b6..a4074cd5b6 100644
--- a/tools/editor/icons/2x/icon_quad.png
+++ b/editor/icons/2x/icon_quad.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_quat.png b/editor/icons/2x/icon_quat.png
index f909e134f4..f909e134f4 100644
--- a/tools/editor/icons/2x/icon_quat.png
+++ b/editor/icons/2x/icon_quat.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_range.png b/editor/icons/2x/icon_range.png
index 92c0934df6..92c0934df6 100644
--- a/tools/editor/icons/2x/icon_range.png
+++ b/editor/icons/2x/icon_range.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rating_no_star.png b/editor/icons/2x/icon_rating_no_star.png
index f855fd8b56..f855fd8b56 100644
--- a/tools/editor/icons/2x/icon_rating_no_star.png
+++ b/editor/icons/2x/icon_rating_no_star.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rating_star.png b/editor/icons/2x/icon_rating_star.png
index bfe082d330..bfe082d330 100644
--- a/tools/editor/icons/2x/icon_rating_star.png
+++ b/editor/icons/2x/icon_rating_star.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_ray_cast.png b/editor/icons/2x/icon_ray_cast.png
index 26d958ac2b..26d958ac2b 100644
--- a/tools/editor/icons/2x/icon_ray_cast.png
+++ b/editor/icons/2x/icon_ray_cast.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_ray_cast_2d.png b/editor/icons/2x/icon_ray_cast_2d.png
index e496cdcc2b..e496cdcc2b 100644
--- a/tools/editor/icons/2x/icon_ray_cast_2d.png
+++ b/editor/icons/2x/icon_ray_cast_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_ray_shape.png b/editor/icons/2x/icon_ray_shape.png
index 54a1cf8fe9..54a1cf8fe9 100644
--- a/tools/editor/icons/2x/icon_ray_shape.png
+++ b/editor/icons/2x/icon_ray_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_ray_shape_2d.png b/editor/icons/2x/icon_ray_shape_2d.png
index 2dc7041a93..2dc7041a93 100644
--- a/tools/editor/icons/2x/icon_ray_shape_2d.png
+++ b/editor/icons/2x/icon_ray_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rayito.png b/editor/icons/2x/icon_rayito.png
index 1959b8bf00..1959b8bf00 100644
--- a/tools/editor/icons/2x/icon_rayito.png
+++ b/editor/icons/2x/icon_rayito.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_real.png b/editor/icons/2x/icon_real.png
index 5ec56ebcac..5ec56ebcac 100644
--- a/tools/editor/icons/2x/icon_real.png
+++ b/editor/icons/2x/icon_real.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rectangle_shape_2d.png b/editor/icons/2x/icon_rectangle_shape_2d.png
index 51a93cdb1d..51a93cdb1d 100644
--- a/tools/editor/icons/2x/icon_rectangle_shape_2d.png
+++ b/editor/icons/2x/icon_rectangle_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_reference_rect.png b/editor/icons/2x/icon_reference_rect.png
index 63fe559fa7..63fe559fa7 100644
--- a/tools/editor/icons/2x/icon_reference_rect.png
+++ b/editor/icons/2x/icon_reference_rect.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_reflection_probe.png b/editor/icons/2x/icon_reflection_probe.png
index 5604b403df..5604b403df 100644
--- a/tools/editor/icons/2x/icon_reflection_probe.png
+++ b/editor/icons/2x/icon_reflection_probe.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_region_edit.png b/editor/icons/2x/icon_region_edit.png
index bcaba769d4..bcaba769d4 100644
--- a/tools/editor/icons/2x/icon_region_edit.png
+++ b/editor/icons/2x/icon_region_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_reload.png b/editor/icons/2x/icon_reload.png
index b13c858124..b13c858124 100644
--- a/tools/editor/icons/2x/icon_reload.png
+++ b/editor/icons/2x/icon_reload.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_reload_small.png b/editor/icons/2x/icon_reload_small.png
index a278c34e4c..a278c34e4c 100644
--- a/tools/editor/icons/2x/icon_reload_small.png
+++ b/editor/icons/2x/icon_reload_small.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_remote.png b/editor/icons/2x/icon_remote.png
index 87883ed7e1..87883ed7e1 100644
--- a/tools/editor/icons/2x/icon_remote.png
+++ b/editor/icons/2x/icon_remote.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_remote_transform.png b/editor/icons/2x/icon_remote_transform.png
index dad528615a..dad528615a 100644
--- a/tools/editor/icons/2x/icon_remote_transform.png
+++ b/editor/icons/2x/icon_remote_transform.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_remote_transform_2d.png b/editor/icons/2x/icon_remote_transform_2d.png
index 7ef3e06f81..7ef3e06f81 100644
--- a/tools/editor/icons/2x/icon_remote_transform_2d.png
+++ b/editor/icons/2x/icon_remote_transform_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_remove.png b/editor/icons/2x/icon_remove.png
index dbed177745..dbed177745 100644
--- a/tools/editor/icons/2x/icon_remove.png
+++ b/editor/icons/2x/icon_remove.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rename.png b/editor/icons/2x/icon_rename.png
index a306a7b8c8..a306a7b8c8 100644
--- a/tools/editor/icons/2x/icon_rename.png
+++ b/editor/icons/2x/icon_rename.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_reparent.png b/editor/icons/2x/icon_reparent.png
index 3063da4b43..3063da4b43 100644
--- a/tools/editor/icons/2x/icon_reparent.png
+++ b/editor/icons/2x/icon_reparent.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_resource_preloader.png b/editor/icons/2x/icon_resource_preloader.png
index d48f37d21f..d48f37d21f 100644
--- a/tools/editor/icons/2x/icon_resource_preloader.png
+++ b/editor/icons/2x/icon_resource_preloader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rich_text_label.png b/editor/icons/2x/icon_rich_text_label.png
index 598913d896..598913d896 100644
--- a/tools/editor/icons/2x/icon_rich_text_label.png
+++ b/editor/icons/2x/icon_rich_text_label.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rigid_body.png b/editor/icons/2x/icon_rigid_body.png
index 3b682f0033..3b682f0033 100644
--- a/tools/editor/icons/2x/icon_rigid_body.png
+++ b/editor/icons/2x/icon_rigid_body.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rigid_body_2d.png b/editor/icons/2x/icon_rigid_body_2d.png
index bd45d2f01a..bd45d2f01a 100644
--- a/tools/editor/icons/2x/icon_rigid_body_2d.png
+++ b/editor/icons/2x/icon_rigid_body_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_room.png b/editor/icons/2x/icon_room.png
index 946f95e955..946f95e955 100644
--- a/tools/editor/icons/2x/icon_room.png
+++ b/editor/icons/2x/icon_room.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_room_bounds.png b/editor/icons/2x/icon_room_bounds.png
index 94da9c437d..94da9c437d 100644
--- a/tools/editor/icons/2x/icon_room_bounds.png
+++ b/editor/icons/2x/icon_room_bounds.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rotate_0.png b/editor/icons/2x/icon_rotate_0.png
index a4524b7856..a4524b7856 100644
--- a/tools/editor/icons/2x/icon_rotate_0.png
+++ b/editor/icons/2x/icon_rotate_0.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rotate_180.png b/editor/icons/2x/icon_rotate_180.png
index a00e1b727c..a00e1b727c 100644
--- a/tools/editor/icons/2x/icon_rotate_180.png
+++ b/editor/icons/2x/icon_rotate_180.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rotate_270.png b/editor/icons/2x/icon_rotate_270.png
index be56f080a9..be56f080a9 100644
--- a/tools/editor/icons/2x/icon_rotate_270.png
+++ b/editor/icons/2x/icon_rotate_270.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_rotate_90.png b/editor/icons/2x/icon_rotate_90.png
index a3a937892d..a3a937892d 100644
--- a/tools/editor/icons/2x/icon_rotate_90.png
+++ b/editor/icons/2x/icon_rotate_90.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sample.png b/editor/icons/2x/icon_sample.png
index b01674f923..b01674f923 100644
--- a/tools/editor/icons/2x/icon_sample.png
+++ b/editor/icons/2x/icon_sample.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sample_library.png b/editor/icons/2x/icon_sample_library.png
index 3f76a78aca..3f76a78aca 100644
--- a/tools/editor/icons/2x/icon_sample_library.png
+++ b/editor/icons/2x/icon_sample_library.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sample_player.png b/editor/icons/2x/icon_sample_player.png
index aac4c1bbed..aac4c1bbed 100644
--- a/tools/editor/icons/2x/icon_sample_player.png
+++ b/editor/icons/2x/icon_sample_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sample_player_2d.png b/editor/icons/2x/icon_sample_player_2d.png
index 9308d43128..9308d43128 100644
--- a/tools/editor/icons/2x/icon_sample_player_2d.png
+++ b/editor/icons/2x/icon_sample_player_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_save.png b/editor/icons/2x/icon_save.png
index 0a643f2c88..0a643f2c88 100644
--- a/tools/editor/icons/2x/icon_save.png
+++ b/editor/icons/2x/icon_save.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_script.png b/editor/icons/2x/icon_script.png
index 6f54c20442..6f54c20442 100644
--- a/tools/editor/icons/2x/icon_script.png
+++ b/editor/icons/2x/icon_script.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_script_create.png b/editor/icons/2x/icon_script_create.png
index f1e25efe1c..f1e25efe1c 100644
--- a/tools/editor/icons/2x/icon_script_create.png
+++ b/editor/icons/2x/icon_script_create.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_script_remove.png b/editor/icons/2x/icon_script_remove.png
index f9a1bb19a4..f9a1bb19a4 100644
--- a/tools/editor/icons/2x/icon_script_remove.png
+++ b/editor/icons/2x/icon_script_remove.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_scroll_bar.png b/editor/icons/2x/icon_scroll_bar.png
index d15a36bb16..d15a36bb16 100644
--- a/tools/editor/icons/2x/icon_scroll_bar.png
+++ b/editor/icons/2x/icon_scroll_bar.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_scroll_container.png b/editor/icons/2x/icon_scroll_container.png
index 4ffe2f78f5..4ffe2f78f5 100644
--- a/tools/editor/icons/2x/icon_scroll_container.png
+++ b/editor/icons/2x/icon_scroll_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_segment_shape_2d.png b/editor/icons/2x/icon_segment_shape_2d.png
index 43d5d837cc..43d5d837cc 100644
--- a/tools/editor/icons/2x/icon_segment_shape_2d.png
+++ b/editor/icons/2x/icon_segment_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_shader.png b/editor/icons/2x/icon_shader.png
index f8c2e15fcb..f8c2e15fcb 100644
--- a/tools/editor/icons/2x/icon_shader.png
+++ b/editor/icons/2x/icon_shader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_shader_material.png b/editor/icons/2x/icon_shader_material.png
index f8c2e15fcb..f8c2e15fcb 100644
--- a/tools/editor/icons/2x/icon_shader_material.png
+++ b/editor/icons/2x/icon_shader_material.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_short_cut.png b/editor/icons/2x/icon_short_cut.png
index 58c3e08ca4..58c3e08ca4 100644
--- a/tools/editor/icons/2x/icon_short_cut.png
+++ b/editor/icons/2x/icon_short_cut.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_signal.png b/editor/icons/2x/icon_signal.png
index 22b6da361e..22b6da361e 100644
--- a/tools/editor/icons/2x/icon_signal.png
+++ b/editor/icons/2x/icon_signal.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_skeleton.png b/editor/icons/2x/icon_skeleton.png
index 5345dfbd5c..5345dfbd5c 100644
--- a/tools/editor/icons/2x/icon_skeleton.png
+++ b/editor/icons/2x/icon_skeleton.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_slider_joint.png b/editor/icons/2x/icon_slider_joint.png
index 626479152f..626479152f 100644
--- a/tools/editor/icons/2x/icon_slider_joint.png
+++ b/editor/icons/2x/icon_slider_joint.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_slot.png b/editor/icons/2x/icon_slot.png
index 2176544c79..2176544c79 100644
--- a/tools/editor/icons/2x/icon_slot.png
+++ b/editor/icons/2x/icon_slot.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_snap.png b/editor/icons/2x/icon_snap.png
index 509b1c73f3..509b1c73f3 100644
--- a/tools/editor/icons/2x/icon_snap.png
+++ b/editor/icons/2x/icon_snap.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sound_room_params.png b/editor/icons/2x/icon_sound_room_params.png
index 32927eaabc..32927eaabc 100644
--- a/tools/editor/icons/2x/icon_sound_room_params.png
+++ b/editor/icons/2x/icon_sound_room_params.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_spatial.png b/editor/icons/2x/icon_spatial.png
index 999771a7fe..999771a7fe 100644
--- a/tools/editor/icons/2x/icon_spatial.png
+++ b/editor/icons/2x/icon_spatial.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_spatial_sample_player.png b/editor/icons/2x/icon_spatial_sample_player.png
index f1926c446e..f1926c446e 100644
--- a/tools/editor/icons/2x/icon_spatial_sample_player.png
+++ b/editor/icons/2x/icon_spatial_sample_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_spatial_shader.png b/editor/icons/2x/icon_spatial_shader.png
index 68f6cf8dac..68f6cf8dac 100644
--- a/tools/editor/icons/2x/icon_spatial_shader.png
+++ b/editor/icons/2x/icon_spatial_shader.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_spatial_stream_player.png b/editor/icons/2x/icon_spatial_stream_player.png
index 835c5c0bbc..835c5c0bbc 100644
--- a/tools/editor/icons/2x/icon_spatial_stream_player.png
+++ b/editor/icons/2x/icon_spatial_stream_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sphere_shape.png b/editor/icons/2x/icon_sphere_shape.png
index bdb7881e70..bdb7881e70 100644
--- a/tools/editor/icons/2x/icon_sphere_shape.png
+++ b/editor/icons/2x/icon_sphere_shape.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_spin_box.png b/editor/icons/2x/icon_spin_box.png
index 3d12664b86..3d12664b86 100644
--- a/tools/editor/icons/2x/icon_spin_box.png
+++ b/editor/icons/2x/icon_spin_box.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_spot_light.png b/editor/icons/2x/icon_spot_light.png
index e7aa35cbbf..e7aa35cbbf 100644
--- a/tools/editor/icons/2x/icon_spot_light.png
+++ b/editor/icons/2x/icon_spot_light.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sprite.png b/editor/icons/2x/icon_sprite.png
index 3f18d313e7..3f18d313e7 100644
--- a/tools/editor/icons/2x/icon_sprite.png
+++ b/editor/icons/2x/icon_sprite.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sprite_3d.png b/editor/icons/2x/icon_sprite_3d.png
index d3a491b9ee..d3a491b9ee 100644
--- a/tools/editor/icons/2x/icon_sprite_3d.png
+++ b/editor/icons/2x/icon_sprite_3d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_sprite_frames.png b/editor/icons/2x/icon_sprite_frames.png
index 263f5c4aad..263f5c4aad 100644
--- a/tools/editor/icons/2x/icon_sprite_frames.png
+++ b/editor/icons/2x/icon_sprite_frames.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_static_body.png b/editor/icons/2x/icon_static_body.png
index 74f65ef490..74f65ef490 100644
--- a/tools/editor/icons/2x/icon_static_body.png
+++ b/editor/icons/2x/icon_static_body.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_static_body_2d.png b/editor/icons/2x/icon_static_body_2d.png
index 220c829edd..220c829edd 100644
--- a/tools/editor/icons/2x/icon_static_body_2d.png
+++ b/editor/icons/2x/icon_static_body_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_stream_player.png b/editor/icons/2x/icon_stream_player.png
index 8ff471cb8a..8ff471cb8a 100644
--- a/tools/editor/icons/2x/icon_stream_player.png
+++ b/editor/icons/2x/icon_stream_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_string.png b/editor/icons/2x/icon_string.png
index e25a81f24e..e25a81f24e 100644
--- a/tools/editor/icons/2x/icon_string.png
+++ b/editor/icons/2x/icon_string.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_style_box_empty.png b/editor/icons/2x/icon_style_box_empty.png
index e790af4de4..e790af4de4 100644
--- a/tools/editor/icons/2x/icon_style_box_empty.png
+++ b/editor/icons/2x/icon_style_box_empty.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_style_box_flat.png b/editor/icons/2x/icon_style_box_flat.png
index 1cd5c7f69a..1cd5c7f69a 100644
--- a/tools/editor/icons/2x/icon_style_box_flat.png
+++ b/editor/icons/2x/icon_style_box_flat.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_style_box_texture.png b/editor/icons/2x/icon_style_box_texture.png
index a93e0228bd..a93e0228bd 100644
--- a/tools/editor/icons/2x/icon_style_box_texture.png
+++ b/editor/icons/2x/icon_style_box_texture.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tab_container.png b/editor/icons/2x/icon_tab_container.png
index 93b7161a69..93b7161a69 100644
--- a/tools/editor/icons/2x/icon_tab_container.png
+++ b/editor/icons/2x/icon_tab_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tabs.png b/editor/icons/2x/icon_tabs.png
index 6c317010c8..6c317010c8 100644
--- a/tools/editor/icons/2x/icon_tabs.png
+++ b/editor/icons/2x/icon_tabs.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_test_cube.png b/editor/icons/2x/icon_test_cube.png
index f2e523be3f..f2e523be3f 100644
--- a/tools/editor/icons/2x/icon_test_cube.png
+++ b/editor/icons/2x/icon_test_cube.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_text_edit.png b/editor/icons/2x/icon_text_edit.png
index 4fd92e518e..4fd92e518e 100644
--- a/tools/editor/icons/2x/icon_text_edit.png
+++ b/editor/icons/2x/icon_text_edit.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_texture.png b/editor/icons/2x/icon_texture.png
index ad5d04dfee..ad5d04dfee 100644
--- a/tools/editor/icons/2x/icon_texture.png
+++ b/editor/icons/2x/icon_texture.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_texture_button.png b/editor/icons/2x/icon_texture_button.png
index 84494209d7..84494209d7 100644
--- a/tools/editor/icons/2x/icon_texture_button.png
+++ b/editor/icons/2x/icon_texture_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_texture_progress.png b/editor/icons/2x/icon_texture_progress.png
index c11c1bbe4b..c11c1bbe4b 100644
--- a/tools/editor/icons/2x/icon_texture_progress.png
+++ b/editor/icons/2x/icon_texture_progress.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_texture_rect.png b/editor/icons/2x/icon_texture_rect.png
index 50d715dd09..50d715dd09 100644
--- a/tools/editor/icons/2x/icon_texture_rect.png
+++ b/editor/icons/2x/icon_texture_rect.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_theme.png b/editor/icons/2x/icon_theme.png
index 55b51428dd..55b51428dd 100644
--- a/tools/editor/icons/2x/icon_theme.png
+++ b/editor/icons/2x/icon_theme.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tile_map.png b/editor/icons/2x/icon_tile_map.png
index fd98fb6a39..fd98fb6a39 100644
--- a/tools/editor/icons/2x/icon_tile_map.png
+++ b/editor/icons/2x/icon_tile_map.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tile_set.png b/editor/icons/2x/icon_tile_set.png
index 9fbd0b4719..9fbd0b4719 100644
--- a/tools/editor/icons/2x/icon_tile_set.png
+++ b/editor/icons/2x/icon_tile_set.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_timer.png b/editor/icons/2x/icon_timer.png
index b0df31d803..b0df31d803 100644
--- a/tools/editor/icons/2x/icon_timer.png
+++ b/editor/icons/2x/icon_timer.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tool_button.png b/editor/icons/2x/icon_tool_button.png
index 091fa8334f..091fa8334f 100644
--- a/tools/editor/icons/2x/icon_tool_button.png
+++ b/editor/icons/2x/icon_tool_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tool_move.png b/editor/icons/2x/icon_tool_move.png
index 86419cb6a9..86419cb6a9 100644
--- a/tools/editor/icons/2x/icon_tool_move.png
+++ b/editor/icons/2x/icon_tool_move.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tool_pan.png b/editor/icons/2x/icon_tool_pan.png
index b7a6c3566f..b7a6c3566f 100644
--- a/tools/editor/icons/2x/icon_tool_pan.png
+++ b/editor/icons/2x/icon_tool_pan.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tool_rotate.png b/editor/icons/2x/icon_tool_rotate.png
index b13c858124..b13c858124 100644
--- a/tools/editor/icons/2x/icon_tool_rotate.png
+++ b/editor/icons/2x/icon_tool_rotate.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tool_scale.png b/editor/icons/2x/icon_tool_scale.png
index 1bc29f4acc..1bc29f4acc 100644
--- a/tools/editor/icons/2x/icon_tool_scale.png
+++ b/editor/icons/2x/icon_tool_scale.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tool_select.png b/editor/icons/2x/icon_tool_select.png
index 7421b98ef6..7421b98ef6 100644
--- a/tools/editor/icons/2x/icon_tool_select.png
+++ b/editor/icons/2x/icon_tool_select.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tools.png b/editor/icons/2x/icon_tools.png
index 6143191fc7..6143191fc7 100644
--- a/tools/editor/icons/2x/icon_tools.png
+++ b/editor/icons/2x/icon_tools.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_touch_screen_button.png b/editor/icons/2x/icon_touch_screen_button.png
index b1af644e42..b1af644e42 100644
--- a/tools/editor/icons/2x/icon_touch_screen_button.png
+++ b/editor/icons/2x/icon_touch_screen_button.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_track_add_key.png b/editor/icons/2x/icon_track_add_key.png
index 9b7bd14fb4..9b7bd14fb4 100644
--- a/tools/editor/icons/2x/icon_track_add_key.png
+++ b/editor/icons/2x/icon_track_add_key.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_track_add_key_hl.png b/editor/icons/2x/icon_track_add_key_hl.png
index 0763836c3a..0763836c3a 100644
--- a/tools/editor/icons/2x/icon_track_add_key_hl.png
+++ b/editor/icons/2x/icon_track_add_key_hl.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_track_continuous.png b/editor/icons/2x/icon_track_continuous.png
index 5b4515f642..5b4515f642 100644
--- a/tools/editor/icons/2x/icon_track_continuous.png
+++ b/editor/icons/2x/icon_track_continuous.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_track_discrete.png b/editor/icons/2x/icon_track_discrete.png
index 19f479657b..19f479657b 100644
--- a/tools/editor/icons/2x/icon_track_discrete.png
+++ b/editor/icons/2x/icon_track_discrete.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_track_trigger.png b/editor/icons/2x/icon_track_trigger.png
index c04d47f9a4..c04d47f9a4 100644
--- a/tools/editor/icons/2x/icon_track_trigger.png
+++ b/editor/icons/2x/icon_track_trigger.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_translation.png b/editor/icons/2x/icon_translation.png
index 0ddc1da282..0ddc1da282 100644
--- a/tools/editor/icons/2x/icon_translation.png
+++ b/editor/icons/2x/icon_translation.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_transparent.png b/editor/icons/2x/icon_transparent.png
index 627607039b..627607039b 100644
--- a/tools/editor/icons/2x/icon_transparent.png
+++ b/editor/icons/2x/icon_transparent.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_transpose.png b/editor/icons/2x/icon_transpose.png
index 589dc54919..589dc54919 100644
--- a/tools/editor/icons/2x/icon_transpose.png
+++ b/editor/icons/2x/icon_transpose.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tree.png b/editor/icons/2x/icon_tree.png
index 3f470cc0f3..3f470cc0f3 100644
--- a/tools/editor/icons/2x/icon_tree.png
+++ b/editor/icons/2x/icon_tree.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_tween.png b/editor/icons/2x/icon_tween.png
index a13d955eb0..a13d955eb0 100644
--- a/tools/editor/icons/2x/icon_tween.png
+++ b/editor/icons/2x/icon_tween.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_unbone.png b/editor/icons/2x/icon_unbone.png
index c20d6d9b2c..c20d6d9b2c 100644
--- a/tools/editor/icons/2x/icon_unbone.png
+++ b/editor/icons/2x/icon_unbone.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_ungroup.png b/editor/icons/2x/icon_ungroup.png
index bb46185370..bb46185370 100644
--- a/tools/editor/icons/2x/icon_ungroup.png
+++ b/editor/icons/2x/icon_ungroup.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_uninstance.png b/editor/icons/2x/icon_uninstance.png
index bf3dc00368..bf3dc00368 100644
--- a/tools/editor/icons/2x/icon_uninstance.png
+++ b/editor/icons/2x/icon_uninstance.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_unlock.png b/editor/icons/2x/icon_unlock.png
index 40ff3f25a0..40ff3f25a0 100644
--- a/tools/editor/icons/2x/icon_unlock.png
+++ b/editor/icons/2x/icon_unlock.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_uv.png b/editor/icons/2x/icon_uv.png
index e06be54edd..e06be54edd 100644
--- a/tools/editor/icons/2x/icon_uv.png
+++ b/editor/icons/2x/icon_uv.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_v_box_container.png b/editor/icons/2x/icon_v_box_container.png
index 97eb18c528..97eb18c528 100644
--- a/tools/editor/icons/2x/icon_v_box_container.png
+++ b/editor/icons/2x/icon_v_box_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_v_button_array.png b/editor/icons/2x/icon_v_button_array.png
index 93fd1fed04..93fd1fed04 100644
--- a/tools/editor/icons/2x/icon_v_button_array.png
+++ b/editor/icons/2x/icon_v_button_array.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_v_scroll_bar.png b/editor/icons/2x/icon_v_scroll_bar.png
index 5e4f83197f..5e4f83197f 100644
--- a/tools/editor/icons/2x/icon_v_scroll_bar.png
+++ b/editor/icons/2x/icon_v_scroll_bar.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_v_separator.png b/editor/icons/2x/icon_v_separator.png
index 58cdc3e8de..58cdc3e8de 100644
--- a/tools/editor/icons/2x/icon_v_separator.png
+++ b/editor/icons/2x/icon_v_separator.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_v_slider.png b/editor/icons/2x/icon_v_slider.png
index afc88cf510..afc88cf510 100644
--- a/tools/editor/icons/2x/icon_v_slider.png
+++ b/editor/icons/2x/icon_v_slider.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_v_split_container.png b/editor/icons/2x/icon_v_split_container.png
index b0f68381fc..b0f68381fc 100644
--- a/tools/editor/icons/2x/icon_v_split_container.png
+++ b/editor/icons/2x/icon_v_split_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_vector.png b/editor/icons/2x/icon_vector.png
index 9950d950ac..9950d950ac 100644
--- a/tools/editor/icons/2x/icon_vector.png
+++ b/editor/icons/2x/icon_vector.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_vector2.png b/editor/icons/2x/icon_vector2.png
index 73c1ca007f..73c1ca007f 100644
--- a/tools/editor/icons/2x/icon_vector2.png
+++ b/editor/icons/2x/icon_vector2.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_vehicle_body.png b/editor/icons/2x/icon_vehicle_body.png
index 215f7ac021..215f7ac021 100644
--- a/tools/editor/icons/2x/icon_vehicle_body.png
+++ b/editor/icons/2x/icon_vehicle_body.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_vehicle_wheel.png b/editor/icons/2x/icon_vehicle_wheel.png
index 6f7fecac4a..6f7fecac4a 100644
--- a/tools/editor/icons/2x/icon_vehicle_wheel.png
+++ b/editor/icons/2x/icon_vehicle_wheel.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_video_player.png b/editor/icons/2x/icon_video_player.png
index 588e17aa4e..588e17aa4e 100644
--- a/tools/editor/icons/2x/icon_video_player.png
+++ b/editor/icons/2x/icon_video_player.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_viewport.png b/editor/icons/2x/icon_viewport.png
index 7e588333fb..7e588333fb 100644
--- a/tools/editor/icons/2x/icon_viewport.png
+++ b/editor/icons/2x/icon_viewport.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_viewport_container.png b/editor/icons/2x/icon_viewport_container.png
index c43e53c34e..c43e53c34e 100644
--- a/tools/editor/icons/2x/icon_viewport_container.png
+++ b/editor/icons/2x/icon_viewport_container.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_viewport_sprite.png b/editor/icons/2x/icon_viewport_sprite.png
index adb336103f..adb336103f 100644
--- a/tools/editor/icons/2x/icon_viewport_sprite.png
+++ b/editor/icons/2x/icon_viewport_sprite.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_viewport_texture.png b/editor/icons/2x/icon_viewport_texture.png
index f798f1d221..f798f1d221 100644
--- a/tools/editor/icons/2x/icon_viewport_texture.png
+++ b/editor/icons/2x/icon_viewport_texture.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_visibility_enabler.png b/editor/icons/2x/icon_visibility_enabler.png
index 4be06a5123..4be06a5123 100644
--- a/tools/editor/icons/2x/icon_visibility_enabler.png
+++ b/editor/icons/2x/icon_visibility_enabler.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_visibility_enabler_2d.png b/editor/icons/2x/icon_visibility_enabler_2d.png
index 3d592e8983..3d592e8983 100644
--- a/tools/editor/icons/2x/icon_visibility_enabler_2d.png
+++ b/editor/icons/2x/icon_visibility_enabler_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_visibility_notifier.png b/editor/icons/2x/icon_visibility_notifier.png
index aa73402d8e..aa73402d8e 100644
--- a/tools/editor/icons/2x/icon_visibility_notifier.png
+++ b/editor/icons/2x/icon_visibility_notifier.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_visibility_notifier_2d.png b/editor/icons/2x/icon_visibility_notifier_2d.png
index 5f3b7ecf42..5f3b7ecf42 100644
--- a/tools/editor/icons/2x/icon_visibility_notifier_2d.png
+++ b/editor/icons/2x/icon_visibility_notifier_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_visible.png b/editor/icons/2x/icon_visible.png
index 761ff12c66..761ff12c66 100644
--- a/tools/editor/icons/2x/icon_visible.png
+++ b/editor/icons/2x/icon_visible.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_visual_script.png b/editor/icons/2x/icon_visual_script.png
index 78a3a0c318..78a3a0c318 100644
--- a/tools/editor/icons/2x/icon_visual_script.png
+++ b/editor/icons/2x/icon_visual_script.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_visual_shader_port.png b/editor/icons/2x/icon_visual_shader_port.png
index 3f9bf96b01..3f9bf96b01 100644
--- a/tools/editor/icons/2x/icon_visual_shader_port.png
+++ b/editor/icons/2x/icon_visual_shader_port.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_vu_empty.png b/editor/icons/2x/icon_vu_empty.png
index 7ecf215933..7ecf215933 100644
--- a/tools/editor/icons/2x/icon_vu_empty.png
+++ b/editor/icons/2x/icon_vu_empty.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_vu_full.png b/editor/icons/2x/icon_vu_full.png
index cfd29fa833..cfd29fa833 100644
--- a/tools/editor/icons/2x/icon_vu_full.png
+++ b/editor/icons/2x/icon_vu_full.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_warning.png b/editor/icons/2x/icon_warning.png
index 5d807065e7..5d807065e7 100644
--- a/tools/editor/icons/2x/icon_warning.png
+++ b/editor/icons/2x/icon_warning.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_window_dialog.png b/editor/icons/2x/icon_window_dialog.png
index 995381ed5f..995381ed5f 100644
--- a/tools/editor/icons/2x/icon_window_dialog.png
+++ b/editor/icons/2x/icon_window_dialog.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_world.png b/editor/icons/2x/icon_world.png
index 51b587c01e..51b587c01e 100644
--- a/tools/editor/icons/2x/icon_world.png
+++ b/editor/icons/2x/icon_world.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_world_2d.png b/editor/icons/2x/icon_world_2d.png
index e9cfa10461..e9cfa10461 100644
--- a/tools/editor/icons/2x/icon_world_2d.png
+++ b/editor/icons/2x/icon_world_2d.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_world_environment.png b/editor/icons/2x/icon_world_environment.png
index 9ca558fcba..9ca558fcba 100644
--- a/tools/editor/icons/2x/icon_world_environment.png
+++ b/editor/icons/2x/icon_world_environment.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_y_sort.png b/editor/icons/2x/icon_y_sort.png
index a38cbbe863..a38cbbe863 100644
--- a/tools/editor/icons/2x/icon_y_sort.png
+++ b/editor/icons/2x/icon_y_sort.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_zoom.png b/editor/icons/2x/icon_zoom.png
index 0c4a6a8c84..0c4a6a8c84 100644
--- a/tools/editor/icons/2x/icon_zoom.png
+++ b/editor/icons/2x/icon_zoom.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_zoom_less.png b/editor/icons/2x/icon_zoom_less.png
index d483db55ce..d483db55ce 100644
--- a/tools/editor/icons/2x/icon_zoom_less.png
+++ b/editor/icons/2x/icon_zoom_less.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_zoom_more.png b/editor/icons/2x/icon_zoom_more.png
index 8f9ef77849..8f9ef77849 100644
--- a/tools/editor/icons/2x/icon_zoom_more.png
+++ b/editor/icons/2x/icon_zoom_more.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_zoom_reset.png b/editor/icons/2x/icon_zoom_reset.png
index 092215b3e2..092215b3e2 100644
--- a/tools/editor/icons/2x/icon_zoom_reset.png
+++ b/editor/icons/2x/icon_zoom_reset.png
Binary files differ
diff --git a/editor/icons/SCsub b/editor/icons/SCsub
new file mode 100644
index 0000000000..3fc8e5461f
--- /dev/null
+++ b/editor/icons/SCsub
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+
+Import('env')
+
+
+def make_editor_icons_action(target, source, env):
+
+ import os
+ import cStringIO
+
+ dst = target[0].srcnode().abspath
+ pixmaps = source
+
+ s = cStringIO.StringIO()
+
+ s.write("#include \"editor_icons.h\"\n\n")
+ s.write("#include \"editor_scale.h\"\n\n")
+ s.write("#include \"scene/resources/theme.h\"\n\n")
+
+ hidpi_list = []
+
+ for x in pixmaps:
+
+ x = str(x)
+ var_str = os.path.basename(x)[:-4] + "_png"
+ # print(var_str)
+
+ s.write("static const unsigned char " + var_str + "[]={\n")
+
+ pngf = open(x, "rb")
+
+ b = pngf.read(1)
+ while(len(b) == 1):
+ s.write(hex(ord(b)))
+ b = pngf.read(1)
+ if (len(b) == 1):
+ s.write(",")
+
+ s.write("\n};\n\n")
+
+ pngf.close()
+ var_str = os.path.basename(x)[:-4] + "_hidpi_png"
+ try:
+
+ pngf = open(os.path.dirname(x) + "/2x/" + os.path.basename(x), "rb")
+
+ s.write("static const unsigned char " + var_str + "[]={\n")
+
+ b = pngf.read(1)
+ while(len(b) == 1):
+ s.write(hex(ord(b)))
+ b = pngf.read(1)
+ if (len(b) == 1):
+ s.write(",")
+
+ s.write("\n};\n\n\n")
+ hidpi_list.append(x)
+
+ except:
+ s.write("static const unsigned char* " + var_str + "=NULL;\n\n\n")
+
+ s.write("static Ref<ImageTexture> make_icon(const uint8_t* p_png,const uint8_t* p_hidpi_png) {\n")
+ s.write("\tRef<ImageTexture> texture( memnew( ImageTexture ) );\n")
+ s.write("\tbool use_hidpi_image=(editor_get_scale()>1.0&&p_hidpi_png);\n")
+ s.write("\tImage img(use_hidpi_image?p_hidpi_png:p_png);\n")
+ s.write("\tif (editor_get_scale()>1.0 && !p_hidpi_png) { img.convert(Image::FORMAT_RGBA8); img.expand_x2_hq2x(); use_hidpi_image=true;}\n")
+ s.write("\timg.resize(img.get_width()*EDSCALE/(use_hidpi_image?2:1),img.get_height()*EDSCALE/(use_hidpi_image?2:1));\n")
+ s.write("\ttexture->create_from_image( img,ImageTexture::FLAG_FILTER );\n")
+ s.write("\treturn texture;\n")
+ s.write("}\n\n")
+
+ s.write("void editor_register_icons(Ref<Theme> p_theme) {\n\n")
+
+ for x in pixmaps:
+
+ x = os.path.basename(str(x))
+ type = x[5:-4].title().replace("_", "")
+ var_str = x[:-4] + "_png"
+ var_str_hidpi = x[:-4] + "_hidpi_png"
+ s.write("\tp_theme->set_icon(\"" + type + "\",\"EditorIcons\",make_icon(" + var_str + "," + var_str_hidpi + "));\n")
+
+ s.write("\n\n}\n\n")
+
+ f = open(dst, "wb")
+ f.write(s.getvalue())
+ f.close()
+ s.close()
+
+make_editor_icons_builder = Builder(action=make_editor_icons_action,
+ suffix='.cpp',
+ src_suffix='.png')
+env['BUILDERS']['MakeEditorIconsBuilder'] = make_editor_icons_builder
+env.Alias('editor_icons', [env.MakeEditorIconsBuilder('#editor/editor_icons.cpp', Glob("*.png"))])
+
+env.editor_sources.append("#editor/editor_icons.cpp")
+Export('env')
diff --git a/tools/editor/icons/icon_accept_dialog.png b/editor/icons/icon_accept_dialog.png
index 7530127f82..7530127f82 100644
--- a/tools/editor/icons/icon_accept_dialog.png
+++ b/editor/icons/icon_accept_dialog.png
Binary files differ
diff --git a/tools/editor/icons/icon_add.png b/editor/icons/icon_add.png
index fa675045bc..fa675045bc 100644
--- a/tools/editor/icons/icon_add.png
+++ b/editor/icons/icon_add.png
Binary files differ
diff --git a/tools/editor/icons/icon_add_track.png b/editor/icons/icon_add_track.png
index fa675045bc..fa675045bc 100644
--- a/tools/editor/icons/icon_add_track.png
+++ b/editor/icons/icon_add_track.png
Binary files differ
diff --git a/tools/editor/icons/icon_anchor.png b/editor/icons/icon_anchor.png
index 7b02eb448e..7b02eb448e 100644
--- a/tools/editor/icons/icon_anchor.png
+++ b/editor/icons/icon_anchor.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_export.png b/editor/icons/icon_anim_export.png
index b17ecdeb22..b17ecdeb22 100644
--- a/tools/editor/icons/icon_anim_export.png
+++ b/editor/icons/icon_anim_export.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_export_all.png b/editor/icons/icon_anim_export_all.png
index 65a3cf5745..65a3cf5745 100644
--- a/tools/editor/icons/icon_anim_export_all.png
+++ b/editor/icons/icon_anim_export_all.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_get.png b/editor/icons/icon_anim_get.png
index 7edd883f02..7edd883f02 100644
--- a/tools/editor/icons/icon_anim_get.png
+++ b/editor/icons/icon_anim_get.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_get_hl.png b/editor/icons/icon_anim_get_hl.png
index fa6e94545b..fa6e94545b 100644
--- a/tools/editor/icons/icon_anim_get_hl.png
+++ b/editor/icons/icon_anim_get_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_import.png b/editor/icons/icon_anim_import.png
index 166e3fecd7..166e3fecd7 100644
--- a/tools/editor/icons/icon_anim_import.png
+++ b/editor/icons/icon_anim_import.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_import_all.png b/editor/icons/icon_anim_import_all.png
index c99893d59d..c99893d59d 100644
--- a/tools/editor/icons/icon_anim_import_all.png
+++ b/editor/icons/icon_anim_import_all.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_set.png b/editor/icons/icon_anim_set.png
index c52334c72f..c52334c72f 100644
--- a/tools/editor/icons/icon_anim_set.png
+++ b/editor/icons/icon_anim_set.png
Binary files differ
diff --git a/tools/editor/icons/icon_anim_set_hl.png b/editor/icons/icon_anim_set_hl.png
index aefaf7f738..aefaf7f738 100644
--- a/tools/editor/icons/icon_anim_set_hl.png
+++ b/editor/icons/icon_anim_set_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_animated_sprite.png b/editor/icons/icon_animated_sprite.png
index 6b6cb2fbfa..6b6cb2fbfa 100644
--- a/tools/editor/icons/icon_animated_sprite.png
+++ b/editor/icons/icon_animated_sprite.png
Binary files differ
diff --git a/tools/editor/icons/icon_animated_sprite_3d.png b/editor/icons/icon_animated_sprite_3d.png
index e04d687bfb..e04d687bfb 100644
--- a/tools/editor/icons/icon_animated_sprite_3d.png
+++ b/editor/icons/icon_animated_sprite_3d.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation.png b/editor/icons/icon_animation.png
index b333f82711..b333f82711 100644
--- a/tools/editor/icons/icon_animation.png
+++ b/editor/icons/icon_animation.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation_node.png b/editor/icons/icon_animation_node.png
index 81026b3a98..81026b3a98 100644
--- a/tools/editor/icons/icon_animation_node.png
+++ b/editor/icons/icon_animation_node.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation_play.png b/editor/icons/icon_animation_play.png
index b405bf98f4..b405bf98f4 100644
--- a/tools/editor/icons/icon_animation_play.png
+++ b/editor/icons/icon_animation_play.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation_player.png b/editor/icons/icon_animation_player.png
index 8a6f446e4e..8a6f446e4e 100644
--- a/tools/editor/icons/icon_animation_player.png
+++ b/editor/icons/icon_animation_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation_set.png b/editor/icons/icon_animation_set.png
index b603382b0c..b603382b0c 100644
--- a/tools/editor/icons/icon_animation_set.png
+++ b/editor/icons/icon_animation_set.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation_tree.png b/editor/icons/icon_animation_tree.png
index 684edb876b..684edb876b 100644
--- a/tools/editor/icons/icon_animation_tree.png
+++ b/editor/icons/icon_animation_tree.png
Binary files differ
diff --git a/tools/editor/icons/icon_animation_tree_player.png b/editor/icons/icon_animation_tree_player.png
index 684edb876b..684edb876b 100644
--- a/tools/editor/icons/icon_animation_tree_player.png
+++ b/editor/icons/icon_animation_tree_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_area.png b/editor/icons/icon_area.png
index 31b4473d17..31b4473d17 100644
--- a/tools/editor/icons/icon_area.png
+++ b/editor/icons/icon_area.png
Binary files differ
diff --git a/tools/editor/icons/icon_area_2d.png b/editor/icons/icon_area_2d.png
index 2f9c6bb8d4..2f9c6bb8d4 100644
--- a/tools/editor/icons/icon_area_2d.png
+++ b/editor/icons/icon_area_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_data.png b/editor/icons/icon_array_data.png
index 447acaab2b..447acaab2b 100644
--- a/tools/editor/icons/icon_array_data.png
+++ b/editor/icons/icon_array_data.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_float.png b/editor/icons/icon_array_float.png
index d1b78b4c3e..d1b78b4c3e 100644
--- a/tools/editor/icons/icon_array_float.png
+++ b/editor/icons/icon_array_float.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_int.png b/editor/icons/icon_array_int.png
index 2c4ec5bafb..2c4ec5bafb 100644
--- a/tools/editor/icons/icon_array_int.png
+++ b/editor/icons/icon_array_int.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_string.png b/editor/icons/icon_array_string.png
index a2e3f11c35..a2e3f11c35 100644
--- a/tools/editor/icons/icon_array_string.png
+++ b/editor/icons/icon_array_string.png
Binary files differ
diff --git a/tools/editor/icons/icon_array_variant.png b/editor/icons/icon_array_variant.png
index ab294898ad..ab294898ad 100644
--- a/tools/editor/icons/icon_array_variant.png
+++ b/editor/icons/icon_array_variant.png
Binary files differ
diff --git a/tools/editor/icons/icon_arrow_left.png b/editor/icons/icon_arrow_left.png
index 1e0d38b4b6..1e0d38b4b6 100644
--- a/tools/editor/icons/icon_arrow_left.png
+++ b/editor/icons/icon_arrow_left.png
Binary files differ
diff --git a/tools/editor/icons/icon_arrow_left_disabled.png b/editor/icons/icon_arrow_left_disabled.png
index f1f9d0f988..f1f9d0f988 100644
--- a/tools/editor/icons/icon_arrow_left_disabled.png
+++ b/editor/icons/icon_arrow_left_disabled.png
Binary files differ
diff --git a/tools/editor/icons/icon_arrow_right.png b/editor/icons/icon_arrow_right.png
index 09907755e1..09907755e1 100644
--- a/tools/editor/icons/icon_arrow_right.png
+++ b/editor/icons/icon_arrow_right.png
Binary files differ
diff --git a/tools/editor/icons/icon_arrow_right_disabled.png b/editor/icons/icon_arrow_right_disabled.png
index 840cd0da0a..840cd0da0a 100644
--- a/tools/editor/icons/icon_arrow_right_disabled.png
+++ b/editor/icons/icon_arrow_right_disabled.png
Binary files differ
diff --git a/tools/editor/icons/icon_arrow_up.png b/editor/icons/icon_arrow_up.png
index f7ec666f69..f7ec666f69 100644
--- a/tools/editor/icons/icon_arrow_up.png
+++ b/editor/icons/icon_arrow_up.png
Binary files differ
diff --git a/tools/editor/icons/icon_arrow_up_disabled.png b/editor/icons/icon_arrow_up_disabled.png
index fb46aa1373..fb46aa1373 100644
--- a/tools/editor/icons/icon_arrow_up_disabled.png
+++ b/editor/icons/icon_arrow_up_disabled.png
Binary files differ
diff --git a/tools/editor/icons/icon_atlas_texture.png b/editor/icons/icon_atlas_texture.png
index 438ac8bfb5..438ac8bfb5 100644
--- a/tools/editor/icons/icon_atlas_texture.png
+++ b/editor/icons/icon_atlas_texture.png
Binary files differ
diff --git a/tools/editor/icons/icon_audio_effect_amplify.png b/editor/icons/icon_audio_effect_amplify.png
index 9af3227d40..9af3227d40 100644
--- a/tools/editor/icons/icon_audio_effect_amplify.png
+++ b/editor/icons/icon_audio_effect_amplify.png
Binary files differ
diff --git a/tools/editor/icons/icon_audio_stream_gibberish.png b/editor/icons/icon_audio_stream_gibberish.png
index 60c85fa5b4..60c85fa5b4 100644
--- a/tools/editor/icons/icon_audio_stream_gibberish.png
+++ b/editor/icons/icon_audio_stream_gibberish.png
Binary files differ
diff --git a/tools/editor/icons/icon_audio_stream_m_p_c.png b/editor/icons/icon_audio_stream_m_p_c.png
index 665d7b56a1..665d7b56a1 100644
--- a/tools/editor/icons/icon_audio_stream_m_p_c.png
+++ b/editor/icons/icon_audio_stream_m_p_c.png
Binary files differ
diff --git a/tools/editor/icons/icon_audio_stream_o_g_g_vorbis.png b/editor/icons/icon_audio_stream_o_g_g_vorbis.png
index 7860e111d0..7860e111d0 100644
--- a/tools/editor/icons/icon_audio_stream_o_g_g_vorbis.png
+++ b/editor/icons/icon_audio_stream_o_g_g_vorbis.png
Binary files differ
diff --git a/tools/editor/icons/icon_audio_stream_opus.png b/editor/icons/icon_audio_stream_opus.png
index 69b0c83b4d..69b0c83b4d 100644
--- a/tools/editor/icons/icon_audio_stream_opus.png
+++ b/editor/icons/icon_audio_stream_opus.png
Binary files differ
diff --git a/tools/editor/icons/icon_audio_stream_speex.png b/editor/icons/icon_audio_stream_speex.png
index 6fefe47284..6fefe47284 100644
--- a/tools/editor/icons/icon_audio_stream_speex.png
+++ b/editor/icons/icon_audio_stream_speex.png
Binary files differ
diff --git a/tools/editor/icons/icon_auto_play.png b/editor/icons/icon_auto_play.png
index a6be64a1d1..a6be64a1d1 100644
--- a/tools/editor/icons/icon_auto_play.png
+++ b/editor/icons/icon_auto_play.png
Binary files differ
diff --git a/tools/editor/icons/icon_b_c_s_f_x.png b/editor/icons/icon_b_c_s_f_x.png
index 2100aea6a0..2100aea6a0 100644
--- a/tools/editor/icons/icon_b_c_s_f_x.png
+++ b/editor/icons/icon_b_c_s_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_b_g_color_f_x.png b/editor/icons/icon_b_g_color_f_x.png
index 5b7552f6d5..5b7552f6d5 100644
--- a/tools/editor/icons/icon_b_g_color_f_x.png
+++ b/editor/icons/icon_b_g_color_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_b_g_image_f_x.png b/editor/icons/icon_b_g_image_f_x.png
index 7e8ec86eec..7e8ec86eec 100644
--- a/tools/editor/icons/icon_b_g_image_f_x.png
+++ b/editor/icons/icon_b_g_image_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_back.png b/editor/icons/icon_back.png
index 52fbc8117a..52fbc8117a 100644
--- a/tools/editor/icons/icon_back.png
+++ b/editor/icons/icon_back.png
Binary files differ
diff --git a/tools/editor/icons/icon_back_buffer_copy.png b/editor/icons/icon_back_buffer_copy.png
index 35f04ddac8..35f04ddac8 100644
--- a/tools/editor/icons/icon_back_buffer_copy.png
+++ b/editor/icons/icon_back_buffer_copy.png
Binary files differ
diff --git a/tools/editor/icons/icon_back_disabled.png b/editor/icons/icon_back_disabled.png
index 31aab496e2..31aab496e2 100644
--- a/tools/editor/icons/icon_back_disabled.png
+++ b/editor/icons/icon_back_disabled.png
Binary files differ
diff --git a/tools/editor/icons/icon_back_no.png b/editor/icons/icon_back_no.png
index 539ce4124a..539ce4124a 100644
--- a/tools/editor/icons/icon_back_no.png
+++ b/editor/icons/icon_back_no.png
Binary files differ
diff --git a/tools/editor/icons/icon_bake.png b/editor/icons/icon_bake.png
index 3b7fce5c9f..3b7fce5c9f 100644
--- a/tools/editor/icons/icon_bake.png
+++ b/editor/icons/icon_bake.png
Binary files differ
diff --git a/tools/editor/icons/icon_baked_light.png b/editor/icons/icon_baked_light.png
index 3b7fce5c9f..3b7fce5c9f 100644
--- a/tools/editor/icons/icon_baked_light.png
+++ b/editor/icons/icon_baked_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_baked_light_instance.png b/editor/icons/icon_baked_light_instance.png
index c667b542c1..c667b542c1 100644
--- a/tools/editor/icons/icon_baked_light_instance.png
+++ b/editor/icons/icon_baked_light_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_baked_light_sampler.png b/editor/icons/icon_baked_light_sampler.png
index 15ff7b98b9..15ff7b98b9 100644
--- a/tools/editor/icons/icon_baked_light_sampler.png
+++ b/editor/icons/icon_baked_light_sampler.png
Binary files differ
diff --git a/tools/editor/icons/icon_bit_map.png b/editor/icons/icon_bit_map.png
index 50dd8157d1..50dd8157d1 100644
--- a/tools/editor/icons/icon_bit_map.png
+++ b/editor/icons/icon_bit_map.png
Binary files differ
diff --git a/tools/editor/icons/icon_bitmap_font.png b/editor/icons/icon_bitmap_font.png
index 5334c335dc..5334c335dc 100644
--- a/tools/editor/icons/icon_bitmap_font.png
+++ b/editor/icons/icon_bitmap_font.png
Binary files differ
diff --git a/tools/editor/icons/icon_blend.png b/editor/icons/icon_blend.png
index 1676c650c2..1676c650c2 100644
--- a/tools/editor/icons/icon_blend.png
+++ b/editor/icons/icon_blend.png
Binary files differ
diff --git a/tools/editor/icons/icon_bone.png b/editor/icons/icon_bone.png
index 2d9a7b47f3..2d9a7b47f3 100644
--- a/tools/editor/icons/icon_bone.png
+++ b/editor/icons/icon_bone.png
Binary files differ
diff --git a/tools/editor/icons/icon_bone_attachment.png b/editor/icons/icon_bone_attachment.png
index 882bb55f44..882bb55f44 100644
--- a/tools/editor/icons/icon_bone_attachment.png
+++ b/editor/icons/icon_bone_attachment.png
Binary files differ
diff --git a/tools/editor/icons/icon_bone_track.png b/editor/icons/icon_bone_track.png
index 1e55e53d6b..1e55e53d6b 100644
--- a/tools/editor/icons/icon_bone_track.png
+++ b/editor/icons/icon_bone_track.png
Binary files differ
diff --git a/tools/editor/icons/icon_bool.png b/editor/icons/icon_bool.png
index 822b5dd688..822b5dd688 100644
--- a/tools/editor/icons/icon_bool.png
+++ b/editor/icons/icon_bool.png
Binary files differ
diff --git a/tools/editor/icons/icon_box_shape.png b/editor/icons/icon_box_shape.png
index 68ec6088c9..68ec6088c9 100644
--- a/tools/editor/icons/icon_box_shape.png
+++ b/editor/icons/icon_box_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_db.png b/editor/icons/icon_bus_vu_db.png
index 52507cae52..52507cae52 100644
--- a/tools/editor/icons/icon_bus_vu_db.png
+++ b/editor/icons/icon_bus_vu_db.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_empty.png b/editor/icons/icon_bus_vu_empty.png
index 6fc3143a55..6fc3143a55 100644
--- a/tools/editor/icons/icon_bus_vu_empty.png
+++ b/editor/icons/icon_bus_vu_empty.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_frozen.png b/editor/icons/icon_bus_vu_frozen.png
index cf128afa91..cf128afa91 100644
--- a/tools/editor/icons/icon_bus_vu_frozen.png
+++ b/editor/icons/icon_bus_vu_frozen.png
Binary files differ
diff --git a/tools/editor/icons/icon_bus_vu_full.png b/editor/icons/icon_bus_vu_full.png
index 9e3d7a93e3..9e3d7a93e3 100644
--- a/tools/editor/icons/icon_bus_vu_full.png
+++ b/editor/icons/icon_bus_vu_full.png
Binary files differ
diff --git a/tools/editor/icons/icon_button.png b/editor/icons/icon_button.png
index da02831da2..da02831da2 100644
--- a/tools/editor/icons/icon_button.png
+++ b/editor/icons/icon_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_button_group.png b/editor/icons/icon_button_group.png
index c105234598..c105234598 100644
--- a/tools/editor/icons/icon_button_group.png
+++ b/editor/icons/icon_button_group.png
Binary files differ
diff --git a/tools/editor/icons/icon_camera.png b/editor/icons/icon_camera.png
index 4dff1791ad..4dff1791ad 100644
--- a/tools/editor/icons/icon_camera.png
+++ b/editor/icons/icon_camera.png
Binary files differ
diff --git a/tools/editor/icons/icon_camera_2d.png b/editor/icons/icon_camera_2d.png
index 6497997afe..6497997afe 100644
--- a/tools/editor/icons/icon_camera_2d.png
+++ b/editor/icons/icon_camera_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_item.png b/editor/icons/icon_canvas_item.png
index 64f5d8abdf..64f5d8abdf 100644
--- a/tools/editor/icons/icon_canvas_item.png
+++ b/editor/icons/icon_canvas_item.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_item_material.png b/editor/icons/icon_canvas_item_material.png
index a04f6e8f5f..a04f6e8f5f 100644
--- a/tools/editor/icons/icon_canvas_item_material.png
+++ b/editor/icons/icon_canvas_item_material.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_item_shader.png b/editor/icons/icon_canvas_item_shader.png
index 8392f889d1..8392f889d1 100644
--- a/tools/editor/icons/icon_canvas_item_shader.png
+++ b/editor/icons/icon_canvas_item_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_item_shader_graph.png b/editor/icons/icon_canvas_item_shader_graph.png
index f40e3755af..f40e3755af 100644
--- a/tools/editor/icons/icon_canvas_item_shader_graph.png
+++ b/editor/icons/icon_canvas_item_shader_graph.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_layer.png b/editor/icons/icon_canvas_layer.png
index bb32d6d3ad..bb32d6d3ad 100644
--- a/tools/editor/icons/icon_canvas_layer.png
+++ b/editor/icons/icon_canvas_layer.png
Binary files differ
diff --git a/tools/editor/icons/icon_canvas_modulate.png b/editor/icons/icon_canvas_modulate.png
index b76e532268..b76e532268 100644
--- a/tools/editor/icons/icon_canvas_modulate.png
+++ b/editor/icons/icon_canvas_modulate.png
Binary files differ
diff --git a/tools/editor/icons/icon_capsule_shape.png b/editor/icons/icon_capsule_shape.png
index bc00e491d3..bc00e491d3 100644
--- a/tools/editor/icons/icon_capsule_shape.png
+++ b/editor/icons/icon_capsule_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_capsule_shape_2d.png b/editor/icons/icon_capsule_shape_2d.png
index 6f6554fbc7..6f6554fbc7 100644
--- a/tools/editor/icons/icon_capsule_shape_2d.png
+++ b/editor/icons/icon_capsule_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_center_container.png b/editor/icons/icon_center_container.png
index 61904e7b00..61904e7b00 100644
--- a/tools/editor/icons/icon_center_container.png
+++ b/editor/icons/icon_center_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_character_body.png b/editor/icons/icon_character_body.png
index b859a271d5..b859a271d5 100644
--- a/tools/editor/icons/icon_character_body.png
+++ b/editor/icons/icon_character_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_character_camera.png b/editor/icons/icon_character_camera.png
index c238487942..c238487942 100644
--- a/tools/editor/icons/icon_character_camera.png
+++ b/editor/icons/icon_character_camera.png
Binary files differ
diff --git a/tools/editor/icons/icon_check_box.png b/editor/icons/icon_check_box.png
index f0e614d0e7..f0e614d0e7 100644
--- a/tools/editor/icons/icon_check_box.png
+++ b/editor/icons/icon_check_box.png
Binary files differ
diff --git a/tools/editor/icons/icon_check_button.png b/editor/icons/icon_check_button.png
index 968188f43d..968188f43d 100644
--- a/tools/editor/icons/icon_check_button.png
+++ b/editor/icons/icon_check_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_checkerboard.png b/editor/icons/icon_checkerboard.png
index 5f658c765e..5f658c765e 100644
--- a/tools/editor/icons/icon_checkerboard.png
+++ b/editor/icons/icon_checkerboard.png
Binary files differ
diff --git a/tools/editor/icons/icon_circle_shape_2d.png b/editor/icons/icon_circle_shape_2d.png
index 7865ed3dbe..7865ed3dbe 100644
--- a/tools/editor/icons/icon_circle_shape_2d.png
+++ b/editor/icons/icon_circle_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_class_list.png b/editor/icons/icon_class_list.png
index 5faff250d7..5faff250d7 100644
--- a/tools/editor/icons/icon_class_list.png
+++ b/editor/icons/icon_class_list.png
Binary files differ
diff --git a/tools/editor/icons/icon_click2edit.png b/editor/icons/icon_click2edit.png
index 795756dff0..795756dff0 100644
--- a/tools/editor/icons/icon_click2edit.png
+++ b/editor/icons/icon_click2edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_close.png b/editor/icons/icon_close.png
index 20d9b5c810..20d9b5c810 100644
--- a/tools/editor/icons/icon_close.png
+++ b/editor/icons/icon_close.png
Binary files differ
diff --git a/tools/editor/icons/icon_close_hover.png b/editor/icons/icon_close_hover.png
index cb519691e5..cb519691e5 100644
--- a/tools/editor/icons/icon_close_hover.png
+++ b/editor/icons/icon_close_hover.png
Binary files differ
diff --git a/tools/editor/icons/icon_collapse.png b/editor/icons/icon_collapse.png
index ad2442183d..ad2442183d 100644
--- a/tools/editor/icons/icon_collapse.png
+++ b/editor/icons/icon_collapse.png
Binary files differ
diff --git a/tools/editor/icons/icon_collapse_hl.png b/editor/icons/icon_collapse_hl.png
index 0dfbc8b175..0dfbc8b175 100644
--- a/tools/editor/icons/icon_collapse_hl.png
+++ b/editor/icons/icon_collapse_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_collision.png b/editor/icons/icon_collision.png
index ccda8b6a25..ccda8b6a25 100644
--- a/tools/editor/icons/icon_collision.png
+++ b/editor/icons/icon_collision.png
Binary files differ
diff --git a/tools/editor/icons/icon_collision_2d.png b/editor/icons/icon_collision_2d.png
index b372749cb0..b372749cb0 100644
--- a/tools/editor/icons/icon_collision_2d.png
+++ b/editor/icons/icon_collision_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_collision_polygon.png b/editor/icons/icon_collision_polygon.png
index 738f80c3f3..738f80c3f3 100644
--- a/tools/editor/icons/icon_collision_polygon.png
+++ b/editor/icons/icon_collision_polygon.png
Binary files differ
diff --git a/tools/editor/icons/icon_collision_polygon_2d.png b/editor/icons/icon_collision_polygon_2d.png
index b372749cb0..b372749cb0 100644
--- a/tools/editor/icons/icon_collision_polygon_2d.png
+++ b/editor/icons/icon_collision_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_collision_shape.png b/editor/icons/icon_collision_shape.png
index 7bcd61c719..7bcd61c719 100644
--- a/tools/editor/icons/icon_collision_shape.png
+++ b/editor/icons/icon_collision_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_collision_shape_2d.png b/editor/icons/icon_collision_shape_2d.png
index afc1326959..afc1326959 100644
--- a/tools/editor/icons/icon_collision_shape_2d.png
+++ b/editor/icons/icon_collision_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_color.png b/editor/icons/icon_color.png
index 589a6d3ffa..589a6d3ffa 100644
--- a/tools/editor/icons/icon_color.png
+++ b/editor/icons/icon_color.png
Binary files differ
diff --git a/tools/editor/icons/icon_color_pick.png b/editor/icons/icon_color_pick.png
index 15679a9558..15679a9558 100644
--- a/tools/editor/icons/icon_color_pick.png
+++ b/editor/icons/icon_color_pick.png
Binary files differ
diff --git a/tools/editor/icons/icon_color_picker.png b/editor/icons/icon_color_picker.png
index 6d1114054a..6d1114054a 100644
--- a/tools/editor/icons/icon_color_picker.png
+++ b/editor/icons/icon_color_picker.png
Binary files differ
diff --git a/tools/editor/icons/icon_color_picker_button.png b/editor/icons/icon_color_picker_button.png
index a399128773..a399128773 100644
--- a/tools/editor/icons/icon_color_picker_button.png
+++ b/editor/icons/icon_color_picker_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_color_ramp.png b/editor/icons/icon_color_ramp.png
index 03d19a56bb..03d19a56bb 100644
--- a/tools/editor/icons/icon_color_ramp.png
+++ b/editor/icons/icon_color_ramp.png
Binary files differ
diff --git a/tools/editor/icons/icon_color_rect.png b/editor/icons/icon_color_rect.png
index 40b9dab605..40b9dab605 100644
--- a/tools/editor/icons/icon_color_rect.png
+++ b/editor/icons/icon_color_rect.png
Binary files differ
diff --git a/tools/editor/icons/icon_concave_polygon_shape.png b/editor/icons/icon_concave_polygon_shape.png
index dc1ff1d388..dc1ff1d388 100644
--- a/tools/editor/icons/icon_concave_polygon_shape.png
+++ b/editor/icons/icon_concave_polygon_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_concave_polygon_shape_2d.png b/editor/icons/icon_concave_polygon_shape_2d.png
index 2e87eea5aa..2e87eea5aa 100644
--- a/tools/editor/icons/icon_concave_polygon_shape_2d.png
+++ b/editor/icons/icon_concave_polygon_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_cone_twist_joint.png b/editor/icons/icon_cone_twist_joint.png
index bbf93f2f71..bbf93f2f71 100644
--- a/tools/editor/icons/icon_cone_twist_joint.png
+++ b/editor/icons/icon_cone_twist_joint.png
Binary files differ
diff --git a/tools/editor/icons/icon_confirmation_dialog.png b/editor/icons/icon_confirmation_dialog.png
index 2dd4cd00fb..2dd4cd00fb 100644
--- a/tools/editor/icons/icon_confirmation_dialog.png
+++ b/editor/icons/icon_confirmation_dialog.png
Binary files differ
diff --git a/tools/editor/icons/icon_connect.png b/editor/icons/icon_connect.png
index 51615838a9..51615838a9 100644
--- a/tools/editor/icons/icon_connect.png
+++ b/editor/icons/icon_connect.png
Binary files differ
diff --git a/tools/editor/icons/icon_connection_and_groups.png b/editor/icons/icon_connection_and_groups.png
index 76e036e5bb..76e036e5bb 100644
--- a/tools/editor/icons/icon_connection_and_groups.png
+++ b/editor/icons/icon_connection_and_groups.png
Binary files differ
diff --git a/tools/editor/icons/icon_console.png b/editor/icons/icon_console.png
index 7dc7407ef7..7dc7407ef7 100644
--- a/tools/editor/icons/icon_console.png
+++ b/editor/icons/icon_console.png
Binary files differ
diff --git a/tools/editor/icons/icon_container.png b/editor/icons/icon_container.png
index ae0d76072b..ae0d76072b 100644
--- a/tools/editor/icons/icon_container.png
+++ b/editor/icons/icon_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_control.png b/editor/icons/icon_control.png
index 0d2a82ad0e..0d2a82ad0e 100644
--- a/tools/editor/icons/icon_control.png
+++ b/editor/icons/icon_control.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_center.png b/editor/icons/icon_control_align_bottom_center.png
index 166f122ace..166f122ace 100644
--- a/tools/editor/icons/icon_control_align_bottom_center.png
+++ b/editor/icons/icon_control_align_bottom_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_left.png b/editor/icons/icon_control_align_bottom_left.png
index 238f33a098..238f33a098 100644
--- a/tools/editor/icons/icon_control_align_bottom_left.png
+++ b/editor/icons/icon_control_align_bottom_left.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_right.png b/editor/icons/icon_control_align_bottom_right.png
index ff8b6a0177..ff8b6a0177 100644
--- a/tools/editor/icons/icon_control_align_bottom_right.png
+++ b/editor/icons/icon_control_align_bottom_right.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_bottom_wide.png b/editor/icons/icon_control_align_bottom_wide.png
index 309907767e..309907767e 100644
--- a/tools/editor/icons/icon_control_align_bottom_wide.png
+++ b/editor/icons/icon_control_align_bottom_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_center.png b/editor/icons/icon_control_align_center.png
index 964f132ac3..964f132ac3 100644
--- a/tools/editor/icons/icon_control_align_center.png
+++ b/editor/icons/icon_control_align_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_center_left.png b/editor/icons/icon_control_align_center_left.png
index 704b4f504f..704b4f504f 100644
--- a/tools/editor/icons/icon_control_align_center_left.png
+++ b/editor/icons/icon_control_align_center_left.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_center_right.png b/editor/icons/icon_control_align_center_right.png
index bd7111aec3..bd7111aec3 100644
--- a/tools/editor/icons/icon_control_align_center_right.png
+++ b/editor/icons/icon_control_align_center_right.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_left_center.png b/editor/icons/icon_control_align_left_center.png
index 75c2d8573f..75c2d8573f 100644
--- a/tools/editor/icons/icon_control_align_left_center.png
+++ b/editor/icons/icon_control_align_left_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_left_wide.png b/editor/icons/icon_control_align_left_wide.png
index 92a13144cb..92a13144cb 100644
--- a/tools/editor/icons/icon_control_align_left_wide.png
+++ b/editor/icons/icon_control_align_left_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_right_center.png b/editor/icons/icon_control_align_right_center.png
index a859035439..a859035439 100644
--- a/tools/editor/icons/icon_control_align_right_center.png
+++ b/editor/icons/icon_control_align_right_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_right_wide.png b/editor/icons/icon_control_align_right_wide.png
index b6fef9569e..b6fef9569e 100644
--- a/tools/editor/icons/icon_control_align_right_wide.png
+++ b/editor/icons/icon_control_align_right_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_center.png b/editor/icons/icon_control_align_top_center.png
index 5cdd6cd2fc..5cdd6cd2fc 100644
--- a/tools/editor/icons/icon_control_align_top_center.png
+++ b/editor/icons/icon_control_align_top_center.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_left.png b/editor/icons/icon_control_align_top_left.png
index 558e3f08cb..558e3f08cb 100644
--- a/tools/editor/icons/icon_control_align_top_left.png
+++ b/editor/icons/icon_control_align_top_left.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_right.png b/editor/icons/icon_control_align_top_right.png
index 5ca294de48..5ca294de48 100644
--- a/tools/editor/icons/icon_control_align_top_right.png
+++ b/editor/icons/icon_control_align_top_right.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_top_wide.png b/editor/icons/icon_control_align_top_wide.png
index ec089d0174..ec089d0174 100644
--- a/tools/editor/icons/icon_control_align_top_wide.png
+++ b/editor/icons/icon_control_align_top_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_align_wide.png b/editor/icons/icon_control_align_wide.png
index 45552740bf..45552740bf 100644
--- a/tools/editor/icons/icon_control_align_wide.png
+++ b/editor/icons/icon_control_align_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_hcenter_wide.png b/editor/icons/icon_control_hcenter_wide.png
index f298b22f5f..f298b22f5f 100644
--- a/tools/editor/icons/icon_control_hcenter_wide.png
+++ b/editor/icons/icon_control_hcenter_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_control_vcenter_wide.png b/editor/icons/icon_control_vcenter_wide.png
index b6c90646fb..b6c90646fb 100644
--- a/tools/editor/icons/icon_control_vcenter_wide.png
+++ b/editor/icons/icon_control_vcenter_wide.png
Binary files differ
diff --git a/tools/editor/icons/icon_convex_polygon_shape.png b/editor/icons/icon_convex_polygon_shape.png
index 4dfc9acc9e..4dfc9acc9e 100644
--- a/tools/editor/icons/icon_convex_polygon_shape.png
+++ b/editor/icons/icon_convex_polygon_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_convex_polygon_shape_2d.png b/editor/icons/icon_convex_polygon_shape_2d.png
index e449c6930f..e449c6930f 100644
--- a/tools/editor/icons/icon_convex_polygon_shape_2d.png
+++ b/editor/icons/icon_convex_polygon_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_copy_node_path.png b/editor/icons/icon_copy_node_path.png
index d777f132d8..d777f132d8 100644
--- a/tools/editor/icons/icon_copy_node_path.png
+++ b/editor/icons/icon_copy_node_path.png
Binary files differ
diff --git a/tools/editor/icons/icon_create_new_scene_from.png b/editor/icons/icon_create_new_scene_from.png
index 45df9b1e25..45df9b1e25 100644
--- a/tools/editor/icons/icon_create_new_scene_from.png
+++ b/editor/icons/icon_create_new_scene_from.png
Binary files differ
diff --git a/tools/editor/icons/icon_cube_grid_map.png b/editor/icons/icon_cube_grid_map.png
index fe13222691..fe13222691 100644
--- a/tools/editor/icons/icon_cube_grid_map.png
+++ b/editor/icons/icon_cube_grid_map.png
Binary files differ
diff --git a/tools/editor/icons/icon_cube_map.png b/editor/icons/icon_cube_map.png
index 9c4c6fdc9f..9c4c6fdc9f 100644
--- a/tools/editor/icons/icon_cube_map.png
+++ b/editor/icons/icon_cube_map.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve.png b/editor/icons/icon_curve.png
index 27d423edcd..27d423edcd 100644
--- a/tools/editor/icons/icon_curve.png
+++ b/editor/icons/icon_curve.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_2d.png b/editor/icons/icon_curve_2d.png
index ce46dcaad4..ce46dcaad4 100644
--- a/tools/editor/icons/icon_curve_2d.png
+++ b/editor/icons/icon_curve_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_3d.png b/editor/icons/icon_curve_3d.png
index 561837e4de..561837e4de 100644
--- a/tools/editor/icons/icon_curve_3d.png
+++ b/editor/icons/icon_curve_3d.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_close.png b/editor/icons/icon_curve_close.png
index 9a66015252..9a66015252 100644
--- a/tools/editor/icons/icon_curve_close.png
+++ b/editor/icons/icon_curve_close.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_constant.png b/editor/icons/icon_curve_constant.png
index 510a01c7ec..510a01c7ec 100644
--- a/tools/editor/icons/icon_curve_constant.png
+++ b/editor/icons/icon_curve_constant.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_create.png b/editor/icons/icon_curve_create.png
index b07820a5cd..b07820a5cd 100644
--- a/tools/editor/icons/icon_curve_create.png
+++ b/editor/icons/icon_curve_create.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_curve.png b/editor/icons/icon_curve_curve.png
index 7d71af0a23..7d71af0a23 100644
--- a/tools/editor/icons/icon_curve_curve.png
+++ b/editor/icons/icon_curve_curve.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_delete.png b/editor/icons/icon_curve_delete.png
index 108bfeac35..108bfeac35 100644
--- a/tools/editor/icons/icon_curve_delete.png
+++ b/editor/icons/icon_curve_delete.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_edit.png b/editor/icons/icon_curve_edit.png
index 51eb583384..51eb583384 100644
--- a/tools/editor/icons/icon_curve_edit.png
+++ b/editor/icons/icon_curve_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_in.png b/editor/icons/icon_curve_in.png
index a809ee43d3..a809ee43d3 100644
--- a/tools/editor/icons/icon_curve_in.png
+++ b/editor/icons/icon_curve_in.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_in_out.png b/editor/icons/icon_curve_in_out.png
index 88e07d48a7..88e07d48a7 100644
--- a/tools/editor/icons/icon_curve_in_out.png
+++ b/editor/icons/icon_curve_in_out.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_linear.png b/editor/icons/icon_curve_linear.png
index 80306b6e04..80306b6e04 100644
--- a/tools/editor/icons/icon_curve_linear.png
+++ b/editor/icons/icon_curve_linear.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_out.png b/editor/icons/icon_curve_out.png
index aa05bc8f86..aa05bc8f86 100644
--- a/tools/editor/icons/icon_curve_out.png
+++ b/editor/icons/icon_curve_out.png
Binary files differ
diff --git a/tools/editor/icons/icon_curve_out_in.png b/editor/icons/icon_curve_out_in.png
index 7be46fc779..7be46fc779 100644
--- a/tools/editor/icons/icon_curve_out_in.png
+++ b/editor/icons/icon_curve_out_in.png
Binary files differ
diff --git a/tools/editor/icons/icon_cylinder_shape.png b/editor/icons/icon_cylinder_shape.png
index fd7d7e26e2..fd7d7e26e2 100644
--- a/tools/editor/icons/icon_cylinder_shape.png
+++ b/editor/icons/icon_cylinder_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_d_o_f_blur_f_x.png b/editor/icons/icon_d_o_f_blur_f_x.png
index fda7d48353..fda7d48353 100644
--- a/tools/editor/icons/icon_d_o_f_blur_f_x.png
+++ b/editor/icons/icon_d_o_f_blur_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_damped_spring_joint_2d.png b/editor/icons/icon_damped_spring_joint_2d.png
index b6a9c2b3a1..b6a9c2b3a1 100644
--- a/tools/editor/icons/icon_damped_spring_joint_2d.png
+++ b/editor/icons/icon_damped_spring_joint_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_debug.png b/editor/icons/icon_debug.png
index 03b98aa9e4..03b98aa9e4 100644
--- a/tools/editor/icons/icon_debug.png
+++ b/editor/icons/icon_debug.png
Binary files differ
diff --git a/tools/editor/icons/icon_debug_continue.png b/editor/icons/icon_debug_continue.png
index 78a61aa98f..78a61aa98f 100644
--- a/tools/editor/icons/icon_debug_continue.png
+++ b/editor/icons/icon_debug_continue.png
Binary files differ
diff --git a/tools/editor/icons/icon_debug_next.png b/editor/icons/icon_debug_next.png
index c61f221562..c61f221562 100644
--- a/tools/editor/icons/icon_debug_next.png
+++ b/editor/icons/icon_debug_next.png
Binary files differ
diff --git a/tools/editor/icons/icon_debug_step.png b/editor/icons/icon_debug_step.png
index a1839d56d8..a1839d56d8 100644
--- a/tools/editor/icons/icon_debug_step.png
+++ b/editor/icons/icon_debug_step.png
Binary files differ
diff --git a/tools/editor/icons/icon_default_project_icon.png b/editor/icons/icon_default_project_icon.png
index e87a49bd28..e87a49bd28 100644
--- a/tools/editor/icons/icon_default_project_icon.png
+++ b/editor/icons/icon_default_project_icon.png
Binary files differ
diff --git a/tools/editor/icons/icon_del.png b/editor/icons/icon_del.png
index 10e56d5bb8..10e56d5bb8 100644
--- a/tools/editor/icons/icon_del.png
+++ b/editor/icons/icon_del.png
Binary files differ
diff --git a/tools/editor/icons/icon_dependency_changed.png b/editor/icons/icon_dependency_changed.png
index 1b396457d3..1b396457d3 100644
--- a/tools/editor/icons/icon_dependency_changed.png
+++ b/editor/icons/icon_dependency_changed.png
Binary files differ
diff --git a/tools/editor/icons/icon_dependency_changed_hl.png b/editor/icons/icon_dependency_changed_hl.png
index 51dfe6b39d..51dfe6b39d 100644
--- a/tools/editor/icons/icon_dependency_changed_hl.png
+++ b/editor/icons/icon_dependency_changed_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_dependency_local_changed.png b/editor/icons/icon_dependency_local_changed.png
index d8737fd2f4..d8737fd2f4 100644
--- a/tools/editor/icons/icon_dependency_local_changed.png
+++ b/editor/icons/icon_dependency_local_changed.png
Binary files differ
diff --git a/tools/editor/icons/icon_dependency_local_changed_hl.png b/editor/icons/icon_dependency_local_changed_hl.png
index a87c48ca3e..a87c48ca3e 100644
--- a/tools/editor/icons/icon_dependency_local_changed_hl.png
+++ b/editor/icons/icon_dependency_local_changed_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_dependency_ok.png b/editor/icons/icon_dependency_ok.png
index 2b9ac389ba..2b9ac389ba 100644
--- a/tools/editor/icons/icon_dependency_ok.png
+++ b/editor/icons/icon_dependency_ok.png
Binary files differ
diff --git a/tools/editor/icons/icon_dependency_ok_hl.png b/editor/icons/icon_dependency_ok_hl.png
index 62e48531e4..62e48531e4 100644
--- a/tools/editor/icons/icon_dependency_ok_hl.png
+++ b/editor/icons/icon_dependency_ok_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_directional_light.png b/editor/icons/icon_directional_light.png
index 31f47c974d..31f47c974d 100644
--- a/tools/editor/icons/icon_directional_light.png
+++ b/editor/icons/icon_directional_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_distraction_free.png b/editor/icons/icon_distraction_free.png
index c6f8a08874..c6f8a08874 100644
--- a/tools/editor/icons/icon_distraction_free.png
+++ b/editor/icons/icon_distraction_free.png
Binary files differ
diff --git a/tools/editor/icons/icon_doc_code_font.png b/editor/icons/icon_doc_code_font.png
index 628654f6e8..628654f6e8 100644
--- a/tools/editor/icons/icon_doc_code_font.png
+++ b/editor/icons/icon_doc_code_font.png
Binary files differ
diff --git a/tools/editor/icons/icon_doc_font.png b/editor/icons/icon_doc_font.png
index 65fbcc5ccc..65fbcc5ccc 100644
--- a/tools/editor/icons/icon_doc_font.png
+++ b/editor/icons/icon_doc_font.png
Binary files differ
diff --git a/tools/editor/icons/icon_doc_title_font.png b/editor/icons/icon_doc_title_font.png
index d78b394da0..d78b394da0 100644
--- a/tools/editor/icons/icon_doc_title_font.png
+++ b/editor/icons/icon_doc_title_font.png
Binary files differ
diff --git a/tools/editor/icons/icon_down.png b/editor/icons/icon_down.png
index d2fcdb4c9f..d2fcdb4c9f 100644
--- a/tools/editor/icons/icon_down.png
+++ b/editor/icons/icon_down.png
Binary files differ
diff --git a/tools/editor/icons/icon_dummy.png b/editor/icons/icon_dummy.png
index 24998a28af..24998a28af 100644
--- a/tools/editor/icons/icon_dummy.png
+++ b/editor/icons/icon_dummy.png
Binary files differ
diff --git a/tools/editor/icons/icon_duplicate.png b/editor/icons/icon_duplicate.png
index 320b36504e..320b36504e 100644
--- a/tools/editor/icons/icon_duplicate.png
+++ b/editor/icons/icon_duplicate.png
Binary files differ
diff --git a/tools/editor/icons/icon_dynamic_character_body.png b/editor/icons/icon_dynamic_character_body.png
index b685841e35..b685841e35 100644
--- a/tools/editor/icons/icon_dynamic_character_body.png
+++ b/editor/icons/icon_dynamic_character_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_dynamic_custom_body.png b/editor/icons/icon_dynamic_custom_body.png
index d383e7087f..d383e7087f 100644
--- a/tools/editor/icons/icon_dynamic_custom_body.png
+++ b/editor/icons/icon_dynamic_custom_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_dynamic_font.png b/editor/icons/icon_dynamic_font.png
index e373553e4e..e373553e4e 100644
--- a/tools/editor/icons/icon_dynamic_font.png
+++ b/editor/icons/icon_dynamic_font.png
Binary files differ
diff --git a/tools/editor/icons/icon_dynamic_font_data.png b/editor/icons/icon_dynamic_font_data.png
index 5cff86c40c..5cff86c40c 100644
--- a/tools/editor/icons/icon_dynamic_font_data.png
+++ b/editor/icons/icon_dynamic_font_data.png
Binary files differ
diff --git a/tools/editor/icons/icon_dynamic_rigid_body.png b/editor/icons/icon_dynamic_rigid_body.png
index f804b29528..f804b29528 100644
--- a/tools/editor/icons/icon_dynamic_rigid_body.png
+++ b/editor/icons/icon_dynamic_rigid_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_edit.png b/editor/icons/icon_edit.png
index c114d2f84d..c114d2f84d 100644
--- a/tools/editor/icons/icon_edit.png
+++ b/editor/icons/icon_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_edit_key.png b/editor/icons/icon_edit_key.png
index 3ebbe75f78..3ebbe75f78 100644
--- a/tools/editor/icons/icon_edit_key.png
+++ b/editor/icons/icon_edit_key.png
Binary files differ
diff --git a/tools/editor/icons/icon_edit_pivot.png b/editor/icons/icon_edit_pivot.png
index 230122b969..230122b969 100644
--- a/tools/editor/icons/icon_edit_pivot.png
+++ b/editor/icons/icon_edit_pivot.png
Binary files differ
diff --git a/tools/editor/icons/icon_edit_resource.png b/editor/icons/icon_edit_resource.png
index 9f064fea3f..9f064fea3f 100644
--- a/tools/editor/icons/icon_edit_resource.png
+++ b/editor/icons/icon_edit_resource.png
Binary files differ
diff --git a/tools/editor/icons/icon_edit_small.png b/editor/icons/icon_edit_small.png
index 19c83415f9..19c83415f9 100644
--- a/tools/editor/icons/icon_edit_small.png
+++ b/editor/icons/icon_edit_small.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_2d.png b/editor/icons/icon_editor_2d.png
index 1594f5adf0..1594f5adf0 100644
--- a/tools/editor/icons/icon_editor_2d.png
+++ b/editor/icons/icon_editor_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_3d_handle.png b/editor/icons/icon_editor_3d_handle.png
index 6935cc9bc4..6935cc9bc4 100644
--- a/tools/editor/icons/icon_editor_3d_handle.png
+++ b/editor/icons/icon_editor_3d_handle.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_focus.png b/editor/icons/icon_editor_focus.png
index 40ce11f381..40ce11f381 100644
--- a/tools/editor/icons/icon_editor_focus.png
+++ b/editor/icons/icon_editor_focus.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_handle.png b/editor/icons/icon_editor_handle.png
index 8950a216da..8950a216da 100644
--- a/tools/editor/icons/icon_editor_handle.png
+++ b/editor/icons/icon_editor_handle.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_node.png b/editor/icons/icon_editor_node.png
index aec161ed54..aec161ed54 100644
--- a/tools/editor/icons/icon_editor_node.png
+++ b/editor/icons/icon_editor_node.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_pivot.png b/editor/icons/icon_editor_pivot.png
index db7feb0be6..db7feb0be6 100644
--- a/tools/editor/icons/icon_editor_pivot.png
+++ b/editor/icons/icon_editor_pivot.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_plugin.png b/editor/icons/icon_editor_plugin.png
index ff7004b993..ff7004b993 100644
--- a/tools/editor/icons/icon_editor_plugin.png
+++ b/editor/icons/icon_editor_plugin.png
Binary files differ
diff --git a/tools/editor/icons/icon_editor_rect_2d.png b/editor/icons/icon_editor_rect_2d.png
index f59d493587..f59d493587 100644
--- a/tools/editor/icons/icon_editor_rect_2d.png
+++ b/editor/icons/icon_editor_rect_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_empty_control.png b/editor/icons/icon_empty_control.png
index b43bb14d39..b43bb14d39 100644
--- a/tools/editor/icons/icon_empty_control.png
+++ b/editor/icons/icon_empty_control.png
Binary files differ
diff --git a/tools/editor/icons/icon_enum.png b/editor/icons/icon_enum.png
index a98a33aedf..a98a33aedf 100644
--- a/tools/editor/icons/icon_enum.png
+++ b/editor/icons/icon_enum.png
Binary files differ
diff --git a/tools/editor/icons/icon_environment.png b/editor/icons/icon_environment.png
index c8c4da3e8f..c8c4da3e8f 100644
--- a/tools/editor/icons/icon_environment.png
+++ b/editor/icons/icon_environment.png
Binary files differ
diff --git a/tools/editor/icons/icon_error.png b/editor/icons/icon_error.png
index 7a9bed43aa..7a9bed43aa 100644
--- a/tools/editor/icons/icon_error.png
+++ b/editor/icons/icon_error.png
Binary files differ
diff --git a/tools/editor/icons/icon_error_sign.png b/editor/icons/icon_error_sign.png
index 1bfb1f345c..1bfb1f345c 100644
--- a/tools/editor/icons/icon_error_sign.png
+++ b/editor/icons/icon_error_sign.png
Binary files differ
diff --git a/tools/editor/icons/icon_event_player.png b/editor/icons/icon_event_player.png
index b5478ca74e..b5478ca74e 100644
--- a/tools/editor/icons/icon_event_player.png
+++ b/editor/icons/icon_event_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_expand.png b/editor/icons/icon_expand.png
index 8a604f945b..8a604f945b 100644
--- a/tools/editor/icons/icon_expand.png
+++ b/editor/icons/icon_expand.png
Binary files differ
diff --git a/tools/editor/icons/icon_expand_hl.png b/editor/icons/icon_expand_hl.png
index 6f51806db2..6f51806db2 100644
--- a/tools/editor/icons/icon_expand_hl.png
+++ b/editor/icons/icon_expand_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_favorites.png b/editor/icons/icon_favorites.png
index 14e05ad9b9..14e05ad9b9 100644
--- a/tools/editor/icons/icon_favorites.png
+++ b/editor/icons/icon_favorites.png
Binary files differ
diff --git a/tools/editor/icons/icon_file.png b/editor/icons/icon_file.png
index 69c6c90dc7..69c6c90dc7 100644
--- a/tools/editor/icons/icon_file.png
+++ b/editor/icons/icon_file.png
Binary files differ
diff --git a/tools/editor/icons/icon_file_big.png b/editor/icons/icon_file_big.png
index d429736b57..d429736b57 100644
--- a/tools/editor/icons/icon_file_big.png
+++ b/editor/icons/icon_file_big.png
Binary files differ
diff --git a/tools/editor/icons/icon_file_dialog.png b/editor/icons/icon_file_dialog.png
index 162827b2b0..162827b2b0 100644
--- a/tools/editor/icons/icon_file_dialog.png
+++ b/editor/icons/icon_file_dialog.png
Binary files differ
diff --git a/tools/editor/icons/icon_file_list.png b/editor/icons/icon_file_list.png
index a98a33aedf..a98a33aedf 100644
--- a/tools/editor/icons/icon_file_list.png
+++ b/editor/icons/icon_file_list.png
Binary files differ
diff --git a/tools/editor/icons/icon_file_server.png b/editor/icons/icon_file_server.png
index f5a18fc52d..f5a18fc52d 100644
--- a/tools/editor/icons/icon_file_server.png
+++ b/editor/icons/icon_file_server.png
Binary files differ
diff --git a/tools/editor/icons/icon_file_server_active.png b/editor/icons/icon_file_server_active.png
index af5fc0033a..af5fc0033a 100644
--- a/tools/editor/icons/icon_file_server_active.png
+++ b/editor/icons/icon_file_server_active.png
Binary files differ
diff --git a/tools/editor/icons/icon_file_thumbnail.png b/editor/icons/icon_file_thumbnail.png
index 6fb4b8f36f..6fb4b8f36f 100644
--- a/tools/editor/icons/icon_file_thumbnail.png
+++ b/editor/icons/icon_file_thumbnail.png
Binary files differ
diff --git a/tools/editor/icons/icon_filesystem.png b/editor/icons/icon_filesystem.png
index 5faff250d7..5faff250d7 100644
--- a/tools/editor/icons/icon_filesystem.png
+++ b/editor/icons/icon_filesystem.png
Binary files differ
diff --git a/tools/editor/icons/icon_fixed_material.png b/editor/icons/icon_fixed_material.png
index a9b0ebb568..a9b0ebb568 100644
--- a/tools/editor/icons/icon_fixed_material.png
+++ b/editor/icons/icon_fixed_material.png
Binary files differ
diff --git a/tools/editor/icons/icon_fixed_spatial_material.png b/editor/icons/icon_fixed_spatial_material.png
index f26ac3be37..f26ac3be37 100644
--- a/tools/editor/icons/icon_fixed_spatial_material.png
+++ b/editor/icons/icon_fixed_spatial_material.png
Binary files differ
diff --git a/tools/editor/icons/icon_fog_f_x.png b/editor/icons/icon_fog_f_x.png
index 54691aa9ab..54691aa9ab 100644
--- a/tools/editor/icons/icon_fog_f_x.png
+++ b/editor/icons/icon_fog_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_folder.png b/editor/icons/icon_folder.png
index cc05e98ebb..cc05e98ebb 100644
--- a/tools/editor/icons/icon_folder.png
+++ b/editor/icons/icon_folder.png
Binary files differ
diff --git a/tools/editor/icons/icon_folder_big.png b/editor/icons/icon_folder_big.png
index 05c41720d8..05c41720d8 100644
--- a/tools/editor/icons/icon_folder_big.png
+++ b/editor/icons/icon_folder_big.png
Binary files differ
diff --git a/tools/editor/icons/icon_folder_scene.png b/editor/icons/icon_folder_scene.png
index 6f6d706dae..6f6d706dae 100644
--- a/tools/editor/icons/icon_folder_scene.png
+++ b/editor/icons/icon_folder_scene.png
Binary files differ
diff --git a/tools/editor/icons/icon_font.png b/editor/icons/icon_font.png
index 543ee01ae4..543ee01ae4 100644
--- a/tools/editor/icons/icon_font.png
+++ b/editor/icons/icon_font.png
Binary files differ
diff --git a/tools/editor/icons/icon_forward.png b/editor/icons/icon_forward.png
index 412ffa89d3..412ffa89d3 100644
--- a/tools/editor/icons/icon_forward.png
+++ b/editor/icons/icon_forward.png
Binary files differ
diff --git a/tools/editor/icons/icon_forward_no.png b/editor/icons/icon_forward_no.png
index bf62cd6ab2..bf62cd6ab2 100644
--- a/tools/editor/icons/icon_forward_no.png
+++ b/editor/icons/icon_forward_no.png
Binary files differ
diff --git a/tools/editor/icons/icon_func.png b/editor/icons/icon_func.png
index 45b32def8a..45b32def8a 100644
--- a/tools/editor/icons/icon_func.png
+++ b/editor/icons/icon_func.png
Binary files differ
diff --git a/tools/editor/icons/icon_g_d_script.png b/editor/icons/icon_g_d_script.png
index 4db4c53796..4db4c53796 100644
--- a/tools/editor/icons/icon_g_d_script.png
+++ b/editor/icons/icon_g_d_script.png
Binary files differ
diff --git a/tools/editor/icons/icon_g_i_probe.png b/editor/icons/icon_g_i_probe.png
index a15ae18675..a15ae18675 100644
--- a/tools/editor/icons/icon_g_i_probe.png
+++ b/editor/icons/icon_g_i_probe.png
Binary files differ
diff --git a/tools/editor/icons/icon_g_i_probe_data.png b/editor/icons/icon_g_i_probe_data.png
index 0aabcc49cb..0aabcc49cb 100644
--- a/tools/editor/icons/icon_g_i_probe_data.png
+++ b/editor/icons/icon_g_i_probe_data.png
Binary files differ
diff --git a/tools/editor/icons/icon_gamma_f_x.png b/editor/icons/icon_gamma_f_x.png
index 50474340d1..50474340d1 100644
--- a/tools/editor/icons/icon_gamma_f_x.png
+++ b/editor/icons/icon_gamma_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_generic_6_d_o_f_joint.png b/editor/icons/icon_generic_6_d_o_f_joint.png
index 00ba76c098..00ba76c098 100644
--- a/tools/editor/icons/icon_generic_6_d_o_f_joint.png
+++ b/editor/icons/icon_generic_6_d_o_f_joint.png
Binary files differ
diff --git a/tools/editor/icons/icon_gizmo_directional_light.png b/editor/icons/icon_gizmo_directional_light.png
index bdeb120b43..bdeb120b43 100644
--- a/tools/editor/icons/icon_gizmo_directional_light.png
+++ b/editor/icons/icon_gizmo_directional_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_gizmo_light.png b/editor/icons/icon_gizmo_light.png
index be9903f8c2..be9903f8c2 100644
--- a/tools/editor/icons/icon_gizmo_light.png
+++ b/editor/icons/icon_gizmo_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_gizmo_listener.png b/editor/icons/icon_gizmo_listener.png
index 47e978be61..47e978be61 100644
--- a/tools/editor/icons/icon_gizmo_listener.png
+++ b/editor/icons/icon_gizmo_listener.png
Binary files differ
diff --git a/tools/editor/icons/icon_gizmo_spatial_sample_player.png b/editor/icons/icon_gizmo_spatial_sample_player.png
index 0119dbc433..0119dbc433 100644
--- a/tools/editor/icons/icon_gizmo_spatial_sample_player.png
+++ b/editor/icons/icon_gizmo_spatial_sample_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_gizmo_spatial_stream_player.png b/editor/icons/icon_gizmo_spatial_stream_player.png
index 6a4f85d550..6a4f85d550 100644
--- a/tools/editor/icons/icon_gizmo_spatial_stream_player.png
+++ b/editor/icons/icon_gizmo_spatial_stream_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_glow_f_x.png b/editor/icons/icon_glow_f_x.png
index c970204359..c970204359 100644
--- a/tools/editor/icons/icon_glow_f_x.png
+++ b/editor/icons/icon_glow_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_godot.png b/editor/icons/icon_godot.png
index 0b72e6ecc7..0b72e6ecc7 100644
--- a/tools/editor/icons/icon_godot.png
+++ b/editor/icons/icon_godot.png
Binary files differ
diff --git a/tools/editor/icons/icon_godot_asset_default.png b/editor/icons/icon_godot_asset_default.png
index 7478399e8b..7478399e8b 100644
--- a/tools/editor/icons/icon_godot_asset_default.png
+++ b/editor/icons/icon_godot_asset_default.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_color_ramp.png b/editor/icons/icon_graph_color_ramp.png
index 03d19a56bb..03d19a56bb 100644
--- a/tools/editor/icons/icon_graph_color_ramp.png
+++ b/editor/icons/icon_graph_color_ramp.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_comment.png b/editor/icons/icon_graph_comment.png
index 1686837d1d..1686837d1d 100644
--- a/tools/editor/icons/icon_graph_comment.png
+++ b/editor/icons/icon_graph_comment.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_cube_uniform.png b/editor/icons/icon_graph_cube_uniform.png
index 8b4ad57c31..8b4ad57c31 100644
--- a/tools/editor/icons/icon_graph_cube_uniform.png
+++ b/editor/icons/icon_graph_cube_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_curve_map.png b/editor/icons/icon_graph_curve_map.png
index ced27bd62f..ced27bd62f 100644
--- a/tools/editor/icons/icon_graph_curve_map.png
+++ b/editor/icons/icon_graph_curve_map.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_default_texture.png b/editor/icons/icon_graph_default_texture.png
index cad05e8332..cad05e8332 100644
--- a/tools/editor/icons/icon_graph_default_texture.png
+++ b/editor/icons/icon_graph_default_texture.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_edit.png b/editor/icons/icon_graph_edit.png
index f6226b2193..f6226b2193 100644
--- a/tools/editor/icons/icon_graph_edit.png
+++ b/editor/icons/icon_graph_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_input.png b/editor/icons/icon_graph_input.png
index 4725bcf7b1..4725bcf7b1 100644
--- a/tools/editor/icons/icon_graph_input.png
+++ b/editor/icons/icon_graph_input.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_node.png b/editor/icons/icon_graph_node.png
index fec38cb3eb..fec38cb3eb 100644
--- a/tools/editor/icons/icon_graph_node.png
+++ b/editor/icons/icon_graph_node.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_rgb.png b/editor/icons/icon_graph_rgb.png
index 3113a18e8c..3113a18e8c 100644
--- a/tools/editor/icons/icon_graph_rgb.png
+++ b/editor/icons/icon_graph_rgb.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_rgb_op.png b/editor/icons/icon_graph_rgb_op.png
index 09d633e722..09d633e722 100644
--- a/tools/editor/icons/icon_graph_rgb_op.png
+++ b/editor/icons/icon_graph_rgb_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_rgb_uniform.png b/editor/icons/icon_graph_rgb_uniform.png
index dbe10c9c8e..dbe10c9c8e 100644
--- a/tools/editor/icons/icon_graph_rgb_uniform.png
+++ b/editor/icons/icon_graph_rgb_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar.png b/editor/icons/icon_graph_scalar.png
index d44fd34891..d44fd34891 100644
--- a/tools/editor/icons/icon_graph_scalar.png
+++ b/editor/icons/icon_graph_scalar.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar_interp.png b/editor/icons/icon_graph_scalar_interp.png
index adcfc7d857..adcfc7d857 100644
--- a/tools/editor/icons/icon_graph_scalar_interp.png
+++ b/editor/icons/icon_graph_scalar_interp.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar_op.png b/editor/icons/icon_graph_scalar_op.png
index 6459cb9759..6459cb9759 100644
--- a/tools/editor/icons/icon_graph_scalar_op.png
+++ b/editor/icons/icon_graph_scalar_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalar_uniform.png b/editor/icons/icon_graph_scalar_uniform.png
index e7e0b9a73c..e7e0b9a73c 100644
--- a/tools/editor/icons/icon_graph_scalar_uniform.png
+++ b/editor/icons/icon_graph_scalar_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_scalars_to_vec.png b/editor/icons/icon_graph_scalars_to_vec.png
index 231a25a02a..231a25a02a 100644
--- a/tools/editor/icons/icon_graph_scalars_to_vec.png
+++ b/editor/icons/icon_graph_scalars_to_vec.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_texscreen.png b/editor/icons/icon_graph_texscreen.png
index 628990553a..628990553a 100644
--- a/tools/editor/icons/icon_graph_texscreen.png
+++ b/editor/icons/icon_graph_texscreen.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_texture_uniform.png b/editor/icons/icon_graph_texture_uniform.png
index 9c0c758dc1..9c0c758dc1 100644
--- a/tools/editor/icons/icon_graph_texture_uniform.png
+++ b/editor/icons/icon_graph_texture_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_time.png b/editor/icons/icon_graph_time.png
index 2a9b73dc2b..2a9b73dc2b 100644
--- a/tools/editor/icons/icon_graph_time.png
+++ b/editor/icons/icon_graph_time.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_dp.png b/editor/icons/icon_graph_vec_dp.png
index c395b61bb6..c395b61bb6 100644
--- a/tools/editor/icons/icon_graph_vec_dp.png
+++ b/editor/icons/icon_graph_vec_dp.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_interp.png b/editor/icons/icon_graph_vec_interp.png
index 00cfe6ed29..00cfe6ed29 100644
--- a/tools/editor/icons/icon_graph_vec_interp.png
+++ b/editor/icons/icon_graph_vec_interp.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_length.png b/editor/icons/icon_graph_vec_length.png
index af449109fd..af449109fd 100644
--- a/tools/editor/icons/icon_graph_vec_length.png
+++ b/editor/icons/icon_graph_vec_length.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_op.png b/editor/icons/icon_graph_vec_op.png
index c4e3cf409a..c4e3cf409a 100644
--- a/tools/editor/icons/icon_graph_vec_op.png
+++ b/editor/icons/icon_graph_vec_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_scalar_op.png b/editor/icons/icon_graph_vec_scalar_op.png
index f7fc3b054e..f7fc3b054e 100644
--- a/tools/editor/icons/icon_graph_vec_scalar_op.png
+++ b/editor/icons/icon_graph_vec_scalar_op.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vec_to_scalars.png b/editor/icons/icon_graph_vec_to_scalars.png
index 33f9fdf9bd..33f9fdf9bd 100644
--- a/tools/editor/icons/icon_graph_vec_to_scalars.png
+++ b/editor/icons/icon_graph_vec_to_scalars.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vecs_to_xform.png b/editor/icons/icon_graph_vecs_to_xform.png
index 82c32525dc..82c32525dc 100644
--- a/tools/editor/icons/icon_graph_vecs_to_xform.png
+++ b/editor/icons/icon_graph_vecs_to_xform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vector.png b/editor/icons/icon_graph_vector.png
index d78a3fdf5c..d78a3fdf5c 100644
--- a/tools/editor/icons/icon_graph_vector.png
+++ b/editor/icons/icon_graph_vector.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_vector_uniform.png b/editor/icons/icon_graph_vector_uniform.png
index a89166768b..a89166768b 100644
--- a/tools/editor/icons/icon_graph_vector_uniform.png
+++ b/editor/icons/icon_graph_vector_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform.png b/editor/icons/icon_graph_xform.png
index 142ec3eca5..142ec3eca5 100644
--- a/tools/editor/icons/icon_graph_xform.png
+++ b/editor/icons/icon_graph_xform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_mult.png b/editor/icons/icon_graph_xform_mult.png
index 94981d81af..94981d81af 100644
--- a/tools/editor/icons/icon_graph_xform_mult.png
+++ b/editor/icons/icon_graph_xform_mult.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_scalar_func.png b/editor/icons/icon_graph_xform_scalar_func.png
index d0edded8b0..d0edded8b0 100644
--- a/tools/editor/icons/icon_graph_xform_scalar_func.png
+++ b/editor/icons/icon_graph_xform_scalar_func.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_to_vecs.png b/editor/icons/icon_graph_xform_to_vecs.png
index 3d59c7957d..3d59c7957d 100644
--- a/tools/editor/icons/icon_graph_xform_to_vecs.png
+++ b/editor/icons/icon_graph_xform_to_vecs.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_uniform.png b/editor/icons/icon_graph_xform_uniform.png
index 36ed91e427..36ed91e427 100644
--- a/tools/editor/icons/icon_graph_xform_uniform.png
+++ b/editor/icons/icon_graph_xform_uniform.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_vec_func.png b/editor/icons/icon_graph_xform_vec_func.png
index 3866430f72..3866430f72 100644
--- a/tools/editor/icons/icon_graph_xform_vec_func.png
+++ b/editor/icons/icon_graph_xform_vec_func.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_vec_imult.png b/editor/icons/icon_graph_xform_vec_imult.png
index 07a7e214c2..07a7e214c2 100644
--- a/tools/editor/icons/icon_graph_xform_vec_imult.png
+++ b/editor/icons/icon_graph_xform_vec_imult.png
Binary files differ
diff --git a/tools/editor/icons/icon_graph_xform_vec_mult.png b/editor/icons/icon_graph_xform_vec_mult.png
index 8048e755c5..8048e755c5 100644
--- a/tools/editor/icons/icon_graph_xform_vec_mult.png
+++ b/editor/icons/icon_graph_xform_vec_mult.png
Binary files differ
diff --git a/tools/editor/icons/icon_grid.png b/editor/icons/icon_grid.png
index 1366205fe0..1366205fe0 100644
--- a/tools/editor/icons/icon_grid.png
+++ b/editor/icons/icon_grid.png
Binary files differ
diff --git a/tools/editor/icons/icon_grid_container.png b/editor/icons/icon_grid_container.png
index 027e992770..027e992770 100644
--- a/tools/editor/icons/icon_grid_container.png
+++ b/editor/icons/icon_grid_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_grid_map.png b/editor/icons/icon_grid_map.png
index 570b11d085..570b11d085 100644
--- a/tools/editor/icons/icon_grid_map.png
+++ b/editor/icons/icon_grid_map.png
Binary files differ
diff --git a/tools/editor/icons/icon_grid_map_floor.png b/editor/icons/icon_grid_map_floor.png
index a75871188b..a75871188b 100644
--- a/tools/editor/icons/icon_grid_map_floor.png
+++ b/editor/icons/icon_grid_map_floor.png
Binary files differ
diff --git a/tools/editor/icons/icon_groove_joint_2d.png b/editor/icons/icon_groove_joint_2d.png
index f65dc2b6b8..f65dc2b6b8 100644
--- a/tools/editor/icons/icon_groove_joint_2d.png
+++ b/editor/icons/icon_groove_joint_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_group.png b/editor/icons/icon_group.png
index 5ffc90455e..5ffc90455e 100644
--- a/tools/editor/icons/icon_group.png
+++ b/editor/icons/icon_group.png
Binary files differ
diff --git a/tools/editor/icons/icon_groups.png b/editor/icons/icon_groups.png
index 84a05560a9..84a05560a9 100644
--- a/tools/editor/icons/icon_groups.png
+++ b/editor/icons/icon_groups.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_box_container.png b/editor/icons/icon_h_box_container.png
index 36cef0a03c..36cef0a03c 100644
--- a/tools/editor/icons/icon_h_box_container.png
+++ b/editor/icons/icon_h_box_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_button_array.png b/editor/icons/icon_h_button_array.png
index baf3386801..baf3386801 100644
--- a/tools/editor/icons/icon_h_button_array.png
+++ b/editor/icons/icon_h_button_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_scroll_bar.png b/editor/icons/icon_h_scroll_bar.png
index e4576c4ae3..e4576c4ae3 100644
--- a/tools/editor/icons/icon_h_scroll_bar.png
+++ b/editor/icons/icon_h_scroll_bar.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_separator.png b/editor/icons/icon_h_separator.png
index 8ab1348c3b..8ab1348c3b 100644
--- a/tools/editor/icons/icon_h_separator.png
+++ b/editor/icons/icon_h_separator.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_slider.png b/editor/icons/icon_h_slider.png
index 87cf585e14..87cf585e14 100644
--- a/tools/editor/icons/icon_h_slider.png
+++ b/editor/icons/icon_h_slider.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_split_container.png b/editor/icons/icon_h_split_container.png
index 65ef8655dd..65ef8655dd 100644
--- a/tools/editor/icons/icon_h_split_container.png
+++ b/editor/icons/icon_h_split_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_t_t_p_request.png b/editor/icons/icon_h_t_t_p_request.png
index 60c6845b33..60c6845b33 100644
--- a/tools/editor/icons/icon_h_t_t_p_request.png
+++ b/editor/icons/icon_h_t_t_p_request.png
Binary files differ
diff --git a/tools/editor/icons/icon_headphones.png b/editor/icons/icon_headphones.png
index 83309d91d5..83309d91d5 100644
--- a/tools/editor/icons/icon_headphones.png
+++ b/editor/icons/icon_headphones.png
Binary files differ
diff --git a/tools/editor/icons/icon_help.png b/editor/icons/icon_help.png
index f05b512f4c..f05b512f4c 100644
--- a/tools/editor/icons/icon_help.png
+++ b/editor/icons/icon_help.png
Binary files differ
diff --git a/tools/editor/icons/icon_hidden.png b/editor/icons/icon_hidden.png
index ef3039f580..ef3039f580 100644
--- a/tools/editor/icons/icon_hidden.png
+++ b/editor/icons/icon_hidden.png
Binary files differ
diff --git a/tools/editor/icons/icon_hinge_joint.png b/editor/icons/icon_hinge_joint.png
index 246ca1ba42..246ca1ba42 100644
--- a/tools/editor/icons/icon_hinge_joint.png
+++ b/editor/icons/icon_hinge_joint.png
Binary files differ
diff --git a/tools/editor/icons/icon_history.png b/editor/icons/icon_history.png
index 4782918233..4782918233 100644
--- a/tools/editor/icons/icon_history.png
+++ b/editor/icons/icon_history.png
Binary files differ
diff --git a/tools/editor/icons/icon_hsize.png b/editor/icons/icon_hsize.png
index 7be48946b4..7be48946b4 100644
--- a/tools/editor/icons/icon_hsize.png
+++ b/editor/icons/icon_hsize.png
Binary files differ
diff --git a/tools/editor/icons/icon_iapi.png b/editor/icons/icon_iapi.png
index dc2639da83..dc2639da83 100644
--- a/tools/editor/icons/icon_iapi.png
+++ b/editor/icons/icon_iapi.png
Binary files differ
diff --git a/tools/editor/icons/icon_image.png b/editor/icons/icon_image.png
index ddfabace25..ddfabace25 100644
--- a/tools/editor/icons/icon_image.png
+++ b/editor/icons/icon_image.png
Binary files differ
diff --git a/tools/editor/icons/icon_image_sky_box.png b/editor/icons/icon_image_sky_box.png
index cf80258577..cf80258577 100644
--- a/tools/editor/icons/icon_image_sky_box.png
+++ b/editor/icons/icon_image_sky_box.png
Binary files differ
diff --git a/tools/editor/icons/icon_image_texture.png b/editor/icons/icon_image_texture.png
index 7c4493395e..7c4493395e 100644
--- a/tools/editor/icons/icon_image_texture.png
+++ b/editor/icons/icon_image_texture.png
Binary files differ
diff --git a/tools/editor/icons/icon_immediate_geometry.png b/editor/icons/icon_immediate_geometry.png
index 1ff9976921..1ff9976921 100644
--- a/tools/editor/icons/icon_immediate_geometry.png
+++ b/editor/icons/icon_immediate_geometry.png
Binary files differ
diff --git a/tools/editor/icons/icon_import_check.png b/editor/icons/icon_import_check.png
index e72a30603d..e72a30603d 100644
--- a/tools/editor/icons/icon_import_check.png
+++ b/editor/icons/icon_import_check.png
Binary files differ
diff --git a/tools/editor/icons/icon_import_fail.png b/editor/icons/icon_import_fail.png
index f7dd6fd79a..f7dd6fd79a 100644
--- a/tools/editor/icons/icon_import_fail.png
+++ b/editor/icons/icon_import_fail.png
Binary files differ
diff --git a/tools/editor/icons/icon_influence_zone.png b/editor/icons/icon_influence_zone.png
index 6d687735e9..6d687735e9 100644
--- a/tools/editor/icons/icon_influence_zone.png
+++ b/editor/icons/icon_influence_zone.png
Binary files differ
diff --git a/tools/editor/icons/icon_instance.png b/editor/icons/icon_instance.png
index 51859a0425..51859a0425 100644
--- a/tools/editor/icons/icon_instance.png
+++ b/editor/icons/icon_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_instance_options.png b/editor/icons/icon_instance_options.png
index ce6810ad27..ce6810ad27 100644
--- a/tools/editor/icons/icon_instance_options.png
+++ b/editor/icons/icon_instance_options.png
Binary files differ
diff --git a/tools/editor/icons/icon_integer.png b/editor/icons/icon_integer.png
index 583b9bda0b..583b9bda0b 100644
--- a/tools/editor/icons/icon_integer.png
+++ b/editor/icons/icon_integer.png
Binary files differ
diff --git a/tools/editor/icons/icon_interp_cubic.png b/editor/icons/icon_interp_cubic.png
index c723f7b648..c723f7b648 100644
--- a/tools/editor/icons/icon_interp_cubic.png
+++ b/editor/icons/icon_interp_cubic.png
Binary files differ
diff --git a/tools/editor/icons/icon_interp_linear.png b/editor/icons/icon_interp_linear.png
index 9d130b4507..9d130b4507 100644
--- a/tools/editor/icons/icon_interp_linear.png
+++ b/editor/icons/icon_interp_linear.png
Binary files differ
diff --git a/tools/editor/icons/icon_interp_raw.png b/editor/icons/icon_interp_raw.png
index 93ade1d674..93ade1d674 100644
--- a/tools/editor/icons/icon_interp_raw.png
+++ b/editor/icons/icon_interp_raw.png
Binary files differ
diff --git a/tools/editor/icons/icon_interp_wrap_clamp.png b/editor/icons/icon_interp_wrap_clamp.png
index 1024bd7d29..1024bd7d29 100644
--- a/tools/editor/icons/icon_interp_wrap_clamp.png
+++ b/editor/icons/icon_interp_wrap_clamp.png
Binary files differ
diff --git a/tools/editor/icons/icon_interp_wrap_loop.png b/editor/icons/icon_interp_wrap_loop.png
index 3a7ddacdb2..3a7ddacdb2 100644
--- a/tools/editor/icons/icon_interp_wrap_loop.png
+++ b/editor/icons/icon_interp_wrap_loop.png
Binary files differ
diff --git a/tools/editor/icons/icon_interpolated_camera.png b/editor/icons/icon_interpolated_camera.png
index c66724f513..c66724f513 100644
--- a/tools/editor/icons/icon_interpolated_camera.png
+++ b/editor/icons/icon_interpolated_camera.png
Binary files differ
diff --git a/tools/editor/icons/icon_invalid_key.png b/editor/icons/icon_invalid_key.png
index 8ebc6d6add..8ebc6d6add 100644
--- a/tools/editor/icons/icon_invalid_key.png
+++ b/editor/icons/icon_invalid_key.png
Binary files differ
diff --git a/tools/editor/icons/icon_inverse_kinematics.png b/editor/icons/icon_inverse_kinematics.png
index dd404765d3..dd404765d3 100644
--- a/tools/editor/icons/icon_inverse_kinematics.png
+++ b/editor/icons/icon_inverse_kinematics.png
Binary files differ
diff --git a/tools/editor/icons/icon_item_list.png b/editor/icons/icon_item_list.png
index 3f5245d520..3f5245d520 100644
--- a/tools/editor/icons/icon_item_list.png
+++ b/editor/icons/icon_item_list.png
Binary files differ
diff --git a/tools/editor/icons/icon_joy_axis.png b/editor/icons/icon_joy_axis.png
index 8b1affd052..8b1affd052 100644
--- a/tools/editor/icons/icon_joy_axis.png
+++ b/editor/icons/icon_joy_axis.png
Binary files differ
diff --git a/tools/editor/icons/icon_joy_button.png b/editor/icons/icon_joy_button.png
index 150102b209..150102b209 100644
--- a/tools/editor/icons/icon_joy_button.png
+++ b/editor/icons/icon_joy_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_joypad.png b/editor/icons/icon_joypad.png
index 5df471109a..5df471109a 100644
--- a/tools/editor/icons/icon_joypad.png
+++ b/editor/icons/icon_joypad.png
Binary files differ
diff --git a/tools/editor/icons/icon_key.png b/editor/icons/icon_key.png
index 564b474331..564b474331 100644
--- a/tools/editor/icons/icon_key.png
+++ b/editor/icons/icon_key.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_call.png b/editor/icons/icon_key_call.png
index 044662eb92..044662eb92 100644
--- a/tools/editor/icons/icon_key_call.png
+++ b/editor/icons/icon_key_call.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_hover.png b/editor/icons/icon_key_hover.png
index 7ab405bb07..7ab405bb07 100644
--- a/tools/editor/icons/icon_key_hover.png
+++ b/editor/icons/icon_key_hover.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_invalid.png b/editor/icons/icon_key_invalid.png
index 8ebc6d6add..8ebc6d6add 100644
--- a/tools/editor/icons/icon_key_invalid.png
+++ b/editor/icons/icon_key_invalid.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_invalid_hover.png b/editor/icons/icon_key_invalid_hover.png
index 6f0396d96a..6f0396d96a 100644
--- a/tools/editor/icons/icon_key_invalid_hover.png
+++ b/editor/icons/icon_key_invalid_hover.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_next.png b/editor/icons/icon_key_next.png
index 288161d245..288161d245 100644
--- a/tools/editor/icons/icon_key_next.png
+++ b/editor/icons/icon_key_next.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_selected.png b/editor/icons/icon_key_selected.png
index 1838dc95aa..1838dc95aa 100644
--- a/tools/editor/icons/icon_key_selected.png
+++ b/editor/icons/icon_key_selected.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_value.png b/editor/icons/icon_key_value.png
index 5c0b25a264..5c0b25a264 100644
--- a/tools/editor/icons/icon_key_value.png
+++ b/editor/icons/icon_key_value.png
Binary files differ
diff --git a/tools/editor/icons/icon_key_xform.png b/editor/icons/icon_key_xform.png
index 1171bd80db..1171bd80db 100644
--- a/tools/editor/icons/icon_key_xform.png
+++ b/editor/icons/icon_key_xform.png
Binary files differ
diff --git a/tools/editor/icons/icon_keyboard.png b/editor/icons/icon_keyboard.png
index a275345577..a275345577 100644
--- a/tools/editor/icons/icon_keyboard.png
+++ b/editor/icons/icon_keyboard.png
Binary files differ
diff --git a/tools/editor/icons/icon_keying.png b/editor/icons/icon_keying.png
index de790a4f09..de790a4f09 100644
--- a/tools/editor/icons/icon_keying.png
+++ b/editor/icons/icon_keying.png
Binary files differ
diff --git a/tools/editor/icons/icon_kinematic_body.png b/editor/icons/icon_kinematic_body.png
index 19a401dbf8..19a401dbf8 100644
--- a/tools/editor/icons/icon_kinematic_body.png
+++ b/editor/icons/icon_kinematic_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_kinematic_body_2d.png b/editor/icons/icon_kinematic_body_2d.png
index 2f9d834805..2f9d834805 100644
--- a/tools/editor/icons/icon_kinematic_body_2d.png
+++ b/editor/icons/icon_kinematic_body_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_label.png b/editor/icons/icon_label.png
index 16919a5fef..16919a5fef 100644
--- a/tools/editor/icons/icon_label.png
+++ b/editor/icons/icon_label.png
Binary files differ
diff --git a/tools/editor/icons/icon_large_texture.png b/editor/icons/icon_large_texture.png
index 1727e2409f..1727e2409f 100644
--- a/tools/editor/icons/icon_large_texture.png
+++ b/editor/icons/icon_large_texture.png
Binary files differ
diff --git a/tools/editor/icons/icon_light_2d.png b/editor/icons/icon_light_2d.png
index ebab16c1b1..ebab16c1b1 100644
--- a/tools/editor/icons/icon_light_2d.png
+++ b/editor/icons/icon_light_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_light_map.png b/editor/icons/icon_light_map.png
index e0333f06ea..e0333f06ea 100644
--- a/tools/editor/icons/icon_light_map.png
+++ b/editor/icons/icon_light_map.png
Binary files differ
diff --git a/tools/editor/icons/icon_light_occluder_2d.png b/editor/icons/icon_light_occluder_2d.png
index ceefbcbe2a..ceefbcbe2a 100644
--- a/tools/editor/icons/icon_light_occluder_2d.png
+++ b/editor/icons/icon_light_occluder_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_lightr.png b/editor/icons/icon_lightr.png
index 6de8c8de3f..6de8c8de3f 100644
--- a/tools/editor/icons/icon_lightr.png
+++ b/editor/icons/icon_lightr.png
Binary files differ
diff --git a/editor/icons/icon_line_2d.png b/editor/icons/icon_line_2d.png
new file mode 100644
index 0000000000..4ebf46af04
--- /dev/null
+++ b/editor/icons/icon_line_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_line_edit.png b/editor/icons/icon_line_edit.png
index 81b5efcf6c..81b5efcf6c 100644
--- a/tools/editor/icons/icon_line_edit.png
+++ b/editor/icons/icon_line_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_line_shape_2d.png b/editor/icons/icon_line_shape_2d.png
index e31722d69c..e31722d69c 100644
--- a/tools/editor/icons/icon_line_shape_2d.png
+++ b/editor/icons/icon_line_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_link_button.png b/editor/icons/icon_link_button.png
index 7febe3c19a..7febe3c19a 100644
--- a/tools/editor/icons/icon_link_button.png
+++ b/editor/icons/icon_link_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_list_select.png b/editor/icons/icon_list_select.png
index 9596d51e72..9596d51e72 100644
--- a/tools/editor/icons/icon_list_select.png
+++ b/editor/icons/icon_list_select.png
Binary files differ
diff --git a/tools/editor/icons/icon_listener.png b/editor/icons/icon_listener.png
index 3ce479e2fa..3ce479e2fa 100644
--- a/tools/editor/icons/icon_listener.png
+++ b/editor/icons/icon_listener.png
Binary files differ
diff --git a/tools/editor/icons/icon_live_debug.png b/editor/icons/icon_live_debug.png
index ad55646b9a..ad55646b9a 100644
--- a/tools/editor/icons/icon_live_debug.png
+++ b/editor/icons/icon_live_debug.png
Binary files differ
diff --git a/tools/editor/icons/icon_load.png b/editor/icons/icon_load.png
index 81835efa25..81835efa25 100644
--- a/tools/editor/icons/icon_load.png
+++ b/editor/icons/icon_load.png
Binary files differ
diff --git a/tools/editor/icons/icon_lock.png b/editor/icons/icon_lock.png
index a7059f5e7c..a7059f5e7c 100644
--- a/tools/editor/icons/icon_lock.png
+++ b/editor/icons/icon_lock.png
Binary files differ
diff --git a/tools/editor/icons/icon_logo.png b/editor/icons/icon_logo.png
index 9bbd7dc619..9bbd7dc619 100644
--- a/tools/editor/icons/icon_logo.png
+++ b/editor/icons/icon_logo.png
Binary files differ
diff --git a/tools/editor/icons/icon_logo_small.png b/editor/icons/icon_logo_small.png
index 9c7c7fe365..9c7c7fe365 100644
--- a/tools/editor/icons/icon_logo_small.png
+++ b/editor/icons/icon_logo_small.png
Binary files differ
diff --git a/tools/editor/icons/icon_loop.png b/editor/icons/icon_loop.png
index 91c3ad600e..91c3ad600e 100644
--- a/tools/editor/icons/icon_loop.png
+++ b/editor/icons/icon_loop.png
Binary files differ
diff --git a/tools/editor/icons/icon_loop_interpolation.png b/editor/icons/icon_loop_interpolation.png
index 488b33316e..488b33316e 100644
--- a/tools/editor/icons/icon_loop_interpolation.png
+++ b/editor/icons/icon_loop_interpolation.png
Binary files differ
diff --git a/tools/editor/icons/icon_main_play.png b/editor/icons/icon_main_play.png
index a72672f963..a72672f963 100644
--- a/tools/editor/icons/icon_main_play.png
+++ b/editor/icons/icon_main_play.png
Binary files differ
diff --git a/tools/editor/icons/icon_main_stop.png b/editor/icons/icon_main_stop.png
index 58387519dc..58387519dc 100644
--- a/tools/editor/icons/icon_main_stop.png
+++ b/editor/icons/icon_main_stop.png
Binary files differ
diff --git a/tools/editor/icons/icon_margin_container.png b/editor/icons/icon_margin_container.png
index 57f0cec42e..57f0cec42e 100644
--- a/tools/editor/icons/icon_margin_container.png
+++ b/editor/icons/icon_margin_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_cube.png b/editor/icons/icon_material_preview_cube.png
index f97c23b950..f97c23b950 100644
--- a/tools/editor/icons/icon_material_preview_cube.png
+++ b/editor/icons/icon_material_preview_cube.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_cube_off.png b/editor/icons/icon_material_preview_cube_off.png
index ad63218658..ad63218658 100644
--- a/tools/editor/icons/icon_material_preview_cube_off.png
+++ b/editor/icons/icon_material_preview_cube_off.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_light_1.png b/editor/icons/icon_material_preview_light_1.png
index 2a49a7530b..2a49a7530b 100644
--- a/tools/editor/icons/icon_material_preview_light_1.png
+++ b/editor/icons/icon_material_preview_light_1.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_light_1_off.png b/editor/icons/icon_material_preview_light_1_off.png
index 738dd75594..738dd75594 100644
--- a/tools/editor/icons/icon_material_preview_light_1_off.png
+++ b/editor/icons/icon_material_preview_light_1_off.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_light_2.png b/editor/icons/icon_material_preview_light_2.png
index 7e43b4425e..7e43b4425e 100644
--- a/tools/editor/icons/icon_material_preview_light_2.png
+++ b/editor/icons/icon_material_preview_light_2.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_light_2_off.png b/editor/icons/icon_material_preview_light_2_off.png
index e2f0e345a9..e2f0e345a9 100644
--- a/tools/editor/icons/icon_material_preview_light_2_off.png
+++ b/editor/icons/icon_material_preview_light_2_off.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_sphere.png b/editor/icons/icon_material_preview_sphere.png
index 80b06b39b7..80b06b39b7 100644
--- a/tools/editor/icons/icon_material_preview_sphere.png
+++ b/editor/icons/icon_material_preview_sphere.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_preview_sphere_off.png b/editor/icons/icon_material_preview_sphere_off.png
index a5acfcb8c9..a5acfcb8c9 100644
--- a/tools/editor/icons/icon_material_preview_sphere_off.png
+++ b/editor/icons/icon_material_preview_sphere_off.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_shader.png b/editor/icons/icon_material_shader.png
index 568a45d938..568a45d938 100644
--- a/tools/editor/icons/icon_material_shader.png
+++ b/editor/icons/icon_material_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_material_shader_graph.png b/editor/icons/icon_material_shader_graph.png
index f40e3755af..f40e3755af 100644
--- a/tools/editor/icons/icon_material_shader_graph.png
+++ b/editor/icons/icon_material_shader_graph.png
Binary files differ
diff --git a/tools/editor/icons/icon_matrix.png b/editor/icons/icon_matrix.png
index ba0772ff8a..ba0772ff8a 100644
--- a/tools/editor/icons/icon_matrix.png
+++ b/editor/icons/icon_matrix.png
Binary files differ
diff --git a/tools/editor/icons/icon_menu_button.png b/editor/icons/icon_menu_button.png
index 1fd2e41c23..1fd2e41c23 100644
--- a/tools/editor/icons/icon_menu_button.png
+++ b/editor/icons/icon_menu_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_mesh.png b/editor/icons/icon_mesh.png
index 03e1501403..03e1501403 100644
--- a/tools/editor/icons/icon_mesh.png
+++ b/editor/icons/icon_mesh.png
Binary files differ
diff --git a/tools/editor/icons/icon_mesh_instance.png b/editor/icons/icon_mesh_instance.png
index c513feb1cd..c513feb1cd 100644
--- a/tools/editor/icons/icon_mesh_instance.png
+++ b/editor/icons/icon_mesh_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_mesh_library.png b/editor/icons/icon_mesh_library.png
index 0bb37b1da3..0bb37b1da3 100644
--- a/tools/editor/icons/icon_mesh_library.png
+++ b/editor/icons/icon_mesh_library.png
Binary files differ
diff --git a/tools/editor/icons/icon_mesh_old.png b/editor/icons/icon_mesh_old.png
index 18531ff844..18531ff844 100644
--- a/tools/editor/icons/icon_mesh_old.png
+++ b/editor/icons/icon_mesh_old.png
Binary files differ
diff --git a/tools/editor/icons/icon_meshr.png b/editor/icons/icon_meshr.png
index 1ed2a123e6..1ed2a123e6 100644
--- a/tools/editor/icons/icon_meshr.png
+++ b/editor/icons/icon_meshr.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_aabb.png b/editor/icons/icon_mini_aabb.png
index eebc4633e4..eebc4633e4 100644
--- a/tools/editor/icons/icon_mini_aabb.png
+++ b/editor/icons/icon_mini_aabb.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_array.png b/editor/icons/icon_mini_array.png
index ade885e4d4..ade885e4d4 100644
--- a/tools/editor/icons/icon_mini_array.png
+++ b/editor/icons/icon_mini_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_boolean.png b/editor/icons/icon_mini_boolean.png
index 9cb64fc983..9cb64fc983 100644
--- a/tools/editor/icons/icon_mini_boolean.png
+++ b/editor/icons/icon_mini_boolean.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_color.png b/editor/icons/icon_mini_color.png
index bebf64e262..bebf64e262 100644
--- a/tools/editor/icons/icon_mini_color.png
+++ b/editor/icons/icon_mini_color.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_color_array.png b/editor/icons/icon_mini_color_array.png
index 434b2f96f5..434b2f96f5 100644
--- a/tools/editor/icons/icon_mini_color_array.png
+++ b/editor/icons/icon_mini_color_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_dictionary.png b/editor/icons/icon_mini_dictionary.png
index 11fd536a83..11fd536a83 100644
--- a/tools/editor/icons/icon_mini_dictionary.png
+++ b/editor/icons/icon_mini_dictionary.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_float.png b/editor/icons/icon_mini_float.png
index f8c8d9a174..f8c8d9a174 100644
--- a/tools/editor/icons/icon_mini_float.png
+++ b/editor/icons/icon_mini_float.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_float_array.png b/editor/icons/icon_mini_float_array.png
index 8b8177e151..8b8177e151 100644
--- a/tools/editor/icons/icon_mini_float_array.png
+++ b/editor/icons/icon_mini_float_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_image.png b/editor/icons/icon_mini_image.png
index 2ad359bdbe..2ad359bdbe 100644
--- a/tools/editor/icons/icon_mini_image.png
+++ b/editor/icons/icon_mini_image.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_input.png b/editor/icons/icon_mini_input.png
index fec26dd68e..fec26dd68e 100644
--- a/tools/editor/icons/icon_mini_input.png
+++ b/editor/icons/icon_mini_input.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_int_array.png b/editor/icons/icon_mini_int_array.png
index d1bd2e82a7..d1bd2e82a7 100644
--- a/tools/editor/icons/icon_mini_int_array.png
+++ b/editor/icons/icon_mini_int_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_integer.png b/editor/icons/icon_mini_integer.png
index dad1bb160b..dad1bb160b 100644
--- a/tools/editor/icons/icon_mini_integer.png
+++ b/editor/icons/icon_mini_integer.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_matrix3.png b/editor/icons/icon_mini_matrix3.png
index dd59d093cc..dd59d093cc 100644
--- a/tools/editor/icons/icon_mini_matrix3.png
+++ b/editor/icons/icon_mini_matrix3.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_matrix32.png b/editor/icons/icon_mini_matrix32.png
index 6018a00747..6018a00747 100644
--- a/tools/editor/icons/icon_mini_matrix32.png
+++ b/editor/icons/icon_mini_matrix32.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_object.png b/editor/icons/icon_mini_object.png
index 4afe7cfca1..4afe7cfca1 100644
--- a/tools/editor/icons/icon_mini_object.png
+++ b/editor/icons/icon_mini_object.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_path.png b/editor/icons/icon_mini_path.png
index 9eb0632571..9eb0632571 100644
--- a/tools/editor/icons/icon_mini_path.png
+++ b/editor/icons/icon_mini_path.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_plane.png b/editor/icons/icon_mini_plane.png
index 45676236bd..45676236bd 100644
--- a/tools/editor/icons/icon_mini_plane.png
+++ b/editor/icons/icon_mini_plane.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_quat.png b/editor/icons/icon_mini_quat.png
index 4ed2f5695c..4ed2f5695c 100644
--- a/tools/editor/icons/icon_mini_quat.png
+++ b/editor/icons/icon_mini_quat.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_raw_array.png b/editor/icons/icon_mini_raw_array.png
index 66bcf7c740..66bcf7c740 100644
--- a/tools/editor/icons/icon_mini_raw_array.png
+++ b/editor/icons/icon_mini_raw_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_rect2.png b/editor/icons/icon_mini_rect2.png
index db13e1a48e..db13e1a48e 100644
--- a/tools/editor/icons/icon_mini_rect2.png
+++ b/editor/icons/icon_mini_rect2.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_rid.png b/editor/icons/icon_mini_rid.png
index 278a9d1ee6..278a9d1ee6 100644
--- a/tools/editor/icons/icon_mini_rid.png
+++ b/editor/icons/icon_mini_rid.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_string.png b/editor/icons/icon_mini_string.png
index 504556dd74..504556dd74 100644
--- a/tools/editor/icons/icon_mini_string.png
+++ b/editor/icons/icon_mini_string.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_string_array.png b/editor/icons/icon_mini_string_array.png
index 5177014185..5177014185 100644
--- a/tools/editor/icons/icon_mini_string_array.png
+++ b/editor/icons/icon_mini_string_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_transform.png b/editor/icons/icon_mini_transform.png
index 068ea0506c..068ea0506c 100644
--- a/tools/editor/icons/icon_mini_transform.png
+++ b/editor/icons/icon_mini_transform.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_variant.png b/editor/icons/icon_mini_variant.png
index 285f0bcd16..285f0bcd16 100644
--- a/tools/editor/icons/icon_mini_variant.png
+++ b/editor/icons/icon_mini_variant.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_vector2.png b/editor/icons/icon_mini_vector2.png
index a7caa1797f..a7caa1797f 100644
--- a/tools/editor/icons/icon_mini_vector2.png
+++ b/editor/icons/icon_mini_vector2.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_vector2_array.png b/editor/icons/icon_mini_vector2_array.png
index de546de16c..de546de16c 100644
--- a/tools/editor/icons/icon_mini_vector2_array.png
+++ b/editor/icons/icon_mini_vector2_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_vector3.png b/editor/icons/icon_mini_vector3.png
index 69baeb229b..69baeb229b 100644
--- a/tools/editor/icons/icon_mini_vector3.png
+++ b/editor/icons/icon_mini_vector3.png
Binary files differ
diff --git a/tools/editor/icons/icon_mini_vector3_array.png b/editor/icons/icon_mini_vector3_array.png
index 6bddbaf627..6bddbaf627 100644
--- a/tools/editor/icons/icon_mini_vector3_array.png
+++ b/editor/icons/icon_mini_vector3_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_mirror_x.png b/editor/icons/icon_mirror_x.png
index 7be48946b4..7be48946b4 100644
--- a/tools/editor/icons/icon_mirror_x.png
+++ b/editor/icons/icon_mirror_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_mirror_y.png b/editor/icons/icon_mirror_y.png
index ba924f7ae7..ba924f7ae7 100644
--- a/tools/editor/icons/icon_mirror_y.png
+++ b/editor/icons/icon_mirror_y.png
Binary files differ
diff --git a/tools/editor/icons/icon_mouse.png b/editor/icons/icon_mouse.png
index ad07a403a6..ad07a403a6 100644
--- a/tools/editor/icons/icon_mouse.png
+++ b/editor/icons/icon_mouse.png
Binary files differ
diff --git a/tools/editor/icons/icon_move_down.png b/editor/icons/icon_move_down.png
index 3934310964..3934310964 100644
--- a/tools/editor/icons/icon_move_down.png
+++ b/editor/icons/icon_move_down.png
Binary files differ
diff --git a/tools/editor/icons/icon_move_down_hl.png b/editor/icons/icon_move_down_hl.png
index f9de58a940..f9de58a940 100644
--- a/tools/editor/icons/icon_move_down_hl.png
+++ b/editor/icons/icon_move_down_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_move_point.png b/editor/icons/icon_move_point.png
index 00e4ea32bd..00e4ea32bd 100644
--- a/tools/editor/icons/icon_move_point.png
+++ b/editor/icons/icon_move_point.png
Binary files differ
diff --git a/tools/editor/icons/icon_move_up.png b/editor/icons/icon_move_up.png
index 684013dc40..684013dc40 100644
--- a/tools/editor/icons/icon_move_up.png
+++ b/editor/icons/icon_move_up.png
Binary files differ
diff --git a/tools/editor/icons/icon_move_up_hl.png b/editor/icons/icon_move_up_hl.png
index e076c9a265..e076c9a265 100644
--- a/tools/editor/icons/icon_move_up_hl.png
+++ b/editor/icons/icon_move_up_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_multi_edit.png b/editor/icons/icon_multi_edit.png
index 0256ae094a..0256ae094a 100644
--- a/tools/editor/icons/icon_multi_edit.png
+++ b/editor/icons/icon_multi_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_multi_line.png b/editor/icons/icon_multi_line.png
index 95a029cc6e..95a029cc6e 100644
--- a/tools/editor/icons/icon_multi_line.png
+++ b/editor/icons/icon_multi_line.png
Binary files differ
diff --git a/tools/editor/icons/icon_multi_mesh.png b/editor/icons/icon_multi_mesh.png
index 6ff9d22266..6ff9d22266 100644
--- a/tools/editor/icons/icon_multi_mesh.png
+++ b/editor/icons/icon_multi_mesh.png
Binary files differ
diff --git a/tools/editor/icons/icon_multi_mesh_instance.png b/editor/icons/icon_multi_mesh_instance.png
index 124bf81b5a..124bf81b5a 100644
--- a/tools/editor/icons/icon_multi_mesh_instance.png
+++ b/editor/icons/icon_multi_mesh_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_multi_node_edit.png b/editor/icons/icon_multi_node_edit.png
index 0256ae094a..0256ae094a 100644
--- a/tools/editor/icons/icon_multi_node_edit.png
+++ b/editor/icons/icon_multi_node_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation.png b/editor/icons/icon_navigation.png
index 3c5a3bdc4a..3c5a3bdc4a 100644
--- a/tools/editor/icons/icon_navigation.png
+++ b/editor/icons/icon_navigation.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation_2d.png b/editor/icons/icon_navigation_2d.png
index a6ea55ef13..a6ea55ef13 100644
--- a/tools/editor/icons/icon_navigation_2d.png
+++ b/editor/icons/icon_navigation_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation_mesh.png b/editor/icons/icon_navigation_mesh.png
index e3bb7f775f..e3bb7f775f 100644
--- a/tools/editor/icons/icon_navigation_mesh.png
+++ b/editor/icons/icon_navigation_mesh.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation_mesh_instance.png b/editor/icons/icon_navigation_mesh_instance.png
index f5f25ef421..f5f25ef421 100644
--- a/tools/editor/icons/icon_navigation_mesh_instance.png
+++ b/editor/icons/icon_navigation_mesh_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation_polygon.png b/editor/icons/icon_navigation_polygon.png
index bfc4bfb542..bfc4bfb542 100644
--- a/tools/editor/icons/icon_navigation_polygon.png
+++ b/editor/icons/icon_navigation_polygon.png
Binary files differ
diff --git a/tools/editor/icons/icon_navigation_polygon_instance.png b/editor/icons/icon_navigation_polygon_instance.png
index 89d420ca14..89d420ca14 100644
--- a/tools/editor/icons/icon_navigation_polygon_instance.png
+++ b/editor/icons/icon_navigation_polygon_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_new.png b/editor/icons/icon_new.png
index 69c6c90dc7..69c6c90dc7 100644
--- a/tools/editor/icons/icon_new.png
+++ b/editor/icons/icon_new.png
Binary files differ
diff --git a/tools/editor/icons/icon_nine_patch_rect.png b/editor/icons/icon_nine_patch_rect.png
index bdd1467144..bdd1467144 100644
--- a/tools/editor/icons/icon_nine_patch_rect.png
+++ b/editor/icons/icon_nine_patch_rect.png
Binary files differ
diff --git a/tools/editor/icons/icon_node.png b/editor/icons/icon_node.png
index 628b632332..628b632332 100644
--- a/tools/editor/icons/icon_node.png
+++ b/editor/icons/icon_node.png
Binary files differ
diff --git a/tools/editor/icons/icon_node_2d.png b/editor/icons/icon_node_2d.png
index d6c8f1f988..d6c8f1f988 100644
--- a/tools/editor/icons/icon_node_2d.png
+++ b/editor/icons/icon_node_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_node_real_slot.png b/editor/icons/icon_node_real_slot.png
index 6373bc0fa5..6373bc0fa5 100644
--- a/tools/editor/icons/icon_node_real_slot.png
+++ b/editor/icons/icon_node_real_slot.png
Binary files differ
diff --git a/tools/editor/icons/icon_node_vec_slot.png b/editor/icons/icon_node_vec_slot.png
index aedd983fb4..aedd983fb4 100644
--- a/tools/editor/icons/icon_node_vec_slot.png
+++ b/editor/icons/icon_node_vec_slot.png
Binary files differ
diff --git a/tools/editor/icons/icon_node_warning.png b/editor/icons/icon_node_warning.png
index 8b1e9212a8..8b1e9212a8 100644
--- a/tools/editor/icons/icon_node_warning.png
+++ b/editor/icons/icon_node_warning.png
Binary files differ
diff --git a/tools/editor/icons/icon_non_favorite.png b/editor/icons/icon_non_favorite.png
index 92351bde04..92351bde04 100644
--- a/tools/editor/icons/icon_non_favorite.png
+++ b/editor/icons/icon_non_favorite.png
Binary files differ
diff --git a/tools/editor/icons/icon_object.png b/editor/icons/icon_object.png
index f4f018c863..f4f018c863 100644
--- a/tools/editor/icons/icon_object.png
+++ b/editor/icons/icon_object.png
Binary files differ
diff --git a/tools/editor/icons/icon_occluder_polygon_2d.png b/editor/icons/icon_occluder_polygon_2d.png
index bbfc9ac0a5..bbfc9ac0a5 100644
--- a/tools/editor/icons/icon_occluder_polygon_2d.png
+++ b/editor/icons/icon_occluder_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_omni_light.png b/editor/icons/icon_omni_light.png
index 286ce723a4..286ce723a4 100644
--- a/tools/editor/icons/icon_omni_light.png
+++ b/editor/icons/icon_omni_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_open.png b/editor/icons/icon_open.png
index cc05e98ebb..cc05e98ebb 100644
--- a/tools/editor/icons/icon_open.png
+++ b/editor/icons/icon_open.png
Binary files differ
diff --git a/tools/editor/icons/icon_option_button.png b/editor/icons/icon_option_button.png
index c1155309aa..c1155309aa 100644
--- a/tools/editor/icons/icon_option_button.png
+++ b/editor/icons/icon_option_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_override.png b/editor/icons/icon_override.png
index 9d917ede75..9d917ede75 100644
--- a/tools/editor/icons/icon_override.png
+++ b/editor/icons/icon_override.png
Binary files differ
diff --git a/tools/editor/icons/icon_p_hash_translation.png b/editor/icons/icon_p_hash_translation.png
index abca359eea..abca359eea 100644
--- a/tools/editor/icons/icon_p_hash_translation.png
+++ b/editor/icons/icon_p_hash_translation.png
Binary files differ
diff --git a/tools/editor/icons/icon_packed_data_container.png b/editor/icons/icon_packed_data_container.png
index af89da48a9..af89da48a9 100644
--- a/tools/editor/icons/icon_packed_data_container.png
+++ b/editor/icons/icon_packed_data_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_packed_scene.png b/editor/icons/icon_packed_scene.png
index 9079762932..9079762932 100644
--- a/tools/editor/icons/icon_packed_scene.png
+++ b/editor/icons/icon_packed_scene.png
Binary files differ
diff --git a/tools/editor/icons/icon_pane_drag.png b/editor/icons/icon_pane_drag.png
index 57f8e49ba3..57f8e49ba3 100644
--- a/tools/editor/icons/icon_pane_drag.png
+++ b/editor/icons/icon_pane_drag.png
Binary files differ
diff --git a/tools/editor/icons/icon_pane_drag_hover.png b/editor/icons/icon_pane_drag_hover.png
index 068253ecef..068253ecef 100644
--- a/tools/editor/icons/icon_pane_drag_hover.png
+++ b/editor/icons/icon_pane_drag_hover.png
Binary files differ
diff --git a/tools/editor/icons/icon_panel.png b/editor/icons/icon_panel.png
index dca2da94f3..dca2da94f3 100644
--- a/tools/editor/icons/icon_panel.png
+++ b/editor/icons/icon_panel.png
Binary files differ
diff --git a/tools/editor/icons/icon_panel_container.png b/editor/icons/icon_panel_container.png
index 05bd1e082f..05bd1e082f 100644
--- a/tools/editor/icons/icon_panel_container.png
+++ b/editor/icons/icon_panel_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_panel_top.png b/editor/icons/icon_panel_top.png
index 20e67fad1a..20e67fad1a 100644
--- a/tools/editor/icons/icon_panel_top.png
+++ b/editor/icons/icon_panel_top.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_1.png b/editor/icons/icon_panels_1.png
index a909e6aee8..a909e6aee8 100644
--- a/tools/editor/icons/icon_panels_1.png
+++ b/editor/icons/icon_panels_1.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_2.png b/editor/icons/icon_panels_2.png
index 28a1ca2a59..28a1ca2a59 100644
--- a/tools/editor/icons/icon_panels_2.png
+++ b/editor/icons/icon_panels_2.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_2_alt.png b/editor/icons/icon_panels_2_alt.png
index 14f21304c5..14f21304c5 100644
--- a/tools/editor/icons/icon_panels_2_alt.png
+++ b/editor/icons/icon_panels_2_alt.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_3.png b/editor/icons/icon_panels_3.png
index 76f1f53636..76f1f53636 100644
--- a/tools/editor/icons/icon_panels_3.png
+++ b/editor/icons/icon_panels_3.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_3_alt.png b/editor/icons/icon_panels_3_alt.png
index b121bc62c3..b121bc62c3 100644
--- a/tools/editor/icons/icon_panels_3_alt.png
+++ b/editor/icons/icon_panels_3_alt.png
Binary files differ
diff --git a/tools/editor/icons/icon_panels_4.png b/editor/icons/icon_panels_4.png
index 19a3bc0bf2..19a3bc0bf2 100644
--- a/tools/editor/icons/icon_panels_4.png
+++ b/editor/icons/icon_panels_4.png
Binary files differ
diff --git a/tools/editor/icons/icon_parallax_background.png b/editor/icons/icon_parallax_background.png
index 78d7484e8b..78d7484e8b 100644
--- a/tools/editor/icons/icon_parallax_background.png
+++ b/editor/icons/icon_parallax_background.png
Binary files differ
diff --git a/tools/editor/icons/icon_parallax_layer.png b/editor/icons/icon_parallax_layer.png
index 748c9164bb..748c9164bb 100644
--- a/tools/editor/icons/icon_parallax_layer.png
+++ b/editor/icons/icon_parallax_layer.png
Binary files differ
diff --git a/tools/editor/icons/icon_particle_attractor_2d.png b/editor/icons/icon_particle_attractor_2d.png
index 84be7dff3b..84be7dff3b 100644
--- a/tools/editor/icons/icon_particle_attractor_2d.png
+++ b/editor/icons/icon_particle_attractor_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_particles.png b/editor/icons/icon_particles.png
index 8d146b2946..8d146b2946 100644
--- a/tools/editor/icons/icon_particles.png
+++ b/editor/icons/icon_particles.png
Binary files differ
diff --git a/tools/editor/icons/icon_particles_2d.png b/editor/icons/icon_particles_2d.png
index e03ff1e189..e03ff1e189 100644
--- a/tools/editor/icons/icon_particles_2d.png
+++ b/editor/icons/icon_particles_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_particles_frame.png b/editor/icons/icon_particles_frame.png
index 968bbccf8a..968bbccf8a 100644
--- a/tools/editor/icons/icon_particles_frame.png
+++ b/editor/icons/icon_particles_frame.png
Binary files differ
diff --git a/tools/editor/icons/icon_particles_shader.png b/editor/icons/icon_particles_shader.png
index 3b5c5644b2..3b5c5644b2 100644
--- a/tools/editor/icons/icon_particles_shader.png
+++ b/editor/icons/icon_particles_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_patch_9_rect.png b/editor/icons/icon_patch_9_rect.png
index bdd1467144..bdd1467144 100644
--- a/tools/editor/icons/icon_patch_9_rect.png
+++ b/editor/icons/icon_patch_9_rect.png
Binary files differ
diff --git a/tools/editor/icons/icon_path.png b/editor/icons/icon_path.png
index 4ebdcbdc44..4ebdcbdc44 100644
--- a/tools/editor/icons/icon_path.png
+++ b/editor/icons/icon_path.png
Binary files differ
diff --git a/tools/editor/icons/icon_path_2d.png b/editor/icons/icon_path_2d.png
index c5b0d5d7c6..c5b0d5d7c6 100644
--- a/tools/editor/icons/icon_path_2d.png
+++ b/editor/icons/icon_path_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_path_follow.png b/editor/icons/icon_path_follow.png
index f71651d241..f71651d241 100644
--- a/tools/editor/icons/icon_path_follow.png
+++ b/editor/icons/icon_path_follow.png
Binary files differ
diff --git a/tools/editor/icons/icon_path_follow_2d.png b/editor/icons/icon_path_follow_2d.png
index d82e682dba..d82e682dba 100644
--- a/tools/editor/icons/icon_path_follow_2d.png
+++ b/editor/icons/icon_path_follow_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_pause.png b/editor/icons/icon_pause.png
index aec11d5c35..aec11d5c35 100644
--- a/tools/editor/icons/icon_pause.png
+++ b/editor/icons/icon_pause.png
Binary files differ
diff --git a/tools/editor/icons/icon_pe_edit.png b/editor/icons/icon_pe_edit.png
index 7082303a4e..7082303a4e 100644
--- a/tools/editor/icons/icon_pe_edit.png
+++ b/editor/icons/icon_pe_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_physics_joint_pin.png b/editor/icons/icon_physics_joint_pin.png
index 27ac67ed0a..27ac67ed0a 100644
--- a/tools/editor/icons/icon_physics_joint_pin.png
+++ b/editor/icons/icon_physics_joint_pin.png
Binary files differ
diff --git a/tools/editor/icons/icon_pin.png b/editor/icons/icon_pin.png
index cf89679f88..cf89679f88 100644
--- a/tools/editor/icons/icon_pin.png
+++ b/editor/icons/icon_pin.png
Binary files differ
diff --git a/tools/editor/icons/icon_pin_joint.png b/editor/icons/icon_pin_joint.png
index 78e8a83724..78e8a83724 100644
--- a/tools/editor/icons/icon_pin_joint.png
+++ b/editor/icons/icon_pin_joint.png
Binary files differ
diff --git a/tools/editor/icons/icon_pin_joint_2d.png b/editor/icons/icon_pin_joint_2d.png
index 355d5a2022..355d5a2022 100644
--- a/tools/editor/icons/icon_pin_joint_2d.png
+++ b/editor/icons/icon_pin_joint_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_pin_pressed.png b/editor/icons/icon_pin_pressed.png
index cf89679f88..cf89679f88 100644
--- a/tools/editor/icons/icon_pin_pressed.png
+++ b/editor/icons/icon_pin_pressed.png
Binary files differ
diff --git a/tools/editor/icons/icon_plane.png b/editor/icons/icon_plane.png
index 25d869f31e..25d869f31e 100644
--- a/tools/editor/icons/icon_plane.png
+++ b/editor/icons/icon_plane.png
Binary files differ
diff --git a/tools/editor/icons/icon_plane_shape.png b/editor/icons/icon_plane_shape.png
index e7ebe1fbcd..e7ebe1fbcd 100644
--- a/tools/editor/icons/icon_plane_shape.png
+++ b/editor/icons/icon_plane_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_play.png b/editor/icons/icon_play.png
index 864e4e4fb9..864e4e4fb9 100644
--- a/tools/editor/icons/icon_play.png
+++ b/editor/icons/icon_play.png
Binary files differ
diff --git a/tools/editor/icons/icon_play_backwards.png b/editor/icons/icon_play_backwards.png
index bab2858373..bab2858373 100644
--- a/tools/editor/icons/icon_play_backwards.png
+++ b/editor/icons/icon_play_backwards.png
Binary files differ
diff --git a/tools/editor/icons/icon_play_custom.png b/editor/icons/icon_play_custom.png
index b742e131ca..b742e131ca 100644
--- a/tools/editor/icons/icon_play_custom.png
+++ b/editor/icons/icon_play_custom.png
Binary files differ
diff --git a/tools/editor/icons/icon_play_scene.png b/editor/icons/icon_play_scene.png
index ebba318799..ebba318799 100644
--- a/tools/editor/icons/icon_play_scene.png
+++ b/editor/icons/icon_play_scene.png
Binary files differ
diff --git a/tools/editor/icons/icon_play_start.png b/editor/icons/icon_play_start.png
index dacc156614..dacc156614 100644
--- a/tools/editor/icons/icon_play_start.png
+++ b/editor/icons/icon_play_start.png
Binary files differ
diff --git a/tools/editor/icons/icon_play_start_backwards.png b/editor/icons/icon_play_start_backwards.png
index 7608e18cba..7608e18cba 100644
--- a/tools/editor/icons/icon_play_start_backwards.png
+++ b/editor/icons/icon_play_start_backwards.png
Binary files differ
diff --git a/tools/editor/icons/icon_polygon_2d.png b/editor/icons/icon_polygon_2d.png
index b372749cb0..b372749cb0 100644
--- a/tools/editor/icons/icon_polygon_2d.png
+++ b/editor/icons/icon_polygon_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_polygon_path_finder.png b/editor/icons/icon_polygon_path_finder.png
index 9d76d872db..9d76d872db 100644
--- a/tools/editor/icons/icon_polygon_path_finder.png
+++ b/editor/icons/icon_polygon_path_finder.png
Binary files differ
diff --git a/tools/editor/icons/icon_popup.png b/editor/icons/icon_popup.png
index 4dda9e50f9..4dda9e50f9 100644
--- a/tools/editor/icons/icon_popup.png
+++ b/editor/icons/icon_popup.png
Binary files differ
diff --git a/tools/editor/icons/icon_popup_dialog.png b/editor/icons/icon_popup_dialog.png
index 82b011e06c..82b011e06c 100644
--- a/tools/editor/icons/icon_popup_dialog.png
+++ b/editor/icons/icon_popup_dialog.png
Binary files differ
diff --git a/tools/editor/icons/icon_popup_menu.png b/editor/icons/icon_popup_menu.png
index 28d928a98e..28d928a98e 100644
--- a/tools/editor/icons/icon_popup_menu.png
+++ b/editor/icons/icon_popup_menu.png
Binary files differ
diff --git a/tools/editor/icons/icon_popup_panel.png b/editor/icons/icon_popup_panel.png
index 90c86c2c05..90c86c2c05 100644
--- a/tools/editor/icons/icon_popup_panel.png
+++ b/editor/icons/icon_popup_panel.png
Binary files differ
diff --git a/tools/editor/icons/icon_portal.png b/editor/icons/icon_portal.png
index b10aee650d..b10aee650d 100644
--- a/tools/editor/icons/icon_portal.png
+++ b/editor/icons/icon_portal.png
Binary files differ
diff --git a/tools/editor/icons/icon_position_2d.png b/editor/icons/icon_position_2d.png
index da7446e3e2..da7446e3e2 100644
--- a/tools/editor/icons/icon_position_2d.png
+++ b/editor/icons/icon_position_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_position_3d.png b/editor/icons/icon_position_3d.png
index a36bca3260..a36bca3260 100644
--- a/tools/editor/icons/icon_position_3d.png
+++ b/editor/icons/icon_position_3d.png
Binary files differ
diff --git a/tools/editor/icons/icon_prev_scene.png b/editor/icons/icon_prev_scene.png
index 9d8dda5180..9d8dda5180 100644
--- a/tools/editor/icons/icon_prev_scene.png
+++ b/editor/icons/icon_prev_scene.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_1.png b/editor/icons/icon_progress_1.png
index 34196ec2dd..34196ec2dd 100644
--- a/tools/editor/icons/icon_progress_1.png
+++ b/editor/icons/icon_progress_1.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_2.png b/editor/icons/icon_progress_2.png
index 6f683f2473..6f683f2473 100644
--- a/tools/editor/icons/icon_progress_2.png
+++ b/editor/icons/icon_progress_2.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_3.png b/editor/icons/icon_progress_3.png
index 82202d28a6..82202d28a6 100644
--- a/tools/editor/icons/icon_progress_3.png
+++ b/editor/icons/icon_progress_3.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_4.png b/editor/icons/icon_progress_4.png
index 70198ab26a..70198ab26a 100644
--- a/tools/editor/icons/icon_progress_4.png
+++ b/editor/icons/icon_progress_4.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_5.png b/editor/icons/icon_progress_5.png
index b5f4bdcdec..b5f4bdcdec 100644
--- a/tools/editor/icons/icon_progress_5.png
+++ b/editor/icons/icon_progress_5.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_6.png b/editor/icons/icon_progress_6.png
index df8f27c60d..df8f27c60d 100644
--- a/tools/editor/icons/icon_progress_6.png
+++ b/editor/icons/icon_progress_6.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_7.png b/editor/icons/icon_progress_7.png
index 892d5b53ba..892d5b53ba 100644
--- a/tools/editor/icons/icon_progress_7.png
+++ b/editor/icons/icon_progress_7.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_8.png b/editor/icons/icon_progress_8.png
index c593afb7dd..c593afb7dd 100644
--- a/tools/editor/icons/icon_progress_8.png
+++ b/editor/icons/icon_progress_8.png
Binary files differ
diff --git a/tools/editor/icons/icon_progress_bar.png b/editor/icons/icon_progress_bar.png
index 30822dd7a8..30822dd7a8 100644
--- a/tools/editor/icons/icon_progress_bar.png
+++ b/editor/icons/icon_progress_bar.png
Binary files differ
diff --git a/tools/editor/icons/icon_property_editor.png b/editor/icons/icon_property_editor.png
index 5ee0ab8068..5ee0ab8068 100644
--- a/tools/editor/icons/icon_property_editor.png
+++ b/editor/icons/icon_property_editor.png
Binary files differ
diff --git a/tools/editor/icons/icon_proximity_group.png b/editor/icons/icon_proximity_group.png
index 230ca752ec..230ca752ec 100644
--- a/tools/editor/icons/icon_proximity_group.png
+++ b/editor/icons/icon_proximity_group.png
Binary files differ
diff --git a/tools/editor/icons/icon_quad.png b/editor/icons/icon_quad.png
index a1b31b026b..a1b31b026b 100644
--- a/tools/editor/icons/icon_quad.png
+++ b/editor/icons/icon_quad.png
Binary files differ
diff --git a/tools/editor/icons/icon_quat.png b/editor/icons/icon_quat.png
index 0fcaa35b56..0fcaa35b56 100644
--- a/tools/editor/icons/icon_quat.png
+++ b/editor/icons/icon_quat.png
Binary files differ
diff --git a/tools/editor/icons/icon_range.png b/editor/icons/icon_range.png
index 6e46df9690..6e46df9690 100644
--- a/tools/editor/icons/icon_range.png
+++ b/editor/icons/icon_range.png
Binary files differ
diff --git a/tools/editor/icons/icon_rating_no_star.png b/editor/icons/icon_rating_no_star.png
index e7421bdb13..e7421bdb13 100644
--- a/tools/editor/icons/icon_rating_no_star.png
+++ b/editor/icons/icon_rating_no_star.png
Binary files differ
diff --git a/tools/editor/icons/icon_rating_star.png b/editor/icons/icon_rating_star.png
index b2a7e01322..b2a7e01322 100644
--- a/tools/editor/icons/icon_rating_star.png
+++ b/editor/icons/icon_rating_star.png
Binary files differ
diff --git a/tools/editor/icons/icon_ray_cast.png b/editor/icons/icon_ray_cast.png
index 19cba12d1d..19cba12d1d 100644
--- a/tools/editor/icons/icon_ray_cast.png
+++ b/editor/icons/icon_ray_cast.png
Binary files differ
diff --git a/tools/editor/icons/icon_ray_cast_2d.png b/editor/icons/icon_ray_cast_2d.png
index 2a5054ab00..2a5054ab00 100644
--- a/tools/editor/icons/icon_ray_cast_2d.png
+++ b/editor/icons/icon_ray_cast_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_ray_shape.png b/editor/icons/icon_ray_shape.png
index a3188d1a3a..a3188d1a3a 100644
--- a/tools/editor/icons/icon_ray_shape.png
+++ b/editor/icons/icon_ray_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_ray_shape_2d.png b/editor/icons/icon_ray_shape_2d.png
index c91a63570d..c91a63570d 100644
--- a/tools/editor/icons/icon_ray_shape_2d.png
+++ b/editor/icons/icon_ray_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_rayito.png b/editor/icons/icon_rayito.png
index 1afb5975d1..1afb5975d1 100644
--- a/tools/editor/icons/icon_rayito.png
+++ b/editor/icons/icon_rayito.png
Binary files differ
diff --git a/tools/editor/icons/icon_real.png b/editor/icons/icon_real.png
index 555b61427f..555b61427f 100644
--- a/tools/editor/icons/icon_real.png
+++ b/editor/icons/icon_real.png
Binary files differ
diff --git a/tools/editor/icons/icon_rect2.png b/editor/icons/icon_rect2.png
index cf3cfe3b22..cf3cfe3b22 100644
--- a/tools/editor/icons/icon_rect2.png
+++ b/editor/icons/icon_rect2.png
Binary files differ
diff --git a/tools/editor/icons/icon_rect3.png b/editor/icons/icon_rect3.png
index 8eacfff207..8eacfff207 100644
--- a/tools/editor/icons/icon_rect3.png
+++ b/editor/icons/icon_rect3.png
Binary files differ
diff --git a/tools/editor/icons/icon_rectangle_shape_2d.png b/editor/icons/icon_rectangle_shape_2d.png
index 002730b942..002730b942 100644
--- a/tools/editor/icons/icon_rectangle_shape_2d.png
+++ b/editor/icons/icon_rectangle_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_reference_rect.png b/editor/icons/icon_reference_rect.png
index b253af477f..b253af477f 100644
--- a/tools/editor/icons/icon_reference_rect.png
+++ b/editor/icons/icon_reference_rect.png
Binary files differ
diff --git a/tools/editor/icons/icon_reflection_probe.png b/editor/icons/icon_reflection_probe.png
index a6646114fb..a6646114fb 100644
--- a/tools/editor/icons/icon_reflection_probe.png
+++ b/editor/icons/icon_reflection_probe.png
Binary files differ
diff --git a/tools/editor/icons/icon_region_edit.png b/editor/icons/icon_region_edit.png
index 5f133072d4..5f133072d4 100644
--- a/tools/editor/icons/icon_region_edit.png
+++ b/editor/icons/icon_region_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_reload.png b/editor/icons/icon_reload.png
index 9303fabb9c..9303fabb9c 100644
--- a/tools/editor/icons/icon_reload.png
+++ b/editor/icons/icon_reload.png
Binary files differ
diff --git a/tools/editor/icons/icon_reload_empty.png b/editor/icons/icon_reload_empty.png
index d43582b2c4..d43582b2c4 100644
--- a/tools/editor/icons/icon_reload_empty.png
+++ b/editor/icons/icon_reload_empty.png
Binary files differ
diff --git a/tools/editor/icons/icon_reload_small.png b/editor/icons/icon_reload_small.png
index 1397ac6aa5..1397ac6aa5 100644
--- a/tools/editor/icons/icon_reload_small.png
+++ b/editor/icons/icon_reload_small.png
Binary files differ
diff --git a/tools/editor/icons/icon_remote.png b/editor/icons/icon_remote.png
index 7eb7608b13..7eb7608b13 100644
--- a/tools/editor/icons/icon_remote.png
+++ b/editor/icons/icon_remote.png
Binary files differ
diff --git a/tools/editor/icons/icon_remote_transform.png b/editor/icons/icon_remote_transform.png
index 2a8b5f4d0e..2a8b5f4d0e 100644
--- a/tools/editor/icons/icon_remote_transform.png
+++ b/editor/icons/icon_remote_transform.png
Binary files differ
diff --git a/tools/editor/icons/icon_remote_transform_2d.png b/editor/icons/icon_remote_transform_2d.png
index 16d2691832..16d2691832 100644
--- a/tools/editor/icons/icon_remote_transform_2d.png
+++ b/editor/icons/icon_remote_transform_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_remove.png b/editor/icons/icon_remove.png
index b6bf05a16d..b6bf05a16d 100644
--- a/tools/editor/icons/icon_remove.png
+++ b/editor/icons/icon_remove.png
Binary files differ
diff --git a/tools/editor/icons/icon_remove_hl.png b/editor/icons/icon_remove_hl.png
index 0d3b887e7f..0d3b887e7f 100644
--- a/tools/editor/icons/icon_remove_hl.png
+++ b/editor/icons/icon_remove_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_remove_small.png b/editor/icons/icon_remove_small.png
index e0903689cf..e0903689cf 100644
--- a/tools/editor/icons/icon_remove_small.png
+++ b/editor/icons/icon_remove_small.png
Binary files differ
diff --git a/tools/editor/icons/icon_rename.png b/editor/icons/icon_rename.png
index 2df503f100..2df503f100 100644
--- a/tools/editor/icons/icon_rename.png
+++ b/editor/icons/icon_rename.png
Binary files differ
diff --git a/tools/editor/icons/icon_reparent.png b/editor/icons/icon_reparent.png
index 135ccee4ad..135ccee4ad 100644
--- a/tools/editor/icons/icon_reparent.png
+++ b/editor/icons/icon_reparent.png
Binary files differ
diff --git a/tools/editor/icons/icon_replace.png b/editor/icons/icon_replace.png
index 662a58dc93..662a58dc93 100644
--- a/tools/editor/icons/icon_replace.png
+++ b/editor/icons/icon_replace.png
Binary files differ
diff --git a/tools/editor/icons/icon_resource_preloader.png b/editor/icons/icon_resource_preloader.png
index d3064f5e90..d3064f5e90 100644
--- a/tools/editor/icons/icon_resource_preloader.png
+++ b/editor/icons/icon_resource_preloader.png
Binary files differ
diff --git a/tools/editor/icons/icon_rich_text_label.png b/editor/icons/icon_rich_text_label.png
index 1aea6e8fa7..1aea6e8fa7 100644
--- a/tools/editor/icons/icon_rich_text_label.png
+++ b/editor/icons/icon_rich_text_label.png
Binary files differ
diff --git a/tools/editor/icons/icon_rid.png b/editor/icons/icon_rid.png
index f7bc02e128..f7bc02e128 100644
--- a/tools/editor/icons/icon_rid.png
+++ b/editor/icons/icon_rid.png
Binary files differ
diff --git a/tools/editor/icons/icon_rigid_body.png b/editor/icons/icon_rigid_body.png
index 4072308f71..4072308f71 100644
--- a/tools/editor/icons/icon_rigid_body.png
+++ b/editor/icons/icon_rigid_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_rigid_body_2_d.png b/editor/icons/icon_rigid_body_2_d.png
index c296b88636..c296b88636 100644
--- a/tools/editor/icons/icon_rigid_body_2_d.png
+++ b/editor/icons/icon_rigid_body_2_d.png
Binary files differ
diff --git a/tools/editor/icons/icon_rigid_body_2d.png b/editor/icons/icon_rigid_body_2d.png
index 8d11d536c1..8d11d536c1 100644
--- a/tools/editor/icons/icon_rigid_body_2d.png
+++ b/editor/icons/icon_rigid_body_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_room.png b/editor/icons/icon_room.png
index 840db145fd..840db145fd 100644
--- a/tools/editor/icons/icon_room.png
+++ b/editor/icons/icon_room.png
Binary files differ
diff --git a/tools/editor/icons/icon_room_bounds.png b/editor/icons/icon_room_bounds.png
index 15b198e821..15b198e821 100644
--- a/tools/editor/icons/icon_room_bounds.png
+++ b/editor/icons/icon_room_bounds.png
Binary files differ
diff --git a/tools/editor/icons/icon_room_instance.png b/editor/icons/icon_room_instance.png
index f0c46e689c..f0c46e689c 100644
--- a/tools/editor/icons/icon_room_instance.png
+++ b/editor/icons/icon_room_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_rotate_0.png b/editor/icons/icon_rotate_0.png
index 75bd667845..75bd667845 100644
--- a/tools/editor/icons/icon_rotate_0.png
+++ b/editor/icons/icon_rotate_0.png
Binary files differ
diff --git a/tools/editor/icons/icon_rotate_180.png b/editor/icons/icon_rotate_180.png
index dd9333207e..dd9333207e 100644
--- a/tools/editor/icons/icon_rotate_180.png
+++ b/editor/icons/icon_rotate_180.png
Binary files differ
diff --git a/tools/editor/icons/icon_rotate_270.png b/editor/icons/icon_rotate_270.png
index 551fd3afb9..551fd3afb9 100644
--- a/tools/editor/icons/icon_rotate_270.png
+++ b/editor/icons/icon_rotate_270.png
Binary files differ
diff --git a/tools/editor/icons/icon_rotate_90.png b/editor/icons/icon_rotate_90.png
index 55a084cc4e..55a084cc4e 100644
--- a/tools/editor/icons/icon_rotate_90.png
+++ b/editor/icons/icon_rotate_90.png
Binary files differ
diff --git a/tools/editor/icons/icon_run.png b/editor/icons/icon_run.png
index 133d383d9e..133d383d9e 100644
--- a/tools/editor/icons/icon_run.png
+++ b/editor/icons/icon_run.png
Binary files differ
diff --git a/tools/editor/icons/icon_s_s_a_o_f_x.png b/editor/icons/icon_s_s_a_o_f_x.png
index 36eccedca5..36eccedca5 100644
--- a/tools/editor/icons/icon_s_s_a_o_f_x.png
+++ b/editor/icons/icon_s_s_a_o_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_sample.png b/editor/icons/icon_sample.png
index 25755699be..25755699be 100644
--- a/tools/editor/icons/icon_sample.png
+++ b/editor/icons/icon_sample.png
Binary files differ
diff --git a/tools/editor/icons/icon_sample_library.png b/editor/icons/icon_sample_library.png
index 5921aa86e7..5921aa86e7 100644
--- a/tools/editor/icons/icon_sample_library.png
+++ b/editor/icons/icon_sample_library.png
Binary files differ
diff --git a/tools/editor/icons/icon_sample_player.png b/editor/icons/icon_sample_player.png
index 4056cceeff..4056cceeff 100644
--- a/tools/editor/icons/icon_sample_player.png
+++ b/editor/icons/icon_sample_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_sample_player_2d.png b/editor/icons/icon_sample_player_2d.png
index eb70340db8..eb70340db8 100644
--- a/tools/editor/icons/icon_sample_player_2d.png
+++ b/editor/icons/icon_sample_player_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_save.png b/editor/icons/icon_save.png
index 8695b7839d..8695b7839d 100644
--- a/tools/editor/icons/icon_save.png
+++ b/editor/icons/icon_save.png
Binary files differ
diff --git a/tools/editor/icons/icon_scene.png b/editor/icons/icon_scene.png
index 9629bb91c2..9629bb91c2 100644
--- a/tools/editor/icons/icon_scene.png
+++ b/editor/icons/icon_scene.png
Binary files differ
diff --git a/tools/editor/icons/icon_scene_instance.png b/editor/icons/icon_scene_instance.png
index 05df811aa0..05df811aa0 100644
--- a/tools/editor/icons/icon_scene_instance.png
+++ b/editor/icons/icon_scene_instance.png
Binary files differ
diff --git a/tools/editor/icons/icon_scene_tree_editor.png b/editor/icons/icon_scene_tree_editor.png
index 0b51763555..0b51763555 100644
--- a/tools/editor/icons/icon_scene_tree_editor.png
+++ b/editor/icons/icon_scene_tree_editor.png
Binary files differ
diff --git a/tools/editor/icons/icon_script.png b/editor/icons/icon_script.png
index 5aa673fcd6..5aa673fcd6 100644
--- a/tools/editor/icons/icon_script.png
+++ b/editor/icons/icon_script.png
Binary files differ
diff --git a/tools/editor/icons/icon_script_control.png b/editor/icons/icon_script_control.png
index cd1cc9b9af..cd1cc9b9af 100644
--- a/tools/editor/icons/icon_script_control.png
+++ b/editor/icons/icon_script_control.png
Binary files differ
diff --git a/tools/editor/icons/icon_script_create.png b/editor/icons/icon_script_create.png
index 86c19f748b..86c19f748b 100644
--- a/tools/editor/icons/icon_script_create.png
+++ b/editor/icons/icon_script_create.png
Binary files differ
diff --git a/tools/editor/icons/icon_script_error.png b/editor/icons/icon_script_error.png
index 3532c2c379..3532c2c379 100644
--- a/tools/editor/icons/icon_script_error.png
+++ b/editor/icons/icon_script_error.png
Binary files differ
diff --git a/tools/editor/icons/icon_script_list.png b/editor/icons/icon_script_list.png
index cdea1e161e..cdea1e161e 100644
--- a/tools/editor/icons/icon_script_list.png
+++ b/editor/icons/icon_script_list.png
Binary files differ
diff --git a/tools/editor/icons/icon_script_node.png b/editor/icons/icon_script_node.png
index fcf205b2e9..fcf205b2e9 100644
--- a/tools/editor/icons/icon_script_node.png
+++ b/editor/icons/icon_script_node.png
Binary files differ
diff --git a/tools/editor/icons/icon_script_remove.png b/editor/icons/icon_script_remove.png
index c200b01690..c200b01690 100644
--- a/tools/editor/icons/icon_script_remove.png
+++ b/editor/icons/icon_script_remove.png
Binary files differ
diff --git a/tools/editor/icons/icon_scroll_bar.png b/editor/icons/icon_scroll_bar.png
index e4576c4ae3..e4576c4ae3 100644
--- a/tools/editor/icons/icon_scroll_bar.png
+++ b/editor/icons/icon_scroll_bar.png
Binary files differ
diff --git a/tools/editor/icons/icon_scroll_container.png b/editor/icons/icon_scroll_container.png
index 4e42d84ab1..4e42d84ab1 100644
--- a/tools/editor/icons/icon_scroll_container.png
+++ b/editor/icons/icon_scroll_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_segment_shape_2d.png b/editor/icons/icon_segment_shape_2d.png
index 8f3771be7a..8f3771be7a 100644
--- a/tools/editor/icons/icon_segment_shape_2d.png
+++ b/editor/icons/icon_segment_shape_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_shader.png b/editor/icons/icon_shader.png
index 568a45d938..568a45d938 100644
--- a/tools/editor/icons/icon_shader.png
+++ b/editor/icons/icon_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_shader_material.png b/editor/icons/icon_shader_material.png
index 568a45d938..568a45d938 100644
--- a/tools/editor/icons/icon_shader_material.png
+++ b/editor/icons/icon_shader_material.png
Binary files differ
diff --git a/tools/editor/icons/icon_short_cut.png b/editor/icons/icon_short_cut.png
index 22e15c3889..22e15c3889 100644
--- a/tools/editor/icons/icon_short_cut.png
+++ b/editor/icons/icon_short_cut.png
Binary files differ
diff --git a/tools/editor/icons/icon_signal.png b/editor/icons/icon_signal.png
index c2f393228c..c2f393228c 100644
--- a/tools/editor/icons/icon_signal.png
+++ b/editor/icons/icon_signal.png
Binary files differ
diff --git a/tools/editor/icons/icon_skeleton.png b/editor/icons/icon_skeleton.png
index 17b003caac..17b003caac 100644
--- a/tools/editor/icons/icon_skeleton.png
+++ b/editor/icons/icon_skeleton.png
Binary files differ
diff --git a/tools/editor/icons/icon_skeletonr.png b/editor/icons/icon_skeletonr.png
index dcb2d512ab..dcb2d512ab 100644
--- a/tools/editor/icons/icon_skeletonr.png
+++ b/editor/icons/icon_skeletonr.png
Binary files differ
diff --git a/tools/editor/icons/icon_sky_box_f_x.png b/editor/icons/icon_sky_box_f_x.png
index cabd19e550..cabd19e550 100644
--- a/tools/editor/icons/icon_sky_box_f_x.png
+++ b/editor/icons/icon_sky_box_f_x.png
Binary files differ
diff --git a/tools/editor/icons/icon_slider_joint.png b/editor/icons/icon_slider_joint.png
index d65fb3650d..d65fb3650d 100644
--- a/tools/editor/icons/icon_slider_joint.png
+++ b/editor/icons/icon_slider_joint.png
Binary files differ
diff --git a/tools/editor/icons/icon_slot.png b/editor/icons/icon_slot.png
index 856bf72281..856bf72281 100644
--- a/tools/editor/icons/icon_slot.png
+++ b/editor/icons/icon_slot.png
Binary files differ
diff --git a/tools/editor/icons/icon_small_next.png b/editor/icons/icon_small_next.png
index f853d100b5..f853d100b5 100644
--- a/tools/editor/icons/icon_small_next.png
+++ b/editor/icons/icon_small_next.png
Binary files differ
diff --git a/tools/editor/icons/icon_snap.png b/editor/icons/icon_snap.png
index 93194d34e7..93194d34e7 100644
--- a/tools/editor/icons/icon_snap.png
+++ b/editor/icons/icon_snap.png
Binary files differ
diff --git a/tools/editor/icons/icon_sound_room_params.png b/editor/icons/icon_sound_room_params.png
index 6f66da2e43..6f66da2e43 100644
--- a/tools/editor/icons/icon_sound_room_params.png
+++ b/editor/icons/icon_sound_room_params.png
Binary files differ
diff --git a/tools/editor/icons/icon_spatial.png b/editor/icons/icon_spatial.png
index 7c9f721053..7c9f721053 100644
--- a/tools/editor/icons/icon_spatial.png
+++ b/editor/icons/icon_spatial.png
Binary files differ
diff --git a/tools/editor/icons/icon_spatial_add.png b/editor/icons/icon_spatial_add.png
index 47950fbbb5..47950fbbb5 100644
--- a/tools/editor/icons/icon_spatial_add.png
+++ b/editor/icons/icon_spatial_add.png
Binary files differ
diff --git a/tools/editor/icons/icon_spatial_sample_player.png b/editor/icons/icon_spatial_sample_player.png
index bb2451da99..bb2451da99 100644
--- a/tools/editor/icons/icon_spatial_sample_player.png
+++ b/editor/icons/icon_spatial_sample_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_spatial_shader.png b/editor/icons/icon_spatial_shader.png
index 7608fc9036..7608fc9036 100644
--- a/tools/editor/icons/icon_spatial_shader.png
+++ b/editor/icons/icon_spatial_shader.png
Binary files differ
diff --git a/tools/editor/icons/icon_spatial_stream_player.png b/editor/icons/icon_spatial_stream_player.png
index a6f9851548..a6f9851548 100644
--- a/tools/editor/icons/icon_spatial_stream_player.png
+++ b/editor/icons/icon_spatial_stream_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_sphere_shape.png b/editor/icons/icon_sphere_shape.png
index 23300a0da1..23300a0da1 100644
--- a/tools/editor/icons/icon_sphere_shape.png
+++ b/editor/icons/icon_sphere_shape.png
Binary files differ
diff --git a/tools/editor/icons/icon_spin_box.png b/editor/icons/icon_spin_box.png
index 6da0dbec79..6da0dbec79 100644
--- a/tools/editor/icons/icon_spin_box.png
+++ b/editor/icons/icon_spin_box.png
Binary files differ
diff --git a/tools/editor/icons/icon_spline.png b/editor/icons/icon_spline.png
index 3239aff383..3239aff383 100644
--- a/tools/editor/icons/icon_spline.png
+++ b/editor/icons/icon_spline.png
Binary files differ
diff --git a/tools/editor/icons/icon_spot_light.png b/editor/icons/icon_spot_light.png
index f52570a5cd..f52570a5cd 100644
--- a/tools/editor/icons/icon_spot_light.png
+++ b/editor/icons/icon_spot_light.png
Binary files differ
diff --git a/tools/editor/icons/icon_sprite.png b/editor/icons/icon_sprite.png
index b698d32d4c..b698d32d4c 100644
--- a/tools/editor/icons/icon_sprite.png
+++ b/editor/icons/icon_sprite.png
Binary files differ
diff --git a/tools/editor/icons/icon_sprite_3d.png b/editor/icons/icon_sprite_3d.png
index 47a3ff429b..47a3ff429b 100644
--- a/tools/editor/icons/icon_sprite_3d.png
+++ b/editor/icons/icon_sprite_3d.png
Binary files differ
diff --git a/tools/editor/icons/icon_sprite_frames.png b/editor/icons/icon_sprite_frames.png
index 5576b24f2e..5576b24f2e 100644
--- a/tools/editor/icons/icon_sprite_frames.png
+++ b/editor/icons/icon_sprite_frames.png
Binary files differ
diff --git a/tools/editor/icons/icon_squirrel_script.png b/editor/icons/icon_squirrel_script.png
index 32926b5975..32926b5975 100644
--- a/tools/editor/icons/icon_squirrel_script.png
+++ b/editor/icons/icon_squirrel_script.png
Binary files differ
diff --git a/tools/editor/icons/icon_static_body.png b/editor/icons/icon_static_body.png
index 62948f97cd..62948f97cd 100644
--- a/tools/editor/icons/icon_static_body.png
+++ b/editor/icons/icon_static_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_static_body_2_d.png b/editor/icons/icon_static_body_2_d.png
index 9af0274a65..9af0274a65 100644
--- a/tools/editor/icons/icon_static_body_2_d.png
+++ b/editor/icons/icon_static_body_2_d.png
Binary files differ
diff --git a/tools/editor/icons/icon_static_body_2d.png b/editor/icons/icon_static_body_2d.png
index b7bad4f742..b7bad4f742 100644
--- a/tools/editor/icons/icon_static_body_2d.png
+++ b/editor/icons/icon_static_body_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_stop.png b/editor/icons/icon_stop.png
index 0fd43b403a..0fd43b403a 100644
--- a/tools/editor/icons/icon_stop.png
+++ b/editor/icons/icon_stop.png
Binary files differ
diff --git a/tools/editor/icons/icon_stream_player.png b/editor/icons/icon_stream_player.png
index 15bdbdf440..15bdbdf440 100644
--- a/tools/editor/icons/icon_stream_player.png
+++ b/editor/icons/icon_stream_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_string.png b/editor/icons/icon_string.png
index 8d01b738da..8d01b738da 100644
--- a/tools/editor/icons/icon_string.png
+++ b/editor/icons/icon_string.png
Binary files differ
diff --git a/tools/editor/icons/icon_style_box_empty.png b/editor/icons/icon_style_box_empty.png
index f595eaaa57..f595eaaa57 100644
--- a/tools/editor/icons/icon_style_box_empty.png
+++ b/editor/icons/icon_style_box_empty.png
Binary files differ
diff --git a/tools/editor/icons/icon_style_box_flat.png b/editor/icons/icon_style_box_flat.png
index 6ec6a6dd35..6ec6a6dd35 100644
--- a/tools/editor/icons/icon_style_box_flat.png
+++ b/editor/icons/icon_style_box_flat.png
Binary files differ
diff --git a/tools/editor/icons/icon_style_box_texture.png b/editor/icons/icon_style_box_texture.png
index f649508418..f649508418 100644
--- a/tools/editor/icons/icon_style_box_texture.png
+++ b/editor/icons/icon_style_box_texture.png
Binary files differ
diff --git a/tools/editor/icons/icon_surface.png b/editor/icons/icon_surface.png
index e7af8e9444..e7af8e9444 100644
--- a/tools/editor/icons/icon_surface.png
+++ b/editor/icons/icon_surface.png
Binary files differ
diff --git a/tools/editor/icons/icon_tab_container.png b/editor/icons/icon_tab_container.png
index 7ff3081ec1..7ff3081ec1 100644
--- a/tools/editor/icons/icon_tab_container.png
+++ b/editor/icons/icon_tab_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_tab_menu.png b/editor/icons/icon_tab_menu.png
index 29edd02f01..29edd02f01 100644
--- a/tools/editor/icons/icon_tab_menu.png
+++ b/editor/icons/icon_tab_menu.png
Binary files differ
diff --git a/tools/editor/icons/icon_tabs.png b/editor/icons/icon_tabs.png
index bef0f60660..bef0f60660 100644
--- a/tools/editor/icons/icon_tabs.png
+++ b/editor/icons/icon_tabs.png
Binary files differ
diff --git a/tools/editor/icons/icon_test_cube.png b/editor/icons/icon_test_cube.png
index 4d11a69c3e..4d11a69c3e 100644
--- a/tools/editor/icons/icon_test_cube.png
+++ b/editor/icons/icon_test_cube.png
Binary files differ
diff --git a/tools/editor/icons/icon_text_edit.png b/editor/icons/icon_text_edit.png
index 7599e89eb1..7599e89eb1 100644
--- a/tools/editor/icons/icon_text_edit.png
+++ b/editor/icons/icon_text_edit.png
Binary files differ
diff --git a/tools/editor/icons/icon_texture.png b/editor/icons/icon_texture.png
index 7c4493395e..7c4493395e 100644
--- a/tools/editor/icons/icon_texture.png
+++ b/editor/icons/icon_texture.png
Binary files differ
diff --git a/tools/editor/icons/icon_texture_button.png b/editor/icons/icon_texture_button.png
index ea1d8235e1..ea1d8235e1 100644
--- a/tools/editor/icons/icon_texture_button.png
+++ b/editor/icons/icon_texture_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_texture_progress.png b/editor/icons/icon_texture_progress.png
index ea3cc35da8..ea3cc35da8 100644
--- a/tools/editor/icons/icon_texture_progress.png
+++ b/editor/icons/icon_texture_progress.png
Binary files differ
diff --git a/tools/editor/icons/icon_texture_rect.png b/editor/icons/icon_texture_rect.png
index 84e4a90bfb..84e4a90bfb 100644
--- a/tools/editor/icons/icon_texture_rect.png
+++ b/editor/icons/icon_texture_rect.png
Binary files differ
diff --git a/tools/editor/icons/icon_theme.png b/editor/icons/icon_theme.png
index 55d799c722..55d799c722 100644
--- a/tools/editor/icons/icon_theme.png
+++ b/editor/icons/icon_theme.png
Binary files differ
diff --git a/tools/editor/icons/icon_thumbnail_wait.png b/editor/icons/icon_thumbnail_wait.png
index 96a7d424e3..96a7d424e3 100644
--- a/tools/editor/icons/icon_thumbnail_wait.png
+++ b/editor/icons/icon_thumbnail_wait.png
Binary files differ
diff --git a/tools/editor/icons/icon_tile_map.png b/editor/icons/icon_tile_map.png
index 0ba6276e25..0ba6276e25 100644
--- a/tools/editor/icons/icon_tile_map.png
+++ b/editor/icons/icon_tile_map.png
Binary files differ
diff --git a/tools/editor/icons/icon_tile_set.png b/editor/icons/icon_tile_set.png
index a1c3fccddd..a1c3fccddd 100644
--- a/tools/editor/icons/icon_tile_set.png
+++ b/editor/icons/icon_tile_set.png
Binary files differ
diff --git a/tools/editor/icons/icon_time.png b/editor/icons/icon_time.png
index a8e97ea7b8..a8e97ea7b8 100644
--- a/tools/editor/icons/icon_time.png
+++ b/editor/icons/icon_time.png
Binary files differ
diff --git a/tools/editor/icons/icon_timer.png b/editor/icons/icon_timer.png
index d3eb6a4b49..d3eb6a4b49 100644
--- a/tools/editor/icons/icon_timer.png
+++ b/editor/icons/icon_timer.png
Binary files differ
diff --git a/tools/editor/icons/icon_tool_button.png b/editor/icons/icon_tool_button.png
index b2f3f6103f..b2f3f6103f 100644
--- a/tools/editor/icons/icon_tool_button.png
+++ b/editor/icons/icon_tool_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_tool_move.png b/editor/icons/icon_tool_move.png
index 2b6984e8b2..2b6984e8b2 100644
--- a/tools/editor/icons/icon_tool_move.png
+++ b/editor/icons/icon_tool_move.png
Binary files differ
diff --git a/tools/editor/icons/icon_tool_pan.png b/editor/icons/icon_tool_pan.png
index a24545a6d4..a24545a6d4 100644
--- a/tools/editor/icons/icon_tool_pan.png
+++ b/editor/icons/icon_tool_pan.png
Binary files differ
diff --git a/tools/editor/icons/icon_tool_rotate.png b/editor/icons/icon_tool_rotate.png
index 9303fabb9c..9303fabb9c 100644
--- a/tools/editor/icons/icon_tool_rotate.png
+++ b/editor/icons/icon_tool_rotate.png
Binary files differ
diff --git a/tools/editor/icons/icon_tool_scale.png b/editor/icons/icon_tool_scale.png
index b389c40746..b389c40746 100644
--- a/tools/editor/icons/icon_tool_scale.png
+++ b/editor/icons/icon_tool_scale.png
Binary files differ
diff --git a/tools/editor/icons/icon_tool_select.png b/editor/icons/icon_tool_select.png
index dcf6fcd2c8..dcf6fcd2c8 100644
--- a/tools/editor/icons/icon_tool_select.png
+++ b/editor/icons/icon_tool_select.png
Binary files differ
diff --git a/tools/editor/icons/icon_tools.png b/editor/icons/icon_tools.png
index 4db4c53796..4db4c53796 100644
--- a/tools/editor/icons/icon_tools.png
+++ b/editor/icons/icon_tools.png
Binary files differ
diff --git a/tools/editor/icons/icon_touch_screen_button.png b/editor/icons/icon_touch_screen_button.png
index 6bd0af3f47..6bd0af3f47 100644
--- a/tools/editor/icons/icon_touch_screen_button.png
+++ b/editor/icons/icon_touch_screen_button.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_add_key.png b/editor/icons/icon_track_add_key.png
index 02d92439a3..02d92439a3 100644
--- a/tools/editor/icons/icon_track_add_key.png
+++ b/editor/icons/icon_track_add_key.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_add_key_hl.png b/editor/icons/icon_track_add_key_hl.png
index 0e857f5fe2..0e857f5fe2 100644
--- a/tools/editor/icons/icon_track_add_key_hl.png
+++ b/editor/icons/icon_track_add_key_hl.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_continuous.png b/editor/icons/icon_track_continuous.png
index dabdc718d5..dabdc718d5 100644
--- a/tools/editor/icons/icon_track_continuous.png
+++ b/editor/icons/icon_track_continuous.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_discrete.png b/editor/icons/icon_track_discrete.png
index 3f580ac5fc..3f580ac5fc 100644
--- a/tools/editor/icons/icon_track_discrete.png
+++ b/editor/icons/icon_track_discrete.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_method.png b/editor/icons/icon_track_method.png
index 1355c84e67..1355c84e67 100644
--- a/tools/editor/icons/icon_track_method.png
+++ b/editor/icons/icon_track_method.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_prop.png b/editor/icons/icon_track_prop.png
index de8f549cd2..de8f549cd2 100644
--- a/tools/editor/icons/icon_track_prop.png
+++ b/editor/icons/icon_track_prop.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_trigger.png b/editor/icons/icon_track_trigger.png
index e89f95561a..e89f95561a 100644
--- a/tools/editor/icons/icon_track_trigger.png
+++ b/editor/icons/icon_track_trigger.png
Binary files differ
diff --git a/tools/editor/icons/icon_track_value.png b/editor/icons/icon_track_value.png
index 5f5dc0d315..5f5dc0d315 100644
--- a/tools/editor/icons/icon_track_value.png
+++ b/editor/icons/icon_track_value.png
Binary files differ
diff --git a/tools/editor/icons/icon_translation.png b/editor/icons/icon_translation.png
index abca359eea..abca359eea 100644
--- a/tools/editor/icons/icon_translation.png
+++ b/editor/icons/icon_translation.png
Binary files differ
diff --git a/tools/editor/icons/icon_transparent.png b/editor/icons/icon_transparent.png
index 07e9b52b5c..07e9b52b5c 100644
--- a/tools/editor/icons/icon_transparent.png
+++ b/editor/icons/icon_transparent.png
Binary files differ
diff --git a/tools/editor/icons/icon_transpose.png b/editor/icons/icon_transpose.png
index 7a126c8428..7a126c8428 100644
--- a/tools/editor/icons/icon_transpose.png
+++ b/editor/icons/icon_transpose.png
Binary files differ
diff --git a/tools/editor/icons/icon_tree.png b/editor/icons/icon_tree.png
index 50ec1df98b..50ec1df98b 100644
--- a/tools/editor/icons/icon_tree.png
+++ b/editor/icons/icon_tree.png
Binary files differ
diff --git a/tools/editor/icons/icon_tween.png b/editor/icons/icon_tween.png
index 36717c0922..36717c0922 100644
--- a/tools/editor/icons/icon_tween.png
+++ b/editor/icons/icon_tween.png
Binary files differ
diff --git a/tools/editor/icons/icon_unbone.png b/editor/icons/icon_unbone.png
index 919e13ad6b..919e13ad6b 100644
--- a/tools/editor/icons/icon_unbone.png
+++ b/editor/icons/icon_unbone.png
Binary files differ
diff --git a/tools/editor/icons/icon_ungroup.png b/editor/icons/icon_ungroup.png
index b4c2e01814..b4c2e01814 100644
--- a/tools/editor/icons/icon_ungroup.png
+++ b/editor/icons/icon_ungroup.png
Binary files differ
diff --git a/tools/editor/icons/icon_uninstance.png b/editor/icons/icon_uninstance.png
index de8b2f9a40..de8b2f9a40 100644
--- a/tools/editor/icons/icon_uninstance.png
+++ b/editor/icons/icon_uninstance.png
Binary files differ
diff --git a/tools/editor/icons/icon_unlock.png b/editor/icons/icon_unlock.png
index d314aa46fe..d314aa46fe 100644
--- a/tools/editor/icons/icon_unlock.png
+++ b/editor/icons/icon_unlock.png
Binary files differ
diff --git a/tools/editor/icons/icon_up.png b/editor/icons/icon_up.png
index 346c4cdba8..346c4cdba8 100644
--- a/tools/editor/icons/icon_up.png
+++ b/editor/icons/icon_up.png
Binary files differ
diff --git a/tools/editor/icons/icon_updown.png b/editor/icons/icon_updown.png
index 3141dc56ae..3141dc56ae 100644
--- a/tools/editor/icons/icon_updown.png
+++ b/editor/icons/icon_updown.png
Binary files differ
diff --git a/tools/editor/icons/icon_uv.png b/editor/icons/icon_uv.png
index f5d901ab91..f5d901ab91 100644
--- a/tools/editor/icons/icon_uv.png
+++ b/editor/icons/icon_uv.png
Binary files differ
diff --git a/tools/editor/icons/icon_v_box_container.png b/editor/icons/icon_v_box_container.png
index 4d9bdb67b8..4d9bdb67b8 100644
--- a/tools/editor/icons/icon_v_box_container.png
+++ b/editor/icons/icon_v_box_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_v_button_array.png b/editor/icons/icon_v_button_array.png
index d7ea9cc375..d7ea9cc375 100644
--- a/tools/editor/icons/icon_v_button_array.png
+++ b/editor/icons/icon_v_button_array.png
Binary files differ
diff --git a/tools/editor/icons/icon_v_scroll_bar.png b/editor/icons/icon_v_scroll_bar.png
index 91e00f4619..91e00f4619 100644
--- a/tools/editor/icons/icon_v_scroll_bar.png
+++ b/editor/icons/icon_v_scroll_bar.png
Binary files differ
diff --git a/tools/editor/icons/icon_v_separator.png b/editor/icons/icon_v_separator.png
index f0122d197f..f0122d197f 100644
--- a/tools/editor/icons/icon_v_separator.png
+++ b/editor/icons/icon_v_separator.png
Binary files differ
diff --git a/tools/editor/icons/icon_v_slider.png b/editor/icons/icon_v_slider.png
index 545c126d23..545c126d23 100644
--- a/tools/editor/icons/icon_v_slider.png
+++ b/editor/icons/icon_v_slider.png
Binary files differ
diff --git a/tools/editor/icons/icon_v_split_container.png b/editor/icons/icon_v_split_container.png
index 23093e334f..23093e334f 100644
--- a/tools/editor/icons/icon_v_split_container.png
+++ b/editor/icons/icon_v_split_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_variant.png b/editor/icons/icon_variant.png
index 1ae2812ff7..1ae2812ff7 100644
--- a/tools/editor/icons/icon_variant.png
+++ b/editor/icons/icon_variant.png
Binary files differ
diff --git a/tools/editor/icons/icon_vector.png b/editor/icons/icon_vector.png
index 8dba948daf..8dba948daf 100644
--- a/tools/editor/icons/icon_vector.png
+++ b/editor/icons/icon_vector.png
Binary files differ
diff --git a/tools/editor/icons/icon_vector2.png b/editor/icons/icon_vector2.png
index f84052cda0..f84052cda0 100644
--- a/tools/editor/icons/icon_vector2.png
+++ b/editor/icons/icon_vector2.png
Binary files differ
diff --git a/tools/editor/icons/icon_vehicle_body.png b/editor/icons/icon_vehicle_body.png
index c404218911..c404218911 100644
--- a/tools/editor/icons/icon_vehicle_body.png
+++ b/editor/icons/icon_vehicle_body.png
Binary files differ
diff --git a/tools/editor/icons/icon_vehicle_wheel.png b/editor/icons/icon_vehicle_wheel.png
index 23299a0425..23299a0425 100644
--- a/tools/editor/icons/icon_vehicle_wheel.png
+++ b/editor/icons/icon_vehicle_wheel.png
Binary files differ
diff --git a/tools/editor/icons/icon_video_player.png b/editor/icons/icon_video_player.png
index 5fd3723b22..5fd3723b22 100644
--- a/tools/editor/icons/icon_video_player.png
+++ b/editor/icons/icon_video_player.png
Binary files differ
diff --git a/tools/editor/icons/icon_video_stream_theora.png b/editor/icons/icon_video_stream_theora.png
index 3f019f9b61..3f019f9b61 100644
--- a/tools/editor/icons/icon_video_stream_theora.png
+++ b/editor/icons/icon_video_stream_theora.png
Binary files differ
diff --git a/tools/editor/icons/icon_view.png b/editor/icons/icon_view.png
index c7975ed461..c7975ed461 100644
--- a/tools/editor/icons/icon_view.png
+++ b/editor/icons/icon_view.png
Binary files differ
diff --git a/tools/editor/icons/icon_viewport.png b/editor/icons/icon_viewport.png
index 8b25ea8764..8b25ea8764 100644
--- a/tools/editor/icons/icon_viewport.png
+++ b/editor/icons/icon_viewport.png
Binary files differ
diff --git a/tools/editor/icons/icon_viewport_container.png b/editor/icons/icon_viewport_container.png
index c70dee3698..c70dee3698 100644
--- a/tools/editor/icons/icon_viewport_container.png
+++ b/editor/icons/icon_viewport_container.png
Binary files differ
diff --git a/tools/editor/icons/icon_viewport_sprite.png b/editor/icons/icon_viewport_sprite.png
index 9aefb471d6..9aefb471d6 100644
--- a/tools/editor/icons/icon_viewport_sprite.png
+++ b/editor/icons/icon_viewport_sprite.png
Binary files differ
diff --git a/tools/editor/icons/icon_viewport_texture.png b/editor/icons/icon_viewport_texture.png
index ae744cc407..ae744cc407 100644
--- a/tools/editor/icons/icon_viewport_texture.png
+++ b/editor/icons/icon_viewport_texture.png
Binary files differ
diff --git a/tools/editor/icons/icon_visibility_area.png b/editor/icons/icon_visibility_area.png
index f3ca05711b..f3ca05711b 100644
--- a/tools/editor/icons/icon_visibility_area.png
+++ b/editor/icons/icon_visibility_area.png
Binary files differ
diff --git a/tools/editor/icons/icon_visibility_enabler.png b/editor/icons/icon_visibility_enabler.png
index 66dffd3483..66dffd3483 100644
--- a/tools/editor/icons/icon_visibility_enabler.png
+++ b/editor/icons/icon_visibility_enabler.png
Binary files differ
diff --git a/tools/editor/icons/icon_visibility_enabler_2d.png b/editor/icons/icon_visibility_enabler_2d.png
index e198b9785b..e198b9785b 100644
--- a/tools/editor/icons/icon_visibility_enabler_2d.png
+++ b/editor/icons/icon_visibility_enabler_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_visibility_notifier.png b/editor/icons/icon_visibility_notifier.png
index 624122fb4c..624122fb4c 100644
--- a/tools/editor/icons/icon_visibility_notifier.png
+++ b/editor/icons/icon_visibility_notifier.png
Binary files differ
diff --git a/tools/editor/icons/icon_visibility_notifier_2d.png b/editor/icons/icon_visibility_notifier_2d.png
index f904223edf..f904223edf 100644
--- a/tools/editor/icons/icon_visibility_notifier_2d.png
+++ b/editor/icons/icon_visibility_notifier_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_visible.png b/editor/icons/icon_visible.png
index 4e79dd3245..4e79dd3245 100644
--- a/tools/editor/icons/icon_visible.png
+++ b/editor/icons/icon_visible.png
Binary files differ
diff --git a/tools/editor/icons/icon_visual_script.png b/editor/icons/icon_visual_script.png
index 1678998d17..1678998d17 100644
--- a/tools/editor/icons/icon_visual_script.png
+++ b/editor/icons/icon_visual_script.png
Binary files differ
diff --git a/tools/editor/icons/icon_visual_shader_port.png b/editor/icons/icon_visual_shader_port.png
index 27daedbdd0..27daedbdd0 100644
--- a/tools/editor/icons/icon_visual_shader_port.png
+++ b/editor/icons/icon_visual_shader_port.png
Binary files differ
diff --git a/tools/editor/icons/icon_volume.png b/editor/icons/icon_volume.png
index 2ce013cb03..2ce013cb03 100644
--- a/tools/editor/icons/icon_volume.png
+++ b/editor/icons/icon_volume.png
Binary files differ
diff --git a/tools/editor/icons/icon_vu_db.png b/editor/icons/icon_vu_db.png
index 405a929e2a..405a929e2a 100644
--- a/tools/editor/icons/icon_vu_db.png
+++ b/editor/icons/icon_vu_db.png
Binary files differ
diff --git a/tools/editor/icons/icon_vu_empty.png b/editor/icons/icon_vu_empty.png
index b749e1f2ca..b749e1f2ca 100644
--- a/tools/editor/icons/icon_vu_empty.png
+++ b/editor/icons/icon_vu_empty.png
Binary files differ
diff --git a/tools/editor/icons/icon_vu_full.png b/editor/icons/icon_vu_full.png
index cb2b30d397..cb2b30d397 100644
--- a/tools/editor/icons/icon_vu_full.png
+++ b/editor/icons/icon_vu_full.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_no_preview.png b/editor/icons/icon_wait_no_preview.png
index 5d20cd99ec..5d20cd99ec 100644
--- a/tools/editor/icons/icon_wait_no_preview.png
+++ b/editor/icons/icon_wait_no_preview.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_1.png b/editor/icons/icon_wait_preview_1.png
index 0aab42e04a..0aab42e04a 100644
--- a/tools/editor/icons/icon_wait_preview_1.png
+++ b/editor/icons/icon_wait_preview_1.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_2.png b/editor/icons/icon_wait_preview_2.png
index f476b9ce1f..f476b9ce1f 100644
--- a/tools/editor/icons/icon_wait_preview_2.png
+++ b/editor/icons/icon_wait_preview_2.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_3.png b/editor/icons/icon_wait_preview_3.png
index 2775d1ef43..2775d1ef43 100644
--- a/tools/editor/icons/icon_wait_preview_3.png
+++ b/editor/icons/icon_wait_preview_3.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_4.png b/editor/icons/icon_wait_preview_4.png
index 2eaa86fec9..2eaa86fec9 100644
--- a/tools/editor/icons/icon_wait_preview_4.png
+++ b/editor/icons/icon_wait_preview_4.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_5.png b/editor/icons/icon_wait_preview_5.png
index 6590644bc1..6590644bc1 100644
--- a/tools/editor/icons/icon_wait_preview_5.png
+++ b/editor/icons/icon_wait_preview_5.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_6.png b/editor/icons/icon_wait_preview_6.png
index 307e412310..307e412310 100644
--- a/tools/editor/icons/icon_wait_preview_6.png
+++ b/editor/icons/icon_wait_preview_6.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_7.png b/editor/icons/icon_wait_preview_7.png
index b0edc94d93..b0edc94d93 100644
--- a/tools/editor/icons/icon_wait_preview_7.png
+++ b/editor/icons/icon_wait_preview_7.png
Binary files differ
diff --git a/tools/editor/icons/icon_wait_preview_8.png b/editor/icons/icon_wait_preview_8.png
index 67a2f48ec3..67a2f48ec3 100644
--- a/tools/editor/icons/icon_wait_preview_8.png
+++ b/editor/icons/icon_wait_preview_8.png
Binary files differ
diff --git a/tools/editor/icons/icon_warning.png b/editor/icons/icon_warning.png
index 451beba820..451beba820 100644
--- a/tools/editor/icons/icon_warning.png
+++ b/editor/icons/icon_warning.png
Binary files differ
diff --git a/tools/editor/icons/icon_window_dialog.png b/editor/icons/icon_window_dialog.png
index 8591b15613..8591b15613 100644
--- a/tools/editor/icons/icon_window_dialog.png
+++ b/editor/icons/icon_window_dialog.png
Binary files differ
diff --git a/tools/editor/icons/icon_world.png b/editor/icons/icon_world.png
index d54b979cad..d54b979cad 100644
--- a/tools/editor/icons/icon_world.png
+++ b/editor/icons/icon_world.png
Binary files differ
diff --git a/tools/editor/icons/icon_world_2d.png b/editor/icons/icon_world_2d.png
index ebe54262ff..ebe54262ff 100644
--- a/tools/editor/icons/icon_world_2d.png
+++ b/editor/icons/icon_world_2d.png
Binary files differ
diff --git a/tools/editor/icons/icon_world_environment.png b/editor/icons/icon_world_environment.png
index d9f1323386..d9f1323386 100644
--- a/tools/editor/icons/icon_world_environment.png
+++ b/editor/icons/icon_world_environment.png
Binary files differ
diff --git a/tools/editor/icons/icon_y_sort.png b/editor/icons/icon_y_sort.png
index 585956983c..585956983c 100644
--- a/tools/editor/icons/icon_y_sort.png
+++ b/editor/icons/icon_y_sort.png
Binary files differ
diff --git a/tools/editor/icons/icon_zoom.png b/editor/icons/icon_zoom.png
index f3748803cf..f3748803cf 100644
--- a/tools/editor/icons/icon_zoom.png
+++ b/editor/icons/icon_zoom.png
Binary files differ
diff --git a/tools/editor/icons/icon_zoom_less.png b/editor/icons/icon_zoom_less.png
index fd8ef9075e..fd8ef9075e 100644
--- a/tools/editor/icons/icon_zoom_less.png
+++ b/editor/icons/icon_zoom_less.png
Binary files differ
diff --git a/tools/editor/icons/icon_zoom_more.png b/editor/icons/icon_zoom_more.png
index 8e818db1ee..8e818db1ee 100644
--- a/tools/editor/icons/icon_zoom_more.png
+++ b/editor/icons/icon_zoom_more.png
Binary files differ
diff --git a/tools/editor/icons/icon_zoom_reset.png b/editor/icons/icon_zoom_reset.png
index fa8a9d197e..fa8a9d197e 100644
--- a/tools/editor/icons/icon_zoom_reset.png
+++ b/editor/icons/icon_zoom_reset.png
Binary files differ
diff --git a/tools/editor/icons/source/icon_accept_dialog.svg b/editor/icons/source/icon_accept_dialog.svg
index 9f82b30c94..9f82b30c94 100644
--- a/tools/editor/icons/source/icon_accept_dialog.svg
+++ b/editor/icons/source/icon_accept_dialog.svg
diff --git a/tools/editor/icons/source/icon_add_track.svg b/editor/icons/source/icon_add_track.svg
index d19448efb0..d19448efb0 100644
--- a/tools/editor/icons/source/icon_add_track.svg
+++ b/editor/icons/source/icon_add_track.svg
diff --git a/tools/editor/icons/source/icon_anchor.svg b/editor/icons/source/icon_anchor.svg
index 6b10be040b..6b10be040b 100644
--- a/tools/editor/icons/source/icon_anchor.svg
+++ b/editor/icons/source/icon_anchor.svg
diff --git a/tools/editor/icons/source/icon_animated_sprite.svg b/editor/icons/source/icon_animated_sprite.svg
index 36ccd8bca2..36ccd8bca2 100644
--- a/tools/editor/icons/source/icon_animated_sprite.svg
+++ b/editor/icons/source/icon_animated_sprite.svg
diff --git a/tools/editor/icons/source/icon_animated_sprite_3d.svg b/editor/icons/source/icon_animated_sprite_3d.svg
index f088c9e32d..f088c9e32d 100644
--- a/tools/editor/icons/source/icon_animated_sprite_3d.svg
+++ b/editor/icons/source/icon_animated_sprite_3d.svg
diff --git a/tools/editor/icons/source/icon_animation.svg b/editor/icons/source/icon_animation.svg
index 371979345f..371979345f 100644
--- a/tools/editor/icons/source/icon_animation.svg
+++ b/editor/icons/source/icon_animation.svg
diff --git a/tools/editor/icons/source/icon_animation_player.svg b/editor/icons/source/icon_animation_player.svg
index add4d5ac42..add4d5ac42 100644
--- a/tools/editor/icons/source/icon_animation_player.svg
+++ b/editor/icons/source/icon_animation_player.svg
diff --git a/tools/editor/icons/source/icon_animation_tree_player.svg b/editor/icons/source/icon_animation_tree_player.svg
index ab81cb226a..ab81cb226a 100644
--- a/tools/editor/icons/source/icon_animation_tree_player.svg
+++ b/editor/icons/source/icon_animation_tree_player.svg
diff --git a/tools/editor/icons/source/icon_area.svg b/editor/icons/source/icon_area.svg
index d16ad26e23..d16ad26e23 100644
--- a/tools/editor/icons/source/icon_area.svg
+++ b/editor/icons/source/icon_area.svg
diff --git a/tools/editor/icons/source/icon_area_2d.svg b/editor/icons/source/icon_area_2d.svg
index ef7b16dd06..ef7b16dd06 100644
--- a/tools/editor/icons/source/icon_area_2d.svg
+++ b/editor/icons/source/icon_area_2d.svg
diff --git a/tools/editor/icons/source/icon_arrow_left.svg b/editor/icons/source/icon_arrow_left.svg
index 75a9ef0d68..75a9ef0d68 100644
--- a/tools/editor/icons/source/icon_arrow_left.svg
+++ b/editor/icons/source/icon_arrow_left.svg
diff --git a/tools/editor/icons/source/icon_arrow_right.svg b/editor/icons/source/icon_arrow_right.svg
index a7600699f7..a7600699f7 100644
--- a/tools/editor/icons/source/icon_arrow_right.svg
+++ b/editor/icons/source/icon_arrow_right.svg
diff --git a/tools/editor/icons/source/icon_arrow_up.svg b/editor/icons/source/icon_arrow_up.svg
index c1839cd69e..c1839cd69e 100644
--- a/tools/editor/icons/source/icon_arrow_up.svg
+++ b/editor/icons/source/icon_arrow_up.svg
diff --git a/tools/editor/icons/source/icon_atlas_texture.svg b/editor/icons/source/icon_atlas_texture.svg
index 10c8b745b6..10c8b745b6 100644
--- a/tools/editor/icons/source/icon_atlas_texture.svg
+++ b/editor/icons/source/icon_atlas_texture.svg
diff --git a/tools/editor/icons/source/icon_audio_stream_gibberish.svg b/editor/icons/source/icon_audio_stream_gibberish.svg
index 82b48c7004..82b48c7004 100644
--- a/tools/editor/icons/source/icon_audio_stream_gibberish.svg
+++ b/editor/icons/source/icon_audio_stream_gibberish.svg
diff --git a/tools/editor/icons/source/icon_auto_play.svg b/editor/icons/source/icon_auto_play.svg
index d4e1068ebf..d4e1068ebf 100644
--- a/tools/editor/icons/source/icon_auto_play.svg
+++ b/editor/icons/source/icon_auto_play.svg
diff --git a/tools/editor/icons/source/icon_back.svg b/editor/icons/source/icon_back.svg
index 597a1c3068..597a1c3068 100644
--- a/tools/editor/icons/source/icon_back.svg
+++ b/editor/icons/source/icon_back.svg
diff --git a/tools/editor/icons/source/icon_back_buffer_copy.svg b/editor/icons/source/icon_back_buffer_copy.svg
index 17d83ed73f..17d83ed73f 100644
--- a/tools/editor/icons/source/icon_back_buffer_copy.svg
+++ b/editor/icons/source/icon_back_buffer_copy.svg
diff --git a/tools/editor/icons/source/icon_bake.svg b/editor/icons/source/icon_bake.svg
index ca07bca379..ca07bca379 100644
--- a/tools/editor/icons/source/icon_bake.svg
+++ b/editor/icons/source/icon_bake.svg
diff --git a/tools/editor/icons/source/icon_baked_light.svg b/editor/icons/source/icon_baked_light.svg
index 98dc3135f6..98dc3135f6 100644
--- a/tools/editor/icons/source/icon_baked_light.svg
+++ b/editor/icons/source/icon_baked_light.svg
diff --git a/tools/editor/icons/source/icon_baked_light_instance.svg b/editor/icons/source/icon_baked_light_instance.svg
index d854378f12..d854378f12 100644
--- a/tools/editor/icons/source/icon_baked_light_instance.svg
+++ b/editor/icons/source/icon_baked_light_instance.svg
diff --git a/tools/editor/icons/source/icon_baked_light_sampler.svg b/editor/icons/source/icon_baked_light_sampler.svg
index 2dc7c39621..2dc7c39621 100644
--- a/tools/editor/icons/source/icon_baked_light_sampler.svg
+++ b/editor/icons/source/icon_baked_light_sampler.svg
diff --git a/tools/editor/icons/source/icon_bit_map.svg b/editor/icons/source/icon_bit_map.svg
index fbaf573af6..fbaf573af6 100644
--- a/tools/editor/icons/source/icon_bit_map.svg
+++ b/editor/icons/source/icon_bit_map.svg
diff --git a/tools/editor/icons/source/icon_bitmap_font.svg b/editor/icons/source/icon_bitmap_font.svg
index 70749923d5..70749923d5 100644
--- a/tools/editor/icons/source/icon_bitmap_font.svg
+++ b/editor/icons/source/icon_bitmap_font.svg
diff --git a/tools/editor/icons/source/icon_blend.svg b/editor/icons/source/icon_blend.svg
index 64d2aeec83..64d2aeec83 100644
--- a/tools/editor/icons/source/icon_blend.svg
+++ b/editor/icons/source/icon_blend.svg
diff --git a/tools/editor/icons/source/icon_bone.svg b/editor/icons/source/icon_bone.svg
index c87902a336..c87902a336 100644
--- a/tools/editor/icons/source/icon_bone.svg
+++ b/editor/icons/source/icon_bone.svg
diff --git a/tools/editor/icons/source/icon_bone_attachment.svg b/editor/icons/source/icon_bone_attachment.svg
index 5cb85c3c17..5cb85c3c17 100644
--- a/tools/editor/icons/source/icon_bone_attachment.svg
+++ b/editor/icons/source/icon_bone_attachment.svg
diff --git a/tools/editor/icons/source/icon_bone_track.svg b/editor/icons/source/icon_bone_track.svg
index cdaab7e34a..cdaab7e34a 100644
--- a/tools/editor/icons/source/icon_bone_track.svg
+++ b/editor/icons/source/icon_bone_track.svg
diff --git a/tools/editor/icons/source/icon_bool.svg b/editor/icons/source/icon_bool.svg
index e471871adf..e471871adf 100644
--- a/tools/editor/icons/source/icon_bool.svg
+++ b/editor/icons/source/icon_bool.svg
diff --git a/tools/editor/icons/source/icon_box_shape.svg b/editor/icons/source/icon_box_shape.svg
index 04aaf16ebc..04aaf16ebc 100644
--- a/tools/editor/icons/source/icon_box_shape.svg
+++ b/editor/icons/source/icon_box_shape.svg
diff --git a/tools/editor/icons/source/icon_button.svg b/editor/icons/source/icon_button.svg
index 54644ecb9b..54644ecb9b 100644
--- a/tools/editor/icons/source/icon_button.svg
+++ b/editor/icons/source/icon_button.svg
diff --git a/tools/editor/icons/source/icon_button_group.svg b/editor/icons/source/icon_button_group.svg
index 9d5df99deb..9d5df99deb 100644
--- a/tools/editor/icons/source/icon_button_group.svg
+++ b/editor/icons/source/icon_button_group.svg
diff --git a/tools/editor/icons/source/icon_camera.svg b/editor/icons/source/icon_camera.svg
index 55d4aa698d..55d4aa698d 100644
--- a/tools/editor/icons/source/icon_camera.svg
+++ b/editor/icons/source/icon_camera.svg
diff --git a/tools/editor/icons/source/icon_camera_2d.svg b/editor/icons/source/icon_camera_2d.svg
index 1be8c0f984..1be8c0f984 100644
--- a/tools/editor/icons/source/icon_camera_2d.svg
+++ b/editor/icons/source/icon_camera_2d.svg
diff --git a/tools/editor/icons/source/icon_canvas_item.svg b/editor/icons/source/icon_canvas_item.svg
index d15a9a71b7..d15a9a71b7 100644
--- a/tools/editor/icons/source/icon_canvas_item.svg
+++ b/editor/icons/source/icon_canvas_item.svg
diff --git a/tools/editor/icons/source/icon_canvas_item_material.svg b/editor/icons/source/icon_canvas_item_material.svg
index ce8fd4b7de..ce8fd4b7de 100644
--- a/tools/editor/icons/source/icon_canvas_item_material.svg
+++ b/editor/icons/source/icon_canvas_item_material.svg
diff --git a/tools/editor/icons/source/icon_canvas_item_shader.svg b/editor/icons/source/icon_canvas_item_shader.svg
index 6d1d7e6bb1..6d1d7e6bb1 100644
--- a/tools/editor/icons/source/icon_canvas_item_shader.svg
+++ b/editor/icons/source/icon_canvas_item_shader.svg
diff --git a/tools/editor/icons/source/icon_canvas_item_shader_graph.svg b/editor/icons/source/icon_canvas_item_shader_graph.svg
index 84575ad388..84575ad388 100644
--- a/tools/editor/icons/source/icon_canvas_item_shader_graph.svg
+++ b/editor/icons/source/icon_canvas_item_shader_graph.svg
diff --git a/tools/editor/icons/source/icon_canvas_layer.svg b/editor/icons/source/icon_canvas_layer.svg
index 794d832eea..794d832eea 100644
--- a/tools/editor/icons/source/icon_canvas_layer.svg
+++ b/editor/icons/source/icon_canvas_layer.svg
diff --git a/tools/editor/icons/source/icon_canvas_modulate.svg b/editor/icons/source/icon_canvas_modulate.svg
index 8f8bd55f82..8f8bd55f82 100644
--- a/tools/editor/icons/source/icon_canvas_modulate.svg
+++ b/editor/icons/source/icon_canvas_modulate.svg
diff --git a/tools/editor/icons/source/icon_capsule_shape.svg b/editor/icons/source/icon_capsule_shape.svg
index dcc6e8c00f..dcc6e8c00f 100644
--- a/tools/editor/icons/source/icon_capsule_shape.svg
+++ b/editor/icons/source/icon_capsule_shape.svg
diff --git a/tools/editor/icons/source/icon_capsule_shape_2d.svg b/editor/icons/source/icon_capsule_shape_2d.svg
index 13c6648368..13c6648368 100644
--- a/tools/editor/icons/source/icon_capsule_shape_2d.svg
+++ b/editor/icons/source/icon_capsule_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_center_container.svg b/editor/icons/source/icon_center_container.svg
index 31262f8494..31262f8494 100644
--- a/tools/editor/icons/source/icon_center_container.svg
+++ b/editor/icons/source/icon_center_container.svg
diff --git a/tools/editor/icons/source/icon_check_box.svg b/editor/icons/source/icon_check_box.svg
index 1068b424bd..1068b424bd 100644
--- a/tools/editor/icons/source/icon_check_box.svg
+++ b/editor/icons/source/icon_check_box.svg
diff --git a/tools/editor/icons/source/icon_check_button.svg b/editor/icons/source/icon_check_button.svg
index 1dddc7bf43..1dddc7bf43 100644
--- a/tools/editor/icons/source/icon_check_button.svg
+++ b/editor/icons/source/icon_check_button.svg
diff --git a/tools/editor/icons/source/icon_circle_shape_2d.svg b/editor/icons/source/icon_circle_shape_2d.svg
index 56ac538672..56ac538672 100644
--- a/tools/editor/icons/source/icon_circle_shape_2d.svg
+++ b/editor/icons/source/icon_circle_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_class_list.svg b/editor/icons/source/icon_class_list.svg
index 326174e566..326174e566 100644
--- a/tools/editor/icons/source/icon_class_list.svg
+++ b/editor/icons/source/icon_class_list.svg
diff --git a/tools/editor/icons/source/icon_close.svg b/editor/icons/source/icon_close.svg
index 65b71ae860..65b71ae860 100644
--- a/tools/editor/icons/source/icon_close.svg
+++ b/editor/icons/source/icon_close.svg
diff --git a/tools/editor/icons/source/icon_collapse.svg b/editor/icons/source/icon_collapse.svg
index a1c55e92de..a1c55e92de 100644
--- a/tools/editor/icons/source/icon_collapse.svg
+++ b/editor/icons/source/icon_collapse.svg
diff --git a/tools/editor/icons/source/icon_collision_2d.svg b/editor/icons/source/icon_collision_2d.svg
index 29905795bd..29905795bd 100644
--- a/tools/editor/icons/source/icon_collision_2d.svg
+++ b/editor/icons/source/icon_collision_2d.svg
diff --git a/tools/editor/icons/source/icon_collision_polygon.svg b/editor/icons/source/icon_collision_polygon.svg
index 41f20abb5f..41f20abb5f 100644
--- a/tools/editor/icons/source/icon_collision_polygon.svg
+++ b/editor/icons/source/icon_collision_polygon.svg
diff --git a/tools/editor/icons/source/icon_collision_shape.svg b/editor/icons/source/icon_collision_shape.svg
index 066e3bc0fd..066e3bc0fd 100644
--- a/tools/editor/icons/source/icon_collision_shape.svg
+++ b/editor/icons/source/icon_collision_shape.svg
diff --git a/tools/editor/icons/source/icon_collision_shape_2d.svg b/editor/icons/source/icon_collision_shape_2d.svg
index e0a750c946..e0a750c946 100644
--- a/tools/editor/icons/source/icon_collision_shape_2d.svg
+++ b/editor/icons/source/icon_collision_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_color.svg b/editor/icons/source/icon_color.svg
index c46f64b8ed..c46f64b8ed 100644
--- a/tools/editor/icons/source/icon_color.svg
+++ b/editor/icons/source/icon_color.svg
diff --git a/tools/editor/icons/source/icon_color_pick.svg b/editor/icons/source/icon_color_pick.svg
index bbb05fc6b6..bbb05fc6b6 100644
--- a/tools/editor/icons/source/icon_color_pick.svg
+++ b/editor/icons/source/icon_color_pick.svg
diff --git a/tools/editor/icons/source/icon_color_picker.svg b/editor/icons/source/icon_color_picker.svg
index 0efd276c50..0efd276c50 100644
--- a/tools/editor/icons/source/icon_color_picker.svg
+++ b/editor/icons/source/icon_color_picker.svg
diff --git a/tools/editor/icons/source/icon_color_picker_button.svg b/editor/icons/source/icon_color_picker_button.svg
index 4e4fb8cc1b..4e4fb8cc1b 100644
--- a/tools/editor/icons/source/icon_color_picker_button.svg
+++ b/editor/icons/source/icon_color_picker_button.svg
diff --git a/tools/editor/icons/source/icon_color_ramp.svg b/editor/icons/source/icon_color_ramp.svg
index ff23cdba8d..ff23cdba8d 100644
--- a/tools/editor/icons/source/icon_color_ramp.svg
+++ b/editor/icons/source/icon_color_ramp.svg
diff --git a/tools/editor/icons/source/icon_color_rect.svg b/editor/icons/source/icon_color_rect.svg
index 76bf6596a9..76bf6596a9 100644
--- a/tools/editor/icons/source/icon_color_rect.svg
+++ b/editor/icons/source/icon_color_rect.svg
diff --git a/tools/editor/icons/source/icon_concave_polygon_shape.svg b/editor/icons/source/icon_concave_polygon_shape.svg
index b0e0fe63ce..b0e0fe63ce 100644
--- a/tools/editor/icons/source/icon_concave_polygon_shape.svg
+++ b/editor/icons/source/icon_concave_polygon_shape.svg
diff --git a/tools/editor/icons/source/icon_concave_polygon_shape_2d.svg b/editor/icons/source/icon_concave_polygon_shape_2d.svg
index 624105e5a8..624105e5a8 100644
--- a/tools/editor/icons/source/icon_concave_polygon_shape_2d.svg
+++ b/editor/icons/source/icon_concave_polygon_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_cone_twist_joint.svg b/editor/icons/source/icon_cone_twist_joint.svg
index 4799deb1d5..4799deb1d5 100644
--- a/tools/editor/icons/source/icon_cone_twist_joint.svg
+++ b/editor/icons/source/icon_cone_twist_joint.svg
diff --git a/tools/editor/icons/source/icon_confirmation_dialog.svg b/editor/icons/source/icon_confirmation_dialog.svg
index 49dbc21e92..49dbc21e92 100644
--- a/tools/editor/icons/source/icon_confirmation_dialog.svg
+++ b/editor/icons/source/icon_confirmation_dialog.svg
diff --git a/tools/editor/icons/source/icon_connect.svg b/editor/icons/source/icon_connect.svg
index 745d3cc436..745d3cc436 100644
--- a/tools/editor/icons/source/icon_connect.svg
+++ b/editor/icons/source/icon_connect.svg
diff --git a/tools/editor/icons/source/icon_connection_and_groups.svg b/editor/icons/source/icon_connection_and_groups.svg
index 5468312b4b..5468312b4b 100644
--- a/tools/editor/icons/source/icon_connection_and_groups.svg
+++ b/editor/icons/source/icon_connection_and_groups.svg
diff --git a/tools/editor/icons/source/icon_container.svg b/editor/icons/source/icon_container.svg
index 2d39efafee..2d39efafee 100644
--- a/tools/editor/icons/source/icon_container.svg
+++ b/editor/icons/source/icon_container.svg
diff --git a/tools/editor/icons/source/icon_control.svg b/editor/icons/source/icon_control.svg
index 675a9f5c43..675a9f5c43 100644
--- a/tools/editor/icons/source/icon_control.svg
+++ b/editor/icons/source/icon_control.svg
diff --git a/tools/editor/icons/source/icon_control_align_bottom_center.svg b/editor/icons/source/icon_control_align_bottom_center.svg
index d6c660bb2d..d6c660bb2d 100644
--- a/tools/editor/icons/source/icon_control_align_bottom_center.svg
+++ b/editor/icons/source/icon_control_align_bottom_center.svg
diff --git a/tools/editor/icons/source/icon_control_align_bottom_left.svg b/editor/icons/source/icon_control_align_bottom_left.svg
index 7a234b10ad..7a234b10ad 100644
--- a/tools/editor/icons/source/icon_control_align_bottom_left.svg
+++ b/editor/icons/source/icon_control_align_bottom_left.svg
diff --git a/tools/editor/icons/source/icon_control_align_bottom_right.svg b/editor/icons/source/icon_control_align_bottom_right.svg
index a4ba9a552a..a4ba9a552a 100644
--- a/tools/editor/icons/source/icon_control_align_bottom_right.svg
+++ b/editor/icons/source/icon_control_align_bottom_right.svg
diff --git a/tools/editor/icons/source/icon_control_align_bottom_wide.svg b/editor/icons/source/icon_control_align_bottom_wide.svg
index 93352dd3f5..93352dd3f5 100644
--- a/tools/editor/icons/source/icon_control_align_bottom_wide.svg
+++ b/editor/icons/source/icon_control_align_bottom_wide.svg
diff --git a/tools/editor/icons/source/icon_control_align_center.svg b/editor/icons/source/icon_control_align_center.svg
index 0c34d13def..0c34d13def 100644
--- a/tools/editor/icons/source/icon_control_align_center.svg
+++ b/editor/icons/source/icon_control_align_center.svg
diff --git a/tools/editor/icons/source/icon_control_align_center_left.svg b/editor/icons/source/icon_control_align_center_left.svg
index ea62c9457d..ea62c9457d 100644
--- a/tools/editor/icons/source/icon_control_align_center_left.svg
+++ b/editor/icons/source/icon_control_align_center_left.svg
diff --git a/tools/editor/icons/source/icon_control_align_center_right.svg b/editor/icons/source/icon_control_align_center_right.svg
index 3212ce8538..3212ce8538 100644
--- a/tools/editor/icons/source/icon_control_align_center_right.svg
+++ b/editor/icons/source/icon_control_align_center_right.svg
diff --git a/tools/editor/icons/source/icon_control_align_left_center.svg b/editor/icons/source/icon_control_align_left_center.svg
index 716b6a2fd0..716b6a2fd0 100644
--- a/tools/editor/icons/source/icon_control_align_left_center.svg
+++ b/editor/icons/source/icon_control_align_left_center.svg
diff --git a/tools/editor/icons/source/icon_control_align_left_wide.svg b/editor/icons/source/icon_control_align_left_wide.svg
index 7092c78508..7092c78508 100644
--- a/tools/editor/icons/source/icon_control_align_left_wide.svg
+++ b/editor/icons/source/icon_control_align_left_wide.svg
diff --git a/tools/editor/icons/source/icon_control_align_right_center.svg b/editor/icons/source/icon_control_align_right_center.svg
index 7e7e4f2b23..7e7e4f2b23 100644
--- a/tools/editor/icons/source/icon_control_align_right_center.svg
+++ b/editor/icons/source/icon_control_align_right_center.svg
diff --git a/tools/editor/icons/source/icon_control_align_right_wide.svg b/editor/icons/source/icon_control_align_right_wide.svg
index ef2d105bd8..ef2d105bd8 100644
--- a/tools/editor/icons/source/icon_control_align_right_wide.svg
+++ b/editor/icons/source/icon_control_align_right_wide.svg
diff --git a/tools/editor/icons/source/icon_control_align_top_center.svg b/editor/icons/source/icon_control_align_top_center.svg
index a5b60846f4..a5b60846f4 100644
--- a/tools/editor/icons/source/icon_control_align_top_center.svg
+++ b/editor/icons/source/icon_control_align_top_center.svg
diff --git a/tools/editor/icons/source/icon_control_align_top_left.svg b/editor/icons/source/icon_control_align_top_left.svg
index 9f4631cf31..9f4631cf31 100644
--- a/tools/editor/icons/source/icon_control_align_top_left.svg
+++ b/editor/icons/source/icon_control_align_top_left.svg
diff --git a/tools/editor/icons/source/icon_control_align_top_right.svg b/editor/icons/source/icon_control_align_top_right.svg
index d968ba3d09..d968ba3d09 100644
--- a/tools/editor/icons/source/icon_control_align_top_right.svg
+++ b/editor/icons/source/icon_control_align_top_right.svg
diff --git a/tools/editor/icons/source/icon_control_align_top_wide.svg b/editor/icons/source/icon_control_align_top_wide.svg
index 886ef60fe0..886ef60fe0 100644
--- a/tools/editor/icons/source/icon_control_align_top_wide.svg
+++ b/editor/icons/source/icon_control_align_top_wide.svg
diff --git a/tools/editor/icons/source/icon_control_align_wide.svg b/editor/icons/source/icon_control_align_wide.svg
index 3f58ed93b6..3f58ed93b6 100644
--- a/tools/editor/icons/source/icon_control_align_wide.svg
+++ b/editor/icons/source/icon_control_align_wide.svg
diff --git a/tools/editor/icons/source/icon_control_hcenter_wide.svg b/editor/icons/source/icon_control_hcenter_wide.svg
index 3aafa0340e..3aafa0340e 100644
--- a/tools/editor/icons/source/icon_control_hcenter_wide.svg
+++ b/editor/icons/source/icon_control_hcenter_wide.svg
diff --git a/tools/editor/icons/source/icon_control_vcenter_wide.svg b/editor/icons/source/icon_control_vcenter_wide.svg
index 96fd44f3c8..96fd44f3c8 100644
--- a/tools/editor/icons/source/icon_control_vcenter_wide.svg
+++ b/editor/icons/source/icon_control_vcenter_wide.svg
diff --git a/tools/editor/icons/source/icon_convex_polygon_shape.svg b/editor/icons/source/icon_convex_polygon_shape.svg
index b867a58f6f..b867a58f6f 100644
--- a/tools/editor/icons/source/icon_convex_polygon_shape.svg
+++ b/editor/icons/source/icon_convex_polygon_shape.svg
diff --git a/tools/editor/icons/source/icon_convex_polygon_shape_2d.svg b/editor/icons/source/icon_convex_polygon_shape_2d.svg
index 3b55df7fba..3b55df7fba 100644
--- a/tools/editor/icons/source/icon_convex_polygon_shape_2d.svg
+++ b/editor/icons/source/icon_convex_polygon_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_copy_node_path.svg b/editor/icons/source/icon_copy_node_path.svg
index 9f33c5e54d..9f33c5e54d 100644
--- a/tools/editor/icons/source/icon_copy_node_path.svg
+++ b/editor/icons/source/icon_copy_node_path.svg
diff --git a/tools/editor/icons/source/icon_create_new_scene_from.svg b/editor/icons/source/icon_create_new_scene_from.svg
index 529553bbd3..529553bbd3 100644
--- a/tools/editor/icons/source/icon_create_new_scene_from.svg
+++ b/editor/icons/source/icon_create_new_scene_from.svg
diff --git a/tools/editor/icons/source/icon_cube_map.svg b/editor/icons/source/icon_cube_map.svg
index 4fd86b1233..4fd86b1233 100644
--- a/tools/editor/icons/source/icon_cube_map.svg
+++ b/editor/icons/source/icon_cube_map.svg
diff --git a/tools/editor/icons/source/icon_curve_2d.svg b/editor/icons/source/icon_curve_2d.svg
index 34719e37de..34719e37de 100644
--- a/tools/editor/icons/source/icon_curve_2d.svg
+++ b/editor/icons/source/icon_curve_2d.svg
diff --git a/tools/editor/icons/source/icon_curve_3d.svg b/editor/icons/source/icon_curve_3d.svg
index 66034968b2..66034968b2 100644
--- a/tools/editor/icons/source/icon_curve_3d.svg
+++ b/editor/icons/source/icon_curve_3d.svg
diff --git a/tools/editor/icons/source/icon_curve_close.svg b/editor/icons/source/icon_curve_close.svg
index 15909df7c8..15909df7c8 100644
--- a/tools/editor/icons/source/icon_curve_close.svg
+++ b/editor/icons/source/icon_curve_close.svg
diff --git a/tools/editor/icons/source/icon_curve_constant.svg b/editor/icons/source/icon_curve_constant.svg
index 6d9a7dc959..6d9a7dc959 100644
--- a/tools/editor/icons/source/icon_curve_constant.svg
+++ b/editor/icons/source/icon_curve_constant.svg
diff --git a/tools/editor/icons/source/icon_curve_create.svg b/editor/icons/source/icon_curve_create.svg
index 8ab578e9a0..8ab578e9a0 100644
--- a/tools/editor/icons/source/icon_curve_create.svg
+++ b/editor/icons/source/icon_curve_create.svg
diff --git a/tools/editor/icons/source/icon_curve_curve.svg b/editor/icons/source/icon_curve_curve.svg
index e3b6b64a4c..e3b6b64a4c 100644
--- a/tools/editor/icons/source/icon_curve_curve.svg
+++ b/editor/icons/source/icon_curve_curve.svg
diff --git a/tools/editor/icons/source/icon_curve_delete.svg b/editor/icons/source/icon_curve_delete.svg
index f40dd1eeb1..f40dd1eeb1 100644
--- a/tools/editor/icons/source/icon_curve_delete.svg
+++ b/editor/icons/source/icon_curve_delete.svg
diff --git a/tools/editor/icons/source/icon_curve_edit.svg b/editor/icons/source/icon_curve_edit.svg
index f695e96b8c..f695e96b8c 100644
--- a/tools/editor/icons/source/icon_curve_edit.svg
+++ b/editor/icons/source/icon_curve_edit.svg
diff --git a/tools/editor/icons/source/icon_curve_in.svg b/editor/icons/source/icon_curve_in.svg
index 9dc033aa95..9dc033aa95 100644
--- a/tools/editor/icons/source/icon_curve_in.svg
+++ b/editor/icons/source/icon_curve_in.svg
diff --git a/tools/editor/icons/source/icon_curve_in_out.svg b/editor/icons/source/icon_curve_in_out.svg
index c68f906423..c68f906423 100644
--- a/tools/editor/icons/source/icon_curve_in_out.svg
+++ b/editor/icons/source/icon_curve_in_out.svg
diff --git a/tools/editor/icons/source/icon_curve_linear.svg b/editor/icons/source/icon_curve_linear.svg
index ae7a889a71..ae7a889a71 100644
--- a/tools/editor/icons/source/icon_curve_linear.svg
+++ b/editor/icons/source/icon_curve_linear.svg
diff --git a/tools/editor/icons/source/icon_curve_out.svg b/editor/icons/source/icon_curve_out.svg
index 080aa755dc..080aa755dc 100644
--- a/tools/editor/icons/source/icon_curve_out.svg
+++ b/editor/icons/source/icon_curve_out.svg
diff --git a/tools/editor/icons/source/icon_curve_out_in.svg b/editor/icons/source/icon_curve_out_in.svg
index d2b4d06e5f..d2b4d06e5f 100644
--- a/tools/editor/icons/source/icon_curve_out_in.svg
+++ b/editor/icons/source/icon_curve_out_in.svg
diff --git a/tools/editor/icons/source/icon_damped_spring_joint_2d.svg b/editor/icons/source/icon_damped_spring_joint_2d.svg
index bf12810a6c..bf12810a6c 100644
--- a/tools/editor/icons/source/icon_damped_spring_joint_2d.svg
+++ b/editor/icons/source/icon_damped_spring_joint_2d.svg
diff --git a/tools/editor/icons/source/icon_debug_continue.svg b/editor/icons/source/icon_debug_continue.svg
index 5d9ccd5a7e..5d9ccd5a7e 100644
--- a/tools/editor/icons/source/icon_debug_continue.svg
+++ b/editor/icons/source/icon_debug_continue.svg
diff --git a/tools/editor/icons/source/icon_debug_next.svg b/editor/icons/source/icon_debug_next.svg
index 4dd9bb8c4b..4dd9bb8c4b 100644
--- a/tools/editor/icons/source/icon_debug_next.svg
+++ b/editor/icons/source/icon_debug_next.svg
diff --git a/tools/editor/icons/source/icon_debug_step.svg b/editor/icons/source/icon_debug_step.svg
index 20d11f8710..20d11f8710 100644
--- a/tools/editor/icons/source/icon_debug_step.svg
+++ b/editor/icons/source/icon_debug_step.svg
diff --git a/tools/editor/icons/source/icon_dependency_changed.svg b/editor/icons/source/icon_dependency_changed.svg
index bbcd3f0c0a..bbcd3f0c0a 100644
--- a/tools/editor/icons/source/icon_dependency_changed.svg
+++ b/editor/icons/source/icon_dependency_changed.svg
diff --git a/tools/editor/icons/source/icon_dependency_changed_hl.svg b/editor/icons/source/icon_dependency_changed_hl.svg
index 54a37695ef..54a37695ef 100644
--- a/tools/editor/icons/source/icon_dependency_changed_hl.svg
+++ b/editor/icons/source/icon_dependency_changed_hl.svg
diff --git a/tools/editor/icons/source/icon_dependency_local_changed.svg b/editor/icons/source/icon_dependency_local_changed.svg
index 799d69c4e0..799d69c4e0 100644
--- a/tools/editor/icons/source/icon_dependency_local_changed.svg
+++ b/editor/icons/source/icon_dependency_local_changed.svg
diff --git a/tools/editor/icons/source/icon_dependency_local_changed_hl.svg b/editor/icons/source/icon_dependency_local_changed_hl.svg
index 67c04c312a..67c04c312a 100644
--- a/tools/editor/icons/source/icon_dependency_local_changed_hl.svg
+++ b/editor/icons/source/icon_dependency_local_changed_hl.svg
diff --git a/tools/editor/icons/source/icon_dependency_ok.svg b/editor/icons/source/icon_dependency_ok.svg
index 76d7f54065..76d7f54065 100644
--- a/tools/editor/icons/source/icon_dependency_ok.svg
+++ b/editor/icons/source/icon_dependency_ok.svg
diff --git a/tools/editor/icons/source/icon_dependency_ok_hl.svg b/editor/icons/source/icon_dependency_ok_hl.svg
index 190458c532..190458c532 100644
--- a/tools/editor/icons/source/icon_dependency_ok_hl.svg
+++ b/editor/icons/source/icon_dependency_ok_hl.svg
diff --git a/tools/editor/icons/source/icon_directional_light.svg b/editor/icons/source/icon_directional_light.svg
index dbec755039..dbec755039 100644
--- a/tools/editor/icons/source/icon_directional_light.svg
+++ b/editor/icons/source/icon_directional_light.svg
diff --git a/tools/editor/icons/source/icon_distraction_free.svg b/editor/icons/source/icon_distraction_free.svg
index 4ae48b2fb6..4ae48b2fb6 100644
--- a/tools/editor/icons/source/icon_distraction_free.svg
+++ b/editor/icons/source/icon_distraction_free.svg
diff --git a/tools/editor/icons/source/icon_duplicate.svg b/editor/icons/source/icon_duplicate.svg
index b1d5544fc0..b1d5544fc0 100644
--- a/tools/editor/icons/source/icon_duplicate.svg
+++ b/editor/icons/source/icon_duplicate.svg
diff --git a/tools/editor/icons/source/icon_dynamic_font.svg b/editor/icons/source/icon_dynamic_font.svg
index a40c0e3408..a40c0e3408 100644
--- a/tools/editor/icons/source/icon_dynamic_font.svg
+++ b/editor/icons/source/icon_dynamic_font.svg
diff --git a/tools/editor/icons/source/icon_dynamic_font_data.svg b/editor/icons/source/icon_dynamic_font_data.svg
index 9f06172fef..9f06172fef 100644
--- a/tools/editor/icons/source/icon_dynamic_font_data.svg
+++ b/editor/icons/source/icon_dynamic_font_data.svg
diff --git a/tools/editor/icons/source/icon_edit.svg b/editor/icons/source/icon_edit.svg
index 6da05a6603..6da05a6603 100644
--- a/tools/editor/icons/source/icon_edit.svg
+++ b/editor/icons/source/icon_edit.svg
diff --git a/tools/editor/icons/source/icon_edit_key.svg b/editor/icons/source/icon_edit_key.svg
index 46795bef35..46795bef35 100644
--- a/tools/editor/icons/source/icon_edit_key.svg
+++ b/editor/icons/source/icon_edit_key.svg
diff --git a/tools/editor/icons/source/icon_edit_pivot.svg b/editor/icons/source/icon_edit_pivot.svg
index 8ae55ad8b7..8ae55ad8b7 100644
--- a/tools/editor/icons/source/icon_edit_pivot.svg
+++ b/editor/icons/source/icon_edit_pivot.svg
diff --git a/tools/editor/icons/source/icon_edit_resource.svg b/editor/icons/source/icon_edit_resource.svg
index 1950988ca2..1950988ca2 100644
--- a/tools/editor/icons/source/icon_edit_resource.svg
+++ b/editor/icons/source/icon_edit_resource.svg
diff --git a/tools/editor/icons/source/icon_editor_3d_handle.svg b/editor/icons/source/icon_editor_3d_handle.svg
index 255d1801a9..255d1801a9 100644
--- a/tools/editor/icons/source/icon_editor_3d_handle.svg
+++ b/editor/icons/source/icon_editor_3d_handle.svg
diff --git a/tools/editor/icons/source/icon_editor_handle.svg b/editor/icons/source/icon_editor_handle.svg
index 17ed2a61e7..17ed2a61e7 100644
--- a/tools/editor/icons/source/icon_editor_handle.svg
+++ b/editor/icons/source/icon_editor_handle.svg
diff --git a/tools/editor/icons/source/icon_editor_pivot.svg b/editor/icons/source/icon_editor_pivot.svg
index 8ce7d48970..8ce7d48970 100644
--- a/tools/editor/icons/source/icon_editor_pivot.svg
+++ b/editor/icons/source/icon_editor_pivot.svg
diff --git a/tools/editor/icons/source/icon_editor_plugin.svg b/editor/icons/source/icon_editor_plugin.svg
index b9460de683..b9460de683 100644
--- a/tools/editor/icons/source/icon_editor_plugin.svg
+++ b/editor/icons/source/icon_editor_plugin.svg
diff --git a/tools/editor/icons/source/icon_environment.svg b/editor/icons/source/icon_environment.svg
index 45add2c7f7..45add2c7f7 100644
--- a/tools/editor/icons/source/icon_environment.svg
+++ b/editor/icons/source/icon_environment.svg
diff --git a/tools/editor/icons/source/icon_error.svg b/editor/icons/source/icon_error.svg
index a0b04a98cb..a0b04a98cb 100644
--- a/tools/editor/icons/source/icon_error.svg
+++ b/editor/icons/source/icon_error.svg
diff --git a/tools/editor/icons/source/icon_error_sign.svg b/editor/icons/source/icon_error_sign.svg
index 01c1dbb4d5..01c1dbb4d5 100644
--- a/tools/editor/icons/source/icon_error_sign.svg
+++ b/editor/icons/source/icon_error_sign.svg
diff --git a/tools/editor/icons/source/icon_event_player.svg b/editor/icons/source/icon_event_player.svg
index 3f5f7da693..3f5f7da693 100644
--- a/tools/editor/icons/source/icon_event_player.svg
+++ b/editor/icons/source/icon_event_player.svg
diff --git a/tools/editor/icons/source/icon_favorites.svg b/editor/icons/source/icon_favorites.svg
index 12d4b56897..12d4b56897 100644
--- a/tools/editor/icons/source/icon_favorites.svg
+++ b/editor/icons/source/icon_favorites.svg
diff --git a/tools/editor/icons/source/icon_file_big.svg b/editor/icons/source/icon_file_big.svg
index 38ad9b707a..38ad9b707a 100644
--- a/tools/editor/icons/source/icon_file_big.svg
+++ b/editor/icons/source/icon_file_big.svg
diff --git a/tools/editor/icons/source/icon_file_dialog.svg b/editor/icons/source/icon_file_dialog.svg
index 9dee04c220..9dee04c220 100644
--- a/tools/editor/icons/source/icon_file_dialog.svg
+++ b/editor/icons/source/icon_file_dialog.svg
diff --git a/tools/editor/icons/source/icon_file_list.svg b/editor/icons/source/icon_file_list.svg
index 82dad29aac..82dad29aac 100644
--- a/tools/editor/icons/source/icon_file_list.svg
+++ b/editor/icons/source/icon_file_list.svg
diff --git a/tools/editor/icons/source/icon_file_server.svg b/editor/icons/source/icon_file_server.svg
index 1e1f9b6e42..1e1f9b6e42 100644
--- a/tools/editor/icons/source/icon_file_server.svg
+++ b/editor/icons/source/icon_file_server.svg
diff --git a/tools/editor/icons/source/icon_file_server_active.svg b/editor/icons/source/icon_file_server_active.svg
index f01ba578da..f01ba578da 100644
--- a/tools/editor/icons/source/icon_file_server_active.svg
+++ b/editor/icons/source/icon_file_server_active.svg
diff --git a/tools/editor/icons/source/icon_file_thumbnail.svg b/editor/icons/source/icon_file_thumbnail.svg
index 48d90dd3c6..48d90dd3c6 100644
--- a/tools/editor/icons/source/icon_file_thumbnail.svg
+++ b/editor/icons/source/icon_file_thumbnail.svg
diff --git a/tools/editor/icons/source/icon_fixed_material.svg b/editor/icons/source/icon_fixed_material.svg
index 5be74f490d..5be74f490d 100644
--- a/tools/editor/icons/source/icon_fixed_material.svg
+++ b/editor/icons/source/icon_fixed_material.svg
diff --git a/tools/editor/icons/source/icon_fixed_spatial_material.svg b/editor/icons/source/icon_fixed_spatial_material.svg
index 7ae0f93ffc..7ae0f93ffc 100644
--- a/tools/editor/icons/source/icon_fixed_spatial_material.svg
+++ b/editor/icons/source/icon_fixed_spatial_material.svg
diff --git a/tools/editor/icons/source/icon_folder.svg b/editor/icons/source/icon_folder.svg
index ca16a5737f..ca16a5737f 100644
--- a/tools/editor/icons/source/icon_folder.svg
+++ b/editor/icons/source/icon_folder.svg
diff --git a/tools/editor/icons/source/icon_folder_big.svg b/editor/icons/source/icon_folder_big.svg
index 818eaa2ba3..818eaa2ba3 100644
--- a/tools/editor/icons/source/icon_folder_big.svg
+++ b/editor/icons/source/icon_folder_big.svg
diff --git a/tools/editor/icons/source/icon_font.svg b/editor/icons/source/icon_font.svg
index 36567fe10c..36567fe10c 100644
--- a/tools/editor/icons/source/icon_font.svg
+++ b/editor/icons/source/icon_font.svg
diff --git a/tools/editor/icons/source/icon_forward.svg b/editor/icons/source/icon_forward.svg
index f6cb351cc1..f6cb351cc1 100644
--- a/tools/editor/icons/source/icon_forward.svg
+++ b/editor/icons/source/icon_forward.svg
diff --git a/tools/editor/icons/source/icon_g_d_script.svg b/editor/icons/source/icon_g_d_script.svg
index f2b8cd9343..f2b8cd9343 100644
--- a/tools/editor/icons/source/icon_g_d_script.svg
+++ b/editor/icons/source/icon_g_d_script.svg
diff --git a/tools/editor/icons/source/icon_g_i_probe.svg b/editor/icons/source/icon_g_i_probe.svg
index d803a5f63d..d803a5f63d 100644
--- a/tools/editor/icons/source/icon_g_i_probe.svg
+++ b/editor/icons/source/icon_g_i_probe.svg
diff --git a/tools/editor/icons/source/icon_g_i_probe_data.svg b/editor/icons/source/icon_g_i_probe_data.svg
index 96fa62723c..96fa62723c 100644
--- a/tools/editor/icons/source/icon_g_i_probe_data.svg
+++ b/editor/icons/source/icon_g_i_probe_data.svg
diff --git a/tools/editor/icons/source/icon_generic_6_d_o_f_joint.svg b/editor/icons/source/icon_generic_6_d_o_f_joint.svg
index 485040c6dc..485040c6dc 100644
--- a/tools/editor/icons/source/icon_generic_6_d_o_f_joint.svg
+++ b/editor/icons/source/icon_generic_6_d_o_f_joint.svg
diff --git a/tools/editor/icons/source/icon_gizmo_directional_light.svg b/editor/icons/source/icon_gizmo_directional_light.svg
index 65202877a0..65202877a0 100644
--- a/tools/editor/icons/source/icon_gizmo_directional_light.svg
+++ b/editor/icons/source/icon_gizmo_directional_light.svg
diff --git a/tools/editor/icons/source/icon_gizmo_light.svg b/editor/icons/source/icon_gizmo_light.svg
index c42d6e1f76..c42d6e1f76 100644
--- a/tools/editor/icons/source/icon_gizmo_light.svg
+++ b/editor/icons/source/icon_gizmo_light.svg
diff --git a/tools/editor/icons/source/icon_gizmo_listener.svg b/editor/icons/source/icon_gizmo_listener.svg
index 3667cbc69b..3667cbc69b 100644
--- a/tools/editor/icons/source/icon_gizmo_listener.svg
+++ b/editor/icons/source/icon_gizmo_listener.svg
diff --git a/tools/editor/icons/source/icon_gizmo_spatial_sample_player.svg b/editor/icons/source/icon_gizmo_spatial_sample_player.svg
index a734095268..a734095268 100644
--- a/tools/editor/icons/source/icon_gizmo_spatial_sample_player.svg
+++ b/editor/icons/source/icon_gizmo_spatial_sample_player.svg
diff --git a/tools/editor/icons/source/icon_gizmo_spatial_stream_player.svg b/editor/icons/source/icon_gizmo_spatial_stream_player.svg
index c333641249..c333641249 100644
--- a/tools/editor/icons/source/icon_gizmo_spatial_stream_player.svg
+++ b/editor/icons/source/icon_gizmo_spatial_stream_player.svg
diff --git a/tools/editor/icons/source/icon_godot.svg b/editor/icons/source/icon_godot.svg
index 419f23125b..419f23125b 100644
--- a/tools/editor/icons/source/icon_godot.svg
+++ b/editor/icons/source/icon_godot.svg
diff --git a/tools/editor/icons/source/icon_graph_comment.svg b/editor/icons/source/icon_graph_comment.svg
index 5ad8fc8253..5ad8fc8253 100644
--- a/tools/editor/icons/source/icon_graph_comment.svg
+++ b/editor/icons/source/icon_graph_comment.svg
diff --git a/tools/editor/icons/source/icon_graph_cube_uniform.svg b/editor/icons/source/icon_graph_cube_uniform.svg
index 63774a7431..63774a7431 100644
--- a/tools/editor/icons/source/icon_graph_cube_uniform.svg
+++ b/editor/icons/source/icon_graph_cube_uniform.svg
diff --git a/tools/editor/icons/source/icon_graph_curve_map.svg b/editor/icons/source/icon_graph_curve_map.svg
index 6c3594cb1b..6c3594cb1b 100644
--- a/tools/editor/icons/source/icon_graph_curve_map.svg
+++ b/editor/icons/source/icon_graph_curve_map.svg
diff --git a/tools/editor/icons/source/icon_graph_default_texture.svg b/editor/icons/source/icon_graph_default_texture.svg
index 8d1c78ddd7..8d1c78ddd7 100644
--- a/tools/editor/icons/source/icon_graph_default_texture.svg
+++ b/editor/icons/source/icon_graph_default_texture.svg
diff --git a/tools/editor/icons/source/icon_graph_edit.svg b/editor/icons/source/icon_graph_edit.svg
index 30d3ad96f6..30d3ad96f6 100644
--- a/tools/editor/icons/source/icon_graph_edit.svg
+++ b/editor/icons/source/icon_graph_edit.svg
diff --git a/tools/editor/icons/source/icon_graph_input.svg b/editor/icons/source/icon_graph_input.svg
index 265fb7279e..265fb7279e 100644
--- a/tools/editor/icons/source/icon_graph_input.svg
+++ b/editor/icons/source/icon_graph_input.svg
diff --git a/tools/editor/icons/source/icon_graph_node.svg b/editor/icons/source/icon_graph_node.svg
index 078b0ffe9e..078b0ffe9e 100644
--- a/tools/editor/icons/source/icon_graph_node.svg
+++ b/editor/icons/source/icon_graph_node.svg
diff --git a/tools/editor/icons/source/icon_graph_rgb.svg b/editor/icons/source/icon_graph_rgb.svg
index a00e97a104..a00e97a104 100644
--- a/tools/editor/icons/source/icon_graph_rgb.svg
+++ b/editor/icons/source/icon_graph_rgb.svg
diff --git a/tools/editor/icons/source/icon_graph_rgb_op.svg b/editor/icons/source/icon_graph_rgb_op.svg
index fdd3d3a9f4..fdd3d3a9f4 100644
--- a/tools/editor/icons/source/icon_graph_rgb_op.svg
+++ b/editor/icons/source/icon_graph_rgb_op.svg
diff --git a/tools/editor/icons/source/icon_graph_rgb_uniform.svg b/editor/icons/source/icon_graph_rgb_uniform.svg
index 359c86d61a..359c86d61a 100644
--- a/tools/editor/icons/source/icon_graph_rgb_uniform.svg
+++ b/editor/icons/source/icon_graph_rgb_uniform.svg
diff --git a/tools/editor/icons/source/icon_graph_scalar.svg b/editor/icons/source/icon_graph_scalar.svg
index 7a75ddba78..7a75ddba78 100644
--- a/tools/editor/icons/source/icon_graph_scalar.svg
+++ b/editor/icons/source/icon_graph_scalar.svg
diff --git a/tools/editor/icons/source/icon_graph_scalar_interp.svg b/editor/icons/source/icon_graph_scalar_interp.svg
index 47b619d608..47b619d608 100644
--- a/tools/editor/icons/source/icon_graph_scalar_interp.svg
+++ b/editor/icons/source/icon_graph_scalar_interp.svg
diff --git a/tools/editor/icons/source/icon_graph_scalar_op.svg b/editor/icons/source/icon_graph_scalar_op.svg
index fcb54f9aa0..fcb54f9aa0 100644
--- a/tools/editor/icons/source/icon_graph_scalar_op.svg
+++ b/editor/icons/source/icon_graph_scalar_op.svg
diff --git a/tools/editor/icons/source/icon_graph_scalar_uniform.svg b/editor/icons/source/icon_graph_scalar_uniform.svg
index e5e5edea9c..e5e5edea9c 100644
--- a/tools/editor/icons/source/icon_graph_scalar_uniform.svg
+++ b/editor/icons/source/icon_graph_scalar_uniform.svg
diff --git a/tools/editor/icons/source/icon_graph_scalars_to_vec.svg b/editor/icons/source/icon_graph_scalars_to_vec.svg
index 0f2994a606..0f2994a606 100644
--- a/tools/editor/icons/source/icon_graph_scalars_to_vec.svg
+++ b/editor/icons/source/icon_graph_scalars_to_vec.svg
diff --git a/tools/editor/icons/source/icon_graph_texscreen.svg b/editor/icons/source/icon_graph_texscreen.svg
index 89d000d7cb..89d000d7cb 100644
--- a/tools/editor/icons/source/icon_graph_texscreen.svg
+++ b/editor/icons/source/icon_graph_texscreen.svg
diff --git a/tools/editor/icons/source/icon_graph_texture_uniform.svg b/editor/icons/source/icon_graph_texture_uniform.svg
index 440f83642c..440f83642c 100644
--- a/tools/editor/icons/source/icon_graph_texture_uniform.svg
+++ b/editor/icons/source/icon_graph_texture_uniform.svg
diff --git a/tools/editor/icons/source/icon_graph_time.svg b/editor/icons/source/icon_graph_time.svg
index 77b80e920b..77b80e920b 100644
--- a/tools/editor/icons/source/icon_graph_time.svg
+++ b/editor/icons/source/icon_graph_time.svg
diff --git a/tools/editor/icons/source/icon_graph_vec_dp.svg b/editor/icons/source/icon_graph_vec_dp.svg
index 8994d8ce59..8994d8ce59 100644
--- a/tools/editor/icons/source/icon_graph_vec_dp.svg
+++ b/editor/icons/source/icon_graph_vec_dp.svg
diff --git a/tools/editor/icons/source/icon_graph_vec_interp.svg b/editor/icons/source/icon_graph_vec_interp.svg
index 885b342a54..885b342a54 100644
--- a/tools/editor/icons/source/icon_graph_vec_interp.svg
+++ b/editor/icons/source/icon_graph_vec_interp.svg
diff --git a/tools/editor/icons/source/icon_graph_vec_length.svg b/editor/icons/source/icon_graph_vec_length.svg
index aa01e3ef2a..aa01e3ef2a 100644
--- a/tools/editor/icons/source/icon_graph_vec_length.svg
+++ b/editor/icons/source/icon_graph_vec_length.svg
diff --git a/tools/editor/icons/source/icon_graph_vec_op.svg b/editor/icons/source/icon_graph_vec_op.svg
index da7540ce86..da7540ce86 100644
--- a/tools/editor/icons/source/icon_graph_vec_op.svg
+++ b/editor/icons/source/icon_graph_vec_op.svg
diff --git a/tools/editor/icons/source/icon_graph_vec_scalar_op.svg b/editor/icons/source/icon_graph_vec_scalar_op.svg
index aeb2626120..aeb2626120 100644
--- a/tools/editor/icons/source/icon_graph_vec_scalar_op.svg
+++ b/editor/icons/source/icon_graph_vec_scalar_op.svg
diff --git a/tools/editor/icons/source/icon_graph_vec_to_scalars.svg b/editor/icons/source/icon_graph_vec_to_scalars.svg
index fb58db9d78..fb58db9d78 100644
--- a/tools/editor/icons/source/icon_graph_vec_to_scalars.svg
+++ b/editor/icons/source/icon_graph_vec_to_scalars.svg
diff --git a/tools/editor/icons/source/icon_graph_vecs_to_xform.svg b/editor/icons/source/icon_graph_vecs_to_xform.svg
index f8ba3eb4b8..f8ba3eb4b8 100644
--- a/tools/editor/icons/source/icon_graph_vecs_to_xform.svg
+++ b/editor/icons/source/icon_graph_vecs_to_xform.svg
diff --git a/tools/editor/icons/source/icon_graph_vector.svg b/editor/icons/source/icon_graph_vector.svg
index e7f6bd927f..e7f6bd927f 100644
--- a/tools/editor/icons/source/icon_graph_vector.svg
+++ b/editor/icons/source/icon_graph_vector.svg
diff --git a/tools/editor/icons/source/icon_graph_vector_uniform.svg b/editor/icons/source/icon_graph_vector_uniform.svg
index 2310938af5..2310938af5 100644
--- a/tools/editor/icons/source/icon_graph_vector_uniform.svg
+++ b/editor/icons/source/icon_graph_vector_uniform.svg
diff --git a/tools/editor/icons/source/icon_graph_xform.svg b/editor/icons/source/icon_graph_xform.svg
index c9b027ee2d..c9b027ee2d 100644
--- a/tools/editor/icons/source/icon_graph_xform.svg
+++ b/editor/icons/source/icon_graph_xform.svg
diff --git a/tools/editor/icons/source/icon_graph_xform_mult.svg b/editor/icons/source/icon_graph_xform_mult.svg
index 71fca83f3d..71fca83f3d 100644
--- a/tools/editor/icons/source/icon_graph_xform_mult.svg
+++ b/editor/icons/source/icon_graph_xform_mult.svg
diff --git a/tools/editor/icons/source/icon_graph_xform_scalar_func.svg b/editor/icons/source/icon_graph_xform_scalar_func.svg
index 45fd97a671..45fd97a671 100644
--- a/tools/editor/icons/source/icon_graph_xform_scalar_func.svg
+++ b/editor/icons/source/icon_graph_xform_scalar_func.svg
diff --git a/tools/editor/icons/source/icon_graph_xform_to_vecs.svg b/editor/icons/source/icon_graph_xform_to_vecs.svg
index cc113e72fd..cc113e72fd 100644
--- a/tools/editor/icons/source/icon_graph_xform_to_vecs.svg
+++ b/editor/icons/source/icon_graph_xform_to_vecs.svg
diff --git a/tools/editor/icons/source/icon_graph_xform_uniform.svg b/editor/icons/source/icon_graph_xform_uniform.svg
index f1cdcd408c..f1cdcd408c 100644
--- a/tools/editor/icons/source/icon_graph_xform_uniform.svg
+++ b/editor/icons/source/icon_graph_xform_uniform.svg
diff --git a/tools/editor/icons/source/icon_graph_xform_vec_func.svg b/editor/icons/source/icon_graph_xform_vec_func.svg
index 0d141bc646..0d141bc646 100644
--- a/tools/editor/icons/source/icon_graph_xform_vec_func.svg
+++ b/editor/icons/source/icon_graph_xform_vec_func.svg
diff --git a/tools/editor/icons/source/icon_graph_xform_vec_imult.svg b/editor/icons/source/icon_graph_xform_vec_imult.svg
index 74dc1ba7e3..74dc1ba7e3 100644
--- a/tools/editor/icons/source/icon_graph_xform_vec_imult.svg
+++ b/editor/icons/source/icon_graph_xform_vec_imult.svg
diff --git a/tools/editor/icons/source/icon_graph_xform_vec_mult.svg b/editor/icons/source/icon_graph_xform_vec_mult.svg
index c3e59abd46..c3e59abd46 100644
--- a/tools/editor/icons/source/icon_graph_xform_vec_mult.svg
+++ b/editor/icons/source/icon_graph_xform_vec_mult.svg
diff --git a/tools/editor/icons/source/icon_grid.svg b/editor/icons/source/icon_grid.svg
index 2d9288de14..2d9288de14 100644
--- a/tools/editor/icons/source/icon_grid.svg
+++ b/editor/icons/source/icon_grid.svg
diff --git a/tools/editor/icons/source/icon_grid_container.svg b/editor/icons/source/icon_grid_container.svg
index a27578f196..a27578f196 100644
--- a/tools/editor/icons/source/icon_grid_container.svg
+++ b/editor/icons/source/icon_grid_container.svg
diff --git a/tools/editor/icons/source/icon_grid_map.svg b/editor/icons/source/icon_grid_map.svg
index 5bbea0ff2c..5bbea0ff2c 100644
--- a/tools/editor/icons/source/icon_grid_map.svg
+++ b/editor/icons/source/icon_grid_map.svg
diff --git a/tools/editor/icons/source/icon_groove_joint_2d.svg b/editor/icons/source/icon_groove_joint_2d.svg
index d05bebef48..d05bebef48 100644
--- a/tools/editor/icons/source/icon_groove_joint_2d.svg
+++ b/editor/icons/source/icon_groove_joint_2d.svg
diff --git a/tools/editor/icons/source/icon_group.svg b/editor/icons/source/icon_group.svg
index a0a2f02af5..a0a2f02af5 100644
--- a/tools/editor/icons/source/icon_group.svg
+++ b/editor/icons/source/icon_group.svg
diff --git a/tools/editor/icons/source/icon_groups.svg b/editor/icons/source/icon_groups.svg
index 00249597a4..00249597a4 100644
--- a/tools/editor/icons/source/icon_groups.svg
+++ b/editor/icons/source/icon_groups.svg
diff --git a/tools/editor/icons/source/icon_h_box_container.svg b/editor/icons/source/icon_h_box_container.svg
index f180dde93a..f180dde93a 100644
--- a/tools/editor/icons/source/icon_h_box_container.svg
+++ b/editor/icons/source/icon_h_box_container.svg
diff --git a/tools/editor/icons/source/icon_h_button_array.svg b/editor/icons/source/icon_h_button_array.svg
index 9470aeb370..9470aeb370 100644
--- a/tools/editor/icons/source/icon_h_button_array.svg
+++ b/editor/icons/source/icon_h_button_array.svg
diff --git a/tools/editor/icons/source/icon_h_scroll_bar.svg b/editor/icons/source/icon_h_scroll_bar.svg
index 2f007c7c94..2f007c7c94 100644
--- a/tools/editor/icons/source/icon_h_scroll_bar.svg
+++ b/editor/icons/source/icon_h_scroll_bar.svg
diff --git a/tools/editor/icons/source/icon_h_separator.svg b/editor/icons/source/icon_h_separator.svg
index 461299731d..461299731d 100644
--- a/tools/editor/icons/source/icon_h_separator.svg
+++ b/editor/icons/source/icon_h_separator.svg
diff --git a/tools/editor/icons/source/icon_h_slider.svg b/editor/icons/source/icon_h_slider.svg
index beee5f8b6a..beee5f8b6a 100644
--- a/tools/editor/icons/source/icon_h_slider.svg
+++ b/editor/icons/source/icon_h_slider.svg
diff --git a/tools/editor/icons/source/icon_h_split_container.svg b/editor/icons/source/icon_h_split_container.svg
index 9ca2df0ff1..9ca2df0ff1 100644
--- a/tools/editor/icons/source/icon_h_split_container.svg
+++ b/editor/icons/source/icon_h_split_container.svg
diff --git a/tools/editor/icons/source/icon_h_t_t_p_request.svg b/editor/icons/source/icon_h_t_t_p_request.svg
index f43141dd7c..f43141dd7c 100644
--- a/tools/editor/icons/source/icon_h_t_t_p_request.svg
+++ b/editor/icons/source/icon_h_t_t_p_request.svg
diff --git a/tools/editor/icons/source/icon_headphones.svg b/editor/icons/source/icon_headphones.svg
index 456a9b8d4e..456a9b8d4e 100644
--- a/tools/editor/icons/source/icon_headphones.svg
+++ b/editor/icons/source/icon_headphones.svg
diff --git a/tools/editor/icons/source/icon_help.svg b/editor/icons/source/icon_help.svg
index 01e85e0f55..01e85e0f55 100644
--- a/tools/editor/icons/source/icon_help.svg
+++ b/editor/icons/source/icon_help.svg
diff --git a/tools/editor/icons/source/icon_hidden.svg b/editor/icons/source/icon_hidden.svg
index 1d504f02fb..1d504f02fb 100644
--- a/tools/editor/icons/source/icon_hidden.svg
+++ b/editor/icons/source/icon_hidden.svg
diff --git a/tools/editor/icons/source/icon_hinge_joint.svg b/editor/icons/source/icon_hinge_joint.svg
index 767feac9d5..767feac9d5 100644
--- a/tools/editor/icons/source/icon_hinge_joint.svg
+++ b/editor/icons/source/icon_hinge_joint.svg
diff --git a/tools/editor/icons/source/icon_history.svg b/editor/icons/source/icon_history.svg
index f81390f0f5..f81390f0f5 100644
--- a/tools/editor/icons/source/icon_history.svg
+++ b/editor/icons/source/icon_history.svg
diff --git a/tools/editor/icons/source/icon_hsize.svg b/editor/icons/source/icon_hsize.svg
index f24a630770..f24a630770 100644
--- a/tools/editor/icons/source/icon_hsize.svg
+++ b/editor/icons/source/icon_hsize.svg
diff --git a/tools/editor/icons/source/icon_image.svg b/editor/icons/source/icon_image.svg
index bb15e96251..bb15e96251 100644
--- a/tools/editor/icons/source/icon_image.svg
+++ b/editor/icons/source/icon_image.svg
diff --git a/tools/editor/icons/source/icon_image_sky_box.svg b/editor/icons/source/icon_image_sky_box.svg
index 9a89c04e58..9a89c04e58 100644
--- a/tools/editor/icons/source/icon_image_sky_box.svg
+++ b/editor/icons/source/icon_image_sky_box.svg
diff --git a/tools/editor/icons/source/icon_image_texture.svg b/editor/icons/source/icon_image_texture.svg
index 39e88e592b..39e88e592b 100644
--- a/tools/editor/icons/source/icon_image_texture.svg
+++ b/editor/icons/source/icon_image_texture.svg
diff --git a/tools/editor/icons/source/icon_immediate_geometry.svg b/editor/icons/source/icon_immediate_geometry.svg
index 54bc4766d9..54bc4766d9 100644
--- a/tools/editor/icons/source/icon_immediate_geometry.svg
+++ b/editor/icons/source/icon_immediate_geometry.svg
diff --git a/tools/editor/icons/source/icon_import_check.svg b/editor/icons/source/icon_import_check.svg
index 606236d82e..606236d82e 100644
--- a/tools/editor/icons/source/icon_import_check.svg
+++ b/editor/icons/source/icon_import_check.svg
diff --git a/tools/editor/icons/source/icon_import_fail.svg b/editor/icons/source/icon_import_fail.svg
index b5d142f968..b5d142f968 100644
--- a/tools/editor/icons/source/icon_import_fail.svg
+++ b/editor/icons/source/icon_import_fail.svg
diff --git a/tools/editor/icons/source/icon_instance.svg b/editor/icons/source/icon_instance.svg
index f12e067e7a..f12e067e7a 100644
--- a/tools/editor/icons/source/icon_instance.svg
+++ b/editor/icons/source/icon_instance.svg
diff --git a/tools/editor/icons/source/icon_instance_options.svg b/editor/icons/source/icon_instance_options.svg
index a8c00bc43f..a8c00bc43f 100644
--- a/tools/editor/icons/source/icon_instance_options.svg
+++ b/editor/icons/source/icon_instance_options.svg
diff --git a/tools/editor/icons/source/icon_integer.svg b/editor/icons/source/icon_integer.svg
index d4e7a9860a..d4e7a9860a 100644
--- a/tools/editor/icons/source/icon_integer.svg
+++ b/editor/icons/source/icon_integer.svg
diff --git a/tools/editor/icons/source/icon_interp_cubic.svg b/editor/icons/source/icon_interp_cubic.svg
index 7d8d5ef70d..7d8d5ef70d 100644
--- a/tools/editor/icons/source/icon_interp_cubic.svg
+++ b/editor/icons/source/icon_interp_cubic.svg
diff --git a/tools/editor/icons/source/icon_interp_linear.svg b/editor/icons/source/icon_interp_linear.svg
index 7b1e4f2dd1..7b1e4f2dd1 100644
--- a/tools/editor/icons/source/icon_interp_linear.svg
+++ b/editor/icons/source/icon_interp_linear.svg
diff --git a/tools/editor/icons/source/icon_interp_raw.svg b/editor/icons/source/icon_interp_raw.svg
index e2e2070449..e2e2070449 100644
--- a/tools/editor/icons/source/icon_interp_raw.svg
+++ b/editor/icons/source/icon_interp_raw.svg
diff --git a/tools/editor/icons/source/icon_interp_wrap_clamp.svg b/editor/icons/source/icon_interp_wrap_clamp.svg
index 068e79ace0..068e79ace0 100644
--- a/tools/editor/icons/source/icon_interp_wrap_clamp.svg
+++ b/editor/icons/source/icon_interp_wrap_clamp.svg
diff --git a/tools/editor/icons/source/icon_interp_wrap_loop.svg b/editor/icons/source/icon_interp_wrap_loop.svg
index bfca46331b..bfca46331b 100644
--- a/tools/editor/icons/source/icon_interp_wrap_loop.svg
+++ b/editor/icons/source/icon_interp_wrap_loop.svg
diff --git a/tools/editor/icons/source/icon_interpolated_camera.svg b/editor/icons/source/icon_interpolated_camera.svg
index 16fc731c12..16fc731c12 100644
--- a/tools/editor/icons/source/icon_interpolated_camera.svg
+++ b/editor/icons/source/icon_interpolated_camera.svg
diff --git a/tools/editor/icons/source/icon_invalid_key.svg b/editor/icons/source/icon_invalid_key.svg
index cbccff571a..cbccff571a 100644
--- a/tools/editor/icons/source/icon_invalid_key.svg
+++ b/editor/icons/source/icon_invalid_key.svg
diff --git a/tools/editor/icons/source/icon_inverse_kinematics.svg b/editor/icons/source/icon_inverse_kinematics.svg
index 227d22f911..227d22f911 100644
--- a/tools/editor/icons/source/icon_inverse_kinematics.svg
+++ b/editor/icons/source/icon_inverse_kinematics.svg
diff --git a/tools/editor/icons/source/icon_item_list.svg b/editor/icons/source/icon_item_list.svg
index 943f6fe435..943f6fe435 100644
--- a/tools/editor/icons/source/icon_item_list.svg
+++ b/editor/icons/source/icon_item_list.svg
diff --git a/tools/editor/icons/source/icon_joy_axis.svg b/editor/icons/source/icon_joy_axis.svg
index 9313342a53..9313342a53 100644
--- a/tools/editor/icons/source/icon_joy_axis.svg
+++ b/editor/icons/source/icon_joy_axis.svg
diff --git a/tools/editor/icons/source/icon_joy_button.svg b/editor/icons/source/icon_joy_button.svg
index f6d4344807..f6d4344807 100644
--- a/tools/editor/icons/source/icon_joy_button.svg
+++ b/editor/icons/source/icon_joy_button.svg
diff --git a/tools/editor/icons/source/icon_joypad.svg b/editor/icons/source/icon_joypad.svg
index fb84462919..fb84462919 100644
--- a/tools/editor/icons/source/icon_joypad.svg
+++ b/editor/icons/source/icon_joypad.svg
diff --git a/tools/editor/icons/source/icon_key.svg b/editor/icons/source/icon_key.svg
index f5d7b85381..f5d7b85381 100644
--- a/tools/editor/icons/source/icon_key.svg
+++ b/editor/icons/source/icon_key.svg
diff --git a/tools/editor/icons/source/icon_key_hover.svg b/editor/icons/source/icon_key_hover.svg
index c3f34a781b..c3f34a781b 100644
--- a/tools/editor/icons/source/icon_key_hover.svg
+++ b/editor/icons/source/icon_key_hover.svg
diff --git a/tools/editor/icons/source/icon_key_invalid.svg b/editor/icons/source/icon_key_invalid.svg
index b6407dc178..b6407dc178 100644
--- a/tools/editor/icons/source/icon_key_invalid.svg
+++ b/editor/icons/source/icon_key_invalid.svg
diff --git a/tools/editor/icons/source/icon_key_next.svg b/editor/icons/source/icon_key_next.svg
index 942245305c..942245305c 100644
--- a/tools/editor/icons/source/icon_key_next.svg
+++ b/editor/icons/source/icon_key_next.svg
diff --git a/tools/editor/icons/source/icon_key_selected.svg b/editor/icons/source/icon_key_selected.svg
index c3f01dbec8..c3f01dbec8 100644
--- a/tools/editor/icons/source/icon_key_selected.svg
+++ b/editor/icons/source/icon_key_selected.svg
diff --git a/tools/editor/icons/source/icon_key_value.svg b/editor/icons/source/icon_key_value.svg
index 5e6333e54b..5e6333e54b 100644
--- a/tools/editor/icons/source/icon_key_value.svg
+++ b/editor/icons/source/icon_key_value.svg
diff --git a/tools/editor/icons/source/icon_key_xform.svg b/editor/icons/source/icon_key_xform.svg
index 06a282f705..06a282f705 100644
--- a/tools/editor/icons/source/icon_key_xform.svg
+++ b/editor/icons/source/icon_key_xform.svg
diff --git a/tools/editor/icons/source/icon_keyboard.svg b/editor/icons/source/icon_keyboard.svg
index a03798e4a4..a03798e4a4 100644
--- a/tools/editor/icons/source/icon_keyboard.svg
+++ b/editor/icons/source/icon_keyboard.svg
diff --git a/tools/editor/icons/source/icon_kinematic_body.svg b/editor/icons/source/icon_kinematic_body.svg
index 6a4c8965ab..6a4c8965ab 100644
--- a/tools/editor/icons/source/icon_kinematic_body.svg
+++ b/editor/icons/source/icon_kinematic_body.svg
diff --git a/tools/editor/icons/source/icon_kinematic_body_2d.svg b/editor/icons/source/icon_kinematic_body_2d.svg
index 04f140b930..04f140b930 100644
--- a/tools/editor/icons/source/icon_kinematic_body_2d.svg
+++ b/editor/icons/source/icon_kinematic_body_2d.svg
diff --git a/tools/editor/icons/source/icon_label.svg b/editor/icons/source/icon_label.svg
index ac9b52be6f..ac9b52be6f 100644
--- a/tools/editor/icons/source/icon_label.svg
+++ b/editor/icons/source/icon_label.svg
diff --git a/tools/editor/icons/source/icon_large_texture.svg b/editor/icons/source/icon_large_texture.svg
index 4db0342041..4db0342041 100644
--- a/tools/editor/icons/source/icon_large_texture.svg
+++ b/editor/icons/source/icon_large_texture.svg
diff --git a/tools/editor/icons/source/icon_light_2d.svg b/editor/icons/source/icon_light_2d.svg
index 27e07a649a..27e07a649a 100644
--- a/tools/editor/icons/source/icon_light_2d.svg
+++ b/editor/icons/source/icon_light_2d.svg
diff --git a/tools/editor/icons/source/icon_light_occluder_2d.svg b/editor/icons/source/icon_light_occluder_2d.svg
index 3558f3f2da..3558f3f2da 100644
--- a/tools/editor/icons/source/icon_light_occluder_2d.svg
+++ b/editor/icons/source/icon_light_occluder_2d.svg
diff --git a/editor/icons/source/icon_line_2d.svg b/editor/icons/source/icon_line_2d.svg
new file mode 100644
index 0000000000..7f833f4a9c
--- /dev/null
+++ b/editor/icons/source/icon_line_2d.svg
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ inkscape:export-filename="D:\PROJETS\INFO\GODOT\ENGINE\godot_fork\tools\editor\icons\2x\icon_line_2d.png"
+ inkscape:export-xdpi="180"
+ inkscape:export-ydpi="180"
+ sodipodi:docname="icon_line_2d.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="31.999999"
+ inkscape:cx="7.5587317"
+ inkscape:cy="9.1781644"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ units="px"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="true"
+ inkscape:bbox-nodes="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="true"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ inkscape:window-x="-8"
+ inkscape:window-y="32"
+ inkscape:window-maximized="1"
+ inkscape:snap-grids="true"
+ inkscape:object-nodes="true"
+ showguides="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3336"
+ empspacing="4" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#a5b7f3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98823529"
+ d="m 2,1045.3622 3,4 3,-10 3,6 3,-2"
+ id="path4135"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+</svg>
diff --git a/tools/editor/icons/source/icon_line_edit.svg b/editor/icons/source/icon_line_edit.svg
index 61ba1ebe7e..61ba1ebe7e 100644
--- a/tools/editor/icons/source/icon_line_edit.svg
+++ b/editor/icons/source/icon_line_edit.svg
diff --git a/tools/editor/icons/source/icon_line_shape_2d.svg b/editor/icons/source/icon_line_shape_2d.svg
index 6a8ab39ef3..6a8ab39ef3 100644
--- a/tools/editor/icons/source/icon_line_shape_2d.svg
+++ b/editor/icons/source/icon_line_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_link_button.svg b/editor/icons/source/icon_link_button.svg
index 3872e43b29..3872e43b29 100644
--- a/tools/editor/icons/source/icon_link_button.svg
+++ b/editor/icons/source/icon_link_button.svg
diff --git a/tools/editor/icons/source/icon_list_select.svg b/editor/icons/source/icon_list_select.svg
index 569a0c6fea..569a0c6fea 100644
--- a/tools/editor/icons/source/icon_list_select.svg
+++ b/editor/icons/source/icon_list_select.svg
diff --git a/tools/editor/icons/source/icon_listener.svg b/editor/icons/source/icon_listener.svg
index f815cb842a..f815cb842a 100644
--- a/tools/editor/icons/source/icon_listener.svg
+++ b/editor/icons/source/icon_listener.svg
diff --git a/tools/editor/icons/source/icon_load.svg b/editor/icons/source/icon_load.svg
index 395a5c1b8a..395a5c1b8a 100644
--- a/tools/editor/icons/source/icon_load.svg
+++ b/editor/icons/source/icon_load.svg
diff --git a/tools/editor/icons/source/icon_lock.svg b/editor/icons/source/icon_lock.svg
index 140b073e83..140b073e83 100644
--- a/tools/editor/icons/source/icon_lock.svg
+++ b/editor/icons/source/icon_lock.svg
diff --git a/tools/editor/icons/source/icon_loop.svg b/editor/icons/source/icon_loop.svg
index fe7f648648..fe7f648648 100644
--- a/tools/editor/icons/source/icon_loop.svg
+++ b/editor/icons/source/icon_loop.svg
diff --git a/tools/editor/icons/source/icon_loop_interpolation.svg b/editor/icons/source/icon_loop_interpolation.svg
index 3733acb253..3733acb253 100644
--- a/tools/editor/icons/source/icon_loop_interpolation.svg
+++ b/editor/icons/source/icon_loop_interpolation.svg
diff --git a/tools/editor/icons/source/icon_main_play.svg b/editor/icons/source/icon_main_play.svg
index 0fb48bb155..0fb48bb155 100644
--- a/tools/editor/icons/source/icon_main_play.svg
+++ b/editor/icons/source/icon_main_play.svg
diff --git a/tools/editor/icons/source/icon_main_stop.svg b/editor/icons/source/icon_main_stop.svg
index 9d01bd5cf5..9d01bd5cf5 100644
--- a/tools/editor/icons/source/icon_main_stop.svg
+++ b/editor/icons/source/icon_main_stop.svg
diff --git a/tools/editor/icons/source/icon_margin_container.svg b/editor/icons/source/icon_margin_container.svg
index 68a6971bd7..68a6971bd7 100644
--- a/tools/editor/icons/source/icon_margin_container.svg
+++ b/editor/icons/source/icon_margin_container.svg
diff --git a/tools/editor/icons/source/icon_material_preview_cube.svg b/editor/icons/source/icon_material_preview_cube.svg
index 2e8e5a6457..2e8e5a6457 100644
--- a/tools/editor/icons/source/icon_material_preview_cube.svg
+++ b/editor/icons/source/icon_material_preview_cube.svg
diff --git a/tools/editor/icons/source/icon_material_preview_cube_off.svg b/editor/icons/source/icon_material_preview_cube_off.svg
index e03905ed05..e03905ed05 100644
--- a/tools/editor/icons/source/icon_material_preview_cube_off.svg
+++ b/editor/icons/source/icon_material_preview_cube_off.svg
diff --git a/tools/editor/icons/source/icon_material_preview_light_1.svg b/editor/icons/source/icon_material_preview_light_1.svg
index d8335641f6..d8335641f6 100644
--- a/tools/editor/icons/source/icon_material_preview_light_1.svg
+++ b/editor/icons/source/icon_material_preview_light_1.svg
diff --git a/tools/editor/icons/source/icon_material_preview_light_1_off.svg b/editor/icons/source/icon_material_preview_light_1_off.svg
index c387b1845b..c387b1845b 100644
--- a/tools/editor/icons/source/icon_material_preview_light_1_off.svg
+++ b/editor/icons/source/icon_material_preview_light_1_off.svg
diff --git a/tools/editor/icons/source/icon_material_preview_light_2.svg b/editor/icons/source/icon_material_preview_light_2.svg
index f192c19959..f192c19959 100644
--- a/tools/editor/icons/source/icon_material_preview_light_2.svg
+++ b/editor/icons/source/icon_material_preview_light_2.svg
diff --git a/tools/editor/icons/source/icon_material_preview_light_2_off.svg b/editor/icons/source/icon_material_preview_light_2_off.svg
index 9d71248cba..9d71248cba 100644
--- a/tools/editor/icons/source/icon_material_preview_light_2_off.svg
+++ b/editor/icons/source/icon_material_preview_light_2_off.svg
diff --git a/tools/editor/icons/source/icon_material_preview_sphere.svg b/editor/icons/source/icon_material_preview_sphere.svg
index 76a6ec97bd..76a6ec97bd 100644
--- a/tools/editor/icons/source/icon_material_preview_sphere.svg
+++ b/editor/icons/source/icon_material_preview_sphere.svg
diff --git a/tools/editor/icons/source/icon_material_preview_sphere_off.svg b/editor/icons/source/icon_material_preview_sphere_off.svg
index f9c8cadb34..f9c8cadb34 100644
--- a/tools/editor/icons/source/icon_material_preview_sphere_off.svg
+++ b/editor/icons/source/icon_material_preview_sphere_off.svg
diff --git a/tools/editor/icons/source/icon_matrix.svg b/editor/icons/source/icon_matrix.svg
index eacf2cdc9d..eacf2cdc9d 100644
--- a/tools/editor/icons/source/icon_matrix.svg
+++ b/editor/icons/source/icon_matrix.svg
diff --git a/tools/editor/icons/source/icon_menu_button.svg b/editor/icons/source/icon_menu_button.svg
index 9cfbf2d502..9cfbf2d502 100644
--- a/tools/editor/icons/source/icon_menu_button.svg
+++ b/editor/icons/source/icon_menu_button.svg
diff --git a/tools/editor/icons/source/icon_mesh.svg b/editor/icons/source/icon_mesh.svg
index f3c33a37b1..f3c33a37b1 100644
--- a/tools/editor/icons/source/icon_mesh.svg
+++ b/editor/icons/source/icon_mesh.svg
diff --git a/tools/editor/icons/source/icon_mesh_instance.svg b/editor/icons/source/icon_mesh_instance.svg
index 51e6447eb2..51e6447eb2 100644
--- a/tools/editor/icons/source/icon_mesh_instance.svg
+++ b/editor/icons/source/icon_mesh_instance.svg
diff --git a/tools/editor/icons/source/icon_mesh_library.svg b/editor/icons/source/icon_mesh_library.svg
index b908a4db6e..b908a4db6e 100644
--- a/tools/editor/icons/source/icon_mesh_library.svg
+++ b/editor/icons/source/icon_mesh_library.svg
diff --git a/tools/editor/icons/source/icon_mini_aabb.svg b/editor/icons/source/icon_mini_aabb.svg
index ebfd505bea..ebfd505bea 100644
--- a/tools/editor/icons/source/icon_mini_aabb.svg
+++ b/editor/icons/source/icon_mini_aabb.svg
diff --git a/tools/editor/icons/source/icon_mini_array.svg b/editor/icons/source/icon_mini_array.svg
index a0a2014fbb..a0a2014fbb 100644
--- a/tools/editor/icons/source/icon_mini_array.svg
+++ b/editor/icons/source/icon_mini_array.svg
diff --git a/tools/editor/icons/source/icon_mini_boolean.svg b/editor/icons/source/icon_mini_boolean.svg
index eb17279a62..eb17279a62 100644
--- a/tools/editor/icons/source/icon_mini_boolean.svg
+++ b/editor/icons/source/icon_mini_boolean.svg
diff --git a/tools/editor/icons/source/icon_mini_color.svg b/editor/icons/source/icon_mini_color.svg
index cdc176e00c..cdc176e00c 100644
--- a/tools/editor/icons/source/icon_mini_color.svg
+++ b/editor/icons/source/icon_mini_color.svg
diff --git a/tools/editor/icons/source/icon_mini_color_array.svg b/editor/icons/source/icon_mini_color_array.svg
index 2ec0e186b5..2ec0e186b5 100644
--- a/tools/editor/icons/source/icon_mini_color_array.svg
+++ b/editor/icons/source/icon_mini_color_array.svg
diff --git a/tools/editor/icons/source/icon_mini_dictionary.svg b/editor/icons/source/icon_mini_dictionary.svg
index 813ba97613..813ba97613 100644
--- a/tools/editor/icons/source/icon_mini_dictionary.svg
+++ b/editor/icons/source/icon_mini_dictionary.svg
diff --git a/tools/editor/icons/source/icon_mini_float.svg b/editor/icons/source/icon_mini_float.svg
index 1007955ea9..1007955ea9 100644
--- a/tools/editor/icons/source/icon_mini_float.svg
+++ b/editor/icons/source/icon_mini_float.svg
diff --git a/tools/editor/icons/source/icon_mini_float_array.svg b/editor/icons/source/icon_mini_float_array.svg
index 86807ca731..86807ca731 100644
--- a/tools/editor/icons/source/icon_mini_float_array.svg
+++ b/editor/icons/source/icon_mini_float_array.svg
diff --git a/tools/editor/icons/source/icon_mini_image.svg b/editor/icons/source/icon_mini_image.svg
index 57faded5c8..57faded5c8 100644
--- a/tools/editor/icons/source/icon_mini_image.svg
+++ b/editor/icons/source/icon_mini_image.svg
diff --git a/tools/editor/icons/source/icon_mini_input.svg b/editor/icons/source/icon_mini_input.svg
index 9e966f77d1..9e966f77d1 100644
--- a/tools/editor/icons/source/icon_mini_input.svg
+++ b/editor/icons/source/icon_mini_input.svg
diff --git a/tools/editor/icons/source/icon_mini_int_array.svg b/editor/icons/source/icon_mini_int_array.svg
index 23b086d5e1..23b086d5e1 100644
--- a/tools/editor/icons/source/icon_mini_int_array.svg
+++ b/editor/icons/source/icon_mini_int_array.svg
diff --git a/tools/editor/icons/source/icon_mini_integer.svg b/editor/icons/source/icon_mini_integer.svg
index c21322adb2..c21322adb2 100644
--- a/tools/editor/icons/source/icon_mini_integer.svg
+++ b/editor/icons/source/icon_mini_integer.svg
diff --git a/tools/editor/icons/source/icon_mini_matrix3.svg b/editor/icons/source/icon_mini_matrix3.svg
index 592230d13c..592230d13c 100644
--- a/tools/editor/icons/source/icon_mini_matrix3.svg
+++ b/editor/icons/source/icon_mini_matrix3.svg
diff --git a/tools/editor/icons/source/icon_mini_matrix32.svg b/editor/icons/source/icon_mini_matrix32.svg
index 5159ea0b87..5159ea0b87 100644
--- a/tools/editor/icons/source/icon_mini_matrix32.svg
+++ b/editor/icons/source/icon_mini_matrix32.svg
diff --git a/tools/editor/icons/source/icon_mini_object.svg b/editor/icons/source/icon_mini_object.svg
index 380be34903..380be34903 100644
--- a/tools/editor/icons/source/icon_mini_object.svg
+++ b/editor/icons/source/icon_mini_object.svg
diff --git a/tools/editor/icons/source/icon_mini_path.svg b/editor/icons/source/icon_mini_path.svg
index ef247b8b8c..ef247b8b8c 100644
--- a/tools/editor/icons/source/icon_mini_path.svg
+++ b/editor/icons/source/icon_mini_path.svg
diff --git a/tools/editor/icons/source/icon_mini_plane.svg b/editor/icons/source/icon_mini_plane.svg
index bc3992cdd6..bc3992cdd6 100644
--- a/tools/editor/icons/source/icon_mini_plane.svg
+++ b/editor/icons/source/icon_mini_plane.svg
diff --git a/tools/editor/icons/source/icon_mini_quat.svg b/editor/icons/source/icon_mini_quat.svg
index 27188a3410..27188a3410 100644
--- a/tools/editor/icons/source/icon_mini_quat.svg
+++ b/editor/icons/source/icon_mini_quat.svg
diff --git a/tools/editor/icons/source/icon_mini_raw_array.svg b/editor/icons/source/icon_mini_raw_array.svg
index cb735b5615..cb735b5615 100644
--- a/tools/editor/icons/source/icon_mini_raw_array.svg
+++ b/editor/icons/source/icon_mini_raw_array.svg
diff --git a/tools/editor/icons/source/icon_mini_rect2.svg b/editor/icons/source/icon_mini_rect2.svg
index ded27f049f..ded27f049f 100644
--- a/tools/editor/icons/source/icon_mini_rect2.svg
+++ b/editor/icons/source/icon_mini_rect2.svg
diff --git a/tools/editor/icons/source/icon_mini_rid.svg b/editor/icons/source/icon_mini_rid.svg
index 6df13ae43d..6df13ae43d 100644
--- a/tools/editor/icons/source/icon_mini_rid.svg
+++ b/editor/icons/source/icon_mini_rid.svg
diff --git a/tools/editor/icons/source/icon_mini_string.svg b/editor/icons/source/icon_mini_string.svg
index a655f70d33..a655f70d33 100644
--- a/tools/editor/icons/source/icon_mini_string.svg
+++ b/editor/icons/source/icon_mini_string.svg
diff --git a/tools/editor/icons/source/icon_mini_string_array.svg b/editor/icons/source/icon_mini_string_array.svg
index cd2e850c49..cd2e850c49 100644
--- a/tools/editor/icons/source/icon_mini_string_array.svg
+++ b/editor/icons/source/icon_mini_string_array.svg
diff --git a/tools/editor/icons/source/icon_mini_transform.svg b/editor/icons/source/icon_mini_transform.svg
index 6da4eb806d..6da4eb806d 100644
--- a/tools/editor/icons/source/icon_mini_transform.svg
+++ b/editor/icons/source/icon_mini_transform.svg
diff --git a/tools/editor/icons/source/icon_mini_variant.svg b/editor/icons/source/icon_mini_variant.svg
index 6883baa584..6883baa584 100644
--- a/tools/editor/icons/source/icon_mini_variant.svg
+++ b/editor/icons/source/icon_mini_variant.svg
diff --git a/tools/editor/icons/source/icon_mini_vector2.svg b/editor/icons/source/icon_mini_vector2.svg
index 5c9aaeccff..5c9aaeccff 100644
--- a/tools/editor/icons/source/icon_mini_vector2.svg
+++ b/editor/icons/source/icon_mini_vector2.svg
diff --git a/tools/editor/icons/source/icon_mini_vector2_array.svg b/editor/icons/source/icon_mini_vector2_array.svg
index 03850f7c86..03850f7c86 100644
--- a/tools/editor/icons/source/icon_mini_vector2_array.svg
+++ b/editor/icons/source/icon_mini_vector2_array.svg
diff --git a/tools/editor/icons/source/icon_mini_vector3.svg b/editor/icons/source/icon_mini_vector3.svg
index e99a211ae0..e99a211ae0 100644
--- a/tools/editor/icons/source/icon_mini_vector3.svg
+++ b/editor/icons/source/icon_mini_vector3.svg
diff --git a/tools/editor/icons/source/icon_mini_vector3_array.svg b/editor/icons/source/icon_mini_vector3_array.svg
index bbac554614..bbac554614 100644
--- a/tools/editor/icons/source/icon_mini_vector3_array.svg
+++ b/editor/icons/source/icon_mini_vector3_array.svg
diff --git a/tools/editor/icons/source/icon_mirror_x.svg b/editor/icons/source/icon_mirror_x.svg
index f24a630770..f24a630770 100644
--- a/tools/editor/icons/source/icon_mirror_x.svg
+++ b/editor/icons/source/icon_mirror_x.svg
diff --git a/tools/editor/icons/source/icon_mirror_y.svg b/editor/icons/source/icon_mirror_y.svg
index bb913b84af..bb913b84af 100644
--- a/tools/editor/icons/source/icon_mirror_y.svg
+++ b/editor/icons/source/icon_mirror_y.svg
diff --git a/tools/editor/icons/source/icon_mouse.svg b/editor/icons/source/icon_mouse.svg
index 731ceeefd8..731ceeefd8 100644
--- a/tools/editor/icons/source/icon_mouse.svg
+++ b/editor/icons/source/icon_mouse.svg
diff --git a/tools/editor/icons/source/icon_move_down.svg b/editor/icons/source/icon_move_down.svg
index e83a69ad50..e83a69ad50 100644
--- a/tools/editor/icons/source/icon_move_down.svg
+++ b/editor/icons/source/icon_move_down.svg
diff --git a/tools/editor/icons/source/icon_move_point.svg b/editor/icons/source/icon_move_point.svg
index c951d6b90a..c951d6b90a 100644
--- a/tools/editor/icons/source/icon_move_point.svg
+++ b/editor/icons/source/icon_move_point.svg
diff --git a/tools/editor/icons/source/icon_move_up.svg b/editor/icons/source/icon_move_up.svg
index 8f671a0d72..8f671a0d72 100644
--- a/tools/editor/icons/source/icon_move_up.svg
+++ b/editor/icons/source/icon_move_up.svg
diff --git a/tools/editor/icons/source/icon_multi_edit.svg b/editor/icons/source/icon_multi_edit.svg
index ef63861e97..ef63861e97 100644
--- a/tools/editor/icons/source/icon_multi_edit.svg
+++ b/editor/icons/source/icon_multi_edit.svg
diff --git a/tools/editor/icons/source/icon_multi_line.svg b/editor/icons/source/icon_multi_line.svg
index 542e311286..542e311286 100644
--- a/tools/editor/icons/source/icon_multi_line.svg
+++ b/editor/icons/source/icon_multi_line.svg
diff --git a/tools/editor/icons/source/icon_multi_mesh.svg b/editor/icons/source/icon_multi_mesh.svg
index 22f843a686..22f843a686 100644
--- a/tools/editor/icons/source/icon_multi_mesh.svg
+++ b/editor/icons/source/icon_multi_mesh.svg
diff --git a/tools/editor/icons/source/icon_multi_mesh_instance.svg b/editor/icons/source/icon_multi_mesh_instance.svg
index deceae5a03..deceae5a03 100644
--- a/tools/editor/icons/source/icon_multi_mesh_instance.svg
+++ b/editor/icons/source/icon_multi_mesh_instance.svg
diff --git a/tools/editor/icons/source/icon_navigation.svg b/editor/icons/source/icon_navigation.svg
index 42e8f59165..42e8f59165 100644
--- a/tools/editor/icons/source/icon_navigation.svg
+++ b/editor/icons/source/icon_navigation.svg
diff --git a/tools/editor/icons/source/icon_navigation_2d.svg b/editor/icons/source/icon_navigation_2d.svg
index 5252541e70..5252541e70 100644
--- a/tools/editor/icons/source/icon_navigation_2d.svg
+++ b/editor/icons/source/icon_navigation_2d.svg
diff --git a/tools/editor/icons/source/icon_navigation_mesh.svg b/editor/icons/source/icon_navigation_mesh.svg
index 31ab5df8ad..31ab5df8ad 100644
--- a/tools/editor/icons/source/icon_navigation_mesh.svg
+++ b/editor/icons/source/icon_navigation_mesh.svg
diff --git a/tools/editor/icons/source/icon_navigation_mesh_instance.svg b/editor/icons/source/icon_navigation_mesh_instance.svg
index 5c4e0f1579..5c4e0f1579 100644
--- a/tools/editor/icons/source/icon_navigation_mesh_instance.svg
+++ b/editor/icons/source/icon_navigation_mesh_instance.svg
diff --git a/tools/editor/icons/source/icon_navigation_polygon.svg b/editor/icons/source/icon_navigation_polygon.svg
index f3b6fcbcc3..f3b6fcbcc3 100644
--- a/tools/editor/icons/source/icon_navigation_polygon.svg
+++ b/editor/icons/source/icon_navigation_polygon.svg
diff --git a/tools/editor/icons/source/icon_navigation_polygon_instance.svg b/editor/icons/source/icon_navigation_polygon_instance.svg
index 5153227b15..5153227b15 100644
--- a/tools/editor/icons/source/icon_navigation_polygon_instance.svg
+++ b/editor/icons/source/icon_navigation_polygon_instance.svg
diff --git a/tools/editor/icons/source/icon_new.svg b/editor/icons/source/icon_new.svg
index a37ba1be3f..a37ba1be3f 100644
--- a/tools/editor/icons/source/icon_new.svg
+++ b/editor/icons/source/icon_new.svg
diff --git a/tools/editor/icons/source/icon_nine_patch_rect.svg b/editor/icons/source/icon_nine_patch_rect.svg
index f12789c19e..f12789c19e 100644
--- a/tools/editor/icons/source/icon_nine_patch_rect.svg
+++ b/editor/icons/source/icon_nine_patch_rect.svg
diff --git a/tools/editor/icons/source/icon_node.svg b/editor/icons/source/icon_node.svg
index 02e2774669..02e2774669 100644
--- a/tools/editor/icons/source/icon_node.svg
+++ b/editor/icons/source/icon_node.svg
diff --git a/tools/editor/icons/source/icon_node_2d.svg b/editor/icons/source/icon_node_2d.svg
index e546f68539..e546f68539 100644
--- a/tools/editor/icons/source/icon_node_2d.svg
+++ b/editor/icons/source/icon_node_2d.svg
diff --git a/tools/editor/icons/source/icon_node_warning.svg b/editor/icons/source/icon_node_warning.svg
index 89d3663fb0..89d3663fb0 100644
--- a/tools/editor/icons/source/icon_node_warning.svg
+++ b/editor/icons/source/icon_node_warning.svg
diff --git a/tools/editor/icons/source/icon_non_favorite.svg b/editor/icons/source/icon_non_favorite.svg
index 54fcb8577e..54fcb8577e 100644
--- a/tools/editor/icons/source/icon_non_favorite.svg
+++ b/editor/icons/source/icon_non_favorite.svg
diff --git a/tools/editor/icons/source/icon_object.svg b/editor/icons/source/icon_object.svg
index 6b36b61168..6b36b61168 100644
--- a/tools/editor/icons/source/icon_object.svg
+++ b/editor/icons/source/icon_object.svg
diff --git a/tools/editor/icons/source/icon_occluder_polygon_2d.svg b/editor/icons/source/icon_occluder_polygon_2d.svg
index 8ae6dc176d..8ae6dc176d 100644
--- a/tools/editor/icons/source/icon_occluder_polygon_2d.svg
+++ b/editor/icons/source/icon_occluder_polygon_2d.svg
diff --git a/tools/editor/icons/source/icon_omni_light.svg b/editor/icons/source/icon_omni_light.svg
index e1049d0039..e1049d0039 100644
--- a/tools/editor/icons/source/icon_omni_light.svg
+++ b/editor/icons/source/icon_omni_light.svg
diff --git a/tools/editor/icons/source/icon_option_button.svg b/editor/icons/source/icon_option_button.svg
index 4537b14616..4537b14616 100644
--- a/tools/editor/icons/source/icon_option_button.svg
+++ b/editor/icons/source/icon_option_button.svg
diff --git a/tools/editor/icons/source/icon_override.svg b/editor/icons/source/icon_override.svg
index b7948c531c..b7948c531c 100644
--- a/tools/editor/icons/source/icon_override.svg
+++ b/editor/icons/source/icon_override.svg
diff --git a/tools/editor/icons/source/icon_packed_data_container.svg b/editor/icons/source/icon_packed_data_container.svg
index 70aed22f2c..70aed22f2c 100644
--- a/tools/editor/icons/source/icon_packed_data_container.svg
+++ b/editor/icons/source/icon_packed_data_container.svg
diff --git a/tools/editor/icons/source/icon_packed_scene.svg b/editor/icons/source/icon_packed_scene.svg
index 910a274841..910a274841 100644
--- a/tools/editor/icons/source/icon_packed_scene.svg
+++ b/editor/icons/source/icon_packed_scene.svg
diff --git a/tools/editor/icons/source/icon_panel.svg b/editor/icons/source/icon_panel.svg
index 28921c4031..28921c4031 100644
--- a/tools/editor/icons/source/icon_panel.svg
+++ b/editor/icons/source/icon_panel.svg
diff --git a/tools/editor/icons/source/icon_panel_container.svg b/editor/icons/source/icon_panel_container.svg
index decf220705..decf220705 100644
--- a/tools/editor/icons/source/icon_panel_container.svg
+++ b/editor/icons/source/icon_panel_container.svg
diff --git a/tools/editor/icons/source/icon_panels_1.svg b/editor/icons/source/icon_panels_1.svg
index fa8bbe9fad..fa8bbe9fad 100644
--- a/tools/editor/icons/source/icon_panels_1.svg
+++ b/editor/icons/source/icon_panels_1.svg
diff --git a/tools/editor/icons/source/icon_panels_2.svg b/editor/icons/source/icon_panels_2.svg
index f00cc4b339..f00cc4b339 100644
--- a/tools/editor/icons/source/icon_panels_2.svg
+++ b/editor/icons/source/icon_panels_2.svg
diff --git a/tools/editor/icons/source/icon_panels_2_alt.svg b/editor/icons/source/icon_panels_2_alt.svg
index cc3a634a3e..cc3a634a3e 100644
--- a/tools/editor/icons/source/icon_panels_2_alt.svg
+++ b/editor/icons/source/icon_panels_2_alt.svg
diff --git a/tools/editor/icons/source/icon_panels_3.svg b/editor/icons/source/icon_panels_3.svg
index 04517c5a66..04517c5a66 100644
--- a/tools/editor/icons/source/icon_panels_3.svg
+++ b/editor/icons/source/icon_panels_3.svg
diff --git a/tools/editor/icons/source/icon_panels_3_alt.svg b/editor/icons/source/icon_panels_3_alt.svg
index e5a9493287..e5a9493287 100644
--- a/tools/editor/icons/source/icon_panels_3_alt.svg
+++ b/editor/icons/source/icon_panels_3_alt.svg
diff --git a/tools/editor/icons/source/icon_panels_4.svg b/editor/icons/source/icon_panels_4.svg
index 6d07a0b6d5..6d07a0b6d5 100644
--- a/tools/editor/icons/source/icon_panels_4.svg
+++ b/editor/icons/source/icon_panels_4.svg
diff --git a/tools/editor/icons/source/icon_parallax_background.svg b/editor/icons/source/icon_parallax_background.svg
index e1b6a4fb2f..e1b6a4fb2f 100644
--- a/tools/editor/icons/source/icon_parallax_background.svg
+++ b/editor/icons/source/icon_parallax_background.svg
diff --git a/tools/editor/icons/source/icon_parallax_layer.svg b/editor/icons/source/icon_parallax_layer.svg
index 022fdd5339..022fdd5339 100644
--- a/tools/editor/icons/source/icon_parallax_layer.svg
+++ b/editor/icons/source/icon_parallax_layer.svg
diff --git a/tools/editor/icons/source/icon_particle_attractor_2d.svg b/editor/icons/source/icon_particle_attractor_2d.svg
index f755d7fc37..f755d7fc37 100644
--- a/tools/editor/icons/source/icon_particle_attractor_2d.svg
+++ b/editor/icons/source/icon_particle_attractor_2d.svg
diff --git a/tools/editor/icons/source/icon_particles.svg b/editor/icons/source/icon_particles.svg
index f48929a7ef..f48929a7ef 100644
--- a/tools/editor/icons/source/icon_particles.svg
+++ b/editor/icons/source/icon_particles.svg
diff --git a/tools/editor/icons/source/icon_particles_2d.svg b/editor/icons/source/icon_particles_2d.svg
index 1ad1d511f8..1ad1d511f8 100644
--- a/tools/editor/icons/source/icon_particles_2d.svg
+++ b/editor/icons/source/icon_particles_2d.svg
diff --git a/tools/editor/icons/source/icon_particles_shader.svg b/editor/icons/source/icon_particles_shader.svg
index b4c2ef7ccd..b4c2ef7ccd 100644
--- a/tools/editor/icons/source/icon_particles_shader.svg
+++ b/editor/icons/source/icon_particles_shader.svg
diff --git a/tools/editor/icons/source/icon_patch_9_rect.svg b/editor/icons/source/icon_patch_9_rect.svg
index c5a09603a6..c5a09603a6 100644
--- a/tools/editor/icons/source/icon_patch_9_rect.svg
+++ b/editor/icons/source/icon_patch_9_rect.svg
diff --git a/tools/editor/icons/source/icon_path.svg b/editor/icons/source/icon_path.svg
index 39c63eac8a..39c63eac8a 100644
--- a/tools/editor/icons/source/icon_path.svg
+++ b/editor/icons/source/icon_path.svg
diff --git a/tools/editor/icons/source/icon_path_2d.svg b/editor/icons/source/icon_path_2d.svg
index 6887834048..6887834048 100644
--- a/tools/editor/icons/source/icon_path_2d.svg
+++ b/editor/icons/source/icon_path_2d.svg
diff --git a/tools/editor/icons/source/icon_path_follow.svg b/editor/icons/source/icon_path_follow.svg
index 6999df33de..6999df33de 100644
--- a/tools/editor/icons/source/icon_path_follow.svg
+++ b/editor/icons/source/icon_path_follow.svg
diff --git a/tools/editor/icons/source/icon_path_follow_2d.svg b/editor/icons/source/icon_path_follow_2d.svg
index 020a094c0a..020a094c0a 100644
--- a/tools/editor/icons/source/icon_path_follow_2d.svg
+++ b/editor/icons/source/icon_path_follow_2d.svg
diff --git a/tools/editor/icons/source/icon_pause.svg b/editor/icons/source/icon_pause.svg
index 411f1b22da..411f1b22da 100644
--- a/tools/editor/icons/source/icon_pause.svg
+++ b/editor/icons/source/icon_pause.svg
diff --git a/tools/editor/icons/source/icon_pin.svg b/editor/icons/source/icon_pin.svg
index 8281b6438b..8281b6438b 100644
--- a/tools/editor/icons/source/icon_pin.svg
+++ b/editor/icons/source/icon_pin.svg
diff --git a/tools/editor/icons/source/icon_pin_joint.svg b/editor/icons/source/icon_pin_joint.svg
index 47dbe6be60..47dbe6be60 100644
--- a/tools/editor/icons/source/icon_pin_joint.svg
+++ b/editor/icons/source/icon_pin_joint.svg
diff --git a/tools/editor/icons/source/icon_pin_joint_2d.svg b/editor/icons/source/icon_pin_joint_2d.svg
index 90e1579903..90e1579903 100644
--- a/tools/editor/icons/source/icon_pin_joint_2d.svg
+++ b/editor/icons/source/icon_pin_joint_2d.svg
diff --git a/tools/editor/icons/source/icon_pin_pressed.svg b/editor/icons/source/icon_pin_pressed.svg
index 8281b6438b..8281b6438b 100644
--- a/tools/editor/icons/source/icon_pin_pressed.svg
+++ b/editor/icons/source/icon_pin_pressed.svg
diff --git a/tools/editor/icons/source/icon_plane.svg b/editor/icons/source/icon_plane.svg
index de5b5efc82..de5b5efc82 100644
--- a/tools/editor/icons/source/icon_plane.svg
+++ b/editor/icons/source/icon_plane.svg
diff --git a/tools/editor/icons/source/icon_plane_shape.svg b/editor/icons/source/icon_plane_shape.svg
index b2d5e18b8f..b2d5e18b8f 100644
--- a/tools/editor/icons/source/icon_plane_shape.svg
+++ b/editor/icons/source/icon_plane_shape.svg
diff --git a/tools/editor/icons/source/icon_play.svg b/editor/icons/source/icon_play.svg
index 9d3beab97d..9d3beab97d 100644
--- a/tools/editor/icons/source/icon_play.svg
+++ b/editor/icons/source/icon_play.svg
diff --git a/tools/editor/icons/source/icon_play_backwards.svg b/editor/icons/source/icon_play_backwards.svg
index d93d529dd8..d93d529dd8 100644
--- a/tools/editor/icons/source/icon_play_backwards.svg
+++ b/editor/icons/source/icon_play_backwards.svg
diff --git a/tools/editor/icons/source/icon_play_custom.svg b/editor/icons/source/icon_play_custom.svg
index 62ff7fe710..62ff7fe710 100644
--- a/tools/editor/icons/source/icon_play_custom.svg
+++ b/editor/icons/source/icon_play_custom.svg
diff --git a/tools/editor/icons/source/icon_play_scene.svg b/editor/icons/source/icon_play_scene.svg
index 599cd14981..599cd14981 100644
--- a/tools/editor/icons/source/icon_play_scene.svg
+++ b/editor/icons/source/icon_play_scene.svg
diff --git a/tools/editor/icons/source/icon_play_start.svg b/editor/icons/source/icon_play_start.svg
index 7157f59f35..7157f59f35 100644
--- a/tools/editor/icons/source/icon_play_start.svg
+++ b/editor/icons/source/icon_play_start.svg
diff --git a/tools/editor/icons/source/icon_play_start_backwards.svg b/editor/icons/source/icon_play_start_backwards.svg
index 06998f1043..06998f1043 100644
--- a/tools/editor/icons/source/icon_play_start_backwards.svg
+++ b/editor/icons/source/icon_play_start_backwards.svg
diff --git a/tools/editor/icons/source/icon_polygon_path_finder.svg b/editor/icons/source/icon_polygon_path_finder.svg
index c2f8d80c3d..c2f8d80c3d 100644
--- a/tools/editor/icons/source/icon_polygon_path_finder.svg
+++ b/editor/icons/source/icon_polygon_path_finder.svg
diff --git a/tools/editor/icons/source/icon_popup.svg b/editor/icons/source/icon_popup.svg
index 1681e537f6..1681e537f6 100644
--- a/tools/editor/icons/source/icon_popup.svg
+++ b/editor/icons/source/icon_popup.svg
diff --git a/tools/editor/icons/source/icon_popup_dialog.svg b/editor/icons/source/icon_popup_dialog.svg
index 54e14accc7..54e14accc7 100644
--- a/tools/editor/icons/source/icon_popup_dialog.svg
+++ b/editor/icons/source/icon_popup_dialog.svg
diff --git a/tools/editor/icons/source/icon_popup_menu.svg b/editor/icons/source/icon_popup_menu.svg
index e812ca695b..e812ca695b 100644
--- a/tools/editor/icons/source/icon_popup_menu.svg
+++ b/editor/icons/source/icon_popup_menu.svg
diff --git a/tools/editor/icons/source/icon_popup_panel.svg b/editor/icons/source/icon_popup_panel.svg
index c307257efe..c307257efe 100644
--- a/tools/editor/icons/source/icon_popup_panel.svg
+++ b/editor/icons/source/icon_popup_panel.svg
diff --git a/tools/editor/icons/source/icon_portal.svg b/editor/icons/source/icon_portal.svg
index 2f3d22025f..2f3d22025f 100644
--- a/tools/editor/icons/source/icon_portal.svg
+++ b/editor/icons/source/icon_portal.svg
diff --git a/tools/editor/icons/source/icon_position_2d.svg b/editor/icons/source/icon_position_2d.svg
index 4dbb2c188a..4dbb2c188a 100644
--- a/tools/editor/icons/source/icon_position_2d.svg
+++ b/editor/icons/source/icon_position_2d.svg
diff --git a/tools/editor/icons/source/icon_position_3d.svg b/editor/icons/source/icon_position_3d.svg
index b735af4ac3..b735af4ac3 100644
--- a/tools/editor/icons/source/icon_position_3d.svg
+++ b/editor/icons/source/icon_position_3d.svg
diff --git a/tools/editor/icons/source/icon_progress_1.svg b/editor/icons/source/icon_progress_1.svg
index 4b4694d0d4..4b4694d0d4 100644
--- a/tools/editor/icons/source/icon_progress_1.svg
+++ b/editor/icons/source/icon_progress_1.svg
diff --git a/tools/editor/icons/source/icon_progress_2.svg b/editor/icons/source/icon_progress_2.svg
index 1edad60e03..1edad60e03 100644
--- a/tools/editor/icons/source/icon_progress_2.svg
+++ b/editor/icons/source/icon_progress_2.svg
diff --git a/tools/editor/icons/source/icon_progress_3.svg b/editor/icons/source/icon_progress_3.svg
index 405a16854e..405a16854e 100644
--- a/tools/editor/icons/source/icon_progress_3.svg
+++ b/editor/icons/source/icon_progress_3.svg
diff --git a/tools/editor/icons/source/icon_progress_4.svg b/editor/icons/source/icon_progress_4.svg
index 26e97928ee..26e97928ee 100644
--- a/tools/editor/icons/source/icon_progress_4.svg
+++ b/editor/icons/source/icon_progress_4.svg
diff --git a/tools/editor/icons/source/icon_progress_5.svg b/editor/icons/source/icon_progress_5.svg
index 024190e9fd..024190e9fd 100644
--- a/tools/editor/icons/source/icon_progress_5.svg
+++ b/editor/icons/source/icon_progress_5.svg
diff --git a/tools/editor/icons/source/icon_progress_6.svg b/editor/icons/source/icon_progress_6.svg
index 3783c528e7..3783c528e7 100644
--- a/tools/editor/icons/source/icon_progress_6.svg
+++ b/editor/icons/source/icon_progress_6.svg
diff --git a/tools/editor/icons/source/icon_progress_7.svg b/editor/icons/source/icon_progress_7.svg
index 2a2c744b5b..2a2c744b5b 100644
--- a/tools/editor/icons/source/icon_progress_7.svg
+++ b/editor/icons/source/icon_progress_7.svg
diff --git a/tools/editor/icons/source/icon_progress_8.svg b/editor/icons/source/icon_progress_8.svg
index 2331aee2e7..2331aee2e7 100644
--- a/tools/editor/icons/source/icon_progress_8.svg
+++ b/editor/icons/source/icon_progress_8.svg
diff --git a/tools/editor/icons/source/icon_progress_bar.svg b/editor/icons/source/icon_progress_bar.svg
index 1a5458080b..1a5458080b 100644
--- a/tools/editor/icons/source/icon_progress_bar.svg
+++ b/editor/icons/source/icon_progress_bar.svg
diff --git a/tools/editor/icons/source/icon_proximity_group.svg b/editor/icons/source/icon_proximity_group.svg
index 041d0c5ee2..041d0c5ee2 100644
--- a/tools/editor/icons/source/icon_proximity_group.svg
+++ b/editor/icons/source/icon_proximity_group.svg
diff --git a/tools/editor/icons/source/icon_quad.svg b/editor/icons/source/icon_quad.svg
index 86bb1979e7..86bb1979e7 100644
--- a/tools/editor/icons/source/icon_quad.svg
+++ b/editor/icons/source/icon_quad.svg
diff --git a/tools/editor/icons/source/icon_quat.svg b/editor/icons/source/icon_quat.svg
index 36560d9d8f..36560d9d8f 100644
--- a/tools/editor/icons/source/icon_quat.svg
+++ b/editor/icons/source/icon_quat.svg
diff --git a/tools/editor/icons/source/icon_range.svg b/editor/icons/source/icon_range.svg
index 1dd857ff32..1dd857ff32 100644
--- a/tools/editor/icons/source/icon_range.svg
+++ b/editor/icons/source/icon_range.svg
diff --git a/tools/editor/icons/source/icon_rating_no_star.svg b/editor/icons/source/icon_rating_no_star.svg
index 09a9efa112..09a9efa112 100644
--- a/tools/editor/icons/source/icon_rating_no_star.svg
+++ b/editor/icons/source/icon_rating_no_star.svg
diff --git a/tools/editor/icons/source/icon_rating_star.svg b/editor/icons/source/icon_rating_star.svg
index 7ed3f9fbfa..7ed3f9fbfa 100644
--- a/tools/editor/icons/source/icon_rating_star.svg
+++ b/editor/icons/source/icon_rating_star.svg
diff --git a/tools/editor/icons/source/icon_ray_cast.svg b/editor/icons/source/icon_ray_cast.svg
index b8cab72d07..b8cab72d07 100644
--- a/tools/editor/icons/source/icon_ray_cast.svg
+++ b/editor/icons/source/icon_ray_cast.svg
diff --git a/tools/editor/icons/source/icon_ray_cast_2d.svg b/editor/icons/source/icon_ray_cast_2d.svg
index faadd41a17..faadd41a17 100644
--- a/tools/editor/icons/source/icon_ray_cast_2d.svg
+++ b/editor/icons/source/icon_ray_cast_2d.svg
diff --git a/tools/editor/icons/source/icon_ray_shape.svg b/editor/icons/source/icon_ray_shape.svg
index 0e0f2940ae..0e0f2940ae 100644
--- a/tools/editor/icons/source/icon_ray_shape.svg
+++ b/editor/icons/source/icon_ray_shape.svg
diff --git a/tools/editor/icons/source/icon_ray_shape_2d.svg b/editor/icons/source/icon_ray_shape_2d.svg
index 7ffc2ff3b5..7ffc2ff3b5 100644
--- a/tools/editor/icons/source/icon_ray_shape_2d.svg
+++ b/editor/icons/source/icon_ray_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_rayito.svg b/editor/icons/source/icon_rayito.svg
index 56988b9e4f..56988b9e4f 100644
--- a/tools/editor/icons/source/icon_rayito.svg
+++ b/editor/icons/source/icon_rayito.svg
diff --git a/tools/editor/icons/source/icon_real.svg b/editor/icons/source/icon_real.svg
index 1a3406ed48..1a3406ed48 100644
--- a/tools/editor/icons/source/icon_real.svg
+++ b/editor/icons/source/icon_real.svg
diff --git a/tools/editor/icons/source/icon_rectangle_shape_2d.svg b/editor/icons/source/icon_rectangle_shape_2d.svg
index d362944e7a..d362944e7a 100644
--- a/tools/editor/icons/source/icon_rectangle_shape_2d.svg
+++ b/editor/icons/source/icon_rectangle_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_reference_rect.svg b/editor/icons/source/icon_reference_rect.svg
index cee814360d..cee814360d 100644
--- a/tools/editor/icons/source/icon_reference_rect.svg
+++ b/editor/icons/source/icon_reference_rect.svg
diff --git a/tools/editor/icons/source/icon_reflection_probe.svg b/editor/icons/source/icon_reflection_probe.svg
index 64b6493d6d..64b6493d6d 100644
--- a/tools/editor/icons/source/icon_reflection_probe.svg
+++ b/editor/icons/source/icon_reflection_probe.svg
diff --git a/tools/editor/icons/source/icon_region_edit.svg b/editor/icons/source/icon_region_edit.svg
index b42a53e88d..b42a53e88d 100644
--- a/tools/editor/icons/source/icon_region_edit.svg
+++ b/editor/icons/source/icon_region_edit.svg
diff --git a/tools/editor/icons/source/icon_reload_small.svg b/editor/icons/source/icon_reload_small.svg
index 2d891c2238..2d891c2238 100644
--- a/tools/editor/icons/source/icon_reload_small.svg
+++ b/editor/icons/source/icon_reload_small.svg
diff --git a/tools/editor/icons/source/icon_remote.svg b/editor/icons/source/icon_remote.svg
index f5b458c348..f5b458c348 100644
--- a/tools/editor/icons/source/icon_remote.svg
+++ b/editor/icons/source/icon_remote.svg
diff --git a/tools/editor/icons/source/icon_remote_transform.svg b/editor/icons/source/icon_remote_transform.svg
index fbbfacf629..fbbfacf629 100644
--- a/tools/editor/icons/source/icon_remote_transform.svg
+++ b/editor/icons/source/icon_remote_transform.svg
diff --git a/tools/editor/icons/source/icon_remote_transform_2d.svg b/editor/icons/source/icon_remote_transform_2d.svg
index 479cc0eb25..479cc0eb25 100644
--- a/tools/editor/icons/source/icon_remote_transform_2d.svg
+++ b/editor/icons/source/icon_remote_transform_2d.svg
diff --git a/tools/editor/icons/source/icon_remove.svg b/editor/icons/source/icon_remove.svg
index 9d75f1e921..9d75f1e921 100644
--- a/tools/editor/icons/source/icon_remove.svg
+++ b/editor/icons/source/icon_remove.svg
diff --git a/tools/editor/icons/source/icon_rename.svg b/editor/icons/source/icon_rename.svg
index 41eb10c7fc..41eb10c7fc 100644
--- a/tools/editor/icons/source/icon_rename.svg
+++ b/editor/icons/source/icon_rename.svg
diff --git a/tools/editor/icons/source/icon_reparent.svg b/editor/icons/source/icon_reparent.svg
index 79543fe066..79543fe066 100644
--- a/tools/editor/icons/source/icon_reparent.svg
+++ b/editor/icons/source/icon_reparent.svg
diff --git a/tools/editor/icons/source/icon_resource_preloader.svg b/editor/icons/source/icon_resource_preloader.svg
index bab1bb4e1e..bab1bb4e1e 100644
--- a/tools/editor/icons/source/icon_resource_preloader.svg
+++ b/editor/icons/source/icon_resource_preloader.svg
diff --git a/tools/editor/icons/source/icon_rich_text_label.svg b/editor/icons/source/icon_rich_text_label.svg
index 4a77dbe672..4a77dbe672 100644
--- a/tools/editor/icons/source/icon_rich_text_label.svg
+++ b/editor/icons/source/icon_rich_text_label.svg
diff --git a/tools/editor/icons/source/icon_rigid_body.svg b/editor/icons/source/icon_rigid_body.svg
index 6bebb5250f..6bebb5250f 100644
--- a/tools/editor/icons/source/icon_rigid_body.svg
+++ b/editor/icons/source/icon_rigid_body.svg
diff --git a/tools/editor/icons/source/icon_rigid_body_2d.svg b/editor/icons/source/icon_rigid_body_2d.svg
index 9c8309ecfb..9c8309ecfb 100644
--- a/tools/editor/icons/source/icon_rigid_body_2d.svg
+++ b/editor/icons/source/icon_rigid_body_2d.svg
diff --git a/tools/editor/icons/source/icon_room.svg b/editor/icons/source/icon_room.svg
index 599bbeb770..599bbeb770 100644
--- a/tools/editor/icons/source/icon_room.svg
+++ b/editor/icons/source/icon_room.svg
diff --git a/tools/editor/icons/source/icon_room_bounds.svg b/editor/icons/source/icon_room_bounds.svg
index 8f7e6e6c83..8f7e6e6c83 100644
--- a/tools/editor/icons/source/icon_room_bounds.svg
+++ b/editor/icons/source/icon_room_bounds.svg
diff --git a/tools/editor/icons/source/icon_rotate_0.svg b/editor/icons/source/icon_rotate_0.svg
index 710edc8fee..710edc8fee 100644
--- a/tools/editor/icons/source/icon_rotate_0.svg
+++ b/editor/icons/source/icon_rotate_0.svg
diff --git a/tools/editor/icons/source/icon_rotate_180.svg b/editor/icons/source/icon_rotate_180.svg
index ba44fa295d..ba44fa295d 100644
--- a/tools/editor/icons/source/icon_rotate_180.svg
+++ b/editor/icons/source/icon_rotate_180.svg
diff --git a/tools/editor/icons/source/icon_rotate_270.svg b/editor/icons/source/icon_rotate_270.svg
index 403321cb89..403321cb89 100644
--- a/tools/editor/icons/source/icon_rotate_270.svg
+++ b/editor/icons/source/icon_rotate_270.svg
diff --git a/tools/editor/icons/source/icon_rotate_90.svg b/editor/icons/source/icon_rotate_90.svg
index f6b7d84032..f6b7d84032 100644
--- a/tools/editor/icons/source/icon_rotate_90.svg
+++ b/editor/icons/source/icon_rotate_90.svg
diff --git a/tools/editor/icons/source/icon_sample.svg b/editor/icons/source/icon_sample.svg
index 782e07a012..782e07a012 100644
--- a/tools/editor/icons/source/icon_sample.svg
+++ b/editor/icons/source/icon_sample.svg
diff --git a/tools/editor/icons/source/icon_sample_library.svg b/editor/icons/source/icon_sample_library.svg
index 78b01430c2..78b01430c2 100644
--- a/tools/editor/icons/source/icon_sample_library.svg
+++ b/editor/icons/source/icon_sample_library.svg
diff --git a/tools/editor/icons/source/icon_sample_player.svg b/editor/icons/source/icon_sample_player.svg
index 2254718a9b..2254718a9b 100644
--- a/tools/editor/icons/source/icon_sample_player.svg
+++ b/editor/icons/source/icon_sample_player.svg
diff --git a/tools/editor/icons/source/icon_sample_player_2d.svg b/editor/icons/source/icon_sample_player_2d.svg
index 33a7eba019..33a7eba019 100644
--- a/tools/editor/icons/source/icon_sample_player_2d.svg
+++ b/editor/icons/source/icon_sample_player_2d.svg
diff --git a/tools/editor/icons/source/icon_save.svg b/editor/icons/source/icon_save.svg
index 9307537d4b..9307537d4b 100644
--- a/tools/editor/icons/source/icon_save.svg
+++ b/editor/icons/source/icon_save.svg
diff --git a/tools/editor/icons/source/icon_script.svg b/editor/icons/source/icon_script.svg
index 8073692ce8..8073692ce8 100644
--- a/tools/editor/icons/source/icon_script.svg
+++ b/editor/icons/source/icon_script.svg
diff --git a/tools/editor/icons/source/icon_script_create.svg b/editor/icons/source/icon_script_create.svg
index 0cf16a9c3b..0cf16a9c3b 100644
--- a/tools/editor/icons/source/icon_script_create.svg
+++ b/editor/icons/source/icon_script_create.svg
diff --git a/tools/editor/icons/source/icon_script_remove.svg b/editor/icons/source/icon_script_remove.svg
index 1a0a0eebe3..1a0a0eebe3 100644
--- a/tools/editor/icons/source/icon_script_remove.svg
+++ b/editor/icons/source/icon_script_remove.svg
diff --git a/tools/editor/icons/source/icon_scroll_bar.svg b/editor/icons/source/icon_scroll_bar.svg
index 2f007c7c94..2f007c7c94 100644
--- a/tools/editor/icons/source/icon_scroll_bar.svg
+++ b/editor/icons/source/icon_scroll_bar.svg
diff --git a/tools/editor/icons/source/icon_scroll_container.svg b/editor/icons/source/icon_scroll_container.svg
index d694b646e0..d694b646e0 100644
--- a/tools/editor/icons/source/icon_scroll_container.svg
+++ b/editor/icons/source/icon_scroll_container.svg
diff --git a/tools/editor/icons/source/icon_segment_shape_2d.svg b/editor/icons/source/icon_segment_shape_2d.svg
index b509a31362..b509a31362 100644
--- a/tools/editor/icons/source/icon_segment_shape_2d.svg
+++ b/editor/icons/source/icon_segment_shape_2d.svg
diff --git a/tools/editor/icons/source/icon_shader.svg b/editor/icons/source/icon_shader.svg
index 1a2393fec2..1a2393fec2 100644
--- a/tools/editor/icons/source/icon_shader.svg
+++ b/editor/icons/source/icon_shader.svg
diff --git a/tools/editor/icons/source/icon_short_cut.svg b/editor/icons/source/icon_short_cut.svg
index 05069e8ea1..05069e8ea1 100644
--- a/tools/editor/icons/source/icon_short_cut.svg
+++ b/editor/icons/source/icon_short_cut.svg
diff --git a/tools/editor/icons/source/icon_signal.svg b/editor/icons/source/icon_signal.svg
index b4d3ff5ac8..b4d3ff5ac8 100644
--- a/tools/editor/icons/source/icon_signal.svg
+++ b/editor/icons/source/icon_signal.svg
diff --git a/tools/editor/icons/source/icon_skeleton.svg b/editor/icons/source/icon_skeleton.svg
index 2850b0331d..2850b0331d 100644
--- a/tools/editor/icons/source/icon_skeleton.svg
+++ b/editor/icons/source/icon_skeleton.svg
diff --git a/tools/editor/icons/source/icon_slider_joint.svg b/editor/icons/source/icon_slider_joint.svg
index 021a295186..021a295186 100644
--- a/tools/editor/icons/source/icon_slider_joint.svg
+++ b/editor/icons/source/icon_slider_joint.svg
diff --git a/tools/editor/icons/source/icon_slot.svg b/editor/icons/source/icon_slot.svg
index d613f1e1a4..d613f1e1a4 100644
--- a/tools/editor/icons/source/icon_slot.svg
+++ b/editor/icons/source/icon_slot.svg
diff --git a/tools/editor/icons/source/icon_snap.svg b/editor/icons/source/icon_snap.svg
index 321dedf6b6..321dedf6b6 100644
--- a/tools/editor/icons/source/icon_snap.svg
+++ b/editor/icons/source/icon_snap.svg
diff --git a/tools/editor/icons/source/icon_sound_room_params.svg b/editor/icons/source/icon_sound_room_params.svg
index a71c126ddc..a71c126ddc 100644
--- a/tools/editor/icons/source/icon_sound_room_params.svg
+++ b/editor/icons/source/icon_sound_room_params.svg
diff --git a/tools/editor/icons/source/icon_spatial.svg b/editor/icons/source/icon_spatial.svg
index 0d03754016..0d03754016 100644
--- a/tools/editor/icons/source/icon_spatial.svg
+++ b/editor/icons/source/icon_spatial.svg
diff --git a/tools/editor/icons/source/icon_spatial_sample_player.svg b/editor/icons/source/icon_spatial_sample_player.svg
index 9b5f5d9af6..9b5f5d9af6 100644
--- a/tools/editor/icons/source/icon_spatial_sample_player.svg
+++ b/editor/icons/source/icon_spatial_sample_player.svg
diff --git a/tools/editor/icons/source/icon_spatial_shader.svg b/editor/icons/source/icon_spatial_shader.svg
index 329354b716..329354b716 100644
--- a/tools/editor/icons/source/icon_spatial_shader.svg
+++ b/editor/icons/source/icon_spatial_shader.svg
diff --git a/tools/editor/icons/source/icon_spatial_stream_player.svg b/editor/icons/source/icon_spatial_stream_player.svg
index bd081a3dc2..bd081a3dc2 100644
--- a/tools/editor/icons/source/icon_spatial_stream_player.svg
+++ b/editor/icons/source/icon_spatial_stream_player.svg
diff --git a/tools/editor/icons/source/icon_sphere_shape.svg b/editor/icons/source/icon_sphere_shape.svg
index b1bca49f97..b1bca49f97 100644
--- a/tools/editor/icons/source/icon_sphere_shape.svg
+++ b/editor/icons/source/icon_sphere_shape.svg
diff --git a/tools/editor/icons/source/icon_spin_box.svg b/editor/icons/source/icon_spin_box.svg
index e0086ed12e..e0086ed12e 100644
--- a/tools/editor/icons/source/icon_spin_box.svg
+++ b/editor/icons/source/icon_spin_box.svg
diff --git a/tools/editor/icons/source/icon_spot_light.svg b/editor/icons/source/icon_spot_light.svg
index 04f5b42f4d..04f5b42f4d 100644
--- a/tools/editor/icons/source/icon_spot_light.svg
+++ b/editor/icons/source/icon_spot_light.svg
diff --git a/tools/editor/icons/source/icon_sprite.svg b/editor/icons/source/icon_sprite.svg
index 488bbf934d..488bbf934d 100644
--- a/tools/editor/icons/source/icon_sprite.svg
+++ b/editor/icons/source/icon_sprite.svg
diff --git a/tools/editor/icons/source/icon_sprite_3d.svg b/editor/icons/source/icon_sprite_3d.svg
index 4ea81f7ea2..4ea81f7ea2 100644
--- a/tools/editor/icons/source/icon_sprite_3d.svg
+++ b/editor/icons/source/icon_sprite_3d.svg
diff --git a/tools/editor/icons/source/icon_sprite_frames.svg b/editor/icons/source/icon_sprite_frames.svg
index dc445da773..dc445da773 100644
--- a/tools/editor/icons/source/icon_sprite_frames.svg
+++ b/editor/icons/source/icon_sprite_frames.svg
diff --git a/tools/editor/icons/source/icon_static_body.svg b/editor/icons/source/icon_static_body.svg
index fcaa2b7d3e..fcaa2b7d3e 100644
--- a/tools/editor/icons/source/icon_static_body.svg
+++ b/editor/icons/source/icon_static_body.svg
diff --git a/tools/editor/icons/source/icon_static_body_2d.svg b/editor/icons/source/icon_static_body_2d.svg
index 0ed3ef7cf0..0ed3ef7cf0 100644
--- a/tools/editor/icons/source/icon_static_body_2d.svg
+++ b/editor/icons/source/icon_static_body_2d.svg
diff --git a/tools/editor/icons/source/icon_stream_player.svg b/editor/icons/source/icon_stream_player.svg
index 618646bbed..618646bbed 100644
--- a/tools/editor/icons/source/icon_stream_player.svg
+++ b/editor/icons/source/icon_stream_player.svg
diff --git a/tools/editor/icons/source/icon_string.svg b/editor/icons/source/icon_string.svg
index f32e82256f..f32e82256f 100644
--- a/tools/editor/icons/source/icon_string.svg
+++ b/editor/icons/source/icon_string.svg
diff --git a/tools/editor/icons/source/icon_style_box_empty.svg b/editor/icons/source/icon_style_box_empty.svg
index c881fe1c10..c881fe1c10 100644
--- a/tools/editor/icons/source/icon_style_box_empty.svg
+++ b/editor/icons/source/icon_style_box_empty.svg
diff --git a/tools/editor/icons/source/icon_style_box_flat.svg b/editor/icons/source/icon_style_box_flat.svg
index 9071014ff3..9071014ff3 100644
--- a/tools/editor/icons/source/icon_style_box_flat.svg
+++ b/editor/icons/source/icon_style_box_flat.svg
diff --git a/tools/editor/icons/source/icon_style_box_texture.svg b/editor/icons/source/icon_style_box_texture.svg
index 30b1f1af68..30b1f1af68 100644
--- a/tools/editor/icons/source/icon_style_box_texture.svg
+++ b/editor/icons/source/icon_style_box_texture.svg
diff --git a/tools/editor/icons/source/icon_tab_container.svg b/editor/icons/source/icon_tab_container.svg
index 6c197a86f6..6c197a86f6 100644
--- a/tools/editor/icons/source/icon_tab_container.svg
+++ b/editor/icons/source/icon_tab_container.svg
diff --git a/tools/editor/icons/source/icon_tabs.svg b/editor/icons/source/icon_tabs.svg
index 79ed1e5910..79ed1e5910 100644
--- a/tools/editor/icons/source/icon_tabs.svg
+++ b/editor/icons/source/icon_tabs.svg
diff --git a/tools/editor/icons/source/icon_test_cube.svg b/editor/icons/source/icon_test_cube.svg
index c42c0bb674..c42c0bb674 100644
--- a/tools/editor/icons/source/icon_test_cube.svg
+++ b/editor/icons/source/icon_test_cube.svg
diff --git a/tools/editor/icons/source/icon_text_edit.svg b/editor/icons/source/icon_text_edit.svg
index 4d08e9e3b2..4d08e9e3b2 100644
--- a/tools/editor/icons/source/icon_text_edit.svg
+++ b/editor/icons/source/icon_text_edit.svg
diff --git a/tools/editor/icons/source/icon_texture.svg b/editor/icons/source/icon_texture.svg
index 39e88e592b..39e88e592b 100644
--- a/tools/editor/icons/source/icon_texture.svg
+++ b/editor/icons/source/icon_texture.svg
diff --git a/tools/editor/icons/source/icon_texture_button.svg b/editor/icons/source/icon_texture_button.svg
index ef447af082..ef447af082 100644
--- a/tools/editor/icons/source/icon_texture_button.svg
+++ b/editor/icons/source/icon_texture_button.svg
diff --git a/tools/editor/icons/source/icon_texture_progress.svg b/editor/icons/source/icon_texture_progress.svg
index 493dd7fd63..493dd7fd63 100644
--- a/tools/editor/icons/source/icon_texture_progress.svg
+++ b/editor/icons/source/icon_texture_progress.svg
diff --git a/tools/editor/icons/source/icon_texture_rect.svg b/editor/icons/source/icon_texture_rect.svg
index 88d9b4081f..88d9b4081f 100644
--- a/tools/editor/icons/source/icon_texture_rect.svg
+++ b/editor/icons/source/icon_texture_rect.svg
diff --git a/tools/editor/icons/source/icon_theme.svg b/editor/icons/source/icon_theme.svg
index 2cacb9755a..2cacb9755a 100644
--- a/tools/editor/icons/source/icon_theme.svg
+++ b/editor/icons/source/icon_theme.svg
diff --git a/tools/editor/icons/source/icon_tile_map.svg b/editor/icons/source/icon_tile_map.svg
index 28f75a97e5..28f75a97e5 100644
--- a/tools/editor/icons/source/icon_tile_map.svg
+++ b/editor/icons/source/icon_tile_map.svg
diff --git a/tools/editor/icons/source/icon_tile_set.svg b/editor/icons/source/icon_tile_set.svg
index e697f03888..e697f03888 100644
--- a/tools/editor/icons/source/icon_tile_set.svg
+++ b/editor/icons/source/icon_tile_set.svg
diff --git a/tools/editor/icons/source/icon_timer.svg b/editor/icons/source/icon_timer.svg
index 0615ab865a..0615ab865a 100644
--- a/tools/editor/icons/source/icon_timer.svg
+++ b/editor/icons/source/icon_timer.svg
diff --git a/tools/editor/icons/source/icon_tool_button.svg b/editor/icons/source/icon_tool_button.svg
index 1c5176c8c9..1c5176c8c9 100644
--- a/tools/editor/icons/source/icon_tool_button.svg
+++ b/editor/icons/source/icon_tool_button.svg
diff --git a/tools/editor/icons/source/icon_tool_move.svg b/editor/icons/source/icon_tool_move.svg
index 243b680dfe..243b680dfe 100644
--- a/tools/editor/icons/source/icon_tool_move.svg
+++ b/editor/icons/source/icon_tool_move.svg
diff --git a/tools/editor/icons/source/icon_tool_pan.svg b/editor/icons/source/icon_tool_pan.svg
index a93fc3d29d..a93fc3d29d 100644
--- a/tools/editor/icons/source/icon_tool_pan.svg
+++ b/editor/icons/source/icon_tool_pan.svg
diff --git a/tools/editor/icons/source/icon_tool_rotate.svg b/editor/icons/source/icon_tool_rotate.svg
index 817aee3995..817aee3995 100644
--- a/tools/editor/icons/source/icon_tool_rotate.svg
+++ b/editor/icons/source/icon_tool_rotate.svg
diff --git a/tools/editor/icons/source/icon_tool_scale.svg b/editor/icons/source/icon_tool_scale.svg
index 515bef3bb7..515bef3bb7 100644
--- a/tools/editor/icons/source/icon_tool_scale.svg
+++ b/editor/icons/source/icon_tool_scale.svg
diff --git a/tools/editor/icons/source/icon_tool_select.svg b/editor/icons/source/icon_tool_select.svg
index 2da6a3e6ba..2da6a3e6ba 100644
--- a/tools/editor/icons/source/icon_tool_select.svg
+++ b/editor/icons/source/icon_tool_select.svg
diff --git a/tools/editor/icons/source/icon_tools.svg b/editor/icons/source/icon_tools.svg
index f2b8cd9343..f2b8cd9343 100644
--- a/tools/editor/icons/source/icon_tools.svg
+++ b/editor/icons/source/icon_tools.svg
diff --git a/tools/editor/icons/source/icon_touch_screen_button.svg b/editor/icons/source/icon_touch_screen_button.svg
index 70abc964aa..70abc964aa 100644
--- a/tools/editor/icons/source/icon_touch_screen_button.svg
+++ b/editor/icons/source/icon_touch_screen_button.svg
diff --git a/tools/editor/icons/source/icon_track_add_key.svg b/editor/icons/source/icon_track_add_key.svg
index f550f922bb..f550f922bb 100644
--- a/tools/editor/icons/source/icon_track_add_key.svg
+++ b/editor/icons/source/icon_track_add_key.svg
diff --git a/tools/editor/icons/source/icon_track_add_key_hl.svg b/editor/icons/source/icon_track_add_key_hl.svg
index 1b45cf8c4a..1b45cf8c4a 100644
--- a/tools/editor/icons/source/icon_track_add_key_hl.svg
+++ b/editor/icons/source/icon_track_add_key_hl.svg
diff --git a/tools/editor/icons/source/icon_track_continuous.svg b/editor/icons/source/icon_track_continuous.svg
index 78b9dd3f4b..78b9dd3f4b 100644
--- a/tools/editor/icons/source/icon_track_continuous.svg
+++ b/editor/icons/source/icon_track_continuous.svg
diff --git a/tools/editor/icons/source/icon_track_discrete.svg b/editor/icons/source/icon_track_discrete.svg
index 381782cf6f..381782cf6f 100644
--- a/tools/editor/icons/source/icon_track_discrete.svg
+++ b/editor/icons/source/icon_track_discrete.svg
diff --git a/tools/editor/icons/source/icon_track_trigger.svg b/editor/icons/source/icon_track_trigger.svg
index 9c13791f70..9c13791f70 100644
--- a/tools/editor/icons/source/icon_track_trigger.svg
+++ b/editor/icons/source/icon_track_trigger.svg
diff --git a/tools/editor/icons/source/icon_translation.svg b/editor/icons/source/icon_translation.svg
index 389b8a40de..389b8a40de 100644
--- a/tools/editor/icons/source/icon_translation.svg
+++ b/editor/icons/source/icon_translation.svg
diff --git a/tools/editor/icons/source/icon_transpose.svg b/editor/icons/source/icon_transpose.svg
index ceccfecfa3..ceccfecfa3 100644
--- a/tools/editor/icons/source/icon_transpose.svg
+++ b/editor/icons/source/icon_transpose.svg
diff --git a/tools/editor/icons/source/icon_tree.svg b/editor/icons/source/icon_tree.svg
index b31fd38097..b31fd38097 100644
--- a/tools/editor/icons/source/icon_tree.svg
+++ b/editor/icons/source/icon_tree.svg
diff --git a/tools/editor/icons/source/icon_tween.svg b/editor/icons/source/icon_tween.svg
index 5cb5cad227..5cb5cad227 100644
--- a/tools/editor/icons/source/icon_tween.svg
+++ b/editor/icons/source/icon_tween.svg
diff --git a/tools/editor/icons/source/icon_unbone.svg b/editor/icons/source/icon_unbone.svg
index 7e4109f2ec..7e4109f2ec 100644
--- a/tools/editor/icons/source/icon_unbone.svg
+++ b/editor/icons/source/icon_unbone.svg
diff --git a/tools/editor/icons/source/icon_ungroup.svg b/editor/icons/source/icon_ungroup.svg
index f0b33465cd..f0b33465cd 100644
--- a/tools/editor/icons/source/icon_ungroup.svg
+++ b/editor/icons/source/icon_ungroup.svg
diff --git a/tools/editor/icons/source/icon_unlock.svg b/editor/icons/source/icon_unlock.svg
index b821d486ed..b821d486ed 100644
--- a/tools/editor/icons/source/icon_unlock.svg
+++ b/editor/icons/source/icon_unlock.svg
diff --git a/tools/editor/icons/source/icon_uv.svg b/editor/icons/source/icon_uv.svg
index 698a57fc0a..698a57fc0a 100644
--- a/tools/editor/icons/source/icon_uv.svg
+++ b/editor/icons/source/icon_uv.svg
diff --git a/tools/editor/icons/source/icon_v_box_container.svg b/editor/icons/source/icon_v_box_container.svg
index 9773b253fb..9773b253fb 100644
--- a/tools/editor/icons/source/icon_v_box_container.svg
+++ b/editor/icons/source/icon_v_box_container.svg
diff --git a/tools/editor/icons/source/icon_v_button_array.svg b/editor/icons/source/icon_v_button_array.svg
index aded4b401b..aded4b401b 100644
--- a/tools/editor/icons/source/icon_v_button_array.svg
+++ b/editor/icons/source/icon_v_button_array.svg
diff --git a/tools/editor/icons/source/icon_v_scroll_bar.svg b/editor/icons/source/icon_v_scroll_bar.svg
index 659dc39b0b..659dc39b0b 100644
--- a/tools/editor/icons/source/icon_v_scroll_bar.svg
+++ b/editor/icons/source/icon_v_scroll_bar.svg
diff --git a/tools/editor/icons/source/icon_v_separator.svg b/editor/icons/source/icon_v_separator.svg
index 7e5ce39ba0..7e5ce39ba0 100644
--- a/tools/editor/icons/source/icon_v_separator.svg
+++ b/editor/icons/source/icon_v_separator.svg
diff --git a/tools/editor/icons/source/icon_v_slider.svg b/editor/icons/source/icon_v_slider.svg
index 74b59cfce5..74b59cfce5 100644
--- a/tools/editor/icons/source/icon_v_slider.svg
+++ b/editor/icons/source/icon_v_slider.svg
diff --git a/tools/editor/icons/source/icon_v_split_container.svg b/editor/icons/source/icon_v_split_container.svg
index 4e7704eb4e..4e7704eb4e 100644
--- a/tools/editor/icons/source/icon_v_split_container.svg
+++ b/editor/icons/source/icon_v_split_container.svg
diff --git a/tools/editor/icons/source/icon_vector.svg b/editor/icons/source/icon_vector.svg
index 3260aa77ac..3260aa77ac 100644
--- a/tools/editor/icons/source/icon_vector.svg
+++ b/editor/icons/source/icon_vector.svg
diff --git a/tools/editor/icons/source/icon_vector2.svg b/editor/icons/source/icon_vector2.svg
index b7b157db01..b7b157db01 100644
--- a/tools/editor/icons/source/icon_vector2.svg
+++ b/editor/icons/source/icon_vector2.svg
diff --git a/tools/editor/icons/source/icon_vehicle_body.svg b/editor/icons/source/icon_vehicle_body.svg
index a168b98a99..a168b98a99 100644
--- a/tools/editor/icons/source/icon_vehicle_body.svg
+++ b/editor/icons/source/icon_vehicle_body.svg
diff --git a/tools/editor/icons/source/icon_vehicle_wheel.svg b/editor/icons/source/icon_vehicle_wheel.svg
index dff80c4d00..dff80c4d00 100644
--- a/tools/editor/icons/source/icon_vehicle_wheel.svg
+++ b/editor/icons/source/icon_vehicle_wheel.svg
diff --git a/tools/editor/icons/source/icon_video_player.svg b/editor/icons/source/icon_video_player.svg
index bfb499518b..bfb499518b 100644
--- a/tools/editor/icons/source/icon_video_player.svg
+++ b/editor/icons/source/icon_video_player.svg
diff --git a/tools/editor/icons/source/icon_viewport.svg b/editor/icons/source/icon_viewport.svg
index 631260ab33..631260ab33 100644
--- a/tools/editor/icons/source/icon_viewport.svg
+++ b/editor/icons/source/icon_viewport.svg
diff --git a/tools/editor/icons/source/icon_viewport_container.svg b/editor/icons/source/icon_viewport_container.svg
index 300b8390c4..300b8390c4 100644
--- a/tools/editor/icons/source/icon_viewport_container.svg
+++ b/editor/icons/source/icon_viewport_container.svg
diff --git a/tools/editor/icons/source/icon_viewport_sprite.svg b/editor/icons/source/icon_viewport_sprite.svg
index ab1ac198ce..ab1ac198ce 100644
--- a/tools/editor/icons/source/icon_viewport_sprite.svg
+++ b/editor/icons/source/icon_viewport_sprite.svg
diff --git a/tools/editor/icons/source/icon_viewport_texture.svg b/editor/icons/source/icon_viewport_texture.svg
index 4cf6532059..4cf6532059 100644
--- a/tools/editor/icons/source/icon_viewport_texture.svg
+++ b/editor/icons/source/icon_viewport_texture.svg
diff --git a/tools/editor/icons/source/icon_visibility_enabler.svg b/editor/icons/source/icon_visibility_enabler.svg
index 7c3bc54c99..7c3bc54c99 100644
--- a/tools/editor/icons/source/icon_visibility_enabler.svg
+++ b/editor/icons/source/icon_visibility_enabler.svg
diff --git a/tools/editor/icons/source/icon_visibility_enabler_2d.svg b/editor/icons/source/icon_visibility_enabler_2d.svg
index 1e7d1a751f..1e7d1a751f 100644
--- a/tools/editor/icons/source/icon_visibility_enabler_2d.svg
+++ b/editor/icons/source/icon_visibility_enabler_2d.svg
diff --git a/tools/editor/icons/source/icon_visibility_notifier.svg b/editor/icons/source/icon_visibility_notifier.svg
index b307a6162d..b307a6162d 100644
--- a/tools/editor/icons/source/icon_visibility_notifier.svg
+++ b/editor/icons/source/icon_visibility_notifier.svg
diff --git a/tools/editor/icons/source/icon_visibility_notifier_2d.svg b/editor/icons/source/icon_visibility_notifier_2d.svg
index dc2482f9e1..dc2482f9e1 100644
--- a/tools/editor/icons/source/icon_visibility_notifier_2d.svg
+++ b/editor/icons/source/icon_visibility_notifier_2d.svg
diff --git a/tools/editor/icons/source/icon_visible.svg b/editor/icons/source/icon_visible.svg
index 0185e1f3a9..0185e1f3a9 100644
--- a/tools/editor/icons/source/icon_visible.svg
+++ b/editor/icons/source/icon_visible.svg
diff --git a/tools/editor/icons/source/icon_visual_script.svg b/editor/icons/source/icon_visual_script.svg
index be4b47ca54..be4b47ca54 100644
--- a/tools/editor/icons/source/icon_visual_script.svg
+++ b/editor/icons/source/icon_visual_script.svg
diff --git a/tools/editor/icons/source/icon_visual_shader_port.svg b/editor/icons/source/icon_visual_shader_port.svg
index 9e80e0e9e9..9e80e0e9e9 100644
--- a/tools/editor/icons/source/icon_visual_shader_port.svg
+++ b/editor/icons/source/icon_visual_shader_port.svg
diff --git a/tools/editor/icons/source/icon_vu_empty.svg b/editor/icons/source/icon_vu_empty.svg
index c4c7a4e625..c4c7a4e625 100644
--- a/tools/editor/icons/source/icon_vu_empty.svg
+++ b/editor/icons/source/icon_vu_empty.svg
diff --git a/tools/editor/icons/source/icon_vu_full.svg b/editor/icons/source/icon_vu_full.svg
index 7084ddf204..7084ddf204 100644
--- a/tools/editor/icons/source/icon_vu_full.svg
+++ b/editor/icons/source/icon_vu_full.svg
diff --git a/tools/editor/icons/source/icon_warning.svg b/editor/icons/source/icon_warning.svg
index 4d39141a58..4d39141a58 100644
--- a/tools/editor/icons/source/icon_warning.svg
+++ b/editor/icons/source/icon_warning.svg
diff --git a/tools/editor/icons/source/icon_window_dialog.svg b/editor/icons/source/icon_window_dialog.svg
index 433ae48a55..433ae48a55 100644
--- a/tools/editor/icons/source/icon_window_dialog.svg
+++ b/editor/icons/source/icon_window_dialog.svg
diff --git a/tools/editor/icons/source/icon_world.svg b/editor/icons/source/icon_world.svg
index b2be396217..b2be396217 100644
--- a/tools/editor/icons/source/icon_world.svg
+++ b/editor/icons/source/icon_world.svg
diff --git a/tools/editor/icons/source/icon_world_2d.svg b/editor/icons/source/icon_world_2d.svg
index cb4427808a..cb4427808a 100644
--- a/tools/editor/icons/source/icon_world_2d.svg
+++ b/editor/icons/source/icon_world_2d.svg
diff --git a/tools/editor/icons/source/icon_world_environment.svg b/editor/icons/source/icon_world_environment.svg
index 912e348c81..912e348c81 100644
--- a/tools/editor/icons/source/icon_world_environment.svg
+++ b/editor/icons/source/icon_world_environment.svg
diff --git a/tools/editor/icons/source/icon_y_sort.svg b/editor/icons/source/icon_y_sort.svg
index 65990097c6..65990097c6 100644
--- a/tools/editor/icons/source/icon_y_sort.svg
+++ b/editor/icons/source/icon_y_sort.svg
diff --git a/tools/editor/icons/source/icon_zoom.svg b/editor/icons/source/icon_zoom.svg
index 811036b370..811036b370 100644
--- a/tools/editor/icons/source/icon_zoom.svg
+++ b/editor/icons/source/icon_zoom.svg
diff --git a/tools/editor/icons/source/icon_zoom_less.svg b/editor/icons/source/icon_zoom_less.svg
index 970b1954bb..970b1954bb 100644
--- a/tools/editor/icons/source/icon_zoom_less.svg
+++ b/editor/icons/source/icon_zoom_less.svg
diff --git a/tools/editor/icons/source/icon_zoom_more.svg b/editor/icons/source/icon_zoom_more.svg
index 87acdfb021..87acdfb021 100644
--- a/tools/editor/icons/source/icon_zoom_more.svg
+++ b/editor/icons/source/icon_zoom_more.svg
diff --git a/tools/editor/icons/source/icon_zoom_reset.svg b/editor/icons/source/icon_zoom_reset.svg
index a82f93dfea..a82f93dfea 100644
--- a/tools/editor/icons/source/icon_zoom_reset.svg
+++ b/editor/icons/source/icon_zoom_reset.svg
diff --git a/tools/editor/icons/xpmfix.sh b/editor/icons/xpmfix.sh
index a24dede3c9..a24dede3c9 100755
--- a/tools/editor/icons/xpmfix.sh
+++ b/editor/icons/xpmfix.sh
diff --git a/tools/editor/import/SCsub b/editor/import/SCsub
index f1fa50148f..f1fa50148f 100644
--- a/tools/editor/import/SCsub
+++ b/editor/import/SCsub
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
new file mode 100644
index 0000000000..7098e8812b
--- /dev/null
+++ b/editor/import/editor_import_collada.cpp
@@ -0,0 +1,2508 @@
+/*************************************************************************/
+/* editor_import_collada.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_import_collada.h"
+
+
+#include "scene/3d/spatial.h"
+#include "scene/3d/skeleton.h"
+#include "scene/3d/path.h"
+#include "scene/3d/camera.h"
+#include "scene/3d/light.h"
+#include "scene/animation/animation_player.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/resources/animation.h"
+#include "scene/resources/packed_scene.h"
+#include "os/os.h"
+#include "editor/collada/collada.h"
+#include "editor/editor_node.h"
+#include <iostream>
+
+
+struct ColladaImport {
+
+ Collada collada;
+ Spatial *scene;
+
+ Vector<Ref<Animation> > animations;
+
+ struct NodeMap {
+ //String path;
+ Spatial *node;
+ int bone;
+ List<int> anim_tracks;
+
+ NodeMap() { node=NULL; bone=-1; }
+ };
+
+ bool found_ambient;
+ Color ambient;
+ bool found_directional;
+ bool force_make_tangents;
+ bool apply_mesh_xform_to_vertices;
+ bool use_mesh_builtin_materials;
+ float bake_fps;
+
+
+
+ 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;
+ Map<Collada::Node*,Skeleton*> skeleton_map;
+
+ Map< Skeleton*, Map< String, int> > skeleton_bone_map;
+
+ Set<String> valid_animated_nodes;
+ Vector<int> valid_animated_properties;
+ Map<String,bool> bones_with_animation;
+
+ Error _populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_node, int &r_bone, int p_parent);
+ Error _create_scene_skeletons(Collada::Node *p_node);
+ Error _create_scene(Collada::Node *p_node, Spatial *p_parent);
+ Error _create_resources(Collada::Node *p_node);
+ Error _create_material(const String& p_material);
+ Error _create_mesh_surfaces(bool p_optimize, Ref<Mesh>& p_mesh, const Map<String,Collada::NodeGeometry::Material>& p_material_map, const Collada::MeshData &meshdata, const Transform& p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data, Vector<Ref<Mesh> > p_morph_meshes=Vector<Ref<Mesh> >(), bool p_for_morph=false, bool p_use_mesh_material=false);
+ Error load(const String& p_path, int p_flags, bool p_force_make_tangents=false);
+ void _fix_param_animation_tracks();
+ void create_animation(int p_clip,bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
+ void create_animations(bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
+
+ Set<String> tracks_in_clips;
+ Vector<String> missing_textures;
+
+ void _pre_process_lights(Collada::Node *p_node);
+
+ ColladaImport() {
+
+ found_ambient=false;
+ found_directional=false;
+ force_make_tangents=false;
+ apply_mesh_xform_to_vertices=true;
+ bake_fps=15;
+
+ }
+};
+
+
+Error ColladaImport::_populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_node, int &r_bone, int p_parent) {
+
+
+ if (p_node->type!=Collada::Node::TYPE_JOINT)
+ return OK;
+
+ Collada::NodeJoint *joint = static_cast<Collada::NodeJoint*>(p_node);
+
+ print_line("populating joint "+joint->name);
+ p_skeleton->add_bone(p_node->name);
+ if (p_parent>=0)
+ p_skeleton->set_bone_parent(r_bone,p_parent);
+
+ NodeMap nm;
+ 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;
+
+ if (collada.state.bone_rest_map.has(joint->sid)) {
+
+ p_skeleton->set_bone_rest(r_bone,collada.fix_transform(collada.state.bone_rest_map[joint->sid]));
+ //should map this bone to something for animation?
+ } else {
+ print_line("no rest: "+joint->sid);
+ WARN_PRINT("Joint has no rest..");
+ }
+
+
+ int id = r_bone++;
+ for(int i=0;i<p_node->children.size();i++) {
+
+ Error err = _populate_skeleton(p_skeleton,p_node->children[i],r_bone,id);
+ if (err)
+ return err;
+ }
+
+ return OK;
+}
+
+
+void ColladaImport::_pre_process_lights(Collada::Node *p_node) {
+
+
+ if (p_node->type==Collada::Node::TYPE_LIGHT) {
+
+
+ Collada::NodeLight *light=static_cast<Collada::NodeLight*>(p_node);
+ if (collada.state.light_data_map.has(light->light)) {
+
+ Collada::LightData &ld = collada.state.light_data_map[light->light];
+ if (ld.mode==Collada::LightData::MODE_AMBIENT) {
+ found_ambient=true;
+ ambient=ld.color;
+ }
+ if (ld.mode==Collada::LightData::MODE_DIRECTIONAL) {
+ found_directional=true;
+ }
+ }
+
+ }
+
+
+ for(int i=0;i<p_node->children.size();i++)
+ _pre_process_lights(p_node->children[i]);
+}
+
+Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) {
+
+
+ if (p_node->type==Collada::Node::TYPE_SKELETON) {
+
+ Skeleton *sk = memnew( Skeleton );
+ int bone = 0;
+
+ for(int i=0;i<p_node->children.size();i++) {
+
+ _populate_skeleton(sk,p_node->children[i],bone,-1);
+ }
+ sk->localize_rests(); //after creating skeleton, rests must be localized...!
+ skeleton_map[p_node]=sk;
+ }
+
+
+ for(int i=0;i<p_node->children.size();i++) {
+
+ Error err = _create_scene_skeletons(p_node->children[i]);
+ if (err)
+ return err;
+ }
+ return OK;
+
+}
+
+
+Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
+
+ Spatial * node=NULL;
+
+ switch(p_node->type) {
+
+ case Collada::Node::TYPE_NODE: {
+
+ node = memnew( Spatial );
+ } break;
+ case Collada::Node::TYPE_JOINT: {
+
+ return OK; // do nothing
+ } break;
+ case Collada::Node::TYPE_LIGHT: {
+
+ //node = memnew( Light)
+ Collada::NodeLight *light = static_cast<Collada::NodeLight*>(p_node);
+ if (collada.state.light_data_map.has(light->light)) {
+
+ Collada::LightData &ld = collada.state.light_data_map[light->light];
+
+ if (ld.mode==Collada::LightData::MODE_AMBIENT) {
+
+ if (found_directional)
+ return OK; //do nothing not needed
+
+ if (!bool(GLOBAL_DEF("collada/use_ambient",false)))
+ return OK;
+ //well, it's an ambient light..
+ Light *l = memnew( DirectionalLight );
+ //l->set_color(Light::COLOR_AMBIENT,ld.color);
+ //l->set_color(Light::COLOR_DIFFUSE,Color(0,0,0));
+ //l->set_color(Light::COLOR_SPECULAR,Color(0,0,0));
+ node = l;
+
+ } else if (ld.mode==Collada::LightData::MODE_DIRECTIONAL) {
+
+ //well, it's an ambient light..
+ Light *l = memnew( DirectionalLight );
+ /*
+ if (found_ambient) //use it here
+ l->set_color(Light::COLOR_AMBIENT,ambient);
+
+ l->set_color(Light::COLOR_DIFFUSE,ld.color);
+ l->set_color(Light::COLOR_SPECULAR,Color(1,1,1));
+ */
+ node = l;
+ } else {
+
+ Light *l;
+
+ if (ld.mode==Collada::LightData::MODE_OMNI)
+ l=memnew( OmniLight );
+ else {
+ l=memnew( SpotLight );
+ //l->set_parameter(Light::PARAM_SPOT_ANGLE,ld.spot_angle);
+ //l->set_parameter(Light::PARAM_SPOT_ATTENUATION,ld.spot_exp);
+ }
+
+ //
+ //l->set_color(Light::COLOR_DIFFUSE,ld.color);
+ //l->set_color(Light::COLOR_SPECULAR,Color(1,1,1));
+ //l->approximate_opengl_attenuation(ld.constant_att,ld.linear_att,ld.quad_att);
+ node=l;
+ }
+
+ } else {
+
+ node = memnew( Spatial );
+ }
+ } break;
+ case Collada::Node::TYPE_CAMERA: {
+
+ Collada::NodeCamera *cam = static_cast<Collada::NodeCamera*>(p_node);
+ Camera *camera = memnew( Camera );
+
+ if (collada.state.camera_data_map.has(cam->camera)) {
+
+ const Collada::CameraData &cd = collada.state.camera_data_map[cam->camera];
+
+ switch(cd.mode) {
+
+ case Collada::CameraData::MODE_ORTHOGONAL: {
+
+ if (cd.orthogonal.y_mag) {
+
+ camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT);
+ camera->set_orthogonal(cd.orthogonal.y_mag*2.0 ,cd.z_near,cd.z_far);
+
+ } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) {
+
+
+ camera->set_keep_aspect_mode(Camera::KEEP_WIDTH);
+ camera->set_orthogonal(cd.orthogonal.x_mag*2.0,cd.z_near,cd.z_far);
+ }
+
+ } break;
+ case Collada::CameraData::MODE_PERSPECTIVE: {
+
+ if (cd.perspective.y_fov) {
+
+ camera->set_perspective(cd.perspective.y_fov,cd.z_near,cd.z_far);
+
+ } else if (!cd.perspective.y_fov && cd.perspective.x_fov) {
+
+ camera->set_perspective(cd.perspective.x_fov / cd.aspect,cd.z_near,cd.z_far);
+ }
+
+ } break;
+ }
+
+ }
+
+ node=camera;
+
+ } break;
+ case Collada::Node::TYPE_GEOMETRY: {
+
+ Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(p_node);
+
+ if (collada.state.curve_data_map.has(ng->source)) {
+
+ node = memnew( Path );
+ } else {
+ //mesh since nothing else
+ node = memnew( MeshInstance );
+ node->cast_to<MeshInstance>()->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT,true);
+ }
+ } break;
+ case Collada::Node::TYPE_SKELETON: {
+
+ ERR_FAIL_COND_V(!skeleton_map.has(p_node),ERR_CANT_CREATE);
+ Skeleton *sk = skeleton_map[p_node];
+ node=sk;
+ } break;
+
+ }
+
+ if (p_node->name!="")
+ node->set_name(p_node->name);
+ 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;
+ node->set_transform(xf);
+ p_parent->add_child(node);
+ node->set_owner(scene);
+
+ if (p_node->empty_draw_type!="") {
+ node->set_meta("empty_draw_type", Variant(p_node->empty_draw_type));
+ }
+
+ for(int i=0;i<p_node->children.size();i++) {
+
+ Error err = _create_scene(p_node->children[i],node);
+ if (err)
+ return err;
+ }
+ return OK;
+}
+
+
+Error ColladaImport::_create_material(const String& p_target) {
+
+ ERR_FAIL_COND_V(material_cache.has(p_target),ERR_ALREADY_EXISTS);
+ ERR_FAIL_COND_V(!collada.state.material_map.has(p_target),ERR_INVALID_PARAMETER);
+ Collada::Material &src_mat=collada.state.material_map[p_target];
+ ERR_FAIL_COND_V(!collada.state.effect_map.has(src_mat.instance_effect),ERR_INVALID_PARAMETER);
+ Collada::Effect &effect=collada.state.effect_map[src_mat.instance_effect];
+
+ Ref<FixedSpatialMaterial> material= memnew( FixedSpatialMaterial );
+
+ if (src_mat.name!="")
+ material->set_name(src_mat.name);
+ else if (effect.name!="")
+ material->set_name(effect.name);
+
+ // DIFFUSE
+
+ if (effect.diffuse.texture!="") {
+
+ String texfile = effect.get_texture_path(effect.diffuse.texture,collada);
+ if (texfile!="") {
+
+ Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
+ if (texture.is_valid()) {
+
+ material->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,texture);
+ material->set_albedo(Color(1,1,1,1));
+ //material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1,1));
+ } else {
+ missing_textures.push_back(texfile.get_file());
+ }
+ }
+ } else {
+ //material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,effect.diffuse.color);
+ }
+
+ // SPECULAR
+
+ if (effect.specular.texture!="") {
+
+ String texfile = effect.get_texture_path(effect.specular.texture,collada);
+ if (texfile!="") {
+
+ Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
+ if (texture.is_valid()) {
+ material->set_texture(FixedSpatialMaterial::TEXTURE_SPECULAR,texture);
+ material->set_specular(Color(1,1,1,1));
+
+ //material->set_texture(FixedSpatialMaterial::PARAM_SPECULAR,texture);
+ //material->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR,Color(1,1,1,1));
+ } else {
+ missing_textures.push_back(texfile.get_file());
+ }
+
+ }
+ } else {
+ material->set_metalness(effect.specular.color.get_v());
+ }
+
+
+ // EMISSION
+
+ if (effect.emission.texture!="") {
+
+ String texfile = effect.get_texture_path(effect.emission.texture,collada);
+ if (texfile!="") {
+
+ Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
+ if (texture.is_valid()) {
+
+ material->set_feature(FixedSpatialMaterial::FEATURE_EMISSION,true);
+ material->set_texture(FixedSpatialMaterial::TEXTURE_EMISSION,texture);
+ material->set_emission(Color(1,1,1,1));
+
+ //material->set_parameter(FixedSpatialMaterial::PARAM_EMISSION,Color(1,1,1,1));
+ }else {
+ missing_textures.push_back(texfile.get_file());
+ }
+
+ }
+ } else {
+ if (effect.emission.color!=Color()) {
+ material->set_feature(FixedSpatialMaterial::FEATURE_EMISSION,true);
+ material->set_emission(effect.emission.color);
+ }
+ }
+
+ // NORMAL
+
+ if (effect.bump.texture!="") {
+
+ String texfile = effect.get_texture_path(effect.bump.texture,collada);
+ if (texfile!="") {
+
+ Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
+ if (texture.is_valid()) {
+ material->set_feature(FixedSpatialMaterial::FEATURE_NORMAL_MAPPING,true);
+ material->set_texture(FixedSpatialMaterial::TEXTURE_NORMAL,texture);
+ //material->set_emission(Color(1,1,1,1));
+
+ //material->set_texture(FixedSpatialMaterial::PARAM_NORMAL,texture);
+ }else {
+ //missing_textures.push_back(texfile.get_file());
+ }
+
+ }
+ }
+
+
+ float roughness = Math::sqrt(1.0-((Math::log(effect.shininess)/Math::log(2.0))/8.0)); //not very right..
+ material->set_roughness(roughness);
+
+ if (effect.double_sided) {
+ material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ }
+ material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,effect.unshaded);
+
+
+
+ material_cache[p_target]=material;
+ return OK;
+}
+
+
+static void _generate_normals(const PoolVector<int>& p_indices,const PoolVector<Vector3>& p_vertices,PoolVector<Vector3>&r_normals) {
+
+
+ r_normals.resize(p_vertices.size());
+ PoolVector<Vector3>::Write narrayw = r_normals.write();
+
+ int iacount=p_indices.size()/3;
+ PoolVector<int>::Read index_arrayr = p_indices.read();
+ PoolVector<Vector3>::Read vertex_arrayr = p_vertices.read();
+
+ for(int idx=0;idx<iacount;idx++) {
+
+ Vector3 v[3]={
+ vertex_arrayr[index_arrayr[idx*3+0]],
+ vertex_arrayr[index_arrayr[idx*3+1]],
+ vertex_arrayr[index_arrayr[idx*3+2]]
+ };
+
+ Vector3 normal = Plane(v[0],v[1],v[2]).normal;
+
+ narrayw[index_arrayr[idx*3+0]]+=normal;
+ narrayw[index_arrayr[idx*3+1]]+=normal;
+ narrayw[index_arrayr[idx*3+2]]+=normal;
+ }
+
+ int vlen=p_vertices.size();
+
+ for(int idx=0;idx<vlen;idx++) {
+ narrayw[idx].normalize();
+ }
+
+}
+
+
+static void _generate_tangents_and_binormals(const PoolVector<int>& p_indices,const PoolVector<Vector3>& p_vertices,const PoolVector<Vector3>& p_uvs,const PoolVector<Vector3>& p_normals,PoolVector<real_t>&r_tangents) {
+
+ int vlen=p_vertices.size();
+
+ Vector<Vector3> tangents;
+ tangents.resize(vlen);
+ Vector<Vector3> binormals;
+ binormals.resize(vlen);
+
+
+ int iacount=p_indices.size()/3;
+
+ PoolVector<int>::Read index_arrayr = p_indices.read();
+ PoolVector<Vector3>::Read vertex_arrayr = p_vertices.read();
+ PoolVector<Vector3>::Read narrayr = p_normals.read();
+ PoolVector<Vector3>::Read uvarrayr = p_uvs.read();
+
+
+ for(int idx=0;idx<iacount;idx++) {
+
+
+ Vector3 v1 = vertex_arrayr[ index_arrayr[idx*3+0] ];
+ Vector3 v2 = vertex_arrayr[ index_arrayr[idx*3+1] ];
+ Vector3 v3 = vertex_arrayr[ index_arrayr[idx*3+2] ];
+
+ Vector3 w1 = uvarrayr[ index_arrayr[idx*3+0] ];
+ Vector3 w2 = uvarrayr[ index_arrayr[idx*3+1] ];
+ Vector3 w3 = uvarrayr[ index_arrayr[idx*3+2] ];
+
+ real_t x1 = v2.x - v1.x;
+ real_t x2 = v3.x - v1.x;
+ real_t y1 = v2.y - v1.y;
+ real_t y2 = v3.y - v1.y;
+ real_t z1 = v2.z - v1.z;
+ real_t z2 = v3.z - v1.z;
+
+ real_t s1 = w2.x - w1.x;
+ real_t s2 = w3.x - w1.x;
+ real_t t1 = w2.y - w1.y;
+ real_t t2 = w3.y - w1.y;
+
+ real_t r = (s1 * t2 - s2 * t1);
+
+ Vector3 tangent;
+ Vector3 binormal;
+
+ if (r==0) {
+
+ binormal=Vector3();
+ tangent=Vector3();
+ } else {
+ tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
+ (t2 * z1 - t1 * z2) * r).normalized();
+ binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
+ (s1 * z2 - s2 * z1) * r).normalized();
+ }
+
+ tangents[ index_arrayr[idx*3+0] ]+=tangent;
+ binormals[ index_arrayr[idx*3+0] ]+=binormal;
+ tangents[ index_arrayr[idx*3+1] ]+=tangent;
+ binormals[ index_arrayr[idx*3+1] ]+=binormal;
+ tangents[ index_arrayr[idx*3+2] ]+=tangent;
+ binormals[ index_arrayr[idx*3+2] ]+=binormal;
+
+ //print_line(itos(idx)+" tangent: "+tangent);
+ //print_line(itos(idx)+" binormal: "+binormal);
+ }
+
+ r_tangents.resize(vlen*4);
+ PoolVector<real_t>::Write tarrayw = r_tangents.write();
+
+ for(int idx=0;idx<vlen;idx++) {
+ Vector3 tangent = tangents[idx];
+ Vector3 bingen = narrayr[idx].cross(tangent);
+ float dir;
+ if (bingen.dot(binormals[idx]) < 0 )
+ dir=-1.0;
+ else
+ dir=+1.0;
+
+ tarrayw[idx*4+0]=tangent.x;
+ tarrayw[idx*4+1]=tangent.y;
+ tarrayw[idx*4+2]=tangent.z;
+ tarrayw[idx*4+3]=dir;
+ }
+}
+
+Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > p_morph_meshes,bool p_for_morph,bool p_use_mesh_material) {
+
+
+ bool local_xform_mirror=p_local_xform.basis.determinant() < 0;
+
+ if (p_morph_data) {
+
+ //add morphie target
+ ERR_FAIL_COND_V( !p_morph_data->targets.has("MORPH_TARGET"), ERR_INVALID_DATA );
+ String mt = p_morph_data->targets["MORPH_TARGET"];
+ ERR_FAIL_COND_V( !p_morph_data->sources.has(mt), ERR_INVALID_DATA);
+ int morph_targets = p_morph_data->sources[mt].sarray.size();
+ for(int i=0;i<morph_targets;i++) {
+
+ String target = p_morph_data->sources[mt].sarray[i];
+ ERR_FAIL_COND_V( !collada.state.mesh_data_map.has(target), ERR_INVALID_DATA );
+ String name = collada.state.mesh_data_map[target].name;
+
+ p_mesh->add_blend_shape(name);
+ }
+ if (p_morph_data->mode=="RELATIVE")
+ p_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_RELATIVE);
+ else if (p_morph_data->mode=="NORMALIZED")
+ p_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
+ }
+
+
+ int surface=0;
+ for(int p_i = 0; p_i < meshdata.primitives.size(); p_i ++ ) {
+
+
+
+ const Collada::MeshData::Primitives& p = meshdata.primitives[p_i];
+
+ /* VERTEX SOURCE */
+ ERR_FAIL_COND_V(!p.sources.has("VERTEX"),ERR_INVALID_DATA);
+
+ String vertex_src_id = p.sources["VERTEX"].source;
+ int vertex_ofs=p.sources["VERTEX"].offset;
+
+ ERR_FAIL_COND_V(!meshdata.vertices.has(vertex_src_id),ERR_INVALID_DATA);
+
+ ERR_FAIL_COND_V(!meshdata.vertices[vertex_src_id].sources.has("POSITION"),ERR_INVALID_DATA);
+ String position_src_id = meshdata.vertices[vertex_src_id].sources["POSITION"];
+
+ ERR_FAIL_COND_V(!meshdata.sources.has(position_src_id),ERR_INVALID_DATA);
+
+ const Collada::MeshData::Source *vertex_src=&meshdata.sources[position_src_id];
+
+ /* NORMAL SOURCE */
+
+ const Collada::MeshData::Source *normal_src=NULL;
+ int normal_ofs=0;
+
+ if (p.sources.has("NORMAL")) {
+
+ String normal_source_id = p.sources["NORMAL"].source;
+ normal_ofs = p.sources["NORMAL"].offset;
+ ERR_FAIL_COND_V( !meshdata.sources.has(normal_source_id),ERR_INVALID_DATA);
+ normal_src=&meshdata.sources[normal_source_id];
+ }
+
+ const Collada::MeshData::Source *binormal_src=NULL;
+ int binormal_ofs=0;
+
+ if (p.sources.has("TEXBINORMAL")) {
+
+ String binormal_source_id = p.sources["TEXBINORMAL"].source;
+ binormal_ofs = p.sources["TEXBINORMAL"].offset;
+ ERR_FAIL_COND_V( !meshdata.sources.has(binormal_source_id),ERR_INVALID_DATA);
+ binormal_src=&meshdata.sources[binormal_source_id];
+ }
+
+ const Collada::MeshData::Source *tangent_src=NULL;
+ int tangent_ofs=0;
+
+ if (p.sources.has("TEXTANGENT")) {
+
+ String tangent_source_id = p.sources["TEXTANGENT"].source;
+ tangent_ofs = p.sources["TEXTANGENT"].offset;
+ ERR_FAIL_COND_V( !meshdata.sources.has(tangent_source_id),ERR_INVALID_DATA);
+ tangent_src=&meshdata.sources[tangent_source_id];
+ }
+
+
+ const Collada::MeshData::Source *uv_src=NULL;
+ int uv_ofs=0;
+
+ if (p.sources.has("TEXCOORD0")) {
+
+ String uv_source_id = p.sources["TEXCOORD0"].source;
+ uv_ofs = p.sources["TEXCOORD0"].offset;
+ ERR_FAIL_COND_V( !meshdata.sources.has(uv_source_id),ERR_INVALID_DATA);
+ uv_src=&meshdata.sources[uv_source_id];
+ }
+
+ const Collada::MeshData::Source *uv2_src=NULL;
+ int uv2_ofs=0;
+
+ if (p.sources.has("TEXCOORD1")) {
+
+ String uv2_source_id = p.sources["TEXCOORD1"].source;
+ uv2_ofs = p.sources["TEXCOORD1"].offset;
+ ERR_FAIL_COND_V( !meshdata.sources.has(uv2_source_id),ERR_INVALID_DATA);
+ uv2_src=&meshdata.sources[uv2_source_id];
+ }
+
+
+ const Collada::MeshData::Source *color_src=NULL;
+ int color_ofs=0;
+
+ if (p.sources.has("COLOR")) {
+
+ String color_source_id = p.sources["COLOR"].source;
+ color_ofs = p.sources["COLOR"].offset;
+ ERR_FAIL_COND_V( !meshdata.sources.has(color_source_id), ERR_INVALID_DATA );
+ color_src=&meshdata.sources[color_source_id];
+ }
+
+ //find largest source..
+
+ /************************/
+ /* ADD WEIGHTS IF EXIST */
+ /************************/
+
+ Map<int,Vector<Collada::Vertex::Weight> > pre_weights;
+
+ bool has_weights=false;
+
+ if (skin_controller) {
+
+ const Collada::SkinControllerData::Source *weight_src=NULL;
+ int weight_ofs=0;
+
+ if (skin_controller->weights.sources.has("WEIGHT")) {
+
+ String weight_id = skin_controller->weights.sources["WEIGHT"].source;
+ weight_ofs = skin_controller->weights.sources["WEIGHT"].offset;
+ if (skin_controller->sources.has(weight_id)) {
+
+ weight_src = &skin_controller->sources[weight_id];
+
+ }
+ }
+
+ int joint_ofs=0;
+
+ if (skin_controller->weights.sources.has("JOINT")) {
+
+ joint_ofs = skin_controller->weights.sources["JOINT"].offset;
+ }
+
+ //should be OK, given this was pre-checked.
+
+ int index_ofs=0;
+ int wstride = skin_controller->weights.sources.size();
+ for(int w_i=0;w_i<skin_controller->weights.sets.size();w_i++) {
+
+ int amount = skin_controller->weights.sets[w_i];
+
+ Vector<Collada::Vertex::Weight> weights;
+
+ for (int a_i=0;a_i<amount;a_i++) {
+
+ Collada::Vertex::Weight w;
+
+ int read_from = index_ofs+a_i*wstride;
+ ERR_FAIL_INDEX_V(read_from+wstride-1,skin_controller->weights.indices.size(),ERR_INVALID_DATA);
+ int weight_index = skin_controller->weights.indices[read_from+weight_ofs];
+ ERR_FAIL_INDEX_V(weight_index,weight_src->array.size(),ERR_INVALID_DATA);
+
+ w.weight = weight_src->array[weight_index];
+
+ int bone_index = skin_controller->weights.indices[read_from+joint_ofs];
+ if (bone_index==-1)
+ continue; //ignore this weight (refers to bind shape)
+ ERR_FAIL_INDEX_V(bone_index,bone_remap.size(),ERR_INVALID_DATA);
+
+ w.bone_idx=bone_remap[bone_index];
+
+
+ weights.push_back(w);
+ }
+
+ /* FIX WEIGHTS */
+
+
+
+ weights.sort();
+
+ if (weights.size()>4) {
+ //cap to 4 and make weights add up 1
+ weights.resize(4);
+
+ }
+
+ //make sure weights allways add up to 1
+ float total=0;
+ for(int i=0;i<weights.size();i++)
+ total+=weights[i].weight;
+ if (total)
+ for(int i=0;i<weights.size();i++)
+ weights[i].weight/=total;
+
+ if (weights.size()==0 || total==0) { //if nothing, add a weight to bone 0
+ //no weights assigned
+ Collada::Vertex::Weight w;
+ w.bone_idx=0;
+ w.weight=1.0;
+ weights.clear();
+ weights.push_back(w);
+
+ }
+
+ pre_weights[w_i]=weights;
+
+ /*
+ for(Set<int>::Element *E=vertex_map[w_i].front();E;E=E->next()) {
+
+ int dst = E->get();
+ ERR_EXPLAIN("invalid vertex index in array");
+ ERR_FAIL_INDEX_V(dst,vertex_array.size(),ERR_INVALID_DATA);
+ vertex_array[dst].weights=weights;
+
+ }*/
+
+
+
+
+ index_ofs+=wstride*amount;
+
+ }
+
+ //vertices need to be localized
+ has_weights=true;
+
+ }
+
+ Set<Collada::Vertex> vertex_set; //vertex set will be the vertices
+ List<int> indices_list; //indices will be the indices
+ //Map<int,Set<int> > vertex_map; //map vertices (for setting skinning/morph)
+
+ /**************************/
+ /* CREATE PRIMITIVE ARRAY */
+ /**************************/
+
+ // The way collada uses indices is more optimal, and friendlier with 3D modelling sofware,
+ // because it can index everything, not only vertices (similar to how the WII works).
+ // This is, however, more incompatible with standard video cards, so arrays must be converted.
+ // Must convert to GL/DX format.
+
+ int _prim_ofs=0;
+ int vertidx=0;
+ for(int p_i=0;p_i<p.count;p_i++) {
+
+
+ int amount;
+ if (p.polygons.size()) {
+
+ ERR_FAIL_INDEX_V(p_i,p.polygons.size(),ERR_INVALID_DATA);
+ amount=p.polygons[p_i];
+ } else {
+ amount=3; //triangles;
+ }
+
+ //COLLADA_PRINT("amount: "+itos(amount));
+
+ int prev2[2]={0,0};
+
+ for(int j=0;j<amount;j++) {
+
+ int src=_prim_ofs;
+ //_prim_ofs+=p.sources.size()
+
+ ERR_FAIL_INDEX_V(src,p.indices.size(),ERR_INVALID_DATA);
+
+ Collada::Vertex vertex;
+ if (!p_optimize)
+ vertex.uid=vertidx++;
+
+
+
+ int vertex_index=p.indices[src+vertex_ofs]; //used for index field (later used by controllers)
+ int vertex_pos = (vertex_src->stride?vertex_src->stride:3) * vertex_index;
+ ERR_FAIL_INDEX_V(vertex_pos,vertex_src->array.size(),ERR_INVALID_DATA);
+ vertex.vertex=Vector3(vertex_src->array[vertex_pos+0],vertex_src->array[vertex_pos+1],vertex_src->array[vertex_pos+2]);
+
+ if (pre_weights.has(vertex_index)) {
+ vertex.weights=pre_weights[vertex_index];
+ }
+
+ if (normal_src) {
+
+
+
+ int normal_pos = (normal_src->stride?normal_src->stride:3) * p.indices[src+normal_ofs];
+ ERR_FAIL_INDEX_V(normal_pos,normal_src->array.size(),ERR_INVALID_DATA);
+ vertex.normal=Vector3(normal_src->array[normal_pos+0],normal_src->array[normal_pos+1],normal_src->array[normal_pos+2]);
+ vertex.normal=vertex.normal.snapped(0.001);
+
+
+ if (tangent_src && binormal_src) {
+
+ int binormal_pos = (binormal_src->stride?binormal_src->stride:3) * p.indices[src+binormal_ofs];
+ ERR_FAIL_INDEX_V(binormal_pos,binormal_src->array.size(),ERR_INVALID_DATA);
+ Vector3 binormal =Vector3(binormal_src->array[binormal_pos+0],binormal_src->array[binormal_pos+1],binormal_src->array[binormal_pos+2]);
+
+ int tangent_pos = (tangent_src->stride?tangent_src->stride:3) * p.indices[src+tangent_ofs];
+ ERR_FAIL_INDEX_V(tangent_pos,tangent_src->array.size(),ERR_INVALID_DATA);
+ Vector3 tangent =Vector3(tangent_src->array[tangent_pos+0],tangent_src->array[tangent_pos+1],tangent_src->array[tangent_pos+2]);
+
+ vertex.tangent.normal=tangent;
+ vertex.tangent.d= vertex.normal.cross(tangent).dot(binormal) > 0 ? 1 : -1;
+ }
+
+ }
+
+
+ if (uv_src) {
+
+ int uv_pos = (uv_src->stride?uv_src->stride:2) * p.indices[src+uv_ofs];
+ ERR_FAIL_INDEX_V(uv_pos,uv_src->array.size(),ERR_INVALID_DATA);
+ vertex.uv=Vector3(uv_src->array[uv_pos+0],1.0-uv_src->array[uv_pos+1],0);
+ }
+
+ if (uv2_src) {
+
+ int uv2_pos = (uv2_src->stride?uv2_src->stride:2) * p.indices[src+uv2_ofs];
+ ERR_FAIL_INDEX_V(uv2_pos,uv2_src->array.size(),ERR_INVALID_DATA);
+ vertex.uv2=Vector3(uv2_src->array[uv2_pos+0],1.0-uv2_src->array[uv2_pos+1],0);
+ }
+
+ if (color_src) {
+
+ int color_pos = (color_src->stride?color_src->stride:3) * p.indices[src+color_ofs]; // colors are RGB in collada..
+ ERR_FAIL_INDEX_V(color_pos,color_src->array.size(),ERR_INVALID_DATA);
+ vertex.color=Color(color_src->array[color_pos+0],color_src->array[color_pos+1],color_src->array[color_pos+2],(color_src->stride>3)?color_src->array[color_pos+3]:1.0);
+
+ }
+
+#ifndef NO_UP_AXIS_SWAP
+ if (collada.state.up_axis==Vector3::AXIS_Z) {
+
+ SWAP( vertex.vertex.z, vertex.vertex.y );
+ vertex.vertex.z = -vertex.vertex.z;
+ SWAP( vertex.normal.z, vertex.normal.y );
+ vertex.normal.z = -vertex.normal.z;
+ SWAP( vertex.tangent.normal.z, vertex.tangent.normal.y );
+ vertex.tangent.normal.z = -vertex.tangent.normal.z;
+
+ }
+
+#endif
+
+ vertex.fix_unit_scale(collada);
+ int index=0;
+ //COLLADA_PRINT("vertex: "+vertex.vertex);
+
+ if (vertex_set.has(vertex)) {
+
+ index=vertex_set.find(vertex)->get().idx;
+ } else {
+
+ index=vertex_set.size();
+ vertex.idx=index;
+ vertex_set.insert(vertex);
+ }
+
+ /* if (!vertex_map.has(vertex_index))
+ vertex_map[vertex_index]=Set<int>();
+ vertex_map[vertex_index].insert(index); //should be outside..*/
+ //build triangles if needed
+ if (j==0)
+ prev2[0]=index;
+
+ if (j>=2) {
+ //insert indices in reverse order (collada uses CCW as frontface)
+ if (local_xform_mirror) {
+
+ indices_list.push_back(prev2[0]);
+ indices_list.push_back(prev2[1]);
+ indices_list.push_back(index);
+
+ } else {
+ indices_list.push_back(prev2[0]);
+ indices_list.push_back(index);
+ indices_list.push_back(prev2[1]);
+ }
+ }
+
+ prev2[1]=index;
+ _prim_ofs+=p.vertex_size;
+ }
+
+ }
+
+
+
+ Vector<Collada::Vertex> vertex_array; //there we go, vertex array
+
+ vertex_array.resize(vertex_set.size());
+ for(Set<Collada::Vertex>::Element *F=vertex_set.front();F;F=F->next()) {
+
+ vertex_array[F->get().idx]=F->get();
+ }
+
+
+ if (has_weights) {
+
+ //if skeleton, localize
+ Transform local_xform = p_local_xform;
+ for(int i=0;i<vertex_array.size();i++) {
+
+ vertex_array[i].vertex=local_xform.xform(vertex_array[i].vertex);
+ vertex_array[i].normal=local_xform.basis.xform(vertex_array[i].normal).normalized();
+ vertex_array[i].tangent.normal=local_xform.basis.xform(vertex_array[i].tangent.normal).normalized();
+ if (local_xform_mirror) {
+ //i shouldn't do this? wtf?
+ //vertex_array[i].normal*=-1.0;
+ //vertex_array[i].tangent.normal*=-1.0;
+ }
+ }
+ }
+
+
+ PoolVector<int> index_array;
+ index_array.resize(indices_list.size());
+ PoolVector<int>::Write index_arrayw = index_array.write();
+
+ int iidx=0;
+ for(List<int>::Element *F=indices_list.front();F;F=F->next()) {
+
+ index_arrayw[iidx++]=F->get();
+ }
+
+ index_arrayw=PoolVector<int>::Write();
+
+
+ /*****************/
+ /* MAKE SURFACES */
+ /*****************/
+
+
+ {
+
+ Ref<FixedSpatialMaterial> material;
+
+ //find material
+ Mesh::PrimitiveType primitive=Mesh::PRIMITIVE_TRIANGLES;
+
+ {
+
+ if (p_material_map.has(p.material)) {
+ String target=p_material_map[p.material].target;
+
+ if (!material_cache.has(target)) {
+ Error err = _create_material(target);
+ if (!err)
+ material=material_cache[target];
+ } else
+ material=material_cache[target];
+
+ } else if (p.material!=""){
+ print_line("Warning, unreferenced material in geometry instance: "+p.material);
+ }
+ }
+
+
+
+ PoolVector<Vector3> final_vertex_array;
+ PoolVector<Vector3> final_normal_array;
+ PoolVector<float> final_tangent_array;
+ PoolVector<Color> final_color_array;
+ PoolVector<Vector3> final_uv_array;
+ PoolVector<Vector3> final_uv2_array;
+ PoolVector<int> final_bone_array;
+ PoolVector<float> final_weight_array;
+
+ uint32_t final_format=0;
+
+ //create format
+ final_format=Mesh::ARRAY_FORMAT_VERTEX|Mesh::ARRAY_FORMAT_INDEX;
+
+ if (normal_src) {
+ final_format|=Mesh::ARRAY_FORMAT_NORMAL;
+ if (uv_src && binormal_src && tangent_src) {
+ final_format|=Mesh::ARRAY_FORMAT_TANGENT;
+ }
+
+ }
+
+
+
+ if (color_src)
+ final_format|=Mesh::ARRAY_FORMAT_COLOR;
+ if (uv_src)
+ final_format|=Mesh::ARRAY_FORMAT_TEX_UV;
+ if (uv2_src)
+ final_format|=Mesh::ARRAY_FORMAT_TEX_UV2;
+
+ if (has_weights) {
+ final_format|=Mesh::ARRAY_FORMAT_WEIGHTS;
+ final_format|=Mesh::ARRAY_FORMAT_BONES;
+ }
+
+
+ //set arrays
+
+ int vlen = vertex_array.size();
+ { //vertices
+
+ PoolVector<Vector3> varray;
+ varray.resize(vertex_array.size());
+
+ PoolVector<Vector3>::Write varrayw = varray.write();
+
+ for(int k=0;k<vlen;k++)
+ varrayw[k]=vertex_array[k].vertex;
+
+ varrayw = PoolVector<Vector3>::Write();
+ final_vertex_array=varray;
+
+ }
+
+
+ if (uv_src) { //compute uv first, may be needed for computing tangent/bionrmal
+ PoolVector<Vector3> uvarray;
+ uvarray.resize(vertex_array.size());
+ PoolVector<Vector3>::Write uvarrayw = uvarray.write();
+
+ for(int k=0;k<vlen;k++) {
+ uvarrayw[k]=vertex_array[k].uv;
+ }
+
+ uvarrayw = PoolVector<Vector3>::Write();
+ final_uv_array=uvarray;
+
+ }
+
+ if (uv2_src) { //compute uv first, may be needed for computing tangent/bionrmal
+ PoolVector<Vector3> uv2array;
+ uv2array.resize(vertex_array.size());
+ PoolVector<Vector3>::Write uv2arrayw = uv2array.write();
+
+ for(int k=0;k<vlen;k++) {
+ uv2arrayw[k]=vertex_array[k].uv2;
+ }
+
+ uv2arrayw = PoolVector<Vector3>::Write();
+ final_uv2_array=uv2array;
+
+ }
+
+ if (normal_src) {
+ PoolVector<Vector3> narray;
+ narray.resize(vertex_array.size());
+ PoolVector<Vector3>::Write narrayw = narray.write();
+
+ for(int k=0;k<vlen;k++) {
+ narrayw[k]=vertex_array[k].normal;
+ }
+
+ narrayw = PoolVector<Vector3>::Write();
+ final_normal_array=narray;
+
+ /*
+ PoolVector<Vector3> altnaray;
+ _generate_normals(index_array,final_vertex_array,altnaray);
+
+ for(int i=0;i<altnaray.size();i++)
+ print_line(rtos(altnaray[i].dot(final_normal_array[i])));
+ */
+
+ } else if (primitive==Mesh::PRIMITIVE_TRIANGLES) {
+ //generate normals (even if unused later)
+
+ _generate_normals(index_array,final_vertex_array,final_normal_array);
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_line("Collada: Triangle mesh lacks normals, so normals were generated.");
+ final_format|=Mesh::ARRAY_FORMAT_NORMAL;
+
+ }
+
+ if (final_normal_array.size() && uv_src && binormal_src && tangent_src && !force_make_tangents) {
+
+ PoolVector<real_t> tarray;
+ tarray.resize(vertex_array.size()*4);
+ PoolVector<real_t>::Write tarrayw = tarray.write();
+
+
+ for(int k=0;k<vlen;k++) {
+ tarrayw[k*4+0]=vertex_array[k].tangent.normal.x;
+ tarrayw[k*4+1]=vertex_array[k].tangent.normal.y;
+ tarrayw[k*4+2]=vertex_array[k].tangent.normal.z;
+ tarrayw[k*4+3]=vertex_array[k].tangent.d;
+
+ }
+
+ tarrayw = PoolVector<real_t>::Write();
+
+ final_tangent_array=tarray;
+ } else if (final_normal_array.size() && primitive==Mesh::PRIMITIVE_TRIANGLES && final_uv_array.size() && (force_make_tangents || (material.is_valid()))){
+ //if this uses triangles, there are uvs and the material is using a normalmap, generate tangents and binormals, because they WILL be needed
+ //generate binormals/tangents
+ _generate_tangents_and_binormals(index_array,final_vertex_array,final_uv_array,final_normal_array,final_tangent_array);
+ final_format|=Mesh::ARRAY_FORMAT_TANGENT;
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_line("Collada: Triangle mesh lacks tangents (And normalmap was used), so tangents were generated.");
+
+ }
+
+
+ if (color_src) {
+ PoolVector<Color> colorarray;
+ colorarray.resize(vertex_array.size());
+ PoolVector<Color>::Write colorarrayw = colorarray.write();
+
+ for(int k=0;k<vlen;k++) {
+ colorarrayw[k]=vertex_array[k].color;
+ }
+
+ colorarrayw = PoolVector<Color>::Write();
+
+ final_color_array=colorarray;
+ }
+
+ if (has_weights) {
+ PoolVector<float> weightarray;
+ PoolVector<int> bonearray;
+
+ weightarray.resize(vertex_array.size()*4);
+ PoolVector<float>::Write weightarrayw = weightarray.write();
+ bonearray.resize(vertex_array.size()*4);
+ PoolVector<int>::Write bonearrayw = bonearray.write();
+
+ for(int k=0;k<vlen;k++) {
+ float sum=0;
+
+ for(int l=0;l<VS::ARRAY_WEIGHTS_SIZE;l++) {
+ if (l<vertex_array[k].weights.size()) {
+ weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=vertex_array[k].weights[l].weight;
+ sum+=weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l];
+ bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=int(vertex_array[k].weights[l].bone_idx);
+ //COLLADA_PRINT(itos(k)+": "+rtos(bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l])+":"+rtos(weightarray[k*VS::ARRAY_WEIGHTS_SIZE+l]));
+ } else {
+
+ weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=0;
+ bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=0;
+
+ }
+
+
+ }
+ /*
+ if (sum<0.8)
+ COLLADA_PRINT("ERROR SUMMING INDEX "+itos(k)+" had weights: "+itos(vertex_array[k].weights.size()));
+ */
+
+ }
+
+ weightarrayw = PoolVector<float>::Write();
+ bonearrayw = PoolVector<int>::Write();
+
+ final_weight_array = weightarray;
+ final_bone_array = bonearray;
+ }
+
+
+
+ ////////////////////////////
+ // FINALLY CREATE SUFRACE //
+ ////////////////////////////
+
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+
+ d[Mesh::ARRAY_INDEX]=index_array;
+ d[Mesh::ARRAY_VERTEX]=final_vertex_array;
+
+ if (final_normal_array.size())
+ d[Mesh::ARRAY_NORMAL]=final_normal_array;
+ if (final_tangent_array.size())
+ d[Mesh::ARRAY_TANGENT]=final_tangent_array;
+ if (final_uv_array.size())
+ d[Mesh::ARRAY_TEX_UV]=final_uv_array;
+ if (final_uv2_array.size())
+ d[Mesh::ARRAY_TEX_UV2]=final_uv2_array;
+ if (final_color_array.size())
+ d[Mesh::ARRAY_COLOR]=final_color_array;
+ if (final_weight_array.size())
+ d[Mesh::ARRAY_WEIGHTS]=final_weight_array;
+ if (final_bone_array.size())
+ d[Mesh::ARRAY_BONES]=final_bone_array;
+
+
+ Array mr;
+
+ ////////////////////////////
+ // THEN THE MORPH TARGETS //
+ ////////////////////////////
+#if 0
+ if (p_morph_data) {
+
+ //add morphie target
+ ERR_FAIL_COND_V( !p_morph_data->targets.has("MORPH_TARGET"), ERR_INVALID_DATA );
+ String mt = p_morph_data->targets["MORPH_TARGET"];
+ ERR_FAIL_COND_V( !p_morph_data->sources.has(mt), ERR_INVALID_DATA);
+ int morph_targets = p_morph_data->sources[mt].sarray.size();
+ mr.resize(morph_targets);
+
+ for(int j=0;j<morph_targets;j++) {
+
+ Array mrt;
+ mrt.resize(VS::ARRAY_MAX);
+
+ String target = p_morph_data->sources[mt].sarray[j];
+ ERR_FAIL_COND_V( !collada.state.mesh_data_map.has(target), ERR_INVALID_DATA );
+ String name = collada.state.mesh_data_map[target].name;
+ Collada::MeshData &md = collada.state.mesh_data_map[target];
+
+ // collada in itself supports morphing everything. However, the spec is unclear and no examples or exporters that
+ // morph anything but "POSITIONS" seem to exit. Because of this, normals and binormals/tangents have to be regenerated here,
+ // which may result in inaccurate (but most of the time good enough) results.
+
+ PoolVector<Vector3> vertices;
+ vertices.resize(vlen);
+
+ ERR_FAIL_COND_V( md.vertices.size() != 1, ERR_INVALID_DATA);
+ String vertex_src_id=md.vertices.front()->key();
+ ERR_FAIL_COND_V(!md.vertices[vertex_src_id].sources.has("POSITION"),ERR_INVALID_DATA);
+ String position_src_id = md.vertices[vertex_src_id].sources["POSITION"];
+
+ ERR_FAIL_COND_V(!md.sources.has(position_src_id),ERR_INVALID_DATA);
+
+ const Collada::MeshData::Source *m=&md.sources[position_src_id];
+
+ ERR_FAIL_COND_V( m->array.size() != vertex_src->array.size(), ERR_INVALID_DATA);
+ int stride=m->stride;
+ if (stride==0)
+ stride=3;
+
+
+ //read vertices from morph target
+ PoolVector<Vector3>::Write vertw = vertices.write();
+
+ for(int m_i=0;m_i<m->array.size()/stride;m_i++) {
+
+ int pos = m_i*stride;
+ Vector3 vtx( m->array[pos+0], m->array[pos+1], m->array[pos+2] );
+
+#ifndef NO_UP_AXIS_SWAP
+ if (collada.state.up_axis==Vector3::AXIS_Z) {
+
+ SWAP( vtx.z, vtx.y );
+ vtx.z = -vtx.z;
+
+ }
+#endif
+
+ Collada::Vertex vertex;
+ vertex.vertex=vtx;
+ vertex.fix_unit_scale(collada);
+ vtx=vertex.vertex;
+
+ vtx = p_local_xform.xform(vtx);
+
+
+ if (vertex_map.has(m_i)) { //vertex may no longer be here, don't bother converting
+
+
+ for (Set<int> ::Element *E=vertex_map[m_i].front() ; E; E=E->next() ) {
+
+ vertw[E->get()]=vtx;
+ }
+ }
+ }
+
+
+ //vertices are in place, now generate everything else
+ vertw = PoolVector<Vector3>::Write();
+ PoolVector<Vector3> normals;
+ PoolVector<float> tangents;
+ print_line("vertex source id: "+vertex_src_id);
+ if(md.vertices[vertex_src_id].sources.has("NORMAL")){
+ //has normals
+ normals.resize(vlen);
+ //std::cout << "has normals" << std::endl;
+ String normal_src_id = md.vertices[vertex_src_id].sources["NORMAL"];
+ //std::cout << "normals source: "<< normal_src_id.utf8().get_data() <<std::endl;
+ ERR_FAIL_COND_V(!md.sources.has(normal_src_id),ERR_INVALID_DATA);
+
+ const Collada::MeshData::Source *m=&md.sources[normal_src_id];
+
+ ERR_FAIL_COND_V( m->array.size() != vertex_src->array.size(), ERR_INVALID_DATA);
+ int stride=m->stride;
+ if (stride==0)
+ stride=3;
+
+
+ //read normals from morph target
+ PoolVector<Vector3>::Write vertw = normals.write();
+
+ for(int m_i=0;m_i<m->array.size()/stride;m_i++) {
+
+ int pos = m_i*stride;
+ Vector3 vtx( m->array[pos+0], m->array[pos+1], m->array[pos+2] );
+
+ #ifndef NO_UP_AXIS_SWAP
+ if (collada.state.up_axis==Vector3::AXIS_Z) {
+
+ SWAP( vtx.z, vtx.y );
+ vtx.z = -vtx.z;
+
+ }
+ #endif
+
+ Collada::Vertex vertex;
+ vertex.vertex=vtx;
+ vertex.fix_unit_scale(collada);
+ vtx=vertex.vertex;
+
+ vtx = p_local_xform.xform(vtx);
+
+
+ if (vertex_map.has(m_i)) { //vertex may no longer be here, don't bother converting
+
+
+ for (Set<int> ::Element *E=vertex_map[m_i].front() ; E; E=E->next() ) {
+
+ vertw[E->get()]=vtx;
+ }
+ }
+ }
+
+ print_line("using built-in normals");
+ }else{
+ print_line("generating normals");
+ _generate_normals(index_array,vertices,normals);//no normals
+ }
+ if (final_tangent_array.size() && final_uv_array.size()) {
+
+ _generate_tangents_and_binormals(index_array,vertices,final_uv_array,normals,tangents);
+
+ }
+
+ mrt[Mesh::ARRAY_VERTEX]=vertices;
+
+ mrt[Mesh::ARRAY_NORMAL]=normals;
+ if (tangents.size())
+ mrt[Mesh::ARRAY_TANGENT]=tangents;
+ if (final_uv_array.size())
+ mrt[Mesh::ARRAY_TEX_UV]=final_uv_array;
+ if (final_uv2_array.size())
+ mrt[Mesh::ARRAY_TEX_UV2]=final_uv2_array;
+ if (final_color_array.size())
+ mrt[Mesh::ARRAY_COLOR]=final_color_array;
+
+ mr[j]=mrt;
+
+ }
+
+ }
+
+#endif
+ for(int mi=0;mi<p_morph_meshes.size();mi++) {
+
+ //print_line("want surface "+itos(mi)+" has "+itos(p_morph_meshes[mi]->get_surface_count()));
+ Array a = p_morph_meshes[mi]->surface_get_arrays(surface);
+ //add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not)
+
+ if (final_weight_array.size())
+ a[Mesh::ARRAY_WEIGHTS]=final_weight_array;
+ if (final_bone_array.size())
+ a[Mesh::ARRAY_BONES]=final_bone_array;
+
+ a[Mesh::ARRAY_INDEX]=Variant();
+ //a.resize(Mesh::ARRAY_MAX); //no need for index
+ mr.push_back(a);
+ }
+
+
+ p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,d,mr,p_for_morph?0:Mesh::ARRAY_COMPRESS_DEFAULT);
+
+ if (material.is_valid()) {
+ if (p_use_mesh_material) {
+ p_mesh->surface_set_material(surface, material);
+ }
+ p_mesh->surface_set_name(surface, material->get_name());
+ }
+ }
+
+ /*****************/
+ /* FIND MATERIAL */
+ /*****************/
+
+ surface++;
+ }
+
+
+ return OK;
+
+}
+
+
+Error ColladaImport::_create_resources(Collada::Node *p_node) {
+
+
+ if (p_node->type==Collada::Node::TYPE_GEOMETRY && node_map.has(p_node->id)) {
+
+
+ Spatial * node=node_map[p_node->id].node;
+ Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(p_node);
+
+
+ if (node->cast_to<Path>()) {
+
+ Path *path = node->cast_to<Path>();
+
+ String curve = ng->source;
+
+ if (curve_cache.has(ng->source)) {
+
+ path->set_curve(curve_cache[ng->source]);
+ } else {
+
+ Ref<Curve3D> c = memnew( Curve3D );
+
+ const Collada::CurveData &cd = collada.state.curve_data_map[ng->source];
+
+ ERR_FAIL_COND_V( !cd.control_vertices.has("POSITION") , ERR_INVALID_DATA);
+ ERR_FAIL_COND_V( !cd.control_vertices.has("IN_TANGENT") , ERR_INVALID_DATA);
+ ERR_FAIL_COND_V( !cd.control_vertices.has("OUT_TANGENT") , ERR_INVALID_DATA);
+ ERR_FAIL_COND_V( !cd.control_vertices.has("INTERPOLATION") , ERR_INVALID_DATA);
+
+
+ ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["POSITION"] ) , ERR_INVALID_DATA);
+ const Collada::CurveData::Source &vertices = cd.sources[ cd.control_vertices["POSITION"] ];
+ ERR_FAIL_COND_V( vertices.stride!=3, ERR_INVALID_DATA );
+
+ ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["IN_TANGENT"] ) , ERR_INVALID_DATA);
+ const Collada::CurveData::Source &in_tangents = cd.sources[ cd.control_vertices["IN_TANGENT"] ];
+ ERR_FAIL_COND_V( in_tangents.stride!=3 , ERR_INVALID_DATA);
+
+ ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["OUT_TANGENT"] ), ERR_INVALID_DATA );
+ const Collada::CurveData::Source &out_tangents = cd.sources[ cd.control_vertices["OUT_TANGENT"] ];
+ ERR_FAIL_COND_V( out_tangents.stride!=3, ERR_INVALID_DATA );
+
+ ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["INTERPOLATION"] ), ERR_INVALID_DATA );
+ const Collada::CurveData::Source &interps = cd.sources[ cd.control_vertices["INTERPOLATION"] ];
+ ERR_FAIL_COND_V( interps.stride!=1, ERR_INVALID_DATA );
+
+ const Collada::CurveData::Source *tilts=NULL;
+ if (cd.control_vertices.has("TILT") && cd.sources.has(cd.control_vertices["TILT"]))
+ tilts=&cd.sources[ cd.control_vertices["TILT"] ];
+
+
+ if (tilts) {
+ print_line("FOUND TILTS!!!");
+ }
+ int pc = vertices.array.size()/3;
+ for(int i=0;i<pc;i++) {
+
+ Vector3 pos( vertices.array[i*3+0], vertices.array[i*3+1], vertices.array[i*3+2] );
+ Vector3 in( in_tangents.array[i*3+0], in_tangents.array[i*3+1], in_tangents.array[i*3+2] );
+ Vector3 out( out_tangents.array[i*3+0], out_tangents.array[i*3+1], out_tangents.array[i*3+2] );
+
+#ifndef NO_UP_AXIS_SWAP
+ if (collada.state.up_axis==Vector3::AXIS_Z) {
+
+ SWAP(pos.y,pos.z);
+ pos.z=-pos.z;
+ SWAP(in.y,in.z);
+ in.z=-in.z;
+ SWAP(out.y,out.z);
+ out.z=-out.z;
+ }
+#endif
+ pos*=collada.state.unit_scale;
+ in*=collada.state.unit_scale;
+ out*=collada.state.unit_scale;
+
+ c->add_point(pos,in-pos,out-pos);
+ if (tilts)
+ c->set_point_tilt(i,tilts->array[i]);
+
+ }
+
+ curve_cache[ng->source]=c;
+ path->set_curve(c);
+
+ }
+
+
+ }
+
+
+ if (node->cast_to<MeshInstance>()) {
+
+
+ Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(p_node);
+
+ MeshInstance *mi = node->cast_to<MeshInstance>();
+
+
+ ERR_FAIL_COND_V(!mi,ERR_BUG);
+
+
+ Collada::SkinControllerData *skin=NULL;
+ Collada::MorphControllerData *morph=NULL;
+ String meshid;
+ Transform apply_xform;
+ Vector<int> bone_remap;
+ Vector<Ref<Mesh> > morphs;
+
+ print_line("mesh: "+String(mi->get_name()));
+
+ if (ng->controller) {
+
+ print_line("has controller");
+
+ String ngsource = ng->source;
+
+ if (collada.state.skin_controller_data_map.has(ngsource)) {
+
+
+ ERR_FAIL_COND_V(!collada.state.skin_controller_data_map.has(ngsource),ERR_INVALID_DATA);
+ skin=&collada.state.skin_controller_data_map[ngsource];
+
+ Vector<String> skeletons = ng->skeletons;
+
+ ERR_FAIL_COND_V( skeletons.empty(), ERR_INVALID_DATA );
+
+ String skname = skeletons[0];
+ if (!node_map.has(skname)) {
+ print_line("no node for skeleton "+skname);
+ }
+ ERR_FAIL_COND_V( !node_map.has(skname), ERR_INVALID_DATA );
+ NodeMap nmsk = node_map[skname];
+ Skeleton *sk = nmsk.node->cast_to<Skeleton>();
+ ERR_FAIL_COND_V( !sk, ERR_INVALID_DATA );
+ ERR_FAIL_COND_V( !skeleton_bone_map.has(sk), ERR_INVALID_DATA );
+ Map<String, int> &bone_remap_map=skeleton_bone_map[sk];
+
+
+ meshid=skin->base;
+
+ if (collada.state.morph_controller_data_map.has(meshid)) {
+ //it's a morph!!
+ morph = &collada.state.morph_controller_data_map[meshid];
+ ngsource=meshid;
+ meshid=morph->mesh;
+ } else {
+ ngsource="";
+ }
+
+ if (apply_mesh_xform_to_vertices) {
+ apply_xform=collada.fix_transform(p_node->default_transform);
+ node->set_transform(Transform());
+ } else {
+ apply_xform=Transform();
+ }
+
+ Collada::SkinControllerData::Source *joint_src=NULL;
+
+ ERR_FAIL_COND_V(!skin->weights.sources.has("JOINT"),ERR_INVALID_DATA);
+
+ String joint_id = skin->weights.sources["JOINT"].source;
+ ERR_FAIL_COND_V(!skin->sources.has(joint_id),ERR_INVALID_DATA);
+
+ joint_src = &skin->sources[joint_id];
+
+ bone_remap.resize(joint_src->sarray.size());
+
+ for(int i=0;i<bone_remap.size();i++) {
+
+ String str = joint_src->sarray[i];
+ if (!bone_remap_map.has(str)) {
+ print_line("bone not found for remap: "+str);
+ print_line("in skeleton: "+skname);
+ }
+ ERR_FAIL_COND_V( !bone_remap_map.has(str), ERR_INVALID_DATA );
+ bone_remap[i]=bone_remap_map[str];
+ }
+ }
+
+ if (collada.state.morph_controller_data_map.has(ngsource)) {
+ print_line("is morph "+ngsource);
+ //it's a morph!!
+ morph = &collada.state.morph_controller_data_map[ngsource];
+ meshid=morph->mesh;
+ printf("KKmorph: %p\n",morph);
+ print_line("morph mshid: "+meshid);
+
+ Vector<String> targets;
+
+ morph->targets.has("MORPH_TARGET");
+ String target = morph->targets["MORPH_TARGET"];
+ bool valid=false;
+ if (morph->sources.has(target)) {
+ valid=true;
+ Vector<String> names = morph->sources[target].sarray;
+ for(int i=0;i<names.size();i++) {
+
+ String meshid=names[i];
+ if (collada.state.mesh_data_map.has(meshid)) {
+ Ref<Mesh> mesh=Ref<Mesh>(memnew( Mesh ));
+ const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
+ Error err = _create_mesh_surfaces(false,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,NULL,Vector<Ref<Mesh> >(),true);
+ ERR_FAIL_COND_V(err,err);
+
+ morphs.push_back(mesh);
+ } else {
+ valid=false;
+ }
+ }
+ }
+
+ if (!valid)
+ morphs.clear();
+
+ ngsource="";
+ }
+
+ if (ngsource!=""){
+ ERR_EXPLAIN("Controller Instance Source '"+ngsource+"' is neither skin or morph!");
+ ERR_FAIL_V( ERR_INVALID_DATA );
+ }
+
+
+
+ } else {
+ meshid=ng->source;
+ }
+
+ Ref<Mesh> mesh;
+ if (mesh_cache.has(meshid)) {
+ mesh=mesh_cache[meshid];
+ } else {
+ if (collada.state.mesh_data_map.has(meshid)) {
+ //bleh, must ignore invalid
+
+ ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid),ERR_INVALID_DATA);
+ mesh=Ref<Mesh>(memnew( Mesh ));
+ const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
+ mesh->set_name( meshdata.name );
+ Error err = _create_mesh_surfaces(morphs.size()==0,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,morph,morphs,false,use_mesh_builtin_materials);
+ ERR_FAIL_COND_V(err,err);
+
+ mesh_cache[meshid]=mesh;
+ } else {
+
+ print_line("Warning, will not import geometry: "+meshid);
+ }
+ }
+
+ if (!mesh.is_null()) {
+
+ mi->set_mesh(mesh);
+ if (!use_mesh_builtin_materials) {
+ const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
+
+ for(int i=0;i<meshdata.primitives.size();i++) {
+
+ String matname=meshdata.primitives[i].material;
+
+ if (ng->material_map.has(matname)) {
+ String target=ng->material_map[matname].target;
+
+ Ref<Material> material;
+ if (!material_cache.has(target)) {
+ Error err = _create_material(target);
+ if (!err)
+ material=material_cache[target];
+ } else
+ material=material_cache[target];
+
+ mi->set_surface_material(i,material);
+ } else if (matname!=""){
+ print_line("Warning, unreferenced material in geometry instance: "+matname);
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ for(int i=0;i<p_node->children.size();i++) {
+
+ Error err = _create_resources(p_node->children[i]);
+ if (err)
+ return err;
+ }
+ return OK;
+}
+
+
+Error ColladaImport::load(const String& p_path,int p_flags,bool p_force_make_tangents) {
+
+ Error err = collada.load(p_path,p_flags);
+ ERR_FAIL_COND_V(err,err);
+
+ force_make_tangents=p_force_make_tangents;
+ ERR_FAIL_COND_V( !collada.state.visual_scene_map.has( collada.state.root_visual_scene ), ERR_INVALID_DATA );
+ Collada::VisualScene &vs = collada.state.visual_scene_map[ collada.state.root_visual_scene ];
+
+ scene = memnew( Spatial ); // root
+
+ //determine what's going on with the lights
+ for(int i=0;i<vs.root_nodes.size();i++) {
+
+ _pre_process_lights(vs.root_nodes[i]);
+
+ }
+ //import scene
+
+ for(int i=0;i<vs.root_nodes.size();i++) {
+
+ Error err = _create_scene_skeletons(vs.root_nodes[i]);
+ if (err!=OK) {
+ memdelete(scene);
+ ERR_FAIL_COND_V(err,err);
+ }
+ }
+
+ for(int i=0;i<vs.root_nodes.size();i++) {
+
+ Error err = _create_scene(vs.root_nodes[i],scene);
+ if (err!=OK) {
+ memdelete(scene);
+ ERR_FAIL_COND_V(err,err);
+ }
+
+ Error err2 = _create_resources(vs.root_nodes[i]);
+ if (err2!=OK) {
+ memdelete(scene);
+ ERR_FAIL_COND_V(err2,err2);
+ }
+ }
+
+ //optatively, set unit scale in the root
+ scene->set_transform(collada.get_root_transform());
+
+
+ return OK;
+
+}
+
+void ColladaImport::_fix_param_animation_tracks() {
+
+ for (Map<String,Collada::Node*>::Element *E=collada.state.scene_map.front();E;E=E->next()) {
+
+ Collada::Node *n = E->get();
+ switch(n->type) {
+
+ case Collada::Node::TYPE_NODE: {
+ // ? do nothing
+ } break;
+ case Collada::Node::TYPE_JOINT: {
+
+ } break;
+ case Collada::Node::TYPE_SKELETON: {
+
+ } break;
+ case Collada::Node::TYPE_LIGHT: {
+
+ } break;
+ case Collada::Node::TYPE_CAMERA: {
+
+ } break;
+ case Collada::Node::TYPE_GEOMETRY: {
+
+ Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(n);
+ // test source(s)
+ String source = ng->source;
+
+ while (source!="") {
+
+ if (collada.state.skin_controller_data_map.has(source)) {
+
+ const Collada::SkinControllerData& skin = collada.state.skin_controller_data_map[source];
+
+ //nothing to animate here i think
+
+ source=skin.base;
+ } else if (collada.state.morph_controller_data_map.has(source)) {
+
+
+ const Collada::MorphControllerData& morph = collada.state.morph_controller_data_map[source];
+
+ if (morph.targets.has("MORPH_WEIGHT") && morph.targets.has("MORPH_TARGET")) {
+
+
+ String weights = morph.targets["MORPH_WEIGHT"];
+ String targets = morph.targets["MORPH_TARGET"];
+ //fails here
+
+ if (morph.sources.has(targets) && morph.sources.has(weights)) {
+ const Collada::MorphControllerData::Source &weight_src=morph.sources[weights];
+ const Collada::MorphControllerData::Source &target_src=morph.sources[targets];
+
+
+ ERR_FAIL_COND(weight_src.array.size() != target_src.sarray.size());
+
+ for(int i=0;i<weight_src.array.size();i++) {
+
+ String track_name = weights+"("+itos(i)+")";
+ String mesh_name = target_src.sarray[i];
+ if (collada.state.mesh_name_map.has(mesh_name) && collada.state.referenced_tracks.has(track_name)) {
+
+
+ const Vector<int>&rt = collada.state.referenced_tracks[track_name];
+
+ for(int rti=0;rti<rt.size();rti++) {
+ Collada::AnimationTrack *at = &collada.state.animation_tracks[rt[rti]];
+
+ at->target=E->key();
+ at->param="morph/"+collada.state.mesh_name_map[mesh_name];
+ at->property=true;
+ //at->param
+ }
+ }
+ }
+ }
+ }
+ source=morph.mesh;
+ } else {
+
+ source=""; // for now nothing else supported
+ }
+ }
+
+ } break;
+
+ }
+ }
+
+}
+
+void ColladaImport::create_animations(bool p_make_tracks_in_all_bones, bool p_import_value_tracks) {
+
+
+ _fix_param_animation_tracks();
+ for(int i=0;i<collada.state.animation_clips.size();i++) {
+
+ for(int j=0;j<collada.state.animation_clips[i].tracks.size();j++)
+ tracks_in_clips.insert(collada.state.animation_clips[i].tracks[j]);
+ }
+
+
+
+ for(int i=0;i<collada.state.animation_tracks.size();i++) {
+
+ Collada::AnimationTrack &at = collada.state.animation_tracks[i];
+ //print_line("CHANNEL: "+at.target+" PARAM: "+at.param);
+
+ String node;
+
+ if (!node_map.has(at.target)) {
+
+ 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;
+ }
+
+
+ if (at.property) {
+
+ valid_animated_properties.push_back(i);
+
+ } else {
+
+ node_map[node].anim_tracks.push_back(i);
+ valid_animated_nodes.insert(node);
+ }
+
+ }
+
+ create_animation(-1,p_make_tracks_in_all_bones, p_import_value_tracks);
+ //print_line("clipcount: "+itos(collada.state.animation_clips.size()));
+ for(int i=0;i<collada.state.animation_clips.size();i++)
+ create_animation(i, p_make_tracks_in_all_bones, p_import_value_tracks);
+
+}
+
+void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks) {
+
+ Ref<Animation> animation = Ref<Animation>( memnew( Animation ));
+
+
+ if (p_clip==-1) {
+
+ //print_line("default");
+ animation->set_name("default");
+ } else {
+ //print_line("clip name: "+collada.state.animation_clips[p_clip].name);
+ animation->set_name(collada.state.animation_clips[p_clip].name);
+ }
+
+ for(Map<String,NodeMap>::Element *E=node_map.front();E;E=E->next()) {
+
+ if (E->get().bone<0)
+ continue;
+ bones_with_animation[E->key()]=false;
+ }
+ //store and validate tracks
+
+ if (p_clip==-1) {
+ //main anim
+ }
+
+ Set<int> track_filter;
+
+
+ if (p_clip==-1) {
+
+ for(int i=0;i<collada.state.animation_clips.size();i++) {
+
+ int tc = collada.state.animation_clips[i].tracks.size();
+ for(int j=0;j<tc;j++) {
+
+ String n = collada.state.animation_clips[i].tracks[j];
+ if (collada.state.by_id_tracks.has(n)) {
+
+ const Vector<int>&ti = collada.state.by_id_tracks[n];
+ for(int k=0;k<ti.size();k++) {
+ track_filter.insert(ti[k]);
+ }
+ }
+ }
+ }
+ } else {
+
+ int tc = collada.state.animation_clips[p_clip].tracks.size();
+ for(int j=0;j<tc;j++) {
+
+ String n = collada.state.animation_clips[p_clip].tracks[j];
+ if (collada.state.by_id_tracks.has(n)) {
+
+ const Vector<int>&ti = collada.state.by_id_tracks[n];
+ for(int k=0;k<ti.size();k++) {
+ track_filter.insert(ti[k]);
+ }
+ }
+ }
+
+ }
+
+ //animation->set_loop(true);
+ //create animation tracks
+
+ Vector<float> base_snapshots;
+
+ float f=0;
+ float snapshot_interval = 1.0/bake_fps; //should be customizable somewhere...
+
+ float anim_length=collada.state.animation_length;
+ if (p_clip>=0 && collada.state.animation_clips[p_clip].end)
+ anim_length=collada.state.animation_clips[p_clip].end;
+
+ while(f<anim_length) {
+
+ base_snapshots.push_back(f);
+
+ f+=snapshot_interval;
+
+ if (f>=anim_length) {
+ base_snapshots.push_back(anim_length);
+
+ }
+ }
+
+ //print_line("anim len: "+rtos(anim_length));
+ animation->set_length(anim_length);
+
+ 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())) {
+
+ continue;
+ }
+
+ NodeMap &nm = node_map[E->get()];
+ String path = scene->get_path_to(nm.node);
+
+ if (nm.bone>=0) {
+ Skeleton *sk = static_cast<Skeleton*>(nm.node);
+ String name = sk->get_bone_name(nm.bone);
+ path=path+":"+name;
+ }
+
+ bool found_anim=false;
+
+
+ Collada::Node *cn = collada.state.scene_map[E->get()];
+ if (cn->ignore_anim) {
+
+ continue;
+ }
+
+
+
+ animation->add_track(Animation::TYPE_TRANSFORM);
+ int track = animation->get_track_count() -1;
+ animation->track_set_path( track , path );
+ animation->track_set_imported( track , true ); //helps merging later
+
+ Vector<float> snapshots = base_snapshots;
+
+ if (nm.anim_tracks.size()==1) {
+ //use snapshot keys from anim track instead, because this was most likely exported baked
+ Collada::AnimationTrack &at = collada.state.animation_tracks[nm.anim_tracks.front()->get()];
+ snapshots.clear();
+ for(int i=0;i<at.keys.size();i++)
+ snapshots.push_back(at.keys[i].time);
+
+
+ }
+
+
+ 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())) {
+
+ continue;
+ }
+ } else {
+
+ if (!track_filter.has(ET->get()))
+ continue;
+
+ }
+
+ found_anim=true;
+
+ Collada::AnimationTrack &at = collada.state.animation_tracks[ET->get()];
+
+ int xform_idx=-1;
+ for(int j=0;j<cn->xform_list.size();j++) {
+
+
+ if (cn->xform_list[j].id==at.param) {
+
+ xform_idx=j;
+ break;
+ }
+ }
+
+ if (xform_idx==-1) {
+ print_line("couldnt find matching node "+at.target+" xform for track "+at.param);
+ continue;
+ }
+
+ ERR_CONTINUE(xform_idx==-1);
+
+ Vector<float> data = at.get_value_at_time(snapshots[i]);
+ ERR_CONTINUE(data.empty());
+
+
+ Collada::Node::XForm &xf = cn->xform_list[xform_idx];
+
+ if (at.component=="ANGLE") {
+ ERR_CONTINUE(data.size()!=1);
+ ERR_CONTINUE(xf.op!=Collada::Node::XForm::OP_ROTATE);
+ ERR_CONTINUE(xf.data.size()<4);
+ xf.data[3]=data[0];
+ } else if (at.component=="X" || at.component=="Y" || at.component=="Z") {
+ int cn=at.component[0]-'X';
+ ERR_CONTINUE(cn>=xf.data.size());
+ ERR_CONTINUE(data.size()>1);
+ xf.data[cn]=data[0];
+ } else if (data.size()==xf.data.size()) {
+
+ xf.data=data;
+ } else {
+
+
+ if ( data.size()!=xf.data.size() ) {
+ print_line("component "+at.component+" datasize "+itos(data.size())+" xfdatasize "+itos(xf.data.size()));
+ }
+
+ ERR_CONTINUE( data.size()!=xf.data.size() );
+ }
+ }
+
+ Transform xform = cn->compute_transform(collada);
+ xform = collada.fix_transform(xform) * cn->post_transform;
+
+
+ if (nm.bone>=0) {
+ //make bone transform relative to rest (in case of skeleton)
+ Skeleton *sk = nm.node->cast_to<Skeleton>();
+ if (sk) {
+
+ xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform;
+ } else {
+
+ ERR_PRINT("INVALID SKELETON!!!!");
+ }
+ }
+
+ Quat q = xform.basis;
+ q.normalize();
+ Vector3 s = xform.basis.get_scale();
+ Vector3 l = xform.origin;
+
+ animation->transform_track_insert_key(track,snapshots[i],l,q,s);
+
+ }
+
+
+
+ if (nm.bone>=0) {
+ if (found_anim)
+ bones_with_animation[E->get()]=true;
+ }
+
+ if (found_anim)
+ tracks_found=true;
+ else {
+ animation->remove_track( track );
+ }
+
+ }
+
+ if (p_make_tracks_in_all_bones) {
+
+ //some bones may lack animation, but since we don't store pose as a property, we must add keyframes!
+ for(Map<String,bool>::Element *E=bones_with_animation.front();E;E=E->next()) {
+
+ if (E->get())
+ continue;
+
+ //print_line("BONE LACKS ANIM: "+E->key());
+
+ NodeMap &nm = node_map[E->key()];
+ String path = scene->get_path_to(nm.node);
+ ERR_CONTINUE( nm.bone <0 );
+ Skeleton *sk = static_cast<Skeleton*>(nm.node);
+ String name = sk->get_bone_name(nm.bone);
+ path=path+":"+name;
+
+ Collada::Node *cn = collada.state.scene_map[E->key()];
+ if (cn->ignore_anim) {
+ print_line("warning, ignoring animation on node: "+path);
+ continue;
+ }
+
+ animation->add_track(Animation::TYPE_TRANSFORM);
+ int track = animation->get_track_count() -1;
+ animation->track_set_path( track , path );
+ animation->track_set_imported( track , true ); //helps merging later
+
+
+ Transform xform = cn->compute_transform(collada);
+ xform = collada.fix_transform(xform) * cn->post_transform;
+
+ xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform;
+
+ Quat q = xform.basis;
+ q.normalize();
+ Vector3 s = xform.basis.get_scale();
+ Vector3 l = xform.origin;
+
+ animation->transform_track_insert_key(track,0,l,q,s);
+
+ tracks_found=true;
+ }
+ }
+
+
+
+ if (p_import_value_tracks) {
+ for (int i = 0; i < valid_animated_properties.size(); i++) {
+
+
+ int ti = valid_animated_properties[i];
+
+ if (p_clip == -1) {
+
+ if (track_filter.has(ti))
+ continue;
+ }
+ else {
+
+ if (!track_filter.has(ti))
+ continue;
+
+ }
+
+
+ Collada::AnimationTrack &at = collada.state.animation_tracks[ti];
+
+ // take snapshots
+ if (!collada.state.scene_map.has(at.target))
+ continue;
+
+ NodeMap &nm = node_map[at.target];
+ String path = scene->get_path_to(nm.node);
+
+ animation->add_track(Animation::TYPE_VALUE);
+ int track = animation->get_track_count() - 1;
+
+ path = path + ":" + at.param;
+ animation->track_set_path(track, path);
+ animation->track_set_imported(track, true); //helps merging later
+
+
+ for (int i = 0; i < at.keys.size(); i++) {
+
+ float time = at.keys[i].time;
+ Variant value;
+ Vector<float> data = at.keys[i].data;
+ if (data.size() == 1) {
+ //push a float
+ value = data[0];
+
+ }
+ else if (data.size() == 16) {
+ //matrix
+ print_line("value keys for matrices not supported");
+ }
+ else {
+
+ print_line("don't know what to do with this amount of value keys: " + itos(data.size()));
+ }
+
+ animation->track_insert_key(track, time, value);
+ }
+
+
+ tracks_found = true;
+
+ }
+ }
+
+
+
+ if (tracks_found) {
+
+ animations.push_back(animation);
+ }
+
+
+
+}
+
+
+/*********************************************************************************/
+/*************************************** SCENE ***********************************/
+/*********************************************************************************/
+
+
+#define DEBUG_ANIMATION
+
+
+uint32_t EditorSceneImporterCollada::get_import_flags() const {
+
+ return IMPORT_SCENE|IMPORT_ANIMATION;
+
+}
+void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) const {
+
+
+ r_extensions->push_back("dae");
+}
+Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_flags,int p_bake_fps, List<String> *r_missing_deps, Error* r_err) {
+
+ ColladaImport state;
+ uint32_t flags=Collada::IMPORT_FLAG_SCENE;
+ if (p_flags&IMPORT_ANIMATION)
+ flags|=Collada::IMPORT_FLAG_ANIMATION;
+
+ state.use_mesh_builtin_materials=!(p_flags&IMPORT_MATERIALS_IN_INSTANCES);
+ state.bake_fps=p_bake_fps;
+
+ Error err = state.load(p_path,flags,p_flags&EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
+
+ ERR_FAIL_COND_V(err!=OK,NULL);
+
+ if (state.missing_textures.size()) {
+
+ /*
+ for(int i=0;i<state.missing_textures.size();i++) {
+ EditorNode::add_io_error("Texture Not Found: "+state.missing_textures[i]);
+ }
+ */
+
+
+ if (r_missing_deps) {
+
+ for(int i=0;i<state.missing_textures.size();i++) {
+ //EditorNode::add_io_error("Texture Not Found: "+state.missing_textures[i]);
+ r_missing_deps->push_back(state.missing_textures[i]);
+ }
+
+ }
+ }
+
+ if (p_flags&IMPORT_ANIMATION) {
+
+ state.create_animations(p_flags&IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS,p_flags&EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
+ AnimationPlayer *ap = memnew( AnimationPlayer );
+ for(int i=0;i<state.animations.size();i++) {
+ String name;
+ if (state.animations[i]->get_name()=="")
+ name="default";
+ else
+ name=state.animations[i]->get_name();
+
+ if (p_flags&IMPORT_ANIMATION_DETECT_LOOP) {
+
+ if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
+ state.animations[i]->set_loop(true);
+ }
+ }
+
+ ap->add_animation(name,state.animations[i]);
+ }
+ state.scene->add_child(ap);
+ ap->set_owner(state.scene);
+
+ }
+
+ return state.scene;
+
+}
+
+Ref<Animation> EditorSceneImporterCollada::import_animation(const String& p_path,uint32_t p_flags) {
+
+
+ ColladaImport state;
+
+
+ state.use_mesh_builtin_materials=false;
+
+ Error err = state.load(p_path,Collada::IMPORT_FLAG_ANIMATION,p_flags&EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
+ ERR_FAIL_COND_V(err!=OK,RES());
+
+
+ state.create_animations(p_flags&EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS,p_flags&EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
+ if (state.scene)
+ memdelete(state.scene);
+
+ if (state.animations.size()==0)
+ return Ref<Animation>();
+ Ref<Animation> anim=state.animations[0];
+ anim=state.animations[0];
+ print_line("Anim Load OK");
+ String base = p_path.get_basename().to_lower();
+ if (p_flags&IMPORT_ANIMATION_DETECT_LOOP) {
+
+ if (base.begins_with("loop") || base.ends_with("loop") || base.begins_with("cycle") || base.ends_with("cycle")) {
+ anim->set_loop(true);
+ }
+ }
+
+
+ return anim;
+}
+
+
+EditorSceneImporterCollada::EditorSceneImporterCollada() {
+
+
+}
+
diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h
new file mode 100644
index 0000000000..5c7624bd33
--- /dev/null
+++ b/editor/import/editor_import_collada.h
@@ -0,0 +1,51 @@
+/*************************************************************************/
+/* editor_import_collada.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_IMPORT_COLLADA_H
+#define EDITOR_IMPORT_COLLADA_H
+
+#include "editor/import/resource_importer_scene.h"
+
+
+
+class EditorSceneImporterCollada : public EditorSceneImporter {
+
+ GDCLASS(EditorSceneImporterCollada,EditorSceneImporter );
+public:
+
+ virtual uint32_t get_import_flags() const;
+ virtual void get_extensions(List<String> *r_extensions) const;
+ virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps=NULL,Error* r_err=NULL);
+ virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
+
+ EditorSceneImporterCollada();
+};
+
+
+#endif
+
diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp
new file mode 100644
index 0000000000..faf62d2839
--- /dev/null
+++ b/editor/import/resource_importer_csv_translation.cpp
@@ -0,0 +1,154 @@
+/*************************************************************************/
+/* resource_importer_csv_translation.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_importer_csv_translation.h"
+
+#include "os/file_access.h"
+#include "translation.h"
+#include "io/resource_saver.h"
+#include "compressed_translation.h"
+
+String ResourceImporterCSVTranslation::get_importer_name() const {
+
+ return "csv_translation";
+}
+
+String ResourceImporterCSVTranslation::get_visible_name() const{
+
+ return "CSV Translation";
+}
+void ResourceImporterCSVTranslation::get_recognized_extensions(List<String> *p_extensions) const{
+
+ p_extensions->push_back("csv");
+}
+
+String ResourceImporterCSVTranslation::get_save_extension() const {
+ return ""; //does not save a single resoure
+}
+
+String ResourceImporterCSVTranslation::get_resource_type() const{
+
+ return "StreamCSVTranslation";
+}
+
+bool ResourceImporterCSVTranslation::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
+
+ return true;
+}
+
+int ResourceImporterCSVTranslation::get_preset_count() const {
+ return 0;
+}
+String ResourceImporterCSVTranslation::get_preset_name(int p_idx) const {
+
+ return "";
+}
+
+
+void ResourceImporterCSVTranslation::get_import_options(List<ImportOption> *r_options,int p_preset) const {
+
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"compress"),true));
+
+}
+
+
+
+Error ResourceImporterCSVTranslation::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
+
+
+ bool compress = p_options["compress"];
+ FileAccessRef f = FileAccess::open(p_source_file,FileAccess::READ);
+
+ ERR_FAIL_COND_V( !f, ERR_INVALID_PARAMETER );
+
+ Vector<String> line = f->get_csv_line();
+ if (line.size()<=1) {
+ return ERR_PARSE_ERROR;
+ }
+
+ Vector<String> locales;
+ Vector<Ref<Translation> > translations;
+
+ for(int i=1;i<line.size();i++) {
+
+ String locale = line[i];
+ if (!TranslationServer::is_locale_valid(locale)) {
+ return ERR_PARSE_ERROR;
+ }
+
+ locales.push_back(locale);
+ Ref<Translation> translation;
+ translation.instance();
+ translation->set_locale(locale);
+ translations.push_back(translation);
+ }
+
+ line = f->get_csv_line();
+
+ while(line.size()==locales.size()+1) {
+
+ String key = line[0];
+ if (key!="") {
+
+ for(int i=1;i<line.size();i++) {
+ translations[i-1]->add_message(key,line[i]);
+ }
+ }
+
+ line = f->get_csv_line();
+ }
+
+
+ for(int i=0;i<translations.size();i++) {
+ Ref<Translation> xlt = translations[i];
+
+ if (compress) {
+ Ref<PHashTranslation> cxl = memnew( PHashTranslation );
+ cxl->generate( xlt );
+ xlt=cxl;
+ }
+
+ String save_path = p_source_file.get_basename()+"."+translations[i]->get_locale()+".xl";
+
+ ResourceSaver::save(save_path,xlt);
+ if (r_gen_files) {
+ r_gen_files->push_back(save_path);
+ }
+ }
+
+
+
+ return OK;
+
+}
+
+ResourceImporterCSVTranslation::ResourceImporterCSVTranslation()
+{
+
+}
diff --git a/editor/import/resource_importer_csv_translation.h b/editor/import/resource_importer_csv_translation.h
new file mode 100644
index 0000000000..a25e6a0fa8
--- /dev/null
+++ b/editor/import/resource_importer_csv_translation.h
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* resource_importer_csv_translation.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCEIMPORTERCSVTRANSLATION_H
+#define RESOURCEIMPORTERCSVTRANSLATION_H
+
+#include "io/resource_import.h"
+
+
+class ResourceImporterCSVTranslation : public ResourceImporter {
+ GDCLASS(ResourceImporterCSVTranslation,ResourceImporter)
+public:
+ virtual String get_importer_name() const;
+ virtual String get_visible_name() const;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual String get_save_extension() const;
+ virtual String get_resource_type() const;
+
+ virtual int get_preset_count() const;
+ virtual String get_preset_name(int p_idx) const;
+
+ virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
+ virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
+
+ virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
+
+ ResourceImporterCSVTranslation();
+};
+
+#endif // RESOURCEIMPORTERCSVTRANSLATION_H
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
new file mode 100644
index 0000000000..3b3e0e3a00
--- /dev/null
+++ b/editor/import/resource_importer_obj.cpp
@@ -0,0 +1,259 @@
+/*************************************************************************/
+/* resource_importer_obj.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_importer_obj.h"
+
+#include "io/resource_saver.h"
+#include "scene/resources/mesh.h"
+#include "scene/resources/surface_tool.h"
+#include "scene/resources/surface_tool.h"
+#include "os/file_access.h"
+
+String ResourceImporterOBJ::get_importer_name() const {
+
+ return "obj_mesh";
+}
+
+String ResourceImporterOBJ::get_visible_name() const{
+
+ return "OBJ As Mesh";
+}
+void ResourceImporterOBJ::get_recognized_extensions(List<String> *p_extensions) const{
+
+ p_extensions->push_back("obj");
+}
+String ResourceImporterOBJ::get_save_extension() const {
+ return "msh";
+}
+
+String ResourceImporterOBJ::get_resource_type() const{
+
+ return "Mesh";
+}
+
+bool ResourceImporterOBJ::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
+
+ return true;
+}
+
+int ResourceImporterOBJ::get_preset_count() const {
+ return 0;
+}
+String ResourceImporterOBJ::get_preset_name(int p_idx) const {
+
+ return String();
+}
+
+
+void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options,int p_preset) const {
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/tangents"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/normals"),true));
+ //not for nowp
+ //r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/materials")));
+ //r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/textures")));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/flip_faces"),false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/smooth_shading"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/weld_vertices"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001"),0.0001));
+ //r_options->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
+
+}
+
+
+
+Error ResourceImporterOBJ::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
+
+ FileAccessRef f = FileAccess::open(p_source_file,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
+
+ Ref<Mesh> mesh = Ref<Mesh>( memnew( Mesh ) );
+ Map<String,Ref<Material> > name_map;
+
+
+
+ bool generate_normals=p_options["generate/normals"];
+ bool generate_tangents=p_options["generate/tangents"];
+ bool flip_faces=p_options["force/flip_faces"];
+ bool force_smooth=p_options["force/smooth_shading"];
+ bool weld_vertices=p_options["force/weld_vertices"];
+ float weld_tolerance=p_options["force/weld_tolerance"];
+ Vector<Vector3> vertices;
+ Vector<Vector3> normals;
+ Vector<Vector2> uvs;
+ String name;
+
+ Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ;
+ surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
+ if (force_smooth)
+ surf_tool->add_smooth_group(true);
+ int has_index_data=false;
+
+ while(true) {
+
+
+ String l = f->get_line().strip_edges();
+
+ if (l.begins_with("v ")) {
+ //vertex
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+ Vector3 vtx;
+ vtx.x=v[1].to_float();
+ vtx.y=v[2].to_float();
+ vtx.z=v[3].to_float();
+ vertices.push_back(vtx);
+ } else if (l.begins_with("vt ")) {
+ //uv
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
+ Vector2 uv;
+ uv.x=v[1].to_float();
+ uv.y=1.0-v[2].to_float();
+ uvs.push_back(uv);
+
+ } else if (l.begins_with("vn ")) {
+ //normal
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+ Vector3 nrm;
+ nrm.x=v[1].to_float();
+ nrm.y=v[2].to_float();
+ nrm.z=v[3].to_float();
+ normals.push_back(nrm);
+ } else if (l.begins_with("f ")) {
+ //vertex
+
+ has_index_data=true;
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+
+ //not very fast, could be sped up
+
+
+ Vector<String> face[3];
+ face[0] = v[1].split("/");
+ face[1] = v[2].split("/");
+ ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR);
+ for(int i=2;i<v.size()-1;i++) {
+
+ face[2] = v[i+1].split("/");
+ ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR);
+ for(int j=0;j<3;j++) {
+
+ int idx=j;
+
+ if (!flip_faces && idx<2) {
+ idx=1^idx;
+ }
+
+
+ if (face[idx].size()==3) {
+ int norm = face[idx][2].to_int()-1;
+ ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR);
+ surf_tool->add_normal(normals[norm]);
+ }
+
+ if (face[idx].size()>=2 && face[idx][1]!=String()) {
+
+ int uv = face[idx][1].to_int()-1;
+ ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR);
+ surf_tool->add_uv(uvs[uv]);
+ }
+
+ int vtx = face[idx][0].to_int()-1;
+ ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR);
+
+ Vector3 vertex = vertices[vtx];
+ if (weld_vertices)
+ vertex=vertex.snapped(weld_tolerance);
+ surf_tool->add_vertex(vertex);
+ }
+
+ face[1]=face[2];
+ }
+ } else if (l.begins_with("s ") && !force_smooth) { //smoothing
+ String what = l.substr(2,l.length()).strip_edges();
+ if (what=="off")
+ surf_tool->add_smooth_group(false);
+ else
+ surf_tool->add_smooth_group(true);
+
+ } else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done
+
+ if (has_index_data) {
+ //new object/surface
+ if (generate_normals || force_smooth)
+ surf_tool->generate_normals();
+ if (uvs.size() && (normals.size() || generate_normals) && generate_tangents)
+ surf_tool->generate_tangents();
+
+ surf_tool->index();
+ mesh = surf_tool->commit(mesh);
+ if (name=="")
+ name=vformat(TTR("Surface %d"),mesh->get_surface_count()-1);
+ mesh->surface_set_name(mesh->get_surface_count()-1,name);
+ name="";
+ surf_tool->clear();
+ surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
+ if (force_smooth)
+ surf_tool->add_smooth_group(true);
+
+ has_index_data=false;
+
+ if (f->eof_reached())
+ break;
+ }
+
+ if (l.begins_with("o ")) //name
+ name=l.substr(2,l.length()).strip_edges();
+ }
+ }
+
+/*
+ TODO, check existing materials and merge?
+ //re-apply materials if exist
+ for(int i=0;i<mesh->get_surface_count();i++) {
+
+ String n = mesh->surface_get_name(i);
+ if (name_map.has(n))
+ mesh->surface_set_material(i,name_map[n]);
+ }
+*/
+
+ Error err = ResourceSaver::save(p_save_path+".msh",mesh);
+
+ return err;
+
+}
+
+ResourceImporterOBJ::ResourceImporterOBJ()
+{
+
+}
diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h
new file mode 100644
index 0000000000..e4e426f9e8
--- /dev/null
+++ b/editor/import/resource_importer_obj.h
@@ -0,0 +1,56 @@
+/*************************************************************************/
+/* resource_importer_obj.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCEIMPORTEROBJ_H
+#define RESOURCEIMPORTEROBJ_H
+
+
+#include "io/resource_import.h"
+
+class ResourceImporterOBJ : public ResourceImporter {
+ GDCLASS(ResourceImporterOBJ,ResourceImporter)
+public:
+ virtual String get_importer_name() const;
+ virtual String get_visible_name() const;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual String get_save_extension() const;
+ virtual String get_resource_type() const;
+
+ virtual int get_preset_count() const;
+ virtual String get_preset_name(int p_idx) const;
+
+ virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
+ virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
+
+ virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
+
+ ResourceImporterOBJ();
+};
+
+
+#endif // RESOURCEIMPORTEROBJ_H
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
new file mode 100644
index 0000000000..3f81b30bf6
--- /dev/null
+++ b/editor/import/resource_importer_scene.cpp
@@ -0,0 +1,1356 @@
+/*************************************************************************/
+/* resource_importer_scene.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_importer_scene.h"
+
+#include "scene/resources/packed_scene.h"
+#include "io/resource_saver.h"
+#include "editor/editor_node.h"
+
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/navigation.h"
+#include "scene/3d/room_instance.h"
+#include "scene/3d/body_shape.h"
+#include "scene/3d/physics_body.h"
+#include "scene/3d/portal.h"
+#include "scene/3d/vehicle_body.h"
+#include "scene/resources/sphere_shape.h"
+#include "scene/resources/box_shape.h"
+#include "scene/resources/ray_shape.h"
+#include "scene/resources/plane_shape.h"
+
+
+void EditorScenePostImport::_bind_methods() {
+
+ BIND_VMETHOD( MethodInfo("post_import",PropertyInfo(Variant::OBJECT,"scene")) );
+
+}
+
+Node *EditorScenePostImport::post_import(Node* p_scene) {
+
+ if (get_script_instance())
+ return get_script_instance()->call("post_import",p_scene);
+
+ return p_scene;
+}
+
+EditorScenePostImport::EditorScenePostImport() {
+
+
+}
+
+
+String ResourceImporterScene::get_importer_name() const {
+
+ return "scene";
+}
+
+String ResourceImporterScene::get_visible_name() const{
+
+ return "Scene";
+}
+
+void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions) const{
+
+ for (Set< Ref<EditorSceneImporter> >::Element *E=importers.front();E;E=E->next()) {
+ E->get()->get_extensions(p_extensions);
+ }
+}
+
+String ResourceImporterScene::get_save_extension() const {
+ return "scn";
+}
+
+String ResourceImporterScene::get_resource_type() const{
+
+ return "PackedScene";
+}
+
+bool ResourceImporterScene::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
+
+ if (p_option.begins_with("animation/")) {
+ if (p_option!="animation/import" && !bool(p_options["animation/import"]))
+ return false;
+
+ if (p_option.begins_with("animation/optimizer/") && p_option!="animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"]))
+ return false;
+
+ if (p_option.begins_with("animation/clip_")) {
+ int max_clip = p_options["animation/clips/amount"];
+ int clip = p_option.get_slice("/",1).get_slice("_",1).to_int()-1;
+ if (clip>=max_clip)
+ return false;
+ }
+ }
+
+ return true;
+
+}
+
+int ResourceImporterScene::get_preset_count() const {
+ return 0;
+}
+String ResourceImporterScene::get_preset_name(int p_idx) const {
+
+ return "";
+}
+
+
+static bool _teststr(const String& p_what,const String& p_str) {
+
+ if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
+ return true;
+ if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
+ return true;
+ if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
+ return true;
+ return false;
+}
+
+static String _fixstr(const String& p_what,const String& p_str) {
+
+ if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
+ return p_what.replace("$"+p_str,"");
+ if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
+ return p_what.substr(0,p_what.length()-(p_str.length()+1));
+ if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
+ return p_what.substr(0,p_what.length()-(p_str.length()+1));
+ return p_what;
+}
+
+
+Node* ResourceImporterScene::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map) {
+
+ // children first..
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+
+ Node *r = _fix_node(p_node->get_child(i),p_root,collision_map);
+ if (!r) {
+ print_line("was erased..");
+ i--; //was erased
+ }
+ }
+
+ String name = p_node->get_name();
+
+ bool isroot = p_node==p_root;
+
+
+ if (!isroot && _teststr(name,"noimp")) {
+
+ memdelete(p_node);
+ return NULL;
+ }
+
+
+ if (p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ bool bb=false;
+
+ if ((_teststr(name,"bb"))) {
+ bb=true;
+ } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) {
+ bb=true;
+
+ }
+
+ if (bb) {
+ mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
+ if (mi->get_mesh().is_valid()) {
+
+ Ref<Mesh> m = mi->get_mesh();
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
+ if (fm.is_valid()) {
+ //fm->set_flag(Material::FLAG_UNSHADED,true);
+ //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
+ //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ }
+ }
+ }
+ }
+ }
+
+
+ if (p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ Ref<Mesh> m = mi->get_mesh();
+
+ if (m.is_valid()) {
+
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> mat = m->surface_get_material(i);
+ if (!mat.is_valid())
+ continue;
+
+ if (_teststr(mat->get_name(),"alpha")) {
+
+ mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
+ mat->set_name(_fixstr(mat->get_name(),"alpha"));
+ }
+ if (_teststr(mat->get_name(),"vcol")) {
+
+ mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
+ mat->set_name(_fixstr(mat->get_name(),"vcol"));
+ }
+
+ }
+ }
+ }
+
+ if (p_node->cast_to<AnimationPlayer>()) {
+ //remove animations referencing non-importable nodes
+ AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>();
+
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
+
+ Ref<Animation> anim=ap->get_animation(E->get());
+ ERR_CONTINUE(anim.is_null());
+ for(int i=0;i<anim->get_track_count();i++) {
+ NodePath path = anim->track_get_path(i);
+
+ for(int j=0;j<path.get_name_count();j++) {
+ String node = path.get_name(j);
+ if (_teststr(node,"noimp")) {
+ anim->remove_track(i);
+ i--;
+ break;
+ }
+ }
+ }
+
+ }
+ }
+
+
+ if (p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ String str;
+
+ if ((_teststr(name,"imp"))) {
+ str=name;
+ } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) {
+ str=mi->get_mesh()->get_name();
+
+ }
+
+
+ if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
+ String d=str.substr(str.find("imp")+3,str.length());
+ if (d!="") {
+ if ((d[0]<'0' || d[0]>'9'))
+ d=d.substr(1,d.length());
+ if (d.length() && d[0]>='0' && d[0]<='9') {
+ float dist = d.to_double();
+ mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
+ mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true);
+ //mi->set_draw_range_begin(dist);
+ //mi->set_draw_range_end(100000);
+
+ //mip->set_draw_range_begin(0);
+ //mip->set_draw_range_end(dist);
+
+ if (mi->get_mesh().is_valid()) {
+
+ Ref<Mesh> m = mi->get_mesh();
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
+ if (fm.is_valid()) {
+ //fm->set_flag(Material::FLAG_UNSHADED,true);
+ //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
+ //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#if 0
+ if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ String str;
+
+ if ((_teststr(name,"lod"))) {
+ str=name;
+ } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) {
+ str=mi->get_mesh()->get_name();
+
+ }
+
+
+ if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
+ String d=str.substr(str.find("lod")+3,str.length());
+ if (d!="") {
+ if ((d[0]<'0' || d[0]>'9'))
+ d=d.substr(1,d.length());
+ if (d.length() && d[0]>='0' && d[0]<='9') {
+ float dist = d.to_double();
+ /// mi->set_draw_range_begin(dist);
+ // mi->set_draw_range_end(100000);
+
+ // mip->set_draw_range_begin(0);
+ // mip->set_draw_range_end(dist);
+
+ /*if (mi->get_mesh().is_valid()) {
+
+ Ref<Mesh> m = mi->get_mesh();
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
+ if (fm.is_valid()) {
+ fm->set_flag(Material::FLAG_UNSHADED,true);
+ fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
+ fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ }
+ }
+ }*/
+ }
+ }
+ }
+ }
+
+
+ if (p_flags&SCENE_FLAG_DETECT_LIGHTMAP_LAYER && _teststr(name,"lm") && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ String str=name;
+ int layer = str.substr(str.find("lm")+3,str.length()).to_int();
+ //mi->set_baked_light_texture_id(layer);
+ }
+#endif
+ if (_teststr(name,"colonly")) {
+
+ if (isroot)
+ return p_node;
+
+ if (p_node->cast_to<MeshInstance>()) {
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ Node * col = mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col,NULL);
+
+ col->set_name(_fixstr(name,"colonly"));
+ col->cast_to<Spatial>()->set_transform(mi->get_transform());
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node=col;
+
+ StaticBody *sb = col->cast_to<StaticBody>();
+ CollisionShape *colshape = memnew( CollisionShape);
+ colshape->set_shape(sb->get_shape(0));
+ colshape->set_name("shape");
+ sb->add_child(colshape);
+ colshape->set_owner(p_node->get_owner());
+ } else if (p_node->has_meta("empty_draw_type")) {
+ String empty_draw_type = String(p_node->get_meta("empty_draw_type"));
+ print_line(empty_draw_type);
+ StaticBody *sb = memnew( StaticBody);
+ sb->set_name(_fixstr(name,"colonly"));
+ sb->cast_to<Spatial>()->set_transform(p_node->cast_to<Spatial>()->get_transform());
+ p_node->replace_by(sb);
+ memdelete(p_node);
+ CollisionShape *colshape = memnew( CollisionShape);
+ if (empty_draw_type == "CUBE") {
+ BoxShape *boxShape = memnew( BoxShape);
+ boxShape->set_extents(Vector3(1, 1, 1));
+ colshape->set_shape(boxShape);
+ colshape->set_name("BoxShape");
+ } else if (empty_draw_type == "SINGLE_ARROW") {
+ RayShape *rayShape = memnew( RayShape);
+ rayShape->set_length(1);
+ colshape->set_shape(rayShape);
+ colshape->set_name("RayShape");
+ sb->cast_to<Spatial>()->rotate_x(Math_PI / 2);
+ } else if (empty_draw_type == "IMAGE") {
+ PlaneShape *planeShape = memnew( PlaneShape);
+ colshape->set_shape(planeShape);
+ colshape->set_name("PlaneShape");
+ } else {
+ SphereShape *sphereShape = memnew( SphereShape);
+ sphereShape->set_radius(1);
+ colshape->set_shape(sphereShape);
+ colshape->set_name("SphereShape");
+ }
+ sb->add_child(colshape);
+ colshape->set_owner(sb->get_owner());
+ }
+
+ } else if (_teststr(name,"rigid") && p_node->cast_to<MeshInstance>()) {
+
+ if (isroot)
+ return p_node;
+
+ // get mesh instance and bounding box
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ Rect3 aabb = mi->get_aabb();
+
+ // create a new rigid body collision node
+ RigidBody * rigid_body = memnew( RigidBody );
+ Node * col = rigid_body;
+ ERR_FAIL_COND_V(!col,NULL);
+
+ // remove node name postfix
+ col->set_name(_fixstr(name,"rigid"));
+ // get mesh instance xform matrix to the rigid body collision node
+ col->cast_to<Spatial>()->set_transform(mi->get_transform());
+ // save original node by duplicating it into a new instance and correcting the name
+ Node * mesh = p_node->duplicate();
+ mesh->set_name(_fixstr(name,"rigid"));
+ // reset the xform matrix of the duplicated node so it can inherit parent node xform
+ mesh->cast_to<Spatial>()->set_transform(Transform(Basis()));
+ // reparent the new mesh node to the rigid body collision node
+ p_node->add_child(mesh);
+ mesh->set_owner(p_node->get_owner());
+ // replace the original node with the rigid body collision node
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node=col;
+
+ // create an alias for the rigid body collision node
+ RigidBody *rb = col->cast_to<RigidBody>();
+ // create a new Box collision shape and set the right extents
+ Ref<BoxShape> shape = memnew( BoxShape );
+ shape->set_extents(aabb.get_size() * 0.5);
+ CollisionShape *colshape = memnew( CollisionShape);
+ colshape->set_name("shape");
+ colshape->set_shape(shape);
+ // reparent the new collision shape to the rigid body collision node
+ rb->add_child(colshape);
+ colshape->set_owner(p_node->get_owner());
+
+ } else if (_teststr(name,"col") && p_node->cast_to<MeshInstance>()) {
+
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ mi->set_name(_fixstr(name,"col"));
+ Node *col= mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col,NULL);
+
+ col->set_name("col");
+ p_node->add_child(col);
+
+ StaticBody *sb=col->cast_to<StaticBody>();
+ CollisionShape *colshape = memnew( CollisionShape);
+ colshape->set_shape(sb->get_shape(0));
+ colshape->set_name("shape");
+ col->add_child(colshape);
+ colshape->set_owner(p_node->get_owner());
+ sb->set_owner(p_node->get_owner());
+
+ } else if (_teststr(name,"navmesh") && p_node->cast_to<MeshInstance>()) {
+
+ if (isroot)
+ return p_node;
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ Ref<Mesh> mesh=mi->get_mesh();
+ ERR_FAIL_COND_V(mesh.is_null(),NULL);
+ NavigationMeshInstance *nmi = memnew( NavigationMeshInstance );
+
+
+ nmi->set_name(_fixstr(name,"navmesh"));
+ Ref<NavigationMesh> nmesh = memnew( NavigationMesh);
+ nmesh->create_from_mesh(mesh);
+ nmi->set_navigation_mesh(nmesh);
+ nmi->cast_to<Spatial>()->set_transform(mi->get_transform());
+ p_node->replace_by(nmi);
+ memdelete(p_node);
+ p_node=nmi;
+ } else if (_teststr(name,"vehicle")) {
+
+ if (isroot)
+ return p_node;
+
+ Node *owner = p_node->get_owner();
+ Spatial *s = p_node->cast_to<Spatial>();
+ VehicleBody *bv = memnew( VehicleBody );
+ String n = _fixstr(p_node->get_name(),"vehicle");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform());
+
+ p_node=bv;
+
+
+ } else if (_teststr(name,"wheel")) {
+
+ if (isroot)
+ return p_node;
+
+ Node *owner = p_node->get_owner();
+ Spatial *s = p_node->cast_to<Spatial>();
+ VehicleWheel *bv = memnew( VehicleWheel );
+ String n = _fixstr(p_node->get_name(),"wheel");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform());
+
+ p_node=bv;
+
+ } else if (_teststr(name,"room") && p_node->cast_to<MeshInstance>()) {
+
+
+ if (isroot)
+ return p_node;
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
+
+
+ BSP_Tree bsptree(faces);
+
+ Ref<RoomBounds> area = memnew( RoomBounds );
+ //area->set_bounds(faces);
+ //area->set_geometry_hint(faces);
+
+
+ Room * room = memnew( Room );
+ room->set_name(_fixstr(name,"room"));
+ room->set_transform(mi->get_transform());
+ room->set_room(area);
+
+ p_node->replace_by(room);
+ memdelete(p_node);
+ p_node=room;
+
+ } else if (_teststr(name,"room")) {
+
+ if (isroot)
+ return p_node;
+
+ Spatial *dummy = p_node->cast_to<Spatial>();
+ ERR_FAIL_COND_V(!dummy,NULL);
+
+ Room * room = memnew( Room );
+ room->set_name(_fixstr(name,"room"));
+ room->set_transform(dummy->get_transform());
+
+ p_node->replace_by(room);
+ memdelete(p_node);
+ p_node=room;
+
+ //room->compute_room_from_subtree();
+
+ } else if (_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) {
+
+ if (isroot)
+ return p_node;
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
+
+ ERR_FAIL_COND_V(faces.size()==0,NULL);
+ //step 1 compute the plane
+ Set<Vector3> points;
+ Plane plane;
+
+ Vector3 center;
+
+ for(int i=0;i<faces.size();i++) {
+
+ Face3 f = faces.get(i);
+ Plane p = f.get_plane();
+ plane.normal+=p.normal;
+ plane.d+=p.d;
+
+ for(int i=0;i<3;i++) {
+
+ Vector3 v = f.vertex[i].snapped(0.01);
+ if (!points.has(v)) {
+ points.insert(v);
+ center+=v;
+ }
+ }
+ }
+
+ plane.normal.normalize();
+ plane.d/=faces.size();
+ center/=points.size();
+
+ //step 2, create points
+
+ Transform t;
+ t.basis.from_z(plane.normal);
+ t.basis.transpose();
+ t.origin=center;
+
+ Vector<Point2> portal_points;
+
+ for(Set<Vector3>::Element *E=points.front();E;E=E->next()) {
+
+ Vector3 local = t.xform_inv(E->get());
+ portal_points.push_back(Point2(local.x,local.y));
+ }
+ // step 3 bubbly sort points
+
+ int swaps=0;
+
+ do {
+ swaps=0;
+
+ for(int i=0;i<portal_points.size()-1;i++) {
+
+ float a = portal_points[i].angle();
+ float b = portal_points[i+1].angle();
+
+ if (a>b) {
+ SWAP( portal_points[i], portal_points[i+1] );
+ swaps++;
+ }
+
+ }
+
+ } while(swaps);
+
+
+ Portal *portal = memnew( Portal );
+
+ portal->set_shape(portal_points);
+ portal->set_transform( mi->get_transform() * t);
+
+ p_node->replace_by(portal);
+ memdelete(p_node);
+ p_node=portal;
+
+ } else if (p_node->cast_to<MeshInstance>()) {
+
+ //last attempt, maybe collision insde the mesh data
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ Ref<Mesh> mesh = mi->get_mesh();
+ if (!mesh.is_null()) {
+
+ if (_teststr(mesh->get_name(),"col")) {
+
+ mesh->set_name( _fixstr(mesh->get_name(),"col") );
+ Ref<Shape> shape;
+
+ if (collision_map.has(mesh)) {
+ shape = collision_map[mesh];
+
+ } else {
+
+ shape = mesh->create_trimesh_shape();
+ if (!shape.is_null())
+ collision_map[mesh]=shape;
+
+
+ }
+
+ if (!shape.is_null()) {
+#if 0
+ StaticBody* static_body = memnew( StaticBody );
+ ERR_FAIL_COND_V(!static_body,NULL);
+ static_body->set_name( String(mesh->get_name()) + "_col" );
+ shape->set_name(static_body->get_name());
+ static_body->add_shape(shape);
+
+ mi->add_child(static_body);
+ if (mi->get_owner())
+ static_body->set_owner( mi->get_owner() );
+#endif
+ }
+
+ }
+
+ for(int i=0;i<mesh->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = mesh->surface_get_material(i);
+ if (fm.is_valid()) {
+ String name = fm->get_name();
+ /* if (_teststr(name,"alpha")) {
+ fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ name=_fixstr(name,"alpha");
+ }
+
+ if (_teststr(name,"vcol")) {
+ fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true);
+ name=_fixstr(name,"vcol");
+ }*/
+ fm->set_name(name);
+ }
+ }
+
+ }
+
+ }
+
+
+ return p_node;
+}
+
+
+void ResourceImporterScene::_create_clips(Node *scene, const Array& p_clips,bool p_bake_all) {
+
+ if (!scene->has_node(String("AnimationPlayer")))
+ return;
+
+ Node* n = scene->get_node(String("AnimationPlayer"));
+ ERR_FAIL_COND(!n);
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+ ERR_FAIL_COND(!anim);
+
+ if (!anim->has_animation("default"))
+ return;
+
+
+ Ref<Animation> default_anim = anim->get_animation("default");
+
+ for(int i=0;i<p_clips.size();i+=4) {
+
+ String name = p_clips[i];
+ float from=p_clips[i+1];
+ float to=p_clips[i+2];
+ bool loop=p_clips[i+3];
+ if (from>=to)
+ continue;
+
+ Ref<Animation> new_anim = memnew( Animation );
+
+ for(int j=0;j<default_anim->get_track_count();j++) {
+
+
+ List<float> keys;
+ int kc = default_anim->track_get_key_count(j);
+ int dtrack=-1;
+ for(int k=0;k<kc;k++) {
+
+ float kt = default_anim->track_get_key_time(j,k);
+ if (kt>=from && kt<to) {
+
+ //found a key within range, so create track
+ if (dtrack==-1) {
+ new_anim->add_track(default_anim->track_get_type(j));
+ dtrack = new_anim->get_track_count()-1;
+ new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
+
+ if (kt>(from+0.01) && k>0) {
+
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_interpolate(j,from,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,0,p,q,s);
+ }
+ }
+
+ }
+
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_get_key(j,k,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,kt-from,p,q,s);
+ }
+
+ }
+
+ if (dtrack!=-1 && kt>=to) {
+
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_interpolate(j,to,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
+ }
+ }
+
+ }
+
+ if (dtrack==-1 && p_bake_all) {
+ new_anim->add_track(default_anim->track_get_type(j));
+ dtrack = new_anim->get_track_count()-1;
+ new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+
+
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_interpolate(j,from,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,0,p,q,s);
+ default_anim->transform_track_interpolate(j,to,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
+ }
+
+ }
+ }
+
+
+ new_anim->set_loop(loop);
+ new_anim->set_length(to-from);
+ anim->add_animation(name,new_anim);
+ }
+
+ anim->remove_animation("default"); //remove default (no longer needed)
+}
+
+void ResourceImporterScene::_filter_anim_tracks(Ref<Animation> anim,Set<String> &keep) {
+
+ Ref<Animation> a = anim;
+ ERR_FAIL_COND(!a.is_valid());
+
+ print_line("From Anim "+anim->get_name()+":");
+
+ for(int j=0;j<a->get_track_count();j++) {
+
+ String path = a->track_get_path(j);
+
+ if (!keep.has(path)) {
+
+ print_line("Remove: "+path);
+ a->remove_track(j);
+ j--;
+ }
+
+ }
+}
+
+
+void ResourceImporterScene::_filter_tracks(Node *scene, const String& p_text) {
+
+ if (!scene->has_node(String("AnimationPlayer")))
+ return;
+ Node* n = scene->get_node(String("AnimationPlayer"));
+ ERR_FAIL_COND(!n);
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+ ERR_FAIL_COND(!anim);
+
+ Vector<String> strings = p_text.split("\n");
+ for(int i=0;i<strings.size();i++) {
+
+ strings[i]=strings[i].strip_edges();
+ }
+
+ List<StringName> anim_names;
+ anim->get_animation_list(&anim_names);
+ for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
+
+ String name = E->get();
+ bool valid_for_this=false;
+ bool valid=false;
+
+ Set<String> keep;
+ Set<String> keep_local;
+
+
+ for(int i=0;i<strings.size();i++) {
+
+
+ if (strings[i].begins_with("@")) {
+
+ valid_for_this=false;
+ for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
+ keep.insert(F->get());
+ }
+ keep_local.clear();
+
+ Vector<String> filters=strings[i].substr(1,strings[i].length()).split(",");
+ for(int j=0;j<filters.size();j++) {
+
+ String fname = filters[j].strip_edges();
+ if (fname=="")
+ continue;
+ int fc = fname[0];
+ bool plus;
+ if (fc=='+')
+ plus=true;
+ else if (fc=='-')
+ plus=false;
+ else
+ continue;
+
+ String filter=fname.substr(1,fname.length()).strip_edges();
+
+ if (!name.matchn(filter))
+ continue;
+ valid_for_this=plus;
+ }
+
+ if (valid_for_this)
+ valid=true;
+
+ } else if (valid_for_this) {
+
+ Ref<Animation> a = anim->get_animation(name);
+ if (!a.is_valid())
+ continue;
+
+ for(int j=0;j<a->get_track_count();j++) {
+
+ String path = a->track_get_path(j);
+
+ String tname = strings[i];
+ if (tname=="")
+ continue;
+ int fc = tname[0];
+ bool plus;
+ if (fc=='+')
+ plus=true;
+ else if (fc=='-')
+ plus=false;
+ else
+ continue;
+
+ String filter=tname.substr(1,tname.length()).strip_edges();
+
+ if (!path.matchn(filter))
+ continue;
+
+ if (plus)
+ keep_local.insert(path);
+ else if (!keep.has(path)) {
+ keep_local.erase(path);
+ }
+ }
+
+ }
+
+ }
+
+ if (valid) {
+ for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
+ keep.insert(F->get());
+ }
+ _filter_anim_tracks(anim->get_animation(name),keep);
+ } else {
+
+ }
+
+ }
+
+
+
+}
+
+void ResourceImporterScene::_optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle) {
+
+ if (!scene->has_node(String("AnimationPlayer")))
+ return;
+ Node* n = scene->get_node(String("AnimationPlayer"));
+ ERR_FAIL_COND(!n);
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+ ERR_FAIL_COND(!anim);
+
+
+ List<StringName> anim_names;
+ anim->get_animation_list(&anim_names);
+ for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
+
+ Ref<Animation> a = anim->get_animation(E->get());
+ a->optimize(p_max_lin_error,p_max_ang_error,Math::deg2rad(p_max_angle));
+ }
+}
+
+
+static String _make_extname(const String& p_str) {
+
+ String ext_name=p_str.replace(".","_");
+ ext_name=ext_name.replace(":","_");
+ ext_name=ext_name.replace("\"","_");
+ ext_name=ext_name.replace("<","_");
+ ext_name=ext_name.replace(">","_");
+ ext_name=ext_name.replace("/","_");
+ ext_name=ext_name.replace("|","_");
+ ext_name=ext_name.replace("\\","_");
+ ext_name=ext_name.replace("?","_");
+ ext_name=ext_name.replace("*","_");
+
+ return ext_name;
+}
+
+void ResourceImporterScene::_make_external_resources(Node* p_node,const String& p_base_path, bool p_make_materials, bool p_make_meshes, Map<Ref<Material>,Ref<Material> >& p_materials, Map<Ref<Mesh>,Ref<Mesh> >& p_meshes) {
+
+ List<PropertyInfo> pi;
+
+ p_node->get_property_list(&pi);
+
+ for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
+
+ if (E->get().type==Variant::OBJECT) {
+
+ Ref<Material> mat = p_node->get(E->get().name);
+ if (p_make_materials && mat.is_valid() && mat->get_name()!="") {
+
+
+ if (!p_materials.has(mat)) {
+
+ String ext_name = p_base_path+"."+_make_extname(mat->get_name())+".mtl";
+ if (FileAccess::exists(ext_name)) {
+ //if exists, use it
+ Ref<Material> existing = ResourceLoader::load(ext_name);
+ p_materials[mat]=existing;
+ } else {
+
+ ResourceSaver::save(ext_name,mat,ResourceSaver::FLAG_CHANGE_PATH);
+ p_materials[mat]=mat;
+ }
+ }
+
+ if (p_materials[mat]!=mat) {
+
+ p_node->set(E->get().name,p_materials[mat]);
+ }
+ } else {
+
+ Ref<Mesh> mesh = p_node->get(E->get().name);
+
+ if (mesh.is_valid()) {
+
+ bool mesh_just_added=false;
+
+ if (p_make_meshes) {
+
+ if (!p_meshes.has(mesh)) {
+
+ String ext_name = p_base_path+"."+_make_extname(mesh->get_name())+".msh";
+ if (FileAccess::exists(ext_name)) {
+ //if exists, use it
+ Ref<Mesh> existing = ResourceLoader::load(ext_name);
+ p_meshes[mesh]=existing;
+ } else {
+
+ ResourceSaver::save(ext_name,mesh,ResourceSaver::FLAG_CHANGE_PATH);
+ p_meshes[mesh]=mesh;
+ mesh_just_added=true;
+ }
+
+
+ }
+ }
+
+
+ if (p_make_materials){
+
+ if (mesh_just_added || !p_meshes.has(mesh)) {
+
+
+ for(int i=0;i<mesh->get_surface_count();i++) {
+ mat=mesh->surface_get_material(i);
+ if (!mat.is_valid() || mat->get_name()=="")
+ continue;
+
+ if (!p_materials.has(mat)) {
+
+ String ext_name = p_base_path+"."+_make_extname(mat->get_name())+".mtl";
+ if (FileAccess::exists(ext_name)) {
+ //if exists, use it
+ Ref<Material> existing = ResourceLoader::load(ext_name);
+ p_materials[mat]=existing;
+ } else {
+
+ ResourceSaver::save(ext_name,mat,ResourceSaver::FLAG_CHANGE_PATH);
+ p_materials[mat]=mat;
+ }
+ }
+
+ if (p_materials[mat]!=mat) {
+
+ mesh->surface_set_material(i,p_materials[mat]);
+ }
+
+ }
+
+ if(!p_make_meshes) {
+ p_meshes[mesh]=Ref<Mesh>(); //save it anyway, so it won't be checked again
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ _make_external_resources(p_node->get_child(i),p_base_path,p_make_materials,p_make_meshes,p_materials,p_meshes);
+ }
+}
+
+
+void ResourceImporterScene::get_import_options(List<ImportOption> *r_options,int p_preset) const {
+
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"nodes/root_type",PROPERTY_HINT_TYPE_STRING,"Node"),"Spatial"));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"nodes/root_name"),"Scene Root"));
+
+ List<String> script_extentions;
+ ResourceLoader::get_recognized_extensions_for_type("Script",&script_extentions);
+
+ String script_ext_hint;
+
+ for(List<String>::Element *E=script_extentions.front();E;E=E->next()) {
+ if (script_ext_hint!="")
+ script_ext_hint+=",";
+ script_ext_hint+="*."+E->get();
+ }
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"nodes/custom_script",PROPERTY_HINT_FILE,script_ext_hint),""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"materials/location",PROPERTY_HINT_ENUM,"Node,Mesh"),0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"materials/storage",PROPERTY_HINT_ENUM,"Bult-In,Files"),0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"geometry/compress"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"geometry/ensure_tangents"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"geometry/storage",PROPERTY_HINT_ENUM,"Built-In,Files"),0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/import",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/fps",PROPERTY_HINT_RANGE,"1,120,1"),15));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"animation/filter_script",PROPERTY_HINT_MULTILINE_TEXT),""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/optimizer/enabled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/optimizer/max_linear_error"),0.05));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/optimizer/max_angular_error"),0.01));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/optimizer/max_angle"),22));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/optimizer/remove_unused_tracks"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"animation/clips/amount",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),0));
+ for(int i=0;i<256;i++) {
+ r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"animation/clip_"+itos(i+1)+"/name"),""));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"animation/clip_"+itos(i+1)+"/start_frame"),0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"animation/clip_"+itos(i+1)+"/end_frame"),0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/clip_"+itos(i+1)+"/loops"),false));
+ }
+}
+
+Error ResourceImporterScene::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
+
+ String src_path=p_source_file;
+
+ Ref<EditorSceneImporter> importer;
+ String ext=src_path.get_extension().to_lower();
+
+
+ EditorProgress progress("import",TTR("Import Scene"),104);
+ progress.step(TTR("Importing Scene.."),0);
+
+ for(Set< Ref<EditorSceneImporter> >::Element *E=importers.front();E;E=E->next()) {
+
+ List<String> extensions;
+ E->get()->get_extensions(&extensions);
+
+ for(List<String>::Element *F=extensions.front();F;F=F->next()) {
+
+ if (F->get().to_lower()==ext) {
+
+ importer = E->get();
+ break;
+ }
+ }
+
+ if (importer.is_valid())
+ break;
+ }
+
+ ERR_FAIL_COND_V(!importer.is_valid(),ERR_FILE_UNRECOGNIZED);
+
+ float fps=p_options["animation/fps"];
+
+
+
+ int import_flags=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
+ if (!bool(p_options["animation/optimizer/remove_unused_tracks"]))
+ import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS;
+
+ if (bool(p_options["animation/import"]))
+ import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
+
+ if (bool(p_options["geometry/ensure_tangents"]))
+ import_flags|=EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
+
+ if (int(p_options["materials/location"])==0)
+ import_flags|=EditorSceneImporter::IMPORT_MATERIALS_IN_INSTANCES;
+
+
+ Error err=OK;
+ List<String> missing_deps; // for now, not much will be done with this
+ Node *scene = importer->import_scene(src_path,import_flags,fps,&missing_deps,&err);
+ if (!scene || err!=OK) {
+ return err;
+ }
+
+ String root_type = p_options["nodes/root_type"];
+
+ if (scene->get_class()!=root_type) {
+ Object *base = ClassDB::instance(root_type);
+ Node *base_node = NULL;
+ if (base)
+ base_node=base->cast_to<Node>();
+
+ if (base_node) {
+
+ scene->replace_by(base_node);
+ memdelete(scene);
+ scene=base_node;
+ }
+ }
+
+ scene->set_name(p_options["nodes/root_name"]);
+
+
+ err=OK;
+
+ String animation_filter = String(p_options["animation/filter_script"]).strip_edges();
+
+ bool use_optimizer = p_options["animation/optimizer/enabled"];
+ float anim_optimizer_linerr=p_options["animation/optimizer/max_linear_error"];
+ float anim_optimizer_angerr=p_options["animation/optimizer/max_angular_error"];
+ float anim_optimizer_maxang=p_options["animation/optimizer/max_angle"];
+
+ Map<Ref<Mesh>,Ref<Shape> > collision_map;
+
+ scene=_fix_node(scene,scene,collision_map);
+
+ if (use_optimizer) {
+ _optimize_animations(scene,anim_optimizer_linerr,anim_optimizer_angerr,anim_optimizer_maxang);
+ }
+
+ Array animation_clips;
+ {
+
+
+ int clip_count = p_options["animation/clips/amount"];
+
+ for(int i=0;i<clip_count;i++) {
+ String name = p_options["animation/clip_"+itos(i+1)+"/name"];
+ int from_frame = p_options["animation/clip_"+itos(i+1)+"/start_frame"];
+ int end_frame = p_options["animation/clip_"+itos(i+1)+"/end_frame"];
+ bool loop = p_options["animation/clip_"+itos(i+1)+"/loops"];
+
+ animation_clips.push_back(name);
+ animation_clips.push_back(from_frame/fps);
+ animation_clips.push_back(end_frame/fps);
+ animation_clips.push_back(loop);
+ }
+
+ }
+ if (animation_clips.size()) {
+ _create_clips(scene,animation_clips,!bool(p_options["animation/optimizer/remove_unused_tracks"]));
+ }
+
+ if (animation_filter!="") {
+ _filter_tracks(scene,animation_filter);
+ }
+
+
+ bool external_materials = p_options["materials/storage"];
+ bool external_meshes = p_options["geometry/storage"];
+
+ if (external_materials || external_meshes) {
+ Map<Ref<Material>, Ref<Material> > mat_map;
+ Map<Ref<Mesh>, Ref<Mesh> > mesh_map;
+ _make_external_resources(scene,p_source_file.get_basename(),external_materials,external_meshes,mat_map,mesh_map);
+ }
+
+ progress.step(TTR("Running Custom Script.."),2);
+
+ String post_import_script_path = p_options["nodes/custom_script"];
+ Ref<EditorScenePostImport> post_import_script;
+
+ if (post_import_script_path!="") {
+ post_import_script_path = post_import_script_path; // FIXME: is there a good reason for this?
+ Ref<Script> scr = ResourceLoader::load(post_import_script_path);
+ if (!scr.is_valid()) {
+ EditorNode::add_io_error(TTR("Couldn't load post-import script:")+" "+post_import_script_path);
+ } else {
+
+ post_import_script = Ref<EditorScenePostImport>( memnew( EditorScenePostImport ) );
+ post_import_script->set_script(scr.get_ref_ptr());
+ if (!post_import_script->get_script_instance()) {
+ EditorNode::add_io_error(TTR("Invalid/broken script for post-import (check console):")+" "+post_import_script_path);
+ post_import_script.unref();
+ return ERR_CANT_CREATE;
+ }
+ }
+ }
+
+
+ if (post_import_script.is_valid()) {
+ scene = post_import_script->post_import(scene);
+ if (!scene) {
+ EditorNode::add_io_error(TTR("Error running post-import script:")+" "+post_import_script_path);
+ return err;
+ }
+
+
+ }
+
+ progress.step(TTR("Saving.."),104);
+
+ Ref<PackedScene> packer = memnew( PackedScene );
+ packer->pack(scene);
+ print_line("SAVING TO: "+p_save_path+".scn");
+ err = ResourceSaver::save(p_save_path+".scn",packer); //do not take over, let the changed files reload themselves
+
+ memdelete(scene);
+
+ EditorNode::get_singleton()->reload_scene(p_source_file);
+
+ return OK;
+}
+
+ResourceImporterScene *ResourceImporterScene::singleton=NULL;
+
+ResourceImporterScene::ResourceImporterScene()
+{
+ singleton=this;
+}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
new file mode 100644
index 0000000000..ab6b223839
--- /dev/null
+++ b/editor/import/resource_importer_scene.h
@@ -0,0 +1,121 @@
+/*************************************************************************/
+/* resource_importer_scene.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCEIMPORTERSCENE_H
+#define RESOURCEIMPORTERSCENE_H
+
+#include "io/resource_import.h"
+#include "scene/resources/animation.h"
+#include "scene/resources/shape.h"
+
+class Material;
+
+class EditorSceneImporter : public Reference {
+
+ GDCLASS(EditorSceneImporter,Reference );
+public:
+
+ enum ImportFlags {
+ IMPORT_SCENE=1,
+ IMPORT_ANIMATION=2,
+ IMPORT_ANIMATION_DETECT_LOOP=4,
+ IMPORT_ANIMATION_OPTIMIZE=8,
+ IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=16,
+ IMPORT_ANIMATION_KEEP_VALUE_TRACKS=32,
+ IMPORT_GENERATE_TANGENT_ARRAYS=256,
+ IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512,
+ IMPORT_MATERIALS_IN_INSTANCES=1024
+
+ };
+
+ virtual uint32_t get_import_flags() const=0;
+ virtual void get_extensions(List<String> *r_extensions) const=0;
+ virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps,Error* r_err=NULL)=0;
+ virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0;
+
+
+
+ EditorSceneImporter() {}
+};
+
+class EditorScenePostImport : public Reference {
+
+ GDCLASS(EditorScenePostImport,Reference );
+protected:
+
+ static void _bind_methods();
+public:
+
+ virtual Node* post_import(Node* p_scene);
+ EditorScenePostImport();
+};
+
+
+class ResourceImporterScene : public ResourceImporter {
+ GDCLASS(ResourceImporterScene,ResourceImporter)
+
+ Set< Ref<EditorSceneImporter> > importers;
+
+ static ResourceImporterScene *singleton;
+public:
+
+ static ResourceImporterScene *get_singleton() { return singleton; }
+
+ const Set< Ref<EditorSceneImporter> >& get_importers() const { return importers; }
+
+ void add_importer(Ref<EditorSceneImporter> p_importer) { importers.insert(p_importer); }
+
+ virtual String get_importer_name() const;
+ virtual String get_visible_name() const;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual String get_save_extension() const;
+ virtual String get_resource_type() const;
+
+
+ virtual int get_preset_count() const;
+ virtual String get_preset_name(int p_idx) const;
+
+ virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
+ virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
+
+ void _make_external_resources(Node* p_node,const String& p_base_path, bool p_make_materials, bool p_make_meshes, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<Mesh>, Ref<Mesh> > &p_meshes);
+
+ Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map);
+
+ void _create_clips(Node *scene, const Array& p_clips,bool p_bake_all);
+ void _filter_anim_tracks(Ref<Animation> anim,Set<String> &keep);
+ void _filter_tracks(Node *scene, const String& p_text);
+ void _optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle);
+
+ virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
+
+ ResourceImporterScene();
+};
+
+
+#endif // RESOURCEIMPORTERSCENE_H
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
new file mode 100644
index 0000000000..f7bd944ceb
--- /dev/null
+++ b/editor/import/resource_importer_texture.cpp
@@ -0,0 +1,422 @@
+/*************************************************************************/
+/* resource_importer_texture.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_importer_texture.h"
+
+#include "io/image_loader.h"
+#include "scene/resources/texture.h"
+#include "editor/editor_file_system.h"
+#include "io/config_file.h"
+
+
+void ResourceImporterTexture::_texture_reimport_srgb(const Ref<StreamTexture>& p_tex) {
+
+ singleton->mutex->lock();
+ StringName path = p_tex->get_path();
+
+ if (!singleton->make_flags.has(path)) {
+ singleton->make_flags[path]=0;
+ }
+
+ singleton->make_flags[path]|=MAKE_SRGB_FLAG;
+
+ print_line("requesting srgb for "+String(path));
+
+ singleton->mutex->unlock();
+
+}
+
+
+
+void ResourceImporterTexture::_texture_reimport_3d(const Ref<StreamTexture>& p_tex) {
+
+
+ singleton->mutex->lock();
+ StringName path = p_tex->get_path();
+
+ if (!singleton->make_flags.has(path)) {
+ singleton->make_flags[path]=0;
+ }
+
+ singleton->make_flags[path]|=MAKE_3D_FLAG;
+
+ print_line("requesting 3d for "+String(path));
+
+ singleton->mutex->unlock();
+
+
+}
+
+void ResourceImporterTexture::update_imports() {
+
+ if (EditorFileSystem::get_singleton()->is_scanning() || EditorFileSystem::get_singleton()->is_importing()) {
+ return; // do nothing for noe
+ }
+ mutex->lock();
+
+ if (make_flags.empty()) {
+ mutex->unlock();
+ return;
+ }
+
+ Vector<String> to_reimport;
+ for (Map<StringName,int>::Element *E=make_flags.front();E;E=E->next()) {
+
+ print_line("checking for reimport "+String(E->key()));
+
+
+ Ref<ConfigFile> cf;
+ cf.instance();
+ String src_path = String(E->key())+".import";
+
+ Error err = cf->load(src_path);
+ ERR_CONTINUE(err!=OK);
+
+ bool changed=false;
+ if (E->get()&MAKE_SRGB_FLAG && int(cf->get_value("params","flags/srgb"))==2) {
+ cf->set_value("params","flags/srgb",1);
+ changed=true;
+ }
+
+ if (E->get()&MAKE_3D_FLAG && bool(cf->get_value("params","detect_3d"))) {
+ cf->set_value("params","detect_3d",false);
+ cf->set_value("params","compress/mode",2);
+ cf->set_value("params","flags/repeat",true);
+ cf->set_value("params","flags/filter",true);
+ cf->set_value("params","flags/mipmaps",true);
+ changed=true;
+ }
+
+ if (changed) {
+ cf->save(src_path);
+ to_reimport.push_back(E->key());
+ }
+
+ }
+
+ make_flags.clear();
+
+ mutex->unlock();
+
+ if (to_reimport.size()) {
+ EditorFileSystem::get_singleton()->reimport_files(to_reimport);
+ }
+
+}
+
+
+
+String ResourceImporterTexture::get_importer_name() const {
+
+ return "texture";
+}
+
+String ResourceImporterTexture::get_visible_name() const{
+
+ return "Texture";
+}
+void ResourceImporterTexture::get_recognized_extensions(List<String> *p_extensions) const{
+
+ ImageLoader::get_recognized_extensions(p_extensions);
+}
+String ResourceImporterTexture::get_save_extension() const {
+ return "stex";
+}
+
+String ResourceImporterTexture::get_resource_type() const{
+
+ return "StreamTexture";
+}
+
+bool ResourceImporterTexture::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
+
+ if (p_option=="compress/lossy_quality" && int(p_options["compress/mode"])!=COMPRESS_LOSSY)
+ return false;
+
+ return true;
+}
+
+int ResourceImporterTexture::get_preset_count() const {
+ return 4;
+}
+String ResourceImporterTexture::get_preset_name(int p_idx) const {
+
+ static const char* preset_names[]={
+ "2D, Detect 3D",
+ "2D",
+ "2D Pixel",
+ "3D"
+ };
+
+ return preset_names[p_idx];
+}
+
+
+void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,int p_preset) const {
+
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Lossless,Lossy,Video RAM,Uncompressed",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),p_preset==PRESET_3D?2:0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"compress/lossy_quality",PROPERTY_HINT_RANGE,"0,1,0.01"),0.7));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/repeat",PROPERTY_HINT_ENUM,"Disabled,Enabled,Mirrored"),p_preset==PRESET_3D?1:0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/filter"),p_preset==PRESET_2D_PIXEL?false:true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/mipmaps"),p_preset==PRESET_3D?true:false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/anisotropic"),false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/srgb",PROPERTY_HINT_ENUM,"Disable,Enable,Detect"),2));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/fix_alpha_border"),p_preset!=PRESET_3D?true:false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/premult_alpha"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"stream"),false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"size_limit",PROPERTY_HINT_RANGE,"0,4096,1"),0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"detect_3d"),p_preset==PRESET_DETECT));
+
+}
+
+
+void ResourceImporterTexture::_save_stex(const Image& p_image, const String& p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable, bool p_detect_3d, bool p_detect_srgb) {
+
+
+ FileAccess *f = FileAccess::open(p_to_path,FileAccess::WRITE);
+ f->store_8('G');
+ f->store_8('D');
+ f->store_8('S');
+ f->store_8('T'); //godot streamable texture
+
+ f->store_32(p_image.get_width());
+ f->store_32(p_image.get_height());
+ f->store_32(p_texture_flags);
+
+ uint32_t format=0;
+
+ if (p_streamable)
+ format|=StreamTexture::FORMAT_BIT_STREAM;
+ if (p_mipmaps || p_compress_mode==COMPRESS_VIDEO_RAM) //VRAM always uses mipmaps
+ format|=StreamTexture::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit
+ if (p_detect_3d)
+ format|=StreamTexture::FORMAT_BIT_DETECT_3D;
+ if (p_detect_srgb)
+ format|=StreamTexture::FORMAT_BIT_DETECT_SRGB;
+
+
+ switch (p_compress_mode) {
+ case COMPRESS_LOSSLESS: {
+
+ Image image = p_image;
+ if (p_mipmaps) {
+ image.generate_mipmaps();
+ } else {
+ image.clear_mipmaps();
+ }
+
+ int mmc = image.get_mipmap_count() + 1;
+
+ format|=StreamTexture::FORMAT_BIT_LOSSLESS;
+ f->store_32(format);
+ f->store_32(mmc);
+
+ for(int i=0;i<mmc;i++) {
+
+ if (i>0) {
+ image.shrink_x2();
+ }
+
+ PoolVector<uint8_t> data = Image::lossless_packer(image);
+ int data_len = data.size();
+ f->store_32(data_len);
+
+ PoolVector<uint8_t>::Read r= data.read();
+ f->store_buffer(r.ptr(),data_len);
+
+ }
+
+
+ } break;
+ case COMPRESS_LOSSY: {
+ Image image = p_image;
+ if (p_mipmaps) {
+ image.generate_mipmaps();
+ } else {
+ image.clear_mipmaps();
+ }
+
+ int mmc = image.get_mipmap_count() + 1;
+
+ format|=StreamTexture::FORMAT_BIT_LOSSY;
+ f->store_32(format);
+ f->store_32(mmc);
+
+ for(int i=0;i<mmc;i++) {
+
+ if (i>0) {
+ image.shrink_x2();
+ }
+
+ PoolVector<uint8_t> data = Image::lossy_packer(image,p_lossy_quality);
+ int data_len = data.size();
+ f->store_32(data_len);
+
+ PoolVector<uint8_t>::Read r = data.read();
+ f->store_buffer(r.ptr(),data_len);
+
+ }
+ } break;
+ case COMPRESS_VIDEO_RAM: {
+
+ Image image = p_image;
+ image.generate_mipmaps();
+ image.compress(p_vram_compression);
+
+ format |= image.get_format();
+
+ f->store_32(format);
+
+ PoolVector<uint8_t> data=image.get_data();
+ int dl = data.size();
+ PoolVector<uint8_t>::Read r = data.read();
+ f->store_buffer(r.ptr(),dl);
+
+ } break;
+ case COMPRESS_UNCOMPRESSED: {
+
+ Image image = p_image;
+ if (p_mipmaps) {
+ image.generate_mipmaps();
+ } else {
+ image.clear_mipmaps();
+ }
+
+ format |= image.get_format();
+ f->store_32(format);
+
+ PoolVector<uint8_t> data=image.get_data();
+ int dl = data.size();
+ PoolVector<uint8_t>::Read r = data.read();
+
+ f->store_buffer(r.ptr(),dl);
+
+ } break;
+ }
+
+ memdelete(f);
+}
+
+Error ResourceImporterTexture::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
+
+ int compress_mode = p_options["compress/mode"];
+ float lossy= p_options["compress/lossy_quality"];
+ int repeat= p_options["flags/repeat"];
+ bool filter= p_options["flags/filter"];
+ bool mipmaps= p_options["flags/mipmaps"];
+ bool anisotropic= p_options["flags/anisotropic"];
+ int srgb= p_options["flags/srgb"];
+ bool fix_alpha_border= p_options["process/fix_alpha_border"];
+ bool premult_alpha= p_options["process/premult_alpha"];
+ bool stream = p_options["stream"];
+ int size_limit = p_options["size_limit"];
+
+
+ Image image;
+ Error err = ImageLoader::load_image(p_source_file,&image);
+ if (err!=OK)
+ return err;
+
+
+ int tex_flags=0;
+ if (repeat>0)
+ tex_flags|=Texture::FLAG_REPEAT;
+ if (repeat==2)
+ tex_flags|=Texture::FLAG_MIRRORED_REPEAT;
+ if (filter)
+ tex_flags|=Texture::FLAG_FILTER;
+ if (mipmaps || compress_mode==COMPRESS_VIDEO_RAM)
+ tex_flags|=Texture::FLAG_MIPMAPS;
+ if (anisotropic)
+ tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER;
+ if (srgb==1)
+ tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR;
+
+ if (size_limit >0 && (image.get_width()>size_limit || image.get_height()>size_limit )) {
+ //limit size
+ if (image.get_width() >= image.get_height()) {
+ int new_width = size_limit;
+ int new_height = image.get_height() * new_width / image.get_width();
+
+ image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC);
+ } else {
+
+ int new_height = size_limit;
+ int new_width = image.get_width() * new_height / image.get_height();
+
+ image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC);
+ }
+ }
+
+ if (fix_alpha_border) {
+ image.fix_alpha_edges();
+ }
+
+ if (premult_alpha) {
+ image.premultiply_alpha();
+ }
+
+ bool detect_3d = p_options["detect_3d"];
+ bool detect_srgb = srgb==2;
+
+ if (compress_mode==COMPRESS_VIDEO_RAM) {
+ //must import in all formats
+ //Android, GLES 2.x
+ _save_stex(image,p_save_path+".etc.stex",compress_mode,lossy,Image::COMPRESS_ETC,mipmaps,tex_flags,stream,detect_3d,detect_srgb);
+ r_platform_variants->push_back("etc");
+ //_save_stex(image,p_save_path+".etc2.stex",compress_mode,lossy,Image::COMPRESS_ETC2,mipmaps,tex_flags,stream);
+ //r_platform_variants->push_back("etc2");
+ _save_stex(image,p_save_path+".s3tc.stex",compress_mode,lossy,Image::COMPRESS_S3TC,mipmaps,tex_flags,stream,detect_3d,detect_srgb);
+ r_platform_variants->push_back("s3tc");
+
+ } else {
+ //import normally
+ _save_stex(image,p_save_path+".stex",compress_mode,lossy,Image::COMPRESS_16BIT /*this is ignored */,mipmaps,tex_flags,stream,detect_3d,detect_srgb);
+ }
+
+ return OK;
+}
+
+ResourceImporterTexture *ResourceImporterTexture::singleton=NULL;
+
+ResourceImporterTexture::ResourceImporterTexture()
+{
+
+ singleton=this;
+ StreamTexture::request_3d_callback=_texture_reimport_3d;
+ StreamTexture::request_srgb_callback=_texture_reimport_srgb;
+ mutex = Mutex::create();
+}
+
+ResourceImporterTexture::~ResourceImporterTexture()
+{
+
+ memdelete(mutex);
+}
+
diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h
new file mode 100644
index 0000000000..2667fb1601
--- /dev/null
+++ b/editor/import/resource_importer_texture.h
@@ -0,0 +1,98 @@
+/*************************************************************************/
+/* resource_importer_texture.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCEIMPORTTEXTURE_H
+#define RESOURCEIMPORTTEXTURE_H
+
+#include "io/resource_import.h"
+class StreamTexture;
+
+class ResourceImporterTexture : public ResourceImporter {
+ GDCLASS(ResourceImporterTexture,ResourceImporter)
+
+
+
+protected:
+
+ enum {
+ MAKE_3D_FLAG=1,
+ MAKE_SRGB_FLAG=2
+ };
+
+ Mutex *mutex;
+ Map<StringName,int> make_flags;
+
+ static void _texture_reimport_srgb(const Ref<StreamTexture>& p_tex);
+ static void _texture_reimport_3d(const Ref<StreamTexture>& p_tex);
+
+
+
+
+ static ResourceImporterTexture *singleton;
+public:
+
+ static ResourceImporterTexture *get_singleton() { return singleton; }
+ virtual String get_importer_name() const;
+ virtual String get_visible_name() const;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual String get_save_extension() const;
+ virtual String get_resource_type() const;
+
+
+ enum Preset {
+ PRESET_DETECT,
+ PRESET_2D,
+ PRESET_2D_PIXEL,
+ PRESET_3D,
+ };
+
+ enum CompressMode {
+ COMPRESS_LOSSLESS,
+ COMPRESS_LOSSY,
+ COMPRESS_VIDEO_RAM,
+ COMPRESS_UNCOMPRESSED
+ };
+
+ virtual int get_preset_count() const;
+ virtual String get_preset_name(int p_idx) const;
+
+ virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
+ virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
+
+ void _save_stex(const Image& p_image, const String& p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable,bool p_detect_3d,bool p_detect_srgb);
+
+ virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
+
+
+ void update_imports();
+
+ ResourceImporterTexture();
+ ~ResourceImporterTexture();
+};
+
+#endif // RESOURCEIMPORTTEXTURE_H
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
new file mode 100644
index 0000000000..684ef4dc5c
--- /dev/null
+++ b/editor/import/resource_importer_wav.cpp
@@ -0,0 +1,647 @@
+/*************************************************************************/
+/* resource_importer_wav.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_importer_wav.h"
+
+#include "scene/resources/audio_stream_sample.h"
+#include "os/file_access.h"
+#include "io/marshalls.h"
+#include "io/resource_saver.h"
+
+String ResourceImporterWAV::get_importer_name() const {
+
+ return "wav";
+}
+
+String ResourceImporterWAV::get_visible_name() const{
+
+ return "Microsoft WAV";
+}
+void ResourceImporterWAV::get_recognized_extensions(List<String> *p_extensions) const{
+
+ p_extensions->push_back("wav");
+}
+String ResourceImporterWAV::get_save_extension() const {
+ return "smp";
+}
+
+String ResourceImporterWAV::get_resource_type() const{
+
+ return "AudioStreamSample";
+}
+
+bool ResourceImporterWAV::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
+
+ return true;
+}
+
+int ResourceImporterWAV::get_preset_count() const {
+ return 0;
+}
+String ResourceImporterWAV::get_preset_name(int p_idx) const {
+
+ return String();
+}
+
+
+void ResourceImporterWAV::get_import_options(List<ImportOption> *r_options,int p_preset) const {
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/8_bit"),false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/mono"),false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/max_rate"),false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/max_rate_hz",PROPERTY_HINT_EXP_RANGE,"11025,192000,1"),44100));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/trim"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/normalize"),true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/loop"),false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)"),0));
+
+}
+
+
+Error ResourceImporterWAV::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
+
+ /* STEP 1, READ WAVE FILE */
+
+ Error err;
+ FileAccess *file=FileAccess::open(p_source_file, FileAccess::READ,&err);
+
+ ERR_FAIL_COND_V( err!=OK, ERR_CANT_OPEN );
+
+ /* CHECK RIFF */
+ char riff[5];
+ riff[4]=0;
+ file->get_buffer((uint8_t*)&riff,4); //RIFF
+
+ if (riff[0]!='R' || riff[1]!='I' || riff[2]!='F' || riff[3]!='F') {
+
+ file->close();
+ memdelete(file);
+ ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
+ }
+
+
+ /* GET FILESIZE */
+ uint32_t filesize=file->get_32();
+
+ /* CHECK WAVE */
+
+ char wave[4];
+
+ file->get_buffer((uint8_t*)&wave,4); //RIFF
+
+ if (wave[0]!='W' || wave[1]!='A' || wave[2]!='V' || wave[3]!='E') {
+
+
+ file->close();
+ memdelete(file);
+ ERR_EXPLAIN("Not a WAV file (no WAVE RIFF Header)")
+ ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
+ }
+
+ int format_bits=0;
+ int format_channels=0;
+
+ AudioStreamSample::LoopMode loop=AudioStreamSample::LOOP_DISABLED;
+ bool format_found=false;
+ bool data_found=false;
+ int format_freq=0;
+ int loop_begin=0;
+ int loop_end=0;
+ int frames;
+
+ Vector<float> data;
+
+ while (!file->eof_reached()) {
+
+
+ /* chunk */
+ char chunkID[4];
+ file->get_buffer((uint8_t*)&chunkID,4); //RIFF
+
+ /* chunk size */
+ uint32_t chunksize=file->get_32();
+ uint32_t file_pos=file->get_pos(); //save file pos, so we can skip to next chunk safely
+
+ if (file->eof_reached()) {
+
+ //ERR_PRINT("EOF REACH");
+ break;
+ }
+
+ if (chunkID[0]=='f' && chunkID[1]=='m' && chunkID[2]=='t' && chunkID[3]==' ' && !format_found) {
+ /* IS FORMAT CHUNK */
+
+ uint16_t compression_code=file->get_16();
+
+
+ if (compression_code!=1) {
+ ERR_PRINT("Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM instead.");
+ break;
+ }
+
+ format_channels=file->get_16();
+ if (format_channels!=1 && format_channels !=2) {
+
+ ERR_PRINT("Format not supported for WAVE file (not stereo or mono)");
+ break;
+
+ }
+
+ format_freq=file->get_32(); //sampling rate
+
+ file->get_32(); // average bits/second (unused)
+ file->get_16(); // block align (unused)
+ format_bits=file->get_16(); // bits per sample
+
+ if (format_bits%8) {
+
+ ERR_PRINT("Strange number of bits in sample (not 8,16,24,32)");
+ break;
+ }
+
+ /* Dont need anything else, continue */
+ format_found=true;
+ }
+
+
+ if (chunkID[0]=='d' && chunkID[1]=='a' && chunkID[2]=='t' && chunkID[3]=='a' && !data_found) {
+ /* IS FORMAT CHUNK */
+ data_found=true;
+
+ if (!format_found) {
+ ERR_PRINT("'data' chunk before 'format' chunk found.");
+ break;
+
+ }
+
+ frames=chunksize;
+
+ frames/=format_channels;
+ frames/=(format_bits>>3);
+
+ /*print_line("chunksize: "+itos(chunksize));
+ print_line("channels: "+itos(format_channels));
+ print_line("bits: "+itos(format_bits));
+*/
+
+ int len=frames;
+ if (format_channels==2)
+ len*=2;
+ if (format_bits>8)
+ len*=2;
+
+
+ data.resize(frames*format_channels);
+
+ for (int i=0;i<frames;i++) {
+
+
+ for (int c=0;c<format_channels;c++) {
+
+
+ if (format_bits==8) {
+ // 8 bit samples are UNSIGNED
+
+ uint8_t s = file->get_8();
+ s-=128;
+ int8_t *sp=(int8_t*)&s;
+
+ data[i*format_channels+c]=float(*sp)/128.0;
+
+ } else {
+ //16+ bits samples are SIGNED
+ // if sample is > 16 bits, just read extra bytes
+
+ uint32_t s=0;
+ for (int b=0;b<(format_bits>>3);b++) {
+
+ s|=((uint32_t)file->get_8())<<(b*8);
+ }
+ s<<=(32-format_bits);
+ int32_t ss=s;
+
+
+ data[i*format_channels+c]=(ss>>16)/32768.0;
+ }
+ }
+
+ }
+
+
+
+ if (file->eof_reached()) {
+ file->close();
+ memdelete(file);
+ ERR_EXPLAIN("Premature end of file.");
+ ERR_FAIL_V(ERR_FILE_CORRUPT);
+ }
+ }
+
+ if (chunkID[0]=='s' && chunkID[1]=='m' && chunkID[2]=='p' && chunkID[3]=='l') {
+ //loop point info!
+
+ for(int i=0;i<10;i++)
+ file->get_32(); // i wish to know why should i do this... no doc!
+
+ loop=file->get_32()?AudioStreamSample::LOOP_PING_PONG:AudioStreamSample::LOOP_FORWARD;
+ loop_begin=file->get_32();
+ loop_end=file->get_32();
+
+ }
+ file->seek( file_pos+chunksize );
+ }
+
+ file->close();
+ memdelete(file);
+
+ // STEP 2, APPLY CONVERSIONS
+
+
+ bool is16=format_bits!=8;
+ int rate=format_freq;
+
+ print_line("Input Sample: ");
+ print_line("\tframes: "+itos(frames));
+ print_line("\tformat_channels: "+itos(format_channels));
+ print_line("\t16bits: "+itos(is16));
+ print_line("\trate: "+itos(rate));
+ print_line("\tloop: "+itos(loop));
+ print_line("\tloop begin: "+itos(loop_begin));
+ print_line("\tloop end: "+itos(loop_end));
+
+
+ //apply frequency limit
+
+ bool limit_rate = p_options["force/max_rate"];
+ int limit_rate_hz = p_options["force/max_rate_hz"];
+ if (limit_rate && rate > limit_rate_hz) {
+ //resampleeee!!!
+ int new_data_frames = frames * limit_rate_hz / rate;
+ Vector<float> new_data;
+ new_data.resize( new_data_frames * format_channels );
+ for(int c=0;c<format_channels;c++) {
+
+ for(int i=0;i<new_data_frames;i++) {
+
+ //simple cubic interpolation should be enough.
+ float pos = float(i) * frames / new_data_frames;
+ float mu = pos-Math::floor(pos);
+ int ipos = int(Math::floor(pos));
+
+ float y0=data[MAX(0,ipos-1)*format_channels+c];
+ float y1=data[ipos*format_channels+c];
+ float y2=data[MIN(frames-1,ipos+1)*format_channels+c];
+ float y3=data[MIN(frames-1,ipos+2)*format_channels+c];
+
+ float mu2 = mu*mu;
+ float a0 = y3 - y2 - y0 + y1;
+ float a1 = y0 - y1 - a0;
+ float a2 = y2 - y0;
+ float a3 = y1;
+
+ float res=(a0*mu*mu2+a1*mu2+a2*mu+a3);
+
+ new_data[i*format_channels+c]=res;
+ }
+ }
+
+ if (loop) {
+
+ loop_begin=loop_begin*new_data_frames/frames;
+ loop_end=loop_end*new_data_frames/frames;
+ }
+ data=new_data;
+ rate=limit_rate_hz;
+ frames=new_data_frames;
+ }
+
+
+ bool normalize = p_options["edit/normalize"];
+
+ if (normalize) {
+
+ float max=0;
+ for(int i=0;i<data.size();i++) {
+
+ float amp = Math::abs(data[i]);
+ if (amp>max)
+ max=amp;
+ }
+
+ if (max>0) {
+
+ float mult=1.0/max;
+ for(int i=0;i<data.size();i++) {
+
+ data[i]*=mult;
+ }
+
+ }
+ }
+
+ bool trim = p_options["edit/trim"];
+
+ if (trim && !loop) {
+
+ int first=0;
+ int last=(frames*format_channels)-1;
+ bool found=false;
+ float limit = Math::db2linear((float)-30);
+ for(int i=0;i<data.size();i++) {
+ float amp = Math::abs(data[i]);
+
+ if (!found && amp > limit) {
+ first=i;
+ found=true;
+ }
+
+ if (found && amp > limit) {
+ last=i;
+ }
+ }
+
+ first/=format_channels;
+ last/=format_channels;
+
+ if (first<last) {
+
+ Vector<float> new_data;
+ new_data.resize((last-first+1)*format_channels);
+ for(int i=first*format_channels;i<=last*format_channels;i++) {
+ new_data[i-first*format_channels]=data[i];
+ }
+
+ data=new_data;
+ frames=data.size()/format_channels;
+ }
+
+ }
+
+ bool make_loop = p_options["edit/loop"];
+
+ if (make_loop && !loop) {
+
+ loop=AudioStreamSample::LOOP_FORWARD;
+ loop_begin=0;
+ loop_end=frames;
+ }
+
+ int compression = p_options["compress/mode"];
+ bool force_mono = p_options["force/mono"];
+
+
+ if (force_mono && format_channels==2) {
+
+ Vector<float> new_data;
+ new_data.resize(data.size()/2);
+ for(int i=0;i<frames;i++) {
+ new_data[i]=(data[i*2+0]+data[i*2+1])/2.0;
+ }
+
+ data=new_data;
+ format_channels=1;
+ }
+
+ bool force_8_bit = p_options["force/8_bit"];
+ if (force_8_bit) {
+
+ is16=false;
+ }
+
+
+ PoolVector<uint8_t> dst_data;
+ AudioStreamSample::Format dst_format;
+
+ if ( compression == 1) {
+
+ dst_format=AudioStreamSample::FORMAT_IMA_ADPCM;
+ if (format_channels==1) {
+ _compress_ima_adpcm(data,dst_data);
+ } else {
+
+ //byte interleave
+ Vector<float> left;
+ Vector<float> right;
+
+ int tframes = data.size()/2;
+ left.resize(tframes);
+ right.resize(tframes);
+
+ for(int i=0;i<tframes;i++) {
+ left[i]=data[i*2+0];
+ right[i]=data[i*2+1];
+ }
+
+ PoolVector<uint8_t> bleft;
+ PoolVector<uint8_t> bright;
+
+ _compress_ima_adpcm(left,bleft);
+ _compress_ima_adpcm(right,bright);
+
+ int dl = bleft.size();
+ dst_data.resize( dl *2 );
+
+ PoolVector<uint8_t>::Write w=dst_data.write();
+ PoolVector<uint8_t>::Read rl=bleft.read();
+ PoolVector<uint8_t>::Read rr=bright.read();
+
+ for(int i=0;i<dl;i++) {
+ w[i*2+0]=rl[i];
+ w[i*2+1]=rr[i];
+ }
+ }
+
+ //print_line("compressing ima-adpcm, resulting buffersize is "+itos(dst_data.size())+" from "+itos(data.size()));
+
+ } else {
+
+ dst_format=is16?AudioStreamSample::FORMAT_16_BITS:AudioStreamSample::FORMAT_8_BITS;
+ dst_data.resize( data.size() * (is16?2:1));
+ {
+ PoolVector<uint8_t>::Write w = dst_data.write();
+
+ int ds=data.size();
+ for(int i=0;i<ds;i++) {
+
+ if (is16) {
+ int16_t v = CLAMP(data[i]*32768,-32768,32767);
+ encode_uint16(v,&w[i*2]);
+ } else {
+ int8_t v = CLAMP(data[i]*128,-128,127);
+ w[i]=v;
+ }
+ }
+ }
+ }
+
+
+ Ref<AudioStreamSample> sample;
+ sample.instance();
+ sample->set_data(dst_data);
+ sample->set_format(dst_format);
+ sample->set_mix_rate(rate);
+ sample->set_loop_mode(loop);
+ sample->set_loop_begin(loop_begin);
+ sample->set_loop_end(loop_end);
+ sample->set_stereo(format_channels==2);
+
+ ResourceSaver::save(p_save_path+".smp",sample);
+
+
+ return OK;
+
+}
+
+void ResourceImporterWAV::_compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data) {
+
+
+ /*p_sample_data->data = (void*)malloc(len);
+ xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/
+
+ static const int16_t _ima_adpcm_step_table[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+ };
+
+ static const int8_t _ima_adpcm_index_table[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+ };
+
+
+ int datalen = p_data.size();
+ int datamax=datalen;
+ if (datalen&1)
+ datalen++;
+
+ dst_data.resize(datalen/2+4);
+ PoolVector<uint8_t>::Write w = dst_data.write();
+
+
+ int i,step_idx=0,prev=0;
+ uint8_t *out = w.ptr();
+ //int16_t xm_prev=0;
+ const float *in=p_data.ptr();
+
+
+ /* initial value is zero */
+ *(out++) =0;
+ *(out++) =0;
+ /* Table index initial value */
+ *(out++) =0;
+ /* unused */
+ *(out++) =0;
+
+ for (i=0;i<datalen;i++) {
+ int step,diff,vpdiff,mask;
+ uint8_t nibble;
+ int16_t xm_sample;
+
+ if (i>=datamax)
+ xm_sample=0;
+ else {
+
+
+ xm_sample=CLAMP(in[i]*32767.0,-32768,32767);
+ /*
+ if (xm_sample==32767 || xm_sample==-32768)
+ printf("clippy!\n",xm_sample);
+ */
+ }
+
+ //xm_sample=xm_sample+xm_prev;
+ //xm_prev=xm_sample;
+
+ diff = (int)xm_sample - prev ;
+
+ nibble=0 ;
+ step = _ima_adpcm_step_table[ step_idx ];
+ vpdiff = step >> 3 ;
+ if (diff < 0) {
+ nibble=8;
+ diff=-diff ;
+ }
+ mask = 4 ;
+ while (mask) {
+
+ if (diff >= step) {
+
+ nibble |= mask;
+ diff -= step;
+ vpdiff += step;
+ }
+
+ step >>= 1 ;
+ mask >>= 1 ;
+ };
+
+ if (nibble&8)
+ prev-=vpdiff ;
+ else
+ prev+=vpdiff ;
+
+ if (prev > 32767) {
+ //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev);
+ prev=32767;
+ } else if (prev < -32768) {
+ //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev);
+ prev = -32768 ;
+ }
+
+ step_idx += _ima_adpcm_index_table[nibble];
+ if (step_idx< 0)
+ step_idx= 0 ;
+ else if (step_idx> 88)
+ step_idx= 88 ;
+
+
+ if (i&1) {
+ *out|=nibble<<4;
+ out++;
+ } else {
+ *out=nibble;
+ }
+ /*dataptr[i]=prev>>8;*/
+ }
+
+
+
+
+}
+
+ResourceImporterWAV::ResourceImporterWAV()
+{
+
+}
diff --git a/editor/import/resource_importer_wav.h b/editor/import/resource_importer_wav.h
new file mode 100644
index 0000000000..bc93799fee
--- /dev/null
+++ b/editor/import/resource_importer_wav.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* resource_importer_wav.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCEIMPORTWAV_H
+#define RESOURCEIMPORTWAV_H
+
+
+#include "io/resource_import.h"
+
+class ResourceImporterWAV : public ResourceImporter {
+ GDCLASS(ResourceImporterWAV,ResourceImporter)
+public:
+ virtual String get_importer_name() const;
+ virtual String get_visible_name() const;
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual String get_save_extension() const;
+ virtual String get_resource_type() const;
+
+
+ virtual int get_preset_count() const;
+ virtual String get_preset_name(int p_idx) const;
+
+ virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
+ virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
+
+ void _compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data);
+
+ virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
+
+ ResourceImporterWAV();
+};
+
+#endif // RESOURCEIMPORTWAV_H
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
new file mode 100644
index 0000000000..910274a13e
--- /dev/null
+++ b/editor/import_dock.cpp
@@ -0,0 +1,359 @@
+/*************************************************************************/
+/* import_dock.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "import_dock.h"
+
+class ImportDockParameters : public Object {
+ GDCLASS(ImportDockParameters,Object)
+public:
+ Map<StringName,Variant> values;
+ List<PropertyInfo> properties;
+ Ref<ResourceImporter> importer;
+ Vector<String> paths;
+
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ if (values.has(p_name)) {
+ values[p_name]=p_value;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const {
+
+ if (values.has(p_name)) {
+ r_ret=values[p_name];
+ return true;
+ }
+
+ return false;
+
+ }
+ void _get_property_list( List<PropertyInfo> *p_list) const {
+
+ for (const List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
+ if (!importer->get_option_visibility(E->get().name,values))
+ continue;
+ p_list->push_back(E->get());
+ }
+ }
+
+ void update() {
+ _change_notify();
+ }
+};
+
+void ImportDock::set_edit_path(const String& p_path) {
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(p_path+".import");
+ if (err!=OK) {
+ clear();
+ return;
+ }
+
+
+ params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer"));
+ if (params->importer.is_null()) {
+ clear();
+ return;
+ }
+
+ List<ResourceImporter::ImportOption> options;
+ params->importer->get_import_options(&options);
+
+ params->properties.clear();
+ params->values.clear();
+
+ for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
+
+ params->properties.push_back(E->get().option);
+ if (config->has_section_key("params",E->get().option.name)) {
+ params->values[E->get().option.name]=config->get_value("params",E->get().option.name);
+ } else {
+ params->values[E->get().option.name]=E->get().default_value;
+ }
+ }
+
+ params->update();
+
+ List<Ref<ResourceImporter> > importers;
+ ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(),&importers);
+ List<Pair<String,String> > importer_names;
+
+ for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) {
+ importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name()));
+ }
+
+ importer_names.sort_custom<PairSort<String,String> >();
+
+ import_as->clear();
+
+ for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) {
+ import_as->add_item(E->get().first);
+ import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second);
+ if (E->get().second==params->importer->get_importer_name()) {
+ import_as->select(import_as->get_item_count()-1);
+ }
+ }
+
+ preset->get_popup()->clear();
+
+ if (params->importer->get_preset_count()==0) {
+ preset->get_popup()->add_item(TTR("Default"));
+ } else {
+ for (int i=0;i<params->importer->get_preset_count();i++) {
+ preset->get_popup()->add_item(params->importer->get_preset_name(i));
+ }
+ }
+
+ params->paths.clear();
+ params->paths.push_back(p_path);
+ import->set_disabled(false);
+ import_as->set_disabled(false);
+
+ imported->set_text(p_path.get_file());
+}
+
+void ImportDock::set_edit_multiple_paths(const Vector<String>& p_paths) {
+
+ clear();
+
+ //use the value that is repeated the mot
+ Map<String,Dictionary> value_frequency;
+
+ for(int i=0;i<p_paths.size();i++) {
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(p_paths[i]+".import");
+ ERR_CONTINUE(err!=OK);
+
+ if (i==0) {
+ params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer"));
+ if (params->importer.is_null()) {
+ clear();
+ return;
+ }
+ }
+
+ List<String> keys;
+ config->get_section_keys("params",&keys);
+
+
+ for (List<String>::Element *E=keys.front();E;E=E->next()) {
+
+ if (!value_frequency.has(E->get())) {
+ value_frequency[E->get()]=Dictionary();
+ }
+
+ Variant value = config->get_value("params",E->get());
+
+ if (value_frequency[E->get()].has(value)) {
+ value_frequency[E->get()][value]=int(value_frequency[E->get()][value])+1;
+ } else {
+ value_frequency[E->get()][value]=1;
+ }
+ }
+
+ }
+
+ ERR_FAIL_COND(params->importer.is_null());
+
+ List<ResourceImporter::ImportOption> options;
+ params->importer->get_import_options(&options);
+
+ params->properties.clear();
+ params->values.clear();
+
+ for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
+
+ params->properties.push_back(E->get().option);
+
+ if (value_frequency.has(E->get().option.name)) {
+
+ Dictionary d = value_frequency[E->get().option.name];
+ int freq=0;
+ List<Variant> v;
+ d.get_key_list(&v);
+ Variant value;
+ for (List<Variant>::Element *F=v.front();F;F=F->next()) {
+ int f = d[F->get()];
+ if (f>freq) {
+ value=F->get();
+ }
+ }
+
+ params->values[E->get().option.name]=value;
+ } else {
+ params->values[E->get().option.name]=E->get().default_value;
+ }
+ }
+
+ params->update();
+
+ List<Ref<ResourceImporter> > importers;
+ ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_paths[0].get_extension(),&importers);
+ List<Pair<String,String> > importer_names;
+
+ for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) {
+ importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name()));
+ }
+
+ importer_names.sort_custom<PairSort<String,String> >();
+
+ import_as->clear();
+
+ for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) {
+ import_as->add_item(E->get().first);
+ import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second);
+ if (E->get().second==params->importer->get_importer_name()) {
+ import_as->select(import_as->get_item_count()-1);
+ }
+ }
+
+ preset->get_popup()->clear();
+
+ if (params->importer->get_preset_count()==0) {
+ preset->get_popup()->add_item(TTR("Default"));
+ } else {
+ for (int i=0;i<params->importer->get_preset_count();i++) {
+ preset->get_popup()->add_item(params->importer->get_preset_name(i));
+ }
+ }
+
+ params->paths=p_paths;
+ import->set_disabled(false);
+ import_as->set_disabled(false);
+
+ imported->set_text(itos(p_paths.size())+TTR(" Files"));
+}
+
+void ImportDock::_preset_selected(int p_idx) {
+
+ print_line("preset selected? "+p_idx);
+ List<ResourceImporter::ImportOption> options;
+
+ params->importer->get_import_options(&options,p_idx);
+
+ for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
+
+ params->values[E->get().option.name]=E->get().default_value;
+ }
+
+ params->update();
+
+}
+
+
+void ImportDock::clear() {
+
+ imported->set_text("");
+ import->set_disabled(true);
+ import_as->clear();
+ import_as->set_disabled(true);
+ params->values.clear();
+ params->properties.clear();
+ params->update();
+ preset->get_popup()->clear();
+
+}
+
+void ImportDock::_reimport() {
+
+ for(int i=0;i<params->paths.size();i++) {
+
+ Ref<ConfigFile> config;
+ config.instance();
+ Error err = config->load(params->paths[i]+".import");
+ ERR_CONTINUE(err!=OK);
+
+ config->erase_section("params");
+
+ for (List<PropertyInfo>::Element *E=params->properties.front();E;E=E->next()) {
+ config->set_value("params",E->get().name,params->values[E->get().name]);
+ }
+
+ config->save(params->paths[i]+".import");
+ }
+
+ EditorFileSystem::get_singleton()->reimport_files(params->paths);
+ EditorFileSystem::get_singleton()->emit_signal("filesystem_changed"); //it changed, so force emitting the signal
+
+}
+
+void ImportDock::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_reimport"),&ImportDock::_reimport);
+ ClassDB::bind_method(D_METHOD("_preset_selected"),&ImportDock::_preset_selected);
+}
+
+ImportDock::ImportDock() {
+
+
+ imported = memnew( LineEdit );
+ imported->set_editable(false);
+ add_child(imported);
+ HBoxContainer *hb = memnew(HBoxContainer);
+ add_margin_child(TTR("Import As:"),hb);
+ import_as = memnew( OptionButton );
+ hb->add_child(import_as);
+ import_as->set_h_size_flags(SIZE_EXPAND_FILL);
+ preset = memnew( MenuButton );
+ preset->set_text(TTR("Preset.."));
+ preset->get_popup()->connect("index_pressed",this,"_preset_selected");
+ hb->add_child(preset);
+
+ import_opts = memnew( PropertyEditor );
+ add_child(import_opts);
+ import_opts->set_v_size_flags(SIZE_EXPAND_FILL);
+ import_opts->hide_top_label();
+ import_opts->set_hide_script(true);
+
+ hb = memnew( HBoxContainer );
+ add_child(hb);
+ import = memnew( Button );
+ import->set_text(TTR("Reimport"));
+ import->connect("pressed",this,"_reimport");
+ hb->add_spacer();
+ hb->add_child(import);
+ hb->add_spacer();
+
+ params = memnew( ImportDockParameters );
+ import_opts->edit(params);
+
+}
+
+ImportDock::~ImportDock() {
+
+ memdelete(params);
+}
diff --git a/editor/import_dock.h b/editor/import_dock.h
new file mode 100644
index 0000000000..0153955d32
--- /dev/null
+++ b/editor/import_dock.h
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* import_dock.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 IMPORTDOCK_H
+#define IMPORTDOCK_H
+
+#include "io/resource_import.h"
+#include "editor_file_system.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/popup_menu.h"
+#include "property_editor.h"
+
+class ImportDockParameters;
+class ImportDock : public VBoxContainer {
+ GDCLASS(ImportDock,VBoxContainer)
+
+ LineEdit *imported;
+ OptionButton *import_as;
+ MenuButton *preset;
+ PropertyEditor *import_opts;
+
+ List<PropertyInfo> properties;
+ Map<StringName,Variant> property_values;
+
+ Button *import;
+
+ ImportDockParameters *params;
+
+ void _preset_selected(int p_idx);
+
+ void _reimport();
+protected:
+ static void _bind_methods();
+public:
+
+ void set_edit_path(const String& p_path);
+ void set_edit_multiple_paths(const Vector<String>& p_paths);
+ void clear();
+
+ ImportDock();
+ ~ImportDock();
+};
+
+#endif // IMPORTDOCK_H
diff --git a/tools/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 253f9bcc01..253f9bcc01 100644
--- a/tools/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
diff --git a/tools/editor/inspector_dock.h b/editor/inspector_dock.h
index be6ed5fa87..be6ed5fa87 100644
--- a/tools/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
diff --git a/tools/editor/io_plugins/SCsub b/editor/io_plugins/SCsub
index f1fa50148f..f1fa50148f 100644
--- a/tools/editor/io_plugins/SCsub
+++ b/editor/io_plugins/SCsub
diff --git a/tools/editor/io_plugins/editor_atlas.cpp b/editor/io_plugins/editor_atlas.cpp
index c5f1ee73cf..c5f1ee73cf 100644
--- a/tools/editor/io_plugins/editor_atlas.cpp
+++ b/editor/io_plugins/editor_atlas.cpp
diff --git a/tools/editor/io_plugins/editor_atlas.h b/editor/io_plugins/editor_atlas.h
index e0cf76576e..e0cf76576e 100644
--- a/tools/editor/io_plugins/editor_atlas.h
+++ b/editor/io_plugins/editor_atlas.h
diff --git a/editor/io_plugins/editor_bitmask_import_plugin.cpp b/editor/io_plugins/editor_bitmask_import_plugin.cpp
new file mode 100644
index 0000000000..7282cbe4e7
--- /dev/null
+++ b/editor/io_plugins/editor_bitmask_import_plugin.cpp
@@ -0,0 +1,387 @@
+/*************************************************************************/
+/* editor_bitmask_import_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_bitmask_import_plugin.h"
+#if 0
+#include "io/image_loader.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_dir_dialog.h"
+#include "editor/editor_node.h"
+#include "editor/property_editor.h"
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "io/marshalls.h"
+#include "editor/editor_settings.h"
+
+class _EditorBitMaskImportOptions : public Object {
+
+ GDCLASS(_EditorBitMaskImportOptions, Object);
+public:
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ return false;
+ }
+
+ bool _get(const StringName& p_name, Variant &r_ret) const{
+
+ return false;
+ }
+
+ void _get_property_list(List<PropertyInfo> *p_list) const{
+
+ }
+
+ static void _bind_methods() {
+
+ ADD_SIGNAL(MethodInfo("changed"));
+ }
+
+
+ _EditorBitMaskImportOptions() {
+
+ }
+
+};
+
+class EditorBitMaskImportDialog : public ConfirmationDialog {
+
+ GDCLASS(EditorBitMaskImportDialog, ConfirmationDialog);
+
+ EditorBitMaskImportPlugin *plugin;
+
+ LineEdit *import_path;
+ LineEdit *save_path;
+ EditorFileDialog *file_select;
+ EditorDirDialog *save_select;
+ ConfirmationDialog *error_dialog;
+ PropertyEditor *option_editor;
+
+public:
+
+ void _choose_files(const Vector<String>& p_path) {
+
+ String files;
+ for (int i = 0; i<p_path.size(); i++) {
+
+ if (i>0)
+ files += ",";
+ files += p_path[i];
+ }
+
+ import_path->set_text(files);
+
+ }
+ void _choose_save_dir(const String& p_path) {
+
+ save_path->set_text(p_path);
+ }
+
+ void _browse() {
+
+ file_select->popup_centered_ratio();
+ }
+
+ void _browse_target() {
+
+ save_select->popup_centered_ratio();
+
+ }
+
+
+ void popup_import(const String& p_path) {
+
+ popup_centered(Size2(400, 100)*EDSCALE);
+ if (p_path != "") {
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+ ERR_FAIL_COND(!rimd.is_valid());
+
+ save_path->set_text(p_path.get_base_dir());
+
+ String src = "";
+ for (int i = 0; i<rimd->get_source_count(); i++) {
+ if (i>0)
+ src += ",";
+ src += EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
+ }
+ import_path->set_text(src);
+ }
+ }
+
+
+ void _import() {
+
+ Vector<String> bitmasks = import_path->get_text().split(",");
+
+ if (bitmasks.size() == 0) {
+ error_dialog->set_text(TTR("No bit masks to import!"));
+ error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
+ }
+
+ if (save_path->get_text().strip_edges() == "") {
+ error_dialog->set_text(TTR("Target path is empty."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (!save_path->get_text().begins_with("res://")) {
+ error_dialog->set_text(TTR("Target path must be a complete resource path."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (!DirAccess::exists(save_path->get_text())) {
+ error_dialog->set_text(TTR("Target path must exist."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ for (int i = 0; i<bitmasks.size(); i++) {
+
+ Ref<ResourceImportMetadata> imd = memnew(ResourceImportMetadata);
+
+ imd->add_source(EditorImportPlugin::validate_source_path(bitmasks[i]));
+
+ String dst = save_path->get_text();
+ if (dst == "") {
+ error_dialog->set_text(TTR("Save path is empty!"));
+ error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
+ }
+
+ dst = dst.plus_file(bitmasks[i].get_file().get_basename() + ".pbm");
+
+ plugin->import(dst, imd);
+ }
+
+ hide();
+
+ }
+
+
+ void _notification(int p_what) {
+
+ }
+
+ static void _bind_methods() {
+
+
+ ClassDB::bind_method("_choose_files", &EditorBitMaskImportDialog::_choose_files);
+ ClassDB::bind_method("_choose_save_dir", &EditorBitMaskImportDialog::_choose_save_dir);
+ ClassDB::bind_method("_import", &EditorBitMaskImportDialog::_import);
+ ClassDB::bind_method("_browse", &EditorBitMaskImportDialog::_browse);
+ ClassDB::bind_method("_browse_target", &EditorBitMaskImportDialog::_browse_target);
+ //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
+ }
+
+ EditorBitMaskImportDialog(EditorBitMaskImportPlugin *p_plugin) {
+
+ plugin = p_plugin;
+
+
+ set_title(TTR("Import BitMasks"));
+
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ add_child(vbc);
+ //set_child_rect(vbc);
+
+
+ HBoxContainer *hbc = memnew(HBoxContainer);
+ vbc->add_margin_child(TTR("Source Texture(s):"), hbc);
+
+ import_path = memnew(LineEdit);
+ import_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(import_path);
+
+ Button * import_choose = memnew(Button);
+ import_choose->set_text(" .. ");
+ hbc->add_child(import_choose);
+
+ import_choose->connect("pressed", this, "_browse");
+
+ hbc = memnew(HBoxContainer);
+ vbc->add_margin_child(TTR("Target Path:"), hbc);
+
+ save_path = memnew(LineEdit);
+ save_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(save_path);
+
+ Button * save_choose = memnew(Button);
+ save_choose->set_text(" .. ");
+ hbc->add_child(save_choose);
+
+ save_choose->connect("pressed", this, "_browse_target");
+
+ file_select = memnew(EditorFileDialog);
+ file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ add_child(file_select);
+ file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+ file_select->connect("files_selected", this, "_choose_files");
+
+ List<String> extensions;
+ ImageLoader::get_recognized_extensions(&extensions);
+ file_select->clear_filters();
+ for (int i = 0; i<extensions.size(); i++) {
+
+ file_select->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ }
+
+ save_select = memnew(EditorDirDialog);
+ add_child(save_select);
+
+ //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
+ save_select->connect("dir_selected", this, "_choose_save_dir");
+
+ get_ok()->connect("pressed", this, "_import");
+ get_ok()->set_text(TTR("Import"));
+
+
+ error_dialog = memnew(ConfirmationDialog);
+ add_child(error_dialog);
+ error_dialog->get_ok()->set_text(TTR("Accept"));
+ //error_dialog->get_cancel()->hide();
+
+ set_hide_on_ok(false);
+ }
+
+ ~EditorBitMaskImportDialog() {
+ }
+
+};
+
+
+String EditorBitMaskImportPlugin::get_name() const {
+
+ return "bitmask";
+}
+String EditorBitMaskImportPlugin::get_visible_name() const{
+
+ return TTR("Bit Mask");
+}
+void EditorBitMaskImportPlugin::import_dialog(const String& p_from){
+
+ dialog->popup_import(p_from);
+}
+Error EditorBitMaskImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
+
+ ERR_FAIL_COND_V(p_from->get_source_count() != 1, ERR_INVALID_PARAMETER);
+
+ Ref<ResourceImportMetadata> from = p_from;
+
+ String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
+ Ref<ImageTexture> it = ResourceLoader::load(src_path);
+ ERR_FAIL_COND_V(it.is_null(), ERR_CANT_OPEN);
+
+ Ref<BitMap> target = memnew(BitMap);
+ target->create_from_image_alpha(it.ptr()->get_data());
+
+ from->set_source_md5(0, FileAccess::get_md5(src_path));
+ from->set_editor(get_name());
+ target->set_import_metadata(from);
+
+
+ Error err = ResourceSaver::save(p_path, target);
+
+ return err;
+
+}
+
+
+EditorBitMaskImportPlugin* EditorBitMaskImportPlugin::singleton = NULL;
+
+
+void EditorBitMaskImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
+
+ Vector<String> files;
+
+ List<String> valid_extensions;
+ ImageLoader::get_recognized_extensions(&valid_extensions);
+ for(int i=0;i<p_drop.size();i++) {
+
+ String extension=p_drop[i].get_extension().to_lower();
+
+ for (List<String>::Element *E=valid_extensions.front();E;E=E->next()) {
+
+ if (E->get()==extension) {
+ files.push_back(p_drop[i]);
+ break;
+ }
+ }
+ }
+
+ if (files.size()) {
+ import_dialog();
+ dialog->_choose_files(files);
+ dialog->_choose_save_dir(p_dest_path);
+ }
+}
+
+void EditorBitMaskImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
+
+ if (p_list.size() == 0)
+ return;
+
+ Vector<String> sources;
+ for (int i = 0; i<p_list.size(); i++) {
+ int idx;
+ EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i], &idx);
+ if (efsd) {
+ for (int j = 0; j<efsd->get_source_count(idx); j++) {
+ String file = expand_source_path(efsd->get_source_file(idx, j));
+ if (sources.find(file) == -1) {
+ sources.push_back(file);
+ }
+
+ }
+ }
+ }
+
+ if (sources.size()) {
+
+ dialog->popup_import(p_list[0]);
+ dialog->_choose_files(sources);
+ dialog->_choose_save_dir(p_list[0].get_base_dir());
+ }
+}
+
+bool EditorBitMaskImportPlugin::can_reimport_multiple_files() const {
+
+ return true;
+}
+
+EditorBitMaskImportPlugin::EditorBitMaskImportPlugin(EditorNode* p_editor) {
+
+ singleton = this;
+ dialog = memnew(EditorBitMaskImportDialog(this));
+ p_editor->get_gui_base()->add_child(dialog);
+}
+
+EditorBitMaskExportPlugin::EditorBitMaskExportPlugin() {
+
+}
+#endif
diff --git a/editor/io_plugins/editor_bitmask_import_plugin.h b/editor/io_plugins/editor_bitmask_import_plugin.h
new file mode 100644
index 0000000000..d1618d7843
--- /dev/null
+++ b/editor/io_plugins/editor_bitmask_import_plugin.h
@@ -0,0 +1,70 @@
+/*************************************************************************/
+/* editor_bitmask_import_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_BITMASK_IMPORT_PLUGIN_H
+#define EDITOR_BITMASK_IMPORT_PLUGIN_H
+#if 0
+#include "editor/editor_import_export.h"
+#include "scene/resources/font.h"
+
+class EditorNode;
+class EditorBitMaskImportDialog;
+
+class EditorBitMaskImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorBitMaskImportPlugin, EditorImportPlugin);
+
+ EditorBitMaskImportDialog *dialog;
+public:
+
+ static EditorBitMaskImportPlugin *singleton;
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from = "");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+ void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
+ virtual void reimport_multiple_files(const Vector<String>& p_list);
+ virtual bool can_reimport_multiple_files() const;
+
+
+ EditorBitMaskImportPlugin(EditorNode* p_editor);
+};
+
+class EditorBitMaskExportPlugin : public EditorExportPlugin {
+
+ GDCLASS(EditorBitMaskExportPlugin, EditorExportPlugin);
+
+
+public:
+
+ EditorBitMaskExportPlugin();
+};
+
+#endif
+#endif // EDITOR_SAMPLE_IMPORT_PLUGIN_H
diff --git a/editor/io_plugins/editor_export_scene.cpp b/editor/io_plugins/editor_export_scene.cpp
new file mode 100644
index 0000000000..a593b870f9
--- /dev/null
+++ b/editor/io_plugins/editor_export_scene.cpp
@@ -0,0 +1,142 @@
+/*************************************************************************/
+/* editor_export_scene.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_export_scene.h"
+#if 0
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+#include "scene/resources/packed_scene.h"
+#include "global_config.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.get_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 = GlobalConfig::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()
+{
+}
+#endif
diff --git a/editor/io_plugins/editor_export_scene.h b/editor/io_plugins/editor_export_scene.h
new file mode 100644
index 0000000000..ac425fbedd
--- /dev/null
+++ b/editor/io_plugins/editor_export_scene.h
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* editor_export_scene.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_EXPORT_SCENE_H
+#define EDITOR_EXPORT_SCENE_H
+
+#include "editor/editor_export.h"
+
+#if 0
+class EditorSceneExportPlugin : public EditorExportPlugin {
+ GDCLASS( EditorSceneExportPlugin, EditorExportPlugin );
+public:
+
+ virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
+
+ EditorSceneExportPlugin();
+};
+#endif
+#endif // EDITOR_EXPORT_SCENE_H
diff --git a/editor/io_plugins/editor_font_import_plugin.cpp b/editor/io_plugins/editor_font_import_plugin.cpp
new file mode 100644
index 0000000000..c792ad717a
--- /dev/null
+++ b/editor/io_plugins/editor_font_import_plugin.cpp
@@ -0,0 +1,1704 @@
+/*************************************************************************/
+/* editor_font_import_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_font_import_plugin.h"
+#if 0
+#include "scene/gui/dialogs.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_node.h"
+#include "os/file_access.h"
+#include "editor_atlas.h"
+#include "io/image_loader.h"
+#include "io/resource_saver.h"
+
+#ifdef FREETYPE_ENABLED
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#endif
+
+
+class _EditorFontImportOptions : public Object {
+
+ GDCLASS(_EditorFontImportOptions,Object);
+public:
+
+ enum FontMode {
+
+ FONT_BITMAP,
+ FONT_DISTANCE_FIELD
+ };
+
+ enum ColorType {
+ COLOR_WHITE,
+ COLOR_CUSTOM,
+ COLOR_GRADIENT_RANGE,
+ COLOR_GRADIENT_IMAGE
+ };
+
+
+ int char_extra_spacing;
+ int top_extra_spacing;
+ int bottom_extra_spacing;
+ int space_extra_spacing;
+
+ enum CharacterSet {
+
+ CHARSET_ASCII,
+ CHARSET_LATIN,
+ CHARSET_UNICODE,
+ CHARSET_CUSTOM,
+ CHARSET_CUSTOM_LATIN
+ };
+
+
+ FontMode font_mode;
+
+ CharacterSet character_set;
+ String custom_file;
+
+ bool shadow;
+ Vector2 shadow_offset;
+ int shadow_radius;
+ Color shadow_color;
+ float shadow_transition;
+
+ bool shadow2;
+ Vector2 shadow2_offset;
+ int shadow2_radius;
+ Color shadow2_color;
+ float shadow2_transition;
+
+ ColorType color_type;
+ Color color;
+ Color gradient_begin;
+ Color gradient_end;
+ bool color_use_monochrome;
+ String gradient_image;
+
+ bool enable_filter;
+ bool round_advance;
+ bool premultiply_alpha;
+
+
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ String n = p_name;
+ if (n=="mode/mode") {
+ font_mode=FontMode(int(p_value));
+ _change_notify();
+ } else if (n=="extra_space/char")
+ char_extra_spacing=p_value;
+ else if (n=="extra_space/space")
+ space_extra_spacing=p_value;
+ else if (n=="extra_space/top")
+ top_extra_spacing=p_value;
+ else if (n=="extra_space/bottom")
+ bottom_extra_spacing=p_value;
+
+ else if (n=="character_set/mode") {
+ character_set=CharacterSet(int(p_value));
+ _change_notify();
+ } else if (n=="character_set/custom")
+ custom_file=p_value;
+
+ else if (n=="shadow/enabled") {
+ shadow=p_value;
+ _change_notify();
+ }else if (n=="shadow/radius")
+ shadow_radius=p_value;
+ else if (n=="shadow/offset")
+ shadow_offset=p_value;
+ else if (n=="shadow/color")
+ shadow_color=p_value;
+ else if (n=="shadow/transition")
+ shadow_transition=p_value;
+
+ else if (n=="shadow2/enabled") {
+ shadow2=p_value;
+ _change_notify();
+ }else if (n=="shadow2/radius")
+ shadow2_radius=p_value;
+ else if (n=="shadow2/offset")
+ shadow2_offset=p_value;
+ else if (n=="shadow2/color")
+ shadow2_color=p_value;
+ else if (n=="shadow2/transition")
+ shadow2_transition=p_value;
+
+ else if (n=="color/mode") {
+ color_type=ColorType(int(p_value));
+ _change_notify();
+ }else if (n=="color/color")
+ color=p_value;
+ else if (n=="color/begin")
+ gradient_begin=p_value;
+ else if (n=="color/end")
+ gradient_end=p_value;
+ else if (n=="color/image")
+ gradient_image=p_value;
+ else if (n=="color/monochrome")
+ color_use_monochrome=p_value;
+ else if (n=="advanced/round_advance")
+ round_advance=p_value;
+ else if (n=="advanced/enable_filter")
+ enable_filter=p_value;
+ else if (n=="advanced/premultiply_alpha")
+ premultiply_alpha=p_value;
+ else
+ return false;
+
+ emit_signal("changed");
+
+
+ return true;
+
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const{
+
+ String n = p_name;
+ if (n=="mode/mode")
+ r_ret=font_mode;
+ else if (n=="extra_space/char")
+ r_ret=char_extra_spacing;
+ else if (n=="extra_space/space")
+ r_ret=space_extra_spacing;
+ else if (n=="extra_space/top")
+ r_ret=top_extra_spacing;
+ else if (n=="extra_space/bottom")
+ r_ret=bottom_extra_spacing;
+
+ else if (n=="character_set/mode")
+ r_ret=character_set;
+ else if (n=="character_set/custom")
+ r_ret=custom_file;
+
+ else if (n=="shadow/enabled")
+ r_ret=shadow;
+ else if (n=="shadow/radius")
+ r_ret=shadow_radius;
+ else if (n=="shadow/offset")
+ r_ret=shadow_offset;
+ else if (n=="shadow/color")
+ r_ret=shadow_color;
+ else if (n=="shadow/transition")
+ r_ret=shadow_transition;
+
+ else if (n=="shadow2/enabled")
+ r_ret=shadow2;
+ else if (n=="shadow2/radius")
+ r_ret=shadow2_radius;
+ else if (n=="shadow2/offset")
+ r_ret=shadow2_offset;
+ else if (n=="shadow2/color")
+ r_ret=shadow2_color;
+ else if (n=="shadow2/transition")
+ r_ret=shadow2_transition;
+
+
+ else if (n=="color/mode")
+ r_ret=color_type;
+ else if (n=="color/color")
+ r_ret=color;
+ else if (n=="color/begin")
+ r_ret=gradient_begin;
+ else if (n=="color/end")
+ r_ret=gradient_end;
+ else if (n=="color/image")
+ r_ret=gradient_image;
+ else if (n=="color/monochrome")
+ r_ret=color_use_monochrome;
+ else if (n=="advanced/round_advance")
+ r_ret=round_advance;
+ else if (n=="advanced/enable_filter")
+ r_ret=enable_filter;
+ else if (n=="advanced/premultiply_alpha")
+ r_ret=premultiply_alpha;
+ else
+ return false;
+
+ return true;
+
+ }
+
+ void _get_property_list( List<PropertyInfo> *p_list) const{
+
+
+ p_list->push_back(PropertyInfo(Variant::INT,"mode/mode",PROPERTY_HINT_ENUM,"Bitmap,Distance Field"));
+
+ p_list->push_back(PropertyInfo(Variant::INT,"extra_space/char",PROPERTY_HINT_RANGE,"-64,64,1"));
+ p_list->push_back(PropertyInfo(Variant::INT,"extra_space/space",PROPERTY_HINT_RANGE,"-64,64,1"));
+ p_list->push_back(PropertyInfo(Variant::INT,"extra_space/top",PROPERTY_HINT_RANGE,"-64,64,1"));
+ p_list->push_back(PropertyInfo(Variant::INT,"extra_space/bottom",PROPERTY_HINT_RANGE,"-64,64,1"));
+ p_list->push_back(PropertyInfo(Variant::INT,"character_set/mode",PROPERTY_HINT_ENUM,"Ascii,Latin,Unicode,Custom,Custom&Latin"));
+
+ if (character_set>=CHARSET_CUSTOM)
+ p_list->push_back(PropertyInfo(Variant::STRING,"character_set/custom",PROPERTY_HINT_GLOBAL_FILE));
+
+ int usage = PROPERTY_USAGE_DEFAULT;
+
+ if (font_mode==FONT_DISTANCE_FIELD) {
+ usage = PROPERTY_USAGE_NOEDITOR;
+ }
+
+ {
+
+ p_list->push_back(PropertyInfo(Variant::BOOL,"shadow/enabled",PROPERTY_HINT_NONE,"",usage));
+ if (shadow) {
+ p_list->push_back(PropertyInfo(Variant::INT,"shadow/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow/offset",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::COLOR,"shadow/color",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::REAL,"shadow/transition",PROPERTY_HINT_EXP_EASING,"",usage));
+ }
+
+ p_list->push_back(PropertyInfo(Variant::BOOL,"shadow2/enabled",PROPERTY_HINT_NONE,"",usage));
+ if (shadow2) {
+ p_list->push_back(PropertyInfo(Variant::INT,"shadow2/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage));
+ p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow2/offset",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::COLOR,"shadow2/color",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::REAL,"shadow2/transition",PROPERTY_HINT_EXP_EASING,"",usage));
+ }
+
+ p_list->push_back(PropertyInfo(Variant::INT,"color/mode",PROPERTY_HINT_ENUM,"White,Color,Gradient,Gradient Image",usage));
+ if (color_type==COLOR_CUSTOM) {
+ p_list->push_back(PropertyInfo(Variant::COLOR,"color/color",PROPERTY_HINT_NONE,"",usage));
+
+ }
+ if (color_type==COLOR_GRADIENT_RANGE) {
+ p_list->push_back(PropertyInfo(Variant::COLOR,"color/begin",PROPERTY_HINT_NONE,"",usage));
+ p_list->push_back(PropertyInfo(Variant::COLOR,"color/end",PROPERTY_HINT_NONE,"",usage));
+ }
+ if (color_type==COLOR_GRADIENT_IMAGE) {
+ p_list->push_back(PropertyInfo(Variant::STRING,"color/image",PROPERTY_HINT_GLOBAL_FILE,"",usage));
+ }
+ p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome",PROPERTY_HINT_NONE,"",usage));
+ }
+
+ p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/round_advance"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/enable_filter"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/premultiply_alpha"));
+
+ }
+
+
+ static void _bind_methods() {
+
+
+ ADD_SIGNAL( MethodInfo("changed"));
+ }
+
+
+ void reset() {
+
+ char_extra_spacing=0;
+ top_extra_spacing=0;
+ bottom_extra_spacing=0;
+ space_extra_spacing=0;
+
+ character_set=CHARSET_LATIN;
+
+ shadow=false;
+ shadow_radius=2;
+ shadow_color=Color(0,0,0,0.3);
+ shadow_transition=1.0;
+
+ shadow2=false;
+ shadow2_radius=2;
+ shadow2_color=Color(0,0,0,0.3);
+ shadow2_transition=1.0;
+
+ color_type=COLOR_WHITE;
+ color=Color(1,1,1,1);
+ gradient_begin=Color(1,1,1,1);
+ gradient_end=Color(0.5,0.5,0.5,1);
+ color_use_monochrome=false;
+
+ font_mode=FONT_BITMAP;
+ round_advance=true;
+ enable_filter=true;
+ premultiply_alpha=false;
+
+ }
+
+ _EditorFontImportOptions() {
+
+ font_mode=FONT_BITMAP;
+
+ char_extra_spacing=0;
+ top_extra_spacing=0;
+ bottom_extra_spacing=0;
+ space_extra_spacing=0;
+
+ character_set=CHARSET_LATIN;
+
+ shadow=false;
+ shadow_radius=2;
+ shadow_color=Color(0,0,0,0.3);
+ shadow_transition=1.0;
+
+ shadow2=false;
+ shadow2_radius=2;
+ shadow2_color=Color(0,0,0,0.3);
+ shadow2_transition=1.0;
+
+ color_type=COLOR_WHITE;
+ color=Color(1,1,1,1);
+ gradient_begin=Color(1,1,1,1);
+ gradient_end=Color(0.5,0.5,0.5,1);
+ color_use_monochrome=false;
+
+ round_advance=true;
+ enable_filter=true;
+ premultiply_alpha=false;
+ }
+
+
+};
+
+
+class EditorFontImportDialog : public ConfirmationDialog {
+
+ GDCLASS(EditorFontImportDialog, ConfirmationDialog);
+
+
+ EditorLineEditFileChooser *source;
+ EditorLineEditFileChooser *dest;
+ SpinBox *font_size;
+ LineEdit *test_string;
+ ColorPickerButton *test_color;
+ Label *test_label;
+ PropertyEditor *prop_edit;
+ Timer *timer;
+ ConfirmationDialog *error_dialog;
+
+
+ Ref<ResourceImportMetadata> get_rimd() {
+
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+ List<PropertyInfo> pl;
+ options->_get_property_list(&pl);
+ for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
+
+ Variant v;
+ String opt=E->get().name;
+ options->_get(opt,v);
+ if (opt=="color/image" || opt=="character_set/custom") {
+ v = EditorImportPlugin::validate_source_path(v);
+ }
+ imd->set_option(opt,v);
+ }
+
+ String src_path = EditorImportPlugin::validate_source_path(source->get_line_edit()->get_text());
+ //print_line("pre src path "+source->get_line_edit()->get_text());
+ //print_line("src path "+src_path);
+ imd->add_source(src_path);
+ imd->set_option("font/size",font_size->get_value());
+
+ return imd;
+
+ }
+
+ void _src_changed(String) {
+ _prop_changed();
+ }
+
+ void _update_text2(String) {
+ _update_text();
+ }
+ void _update_text3(Color) {
+ _update_text();
+ }
+
+ void _update_text() {
+
+ test_label->set_text("");
+ test_label->set_text(test_string->get_text());
+ test_label->add_color_override("font_color",test_color->get_pick_color());
+ }
+
+ void _update() {
+
+ Ref<ResourceImportMetadata> imd = get_rimd();
+ Ref<BitmapFont> font = plugin->generate_font(imd);
+ test_label->add_font_override("font",font);
+ _update_text();
+ }
+
+ void _font_size_changed(double) {
+
+ _prop_changed();
+ }
+
+ void _prop_changed() {
+
+ timer->start();
+ }
+
+ void _import_inc(String p_font) {
+
+ Ref<BitmapFont> font = ResourceLoader::load(p_font);
+ if (!font.is_valid())
+ return;
+ Ref<ImageTexture> tex = font->get_texture(0);
+ if (tex.is_null())
+ return;
+ FileAccessRef f=FileAccess::open(p_font.get_basename()+".inc",FileAccess::WRITE);
+ Vector<CharType> ck = font->get_char_keys();
+
+ f->store_line("static const int _builtin_font_height="+itos(font->get_height())+";");
+ f->store_line("static const int _builtin_font_ascent="+itos(font->get_ascent())+";");
+ f->store_line("static const int _builtin_font_charcount="+itos(ck.size())+";");
+ f->store_line("static const int _builtin_font_charrects["+itos(ck.size())+"][8]={");
+ f->store_line("/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */");
+
+ for(int i=0;i<ck.size();i++) {
+ CharType k=ck[i];
+ BitmapFont::Character c=font->get_character(k);
+ f->store_line("{"+itos(k)+","+rtos(c.rect.pos.x)+","+rtos(c.rect.pos.y)+","+rtos(c.rect.size.x)+","+rtos(c.rect.size.y)+","+rtos(c.v_align)+","+rtos(c.h_align)+","+rtos(c.advance)+"},");
+ }
+ f->store_line("};");
+
+ Vector<BitmapFont::KerningPairKey> kp=font->get_kerning_pair_keys();
+ f->store_line("static const int _builtin_font_kerning_pair_count="+itos(kp.size())+";");
+ f->store_line("static const int _builtin_font_kerning_pairs["+itos(kp.size())+"][3]={");
+ for(int i=0;i<kp.size();i++) {
+
+ int d = font->get_kerning_pair(kp[i].A,kp[i].B);
+ f->store_line("{"+itos(kp[i].A)+","+itos(kp[i].B)+","+itos(d)+"},");
+ }
+
+ f->store_line("};");
+ Image img = tex->get_data();
+
+ f->store_line("static const int _builtin_font_img_width="+itos(img.get_width())+";");
+ f->store_line("static const int _builtin_font_img_height="+itos(img.get_height())+";");
+
+ String fname = p_font.get_basename()+".sv.png";
+ ResourceSaver::save(fname,tex);
+ Vector<uint8_t> data=FileAccess::get_file_as_array(fname);
+
+
+ f->store_line("static const int _builtin_font_img_data_size="+itos(data.size())+";");
+ f->store_line("static const unsigned char _builtin_font_img_data["+itos(data.size())+"]={");
+
+
+
+ for(int i=0;i<data.size();i++) {
+
+ f->store_line(itos(data[i])+",");
+
+ }
+ f->store_line("};");
+
+ }
+
+ void _import() {
+
+ if (source->get_line_edit()->get_text()=="") {
+ error_dialog->set_text(TTR("No source font file!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ if (dest->get_line_edit()->get_text()=="") {
+ error_dialog->set_text(TTR("No target font resource!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ 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().get_basename() + ".fnt" );
+ }
+
+ if (dest->get_line_edit()->get_text().get_extension() == dest->get_line_edit()->get_text()) {
+ dest->get_line_edit()->set_text(dest->get_line_edit()->get_text() + ".fnt");
+ }
+
+ if (dest->get_line_edit()->get_text().get_extension().to_lower() != "fnt") {
+ error_dialog->set_text(TTR("Invalid file extension.\nPlease use .fnt."));
+ error_dialog->popup_centered(Size2(200,100));
+ return;
+ }
+
+ Ref<ResourceImportMetadata> rimd = get_rimd();
+
+ if (rimd.is_null()) {
+ error_dialog->set_text(TTR("Can't load/process source font."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ Error err = plugin->import(dest->get_line_edit()->get_text(),rimd);
+
+ if (err!=OK) {
+ error_dialog->set_text(TTR("Couldn't save font."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ _import_inc(dest->get_line_edit()->get_text());
+
+ hide();
+ }
+
+ EditorFontImportPlugin *plugin;
+ _EditorFontImportOptions *options;
+
+ static void _bind_methods() {
+
+ ClassDB::bind_method("_update",&EditorFontImportDialog::_update);
+ ClassDB::bind_method("_update_text",&EditorFontImportDialog::_update_text);
+ ClassDB::bind_method("_update_text2",&EditorFontImportDialog::_update_text2);
+ ClassDB::bind_method("_update_text3",&EditorFontImportDialog::_update_text3);
+ ClassDB::bind_method("_prop_changed",&EditorFontImportDialog::_prop_changed);
+ ClassDB::bind_method("_src_changed",&EditorFontImportDialog::_src_changed);
+ ClassDB::bind_method("_font_size_changed",&EditorFontImportDialog::_font_size_changed);
+ ClassDB::bind_method("_import",&EditorFontImportDialog::_import);
+
+ }
+
+public:
+
+ void _notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ prop_edit->edit(options);
+ _update_text();
+ }
+ }
+
+ void popup_import(const String& p_path) {
+
+ popup_centered(Size2(600,500)*EDSCALE);
+
+ if (p_path!="") {
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+ ERR_FAIL_COND(!rimd.is_valid());
+
+ dest->get_line_edit()->set_text(p_path);
+ List<String> opts;
+ rimd->get_options(&opts);
+ options->reset();
+ for(List<String>::Element *E=opts.front();E;E=E->next()) {
+
+ options->_set(E->get(),rimd->get_option(E->get()));
+ }
+
+ String src = "";
+ for(int i=0;i<rimd->get_source_count();i++) {
+ if (i>0)
+ src+=",";
+ src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
+ }
+ source->get_line_edit()->set_text(src);
+
+ font_size->set_value(rimd->get_option("font/size"));
+ }
+ }
+
+
+ void set_source_and_dest(const String& p_font,const String& p_dest) {
+ source->get_line_edit()->set_text(p_font);
+ dest->get_line_edit()->set_text(p_dest);
+ _prop_changed();
+ }
+
+ EditorFontImportDialog(EditorFontImportPlugin *p_plugin) {
+ plugin=p_plugin;
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ //set_child_rect(vbc);
+ HBoxContainer *hbc = memnew( HBoxContainer);
+ vbc->add_child(hbc);
+ VBoxContainer *vbl = memnew( VBoxContainer );
+ hbc->add_child(vbl);
+ hbc->set_v_size_flags(SIZE_EXPAND_FILL);
+ vbl->set_h_size_flags(SIZE_EXPAND_FILL);
+ VBoxContainer *vbr = memnew( VBoxContainer );
+ hbc->add_child(vbr);
+ vbr->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ source = memnew( EditorLineEditFileChooser );
+ source->get_file_dialog()->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ 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(TTR("Source Font:"),source);
+ font_size = memnew( SpinBox );
+ vbl->add_margin_child(TTR("Source Font Size:"),font_size);
+ font_size->set_min(3);
+ font_size->set_max(256);
+ font_size->set_value(16);
+ font_size->connect("value_changed",this,"_font_size_changed");
+ dest = memnew( EditorLineEditFileChooser );
+ //
+ List<String> fl;
+ Ref<BitmapFont> font= memnew(BitmapFont);
+ dest->get_file_dialog()->add_filter("*.fnt ; Font" );
+ /*
+ ResourceSaver::get_recognized_extensions(font,&fl);
+ for(List<String>::Element *E=fl.front();E;E=E->next()) {
+ dest->get_file_dialog()->add_filter("*."+E->get());
+ }
+ */
+
+ vbl->add_margin_child(TTR("Dest Resource:"),dest);
+ HBoxContainer *testhb = memnew( HBoxContainer );
+ test_string = memnew( LineEdit );
+ test_string->set_text(TTR("The quick brown fox jumps over the lazy dog."));
+ test_string->set_h_size_flags(SIZE_EXPAND_FILL);
+ test_string->set_stretch_ratio(5);
+
+ testhb->add_child(test_string);
+ test_color = memnew( ColorPickerButton );
+ test_color->set_pick_color(get_color("font_color","Label"));
+ test_color->set_h_size_flags(SIZE_EXPAND_FILL);
+ test_color->set_stretch_ratio(1);
+ test_color->connect("color_changed",this,"_update_text3");
+ testhb->add_child(test_color);
+
+ vbl->add_spacer();
+ vbl->add_margin_child(TTR("Test:")+" ",testhb);
+ /*
+ HBoxContainer *upd_hb = memnew( HBoxContainer );
+ //vbl->add_child(upd_hb);
+ upd_hb->add_spacer();
+ Button *update = memnew( Button);
+ upd_hb->add_child(update);
+ update->set_text("Update");
+ update->connect("pressed",this,"_update");
+*/
+ options = memnew( _EditorFontImportOptions );
+ prop_edit = memnew( PropertyEditor() );
+ vbr->add_margin_child(TTR("Options:"),prop_edit,true);
+ options->connect("changed",this,"_prop_changed");
+
+ prop_edit->hide_top_label();
+
+ Panel *panel = memnew( Panel );
+ vbc->add_child(panel);
+ test_label = memnew( Label );
+ test_label->set_autowrap(true);
+ panel->add_child(test_label);
+ test_label->set_area_as_parent_rect();
+ panel->set_v_size_flags(SIZE_EXPAND_FILL);
+ test_string->connect("text_changed",this,"_update_text2");
+ set_title(TTR("Font Import"));
+ timer = memnew( Timer );
+ add_child(timer);
+ timer->connect("timeout",this,"_update");
+ timer->set_wait_time(0.4);
+ timer->set_one_shot(true);
+
+ get_ok()->connect("pressed", this,"_import");
+ get_ok()->set_text(TTR("Import"));
+
+ error_dialog = memnew ( ConfirmationDialog );
+ add_child(error_dialog);
+ error_dialog->get_ok()->set_text(TTR("Accept"));
+ set_hide_on_ok(false);
+
+
+ }
+
+ ~EditorFontImportDialog() {
+ memdelete(options);
+ }
+};
+
+
+///////////////////////////////////////
+
+
+
+struct _EditorFontData {
+
+ Vector<uint8_t> bitmap;
+ int width,height;
+ int ofs_x; //ofset to center, from ABOVE
+ int ofs_y; //ofset to begining, from LEFT
+ int valign; //vertical alignment
+ int halign;
+ float advance;
+ int character;
+ int glyph;
+
+ int texture;
+ Image blit;
+ Point2i blit_ofs;
+ //bool printable;
+
+};
+
+
+struct _EditorFontDataSort {
+
+ bool operator()(const _EditorFontData *p_A,const _EditorFontData *p_B) const {
+ return p_A->height > p_B->height;
+ };
+};
+
+struct _EditorKerningKey {
+
+ CharType A,B;
+ bool operator<(const _EditorKerningKey& p_k) const { return (A==p_k.A)?(B<p_k.B):(A<p_k.A); }
+
+};
+
+
+static unsigned char get_SDF_radial(
+ unsigned char *fontmap,
+ int w, int h,
+ int x, int y,
+ int max_radius )
+{
+ //hideous brute force method
+ float d2 = max_radius*max_radius+1.0;
+ unsigned char v = fontmap[x+y*w];
+ for( int radius = 1; (radius <= max_radius) && (radius*radius < d2); ++radius )
+ {
+ int line, lo, hi;
+ //north
+ line = y - radius;
+ if( (line >= 0) && (line < h) )
+ {
+ lo = x - radius;
+ hi = x + radius;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= w ) { hi = w-1; }
+ int idx = line * w + lo;
+ for( int i = lo; i <= hi; ++i )
+ {
+ //check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = i - x;
+ float ny = line - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ //move on
+ ++idx;
+ }
+ }
+ //south
+ line = y + radius;
+ if( (line >= 0) && (line < h) )
+ {
+ lo = x - radius;
+ hi = x + radius;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= w ) { hi = w-1; }
+ int idx = line * w + lo;
+ for( int i = lo; i <= hi; ++i )
+ {
+ //check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = i - x;
+ float ny = line - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ //move on
+ ++idx;
+ }
+ }
+ //west
+ line = x - radius;
+ if( (line >= 0) && (line < w) )
+ {
+ lo = y - radius + 1;
+ hi = y + radius - 1;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= h ) { hi = h-1; }
+ int idx = lo * w + line;
+ for( int i = lo; i <= hi; ++i )
+ {
+ //check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = line - x;
+ float ny = i - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ //move on
+ idx += w;
+ }
+ }
+ //east
+ line = x + radius;
+ if( (line >= 0) && (line < w) )
+ {
+ lo = y - radius + 1;
+ hi = y + radius - 1;
+ if( lo < 0 ) { lo = 0; }
+ if( hi >= h ) { hi = h-1; }
+ int idx = lo * w + line;
+ for( int i = lo; i <= hi; ++i )
+ {
+ //check this pixel
+ if( fontmap[idx] != v )
+ {
+ float nx = line - x;
+ float ny = i - y;
+ float nd2 = nx*nx+ny*ny;
+ if( nd2 < d2 )
+ {
+ d2 = nd2;
+ }
+ }
+ //move on
+ idx += w;
+ }
+ }
+ }
+ d2 = sqrtf( d2 );
+ if( v==0 )
+ {
+ d2 = -d2;
+ }
+ d2 *= 127.5 / max_radius;
+ d2 += 127.5;
+ if( d2 < 0.0 ) d2 = 0.0;
+ if( d2 > 255.0 ) d2 = 255.0;
+ return (unsigned char)(d2 + 0.5);
+}
+
+
+Ref<BitmapFont> 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<BitmapFont>());
+
+ String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
+
+ if (src_path.get_extension().to_lower()=="fnt") {
+
+ if (ResourceLoader::load(src_path).is_valid()) {
+ EditorNode::get_singleton()->show_warning(TTR("Path:")+" "+src_path+"\n"+TTR("This file is already a Godot font file, please supply a BMFont type file instead."));
+ return Ref<BitmapFont>();
+ }
+
+ Ref<BitmapFont> font;
+ font.instance();
+ Error err = font->create_from_fnt(src_path);
+ if (err) {
+ EditorNode::get_singleton()->show_warning(TTR("Path:")+" "+src_path+"\n"+TTR("Failed opening as BMFont file."));
+ return Ref<BitmapFont>();
+ }
+
+ return font;
+ }
+
+ int size = from->get_option("font/size");
+
+#ifdef FREETYPE_ENABLED
+ FT_Library library; /* handle to library */
+ FT_Face face; /* handle to face object */
+
+ Vector<_EditorFontData*> font_data_list;
+
+ int error = FT_Init_FreeType( &library );
+
+ ERR_EXPLAIN(TTR("Error initializing FreeType."));
+ ERR_FAIL_COND_V( error !=0, Ref<BitmapFont>() );
+
+ print_line("loadfrom: "+src_path);
+ error = FT_New_Face( library, src_path.utf8().get_data(),0,&face );
+
+ if ( error == FT_Err_Unknown_File_Format ) {
+ ERR_EXPLAIN(TTR("Unknown font format."));
+ FT_Done_FreeType( library );
+ } else if ( error ) {
+
+ ERR_EXPLAIN(TTR("Error loading font."));
+ FT_Done_FreeType( library );
+
+ }
+
+ ERR_FAIL_COND_V(error,Ref<BitmapFont>());
+
+
+ int height=0;
+ int ascent=0;
+ int font_spacing=0;
+
+ error = FT_Set_Char_Size(face,0,64*size,512,512);
+
+ if ( error ) {
+ FT_Done_FreeType( library );
+ ERR_EXPLAIN(TTR("Invalid font size."));
+ ERR_FAIL_COND_V( error,Ref<BitmapFont>() );
+
+ }
+
+ int font_mode = from->get_option("mode/mode");
+
+ int scaler=(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD)?16:1;
+
+ error = FT_Set_Pixel_Sizes(face,0,size*scaler);
+
+ FT_GlyphSlot slot = face->glyph;
+
+ //error = FT_Set_Charmap(face,ft_encoding_unicode ); /* encoding.. */
+
+
+ /* PRINT CHARACTERS TO INDIVIDUAL BITMAPS */
+
+
+ //int space_size=5; //size for space, if none found.. 5!
+ //int min_valign=500; //some ridiculous number
+
+ FT_ULong charcode;
+ FT_UInt gindex;
+
+ int max_up=-1324345; ///gibberish
+ int max_down=124232;
+
+ Map<_EditorKerningKey,int> kerning_map;
+
+ charcode = FT_Get_First_Char( face, &gindex );
+
+ Set<CharType> import_chars;
+
+ int import_mode = from->get_option("character_set/mode");
+ bool round_advance = from->get_option("advanced/round_advance");
+
+ if (import_mode>=_EditorFontImportOptions::CHARSET_CUSTOM) {
+
+ //load from custom text
+ String path = from->get_option("character_set/custom");
+
+ FileAccess *fa = FileAccess::open(EditorImportPlugin::expand_source_path(path),FileAccess::READ);
+
+ if ( !fa ) {
+
+ FT_Done_FreeType( library );
+ ERR_EXPLAIN(TTR("Invalid font custom source."));
+ ERR_FAIL_COND_V( !fa,Ref<BitmapFont>() );
+
+ }
+
+
+ while(!fa->eof_reached()) {
+
+ String line = fa->get_line();
+ for(int i=0;i<line.length();i++) {
+ import_chars.insert(line[i]);
+ }
+ }
+
+ if (import_mode==_EditorFontImportOptions::CHARSET_CUSTOM_LATIN) {
+
+ for(int i=32;i<128;i++)
+ import_chars.insert(i);
+ }
+
+ memdelete(fa);
+ }
+
+ int xsize=0;
+ while ( gindex != 0 )
+ {
+
+ bool skip=false;
+ error = FT_Load_Char( face, charcode, font_mode==_EditorFontImportOptions::FONT_BITMAP?FT_LOAD_RENDER:FT_LOAD_MONOCHROME );
+ if (error) skip=true;
+ else error = FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono );
+ if (error) {
+ skip=true;
+ } else if (!skip) {
+
+ switch(import_mode) {
+
+ case _EditorFontImportOptions::CHARSET_ASCII: skip = charcode>127; break;
+ case _EditorFontImportOptions::CHARSET_LATIN: skip = charcode>255 ;break;
+ case _EditorFontImportOptions::CHARSET_UNICODE: break; //none
+ case _EditorFontImportOptions::CHARSET_CUSTOM:
+ case _EditorFontImportOptions::CHARSET_CUSTOM_LATIN: skip = !import_chars.has(charcode); break;
+
+ }
+ }
+
+ if (charcode<=32) //??
+ skip=true;
+
+ if (skip) {
+ charcode=FT_Get_Next_Char(face,charcode,&gindex);
+ continue;
+ }
+
+ _EditorFontData * fdata = memnew( _EditorFontData );
+
+
+ int w = slot->bitmap.width;
+ int h = slot->bitmap.rows;
+ int p = slot->bitmap.pitch;
+
+ //print_line("W: "+itos(w)+" P: "+itos(slot->bitmap.pitch));
+
+ if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
+
+ //oversize the holding buffer so I can smooth it!
+ int sw = w + scaler * 4;
+ int sh = h + scaler * 4;
+ //do the SDF
+ int sdfw = sw / scaler;
+ int sdfh = sh / scaler;
+
+ fdata->width=sdfw;
+ fdata->height=sdfh;
+ } else {
+ fdata->width=w;
+ fdata->height=h;
+ }
+
+ fdata->character=charcode;
+ fdata->glyph=FT_Get_Char_Index(face,charcode);
+ if (charcode=='x')
+ xsize=w/scaler;
+
+
+
+ fdata->valign=slot->bitmap_top;
+ fdata->halign=slot->bitmap_left;
+
+ if (round_advance)
+ fdata->advance=(slot->advance.x+(1<<5))>>6;
+ else
+ fdata->advance=slot->advance.x/float(1<<6);
+
+ if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
+
+ fdata->halign = fdata->halign / scaler - 1.5;
+ fdata->valign = fdata->valign / scaler + 1.5;
+ fdata->advance/=scaler;
+
+ }
+
+ fdata->advance+=font_spacing;
+
+
+ if (charcode<127) {
+ int top = fdata->valign;
+ int hmax = h/scaler;
+
+ if (top>max_up) {
+
+ max_up=top;
+ }
+
+
+ if ( (top - hmax)<max_down ) {
+
+ max_down=top - hmax;
+ }
+ }
+
+ if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
+
+
+ //oversize the holding buffer so I can smooth it!
+ int sw = w + scaler * 4;
+ int sh = h + scaler * 4;
+
+ unsigned char *smooth_buf = new unsigned char[sw*sh];
+
+ for( int i = 0; i < sw*sh; ++i ) {
+ smooth_buf[i] = 0;
+ }
+
+ // copy the glyph into the buffer to be smoothed
+ unsigned char *buf = slot->bitmap.buffer;
+ for( int j = 0; j < h; ++j ) {
+ for( int i = 0; i < w; ++i ) {
+ smooth_buf[scaler*2+i+(j+scaler*2)*sw] = 255 * ((buf[j*p+(i>>3)] >> (7 - (i & 7))) & 1);
+ }
+ }
+
+ // do the SDF
+ int sdfw = fdata->width;
+ int sdfh = fdata->height;
+
+ fdata->bitmap.resize( sdfw*sdfh );
+
+ for( int j = 0; j < sdfh; ++j ) {
+ for( int i = 0; i < sdfw; ++i ) {
+ int pd_idx = j*sdfw+i;
+
+ //fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
+
+ fdata->bitmap[pd_idx] =
+ //get_SDF
+ get_SDF_radial
+ ( smooth_buf, sw, sh,
+ i*scaler + (scaler >>1), j*scaler + (scaler >>1),
+ 2*scaler );
+
+ }
+ }
+
+ delete [] smooth_buf;
+
+ } else {
+ fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows );
+ for (int i=0;i<slot->bitmap.width;i++) {
+ for (int j=0;j<slot->bitmap.rows;j++) {
+
+ fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
+ }
+ }
+ }
+
+ font_data_list.push_back(fdata);
+ charcode=FT_Get_Next_Char(face,charcode,&gindex);
+// printf("reading char %i\n",charcode);
+ }
+
+ /* SPACE */
+
+ _EditorFontData *spd = memnew( _EditorFontData );
+ spd->advance=0;
+ spd->character=' ';
+ spd->halign=0;
+ spd->valign=0;
+ spd->width=0;
+ spd->height=0;
+ spd->ofs_x=0;
+ spd->ofs_y=0;
+
+ if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono )) {
+
+ spd->advance = slot->advance.x>>6; //round to nearest or store as float
+ spd->advance/=scaler;
+ spd->advance+=font_spacing;
+ } else {
+
+ spd->advance=xsize;
+ spd->advance+=font_spacing;
+ }
+
+ font_data_list.push_back(spd);
+
+ Set<CharType> exported;
+ for (int i=0; i<font_data_list.size(); i++) {
+ exported.insert(font_data_list[i]->character);
+ };
+ int missing = 0;
+ for(Set<CharType>::Element *E=import_chars.front();E;E=E->next()) {
+ CharType c = E->get();
+ if (!exported.has(c)) {
+ CharType str[2] = {c, 0};
+ printf("** Warning: character %i (%ls) not exported\n", (int)c, str);
+ ++missing;
+ };
+ };
+ print_line("total_chars: "+itos(font_data_list.size()));
+
+ /* KERNING */
+
+
+ for(int i=0;i<font_data_list.size();i++) {
+
+ if (font_data_list[i]->character>512)
+ continue;
+ for(int j=0;j<font_data_list.size();j++) {
+
+ if (font_data_list[j]->character>512)
+ continue;
+
+ FT_Vector delta;
+ FT_Get_Kerning( face, font_data_list[i]->glyph,font_data_list[j]->glyph, FT_KERNING_DEFAULT, &delta );
+
+ if (delta.x!=0) {
+
+ _EditorKerningKey kpk;
+ kpk.A = font_data_list[i]->character;
+ kpk.B = font_data_list[j]->character;
+ int kern = ((-delta.x)+(1<<5))>>6;
+
+ if (kern==0)
+ continue;
+ kerning_map[kpk]=kern/scaler;
+ }
+ }
+ }
+
+ height=max_up-max_down;
+ ascent=max_up;
+
+ /* FIND OUT WHAT THE FONT HEIGHT FOR THIS IS */
+
+ /* ADJUST THE VALIGN FOR EACH CHARACTER */
+
+ for (int i=0;i<(int)font_data_list.size();i++) {
+
+ font_data_list[i]->valign=max_up-font_data_list[i]->valign;
+ }
+
+
+
+ /* ADD THE SPACEBAR CHARACTER */
+/*
+ _EditorFontData * fdata = new _EditorFontData;
+
+ fdata->character=32;
+ fdata->bitmap=0;
+ fdata->width=xsize;
+ fdata->height=1;
+ fdata->valign=0;
+
+ font_data_list.push_back(fdata);
+*/
+ /* SORT BY HEIGHT, SO THEY FIT BETTER ON THE TEXTURE */
+
+ font_data_list.sort_custom<_EditorFontDataSort>();
+ Color *color=memnew_arr(Color,height);
+
+ int gradient_type=from->get_option("color/mode");
+ switch(gradient_type) {
+ case _EditorFontImportOptions::COLOR_WHITE: {
+
+ for(int i=0;i<height;i++){
+ color[i]=Color(1,1,1,1);
+ }
+
+ } break;
+ case _EditorFontImportOptions::COLOR_CUSTOM: {
+
+ Color cc = from->get_option("color/color");
+ for(int i=0;i<height;i++){
+ color[i]=cc;
+ }
+
+ } break;
+ case _EditorFontImportOptions::COLOR_GRADIENT_RANGE: {
+
+ Color src=from->get_option("color/begin");
+ Color to=from->get_option("color/end");
+ for(int i=0;i<height;i++){
+ color[i]=src.linear_interpolate(to,i/float(height));
+ }
+
+ } break;
+ case _EditorFontImportOptions::COLOR_GRADIENT_IMAGE: {
+
+ String fp = EditorImportPlugin::expand_source_path(from->get_option("color/image"));
+ Image img;
+ Error err = ImageLoader::load_image(fp,&img);
+ if (err==OK) {
+
+ for(int i=0;i<height;i++){
+ //color[i]=img.get_pixel(0,i*img.get_height()/height);
+ }
+ } else {
+
+ for(int i=0;i<height;i++){
+ color[i]=Color(1,1,1,1);
+ }
+ }
+
+ } break;
+ }
+
+
+ for(int i=0;i<font_data_list.size();i++) {
+
+ if (font_data_list[i]->bitmap.size()==0)
+ continue;
+
+ int margin[4]={0,0,0,0};
+
+ if (from->get_option("shadow/enabled").operator bool()) {
+ int r=from->get_option("shadow/radius");
+ Point2i ofs=Point2(from->get_option("shadow/offset"));
+ margin[ MARGIN_LEFT ] = MAX( r - ofs.x, 0);
+ margin[ MARGIN_RIGHT ] = MAX( r + ofs.x, 0);
+ margin[ MARGIN_TOP ] = MAX( r - ofs.y, 0);
+ margin[ MARGIN_BOTTOM ] = MAX( r + ofs.y, 0);
+
+ }
+
+ if (from->get_option("shadow2/enabled").operator bool()) {
+ int r=from->get_option("shadow2/radius");
+ Point2i ofs=Point2(from->get_option("shadow2/offset"));
+ margin[ MARGIN_LEFT ] = MAX( r - ofs.x, margin[ MARGIN_LEFT ]);
+ margin[ MARGIN_RIGHT ] = MAX( r + ofs.x, margin[ MARGIN_RIGHT ]);
+ margin[ MARGIN_TOP ] = MAX( r - ofs.y, margin[ MARGIN_TOP ]);
+ margin[ MARGIN_BOTTOM ] = MAX( r + ofs.y, margin[ MARGIN_BOTTOM ]);
+
+ }
+
+ Size2i s;
+ s.width=font_data_list[i]->width+margin[MARGIN_LEFT]+margin[MARGIN_RIGHT];
+ s.height=font_data_list[i]->height+margin[MARGIN_TOP]+margin[MARGIN_BOTTOM];
+ Point2i o;
+ o.x=margin[MARGIN_LEFT];
+ o.y=margin[MARGIN_TOP];
+
+ int ow=font_data_list[i]->width;
+ int oh=font_data_list[i]->height;
+
+ PoolVector<uint8_t> pixels;
+ pixels.resize(s.x*s.y*4);
+
+ PoolVector<uint8_t>::Write w = pixels.write();
+ //print_line("val: "+itos(font_data_list[i]->valign));
+ for(int y=0;y<s.height;y++) {
+
+ int yc=CLAMP(y-o.y+font_data_list[i]->valign,0,height-1);
+ Color c=color[yc];
+ c.a=0;
+
+ for(int x=0;x<s.width;x++) {
+
+ int ofs=y*s.x+x;
+ w[ofs*4+0]=c.r*255.0;
+ w[ofs*4+1]=c.g*255.0;
+ w[ofs*4+2]=c.b*255.0;
+ w[ofs*4+3]=c.a*255.0;
+ }
+ }
+
+
+ for(int si=0;si<2;si++) {
+
+#define S_VAR(m_v) (String(si==0?"shadow/":"shadow2/")+m_v)
+ if (from->get_option(S_VAR("enabled")).operator bool()) {
+ int r = from->get_option(S_VAR("radius"));
+
+ Color sc = from->get_option(S_VAR("color"));
+ Point2i so=Point2(from->get_option(S_VAR("offset")));
+
+ float tr = from->get_option(S_VAR("transition"));
+ print_line("shadow enabled: "+itos(si));
+
+ Vector<uint8_t> s2buf;
+ s2buf.resize(s.x*s.y);
+ uint8_t *wa=s2buf.ptr();
+
+ for(int j=0;j<s.x*s.y;j++){
+
+ wa[j]=0;
+ }
+
+ // blit shadowa
+ for(int x=0;x<ow;x++) {
+ for(int y=0;y<oh;y++) {
+ int ofs = (o.y+y+so.y)*s.x+x+o.x+so.x;
+ wa[ofs]=font_data_list[i]->bitmap[y*ow+x];
+ }
+ }
+ //blur shadow2 with separatable convolution
+
+ if (r>0) {
+
+ Vector<uint8_t> pixels2;
+ pixels2.resize(s2buf.size());
+ uint8_t *w2=pixels2.ptr();
+ //vert
+ for(int x=0;x<s.width;x++) {
+ for(int y=0;y<s.height;y++) {
+
+ int ofs = y*s.width+x;
+ int sum=wa[ofs];
+
+ for(int k=1;k<=r;k++) {
+
+ int ofs_d=MIN(y+k,s.height-1)*s.width+x;
+ int ofs_u=MAX(y-k,0)*s.width+x;
+ sum+=wa[ofs_d];
+ sum+=wa[ofs_u];
+ }
+
+ w2[ofs]=sum/(r*2+1);
+
+ }
+ }
+ //horiz
+ for(int x=0;x<s.width;x++) {
+ for(int y=0;y<s.height;y++) {
+
+ int ofs = y*s.width+x;
+ int sum=w2[ofs];
+
+ for(int k=1;k<=r;k++) {
+
+ int ofs_r=MIN(x+k,s.width-1)+s.width*y;
+ int ofs_l=MAX(x-k,0)+s.width*y;
+ sum+=w2[ofs_r];
+ sum+=w2[ofs_l];
+ }
+
+ wa[ofs]=Math::pow(float(sum/(r*2+1))/255.0f,tr)*255.0f;
+
+ }
+ }
+
+ }
+
+ //blend back
+
+ for(int j=0;j<s.x*s.y;j++){
+ Color wd(w[j*4+0]/255.0,w[j*4+1]/255.0,w[j*4+2]/255.0,w[j*4+3]/255.0);
+ Color ws(sc.r,sc.g,sc.b,sc.a*(wa[j]/255.0));
+ Color b = wd.blend(ws);
+
+ w[j*4+0]=b.r*255.0;
+ w[j*4+1]=b.g*255.0;
+ w[j*4+2]=b.b*255.0;
+ w[j*4+3]=b.a*255.0;
+
+ }
+ }
+ }
+
+ for(int y=0;y<oh;y++) {
+ int yc=CLAMP(y+font_data_list[i]->valign,0,height-1);
+ Color sc=color[yc];
+ for(int x=0;x<ow;x++) {
+ int ofs = (o.y+y)*s.x+x+o.x;
+ float c = font_data_list[i]->bitmap[y*ow+x]/255.0;
+ Color src_col=sc;
+ src_col.a*=c;
+ Color dst_col(w[ofs*4+0]/255.0,w[ofs*4+1]/255.0,w[ofs*4+2]/255.0,w[ofs*4+3]/255.0);
+ dst_col = dst_col.blend(src_col);
+ w[ofs*4+0]=dst_col.r*255.0;
+ w[ofs*4+1]=dst_col.g*255.0;
+ w[ofs*4+2]=dst_col.b*255.0;
+ w[ofs*4+3]=dst_col.a*255.0;
+ }
+ }
+
+
+ w=PoolVector<uint8_t>::Write();
+
+ Image img(s.width,s.height,0,Image::FORMAT_RGBA8,pixels);
+
+ font_data_list[i]->blit=img;
+ font_data_list[i]->blit_ofs=o;
+
+ }
+
+ //make atlas
+ int spacing=2;
+ Vector<Size2i> sizes;
+ sizes.resize(font_data_list.size());
+ for(int i=0;i<font_data_list.size();i++) {
+
+ sizes[i]=Size2(font_data_list[i]->blit.get_width()+spacing*2,font_data_list[i]->blit.get_height()+spacing*2);
+
+ }
+ Vector<Point2i> res;
+ Size2i res_size;
+ EditorAtlas::fit(sizes,res,res_size);
+ res_size.x=nearest_power_of_2(res_size.x);
+ res_size.y=nearest_power_of_2(res_size.y);
+ print_line("Atlas size: "+res_size);
+
+ Image atlas(res_size.x,res_size.y,0,Image::FORMAT_RGBA8);
+
+ for(int i=0;i<font_data_list.size();i++) {
+
+ if (font_data_list[i]->bitmap.size()==0)
+ continue;
+ atlas.blit_rect(font_data_list[i]->blit,Rect2(0,0,font_data_list[i]->blit.get_width(),font_data_list[i]->blit.get_height()),res[i]+Size2(spacing,spacing));
+ font_data_list[i]->ofs_x=res[i].x+spacing;
+ font_data_list[i]->ofs_y=res[i].y+spacing;
+
+
+ }
+
+ if (from->has_option("advanced/premultiply_alpha") && bool(from->get_option("advanced/premultiply_alpha"))) {
+
+ PoolVector<uint8_t> data = atlas.get_data();
+ int dl = data.size();
+ {
+ PoolVector<uint8_t>::Write w = data.write();
+
+ for(int i=0;i<dl;i+=4) {
+
+ w[i+0]= uint8_t(int(w[i+0])*int(w[i+3])/255);
+ w[i+1]= uint8_t(int(w[i+1])*int(w[i+3])/255);
+ w[i+2]= uint8_t(int(w[i+2])*int(w[i+3])/255);
+ }
+ }
+
+ atlas=Image(res_size.x,res_size.y,0,Image::FORMAT_RGBA8,data);
+ }
+
+ if (from->has_option("color/monochrome") && bool(from->get_option("color/monochrome"))) {
+
+ atlas.convert(Image::FORMAT_LA8);
+ }
+
+
+ if (0) {
+ //debug the texture
+ Ref<ImageTexture> atlast = memnew( ImageTexture );
+ atlast->create_from_image(atlas);
+ //atlast->create_from_image(font_data_list[5]->blit);
+ TextureRect *tf = memnew( TextureRect );
+ tf->set_texture(atlast);
+ dialog->add_child(tf);
+ }
+
+
+ /* CREATE FONT */
+
+ int char_space = from->get_option("extra_space/char");
+ int space_space = from->get_option("extra_space/space");
+ int top_space = from->get_option("extra_space/top");
+ int bottom_space = from->get_option("extra_space/bottom");
+ bool enable_filter = from->get_option("advanced/enable_filter");
+ if (from->has_option("advanced/disable_filter")){ // this is a compatibility check for a deprecated option
+ enable_filter = !from->get_option("advanced/disable_filter");
+ }
+
+ Ref<BitmapFont> font;
+
+ if (p_existing!=String() && ResourceCache::has(p_existing)) {
+
+ font = Ref<BitmapFont>( ResourceCache::get(p_existing)->cast_to<BitmapFont>());
+ }
+
+ if (font.is_null()) {
+ font = Ref<BitmapFont>( memnew( BitmapFont ) );
+ }
+
+ font->clear();
+ font->set_height(height+bottom_space+top_space);
+ font->set_ascent(ascent+top_space);
+ font->set_distance_field_hint(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD);
+
+ //register texures
+ {
+ Ref<ImageTexture> t = memnew(ImageTexture);
+ int flags;
+ if (!enable_filter)
+ flags=0;
+ else
+ flags=Texture::FLAG_FILTER;
+ t->create_from_image(atlas,flags);
+ t->set_storage( ImageTexture::STORAGE_COMPRESS_LOSSLESS );
+ font->add_texture(t);
+
+ }
+ //register characters
+
+
+ for(int i=0;i<font_data_list.size();i++) {
+ _EditorFontData *fd=font_data_list[i];
+ int tex_idx=0;
+
+ font->add_char(fd->character,tex_idx,Rect2( fd->ofs_x, fd->ofs_y, fd->blit.get_width(), fd->blit.get_height()),Point2(fd->halign-fd->blit_ofs.x,fd->valign-fd->blit_ofs.y+top_space), fd->advance+char_space+(fd->character==' '?space_space:0));
+ memdelete(fd);
+ }
+
+ for(Map<_EditorKerningKey,int>::Element *E=kerning_map.front();E;E=E->next()) {
+
+ font->add_kerning_pair(E->key().A,E->key().B,E->get());
+ }
+
+ FT_Done_FreeType( library );
+
+ return font;
+#else
+
+ return Ref<BitmapFont>();
+#endif
+}
+
+
+String EditorFontImportPlugin::get_name() const {
+
+ return "font";
+}
+String EditorFontImportPlugin::get_visible_name() const{
+
+ return TTR("Font");
+}
+void EditorFontImportPlugin::import_dialog(const String& p_from){
+
+ dialog->popup_import(p_from);
+}
+Error EditorFontImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
+
+
+ Ref<BitmapFont> font = EditorFontImportPlugin::generate_font(p_from,p_path);
+ if (!font.is_valid())
+ return ERR_CANT_CREATE;
+
+ Ref<ResourceImportMetadata> from=p_from;
+ from->set_source_md5(0,FileAccess::get_md5(EditorImportPlugin::expand_source_path(from->get_source_path(0))));
+ from->set_editor(get_name());
+ font->set_import_metadata(from);
+
+ return ResourceSaver::save(p_path,font);
+
+}
+
+void EditorFontImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
+
+ for(int i=0;i<p_drop.size();i++) {
+ String ext = p_drop[i].get_extension().to_lower();
+ String file = p_drop[i].get_file();
+ if (ext=="ttf" || ext=="otf" || ext=="fnt") {
+
+ import_dialog();
+ dialog->set_source_and_dest(p_drop[i],p_dest_path.plus_file(file.get_basename()+".fnt"));
+ break;
+ }
+ }
+}
+
+
+EditorFontImportPlugin::EditorFontImportPlugin(EditorNode* p_editor) {
+
+ dialog = memnew( EditorFontImportDialog(this) );
+ p_editor->get_gui_base()->add_child(dialog);
+}
+#endif
diff --git a/editor/io_plugins/editor_font_import_plugin.h b/editor/io_plugins/editor_font_import_plugin.h
new file mode 100644
index 0000000000..315a80e8cd
--- /dev/null
+++ b/editor/io_plugins/editor_font_import_plugin.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* editor_font_import_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_FONT_IMPORT_PLUGIN_H
+#define EDITOR_FONT_IMPORT_PLUGIN_H
+
+#include "editor/editor_export.h"
+#include "scene/resources/font.h"
+#if 0
+class EditorNode;
+class EditorFontImportDialog;
+
+class EditorFontImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorFontImportPlugin,EditorImportPlugin);
+
+ EditorFontImportDialog *dialog;
+public:
+
+ Ref<BitmapFont> generate_font(const Ref<ResourceImportMetadata>& p_from,const String& p_existing=String()); //used by editor
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from="");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+ virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
+
+
+ EditorFontImportPlugin(EditorNode* p_editor);
+};
+
+#endif // EDITOR_FONT_IMPORT_PLUGIN_H
+#endif
diff --git a/editor/io_plugins/editor_mesh_import_plugin.cpp b/editor/io_plugins/editor_mesh_import_plugin.cpp
new file mode 100644
index 0000000000..df9d0a62e6
--- /dev/null
+++ b/editor/io_plugins/editor_mesh_import_plugin.cpp
@@ -0,0 +1,593 @@
+/*************************************************************************/
+/* editor_mesh_import_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_mesh_import_plugin.h"
+
+#if 0
+
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_dir_dialog.h"
+#include "editor/editor_node.h"
+#include "editor/property_editor.h"
+//#include "scene/resources/sample.h"
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "io/marshalls.h"
+#include "scene/resources/surface_tool.h"
+
+class _EditorMeshImportOptions : public Object {
+
+ GDCLASS(_EditorMeshImportOptions,Object);
+public:
+
+
+ bool generate_tangents;
+ bool generate_normals;
+ bool flip_faces;
+ bool smooth_shading;
+ bool weld_vertices;
+ bool import_material;
+ bool import_textures;
+ float weld_tolerance;
+
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ String n = p_name;
+ if (n=="generate/tangents")
+ generate_tangents=p_value;
+ else if (n=="generate/normals")
+ generate_normals=p_value;
+ else if (n=="import/materials")
+ import_material=p_value;
+ else if (n=="import/textures")
+ import_textures=p_value;
+ else if (n=="force/flip_faces")
+ flip_faces=p_value;
+ else if (n=="force/smooth_shading")
+ smooth_shading=p_value;
+ else if (n=="force/weld_vertices")
+ weld_vertices=p_value;
+ else if (n=="force/weld_tolerance")
+ weld_tolerance=p_value;
+ else
+ return false;
+
+ return true;
+
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const{
+
+ String n = p_name;
+ if (n=="generate/tangents")
+ r_ret=generate_tangents;
+ else if (n=="generate/normals")
+ r_ret=generate_normals;
+ else if (n=="import/materials")
+ r_ret=import_material;
+ else if (n=="import/textures")
+ r_ret=import_textures;
+ else if (n=="force/flip_faces")
+ r_ret=flip_faces;
+ else if (n=="force/smooth_shading")
+ r_ret=smooth_shading;
+ else if (n=="force/weld_vertices")
+ r_ret=weld_vertices;
+ else if (n=="force/weld_tolerance")
+ r_ret=weld_tolerance;
+ else
+ return false;
+
+ return true;
+
+ }
+ void _get_property_list( List<PropertyInfo> *p_list) const{
+
+ p_list->push_back(PropertyInfo(Variant::BOOL,"generate/tangents"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"generate/normals"));
+ //not for nowp
+ //p_list->push_back(PropertyInfo(Variant::BOOL,"import/materials"));
+ //p_list->push_back(PropertyInfo(Variant::BOOL,"import/textures"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"force/flip_faces"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"force/smooth_shading"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"force/weld_vertices"));
+ p_list->push_back(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001"));
+ //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable"));
+ //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
+
+
+ }
+
+
+ static void _bind_methods() {
+
+
+ ADD_SIGNAL( MethodInfo("changed"));
+ }
+
+
+ _EditorMeshImportOptions() {
+
+ generate_tangents=true;
+ generate_normals=false;
+ flip_faces=false;
+ smooth_shading=false;
+ weld_vertices=true;
+ weld_tolerance=0.0001;
+ import_material=false;
+ import_textures=false;
+
+ }
+
+
+};
+
+class EditorMeshImportDialog : public ConfirmationDialog {
+
+ GDCLASS(EditorMeshImportDialog,ConfirmationDialog);
+
+ EditorMeshImportPlugin *plugin;
+
+ LineEdit *import_path;
+ LineEdit *save_path;
+ EditorFileDialog *file_select;
+ EditorDirDialog *save_select;
+ AcceptDialog *error_dialog;
+ PropertyEditor *option_editor;
+
+ _EditorMeshImportOptions *options;
+
+
+public:
+
+ void _choose_files(const Vector<String>& p_path) {
+
+ String files;
+ for(int i=0;i<p_path.size();i++) {
+
+ if (i>0)
+ files+=",";
+ files+=p_path[i];
+ }
+ /*
+ if (p_path.size()) {
+ String srctex=p_path[0];
+ String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
+
+ if (ipath!="")
+ save_path->set_text(ipath.get_base_dir());
+ }*/
+ import_path->set_text(files);
+
+ }
+ void _choose_save_dir(const String& p_path) {
+
+ save_path->set_text(p_path);
+ }
+
+ void _browse() {
+
+ file_select->popup_centered_ratio();
+ }
+
+ void _browse_target() {
+
+ save_select->popup_centered_ratio();
+ }
+
+ void popup_import(const String& p_path) {
+
+ popup_centered(Size2(400,400)*EDSCALE);
+
+ if (p_path!="") {
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+ ERR_FAIL_COND(!rimd.is_valid());
+
+ save_path->set_text(p_path.get_base_dir());
+ List<String> opts;
+ rimd->get_options(&opts);
+ for(List<String>::Element *E=opts.front();E;E=E->next()) {
+
+ options->_set(E->get(),rimd->get_option(E->get()));
+ }
+
+ String src = "";
+ for(int i=0;i<rimd->get_source_count();i++) {
+ if (i>0)
+ src+=",";
+ src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
+ }
+ import_path->set_text(src);
+ }
+ }
+
+ void _import() {
+
+ Vector<String> meshes = import_path->get_text().split(",");
+ if (meshes.size()==0) {
+ error_dialog->set_text(TTR("No meshes to import!"));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ String dst = save_path->get_text();
+ if (dst=="") {
+ error_dialog->set_text(TTR("Save path is empty!"));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ for(int i=0;i<meshes.size();i++) {
+
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+
+ List<PropertyInfo> pl;
+ options->_get_property_list(&pl);
+ for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
+
+ Variant v;
+ String opt=E->get().name;
+ options->_get(opt,v);
+ imd->set_option(opt,v);
+
+ }
+
+ imd->add_source(EditorImportPlugin::validate_source_path(meshes[i]));
+
+ String file_path = dst.plus_file(meshes[i].get_file().get_basename()+".msh");
+
+ plugin->import(file_path,imd);
+ }
+
+ hide();
+ }
+
+ void _notification(int p_what) {
+
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ option_editor->edit(options);
+ }
+ }
+
+ static void _bind_methods() {
+
+ ClassDB::bind_method("_choose_files",&EditorMeshImportDialog::_choose_files);
+ ClassDB::bind_method("_choose_save_dir",&EditorMeshImportDialog::_choose_save_dir);
+ ClassDB::bind_method("_import",&EditorMeshImportDialog::_import);
+ ClassDB::bind_method("_browse",&EditorMeshImportDialog::_browse);
+ ClassDB::bind_method("_browse_target",&EditorMeshImportDialog::_browse_target);
+ }
+
+ EditorMeshImportDialog(EditorMeshImportPlugin *p_plugin) {
+
+ plugin=p_plugin;
+
+ set_title(TTR("Single Mesh Import"));
+ set_hide_on_ok(false);
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ //set_child_rect(vbc);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Source Mesh(es):"),hbc);
+
+ import_path = memnew( LineEdit );
+ import_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(import_path);
+
+ Button * import_choose = memnew( Button );
+ import_choose->set_text(" .. ");
+ hbc->add_child(import_choose);
+
+ import_choose->connect("pressed", this,"_browse");
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Target Path:"),hbc);
+
+ save_path = memnew( LineEdit );
+ save_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(save_path);
+
+ Button * save_choose = memnew( Button );
+ save_choose->set_text(" .. ");
+ hbc->add_child(save_choose);
+
+ save_choose->connect("pressed", this,"_browse_target");
+
+ file_select = memnew( EditorFileDialog );
+ file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+ file_select->add_filter("*.obj ; Wavefront OBJ");
+ add_child(file_select);
+ file_select->connect("files_selected", this,"_choose_files");
+
+ save_select = memnew( EditorDirDialog );
+ add_child(save_select);
+ save_select->connect("dir_selected", this,"_choose_save_dir");
+
+ get_ok()->connect("pressed", this,"_import");
+ get_ok()->set_text(TTR("Import"));
+
+ error_dialog = memnew( AcceptDialog );
+ add_child(error_dialog);
+
+ options = memnew( _EditorMeshImportOptions );
+
+ option_editor = memnew( PropertyEditor );
+ option_editor->hide_top_label();
+ vbc->add_margin_child(TTR("Options:"),option_editor,true);
+ }
+
+ ~EditorMeshImportDialog() {
+ memdelete(options);
+ }
+
+};
+
+
+String EditorMeshImportPlugin::get_name() const {
+
+ return "mesh";
+}
+String EditorMeshImportPlugin::get_visible_name() const{
+
+ return TTR("Mesh");
+}
+void EditorMeshImportPlugin::import_dialog(const String& p_from){
+
+ dialog->popup_import(p_from);
+}
+Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
+
+
+ ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER);
+
+ Ref<ResourceImportMetadata> from=p_from;
+
+ String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
+ FileAccessRef f = FileAccess::open(src_path,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
+
+ Ref<Mesh> mesh;
+ Map<String,Ref<Material> > name_map;
+
+ if (FileAccess::exists(p_path)) {
+ mesh=ResourceLoader::load(p_path,"Mesh");
+ if (mesh.is_valid()) {
+ for(int i=0;i<mesh->get_surface_count();i++) {
+
+ if (!mesh->surface_get_material(i).is_valid())
+ continue;
+ String name;
+ if (mesh->surface_get_name(i)!="")
+ name=mesh->surface_get_name(i);
+ else
+ name=vformat(TTR("Surface %d"),i+1);
+
+ name_map[name]=mesh->surface_get_material(i);
+ }
+
+ while(mesh->get_surface_count()) {
+ mesh->surface_remove(0);
+ }
+ }
+ }
+
+ if (!mesh.is_valid())
+ mesh = Ref<Mesh>( memnew( Mesh ) );
+
+
+ bool generate_normals=from->get_option("generate/normals");
+ bool generate_tangents=from->get_option("generate/tangents");
+ bool flip_faces=from->get_option("force/flip_faces");
+ bool force_smooth=from->get_option("force/smooth_shading");
+ bool weld_vertices=from->get_option("force/weld_vertices");
+ float weld_tolerance=from->get_option("force/weld_tolerance");
+ Vector<Vector3> vertices;
+ Vector<Vector3> normals;
+ Vector<Vector2> uvs;
+ String name;
+
+ Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ;
+ surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
+ if (force_smooth)
+ surf_tool->add_smooth_group(true);
+ int has_index_data=false;
+
+ while(true) {
+
+
+ String l = f->get_line().strip_edges();
+
+ if (l.begins_with("v ")) {
+ //vertex
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+ Vector3 vtx;
+ vtx.x=v[1].to_float();
+ vtx.y=v[2].to_float();
+ vtx.z=v[3].to_float();
+ vertices.push_back(vtx);
+ } else if (l.begins_with("vt ")) {
+ //uv
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
+ Vector2 uv;
+ uv.x=v[1].to_float();
+ uv.y=1.0-v[2].to_float();
+ uvs.push_back(uv);
+
+ } else if (l.begins_with("vn ")) {
+ //normal
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+ Vector3 nrm;
+ nrm.x=v[1].to_float();
+ nrm.y=v[2].to_float();
+ nrm.z=v[3].to_float();
+ normals.push_back(nrm);
+ } if (l.begins_with("f ")) {
+ //vertex
+
+ has_index_data=true;
+ Vector<String> v = l.split(" ",false);
+ ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
+
+ //not very fast, could be sped up
+
+
+ Vector<String> face[3];
+ face[0] = v[1].split("/");
+ face[1] = v[2].split("/");
+ ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR);
+ for(int i=2;i<v.size()-1;i++) {
+
+ face[2] = v[i+1].split("/");
+ ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR);
+ for(int j=0;j<3;j++) {
+
+ int idx=j;
+
+ if (!flip_faces && idx<2) {
+ idx=1^idx;
+ }
+
+
+ if (face[idx].size()==3) {
+ int norm = face[idx][2].to_int()-1;
+ ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR);
+ surf_tool->add_normal(normals[norm]);
+ }
+
+ if (face[idx].size()>=2 && face[idx][1]!=String()) {
+
+ int uv = face[idx][1].to_int()-1;
+ ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR);
+ surf_tool->add_uv(uvs[uv]);
+ }
+
+ int vtx = face[idx][0].to_int()-1;
+ ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR);
+
+ Vector3 vertex = vertices[vtx];
+ if (weld_vertices)
+ vertex=vertex.snapped(weld_tolerance);
+ surf_tool->add_vertex(vertex);
+ }
+
+ face[1]=face[2];
+ }
+ } else if (l.begins_with("s ") && !force_smooth) { //smoothing
+ String what = l.substr(2,l.length()).strip_edges();
+ if (what=="off")
+ surf_tool->add_smooth_group(false);
+ else
+ surf_tool->add_smooth_group(true);
+
+ } else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done
+
+ if (has_index_data) {
+ //new object/surface
+ if (generate_normals || force_smooth)
+ surf_tool->generate_normals();
+ if (uvs.size() && (normals.size() || generate_normals) && generate_tangents)
+ surf_tool->generate_tangents();
+
+ surf_tool->index();
+ mesh = surf_tool->commit(mesh);
+ if (name=="")
+ name=vformat(TTR("Surface %d"),mesh->get_surface_count()-1);
+ mesh->surface_set_name(mesh->get_surface_count()-1,name);
+ name="";
+ surf_tool->clear();
+ surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
+ if (force_smooth)
+ surf_tool->add_smooth_group(true);
+
+ has_index_data=false;
+
+ if (f->eof_reached())
+ break;
+ }
+
+ if (l.begins_with("o ")) //name
+ name=l.substr(2,l.length()).strip_edges();
+ }
+ }
+
+
+ from->set_source_md5(0,FileAccess::get_md5(src_path));
+ from->set_editor(get_name());
+ mesh->set_import_metadata(from);
+
+ //re-apply materials if exist
+ for(int i=0;i<mesh->get_surface_count();i++) {
+
+ String n = mesh->surface_get_name(i);
+ if (name_map.has(n))
+ mesh->surface_set_material(i,name_map[n]);
+ }
+
+ Error err = ResourceSaver::save(p_path,mesh);
+
+ return err;
+}
+
+
+void EditorMeshImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
+
+
+ Vector<String> files;
+ for(int i=0;i<p_drop.size();i++) {
+ String ext = p_drop[i].get_extension().to_lower();
+ String file = p_drop[i].get_file();
+ if (ext=="obj") {
+
+ files.push_back(p_drop[i]);
+ }
+ }
+
+ if (files.size()) {
+ import_dialog();
+ dialog->_choose_files(files);
+ dialog->_choose_save_dir(p_dest_path);
+ }
+}
+
+EditorMeshImportPlugin::EditorMeshImportPlugin(EditorNode* p_editor) {
+
+ dialog = memnew( EditorMeshImportDialog(this));
+ p_editor->get_gui_base()->add_child(dialog);
+}
+#endif
diff --git a/editor/io_plugins/editor_mesh_import_plugin.h b/editor/io_plugins/editor_mesh_import_plugin.h
new file mode 100644
index 0000000000..df374549d4
--- /dev/null
+++ b/editor/io_plugins/editor_mesh_import_plugin.h
@@ -0,0 +1,59 @@
+/*************************************************************************/
+/* editor_mesh_import_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_MESH_IMPORT_PLUGIN_H
+#define EDITOR_MESH_IMPORT_PLUGIN_H
+
+#if 0
+#include "editor/editor_import_export.h"
+#include "scene/resources/font.h"
+
+class EditorNode;
+class EditorMeshImportDialog;
+
+class EditorMeshImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorMeshImportPlugin,EditorImportPlugin);
+
+ EditorMeshImportDialog *dialog;
+
+
+public:
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from="");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+ void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
+
+
+ EditorMeshImportPlugin(EditorNode* p_editor);
+};
+
+#endif
+#endif // EDITOR_MESH_IMPORT_PLUGIN_H
diff --git a/editor/io_plugins/editor_sample_import_plugin.cpp b/editor/io_plugins/editor_sample_import_plugin.cpp
new file mode 100644
index 0000000000..d446d39027
--- /dev/null
+++ b/editor/io_plugins/editor_sample_import_plugin.cpp
@@ -0,0 +1,929 @@
+/*************************************************************************/
+/* editor_sample_import_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_sample_import_plugin.h"
+
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_dir_dialog.h"
+#include "editor/editor_node.h"
+#include "editor/property_editor.h"
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "io/marshalls.h"
+#include "editor/editor_settings.h"
+
+#if 0
+
+class _EditorSampleImportOptions : public Object {
+
+ GDCLASS(_EditorSampleImportOptions,Object);
+public:
+
+ enum CompressMode {
+ COMPRESS_MODE_DISABLED,
+ COMPRESS_MODE_RAM,
+ COMPRESS_MODE_DISK
+ };
+
+ enum CompressBitrate {
+ COMPRESS_64,
+ COMPRESS_96,
+ COMPRESS_128,
+ COMPRESS_192
+ };
+
+ bool force_8_bit;
+ bool force_mono;
+ bool force_rate;
+ float force_rate_hz;
+
+ bool edit_trim;
+ bool edit_normalize;
+ bool edit_loop;
+
+ CompressMode compress_mode;
+ CompressBitrate compress_bitrate;
+
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ String n = p_name;
+ if (n=="force/8_bit")
+ force_8_bit=p_value;
+ else if (n=="force/mono")
+ force_mono=p_value;
+ else if (n=="force/max_rate")
+ force_rate=p_value;
+ else if (n=="force/max_rate_hz")
+ force_rate_hz=p_value;
+ else if (n=="edit/trim")
+ edit_trim=p_value;
+ else if (n=="edit/normalize")
+ edit_normalize=p_value;
+ else if (n=="edit/loop")
+ edit_loop=p_value;
+ else if (n=="compress/mode")
+ compress_mode=CompressMode(int(p_value));
+ else if (n=="compress/bitrate")
+ compress_bitrate=CompressBitrate(int(p_value));
+ else
+ return false;
+
+ return true;
+
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const{
+
+ String n = p_name;
+ if (n=="force/8_bit")
+ r_ret=force_8_bit;
+ else if (n=="force/mono")
+ r_ret=force_mono;
+ else if (n=="force/max_rate")
+ r_ret=force_rate;
+ else if (n=="force/max_rate_hz")
+ r_ret=force_rate_hz;
+ else if (n=="edit/trim")
+ r_ret=edit_trim;
+ else if (n=="edit/normalize")
+ r_ret=edit_normalize;
+ else if (n=="edit/loop")
+ r_ret=edit_loop;
+ else if (n=="compress/mode")
+ r_ret=compress_mode;
+ else if (n=="compress/bitrate")
+ r_ret=compress_bitrate;
+ else
+ return false;
+
+ return true;
+
+ }
+ void _get_property_list( List<PropertyInfo> *p_list) const{
+
+ p_list->push_back(PropertyInfo(Variant::BOOL,"force/8_bit"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"force/mono"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"force/max_rate"));
+ p_list->push_back(PropertyInfo(Variant::REAL,"force/max_rate_hz",PROPERTY_HINT_EXP_RANGE,"11025,192000,1"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"edit/trim"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"edit/normalize"));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"edit/loop"));
+ p_list->push_back(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)"));
+ //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
+
+
+ }
+
+
+ static void _bind_methods() {
+
+
+ ADD_SIGNAL( MethodInfo("changed"));
+ }
+
+
+ _EditorSampleImportOptions() {
+
+ force_8_bit=false;
+ force_mono=false;
+ force_rate=true;
+ force_rate_hz=44100;
+
+ edit_trim=true;
+ edit_normalize=true;
+ edit_loop=false;
+
+ compress_mode=COMPRESS_MODE_RAM;
+ compress_bitrate=COMPRESS_128;
+ }
+
+
+};
+
+class EditorSampleImportDialog : public ConfirmationDialog {
+
+ GDCLASS(EditorSampleImportDialog,ConfirmationDialog);
+
+ EditorSampleImportPlugin *plugin;
+
+ LineEdit *import_path;
+ LineEdit *save_path;
+ EditorFileDialog *file_select;
+ EditorDirDialog *save_select;
+ ConfirmationDialog *error_dialog;
+ PropertyEditor *option_editor;
+
+ _EditorSampleImportOptions *options;
+
+
+public:
+
+ void _choose_files(const Vector<String>& p_path) {
+
+ String files;
+ for(int i=0;i<p_path.size();i++) {
+
+ if (i>0)
+ files+=",";
+ files+=p_path[i];
+ }
+ /*
+ if (p_path.size()) {
+ String srctex=p_path[0];
+ String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
+
+ if (ipath!="")
+ save_path->set_text(ipath.get_base_dir());
+ }*/
+ import_path->set_text(files);
+
+ }
+ void _choose_save_dir(const String& p_path) {
+
+ save_path->set_text(p_path);
+ }
+
+ void _browse() {
+
+ file_select->popup_centered_ratio();
+ }
+
+ void _browse_target() {
+
+ save_select->popup_centered_ratio();
+
+ }
+
+
+ void popup_import(const String& p_path) {
+
+ popup_centered(Size2(400,400)*EDSCALE);
+ if (p_path!="") {
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+ ERR_FAIL_COND(!rimd.is_valid());
+
+ save_path->set_text(p_path.get_base_dir());
+ List<String> opts;
+ rimd->get_options(&opts);
+ for(List<String>::Element *E=opts.front();E;E=E->next()) {
+
+ options->_set(E->get(),rimd->get_option(E->get()));
+ }
+
+ String src = "";
+ for(int i=0;i<rimd->get_source_count();i++) {
+ if (i>0)
+ src+=",";
+ src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
+ }
+ import_path->set_text(src);
+ }
+ }
+
+
+ void _import() {
+
+ Vector<String> samples = import_path->get_text().split(",");
+
+ if (samples.size()==0) {
+ error_dialog->set_text(TTR("No samples to import!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ }
+
+ if (save_path->get_text().strip_edges()=="") {
+ error_dialog->set_text(TTR("Target path is empty."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (!save_path->get_text().begins_with("res://")) {
+ error_dialog->set_text(TTR("Target path must be a complete resource path."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (!DirAccess::exists(save_path->get_text())) {
+ error_dialog->set_text(TTR("Target path must exist."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ for(int i=0;i<samples.size();i++) {
+
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+
+ List<PropertyInfo> pl;
+ options->_get_property_list(&pl);
+ for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
+
+ Variant v;
+ String opt=E->get().name;
+ options->_get(opt,v);
+ imd->set_option(opt,v);
+
+ }
+
+ imd->add_source(EditorImportPlugin::validate_source_path(samples[i]));
+
+ String dst = save_path->get_text();
+ if (dst=="") {
+ error_dialog->set_text(TTR("Save path is empty!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ }
+
+ dst = dst.plus_file(samples[i].get_file().get_basename()+".smp");
+
+ plugin->import(dst,imd);
+ }
+
+ hide();
+
+ }
+
+
+ void _notification(int p_what) {
+
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ option_editor->edit(options);
+ }
+ }
+
+ static void _bind_methods() {
+
+
+ ClassDB::bind_method("_choose_files",&EditorSampleImportDialog::_choose_files);
+ ClassDB::bind_method("_choose_save_dir",&EditorSampleImportDialog::_choose_save_dir);
+ ClassDB::bind_method("_import",&EditorSampleImportDialog::_import);
+ ClassDB::bind_method("_browse",&EditorSampleImportDialog::_browse);
+ ClassDB::bind_method("_browse_target",&EditorSampleImportDialog::_browse_target);
+ //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
+ }
+
+ EditorSampleImportDialog(EditorSampleImportPlugin *p_plugin) {
+
+ plugin=p_plugin;
+
+
+ set_title(TTR("Import Audio Samples"));
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ //set_child_rect(vbc);
+
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Source Sample(s):"),hbc);
+
+ import_path = memnew( LineEdit );
+ import_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(import_path);
+
+ Button * import_choose = memnew( Button );
+ import_choose->set_text(" .. ");
+ hbc->add_child(import_choose);
+
+ import_choose->connect("pressed", this,"_browse");
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Target Path:"),hbc);
+
+ save_path = memnew( LineEdit );
+ save_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(save_path);
+
+ Button * save_choose = memnew( Button );
+ save_choose->set_text(" .. ");
+ hbc->add_child(save_choose);
+
+ save_choose->connect("pressed", this,"_browse_target");
+
+ file_select = memnew(EditorFileDialog);
+ file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ add_child(file_select);
+ file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+ file_select->connect("files_selected", this,"_choose_files");
+ file_select->add_filter("*.wav ; MS Waveform");
+ save_select = memnew( EditorDirDialog );
+ add_child(save_select);
+
+ //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
+ save_select->connect("dir_selected", this,"_choose_save_dir");
+
+ get_ok()->connect("pressed", this,"_import");
+ get_ok()->set_text(TTR("Import"));
+
+
+ error_dialog = memnew ( ConfirmationDialog );
+ add_child(error_dialog);
+ error_dialog->get_ok()->set_text(TTR("Accept"));
+ //error_dialog->get_cancel()->hide();
+
+ set_hide_on_ok(false);
+ options = memnew( _EditorSampleImportOptions );
+
+ option_editor = memnew( PropertyEditor );
+ option_editor->hide_top_label();
+ vbc->add_margin_child(TTR("Options:"),option_editor,true);
+ }
+
+ ~EditorSampleImportDialog() {
+ memdelete(options);
+ }
+
+};
+
+
+String EditorSampleImportPlugin::get_name() const {
+
+ return "sample";
+}
+String EditorSampleImportPlugin::get_visible_name() const{
+
+ return TTR("Audio Sample");
+}
+void EditorSampleImportPlugin::import_dialog(const String& p_from){
+
+ dialog->popup_import(p_from);
+}
+Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
+
+ ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER);
+
+ Ref<ResourceImportMetadata> from=p_from;
+
+ String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
+ Ref<Sample> smp = ResourceLoader::load(src_path);
+ ERR_FAIL_COND_V(smp.is_null(),ERR_CANT_OPEN);
+
+
+ float rate = smp->get_mix_rate();
+ bool is16 = smp->get_format()==Sample::FORMAT_PCM16;
+ int chans = smp->is_stereo()?2:1;
+ int len = smp->get_length();
+ Sample::LoopFormat loop= smp->get_loop_format();
+ int loop_beg = smp->get_loop_begin();
+ int loop_end = smp->get_loop_end();
+
+ print_line("Input Sample: ");
+ print_line("\tlen: "+itos(len));
+ print_line("\tchans: "+itos(chans));
+ print_line("\t16bits: "+itos(is16));
+ print_line("\trate: "+itos(rate));
+ print_line("\tloop: "+itos(loop));
+ print_line("\tloop begin: "+itos(loop_beg));
+ print_line("\tloop end: "+itos(loop_end));
+ Vector<float> data;
+ data.resize(len*chans);
+
+ {
+ PoolVector<uint8_t> src_data = smp->get_data();
+ PoolVector<uint8_t>::Read sr = src_data.read();
+
+
+ for(int i=0;i<len*chans;i++) {
+
+ float s=0;
+ if (is16) {
+
+ int16_t i16 = decode_uint16(&sr[i*2]);
+ s=i16/32767.0;
+ } else {
+
+ int8_t i8 = sr[i];
+ s=i8/127.0;
+ }
+ data[i]=s;
+ }
+ }
+
+ //apply frequency limit
+
+ bool limit_rate = from->get_option("force/max_rate");
+ int limit_rate_hz = from->get_option("force/max_rate_hz");
+ if (limit_rate && rate > limit_rate_hz) {
+ //resampleeee!!!
+ int new_data_len = len * limit_rate_hz / rate;
+ Vector<float> new_data;
+ new_data.resize( new_data_len * chans );
+ for(int c=0;c<chans;c++) {
+
+ for(int i=0;i<new_data_len;i++) {
+
+ //simple cubic interpolation should be enough.
+ float pos = float(i) * len / new_data_len;
+ float mu = pos-Math::floor(pos);
+ int ipos = int(Math::floor(pos));
+
+ float y0=data[MAX(0,ipos-1)*chans+c];
+ float y1=data[ipos*chans+c];
+ float y2=data[MIN(len-1,ipos+1)*chans+c];
+ float y3=data[MIN(len-1,ipos+2)*chans+c];
+
+ float mu2 = mu*mu;
+ float a0 = y3 - y2 - y0 + y1;
+ float a1 = y0 - y1 - a0;
+ float a2 = y2 - y0;
+ float a3 = y1;
+
+ float res=(a0*mu*mu2+a1*mu2+a2*mu+a3);
+
+ new_data[i*chans+c]=res;
+ }
+ }
+
+ if (loop) {
+
+ loop_beg=loop_beg*new_data_len/len;
+ loop_end=loop_end*new_data_len/len;
+ }
+ data=new_data;
+ rate=limit_rate_hz;
+ len=new_data_len;
+ }
+
+
+ bool normalize = from->get_option("edit/normalize");
+
+ if (normalize) {
+
+ float max=0;
+ for(int i=0;i<data.size();i++) {
+
+ float amp = Math::abs(data[i]);
+ if (amp>max)
+ max=amp;
+ }
+
+ if (max>0) {
+
+ float mult=1.0/max;
+ for(int i=0;i<data.size();i++) {
+
+ data[i]*=mult;
+ }
+
+ }
+ }
+
+ bool trim = from->get_option("edit/trim");
+
+ if (trim && !loop) {
+
+ int first=0;
+ int last=(len*chans)-1;
+ bool found=false;
+ float limit = Math::db2linear((float)-30);
+ for(int i=0;i<data.size();i++) {
+ float amp = Math::abs(data[i]);
+
+ if (!found && amp > limit) {
+ first=i;
+ found=true;
+ }
+
+ if (found && amp > limit) {
+ last=i;
+ }
+ }
+
+ first/=chans;
+ last/=chans;
+
+ if (first<last) {
+
+ Vector<float> new_data;
+ new_data.resize((last-first+1)*chans);
+ for(int i=first*chans;i<=last*chans;i++) {
+ new_data[i-first*chans]=data[i];
+ }
+
+ data=new_data;
+ len=data.size()/chans;
+ }
+
+ }
+
+ bool make_loop = from->get_option("edit/loop");
+
+ if (make_loop && !loop) {
+
+ loop=Sample::LOOP_FORWARD;
+ loop_beg=0;
+ loop_end=len;
+ }
+
+ int compression = from->get_option("compress/mode");
+ bool force_mono = from->get_option("force/mono");
+
+
+ if (force_mono && chans==2) {
+
+ Vector<float> new_data;
+ new_data.resize(data.size()/2);
+ for(int i=0;i<len;i++) {
+ new_data[i]=(data[i*2+0]+data[i*2+1])/2.0;
+ }
+
+ data=new_data;
+ chans=1;
+ }
+
+ bool force_8_bit = from->get_option("force/8_bit");
+ if (force_8_bit) {
+
+ is16=false;
+ }
+
+
+ PoolVector<uint8_t> dst_data;
+ Sample::Format dst_format;
+
+ if ( compression == _EditorSampleImportOptions::COMPRESS_MODE_RAM) {
+
+ dst_format=Sample::FORMAT_IMA_ADPCM;
+ if (chans==1) {
+ _compress_ima_adpcm(data,dst_data);
+ } else {
+
+ print_line("INTERLEAAVE!");
+
+
+
+ //byte interleave
+ Vector<float> left;
+ Vector<float> right;
+
+ int tlen = data.size()/2;
+ left.resize(tlen);
+ right.resize(tlen);
+
+ for(int i=0;i<tlen;i++) {
+ left[i]=data[i*2+0];
+ right[i]=data[i*2+1];
+ }
+
+ PoolVector<uint8_t> bleft;
+ PoolVector<uint8_t> bright;
+
+ _compress_ima_adpcm(left,bleft);
+ _compress_ima_adpcm(right,bright);
+
+ int dl = bleft.size();
+ dst_data.resize( dl *2 );
+
+ PoolVector<uint8_t>::Write w=dst_data.write();
+ PoolVector<uint8_t>::Read rl=bleft.read();
+ PoolVector<uint8_t>::Read rr=bright.read();
+
+ for(int i=0;i<dl;i++) {
+ w[i*2+0]=rl[i];
+ w[i*2+1]=rr[i];
+ }
+ }
+
+ //print_line("compressing ima-adpcm, resulting buffersize is "+itos(dst_data.size())+" from "+itos(data.size()));
+
+ } else {
+
+ dst_format=is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8;
+ dst_data.resize( data.size() * (is16?2:1));
+ {
+ PoolVector<uint8_t>::Write w = dst_data.write();
+
+ int ds=data.size();
+ for(int i=0;i<ds;i++) {
+
+ if (is16) {
+ int16_t v = CLAMP(data[i]*32767,-32768,32767);
+ encode_uint16(v,&w[i*2]);
+ } else {
+ int8_t v = CLAMP(data[i]*127,-128,127);
+ w[i]=v;
+ }
+ }
+ }
+ }
+
+
+ Ref<Sample> target;
+
+ if (ResourceCache::has(p_path)) {
+
+ target = Ref<Sample>( ResourceCache::get(p_path)->cast_to<Sample>() );
+ } else {
+
+ target = smp;
+ }
+
+ target->create(dst_format,chans==2?true:false,len);
+ target->set_data(dst_data);
+ target->set_mix_rate(rate);
+ target->set_loop_format(loop);
+ target->set_loop_begin(loop_beg);
+ target->set_loop_end(loop_end);
+
+ from->set_source_md5(0,FileAccess::get_md5(src_path));
+ from->set_editor(get_name());
+ target->set_import_metadata(from);
+
+
+ Error err = ResourceSaver::save(p_path,smp);
+
+ return err;
+
+}
+
+void EditorSampleImportPlugin::_compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data) {
+
+
+ /*p_sample_data->data = (void*)malloc(len);
+ xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/
+
+ static const int16_t _ima_adpcm_step_table[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+ };
+
+ static const int8_t _ima_adpcm_index_table[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+ };
+
+
+ int datalen = p_data.size();
+ int datamax=datalen;
+ if (datalen&1)
+ datalen++;
+
+ dst_data.resize(datalen/2+4);
+ PoolVector<uint8_t>::Write w = dst_data.write();
+
+
+ int i,step_idx=0,prev=0;
+ uint8_t *out = w.ptr();
+ //int16_t xm_prev=0;
+ const float *in=p_data.ptr();
+
+
+ /* initial value is zero */
+ *(out++) =0;
+ *(out++) =0;
+ /* Table index initial value */
+ *(out++) =0;
+ /* unused */
+ *(out++) =0;
+
+ for (i=0;i<datalen;i++) {
+ int step,diff,vpdiff,mask;
+ uint8_t nibble;
+ int16_t xm_sample;
+
+ if (i>=datamax)
+ xm_sample=0;
+ else {
+
+
+ xm_sample=CLAMP(in[i]*32767.0,-32768,32767);
+ /*
+ if (xm_sample==32767 || xm_sample==-32768)
+ printf("clippy!\n",xm_sample);
+ */
+ }
+
+ //xm_sample=xm_sample+xm_prev;
+ //xm_prev=xm_sample;
+
+ diff = (int)xm_sample - prev ;
+
+ nibble=0 ;
+ step = _ima_adpcm_step_table[ step_idx ];
+ vpdiff = step >> 3 ;
+ if (diff < 0) {
+ nibble=8;
+ diff=-diff ;
+ }
+ mask = 4 ;
+ while (mask) {
+
+ if (diff >= step) {
+
+ nibble |= mask;
+ diff -= step;
+ vpdiff += step;
+ }
+
+ step >>= 1 ;
+ mask >>= 1 ;
+ };
+
+ if (nibble&8)
+ prev-=vpdiff ;
+ else
+ prev+=vpdiff ;
+
+ if (prev > 32767) {
+ //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev);
+ prev=32767;
+ } else if (prev < -32768) {
+ //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev);
+ prev = -32768 ;
+ }
+
+ step_idx += _ima_adpcm_index_table[nibble];
+ if (step_idx< 0)
+ step_idx= 0 ;
+ else if (step_idx> 88)
+ step_idx= 88 ;
+
+
+ if (i&1) {
+ *out|=nibble<<4;
+ out++;
+ } else {
+ *out=nibble;
+ }
+ /*dataptr[i]=prev>>8;*/
+ }
+
+}
+
+
+EditorSampleImportPlugin* EditorSampleImportPlugin::singleton=NULL;
+
+
+void EditorSampleImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
+
+
+ Vector<String> files;
+ for(int i=0;i<p_drop.size();i++) {
+ String ext = p_drop[i].get_extension().to_lower();
+
+ if (ext=="wav") {
+
+ files.push_back(p_drop[i]);
+ }
+ }
+
+ if (files.size()) {
+ import_dialog();
+ dialog->_choose_files(files);
+ dialog->_choose_save_dir(p_dest_path);
+ }
+}
+
+void EditorSampleImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
+
+ if (p_list.size()==0)
+ return;
+
+ Vector<String> sources;
+ for(int i=0;i<p_list.size();i++) {
+ int idx;
+ EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i],&idx);
+ if (efsd) {
+ for(int j=0;j<efsd->get_source_count(idx);j++) {
+ String file = expand_source_path(efsd->get_source_file(idx,j));
+ if (sources.find(file)==-1) {
+ sources.push_back(file);
+ }
+
+ }
+ }
+ }
+
+ if (sources.size()) {
+
+ dialog->popup_import(p_list[0]);
+ dialog->_choose_files(sources);
+ dialog->_choose_save_dir(p_list[0].get_base_dir());
+ }
+}
+
+bool EditorSampleImportPlugin::can_reimport_multiple_files() const {
+
+ return true;
+}
+
+EditorSampleImportPlugin::EditorSampleImportPlugin(EditorNode* p_editor) {
+
+ singleton=this;
+ dialog = memnew( EditorSampleImportDialog(this));
+ p_editor->get_gui_base()->add_child(dialog);
+}
+
+Vector<uint8_t> EditorSampleExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
+
+
+
+ if (EditorImportExport::get_singleton()->sample_get_action()==EditorImportExport::SAMPLE_ACTION_NONE || p_path.get_extension().to_lower()!="wav") {
+
+ return Vector<uint8_t>();
+ }
+
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+
+ imd->add_source(EditorImportPlugin::validate_source_path(p_path));
+
+ imd->set_option("force/8_bit",false);
+ imd->set_option("force/mono",false);
+ imd->set_option("force/max_rate",true);
+ imd->set_option("force/max_rate_hz",EditorImportExport::get_singleton()->sample_get_max_hz());
+ imd->set_option("edit/trim",EditorImportExport::get_singleton()->sample_get_trim());
+ imd->set_option("edit/normalize",false);
+ imd->set_option("edit/loop",false);
+ imd->set_option("compress/mode",1);
+
+ String savepath = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/smpconv.smp");
+ Error err = EditorSampleImportPlugin::singleton->import(savepath,imd);
+
+
+ ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
+
+ p_path=p_path.get_basename()+".converted.smp";
+ return FileAccess::get_file_as_array(savepath);
+
+}
+
+
+
+EditorSampleExportPlugin::EditorSampleExportPlugin() {
+
+}
+
+#endif
diff --git a/editor/io_plugins/editor_sample_import_plugin.h b/editor/io_plugins/editor_sample_import_plugin.h
new file mode 100644
index 0000000000..6085043a83
--- /dev/null
+++ b/editor/io_plugins/editor_sample_import_plugin.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* editor_sample_import_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_SAMPLE_IMPORT_PLUGIN_H
+#define EDITOR_SAMPLE_IMPORT_PLUGIN_H
+
+#if 0
+#include "editor/editor_import_export.h"
+#include "scene/resources/font.h"
+
+class EditorNode;
+class EditorSampleImportDialog;
+
+class EditorSampleImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorSampleImportPlugin,EditorImportPlugin);
+
+ EditorSampleImportDialog *dialog;
+ void _compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data);
+public:
+
+ static EditorSampleImportPlugin *singleton;
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from="");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+ void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
+ virtual void reimport_multiple_files(const Vector<String>& p_list);
+ virtual bool can_reimport_multiple_files() const;
+
+
+ EditorSampleImportPlugin(EditorNode* p_editor);
+};
+
+class EditorSampleExportPlugin : public EditorExportPlugin {
+
+ GDCLASS( EditorSampleExportPlugin, EditorExportPlugin);
+
+
+public:
+
+ virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
+
+ EditorSampleExportPlugin();
+};
+
+#endif // EDITOR_SAMPLE_IMPORT_PLUGIN_H
+#endif
diff --git a/editor/io_plugins/editor_scene_import_plugin.cpp b/editor/io_plugins/editor_scene_import_plugin.cpp
new file mode 100644
index 0000000000..963968ce47
--- /dev/null
+++ b/editor/io_plugins/editor_scene_import_plugin.cpp
@@ -0,0 +1,2992 @@
+/*************************************************************************/
+/* editor_scene_import_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_scene_import_plugin.h"
+#if 0
+#include "global_config.h"
+#include "editor/editor_node.h"
+#include "scene/resources/packed_scene.h"
+#include "scene/resources/box_shape.h"
+#include "os/file_access.h"
+#include "scene/3d/path.h"
+#include "scene/animation/animation_player.h"
+#include "io/resource_saver.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/navigation.h"
+#include "scene/3d/room_instance.h"
+#include "scene/3d/body_shape.h"
+#include "scene/3d/physics_body.h"
+#include "scene/3d/portal.h"
+#include "scene/3d/vehicle_body.h"
+#include "scene/resources/sphere_shape.h"
+#include <scene/resources/box_shape.h>
+#include <scene/resources/ray_shape.h>
+#include <scene/resources/plane_shape.h>
+#include "editor/create_dialog.h"
+#include "os/os.h"
+
+
+
+
+EditorSceneImporter::EditorSceneImporter() {
+
+
+}
+
+void EditorScenePostImport::_bind_methods() {
+
+ BIND_VMETHOD( MethodInfo("post_import",PropertyInfo(Variant::OBJECT,"scene")) );
+
+}
+
+Node *EditorScenePostImport::post_import(Node* p_scene) {
+
+ if (get_script_instance())
+ return get_script_instance()->call("post_import",p_scene);
+
+ return p_scene;
+}
+
+EditorScenePostImport::EditorScenePostImport() {
+
+
+}
+
+
+/////////////////////////////
+
+
+class EditorImportAnimationOptions : public VBoxContainer {
+
+ GDCLASS( EditorImportAnimationOptions, VBoxContainer );
+
+
+
+ TreeItem *fps;
+ TreeItem* optimize_linear_error;
+ TreeItem* optimize_angular_error;
+ TreeItem* optimize_max_angle;
+
+ TreeItem *clips_base;
+
+ TextEdit *filters;
+ Vector<TreeItem*> clips;
+
+ Tree *flags;
+ Tree *clips_tree;
+ Tree *optimization_tree;
+ Vector<TreeItem*> items;
+
+
+ bool updating;
+ bool validating;
+
+
+
+ void _changed();
+ void _item_edited();
+ void _button_action(Object *p_obj,int p_col,int p_id);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+
+ void set_flags(uint32_t p_flags);
+ uint32_t get_flags() const;
+
+ void set_fps(int p_fps);
+ int get_fps() const;
+
+ void set_optimize_linear_error(float p_error);
+ float get_optimize_linear_error() const;
+
+ void set_optimize_angular_error(float p_error);
+ float get_optimize_angular_error() const;
+
+ void set_optimize_max_angle(float p_error);
+ float get_optimize_max_angle() const;
+
+ void setup_clips(const Array& p_clips);
+ Array get_clips() const;
+
+ void set_filter(const String& p_filter);
+ String get_filter() const;
+
+ EditorImportAnimationOptions();
+
+
+};
+
+////////////////////////////
+
+class EditorSceneImportDialog : public ConfirmationDialog {
+
+ GDCLASS(EditorSceneImportDialog,ConfirmationDialog);
+
+
+ struct FlagInfo {
+ int value;
+ const char *category;
+ const char *text;
+ bool defval;
+ };
+
+ static const FlagInfo scene_flag_names[];
+
+ EditorImportTextureOptions *texture_options;
+ EditorImportAnimationOptions *animation_options;
+
+ EditorSceneImportPlugin *plugin;
+
+ EditorNode *editor;
+
+ LineEdit *import_path;
+ LineEdit *save_path;
+ LineEdit *script_path;
+ Tree *import_options;
+ EditorFileDialog *file_select;
+ EditorFileDialog *script_select;
+ EditorDirDialog *save_select;
+ OptionButton *texture_action;
+ CreateDialog *root_type_choose;
+ LineEdit *root_node_name;
+
+ ConfirmationDialog *confirm_open;
+
+ ConfirmationDialog *confirm_import;
+ RichTextLabel *missing_files;
+
+ Vector<TreeItem*> scene_flags;
+
+ Map<Ref<Mesh>,Ref<Shape> > collision_map;
+ ConfirmationDialog *error_dialog;
+
+ Button *root_type;
+ CheckBox *root_default;
+
+
+ void _root_default_pressed();
+ void _root_type_pressed();
+ void _set_root_type();
+
+ void _choose_file(const String& p_path);
+ void _choose_save_file(const String& p_path);
+ void _choose_script(const String& p_path);
+ void _browse();
+ void _browse_target();
+ void _browse_script();
+ void _import(bool p_and_open=false);
+ void _import_confirm();
+
+ Ref<ResourceImportMetadata> wip_rimd;
+ Node *wip_import;
+ String wip_save_file;
+ bool wip_blocked;
+ bool wip_open;
+
+ void _dialog_hid();
+ void _open_and_import();
+
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void setup_popup(const String& p_from,const String& p_to_path) {
+ _choose_file(p_from);
+ _choose_save_file(p_to_path);
+ }
+
+ Error import(const String& p_from, const String& p_to, const String& p_preset);
+ void popup_import(const String& p_from);
+ EditorSceneImportDialog(EditorNode *p_editor,EditorSceneImportPlugin *p_plugin);
+};
+
+///////////////////////////////////
+
+
+static const char *anim_flag_names[]={
+ "Detect Loop (-loop,-cycle)",
+ "Keep Value Tracks",
+ "Optimize",
+ "Force All Tracks in All Clips",
+ NULL
+};
+
+static const char *anim_flag_descript[]={
+ "Set loop flag for animation names that\ncontain 'cycle' or 'loop' in the name.",
+ "When merging an existing aimation,\nkeep the user-created value-tracks.",
+ "Remove redundant keyframes in\n transform tacks.",
+ "Some exporters will rely on default pose for some bones.\nThis forces those bones to have at least one animation key.",
+ NULL
+};
+
+
+
+void EditorImportAnimationOptions::set_flags(uint32_t p_flags){
+
+ updating=true;
+ for(int i=0;i<items.size();i++) {
+
+ items[i]->set_checked(0,p_flags&(1<<i));
+ }
+ updating=false;
+
+}
+uint32_t EditorImportAnimationOptions::get_flags() const{
+
+ uint32_t f=0;
+ for(int i=0;i<items.size();i++) {
+
+ if (items[i]->is_checked(0))
+ f|=(1<<i);
+ }
+
+ return f;
+}
+
+
+void EditorImportAnimationOptions::_changed() {
+
+ if (updating)
+ return;
+ emit_signal("changed");
+}
+
+
+void EditorImportAnimationOptions::_button_action(Object *p_obj,int p_col,int p_id) {
+
+ memdelete(p_obj);
+
+}
+
+
+void EditorImportAnimationOptions::_item_edited() {
+
+ if (validating)
+ return;
+
+ if (clips.size()==0)
+ return;
+ validating=true;
+ print_line("edited");
+ TreeItem *item = clips_tree->get_edited();
+ if (item==clips[clips.size()-1]) {
+ //add new
+ print_line("islast");
+ if (item->get_text(0).find("<")!=-1 || item->get_text(0).find(">")!=-1) {
+ validating=false;
+ return; //fuckit
+ }
+
+ item->set_editable(1,true);
+ item->set_editable(2,true);
+ item->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons"));
+ item->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ item->set_range_config(1,0,3600,0.01);
+ item->set_range(1,0);
+ item->set_editable(1,true);
+ item->set_cell_mode(2,TreeItem::CELL_MODE_RANGE);
+ item->set_range_config(2,0,3600,0.01);
+ item->set_range(2,0);
+ item->set_cell_mode(3,TreeItem::CELL_MODE_CHECK);
+ item->set_editable(3,true);
+
+ TreeItem *newclip = clips_tree->create_item(clips_base);
+ newclip->set_text(0,"<new clip>");
+ newclip->set_editable(0,true);
+ newclip->set_editable(1,false);
+ newclip->set_editable(2,false);
+ clips.push_back(newclip);
+
+
+
+ }
+
+
+ //make name unique JUST IN CASE
+ String name = item->get_text(0);
+ name=name.replace("/","_").replace(":","_").strip_edges();
+ if (name=="")
+ name=TTR("New Clip");
+
+ if (clips.size()>2) {
+ int index=1;
+ while(true) {
+ bool valid = true;
+ String try_name=name;
+ if (index>1)
+ try_name+=" "+itos(index);
+
+ for(int i=0;i<clips.size()-1;i++) {
+
+ if (clips[i]==item)
+ continue;
+ if (clips[i]->get_text(0)==try_name) {
+ index++;
+ valid=false;
+ break;
+ }
+ }
+
+ if (valid) {
+ name=try_name;
+ break;
+ }
+
+ }
+ }
+
+ if (item->get_text(0)!=name)
+ item->set_text(0,name);
+
+ validating=false;
+
+}
+
+void EditorImportAnimationOptions::_bind_methods() {
+
+ ClassDB::bind_method("_changed",&EditorImportAnimationOptions::_changed);
+ ClassDB::bind_method("_item_edited",&EditorImportAnimationOptions::_item_edited);
+ ClassDB::bind_method("_button_action",&EditorImportAnimationOptions::_button_action);
+ //ClassDB::bind_method("_changedp",&EditorImportAnimationOptions::_changedp);
+
+ ADD_SIGNAL(MethodInfo("changed"));
+}
+
+
+void EditorImportAnimationOptions::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ flags->connect("item_edited",this,"_changed");
+ clips_tree->connect("item_edited",this,"_item_edited");
+ clips_tree->connect("button_pressed",this,"_button_action",varray(),CONNECT_DEFERRED);
+ //format->connect("item_selected",this,"_changedp");
+ }
+}
+
+
+Array EditorImportAnimationOptions::get_clips() const {
+
+ Array arr;
+ for(int i=0;i<clips.size()-1;i++) {
+
+ arr.push_back(clips[i]->get_text(0));
+ arr.push_back(clips[i]->get_range(1));
+ arr.push_back(clips[i]->get_range(2));
+ arr.push_back(clips[i]->is_checked(3));
+ }
+
+ return arr;
+}
+
+
+void EditorImportAnimationOptions::setup_clips(const Array& p_clips) {
+
+ ERR_FAIL_COND(p_clips.size()%4!=0);
+ for(int i=0;i<clips.size();i++) {
+
+ memdelete(clips[i]);
+ }
+
+
+ clips.clear();
+
+ for(int i=0;i<p_clips.size();i+=4) {
+
+ TreeItem *clip = clips_tree->create_item(clips_base);
+ clip->set_text(0,p_clips[i]);
+ clip->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons"));
+ clip->set_editable(0,true);
+ clip->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ clip->set_range_config(1,0,3600,0.01);
+ clip->set_range(1,p_clips[i+1]);
+ clip->set_editable(1,true);
+ clip->set_cell_mode(2,TreeItem::CELL_MODE_RANGE);
+ clip->set_range_config(2,0,3600,0.01);
+ clip->set_range(2,p_clips[i+2]);
+ clip->set_editable(2,true);
+ clip->set_cell_mode(3,TreeItem::CELL_MODE_CHECK);
+ clip->set_editable(3,true);
+ clip->set_checked(3,p_clips[i+3]);
+ clips.push_back(clip);
+
+ }
+
+ TreeItem *newclip = clips_tree->create_item(clips_base);
+ newclip->set_text(0,"<new clip>");
+ newclip->set_editable(0,true);
+ newclip->set_editable(1,false);
+ newclip->set_editable(2,false);
+ newclip->set_editable(3,false);
+ clips.push_back(newclip);
+
+}
+
+
+EditorImportAnimationOptions::EditorImportAnimationOptions() {
+
+
+ updating=false;
+ validating=false;
+
+ TabContainer *tab= memnew(TabContainer);
+ add_margin_child(TTR("Animation Options"),tab,true);
+
+ flags = memnew( Tree );
+ flags->set_hide_root(true);
+ tab->add_child(flags);
+ flags->set_name(TTR("Flags"));
+ TreeItem *root = flags->create_item();
+
+ const char ** fname=anim_flag_names;
+ const char ** fdescr=anim_flag_descript;
+
+ while( *fname ) {
+
+ TreeItem*ti = flags->create_item(root);
+ ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ ti->set_text(0,*fname);
+ ti->set_editable(0,true);
+ ti->set_tooltip(0,*fdescr);
+ items.push_back(ti);
+ fname++;
+ fdescr++;
+ }
+
+
+ TreeItem *fps_base = flags->create_item(root);
+ fps_base->set_text(0,TTR("Bake FPS:"));
+ fps_base->set_editable(0,false);
+ fps = flags->create_item(fps_base);
+ fps->set_cell_mode(0,TreeItem::CELL_MODE_RANGE);
+ fps->set_editable(0,true);
+ fps->set_range_config(0,1,120,1);
+ fps->set_range(0,15);
+
+ optimization_tree = memnew( Tree );
+ optimization_tree->set_columns(2);
+ tab->add_child(optimization_tree);
+ optimization_tree->set_name(TTR("Optimizer"));
+ optimization_tree->set_column_expand(0,true);
+ optimization_tree->set_column_expand(1,false);
+ optimization_tree->set_column_min_width(1,80);
+ optimization_tree->set_hide_root(true);
+
+
+ TreeItem *optimize_root = optimization_tree->create_item();
+
+ optimize_linear_error = optimization_tree->create_item(optimize_root);
+ optimize_linear_error->set_text(0,TTR("Max Linear Error"));
+ optimize_linear_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ optimize_linear_error->set_editable(1,true);
+ optimize_linear_error->set_range_config(1,0,1,0.001);
+ optimize_linear_error->set_range(1,0.05);
+
+ optimize_angular_error = optimization_tree->create_item(optimize_root);
+ optimize_angular_error->set_text(0,TTR("Max Angular Error"));
+ optimize_angular_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ optimize_angular_error->set_editable(1,true);
+ optimize_angular_error->set_range_config(1,0,1,0.001);
+ optimize_angular_error->set_range(1,0.01);
+
+ optimize_max_angle = optimization_tree->create_item(optimize_root);
+ optimize_max_angle->set_text(0,TTR("Max Angle"));
+ optimize_max_angle->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ optimize_max_angle->set_editable(1,true);
+ optimize_max_angle->set_range_config(1,0,360,0.001);
+ optimize_max_angle->set_range(1,int(180*0.125));
+
+ clips_tree = memnew( Tree );
+ clips_tree->set_hide_root(true);
+ tab->add_child(clips_tree);
+ clips_tree->set_name(TTR("Clips"));
+
+ clips_tree->set_columns(4);
+ clips_tree->set_column_expand(0,1);
+ clips_tree->set_column_expand(1,0);
+ clips_tree->set_column_expand(2,0);
+ clips_tree->set_column_expand(3,0);
+ clips_tree->set_column_min_width(1,60);
+ clips_tree->set_column_min_width(2,60);
+ clips_tree->set_column_min_width(3,40);
+ clips_tree->set_column_titles_visible(true);
+ clips_tree->set_column_title(0,TTR("Name"));
+ clips_tree->set_column_title(1,TTR("Start(s)"));
+ clips_tree->set_column_title(2,TTR("End(s)"));
+ clips_tree->set_column_title(3,TTR("Loop"));
+ clips_base =clips_tree->create_item(0);
+
+
+ setup_clips(Array());
+
+
+ filters = memnew( TextEdit );
+ tab->add_child(filters);
+ filters->set_name(TTR("Filters"));
+}
+
+
+
+void EditorImportAnimationOptions::set_fps(int p_fps) {
+
+ fps->set_range(0,p_fps);
+}
+
+int EditorImportAnimationOptions::get_fps() const {
+
+ return fps->get_range(0);
+}
+
+
+void EditorImportAnimationOptions::set_optimize_linear_error(float p_optimize_linear_error) {
+
+ optimize_linear_error->set_range(1,p_optimize_linear_error);
+}
+
+float EditorImportAnimationOptions::get_optimize_linear_error() const {
+
+ return optimize_linear_error->get_range(1);
+}
+
+void EditorImportAnimationOptions::set_optimize_angular_error(float p_optimize_angular_error) {
+
+ optimize_angular_error->set_range(1,p_optimize_angular_error);
+}
+
+float EditorImportAnimationOptions::get_optimize_angular_error() const {
+
+ return optimize_angular_error->get_range(1);
+}
+
+void EditorImportAnimationOptions::set_optimize_max_angle(float p_optimize_max_angle) {
+
+ optimize_max_angle->set_range(1,p_optimize_max_angle);
+}
+
+float EditorImportAnimationOptions::get_optimize_max_angle() const {
+
+ return optimize_max_angle->get_range(1);
+}
+
+
+void EditorImportAnimationOptions::set_filter(const String& p_filter) {
+
+ filters->set_text(p_filter);
+}
+
+String EditorImportAnimationOptions::get_filter() const {
+
+ return filters->get_text();
+}
+
+
+
+
+
+////////////////////////////////////////////////////////
+
+
+
+void EditorSceneImportDialog::_choose_file(const String& p_path) {
+#if 0
+ StringName sn = EditorImportDB::get_singleton()->find_source_path(p_path);
+ if (sn!=StringName()) {
+
+ EditorImportDB::ImportScene isc;
+ if (EditorImportDB::get_singleton()->get_scene(sn,isc)==OK) {
+
+ save_path->set_text(String(sn).get_base_dir());
+ texture_options->set_flags( isc.image_flags );
+ texture_options->set_quality( isc.image_quality );
+ texture_options->set_format( isc.image_format );
+ animation_options->set_flags( isc.anim_flags );
+ script_path->set_text( isc.import_script );
+ uint32_t f = isc.flags;
+ for(int i=0;i<scene_flags.size();i++) {
+
+ scene_flags[i]->set_checked(0,f&(1<<i));
+ }
+ }
+ } else {
+#endif
+ save_path->set_text("");
+ root_node_name->set_text("");
+ //save_path->set_text(p_path.get_file().basename()+".scn");
+#if 0
+ }
+#endif
+
+ if (p_path!=String()) {
+
+ String from_path = EditorFileSystem::get_singleton()->find_resource_from_source(EditorImportPlugin::validate_source_path(p_path));
+ print_line("from path.."+from_path);
+ if (from_path!=String()) {
+ popup_import(from_path);
+
+ }
+ }
+
+
+ import_path->set_text(p_path);
+ if (root_node_name->get_text().size()==0){
+ root_node_name->set_text(import_path->get_text().get_file().get_basename());
+ }
+
+}
+void EditorSceneImportDialog::_choose_save_file(const String& p_path) {
+
+ save_path->set_text(p_path);
+}
+
+void EditorSceneImportDialog::_choose_script(const String& p_path) {
+
+ String p = GlobalConfig::get_singleton()->localize_path(p_path);
+ if (!p.is_resource_file())
+ p=GlobalConfig::get_singleton()->get_resource_path().path_to(p_path.get_base_dir())+p_path.get_file();
+ script_path->set_text(p);
+
+}
+
+
+void EditorSceneImportDialog::_open_and_import() {
+
+ bool unsaved=EditorNode::has_unsaved_changes();
+
+ if (unsaved) {
+
+ confirm_open->popup_centered_minsize(Size2(300,80)*EDSCALE);
+ } else {
+ _import(true);
+ }
+}
+
+void EditorSceneImportDialog::_import(bool p_and_open) {
+
+ wip_open=p_and_open;
+//' ImportMonitorBlock imb;
+
+
+ if (import_path->get_text().strip_edges()=="") {
+ error_dialog->set_text(TTR("Source path is empty."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (save_path->get_text().strip_edges()=="") {
+ error_dialog->set_text(TTR("Target path is empty."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (!save_path->get_text().begins_with("res://")) {
+ error_dialog->set_text(TTR("Target path must be a complete resource path."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (!DirAccess::exists(save_path->get_text())) {
+ error_dialog->set_text(TTR("Target path must exist."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ String dst_path;
+
+ if (texture_action->get_selected()==0)
+ dst_path=save_path->get_text();//.get_base_dir();
+ else
+ dst_path=GlobalConfig::get_singleton()->get("import/shared_textures");
+
+ uint32_t flags=0;
+
+ for(int i=0;i<scene_flags.size();i++) {
+
+ if (scene_flags[i]->is_checked(0)) {
+ int md = scene_flags[i]->get_metadata(0);
+ flags|=md;
+ }
+ }
+
+
+
+
+
+ if (script_path->get_text()!="") {
+ Ref<Script> scr = ResourceLoader::load(script_path->get_text());
+ if (!scr.is_valid()) {
+ error_dialog->set_text(TTR("Couldn't load post-import script."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ Ref<EditorScenePostImport> pi = Ref<EditorScenePostImport>( memnew( EditorScenePostImport ) );
+ pi->set_script(scr.get_ref_ptr());
+ if (!pi->get_script_instance()) {
+
+ error_dialog->set_text(TTR("Invalid/broken script for post-import."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ }
+
+
+ // Scenes should always be imported as binary format since vertex data is large and would take
+ // up a lot of space and time to load if imported as text format (GH-5778)
+ String save_file = save_path->get_text().plus_file(import_path->get_text().get_file().get_basename()+".scn");
+ print_line("Saving to: "+save_file);
+
+
+
+
+
+ Node *scene=NULL;
+
+
+ Ref<ResourceImportMetadata> rim = memnew( ResourceImportMetadata );
+
+ rim->add_source(EditorImportPlugin::validate_source_path(import_path->get_text()));
+ rim->set_option("flags",flags);
+ print_line("GET FLAGS: "+itos(texture_options->get_flags()));
+ rim->set_option("texture_flags",texture_options->get_flags());
+ rim->set_option("texture_format",texture_options->get_format());
+ rim->set_option("texture_quality",texture_options->get_quality());
+ rim->set_option("animation_flags",animation_options->get_flags());
+ rim->set_option("animation_bake_fps",animation_options->get_fps());
+ rim->set_option("animation_optimizer_linear_error",animation_options->get_optimize_linear_error());
+ rim->set_option("animation_optimizer_angular_error",animation_options->get_optimize_angular_error());
+ rim->set_option("animation_optimizer_max_angle",animation_options->get_optimize_max_angle());
+ rim->set_option("animation_filters",animation_options->get_filter());
+ rim->set_option("animation_clips",animation_options->get_clips());
+ rim->set_option("post_import_script",script_path->get_text());
+ rim->set_option("reimport",true);
+ if (!root_default->is_pressed()) {
+ rim->set_option("root_type",root_type->get_text());
+ }
+ if (root_node_name->get_text().size()==0) {
+ root_node_name->set_text(import_path->get_text().get_file().get_basename());
+ }
+ rim->set_option("root_name",root_node_name->get_text());
+
+ List<String> missing;
+ Error err = plugin->import1(rim,&scene,&missing);
+
+ if (err || !scene) {
+
+ error_dialog->set_text(TTR("Error importing scene."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ if (missing.size()) {
+
+ missing_files->clear();
+ for(List<String>::Element *E=missing.front();E;E=E->next()) {
+
+ missing_files->add_text(E->get());
+ missing_files->add_newline();
+ }
+ wip_import=scene;
+ wip_rimd=rim;
+ wip_save_file=save_file;
+ confirm_import->popup_centered_ratio();
+ return;
+
+ } else {
+
+ err = plugin->import2(scene,save_file,rim);
+
+ if (err) {
+
+ error_dialog->set_text(TTR("Error importing scene."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+ if (wip_open)
+ EditorNode::get_singleton()->load_scene(save_file,false,false,false);
+
+ }
+
+ hide();
+
+ /*
+ editor->clear_scene();
+
+ Error err = EditorImport::import_scene(import_path->get_text(),save_file,dst_path,flags,texture_options->get_format(),compression,texture_options->get_flags(),texture_options->get_quality(),animation_options->get_flags(), &scene,pi);
+
+ if (err) {
+
+ error_dialog->set_text("Error importing scene.");
+ error_dialog->popup_centered(Size2(200,100));
+ return;
+ }
+
+ editor->save_import_export();
+ if (scene)
+ editor->set_edited_scene(scene);
+
+ hide();
+ */
+};
+
+
+void EditorSceneImportDialog::_import_confirm() {
+
+ wip_blocked=true;
+ print_line("import confirm!");
+ Error err = plugin->import2(wip_import,wip_save_file,wip_rimd);
+ wip_blocked=false;
+ wip_import=NULL;
+ wip_rimd=Ref<ResourceImportMetadata>();
+ confirm_import->hide();
+ if (err) {
+
+ wip_save_file="";
+ error_dialog->set_text(TTR("Error importing scene."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ if (wip_open)
+ EditorNode::get_singleton()->load_scene(wip_save_file,false,false,false);
+ wip_open=false;
+ wip_save_file="";
+
+ hide();
+
+}
+
+
+void EditorSceneImportDialog::_browse() {
+
+ file_select->popup_centered_ratio();
+}
+
+void EditorSceneImportDialog::_browse_target() {
+
+ save_select->popup_centered_ratio();
+ if (save_path->get_text()!="")
+ save_select->set_current_path(save_path->get_text());
+
+}
+
+void EditorSceneImportDialog::_browse_script() {
+
+ script_select->popup_centered_ratio();
+
+}
+
+void EditorSceneImportDialog::popup_import(const String &p_from) {
+
+ popup_centered(Size2(750,550)*EDSCALE);
+ if (p_from!="") {
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
+ if (rimd.is_null())
+ return;
+
+ int flags = rimd->get_option("flags");
+
+ for(int i=0;i<scene_flags.size();i++) {
+
+ int md = scene_flags[i]->get_metadata(0);
+ scene_flags[i]->set_checked(0,flags&md);
+ }
+
+ texture_options->set_flags(rimd->get_option("texture_flags"));
+ texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("texture_format"))));
+ texture_options->set_quality(rimd->get_option("texture_quality"));
+ animation_options->set_flags(rimd->get_option("animation_flags"));
+ if (rimd->has_option("animation_clips"))
+ animation_options->setup_clips(rimd->get_option("animation_clips"));
+ if (rimd->has_option("animation_filters"))
+ animation_options->set_filter(rimd->get_option("animation_filters"));
+ if (rimd->has_option("animation_bake_fps"))
+ animation_options->set_fps(rimd->get_option("animation_bake_fps"));
+ if (rimd->has_option("animation_optimizer_linear_error"))
+ animation_options->set_optimize_linear_error(rimd->get_option("animation_optimizer_linear_error"));
+ if (rimd->has_option("animation_optimizer_angular_error"))
+ animation_options->set_optimize_angular_error(rimd->get_option("animation_optimizer_angular_error"));
+ if (rimd->has_option("animation_optimizer_max_angle"))
+ animation_options->set_optimize_max_angle(rimd->get_option("animation_optimizer_max_angle"));
+
+ if (rimd->has_option("root_type")) {
+ root_default->set_pressed(false);
+ String type = rimd->get_option("root_type");
+ root_type->set_text(type);
+ root_type->set_disabled(false);
+
+ if (has_icon(type,"EditorIcons")) {
+ root_type->set_icon(get_icon(type,"EditorIcons"));
+ } else {
+ root_type->set_icon(get_icon("Object","EditorIcons"));
+ }
+
+ } else {
+ root_default->set_pressed(true);
+ root_type->set_disabled(true);
+ }
+ if (rimd->has_option("root_name")) {
+ root_node_name->set_text(rimd->get_option("root_name"));
+ } else {
+ root_node_name->set_text(root_type->get_text()); // backward compatibility for 2.1 or before
+ }
+ script_path->set_text(rimd->get_option("post_import_script"));
+
+ save_path->set_text(p_from.get_base_dir());
+ import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
+
+ }
+}
+
+
+void EditorSceneImportDialog::_notification(int p_what) {
+
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+
+ List<String> extensions;
+ file_select->clear_filters();
+ root_type->set_icon(get_icon("Spatial","EditorIcons"));
+ root_type->set_text("Spatial");
+ root_type->set_disabled(true);
+
+ for(int i=0;i<plugin->get_importers().size();i++) {
+ plugin->get_importers()[i]->get_extensions(&extensions);
+ }
+
+
+ for(int i=0;i<extensions.size();i++) {
+
+ file_select->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+ extensions.clear();
+
+ //EditorImport::get_import_extensions(&extensions)
+ /* ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
+ save_select->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ save_select->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }*/
+
+
+ }
+}
+
+Error EditorSceneImportDialog::import(const String& p_from, const String& p_to, const String& p_preset) {
+
+ import_path->set_text(p_from);
+ save_path->set_text(p_to);
+ script_path->set_text(p_preset);
+
+ _import();
+
+
+
+ return OK;
+}
+
+void EditorSceneImportDialog::_dialog_hid() {
+
+ if (wip_blocked)
+ return;
+ print_line("DIALOGHID!");
+ if (wip_import) {
+ memdelete(wip_import);
+ wip_import=NULL;
+ wip_save_file="";
+ wip_rimd=Ref<ResourceImportMetadata>();
+ }
+}
+void EditorSceneImportDialog::_root_default_pressed() {
+
+ root_type->set_disabled(root_default->is_pressed());
+}
+
+void EditorSceneImportDialog::_root_type_pressed() {
+
+
+ root_type_choose->popup(false);
+}
+
+
+void EditorSceneImportDialog::_set_root_type() {
+
+ String type = root_type_choose->get_selected_type();
+ if (type==String())
+ return;
+ root_type->set_text(type);
+ if (has_icon(type,"EditorIcons")) {
+ root_type->set_icon(get_icon(type,"EditorIcons"));
+ } else {
+ root_type->set_icon(get_icon("Object","EditorIcons"));
+ }
+}
+
+void EditorSceneImportDialog::_bind_methods() {
+
+
+ ClassDB::bind_method("_choose_file",&EditorSceneImportDialog::_choose_file);
+ ClassDB::bind_method("_choose_save_file",&EditorSceneImportDialog::_choose_save_file);
+ ClassDB::bind_method("_choose_script",&EditorSceneImportDialog::_choose_script);
+ ClassDB::bind_method("_import",&EditorSceneImportDialog::_import,DEFVAL(false));
+ ClassDB::bind_method("_browse",&EditorSceneImportDialog::_browse);
+ ClassDB::bind_method("_browse_target",&EditorSceneImportDialog::_browse_target);
+ ClassDB::bind_method("_browse_script",&EditorSceneImportDialog::_browse_script);
+ ClassDB::bind_method("_dialog_hid",&EditorSceneImportDialog::_dialog_hid);
+ ClassDB::bind_method("_import_confirm",&EditorSceneImportDialog::_import_confirm);
+ ClassDB::bind_method("_open_and_import",&EditorSceneImportDialog::_open_and_import);
+ ClassDB::bind_method("_root_default_pressed",&EditorSceneImportDialog::_root_default_pressed);
+ ClassDB::bind_method("_root_type_pressed",&EditorSceneImportDialog::_root_type_pressed);
+ ClassDB::bind_method("_set_root_type",&EditorSceneImportDialog::_set_root_type);
+
+
+ ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
+}
+
+
+
+const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_names[]={
+
+ {EditorSceneImportPlugin::SCENE_FLAG_REMOVE_NOIMP,("Actions"),"Remove Nodes (-noimp)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_IMPORT_ANIMATIONS,("Actions"),"Import Animations",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_COMPRESS_GEOMETRY,("Actions"),"Compress Geometry",false},
+ {EditorSceneImportPlugin::SCENE_FLAG_GENERATE_TANGENT_ARRAYS,("Actions"),"Force Generation of Tangent Arrays",false},
+ {EditorSceneImportPlugin::SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES,("Actions"),"SRGB->Linear Of Diffuse Textures",false},
+ {EditorSceneImportPlugin::SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY,("Actions"),"Convert Normal Maps to XY",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS,("Actions"),"Set Material Lightmap to UV2 if Tex2Array Exists",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_MERGE_KEEP_MATERIALS,("Merge"),"Keep Materials after first import (delete them for re-import).",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,("Merge"),"Keep user-added Animation tracks.",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,("Materials"),"Set Alpha in Materials (-alpha)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,("Materials"),"Set Vert. Color in Materials (-vcol)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,("Create"),"Create Collisions and/or Rigid Bodies (-col,-colonly,-rigid)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,("Create"),"Create Portals (-portal)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_ROOMS,("Create"),"Create Rooms (-room)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_SIMPLIFY_ROOMS,("Create"),"Simplify Rooms",false},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_BILLBOARDS,("Create"),"Create Billboards (-bb)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,("Create"),"Create Impostors (-imp:dist)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_LODS,("Create"),"Create LODs (-lod:dist)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,("Create"),"Create Vehicles (-vehicle)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,("Create"),"Create Vehicle Wheels (-wheel)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_CREATE_NAVMESH,("Create"),"Create Navigation Meshes (-navmesh)",true},
+ {EditorSceneImportPlugin::SCENE_FLAG_DETECT_LIGHTMAP_LAYER,("Create"),"Detect LightMap Layer (-lm:<int>).",true},
+ {-1,NULL,NULL,false}
+};
+
+
+EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSceneImportPlugin *p_plugin) {
+
+
+ editor=p_editor;
+ plugin=p_plugin;
+
+ set_title(TTR("Import 3D Scene"));
+ HBoxContainer *import_hb = memnew( HBoxContainer );
+ add_child(import_hb);
+ //set_child_rect(import_hb);
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ import_hb->add_child(vbc);
+ vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Source Scene:"),hbc);
+
+ import_path = memnew( LineEdit );
+ import_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(import_path);
+
+ Button * import_choose = memnew( Button );
+ import_choose->set_text(" .. ");
+ hbc->add_child(import_choose);
+
+ import_choose->connect("pressed", this,"_browse");
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Target Path:"),hbc);
+
+ save_path = memnew( LineEdit );
+ save_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(save_path);
+
+ Button * save_choose = memnew( Button );
+ save_choose->set_text(" .. ");
+ hbc->add_child(save_choose);
+
+ save_choose->connect("pressed", this,"_browse_target");
+
+ texture_action = memnew( OptionButton );
+ texture_action->add_item(TTR("Same as Target Scene"));
+ texture_action->add_item(TTR("Shared"));
+ texture_action->select(0);
+ vbc->add_margin_child(TTR("Target Texture Folder:"),texture_action);
+
+ import_options = memnew( Tree );
+ vbc->set_v_size_flags(SIZE_EXPAND_FILL);
+ vbc->add_margin_child(TTR("Options:"),import_options,true);
+
+ file_select = memnew(EditorFileDialog);
+ file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ add_child(file_select);
+
+
+ file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+
+ file_select->connect("file_selected", this,"_choose_file");
+
+ save_select = memnew(EditorDirDialog);
+ add_child(save_select);
+
+ //save_select->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ save_select->connect("dir_selected", this,"_choose_save_file");
+
+ get_ok()->connect("pressed", this,"_import");
+ get_ok()->set_text(TTR("Import"));
+
+ TreeItem *root = import_options->create_item(NULL);
+ import_options->set_hide_root(true);
+
+ const FlagInfo* fn=scene_flag_names;
+
+ Map<String,TreeItem*> categories;
+
+ while(fn->text) {
+
+ String cat = fn->category;
+ TreeItem *parent;
+ if (!categories.has(cat)) {
+ parent = import_options->create_item(root);
+ parent->set_text(0,cat);
+ categories[cat]=parent;
+ } else {
+ parent=categories[cat];
+ }
+
+ TreeItem *opt = import_options->create_item(parent);
+ opt->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ opt->set_checked(0,fn->defval);
+ opt->set_editable(0,true);
+ opt->set_text(0,fn->text);
+ opt->set_metadata(0,fn->value);
+
+ scene_flags.push_back(opt);
+ fn++;
+ }
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Post-Process Script:"),hbc);
+
+ script_path = memnew( LineEdit );
+ script_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(script_path);
+
+ Button * script_choose = memnew( Button );
+ script_choose->set_text(" .. ");
+ hbc->add_child(script_choose);
+
+ script_choose->connect("pressed", this,"_browse_script");
+
+ script_select = memnew(EditorFileDialog);
+ add_child(script_select);
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+
+ ScriptLanguage *sl=ScriptServer::get_language(i);
+ String ext = sl->get_extension();
+ if (ext=="")
+ continue;
+ script_select->add_filter("*."+ext+" ; "+sl->get_name());
+ }
+
+
+ script_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+
+ script_select->connect("file_selected", this,"_choose_script");
+
+ error_dialog = memnew ( ConfirmationDialog );
+ add_child(error_dialog);
+ error_dialog->get_ok()->set_text(TTR("Accept"));
+ //error_dialog->get_cancel()->hide();
+
+
+ HBoxContainer *custom_root_hb = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Custom Root Node Type:"),custom_root_hb);
+ root_type = memnew(Button);
+ root_type->set_h_size_flags(SIZE_EXPAND_FILL);
+ root_type->set_text_align(Button::ALIGN_LEFT);
+ root_type->connect("pressed",this,"_root_type_pressed");
+ custom_root_hb->add_child(root_type);
+
+ root_default = memnew(CheckBox);
+ root_default->set_text(TTR("Auto"));
+ root_default->set_pressed(true);
+ root_default->connect("pressed",this,"_root_default_pressed");
+ custom_root_hb->add_child(root_default);
+
+ root_node_name = memnew( LineEdit );
+ root_node_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbc->add_margin_child(TTR("Root Node Name:"),root_node_name);
+ /*
+ this_import = memnew( OptionButton );
+ this_import->add_item("Overwrite Existing Scene");
+ this_import->add_item("Overwrite Existing, Keep Materials");
+ this_import->add_item("Keep Existing, Merge with New");
+ this_import->add_item("Keep Existing, Ignore New");
+ vbc->add_margin_child("This Time:",this_import);
+
+ next_import = memnew( OptionButton );
+ next_import->add_item("Overwrite Existing Scene");
+ next_import->add_item("Overwrite Existing, Keep Materials");
+ next_import->add_item("Keep Existing, Merge with New");
+ next_import->add_item("Keep Existing, Ignore New");
+ vbc->add_margin_child("Next Time:",next_import);
+*/
+ set_hide_on_ok(false);
+
+ GLOBAL_DEF("import/shared_textures","res://");
+ GlobalConfig::get_singleton()->set_custom_property_info("import/shared_textures",PropertyInfo(Variant::STRING,"import/shared_textures",PROPERTY_HINT_DIR));
+
+ import_hb->add_constant_override("separation",30);
+
+
+ VBoxContainer *ovb = memnew( VBoxContainer);
+ ovb->set_h_size_flags(SIZE_EXPAND_FILL);
+ import_hb->add_child(ovb);
+
+ texture_options = memnew( EditorImportTextureOptions );
+ ovb->add_child(texture_options);
+ texture_options->set_v_size_flags(SIZE_EXPAND_FILL);
+ //animation_options->set_flags(EditorImport::
+ texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
+ texture_options->set_flags( EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA | EditorTextureImportPlugin::IMAGE_FLAG_REPEAT | EditorTextureImportPlugin::IMAGE_FLAG_FILTER );
+
+
+ animation_options = memnew( EditorImportAnimationOptions );
+ ovb->add_child(animation_options);
+ animation_options->set_v_size_flags(SIZE_EXPAND_FILL);
+ animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
+
+
+ confirm_import = memnew( ConfirmationDialog );
+ add_child(confirm_import);
+ VBoxContainer *cvb = memnew( VBoxContainer );
+ confirm_import->add_child(cvb);
+ //confirm_import->set_child_rect(cvb);
+
+ PanelContainer *pc = memnew( PanelContainer );
+ pc->add_style_override("panel",get_stylebox("normal","TextEdit"));
+ //ec->add_child(pc);
+ missing_files = memnew( RichTextLabel );
+ cvb->add_margin_child(TTR("The Following Files are Missing:"),pc,true);
+ pc->add_child(missing_files);
+ confirm_import->get_ok()->set_text(TTR("Import Anyway"));
+ confirm_import->get_cancel()->set_text(TTR("Cancel"));
+ confirm_import->connect("popup_hide",this,"_dialog_hid");
+ confirm_import->connect("confirmed",this,"_import_confirm");
+ confirm_import->set_hide_on_ok(false);
+
+ add_button(TTR("Import & Open"),!OS::get_singleton()->get_swap_ok_cancel())->connect("pressed",this,"_open_and_import");
+
+ confirm_open = memnew( ConfirmationDialog );
+ add_child(confirm_open);
+ confirm_open->set_text(TTR("Edited scene has not been saved, open imported scene anyway?"));
+ confirm_open->connect("confirmed",this,"_import",varray(true));
+
+
+ wip_import=NULL;
+ wip_blocked=false;
+ wip_open=false;
+ //texture_options->set_format(EditorImport::IMAGE_FORMAT_C);
+
+ root_type_choose = memnew( CreateDialog );
+ add_child(root_type_choose);
+ root_type_choose->set_base_type("Node");
+ root_type_choose->connect("create",this,"_set_root_type");
+}
+
+
+
+////////////////////////////////
+
+
+
+String EditorSceneImportPlugin::get_name() const {
+
+ return "scene_3d";
+}
+
+String EditorSceneImportPlugin::get_visible_name() const{
+
+ return TTR("Scene");
+}
+
+void EditorSceneImportPlugin::import_dialog(const String& p_from){
+
+ dialog->popup_import(p_from);
+}
+
+
+//////////////////////////
+
+
+static bool _teststr(const String& p_what,const String& p_str) {
+
+ if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
+ return true;
+ if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
+ return true;
+ if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
+ return true;
+ return false;
+}
+
+static String _fixstr(const String& p_what,const String& p_str) {
+
+ if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
+ return p_what.replace("$"+p_str,"");
+ if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
+ return p_what.substr(0,p_what.length()-(p_str.length()+1));
+ if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
+ return p_what.substr(0,p_what.length()-(p_str.length()+1));
+ return p_what;
+}
+
+
+
+void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<ImageTexture>, TextureRole> &image_map,int p_flags) {
+
+
+ switch(p_var.get_type()) {
+
+ case Variant::OBJECT: {
+
+ Ref<Resource> res = p_var;
+ if (res.is_valid()) {
+
+ if (res->is_class("Texture") && !image_map.has(res)) {
+
+ image_map.insert(res,TEXTURE_ROLE_DEFAULT);
+
+
+ } else {
+
+
+ List<PropertyInfo> pl;
+ res->get_property_list(&pl);
+ for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
+
+ if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) {
+ if (E->get().type==Variant::OBJECT && res->cast_to<FixedSpatialMaterial>() && (E->get().name=="textures/diffuse" || E->get().name=="textures/detail" || E->get().name=="textures/emission")) {
+
+ Ref<ImageTexture> tex =res->get(E->get().name);
+ if (tex.is_valid()) {
+
+ image_map.insert(tex,TEXTURE_ROLE_DIFFUSE);
+ }
+
+ } else if (E->get().type==Variant::OBJECT && res->cast_to<FixedSpatialMaterial>() && (E->get().name=="textures/normal")) {
+
+ Ref<ImageTexture> tex =res->get(E->get().name);
+ if (tex.is_valid()) {
+
+ image_map.insert(tex,TEXTURE_ROLE_NORMALMAP);
+ /*
+ if (p_flags&SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY)
+ res->cast_to<FixedSpatialMaterial>()->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_XY_NORMALMAP,true);
+ */
+ }
+
+
+ } else {
+ _find_resources(res->get(E->get().name),image_map,p_flags);
+ }
+ }
+ }
+
+ }
+ }
+
+ } break;
+ case Variant::DICTIONARY: {
+
+ Dictionary d= p_var;
+
+ List<Variant> keys;
+ d.get_key_list(&keys);
+
+ for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
+
+
+ _find_resources(E->get(),image_map,p_flags);
+ _find_resources(d[E->get()],image_map,p_flags);
+
+ }
+
+
+ } break;
+ case Variant::ARRAY: {
+
+ Array a = p_var;
+ for(int i=0;i<a.size();i++) {
+
+ _find_resources(a[i],image_map,p_flags);
+ }
+
+ } break;
+ default: {}
+
+ }
+
+}
+
+
+Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map) {
+
+ // children first..
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+
+ Node *r = _fix_node(p_node->get_child(i),p_root,collision_map,p_flags,image_map);
+ if (!r) {
+ print_line("was erased..");
+ i--; //was erased
+ }
+ }
+
+ String name = p_node->get_name();
+
+ bool isroot = p_node==p_root;
+
+
+ if (!isroot && p_flags&SCENE_FLAG_REMOVE_NOIMP && _teststr(name,"noimp")) {
+
+ memdelete(p_node);
+ return NULL;
+ }
+
+ {
+
+ List<PropertyInfo> pl;
+ p_node->get_property_list(&pl);
+ for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
+
+ if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) {
+ _find_resources(p_node->get(E->get().name),image_map,p_flags);
+ }
+ }
+
+ }
+
+
+
+
+ if (p_flags&SCENE_FLAG_CREATE_BILLBOARDS && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ bool bb=false;
+
+ if ((_teststr(name,"bb"))) {
+ bb=true;
+ } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) {
+ bb=true;
+
+ }
+
+ if (bb) {
+ mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
+ if (mi->get_mesh().is_valid()) {
+
+ Ref<Mesh> m = mi->get_mesh();
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
+ if (fm.is_valid()) {
+ //fm->set_flag(Material::FLAG_UNSHADED,true);
+ //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
+ //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ }
+ }
+ }
+ }
+ }
+
+
+ if (p_flags&(SCENE_FLAG_DETECT_ALPHA|SCENE_FLAG_DETECT_VCOLOR|SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS) && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ Ref<Mesh> m = mi->get_mesh();
+
+ if (m.is_valid()) {
+
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> mat = m->surface_get_material(i);
+ if (!mat.is_valid())
+ continue;
+
+ if (p_flags&SCENE_FLAG_DETECT_ALPHA && _teststr(mat->get_name(),"alpha")) {
+
+ //mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ //mat->set_name(_fixstr(mat->get_name(),"alpha"));
+ }
+ if (p_flags&SCENE_FLAG_DETECT_VCOLOR && _teststr(mat->get_name(),"vcol")) {
+
+ //mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true);
+ //mat->set_name(_fixstr(mat->get_name(),"vcol"));
+ }
+
+ if (p_flags&SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS && m->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
+ //mat->set_flag(Material::FLAG_LIGHTMAP_ON_UV2,true);
+ }
+
+ }
+ }
+ }
+
+ if (p_flags&SCENE_FLAG_REMOVE_NOIMP && p_node->cast_to<AnimationPlayer>()) {
+ //remove animations referencing non-importable nodes
+ AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>();
+
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
+
+ Ref<Animation> anim=ap->get_animation(E->get());
+ ERR_CONTINUE(anim.is_null());
+ for(int i=0;i<anim->get_track_count();i++) {
+ NodePath path = anim->track_get_path(i);
+
+ for(int j=0;j<path.get_name_count();j++) {
+ String node = path.get_name(j);
+ if (_teststr(node,"noimp")) {
+ anim->remove_track(i);
+ i--;
+ break;
+ }
+ }
+ }
+
+ }
+ }
+
+
+ if (p_flags&SCENE_FLAG_CREATE_IMPOSTORS && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ String str;
+
+ if ((_teststr(name,"imp"))) {
+ str=name;
+ } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) {
+ str=mi->get_mesh()->get_name();
+
+ }
+
+
+ if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
+ String d=str.substr(str.find("imp")+3,str.length());
+ if (d!="") {
+ if ((d[0]<'0' || d[0]>'9'))
+ d=d.substr(1,d.length());
+ if (d.length() && d[0]>='0' && d[0]<='9') {
+ float dist = d.to_double();
+ mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
+ mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true);
+ //mi->set_draw_range_begin(dist);
+ //mi->set_draw_range_end(100000);
+
+ //mip->set_draw_range_begin(0);
+ //mip->set_draw_range_end(dist);
+
+ if (mi->get_mesh().is_valid()) {
+
+ Ref<Mesh> m = mi->get_mesh();
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
+ if (fm.is_valid()) {
+ //fm->set_flag(Material::FLAG_UNSHADED,true);
+ //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
+ //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ String str;
+
+ if ((_teststr(name,"lod"))) {
+ str=name;
+ } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) {
+ str=mi->get_mesh()->get_name();
+
+ }
+
+
+ if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
+ String d=str.substr(str.find("lod")+3,str.length());
+ if (d!="") {
+ if ((d[0]<'0' || d[0]>'9'))
+ d=d.substr(1,d.length());
+ if (d.length() && d[0]>='0' && d[0]<='9') {
+ float dist = d.to_double();
+ /// mi->set_draw_range_begin(dist);
+ // mi->set_draw_range_end(100000);
+
+ // mip->set_draw_range_begin(0);
+ // mip->set_draw_range_end(dist);
+
+ /*if (mi->get_mesh().is_valid()) {
+
+ Ref<Mesh> m = mi->get_mesh();
+ for(int i=0;i<m->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
+ if (fm.is_valid()) {
+ fm->set_flag(Material::FLAG_UNSHADED,true);
+ fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
+ fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ }
+ }
+ }*/
+ }
+ }
+ }
+ }
+
+
+ if (p_flags&SCENE_FLAG_DETECT_LIGHTMAP_LAYER && _teststr(name,"lm") && p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ String str=name;
+ int layer = str.substr(str.find("lm")+3,str.length()).to_int();
+ //mi->set_baked_light_texture_id(layer);
+ }
+
+ if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly")) {
+
+ if (isroot)
+ return p_node;
+
+ if (p_node->cast_to<MeshInstance>()) {
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ Node * col = mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col,NULL);
+
+ col->set_name(_fixstr(name,"colonly"));
+ col->cast_to<Spatial>()->set_transform(mi->get_transform());
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node=col;
+
+ StaticBody *sb = col->cast_to<StaticBody>();
+ CollisionShape *colshape = memnew( CollisionShape);
+ colshape->set_shape(sb->get_shape(0));
+ colshape->set_name("shape");
+ sb->add_child(colshape);
+ colshape->set_owner(p_node->get_owner());
+ } else if (p_node->has_meta("empty_draw_type")) {
+ String empty_draw_type = String(p_node->get_meta("empty_draw_type"));
+ print_line(empty_draw_type);
+ StaticBody *sb = memnew( StaticBody);
+ sb->set_name(_fixstr(name,"colonly"));
+ sb->cast_to<Spatial>()->set_transform(p_node->cast_to<Spatial>()->get_transform());
+ p_node->replace_by(sb);
+ memdelete(p_node);
+ CollisionShape *colshape = memnew( CollisionShape);
+ if (empty_draw_type == "CUBE") {
+ BoxShape *boxShape = memnew( BoxShape);
+ boxShape->set_extents(Vector3(1, 1, 1));
+ colshape->set_shape(boxShape);
+ colshape->set_name("BoxShape");
+ } else if (empty_draw_type == "SINGLE_ARROW") {
+ RayShape *rayShape = memnew( RayShape);
+ rayShape->set_length(1);
+ colshape->set_shape(rayShape);
+ colshape->set_name("RayShape");
+ sb->cast_to<Spatial>()->rotate_x(Math_PI / 2);
+ } else if (empty_draw_type == "IMAGE") {
+ PlaneShape *planeShape = memnew( PlaneShape);
+ colshape->set_shape(planeShape);
+ colshape->set_name("PlaneShape");
+ } else {
+ SphereShape *sphereShape = memnew( SphereShape);
+ sphereShape->set_radius(1);
+ colshape->set_shape(sphereShape);
+ colshape->set_name("SphereShape");
+ }
+ sb->add_child(colshape);
+ colshape->set_owner(sb->get_owner());
+ }
+
+ } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"rigid") && p_node->cast_to<MeshInstance>()) {
+
+ if (isroot)
+ return p_node;
+
+ // get mesh instance and bounding box
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ Rect3 aabb = mi->get_aabb();
+
+ // create a new rigid body collision node
+ RigidBody * rigid_body = memnew( RigidBody );
+ Node * col = rigid_body;
+ ERR_FAIL_COND_V(!col,NULL);
+
+ // remove node name postfix
+ col->set_name(_fixstr(name,"rigid"));
+ // get mesh instance xform matrix to the rigid body collision node
+ col->cast_to<Spatial>()->set_transform(mi->get_transform());
+ // save original node by duplicating it into a new instance and correcting the name
+ Node * mesh = p_node->duplicate();
+ mesh->set_name(_fixstr(name,"rigid"));
+ // reset the xform matrix of the duplicated node so it can inherit parent node xform
+ mesh->cast_to<Spatial>()->set_transform(Transform(Basis()));
+ // reparent the new mesh node to the rigid body collision node
+ p_node->add_child(mesh);
+ mesh->set_owner(p_node->get_owner());
+ // replace the original node with the rigid body collision node
+ p_node->replace_by(col);
+ memdelete(p_node);
+ p_node=col;
+
+ // create an alias for the rigid body collision node
+ RigidBody *rb = col->cast_to<RigidBody>();
+ // create a new Box collision shape and set the right extents
+ Ref<BoxShape> shape = memnew( BoxShape );
+ shape->set_extents(aabb.get_size() * 0.5);
+ CollisionShape *colshape = memnew( CollisionShape);
+ colshape->set_name("shape");
+ colshape->set_shape(shape);
+ // reparent the new collision shape to the rigid body collision node
+ rb->add_child(colshape);
+ colshape->set_owner(p_node->get_owner());
+
+ } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to<MeshInstance>()) {
+
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ mi->set_name(_fixstr(name,"col"));
+ Node *col= mi->create_trimesh_collision_node();
+ ERR_FAIL_COND_V(!col,NULL);
+
+ col->set_name("col");
+ p_node->add_child(col);
+
+ StaticBody *sb=col->cast_to<StaticBody>();
+ CollisionShape *colshape = memnew( CollisionShape);
+ colshape->set_shape(sb->get_shape(0));
+ colshape->set_name("shape");
+ col->add_child(colshape);
+ colshape->set_owner(p_node->get_owner());
+ sb->set_owner(p_node->get_owner());
+
+ } else if (p_flags&SCENE_FLAG_CREATE_NAVMESH &&_teststr(name,"navmesh") && p_node->cast_to<MeshInstance>()) {
+
+ if (isroot)
+ return p_node;
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ Ref<Mesh> mesh=mi->get_mesh();
+ ERR_FAIL_COND_V(mesh.is_null(),NULL);
+ NavigationMeshInstance *nmi = memnew( NavigationMeshInstance );
+
+
+ nmi->set_name(_fixstr(name,"navmesh"));
+ Ref<NavigationMesh> nmesh = memnew( NavigationMesh);
+ nmesh->create_from_mesh(mesh);
+ nmi->set_navigation_mesh(nmesh);
+ nmi->cast_to<Spatial>()->set_transform(mi->get_transform());
+ p_node->replace_by(nmi);
+ memdelete(p_node);
+ p_node=nmi;
+ } else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"vehicle")) {
+
+ if (isroot)
+ return p_node;
+
+ Node *owner = p_node->get_owner();
+ Spatial *s = p_node->cast_to<Spatial>();
+ VehicleBody *bv = memnew( VehicleBody );
+ String n = _fixstr(p_node->get_name(),"vehicle");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform());
+
+ p_node=bv;
+
+
+ } else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"wheel")) {
+
+ if (isroot)
+ return p_node;
+
+ Node *owner = p_node->get_owner();
+ Spatial *s = p_node->cast_to<Spatial>();
+ VehicleWheel *bv = memnew( VehicleWheel );
+ String n = _fixstr(p_node->get_name(),"wheel");
+ bv->set_name(n);
+ p_node->replace_by(bv);
+ p_node->set_name(n);
+ bv->add_child(p_node);
+ bv->set_owner(owner);
+ p_node->set_owner(owner);
+ bv->set_transform(s->get_transform());
+ s->set_transform(Transform());
+
+ p_node=bv;
+
+ } else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) {
+
+
+ if (isroot)
+ return p_node;
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
+
+
+ BSP_Tree bsptree(faces);
+
+ Ref<RoomBounds> area = memnew( RoomBounds );
+ //area->set_bounds(faces);
+ //area->set_geometry_hint(faces);
+
+
+ Room * room = memnew( Room );
+ room->set_name(_fixstr(name,"room"));
+ room->set_transform(mi->get_transform());
+ room->set_room(area);
+
+ p_node->replace_by(room);
+ memdelete(p_node);
+ p_node=room;
+
+ } else if (p_flags&SCENE_FLAG_CREATE_ROOMS &&_teststr(name,"room")) {
+
+ if (isroot)
+ return p_node;
+
+ Spatial *dummy = p_node->cast_to<Spatial>();
+ ERR_FAIL_COND_V(!dummy,NULL);
+
+ Room * room = memnew( Room );
+ room->set_name(_fixstr(name,"room"));
+ room->set_transform(dummy->get_transform());
+
+ p_node->replace_by(room);
+ memdelete(p_node);
+ p_node=room;
+
+ //room->compute_room_from_subtree();
+
+ } else if (p_flags&SCENE_FLAG_CREATE_PORTALS &&_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) {
+
+ if (isroot)
+ return p_node;
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+ PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
+
+ ERR_FAIL_COND_V(faces.size()==0,NULL);
+ //step 1 compute the plane
+ Set<Vector3> points;
+ Plane plane;
+
+ Vector3 center;
+
+ for(int i=0;i<faces.size();i++) {
+
+ Face3 f = faces.get(i);
+ Plane p = f.get_plane();
+ plane.normal+=p.normal;
+ plane.d+=p.d;
+
+ for(int i=0;i<3;i++) {
+
+ Vector3 v = f.vertex[i].snapped(0.01);
+ if (!points.has(v)) {
+ points.insert(v);
+ center+=v;
+ }
+ }
+ }
+
+ plane.normal.normalize();
+ plane.d/=faces.size();
+ center/=points.size();
+
+ //step 2, create points
+
+ Transform t;
+ t.basis.from_z(plane.normal);
+ t.basis.transpose();
+ t.origin=center;
+
+ Vector<Point2> portal_points;
+
+ for(Set<Vector3>::Element *E=points.front();E;E=E->next()) {
+
+ Vector3 local = t.xform_inv(E->get());
+ portal_points.push_back(Point2(local.x,local.y));
+ }
+ // step 3 bubbly sort points
+
+ int swaps=0;
+
+ do {
+ swaps=0;
+
+ for(int i=0;i<portal_points.size()-1;i++) {
+
+ float a = portal_points[i].angle();
+ float b = portal_points[i+1].angle();
+
+ if (a>b) {
+ SWAP( portal_points[i], portal_points[i+1] );
+ swaps++;
+ }
+
+ }
+
+ } while(swaps);
+
+
+ Portal *portal = memnew( Portal );
+
+ portal->set_shape(portal_points);
+ portal->set_transform( mi->get_transform() * t);
+
+ p_node->replace_by(portal);
+ memdelete(p_node);
+ p_node=portal;
+
+ } else if (p_node->cast_to<MeshInstance>()) {
+
+ //last attempt, maybe collision insde the mesh data
+
+ MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+ Ref<Mesh> mesh = mi->get_mesh();
+ if (!mesh.is_null()) {
+
+ if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(mesh->get_name(),"col")) {
+
+ mesh->set_name( _fixstr(mesh->get_name(),"col") );
+ Ref<Shape> shape;
+
+ if (collision_map.has(mesh)) {
+ shape = collision_map[mesh];
+
+ } else {
+
+ shape = mesh->create_trimesh_shape();
+ if (!shape.is_null())
+ collision_map[mesh]=shape;
+
+
+ }
+
+ if (!shape.is_null()) {
+#if 0
+ StaticBody* static_body = memnew( StaticBody );
+ ERR_FAIL_COND_V(!static_body,NULL);
+ static_body->set_name( String(mesh->get_name()) + "_col" );
+ shape->set_name(static_body->get_name());
+ static_body->add_shape(shape);
+
+ mi->add_child(static_body);
+ if (mi->get_owner())
+ static_body->set_owner( mi->get_owner() );
+#endif
+ }
+
+ }
+
+ for(int i=0;i<mesh->get_surface_count();i++) {
+
+ Ref<FixedSpatialMaterial> fm = mesh->surface_get_material(i);
+ if (fm.is_valid()) {
+ String name = fm->get_name();
+ /* if (_teststr(name,"alpha")) {
+ fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
+ name=_fixstr(name,"alpha");
+ }
+
+ if (_teststr(name,"vcol")) {
+ fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true);
+ name=_fixstr(name,"vcol");
+ }*/
+ fm->set_name(name);
+ }
+ }
+
+ }
+
+ }
+
+
+ return p_node;
+}
+
+
+
+
+#if 0
+
+Error EditorImport::import_scene(const String& p_path,const String& p_dest_path,const String& p_resource_path,uint32_t p_flags,ImageFormat p_image_format,ImageCompression p_image_compression,uint32_t p_image_flags,float p_quality,uint32_t animation_flags,Node **r_scene,Ref<EditorPostImport> p_post_import) {
+
+
+}
+#endif
+
+void EditorSceneImportPlugin::_tag_import_paths(Node *p_scene,Node *p_node) {
+
+ if (p_scene!=p_node && p_node->get_owner()!=p_scene)
+ return;
+
+ NodePath path = p_scene->get_path_to(p_node);
+ p_node->set_import_path( path );
+
+ Spatial *snode=p_node->cast_to<Spatial>();
+
+ if (snode) {
+
+ snode->set_import_transform(snode->get_transform());
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+ _tag_import_paths(p_scene,p_node->get_child(i));
+ }
+
+}
+
+Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from,Node**r_node,List<String> *r_missing) {
+
+ Ref<ResourceImportMetadata> from=p_from;
+
+ ERR_FAIL_COND_V(from->get_source_count()!=1,ERR_INVALID_PARAMETER);
+
+ String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
+
+ Ref<EditorSceneImporter> importer;
+ String ext=src_path.get_extension().to_lower();
+
+
+ EditorProgress progress("import",TTR("Import Scene"),104);
+ progress.step(TTR("Importing Scene.."),0);
+
+ for(int i=0;i<importers.size();i++) {
+
+ List<String> extensions;
+ importers[i]->get_extensions(&extensions);
+
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+
+ if (E->get().to_lower()==ext) {
+
+ importer = importers[i];
+ break;
+ }
+ }
+
+ if (importer.is_valid())
+ break;
+ }
+
+ ERR_FAIL_COND_V(!importer.is_valid(),ERR_FILE_UNRECOGNIZED);
+
+ int animation_flags=p_from->get_option("animation_flags");
+ int scene_flags = from->get_option("flags");
+ int fps = 24;
+ if (from->has_option("animation_bake_fps"))
+ fps=from->get_option("animation_bake_fps");
+
+
+ Array clips;
+ if (from->has_option("animation_clips"))
+ clips=from->get_option("animation_clips");
+
+ uint32_t import_flags=0;
+ if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP)
+ import_flags|=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
+ if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS)
+ import_flags |= EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS;
+ if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
+ import_flags|=EditorSceneImporter::IMPORT_ANIMATION_OPTIMIZE;
+ if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS)
+ import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS;
+ if (scene_flags&SCENE_FLAG_IMPORT_ANIMATIONS)
+ import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
+ /*
+ if (scene_flags&SCENE_FLAG_FAIL_ON_MISSING_IMAGES)
+ import_flags|=EditorSceneImporter::IMPORT_FAIL_ON_MISSING_DEPENDENCIES;
+ */
+ if (scene_flags&SCENE_FLAG_GENERATE_TANGENT_ARRAYS)
+ import_flags|=EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
+
+
+
+
+
+ Error err=OK;
+ Node *scene = importer->import_scene(src_path,import_flags,fps,r_missing,&err);
+ if (!scene || err!=OK) {
+ return err;
+ }
+
+ if (from->has_option("root_type")) {
+ String type = from->get_option("root_type");
+ Object *base = ClassDB::instance(type);
+ Node *base_node = NULL;
+ if (base)
+ base_node=base->cast_to<Node>();
+
+ if (base_node) {
+
+ scene->replace_by(base_node);
+ memdelete(scene);
+ scene=base_node;
+ }
+ }
+
+ scene->set_name(from->get_option("root_name"));
+ _tag_import_paths(scene,scene);
+
+ *r_node=scene;
+ return OK;
+}
+
+
+void EditorSceneImportPlugin::_create_clips(Node *scene, const Array& p_clips,bool p_bake_all) {
+
+ if (!scene->has_node(String("AnimationPlayer")))
+ return;
+
+ Node* n = scene->get_node(String("AnimationPlayer"));
+ ERR_FAIL_COND(!n);
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+ ERR_FAIL_COND(!anim);
+
+ if (!anim->has_animation("default"))
+ return;
+
+
+ Ref<Animation> default_anim = anim->get_animation("default");
+
+ for(int i=0;i<p_clips.size();i+=4) {
+
+ String name = p_clips[i];
+ float from=p_clips[i+1];
+ float to=p_clips[i+2];
+ bool loop=p_clips[i+3];
+ if (from>=to)
+ continue;
+
+ Ref<Animation> new_anim = memnew( Animation );
+
+ for(int j=0;j<default_anim->get_track_count();j++) {
+
+
+ List<float> keys;
+ int kc = default_anim->track_get_key_count(j);
+ int dtrack=-1;
+ for(int k=0;k<kc;k++) {
+
+ float kt = default_anim->track_get_key_time(j,k);
+ if (kt>=from && kt<to) {
+
+ //found a key within range, so create track
+ if (dtrack==-1) {
+ new_anim->add_track(default_anim->track_get_type(j));
+ dtrack = new_anim->get_track_count()-1;
+ new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
+
+ if (kt>(from+0.01) && k>0) {
+
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_interpolate(j,from,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,0,p,q,s);
+ }
+ }
+
+ }
+
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_get_key(j,k,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,kt-from,p,q,s);
+ }
+
+ }
+
+ if (dtrack!=-1 && kt>=to) {
+
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_interpolate(j,to,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
+ }
+ }
+
+ }
+
+ if (dtrack==-1 && p_bake_all) {
+ new_anim->add_track(default_anim->track_get_type(j));
+ dtrack = new_anim->get_track_count()-1;
+ new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
+ if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+
+
+ Quat q;
+ Vector3 p;
+ Vector3 s;
+ default_anim->transform_track_interpolate(j,from,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,0,p,q,s);
+ default_anim->transform_track_interpolate(j,to,&p,&q,&s);
+ new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
+ }
+
+ }
+ }
+
+
+ new_anim->set_loop(loop);
+ new_anim->set_length(to-from);
+ anim->add_animation(name,new_anim);
+ }
+
+ anim->remove_animation("default"); //remove default (no longer needed)
+}
+
+void EditorSceneImportPlugin::_filter_anim_tracks(Ref<Animation> anim,Set<String> &keep) {
+
+ Ref<Animation> a = anim;
+ ERR_FAIL_COND(!a.is_valid());
+
+ print_line("From Anim "+anim->get_name()+":");
+
+ for(int j=0;j<a->get_track_count();j++) {
+
+ String path = a->track_get_path(j);
+
+ if (!keep.has(path)) {
+
+ print_line("Remove: "+path);
+ a->remove_track(j);
+ j--;
+ }
+
+ }
+}
+
+
+void EditorSceneImportPlugin::_filter_tracks(Node *scene, const String& p_text) {
+
+ if (!scene->has_node(String("AnimationPlayer")))
+ return;
+ Node* n = scene->get_node(String("AnimationPlayer"));
+ ERR_FAIL_COND(!n);
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+ ERR_FAIL_COND(!anim);
+
+ Vector<String> strings = p_text.split("\n");
+ for(int i=0;i<strings.size();i++) {
+
+ strings[i]=strings[i].strip_edges();
+ }
+
+ List<StringName> anim_names;
+ anim->get_animation_list(&anim_names);
+ for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
+
+ String name = E->get();
+ bool valid_for_this=false;
+ bool valid=false;
+
+ Set<String> keep;
+ Set<String> keep_local;
+
+
+ for(int i=0;i<strings.size();i++) {
+
+
+ if (strings[i].begins_with("@")) {
+
+ valid_for_this=false;
+ for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
+ keep.insert(F->get());
+ }
+ keep_local.clear();
+
+ Vector<String> filters=strings[i].substr(1,strings[i].length()).split(",");
+ for(int j=0;j<filters.size();j++) {
+
+ String fname = filters[j].strip_edges();
+ if (fname=="")
+ continue;
+ int fc = fname[0];
+ bool plus;
+ if (fc=='+')
+ plus=true;
+ else if (fc=='-')
+ plus=false;
+ else
+ continue;
+
+ String filter=fname.substr(1,fname.length()).strip_edges();
+
+ if (!name.matchn(filter))
+ continue;
+ valid_for_this=plus;
+ }
+
+ if (valid_for_this)
+ valid=true;
+
+ } else if (valid_for_this) {
+
+ Ref<Animation> a = anim->get_animation(name);
+ if (!a.is_valid())
+ continue;
+
+ for(int j=0;j<a->get_track_count();j++) {
+
+ String path = a->track_get_path(j);
+
+ String tname = strings[i];
+ if (tname=="")
+ continue;
+ int fc = tname[0];
+ bool plus;
+ if (fc=='+')
+ plus=true;
+ else if (fc=='-')
+ plus=false;
+ else
+ continue;
+
+ String filter=tname.substr(1,tname.length()).strip_edges();
+
+ if (!path.matchn(filter))
+ continue;
+
+ if (plus)
+ keep_local.insert(path);
+ else if (!keep.has(path)) {
+ keep_local.erase(path);
+ }
+ }
+
+ }
+
+ }
+
+ if (valid) {
+ for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
+ keep.insert(F->get());
+ }
+ print_line("FILTERING ANIM: "+String(E->get()));
+ _filter_anim_tracks(anim->get_animation(name),keep);
+ } else {
+ print_line("NOT FILTERING ANIM: "+String(E->get()));
+
+ }
+
+ }
+
+
+
+}
+
+void EditorSceneImportPlugin::_optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle) {
+
+ if (!scene->has_node(String("AnimationPlayer")))
+ return;
+ Node* n = scene->get_node(String("AnimationPlayer"));
+ ERR_FAIL_COND(!n);
+ AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+ ERR_FAIL_COND(!anim);
+
+
+ List<StringName> anim_names;
+ anim->get_animation_list(&anim_names);
+ for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
+
+ Ref<Animation> a = anim->get_animation(E->get());
+ a->optimize(p_max_lin_error,p_max_ang_error,Math::deg2rad(p_max_angle));
+ }
+}
+
+
+void EditorSceneImportPlugin::_find_resources_to_merge(Node *scene, Node *node, bool p_merge_material, Map<String, Ref<Material> > &materials, bool p_merge_anims, Map<String,Ref<Animation> >& merged_anims,Set<Ref<Mesh> > &tested_meshes) {
+
+ if (node!=scene && node->get_owner()!=scene)
+ return;
+
+ String path = scene->get_path_to(node);
+
+ if (p_merge_anims && node->cast_to<AnimationPlayer>()) {
+
+ AnimationPlayer *ap = node->cast_to<AnimationPlayer>();
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (List<StringName>::Element *E=anims.front();E;E=E->next()) {
+ Ref<Animation> anim = ap->get_animation(E->get());
+ Ref<Animation> clone;
+
+ bool has_user_tracks=false;
+
+ for(int i=0;i<anim->get_track_count();i++) {
+
+ if (!anim->track_is_imported(i)) {
+ has_user_tracks=true;
+ break;
+ }
+ }
+
+ if (has_user_tracks) {
+
+ clone = anim->duplicate();
+ for(int i=0;i<clone->get_track_count();i++) {
+ if (clone->track_is_imported(i)) {
+ clone->remove_track(i);
+ i--;
+ }
+ }
+
+ merged_anims[path+"::"+String(E->get())]=clone;
+ }
+ }
+ }
+
+
+
+ if (p_merge_material && node->cast_to<MeshInstance>()) {
+ MeshInstance *mi=node->cast_to<MeshInstance>();
+ Ref<Mesh> mesh = mi->get_mesh();
+ if (mesh.is_valid() && mesh->get_name()!=String() && !tested_meshes.has(mesh)) {
+
+ for(int i=0;i<mesh->get_surface_count();i++) {
+ Ref<Material> material = mesh->surface_get_material(i);
+
+ if (material.is_valid()) {
+
+ String sname = mesh->surface_get_name(i);
+ if (sname=="")
+ sname="surf_"+itos(i);
+
+ sname=mesh->get_name()+":surf:"+sname;
+ materials[sname]=material;
+ }
+ }
+
+ tested_meshes.insert(mesh);
+ }
+
+ if (mesh.is_valid()) {
+
+ for(int i=0;i<mesh->get_surface_count();i++) {
+ Ref<Material> material = mi->get_surface_material(i);
+ if (material.is_valid()) {
+ String sname = mesh->surface_get_name(i);
+ if (sname=="")
+ sname="surf_"+itos(i);
+
+ sname=path+":inst_surf:"+sname;
+ materials[sname]=material;
+ }
+ }
+
+ }
+
+ Ref<Material> override = mi->get_material_override();
+
+ if (override.is_valid()) {
+
+ materials[path+":override"]=override;
+ }
+ }
+
+
+
+ for(int i=0;i<node->get_child_count();i++) {
+ _find_resources_to_merge(scene,node->get_child(i),p_merge_material,materials,p_merge_anims,merged_anims,tested_meshes);
+ }
+
+}
+
+
+void EditorSceneImportPlugin::_merge_found_resources(Node *scene, Node *node, bool p_merge_material, const Map<String, Ref<Material> > &materials, bool p_merge_anims, const Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes) {
+
+ if (node!=scene && node->get_owner()!=scene)
+ return;
+
+ String path = scene->get_path_to(node);
+
+ print_line("at path: "+path);
+
+ if (node->cast_to<AnimationPlayer>()) {
+
+ AnimationPlayer *ap = node->cast_to<AnimationPlayer>();
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ for (List<StringName>::Element *E=anims.front();E;E=E->next()) {
+ Ref<Animation> anim = ap->get_animation(E->get());
+
+ String anim_path = path+"::"+String(E->get());
+
+ if (merged_anims.has(anim_path)) {
+
+ Ref<Animation> user_tracks = merged_anims[anim_path];
+ for(int i=0;i<user_tracks->get_track_count();i++) {
+
+ int idx = anim->get_track_count();
+ anim->add_track(user_tracks->track_get_type(i));
+ anim->track_set_path(idx,user_tracks->track_get_path(i));
+ anim->track_set_interpolation_type(idx,user_tracks->track_get_interpolation_type(i));
+ for(int j=0;j<user_tracks->track_get_key_count(i);j++) {
+
+ float ofs = user_tracks->track_get_key_time(i,j);
+ float trans = user_tracks->track_get_key_transition(i,j);
+ Variant value = user_tracks->track_get_key_value(i,j);
+
+ anim->track_insert_key(idx,ofs,value,trans);
+ }
+ }
+ }
+ }
+ }
+
+
+
+ if (node->cast_to<MeshInstance>()) {
+ MeshInstance *mi=node->cast_to<MeshInstance>();
+ Ref<Mesh> mesh = mi->get_mesh();
+ if (mesh.is_valid() && mesh->get_name()!=String() && !tested_meshes.has(mesh)) {
+
+ for(int i=0;i<mesh->get_surface_count();i++) {
+
+ String sname = mesh->surface_get_name(i);
+ if (sname=="")
+ sname="surf_"+itos(i);
+
+ sname=mesh->get_name()+":surf:"+sname;
+
+
+ if (materials.has(sname)) {
+
+ mesh->surface_set_material(i,materials[sname]);
+ }
+ }
+
+ tested_meshes.insert(mesh);
+ }
+
+ if (mesh.is_valid()) {
+
+ for(int i=0;i<mesh->get_surface_count();i++) {
+
+ String sname = mesh->surface_get_name(i);
+ if (sname=="")
+ sname="surf_"+itos(i);
+
+ sname=path+":inst_surf:"+sname;
+
+
+ if (materials.has(sname)) {
+
+ mi->set_surface_material(i,materials[sname]);
+ }
+ }
+
+ }
+
+
+ String opath = path+":override";
+ if (materials.has(opath)) {
+ mi->set_material_override(materials[opath]);
+ }
+
+ }
+
+
+
+ for(int i=0;i<node->get_child_count();i++) {
+ _merge_found_resources(scene,node->get_child(i),p_merge_material,materials,p_merge_anims,merged_anims,tested_meshes);
+ }
+
+}
+
+Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
+
+ Error err=OK;
+ Ref<ResourceImportMetadata> from=p_from;
+ String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
+ int animation_flags=p_from->get_option("animation_flags");
+ Array animation_clips = p_from->get_option("animation_clips");
+ String animation_filter = p_from->get_option("animation_filters");
+ int scene_flags = from->get_option("flags");
+ float anim_optimizer_linerr=0.05;
+ float anim_optimizer_angerr=0.01;
+ float anim_optimizer_maxang=22;
+
+ if (from->has_option("animation_optimizer_linear_error"))
+ anim_optimizer_linerr=from->get_option("animation_optimizer_linear_error");
+ if (from->has_option("animation_optimizer_angular_error"))
+ anim_optimizer_angerr=from->get_option("animation_optimizer_angular_error");
+ if (from->has_option("animation_optimizer_max_angle"))
+ anim_optimizer_maxang=from->get_option("animation_optimizer_max_angle");
+
+ EditorProgress progress("import",TTR("Import Scene"),104);
+ progress.step(TTR("Importing Scene.."),2);
+
+
+ from->set_source_md5(0,FileAccess::get_md5(src_path));
+ from->set_editor(get_name());
+
+ from->set_option("reimport",false);
+ String target_res_path=p_dest_path.get_base_dir();
+
+ Map<Ref<Mesh>,Ref<Shape> > collision_map;
+
+ Map< Ref<ImageTexture>,TextureRole > imagemap;
+
+ scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
+ if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
+ _optimize_animations(scene,anim_optimizer_linerr,anim_optimizer_angerr,anim_optimizer_maxang);
+ if (animation_clips.size())
+ _create_clips(scene,animation_clips,animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
+
+ _filter_tracks(scene,animation_filter);
+
+
+ if (scene_flags&(SCENE_FLAG_MERGE_KEEP_MATERIALS|SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS) && FileAccess::exists(p_dest_path)) {
+ //must merge!
+
+ print_line("MUST MERGE");
+ Ref<PackedScene> pscene = ResourceLoader::load(p_dest_path,"PackedScene",true);
+ if (pscene.is_valid()) {
+
+ Node *instance = pscene->instance();
+ if (instance) {
+ Map<String,Ref<Animation> > merged_anims;
+ Map<String,Ref<Material> > merged_materials;
+ Set<Ref<Mesh> > tested_meshes;
+
+ _find_resources_to_merge(instance,instance,scene_flags&SCENE_FLAG_MERGE_KEEP_MATERIALS,merged_materials,scene_flags&SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,merged_anims,tested_meshes);
+
+ tested_meshes.clear();
+ _merge_found_resources(scene,scene,scene_flags&SCENE_FLAG_MERGE_KEEP_MATERIALS,merged_materials,scene_flags&SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,merged_anims,tested_meshes);
+
+ memdelete(instance);
+ }
+
+ }
+
+ }
+
+ /// BEFORE ANYTHING, RUN SCRIPT
+
+ progress.step(TTR("Running Custom Script.."),2);
+
+ String post_import_script_path = from->get_option("post_import_script");
+ Ref<EditorScenePostImport> post_import_script;
+
+ if (post_import_script_path!="") {
+ post_import_script_path = post_import_script_path;
+ Ref<Script> scr = ResourceLoader::load(post_import_script_path);
+ if (!scr.is_valid()) {
+ EditorNode::add_io_error(TTR("Couldn't load post-import script:")+" "+post_import_script_path);
+ } else {
+
+ post_import_script = Ref<EditorScenePostImport>( memnew( EditorScenePostImport ) );
+ post_import_script->set_script(scr.get_ref_ptr());
+ if (!post_import_script->get_script_instance()) {
+ EditorNode::add_io_error(TTR("Invalid/broken script for post-import (check console):")+" "+post_import_script_path);
+ post_import_script.unref();
+ return ERR_CANT_CREATE;
+ }
+ }
+ }
+
+
+ if (post_import_script.is_valid()) {
+ scene = post_import_script->post_import(scene);
+ if (!scene) {
+ EditorNode::add_io_error(TTR("Error running post-import script:")+" "+post_import_script_path);
+ return err;
+ }
+
+
+ }
+
+
+ /// IMPORT IMAGES
+
+
+ int idx=0;
+
+ int image_format = from->get_option("texture_format");
+ int image_flags = from->get_option("texture_flags");
+ float image_quality = from->get_option("texture_quality");
+
+ for (Map< Ref<ImageTexture>,TextureRole >::Element *E=imagemap.front();E;E=E->next()) {
+
+ //texture could be converted to something more useful for 3D, that could load individual mipmaps and stuff
+ //but not yet..
+
+ Ref<ImageTexture> texture = E->key();
+
+ ERR_CONTINUE(!texture.is_valid());
+
+ String path = texture->get_path();
+ String fname= path.get_file();
+ String target_path = GlobalConfig::get_singleton()->localize_path(target_res_path.plus_file(fname));
+ progress.step(TTR("Import Image:")+" "+fname,3+(idx)*100/imagemap.size());
+
+ idx++;
+
+ if (path==target_path) {
+
+ EditorNode::add_io_error(TTR("Can't import a file over itself:")+" "+target_path);
+ continue;
+ }
+
+ if (!target_path.begins_with("res://")) {
+ EditorNode::add_io_error(vformat(TTR("Couldn't localize path: %s (already local)"),target_path));
+ continue;
+ }
+
+
+ {
+
+
+ target_path=target_path.get_basename()+".tex";
+
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+
+ uint32_t flags = image_flags;
+ if (E->get()==TEXTURE_ROLE_DIFFUSE && scene_flags&SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES)
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR;
+
+ if (E->get()==TEXTURE_ROLE_NORMALMAP && scene_flags&SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY)
+ flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_NORMAL_TO_XY;
+
+ imd->set_option("flags",flags);
+ imd->set_option("format",image_format);
+ imd->set_option("quality",image_quality);
+ imd->set_option("atlas",false);
+ imd->add_source(EditorImportPlugin::validate_source_path(path));
+
+
+ if (FileAccess::exists(target_path)) {
+
+ Ref<ResourceImportMetadata> rimdex = ResourceLoader::load_import_metadata(target_path);
+ if (rimdex.is_valid()) {
+ //make sure the options are the same, otherwise re-import
+ List<String> opts;
+ imd->get_options(&opts);
+ bool differ=false;
+ for (List<String>::Element *E=opts.front();E;E=E->next()) {
+ if (!(rimdex->get_option(E->get())==imd->get_option(E->get()))) {
+ differ=true;
+ break;
+ }
+ }
+
+ if (!differ) {
+ texture->set_path(target_path);
+ continue; //already imported
+ }
+ }
+ }
+
+ EditorTextureImportPlugin::get_singleton()->import(target_path,imd);
+
+ }
+ }
+
+
+
+ progress.step(TTR("Saving.."),104);
+
+ Ref<PackedScene> packer = memnew( PackedScene );
+ packer->pack(scene);
+ //packer->set_path(p_dest_path); do not take over, let the changed files reload themselves
+ packer->set_import_metadata(from);
+
+ print_line("SAVING TO: "+p_dest_path);
+ err = ResourceSaver::save(p_dest_path,packer); //do not take over, let the changed files reload themselves
+
+ //EditorFileSystem::get_singleton()->update_resource(packer);
+
+ memdelete(scene);
+
+ /*
+ scene->set_filename(p_dest_path);
+ if (r_scene) {
+ *r_scene=scene;
+ } else {
+ memdelete(scene);
+ }
+
+ String sp;
+ if (p_post_import.is_valid() && !p_post_import->get_script().is_null()) {
+ Ref<Script> scr = p_post_import->get_script();
+ if (scr.is_valid())
+ sp=scr->get_path();
+ }
+
+ String op=_getrelpath(p_path,p_dest_path);
+
+ */
+
+ EditorNode::get_singleton()->reload_scene(p_dest_path);
+
+ return err;
+
+}
+
+
+Error EditorSceneImportPlugin::import(const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from){
+
+
+ Node *n=NULL;
+ Error err = import1(p_from,&n);
+ if (err!=OK) {
+ if (n) {
+ memdelete(n);
+ }
+ return err;
+ }
+ return import2(n,p_dest_path,p_from);
+}
+
+void EditorSceneImportPlugin::add_importer(const Ref<EditorSceneImporter>& p_importer) {
+
+ importers.push_back(p_importer);
+}
+
+void EditorSceneImportPlugin::import_from_drop(const Vector<String>& p_drop,const String& p_dest_path) {
+
+ List<String> extensions;
+ for(int i=0;i<importers.size();i++) {
+ importers[i]->get_extensions(&extensions);
+ }
+ //bool warn_compatible=false;
+ for(int i=0;i<p_drop.size();i++) {
+
+ String extension = p_drop[i].get_extension().to_lower();
+
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+
+ if (E->get()==extension) {
+
+ dialog->popup_import(String());
+ dialog->setup_popup(p_drop[i],p_dest_path);
+ return;
+ }
+ }
+ }
+
+}
+
+
+EditorSceneImportPlugin::EditorSceneImportPlugin(EditorNode* p_editor) {
+
+ dialog = memnew( EditorSceneImportDialog(p_editor,this) );
+ p_editor->get_gui_base()->add_child(dialog);
+}
+
+
+///////////////////////////////
+
+
+String EditorSceneAnimationImportPlugin::get_name() const {
+
+ return "anim_3d";
+}
+String EditorSceneAnimationImportPlugin::get_visible_name() const{
+
+
+ return TTR("3D Scene Animation");
+}
+void EditorSceneAnimationImportPlugin::import_dialog(const String& p_from){
+
+
+}
+Error EditorSceneAnimationImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
+
+ return OK;
+}
+
+EditorSceneAnimationImportPlugin::EditorSceneAnimationImportPlugin(EditorNode* p_editor) {
+
+
+}
+#endif
diff --git a/editor/io_plugins/editor_scene_import_plugin.h b/editor/io_plugins/editor_scene_import_plugin.h
new file mode 100644
index 0000000000..2ae0693600
--- /dev/null
+++ b/editor/io_plugins/editor_scene_import_plugin.h
@@ -0,0 +1,200 @@
+/*************************************************************************/
+/* editor_scene_import_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_SCENE_IMPORT_PLUGIN_H
+#define EDITOR_SCENE_IMPORT_PLUGIN_H
+#if 0
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/label.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/progress_bar.h"
+#include "scene/gui/slider.h"
+#include "scene/gui/spin_box.h"
+#include "scene/resources/mesh.h"
+#include "editor/editor_file_system.h"
+#include "editor/editor_dir_dialog.h"
+#include "editor/editor_import_export.h"
+#include "editor/io_plugins/editor_texture_import_plugin.h"
+#include "scene/resources/animation.h"
+
+
+class EditorNode;
+class EditorSceneImportDialog;
+
+class EditorSceneImporter : public Reference {
+
+ GDCLASS(EditorSceneImporter,Reference );
+public:
+
+ enum ImportFlags {
+ IMPORT_SCENE=1,
+ IMPORT_ANIMATION=2,
+ IMPORT_ANIMATION_DETECT_LOOP=4,
+ IMPORT_ANIMATION_OPTIMIZE=8,
+ IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=16,
+ IMPORT_ANIMATION_KEEP_VALUE_TRACKS=32,
+ IMPORT_GENERATE_TANGENT_ARRAYS=256,
+ IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512
+
+ };
+
+ virtual uint32_t get_import_flags() const=0;
+ virtual void get_extensions(List<String> *r_extensions) const=0;
+ virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps,Error* r_err=NULL)=0;
+ virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0;
+
+
+
+ EditorSceneImporter();
+};
+
+/////////////////////////////////////////
+
+
+//Plugin for post processing scenes or images
+
+class EditorScenePostImport : public Reference {
+
+ GDCLASS(EditorScenePostImport,Reference );
+protected:
+
+ static void _bind_methods();
+public:
+
+ virtual Node* post_import(Node* p_scene);
+ EditorScenePostImport();
+};
+
+
+class EditorSceneImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorSceneImportPlugin,EditorImportPlugin);
+
+ EditorSceneImportDialog *dialog;
+
+ Vector<Ref<EditorSceneImporter> > importers;
+
+ enum TextureRole {
+ TEXTURE_ROLE_DEFAULT,
+ TEXTURE_ROLE_DIFFUSE,
+ TEXTURE_ROLE_NORMALMAP
+ };
+
+ void _find_resources(const Variant& p_var,Map<Ref<ImageTexture>,TextureRole >& image_map,int p_flags);
+ Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map);
+ void _create_clips(Node *scene, const Array& p_clips, bool p_bake_all);
+ void _filter_anim_tracks(Ref<Animation> anim,Set<String> &keep);
+ void _filter_tracks(Node *scene, const String& p_text);
+ void _optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle);
+
+ void _tag_import_paths(Node *p_scene,Node *p_node);
+
+ void _find_resources_to_merge(Node *scene, Node *node, bool p_merge_material, Map<String,Ref<Material> >&materials, bool p_merge_anims, Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
+ void _merge_found_resources(Node *scene, Node *node, bool p_merge_material, const Map<String, Ref<Material> > &materials, bool p_merge_anims, const Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
+
+
+public:
+
+ enum SceneFlags {
+
+ SCENE_FLAG_CREATE_COLLISIONS=1<<0,
+ SCENE_FLAG_CREATE_PORTALS=1<<1,
+ SCENE_FLAG_CREATE_ROOMS=1<<2,
+ SCENE_FLAG_SIMPLIFY_ROOMS=1<<3,
+ SCENE_FLAG_CREATE_BILLBOARDS=1<<4,
+ SCENE_FLAG_CREATE_IMPOSTORS=1<<5,
+ SCENE_FLAG_CREATE_LODS=1<<6,
+ SCENE_FLAG_CREATE_CARS=1<<8,
+ SCENE_FLAG_CREATE_WHEELS=1<<9,
+ SCENE_FLAG_DETECT_ALPHA=1<<15,
+ SCENE_FLAG_DETECT_VCOLOR=1<<16,
+ SCENE_FLAG_CREATE_NAVMESH=1<<17,
+ SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
+
+ SCENE_FLAG_MERGE_KEEP_MATERIALS=1<<20,
+ SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS=1<<21,
+
+ SCENE_FLAG_REMOVE_NOIMP=1<<24,
+ SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,
+ SCENE_FLAG_COMPRESS_GEOMETRY=1<<26,
+ SCENE_FLAG_GENERATE_TANGENT_ARRAYS=1<<27,
+ SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES=1<<28,
+ SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS=1<<29,
+ SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY=1<<30,
+ };
+
+
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from="");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+
+ Error import1(const Ref<ResourceImportMetadata>& p_from,Node**r_node,List<String> *r_missing=NULL);
+ Error import2(Node* p_scene,const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+
+ void add_importer(const Ref<EditorSceneImporter>& p_importer);
+ const Vector<Ref<EditorSceneImporter> >& get_importers() { return importers; }
+
+ virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
+
+ EditorSceneImportPlugin(EditorNode* p_editor=NULL);
+
+
+};
+
+
+class EditorSceneAnimationImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorSceneAnimationImportPlugin,EditorImportPlugin);
+public:
+
+
+ enum AnimationFlags {
+
+ ANIMATION_DETECT_LOOP=1,
+ ANIMATION_KEEP_VALUE_TRACKS=2,
+ ANIMATION_OPTIMIZE=4,
+ ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=8
+ };
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from="");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+
+ EditorSceneAnimationImportPlugin(EditorNode* p_editor=NULL);
+
+
+};
+
+#endif
+#endif // EDITOR_SCENE_IMPORT_PLUGIN_H
diff --git a/editor/io_plugins/editor_scene_importer_fbxconv.cpp b/editor/io_plugins/editor_scene_importer_fbxconv.cpp
new file mode 100644
index 0000000000..d75a26a948
--- /dev/null
+++ b/editor/io_plugins/editor_scene_importer_fbxconv.cpp
@@ -0,0 +1,1136 @@
+/*************************************************************************/
+/* editor_scene_importer_fbxconv.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_scene_importer_fbxconv.h"
+
+#include "os/file_access.h"
+#include "os/os.h"
+#include "editor/editor_settings.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/animation/animation_player.h"
+
+#if 0
+String EditorSceneImporterFBXConv::_id(const String& p_id) const {
+
+ return p_id.replace(":","_").replace("/","_");
+}
+
+uint32_t EditorSceneImporterFBXConv::get_import_flags() const {
+
+ return IMPORT_SCENE|IMPORT_ANIMATION;
+}
+void EditorSceneImporterFBXConv::get_extensions(List<String> *r_extensions) const{
+
+ r_extensions->push_back("fbx");
+ r_extensions->push_back("g3dj");
+}
+
+
+Color EditorSceneImporterFBXConv::_get_color(const Array& a) {
+
+ if (a.size()<3)
+ return Color();
+ Color c;
+ c.r=a[0];
+ c.g=a[1];
+ c.b=a[2];
+ if (a.size()>=4)
+ c.a=a[3];
+ return c;
+
+}
+
+Transform EditorSceneImporterFBXConv::_get_transform_mixed(const Dictionary& d,const Dictionary& dbase) {
+
+
+
+
+ Array translation;
+
+ if (d.has("translation"))
+ translation=d["translation"];
+ else if (dbase.has("translation"))
+ translation=dbase["translation"];
+
+ Array rotation;
+
+ if (d.has("rotation"))
+ rotation=d["rotation"];
+ else if (dbase.has("rotation"))
+ rotation=dbase["rotation"];
+
+ Array scale;
+
+ if (d.has("scale"))
+ scale=d["scale"];
+ else if (dbase.has("scale"))
+ scale=dbase["scale"];
+
+ Transform t;
+
+
+ if (translation.size()) {
+ Array tr = translation;
+ if (tr.size()>=3) {
+ t.origin.x=tr[0];
+ t.origin.y=tr[1];
+ t.origin.z=tr[2];
+ }
+ }
+
+ if (rotation.size()) {
+
+ Array r = rotation;
+ if (r.size()>=4) {
+
+ Quat q;
+ q.x = r[0];
+ q.y = r[1];
+ q.z = r[2];
+ q.w = r[3];
+ t.basis=Matrix3(q);
+ }
+ }
+
+
+ if (scale.size()) {
+
+ Array sc = scale;
+ if (sc.size()>=3) {
+ Vector3 s;
+ s.x=sc[0];
+ s.y=sc[1];
+ s.z=sc[2];
+ t.basis.scale(s);
+ }
+ }
+
+ return t;
+
+
+}
+
+Transform EditorSceneImporterFBXConv::_get_transform(const Dictionary& d) {
+
+
+ Transform t;
+
+ if (d.has("translation")) {
+ Array tr = d["translation"];
+ if (tr.size()>=3) {
+ t.origin.x=tr[0];
+ t.origin.y=tr[1];
+ t.origin.z=tr[2];
+ }
+ }
+
+ if (d.has("rotation")) {
+
+ Array r = d["rotation"];
+ if (r.size()>=4) {
+
+ Quat q;
+ q.x = r[0];
+ q.y = r[1];
+ q.z = r[2];
+ q.w = r[3];
+ t.basis=Matrix3(q);
+ }
+ }
+
+
+ if (d.has("scale")) {
+
+ Array sc = d["scale"];
+ if (sc.size()>=3) {
+ Vector3 s;
+ s.x=sc[0];
+ s.y=sc[1];
+ s.z=sc[2];
+ t.basis.scale(s);
+ }
+ }
+
+ return t;
+}
+
+
+void EditorSceneImporterFBXConv::_detect_bones_in_nodes(State& state,const Array& p_nodes) {
+
+
+ for(int i=0;i<p_nodes.size();i++) {
+
+ Dictionary d = p_nodes[i];
+ if (d.has("isBone") && bool(d["isBone"])) {
+
+ String bone_name=_id(d["id"]);
+ print_line("IS BONE: "+bone_name);
+ if (!state.bones.has(bone_name)) {
+ state.bones.insert(bone_name,BoneInfo());
+ }
+
+ if (!state.bones[bone_name].has_rest) {
+ state.bones[bone_name].rest=_get_transform(d).affine_inverse();
+ }
+
+ state.bones[bone_name].node=d;
+
+ //state.bones[name].rest=_get_transform(b);
+ }
+
+ if (d.has("parts")) {
+
+ Array parts=d["parts"];
+ for(int j=0;j<parts.size();j++) {
+
+ Dictionary p=parts[j];
+ if (p.has("bones")) {
+ Array bones=p["bones"];
+ //omfg
+ for(int k=0;k<bones.size();k++) {
+
+ Dictionary b = bones[k];
+ if (b.has("node")) {
+
+ String name = _id(b["node"]);
+ if (!state.bones.has(name)) {
+ state.bones.insert(name,BoneInfo());
+ }
+
+ state.bones[name].rest=_get_transform(b);
+ state.bones[name].has_rest=true;
+ }
+ }
+ }
+
+ }
+ }
+
+ if (d.has("children")) {
+
+ _detect_bones_in_nodes(state,d["children"]);
+ }
+ }
+
+}
+
+void EditorSceneImporterFBXConv::_parse_skeletons(const String& p_name,State& state, const Array &p_nodes, Skeleton *p_skeleton,int p_parent) {
+
+
+
+ for(int i=0;i<p_nodes.size();i++) {
+
+
+ Dictionary d = p_nodes[i];
+ int bone_idx=-1;
+ String id;
+ Skeleton* skeleton=p_skeleton;
+ if (d.has("id")) {
+
+ id=_id(d["id"]);
+ if (state.bones.has(id)) {
+ //BONER
+ if (!skeleton) {
+ skeleton=memnew( Skeleton );
+ state.skeletons[id]=skeleton;
+ }
+ bone_idx = skeleton->get_bone_count();
+ skeleton->add_bone(id);
+ skeleton->set_bone_parent(bone_idx,p_parent);
+ skeleton->set_bone_rest(bone_idx,state.bones[id].rest);
+ state.bones[id].skeleton=skeleton;
+ }
+ }
+
+ if (d.has("children")) {
+
+ _parse_skeletons(id,state,d["children"],skeleton,bone_idx);
+ }
+ }
+
+}
+
+void EditorSceneImporterFBXConv::_detect_bones(State& state) {
+ //This format should mark when a node is a bone,
+ //which is the only thing that Collada does right.
+ //think about others implementing a parser.
+ //Just _one_ string and you avoid loads of lines of code to other people.
+
+ for(int i=0;i<state.animations.size();i++) {
+
+ Dictionary an = state.animations[i];
+ if (an.has("bones")) {
+
+ Array bo=an["bones"];
+ for(int j=0;j<bo.size();j++) {
+
+ Dictionary b=bo[j];
+ if (b.has("boneId")) {
+
+ String id = b["boneId"];
+ if (!state.bones.has(id)) {
+ state.bones.insert(id,BoneInfo());
+ }
+ state.bones[id].has_anim_chan=true; //used in anim
+
+
+ }
+ }
+ }
+ }
+
+ _detect_bones_in_nodes(state,state.nodes);
+ _parse_skeletons("",state,state.nodes,NULL,-1);
+
+ print_line("found bones: "+itos(state.bones.size()));
+ print_line("found skeletons: "+itos(state.skeletons.size()));
+}
+
+Error EditorSceneImporterFBXConv::_parse_bones(State& state,const Array &p_bones,Skeleton* p_skeleton) {
+
+
+
+ return OK;
+}
+
+
+void EditorSceneImporterFBXConv::_add_surface(State& state,Ref<Mesh>& m,const Dictionary &part) {
+
+ if (part.has("meshpartid")) {
+
+ String id = part["meshpartid"];
+ ERR_FAIL_COND(!state.surface_cache.has(id));
+
+
+ Ref<Material> mat;
+ if (part.has("materialid")) {
+ String matid=part["materialid"];
+ if (state.material_cache.has(matid)) {
+ mat=state.material_cache[matid];
+ }
+ }
+ int idx = m->get_surface_count();
+
+ Array array = state.surface_cache[id].array;
+ PoolVector<float> indices = array[Mesh::ARRAY_BONES];
+ if (indices.size() && part.has("bones")) {
+
+
+ Map<int,int> index_map;
+
+ Array bones=part["bones"];
+
+ for(int i=0;i<bones.size();i++) {
+
+ Dictionary bone=bones[i];
+ String name=_id(bone["node"]);
+
+ if (state.bones.has(name)) {
+ int idx=state.bones[name].skeleton->find_bone(name);
+ if (idx==-1)
+ idx=0;
+ index_map[i]=idx;
+ }
+ }
+
+
+
+ int ilen=indices.size();
+ {
+ PoolVector<float>::Write iw=indices.write();
+ for(int j=0;j<ilen;j++) {
+ int b = iw[j];
+ ERR_CONTINUE(!index_map.has(b));
+ b=index_map[b];
+ iw[j]=b;
+ }
+ }
+
+ array[Mesh::ARRAY_BONES]=indices;
+
+
+ }
+
+ m->add_surface(state.surface_cache[id].primitive,array);
+ m->surface_set_material(idx,mat);
+ m->surface_set_name(idx,id);
+ }
+
+}
+
+Error EditorSceneImporterFBXConv::_parse_nodes(State& state,const Array &p_nodes,Node* p_base) {
+
+ for(int i=0;i<p_nodes.size();i++) {
+
+ Dictionary n = p_nodes[i];
+ Spatial *node=NULL;
+ bool skip=false;
+
+ String id;
+ if (n.has("id")) {
+ id=_id(n["id"]);
+ }
+
+ print_line("ID: "+id);
+
+ if (state.skeletons.has(id)) {
+
+ Skeleton *skeleton = state.skeletons[id];
+ node=skeleton;
+ skeleton->localize_rests();
+ print_line("IS SKELETON! ");
+ } else if (state.bones.has(id)) {
+ if (p_base)
+ node=p_base->cast_to<Spatial>();
+ if (!state.bones[id].has_anim_chan) {
+ print_line("no has anim "+id);
+ }
+ skip=true;
+ } else if (n.has("parts")) {
+ //is a mesh
+ MeshInstance *mesh = memnew( MeshInstance );
+ node=mesh;
+
+ Array parts=n["parts"];
+ String long_identifier;
+ for(int j=0;j<parts.size();j++) {
+
+ Dictionary part=parts[j];
+ if (part.has("meshpartid")) {
+ String partid=part["meshpartid"];
+ long_identifier+=partid;
+ }
+ }
+
+ Ref<Mesh> m;
+
+ if (state.mesh_cache.has(long_identifier)) {
+ m=state.mesh_cache[long_identifier];
+ } else {
+ m = Ref<Mesh>( memnew( Mesh ) );
+
+ //and parts are surfaces
+ for(int j=0;j<parts.size();j++) {
+
+ Dictionary part=parts[j];
+ if (part.has("meshpartid")) {
+ _add_surface(state,m,part);
+ }
+ }
+
+
+ state.mesh_cache[long_identifier]=m;
+ }
+
+ mesh->set_mesh(m);
+ }
+
+ if (!skip) {
+
+ if (!node) {
+ node = memnew( Spatial );
+ }
+
+ node->set_name(id);
+ node->set_transform(_get_transform(n));
+ p_base->add_child(node);
+ node->set_owner(state.scene);
+ }
+
+
+ if (n.has("children")) {
+ Error err = _parse_nodes(state,n["children"],node);
+ if (err)
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+
+void EditorSceneImporterFBXConv::_parse_materials(State& state) {
+
+ for(int i=0;i<state.materials.size();i++) {
+
+ Dictionary material = state.materials[i];
+
+ ERR_CONTINUE(!material.has("id"));
+ String id = _id(material["id"]);
+
+ Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
+
+ if (material.has("diffuse")) {
+ mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,_get_color(material["diffuse"]));
+ }
+
+ if (material.has("specular")) {
+ mat->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR,_get_color(material["specular"]));
+ }
+
+ if (material.has("emissive")) {
+ mat->set_parameter(FixedSpatialMaterial::PARAM_EMISSION,_get_color(material["emissive"]));
+ }
+
+ if (material.has("shininess")) {
+ float exp = material["shininess"];
+ mat->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR_EXP,exp);
+ }
+
+ if (material.has("opacity")) {
+ Color c = mat->get_parameter(FixedSpatialMaterial::PARAM_DIFFUSE);
+ c.a=material["opacity"];
+ mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,c);
+ }
+
+
+ if (material.has("textures")) {
+
+ Array textures = material["textures"];
+ for(int j=0;j<textures.size();j++) {
+
+ Dictionary texture=textures[j];
+ Ref<Texture> tex;
+ if (texture.has("filename")) {
+
+
+ String filename=texture["filename"];
+ String path=state.base_path+"/"+filename.replace("\\","/");
+ if (state.texture_cache.has(path)) {
+ tex=state.texture_cache[path];
+ } else {
+ tex = ResourceLoader::load(path,"ImageTexture");
+ if (tex.is_null()) {
+ if (state.missing_deps)
+ state.missing_deps->push_back(path);
+ }
+ state.texture_cache[path]=tex; //add anyway
+ }
+ }
+
+ if (tex.is_valid() && texture.has("type")) {
+
+ String type=texture["type"];
+ if (type=="DIFFUSE")
+ mat->set_texture(FixedSpatialMaterial::PARAM_DIFFUSE,tex);
+ else if (type=="SPECULAR")
+ mat->set_texture(FixedSpatialMaterial::PARAM_SPECULAR,tex);
+ else if (type=="SHININESS")
+ mat->set_texture(FixedSpatialMaterial::PARAM_SPECULAR_EXP,tex);
+ else if (type=="NORMAL")
+ mat->set_texture(FixedSpatialMaterial::PARAM_NORMAL,tex);
+ else if (type=="EMISSIVE")
+ mat->set_texture(FixedSpatialMaterial::PARAM_EMISSION,tex);
+ }
+
+ }
+ }
+
+ state.material_cache[id]=mat;
+
+ }
+
+}
+
+void EditorSceneImporterFBXConv::_parse_surfaces(State& state) {
+
+ for(int i=0;i<state.meshes.size();i++) {
+
+ Dictionary mesh = state.meshes[i];
+
+ ERR_CONTINUE(!mesh.has("attributes"));
+ ERR_CONTINUE(!mesh.has("vertices"));
+ ERR_CONTINUE(!mesh.has("parts"));
+
+ print_line("MESH #"+itos(i));
+
+ Array attrlist=mesh["attributes"];
+ Array vertices=mesh["vertices"];
+ bool exists[Mesh::ARRAY_MAX];
+ int ofs[Mesh::ARRAY_MAX];
+ int weight_max=0;
+ int binormal_ofs=-1;
+ int weight_ofs[4];
+
+ for(int j=0;j<Mesh::ARRAY_MAX;j++) {
+ exists[j]=false;
+ ofs[j]=0;
+ }
+ exists[Mesh::ARRAY_INDEX]=true;
+ float stride=0;
+
+ for(int j=0;j<attrlist.size();j++) {
+
+ String attr=attrlist[j];
+ if (attr=="POSITION") {
+ exists[Mesh::ARRAY_VERTEX]=true;
+ ofs[Mesh::ARRAY_VERTEX]=stride;
+ stride+=3;
+ } else if (attr=="NORMAL") {
+ exists[Mesh::ARRAY_NORMAL]=true;
+ ofs[Mesh::ARRAY_NORMAL]=stride;
+ stride+=3;
+ } else if (attr=="COLOR") {
+ exists[Mesh::ARRAY_COLOR]=true;
+ ofs[Mesh::ARRAY_COLOR]=stride;
+ stride+=4;
+ } else if (attr=="COLORPACKED") {
+ stride+=1; //ignore
+ } else if (attr=="TANGENT") {
+ exists[Mesh::ARRAY_TANGENT]=true;
+ ofs[Mesh::ARRAY_TANGENT]=stride;
+ stride+=3;
+ } else if (attr=="BINORMAL") {
+ binormal_ofs=stride;
+ stride+=3;
+ } else if (attr=="TEXCOORD0") {
+ exists[Mesh::ARRAY_TEX_UV]=true;
+ ofs[Mesh::ARRAY_TEX_UV]=stride;
+ stride+=2;
+ } else if (attr=="TEXCOORD1") {
+ exists[Mesh::ARRAY_TEX_UV2]=true;
+ ofs[Mesh::ARRAY_TEX_UV2]=stride;
+ stride+=2;
+ } else if (attr.begins_with("TEXCOORD")) {
+ stride+=2;
+ } else if (attr.begins_with("BLENDWEIGHT")) {
+ int idx=attr.replace("BLENDWEIGHT","").to_int();
+ if (idx==0) {
+ exists[Mesh::ARRAY_BONES]=true;
+ ofs[Mesh::ARRAY_BONES]=stride;
+ exists[Mesh::ARRAY_WEIGHTS]=true;
+ ofs[Mesh::ARRAY_WEIGHTS]=stride+1;
+ } if (idx<4) {
+ weight_ofs[idx]=stride;
+ weight_max=MAX(weight_max,idx+1);
+ }
+
+ stride+=2;
+ }
+
+ print_line("ATTR "+attr+" OFS: "+itos(stride));
+
+ }
+
+ Array parts=mesh["parts"];
+
+ for(int j=0;j<parts.size();j++) {
+
+
+
+ Dictionary part=parts[j];
+ ERR_CONTINUE(!part.has("indices"));
+ ERR_CONTINUE(!part.has("id"));
+
+ print_line("PART: "+String(part["id"]));
+ Array indices=part["indices"];
+ Map<int,int> iarray;
+ Map<int,int> array;
+
+ for(int k=0;k<indices.size();k++) {
+
+ int idx = indices[k];
+ if (!iarray.has(idx)) {
+ int map_to=array.size();
+ iarray[idx]=map_to;
+ array[map_to]=idx;
+ }
+ }
+
+ print_line("indices total "+itos(indices.size())+" vertices used: "+itos(array.size()));
+
+ Array arrays;
+ arrays.resize(Mesh::ARRAY_MAX);
+
+
+
+ for(int k=0;k<Mesh::ARRAY_MAX;k++) {
+
+
+ if (!exists[k])
+ continue;
+ print_line("exists: "+itos(k));
+ int lofs = ofs[k];
+ switch(k) {
+
+ case Mesh::ARRAY_VERTEX:
+ case Mesh::ARRAY_NORMAL: {
+
+ PoolVector<Vector3> vtx;
+ vtx.resize(array.size());
+ {
+ int len=array.size();
+ PoolVector<Vector3>::Write w = vtx.write();
+ for(int l=0;l<len;l++) {
+
+ int pos = array[l];
+ w[l].x=vertices[pos*stride+lofs+0];
+ w[l].y=vertices[pos*stride+lofs+1];
+ w[l].z=vertices[pos*stride+lofs+2];
+ }
+ }
+ arrays[k]=vtx;
+
+ } break;
+ case Mesh::ARRAY_TANGENT: {
+
+ if (binormal_ofs<0)
+ break;
+
+ PoolVector<float> tangents;
+ tangents.resize(array.size()*4);
+ {
+ int len=array.size();
+
+ PoolVector<float>::Write w = tangents.write();
+ for(int l=0;l<len;l++) {
+
+ int pos = array[l];
+ Vector3 n;
+ n.x=vertices[pos*stride+ofs[Mesh::ARRAY_NORMAL]+0];
+ n.y=vertices[pos*stride+ofs[Mesh::ARRAY_NORMAL]+1];
+ n.z=vertices[pos*stride+ofs[Mesh::ARRAY_NORMAL]+2];
+ Vector3 t;
+ t.x=vertices[pos*stride+lofs+0];
+ t.y=vertices[pos*stride+lofs+1];
+ t.z=vertices[pos*stride+lofs+2];
+ Vector3 bi;
+ bi.x=vertices[pos*stride+binormal_ofs+0];
+ bi.y=vertices[pos*stride+binormal_ofs+1];
+ bi.z=vertices[pos*stride+binormal_ofs+2];
+ float d = bi.dot(n.cross(t));
+
+ w[l*4+0]=t.x;
+ w[l*4+1]=t.y;
+ w[l*4+2]=t.z;
+ w[l*4+3]=d;
+
+ }
+ }
+ arrays[k]=tangents;
+
+ } break;
+ case Mesh::ARRAY_COLOR: {
+
+ PoolVector<Color> cols;
+ cols.resize(array.size());
+ {
+ int len=array.size();
+ PoolVector<Color>::Write w = cols.write();
+ for(int l=0;l<len;l++) {
+
+ int pos = array[l];
+ w[l].r=vertices[pos*stride+lofs+0];
+ w[l].g=vertices[pos*stride+lofs+1];
+ w[l].b=vertices[pos*stride+lofs+2];
+ w[l].a=vertices[pos*stride+lofs+3];
+ }
+ }
+ arrays[k]=cols;
+
+ } break;
+ case Mesh::ARRAY_TEX_UV:
+ case Mesh::ARRAY_TEX_UV2: {
+
+ PoolVector<Vector2> uvs;
+ uvs.resize(array.size());
+ {
+ int len=array.size();
+ PoolVector<Vector2>::Write w = uvs.write();
+ for(int l=0;l<len;l++) {
+
+ int pos = array[l];
+ w[l].x=vertices[pos*stride+lofs+0];
+ w[l].y=vertices[pos*stride+lofs+1];
+ w[l].y=1.0-w[l].y;
+ }
+ }
+ arrays[k]=uvs;
+
+ } break;
+ case Mesh::ARRAY_BONES:
+ case Mesh::ARRAY_WEIGHTS: {
+
+ PoolVector<float> arr;
+ arr.resize(array.size()*4);
+ int po=k==Mesh::ARRAY_WEIGHTS?1:0;
+ lofs=ofs[Mesh::ARRAY_BONES];
+ {
+ int len=array.size();
+
+ PoolVector<float>::Write w = arr.write();
+ for(int l=0;l<len;l++) {
+
+ int pos = array[l];
+
+ for(int m=0;m<4;m++) {
+
+ float val=0;
+ if (m<=weight_max)
+ val=vertices[pos*stride+lofs+m*2+po];
+ w[l*4+m]=val;
+ }
+ }
+ }
+
+ arrays[k]=arr;
+ } break;
+ case Mesh::ARRAY_INDEX: {
+
+ PoolVector<int> arr;
+ arr.resize(indices.size());
+ {
+ int len=indices.size();
+
+ PoolVector<int>::Write w = arr.write();
+ for(int l=0;l<len;l++) {
+
+ w[l]=iarray[ indices[l] ];
+ }
+ }
+
+ arrays[k]=arr;
+
+ } break;
+
+
+ }
+
+
+ }
+
+ Mesh::PrimitiveType pt=Mesh::PRIMITIVE_TRIANGLES;
+
+ if (part.has("type")) {
+ String type=part["type"];
+ if (type=="LINES")
+ pt=Mesh::PRIMITIVE_LINES;
+ else if (type=="POINTS")
+ pt=Mesh::PRIMITIVE_POINTS;
+ else if (type=="TRIANGLE_STRIP")
+ pt=Mesh::PRIMITIVE_TRIANGLE_STRIP;
+ else if (type=="LINE_STRIP")
+ pt=Mesh::PRIMITIVE_LINE_STRIP;
+ }
+
+ if (pt==Mesh::PRIMITIVE_TRIANGLES) {
+ PoolVector<int> ia=arrays[Mesh::ARRAY_INDEX];
+ int len=ia.size();
+ {
+ PoolVector<int>::Write w=ia.write();
+ for(int l=0;l<len;l+=3) {
+ SWAP(w[l+1],w[l+2]);
+ }
+ }
+ arrays[Mesh::ARRAY_INDEX]=ia;
+
+
+ }
+ SurfaceInfo si;
+ si.array=arrays;
+ si.primitive=pt;
+ state.surface_cache[_id(part["id"])]=si;
+
+ }
+ }
+}
+
+
+Error EditorSceneImporterFBXConv::_parse_animations(State& state) {
+
+ AnimationPlayer *ap = memnew( AnimationPlayer );
+
+ state.scene->add_child(ap);
+ ap->set_owner(state.scene);
+
+ for(int i=0;i<state.animations.size();i++) {
+
+ Dictionary anim = state.animations[i];
+ ERR_CONTINUE(!anim.has("id"));
+ Ref<Animation> an = memnew( Animation );
+ an->set_name(_id(anim["id"]));
+
+
+ if (anim.has("bones")) {
+
+ Array bone_tracks = anim["bones"];
+ for(int j=0;j<bone_tracks.size();j++) {
+ Dictionary bone_track=bone_tracks[j];
+ String bone = bone_track["boneId"];
+ if (!bone_track.has("keyframes"))
+ continue;
+ if (!state.bones.has(bone))
+ continue;
+
+ Skeleton *sk = state.bones[bone].skeleton;
+
+ if (!sk)
+ continue;
+ int bone_idx=sk->find_bone(bone);
+ if (bone_idx==-1)
+ continue;
+
+
+
+ String path = state.scene->get_path_to(sk);
+ path+=":"+bone;
+ an->add_track(Animation::TYPE_TRANSFORM);
+ int tidx = an->get_track_count()-1;
+ an->track_set_path(tidx,path);
+
+
+ Dictionary parent_xform_dict;
+ Dictionary xform_dict;
+
+ if (state.bones.has(bone)) {
+ xform_dict=state.bones[bone].node;
+ }
+
+
+ Array parent_keyframes;
+ if (sk->get_bone_parent(bone_idx)!=-1) {
+ String parent_name = sk->get_bone_name(sk->get_bone_parent(bone_idx));
+ if (state.bones.has(parent_name)) {
+ parent_xform_dict=state.bones[parent_name].node;
+ }
+
+ print_line("parent for "+bone+"? "+parent_name+" XFD: "+String(Variant(parent_xform_dict)));
+ for(int k=0;k<bone_tracks.size();k++) {
+ Dictionary d = bone_tracks[k];
+ if (d["boneId"]==parent_name) {
+ parent_keyframes=d["keyframes"];
+ print_line("found keyframes");
+ break;
+ }
+ }
+
+
+ }
+
+ print_line("BONE XFD "+String(Variant(xform_dict)));
+
+ Array keyframes=bone_track["keyframes"];
+
+ for(int k=0;k<keyframes.size();k++) {
+
+ Dictionary key=keyframes[k];
+ Transform xform=_get_transform_mixed(key,xform_dict);
+ float time = key["keytime"];
+ time=time/1000.0;
+#if 0
+ if (parent_keyframes.size()) {
+ //localize
+ print_line(itos(k)+" localizate for: "+bone);
+
+ float prev_kt=-1;
+ float kt;
+ int idx=0;
+
+ for(int l=0;l<parent_keyframes.size();l++) {
+
+ Dictionary d=parent_keyframes[l];
+ kt=d["keytime"];
+ kt=kt/1000.0;
+ if (kt>time)
+ break;
+ prev_kt=kt;
+ idx++;
+
+ }
+
+ Transform t;
+ if (idx==0) {
+ t=_get_transform_mixed(parent_keyframes[0],parent_xform_dict);
+ } else if (idx==parent_keyframes.size()){
+ t=_get_transform_mixed(parent_keyframes[idx-1],parent_xform_dict);
+ } else {
+ t=_get_transform_mixed(parent_keyframes[idx-1],parent_xform_dict);
+ float d = (time-prev_kt)/(kt-prev_kt);
+ if (d>0) {
+ Transform t2=_get_transform_mixed(parent_keyframes[idx],parent_xform_dict);
+ t=t.interpolate_with(t2,d);
+ } else {
+ print_line("exact: "+rtos(kt));
+ }
+ }
+
+ xform = t.affine_inverse() * xform; //localize
+ } else if (!parent_xform_dict.empty()) {
+ Transform t = _get_transform(parent_xform_dict);
+ xform = t.affine_inverse() * xform; //localize
+ }
+#endif
+
+ xform = sk->get_bone_rest(bone_idx).affine_inverse() * xform;
+
+
+ Quat q = xform.basis;
+ q.normalize();
+ Vector3 s = xform.basis.get_scale();
+ Vector3 l = xform.origin;
+
+
+
+ an->transform_track_insert_key(tidx,time,l,q,s);
+
+ }
+
+ }
+
+
+ }
+
+
+ ap->add_animation(_id(anim["id"]),an);
+
+ }
+
+ return OK;
+}
+
+Error EditorSceneImporterFBXConv::_parse_json(State& state, const String &p_path) {
+
+ //not the happiest....
+ Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
+ ERR_FAIL_COND_V(!data.size(),ERR_FILE_CANT_OPEN);
+ String str;
+ bool utferr = str.parse_utf8((const char*)data.ptr(),data.size());
+ ERR_FAIL_COND_V(utferr,ERR_PARSE_ERROR);
+
+ Dictionary dict;
+ Error err = dict.parse_json(str);
+ str=String(); //free mem immediately
+ ERR_FAIL_COND_V(err,err);
+
+ if (dict.has("meshes"))
+ state.meshes=dict["meshes"];
+ if (dict.has("materials"))
+ state.materials=dict["materials"];
+ if (dict.has("nodes"))
+ state.nodes=dict["nodes"];
+ if (dict.has("animations"))
+ state.animations=dict["animations"];
+
+
+ state.scene = memnew( Spatial );
+ _detect_bones(state);
+ _parse_surfaces(state);
+ _parse_materials(state);
+ err = _parse_nodes(state,state.nodes,state.scene);
+ if (err)
+ return err;
+
+ if (state.import_animations) {
+ err = _parse_animations(state);
+ if (err)
+ return err;
+ }
+
+ print_line("JSON PARSED O-K!");
+
+ return OK;
+}
+
+Error EditorSceneImporterFBXConv::_parse_fbx(State& state,const String& p_path) {
+
+ state.base_path=p_path.get_base_dir();
+
+ if (p_path.to_lower().ends_with("g3dj")) {
+ return _parse_json(state,p_path.basename()+".g3dj");
+ }
+
+ String tool = EDITOR_DEF("fbxconv/path","");
+ ERR_FAIL_COND_V( !FileAccess::exists(tool),ERR_UNCONFIGURED);
+ String wine = EDITOR_DEF("fbxconv/use_wine","");
+
+ List<String> args;
+ String path=p_path;
+ if (wine!="") {
+ List<String> wpargs;
+ wpargs.push_back("-w");
+ wpargs.push_back(p_path);
+ String pipe; //winepath to convert to windows path
+ int wpres;
+ Error wperr = OS::get_singleton()->execute(wine+"path",wpargs,true,NULL,&pipe,&wpres);
+ ERR_FAIL_COND_V(wperr!=OK,ERR_CANT_CREATE);
+ ERR_FAIL_COND_V(wpres!=0,ERR_CANT_CREATE);
+ path=pipe.strip_edges();
+ args.push_back(tool);
+ tool=wine;
+ }
+
+ args.push_back("-o");
+ args.push_back("G3DJ");
+ args.push_back(path);
+
+ int res;
+ Error err = OS::get_singleton()->execute(tool,args,true,NULL,NULL,&res);
+ ERR_FAIL_COND_V(err!=OK,ERR_CANT_CREATE);
+ ERR_FAIL_COND_V(res!=0,ERR_CANT_CREATE);
+
+ return _parse_json(state,p_path.basename()+".g3dj");
+
+
+}
+
+Node* EditorSceneImporterFBXConv::import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps,Error* r_err){
+
+ State state;
+ state.scene=NULL;
+ state.missing_deps=r_missing_deps;
+ state.import_animations=p_flags&IMPORT_ANIMATION;
+ Error err = _parse_fbx(state,p_path);
+ if (err!=OK) {
+ if (r_err)
+ *r_err=err;
+ return NULL;
+ }
+
+
+ return state.scene;
+}
+Ref<Animation> EditorSceneImporterFBXConv::import_animation(const String& p_path,uint32_t p_flags){
+
+
+ return Ref<Animation>();
+}
+
+
+EditorSceneImporterFBXConv::EditorSceneImporterFBXConv() {
+
+ EDITOR_DEF("fbxconv/path","");
+#ifndef WINDOWS_ENABLED
+ EDITOR_DEF("fbxconv/use_wine","");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"fbxconv/use_wine",PROPERTY_HINT_GLOBAL_FILE));
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"fbxconv/path",PROPERTY_HINT_GLOBAL_FILE));
+#else
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"fbxconv/path",PROPERTY_HINT_GLOBAL_FILE,"exe"));
+#endif
+
+}
+#endif
diff --git a/editor/io_plugins/editor_scene_importer_fbxconv.h b/editor/io_plugins/editor_scene_importer_fbxconv.h
new file mode 100644
index 0000000000..da7058ad88
--- /dev/null
+++ b/editor/io_plugins/editor_scene_importer_fbxconv.h
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* editor_scene_importer_fbxconv.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_SCENE_IMPORTER_FBXCONV_H
+#define EDITOR_SCENE_IMPORTER_FBXCONV_H
+
+#include "editor/io_plugins/editor_scene_import_plugin.h"
+#include "scene/3d/skeleton.h"
+
+#if 0
+
+class EditorSceneImporterFBXConv : public EditorSceneImporter {
+
+ GDCLASS(EditorSceneImporterFBXConv,EditorSceneImporter );
+
+
+ struct BoneInfo {
+
+ Skeleton *skeleton;
+ Transform rest;
+ int index;
+ bool has_anim_chan;
+ bool has_rest;
+ Dictionary node;
+ BoneInfo() {
+ has_rest=false;
+ skeleton=NULL;
+ index=-1;
+ has_anim_chan=false;
+ }
+ };
+
+ struct SurfaceInfo {
+ Array array;
+ Mesh::PrimitiveType primitive;
+ };
+
+ struct State {
+
+ Node *scene;
+ Array meshes;
+ Array materials;
+ Array nodes;
+ Array animations;
+ Map<String,BoneInfo > bones;
+ Map<String,Skeleton*> skeletons;
+ Map<String,Ref<Mesh> > mesh_cache;
+ Map<String,SurfaceInfo> surface_cache;
+ Map<String,Ref<Material> > material_cache;
+ Map<String,Ref<Texture> > texture_cache;
+ List<String> *missing_deps;
+ String base_path;
+ bool import_animations;
+ };
+
+ String _id(const String& p_id) const;
+
+ Transform _get_transform_mixed(const Dictionary& d, const Dictionary& dbase);
+ Transform _get_transform(const Dictionary& d);
+ Color _get_color(const Array& a);
+ void _detect_bones_in_nodes(State& state,const Array& p_nodes);
+ void _detect_bones(State& state);
+
+ Error _parse_bones(State& state,const Array &p_bones,Skeleton* p_skeleton);
+ void _parse_skeletons(const String& p_name,State& state, const Array &p_nodes, Skeleton*p_skeleton=NULL, int p_parent=-1);
+
+ void _add_surface(State& state,Ref<Mesh>& m,const Dictionary &part);
+ Error _parse_nodes(State& state,const Array &p_nodes,Node* p_base);
+ Error _parse_animations(State& state);
+ void _parse_materials(State& state);
+ void _parse_surfaces(State& state);
+ Error _parse_json(State& state,const String& p_path);
+ Error _parse_fbx(State &state, const String &p_path);
+
+public:
+
+ virtual uint32_t get_import_flags() const;
+ virtual void get_extensions(List<String> *r_extensions) const;
+ virtual Node* import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps=NULL,Error* r_err=NULL);
+ virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
+
+ EditorSceneImporterFBXConv();
+};
+
+#endif // EDITOR_SCENE_IMPORTER_FBXCONV_H
+#endif
diff --git a/editor/io_plugins/editor_texture_import_plugin.cpp b/editor/io_plugins/editor_texture_import_plugin.cpp
new file mode 100644
index 0000000000..8bafe80673
--- /dev/null
+++ b/editor/io_plugins/editor_texture_import_plugin.cpp
@@ -0,0 +1,1893 @@
+/*************************************************************************/
+/* editor_texture_import_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_texture_import_plugin.h"
+#if 0
+#include "io/image_loader.h"
+#include "editor/editor_node.h"
+#include "io/resource_saver.h"
+#include "editor_atlas.h"
+#include "editor/editor_settings.h"
+#include "io/md5.h"
+#include "io/marshalls.h"
+#include "global_config.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/button_group.h"
+#include "scene/gui/margin_container.h"
+#include "scene/io/resource_format_image.h"
+
+static const char *flag_names[]={
+ ("Streaming Format"),
+ ("Fix Border Alpha"),
+ ("Alpha Bit Hint"),
+ ("Compress Extra (PVRTC2)"),
+ ("No MipMaps"),
+ ("Repeat"),
+ ("Filter (Magnifying)"),
+ ("Premultiply Alpha"),
+ ("Convert SRGB->Linear"),
+ ("Convert NormalMap to XY"),
+ ("Use Anisotropy"),
+ NULL
+};
+
+#if 0 // not used
+static const char *flag_short_names[]={
+ "Stream",
+ "FixBorder",
+ "AlphBit",
+ "ExtComp",
+ "NoMipMap",
+ "Repeat",
+ "Filter",
+ "PMAlpha",
+ "ToLinear",
+ "ToRG",
+ "Anisoropic",
+ NULL
+};
+#endif
+
+
+void EditorImportTextureOptions::set_format(EditorTextureImportPlugin::ImageFormat p_format) {
+
+ updating=true;
+ format->select(p_format);
+ if (p_format==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
+ quality_vb->show();
+ } else {
+ quality_vb->hide();
+ }
+
+ updating=false;
+
+}
+
+EditorTextureImportPlugin::ImageFormat EditorImportTextureOptions::get_format() const{
+
+ return (EditorTextureImportPlugin::ImageFormat)format->get_selected();
+
+}
+
+void EditorImportTextureOptions::set_flags(uint32_t p_flags){
+
+ updating=true;
+ for(int i=0;i<items.size();i++) {
+
+ items[i]->set_checked(0,p_flags&(1<<i));
+ }
+ updating=false;
+
+}
+
+void EditorImportTextureOptions::set_quality(float p_quality) {
+
+ quality->set_value(p_quality);
+}
+
+float EditorImportTextureOptions::get_quality() const {
+
+ return quality->get_value();
+}
+
+
+uint32_t EditorImportTextureOptions::get_flags() const{
+
+ uint32_t f=0;
+ for(int i=0;i<items.size();i++) {
+
+ if (items[i]->is_checked(0))
+ f|=(1<<i);
+ }
+
+ return f;
+}
+
+void EditorImportTextureOptions::_changedp(int p_value) {
+
+ _changed();
+}
+
+void EditorImportTextureOptions::_changed() {
+
+ if (updating)
+ return;
+ if (format->get_selected()==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
+ quality_vb->show();
+ } else {
+ quality_vb->hide();
+ }
+
+ emit_signal("changed");
+}
+
+
+void EditorImportTextureOptions::_bind_methods() {
+
+ ClassDB::bind_method("_changed",&EditorImportTextureOptions::_changed);
+ ClassDB::bind_method("_changedp",&EditorImportTextureOptions::_changedp);
+
+ ADD_SIGNAL(MethodInfo("changed"));
+}
+
+
+void EditorImportTextureOptions::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ flags->connect("item_edited",this,"_changed");
+ format->connect("item_selected",this,"_changedp");
+ }
+}
+
+void EditorImportTextureOptions::show_2d_notice() {
+
+ //notice_for_2d->show();
+}
+
+EditorImportTextureOptions::EditorImportTextureOptions() {
+
+
+ add_constant_override("separation",3);
+ updating=false;
+ format = memnew( OptionButton );
+
+ format->add_item(TTR("Uncompressed"),EditorTextureImportPlugin::IMAGE_FORMAT_UNCOMPRESSED);
+ format->add_item(TTR("Compress Lossless (PNG)"),EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS);
+ format->add_item(TTR("Compress Lossy (WebP)"),EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
+ format->add_item(TTR("Compress (VRAM)"),EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
+
+
+ add_margin_child(TTR("Texture Format"),format);
+
+ quality_vb = memnew( VBoxContainer );
+
+ HBoxContainer *quality_hb = memnew(HBoxContainer);
+ HSlider *hs = memnew( HSlider );
+ hs->set_h_size_flags(SIZE_EXPAND_FILL);
+ hs->set_stretch_ratio(0.8);
+ quality_hb->add_child(hs);
+ quality_hb->set_h_size_flags(SIZE_EXPAND_FILL);
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_h_size_flags(SIZE_EXPAND_FILL);
+ sb->set_stretch_ratio(0.2);
+ quality_hb->add_child(sb);
+ sb->share(hs);
+ hs->set_min(0);
+ hs->set_max(1.0);
+ hs->set_step(0.01);
+ hs->set_value(0.7);
+ quality=hs;
+ quality_vb->add_margin_child(TTR("Texture Compression Quality (WebP):"),quality_hb);
+
+ add_child(quality_vb);
+
+ flags = memnew( Tree );
+ flags->set_hide_root(true);
+ TreeItem *root = flags->create_item();
+
+
+
+ const char ** fname=flag_names;
+
+ while( *fname ) {
+
+ TreeItem*ti = flags->create_item(root);
+ ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ ti->set_text(0,*fname);
+ ti->set_editable(0,true);
+ items.push_back(ti);
+ fname++;
+ }
+
+ add_margin_child(TTR("Texture Options"),flags,true);
+
+
+}
+
+///////////////////////////////////////////////////////////
+
+
+
+
+class EditorTextureImportDialog : public ConfirmationDialog {
+
+ GDCLASS(EditorTextureImportDialog,ConfirmationDialog);
+
+
+
+ HBoxContainer *mode_hb;
+ CheckBox *mode_check[EditorTextureImportPlugin::MODE_MAX];
+
+ EditorImportTextureOptions *texture_options;
+
+ EditorTextureImportPlugin::Mode mode;
+ //EditorNode *editor;
+
+ LineEdit *import_path;
+ LineEdit *save_path;
+ EditorFileDialog *file_select;
+ EditorFileDialog *save_file_select;
+ EditorDirDialog *save_select;
+ OptionButton *texture_action;
+ ConfirmationDialog *error_dialog;
+ CheckButton *crop_source;
+ SpinBox *size;
+
+ MarginContainer *size_mc;
+ Label* size_label;
+
+ Label* source_label;
+ Label *notice_for_2d;
+
+ EditorTextureImportPlugin *plugin;
+
+ void _mode_changed(int p_mode);
+ void _choose_files(const Vector<String>& p_path);
+ void _choose_file(const String& p_path);
+ void _choose_save_dir(const String& p_path);
+ void _browse();
+ void _browse_target();
+ void _import();
+
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+
+ void setup_multiple_import_3d(const Vector<String>& p_path,const String& p_dest) {
+
+ _mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_3D);
+ _choose_files(p_path);
+ _choose_save_dir(p_dest);
+ }
+
+ void add_sources_and_dest(const Vector<String>& p_path,const String& p_dest) {
+
+ _choose_files(p_path);
+ _choose_save_dir(p_dest);
+ }
+
+ Error import(const String& p_from, const String& p_to, const String& p_preset);
+ void popup_import(const String &p_from=String());
+ EditorTextureImportDialog(EditorTextureImportPlugin *p_plugin=NULL);
+};
+
+
+/////////////////////////////////////////////////////////
+
+
+
+
+void EditorTextureImportDialog::_choose_files(const Vector<String>& p_path) {
+
+ String files;
+ for(int i=0;i<p_path.size();i++) {
+
+ if (i>0)
+ files+=",";
+ files+=p_path[i];
+ }
+ /*
+ if (p_path.size()) {
+ String srctex=p_path[0];
+ String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
+
+ if (ipath!="")
+ save_path->set_text(ipath.get_base_dir());
+ }*/
+ import_path->set_text(files);
+
+}
+
+
+
+void EditorTextureImportDialog::_choose_file(const String& p_path) {
+
+
+ import_path->set_text(p_path);
+
+}
+void EditorTextureImportDialog::_choose_save_dir(const String& p_path) {
+
+ save_path->set_text(p_path);
+}
+
+
+void EditorTextureImportDialog::_import() {
+
+
+ //ImportMonitorBlock imb;
+
+ Vector<String> files=import_path->get_text().split(",");
+
+ if (!files.size()) {
+
+ error_dialog->set_text(TTR("Please specify some files!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+ }
+
+ String dst_path=save_path->get_text();
+
+ if (save_path->get_text().strip_edges()=="") {
+ error_dialog->set_text(TTR("Target path is empty."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (!save_path->get_text().begins_with("res://")) {
+ error_dialog->set_text(TTR("Target path must be a complete resource path."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+
+ if (mode!=EditorTextureImportPlugin::MODE_ATLAS && mode!=EditorTextureImportPlugin::MODE_LARGE && !DirAccess::exists(save_path->get_text())) {
+ error_dialog->set_text(TTR("Target path must exist."));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (mode==EditorTextureImportPlugin::MODE_ATLAS) { //atlas
+
+ if (files.size()==0) {
+
+ error_dialog->set_text(TTR("At least one file needed for Atlas."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+
+ }
+ String dst_file = dst_path;
+ //dst_file=dst_file.basename()+".tex";
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+ //imd->set_editor();
+ for(int i=0;i<files.size();i++) {
+ imd->add_source(EditorImportPlugin::validate_source_path(files[i]));
+ }
+ imd->set_option("format",texture_options->get_format());
+ imd->set_option("flags",texture_options->get_flags());
+ imd->set_option("quality",texture_options->get_quality());
+ imd->set_option("atlas",true);
+ imd->set_option("atlas_size",int(size->get_value()));
+ imd->set_option("large",false);
+ imd->set_option("crop",crop_source->is_pressed());
+ imd->set_option("mode",mode);
+
+ Error err = plugin->import(dst_file,imd);
+ if (err) {
+
+ error_dialog->set_text(TTR("Error importing:")+" "+dst_file.get_file());
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+
+ }
+ } else if (mode==EditorTextureImportPlugin::MODE_LARGE) { //large
+
+ if (files.size()!=1) {
+
+ error_dialog->set_text(TTR("Only one file is required for large texture."));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+
+ }
+ String dst_file = dst_path;
+ //dst_file=dst_file.basename()+".tex";
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+ //imd->set_editor();
+ for(int i=0;i<files.size();i++) {
+ imd->add_source(EditorImportPlugin::validate_source_path(files[i]));
+ }
+ imd->set_option("format",texture_options->get_format());
+ imd->set_option("flags",texture_options->get_flags());
+ imd->set_option("quality",texture_options->get_quality());
+ imd->set_option("atlas",false);
+ imd->set_option("large",true);
+ imd->set_option("large_cell_size",int(size->get_value()));
+ imd->set_option("crop",crop_source->is_pressed());
+ imd->set_option("mode",mode);
+
+ Error err = plugin->import(dst_file,imd);
+ if (err) {
+
+ error_dialog->set_text(TTR("Error importing:")+" "+dst_file.get_file());
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+
+ }
+ } else {
+
+
+ for(int i=0;i<files.size();i++) {
+
+ String dst_file = dst_path.plus_file(files[i].get_file());
+ dst_file=dst_file.get_basename()+".tex";
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+ //imd->set_editor();
+ imd->add_source(EditorImportPlugin::validate_source_path(files[i]));
+ imd->set_option("format",texture_options->get_format());
+ imd->set_option("flags",texture_options->get_flags());
+ imd->set_option("quality",texture_options->get_quality());
+ imd->set_option("atlas",false);
+ imd->set_option("large",false);
+ imd->set_option("mode",mode);
+
+ Error err = plugin->import(dst_file,imd);
+ if (err) {
+
+ error_dialog->set_text(TTR("Error importing:")+" "+dst_file.get_file());
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+
+ }
+ }
+ }
+
+ hide();
+}
+
+void EditorTextureImportDialog::_browse() {
+
+ file_select->popup_centered_ratio();
+}
+
+void EditorTextureImportDialog::_browse_target() {
+
+ if (mode==EditorTextureImportPlugin::MODE_ATLAS || mode==EditorTextureImportPlugin::MODE_LARGE) {
+ save_file_select->popup_centered_ratio();
+ } else {
+ save_select->popup_centered_ratio();
+ }
+
+}
+
+
+void EditorTextureImportDialog::popup_import(const String& p_from) {
+
+ popup_centered(Size2(600,500)*EDSCALE);
+ if (p_from!="") {
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
+ ERR_FAIL_COND(!rimd.is_valid());
+
+ if (rimd->has_option("mode")) {
+ //new imported stuff uses this option
+ _mode_changed(rimd->get_option("mode"));
+ } else {
+ //this one is for compatibility, will have to guess it
+ if (rimd->has_option("atlas") && rimd->get_option("atlas")) {
+ _mode_changed(EditorTextureImportPlugin::MODE_ATLAS);
+ } else if (rimd->has_option("large") && rimd->get_option("large")) {
+ _mode_changed(EditorTextureImportPlugin::MODE_LARGE);
+ } else {
+ //guess by usage of mipmaps..?
+ _mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_2D);
+ }
+
+ }
+
+ if (mode==EditorTextureImportPlugin::MODE_ATLAS || mode==EditorTextureImportPlugin::MODE_LARGE)
+ save_path->set_text(p_from);
+ else
+ save_path->set_text(p_from.get_base_dir());
+
+ texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("format"))));
+ texture_options->set_flags(rimd->get_option("flags"));
+ texture_options->set_quality(rimd->get_option("quality"));
+ String src = "";
+ for(int i=0;i<rimd->get_source_count();i++) {
+ if (i>0)
+ src+=",";
+ src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
+ }
+ import_path->set_text(src);
+ }
+}
+
+
+void EditorTextureImportDialog::_notification(int p_what) {
+
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+
+ List<String> extensions;
+ ImageLoader::get_recognized_extensions(&extensions);
+ //ResourceLoader::get_recognized_extensions_for_type("PackedTexture",&extensions);
+ file_select->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ file_select->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+ }
+}
+
+Error EditorTextureImportDialog::import(const String& p_from, const String& p_to, const String& p_preset) {
+
+
+ import_path->set_text(p_from);
+ save_path->set_text(p_to);
+ _import();
+
+ return OK;
+}
+
+void EditorTextureImportDialog::_mode_changed(int p_mode) {
+
+ mode = EditorTextureImportPlugin::Mode(p_mode);
+
+ for(int i=0;i<EditorTextureImportPlugin::MODE_MAX;i++) {
+ mode_check[i]->set_pressed(i==mode);
+ }
+
+ if (p_mode==EditorTextureImportPlugin::MODE_ATLAS) {
+
+ size_label->set_text(TTR("Max Texture Size:"));
+ size->set_value(2048);
+ crop_source->show();
+ size_label->show();
+ size->show();
+
+ texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
+ texture_options->set_quality(0.7);
+ texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
+ set_title(TTR("Import Textures for Atlas (2D)"));
+
+ } else {
+ crop_source->hide();
+ }
+
+
+ if (p_mode==EditorTextureImportPlugin::MODE_LARGE) {
+
+ size_label->set_text(TTR("Cell Size:"));
+ size->set_value(256);
+ size_label->show();
+ size->show();
+
+ file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ save_file_select->add_filter("*.ltex;"+TTR("Large Texture"));
+
+ texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
+ texture_options->set_quality(0.7);
+ texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS);
+ set_title(TTR("Import Large Textures (2D)"));
+ source_label->set_text(TTR("Source Texture"));
+
+ } else {
+ file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+ save_file_select->add_filter("*.tex;"+TTR("Base Atlas Texture"));
+ source_label->set_text(TTR("Source Texture(s)"));
+ }
+
+ if (p_mode==EditorTextureImportPlugin::MODE_TEXTURE_2D) {
+
+ size_label->hide();
+ size->hide();
+
+ texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
+ texture_options->set_quality(0.7);
+ texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
+ notice_for_2d->show();
+ set_title(TTR("Import Textures for 2D"));
+
+ } else {
+ notice_for_2d->hide();
+ }
+
+ if (p_mode==EditorTextureImportPlugin::MODE_TEXTURE_3D) {
+
+ size_label->hide();
+ size->hide();
+ //texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_);
+ //texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS);
+ texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER|EditorTextureImportPlugin::IMAGE_FLAG_REPEAT);
+ texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
+ set_title(TTR("Import Textures for 3D"));
+ }
+}
+
+void EditorTextureImportDialog::_bind_methods() {
+
+
+ ClassDB::bind_method("_choose_files",&EditorTextureImportDialog::_choose_files);
+ ClassDB::bind_method("_choose_file",&EditorTextureImportDialog::_choose_file);
+ ClassDB::bind_method("_choose_save_dir",&EditorTextureImportDialog::_choose_save_dir);
+ ClassDB::bind_method("_import",&EditorTextureImportDialog::_import);
+ ClassDB::bind_method("_browse",&EditorTextureImportDialog::_browse);
+ ClassDB::bind_method("_browse_target",&EditorTextureImportDialog::_browse_target);
+ ClassDB::bind_method("_mode_changed",&EditorTextureImportDialog::_mode_changed);
+ //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
+}
+
+EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* p_plugin) {
+
+
+
+
+
+ plugin=p_plugin;
+ set_title(TTR("Import Textures"));
+
+ mode_hb = memnew( HBoxContainer );
+ add_child(mode_hb);
+ //set_child_rect(mode_hb);
+
+ VBoxContainer *vbcg = memnew( VBoxContainer);
+
+
+ mode_hb->add_child(vbcg);
+ mode_hb->add_constant_override("separation",15);
+ VBoxContainer *bg = memnew( VBoxContainer );
+ vbcg->add_margin_child("Import Mode",bg);
+
+ for(int i=0;i<EditorTextureImportPlugin::MODE_MAX;i++) {
+ String mode_name[EditorTextureImportPlugin::MODE_MAX]={
+ TTR("2D Texture"),
+ TTR("3D Texture"),
+ TTR("Atlas Texture"),
+ TTR("Large Texture")
+ };
+
+
+ mode_check[i]=memnew(CheckBox);
+ bg->add_child(mode_check[i]);
+ mode_check[i]->set_text(mode_name[i]);
+ mode_check[i]->connect("pressed",this,"_mode_changed",varray(i));
+ }
+
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ mode_hb->add_child(vbc);
+ vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbc->add_constant_override("separation",4);
+
+ notice_for_2d = memnew( Label );
+ notice_for_2d->set_text(TTR("NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to the project."));
+ //notice_for_2d->set_custom_minimum_size(Size2(0,50));
+ notice_for_2d->set_autowrap(true);
+ notice_for_2d->hide();
+ vbcg->add_child(notice_for_2d);
+ notice_for_2d->set_v_size_flags(SIZE_EXPAND_FILL);
+ notice_for_2d->set_valign(Label::VALIGN_BOTTOM);
+
+ VBoxContainer *source_vb=memnew(VBoxContainer);
+ MarginContainer *source_mc = vbc->add_margin_child(TTR("Source Texture(s):"),source_vb);
+
+ source_label = vbc->get_child(source_mc->get_index()-1)->cast_to<Label>();
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ source_vb->add_child(hbc);
+
+ import_path = memnew( LineEdit );
+ import_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(import_path);
+ crop_source = memnew( CheckButton );
+ crop_source->set_pressed(true);
+ source_vb->add_child(crop_source);
+ crop_source->set_text(TTR("Crop empty space."));
+
+
+ Button * import_choose = memnew( Button );
+ import_choose->set_text(" .. ");
+ hbc->add_child(import_choose);
+
+ import_choose->connect("pressed", this,"_browse");
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_margin_child(TTR("Target Path:"),hbc);
+
+ size = memnew( SpinBox );
+ size->set_min(128);
+ size->set_max(16384);
+
+
+ size->set_value(256);
+ size_mc=vbc->add_margin_child(TTR("Cell Size:"),size);
+ size_label=vbc->get_child(size_mc->get_index()-1)->cast_to<Label>();
+
+
+ save_path = memnew( LineEdit );
+ save_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(save_path);
+
+ Button * save_choose = memnew( Button );
+ save_choose->set_text(" .. ");
+ hbc->add_child(save_choose);
+
+ save_choose->connect("pressed", this,"_browse_target");
+
+ file_select = memnew(EditorFileDialog);
+ file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ add_child(file_select);
+
+ file_select->connect("files_selected", this,"_choose_files");
+ file_select->connect("file_selected", this,"_choose_file");
+
+ save_file_select = memnew(EditorFileDialog);
+ save_file_select->set_access(EditorFileDialog::ACCESS_RESOURCES);
+ add_child(save_file_select);
+ save_file_select->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ save_file_select->clear_filters();
+
+ save_file_select->connect("file_selected", this,"_choose_save_dir");
+
+ save_select = memnew( EditorDirDialog );
+ add_child(save_select);
+
+ //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
+ save_select->connect("dir_selected", this,"_choose_save_dir");
+
+ get_ok()->connect("pressed", this,"_import");
+ get_ok()->set_text(TTR("Import"));
+
+ //move stuff up
+ /*
+ for(int i=0;i<4;i++)
+ vbc->move_child( vbc->get_child( vbc->get_child_count() -1), 0);
+ */
+
+ error_dialog = memnew ( ConfirmationDialog );
+ add_child(error_dialog);
+ error_dialog->get_ok()->set_text(TTR("Accept"));
+ //error_dialog->get_cancel()->hide();
+
+ set_hide_on_ok(false);
+
+ texture_options = memnew( EditorImportTextureOptions );
+ vbc->add_child(texture_options);
+ texture_options->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ _mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_3D);
+
+
+ //GLOBAL_DEF("import/shared_textures","res://");
+ //Globals::get_singleton()->set_custom_property_info("import/shared_textures",PropertyInfo(Variant::STRING,"import/shared_textures",PROPERTY_HINT_DIR));
+
+
+}
+
+
+
+///////////////////////////////////////////////////////////
+
+
+String EditorTextureImportPlugin::get_name() const {
+
+ return "texture";
+#if 0 //old names, kept for compatibility reference
+ switch(mode) {
+ case MODE_TEXTURE_2D: {
+
+ return "texture_2d";
+ } break;
+ case MODE_TEXTURE_3D: {
+
+ return "texture_3d";
+
+ } break;
+ case MODE_ATLAS: {
+
+ return "texture_atlas";
+ } break;
+ case MODE_LARGE: {
+
+ return "texture_large";
+ } break;
+
+ }
+
+
+ return "";
+#endif
+}
+
+String EditorTextureImportPlugin::get_visible_name() const {
+
+ return TTR("Texture");
+
+}
+void EditorTextureImportPlugin::import_dialog(const String& p_from) {
+
+ dialog->popup_import(p_from);
+}
+
+void EditorTextureImportPlugin::compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller) {
+
+
+ switch(p_mode) {
+ case EditorExportPlatform::IMAGE_COMPRESSION_NONE: {
+
+ //do absolutely nothing
+
+ } break;
+ case EditorExportPlatform::IMAGE_COMPRESSION_BC: {
+
+
+ // for maximum compatibility, BC shall always use mipmaps and be PO2
+ image.resize_to_po2();
+ if (!image.has_mipmaps())
+ image.generate_mipmaps();
+
+ image.compress(Image::COMPRESS_S3TC);
+ /*
+ if (has_alpha) {
+
+ if (flags&IMAGE_FLAG_ALPHA_BIT) {
+ image.convert(Image::FORMAT_DXT5);
+ } else {
+ image.convert(Image::FORMAT_DXT3);
+ }
+ } else {
+
+ image.convert(Image::FORMAT_DXT1);
+ }*/
+
+
+ } break;
+ case EditorExportPlatform::IMAGE_COMPRESSION_PVRTC:
+ case EditorExportPlatform::IMAGE_COMPRESSION_PVRTC_SQUARE: {
+
+ // for maximum compatibility (hi apple!), PVRT shall always
+ // use mipmaps, be PO2 and square
+
+ if (!image.has_mipmaps())
+ image.generate_mipmaps();
+ image.resize_to_po2(true);
+
+ if (p_smaller) {
+
+ image.compress(Image::COMPRESS_PVRTC2);
+ //image.convert(has_alpha ? Image::FORMAT_PVRTC2A : Image::FORMAT_PVRTC2);
+ } else {
+ image.compress(Image::COMPRESS_PVRTC4);
+ //image.convert(has_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4);
+ }
+
+ } break;
+ case EditorExportPlatform::IMAGE_COMPRESSION_ETC1: {
+
+ image.resize_to_po2(); //square or not?
+ if (!image.has_mipmaps())
+ image.generate_mipmaps();
+ if (!image.detect_alpha()) {
+ //ETC1 is only opaque
+ image.compress(Image::COMPRESS_ETC);
+ }
+
+ } break;
+ case EditorExportPlatform::IMAGE_COMPRESSION_ETC2: {
+
+
+ } break;
+ }
+
+
+}
+
+Error EditorTextureImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
+
+
+ return import2(p_path,p_from,EditorExportPlatform::IMAGE_COMPRESSION_BC,false);
+}
+
+
+Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &texture,int format, float quality,int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink) {
+
+
+ if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
+
+ Image image=texture->get_data();
+ ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
+
+ bool has_alpha=image.detect_alpha();
+ if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
+
+ image.convert(Image::FORMAT_RGB8);
+
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
+
+ image.fix_alpha_edges();
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
+
+ image.premultiply_alpha();
+ }
+
+ if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
+ image.normalmap_to_xy();
+ }
+
+ /*
+ if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+
+ image.srgb_to_linear();
+ }
+ */
+
+ if (shrink>1) {
+
+ int orig_w=image.get_width();
+ int orig_h=image.get_height();
+ image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC);
+ texture->create_from_image(image,tex_flags);
+ texture->set_size_override(Size2(orig_w,orig_h));
+
+
+ } else {
+
+ texture->create_from_image(image,tex_flags);
+ }
+
+
+ if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS) {
+ texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSLESS);
+ } else {
+ texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
+ }
+
+
+
+ texture->set_lossy_storage_quality(quality);
+
+
+ } else {
+
+
+ Image image=texture->get_data();
+ ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
+
+
+ bool has_alpha=image.detect_alpha();
+ if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
+
+ image.convert(Image::FORMAT_RGB8);
+
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
+
+ image.fix_alpha_edges();
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
+
+ image.premultiply_alpha();
+ }
+
+ if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
+ image.normalmap_to_xy();
+ }
+
+ /*
+ if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+
+ print_line("CONVERT BECAUSE: "+itos(flags));
+ image.srgb_to_linear();
+ }
+ */
+
+ int orig_w=image.get_width();
+ int orig_h=image.get_height();
+
+ if (shrink>1) {
+ image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC);
+ texture->create_from_image(image,tex_flags);
+ texture->set_size_override(Size2(orig_w,orig_h));
+ }
+
+ if (!(flags&IMAGE_FLAG_NO_MIPMAPS)) {
+ image.generate_mipmaps();
+
+ }
+
+ if (format!=IMAGE_FORMAT_UNCOMPRESSED) {
+
+ compress_image(p_compr,image,flags&IMAGE_FLAG_COMPRESS_EXTRA);
+ }
+
+
+ texture->create_from_image(image,tex_flags);
+
+
+ if (shrink>1 || (format!=IMAGE_FORMAT_UNCOMPRESSED && (image.get_width()!=orig_w || image.get_height()!=orig_h))) {
+ texture->set_size_override(Size2(orig_w,orig_h));
+ }
+
+ //uint32_t save_flags=ResourceSaver::FLAG_COMPRESS;
+ }
+
+ return OK;
+}
+
+
+Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<ResourceImportMetadata>& p_from,EditorExportPlatform::ImageCompression p_compr, bool p_external){
+
+
+
+ ERR_FAIL_COND_V(p_from->get_source_count()==0,ERR_INVALID_PARAMETER);
+
+ Ref<ResourceImportMetadata> from=p_from;
+
+ Ref<ImageTexture> texture;
+ Vector<Ref<AtlasTexture> > atlases;
+ bool atlas = from->get_option("atlas");
+ bool large = from->get_option("large");
+
+ int flags=from->get_option("flags");
+ int format=from->get_option("format");
+ float quality=from->get_option("quality");
+
+ uint32_t tex_flags=0;
+
+ if (flags&EditorTextureImportPlugin::IMAGE_FLAG_REPEAT)
+ tex_flags|=Texture::FLAG_REPEAT;
+ if (flags&EditorTextureImportPlugin::IMAGE_FLAG_FILTER)
+ tex_flags|=Texture::FLAG_FILTER;
+ if (!(flags&EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS))
+ tex_flags|=Texture::FLAG_MIPMAPS;
+ if (flags&EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR)
+ tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR;
+ if (flags&EditorTextureImportPlugin::IMAGE_FLAG_USE_ANISOTROPY)
+ tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER;
+
+ print_line("path: "+p_path+" flags: "+itos(tex_flags));
+ float shrink=1;
+ if (from->has_option("shrink"))
+ shrink=from->get_option("shrink");
+
+ if (large) {
+ ERR_FAIL_COND_V(from->get_source_count()!=1,ERR_INVALID_PARAMETER);
+
+ String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
+
+
+ int cell_size=from->get_option("large_cell_size");
+ ERR_FAIL_COND_V(cell_size<128 || cell_size>16384,ERR_CANT_OPEN);
+
+ EditorProgress pg("ltex",TTR("Import Large Texture"),3);
+
+ pg.step(TTR("Load Source Image"),0);
+ Image img;
+ Error err = ImageLoader::load_image(src_path,&img);
+ if (err) {
+ return err;
+ }
+
+ pg.step(TTR("Slicing"),1);
+
+ Map<Vector2,Image> pieces;
+ for(int i=0;i<img.get_width();i+=cell_size) {
+ int w = MIN(img.get_width()-i,cell_size);
+ for(int j=0;j<img.get_height();j+=cell_size) {
+ int h = MIN(img.get_height()-j,cell_size);
+
+ Image piece(w,h,0,img.get_format());
+ piece.blit_rect(img,Rect2(i,j,w,h),Point2(0,0));
+ if (!piece.is_invisible()) {
+ pieces[Vector2(i,j)]=piece;
+ //print_line("ADDING PIECE AT "+Vector2(i,j));
+ }
+ }
+ }
+
+ Ref<LargeTexture> existing;
+ if (ResourceCache::has(p_path)) {
+ existing = ResourceCache::get(p_path);
+ }
+
+ if (existing.is_valid()) {
+ existing->clear();
+ } else {
+ existing = Ref<LargeTexture>(memnew( LargeTexture ));
+ }
+
+ existing->set_size(Size2(img.get_width(),img.get_height()));
+ pg.step(TTR("Inserting"),2);
+
+ for (Map<Vector2,Image>::Element *E=pieces.front();E;E=E->next()) {
+
+ Ref<ImageTexture> imgtex = Ref<ImageTexture>( memnew( ImageTexture ) );
+ imgtex->create_from_image(E->get(),tex_flags);
+ _process_texture_data(imgtex,format,quality,flags,p_compr,tex_flags,shrink);
+ existing->add_piece(E->key(),imgtex);
+ }
+
+ if (!p_external) {
+ from->set_editor(get_name());
+ from->set_source_md5(0,FileAccess::get_md5(src_path));
+ existing->set_path(p_path);
+ existing->set_import_metadata(from);
+ }
+ pg.step(TTR("Saving"),3);
+
+ err = ResourceSaver::save(p_path,existing);
+ if (err!=OK) {
+ EditorNode::add_io_error(TTR("Couldn't save large texture:")+" "+p_path);
+ return err;
+ }
+
+ return OK;
+
+
+ } else if (atlas) {
+
+ //prepare atlas!
+ Vector< Image > sources;
+ Vector< Image > tsources;
+ bool alpha=false;
+ bool crop = from->get_option("crop");
+
+ EditorProgress ep("make_atlas",TTR("Build Atlas For:")+" "+p_path.get_file(),from->get_source_count()+3);
+
+ print_line("sources: "+itos(from->get_source_count()));
+
+ for(int i=0;i<from->get_source_count();i++) {
+
+ String path = EditorImportPlugin::expand_source_path(from->get_source_path(i));
+ String md5 = FileAccess::get_md5(path);
+ from->set_source_md5(i,FileAccess::get_md5(path));
+ ep.step(TTR("Loading Image:")+" "+path,i);
+ print_line("source path: "+path+" md5 "+md5);
+ Image src;
+ Error err = ImageLoader::load_image(path,&src);
+ if (err) {
+ EditorNode::add_io_error(TTR("Couldn't load image:")+" "+path);
+ return err;
+ }
+
+ if (src.detect_alpha())
+ alpha=true;
+
+ tsources.push_back(src);
+ }
+ ep.step(TTR("Converting Images"),sources.size());
+
+
+ Map<uint64_t,int> source_md5;
+ Map<int,List<int> > source_map;
+
+ for(int i=0;i<tsources.size();i++) {
+
+ Image src = tsources[i];
+
+ if (alpha) {
+ src.convert(Image::FORMAT_RGBA8);
+ } else {
+ src.convert(Image::FORMAT_RGB8);
+ }
+
+ PoolVector<uint8_t> data = src.get_data();
+ MD5_CTX md5;
+ PoolVector<uint8_t>::Read r=data.read();
+ MD5Init(&md5);
+ int len=data.size();
+ for(int j=0;j<len;j++) {
+ uint8_t b = r[j];
+ b>>=2; //to aid in comparing
+ MD5Update(&md5,(unsigned char*)&b,1);
+ }
+ MD5Final(&md5);
+ uint64_t *cmp = (uint64_t*)md5.digest; //less bits, but still useful for this
+
+ tsources[i]=Image(); //clear
+
+ if (source_md5.has(*cmp)) {
+ int sidx=source_md5[*cmp];
+ source_map[sidx].push_back(i);
+ print_line("REUSING "+from->get_source_path(i));
+
+ } else {
+ int sidx=sources.size();
+ source_md5[*cmp]=sidx;
+ sources.push_back(src);
+ List<int> sm;
+ sm.push_back(i);
+ source_map[sidx]=sm;
+
+ }
+
+
+ }
+
+ //texturepacker is not really good for optimizing, so..
+ //will at some point likely replace with my own
+ //first, will find the nearest to a square packing
+ int border=1;
+
+ Vector<Size2i> src_sizes;
+ Vector<Rect2> crops;
+
+ ep.step(TTR("Cropping Images"),sources.size()+1);
+
+ for(int j=0;j<sources.size();j++) {
+
+ Size2i s;
+ if (crop) {
+ Rect2 crop = sources[j].get_used_rect();
+ print_line("CROP: "+crop);
+ s=crop.size;
+ crops.push_back(crop);
+ } else {
+
+ s=Size2i(sources[j].get_width(),sources[j].get_height());
+ }
+ s+=Size2i(border*2,border*2);
+ src_sizes.push_back(s); //add a line to constraint width
+ }
+
+ Vector<Point2i> dst_positions;
+ Size2i dst_size;
+ EditorAtlas::fit(src_sizes,dst_positions,dst_size);
+
+ print_line("size that worked: "+itos(dst_size.width)+","+itos(dst_size.height));
+
+ ep.step(TTR("Blitting Images"),sources.size()+2);
+
+ bool blit_to_po2=tex_flags&Texture::FLAG_MIPMAPS;
+ int atlas_w=dst_size.width;
+ int atlas_h=dst_size.height;
+ if (blit_to_po2) {
+ atlas_w=nearest_power_of_2(dst_size.width);
+ atlas_h=nearest_power_of_2(dst_size.height);
+ }
+ Image atlas;
+ atlas.create(atlas_w,atlas_h,0,alpha?Image::FORMAT_RGBA8:Image::FORMAT_RGB8);
+
+
+ atlases.resize(from->get_source_count());
+
+ for(int i=0;i<sources.size();i++) {
+
+ int x=dst_positions[i].x;
+ int y=dst_positions[i].y;
+
+ Size2 sz = Size2(sources[i].get_width(),sources[i].get_height());
+
+ Rect2 region;
+ Rect2 margin;
+
+ if (crop && sz!=crops[i].size) {
+ Rect2 rect = crops[i];
+ rect.size=sz-rect.size;
+ region=Rect2(x+border,y+border,crops[i].size.width,crops[i].size.height);
+ margin=rect;
+ atlas.blit_rect(sources[i],crops[i],Point2(x+border,y+border));
+ } else {
+ region=Rect2(x+border,y+border,sz.x,sz.y);
+ atlas.blit_rect(sources[i],Rect2(0,0,sources[i].get_width(),sources[i].get_height()),Point2(x+border,y+border));
+ }
+
+ ERR_CONTINUE( !source_map.has(i) );
+ for (List<int>::Element *E=source_map[i].front();E;E=E->next()) {
+
+ String apath;
+ String spath = from->get_source_path(E->get()).get_file();
+
+ if (p_external) {
+ apath = p_path.get_base_dir().plus_file(spath.get_basename()+"."+from->get_source_path(E->get()).md5_text()+".atex");
+ } else {
+ apath = p_path.get_base_dir().plus_file(spath.get_basename()+".atex");
+ }
+
+ Ref<AtlasTexture> at;
+
+ if (ResourceCache::has(apath)) {
+
+ at = Ref<AtlasTexture>( ResourceCache::get(apath)->cast_to<AtlasTexture>() );
+ } else {
+
+ at = Ref<AtlasTexture>( memnew( AtlasTexture ) );
+
+ }
+ at->set_region(region);
+ at->set_margin(margin);
+ at->set_path(apath);
+ atlases[E->get()]=at;
+
+ }
+ }
+ if (ResourceCache::has(p_path)) {
+ texture = Ref<ImageTexture> ( ResourceCache::get(p_path)->cast_to<ImageTexture>() );
+ } else {
+ texture = Ref<ImageTexture>( memnew( ImageTexture ) );
+ }
+ texture->create_from_image(atlas,tex_flags);
+
+ } else {
+ ERR_FAIL_COND_V(from->get_source_count()!=1,ERR_INVALID_PARAMETER);
+
+ String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
+
+ if (ResourceCache::has(p_path)) {
+ Resource *r = ResourceCache::get(p_path);
+
+ texture = Ref<ImageTexture> ( r->cast_to<ImageTexture>() );
+
+ Image img;
+ Error err = img.load(src_path);
+ ERR_FAIL_COND_V(err!=OK,ERR_CANT_OPEN);
+ texture->create_from_image(img);
+ } else {
+ texture=ResourceLoader::load(src_path,"ImageTexture");
+ }
+
+ ERR_FAIL_COND_V(texture.is_null(),ERR_CANT_OPEN);
+ if (!p_external)
+ from->set_source_md5(0,FileAccess::get_md5(src_path));
+
+ }
+
+
+
+ if (!p_external) {
+ from->set_editor(get_name());
+ texture->set_path(p_path);
+ texture->set_import_metadata(from);
+ }
+
+ if (atlas) {
+
+ if (p_external) {
+ //used by exporter
+ Array rects;
+ for(int i=0;i<atlases.size();i++) {
+ rects.push_back(atlases[i]->get_region());
+ rects.push_back(atlases[i]->get_margin());
+ }
+ from->set_option("rects",rects);
+
+ } else {
+ //used by importer
+ for(int i=0;i<atlases.size();i++) {
+ String apath = atlases[i]->get_path();
+ atlases[i]->set_atlas(texture);
+ Error err = ResourceSaver::save(apath,atlases[i]);
+ if (err) {
+ EditorNode::add_io_error(TTR("Couldn't save atlas image:")+" "+apath);
+ return err;
+ }
+ //from->set_source_md5(i,FileAccess::get_md5(apath));
+ }
+ }
+ }
+
+ bool compress=false;
+#if 1
+
+ _process_texture_data(texture,format,quality,flags,p_compr,tex_flags,shrink);
+#else
+ if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
+
+ Image image=texture->get_data();
+ ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
+
+ bool has_alpha=image.detect_alpha();
+ if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
+
+ image.convert(Image::FORMAT_RGB8);
+
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
+
+ image.fix_alpha_edges();
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
+
+ image.premultiply_alpha();
+ }
+
+ if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
+ image.normalmap_to_xy();
+ }
+
+ /*
+ if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+
+ image.srgb_to_linear();
+ }
+ */
+
+ if (shrink>1) {
+
+ int orig_w=image.get_width();
+ int orig_h=image.get_height();
+ image.resize(orig_w/shrink,orig_h/shrink);
+ texture->create_from_image(image,tex_flags);
+ texture->set_size_override(Size2(orig_w,orig_h));
+
+
+ } else {
+
+ texture->create_from_image(image,tex_flags);
+ }
+
+
+ if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS) {
+ texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSLESS);
+ } else {
+ texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
+ }
+
+
+
+ texture->set_lossy_storage_quality(quality);
+
+
+ } else {
+
+
+ Image image=texture->get_data();
+ ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
+
+
+ bool has_alpha=image.detect_alpha();
+ if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
+
+ image.convert(Image::FORMAT_RGB8);
+
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
+
+ image.fix_alpha_edges();
+ }
+
+ if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
+
+ image.premultiply_alpha();
+ }
+
+ if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
+ image.normalmap_to_xy();
+ }
+
+ /*
+ if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+
+ print_line("CONVERT BECAUSE: "+itos(flags));
+ image.srgb_to_linear();
+ }
+ */
+
+ int orig_w=image.get_width();
+ int orig_h=image.get_height();
+
+ if (shrink>1) {
+ image.resize(orig_w/shrink,orig_h/shrink);
+ texture->create_from_image(image,tex_flags);
+ texture->set_size_override(Size2(orig_w,orig_h));
+ }
+
+ if (!(flags&IMAGE_FLAG_NO_MIPMAPS)) {
+ image.generate_mipmaps();
+
+ }
+
+ if (format!=IMAGE_FORMAT_UNCOMPRESSED) {
+
+ compress_image(p_compr,image,flags&IMAGE_FLAG_COMPRESS_EXTRA);
+ }
+
+
+ texture->create_from_image(image,tex_flags);
+
+
+ if (shrink>1 || (format!=IMAGE_FORMAT_UNCOMPRESSED && (image.get_width()!=orig_w || image.get_height()!=orig_h))) {
+ texture->set_size_override(Size2(orig_w,orig_h));
+ }
+
+ compress=true;
+
+
+ }
+#endif
+ uint32_t save_flags=0;
+ if (compress)
+ save_flags=ResourceSaver::FLAG_COMPRESS;
+
+ Error err = ResourceSaver::save(p_path,texture,save_flags);
+ if (err!=OK) {
+ EditorNode::add_io_error(TTR("Couldn't save converted texture:")+" "+p_path);
+ return err;
+ }
+
+ return OK;
+}
+
+Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, const Ref<EditorExportPlatform> &p_platform) {
+
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+
+ if (rimd.is_null()) {
+
+ StringName group = EditorImportExport::get_singleton()->image_get_export_group(p_path);
+
+ if (group!=StringName()) {
+ //handled by export group
+ rimd = Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) );
+
+ int group_format=0;
+ float group_lossy_quality=EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(group);
+ int group_shrink=EditorImportExport::get_singleton()->image_export_group_get_shrink(group);
+ group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink();
+
+ switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(group)) {
+ case EditorImportExport::IMAGE_ACTION_NONE: {
+
+ switch(EditorImportExport::get_singleton()->get_export_image_action()) {
+ case EditorImportExport::IMAGE_ACTION_NONE: {
+
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS; //?
+
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
+ } break; //use default
+ }
+
+ group_lossy_quality=EditorImportExport::get_singleton()->get_export_image_quality();
+
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
+ group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
+ } break; //use default
+ case EditorImportExport::IMAGE_ACTION_KEEP: {
+ return Vector<uint8_t>();
+ } break; //use default
+ }
+
+ String validated_path=EditorImportPlugin::validate_source_path(p_path);
+
+ int flags=texture_flags_to_export_flags(ResourceFormatLoaderImage::load_image_flags(validated_path));
+ flags|=IMAGE_FLAG_FIX_BORDER_ALPHA;
+
+ print_line("group format"+itos(group_format));
+ rimd->set_option("format",group_format);
+ rimd->set_option("flags",flags);
+ rimd->set_option("quality",group_lossy_quality);
+ rimd->set_option("atlas",false);
+ rimd->set_option("shrink",group_shrink);
+ rimd->add_source(validated_path,FileAccess::get_md5(p_path));
+
+ } else if (EditorImportExport::get_singleton()->get_image_formats().has(p_path.get_extension().to_lower()) && EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE) {
+ //handled by general image export settings
+
+ rimd = Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) );
+
+ switch(EditorImportExport::get_singleton()->get_export_image_action()) {
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: rimd->set_option("format",IMAGE_FORMAT_COMPRESS_DISK_LOSSY); break;
+ case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: rimd->set_option("format",IMAGE_FORMAT_COMPRESS_RAM); break;
+ }
+
+ String validated_path=EditorImportPlugin::validate_source_path(p_path);
+
+ int flags=texture_flags_to_export_flags(ResourceFormatLoaderImage::load_image_flags(validated_path));
+ flags|=IMAGE_FLAG_FIX_BORDER_ALPHA;
+
+ rimd->set_option("shrink",EditorImportExport::get_singleton()->get_export_image_shrink());
+ rimd->set_option("flags",flags);
+ rimd->set_option("quality",EditorImportExport::get_singleton()->get_export_image_quality());
+ rimd->set_option("atlas",false);
+ rimd->add_source(validated_path,FileAccess::get_md5(p_path));
+
+ } else {
+ return Vector<uint8_t>();
+ }
+ }
+
+ int fmt = rimd->get_option("format");
+
+ if (fmt!=IMAGE_FORMAT_COMPRESS_RAM && fmt!=IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
+ print_line("no compress ram or lossy");
+ return Vector<uint8_t>(); //pointless to do anything, since no need to reconvert
+ }
+
+ uint32_t flags = rimd->get_option("flags");
+ uint8_t shrink = rimd->has_option("shrink") ? rimd->get_option("shrink"): Variant(1);
+ uint8_t format = rimd->get_option("format");
+ uint8_t comp = (format==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM)?uint8_t(p_platform->get_image_compression()):uint8_t(255);
+
+ MD5_CTX ctx;
+ uint8_t f4[4];
+ encode_uint32(flags,&f4[0]);
+ MD5Init(&ctx);
+ String gp = GlobalConfig::get_singleton()->globalize_path(p_path);
+ CharString cs = gp.utf8();
+ MD5Update(&ctx,(unsigned char*)cs.get_data(),cs.length());
+ MD5Update(&ctx,f4,4);
+ MD5Update(&ctx,&format,1);
+ MD5Update(&ctx,&comp,1);
+ MD5Update(&ctx,&shrink,1);
+ MD5Final(&ctx);
+
+
+
+ uint64_t sd=0;
+ String smd5;
+
+ String md5 = String::md5(ctx.digest);
+ print_line(p_path+" MD5: "+md5+" FLAGS: "+itos(flags));
+
+ 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+"imgexp-"+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
+ Error err = import2(tmp_path+"imgexp-"+md5+".tex",rimd,p_platform->get_image_compression(),true);
+ ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
+ FileAccessRef f = FileAccess::open(tmp_path+"imgexp-"+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;
+ FileAccessRef f = FileAccess::open(tmp_path+"imgexp-"+md5+".tex",FileAccess::READ);
+ ERR_FAIL_COND_V(!f,ret);
+
+ ret.resize(f->get_len());
+ f->get_buffer(ret.ptr(),ret.size());
+
+ return ret;
+}
+
+uint32_t EditorTextureImportPlugin::texture_flags_to_export_flags(uint32_t p_tex_flags) const {
+
+ uint32_t flags=0;
+
+ if (!(p_tex_flags&Texture::FLAG_MIPMAPS)) {
+ flags|=IMAGE_FLAG_NO_MIPMAPS;
+ }
+ if (p_tex_flags&Texture::FLAG_REPEAT) {
+ flags|=IMAGE_FLAG_REPEAT;
+ }
+ if (p_tex_flags&Texture::FLAG_FILTER) {
+ flags|=IMAGE_FLAG_FILTER;
+ }
+ if (p_tex_flags&Texture::FLAG_ANISOTROPIC_FILTER) {
+ flags|=IMAGE_FLAG_USE_ANISOTROPY;
+ }
+ if (p_tex_flags&Texture::FLAG_CONVERT_TO_LINEAR) {
+ flags|=IMAGE_FLAG_CONVERT_TO_LINEAR;
+ }
+ /* // no correspondence yet
+ if (p_tex_flags&Texture::TEXTURE_FLAG_MIRRORED_REPEAT) {
+ flags|=;
+ }*/
+
+ return flags;
+}
+
+void EditorTextureImportPlugin::import_from_drop(const Vector<String>& p_drop,const String& p_dest_path) {
+
+ Vector<String> valid;
+
+ List<String> valid_extensions;
+ ImageLoader::get_recognized_extensions(&valid_extensions);
+ for(int i=0;i<p_drop.size();i++) {
+
+ String extension=p_drop[i].get_extension().to_lower();
+
+ for (List<String>::Element *E=valid_extensions.front();E;E=E->next()) {
+
+ if (E->get()==extension) {
+ valid.push_back(p_drop[i]);
+ break;
+ }
+ }
+ }
+
+ if (valid.size()) {
+ dialog->popup_import();
+ dialog->setup_multiple_import_3d(valid,p_dest_path);
+ }
+}
+
+void EditorTextureImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
+
+ Vector<String> valid;
+
+
+ for(int i=0;i<p_list.size();i++) {
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_list[i]);
+ String type = rimd->get_editor();
+ if (type=="texture" || type.begins_with("texture_")) {
+
+ if ((rimd->has_option("atlas") && rimd->get_option("atlas")) || (rimd->has_option("large") && rimd->get_option("large"))) {
+ continue;
+ }
+
+ valid.push_back(p_list[i]);
+ }
+ }
+
+ if (valid.size()) {
+
+ dialog->popup_import(valid[0]);
+
+ Vector<String> sources;
+ for(int i=0;i<valid.size();i++) {
+ int idx;
+ EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(valid[i],&idx);
+ if (efsd) {
+ for(int j=0;j<efsd->get_source_count(idx);j++) {
+ String file = expand_source_path(efsd->get_source_file(idx,j));
+ if (sources.find(file)==-1) {
+ sources.push_back(file);
+ }
+
+ }
+ }
+ }
+
+ if (sources.size()) {
+
+ dialog->add_sources_and_dest(sources,valid[0].get_base_dir());
+ }
+ }
+}
+
+bool EditorTextureImportPlugin::can_reimport_multiple_files() const {
+
+ return true;
+
+}
+
+
+
+EditorTextureImportPlugin *EditorTextureImportPlugin::singleton=NULL;
+
+EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor) {
+
+ singleton=this;
+ editor=p_editor;
+ dialog = memnew( EditorTextureImportDialog(this) );
+ editor->get_gui_base()->add_child(dialog);
+
+}
+
+////////////////////////////
+
+
+ Vector<uint8_t> EditorTextureExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+
+ if (rimd.is_valid()) {
+
+ if (rimd->get_editor()!="") {
+ int compression = rimd->get_option("format");
+ if (compression!=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM)
+ return Vector<uint8_t>(); //only useful for RAM compression to reconvert
+ Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name(rimd->get_editor());
+ if (pl.is_valid()) {
+ Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
+ if (ce.size())
+ return ce;
+ }
+ }
+ } else if (EditorImportExport::get_singleton()->image_get_export_group(p_path)) {
+
+
+ Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture");
+ if (pl.is_valid()) {
+ Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
+ if (ce.size()) {
+ p_path=p_path.get_basename()+".converted.tex";
+ return ce;
+ }
+ }
+
+ } else if (EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE){
+
+ String xt = p_path.get_extension().to_lower();
+ if (EditorImportExport::get_singleton()->get_image_formats().has(xt)) { //should check for more I guess?
+
+ Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture");
+ if (pl.is_valid()) {
+ Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
+ if (ce.size()) {
+ p_path=p_path.get_basename()+".converted.tex";
+ return ce;
+ }
+ }
+ }
+ }
+
+ return Vector<uint8_t>();
+}
+
+EditorTextureExportPlugin::EditorTextureExportPlugin() {
+
+
+}
+#endif
diff --git a/editor/io_plugins/editor_texture_import_plugin.h b/editor/io_plugins/editor_texture_import_plugin.h
new file mode 100644
index 0000000000..f63bc57ecd
--- /dev/null
+++ b/editor/io_plugins/editor_texture_import_plugin.h
@@ -0,0 +1,179 @@
+/*************************************************************************/
+/* editor_texture_import_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_TEXTURE_IMPORT_PLUGIN_H
+#define EDITOR_TEXTURE_IMPORT_PLUGIN_H
+
+
+
+
+
+
+#if 0
+#include "editor/editor_import_export.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/label.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/progress_bar.h"
+#include "scene/gui/slider.h"
+#include "scene/gui/spin_box.h"
+#include "editor/editor_file_system.h"
+#include "editor/editor_dir_dialog.h"
+
+
+
+class EditorNode;
+class EditorTextureImportDialog;
+
+class EditorTextureImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorTextureImportPlugin,EditorImportPlugin);
+public:
+
+
+ enum Mode {
+ MODE_TEXTURE_2D,
+ MODE_TEXTURE_3D,
+ MODE_ATLAS,
+ MODE_LARGE,
+ MODE_MAX
+ };
+
+
+
+private:
+
+ EditorNode *editor;
+ EditorTextureImportDialog *dialog;
+ static EditorTextureImportPlugin *singleton;
+ //used by other importers such as mesh
+
+ Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink);
+ void compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller);
+
+ uint32_t texture_flags_to_export_flags(uint32_t p_tex_flags) const;
+public:
+
+
+ static EditorTextureImportPlugin *get_singleton() { return singleton; }
+
+ enum ImageFormat {
+
+ IMAGE_FORMAT_UNCOMPRESSED,
+ IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS,
+ IMAGE_FORMAT_COMPRESS_DISK_LOSSY,
+ IMAGE_FORMAT_COMPRESS_RAM,
+ };
+
+ enum ImageFlags {
+
+ IMAGE_FLAG_STREAM_FORMAT=1,
+ IMAGE_FLAG_FIX_BORDER_ALPHA=2,
+ IMAGE_FLAG_ALPHA_BIT=4, //hint for compressions that use a bit for alpha
+ IMAGE_FLAG_COMPRESS_EXTRA=8, // used for pvrtc2
+ IMAGE_FLAG_NO_MIPMAPS=16, //normal for 2D games
+ IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
+ IMAGE_FLAG_FILTER=64, //almost always enabled
+ IMAGE_FLAG_PREMULT_ALPHA=128,//almost always enabled
+ IMAGE_FLAG_CONVERT_TO_LINEAR=256, //convert image to linear
+ IMAGE_FLAG_CONVERT_NORMAL_TO_XY=512, //convert image to linear
+ IMAGE_FLAG_USE_ANISOTROPY=1024, //convert image to linear
+ };
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from="");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+ virtual Error import2(const String& p_path, const Ref<ResourceImportMetadata>& p_from,EditorExportPlatform::ImageCompression p_compr, bool p_external=false);
+ virtual Vector<uint8_t> custom_export(const String& p_path,const Ref<EditorExportPlatform> &p_platform);
+
+ virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
+ virtual void reimport_multiple_files(const Vector<String>& p_list);
+ virtual bool can_reimport_multiple_files() const;
+
+ EditorTextureImportPlugin(EditorNode* p_editor=NULL);
+};
+
+
+class EditorTextureExportPlugin : public EditorExportPlugin {
+
+ GDCLASS( EditorTextureExportPlugin, EditorExportPlugin);
+
+
+public:
+
+ virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
+ EditorTextureExportPlugin();
+};
+
+class EditorImportTextureOptions : public VBoxContainer {
+
+ GDCLASS( EditorImportTextureOptions, VBoxContainer );
+
+
+ OptionButton *format;
+ VBoxContainer *quality_vb;
+ HSlider *quality;
+ Tree *flags;
+ Vector<TreeItem*> items;
+
+
+ bool updating;
+
+ void _changedp(int p_value);
+ void _changed();
+
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+
+
+
+ void set_format(EditorTextureImportPlugin::ImageFormat p_format);
+ EditorTextureImportPlugin::ImageFormat get_format() const;
+
+ void set_flags(uint32_t p_flags);
+ uint32_t get_flags() const;
+
+ void set_quality(float p_quality);
+ float get_quality() const;
+
+ void show_2d_notice();
+
+ EditorImportTextureOptions();
+
+
+};
+#endif // EDITOR_TEXTURE_IMPORT_PLUGIN_H
+#endif
diff --git a/editor/io_plugins/editor_translation_import_plugin.cpp b/editor/io_plugins/editor_translation_import_plugin.cpp
new file mode 100644
index 0000000000..0fd298d6d3
--- /dev/null
+++ b/editor/io_plugins/editor_translation_import_plugin.cpp
@@ -0,0 +1,479 @@
+/*************************************************************************/
+/* editor_translation_import_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_translation_import_plugin.h"
+
+#if 0
+#include "scene/gui/file_dialog.h"
+#include "editor/editor_dir_dialog.h"
+#include "editor/editor_node.h"
+#include "editor/property_editor.h"
+//#include "scene/resources/sample.h"
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "translation.h"
+#include "compressed_translation.h"
+#include "editor/project_settings.h"
+
+
+class EditorTranslationImportDialog : public ConfirmationDialog {
+
+ GDCLASS(EditorTranslationImportDialog,ConfirmationDialog);
+
+ EditorTranslationImportPlugin *plugin;
+
+ LineEdit *import_path;
+ LineEdit *save_path;
+ EditorFileDialog *file_select;
+ CheckButton *ignore_first;
+ CheckButton *compress;
+ CheckButton *add_to_project;
+ EditorDirDialog *save_select;
+ ConfirmationDialog *error_dialog;
+ Vector<TreeItem*> items;
+ Tree *columns;
+
+public:
+
+ void _choose_file(const String& p_path) {
+
+ import_path->set_text(p_path);
+ FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
+ if (!f) {
+
+ error_dialog->set_text(TTR("Invalid source!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+
+ }
+
+ Vector<String> csvh = f->get_csv_line();
+ memdelete(f);
+
+ if (csvh.size()<2) {
+
+ error_dialog->set_text(TTR("Invalid translation source!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ return;
+
+ }
+
+ columns->clear();
+ columns->set_columns(2);
+ TreeItem *root = columns->create_item();
+ columns->set_hide_root(true);
+ columns->set_column_titles_visible(true);
+ columns->set_column_title(0,TTR("Column"));
+ columns->set_column_title(1,TTR("Language"));
+ Vector<String> langs = TranslationServer::get_all_locales();
+ Vector<String> names = TranslationServer::get_all_locale_names();
+ if (csvh[0]=="")
+ ignore_first->set_pressed(true);
+
+
+ items.clear();
+
+ for(int i=1;i<csvh.size();i++) {
+
+ TreeItem *ti = columns->create_item(root);
+
+ ti->set_editable(0,true);
+ ti->set_selectable(0,false);
+ ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ ti->set_checked(0,true);
+ ti->set_text(0,itos(i));
+ items.push_back(ti);
+
+ String lname = csvh[i].to_lower().strip_edges();
+ int idx=-1;
+ String hint;
+ for(int j=0;j<langs.size();j++) {
+
+ if (langs[j]==lname.substr(0,langs[j].length()).to_lower()) {
+ idx=j;
+ }
+ if (j>0) {
+ hint+=",";
+ }
+ hint+=names[j].replace(","," ");
+ }
+
+ ti->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ ti->set_text(1,hint);
+ ti->set_editable(1,true);
+
+
+ if (idx!=-1) {
+ ignore_first->set_pressed(true);
+ ti->set_range(1,idx);
+ } else {
+
+ //not found, maybe used stupid name
+ if (lname.begins_with("br")) //brazilian
+ ti->set_range(1,langs.find("pt"));
+ else if (lname.begins_with("ch")) //chinese
+ ti->set_range(1,langs.find("zh"));
+ else if (lname.begins_with("sp")) //spanish
+ ti->set_range(1,langs.find("es"));
+ else if (lname.begins_with("kr"))// kprean
+ ti->set_range(1,langs.find("ko"));
+ else if (i==0)
+ ti->set_range(1,langs.find("en"));
+ else
+ ti->set_range(1,langs.find("es"));
+ }
+
+ ti->set_metadata(1,names[ti->get_range(1)]);
+ }
+
+
+
+ }
+ void _choose_save_dir(const String& p_path) {
+
+ save_path->set_text(p_path);
+ }
+
+ void _browse() {
+
+ file_select->popup_centered_ratio();
+ }
+
+ void _browse_target() {
+
+ save_select->popup_centered_ratio();
+
+ }
+
+
+ void popup_import(const String& p_from) {
+
+ popup_centered(Size2(400,400)*EDSCALE);
+
+ if (p_from!="") {
+
+ Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
+ ERR_FAIL_COND(!rimd.is_valid());
+ ERR_FAIL_COND(rimd->get_source_count()!=1);
+ _choose_file(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
+ _choose_save_dir(p_from.get_base_dir());
+ String locale = rimd->get_option("locale");
+ bool skip_first=rimd->get_option("skip_first");
+ bool compressed = rimd->get_option("compress");
+
+ int idx=-1;
+
+ for(int i=0;i<items.size();i++) {
+
+ String il = TranslationServer::get_all_locales()[items[i]->get_range(1)];
+ if (il==locale) {
+ idx=i;
+ break;
+ }
+ }
+
+ if (idx!=-1) {
+ idx=rimd->get_option("index");
+ }
+
+ for(int i=0;i<items.size();i++) {
+
+ if (i==idx) {
+
+ Vector<String> locs = TranslationServer::get_all_locales();
+ for(int j=0;j<locs.size();j++) {
+ if (locs[j]==locale) {
+ items[i]->set_range(1,j);
+ }
+
+ }
+ items[i]->set_checked(0,true);
+ } else {
+ items[i]->set_checked(0,false);
+
+ }
+ }
+
+ ignore_first->set_pressed(skip_first);
+ compress->set_pressed(compressed);
+
+
+
+ }
+
+ }
+
+
+ void _import() {
+
+
+ if (items.size()==0) {
+ error_dialog->set_text(TTR("No items to import!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ }
+
+ if (!save_path->get_text().begins_with("res://")) {
+ error_dialog->set_text(TTR("No target path!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ }
+
+ EditorProgress progress("import_xl",TTR("Import Translations"),items.size());
+ for(int i=0;i<items.size();i++) {
+
+ progress.step(items[i]->get_metadata(1),i);
+ if (!items[i]->is_checked(0))
+ continue;
+
+ String locale = TranslationServer::get_all_locales()[items[i]->get_range(1)];
+ Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
+ imd->add_source(EditorImportPlugin::validate_source_path(import_path->get_text()));
+ imd->set_option("locale",locale);
+ imd->set_option("index",i);
+ imd->set_option("skip_first",ignore_first->is_pressed());
+ imd->set_option("compress",compress->is_pressed());
+
+ String savefile = save_path->get_text().plus_file(import_path->get_text().get_file().get_basename()+"."+locale+".xl");
+ Error err = plugin->import(savefile,imd);
+ if (err!=OK) {
+ error_dialog->set_text(TTR("Couldn't import!"));
+ error_dialog->popup_centered(Size2(200,100)*EDSCALE);
+ } else if (add_to_project->is_pressed()) {
+
+ ProjectSettings::get_singleton()->add_translation(savefile);
+ }
+ }
+ hide();
+
+ }
+
+
+ void _notification(int p_what) {
+
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+
+ }
+ }
+
+ static void _bind_methods() {
+
+
+ ClassDB::bind_method("_choose_file",&EditorTranslationImportDialog::_choose_file);
+ ClassDB::bind_method("_choose_save_dir",&EditorTranslationImportDialog::_choose_save_dir);
+ ClassDB::bind_method("_import",&EditorTranslationImportDialog::_import);
+ ClassDB::bind_method("_browse",&EditorTranslationImportDialog::_browse);
+ ClassDB::bind_method("_browse_target",&EditorTranslationImportDialog::_browse_target);
+ //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
+ }
+
+ EditorTranslationImportDialog(EditorTranslationImportPlugin *p_plugin) {
+
+ plugin=p_plugin;
+
+
+ set_title(TTR("Import Translation"));
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ //set_child_rect(vbc);
+
+
+
+ VBoxContainer *csvb = memnew( VBoxContainer );
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ csvb->add_child(hbc);
+ vbc->add_margin_child(TTR("Source CSV:"),csvb);
+
+ import_path = memnew( LineEdit );
+ import_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(import_path);
+ ignore_first = memnew( CheckButton );
+ ignore_first->set_text(TTR("Ignore First Row"));
+ csvb->add_child(ignore_first);
+
+ Button * import_choose = memnew( Button );
+ import_choose->set_text(" .. ");
+ hbc->add_child(import_choose);
+
+ import_choose->connect("pressed", this,"_browse");
+
+ VBoxContainer *tcomp = memnew( VBoxContainer);
+ hbc = memnew( HBoxContainer );
+ tcomp->add_child(hbc);
+ vbc->add_margin_child(TTR("Target Path:"),tcomp);
+
+ save_path = memnew( LineEdit );
+ save_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(save_path);
+
+ Button * save_choose = memnew( Button );
+ save_choose->set_text(" .. ");
+ hbc->add_child(save_choose);
+
+ save_choose->connect("pressed", this,"_browse_target");
+
+ compress = memnew( CheckButton);
+ compress->set_pressed(true);
+ compress->set_text(TTR("Compress"));
+ tcomp->add_child(compress);
+
+ add_to_project = memnew( CheckButton);
+ add_to_project->set_pressed(true);
+ add_to_project->set_text(TTR("Add to Project (godot.cfg)"));
+ tcomp->add_child(add_to_project);
+
+ file_select = memnew(EditorFileDialog);
+ file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ add_child(file_select);
+ file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_select->connect("file_selected", this,"_choose_file");
+ file_select->add_filter("*.csv ; Translation CSV");
+ save_select = memnew( EditorDirDialog );
+ add_child(save_select);
+
+ //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
+ save_select->connect("dir_selected", this,"_choose_save_dir");
+
+ get_ok()->connect("pressed", this,"_import");
+ get_ok()->set_text(TTR("Import"));
+
+
+ error_dialog = memnew ( ConfirmationDialog );
+ add_child(error_dialog);
+ error_dialog->get_ok()->set_text(TTR("Accept"));
+ //error_dialog->get_cancel()->hide();
+
+ set_hide_on_ok(false);
+
+ columns = memnew( Tree );
+ vbc->add_margin_child(TTR("Import Languages:"),columns,true);
+ }
+
+ ~EditorTranslationImportDialog() {
+
+ }
+
+};
+
+
+String EditorTranslationImportPlugin::get_name() const {
+
+ return "translation";
+}
+String EditorTranslationImportPlugin::get_visible_name() const {
+
+ return TTR("Translation");
+}
+void EditorTranslationImportPlugin::import_dialog(const String& p_from) {
+
+ dialog->popup_import(p_from);
+}
+
+
+
+void EditorTranslationImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
+
+
+ for(int i=0;i<p_drop.size();i++) {
+ String ext = p_drop[i].get_extension().to_lower();
+
+ if (ext=="csv") {
+
+ import_dialog();
+ dialog->_choose_file(p_drop[i]);
+ dialog->_choose_save_dir(p_dest_path);
+ break;
+ }
+ }
+
+
+}
+
+Error EditorTranslationImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
+
+ Ref<ResourceImportMetadata> from = p_from;
+ ERR_FAIL_COND_V( from->get_source_count()!=1, ERR_INVALID_PARAMETER);
+
+ String source = EditorImportPlugin::expand_source_path( from->get_source_path(0) );
+
+ FileAccessRef f = FileAccess::open(source,FileAccess::READ);
+
+ ERR_FAIL_COND_V( !f, ERR_INVALID_PARAMETER );
+
+ bool skip_first = from->get_option("skip_first");
+ int index = from->get_option("index");
+ index+=1;
+ String locale = from->get_option("locale");
+
+ Ref<Translation> translation = memnew( Translation );
+
+ translation->set_locale( locale );
+
+ Vector<String> line = f->get_csv_line();
+
+ while(line.size()>1) {
+
+ if (!skip_first) {
+ ERR_FAIL_INDEX_V(index,line.size(),ERR_INVALID_DATA );
+ translation->add_message(line[0].strip_edges(),line[index]);
+
+ } else {
+
+ skip_first=false;
+ }
+
+ line = f->get_csv_line();
+ }
+
+ from->set_source_md5(0,FileAccess::get_md5(source));
+ from->set_editor(get_name());
+
+ String dst_path = p_path;
+
+ if (from->get_option("compress")) {
+
+ Ref<PHashTranslation> cxl = memnew( PHashTranslation );
+ cxl->generate( translation );
+ translation=cxl;
+ }
+
+ translation->set_import_metadata(from);
+ return ResourceSaver::save(dst_path,translation);
+
+}
+
+
+EditorTranslationImportPlugin::EditorTranslationImportPlugin(EditorNode* p_editor) {
+
+ dialog = memnew(EditorTranslationImportDialog(this));
+ p_editor->get_gui_base()->add_child(dialog);
+}
+
+#endif
diff --git a/editor/io_plugins/editor_translation_import_plugin.h b/editor/io_plugins/editor_translation_import_plugin.h
new file mode 100644
index 0000000000..030c5bbf6f
--- /dev/null
+++ b/editor/io_plugins/editor_translation_import_plugin.h
@@ -0,0 +1,56 @@
+/*************************************************************************/
+/* editor_translation_import_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#ifndef EDITOR_TRANSLATION_IMPORT_PLUGIN_H
+#define EDITOR_TRANSLATION_IMPORT_PLUGIN_H
+
+#include "editor/editor_export.h"
+#include "scene/resources/font.h"
+#if 0
+class EditorNode;
+class EditorTranslationImportDialog;
+
+class EditorTranslationImportPlugin : public EditorImportPlugin {
+
+ GDCLASS(EditorTranslationImportPlugin,EditorImportPlugin);
+
+ EditorTranslationImportDialog *dialog;
+public:
+
+ virtual String get_name() const;
+ virtual String get_visible_name() const;
+ virtual void import_dialog(const String& p_from="");
+ virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+ void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
+
+
+ EditorTranslationImportPlugin(EditorNode* p_editor);
+};
+
+#endif
+#endif // EDITOR_TRANSLATION_IMPORT_PLUGIN_H
diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp
new file mode 100644
index 0000000000..0428d7ef30
--- /dev/null
+++ b/editor/multi_node_edit.cpp
@@ -0,0 +1,191 @@
+/*************************************************************************/
+/* multi_node_edit.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "multi_node_edit.h"
+
+#include "editor_node.h"
+#include "core/helper/math_fieldwise.h"
+
+bool MultiNodeEdit::_set(const StringName& p_name, const Variant& p_value){
+
+ return _set_impl(p_name, p_value, "");
+}
+
+bool MultiNodeEdit::_set_impl(const StringName& p_name, const Variant& p_value, const String& p_field) {
+
+ Node *es = EditorNode::get_singleton()->get_edited_scene();
+ if (!es)
+ return false;
+
+ String name = p_name;
+
+ if (name=="scripts") { // script set is intercepted at object level (check Variant Object::get() ) ,so use a different name
+ name="script";
+ }
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+ ur->create_action(TTR("MultiNode Set")+" "+String(name));
+ for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
+
+ if (!es->has_node(E->get()))
+ continue;
+
+ Node*n=es->get_node(E->get());
+ if (!n)
+ continue;
+
+ if (p_value.get_type() == Variant::NODE_PATH) {
+ Node *tonode = n->get_node(p_value);
+ NodePath p_path = n->get_path_to(tonode);
+ ur->add_do_property(n,name,p_path);
+ } else {
+ Variant new_value;
+ if (p_field=="") {
+ // whole value
+ new_value=p_value;
+ } else {
+ // only one field
+ new_value=fieldwise_assign(n->get(name),p_value,p_field);
+ }
+ ur->add_do_property(n,name,new_value);
+ }
+
+ ur->add_undo_property(n,name,n->get(name));
+
+
+ }
+ ur->add_do_method(EditorNode::get_singleton()->get_property_editor(),"refresh");
+ ur->add_undo_method(EditorNode::get_singleton()->get_property_editor(),"refresh");
+
+ ur->commit_action();
+ return true;
+}
+
+bool MultiNodeEdit::_get(const StringName& p_name,Variant &r_ret) const {
+
+ Node *es = EditorNode::get_singleton()->get_edited_scene();
+ if (!es)
+ return false;
+
+ String name=p_name;
+ if (name=="scripts") { // script set is intercepted at object level (check Variant Object::get() ) ,so use a different name
+ name="script";
+ }
+
+ for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
+
+ if (!es->has_node(E->get()))
+ continue;
+
+ const Node*n=es->get_node(E->get());
+ if (!n)
+ continue;
+
+ bool found;
+ r_ret=n->get(name,&found);
+ if (found)
+ return true;
+
+ }
+
+ return false;
+}
+
+void MultiNodeEdit::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ HashMap<String,PLData> usage;
+
+ Node *es = EditorNode::get_singleton()->get_edited_scene();
+ if (!es)
+ return;
+
+ int nc=0;
+
+ List<PLData*> datas;
+
+ for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
+
+ if (!es->has_node(E->get()))
+ continue;
+
+ Node*n=es->get_node(E->get());
+ if (!n)
+ continue;
+
+ List<PropertyInfo> plist;
+ n->get_property_list(&plist,true);
+
+ for(List<PropertyInfo>::Element *F=plist.front();F;F=F->next()) {
+
+ if (F->get().name=="script")
+ continue; //added later manually, since this is intercepted before being set (check Variant Object::get() )
+ if (!usage.has(F->get().name)) {
+ PLData pld;
+ pld.uses=0;
+ pld.info=F->get();
+ usage[F->get().name]=pld;
+ datas.push_back(usage.getptr(F->get().name));
+ }
+
+ usage[F->get().name].uses++;
+ }
+
+ nc++;
+ }
+
+ for (List<PLData*>::Element *E=datas.front();E;E=E->next()) {
+
+ if (nc==E->get()->uses) {
+ p_list->push_back(E->get()->info);
+ }
+ }
+
+ p_list->push_back(PropertyInfo(Variant::OBJECT,"scripts",PROPERTY_HINT_RESOURCE_TYPE,"Script"));
+
+
+}
+
+void MultiNodeEdit::clear_nodes() {
+
+ nodes.clear();
+}
+
+void MultiNodeEdit::add_node(const NodePath& p_node){
+
+ nodes.push_back(p_node);
+}
+
+void MultiNodeEdit::set_property_field(const StringName& p_property, const Variant& p_value, const String& p_field) {
+
+ _set_impl(p_property, p_value, p_field);
+}
+
+MultiNodeEdit::MultiNodeEdit()
+{
+}
diff --git a/editor/multi_node_edit.h b/editor/multi_node_edit.h
new file mode 100644
index 0000000000..26e557c1cb
--- /dev/null
+++ b/editor/multi_node_edit.h
@@ -0,0 +1,65 @@
+/*************************************************************************/
+/* multi_node_edit.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 MULTI_NODE_EDIT_H
+#define MULTI_NODE_EDIT_H
+
+#include "scene/main/node.h"
+
+class MultiNodeEdit : public Reference {
+
+ GDCLASS(MultiNodeEdit,Reference);
+
+ List<NodePath> nodes;
+ struct PLData {
+ int uses;
+ PropertyInfo info;
+ };
+
+ bool _set_impl(const StringName& p_name, const Variant& p_value, const String& p_field);
+
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+
+
+ void clear_nodes();
+ void add_node(const NodePath& p_node);
+
+ void set_property_field(const StringName& p_property, const Variant& p_value, const String& p_field);
+
+ MultiNodeEdit();
+};
+
+#endif // MULTI_NODE_EDIT_H
diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp
new file mode 100644
index 0000000000..fed3d2efb4
--- /dev/null
+++ b/editor/node_dock.cpp
@@ -0,0 +1,133 @@
+/*************************************************************************/
+/* node_dock.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "node_dock.h"
+
+#include "editor_node.h"
+
+void NodeDock::show_groups() {
+
+ groups_button->set_pressed(true);
+ connections_button->set_pressed(false);
+ groups->show();
+ connections->hide();
+}
+
+void NodeDock::show_connections(){
+
+ groups_button->set_pressed(false);
+ connections_button->set_pressed(true);
+ groups->hide();
+ connections->show();
+}
+
+
+void NodeDock::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("show_groups"),&NodeDock::show_groups);
+ ClassDB::bind_method(D_METHOD("show_connections"),&NodeDock::show_connections);
+}
+
+void NodeDock::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ connections_button->set_icon(get_icon("Connect","EditorIcons"));
+ groups_button->set_icon(get_icon("Groups","EditorIcons"));
+ }
+}
+
+NodeDock *NodeDock::singleton=NULL;
+
+void NodeDock::set_node(Node* p_node) {
+
+ connections->set_node(p_node);
+ groups->set_current(p_node);
+
+ if (p_node) {
+ if (connections_button->is_pressed())
+ connections->show();
+ else
+ groups->show();
+
+ mode_hb->show();
+ select_a_node->hide();
+ } else {
+ connections->hide();
+ groups->hide();
+ mode_hb->hide();
+ select_a_node->show();
+ }
+}
+
+NodeDock::NodeDock()
+{
+ singleton=this;
+
+ set_name(TTR("Node"));
+ mode_hb = memnew( HBoxContainer );
+ add_child(mode_hb);
+ mode_hb->hide();
+
+
+ connections_button = memnew( ToolButton );
+ connections_button->set_text(TTR("Signals"));
+ connections_button->set_toggle_mode(true);
+ connections_button->set_pressed(true);
+ connections_button->set_h_size_flags(SIZE_EXPAND_FILL);
+ mode_hb->add_child(connections_button);
+ connections_button->connect("pressed",this,"show_connections");
+
+ groups_button = memnew( ToolButton );
+ groups_button->set_text(TTR("Groups"));
+ groups_button->set_toggle_mode(true);
+ groups_button->set_pressed(false);
+ groups_button->set_h_size_flags(SIZE_EXPAND_FILL);
+ mode_hb->add_child(groups_button);
+ groups_button->connect("pressed",this,"show_groups");
+
+ connections = memnew( ConnectionsDock(EditorNode::get_singleton()) );
+ connections->set_undoredo(EditorNode::get_singleton()->get_undo_redo());
+ add_child(connections);
+ connections->set_v_size_flags(SIZE_EXPAND_FILL);
+ connections->hide();
+
+ groups = memnew( GroupsEditor );
+ groups->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
+ add_child(groups);
+ groups->set_v_size_flags(SIZE_EXPAND_FILL);
+ groups->hide();
+
+ select_a_node = memnew( Label );
+ select_a_node->set_text(TTR("Select a Node to edit Signals and Groups."));
+ select_a_node->set_v_size_flags(SIZE_EXPAND_FILL);
+ select_a_node->set_valign(Label::VALIGN_CENTER);
+ select_a_node->set_align(Label::ALIGN_CENTER);
+ select_a_node->set_autowrap(true);
+ add_child(select_a_node);
+
+}
diff --git a/tools/editor/node_dock.h b/editor/node_dock.h
index df41ecf5bd..df41ecf5bd 100644
--- a/tools/editor/node_dock.h
+++ b/editor/node_dock.h
diff --git a/tools/editor/output_strings.cpp b/editor/output_strings.cpp
index cb43bb9230..cb43bb9230 100644
--- a/tools/editor/output_strings.cpp
+++ b/editor/output_strings.cpp
diff --git a/tools/editor/output_strings.h b/editor/output_strings.h
index cc721ef652..cc721ef652 100644
--- a/tools/editor/output_strings.h
+++ b/editor/output_strings.h
diff --git a/tools/editor/pane_drag.cpp b/editor/pane_drag.cpp
index 122abd37b9..122abd37b9 100644
--- a/tools/editor/pane_drag.cpp
+++ b/editor/pane_drag.cpp
diff --git a/tools/editor/pane_drag.h b/editor/pane_drag.h
index 8796fc2594..8796fc2594 100644
--- a/tools/editor/pane_drag.h
+++ b/editor/pane_drag.h
diff --git a/tools/editor/plugins/SCsub b/editor/plugins/SCsub
index f1fa50148f..f1fa50148f 100644
--- a/tools/editor/plugins/SCsub
+++ b/editor/plugins/SCsub
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
new file mode 100644
index 0000000000..2e6792bbaa
--- /dev/null
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -0,0 +1,1604 @@
+/*************************************************************************/
+/* animation_player_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "animation_player_editor_plugin.h"
+
+#include "global_config.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "os/keyboard.h"
+#include "editor/editor_settings.h"
+#include "editor/animation_editor.h"
+
+void AnimationPlayerEditor::_node_removed(Node *p_node) {
+
+ if (player && player == p_node) {
+ player=NULL;
+
+ set_process(false);
+
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
+ key_editor->show_select_node_warning(true);
+ _update_player();
+ //editor->animation_editor_make_visible(false);
+
+ }
+}
+
+void AnimationPlayerEditor::_gui_input(InputEvent p_event) {
+
+
+}
+
+void AnimationPlayerEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ if (!player)
+ return;
+
+ updating = true;
+
+ if (player->is_playing()) {
+
+ {
+ String animname=player->get_current_animation();
+
+ if (player->has_animation(animname)) {
+ Ref<Animation> anim = player->get_animation(animname);
+ if (!anim.is_null()) {
+
+ frame->set_max(anim->get_length());
+ }
+ }
+ }
+ frame->set_value(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
+
+ frame->set_value(player->get_current_animation_pos());
+ }
+
+ last_active=player->is_playing();
+ //seek->set_val(player->get_pos());
+ updating = false;
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ //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") );
+ autoplay->set_icon( get_icon("AutoPlay","EditorIcons") );
+ load_anim->set_icon( get_icon("Folder","EditorIcons") );
+ save_anim->set_icon(get_icon("Save", "EditorIcons"));
+ save_anim->get_popup()->connect("id_pressed", this, "_animation_save_menu");
+ remove_anim->set_icon( get_icon("Remove","EditorIcons") );
+
+ blend_anim->set_icon( get_icon("Blend","EditorIcons") );
+ play->set_icon( get_icon("PlayStart","EditorIcons") );
+ play_from->set_icon( get_icon("Play","EditorIcons") );
+ play_bw->set_icon( get_icon("PlayStartBackwards","EditorIcons") );
+ play_bw_from->set_icon( get_icon("PlayBackwards","EditorIcons") );
+
+ autoplay_icon=get_icon("AutoPlay","EditorIcons");
+ stop->set_icon( get_icon("Stop","EditorIcons") );
+ resource_edit_anim->set_icon( get_icon("EditResource","EditorIcons") );
+ pin->set_icon(get_icon("Pin","EditorIcons") );
+ tool_anim->set_icon(get_icon("Tools","EditorIcons"));
+ tool_anim->get_popup()->connect("id_pressed",this,"_animation_tool_menu");
+
+ blend_editor.next->connect("item_selected", 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"));
+ anim_editor_load->set_pressed_texture( get_icon("AnimGet","EditorIcons"));
+ anim_editor_store->set_pressed_texture( get_icon("AnimSet","EditorIcons"));
+ anim_editor_load->set_hover_texture( get_icon("AnimGetHl","EditorIcons"));
+ anim_editor_store->set_hover_texture( get_icon("AnimSetHl","EditorIcons"));
+*/
+
+ get_tree()->connect("node_removed",this,"_node_removed");
+ }
+}
+
+void AnimationPlayerEditor::_autoplay_pressed() {
+
+ if (updating)
+ return;
+ if (animation->get_item_count()==0) {
+ return;
+ }
+
+ String current = animation->get_item_text( animation->get_selected() );
+ if (player->get_autoplay()==current) {
+ //unset
+ undo_redo->create_action(TTR("Toggle Autoplay"));
+ undo_redo->add_do_method(player,"set_autoplay","");
+ undo_redo->add_undo_method(player,"set_autoplay",player->get_autoplay());
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+
+
+ } else {
+ //set
+ undo_redo->create_action(TTR("Toggle Autoplay"));
+ undo_redo->add_do_method(player,"set_autoplay",current);
+ undo_redo->add_undo_method(player,"set_autoplay",player->get_autoplay());
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+ }
+
+}
+
+void AnimationPlayerEditor::_play_pressed() {
+
+ String current;
+ if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
+
+ current = animation->get_item_text( animation->get_selected() );
+ }
+
+ if (current!="") {
+
+ if (current==player->get_current_animation())
+ player->stop(); //so it wont blend with itself
+ player->play(current );
+ }
+
+ //unstop
+ stop->set_pressed(false);
+ //unpause
+ //pause->set_pressed(false);
+}
+
+void AnimationPlayerEditor::_play_from_pressed() {
+
+ String current;
+ if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
+
+ current = animation->get_item_text( animation->get_selected() );
+ }
+
+ if (current!="") {
+
+ float time = player->get_current_animation_pos();
+
+ if (current==player->get_current_animation() && player->is_playing()) {
+
+ player->stop(); //so it wont blend with itself
+ }
+
+ player->play( current );
+ player->seek(time);
+ }
+
+ //unstop
+ stop->set_pressed(false);
+ //unpause
+ //pause->set_pressed(false);
+}
+
+
+void AnimationPlayerEditor::_play_bw_pressed() {
+
+ String current;
+ if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
+
+ current = animation->get_item_text( animation->get_selected() );
+ }
+
+ if (current!="") {
+
+ if (current==player->get_current_animation())
+ player->stop(); //so it wont blend with itself
+ player->play(current,-1,-1,true);
+ }
+
+ //unstop
+ stop->set_pressed(false);
+ //unpause
+ //pause->set_pressed(false);
+}
+
+void AnimationPlayerEditor::_play_bw_from_pressed() {
+
+ String current;
+ if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
+
+ current = animation->get_item_text( animation->get_selected() );
+ }
+
+ if (current!="") {
+
+ float time = player->get_current_animation_pos();
+ if (current==player->get_current_animation())
+ player->stop(); //so it wont blend with itself
+
+ player->play(current,-1,-1,true);
+ player->seek(time);
+ }
+
+ //unstop
+ stop->set_pressed(false);
+ //unpause
+ //pause->set_pressed(false);
+}
+void AnimationPlayerEditor::_stop_pressed() {
+
+ player->stop(false);
+ play->set_pressed(false);
+ stop->set_pressed(true);
+ //pause->set_pressed(false);
+ //player->set_pause(false);
+}
+
+void AnimationPlayerEditor::_pause_pressed() {
+
+ //player->set_pause( pause->is_pressed() );
+}
+void AnimationPlayerEditor::_animation_selected(int p_which) {
+
+ if (updating)
+ return;
+ // when selecting an animation, the idea is that the only interesting behavior
+ // ui-wise is that it should play/blend the next one if currently playing
+ String current;
+ if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
+
+ current = animation->get_item_text( animation->get_selected() );
+ }
+
+ if (current!="") {
+
+
+ player->set_current_animation( current );
+
+ 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);
+ }
+ }
+ frame->set_max(anim->get_length());
+ if (anim->get_step())
+ frame->set_step(anim->get_step());
+ else
+ frame->set_step(0.00001);
+
+
+
+ } else {
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
+
+ }
+
+
+ autoplay->set_pressed(current==player->get_autoplay());
+}
+
+void AnimationPlayerEditor::_animation_new() {
+
+ renaming=false;
+ name_title->set_text(TTR("New Animation Name:"));
+
+ int count=1;
+ String base=TTR("New Anim");
+ while(true) {
+ String attempt = base;
+ if (count>1)
+ attempt+=" ("+itos(count)+")";
+ if (player->has_animation(attempt)) {
+ count++;
+ continue;
+ }
+ base=attempt;
+ break;
+ }
+
+ name->set_text(base);
+ name_dialog->popup_centered(Size2(300,90));
+ name->select_all();
+ name->grab_focus();
+}
+void AnimationPlayerEditor::_animation_rename() {
+
+ if (animation->get_item_count()==0)
+ return;
+ int selected = animation->get_selected();
+ String selected_name = animation->get_item_text(selected);
+
+ name_title->set_text(TTR("Change Animation Name:"));
+ name->set_text(selected_name);
+ renaming=true;
+ name_dialog->popup_centered(Size2(300,90));
+ name->select_all();
+ name->grab_focus();
+
+}
+void AnimationPlayerEditor::_animation_load() {
+ ERR_FAIL_COND(!player);
+ file->set_mode( EditorFileDialog::MODE_OPEN_FILE );
+ file->clear_filters();
+ List<String> extensions;
+
+ ResourceLoader::get_recognized_extensions_for_type("Animation",&extensions);
+ for (List<String>::Element *E=extensions.front();E;E=E->next()) {
+
+ file->add_filter("*."+E->get()+" ; "+E->get().to_upper() );
+
+ }
+
+ file->popup_centered_ratio();
+ current_option = RESOURCE_LOAD;
+}
+
+
+void AnimationPlayerEditor::_animation_save_in_path(const Ref<Resource>& p_resource, const String& p_path) {
+
+ int flg = 0;
+ if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
+ flg |= ResourceSaver::FLAG_COMPRESS;
+ /*
+ if (EditorSettings::get_singleton()->get("filesystem/on_save/save_paths_as_relative"))
+ flg |= ResourceSaver::FLAG_RELATIVE_PATHS;
+ */
+
+ String path = GlobalConfig::get_singleton()->localize_path(p_path);
+ Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
+
+ if (err != OK) {
+ accept->set_text(TTR("Error saving resource!"));
+ accept->popup_centered_minsize();
+ return;
+ }
+ //EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
+
+ ((Resource*)p_resource.ptr())->set_path(path);
+ editor->emit_signal("resource_saved", p_resource);
+
+}
+
+void AnimationPlayerEditor::_animation_save(const Ref<Resource>& p_resource) {
+
+ if (p_resource->get_path().is_resource_file()) {
+ _animation_save_in_path(p_resource, p_resource->get_path());
+ }
+ else {
+ _animation_save_as(p_resource);
+ }
+}
+
+void AnimationPlayerEditor::_animation_save_as(const Ref<Resource>& p_resource) {
+
+ file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+
+ List<String> extensions;
+ ResourceSaver::get_recognized_extensions(p_resource, &extensions);
+ file->clear_filters();
+ for (int i = 0; i<extensions.size(); i++) {
+
+ file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ }
+
+ //file->set_current_path(current_path);
+ if (p_resource->get_path() != "") {
+ file->set_current_path(p_resource->get_path());
+ if (extensions.size()) {
+ String ext = p_resource->get_path().get_extension().to_lower();
+ if (extensions.find(ext) == NULL) {
+ file->set_current_path(p_resource->get_path().replacen("." + ext, "." + extensions.front()->get()));
+ }
+ }
+ }
+ else {
+
+ String existing;
+ if (extensions.size()) {
+ if( p_resource->get_name() != "" ) {
+ existing = p_resource->get_name() + "." + extensions.front()->get().to_lower();
+ }
+ else {
+ existing = "new_" + p_resource->get_class().to_lower() + "." + extensions.front()->get().to_lower();
+ }
+ }
+ file->set_current_path(existing);
+
+ }
+ file->popup_centered_ratio();
+ file->set_title(TTR("Save Resource As.."));
+ current_option = RESOURCE_SAVE;
+}
+
+void AnimationPlayerEditor::_animation_remove() {
+
+ if (animation->get_item_count() == 0)
+ return;
+
+ delete_dialog->set_text(TTR("Delete Animation?"));
+ delete_dialog->popup_centered_minsize();
+}
+
+void AnimationPlayerEditor::_animation_remove_confirmed() {
+
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+
+ undo_redo->create_action(TTR("Remove Animation"));
+ undo_redo->add_do_method(player, "remove_animation", current);
+ undo_redo->add_undo_method(player, "add_animation", current, anim);
+ undo_redo->add_do_method(this, "_animation_player_changed", player);
+ undo_redo->add_undo_method(this, "_animation_player_changed", player);
+ undo_redo->commit_action();
+}
+
+void AnimationPlayerEditor::_select_anim_by_name(const String& p_anim) {
+
+ int idx=-1;
+ for(int i=0;i<animation->get_item_count();i++) {
+
+ if (animation->get_item_text(i)==p_anim) {
+
+ idx=i;
+ break;
+ }
+ }
+
+ ERR_FAIL_COND(idx==-1);
+
+
+ animation->select(idx);
+
+ _animation_selected(idx);
+
+}
+
+void AnimationPlayerEditor::_animation_name_edited() {
+
+ player->stop();
+
+ String new_name = name->get_text();
+ if (new_name=="" || new_name.find(":")!=-1 || new_name.find("/")!=-1) {
+ error_dialog->set_text(TTR("ERROR: Invalid animation name!"));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (renaming && animation->get_item_count()>0 && animation->get_item_text(animation->get_selected())==new_name) {
+ name_dialog->hide();
+ return;
+ }
+
+ if (player->has_animation(new_name)) {
+ error_dialog->set_text(TTR("ERROR: Animation name already exists!"));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ if (renaming) {
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+
+ undo_redo->create_action(TTR("Rename Animation"));
+ undo_redo->add_do_method(player,"rename_animation",current,new_name);
+ undo_redo->add_do_method(anim.ptr(),"set_name",new_name);
+ undo_redo->add_undo_method(player,"rename_animation",new_name,current);
+ undo_redo->add_undo_method(anim.ptr(),"set_name",current);
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+
+ _select_anim_by_name(new_name);
+
+ } else {
+
+ Ref<Animation> new_anim = Ref<Animation>(memnew( Animation ));
+ new_anim->set_name(new_name);
+
+ undo_redo->create_action(TTR("Add Animation"));
+ undo_redo->add_do_method(player,"add_animation",new_name,new_anim);
+ undo_redo->add_undo_method(player,"remove_animation",new_name);
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+
+ _select_anim_by_name(new_name);
+
+ }
+
+ name_dialog->hide();
+}
+
+
+void AnimationPlayerEditor::_blend_editor_next_changed(const int p_idx) {
+
+ if (animation->get_item_count()==0)
+ return;
+
+ String current = animation->get_item_text(animation->get_selected());
+
+ undo_redo->create_action(TTR("Blend Next Changed"));
+ undo_redo->add_do_method(player,"animation_set_next",current,blend_editor.next->get_item_text(p_idx));
+ undo_redo->add_undo_method(player,"animation_set_next",current,player->animation_get_next(current));
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+}
+
+void AnimationPlayerEditor::_animation_blend() {
+
+ if (updating_blends)
+ return;
+
+ blend_editor.tree->clear();
+
+ if (animation->get_item_count()==0)
+ return;
+
+ String current = animation->get_item_text(animation->get_selected());
+
+ blend_editor.dialog->popup_centered(Size2(400,400));
+
+ blend_editor.tree->set_hide_root(true);
+ blend_editor.tree->set_column_min_width(0,10);
+ blend_editor.tree->set_column_min_width(1,3);
+
+ List<StringName> anims;
+ player->get_animation_list(&anims);
+ TreeItem *root = blend_editor.tree->create_item();
+ updating_blends=true;
+
+ int i = 0;
+ bool anim_found = false;
+ blend_editor.next->clear();
+ blend_editor.next->add_item("", i);
+
+ for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
+
+ String to=E->get();
+ TreeItem *blend=blend_editor.tree->create_item(root);
+ blend->set_editable(0,false);
+ blend->set_editable(1,true);
+ blend->set_text(0,to);
+ blend->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ blend->set_range_config(1,0,3600,0.001);
+ blend->set_range(1,player->get_blend_time(current,to));
+
+ i++;
+ blend_editor.next->add_item(to, i);
+ if (to == player->animation_get_next(current)) {
+ blend_editor.next->select(i);
+ anim_found = true;
+ }
+ }
+
+ // make sure we reset it else it becomes out of sync and could contain a deleted animation
+ if (!anim_found) {
+ blend_editor.next->select(0);
+ player->animation_set_next(current, blend_editor.next->get_item_text(0));
+ }
+
+ updating_blends=false;
+}
+
+void AnimationPlayerEditor::_blend_edited() {
+
+ if (updating_blends)
+ return;
+
+ if (animation->get_item_count()==0)
+ return;
+
+ String current = animation->get_item_text(animation->get_selected());
+
+ TreeItem *selected = blend_editor.tree->get_edited();
+ if (!selected)
+ return;
+
+ updating_blends=true;
+ String to=selected->get_text(0);
+ float blend_time = selected->get_range(1);
+ float prev_blend_time = player->get_blend_time(current,to);
+
+ undo_redo->create_action(TTR("Change Blend Time"));
+ undo_redo->add_do_method(player,"set_blend_time",current,to,blend_time);
+ undo_redo->add_undo_method(player,"set_blend_time",current,to,prev_blend_time);
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+ updating_blends=false;
+}
+
+void AnimationPlayerEditor::ensure_visibility() {
+
+ if (player && pin->is_pressed())
+ return; // another player is pinned, don't reset
+
+ _animation_edit();
+}
+
+Dictionary AnimationPlayerEditor::get_state() const {
+
+
+ Dictionary d;
+
+ d["visible"]=is_visible_in_tree();
+ if (EditorNode::get_singleton()->get_edited_scene() && is_visible_in_tree() && player) {
+ d["player"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(player);
+ d["animation"]=player->get_current_animation();
+
+ }
+
+ return d;
+
+}
+void AnimationPlayerEditor::set_state(const Dictionary& p_state) {
+
+ if (p_state.has("visible") && p_state["visible"]) {
+
+ if (!EditorNode::get_singleton()->get_edited_scene())
+ return;
+
+ Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]);
+ if (n && n->cast_to<AnimationPlayer>() && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) {
+ player=n->cast_to<AnimationPlayer>();
+ _update_player();
+ show();
+ set_process(true);
+ ensure_visibility();
+ //EditorNode::get_singleton()->animation_panel_make_visible(true);
+
+ if (p_state.has("animation")) {
+ String anim = p_state["animation"];
+ _select_anim_by_name(anim);
+ _animation_edit();
+ }
+
+ }
+ }
+
+}
+
+
+void AnimationPlayerEditor::_animation_resource_edit() {
+
+ if (animation->get_item_count()) {
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+ editor->edit_resource(anim);
+ }
+
+}
+
+void AnimationPlayerEditor::_animation_edit() {
+
+ 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 {
+
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
+
+ }
+
+}
+void AnimationPlayerEditor::_dialog_action(String p_file) {
+
+ switch (current_option) {
+ case RESOURCE_LOAD: {
+ ERR_FAIL_COND(!player);
+
+ Ref<Resource> res = ResourceLoader::load(p_file, "Animation");
+ ERR_FAIL_COND(res.is_null());
+ ERR_FAIL_COND(!res->is_class("Animation"));
+ if (p_file.find_last("/") != -1) {
+
+ p_file = p_file.substr(p_file.find_last("/") + 1, p_file.length());
+
+ }
+ if (p_file.find_last("\\") != -1) {
+
+ p_file = p_file.substr(p_file.find_last("\\") + 1, p_file.length());
+
+ }
+
+ if (p_file.find(".") != -1)
+ p_file = p_file.substr(0, p_file.find("."));
+
+ undo_redo->create_action(TTR("Load Animation"));
+ undo_redo->add_do_method(player, "add_animation", p_file, res);
+ undo_redo->add_undo_method(player, "remove_animation", p_file);
+ if (player->has_animation(p_file)) {
+ undo_redo->add_undo_method(player, "add_animation", p_file, player->get_animation(p_file));
+
+ }
+ undo_redo->add_do_method(this, "_animation_player_changed", player);
+ undo_redo->add_undo_method(this, "_animation_player_changed", player);
+ undo_redo->commit_action();
+ break;
+ }
+ case RESOURCE_SAVE: {
+
+ String current = animation->get_item_text(animation->get_selected());
+ if (current != "") {
+ Ref<Animation> anim = player->get_animation(current);
+
+ ERR_FAIL_COND(!anim->cast_to<Resource>())
+
+ RES current_res = RES(anim->cast_to<Resource>());
+
+ _animation_save_in_path(current_res, p_file);
+ }
+ }
+ }
+}
+
+void AnimationPlayerEditor::_scale_changed(const String& p_scale) {
+
+ player->set_speed_scale(p_scale.to_double());
+}
+
+void AnimationPlayerEditor::_update_animation() {
+
+ // the purpose of _update_animation is to reflect the current state
+ // of the animation player in the current editor..
+
+ updating=true;
+
+
+ if (player->is_playing()) {
+
+ play->set_pressed(true);
+ stop->set_pressed(false);
+
+ } else {
+
+ play->set_pressed(false);
+ stop->set_pressed(true);
+ }
+
+ scale->set_text( String::num(player->get_speed_scale(),2) );
+ String current=player->get_current_animation();
+
+ for (int i=0;i<animation->get_item_count();i++) {
+
+ if (animation->get_item_text(i)==current) {
+ animation->select(i);
+ break;
+ }
+ }
+
+ updating=false;
+}
+
+void AnimationPlayerEditor::_update_player() {
+
+
+ updating=true;
+ List<StringName> animlist;
+ if (player)
+ player->get_animation_list(&animlist);
+
+ animation->clear();
+ 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);
+ play_bw_from->set_disabled(animlist.size()==0);
+ play_from->set_disabled(animlist.size()==0);
+ autoplay->set_disabled(animlist.size()==0);
+ duplicate_anim->set_disabled(animlist.size()==0);
+ rename_anim->set_disabled(animlist.size()==0);
+ blend_anim->set_disabled(animlist.size()==0);
+ remove_anim->set_disabled(animlist.size()==0);
+ resource_edit_anim->set_disabled(animlist.size()==0);
+ save_anim->set_disabled(animlist.size() == 0);
+ tool_anim->set_disabled(player==NULL);
+
+
+ int active_idx=-1;
+ for (List<StringName>::Element *E=animlist.front();E;E=E->next()) {
+
+ if (player->get_autoplay()==E->get())
+ animation->add_icon_item(autoplay_icon,E->get());
+ else
+ animation->add_item(E->get());
+
+ if (player->get_current_animation()==E->get())
+ active_idx=animation->get_item_count()-1;
+
+ }
+
+ if (!player)
+ return;
+
+ updating=false;
+ if (active_idx!=-1) {
+ animation->select(active_idx);
+ autoplay->set_pressed(animation->get_item_text(active_idx)==player->get_autoplay());
+ _animation_selected(active_idx);
+
+ } else if (animation->get_item_count()>0){
+
+ animation->select(0);
+ autoplay->set_pressed(animation->get_item_text(0)==player->get_autoplay());
+ _animation_selected(0);
+ }
+
+ //pause->set_pressed(player->is_paused());
+
+
+ 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);
+ }
+
+ }
+
+ _update_animation();
+}
+
+
+
+void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
+
+
+ if (player && pin->is_pressed())
+ return; //ignore, pinned
+ player=p_player;
+
+ if (player) {
+ _update_player();
+ key_editor->show_select_node_warning(false);
+ } else {
+ key_editor->show_select_node_warning(true);
+
+ //hide();
+
+ }
+
+}
+
+
+void AnimationPlayerEditor::_animation_duplicate() {
+
+
+ if (!animation->get_item_count())
+ return;
+
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+ if (!anim.is_valid())
+ return;
+
+ Ref<Animation> new_anim = memnew( Animation );
+ List<PropertyInfo> plist;
+ anim->get_property_list(&plist);
+ for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
+
+ if (E->get().usage&PROPERTY_USAGE_STORAGE) {
+
+ new_anim->set(E->get().name, anim->get(E->get().name));
+ }
+ }
+ new_anim->set_path("");
+
+ String new_name = current;
+ while(player->has_animation(new_name)) {
+
+ new_name=new_name+" (copy)";
+ }
+
+
+ undo_redo->create_action(TTR("Duplicate Animation"));
+ undo_redo->add_do_method(player,"add_animation",new_name,new_anim);
+ undo_redo->add_undo_method(player,"remove_animation",new_name);
+ undo_redo->add_do_method(player,"animation_set_next",new_name,player->animation_get_next(current));
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+
+
+ for(int i=0;i<animation->get_item_count();i++) {
+
+ if (animation->get_item_text(i)==new_name) {
+
+ animation->select(i);
+ _animation_selected(i);
+ return;
+ }
+ }
+
+}
+
+void AnimationPlayerEditor::_seek_value_changed(float p_value,bool p_set) {
+
+ if (updating || !player || player->is_playing()) {
+ return;
+ };
+
+
+ updating=true;
+ String current=player->get_current_animation(); //animation->get_item_text( animation->get_selected() );
+ if (current == "" || !player->has_animation(current)) {
+ updating=false;
+ current="";
+ return;
+ };
+
+ Ref<Animation> anim;
+ anim=player->get_animation(current);
+
+ float pos = anim->get_length() * (p_value / frame->get_max());
+ float step = anim->get_step();
+ if (step) {
+ pos=Math::stepify(pos, step);
+ if (pos<0)
+ pos=0;
+ if (pos>=anim->get_length())
+ pos=anim->get_length();
+ }
+
+ if (player->is_valid() && !p_set) {
+ float cpos = player->get_current_animation_pos();
+
+ player->seek_delta(pos,pos-cpos);
+ } else {
+ player->seek(pos,true);
+ }
+
+
+ key_editor->set_anim_pos(pos);
+
+ updating=true;
+};
+
+void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) {
+
+ if (player==p_pl && is_visible_in_tree()) {
+
+ _update_player();
+ if (blend_editor.dialog->is_visible_in_tree())
+ _animation_blend(); //update
+ }
+}
+
+
+
+void AnimationPlayerEditor::_list_changed() {
+
+ if(is_visible_in_tree())
+ _update_player();
+}
+#if 0
+void AnimationPlayerEditor::_editor_store() {
+
+ if (animation->get_item_count()==0)
+ return;
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+
+ if (key_editor->get_current_animation()==anim)
+ return; //already there
+
+
+ undo_redo->create_action("Store anim in editor");
+ 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 = key_editor->get_current_animation();
+ if (anim.is_null())
+ return;
+
+ String existing = player->find_animation(anim);
+ if (existing!="") {
+ _select_anim_by_name(existing);
+ return; //already has
+ }
+
+ int count=1;
+ String base=anim->get_name();
+ bool noname=false;
+ if (base=="") {
+ base="New Anim";
+ noname=true;
+ }
+
+ while(true) {
+ String attempt = base;
+ if (count>1)
+ attempt+=" ("+itos(count)+")";
+ if (player->has_animation(attempt)) {
+ count++;
+ continue;
+ }
+ base=attempt;
+ break;
+ }
+
+ if (noname)
+ anim->set_name(base);
+
+ undo_redo->create_action("Add Animation From Editor");
+ undo_redo->add_do_method(player,"add_animation",base,anim);
+ undo_redo->add_undo_method(player,"remove_animation",base);
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+
+ _select_anim_by_name(base);
+
+
+}
+#endif
+
+void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float 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);
+
+}
+
+
+void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos,bool p_drag) {
+
+ if (!is_visible_in_tree())
+ return;
+ if (!player)
+ return;
+
+ if (player->is_playing() )
+ return;
+
+ updating=true;
+ frame->set_value(p_pos);
+ updating=false;
+ _seek_value_changed(p_pos,!p_drag);
+
+ EditorNode::get_singleton()->get_property_editor()->refresh();
+
+
+
+ //seekit
+}
+
+void AnimationPlayerEditor::_hide_anim_editors() {
+
+ player=NULL;
+ hide();
+ set_process(false);
+
+ key_editor->set_animation(Ref<Animation>());
+ key_editor->set_root(NULL);
+ key_editor->show_select_node_warning(true);
+ //editor->animation_editor_make_visible(false);
+
+}
+
+
+void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
+
+ switch(p_option) {
+
+ case TOOL_COPY_ANIM: {
+
+ if (!animation->get_item_count()) {
+ error_dialog->set_text(TTR("ERROR: No animation to copy!"));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+ //editor->edit_resource(anim);
+ EditorSettings::get_singleton()->set_resource_clipboard(anim);
+
+ } break;
+ case TOOL_PASTE_ANIM: {
+
+ Ref<Animation> anim = EditorSettings::get_singleton()->get_resource_clipboard();
+ if (!anim.is_valid()) {
+ error_dialog->set_text(TTR("ERROR: No animation resource on clipboard!"));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ String name = anim->get_name();
+ if (name=="") {
+ name=TTR("Pasted Animation");
+ }
+
+ int idx=1;
+ String base = name;
+ while (player->has_animation(name)) {
+
+ idx++;
+ name=base+" "+itos(idx);
+ }
+
+ undo_redo->create_action(TTR("Paste Animation"));
+ undo_redo->add_do_method(player,"add_animation",name,anim);
+ undo_redo->add_undo_method(player,"remove_animation",name);
+ undo_redo->add_do_method(this,"_animation_player_changed",player);
+ undo_redo->add_undo_method(this,"_animation_player_changed",player);
+ undo_redo->commit_action();
+
+ _select_anim_by_name(name);
+
+
+ } break;
+ case TOOL_EDIT_RESOURCE: {
+
+ if (!animation->get_item_count()) {
+ error_dialog->set_text(TTR("ERROR: No animation to edit!"));
+ error_dialog->popup_centered_minsize();
+ return;
+ }
+
+ String current = animation->get_item_text(animation->get_selected());
+ Ref<Animation> anim = player->get_animation(current);
+ editor->edit_resource(anim);
+
+ } break;
+
+ }
+}
+
+void AnimationPlayerEditor::_animation_save_menu(int p_option) {
+
+ String current = animation->get_item_text(animation->get_selected());
+ if (current != "") {
+ Ref<Animation> anim = player->get_animation(current);
+
+ switch (p_option) {
+ case ANIM_SAVE:
+ _animation_save(anim);
+ break;
+ case ANIM_SAVE_AS:
+ _animation_save_as(anim);
+ break;
+ }
+ }
+}
+
+void AnimationPlayerEditor::_unhandled_key_input(const InputEvent& p_ev) {
+
+ if (is_visible_in_tree() && p_ev.type==InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) {
+
+ switch(p_ev.key.scancode) {
+
+ case KEY_A: {
+ if (!p_ev.key.mod.shift)
+ _play_bw_from_pressed();
+ else
+ _play_bw_pressed();
+ } break;
+ case KEY_S: {
+ _stop_pressed();
+ } break;
+ case KEY_D: {
+ if (!p_ev.key.mod.shift)
+ _play_from_pressed();
+ else
+ _play_pressed();
+ } break;
+ }
+ }
+}
+
+void AnimationPlayerEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&AnimationPlayerEditor::_gui_input);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&AnimationPlayerEditor::_node_removed);
+ ClassDB::bind_method(D_METHOD("_play_pressed"),&AnimationPlayerEditor::_play_pressed);
+ ClassDB::bind_method(D_METHOD("_play_from_pressed"),&AnimationPlayerEditor::_play_from_pressed);
+ ClassDB::bind_method(D_METHOD("_play_bw_pressed"),&AnimationPlayerEditor::_play_bw_pressed);
+ ClassDB::bind_method(D_METHOD("_play_bw_from_pressed"),&AnimationPlayerEditor::_play_bw_from_pressed);
+ ClassDB::bind_method(D_METHOD("_stop_pressed"),&AnimationPlayerEditor::_stop_pressed);
+ ClassDB::bind_method(D_METHOD("_autoplay_pressed"),&AnimationPlayerEditor::_autoplay_pressed);
+ ClassDB::bind_method(D_METHOD("_pause_pressed"),&AnimationPlayerEditor::_pause_pressed);
+ ClassDB::bind_method(D_METHOD("_animation_selected"),&AnimationPlayerEditor::_animation_selected);
+ ClassDB::bind_method(D_METHOD("_animation_name_edited"),&AnimationPlayerEditor::_animation_name_edited);
+ ClassDB::bind_method(D_METHOD("_animation_new"),&AnimationPlayerEditor::_animation_new);
+ ClassDB::bind_method(D_METHOD("_animation_rename"),&AnimationPlayerEditor::_animation_rename);
+ ClassDB::bind_method(D_METHOD("_animation_load"),&AnimationPlayerEditor::_animation_load);
+ ClassDB::bind_method(D_METHOD("_animation_remove"),&AnimationPlayerEditor::_animation_remove);
+ ClassDB::bind_method(D_METHOD("_animation_remove_confirmed"),&AnimationPlayerEditor::_animation_remove_confirmed);
+ ClassDB::bind_method(D_METHOD("_animation_blend"),&AnimationPlayerEditor::_animation_blend);
+ ClassDB::bind_method(D_METHOD("_animation_edit"),&AnimationPlayerEditor::_animation_edit);
+ ClassDB::bind_method(D_METHOD("_animation_resource_edit"),&AnimationPlayerEditor::_animation_resource_edit);
+ ClassDB::bind_method(D_METHOD("_dialog_action"),&AnimationPlayerEditor::_dialog_action);
+ ClassDB::bind_method(D_METHOD("_seek_value_changed"),&AnimationPlayerEditor::_seek_value_changed,DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("_animation_player_changed"),&AnimationPlayerEditor::_animation_player_changed);
+ ClassDB::bind_method(D_METHOD("_blend_edited"),&AnimationPlayerEditor::_blend_edited);
+ //ClassDB::bind_method(D_METHOD("_seek_frame_changed"),&AnimationPlayerEditor::_seek_frame_changed);
+ ClassDB::bind_method(D_METHOD("_scale_changed"),&AnimationPlayerEditor::_scale_changed);
+ //ClassDB::bind_method(D_METHOD("_editor_store_all"),&AnimationPlayerEditor::_editor_store_all);
+ //ClassDB::bind_method(D_METHOD("_editor_load_all"),&AnimationPlayerEditor::_editor_load_all);
+ ClassDB::bind_method(D_METHOD("_list_changed"),&AnimationPlayerEditor::_list_changed);
+ ClassDB::bind_method(D_METHOD("_animation_key_editor_seek"),&AnimationPlayerEditor::_animation_key_editor_seek);
+ ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_len_changed"),&AnimationPlayerEditor::_animation_key_editor_anim_len_changed);
+ ClassDB::bind_method(D_METHOD("_animation_key_editor_anim_step_changed"),&AnimationPlayerEditor::_animation_key_editor_anim_step_changed);
+ ClassDB::bind_method(D_METHOD("_hide_anim_editors"),&AnimationPlayerEditor::_hide_anim_editors);
+ ClassDB::bind_method(D_METHOD("_animation_duplicate"),&AnimationPlayerEditor::_animation_duplicate);
+ ClassDB::bind_method(D_METHOD("_blend_editor_next_changed"),&AnimationPlayerEditor::_blend_editor_next_changed);
+ ClassDB::bind_method(D_METHOD("_unhandled_key_input"),&AnimationPlayerEditor::_unhandled_key_input);
+ ClassDB::bind_method(D_METHOD("_animation_tool_menu"),&AnimationPlayerEditor::_animation_tool_menu);
+ ClassDB::bind_method(D_METHOD("_animation_save_menu"), &AnimationPlayerEditor::_animation_save_menu);
+
+
+
+
+}
+
+AnimationPlayerEditor *AnimationPlayerEditor::singleton=NULL;
+
+AnimationPlayer *AnimationPlayerEditor::get_player() const {
+
+ return player;
+}
+AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
+ editor=p_editor;
+ singleton=this;
+
+ updating=false;
+
+ set_focus_mode(FOCUS_ALL);
+
+ player=NULL;
+ add_style_override("panel", get_stylebox("panel","Panel"));
+
+
+ Label * l;
+
+ /*l= memnew( Label );
+ l->set_text("Animation Player:");
+ add_child(l);*/
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ add_child(hb);
+
+
+ play_bw_from = memnew( ToolButton );
+ play_bw_from->set_tooltip(TTR("Play selected animation backwards from current pos. (A)"));
+ hb->add_child(play_bw_from);
+
+ play_bw = memnew( ToolButton );
+ play_bw->set_tooltip(TTR("Play selected animation backwards from end. (Shift+A)"));
+ hb->add_child(play_bw);
+
+ stop = memnew( ToolButton );
+ stop->set_toggle_mode(true);
+ hb->add_child(stop);
+ stop->set_tooltip(TTR("Stop animation playback. (S)"));
+
+ play = memnew( ToolButton );
+ play->set_tooltip(TTR("Play selected animation from start. (Shift+D)"));
+ hb->add_child(play);
+
+
+ play_from = memnew( ToolButton );
+ play_from->set_tooltip(TTR("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(60,0));
+ frame->set_stretch_ratio(2);
+ frame->set_tooltip(TTR("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(TTR("Scale animation playback globally for the node."));
+ scale->hide();
+
+
+ add_anim = memnew( ToolButton );
+ ED_SHORTCUT("animation_player_editor/add_animation", TTR("Create new animation in player."));
+ add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/add_animation"));
+ add_anim->set_tooltip(TTR("Create new animation in player."));
+
+ hb->add_child(add_anim);
+
+
+ load_anim = memnew( ToolButton );
+ ED_SHORTCUT("animation_player_editor/load_from_disk", TTR("Load animation from disk."));
+ add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/load_from_disk"));
+ load_anim->set_tooltip(TTR("Load an animation from disk."));
+ hb->add_child(load_anim);
+
+ save_anim = memnew(MenuButton);
+ save_anim->set_tooltip(TTR("Save the current animation"));
+ save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save", TTR("Save")), ANIM_SAVE);
+ save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_as", TTR("Save As")), ANIM_SAVE_AS);
+ save_anim->set_focus_mode(Control::FOCUS_NONE);
+ hb->add_child(save_anim);
+
+ accept = memnew(AcceptDialog);
+ add_child(accept);
+ accept->connect("confirmed", this, "_menu_confirm_current");
+
+ delete_dialog = memnew(ConfirmationDialog);
+ add_child(delete_dialog);
+ delete_dialog->connect("confirmed", this, "_animation_remove_confirmed");
+
+ duplicate_anim = memnew( ToolButton );
+ hb->add_child(duplicate_anim);
+ ED_SHORTCUT("animation_player_editor/duplicate_animation", TTR("Duplicate Animation"));
+ duplicate_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/duplicate_animation"));
+ duplicate_anim->set_tooltip(TTR("Duplicate Animation"));
+
+ rename_anim = memnew( ToolButton );
+ hb->add_child(rename_anim);
+ ED_SHORTCUT("animation_player_editor/rename_animation", TTR("Rename Animation"));
+ rename_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/rename_animation"));
+ rename_anim->set_tooltip(TTR("Rename Animation"));
+
+ remove_anim = memnew( ToolButton );
+ hb->add_child(remove_anim);
+ ED_SHORTCUT("animation_player_editor/remove_animation", TTR("Remove Animation"));
+ remove_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/remove_animation"));
+ remove_anim->set_tooltip(TTR("Remove Animation"));
+
+
+ animation = memnew( OptionButton );
+ hb->add_child(animation);
+ animation->set_h_size_flags(SIZE_EXPAND_FILL);
+ animation->set_tooltip(TTR("Display list of animations in player."));
+ animation->set_clip_text(true);
+
+ autoplay = memnew( ToolButton );
+ hb->add_child(autoplay);
+ autoplay->set_tooltip(TTR("Autoplay on Load"));
+
+
+
+ blend_anim = memnew( ToolButton );
+ hb->add_child(blend_anim);
+ blend_anim->set_tooltip(TTR("Edit Target Blend Times"));
+
+ tool_anim = memnew( MenuButton);
+ //tool_anim->set_flat(false);
+ tool_anim->set_tooltip(TTR("Animation Tools"));
+ tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/copy_animation", TTR("Copy Animation")),TOOL_COPY_ANIM);
+ tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/paste_animation", TTR("Paste Animation")),TOOL_PASTE_ANIM);
+ //tool_anim->get_popup()->add_separator();
+ //tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM);
+ hb->add_child(tool_anim);
+
+ nodename = memnew( Button );
+ hb->add_child(nodename);
+ pin = memnew( ToolButton );
+ pin->set_toggle_mode(true);
+ hb->add_child(pin);
+
+
+
+ resource_edit_anim= memnew( Button );
+ hb->add_child(resource_edit_anim);
+ resource_edit_anim->hide();
+
+
+ file = memnew(EditorFileDialog);
+ add_child(file);
+
+ name_dialog = memnew( ConfirmationDialog );
+ name_dialog->set_title(TTR("Create New Animation"));
+ name_dialog->set_hide_on_ok(false);
+ add_child(name_dialog);
+ name = memnew( LineEdit );
+ name_dialog->add_child(name);
+ name->set_pos(Point2(18,30));
+ name->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,10);
+ name_dialog->register_text_enter(name);
+
+
+ l = memnew( Label );
+ l->set_text(TTR("Animation Name:"));
+ l->set_pos( Point2(10,10) );
+
+ name_dialog->add_child(l);
+ name_title=l;
+
+ error_dialog = memnew( ConfirmationDialog );
+ error_dialog->get_ok()->set_text(TTR("Close"));
+ //error_dialog->get_cancel()->set_text("Close");
+ error_dialog->set_text(TTR("Error!"));
+ add_child(error_dialog);
+
+ name_dialog->connect("confirmed", this,"_animation_name_edited");
+
+ blend_editor.dialog = memnew( AcceptDialog );
+ add_child(blend_editor.dialog);
+ blend_editor.dialog->get_ok()->set_text(TTR("Close"));
+ blend_editor.dialog->set_hide_on_ok(true);
+ VBoxContainer *blend_vb = memnew( VBoxContainer);
+ blend_editor.dialog->add_child(blend_vb);
+ //blend_editor.dialog->set_child_rect(blend_vb);
+ blend_editor.tree = memnew( Tree );
+ blend_editor.tree->set_columns(2);
+ blend_vb->add_margin_child(TTR("Blend Times:"),blend_editor.tree,true);
+ blend_editor.next = memnew( OptionButton );
+ blend_vb->add_margin_child(TTR("Next (Auto Queue):"),blend_editor.next);
+ blend_editor.dialog->set_title(TTR("Cross-Animation Blend Times"));
+ updating_blends=false;
+
+ blend_editor.tree->connect("item_edited",this,"_blend_edited");
+
+
+ autoplay->connect("pressed", this,"_autoplay_pressed");
+ autoplay->set_toggle_mode(true);
+ play->connect("pressed", this,"_play_pressed");
+ play_from->connect("pressed", this,"_play_from_pressed");
+ play_bw->connect("pressed", this,"_play_bw_pressed");
+ play_bw_from->connect("pressed", this,"_play_bw_from_pressed");
+ stop->connect("pressed", this,"_stop_pressed");
+ //pause->connect("pressed", this,"_pause_pressed");
+ add_anim->connect("pressed", this,"_animation_new");
+ rename_anim->connect("pressed", this,"_animation_rename");
+ load_anim->connect("pressed", this,"_animation_load");
+ duplicate_anim->connect("pressed", this,"_animation_duplicate");
+ //frame->connect("text_entered", this,"_seek_frame_changed");
+
+ 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");
+ frame->connect("value_changed", this, "_seek_value_changed",Vector<Variant>(),true);
+ scale->connect("text_entered", this, "_scale_changed",Vector<Variant>(),true);
+
+
+
+ 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();
+}
+
+
+void AnimationPlayerEditorPlugin::edit(Object *p_object) {
+
+ anim_editor->set_undo_redo(&get_undo_redo());
+ if (!p_object)
+ return;
+ anim_editor->edit(p_object->cast_to<AnimationPlayer>());
+
+
+}
+
+bool AnimationPlayerEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("AnimationPlayer");
+}
+
+void AnimationPlayerEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ editor->make_bottom_panel_item_visible(anim_editor);
+ anim_editor->set_process(true);
+ anim_editor->ensure_visibility();
+ //editor->animation_panel_make_visible(true);
+ } else {
+
+ //anim_editor->hide();
+ //anim_editor->set_idle_process(false);
+ }
+
+}
+
+AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ anim_editor = memnew( AnimationPlayerEditor(editor) );
+ anim_editor->set_undo_redo(editor->get_undo_redo());
+
+ editor->add_bottom_panel_item(TTR("Animation"),anim_editor);
+ /*
+ editor->get_viewport()->add_child(anim_editor);
+ anim_editor->set_area_as_parent_rect();
+ anim_editor->set_anchor( MARGIN_TOP, Control::ANCHOR_END);
+ anim_editor->set_margin( MARGIN_TOP, 75 );
+ anim_editor->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END);
+ anim_editor->set_margin( MARGIN_RIGHT, 0 );*/
+ anim_editor->hide();
+
+
+
+}
+
+
+AnimationPlayerEditorPlugin::~AnimationPlayerEditorPlugin()
+{
+}
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
new file mode 100644
index 0000000000..d9b6ad52ff
--- /dev/null
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -0,0 +1,219 @@
+/*************************************************************************/
+/* animation_player_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 ANIMATION_PLAYER_EDITOR_PLUGIN_H
+#define ANIMATION_PLAYER_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/animation/animation_player.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/texture_button.h"
+#include "scene/gui/slider.h"
+#include "scene/gui/spin_box.h"
+
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class AnimationKeyEditor;
+class AnimationPlayerEditor : public VBoxContainer {
+
+ GDCLASS(AnimationPlayerEditor, VBoxContainer );
+
+ EditorNode *editor;
+ AnimationPlayer *player;
+
+ enum {
+ TOOL_COPY_ANIM,
+ TOOL_PASTE_ANIM,
+ TOOL_EDIT_RESOURCE
+ };
+
+ enum {
+ ANIM_SAVE,
+ ANIM_SAVE_AS
+ };
+
+ enum {
+ RESOURCE_LOAD,
+ RESOURCE_SAVE
+ };
+
+
+ OptionButton *animation;
+ Button *stop;
+ Button *play;
+ Button *play_from;
+ Button *play_bw;
+ Button *play_bw_from;
+
+ //Button *pause;
+ Button *add_anim;
+ Button *autoplay;
+ Button *rename_anim;
+ Button *duplicate_anim;
+
+ Button *resource_edit_anim;
+ Button *load_anim;
+ MenuButton *save_anim;
+ Button *blend_anim;
+ Button *remove_anim;
+ MenuButton *tool_anim;
+ ToolButton *pin;
+ Button *nodename;
+ SpinBox *frame;
+ LineEdit *scale;
+ LineEdit *name;
+ Label *name_title;
+ UndoRedo *undo_redo;
+ Ref<Texture> autoplay_icon;
+ bool last_active;
+
+ EditorFileDialog *file;
+ AcceptDialog *accept;
+ ConfirmationDialog* delete_dialog;
+ int current_option;
+
+ struct BlendEditor {
+
+ AcceptDialog * dialog;
+ Tree *tree;
+ OptionButton *next;
+
+ } blend_editor;
+
+
+ ConfirmationDialog *name_dialog;
+ ConfirmationDialog *error_dialog;
+ bool renaming;
+
+
+ bool updating;
+ bool updating_blends;
+
+ AnimationKeyEditor *key_editor;
+
+
+ void _select_anim_by_name(const String& p_anim);
+ void _play_pressed();
+ void _play_from_pressed();
+ void _play_bw_pressed();
+ void _play_bw_from_pressed();
+ void _autoplay_pressed();
+ void _stop_pressed();
+ void _pause_pressed();
+ void _animation_selected(int p_which);
+ void _animation_new();
+ void _animation_rename();
+ void _animation_name_edited();
+ void _animation_load();
+
+ void _animation_save_in_path(const Ref<Resource>& p_resource, const String& p_path);
+ void _animation_save(const Ref<Resource>& p_resource);
+ void _animation_save_as(const Ref<Resource>& p_resource);
+
+ void _animation_remove();
+ void _animation_remove_confirmed();
+ void _animation_blend();
+ void _animation_edit();
+ void _animation_duplicate();
+ void _animation_resource_edit();
+ void _scale_changed(const String& p_scale);
+ void _dialog_action(String p_file);
+ void _seek_frame_changed(const String& p_frame);
+ void _seek_value_changed(float p_value, bool p_set=false);
+ void _blend_editor_next_changed(const int p_idx);
+
+ void _list_changed();
+ void _update_animation();
+ void _update_player();
+ void _blend_edited();
+
+
+ void _hide_anim_editors();
+
+ void _animation_player_changed(Object *p_pl);
+
+ void _animation_key_editor_seek(float p_pos, bool p_drag);
+ 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:
+
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ void _node_removed(Node *p_node);
+ 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);
+
+
+ void ensure_visibility();
+
+ void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
+ void edit(AnimationPlayer *p_player);
+ AnimationPlayerEditor(EditorNode *p_editor);
+};
+
+class AnimationPlayerEditorPlugin : public EditorPlugin {
+
+ GDCLASS( AnimationPlayerEditorPlugin, EditorPlugin );
+
+ AnimationPlayerEditor *anim_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual Dictionary get_state() const { return anim_editor->get_state(); }
+ virtual void set_state(const Dictionary& p_state) { anim_editor->set_state(p_state); }
+
+ virtual String get_name() const { return "Anim"; }
+ 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);
+
+ AnimationPlayerEditorPlugin(EditorNode *p_node);
+ ~AnimationPlayerEditorPlugin();
+
+};
+
+#endif // ANIMATION_PLAYER_EDITOR_PLUGIN_H
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
new file mode 100644
index 0000000000..988136d475
--- /dev/null
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -0,0 +1,1536 @@
+/*************************************************************************/
+/* animation_tree_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "animation_tree_editor_plugin.h"
+
+#include "scene/gui/menu_button.h"
+#include "scene/gui/panel.h"
+#include "scene/main/viewport.h"
+#include "core/io/resource_loader.h"
+#include "core/global_config.h"
+#include "os/input.h"
+#include "os/keyboard.h"
+
+void AnimationTreeEditor::edit(AnimationTreePlayer* p_anim_tree) {
+
+
+ anim_tree=p_anim_tree;
+
+ if (!anim_tree) {
+ hide();
+ } else {
+ order.clear();
+ p_anim_tree->get_node_list(&order);
+ /*
+ for(List<StringName>::Element* E=order.front();E;E=E->next()) {
+
+ if (E->get() >= (int)last_id)
+ last_id=E->get()+1;
+ }*/
+ play_button->set_pressed(p_anim_tree->is_active());
+ //read the orders
+ }
+
+}
+
+Size2 AnimationTreeEditor::_get_maximum_size() {
+
+ Size2 max;
+
+ for(List<StringName>::Element *E=order.front();E;E=E->next()) {
+
+ Point2 pos = anim_tree->node_get_pos(E->get());
+
+ if (click_type==CLICK_NODE && click_node==E->get()) {
+
+ pos+=click_motion-click_pos;
+ }
+ pos+=get_node_size(E->get());
+ if (pos.x>max.x)
+ max.x=pos.x;
+ if (pos.y>max.y)
+ max.y=pos.y;
+
+ }
+
+ return max;
+}
+
+
+const char* AnimationTreeEditor::_node_type_names[]={"Output","Animation","OneShot","Mix","Blend2","Blend3","Blend4","TimeScale","TimeSeek","Transition"};
+
+Size2 AnimationTreeEditor::get_node_size(const StringName& p_node) const {
+
+ AnimationTreePlayer::NodeType type=anim_tree->node_get_type(p_node);
+
+ Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
+ Ref<Font> font = get_font("font","PopupMenu");
+
+ Size2 size = style->get_minimum_size();
+
+ int count=2; // title and name
+ int inputs = anim_tree->node_get_input_count(p_node);
+ count += inputs?inputs:1;
+ String name = p_node;
+
+
+ float name_w = font->get_string_size( name ).width;
+ float type_w = font->get_string_size( String(_node_type_names[type]) ).width;
+ float max_w=MAX(name_w,type_w);
+
+
+
+ switch(type) {
+ case AnimationTreePlayer::NODE_TIMESEEK:
+ case AnimationTreePlayer::NODE_OUTPUT: {} break;
+ case AnimationTreePlayer::NODE_ANIMATION:
+ case AnimationTreePlayer::NODE_ONESHOT:
+ case AnimationTreePlayer::NODE_MIX:
+ case AnimationTreePlayer::NODE_BLEND2:
+ case AnimationTreePlayer::NODE_BLEND3:
+ case AnimationTreePlayer::NODE_BLEND4:
+ case AnimationTreePlayer::NODE_TIMESCALE:
+ case AnimationTreePlayer::NODE_TRANSITION: {
+
+
+ size.height+=font->get_height();
+ } break;
+ case AnimationTreePlayer::NODE_MAX: {}
+ }
+
+ size.x+=max_w+20;
+ size.y+=count*(font->get_height()+get_constant("vseparation","PopupMenu"));
+
+ return size;
+}
+
+
+void AnimationTreeEditor::_edit_dialog_changede(String) {
+
+ edit_dialog->hide();
+}
+
+void AnimationTreeEditor::_edit_dialog_changeds(String s) {
+
+ _edit_dialog_changed();
+}
+
+void AnimationTreeEditor::_edit_dialog_changedf(float) {
+
+ _edit_dialog_changed();
+}
+
+void AnimationTreeEditor::_edit_dialog_changed() {
+
+ if (updating_edit)
+ return;
+
+ if (renaming_edit) {
+
+ if (anim_tree->node_rename(edited_node,edit_line[0]->get_text())==OK) {
+ for(List<StringName>::Element* E=order.front();E;E=E->next()) {
+
+ if (E->get() == edited_node)
+ E->get()=edit_line[0]->get_text();
+ }
+ edited_node=edit_line[0]->get_text();
+ }
+ update();
+ return;
+ }
+
+ AnimationTreePlayer::NodeType type=anim_tree->node_get_type(edited_node);
+
+ switch(type) {
+
+ case AnimationTreePlayer::NODE_TIMESCALE:
+ anim_tree->timescale_node_set_scale(edited_node,edit_line[0]->get_text().to_double());
+ break;
+ case AnimationTreePlayer::NODE_ONESHOT:
+ anim_tree->oneshot_node_set_fadein_time(edited_node,edit_line[0]->get_text().to_double());
+ anim_tree->oneshot_node_set_fadeout_time(edited_node,edit_line[1]->get_text().to_double());
+ anim_tree->oneshot_node_set_autorestart_delay(edited_node,edit_line[2]->get_text().to_double());
+ anim_tree->oneshot_node_set_autorestart_random_delay(edited_node,edit_line[3]->get_text().to_double());
+ anim_tree->oneshot_node_set_autorestart(edited_node,edit_check->is_pressed());
+ anim_tree->oneshot_node_set_mix_mode(edited_node,edit_option->get_selected());
+
+ break;
+
+ case AnimationTreePlayer::NODE_MIX:
+
+ anim_tree->mix_node_set_amount(edited_node,edit_scroll[0]->get_value());
+ break;
+ case AnimationTreePlayer::NODE_BLEND2:
+ anim_tree->blend2_node_set_amount(edited_node,edit_scroll[0]->get_value());
+
+ break;
+
+ case AnimationTreePlayer::NODE_BLEND3:
+ anim_tree->blend3_node_set_amount(edited_node,edit_scroll[0]->get_value());
+
+ break;
+ case AnimationTreePlayer::NODE_BLEND4:
+
+ anim_tree->blend4_node_set_amount(edited_node,Point2(edit_scroll[0]->get_value(),edit_scroll[1]->get_value()));
+
+ break;
+
+ case AnimationTreePlayer::NODE_TRANSITION: {
+ anim_tree->transition_node_set_xfade_time(edited_node,edit_line[0]->get_text().to_double());
+ if (anim_tree->transition_node_get_current(edited_node)!=edit_option->get_selected())
+ anim_tree->transition_node_set_current(edited_node,edit_option->get_selected());
+ } break;
+ default: {}
+ }
+
+}
+
+void AnimationTreeEditor::_edit_dialog_animation_changed() {
+
+
+ Ref<Animation> anim = property_editor->get_variant().operator RefPtr();
+ anim_tree->animation_node_set_animation(edited_node,anim);
+ update();
+}
+
+void AnimationTreeEditor::_edit_dialog_edit_animation() {
+
+ if (get_tree()->is_editor_hint()) {
+ get_tree()->get_root()->get_child(0)->call("_resource_selected", property_editor->get_variant().operator RefPtr());
+ };
+};
+
+void AnimationTreeEditor::_edit_oneshot_start() {
+
+ anim_tree->oneshot_node_start(edited_node);
+}
+
+void AnimationTreeEditor::_play_toggled() {
+
+ anim_tree->set_active(play_button->is_pressed());
+}
+
+
+void AnimationTreeEditor::_master_anim_menu_item(int p_item) {
+
+ if(p_item == 0) _edit_filters();
+ else {
+
+ String str = master_anim_popup->get_item_text(p_item);
+ anim_tree->animation_node_set_master_animation(edited_node,str);
+ }
+ update();
+}
+
+void AnimationTreeEditor::_popup_edit_dialog() {
+
+ updating_edit=true;
+
+ for(int i=0;i<2;i++)
+ edit_scroll[i]->hide();
+
+ for(int i=0;i<4;i++) {
+
+ edit_line[i]->hide();
+ edit_label[i]->hide();
+ }
+
+ edit_option->hide();
+ edit_button->hide();
+ filter_button->hide();
+ edit_check->hide();
+
+ Point2 pos = anim_tree->node_get_pos(edited_node)-Point2(h_scroll->get_value(),v_scroll->get_value());
+ Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
+ Size2 size = get_node_size(edited_node);
+ Point2 popup_pos( pos.x+style->get_margin(MARGIN_LEFT), pos.y+size.y-style->get_margin(MARGIN_BOTTOM));
+ popup_pos+=get_global_pos();
+
+ if (renaming_edit) {
+
+ edit_label[0]->set_text(TTR("New name:"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_line[0]->set_begin(Point2(15,25));
+ edit_line[0]->set_text(edited_node);
+ edit_line[0]->show();
+ edit_dialog->set_size(Size2(150,50));
+
+ } else {
+
+ AnimationTreePlayer::NodeType type=anim_tree->node_get_type(edited_node);
+
+
+ switch(type) {
+
+ case AnimationTreePlayer::NODE_ANIMATION:
+
+ if (anim_tree->get_master_player()!=NodePath() && anim_tree->has_node(anim_tree->get_master_player()) && anim_tree->get_node(anim_tree->get_master_player())->cast_to<AnimationPlayer>()) {
+
+ AnimationPlayer *ap = anim_tree->get_node(anim_tree->get_master_player())->cast_to<AnimationPlayer>();
+ master_anim_popup->clear();
+ master_anim_popup->add_item("Edit Filters");
+ master_anim_popup->add_separator();
+ List<StringName> sn;
+ ap->get_animation_list(&sn);
+ sn.sort_custom<StringName::AlphCompare>();
+ for (List<StringName>::Element *E=sn.front();E;E=E->next()) {
+ master_anim_popup->add_item(E->get());
+ }
+
+ master_anim_popup->set_pos(popup_pos);
+ master_anim_popup->popup();
+ } else {
+ property_editor->edit(this,"",Variant::OBJECT,anim_tree->animation_node_get_animation(edited_node),PROPERTY_HINT_RESOURCE_TYPE,"Animation");
+ property_editor->set_pos(popup_pos);
+ property_editor->popup();
+ updating_edit=false;
+ }
+ return;
+ case AnimationTreePlayer::NODE_TIMESCALE:
+ edit_label[0]->set_text(TTR("Scale:"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_line[0]->set_begin(Point2(15,25));
+ edit_line[0]->set_text(rtos(anim_tree->timescale_node_get_scale(edited_node)));
+ edit_line[0]->show();
+ edit_dialog->set_size(Size2(150,50));
+ break;
+ case AnimationTreePlayer::NODE_ONESHOT:
+ edit_label[0]->set_text(TTR("Fade In (s):"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_line[0]->set_begin(Point2(15,25));
+ edit_line[0]->set_text(rtos(anim_tree->oneshot_node_get_fadein_time(edited_node)));
+ edit_line[0]->show();
+ edit_label[1]->set_text(TTR("Fade Out (s):"));
+ edit_label[1]->set_pos(Point2(5,55));
+ edit_label[1]->show();
+ edit_line[1]->set_begin(Point2(15,75));
+ edit_line[1]->set_text(rtos(anim_tree->oneshot_node_get_fadeout_time(edited_node)));
+ edit_line[1]->show();
+
+ edit_option->clear();
+ edit_option->add_item(TTR("Blend"),0);
+ edit_option->add_item(TTR("Mix"),1);
+ edit_option->set_begin(Point2(15,105));
+
+ edit_option->select( anim_tree->oneshot_node_get_mix_mode(edited_node));
+ edit_option->show();
+
+ edit_check->set_text(TTR("Auto Restart:"));
+ edit_check->set_begin(Point2(15,125));
+ edit_check->set_pressed(anim_tree->oneshot_node_has_autorestart(edited_node));
+ edit_check->show();
+
+ edit_label[2]->set_text(TTR("Restart (s):"));
+ edit_label[2]->set_pos(Point2(5,145));
+ edit_label[2]->show();
+ edit_line[2]->set_begin(Point2(15,165));
+ edit_line[2]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_delay(edited_node)));
+ edit_line[2]->show();
+ edit_label[3]->set_text(TTR("Random Restart (s):"));
+ edit_label[3]->set_pos(Point2(5,195));
+ edit_label[3]->show();
+ edit_line[3]->set_begin(Point2(15,215));
+ edit_line[3]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_random_delay(edited_node)));
+ edit_line[3]->show();
+
+ filter_button->set_begin(Point2(10,245));
+ filter_button->show();
+
+ edit_button->set_begin(Point2(10,268));
+ edit_button->set_text(TTR("Start!"));
+
+ edit_button->show();
+
+ edit_dialog->set_size(Size2(180,293));
+
+ break;
+
+ case AnimationTreePlayer::NODE_MIX:
+
+ edit_label[0]->set_text(TTR("Amount:"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_scroll[0]->set_min(0);
+ edit_scroll[0]->set_max(1);
+ edit_scroll[0]->set_value(anim_tree->mix_node_get_amount(edited_node));
+ edit_scroll[0]->set_begin(Point2(15,25));
+ edit_scroll[0]->show();
+ edit_dialog->set_size(Size2(150,50));
+
+ break;
+ case AnimationTreePlayer::NODE_BLEND2:
+ edit_label[0]->set_text(TTR("Blend:"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_scroll[0]->set_min(0);
+ edit_scroll[0]->set_max(1);
+ edit_scroll[0]->set_value(anim_tree->blend2_node_get_amount(edited_node));
+ edit_scroll[0]->set_begin(Point2(15,25));
+ edit_scroll[0]->show();
+ filter_button->set_begin(Point2(10,47));
+ filter_button->show();
+ edit_dialog->set_size(Size2(150,74));
+
+ break;
+
+ case AnimationTreePlayer::NODE_BLEND3:
+ edit_label[0]->set_text(TTR("Blend:"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_scroll[0]->set_min(-1);
+ edit_scroll[0]->set_max(1);
+ edit_scroll[0]->set_value(anim_tree->blend3_node_get_amount(edited_node));
+ edit_scroll[0]->set_begin(Point2(15,25));
+ edit_scroll[0]->show();
+ edit_dialog->set_size(Size2(150,50));
+
+ break;
+ case AnimationTreePlayer::NODE_BLEND4:
+
+ edit_label[0]->set_text(TTR("Blend 0:"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_scroll[0]->set_min(0);
+ edit_scroll[0]->set_max(1);
+ edit_scroll[0]->set_value(anim_tree->blend4_node_get_amount(edited_node).x);
+ edit_scroll[0]->set_begin(Point2(15,25));
+ edit_scroll[0]->show();
+ edit_label[1]->set_text(TTR("Blend 1:"));
+ edit_label[1]->set_pos(Point2(5,55));
+ edit_label[1]->show();
+ edit_scroll[1]->set_min(0);
+ edit_scroll[1]->set_max(1);
+ edit_scroll[1]->set_value(anim_tree->blend4_node_get_amount(edited_node).y);
+ edit_scroll[1]->set_begin(Point2(15,75));
+ edit_scroll[1]->show();
+ edit_dialog->set_size(Size2(150,100));
+
+ break;
+
+ case AnimationTreePlayer::NODE_TRANSITION: {
+
+
+ edit_label[0]->set_text(TTR("X-Fade Time (s):"));
+ edit_label[0]->set_pos(Point2(5,5));
+ edit_label[0]->show();
+ edit_line[0]->set_begin(Point2(15,25));
+ edit_line[0]->set_text(rtos(anim_tree->transition_node_get_xfade_time(edited_node)));
+ edit_line[0]->show();
+
+ edit_label[1]->set_text(TTR("Current:"));
+ edit_label[1]->set_pos(Point2(5,55));
+ edit_label[1]->show();
+ edit_option->set_begin(Point2(15,75));
+
+ edit_option->clear();
+
+ for(int i=0;i<anim_tree->transition_node_get_input_count(edited_node);i++) {
+ edit_option->add_item(itos(i),i);
+ }
+
+ edit_option->select(anim_tree->transition_node_get_current(edited_node));
+ edit_option->show();
+ edit_dialog->set_size(Size2(150,100));
+
+ } break;
+ default: {}
+
+ }
+
+ }
+
+
+
+ edit_dialog->set_pos(popup_pos);
+ edit_dialog->popup();
+
+ updating_edit=false;
+}
+
+void AnimationTreeEditor::_draw_node(const StringName& p_node) {
+
+ RID ci = get_canvas_item();
+ AnimationTreePlayer::NodeType type=anim_tree->node_get_type(p_node);
+
+ Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
+ Ref<Font> font = get_font("font","PopupMenu");
+ Color font_color = get_color("font_color","PopupMenu");
+ Color font_color_title = get_color("font_color_hover","PopupMenu");
+ font_color_title.a*=0.8;
+ Ref<Texture> slot_icon = get_icon("NodeRealSlot","EditorIcons");
+
+
+ Size2 size=get_node_size(p_node);
+ Point2 pos = anim_tree->node_get_pos(p_node);
+ if (click_type==CLICK_NODE && click_node==p_node) {
+
+ pos+=click_motion-click_pos;
+ if (pos.x<5)
+ pos.x=5;
+ if (pos.y<5)
+ pos.y=5;
+
+ }
+
+ pos-=Point2(h_scroll->get_value(),v_scroll->get_value());
+
+ style->draw(ci,Rect2(pos,size));
+
+ float w = size.width-style->get_minimum_size().width;
+ float h = font->get_height()+get_constant("vseparation","PopupMenu");
+
+ Point2 ofs=style->get_offset()+pos;
+ Point2 ascofs(0,font->get_ascent());
+
+ Color bx = font_color_title;
+ bx.a*=0.1;
+ draw_rect(Rect2(ofs,Size2(size.width-style->get_minimum_size().width,font->get_height())),bx);
+ font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,String(_node_type_names[type]),font_color_title);
+
+ ofs.y+=h;
+ font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,p_node,font_color);
+ ofs.y+=h;
+
+ int count=2; // title and name
+ int inputs = anim_tree->node_get_input_count(p_node);
+ count += inputs?inputs:1;
+
+ float icon_h_ofs = Math::floor(( font->get_height()-slot_icon->get_height())/2.0 )+1;
+
+ if (type!=AnimationTreePlayer::NODE_OUTPUT)
+ slot_icon->draw(ci,ofs+Point2(w,icon_h_ofs)); //output
+
+ if (inputs) {
+ for(int i=0;i<inputs;i++) {
+
+ slot_icon->draw(ci,ofs+Point2(-slot_icon->get_width(),icon_h_ofs));
+ String text;
+ switch(type) {
+
+ case AnimationTreePlayer::NODE_TIMESCALE:
+ case AnimationTreePlayer::NODE_TIMESEEK: text="in"; break;
+ case AnimationTreePlayer::NODE_OUTPUT: text="out"; break;
+ case AnimationTreePlayer::NODE_ANIMATION: break;
+ case AnimationTreePlayer::NODE_ONESHOT: text=(i==0?"in":"add"); break;
+ case AnimationTreePlayer::NODE_BLEND2:
+ case AnimationTreePlayer::NODE_MIX: text=(i==0?"a":"b"); break;
+ case AnimationTreePlayer::NODE_BLEND3:
+ switch(i) {
+ case 0: text="b-"; break;
+ case 1: text="a"; break;
+ case 2: text="b+"; break;
+
+ }
+ break;
+
+
+ case AnimationTreePlayer::NODE_BLEND4:
+ switch(i) {
+ case 0: text="a0"; break;
+ case 1: text="b0"; break;
+ case 2: text="a1"; break;
+ case 3: text="b1"; break;
+ }
+ break;
+
+ case AnimationTreePlayer::NODE_TRANSITION:
+ text=itos(i);
+ if (anim_tree->transition_node_has_input_auto_advance(p_node,i))
+ text+="->";
+
+ break;
+ default: {}
+ }
+ font->draw(ci,ofs+ascofs+Point2(3,0),text,font_color);
+
+ ofs.y+=h;
+ }
+ } else {
+ ofs.y+=h;
+ }
+
+ Ref<StyleBox> pg_bg=get_stylebox("bg","ProgressBar");
+ Ref<StyleBox> pg_fill=get_stylebox("fill","ProgressBar");
+ Rect2 pg_rect(ofs,Size2(w,h));
+
+ bool editable=true;
+ switch(type) {
+ case AnimationTreePlayer::NODE_ANIMATION: {
+
+ Ref<Animation> anim = anim_tree->animation_node_get_animation(p_node);
+ String text;
+ if (anim_tree->animation_node_get_master_animation(p_node)!="")
+ text=anim_tree->animation_node_get_master_animation(p_node);
+ else if (anim.is_null())
+ text="load..";
+ else
+ text=anim->get_name();
+
+ font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,text,font_color_title);
+
+ } break;
+ case AnimationTreePlayer::NODE_ONESHOT:
+ case AnimationTreePlayer::NODE_MIX:
+ case AnimationTreePlayer::NODE_BLEND2:
+ case AnimationTreePlayer::NODE_BLEND3:
+ case AnimationTreePlayer::NODE_BLEND4:
+ case AnimationTreePlayer::NODE_TIMESCALE:
+ case AnimationTreePlayer::NODE_TRANSITION: {
+
+ font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,"edit..",font_color_title);
+ } break;
+ default: editable=false;
+ }
+
+ if (editable) {
+
+ Ref<Texture> arrow = get_icon("arrow","Tree");
+ Point2 arrow_ofs( w-arrow->get_width(),Math::floor( (h-arrow->get_height())/2) );
+ arrow->draw(ci,ofs+arrow_ofs);
+ }
+}
+
+#if 0
+void AnimationTreeEditor::_node_param_changed() {
+
+ //anim_tree->node_set_param( click_node,property_editor->get_variant() );
+ //update();
+ //_write_anim_tree_graph();
+}
+#endif
+
+AnimationTreeEditor::ClickType AnimationTreeEditor::_locate_click(const Point2& p_click,StringName *p_node_id,int *p_slot_index) const {
+
+
+ Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
+ Ref<Font> font = get_font("font","PopupMenu");
+
+ float h = (font->get_height()+get_constant("vseparation","PopupMenu"));
+
+ for(const List<StringName>::Element *E=order.back();E;E=E->prev()) {
+
+ StringName node = E->get();
+
+ AnimationTreePlayer::NodeType type=anim_tree->node_get_type(node);
+
+ Point2 pos = anim_tree->node_get_pos(node);
+ Size2 size = get_node_size(node);
+
+ pos-=Point2(h_scroll->get_value(),v_scroll->get_value());
+
+ if (!Rect2(pos,size).has_point(p_click))
+ continue;
+
+ if (p_node_id)
+ *p_node_id=node;
+
+ pos=p_click-pos;
+
+ float y = pos.y-style->get_offset().height;
+
+ if (y<2*h)
+ return CLICK_NODE;
+ y-=2*h;
+
+ int inputs = anim_tree->node_get_input_count(node);
+ int count = MAX(inputs,1);
+
+ if (inputs==0 || (pos.x > size.width/2 && type != AnimationTreePlayer::NODE_OUTPUT)) {
+
+ if (y<count*h) {
+
+ if (p_slot_index)
+ *p_slot_index=0;
+ return CLICK_OUTPUT_SLOT;
+ }
+ }
+
+ for(int i=0;i<count;i++) {
+
+ if (y<h) {
+ if (p_slot_index)
+ *p_slot_index=i;
+ return CLICK_INPUT_SLOT;
+ }
+ y-=h;
+ }
+
+ bool has_parameters = type!=AnimationTreePlayer::NODE_OUTPUT && type!=AnimationTreePlayer::NODE_TIMESEEK;
+ return has_parameters ? CLICK_PARAMETER : CLICK_NODE;
+ }
+
+ return CLICK_NONE;
+}
+
+Point2 AnimationTreeEditor::_get_slot_pos(const StringName& p_node,bool p_input,int p_slot) {
+
+ Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
+ Ref<Font> font = get_font("font","PopupMenu");
+ Ref<Texture> slot_icon = get_icon("NodeRealSlot","EditorIcons");
+
+ Size2 size=get_node_size(p_node);
+ Point2 pos = anim_tree->node_get_pos(p_node);
+
+ if (click_type==CLICK_NODE && click_node==p_node) {
+
+ pos+=click_motion-click_pos;
+ if (pos.x<5)
+ pos.x=5;
+ if (pos.y<5)
+ pos.y=5;
+
+ }
+
+ pos-=Point2(h_scroll->get_value(),v_scroll->get_value());
+
+
+ float w = size.width-style->get_minimum_size().width;
+ float h = font->get_height()+get_constant("vseparation","PopupMenu");
+
+
+ pos+=style->get_offset();
+
+ pos.y+=h*2;
+
+ pos.y+=h*p_slot;
+
+ pos+=Point2( -slot_icon->get_width()/2.0, h/2.0).floor();
+
+ if(!p_input) {
+ pos.x+=w+slot_icon->get_width();
+
+ }
+
+ return pos;
+
+}
+
+#if 0
+void AnimationTreeEditor::_node_edit_property(const StringName& p_node) {
+
+ Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
+ Size2 size = get_node_size(p_node);
+ Point2 pos = Point2( anim_tree->node_get_pos_x(p_node), anim_tree->node_get_pos_y(p_node) )-offset;
+
+ VisualServer::AnimationTreeNodeType type=anim_tree->node_get_type(p_node);
+
+ PropertyInfo ph = VisualServer::get_singleton()->anim_tree_node_get_type_info(type);
+ if (ph.type==Variant::NIL)
+ return;
+ if (ph.type==Variant::_RID)
+ ph.type=Variant::RESOURCE;
+
+ property_editor->edit(NULL,ph.name,ph.type,anim_tree->node_get_param(p_node),ph.hint,ph.hint_string);
+
+ Point2 popup_pos=Point2( pos.x+(size.width-property_editor->get_size().width)/2.0,pos.y+(size.y-style->get_margin(MARGIN_BOTTOM))).floor();
+ popup_pos+=get_global_pos();
+ property_editor->set_pos(popup_pos);
+
+ property_editor->popup();
+
+}
+#endif
+
+void AnimationTreeEditor::_gui_input(InputEvent p_event) {
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ if (p_event.mouse_button.pressed) {
+
+
+ if (p_event.mouse_button.button_index==1) {
+ click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
+ click_motion=click_pos;
+ click_type = _locate_click(click_pos,&click_node,&click_slot);
+ if( click_type!=CLICK_NONE) {
+
+ order.erase(click_node);
+ order.push_back(click_node);
+ update();
+ }
+
+ switch(click_type) {
+ case CLICK_INPUT_SLOT: {
+ click_pos=_get_slot_pos(click_node,true,click_slot);
+ } break;
+ case CLICK_OUTPUT_SLOT: {
+ click_pos=_get_slot_pos(click_node,false,click_slot);
+ } break;
+ case CLICK_PARAMETER: {
+
+ edited_node=click_node;
+ renaming_edit=false;
+ _popup_edit_dialog();
+ //open editor
+ //_node_edit_property(click_node);
+ } break;
+ default:{}
+ }
+ }
+ if (p_event.mouse_button.button_index==2) {
+
+ if (click_type!=CLICK_NONE) {
+ click_type=CLICK_NONE;
+ update();
+ } else {
+ // try to disconnect/remove
+
+ Point2 rclick_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
+ rclick_type = _locate_click(rclick_pos,&rclick_node,&rclick_slot);
+ if (rclick_type==CLICK_INPUT_SLOT || rclick_type==CLICK_OUTPUT_SLOT) {
+
+ node_popup->clear();
+ node_popup->add_item(TTR("Disconnect"),NODE_DISCONNECT);
+ if (anim_tree->node_get_type(rclick_node)==AnimationTreePlayer::NODE_TRANSITION) {
+ node_popup->add_item(TTR("Add Input"),NODE_ADD_INPUT);
+ if (rclick_type==CLICK_INPUT_SLOT) {
+ if (anim_tree->transition_node_has_input_auto_advance(rclick_node,rclick_slot))
+ node_popup->add_item(TTR("Clear Auto-Advance"),NODE_CLEAR_AUTOADVANCE);
+ else
+ node_popup->add_item(TTR("Set Auto-Advance"),NODE_SET_AUTOADVANCE);
+ node_popup->add_item(TTR("Delete Input"),NODE_DELETE_INPUT);
+
+ }
+ }
+
+ node_popup->set_pos(rclick_pos+get_global_pos());
+ node_popup->popup();
+
+ }
+
+ if (rclick_type==CLICK_NODE) {
+ node_popup->clear();
+ node_popup->add_item(TTR("Rename"),NODE_RENAME);
+ node_popup->add_item(TTR("Remove"),NODE_ERASE);
+ if (anim_tree->node_get_type(rclick_node)==AnimationTreePlayer::NODE_TRANSITION)
+ node_popup->add_item(TTR("Add Input"),NODE_ADD_INPUT);
+ node_popup->set_pos(rclick_pos+get_global_pos());
+ node_popup->popup();
+ }
+
+
+ }
+ }
+ } else {
+
+ if (p_event.mouse_button.button_index==1 && click_type!=CLICK_NONE) {
+
+ switch(click_type) {
+ case CLICK_INPUT_SLOT:
+ case CLICK_OUTPUT_SLOT: {
+
+ Point2 dst_click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
+ StringName id;
+ int slot;
+ ClickType dst_click_type = _locate_click(dst_click_pos,&id,&slot);
+
+ if (dst_click_type==CLICK_INPUT_SLOT && click_type==CLICK_OUTPUT_SLOT) {
+
+ anim_tree->connect_nodes(click_node,id,slot);
+
+ }
+ if (click_type==CLICK_INPUT_SLOT && dst_click_type==CLICK_OUTPUT_SLOT) {
+
+ anim_tree->connect_nodes(id,click_node,click_slot);
+ }
+
+ } break;
+ case CLICK_NODE: {
+ Point2 new_pos = anim_tree->node_get_pos(click_node)+(click_motion-click_pos);
+ if (new_pos.x<5)
+ new_pos.x=5;
+ if (new_pos.y<5)
+ new_pos.y=5;
+ anim_tree->node_set_pos(click_node,new_pos);
+
+ } break;
+ default: {}
+ }
+
+ click_type=CLICK_NONE;
+ update();
+ }
+ }
+ }
+
+ case InputEvent::MOUSE_MOTION: {
+
+ if (p_event.mouse_motion.button_mask&1 && click_type!=CLICK_NONE) {
+
+ click_motion=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
+ update();
+ }
+ if ((p_event.mouse_motion.button_mask&4 || Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+
+ h_scroll->set_value( h_scroll->get_value() - p_event.mouse_motion.relative_x );
+ v_scroll->set_value( v_scroll->get_value() - p_event.mouse_motion.relative_y );
+ update();
+ }
+
+ } break;
+ }
+
+}
+
+
+void AnimationTreeEditor::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) {
+
+ static const int steps = 20;
+
+ Rect2 r;
+ r.pos=p_from;
+ r.expand_to(p_to);
+ Vector2 sign=Vector2((p_from.x < p_to.x) ? 1 : -1,(p_from.y < p_to.y) ? 1 : -1);
+ bool flip = sign.x * sign.y < 0;
+
+ Vector2 prev;
+ for(int i=0;i<=steps;i++) {
+
+ float d = i/float(steps);
+ float c=-Math::cos(d*Math_PI) * 0.5+0.5;
+ if (flip)
+ c=1.0-c;
+ Vector2 p = r.pos+Vector2(d*r.size.width,c*r.size.height);
+
+ if (i>0) {
+
+ draw_line(prev,p,p_color,2);
+ }
+
+ prev=p;
+ }
+}
+
+void AnimationTreeEditor::_notification(int p_what) {
+
+
+ switch(p_what) {
+
+ case NOTIFICATION_ENTER_TREE: {
+
+ play_button->set_icon( get_icon("Play","EditorIcons") );
+ add_menu->set_icon( get_icon("Add","EditorIcons") );
+ } break;
+ case NOTIFICATION_DRAW: {
+
+
+ _update_scrollbars();
+ //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1));
+ get_stylebox("bg","Tree")->draw(get_canvas_item(),Rect2(Point2(),get_size()));
+
+ for(List<StringName>::Element *E=order.front();E;E=E->next()) {
+
+ _draw_node(E->get());
+ }
+
+ if (click_type==CLICK_INPUT_SLOT || click_type==CLICK_OUTPUT_SLOT) {
+
+ _draw_cos_line(click_pos,click_motion,Color(0.5,1,0.5,0.8));
+ }
+
+ List<AnimationTreePlayer::Connection> connections;
+ anim_tree->get_connection_list(&connections);
+
+ for(List<AnimationTreePlayer::Connection>::Element *E=connections.front();E;E=E->next()) {
+
+ const AnimationTreePlayer::Connection &c=E->get();
+ Point2 source = _get_slot_pos(c.src_node,false,0);
+ Point2 dest = _get_slot_pos(c.dst_node,true,c.dst_input);
+ Color col = Color(1,1,0.5,0.8);
+/*
+ if (click_type==CLICK_NODE && click_node==c.src_node) {
+
+ source+=click_motion-click_pos;
+ }
+
+ if (click_type==CLICK_NODE && click_node==c.dst_node) {
+
+ dest+=click_motion-click_pos;
+ }*/
+
+ _draw_cos_line(source,dest,col);
+
+ }
+
+ switch(anim_tree->get_last_error()) {
+
+ case AnimationTreePlayer::CONNECT_OK: {
+
+ Ref<Font> f = get_font("font","Label");
+ f->draw(get_canvas_item(),Point2(5,25+f->get_ascent()),TTR("Animation tree is valid."),Color(0,1,0.6,0.8));
+ } break;
+ default: {
+
+ Ref<Font> f = get_font("font","Label");
+ f->draw(get_canvas_item(),Point2(5,25+f->get_ascent()),TTR("Animation tree is invalid."),Color(1,0.6,0.0,0.8));
+ } break;
+ }
+
+ } break;
+ }
+
+}
+
+void AnimationTreeEditor::_update_scrollbars() {
+
+ Size2 size = get_size();
+ Size2 hmin = h_scroll->get_combined_minimum_size();
+ Size2 vmin = v_scroll->get_combined_minimum_size();
+
+ v_scroll->set_begin( Point2(size.width - vmin.width, 0) );
+ v_scroll->set_end( Point2(size.width, size.height) );
+
+ h_scroll->set_begin( Point2( 0, size.height - hmin.height) );
+ h_scroll->set_end( Point2(size.width-vmin.width, size.height) );
+
+
+ Size2 min = _get_maximum_size();
+
+ if (min.height < size.height - hmin.height) {
+
+ v_scroll->hide();
+ offset.y=0;
+ } else {
+
+ v_scroll->show();
+ v_scroll->set_max(min.height);
+ v_scroll->set_page(size.height - hmin.height);
+ offset.y=v_scroll->get_value();
+ }
+
+ if (min.width < size.width - vmin.width) {
+
+ h_scroll->hide();
+ offset.x=0;
+ } else {
+
+ h_scroll->show();
+ h_scroll->set_max(min.width);
+ h_scroll->set_page(size.width - vmin.width);
+ offset.x=h_scroll->get_value();
+ }
+}
+
+void AnimationTreeEditor::_scroll_moved(float) {
+
+ offset.x=h_scroll->get_value();
+ offset.y=v_scroll->get_value();
+ update();
+}
+
+
+void AnimationTreeEditor::_node_menu_item(int p_item) {
+
+ switch(p_item) {
+
+ case NODE_DISCONNECT: {
+
+ if (rclick_type==CLICK_INPUT_SLOT) {
+
+ anim_tree->disconnect_nodes(rclick_node,rclick_slot);
+ update();
+ }
+
+ if (rclick_type==CLICK_OUTPUT_SLOT) {
+
+
+ List<AnimationTreePlayer::Connection> connections;
+ anim_tree->get_connection_list(&connections);
+
+ for(List<AnimationTreePlayer::Connection>::Element *E=connections.front();E;E=E->next()) {
+
+ const AnimationTreePlayer::Connection &c=E->get();
+ if( c.dst_node==rclick_node) {
+
+ anim_tree->disconnect_nodes(c.dst_node,c.dst_input);
+ }
+ }
+ update();
+ }
+
+ } break;
+ case NODE_RENAME: {
+
+ renaming_edit=true;
+ edited_node=rclick_node;
+ _popup_edit_dialog();
+
+ } break;
+ case NODE_ADD_INPUT: {
+
+ anim_tree->transition_node_set_input_count(rclick_node, anim_tree->transition_node_get_input_count(rclick_node)+1);
+ update();
+ } break;
+ case NODE_DELETE_INPUT: {
+
+ anim_tree->transition_node_delete_input(rclick_node, rclick_slot);
+ update();
+ } break;
+ case NODE_SET_AUTOADVANCE: {
+
+ anim_tree->transition_node_set_input_auto_advance(rclick_node,rclick_slot,true);
+ update();
+
+ } break;
+ case NODE_CLEAR_AUTOADVANCE: {
+
+ anim_tree->transition_node_set_input_auto_advance(rclick_node,rclick_slot,false);
+ update();
+
+ } break;
+
+ case NODE_ERASE: {
+
+ if (rclick_node=="out")
+ break;
+ order.erase(rclick_node);
+ anim_tree->remove_node(rclick_node);
+ update();
+ } break;
+ }
+}
+
+StringName AnimationTreeEditor::_add_node(int p_item) {
+
+ static const char* bname[] = {
+ "out",
+ "anim",
+ "oneshot",
+ "mix",
+ "blend2",
+ "blend3",
+ "blend4",
+ "scale",
+ "seek",
+ "transition"
+ };
+
+ String name;
+ int idx=1;
+
+ while(true) {
+
+ name = bname[p_item];
+ if (idx>1)
+ name+=" "+itos(idx);
+ if (anim_tree->node_exists(name))
+ idx++;
+ else
+ break;
+ }
+
+
+ anim_tree->add_node((AnimationTreePlayer::NodeType)p_item,name);
+ anim_tree->node_set_pos(name,Point2(last_x,last_y));
+ order.push_back(name);
+ last_x+=10;
+ last_y+=10;
+ last_x=last_x % (int)get_size().width;
+ last_y=last_y % (int)get_size().height;
+ update();
+
+ return name;
+};
+
+void AnimationTreeEditor::_file_dialog_selected(String p_path) {
+
+ switch (file_op) {
+
+ case MENU_IMPORT_ANIMATIONS: {
+ Vector<String> files = file_dialog->get_selected_files();
+
+ for (int i=0; i<files.size(); i++) {
+
+ StringName node = _add_node(AnimationTreePlayer::NODE_ANIMATION);
+
+ RES anim = ResourceLoader::load(files[i]);
+ anim_tree->animation_node_set_animation(node,anim);
+ //anim_tree->node_set_name(node, files[i].get_file());
+ };
+ } break;
+
+ default:
+ break;
+ };
+};
+
+void AnimationTreeEditor::_add_menu_item(int p_item) {
+
+ if (p_item==MENU_GRAPH_CLEAR) {
+
+ //clear
+ } else if (p_item == MENU_IMPORT_ANIMATIONS) {
+
+ file_op = MENU_IMPORT_ANIMATIONS;
+ file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_dialog->popup_centered_ratio();
+
+ } else {
+
+ _add_node(p_item);
+ }
+}
+
+Size2 AnimationTreeEditor::get_minimum_size() const {
+
+ return Size2(10,200);
+}
+
+void AnimationTreeEditor::_find_paths_for_filter(const StringName& p_node,Set<String>& paths) {
+
+ ERR_FAIL_COND( !anim_tree->node_exists(p_node) );
+
+ for(int i=0;i<anim_tree->node_get_input_count(p_node);i++) {
+
+ StringName port = anim_tree->node_get_input_source(p_node,i);
+ if (port==StringName())
+ continue;
+ _find_paths_for_filter(port,paths);
+ }
+
+ if (anim_tree->node_get_type(p_node)==AnimationTreePlayer::NODE_ANIMATION) {
+
+ Ref<Animation> anim = anim_tree->animation_node_get_animation(p_node);
+ if (anim.is_valid()) {
+
+ for(int i=0;i<anim->get_track_count();i++) {
+ paths.insert(anim->track_get_path(i));
+ }
+ }
+ }
+}
+
+
+void AnimationTreeEditor::_filter_edited() {
+
+
+ TreeItem *ed = filter->get_edited();
+ if (!ed)
+ return;
+
+ if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ONESHOT) {
+ anim_tree->oneshot_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0));
+ } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) {
+ anim_tree->blend2_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0));
+ } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ANIMATION) {
+ anim_tree->animation_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0));
+ }
+
+}
+
+void AnimationTreeEditor::_edit_filters() {
+
+ filter_dialog->popup_centered_ratio();
+ filter->clear();
+
+ Set<String> npb;
+ _find_paths_for_filter(edited_node,npb);
+
+ TreeItem *root = filter->create_item();
+ filter->set_hide_root(true);
+ Map<String,TreeItem*> pm;
+
+ Node *base = anim_tree->get_node( anim_tree->get_base_path() );
+
+ for(Set<String>::Element *E=npb.front();E;E=E->next()) {
+
+ TreeItem *parent=root;
+ String descr=E->get();
+ if (base) {
+ NodePath np = E->get();
+
+ if (np.get_property()!=StringName()) {
+ Node *n = base->get_node(np);
+ Skeleton *s = n->cast_to<Skeleton>();
+ if (s) {
+
+ String skelbase = E->get().substr(0,E->get().find(":"));
+
+
+ int bidx = s->find_bone(np.get_property());
+
+ if (bidx!=-1) {
+ int bparent = s->get_bone_parent(bidx);
+ //
+ if (bparent!=-1) {
+
+
+ String bpn = skelbase+":"+s->get_bone_name(bparent);
+ if (pm.has(bpn)) {
+ parent=pm[bpn];
+ descr=np.get_property();
+ }
+ } else {
+
+ if (pm.has(skelbase)) {
+ parent=pm[skelbase];
+
+ }
+ }
+ }
+ }
+ }
+ }
+
+ TreeItem *it = filter->create_item(parent);
+ it->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ it->set_text(0,descr);
+ it->set_metadata(0,NodePath(E->get()));
+ it->set_editable(0,true);
+ if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ONESHOT) {
+ it->set_checked(0, anim_tree->oneshot_node_is_path_filtered(edited_node,E->get()));
+ } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) {
+ it->set_checked(0, anim_tree->blend2_node_is_path_filtered(edited_node,E->get()));
+ } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ANIMATION) {
+ it->set_checked(0, anim_tree->animation_node_is_path_filtered(edited_node,E->get()));
+ }
+ pm[E->get()]=it;
+ }
+
+
+}
+
+void AnimationTreeEditor::_bind_methods() {
+
+ ClassDB::bind_method( "_add_menu_item", &AnimationTreeEditor::_add_menu_item );
+ ClassDB::bind_method( "_node_menu_item", &AnimationTreeEditor::_node_menu_item );
+ ClassDB::bind_method( "_gui_input", &AnimationTreeEditor::_gui_input );
+ //ClassDB::bind_method( "_node_param_changed", &AnimationTreeEditor::_node_param_changed );
+ ClassDB::bind_method( "_scroll_moved", &AnimationTreeEditor::_scroll_moved );
+ ClassDB::bind_method( "_edit_dialog_changeds", &AnimationTreeEditor::_edit_dialog_changeds );
+ ClassDB::bind_method( "_edit_dialog_changede", &AnimationTreeEditor::_edit_dialog_changede );
+ ClassDB::bind_method( "_edit_dialog_changedf", &AnimationTreeEditor::_edit_dialog_changedf );
+ ClassDB::bind_method( "_edit_dialog_changed", &AnimationTreeEditor::_edit_dialog_changed );
+ ClassDB::bind_method( "_edit_dialog_animation_changed", &AnimationTreeEditor::_edit_dialog_animation_changed );
+ ClassDB::bind_method( "_edit_dialog_edit_animation", &AnimationTreeEditor::_edit_dialog_edit_animation );
+ ClassDB::bind_method( "_play_toggled", &AnimationTreeEditor::_play_toggled );
+ ClassDB::bind_method( "_edit_oneshot_start", &AnimationTreeEditor::_edit_oneshot_start );
+ ClassDB::bind_method( "_file_dialog_selected", &AnimationTreeEditor::_file_dialog_selected);
+ ClassDB::bind_method( "_master_anim_menu_item", &AnimationTreeEditor::_master_anim_menu_item);
+ ClassDB::bind_method( "_edit_filters", &AnimationTreeEditor::_edit_filters);
+ ClassDB::bind_method( "_filter_edited", &AnimationTreeEditor::_filter_edited);
+
+}
+
+AnimationTreeEditor::AnimationTreeEditor() {
+
+ set_focus_mode(FOCUS_ALL);
+
+ PopupMenu *p;
+ List<PropertyInfo> defaults;
+
+ add_menu = memnew( MenuButton );
+ //add_menu->set_
+ add_menu->set_pos( Point2( 0,0) );
+ add_menu->set_size( Point2( 25,15) );
+ add_child( add_menu );
+
+ p=add_menu->get_popup();
+ p->add_item(TTR("Animation Node"),AnimationTreePlayer::NODE_ANIMATION);
+ p->add_item(TTR("OneShot Node"),AnimationTreePlayer::NODE_ONESHOT);
+ p->add_item(TTR("Mix Node"),AnimationTreePlayer::NODE_MIX);
+ p->add_item(TTR("Blend2 Node"),AnimationTreePlayer::NODE_BLEND2);
+ p->add_item(TTR("Blend3 Node"),AnimationTreePlayer::NODE_BLEND3);
+ p->add_item(TTR("Blend4 Node"),AnimationTreePlayer::NODE_BLEND4);
+ p->add_item(TTR("TimeScale Node"),AnimationTreePlayer::NODE_TIMESCALE);
+ p->add_item(TTR("TimeSeek Node"),AnimationTreePlayer::NODE_TIMESEEK);
+ p->add_item(TTR("Transition Node"),AnimationTreePlayer::NODE_TRANSITION);
+ p->add_separator();
+ p->add_item(TTR("Import Animations.."), MENU_IMPORT_ANIMATIONS); // wtf
+ p->add_separator();
+ p->add_item(TTR("Clear"),MENU_GRAPH_CLEAR);
+
+ p->connect("id_pressed", this,"_add_menu_item");
+
+ play_button = memnew(Button);
+ play_button->set_pos(Point2(25,0));
+ play_button->set_size(Point2(25,15));
+ add_child(play_button);
+ play_button->set_toggle_mode(true);
+ play_button->connect("pressed", this,"_play_toggled");
+
+
+
+
+
+ last_x=50;
+ last_y=50;
+
+ property_editor = memnew( CustomPropertyEditor );
+ add_child(property_editor);
+ property_editor->connect("variant_changed", this,"_edit_dialog_animation_changed");
+ property_editor->connect("resource_edit_request", this, "_edit_dialog_edit_animation");
+
+ h_scroll = memnew( HScrollBar );
+ v_scroll = memnew( VScrollBar );
+
+ add_child(h_scroll);
+ add_child(v_scroll);
+
+ h_scroll->connect("value_changed", this,"_scroll_moved");
+ v_scroll->connect("value_changed", this,"_scroll_moved");
+
+ node_popup= memnew(PopupMenu );
+ add_child(node_popup);
+ node_popup->set_as_toplevel(true);
+
+ master_anim_popup = memnew( PopupMenu );
+ add_child(master_anim_popup);
+ master_anim_popup->connect("id_pressed",this,"_master_anim_menu_item");
+
+
+ node_popup->connect("id_pressed", this,"_node_menu_item");
+
+ updating_edit=false;
+
+ edit_dialog = memnew( PopupPanel );
+ //edit_dialog->get_ok()->hide();
+ //edit_dialog->get_cancel()->hide();
+ add_child(edit_dialog);
+
+ edit_option = memnew( OptionButton );
+ edit_option->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ edit_option->set_margin(MARGIN_RIGHT, 10);
+ edit_dialog->add_child(edit_option);
+ edit_option->connect("item_selected", this,"_edit_dialog_changedf");
+ edit_option->hide();
+
+
+ for(int i=0;i<2;i++) {
+ edit_scroll[i] = memnew ( HSlider );
+ edit_scroll[i]->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ edit_scroll[i]->set_margin(MARGIN_RIGHT, 10);
+ edit_dialog->add_child(edit_scroll[i]);
+ edit_scroll[i]->hide();
+ edit_scroll[i]->connect("value_changed", this,"_edit_dialog_changedf");
+ }
+ for(int i=0;i<4;i++) {
+ edit_line[i] = memnew ( LineEdit );
+ edit_line[i]->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ edit_line[i]->set_margin(MARGIN_RIGHT, 10);
+ edit_dialog->add_child(edit_line[i]);
+ edit_line[i]->hide();
+ edit_line[i]->connect("text_changed", this,"_edit_dialog_changeds");
+ edit_line[i]->connect("text_entered", this,"_edit_dialog_changede");
+ edit_label[i] = memnew ( Label );
+ edit_dialog->add_child(edit_label[i]);
+ edit_label[i]->hide();
+ }
+
+ edit_button = memnew( Button );
+ edit_button->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ edit_button->set_margin(MARGIN_RIGHT, 10);
+ edit_dialog->add_child(edit_button);
+ edit_button->hide();
+ edit_button->connect("pressed", this,"_edit_oneshot_start");
+
+ edit_check = memnew( CheckButton );
+ edit_check->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ edit_check->set_margin(MARGIN_RIGHT, 10);
+ edit_dialog->add_child(edit_check);
+ edit_check->hide();
+ edit_check->connect("pressed", this,"_edit_dialog_changed");
+
+ file_dialog = memnew( EditorFileDialog );
+ file_dialog->set_enable_multiple_selection(true);
+ file_dialog->set_current_dir(GlobalConfig::get_singleton()->get_resource_path());
+ add_child(file_dialog);
+ file_dialog->connect("file_selected", this, "_file_dialog_selected");
+
+ filter_dialog = memnew( AcceptDialog );
+ filter_dialog->set_title(TTR("Edit Node Filters"));
+ add_child(filter_dialog);
+
+ filter = memnew( Tree );
+ filter_dialog->add_child(filter);
+ //filter_dialog->set_child_rect(filter);
+ filter->connect("item_edited",this,"_filter_edited");
+
+ filter_button = memnew( Button );
+ filter_button->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ filter_button->set_margin(MARGIN_RIGHT, 10);
+ edit_dialog->add_child(filter_button);
+ filter_button->hide();
+ filter_button->set_text(TTR("Filters.."));
+ filter_button->connect("pressed", this,"_edit_filters");
+
+ set_clip_contents(true);
+}
+
+
+void AnimationTreeEditorPlugin::edit(Object *p_object) {
+
+ anim_tree_editor->edit(p_object->cast_to<AnimationTreePlayer>());
+
+}
+
+bool AnimationTreeEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("AnimationTreePlayer");
+}
+
+void AnimationTreeEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ //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);
+ } else {
+
+ if (anim_tree_editor->is_visible_in_tree())
+ editor->hide_bottom_panel();
+ button->hide();
+ anim_tree_editor->set_fixed_process(false);
+ }
+}
+
+AnimationTreeEditorPlugin::AnimationTreeEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ anim_tree_editor = memnew( AnimationTreeEditor );
+ anim_tree_editor->set_custom_minimum_size(Size2(0,300));
+
+ button=editor->add_bottom_panel_item("AnimationTree",anim_tree_editor);
+ button->hide();
+
+
+
+}
+
+
+AnimationTreeEditorPlugin::~AnimationTreeEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h
new file mode 100644
index 0000000000..4e5fb871f1
--- /dev/null
+++ b/editor/plugins/animation_tree_editor_plugin.h
@@ -0,0 +1,194 @@
+/*************************************************************************/
+/* animation_tree_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 ANIMATION_TREE_EDITOR_PLUGIN_H
+#define ANIMATION_TREE_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/animation/animation_tree_player.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/button.h"
+#include "scene/gui/popup.h"
+#include "editor/property_editor.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class AnimationTreeEditor : public Control {
+
+ GDCLASS(AnimationTreeEditor, Control );
+
+ static const char* _node_type_names[];
+
+ enum ClickType {
+ CLICK_NONE,
+ CLICK_NAME,
+ CLICK_NODE,
+ CLICK_INPUT_SLOT,
+ CLICK_OUTPUT_SLOT,
+ CLICK_PARAMETER
+ };
+
+ enum {
+
+ MENU_GRAPH_CLEAR=100,
+ MENU_IMPORT_ANIMATIONS=101,
+ NODE_DISCONNECT,
+ NODE_RENAME,
+ NODE_ERASE,
+ NODE_ADD_INPUT,
+ NODE_DELETE_INPUT,
+ NODE_SET_AUTOADVANCE,
+ NODE_CLEAR_AUTOADVANCE
+ };
+
+ bool renaming_edit;
+ StringName edited_node;
+ bool updating_edit;
+ Popup *edit_dialog;
+ HSlider *edit_scroll[2];
+ LineEdit *edit_line[4];
+ OptionButton *edit_option;
+ Label *edit_label[4];
+ Button *edit_button;
+ Button *filter_button;
+ CheckButton *edit_check;
+ EditorFileDialog* file_dialog;
+ int file_op;
+
+ void _popup_edit_dialog();
+
+
+ void _setup_edit_dialog(const StringName& p_node);
+ PopupMenu *master_anim_popup;
+ PopupMenu *node_popup;
+ PopupMenu *add_popup;
+ HScrollBar *h_scroll;
+ VScrollBar *v_scroll;
+ MenuButton* add_menu;
+
+ CustomPropertyEditor *property_editor;
+
+ AnimationTreePlayer* anim_tree;
+ List<StringName> order;
+ Set<StringName> active_nodes;
+
+ int last_x,last_y;
+
+ Point2 offset;
+ ClickType click_type;
+ Point2 click_pos;
+ StringName click_node;
+ int click_slot;
+ Point2 click_motion;
+ ClickType rclick_type;
+ StringName rclick_node;
+ int rclick_slot;
+
+ Button *play_button;
+
+ Size2 _get_maximum_size();
+ Size2 get_node_size(const StringName &p_node) const;
+ void _draw_node(const StringName& p_node);
+
+ AcceptDialog *filter_dialog;
+ Tree *filter;
+
+
+
+ void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color);
+ void _update_scrollbars();
+ void _scroll_moved(float);
+ void _play_toggled();
+/*
+ void _node_param_changed();
+ void _node_add_callback();
+ void _node_add(VisualServer::AnimationTreeNodeType p_type);
+ void _node_edit_property(const StringName& p_node);
+*/
+
+ void _master_anim_menu_item(int p_item);
+ void _node_menu_item(int p_item);
+ void _add_menu_item(int p_item);
+
+
+ void _filter_edited();
+ void _find_paths_for_filter(const StringName& p_node,Set<String>& paths);
+ void _edit_filters();
+
+
+ void _edit_oneshot_start();
+ void _edit_dialog_animation_changed();
+ void _edit_dialog_edit_animation();
+ void _edit_dialog_changeds(String);
+ void _edit_dialog_changede(String);
+ void _edit_dialog_changedf(float);
+ void _edit_dialog_changed();
+ void _dialog_changed() const;
+ ClickType _locate_click(const Point2& p_click,StringName *p_node_id,int *p_slot_index) const;
+ Point2 _get_slot_pos(const StringName& p_node_id,bool p_input,int p_slot);
+
+ StringName _add_node(int p_item);
+ void _file_dialog_selected(String p_path);
+
+
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+
+ virtual Size2 get_minimum_size() const;
+ void edit(AnimationTreePlayer *p_player);
+ AnimationTreeEditor();
+};
+
+class AnimationTreeEditorPlugin : public EditorPlugin {
+
+ GDCLASS( AnimationTreeEditorPlugin, EditorPlugin );
+
+ AnimationTreeEditor *anim_tree_editor;
+ EditorNode *editor;
+ Button *button;
+
+public:
+
+ virtual String get_name() const { return "AnimTree"; }
+ 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);
+
+ AnimationTreeEditorPlugin(EditorNode *p_node);
+ ~AnimationTreeEditorPlugin();
+
+};
+
+#endif // ANIMATION_TREE_EDITOR_PLUGIN_H
diff --git a/editor/plugins/baked_light_baker.cpp b/editor/plugins/baked_light_baker.cpp
new file mode 100644
index 0000000000..e491fe012e
--- /dev/null
+++ b/editor/plugins/baked_light_baker.cpp
@@ -0,0 +1,2731 @@
+/*************************************************************************/
+/* baked_light_baker.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "baked_light_baker.h"
+
+#include <stdlib.h>
+#include <cmath>
+#include "io/marshalls.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+
+#if 0
+void baked_light_baker_add_64f(double *dst,double value);
+void baked_light_baker_add_64i(int64_t *dst,int64_t value);
+
+//-separar en 2 testuras?
+//*mejorar performance y threads
+//*modos lineales
+//*saturacion
+
+_FORCE_INLINE_ static uint64_t get_uv_normal_bit(const Vector3& p_vector) {
+
+ int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*6.0/Math_PI+0.5));
+
+ if (lat==0) {
+ return 60;
+ } else if (lat==6) {
+ return 61;
+ }
+
+ int lon = Math::fast_ftoi(Math::floor( (Math_PI+Math::atan2(p_vector.x,p_vector.z))*12.0/(Math_PI*2.0) + 0.5))%12;
+
+ return lon+(lat-1)*12;
+}
+
+
+
+_FORCE_INLINE_ static Vector3 get_bit_normal(int p_bit) {
+
+ if (p_bit==61) {
+ return Vector3(0,1,0);
+ } else if (p_bit==62){
+ return Vector3(0,-1,0);
+ }
+
+ float latang = ((p_bit / 12)+1)*Math_PI/6.0;
+
+ Vector2 latv(Math::sin(latang),Math::cos(latang));
+
+ float lonang = ((p_bit%12)*Math_PI*2.0/12.0)-Math_PI;
+
+ Vector2 lonv(Math::sin(lonang),Math::cos(lonang));
+
+ return Vector3(lonv.x*latv.x,latv.y,lonv.y*latv.x).normalized();
+
+}
+
+
+BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>& p_tex) {
+
+ if (!tex_map.has(p_tex)) {
+
+ Ref<ImageTexture> imgtex=p_tex;
+ if (imgtex.is_null())
+ return NULL;
+ Image image=imgtex->get_data();
+ if (image.empty())
+ return NULL;
+
+ if (image.get_format()!=Image::FORMAT_RGBA8) {
+ if (image.get_format()>Image::FORMAT_INDEXED_ALPHA) {
+ Error err = image.decompress();
+ if (err)
+ return NULL;
+ }
+
+ if (image.get_format()!=Image::FORMAT_RGBA8)
+ image.convert(Image::FORMAT_RGBA8);
+ }
+
+ if (imgtex->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR) {
+ Image copy = image;
+ copy.srgb_to_linear();
+ image=copy;
+ }
+
+ PoolVector<uint8_t> dvt=image.get_data();
+ PoolVector<uint8_t>::Read r=dvt.read();
+ MeshTexture mt;
+ mt.tex_w=image.get_width();
+ mt.tex_h=image.get_height();
+ int len = image.get_width()*image.get_height()*4;
+ mt.tex.resize(len);
+ copymem(mt.tex.ptr(),r.ptr(),len);
+
+ textures.push_back(mt);
+ tex_map[p_tex]=&textures.back()->get();
+ }
+
+ return tex_map[p_tex];
+}
+
+
+void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform,int p_baked_texture) {
+
+
+ for(int i=0;i<p_mesh->get_surface_count();i++) {
+
+ if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES)
+ continue;
+ Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i);
+
+ MeshMaterial *matptr=NULL;
+ int baked_tex=p_baked_texture;
+
+ if (mat.is_valid()) {
+
+ if (!mat_map.has(mat)) {
+
+ MeshMaterial mm;
+
+ Ref<FixedSpatialMaterial> fm = mat;
+ if (fm.is_valid()) {
+ //fixed route
+ mm.diffuse.color=fm->get_parameter(FixedSpatialMaterial::PARAM_DIFFUSE);
+ if (linear_color)
+ mm.diffuse.color=mm.diffuse.color.to_linear();
+ mm.diffuse.tex=_get_mat_tex(fm->get_texture(FixedSpatialMaterial::PARAM_DIFFUSE));
+ mm.specular.color=fm->get_parameter(FixedSpatialMaterial::PARAM_SPECULAR);
+ if (linear_color)
+ mm.specular.color=mm.specular.color.to_linear();
+
+ mm.specular.tex=_get_mat_tex(fm->get_texture(FixedSpatialMaterial::PARAM_SPECULAR));
+ } else {
+
+ mm.diffuse.color=Color(1,1,1,1);
+ mm.diffuse.tex=NULL;
+ mm.specular.color=Color(0,0,0,1);
+ mm.specular.tex=NULL;
+ }
+
+ materials.push_back(mm);
+ mat_map[mat]=&materials.back()->get();
+
+ }
+
+ matptr=mat_map[mat];
+
+ }
+
+
+ int facecount=0;
+
+
+ if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) {
+
+ facecount=p_mesh->surface_get_array_index_len(i);
+ } else {
+
+ facecount=p_mesh->surface_get_array_len(i);
+ }
+
+ ERR_CONTINUE((facecount==0 || (facecount%3)!=0));
+
+ facecount/=3;
+
+ int tbase=triangles.size();
+ triangles.resize(facecount+tbase);
+
+
+ Array a = p_mesh->surface_get_arrays(i);
+
+ PoolVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
+ PoolVector<Vector3>::Read vr=vertices.read();
+ PoolVector<Vector2> uv;
+ PoolVector<Vector2>::Read uvr;
+ PoolVector<Vector2> uv2;
+ PoolVector<Vector2>::Read uv2r;
+ PoolVector<Vector3> normal;
+ PoolVector<Vector3>::Read normalr;
+ bool read_uv=false;
+ bool read_normal=false;
+
+ if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV) {
+
+ uv=a[Mesh::ARRAY_TEX_UV];
+ uvr=uv.read();
+ read_uv=true;
+
+ if (mat.is_valid() && mat->get_flag(Material::FLAG_LIGHTMAP_ON_UV2) && p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
+
+ uv2=a[Mesh::ARRAY_TEX_UV2];
+ uv2r=uv2.read();
+
+ } else {
+ uv2r=uv.read();
+ if (baked_light->get_transfer_lightmaps_only_to_uv2()) {
+ baked_tex=-1;
+ }
+ }
+ }
+
+ if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_NORMAL) {
+
+ normal=a[Mesh::ARRAY_NORMAL];
+ normalr=normal.read();
+ read_normal=true;
+ }
+
+ Matrix3 normal_xform = p_xform.basis.inverse().transposed();
+
+
+ if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) {
+
+ PoolVector<int> indices = a[Mesh::ARRAY_INDEX];
+ PoolVector<int>::Read ir = indices.read();
+
+ for(int i=0;i<facecount;i++) {
+ Triangle &t=triangles[tbase+i];
+ t.vertices[0]=p_xform.xform(vr[ ir[i*3+0] ]);
+ t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]);
+ t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]);
+ t.material=matptr;
+ t.baked_texture=baked_tex;
+ if (read_uv) {
+
+ t.uvs[0]=uvr[ ir[i*3+0] ];
+ t.uvs[1]=uvr[ ir[i*3+1] ];
+ t.uvs[2]=uvr[ ir[i*3+2] ];
+
+ t.bake_uvs[0]=uv2r[ ir[i*3+0] ];
+ t.bake_uvs[1]=uv2r[ ir[i*3+1] ];
+ t.bake_uvs[2]=uv2r[ ir[i*3+2] ];
+ }
+ if (read_normal) {
+
+ t.normals[0]=normal_xform.xform(normalr[ ir[i*3+0] ]).normalized();
+ t.normals[1]=normal_xform.xform(normalr[ ir[i*3+1] ]).normalized();
+ t.normals[2]=normal_xform.xform(normalr[ ir[i*3+2] ]).normalized();
+ }
+ }
+
+ } else {
+
+ for(int i=0;i<facecount;i++) {
+ Triangle &t=triangles[tbase+i];
+ t.vertices[0]=p_xform.xform(vr[ i*3+0 ]);
+ t.vertices[1]=p_xform.xform(vr[ i*3+1 ]);
+ t.vertices[2]=p_xform.xform(vr[ i*3+2 ]);
+ t.material=matptr;
+ t.baked_texture=baked_tex;
+ if (read_uv) {
+
+ t.uvs[0]=uvr[ i*3+0 ];
+ t.uvs[1]=uvr[ i*3+1 ];
+ t.uvs[2]=uvr[ i*3+2 ];
+
+ t.bake_uvs[0]=uv2r[ i*3+0 ];
+ t.bake_uvs[1]=uv2r[ i*3+1 ];
+ t.bake_uvs[2]=uv2r[ i*3+2 ];
+
+ }
+ if (read_normal) {
+
+ t.normals[0]=normal_xform.xform(normalr[ i*3+0 ]).normalized();
+ t.normals[1]=normal_xform.xform(normalr[ i*3+1 ]).normalized();
+ t.normals[2]=normal_xform.xform(normalr[ i*3+2 ]).normalized();
+ }
+ }
+ }
+ }
+
+}
+
+
+void BakedLightBaker::_parse_geometry(Node* p_node) {
+
+ if (p_node->cast_to<MeshInstance>()) {
+
+ MeshInstance *meshi=p_node->cast_to<MeshInstance>();
+ Ref<Mesh> mesh=meshi->get_mesh();
+ if (mesh.is_valid()) {
+ _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform(),meshi->get_baked_light_texture_id());
+ }
+ } else if (p_node->cast_to<Light>()) {
+
+ Light *dl=p_node->cast_to<Light>();
+
+ if (dl->get_bake_mode()!=Light::BAKE_MODE_DISABLED) {
+
+
+ LightData dirl;
+ dirl.type=VS::LightType(dl->get_light_type());
+ dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE);
+ dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR);
+ if (linear_color)
+ dirl.diffuse=dirl.diffuse.to_linear();
+ if (linear_color)
+ dirl.specular=dirl.specular.to_linear();
+
+ dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY);
+ dirl.pos=dl->get_global_transform().origin;
+ dirl.up=dl->get_global_transform().basis.get_axis(1).normalized();
+ dirl.left=dl->get_global_transform().basis.get_axis(0).normalized();
+ dirl.dir=-dl->get_global_transform().basis.get_axis(2).normalized();
+ dirl.spot_angle=dl->get_parameter(DirectionalLight::PARAM_SPOT_ANGLE);
+ dirl.spot_attenuation=dl->get_parameter(DirectionalLight::PARAM_SPOT_ATTENUATION);
+ dirl.attenuation=dl->get_parameter(DirectionalLight::PARAM_ATTENUATION);
+ dirl.darkening=dl->get_parameter(DirectionalLight::PARAM_SHADOW_DARKENING);
+ dirl.radius=dl->get_parameter(DirectionalLight::PARAM_RADIUS);
+ dirl.bake_direct=dl->get_bake_mode()==Light::BAKE_MODE_FULL;
+ dirl.rays_thrown=0;
+ dirl.bake_shadow=dl->get_bake_mode()==Light::BAKE_MODE_INDIRECT_AND_SHADOWS;
+ lights.push_back(dirl);
+ }
+
+ } else if (p_node->cast_to<Spatial>()){
+
+ Spatial *sp = p_node->cast_to<Spatial>();
+
+ Array arr = p_node->call("_get_baked_light_meshes");
+ for(int i=0;i<arr.size();i+=2) {
+
+ Transform xform=arr[i];
+ Ref<Mesh> mesh=arr[i+1];
+ _add_mesh(mesh,Ref<Material>(),base_inv * (sp->get_global_transform() * xform));
+ }
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ _parse_geometry(p_node->get_child(i));
+ }
+}
+
+
+void BakedLightBaker::_fix_lights() {
+
+
+ total_light_area=0;
+ for(int i=0;i<lights.size();i++) {
+
+ LightData &dl=lights[i];
+
+ switch(dl.type) {
+ case VS::LIGHT_DIRECTIONAL: {
+
+ float up_max=-1e10;
+ float dir_max=-1e10;
+ float left_max=-1e10;
+ float up_min=1e10;
+ float dir_min=1e10;
+ float left_min=1e10;
+
+ for(int j=0;j<triangles.size();j++) {
+
+ for(int k=0;k<3;k++) {
+
+ Vector3 v = triangles[j].vertices[k];
+
+ float up_d = dl.up.dot(v);
+ float dir_d = dl.dir.dot(v);
+ float left_d = dl.left.dot(v);
+
+ if (up_d>up_max)
+ up_max=up_d;
+ if (up_d<up_min)
+ up_min=up_d;
+
+ if (left_d>left_max)
+ left_max=left_d;
+ if (left_d<left_min)
+ left_min=left_d;
+
+ if (dir_d>dir_max)
+ dir_max=dir_d;
+ if (dir_d<dir_min)
+ dir_min=dir_d;
+
+ }
+ }
+
+ //make a center point, then the upvector and leftvector
+ dl.pos = dl.left*( left_max+left_min )*0.5 + dl.up*( up_max+up_min )*0.5 + dl.dir*(dir_min-(dir_max-dir_min));
+ dl.left*=(left_max-left_min)*0.5;
+ dl.up*=(up_max-up_min)*0.5;
+ dl.length = (dir_max - dir_min)*10; //arbitrary number to keep it in scale
+ dl.area=dl.left.length()*2*dl.up.length()*2;
+ dl.constant=1.0/dl.area;
+ } break;
+ case VS::LIGHT_OMNI:
+ case VS::LIGHT_SPOT: {
+
+ dl.attenuation_table.resize(ATTENUATION_CURVE_LEN);
+ for(int j=0;j<ATTENUATION_CURVE_LEN;j++) {
+ dl.attenuation_table[j]=1.0-Math::pow(j/float(ATTENUATION_CURVE_LEN),dl.attenuation);
+ float falloff=j*dl.radius/float(ATTENUATION_CURVE_LEN);
+ if (falloff==0)
+ falloff=0.000001;
+ float intensity=4*Math_PI*(falloff*falloff);
+ //dl.attenuation_table[j]*=falloff*falloff;
+ dl.attenuation_table[j]*=1.0/(3.0/intensity);
+
+ }
+ if (dl.type==VS::LIGHT_OMNI) {
+
+ dl.area=4.0*Math_PI*pow(dl.radius,2.0f);
+ dl.constant=1.0/3.5;
+ } else {
+
+
+ float r = Math::tan(Math::deg2rad(dl.spot_angle))*dl.radius;
+ float c = 1.0-(Math::deg2rad(dl.spot_angle)*0.5+0.5);
+ dl.constant=1.0/3.5;
+ dl.constant*=1.0/c;
+
+ dl.area=Math_PI*r*r*c;
+ }
+
+ } break;
+
+
+ }
+
+ total_light_area+=dl.area;
+ }
+}
+
+BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size, int p_depth, int &max_depth) {
+
+ if (p_depth>max_depth) {
+ max_depth=p_depth;
+ }
+
+ if (p_size==1) {
+
+ return p_children[0];
+ } else if (p_size==0) {
+
+ return NULL;
+ }
+
+
+ AABB aabb;
+ aabb=p_children[0]->aabb;
+ for(int i=1;i<p_size;i++) {
+
+ aabb.merge_with(p_children[i]->aabb);
+ }
+
+ int li=aabb.get_longest_axis_index();
+
+ switch(li) {
+
+ case Vector3::AXIS_X: {
+ SortArray<BVH*,BVHCmpX> sort_x;
+ sort_x.nth_element(0,p_size,p_size/2,p_children);
+ //sort_x.sort(&p_bb[p_from],p_size);
+ } break;
+ case Vector3::AXIS_Y: {
+ SortArray<BVH*,BVHCmpY> sort_y;
+ sort_y.nth_element(0,p_size,p_size/2,p_children);
+ //sort_y.sort(&p_bb[p_from],p_size);
+ } break;
+ case Vector3::AXIS_Z: {
+ SortArray<BVH*,BVHCmpZ> sort_z;
+ sort_z.nth_element(0,p_size,p_size/2,p_children);
+ //sort_z.sort(&p_bb[p_from],p_size);
+
+ } break;
+ }
+
+
+ BVH* left = _parse_bvh(p_children,p_size/2,p_depth+1,max_depth);
+ BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth);
+
+ BVH *_new = memnew(BVH);
+ _new->aabb=aabb;
+ _new->center=aabb.pos+aabb.size*0.5;
+ _new->children[0]=left;
+ _new->children[1]=right;
+ _new->leaf=NULL;
+
+ return _new;
+}
+
+void BakedLightBaker::_make_bvh() {
+
+ Vector<BVH*> bases;
+ bases.resize(triangles.size());
+ int max_depth=0;
+ for(int i=0;i<triangles.size();i++) {
+ bases[i]=memnew( BVH );
+ bases[i]->leaf=&triangles[i];
+ bases[i]->aabb.pos=triangles[i].vertices[0];
+ bases[i]->aabb.expand_to(triangles[i].vertices[1]);
+ bases[i]->aabb.expand_to(triangles[i].vertices[2]);
+ triangles[i].aabb=bases[i]->aabb;
+ bases[i]->center=bases[i]->aabb.pos+bases[i]->aabb.size*0.5;
+ }
+
+ bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth);
+
+ ray_stack = memnew_arr(uint32_t,max_depth);
+ bvh_stack = memnew_arr(BVH*,max_depth);
+
+ bvh_depth = max_depth;
+}
+
+void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_depth) {
+
+
+
+
+ uint32_t *stack=octant_stack;
+ uint32_t *ptr_stack=octantptr_stack;
+ Octant *octants=octant_pool.ptr();
+
+ stack[0]=0;
+ ptr_stack[0]=0;
+
+ int stack_pos=0;
+
+
+ while(true) {
+
+ Octant *octant=&octants[ptr_stack[stack_pos]];
+ if (stack[stack_pos]<8) {
+
+ int i = stack[stack_pos];
+ stack[stack_pos]++;
+
+
+
+ //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001);
+
+ int child_idx =octant->children[i];
+ bool encloses;
+ if (!child_idx) {
+
+ AABB aabb=octant->aabb;
+ aabb.size*=0.5;
+ if (i&1)
+ aabb.pos.x+=aabb.size.x;
+ if (i&2)
+ aabb.pos.y+=aabb.size.y;
+ if (i&4)
+ aabb.pos.z+=aabb.size.z;
+
+ aabb.grow_by(cell_size*octree_extra_margin);
+ if (!aabb.intersects(p_triangle->aabb))
+ continue;
+ encloses=aabb.grow(cell_size*-octree_extra_margin*2.0).encloses(p_triangle->aabb);
+ if (!encloses && !Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb2(aabb))
+ continue;
+ } else {
+
+ Octant *child=&octants[child_idx];
+ AABB aabb=child->aabb;
+ aabb.grow_by(cell_size*octree_extra_margin);
+ if (!aabb.intersects(p_triangle->aabb))
+ continue;
+ encloses=aabb.grow(cell_size*-octree_extra_margin*2.0).encloses(p_triangle->aabb);
+ if (!encloses && !Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb2(aabb))
+ continue;
+
+ }
+
+ if (encloses)
+ stack[stack_pos]=8; // quick and dirty opt
+
+ if (!child_idx) {
+
+
+ if (octant_pool_size==octant_pool.size()) {
+ octant_pool.resize(octant_pool_size+OCTANT_POOL_CHUNK);
+ octants=octant_pool.ptr();
+ octant=&octants[ptr_stack[stack_pos]];
+ }
+ child_idx=octant_pool_size++;
+ octant->children[i]=child_idx;
+ Octant *child=&octants[child_idx];
+
+ child->aabb=octant->aabb;
+ child->texture_x=0;
+ child->texture_y=0;
+
+ child->aabb.size*=0.5;
+ if (i&1)
+ child->aabb.pos.x+=child->aabb.size.x;
+ if (i&2)
+ child->aabb.pos.y+=child->aabb.size.y;
+ if (i&4)
+ child->aabb.pos.z+=child->aabb.size.z;
+
+
+ child->full_accum[0]=0;
+ child->full_accum[1]=0;
+ child->full_accum[2]=0;
+ child->sampler_ofs=0;
+
+
+
+ if (stack_pos==octree_depth-1) {
+ child->leaf=true;
+ child->offset[0]=child->aabb.pos.x+child->aabb.size.x*0.5;
+ child->offset[1]=child->aabb.pos.y+child->aabb.size.y*0.5;
+ child->offset[2]=child->aabb.pos.z+child->aabb.size.z*0.5;
+ child->next_leaf=leaf_list;
+
+
+ for(int ci=0;ci<8;ci++) {
+ child->normal_accum[ci][0]=0;
+ child->normal_accum[ci][1]=0;
+ child->normal_accum[ci][2]=0;
+
+ }
+
+ child->bake_neighbour=0;
+ child->first_neighbour=true;
+ leaf_list=child_idx;
+ cell_count++;
+
+ for(int ci=0;ci<8;ci++) {
+ child->light_accum[ci][0]=0;
+ child->light_accum[ci][1]=0;
+ child->light_accum[ci][2]=0;
+ }
+
+ child->parent=ptr_stack[stack_pos];
+
+ } else {
+
+ child->leaf=false;
+ for(int j=0;j<8;j++) {
+ child->children[j]=0;
+ }
+ }
+ }
+
+ if (!octants[child_idx].leaf) {
+ stack_pos++;
+ stack[stack_pos]=0;
+ ptr_stack[stack_pos]=child_idx;
+ } else {
+
+ Octant *child=&octants[child_idx];
+
+ Vector3 n = Plane(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).normal;
+
+
+ for(int ci=0;ci<8;ci++) {
+
+ Vector3 pos = child->aabb.pos;
+
+ if (ci&1)
+ pos.x+=child->aabb.size.x;
+ if (ci&2)
+ pos.y+=child->aabb.size.y;
+ if (ci&4)
+ pos.z+=child->aabb.size.z;
+
+
+ pos.x=floor((pos.x+cell_size*0.5)/cell_size);
+ pos.y=floor((pos.y+cell_size*0.5)/cell_size);
+ pos.z=floor((pos.z+cell_size*0.5)/cell_size);
+
+ {
+ Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
+ if (!E) {
+ endpoint_normal[pos]=n;
+ } else {
+ E->get()+=n;
+ }
+ }
+
+ {
+
+ uint64_t bit = get_uv_normal_bit(n);
+
+ Map<Vector3,uint64_t>::Element *E=endpoint_normal_bits.find(pos);
+ if (!E) {
+ endpoint_normal_bits[pos]=(1<<bit);
+ } else {
+ E->get()|=(1<<bit);
+ }
+
+ }
+
+ }
+
+ }
+
+
+ } else {
+ stack_pos--;
+ if (stack_pos<0)
+ break;
+ }
+ }
+
+
+}
+
+
+void BakedLightBaker::_make_octree() {
+
+
+ AABB base = bvh->aabb;
+ float lal=base.get_longest_axis_size();
+ //must be square because we want square blocks
+ base.size.x=lal;
+ base.size.y=lal;
+ base.size.z=lal;
+ base.grow_by(lal*0.001); //for precision
+ octree_aabb=base;
+
+ cell_size=base.size.x;
+ for(int i=0;i<octree_depth;i++)
+ cell_size/=2.0;
+ octant_stack = memnew_arr(uint32_t,octree_depth*2 );
+ octantptr_stack = memnew_arr(uint32_t,octree_depth*2 );
+
+ octant_pool.resize(OCTANT_POOL_CHUNK);
+ octant_pool_size=1;
+ Octant *root=octant_pool.ptr();
+ root->leaf=false;
+ root->aabb=octree_aabb;
+ root->parent=-1;
+ for(int i=0;i<8;i++)
+ root->children[i]=0;
+
+ EditorProgress ep("bake_octree",vformat(TTR("Parsing %d Triangles:"), triangles.size()),triangles.size());
+
+ for(int i=0;i<triangles.size();i++) {
+
+ _octree_insert(0,&triangles[i],octree_depth-1);
+ if ((i%1000)==0) {
+
+ ep.step(TTR("Triangle #")+itos(i),i);
+ }
+ }
+
+ {
+ uint32_t oct_idx=leaf_list;
+ Octant *octants=octant_pool.ptr();
+ while(oct_idx) {
+
+ BakedLightBaker::Octant *oct = &octants[oct_idx];
+ for(int ci=0;ci<8;ci++) {
+
+
+ Vector3 pos = oct->aabb.pos;
+
+ if (ci&1)
+ pos.x+=oct->aabb.size.x;
+ if (ci&2)
+ pos.y+=oct->aabb.size.y;
+ if (ci&4)
+ pos.z+=oct->aabb.size.z;
+
+
+ pos.x=floor((pos.x+cell_size*0.5)/cell_size);
+ pos.y=floor((pos.y+cell_size*0.5)/cell_size);
+ pos.z=floor((pos.z+cell_size*0.5)/cell_size);
+
+ {
+ Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
+ if (!E) {
+ //?
+ print_line("lolwut?");
+ } else {
+ Vector3 n = E->get().normalized();
+ oct->normal_accum[ci][0]=n.x;
+ oct->normal_accum[ci][1]=n.y;
+ oct->normal_accum[ci][2]=n.z;
+
+ }
+
+ }
+
+ {
+
+ Map<Vector3,uint64_t>::Element *E=endpoint_normal_bits.find(pos);
+ if (!E) {
+ //?
+ print_line("lolwut?");
+ } else {
+
+ float max_aper=0;
+ for(uint64_t i=0;i<62;i++) {
+
+ if (!(E->get()&(1<<i)))
+ continue;
+ Vector3 ang_i = get_bit_normal(i);
+
+ for(uint64_t j=0;j<62;j++) {
+
+ if (i==j)
+ continue;
+ if (!(E->get()&(1<<j)))
+ continue;
+ Vector3 ang_j = get_bit_normal(j);
+ float ang = Math::acos(ang_i.dot(ang_j));
+ if (ang>max_aper)
+ max_aper=ang;
+ }
+ }
+ if (max_aper>0.75*Math_PI) {
+ //angle too wide prevent problems and forget
+ oct->normal_accum[ci][0]=0;
+ oct->normal_accum[ci][1]=0;
+ oct->normal_accum[ci][2]=0;
+ }
+ }
+ }
+
+
+ }
+
+ oct_idx=oct->next_leaf;
+ }
+ }
+
+
+}
+
+
+
+
+
+void BakedLightBaker::_plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light,const Color& p_tint_light,bool p_only_full, const Plane& p_plane) {
+
+ //stackless version
+
+ uint32_t *stack=thread_stack.octant_stack;
+ uint32_t *ptr_stack=thread_stack.octantptr_stack;
+ Octant *octants=octant_pool.ptr();
+
+ stack[0]=0;
+ ptr_stack[0]=0;
+
+ int stack_pos=0;
+
+
+ while(true) {
+
+ Octant &octant=octants[ptr_stack[stack_pos]];
+
+ if (stack[stack_pos]==0) {
+
+
+ Vector3 pos = octant.aabb.pos + octant.aabb.size*0.5;
+ float md = 1<<(octree_depth - stack_pos );
+ float r=cell_size*plot_size*md;
+ float div = 1.0/(md*md*md);
+ //div=1.0;
+
+
+ float d = p_plot_pos.distance_to(pos);
+
+ if ((p_plane.distance_to(pos)>-cell_size*1.75*md) && d<=r) {
+
+
+ float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
+
+ baked_light_baker_add_64f(&octant.full_accum[0],p_tint_light.r*intensity*div);
+ baked_light_baker_add_64f(&octant.full_accum[1],p_tint_light.g*intensity*div);
+ baked_light_baker_add_64f(&octant.full_accum[2],p_tint_light.b*intensity*div);
+ }
+ }
+
+ if (octant.leaf) {
+
+
+
+ //if (p_plane.normal.dot(octant.aabb.get_support(p_plane.normal)) < p_plane.d-CMP_EPSILON) { //octants behind are no go
+
+
+ if (!p_only_full) {
+ float r=cell_size*plot_size;
+ for(int i=0;i<8;i++) {
+ Vector3 pos=octant.aabb.pos;
+ if (i&1)
+ pos.x+=octant.aabb.size.x;
+ if (i&2)
+ pos.y+=octant.aabb.size.y;
+ if (i&4)
+ pos.z+=octant.aabb.size.z;
+
+
+
+ float d = p_plot_pos.distance_to(pos);
+
+ if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) {
+
+
+ float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
+ if (edge_damp>0) {
+ Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]);
+ if (normal.x>0 || normal.y>0 || normal.z>0) {
+
+ float damp = Math::abs(p_plane.normal.dot(normal));
+ intensity*=pow(damp,edge_damp);
+
+ }
+ }
+
+ //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size);
+ //intensity = Math::cos(d*Math_PI*0.5/r);
+
+ baked_light_baker_add_64f(&octant.light_accum[i][0],p_light.r*intensity);
+ baked_light_baker_add_64f(&octant.light_accum[i][1],p_light.g*intensity);
+ baked_light_baker_add_64f(&octant.light_accum[i][2],p_light.b*intensity);
+
+
+ }
+ }
+ }
+
+ stack_pos--;
+ } else if (stack[stack_pos]<8) {
+
+ int i = stack[stack_pos];
+ stack[stack_pos]++;
+
+ if (!octant.children[i]) {
+ continue;
+ }
+
+ Octant &child=octants[octant.children[i]];
+
+ if (!child.aabb.intersects(p_plot_aabb))
+ continue;
+
+ if (child.aabb.encloses(p_plot_aabb)) {
+ stack[stack_pos]=8; //don't test the rest
+ }
+
+ stack_pos++;
+ stack[stack_pos]=0;
+ ptr_stack[stack_pos]=octant.children[i];
+ } else {
+ stack_pos--;
+ if (stack_pos<0)
+ break;
+ }
+ }
+
+
+}
+
+
+float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) {
+
+
+ uint32_t* stack = thread_stack.ray_stack;
+ BVH **bstack = thread_stack.bvh_stack;
+
+ enum {
+ TEST_AABB_BIT=0,
+ VISIT_LEFT_BIT=1,
+ VISIT_RIGHT_BIT=2,
+ VISIT_DONE_BIT=3,
+
+
+ };
+
+ Vector3 n = (p_end-p_begin);
+ float len=n.length();
+ if (len==0)
+ return 0;
+ n/=len;
+
+
+
+ real_t d=1e10;
+ bool inters=false;
+ Vector3 r_normal;
+ Vector3 r_point;
+ Vector3 end=p_end;
+
+ Triangle *triangle=NULL;
+
+ /*
+ for(int i=0;i<max_depth;i++)
+ stack[i]=0;
+ */
+
+ int level=0;
+ //AABB ray_aabb;
+ //ray_aabb.pos=p_begin;
+ //ray_aabb.expand_to(p_end);
+
+
+ bstack[0]=bvh;
+ stack[0]=TEST_AABB_BIT;
+
+
+ while(true) {
+
+ uint32_t mode = stack[level];
+ const BVH &b = *bstack[level];
+ bool done=false;
+
+ switch(mode) {
+ case TEST_AABB_BIT: {
+
+ if (b.leaf) {
+
+
+ Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
+
+
+ Vector3 res;
+
+ if (f3.intersects_segment(p_begin,end,&res)) {
+
+
+ float nd = n.dot(res);
+ if (nd<d) {
+
+ d=nd;
+ r_point=res;
+ end=res;
+ len=(p_begin-end).length();
+ r_normal=f3.get_plane().get_normal();
+ triangle=b.leaf;
+ inters=true;
+ }
+
+ }
+
+ stack[level]=VISIT_DONE_BIT;
+ } else {
+
+
+ bool valid = b.aabb.smits_intersect_ray(p_begin,n,0,len);
+ //bool valid = b.aabb.intersects_segment(p_begin,p_end);
+ //bool valid = b.aabb.intersects(ray_aabb);
+
+ if (!valid) {
+
+ stack[level]=VISIT_DONE_BIT;
+
+ } else {
+
+ stack[level]=VISIT_LEFT_BIT;
+ }
+ }
+
+ } continue;
+ case VISIT_LEFT_BIT: {
+
+ stack[level]=VISIT_RIGHT_BIT;
+ bstack[level+1]=b.children[0];
+ stack[level+1]=TEST_AABB_BIT;
+ level++;
+
+ } continue;
+ case VISIT_RIGHT_BIT: {
+
+ stack[level]=VISIT_DONE_BIT;
+ bstack[level+1]=b.children[1];
+ stack[level+1]=TEST_AABB_BIT;
+ level++;
+ } continue;
+ case VISIT_DONE_BIT: {
+
+ if (level==0) {
+ done=true;
+ break;
+ } else
+ level--;
+
+ } continue;
+ }
+
+
+ if (done)
+ break;
+ }
+
+
+
+ if (inters) {
+
+ if (p_only_dist) {
+
+ return p_begin.distance_to(r_point);
+ }
+
+
+ //should check if there is normals first
+ Vector2 uv;
+ if (true) {
+
+ triangle->get_uv_and_normal(r_point,uv,r_normal);
+
+ } else {
+
+ }
+
+ if (n.dot(r_normal)>0)
+ return -1;
+
+ if (n.dot(r_normal)>0)
+ r_normal=-r_normal;
+
+
+ //ok...
+ Color diffuse_at_point(0.8,0.8,0.8);
+ Color specular_at_point(0.0,0.0,0.0);
+
+
+ float dist = p_begin.distance_to(r_point);
+
+ AABB aabb;
+ aabb.pos=r_point;
+ aabb.pos-=Vector3(1,1,1)*cell_size*plot_size;
+ aabb.size=Vector3(2,2,2)*cell_size*plot_size;
+
+ Color res_light=p_light;
+ float att=1.0;
+ float dp=(1.0-normal_damp)*n.dot(-r_normal)+normal_damp;
+
+ if (p_att_curve) {
+
+ p_att_pos+=dist;
+ int cpos = Math::fast_ftoi((p_att_pos/p_att_curve_len)*ATTENUATION_CURVE_LEN);
+ cpos=CLAMP(cpos,0,ATTENUATION_CURVE_LEN-1);
+ att=p_att_curve[cpos];
+ }
+
+
+ res_light.r*=dp;
+ res_light.g*=dp;
+ res_light.b*=dp;
+
+ //light is plotted before multiplication with diffuse, this way
+ //the multiplication can happen with more detail in the shader
+
+
+
+ if (triangle->material) {
+
+ //triangle->get_uv(r_point);
+
+ diffuse_at_point=triangle->material->diffuse.get_color(uv);
+ specular_at_point=triangle->material->specular.get_color(uv);
+ }
+
+
+ diffuse_at_point.r=res_light.r*diffuse_at_point.r;
+ diffuse_at_point.g=res_light.g*diffuse_at_point.g;
+ diffuse_at_point.b=res_light.b*diffuse_at_point.b;
+
+ if (p_bounces>0) {
+
+
+ p_rest-=dist;
+ if (p_rest<CMP_EPSILON)
+ return 0;
+
+ if (r_normal==-n)
+ return 0; //todo change a little
+
+ r_point+=r_normal*0.01;
+
+
+
+
+ specular_at_point.r=res_light.r*specular_at_point.r;
+ specular_at_point.g=res_light.g*specular_at_point.g;
+ specular_at_point.b=res_light.b*specular_at_point.b;
+
+
+
+ if (use_diffuse && (diffuse_at_point.r>CMP_EPSILON || diffuse_at_point.g>CMP_EPSILON || diffuse_at_point.b>CMP_EPSILON)) {
+ //diffuse bounce
+
+ Vector3 c1=r_normal.cross(n).normalized();
+ Vector3 c2=r_normal.cross(c1).normalized();
+ double r1 = double(rand())/RAND_MAX;
+ double r2 = double(rand())/RAND_MAX;
+ double r3 = double(rand())/RAND_MAX;
+#if 0
+ Vector3 next = - ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*(r3-0.5))).normalized()*0.5 + r_normal*0.5;
+
+ if (next==Vector3())
+ next=r_normal;
+ Vector3 rn=next.normalized();
+
+#else
+ Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.5)).normalized();
+#endif
+
+
+ _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1);
+ }
+
+ if (use_specular && (specular_at_point.r>CMP_EPSILON || specular_at_point.g>CMP_EPSILON || specular_at_point.b>CMP_EPSILON)) {
+ //specular bounce
+
+ //Vector3 c1=r_normal.cross(n).normalized();
+ //Vector3 c2=r_normal.cross(c1).normalized();
+
+ Vector3 rn = n - r_normal *r_normal.dot(n) * 2.0;
+
+ _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1);
+ }
+ }
+
+ //specular later
+ //_plot_light_point(r_point,octree,octree_aabb,p_light);
+
+
+ Color plot_light=res_light.linear_interpolate(diffuse_at_point,tint);
+ plot_light.r*=att;
+ plot_light.g*=att;
+ plot_light.b*=att;
+ Color tint_light=diffuse_at_point;
+ tint_light.r*=att;
+ tint_light.g*=att;
+ tint_light.b*=att;
+
+ bool skip=false;
+
+ if (!p_first_bounce || p_bake_direct) {
+
+
+ float r = plot_size * cell_size*2;
+ if (dist<r) {
+ //avoid accumulaiton of light on corners
+ //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
+ skip=true;
+
+ } else {
+
+
+ Vector3 c1=r_normal.cross(n).normalized();
+ Vector3 c2=r_normal.cross(c1).normalized();
+ double r1 = double(rand())/RAND_MAX;
+ double r2 = double(rand())/RAND_MAX;
+ double r3 = double(rand())/RAND_MAX;
+ Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.25)).normalized();
+ float d =_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1,false,true);
+ r = plot_size*cell_size*ao_radius;
+ if (d>0 && d<r) {
+ //avoid accumulaiton of light on corners
+ //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
+ skip=true;
+
+ } else {
+ //plot_light=Color(0,0,0,0);
+ }
+ }
+ }
+
+
+ Plane plane(r_point,r_normal);
+ if (!skip)
+ _plot_light(thread_stack,r_point,aabb,plot_light,tint_light,!(!p_first_bounce || p_bake_direct),plane);
+
+
+ return dist;
+ }
+
+ return -1;
+
+}
+
+
+
+
+void BakedLightBaker::_make_octree_texture() {
+
+
+ BakedLightBaker::Octant *octants=octant_pool.ptr();
+
+ //find neighbours first, to have a better idea of what amount of space is needed
+ {
+
+ Vector<OctantHash> octant_hashing;
+ octant_hashing.resize(octant_pool_size);
+ Vector<uint32_t> hash_table;
+ int hash_table_size=Math::larger_prime(16384);
+ hash_table.resize(hash_table_size);
+ uint32_t*hashptr = hash_table.ptr();
+ OctantHash*octhashptr = octant_hashing.ptr();
+
+ for(int i=0;i<hash_table_size;i++)
+ hashptr[i]=0;
+
+
+ //step 1 add to hash table
+
+ uint32_t oct_idx=leaf_list;
+
+
+ while(oct_idx) {
+
+ BakedLightBaker::Octant *oct = &octants[oct_idx];
+ uint64_t base=0;
+ Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive
+ base=int((pos.x+cell_size*0.5)/cell_size);
+ base<<=16;
+ base|=int((pos.y+cell_size*0.5)/cell_size);
+ base<<=16;
+ base|=int((pos.z+cell_size*0.5)/cell_size);
+
+ uint32_t hash = HashMapHasherDefault::hash(base);
+ uint32_t idx = hash % hash_table_size;
+ octhashptr[oct_idx].next=hashptr[idx];
+ octhashptr[oct_idx].hash=hash;
+ octhashptr[oct_idx].value=base;
+ hashptr[idx]=oct_idx;
+
+ oct_idx=oct->next_leaf;
+
+ }
+
+ //step 2 find neighbours
+ oct_idx=leaf_list;
+ int neighbours=0;
+
+
+ while(oct_idx) {
+
+ BakedLightBaker::Octant *oct = &octants[oct_idx];
+ Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive
+ pos.x+=cell_size;
+ uint64_t base=0;
+ base=int((pos.x+cell_size*0.5)/cell_size);
+ base<<=16;
+ base|=int((pos.y+cell_size*0.5)/cell_size);
+ base<<=16;
+ base|=int((pos.z+cell_size*0.5)/cell_size);
+
+ uint32_t hash = HashMapHasherDefault::hash(base);
+ uint32_t idx = hash % hash_table_size;
+
+ uint32_t bucket = hashptr[idx];
+
+ while(bucket) {
+
+ if (octhashptr[bucket].value==base) {
+
+ oct->bake_neighbour=bucket;
+ octants[bucket].first_neighbour=false;
+ neighbours++;
+ break;
+ }
+
+ bucket = octhashptr[bucket].next;
+ }
+
+ oct_idx=oct->next_leaf;
+
+ }
+
+ print_line("octant with neighbour: "+itos(neighbours));
+
+ }
+
+
+ //ok let's try to just create a texture
+
+ int otex_w=256;
+
+ while (true) {
+
+
+
+ uint32_t oct_idx=leaf_list;
+
+ int row=0;
+
+
+ print_line("begin at row "+itos(row));
+ int longest_line_reused=0;
+ int col=0;
+ int processed=0;
+
+ //reset
+ while(oct_idx) {
+
+ BakedLightBaker::Octant *oct = &octants[oct_idx];
+ oct->texture_x=0;
+ oct->texture_y=0;
+ oct_idx=oct->next_leaf;
+
+ }
+
+ oct_idx=leaf_list;
+ //assign
+ while(oct_idx) {
+
+ BakedLightBaker::Octant *oct = &octants[oct_idx];
+ if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) {
+ //was not processed
+ uint32_t current_idx=oct_idx;
+ int reused=0;
+
+ while(current_idx) {
+ BakedLightBaker::Octant *o = &octants[current_idx];
+ if (col+1 >= otex_w) {
+ col=0;
+ row+=4;
+ }
+ o->texture_x=col;
+ o->texture_y=row;
+ processed++;
+
+ if (o->bake_neighbour) {
+ reused++;
+ }
+ col+=o->bake_neighbour ? 1 : 2; //reuse neighbour
+ current_idx=o->bake_neighbour;
+ }
+
+ if (reused>longest_line_reused) {
+ longest_line_reused=reused;
+ }
+ }
+ oct_idx=oct->next_leaf;
+ }
+
+ row+=4;
+
+ if (otex_w < row) {
+
+ otex_w*=2;
+ } else {
+
+ baked_light_texture_w=otex_w;
+ baked_light_texture_h=nearest_power_of_2(row);
+ print_line("w: "+itos(otex_w));
+ print_line("h: "+itos(row));
+ break;
+ }
+
+
+ }
+
+
+ {
+
+ otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally
+ Vector3 lattice_cell_size=octree_aabb.size;
+ for(int i=0;i<lattice_size;i++) {
+
+ lattice_cell_size*=0.5;
+ }
+
+
+
+ while(true) {
+
+ //let's plot the leafs first, given the octree is not so obvious which size it will have
+ int row=4+4*(1<<lattice_size);
+ int col=0;
+
+ col=0;
+ row+=4;
+ print_line("end at row "+itos(row));
+
+ //put octree, no need for recursion, just loop backwards.
+ int regular_octants=0;
+ for(int i=octant_pool_size-1;i>=0;i--) {
+
+ BakedLightBaker::Octant *oct = &octants[i];
+ if (oct->leaf) //ignore leaf
+ continue;
+ if (oct->aabb.size.x>lattice_cell_size.x*1.1) { //bigger than latice, skip
+ oct->texture_x=0;
+ oct->texture_y=0;
+ } else if (oct->aabb.size.x>lattice_cell_size.x*0.8) {
+ //this is the initial lattice
+ Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive
+ int x = int((pos.x+lattice_cell_size.x*0.5)/lattice_cell_size.x);
+ int y = int((pos.y+lattice_cell_size.y*0.5)/lattice_cell_size.y);
+ int z = int((pos.z+lattice_cell_size.z*0.5)/lattice_cell_size.z);
+ //bug net
+ ERR_FAIL_INDEX(x,(1<<lattice_size));
+ ERR_FAIL_INDEX(y,(1<<lattice_size));
+ ERR_FAIL_INDEX(z,(1<<lattice_size));
+
+ /*int ofs = z*(1<<lattice_size)*(1<<lattice_size)+y*(1<<lattice_size)+x;
+ ofs*=4;
+ oct->texture_x=ofs%otex_w;
+ oct->texture_y=(ofs/otex_w)*4+4;
+ */
+
+ oct->texture_x=(x+(1<<lattice_size)*z)*2;
+ oct->texture_y=4+y*4;
+ //print_line("pos: "+itos(x)+","+itos(y)+","+itos(z)+" - ofs"+itos(oct->texture_x)+","+itos(oct->texture_y));
+
+
+ } else {
+ //an everyday regular octant
+
+ if (col+2 > otex_w) {
+ col=0;
+ row+=4;
+ }
+
+ oct->texture_x=col;
+ oct->texture_y=row;
+ col+=2;
+ regular_octants++;
+
+
+ }
+ }
+ print_line("octants end at row "+itos(row)+" totalling"+itos(regular_octants));
+
+ //ok evaluation.
+
+ if (otex_w<=2048 && row>2048) { //too big upwards, try bigger texture
+ otex_w*=2;
+ continue;
+ } else {
+ baked_octree_texture_w=otex_w;
+ baked_octree_texture_h=row+4;
+ break;
+ }
+
+ }
+
+
+ }
+
+
+ baked_octree_texture_h=nearest_power_of_2(baked_octree_texture_h);
+ print_line("RESULT! "+itos(baked_octree_texture_w)+","+itos(baked_octree_texture_h));
+
+}
+
+
+
+
+
+
+
+
+double BakedLightBaker::get_normalization(int p_light_idx) const {
+
+ double nrg=0;
+
+ const LightData &dl=lights[p_light_idx];
+ double cell_area = cell_size*cell_size;
+ //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area);
+ nrg=dl.rays_thrown * cell_area;
+ nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel
+ nrg*=dl.constant;
+ //nrg*=5;
+
+
+ return nrg;
+}
+
+
+
+double BakedLightBaker::get_modifier(int p_light_idx) const {
+
+ double nrg=0;
+
+ const LightData &dl=lights[p_light_idx];
+ double cell_area = cell_size*cell_size;
+ //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area);
+ nrg=cell_area;
+ nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel
+ nrg*=dl.constant;
+ //nrg*=5;
+
+
+ return nrg;
+}
+
+void BakedLightBaker::throw_rays(ThreadStack& thread_stack,int p_amount) {
+
+
+
+ for(int i=0;i<lights.size();i++) {
+
+ LightData &dl=lights[i];
+
+
+ int amount = p_amount * total_light_area / dl.area;
+ double mod = 1.0/double(get_modifier(i));
+ mod*=p_amount/float(amount);
+
+ switch(dl.type) {
+
+ case VS::LIGHT_DIRECTIONAL: {
+
+
+ for(int j=0;j<amount;j++) {
+ Vector3 from = dl.pos;
+ double r1 = double(rand())/RAND_MAX;
+ double r2 = double(rand())/RAND_MAX;
+ from+=dl.up*(r1*2.0-1.0);
+ from+=dl.left*(r2*2.0-1.0);
+ Vector3 to = from+dl.dir*dl.length;
+ Color col=dl.diffuse;
+ float m = mod*dl.energy;
+ col.r*=m;
+ col.g*=m;
+ col.b*=m;
+
+ dl.rays_thrown++;
+ baked_light_baker_add_64i(&total_rays,1);
+
+ _throw_ray(thread_stack,dl.bake_direct,from,to,dl.length,col,NULL,0,0,max_bounces,true);
+ }
+ } break;
+ case VS::LIGHT_OMNI: {
+
+
+ for(int j=0;j<amount;j++) {
+ Vector3 from = dl.pos;
+
+ double r1 = double(rand())/RAND_MAX;
+ double r2 = double(rand())/RAND_MAX;
+ double r3 = double(rand())/RAND_MAX;
+
+#if 0
+ //crap is not uniform..
+ Vector3 dir = Vector3(r1*2.0-1.0,r2*2.0-1.0,r3*2.0-1.0).normalized();
+
+#else
+
+ double phi = r1*Math_PI*2.0;
+ double costheta = r2*2.0-1.0;
+ double u = r3;
+
+ double theta = acos( costheta );
+ double r = 1.0 * pow( u,1/3.0 );
+
+ Vector3 dir(
+ r * sin( theta) * cos( phi ),
+ r * sin( theta) * sin( phi ),
+ r * cos( theta )
+ );
+ dir.normalize();
+
+#endif
+ Vector3 to = dl.pos+dir*dl.radius;
+ Color col=dl.diffuse;
+ float m = mod*dl.energy;
+ col.r*=m;
+ col.g*=m;
+ col.b*=m;
+
+ dl.rays_thrown++;
+ baked_light_baker_add_64i(&total_rays,1);
+ _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true);
+ //_throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true);
+ }
+
+ } break;
+ case VS::LIGHT_SPOT: {
+
+ for(int j=0;j<amount;j++) {
+ Vector3 from = dl.pos;
+
+ double r1 = double(rand())/RAND_MAX;
+ //double r2 = double(rand())/RAND_MAX;
+ double r3 = double(rand())/RAND_MAX;
+
+ float d=Math::tan(Math::deg2rad(dl.spot_angle));
+
+ float x = sin(r1*Math_PI*2.0)*d;
+ float y = cos(r1*Math_PI*2.0)*d;
+
+ Vector3 dir = r3*(dl.dir + dl.up*y + dl.left*x) + (1.0-r3)*dl.dir;
+ dir.normalize();
+
+
+ Vector3 to = dl.pos+dir*dl.radius;
+ Color col=dl.diffuse;
+ float m = mod*dl.energy;
+ col.r*=m;
+ col.g*=m;
+ col.b*=m;
+
+ dl.rays_thrown++;
+ baked_light_baker_add_64i(&total_rays,1);
+ _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true);
+ //_throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true);
+ }
+
+ } break;
+
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) {
+
+ if (baking)
+ return;
+ cell_count=0;
+
+ base_inv=p_node->cast_to<Spatial>()->get_global_transform().affine_inverse();
+ EditorProgress ep("bake",TTR("Light Baker Setup:"),5);
+ baked_light=p_light;
+ lattice_size=baked_light->get_initial_lattice_subdiv();
+ octree_depth=baked_light->get_cell_subdivision();
+ plot_size=baked_light->get_plot_size();
+ max_bounces=baked_light->get_bounces();
+ use_diffuse=baked_light->get_bake_flag(BakedLight::BAKE_DIFFUSE);
+ use_specular=baked_light->get_bake_flag(BakedLight::BAKE_SPECULAR);
+ use_translucency=baked_light->get_bake_flag(BakedLight::BAKE_TRANSLUCENT);
+
+ edge_damp=baked_light->get_edge_damp();
+ normal_damp=baked_light->get_normal_damp();
+ octree_extra_margin=baked_light->get_cell_extra_margin();
+ tint=baked_light->get_tint();
+ ao_radius=baked_light->get_ao_radius();
+ ao_strength=baked_light->get_ao_strength();
+ linear_color=baked_light->get_bake_flag(BakedLight::BAKE_LINEAR_COLOR);
+
+ baked_textures.clear();
+ for(int i=0;i<baked_light->get_lightmaps_count();i++) {
+ BakeTexture bt;
+ bt.width=baked_light->get_lightmap_gen_size(i).x;
+ bt.height=baked_light->get_lightmap_gen_size(i).y;
+ baked_textures.push_back(bt);
+ }
+
+
+ ep.step(TTR("Parsing Geometry"),0);
+ _parse_geometry(p_node);
+ mat_map.clear();
+ tex_map.clear();
+ print_line("\ttotal triangles: "+itos(triangles.size()));
+ // no geometry
+ if (triangles.size() == 0) {
+ return;
+ }
+ ep.step(TTR("Fixing Lights"),1);
+ _fix_lights();
+ ep.step(TTR("Making BVH"),2);
+ _make_bvh();
+ ep.step(TTR("Creating Light Octree"),3);
+ _make_octree();
+ ep.step(TTR("Creating Octree Texture"),4);
+ _make_octree_texture();
+ baking=true;
+ _start_thread();
+
+}
+
+
+void BakedLightBaker::update_octree_sampler(PoolVector<int> &p_sampler) {
+
+ BakedLightBaker::Octant *octants=octant_pool.ptr();
+ double norm = 1.0/double(total_rays);
+
+
+
+ if (p_sampler.size()==0 || first_bake_to_map) {
+
+ Vector<int> tmp_smp;
+ tmp_smp.resize(32); //32 for header
+
+ for(int i=0;i<32;i++) {
+ tmp_smp[i]=0;
+ }
+
+ for(int i=octant_pool_size-1;i>=0;i--) {
+
+ if (i==0)
+ tmp_smp[1]=tmp_smp.size();
+
+ Octant &octant=octants[i];
+ octant.sampler_ofs = tmp_smp.size();
+ int idxcol[2]={0,0};
+
+ int r = CLAMP((octant.full_accum[0]*norm)*2048,0,32767);
+ int g = CLAMP((octant.full_accum[1]*norm)*2048,0,32767);
+ int b = CLAMP((octant.full_accum[2]*norm)*2048,0,32767);
+
+ idxcol[0]|=r;
+ idxcol[1]|=(g<<16)|b;
+
+ if (octant.leaf) {
+ tmp_smp.push_back(idxcol[0]);
+ tmp_smp.push_back(idxcol[1]);
+ } else {
+
+ for(int j=0;j<8;j++) {
+ if (octant.children[j]) {
+ idxcol[0]|=(1<<(j+16));
+ }
+ }
+ tmp_smp.push_back(idxcol[0]);
+ tmp_smp.push_back(idxcol[1]);
+ for(int j=0;j<8;j++) {
+ if (octant.children[j]) {
+ tmp_smp.push_back(octants[octant.children[j]].sampler_ofs);
+ if (octants[octant.children[j]].sampler_ofs==0) {
+ print_line("FUUUUUUUUCK");
+ }
+ }
+ }
+ }
+
+ }
+
+ p_sampler.resize(tmp_smp.size());
+ PoolVector<int>::Write w = p_sampler.write();
+ int ss = tmp_smp.size();
+ for(int i=0;i<ss;i++) {
+ w[i]=tmp_smp[i];
+ }
+
+ first_bake_to_map=false;
+
+ }
+
+ double gamma = baked_light->get_gamma_adjust();
+ double mult = baked_light->get_energy_multiplier();
+ float saturation = baked_light->get_saturation();
+
+ PoolVector<int>::Write w = p_sampler.write();
+
+ encode_uint32(octree_depth,(uint8_t*)&w[2]);
+ encode_uint32(linear_color,(uint8_t*)&w[3]);
+
+ encode_float(octree_aabb.pos.x,(uint8_t*)&w[4]);
+ encode_float(octree_aabb.pos.y,(uint8_t*)&w[5]);
+ encode_float(octree_aabb.pos.z,(uint8_t*)&w[6]);
+ encode_float(octree_aabb.size.x,(uint8_t*)&w[7]);
+ encode_float(octree_aabb.size.y,(uint8_t*)&w[8]);
+ encode_float(octree_aabb.size.z,(uint8_t*)&w[9]);
+
+ //norm*=multiplier;
+
+ for(int i=octant_pool_size-1;i>=0;i--) {
+
+ Octant &octant=octants[i];
+ int idxcol[2]={w[octant.sampler_ofs],w[octant.sampler_ofs+1]};
+
+ double rf=pow(octant.full_accum[0]*norm*mult,gamma);
+ double gf=pow(octant.full_accum[1]*norm*mult,gamma);
+ double bf=pow(octant.full_accum[2]*norm*mult,gamma);
+
+ double gray = (rf+gf+bf)/3.0;
+ rf = gray + (rf-gray)*saturation;
+ gf = gray + (gf-gray)*saturation;
+ bf = gray + (bf-gray)*saturation;
+
+
+ int r = CLAMP((rf)*2048,0,32767);
+ int g = CLAMP((gf)*2048,0,32767);
+ int b = CLAMP((bf)*2048,0,32767);
+
+ idxcol[0]=((idxcol[0]>>16)<<16)|r;
+ idxcol[1]=(g<<16)|b;
+ w[octant.sampler_ofs]=idxcol[0];
+ w[octant.sampler_ofs+1]=idxcol[1];
+ }
+
+}
+
+void BakedLightBaker::update_octree_images(PoolVector<uint8_t> &p_octree,PoolVector<uint8_t> &p_light) {
+
+
+ int len = baked_octree_texture_w*baked_octree_texture_h*4;
+ p_octree.resize(len);
+
+ int ilen = baked_light_texture_w*baked_light_texture_h*4;
+ p_light.resize(ilen);
+
+
+ PoolVector<uint8_t>::Write w = p_octree.write();
+ zeromem(w.ptr(),len);
+
+ PoolVector<uint8_t>::Write iw = p_light.write();
+ zeromem(iw.ptr(),ilen);
+
+ float gamma = baked_light->get_gamma_adjust();
+ float mult = baked_light->get_energy_multiplier();
+
+ for(int i=0;i<len;i+=4) {
+ w[i+0]=0xFF;
+ w[i+1]=0;
+ w[i+2]=0xFF;
+ w[i+3]=0xFF;
+ }
+
+ for(int i=0;i<ilen;i+=4) {
+ iw[i+0]=0xFF;
+ iw[i+1]=0;
+ iw[i+2]=0xFF;
+ iw[i+3]=0xFF;
+ }
+
+ float multiplier=1.0;
+
+ if (baked_light->get_format()==BakedLight::FORMAT_HDR8)
+ multiplier=8;
+ encode_uint32(baked_octree_texture_w,&w[0]);
+ encode_uint32(baked_octree_texture_h,&w[4]);
+ encode_uint32(0,&w[8]);
+ encode_float(1<<lattice_size,&w[12]);
+ encode_uint32(octree_depth-lattice_size,&w[16]);
+ encode_uint32(multiplier,&w[20]);
+ encode_uint16(baked_light_texture_w,&w[24]); //if present, use the baked light texture
+ encode_uint16(baked_light_texture_h,&w[26]);
+ encode_uint32(0,&w[28]); //baked light texture format
+
+ encode_float(octree_aabb.pos.x,&w[32]);
+ encode_float(octree_aabb.pos.y,&w[36]);
+ encode_float(octree_aabb.pos.z,&w[40]);
+ encode_float(octree_aabb.size.x,&w[44]);
+ encode_float(octree_aabb.size.y,&w[48]);
+ encode_float(octree_aabb.size.z,&w[52]);
+
+
+ BakedLightBaker::Octant *octants=octant_pool.ptr();
+ int octant_count=octant_pool_size;
+ uint8_t *ptr = w.ptr();
+ uint8_t *lptr = iw.ptr();
+
+
+ int child_offsets[8]={
+ 0,
+ 4,
+ baked_octree_texture_w*4,
+ baked_octree_texture_w*4+4,
+ baked_octree_texture_w*8+0,
+ baked_octree_texture_w*8+4,
+ baked_octree_texture_w*8+baked_octree_texture_w*4,
+ baked_octree_texture_w*8+baked_octree_texture_w*4+4,
+ };
+
+ int lchild_offsets[8]={
+ 0,
+ 4,
+ baked_light_texture_w*4,
+ baked_light_texture_w*4+4,
+ baked_light_texture_w*8+0,
+ baked_light_texture_w*8+4,
+ baked_light_texture_w*8+baked_light_texture_w*4,
+ baked_light_texture_w*8+baked_light_texture_w*4+4,
+ };
+
+ /*Vector<double> norm_arr;
+ norm_arr.resize(lights.size());
+
+ for(int i=0;i<lights.size();i++) {
+ norm_arr[i] = 1.0/get_normalization(i);
+ }
+
+ const double *normptr=norm_arr.ptr();
+*/
+ double norm = 1.0/double(total_rays);
+ mult/=multiplier;
+ double saturation = baked_light->get_saturation();
+
+ for(int i=0;i<octant_count;i++) {
+
+ Octant &oct=octants[i];
+ if (oct.texture_x==0 && oct.texture_y==0)
+ continue;
+
+
+ if (oct.leaf) {
+
+ int ofs = (oct.texture_y * baked_light_texture_w + oct.texture_x)<<2;
+ ERR_CONTINUE(ofs<0 || ofs >ilen);
+ //write colors
+ for(int j=0;j<8;j++) {
+
+ /*
+ if (!oct.children[j])
+ continue;
+ */
+ uint8_t *iptr=&lptr[ofs+lchild_offsets[j]];
+
+ float r=oct.light_accum[j][0]*norm;
+ float g=oct.light_accum[j][1]*norm;
+ float b=oct.light_accum[j][2]*norm;
+
+ r=pow(r*mult,gamma);
+ g=pow(g*mult,gamma);
+ b=pow(b*mult,gamma);
+
+ double gray = (r+g+b)/3.0;
+ r = gray + (r-gray)*saturation;
+ g = gray + (g-gray)*saturation;
+ b = gray + (b-gray)*saturation;
+
+ float ic[3]={
+ r,
+ g,
+ b,
+ };
+ iptr[0]=CLAMP(ic[0]*255.0,0,255);
+ iptr[1]=CLAMP(ic[1]*255.0,0,255);
+ iptr[2]=CLAMP(ic[2]*255.0,0,255);
+ iptr[3]=255;
+ }
+
+ } else {
+
+ int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2;
+ ERR_CONTINUE(ofs<0 || ofs >len);
+
+ //write indices
+ for(int j=0;j<8;j++) {
+
+ if (!oct.children[j])
+ continue;
+ Octant&choct=octants[oct.children[j]];
+ uint8_t *iptr=&ptr[ofs+child_offsets[j]];
+
+ iptr[0]=choct.texture_x>>8;
+ iptr[1]=choct.texture_x&0xFF;
+ iptr[2]=choct.texture_y>>8;
+ iptr[3]=choct.texture_y&0xFF;
+
+ }
+ }
+
+ }
+
+
+}
+
+
+void BakedLightBaker::_free_bvh(BVH* p_bvh) {
+
+ if (!p_bvh->leaf) {
+ if (p_bvh->children[0])
+ _free_bvh(p_bvh->children[0]);
+ if (p_bvh->children[1])
+ _free_bvh(p_bvh->children[1]);
+ }
+
+ memdelete(p_bvh);
+
+}
+
+
+bool BakedLightBaker::is_baking() {
+
+ return baking;
+}
+
+void BakedLightBaker::set_pause(bool p_pause){
+
+ if (paused==p_pause)
+ return;
+
+ paused=p_pause;
+
+ if (paused) {
+ _stop_thread();
+ } else {
+ _start_thread();
+ }
+}
+bool BakedLightBaker::is_paused() {
+
+ return paused;
+
+}
+
+void BakedLightBaker::_bake_thread_func(void *arg) {
+
+ BakedLightBaker *ble = (BakedLightBaker*)arg;
+
+
+
+ ThreadStack thread_stack;
+
+ thread_stack.ray_stack = memnew_arr(uint32_t,ble->bvh_depth);
+ thread_stack.bvh_stack = memnew_arr(BVH*,ble->bvh_depth);
+ thread_stack.octant_stack = memnew_arr(uint32_t,ble->octree_depth*2 );
+ thread_stack.octantptr_stack = memnew_arr(uint32_t,ble->octree_depth*2 );
+
+ while(!ble->bake_thread_exit) {
+
+ ble->throw_rays(thread_stack,1000);
+ }
+
+ memdelete_arr(thread_stack.ray_stack );
+ memdelete_arr(thread_stack.bvh_stack );
+ memdelete_arr(thread_stack.octant_stack );
+ memdelete_arr(thread_stack.octantptr_stack );
+
+}
+
+void BakedLightBaker::_start_thread() {
+
+ if (threads.size()!=0)
+ return;
+ bake_thread_exit=false;
+
+ int thread_count = EDITOR_DEF("light_baker/custom_bake_threads",0);
+ if (thread_count<=0 || thread_count>64)
+ thread_count=OS::get_singleton()->get_processor_count();
+
+ //thread_count=1;
+ threads.resize(thread_count);
+ for(int i=0;i<threads.size();i++) {
+ threads[i]=Thread::create(_bake_thread_func,this);
+ }
+}
+
+void BakedLightBaker::_stop_thread() {
+
+ if (threads.size()==0)
+ return;
+ bake_thread_exit=true;
+ for(int i=0;i<threads.size();i++) {
+ Thread::wait_to_finish(threads[i]);
+ memdelete(threads[i]);
+ }
+ threads.clear();
+}
+
+void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma) {
+
+
+ uint8_t *ptr = &image[(y*width+x)*4];
+ //int lc = lights.size();
+ double norm = 1.0/double(total_rays);
+
+
+ Color color;
+
+ Octant *octants=octant_pool.ptr();
+
+
+ int octant_idx=0;
+
+
+ while(true) {
+
+ Octant &octant=octants[octant_idx];
+
+ if (octant.leaf) {
+
+ Vector3 lpos = p_pos-octant.aabb.pos;
+ lpos/=octant.aabb.size;
+
+ Vector3 cols[8];
+
+ for(int i=0;i<8;i++) {
+
+ cols[i].x+=octant.light_accum[i][0]*norm;
+ cols[i].y+=octant.light_accum[i][1]*norm;
+ cols[i].z+=octant.light_accum[i][2]*norm;
+ }
+
+
+ /*Vector3 final = (cols[0] + (cols[1] - cols[0]) * lpos.y);
+ final = final + ((cols[2] + (cols[3] - cols[2]) * lpos.y) - final)*lpos.x;
+
+ Vector3 final2 = (cols[4+0] + (cols[4+1] - cols[4+0]) * lpos.y);
+ final2 = final2 + ((cols[4+2] + (cols[4+3] - cols[4+2]) * lpos.y) - final2)*lpos.x;*/
+
+ Vector3 finala = cols[0].linear_interpolate(cols[1],lpos.x);
+ Vector3 finalb = cols[2].linear_interpolate(cols[3],lpos.x);
+ Vector3 final = finala.linear_interpolate(finalb,lpos.y);
+
+ Vector3 final2a = cols[4+0].linear_interpolate(cols[4+1],lpos.x);
+ Vector3 final2b = cols[4+2].linear_interpolate(cols[4+3],lpos.x);
+ Vector3 final2 = final2a.linear_interpolate(final2b,lpos.y);
+
+ final = final.linear_interpolate(final2,lpos.z);
+ if (baked_light->get_format()==BakedLight::FORMAT_HDR8)
+ final*=8.0;
+
+
+ color.r=pow(final.x*mult,gamma);
+ color.g=pow(final.y*mult,gamma);
+ color.b=pow(final.z*mult,gamma);
+ color.a=1.0;
+
+ int lc = lights.size();
+ LightData *lv = lights.ptr();
+ for(int i=0;i<lc;i++) {
+ //shadow baking
+ if (!lv[i].bake_shadow)
+ continue;
+ Vector3 from = p_pos+p_normal*0.01;
+ Vector3 to;
+ float att=0;
+ switch(lv[i].type) {
+ case VS::LIGHT_DIRECTIONAL: {
+ to=from-lv[i].dir*lv[i].length;
+ } break;
+ case VS::LIGHT_OMNI: {
+ to=lv[i].pos;
+ float d = MIN(lv[i].radius,to.distance_to(from))/lv[i].radius;
+ att=d;//1.0-d;
+ } break;
+ default: continue;
+ }
+
+ uint32_t* stack = ray_stack;
+ BVH **bstack = bvh_stack;
+
+ enum {
+ TEST_RAY_BIT=0,
+ VISIT_LEFT_BIT=1,
+ VISIT_RIGHT_BIT=2,
+ VISIT_DONE_BIT=3,
+
+
+ };
+
+ bool intersected=false;
+
+ int level=0;
+
+ Vector3 n = (to-from);
+ float len=n.length();
+ if (len==0)
+ continue;
+ n/=len;
+
+ bstack[0]=bvh;
+ stack[0]=TEST_RAY_BIT;
+
+
+ while(!intersected) {
+
+ uint32_t mode = stack[level];
+ const BVH &b = *bstack[level];
+ bool done=false;
+
+ switch(mode) {
+ case TEST_RAY_BIT: {
+
+ if (b.leaf) {
+
+
+ Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
+
+
+ Vector3 res;
+
+ if (f3.intersects_segment(from,to)) {
+ intersected=true;
+ done=true;
+ }
+
+ stack[level]=VISIT_DONE_BIT;
+ } else {
+
+
+ bool valid = b.aabb.smits_intersect_ray(from,n,0,len);
+ //bool valid = b.aabb.intersects_segment(p_begin,p_end);
+ //bool valid = b.aabb.intersects(ray_aabb);
+
+ if (!valid) {
+
+ stack[level]=VISIT_DONE_BIT;
+
+ } else {
+
+ stack[level]=VISIT_LEFT_BIT;
+ }
+ }
+
+ } continue;
+ case VISIT_LEFT_BIT: {
+
+ stack[level]=VISIT_RIGHT_BIT;
+ bstack[level+1]=b.children[0];
+ stack[level+1]=TEST_RAY_BIT;
+ level++;
+
+ } continue;
+ case VISIT_RIGHT_BIT: {
+
+ stack[level]=VISIT_DONE_BIT;
+ bstack[level+1]=b.children[1];
+ stack[level+1]=TEST_RAY_BIT;
+ level++;
+ } continue;
+ case VISIT_DONE_BIT: {
+
+ if (level==0) {
+ done=true;
+ break;
+ } else
+ level--;
+
+ } continue;
+ }
+
+
+ if (done)
+ break;
+ }
+
+
+
+ if (intersected) {
+
+ color.a=Math::lerp(MAX(0.01,lv[i].darkening),1.0,att);
+ }
+
+ }
+
+ break;
+ } else {
+
+ Vector3 lpos = p_pos - octant.aabb.pos;
+ Vector3 half = octant.aabb.size * 0.5;
+
+ int ofs=0;
+
+ if (lpos.x >= half.x)
+ ofs|=1;
+ if (lpos.y >= half.y)
+ ofs|=2;
+ if (lpos.z >= half.z)
+ ofs|=4;
+
+ octant_idx = octant.children[ofs];
+
+ if (octant_idx==0)
+ return;
+
+ }
+ }
+
+ ptr[0]=CLAMP(color.r*255.0,0,255);
+ ptr[1]=CLAMP(color.g*255.0,0,255);
+ ptr[2]=CLAMP(color.b*255.0,0,255);
+ ptr[3]=CLAMP(color.a*255.0,0,255);
+
+}
+
+
+Error BakedLightBaker::transfer_to_lightmaps() {
+
+ if (!triangles.size() || baked_textures.size()==0)
+ return ERR_UNCONFIGURED;
+
+ EditorProgress ep("transfer_to_lightmaps",TTR("Transfer to Lightmaps:"),baked_textures.size()*2+triangles.size());
+
+ for(int i=0;i<baked_textures.size();i++) {
+
+ ERR_FAIL_COND_V( baked_textures[i].width<=0 || baked_textures[i].height<=0,ERR_UNCONFIGURED );
+
+ baked_textures[i].data.resize( baked_textures[i].width*baked_textures[i].height*4 );
+ zeromem(baked_textures[i].data.ptr(),baked_textures[i].data.size());
+ ep.step(TTR("Allocating Texture #")+itos(i+1),i);
+ }
+
+ Vector<double> norm_arr;
+ norm_arr.resize(lights.size());
+
+ for(int i=0;i<lights.size();i++) {
+ norm_arr[i] = 1.0/get_normalization(i);
+ }
+ float gamma = baked_light->get_gamma_adjust();
+ float mult = baked_light->get_energy_multiplier();
+
+ for(int i=0;i<triangles.size();i++) {
+
+ if (i%200==0) {
+ ep.step(TTR("Baking Triangle #")+itos(i),i+baked_textures.size());
+ }
+ Triangle &t=triangles[i];
+ if (t.baked_texture<0 || t.baked_texture>=baked_textures.size())
+ continue;
+
+ BakeTexture &bt=baked_textures[t.baked_texture];
+ Vector3 normal = Plane(t.vertices[0],t.vertices[1],t.vertices[2]).normal;
+
+
+ int x[3];
+ int y[3];
+
+ Vector3 vertices[3]={
+ t.vertices[0],
+ t.vertices[1],
+ t.vertices[2]
+ };
+
+ for(int j=0;j<3;j++) {
+
+ x[j]=t.bake_uvs[j].x*bt.width;
+ y[j]=t.bake_uvs[j].y*bt.height;
+ x[j]=CLAMP(x[j],0,bt.width-1);
+ y[j]=CLAMP(y[j],0,bt.height-1);
+ }
+
+
+ {
+
+ // sort the points vertically
+ if (y[1] > y[2]) {
+ SWAP(x[1], x[2]);
+ SWAP(y[1], y[2]);
+ SWAP(vertices[1],vertices[2]);
+ }
+ if (y[0] > y[1]) {
+ SWAP(x[0], x[1]);
+ SWAP(y[0], y[1]);
+ SWAP(vertices[0],vertices[1]);
+ }
+ if (y[1] > y[2]) {
+ SWAP(x[1], x[2]);
+ SWAP(y[1], y[2]);
+ SWAP(vertices[1],vertices[2]);
+ }
+
+ double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1);
+ double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1);
+ double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1);
+ double xf = x[0];
+ double xt = x[0] + dx_upper; // if y[0] == y[1], special case
+ for (int yi = y[0]; yi <= (y[2] > bt.height-1 ? bt.height-1 : y[2]); yi++)
+ {
+ if (yi >= 0) {
+ for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < bt.width ? xt : bt.width-1) ; xi++) {
+ //pixels[int(x + y * width)] = color;
+
+ Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
+ Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
+ //vertices[2] - vertices[0];
+ Vector2 v2 = Vector2(xi-x[0],yi-y[0]);
+ float d00 = v0.dot( v0);
+ float d01 = v0.dot( v1);
+ float d11 = v1.dot( v1);
+ float d20 = v2.dot( v0);
+ float d21 = v2.dot( v1);
+ float denom = (d00 * d11 - d01 * d01);
+ Vector3 pos;
+ if (denom==0) {
+ pos=t.vertices[0];
+ } else {
+ float v = (d11 * d20 - d01 * d21) / denom;
+ float w = (d00 * d21 - d01 * d20) / denom;
+ float u = 1.0f - v - w;
+ pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
+ }
+ _plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
+
+ }
+
+ for (int xi = (xf < bt.width ? int(xf) : bt.width-1); xi >= (xt > 0 ? xt : 0); xi--) {
+ //pixels[int(x + y * width)] = color;
+ Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
+ Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
+ //vertices[2] - vertices[0];
+ Vector2 v2 = Vector2(xi-x[0],yi-y[0]);
+ float d00 = v0.dot( v0);
+ float d01 = v0.dot( v1);
+ float d11 = v1.dot( v1);
+ float d20 = v2.dot( v0);
+ float d21 = v2.dot( v1);
+ float denom = (d00 * d11 - d01 * d01);
+ Vector3 pos;
+ if (denom==0) {
+ pos=t.vertices[0];
+ } else {
+ float v = (d11 * d20 - d01 * d21) / denom;
+ float w = (d00 * d21 - d01 * d20) / denom;
+ float u = 1.0f - v - w;
+ pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
+ }
+
+ _plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
+
+ }
+ }
+ xf += dx_far;
+ if (yi < y[1])
+ xt += dx_upper;
+ else
+ xt += dx_low;
+ }
+ }
+
+ }
+
+
+ for(int i=0;i<baked_textures.size();i++) {
+
+
+ {
+
+ ep.step(TTR("Post-Processing Texture #")+itos(i),i+baked_textures.size()+triangles.size());
+
+ BakeTexture &bt=baked_textures[i];
+
+ Vector<uint8_t> copy_data=bt.data;
+ uint8_t *data=bt.data.ptr();
+ const int max_radius=8;
+ const int shadow_radius=2;
+ const int max_dist=0x7FFFFFFF;
+
+ for(int x=0;x<bt.width;x++) {
+
+ for(int y=0;y<bt.height;y++) {
+
+
+ uint8_t a = copy_data[(y*bt.width+x)*4+3];
+
+ if (a>0) {
+ //blur shadow
+
+ int from_x = MAX(0,x-shadow_radius);
+ int to_x = MIN(bt.width-1,x+shadow_radius);
+ int from_y = MAX(0,y-shadow_radius);
+ int to_y = MIN(bt.height-1,y+shadow_radius);
+
+ int sum=0;
+ int sumc=0;
+
+ for(int k=from_y;k<=to_y;k++) {
+ for(int l=from_x;l<=to_x;l++) {
+
+ const uint8_t * rp = &copy_data[(k*bt.width+l)<<2];
+
+ sum+=rp[3];
+ sumc++;
+ }
+ }
+
+ sum/=sumc;
+ data[(y*bt.width+x)*4+3]=sum;
+
+ } else {
+
+ int closest_dist=max_dist;
+ uint8_t closest_color[4];
+
+ int from_x = MAX(0,x-max_radius);
+ int to_x = MIN(bt.width-1,x+max_radius);
+ int from_y = MAX(0,y-max_radius);
+ int to_y = MIN(bt.height-1,y+max_radius);
+
+ for(int k=from_y;k<=to_y;k++) {
+ for(int l=from_x;l<=to_x;l++) {
+
+ int dy = y-k;
+ int dx = x-l;
+ int dist = dy*dy+dx*dx;
+ if (dist>=closest_dist)
+ continue;
+
+ const uint8_t * rp = &copy_data[(k*bt.width+l)<<2];
+
+ if (rp[3]==0)
+ continue;
+
+ closest_dist=dist;
+ closest_color[0]=rp[0];
+ closest_color[1]=rp[1];
+ closest_color[2]=rp[2];
+ closest_color[3]=rp[3];
+ }
+ }
+
+
+ if (closest_dist!=max_dist) {
+
+ data[(y*bt.width+x)*4+0]=closest_color[0];
+ data[(y*bt.width+x)*4+1]=closest_color[1];
+ data[(y*bt.width+x)*4+2]=closest_color[2];
+ data[(y*bt.width+x)*4+3]=closest_color[3];
+ }
+ }
+ }
+ }
+ }
+
+ PoolVector<uint8_t> dv;
+ dv.resize(baked_textures[i].data.size());
+ {
+ PoolVector<uint8_t>::Write w = dv.write();
+ copymem(w.ptr(),baked_textures[i].data.ptr(),baked_textures[i].data.size());
+ }
+
+ Image img(baked_textures[i].width,baked_textures[i].height,0,Image::FORMAT_RGBA8,dv);
+ Ref<ImageTexture> tex = memnew( ImageTexture );
+ tex->create_from_image(img);
+ baked_light->set_lightmap_texture(i,tex);
+ }
+
+
+ return OK;
+}
+
+void BakedLightBaker::clear() {
+
+
+
+ _stop_thread();
+
+ if (bvh)
+ _free_bvh(bvh);
+
+ if (ray_stack)
+ memdelete_arr(ray_stack);
+ if (octant_stack)
+ memdelete_arr(octant_stack);
+ if (octantptr_stack)
+ memdelete_arr(octantptr_stack);
+ if (bvh_stack)
+ memdelete_arr(bvh_stack);
+/*
+ * ???
+ for(int i=0;i<octant_pool.size();i++) {
+ /*
+ if (octant_pool[i].leaf) {
+ memdelete_arr( octant_pool[i].light );
+ }
+ Vector<double> norm_arr;
+ norm_arr.resize(lights.size());
+ */
+
+ for(int i=0;i<lights.size();i++) {
+ norm_arr[i] = 1.0/get_normalization(i);
+ }
+
+ const double *normptr=norm_arr.ptr();
+ }
+*/
+ octant_pool.clear();
+ octant_pool_size=0;
+ bvh=NULL;
+ leaf_list=0;
+ cell_count=0;
+ ray_stack=NULL;
+ octant_stack=NULL;
+ octantptr_stack=NULL;
+ bvh_stack=NULL;
+ materials.clear();
+ materials.clear();
+ textures.clear();
+ lights.clear();
+ triangles.clear();
+ endpoint_normal.clear();
+ endpoint_normal_bits.clear();
+ baked_octree_texture_w=0;
+ baked_octree_texture_h=0;
+ paused=false;
+ baking=false;
+
+ bake_thread_exit=false;
+ first_bake_to_map=true;
+ baked_light=Ref<BakedLight>();
+ total_rays=0;
+
+}
+
+BakedLightBaker::BakedLightBaker() {
+ octree_depth=9;
+ lattice_size=4;
+ octant_pool.clear();
+ octant_pool_size=0;
+ bvh=NULL;
+ leaf_list=0;
+ cell_count=0;
+ ray_stack=NULL;
+ bvh_stack=NULL;
+ octant_stack=NULL;
+ octantptr_stack=NULL;
+ plot_size=2.5;
+ max_bounces=2;
+ materials.clear();
+ baked_octree_texture_w=0;
+ baked_octree_texture_h=0;
+ paused=false;
+ baking=false;
+
+ bake_thread_exit=false;
+ total_rays=0;
+ first_bake_to_map=true;
+ linear_color=false;
+
+}
+
+BakedLightBaker::~BakedLightBaker() {
+
+ clear();
+}
+#endif
diff --git a/tools/editor/plugins/baked_light_baker.h b/editor/plugins/baked_light_baker.h
index 89788338d9..89788338d9 100644
--- a/tools/editor/plugins/baked_light_baker.h
+++ b/editor/plugins/baked_light_baker.h
diff --git a/tools/editor/plugins/baked_light_baker_cmpxchg.cpp b/editor/plugins/baked_light_baker_cmpxchg.cpp
index 5e9228b7de..5e9228b7de 100644
--- a/tools/editor/plugins/baked_light_baker_cmpxchg.cpp
+++ b/editor/plugins/baked_light_baker_cmpxchg.cpp
diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/editor/plugins/baked_light_editor_plugin.cpp
index 6a7e708b85..6a7e708b85 100644
--- a/tools/editor/plugins/baked_light_editor_plugin.cpp
+++ b/editor/plugins/baked_light_editor_plugin.cpp
diff --git a/editor/plugins/baked_light_editor_plugin.h b/editor/plugins/baked_light_editor_plugin.h
new file mode 100644
index 0000000000..a71de12bcc
--- /dev/null
+++ b/editor/plugins/baked_light_editor_plugin.h
@@ -0,0 +1,120 @@
+/*************************************************************************/
+/* baked_light_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 BAKED_LIGHT_EDITOR_PLUGIN_H
+#define BAKED_LIGHT_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "editor/plugins/baked_light_baker.h"
+#include "scene/gui/spin_box.h"
+
+
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+#if 0
+
+class MeshInstance;
+
+class BakedLightEditor : public Control {
+
+ GDCLASS(BakedLightEditor, Control );
+
+
+ float update_timeout;
+ PoolVector<uint8_t> octree_texture;
+ PoolVector<uint8_t> light_texture;
+ PoolVector<int> octree_sampler;
+
+ BakedLightBaker *baker;
+ AcceptDialog *err_dialog;
+
+ HBoxContainer *bake_hbox;
+ Button *button_bake;
+ Button *button_reset;
+ Button *button_make_lightmaps;
+ Label *bake_info;
+
+ uint64_t last_rays_time;
+
+
+
+ BakedLightInstance *node;
+
+ enum Menu {
+
+ MENU_OPTION_BAKE,
+ MENU_OPTION_CLEAR
+ };
+
+ void _bake_lightmaps();
+
+ void _bake_pressed();
+ void _clear_pressed();
+
+ void _end_baking();
+ void _menu_option(int);
+
+friend class BakedLightEditorPlugin;
+protected:
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+ void _notification(int p_what);
+public:
+
+ void edit(BakedLightInstance *p_baked_light);
+ BakedLightEditor();
+ ~BakedLightEditor();
+};
+
+class BakedLightEditorPlugin : public EditorPlugin {
+
+ GDCLASS( BakedLightEditorPlugin, EditorPlugin );
+
+ BakedLightEditor *baked_light_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "BakedLight"; }
+ 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);
+
+ BakedLightEditorPlugin(EditorNode *p_node);
+ ~BakedLightEditorPlugin();
+
+};
+
+#endif // MULTIMESH_EDITOR_PLUGIN_H
+#endif
+
diff --git a/editor/plugins/camera_editor_plugin.cpp b/editor/plugins/camera_editor_plugin.cpp
new file mode 100644
index 0000000000..7073acd2c0
--- /dev/null
+++ b/editor/plugins/camera_editor_plugin.cpp
@@ -0,0 +1,150 @@
+/*************************************************************************/
+/* camera_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "camera_editor_plugin.h"
+
+#include "spatial_editor_plugin.h"
+
+
+void CameraEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+/* case NOTIFICATION_PROCESS: {
+
+ if (preview->is_pressed() && node)
+ node->call("make_current");
+
+ } break;*/
+ }
+
+}
+void CameraEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ SpatialEditor::get_singleton()->set_custom_camera(NULL);
+ hide();
+ }
+
+}
+
+void CameraEditor::_pressed() {
+
+ Node *sn = (node && preview->is_pressed())?node:NULL;
+ SpatialEditor::get_singleton()->set_custom_camera(sn);
+}
+
+void CameraEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_pressed"),&CameraEditor::_pressed);
+
+}
+
+void CameraEditor::edit(Node *p_camera) {
+
+ node=p_camera;
+
+ if (!node) {
+ preview->set_pressed(false);
+ SpatialEditor::get_singleton()->set_custom_camera(NULL);
+ } else {
+
+ if (preview->is_pressed())
+ SpatialEditor::get_singleton()->set_custom_camera(p_camera);
+ else
+ SpatialEditor::get_singleton()->set_custom_camera(NULL);
+ }
+}
+
+
+CameraEditor::CameraEditor() {
+
+ preview = memnew( Button );
+ add_child(preview);
+
+ preview->set_text(TTR("Preview"));
+ preview->set_toggle_mode(true);
+ preview->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
+ preview->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
+ preview->set_margin(MARGIN_LEFT,60);
+ preview->set_margin(MARGIN_RIGHT,0);
+ preview->set_margin(MARGIN_TOP,0);
+ preview->set_margin(MARGIN_BOTTOM,10);
+ preview->connect("pressed",this,"_pressed");
+
+}
+
+
+void CameraEditorPlugin::edit(Object *p_object) {
+
+ SpatialEditor::get_singleton()->set_can_preview(p_object->cast_to<Camera>());
+ //camera_editor->edit(p_object->cast_to<Node>());
+}
+
+bool CameraEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Camera");
+}
+
+void CameraEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ //SpatialEditor::get_singleton()->set_can_preview(p_object->cast_to<Camera>());
+ } else {
+ SpatialEditor::get_singleton()->set_can_preview(NULL);
+ }
+
+}
+
+CameraEditorPlugin::CameraEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+/* camera_editor = memnew( CameraEditor );
+ editor->get_viewport()->add_child(camera_editor);
+
+ camera_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
+ camera_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
+ camera_editor->set_margin(MARGIN_LEFT,60);
+ camera_editor->set_margin(MARGIN_RIGHT,0);
+ camera_editor->set_margin(MARGIN_TOP,0);
+ camera_editor->set_margin(MARGIN_BOTTOM,10);
+
+
+ camera_editor->hide();
+*/
+
+
+}
+
+
+CameraEditorPlugin::~CameraEditorPlugin()
+{
+}
+
+
diff --git a/editor/plugins/camera_editor_plugin.h b/editor/plugins/camera_editor_plugin.h
new file mode 100644
index 0000000000..b5817b9960
--- /dev/null
+++ b/editor/plugins/camera_editor_plugin.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* camera_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 CAMERA_EDITOR_PLUGIN_H
+#define CAMERA_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/3d/camera.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class CameraEditor : public Control {
+
+ GDCLASS(CameraEditor, Control );
+
+ Panel *panel;
+ Button * preview;
+ Node *node;
+
+ void _pressed();
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(Node *p_camera);
+ CameraEditor();
+};
+
+class CameraEditorPlugin : public EditorPlugin {
+
+ GDCLASS( CameraEditorPlugin, EditorPlugin );
+
+ //CameraEditor *camera_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "Camera"; }
+ 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);
+
+ CameraEditorPlugin(EditorNode *p_node);
+ ~CameraEditorPlugin();
+
+};
+
+#endif // CAMERA_EDITOR_PLUGIN_H
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
new file mode 100644
index 0000000000..1a0791d864
--- /dev/null
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -0,0 +1,4063 @@
+/*************************************************************************/
+/* canvas_item_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "canvas_item_editor_plugin.h"
+
+#include "print_string.h"
+#include "editor/editor_node.h"
+#include "os/keyboard.h"
+#include "scene/main/viewport.h"
+#include "scene/main/canvas_layer.h"
+#include "scene/2d/sprite.h"
+#include "scene/2d/light_2d.h"
+#include "scene/2d/particles_2d.h"
+#include "scene/2d/polygon_2d.h"
+#include "scene/2d/screen_button.h"
+#include "global_config.h"
+#include "os/input.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/grid_container.h"
+#include "scene/gui/patch_9_rect.h"
+#include "editor/animation_editor.h"
+#include "editor/plugins/animation_player_editor_plugin.h"
+#include "editor/script_editor_debugger.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "scene/resources/packed_scene.h"
+
+
+#define MIN_ZOOM 0.01
+#define MAX_ZOOM 100
+
+
+class SnapDialog : public ConfirmationDialog {
+
+ GDCLASS(SnapDialog,ConfirmationDialog);
+
+friend class CanvasItemEditor;
+
+ SpinBox *grid_offset_x;
+ SpinBox *grid_offset_y;
+ SpinBox *grid_step_x;
+ SpinBox *grid_step_y;
+ SpinBox *rotation_offset;
+ SpinBox *rotation_step;
+
+public:
+ SnapDialog() : ConfirmationDialog() {
+ const int SPIN_BOX_GRID_RANGE = 256;
+ const int SPIN_BOX_ROTATION_RANGE = 360;
+ Label *label;
+ VBoxContainer *container;
+ GridContainer *child_container;
+
+ set_title(TTR("Configure Snap"));
+ get_ok()->set_text(TTR("Close"));
+
+ container = memnew( VBoxContainer );
+ add_child(container);
+ //set_child_rect(container);
+
+ child_container = memnew( GridContainer );
+ child_container->set_columns(3);
+ container->add_child(child_container);
+
+ label = memnew( Label );
+ label->set_text(TTR("Grid Offset:"));
+ child_container->add_child(label);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ grid_offset_x = memnew( SpinBox );
+ grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_x->set_suffix("px");
+ child_container->add_child(grid_offset_x);
+
+ grid_offset_y = memnew( SpinBox );
+ grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_offset_y->set_suffix("px");
+ child_container->add_child(grid_offset_y);
+
+ label = memnew( Label );
+ label->set_text(TTR("Grid Step:"));
+ child_container->add_child(label);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ grid_step_x = memnew( SpinBox );
+ grid_step_x->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_x->set_suffix("px");
+ child_container->add_child(grid_step_x);
+
+ grid_step_y = memnew( SpinBox );
+ grid_step_y->set_min(-SPIN_BOX_GRID_RANGE);
+ grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
+ grid_step_y->set_suffix("px");
+ child_container->add_child(grid_step_y);
+
+ container->add_child( memnew( HSeparator ) );
+
+ child_container = memnew( GridContainer );
+ child_container->set_columns(2);
+ container->add_child(child_container);
+
+ label = memnew( Label );
+ label->set_text(TTR("Rotation Offset:"));
+ child_container->add_child(label);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ rotation_offset = memnew( SpinBox );
+ rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
+ rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
+ rotation_offset->set_suffix("deg");
+ child_container->add_child(rotation_offset);
+
+ label = memnew( Label );
+ label->set_text(TTR("Rotation Step:"));
+ child_container->add_child(label);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ rotation_step = memnew( SpinBox );
+ rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
+ rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
+ rotation_step->set_suffix("deg");
+ child_container->add_child(rotation_step);
+ }
+
+ void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
+ grid_offset_x->set_value(p_grid_offset.x);
+ grid_offset_y->set_value(p_grid_offset.y);
+ grid_step_x->set_value(p_grid_step.x);
+ grid_step_y->set_value(p_grid_step.y);
+ rotation_offset->set_value(p_rotation_offset * (180 / Math_PI));
+ rotation_step->set_value(p_rotation_step * (180 / Math_PI));
+ }
+
+ void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
+ p_grid_offset.x = grid_offset_x->get_value();
+ p_grid_offset.y = grid_offset_y->get_value();
+ p_grid_step.x = grid_step_x->get_value();
+ p_grid_step.y = grid_step_y->get_value();
+ p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI);
+ p_rotation_step = rotation_step->get_value() / (180 / Math_PI);
+ }
+};
+
+void CanvasItemEditor::_edit_set_pivot(const Vector2& mouse_pos) {
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ undo_redo->create_action(TTR("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_position();
+
+ 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_position());
+ undo_redo->add_undo_method(n2dc,"set_global_pos",n2dc->get_global_position());
+
+ }
+
+ }
+
+ }
+
+ undo_redo->commit_action();
+
+}
+
+void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
+
+ if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
+ return;
+
+ if (p_ev.key.mod.control)
+ return;
+
+ if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode==KEY_V && drag==DRAG_NONE && can_move_pivot) {
+
+ if (p_ev.key.mod.shift) {
+ //move drag pivot
+ drag=DRAG_PIVOT;
+ } else if (!Input::get_singleton()->is_mouse_button_pressed(0)) {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ Vector2 mouse_pos = viewport->get_local_mouse_pos();
+ if (selection.size() && viewport->get_rect().has_point(mouse_pos)) {
+ //just in case, make it work if over viewport
+ mouse_pos=transform.affine_inverse().xform(mouse_pos);
+ mouse_pos=snap_point(mouse_pos);
+
+ _edit_set_pivot(mouse_pos);
+ }
+
+ }
+ }
+
+}
+
+void CanvasItemEditor::_tool_select(int p_index) {
+
+
+ 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);
+ }
+
+
+ viewport->update();
+ tool=(Tool)p_index;
+
+}
+
+Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
+
+ CanvasItem *ci = p_what->cast_to<CanvasItem>();
+ if (!ci)
+ return NULL;
+
+ return memnew( CanvasItemEditorSelectedItem );
+}
+
+inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) {
+ float offset = p_snap_relative ? p_start : p_offset;
+ return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target;
+}
+
+Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const {
+ if (snap_grid) {
+ p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x);
+ p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y);
+ }
+ if (snap_pixel)
+ p_target = p_target.snapped(Size2(1, 1));
+
+ return p_target;
+}
+
+float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
+ return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target;
+}
+
+Dictionary CanvasItemEditor::get_state() const {
+
+ Dictionary state;
+ state["zoom"]=zoom;
+ state["ofs"]=Point2(h_scroll->get_value(),v_scroll->get_value());
+ //state["ofs"]=-transform.get_origin();
+ state["snap_offset"]=snap_offset;
+ state["snap_step"]=snap_step;
+ state["snap_rotation_offset"]=snap_rotation_offset;
+ state["snap_rotation_step"]=snap_rotation_step;
+ state["snap_grid"]=snap_grid;
+ state["snap_show_grid"]=snap_show_grid;
+ state["snap_rotation"]=snap_rotation;
+ state["snap_relative"]=snap_relative;
+ state["snap_pixel"]=snap_pixel;
+ state["skeleton_show_bones"]=skeleton_show_bones;
+ return state;
+}
+void CanvasItemEditor::set_state(const Dictionary& p_state){
+
+ Dictionary state=p_state;
+ if (state.has("zoom")) {
+ zoom=p_state["zoom"];
+ }
+
+ if (state.has("ofs")) {
+ _update_scrollbars(); // i wonder how safe is calling this here..
+ Point2 ofs=p_state["ofs"];
+ h_scroll->set_value(ofs.x);
+ v_scroll->set_value(ofs.y);
+ }
+
+ if (state.has("snap_step")) {
+ snap_step=state["snap_step"];
+ }
+
+ if (state.has("snap_offset")) {
+ snap_offset=state["snap_offset"];
+ }
+
+ if (state.has("snap_rotation_step")) {
+ snap_rotation_step=state["snap_rotation_step"];
+ }
+
+ if (state.has("snap_rotation_offset")) {
+ snap_rotation_offset=state["snap_rotation_offset"];
+ }
+
+ if (state.has("snap_grid")) {
+ snap_grid=state["snap_grid"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
+ edit_menu->get_popup()->set_item_checked(idx,snap_grid);
+ }
+
+ if (state.has("snap_show_grid")) {
+ snap_show_grid=state["snap_show_grid"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
+ edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
+ }
+
+ if (state.has("snap_rotation")) {
+ snap_rotation=state["snap_rotation"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+ edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
+ }
+
+ if (state.has("snap_relative")) {
+ snap_relative=state["snap_relative"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+ edit_menu->get_popup()->set_item_checked(idx,snap_relative);
+ }
+
+ if (state.has("snap_pixel")) {
+ snap_pixel=state["snap_pixel"];
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
+ edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
+ }
+
+ if (state.has("skeleton_show_bones")) {
+ skeleton_show_bones=state["skeleton_show_bones"];
+ int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES);
+ skeleton_menu->set_item_checked(idx,skeleton_show_bones);
+ }
+}
+
+
+void CanvasItemEditor::_add_canvas_item(CanvasItem *p_canvas_item) {
+
+ editor_selection->add_node(p_canvas_item);
+#if 0
+ if (canvas_items.has(p_canvas_item))
+ return;
+
+ canvas_items.insert(p_canvas_item,p_info);
+ p_canvas_item->connect("hide",this,"_visibility_changed",varray(p_canvas_item->get_instance_ID()),CONNECT_ONESHOT);
+#endif
+}
+
+void CanvasItemEditor::_remove_canvas_item(CanvasItem *p_canvas_item) {
+
+ editor_selection->remove_node(p_canvas_item);
+#if 0
+ p_canvas_item->disconnect("hide",this,"_visibility_changed");
+ canvas_items.erase(p_canvas_item);
+#endif
+
+}
+void CanvasItemEditor::_clear_canvas_items() {
+
+ editor_selection->clear();
+#if 0
+ while(canvas_items.size())
+ _remove_canvas_item(canvas_items.front()->key());
+#endif
+}
+
+void CanvasItemEditor::_visibility_changed(ObjectID p_canvas_item) {
+#if 0
+ Object *c = ObjectDB::get_instance(p_canvas_item);
+ if (!c)
+ return;
+ CanvasItem *ct = c->cast_to<CanvasItem>();
+ if (!ct)
+ return;
+ canvas_items.erase(ct);
+ //_remove_canvas_item(ct);
+ update();
+#endif
+}
+
+
+void CanvasItemEditor::_node_removed(Node *p_node) {
+#if 0
+ CanvasItem *canvas_item = (CanvasItem*)p_node; //not a good cast, but safe
+ if (canvas_items.has(canvas_item))
+ _remove_canvas_item(canvas_item);
+
+ update();
+#endif
+}
+
+void CanvasItemEditor::_keying_changed() {
+
+ if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible_in_tree())
+ animation_hb->show();
+ else
+ animation_hb->hide();
+}
+
+bool CanvasItemEditor::_is_part_of_subscene(CanvasItem *p_item) {
+
+ Node* scene_node = get_tree()->get_edited_scene_root();
+ Node* item_owner = p_item->get_owner();
+
+ return item_owner && item_owner!=scene_node && p_item!=scene_node && item_owner->get_filename()!="";
+}
+
+// slow but modern computers should have no problem
+CanvasItem* CanvasItemEditor::_select_canvas_item_at_pos(const Point2& p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform) {
+
+ if (!p_node)
+ return NULL;
+ if (p_node->cast_to<Viewport>())
+ return NULL;
+
+ CanvasItem *c=p_node->cast_to<CanvasItem>();
+
+
+ for (int i=p_node->get_child_count()-1;i>=0;i--) {
+
+ CanvasItem *r=NULL;
+
+ if (c && !c->is_set_as_toplevel())
+ r=_select_canvas_item_at_pos(p_pos,p_node->get_child(i),p_parent_xform * c->get_transform(),p_canvas_xform);
+ else {
+ CanvasLayer *cl = p_node->cast_to<CanvasLayer>();
+ r=_select_canvas_item_at_pos(p_pos,p_node->get_child(i),transform ,cl ? cl->get_transform() : p_canvas_xform); //use base transform
+ }
+
+ if (r)
+ return r;
+ }
+
+ if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !_is_part_of_subscene(c) && !c->cast_to<CanvasLayer>()) {
+
+ Rect2 rect = c->get_item_rect();
+ Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos);
+
+
+ if (rect.has_point(local_pos))
+ return c;
+
+ }
+
+ return NULL;
+}
+
+void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform, Vector<_SelectResult> &r_items) {
+ if (!p_node)
+ return;
+ if (p_node->cast_to<Viewport>())
+ return;
+
+ CanvasItem *c=p_node->cast_to<CanvasItem>();
+
+ for (int i=p_node->get_child_count()-1;i>=0;i--) {
+
+ if (c && !c->is_set_as_toplevel())
+ _find_canvas_items_at_pos(p_pos,p_node->get_child(i),p_parent_xform * c->get_transform(),p_canvas_xform, r_items);
+ else {
+ CanvasLayer *cl = p_node->cast_to<CanvasLayer>();
+ _find_canvas_items_at_pos(p_pos,p_node->get_child(i),transform ,cl ? cl->get_transform() : p_canvas_xform, r_items); //use base transform
+ }
+ }
+
+
+ if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !c->cast_to<CanvasLayer>()) {
+
+ Rect2 rect = c->get_item_rect();
+ Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos);
+
+
+ if (rect.has_point(local_pos)) {
+ Node2D *node=c->cast_to<Node2D>();
+
+ _SelectResult res;
+ res.item=c;
+ res.z=node?node->get_z():0;
+ res.has_z=node;
+ r_items.push_back(res);
+ }
+
+ }
+
+ return;
+}
+
+void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform,List<CanvasItem*> *r_items) {
+
+ if (!p_node)
+ return;
+ if (p_node->cast_to<Viewport>())
+ return;
+
+ CanvasItem *c=p_node->cast_to<CanvasItem>();
+
+
+ bool inherited=p_node!=get_tree()->get_edited_scene_root() && p_node->get_filename()!="";
+ bool editable=false;
+ if (inherited){
+ editable=EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
+ }
+ bool lock_children=p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
+ if (!lock_children && (!inherited || editable)) {
+ for (int i=p_node->get_child_count()-1;i>=0;i--) {
+
+ if (c && !c->is_set_as_toplevel())
+ _find_canvas_items_at_rect(p_rect,p_node->get_child(i),p_parent_xform * c->get_transform(),p_canvas_xform,r_items);
+ else {
+ CanvasLayer *cl = p_node->cast_to<CanvasLayer>();
+ _find_canvas_items_at_rect(p_rect,p_node->get_child(i),transform,cl?cl->get_transform():p_canvas_xform,r_items);
+ }
+ }
+ }
+
+ if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !c->cast_to<CanvasLayer>()) {
+
+ Rect2 rect = c->get_item_rect();
+ Transform2D xform = p_parent_xform * p_canvas_xform * c->get_transform();
+
+ if ( p_rect.has_point( xform.xform( rect.pos ) ) &&
+ p_rect.has_point( xform.xform( rect.pos+Vector2(rect.size.x,0) ) ) &&
+ p_rect.has_point( xform.xform( rect.pos+Vector2(rect.size.x,rect.size.y) ) ) &&
+ p_rect.has_point( xform.xform( rect.pos+Vector2(0,rect.size.y) ) ) ) {
+
+ r_items->push_back(c);
+
+ }
+ }
+
+
+}
+
+bool CanvasItemEditor::_select(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag) {
+
+ if (p_append) {
+ //additive selection
+
+ if (!item) {
+
+ if (p_drag) {
+ drag_from=transform.affine_inverse().xform(p_click_pos);
+
+ box_selecting=true;
+ box_selecting_to=drag_from;
+ }
+
+ return false; //nothing to add
+ }
+
+ if (editor_selection->is_selected(item)) {
+ //already in here, erase it
+ editor_selection->remove_node(item);
+ //_remove_canvas_item(c);
+
+ viewport->update();
+ return false;
+
+ }
+ _append_canvas_item(item);
+ viewport->update();
+
+ return true;
+
+ } else {
+ //regular selection
+
+ if (!item) {
+ //clear because nothing clicked
+ editor_selection->clear();
+
+ if (p_drag) {
+ drag_from=transform.affine_inverse().xform(p_click_pos);
+
+ box_selecting=true;
+ box_selecting_to=drag_from;
+ }
+
+ viewport->update();
+ return false;
+ }
+
+ if (!editor_selection->is_selected(item)) {
+ //select a new one and clear previous selection
+ editor_selection->clear();
+ editor_selection->add_node(item);
+ //reselect
+ if (get_tree()->is_editor_hint()) {
+ editor->call("edit_node",item);
+ }
+
+ }
+
+ if (p_drag) {
+ //prepare to move!
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+ se->undo_state=canvas_item->edit_get_state();
+ if (canvas_item->cast_to<Node2D>())
+ se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
+
+ }
+
+ drag=DRAG_ALL;
+ drag_from=transform.affine_inverse().xform(p_click_pos);
+ drag_point_from=_find_topleftmost_point();
+ }
+
+ viewport->update();
+
+ return true;
+
+ }
+}
+
+void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE p_move_mode) {
+
+
+ if (drag!=DRAG_NONE)
+ return;
+
+ if (editor_selection->get_selected_node_list().empty())
+ return;
+
+ undo_redo->create_action(TTR("Move Action"),UndoRedo::MERGE_ENDS);
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+ if (canvas_item->has_meta("_edit_lock_"))
+ continue;
+
+
+ Vector2 drag = p_dir;
+ if (p_snap)
+ drag*=snap_step;
+
+ undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state());
+
+ if (p_move_mode == MOVE_VIEW_BASE) {
+
+ // drag = transform.affine_inverse().basis_xform(p_dir); // zoom sensitive
+ drag = canvas_item->get_global_transform_with_canvas().affine_inverse().basis_xform(drag);
+ Rect2 local_rect = canvas_item->get_item_rect();
+ local_rect.pos+=drag;
+ undo_redo->add_do_method(canvas_item,"edit_set_rect",local_rect);
+
+ } else { // p_move_mode==MOVE_LOCAL_BASE || p_move_mode==MOVE_LOCAL_WITH_ROT
+
+ if (Node2D *node_2d = canvas_item->cast_to<Node2D>()) {
+
+ if (p_move_mode == MOVE_LOCAL_WITH_ROT) {
+ Transform2D m;
+ m.rotate( node_2d->get_rotation() );
+ drag = m.xform(drag);
+ }
+ node_2d->set_position(node_2d->get_position() + drag);
+
+ } else if (Control *control = canvas_item->cast_to<Control>()) {
+
+ control->set_pos(control->get_pos()+drag);
+ }
+ }
+ }
+
+ undo_redo->commit_action();
+}
+
+Point2 CanvasItemEditor::_find_topleftmost_point() {
+
+
+
+ Vector2 tl=Point2(1e10,1e10);
+ Rect2 r2;
+ r2.pos=tl;
+
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+
+
+
+ Rect2 rect=canvas_item->get_item_rect();
+ Transform2D xform=canvas_item->get_global_transform_with_canvas();
+
+ r2.expand_to(xform.xform(rect.pos));
+ r2.expand_to(xform.xform(rect.pos+Vector2(rect.size.x,0)));
+ r2.expand_to(xform.xform(rect.pos+rect.size));
+ r2.expand_to(xform.xform(rect.pos+Vector2(0,rect.size.y)));
+
+ }
+
+ return r2.pos;
+}
+
+
+
+int CanvasItemEditor::get_item_count() {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ int ic=0;
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ ic++;
+ };
+
+ return ic;
+}
+
+CanvasItem *CanvasItemEditor::get_single_item() {
+
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ CanvasItem *single_item=NULL;
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ if (single_item)
+ return NULL; //morethan one
+
+ single_item=canvas_item;
+ };
+
+ return single_item;
+}
+
+CanvasItemEditor::DragType CanvasItemEditor::_find_drag_type(const Transform2D& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point) {
+
+ CanvasItem *canvas_item = get_single_item();
+
+ ERR_FAIL_COND_V(!canvas_item,DRAG_NONE);
+
+ Rect2 rect=canvas_item->get_item_rect();
+ Transform2D xforml=canvas_item->get_global_transform_with_canvas();
+ Transform2D xform=transform * xforml;
+
+ Vector2 endpoints[4]={
+
+ xform.xform(rect.pos),
+ xform.xform(rect.pos+Vector2(rect.size.x,0)),
+ xform.xform(rect.pos+rect.size),
+ xform.xform(rect.pos+Vector2(0,rect.size.y))
+ };
+
+ Vector2 endpointsl[4]={
+
+ xforml.xform(rect.pos),
+ xforml.xform(rect.pos+Vector2(rect.size.x,0)),
+ xforml.xform(rect.pos+rect.size),
+ xforml.xform(rect.pos+Vector2(0,rect.size.y))
+ };
+
+ DragType dragger[]={
+ DRAG_TOP_LEFT,
+ DRAG_TOP,
+ DRAG_TOP_RIGHT,
+ DRAG_RIGHT,
+ DRAG_BOTTOM_RIGHT,
+ DRAG_BOTTOM,
+ DRAG_BOTTOM_LEFT,
+ DRAG_LEFT
+ };
+
+ float radius = (select_handle->get_size().width/2)*1.5;
+
+ //try draggers
+
+ for(int i=0;i<4;i++) {
+
+ int prev = (i+3)%4;
+ int next = (i+1)%4;
+
+ r_point=endpointsl[i];
+
+ Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
+ ofs*=1.4144*(select_handle->get_size().width/2);
+
+ ofs+=endpoints[i];
+
+ if (ofs.distance_to(p_click)<radius)
+ return dragger[i*2];
+
+ ofs = (endpoints[i]+endpoints[next])/2;
+ ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2);
+
+ r_point=(endpointsl[i]+endpointsl[next])/2;
+
+
+ if (ofs.distance_to(p_click)<radius)
+ return dragger[i*2+1];
+
+ }
+
+ /*
+ if (rect.has_point(xform.affine_inverse().xform(p_click))) {
+ r_point=_find_topleftmost_point();
+ return DRAG_ALL;
+ }*/
+
+ //try draggers
+
+ return DRAG_NONE;
+}
+
+void CanvasItemEditor::incbeg(float& beg,float &end, float inc, float minsize,bool p_symmetric) {
+
+ if (minsize<0) {
+
+ beg+=inc;
+ if (p_symmetric)
+ end-=inc;
+ } else {
+
+ if (p_symmetric) {
+ beg+=inc;
+ end-=inc;
+ if (end-beg < minsize) {
+ float center = (beg+end)/2.0;
+ beg=center-minsize/2.0;
+ end=center+minsize/2.0;
+ }
+
+ } else {
+ if (end-(beg+inc) < minsize)
+ beg=end-minsize;
+ else
+ beg+=inc;
+ }
+
+ }
+}
+
+void CanvasItemEditor::incend(float &beg,float& end, float inc, float minsize,bool p_symmetric) {
+
+ if (minsize<0) {
+
+ end+=inc;
+ if (p_symmetric)
+ beg-=inc;
+ } else {
+
+ if (p_symmetric) {
+
+ end+=inc;
+ beg-=inc;
+ if (end-beg < minsize) {
+ float center = (beg+end)/2.0;
+ beg=center-minsize/2.0;
+ end=center+minsize/2.0;
+ }
+
+ } else {
+ if ((end+inc)-beg < minsize)
+ end=beg+minsize;
+ else
+ end+=inc;
+ }
+
+ }
+}
+
+void CanvasItemEditor::_append_canvas_item(CanvasItem *c) {
+
+ editor_selection->add_node(c);
+
+}
+
+
+void CanvasItemEditor::_snap_changed() {
+ ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
+ viewport->update();
+}
+
+void CanvasItemEditor::_dialog_value_changed(double) {
+
+ if (updating_value_dialog)
+ return;
+
+ switch(last_option) {
+
+ case ZOOM_SET: {
+
+ zoom=dialog_val->get_value()/100.0;
+ _update_scroll(0);
+ viewport->update();
+
+ } break;
+ default:{}
+ }
+}
+
+void CanvasItemEditor::_selection_result_pressed(int p_result) {
+
+ if (selection_results.size() <= p_result)
+ return;
+
+ CanvasItem *item=selection_results[p_result].item;
+
+ if (item)
+ _select(item, Point2(), additive_selection, false);
+}
+
+void CanvasItemEditor::_selection_menu_hide() {
+
+ selection_results.clear();
+ selection_menu->clear();
+ selection_menu->set_size(Vector2(0, 0));
+}
+
+bool CanvasItemEditor::get_remove_list(List<Node*> *p_list) {
+
+
+ return false;//!p_list->empty();
+}
+
+
+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,Transform2D(), 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_class(),"EditorIcons")?item->get_class():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_class()+"\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_gui_input(const InputEvent& p_event) {
+
+ {
+
+ EditorNode *en = editor;
+ EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
+
+ if (!over_plugin_list->empty()) {
+ bool discard = over_plugin_list->forward_gui_input(transform,p_event);
+ if (discard) {
+ accept_event();
+ return;
+ }
+ }
+ }
+
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON) {
+
+ const InputEventMouseButton &b=p_event.mouse_button;
+
+
+ if (b.button_index==BUTTON_WHEEL_DOWN) {
+
+ if (zoom<MIN_ZOOM)
+ return;
+
+ float prev_zoom=zoom;
+ zoom=zoom*0.95;
+ {
+ Point2 ofs(b.x,b.y);
+ ofs = ofs/prev_zoom - ofs/zoom;
+ h_scroll->set_value( h_scroll->get_value() + ofs.x );
+ v_scroll->set_value( v_scroll->get_value() + ofs.y );
+ }
+ _update_scroll(0);
+ viewport->update();
+ return;
+ }
+
+ if (b.button_index==BUTTON_WHEEL_UP) {
+
+ if (zoom>MAX_ZOOM)
+ return;
+
+ float prev_zoom=zoom;
+ zoom=zoom*(1.0/0.95);
+ {
+ Point2 ofs(b.x,b.y);
+ ofs = ofs/prev_zoom - ofs/zoom;
+ h_scroll->set_value( h_scroll->get_value() + ofs.x );
+ v_scroll->set_value( v_scroll->get_value() + ofs.y );
+ }
+
+ _update_scroll(0);
+ viewport->update();
+ return;
+ }
+
+ if (b.button_index==BUTTON_RIGHT) {
+
+
+ if (b.pressed && (tool==TOOL_SELECT && b.mod.alt)) {
+
+ _list_select(b);
+ return;
+ }
+
+ if (get_item_count() > 0 && drag!=DRAG_NONE) {
+ //cancel drag
+
+ if (bone_ik_list.size()) {
+
+ for(List<BoneIK>::Element *E=bone_ik_list.back();E;E=E->prev()) {
+
+ E->get().node->edit_set_state(E->get().orig_state);
+ }
+
+ bone_ik_list.clear();
+
+ } else {
+
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+ canvas_item->edit_set_state(se->undo_state);
+ if (canvas_item->cast_to<Node2D>())
+ canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot);
+
+ }
+ }
+
+ drag=DRAG_NONE;
+ viewport->update();
+ can_move_pivot=false;
+
+ } else if (box_selecting) {
+ box_selecting=false;
+ viewport->update();
+ } else if (b.pressed) {
+#if 0
+ ref_item = NULL;
+ Node* scene = get_scene()->get_root_node()->cast_to<EditorNode>()->get_edited_scene();
+ if ( scene ) ref_item =_select_canvas_item_at_pos( Point2( b.x, b.y ), scene, transform );
+#endif
+ //popup->set_pos(Point2(b.x,b.y));
+ //popup->popup();
+ }
+ return;
+ }
+ /*
+ 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;
+
+ if (!b.pressed) {
+
+ if (drag!=DRAG_NONE) {
+
+ if (undo_redo) {
+
+
+ if (bone_ik_list.size()) {
+
+
+ undo_redo->create_action(TTR("Edit IK Chain"));
+
+ for(List<BoneIK>::Element *E=bone_ik_list.back();E;E=E->prev()) {
+
+ undo_redo->add_do_method(E->get().node,"edit_set_state",E->get().node->edit_get_state());
+ undo_redo->add_undo_method(E->get().node,"edit_set_state",E->get().orig_state);
+ }
+
+ undo_redo->add_do_method(viewport,"update");
+ undo_redo->add_undo_method(viewport,"update");
+
+ bone_ik_list.clear();
+
+ undo_redo->commit_action();
+ } else {
+
+ undo_redo->create_action(TTR("Edit CanvasItem"));
+
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+ Variant state=canvas_item->edit_get_state();
+ undo_redo->add_do_method(canvas_item,"edit_set_state",state);
+ undo_redo->add_undo_method(canvas_item,"edit_set_state",se->undo_state);
+ if (canvas_item->cast_to<Node2D>()) {
+ Node2D *pvt = canvas_item->cast_to<Node2D>();
+ if (pvt->edit_has_pivot()) {
+ undo_redo->add_do_method(canvas_item,"edit_set_pivot",pvt->edit_get_pivot());
+ undo_redo->add_undo_method(canvas_item,"edit_set_pivot",se->undo_pivot);
+ }
+ }
+ }
+ undo_redo->commit_action();
+ }
+ }
+
+ drag=DRAG_NONE;
+ viewport->update();
+ can_move_pivot=false;
+
+ }
+
+ if (box_selecting) {
+#if 0
+ if ( ! b.mod.shift ) _clear_canvas_items();
+ if ( box_selection_end() ) return;
+#endif
+
+ Node* scene = editor->get_edited_scene();
+ if (scene) {
+
+ List<CanvasItem*> selitems;
+
+ Point2 bsfrom = transform.xform(drag_from);
+ Point2 bsto= transform.xform(box_selecting_to);
+ if (bsfrom.x>bsto.x)
+ SWAP(bsfrom.x,bsto.x);
+ if (bsfrom.y>bsto.y)
+ SWAP(bsfrom.y,bsto.y);
+
+ _find_canvas_items_at_rect(Rect2(bsfrom,bsto-bsfrom),scene,transform,Transform2D(),&selitems);
+
+ for(List<CanvasItem*>::Element *E=selitems.front();E;E=E->next()) {
+
+ _append_canvas_item(E->get());
+ }
+
+ }
+
+ box_selecting=false;
+ viewport->update();
+
+ }
+ return;
+ }
+
+
+ Map<ObjectID,BoneList>::Element *Cbone=NULL; //closest
+
+ {
+ bone_ik_list.clear();
+ float closest_dist=1e20;
+ int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
+ for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) {
+
+ if (E->get().from == E->get().to)
+ continue;
+ Vector2 s[2]={
+ E->get().from,
+ E->get().to
+ };
+
+ Vector2 p = Geometry::get_closest_point_to_segment_2d(Vector2(b.x,b.y),s);
+ float d = p.distance_to(Vector2(b.x,b.y));
+ if (d<bone_width && d<closest_dist) {
+ Cbone=E;
+ closest_dist=d;
+ }
+ }
+
+ if (Cbone) {
+ Node2D *b=NULL;
+ Object* obj=ObjectDB::get_instance(Cbone->get().bone);
+ if (obj)
+ b=obj->cast_to<Node2D>();
+
+ if (b) {
+
+
+ bool ik_found=false;
+ bool first=true;
+
+
+
+ while(b) {
+
+ CanvasItem *pi=b->get_parent_item();
+ if (!pi)
+ break;
+
+ float len=pi->get_global_transform().get_origin().distance_to(b->get_global_position());
+ b=pi->cast_to<Node2D>();
+ if (!b)
+ break;
+
+ if (first) {
+
+ bone_orig_xform=b->get_global_transform();
+ first=false;
+ }
+
+ BoneIK bik;
+ bik.node=b;
+ bik.len=len;
+ bik.orig_state=b->edit_get_state();
+
+ bone_ik_list.push_back(bik);
+
+ if (b->has_meta("_edit_ik_")) {
+
+ ik_found=bone_ik_list.size()>1;
+ break;
+ }
+
+ if (!pi->has_meta("_edit_bone_"))
+ break;
+
+ }
+
+ if (!ik_found)
+ bone_ik_list.clear();
+
+ }
+ }
+ }
+
+ CanvasItem *single_item = get_single_item();
+
+ if (single_item) {
+ //try single canvas_item edit
+
+ CanvasItem *canvas_item = single_item;
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ ERR_FAIL_COND(!se);
+
+
+ Point2 click(b.x,b.y);
+
+ if ((b.mod.control && tool==TOOL_SELECT) || tool==TOOL_ROTATE) {
+
+ drag=DRAG_ROTATE;
+ drag_from=transform.affine_inverse().xform(click);
+ se->undo_state=canvas_item->edit_get_state();
+ if (canvas_item->cast_to<Node2D>())
+ se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
+ if (canvas_item->cast_to<Control>())
+ se->undo_pivot=Vector2();
+ return;
+ }
+
+ Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
+ Rect2 rect=canvas_item->get_item_rect();
+ //float handle_radius = handle_len * 1.4144; //magic number, guess what it means!
+
+ if (tool==TOOL_SELECT) {
+ drag = _find_drag_type(xform,rect,click,drag_point_from);
+
+ if (b.doubleclick) {
+
+ if (canvas_item->get_filename()!="" && canvas_item!=editor->get_edited_scene()) {
+
+ editor->open_request(canvas_item->get_filename());
+ return;
+ }
+ }
+
+ if (drag!=DRAG_NONE && (!Cbone || drag!=DRAG_ALL)) {
+ drag_from=transform.affine_inverse().xform(click);
+ se->undo_state=canvas_item->edit_get_state();
+ if (canvas_item->cast_to<Node2D>())
+ se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
+
+ return;
+ }
+ } else {
+
+ drag=DRAG_NONE;
+ }
+ }
+
+ //multi canvas_item edit
+
+
+ Point2 click=Point2(b.x,b.y);
+
+ if ((b.mod.alt || tool==TOOL_MOVE) && get_item_count()) {
+
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+ se->undo_state=canvas_item->edit_get_state();
+ if (canvas_item->cast_to<Node2D>())
+ se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
+
+ }
+
+
+ drag=DRAG_ALL;
+ drag_from=transform.affine_inverse().xform(click);
+ drag_point_from=_find_topleftmost_point();
+ viewport->update();
+ return;
+
+ }
+
+ Node* scene = editor->get_edited_scene();
+ if (!scene)
+ return;
+
+ /*
+ if (current_window) {
+ //no window.... ?
+ click-=current_window->get_scroll();
+ }*/
+ CanvasItem *c=NULL;
+
+ if (Cbone) {
+
+ Object* obj=ObjectDB::get_instance(Cbone->get().bone);
+ if (obj)
+ c=obj->cast_to<CanvasItem>();
+ if (c)
+ c=c->get_parent_item();
+
+
+ }
+ if (!c) {
+ c =_select_canvas_item_at_pos(click, scene,transform,Transform2D());
+
+
+ CanvasItem* cn = c;
+
+ while(cn) {
+ if (cn->has_meta("_edit_group_")) {
+ c=cn;
+ }
+ cn=cn->get_parent_item();
+ }
+ }
+
+ Node* n = c;
+
+ while ((n && n != scene && n->get_owner() != scene) || (n && !n->is_class("CanvasItem"))) {
+ n = n->get_parent();
+ };
+ c = n->cast_to<CanvasItem>();
+#if 0
+ if ( b.pressed ) box_selection_start( click );
+#endif
+
+ additive_selection=b.mod.shift;
+ if (!_select(c, click, additive_selection))
+ return;
+
+ }
+
+ if (p_event.type==InputEvent::MOUSE_MOTION) {
+
+ if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
+ viewport->call_deferred("grab_focus");
+
+ const InputEventMouseMotion &m=p_event.mouse_motion;
+
+ if (box_selecting) {
+
+ box_selecting_to=transform.affine_inverse().xform(Point2(m.x,m.y));
+ viewport->update();
+ return;
+
+ }
+
+
+ if (drag==DRAG_NONE) {
+
+
+ if ( (m.button_mask&BUTTON_MASK_LEFT && tool == TOOL_PAN) || m.button_mask&BUTTON_MASK_MIDDLE || (m.button_mask&BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+ h_scroll->set_value( h_scroll->get_value() - m.relative_x/zoom);
+ v_scroll->set_value( v_scroll->get_value() - m.relative_y/zoom);
+ }
+
+ return;
+
+ }
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+ bool dragging_bone = drag==DRAG_ALL && selection.size()==1 && bone_ik_list.size();
+
+
+ if (!dragging_bone) {
+ canvas_item->edit_set_state(se->undo_state); //reset state and reapply
+ if (canvas_item->cast_to<Node2D>())
+ canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot);
+ }
+
+
+ Vector2 dfrom = drag_from;
+ Vector2 dto = transform.affine_inverse().xform(Point2(m.x,m.y));
+ if (canvas_item->has_meta("_edit_lock_"))
+ continue;
+
+
+ if (drag==DRAG_ROTATE) {
+
+ Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
+ {
+ Node2D *node = canvas_item->cast_to<Node2D>();
+
+
+ if (node) {
+ real_t angle = node->get_rotation();
+ node->set_rotation(snap_angle( angle + (dfrom - center).angle_to(dto-center), angle ));
+ display_rotate_to = dto;
+ display_rotate_from = center;
+ viewport->update();
+ }
+ }
+
+ {
+ Control *node = canvas_item->cast_to<Control>();
+
+
+ if (node) {
+ real_t angle = node->get_rotation();
+ node->set_rotation(snap_angle( angle + (dfrom - center).angle_to(dto-center), angle ));
+ display_rotate_to = dto;
+ display_rotate_from = center;
+ viewport->update();
+ }
+ }
+
+ continue;
+ }
+
+
+ bool uniform = m.mod.shift;
+ bool symmetric=m.mod.alt;
+
+ dto = dto - (drag == DRAG_ALL ? drag_from - drag_point_from : Vector2(0, 0));
+
+ if(uniform && drag == DRAG_ALL) {
+ if(ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) {
+ dto.y = drag_point_from.y;
+ } else {
+ dto.x = drag_point_from.x;
+ }
+ }
+
+ dfrom = drag_point_from;
+ dto = snap_point(dto, drag_point_from);
+
+ Vector2 drag_vector =
+ 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();
+ Vector2 begin=local_rect.pos;
+ Vector2 end=local_rect.pos+local_rect.size;
+ Vector2 minsize = canvas_item->edit_get_minimum_size();
+
+ if (uniform) {
+ float aspect = local_rect.size.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: {
+ begin+=drag_vector;
+ end+=drag_vector;
+ } break;
+ case DRAG_RIGHT: {
+
+ incend(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
+
+ } break;
+ case DRAG_BOTTOM: {
+
+ incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
+
+ } break;
+ case DRAG_BOTTOM_RIGHT: {
+
+ incend(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
+ incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
+ } break;
+ case DRAG_TOP_LEFT: {
+
+ incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
+ incbeg(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
+ } break;
+ case DRAG_TOP: {
+
+ incbeg(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
+
+ } break;
+ case DRAG_LEFT: {
+
+ incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
+
+ } break;
+ case DRAG_TOP_RIGHT: {
+
+ 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: {
+
+ incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
+ incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
+ } break;
+ case DRAG_PIVOT: {
+
+ if (canvas_item->cast_to<Node2D>()) {
+ Node2D *n2d =canvas_item->cast_to<Node2D>();
+ n2d->edit_set_pivot(se->undo_pivot+drag_vector);
+
+ }
+ continue;
+ } break;
+
+ default:{}
+ }
+
+
+
+ if (!dragging_bone) {
+
+ local_rect.pos=begin;
+ local_rect.size=end-begin;
+ canvas_item->edit_set_rect(local_rect);
+
+ } else {
+ //ok, all that had to be done was done, now solve IK
+
+
+
+
+ Node2D *n2d = canvas_item->cast_to<Node2D>();
+ Transform2D final_xform = bone_orig_xform;
+
+
+
+ if (n2d) {
+
+ float total_len = 0;
+ for (List<BoneIK>::Element *E=bone_ik_list.front();E;E=E->next()) {
+ if (E->prev())
+ total_len+=E->get().len;
+ E->get().pos = E->get().node->get_global_transform().get_origin();
+ }
+
+ {
+
+ final_xform.elements[2]+=dto-dfrom;//final_xform.affine_inverse().basis_xform_inv(drag_vector);
+ //n2d->set_global_transform(final_xform);
+
+ }
+
+
+ CanvasItem *last = bone_ik_list.back()->get().node;
+ if (!last)
+ break;
+
+ Vector2 root_pos = last->get_global_transform().get_origin();
+ Vector2 leaf_pos = final_xform.get_origin();
+
+ if ((leaf_pos.distance_to(root_pos)) > total_len) {
+ //oops dude you went too far
+ //print_line("TOO FAR!");
+ Vector2 rel = leaf_pos - root_pos;
+ rel = rel.normalized() * total_len;
+ leaf_pos=root_pos+rel;
+
+ }
+
+ bone_ik_list.front()->get().pos=leaf_pos;
+
+ //print_line("BONE IK LIST "+itos(bone_ik_list.size()));
+
+
+ if (bone_ik_list.size()>2) {
+ int solver_iterations=64;
+ float solver_k=0.3;
+
+ for(int i=0;i<solver_iterations;i++) {
+
+ for (List<BoneIK>::Element *E=bone_ik_list.front();E;E=E->next()) {
+
+
+
+ if (E==bone_ik_list.back()) {
+
+ break;
+ }
+
+ float len = E->next()->get().len;
+
+ if (E->next()==bone_ik_list.back()) {
+
+ //print_line("back");
+
+ Vector2 rel = E->get().pos - E->next()->get().pos;
+ //print_line("PREV "+E->get().pos);
+ Vector2 desired = E->next()->get().pos+rel.normalized()*len;
+ //print_line("DESIRED "+desired);
+ E->get().pos=E->get().pos.linear_interpolate(desired,solver_k);
+ //print_line("POST "+E->get().pos);
+
+
+ } else if (E==bone_ik_list.front()) {
+ //only adjust parent
+ //print_line("front");
+ Vector2 rel = E->next()->get().pos - E->get().pos;
+ //print_line("PREV "+E->next()->get().pos);
+ Vector2 desired = E->get().pos+rel.normalized()*len;
+ //print_line("DESIRED "+desired);
+ E->next()->get().pos=E->next()->get().pos.linear_interpolate(desired,solver_k);
+ //print_line("POST "+E->next()->get().pos);
+ } else {
+
+ Vector2 rel = E->next()->get().pos - E->get().pos;
+ Vector2 cen = (E->next()->get().pos + E->get().pos)*0.5;
+ rel=rel.linear_interpolate(rel.normalized()*len,solver_k);
+ rel*=0.5;
+ E->next()->get().pos=cen+rel;
+ E->get().pos=cen-rel;
+ //print_line("mid");
+
+ }
+ }
+ }
+ }
+ }
+
+ for (List<BoneIK>::Element *E=bone_ik_list.back();E;E=E->prev()) {
+
+ Node2D *n = E->get().node;
+
+ if (!E->prev()) {
+ //last goes to what it was
+ final_xform.set_origin(n->get_global_position());
+ n->set_global_transform(final_xform);
+
+ } else {
+ Vector2 rel = (E->prev()->get().node->get_global_position() - n->get_global_position()).normalized();
+ Vector2 rel2 = (E->prev()->get().pos - E->get().pos).normalized();
+ float rot = rel.angle_to(rel2);
+ if (n->get_global_transform().basis_determinant()<0) {
+ //mirrored, rotate the other way
+ rot=-rot;
+ }
+
+ n->rotate(rot);
+ }
+
+ }
+
+
+
+ break;
+ }
+ }
+ }
+
+ if (p_event.type==InputEvent::KEY) {
+
+ const InputEventKey &k=p_event.key;
+
+ if (k.pressed && drag==DRAG_NONE) {
+
+ KeyMoveMODE move_mode = MOVE_VIEW_BASE;
+ if (k.mod.alt) move_mode = MOVE_LOCAL_BASE;
+ if (k.mod.control || k.mod.meta) move_mode = MOVE_LOCAL_WITH_ROT;
+
+ if (k.scancode==KEY_UP)
+ _key_move( Vector2(0,-1), k.mod.shift, move_mode );
+ else if (k.scancode==KEY_DOWN)
+ _key_move( Vector2(0,1), k.mod.shift, move_mode );
+ else if (k.scancode==KEY_LEFT)
+ _key_move( Vector2(-1,0), k.mod.shift, move_mode );
+ else if (k.scancode==KEY_RIGHT)
+ _key_move( Vector2(1,0), k.mod.shift, move_mode );
+ else if (k.scancode==KEY_ESCAPE) {
+ editor_selection->clear();
+ viewport->update();
+ }
+ else
+ return;
+
+ accept_event();
+ }
+
+ }
+
+
+
+
+}
+
+void CanvasItemEditor::_viewport_draw() {
+
+ // TODO fetch the viewport?
+
+ Ref<Texture> pivot = get_icon("EditorPivot","EditorIcons");
+ _update_scrollbars();
+ RID ci=viewport->get_canvas_item();
+
+ if (snap_show_grid) {
+ Size2 s = viewport->get_size();
+ int last_cell;
+ Transform2D xform = transform.affine_inverse();
+
+ if (snap_step.x!=0) {
+ for(int i=0;i<s.width;i++) {
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ }
+
+ if (snap_step.y!=0) {
+ for(int i=0;i<s.height;i++) {
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ }
+ }
+
+ if (viewport->has_focus()) {
+ Size2 size = viewport->get_size();
+ if (v_scroll->is_visible_in_tree())
+ size.width-=v_scroll->get_size().width;
+ if (h_scroll->is_visible_in_tree())
+ size.height-=h_scroll->get_size().height;
+
+ get_stylebox("EditorFocus","EditorStyles")->draw(ci,Rect2(Point2(),size));
+ }
+
+ Ref<Texture> lock = get_icon("Lock","EditorIcons");
+ Ref<Texture> group = get_icon("Group","EditorIcons");
+
+
+ bool single = get_single_item()!=NULL;
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ bool pivot_found=false;
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+
+ CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+
+ Rect2 rect=canvas_item->get_item_rect();
+
+ Transform2D xform=transform * canvas_item->get_global_transform_with_canvas();
+ VisualServer::get_singleton()->canvas_item_add_set_transform(ci,xform);
+
+ Vector2 endpoints[4]={
+
+ xform.xform(rect.pos),
+ xform.xform(rect.pos+Vector2(rect.size.x,0)),
+ xform.xform(rect.pos+rect.size),
+ xform.xform(rect.pos+Vector2(0,rect.size.y))
+ };
+
+ Color c = Color(1,0.6,0.4,0.7);
+
+ VisualServer::get_singleton()->canvas_item_add_set_transform(ci,Transform2D());
+
+ for(int i=0;i<4;i++) {
+ viewport->draw_line(endpoints[i],endpoints[(i+1)%4],c,2);
+ }
+
+ if (single && (tool==TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool==TOOL_EDIT_PIVOT)) { //kind of sucks
+
+ if (canvas_item->cast_to<Node2D>()) {
+
+
+ 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;
+ }
+
+ }
+
+
+ if (tool==TOOL_SELECT) {
+
+
+ for(int i=0;i<4;i++) {
+
+ int prev = (i+3)%4;
+ int next = (i+1)%4;
+
+ Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
+ ofs*=1.4144*(select_handle->get_size().width/2);
+
+ select_handle->draw(ci,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor());
+
+ ofs = (endpoints[i]+endpoints[next])/2;
+ ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2);
+
+ select_handle->draw(ci,(ofs-(select_handle->get_size()/2)).floor());
+
+ }
+
+ }
+ }
+
+
+
+ //DRAW_EMPTY_RECT( Rect2( current_window->get_scroll()-Point2(1,1), get_size()+Size2(2,2)), Color(0.8,0.8,1.0,0.8) );
+ //E->get().last_rect = rect;
+ }
+
+ pivot_button->set_disabled(!pivot_found);
+ VisualServer::get_singleton()->canvas_item_add_set_transform(ci,Transform2D());
+
+
+
+ Color x_axis_color(1.0,0.4,0.4,0.6);
+ Color y_axis_color(0.4,1.0,0.4,0.6);
+ Color area_axis_color(0.4,0.4,1.0,0.4);
+ Color rotate_color(0.4,0.7,1.0,0.8);
+
+ VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(h_scroll->get_min(),0)+transform.get_origin(),Point2(h_scroll->get_max(),0)+transform.get_origin(),x_axis_color);
+ VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(0,v_scroll->get_min())+transform.get_origin(),Point2(0,v_scroll->get_max())+transform.get_origin(),y_axis_color);
+
+
+ if (box_selecting) {
+
+ Point2 bsfrom = transform.xform(drag_from);
+ Point2 bsto= transform.xform(box_selecting_to);
+
+
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(bsfrom,bsto-bsfrom),Color(0.7,0.7,1.0,0.3));
+ }
+
+ if (drag==DRAG_ROTATE) {
+ VisualServer::get_singleton()->canvas_item_add_line(ci,transform.xform(display_rotate_from), transform.xform(display_rotate_to),rotate_color);
+ }
+
+ Size2 screen_size = Size2( GlobalConfig::get_singleton()->get("display/window/width"), GlobalConfig::get_singleton()->get("display/window/height") );
+
+ Vector2 screen_endpoints[4]= {
+ transform.xform(Vector2(0,0)),
+ transform.xform(Vector2(screen_size.width,0)),
+ transform.xform(Vector2(screen_size.width,screen_size.height)),
+ transform.xform(Vector2(0,screen_size.height))
+ };
+
+ for(int i=0;i<4;i++) {
+
+ VisualServer::get_singleton()->canvas_item_add_line(ci,screen_endpoints[i], screen_endpoints[(i+1)%4],area_axis_color);
+
+ }
+
+ for(List<LockList>::Element*E=lock_list.front();E;E=E->next()) {
+
+ Vector2 ofs = transform.xform(E->get().pos);
+ if (E->get().lock) {
+
+ lock->draw(ci,ofs);
+ ofs.x+=lock->get_width();
+ }
+ if (E->get().group) {
+
+ group->draw(ci,ofs);
+ }
+
+ }
+
+ {
+
+ EditorNode *en = editor;
+ EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
+
+ if (!over_plugin_list->empty()) {
+
+ over_plugin_list->forward_draw_over_canvas(transform,viewport);
+
+ }
+ }
+
+ if (skeleton_show_bones) {
+ int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
+ Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
+ Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
+ Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
+ Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
+
+ for(Map<ObjectID,BoneList>::Element*E=bone_list.front();E;E=E->next()) {
+
+ E->get().from=Vector2();
+ E->get().to=Vector2();
+
+ Object *obj = ObjectDB::get_instance(E->get().bone);
+ if (!obj)
+ continue;
+
+ Node2D* n2d = obj->cast_to<Node2D>();
+ if (!n2d)
+ continue;
+
+ if (!n2d->get_parent())
+ continue;
+
+ CanvasItem *pi = n2d->get_parent_item();
+
+
+ Node2D* pn2d=n2d->get_parent()->cast_to<Node2D>();
+
+ if (!pn2d)
+ continue;
+
+ Vector2 from = transform.xform(pn2d->get_global_position());
+ Vector2 to = transform.xform(n2d->get_global_position());
+
+ E->get().from=from;
+ E->get().to=to;
+
+ Vector2 rel = to-from;
+ Vector2 relt = rel.tangent().normalized()*bone_width;
+
+
+
+ Vector<Vector2> bone_shape;
+ bone_shape.push_back(from);
+ bone_shape.push_back(from+rel*0.2+relt);
+ bone_shape.push_back(to);
+ bone_shape.push_back(from+rel*0.2-relt);
+ Vector<Color> colors;
+ if (pi->has_meta("_edit_ik_")) {
+
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ colors.push_back(bone_ik_color);
+ } else {
+ colors.push_back(bone_color1);
+ colors.push_back(bone_color2);
+ colors.push_back(bone_color1);
+ colors.push_back(bone_color2);
+ }
+
+
+ VisualServer::get_singleton()->canvas_item_add_primitive(ci,bone_shape,colors,Vector<Vector2>(),RID());
+
+ if (editor_selection->is_selected(pi)) {
+ for(int i=0;i<bone_shape.size();i++) {
+
+ VisualServer::get_singleton()->canvas_item_add_line(ci,bone_shape[i],bone_shape[(i+1)%bone_shape.size()],bone_selected_color,2);
+ }
+ }
+
+ }
+ }
+}
+
+void CanvasItemEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ bool all_control=true;
+ bool has_control=false;
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ if (canvas_item->cast_to<Control>())
+ has_control=true;
+ else
+ all_control=false;
+
+ CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
+ if (!se)
+ continue;
+
+ Rect2 r=canvas_item->get_item_rect();
+
+ Transform2D xform = canvas_item->get_transform();
+
+ if (r != se->prev_rect || xform!=se->prev_xform) {
+ viewport->update();
+ se->prev_rect=r;
+ se->prev_xform=xform;
+ }
+
+ }
+
+ bool show_anchor = all_control && has_control;
+ if (show_anchor != anchor_menu->is_visible()) {
+ if (show_anchor)
+ anchor_menu->show();
+ else
+ anchor_menu->hide();
+ }
+
+ for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) {
+
+ Object *b = ObjectDB::get_instance(E->get().bone);
+ if (!b) {
+
+ viewport->update();
+ break;
+ }
+
+ Node2D *b2 = b->cast_to<Node2D>();
+ if (!b2) {
+ continue;
+ }
+
+ if (b2->get_global_transform()!=E->get().xform) {
+
+ E->get().xform=b2->get_global_transform();
+ viewport->update();
+ }
+ }
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ select_sb->set_texture( get_icon("EditorRect2D","EditorIcons") );
+ for(int i=0;i<4;i++) {
+ select_sb->set_margin_size(Margin(i),4);
+ select_sb->set_default_margin(Margin(i),4);
+ }
+
+ 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"));
+ group_button->set_icon(get_icon("Group","EditorIcons"));
+ ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
+ key_insert_button->set_icon(get_icon("Key","EditorIcons"));
+
+
+ //anchor_menu->add_icon_override("Align Top Left");
+ anchor_menu->set_icon(get_icon("Anchor","EditorIcons"));
+ PopupMenu *p=anchor_menu->get_popup();
+
+ p->add_icon_item(get_icon("ControlAlignTopLeft","EditorIcons"),"Top Left",ANCHOR_ALIGN_TOP_LEFT);
+ p->add_icon_item(get_icon("ControlAlignTopRight","EditorIcons"),"Top Right",ANCHOR_ALIGN_TOP_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomRight","EditorIcons"),"Bottom Right",ANCHOR_ALIGN_BOTTOM_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomLeft","EditorIcons"),"Bottom Left",ANCHOR_ALIGN_BOTTOM_LEFT);
+ p->add_separator();
+ p->add_icon_item(get_icon("ControlAlignLeftCenter","EditorIcons"),"Center Left",ANCHOR_ALIGN_CENTER_LEFT);
+ p->add_icon_item(get_icon("ControlAlignTopCenter","EditorIcons"),"Center Top",ANCHOR_ALIGN_CENTER_TOP);
+ p->add_icon_item(get_icon("ControlAlignRightCenter","EditorIcons"),"Center Right",ANCHOR_ALIGN_CENTER_RIGHT);
+ p->add_icon_item(get_icon("ControlAlignBottomCenter","EditorIcons"),"Center Bottom",ANCHOR_ALIGN_CENTER_BOTTOM);
+ p->add_icon_item(get_icon("ControlAlignCenter","EditorIcons"),"Center",ANCHOR_ALIGN_CENTER);
+ p->add_separator();
+ p->add_icon_item(get_icon("ControlAlignLeftWide","EditorIcons"),"Left Wide",ANCHOR_ALIGN_LEFT_WIDE);
+ p->add_icon_item(get_icon("ControlAlignTopWide","EditorIcons"),"Top Wide",ANCHOR_ALIGN_TOP_WIDE);
+ p->add_icon_item(get_icon("ControlAlignRightWide","EditorIcons"),"Right Wide",ANCHOR_ALIGN_RIGHT_WIDE);
+ p->add_icon_item(get_icon("ControlAlignBottomWide","EditorIcons"),"Bottom Wide",ANCHOR_ALIGN_BOTTOM_WIDE);
+ p->add_icon_item(get_icon("ControlVcenterWide","EditorIcons"),"VCenter Wide ",ANCHOR_ALIGN_VCENTER_WIDE);
+ p->add_icon_item(get_icon("ControlHcenterWide","EditorIcons"),"HCenter Wide ",ANCHOR_ALIGN_HCENTER_WIDE);
+ p->add_separator();
+ p->add_icon_item(get_icon("ControlAlignWide","EditorIcons"),"Full Rect",ANCHOR_ALIGN_WIDE);
+
+
+ AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed",this,"_keying_changed");
+ _keying_changed();
+ }
+
+ if (p_what==NOTIFICATION_READY) {
+
+ get_tree()->connect("node_removed",this,"_node_removed");
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+
+
+ }
+}
+
+void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
+
+ drag=DRAG_NONE;
+
+ editor_selection->clear();//_clear_canvas_items();
+ editor_selection->add_node(p_canvas_item);
+ //_add_canvas_item(p_canvas_item);
+ viewport->update();
+
+}
+
+
+void CanvasItemEditor::_find_canvas_items_span(Node *p_node, Rect2& r_rect, const Transform2D& p_xform) {
+
+
+
+ if (!p_node)
+ return;
+
+ CanvasItem *c=p_node->cast_to<CanvasItem>();
+
+
+ for (int i=p_node->get_child_count()-1;i>=0;i--) {
+
+ //CanvasItem *r=NULL;
+
+ if (c && !c->is_set_as_toplevel())
+ _find_canvas_items_span(p_node->get_child(i),r_rect,p_xform * c->get_transform());
+ else
+ _find_canvas_items_span(p_node->get_child(i),r_rect,Transform2D());
+ }
+
+
+
+ if (c && c->is_visible_in_tree()) {
+
+ Rect2 rect = c->get_item_rect();
+ Transform2D xform = p_xform * c->get_transform();
+
+
+ LockList lock;
+ lock.lock=c->has_meta("_edit_lock_");
+ lock.group=c->has_meta("_edit_group_");
+
+ if (lock.group || lock.lock) {
+ lock.pos=xform.xform(rect.pos);
+ lock_list.push_back(lock);
+ }
+
+ if (c->has_meta("_edit_bone_")) {
+
+ ObjectID id = c->get_instance_ID();
+ if (!bone_list.has(id)) {
+ BoneList bone;
+ bone.bone=id;
+ bone_list[id]=bone;
+ }
+
+ bone_list[id].last_pass=bone_last_frame;
+ }
+
+ r_rect.expand_to( xform.xform(rect.pos) );
+ r_rect.expand_to( xform.xform(rect.pos+Point2(rect.size.x,0)) );
+ r_rect.expand_to( xform.xform(rect.pos+Point2(0,rect.size.y)) );
+ r_rect.expand_to( xform.xform(rect.pos+rect.size) );
+
+ }
+
+}
+
+void CanvasItemEditor::_update_scrollbars() {
+
+
+ updating_scroll=true;
+
+ Size2 size = viewport->get_size();
+ Size2 hmin = h_scroll->get_minimum_size();
+ Size2 vmin = v_scroll->get_minimum_size();
+
+ v_scroll->set_begin( Point2(size.width - vmin.width, 0) );
+ v_scroll->set_end( Point2(size.width, size.height) );
+
+ h_scroll->set_begin( Point2( 0, size.height - hmin.height) );
+ h_scroll->set_end( Point2(size.width-vmin.width, size.height) );
+
+
+ Size2 screen_rect = Size2( GlobalConfig::get_singleton()->get("display/window/width"), GlobalConfig::get_singleton()->get("display/window/height") );
+
+
+ Rect2 local_rect = Rect2(Point2(),viewport->get_size()-Size2(vmin.width,hmin.height));
+
+ Rect2 canvas_item_rect=Rect2(Point2(),screen_rect);
+
+ lock_list.clear();
+ bone_last_frame++;
+
+
+
+ if (editor->get_edited_scene())
+ _find_canvas_items_span(editor->get_edited_scene(),canvas_item_rect,Transform2D());
+
+ List<Map<ObjectID,BoneList>::Element*> bone_to_erase;
+
+ for(Map<ObjectID,BoneList>::Element*E=bone_list.front();E;E=E->next()) {
+
+ if (E->get().last_pass!=bone_last_frame) {
+ bone_to_erase.push_back(E);
+ }
+ }
+
+ while(bone_to_erase.size()) {
+ bone_list.erase(bone_to_erase.front()->get());
+ bone_to_erase.pop_front();
+ }
+
+ //expand area so it's easier to do animations and stuff at 0,0
+ canvas_item_rect.size+=screen_rect*2;
+ canvas_item_rect.pos-=screen_rect;
+
+ Point2 ofs;
+
+
+ if (canvas_item_rect.size.height <= (local_rect.size.y/zoom)) {
+
+ v_scroll->hide();
+ ofs.y=canvas_item_rect.pos.y;
+ } else {
+
+ v_scroll->show();
+ v_scroll->set_min(canvas_item_rect.pos.y);
+ v_scroll->set_max(canvas_item_rect.pos.y+canvas_item_rect.size.y);
+ v_scroll->set_page(local_rect.size.y/zoom);
+ if (first_update) {
+ //so 0,0 is visible
+ v_scroll->set_value(-10);
+ h_scroll->set_value(-10);
+ first_update=false;
+
+ }
+
+ ofs.y=v_scroll->get_value();
+ }
+
+ if (canvas_item_rect.size.width <= (local_rect.size.x/zoom)) {
+
+ h_scroll->hide();
+ ofs.x=canvas_item_rect.pos.x;
+ } else {
+
+ h_scroll->show();
+ h_scroll->set_min(canvas_item_rect.pos.x);
+ h_scroll->set_max(canvas_item_rect.pos.x+canvas_item_rect.size.x);
+ h_scroll->set_page(local_rect.size.x/zoom);
+ ofs.x=h_scroll->get_value();
+ }
+
+ //transform=Matrix32();
+ transform.elements[2]=-ofs*zoom;
+
+ editor->get_scene_root()->set_global_canvas_transform(transform);
+
+
+ updating_scroll=false;
+
+ //transform.scale_basis(Vector2(zoom,zoom));
+
+
+}
+
+void CanvasItemEditor::_update_scroll(float) {
+
+
+ if (updating_scroll)
+ return;
+
+ Point2 ofs;
+ ofs.x=h_scroll->get_value();
+ ofs.y=v_scroll->get_value();
+
+ //current_window->set_scroll(-ofs);
+
+ transform=Transform2D();
+
+ transform.scale_basis(Size2(zoom,zoom));
+ transform.elements[2]=-ofs;
+
+ editor->get_scene_root()->set_global_canvas_transform(transform);
+
+
+ viewport->update();
+
+}
+
+void CanvasItemEditor::_set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom) {
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ undo_redo->create_action(TTR("Change Anchors"));
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Control *c = E->get()->cast_to<Control>();
+
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_LEFT,p_left);
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_TOP,p_top);
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_RIGHT,p_right);
+ undo_redo->add_do_method(c,"set_anchor",MARGIN_BOTTOM,p_bottom);
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_LEFT,c->get_anchor(MARGIN_LEFT));
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_TOP,c->get_anchor(MARGIN_TOP));
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_RIGHT,c->get_anchor(MARGIN_RIGHT));
+ undo_redo->add_undo_method(c,"set_anchor",MARGIN_BOTTOM,c->get_anchor(MARGIN_BOTTOM));
+ }
+
+ undo_redo->commit_action();
+
+}
+
+void CanvasItemEditor::_popup_callback(int p_op) {
+
+ last_option=MenuOption(p_op);
+ switch(p_op) {
+
+ case SNAP_USE: {
+ snap_grid = !snap_grid;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
+ edit_menu->get_popup()->set_item_checked(idx,snap_grid);
+ } break;
+ case SNAP_SHOW_GRID: {
+ snap_show_grid = !snap_show_grid;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
+ edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
+ viewport->update();
+ } break;
+ case SNAP_USE_ROTATION: {
+ snap_rotation = !snap_rotation;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+ edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
+ } break;
+ case SNAP_RELATIVE: {
+ snap_relative = !snap_relative;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+ edit_menu->get_popup()->set_item_checked(idx,snap_relative);
+ } break;
+ case SNAP_USE_PIXEL: {
+ snap_pixel = !snap_pixel;
+ int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
+ edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
+ } break;
+ case SNAP_CONFIGURE: {
+ ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
+ snap_dialog->popup_centered(Size2(220,160));
+ } break;
+ case SKELETON_SHOW_BONES: {
+ skeleton_show_bones = !skeleton_show_bones;
+ int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES);
+ skeleton_menu->set_item_checked(idx,skeleton_show_bones);
+ viewport->update();
+ } break;
+ case ZOOM_IN: {
+ if (zoom>MAX_ZOOM)
+ return;
+ zoom=zoom*(1.0/0.5);
+ _update_scroll(0);
+ viewport->update();
+ return;
+ } break;
+ case ZOOM_OUT: {
+ if (zoom<MIN_ZOOM)
+ return;
+
+ zoom=zoom*0.5;
+ _update_scroll(0);
+ viewport->update();
+ return;
+
+ } break;
+ case ZOOM_RESET: {
+
+ zoom=1;
+ _update_scroll(0);
+ viewport->update();
+ return;
+
+ } break;
+ case ZOOM_SET: {
+
+ updating_value_dialog=true;
+
+ dialog_label->set_text(TTR("Zoom (%):"));
+ dialog_val->set_min(0.1);
+ dialog_val->set_step(0.1);
+ dialog_val->set_max(800);
+ dialog_val->set_value(zoom*100);
+ value_dialog->popup_centered(Size2(200,85));
+ updating_value_dialog=false;
+
+
+ } break;
+ case LOCK_SELECTED: {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ canvas_item->set_meta("_edit_lock_",true);
+ emit_signal("item_lock_status_changed");
+ }
+ viewport->update();
+ } break;
+ case UNLOCK_SELECTED: {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+
+ canvas_item->set_meta("_edit_lock_",Variant());
+ emit_signal("item_lock_status_changed");
+ }
+
+ viewport->update();
+
+ } break;
+ case GROUP_SELECTED: {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ canvas_item->set_meta("_edit_group_",true);
+ emit_signal("item_group_status_changed");
+ }
+ viewport->update();
+ } break;
+ case UNGROUP_SELECTED: {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ canvas_item->set_meta("_edit_group_",Variant());
+ emit_signal("item_group_status_changed");
+ }
+
+ viewport->update();
+
+ } break;
+
+ case EXPAND_TO_PARENT: {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+
+ Control *c = canvas_item->cast_to<Control>();
+ if (!c)
+ continue;
+ c->set_area_as_parent_rect();
+
+ }
+
+ viewport->update();
+
+ } break;
+
+ case ALIGN_VERTICAL: {
+#if 0
+ if ( ref_item && canvas_items.size() > 1 ) {
+ Vector2 ref_pos = ref_item->get_global_transform().elements[2];
+ Rect2 ref_r = ref_item->get_item_rect();
+ for ( CanvasItemMap::Element *E = canvas_items.front(); E; E = E->next() ) {
+ CanvasItem *it_curr = E->key();
+ if ( it_curr == ref_item ) continue;
+ Vector2 v = it_curr->get_global_transform().elements[2];
+ Rect2 r = it_curr->get_item_rect();
+ r.pos.x = ( ref_pos.x + ref_r.size.x / 2 ) - ( v.x + r.size.x / 2 );
+ it_curr->edit_set_rect( r );
+ }
+ viewport->update();
+ }
+#endif
+ } break;
+
+ case ALIGN_HORIZONTAL: {
+#if 0
+ if ( ref_item && canvas_items.size() > 1 ) {
+ Vector2 ref_pos = ref_item->get_global_transform().elements[2];
+ Rect2 ref_r = ref_item->get_item_rect();
+ for ( CanvasItemMap::Element *E = canvas_items.front(); E; E = E->next() ) {
+ CanvasItem *it_curr = E->key();
+ if ( it_curr == ref_item ) continue;
+ Vector2 v = it_curr->get_global_transform().elements[2];
+ Rect2 r = it_curr->get_item_rect();
+ r.pos.y = ( ref_pos.y + ref_r.size.y / 2 ) - ( v.y + r.size.y / 2 );
+ it_curr->edit_set_rect( r );
+ }
+ viewport->update();
+ }
+#endif
+ } break;
+
+ case SPACE_HORIZONTAL: {
+ //space_selected_items< proj_vector2_x, compare_items_x >();
+ } break;
+
+ case SPACE_VERTICAL: {
+ //space_selected_items< proj_vector2_y, compare_items_y >();
+ } break;
+ case ANCHOR_ALIGN_TOP_LEFT: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_TOP_RIGHT: {
+ _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_BOTTOM_LEFT: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_BOTTOM_RIGHT: {
+ _set_anchor(ANCHOR_END,ANCHOR_END,ANCHOR_END,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_CENTER_LEFT: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_CENTER_RIGHT: {
+
+ _set_anchor(ANCHOR_END,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_CENTER_TOP: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_CENTER_BOTTOM: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_CENTER: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_TOP_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
+ } break;
+ case ANCHOR_ALIGN_LEFT_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_RIGHT_WIDE: {
+ _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_BOTTOM_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_VCENTER_WIDE: {
+ _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END);
+ } break;
+ case ANCHOR_ALIGN_HCENTER_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
+ } break;
+ case ANCHOR_ALIGN_WIDE: {
+ _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
+ } break;
+
+ case ANIM_INSERT_KEY:
+ case ANIM_INSERT_KEY_EXISTING: {
+
+ bool existing = p_op==ANIM_INSERT_KEY_EXISTING;
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ if (canvas_item->cast_to<Node2D>()) {
+ Node2D *n2d = canvas_item->cast_to<Node2D>();
+
+ if (key_pos)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d,"transform/pos",n2d->get_position(),existing);
+ if (key_rot)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d,"transform/rot",Math::rad2deg(n2d->get_rotation()),existing);
+ if (key_scale)
+ 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()) {
+ //look for an IK chain
+ List<Node2D*> ik_chain;
+
+ Node2D *n = n2d->get_parent_item()->cast_to<Node2D>();
+ bool has_chain=false;
+
+ while(n) {
+
+ ik_chain.push_back(n);
+ if (n->has_meta("_edit_ik_")) {
+ has_chain=true;
+ break;
+ }
+
+ if (!n->get_parent_item())
+ break;
+ n=n->get_parent_item()->cast_to<Node2D>();
+ }
+
+ if (has_chain && ik_chain.size()) {
+
+ for(List<Node2D*>::Element *F=ik_chain.front();F;F=F->next()) {
+
+ if (key_pos)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/pos",F->get()->get_position(),existing);
+ if (key_rot)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/rot",Math::rad2deg(F->get()->get_rotation()),existing);
+ if (key_scale)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/scale",F->get()->get_scale(),existing);
+
+
+ }
+ }
+ }
+
+ } else if (canvas_item->cast_to<Control>()) {
+
+ Control *ctrl = canvas_item->cast_to<Control>();
+
+ if (key_pos)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/pos",ctrl->get_pos(),existing);
+ if (key_scale)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size(),existing);
+ }
+
+ }
+
+ } break;
+ case ANIM_INSERT_POS: {
+
+ key_pos = key_loc_button->is_pressed();
+ } break;
+ case ANIM_INSERT_ROT: {
+
+ key_rot = key_rot_button->is_pressed();
+ } break;
+ case ANIM_INSERT_SCALE: {
+
+ key_scale = key_scale_button->is_pressed();
+ } break;
+ /*
+ case ANIM_INSERT_POS_ROT
+ case ANIM_INSERT_POS_SCALE:
+ case ANIM_INSERT_ROT_SCALE:
+ case ANIM_INSERT_POS_ROT_SCALE: {
+
+ static const bool key_toggles[7][3]={
+ {true,false,false},
+ {false,true,false},
+ {false,false,true},
+ {true,true,false},
+ {true,false,true},
+ {false,true,true},
+ {true,true,true}
+ };
+ key_pos=key_toggles[p_op-ANIM_INSERT_POS][0];
+ key_rot=key_toggles[p_op-ANIM_INSERT_POS][1];
+ key_scale=key_toggles[p_op-ANIM_INSERT_POS][2];
+
+ for(int i=ANIM_INSERT_POS;i<=ANIM_INSERT_POS_ROT_SCALE;i++) {
+ int idx = animation_menu->get_popup()->get_item_index(i);
+ animation_menu->get_popup()->set_item_checked(idx,i==p_op);
+ }
+
+ } break;*/
+ case ANIM_COPY_POSE: {
+
+ pose_clipboard.clear();
+
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+
+ if (canvas_item->cast_to<Node2D>()) {
+
+ Node2D *n2d = canvas_item->cast_to<Node2D>();
+ PoseClipboard pc;
+ pc.pos=n2d->get_position();
+ pc.rot=n2d->get_rotation();
+ pc.scale=n2d->get_scale();
+ pc.id=n2d->get_instance_ID();
+ pose_clipboard.push_back(pc);
+ }
+ }
+
+
+ } break;
+ case ANIM_PASTE_POSE: {
+
+ if (!pose_clipboard.size())
+ break;
+
+ undo_redo->create_action(TTR("Paste Pose"));
+ for (List<PoseClipboard>::Element *E=pose_clipboard.front();E;E=E->next()) {
+
+ Object *o = ObjectDB::get_instance(E->get().id);
+ if (!o)
+ continue;
+ Node2D *n2d = o->cast_to<Node2D>();
+ if (!n2d)
+ continue;
+ undo_redo->add_do_method(n2d,"set_pos",E->get().pos);
+ undo_redo->add_do_method(n2d,"set_rot",E->get().rot);
+ undo_redo->add_do_method(n2d,"set_scale",E->get().scale);
+ undo_redo->add_undo_method(n2d,"set_pos",n2d->get_position());
+ undo_redo->add_undo_method(n2d,"set_rot",n2d->get_rotation());
+ undo_redo->add_undo_method(n2d,"set_scale",n2d->get_scale());
+ }
+ undo_redo->commit_action();
+
+ } break;
+ case ANIM_CLEAR_POSE: {
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ if (canvas_item->cast_to<Node2D>()) {
+ Node2D *n2d = canvas_item->cast_to<Node2D>();
+
+ if (key_pos)
+ n2d->set_position(Vector2());
+ if (key_rot)
+ n2d->set_rotation(0);
+ if (key_scale)
+ n2d->set_scale(Vector2(1,1));
+ } else if (canvas_item->cast_to<Control>()) {
+
+ Control *ctrl = canvas_item->cast_to<Control>();
+
+ if (key_pos)
+ ctrl->set_pos(Point2());
+ /*
+ if (key_scale)
+ AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
+ */
+ }
+
+ }
+
+
+ } break;
+ case VIEW_CENTER_TO_SELECTION:
+ case VIEW_FRAME_TO_SELECTION: {
+
+ _focus_selection(p_op);
+
+ } break;
+ case SKELETON_MAKE_BONES: {
+
+
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ Node2D *n2d = E->key()->cast_to<Node2D>();
+ if (!n2d)
+ continue;
+ if (!n2d->is_visible_in_tree())
+ continue;
+ if (!n2d->get_parent_item())
+ continue;
+
+ n2d->set_meta("_edit_bone_",true);
+ if (!skeleton_show_bones)
+ skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+
+ }
+ viewport->update();
+
+ } break;
+ case SKELETON_CLEAR_BONES: {
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ Node2D *n2d = E->key()->cast_to<Node2D>();
+ if (!n2d)
+ continue;
+ if (!n2d->is_visible_in_tree())
+ continue;
+
+ n2d->set_meta("_edit_bone_",Variant());
+ if (!skeleton_show_bones)
+ skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+
+ }
+ viewport->update();
+
+ } break;
+ case SKELETON_SET_IK_CHAIN: {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
+ if (!canvas_item || !canvas_item->is_visible_in_tree())
+ continue;
+
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+ canvas_item->set_meta("_edit_ik_",true);
+ if (!skeleton_show_bones)
+ skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+
+ }
+
+ viewport->update();
+
+ } break;
+ case SKELETON_CLEAR_IK_CHAIN: {
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ CanvasItem *n2d = E->key()->cast_to<CanvasItem>();
+ if (!n2d)
+ continue;
+ if (!n2d->is_visible_in_tree())
+ continue;
+
+ n2d->set_meta("_edit_ik_",Variant());
+ if (!skeleton_show_bones)
+ skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+
+ }
+ viewport->update();
+
+ } break;
+
+ }
+}
+#if 0
+template< class P, class C > void CanvasItemEditor::space_selected_items() {
+ P p;
+ if ( canvas_items.size() > 2 ) {
+ Vector< CanvasItem * > items;
+ for ( CanvasItemMap::Element *E = canvas_items.front(); E; E = E->next() ) {
+ CanvasItem *it_curr = E->key();
+ items.push_back( it_curr );
+ }
+ items.sort_custom< C >();
+
+ float width_s = p.get( items[0]->get_item_rect().size );
+ float width_e = p.get( items[ items.size() - 1 ]->get_item_rect().size );
+ float start_x = p.get( items[0]->get_global_transform().elements[2] ) + ( width_s / 2 );
+ float end_x = p.get( items[ items.size() - 1 ]->get_global_transform().elements[2] ) + ( width_e / 2 );
+ float sp = ( end_x - start_x ) / ( items.size() - 1 );
+
+ for ( int i = 0; i < items.size(); i++ ) {
+ CanvasItem *it_curr = items[i];
+ Vector2 v = it_curr->get_global_transform().elements[2];
+ Rect2 r = it_curr->get_item_rect();
+ p.set( r.pos, ( start_x + sp * i ) - ( p.get( v ) + p.get( r.size ) / 2 ) );
+ it_curr->edit_set_rect( r );
+ }
+ viewport->update();
+ }
+}
+#endif
+
+
+void CanvasItemEditor::_focus_selection(int p_op) {
+ Vector2 center(0.f, 0.f);
+ Rect2 rect;
+ int count = 0;
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+ CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
+ if (!canvas_item) continue;
+ if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
+ continue;
+
+
+ // counting invisible items, for now
+ //if (!canvas_item->is_visible_in_tree()) continue;
+ ++count;
+
+ Rect2 item_rect = canvas_item->get_item_rect();
+
+ Vector2 pos = canvas_item->get_global_transform().get_origin();
+ Vector2 scale = canvas_item->get_global_transform().get_scale();
+ real_t angle = canvas_item->get_global_transform().get_rotation();
+
+ Transform2D t(angle, Vector2(0.f,0.f));
+ item_rect = t.xform(item_rect);
+ Rect2 canvas_item_rect(pos + scale*item_rect.pos, scale*item_rect.size);
+ if (count == 1) {
+ rect = canvas_item_rect;
+ } else {
+ rect = rect.merge(canvas_item_rect);
+ }
+ };
+ if (count==0) return;
+
+ if (p_op == VIEW_CENTER_TO_SELECTION) {
+
+ center = rect.pos + rect.size/2;
+ Vector2 offset = viewport->get_size()/2 - editor->get_scene_root()->get_global_canvas_transform().xform(center);
+ h_scroll->set_value(h_scroll->get_value() - offset.x/zoom);
+ v_scroll->set_value(v_scroll->get_value() - offset.y/zoom);
+
+ } else { // VIEW_FRAME_TO_SELECTION
+
+ if (rect.size.x > CMP_EPSILON && rect.size.y > CMP_EPSILON) {
+ float scale_x = viewport->get_size().x/rect.size.x;
+ float scale_y = viewport->get_size().y/rect.size.y;
+ zoom = scale_x < scale_y? scale_x:scale_y;
+ zoom *= 0.90;
+ _update_scroll(0);
+ call_deferred("_popup_callback", VIEW_CENTER_TO_SELECTION);
+ }
+ }
+}
+
+
+void CanvasItemEditor::_bind_methods() {
+
+ ClassDB::bind_method("_node_removed",&CanvasItemEditor::_node_removed);
+ ClassDB::bind_method("_update_scroll",&CanvasItemEditor::_update_scroll);
+ ClassDB::bind_method("_popup_callback",&CanvasItemEditor::_popup_callback);
+ ClassDB::bind_method("_visibility_changed",&CanvasItemEditor::_visibility_changed);
+ ClassDB::bind_method("_dialog_value_changed",&CanvasItemEditor::_dialog_value_changed);
+ ClassDB::bind_method("_get_editor_data",&CanvasItemEditor::_get_editor_data);
+ ClassDB::bind_method("_tool_select",&CanvasItemEditor::_tool_select);
+ ClassDB::bind_method("_keying_changed",&CanvasItemEditor::_keying_changed);
+ ClassDB::bind_method("_unhandled_key_input",&CanvasItemEditor::_unhandled_key_input);
+ ClassDB::bind_method("_viewport_draw",&CanvasItemEditor::_viewport_draw);
+ ClassDB::bind_method("_viewport_gui_input",&CanvasItemEditor::_viewport_gui_input);
+ ClassDB::bind_method("_snap_changed",&CanvasItemEditor::_snap_changed);
+ ClassDB::bind_method(D_METHOD("_selection_result_pressed"),&CanvasItemEditor::_selection_result_pressed);
+ ClassDB::bind_method(D_METHOD("_selection_menu_hide"),&CanvasItemEditor::_selection_menu_hide);
+
+ ADD_SIGNAL( MethodInfo("item_lock_status_changed") );
+ ADD_SIGNAL( MethodInfo("item_group_status_changed") );
+
+}
+
+#if 0
+void CanvasItemEditor::end_drag() {
+ print_line( "end drag" );
+
+ if (undo_redo) {
+
+ undo_redo->create_action("Edit CanvasItem");
+ for(CanvasItemMap::Element *E=canvas_items.front();E;E=E->next()) {
+ CanvasItem *canvas_item = E->key();
+ Variant state=canvas_item->edit_get_state();
+ undo_redo->add_do_method(canvas_item,"edit_set_state",state);
+ undo_redo->add_undo_method(canvas_item,"edit_set_state",E->get().undo_state);
+ }
+ undo_redo->commit_action();
+ }
+
+ drag=DRAG_NONE;
+ viewport->update();
+}
+
+void CanvasItemEditor::box_selection_start( Point2 &click ) {
+ print_line( "box selection start" );
+
+ drag_from=transform.affine_inverse().xform(click);
+
+ box_selecting=true;
+ box_selecting_to=drag_from;
+ viewport->update();
+}
+
+bool CanvasItemEditor::box_selection_end() {
+ print_line( "box selection end" );
+
+ Node* scene = get_scene()->get_root_node()->cast_to<EditorNode>()->get_edited_scene();
+ if (scene) {
+
+ List<CanvasItem*> selitems;
+
+ Point2 bsfrom = transform.xform(drag_from);
+ Point2 bsto= transform.xform(box_selecting_to);
+ if (bsfrom.x>bsto.x)
+ SWAP(bsfrom.x,bsto.x);
+ if (bsfrom.y>bsto.y)
+ SWAP(bsfrom.y,bsto.y);
+
+ if ( bsfrom.distance_to( bsto ) < 3 ) {
+ print_line( "box selection too small" );
+ box_selecting=false;
+ viewport->update();
+ return false;
+ }
+
+ _find_canvas_items_at_rect(Rect2(bsfrom,bsto-bsfrom),scene,transform,&selitems);
+
+ for(List<CanvasItem*>::Element *E=selitems.front();E;E=E->next()) {
+
+ _append_canvas_item(E->get());
+ }
+
+ }
+
+ box_selecting=false;
+ viewport->update();
+
+ return true;
+}
+#endif
+
+void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
+
+ hb->add_child(p_control);
+}
+
+HSplitContainer *CanvasItemEditor::get_palette_split() {
+
+ return palette_split;
+}
+
+VSplitContainer *CanvasItemEditor::get_bottom_split() {
+
+ return bottom_split;
+}
+
+
+void CanvasItemEditor::focus_selection() {
+ _focus_selection(VIEW_CENTER_TO_SELECTION);
+}
+
+
+CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
+
+ tool = TOOL_SELECT;
+ undo_redo=p_editor->get_undo_redo();
+ editor=p_editor;
+ editor_selection=p_editor->get_editor_selection();
+ editor_selection->add_editor_plugin(this);
+ editor_selection->connect("selection_changed",this,"update");
+
+
+ hb = memnew( HBoxContainer );
+ add_child( hb );
+ hb->set_area_as_parent_rect();
+
+ bottom_split = memnew( VSplitContainer );
+ bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(bottom_split);
+
+ palette_split = memnew( HSplitContainer);
+ palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
+ bottom_split->add_child(palette_split);
+
+ Control *vp_base = memnew (Control);
+ vp_base->set_v_size_flags(SIZE_EXPAND_FILL);
+ palette_split->add_child(vp_base);
+
+ ViewportContainer *vp = memnew (ViewportContainer);
+ vp->set_stretch(true);
+ vp_base->add_child(vp);
+ vp->set_area_as_parent_rect();
+ vp->add_child(p_editor->get_scene_root());
+
+
+ viewport = memnew( CanvasItemEditorViewport(p_editor, this) );
+ vp_base->add_child(viewport);
+ viewport->set_area_as_parent_rect();
+ viewport->set_clip_contents(true);
+
+ h_scroll = memnew( HScrollBar );
+ v_scroll = memnew( VScrollBar );
+
+ viewport->add_child(h_scroll);
+ viewport->add_child(v_scroll);
+ viewport->connect("draw",this,"_viewport_draw");
+ viewport->connect("gui_input",this,"_viewport_gui_input");
+
+
+ h_scroll->connect("value_changed", this,"_update_scroll",Vector<Variant>(),Object::CONNECT_DEFERRED);
+ v_scroll->connect("value_changed", this,"_update_scroll",Vector<Variant>(),Object::CONNECT_DEFERRED);
+
+ h_scroll->hide();
+ v_scroll->hide();
+ updating_scroll=false;
+ viewport->set_focus_mode(FOCUS_ALL);
+ handle_len=10;
+ first_update=true;
+
+
+ select_button = memnew( ToolButton );
+ select_button->set_toggle_mode(true);
+ hb->add_child(select_button);
+ select_button->connect("pressed",this,"_tool_select",make_binds(TOOL_SELECT));
+ select_button->set_pressed(true);
+ select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode",TTR("Select Mode"),KEY_Q));
+ select_button->set_tooltip(TTR("Select Mode")+" $sc\n"+keycode_get_string(KEY_MASK_CMD)+TTR("Drag: Rotate")+"\n"+TTR("Alt+Drag: Move")+"\n"+TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).")+"\n"+TTR("Alt+RMB: Depth list selection"));
+
+
+ move_button = memnew( ToolButton );
+ move_button->set_toggle_mode(true);
+ hb->add_child(move_button);
+ move_button->connect("pressed",this,"_tool_select",make_binds(TOOL_MOVE));
+ move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode",TTR("Move Mode"),KEY_W));
+ move_button->set_tooltip(TTR("Move Mode"));
+
+ rotate_button = memnew( ToolButton );
+ rotate_button->set_toggle_mode(true);
+ hb->add_child(rotate_button);
+ rotate_button->connect("pressed",this,"_tool_select",make_binds(TOOL_ROTATE));
+ rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode",TTR("Rotate Mode"),KEY_E));
+ rotate_button->set_tooltip(TTR("Rotate Mode"));
+
+ 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(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select 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(TTR("Click to change object's rotation pivot."));
+
+ pan_button = memnew( ToolButton );
+ pan_button->set_toggle_mode(true);
+ hb->add_child(pan_button);
+ pan_button->connect("pressed",this,"_tool_select",make_binds(TOOL_PAN));
+ pan_button->set_tooltip(TTR("Pan Mode"));
+
+ hb->add_child(memnew(VSeparator));
+
+ lock_button = memnew( ToolButton );
+ hb->add_child(lock_button);
+
+ lock_button->connect("pressed",this,"_popup_callback",varray(LOCK_SELECTED));
+ lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved)."));
+
+ unlock_button = memnew( ToolButton );
+ hb->add_child(unlock_button);
+ unlock_button->connect("pressed",this,"_popup_callback",varray(UNLOCK_SELECTED));
+ unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved)."));
+
+ group_button = memnew( ToolButton );
+ hb->add_child(group_button);
+ group_button->connect("pressed",this,"_popup_callback",varray(GROUP_SELECTED));
+ group_button->set_tooltip(TTR("Makes sure the object's children are not selectable."));
+
+ ungroup_button = memnew( ToolButton );
+ hb->add_child(ungroup_button);
+ ungroup_button->connect("pressed",this,"_popup_callback",varray(UNGROUP_SELECTED));
+ ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected."));
+
+ hb->add_child(memnew(VSeparator));
+
+ edit_menu = memnew( MenuButton );
+ edit_menu->set_text(TTR("Edit"));
+ hb->add_child(edit_menu);
+ edit_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
+
+ PopupMenu *p;
+ p = edit_menu->get_popup();
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap")), SNAP_USE);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid")), SNAP_SHOW_GRID);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap..")), SNAP_CONFIGURE);
+ p->add_separator();
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/expand_to_parent", TTR("Expand to Parent"), KEY_MASK_CMD | KEY_P), EXPAND_TO_PARENT);
+ p->add_separator();
+ p->add_submenu_item(TTR("Skeleton.."),"skeleton");
+ skeleton_menu = memnew(PopupMenu);
+ p->add_child(skeleton_menu);
+ skeleton_menu->set_name("skeleton");
+ skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B ),SKELETON_MAKE_BONES);
+ skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES);
+ skeleton_menu->add_separator();
+ skeleton_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
+ skeleton_menu->add_separator();
+ skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
+ skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
+ skeleton_menu->connect("id_pressed", this,"_popup_callback");
+
+
+ /*
+ p->add_item("Align Horizontal",ALIGN_HORIZONTAL);
+ p->add_item("Align Vertical",ALIGN_VERTICAL);
+ p->add_item("Space Horizontal",SPACE_HORIZONTAL);
+ p->add_item("Space Vertical",SPACE_VERTICAL);*/
+
+ view_menu = memnew( MenuButton );
+ view_menu->set_text(TTR("View"));
+ hb->add_child(view_menu);
+ view_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
+
+ p = view_menu->get_popup();
+
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_in", TTR("Zoom In")), ZOOM_IN);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_out", TTR("Zoom Out")), ZOOM_OUT);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset")), ZOOM_RESET);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_set", TTR("Zoom Set..")), ZOOM_SET);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
+
+ anchor_menu = memnew( MenuButton );
+ anchor_menu->set_text(TTR("Anchor"));
+ hb->add_child(anchor_menu);
+ anchor_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
+ anchor_menu->hide();
+
+ //p = anchor_menu->get_popup();
+
+
+
+ animation_hb = memnew( HBoxContainer );
+ hb->add_child(animation_hb);
+ animation_hb->add_child( memnew( VSeparator ));
+ animation_hb->hide();
+
+ key_loc_button = memnew( Button("loc"));
+ key_loc_button->set_toggle_mode(true);
+ key_loc_button->set_pressed(true);
+ key_loc_button->set_focus_mode(FOCUS_NONE);
+ key_loc_button->add_color_override("font_color",Color(1,0.6,0.6));
+ key_loc_button->add_color_override("font_color_pressed",Color(0.6,1,0.6));
+ key_loc_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_POS));
+ animation_hb->add_child(key_loc_button);
+ key_rot_button = memnew( Button("rot"));
+ key_rot_button->set_toggle_mode(true);
+ key_rot_button->set_pressed(true);
+ key_rot_button->set_focus_mode(FOCUS_NONE);
+ key_rot_button->add_color_override("font_color",Color(1,0.6,0.6));
+ key_rot_button->add_color_override("font_color_pressed",Color(0.6,1,0.6));
+ key_rot_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_ROT));
+ animation_hb->add_child(key_rot_button);
+ key_scale_button = memnew( Button("scl"));
+ key_scale_button->set_toggle_mode(true);
+ key_scale_button->set_focus_mode(FOCUS_NONE);
+ key_scale_button->add_color_override("font_color",Color(1,0.6,0.6));
+ key_scale_button->add_color_override("font_color_pressed",Color(0.6,1,0.6));
+ key_scale_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_SCALE));
+ animation_hb->add_child(key_scale_button);
+ key_insert_button = memnew( Button );
+ key_insert_button->set_focus_mode(FOCUS_NONE);
+ key_insert_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_KEY));
+ key_insert_button->set_tooltip(TTR("Insert Keys"));
+ key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), KEY_INSERT));
+
+ animation_hb->add_child(key_insert_button);
+
+ animation_menu = memnew( MenuButton );
+ animation_menu->set_text(TTR("Animation"));
+ animation_hb->add_child(animation_menu);
+ animation_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
+
+ p = animation_menu->get_popup();
+
+ p->add_shortcut(ED_GET_SHORTCUT("canvas_item_editor/anim_insert_key"), ANIM_INSERT_KEY);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key_existing_tracks", TTR("Insert Key (Existing Tracks)"), KEY_MASK_CMD+KEY_INSERT), ANIM_INSERT_KEY_EXISTING);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_copy_pose", TTR("Copy Pose")), ANIM_COPY_POSE);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_paste_pose", TTR("Paste Pose")), ANIM_PASTE_POSE);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_clear_pose", TTR("Clear Pose"), KEY_MASK_SHIFT | KEY_K), ANIM_CLEAR_POSE);
+
+ snap_dialog = memnew( SnapDialog );
+ snap_dialog->connect("confirmed",this,"_snap_changed");
+ add_child(snap_dialog);
+
+ value_dialog = memnew( AcceptDialog );
+ value_dialog->set_title(TTR("Set a Value"));
+ value_dialog->get_ok()->set_text(TTR("Close"));
+ add_child(value_dialog);
+
+ Label *l = memnew(Label);
+ l->set_text(TTR("Snap (Pixels):"));
+ l->set_pos(Point2(5,5));
+ value_dialog->add_child(l);
+ dialog_label=l;
+
+ dialog_val=memnew(SpinBox);
+ dialog_val->set_anchor(MARGIN_RIGHT,ANCHOR_END);
+ dialog_val->set_begin(Point2(15,25));
+ dialog_val->set_end(Point2(10,25));
+ value_dialog->add_child(dialog_val);
+ dialog_val->connect("value_changed",this,"_dialog_value_changed");
+ select_sb = Ref<StyleBoxTexture>( memnew( StyleBoxTexture) );
+
+ selection_menu = memnew( PopupMenu );
+ add_child(selection_menu);
+ selection_menu->set_custom_minimum_size(Vector2(100, 0));
+ selection_menu->connect("id_pressed", this, "_selection_result_pressed");
+ selection_menu->connect("popup_hide", this, "_selection_menu_hide");
+
+ key_pos=true;
+ key_rot=true;
+ key_scale=false;
+
+ zoom=1;
+ snap_offset=Vector2(0, 0);
+ snap_step=Vector2(10, 10);
+ snap_rotation_offset=0;
+ snap_rotation_step=15 / (180 / Math_PI);
+ snap_grid=false;
+ snap_show_grid=false;
+ snap_rotation=false;
+ snap_pixel=false;
+ skeleton_show_bones=true;
+ skeleton_menu->set_item_checked(skeleton_menu->get_item_index(SKELETON_SHOW_BONES),true);
+ updating_value_dialog=false;
+ box_selecting=false;
+ //zoom=0.5;
+ singleton=this;
+
+ set_process_unhandled_key_input(true);
+ can_move_pivot=false;
+ drag=DRAG_NONE;
+ bone_last_frame=0;
+ additive_selection=false;
+}
+
+CanvasItemEditor *CanvasItemEditor::singleton=NULL;
+
+void CanvasItemEditorPlugin::edit(Object *p_object) {
+
+ canvas_item_editor->set_undo_redo(&get_undo_redo());
+ canvas_item_editor->edit(p_object->cast_to<CanvasItem>());
+}
+
+bool CanvasItemEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("CanvasItem");
+}
+
+void CanvasItemEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ canvas_item_editor->show();
+ canvas_item_editor->set_fixed_process(true);
+ VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(),false);
+ canvas_item_editor->viewport->grab_focus();
+
+ } else {
+
+ canvas_item_editor->hide();
+ canvas_item_editor->set_fixed_process(false);
+ VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(),true);
+ }
+
+}
+
+Dictionary CanvasItemEditorPlugin::get_state() const {
+
+ return canvas_item_editor->get_state();
+}
+void CanvasItemEditorPlugin::set_state(const Dictionary& p_state) {
+
+ canvas_item_editor->set_state(p_state);
+}
+
+CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ canvas_item_editor = memnew( CanvasItemEditor(editor) );
+ canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ editor->get_viewport()->add_child(canvas_item_editor);
+ canvas_item_editor->set_area_as_parent_rect();
+ canvas_item_editor->hide();
+
+}
+
+
+CanvasItemEditorPlugin::~CanvasItemEditorPlugin()
+{
+}
+
+
+void CanvasItemEditorViewport::_on_mouse_exit() {
+ if (!selector->is_visible()){
+ _remove_preview();
+ }
+}
+
+void CanvasItemEditorViewport::_on_select_type(Object* selected) {
+ CheckBox* check = selected->cast_to<CheckBox>();
+ String type = check->get_text();
+ selector_label->set_text(vformat(TTR("Add %s"),type));
+ label->set_text(vformat(TTR("Adding %s..."),type));
+}
+
+void CanvasItemEditorViewport::_on_change_type() {
+ if (!button_group->get_pressed_button())
+ return;
+
+ CheckBox* check=button_group->get_pressed_button()->cast_to<CheckBox>();
+ default_type=check->get_text();
+ _perform_drop_data();
+ selector->hide();
+}
+
+void CanvasItemEditorViewport::_create_preview(const Vector<String>& files) const {
+ label->set_pos(get_global_pos()+Point2(14,14));
+ label_desc->set_pos(label->get_pos()+Point2(0,label->get_size().height));
+ for (int i=0;i<files.size();i++) {
+ String path=files[i];
+ RES res=ResourceLoader::load(path);
+ String type=res->get_class();
+ if (type=="ImageTexture" || type=="PackedScene") {
+ if (type=="ImageTexture") {
+ Ref<ImageTexture> texture=Ref<ImageTexture> ( ResourceCache::get(path)->cast_to<ImageTexture>() );
+ Sprite* sprite=memnew(Sprite);
+ sprite->set_texture(texture);
+ sprite->set_modulate(Color(1,1,1,0.7f));
+ preview->add_child(sprite);
+ label->show();
+ label_desc->show();
+ } else if (type=="PackedScene") {
+ Ref<PackedScene> scn=ResourceLoader::load(path);
+ if (scn.is_valid()){
+ Node* instance=scn->instance();
+ if (instance){
+ preview->add_child(instance);
+ }
+ }
+ }
+ editor->get_scene_root()->add_child(preview);
+ }
+ }
+}
+
+void CanvasItemEditorViewport::_remove_preview() {
+ if (preview->get_parent()){
+ editor->get_scene_root()->remove_child(preview);
+ for (int i=preview->get_child_count()-1;i>=0;i--){
+ Node* node=preview->get_child(i);
+ memdelete(node);
+ }
+ label->hide();
+ label_desc->hide();
+ }
+}
+
+bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) {
+ if (p_desired_node->get_filename()==p_target_scene_path) {
+ return true;
+ }
+
+ int childCount=p_desired_node->get_child_count();
+ for (int i=0;i<childCount;i++) {
+ Node* child=p_desired_node->get_child(i);
+ if(_cyclical_dependency_exists(p_target_scene_path,child)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void CanvasItemEditorViewport::_create_nodes(Node* parent, Node* child, String& path, const Point2& p_point) {
+ child->set_name(path.get_file().get_basename());
+ Ref<ImageTexture> texture=Ref<ImageTexture> ( ResourceCache::get(path)->cast_to<ImageTexture>() );
+ Size2 texture_size = texture->get_size();
+
+ editor_data->get_undo_redo().add_do_method(parent,"add_child",child);
+ editor_data->get_undo_redo().add_do_method(child,"set_owner",editor->get_edited_scene());
+ editor_data->get_undo_redo().add_do_reference(child);
+ editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child);
+
+ String new_name=parent->validate_child_name(child);
+ ScriptEditorDebugger *sed=ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",editor->get_edited_scene()->get_path_to(parent),child->get_class(),new_name);
+ editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(editor->get_edited_scene()->get_path_to(parent))+"/"+new_name));
+
+ // handle with different property for texture
+ String property = "texture";
+ List<PropertyInfo> props;
+ child->get_property_list(&props);
+ for(const List<PropertyInfo>::Element *E=props.front();E;E=E->next() ) {
+ if (E->get().name=="config/texture") { // Particles2D
+ property="config/texture";
+ break;
+ } else if (E->get().name=="texture/texture") { // Polygon2D
+ property="texture/texture";
+ break;
+ } else if (E->get().name=="normal") { // TouchScreenButton
+ property="normal";
+ break;
+ }
+ }
+ editor_data->get_undo_redo().add_do_property(child,property,texture);
+
+ // make visible for certain node type
+ if (default_type=="Patch9Rect") {
+ editor_data->get_undo_redo().add_do_property(child,"rect/size",texture_size);
+ } else if (default_type=="Polygon2D") {
+ PoolVector<Vector2> list;
+ list.push_back(Vector2(0,0));
+ list.push_back(Vector2(texture_size.width,0));
+ list.push_back(Vector2(texture_size.width,texture_size.height));
+ list.push_back(Vector2(0,texture_size.height));
+ editor_data->get_undo_redo().add_do_property(child,"polygon",list);
+ }
+
+ // locate at preview position
+ Point2 pos;
+ if (parent->has_method("get_global_pos")) {
+ pos=parent->call("get_global_pos");
+ }
+ Transform2D trans=canvas->get_canvas_transform();
+ Point2 target_pos = (p_point-trans.get_origin())/trans.get_scale().x-pos;
+ if (default_type=="Polygon2D" || default_type=="TouchScreenButton" || default_type=="TextureRect" || default_type=="Patch9Rect") {
+ target_pos -= texture_size/2;
+ }
+ editor_data->get_undo_redo().add_do_method(child,"set_pos",target_pos);
+}
+
+bool CanvasItemEditorViewport::_create_instance(Node* parent, String& path, const Point2& p_point) {
+ Ref<PackedScene> sdata=ResourceLoader::load(path);
+ if (!sdata.is_valid()) { // invalid scene
+ return false;
+ }
+
+ Node* instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ if (!instanced_scene) { // error on instancing
+ return false;
+ }
+
+ if (editor->get_edited_scene()->get_filename()!="") { // cyclical instancing
+ if (_cyclical_dependency_exists(editor->get_edited_scene()->get_filename(), instanced_scene)) {
+ memdelete(instanced_scene);
+ return false;
+ }
+ }
+
+ instanced_scene->set_filename( GlobalConfig::get_singleton()->localize_path(path) );
+
+ editor_data->get_undo_redo().add_do_method(parent,"add_child",instanced_scene);
+ editor_data->get_undo_redo().add_do_method(instanced_scene,"set_owner",editor->get_edited_scene());
+ editor_data->get_undo_redo().add_do_reference(instanced_scene);
+ editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene);
+
+ String new_name=parent->validate_child_name(instanced_scene);
+ ScriptEditorDebugger *sed=ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",editor->get_edited_scene()->get_path_to(parent),path,new_name);
+ editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(editor->get_edited_scene()->get_path_to(parent))+"/"+new_name));
+
+ Point2 pos;
+ Node2D* parent_node2d=parent->cast_to<Node2D>();
+ if (parent_node2d) {
+ pos=parent_node2d->get_global_position();
+ } else {
+ Control* parent_control=parent->cast_to<Control>();
+ if (parent_control) {
+ pos=parent_control->get_global_pos();
+ }
+ }
+ Transform2D trans=canvas->get_canvas_transform();
+ editor_data->get_undo_redo().add_do_method(instanced_scene,"set_pos",(p_point-trans.get_origin())/trans.get_scale().x-pos);
+
+ return true;
+}
+
+void CanvasItemEditorViewport::_perform_drop_data(){
+ _remove_preview();
+
+ Vector<String> error_files;
+
+ editor_data->get_undo_redo().create_action(TTR("Create Node"));
+
+ for (int i=0;i<selected_files.size();i++) {
+ String path=selected_files[i];
+ RES res=ResourceLoader::load(path);
+ if (res.is_null()) {
+ continue;
+ }
+ String type=res->get_class();
+ if (type=="ImageTexture") {
+ Node* child;
+ if (default_type=="Light2D") child=memnew(Light2D);
+ else if (default_type=="Particles2D") child=memnew(Particles2D);
+ else if (default_type=="Polygon2D") child=memnew(Polygon2D);
+ else if (default_type=="TouchScreenButton") child=memnew(TouchScreenButton);
+ else if (default_type=="TextureRect") child=memnew(TextureRect);
+ else if (default_type=="Patch9Rect") child=memnew(NinePatchRect);
+ else child=memnew(Sprite); // default
+
+ _create_nodes(target_node, child, path, drop_pos);
+ } else if (type=="PackedScene") {
+ bool success=_create_instance(target_node, path, drop_pos);
+ if (!success) {
+ error_files.push_back(path);
+ }
+ }
+ }
+
+ editor_data->get_undo_redo().commit_action();
+
+ if (error_files.size()>0) {
+ String files_str;
+ for (int i=0;i<error_files.size();i++) {
+ files_str += error_files[i].get_file().get_basename() + ",";
+ }
+ files_str=files_str.substr(0,files_str.length()-1);
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(vformat(TTR("Error instancing scene from %s"),files_str.c_str()));
+ accept->popup_centered_minsize();
+ }
+}
+
+bool CanvasItemEditorViewport::can_drop_data(const Point2& p_point,const Variant& p_data) const {
+ Dictionary d=p_data;
+ if (d.has("type")) {
+ if (String(d["type"])=="files") {
+ Vector<String> files=d["files"];
+ bool can_instance=false;
+ for (int i=0;i<files.size();i++) { // check if dragged files contain resource or scene can be created at least one
+ RES res=ResourceLoader::load(files[i]);
+ if (res.is_null()) {
+ continue;
+ }
+ String type=res->get_class();
+ if (type=="PackedScene") {
+ Ref<PackedScene> sdata=ResourceLoader::load(files[i]);
+ Node* instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ if (!instanced_scene) {
+ continue;
+ }
+ memdelete(instanced_scene);
+ }
+ can_instance=true;
+ break;
+ }
+ if (can_instance) {
+ if (!preview->get_parent()){ // create preview only once
+ _create_preview(files);
+ }
+ Transform2D trans=canvas->get_canvas_transform();
+ preview->set_position((p_point-trans.get_origin())/trans.get_scale().x);
+ label->set_text(vformat(TTR("Adding %s..."),default_type));
+ }
+ return can_instance;
+ }
+ }
+ label->hide();
+ return false;
+}
+
+void CanvasItemEditorViewport::drop_data(const Point2& p_point,const Variant& p_data) {
+ bool is_shift=Input::get_singleton()->is_key_pressed(KEY_SHIFT);
+ bool is_alt=Input::get_singleton()->is_key_pressed(KEY_ALT);
+
+ selected_files.clear();
+ Dictionary d=p_data;
+ if (d.has("type") && String(d["type"])=="files"){
+ selected_files=d["files"];
+ }
+
+ List<Node*> list=editor->get_editor_selection()->get_selected_node_list();
+ if (list.size()==0) {
+ accept->get_ok()->set_text(TTR("OK :("));
+ accept->set_text(TTR("No parent to instance a child at."));
+ accept->popup_centered_minsize();
+ _remove_preview();
+ return;
+ }
+ if (list.size()!=1) {
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("This operation requires a single selected node."));
+ accept->popup_centered_minsize();
+ _remove_preview();
+ return;
+ }
+
+ target_node=list[0];
+ if (is_shift && target_node!=editor->get_edited_scene()) {
+ target_node=target_node->get_parent();
+ }
+ drop_pos=p_point;
+
+ if (is_alt) {
+ List<BaseButton*> btn_list;
+ button_group->get_buttons(&btn_list);
+
+ for (int i=0;i<btn_list.size();i++) {
+ CheckBox* check=btn_list[i]->cast_to<CheckBox>();
+ check->set_pressed(check->get_text()==default_type);
+ }
+ selector_label->set_text(vformat(TTR("Add %s"),default_type));
+ selector->popup_centered_minsize();
+ } else {
+ _perform_drop_data();
+ }
+}
+
+void CanvasItemEditorViewport::_notification(int p_what) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ connect("mouse_exited",this,"_on_mouse_exit");
+ } else if (p_what==NOTIFICATION_EXIT_TREE) {
+ disconnect("mouse_exited",this,"_on_mouse_exit");
+ }
+}
+
+void CanvasItemEditorViewport::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_on_select_type"),&CanvasItemEditorViewport::_on_select_type);
+ ClassDB::bind_method(D_METHOD("_on_change_type"),&CanvasItemEditorViewport::_on_change_type);
+ ClassDB::bind_method(D_METHOD("_on_mouse_exit"),&CanvasItemEditorViewport::_on_mouse_exit);
+}
+
+CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor* p_canvas) {
+ default_type="Sprite";
+ // Node2D
+ types.push_back("Sprite");
+ types.push_back("Light2D");
+ types.push_back("Particles2D");
+ types.push_back("Polygon2D");
+ types.push_back("TouchScreenButton");
+ // Control
+ types.push_back("TextureRect");
+ types.push_back("Patch9Rect");
+
+ target_node=NULL;
+ editor=p_node;
+ editor_data=editor->get_scene_tree_dock()->get_editor_data();
+ canvas=p_canvas;
+ preview=memnew( Node2D );
+ accept=memnew( AcceptDialog );
+ editor->get_gui_base()->add_child(accept);
+
+ selector=memnew( WindowDialog );
+ selector->set_title(TTR("Change default type"));
+
+ VBoxContainer* vbc=memnew(VBoxContainer);
+ vbc->add_constant_override("separation",10*EDSCALE);
+ vbc->set_custom_minimum_size(Size2(200,260)*EDSCALE);
+
+ selector_label=memnew(Label);
+ selector_label->set_align(Label::ALIGN_CENTER);
+ selector_label->set_valign(Label::VALIGN_BOTTOM);
+ selector_label->set_custom_minimum_size(Size2(0,30)*EDSCALE);
+ vbc->add_child(selector_label);
+
+ button_group.instance();
+
+ btn_group=memnew( VBoxContainer );
+ btn_group->set_h_size_flags(0);
+ btn_group->connect("button_selected", this, "_on_select_type");
+
+ for (int i=0;i<types.size();i++) {
+ CheckBox* check=memnew(CheckBox);
+ check->set_text(types[i]);
+ btn_group->add_child(check);
+ check->set_button_group(button_group);
+ }
+ vbc->add_child(btn_group);
+
+ Button* ok=memnew(Button);
+ ok->set_text(TTR("OK"));
+ ok->set_h_size_flags(0);
+ vbc->add_child(ok);
+ ok->connect("pressed", this, "_on_change_type");
+
+ selector->add_child(vbc);
+ editor->get_gui_base()->add_child(selector);
+
+ label=memnew(Label);
+ label->add_color_override("font_color", Color(1,1,0,1));
+ label->add_color_override("font_color_shadow", Color(0,0,0,1));
+ label->add_constant_override("shadow_as_outline", 1*EDSCALE);
+ label->hide();
+ editor->get_gui_base()->add_child(label);
+
+ label_desc=memnew(Label);
+ label_desc->set_text(TTR("Drag & drop + Shift : Add node as sibling\nDrag & drop + Alt : Change node type"));
+ label_desc->add_color_override("font_color", Color(0.6,0.6,0.6,1));
+ label_desc->add_color_override("font_color_shadow", Color(0.2,0.2,0.2,1));
+ label_desc->add_constant_override("shadow_as_outline", 1*EDSCALE);
+ label_desc->add_constant_override("line_spacing", 0);
+ label_desc->hide();
+ editor->get_gui_base()->add_child(label_desc);
+}
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
new file mode 100644
index 0000000000..0c2dcdff3d
--- /dev/null
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -0,0 +1,503 @@
+/*************************************************************************/
+/* canvas_item_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 CONTROL_EDITOR_PLUGIN_H
+#define CONTROL_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/gui/button_group.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/label.h"
+#include "scene/gui/spin_box.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/box_container.h"
+#include "scene/2d/canvas_item.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class CanvasItemEditorViewport;
+
+class CanvasItemEditorSelectedItem : public Object {
+
+ GDCLASS(CanvasItemEditorSelectedItem,Object);
+public:
+ Variant undo_state;
+ Vector2 undo_pivot;
+
+ Transform2D prev_xform;
+ float prev_rot;
+ Rect2 prev_rect;
+
+ CanvasItemEditorSelectedItem() { prev_rot=0; }
+};
+
+class CanvasItemEditor : public VBoxContainer {
+
+ GDCLASS(CanvasItemEditor, VBoxContainer );
+
+ EditorNode *editor;
+
+
+ enum Tool {
+
+ TOOL_SELECT,
+ TOOL_LIST_SELECT,
+ TOOL_MOVE,
+ TOOL_ROTATE,
+ TOOL_EDIT_PIVOT,
+ TOOL_PAN,
+ TOOL_MAX
+ };
+
+ enum MenuOption {
+ SNAP_USE,
+ SNAP_SHOW_GRID,
+ SNAP_USE_ROTATION,
+ SNAP_RELATIVE,
+ SNAP_CONFIGURE,
+ SNAP_USE_PIXEL,
+ ZOOM_IN,
+ ZOOM_OUT,
+ ZOOM_RESET,
+ ZOOM_SET,
+ LOCK_SELECTED,
+ UNLOCK_SELECTED,
+ GROUP_SELECTED,
+ UNGROUP_SELECTED,
+ ALIGN_HORIZONTAL,
+ ALIGN_VERTICAL,
+ ANCHOR_ALIGN_TOP_LEFT,
+ ANCHOR_ALIGN_TOP_RIGHT,
+ ANCHOR_ALIGN_BOTTOM_LEFT,
+ ANCHOR_ALIGN_BOTTOM_RIGHT,
+ ANCHOR_ALIGN_CENTER_LEFT,
+ ANCHOR_ALIGN_CENTER_RIGHT,
+ ANCHOR_ALIGN_CENTER_TOP,
+ ANCHOR_ALIGN_CENTER_BOTTOM,
+ ANCHOR_ALIGN_CENTER,
+ ANCHOR_ALIGN_TOP_WIDE,
+ ANCHOR_ALIGN_LEFT_WIDE,
+ ANCHOR_ALIGN_RIGHT_WIDE,
+ ANCHOR_ALIGN_BOTTOM_WIDE,
+ ANCHOR_ALIGN_VCENTER_WIDE,
+ ANCHOR_ALIGN_HCENTER_WIDE,
+ ANCHOR_ALIGN_WIDE,
+
+ SPACE_HORIZONTAL,
+ SPACE_VERTICAL,
+ EXPAND_TO_PARENT,
+ ANIM_INSERT_KEY,
+ ANIM_INSERT_KEY_EXISTING,
+ ANIM_INSERT_POS,
+ ANIM_INSERT_ROT,
+ ANIM_INSERT_SCALE,
+ ANIM_COPY_POSE,
+ ANIM_PASTE_POSE,
+ ANIM_CLEAR_POSE,
+ VIEW_CENTER_TO_SELECTION,
+ VIEW_FRAME_TO_SELECTION,
+ SKELETON_MAKE_BONES,
+ SKELETON_CLEAR_BONES,
+ SKELETON_SHOW_BONES,
+ SKELETON_SET_IK_CHAIN,
+ SKELETON_CLEAR_IK_CHAIN
+
+ };
+
+ enum DragType {
+ DRAG_NONE,
+ DRAG_LEFT,
+ DRAG_TOP_LEFT,
+ DRAG_TOP,
+ DRAG_TOP_RIGHT,
+ DRAG_RIGHT,
+ DRAG_BOTTOM_RIGHT,
+ DRAG_BOTTOM,
+ DRAG_BOTTOM_LEFT,
+ DRAG_ALL,
+ DRAG_ROTATE,
+ DRAG_PIVOT,
+
+ };
+
+ enum KeyMoveMODE {
+ MOVE_VIEW_BASE,
+ MOVE_LOCAL_BASE,
+ MOVE_LOCAL_WITH_ROT
+ };
+
+ EditorSelection *editor_selection;
+ bool additive_selection;
+
+ Tool tool;
+ bool first_update;
+ Control *viewport;
+
+ bool can_move_pivot;
+
+ HScrollBar *h_scroll;
+ VScrollBar *v_scroll;
+ HBoxContainer *hb;
+
+ Transform2D transform;
+ float zoom;
+ Vector2 snap_offset;
+ Vector2 snap_step;
+ float snap_rotation_step;
+ float snap_rotation_offset;
+ bool snap_grid;
+ bool snap_show_grid;
+ bool snap_rotation;
+ bool snap_relative;
+ bool snap_pixel;
+ bool skeleton_show_bones;
+ bool box_selecting;
+ Point2 box_selecting_to;
+ bool key_pos;
+ bool key_rot;
+ bool key_scale;
+
+ void _tool_select(int p_index);
+
+
+ MenuOption last_option;
+
+ struct _SelectResult {
+
+ CanvasItem* item;
+ float z;
+ bool has_z;
+ _FORCE_INLINE_ bool operator<(const _SelectResult& p_rr) const {
+ return has_z && p_rr.has_z ? p_rr.z < z : p_rr.has_z;
+ }
+ };
+
+ Vector<_SelectResult> selection_results;
+
+ struct LockList {
+ Point2 pos;
+ bool lock;
+ bool group;
+ LockList() { lock=false; group=false; }
+ };
+
+ List<LockList> lock_list;
+
+ struct BoneList {
+
+ Transform2D xform;
+ Vector2 from;
+ Vector2 to;
+ ObjectID bone;
+ uint64_t last_pass;
+ };
+
+ uint64_t bone_last_frame;
+ Map<ObjectID,BoneList> bone_list;
+
+ Transform2D bone_orig_xform;
+
+ struct BoneIK {
+
+ Variant orig_state;
+ Vector2 pos;
+ float len;
+ Node2D *node;
+ };
+
+ List<BoneIK> bone_ik_list;
+
+ struct PoseClipboard {
+
+ Vector2 pos;
+ Vector2 scale;
+ float rot;
+ ObjectID id;
+ };
+
+ 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;
+ ToolButton *unlock_button;
+
+ ToolButton *group_button;
+ ToolButton *ungroup_button;
+
+ MenuButton *edit_menu;
+ PopupMenu *skeleton_menu;
+ MenuButton *view_menu;
+ HBoxContainer *animation_hb;
+ MenuButton *animation_menu;
+ MenuButton *anchor_menu;
+
+ Button *key_loc_button;
+ Button *key_rot_button;
+ Button *key_scale_button;
+ Button *key_insert_button;
+
+ PopupMenu *selection_menu;
+
+
+ //PopupMenu *popup;
+ DragType drag;
+ Point2 drag_from;
+ Point2 drag_point_from;
+ bool updating_value_dialog;
+ Point2 display_rotate_from;
+ Point2 display_rotate_to;
+#if 0
+ struct EditInfo {
+
+ Variant undo_state;
+
+ Matrix32 prev_xform;
+ float prev_rot;
+ Rect2 prev_rect;
+ EditInfo() { prev_rot=0; }
+ };
+
+ typedef Map<CanvasItem*,EditInfo> CanvasItemMap;
+ CanvasItemMap canvas_items;
+#endif
+ Ref<StyleBoxTexture> select_sb;
+ Ref<Texture> select_handle;
+
+
+ int handle_len;
+ bool _is_part_of_subscene(CanvasItem *p_item);
+ CanvasItem* _select_canvas_item_at_pos(const Point2 &p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform);
+ void _find_canvas_items_at_pos(const Point2 &p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform, Vector<_SelectResult> &r_items);
+ void _find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform,List<CanvasItem*> *r_items);
+
+ bool _select(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag=true);
+
+ ConfirmationDialog *snap_dialog;
+
+ AcceptDialog *value_dialog;
+ Label *dialog_label;
+ SpinBox *dialog_val;
+
+ 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 Transform2D& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point);
+
+ void _popup_callback(int p_op);
+ bool updating_scroll;
+ void _update_scroll(float);
+ void _update_scrollbars();
+ void incbeg(float& beg,float& end, float inc, float minsize,bool p_symmetric);
+ void incend(float& beg,float& end, float inc, float minsize,bool p_symmetric);
+
+ void _append_canvas_item(CanvasItem *p_item);
+ void _dialog_value_changed(double);
+ void _snap_changed();
+ void _selection_result_pressed(int);
+ void _selection_menu_hide();
+
+ UndoRedo *undo_redo;
+
+ Point2 _find_topleftmost_point();
+
+
+ void _find_canvas_items_span(Node *p_node, Rect2& r_rect, const Transform2D& p_xform);
+
+
+ Object *_get_editor_data(Object *p_what);
+
+ CanvasItem *get_single_item();
+ int get_item_count();
+ void _keying_changed();
+
+ void _unhandled_key_input(const InputEvent& p_ev);
+
+ void _viewport_gui_input(const InputEvent& p_event);
+ void _viewport_draw();
+
+ void _focus_selection(int p_op);
+
+ void _set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom);
+
+ HSplitContainer *palette_split;
+ VSplitContainer *bottom_split;
+
+friend class CanvasItemEditorPlugin;
+protected:
+
+
+ void _notification(int p_what);
+
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+ void end_drag();
+ void box_selection_start( Point2 &click );
+ bool box_selection_end();
+
+ HBoxContainer *get_panel_hb() { return hb; }
+
+ struct compare_items_x {
+ bool operator()( const CanvasItem *a, const CanvasItem *b ) const {
+ return a->get_global_transform().elements[2].x < b->get_global_transform().elements[2].x;
+ }
+ };
+
+ struct compare_items_y {
+ bool operator()( const CanvasItem *a, const CanvasItem *b ) const {
+ return a->get_global_transform().elements[2].y < b->get_global_transform().elements[2].y;
+ }
+ };
+
+ struct proj_vector2_x {
+ float get( const Vector2 &v ) { return v.x; }
+ void set( Vector2 &v, float f ) { v.x = f; }
+ };
+
+ struct proj_vector2_y {
+ float get( const Vector2 &v ) { return v.y; }
+ void set( Vector2 &v, float f ) { v.y = f; }
+ };
+
+ template< class P, class C > void space_selected_items();
+
+ static CanvasItemEditor *singleton;
+public:
+
+ Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
+ float snap_angle(float p_target, float p_start = 0) const;
+
+ Transform2D get_canvas_transform() const { return transform; }
+
+ static CanvasItemEditor *get_singleton() { return singleton; }
+ Dictionary get_state() const;
+ void set_state(const Dictionary& p_state);
+
+ void add_control_to_menu_panel(Control *p_control);
+
+ HSplitContainer *get_palette_split();
+ VSplitContainer *get_bottom_split();
+
+ Control *get_viewport_control() { return viewport; }
+
+ bool get_remove_list(List<Node*> *p_list);
+ void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
+ void edit(CanvasItem *p_canvas_item);
+
+ void focus_selection();
+
+ CanvasItemEditor(EditorNode *p_editor);
+};
+
+class CanvasItemEditorPlugin : public EditorPlugin {
+
+ GDCLASS( CanvasItemEditorPlugin, EditorPlugin );
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "2D"; }
+ bool has_main_screen() const { return true; }
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+ virtual void make_visible(bool p_visible);
+ virtual bool get_remove_list(List<Node*> *p_list) { return canvas_item_editor->get_remove_list(p_list); }
+ virtual Dictionary get_state() const;
+ virtual void set_state(const Dictionary& p_state);
+
+ CanvasItemEditor *get_canvas_item_editor() { return canvas_item_editor; }
+
+ CanvasItemEditorPlugin(EditorNode *p_node);
+ ~CanvasItemEditorPlugin();
+
+};
+
+class CanvasItemEditorViewport : public Control {
+ GDCLASS( CanvasItemEditorViewport, Control );
+
+ String default_type;
+ Vector<String> types;
+
+ Vector<String> selected_files;
+ Node* target_node;
+ Point2 drop_pos;
+
+ EditorNode* editor;
+ EditorData* editor_data;
+ CanvasItemEditor* canvas;
+ Node2D* preview;
+ AcceptDialog* accept;
+ WindowDialog* selector;
+ Label* selector_label;
+ Label* label;
+ Label* label_desc;
+ VBoxContainer* btn_group;
+ Ref<ButtonGroup> button_group;
+
+ void _on_mouse_exit();
+ void _on_select_type(Object* selected);
+ void _on_change_type();
+
+ void _create_preview(const Vector<String>& files) const;
+ void _remove_preview();
+
+ bool _cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node);
+ void _create_nodes(Node* parent, Node* child, String& path, const Point2& p_point);
+ bool _create_instance(Node* parent, String& path, const Point2& p_point);
+ void _perform_drop_data();
+
+ static void _bind_methods();
+
+protected:
+ void _notification(int p_what);
+
+public:
+ virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
+ virtual void drop_data(const Point2& p_point,const Variant& p_data);
+
+ CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor* p_canvas);
+};
+
+#endif
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..5a45267c85
--- /dev/null
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -0,0 +1,482 @@
+/*************************************************************************/
+/* collision_polygon_2d_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "collision_polygon_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+
+
+void CollisionPolygon2DEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon( get_icon("Edit","EditorIcons"));
+ button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ button_edit->set_pressed(true);
+ get_tree()->connect("node_removed",this,"_node_removed");
+
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
+}
+
+
+void CollisionPolygon2DEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case MODE_CREATE: {
+
+ mode=MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode=MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+
+ }
+}
+
+void CollisionPolygon2DEditor::_wip_close() {
+
+ undo_redo->create_action(TTR("Create Poly"));
+ undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
+ undo_redo->add_do_method(node,"set_polygon",wip);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ wip.clear();
+ wip_active=false;
+ mode=MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ edited_point=-1;
+}
+
+bool CollisionPolygon2DEditor::forward_gui_input(const InputEvent& p_event) {
+
+
+ if (!node)
+ return false;
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ Vector<Vector2> poly = node->get_polygon();
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
+
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( cpoint );
+ wip_active=true;
+ edited_point_pos=cpoint;
+ canvas_item_editor->get_viewport_control()->update();
+ edited_point=1;
+ return true;
+ } else {
+
+
+ if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close();
+
+ return true;
+ } else {
+
+ wip.push_back( cpoint );
+ edited_point=wip.size();
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close();
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ if (poly.size() < 3) {
+
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.push_back(cpoint);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ //search edges
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 points[2] ={ xform.xform(poly[i]),
+ xform.xform(poly[(i+1)%poly.size()]) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+ if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
+ edited_point=closest_idx+1;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ node->set_polygon(poly);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ edited_point=closest_idx;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly[edited_point]=edited_point_pos;
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ }
+
+
+
+ } break;
+ }
+
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ }
+
+ } break;
+ }
+
+ return false;
+}
+void CollisionPolygon2DEditor::_canvas_draw() {
+
+ if (!node)
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ Vector<Vector2> poly;
+
+ if (wip_active)
+ poly=wip;
+ else
+ poly=node->get_polygon();
+
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
+
+ for(int i=0;i<poly.size();i++) {
+
+
+ Vector2 p,p2;
+ p = i==edited_point ? edited_point_pos : poly[i];
+ if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
+ p2=edited_point_pos;
+ else
+ p2 = poly[(i+1)%poly.size()];
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ Color col=Color(1,0.3,0.1,0.8);
+ vpc->draw_line(point,next_point,col,2);
+ vpc->draw_texture(handle,point-handle->get_size()*0.5);
+ }
+}
+
+
+
+void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton();
+ }
+
+ if (p_collision_polygon) {
+
+ node=p_collision_polygon->cast_to<CollisionPolygon2D>();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+ canvas_item_editor->get_viewport_control()->update();
+
+ } else {
+ node=NULL;
+
+ if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
+
+ }
+
+}
+
+void CollisionPolygon2DEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_menu_option"),&CollisionPolygon2DEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_canvas_draw"),&CollisionPolygon2DEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&CollisionPolygon2DEditor::_node_removed);
+
+}
+
+CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) {
+
+ node=NULL;
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ add_child( memnew( VSeparator ));
+ button_create = memnew( ToolButton );
+ add_child(button_create);
+ button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+ button_create->set_tooltip(TTR("Create a new polygon from scratch."));
+
+ button_edit = memnew( ToolButton );
+ add_child(button_edit);
+ button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.");
+
+ //add_constant_override("separation",0);
+
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+#endif
+
+ mode = MODE_EDIT;
+ wip_active=false;
+
+}
+
+
+void CollisionPolygon2DEditorPlugin::edit(Object *p_object) {
+
+ collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool CollisionPolygon2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("CollisionPolygon2D");
+}
+
+void CollisionPolygon2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ collision_polygon_editor->show();
+ } else {
+
+ collision_polygon_editor->hide();
+ collision_polygon_editor->edit(NULL);
+ }
+
+}
+
+CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ collision_polygon_editor = memnew( CollisionPolygon2DEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+ collision_polygon_editor->hide();
+
+
+
+}
+
+
+CollisionPolygon2DEditorPlugin::~CollisionPolygon2DEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.h b/editor/plugins/collision_polygon_2d_editor_plugin.h
new file mode 100644
index 0000000000..796328753d
--- /dev/null
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.h
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* collision_polygon_2d_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
+#define COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/collision_polygon_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class CollisionPolygon2DEditor : public HBoxContainer {
+
+ GDCLASS(CollisionPolygon2DEditor, HBoxContainer );
+
+ UndoRedo *undo_redo;
+ enum Mode {
+
+ MODE_CREATE,
+ MODE_EDIT,
+
+ };
+
+ Mode mode;
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ CollisionPolygon2D *node;
+ MenuButton *options;
+
+ int edited_point;
+ Vector2 edited_point_pos;
+ Vector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+
+
+ void _wip_close();
+ void _canvas_draw();
+ void _menu_option(int p_option);
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node *p_collision_polygon);
+ CollisionPolygon2DEditor(EditorNode *p_editor);
+};
+
+class CollisionPolygon2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS( CollisionPolygon2DEditorPlugin, EditorPlugin );
+
+ CollisionPolygon2DEditor *collision_polygon_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+
+ virtual String get_name() const { return "CollisionPolygon2D"; }
+ 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);
+
+ CollisionPolygon2DEditorPlugin(EditorNode *p_node);
+ ~CollisionPolygon2DEditorPlugin();
+
+};
+
+#endif // COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp
new file mode 100644
index 0000000000..3aad53b420
--- /dev/null
+++ b/editor/plugins/collision_polygon_editor_plugin.cpp
@@ -0,0 +1,648 @@
+/*************************************************************************/
+/* collision_polygon_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "collision_polygon_editor_plugin.h"
+
+#include "spatial_editor_plugin.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+#include "scene/3d/camera.h"
+#include "canvas_item_editor_plugin.h"
+
+#if 0
+
+void CollisionPolygonEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon( get_icon("Edit","EditorIcons"));
+ button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ button_edit->set_pressed(true);
+ get_tree()->connect("node_removed",this,"_node_removed");
+
+
+ } break;
+ case NOTIFICATION_PROCESS: {
+
+ if (node->get_depth() != prev_depth) {
+ _polygon_draw();
+ prev_depth=node->get_depth();
+ }
+
+ } break;
+ }
+
+}
+void CollisionPolygonEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ if (imgeom->get_parent()==p_node)
+ p_node->remove_child(imgeom);
+ hide();
+ set_process(false);
+ }
+
+}
+
+
+void CollisionPolygonEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case MODE_CREATE: {
+
+ mode=MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode=MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+
+ }
+}
+
+void CollisionPolygonEditor::_wip_close() {
+
+ undo_redo->create_action(TTR("Create Poly3D"));
+ undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
+ undo_redo->add_do_method(node,"set_polygon",wip);
+ undo_redo->add_do_method(this,"_polygon_draw");
+ undo_redo->add_undo_method(this,"_polygon_draw");
+ wip.clear();
+ wip_active=false;
+ mode=MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ edited_point=-1;
+ undo_redo->commit_action();
+
+}
+
+bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) {
+
+ if (!node)
+ return false;
+
+ Transform gt = node->get_global_transform();
+ Transform gi = gt.affine_inverse();
+ float depth = node->get_depth()*0.5;
+ Vector3 n = gt.basis.get_axis(2).normalized();
+ Plane p(gt.origin+n*depth,n);
+
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+
+
+ Vector2 gpoint=Point2(mb.x,mb.y);
+ Vector3 ray_from = p_camera->project_ray_origin(gpoint);
+ Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
+
+ Vector3 spoint;
+
+ if (!p.intersects_ray(ray_from,ray_dir,&spoint))
+ break;
+
+ spoint = gi.xform(spoint);
+
+ Vector2 cpoint(spoint.x,spoint.y);
+
+ cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
+
+ Vector<Vector2> poly = node->get_polygon();
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
+
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( cpoint );
+ wip_active=true;
+ edited_point_pos=cpoint;
+ _polygon_draw();
+ edited_point=1;
+ return true;
+ } else {
+
+
+ if (wip.size()>1 && p_camera->unproject_position(gt.xform(Vector3(wip[0].x,wip[0].y,depth))).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close();
+
+ return true;
+ } else {
+
+ wip.push_back( cpoint );
+ edited_point=wip.size();
+ _polygon_draw();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close();
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ if (poly.size() < 3) {
+
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.push_back(cpoint);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(this,"_polygon_draw");
+ undo_redo->add_undo_method(this,"_polygon_draw");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ //search edges
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 points[2] ={
+ p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth))),
+ p_camera->unproject_position(gt.xform(Vector3(poly[(i+1)%poly.size()].x,poly[(i+1)%poly.size()].y,depth)))
+ };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+ if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ poly.insert(closest_idx+1,cpoint);
+ edited_point=closest_idx+1;
+ edited_point_pos=cpoint;
+ node->set_polygon(poly);
+ _polygon_draw();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth)));
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ edited_point=closest_idx;
+ edited_point_pos=poly[closest_idx];
+ _polygon_draw();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly[edited_point]=edited_point_pos;
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
+ undo_redo->add_do_method(this,"_polygon_draw");
+ undo_redo->add_undo_method(this,"_polygon_draw");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth)));
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(this,"_polygon_draw");
+ undo_redo->add_undo_method(this,"_polygon_draw");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ }
+
+
+
+ } break;
+ }
+
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+
+ Vector3 ray_from = p_camera->project_ray_origin(gpoint);
+ Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
+
+ Vector3 spoint;
+
+ if (!p.intersects_ray(ray_from,ray_dir,&spoint))
+ break;
+
+ spoint = gi.xform(spoint);
+
+ Vector2 cpoint(spoint.x,spoint.y);
+
+ cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
+ edited_point_pos = cpoint;
+
+ _polygon_draw();
+
+ }
+
+ } break;
+ }
+
+ return false;
+}
+void CollisionPolygonEditor::_polygon_draw() {
+
+ if (!node)
+ return;
+
+ Vector<Vector2> poly;
+
+ if (wip_active)
+ poly=wip;
+ else
+ poly=node->get_polygon();
+
+
+ float depth = node->get_depth()*0.5;
+
+ imgeom->clear();
+ imgeom->set_material_override(line_material);
+ imgeom->begin(Mesh::PRIMITIVE_LINES,Ref<Texture>());
+
+
+ Rect2 rect;
+
+ for(int i=0;i<poly.size();i++) {
+
+
+ Vector2 p,p2;
+ p = i==edited_point ? edited_point_pos : poly[i];
+ if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
+ p2=edited_point_pos;
+ else
+ p2 = poly[(i+1)%poly.size()];
+
+ if (i==0)
+ rect.pos=p;
+ else
+ rect.expand_to(p);
+
+ Vector3 point = Vector3(p.x,p.y,depth);
+ Vector3 next_point = Vector3(p2.x,p2.y,depth);
+
+ imgeom->set_color(Color(1,0.3,0.1,0.8));
+ imgeom->add_vertex(point);
+ imgeom->set_color(Color(1,0.3,0.1,0.8));
+ imgeom->add_vertex(next_point);
+
+ //Color col=Color(1,0.3,0.1,0.8);
+ //vpc->draw_line(point,next_point,col,2);
+ //vpc->draw_texture(handle,point-handle->get_size()*0.5);
+ }
+
+ rect=rect.grow(1);
+
+ AABB r;
+ r.pos.x=rect.pos.x;
+ r.pos.y=rect.pos.y;
+ r.pos.z=depth;
+ r.size.x=rect.size.x;
+ r.size.y=rect.size.y;
+ r.size.z=0;
+
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos);
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(0.3,0,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos);
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(0.0,0.3,0));
+
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)-Vector3(0.3,0,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)+Vector3(0,0.3,0));
+
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)-Vector3(0,0.3,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)+Vector3(0.3,0,0));
+
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+r.size);
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+r.size-Vector3(0.3,0,0));
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+r.size);
+ imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+ imgeom->add_vertex(r.pos+r.size-Vector3(0.0,0.3,0));
+
+ imgeom->end();
+
+
+ while(m->get_surface_count()) {
+ m->surface_remove(0);
+ }
+
+ if (poly.size()==0)
+ return;
+
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ PoolVector<Vector3> va;
+ {
+
+ va.resize(poly.size());
+ PoolVector<Vector3>::Write w=va.write();
+ for(int i=0;i<poly.size();i++) {
+
+
+ Vector2 p,p2;
+ p = i==edited_point ? edited_point_pos : poly[i];
+
+ Vector3 point = Vector3(p.x,p.y,depth);
+ w[i]=point;
+ }
+ }
+ a[Mesh::ARRAY_VERTEX]=va;
+ m->add_surface(Mesh::PRIMITIVE_POINTS,a);
+ m->surface_set_material(0,handle_material);
+
+}
+
+
+
+void CollisionPolygonEditor::edit(Node *p_collision_polygon) {
+
+
+
+ if (p_collision_polygon) {
+
+ node=p_collision_polygon->cast_to<CollisionPolygon>();
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+ p_collision_polygon->add_child(imgeom);
+ _polygon_draw();
+ set_process(true);
+ prev_depth=-1;
+
+ } else {
+ node=NULL;
+
+ if (imgeom->get_parent())
+ imgeom->get_parent()->remove_child(imgeom);
+
+ set_process(false);
+ }
+
+}
+
+void CollisionPolygonEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_menu_option"),&CollisionPolygonEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_polygon_draw"),&CollisionPolygonEditor::_polygon_draw);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&CollisionPolygonEditor::_node_removed);
+
+}
+
+CollisionPolygonEditor::CollisionPolygonEditor(EditorNode *p_editor) {
+
+
+ node=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ add_child( memnew( VSeparator ));
+ button_create = memnew( ToolButton );
+ add_child(button_create);
+ button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+
+ button_edit = memnew( ToolButton );
+ add_child(button_edit);
+ button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+
+ //add_constant_override("separation",0);
+
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+#endif
+
+ mode = MODE_EDIT;
+ wip_active=false;
+ imgeom = memnew( ImmediateGeometry );
+ imgeom->set_transform(Transform(Matrix3(),Vector3(0,0,0.00001)));
+
+
+ line_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ line_material->set_flag(Material::FLAG_UNSHADED, true);
+ line_material->set_line_width(3.0);
+ line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
+ line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true);
+ line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1));
+
+
+
+
+ handle_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ handle_material->set_flag(Material::FLAG_UNSHADED, true);
+ handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_POINT_SIZE, true);
+ handle_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1));
+ handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
+ handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, false);
+ Ref<Texture> handle=editor->get_gui_base()->get_icon("Editor3DHandle","EditorIcons");
+ handle_material->set_point_size(handle->get_width());
+ handle_material->set_texture(FixedSpatialMaterial::PARAM_DIFFUSE,handle);
+
+ pointsm = memnew( MeshInstance );
+ imgeom->add_child(pointsm);
+ m = Ref<Mesh>( memnew( Mesh ) );
+ pointsm->set_mesh(m);
+ pointsm->set_transform(Transform(Matrix3(),Vector3(0,0,0.00001)));
+
+
+}
+
+CollisionPolygonEditor::~CollisionPolygonEditor() {
+
+ memdelete( imgeom );
+}
+
+
+void CollisionPolygonEditorPlugin::edit(Object *p_object) {
+
+ collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool CollisionPolygonEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("CollisionPolygon");
+}
+
+void CollisionPolygonEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ collision_polygon_editor->show();
+ } else {
+
+ collision_polygon_editor->hide();
+ collision_polygon_editor->edit(NULL);
+ }
+
+}
+
+CollisionPolygonEditorPlugin::CollisionPolygonEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ collision_polygon_editor = memnew( CollisionPolygonEditor(p_node) );
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+ collision_polygon_editor->hide();
+
+
+
+}
+
+
+CollisionPolygonEditorPlugin::~CollisionPolygonEditorPlugin()
+{
+}
+
+#endif
diff --git a/editor/plugins/collision_polygon_editor_plugin.h b/editor/plugins/collision_polygon_editor_plugin.h
new file mode 100644
index 0000000000..aaad2174fe
--- /dev/null
+++ b/editor/plugins/collision_polygon_editor_plugin.h
@@ -0,0 +1,123 @@
+/*************************************************************************/
+/* collision_polygon_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 COLLISION_POLYGON_EDITOR_PLUGIN_H
+#define COLLISION_POLYGON_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/3d/collision_polygon.h"
+#include "scene/3d/immediate_geometry.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+#if 0
+class CanvasItemEditor;
+
+class CollisionPolygonEditor : public HBoxContainer {
+
+ GDCLASS(CollisionPolygonEditor, HBoxContainer );
+
+ UndoRedo *undo_redo;
+ enum Mode {
+
+ MODE_CREATE,
+ MODE_EDIT,
+
+ };
+
+ Mode mode;
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+
+
+ Ref<FixedSpatialMaterial> line_material;
+ Ref<FixedSpatialMaterial> handle_material;
+
+ EditorNode *editor;
+ Panel *panel;
+ CollisionPolygon *node;
+ ImmediateGeometry *imgeom;
+ MeshInstance *pointsm;
+ Ref<Mesh> m;
+
+ MenuButton *options;
+
+ int edited_point;
+ Vector2 edited_point_pos;
+ Vector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+
+ float prev_depth;
+
+ void _wip_close();
+ void _polygon_draw();
+ void _menu_option(int p_option);
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event);
+ void edit(Node *p_collision_polygon);
+ CollisionPolygonEditor(EditorNode *p_editor);
+ ~CollisionPolygonEditor();
+};
+
+class CollisionPolygonEditorPlugin : public EditorPlugin {
+
+ GDCLASS( CollisionPolygonEditorPlugin, EditorPlugin );
+
+ CollisionPolygonEditor *collision_polygon_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) { return collision_polygon_editor->forward_spatial_gui_input(p_camera,p_event); }
+
+ virtual String get_name() const { return "CollisionPolygon"; }
+ 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);
+
+ CollisionPolygonEditorPlugin(EditorNode *p_node);
+ ~CollisionPolygonEditorPlugin();
+
+};
+#endif
+#endif // COLLISION_POLYGON_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index a05eeb7a27..a05eeb7a27 100644
--- a/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
new file mode 100644
index 0000000000..f7e6da8b4e
--- /dev/null
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -0,0 +1,101 @@
+/*************************************************************************/
+/* collision_shape_2d_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
+#define COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+
+#include "scene/2d/collision_shape_2d.h"
+
+class CanvasItemEditor;
+
+class CollisionShape2DEditor : public Control {
+ GDCLASS(CollisionShape2DEditor, Control);
+
+ enum ShapeType {
+ CAPSULE_SHAPE,
+ CIRCLE_SHAPE,
+ CONCAVE_POLYGON_SHAPE,
+ CONVEX_POLYGON_SHAPE,
+ LINE_SHAPE,
+ RAY_SHAPE,
+ RECTANGLE_SHAPE,
+ SEGMENT_SHAPE
+ };
+
+ EditorNode* editor;
+ UndoRedo* undo_redo;
+ CanvasItemEditor* canvas_item_editor;
+ CollisionShape2D* node;
+
+ Vector<Point2> handles;
+
+ int shape_type;
+ int edit_handle;
+ bool pressed;
+ Variant original;
+
+ Variant get_handle_value(int idx) const;
+ void set_handle(int idx, Point2& p_point);
+ void commit_handle(int idx, Variant& p_org);
+
+ void _get_current_shape_type();
+ void _canvas_draw();
+
+protected:
+ static void _bind_methods();
+
+public:
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node* p_node);
+
+ CollisionShape2DEditor(EditorNode* p_editor);
+};
+
+class CollisionShape2DEditorPlugin : public EditorPlugin {
+ GDCLASS(CollisionShape2DEditorPlugin, EditorPlugin);
+
+ CollisionShape2DEditor* collision_shape_2d_editor;
+ EditorNode* editor;
+
+public:
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_shape_2d_editor->forward_gui_input(p_event); }
+
+ virtual String get_name() const { return "CollisionShape2D"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object* p_obj);
+ virtual bool handles(Object* p_obj) const;
+ virtual void make_visible(bool visible);
+
+ CollisionShape2DEditorPlugin(EditorNode* p_editor);
+ ~CollisionShape2DEditorPlugin();
+};
+
+#endif //COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/color_ramp_editor_plugin.cpp b/editor/plugins/color_ramp_editor_plugin.cpp
new file mode 100644
index 0000000000..82674fabb8
--- /dev/null
+++ b/editor/plugins/color_ramp_editor_plugin.cpp
@@ -0,0 +1,112 @@
+/*************************************************************************/
+/* color_ramp_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "color_ramp_editor_plugin.h"
+
+#include "spatial_editor_plugin.h"
+#include "canvas_item_editor_plugin.h"
+
+ColorRampEditorPlugin::ColorRampEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ ramp_editor = memnew( ColorRampEdit );
+
+
+ add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,ramp_editor);
+
+ ramp_editor->set_custom_minimum_size(Size2(100, 48));
+ ramp_editor->hide();
+ ramp_editor->connect("ramp_changed", this, "ramp_changed");
+}
+
+void ColorRampEditorPlugin::edit(Object *p_object) {
+
+ ColorRamp* color_ramp = p_object->cast_to<ColorRamp>();
+ if (!color_ramp)
+ return;
+ color_ramp_ref = Ref<ColorRamp>(color_ramp);
+ ramp_editor->set_points(color_ramp_ref->get_points());
+}
+
+bool ColorRampEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("ColorRamp");
+
+}
+
+void ColorRampEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ ramp_editor->show();
+ } else {
+ ramp_editor->hide();
+ }
+
+}
+
+void ColorRampEditorPlugin::_ramp_changed() {
+
+ if(color_ramp_ref.is_valid())
+ {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+ //Not sure if I should convert this data to PoolVector
+ Vector<float> new_offsets=ramp_editor->get_offsets();
+ Vector<Color> new_colors=ramp_editor->get_colors();
+ Vector<float> old_offsets=color_ramp_ref->get_offsets();
+ Vector<Color> old_colors=color_ramp_ref->get_colors();
+
+ if (old_offsets.size()!=new_offsets.size())
+ ur->create_action(TTR("Add/Remove Color Ramp Point"));
+ else
+ ur->create_action(TTR("Modify Color Ramp"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(this,"undo_redo_color_ramp",new_offsets,new_colors);
+ ur->add_undo_method(this,"undo_redo_color_ramp",old_offsets,old_colors);
+ ur->commit_action();
+
+ //color_ramp_ref->set_points(ramp_editor->get_points());
+ }
+}
+
+void ColorRampEditorPlugin::_undo_redo_color_ramp(const Vector<float>& offsets,
+ const Vector<Color>& colors) {
+
+ color_ramp_ref->set_offsets(offsets);
+ color_ramp_ref->set_colors(colors);
+ ramp_editor->set_points(color_ramp_ref->get_points());
+ ramp_editor->update();
+}
+
+ColorRampEditorPlugin::~ColorRampEditorPlugin(){
+}
+
+void ColorRampEditorPlugin::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("ramp_changed"),&ColorRampEditorPlugin::_ramp_changed);
+ ClassDB::bind_method(D_METHOD("undo_redo_color_ramp","offsets","colors"),&ColorRampEditorPlugin::_undo_redo_color_ramp);
+}
diff --git a/editor/plugins/color_ramp_editor_plugin.h b/editor/plugins/color_ramp_editor_plugin.h
new file mode 100644
index 0000000000..0323bd7a46
--- /dev/null
+++ b/editor/plugins/color_ramp_editor_plugin.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* color_ramp_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
+#define TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/gui/color_ramp_edit.h"
+
+class ColorRampEditorPlugin : public EditorPlugin {
+
+ GDCLASS( ColorRampEditorPlugin, EditorPlugin );
+
+ bool _2d;
+ Ref<ColorRamp> color_ramp_ref;
+ ColorRampEdit *ramp_editor;
+ EditorNode *editor;
+
+protected:
+ static void _bind_methods();
+ void _ramp_changed();
+ void _undo_redo_color_ramp(const Vector<float>& offsets, const Vector<Color>& colors);
+
+public:
+ virtual String get_name() const { return "ColorRamp"; }
+ 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);
+
+ ColorRampEditorPlugin(EditorNode *p_node);
+ ~ColorRampEditorPlugin();
+
+};
+
+#endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */
diff --git a/editor/plugins/cube_grid_theme_editor_plugin.cpp b/editor/plugins/cube_grid_theme_editor_plugin.cpp
new file mode 100644
index 0000000000..b8abd2e9cc
--- /dev/null
+++ b/editor/plugins/cube_grid_theme_editor_plugin.cpp
@@ -0,0 +1,357 @@
+/*************************************************************************/
+/* cube_grid_theme_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "cube_grid_theme_editor_plugin.h"
+
+#if 0
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/physics_body.h"
+#include "scene/main/viewport.h"
+#include "scene/resources/packed_scene.h"
+#include "editor/editor_node.h"
+#include "main/main.h"
+#include "editor/editor_settings.h"
+#include "scene/3d/navigation_mesh.h"
+
+void MeshLibraryEditor::edit(const Ref<MeshLibrary>& p_theme) {
+
+ theme=p_theme;
+ if (theme.is_valid())
+ menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE),!theme->has_meta("_editor_source_scene"));
+
+}
+
+void MeshLibraryEditor::_menu_confirm() {
+
+
+ switch(option) {
+
+ case MENU_OPTION_REMOVE_ITEM: {
+
+ theme->remove_item(to_erase);
+ } break;
+ case MENU_OPTION_UPDATE_FROM_SCENE: {
+ String existing = theme->get_meta("_editor_source_scene");
+ ERR_FAIL_COND(existing=="");
+ _import_scene_cbk(existing);
+
+ } break;
+ default: {};
+ }
+
+}
+
+
+void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge) {
+
+ if (!p_merge)
+ p_library->clear();
+
+
+ for(int i=0;i<p_scene->get_child_count();i++) {
+
+
+ Node *child = p_scene->get_child(i);
+
+ if (!child->cast_to<MeshInstance>()) {
+ if (child->get_child_count()>0) {
+ child=child->get_child(0);
+ if (!child->cast_to<MeshInstance>()) {
+ continue;
+ }
+
+ } else
+ continue;
+
+
+ }
+
+ MeshInstance *mi = child->cast_to<MeshInstance>();
+ Ref<Mesh> mesh=mi->get_mesh();
+ if (mesh.is_null())
+ continue;
+
+ int id = p_library->find_item_name(mi->get_name());
+ if (id<0) {
+
+ id=p_library->get_last_unused_item_id();
+ p_library->create_item(id);
+ p_library->set_item_name(id,mi->get_name());
+ }
+
+
+ p_library->set_item_mesh(id,mesh);
+
+ Ref<Shape> collision;
+
+
+ for(int j=0;j<mi->get_child_count();j++) {
+#if 1
+ Node *child2 = mi->get_child(j);
+ if (!child2->cast_to<StaticBody>())
+ continue;
+ StaticBody *sb = child2->cast_to<StaticBody>();
+ if (sb->get_shape_count()==0)
+ continue;
+ collision=sb->get_shape(0);
+ if (!collision.is_null())
+ break;
+#endif
+ }
+
+ if (!collision.is_null()) {
+
+ p_library->set_item_shape(id,collision);
+ }
+ Ref<NavigationMesh> navmesh;
+ for(int j=0;j<mi->get_child_count();j++) {
+ Node *child2 = mi->get_child(j);
+ if (!child2->cast_to<NavigationMeshInstance>())
+ continue;
+ NavigationMeshInstance *sb = child2->cast_to<NavigationMeshInstance>();
+ navmesh=sb->get_navigation_mesh();
+ if (!navmesh.is_null())
+ break;
+ }
+ if(!navmesh.is_null()){
+ p_library->set_item_navmesh(id, navmesh);
+ }
+ }
+
+ //generate previews!
+
+ if (1) {
+ Vector<int> ids = p_library->get_item_list();
+ RID vp = VS::get_singleton()->viewport_create();
+ VS::ViewportRect vr;
+ vr.x=0;
+ vr.y=0;
+ vr.width=EditorSettings::get_singleton()->get("editors/grid_map/preview_size");
+ vr.height=EditorSettings::get_singleton()->get("editors/grid_map/preview_size");
+ VS::get_singleton()->viewport_set_rect(vp,vr);
+ VS::get_singleton()->viewport_set_as_render_target(vp,true);
+ VS::get_singleton()->viewport_set_render_target_update_mode(vp,VS::RENDER_TARGET_UPDATE_ALWAYS);
+ RID scen = VS::get_singleton()->scenario_create();
+ VS::get_singleton()->viewport_set_scenario(vp,scen);
+ RID cam = VS::get_singleton()->camera_create();
+ VS::get_singleton()->camera_set_transform(cam, Transform() );
+ VS::get_singleton()->viewport_attach_camera(vp,cam);
+ RID light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ RID lightinst = VS::get_singleton()->instance_create2(light,scen);
+ VS::get_singleton()->camera_set_orthogonal(cam,1.0,0.01,1000.0);
+
+
+ EditorProgress ep("mlib",TTR("Creating Mesh Library"),ids.size());
+
+ for(int i=0;i<ids.size();i++) {
+
+ int id=ids[i];
+ Ref<Mesh> mesh = p_library->get_item_mesh(id);
+ if (!mesh.is_valid())
+ continue;
+ AABB aabb= mesh->get_aabb();
+ print_line("aabb: "+aabb);
+ Vector3 ofs = aabb.pos + aabb.size*0.5;
+ aabb.pos-=ofs;
+ Transform xform;
+ xform.basis=Matrix3().rotated(Vector3(0,1,0),-Math_PI*0.25);
+ xform.basis = Matrix3().rotated(Vector3(1,0,0),Math_PI*0.25)*xform.basis;
+ AABB rot_aabb = xform.xform(aabb);
+ print_line("rot_aabb: "+rot_aabb);
+ float m = MAX(rot_aabb.size.x,rot_aabb.size.y)*0.5;
+ if (m==0)
+ continue;
+ m=1.0/m;
+ m*=0.5;
+ print_line("scale: "+rtos(m));
+ xform.basis.scale(Vector3(m,m,m));
+ xform.origin=-xform.basis.xform(ofs); //-ofs*m;
+ xform.origin.z-=rot_aabb.size.z*2;
+ RID inst = VS::get_singleton()->instance_create2(mesh->get_rid(),scen);
+ VS::get_singleton()->instance_set_transform(inst,xform);
+ ep.step(TTR("Thumbnail.."),i);
+ VS::get_singleton()->viewport_queue_screen_capture(vp);
+ Main::iteration();
+ Image img = VS::get_singleton()->viewport_get_screen_capture(vp);
+ ERR_CONTINUE(img.empty());
+ Ref<ImageTexture> it( memnew( ImageTexture ));
+ it->create_from_image(img);
+ p_library->set_item_preview(id,it);
+
+ //print_line("loaded image, size: "+rtos(m)+" dist: "+rtos(dist)+" empty?"+itos(img.empty())+" w: "+itos(it->get_width())+" h: "+itos(it->get_height()));
+ VS::get_singleton()->free(inst);
+ }
+
+ VS::get_singleton()->free(lightinst);
+ VS::get_singleton()->free(light);
+ VS::get_singleton()->free(vp);
+ VS::get_singleton()->free(cam);
+ VS::get_singleton()->free(scen);
+ }
+
+
+}
+
+
+void MeshLibraryEditor::_import_scene_cbk(const String& p_str) {
+
+
+ print_line("Impot Callback!");
+
+ Ref<PackedScene> ps = ResourceLoader::load(p_str,"PackedScene");
+ ERR_FAIL_COND(ps.is_null());
+ Node *scene = ps->instance();
+
+ _import_scene(scene,theme,option==MENU_OPTION_UPDATE_FROM_SCENE);
+
+ memdelete(scene);
+ theme->set_meta("_editor_source_scene",p_str);
+ menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE),false);
+
+}
+
+Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml,bool p_merge) {
+
+ _import_scene(p_base_scene,ml,p_merge);
+ return OK;
+}
+
+
+void MeshLibraryEditor::_menu_cbk(int p_option) {
+
+ option=p_option;
+ switch(p_option) {
+
+ case MENU_OPTION_ADD_ITEM: {
+
+ theme->create_item(theme->get_last_unused_item_id());
+ } break;
+ case MENU_OPTION_REMOVE_ITEM: {
+
+ String p = editor->get_property_editor()->get_selected_path();
+ if (p.begins_with("/MeshLibrary/item") && p.get_slice_count("/")>=3) {
+
+ to_erase = p.get_slice("/",3).to_int();
+ cd->set_text(vformat(TTR("Remove item %d?"),to_erase));
+ cd->popup_centered(Size2(300,60));
+ }
+ } break;
+ case MENU_OPTION_IMPORT_FROM_SCENE: {
+
+ file->popup_centered_ratio();
+ } break;
+ case MENU_OPTION_UPDATE_FROM_SCENE: {
+
+ cd->set_text("Update from existing scene?:\n"+String(theme->get_meta("_editor_source_scene")));
+ cd->popup_centered(Size2(500,60));
+ } break;
+ }
+}
+
+
+void MeshLibraryEditor::_bind_methods() {
+
+ ClassDB::bind_method("_menu_cbk",&MeshLibraryEditor::_menu_cbk);
+ ClassDB::bind_method("_menu_confirm",&MeshLibraryEditor::_menu_confirm);
+ ClassDB::bind_method("_import_scene_cbk",&MeshLibraryEditor::_import_scene_cbk);
+}
+
+MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) {
+
+ file = memnew( EditorFileDialog );
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ //not for now?
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
+ file->clear_filters();
+ file->set_title(TTR("Import Scene"));
+ for(int i=0;i<extensions.size();i++) {
+
+ file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+ add_child(file);
+ file->connect("file_selected",this,"_import_scene_cbk");
+
+ Panel *panel = memnew( Panel );
+ panel->set_area_as_parent_rect();
+ add_child(panel);
+ MenuButton * options = memnew( MenuButton );
+ panel->add_child(options);
+ options->set_pos(Point2(1,1));
+ options->set_text("Theme");
+ options->get_popup()->add_item(TTR("Add Item"),MENU_OPTION_ADD_ITEM);
+ options->get_popup()->add_item(TTR("Remove Selected Item"),MENU_OPTION_REMOVE_ITEM);
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item(TTR("Import from Scene"),MENU_OPTION_IMPORT_FROM_SCENE);
+ options->get_popup()->add_item(TTR("Update from Scene"),MENU_OPTION_UPDATE_FROM_SCENE);
+ options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE),true);
+ options->get_popup()->connect("id_pressed", this,"_menu_cbk");
+ menu=options;
+ editor=p_editor;
+ cd = memnew(ConfirmationDialog);
+ add_child(cd);
+ cd->get_ok()->connect("pressed", this,"_menu_confirm");
+
+}
+
+void MeshLibraryEditorPlugin::edit(Object *p_node) {
+
+ if (p_node && p_node->cast_to<MeshLibrary>()) {
+ theme_editor->edit( p_node->cast_to<MeshLibrary>() );
+ theme_editor->show();
+ } else
+ theme_editor->hide();
+}
+
+bool MeshLibraryEditorPlugin::handles(Object *p_node) const{
+
+ return p_node->is_type("MeshLibrary");
+}
+
+void MeshLibraryEditorPlugin::make_visible(bool p_visible){
+
+ if (p_visible)
+ theme_editor->show();
+ else
+ theme_editor->hide();
+}
+
+MeshLibraryEditorPlugin::MeshLibraryEditorPlugin(EditorNode *p_node) {
+
+ EDITOR_DEF("editors/grid_map/preview_size",64);
+ theme_editor = memnew( MeshLibraryEditor(p_node) );
+
+ p_node->get_viewport()->add_child(theme_editor);
+ theme_editor->set_area_as_parent_rect();
+ theme_editor->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
+ theme_editor->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_BEGIN );
+ theme_editor->set_end( Point2(0,22) );
+ theme_editor->hide();
+
+}
+#endif
diff --git a/editor/plugins/cube_grid_theme_editor_plugin.h b/editor/plugins/cube_grid_theme_editor_plugin.h
new file mode 100644
index 0000000000..07e7c7cadd
--- /dev/null
+++ b/editor/plugins/cube_grid_theme_editor_plugin.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* cube_grid_theme_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 CUBE_GRID_THEME_EDITOR_PLUGIN_H
+#define CUBE_GRID_THEME_EDITOR_PLUGIN_H
+
+#include "scene/resources/mesh_library.h"
+#include "editor/editor_node.h"
+
+#if 0
+class MeshLibraryEditor : public Control {
+
+ GDCLASS( MeshLibraryEditor, Control );
+
+ Ref<MeshLibrary> theme;
+
+ EditorNode *editor;
+ MenuButton *menu;
+ ConfirmationDialog *cd;
+ EditorFileDialog *file;
+ int to_erase;
+
+ enum {
+
+ MENU_OPTION_ADD_ITEM,
+ MENU_OPTION_REMOVE_ITEM,
+ MENU_OPTION_UPDATE_FROM_SCENE,
+ MENU_OPTION_IMPORT_FROM_SCENE
+ };
+
+ int option;
+ void _import_scene_cbk(const String& p_str);
+ void _menu_cbk(int p_option);
+ void _menu_confirm();
+
+ static void _import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge);
+
+protected:
+ static void _bind_methods();
+public:
+
+ void edit(const Ref<MeshLibrary>& p_theme);
+ static Error update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml,bool p_merge=true);
+
+ MeshLibraryEditor(EditorNode *p_editor);
+};
+
+
+
+class MeshLibraryEditorPlugin : public EditorPlugin {
+
+ GDCLASS( MeshLibraryEditorPlugin, EditorPlugin );
+
+ MeshLibraryEditor *theme_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "MeshLibrary"; }
+ 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);
+
+ MeshLibraryEditorPlugin(EditorNode *p_node);
+
+};
+
+
+#endif // CUBE_GRID_THEME_EDITOR_PLUGIN_H
+#endif
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
new file mode 100644
index 0000000000..3f31f1e0f1
--- /dev/null
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -0,0 +1,907 @@
+/*************************************************************************/
+/* editor_preview_plugins.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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_preview_plugins.h"
+
+#include "io/resource_loader.h"
+#include "editor/editor_settings.h"
+#include "io/file_access_memory.h"
+#include "os/os.h"
+#include "scene/resources/material.h"
+//#include "scene/resources/sample.h"
+#include "scene/resources/mesh.h"
+#include "scene/resources/bit_mask.h"
+#include "editor/editor_scale.h"
+
+#if 0
+bool EditorTexturePreviewPlugin::handles(const String& p_type) const {
+
+ return (ClassDB::is_type(p_type,"ImageTexture") || ClassDB::is_type(p_type, "AtlasTexture"));
+}
+
+Ref<Texture> EditorTexturePreviewPlugin::generate(const RES& p_from) {
+
+ 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>();
+
+ img.clear_mipmaps();
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ if (img.is_compressed()) {
+ if (img.decompress()!=OK)
+ return Ref<Texture>();
+ } else if (img.get_format()!=Image::FORMAT_RGB8 && img.get_format()!=Image::FORMAT_RGBA8) {
+ img.convert(Image::FORMAT_RGBA8);
+ }
+
+ 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;
+
+}
+
+EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
+
+
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+bool EditorBitmapPreviewPlugin::handles(const String& p_type) const {
+
+ return ClassDB::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>();
+ }
+
+ PoolVector<uint8_t> data;
+
+ data.resize(bm->get_size().width*bm->get_size().height);
+
+ {
+ PoolVector<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_L8,data);
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ if (img.is_compressed()) {
+ if (img.decompress()!=OK)
+ return Ref<Texture>();
+ } else if (img.get_format()!=Image::FORMAT_RGB8 && img.get_format()!=Image::FORMAT_RGBA8) {
+ img.convert(Image::FORMAT_RGBA8);
+ }
+
+ 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() {
+
+
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+
+Ref<Texture> EditorPackedScenePreviewPlugin::_gen_from_imd(Ref<ResourceImportMetadata> p_imd) {
+
+ if (p_imd.is_null()) {
+ return Ref<Texture>();
+ }
+
+ if (!p_imd->has_option("thumbnail"))
+ return Ref<Texture>();
+
+ Variant tn = p_imd->get_option("thumbnail");
+ //print_line(Variant::get_type_name(tn.get_type()));
+ PoolVector<uint8_t> thumbnail = tn;
+
+ int len = thumbnail.size();
+ if (len==0)
+ return Ref<Texture>();
+
+
+ PoolVector<uint8_t>::Read r = thumbnail.read();
+
+ Image img(r.ptr(),len);
+ if (img.empty())
+ return Ref<Texture>();
+
+ Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+ ptex->create_from_image(img,0);
+ return ptex;
+
+}
+
+bool EditorPackedScenePreviewPlugin::handles(const String& p_type) const {
+
+ return ClassDB::is_type(p_type,"PackedScene");
+}
+Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES& p_from) {
+
+ Ref<ResourceImportMetadata> imd = p_from->get_import_metadata();
+ return _gen_from_imd(imd);
+}
+
+Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String& p_path) {
+
+ Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path);
+ return _gen_from_imd(imd);
+}
+
+EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
+
+}
+
+//////////////////////////////////////////////////////////////////
+
+bool EditorMaterialPreviewPlugin::handles(const String& p_type) const {
+
+ return ClassDB::is_type(p_type,"Material"); //any material
+}
+
+Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES& p_from) {
+
+ Ref<Material> material = p_from;
+ ERR_FAIL_COND_V(material.is_null(),Ref<Texture>());
+
+ VS::get_singleton()->mesh_surface_set_material(sphere,0,material->get_rid());
+
+ VS::get_singleton()->viewport_queue_screen_capture(viewport);
+ VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
+ //print_line("queue capture!");
+ Image img;
+
+ int timeout=1000;
+ while(timeout) {
+ //print_line("try capture?");
+ OS::get_singleton()->delay_usec(10);
+ img = VS::get_singleton()->viewport_get_screen_capture(viewport);
+ if (!img.empty())
+ break;
+ timeout--;
+ }
+
+ //print_line("captured!");
+ VS::get_singleton()->mesh_surface_set_material(sphere,0,RID());
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ img.resize(thumbnail_size,thumbnail_size);
+
+ Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+ ptex->create_from_image(img,0);
+ return ptex;
+}
+
+EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
+
+ scenario = VS::get_singleton()->scenario_create();
+
+ viewport = VS::get_singleton()->viewport_create();
+ VS::get_singleton()->viewport_set_as_render_target(viewport,true);
+ VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED);
+ VS::get_singleton()->viewport_set_scenario(viewport,scenario);
+ VS::ViewportRect vr;
+ vr.x=0;
+ vr.y=0;
+ vr.width=128;
+ vr.height=128;
+ VS::get_singleton()->viewport_set_rect(viewport,vr);
+
+ camera = VS::get_singleton()->camera_create();
+ VS::get_singleton()->viewport_attach_camera(viewport,camera);
+ VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3)));
+ VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
+
+ light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light_instance = VS::get_singleton()->instance_create2(light,scenario);
+ VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
+
+ light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7));
+ VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0));
+ light_instance2 = VS::get_singleton()->instance_create2(light2,scenario);
+
+ VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
+
+ sphere = VS::get_singleton()->mesh_create();
+ sphere_instance = VS::get_singleton()->instance_create2(sphere,scenario);
+
+ int lats=32;
+ int lons=32;
+ float radius=1.0;
+
+ PoolVector<Vector3> vertices;
+ PoolVector<Vector3> normals;
+ PoolVector<Vector2> uvs;
+ PoolVector<float> tangents;
+ Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5);
+
+ for(int i = 1; i <= lats; i++) {
+ double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
+ double z0 = Math::sin(lat0);
+ double zr0 = Math::cos(lat0);
+
+ double lat1 = Math_PI * (-0.5 + (double) i / lats);
+ double z1 = Math::sin(lat1);
+ double zr1 = Math::cos(lat1);
+
+ for(int j = lons; j >= 1; j--) {
+
+ double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
+ double x0 = Math::cos(lng0);
+ double y0 = Math::sin(lng0);
+
+ double lng1 = 2 * Math_PI * (double) (j) / lons;
+ double x1 = Math::cos(lng1);
+ double y1 = Math::sin(lng1);
+
+
+ Vector3 v[4]={
+ Vector3(x1 * zr0, z0, y1 *zr0),
+ Vector3(x1 * zr1, z1, y1 *zr1),
+ Vector3(x0 * zr1, z1, y0 *zr1),
+ Vector3(x0 * zr0, z0, y0 *zr0)
+ };
+
+#define ADD_POINT(m_idx) \
+ normals.push_back(v[m_idx]);\
+ vertices.push_back(v[m_idx]*radius);\
+ { Vector2 uv(Math::atan2(v[m_idx].x,v[m_idx].z),Math::atan2(-v[m_idx].y,v[m_idx].z));\
+ uv/=Math_PI;\
+ uv*=4.0;\
+ uv=uv*0.5+Vector2(0.5,0.5);\
+ uvs.push_back(uv);\
+ }\
+ { Vector3 t = tt.xform(v[m_idx]);\
+ tangents.push_back(t.x);\
+ tangents.push_back(t.y);\
+ tangents.push_back(t.z);\
+ tangents.push_back(1.0);\
+ }
+
+
+
+ ADD_POINT(0);
+ ADD_POINT(1);
+ ADD_POINT(2);
+
+ ADD_POINT(2);
+ ADD_POINT(3);
+ ADD_POINT(0);
+ }
+ }
+
+ Array arr;
+ arr.resize(VS::ARRAY_MAX);
+ arr[VS::ARRAY_VERTEX]=vertices;
+ arr[VS::ARRAY_NORMAL]=normals;
+ arr[VS::ARRAY_TANGENT]=tangents;
+ arr[VS::ARRAY_TEX_UV]=uvs;
+ VS::get_singleton()->mesh_add_surface(sphere,VS::PRIMITIVE_TRIANGLES,arr);
+
+}
+
+EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
+
+ VS::get_singleton()->free(sphere);
+ VS::get_singleton()->free(sphere_instance);
+ VS::get_singleton()->free(viewport);
+ VS::get_singleton()->free(light);
+ VS::get_singleton()->free(light_instance);
+ VS::get_singleton()->free(light2);
+ VS::get_singleton()->free(light_instance2);
+ VS::get_singleton()->free(camera);
+ VS::get_singleton()->free(scenario);
+
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static bool _is_text_char(CharType c) {
+
+ return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
+}
+
+bool EditorScriptPreviewPlugin::handles(const String& p_type) const {
+
+ return ClassDB::is_type(p_type,"Script");
+}
+
+Ref<Texture> EditorScriptPreviewPlugin::generate(const RES& p_from) {
+
+
+ Ref<Script> scr = p_from;
+ if (scr.is_null())
+ return Ref<Texture>();
+
+ String code = scr->get_source_code().strip_edges();
+ if (code=="")
+ return Ref<Texture>();
+
+ List<String> kwors;
+ scr->get_language()->get_reserved_words(&kwors);
+
+ Set<String> keywords;
+
+ for(List<String>::Element *E=kwors.front();E;E=E->next()) {
+
+ keywords.insert(E->get());
+
+ }
+
+
+ int line = 0;
+ int col=0;
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ Image img(thumbnail_size,thumbnail_size,0,Image::FORMAT_RGBA8);
+
+
+
+ Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color");
+ bg_color.a=1.0;
+ Color keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color");
+ Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
+ Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color");
+
+
+ for(int i=0;i<thumbnail_size;i++) {
+ for(int j=0;j<thumbnail_size;j++) {
+ img.put_pixel(i,j,bg_color);
+ }
+
+ }
+
+ bool prev_is_text=false;
+ bool in_keyword=false;
+ for(int i=0;i<code.length();i++) {
+
+ CharType c = code[i];
+ if (c>32) {
+ if (col<thumbnail_size) {
+ Color color = text_color;
+
+ if (c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t')) {
+ //make symbol a little visible
+ color=symbol_color;
+ in_keyword=false;
+ } else if (!prev_is_text && _is_text_char(c)) {
+ int pos = i;
+
+ while(_is_text_char(code[pos])) {
+ pos++;
+ }
+ ///print_line("from "+itos(i)+" to "+itos(pos));
+ String word = code.substr(i,pos-i);
+ //print_line("found word: "+word);
+ if (keywords.has(word))
+ in_keyword=true;
+
+ } else if (!_is_text_char(c)) {
+ in_keyword=false;
+ }
+
+ if (in_keyword)
+ color=keyword_color;
+
+ Color ul=color;
+ ul.a*=0.5;
+ img.put_pixel(col,line*2,bg_color.blend(ul));
+ img.put_pixel(col,line*2+1,color);
+
+ prev_is_text=_is_text_char(c);
+ }
+ } else {
+
+ prev_is_text=false;
+ in_keyword=false;
+
+ if (c=='\n') {
+ col=0;
+ line++;
+ if (line>=thumbnail_size/2)
+ break;
+ } else if (c=='\t') {
+ col+=3;
+ }
+ }
+ col++;
+ }
+
+ Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
+
+ ptex->create_from_image(img,0);
+ return ptex;
+
+}
+
+EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
+
+
+}
+///////////////////////////////////////////////////////////////////
+#if 0
+bool EditorSamplePreviewPlugin::handles(const String& p_type) const {
+
+ return ClassDB::is_type(p_type,"Sample");
+}
+
+Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {
+
+ Ref<Sample> smp =p_from;
+ ERR_FAIL_COND_V(smp.is_null(),Ref<Texture>());
+
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ PoolVector<uint8_t> img;
+ int w = thumbnail_size;
+ int h = thumbnail_size;
+ img.resize(w*h*3);
+
+ PoolVector<uint8_t>::Write imgdata = img.write();
+ uint8_t * imgw = imgdata.ptr();
+ PoolVector<uint8_t> data = smp->get_data();
+ PoolVector<uint8_t>::Read sampledata = data.read();
+ const uint8_t *sdata=sampledata.ptr();
+
+ bool stereo = smp->is_stereo();
+ bool _16=smp->get_format()==Sample::FORMAT_PCM16;
+ int len = smp->get_length();
+
+ if (len<1)
+ return Ref<Texture>();
+
+ if (smp->get_format()==Sample::FORMAT_IMA_ADPCM) {
+
+ struct IMA_ADPCM_State {
+
+ int16_t step_index;
+ int32_t predictor;
+ /* values at loop point */
+ int16_t loop_step_index;
+ int32_t loop_predictor;
+ int32_t last_nibble;
+ int32_t loop_pos;
+ int32_t window_ofs;
+ const uint8_t *ptr;
+ } ima_adpcm;
+
+ ima_adpcm.step_index=0;
+ ima_adpcm.predictor=0;
+ ima_adpcm.loop_step_index=0;
+ ima_adpcm.loop_predictor=0;
+ ima_adpcm.last_nibble=-1;
+ ima_adpcm.loop_pos=0x7FFFFFFF;
+ ima_adpcm.window_ofs=0;
+ ima_adpcm.ptr=NULL;
+
+
+ for(int i=0;i<w;i++) {
+
+ float max[2]={-1e10,-1e10};
+ float min[2]={1e10,1e10};
+ int from = i*len/w;
+ int to = (i+1)*len/w;
+ if (to>=len)
+ to=len-1;
+
+ for(int j=from;j<to;j++) {
+
+ while(j>ima_adpcm.last_nibble) {
+
+ static const int16_t _ima_adpcm_step_table[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+ };
+
+ static const int8_t _ima_adpcm_index_table[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+ };
+
+ int16_t nibble,diff,step;
+
+ ima_adpcm.last_nibble++;
+ const uint8_t *src_ptr=sdata;
+
+ int ofs = ima_adpcm.last_nibble>>1;
+
+ if (stereo)
+ ofs*=2;
+
+
+ nibble = (ima_adpcm.last_nibble&1)?
+ (src_ptr[ofs]>>4):(src_ptr[ofs]&0xF);
+ step=_ima_adpcm_step_table[ima_adpcm.step_index];
+
+ ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
+ if (ima_adpcm.step_index<0)
+ ima_adpcm.step_index=0;
+ if (ima_adpcm.step_index>88)
+ ima_adpcm.step_index=88;
+
+ diff = step >> 3 ;
+ if (nibble & 1)
+ diff += step >> 2 ;
+ if (nibble & 2)
+ diff += step >> 1 ;
+ if (nibble & 4)
+ diff += step ;
+ if (nibble & 8)
+ diff = -diff ;
+
+ ima_adpcm.predictor+=diff;
+ if (ima_adpcm.predictor<-0x8000)
+ ima_adpcm.predictor=-0x8000;
+ else if (ima_adpcm.predictor>0x7FFF)
+ ima_adpcm.predictor=0x7FFF;
+
+
+ /* store loop if there */
+ if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {
+
+ ima_adpcm.loop_step_index = ima_adpcm.step_index;
+ ima_adpcm.loop_predictor = ima_adpcm.predictor;
+ }
+
+ }
+
+ float v=ima_adpcm.predictor/32767.0;
+ if (v>max[0])
+ max[0]=v;
+ if (v<min[0])
+ min[0]=v;
+ }
+ max[0]*=0.8;
+ min[0]*=0.8;
+
+ for(int j=0;j<h;j++) {
+ float v = (j/(float)h) * 2.0 - 1.0;
+ uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
+ if (v>min[0] && v<max[0]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
+ }
+ }
+ } else {
+ for(int i=0;i<w;i++) {
+ // i trust gcc will optimize this loop
+ float max[2]={-1e10,-1e10};
+ float min[2]={1e10,1e10};
+ int c=stereo?2:1;
+ int from = uint64_t(i)*len/w;
+ int to = (uint64_t(i)+1)*len/w;
+ if (to>=len)
+ to=len-1;
+
+ if (_16) {
+ const int16_t*src =(const int16_t*)sdata;
+
+ for(int j=0;j<c;j++) {
+
+ for(int k=from;k<=to;k++) {
+
+ float v = src[uint64_t(k)*c+j]/32768.0;
+ if (v>max[j])
+ max[j]=v;
+ if (v<min[j])
+ min[j]=v;
+ }
+
+ }
+ } else {
+
+ const int8_t*src =(const int8_t*)sdata;
+
+ for(int j=0;j<c;j++) {
+
+ for(int k=from;k<=to;k++) {
+
+ float v = src[uint64_t(k)*c+j]/128.0;
+ if (v>max[j])
+ max[j]=v;
+ if (v<min[j])
+ min[j]=v;
+ }
+
+ }
+ }
+
+ max[0]*=0.8;
+ max[1]*=0.8;
+ min[0]*=0.8;
+ min[1]*=0.8;
+
+ if (!stereo) {
+ for(int j=0;j<h;j++) {
+ float v = (j/(float)h) * 2.0 - 1.0;
+ uint8_t* imgofs = &imgw[(j*w+i)*3];
+ if (v>min[0] && v<max[0]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
+ }
+ } else {
+
+ for(int j=0;j<h;j++) {
+
+ int half;
+ float v;
+ if (j<(h/2)) {
+ half=0;
+ v = (j/(float)(h/2)) * 2.0 - 1.0;
+ } else {
+ half=1;
+ if( (float)(h/2) != 0 ) {
+ v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
+ } else {
+ v = ((j-(h/2))/(float)(1/2)) * 2.0 - 1.0;
+ }
+ }
+
+ uint8_t* imgofs = &imgw[(j*w+i)*3];
+ if (v>min[half] && v<max[half]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
+ }
+
+ }
+
+ }
+ }
+
+ imgdata = PoolVector<uint8_t>::Write();
+
+ Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
+ ptex->create_from_image(Image(w,h,0,Image::FORMAT_RGB8,img),0);
+ return ptex;
+
+}
+
+EditorSamplePreviewPlugin::EditorSamplePreviewPlugin() {
+
+
+}
+#endif
+///////////////////////////////////////////////////////////////////////////
+
+bool EditorMeshPreviewPlugin::handles(const String& p_type) const {
+
+ return ClassDB::is_type(p_type,"Mesh"); //any Mesh
+}
+
+Ref<Texture> EditorMeshPreviewPlugin::generate(const RES& p_from) {
+
+ Ref<Mesh> mesh = p_from;
+ ERR_FAIL_COND_V(mesh.is_null(),Ref<Texture>());
+
+ VS::get_singleton()->instance_set_base(mesh_instance,mesh->get_rid());
+
+ AABB aabb= mesh->get_aabb();
+ Vector3 ofs = aabb.pos + aabb.size*0.5;
+ aabb.pos-=ofs;
+ Transform xform;
+ xform.basis=Matrix3().rotated(Vector3(0,1,0),-Math_PI*0.125);
+ xform.basis = Matrix3().rotated(Vector3(1,0,0),Math_PI*0.125)*xform.basis;
+ AABB rot_aabb = xform.xform(aabb);
+ float m = MAX(rot_aabb.size.x,rot_aabb.size.y)*0.5;
+ if (m==0)
+ return Ref<Texture>();
+ m=1.0/m;
+ m*=0.5;
+ //print_line("scale: "+rtos(m));
+ xform.basis.scale(Vector3(m,m,m));
+ xform.origin=-xform.basis.xform(ofs); //-ofs*m;
+ xform.origin.z-=rot_aabb.size.z*2;
+ VS::get_singleton()->instance_set_transform(mesh_instance,xform);
+
+
+
+ VS::get_singleton()->viewport_queue_screen_capture(viewport);
+ VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
+ //print_line("queue capture!");
+ Image img;
+
+ int timeout=1000;
+ while(timeout) {
+ //print_line("try capture?");
+ OS::get_singleton()->delay_usec(10);
+ img = VS::get_singleton()->viewport_get_screen_capture(viewport);
+ if (!img.empty())
+ break;
+ timeout--;
+ }
+
+ //print_line("captured!");
+ VS::get_singleton()->instance_set_base(mesh_instance,RID());
+
+ int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
+ thumbnail_size*=EDSCALE;
+ img.resize(thumbnail_size,thumbnail_size);
+
+ Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
+ ptex->create_from_image(img,0);
+ return ptex;
+}
+
+EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
+
+ scenario = VS::get_singleton()->scenario_create();
+ viewport = VS::get_singleton()->viewport_create();
+ VS::get_singleton()->viewport_set_as_render_target(viewport,true);
+ VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED);
+ VS::get_singleton()->viewport_set_scenario(viewport,scenario);
+ VS::ViewportRect vr;
+ vr.x=0;
+ vr.y=0;
+ vr.width=128;
+ vr.height=128;
+ VS::get_singleton()->viewport_set_rect(viewport,vr);
+
+ camera = VS::get_singleton()->camera_create();
+ VS::get_singleton()->viewport_attach_camera(viewport,camera);
+ VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3)));
+ //VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
+ VS::get_singleton()->camera_set_orthogonal(camera,1.0,0.01,1000.0);
+
+ light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ light_instance = VS::get_singleton()->instance_create2(light,scenario);
+ VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
+
+ light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
+ VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7));
+ VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0));
+ light_instance2 = VS::get_singleton()->instance_create2(light2,scenario);
+
+ VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
+
+ //sphere = VS::get_singleton()->mesh_create();
+ mesh_instance = VS::get_singleton()->instance_create();
+ VS::get_singleton()->instance_set_scenario(mesh_instance,scenario);
+
+
+
+}
+
+
+EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
+
+ //VS::get_singleton()->free(sphere);
+ VS::get_singleton()->free(mesh_instance);
+ VS::get_singleton()->free(viewport);
+ VS::get_singleton()->free(light);
+ VS::get_singleton()->free(light_instance);
+ VS::get_singleton()->free(light2);
+ VS::get_singleton()->free(light_instance2);
+ VS::get_singleton()->free(camera);
+ VS::get_singleton()->free(scenario);
+
+}
+#endif
diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h
new file mode 100644
index 0000000000..b1d4fa0b38
--- /dev/null
+++ b/editor/plugins/editor_preview_plugins.h
@@ -0,0 +1,128 @@
+/*************************************************************************/
+/* editor_preview_plugins.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 EDITORPREVIEWPLUGINS_H
+#define EDITORPREVIEWPLUGINS_H
+
+#include "editor/editor_resource_preview.h"
+
+#if 0
+class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
+public:
+
+ virtual bool handles(const String& p_type) const;
+ virtual Ref<Texture> generate(const RES& p_from);
+
+ EditorTexturePreviewPlugin();
+};
+
+
+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);
+public:
+
+ virtual bool handles(const String& p_type) const;
+ virtual Ref<Texture> generate(const RES& p_from);
+ virtual Ref<Texture> generate_from_path(const String& p_path);
+
+ EditorPackedScenePreviewPlugin();
+};
+
+class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
+
+ RID scenario;
+ RID sphere;
+ RID sphere_instance;
+ RID viewport;
+ RID light;
+ RID light_instance;
+ RID light2;
+ RID light_instance2;
+ RID camera;
+public:
+
+ virtual bool handles(const String& p_type) const;
+ virtual Ref<Texture> generate(const RES& p_from);
+
+ EditorMaterialPreviewPlugin();
+ ~EditorMaterialPreviewPlugin();
+};
+
+class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
+public:
+
+ virtual bool handles(const String& p_type) const;
+ virtual Ref<Texture> generate(const RES& p_from);
+
+ EditorScriptPreviewPlugin();
+};
+
+#if 0
+class EditorSamplePreviewPlugin : public EditorResourcePreviewGenerator {
+public:
+
+ virtual bool handles(const String& p_type) const;
+ virtual Ref<Texture> generate(const RES& p_from);
+
+ EditorSamplePreviewPlugin();
+};
+
+#endif
+class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
+
+ RID scenario;
+ RID mesh_instance;
+ RID viewport;
+ RID light;
+ RID light_instance;
+ RID light2;
+ RID light_instance2;
+ RID camera;
+public:
+
+ virtual bool handles(const String& p_type) const;
+ virtual Ref<Texture> generate(const RES& p_from);
+
+ EditorMeshPreviewPlugin();
+ ~EditorMeshPreviewPlugin();
+};
+
+#endif
+#endif // EDITORPREVIEWPLUGINS_H
diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp
new file mode 100644
index 0000000000..925ac8ef11
--- /dev/null
+++ b/editor/plugins/gi_probe_editor_plugin.cpp
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* gi_probe_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "gi_probe_editor_plugin.h"
+
+
+void GIProbeEditorPlugin::_bake() {
+
+ if (gi_probe) {
+ gi_probe->bake();
+ }
+}
+
+
+void GIProbeEditorPlugin::edit(Object *p_object) {
+
+ GIProbe * s = p_object->cast_to<GIProbe>();
+ if (!s)
+ return;
+
+ gi_probe=s;
+}
+
+bool GIProbeEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("GIProbe");
+}
+
+void GIProbeEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ bake->show();
+ } else {
+
+ bake->hide();
+ }
+
+}
+
+void GIProbeEditorPlugin::_bind_methods() {
+
+ ClassDB::bind_method("_bake",&GIProbeEditorPlugin::_bake);
+}
+
+GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ bake = memnew( Button );
+ bake->set_icon(editor->get_gui_base()->get_icon("BakedLight","EditorIcons"));
+ bake->hide();
+ bake->connect("pressed",this,"_bake");
+ add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU,bake);
+ gi_probe=NULL;
+}
+
+
+GIProbeEditorPlugin::~GIProbeEditorPlugin() {
+}
diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h
new file mode 100644
index 0000000000..982a549368
--- /dev/null
+++ b/editor/plugins/gi_probe_editor_plugin.h
@@ -0,0 +1,65 @@
+/*************************************************************************/
+/* gi_probe_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 GIPROBEEDITORPLUGIN_H
+#define GIPROBEEDITORPLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/resources/material.h"
+#include "scene/3d/gi_probe.h"
+
+
+
+class GIProbeEditorPlugin : public EditorPlugin {
+
+ GDCLASS( GIProbeEditorPlugin, EditorPlugin );
+
+ GIProbe *gi_probe;
+
+ Button *bake;
+ EditorNode *editor;
+
+ void _bake();
+protected:
+
+ static void _bind_methods();
+public:
+
+ virtual String get_name() const { return "GIProbe"; }
+ 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);
+
+ GIProbeEditorPlugin(EditorNode *p_node);
+ ~GIProbeEditorPlugin();
+
+};
+
+#endif // GIPROBEEDITORPLUGIN_H
diff --git a/tools/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp
index f31074a9dc..f31074a9dc 100644
--- a/tools/editor/plugins/item_list_editor_plugin.cpp
+++ b/editor/plugins/item_list_editor_plugin.cpp
diff --git a/editor/plugins/item_list_editor_plugin.h b/editor/plugins/item_list_editor_plugin.h
new file mode 100644
index 0000000000..25d6ed6757
--- /dev/null
+++ b/editor/plugins/item_list_editor_plugin.h
@@ -0,0 +1,230 @@
+/*************************************************************************/
+/* item_list_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 ITEM_LIST_EDITOR_PLUGIN_H
+#define ITEM_LIST_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "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"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+
+class ItemListPlugin : public Object {
+
+ GDCLASS(ItemListPlugin,Object);
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+ enum Flags {
+
+ FLAG_ICON=1,
+ FLAG_CHECKABLE=2,
+ 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 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 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 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;
+ virtual void erase(int p_idx)=0;
+
+ ItemListPlugin() {}
+};
+
+///////////////////////////////////////////////////////////////
+
+class ItemListOptionButtonPlugin : public ItemListPlugin {
+
+ GDCLASS(ItemListOptionButtonPlugin,ItemListPlugin);
+
+ OptionButton *ob;
+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) { ob->set_item_text(p_idx,p_text); }
+ virtual String get_item_text(int p_idx) const { return ob->get_item_text(p_idx); }
+
+ 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); }
+
+ 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 {
+
+ GDCLASS(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 {
+
+ GDCLASS(ItemListEditor,HBoxContainer);
+
+ Node *item_list;
+
+ ToolButton *toolbar_button;
+
+ AcceptDialog *dialog;
+ PropertyEditor *property_editor;
+ Tree *tree;
+ Button *add_button;
+ Button *del_button;
+
+ int selected_idx;
+
+ Vector<ItemListPlugin*> item_plugins;
+
+ 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:
+
+ void edit(Node *p_item_list);
+ bool handles(Object *p_object) const;
+ void add_plugin(ItemListPlugin* p_plugin) { item_plugins.push_back(p_plugin); }
+ ItemListEditor();
+ ~ItemListEditor();
+};
+
+class ItemListEditorPlugin : public EditorPlugin {
+
+ GDCLASS(ItemListEditorPlugin,EditorPlugin);
+
+ ItemListEditor *item_list_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "ItemList"; }
+ 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);
+
+ ItemListEditorPlugin(EditorNode *p_node);
+ ~ItemListEditorPlugin();
+
+};
+
+#endif // ITEM_LIST_EDITOR_PLUGIN_H
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..be9e52e241
--- /dev/null
+++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp
@@ -0,0 +1,518 @@
+/*************************************************************************/
+/* light_occluder_2d_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "light_occluder_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+
+void LightOccluder2DEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon( get_icon("Edit","EditorIcons"));
+ button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ button_edit->set_pressed(true);
+ get_tree()->connect("node_removed",this,"_node_removed");
+ create_poly->connect("confirmed",this,"_create_poly");
+
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void LightOccluder2DEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
+}
+
+
+void LightOccluder2DEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case MODE_CREATE: {
+
+ mode=MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode=MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+
+ }
+}
+
+void LightOccluder2DEditor::_wip_close(bool p_closed) {
+
+ undo_redo->create_action(TTR("Create Poly"));
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",node->get_occluder_polygon()->get_polygon());
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",wip);
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_closed",node->get_occluder_polygon()->is_closed());
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_closed",p_closed);
+
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ wip.clear();
+ wip_active=false;
+ mode=MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ edited_point=-1;
+}
+
+bool LightOccluder2DEditor::forward_gui_input(const InputEvent& p_event) {
+
+
+ if (!node)
+ return false;
+
+ if (node->get_occluder_polygon().is_null()) {
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+ create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?");
+ create_poly->popup_centered_minsize();
+ }
+ return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);
+ }
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
+
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( cpoint );
+ wip_active=true;
+ edited_point_pos=cpoint;
+ canvas_item_editor->get_viewport_control()->update();
+ edited_point=1;
+ return true;
+ } else {
+
+
+ if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close(true);
+
+ return true;
+ } else if (wip.size()>1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close(false);
+ return true;
+
+ } else {
+
+ wip.push_back( cpoint );
+ edited_point=wip.size();
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close(true);
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ if (poly.size() < 3) {
+
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ poly.push_back(cpoint);
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ //search edges
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 points[2] ={ xform.xform(poly[i]),
+ xform.xform(poly[(i+1)%poly.size()]) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+ if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
+ edited_point=closest_idx+1;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ node->get_occluder_polygon()->set_polygon(Variant(poly));
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ edited_point=closest_idx;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly[edited_point]=edited_point_pos;
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",pre_move_edit);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ }
+
+
+
+ } break;
+ }
+
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ }
+
+ } break;
+ }
+
+ return false;
+}
+void LightOccluder2DEditor::_canvas_draw() {
+
+ if (!node || !node->get_occluder_polygon().is_valid())
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ Vector<Vector2> poly;
+
+ if (wip_active)
+ poly=wip;
+ else
+ poly=Variant(node->get_occluder_polygon()->get_polygon());
+
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
+
+ for(int i=0;i<poly.size();i++) {
+
+
+ Vector2 p,p2;
+ p = i==edited_point ? edited_point_pos : poly[i];
+ if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
+ p2=edited_point_pos;
+ else
+ p2 = poly[(i+1)%poly.size()];
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ Color col=Color(1,0.3,0.1,0.8);
+
+ if (i==poly.size()-1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) {
+
+ } else {
+ vpc->draw_line(point,next_point,col,2);
+ }
+ vpc->draw_texture(handle,point-handle->get_size()*0.5);
+ }
+}
+
+
+
+void LightOccluder2DEditor::edit(Node *p_collision_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton();
+ }
+
+ if (p_collision_polygon) {
+
+ node=p_collision_polygon->cast_to<LightOccluder2D>();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+ canvas_item_editor->get_viewport_control()->update();
+ } else {
+ node=NULL;
+
+ if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
+
+ }
+
+}
+
+void LightOccluder2DEditor::_create_poly() {
+
+ if (!node)
+ return;
+ undo_redo->create_action(TTR("Create Occluder Polygon"));
+ undo_redo->add_do_method(node,"set_occluder_polygon",Ref<OccluderPolygon2D>(memnew( OccluderPolygon2D)));
+ undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF()));
+ undo_redo->commit_action();
+}
+
+void LightOccluder2DEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_menu_option"),&LightOccluder2DEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_canvas_draw"),&LightOccluder2DEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&LightOccluder2DEditor::_node_removed);
+ ClassDB::bind_method(D_METHOD("_create_poly"),&LightOccluder2DEditor::_create_poly);
+
+}
+
+
+LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) {
+
+ node=NULL;
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ add_child( memnew( VSeparator ));
+ button_create = memnew( ToolButton );
+ add_child(button_create);
+ button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+ button_create->set_tooltip(TTR("Create a new polygon from scratch."));
+
+ button_edit = memnew( ToolButton );
+ add_child(button_edit);
+ button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip(TTR("Edit existing polygon:")+"\n"+TTR("LMB: Move Point.")+"\n"+TTR("Ctrl+LMB: Split Segment.")+"\n"+TTR("RMB: Erase Point."));
+
+ create_poly = memnew( ConfirmationDialog );
+ add_child(create_poly);
+ create_poly->get_ok()->set_text(TTR("Create"));
+
+
+ //add_constant_override("separation",0);
+
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+#endif
+
+ mode = MODE_EDIT;
+ wip_active=false;
+
+}
+
+
+void LightOccluder2DEditorPlugin::edit(Object *p_object) {
+
+ collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool LightOccluder2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("LightOccluder2D");
+}
+
+void LightOccluder2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ collision_polygon_editor->show();
+ } else {
+
+ collision_polygon_editor->hide();
+ collision_polygon_editor->edit(NULL);
+ }
+
+}
+
+LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ collision_polygon_editor = memnew( LightOccluder2DEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+ collision_polygon_editor->hide();
+
+
+
+}
+
+
+LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h
new file mode 100644
index 0000000000..1f1c6e86eb
--- /dev/null
+++ b/editor/plugins/light_occluder_2d_editor_plugin.h
@@ -0,0 +1,115 @@
+/*************************************************************************/
+/* light_occluder_2d_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
+#define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
+
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/light_occluder_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class LightOccluder2DEditor : public HBoxContainer {
+
+ GDCLASS(LightOccluder2DEditor, HBoxContainer );
+
+ UndoRedo *undo_redo;
+ enum Mode {
+
+ MODE_CREATE,
+ MODE_EDIT,
+
+ };
+
+ Mode mode;
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ LightOccluder2D *node;
+ MenuButton *options;
+
+ int edited_point;
+ Vector2 edited_point_pos;
+ Vector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+
+ ConfirmationDialog *create_poly;
+
+ void _wip_close(bool p_closed);
+ void _canvas_draw();
+ void _menu_option(int p_option);
+ void _create_poly();
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ Vector2 snap_point(const Vector2& p_point) const;
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node *p_collision_polygon);
+ LightOccluder2DEditor(EditorNode *p_editor);
+};
+
+class LightOccluder2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS( LightOccluder2DEditorPlugin, EditorPlugin );
+
+ LightOccluder2DEditor *collision_polygon_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+
+ virtual String get_name() const { return "LightOccluder2D"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_node);
+ virtual bool handles(Object *p_node) const;
+ virtual void make_visible(bool p_visible);
+
+ LightOccluder2DEditorPlugin(EditorNode *p_node);
+ ~LightOccluder2DEditorPlugin();
+
+};
+
+#endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..4a0f90a2b4
--- /dev/null
+++ b/editor/plugins/line_2d_editor_plugin.cpp
@@ -0,0 +1,311 @@
+/*************************************************************************/
+/* line_2d_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "line_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+#include "os/keyboard.h"
+
+
+//----------------------------------------------------------------------------
+// Line2DEditor
+//----------------------------------------------------------------------------
+
+void Line2DEditor::_node_removed(Node *p_node) {
+ if(p_node == node) {
+ node=NULL;
+ hide();
+ }
+}
+
+void Line2DEditor::_notification(int p_what) {
+ switch(p_what) {
+ case NOTIFICATION_VISIBILITY_CHANGED:
+ // This widget is not a child but should have the same visibility state
+ base_hb->set_visible(is_visible());
+ break;
+ }
+}
+
+Vector2 Line2DEditor::mouse_to_local_pos(Vector2 gpoint, bool alt) {
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ return !alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
+ : node->get_global_transform().affine_inverse().xform(
+ canvas_item_editor->snap_point(
+ canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
+}
+
+int Line2DEditor::get_point_index_at(Vector2 gpos) {
+ ERR_FAIL_COND_V(node == 0, -1);
+
+ real_t grab_treshold = EDITOR_DEF("poly_editor/point_grab_radius", 8);
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+ for(int i = 0; i < node->get_point_count(); ++i) {
+ Point2 p = xform.xform( node->get_point_pos(i) );
+ if(gpos.distance_to(p) < grab_treshold) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+bool Line2DEditor::forward_gui_input(const InputEvent& p_event) {
+
+ if (!node)
+ return false;
+
+ if (!node->is_visible())
+ return false;
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb = p_event.mouse_button;
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = mouse_to_local_pos(gpoint, mb.mod.alt);
+
+ if(mb.pressed && _dragging == false) {
+ int i = get_point_index_at(gpoint);
+ if(i != -1) {
+ if (mb.button_index == BUTTON_LEFT && !mb.mod.shift && mode == MODE_EDIT) {
+ _dragging = true;
+ action_point = i;
+ moving_from = node->get_point_pos(i);
+ moving_screen_from = gpoint;
+ }
+ else if((mb.button_index == BUTTON_RIGHT && mode == MODE_EDIT) || (mb.button_index == BUTTON_LEFT && mode == MODE_DELETE)) {
+ undo_redo->create_action(TTR("Remove Point from Line2D"));
+ undo_redo->add_do_method(node, "remove_point", i);
+ undo_redo->add_undo_method(node, "add_point", node->get_point_pos(i), i);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->commit_action();
+ }
+ return true;
+ }
+ }
+
+ if(mb.pressed && mb.button_index == BUTTON_LEFT && ((mb.mod.command && mode == MODE_EDIT) || mode == MODE_CREATE)) {
+
+ undo_redo->create_action(TTR("Add Point to Line2D"));
+ undo_redo->add_do_method(node, "add_point", cpoint);
+ undo_redo->add_undo_method(node, "remove_point", node->get_point_count());
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->commit_action();
+
+ _dragging = true;
+ action_point = node->get_point_count()-1;
+ moving_from = node->get_point_pos(action_point);
+ moving_screen_from = gpoint;
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ return true;
+ }
+
+ if(!mb.pressed && mb.button_index == BUTTON_LEFT && _dragging) {
+ undo_redo->create_action(TTR("Move Point in Line2D"));
+ undo_redo->add_do_method(node, "set_point_pos", action_point, cpoint);
+ undo_redo->add_undo_method(node, "set_point_pos", action_point, moving_from);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update");
+ undo_redo->commit_action();
+ _dragging = false;
+ return true;
+ }
+ }
+ break;
+
+ case InputEvent::MOUSE_MOTION: {
+ if (_dragging) {
+ const InputEventMouseMotion &mm = p_event.mouse_motion;
+ Vector2 cpoint = mouse_to_local_pos(Vector2(mm.x, mm.y), mm.mod.alt);
+ node->set_point_pos(action_point,cpoint);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ break;
+ }
+
+ return false;
+}
+
+void Line2DEditor::_canvas_draw() {
+
+ if (!node)
+ return;
+
+ if (!node->is_visible())
+ return;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
+ Size2 handle_size = handle->get_size();
+
+ int len = node->get_point_count();
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ for(int i=0; i < len; ++i) {
+ Vector2 point = xform.xform(node->get_point_pos(i));
+ vpc->draw_texture_rect(handle, Rect2(point - handle_size * 0.5, handle_size), false);
+ }
+}
+
+void Line2DEditor::_node_visibility_changed() {
+ if (!node)
+ return;
+ canvas_item_editor->get_viewport_control()->update();
+}
+
+void Line2DEditor::edit(Node *p_line2d) {
+
+ if (!canvas_item_editor)
+ canvas_item_editor = CanvasItemEditor::get_singleton();
+
+ if (p_line2d) {
+ node = p_line2d->cast_to<Line2D>();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw", this, "_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw", this, "_canvas_draw");
+ 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"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw", this, "_canvas_draw");
+ // node may have been deleted at this point
+ if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed"))
+ node->disconnect("visibility_changed", this, "_node_visibility_changed");
+ node = NULL;
+ }
+}
+
+void Line2DEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_canvas_draw"), &Line2DEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Line2DEditor::_node_visibility_changed);
+ ClassDB::bind_method(D_METHOD("_mode_selected"), &Line2DEditor::_mode_selected);
+}
+
+void Line2DEditor::_mode_selected(int p_mode) {
+ for(unsigned int i = 0; i < _MODE_COUNT; ++i) {
+ toolbar_buttons[i]->set_pressed(i == p_mode);
+ }
+ mode = Mode(p_mode);
+}
+
+Line2DEditor::Line2DEditor(EditorNode *p_editor) {
+
+ canvas_item_editor = NULL;
+ editor = p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ _dragging = false;
+
+ base_hb = memnew( HBoxContainer );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(base_hb);
+
+ sep = memnew( VSeparator);
+ base_hb->add_child(sep);
+
+ {
+ ToolButton * b = memnew(ToolButton);
+ b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons"));
+ b->set_toggle_mode(true);
+ b->set_focus_mode(Control::FOCUS_NONE);
+ b->set_tooltip(
+ TTR("Select Points")+"\n"
+ + TTR("Shift+Drag: Select Control Points")+"\n"
+ + keycode_get_string(KEY_MASK_CMD)
+ + TTR("Click: Add Point")+"\n"
+ + TTR("Right Click: Delete Point"));
+ b->connect("pressed", this, "_mode_selected", varray(MODE_EDIT));
+ toolbar_buttons[MODE_EDIT] = b;
+ base_hb->add_child(b);
+ }
+
+ {
+ ToolButton * b = memnew(ToolButton);
+ b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons"));
+ b->set_toggle_mode(true);
+ b->set_focus_mode(Control::FOCUS_NONE);
+ b->set_tooltip(TTR("Add Point (in empty space)")+"\n"+TTR("Split Segment (in line)"));
+ b->connect("pressed", this, "_mode_selected", varray(MODE_CREATE));
+ toolbar_buttons[MODE_CREATE] = b;
+ base_hb->add_child(b);
+ }
+
+ {
+ ToolButton * b = memnew( ToolButton );
+ b->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete", "EditorIcons"));
+ b->set_toggle_mode(true);
+ b->set_focus_mode(Control::FOCUS_NONE);
+ b->set_tooltip(TTR("Delete Point"));
+ b->connect("pressed", this, "_mode_selected", varray(MODE_DELETE));
+ toolbar_buttons[MODE_DELETE] = b;
+ base_hb->add_child(b);
+ }
+
+ base_hb->hide();
+ hide();
+
+ _mode_selected(MODE_CREATE);
+}
+
+//----------------------------------------------------------------------------
+// Line2DEditorPlugin
+//----------------------------------------------------------------------------
+
+void Line2DEditorPlugin::edit(Object *p_object) {
+ line2d_editor->edit(p_object->cast_to<Node>());
+}
+
+bool Line2DEditorPlugin::handles(Object *p_object) const {
+ return p_object->is_class("Line2D");
+}
+
+void Line2DEditorPlugin::make_visible(bool p_visible) {
+ line2d_editor->set_visible(p_visible);
+ if(p_visible == false)
+ line2d_editor->edit(NULL);
+}
+
+Line2DEditorPlugin::Line2DEditorPlugin(EditorNode *p_node) {
+ editor=p_node;
+ line2d_editor = memnew( Line2DEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(line2d_editor);
+ line2d_editor->hide();
+}
+
+
diff --git a/editor/plugins/line_2d_editor_plugin.h b/editor/plugins/line_2d_editor_plugin.h
new file mode 100644
index 0000000000..6e0da7df38
--- /dev/null
+++ b/editor/plugins/line_2d_editor_plugin.h
@@ -0,0 +1,118 @@
+/*************************************************************************/
+/* line_2d_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 LINE_2D_EDITOR_PLUGIN_H
+#define LINE_2D_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/path_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+#include "scene/2d/line_2d.h"
+
+
+class CanvasItemEditor;
+
+class Line2DEditor : public HBoxContainer {
+ GDCLASS(Line2DEditor, HBoxContainer)
+
+public:
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node *p_line2d);
+ Line2DEditor(EditorNode *p_editor);
+
+protected:
+ void _node_removed(Node *p_node);
+ void _notification(int p_what);
+
+ Vector2 mouse_to_local_pos(Vector2 mpos);
+
+ static void _bind_methods();
+
+private:
+ void _mode_selected(int p_mode);
+ void _canvas_draw();
+ void _node_visibility_changed();
+
+ int get_point_index_at(Vector2 gpos);
+ Vector2 mouse_to_local_pos(Vector2 gpos, bool alt);
+
+ UndoRedo *undo_redo;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ Line2D *node;
+
+ HBoxContainer *base_hb;
+ Separator *sep;
+
+ enum Mode {
+ MODE_CREATE = 0,
+ MODE_EDIT,
+ MODE_DELETE,
+ _MODE_COUNT
+ };
+
+ Mode mode;
+ ToolButton* toolbar_buttons[_MODE_COUNT];
+
+ bool _dragging;
+ int action_point;
+ Point2 moving_from;
+ Point2 moving_screen_from;
+};
+
+class Line2DEditorPlugin : public EditorPlugin {
+ GDCLASS( Line2DEditorPlugin, EditorPlugin )
+
+public:
+ virtual bool forward_canvas_gui_input(
+ const Transform2D& p_canvas_xform,
+ const InputEvent& p_event)
+ {
+ return line2d_editor->forward_gui_input(p_event);
+ }
+
+ virtual String get_name() const { return "Line2D"; }
+ 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);
+
+ Line2DEditorPlugin(EditorNode *p_node);
+
+private:
+ Line2DEditor *line2d_editor;
+ EditorNode *editor;
+
+};
+
+#endif // LINE_2D_EDITOR_PLUGIN_H
+
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
new file mode 100644
index 0000000000..cdf7c70d39
--- /dev/null
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -0,0 +1,413 @@
+/*************************************************************************/
+/* material_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "material_editor_plugin.h"
+
+#include "scene/main/viewport.h"
+
+#if 0
+
+void MaterialEditor::_gui_input(InputEvent p_event) {
+
+
+}
+
+void MaterialEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+ }
+
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //get_scene()->connect("node_removed",this,"_node_removed");
+
+ if (first_enter) {
+ //it's in propertyeditor so.. could be moved around
+
+ light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1","EditorIcons"));
+ light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off","EditorIcons"));
+ light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2","EditorIcons"));
+ light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off","EditorIcons"));
+
+ sphere_switch->set_normal_texture(get_icon("MaterialPreviewSphereOff","EditorIcons"));
+ sphere_switch->set_pressed_texture(get_icon("MaterialPreviewSphere","EditorIcons"));
+ box_switch->set_normal_texture(get_icon("MaterialPreviewCubeOff","EditorIcons"));
+ box_switch->set_pressed_texture(get_icon("MaterialPreviewCube","EditorIcons"));
+
+ first_enter=false;
+ }
+
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+
+ Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons");
+ Size2 size = get_size();
+
+ draw_texture_rect(checkerboard,Rect2(Point2(),size),true);
+
+ }
+}
+
+
+
+void MaterialEditor::edit(Ref<Material> p_material) {
+
+ material=p_material;
+
+ if (!material.is_null()) {
+ sphere_mesh->surface_set_material(0,material);
+ box_mesh->surface_set_material(0,material);
+ } else {
+
+ hide();
+ }
+
+}
+
+
+void MaterialEditor::_button_pressed(Node* p_button) {
+
+ if (p_button==light_1_switch) {
+ light1->set_enabled(!light_1_switch->is_pressed());
+ }
+
+ if (p_button==light_2_switch) {
+ light2->set_enabled(!light_2_switch->is_pressed());
+ }
+
+ if (p_button==box_switch) {
+ box_instance->show();
+ sphere_instance->hide();
+ box_switch->set_pressed(true);
+ sphere_switch->set_pressed(false);
+ }
+
+ if (p_button==sphere_switch) {
+ box_instance->hide();
+ sphere_instance->show();
+ box_switch->set_pressed(false);
+ sphere_switch->set_pressed(true);
+ }
+
+}
+
+void MaterialEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&MaterialEditor::_gui_input);
+ ClassDB::bind_method(D_METHOD("_button_pressed"),&MaterialEditor::_button_pressed);
+
+}
+
+MaterialEditor::MaterialEditor() {
+
+ viewport = memnew( Viewport );
+ Ref<World> world;
+ world.instance();
+ viewport->set_world(world); //use own world
+ add_child(viewport);
+ viewport->set_disable_input(true);
+
+ camera = memnew( Camera );
+ camera->set_transform(Transform(Matrix3(),Vector3(0,0,3)));
+ camera->set_perspective(45,0.1,10);
+ viewport->add_child(camera);
+
+ light1 = memnew( DirectionalLight );
+ light1->set_transform(Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
+ viewport->add_child(light1);
+
+ light2 = memnew( DirectionalLight );
+ light2->set_transform(Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
+ light2->set_color(Light::COLOR_DIFFUSE,Color(0.7,0.7,0.7));
+ light2->set_color(Light::COLOR_SPECULAR,Color(0.7,0.7,0.7));
+ viewport->add_child(light2);
+
+ sphere_instance = memnew( MeshInstance );
+ viewport->add_child(sphere_instance);
+
+ box_instance = memnew( MeshInstance );
+ viewport->add_child(box_instance);
+
+ Transform box_xform;
+ box_xform.basis.rotate(Vector3(1,0,0),Math::deg2rad(25));
+ box_xform.basis = box_xform.basis * Matrix3().rotated(Vector3(0,1,0),Math::deg2rad(25));
+ box_xform.basis.scale(Vector3(0.8,0.8,0.8));
+ box_instance->set_transform(box_xform);
+
+ {
+
+ sphere_mesh.instance();
+
+
+ int lats=32;
+ int lons=32;
+ float radius=1.0;
+
+ PoolVector<Vector3> vertices;
+ PoolVector<Vector3> normals;
+ PoolVector<Vector2> uvs;
+ PoolVector<float> tangents;
+ Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5);
+
+ for(int i = 1; i <= lats; i++) {
+ double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
+ double z0 = Math::sin(lat0);
+ double zr0 = Math::cos(lat0);
+
+ double lat1 = Math_PI * (-0.5 + (double) i / lats);
+ double z1 = Math::sin(lat1);
+ double zr1 = Math::cos(lat1);
+
+ for(int j = lons; j >= 1; j--) {
+
+ double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
+ double x0 = Math::cos(lng0);
+ double y0 = Math::sin(lng0);
+
+ double lng1 = 2 * Math_PI * (double) (j) / lons;
+ double x1 = Math::cos(lng1);
+ double y1 = Math::sin(lng1);
+
+
+ Vector3 v[4]={
+ Vector3(x1 * zr0, z0, y1 *zr0),
+ Vector3(x1 * zr1, z1, y1 *zr1),
+ Vector3(x0 * zr1, z1, y0 *zr1),
+ Vector3(x0 * zr0, z0, y0 *zr0)
+ };
+
+ #define ADD_POINT(m_idx) \
+ normals.push_back(v[m_idx]);\
+ vertices.push_back(v[m_idx]*radius);\
+ { Vector2 uv(Math::atan2(v[m_idx].x,v[m_idx].z),Math::atan2(-v[m_idx].y,v[m_idx].z));\
+ uv/=Math_PI;\
+ uv*=4.0;\
+ uv=uv*0.5+Vector2(0.5,0.5);\
+ uvs.push_back(uv);\
+ }\
+ { Vector3 t = tt.xform(v[m_idx]);\
+ tangents.push_back(t.x);\
+ tangents.push_back(t.y);\
+ tangents.push_back(t.z);\
+ tangents.push_back(1.0);\
+ }
+
+
+
+ ADD_POINT(0);
+ ADD_POINT(1);
+ ADD_POINT(2);
+
+ ADD_POINT(2);
+ ADD_POINT(3);
+ ADD_POINT(0);
+ }
+ }
+
+ Array arr;
+ arr.resize(VS::ARRAY_MAX);
+ arr[VS::ARRAY_VERTEX]=vertices;
+ arr[VS::ARRAY_NORMAL]=normals;
+ arr[VS::ARRAY_TANGENT]=tangents;
+ arr[VS::ARRAY_TEX_UV]=uvs;
+
+ sphere_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr);
+
+ sphere_instance->set_mesh(sphere_mesh);
+
+ }
+ {
+
+
+ box_mesh.instance();
+
+ PoolVector<Vector3> vertices;
+ PoolVector<Vector3> normals;
+ PoolVector<float> tangents;
+ PoolVector<Vector3> uvs;
+
+ int vtx_idx=0;
+ #define ADD_VTX(m_idx);\
+ vertices.push_back( face_points[m_idx] );\
+ normals.push_back( normal_points[m_idx] );\
+ tangents.push_back( normal_points[m_idx][1] );\
+ tangents.push_back( normal_points[m_idx][2] );\
+ tangents.push_back( normal_points[m_idx][0] );\
+ tangents.push_back( 1.0 );\
+ uvs.push_back( Vector3(uv_points[m_idx*2+0],uv_points[m_idx*2+1],0) );\
+ vtx_idx++;\
+
+ for (int i=0;i<6;i++) {
+
+
+ Vector3 face_points[4];
+ Vector3 normal_points[4];
+ float uv_points[8]={0,0,0,1,1,1,1,0};
+
+ for (int j=0;j<4;j++) {
+
+ float v[3];
+ v[0]=1.0;
+ v[1]=1-2*((j>>1)&1);
+ v[2]=v[1]*(1-2*(j&1));
+
+ for (int k=0;k<3;k++) {
+
+ if (i<3)
+ face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ else
+ face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ }
+ normal_points[j]=Vector3();
+ normal_points[j][i%3]=(i>=3?-1:1);
+ }
+
+ //tri 1
+ ADD_VTX(0);
+ ADD_VTX(1);
+ ADD_VTX(2);
+ //tri 2
+ ADD_VTX(2);
+ ADD_VTX(3);
+ ADD_VTX(0);
+
+ }
+
+
+
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+ d[VisualServer::ARRAY_NORMAL]= normals ;
+ d[VisualServer::ARRAY_TANGENT]= tangents ;
+ d[VisualServer::ARRAY_TEX_UV]= uvs ;
+ d[VisualServer::ARRAY_VERTEX]= vertices ;
+
+ PoolVector<int> indices;
+ indices.resize(vertices.size());
+ for(int i=0;i<vertices.size();i++)
+ indices.set(i,i);
+ d[VisualServer::ARRAY_INDEX]=indices;
+
+ box_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d);
+ box_instance->set_mesh(box_mesh);
+ box_instance->hide();
+
+
+
+ }
+
+ set_custom_minimum_size(Size2(1,150)*EDSCALE);
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ add_child(hb);
+ hb->set_area_as_parent_rect(2);
+
+ VBoxContainer *vb_shape = memnew( VBoxContainer );
+ hb->add_child(vb_shape);
+
+ sphere_switch = memnew( TextureButton );
+ sphere_switch->set_toggle_mode(true);
+ sphere_switch->set_pressed(true);
+ vb_shape->add_child(sphere_switch);
+ sphere_switch->connect("pressed",this,"_button_pressed",varray(sphere_switch));
+
+ box_switch = memnew( TextureButton );
+ box_switch->set_toggle_mode(true);
+ box_switch->set_pressed(false);
+ vb_shape->add_child(box_switch);
+ box_switch->connect("pressed",this,"_button_pressed",varray(box_switch));
+
+ hb->add_spacer();
+
+ VBoxContainer *vb_light = memnew( VBoxContainer );
+ hb->add_child(vb_light);
+
+ light_1_switch = memnew( TextureButton );
+ light_1_switch->set_toggle_mode(true);
+ vb_light->add_child(light_1_switch);
+ light_1_switch->connect("pressed",this,"_button_pressed",varray(light_1_switch));
+
+ light_2_switch = memnew( TextureButton );
+ light_2_switch->set_toggle_mode(true);
+ vb_light->add_child(light_2_switch);
+ light_2_switch->connect("pressed",this,"_button_pressed",varray(light_2_switch));
+
+ first_enter=true;
+
+}
+
+
+void MaterialEditorPlugin::edit(Object *p_object) {
+
+ Material * s = p_object->cast_to<Material>();
+ if (!s)
+ return;
+
+ material_editor->edit(Ref<Material>(s));
+}
+
+bool MaterialEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("Material");
+}
+
+void MaterialEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ material_editor->show();
+ //material_editor->set_process(true);
+ } else {
+
+ material_editor->hide();
+ //material_editor->set_process(false);
+ }
+
+}
+
+MaterialEditorPlugin::MaterialEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ material_editor = memnew( MaterialEditor );
+ add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,material_editor);
+ material_editor->hide();
+
+
+
+}
+
+
+MaterialEditorPlugin::~MaterialEditorPlugin()
+{
+}
+
+
+#endif
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
new file mode 100644
index 0000000000..604e7e61bd
--- /dev/null
+++ b/editor/plugins/material_editor_plugin.h
@@ -0,0 +1,100 @@
+/*************************************************************************/
+/* material_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 MATERIAL_EDITOR_PLUGIN_H
+#define MATERIAL_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/resources/material.h"
+#include "scene/3d/light.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/camera.h"
+
+#if 0
+class MaterialEditor : public Control {
+
+ GDCLASS(MaterialEditor, Control);
+
+
+ Viewport *viewport;
+ MeshInstance *sphere_instance;
+ MeshInstance *box_instance;
+ DirectionalLight *light1;
+ DirectionalLight *light2;
+ Camera *camera;
+
+ Ref<Mesh> sphere_mesh;
+ Ref<Mesh> box_mesh;
+
+ TextureButton *sphere_switch;
+ TextureButton *box_switch;
+
+ TextureButton *light_1_switch;
+ TextureButton *light_2_switch;
+
+
+ Ref<Material> material;
+
+
+ void _button_pressed(Node* p_button);
+ bool first_enter;
+
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+ void edit(Ref<Material> p_material);
+ MaterialEditor();
+};
+
+
+class MaterialEditorPlugin : public EditorPlugin {
+
+ GDCLASS( MaterialEditorPlugin, EditorPlugin );
+
+ MaterialEditor *material_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "Material"; }
+ 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);
+
+ MaterialEditorPlugin(EditorNode *p_node);
+ ~MaterialEditorPlugin();
+
+};
+
+#endif // MATERIAL_EDITOR_PLUGIN_H
+#endif
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
new file mode 100644
index 0000000000..93f417247e
--- /dev/null
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -0,0 +1,245 @@
+/*************************************************************************/
+/* mesh_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "mesh_editor_plugin.h"
+
+#if 0
+void MeshEditor::_gui_input(InputEvent p_event) {
+
+
+ if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
+
+ rot_x-=p_event.mouse_motion.relative_y*0.01;
+ rot_y-=p_event.mouse_motion.relative_x*0.01;
+ if (rot_x<-Math_PI/2)
+ rot_x=-Math_PI/2;
+ else if (rot_x>Math_PI/2) {
+ rot_x=Math_PI/2;
+ }
+ _update_rotation();
+ }
+}
+
+void MeshEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+ }
+
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //get_scene()->connect("node_removed",this,"_node_removed");
+
+ if (first_enter) {
+ //it's in propertyeditor so.. could be moved around
+
+ light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1","EditorIcons"));
+ light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off","EditorIcons"));
+ light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2","EditorIcons"));
+ light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off","EditorIcons"));
+ first_enter=false;
+ }
+
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+
+ Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons");
+ Size2 size = get_size();
+
+ draw_texture_rect(checkerboard,Rect2(Point2(),size),true);
+
+ }
+}
+
+void MeshEditor::_update_rotation() {
+
+ Transform t;
+ t.basis.rotate(Vector3(0, 1, 0), -rot_y);
+ t.basis.rotate(Vector3(1, 0, 0), -rot_x);
+ mesh_instance->set_transform(t);
+
+}
+
+void MeshEditor::edit(Ref<Mesh> p_mesh) {
+
+ mesh=p_mesh;
+ mesh_instance->set_mesh(mesh);
+
+ if (mesh.is_null()) {
+
+ hide();
+ } else {
+ rot_x=0;
+ rot_y=0;
+ _update_rotation();
+
+ AABB aabb= mesh->get_aabb();
+ Vector3 ofs = aabb.pos + aabb.size*0.5;
+ aabb.pos-=ofs;
+ float m = MAX(aabb.size.x,aabb.size.y)*0.5;
+ if (m!=0) {
+ m=1.0/m;
+ m*=0.5;
+ //print_line("scale: "+rtos(m));
+ Transform xform;
+ xform.basis.scale(Vector3(m,m,m));
+ xform.origin=-xform.basis.xform(ofs); //-ofs*m;
+ xform.origin.z-=aabb.size.z*2;
+ mesh_instance->set_transform(xform);
+ }
+
+ }
+
+}
+
+
+void MeshEditor::_button_pressed(Node* p_button) {
+
+ if (p_button==light_1_switch) {
+ light1->set_enabled(!light_1_switch->is_pressed());
+ }
+
+ if (p_button==light_2_switch) {
+ light2->set_enabled(!light_2_switch->is_pressed());
+ }
+
+
+}
+
+void MeshEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&MeshEditor::_gui_input);
+ ClassDB::bind_method(D_METHOD("_button_pressed"),&MeshEditor::_button_pressed);
+
+}
+
+MeshEditor::MeshEditor() {
+
+ viewport = memnew( Viewport );
+ Ref<World> world;
+ world.instance();
+ viewport->set_world(world); //use own world
+ add_child(viewport);
+ viewport->set_disable_input(true);
+
+ camera = memnew( Camera );
+ camera->set_transform(Transform(Matrix3(),Vector3(0,0,3)));
+ camera->set_perspective(45,0.1,10);
+ viewport->add_child(camera);
+
+ light1 = memnew( DirectionalLight );
+ light1->set_transform(Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
+ viewport->add_child(light1);
+
+ light2 = memnew( DirectionalLight );
+ light2->set_transform(Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
+ light2->set_color(Light::COLOR_DIFFUSE,Color(0.7,0.7,0.7));
+ light2->set_color(Light::COLOR_SPECULAR,Color(0.7,0.7,0.7));
+ viewport->add_child(light2);
+
+ mesh_instance = memnew( MeshInstance );
+ viewport->add_child(mesh_instance);
+
+
+
+ set_custom_minimum_size(Size2(1,150)*EDSCALE);
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ add_child(hb);
+ hb->set_area_as_parent_rect(2);
+
+ hb->add_spacer();
+
+ VBoxContainer *vb_light = memnew( VBoxContainer );
+ hb->add_child(vb_light);
+
+ light_1_switch = memnew( TextureButton );
+ light_1_switch->set_toggle_mode(true);
+ vb_light->add_child(light_1_switch);
+ light_1_switch->connect("pressed",this,"_button_pressed",varray(light_1_switch));
+
+ light_2_switch = memnew( TextureButton );
+ light_2_switch->set_toggle_mode(true);
+ vb_light->add_child(light_2_switch);
+ light_2_switch->connect("pressed",this,"_button_pressed",varray(light_2_switch));
+
+ first_enter=true;
+
+ rot_x=0;
+ rot_y=0;
+
+
+}
+
+
+void MeshEditorPlugin::edit(Object *p_object) {
+
+ Mesh * s = p_object->cast_to<Mesh>();
+ if (!s)
+ return;
+
+ mesh_editor->edit(Ref<Mesh>(s));
+}
+
+bool MeshEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("Mesh");
+}
+
+void MeshEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ mesh_editor->show();
+ //mesh_editor->set_process(true);
+ } else {
+
+ mesh_editor->hide();
+ //mesh_editor->set_process(false);
+ }
+
+}
+
+MeshEditorPlugin::MeshEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ mesh_editor = memnew( MeshEditor );
+ add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,mesh_editor);
+ mesh_editor->hide();
+
+
+
+}
+
+
+MeshEditorPlugin::~MeshEditorPlugin()
+{
+}
+#endif
diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h
new file mode 100644
index 0000000000..80504ae445
--- /dev/null
+++ b/editor/plugins/mesh_editor_plugin.h
@@ -0,0 +1,98 @@
+/*************************************************************************/
+/* mesh_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 MESH_EDITOR_PLUGIN_H
+#define MESH_EDITOR_PLUGIN_H
+
+#if 0
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/resources/material.h"
+#include "scene/3d/light.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/camera.h"
+
+class MeshEditor : public Control {
+
+ GDCLASS(MeshEditor, Control);
+
+
+
+ float rot_x;
+ float rot_y;
+
+ Viewport *viewport;
+ MeshInstance *mesh_instance;
+ DirectionalLight *light1;
+ DirectionalLight *light2;
+ Camera *camera;
+
+ Ref<Mesh> mesh;
+
+
+ TextureButton *light_1_switch;
+ TextureButton *light_2_switch;
+
+ void _button_pressed(Node* p_button);
+ bool first_enter;
+
+ void _update_rotation();
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+ void edit(Ref<Mesh> p_mesh);
+ MeshEditor();
+};
+
+
+class MeshEditorPlugin : public EditorPlugin {
+
+ GDCLASS( MeshEditorPlugin, EditorPlugin );
+
+ MeshEditor *mesh_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "Mesh"; }
+ 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);
+
+ MeshEditorPlugin(EditorNode *p_node);
+ ~MeshEditorPlugin();
+
+};
+
+#endif // MESH_EDITOR_PLUGIN_H
+#endif
diff --git a/tools/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp
index 322e212534..322e212534 100644
--- a/tools/editor/plugins/mesh_instance_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_editor_plugin.cpp
diff --git a/editor/plugins/mesh_instance_editor_plugin.h b/editor/plugins/mesh_instance_editor_plugin.h
new file mode 100644
index 0000000000..de5be2fbbb
--- /dev/null
+++ b/editor/plugins/mesh_instance_editor_plugin.h
@@ -0,0 +1,97 @@
+/*************************************************************************/
+/* mesh_instance_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 MESH_INSTANCE_EDITOR_PLUGIN_H
+#define MESH_INSTANCE_EDITOR_PLUGIN_H
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/gui/spin_box.h"
+
+
+class MeshInstanceEditor : public Node {
+
+ GDCLASS(MeshInstanceEditor, Node );
+
+
+ enum Menu {
+
+ MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
+ MENU_OPTION_CREATE_STATIC_CONVEX_BODY,
+ MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
+ MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE,
+ MENU_OPTION_CREATE_NAVMESH,
+ MENU_OPTION_CREATE_OUTLINE_MESH,
+ };
+
+ MeshInstance *node;
+
+ MenuButton *options;
+
+ ConfirmationDialog *outline_dialog;
+ SpinBox *outline_size;
+
+ AcceptDialog *err_dialog;
+
+ void _menu_option(int p_option);
+ void _create_outline_mesh();
+
+friend class MeshInstanceEditorPlugin;
+
+protected:
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(MeshInstance *p_mesh);
+ MeshInstanceEditor();
+};
+
+class MeshInstanceEditorPlugin : public EditorPlugin {
+
+ GDCLASS( MeshInstanceEditorPlugin, EditorPlugin );
+
+ MeshInstanceEditor *mesh_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "MeshInstance"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_node);
+ virtual bool handles(Object *p_node) const;
+ virtual void make_visible(bool p_visible);
+
+ MeshInstanceEditorPlugin(EditorNode *p_node);
+ ~MeshInstanceEditorPlugin();
+
+};
+
+#endif // MESH_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index 6259ddf473..6259ddf473 100644
--- a/tools/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
diff --git a/editor/plugins/multimesh_editor_plugin.h b/editor/plugins/multimesh_editor_plugin.h
new file mode 100644
index 0000000000..a97b3758a1
--- /dev/null
+++ b/editor/plugins/multimesh_editor_plugin.h
@@ -0,0 +1,107 @@
+/*************************************************************************/
+/* multimesh_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 MULTIMESH_EDITOR_PLUGIN_H
+#define MULTIMESH_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/3d/multimesh_instance.h"
+#include "scene/gui/spin_box.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class MultiMeshEditor : public Control {
+
+ GDCLASS(MultiMeshEditor, Control );
+
+friend class MultiMeshEditorPlugin;
+
+ AcceptDialog *err_dialog;
+ MenuButton * options;
+ MultiMeshInstance *_last_pp_node;
+ bool browsing_source;
+
+ Panel *panel;
+ MultiMeshInstance *node;
+
+ LineEdit *surface_source;
+ LineEdit *mesh_source;
+
+ SceneTreeDialog *std;
+
+ ConfirmationDialog *populate_dialog;
+ OptionButton *populate_axis;
+ HSlider *populate_rotate_random;
+ HSlider *populate_tilt_random;
+ SpinBox *populate_scale_random;
+ SpinBox *populate_scale;
+ SpinBox *populate_amount;
+
+ enum Menu {
+
+ MENU_OPTION_POPULATE
+ };
+
+ void _browsed(const NodePath& p_path);
+ void _menu_option(int);
+ void _populate();
+ void _browse(bool p_source);
+
+protected:
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(MultiMeshInstance *p_multimesh);
+ MultiMeshEditor();
+};
+
+class MultiMeshEditorPlugin : public EditorPlugin {
+
+ GDCLASS( MultiMeshEditorPlugin, EditorPlugin );
+
+ MultiMeshEditor *multimesh_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "MultiMesh"; }
+ 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);
+
+ MultiMeshEditorPlugin(EditorNode *p_node);
+ ~MultiMeshEditorPlugin();
+
+};
+
+#endif // MULTIMESH_EDITOR_PLUGIN_H
diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp
new file mode 100644
index 0000000000..654afb754e
--- /dev/null
+++ b/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -0,0 +1,566 @@
+/*************************************************************************/
+/* navigation_polygon_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "navigation_polygon_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+
+void NavigationPolygonEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon( get_icon("Edit","EditorIcons"));
+ button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ button_edit->set_pressed(true);
+ get_tree()->connect("node_removed",this,"_node_removed");
+ create_nav->connect("confirmed",this,"_create_nav");
+
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void NavigationPolygonEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
+}
+
+void NavigationPolygonEditor::_create_nav() {
+
+ if (!node)
+ return;
+
+ undo_redo->create_action(TTR("Create Navigation Polygon"));
+ undo_redo->add_do_method(node,"set_navigation_polygon",Ref<NavigationPolygon>(memnew( NavigationPolygon)));
+ undo_redo->add_undo_method(node,"set_navigation_polygon",Variant(REF()));
+ undo_redo->commit_action();
+}
+
+void NavigationPolygonEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case MODE_CREATE: {
+
+ mode=MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode=MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+
+ }
+}
+
+void NavigationPolygonEditor::_wip_close() {
+
+
+ if (wip.size()>=3) {
+
+ undo_redo->create_action(TTR("Create Poly"));
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"remove_outline",node->get_navigation_polygon()->get_outline_count());
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"add_outline",wip);
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ mode=MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ }
+
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+}
+
+bool NavigationPolygonEditor::forward_gui_input(const InputEvent& p_event) {
+
+
+ if (!node)
+ return false;
+
+ if (node->get_navigation_polygon().is_null()) {
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+ create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?");
+ create_nav->popup_centered_minsize();
+ }
+ return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);
+ }
+
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+
+
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
+
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( cpoint );
+ wip_active=true;
+ edited_point_pos=cpoint;
+ edited_outline=-1;
+ canvas_item_editor->get_viewport_control()->update();
+ edited_point=1;
+ return true;
+ } else {
+
+
+ if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close();
+
+ return true;
+ } else {
+
+ wip.push_back( cpoint );
+ edited_point=wip.size();
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close();
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ //search edges
+ int closest_outline=-1;
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+
+ for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) {
+
+
+ PoolVector<Vector2> points=node->get_navigation_polygon()->get_outline(j);
+
+ int pc=points.size();
+ PoolVector<Vector2>::Read poly=points.read();
+
+ for(int i=0;i<pc;i++) {
+
+ Vector2 points[2] ={ xform.xform(poly[i]),
+ xform.xform(poly[(i+1)%pc]) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+ if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_outline=j;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+
+ }
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=node->get_navigation_polygon()->get_outline(closest_outline);
+ PoolVector<Point2> poly = pre_move_edit;
+ poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
+ edited_point=closest_idx+1;
+ edited_outline=closest_outline;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ node->get_navigation_polygon()->set_outline(closest_outline,poly);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+ int closest_outline=-1;
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+
+ for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) {
+
+
+ PoolVector<Vector2> points=node->get_navigation_polygon()->get_outline(j);
+
+ int pc=points.size();
+ PoolVector<Vector2>::Read poly=points.read();
+
+ for(int i=0;i<pc;i++) {
+
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_outline=j;
+ closest_idx=i;
+ }
+ }
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=node->get_navigation_polygon()->get_outline(closest_outline);
+ edited_point=closest_idx;
+ edited_outline=closest_outline;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline);
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly.set(edited_point,edited_point_pos);
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"set_outline",edited_outline,poly);
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"set_outline",edited_outline,pre_move_edit);
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+ int closest_outline=-1;
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+
+ for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) {
+
+
+ PoolVector<Vector2> points=node->get_navigation_polygon()->get_outline(j);
+
+ int pc=points.size();
+ PoolVector<Vector2>::Read poly=points.read();
+
+ for(int i=0;i<pc;i++) {
+
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_outline=j;
+ closest_idx=i;
+ }
+ }
+ }
+
+ if (closest_idx>=0) {
+
+
+ PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline);
+
+ if (poly.size()>3) {
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"set_outline",closest_outline,poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"set_outline",closest_outline,poly);
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ } else {
+
+ undo_redo->create_action(TTR("Remove Poly And Point"));
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"add_outline_at_index",poly,closest_outline);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"remove_outline",closest_outline);
+ undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ }
+ return true;
+ }
+ }
+
+
+
+ } break;
+ }
+
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ }
+
+ } break;
+ }
+
+ return false;
+}
+void NavigationPolygonEditor::_canvas_draw() {
+
+ if (!node)
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+ if (node->get_navigation_polygon().is_null())
+ return;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
+
+
+
+ for(int j=-1;j<node->get_navigation_polygon()->get_outline_count();j++) {
+ Vector<Vector2> poly;
+
+ if (wip_active && j==edited_outline) {
+ poly=wip;
+ } else {
+ if (j==-1)
+ continue;
+ poly = Variant(node->get_navigation_polygon()->get_outline(j));
+ }
+
+ for(int i=0;i<poly.size();i++) {
+
+
+ Vector2 p,p2;
+ p = (j==edited_outline && i==edited_point) ? edited_point_pos : poly[i];
+ if (j==edited_outline && ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point)))
+ p2=edited_point_pos;
+ else
+ p2 = poly[(i+1)%poly.size()];
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ Color col=Color(1,0.3,0.1,0.8);
+ vpc->draw_line(point,next_point,col,2);
+ vpc->draw_texture(handle,point-handle->get_size()*0.5);
+ }
+ }
+}
+
+
+
+void NavigationPolygonEditor::edit(Node *p_collision_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton();
+ }
+
+ if (p_collision_polygon) {
+
+ node=p_collision_polygon->cast_to<NavigationPolygonInstance>();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+ canvas_item_editor->get_viewport_control()->update();
+
+ } else {
+ node=NULL;
+
+ if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
+
+ }
+
+}
+
+void NavigationPolygonEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_menu_option"),&NavigationPolygonEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_canvas_draw"),&NavigationPolygonEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&NavigationPolygonEditor::_node_removed);
+ ClassDB::bind_method(D_METHOD("_create_nav"),&NavigationPolygonEditor::_create_nav);
+
+}
+
+NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) {
+ node=NULL;
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ add_child( memnew( VSeparator ));
+ button_create = memnew( ToolButton );
+ add_child(button_create);
+ button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+ button_create->set_tooltip(TTR("Create a new polygon from scratch."));
+
+ button_edit = memnew( ToolButton );
+ add_child(button_edit);
+ button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip(TTR("Edit existing polygon:")+"\n"+TTR("LMB: Move Point.")+"\n"+TTR("Ctrl+LMB: Split Segment.")+"\n"+TTR("RMB: Erase Point."));
+ create_nav = memnew( ConfirmationDialog );
+ add_child(create_nav);
+ create_nav->get_ok()->set_text(TTR("Create"));
+
+
+ //add_constant_override("separation",0);
+
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+#endif
+
+ mode = MODE_EDIT;
+ wip_active=false;
+ edited_outline=-1;
+
+}
+
+
+void NavigationPolygonEditorPlugin::edit(Object *p_object) {
+
+ collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool NavigationPolygonEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("NavigationPolygonInstance");
+}
+
+void NavigationPolygonEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ collision_polygon_editor->show();
+ } else {
+
+ collision_polygon_editor->hide();
+ collision_polygon_editor->edit(NULL);
+ }
+
+}
+
+NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ collision_polygon_editor = memnew( NavigationPolygonEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+ collision_polygon_editor->hide();
+
+
+
+}
+
+
+NavigationPolygonEditorPlugin::~NavigationPolygonEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h
new file mode 100644
index 0000000000..0d5e67e352
--- /dev/null
+++ b/editor/plugins/navigation_polygon_editor_plugin.h
@@ -0,0 +1,118 @@
+/*************************************************************************/
+/* navigation_polygon_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 NAVIGATIONPOLYGONEDITORPLUGIN_H
+#define NAVIGATIONPOLYGONEDITORPLUGIN_H
+
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/navigation_polygon.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class NavigationPolygonEditor : public HBoxContainer {
+
+ GDCLASS(NavigationPolygonEditor, HBoxContainer );
+
+ UndoRedo *undo_redo;
+ enum Mode {
+
+ MODE_CREATE,
+ MODE_EDIT,
+
+ };
+
+ Mode mode;
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+
+ ConfirmationDialog *create_nav;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ NavigationPolygonInstance *node;
+ MenuButton *options;
+
+ int edited_outline;
+ int edited_point;
+ Vector2 edited_point_pos;
+ PoolVector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+
+
+ void _wip_close();
+ void _canvas_draw();
+ void _create_nav();
+
+ void _menu_option(int p_option);
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node *p_collision_polygon);
+ NavigationPolygonEditor(EditorNode *p_editor);
+};
+
+class NavigationPolygonEditorPlugin : public EditorPlugin {
+
+ GDCLASS( NavigationPolygonEditorPlugin, EditorPlugin );
+
+ NavigationPolygonEditor *collision_polygon_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+
+ virtual String get_name() const { return "NavigationPolygonInstance"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_node);
+ virtual bool handles(Object *p_node) const;
+ virtual void make_visible(bool p_visible);
+
+ NavigationPolygonEditorPlugin(EditorNode *p_node);
+ ~NavigationPolygonEditorPlugin();
+
+};
+
+
+#endif // NAVIGATIONPOLYGONEDITORPLUGIN_H
diff --git a/editor/plugins/particles_2d_editor_plugin.cpp b/editor/plugins/particles_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..1efdbe9e68
--- /dev/null
+++ b/editor/plugins/particles_2d_editor_plugin.cpp
@@ -0,0 +1,199 @@
+/*************************************************************************/
+/* particles_2d_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "particles_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "io/image_loader.h"
+#include "scene/gui/separator.h"
+
+void Particles2DEditorPlugin::edit(Object *p_object) {
+
+ if (p_object) {
+ particles=p_object->cast_to<Particles2D>();
+ } else {
+ particles=NULL;
+ }
+}
+
+bool Particles2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Particles2D");
+}
+
+void Particles2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ toolbar->show();
+ } else {
+
+ toolbar->hide();
+ }
+
+}
+
+void Particles2DEditorPlugin::_file_selected(const String& p_file) {
+
+ print_line("file: "+p_file);
+
+ int epc=epoints->get_value();
+
+ Image img;
+ Error err = ImageLoader::load_image(p_file,&img);
+ ERR_EXPLAIN(TTR("Error loading image:")+" "+p_file);
+ ERR_FAIL_COND(err!=OK);
+
+ img.convert(Image::FORMAT_LA8);
+ ERR_FAIL_COND(img.get_format()!=Image::FORMAT_LA8);
+ Size2i s = Size2(img.get_width(),img.get_height());
+ ERR_FAIL_COND(s.width==0 || s.height==0);
+
+ PoolVector<uint8_t> data = img.get_data();
+ PoolVector<uint8_t>::Read r = data.read();
+
+ Vector<Point2i> valid_positions;
+ valid_positions.resize(s.width*s.height);
+ int vpc=0;
+
+
+ for(int i=0;i<s.width*s.height;i++) {
+
+ uint8_t a = r[i*2+1];
+ if (a>128) {
+ valid_positions[vpc++]=Point2i(i%s.width,i/s.width);
+ }
+ }
+
+ valid_positions.resize(vpc);
+
+ ERR_EXPLAIN(TTR("No pixels with transparency > 128 in image.."));
+ ERR_FAIL_COND(valid_positions.size()==0);
+
+ PoolVector<Point2> epoints;
+ epoints.resize(epc);
+ PoolVector<Point2>::Write w = epoints.write();
+
+ Size2 extents = Size2(img.get_width()*0.5,img.get_height()*0.5);
+
+ for(int i=0;i<epc;i++) {
+
+ Point2 p = valid_positions[Math::rand()%vpc];
+ p-=s/2;
+ w[i]=p/extents;
+ }
+
+ w = PoolVector<Point2>::Write();
+
+ undo_redo->create_action(TTR("Set Emission Mask"));
+ undo_redo->add_do_method(particles,"set_emission_points",epoints);
+ undo_redo->add_do_method(particles,"set_emission_half_extents",extents);
+ undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points());
+ undo_redo->add_undo_method(particles,"set_emission_half_extents",particles->get_emission_half_extents());
+ undo_redo->commit_action();
+
+}
+
+void Particles2DEditorPlugin::_menu_callback(int p_idx) {
+
+ switch(p_idx) {
+ case MENU_LOAD_EMISSION_MASK: {
+
+
+ file->popup_centered_ratio();
+
+ } break;
+ case MENU_CLEAR_EMISSION_MASK: {
+
+ undo_redo->create_action(TTR("Clear Emission Mask"));
+ undo_redo->add_do_method(particles,"set_emission_points",PoolVector<Vector2>());
+ undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points());
+ undo_redo->commit_action();
+ } break;
+ }
+
+}
+
+
+void Particles2DEditorPlugin::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ menu->get_popup()->connect("id_pressed",this,"_menu_callback");
+ menu->set_icon(menu->get_popup()->get_icon("Particles2D","EditorIcons"));
+ file->connect("file_selected",this,"_file_selected");
+ }
+}
+
+void Particles2DEditorPlugin::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_menu_callback"),&Particles2DEditorPlugin::_menu_callback);
+ ClassDB::bind_method(D_METHOD("_file_selected"),&Particles2DEditorPlugin::_file_selected);
+}
+
+
+
+Particles2DEditorPlugin::Particles2DEditorPlugin(EditorNode *p_node) {
+
+ particles=NULL;
+ editor=p_node;
+ undo_redo=editor->get_undo_redo();
+
+ toolbar = memnew( HBoxContainer );
+ add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, toolbar);
+ toolbar->hide();
+
+ toolbar->add_child( memnew( VSeparator ) );
+
+ menu = memnew( MenuButton );
+ menu->get_popup()->add_item(TTR("Load Emission Mask"),MENU_LOAD_EMISSION_MASK);
+ menu->get_popup()->add_item(TTR("Clear Emission Mask"),MENU_CLEAR_EMISSION_MASK);
+ menu->set_text("Particles");
+ toolbar->add_child(menu);
+
+ file = memnew( EditorFileDialog );
+ List<String> ext;
+ ImageLoader::get_recognized_extensions(&ext);
+ for(List<String>::Element *E=ext.front();E;E=E->next()) {
+ file->add_filter("*."+E->get()+"; "+E->get().to_upper());
+ }
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ toolbar->add_child(file);
+
+ epoints = memnew( SpinBox );
+ epoints->set_min(1);
+ epoints->set_max(8192);
+ epoints->set_step(1);
+ epoints->set_value(512);
+ file->get_vbox()->add_margin_child(TTR("Generated Point Count:"),epoints);
+}
+
+Particles2DEditorPlugin::~Particles2DEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/particles_2d_editor_plugin.h b/editor/plugins/particles_2d_editor_plugin.h
new file mode 100644
index 0000000000..ea71c739f3
--- /dev/null
+++ b/editor/plugins/particles_2d_editor_plugin.h
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* particles_2d_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PARTICLES_2D_EDITOR_PLUGIN_H
+#define PARTICLES_2D_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/collision_polygon_2d.h"
+
+#include "scene/gui/box_container.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/2d/particles_2d.h"
+
+class Particles2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS( Particles2DEditorPlugin, EditorPlugin );
+
+ enum {
+
+ MENU_LOAD_EMISSION_MASK,
+ MENU_CLEAR_EMISSION_MASK
+ };
+
+ Particles2D *particles;
+
+ EditorFileDialog *file;
+ EditorNode *editor;
+
+ HBoxContainer *toolbar;
+ MenuButton *menu;
+
+ SpinBox *epoints;
+
+ UndoRedo *undo_redo;
+ void _file_selected(const String& p_file);
+ void _menu_callback(int p_idx);
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+
+
+ virtual String get_name() const { return "Particles2D"; }
+ 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);
+
+ Particles2DEditorPlugin(EditorNode *p_node);
+ ~Particles2DEditorPlugin();
+
+};
+
+
+#endif // PARTICLES_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp
new file mode 100644
index 0000000000..4ce1f5eb54
--- /dev/null
+++ b/editor/plugins/particles_editor_plugin.cpp
@@ -0,0 +1,461 @@
+/*************************************************************************/
+/* particles_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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. */
+/*************************************************************************/
+
+#if 0
+#include "particles_editor_plugin.h"
+#include "io/resource_loader.h"
+#include "servers/visual/particle_system_sw.h"
+#include "editor/plugins/spatial_editor_plugin.h"
+
+
+void ParticlesEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ }
+
+}
+
+
+void ParticlesEditor::_resource_seleted(const String& p_res) {
+
+ //print_line("selected resource path: "+p_res);
+}
+
+void ParticlesEditor::_node_selected(const NodePath& p_path){
+
+
+ Node *sel = get_node(p_path);
+ if (!sel)
+ return;
+
+ VisualInstance *vi = sel->cast_to<VisualInstance>();
+ if (!vi) {
+
+ err_dialog->set_text(TTR("Node does not contain geometry."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ geometry = vi->get_faces(VisualInstance::FACES_SOLID);
+
+ if (geometry.size()==0) {
+
+ err_dialog->set_text(TTR("Node does not contain geometry (faces)."));
+ err_dialog->popup_centered_minsize();
+ return;
+
+ }
+
+ Transform geom_xform = node->get_global_transform().affine_inverse() * vi->get_global_transform();
+
+ int gc = geometry.size();
+ PoolVector<Face3>::Write w = geometry.write();
+
+
+ for(int i=0;i<gc;i++) {
+ for(int j=0;j<3;j++) {
+ w[i].vertex[j] = geom_xform.xform( w[i].vertex[j] );
+ }
+ }
+
+
+ w = PoolVector<Face3>::Write();
+
+ emission_dialog->popup_centered(Size2(300,130));
+}
+
+
+/*
+
+void ParticlesEditor::_populate() {
+
+ if(!node)
+ return;
+
+
+ if (node->get_particles().is_null())
+ return;
+
+ node->get_particles()->set_instance_count(populate_amount->get_text().to_int());
+ node->populate_parent(populate_rotate_random->get_val(),populate_tilt_random->get_val(),populate_scale_random->get_text().to_double(),populate_scale->get_text().to_double());
+
+}
+*/
+
+void ParticlesEditor::_notification(int p_notification) {
+
+ if (p_notification==NOTIFICATION_ENTER_TREE) {
+ options->set_icon(options->get_popup()->get_icon("Particles","EditorIcons"));
+
+ }
+}
+
+
+void ParticlesEditor::_menu_option(int p_option) {
+
+
+ switch(p_option) {
+
+ case MENU_OPTION_GENERATE_AABB: {
+
+ Transform globalizer = node->get_global_transform();
+ ParticleSystemSW pssw;
+ for(int i=0;i<VS::PARTICLE_VAR_MAX;i++) {
+
+ pssw.particle_vars[i]=node->get_variable((Particles::Variable)i);
+ pssw.particle_randomness[i]=node->get_randomness((Particles::Variable)i);
+ }
+
+ pssw.emission_half_extents=node->get_emission_half_extents();
+ pssw.emission_points=node->get_emission_points();
+ pssw.emission_base_velocity=node->get_emission_base_velocity();
+ pssw.amount=node->get_amount();
+ pssw.gravity_normal=node->get_gravity_normal();
+ pssw.emitting=true;
+ pssw.height_from_velocity=node->has_height_from_velocity();
+ pssw.color_phase_count=1;
+
+
+ ParticleSystemProcessSW pp;
+ float delta=0.01;
+ float lifetime=pssw.particle_vars[VS::PARTICLE_LIFETIME];
+
+
+ Transform localizer = globalizer.affine_inverse();
+ AABB aabb;
+ for(float t=0;t<lifetime;t+=delta) {
+
+ pp.process(&pssw,globalizer,delta);
+ for(int i=0;i<pp.particle_data.size();i++) {
+
+ Vector3 p = localizer.xform(pp.particle_data[i].pos);
+
+ if (t==0 && i==0)
+ aabb.pos=p;
+ else
+ aabb.expand_to(p);
+ }
+ }
+
+ aabb.grow_by( aabb.get_longest_axis_size()*0.2);
+
+ node->set_visibility_aabb(aabb);
+
+
+ } break;
+ case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: {
+
+
+ emission_file_dialog->popup_centered_ratio();
+
+ } break;
+
+ case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: {
+/*
+ Node *root = get_scene()->get_root_node();
+ ERR_FAIL_COND(!root);
+ EditorNode *en = root->cast_to<EditorNode>();
+ ERR_FAIL_COND(!en);
+ Node * node = en->get_edited_scene();
+*/
+ emission_tree_dialog->popup_centered_ratio();
+
+ } break;
+ }
+}
+
+
+void ParticlesEditor::edit(Particles *p_particles) {
+
+ node=p_particles;
+
+}
+
+void ParticlesEditor::_generate_emission_points() {
+
+ /// hacer codigo aca
+ PoolVector<Vector3> points;
+
+ if (emission_fill->get_selected()==0) {
+
+ float area_accum=0;
+ Map<float,int> triangle_area_map;
+ print_line("geometry size: "+itos(geometry.size()));
+
+ for(int i=0;i<geometry.size();i++) {
+
+ float area = geometry[i].get_area();
+ if (area<CMP_EPSILON)
+ continue;
+ triangle_area_map[area_accum]=i;
+ area_accum+=area;
+ }
+
+ if (!triangle_area_map.size() || area_accum==0) {
+
+ err_dialog->set_text(TTR("Faces contain no area!"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ int emissor_count=emission_amount->get_val();
+
+ for(int i=0;i<emissor_count;i++) {
+
+ float areapos = Math::random(0,area_accum);
+
+ Map<float,int>::Element *E = triangle_area_map.find_closest(areapos);
+ ERR_FAIL_COND(!E)
+ int index = E->get();
+ ERR_FAIL_INDEX(index,geometry.size());
+
+ // ok FINALLY get face
+ Face3 face = geometry[index];
+ //now compute some position inside the face...
+
+ Vector3 pos = face.get_random_point_inside();
+
+ points.push_back(pos);
+ }
+ } else {
+
+ int gcount = geometry.size();
+
+ if (gcount==0) {
+
+ err_dialog->set_text(TTR("No faces!"));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+
+ PoolVector<Face3>::Read r = geometry.read();
+
+ AABB aabb;
+
+ for(int i=0;i<gcount;i++) {
+
+ for(int j=0;j<3;j++) {
+
+ if (i==0 && j==0)
+ aabb.pos=r[i].vertex[j];
+ else
+ aabb.expand_to(r[i].vertex[j]);
+ }
+ }
+
+ int emissor_count=emission_amount->get_val();
+
+ for(int i=0;i<emissor_count;i++) {
+
+ int attempts=5;
+
+ for(int j=0;j<attempts;j++) {
+
+ Vector3 dir;
+ dir[Math::rand()%3]=1.0;
+ Vector3 ofs = Vector3(1,1,1)-dir;
+ ofs=(Vector3(1,1,1)-dir)*Vector3(Math::randf(),Math::randf(),Math::randf())*aabb.size;
+ ofs+=aabb.pos;
+
+ Vector3 ofsv = ofs + aabb.size * dir;
+
+ //space it a little
+ ofs -= dir;
+ ofsv += dir;
+
+ float max=-1e7,min=1e7;
+
+ for(int k=0;k<gcount;k++) {
+
+ const Face3& f3 = r[k];
+
+ Vector3 res;
+ if (f3.intersects_segment(ofs,ofsv,&res)) {
+
+ res-=ofs;
+ float d = dir.dot(res);
+
+ if (d<min)
+ min=d;
+ if (d>max)
+ max=d;
+
+ }
+ }
+
+
+ if (max<min)
+ continue; //lost attempt
+
+ float val = min + (max-min)*Math::randf();
+
+ Vector3 point = ofs + dir * val;
+
+ points.push_back(point);
+ break;
+ }
+ }
+ }
+
+ //print_line("point count: "+itos(points.size()));
+ node->set_emission_points(points);
+
+}
+
+void ParticlesEditor::_bind_methods() {
+
+ ClassDB::bind_method("_menu_option",&ParticlesEditor::_menu_option);
+ ClassDB::bind_method("_resource_seleted",&ParticlesEditor::_resource_seleted);
+ ClassDB::bind_method("_node_selected",&ParticlesEditor::_node_selected);
+ ClassDB::bind_method("_generate_emission_points",&ParticlesEditor::_generate_emission_points);
+
+ //ClassDB::bind_method("_populate",&ParticlesEditor::_populate);
+
+}
+
+ParticlesEditor::ParticlesEditor() {
+
+ particles_editor_hb = memnew ( HBoxContainer );
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb);
+ options = memnew( MenuButton );
+ particles_editor_hb->add_child(options);
+ particles_editor_hb->hide();
+
+ options->set_text("Particles");
+ options->get_popup()->add_item(TTR("Generate AABB"),MENU_OPTION_GENERATE_AABB);
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item(TTR("Create Emitter From Mesh"),MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH);
+ options->get_popup()->add_item(TTR("Create Emitter From Node"),MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
+ options->get_popup()->add_item(TTR("Clear Emitter"),MENU_OPTION_CLEAR_EMISSION_VOLUME);
+
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+
+ emission_dialog = memnew( ConfirmationDialog );
+ emission_dialog->set_title(TTR("Create Emitter"));
+ add_child(emission_dialog);
+ Label *l = memnew(Label);
+ l->set_pos(Point2(5,5));
+ l->set_text(TTR("Emission Positions:"));
+ emission_dialog->add_child(l);
+
+
+ emission_amount = memnew( SpinBox );
+ emission_amount->set_anchor(MARGIN_RIGHT,ANCHOR_END);
+ emission_amount->set_begin( Point2(20,23));
+ emission_amount->set_end( Point2(5,25));
+ emission_amount->set_min(1);
+ emission_amount->set_max(65536);
+ emission_amount->set_val(512);
+ emission_dialog->add_child(emission_amount);
+ emission_dialog->get_ok()->set_text(TTR("Create"));
+ emission_dialog->connect("confirmed",this,"_generate_emission_points");
+
+ l = memnew(Label);
+ l->set_pos(Point2(5,50));
+ l->set_text(TTR("Emission Fill:"));
+ emission_dialog->add_child(l);
+
+ emission_fill = memnew( OptionButton );
+ emission_fill->set_anchor(MARGIN_RIGHT,ANCHOR_END);
+ emission_fill->set_begin( Point2(20,70));
+ emission_fill->set_end( Point2(5,75));
+ emission_fill->add_item(TTR("Surface"));
+ emission_fill->add_item(TTR("Volume"));
+ emission_dialog->add_child(emission_fill);
+
+ err_dialog = memnew( ConfirmationDialog );
+ //err_dialog->get_cancel()->hide();
+ add_child(err_dialog);
+
+
+ emission_file_dialog = memnew( EditorFileDialog );
+ add_child(emission_file_dialog);
+ emission_file_dialog->connect("file_selected",this,"_resource_seleted");
+ emission_tree_dialog = memnew( SceneTreeDialog );
+ add_child(emission_tree_dialog);
+ emission_tree_dialog->connect("selected",this,"_node_selected");
+
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Mesh",&extensions);
+
+ emission_file_dialog->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ emission_file_dialog->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+ emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+
+ //options->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
+ //options->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
+
+}
+
+
+void ParticlesEditorPlugin::edit(Object *p_object) {
+
+ particles_editor->edit(p_object->cast_to<Particles>());
+}
+
+bool ParticlesEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("Particles");
+}
+
+void ParticlesEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ particles_editor->show();
+ particles_editor->particles_editor_hb->show();
+ } else {
+ particles_editor->particles_editor_hb->hide();
+ particles_editor->hide();
+ particles_editor->edit(NULL);
+ }
+
+}
+
+ParticlesEditorPlugin::ParticlesEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ particles_editor = memnew( ParticlesEditor );
+ editor->get_viewport()->add_child(particles_editor);
+
+ particles_editor->hide();
+}
+
+
+ParticlesEditorPlugin::~ParticlesEditorPlugin()
+{
+}
+
+
+#endif
diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h
new file mode 100644
index 0000000000..06134ddef2
--- /dev/null
+++ b/editor/plugins/particles_editor_plugin.h
@@ -0,0 +1,116 @@
+/*************************************************************************/
+/* particles_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PARTICLES_EDITOR_PLUGIN_H
+#define PARTICLES_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/3d/particles.h"
+#include "scene/gui/spin_box.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+#if 0
+class ParticlesEditor : public Control {
+
+ GDCLASS(ParticlesEditor, Control );
+
+ Panel *panel;
+ MenuButton *options;
+ HBoxContainer *particles_editor_hb;
+ Particles *node;
+
+
+ EditorFileDialog *emission_file_dialog;
+ SceneTreeDialog *emission_tree_dialog;
+
+ ConfirmationDialog *err_dialog;
+
+ ConfirmationDialog *emission_dialog;
+ SpinBox *emission_amount;
+ OptionButton *emission_fill;
+
+
+
+
+ enum Menu {
+
+ MENU_OPTION_GENERATE_AABB,
+ MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE,
+ MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH,
+ MENU_OPTION_CLEAR_EMISSION_VOLUME,
+
+ };
+
+ PoolVector<Face3> geometry;
+
+ void _generate_emission_points();
+ void _resource_seleted(const String& p_res);
+ void _node_selected(const NodePath& p_path);
+
+ void _menu_option(int);
+
+ void _populate();
+
+friend class ParticlesEditorPlugin;
+
+protected:
+
+ void _notification(int p_notification);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(Particles *p_particles);
+ ParticlesEditor();
+};
+
+class ParticlesEditorPlugin : public EditorPlugin {
+
+ GDCLASS( ParticlesEditorPlugin, EditorPlugin );
+
+ ParticlesEditor *particles_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "Particles"; }
+ 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);
+
+ ParticlesEditorPlugin(EditorNode *p_node);
+ ~ParticlesEditorPlugin();
+
+};
+
+#endif // PARTICLES_EDITOR_PLUGIN_H
+#endif
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..00b026e25b
--- /dev/null
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -0,0 +1,718 @@
+/*************************************************************************/
+/* path_2d_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "path_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+#include "os/keyboard.h"
+void Path2DEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ //button_create->set_icon( get_icon("Edit","EditorIcons"));
+ //button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ //set_pressed_button(button_edit);
+ //button_edit->set_pressed(true);
+
+
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void Path2DEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ }
+
+}
+
+
+bool Path2DEditor::forward_gui_input(const InputEvent& p_event) {
+
+ if (!node)
+ return false;
+
+ if (!node->is_visible_in_tree())
+ return false;
+
+ if (!node->get_curve().is_valid())
+ return false;
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = !mb.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
+ : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
+
+
+
+ // Test move point!!
+
+ if ( mb.pressed && action==ACTION_NONE ) {
+
+ Ref<Curve2D> curve = node->get_curve();
+
+ for(int i=0;i<curve->get_point_count();i++) {
+
+ bool pointunder=false;
+
+ {
+ Point2 p = xform.xform( curve->get_point_pos(i) );
+ if (gpoint.distance_to(p) < grab_treshold ) {
+
+ if (mb.button_index==BUTTON_LEFT && !mb.mod.shift && mode==MODE_EDIT) {
+
+ action=ACTION_MOVING_POINT;
+ action_point=i;
+ moving_from=curve->get_point_pos(i);
+ moving_screen_from=gpoint;
+ return true;
+ } else if ((mb.button_index==BUTTON_RIGHT && mode==MODE_EDIT) || (mb.button_index==BUTTON_LEFT && mode==MODE_DELETE)) {
+
+ undo_redo->create_action(TTR("Remove Point from Curve"));
+ undo_redo->add_do_method(curve.ptr(),"remove_point",i);
+ undo_redo->add_undo_method(curve.ptr(),"add_point",curve->get_point_pos(i),curve->get_point_in(i),curve->get_point_out(i),i);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ } else
+ pointunder=true;
+ }
+ }
+
+ if (mb.button_index==BUTTON_LEFT && i<(curve->get_point_count()-1)) {
+ Point2 p = xform.xform( curve->get_point_pos(i)+curve->get_point_out(i) );
+ if (gpoint.distance_to(p) < grab_treshold && (mode == MODE_EDIT || mode==MODE_EDIT_CURVE) ) {
+
+ action=ACTION_MOVING_OUT;
+ action_point=i;
+ moving_from=curve->get_point_out(i);
+ moving_screen_from=gpoint;
+ return true;
+ }
+ }
+
+ if (mb.button_index==BUTTON_LEFT && i>0) {
+ Point2 p = xform.xform( curve->get_point_pos(i)+curve->get_point_in(i) );
+ if (gpoint.distance_to(p) < grab_treshold && (mode == MODE_EDIT || mode==MODE_EDIT_CURVE)) {
+
+ action=ACTION_MOVING_IN;
+ action_point=i;
+ moving_from=curve->get_point_in(i);
+ moving_screen_from=gpoint;
+ return true;
+ }
+ }
+
+ if (pointunder)
+ return true;
+
+ }
+
+ }
+
+ // Test add point in empty space!
+
+ if ( mb.pressed && mb.button_index==BUTTON_LEFT && ((mb.mod.command && mode == MODE_EDIT) || mode == MODE_CREATE)) {
+
+ Ref<Curve2D> curve = node->get_curve();
+
+ undo_redo->create_action(TTR("Add Point to Curve"));
+ undo_redo->add_do_method(curve.ptr(),"add_point",cpoint);
+ undo_redo->add_undo_method(curve.ptr(),"remove_point",curve->get_point_count());
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ action=ACTION_MOVING_POINT;
+ action_point=curve->get_point_count()-1;
+ moving_from=curve->get_point_pos(action_point);
+ moving_screen_from=gpoint;
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ return true;
+ }
+
+ if ( !mb.pressed && mb.button_index==BUTTON_LEFT && action!=ACTION_NONE) {
+
+
+ Ref<Curve2D> curve = node->get_curve();
+
+ Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
+ switch(action) {
+
+ case ACTION_MOVING_POINT: {
+
+
+ undo_redo->create_action(TTR("Move Point in Curve"));
+ undo_redo->add_do_method(curve.ptr(),"set_point_pos",action_point,cpoint);
+ undo_redo->add_undo_method(curve.ptr(),"set_point_pos",action_point,moving_from);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ } break;
+ case ACTION_MOVING_IN: {
+
+ undo_redo->create_action(TTR("Move In-Control in Curve"));
+ undo_redo->add_do_method(curve.ptr(),"set_point_in",action_point,new_pos);
+ undo_redo->add_undo_method(curve.ptr(),"set_point_in",action_point,moving_from);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ } break;
+ case ACTION_MOVING_OUT: {
+
+ undo_redo->create_action(TTR("Move Out-Control in Curve"));
+ undo_redo->add_do_method(curve.ptr(),"set_point_out",action_point,new_pos);
+ undo_redo->add_undo_method(curve.ptr(),"set_point_out",action_point,moving_from);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ } break;
+
+ }
+
+ action=ACTION_NONE;
+
+ return true;
+ }
+
+
+#if 0
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( canvas_item_editor->snap_point(cpoint) );
+ wip_active=true;
+ edited_point_pos=canvas_item_editor->snap_point(cpoint);
+ canvas_item_editor->update();
+ edited_point=1;
+ return true;
+ } else {
+
+ if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close();
+
+ return true;
+ } else {
+
+ wip.push_back( canvas_item_editor->snap_point(cpoint) );
+ edited_point=wip.size();
+ canvas_item_editor->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close();
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ if (poly.size() < 3) {
+
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.push_back(cpoint);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ //search edges
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 points[2] ={ xform.xform(poly[i]),
+ xform.xform(poly[(i+1)%poly.size()]) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+ if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)));
+ edited_point=closest_idx+1;
+ edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos));
+ node->set_polygon(poly);
+ canvas_item_editor->update();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ edited_point=closest_idx;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly[edited_point]=edited_point_pos;
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]);
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ }
+
+
+
+ } break;
+ }
+
+
+#endif
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+
+ if ( action!=ACTION_NONE) {
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ Vector2 cpoint = !mm.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
+ : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
+
+ Ref<Curve2D> curve = node->get_curve();
+
+ Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
+
+ switch(action) {
+
+ case ACTION_MOVING_POINT: {
+
+ curve->set_point_pos(action_point,cpoint);
+ } break;
+ case ACTION_MOVING_IN: {
+
+ curve->set_point_in(action_point,new_pos);
+
+ } break;
+ case ACTION_MOVING_OUT: {
+
+ curve->set_point_out(action_point,new_pos);
+
+ } break;
+ }
+
+
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+
+#if 0
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+
+ Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint));
+ canvas_item_editor->update();
+
+ }
+#endif
+ } break;
+ }
+
+ return false;
+}
+void Path2DEditor::_canvas_draw() {
+
+ if (!node)
+ return ;
+
+ if (!node->is_visible_in_tree())
+ return;
+
+ if (!node->get_curve().is_valid())
+ return ;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
+ Size2 handle_size = handle->get_size();
+
+ Ref<Curve2D> curve = node->get_curve();
+
+ int len = curve->get_point_count();
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+
+ for(int i=0;i<len;i++) {
+
+
+ Vector2 point = xform.xform(curve->get_point_pos(i));
+ vpc->draw_texture_rect(handle,Rect2(point-handle_size*0.5,handle_size),false,Color(1,1,1,1));
+
+ if (i<len-1) {
+ Vector2 pointout = xform.xform(curve->get_point_pos(i)+curve->get_point_out(i));
+ vpc->draw_line(point,pointout,Color(0.5,0.5,1.0,0.8),1.0);
+ vpc->draw_texture_rect(handle, Rect2(pointout-handle_size*0.5,handle_size),false,Color(1,0.5,1,0.3));
+ }
+
+ if (i>0) {
+ Vector2 pointin = xform.xform(curve->get_point_pos(i)+curve->get_point_in(i));
+ vpc->draw_line(point,pointin,Color(0.5,0.5,1.0,0.8),1.0);
+ vpc->draw_texture_rect(handle, Rect2(pointin-handle_size*0.5,handle_size),false,Color(1,0.5,1,0.3));
+ }
+
+ }
+
+}
+
+void Path2DEditor::_node_visibility_changed() {
+ if (!node)
+ return;
+
+ canvas_item_editor->get_viewport_control()->update();
+}
+
+void Path2DEditor::edit(Node *p_path2d) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton();
+ }
+
+ if (p_path2d) {
+
+ node=p_path2d->cast_to<Path2D>();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+ 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"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
+
+ // node may have been deleted at this point
+ if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed"))
+ node->disconnect("visibility_changed", this, "_node_visibility_changed");
+ node=NULL;
+ }
+
+}
+
+void Path2DEditor::_bind_methods() {
+
+ //ClassDB::bind_method(D_METHOD("_menu_option"),&Path2DEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_canvas_draw"),&Path2DEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_node_visibility_changed"),&Path2DEditor::_node_visibility_changed);
+ ClassDB::bind_method(D_METHOD("_mode_selected"),&Path2DEditor::_mode_selected);
+}
+
+void Path2DEditor::_mode_selected(int p_mode) {
+
+ if (p_mode==MODE_CREATE) {
+
+ curve_create->set_pressed(true);
+ curve_edit->set_pressed(false);
+ curve_edit_curve->set_pressed(false);
+ curve_del->set_pressed(false);
+ } else if (p_mode==MODE_EDIT) {
+
+ curve_create->set_pressed(false);
+ curve_edit->set_pressed(true);
+ curve_edit_curve->set_pressed(false);
+ curve_del->set_pressed(false);
+ } else if (p_mode==MODE_EDIT_CURVE) {
+
+ curve_create->set_pressed(false);
+ curve_edit->set_pressed(false);
+ curve_edit_curve->set_pressed(true);
+ curve_del->set_pressed(false);
+ } else if (p_mode==MODE_DELETE) {
+
+ curve_create->set_pressed(false);
+ curve_edit->set_pressed(false);
+ curve_edit_curve->set_pressed(false);
+ curve_del->set_pressed(true);
+ } else if (p_mode==ACTION_CLOSE) {
+
+ //?
+
+ if (!node->get_curve().is_valid())
+ return ;
+ if (node->get_curve()->get_point_count()<3)
+ return;
+
+ Vector2 begin = node->get_curve()->get_point_pos(0);
+ Vector2 end = node->get_curve()->get_point_pos( node->get_curve()->get_point_count() -1 );
+ if (begin.distance_to(end)<CMP_EPSILON)
+ return;
+
+ undo_redo->create_action(TTR("Remove Point from Curve"));
+ undo_redo->add_do_method(node->get_curve().ptr(),"add_point",begin);
+ undo_redo->add_undo_method(node->get_curve().ptr(),"remove_point",node->get_curve()->get_point_count());
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return;
+ }
+
+ mode=Mode(p_mode);
+
+}
+
+Path2DEditor::Path2DEditor(EditorNode *p_editor) {
+
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ mode=MODE_EDIT;
+
+ action=ACTION_NONE;
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+#endif
+
+ base_hb = memnew( HBoxContainer );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(base_hb);
+
+ sep = memnew( VSeparator);
+ base_hb->add_child(sep);
+ curve_edit = memnew( ToolButton );
+ curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit","EditorIcons"));
+ curve_edit->set_toggle_mode(true);
+ curve_edit->set_focus_mode(Control::FOCUS_NONE);
+ curve_edit->set_tooltip(TTR("Select Points")+"\n"+TTR("Shift+Drag: Select Control Points")+"\n"+keycode_get_string(KEY_MASK_CMD)+TTR("Click: Add Point")+"\n"+TTR("Right Click: Delete Point"));
+ curve_edit->connect("pressed",this,"_mode_selected",varray(MODE_EDIT));
+ base_hb->add_child(curve_edit);
+ curve_edit_curve = memnew( ToolButton );
+ curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCurve","EditorIcons"));
+ curve_edit_curve->set_toggle_mode(true);
+ curve_edit_curve->set_focus_mode(Control::FOCUS_NONE);
+ curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)"));
+ curve_edit_curve->connect("pressed",this,"_mode_selected",varray(MODE_EDIT_CURVE));
+ base_hb->add_child(curve_edit_curve);
+ curve_create = memnew( ToolButton );
+ curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate","EditorIcons"));
+ curve_create->set_toggle_mode(true);
+ curve_create->set_focus_mode(Control::FOCUS_NONE);
+ curve_create->set_tooltip(TTR("Add Point (in empty space)")+"\n"+TTR("Split Segment (in curve)"));
+ curve_create->connect("pressed",this,"_mode_selected",varray(MODE_CREATE));
+ base_hb->add_child(curve_create);
+ curve_del = memnew( ToolButton );
+ curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete","EditorIcons"));
+ curve_del->set_toggle_mode(true);
+ curve_del->set_focus_mode(Control::FOCUS_NONE);
+ curve_del->set_tooltip(TTR("Delete Point"));
+ curve_del->connect("pressed",this,"_mode_selected",varray(MODE_DELETE));
+ base_hb->add_child(curve_del);
+ curve_close = memnew( ToolButton );
+ curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveClose","EditorIcons"));
+ curve_close->set_focus_mode(Control::FOCUS_NONE);
+ curve_close->set_tooltip(TTR("Close Curve"));
+ curve_close->connect("pressed",this,"_mode_selected",varray(ACTION_CLOSE));
+ base_hb->add_child(curve_close);
+ base_hb->hide();
+
+
+
+ curve_edit->set_pressed(true);
+
+
+}
+
+
+void Path2DEditorPlugin::edit(Object *p_object) {
+
+ path2d_editor->edit(p_object->cast_to<Node>());
+}
+
+bool Path2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Path2D");
+}
+
+void Path2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ path2d_editor->show();
+ path2d_editor->base_hb->show();
+
+ } else {
+
+ path2d_editor->hide();
+ path2d_editor->base_hb->hide();
+ path2d_editor->edit(NULL);
+ }
+
+}
+
+Path2DEditorPlugin::Path2DEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ path2d_editor = memnew( Path2DEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(path2d_editor);
+ path2d_editor->hide();
+
+
+}
+
+
+Path2DEditorPlugin::~Path2DEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
new file mode 100644
index 0000000000..89f42d94cc
--- /dev/null
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -0,0 +1,126 @@
+/*************************************************************************/
+/* path_2d_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PATH_2D_EDITOR_PLUGIN_H
+#define PATH_2D_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/path_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class Path2DEditor : public HBoxContainer {
+
+ GDCLASS(Path2DEditor, HBoxContainer);
+
+ UndoRedo *undo_redo;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ Path2D *node;
+
+ HBoxContainer *base_hb;
+ Separator *sep;
+
+ enum Mode {
+ MODE_CREATE,
+ MODE_EDIT,
+ MODE_EDIT_CURVE,
+ MODE_DELETE,
+ ACTION_CLOSE
+ };
+
+ Mode mode;
+ ToolButton *curve_create;
+ ToolButton *curve_edit;
+ ToolButton *curve_edit_curve;
+ ToolButton *curve_del;
+ ToolButton *curve_close;
+
+ enum Action {
+
+ ACTION_NONE,
+ ACTION_MOVING_POINT,
+ ACTION_MOVING_IN,
+ ACTION_MOVING_OUT,
+ };
+
+
+ Action action;
+ int action_point;
+ Point2 moving_from;
+ Point2 moving_screen_from;
+
+ void _mode_selected(int p_mode);
+
+ void _canvas_draw();
+ void _node_visibility_changed();
+friend class Path2DEditorPlugin;
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node *p_path2d);
+ Path2DEditor(EditorNode *p_editor);
+};
+
+class Path2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS( Path2DEditorPlugin, EditorPlugin );
+
+ Path2DEditor *path2d_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return path2d_editor->forward_gui_input(p_event); }
+
+ virtual String get_name() const { return "Path2D"; }
+ 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);
+
+ Path2DEditorPlugin(EditorNode *p_node);
+ ~Path2DEditorPlugin();
+
+};
+
+
+
+#endif // PATH_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp
new file mode 100644
index 0000000000..a3df39fdaa
--- /dev/null
+++ b/editor/plugins/path_editor_plugin.cpp
@@ -0,0 +1,604 @@
+/*************************************************************************/
+/* path_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "path_editor_plugin.h"
+
+#include "spatial_editor_plugin.h"
+#include "scene/resources/curve.h"
+#include "os/keyboard.h"
+
+#if 0
+String PathSpatialGizmo::get_handle_name(int p_idx) const {
+
+ Ref<Curve3D> c = path->get_curve();
+ if (c.is_null())
+ return "";
+
+ if (p_idx<c->get_point_count()) {
+
+ return TTR("Curve Point #")+itos(p_idx);
+ }
+
+ p_idx=p_idx-c->get_point_count()+1;
+
+ int idx=p_idx/2;
+ int t=p_idx%2;
+ String n = TTR("Curve Point #")+itos(idx);
+ if (t==0)
+ n+=" In";
+ else
+ n+=" Out";
+
+ return n;
+
+
+}
+Variant PathSpatialGizmo::get_handle_value(int p_idx) const{
+
+ Ref<Curve3D> c = path->get_curve();
+ if (c.is_null())
+ return Variant();
+
+ if (p_idx<c->get_point_count()) {
+
+ original=c->get_point_pos(p_idx);
+ return original;
+ }
+
+ p_idx=p_idx-c->get_point_count()+1;
+
+ int idx=p_idx/2;
+ int t=p_idx%2;
+
+ Vector3 ofs;
+ if (t==0)
+ ofs=c->get_point_in(idx);
+ else
+ ofs= c->get_point_out(idx);
+
+ original=ofs+c->get_point_pos(idx);
+
+ return ofs;
+
+}
+void PathSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
+
+ Ref<Curve3D> c = path->get_curve();
+ if (c.is_null())
+ return;
+
+ Transform gt = path->get_global_transform();
+ Transform gi = gt.affine_inverse();
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ if (p_idx<c->get_point_count()) {
+
+ Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
+
+ Vector3 inters;
+
+ if (p.intersects_ray(ray_from,ray_dir,&inters)) {
+
+ if(SpatialEditor::get_singleton()->is_snap_enabled())
+ {
+ float snap = SpatialEditor::get_singleton()->get_translate_snap();
+ inters.snap(snap);
+ }
+
+ Vector3 local = gi.xform(inters);
+ c->set_point_pos(p_idx,local);
+ }
+
+ return;
+ }
+
+ p_idx=p_idx-c->get_point_count()+1;
+
+ int idx=p_idx/2;
+ int t=p_idx%2;
+
+ Vector3 base = c->get_point_pos(idx);
+
+ Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
+
+ Vector3 inters;
+
+ if (p.intersects_ray(ray_from,ray_dir,&inters)) {
+
+ Vector3 local = gi.xform(inters)-base;
+ if (t==0) {
+ c->set_point_in(idx,local);
+ } else {
+ c->set_point_out(idx,local);
+ }
+ }
+
+}
+
+void PathSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+
+ Ref<Curve3D> c = path->get_curve();
+ if (c.is_null())
+ return;
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+
+ if (p_idx<c->get_point_count()) {
+
+ if (p_cancel) {
+
+ c->set_point_pos(p_idx,p_restore);
+ return;
+ }
+ ur->create_action(TTR("Set Curve Point Pos"));
+ ur->add_do_method(c.ptr(),"set_point_pos",p_idx,c->get_point_pos(p_idx));
+ ur->add_undo_method(c.ptr(),"set_point_pos",p_idx,p_restore);
+ ur->commit_action();
+
+ return;
+ }
+
+ p_idx=p_idx-c->get_point_count()+1;
+
+ int idx=p_idx/2;
+ int t=p_idx%2;
+
+ Vector3 ofs;
+
+ if (p_cancel) {
+
+
+
+ return;
+ }
+
+
+
+ if (t==0) {
+
+ if (p_cancel) {
+
+ c->set_point_in(p_idx,p_restore);
+ return;
+ }
+ ur->create_action(TTR("Set Curve In Pos"));
+ ur->add_do_method(c.ptr(),"set_point_in",idx,c->get_point_in(idx));
+ ur->add_undo_method(c.ptr(),"set_point_in",idx,p_restore);
+ ur->commit_action();
+
+
+ } else {
+ if (p_cancel) {
+
+ c->set_point_out(idx,p_restore);
+ return;
+ }
+ ur->create_action(TTR("Set Curve Out Pos"));
+ ur->add_do_method(c.ptr(),"set_point_out",idx,c->get_point_out(idx));
+ ur->add_undo_method(c.ptr(),"set_point_out",idx,p_restore);
+ ur->commit_action();
+
+ }
+
+}
+
+
+void PathSpatialGizmo::redraw(){
+
+ clear();
+
+ Ref<Curve3D> c = path->get_curve();
+ if (c.is_null())
+ return;
+
+ Vector3Array v3a=c->tesselate();
+ //Vector3Array v3a=c->get_baked_points();
+
+ int v3s = v3a.size();
+ if (v3s==0)
+ return;
+ Vector<Vector3> v3p;
+ Vector3Array::Read r = v3a.read();
+
+ for(int i=0;i<v3s-1;i++) {
+
+ v3p.push_back(r[i]);
+ v3p.push_back(r[i+1]);
+ //v3p.push_back(r[i]);
+ //v3p.push_back(r[i]+Vector3(0,0.2,0));
+ }
+
+ add_lines(v3p,PathEditorPlugin::singleton->path_material);
+ add_collision_segments(v3p);
+
+ if (PathEditorPlugin::singleton->get_edited_path()==path) {
+ v3p.clear();
+ Vector<Vector3> handles;
+ Vector<Vector3> sec_handles;
+
+ for(int i=0;i<c->get_point_count();i++) {
+
+ Vector3 p = c->get_point_pos(i);
+ handles.push_back(p);
+ if (i>0) {
+ v3p.push_back(p);
+ v3p.push_back(p+c->get_point_in(i));
+ sec_handles.push_back(p+c->get_point_in(i));
+ }
+
+ if (i<c->get_point_count()-1) {
+ v3p.push_back(p);
+ v3p.push_back(p+c->get_point_out(i));
+ sec_handles.push_back(p+c->get_point_out(i));
+ }
+ }
+
+ add_lines(v3p,PathEditorPlugin::singleton->path_thin_material);
+ add_handles(handles);
+ add_handles(sec_handles,false,true);
+ }
+
+}
+
+PathSpatialGizmo::PathSpatialGizmo(Path* p_path){
+
+ path=p_path;
+ set_spatial_node(p_path);
+
+
+
+}
+
+Ref<SpatialEditorGizmo> PathEditorPlugin::create_spatial_gizmo(Spatial* p_spatial) {
+
+
+ if (p_spatial->cast_to<Path>()) {
+
+ return memnew( PathSpatialGizmo(p_spatial->cast_to<Path>()));
+ }
+
+ return Ref<SpatialEditorGizmo>();
+}
+
+bool PathEditorPlugin::forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) {
+
+ if (!path)
+ return false;
+ Ref<Curve3D> c=path->get_curve();
+ if (c.is_null())
+ return false;
+ Transform gt = path->get_global_transform();
+ Transform it = gt.affine_inverse();
+
+ static const int click_dist = 10; //should make global
+
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON) {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+ Point2 mbpos(mb.x,mb.y);
+
+ if (mb.pressed && mb.button_index==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) {
+ //click into curve, break it down
+ Vector3Array v3a = c->tesselate();
+ int idx=0;
+ int rc=v3a.size();
+ int closest_seg=-1;
+ Vector3 closest_seg_point;
+ float closest_d=1e20;
+
+ if (rc>=2) {
+ Vector3Array::Read r = v3a.read();
+
+ if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos)<click_dist)
+ return false; //nope, existing
+
+
+ for(int i=0;i<c->get_point_count()-1;i++) {
+ //find the offset and point index of the place to break up
+ int j=idx;
+ if (p_camera->unproject_position(gt.xform(c->get_point_pos(i+1))).distance_to(mbpos)<click_dist)
+ return false; //nope, existing
+
+
+ while(j<rc && c->get_point_pos(i+1)!=r[j]) {
+
+ Vector3 from =r[j];
+ Vector3 to =r[j+1];
+ real_t cdist = from.distance_to(to);
+ from=gt.xform(from);
+ to=gt.xform(to);
+ if (cdist>0) {
+ Vector2 s[2];
+ s[0] = p_camera->unproject_position(from);
+ s[1] = p_camera->unproject_position(to);
+ Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos,s);
+ float d = inters.distance_to(mbpos);
+
+ if (d<10 && d<closest_d) {
+
+
+ closest_d=d;
+ closest_seg=i;
+ Vector3 ray_from=p_camera->project_ray_origin(mbpos);
+ Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
+
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(ray_from,ray_from+ray_dir*4096,from,to,ra,rb);
+
+ closest_seg_point=it.xform(rb);
+ }
+
+ }
+ j++;
+
+ }
+ if (idx==j)
+ idx++; //force next
+ else
+ idx=j; //swap
+
+
+ if (j==rc)
+ break;
+ }
+ }
+
+ UndoRedo *ur = editor->get_undo_redo();
+ if (closest_seg!=-1) {
+ //subdivide
+
+ ur->create_action(TTR("Split Path"));
+ ur->add_do_method(c.ptr(),"add_point",closest_seg_point,Vector3(),Vector3(),closest_seg+1);
+ ur->add_undo_method(c.ptr(),"remove_point",closest_seg+1);
+ ur->commit_action();
+ return true;
+
+ } else {
+
+ Vector3 org;
+ if (c->get_point_count()==0)
+ org=path->get_transform().get_origin();
+ else
+ org=gt.xform(c->get_point_pos(c->get_point_count()));
+ Plane p(org,p_camera->get_transform().basis.get_axis(2));
+ Vector3 ray_from=p_camera->project_ray_origin(mbpos);
+ Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
+
+ Vector3 inters;
+ if (p.intersects_ray(ray_from,ray_dir,&inters)) {
+
+ ur->create_action(TTR("Add Point to Curve"));
+ ur->add_do_method(c.ptr(),"add_point",it.xform(inters),Vector3(),Vector3(),-1);
+ ur->add_undo_method(c.ptr(),"remove_point",c->get_point_count());
+ ur->commit_action();
+ return true;
+ }
+
+ //add new at pos
+ }
+
+ } else if (mb.pressed && ((mb.button_index==BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index==BUTTON_RIGHT && curve_edit->is_pressed()))) {
+
+ int erase_idx=-1;
+ for(int i=0;i<c->get_point_count();i++) {
+ //find the offset and point index of the place to break up
+ if (p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos)<click_dist) {
+
+ erase_idx=i;
+ break;
+ }
+ }
+
+ if (erase_idx!=-1) {
+
+ UndoRedo *ur = editor->get_undo_redo();
+ ur->create_action(TTR("Remove Path Point"));
+ ur->add_do_method(c.ptr(),"remove_point",erase_idx);
+ ur->add_undo_method(c.ptr(),"add_point",c->get_point_pos(erase_idx),c->get_point_in(erase_idx),c->get_point_out(erase_idx),erase_idx);
+ ur->commit_action();
+ return true;
+ }
+ }
+
+ }
+
+ return false;
+}
+
+
+void PathEditorPlugin::edit(Object *p_object) {
+
+ if (p_object) {
+ path=p_object->cast_to<Path>();
+ if (path) {
+
+ if (path->get_curve().is_valid()) {
+ path->get_curve()->emit_signal("changed");
+ }
+ }
+ } else {
+ Path *pre=path;
+ path=NULL;
+ if (pre) {
+ pre->get_curve()->emit_signal("changed");
+ }
+ }
+ //collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool PathEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_type("Path");
+}
+
+void PathEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ curve_create->show();
+ curve_edit->show();
+ curve_del->show();
+ curve_close->show();
+ sep->show();
+ } else {
+
+ curve_create->hide();
+ curve_edit->hide();
+ curve_del->hide();
+ curve_close->hide();
+ sep->hide();
+
+ {
+ Path *pre=path;
+ path=NULL;
+ if (pre && pre->get_curve().is_valid()) {
+ pre->get_curve()->emit_signal("changed");
+ }
+ }
+ }
+
+}
+
+void PathEditorPlugin::_mode_changed(int p_idx) {
+
+ curve_create->set_pressed(p_idx==0);
+ curve_edit->set_pressed(p_idx==1);
+ curve_del->set_pressed(p_idx==2);
+}
+
+void PathEditorPlugin::_close_curve() {
+
+ Ref<Curve3D> c = path->get_curve();
+ if (c.is_null())
+ return ;
+ if (c->get_point_count()<2)
+ return;
+ c->add_point(c->get_point_pos(0),c->get_point_in(0),c->get_point_out(0));
+
+}
+
+void PathEditorPlugin::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ curve_create->connect("pressed",this,"_mode_changed",make_binds(0));
+ curve_edit->connect("pressed",this,"_mode_changed",make_binds(1));
+ curve_del->connect("pressed",this,"_mode_changed",make_binds(2));
+ curve_close->connect("pressed",this,"_close_curve");
+ }
+}
+
+void PathEditorPlugin::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_mode_changed"),&PathEditorPlugin::_mode_changed);
+ ClassDB::bind_method(D_METHOD("_close_curve"),&PathEditorPlugin::_close_curve);
+}
+
+PathEditorPlugin* PathEditorPlugin::singleton=NULL;
+
+
+PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) {
+
+ path=NULL;
+ editor=p_node;
+ singleton=this;
+
+ path_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ path_material->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) );
+ path_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
+ path_material->set_line_width(3);
+ path_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ path_material->set_flag(Material::FLAG_UNSHADED,true);
+
+ path_thin_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ path_thin_material->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) );
+ path_thin_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
+ path_thin_material->set_line_width(1);
+ path_thin_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
+ path_thin_material->set_flag(Material::FLAG_UNSHADED,true);
+
+ //SpatialEditor::get_singleton()->add_gizmo_plugin(this);
+
+ sep = memnew( VSeparator);
+ sep->hide();
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(sep);
+ curve_edit = memnew( ToolButton );
+ curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit","EditorIcons"));
+ curve_edit->set_toggle_mode(true);
+ curve_edit->hide();
+ curve_edit->set_focus_mode(Control::FOCUS_NONE);
+ curve_edit->set_tooltip(TTR("Select Points")+"\n"+TTR("Shift+Drag: Select Control Points")+"\n"+keycode_get_string(KEY_MASK_CMD)+TTR("Click: Add Point")+"\n"+TTR("Right Click: Delete Point"));
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit);
+ curve_create = memnew( ToolButton );
+ curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate","EditorIcons"));
+ curve_create->set_toggle_mode(true);
+ curve_create->hide();
+ curve_create->set_focus_mode(Control::FOCUS_NONE);
+ curve_create->set_tooltip(TTR("Add Point (in empty space)")+"\n"+TTR("Split Segment (in curve)"));
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create);
+ curve_del = memnew( ToolButton );
+ curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete","EditorIcons"));
+ curve_del->set_toggle_mode(true);
+ curve_del->hide();
+ curve_del->set_focus_mode(Control::FOCUS_NONE);
+ curve_del->set_tooltip(TTR("Delete Point"));
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del);
+ curve_close = memnew( ToolButton );
+ curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveClose","EditorIcons"));
+ curve_close->hide();
+ curve_close->set_focus_mode(Control::FOCUS_NONE);
+ curve_close->set_tooltip(TTR("Close Curve"));
+ SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close);
+
+
+
+ curve_edit->set_pressed(true);
+ /*
+ collision_polygon_editor = memnew( PathEditor(p_node) );
+ editor->get_viewport()->add_child(collision_polygon_editor);
+
+ collision_polygon_editor->set_margin(MARGIN_LEFT,200);
+ collision_polygon_editor->set_margin(MARGIN_RIGHT,230);
+ collision_polygon_editor->set_margin(MARGIN_TOP,0);
+ collision_polygon_editor->set_margin(MARGIN_BOTTOM,10);
+
+
+ collision_polygon_editor->hide();
+ */
+
+
+}
+
+
+PathEditorPlugin::~PathEditorPlugin()
+{
+}
+
+#endif
diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h
new file mode 100644
index 0000000000..fe1c5ad159
--- /dev/null
+++ b/editor/plugins/path_editor_plugin.h
@@ -0,0 +1,100 @@
+/*************************************************************************/
+/* path_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PATH_EDITOR_PLUGIN_H
+#define PATH_EDITOR_PLUGIN_H
+
+
+#include "editor/spatial_editor_gizmos.h"
+#include "scene/3d/path.h"
+# if 0
+class PathSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(PathSpatialGizmo,EditorSpatialGizmo);
+
+ Path* path;
+ mutable Vector3 original;
+
+public:
+
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+
+ void redraw();
+ PathSpatialGizmo(Path* p_path=NULL);
+
+};
+
+class PathEditorPlugin : public EditorPlugin {
+
+ GDCLASS( PathEditorPlugin, EditorPlugin );
+
+
+ Separator *sep;
+ ToolButton *curve_create;
+ ToolButton *curve_edit;
+ ToolButton *curve_del;
+ ToolButton *curve_close;
+
+ EditorNode *editor;
+
+
+ Path *path;
+
+ void _mode_changed(int p_idx);
+ void _close_curve();
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+
+ Path *get_edited_path() { return path; }
+
+ static PathEditorPlugin* singleton;
+ Ref<FixedSpatialMaterial> path_material;
+ Ref<FixedSpatialMaterial> path_thin_material;
+ virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event);
+
+ //virtual bool forward_gui_input(const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+ virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial* p_spatial);
+ virtual String get_name() const { return "Path"; }
+ 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);
+
+ PathEditorPlugin(EditorNode *p_node);
+ ~PathEditorPlugin();
+
+};
+
+#endif
+#endif // PATH_EDITOR_PLUGIN_H
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..3a41b2cb6b
--- /dev/null
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -0,0 +1,1028 @@
+/*************************************************************************/
+/* polygon_2d_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "polygon_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "editor/editor_settings.h"
+#include "os/keyboard.h"
+#include "os/input.h"
+
+void Polygon2DEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ button_create->set_icon( get_icon("Edit","EditorIcons"));
+ button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
+ button_edit->set_pressed(true);
+ button_uv->set_icon( get_icon("Uv","EditorIcons"));
+
+ uv_button[UV_MODE_EDIT_POINT]->set_icon(get_icon("ToolSelect","EditorIcons"));
+ uv_button[UV_MODE_MOVE]->set_icon(get_icon("ToolMove","EditorIcons"));
+ uv_button[UV_MODE_ROTATE]->set_icon(get_icon("ToolRotate","EditorIcons"));
+ uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale","EditorIcons"));
+
+ b_snap_grid->set_icon( get_icon("Grid", "EditorIcons"));
+ b_snap_enable->set_icon( get_icon("Snap", "EditorIcons"));
+ uv_icon_zoom->set_texture( get_icon("Zoom", "EditorIcons"));
+
+ get_tree()->connect("node_removed", this, "_node_removed");
+
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void Polygon2DEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ edit(NULL);
+ hide();
+
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
+}
+
+
+void Polygon2DEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case MODE_CREATE: {
+
+ mode=MODE_CREATE;
+ button_create->set_pressed(true);
+ button_edit->set_pressed(false);
+ } break;
+ case MODE_EDIT: {
+
+ mode=MODE_EDIT;
+ button_create->set_pressed(false);
+ button_edit->set_pressed(true);
+ } break;
+ case MODE_EDIT_UV: {
+
+ if (node->get_texture().is_null()) {
+
+ error->set_text("No texture in this polygon.\nSet a texture to be able to edit UV.");
+ error->popup_centered_minsize();
+ return;
+ }
+
+
+ PoolVector<Vector2> points = node->get_polygon();
+ PoolVector<Vector2> uvs = node->get_uv();
+ if (uvs.size()!=points.size()) {
+ undo_redo->create_action(TTR("Create UV Map"));
+ undo_redo->add_do_method(node,"set_uv",points);
+ undo_redo->add_undo_method(node,"set_uv",uvs);
+ undo_redo->add_do_method(uv_edit_draw,"update");
+ undo_redo->add_undo_method(uv_edit_draw,"update");
+ undo_redo->commit_action();
+
+ }
+
+
+ uv_edit->popup_centered_ratio(0.85);
+ } break;
+ case UVEDIT_POLYGON_TO_UV: {
+
+ PoolVector<Vector2> points = node->get_polygon();
+ if (points.size()==0)
+ break;
+ PoolVector<Vector2> uvs = node->get_uv();
+ undo_redo->create_action(TTR("Create UV Map"));
+ undo_redo->add_do_method(node,"set_uv",points);
+ undo_redo->add_undo_method(node,"set_uv",uvs);
+ undo_redo->add_do_method(uv_edit_draw,"update");
+ undo_redo->add_undo_method(uv_edit_draw,"update");
+ undo_redo->commit_action();
+
+
+ } break;
+ case UVEDIT_UV_TO_POLYGON: {
+
+ PoolVector<Vector2> points = node->get_polygon();
+ PoolVector<Vector2> uvs = node->get_uv();
+ if (uvs.size()==0)
+ break;
+
+ undo_redo->create_action(TTR("Create UV Map"));
+ undo_redo->add_do_method(node,"set_polygon",uvs);
+ undo_redo->add_undo_method(node,"set_polygon",points);
+ undo_redo->add_do_method(uv_edit_draw,"update");
+ undo_redo->add_undo_method(uv_edit_draw,"update");
+ undo_redo->commit_action();
+
+ } break;
+ case UVEDIT_UV_CLEAR: {
+
+ PoolVector<Vector2> uvs = node->get_uv();
+ if (uvs.size()==0)
+ break;
+ undo_redo->create_action(TTR("Create UV Map"));
+ undo_redo->add_do_method(node,"set_uv",PoolVector<Vector2>());
+ undo_redo->add_undo_method(node,"set_uv",uvs);
+ undo_redo->add_do_method(uv_edit_draw,"update");
+ undo_redo->add_undo_method(uv_edit_draw,"update");
+ undo_redo->commit_action();
+
+ } break;
+
+
+ }
+}
+
+void Polygon2DEditor::_set_use_snap(bool p_use)
+{
+ use_snap=p_use;
+}
+
+void Polygon2DEditor::_set_show_grid(bool p_show)
+{
+ snap_show_grid=p_show;
+ uv_edit_draw->update();
+}
+
+void Polygon2DEditor::_set_snap_off_x(float p_val)
+{
+ snap_offset.x=p_val;
+ uv_edit_draw->update();
+}
+
+void Polygon2DEditor::_set_snap_off_y(float p_val)
+{
+ snap_offset.y=p_val;
+ uv_edit_draw->update();
+}
+
+void Polygon2DEditor::_set_snap_step_x(float p_val)
+{
+ snap_step.x=p_val;
+ uv_edit_draw->update();
+}
+
+void Polygon2DEditor::_set_snap_step_y(float p_val)
+{
+ snap_step.y=p_val;
+ uv_edit_draw->update();
+}
+
+void Polygon2DEditor::_wip_close() {
+
+ undo_redo->create_action(TTR("Create Poly"));
+ undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
+ undo_redo->add_do_method(node,"set_polygon",wip);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ wip.clear();
+ wip_active=false;
+ mode=MODE_EDIT;
+ button_edit->set_pressed(true);
+ button_create->set_pressed(false);
+ edited_point=-1;
+}
+
+bool Polygon2DEditor::forward_gui_input(const InputEvent& p_event) {
+
+ if (node==NULL)
+ return false;
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+
+
+ Vector2 gpoint = Point2(mb.x,mb.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+
+
+ Vector<Vector2> poly = Variant(node->get_polygon());
+
+ //first check if a point is to be added (segment split)
+ real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
+
+ switch(mode) {
+
+
+ case MODE_CREATE: {
+
+ if (mb.button_index==BUTTON_LEFT && mb.pressed) {
+
+
+ if (!wip_active) {
+
+ wip.clear();
+ wip.push_back( cpoint-node->get_offset() );
+ wip_active=true;
+ edited_point_pos=cpoint;
+ canvas_item_editor->get_viewport_control()->update();
+ edited_point=1;
+ return true;
+ } else {
+
+
+ if (wip.size()>1 && xform.xform(wip[0]+node->get_offset()).distance_to(gpoint)<grab_treshold) {
+ //wip closed
+ _wip_close();
+
+ return true;
+ } else {
+
+ wip.push_back( cpoint-node->get_offset() );
+ edited_point=wip.size();
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+
+ //add wip point
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
+ _wip_close();
+ }
+
+
+
+ } break;
+
+ case MODE_EDIT: {
+
+ if (mb.button_index==BUTTON_LEFT) {
+ if (mb.pressed) {
+
+ if (mb.mod.control) {
+
+
+ if (poly.size() < 3) {
+
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.push_back(cpoint);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ //search edges
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 points[2] ={ xform.xform(poly[i]+node->get_offset()),
+ xform.xform(poly[(i+1)%poly.size()]+node->get_offset()) };
+
+ Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
+ if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
+ continue; //not valid to reuse point
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos)-node->get_offset());
+ edited_point=closest_idx+1;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ node->set_polygon(Variant(poly));
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ } else {
+
+ //look for points to move
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]+node->get_offset());
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+ pre_move_edit=poly;
+ edited_point=closest_idx;
+ edited_point_pos=xform.affine_inverse().xform(closest_pos);
+ canvas_item_editor->get_viewport_control()->update();
+ return true;
+ }
+ }
+ } else {
+
+ if (edited_point!=-1) {
+
+ //apply
+
+ ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
+ poly[edited_point]=edited_point_pos-node->get_offset();
+ undo_redo->create_action(TTR("Edit Poly"));
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+
+ edited_point=-1;
+ return true;
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
+
+
+
+ int closest_idx=-1;
+ Vector2 closest_pos;
+ real_t closest_dist=1e10;
+ for(int i=0;i<poly.size();i++) {
+
+ Vector2 cp =xform.xform(poly[i]+node->get_offset());
+
+ real_t d = cp.distance_to(gpoint);
+ if (d<closest_dist && d<grab_treshold) {
+ closest_dist=d;
+ closest_pos=cp;
+ closest_idx=i;
+ }
+
+ }
+
+ if (closest_idx>=0) {
+
+
+ undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
+ undo_redo->add_undo_method(node,"set_polygon",poly);
+ poly.remove(closest_idx);
+ undo_redo->add_do_method(node,"set_polygon",poly);
+ undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
+ undo_redo->commit_action();
+ return true;
+ }
+
+ }
+
+
+
+ } break;
+ }
+
+
+
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
+
+ Vector2 gpoint = Point2(mm.x,mm.y);
+ Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
+ cpoint=canvas_item_editor->snap_point(cpoint);
+ edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
+
+ canvas_item_editor->get_viewport_control()->update();
+
+ }
+
+ } break;
+ }
+
+ return false;
+}
+void Polygon2DEditor::_canvas_draw() {
+
+ if (!node)
+ return;
+
+ Control *vpc = canvas_item_editor->get_viewport_control();
+
+ Vector<Vector2> poly;
+
+ if (wip_active)
+ poly=wip;
+ else
+ poly=Variant(node->get_polygon());
+
+
+ Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
+ Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
+
+ for(int i=0;i<poly.size();i++) {
+
+
+ Vector2 p,p2;
+ p = i==edited_point ? edited_point_pos : (poly[i]+node->get_offset());
+ if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
+ p2=edited_point_pos;
+ else
+ p2 = poly[(i+1)%poly.size()]+node->get_offset();
+
+ Vector2 point = xform.xform(p);
+ Vector2 next_point = xform.xform(p2);
+
+ Color col=Color(1,0.3,0.1,0.8);
+ vpc->draw_line(point,next_point,col,2);
+ vpc->draw_texture(handle,point-handle->get_size()*0.5);
+ }
+}
+
+
+void Polygon2DEditor::_uv_mode(int p_mode) {
+
+
+ uv_mode=UVMode(p_mode);
+ for(int i=0;i<UV_MODE_MAX;i++) {
+ uv_button[i]->set_pressed(p_mode==i);
+ }
+}
+
+
+void Polygon2DEditor::_uv_input(const InputEvent& p_input) {
+
+
+ Transform2D mtx;
+ mtx.elements[2]=-uv_draw_ofs;
+ mtx.scale_basis(Vector2(uv_draw_zoom,uv_draw_zoom));
+
+ if (p_input.type==InputEvent::MOUSE_BUTTON) {
+
+
+ const InputEventMouseButton &mb=p_input.mouse_button;
+
+ if (mb.button_index==BUTTON_LEFT) {
+
+
+ if (mb.pressed) {
+
+ uv_drag_from=Vector2(mb.x,mb.y);
+ uv_drag=true;
+ uv_prev=node->get_uv();
+ uv_move_current=uv_mode;
+ if (uv_move_current==UV_MODE_EDIT_POINT) {
+
+ if (mb.mod.shift && mb.mod.command)
+ uv_move_current=UV_MODE_SCALE;
+ else if (mb.mod.shift)
+ uv_move_current=UV_MODE_MOVE;
+ else if (mb.mod.command)
+ uv_move_current=UV_MODE_ROTATE;
+ }
+
+ if (uv_move_current==UV_MODE_EDIT_POINT) {
+
+ uv_drag_index=-1;
+ for(int i=0;i<uv_prev.size();i++) {
+
+ Vector2 tuv=mtx.xform(uv_prev[i]);
+ if (tuv.distance_to(Vector2(mb.x,mb.y))<8) {
+ uv_drag_from=tuv;
+ uv_drag_index=i;
+ }
+ }
+
+ if (uv_drag_index==-1) {
+ uv_drag=false;
+ }
+
+ }
+ } else if (uv_drag) {
+
+ undo_redo->create_action(TTR("Transform UV Map"));
+ undo_redo->add_do_method(node,"set_uv",node->get_uv());
+ undo_redo->add_undo_method(node,"set_uv",uv_prev);
+ undo_redo->add_do_method(uv_edit_draw,"update");
+ undo_redo->add_undo_method(uv_edit_draw,"update");
+ undo_redo->commit_action();
+
+ uv_drag=false;
+ }
+
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed) {
+
+ if (uv_drag) {
+
+ uv_drag=false;
+ node->set_uv(uv_prev);
+ uv_edit_draw->update();
+ }
+
+ } else if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) {
+
+ uv_zoom->set_value( uv_zoom->get_value()/0.9 );
+ } else if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) {
+
+ uv_zoom->set_value( uv_zoom->get_value()*0.9);
+ }
+
+ } else if (p_input.type==InputEvent::MOUSE_MOTION) {
+
+ const InputEventMouseMotion &mm=p_input.mouse_motion;
+
+ if (mm.button_mask&BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+
+ Vector2 drag(mm.relative_x,mm.relative_y);
+ uv_hscroll->set_value( uv_hscroll->get_value()-drag.x );
+ uv_vscroll->set_value( uv_vscroll->get_value()-drag.y );
+
+ } else if (uv_drag) {
+
+ Vector2 uv_drag_to=snap_point(Vector2(mm.x,mm.y));
+ Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from);
+
+
+ switch(uv_move_current) {
+
+ case UV_MODE_EDIT_POINT: {
+
+ PoolVector<Vector2> uv_new=uv_prev;
+ uv_new.set( uv_drag_index, uv_new[uv_drag_index]+drag );
+ node->set_uv(uv_new);
+ } break;
+ case UV_MODE_MOVE: {
+
+ PoolVector<Vector2> uv_new=uv_prev;
+ for(int i=0;i<uv_new.size();i++)
+ uv_new.set( i, uv_new[i]+drag );
+
+ node->set_uv(uv_new);
+
+
+ } break;
+ case UV_MODE_ROTATE: {
+
+ Vector2 center;
+ PoolVector<Vector2> uv_new=uv_prev;
+
+ for(int i=0;i<uv_new.size();i++)
+ center+=uv_prev[i];
+ center/=uv_new.size();
+
+ float angle = (uv_drag_from - mtx.xform(center)).normalized().angle_to( (uv_drag_to - mtx.xform(center)).normalized() );
+
+ for(int i=0;i<uv_new.size();i++) {
+ Vector2 rel = uv_prev[i] - center;
+ rel=rel.rotated(angle);
+ uv_new.set(i,center+rel);
+ }
+
+ node->set_uv(uv_new);
+
+ } break;
+ case UV_MODE_SCALE: {
+
+ Vector2 center;
+ PoolVector<Vector2> uv_new=uv_prev;
+
+ for(int i=0;i<uv_new.size();i++)
+ center+=uv_prev[i];
+ center/=uv_new.size();
+
+ float from_dist = uv_drag_from.distance_to(mtx.xform(center));
+ float to_dist = uv_drag_to.distance_to(mtx.xform(center));
+ if (from_dist<2)
+ break;
+
+ float scale = to_dist/from_dist;
+
+
+ for(int i=0;i<uv_new.size();i++) {
+ Vector2 rel = uv_prev[i] - center;
+ rel=rel*scale;
+ uv_new.set(i,center+rel);
+ }
+
+ node->set_uv(uv_new);
+ } break;
+
+
+ }
+ uv_edit_draw->update();
+ }
+
+ }
+
+}
+
+
+void Polygon2DEditor::_uv_scroll_changed(float) {
+
+ if (updating_uv_scroll)
+ return;
+
+ uv_draw_ofs.x=uv_hscroll->get_value();
+ uv_draw_ofs.y=uv_vscroll->get_value();
+ uv_draw_zoom=uv_zoom->get_value();
+ uv_edit_draw->update();
+}
+
+void Polygon2DEditor::_uv_draw() {
+
+ Ref<Texture> base_tex = node->get_texture();
+ if (base_tex.is_null())
+ return;
+
+ Transform2D mtx;
+ mtx.elements[2]=-uv_draw_ofs;
+ mtx.scale_basis(Vector2(uv_draw_zoom,uv_draw_zoom));
+
+ VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(),mtx);
+ uv_edit_draw->draw_texture(base_tex,Point2());
+ VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(),Transform2D());
+
+ if (snap_show_grid) {
+ Size2 s = uv_edit_draw->get_size();
+ int last_cell;
+
+ if (snap_step.x!=0) {
+ for(int i=0;i<s.width;i++) {
+ int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ uv_edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ }
+
+ if (snap_step.y!=0) {
+ for(int i=0;i<s.height;i++) {
+ int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ uv_edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ }
+ }
+
+ PoolVector<Vector2> uvs = node->get_uv();
+ Ref<Texture> handle = get_icon("EditorHandle","EditorIcons");
+
+ Rect2 rect(Point2(),mtx.basis_xform(base_tex->get_size()));
+ rect.expand_to(mtx.basis_xform(uv_edit_draw->get_size()));
+
+ for(int i=0;i<uvs.size();i++) {
+
+ int next = (i+1)%uvs.size();
+ uv_edit_draw->draw_line(mtx.xform(uvs[i]),mtx.xform(uvs[next]),Color(0.9,0.5,0.5),2);
+ uv_edit_draw->draw_texture(handle,mtx.xform(uvs[i])-handle->get_size()*0.5);
+ rect.expand_to(mtx.basis_xform(uvs[i]));
+ }
+
+ rect=rect.grow(200);
+ updating_uv_scroll=true;
+ uv_hscroll->set_min(rect.pos.x);
+ uv_hscroll->set_max(rect.pos.x+rect.size.x);
+ uv_hscroll->set_page(uv_edit_draw->get_size().x);
+ uv_hscroll->set_value(uv_draw_ofs.x);
+ uv_hscroll->set_step(0.001);
+
+ uv_vscroll->set_min(rect.pos.y);
+ uv_vscroll->set_max(rect.pos.y+rect.size.y);
+ uv_vscroll->set_page(uv_edit_draw->get_size().y);
+ uv_vscroll->set_value(uv_draw_ofs.y);
+ uv_vscroll->set_step(0.001);
+ updating_uv_scroll=false;
+
+}
+
+void Polygon2DEditor::edit(Node *p_collision_polygon) {
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton();
+ }
+
+ if (p_collision_polygon) {
+
+ node=p_collision_polygon->cast_to<Polygon2D>();
+ if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+
+ wip.clear();
+ wip_active=false;
+ edited_point=-1;
+
+ } else {
+
+ node=NULL;
+
+ if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
+
+ }
+
+}
+
+void Polygon2DEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_menu_option"),&Polygon2DEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_canvas_draw"),&Polygon2DEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_uv_mode"),&Polygon2DEditor::_uv_mode);
+ ClassDB::bind_method(D_METHOD("_uv_draw"),&Polygon2DEditor::_uv_draw);
+ ClassDB::bind_method(D_METHOD("_uv_input"),&Polygon2DEditor::_uv_input);
+ ClassDB::bind_method(D_METHOD("_uv_scroll_changed"),&Polygon2DEditor::_uv_scroll_changed);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&Polygon2DEditor::_node_removed);
+ ClassDB::bind_method(D_METHOD("_set_use_snap"),&Polygon2DEditor::_set_use_snap);
+ ClassDB::bind_method(D_METHOD("_set_show_grid"),&Polygon2DEditor::_set_show_grid);
+ ClassDB::bind_method(D_METHOD("_set_snap_off_x"),&Polygon2DEditor::_set_snap_off_x);
+ ClassDB::bind_method(D_METHOD("_set_snap_off_y"),&Polygon2DEditor::_set_snap_off_y);
+ ClassDB::bind_method(D_METHOD("_set_snap_step_x"),&Polygon2DEditor::_set_snap_step_x);
+ ClassDB::bind_method(D_METHOD("_set_snap_step_y"),&Polygon2DEditor::_set_snap_step_y);
+
+
+}
+
+inline float _snap_scalar(float p_offset, float p_step, float p_target) {
+ return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
+}
+
+Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
+ if (use_snap) {
+ p_target.x = _snap_scalar(snap_offset.x*uv_draw_zoom-uv_draw_ofs.x, snap_step.x*uv_draw_zoom, p_target.x);
+ p_target.y = _snap_scalar(snap_offset.y*uv_draw_zoom-uv_draw_ofs.y, snap_step.y*uv_draw_zoom, p_target.y);
+ }
+
+ return p_target;
+}
+
+Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) {
+
+ node=NULL;
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ snap_step=Vector2(10,10);
+ use_snap=false;
+ snap_show_grid=false;
+
+ add_child( memnew( VSeparator ));
+ button_create = memnew( ToolButton );
+ add_child(button_create);
+ button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
+ button_create->set_toggle_mode(true);
+
+ button_edit = memnew( ToolButton );
+ add_child(button_edit);
+ button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+ button_edit->set_toggle_mode(true);
+
+ button_uv = memnew( ToolButton );
+ add_child(button_uv);
+ button_uv->connect("pressed",this,"_menu_option",varray(MODE_EDIT_UV));
+
+ //add_constant_override("separation",0);
+
+#if 0
+ options = memnew( MenuButton );
+ add_child(options);
+ options->set_area_as_parent_rect();
+ options->set_text("Polygon");
+ //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+#endif
+
+ mode = MODE_EDIT;
+ wip_active=false;
+
+ uv_mode=UV_MODE_EDIT_POINT;
+ uv_edit = memnew( AcceptDialog );
+ add_child(uv_edit);
+ uv_edit->set_title(TTR("Polygon 2D UV Editor"));
+ uv_edit->set_self_modulate(Color(1,1,1,0.9));
+
+ VBoxContainer *uv_main_vb = memnew( VBoxContainer );
+ uv_edit->add_child(uv_main_vb);
+ //uv_edit->set_child_rect(uv_main_vb);
+ HBoxContainer *uv_mode_hb = memnew( HBoxContainer );
+ uv_main_vb->add_child(uv_mode_hb);
+ for(int i=0;i<UV_MODE_MAX;i++) {
+
+ uv_button[i]=memnew( ToolButton );
+ uv_button[i]->set_toggle_mode(true);
+ uv_mode_hb->add_child(uv_button[i]);
+ uv_button[i]->connect("pressed",this,"_uv_mode",varray(i));
+ uv_button[i]->set_focus_mode(FOCUS_NONE);
+ }
+
+ uv_button[0]->set_tooltip(TTR("Move Point")+"\n"+TTR("Ctrl: Rotate")+"\n"+TTR("Shift: Move All")+"\n"+TTR("Shift+Ctrl: Scale"));
+ uv_button[1]->set_tooltip(TTR("Move Polygon"));
+ uv_button[2]->set_tooltip(TTR("Rotate Polygon"));
+ uv_button[3]->set_tooltip(TTR("Scale Polygon"));
+
+ uv_button[0]->set_pressed(true);
+ HBoxContainer *uv_main_hb = memnew( HBoxContainer );
+ uv_main_vb->add_child(uv_main_hb);
+ uv_edit_draw = memnew( Control );
+ uv_main_hb->add_child(uv_edit_draw);
+ uv_main_hb->set_v_size_flags(SIZE_EXPAND_FILL);
+ uv_edit_draw->set_h_size_flags(SIZE_EXPAND_FILL);
+ uv_menu = memnew( MenuButton );
+ uv_mode_hb->add_child(uv_menu);
+ uv_menu->set_text(TTR("Edit"));
+ uv_menu->get_popup()->add_item(TTR("Polygon->UV"),UVEDIT_POLYGON_TO_UV);
+ uv_menu->get_popup()->add_item(TTR("UV->Polygon"),UVEDIT_UV_TO_POLYGON);
+ uv_menu->get_popup()->add_separator();
+ uv_menu->get_popup()->add_item(TTR("Clear UV"),UVEDIT_UV_CLEAR);
+ uv_menu->get_popup()->connect("id_pressed",this,"_menu_option");
+
+ uv_mode_hb->add_child( memnew( VSeparator ));
+
+ b_snap_enable = memnew( ToolButton );
+ uv_mode_hb->add_child(b_snap_enable);
+ b_snap_enable->set_text(TTR("Snap"));
+ b_snap_enable->set_focus_mode(FOCUS_NONE);
+ b_snap_enable->set_toggle_mode(true);
+ b_snap_enable->set_pressed(use_snap);
+ b_snap_enable->set_tooltip(TTR("Enable Snap"));
+ b_snap_enable->connect("toggled",this,"_set_use_snap");
+
+ b_snap_grid = memnew( ToolButton );
+ uv_mode_hb->add_child(b_snap_grid);
+ b_snap_grid->set_text(TTR("Grid"));
+ b_snap_grid->set_focus_mode(FOCUS_NONE);
+ b_snap_grid->set_toggle_mode(true);
+ b_snap_grid->set_pressed(snap_show_grid);
+ b_snap_grid->set_tooltip(TTR("Show Grid"));
+ b_snap_grid->connect("toggled",this,"_set_show_grid");
+
+ uv_mode_hb->add_child( memnew( VSeparator ));
+ uv_mode_hb->add_child( memnew( Label(TTR("Grid Offset:")) ) );
+
+ SpinBox *sb_off_x = memnew( SpinBox );
+ sb_off_x->set_min(-256);
+ sb_off_x->set_max(256);
+ sb_off_x->set_step(1);
+ sb_off_x->set_value(snap_offset.x);
+ sb_off_x->set_suffix("px");
+ sb_off_x->connect("value_changed", this, "_set_snap_off_x");
+ uv_mode_hb->add_child(sb_off_x);
+
+ SpinBox *sb_off_y = memnew( SpinBox );
+ sb_off_y->set_min(-256);
+ sb_off_y->set_max(256);
+ sb_off_y->set_step(1);
+ sb_off_y->set_value(snap_offset.y);
+ sb_off_y->set_suffix("px");
+ sb_off_y->connect("value_changed", this, "_set_snap_off_y");
+ uv_mode_hb->add_child(sb_off_y);
+
+ uv_mode_hb->add_child( memnew( VSeparator ));
+ uv_mode_hb->add_child( memnew( Label(TTR("Grid Step:")) ) );
+
+ SpinBox *sb_step_x = memnew( SpinBox );
+ sb_step_x->set_min(-256);
+ sb_step_x->set_max(256);
+ sb_step_x->set_step(1);
+ sb_step_x->set_value(snap_step.x);
+ sb_step_x->set_suffix("px");
+ sb_step_x->connect("value_changed", this, "_set_snap_step_x");
+ uv_mode_hb->add_child(sb_step_x);
+
+ SpinBox *sb_step_y = memnew( SpinBox );
+ sb_step_y->set_min(-256);
+ sb_step_y->set_max(256);
+ sb_step_y->set_step(1);
+ sb_step_y->set_value(snap_step.y);
+ sb_step_y->set_suffix("px");
+ sb_step_y->connect("value_changed", this, "_set_snap_step_y");
+ uv_mode_hb->add_child(sb_step_y);
+
+ uv_mode_hb->add_child( memnew( VSeparator ));
+ uv_icon_zoom = memnew( TextureRect );
+ uv_mode_hb->add_child( uv_icon_zoom );
+ uv_zoom = memnew( HSlider );
+ uv_zoom->set_min(0.01);
+ uv_zoom->set_max(4);
+ uv_zoom->set_value(1);
+ uv_zoom->set_step(0.01);
+ uv_mode_hb->add_child(uv_zoom);
+ uv_zoom->set_custom_minimum_size(Size2(200,0));
+ uv_zoom_value = memnew( SpinBox );
+ uv_zoom->share(uv_zoom_value);
+ uv_zoom_value->set_custom_minimum_size(Size2(50,0));
+ uv_mode_hb->add_child(uv_zoom_value);
+ uv_zoom->connect("value_changed",this,"_uv_scroll_changed");
+
+
+
+ uv_vscroll = memnew( VScrollBar);
+ uv_main_hb->add_child(uv_vscroll);
+ uv_vscroll->connect("value_changed",this,"_uv_scroll_changed");
+ uv_hscroll = memnew( HScrollBar );
+ uv_main_vb->add_child(uv_hscroll);
+ uv_hscroll->connect("value_changed",this,"_uv_scroll_changed");
+
+ uv_edit_draw->connect("draw",this,"_uv_draw");
+ uv_edit_draw->connect("gui_input",this,"_uv_input");
+ uv_draw_zoom=1.0;
+ uv_drag_index=-1;
+ uv_drag=false;
+ updating_uv_scroll=false;
+
+ error = memnew( AcceptDialog);
+ add_child(error);
+
+ uv_edit_draw->set_clip_contents(true);
+
+}
+
+
+void Polygon2DEditorPlugin::edit(Object *p_object) {
+
+
+ collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool Polygon2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Polygon2D");
+}
+
+void Polygon2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ collision_polygon_editor->show();
+ } else {
+
+ collision_polygon_editor->hide();
+ collision_polygon_editor->edit(NULL);
+ }
+
+}
+
+Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ collision_polygon_editor = memnew( Polygon2DEditor(p_node) );
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+ collision_polygon_editor->hide();
+
+}
+
+
+Polygon2DEditorPlugin::~Polygon2DEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
new file mode 100644
index 0000000000..c994867705
--- /dev/null
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -0,0 +1,167 @@
+/*************************************************************************/
+/* polygon_2d_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 POLYGON_2D_EDITOR_PLUGIN_H
+#define POLYGON_2D_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/polygon_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+class CanvasItemEditor;
+
+class Polygon2DEditor : public HBoxContainer {
+
+ GDCLASS(Polygon2DEditor, HBoxContainer );
+
+ UndoRedo *undo_redo;
+ enum Mode {
+
+ MODE_CREATE,
+ MODE_EDIT,
+ MODE_EDIT_UV,
+ UVEDIT_POLYGON_TO_UV,
+ UVEDIT_UV_TO_POLYGON,
+ UVEDIT_UV_CLEAR
+
+ };
+
+ enum UVMode {
+ UV_MODE_EDIT_POINT,
+ UV_MODE_MOVE,
+ UV_MODE_ROTATE,
+ UV_MODE_SCALE,
+ UV_MODE_MAX
+ };
+
+ Mode mode;
+
+ UVMode uv_mode;
+ AcceptDialog *uv_edit;
+ ToolButton *uv_button[4];
+ ToolButton *b_snap_enable;
+ ToolButton *b_snap_grid;
+ Control *uv_edit_draw;
+ HSlider *uv_zoom;
+ SpinBox *uv_zoom_value;
+ HScrollBar *uv_hscroll;
+ VScrollBar *uv_vscroll;
+ MenuButton *uv_menu;
+ TextureRect *uv_icon_zoom;
+
+ Vector2 uv_draw_ofs;
+ float uv_draw_zoom;
+ PoolVector<Vector2> uv_prev;
+ int uv_drag_index;
+ bool uv_drag;
+ UVMode uv_move_current;
+ Vector2 uv_drag_from;
+ bool updating_uv_scroll;
+
+
+
+ AcceptDialog *error;
+
+ ToolButton *button_create;
+ ToolButton *button_edit;
+ ToolButton *button_uv;
+
+ CanvasItemEditor *canvas_item_editor;
+ EditorNode *editor;
+ Panel *panel;
+ Polygon2D *node;
+ MenuButton *options;
+
+ int edited_point;
+ Vector2 edited_point_pos;
+ Vector<Vector2> pre_move_edit;
+ Vector<Vector2> wip;
+ bool wip_active;
+
+ bool use_snap;
+ bool snap_show_grid;
+ Vector2 snap_offset;
+ Vector2 snap_step;
+
+ void _uv_scroll_changed(float);
+ void _uv_input(const InputEvent& p_input);
+ void _uv_draw();
+ void _uv_mode(int p_mode);
+ void _wip_close();
+ void _canvas_draw();
+ void _menu_option(int p_option);
+
+ void _set_use_snap(bool p_use);
+ void _set_show_grid(bool p_show);
+ void _set_snap_off_x(float p_val);
+ void _set_snap_off_y(float p_val);
+ void _set_snap_step_x(float p_val);
+ void _set_snap_step_y(float p_val);
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+
+ Vector2 snap_point(Vector2 p_target) const;
+
+public:
+
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node *p_collision_polygon);
+ Polygon2DEditor(EditorNode *p_editor);
+};
+
+class Polygon2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS( Polygon2DEditorPlugin, EditorPlugin );
+
+ Polygon2DEditor *collision_polygon_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
+
+ virtual String get_name() const { return "Polygon2D"; }
+ 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);
+
+ Polygon2DEditorPlugin(EditorNode *p_node);
+ ~Polygon2DEditorPlugin();
+
+};
+
+#endif // POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
new file mode 100644
index 0000000000..e876fa55c6
--- /dev/null
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -0,0 +1,507 @@
+/*************************************************************************/
+/* resource_preloader_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_preloader_editor_plugin.h"
+
+#include "io/resource_loader.h"
+#include "global_config.h"
+#include "editor/editor_settings.h"
+
+
+void ResourcePreloaderEditor::_gui_input(InputEvent p_event) {
+
+
+}
+
+void ResourcePreloaderEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ load->set_icon( get_icon("Folder","EditorIcons") );
+ _delete->set_icon( get_icon("Del","EditorIcons") );
+ }
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //NodePath("/root")->connect("node_removed", this,"_node_removed",Vector<Variant>(),true);
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ }
+}
+
+void ResourcePreloaderEditor::_files_load_request(const Vector<String>& p_paths) {
+
+ for(int i=0;i<p_paths.size();i++) {
+
+ String path = p_paths[i];
+
+ RES resource;
+ resource = ResourceLoader::load(path);
+
+ if (resource.is_null()) {
+ dialog->set_text(TTR("ERROR: Couldn't load resource!"));
+ dialog->set_title(TTR("Error!"));
+ //dialog->get_cancel()->set_text("Close");
+ dialog->get_ok()->set_text(TTR("Close"));
+ dialog->popup_centered_minsize();
+ return; ///beh should show an error i guess
+ }
+
+
+ String basename = path.get_file().get_basename();
+ String name=basename;
+ int counter=1;
+ while(preloader->has_resource(name)) {
+ counter++;
+ name=basename+" "+itos(counter);
+ }
+
+ undo_redo->create_action(TTR("Add Resource"));
+ undo_redo->add_do_method(preloader,"add_resource",name,resource);
+ undo_redo->add_undo_method(preloader,"remove_resource",name);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+ }
+}
+
+void ResourcePreloaderEditor::_load_pressed() {
+
+ loading_scene=false;
+
+ file->clear_filters();
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("",&extensions);
+ for(int i=0;i<extensions.size();i++)
+ file->add_filter("*."+extensions[i]);
+
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+
+ file->popup_centered_ratio();
+
+}
+
+
+void ResourcePreloaderEditor::_item_edited() {
+
+ if (!tree->get_selected())
+ return;
+
+ TreeItem *s = tree->get_selected();
+
+ if (tree->get_selected_column()==0) {
+ // renamed
+ String old_name=s->get_metadata(0);
+ String new_name=s->get_text(0);
+ if (old_name==new_name)
+ return;
+
+ if (new_name=="" || new_name.find("\\")!=-1 || new_name.find("/")!=-1 || preloader->has_resource(new_name)) {
+
+ s->set_text(0,old_name);
+ return;
+ }
+
+ RES samp = preloader->get_resource(old_name);
+ undo_redo->create_action(TTR("Rename Resource"));
+ undo_redo->add_do_method(preloader,"remove_resource",old_name);
+ undo_redo->add_do_method(preloader,"add_resource",new_name,samp);
+ undo_redo->add_undo_method(preloader,"remove_resource",new_name);
+ undo_redo->add_undo_method(preloader,"add_resource",old_name,samp);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+ }
+
+
+}
+
+void ResourcePreloaderEditor::_delete_confirm_pressed() {
+
+ if (!tree->get_selected())
+ return;
+
+ String to_remove = tree->get_selected()->get_text(0);
+ undo_redo->create_action(TTR("Delete Resource"));
+ undo_redo->add_do_method(preloader,"remove_resource",to_remove);
+ undo_redo->add_undo_method(preloader,"add_resource",to_remove,preloader->get_resource(to_remove));
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+}
+
+
+void ResourcePreloaderEditor::_paste_pressed() {
+
+ RES r=EditorSettings::get_singleton()->get_resource_clipboard();
+ if (!r.is_valid()) {
+ dialog->set_text(TTR("Resource clipboard is empty!"));
+ dialog->set_title(TTR("Error!"));
+ //dialog->get_cancel()->set_text("Close");
+ dialog->get_ok()->set_text(TTR("Close"));
+ dialog->popup_centered_minsize();
+ return; ///beh should show an error i guess
+ }
+
+ String name = r->get_name();
+ if (name=="")
+ name=r->get_path().get_file();
+ if (name=="")
+ name=r->get_class();
+
+ String basename = name;
+ int counter=1;
+ while(preloader->has_resource(name)) {
+ counter++;
+ name=basename+" "+itos(counter);
+ }
+
+ undo_redo->create_action(TTR("Paste Resource"));
+ undo_redo->add_do_method(preloader,"add_resource",name,r);
+ undo_redo->add_undo_method(preloader,"remove_resource",name);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+}
+
+
+void ResourcePreloaderEditor::_delete_pressed() {
+
+
+ if (!tree->get_selected())
+ return;
+
+ _delete_confirm_pressed(); //it has undo.. why bother with a dialog..
+ /*
+ dialog->set_title("Confirm...");
+ dialog->set_text("Remove Resource '"+tree->get_selected()->get_text(0)+"' ?");
+ //dialog->get_cancel()->set_text("Cancel");
+ //dialog->get_ok()->show();
+ dialog->get_ok()->set_text("Remove");
+ dialog->popup_centered(Size2(300,60));*/
+
+}
+
+
+void ResourcePreloaderEditor::_update_library() {
+
+ tree->clear();
+ tree->set_hide_root(true);
+ TreeItem *root = tree->create_item(NULL);
+
+ List<StringName> rnames;
+ preloader->get_resource_list(&rnames);
+
+ List<String> names;
+ for(List<StringName>::Element *E=rnames.front();E;E=E->next()) {
+ names.push_back(E->get());
+ }
+
+ names.sort();
+
+ for(List<String>::Element *E=names.front();E;E=E->next()) {
+
+ 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);
+ ti->set_text(0,E->get());
+ ti->set_metadata(0,E->get());
+
+
+
+ RES r = preloader->get_resource(E->get());
+
+ ERR_CONTINUE(r.is_null());
+
+ ti->set_tooltip(0,r->get_path());
+ String type = r->get_class();
+ ti->set_text(1,type);
+ ti->set_selectable(1,false);
+
+ if (has_icon(type,"EditorIcons"))
+ ti->set_icon( 1, get_icon(type,"EditorIcons") );
+
+ }
+
+ //player->add_resource("default",resource);
+}
+
+
+
+void ResourcePreloaderEditor::edit(ResourcePreloader* p_preloader) {
+
+ preloader=p_preloader;
+
+
+ if (p_preloader) {
+ _update_library();
+ } else {
+
+ hide();
+ set_fixed_process(false);
+ }
+
+}
+
+
+
+Variant ResourcePreloaderEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ TreeItem*ti =tree->get_item_at_pos(p_point);
+ if (!ti)
+ return Variant();
+
+ String name = ti->get_metadata(0);
+
+ RES res = preloader->get_resource(name);
+ if (!res.is_valid())
+ return Variant();
+
+ return EditorNode::get_singleton()->drag_resource(res,p_from);
+
+}
+
+bool ResourcePreloaderEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
+
+
+
+ Dictionary d = p_data;
+
+ if (!d.has("type"))
+ return false;
+
+ if (d.has("from") && (Object*)(d["from"])==tree)
+ return false;
+
+ if (String(d["type"])=="resource" && d.has("resource")) {
+ RES r=d["resource"];
+
+ return r.is_valid();
+ }
+
+
+ if (String(d["type"])=="files") {
+
+ Vector<String> files = d["files"];
+
+ if (files.size()==0)
+ return false;
+
+ return true;
+
+ }
+ return false;
+}
+
+void ResourcePreloaderEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
+
+ if (!can_drop_data_fw(p_point,p_data,p_from))
+ return;
+
+ Dictionary d = p_data;
+
+ if (!d.has("type"))
+ return;
+
+
+ if (String(d["type"])=="resource" && d.has("resource")) {
+ RES r=d["resource"];
+
+ if (r.is_valid()) {
+
+ String basename;
+ if (r->get_name()!="") {
+ basename=r->get_name();
+ } else if (r->get_path().is_resource_file()) {
+ basename = r->get_path().get_basename();
+ } else {
+ basename="Resource";
+ }
+
+ String name=basename;
+ int counter=0;
+ while(preloader->has_resource(name)) {
+ counter++;
+ name=basename+"_"+itos(counter);
+ }
+
+ undo_redo->create_action(TTR("Add Resource"));
+ undo_redo->add_do_method(preloader,"add_resource",name,r);
+ undo_redo->add_undo_method(preloader,"remove_resource",name);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+ }
+ }
+
+
+ if (String(d["type"])=="files") {
+
+ Vector<String> files = d["files"];
+
+ _files_load_request(files);
+ }
+}
+
+
+
+void ResourcePreloaderEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&ResourcePreloaderEditor::_gui_input);
+ ClassDB::bind_method(D_METHOD("_load_pressed"),&ResourcePreloaderEditor::_load_pressed);
+ ClassDB::bind_method(D_METHOD("_item_edited"),&ResourcePreloaderEditor::_item_edited);
+ ClassDB::bind_method(D_METHOD("_delete_pressed"),&ResourcePreloaderEditor::_delete_pressed);
+ ClassDB::bind_method(D_METHOD("_paste_pressed"),&ResourcePreloaderEditor::_paste_pressed);
+ ClassDB::bind_method(D_METHOD("_delete_confirm_pressed"),&ResourcePreloaderEditor::_delete_confirm_pressed);
+ ClassDB::bind_method(D_METHOD("_files_load_request"),&ResourcePreloaderEditor::_files_load_request);
+ ClassDB::bind_method(D_METHOD("_update_library"),&ResourcePreloaderEditor::_update_library);
+
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &ResourcePreloaderEditor::drop_data_fw);
+
+
+}
+
+ResourcePreloaderEditor::ResourcePreloaderEditor() {
+
+ //add_style_override("panel", get_stylebox("panel","Panel"));
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
+
+ load = memnew( Button );
+ load->set_tooltip(TTR("Load Resource"));
+ hbc->add_child(load);
+
+
+
+ _delete = memnew( Button );
+ hbc->add_child(_delete);
+
+ paste = memnew( Button );
+ paste->set_text(TTR("Paste"));
+ hbc->add_child(paste);
+
+ file = memnew( EditorFileDialog );
+ add_child(file);
+
+
+ tree = memnew( Tree );
+ tree->set_columns(2);
+ tree->set_column_min_width(0,3);
+ tree->set_column_min_width(1,1);
+ tree->set_column_expand(0,true);
+ tree->set_column_expand(1,true);
+ tree->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ tree->set_drag_forwarding(this);
+ vbc->add_child(tree);
+
+ dialog = memnew( AcceptDialog );
+ add_child( dialog );
+
+ load->connect("pressed", this,"_load_pressed");
+ _delete->connect("pressed", this,"_delete_pressed");
+ paste->connect("pressed", this,"_paste_pressed");
+ file->connect("files_selected", this,"_files_load_request");
+ //dialog->connect("confirmed", this,"_delete_confirm_pressed");
+ tree->connect("item_edited", this,"_item_edited");
+ loading_scene=false;
+
+}
+
+
+void ResourcePreloaderEditorPlugin::edit(Object *p_object) {
+
+ preloader_editor->set_undo_redo(&get_undo_redo());
+ ResourcePreloader * s = p_object->cast_to<ResourcePreloader>();
+ if (!s)
+ return;
+
+ preloader_editor->edit(s);
+}
+
+bool ResourcePreloaderEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("ResourcePreloader");
+}
+
+void ResourcePreloaderEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ //preloader_editor->show();
+ button->show();
+ editor->make_bottom_panel_item_visible(preloader_editor);
+ //preloader_editor->set_process(true);
+ } else {
+
+ if (preloader_editor->is_visible_in_tree())
+ editor->hide_bottom_panel();
+ button->hide();
+ //preloader_editor->hide();
+ //preloader_editor->set_process(false);
+ }
+
+}
+
+ResourcePreloaderEditorPlugin::ResourcePreloaderEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ preloader_editor = memnew( ResourcePreloaderEditor );
+ 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 );
+
+
+
+
+}
+
+
+ResourcePreloaderEditorPlugin::~ResourcePreloaderEditorPlugin()
+{
+}
+
+
diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h
new file mode 100644
index 0000000000..54ccad4341
--- /dev/null
+++ b/editor/plugins/resource_preloader_editor_plugin.h
@@ -0,0 +1,108 @@
+/*************************************************************************/
+/* resource_preloader_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCE_PRELOADER_EDITOR_PLUGIN_H
+#define RESOURCE_PRELOADER_EDITOR_PLUGIN_H
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/gui/tree.h"
+#include "scene/main/resource_preloader.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/dialogs.h"
+
+
+class ResourcePreloaderEditor : public PanelContainer {
+
+ GDCLASS(ResourcePreloaderEditor, PanelContainer );
+
+ Button *load;
+ Button *_delete;
+ Button *paste;
+ Tree *tree;
+ bool loading_scene;
+
+
+ EditorFileDialog *file;
+
+ AcceptDialog *dialog;
+
+ ResourcePreloader *preloader;
+
+
+ void _load_pressed();
+ void _load_scene_pressed();
+ void _files_load_request(const Vector<String>& p_paths);
+ void _paste_pressed();
+ void _delete_pressed();
+ void _delete_confirm_pressed();
+ void _update_library();
+ void _item_edited();
+
+ UndoRedo *undo_redo;
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+ void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
+
+ void edit(ResourcePreloader* p_preloader);
+ ResourcePreloaderEditor();
+};
+
+class ResourcePreloaderEditorPlugin : public EditorPlugin {
+
+ GDCLASS( ResourcePreloaderEditorPlugin, EditorPlugin );
+
+ ResourcePreloaderEditor *preloader_editor;
+ EditorNode *editor;
+ Button *button;
+
+public:
+
+ virtual String get_name() const { return "ResourcePreloader"; }
+ 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);
+
+ ResourcePreloaderEditorPlugin(EditorNode *p_node);
+ ~ResourcePreloaderEditorPlugin();
+
+};
+
+#endif // RESOURCE_PRELOADER_EDITOR_PLUGIN_H
diff --git a/editor/plugins/rich_text_editor_plugin.cpp b/editor/plugins/rich_text_editor_plugin.cpp
new file mode 100644
index 0000000000..797ee8e8ea
--- /dev/null
+++ b/editor/plugins/rich_text_editor_plugin.cpp
@@ -0,0 +1,164 @@
+/*************************************************************************/
+/* rich_text_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "rich_text_editor_plugin.h"
+
+#include "os/file_access.h"
+#include "canvas_item_editor_plugin.h"
+
+void RichTextEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_FIXED_PROCESS: {
+
+
+ } break;
+ }
+
+}
+void RichTextEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ }
+
+}
+
+
+void RichTextEditor::_file_selected(const String& p_path) {
+
+ CharString cs;
+ FileAccess *fa = FileAccess::open(p_path,FileAccess::READ);
+ if (!fa) {
+ ERR_FAIL();
+ }
+
+ while(!fa->eof_reached())
+ cs.push_back(fa->get_8());
+ cs.push_back(0);
+ memdelete(fa);
+
+ String bbcode;
+ bbcode.parse_utf8(&cs[0]);
+ node->parse_bbcode(bbcode);
+
+}
+
+void RichTextEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case PARSE_BBCODE: {
+
+ file_dialog->popup_centered_ratio();
+ } break;
+ case CLEAR: {
+
+ node->clear();
+
+ } break;
+
+ }
+}
+
+void RichTextEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_menu_option"),&RichTextEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_file_selected"),&RichTextEditor::_file_selected);
+
+}
+
+void RichTextEditor::edit(Node *p_rich_text) {
+
+ node=p_rich_text->cast_to<RichTextLabel>();
+
+}
+RichTextEditor::RichTextEditor() {
+
+ options = memnew( MenuButton );
+ //add_child(options);
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options);
+ options->set_area_as_parent_rect();
+
+ options->set_text("RichText");
+ options->get_popup()->add_item(TTR("Parse BBCode"),PARSE_BBCODE);
+ options->get_popup()->add_item(TTR("Clear"),CLEAR);
+
+ options->get_popup()->connect("id_pressed", this,"_menu_option");
+ file_dialog = memnew( EditorFileDialog );
+ add_child(file_dialog);
+ file_dialog->add_filter("*.txt");
+ file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_dialog->connect("file_selected",this,"_file_selected");
+}
+
+
+void RichTextEditorPlugin::edit(Object *p_object) {
+
+ rich_text_editor->edit(p_object->cast_to<Node>());
+}
+
+bool RichTextEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("RichTextLabel");
+}
+
+void RichTextEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ rich_text_editor->options->show();
+ } else {
+
+ rich_text_editor->options->hide();
+ rich_text_editor->edit(NULL);
+ }
+
+}
+
+RichTextEditorPlugin::RichTextEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ rich_text_editor = memnew( RichTextEditor );
+ editor->get_viewport()->add_child(rich_text_editor);
+
+ rich_text_editor->set_margin(MARGIN_LEFT,184);
+ rich_text_editor->set_margin(MARGIN_RIGHT,230);
+ rich_text_editor->set_margin(MARGIN_TOP,0);
+ rich_text_editor->set_margin(MARGIN_BOTTOM,10);
+
+ rich_text_editor->options->hide();
+
+}
+
+
+RichTextEditorPlugin::~RichTextEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/rich_text_editor_plugin.h b/editor/plugins/rich_text_editor_plugin.h
new file mode 100644
index 0000000000..c7f95fb479
--- /dev/null
+++ b/editor/plugins/rich_text_editor_plugin.h
@@ -0,0 +1,91 @@
+/*************************************************************************/
+/* rich_text_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RICH_TEXT_EDITOR_PLUGIN_H
+#define RICH_TEXT_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/gui/rich_text_label.h"
+#include "scene/gui/file_dialog.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class RichTextEditor : public Control {
+
+ GDCLASS(RichTextEditor, Control );
+
+ friend class RichTextEditorPlugin;
+
+ enum {
+
+ PARSE_BBCODE,
+ CLEAR
+ };
+
+ Panel *panel;
+ MenuButton *options;
+ RichTextLabel *node;
+ EditorFileDialog *file_dialog;
+
+ void _file_selected(const String& p_path);
+ void _menu_option(int p_option);
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(Node *p_rich_text);
+ RichTextEditor();
+};
+
+class RichTextEditorPlugin : public EditorPlugin {
+
+ GDCLASS( RichTextEditorPlugin, EditorPlugin );
+
+ RichTextEditor *rich_text_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "RichText"; }
+ 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);
+
+ RichTextEditorPlugin(EditorNode *p_node);
+ ~RichTextEditorPlugin();
+
+};
+
+#endif // RICH_TEXT_EDITOR_PLUGIN_H
diff --git a/editor/plugins/sample_editor_plugin.cpp b/editor/plugins/sample_editor_plugin.cpp
new file mode 100644
index 0000000000..b6b96c946e
--- /dev/null
+++ b/editor/plugins/sample_editor_plugin.cpp
@@ -0,0 +1,451 @@
+/*************************************************************************/
+/* sample_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "sample_editor_plugin.h"
+
+#if 0
+#include "io/resource_loader.h"
+#include "global_config.h"
+#include "editor/editor_settings.h"
+
+
+
+
+void SampleEditor::_gui_input(InputEvent p_event) {
+
+
+}
+
+void SampleEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ play->set_icon( get_icon("Play","EditorIcons") );
+ stop->set_icon( get_icon("Stop","EditorIcons") );
+ }
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //get_scene()->connect("node_removed",this,"_node_removed");
+
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ }
+}
+
+void SampleEditor::_play_pressed() {
+
+ player->play("default",true);
+ stop->set_pressed(false);
+ play->set_pressed(true);
+}
+void SampleEditor::_stop_pressed() {
+
+ player->stop_all();
+ play->set_pressed(false);
+}
+
+void SampleEditor::generate_preview_texture(const Ref<Sample>& p_sample,Ref<ImageTexture> &p_texture) {
+
+
+ PoolVector<uint8_t> data = p_sample->get_data();
+
+ PoolVector<uint8_t> img;
+ int w = p_texture->get_width();
+ int h = p_texture->get_height();
+ img.resize(w*h*3);
+ PoolVector<uint8_t>::Write imgdata = img.write();
+ uint8_t * imgw = imgdata.ptr();
+ PoolVector<uint8_t>::Read sampledata = data.read();
+ const uint8_t *sdata=sampledata.ptr();
+
+ bool stereo = p_sample->is_stereo();
+ bool _16=p_sample->get_format()==Sample::FORMAT_PCM16;
+ int len = p_sample->get_length();
+
+ if (len<1)
+ return;
+
+ if (p_sample->get_format()==Sample::FORMAT_IMA_ADPCM) {
+
+
+ struct IMA_ADPCM_State {
+
+ int16_t step_index;
+ int32_t predictor;
+ /* values at loop point */
+ int16_t loop_step_index;
+ int32_t loop_predictor;
+ int32_t last_nibble;
+ int32_t loop_pos;
+ int32_t window_ofs;
+ const uint8_t *ptr;
+ } ima_adpcm;
+
+ ima_adpcm.step_index=0;
+ ima_adpcm.predictor=0;
+ ima_adpcm.loop_step_index=0;
+ ima_adpcm.loop_predictor=0;
+ ima_adpcm.last_nibble=-1;
+ ima_adpcm.loop_pos=0x7FFFFFFF;
+ ima_adpcm.window_ofs=0;
+ ima_adpcm.ptr=NULL;
+
+
+ for(int i=0;i<w;i++) {
+
+ float max[2]={-1e10,-1e10};
+ float min[2]={1e10,1e10};
+ int from = i*len/w;
+ int to = (i+1)*len/w;
+ if (to>=len)
+ to=len-1;
+
+ for(int j=from;j<to;j++) {
+
+ while(j>ima_adpcm.last_nibble) {
+
+ static const int16_t _ima_adpcm_step_table[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+ };
+
+ static const int8_t _ima_adpcm_index_table[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8
+ };
+
+ int16_t nibble,diff,step;
+
+ ima_adpcm.last_nibble++;
+ const uint8_t *src_ptr=sdata;
+
+ int ofs = ima_adpcm.last_nibble>>1;
+
+ if (stereo)
+ ofs*=2;
+
+ nibble = (ima_adpcm.last_nibble&1)?
+ (src_ptr[ofs]>>4):(src_ptr[ofs]&0xF);
+
+ step=_ima_adpcm_step_table[ima_adpcm.step_index];
+
+ ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
+ if (ima_adpcm.step_index<0)
+ ima_adpcm.step_index=0;
+ if (ima_adpcm.step_index>88)
+ ima_adpcm.step_index=88;
+
+ diff = step >> 3 ;
+ if (nibble & 1)
+ diff += step >> 2 ;
+ if (nibble & 2)
+ diff += step >> 1 ;
+ if (nibble & 4)
+ diff += step ;
+ if (nibble & 8)
+ diff = -diff ;
+
+ ima_adpcm.predictor+=diff;
+ if (ima_adpcm.predictor<-0x8000)
+ ima_adpcm.predictor=-0x8000;
+ else if (ima_adpcm.predictor>0x7FFF)
+ ima_adpcm.predictor=0x7FFF;
+
+
+ /* store loop if there */
+ if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {
+
+ ima_adpcm.loop_step_index = ima_adpcm.step_index;
+ ima_adpcm.loop_predictor = ima_adpcm.predictor;
+ }
+
+ }
+
+ float v=ima_adpcm.predictor/32767.0;
+ if (v>max[0])
+ max[0]=v;
+ if (v<min[0])
+ min[0]=v;
+ }
+
+ for(int j=0;j<h;j++) {
+ float v = (j/(float)h) * 2.0 - 1.0;
+ uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
+ if (v>min[0] && v<max[0]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
+ }
+ }
+ } else {
+ for(int i=0;i<w;i++) {
+ // i trust gcc will optimize this loop
+ float max[2]={-1e10,-1e10};
+ float min[2]={1e10,1e10};
+ int c=stereo?2:1;
+ int from = uint64_t(i)*len/w;
+ int to = (uint64_t(i)+1)*len/w;
+ if (to>=len)
+ to=len-1;
+
+ if (_16) {
+ const int16_t*src =(const int16_t*)sdata;
+
+ for(int j=0;j<c;j++) {
+
+ for(int k=from;k<=to;k++) {
+
+ float v = src[uint64_t(k)*c+j]/32768.0;
+ if (v>max[j])
+ max[j]=v;
+ if (v<min[j])
+ min[j]=v;
+ }
+
+ }
+ } else {
+
+ const int8_t*src =(const int8_t*)sdata;
+
+ for(int j=0;j<c;j++) {
+
+ for(int k=from;k<=to;k++) {
+
+ float v = src[uint64_t(k)*c+j]/128.0;
+ if (v>max[j])
+ max[j]=v;
+ if (v<min[j])
+ min[j]=v;
+ }
+
+ }
+ }
+
+ if (!stereo) {
+ for(int j=0;j<h;j++) {
+ float v = (j/(float)h) * 2.0 - 1.0;
+ uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
+ if (v>min[0] && v<max[0]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
+ }
+ } else {
+
+ for(int j=0;j<h;j++) {
+
+ int half;
+ float v;
+ if (j<(h/2)) {
+ half=0;
+ v = (j/(float)(h/2)) * 2.0 - 1.0;
+ } else {
+ half=1;
+ v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
+ }
+
+ uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
+ if (v>min[half] && v<max[half]) {
+ imgofs[0]=255;
+ imgofs[1]=150;
+ imgofs[2]=80;
+ } else {
+ imgofs[0]=0;
+ imgofs[1]=0;
+ imgofs[2]=0;
+ }
+ }
+
+ }
+
+ }
+ }
+
+ imgdata = PoolVector<uint8_t>::Write();
+
+
+ p_texture->set_data(Image(w,h,0,Image::FORMAT_RGB8,img));
+
+}
+
+void SampleEditor::_update_sample() {
+
+ player->stop_all();
+
+ generate_preview_texture(sample,peakdisplay);
+ info_label->set_text(TTR("Length:")+" "+String::num(sample->get_length()/(float)sample->get_mix_rate(),2)+"s");
+
+ if (library->has_sample("default"))
+ library->remove_sample("default");
+
+ library->add_sample("default",sample);
+}
+
+
+
+void SampleEditor::edit(Ref<Sample> p_sample) {
+
+ sample=p_sample;
+
+ if (!sample.is_null())
+ _update_sample();
+ else {
+
+ hide();
+ set_fixed_process(false);
+ }
+
+}
+
+
+
+void SampleEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&SampleEditor::_gui_input);
+ ClassDB::bind_method(D_METHOD("_play_pressed"),&SampleEditor::_play_pressed);
+ ClassDB::bind_method(D_METHOD("_stop_pressed"),&SampleEditor::_stop_pressed);
+
+}
+
+SampleEditor::SampleEditor() {
+
+ player = memnew(SamplePlayer);
+ add_child(player);
+ add_style_override("panel", get_stylebox("panel","Panel"));
+ library = Ref<SampleLibrary>(memnew(SampleLibrary));
+ player->set_sample_library(library);
+ sample_texframe = memnew( TextureRect );
+ add_child(sample_texframe);
+ sample_texframe->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
+ sample_texframe->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
+ sample_texframe->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,30);
+ sample_texframe->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
+
+ info_label = memnew( Label );
+ sample_texframe->add_child(info_label);
+ info_label->set_area_as_parent_rect();
+ info_label->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,15);
+ info_label->set_margin(MARGIN_BOTTOM,4);
+ info_label->set_margin(MARGIN_RIGHT,4);
+ info_label->set_align(Label::ALIGN_RIGHT);
+
+
+ play = memnew( Button );
+
+ play->set_pos(Point2( 5, 5 ));
+ play->set_size( Size2(1,1 ) );
+ play->set_toggle_mode(true);
+ add_child(play);
+
+ stop = memnew( Button );
+
+ stop->set_pos(Point2( 35, 5 ));
+ stop->set_size( Size2(1,1 ) );
+ stop->set_toggle_mode(true);
+ add_child(stop);
+
+ peakdisplay=Ref<ImageTexture>( memnew( ImageTexture) );
+ peakdisplay->create( EDITOR_DEF("editors/sample_editor/preview_width",512),EDITOR_DEF("editors/sample_editor/preview_height",128),Image::FORMAT_RGB8);
+ sample_texframe->set_expand(true);
+ sample_texframe->set_texture(peakdisplay);
+
+ play->connect("pressed", this,"_play_pressed");
+ stop->connect("pressed", this,"_stop_pressed");
+
+ set_custom_minimum_size(Size2(1,150)*EDSCALE);
+
+}
+
+
+void SampleEditorPlugin::edit(Object *p_object) {
+
+ Sample * s = p_object->cast_to<Sample>();
+ if (!s)
+ return;
+
+ sample_editor->edit(Ref<Sample>(s));
+}
+
+bool SampleEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Sample");
+}
+
+void SampleEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ sample_editor->show();
+ //sample_editor->set_process(true);
+ } else {
+
+ sample_editor->hide();
+ //sample_editor->set_process(false);
+ }
+
+}
+
+SampleEditorPlugin::SampleEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ sample_editor = memnew( SampleEditor );
+ add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,sample_editor);
+ sample_editor->hide();
+
+
+
+}
+
+
+SampleEditorPlugin::~SampleEditorPlugin()
+{
+}
+
+#endif
diff --git a/editor/plugins/sample_editor_plugin.h b/editor/plugins/sample_editor_plugin.h
new file mode 100644
index 0000000000..dae9cef9f4
--- /dev/null
+++ b/editor/plugins/sample_editor_plugin.h
@@ -0,0 +1,92 @@
+/*************************************************************************/
+/* sample_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SAMPLE_EDITOR_PLUGIN_H
+#define SAMPLE_EDITOR_PLUGIN_H
+
+#if 0
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/audio/sample_player.h"
+#include "scene/resources/sample.h"
+#include "scene/resources/sample_library.h"
+
+
+class SampleEditor : public Panel {
+
+ GDCLASS(SampleEditor, Panel );
+
+
+ SamplePlayer *player;
+ Label *info_label;
+ Ref<ImageTexture> peakdisplay;
+ Ref<Sample> sample;
+ Ref<SampleLibrary> library;
+ TextureRect *sample_texframe;
+ Button *stop;
+ Button *play;
+
+ void _play_pressed();
+ void _stop_pressed();
+ void _update_sample();
+
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+ static void generate_preview_texture(const Ref<Sample>& p_sample,Ref<ImageTexture> &p_texture);
+ void edit(Ref<Sample> p_sample);
+ SampleEditor();
+};
+
+
+class SampleEditorPlugin : public EditorPlugin {
+
+ GDCLASS( SampleEditorPlugin, EditorPlugin );
+
+ SampleEditor *sample_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "Sample"; }
+ 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);
+
+ SampleEditorPlugin(EditorNode *p_node);
+ ~SampleEditorPlugin();
+
+};
+
+#endif
+
+#endif // SAMPLE_EDITOR_PLUGIN_H
diff --git a/editor/plugins/sample_library_editor_plugin.cpp b/editor/plugins/sample_library_editor_plugin.cpp
new file mode 100644
index 0000000000..4ead1d2709
--- /dev/null
+++ b/editor/plugins/sample_library_editor_plugin.cpp
@@ -0,0 +1,546 @@
+/*************************************************************************/
+/* sample_library_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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. */
+/*************************************************************************/
+
+#if 0
+#include "sample_library_editor_plugin.h"
+
+#include "io/resource_loader.h"
+#include "global_config.h"
+#include "editor/editor_settings.h"
+#include "scene/main/viewport.h"
+#include "sample_editor_plugin.h"
+
+
+void SampleLibraryEditor::_gui_input(InputEvent p_event) {
+
+
+}
+
+void SampleLibraryEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_PROCESS) {
+ if (is_playing && !player->is_active()) {
+ TreeItem *tl=last_sample_playing->cast_to<TreeItem>();
+ tl->set_button(0,0,get_icon("Play","EditorIcons"));
+ is_playing = false;
+ set_process(false);
+ }
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ load->set_icon( get_icon("Folder","EditorIcons") );
+ load->set_tooltip(TTR("Open Sample File(s)"));
+ }
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //NodePath("/root")->connect("node_removed", this,"_node_removed",Vector<Variant>(),true);
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ }
+}
+
+void SampleLibraryEditor::_file_load_request(const PoolVector<String>& p_path) {
+
+
+ for(int i=0;i<p_path.size();i++) {
+
+ String path = p_path[i];
+ Ref<Sample> sample = ResourceLoader::load(path,"Sample");
+ if (sample.is_null()) {
+ dialog->set_text(TTR("ERROR: Couldn't load sample!"));
+ dialog->set_title(TTR("Error!"));
+ //dialog->get_cancel()->set_text("Close");
+ dialog->get_ok()->set_text(TTR("Close"));
+ dialog->popup_centered_minsize();
+ return; ///beh should show an error i guess
+ }
+ String basename = path.get_file().get_basename();
+ String name=basename;
+ int counter=0;
+ while(sample_library->has_sample(name)) {
+ counter++;
+ name=basename+"_"+itos(counter);
+ }
+
+ undo_redo->create_action(TTR("Add Sample"));
+ undo_redo->add_do_method(sample_library.operator->(),"add_sample",name,sample);
+ undo_redo->add_undo_method(sample_library.operator->(),"remove_sample",name);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+ }
+}
+
+void SampleLibraryEditor::_load_pressed() {
+
+ file->popup_centered_ratio();
+
+}
+
+void SampleLibraryEditor::_button_pressed(Object *p_item,int p_column, int p_id) {
+
+ TreeItem *ti=p_item->cast_to<TreeItem>();
+ String name = ti->get_text(0);
+
+ if (p_column==0) { // Play/Stop
+
+ String btn_type;
+ if(!is_playing) {
+ is_playing = true;
+ btn_type = TTR("Stop");
+ player->play(name,true);
+ last_sample_playing = p_item;
+ set_process(true);
+ } else {
+ player->stop_all();
+ if(last_sample_playing != p_item){
+ TreeItem *tl=last_sample_playing->cast_to<TreeItem>();
+ tl->set_button(p_column,0,get_icon("Play","EditorIcons"));
+ btn_type = TTR("Stop");
+ player->play(name,true);
+ last_sample_playing = p_item;
+ } else {
+ btn_type = TTR("Play");
+ is_playing = false;
+ }
+ }
+ ti->set_button(p_column,0,get_icon(btn_type,"EditorIcons"));
+ } else if (p_column==1) { // Edit
+
+ get_tree()->get_root()->get_child(0)->call("_resource_selected",sample_library->get_sample(name));
+ } else if (p_column==5) { // Delete
+
+ ti->select(0);
+ _delete_pressed();
+ }
+
+
+}
+
+
+
+
+
+void SampleLibraryEditor::_item_edited() {
+
+ if (!tree->get_selected())
+ return;
+
+ TreeItem *s = tree->get_selected();
+
+ if (tree->get_selected_column()==0) { // Name
+ // renamed
+ String old_name=s->get_metadata(0);
+ String new_name=s->get_text(0);
+ if (old_name==new_name)
+ return;
+
+ if (new_name=="" || new_name.find("\\")!=-1 || new_name.find("/")!=-1 || sample_library->has_sample(new_name)) {
+
+ s->set_text(0,old_name);
+ return;
+ }
+
+ Ref<Sample> samp = sample_library->get_sample(old_name);
+ undo_redo->create_action(TTR("Rename Sample"));
+ undo_redo->add_do_method(sample_library.operator->(),"remove_sample",old_name);
+ undo_redo->add_do_method(sample_library.operator->(),"add_sample",new_name,samp);
+ undo_redo->add_undo_method(sample_library.operator->(),"remove_sample",new_name);
+ undo_redo->add_undo_method(sample_library.operator->(),"add_sample",old_name,samp);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+ } else if (tree->get_selected_column()==3) { // Volume dB
+
+ StringName n = s->get_text(0);
+ sample_library->sample_set_volume_db(n,s->get_range(3));
+
+ } else if (tree->get_selected_column()==4) { // Pitch scale
+
+ StringName n = s->get_text(0);
+ sample_library->sample_set_pitch_scale(n,s->get_range(4));
+
+ }
+
+
+}
+
+void SampleLibraryEditor::_delete_pressed() {
+
+ if (!tree->get_selected())
+ return;
+
+ String to_remove = tree->get_selected()->get_text(0);
+ undo_redo->create_action(TTR("Delete Sample"));
+ undo_redo->add_do_method(sample_library.operator->(),"remove_sample",to_remove);
+ undo_redo->add_undo_method(sample_library.operator->(),"add_sample",to_remove,sample_library->get_sample(to_remove));
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+}
+
+
+void SampleLibraryEditor::_update_library() {
+
+ player->stop_all();
+
+ tree->clear();
+ tree->set_hide_root(true);
+ TreeItem *root = tree->create_item(NULL);
+
+ List<StringName> names;
+ sample_library->get_sample_list(&names);
+ names.sort_custom<StringName::AlphCompare>();
+
+ for(List<StringName>::Element *E=names.front();E;E=E->next()) {
+
+ TreeItem *ti = tree->create_item(root);
+
+ // Name + Play/Stop
+ ti->set_cell_mode(0,TreeItem::CELL_MODE_STRING);
+ ti->set_editable(0,true);
+ ti->set_selectable(0,true);
+ ti->set_text(0,E->get());
+ ti->set_metadata(0,E->get());
+ ti->add_button(0,get_icon("Play","EditorIcons"));
+
+ Ref<Sample> smp = sample_library->get_sample(E->get());
+
+ // Preview/edit
+ Ref<ImageTexture> preview( memnew( ImageTexture ));
+ preview->create(128,16,Image::FORMAT_RGB8);
+ SampleEditor::generate_preview_texture(smp,preview);
+ ti->set_cell_mode(1,TreeItem::CELL_MODE_ICON);
+ ti->set_selectable(1,false);
+ ti->set_editable(1,false);
+ ti->set_icon(1,preview);
+ ti->add_button(1,get_icon("Edit","EditorIcons"));
+
+ // Format
+ ti->set_cell_mode(2,TreeItem::CELL_MODE_STRING);
+ ti->set_editable(2,false);
+ ti->set_selectable(2,false);
+ ti->set_text(2,String()+(smp->get_format()==Sample::FORMAT_PCM16?TTR("16 Bits")+", ":(smp->get_format()==Sample::FORMAT_PCM8?TTR("8 Bits")+", ":"IMA-ADPCM,"))+(smp->is_stereo()?TTR("Stereo"):TTR("Mono")));
+
+ // Volume dB
+ ti->set_cell_mode(3,TreeItem::CELL_MODE_RANGE);
+ ti->set_range_config(3,-60,24,0.01);
+ ti->set_selectable(3,true);
+ ti->set_editable(3,true);
+ ti->set_range(3,sample_library->sample_get_volume_db(E->get()));
+
+ // Pitch scale
+ ti->set_cell_mode(4,TreeItem::CELL_MODE_RANGE);
+ ti->set_range_config(4,0.01,100,0.01);
+ ti->set_selectable(4,true);
+ ti->set_editable(4,true);
+ ti->set_range(4,sample_library->sample_get_pitch_scale(E->get()));
+
+ // Delete
+ ti->set_cell_mode(5,TreeItem::CELL_MODE_STRING);
+ ti->add_button(5,get_icon("Remove","EditorIcons"));
+
+ }
+
+ //player->add_sample("default",sample);
+}
+
+
+
+void SampleLibraryEditor::edit(Ref<SampleLibrary> p_sample_library) {
+
+ sample_library=p_sample_library;
+
+
+ if (!sample_library.is_null()) {
+ player->set_sample_library(sample_library);
+ _update_library();
+ } else {
+
+ hide();
+ }
+
+}
+
+Variant SampleLibraryEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ TreeItem*ti =tree->get_item_at_pos(p_point);
+ if (!ti)
+ return Variant();
+
+ String name = ti->get_metadata(0);
+
+ RES res = sample_library->get_sample(name);
+ if (!res.is_valid())
+ return Variant();
+
+ return EditorNode::get_singleton()->drag_resource(res,p_from);
+
+
+}
+
+bool SampleLibraryEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
+
+
+
+ Dictionary d = p_data;
+
+ if (!d.has("type"))
+ return false;
+
+ if (d.has("from") && (Object*)(d["from"])==tree)
+ return false;
+
+ if (String(d["type"])=="resource" && d.has("resource")) {
+ RES r=d["resource"];
+
+ Ref<Sample> sample = r;
+
+ if (sample.is_valid()) {
+
+ return true;
+ }
+ }
+
+
+ if (String(d["type"])=="files") {
+
+ Vector<String> files = d["files"];
+
+ if (files.size()==0)
+ return false;
+
+ for(int i=0;i<files.size();i++) {
+ String file = files[0];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+
+ if (ftype!="Sample") {
+ return false;
+ }
+
+ }
+
+ return true;
+
+ }
+ return false;
+}
+
+void SampleLibraryEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
+
+ if (!can_drop_data_fw(p_point,p_data,p_from))
+ return;
+
+ Dictionary d = p_data;
+
+ if (!d.has("type"))
+ return;
+
+
+ if (String(d["type"])=="resource" && d.has("resource")) {
+ RES r=d["resource"];
+
+ Ref<Sample> sample = r;
+
+ if (sample.is_valid()) {
+
+ String basename;
+ if (sample->get_name()!="") {
+ basename=sample->get_name();
+ } else if (sample->get_path().is_resource_file()) {
+ basename = sample->get_path().get_basename();
+ } else {
+ basename="Sample";
+ }
+
+ String name=basename;
+ int counter=0;
+ while(sample_library->has_sample(name)) {
+ counter++;
+ name=basename+"_"+itos(counter);
+ }
+
+ undo_redo->create_action(TTR("Add Sample"));
+ undo_redo->add_do_method(sample_library.operator->(),"add_sample",name,sample);
+ undo_redo->add_undo_method(sample_library.operator->(),"remove_sample",name);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+ }
+ }
+
+
+ if (String(d["type"])=="files") {
+
+ PoolVector<String> files = d["files"];
+
+ _file_load_request(files);
+
+ }
+
+}
+
+
+void SampleLibraryEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&SampleLibraryEditor::_gui_input);
+ ClassDB::bind_method(D_METHOD("_load_pressed"),&SampleLibraryEditor::_load_pressed);
+ ClassDB::bind_method(D_METHOD("_item_edited"),&SampleLibraryEditor::_item_edited);
+ ClassDB::bind_method(D_METHOD("_delete_pressed"),&SampleLibraryEditor::_delete_pressed);
+ ClassDB::bind_method(D_METHOD("_file_load_request"),&SampleLibraryEditor::_file_load_request);
+ ClassDB::bind_method(D_METHOD("_update_library"),&SampleLibraryEditor::_update_library);
+ ClassDB::bind_method(D_METHOD("_button_pressed"),&SampleLibraryEditor::_button_pressed);
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SampleLibraryEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SampleLibraryEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &SampleLibraryEditor::drop_data_fw);
+
+}
+
+SampleLibraryEditor::SampleLibraryEditor() {
+
+ player = memnew(SamplePlayer);
+ add_child(player);
+ add_style_override("panel", get_stylebox("panel","Panel"));
+
+
+ load = memnew( Button );
+ load->set_pos(Point2( 5, 5 ));
+ load->set_size( Size2(1,1 ) );
+ add_child(load);
+
+ file = memnew( EditorFileDialog );
+ add_child(file);
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Sample",&extensions);
+ for(int i=0;i<extensions.size();i++)
+ file->add_filter("*."+extensions[i]);
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+
+ tree = memnew( Tree );
+ tree->set_columns(6);
+ add_child(tree);
+ tree->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
+ tree->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
+ tree->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,30);
+ tree->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
+ tree->set_column_titles_visible(true);
+ tree->set_column_title(0,TTR("Name"));
+ tree->set_column_title(1,TTR("Preview"));
+ tree->set_column_title(2,TTR("Format"));
+ tree->set_column_title(3,"dB");
+ tree->set_column_title(4,TTR("Pitch"));
+ tree->set_column_title(5,"");
+
+ tree->set_column_min_width(1,150);
+ tree->set_column_min_width(2,100);
+ tree->set_column_min_width(3,50);
+ tree->set_column_min_width(4,50);
+ tree->set_column_min_width(5,32);
+ tree->set_column_expand(1,false);
+ tree->set_column_expand(2,false);
+ tree->set_column_expand(3,false);
+ tree->set_column_expand(4,false);
+ tree->set_column_expand(5,false);
+
+ tree->set_drag_forwarding(this);
+
+ dialog = memnew( ConfirmationDialog );
+ add_child( dialog );
+
+ tree->connect("button_pressed",this,"_button_pressed");
+ load->connect("pressed", this,"_load_pressed");
+ file->connect("files_selected", this,"_file_load_request");
+ tree->connect("item_edited", this,"_item_edited");
+
+ is_playing = false;
+}
+
+
+void SampleLibraryEditorPlugin::edit(Object *p_object) {
+
+ sample_library_editor->set_undo_redo(&get_undo_redo());
+ SampleLibrary * s = p_object->cast_to<SampleLibrary>();
+ if (!s)
+ return;
+
+ sample_library_editor->edit(Ref<SampleLibrary>(s));
+}
+
+bool SampleLibraryEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("SampleLibrary");
+}
+
+void SampleLibraryEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ //sample_library_editor->show();
+ button->show();
+ editor->make_bottom_panel_item_visible(sample_library_editor);
+ //sample_library_editor->set_process(true);
+ } else {
+
+ if (sample_library_editor->is_visible_in_tree())
+ editor->hide_bottom_panel();
+ button->hide();
+
+ //sample_library_editor->set_process(false);
+ }
+
+}
+
+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_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();
+
+
+
+}
+
+
+SampleLibraryEditorPlugin::~SampleLibraryEditorPlugin()
+{
+}
+#endif
diff --git a/editor/plugins/sample_library_editor_plugin.h b/editor/plugins/sample_library_editor_plugin.h
new file mode 100644
index 0000000000..4bbc29b147
--- /dev/null
+++ b/editor/plugins/sample_library_editor_plugin.h
@@ -0,0 +1,108 @@
+/*************************************************************************/
+/* sample_library_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SAMPLE_LIBRARY_EDITOR_PLUGIN_H
+#define SAMPLE_LIBRARY_EDITOR_PLUGIN_H
+
+
+#if 0
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/audio/sample_player.h"
+#include "scene/resources/sample.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/dialogs.h"
+
+
+class SampleLibraryEditor : public Panel {
+
+ GDCLASS(SampleLibraryEditor, Panel );
+
+
+
+ SamplePlayer *player;
+ Ref<SampleLibrary> sample_library;
+ Button *load;
+ Tree *tree;
+ bool is_playing;
+ Object *last_sample_playing;
+
+ EditorFileDialog *file;
+
+ ConfirmationDialog *dialog;
+
+
+ void _load_pressed();
+ void _file_load_request(const PoolVector<String>& p_path);
+ void _delete_pressed();
+ void _update_library();
+ void _item_edited();
+
+ UndoRedo *undo_redo;
+
+ void _button_pressed(Object *p_item,int p_column, int p_id);
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+ void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
+ void edit(Ref<SampleLibrary> p_sample);
+ SampleLibraryEditor();
+};
+
+class SampleLibraryEditorPlugin : public EditorPlugin {
+
+ GDCLASS( SampleLibraryEditorPlugin, EditorPlugin );
+
+ SampleLibraryEditor *sample_library_editor;
+ EditorNode *editor;
+ Button *button;
+
+public:
+
+ virtual String get_name() const { return "SampleLibrary"; }
+ 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);
+
+ SampleLibraryEditorPlugin(EditorNode *p_node);
+ ~SampleLibraryEditorPlugin();
+
+};
+
+#endif
+#endif // SAMPLE_LIBRARY_EDITOR_PLUGIN_H
diff --git a/editor/plugins/sample_player_editor_plugin.cpp b/editor/plugins/sample_player_editor_plugin.cpp
new file mode 100644
index 0000000000..7e2683dedf
--- /dev/null
+++ b/editor/plugins/sample_player_editor_plugin.cpp
@@ -0,0 +1,203 @@
+/*************************************************************************/
+/* sample_player_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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. */
+/*************************************************************************/
+
+#if 0
+#include "sample_player_editor_plugin.h"
+
+
+#include "scene/resources/sample_library.h"
+
+
+void SamplePlayerEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ play->set_icon( get_icon("Play","EditorIcons") );
+ stop->set_icon( get_icon("Stop","EditorIcons") );
+ }
+
+}
+
+void SamplePlayerEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ }
+
+}
+
+void SamplePlayerEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_play"),&SamplePlayerEditor::_play);
+ ClassDB::bind_method(D_METHOD("_stop"),&SamplePlayerEditor::_stop);
+
+}
+
+
+void SamplePlayerEditor::_play() {
+
+ if (!node)
+ return;
+ if (samples->get_item_count()<=0)
+ return;
+
+ node->call("play",samples->get_item_text( samples->get_selected() ));
+ stop->set_pressed(false);
+ play->set_pressed(true);
+}
+
+void SamplePlayerEditor::_stop() {
+
+ if (!node)
+ return;
+ if (samples->get_item_count()<=0)
+ return;
+
+ node->call("stop_all");
+ print_line("STOP ALL!!");
+ stop->set_pressed(true);
+ play->set_pressed(false);
+
+}
+
+
+void SamplePlayerEditor::_update_sample_library() {
+
+ samples->clear();
+ Ref<SampleLibrary> sl = node->call("get_sample_library");
+ if (sl.is_null()) {
+ samples->add_item("<NO SAMPLE LIBRARY>");
+ return; //no sample library;
+ }
+
+ List<StringName> samplenames;
+ sl->get_sample_list(&samplenames);
+ samplenames.sort_custom<StringName::AlphCompare>();
+ for(List<StringName>::Element *E=samplenames.front();E;E=E->next()) {
+ samples->add_item(E->get());
+ }
+
+}
+
+void SamplePlayerEditor::edit(Node *p_sample_player) {
+
+ node=p_sample_player;
+ if (node) {
+ _update_sample_library();
+ }
+
+}
+SamplePlayerEditor::SamplePlayerEditor() {
+
+
+ play = memnew( Button );
+
+ play->set_pos(Point2( 5, 5 ));
+ play->set_toggle_mode(true);
+ play->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,250);
+ play->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,230);
+ play->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
+ play->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
+
+ add_child(play);
+
+ stop = memnew( Button );
+
+ stop->set_pos(Point2( 35, 5 ));
+ stop->set_toggle_mode(true);
+ stop->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,220);
+ stop->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,200);
+ stop->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
+ stop->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
+ add_child(stop);
+
+ samples = memnew( OptionButton );
+ samples->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,190);
+ samples->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,5);
+ samples->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
+ samples->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
+ add_child(samples);
+
+ play->connect("pressed", this,"_play");
+ stop->connect("pressed", this,"_stop");
+
+}
+
+
+void SamplePlayerEditorPlugin::edit(Object *p_object) {
+
+ sample_player_editor->edit(p_object->cast_to<Node>());
+}
+
+bool SamplePlayerEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("SamplePlayer2D") || p_object->is_class("SamplePlayer") || p_object->is_class("SpatialSamplePlayer");
+}
+
+void SamplePlayerEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ sample_player_editor->show();
+ sample_player_editor->set_fixed_process(true);
+ } else {
+
+ sample_player_editor->hide();
+ sample_player_editor->set_fixed_process(false);
+ sample_player_editor->edit(NULL);
+ }
+
+}
+
+SamplePlayerEditorPlugin::SamplePlayerEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ sample_player_editor = memnew( SamplePlayerEditor );
+ editor->get_viewport()->add_child(sample_player_editor);
+
+ sample_player_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
+ sample_player_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
+ sample_player_editor->set_margin(MARGIN_LEFT,250);
+ sample_player_editor->set_margin(MARGIN_RIGHT,0);
+ sample_player_editor->set_margin(MARGIN_TOP,0);
+ sample_player_editor->set_margin(MARGIN_BOTTOM,10);
+
+
+ sample_player_editor->hide();
+
+
+
+}
+
+
+SamplePlayerEditorPlugin::~SamplePlayerEditorPlugin()
+{
+}
+
+
+#endif
diff --git a/editor/plugins/sample_player_editor_plugin.h b/editor/plugins/sample_player_editor_plugin.h
new file mode 100644
index 0000000000..c1d599540a
--- /dev/null
+++ b/editor/plugins/sample_player_editor_plugin.h
@@ -0,0 +1,90 @@
+/*************************************************************************/
+/* sample_player_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SAMPLE_PLAYER_EDITOR_PLUGIN_H
+#define SAMPLE_PLAYER_EDITOR_PLUGIN_H
+
+#if 0
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/3d/spatial_sample_player.h"
+#include "scene/gui/option_button.h"
+#include "scene/audio/sample_player.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class SamplePlayerEditor : public Control {
+
+ GDCLASS(SamplePlayerEditor, Control );
+
+ Panel *panel;
+ Button * play;
+ Button * stop;
+ OptionButton *samples;
+ Node *node;
+
+
+ void _update_sample_library();
+ void _play();
+ void _stop();
+
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(Node *p_sample_player);
+ SamplePlayerEditor();
+};
+
+class SamplePlayerEditorPlugin : public EditorPlugin {
+
+ GDCLASS( SamplePlayerEditorPlugin, EditorPlugin );
+
+ SamplePlayerEditor *sample_player_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "SamplePlayer"; }
+ 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);
+
+ SamplePlayerEditorPlugin(EditorNode *p_node);
+ ~SamplePlayerEditorPlugin();
+
+};
+
+#endif
+#endif // SAMPLE_PLAYER_EDITOR_PLUGIN_H
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
new file mode 100644
index 0000000000..3631d39f9a
--- /dev/null
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -0,0 +1,2491 @@
+/*************************************************************************/
+/* script_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "script_editor_plugin.h"
+
+#include "editor/editor_settings.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "os/keyboard.h"
+#include "os/os.h"
+#include "editor/editor_node.h"
+#include "editor/script_editor_debugger.h"
+#include "global_config.h"
+#include "os/file_access.h"
+#include "scene/main/viewport.h"
+#include "os/keyboard.h"
+#include "os/input.h"
+
+/*** SCRIPT EDITOR ****/
+
+
+
+void ScriptEditorBase::_bind_methods() {
+
+ ADD_SIGNAL(MethodInfo("name_changed"));
+ ADD_SIGNAL(MethodInfo("request_help_search",PropertyInfo(Variant::STRING,"topic")));
+ ADD_SIGNAL(MethodInfo("request_open_script_at_line",PropertyInfo(Variant::OBJECT,"script"),PropertyInfo(Variant::INT,"line")));
+ ADD_SIGNAL(MethodInfo("request_save_history"));
+ ADD_SIGNAL(MethodInfo("go_to_help",PropertyInfo(Variant::STRING,"what")));
+
+}
+
+static bool _can_open_in_editor(Script* p_script) {
+
+ String path = p_script->get_path();
+
+ if (path.find("::")!=-1) {
+ //refuse handling this if it can't be edited
+
+ bool valid=false;
+ for(int i=0;i<EditorNode::get_singleton()->get_editor_data().get_edited_scene_count();i++) {
+ if (path.begins_with(EditorNode::get_singleton()->get_editor_data().get_scene_path(i))) {
+ valid=true;
+ break;
+ }
+ }
+
+ return valid;
+ }
+
+ return true;
+}
+
+
+class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache {
+
+
+ struct Cache {
+ uint64_t time_loaded;
+ RES cache;
+ };
+
+ Map<String,Cache> cached;
+
+
+public:
+
+ uint64_t max_time_cache;
+ int max_cache_size;
+
+ void cleanup() {
+
+ List< Map<String,Cache>::Element * > to_clean;
+
+
+ Map<String,Cache>::Element *I=cached.front();
+ while(I) {
+ if ((OS::get_singleton()->get_ticks_msec()-I->get().time_loaded)>max_time_cache) {
+ to_clean.push_back(I);
+ }
+ I=I->next();
+ }
+
+ while(to_clean.front()) {
+ cached.erase(to_clean.front()->get());
+ to_clean.pop_front();
+ }
+ }
+
+ RES get_cached_resource(const String& p_path) {
+
+ Map<String,Cache>::Element *E=cached.find(p_path);
+ if (!E) {
+
+ Cache c;
+ c.cache=ResourceLoader::load(p_path);
+ E=cached.insert(p_path,c);
+ }
+
+ E->get().time_loaded=OS::get_singleton()->get_ticks_msec();
+
+ if (cached.size()>max_cache_size) {
+ uint64_t older;
+ Map<String,Cache>::Element *O=cached.front();
+ older=O->get().time_loaded;
+ Map<String,Cache>::Element *I=O;
+ while(I) {
+ if (I->get().time_loaded<older) {
+ older = I->get().time_loaded;
+ O=I;
+ }
+ I=I->next();
+ }
+
+ if (O!=E) {//should never heppane..
+ cached.erase(O);
+ }
+ }
+
+ return E->get().cache;
+ }
+
+
+ EditorScriptCodeCompletionCache() {
+
+ max_cache_size=128;
+ max_time_cache=5*60*1000; //minutes, five
+ }
+
+};
+
+#define SORT_SCRIPT_LIST
+
+void ScriptEditorQuickOpen::popup(const Vector<String>& p_functions, bool p_dontclear) {
+
+ popup_centered_ratio(0.6);
+ if (p_dontclear)
+ search_box->select_all();
+ else
+ search_box->clear();
+ search_box->grab_focus();
+ functions=p_functions;
+ _update_search();
+
+
+}
+
+
+void ScriptEditorQuickOpen::_text_changed(const String& p_newtext) {
+
+ _update_search();
+}
+
+void ScriptEditorQuickOpen::_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 ) ) {
+
+ search_options->call("_gui_input",p_ie);
+ search_box->accept_event();
+ }
+
+}
+
+
+
+void ScriptEditorQuickOpen::_update_search() {
+
+
+ search_options->clear();
+ TreeItem *root = search_options->create_item();
+
+ for(int i=0;i<functions.size();i++) {
+
+ String file = functions[i];
+ if ((search_box->get_text()=="" || file.findn(search_box->get_text())!=-1)) {
+
+ TreeItem *ti = search_options->create_item(root);
+ ti->set_text(0,file);
+ if (root->get_children()==ti)
+ ti->select(0);
+
+ }
+ }
+
+ get_ok()->set_disabled(root->get_children()==NULL);
+
+}
+
+void ScriptEditorQuickOpen::_confirmed() {
+
+ TreeItem *ti = search_options->get_selected();
+ if (!ti)
+ return;
+ int line = ti->get_text(0).get_slice(":",1).to_int();
+
+ emit_signal("goto_line",line-1);
+ hide();
+}
+
+void ScriptEditorQuickOpen::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ connect("confirmed",this,"_confirmed");
+
+
+ }
+}
+
+
+
+
+void ScriptEditorQuickOpen::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_text_changed"),&ScriptEditorQuickOpen::_text_changed);
+ ClassDB::bind_method(D_METHOD("_confirmed"),&ScriptEditorQuickOpen::_confirmed);
+ ClassDB::bind_method(D_METHOD("_sbox_input"),&ScriptEditorQuickOpen::_sbox_input);
+
+ ADD_SIGNAL(MethodInfo("goto_line",PropertyInfo(Variant::INT,"line")));
+
+}
+
+
+ScriptEditorQuickOpen::ScriptEditorQuickOpen() {
+
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ //set_child_rect(vbc);
+ search_box = memnew( LineEdit );
+ vbc->add_margin_child(TTR("Search:"),search_box);
+ search_box->connect("text_changed",this,"_text_changed");
+ search_box->connect("gui_input",this,"_sbox_input");
+ search_options = memnew( Tree );
+ vbc->add_margin_child(TTR("Matches:"),search_options,true);
+ get_ok()->set_text(TTR("Open"));
+ get_ok()->set_disabled(true);
+ register_text_enter(search_box);
+ set_hide_on_ok(false);
+ search_options->connect("item_activated",this,"_confirmed");
+ search_options->set_hide_root(true);
+}
+
+
+/////////////////////////////////
+
+ScriptEditor *ScriptEditor::script_editor=NULL;
+
+/*** SCRIPT EDITOR ******/
+
+String ScriptEditor::_get_debug_tooltip(const String&p_text,Node *_se) {
+
+ //ScriptEditorBase *se=_se->cast_to<ScriptEditorBase>();
+
+ String val = debugger->get_var_value(p_text);
+ if (val!=String()) {
+ return p_text+": "+val;
+ } else {
+
+ return String();
+ }
+}
+
+void ScriptEditor::_breaked(bool p_breaked,bool p_can_debug) {
+
+ if (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
+ return;
+ }
+
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), !(p_breaked && p_can_debug));
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), !(p_breaked && p_can_debug) );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), p_breaked );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), !p_breaked );
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se) {
+
+ continue;
+ }
+
+ se->set_debugger_active(p_breaked);
+ }
+
+}
+
+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) {
+ editor->push_item(p_script.operator->());
+}
+
+
+void ScriptEditor::_goto_script_line2(int p_line) {
+
+ int selected = tab_container->get_current_tab();
+ if (selected<0 || selected>=tab_container->get_child_count())
+ return;
+
+ ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
+ if (!current)
+ return;
+
+ current->goto_line(p_line);
+
+}
+
+void ScriptEditor::_goto_script_line(REF p_script,int p_line) {
+
+
+ editor->push_item(p_script.ptr());
+
+ int selected = tab_container->get_current_tab();
+ if (selected<0 || selected>=tab_container->get_child_count())
+ return;
+
+ ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
+ if (!current)
+ return;
+
+ current->goto_line(p_line,true);
+
+}
+
+
+void ScriptEditor::_update_history_arrows() {
+
+ script_back->set_disabled( history_pos<=0 );
+ script_forward->set_disabled( history_pos>=history.size()-1 );
+}
+
+void ScriptEditor::_save_history() {
+
+
+ if (history_pos>=0 && history_pos<history.size() && history[history_pos].control==tab_container->get_current_tab_control()) {
+
+ Node *n = tab_container->get_current_tab_control();
+
+ if (n->cast_to<ScriptEditorBase>()) {
+
+ history[history_pos].state=n->cast_to<ScriptEditorBase>()->get_edit_state();
+ }
+ if (n->cast_to<EditorHelp>()) {
+
+ history[history_pos].state=n->cast_to<EditorHelp>()->get_scroll();
+ }
+ }
+
+ history.resize(history_pos+1);
+ ScriptHistory sh;
+ sh.control=tab_container->get_current_tab_control();
+ sh.state=Variant();
+
+ history.push_back(sh);
+ history_pos++;
+
+ _update_history_arrows();
+}
+
+
+void ScriptEditor::_go_to_tab(int p_idx) {
+
+ Node *cn = tab_container->get_child(p_idx);
+ if (!cn)
+ return;
+ Control *c = cn->cast_to<Control>();
+ if (!c)
+ return;
+
+ if (history_pos>=0 && history_pos<history.size() && history[history_pos].control==tab_container->get_current_tab_control()) {
+
+ Node *n = tab_container->get_current_tab_control();
+
+ if (n->cast_to<ScriptEditorBase>()) {
+
+ history[history_pos].state=n->cast_to<ScriptEditorBase>()->get_edit_state();
+ }
+ if (n->cast_to<EditorHelp>()) {
+
+ history[history_pos].state=n->cast_to<EditorHelp>()->get_scroll();
+ }
+ }
+
+ history.resize(history_pos+1);
+ ScriptHistory sh;
+ sh.control=c;
+ sh.state=Variant();
+
+ history.push_back(sh);
+ history_pos++;
+
+
+ tab_container->set_current_tab(p_idx);
+
+ c = tab_container->get_current_tab_control();
+
+ if (c->cast_to<ScriptEditorBase>()) {
+
+ script_name_label->set_text(c->cast_to<ScriptEditorBase>()->get_name());
+ script_icon->set_texture(c->cast_to<ScriptEditorBase>()->get_icon());
+ if (is_visible_in_tree())
+ c->cast_to<ScriptEditorBase>()->ensure_focus();
+ }
+ if (c->cast_to<EditorHelp>()) {
+
+ script_name_label->set_text(c->cast_to<EditorHelp>()->get_class());
+ script_icon->set_texture(get_icon("Help","EditorIcons"));
+ if (is_visible_in_tree())
+ c->cast_to<EditorHelp>()->set_focused();
+ }
+
+
+
+ c->set_meta("__editor_pass",++edit_pass);
+ _update_history_arrows();
+ _update_script_colors();
+ _update_selected_editor_menu();
+}
+
+void ScriptEditor::_close_tab(int p_idx, bool p_save) {
+
+ int selected = p_idx;
+ if (selected<0 || selected>=tab_container->get_child_count())
+ return;
+
+ Node *tselected = tab_container->get_child(selected);
+ ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
+ if (current) {
+ if (p_save) {
+ apply_scripts();
+ }
+ if (current->get_edit_menu()) {
+ memdelete(current->get_edit_menu());
+ }
+ }
+
+ //remove from history
+ history.resize(history_pos+1);
+
+ for(int i=0;i<history.size();i++) {
+ if (history[i].control==tselected) {
+ history.remove(i);
+ i--;
+ history_pos--;
+ }
+ }
+
+ if (history_pos>=history.size()) {
+ history_pos=history.size()-1;
+ }
+
+ int idx = tab_container->get_current_tab();
+ memdelete(tselected);
+ if (idx>=tab_container->get_child_count())
+ idx=tab_container->get_child_count()-1;
+ if (idx>=0) {
+
+ if (history_pos>=0) {
+ idx = history[history_pos].control->get_index();
+ }
+ tab_container->set_current_tab(idx);
+
+ //script_list->select(idx);
+ }
+
+
+ _update_history_arrows();
+
+
+
+ _update_script_names();
+ _save_layout();
+}
+
+void ScriptEditor::_close_current_tab() {
+
+ _close_tab(tab_container->get_current_tab());
+
+}
+
+void ScriptEditor::_close_discard_current_tab(const String& p_str) {
+ _close_tab(tab_container->get_current_tab(), false);
+ erase_tab_confirm->hide();
+}
+
+void ScriptEditor::_close_docs_tab() {
+
+ int child_count = tab_container->get_child_count();
+ for (int i = child_count-1; i>=0; i--) {
+
+ EditorHelp *se = tab_container->get_child(i)->cast_to<EditorHelp>();
+
+ if (se) {
+ _close_tab(i);
+ }
+
+ }
+
+}
+
+void ScriptEditor::_close_all_tabs() {
+
+ int child_count = tab_container->get_child_count();
+ for (int i = child_count-1; i>=0; i--) {
+
+ tab_container->set_current_tab(i);
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+
+ if (se) {
+
+ // Maybe there are unsaved changes
+ if (se->is_unsaved()) {
+ _ask_close_current_unsaved_tab(se);
+ continue;
+ }
+
+ }
+
+ _close_current_tab();
+ }
+
+}
+
+void ScriptEditor::_ask_close_current_unsaved_tab(ScriptEditorBase *current) {
+ erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\"");
+ erase_tab_confirm->popup_centered_minsize();
+}
+
+
+void ScriptEditor::_resave_scripts(const String& p_str) {
+
+ apply_scripts();
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se)
+ continue;
+
+
+ Ref<Script> script = se->get_edited_script();
+
+ if (script->get_path()=="" || script->get_path().find("local://")!=-1 || script->get_path().find("::")!=-1)
+ continue; //internal script, who cares
+
+ if (trim_trailing_whitespace_on_save) {
+ se->trim_trailing_whitespace();
+ }
+ editor->save_resource(script);
+ se->tag_saved_version();
+ }
+
+ disk_changed->hide();
+
+}
+
+void ScriptEditor::_reload_scripts(){
+
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se) {
+
+ continue;
+ }
+
+
+ Ref<Script> script = se->get_edited_script();
+
+ 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());
+
+ //printf("last date: %lli vs date: %lli\n",last_date,date);
+ if (last_date==date) {
+ continue;
+ }
+
+
+ Ref<Script> rel_script = ResourceLoader::load(script->get_path(),script->get_class(),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->reload();
+ se->reload_text();
+
+
+ }
+
+ disk_changed->hide();
+ _update_script_names();
+
+}
+
+
+
+void ScriptEditor::_res_saved_callback(const Ref<Resource>& p_res) {
+
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se) {
+
+ continue;
+ }
+
+
+ Ref<Script> script = se->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==p_res) {
+
+ se->tag_saved_version();
+ }
+
+ }
+
+ _update_script_names();
+
+
+ if (!pending_auto_reload && auto_reload_running_scripts) {
+ call_deferred("_live_auto_reload_running_scripts");
+ pending_auto_reload=true;
+ }
+}
+
+void ScriptEditor::_live_auto_reload_running_scripts() {
+ pending_auto_reload=false;
+ debugger->reload_scripts();
+}
+
+
+bool ScriptEditor::_test_script_times_on_disk(Ref<Script> p_for_script) {
+
+
+ disk_changed_list->clear();
+ TreeItem *r = disk_changed_list->create_item();
+ disk_changed_list->set_hide_root(true);
+
+ bool need_ask=false;
+ bool need_reload=false;
+ bool use_autoreload=bool(EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change",false));
+
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (se) {
+
+ Ref<Script> script = se->get_edited_script();
+
+ if (p_for_script.is_valid() && p_for_script!=script)
+ continue;
+
+ 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());
+
+ //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());
+
+ if (!use_autoreload || se->is_unsaved()) {
+ need_ask=true;
+ }
+ need_reload=true;
+ //r->set_metadata(0,);
+ }
+ }
+ }
+
+
+
+ if (need_reload) {
+ if (!need_ask) {
+ script_editor->_reload_scripts();
+ need_reload=false;
+ } else {
+ disk_changed->call_deferred("popup_centered_ratio",0.5);
+ }
+ }
+
+ return need_reload;
+}
+
+
+void ScriptEditor::_file_dialog_action(String p_file) {
+
+ switch (file_dialog_option) {
+ case FILE_SAVE_THEME_AS: {
+ if(!EditorSettings::get_singleton()->save_text_editor_theme_as(p_file)) {
+ editor->show_warning(TTR("Error while saving theme"), TTR("Error saving"));
+ }
+ } break;
+ case FILE_IMPORT_THEME: {
+ if(!EditorSettings::get_singleton()->import_text_editor_theme(p_file)) {
+ editor->show_warning(TTR("Error importing theme"), TTR("Error importing"));
+ }
+ } break;
+ }
+ file_dialog_option = -1;
+}
+
+void ScriptEditor::_menu_option(int p_option) {
+
+
+ switch(p_option) {
+ case FILE_NEW: {
+ script_create_dialog->config("Node", ".gd");
+ script_create_dialog->popup_centered(Size2(300, 300)*EDSCALE);
+ } break;
+ case FILE_OPEN: {
+
+ editor->open_resource("Script");
+ return;
+ } break;
+ case FILE_SAVE_ALL: {
+
+ if (_test_script_times_on_disk())
+ return;
+
+ save_all_scripts();
+ } break;
+ case FILE_IMPORT_THEME: {
+ file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file_dialog_option = FILE_IMPORT_THEME;
+ file_dialog->clear_filters();
+ file_dialog->add_filter("*.tet");
+ file_dialog->popup_centered_ratio();
+ file_dialog->set_title(TTR("Import Theme"));
+ } break;
+ case FILE_RELOAD_THEME: {
+ EditorSettings::get_singleton()->load_text_editor_theme();
+ } break;
+ case FILE_SAVE_THEME: {
+ if(!EditorSettings::get_singleton()->save_text_editor_theme()) {
+ editor->show_warning(TTR("Error while saving theme"), TTR("Error saving"));
+ }
+ } break;
+ case FILE_SAVE_THEME_AS: {
+ file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file_dialog_option = FILE_SAVE_THEME_AS;
+ file_dialog->clear_filters();
+ file_dialog->add_filter("*.tet");
+ file_dialog->set_current_path(EditorSettings::get_singleton()->get_settings_path() + "/text_editor_themes/" + EditorSettings::get_singleton()->get("text_editor/theme/color_theme"));
+ file_dialog->popup_centered_ratio();
+ file_dialog->set_title(TTR("Save Theme As.."));
+ } break;
+ case SEARCH_HELP: {
+
+ help_search_dialog->popup();
+ } break;
+ case SEARCH_CLASSES: {
+
+ String current;
+
+ if (tab_container->get_tab_count()>0) {
+ EditorHelp *eh = tab_container->get_child( tab_container->get_current_tab() )->cast_to<EditorHelp>();
+ if (eh) {
+ current=eh->get_class();
+ }
+ }
+
+ help_index->popup();
+
+ if (current!="") {
+ help_index->call_deferred("select_class",current);
+ }
+ } break;
+ case SEARCH_WEBSITE: {
+
+ OS::get_singleton()->shell_open("http://docs.godotengine.org/");
+ } break;
+
+ case WINDOW_NEXT: {
+
+ _history_forward();
+ } break;
+ 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;
+ }
+
+
+ int selected = tab_container->get_current_tab();
+ if (selected<0 || selected>=tab_container->get_child_count())
+ return;
+
+ ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
+ if (current) {
+
+ switch(p_option) {
+ case FILE_NEW: {
+ script_create_dialog->config("Node", ".gd");
+ script_create_dialog->popup_centered(Size2(300, 300)*EDSCALE);
+ } break;
+ case FILE_SAVE: {
+
+ if (_test_script_times_on_disk())
+ return;
+
+ if (trim_trailing_whitespace_on_save)
+ current->trim_trailing_whitespace();
+ editor->save_resource( current->get_edited_script() );
+
+ } break;
+ case FILE_SAVE_AS: {
+
+ current->trim_trailing_whitespace();
+ editor->push_item(current->get_edited_script()->cast_to<Object>());
+ editor->save_resource_as( current->get_edited_script() );
+
+ } break;
+
+ case FILE_TOOL_RELOAD:
+ case FILE_TOOL_RELOAD_SOFT: {
+
+ current->reload(p_option==FILE_TOOL_RELOAD_SOFT);
+
+ } break;
+
+ case FILE_CLOSE: {
+ if (current->is_unsaved()) {
+ _ask_close_current_unsaved_tab(current);
+ } else {
+ _close_current_tab();
+ }
+ } break;
+ case CLOSE_DOCS: {
+ _close_docs_tab();
+ } break;
+ case CLOSE_ALL: {
+ _close_all_tabs();
+ } break;
+ case DEBUG_NEXT: {
+
+ if (debugger)
+ debugger->debug_next();
+ } break;
+ case DEBUG_STEP: {
+
+ if (debugger)
+ debugger->debug_step();
+
+ } break;
+ case DEBUG_BREAK: {
+
+ if (debugger)
+ debugger->debug_break();
+
+ } break;
+ case DEBUG_CONTINUE: {
+
+ if (debugger)
+ debugger->debug_continue();
+
+ } break;
+ case WINDOW_MOVE_LEFT: {
+
+ if (tab_container->get_current_tab()>0) {
+ tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()-1);
+ script_list->call_deferred("select",tab_container->get_current_tab()-1);
+ tab_container->move_child(current,tab_container->get_current_tab()-1);
+ _update_script_names();
+ }
+ } break;
+ case WINDOW_MOVE_RIGHT: {
+
+ if (tab_container->get_current_tab()<tab_container->get_child_count()-1) {
+ tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()+1);
+ script_list->call_deferred("select",tab_container->get_current_tab()+1);
+ tab_container->move_child(current,tab_container->get_current_tab()+1);
+ _update_script_names();
+ }
+
+
+ } break;
+
+ default: {
+
+ if (p_option>=WINDOW_SELECT_BASE) {
+
+ tab_container->set_current_tab(p_option-WINDOW_SELECT_BASE);
+ script_list->select(p_option-WINDOW_SELECT_BASE);
+
+ }
+ }
+ }
+ }
+
+ EditorHelp *help = tab_container->get_current_tab_control()->cast_to<EditorHelp>();
+ if (help) {
+
+ switch(p_option) {
+
+ case HELP_SEARCH_FIND: {
+ help->popup_search();
+ } break;
+ case HELP_SEARCH_FIND_NEXT: {
+ help->search_again();
+ } break;
+ case FILE_CLOSE: {
+ _close_current_tab();
+ } break;
+ case CLOSE_DOCS: {
+ _close_docs_tab();
+ } break;
+ case CLOSE_ALL: {
+ _close_all_tabs();
+ } break;
+
+
+ }
+ }
+
+
+}
+
+void ScriptEditor::_tab_changed(int p_which) {
+
+ ensure_select_current();
+}
+
+void ScriptEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ editor->connect("play_pressed",this,"_editor_play");
+ editor->connect("pause_pressed",this,"_editor_pause");
+ editor->connect("stop_pressed",this,"_editor_stop");
+ editor->connect("script_add_function_request",this,"_add_callback");
+ editor->connect("resource_saved",this,"_res_saved_callback");
+ script_list->connect("item_selected",this,"_script_selected");
+ script_split->connect("dragged",this,"_script_split_dragged");
+ autosave_timer->connect("timeout",this,"_autosave_scripts");
+ {
+ float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
+ if (autosave_time>0) {
+ autosave_timer->set_wait_time(autosave_time);
+ autosave_timer->start();
+ } else {
+ autosave_timer->stop();
+ }
+ }
+
+ EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed");
+ help_search->set_icon(get_icon("Help","EditorIcons"));
+ site_search->set_icon(get_icon("Godot","EditorIcons"));
+ class_search->set_icon(get_icon("ClassList","EditorIcons"));
+
+ script_forward->set_icon(get_icon("Forward","EditorIcons"));
+ script_back->set_icon(get_icon("Back","EditorIcons"));
+
+
+
+
+ }
+
+ if (p_what==NOTIFICATION_READY) {
+
+ get_tree()->connect("tree_changed",this,"_tree_changed");
+ editor->connect("request_help",this,"_request_help");
+ }
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ editor->disconnect("play_pressed",this,"_editor_play");
+ editor->disconnect("pause_pressed",this,"_editor_pause");
+ editor->disconnect("stop_pressed",this,"_editor_stop");
+
+ }
+
+ if (p_what==MainLoop::NOTIFICATION_WM_FOCUS_IN) {
+
+ _test_script_times_on_disk();
+ _update_modified_scripts_for_external_editor();
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+ }
+
+}
+
+bool ScriptEditor::can_take_away_focus() const {
+
+ int selected = tab_container->get_current_tab();
+ if (selected<0 || selected>=tab_container->get_child_count())
+ return true;
+
+ ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
+ if (!current)
+ return true;
+
+
+ return current->can_lose_focus_on_node_selection();
+
+}
+
+void ScriptEditor::close_builtin_scripts_from_scene(const String& p_scene) {
+
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+
+ if (se) {
+
+ Ref<Script> script = se->get_edited_script();
+ if (!script.is_valid())
+ continue;
+
+ if (script->get_path().find("::")!=-1 && script->get_path().begins_with(p_scene)) { //is an internal script and belongs to scene being closed
+ _close_tab(i);
+ i--;
+
+ }
+ }
+
+ }
+
+
+}
+
+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) {
+
+ if (p_node->get_script()==p_script)
+ return p_node;
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ const Node *result = _find_node_with_script(p_node->get_child(i),p_script);
+ if (result)
+ return result;
+ }
+
+ return NULL;
+}
+
+Dictionary ScriptEditor::get_state() const {
+
+
+ //apply_scripts();
+
+ Dictionary state;
+#if 0
+ Array paths;
+ int open=-1;
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptTextEditor *se = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
+ if (!se)
+ continue;
+
+
+ Ref<Script> script = se->get_edited_script();
+ if (script->get_path()!="" && script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) {
+
+ paths.push_back(script->get_path());
+ } else {
+
+
+ const Node *owner = _find_node_with_script(get_tree()->get_root(),script.get_ref_ptr());
+ if (owner)
+ paths.push_back(owner->get_path());
+
+ }
+
+ if (i==tab_container->get_current_tab())
+ open=i;
+ }
+
+ if (paths.size())
+ state["sources"]=paths;
+ if (open!=-1)
+ state["current"]=open;
+
+#endif
+ return state;
+}
+void ScriptEditor::set_state(const Dictionary& p_state) {
+
+#if 0
+ print_line("attempt set state: "+String(Variant(p_state)));
+
+ if (!p_state.has("sources"))
+ return; //bleh
+
+ Array sources = p_state["sources"];
+ for(int i=0;i<sources.size();i++) {
+
+ Variant source=sources[i];
+
+ Ref<Script> script;
+
+ if (source.get_type()==Variant::NODE_PATH) {
+
+
+ Node *owner=get_tree()->get_root()->get_node(source);
+ if (!owner)
+ continue;
+
+ script = owner->get_script();
+ } else if (source.get_type()==Variant::STRING) {
+
+
+ script = ResourceLoader::load(source,"Script");
+ }
+
+
+ if (script.is_null()) //ah well..
+ continue;
+
+ editor->call("_resource_selected",script);
+ }
+
+ if (p_state.has("current")) {
+ tab_container->set_current_tab(p_state["current"]);
+ }
+#endif
+
+}
+void ScriptEditor::clear() {
+#if 0
+ List<ScriptTextEditor*> stes;
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptTextEditor *se = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
+ if (!se)
+ continue;
+ stes.push_back(se);
+
+ }
+
+ while(stes.size()) {
+
+ memdelete(stes.front()->get());
+ stes.pop_front();
+ }
+
+ int idx = tab_container->get_current_tab();
+ if (idx>=tab_container->get_child_count())
+ idx=tab_container->get_child_count()-1;
+ if (idx>=0) {
+ tab_container->set_current_tab(idx);
+ script_list->select( script_list->find_metadata(idx) );
+ }
+
+#endif
+
+
+}
+
+
+void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se)
+ continue;
+
+ List<int> bpoints;
+ se->get_breakpoints(&bpoints);
+ Ref<Script> script = se->get_edited_script();
+ String base = script->get_path();
+ ERR_CONTINUE( base.begins_with("local://") || base=="" );
+
+ for(List<int>::Element *E=bpoints.front();E;E=E->next()) {
+
+ p_breakpoints->push_back(base+":"+itos(E->get()+1));
+ }
+ }
+
+}
+
+
+
+
+
+void ScriptEditor::ensure_focus_current() {
+
+ if (!is_inside_tree())
+ return;
+
+ int cidx = tab_container->get_current_tab();
+ if (cidx<0 || cidx>=tab_container->get_tab_count());
+ Control *c = tab_container->get_child(cidx)->cast_to<Control>();
+ if (!c)
+ return;
+ ScriptEditorBase *se = c->cast_to<ScriptEditorBase>();
+ if (!se)
+ return;
+ se->ensure_focus();
+}
+
+void ScriptEditor::_script_selected(int p_idx) {
+
+ grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(1); //amazing hack, simply amazing
+
+ _go_to_tab(script_list->get_item_metadata(p_idx));
+ grab_focus_block=false;
+}
+
+void ScriptEditor::ensure_select_current() {
+
+
+ if (tab_container->get_child_count() && tab_container->get_current_tab()>=0) {
+
+ Node *current = tab_container->get_child(tab_container->get_current_tab());
+
+
+ ScriptEditorBase *se = current->cast_to<ScriptEditorBase>();
+ if (se) {
+
+ Ref<Script> script = se->get_edited_script();
+
+ if (!grab_focus_block && is_visible_in_tree())
+ se->ensure_focus();
+
+
+ //edit_menu->show();
+ //search_menu->show();
+
+
+ }
+
+ EditorHelp *eh = current->cast_to<EditorHelp>();
+
+ if (eh) {
+ //edit_menu->hide();
+ //search_menu->hide();
+ //script_search_menu->show();
+
+ }
+ }
+
+ _update_selected_editor_menu();
+
+
+
+}
+
+void ScriptEditor::_find_scripts(Node* p_base, Node* p_current, Set<Ref<Script> > &used) {
+ if (p_current!=p_base && p_current->get_owner()!=p_base)
+ return;
+
+ if (p_current->get_script_instance()) {
+ Ref<Script> scr = p_current->get_script();
+ if (scr.is_valid())
+ used.insert(scr);
+ }
+
+ for(int i=0;i<p_current->get_child_count();i++) {
+ _find_scripts(p_base,p_current->get_child(i),used);
+ }
+
+}
+
+struct _ScriptEditorItemData {
+
+ String name;
+ String sort_key;
+ Ref<Texture> icon;
+ int index;
+ String tooltip;
+ bool used;
+ int category;
+
+
+ bool operator<(const _ScriptEditorItemData& id) const {
+
+ return category==id.category?sort_key<id.sort_key:category<id.category;
+ }
+
+};
+
+
+void ScriptEditor::_update_script_colors() {
+
+ bool script_temperature_enabled = EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_enabled");
+ bool highlight_current = EditorSettings::get_singleton()->get("text_editor/open_scripts/highlight_current_script");
+
+ int hist_size = EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_history_size");
+ Color hot_color=EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_hot_color");
+ Color cold_color=EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_cold_color");
+
+ for(int i=0;i<script_list->get_item_count();i++) {
+
+ int c = script_list->get_item_metadata(i);
+ Node *n = tab_container->get_child(c);
+ if (!n)
+ continue;
+
+ script_list->set_item_custom_bg_color(i,Color(0,0,0,0));
+
+ bool current = tab_container->get_current_tab() == c;
+ if (current && highlight_current) {
+ script_list->set_item_custom_bg_color(i, EditorSettings::get_singleton()->get("text_editor/open_scripts/current_script_background_color"));
+
+ } else if (script_temperature_enabled) {
+
+ if (!n->has_meta("__editor_pass")) {
+ continue;
+ }
+
+ int pass=n->get_meta("__editor_pass");
+ int h = edit_pass - pass;
+ if (h>hist_size) {
+ continue;
+ }
+ int non_zero_hist_size = ( hist_size == 0 ) ? 1 : hist_size;
+ float v = Math::ease((edit_pass-pass)/float(non_zero_hist_size),0.4);
+
+ script_list->set_item_custom_bg_color(i,hot_color.linear_interpolate(cold_color,v));
+ }
+ }
+}
+
+void ScriptEditor::_update_script_names() {
+
+ if (restoring_layout)
+ return;
+
+ waiting_update_names=false;
+ Set<Ref<Script> > used;
+ Node* edited = EditorNode::get_singleton()->get_edited_scene();
+ if (edited) {
+ _find_scripts(edited,edited,used);
+ }
+
+ script_list->clear();
+ bool split_script_help = EditorSettings::get_singleton()->get("text_editor/open_scripts/group_help_pages");
+ ScriptSortBy sort_by = (ScriptSortBy) (int) EditorSettings::get_singleton()->get("text_editor/open_scripts/sort_scripts_by");
+ ScriptListName display_as = (ScriptListName) (int) EditorSettings::get_singleton()->get("text_editor/open_scripts/list_script_names_as");
+
+ Vector<_ScriptEditorItemData> sedata;
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (se) {
+
+ String name = se->get_name();
+ Ref<Texture> icon = se->get_icon();
+ String path = se->get_edited_script()->get_path();
+
+ _ScriptEditorItemData sd;
+ sd.icon=icon;
+ sd.name=name;
+ sd.tooltip=path;
+ sd.index=i;
+ sd.used=used.has(se->get_edited_script());
+ sd.category=0;
+
+ switch (sort_by) {
+ case SORT_BY_NAME: {
+ sd.sort_key=name.to_lower();
+ } break;
+ case SORT_BY_PATH: {
+ sd.sort_key=path;
+ } break;
+ }
+
+ switch (display_as) {
+ case DISPLAY_NAME: {
+ sd.name=name;
+ } break;
+ case DISPLAY_DIR_AND_NAME: {
+ if (!path.get_base_dir().get_file().empty()) {
+ sd.name=path.get_base_dir().get_file() + "/" + name;
+ } else {
+ sd.name=name;
+ }
+ } break;
+ case DISPLAY_FULL_PATH: {
+ sd.name=path;
+ } break;
+ }
+
+
+ sedata.push_back(sd);
+ }
+
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+ if (eh) {
+
+ String name = eh->get_class();
+ Ref<Texture> icon = get_icon("Help","EditorIcons");
+ String tooltip = name+" Class Reference";
+
+ _ScriptEditorItemData sd;
+ sd.icon=icon;
+ sd.name=name;
+ sd.sort_key=name;
+ sd.tooltip=tooltip;
+ sd.index=i;
+ sd.used=false;
+ sd.category=split_script_help?1:0;
+ sedata.push_back(sd);
+
+ }
+
+ }
+
+ sedata.sort();
+
+ for(int i=0;i<sedata.size();i++) {
+
+ script_list->add_item(sedata[i].name,sedata[i].icon);
+ int index = script_list->get_item_count()-1;
+ script_list->set_item_tooltip(index,sedata[i].tooltip);
+ script_list->set_item_metadata(index,sedata[i].index);
+ if (sedata[i].used) {
+
+ script_list->set_item_custom_bg_color(index,Color(88/255.0,88/255.0,60/255.0));
+ }
+ if (tab_container->get_current_tab()==sedata[i].index) {
+ script_list->select(index);
+ script_name_label->set_text(sedata[i].name);
+ script_icon->set_texture(sedata[i].icon);
+
+ }
+ }
+
+ _update_script_colors();
+
+
+
+
+}
+
+
+
+void ScriptEditor::edit(const Ref<Script>& p_script, bool p_grab_focus) {
+
+ if (p_script.is_null())
+ return;
+
+ // refuse to open built-in if scene is not loaded
+
+
+
+
+ // see if already has it
+
+ bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
+
+ if (p_script->get_path().is_resource_file() && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
+
+ String path = EditorSettings::get_singleton()->get("text_editor/external/exec_path");
+ String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags");
+ List<String> args;
+ flags=flags.strip_edges();
+ if (flags!=String()) {
+ Vector<String> flagss = flags.split(" ",false);
+ for(int i=0;i<flagss.size();i++)
+ args.push_back(flagss[i]);
+ }
+
+ args.push_back(GlobalConfig::get_singleton()->globalize_path(p_script->get_path()));
+ Error err = OS::get_singleton()->execute(path,args,false);
+ if (err==OK)
+ return;
+ WARN_PRINT("Couldn't open external text editor, using internal");
+ }
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se)
+ continue;
+
+ if (se->get_edited_script()==p_script) {
+
+ if (open_dominant || !EditorNode::get_singleton()->is_changing_scene()) {
+ if (tab_container->get_current_tab()!=i) {
+ _go_to_tab(i);
+ script_list->select( script_list->find_metadata(i) );
+ }
+ if (is_visible_in_tree())
+ se->ensure_focus();
+ }
+ return;
+ }
+ }
+
+ // doesn't have it, make a new one
+
+ ScriptEditorBase *se;
+
+ for(int i=script_editor_func_count-1;i>=0;i--) {
+ se = script_editor_funcs[i](p_script);
+ if (se)
+ break;
+ }
+ ERR_FAIL_COND(!se);
+ tab_container->add_child(se);
+
+ se->set_edited_script(p_script);
+ se->set_tooltip_request_func("_get_debug_tooltip",this);
+ if (se->get_edit_menu()) {
+ se->get_edit_menu()->hide();
+ menu_hb->add_child(se->get_edit_menu());
+ menu_hb->move_child(se->get_edit_menu(),1);
+ }
+
+
+ if (p_grab_focus) {
+ _go_to_tab(tab_container->get_tab_count()-1);
+ }
+
+
+
+
+
+ _update_script_names();
+ _save_layout();
+ se->connect("name_changed",this,"_update_script_names");
+ se->connect("request_help_search",this,"_help_search");
+ se->connect("request_open_script_at_line",this,"_goto_script_line");
+ se->connect("go_to_help",this,"_help_class_goto");
+ se->connect("request_save_history",this,"_save_history");
+
+
+
+
+ //test for modification, maybe the script was not edited but was loaded
+
+ _test_script_times_on_disk(p_script);
+ _update_modified_scripts_for_external_editor(p_script);
+
+}
+
+void ScriptEditor::save_all_scripts() {
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se)
+ continue;
+
+
+ if (!se->is_unsaved())
+ continue;
+
+ if (trim_trailing_whitespace_on_save) {
+ se->trim_trailing_whitespace();
+ }
+
+ Ref<Script> script = se->get_edited_script();
+ if (script.is_valid())
+ se->apply_code();
+
+ if (script->get_path()!="" && script->get_path().find("local://")==-1 &&script->get_path().find("::")==-1) {
+ //external script, save it
+
+ editor->save_resource(script);
+ //ResourceSaver::save(script->get_path(),script);
+
+ }
+
+ }
+
+ _update_script_names();
+
+}
+
+void ScriptEditor::apply_scripts() const {
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se)
+ continue;
+ se->apply_code();
+ }
+
+}
+
+void ScriptEditor::_editor_play() {
+
+ debugger->start();
+ debug_menu->get_popup()->grab_focus();
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), false );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
+
+ //debugger_gui->start_listening(Globals::get_singleton()->get("debug/debug_port"));
+}
+
+void ScriptEditor::_editor_pause() {
+
+
+}
+void ScriptEditor::_editor_stop() {
+
+ debugger->stop();
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), true );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se) {
+
+ continue;
+ }
+
+ se->set_debugger_active(false);
+ }
+}
+
+
+void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const PoolStringArray& p_args) {
+
+ //print_line("add callback! hohoho"); kinda sad to remove this
+ ERR_FAIL_COND(!p_obj);
+ Ref<Script> script = p_obj->get_script();
+ ERR_FAIL_COND( !script.is_valid() );
+
+ editor->push_item(script.ptr());
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se)
+ continue;
+ if (se->get_edited_script()!=script)
+ continue;
+
+ se->add_callback(p_function,p_args);
+
+ _go_to_tab(i);
+
+ script_list->select( script_list->find_metadata(i) );
+
+ break;
+
+ }
+
+}
+
+void ScriptEditor::_save_layout() {
+
+ if (restoring_layout) {
+ return;
+ }
+
+ editor->save_layout();
+}
+
+void ScriptEditor::_editor_settings_changed() {
+
+ trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/files/trim_trailing_whitespace_on_save");
+ float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
+ if (autosave_time>0) {
+ autosave_timer->set_wait_time(autosave_time);
+ autosave_timer->start();
+ } else {
+ autosave_timer->stop();
+ }
+
+ if (current_theme == "") {
+ current_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
+ } else if (current_theme != EditorSettings::get_singleton()->get("text_editor/theme/color_theme")) {
+ current_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
+ EditorSettings::get_singleton()->load_text_editor_theme();
+ }
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (!se)
+ continue;
+
+ se->update_settings();
+ }
+ _update_script_colors();
+ _update_script_names();
+
+ ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save",true));
+
+}
+
+void ScriptEditor::_autosave_scripts() {
+
+ save_all_scripts();
+}
+
+void ScriptEditor::_tree_changed() {
+
+ if (waiting_update_names)
+ return;
+
+ waiting_update_names=true;
+ call_deferred("_update_script_names");
+}
+
+void ScriptEditor::_script_split_dragged(float) {
+
+ _save_layout();
+}
+
+void ScriptEditor::_unhandled_input(const InputEvent& p_event) {
+ if (p_event.key.pressed || !is_visible_in_tree()) return;
+ if (ED_IS_SHORTCUT("script_editor/next_script", p_event)) {
+ int next_tab = script_list->get_current() + 1;
+ next_tab %= script_list->get_item_count();
+ _go_to_tab(script_list->get_item_metadata(next_tab));
+ _update_script_names();
+ }
+ if (ED_IS_SHORTCUT("script_editor/prev_script", p_event)) {
+ int next_tab = script_list->get_current() - 1;
+ next_tab = next_tab >= 0 ? next_tab : script_list->get_item_count() - 1;
+ _go_to_tab(script_list->get_item_metadata(next_tab));
+ _update_script_names();
+ }
+}
+
+void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
+
+ if (!bool(EDITOR_DEF("text_editor/files/restore_scripts_on_load",true))) {
+ return;
+ }
+
+ if (!p_layout->has_section_key("ScriptEditor","open_scripts") && !p_layout->has_section_key("ScriptEditor","open_help"))
+ return;
+
+ Array scripts = p_layout->get_value("ScriptEditor","open_scripts");
+ Array helps;
+ if (p_layout->has_section_key("ScriptEditor","open_help"))
+ helps=p_layout->get_value("ScriptEditor","open_help");
+
+ restoring_layout=true;
+
+ for(int i=0;i<scripts.size();i++) {
+
+ String path = scripts[i];
+ if (!FileAccess::exists(path))
+ continue;
+ Ref<Script> scr = ResourceLoader::load(path);
+ if (scr.is_valid()) {
+ edit(scr);
+ }
+ }
+
+ for(int i=0;i<helps.size();i++) {
+
+ String path = helps[i];
+ _help_class_open(path);
+ }
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+ tab_container->get_child(i)->set_meta("__editor_pass",Variant());
+ }
+
+
+ if (p_layout->has_section_key("ScriptEditor","split_offset")) {
+ script_split->set_split_offset(p_layout->get_value("ScriptEditor","split_offset"));
+ }
+
+ restoring_layout=false;
+
+ _update_script_names();
+}
+
+void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
+
+ Array scripts;
+ Array helps;
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (se) {
+
+ String path = se->get_edited_script()->get_path();
+ if (!path.is_resource_file())
+ continue;
+
+ scripts.push_back(path);
+ }
+
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+
+ if (eh) {
+
+ helps.push_back(eh->get_class());
+ }
+
+
+ }
+
+ p_layout->set_value("ScriptEditor","open_scripts",scripts);
+ p_layout->set_value("ScriptEditor","open_help",helps);
+ p_layout->set_value("ScriptEditor","split_offset",script_split->get_split_offset());
+}
+
+
+void ScriptEditor::_help_class_open(const String& p_class) {
+
+ if (p_class=="")
+ return;
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+
+ if (eh && eh->get_class()==p_class) {
+
+ _go_to_tab(i);
+ _update_script_names();
+ return;
+ }
+ }
+
+ EditorHelp * eh = memnew( EditorHelp );
+
+
+ eh->set_name(p_class);
+ tab_container->add_child(eh);
+ _go_to_tab(tab_container->get_tab_count()-1);
+ eh->go_to_class(p_class,0);
+ eh->connect("go_to_help",this,"_help_class_goto");
+ _update_script_names();
+ _save_layout();
+}
+
+void ScriptEditor::_help_class_goto(const String& p_desc) {
+
+ String cname=p_desc.get_slice(":",1);
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+
+ if (eh && eh->get_class()==cname) {
+
+ _go_to_tab(i);
+ eh->go_to_help(p_desc);
+ _update_script_names();
+ return;
+ }
+ }
+
+ EditorHelp * eh = memnew( EditorHelp );
+
+ eh->set_name(cname);
+ tab_container->add_child(eh);
+ _go_to_tab(tab_container->get_tab_count()-1);
+ eh->go_to_help(p_desc);
+ eh->connect("go_to_help",this,"_help_class_goto");
+ _update_script_names();
+ _save_layout();
+}
+
+void ScriptEditor::_update_selected_editor_menu() {
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ bool current = tab_container->get_current_tab() == i;
+
+ ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+ if (se && se->get_edit_menu()) {
+
+ if (current)
+ se->get_edit_menu()->show();
+ else
+ se->get_edit_menu()->hide();
+ }
+
+ }
+
+ EditorHelp *eh=tab_container->get_current_tab_control()->cast_to<EditorHelp>();
+ if (eh) {
+ script_search_menu->show();
+ } else {
+ script_search_menu->hide();
+ }
+}
+
+void ScriptEditor::_update_history_pos(int p_new_pos) {
+
+ Node *n = tab_container->get_current_tab_control();
+
+ if (n->cast_to<ScriptEditorBase>()) {
+
+ history[history_pos].state=n->cast_to<ScriptEditorBase>()->get_edit_state();
+ }
+ if (n->cast_to<EditorHelp>()) {
+
+ history[history_pos].state=n->cast_to<EditorHelp>()->get_scroll();
+ }
+
+ history_pos=p_new_pos;
+ tab_container->set_current_tab(history[history_pos].control->get_index());
+
+ n = history[history_pos].control;
+
+ if (n->cast_to<ScriptEditorBase>()) {
+
+ n->cast_to<ScriptEditorBase>()->set_edit_state(history[history_pos].state);
+ n->cast_to<ScriptEditorBase>()->ensure_focus();
+ }
+
+ if (n->cast_to<EditorHelp>()) {
+
+ n->cast_to<EditorHelp>()->set_scroll(history[history_pos].state);
+ n->cast_to<EditorHelp>()->set_focused();
+ }
+
+ n->set_meta("__editor_pass",++edit_pass);
+ _update_script_names();
+ _update_history_arrows();
+ _update_selected_editor_menu();
+
+}
+
+void ScriptEditor::_history_forward() {
+
+ if (history_pos<history.size()-1) {
+ _update_history_pos(history_pos+1);
+ }
+}
+
+void ScriptEditor::_history_back(){
+
+ if (history_pos>0) {
+ _update_history_pos(history_pos-1);
+ }
+
+}
+void ScriptEditor::set_scene_root_script( Ref<Script> p_script ) {
+
+ bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
+
+ if (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")))
+ return;
+
+ if (open_dominant && p_script.is_valid() && _can_open_in_editor(p_script.ptr())) {
+ edit(p_script);
+ }
+}
+
+bool ScriptEditor::script_go_to_method(Ref<Script> p_script, const String& p_method) {
+
+
+ for (int i=0;i<tab_container->get_child_count();i++) {
+ ScriptEditorBase *current = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
+
+ if (current && current->get_edited_script()==p_script) {
+ if (current->goto_method(p_method)) {
+ edit(p_script);
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+void ScriptEditor::set_live_auto_reload_running_scripts(bool p_enabled) {
+
+ auto_reload_running_scripts=p_enabled;
+}
+
+void ScriptEditor::_help_search(String p_text) {
+ help_search_dialog->popup(p_text);
+}
+
+void ScriptEditor::_open_script_request(const String& p_path) {
+
+ Ref<Script> script = ResourceLoader::load(p_path);
+ if (script.is_valid()) {
+ script_editor->edit(script,false);
+ }
+}
+
+int ScriptEditor::script_editor_func_count=0;
+CreateScriptEditorFunc ScriptEditor::script_editor_funcs[ScriptEditor::SCRIPT_EDITOR_FUNC_MAX];
+
+void ScriptEditor::register_create_script_editor_function(CreateScriptEditorFunc p_func) {
+
+ ERR_FAIL_COND(script_editor_func_count==SCRIPT_EDITOR_FUNC_MAX);
+ script_editor_funcs[script_editor_func_count++]=p_func;
+}
+
+void ScriptEditor::_bind_methods() {
+
+ ClassDB::bind_method("_file_dialog_action",&ScriptEditor::_file_dialog_action);
+ ClassDB::bind_method("_tab_changed",&ScriptEditor::_tab_changed);
+ ClassDB::bind_method("_menu_option",&ScriptEditor::_menu_option);
+ ClassDB::bind_method("_close_current_tab",&ScriptEditor::_close_current_tab);
+ ClassDB::bind_method("_close_discard_current_tab", &ScriptEditor::_close_discard_current_tab);
+ ClassDB::bind_method("_close_docs_tab", &ScriptEditor::_close_docs_tab);
+ ClassDB::bind_method("_close_all_tabs", &ScriptEditor::_close_all_tabs);
+ ClassDB::bind_method("_editor_play",&ScriptEditor::_editor_play);
+ ClassDB::bind_method("_editor_pause",&ScriptEditor::_editor_pause);
+ ClassDB::bind_method("_editor_stop",&ScriptEditor::_editor_stop);
+ ClassDB::bind_method("_add_callback",&ScriptEditor::_add_callback);
+ ClassDB::bind_method("_reload_scripts",&ScriptEditor::_reload_scripts);
+ ClassDB::bind_method("_resave_scripts",&ScriptEditor::_resave_scripts);
+ ClassDB::bind_method("_res_saved_callback",&ScriptEditor::_res_saved_callback);
+ ClassDB::bind_method("_goto_script_line",&ScriptEditor::_goto_script_line);
+ ClassDB::bind_method("_goto_script_line2",&ScriptEditor::_goto_script_line2);
+ ClassDB::bind_method("_help_search",&ScriptEditor::_help_search);
+ ClassDB::bind_method("_save_history",&ScriptEditor::_save_history);
+
+
+
+ ClassDB::bind_method("_breaked",&ScriptEditor::_breaked);
+ ClassDB::bind_method("_show_debugger",&ScriptEditor::_show_debugger);
+ ClassDB::bind_method("_get_debug_tooltip",&ScriptEditor::_get_debug_tooltip);
+ ClassDB::bind_method("_autosave_scripts",&ScriptEditor::_autosave_scripts);
+ ClassDB::bind_method("_editor_settings_changed",&ScriptEditor::_editor_settings_changed);
+ ClassDB::bind_method("_update_script_names",&ScriptEditor::_update_script_names);
+ ClassDB::bind_method("_tree_changed",&ScriptEditor::_tree_changed);
+ ClassDB::bind_method("_script_selected",&ScriptEditor::_script_selected);
+ ClassDB::bind_method("_script_created",&ScriptEditor::_script_created);
+ ClassDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged);
+ ClassDB::bind_method("_help_class_open",&ScriptEditor::_help_class_open);
+ ClassDB::bind_method("_help_class_goto",&ScriptEditor::_help_class_goto);
+ ClassDB::bind_method("_request_help",&ScriptEditor::_help_class_open);
+ ClassDB::bind_method("_history_forward",&ScriptEditor::_history_forward);
+ ClassDB::bind_method("_history_back",&ScriptEditor::_history_back);
+ ClassDB::bind_method("_live_auto_reload_running_scripts",&ScriptEditor::_live_auto_reload_running_scripts);
+ ClassDB::bind_method("_unhandled_input",&ScriptEditor::_unhandled_input);
+
+}
+
+ScriptEditor::ScriptEditor(EditorNode *p_editor) {
+
+ current_theme = "";
+
+ completion_cache = memnew( EditorScriptCodeCompletionCache );
+ restoring_layout=false;
+ waiting_update_names=false;
+ pending_auto_reload=false;
+ auto_reload_running_scripts=false;
+ editor=p_editor;
+
+ menu_hb = memnew( HBoxContainer );
+ add_child(menu_hb);
+
+
+ script_split = memnew( HSplitContainer );
+ 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(0,0));
+ script_split->set_split_offset(140);
+
+ tab_container = memnew( TabContainer );
+ tab_container->set_tabs_visible(false);
+ script_split->add_child(tab_container);
+
+
+ tab_container->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ ED_SHORTCUT("script_editor/next_script", TTR("Next script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_GREATER);
+ ED_SHORTCUT("script_editor/prev_script", TTR("Previous script"), KEY_MASK_CMD | KEY_LESS);
+ set_process_unhandled_input(true);
+
+ file_menu = memnew( MenuButton );
+ menu_hb->add_child(file_menu);
+ file_menu->set_text(TTR("File"));
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New")), FILE_NEW);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open")), FILE_OPEN);
+ file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KEY_MASK_ALT|KEY_MASK_CMD|KEY_S), FILE_SAVE);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As..")), FILE_SAVE_AS);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_MASK_ALT|KEY_S), FILE_SAVE_ALL);
+ file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_R), FILE_TOOL_RELOAD_SOFT);
+ file_menu->get_popup()->add_separator();
+
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Prev"), KEY_MASK_ALT|KEY_LEFT), WINDOW_PREV);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KEY_MASK_ALT|KEY_RIGHT), WINDOW_NEXT);
+ file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/import_theme", TTR("Import Theme")), FILE_IMPORT_THEME);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_theme", TTR("Reload Theme")), FILE_RELOAD_THEME);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_theme", TTR("Save Theme")), FILE_SAVE_THEME);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As")), FILE_SAVE_THEME_AS);
+ file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KEY_MASK_CMD | KEY_W), FILE_CLOSE);
+ file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_all", TTR("Close All")), CLOSE_ALL);
+ file_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+
+
+
+ script_search_menu = memnew( MenuButton );
+ menu_hb->add_child(script_search_menu);
+ script_search_menu->set_text(TTR("Search"));
+ script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find.."), KEY_MASK_CMD|KEY_F), HELP_SEARCH_FIND);
+ script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), HELP_SEARCH_FIND_NEXT);
+ script_search_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+ script_search_menu->hide();
+
+
+ debug_menu = memnew( MenuButton );
+ menu_hb->add_child(debug_menu);
+ debug_menu->set_text(TTR("Debug"));
+ debug_menu->get_popup()->add_separator();
+ debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_over", TTR("Step Over"), KEY_F10), DEBUG_NEXT);
+ debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_into", TTR("Step Into"), KEY_F11), DEBUG_STEP);
+ debug_menu->get_popup()->add_separator();
+ debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/break", TTR("Break")), DEBUG_BREAK);
+ debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/continue", TTR("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_shortcut(ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")), DEBUG_SHOW_KEEP_OPEN);
+ debug_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true);
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), true );
+ debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
+
+
+#if 0
+ window_menu = memnew( MenuButton );
+ menu_hb->add_child(window_menu);
+ window_menu->set_text(TTR("Window"));
+ window_menu->get_popup()->add_item(TTR("Close"),WINDOW_CLOSE,KEY_MASK_CMD|KEY_W);
+ window_menu->get_popup()->add_separator();
+ window_menu->get_popup()->add_item(TTR("Move Left"),WINDOW_MOVE_LEFT,KEY_MASK_CMD|KEY_LEFT);
+ window_menu->get_popup()->add_item(TTR("Move Right"),WINDOW_MOVE_RIGHT,KEY_MASK_CMD|KEY_RIGHT);
+ window_menu->get_popup()->add_separator();
+ window_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+
+#endif
+
+
+ menu_hb->add_spacer();
+
+
+ script_icon = memnew( TextureRect );
+ menu_hb->add_child(script_icon);
+ script_name_label = memnew( Label );
+ menu_hb->add_child(script_name_label);
+
+ script_icon->hide();
+ script_name_label->hide();
+
+ menu_hb->add_spacer();
+
+ site_search = memnew( ToolButton );
+ site_search->set_text(TTR("Tutorials"));
+ site_search->connect("pressed",this,"_menu_option",varray(SEARCH_WEBSITE));
+ menu_hb->add_child(site_search);
+ site_search->set_tooltip(TTR("Open https://godotengine.org at tutorials section."));
+
+ class_search = memnew( ToolButton );
+ class_search->set_text(TTR("Classes"));
+ class_search->connect("pressed",this,"_menu_option",varray(SEARCH_CLASSES));
+ menu_hb->add_child(class_search);
+ class_search->set_tooltip(TTR("Search the class hierarchy."));
+
+ help_search = memnew( ToolButton );
+ help_search->set_text(TTR("Search Help"));
+ help_search->connect("pressed",this,"_menu_option",varray(SEARCH_HELP));
+ menu_hb->add_child(help_search);
+ help_search->set_tooltip(TTR("Search the reference documentation."));
+
+ menu_hb->add_child( memnew( VSeparator) );
+
+ script_back = memnew( ToolButton );
+ script_back->connect("pressed",this,"_history_back");
+ menu_hb->add_child(script_back);
+ script_back->set_disabled(true);
+ script_back->set_tooltip(TTR("Go to previous edited document."));
+
+ script_forward = memnew( ToolButton );
+ script_forward->connect("pressed",this,"_history_forward");
+ menu_hb->add_child(script_forward);
+ script_forward->set_disabled(true);
+ script_forward->set_tooltip(TTR("Go to next edited document."));
+
+
+
+ tab_container->connect("tab_changed", this,"_tab_changed");
+
+ erase_tab_confirm = memnew( ConfirmationDialog );
+ erase_tab_confirm->get_ok()->set_text(TTR("Save"));
+ erase_tab_confirm->add_button(TTR("Discard"), OS::get_singleton()->get_swap_ok_cancel(), "discard");
+ erase_tab_confirm->connect("confirmed", this,"_close_current_tab");
+ erase_tab_confirm->connect("custom_action", this, "_close_discard_current_tab");
+ add_child(erase_tab_confirm);
+
+ script_create_dialog = memnew(ScriptCreateDialog);
+ script_create_dialog->set_title(TTR("Create Script"));
+ add_child(script_create_dialog);
+ script_create_dialog->connect("script_created", this, "_script_created");
+
+ file_dialog_option = -1;
+ file_dialog = memnew( EditorFileDialog );
+ add_child(file_dialog);
+ file_dialog->connect("file_selected", this,"_file_dialog_action");
+
+
+ debugger = memnew( ScriptEditorDebugger(editor) );
+ debugger->connect("goto_script_line",this,"_goto_script_line");
+ debugger->connect("show_debugger",this,"_show_debugger");
+
+ disk_changed = memnew( ConfirmationDialog );
+ {
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ disk_changed->add_child(vbc);
+ //disk_changed->set_child_rect(vbc);
+
+ Label *dl = memnew( Label );
+ dl->set_text(TTR("The following files are newer on disk.\nWhat action should be taken?:"));
+ vbc->add_child(dl);
+
+ disk_changed_list = memnew( Tree );
+ vbc->add_child(disk_changed_list);
+ disk_changed_list->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ disk_changed->connect("confirmed",this,"_reload_scripts");
+ disk_changed->get_ok()->set_text(TTR("Reload"));
+
+ disk_changed->add_button(TTR("Resave"),!OS::get_singleton()->get_swap_ok_cancel(),"resave");
+ disk_changed->connect("custom_action",this,"_resave_scripts");
+
+
+ }
+
+ add_child(disk_changed);
+
+ script_editor=this;
+
+
+ Button *db = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Debugger"),debugger);
+ debugger->set_tool_button(db);
+
+
+ debugger->connect("breaked",this,"_breaked");
+
+ autosave_timer = memnew( Timer );
+ autosave_timer->set_one_shot(false);
+ add_child(autosave_timer);
+
+ grab_focus_block=false;
+
+ help_search_dialog = memnew( EditorHelpSearch );
+ add_child(help_search_dialog);
+ help_search_dialog->connect("go_to_help",this,"_help_class_goto");
+
+
+ help_index = memnew( EditorHelpIndex );
+ add_child(help_index);
+ help_index->connect("open_class",this,"_help_class_open");
+
+ history_pos=-1;
+ //debugger_gui->hide();
+
+ edit_pass=0;
+ trim_trailing_whitespace_on_save = false;
+
+ ScriptServer::edit_request_func=_open_script_request;
+}
+
+
+ScriptEditor::~ScriptEditor() {
+
+ memdelete(completion_cache);
+}
+
+void ScriptEditorPlugin::edit(Object *p_object) {
+
+ if (!p_object->cast_to<Script>())
+ return;
+
+ script_editor->edit(p_object->cast_to<Script>());
+
+}
+
+bool ScriptEditorPlugin::handles(Object *p_object) const {
+
+ if (p_object->cast_to<Script>()) {
+
+ bool valid = _can_open_in_editor(p_object->cast_to<Script>());
+
+ if (!valid) { //user tried to open it by clicking
+ EditorNode::get_singleton()->show_warning(TTR("Built-in scripts can only be edited when the scene they belong to is loaded"));
+ }
+ return valid;
+ }
+
+ return p_object->is_class("Script");
+}
+
+void ScriptEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ script_editor->show();
+ script_editor->set_process(true);
+ script_editor->ensure_select_current();
+ } else {
+
+ script_editor->hide();
+ script_editor->set_process(false);
+ }
+
+}
+
+void ScriptEditorPlugin::selected_notify() {
+
+ script_editor->ensure_select_current();
+}
+
+Dictionary ScriptEditorPlugin::get_state() const {
+
+ return script_editor->get_state();
+}
+
+void ScriptEditorPlugin::set_state(const Dictionary& p_state) {
+
+ script_editor->set_state(p_state);
+}
+void ScriptEditorPlugin::clear() {
+
+ script_editor->clear();
+}
+
+void ScriptEditorPlugin::save_external_data() {
+
+ script_editor->save_all_scripts();
+}
+
+void ScriptEditorPlugin::apply_changes() {
+
+ script_editor->apply_scripts();
+}
+
+void ScriptEditorPlugin::restore_global_state() {
+
+
+}
+
+void ScriptEditorPlugin::save_global_state() {
+
+}
+
+void ScriptEditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
+
+ script_editor->set_window_layout(p_layout);
+}
+
+void ScriptEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout){
+
+ script_editor->get_window_layout(p_layout);
+}
+
+
+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;
+ script_editor = memnew( ScriptEditor(p_node) );
+ editor->get_viewport()->add_child(script_editor);
+ script_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ script_editor->hide();
+
+ EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change",true);
+ ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save",true));
+ EDITOR_DEF("text_editor/files/open_dominant_script_on_scene_change",true);
+ EDITOR_DEF("text_editor/external/use_external_editor",false);
+ EDITOR_DEF("text_editor/external/exec_path","");
+ EDITOR_DEF("text_editor/open_scripts/script_temperature_enabled",true);
+ EDITOR_DEF("text_editor/open_scripts/highlight_current_script", true);
+ EDITOR_DEF("text_editor/open_scripts/script_temperature_history_size",15);
+ EDITOR_DEF("text_editor/open_scripts/script_temperature_hot_color",Color(1,0,0,0.3));
+ EDITOR_DEF("text_editor/open_scripts/script_temperature_cold_color",Color(0,0,1,0.3));
+ EDITOR_DEF("text_editor/open_scripts/current_script_background_color",Color(0.81,0.81,0.14,0.63));
+ EDITOR_DEF("text_editor/open_scripts/group_help_pages",true);
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT,"text_editor/open_scripts/sort_scripts_by",PROPERTY_HINT_ENUM,"Name,Path"));
+ EDITOR_DEF("text_editor/open_scripts/sort_scripts_by",0);
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT,"text_editor/open_scripts/list_script_names_as",PROPERTY_HINT_ENUM,"Name,Parent Directory And Name,Full Path"));
+ EDITOR_DEF("text_editor/open_scripts/list_script_names_as",0);
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"text_editor/external/exec_path",PROPERTY_HINT_GLOBAL_FILE));
+ EDITOR_DEF("text_editor/external/exec_flags","");
+
+
+}
+
+
+ScriptEditorPlugin::~ScriptEditorPlugin()
+{
+}
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
new file mode 100644
index 0000000000..bf5316363c
--- /dev/null
+++ b/editor/plugins/script_editor_plugin.h
@@ -0,0 +1,394 @@
+/*************************************************************************/
+/* script_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SCRIPT_EDITOR_PLUGIN_H
+#define SCRIPT_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/script_create_dialog.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/text_edit.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/tree.h"
+#include "scene/main/timer.h"
+#include "script_language.h"
+#include "editor/code_editor.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/item_list.h"
+#include "editor/editor_help.h"
+
+class ScriptEditorQuickOpen : public ConfirmationDialog {
+
+ GDCLASS(ScriptEditorQuickOpen,ConfirmationDialog )
+
+ LineEdit *search_box;
+ Tree *search_options;
+ String function;
+
+ void _update_search();
+
+ void _sbox_input(const InputEvent& p_ie);
+ Vector<String> functions;
+
+
+ void _confirmed();
+ void _text_changed(const String& p_newtext);
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void popup(const Vector<String>& p_base,bool p_dontclear=false);
+ ScriptEditorQuickOpen();
+};
+
+
+class ScriptEditorDebugger;
+
+
+
+class ScriptEditorBase : public Control {
+
+ GDCLASS( ScriptEditorBase, Control );
+protected:
+ static void _bind_methods();
+public:
+
+ virtual void apply_code()=0;
+ virtual Ref<Script> get_edited_script() const=0;
+ virtual Vector<String> get_functions()=0;
+ virtual void set_edited_script(const Ref<Script>& p_script)=0;
+ virtual void reload_text()=0;
+ virtual String get_name()=0;
+ virtual Ref<Texture> get_icon()=0;
+ virtual bool is_unsaved()=0;
+ virtual Variant get_edit_state()=0;
+ virtual void set_edit_state(const Variant& p_state)=0;
+ virtual void goto_line(int p_line,bool p_with_error=false)=0;
+ virtual void trim_trailing_whitespace()=0;
+ virtual void ensure_focus()=0;
+ virtual void tag_saved_version()=0;
+ virtual void reload(bool p_soft)=0;
+ virtual void get_breakpoints(List<int> *p_breakpoints)=0;
+ virtual bool goto_method(const String& p_method)=0;
+ virtual void add_callback(const String& p_function,PoolStringArray p_args)=0;
+ virtual void update_settings()=0;
+ virtual void set_debugger_active(bool p_active)=0;
+ virtual bool can_lose_focus_on_node_selection() { return true; }
+
+ virtual void set_tooltip_request_func(String p_method,Object* p_obj)=0;
+ virtual Control *get_edit_menu()=0;
+
+ ScriptEditorBase() {}
+};
+
+
+typedef ScriptEditorBase* (*CreateScriptEditorFunc)(const Ref<Script>& p_script);
+
+
+class EditorScriptCodeCompletionCache;
+
+class ScriptEditor : public VBoxContainer {
+
+ GDCLASS(ScriptEditor, VBoxContainer );
+
+
+ EditorNode *editor;
+ enum {
+ FILE_NEW,
+ FILE_OPEN,
+ FILE_SAVE,
+ FILE_SAVE_AS,
+ FILE_SAVE_ALL,
+ FILE_IMPORT_THEME,
+ FILE_RELOAD_THEME,
+ FILE_SAVE_THEME,
+ FILE_SAVE_THEME_AS,
+ FILE_CLOSE,
+ CLOSE_DOCS,
+ CLOSE_ALL,
+ FILE_TOOL_RELOAD,
+ FILE_TOOL_RELOAD_SOFT,
+ DEBUG_NEXT,
+ DEBUG_STEP,
+ DEBUG_BREAK,
+ DEBUG_CONTINUE,
+ DEBUG_SHOW,
+ DEBUG_SHOW_KEEP_OPEN,
+ SEARCH_HELP,
+ SEARCH_CLASSES,
+ SEARCH_WEBSITE,
+ HELP_SEARCH_FIND,
+ HELP_SEARCH_FIND_NEXT,
+ WINDOW_MOVE_LEFT,
+ WINDOW_MOVE_RIGHT,
+ WINDOW_NEXT,
+ WINDOW_PREV,
+ WINDOW_SELECT_BASE=100
+ };
+
+ enum ScriptSortBy {
+ SORT_BY_NAME,
+ SORT_BY_PATH,
+ };
+
+ enum ScriptListName {
+ DISPLAY_NAME,
+ DISPLAY_DIR_AND_NAME,
+ DISPLAY_FULL_PATH,
+ };
+
+ HBoxContainer *menu_hb;
+ MenuButton *file_menu;
+ MenuButton *edit_menu;
+ MenuButton *script_search_menu;
+ MenuButton *debug_menu;
+ Timer *autosave_timer;
+ uint64_t idle;
+
+ Button *help_search;
+ Button *site_search;
+ Button *class_search;
+ EditorHelpSearch *help_search_dialog;
+
+ ItemList *script_list;
+ HSplitContainer *script_split;
+ TabContainer *tab_container;
+ EditorFileDialog *file_dialog;
+ ConfirmationDialog *erase_tab_confirm;
+ ScriptCreateDialog *script_create_dialog;
+ ScriptEditorDebugger* debugger;
+ ToolButton *scripts_visible;
+
+ String current_theme;
+
+ TextureRect *script_icon;
+ Label *script_name_label;
+
+ ToolButton *script_back;
+ ToolButton *script_forward;
+
+ enum {
+ SCRIPT_EDITOR_FUNC_MAX=32
+ };
+
+ static int script_editor_func_count;
+ static CreateScriptEditorFunc script_editor_funcs[SCRIPT_EDITOR_FUNC_MAX];
+
+ struct ScriptHistory {
+
+ Control *control;
+ Variant state;
+ };
+
+ Vector<ScriptHistory> history;
+ int history_pos;
+
+
+ EditorHelpIndex *help_index;
+
+ void _tab_changed(int p_which);
+ void _menu_option(int p_optin);
+
+ Tree *disk_changed_list;
+ ConfirmationDialog *disk_changed;
+
+ bool restoring_layout;
+
+ String _get_debug_tooltip(const String&p_text,Node *_ste);
+
+ void _resave_scripts(const String& p_str);
+ void _reload_scripts();
+
+ bool _test_script_times_on_disk(Ref<Script> p_for_script=Ref<Script>());
+
+ void _close_tab(int p_idx, bool p_save=true);
+
+ void _close_current_tab();
+ void _close_discard_current_tab(const String& p_str);
+ void _close_docs_tab();
+ void _close_all_tabs();
+
+ void _ask_close_current_unsaved_tab(ScriptEditorBase *current);
+
+ bool grab_focus_block;
+
+ bool pending_auto_reload;
+ bool auto_reload_running_scripts;
+ void _live_auto_reload_running_scripts();
+
+ void _update_selected_editor_menu();
+
+ EditorScriptCodeCompletionCache *completion_cache;
+
+ void _editor_play();
+ void _editor_pause();
+ void _editor_stop();
+
+ int edit_pass;
+
+ void _add_callback(Object *p_obj, const String& p_function, const PoolStringArray& p_args);
+ void _res_saved_callback(const Ref<Resource>& p_res);
+
+ bool trim_trailing_whitespace_on_save;
+
+ void _trim_trailing_whitespace(TextEdit *tx);
+
+ void _goto_script_line2(int p_line);
+ void _goto_script_line(REF p_script,int p_line);
+ void _breaked(bool p_breaked,bool p_can_debug);
+ void _show_debugger(bool p_show);
+ void _update_window_menu();
+ void _script_created(Ref<Script> p_script);
+
+ void _save_layout();
+ void _editor_settings_changed();
+ void _autosave_scripts();
+
+ void _update_script_names();
+
+ void _script_selected(int p_idx);
+
+ void _find_scripts(Node* p_base, Node* p_current,Set<Ref<Script> >& used);
+
+ void _tree_changed();
+
+ void _script_split_dragged(float);
+
+ void _unhandled_input(const InputEvent& p_event);
+
+ void _help_search(String p_text);
+
+ void _history_forward();
+ void _history_back();
+
+ bool waiting_update_names;
+
+ void _help_class_open(const String& p_class);
+ void _help_class_goto(const String& p_desc);
+ void _update_history_arrows();
+ void _save_history();
+ 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(Ref<Script> p_for_script=Ref<Script>());
+
+ int file_dialog_option;
+ void _file_dialog_action(String p_file);
+
+ static void _open_script_request(const String& p_path);
+
+ static ScriptEditor *script_editor;
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ static ScriptEditor *get_singleton() { return script_editor; }
+
+ void ensure_focus_current();
+ void apply_scripts() const;
+
+ void ensure_select_current();
+ void edit(const Ref<Script>& p_script,bool p_grab_focus=true);
+
+ Dictionary get_state() const;
+ void set_state(const Dictionary& p_state);
+ void clear();
+
+ void get_breakpoints(List<String> *p_breakpoints);
+
+ //void swap_lines(TextEdit *tx, int line1, int line2);
+
+ void save_all_scripts();
+
+ void set_window_layout(Ref<ConfigFile> p_layout);
+ void get_window_layout(Ref<ConfigFile> p_layout);
+
+ void set_scene_root_script( Ref<Script> p_script );
+
+ bool script_go_to_method(Ref<Script> p_script, const String& p_method);
+
+ virtual void edited_scene_changed();
+
+ void close_builtin_scripts_from_scene(const String& p_scene);
+
+ void goto_help(const String& p_desc) { _help_class_goto(p_desc); }
+
+ bool can_take_away_focus() const;
+
+ ScriptEditorDebugger *get_debugger() { return debugger; }
+ void set_live_auto_reload_running_scripts(bool p_enabled);
+
+ static void register_create_script_editor_function(CreateScriptEditorFunc p_func);
+ ScriptEditor(EditorNode *p_editor);
+ ~ScriptEditor();
+};
+
+class ScriptEditorPlugin : public EditorPlugin {
+
+ GDCLASS( ScriptEditorPlugin, EditorPlugin );
+
+ ScriptEditor *script_editor;
+ EditorNode *editor;
+public:
+
+ virtual String get_name() const { return "Script"; }
+ bool has_main_screen() const { return true; }
+ virtual void edit(Object *p_node);
+ virtual bool handles(Object *p_node) const;
+ virtual void make_visible(bool p_visible);
+ virtual void selected_notify();
+
+ Dictionary get_state() const;
+ virtual void set_state(const Dictionary& p_state);
+ virtual void clear();
+
+ virtual void save_external_data();
+ virtual void apply_changes();
+
+ virtual void restore_global_state();
+ virtual void save_global_state();
+
+ virtual void set_window_layout(Ref<ConfigFile> p_layout);
+ virtual void get_window_layout(Ref<ConfigFile> p_layout);
+
+ virtual void get_breakpoints(List<String> *p_breakpoints);
+
+
+ virtual void edited_scene_changed();
+
+ ScriptEditorPlugin(EditorNode *p_node);
+ ~ScriptEditorPlugin();
+
+};
+
+#endif // SCRIPT_EDITOR_PLUGIN_H
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
new file mode 100644
index 0000000000..8723a863f0
--- /dev/null
+++ b/editor/plugins/script_text_editor.cpp
@@ -0,0 +1,1401 @@
+/*************************************************************************/
+/* script_text_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "script_text_editor.h"
+
+#include "editor/editor_settings.h"
+#include "os/keyboard.h"
+#include "editor/script_editor_debugger.h"
+#include "editor/editor_node.h"
+
+Vector<String> ScriptTextEditor::get_functions() {
+
+
+ String errortxt;
+ int line=-1,col;
+ TextEdit *te=code_editor->get_text_edit();
+ String text = te->get_text();
+ List<String> fnc;
+
+ if (script->get_language()->validate(text,line,col,errortxt,script->get_path(),&fnc)) {
+
+ //if valid rewrite functions to latest
+ functions.clear();
+ for (List<String>::Element *E=fnc.front();E;E=E->next()) {
+
+ functions.push_back(E->get());
+ }
+
+
+ }
+
+ return functions;
+}
+
+void ScriptTextEditor::apply_code() {
+
+ if (script.is_null())
+ return;
+ //print_line("applying code");
+ script->set_source_code(code_editor->get_text_edit()->get_text());
+ script->update_exports();
+}
+
+Ref<Script> ScriptTextEditor::get_edited_script() const {
+
+ return script;
+}
+
+bool ScriptTextEditor::goto_method(const String& p_method) {
+
+
+ Vector<String> functions = get_functions();
+
+ String method_search = p_method + ":";
+
+ for (int i=0;i<functions.size();i++) {
+ String function=functions[i];
+
+ if (function.begins_with(method_search)) {
+
+ int line=function.get_slice(":",1).to_int();
+ goto_line(line-1);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ScriptTextEditor::_load_theme_settings() {
+
+ TextEdit *text_edit = code_editor->get_text_edit();
+
+ text_edit->clear_colors();
+
+ /* keyword color */
+
+
+ text_edit->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color",Color(0,0,0,0)));
+ text_edit->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0,0,0,0)));
+ text_edit->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")));
+ text_edit->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")));
+ text_edit->add_color_override("completion_scroll_color", EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff")));
+ text_edit->add_color_override("completion_font_color", EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa")));
+ text_edit->add_color_override("font_color",EDITOR_DEF("text_editor/highlighting/text_color",Color(0,0,0)));
+ text_edit->add_color_override("line_number_color",EDITOR_DEF("text_editor/highlighting/line_number_color",Color(0,0,0)));
+ text_edit->add_color_override("caret_color",EDITOR_DEF("text_editor/highlighting/caret_color",Color(0,0,0)));
+ text_edit->add_color_override("caret_background_color",EDITOR_DEF("text_editor/highlighting/caret_background_color",Color(0,0,0)));
+ text_edit->add_color_override("font_selected_color",EDITOR_DEF("text_editor/highlighting/text_selected_color",Color(1,1,1)));
+ text_edit->add_color_override("selection_color",EDITOR_DEF("text_editor/highlighting/selection_color",Color(0.2,0.2,1)));
+ text_edit->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2)));
+ text_edit->add_color_override("current_line_color",EDITOR_DEF("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15)));
+ text_edit->add_color_override("line_length_guideline_color", EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0,0,0)));
+ text_edit->add_color_override("word_highlighted_color",EDITOR_DEF("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15)));
+ text_edit->add_color_override("number_color",EDITOR_DEF("text_editor/highlighting/number_color",Color(0.9,0.6,0.0,2)));
+ text_edit->add_color_override("function_color",EDITOR_DEF("text_editor/highlighting/function_color",Color(0.4,0.6,0.8)));
+ text_edit->add_color_override("member_variable_color",EDITOR_DEF("text_editor/highlighting/member_variable_color",Color(0.9,0.3,0.3)));
+ text_edit->add_color_override("mark_color", EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0,0.4,0.4,0.4)));
+ text_edit->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8,0.8,0.4,0.2)));
+ text_edit->add_color_override("search_result_color",EDITOR_DEF("text_editor/highlighting/search_result_color",Color(0.05,0.25,0.05,1)));
+ text_edit->add_color_override("search_result_border_color",EDITOR_DEF("text_editor/highlighting/search_result_border_color",Color(0.1,0.45,0.1,1)));
+ text_edit->add_color_override("symbol_color",EDITOR_DEF("text_editor/highlighting/symbol_color",Color::hex(0x005291ff)));
+ text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing",4));
+
+ Color keyword_color= EDITOR_DEF("text_editor/highlighting/keyword_color",Color(0.5,0.0,0.2));
+
+ List<String> keywords;
+ script->get_language()->get_reserved_words(&keywords);
+ for(List<String>::Element *E=keywords.front();E;E=E->next()) {
+
+ text_edit->add_keyword_color(E->get(),keyword_color);
+ }
+
+ //colorize core types
+ Color basetype_color= EDITOR_DEF("text_editor/highlighting/base_type_color",Color(0.3,0.3,0.0));
+
+ text_edit->add_keyword_color("Vector2",basetype_color);
+ text_edit->add_keyword_color("Vector3",basetype_color);
+ text_edit->add_keyword_color("Plane",basetype_color);
+ text_edit->add_keyword_color("Quat",basetype_color);
+ text_edit->add_keyword_color("AABB",basetype_color);
+ text_edit->add_keyword_color("Matrix3",basetype_color);
+ text_edit->add_keyword_color("Transform",basetype_color);
+ text_edit->add_keyword_color("Color",basetype_color);
+ text_edit->add_keyword_color("Image",basetype_color);
+ text_edit->add_keyword_color("InputEvent",basetype_color);
+ text_edit->add_keyword_color("Rect2",basetype_color);
+ text_edit->add_keyword_color("NodePath",basetype_color);
+
+ //colorize engine types
+ Color type_color= EDITOR_DEF("text_editor/highlighting/engine_type_color",Color(0.0,0.2,0.4));
+
+ List<StringName> types;
+ ClassDB::get_class_list(&types);
+
+ for(List<StringName>::Element *E=types.front();E;E=E->next()) {
+
+ String n = E->get();
+ if (n.begins_with("_"))
+ n = n.substr(1, n.length());
+
+ text_edit->add_keyword_color(n,type_color);
+ }
+
+ //colorize comments
+ Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color",Color::hex(0x797e7eff));
+ List<String> comments;
+ script->get_language()->get_comment_delimiters(&comments);
+
+ for(List<String>::Element *E=comments.front();E;E=E->next()) {
+
+ String comment = E->get();
+ String beg = comment.get_slice(" ",0);
+ String end = comment.get_slice_count(" ")>1?comment.get_slice(" ",1):String();
+
+ text_edit->add_color_region(beg,end,comment_color,end=="");
+ }
+
+ //colorize strings
+ Color string_color = EDITOR_DEF("text_editor/highlighting/string_color",Color::hex(0x6b6f00ff));
+ List<String> strings;
+ script->get_language()->get_string_delimiters(&strings);
+
+ for (List<String>::Element *E=strings.front();E;E=E->next()) {
+
+ String string = E->get();
+ String beg = string.get_slice(" ",0);
+ String end = string.get_slice_count(" ")>1?string.get_slice(" ",1):String();
+ text_edit->add_color_region(beg,end,string_color,end=="");
+ }
+}
+
+
+void ScriptTextEditor::reload_text() {
+
+ ERR_FAIL_COND(script.is_null()) ;
+
+ TextEdit *te = code_editor->get_text_edit();
+ int column = te->cursor_get_column();
+ int row = te->cursor_get_line();
+ int h = te->get_h_scroll();
+ int v = te->get_v_scroll();
+
+ te->set_text(script->get_source_code());
+ te->clear_undo_history();
+ te->cursor_set_line(row);
+ te->cursor_set_column(column);
+ te->set_h_scroll(h);
+ te->set_v_scroll(v);
+
+ te->tag_saved_version();
+
+ code_editor->update_line_and_column();
+
+}
+
+void ScriptTextEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //emit_signal("name_changed");
+ }
+}
+
+void ScriptTextEditor::add_callback(const String& p_function,PoolStringArray p_args) {
+
+ String code = code_editor->get_text_edit()->get_text();
+ int pos = script->get_language()->find_function(p_function,code);
+ if (pos==-1) {
+ //does not exist
+ code_editor->get_text_edit()->deselect();
+ pos=code_editor->get_text_edit()->get_line_count()+2;
+ String func = script->get_language()->make_function("",p_function,p_args);
+ //code=code+func;
+ code_editor->get_text_edit()->cursor_set_line(pos+1);
+ code_editor->get_text_edit()->cursor_set_column(1000000); //none shall be that big
+ code_editor->get_text_edit()->insert_text_at_cursor("\n\n"+func);
+ }
+ code_editor->get_text_edit()->cursor_set_line(pos);
+ code_editor->get_text_edit()->cursor_set_column(1);
+}
+
+void ScriptTextEditor::update_settings() {
+
+ code_editor->update_editor_settings();
+}
+
+bool ScriptTextEditor::is_unsaved() {
+
+ return code_editor->get_text_edit()->get_version()!=code_editor->get_text_edit()->get_saved_version();
+}
+
+Variant ScriptTextEditor::get_edit_state() {
+
+ Dictionary state;
+
+ state["scroll_pos"]=code_editor->get_text_edit()->get_v_scroll();
+ state["column"]=code_editor->get_text_edit()->cursor_get_column();
+ state["row"]=code_editor->get_text_edit()->cursor_get_line();
+
+ return state;
+}
+
+void ScriptTextEditor::trim_trailing_whitespace() {
+
+ TextEdit *tx = code_editor->get_text_edit();
+
+ bool trimed_whitespace = false;
+ for (int i = 0; i < tx->get_line_count(); i++) {
+ String line = tx->get_line(i);
+ if (line.ends_with(" ") || line.ends_with("\t")) {
+
+ if (!trimed_whitespace) {
+ tx->begin_complex_operation();
+ trimed_whitespace = true;
+ }
+
+ int end = 0;
+ for (int j = line.length() - 1; j > -1; j--) {
+ if (line[j] != ' ' && line[j] != '\t') {
+ end = j+1;
+ break;
+ }
+ }
+ tx->set_line(i, line.substr(0, end));
+ }
+ }
+ if (trimed_whitespace) {
+ tx->end_complex_operation();
+ tx->update();
+ }
+}
+
+void ScriptTextEditor::tag_saved_version() {
+
+ code_editor->get_text_edit()->tag_saved_version();
+}
+
+void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
+ code_editor->get_text_edit()->cursor_set_line(p_line);
+}
+
+void ScriptTextEditor::ensure_focus() {
+
+ code_editor->get_text_edit()->grab_focus();
+}
+
+void ScriptTextEditor::set_edit_state(const Variant& p_state) {
+
+ Dictionary state=p_state;
+ code_editor->get_text_edit()->set_v_scroll(state["scroll_pos"]);
+ code_editor->get_text_edit()->cursor_set_column( state["column"]);
+ code_editor->get_text_edit()->cursor_set_line( state["row"] );
+ code_editor->get_text_edit()->grab_focus();
+
+ //int scroll_pos;
+ //int cursor_column;
+ //int cursor_row;
+}
+
+String ScriptTextEditor::get_name() {
+ String name;
+
+ if (script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) {
+ name=script->get_path().get_file();
+ if (is_unsaved()) {
+ name+="(*)";
+ }
+ } else if (script->get_name()!="")
+ name=script->get_name();
+ else
+ name=script->get_class()+"("+itos(script->get_instance_ID())+")";
+
+ return name;
+
+}
+
+Ref<Texture> ScriptTextEditor::get_icon() {
+
+ if (get_parent_control() && get_parent_control()->has_icon(script->get_class(),"EditorIcons")) {
+ return get_parent_control()->get_icon(script->get_class(),"EditorIcons");
+ }
+
+ return Ref<Texture>();
+}
+
+
+
+void ScriptTextEditor::set_edited_script(const Ref<Script>& p_script) {
+
+ ERR_FAIL_COND(!script.is_null());
+
+ script=p_script;
+
+
+ _load_theme_settings();
+
+ code_editor->get_text_edit()->set_text(script->get_source_code());
+ code_editor->get_text_edit()->clear_undo_history();
+ code_editor->get_text_edit()->tag_saved_version();
+
+ emit_signal("name_changed");
+ code_editor->update_line_and_column();
+}
+
+
+void ScriptTextEditor::_validate_script() {
+
+ String errortxt;
+ int line=-1,col;
+ TextEdit *te=code_editor->get_text_edit();
+
+ String text = te->get_text();
+ List<String> fnc;
+
+ if (!script->get_language()->validate(text,line,col,errortxt,script->get_path(),&fnc)) {
+ String error_text="error("+itos(line)+","+itos(col)+"): "+errortxt;
+ code_editor->set_error(error_text);
+ } else {
+ code_editor->set_error("");
+ line=-1;
+ if (!script->is_tool()) {
+ script->set_source_code(text);
+ script->update_exports();
+ //script->reload(); //will update all the variables in property editors
+ }
+
+ functions.clear();
+ for (List<String>::Element *E=fnc.front();E;E=E->next()) {
+
+ functions.push_back(E->get());
+ }
+
+ }
+
+ line--;
+ for(int i=0;i<te->get_line_count();i++) {
+ te->set_line_as_marked(i,line==i);
+ }
+
+ emit_signal("name_changed");
+}
+
+
+static Node* _find_node_for_script(Node* p_base, Node*p_current, const Ref<Script>& p_script) {
+
+ if (p_current->get_owner()!=p_base && p_base!=p_current)
+ return NULL;
+ Ref<Script> c = p_current->get_script();
+ if (c==p_script)
+ return p_current;
+ for(int i=0;i<p_current->get_child_count();i++) {
+ Node *found = _find_node_for_script(p_base,p_current->get_child(i),p_script);
+ if (found)
+ return found;
+ }
+
+ return NULL;
+}
+
+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(Ref<Script> p_for_script) {
+
+ if (!bool(EditorSettings::get_singleton()->get("text_editor/external/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 (p_for_script.is_valid() && p_for_script!=script)
+ continue;
+
+ 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_class(),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_scripts(void* p_ud,const String& p_code, List<String>* r_options) {
+
+ ScriptTextEditor *ste = (ScriptTextEditor *)p_ud;
+ ste->_code_complete_script(p_code,r_options);
+}
+
+void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) {
+
+ if (color_panel->is_visible_in_tree()) return;
+ Node *base = get_tree()->get_edited_scene_root();
+ if (base) {
+ base = _find_node_for_script(base,base,script);
+ }
+ String hint;
+ Error err = script->get_language()->complete_code(p_code,script->get_path().get_base_dir(),base,r_options,hint);
+ if (hint!="") {
+ code_editor->get_text_edit()->set_code_hint(hint);
+ }
+
+}
+
+void ScriptTextEditor::_breakpoint_toggled(int p_row) {
+
+ ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(script->get_path(),p_row+1,code_editor->get_text_edit()->is_line_set_as_breakpoint(p_row));
+
+}
+
+static void swap_lines(TextEdit *tx, int line1, int line2)
+{
+ String tmp = tx->get_line(line1);
+ String tmp2 = tx->get_line(line2);
+ tx->set_line(line2, tmp);
+ tx->set_line(line1, tmp2);
+
+ tx->cursor_set_line(line2);
+}
+
+void ScriptTextEditor::_lookup_symbol(const String& p_symbol,int p_row, int p_column) {
+
+ Node *base = get_tree()->get_edited_scene_root();
+ if (base) {
+ base = _find_node_for_script(base,base,script);
+ }
+
+
+ ScriptLanguage::LookupResult result;
+ if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(),p_symbol,script->get_path().get_base_dir(),base,result)==OK) {
+
+ _goto_line(p_row);
+
+ switch(result.type) {
+ case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: {
+
+ if (result.script.is_valid()) {
+ emit_signal("request_open_script_at_line",result.script,result.location-1);
+ } else {
+ emit_signal("request_save_history");
+ _goto_line(result.location-1);
+ }
+ } break;
+ case ScriptLanguage::LookupResult::RESULT_CLASS: {
+ emit_signal("go_to_help","class_name:"+result.class_name);
+ } break;
+ case ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT: {
+
+ StringName cname = result.class_name;
+ bool success;
+ while(true) {
+ ClassDB::get_integer_constant(cname,result.class_member,&success);
+ if (success) {
+ result.class_name=cname;
+ cname=ClassDB::get_parent_class(cname);
+ } else {
+ break;
+ }
+ }
+
+
+ emit_signal("go_to_help","class_constant:"+result.class_name+":"+result.class_member);
+
+ } break;
+ case ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY: {
+ emit_signal("go_to_help","class_property:"+result.class_name+":"+result.class_member);
+
+ } break;
+ case ScriptLanguage::LookupResult::RESULT_CLASS_METHOD: {
+
+ StringName cname = result.class_name;
+
+ while(true) {
+ if (ClassDB::has_method(cname,result.class_member)) {
+ result.class_name=cname;
+ cname=ClassDB::get_parent_class(cname);
+ } else {
+ break;
+ }
+ }
+
+ emit_signal("go_to_help","class_method:"+result.class_name+":"+result.class_member);
+
+ } break;
+ }
+
+ }
+}
+
+void ScriptTextEditor::_edit_option(int p_op) {
+
+ switch(p_op) {
+ case EDIT_UNDO: {
+ code_editor->get_text_edit()->undo();
+ code_editor->get_text_edit()->call_deferred("grab_focus");
+ } break;
+ case EDIT_REDO: {
+ code_editor->get_text_edit()->redo();
+ code_editor->get_text_edit()->call_deferred("grab_focus");
+ } break;
+ case EDIT_CUT: {
+
+ code_editor->get_text_edit()->cut();
+ code_editor->get_text_edit()->call_deferred("grab_focus");
+ } break;
+ case EDIT_COPY: {
+ code_editor->get_text_edit()->copy();
+ code_editor->get_text_edit()->call_deferred("grab_focus");
+
+ } break;
+ case EDIT_PASTE: {
+ code_editor->get_text_edit()->paste();
+ code_editor->get_text_edit()->call_deferred("grab_focus");
+
+ } break;
+ case EDIT_SELECT_ALL: {
+
+ code_editor->get_text_edit()->select_all();
+ code_editor->get_text_edit()->call_deferred("grab_focus");
+
+ } break;
+ case EDIT_MOVE_LINE_UP: {
+
+ TextEdit *tx = code_editor->get_text_edit();
+ Ref<Script> scr = script;
+ if (scr.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active())
+ {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = from_line; i <= to_line; i++)
+ {
+ int line_id = i;
+ int next_id = i - 1;
+
+ if (line_id == 0 || next_id < 0)
+ return;
+
+ swap_lines(tx, line_id, next_id);
+ }
+ int from_line_up = from_line > 0 ? from_line-1 : from_line;
+ int to_line_up = to_line > 0 ? to_line-1 : to_line;
+ tx->select(from_line_up, from_col, to_line_up, to_column);
+ }
+ else
+ {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id - 1;
+
+ if (line_id == 0 || next_id < 0)
+ return;
+
+ swap_lines(tx, line_id, next_id);
+ }
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_MOVE_LINE_DOWN: {
+
+ TextEdit *tx = code_editor->get_text_edit();
+ Ref<Script> scr = get_edited_script();
+ if (scr.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active())
+ {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = to_line; i >= from_line; i--)
+ {
+ int line_id = i;
+ int next_id = i + 1;
+
+ if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
+ return;
+
+ swap_lines(tx, line_id, next_id);
+ }
+ int from_line_down = from_line < tx->get_line_count() ? from_line+1 : from_line;
+ int to_line_down = to_line < tx->get_line_count() ? to_line+1 : to_line;
+ tx->select(from_line_down, from_col, to_line_down, to_column);
+ }
+ else
+ {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id + 1;
+
+ if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
+ return;
+
+ swap_lines(tx, line_id, next_id);
+ }
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_INDENT_LEFT: {
+
+ TextEdit *tx = code_editor->get_text_edit();
+ Ref<Script> scr = get_edited_script();
+ if (scr.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active())
+ {
+ tx->indent_selection_left();
+ }
+ else
+ {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ // begins with tab
+ if (line_text.begins_with("\t"))
+ {
+ line_text = line_text.substr(1, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ // begins with 4 spaces
+ else if (line_text.begins_with(" "))
+ {
+ line_text = line_text.substr(4, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_INDENT_RIGHT: {
+
+ TextEdit *tx = code_editor->get_text_edit();
+ Ref<Script> scr = get_edited_script();
+ if (scr.is_null())
+ return;
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active())
+ {
+ tx->indent_selection_right();
+ }
+ else
+ {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ line_text = '\t' + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_CLONE_DOWN: {
+
+ TextEdit *tx = code_editor->get_text_edit();
+ Ref<Script> scr = get_edited_script();
+ if (scr.is_null())
+ return;
+
+ int from_line = tx->cursor_get_line();
+ int to_line = tx->cursor_get_line();
+ int column = tx->cursor_get_column();
+
+ if (tx->is_selection_active()) {
+ from_line = tx->get_selection_from_line();
+ to_line = tx->get_selection_to_line();
+ column = tx->cursor_get_column();
+ }
+ int next_line = to_line + 1;
+
+ tx->begin_complex_operation();
+ for (int i = from_line; i <= to_line; i++) {
+
+ if (i >= tx->get_line_count() - 1) {
+ tx->set_line(i, tx->get_line(i) + "\n");
+ }
+ String line_clone = tx->get_line(i);
+ tx->insert_at(line_clone, next_line);
+ next_line++;
+ }
+
+ tx->cursor_set_column(column);
+ if (tx->is_selection_active()) {
+ tx->select(to_line + 1, tx->get_selection_from_column(), next_line - 1, tx->get_selection_to_column());
+ }
+
+ tx->end_complex_operation();
+ tx->update();
+
+ } break;
+ case EDIT_TOGGLE_COMMENT: {
+
+ TextEdit *tx = code_editor->get_text_edit();
+ Ref<Script> scr = get_edited_script();
+ if (scr.is_null())
+ return;
+
+
+ tx->begin_complex_operation();
+ if (tx->is_selection_active())
+ {
+ int begin = tx->get_selection_from_line();
+ int end = tx->get_selection_to_line();
+
+ // End of selection ends on the first column of the last line, ignore it.
+ if(tx->get_selection_to_column() == 0)
+ end -= 1;
+
+ for (int i = begin; i <= end; i++)
+ {
+ String line_text = tx->get_line(i);
+
+ if (line_text.begins_with("#"))
+ line_text = line_text.substr(1, line_text.length());
+ else
+ line_text = "#" + line_text;
+ tx->set_line(i, line_text);
+ }
+ }
+ else
+ {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+
+ if (line_text.begins_with("#"))
+ line_text = line_text.substr(1, line_text.length());
+ else
+ line_text = "#" + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->end_complex_operation();
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_COMPLETE: {
+
+ code_editor->get_text_edit()->query_code_comple();
+
+ } break;
+ case EDIT_AUTO_INDENT: {
+
+ TextEdit *te = code_editor->get_text_edit();
+ String text = te->get_text();
+ Ref<Script> scr = get_edited_script();
+ if (scr.is_null())
+ return;
+ int begin,end;
+ if (te->is_selection_active()) {
+ begin=te->get_selection_from_line();
+ end=te->get_selection_to_line();
+ } else {
+ begin=0;
+ end=te->get_line_count()-1;
+ }
+ scr->get_language()->auto_indent_code(text,begin,end);
+ te->set_text(text);
+
+
+ } break;
+ case EDIT_TRIM_TRAILING_WHITESAPCE: {
+ trim_trailing_whitespace();
+ } break;
+ case EDIT_PICK_COLOR: {
+ color_panel->popup();
+ } break;
+
+
+ case SEARCH_FIND: {
+
+ code_editor->get_find_replace_bar()->popup_search();
+ } break;
+ case SEARCH_FIND_NEXT: {
+
+ code_editor->get_find_replace_bar()->search_next();
+ } break;
+ case SEARCH_FIND_PREV: {
+
+ code_editor->get_find_replace_bar()->search_prev();
+ } break;
+ case SEARCH_REPLACE: {
+
+ code_editor->get_find_replace_bar()->popup_replace();
+ } break;
+ case SEARCH_LOCATE_FUNCTION: {
+
+ quick_open->popup(get_functions());
+ } break;
+ case SEARCH_GOTO_LINE: {
+
+ goto_line_dialog->popup_find_line(code_editor->get_text_edit());
+ } break;
+ case DEBUG_TOGGLE_BREAKPOINT: {
+ int line=code_editor->get_text_edit()->cursor_get_line();
+ bool dobreak = !code_editor->get_text_edit()->is_line_set_as_breakpoint(line);
+ code_editor->get_text_edit()->set_line_as_breakpoint(line,dobreak);
+ ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(get_edited_script()->get_path(),line+1,dobreak);
+ } break;
+ case DEBUG_REMOVE_ALL_BREAKPOINTS: {
+ List<int> bpoints;
+ code_editor->get_text_edit()->get_breakpoints(&bpoints);
+
+ for(List<int>::Element *E=bpoints.front();E;E=E->next()) {
+ int line = E->get();
+ bool dobreak = !code_editor->get_text_edit()->is_line_set_as_breakpoint(line);
+ code_editor->get_text_edit()->set_line_as_breakpoint(line,dobreak);
+ ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(get_edited_script()->get_path(),line+1,dobreak);
+ }
+ }
+ case DEBUG_GOTO_NEXT_BREAKPOINT: {
+ List<int> bpoints;
+ code_editor->get_text_edit()->get_breakpoints(&bpoints);
+ if (bpoints.size() <= 0) {
+ return;
+ }
+
+ int line=code_editor->get_text_edit()->cursor_get_line();
+ // wrap around
+ if (line >= bpoints[bpoints.size() - 1]) {
+ code_editor->get_text_edit()->cursor_set_line(bpoints[0]);
+ } else {
+ for(List<int>::Element *E=bpoints.front();E;E=E->next()) {
+ int bline = E->get();
+ if (bline > line) {
+ code_editor->get_text_edit()->cursor_set_line(bline);
+ return;
+ }
+ }
+ }
+
+ } break;
+ case DEBUG_GOTO_PREV_BREAKPOINT: {
+ List<int> bpoints;
+ code_editor->get_text_edit()->get_breakpoints(&bpoints);
+ if (bpoints.size() <= 0) {
+ return;
+ }
+
+ int line=code_editor->get_text_edit()->cursor_get_line();
+ // wrap around
+ if (line <= bpoints[0]) {
+ code_editor->get_text_edit()->cursor_set_line(bpoints[bpoints.size() - 1]);
+ } else {
+ for(List<int>::Element *E=bpoints.back();E;E=E->prev()) {
+ int bline = E->get();
+ if (bline < line) {
+ code_editor->get_text_edit()->cursor_set_line(bline);
+ return;
+ }
+ }
+ }
+
+ } break;
+
+ case HELP_CONTEXTUAL: {
+ String text = code_editor->get_text_edit()->get_selection_text();
+ if (text == "")
+ text = code_editor->get_text_edit()->get_word_under_cursor();
+ if (text != "") {
+ emit_signal("request_help_search",text);
+ }
+ } break;
+ }
+}
+
+void ScriptTextEditor::_bind_methods() {
+
+ ClassDB::bind_method("_validate_script",&ScriptTextEditor::_validate_script);
+ ClassDB::bind_method("_load_theme_settings",&ScriptTextEditor::_load_theme_settings);
+ ClassDB::bind_method("_breakpoint_toggled",&ScriptTextEditor::_breakpoint_toggled);
+ ClassDB::bind_method("_edit_option",&ScriptTextEditor::_edit_option);
+ ClassDB::bind_method("_goto_line",&ScriptTextEditor::_goto_line);
+ ClassDB::bind_method("_lookup_symbol",&ScriptTextEditor::_lookup_symbol);
+ ClassDB::bind_method("_text_edit_gui_input", &ScriptTextEditor::_text_edit_gui_input);
+ ClassDB::bind_method("_color_changed", &ScriptTextEditor::_color_changed);
+
+
+ ClassDB::bind_method("get_drag_data_fw",&ScriptTextEditor::get_drag_data_fw);
+ ClassDB::bind_method("can_drop_data_fw",&ScriptTextEditor::can_drop_data_fw);
+ ClassDB::bind_method("drop_data_fw",&ScriptTextEditor::drop_data_fw);
+
+}
+
+Control *ScriptTextEditor::get_edit_menu() {
+
+ return edit_hb;
+}
+
+void ScriptTextEditor::reload(bool p_soft) {
+
+ TextEdit *te = code_editor->get_text_edit();
+ Ref<Script> scr = get_edited_script();
+ if (scr.is_null())
+ return;
+ scr->set_source_code(te->get_text());
+ bool soft = p_soft || scr->get_instance_base_type()=="EditorPlugin"; //always soft-reload editor plugins
+
+ scr->get_language()->reload_tool_script(scr,soft);
+}
+
+void ScriptTextEditor::get_breakpoints(List<int> *p_breakpoints) {
+
+ code_editor->get_text_edit()->get_breakpoints(p_breakpoints);
+
+}
+
+void ScriptTextEditor::set_tooltip_request_func(String p_method,Object* p_obj) {
+
+ code_editor->get_text_edit()->set_tooltip_request_func(p_obj,p_method,this);
+}
+
+void ScriptTextEditor::set_debugger_active(bool p_active) {
+
+
+}
+
+
+Variant ScriptTextEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ return Variant();
+}
+
+bool ScriptTextEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ Dictionary d = p_data;
+ if (d.has("type") &&
+ (
+
+ String(d["type"])=="resource" ||
+ String(d["type"])=="files" ||
+ String(d["type"])=="nodes"
+ ) ) {
+
+
+ return true;
+ }
+
+
+ return false;
+
+}
+
+#ifdef TOOLS_ENABLED
+
+static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
+
+ if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene)
+ return NULL;
+
+ Ref<Script> scr = p_current_node->get_script();
+
+ if (scr.is_valid() && scr==script)
+ return p_current_node;
+
+ for(int i=0;i<p_current_node->get_child_count();i++) {
+ Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script);
+ if (n)
+ return n;
+ }
+
+ return NULL;
+}
+
+#else
+
+static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
+
+ return NULL;
+}
+#endif
+
+
+
+
+void ScriptTextEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ Dictionary d = p_data;
+
+ if (d.has("type") && String(d["type"])=="resource") {
+
+ Ref<Resource> res = d["resource"];
+ if (!res.is_valid()) {
+ return;
+ }
+
+ if (res->get_path().is_resource_file()) {
+ EditorNode::get_singleton()->show_warning("Only resources from filesystem can be dropped.");
+ return;
+ }
+
+ code_editor->get_text_edit()->insert_text_at_cursor(res->get_path());
+
+ }
+
+ if (d.has("type") && String(d["type"])=="files") {
+
+
+ Array files = d["files"];
+
+ String text_to_drop;
+ for(int i=0;i<files.size();i++) {
+
+ if (i>0)
+ text_to_drop+=",";
+ text_to_drop+="\""+String(files[i]).c_escape()+"\"";
+
+ }
+
+ code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop);
+
+ }
+
+ if (d.has("type") && String(d["type"])=="nodes") {
+
+ Node* sn = _find_script_node(get_tree()->get_edited_scene_root(),get_tree()->get_edited_scene_root(),script);
+
+
+ if (!sn) {
+ EditorNode::get_singleton()->show_warning("Can't drop nodes because script '"+get_name()+"' is not used in this scene.");
+ return;
+ }
+
+
+ Array nodes = d["nodes"];
+ String text_to_drop;
+ for(int i=0;i<nodes.size();i++) {
+
+ if (i>0)
+ text_to_drop+=",";
+
+ NodePath np = nodes[i];
+ Node *node = get_node(np);
+ if (!node) {
+ continue;
+ }
+
+
+
+ String path = sn->get_path_to(node);
+ text_to_drop+="\""+path.c_escape()+"\"";
+
+
+ }
+
+ code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop);
+
+
+ }
+
+
+
+}
+
+void ScriptTextEditor::_text_edit_gui_input(const InputEvent& ev) {
+ if (ev.type == InputEvent::MOUSE_BUTTON) {
+ InputEventMouseButton mb = ev.mouse_button;
+ if (mb.button_index == BUTTON_RIGHT && !mb.pressed) {
+
+ int col, row;
+ TextEdit* tx = code_editor->get_text_edit();
+ tx->_get_mouse_pos(Point2i(mb.global_x, mb.global_y)-tx->get_global_pos(), row, col);
+ Vector2 mpos = Vector2(mb.global_x, mb.global_y)-tx->get_global_pos();
+ bool have_selection = (tx->get_selection_text().length() > 0);
+ bool have_color = (tx->get_word_at_pos(mpos) == "Color");
+ if (have_color) {
+
+ String line = tx->get_line(row);
+ color_line = row;
+ int begin = 0;
+ int end = 0;
+ bool valid = false;
+ for (int i = col; i < line.length(); i++) {
+ if (line[i] == '(') {
+ begin = i;
+ continue;
+ }
+ else if (line[i] == ')') {
+ end = i+1;
+ valid = true;
+ break;
+ }
+ }
+ if (valid) {
+ color_args = line.substr(begin, end-begin);
+ String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
+ Vector<float> color = stripped.split_floats(",");
+ if (color.size() > 2) {
+ float alpha = color.size() > 3 ? color[3] : 1.0f;
+ color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
+ }
+ color_panel->set_pos(get_global_transform().xform(get_local_mouse_pos()));
+ Size2 ms = Size2(300, color_picker->get_combined_minimum_size().height+10);
+ color_panel->set_size(ms);
+ } else {
+ have_color = false;
+ }
+ }
+ _make_context_menu(have_selection, have_color);
+ }
+ }
+}
+
+void ScriptTextEditor::_color_changed(const Color& p_color) {
+ String new_args;
+ if (p_color.a == 1.0f) {
+ new_args = String("("+rtos(p_color.r)+", "+rtos(p_color.g)+", "+rtos(p_color.b)+")");
+ } else {
+ new_args = String("("+rtos(p_color.r)+", "+rtos(p_color.g)+", "+rtos(p_color.b)+", "+rtos(p_color.a)+")");
+ }
+
+ String line = code_editor->get_text_edit()->get_line(color_line);
+ String new_line = line.replace(color_args, new_args);
+ color_args = new_args;
+ code_editor->get_text_edit()->set_line(color_line, new_line);
+}
+
+void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color) {
+
+ context_menu->clear();
+ if (p_selection) {
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ }
+
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+
+ if (p_selection) {
+ context_menu->add_separator();
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
+ context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
+ }
+ if (p_color) {
+ context_menu->add_separator();
+ context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR);
+ }
+ context_menu->set_pos(get_global_transform().xform(get_local_mouse_pos()));
+ context_menu->set_size(Vector2(1, 1));
+ context_menu->popup();
+}
+
+ScriptTextEditor::ScriptTextEditor() {
+
+ code_editor = memnew( CodeTextEditor );
+ add_child(code_editor);
+ code_editor->set_area_as_parent_rect();
+ code_editor->connect("validate_script",this,"_validate_script");
+ code_editor->connect("load_theme_settings",this,"_load_theme_settings");
+ code_editor->set_code_complete_func(_code_complete_scripts,this);
+ code_editor->get_text_edit()->connect("breakpoint_toggled", this, "_breakpoint_toggled");
+ code_editor->get_text_edit()->connect("symbol_lookup", this, "_lookup_symbol");
+
+ update_settings();
+
+ code_editor->get_text_edit()->set_callhint_settings(
+ EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
+ EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
+
+ code_editor->get_text_edit()->set_select_identifiers_on_hover(true);
+ code_editor->get_text_edit()->set_context_menu_enabled(false);
+ code_editor->get_text_edit()->connect("gui_input", this, "_text_edit_gui_input");
+
+ context_menu = memnew(PopupMenu);
+ add_child(context_menu);
+ context_menu->connect("id_pressed", this, "_edit_option");
+
+ color_panel = memnew(PopupPanel);
+ add_child(color_panel);
+ color_picker = memnew(ColorPicker);
+ color_panel->add_child(color_picker);
+ color_panel->set_child_rect(color_picker); //NOT
+ color_picker->connect("color_changed", this, "_color_changed");
+
+ edit_hb = memnew (HBoxContainer);
+
+ edit_menu = memnew( MenuButton );
+ edit_menu->set_text(TTR("Edit"));
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_up"), EDIT_MOVE_LINE_UP);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_down"), EDIT_MOVE_LINE_DOWN);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
+ edit_menu->get_popup()->add_separator();
+#ifdef OSX_ENABLED
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
+#else
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
+#endif
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/auto_indent"), EDIT_AUTO_INDENT);
+ edit_menu->get_popup()->connect("id_pressed", this,"_edit_option");
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_breakpoint"), DEBUG_TOGGLE_BREAKPOINT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/remove_all_breakpoints"), DEBUG_REMOVE_ALL_BREAKPOINTS);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_breakpoint"), DEBUG_GOTO_NEXT_BREAKPOINT);
+ edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_breakpoint"), DEBUG_GOTO_PREV_BREAKPOINT);
+
+ search_menu = memnew( MenuButton );
+ edit_hb->add_child(search_menu);
+ search_menu->set_text(TTR("Search"));
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
+ search_menu->get_popup()->add_separator();
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_function"), SEARCH_LOCATE_FUNCTION);
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE);
+ search_menu->get_popup()->add_separator();
+ search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/contextual_help"), HELP_CONTEXTUAL);
+
+ search_menu->get_popup()->connect("id_pressed", this,"_edit_option");
+
+ edit_hb->add_child(edit_menu);
+
+ quick_open = memnew( ScriptEditorQuickOpen );
+ add_child(quick_open);
+ quick_open->connect("goto_line",this,"_goto_line");
+
+ goto_line_dialog = memnew(GotoLineDialog);
+ add_child(goto_line_dialog);
+
+
+ code_editor->get_text_edit()->set_drag_forwarding(this);
+}
+
+static ScriptEditorBase * create_editor(const Ref<Script>& p_script) {
+
+ if (p_script->has_source_code()) {
+ return memnew( ScriptTextEditor );
+ }
+
+ return NULL;
+}
+
+void ScriptTextEditor::register_editor() {
+
+ ED_SHORTCUT("script_text_editor/undo", TTR("Undo"), KEY_MASK_CMD|KEY_Z);
+ ED_SHORTCUT("script_text_editor/redo", TTR("Redo"), KEY_MASK_CMD|KEY_Y);
+ ED_SHORTCUT("script_text_editor/cut", TTR("Cut"), KEY_MASK_CMD|KEY_X);
+ ED_SHORTCUT("script_text_editor/copy", TTR("Copy"), KEY_MASK_CMD|KEY_C);
+ ED_SHORTCUT("script_text_editor/paste", TTR("Paste"), KEY_MASK_CMD|KEY_V);
+ ED_SHORTCUT("script_text_editor/select_all", TTR("Select All"), KEY_MASK_CMD|KEY_A);
+ ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT|KEY_UP);
+ ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT|KEY_DOWN);
+
+ //leave these at zero, same can be accomplished with tab/shift-tab, including selection
+ //the next/previous in history shortcut in this case makes a lot more sene.
+
+ ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), 0);
+ ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0);
+ ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD|KEY_K);
+ ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD|KEY_B);
+#ifdef OSX_ENABLED
+ ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CTRL|KEY_SPACE);
+#else
+ ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CMD|KEY_SPACE);
+#endif
+ ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CTRL|KEY_MASK_ALT|KEY_T);
+ ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD|KEY_I);
+
+ ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9);
+ ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CTRL|KEY_MASK_SHIFT|KEY_F9);
+ ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Goto Next Breakpoint"), KEY_MASK_CTRL|KEY_PERIOD);
+ ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Goto Previous Breakpoint"), KEY_MASK_CTRL|KEY_COMMA);
+
+ ED_SHORTCUT("script_text_editor/find", TTR("Find.."), KEY_MASK_CMD|KEY_F);
+ ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3);
+ ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT|KEY_F3);
+ ED_SHORTCUT("script_text_editor/replace", TTR("Replace.."), KEY_MASK_CMD|KEY_R);
+
+ ED_SHORTCUT("script_text_editor/goto_function", TTR("Goto Function.."), KEY_MASK_SHIFT|KEY_MASK_CMD|KEY_F);
+ ED_SHORTCUT("script_text_editor/goto_line", TTR("Goto Line.."), KEY_MASK_CMD|KEY_L);
+
+ ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_SHIFT|KEY_F1);
+
+ ScriptEditor::register_create_script_editor_function(create_editor);
+}
diff --git a/tools/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index e30a78340e..e30a78340e 100644
--- a/tools/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
new file mode 100644
index 0000000000..c14d1650fd
--- /dev/null
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -0,0 +1,584 @@
+/*************************************************************************/
+/* shader_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "shader_editor_plugin.h"
+
+#include "editor/editor_settings.h"
+#include "spatial_editor_plugin.h"
+#include "scene/resources/shader_graph.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "os/keyboard.h"
+#include "editor/editor_node.h"
+#include "editor/property_editor.h"
+#include "os/os.h"
+#include "servers/visual/shader_types.h"
+
+/*** SETTINGS EDITOR ****/
+
+
+
+
+/*** SCRIPT EDITOR ****/
+
+
+Ref<Shader> ShaderTextEditor::get_edited_shader() const {
+
+ return shader;
+}
+void ShaderTextEditor::set_edited_shader(const Ref<Shader>& p_shader) {
+
+ shader=p_shader;
+
+
+ _load_theme_settings();
+
+ get_text_edit()->set_text(p_shader->get_code());
+
+ _line_col_changed();
+
+
+}
+
+
+void ShaderTextEditor::_load_theme_settings() {
+
+ get_text_edit()->clear_colors();
+
+ /* keyword color */
+
+ get_text_edit()->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color",Color(0,0,0,0)));
+ get_text_edit()->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0,0,0,0)));
+ get_text_edit()->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")));
+ get_text_edit()->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")));
+ get_text_edit()->add_color_override("completion_scroll_color", EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff")));
+ get_text_edit()->add_color_override("completion_font_color", EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa")));
+ get_text_edit()->add_color_override("font_color",EDITOR_DEF("text_editor/highlighting/text_color",Color(0,0,0)));
+ get_text_edit()->add_color_override("line_number_color",EDITOR_DEF("text_editor/highlighting/line_number_color",Color(0,0,0)));
+ get_text_edit()->add_color_override("caret_color",EDITOR_DEF("text_editor/highlighting/caret_color",Color(0,0,0)));
+ get_text_edit()->add_color_override("caret_background_color",EDITOR_DEF("text_editor/highlighting/caret_background_color",Color(0,0,0)));
+ get_text_edit()->add_color_override("font_selected_color",EDITOR_DEF("text_editor/highlighting/text_selected_color",Color(1,1,1)));
+ get_text_edit()->add_color_override("selection_color",EDITOR_DEF("text_editor/highlighting/selection_color",Color(0.2,0.2,1)));
+ get_text_edit()->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2)));
+ get_text_edit()->add_color_override("current_line_color",EDITOR_DEF("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15)));
+ get_text_edit()->add_color_override("word_highlighted_color",EDITOR_DEF("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15)));
+ get_text_edit()->add_color_override("number_color",EDITOR_DEF("text_editor/highlighting/number_color",Color(0.9,0.6,0.0,2)));
+ get_text_edit()->add_color_override("function_color",EDITOR_DEF("text_editor/highlighting/function_color",Color(0.4,0.6,0.8)));
+ get_text_edit()->add_color_override("member_variable_color",EDITOR_DEF("text_editor/highlighting/member_variable_color",Color(0.9,0.3,0.3)));
+ get_text_edit()->add_color_override("mark_color", EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0,0.4,0.4,0.4)));
+ get_text_edit()->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8,0.8,0.4,0.2)));
+ get_text_edit()->add_color_override("search_result_color",EDITOR_DEF("text_editor/highlighting/search_result_color",Color(0.05,0.25,0.05,1)));
+ get_text_edit()->add_color_override("search_result_border_color",EDITOR_DEF("text_editor/highlighting/search_result_border_color",Color(0.1,0.45,0.1,1)));
+ get_text_edit()->add_color_override("symbol_color",EDITOR_DEF("text_editor/highlighting/symbol_color",Color::hex(0x005291ff)));
+
+ Color keyword_color= EDITOR_DEF("text_editor/highlighting/keyword_color",Color(0.5,0.0,0.2));
+
+
+ List<String> keywords;
+ ShaderLanguage::get_keyword_list(&keywords);
+
+ if (shader.is_valid()) {
+
+
+ for(const Map< StringName, Map<StringName,ShaderLanguage::DataType> >::Element *E=ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())).front();E;E=E->next()) {
+
+ for (const Map<StringName,ShaderLanguage::DataType>::Element *F=E->get().front();F;F=F->next()) {
+ keywords.push_back(F->key());
+ }
+
+ }
+
+ for(const Set<String>::Element *E =ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())).front();E;E=E->next()) {
+
+ keywords.push_back(E->get());
+
+ }
+ }
+
+
+ for(List<String>::Element *E=keywords.front();E;E=E->next()) {
+
+ get_text_edit()->add_keyword_color(E->get(),keyword_color);
+ }
+
+ //colorize core types
+ //Color basetype_color= EDITOR_DEF("text_editor/base_type_color",Color(0.3,0.3,0.0));
+
+
+ //colorize comments
+ Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color",Color::hex(0x797e7eff));
+
+ get_text_edit()->add_color_region("/*","*/",comment_color,false);
+ get_text_edit()->add_color_region("//","",comment_color,false);
+
+ /*//colorize strings
+ Color string_color = EDITOR_DEF("text_editor/string_color",Color::hex(0x6b6f00ff));
+
+ List<String> strings;
+ shader->get_shader_mode()->get_string_delimiters(&strings);
+
+ for (List<String>::Element *E=strings.front();E;E=E->next()) {
+
+ String string = E->get();
+ String beg = string.get_slice(" ",0);
+ String end = string.get_slice_count(" ")>1?string.get_slice(" ",1):String();
+ get_text_edit()->add_color_region(beg,end,string_color,end=="");
+ }*/
+}
+
+void ShaderTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) {
+
+ print_line("code complete");
+
+ ShaderLanguage sl;
+ String calltip;
+
+ Error err = sl.complete(p_code,ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())),ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())),r_options,calltip);
+
+ if (calltip!="") {
+ get_text_edit()->set_code_hint(calltip);
+ }
+}
+
+void ShaderTextEditor::_validate_script() {
+
+ String code=get_text_edit()->get_text();
+ //List<StringName> params;
+ //shader->get_param_list(&params);
+
+ ShaderLanguage sl;
+
+ Error err = sl.compile(code,ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())),ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())));
+
+ if (err!=OK) {
+ String error_text="error("+itos(sl.get_error_line())+"): "+sl.get_error_text();
+ set_error(error_text);
+ get_text_edit()->set_line_as_marked(sl.get_error_line(),true);
+
+ } else {
+ for(int i=0;i<get_text_edit()->get_line_count();i++)
+ get_text_edit()->set_line_as_marked(i,false);
+ set_error("");
+ }
+
+ emit_signal("script_changed");
+}
+
+void ShaderTextEditor::_bind_methods() {
+
+
+ //ADD_SIGNAL( MethodInfo("script_changed") );
+
+}
+
+ShaderTextEditor::ShaderTextEditor() {
+
+
+}
+
+/*** SCRIPT EDITOR ******/
+
+
+
+void ShaderEditor::_menu_option(int p_option) {
+
+
+ ShaderTextEditor *current = shader_editor;
+
+ switch(p_option) {
+ case EDIT_UNDO: {
+
+
+ current->get_text_edit()->undo();
+ } break;
+ case EDIT_REDO: {
+ current->get_text_edit()->redo();
+
+ } break;
+ case EDIT_CUT: {
+
+ current->get_text_edit()->cut();
+ } break;
+ case EDIT_COPY: {
+ current->get_text_edit()->copy();
+
+ } break;
+ case EDIT_PASTE: {
+ current->get_text_edit()->paste();
+
+ } break;
+ case EDIT_SELECT_ALL: {
+
+ current->get_text_edit()->select_all();
+
+ } break;
+ case SEARCH_FIND: {
+
+ current->get_find_replace_bar()->popup_search();
+ } break;
+ case SEARCH_FIND_NEXT: {
+
+ current->get_find_replace_bar()->search_next();
+ } break;
+ case SEARCH_FIND_PREV: {
+
+ current->get_find_replace_bar()->search_prev();
+ } break;
+ case SEARCH_REPLACE: {
+
+ current->get_find_replace_bar()->popup_replace();
+ } break;
+ //case SEARCH_LOCATE_SYMBOL: {
+
+ //} break;
+ case SEARCH_GOTO_LINE: {
+
+ goto_line_dialog->popup_find_line(current->get_text_edit());
+ } break;
+
+ }
+}
+
+
+void ShaderEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+
+ }
+ if (p_what==NOTIFICATION_DRAW) {
+
+ RID ci = get_canvas_item();
+ Ref<StyleBox> style = get_stylebox("panel","Panel");
+ style->draw( ci, Rect2( Point2(), get_size() ) );
+
+ }
+
+}
+
+
+
+Dictionary ShaderEditor::get_state() const {
+#if 0
+ apply_shaders();
+
+ Dictionary state;
+
+ Array paths;
+ int open=-1;
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ ShaderTextEditor *ste = tab_container->get_child(i)->cast_to<ShaderTextEditor>();
+ if (!ste)
+ continue;
+
+
+ Ref<Shader> shader = ste->get_edited_shader();
+ if (shader->get_path()!="" && shader->get_path().find("local://")==-1 && shader->get_path().find("::")==-1) {
+
+ paths.push_back(shader->get_path());
+ } else {
+
+
+ const Node *owner = _find_node_with_shader(get_root_node(),shader.get_ref_ptr());
+ if (owner)
+ paths.push_back(owner->get_path());
+
+ }
+
+ if (i==tab_container->get_current_tab())
+ open=i;
+ }
+
+ if (paths.size())
+ state["sources"]=paths;
+ if (open!=-1)
+ state["current"]=open;
+
+
+ return state;
+#endif
+ return Dictionary();
+}
+void ShaderEditor::set_state(const Dictionary& p_state) {
+#if 0
+ print_line("setting state..");
+ if (!p_state.has("sources"))
+ return; //bleh
+
+ Array sources = p_state["sources"];
+ for(int i=0;i<sources.size();i++) {
+
+ Variant source=sources[i];
+
+ Ref<Shader> shader;
+
+ if (source.get_type()==Variant::NODE_PATH) {
+
+ print_line("cain find owner at path "+String(source));
+ Node *owner=get_root_node()->get_node(source);
+ if (!owner)
+ continue;
+
+ shader = owner->get_shader();
+ } else if (source.get_type()==Variant::STRING) {
+
+ print_line("loading at path "+String(source));
+ shader = ResourceLoader::load(source,"Shader");
+ }
+
+ print_line("found shader at "+String(source)+"? - "+itos(shader.is_null()));
+ if (shader.is_null()) //ah well..
+ continue;
+
+ get_scene()->get_root_node()->call("_resource_selected",shader);
+ }
+
+ if (p_state.has("current"))
+ tab_container->set_current_tab(p_state["current"]);
+#endif
+}
+void ShaderEditor::clear() {
+
+}
+
+void ShaderEditor::_params_changed() {
+
+
+ shader_editor->_validate_script();
+}
+
+void ShaderEditor::_editor_settings_changed() {
+
+ shader_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
+ shader_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
+ shader_editor->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/indent/tab_size"));
+ shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
+ shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers"));
+ shader_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
+ shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
+ shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
+ shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
+ shader_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
+ shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
+}
+
+void ShaderEditor::_bind_methods() {
+
+ ClassDB::bind_method("_editor_settings_changed",&ShaderEditor::_editor_settings_changed);
+
+ ClassDB::bind_method("_menu_option",&ShaderEditor::_menu_option);
+ ClassDB::bind_method("_params_changed",&ShaderEditor::_params_changed);
+ ClassDB::bind_method("apply_shaders",&ShaderEditor::apply_shaders);
+ //ClassDB::bind_method("_close_current_tab",&ShaderEditor::_close_current_tab);
+}
+
+void ShaderEditor::ensure_select_current() {
+
+/*
+ if (tab_container->get_child_count() && tab_container->get_current_tab()>=0) {
+
+ ShaderTextEditor *ste = tab_container->get_child(tab_container->get_current_tab())->cast_to<ShaderTextEditor>();
+ if (!ste)
+ return;
+ Ref<Shader> shader = ste->get_edited_shader();
+ get_scene()->get_root_node()->call("_resource_selected",shader);
+ }*/
+}
+
+void ShaderEditor::edit(const Ref<Shader>& p_shader) {
+
+ if (p_shader.is_null())
+ return;
+
+
+ shader=p_shader;
+
+ shader_editor->set_edited_shader(p_shader);
+
+ //vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX);
+ // see if already has it
+
+
+}
+
+void ShaderEditor::save_external_data() {
+
+ if (shader.is_null())
+ return;
+ apply_shaders();
+
+ if (shader->get_path()!="" && shader->get_path().find("local://")==-1 &&shader->get_path().find("::")==-1) {
+ //external shader, save it
+ ResourceSaver::save(shader->get_path(),shader);
+ }
+}
+
+void ShaderEditor::apply_shaders() {
+
+
+ if (shader.is_valid()) {
+ shader->set_code(shader_editor->get_text_edit()->get_text());
+ shader->set_edited(true);
+ }
+}
+
+
+ShaderEditor::ShaderEditor() {
+
+
+ HBoxContainer *hbc = memnew( HBoxContainer);
+
+ add_child(hbc);
+
+ edit_menu = memnew( MenuButton );
+ hbc->add_child(edit_menu);
+ edit_menu->set_pos(Point2(5,-1));
+ edit_menu->set_text(TTR("Edit"));
+ edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/undo", TTR("Undo"), KEY_MASK_CMD|KEY_Z), EDIT_UNDO);
+ edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/redo", TTR("Redo"), KEY_MASK_CMD|KEY_Y), EDIT_REDO);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/cut", TTR("Cut"), KEY_MASK_CMD|KEY_X), EDIT_CUT);
+ edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy", TTR("Copy"), KEY_MASK_CMD|KEY_C), EDIT_COPY);
+ edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/paste", TTR("Paste"), KEY_MASK_CMD|KEY_V), EDIT_PASTE);
+ edit_menu->get_popup()->add_separator();
+ edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/select_all", TTR("Select All"), KEY_MASK_CMD|KEY_A), EDIT_SELECT_ALL);
+ edit_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+
+
+ search_menu = memnew( MenuButton );
+ hbc->add_child(search_menu);
+ search_menu->set_pos(Point2(38,-1));
+ search_menu->set_text(TTR("Search"));
+ search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find.."), KEY_MASK_CMD|KEY_F), SEARCH_FIND);
+ search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), SEARCH_FIND_NEXT);
+ search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT|KEY_F3), SEARCH_FIND_PREV);
+ search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/replace", TTR("Replace.."), KEY_MASK_CMD|KEY_R), SEARCH_REPLACE);
+ search_menu->get_popup()->add_separator();
+ //search_menu->get_popup()->add_item("Locate Symbol..",SEARCH_LOCATE_SYMBOL,KEY_MASK_CMD|KEY_K);
+ search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/goto_line", TTR("Goto Line.."), KEY_MASK_CMD|KEY_L), SEARCH_GOTO_LINE);
+ search_menu->get_popup()->connect("id_pressed", this,"_menu_option");
+
+
+ goto_line_dialog = memnew(GotoLineDialog);
+ add_child(goto_line_dialog);
+
+ shader_editor = memnew( ShaderTextEditor );
+ add_child(shader_editor);
+ shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+
+
+ shader_editor->connect("script_changed", this,"apply_shaders");
+ EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed");
+
+ _editor_settings_changed();
+}
+
+
+void ShaderEditorPlugin::edit(Object *p_object) {
+
+ Shader* s = p_object->cast_to<Shader>();
+ shader_editor->edit(s);
+
+}
+
+bool ShaderEditorPlugin::handles(Object *p_object) const {
+
+ bool handles = true;
+ Shader *shader=p_object->cast_to<Shader>();
+ /*
+ if (!shader || shader->cast_to<ShaderGraph>()) // Dont handle ShaderGraph's
+ handles = false;
+ */
+
+ return shader!=NULL;
+}
+
+void ShaderEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ button->show();
+ editor->make_bottom_panel_item_visible(shader_editor);
+
+ } else {
+
+ button->hide();
+ if (shader_editor->is_visible_in_tree())
+ editor->hide_bottom_panel();
+ shader_editor->apply_shaders();
+
+ }
+
+}
+
+void ShaderEditorPlugin::selected_notify() {
+
+ shader_editor->ensure_select_current();
+}
+
+Dictionary ShaderEditorPlugin::get_state() const {
+
+ return shader_editor->get_state();
+}
+
+void ShaderEditorPlugin::set_state(const Dictionary& p_state) {
+
+ shader_editor->set_state(p_state);
+}
+void ShaderEditorPlugin::clear() {
+
+ shader_editor->clear();
+}
+
+void ShaderEditorPlugin::save_external_data() {
+
+ shader_editor->save_external_data();
+}
+
+void ShaderEditorPlugin::apply_changes() {
+
+ shader_editor->apply_shaders();
+}
+
+ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) {
+
+
+ editor=p_node;
+ shader_editor = memnew( ShaderEditor );
+
+ shader_editor->set_custom_minimum_size(Size2(0,300));
+ button=editor->add_bottom_panel_item("Shader",shader_editor);
+
+}
+
+
+ShaderEditorPlugin::~ShaderEditorPlugin() {
+}
+
+
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
new file mode 100644
index 0000000000..703913e431
--- /dev/null
+++ b/editor/plugins/shader_editor_plugin.h
@@ -0,0 +1,156 @@
+/*************************************************************************/
+/* shader_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SHADER_EDITOR_PLUGIN_H
+#define SHADER_EDITOR_PLUGIN_H
+
+#include "editor/code_editor.h"
+#include "editor/editor_plugin.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/text_edit.h"
+#include "scene/gui/menu_button.h"
+#include "scene/main/timer.h"
+#include "scene/resources/shader.h"
+#include "servers/visual/shader_language.h"
+
+class ShaderTextEditor : public CodeTextEditor {
+
+ GDCLASS( ShaderTextEditor, CodeTextEditor );
+
+ Ref<Shader> shader;
+
+protected:
+
+ static void _bind_methods();
+ virtual void _load_theme_settings();
+
+ virtual void _code_complete_script(const String& p_code, List<String>* r_options);
+
+public:
+
+ virtual void _validate_script();
+
+
+ Ref<Shader> get_edited_shader() const;
+ void set_edited_shader(const Ref<Shader>& p_shader);
+ ShaderTextEditor();
+
+};
+
+
+class ShaderEditor : public VBoxContainer {
+
+ GDCLASS(ShaderEditor, VBoxContainer );
+
+ enum {
+
+ EDIT_UNDO,
+ EDIT_REDO,
+ EDIT_CUT,
+ EDIT_COPY,
+ EDIT_PASTE,
+ EDIT_SELECT_ALL,
+ SEARCH_FIND,
+ SEARCH_FIND_NEXT,
+ SEARCH_FIND_PREV,
+ SEARCH_REPLACE,
+ //SEARCH_LOCATE_SYMBOL,
+ SEARCH_GOTO_LINE,
+
+ };
+
+ MenuButton *edit_menu;
+ MenuButton *search_menu;
+ MenuButton *settings_menu;
+ uint64_t idle;
+
+ GotoLineDialog *goto_line_dialog;
+ ConfirmationDialog *erase_tab_confirm;
+
+
+ ShaderTextEditor *shader_editor;
+
+
+ void _menu_option(int p_optin);
+ void _params_changed();
+ mutable Ref<Shader> shader;
+
+
+ void _editor_settings_changed();
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void apply_shaders();
+
+ void ensure_select_current();
+ void edit(const Ref<Shader>& p_shader);
+
+ Dictionary get_state() const;
+ void set_state(const Dictionary& p_state);
+ void clear();
+
+ virtual Size2 get_minimum_size() const { return Size2(0,200); }
+ void save_external_data();
+
+ ShaderEditor();
+};
+
+class ShaderEditorPlugin : public EditorPlugin {
+
+ GDCLASS( ShaderEditorPlugin, EditorPlugin );
+
+ bool _2d;
+ ShaderEditor *shader_editor;
+ EditorNode *editor;
+ Button *button;
+
+public:
+
+ virtual String get_name() const { return "Shader"; }
+ 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);
+ virtual void selected_notify();
+
+ Dictionary get_state() const;
+ virtual void set_state(const Dictionary& p_state);
+ virtual void clear();
+
+ virtual void save_external_data();
+ virtual void apply_changes();
+
+ ShaderEditorPlugin(EditorNode *p_node);
+ ~ShaderEditorPlugin();
+
+};
+
+#endif
diff --git a/editor/plugins/shader_graph_editor_plugin.cpp b/editor/plugins/shader_graph_editor_plugin.cpp
new file mode 100644
index 0000000000..dac63b4a9f
--- /dev/null
+++ b/editor/plugins/shader_graph_editor_plugin.cpp
@@ -0,0 +1,2948 @@
+/*************************************************************************/
+/* shader_graph_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "shader_graph_editor_plugin.h"
+
+#if 0
+
+#include "scene/gui/check_box.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/panel.h"
+#include "spatial_editor_plugin.h"
+#include "os/keyboard.h"
+#include "canvas_item_editor_plugin.h"
+
+void GraphColorRampEdit::_gui_input(const InputEvent& p_event) {
+
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) {
+
+ points.remove(grabbed);
+ grabbed=-1;
+ update();
+ emit_signal("ramp_changed");
+ accept_event();
+ }
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+
+ update();
+ int x = p_event.mouse_button.x;
+ int total_w = get_size().width-get_size().height-3;
+ if (x>total_w+3) {
+
+ if (grabbed==-1)
+ return;
+ Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10);
+ picker->set_color(points[grabbed].color);
+ popup->set_pos(get_global_pos()-Size2(0,ms.height));
+ popup->set_size(ms);
+ popup->popup();
+ return;
+ }
+
+
+ float ofs = CLAMP(x/float(total_w),0,1);
+
+ grabbed=-1;
+ grabbing=true;
+ int pos=-1;
+ for(int i=0;i<points.size();i++) {
+
+ if (ABS(x-points[i].offset*total_w)<4) {
+ grabbed=i;
+ }
+ if (points[i].offset<ofs)
+ pos=i;
+ }
+
+ grabbed_at=ofs;
+ //grab or select
+ if (grabbed!=-1) {
+ return;
+ }
+ //insert
+
+
+ Point p;
+ p.offset=ofs;
+
+ Point prev;
+ Point next;
+
+ if (pos==-1) {
+
+ prev.color=Color(0,0,0);
+ prev.offset=0;
+ if (points.size()) {
+ next=points[0];
+ } else {
+ next.color=Color(1,1,1);
+ next.offset=1.0;
+ }
+ } else {
+
+ if (pos==points.size()-1) {
+ next.color=Color(1,1,1);
+ next.offset=1.0;
+ } else {
+ next=points[pos+1];
+ }
+ prev=points[pos];
+
+ }
+
+ p.color=prev.color.linear_interpolate(next.color,(p.offset-prev.offset)/(next.offset-prev.offset));
+
+ points.push_back(p);
+ points.sort();
+ for(int i=0;i<points.size();i++) {
+ if (points[i].offset==ofs) {
+ grabbed=i;
+ break;
+ }
+ }
+
+ emit_signal("ramp_changed");
+
+ }
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) {
+
+ if (grabbing) {
+ grabbing=false;
+ emit_signal("ramp_changed");
+ }
+ update();
+ }
+
+ if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) {
+
+ int total_w = get_size().width-get_size().height-3;
+
+ int x = p_event.mouse_motion.x;
+ float newofs = CLAMP(x/float(total_w),0,1);
+
+ bool valid=true;
+ for(int i=0;i<points.size();i++) {
+
+ if (points[i].offset==newofs && i!=grabbed) {
+ valid=false;
+ }
+ }
+
+ if (!valid)
+ return;
+
+ points[grabbed].offset=newofs;
+
+ points.sort();
+ for(int i=0;i<points.size();i++) {
+ if (points[i].offset==newofs) {
+ grabbed=i;
+ break;
+ }
+ }
+
+ emit_signal("ramp_changed");
+
+ update();
+ }
+}
+
+void GraphColorRampEdit::_notification(int p_what){
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ if (!picker->is_connected("color_changed",this,"_color_changed")) {
+ picker->connect("color_changed",this,"_color_changed");
+ }
+ }
+ if (p_what==NOTIFICATION_DRAW) {
+
+
+ Point prev;
+ prev.offset=0;
+ prev.color=Color(0,0,0);
+
+ int h = get_size().y;
+ int total_w = get_size().width-get_size().height-3;
+
+ for(int i=-1;i<points.size();i++) {
+
+ Point next;
+ if (i+1==points.size()) {
+ next.color=Color(1,1,1);
+ next.offset=1;
+ } else {
+ next=points[i+1];
+ }
+
+ if (prev.offset==next.offset) {
+ prev=next;
+ continue;
+ }
+
+ Vector<Vector2> points;
+ Vector<Color> colors;
+ points.push_back(Vector2(prev.offset*total_w,h));
+ points.push_back(Vector2(prev.offset*total_w,0));
+ points.push_back(Vector2(next.offset*total_w,0));
+ points.push_back(Vector2(next.offset*total_w,h));
+ colors.push_back(prev.color);
+ colors.push_back(prev.color);
+ colors.push_back(next.color);
+ colors.push_back(next.color);
+ draw_primitive(points,colors,Vector<Point2>());
+ prev=next;
+ }
+
+ for(int i=0;i<points.size();i++) {
+
+ Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8);
+
+ draw_line(Vector2(points[i].offset*total_w,0),Vector2(points[i].offset*total_w,h-1),Color(0,0,0,0.7));
+ draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w-1,h-1),col);
+ draw_line(Vector2(points[i].offset*total_w+1,h/2),Vector2(points[i].offset*total_w+1,h-1),col);
+ draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w+1,h/2),col);
+ draw_line(Vector2(points[i].offset*total_w-1,h-1),Vector2(points[i].offset*total_w+1,h-1),col);
+
+ }
+
+ if (grabbed!=-1) {
+
+ draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color);
+ }
+
+ if (has_focus()) {
+
+ draw_line(Vector2(-1,-1),Vector2(total_w+1,-1),Color(1,1,1,0.6));
+ draw_line(Vector2(total_w+1,-1),Vector2(total_w+1,h+1),Color(1,1,1,0.6));
+ draw_line(Vector2(total_w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6));
+ draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6));
+ }
+
+ }
+}
+
+Size2 GraphColorRampEdit::get_minimum_size() const {
+
+ return Vector2(0,16);
+}
+
+
+void GraphColorRampEdit::_color_changed(const Color& p_color) {
+
+ if (grabbed==-1)
+ return;
+ points[grabbed].color=p_color;
+ update();
+ emit_signal("ramp_changed");
+
+}
+
+void GraphColorRampEdit::set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors) {
+
+ ERR_FAIL_COND(p_offsets.size()!=p_colors.size());
+ points.clear();
+ for(int i=0;i<p_offsets.size();i++) {
+ Point p;
+ p.offset=p_offsets[i];
+ p.color=p_colors[i];
+ points.push_back(p);
+ }
+
+ points.sort();
+ update();
+}
+
+Vector<float> GraphColorRampEdit::get_offsets() const{
+ Vector<float> ret;
+ for(int i=0;i<points.size();i++)
+ ret.push_back(points[i].offset);
+ return ret;
+}
+Vector<Color> GraphColorRampEdit::get_colors() const{
+
+ Vector<Color> ret;
+ for(int i=0;i<points.size();i++)
+ ret.push_back(points[i].color);
+ return ret;
+}
+
+
+void GraphColorRampEdit::_bind_methods(){
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&GraphColorRampEdit::_gui_input);
+ ClassDB::bind_method(D_METHOD("_color_changed"),&GraphColorRampEdit::_color_changed);
+ ADD_SIGNAL(MethodInfo("ramp_changed"));
+}
+
+GraphColorRampEdit::GraphColorRampEdit(){
+
+ grabbed=-1;
+ grabbing=false;
+ set_focus_mode(FOCUS_ALL);
+
+ popup = memnew( PopupPanel );
+ picker = memnew( ColorPicker );
+ popup->add_child(picker);
+ /popup->set_child_rect(picker);
+ add_child(popup);
+
+}
+////////////
+
+void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
+
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) {
+
+ points.remove(grabbed);
+ grabbed=-1;
+ update();
+ emit_signal("curve_changed");
+ accept_event();
+ }
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
+
+ update();
+ Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size();
+ p.y=1.0-p.y;
+ grabbed=-1;
+ grabbing=true;
+
+ for(int i=0;i<points.size();i++) {
+
+ Vector2 ps = p*get_size();
+ Vector2 pt = Vector2(points[i].offset,points[i].height)*get_size();
+ if (ps.distance_to(pt)<4) {
+ grabbed=i;
+ }
+
+ }
+
+
+ //grab or select
+ if (grabbed!=-1) {
+ return;
+ }
+ //insert
+
+
+ Point np;
+ np.offset=p.x;
+ np.height=p.y;
+
+ points.push_back(np);
+ points.sort();
+ for(int i=0;i<points.size();i++) {
+ if (points[i].offset==p.x && points[i].height==p.y) {
+ grabbed=i;
+ break;
+ }
+ }
+
+ emit_signal("curve_changed");
+
+ }
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) {
+
+ if (grabbing) {
+ grabbing=false;
+ emit_signal("curve_changed");
+ }
+ update();
+ }
+
+ if (p_event.type==InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) {
+
+ Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size();
+ p.y=1.0-p.y;
+
+ p.x = CLAMP(p.x,0.0,1.0);
+ p.y = CLAMP(p.y,0.0,1.0);
+
+ bool valid=true;
+
+ for(int i=0;i<points.size();i++) {
+
+ if (points[i].offset==p.x && points[i].height==p.y && i!=grabbed) {
+ valid=false;
+ }
+ }
+
+ if (!valid)
+ return;
+
+ points[grabbed].offset=p.x;
+ points[grabbed].height=p.y;
+
+ points.sort();
+ for(int i=0;i<points.size();i++) {
+ if (points[i].offset==p.x && points[i].height==p.y) {
+ grabbed=i;
+ break;
+ }
+ }
+
+ emit_signal("curve_changed");
+
+ update();
+ }
+}
+
+void GraphCurveMapEdit::_plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d) {
+
+ float geometry[4][4];
+ float tmp1[4][4];
+ float tmp2[4][4];
+ float deltas[4][4];
+ double x, dx, dx2, dx3;
+ double y, dy, dy2, dy3;
+ double d, d2, d3;
+ int lastx, lasty;
+ int newx, newy;
+ int ntimes;
+ int i,j;
+
+ int xmax=get_size().x;
+ int ymax=get_size().y;
+
+ /* construct the geometry matrix from the segment */
+ for (i = 0; i < 4; i++) {
+ geometry[i][2] = 0;
+ geometry[i][3] = 0;
+ }
+
+ geometry[0][0] = (p_a[0] * xmax);
+ geometry[1][0] = (p_b[0] * xmax);
+ geometry[2][0] = (p_c[0] * xmax);
+ geometry[3][0] = (p_d[0] * xmax);
+
+ geometry[0][1] = (p_a[1] * ymax);
+ geometry[1][1] = (p_b[1] * ymax);
+ geometry[2][1] = (p_c[1] * ymax);
+ geometry[3][1] = (p_d[1] * ymax);
+
+ /* subdivide the curve ntimes (1000) times */
+ ntimes = 4 * xmax;
+ /* ntimes can be adjusted to give a finer or coarser curve */
+ d = 1.0 / ntimes;
+ d2 = d * d;
+ d3 = d * d * d;
+
+ /* construct a temporary matrix for determining the forward differencing deltas */
+ tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1;
+ tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0;
+ tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0;
+ tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0;
+
+ /* compose the basis and geometry matrices */
+
+ static const float CR_basis[4][4] = {
+ { -0.5, 1.5, -1.5, 0.5 },
+ { 1.0, -2.5, 2.0, -0.5 },
+ { -0.5, 0.0, 0.5, 0.0 },
+ { 0.0, 1.0, 0.0, 0.0 },
+ };
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] +
+ CR_basis[i][1] * geometry[1][j] +
+ CR_basis[i][2] * geometry[2][j] +
+ CR_basis[i][3] * geometry[3][j]);
+ }
+ }
+ /* compose the above results to get the deltas matrix */
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ deltas[i][j] = (tmp2[i][0] * tmp1[0][j] +
+ tmp2[i][1] * tmp1[1][j] +
+ tmp2[i][2] * tmp1[2][j] +
+ tmp2[i][3] * tmp1[3][j]);
+ }
+ }
+
+
+ /* extract the x deltas */
+ x = deltas[0][0];
+ dx = deltas[1][0];
+ dx2 = deltas[2][0];
+ dx3 = deltas[3][0];
+
+ /* extract the y deltas */
+ y = deltas[0][1];
+ dy = deltas[1][1];
+ dy2 = deltas[2][1];
+ dy3 = deltas[3][1];
+
+
+ lastx = CLAMP (x, 0, xmax);
+ lasty = CLAMP (y, 0, ymax);
+
+ /* if (fix255)
+ {
+ cd->curve[cd->outline][lastx] = lasty;
+ }
+ else
+ {
+ cd->curve_ptr[cd->outline][lastx] = lasty;
+ if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax);
+ }
+*/
+ /* loop over the curve */
+ for (i = 0; i < ntimes; i++)
+ {
+ /* increment the x values */
+ x += dx;
+ dx += dx2;
+ dx2 += dx3;
+
+ /* increment the y values */
+ y += dy;
+ dy += dy2;
+ dy2 += dy3;
+
+ newx = CLAMP ((Math::round (x)), 0, xmax);
+ newy = CLAMP ((Math::round (y)), 0, ymax);
+
+ /* if this point is different than the last one...then draw it */
+ if ((lastx != newx) || (lasty != newy))
+ {
+#if 0
+ if(fix255)
+ {
+ /* use fixed array size (for the curve graph) */
+ cd->curve[cd->outline][newx] = newy;
+ }
+ else
+ {
+ /* use dynamic allocated curve_ptr (for the real curve) */
+ cd->curve_ptr[cd->outline][newx] = newy;
+
+ if(gb_debug) printf("outline: %d cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy);
+ }
+#endif
+ draw_line(Vector2(lastx,ymax-lasty),Vector2(newx,ymax-newy),Color(0.8,0.8,0.8,0.8),2.0);
+ }
+
+ lastx = newx;
+ lasty = newy;
+ }
+}
+
+
+void GraphCurveMapEdit::_notification(int p_what){
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ draw_style_box(get_stylebox("bg","Tree"),Rect2(Point2(),get_size()));
+
+ int w = get_size().x;
+ int h = get_size().y;
+
+ Vector2 prev=Vector2(0,0);
+ Vector2 prev2=Vector2(0,0);
+
+ for(int i=-1;i<points.size();i++) {
+
+ Vector2 next;
+ Vector2 next2;
+ if (i+1>=points.size()) {
+ next=Vector2(1,1);
+ } else {
+ next=Vector2(points[i+1].offset,points[i+1].height);
+ }
+
+ if (i+2>=points.size()) {
+ next2=Vector2(1,1);
+ } else {
+ next2=Vector2(points[i+2].offset,points[i+2].height);
+ }
+
+ /*if (i==-1 && prev.offset==next.offset) {
+ prev=next;
+ continue;
+ }*/
+
+ _plot_curve(prev2,prev,next,next2);
+
+ prev2=prev;
+ prev=next;
+ }
+
+ for(int i=0;i<points.size();i++) {
+
+ Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8);
+
+
+ draw_rect(Rect2( Vector2(points[i].offset,1.0-points[i].height)*get_size()-Vector2(2,2),Vector2(5,5)),col);
+ }
+
+ /* if (grabbed!=-1) {
+
+ draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color);
+ }
+*/
+ if (has_focus()) {
+
+ draw_line(Vector2(-1,-1),Vector2(w+1,-1),Color(1,1,1,0.6));
+ draw_line(Vector2(w+1,-1),Vector2(w+1,h+1),Color(1,1,1,0.6));
+ draw_line(Vector2(w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6));
+ draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6));
+ }
+
+ }
+}
+
+Size2 GraphCurveMapEdit::get_minimum_size() const {
+
+ return Vector2(64,64);
+}
+
+
+
+void GraphCurveMapEdit::set_points(const Vector<Vector2>& p_points) {
+
+
+ points.clear();
+ for(int i=0;i<p_points.size();i++) {
+ Point p;
+ p.offset=p_points[i].x;
+ p.height=p_points[i].y;
+ points.push_back(p);
+ }
+
+ points.sort();
+ update();
+}
+
+Vector<Vector2> GraphCurveMapEdit::get_points() const {
+ Vector<Vector2> ret;
+ for(int i=0;i<points.size();i++)
+ ret.push_back(Vector2(points[i].offset,points[i].height));
+ return ret;
+}
+
+void GraphCurveMapEdit::_bind_methods(){
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&GraphCurveMapEdit::_gui_input);
+ ADD_SIGNAL(MethodInfo("curve_changed"));
+}
+
+GraphCurveMapEdit::GraphCurveMapEdit(){
+
+ grabbed=-1;
+ grabbing=false;
+ set_focus_mode(FOCUS_ALL);
+
+}
+
+
+////cbacks
+///
+void ShaderGraphView::_scalar_const_changed(double p_value,int p_id) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Scalar Constant"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,p_value);
+ ur->add_undo_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,graph->scalar_const_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+
+void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){
+
+ Vector3 val;
+ for(int i=0;i<p_arr.size();i++) {
+ val[i]=p_arr[i].call("get_val");
+ }
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Vec Constant"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(graph.ptr(),"vec_const_node_set_value",type,p_id,val);
+ ur->add_undo_method(graph.ptr(),"vec_const_node_set_value",type,p_id,graph->vec_const_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+void ShaderGraphView::_rgb_const_changed(const Color& p_color, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change RGB Constant"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,p_color);
+ ur->add_undo_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,graph->rgb_const_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+void ShaderGraphView::_scalar_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Scalar Operator"));
+ ur->add_do_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,graph->scalar_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+void ShaderGraphView::_vec_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Vec Operator"));
+ ur->add_do_method(graph.ptr(),"vec_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"vec_op_node_set_op",type,p_id,graph->vec_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_vec_scalar_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Vec Scalar Operator"));
+ ur->add_do_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,graph->vec_scalar_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+void ShaderGraphView::_rgb_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change RGB Operator"));
+ ur->add_do_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,graph->rgb_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_xform_inv_rev_changed(bool p_enabled, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Toggle Rot Only"));
+ ur->add_do_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,p_enabled);
+ ur->add_undo_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,graph->xform_vec_mult_node_get_no_translation(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_scalar_func_changed(int p_func, int p_id){
+
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Scalar Function"));
+ ur->add_do_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,p_func);
+ ur->add_undo_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,graph->scalar_func_node_get_function(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_vec_func_changed(int p_func, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Vec Function"));
+ ur->add_do_method(graph.ptr(),"vec_func_node_set_function",type,p_id,p_func);
+ ur->add_undo_method(graph.ptr(),"vec_func_node_set_function",type,p_id,graph->vec_func_node_get_function(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+void ShaderGraphView::_scalar_input_changed(double p_value,int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Scalar Uniform"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,p_value);
+ ur->add_undo_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,graph->scalar_input_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){
+
+ Vector3 val;
+ for(int i=0;i<p_arr.size();i++) {
+ val[i]=p_arr[i].call("get_val");
+ }
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Vec Uniform"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(graph.ptr(),"vec_input_node_set_value",type,p_id,val);
+ ur->add_undo_method(graph.ptr(),"vec_input_node_set_value",type,p_id,graph->vec_input_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){
+
+
+ ToolButton *tb = p_button->cast_to<ToolButton>();
+ ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
+ ped_popup->set_size(tb->get_size());
+ edited_id=p_id;
+ edited_def=-1;
+ ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_input_node_get_value(type,p_id),PROPERTY_HINT_NONE,"");
+ ped_popup->popup();
+
+}
+void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){
+
+ ToolButton *tb = p_button->cast_to<ToolButton>();
+ ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
+ ped_popup->set_size(tb->get_size());
+ edited_id=p_id;
+ edited_def=-1;
+ ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_const_node_get_value(type,p_id),PROPERTY_HINT_NONE,"");
+ ped_popup->popup();
+
+}
+
+void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){
+
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change RGB Uniform"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,p_color);
+ ur->add_undo_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,graph->rgb_input_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_tex_input_change(int p_id, Node *p_button){
+
+
+}
+void ShaderGraphView::_cube_input_change(int p_id){
+
+
+}
+
+void ShaderGraphView::_variant_edited() {
+
+ if (edited_def != -1) {
+
+ Variant v = ped_popup->get_variant();
+ Variant v2 = graph->default_get_value(type,edited_id,edited_def);
+ if (v2.get_type() == Variant::NIL)
+ switch (v.get_type()) {
+ case Variant::VECTOR3:
+ v2=Vector3();
+ break;
+ case Variant::REAL:
+ v2=0.0;
+ break;
+ case Variant::TRANSFORM:
+ v2=Transform();
+ break;
+ case Variant::COLOR:
+ v2=Color();
+ break;
+ default: {}
+ }
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Default Value"));
+ ur->add_do_method(graph.ptr(),"default_set_value",type,edited_id,edited_def, v);
+ ur->add_undo_method(graph.ptr(),"default_set_value",type,edited_id,edited_def, v2);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ return;
+ }
+
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change XForm Uniform"));
+ ur->add_do_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,graph->xform_const_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
+
+
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_INPUT) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change XForm Uniform"));
+ ur->add_do_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,graph->xform_input_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
+
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_TEXTURE_INPUT) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Texture Uniform"));
+ ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,graph->texture_input_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
+
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_CUBEMAP_INPUT) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Cubemap Uniform"));
+ ur->add_do_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,graph->cubemap_input_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
+
+}
+
+void ShaderGraphView::_comment_edited(int p_id,Node* p_button) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ TextEdit *te=p_button->cast_to<TextEdit>();
+ ur->create_action(TTR("Change Comment"),UndoRedo::MERGE_ENDS);
+ ur->add_do_method(graph.ptr(),"comment_node_set_text",type,p_id,te->get_text());
+ ur->add_undo_method(graph.ptr(),"comment_node_set_text",type,p_id,graph->comment_node_get_text(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+
+}
+
+void ShaderGraphView::_color_ramp_changed(int p_id,Node* p_ramp) {
+
+ GraphColorRampEdit *cr=p_ramp->cast_to<GraphColorRampEdit>();
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+
+ Vector<float> offsets=cr->get_offsets();
+ Vector<Color> colors=cr->get_colors();
+
+ PoolVector<float> new_offsets;
+ PoolVector<Color> new_colors;
+ {
+ new_offsets.resize(offsets.size());
+ new_colors.resize(colors.size());
+ PoolVector<float>::Write ow=new_offsets.write();
+ PoolVector<Color>::Write cw=new_colors.write();
+ for(int i=0;i<new_offsets.size();i++) {
+ ow[i]=offsets[i];
+ cw[i]=colors[i];
+ }
+
+ }
+
+
+ PoolVector<float> old_offsets=graph->color_ramp_node_get_offsets(type,p_id);
+ PoolVector<Color> old_colors=graph->color_ramp_node_get_colors(type,p_id);
+
+ if (old_offsets.size()!=new_offsets.size())
+ ur->create_action(TTR("Add/Remove to Color Ramp"));
+ else
+ ur->create_action(TTR("Modify Color Ramp"),UndoRedo::MERGE_ENDS);
+
+ ur->add_do_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,new_colors,new_offsets);
+ ur->add_undo_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,old_colors,old_offsets);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+
+void ShaderGraphView::_curve_changed(int p_id,Node* p_curve) {
+
+ GraphCurveMapEdit *cr=p_curve->cast_to<GraphCurveMapEdit>();
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+
+ Vector<Point2> points=cr->get_points();
+
+ PoolVector<Vector2> new_points;
+ {
+ new_points.resize(points.size());
+ PoolVector<Vector2>::Write ow=new_points.write();
+ for(int i=0;i<new_points.size();i++) {
+ ow[i]=points[i];
+ }
+
+ }
+
+
+ PoolVector<Vector2> old_points=graph->curve_map_node_get_points(type,p_id);
+
+ if (old_points.size()!=new_points.size())
+ ur->create_action(TTR("Add/Remove to Curve Map"));
+ else
+ ur->create_action(TTR("Modify Curve Map"),UndoRedo::MERGE_ENDS);
+
+ ur->add_do_method(graph.ptr(),"curve_map_node_set_points",type,p_id,new_points);
+ ur->add_undo_method(graph.ptr(),"curve_map_node_set_points",type,p_id,old_points);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+
+
+void ShaderGraphView::_input_name_changed(const String& p_name, int p_id, Node *p_line_edit) {
+
+ LineEdit *le=p_line_edit->cast_to<LineEdit>();
+ ERR_FAIL_COND(!le);
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Input Name"));
+ ur->add_do_method(graph.ptr(),"input_node_set_name",type,p_id,p_name);
+ ur->add_undo_method(graph.ptr(),"input_node_set_name",type,p_id,graph->input_node_get_name(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+ le->set_text(graph->input_node_get_name(type,p_id));
+}
+
+void ShaderGraphView::_tex_edited(int p_id,Node* p_button) {
+
+ ToolButton *tb = p_button->cast_to<ToolButton>();
+ ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
+ ped_popup->set_size(tb->get_size());
+ edited_id=p_id;
+ edited_def=-1;
+ ped_popup->edit(NULL,"",Variant::OBJECT,graph->texture_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"Texture");
+}
+
+void ShaderGraphView::_cube_edited(int p_id,Node* p_button) {
+
+ ToolButton *tb = p_button->cast_to<ToolButton>();
+ ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
+ ped_popup->set_size(tb->get_size());
+ edited_id=p_id;
+ edited_def=-1;
+ ped_popup->edit(NULL,"",Variant::OBJECT,graph->cubemap_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"CubeMap");
+}
+
+
+//////////////view/////////////
+
+
+void ShaderGraphView::_connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+ int from_idx=-1;
+ int to_idx=-1;
+ for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
+
+ if (p_from==E->get()->get_name())
+ from_idx=E->key();
+ if (p_to==E->get()->get_name())
+ to_idx=E->key();
+ }
+
+ ERR_FAIL_COND(from_idx==-1);
+ ERR_FAIL_COND(to_idx==-1);
+
+ ur->create_action(TTR("Connect Graph Nodes"));
+
+ List<ShaderGraph::Connection> conns;
+
+ graph->get_node_connections(type,&conns);
+ //disconnect/reconnect dependencies
+ ur->add_undo_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
+ for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
+
+ if (E->get().dst_id==to_idx && E->get().dst_slot==p_to_slot) {
+ ur->add_do_method(graph.ptr(),"disconnect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
+ ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
+ }
+ }
+ ur->add_do_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+
+
+}
+
+void ShaderGraphView::_disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+
+ int from_idx=-1;
+ int to_idx=-1;
+ for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
+
+ if (p_from==E->get()->get_name())
+ from_idx=E->key();
+ if (p_to==E->get()->get_name())
+ to_idx=E->key();
+ }
+
+ ERR_FAIL_COND(from_idx==-1);
+ ERR_FAIL_COND(to_idx==-1);
+
+ if (!graph->is_node_connected(type,from_idx,p_from_slot,to_idx,p_to_slot))
+ return; //nothing to disconnect
+
+ ur->create_action(TTR("Disconnect Graph Nodes"));
+
+ List<ShaderGraph::Connection> conns;
+
+ graph->get_node_connections(type,&conns);
+ //disconnect/reconnect dependencies
+ ur->add_do_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
+ ur->add_undo_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+
+
+}
+
+void ShaderGraphView::_node_removed(int p_id) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Remove Shader Graph Node"));
+
+ ur->add_do_method(graph.ptr(),"node_remove",type,p_id);
+ ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,p_id),p_id);
+ ur->add_undo_method(graph.ptr(),"node_set_state",type,p_id,graph->node_get_state(type,p_id));
+ List<ShaderGraph::Connection> conns;
+
+ graph->get_node_connections(type,&conns);
+ for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
+
+ if (E->get().dst_id==p_id || E->get().src_id==p_id) {
+ ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
+ }
+ }
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+
+}
+
+void ShaderGraphView::_begin_node_move()
+{
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Move Shader Graph Node"));
+}
+
+void ShaderGraphView::_node_moved(const Vector2& p_from, const Vector2& p_to,int p_id) {
+
+
+ ERR_FAIL_COND(!node_map.has(p_id));
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->add_do_method(this,"_move_node",p_id,p_to);
+ ur->add_undo_method(this,"_move_node",p_id,p_from);
+}
+
+void ShaderGraphView::_end_node_move()
+{
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->commit_action();
+}
+
+void ShaderGraphView::_move_node(int p_id,const Vector2& p_to) {
+
+ ERR_FAIL_COND(!node_map.has(p_id));
+ node_map[p_id]->set_offset(p_to);
+ graph->node_set_pos(type,p_id,p_to);
+}
+
+void ShaderGraphView::_duplicate_nodes_request()
+{
+ Array s_id;
+
+ for(Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
+ ShaderGraph::NodeType t=graph->node_get_type(type, E->key());
+ if (t==ShaderGraph::NODE_OUTPUT || t==ShaderGraph::NODE_INPUT)
+ continue;
+ GraphNode *gn = E->get();
+ if (gn && gn->is_selected())
+ s_id.push_back(E->key());
+ }
+
+ if (s_id.size()==0)
+ return;
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Duplicate Graph Node(s)"));
+ ur->add_do_method(this,"_duplicate_nodes",s_id);
+ List<int> n_ids = graph->generate_ids(type, s_id.size());
+ for (List<int>::Element *E=n_ids.front();E;E=E->next())
+ ur->add_undo_method(graph.ptr(),"node_remove",type,E->get());
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+
+}
+
+void ShaderGraphView::_duplicate_nodes(const Array &p_nodes)
+{
+ List<int> n = List<int>();
+ for (int i=0; i<p_nodes.size();i++)
+ n.push_back(p_nodes.get(i));
+ graph->duplicate_nodes(type, n);
+ call_deferred("_update_graph");
+}
+
+void ShaderGraphView::_delete_nodes_request()
+{
+ List<int> s_id=List<int>();
+
+ for(Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
+ ShaderGraph::NodeType t=graph->node_get_type(type, E->key());
+ if (t==ShaderGraph::NODE_OUTPUT)
+ continue;
+ GraphNode *gn = E->get();
+ if (gn && gn->is_selected())
+ s_id.push_back(E->key());
+ }
+
+ if (s_id.size()==0)
+ return;
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Delete Shader Graph Node(s)"));
+
+ for (List<int>::Element *N=s_id.front();N;N=N->next()) {
+ ur->add_do_method(graph.ptr(),"node_remove",type,N->get());
+ ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,N->get()),N->get());
+ ur->add_undo_method(graph.ptr(),"node_set_state",type,N->get(),graph->node_get_state(type,N->get()));
+ List<ShaderGraph::Connection> conns;
+
+ graph->get_node_connections(type,&conns);
+ for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
+
+ if (E->get().dst_id==N->get() || E->get().src_id==N->get()) {
+ ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
+ }
+ }
+ }
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+
+}
+
+void ShaderGraphView::_default_changed(int p_id, Node *p_button, int p_param, int v_type, String p_hint)
+{
+ ToolButton *tb = p_button->cast_to<ToolButton>();
+ ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
+ ped_popup->set_size(tb->get_size());
+ edited_id=p_id;
+ edited_def=p_param;
+ Variant::Type vt = (Variant::Type)v_type;
+ Variant v = graph->default_get_value(type,p_id,edited_def);
+ int h=PROPERTY_HINT_NONE;
+ if (v.get_type() == Variant::NIL)
+ switch (vt) {
+ case Variant::VECTOR3:
+ v=Vector3();
+ break;
+ case Variant::REAL:
+ h=PROPERTY_HINT_RANGE;
+ v=0.0;
+ break;
+ case Variant::TRANSFORM:
+ v=Transform();
+ break;
+ case Variant::COLOR:
+ h=PROPERTY_HINT_COLOR_NO_ALPHA;
+ v=Color();
+ break;
+ default: {}
+ }
+
+ ped_popup->edit(NULL,"",vt,v,h,p_hint);
+
+ ped_popup->popup();
+}
+
+ToolButton *ShaderGraphView::make_label(String text, Variant::Type v_type) {
+ ToolButton *l = memnew( ToolButton );
+ l->set_text(text);
+ l->set_text_align(ToolButton::ALIGN_LEFT);
+ l->add_style_override("hover", l->get_stylebox("normal", "ToolButton"));
+ l->add_style_override("pressed", l->get_stylebox("normal", "ToolButton"));
+ l->add_style_override("focus", l->get_stylebox("normal", "ToolButton"));
+ switch (v_type) {
+ case Variant::REAL:
+ l->set_icon(ped_popup->get_icon("Real", "EditorIcons"));
+ break;
+ case Variant::VECTOR3:
+ l->set_icon(ped_popup->get_icon("Vector", "EditorIcons"));
+ break;
+ case Variant::TRANSFORM:
+ l->set_icon(ped_popup->get_icon("Matrix", "EditorIcons"));
+ break;
+ case Variant::COLOR:
+ l->set_icon(ped_popup->get_icon("Color", "EditorIcons"));
+ break;
+ default: {}
+ }
+ return l;
+}
+
+ToolButton *ShaderGraphView::make_editor(String text,GraphNode* gn,int p_id,int param,Variant::Type v_type, String p_hint) {
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text(text);
+ edit->set_text_align(ToolButton::ALIGN_LEFT);
+ edit->set_flat(false);
+ edit->add_style_override("normal", gn->get_stylebox("defaultframe", "GraphNode"));
+ edit->add_style_override("hover", gn->get_stylebox("defaultframe", "GraphNode"));
+ edit->add_style_override("pressed", gn->get_stylebox("defaultframe", "GraphNode"));
+ edit->add_style_override("focus", gn->get_stylebox("defaultfocus", "GraphNode"));
+ edit->connect("pressed",this,"_default_changed",varray(p_id,edit,param,v_type,p_hint));
+
+ switch (v_type) {
+ case Variant::REAL:
+ edit->set_icon(ped_popup->get_icon("Real", "EditorIcons"));
+ break;
+ case Variant::VECTOR3:
+ edit->set_icon(ped_popup->get_icon("Vector", "EditorIcons"));
+ break;
+ case Variant::TRANSFORM:
+ edit->set_icon(ped_popup->get_icon("Matrix", "EditorIcons"));
+ break;
+ case Variant::COLOR: {
+ Image icon_color = Image(15,15,false,Image::FORMAT_RGB8);
+ Color c = graph->default_get_value(type,p_id,param);
+ for (int x=1;x<14;x++)
+ for (int y=1;y<14;y++)
+ icon_color.put_pixel(x,y,c);
+ Ref<ImageTexture> t;
+ t.instance();
+ t->create_from_image(icon_color);
+ edit->set_icon(t);
+ } break;
+ default: {}
+ }
+ return edit;
+}
+
+void ShaderGraphView::_create_node(int p_id) {
+
+
+ GraphNode *gn = memnew( GraphNode );
+ gn->set_show_close_button(true);
+ Color typecol[4]={
+ Color(0.9,0.4,1),
+ Color(0.8,1,0.2),
+ Color(1,0.2,0.2),
+ Color(0,1,1)
+ };
+
+ const String hint_spin = "-65536,65535,0.001";
+ const String hint_slider = "0.0,1.0,0.01,slider";
+
+
+ switch(graph->node_get_type(type,p_id)) {
+
+ case ShaderGraph::NODE_INPUT: {
+
+ gn->set_title("Input");
+
+ List<ShaderGraph::SlotInfo> si;
+ ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si);
+
+ int idx=0;
+ for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) {
+ ShaderGraph::SlotInfo& s=E->get();
+ if (s.dir==ShaderGraph::SLOT_IN) {
+
+ Label *l= memnew( Label );
+ l->set_text(s.name);
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+ gn->set_slot(idx,false,0,Color(),true,s.type,typecol[s.type]);
+ idx++;
+ }
+ }
+
+ } break; // all inputs (case Shader type dependent)
+ case ShaderGraph::NODE_SCALAR_CONST: {
+ gn->set_title("Scalar");
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->scalar_const_node_get_value(type,p_id));
+ sb->connect("value_changed",this,"_scalar_const_changed",varray(p_id));
+ gn->add_child(sb);
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; //scalar constant
+ case ShaderGraph::NODE_VEC_CONST: {
+
+ gn->set_title("Vector");
+ Array v3p(true);
+ for(int i=0;i<3;i++) {
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ Label *l = memnew( Label );
+ l->set_text(String::chr('X'+i));
+ hbc->add_child(l);
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->vec_const_node_get_value(type,p_id)[i]);
+ sb->connect("value_changed",this,"_vec_const_changed",varray(p_id,v3p));
+ v3p.push_back(sb);
+ hbc->add_child(sb);
+ gn->add_child(hbc);
+ }
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; //vec3 constant
+ case ShaderGraph::NODE_RGB_CONST: {
+
+ gn->set_title("Color");
+ ColorPickerButton *cpb = memnew( ColorPickerButton );
+ cpb->set_color(graph->rgb_const_node_get_value(type,p_id));
+ cpb->connect("color_changed",this,"_rgb_const_changed",varray(p_id));
+ gn->add_child(cpb);
+ Label *l = memnew( Label );
+ l->set_text("RGB");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; //rgb constant (shows a color picker instead)
+ case ShaderGraph::NODE_XFORM_CONST: {
+ gn->set_title("XForm");
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_xform_const_changed",varray(p_id,edit));
+ gn->add_child(edit);
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+
+ } break; // 4x4 matrix constant
+ case ShaderGraph::NODE_TIME: {
+
+ gn->set_title("Time");
+ Label *l = memnew( Label );
+ l->set_text("(s)");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // time in seconds
+ case ShaderGraph::NODE_SCREEN_TEX: {
+
+ gn->set_title("ScreenTex");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (!graph->is_slot_connected(type,p_id,0)) {
+ Vector3 v = graph->default_get_value(type, p_id, 0);
+ hbc->add_child(make_editor("UV: " + v,gn,p_id,0,Variant::VECTOR3));
+ } else {
+ hbc->add_child(make_label("UV",Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("RGB")));
+ gn->add_child(hbc);
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // screen texture sampler (takes UV) (only usable in fragment case Shader)
+ case ShaderGraph::NODE_SCALAR_OP: {
+
+ gn->set_title("ScalarOp");
+ static const char* op_name[ShaderGraph::SCALAR_MAX_OP]={
+ ("Add"),
+ ("Sub"),
+ ("Mul"),
+ ("Div"),
+ ("Mod"),
+ ("Pow"),
+ ("Max"),
+ ("Min"),
+ ("Atan2")
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::SCALAR_MAX_OP;i++) {
+
+ ob->add_item(op_name[i],i);
+ }
+
+ ob->select(graph->scalar_op_node_get_op(type,p_id));
+ ob->connect("item_selected",this,"_scalar_op_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a",Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("a: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b",Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin));
+ }
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+
+ } break; // scalar vs scalar op (mul: { } break; add: { } break; div: { } break; etc)
+ case ShaderGraph::NODE_VEC_OP: {
+
+ gn->set_title("VecOp");
+ static const char* op_name[ShaderGraph::VEC_MAX_OP]={
+ ("Add"),
+ ("Sub"),
+ ("Mul"),
+ ("Div"),
+ ("Mod"),
+ ("Pow"),
+ ("Max"),
+ ("Min"),
+ ("Cross")
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::VEC_MAX_OP;i++) {
+
+ ob->add_item(op_name[i],i);
+ }
+
+ ob->select(graph->vec_op_node_get_op(type,p_id));
+ ob->connect("item_selected",this,"_vec_op_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a",Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b",Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3));
+ }
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+
+ } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc)
+ case ShaderGraph::NODE_VEC_SCALAR_OP: {
+
+ gn->set_title("VecScalarOp");
+ static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={
+ ("Mul"),
+ ("Div"),
+ ("Pow"),
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) {
+
+ ob->add_item(op_name[i],i);
+ }
+
+ ob->select(graph->vec_scalar_op_node_get_op(type,p_id));
+ ob->connect("item_selected",this,"_vec_scalar_op_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a",Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b",Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin));
+ }
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+
+ } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc)
+ case ShaderGraph::NODE_RGB_OP: {
+
+ gn->set_title("RGB Op");
+ static const char* op_name[ShaderGraph::RGB_MAX_OP]={
+ ("Screen"),
+ ("Difference"),
+ ("Darken"),
+ ("Lighten"),
+ ("Overlay"),
+ ("Dodge"),
+ ("Burn"),
+ ("SoftLight"),
+ ("HardLight")
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::RGB_MAX_OP;i++) {
+
+ ob->add_item(op_name[i],i);
+ }
+
+ ob->select(graph->rgb_op_node_get_op(type,p_id));
+ ob->connect("item_selected",this,"_rgb_op_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a",Variant::COLOR));
+ } else {
+ hbc->add_child(make_editor(String("a: "),gn,p_id,0,Variant::COLOR));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b",Variant::COLOR));
+ } else {
+ gn->add_child(make_editor(String("b: "),gn,p_id,1,Variant::COLOR));
+ }
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break; // vec3 vs vec3 rgb op (with scalar amount): { } break; like brighten: { } break; darken: { } break; burn: { } break; dodge: { } break; multiply: { } break; etc.
+ case ShaderGraph::NODE_XFORM_MULT: {
+
+ gn->set_title("XFMult");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a",Variant::TRANSFORM));
+ } else {
+ hbc->add_child(make_editor(String("a: edit..."),gn,p_id,0,Variant::TRANSFORM));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b",Variant::TRANSFORM));
+ } else {
+ gn->add_child(make_editor(String("b: edit..."),gn,p_id,1,Variant::TRANSFORM));
+ }
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],false,0,Color());
+
+
+ } break; // mat4 x mat4
+ case ShaderGraph::NODE_XFORM_VEC_MULT: {
+
+ gn->set_title("XFVecMult");
+
+ CheckBox *button = memnew (CheckBox("RotOnly"));
+ button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id));
+ button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id));
+
+ gn->add_child(button);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("xf",Variant::TRANSFORM));
+ } else {
+ hbc->add_child(make_editor(String("xf: edit..."),gn,p_id,0,Variant::TRANSFORM));
+ }
+ hbc->add_spacer();
+ Label *l = memnew(Label("out"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("a",Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("a: ")+v,gn,p_id,1,Variant::VECTOR3));
+ }
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break;
+ case ShaderGraph::NODE_XFORM_VEC_INV_MULT: {
+
+ gn->set_title("XFVecInvMult");
+
+
+ CheckBox *button = memnew( CheckBox("RotOnly"));
+ button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id));
+ button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id));
+
+ gn->add_child(button);
+
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ gn->add_child(make_label("a",Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ gn->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ hbc->add_child(make_label("xf", Variant::TRANSFORM));
+ } else {
+ hbc->add_child(make_editor(String("xf: edit..."),gn,p_id,1,Variant::TRANSFORM));
+ }
+ hbc->add_spacer();
+ Label *l = memnew(Label("out"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+
+ } break; // mat4 x vec3 inverse mult (with no-translation option)
+ case ShaderGraph::NODE_SCALAR_FUNC: {
+
+ gn->set_title("ScalarFunc");
+ static const char* func_name[ShaderGraph::SCALAR_MAX_FUNC]={
+ ("Sin"),
+ ("Cos"),
+ ("Tan"),
+ ("ASin"),
+ ("ACos"),
+ ("ATan"),
+ ("SinH"),
+ ("CosH"),
+ ("TanH"),
+ ("Log"),
+ ("Exp"),
+ ("Sqrt"),
+ ("Abs"),
+ ("Sign"),
+ ("Floor"),
+ ("Round"),
+ ("Ceil"),
+ ("Frac"),
+ ("Satr"),
+ ("Neg")
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::SCALAR_MAX_FUNC;i++) {
+
+ ob->add_item(func_name[i],i);
+ }
+
+ ob->select(graph->scalar_func_node_get_function(type,p_id));
+ ob->connect("item_selected",this,"_scalar_func_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("in", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("in: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+ } break; // scalar function (sin: { } break; cos: { } break; etc)
+ case ShaderGraph::NODE_VEC_FUNC: {
+
+
+
+ gn->set_title("VecFunc");
+ static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={
+ ("Normalize"),
+ ("Saturate"),
+ ("Negate"),
+ ("Reciprocal"),
+ ("RGB to HSV"),
+ ("HSV to RGB"),
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) {
+
+ ob->add_item(func_name[i],i);
+ }
+
+ ob->select(graph->vec_func_node_get_function(type,p_id));
+ ob->connect("item_selected",this,"_vec_func_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("in", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("in: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // vector function (normalize: { } break; negate: { } break; reciprocal: { } break; rgb2hsv: { } break; hsv2rgb: { } break; etc: { } break; etc)
+ case ShaderGraph::NODE_VEC_LEN: {
+ gn->set_title("VecLength");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("in", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("in: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("len")));
+ gn->add_child(hbc);
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // vec3 length
+ case ShaderGraph::NODE_DOT_PROD: {
+
+ gn->set_title("DotProduct");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("dp")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3));
+ }
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break; // vec3 . vec3 (dot product -> scalar output)
+ case ShaderGraph::NODE_VEC_TO_SCALAR: {
+
+ gn->set_title("Vec2Scalar");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("vec", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("vec: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ Label *l=memnew(Label("x"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+ l=memnew(Label("y"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l );
+ l=memnew(Label("z"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l);
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+
+
+ } break; // 1 vec3 input: { } break; 3 scalar outputs
+ case ShaderGraph::NODE_SCALAR_TO_VEC: {
+
+ gn->set_title("Scalar2Vec");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("x", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("x: ")+Variant(v),gn,p_id,0,Variant::REAL));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("vec")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("y", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("y: ")+Variant(v),gn,p_id,1,Variant::REAL));
+ }
+ if (graph->is_slot_connected(type, p_id, 2)) {
+ gn->add_child(make_label("in", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,2);
+ gn->add_child(make_editor(String("in: ")+Variant(v),gn,p_id,2,Variant::REAL));
+ }
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+ } break; // 3 scalar input: { } break; 1 vec3 output
+ case ShaderGraph::NODE_VEC_TO_XFORM: {
+
+ gn->set_title("Vec2XForm");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("x", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("x: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("xf")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("y", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("y: ")+v,gn,p_id,1,Variant::VECTOR3));
+ }
+ if (graph->is_slot_connected(type, p_id, 2)) {
+ gn->add_child(make_label("z", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,2);
+ gn->add_child(make_editor(String("z: ")+v,gn,p_id,2,Variant::VECTOR3));
+ }
+ if (graph->is_slot_connected(type, p_id, 3)) {
+ gn->add_child(make_label("ofs", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,3);
+ gn->add_child(make_editor(String("ofs: ")+v,gn,p_id,3,Variant::VECTOR3));
+ }
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+ gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break; // 3 vec input: { } break; 1 xform output
+ case ShaderGraph::NODE_XFORM_TO_VEC: {
+
+ gn->set_title("XForm2Vec");
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("fx", Variant::TRANSFORM));
+ } else {
+ hbc->add_child(make_editor(String("fx: edit..."),gn,p_id,0,Variant::TRANSFORM));
+ }
+ hbc->add_spacer();
+ Label *l=memnew(Label("x"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+ l=memnew(Label("y"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l );
+ l=memnew(Label("z"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l);
+ l=memnew(Label("ofs"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l);
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // 3 vec input: { } break; 1 xform output
+ case ShaderGraph::NODE_SCALAR_INTERP: {
+
+ gn->set_title("ScalarInterp");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("a: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("interp")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin));
+ }
+ if (graph->is_slot_connected(type, p_id, 2)) {
+ gn->add_child(make_label("c", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,2);
+ gn->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,2,Variant::REAL,hint_slider));
+ }
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+
+ } break; // scalar interpolation (with optional curve)
+ case ShaderGraph::NODE_VEC_INTERP: {
+
+ gn->set_title("VecInterp");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("a", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("interp")));
+ gn->add_child(hbc);
+ if (graph->is_slot_connected(type, p_id, 1)) {
+ gn->add_child(make_label("b", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,1);
+ gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3));
+ }
+ if (graph->is_slot_connected(type, p_id, 2)) {
+ gn->add_child(make_label("c", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,2);
+ gn->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,2,Variant::REAL,hint_slider));
+ }
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+ } break; // vec3 interpolation (with optional curve)
+ case ShaderGraph::NODE_COLOR_RAMP: {
+
+ gn->set_title("ColorRamp");
+ GraphColorRampEdit * ramp = memnew( GraphColorRampEdit );
+
+ PoolVector<real_t> offsets = graph->color_ramp_node_get_offsets(type,p_id);
+ PoolVector<Color> colors = graph->color_ramp_node_get_colors(type,p_id);
+
+ int oc = offsets.size();
+
+ if (oc) {
+ PoolVector<real_t>::Read rofs = offsets.read();
+ PoolVector<Color>::Read rcol = colors.read();
+
+ Vector<float> ofsv;
+ Vector<Color> colorv;
+ for(int i=0;i<oc;i++) {
+ ofsv.push_back(rofs[i]);
+ colorv.push_back(rcol[i]);
+ }
+
+ ramp->set_ramp(ofsv,colorv);
+
+ }
+
+ ramp->connect("ramp_changed",this,"_color_ramp_changed",varray(p_id,ramp));
+ ramp->set_custom_minimum_size(Size2(128,1));
+ gn->add_child(ramp);
+
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("c", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_slider));
+ }
+ hbc->add_spacer();
+ Label *l=memnew(Label("rgb"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+ l=memnew(Label("alpha"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l);
+
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,false,ShaderGraph::SLOT_MAX,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+ } break; // scalar interpolation (with optional curve)
+ case ShaderGraph::NODE_CURVE_MAP: {
+
+ gn->set_title("CurveMap");
+ GraphCurveMapEdit * map = memnew( GraphCurveMapEdit );
+
+ PoolVector<Vector2> points = graph->curve_map_node_get_points(type,p_id);
+
+ int oc = points.size();
+
+ if (oc) {
+ PoolVector<Vector2>::Read rofs = points.read();
+
+
+ Vector<Vector2> ofsv;
+ for(int i=0;i<oc;i++) {
+ ofsv.push_back(rofs[i]);
+ }
+
+ map->set_points(ofsv);
+
+ }
+ map->connect("curve_changed",this,"_curve_changed",varray(p_id,map));
+
+ //map->connect("map_changed",this,"_curve_map_changed",varray(p_id,map));
+ map->set_custom_minimum_size(Size2(128,64));
+ gn->add_child(map);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("c", Variant::REAL));
+ } else {
+ float v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_slider));
+ }
+ hbc->add_spacer();
+ Label *l=memnew(Label("cmap"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+ } break; // scalar interpolation (with optional curve)
+
+ case ShaderGraph::NODE_SCALAR_INPUT: {
+
+ gn->set_title("ScalarUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->scalar_input_node_get_value(type,p_id));
+ sb->connect("value_changed",this,"_scalar_input_changed",varray(p_id));
+ gn->add_child(sb);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // scalar uniform (assignable in material)
+ case ShaderGraph::NODE_VEC_INPUT: {
+
+ gn->set_title("VectorUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ Array v3p(true);
+ for(int i=0;i<3;i++) {
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ Label *l = memnew( Label );
+ l->set_text(String::chr('X'+i));
+ hbc->add_child(l);
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->vec_input_node_get_value(type,p_id)[i]);
+ sb->connect("value_changed",this,"_vec_input_changed",varray(p_id,v3p));
+ v3p.push_back(sb);
+ hbc->add_child(sb);
+ gn->add_child(hbc);
+ }
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // vec3 uniform (assignable in material)
+ case ShaderGraph::NODE_RGB_INPUT: {
+
+ gn->set_title("ColorUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ ColorPickerButton *cpb = memnew( ColorPickerButton );
+ cpb->set_color(graph->rgb_input_node_get_value(type,p_id));
+ cpb->connect("color_changed",this,"_rgb_input_changed",varray(p_id));
+ gn->add_child(cpb);
+ Label *l = memnew( Label );
+ l->set_text("RGB");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+ } break; // color uniform (assignable in material)
+ case ShaderGraph::NODE_XFORM_INPUT: {
+ gn->set_title("XFUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_xform_input_changed",varray(p_id,edit));
+ gn->add_child(edit);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+
+ } break; // mat4 uniform (assignable in material)
+ case ShaderGraph::NODE_TEXTURE_INPUT: {
+
+ gn->set_title("TexUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ TextureRect *tex = memnew( TextureRect );
+ tex->set_expand(true);
+ tex->set_custom_minimum_size(Size2(80,80));
+ tex->set_drag_forwarding(this);
+ gn->add_child(tex);
+ tex->set_mouse_filter(MOUSE_FILTER_PASS);
+ tex->set_texture(graph->texture_input_node_get_value(type,p_id));
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_tex_edited",varray(p_id,edit));
+ gn->add_child(edit);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("UV", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ Label *l=memnew(Label("RGB"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child(l);
+ gn->add_child(hbc);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(4,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // texture input (assignable in material)
+ case ShaderGraph::NODE_CUBEMAP_INPUT: {
+
+ gn->set_title("TexUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_cube_edited",varray(p_id,edit));
+ gn->add_child(edit);
+
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("UV", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ Label *l=memnew(Label("RGB"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child(l);
+ gn->add_child(hbc);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // cubemap input (assignable in material)
+ case ShaderGraph::NODE_DEFAULT_TEXTURE: {
+
+ gn->set_title("CanvasItemTex");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ if (graph->is_slot_connected(type, p_id, 0)) {
+ hbc->add_child(make_label("UV", Variant::VECTOR3));
+ } else {
+ Vector3 v = graph->default_get_value(type,p_id,0);
+ hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3));
+ }
+ hbc->add_spacer();
+ Label *l=memnew(Label("RGB"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child(l);
+ gn->add_child(hbc);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+ } break; // screen texture sampler (takes UV) (only usable in fragment case Shader)
+
+ case ShaderGraph::NODE_OUTPUT: {
+ gn->set_title("Output");
+ gn->set_show_close_button(false);
+
+ List<ShaderGraph::SlotInfo> si;
+ ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si);
+
+ Array colors;
+ colors.push_back("Color");
+ colors.push_back("LightColor");
+ colors.push_back("Light");
+ colors.push_back("ShadowColor");
+ colors.push_back("Diffuse");
+ colors.push_back("Specular");
+ colors.push_back("Emmision");
+ Array reals;
+ reals.push_back("Alpha");
+ reals.push_back("DiffuseAlpha");
+ reals.push_back("NormalMapDepth");
+ reals.push_back("SpecExp");
+ reals.push_back("Glow");
+ reals.push_back("ShadeParam");
+ reals.push_back("SpecularExp");
+ reals.push_back("LightAlpha");
+ reals.push_back("ShadowAlpha");
+ reals.push_back("PointSize");
+ reals.push_back("Discard");
+
+ int idx=0;
+ for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) {
+ ShaderGraph::SlotInfo& s=E->get();
+ if (s.dir==ShaderGraph::SLOT_OUT) {
+ Variant::Type v;
+ if (colors.find(s.name)>=0)
+ v=Variant::COLOR;
+ else if (reals.find(s.name)>=0)
+ v=Variant::REAL;
+ else
+ v=Variant::VECTOR3;
+ gn->add_child(make_label(s.name, v));
+ gn->set_slot(idx,true,s.type,typecol[s.type],false,0,Color());
+ idx++;
+ }
+ }
+
+ } break; // output (case Shader type dependent)
+ case ShaderGraph::NODE_COMMENT: {
+ gn->set_title("Comment");
+ TextEdit *te = memnew(TextEdit);
+ te->set_custom_minimum_size(Size2(100,100));
+ gn->add_child(te);
+ te->set_text(graph->comment_node_get_text(type,p_id));
+ te->connect("text_changed",this,"_comment_edited",varray(p_id,te));
+
+ } break; // comment
+
+
+
+ }
+
+ gn->connect("dragged",this,"_node_moved",varray(p_id));
+ gn->connect("close_request",this,"_node_removed",varray(p_id),CONNECT_DEFERRED);
+ graph_edit->add_child(gn);
+ node_map[p_id]=gn;
+ gn->set_offset(graph->node_get_pos(type,p_id));
+
+
+}
+
+void ShaderGraphView::_update_graph() {
+
+
+ if (block_update)
+ return;
+
+ for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
+
+ memdelete(E->get());
+ }
+
+ node_map.clear();
+
+ if (!graph.is_valid())
+ return;
+
+
+ List<int> nl;
+ graph->get_node_list(type,&nl);
+
+ for(List<int>::Element *E=nl.front();E;E=E->next()) {
+
+ _create_node(E->get());
+ }
+ graph_edit->clear_connections();
+
+ List<ShaderGraph::Connection> connections;
+ graph->get_node_connections(type,&connections);
+ for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
+
+ ERR_CONTINUE(!node_map.has(E->get().src_id) || !node_map.has(E->get().dst_id));
+ graph_edit->connect_node(node_map[E->get().src_id]->get_name(),E->get().src_slot,node_map[E->get().dst_id]->get_name(),E->get().dst_slot);
+ }
+
+}
+
+void ShaderGraphView::_sg_updated() {
+
+ if (!graph.is_valid())
+ return;
+ switch(graph->get_graph_error(type)) {
+ case ShaderGraph::GRAPH_OK: status->set_text(""); break;
+ case ShaderGraph::GRAPH_ERROR_CYCLIC: status->set_text(TTR("Error: Cyclic Connection Link")); break;
+ case ShaderGraph::GRAPH_ERROR_MISSING_CONNECTIONS: status->set_text(TTR("Error: Missing Input Connections")); break;
+ }
+}
+
+Variant ShaderGraphView::get_drag_data_fw(const Point2 &p_point, Control *p_from)
+{
+ TextureRect* frame = p_from->cast_to<TextureRect>();
+ if (!frame)
+ return Variant();
+
+ if (!frame->get_texture().is_valid())
+ return Variant();
+
+ RES res = frame->get_texture();
+ return EditorNode::get_singleton()->drag_resource(res,p_from);
+
+ return Variant();
+}
+
+bool ShaderGraphView::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const
+{
+ if (p_data.get_type() != Variant::DICTIONARY)
+ return false;
+
+ Dictionary d = p_data;
+
+ if (d.has("type")){
+ if (d["type"] == "resource" && d.has("resource")) {
+ Variant val = d["resource"];
+
+ if (val.get_type()==Variant::OBJECT) {
+ RES res = val;
+ if (res.is_valid() && res->cast_to<Texture>())
+ return true;
+ }
+ }
+ else if (d["type"] == "files" && d.has("files")) {
+ Vector<String> files = d["files"];
+ if (files.size() != 1)
+ return false;
+ return (ResourceLoader::get_resource_type(files[0]) == "ImageTexture");
+ }
+ }
+
+ return false;
+}
+
+void ShaderGraphView::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from)
+{
+ if (!can_drop_data_fw(p_point, p_data, p_from))
+ return;
+
+ TextureRect *frame = p_from->cast_to<TextureRect>();
+ if (!frame)
+ return;
+
+ Dictionary d = p_data;
+ Ref<Texture> tex;
+
+ if (d.has("type")) {
+ if (d["type"] == "resource" && d.has("resource")){
+ Variant val = d["resource"];
+
+ if (val.get_type()==Variant::OBJECT) {
+ RES res = val;
+ if (res.is_valid())
+ tex = Ref<Texture>(res->cast_to<Texture>());
+ }
+ }
+ else if (d["type"] == "files" && d.has("files")) {
+ Vector<String> files = d["files"];
+ RES res = ResourceLoader::load(files[0]);
+ if (res.is_valid())
+ tex = Ref<Texture>(res->cast_to<Texture>());
+ }
+ }
+
+ if (!tex.is_valid()) return;
+
+ GraphNode *gn = frame->get_parent()->cast_to<GraphNode>();
+ if (!gn) return;
+
+ int id = -1;
+ for(Map<int,GraphNode*>::Element *E = node_map.front();E;E=E->next())
+ if (E->get() == gn) {
+ id = E->key();
+ break;
+ }
+ print_line(String::num(double(id)));
+ if (id < 0) return;
+
+ if (graph->node_get_type(type,id)==ShaderGraph::NODE_TEXTURE_INPUT) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Texture Uniform"));
+ ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,id,tex);
+ ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,id,graph->texture_input_node_get_value(type,id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
+}
+
+void ShaderGraphView::set_graph(Ref<ShaderGraph> p_graph){
+
+
+ if (graph.is_valid()) {
+ graph->disconnect("updated",this,"_sg_updated");
+ }
+ graph=p_graph;
+ if (graph.is_valid()) {
+ graph->connect("updated",this,"_sg_updated");
+ }
+ _update_graph();
+ _sg_updated();
+
+}
+
+void ShaderGraphView::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ ped_popup->connect("variant_changed",this,"_variant_edited");
+ }
+}
+
+void ShaderGraphView::add_node(int p_type, const Vector2 &location) {
+
+ if (p_type==ShaderGraph::NODE_INPUT && graph->node_count(type, p_type)>0)
+ return;
+
+ List<int> existing;
+ graph->get_node_list(type,&existing);
+ existing.sort();
+ int newid=1;
+ for(List<int>::Element *E=existing.front();E;E=E->next()) {
+ if (!E->next() || (E->get()+1!=E->next()->get())){
+ newid=E->get()+1;
+ break;
+ }
+ }
+
+ Vector2 init_ofs = location;
+ while(true) {
+ bool valid=true;
+ for(List<int>::Element *E=existing.front();E;E=E->next()) {
+ Vector2 pos = graph->node_get_pos(type,E->get());
+ if (init_ofs==pos) {
+ init_ofs+=Vector2(20,20);
+ valid=false;
+ break;
+
+ }
+ }
+
+ if (valid)
+ break;
+ }
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Add Shader Graph Node"));
+ ur->add_do_method(graph.ptr(),"node_add",type,p_type,newid);
+ ur->add_do_method(graph.ptr(),"node_set_pos",type,newid,init_ofs);
+ ur->add_undo_method(graph.ptr(),"node_remove",type,newid);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+
+}
+
+void ShaderGraphView::_bind_methods() {
+
+ ClassDB::bind_method("_update_graph",&ShaderGraphView::_update_graph);
+ ClassDB::bind_method("_begin_node_move", &ShaderGraphView::_begin_node_move);
+ ClassDB::bind_method("_node_moved",&ShaderGraphView::_node_moved);
+ ClassDB::bind_method("_end_node_move", &ShaderGraphView::_end_node_move);
+ ClassDB::bind_method("_move_node",&ShaderGraphView::_move_node);
+ ClassDB::bind_method("_node_removed",&ShaderGraphView::_node_removed);
+ ClassDB::bind_method("_connection_request",&ShaderGraphView::_connection_request);
+ ClassDB::bind_method("_disconnection_request",&ShaderGraphView::_disconnection_request);
+ ClassDB::bind_method("_duplicate_nodes_request", &ShaderGraphView::_duplicate_nodes_request);
+ ClassDB::bind_method("_duplicate_nodes", &ShaderGraphView::_duplicate_nodes);
+ ClassDB::bind_method("_delete_nodes_request", &ShaderGraphView::_delete_nodes_request);
+
+ ClassDB::bind_method("_default_changed",&ShaderGraphView::_default_changed);
+ ClassDB::bind_method("_scalar_const_changed",&ShaderGraphView::_scalar_const_changed);
+ ClassDB::bind_method("_vec_const_changed",&ShaderGraphView::_vec_const_changed);
+ ClassDB::bind_method("_rgb_const_changed",&ShaderGraphView::_rgb_const_changed);
+ ClassDB::bind_method("_xform_const_changed",&ShaderGraphView::_xform_const_changed);
+ ClassDB::bind_method("_scalar_op_changed",&ShaderGraphView::_scalar_op_changed);
+ ClassDB::bind_method("_vec_op_changed",&ShaderGraphView::_vec_op_changed);
+ ClassDB::bind_method("_vec_scalar_op_changed",&ShaderGraphView::_vec_scalar_op_changed);
+ ClassDB::bind_method("_rgb_op_changed",&ShaderGraphView::_rgb_op_changed);
+ ClassDB::bind_method("_xform_inv_rev_changed",&ShaderGraphView::_xform_inv_rev_changed);
+ ClassDB::bind_method("_scalar_func_changed",&ShaderGraphView::_scalar_func_changed);
+ ClassDB::bind_method("_vec_func_changed",&ShaderGraphView::_vec_func_changed);
+ ClassDB::bind_method("_scalar_input_changed",&ShaderGraphView::_scalar_input_changed);
+ ClassDB::bind_method("_vec_input_changed",&ShaderGraphView::_vec_input_changed);
+ ClassDB::bind_method("_xform_input_changed",&ShaderGraphView::_xform_input_changed);
+ ClassDB::bind_method("_rgb_input_changed",&ShaderGraphView::_rgb_input_changed);
+ ClassDB::bind_method("_tex_input_change",&ShaderGraphView::_tex_input_change);
+ ClassDB::bind_method("_cube_input_change",&ShaderGraphView::_cube_input_change);
+ ClassDB::bind_method("_input_name_changed",&ShaderGraphView::_input_name_changed);
+ ClassDB::bind_method("_tex_edited",&ShaderGraphView::_tex_edited);
+ ClassDB::bind_method("_variant_edited",&ShaderGraphView::_variant_edited);
+ ClassDB::bind_method("_cube_edited",&ShaderGraphView::_cube_edited);
+ ClassDB::bind_method("_comment_edited",&ShaderGraphView::_comment_edited);
+ ClassDB::bind_method("_color_ramp_changed",&ShaderGraphView::_color_ramp_changed);
+ ClassDB::bind_method("_curve_changed",&ShaderGraphView::_curve_changed);
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ShaderGraphView::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ShaderGraphView::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &ShaderGraphView::drop_data_fw);
+
+ ClassDB::bind_method("_sg_updated",&ShaderGraphView::_sg_updated);
+}
+
+ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) {
+
+ type=p_type;
+ graph_edit = memnew( GraphEdit );
+ block_update=false;
+ ped_popup = memnew( CustomPropertyEditor );
+ graph_edit->add_child(ped_popup);
+ status = memnew( Label );
+ graph_edit->get_top_layer()->add_child(status);
+ graph_edit->connect("_begin_node_move", this, "_begin_node_move");
+ graph_edit->connect("_end_node_move", this, "_end_node_move");
+ status->set_pos(Vector2(5,5));
+ status->add_color_override("font_color_shadow",Color(0,0,0));
+ status->add_color_override("font_color",Color(1,0.4,0.3));
+ status->add_constant_override("shadow_as_outline",1);
+ status->add_constant_override("shadow_offset_x",2);
+ status->add_constant_override("shadow_offset_y",2);
+ status->set_text("");
+}
+
+
+//////////////edit//////////////
+void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) {
+
+ for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) {
+ graph_edits[i]->set_graph(p_shader);
+ }
+}
+
+void ShaderGraphEditor::_add_node(int p_type) {
+
+ ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab());
+ graph_edits[shader_type]->add_node(p_type, next_location);
+}
+
+void ShaderGraphEditor::_popup_requested(const Vector2 &p_position)
+{
+ 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();
+ popup->call_deferred("grab_click_focus");
+ popup->set_invalidate_click_until_motion();
+}
+
+void ShaderGraphEditor::_notification(int p_what) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ for(int i=0;i<ShaderGraph::NODE_TYPE_MAX;i++) {
+
+ if (i==ShaderGraph::NODE_OUTPUT)
+ continue;
+ if (!_2d && i==ShaderGraph::NODE_DEFAULT_TEXTURE)
+ continue;
+
+ String nn = node_names[i];
+ String ic = nn.get_slice(":",0);
+ String v = nn.get_slice(":",1);
+ bool addsep=false;
+ if (nn.ends_with(":")) {
+ addsep=true;
+ }
+ popup->add_icon_item(get_icon(ic,"EditorIcons"),v,i);
+ if (addsep)
+ popup->add_separator();
+ }
+ popup->connect("id_pressed",this,"_add_node");
+
+
+ }
+}
+
+void ShaderGraphEditor::_bind_methods() {
+
+ ClassDB::bind_method("_add_node",&ShaderGraphEditor::_add_node);
+ ClassDB::bind_method("_popup_requested",&ShaderGraphEditor::_popup_requested);
+}
+
+
+const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={
+ ("GraphInput:Input"), // all inputs (shader type dependent)
+ ("GraphScalar:Scalar Constant"), //scalar constant
+ ("GraphVector:Vector Constant"), //vec3 constant
+ ("GraphRgb:RGB Constant"), //rgb constant (shows a color picker instead)
+ ("GraphXform:XForm Constant"), // 4x4 matrix constant
+ ("GraphTime:Time:"), // time in seconds
+ ("GraphTexscreen:Screen Sample"), // screen texture sampler (takes uv) (only usable in fragment shader)
+ ("GraphScalarOp:Scalar Operator"), // scalar vs scalar op (mul", add", div", etc)
+ ("GraphVecOp:Vector Operator"), // vec3 vs vec3 op (mul",ad",div",crossprod",etc)
+ ("GraphVecScalarOp:Scalar+Vector Operator"), // vec3 vs scalar op (mul", add", div", etc)
+ ("GraphRgbOp:RGB Operator:"), // vec3 vs vec3 rgb op (with scalar amount)", like brighten", darken", burn", dodge", multiply", etc.
+ ("GraphXformMult:XForm Multiply"), // mat4 x mat4
+ ("GraphXformVecMult:XForm+Vector Multiply"), // mat4 x vec3 mult (with no-translation option)
+ ("GraphXformVecImult:Form+Vector InvMultiply:"), // mat4 x vec3 inverse mult (with no-translation option)
+ ("GraphXformScalarFunc:Scalar Function"), // scalar function (sin", cos", etc)
+ ("GraphXformVecFunc:Vector Function"), // vector function (normalize", negate", reciprocal", rgb2hsv", hsv2rgb", etc", etc)
+ ("GraphVecLength:Vector Length"), // vec3 length
+ ("GraphVecDp:Dot Product:"), // vec3 . vec3 (dot product -> scalar output)
+ ("GraphVecToScalars:Vector -> Scalars"), // 1 vec3 input", 3 scalar outputs
+ ("GraphScalarsToVec:Scalars -> Vector"), // 3 scalar input", 1 vec3 output
+ ("GraphXformToVecs:XForm -> Vectors"), // 3 vec input", 1 xform output
+ ("GraphVecsToXform:Vectors -> XForm:"), // 3 vec input", 1 xform output
+ ("GraphScalarInterp:Scalar Interpolate"), // scalar interpolation (with optional curve)
+ ("GraphVecInterp:Vector Interpolate:"), // vec3 interpolation (with optional curve)
+ ("GraphColorRamp:Color Ramp"), // vec3 interpolation (with optional curve)
+ ("GraphCurveMap:Curve Remap:"), // vec3 interpolation (with optional curve)
+ ("GraphScalarUniform:Scalar Uniform"), // scalar uniform (assignable in material)
+ ("GraphVectorUniform:Vector Uniform"), // vec3 uniform (assignable in material)
+ ("GraphRgbUniform:RGB Uniform"), // color uniform (assignable in material)
+ ("GraphXformUniform:XForm Uniform"), // mat4 uniform (assignable in material)
+ ("GraphTextureUniform:Texture Uniform"), // texture input (assignable in material)
+ ("GraphCubeUniform:CubeMap Uniform:"), // cubemap input (assignable in material)
+ ("GraphDefaultTexture:CanvasItem Texture:"), // cubemap input (assignable in material)
+ ("Output"), // output (shader type dependent)
+ ("GraphComment:Comment"), // comment
+
+
+};
+ShaderGraphEditor::ShaderGraphEditor(bool p_2d) {
+ _2d=p_2d;
+
+ popup = memnew( PopupMenu );
+ add_child(popup);
+
+
+ tabs = memnew(TabContainer);
+ tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(tabs);
+ const char* sname[ShaderGraph::SHADER_TYPE_MAX]={
+ "Vertex",
+ "Fragment",
+ "Light"
+ };
+ for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) {
+
+ graph_edits[i]= memnew( ShaderGraphView(ShaderGraph::ShaderType(i)) );
+ add_child(graph_edits[i]);
+ graph_edits[i]->get_graph_edit()->set_name(sname[i]);
+ tabs->add_child(graph_edits[i]->get_graph_edit());
+ graph_edits[i]->get_graph_edit()->connect("connection_request",graph_edits[i],"_connection_request");
+ graph_edits[i]->get_graph_edit()->connect("disconnection_request",graph_edits[i],"_disconnection_request");
+ graph_edits[i]->get_graph_edit()->connect("duplicate_nodes_request", graph_edits[i], "_duplicate_nodes_request");
+ graph_edits[i]->get_graph_edit()->connect("popup_request",this,"_popup_requested");
+ graph_edits[i]->get_graph_edit()->connect("delete_nodes_request",graph_edits[i],"_delete_nodes_request");
+ graph_edits[i]->get_graph_edit()->set_right_disconnects(true);
+ }
+
+ tabs->set_current_tab(1);
+
+ set_custom_minimum_size(Size2(100,300));
+}
+
+
+void ShaderGraphEditorPlugin::edit(Object *p_object) {
+
+ shader_editor->edit(p_object->cast_to<ShaderGraph>());
+}
+
+bool ShaderGraphEditorPlugin::handles(Object *p_object) const {
+
+ ShaderGraph *shader=p_object->cast_to<ShaderGraph>();
+ if (!shader)
+ return false;
+ if (_2d)
+ return shader->get_mode()==Shader::MODE_CANVAS_ITEM;
+ else
+ return shader->get_mode()==Shader::MODE_MATERIAL;
+}
+
+void ShaderGraphEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ shader_editor->show();
+ } else {
+
+ shader_editor->hide();
+ }
+
+}
+
+ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node, bool p_2d) {
+
+ _2d=p_2d;
+ editor=p_node;
+ shader_editor = memnew( ShaderGraphEditor(p_2d) );
+ shader_editor->hide();
+ if (p_2d)
+ CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(shader_editor);
+ else
+ SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor);
+
+
+ //editor->get_viewport()->add_child(shader_editor);
+ //shader_editor->set_area_as_parent_rect();
+ //shader_editor->hide();
+
+}
+
+
+ShaderGraphEditorPlugin::~ShaderGraphEditorPlugin()
+{
+}
+
+
+
+#endif
diff --git a/editor/plugins/shader_graph_editor_plugin.h b/editor/plugins/shader_graph_editor_plugin.h
new file mode 100644
index 0000000000..5143722242
--- /dev/null
+++ b/editor/plugins/shader_graph_editor_plugin.h
@@ -0,0 +1,242 @@
+/*************************************************************************/
+/* shader_graph_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SHADER_GRAPH_EDITOR_PLUGIN_H
+#define SHADER_GRAPH_EDITOR_PLUGIN_H
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/resources/shader.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/button.h"
+#include "scene/gui/graph_edit.h"
+#include "scene/gui/popup.h"
+#include "editor/property_editor.h"
+#include "scene/resources/shader_graph.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+#if 0
+class GraphColorRampEdit : public Control {
+
+ GDCLASS(GraphColorRampEdit,Control);
+
+
+ struct Point {
+
+ float offset;
+ Color color;
+ bool operator<(const Point& p_ponit) const {
+ return offset<p_ponit.offset;
+ }
+ };
+
+ PopupPanel *popup;
+ ColorPicker *picker;
+
+
+ bool grabbing;
+ int grabbed;
+ float grabbed_at;
+ Vector<Point> points;
+
+ void _color_changed(const Color& p_color);
+
+protected:
+ void _gui_input(const InputEvent& p_event);
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors);
+ Vector<float> get_offsets() const;
+ Vector<Color> get_colors() const;
+ virtual Size2 get_minimum_size() const;
+ GraphColorRampEdit();
+};
+
+
+class GraphCurveMapEdit : public Control {
+
+ GDCLASS(GraphCurveMapEdit,Control);
+
+
+ struct Point {
+
+ float offset;
+ float height;
+ bool operator<(const Point& p_ponit) const {
+ return offset<p_ponit.offset;
+ }
+ };
+
+
+ bool grabbing;
+ int grabbed;
+ Vector<Point> points;
+
+ void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d);
+protected:
+ void _gui_input(const InputEvent& p_event);
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_points(const Vector<Vector2>& p_points);
+ Vector<Vector2> get_points() const;
+ virtual Size2 get_minimum_size() const;
+ GraphCurveMapEdit();
+};
+
+class ShaderGraphView : public Control {
+
+ GDCLASS(ShaderGraphView,Control);
+
+
+
+ CustomPropertyEditor *ped_popup;
+ bool block_update;
+
+ Label *status;
+ GraphEdit *graph_edit;
+ Ref<ShaderGraph> graph;
+ int edited_id;
+ int edited_def;
+
+ ShaderGraph::ShaderType type;
+
+ void _update_graph();
+ void _create_node(int p_id);
+
+
+ ToolButton *make_label(String text, Variant::Type v_type = Variant::NIL);
+ ToolButton *make_editor(String text, GraphNode* gn, int p_id, int param, Variant::Type type, String p_hint="");
+
+ void _connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot);
+ void _disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot);
+
+ void _node_removed(int p_id);
+ void _begin_node_move();
+ void _node_moved(const Vector2& p_from, const Vector2& p_to,int p_id);
+ 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 _delete_nodes_request();
+
+
+ void _default_changed(int p_id, Node* p_button, int p_param, int v_type, String p_hint);
+
+ void _scalar_const_changed(double p_value,int p_id);
+ void _vec_const_changed(double p_value, int p_id, Array p_arr);
+ void _rgb_const_changed(const Color& p_color, int p_id);
+ void _xform_const_changed(int p_id,Node* p_button);
+ void _scalar_op_changed(int p_op, int p_id);
+ void _vec_op_changed(int p_op, int p_id);
+ void _vec_scalar_op_changed(int p_op, int p_id);
+ void _rgb_op_changed(int p_op, int p_id);
+ void _xform_inv_rev_changed(bool p_enabled, int p_id);
+ void _scalar_func_changed(int p_func, int p_id);
+ void _vec_func_changed(int p_func, int p_id);
+ void _scalar_input_changed(double p_value,int p_id);
+ void _vec_input_changed(double p_value, int p_id, Array p_arr);
+ void _xform_input_changed(int p_id,Node* p_button);
+ void _rgb_input_changed(const Color& p_color, int p_id);
+ void _tex_input_change(int p_id,Node* p_button);
+ void _cube_input_change(int p_id);
+ void _input_name_changed(const String& p_name,int p_id,Node* p_line_edit);
+ void _tex_edited(int p_id,Node* p_button);
+ void _cube_edited(int p_id,Node* p_button);
+ void _variant_edited();
+ void _comment_edited(int p_id,Node* p_button);
+ void _color_ramp_changed(int p_id,Node* p_ramp);
+ void _curve_changed(int p_id,Node* p_curve);
+ void _sg_updated();
+ Map<int,GraphNode*> node_map;
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void add_node(int p_type, const Vector2 &location);
+ GraphEdit *get_graph_edit() { return graph_edit; }
+ void set_graph(Ref<ShaderGraph> p_graph);
+
+ ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT);
+};
+
+class ShaderGraphEditor : public VBoxContainer {
+
+ GDCLASS(ShaderGraphEditor,VBoxContainer);
+
+ PopupMenu *popup;
+ TabContainer *tabs;
+ ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX];
+ static const char* node_names[ShaderGraph::NODE_TYPE_MAX];
+ Vector2 next_location;
+
+ bool _2d;
+ void _add_node(int p_type);
+ void _popup_requested(const Vector2 &p_position);
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void edit(Ref<ShaderGraph> p_shader);
+ ShaderGraphEditor(bool p_2d);
+};
+
+class ShaderGraphEditorPlugin : public EditorPlugin {
+
+ GDCLASS( ShaderGraphEditorPlugin, EditorPlugin );
+
+ bool _2d;
+ ShaderGraphEditor *shader_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "ShaderGraph"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_node);
+ virtual bool handles(Object *p_node) const;
+ virtual void make_visible(bool p_visible);
+
+ ShaderGraphEditorPlugin(EditorNode *p_node,bool p_2d);
+ ~ShaderGraphEditorPlugin();
+
+};
+#endif
+#endif
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
new file mode 100644
index 0000000000..8a7969c71b
--- /dev/null
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -0,0 +1,4131 @@
+/*************************************************************************/
+/* spatial_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "spatial_editor_plugin.h"
+
+#include "print_string.h"
+#include "os/keyboard.h"
+#include "scene/3d/visual_instance.h"
+#include "scene/3d/camera.h"
+#include "camera_matrix.h"
+#include "sort.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "scene/resources/surface_tool.h"
+#include "editor/spatial_editor_gizmos.h"
+#include "global_config.h"
+#include "editor/plugins/animation_player_editor_plugin.h"
+#include "editor/animation_editor.h"
+
+#define DISTANCE_DEFAULT 4
+
+
+#define GIZMO_ARROW_SIZE 0.3
+#define GIZMO_RING_HALF_WIDTH 0.1
+//#define GIZMO_SCALE_DEFAULT 0.28
+#define GIZMO_SCALE_DEFAULT 0.15
+
+
+void SpatialEditorViewport::_update_camera() {
+ if (orthogonal) {
+ //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar());
+ camera->set_orthogonal(2 * cursor.distance, 0.1, 8192);
+ }
+ else
+ camera->set_perspective(get_fov(), get_znear(), get_zfar());
+
+ Transform camera_transform;
+ camera_transform.translate(cursor.pos);
+ camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
+ camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
+
+ if (orthogonal)
+ camera_transform.translate(0, 0, 4096);
+ else
+ camera_transform.translate(0, 0, cursor.distance);
+
+ if (camera->get_global_transform() != camera_transform) {
+ camera->set_global_transform(camera_transform);
+ update_transform_gizmo_view();
+ }
+}
+
+String SpatialEditorGizmo::get_handle_name(int p_idx) const {
+
+ if (get_script_instance() && get_script_instance()->has_method("get_handle_name"))
+ return get_script_instance()->call("get_handle_name", p_idx);
+
+ return "";
+}
+
+Variant SpatialEditorGizmo::get_handle_value(int p_idx) const{
+
+ if (get_script_instance() && get_script_instance()->has_method("get_handle_value"))
+ return get_script_instance()->call("get_handle_value", p_idx);
+
+ return Variant();
+}
+
+void SpatialEditorGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point) {
+
+ if (get_script_instance() && get_script_instance()->has_method("set_handle"))
+ get_script_instance()->call("set_handle", p_idx, p_camera, p_point);
+}
+
+void SpatialEditorGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+
+ if (get_script_instance() && get_script_instance()->has_method("commit_handle"))
+ get_script_instance()->call("commit_handle", p_idx, p_restore, p_cancel);
+}
+
+bool SpatialEditorGizmo::intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum) {
+
+ return false;
+}
+
+bool SpatialEditorGizmo::intersect_ray(const Camera *p_camera, const Point2 &p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle,bool p_sec_first) {
+
+ return false;
+}
+
+SpatialEditorGizmo::SpatialEditorGizmo(){
+
+ selected=false;
+}
+
+
+
+int SpatialEditorViewport::get_selected_count() const {
+
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ int count=0;
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->key()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ count++;
+ }
+
+ return count;
+}
+
+
+
+float SpatialEditorViewport::get_znear() const {
+
+ float val = spatial_editor->get_znear();
+ if (val<0.001)
+ val=0.001;
+ return val;
+}
+float SpatialEditorViewport::get_zfar() const{
+
+ float val = spatial_editor->get_zfar();
+ if (val<0.001)
+ val=0.001;
+ return val;
+
+}
+float SpatialEditorViewport::get_fov() const{
+
+ float val = spatial_editor->get_fov();
+ if (val<0.001)
+ val=0.001;
+ if (val>89)
+ val=89;
+ return val;
+
+}
+
+
+
+Transform SpatialEditorViewport::_get_camera_transform() const {
+
+ return camera->get_global_transform();
+}
+
+Vector3 SpatialEditorViewport::_get_camera_pos() const {
+
+ return _get_camera_transform().origin;
+}
+
+Point2 SpatialEditorViewport::_point_to_screen(const Vector3& p_point) {
+
+ return camera->unproject_position(p_point);
+
+}
+
+Vector3 SpatialEditorViewport::_get_ray_pos(const Vector2& p_pos) const {
+
+ return camera->project_ray_origin(p_pos);
+}
+
+
+Vector3 SpatialEditorViewport::_get_camera_normal() const {
+
+ return -_get_camera_transform().basis.get_axis(2);
+}
+
+Vector3 SpatialEditorViewport::_get_ray(const Vector2& p_pos) {
+
+
+ return camera->project_ray_normal(p_pos);
+
+
+}
+/*
+void SpatialEditorViewport::_clear_id(Spatial *p_node) {
+
+
+ editor_selection->remove_node(p_node);
+
+
+}
+*/
+void SpatialEditorViewport::_clear_selected() {
+
+ editor_selection->clear();
+}
+
+
+
+void SpatialEditorViewport::_select_clicked(bool p_append,bool p_single) {
+
+ if (!clicked)
+ return;
+
+ Object *obj = ObjectDB::get_instance(clicked);
+ if (!obj)
+ return;
+
+
+ Spatial *sp = obj->cast_to<Spatial>();
+ if (!sp)
+ return;
+
+ _select(sp, clicked_wants_append,true);
+}
+
+
+
+void SpatialEditorViewport::_select(Spatial *p_node, bool p_append,bool p_single) {
+
+
+ if (!p_append) {
+
+ // should not modify the selection..
+
+ editor_selection->clear();
+ editor_selection->add_node(p_node);
+
+ } else {
+
+ if (editor_selection->is_selected(p_node) && p_single) {
+ //erase
+ editor_selection->remove_node(p_node);
+ } else {
+
+ editor_selection->add_node(p_node);
+ }
+
+ }
+
+}
+
+ObjectID SpatialEditorViewport::_select_ray(const Point2& p_pos, bool p_append,bool &r_includes_current,int *r_gizmo_handle,bool p_alt_select) {
+
+ if (r_gizmo_handle)
+ *r_gizmo_handle=-1;
+
+ Vector3 ray=_get_ray(p_pos);
+ Vector3 pos=_get_ray_pos(p_pos);
+
+ Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_ray(pos,ray,get_tree()->get_root()->get_world()->get_scenario() );
+ Set<Ref<SpatialEditorGizmo> > found_gizmos;
+
+ ObjectID closest=0;
+ Spatial *item=NULL;
+ float closest_dist=1e20;
+ int selected_handle=-1;
+
+ for (int i=0;i<instances.size();i++) {
+
+ Object *obj=ObjectDB::get_instance(instances[i]);
+ if (!obj)
+ continue;
+
+ Spatial *spat=obj->cast_to<Spatial>();
+
+ if (!spat)
+ continue;
+
+ Ref<SpatialEditorGizmo> seg = spat->get_gizmo();
+
+ if (!seg.is_valid())
+ continue;
+
+ if (found_gizmos.has(seg))
+ continue;
+
+ found_gizmos.insert(seg);
+ Vector3 point;
+ Vector3 normal;
+
+ int handle=-1;
+ bool inters = seg->intersect_ray(camera,p_pos,point,normal,NULL,p_alt_select);
+
+ if (!inters)
+ continue;
+
+ float dist = pos.distance_to(point);
+
+ if (dist<0)
+ continue;
+
+ if (dist < closest_dist) {
+ closest=instances[i];
+ closest_dist=dist;
+ selected_handle=handle;
+ item=spat;
+ }
+
+ // if (editor_selection->is_selected(spat))
+ // r_includes_current=true;
+
+ }
+
+
+ if (!item)
+ return 0;
+
+ if (!editor_selection->is_selected(item) || (r_gizmo_handle && selected_handle>=0)) {
+
+ if (r_gizmo_handle)
+ *r_gizmo_handle=selected_handle;
+
+ }
+
+ return closest;
+
+}
+
+void SpatialEditorViewport::_find_items_at_pos(const Point2& p_pos,bool &r_includes_current,Vector<_RayResult> &results,bool p_alt_select) {
+
+ Vector3 ray=_get_ray(p_pos);
+ Vector3 pos=_get_ray_pos(p_pos);
+
+ Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_ray(pos,ray,get_tree()->get_root()->get_world()->get_scenario() );
+ Set<Ref<SpatialEditorGizmo> > found_gizmos;
+
+ r_includes_current=false;
+
+ for (int i=0;i<instances.size();i++) {
+
+ Object *obj=ObjectDB::get_instance(instances[i]);
+
+ if (!obj)
+ continue;
+
+ Spatial *spat=obj->cast_to<Spatial>();
+
+ if (!spat)
+ continue;
+
+ Ref<SpatialEditorGizmo> seg = spat->get_gizmo();
+
+ if (!seg.is_valid())
+ continue;
+
+ if (found_gizmos.has(seg))
+ continue;
+
+ found_gizmos.insert(seg);
+ Vector3 point;
+ Vector3 normal;
+
+ int handle=-1;
+ bool inters = seg->intersect_ray(camera,p_pos,point,normal,NULL,p_alt_select);
+
+ if (!inters)
+ continue;
+
+ float dist = pos.distance_to(point);
+
+ if (dist<0)
+ continue;
+
+
+
+ if (editor_selection->is_selected(spat))
+ r_includes_current=true;
+
+ _RayResult res;
+ res.item=spat;
+ res.depth=dist;
+ res.handle=handle;
+ results.push_back(res);
+ }
+
+
+ if (results.empty())
+ return;
+
+ results.sort();
+}
+
+
+Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3& p_pos) {
+
+
+ CameraMatrix cm;
+ cm.set_perspective(get_fov(),get_size().aspect(),get_znear(),get_zfar());
+ float screen_w,screen_h;
+ cm.get_viewport_size(screen_w,screen_h);
+
+ Transform camera_transform;
+ camera_transform.translate( cursor.pos );
+ camera_transform.basis.rotate(Vector3(1,0,0),-cursor.x_rot);
+ camera_transform.basis.rotate(Vector3(0,1,0),-cursor.y_rot);
+ camera_transform.translate(0,0,cursor.distance);
+
+ return camera_transform.xform(Vector3( ((p_pos.x/get_size().width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/get_size().height))*2.0-1.0)*screen_h,-get_znear()));
+
+}
+
+
+void SpatialEditorViewport::_select_region() {
+
+ if (cursor.region_begin==cursor.region_end)
+ return; //nothing really
+
+ Vector3 box[4]={
+ Vector3(
+ MIN( cursor.region_begin.x, cursor.region_end.x),
+ MIN( cursor.region_begin.y, cursor.region_end.y),
+ 0
+ ),
+ Vector3(
+ MAX( cursor.region_begin.x, cursor.region_end.x),
+ MIN( cursor.region_begin.y, cursor.region_end.y),
+ 0
+ ),
+ Vector3(
+ MAX( cursor.region_begin.x, cursor.region_end.x),
+ MAX( cursor.region_begin.y, cursor.region_end.y),
+ 0
+ ),
+ Vector3(
+ MIN( cursor.region_begin.x, cursor.region_end.x),
+ MAX( cursor.region_begin.y, cursor.region_end.y),
+ 0
+ )
+ };
+
+ Vector<Plane> frustum;
+
+ Vector3 cam_pos=_get_camera_pos();
+ Set<Ref<SpatialEditorGizmo> > found_gizmos;
+
+ for(int i=0;i<4;i++) {
+
+ Vector3 a=_get_screen_to_space(box[i]);
+ Vector3 b=_get_screen_to_space(box[(i+1)%4]);
+ frustum.push_back( Plane(a,b,cam_pos) );
+ }
+
+ Plane near( cam_pos, -_get_camera_normal() );
+ near.d-=get_znear();
+
+ frustum.push_back( near );
+
+ Plane far=-near;
+ far.d+=500.0;
+
+ frustum.push_back( far );
+
+ Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_convex(frustum,get_tree()->get_root()->get_world()->get_scenario());
+
+
+ for (int i=0;i<instances.size();i++) {
+
+ Object *obj=ObjectDB::get_instance(instances[i]);
+ if (!obj)
+ continue;
+ Spatial *sp = obj->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ Ref<SpatialEditorGizmo> seg = sp->get_gizmo();
+
+ if (!seg.is_valid())
+ continue;
+
+ if (found_gizmos.has(seg))
+ continue;
+
+ if (seg->intersect_frustum(camera,frustum))
+ _select(sp,true,false);
+ }
+
+}
+
+void SpatialEditorViewport::_update_name() {
+
+ String ortho = orthogonal?TTR("Orthogonal"):TTR("Perspective");
+
+ if (name!="")
+ view_menu->set_text("[ "+name+" "+ortho+" ]");
+ else
+ view_menu->set_text("[ "+ortho+" ]");
+}
+
+
+void SpatialEditorViewport::_compute_edit(const Point2& p_point) {
+
+ _edit.click_ray=_get_ray( Vector2( p_point.x, p_point.y ) );
+ _edit.click_ray_pos=_get_ray_pos( Vector2( p_point.x, p_point.y ) );
+ _edit.plane=TRANSFORM_VIEW;
+ spatial_editor->update_transform_gizmo();
+ _edit.center=spatial_editor->get_gizmo_transform().origin;
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ //Vector3 center;
+ //int nc=0;
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ se->original=se->sp->get_global_transform();
+ //center+=se->original.origin;
+ //nc++;
+ }
+
+ /*
+ if (nc)
+ _edit.center=center/float(nc);
+ */
+}
+
+static int _get_key_modifier(const String& p_property) {
+
+ switch(EditorSettings::get_singleton()->get(p_property).operator int()) {
+
+ case 0: return 0;
+ case 1: return KEY_SHIFT;
+ case 2: return KEY_ALT;
+ case 3: return KEY_META;
+ case 4: return KEY_CONTROL;
+ }
+ return 0;
+}
+
+bool SpatialEditorViewport::_gizmo_select(const Vector2& p_screenpos,bool p_hilite_only) {
+
+ if (!spatial_editor->is_gizmo_visible())
+ return false;
+ if (get_selected_count()==0) {
+ if (p_hilite_only)
+ spatial_editor->select_gizmo_hilight_axis(-1);
+ return false;
+ }
+
+
+ Vector3 ray_pos=_get_ray_pos( Vector2( p_screenpos.x, p_screenpos.y ) );
+ Vector3 ray=_get_ray( Vector2( p_screenpos.x, p_screenpos.y ) );
+
+ Transform gt = spatial_editor->get_gizmo_transform();
+ float gs=gizmo_scale;
+
+ if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_MOVE) {
+
+ int col_axis=-1;
+ float col_d=1e20;
+
+ for(int i=0;i<3;i++) {
+
+ Vector3 grabber_pos = gt.origin+gt.basis.get_axis(i)*gs;
+ float grabber_radius = gs*GIZMO_ARROW_SIZE;
+
+ Vector3 r;
+ if (Geometry::segment_intersects_sphere(ray_pos,ray_pos+ray*10000.0,grabber_pos,grabber_radius,&r)) {
+ float d = r.distance_to(ray_pos);
+ if (d<col_d) {
+ col_d=d;
+ col_axis=i;
+ }
+ }
+ }
+
+ if (col_axis!=-1) {
+
+
+ if (p_hilite_only) {
+
+ spatial_editor->select_gizmo_hilight_axis(col_axis);
+
+
+ } else {
+ //handle rotate
+ _edit.mode=TRANSFORM_TRANSLATE;
+ _compute_edit(Point2(p_screenpos.x,p_screenpos.y));
+ _edit.plane=TransformPlane(TRANSFORM_X_AXIS+col_axis);
+ }
+ return true;
+
+
+ }
+
+ }
+
+
+ if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_ROTATE) {
+
+ int col_axis=-1;
+ float col_d=1e20;
+
+ for(int i=0;i<3;i++) {
+
+ Plane plane(gt.origin,gt.basis.get_axis(i).normalized());
+ Vector3 r;
+ if (!plane.intersects_ray(ray_pos,ray,&r))
+ continue;
+
+ float dist = r.distance_to(gt.origin);
+
+
+
+ if (dist > gs*(1-GIZMO_RING_HALF_WIDTH) && dist < gs *(1+GIZMO_RING_HALF_WIDTH)) {
+
+ float d = ray_pos.distance_to(r);
+ if (d<col_d) {
+ col_d=d;
+ col_axis=i;
+ }
+ }
+ }
+
+ if (col_axis!=-1) {
+
+ if (p_hilite_only) {
+
+ spatial_editor->select_gizmo_hilight_axis(col_axis+3);
+ } else {
+ //handle rotate
+ _edit.mode=TRANSFORM_ROTATE;
+ _compute_edit(Point2(p_screenpos.x,p_screenpos.y));
+ _edit.plane=TransformPlane(TRANSFORM_X_AXIS+col_axis);
+ }
+ return true;
+ }
+ }
+
+
+ if (p_hilite_only)
+ spatial_editor->select_gizmo_hilight_axis(-1);
+
+ return false;
+
+}
+
+
+void SpatialEditorViewport::_smouseenter() {
+
+ if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
+ 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_class(),"EditorIcons")?spat->get_class():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_class()+"\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)
+ return; //do NONE
+
+
+ {
+
+ EditorNode *en = editor;
+ EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
+
+ if (!over_plugin_list->empty()) {
+ bool discard = over_plugin_list->forward_spatial_gui_input(camera,p_event);
+ if (discard)
+ return;
+ }
+ }
+
+ switch(p_event.type) {
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &b=p_event.mouse_button;
+
+ switch(b.button_index) {
+
+ case BUTTON_WHEEL_UP: {
+
+
+ cursor.distance/=1.08;
+ if (cursor.distance<0.001)
+ cursor.distance=0.001;
+
+ } break;
+ case BUTTON_WHEEL_DOWN: {
+
+ if (cursor.distance<0.001)
+ cursor.distance=0.001;
+ cursor.distance*=1.08;
+
+ } break;
+ case BUTTON_RIGHT: {
+
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
+
+ if (b.pressed && _edit.gizmo.is_valid()) {
+ //restore
+ _edit.gizmo->commit_handle(_edit.gizmo_handle,_edit.gizmo_initial_value,true);
+ _edit.gizmo=Ref<SpatialEditorGizmo>();
+ }
+
+ if (_edit.mode==TRANSFORM_NONE && b.pressed) {
+
+ Plane cursor_plane(cursor.cursor_pos,_get_camera_normal());
+
+ Vector3 ray_origin = _get_ray_pos(Vector2(b.x,b.y));
+ Vector3 ray_dir = _get_ray(Vector2(b.x,b.y));
+
+
+ //gizmo modify
+
+ if (b.mod.control) {
+
+ Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_ray(ray_origin,ray_dir,get_tree()->get_root()->get_world()->get_scenario() );
+
+ Plane p(ray_origin,_get_camera_normal());
+
+ float min_d=1e10;
+ bool found=false;
+
+ for (int i=0;i<instances.size();i++) {
+
+
+ Object *obj=ObjectDB::get_instance(instances[i]);
+
+ if (!obj)
+ continue;
+
+ VisualInstance *vi=obj->cast_to<VisualInstance>();
+ if (!vi)
+ continue;
+
+ //optimize by checking AABB (although should pre sort by distance)
+ Rect3 aabb = vi->get_global_transform().xform(vi->get_aabb());
+ if (p.distance_to(aabb.get_support(-ray_dir))>min_d)
+ continue;
+
+ PoolVector<Face3> faces = vi->get_faces(VisualInstance::FACES_SOLID);
+ int c = faces.size();
+ if (c>0) {
+ PoolVector<Face3>::Read r = faces.read();
+
+ for(int j=0;j<c;j++) {
+
+ Vector3 inters;
+ if (r[j].intersects_ray(ray_origin,ray_dir,&inters)) {
+
+ float d = p.distance_to(inters);
+ if (d<0)
+ continue;
+
+ if (d<min_d) {
+ min_d=d;
+ found=true;
+ }
+ }
+
+ }
+ }
+
+ }
+
+ if (found) {
+
+ //cursor.cursor_pos=ray_origin+ray_dir*min_d;
+ //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
+
+ }
+
+ } else {
+ Vector3 new_pos;
+ if (cursor_plane.intersects_ray(ray_origin,ray_dir,&new_pos)) {
+
+ //cursor.cursor_pos=new_pos;
+ //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
+ }
+ }
+
+ if (b.mod.alt) {
+
+ if (nav_scheme == NAVIGATION_MAYA)
+ break;
+
+ _list_select(b);
+ return;
+
+ }
+ }
+
+ if (_edit.mode!=TRANSFORM_NONE && b.pressed) {
+ //cancel motion
+ _edit.mode=TRANSFORM_NONE;
+ //_validate_selection();
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ sp->set_global_transform( se->original );
+
+ }
+ surface->update();
+ //VisualServer::get_singleton()->poly_clear(indicators);
+ set_message(TTR("Transform Aborted."),3);
+ }
+ } break;
+ case BUTTON_MIDDLE: {
+
+ if (b.pressed && _edit.mode!=TRANSFORM_NONE) {
+
+ switch(_edit.plane ) {
+
+ case TRANSFORM_VIEW: {
+
+ _edit.plane=TRANSFORM_X_AXIS;
+ set_message(TTR("X-Axis Transform."),2);
+ name="";
+ _update_name();
+ } break;
+ case TRANSFORM_X_AXIS: {
+
+ _edit.plane=TRANSFORM_Y_AXIS;
+ set_message(TTR("Y-Axis Transform."),2);
+
+ } break;
+ case TRANSFORM_Y_AXIS: {
+
+ _edit.plane=TRANSFORM_Z_AXIS;
+ set_message(TTR("Z-Axis Transform."),2);
+
+ } break;
+ case TRANSFORM_Z_AXIS: {
+
+ _edit.plane=TRANSFORM_VIEW;
+ set_message(TTR("View Plane Transform."),2);
+
+ } break;
+ }
+
+ }
+ } break;
+ case BUTTON_LEFT: {
+
+ if (b.pressed) {
+
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
+ if ( (nav_scheme==NAVIGATION_MAYA || nav_scheme==NAVIGATION_MODO) && b.mod.alt) {
+ 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;
+
+
+ //gizmo has priority over everything
+
+ bool can_select_gizmos=true;
+
+ {
+ int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
+ can_select_gizmos = view_menu->get_popup()->is_item_checked( idx );
+ }
+
+
+
+ if (can_select_gizmos && spatial_editor->get_selected()) {
+
+ Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo();
+ if (seg.is_valid()) {
+ int handle=-1;
+ Vector3 point;
+ Vector3 normal;
+ bool inters = seg->intersect_ray(camera,_edit.mouse_pos,point,normal,&handle,b.mod.shift);
+ if (inters && handle!=-1) {
+
+ _edit.gizmo=seg;
+ _edit.gizmo_handle=handle;
+ //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
+ _edit.gizmo_initial_value=seg->get_handle_value(handle);
+ break;
+
+ }
+ }
+ }
+
+
+
+ if (_gizmo_select(_edit.mouse_pos))
+ break;
+
+ clicked=0;
+ clicked_includes_current=false;
+
+
+ if ((spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT && b.mod.control) || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_ROTATE) {
+
+ /* HANDLE ROTATION */
+ if (get_selected_count()==0)
+ break; //bye
+ //handle rotate
+ _edit.mode=TRANSFORM_ROTATE;
+ _compute_edit(Point2(b.x,b.y));
+ break;
+
+ }
+
+ if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_MOVE) {
+
+ if (get_selected_count()==0)
+ break; //bye
+ //handle rotate
+ _edit.mode=TRANSFORM_TRANSLATE;
+ _compute_edit(Point2(b.x,b.y));
+ break;
+
+
+ }
+
+
+ if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SCALE) {
+
+ if (get_selected_count()==0)
+ break; //bye
+ //handle rotate
+ _edit.mode=TRANSFORM_SCALE;
+ _compute_edit(Point2(b.x,b.y));
+ break;
+
+
+ }
+
+
+
+ // todo scale
+
+ int gizmo_handle=-1;
+
+ clicked=_select_ray(Vector2( b.x, b.y ),b.mod.shift,clicked_includes_current,&gizmo_handle,b.mod.shift);
+
+ //clicking is always deferred to either move or release
+
+ clicked_wants_append=b.mod.shift;
+
+ if (!clicked) {
+
+ if (!clicked_wants_append)
+ _clear_selected();
+
+ //default to regionselect
+ cursor.region_select=true;
+ cursor.region_begin=Point2(b.x,b.y);
+ cursor.region_end=Point2(b.x,b.y);
+ }
+
+ if (clicked && gizmo_handle>=0) {
+
+ Object *obj=ObjectDB::get_instance(clicked);
+ if (obj) {
+
+ Spatial *spa = obj->cast_to<Spatial>();
+ if (spa) {
+
+ Ref<SpatialEditorGizmo> seg=spa->get_gizmo();
+ if (seg.is_valid()) {
+
+ _edit.gizmo=seg;
+ _edit.gizmo_handle=gizmo_handle;
+ //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
+ _edit.gizmo_initial_value=seg->get_handle_value(gizmo_handle);
+ //print_line("GIZMO: "+itos(gizmo_handle)+" FROMPOS: "+_edit.orig_gizmo_pos);
+ break;
+
+ }
+ }
+
+ }
+ //_compute_edit(Point2(b.x,b.y)); //in case a motion happens..
+ }
+
+
+
+ surface->update();
+ } else {
+
+
+ if (_edit.gizmo.is_valid()) {
+
+ _edit.gizmo->commit_handle(_edit.gizmo_handle,_edit.gizmo_initial_value,false);
+ _edit.gizmo=Ref<SpatialEditorGizmo>();
+ break;
+ }
+ if (clicked) {
+ _select_clicked(clicked_wants_append,true);
+ //clickd processing was deferred
+ clicked=0;
+
+
+ }
+
+ if (cursor.region_select) {
+ _select_region();
+ cursor.region_select=false;
+ surface->update();
+ }
+
+
+ if (_edit.mode!=TRANSFORM_NONE) {
+
+
+ static const char* _transform_name[4]={"None","Rotate","Translate","Scale"};
+ undo_redo->create_action(_transform_name[_edit.mode]);
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ undo_redo->add_do_method(sp,"set_global_transform",sp->get_global_transform());
+ undo_redo->add_undo_method(sp,"set_global_transform",se->original);
+ }
+ undo_redo->commit_action();
+ _edit.mode=TRANSFORM_NONE;
+ //VisualServer::get_singleton()->poly_clear(indicators);
+ set_message("");
+ }
+
+
+ surface->update();
+ }
+ } break;
+ }
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+ const InputEventMouseMotion &m=p_event.mouse_motion;
+ _edit.mouse_pos=Point2(p_event.mouse_motion.x,p_event.mouse_motion.y);
+
+ if (spatial_editor->get_selected()) {
+
+
+ Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo();
+ if (seg.is_valid()) {
+
+ int selected_handle=-1;
+
+ int handle=-1;
+ Vector3 point;
+ Vector3 normal;
+ bool inters = seg->intersect_ray(camera,_edit.mouse_pos,point,normal,&handle,false);
+ if (inters && handle!=-1) {
+
+ selected_handle=handle;
+
+ }
+
+ if (selected_handle!=spatial_editor->get_over_gizmo_handle()) {
+ spatial_editor->set_over_gizmo_handle(selected_handle);
+ spatial_editor->get_selected()->update_gizmo();
+ if (selected_handle!=-1)
+ spatial_editor->select_gizmo_hilight_axis(-1);
+ }
+ }
+ }
+
+ if (spatial_editor->get_over_gizmo_handle()==-1 && !(m.button_mask&1) && !_edit.gizmo.is_valid()) {
+
+ _gizmo_select(_edit.mouse_pos,true);
+
+ }
+
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
+ NavigationMode nav_mode = NAVIGATION_NONE;
+
+ if (_edit.gizmo.is_valid()) {
+
+ _edit.gizmo->set_handle(_edit.gizmo_handle,camera,Vector2(m.x,m.y));
+ Variant v = _edit.gizmo->get_handle_value(_edit.gizmo_handle);
+ String n = _edit.gizmo->get_handle_name(_edit.gizmo_handle);
+ set_message(n+": "+String(v));
+
+ } else if (m.button_mask&1) {
+
+ if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
+ nav_mode = NAVIGATION_ORBIT;
+ } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt && m.mod.shift) {
+ nav_mode = NAVIGATION_PAN;
+ } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt && m.mod.control) {
+ nav_mode = NAVIGATION_ZOOM;
+ } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt) {
+ nav_mode = NAVIGATION_ORBIT;
+ } else {
+ if (clicked) {
+
+ if (!clicked_includes_current) {
+
+ _select_clicked(clicked_wants_append,true);
+ //clickd processing was deferred
+ }
+
+
+ _compute_edit(_edit.mouse_pos);
+ clicked=0;
+
+ _edit.mode=TRANSFORM_TRANSLATE;
+
+ }
+
+ if (cursor.region_select && nav_mode == NAVIGATION_NONE) {
+
+ cursor.region_end=Point2(m.x,m.y);
+ surface->update();
+ return;
+ }
+
+ if (_edit.mode==TRANSFORM_NONE && nav_mode == NAVIGATION_NONE)
+ break;
+
+
+ Vector3 ray_pos=_get_ray_pos( Vector2( m.x, m.y ) );
+ Vector3 ray=_get_ray( Vector2( m.x, m.y ) );
+
+
+ switch(_edit.mode) {
+
+ case TRANSFORM_SCALE: {
+
+
+ Plane plane=Plane(_edit.center,_get_camera_normal());
+
+
+ Vector3 intersection;
+ if (!plane.intersects_ray(ray_pos,ray,&intersection))
+ break;
+
+ Vector3 click;
+ if (!plane.intersects_ray(_edit.click_ray_pos,_edit.click_ray,&click))
+ break;
+
+ float center_click_dist = click.distance_to(_edit.center);
+ float center_inters_dist = intersection.distance_to(_edit.center);
+ if (center_click_dist==0)
+ break;
+
+ float scale = (center_inters_dist / center_click_dist)*100.0;
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+
+ scale = Math::stepify(scale,spatial_editor->get_scale_snap());
+ }
+
+ set_message(vformat(TTR("Scaling to %s%%."),String::num(scale,1)));
+ scale/=100.0;
+
+ Transform r;
+ r.basis.scale(Vector3(scale,scale,scale));
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+
+ Transform original=se->original;
+
+ Transform base=Transform( Basis(), _edit.center);
+ Transform t=base * (r * (base.inverse() * original));
+
+ sp->set_global_transform(t);
+ }
+
+ surface->update();
+
+ } break;
+
+ case TRANSFORM_TRANSLATE: {
+
+
+ Vector3 motion_mask;
+ Plane plane;
+
+ switch( _edit.plane ) {
+ case TRANSFORM_VIEW:
+ motion_mask=Vector3(0,0,0);
+ plane=Plane(_edit.center,_get_camera_normal());
+ break;
+ case TRANSFORM_X_AXIS:
+ motion_mask=spatial_editor->get_gizmo_transform().basis.get_axis(0);
+ plane=Plane(_edit.center,motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
+ break;
+ case TRANSFORM_Y_AXIS:
+ motion_mask=spatial_editor->get_gizmo_transform().basis.get_axis(1);
+ plane=Plane(_edit.center,motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
+ break;
+ case TRANSFORM_Z_AXIS:
+ motion_mask=spatial_editor->get_gizmo_transform().basis.get_axis(2);
+ plane=Plane(_edit.center,motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
+ break;
+ }
+
+ Vector3 intersection;
+ if (!plane.intersects_ray(ray_pos,ray,&intersection))
+ break;
+
+ Vector3 click;
+ if (!plane.intersects_ray(_edit.click_ray_pos,_edit.click_ray,&click))
+ break;
+
+ //_validate_selection();
+ Vector3 motion = intersection-click;
+ if (motion_mask!=Vector3()) {
+ motion=motion_mask.dot(motion)*motion_mask;
+ }
+
+ float snap=0;
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+
+ snap = spatial_editor->get_translate_snap();
+ motion.snap(snap);
+ }
+
+ //set_message("Translating: "+motion);
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp) {
+ continue;
+ }
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se) {
+ continue;
+ }
+
+ Transform t=se->original;
+ t.origin+=motion;
+ sp->set_global_transform(t);
+ }
+ } break;
+
+ case TRANSFORM_ROTATE: {
+
+
+ Plane plane;
+
+ switch( _edit.plane ) {
+ case TRANSFORM_VIEW:
+ plane=Plane(_edit.center,_get_camera_normal());
+ break;
+ case TRANSFORM_X_AXIS:
+ plane=Plane(_edit.center,spatial_editor->get_gizmo_transform().basis.get_axis(0));
+ break;
+ case TRANSFORM_Y_AXIS:
+ plane=Plane(_edit.center,spatial_editor->get_gizmo_transform().basis.get_axis(1));
+ break;
+ case TRANSFORM_Z_AXIS:
+ plane=Plane(_edit.center,spatial_editor->get_gizmo_transform().basis.get_axis(2));
+ break;
+ }
+
+ Vector3 intersection;
+ if (!plane.intersects_ray(ray_pos,ray,&intersection))
+ break;
+
+ Vector3 click;
+ if (!plane.intersects_ray(_edit.click_ray_pos,_edit.click_ray,&click))
+ break;
+
+
+ Vector3 y_axis=(click-_edit.center).normalized();
+ Vector3 x_axis=plane.normal.cross(y_axis).normalized();
+
+ float angle=Math::atan2( x_axis.dot(intersection-_edit.center), y_axis.dot(intersection-_edit.center) );
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+
+ float snap = spatial_editor->get_rotate_snap();
+
+ if (snap) {
+ angle=Math::rad2deg(angle)+snap*0.5; //else it wont reach +180
+ angle-=Math::fmod(angle,snap);
+ set_message(vformat(TTR("Rotating %s degrees."),rtos(angle)));
+ angle=Math::deg2rad(angle);
+ } else
+ set_message(vformat(TTR("Rotating %s degrees."),rtos(Math::rad2deg(angle))));
+
+ } else {
+ set_message(vformat(TTR("Rotating %s degrees."),rtos(Math::rad2deg(angle))));
+ }
+
+
+
+
+ Transform r;
+ r.basis.rotate(plane.normal,angle);
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+
+ Transform original=se->original;
+
+ Transform base=Transform( Basis(), _edit.center);
+ Transform t=base * r * base.inverse() * original;
+
+ sp->set_global_transform(t);
+ }
+
+ surface->update();
+ /*
+ VisualServer::get_singleton()->poly_clear(indicators);
+
+ Vector<Vector3> points;
+ Vector<Vector3> empty;
+ Vector<Color> colors;
+ points.push_back(intersection);
+ points.push_back(_edit.original.origin);
+ colors.push_back( Color(255,155,100) );
+ colors.push_back( Color(255,155,100) );
+ VisualServer::get_singleton()->poly_add_primitive(indicators,points,empty,colors,empty);
+ */
+ } break;
+ default:{}
+ }
+
+ }
+
+ } else if (m.button_mask&2) {
+
+ if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
+ nav_mode = NAVIGATION_ZOOM;
+ }
+
+ } else if (m.button_mask&4) {
+
+ if (nav_scheme == NAVIGATION_GODOT) {
+
+ int mod = 0;
+ if (m.mod.shift)
+ mod=KEY_SHIFT;
+ if (m.mod.alt)
+ mod=KEY_ALT;
+ if (m.mod.control)
+ mod=KEY_CONTROL;
+ if (m.mod.meta)
+ mod=KEY_META;
+
+ if (mod == _get_key_modifier("editors/3d/pan_modifier"))
+ nav_mode = NAVIGATION_PAN;
+ else if (mod == _get_key_modifier("editors/3d/zoom_modifier"))
+ nav_mode = NAVIGATION_ZOOM;
+ else if (mod == _get_key_modifier("editors/3d/orbit_modifier"))
+ nav_mode = NAVIGATION_ORBIT;
+
+ } else if (nav_scheme == NAVIGATION_MAYA) {
+ if (m.mod.alt)
+ nav_mode = NAVIGATION_PAN;
+ }
+
+ } else if (EditorSettings::get_singleton()->get("editors/3d/emulate_3_button_mouse")) {
+ // Handle trackpad (no external mouse) use case
+ int mod = 0;
+ if (m.mod.shift)
+ mod=KEY_SHIFT;
+ if (m.mod.alt)
+ mod=KEY_ALT;
+ if (m.mod.control)
+ mod=KEY_CONTROL;
+ if (m.mod.meta)
+ mod=KEY_META;
+
+ if(mod){
+ if (mod == _get_key_modifier("editors/3d/pan_modifier"))
+ nav_mode = NAVIGATION_PAN;
+ else if (mod == _get_key_modifier("editors/3d/zoom_modifier"))
+ nav_mode = NAVIGATION_ZOOM;
+ else if (mod == _get_key_modifier("editors/3d/orbit_modifier"))
+ nav_mode = NAVIGATION_ORBIT;
+ }
+ }
+
+ switch(nav_mode) {
+ case NAVIGATION_PAN:{
+
+ real_t pan_speed = 1/150.0;
+ int pan_speed_modifier = 10;
+ if (nav_scheme==NAVIGATION_MAYA && m.mod.shift)
+ pan_speed *= pan_speed_modifier;
+
+ Transform camera_transform;
+
+ camera_transform.translate(cursor.pos);
+ camera_transform.basis.rotate(Vector3(1,0,0),-cursor.x_rot);
+ camera_transform.basis.rotate(Vector3(0,1,0),-cursor.y_rot);
+ Vector3 translation(-m.relative_x*pan_speed,m.relative_y*pan_speed,0);
+ translation*=cursor.distance/DISTANCE_DEFAULT;
+ camera_transform.translate(translation);
+ cursor.pos=camera_transform.origin;
+
+ } break;
+
+ case NAVIGATION_ZOOM: {
+ real_t zoom_speed = 1/80.0;
+ int zoom_speed_modifier = 10;
+ if (nav_scheme==NAVIGATION_MAYA && m.mod.shift)
+ zoom_speed *= zoom_speed_modifier;
+
+ NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/zoom_style").operator int();
+ if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
+ if ( m.relative_x > 0)
+ cursor.distance*=1-m.relative_x*zoom_speed;
+ else if (m.relative_x < 0)
+ cursor.distance/=1+m.relative_x*zoom_speed;
+ }
+ else {
+ if ( m.relative_y > 0)
+ cursor.distance*=1+m.relative_y*zoom_speed;
+ else if (m.relative_y < 0)
+ cursor.distance/=1-m.relative_y*zoom_speed;
+ }
+
+ } break;
+
+ case NAVIGATION_ORBIT: {
+ cursor.x_rot+=m.relative_y/80.0;
+ cursor.y_rot+=m.relative_x/80.0;
+ if (cursor.x_rot>Math_PI/2.0)
+ cursor.x_rot=Math_PI/2.0;
+ if (cursor.x_rot<-Math_PI/2.0)
+ cursor.x_rot=-Math_PI/2.0;
+ name="";
+ _update_name();
+ } break;
+
+ default: {}
+ }
+ } break;
+ case InputEvent::KEY: {
+ const InputEventKey &k = p_event.key;
+ if (!k.pressed)
+ break;
+
+ if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) {
+ if (_edit.mode != TRANSFORM_NONE) {
+ _edit.snap=true;
+ }
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/bottom_view", p_event)) {
+ cursor.y_rot = 0;
+ cursor.x_rot = -Math_PI/2.0;
+ set_message(TTR("Bottom View."),2);
+ name = TTR("Bottom");
+ _update_name();
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/top_view", p_event)) {
+ cursor.y_rot = 0;
+ cursor.x_rot = Math_PI/2.0;
+ set_message(TTR("Top View."),2);
+ name = TTR("Top");
+ _update_name();
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/rear_view", p_event)) {
+ cursor.x_rot = 0;
+ cursor.y_rot = Math_PI;
+ set_message(TTR("Rear View."),2);
+ name = TTR("Rear");
+ _update_name();
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/front_view", p_event)) {
+ cursor.x_rot = 0;
+ cursor.y_rot=0;
+ set_message(TTR("Front View."),2);
+ name=TTR("Front");
+ _update_name();
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/left_view", p_event)) {
+ cursor.x_rot=0;
+ cursor.y_rot = Math_PI/2.0;
+ set_message(TTR("Left View."),2);
+ name = TTR("Left");
+ _update_name();
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/right_view", p_event)) {
+ cursor.x_rot=0;
+ cursor.y_rot = -Math_PI/2.0;
+ set_message(TTR("Right View."),2);
+ name = TTR("Right");
+ _update_name();
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/switch_perspective_orthogonal", p_event)) {
+ _menu_option(orthogonal?VIEW_PERSPECTIVE:VIEW_ORTHOGONAL);
+ _update_name();
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/insert_anim_key", p_event)) {
+ if (!get_selected_count() || _edit.mode!=TRANSFORM_NONE)
+ break;
+
+ if (!AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
+ set_message(TTR("Keying is disabled (no key inserted)."));
+ break;
+ }
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ emit_signal("transform_key_request",sp,"",sp->get_transform());
+ }
+
+
+ set_message(TTR("Animation Key Inserted."));
+ }
+
+ if (k.scancode == KEY_SPACE) {
+ if (!k.pressed) emit_signal("toggle_maximize_view", this);
+ }
+
+ } break;
+
+ }
+
+}
+
+void SpatialEditorViewport::set_message(String p_message,float p_time) {
+
+ message=p_message;
+ message_time=p_time;
+
+}
+
+
+
+void SpatialEditorViewport::_notification(int p_what) {
+
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ bool visible=is_visible_in_tree();
+
+ set_process(visible);
+
+ if (visible)
+ _update_camera();
+
+ call_deferred("update_transform_gizmo_view");
+ }
+
+ if (p_what==NOTIFICATION_RESIZED) {
+
+ call_deferred("update_transform_gizmo_view");
+
+ }
+
+ if (p_what==NOTIFICATION_PROCESS) {
+
+
+ //force editr camera
+ /*
+ current_camera=get_root_node()->get_current_camera();
+ if (current_camera!=camera) {
+
+
+ }
+ */
+
+ _update_camera();
+
+ Map<Node*,Object*> &selection = editor_selection->get_selection();
+
+ bool changed=false;
+ bool exist=false;
+
+ for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->key()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+
+ VisualInstance *vi=sp->cast_to<VisualInstance>();
+
+
+ if (se->aabb.has_no_surface()) {
+
+ se->aabb=vi?vi->get_aabb():Rect3( Vector3(-0.2,-0.2,-0.2),Vector3(0.4,0.4,0.4));
+ }
+
+ Transform t=sp->get_global_transform();
+ t.translate(se->aabb.pos);
+ t.basis.scale( se->aabb.size );
+
+ exist=true;
+ if (se->last_xform==t)
+ continue;
+ changed=true;
+ se->last_xform=t;
+ VisualServer::get_singleton()->instance_set_transform(se->sbox_instance,t);
+
+ }
+
+ if (changed || (spatial_editor->is_gizmo_visible() && !exist)) {
+ spatial_editor->update_transform_gizmo();
+ }
+
+ if (message_time>0) {
+
+ if (message!=last_message) {
+ surface->update();
+ last_message=message;
+ }
+
+ message_time-=get_fixed_process_delta_time();
+ if (message_time<0)
+ surface->update();
+ }
+
+ //update shadow atlas if changed
+
+ int shadowmap_size = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/size");
+ int atlas_q0 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_0_subdiv");
+ int atlas_q1 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_1_subdiv");
+ int atlas_q2 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_2_subdiv");
+ int atlas_q3 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_3_subdiv");
+
+
+ viewport->set_shadow_atlas_size(shadowmap_size);
+ viewport->set_shadow_atlas_quadrant_subdiv(0,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
+ viewport->set_shadow_atlas_quadrant_subdiv(1,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
+ viewport->set_shadow_atlas_quadrant_subdiv(2,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
+ viewport->set_shadow_atlas_quadrant_subdiv(3,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
+
+ //update msaa if changed
+
+ int msaa_mode = GlobalConfig::get_singleton()->get("rendering/quality/msaa");
+ viewport->set_msaa(Viewport::MSAA(msaa_mode));
+
+ bool hdr = GlobalConfig::get_singleton()->get("rendering/quality/hdr");
+ viewport->set_hdr(hdr);
+
+
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ surface->connect("draw",this,"_draw");
+ surface->connect("gui_input",this,"_sinput");
+ surface->connect("mouse_entered",this,"_smouseenter");
+ preview_camera->set_icon(get_icon("Camera","EditorIcons"));
+ _init_gizmo_instance(index);
+ }
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+
+ _finish_gizmo_instances();
+
+ }
+
+ if (p_what==NOTIFICATION_MOUSE_ENTER) {
+
+
+ }
+
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+
+
+ }
+
+}
+
+void SpatialEditorViewport::_draw() {
+
+ if (surface->has_focus()) {
+ Size2 size = surface->get_size();
+ Rect2 r =Rect2(Point2(),size);
+ get_stylebox("EditorFocus","EditorStyles")->draw(surface->get_canvas_item(),r);
+ }
+
+
+ RID ci=surface->get_canvas_item();
+
+ if (cursor.region_select) {
+
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor.region_begin,cursor.region_end-cursor.region_begin),Color(0.7,0.7,1.0,0.3));
+ }
+
+ if (message_time>0) {
+ Ref<Font> font = get_font("font","Label");
+ Point2 msgpos=Point2(5,get_size().y-20);
+ font->draw(ci,msgpos+Point2(1,1),message,Color(0,0,0,0.8));
+ font->draw(ci,msgpos+Point2(-1,-1),message,Color(0,0,0,0.8));
+ font->draw(ci,msgpos,message,Color(1,1,1,1));
+ }
+
+
+ if (_edit.mode==TRANSFORM_ROTATE) {
+
+ Point2 center = _point_to_screen(_edit.center);
+ VisualServer::get_singleton()->canvas_item_add_line(ci,_edit.mouse_pos, center, Color(0.4,0.7,1.0,0.8));
+
+
+ }
+
+ if (previewing) {
+
+
+ Size2 ss = Size2( GlobalConfig::get_singleton()->get("display/width"), GlobalConfig::get_singleton()->get("display/height") );
+ float aspect = ss.aspect();
+ Size2 s = get_size();
+
+ Rect2 draw_rect;
+
+
+ switch(previewing->get_keep_aspect_mode()) {
+ case Camera::KEEP_WIDTH: {
+
+ draw_rect.size = Size2(s.width,s.width/aspect);
+ draw_rect.pos.x=0;
+ draw_rect.pos.y=(s.height-draw_rect.size.y)*0.5;
+
+ } break;
+ case Camera::KEEP_HEIGHT: {
+
+ draw_rect.size = Size2(s.height*aspect,s.height);
+ draw_rect.pos.y=0;
+ draw_rect.pos.x=(s.width-draw_rect.size.x)*0.5;
+
+ } break;
+ }
+
+ draw_rect = Rect2(Vector2(),s).clip(draw_rect);
+
+ surface->draw_line(draw_rect.pos,draw_rect.pos+Vector2(draw_rect.size.x,0),Color(0.6,0.6,0.1,0.5),2.0);
+ surface->draw_line(draw_rect.pos+Vector2(draw_rect.size.x,0),draw_rect.pos+draw_rect.size,Color(0.6,0.6,0.1,0.5),2.0);
+ surface->draw_line(draw_rect.pos+draw_rect.size,draw_rect.pos+Vector2(0,draw_rect.size.y),Color(0.6,0.6,0.1,0.5),2.0);
+ surface->draw_line(draw_rect.pos,draw_rect.pos+Vector2(0,draw_rect.size.y),Color(0.6,0.6,0.1,0.5),2.0);
+ }
+
+}
+
+
+void SpatialEditorViewport::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case VIEW_TOP: {
+
+ cursor.x_rot=Math_PI/2.0;
+ cursor.y_rot=0;
+ name=TTR("Top");
+ _update_name();
+ } break;
+ case VIEW_BOTTOM: {
+
+ cursor.x_rot=-Math_PI/2.0;
+ cursor.y_rot=0;
+ name=TTR("Bottom");
+ _update_name();
+
+ } break;
+ case VIEW_LEFT: {
+
+ cursor.y_rot=Math_PI/2.0;
+ cursor.x_rot=0;
+ name=TTR("Left");
+ _update_name();
+
+ } break;
+ case VIEW_RIGHT: {
+
+ cursor.y_rot=-Math_PI/2.0;
+ cursor.x_rot=0;
+ name=TTR("Right");
+ _update_name();
+
+ } break;
+ case VIEW_FRONT: {
+
+ cursor.y_rot=0;
+ cursor.x_rot=0;
+ name=TTR("Front");
+ _update_name();
+
+ } break;
+ case VIEW_REAR: {
+
+ cursor.y_rot=Math_PI;
+ cursor.x_rot=0;
+ name=TTR("Rear");
+ _update_name();
+
+ } break;
+ case VIEW_CENTER_TO_ORIGIN: {
+
+ cursor.pos = Vector3(0,0,0);
+
+ } break;
+ case VIEW_CENTER_TO_SELECTION: {
+
+ focus_selection();
+
+ } break;
+ case VIEW_ALIGN_SELECTION_WITH_VIEW: {
+
+ if (!get_selected_count())
+ break;
+
+ Transform camera_transform = camera->get_global_transform();
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ undo_redo->create_action(TTR("Align with view"));
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ Transform xform = camera_transform;
+ xform.scale_basis(sp->get_scale());
+
+ undo_redo->add_do_method(sp,"set_global_transform",xform);
+ undo_redo->add_undo_method(sp,"set_global_transform",sp->get_global_transform());
+ }
+ undo_redo->commit_action();
+ } break;
+ case VIEW_ENVIRONMENT: {
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT);
+ bool current = view_menu->get_popup()->is_item_checked( idx );
+ current=!current;
+ if (current) {
+
+ camera->set_environment(RES());
+ } else {
+
+ camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
+ }
+
+ view_menu->get_popup()->set_item_checked( idx, current );
+
+
+ } break;
+ case VIEW_PERSPECTIVE: {
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false );
+ orthogonal=false;
+ call_deferred("update_transform_gizmo_view");
+ _update_name();
+
+ } break;
+ case VIEW_ORTHOGONAL: {
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true );
+ orthogonal=true;
+ call_deferred("update_transform_gizmo_view");
+ _update_name();
+
+ } break;
+ case VIEW_AUDIO_LISTENER: {
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
+ bool current = view_menu->get_popup()->is_item_checked( idx );
+ current=!current;
+ viewport->set_as_audio_listener(current);
+ view_menu->get_popup()->set_item_checked( idx, current );
+
+ } break;
+ case VIEW_GIZMOS: {
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
+ bool current = view_menu->get_popup()->is_item_checked( idx );
+ current=!current;
+ if (current)
+ camera->set_cull_mask( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) );
+ else
+ camera->set_cull_mask( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_GRID_LAYER) );
+ view_menu->get_popup()->set_item_checked( idx, current );
+
+ } break;
+
+ }
+
+}
+
+
+void SpatialEditorViewport::_preview_exited_scene() {
+
+ preview_camera->set_pressed(false);
+ _toggle_camera_preview(false);
+ view_menu->show();
+}
+
+
+void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
+
+ uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx);//|(1<<GIZMO_GRID_LAYER);
+
+ for(int i=0;i<3;i++) {
+ move_gizmo_instance[i]=VS::get_singleton()->instance_create();
+ VS::get_singleton()->instance_set_base(move_gizmo_instance[i],spatial_editor->get_move_gizmo(i)->get_rid());
+ VS::get_singleton()->instance_set_scenario(move_gizmo_instance[i],get_tree()->get_root()->get_world()->get_scenario());
+ VS::get_singleton()->instance_set_visible(move_gizmo_instance[i],false);
+ //VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
+ VS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
+ VS::get_singleton()->instance_set_layer_mask(move_gizmo_instance[i],layer);
+
+ rotate_gizmo_instance[i]=VS::get_singleton()->instance_create();
+ VS::get_singleton()->instance_set_base(rotate_gizmo_instance[i],spatial_editor->get_rotate_gizmo(i)->get_rid());
+ VS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i],get_tree()->get_root()->get_world()->get_scenario());
+ VS::get_singleton()->instance_set_visible(rotate_gizmo_instance[i],false);
+ //VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
+ VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
+ VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i],layer);
+ }
+
+}
+
+
+void SpatialEditorViewport::_finish_gizmo_instances() {
+
+
+ for(int i=0;i<3;i++) {
+ VS::get_singleton()->free(move_gizmo_instance[i]);
+ VS::get_singleton()->free(rotate_gizmo_instance[i]);
+ }
+
+}
+void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
+
+
+ ERR_FAIL_COND(p_activate && !preview);
+ ERR_FAIL_COND(!p_activate && !previewing);
+
+ if (!p_activate) {
+
+ previewing->disconnect("tree_exited",this,"_preview_exited_scene");
+ previewing=NULL;
+ VS::get_singleton()->viewport_attach_camera( viewport->get_viewport_rid(), camera->get_camera() ); //restore
+ if (!preview)
+ preview_camera->hide();
+ view_menu->show();
+ surface->update();
+
+ } else {
+
+ previewing=preview;
+ previewing->connect("tree_exited",this,"_preview_exited_scene");
+ VS::get_singleton()->viewport_attach_camera( viewport->get_viewport_rid(), preview->get_camera() ); //replace
+ view_menu->hide();
+ surface->update();
+
+ }
+}
+
+void SpatialEditorViewport::_selection_result_pressed(int p_result) {
+
+ if (selection_results.size() <= p_result)
+ return;
+
+ clicked=selection_results[p_result].item->get_instance_ID();
+
+ if (clicked) {
+ _select_clicked(clicked_wants_append,true);
+ clicked=0;
+ }
+}
+
+void SpatialEditorViewport::_selection_menu_hide() {
+
+ selection_results.clear();
+ selection_menu->clear();
+ selection_menu->set_size(Vector2(0, 0));
+}
+
+void SpatialEditorViewport::set_can_preview(Camera* p_preview) {
+
+ preview=p_preview;
+
+ if (!preview_camera->is_pressed()) {
+
+ if (p_preview) {
+ preview_camera->show();
+ } else {
+ preview_camera->hide();
+ }
+ }
+}
+
+void SpatialEditorViewport::update_transform_gizmo_view() {
+
+ if (!is_visible_in_tree())
+ return;
+
+ Transform xform = spatial_editor->get_gizmo_transform();
+
+
+ Transform camera_xform = camera->get_transform();
+ Vector3 camz = -camera_xform.get_basis().get_axis(2).normalized();
+ Vector3 camy = -camera_xform.get_basis().get_axis(1).normalized();
+ Plane p(camera_xform.origin,camz);
+ float gizmo_d = Math::abs( p.distance_to(xform.origin ));
+ float d0 = camera->unproject_position(camera_xform.origin+camz*gizmo_d).y;
+ float d1 = camera->unproject_position(camera_xform.origin+camz*gizmo_d+camy).y;
+ float dd = Math::abs(d0-d1);
+ if (dd==0)
+ dd=0.0001;
+
+ float gsize = EditorSettings::get_singleton()->get("editors/3d/manipulator_gizmo_size");
+ gizmo_scale=(gsize/Math::abs(dd));
+ Vector3 scale = Vector3(1,1,1) * gizmo_scale;
+
+ xform.basis.scale(scale);
+
+ //xform.basis.scale(GIZMO_SCALE_DEFAULT*Vector3(1,1,1));
+
+
+ for(int i=0;i<3;i++) {
+ VisualServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform );
+ VisualServer::get_singleton()->instance_set_visible(move_gizmo_instance[i],spatial_editor->is_gizmo_visible()&& (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_MOVE) );
+ VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform );
+ VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i],spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_ROTATE) );
+ }
+
+}
+
+void SpatialEditorViewport::set_state(const Dictionary& p_state) {
+
+ cursor.pos=p_state["pos"];
+ cursor.x_rot=p_state["x_rot"];
+ cursor.y_rot=p_state["y_rot"];
+ cursor.distance=p_state["distance"];
+ bool env = p_state["use_environment"];
+ bool orth = p_state["use_orthogonal"];
+ if (orth)
+ _menu_option(VIEW_ORTHOGONAL);
+ else
+ _menu_option(VIEW_PERSPECTIVE);
+ if (env != camera->get_environment().is_valid())
+ _menu_option(VIEW_ENVIRONMENT);
+ if (p_state.has("listener")) {
+ bool listener = p_state["listener"];
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
+ viewport->set_as_audio_listener(listener);
+ view_menu->get_popup()->set_item_checked( idx, listener );
+ }
+
+ if (p_state.has("previewing")) {
+ Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]);
+ if (pv && pv->cast_to<Camera>()) {
+ previewing=pv->cast_to<Camera>();
+ previewing->connect("tree_exited",this,"_preview_exited_scene");
+ VS::get_singleton()->viewport_attach_camera( viewport->get_viewport_rid(), previewing->get_camera() ); //replace
+ view_menu->hide();
+ surface->update();
+ preview_camera->set_pressed(true);
+ preview_camera->show();
+ }
+ }
+}
+
+Dictionary SpatialEditorViewport::get_state() const {
+
+ Dictionary d;
+ d["pos"]=cursor.pos;
+ d["x_rot"]=cursor.x_rot;
+ d["y_rot"]=cursor.y_rot;
+ d["distance"]=cursor.distance;
+ d["use_environment"]=camera->get_environment().is_valid();
+ d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
+ d["listener"]=viewport->is_audio_listener();
+ if (previewing) {
+ d["previewing"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);
+ }
+
+ return d;
+}
+
+
+void SpatialEditorViewport::_bind_methods(){
+
+ ClassDB::bind_method(D_METHOD("_draw"),&SpatialEditorViewport::_draw);
+ ClassDB::bind_method(D_METHOD("_smouseenter"),&SpatialEditorViewport::_smouseenter);
+ ClassDB::bind_method(D_METHOD("_sinput"),&SpatialEditorViewport::_sinput);
+ ClassDB::bind_method(D_METHOD("_menu_option"),&SpatialEditorViewport::_menu_option);
+ ClassDB::bind_method(D_METHOD("_toggle_camera_preview"),&SpatialEditorViewport::_toggle_camera_preview);
+ ClassDB::bind_method(D_METHOD("_preview_exited_scene"),&SpatialEditorViewport::_preview_exited_scene);
+ ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"),&SpatialEditorViewport::update_transform_gizmo_view);
+ ClassDB::bind_method(D_METHOD("_selection_result_pressed"),&SpatialEditorViewport::_selection_result_pressed);
+ ClassDB::bind_method(D_METHOD("_selection_menu_hide"),&SpatialEditorViewport::_selection_menu_hide);
+
+ ADD_SIGNAL( MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")) );
+}
+
+
+void SpatialEditorViewport::reset() {
+
+ orthogonal=false;
+ message_time=0;
+ message="";
+ last_message="";
+ name="";
+
+ cursor.x_rot=0.5;
+ cursor.y_rot=0.5;
+ cursor.distance=4;
+ cursor.region_select=false;
+ _update_name();
+}
+
+
+void SpatialEditorViewport::focus_selection() {
+ if (!get_selected_count())
+ return;
+
+ Vector3 center;
+ int count=0;
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ center+=sp->get_global_transform().origin;
+ count++;
+ }
+
+ if( count != 0 ) {
+ center/=float(count);
+ }
+
+ cursor.pos=center;
+}
+
+
+SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
+
+ _edit.mode=TRANSFORM_NONE;
+ _edit.plane=TRANSFORM_VIEW;
+ _edit.edited_gizmo=0;
+ _edit.snap=1;
+ _edit.gizmo_handle=0;
+
+
+
+ index=p_index;
+ editor=p_editor;
+ editor_selection=editor->get_editor_selection();
+ undo_redo=editor->get_undo_redo();
+ clicked=0;
+ clicked_includes_current=false;
+ orthogonal=false;
+ message_time=0;
+
+ spatial_editor=p_spatial_editor;
+ ViewportContainer *c=memnew(ViewportContainer);
+ c->set_stretch(true);
+ 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);
+ surface->set_area_as_parent_rect();
+ camera = memnew(Camera);
+ camera->set_disable_gizmo(true);
+ camera->set_cull_mask( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+p_index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) );
+ //camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
+ viewport->add_child(camera);
+ camera->make_current();
+ surface->set_focus_mode(FOCUS_ALL);
+
+ view_menu = memnew( MenuButton );
+ surface->add_child(view_menu);
+ view_menu->set_pos( Point2(4,4));
+ view_menu->set_self_modulate(Color(1,1,1,0.5));
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP);
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/bottom_view"), VIEW_BOTTOM);
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/left_view"), VIEW_LEFT);
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/right_view"), VIEW_RIGHT);
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/front_view"), VIEW_FRONT);
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/rear_view"), VIEW_REAR);
+ view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_check_item(TTR("Perspective") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_PERSPECTIVE);
+ view_menu->get_popup()->add_check_item(TTR("Orthogonal") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_ORTHOGONAL);
+ view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE),true);
+ view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTR("Environment")), VIEW_ENVIRONMENT);
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT),true);
+ view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_audio_listener", TTR("Audio Listener")), VIEW_AUDIO_LISTENER);
+ view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_gizmos", TTR("Gizmos")),VIEW_GIZMOS);
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_GIZMOS),true);
+
+ view_menu->get_popup()->add_separator();
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_origin"), VIEW_CENTER_TO_ORIGIN);
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_selection"), VIEW_CENTER_TO_SELECTION);
+ view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW);
+ view_menu->get_popup()->connect("id_pressed",this,"_menu_option");
+
+ preview_camera = memnew( Button );
+ preview_camera->set_toggle_mode(true);
+ preview_camera->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,90);
+ preview_camera->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,10);
+ preview_camera->set_text("preview");
+ surface->add_child(preview_camera);
+ preview_camera->hide();
+ preview_camera->connect("toggled",this,"_toggle_camera_preview");
+ previewing=NULL;
+ preview=NULL;
+ gizmo_scale=1.0;
+
+ selection_menu = memnew( PopupMenu );
+ add_child(selection_menu);
+ selection_menu->set_custom_minimum_size(Vector2(100, 0));
+ selection_menu->connect("id_pressed", this, "_selection_result_pressed");
+ selection_menu->connect("popup_hide", this, "_selection_menu_hide");
+
+ if (p_index==0) {
+ view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER),true);
+ viewport->set_as_audio_listener(true);
+ }
+
+
+ name=TTR("Top");
+ _update_name();
+
+ EditorSettings::get_singleton()->connect("settings_changed",this,"update_transform_gizmo_view");
+
+}
+
+
+
+
+
+
+
+SpatialEditor *SpatialEditor::singleton=NULL;
+
+SpatialEditorSelectedItem::~SpatialEditorSelectedItem() {
+
+ if (sbox_instance.is_valid())
+ VisualServer::get_singleton()->free(sbox_instance);
+}
+
+
+
+void SpatialEditor::select_gizmo_hilight_axis(int p_axis) {
+
+
+ for(int i=0;i<3;i++) {
+
+ move_gizmo[i]->surface_set_material(0,i==p_axis?gizmo_hl:gizmo_color[i]);
+ rotate_gizmo[i]->surface_set_material(0,(i+3)==p_axis?gizmo_hl:gizmo_color[i]);
+ }
+
+}
+
+void SpatialEditor::update_transform_gizmo() {
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+ Rect3 center;
+ bool first=true;
+
+ Basis gizmo_basis;
+ bool local_gizmo_coords = transform_menu->get_popup()->is_item_checked( transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS) );
+
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ Transform xf = se->sp->get_global_transform();
+ if (first) {
+ center.pos=xf.origin;
+ first=false;
+ if (local_gizmo_coords) {
+ gizmo_basis=xf.basis;
+ gizmo_basis.orthonormalize();
+ }
+ } else {
+ center.expand_to(xf.origin);
+ gizmo_basis=Basis();
+ }
+ //count++;
+ }
+
+ Vector3 pcenter = center.pos+center.size*0.5;
+ gizmo.visible=!first;
+ gizmo.transform.origin=pcenter;
+ gizmo.transform.basis=gizmo_basis;
+
+ for(int i=0;i<4;i++) {
+ viewports[i]->update_transform_gizmo_view();
+ }
+
+}
+
+
+Object *SpatialEditor::_get_editor_data(Object *p_what) {
+
+ Spatial *sp = p_what->cast_to<Spatial>();
+ if (!sp)
+ return NULL;
+
+
+ SpatialEditorSelectedItem *si = memnew( SpatialEditorSelectedItem );
+
+ si->sp=sp;
+ si->sbox_instance=VisualServer::get_singleton()->instance_create2(selection_box->get_rid(),sp->get_world()->get_scenario());
+ VS::get_singleton()->instance_geometry_set_cast_shadows_setting(si->sbox_instance, VS::SHADOW_CASTING_SETTING_OFF);
+
+ if (get_tree()->is_editor_hint())
+ editor->call("edit_node",sp);
+
+ return si;
+}
+
+void SpatialEditor::_generate_selection_box() {
+
+ Rect3 aabb( Vector3(), Vector3(1,1,1) );
+ aabb.grow_by( aabb.get_longest_axis_size()/20.0 );
+
+ Ref<SurfaceTool> st = memnew( SurfaceTool );
+
+ st->begin(Mesh::PRIMITIVE_LINES);
+ for (int i=0;i<12;i++) {
+
+ Vector3 a,b;
+ aabb.get_edge(i,a,b);
+
+ /*Vector<Vector3> points;
+ Vector<Color> colors;
+ points.push_back(a);
+ points.push_back(b);*/
+
+ st->add_color( Color(1.0,1.0,0.8,0.8) );
+ st->add_vertex(a);
+ st->add_color( Color(1.0,1.0,0.8,0.4) );
+ st->add_vertex(a.linear_interpolate(b,0.2));
+
+ st->add_color( Color(1.0,1.0,0.8,0.4) );
+ st->add_vertex(a.linear_interpolate(b,0.8));
+ st->add_color( Color(1.0,1.0,0.8,0.8) );
+ st->add_vertex(b);
+
+ }
+
+ Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
+ mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+ mat->set_albedo(Color(1,1,1));
+ mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
+ st->set_material(mat);
+ selection_box = st->commit();
+}
+
+
+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) ))
+ vc=1;
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS) ))
+ vc=2;
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS) ))
+ vc=3;
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) ))
+ vc=4;
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) ))
+ vc=5;
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) ))
+ vc=6;
+
+ d["viewport_mode"]=vc;
+ Array vpdata;
+ for(int i=0;i<4;i++) {
+ vpdata.push_back( viewports[i]->get_state() );
+ }
+
+ d["viewports"]=vpdata;
+
+ d["default_light"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT) );
+ d["ambient_light_color"]=settings_ambient_color->get_pick_color();
+
+ d["default_srgb"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB) );
+ d["show_grid"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID) );
+ d["show_origin"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN) );
+ d["fov"]=get_fov();
+ d["znear"]=get_znear();
+ d["zfar"]=get_zfar();
+ d["deflight_rot_x"]=settings_default_light_rot_x;
+ d["deflight_rot_y"]=settings_default_light_rot_y;
+
+ return d;
+}
+void SpatialEditor::set_state(const Dictionary& p_state) {
+
+ Dictionary d = p_state;
+
+ 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 );
+ }
+
+ if (d.has("translate_snap"))
+ snap_translate->set_text(d["translate_snap"]);
+
+ if (d.has("rotate_snap"))
+ snap_rotate->set_text(d["rotate_snap"]);
+
+ 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_value(float(d["zfar"]));
+ if (d.has("znear"))
+ settings_znear->set_value(float(d["znear"]));
+ if (d.has("fov"))
+ settings_fov->set_value(float(d["fov"]));
+
+ if (d.has("default_light")) {
+ bool use = d["default_light"];
+
+ bool existing = light_instance.is_valid();
+ if (use!=existing) {
+ if (existing) {
+ VisualServer::get_singleton()->free(light_instance);
+ light_instance=RID();
+ } else {
+ light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario());
+ VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform);
+
+ }
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), light_instance.is_valid() );
+ }
+
+ }
+ if (d.has("ambient_light_color")) {
+ settings_ambient_color->set_pick_color(d["ambient_light_color"]);
+ //viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,d["ambient_light_color"]);
+ }
+
+ if (d.has("default_srgb")) {
+ bool use = d["default_srgb"];
+
+ //viewport_environment->set_enable_fx(Environment::FX_SRGB,use);
+ //view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB), use );
+ }
+ if (d.has("show_grid")) {
+ bool use = d["show_grid"];
+
+ if (use!=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID))) {
+ _menu_item_pressed(MENU_VIEW_GRID);
+ }
+ }
+
+ if (d.has("show_origin")) {
+ bool use = d["show_origin"];
+
+ if (use!=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN))) {
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), use );
+ VisualServer::get_singleton()->instance_set_visible(origin_instance,use);
+ }
+ }
+
+ if (d.has("deflight_rot_x"))
+ settings_default_light_rot_x=d["deflight_rot_x"];
+ if (d.has("deflight_rot_y"))
+ settings_default_light_rot_y=d["deflight_rot_y"];
+
+ _update_default_light_angle();
+
+
+}
+
+
+void SpatialEditor::edit(Spatial *p_spatial) {
+
+ if (p_spatial!=selected) {
+ if (selected) {
+
+ Ref<SpatialEditorGizmo> seg = selected->get_gizmo();
+ if (seg.is_valid()) {
+ seg->set_selected(false);
+ selected->update_gizmo();
+ }
+ }
+
+ selected=p_spatial;
+ over_gizmo_handle=-1;
+
+ if (selected) {
+
+ Ref<SpatialEditorGizmo> seg = selected->get_gizmo();
+ if (seg.is_valid()) {
+ seg->set_selected(true);
+ selected->update_gizmo();
+ }
+ }
+ }
+
+ /*
+ if (p_spatial) {
+ _validate_selection();
+ if (selected.has(p_spatial->get_instance_ID()) && selected.size()==1)
+ return;
+ _select(p_spatial->get_instance_ID(),false,true);
+
+ // should become the selection
+ }
+ */
+}
+
+void SpatialEditor::_xform_dialog_action() {
+
+ Transform t;
+ //translation
+ Vector3 scale;
+ Vector3 rotate;
+ Vector3 translate;
+
+ for(int i=0;i<3;i++) {
+ translate[i]=xform_translate[i]->get_text().to_double();
+ rotate[i]=Math::deg2rad(xform_rotate[i]->get_text().to_double());
+ scale[i]=xform_scale[i]->get_text().to_double();
+ }
+
+ t.basis.scale(scale);
+ t.basis.rotate(rotate);
+ t.origin=translate;
+
+
+ undo_redo->create_action(TTR("XForm Dialog"));
+
+ List<Node*> &selection = editor_selection->get_selected_node_list();
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Spatial *sp = E->get()->cast_to<Spatial>();
+ if (!sp)
+ continue;
+
+ SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
+ if (!se)
+ continue;
+
+ bool post = xform_type->get_selected()>0;
+
+ Transform tr = sp->get_global_transform();
+ if (post)
+ tr = tr * t;
+ else {
+
+ tr.basis = t.basis * tr.basis;
+ tr.origin+=t.origin;
+ }
+
+ undo_redo->add_do_method(sp,"set_global_transform",tr);
+ undo_redo->add_undo_method(sp,"set_global_transform",sp->get_global_transform());
+ }
+ undo_redo->commit_action();
+}
+
+void SpatialEditor::_menu_item_pressed(int p_option) {
+
+ switch(p_option) {
+
+ case MENU_TOOL_SELECT:
+ case MENU_TOOL_MOVE:
+ case MENU_TOOL_ROTATE:
+ case MENU_TOOL_SCALE:
+ case MENU_TOOL_LIST_SELECT: {
+
+ 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.","List Selection Mode."};
+ //set_message(_mode[p_option],3);
+ update_transform_gizmo();
+
+ } break;
+ case MENU_TRANSFORM_USE_SNAP: {
+
+ bool is_checked = transform_menu->get_popup()->is_item_checked( transform_menu->get_popup()->get_item_index(p_option) );
+ snap_enabled=!is_checked;
+ transform_menu->get_popup()->set_item_checked( transform_menu->get_popup()->get_item_index(p_option), snap_enabled );
+ } break;
+ case MENU_TRANSFORM_CONFIGURE_SNAP: {
+
+ snap_dialog->popup_centered(Size2(200,180));
+ } break;
+ case MENU_TRANSFORM_LOCAL_COORDS: {
+
+ bool is_checked = transform_menu->get_popup()->is_item_checked( transform_menu->get_popup()->get_item_index(p_option) );
+ transform_menu->get_popup()->set_item_checked( transform_menu->get_popup()->get_item_index(p_option), !is_checked );
+ update_transform_gizmo();
+
+ } break;
+ case MENU_TRANSFORM_DIALOG: {
+
+ for(int i=0;i<3;i++) {
+
+
+ xform_translate[i]->set_text("0");
+ xform_rotate[i]->set_text("0");
+ xform_scale[i]->set_text("1");
+
+ }
+
+ xform_dialog->popup_centered(Size2(200,200));
+
+ } break;
+ case MENU_VIEW_USE_DEFAULT_LIGHT: {
+
+ bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
+
+ if (is_checked) {
+ VisualServer::get_singleton()->free(light_instance);
+ light_instance=RID();
+ } else {
+ light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario());
+ VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform);
+
+ _update_default_light_angle();
+ }
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), light_instance.is_valid() );
+
+ } break;
+ case MENU_VIEW_USE_DEFAULT_SRGB: {
+
+ bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
+
+ if (is_checked) {
+ //viewport_environment->set_enable_fx(Environment::FX_SRGB,false);
+ } else {
+ //viewport_environment->set_enable_fx(Environment::FX_SRGB,true);
+ }
+
+ is_checked = ! is_checked;
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), is_checked );
+
+
+ } break;
+ case MENU_VIEW_USE_1_VIEWPORT: {
+
+ for(int i=1;i<4;i++) {
+
+ viewports[i]->hide();
+ }
+
+ viewports[0]->set_area_as_parent_rect();
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
+
+ } break;
+ case MENU_VIEW_USE_2_VIEWPORTS: {
+
+ for(int i=1;i<4;i++) {
+
+ if (i==1 || i==3)
+ viewports[i]->hide();
+ else
+ viewports[i]->show();
+
+
+ }
+ viewports[0]->set_area_as_parent_rect();
+ //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
+ viewports[2]->set_area_as_parent_rect();
+ //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
+
+ } break;
+ case MENU_VIEW_USE_2_VIEWPORTS_ALT: {
+
+ for(int i=1;i<4;i++) {
+
+ if (i==1 || i==3)
+ viewports[i]->hide();
+ else
+ viewports[i]->show();
+
+
+ }
+ viewports[0]->set_area_as_parent_rect();
+ //viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ viewports[2]->set_area_as_parent_rect();
+ //viewports[2]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
+
+ } break;
+ case MENU_VIEW_USE_3_VIEWPORTS: {
+
+ for(int i=1;i<4;i++) {
+
+ if (i==1)
+ viewports[i]->hide();
+ else
+ viewports[i]->show();
+ }
+ viewports[0]->set_area_as_parent_rect();
+ //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
+ viewports[2]->set_area_as_parent_rect();
+ //viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
+ viewports[3]->set_area_as_parent_rect();
+ //viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
+ //viewports[3]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
+
+ } break;
+ case MENU_VIEW_USE_3_VIEWPORTS_ALT: {
+
+ for(int i=1;i<4;i++) {
+
+ if (i==1)
+ viewports[i]->hide();
+ else
+ viewports[i]->show();
+ }
+ viewports[0]->set_area_as_parent_rect();
+ //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
+ //viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ viewports[2]->set_area_as_parent_rect();
+ //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
+ //viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ viewports[3]->set_area_as_parent_rect();
+ //viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), true );
+
+ } break;
+ case MENU_VIEW_USE_4_VIEWPORTS: {
+
+ for(int i=1;i<4;i++) {
+
+ viewports[i]->show();
+ }
+ viewports[0]->set_area_as_parent_rect();
+ //viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
+ viewports[1]->set_area_as_parent_rect();
+ //viewports[1]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
+ //viewports[1]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
+ viewports[2]->set_area_as_parent_rect();
+ //viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
+ //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
+ viewports[3]->set_area_as_parent_rect();
+ //viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
+ //viewports[3]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
+
+ } break;
+ case MENU_VIEW_DISPLAY_NORMAL: {
+
+
+ VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_DISABLED );
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false );
+
+ } break;
+ case MENU_VIEW_DISPLAY_WIREFRAME: {
+
+ VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_WIREFRAME );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false );
+
+ } break;
+ case MENU_VIEW_DISPLAY_OVERDRAW: {
+
+ VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_OVERDRAW );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), true );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false );
+
+ } break;
+ case MENU_VIEW_DISPLAY_SHADELESS: {
+
+ VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_SHADELESS );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false );
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), true );
+
+ } break;
+ case MENU_VIEW_ORIGIN: {
+
+ bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
+
+ is_checked=!is_checked;
+ VisualServer::get_singleton()->instance_set_visible(origin_instance,is_checked);
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), is_checked);
+ } break;
+ case MENU_VIEW_GRID: {
+
+ bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
+
+ grid_enabled=!is_checked;
+
+ for(int i=0;i<3;++i) {
+ if (grid_enable[i]) {
+ VisualServer::get_singleton()->instance_set_visible(grid_instance[i],grid_enabled);
+ grid_visible[i]=grid_enabled;
+ }
+ }
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), grid_enabled );
+
+
+ } break;
+ case MENU_VIEW_CAMERA_SETTINGS: {
+
+ settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size()+Size2(50,50));
+ } break;
+
+ }
+}
+
+
+void SpatialEditor::_init_indicators() {
+
+ //make sure that the camera indicator is not selectable
+ light=VisualServer::get_singleton()->light_create( VisualServer::LIGHT_DIRECTIONAL );
+ //VisualServer::get_singleton()->light_set_shadow( light, true );
+ light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario());
+
+
+
+ light_transform.rotate(Vector3(1,0,0),-Math_PI/5.0);
+ VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform);
+
+
+ //RID mat = VisualServer::get_singleton()->fixed_material_create();
+ ///VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA,true);
+ //VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);
+
+
+ {
+
+ indicator_mat.instance();
+ indicator_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+ //indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true);
+ indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
+ indicator_mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
+
+ indicator_mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
+
+ PoolVector<Color> grid_colors[3];
+ PoolVector<Vector3> grid_points[3];
+ Vector<Color> origin_colors;
+ Vector<Vector3> origin_points;
+
+ Color grid_color = EditorSettings::get_singleton()->get("editors/3d/grid_color");
+
+ for(int i=0;i<3;i++) {
+ Vector3 axis;
+ axis[i]=1;
+ Vector3 axis_n1;
+ axis_n1[(i+1)%3]=1;
+ Vector3 axis_n2;
+ axis_n2[(i+2)%3]=1;
+
+ origin_colors.push_back(Color(axis.x,axis.y,axis.z));
+ origin_colors.push_back(Color(axis.x,axis.y,axis.z));
+ origin_points.push_back(axis*4096);
+ origin_points.push_back(axis*-4096);
+#define ORIGIN_GRID_SIZE 25
+
+ for(int j=-ORIGIN_GRID_SIZE;j<=ORIGIN_GRID_SIZE;j++) {
+
+
+ grid_colors[i].push_back(grid_color);
+ grid_colors[i].push_back(grid_color);
+ grid_colors[i].push_back(grid_color);
+ grid_colors[i].push_back(grid_color);
+ grid_points[i].push_back(axis_n1*ORIGIN_GRID_SIZE+axis_n2*j);
+ grid_points[i].push_back(-axis_n1*ORIGIN_GRID_SIZE+axis_n2*j);
+ grid_points[i].push_back(axis_n2*ORIGIN_GRID_SIZE+axis_n1*j);
+ grid_points[i].push_back(-axis_n2*ORIGIN_GRID_SIZE+axis_n1*j);
+
+ }
+
+ grid[i] = VisualServer::get_singleton()->mesh_create();
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+ d[VisualServer::ARRAY_VERTEX]=grid_points[i];
+ d[VisualServer::ARRAY_COLOR]=grid_colors[i];
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i],VisualServer::PRIMITIVE_LINES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(grid[i],0,indicator_mat->get_rid());
+ grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i],get_tree()->get_root()->get_world()->get_scenario());
+
+ grid_visible[i]=false;
+ grid_enable[i]=false;
+ VisualServer::get_singleton()->instance_set_visible(grid_instance[i],false);
+ VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
+ VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << SpatialEditorViewport::GIZMO_GRID_LAYER);
+
+
+ }
+
+ origin = VisualServer::get_singleton()->mesh_create();
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+ d[VisualServer::ARRAY_VERTEX]=origin_points;
+ d[VisualServer::ARRAY_COLOR]=origin_colors;
+
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(origin,VisualServer::PRIMITIVE_LINES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(origin,0,indicator_mat->get_rid());
+
+
+ //origin = VisualServer::get_singleton()->poly_create();
+ //VisualServer::get_singleton()->poly_add_primitive(origin,origin_points,Vector<Vector3>(),origin_colors,Vector<Vector3>());
+ //VisualServer::get_singleton()->poly_set_material(origin,indicator_mat,true);
+ origin_instance = VisualServer::get_singleton()->instance_create2(origin,get_tree()->get_root()->get_world()->get_scenario());
+ VS::get_singleton()->instance_set_layer_mask(origin_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER);
+
+ VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF);
+
+
+
+ VisualServer::get_singleton()->instance_set_visible(grid_instance[1],true);
+ grid_enable[1]=true;
+ grid_visible[1]=true;
+ grid_enabled=true;
+ last_grid_snap=1;
+
+ }
+
+ {
+ cursor_mesh = VisualServer::get_singleton()->mesh_create();
+ PoolVector<Vector3> cursor_points;
+ float cs = 0.25;
+ cursor_points.push_back(Vector3(+cs,0,0));
+ cursor_points.push_back(Vector3(-cs,0,0));
+ cursor_points.push_back(Vector3(0,+cs,0));
+ cursor_points.push_back(Vector3(0,-cs,0));
+ cursor_points.push_back(Vector3(0,0,+cs));
+ cursor_points.push_back(Vector3(0,0,-cs));
+ cursor_material.instance();
+ cursor_material->set_albedo(Color(0,1,1));
+ cursor_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+ d[VS::ARRAY_VERTEX]=cursor_points;
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(cursor_mesh,VS::PRIMITIVE_LINES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(cursor_mesh,0,cursor_material->get_rid());
+
+ cursor_instance = VisualServer::get_singleton()->instance_create2(cursor_mesh,get_tree()->get_root()->get_world()->get_scenario());
+ VS::get_singleton()->instance_set_layer_mask(cursor_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER);
+
+ VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(cursor_instance, VS::SHADOW_CASTING_SETTING_OFF);
+
+
+ }
+
+
+ {
+
+ //move gizmo
+
+
+ float gizmo_alph = EditorSettings::get_singleton()->get("editors/3d/manipulator_gizmo_opacity");
+
+ gizmo_hl = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ) );
+ gizmo_hl->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ gizmo_hl->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true);
+ gizmo_hl->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ gizmo_hl->set_albedo(Color(1,1,1,gizmo_alph+0.2f));
+
+ for(int i=0;i<3;i++) {
+
+ move_gizmo[i]=Ref<Mesh>( memnew( Mesh ) );
+ rotate_gizmo[i]=Ref<Mesh>( memnew( Mesh ) );
+
+
+ Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
+ mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true);
+ mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ Color col;
+ col[i]=1.0;
+ col.a= gizmo_alph;
+ mat->set_albedo(col);
+ gizmo_color[i]=mat;
+
+
+
+
+ Vector3 ivec;
+ ivec[i]=1;
+ Vector3 nivec;
+ nivec[(i+1)%3]=1;
+ nivec[(i+2)%3]=1;
+ Vector3 ivec2;
+ ivec2[(i+1)%3]=1;
+ Vector3 ivec3;
+ ivec3[(i+2)%3]=1;
+
+
+ {
+
+ Ref<SurfaceTool> surftool = memnew( SurfaceTool );
+ surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
+
+ //translate
+
+ const int arrow_points=5;
+ Vector3 arrow[5]={
+ nivec*0.0+ivec*0.0,
+ nivec*0.01+ivec*0.0,
+ nivec*0.01+ivec*1.0,
+ nivec*0.1+ivec*1.0,
+ nivec*0.0+ivec*(1+GIZMO_ARROW_SIZE),
+ };
+
+ int arrow_sides=6;
+
+
+ for(int k = 0; k < 7 ; k++) {
+
+
+ Basis ma(ivec,Math_PI*2*float(k)/arrow_sides);
+ Basis mb(ivec,Math_PI*2*float(k+1)/arrow_sides);
+
+
+ for(int j=0;j<arrow_points-1;j++) {
+
+ Vector3 points[4]={
+ ma.xform(arrow[j]),
+ mb.xform(arrow[j]),
+ mb.xform(arrow[j+1]),
+ ma.xform(arrow[j+1]),
+ };
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[1]);
+ surftool->add_vertex(points[2]);
+
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[2]);
+ surftool->add_vertex(points[3]);
+ }
+
+ }
+
+ surftool->set_material(mat);
+ surftool->commit(move_gizmo[i]);
+ }
+
+ {
+
+
+ Ref<SurfaceTool> surftool = memnew( SurfaceTool );
+ surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
+
+ Vector3 circle[5]={
+ ivec*0.02+ivec2*0.02+ivec2*1.0,
+ ivec*-0.02+ivec2*0.02+ivec2*1.0,
+ ivec*-0.02+ivec2*-0.02+ivec2*1.0,
+ ivec*0.02+ivec2*-0.02+ivec2*1.0,
+ ivec*0.02+ivec2*0.02+ivec2*1.0,
+ };
+
+
+ for(int k = 0; k < 33 ; k++) {
+
+
+ Basis ma(ivec,Math_PI*2*float(k)/32);
+ Basis mb(ivec,Math_PI*2*float(k+1)/32);
+
+
+ for(int j=0;j<4;j++) {
+
+ Vector3 points[4]={
+ ma.xform(circle[j]),
+ mb.xform(circle[j]),
+ mb.xform(circle[j+1]),
+ ma.xform(circle[j+1]),
+ };
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[1]);
+ surftool->add_vertex(points[2]);
+
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[2]);
+ surftool->add_vertex(points[3]);
+ }
+
+ }
+
+ surftool->set_material(mat);
+ surftool->commit(rotate_gizmo[i]);
+
+ }
+
+
+ }
+ }
+
+ /*for(int i=0;i<4;i++) {
+
+ viewports[i]->init_gizmo_instance(i);
+ }*/
+
+ _generate_selection_box();
+
+
+ //get_scene()->get_root_node()->cast_to<EditorNode>()->get_scene_root()->add_child(camera);
+
+ //current_camera=camera;
+
+}
+
+void SpatialEditor::_finish_indicators() {
+
+ VisualServer::get_singleton()->free(origin_instance);
+ VisualServer::get_singleton()->free(origin);
+ for(int i=0;i<3;i++) {
+ VisualServer::get_singleton()->free(grid_instance[i]);
+ VisualServer::get_singleton()->free(grid[i]);
+ }
+ VisualServer::get_singleton()->free(light_instance);
+ VisualServer::get_singleton()->free(light);
+ //VisualServer::get_singleton()->free(poly);
+ //VisualServer::get_singleton()->free(indicators_instance);
+ //VisualServer::get_singleton()->free(indicators);
+
+ VisualServer::get_singleton()->free(cursor_instance);
+ VisualServer::get_singleton()->free(cursor_mesh);
+}
+
+void SpatialEditor::_instance_scene() {
+#if 0
+ EditorNode *en = get_scene()->get_root_node()->cast_to<EditorNode>();
+ ERR_FAIL_COND(!en);
+ String path = en->get_filesystem_dock()->get_selected_path();
+ if (path=="") {
+ set_message(TTR("No scene selected to instance!"));
+ return;
+ }
+
+ undo_redo->create_action(TTR("Instance at Cursor"));
+
+ Node* scene = en->request_instance_scene(path);
+
+ if (!scene) {
+ set_message(TTR("Could not instance scene!"));
+ undo_redo->commit_action(); //bleh
+ return;
+ }
+
+ Spatial *s = scene->cast_to<Spatial>();
+ if (s) {
+
+ undo_redo->add_do_method(s,"set_global_transform",Transform(Matrix3(),cursor.cursor_pos));
+ }
+
+ undo_redo->commit_action();
+#endif
+}
+
+void SpatialEditor::_unhandled_key_input(InputEvent p_event) {
+
+ if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
+ return;
+
+#if 0
+//i don't remember this being used, why was it here?
+ {
+
+ EditorNode *en = editor;
+ EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
+
+ if (!over_plugin_list->empty() && over_plugin_list->forward_gui_input(p_event)) {
+
+ return; //ate the over input event
+ }
+
+ }
+#endif
+
+ switch(p_event.type) {
+
+ case InputEvent::KEY: {
+
+
+ const InputEventKey &k=p_event.key;
+
+ if (!k.pressed)
+ break;
+
+ switch(k.scancode) {
+
+ case KEY_Q: _menu_item_pressed(MENU_TOOL_SELECT); break;
+ case KEY_W: _menu_item_pressed(MENU_TOOL_MOVE); break;
+ case KEY_E: _menu_item_pressed(MENU_TOOL_ROTATE); break;
+ case KEY_R: _menu_item_pressed(MENU_TOOL_SCALE); break;
+
+ case KEY_Z: {
+ if (k.mod.shift || k.mod.control || k.mod.command)
+ break;
+
+ if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME))) {
+ _menu_item_pressed(MENU_VIEW_DISPLAY_NORMAL);
+ } else {
+ _menu_item_pressed(MENU_VIEW_DISPLAY_WIREFRAME);
+ }
+ } break;
+
+#if 0
+#endif
+ }
+
+ } break;
+ }
+}
+void SpatialEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_READY) {
+
+ tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon( get_icon("ToolSelect","EditorIcons") );
+ 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();
+
+
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT),get_icon("Panels1","EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS),get_icon("Panels2","EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT),get_icon("Panels2Alt","EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS),get_icon("Panels3","EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT),get_icon("Panels3Alt","EditorIcons"));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS),get_icon("Panels4","EditorIcons"));
+
+ _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
+
+ get_tree()->connect("node_removed",this,"_node_removed");
+ VS::get_singleton()->scenario_set_fallback_environment(get_viewport()->find_world()->get_scenario(),viewport_environment->get_rid());
+
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ gizmos = memnew( SpatialEditorGizmos );
+ _init_indicators();
+ _update_default_light_angle();
+ }
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ _finish_indicators();
+ memdelete( gizmos );
+
+ }
+}
+
+void SpatialEditor::add_control_to_menu_panel(Control *p_control) {
+
+
+ hbc_menu->add_child(p_control);
+}
+
+void SpatialEditor::set_can_preview(Camera* p_preview) {
+
+ for(int i=0;i<4;i++) {
+ viewports[i]->set_can_preview(p_preview);
+ }
+}
+
+VSplitContainer *SpatialEditor::get_shader_split() {
+
+ return shader_split;
+}
+
+HSplitContainer *SpatialEditor::get_palette_split() {
+
+ return palette_split;
+}
+
+
+void SpatialEditor::_request_gizmo(Object* p_obj) {
+
+ Spatial *sp=p_obj->cast_to<Spatial>();
+ if (!sp)
+ return;
+ if (editor->get_edited_scene() && (sp==editor->get_edited_scene() || sp->get_owner()==editor->get_edited_scene() || editor->get_edited_scene()->is_editable_instance(sp->get_owner()))) {
+
+ Ref<SpatialEditorGizmo> seg;
+
+ for(int i=0;i<EditorNode::get_singleton()->get_editor_data().get_editor_plugin_count();i++) {
+
+ seg = EditorNode::get_singleton()->get_editor_data().get_editor_plugin(i)->create_spatial_gizmo(sp);
+ if (seg.is_valid())
+ break;
+ }
+
+ if (!seg.is_valid()) {
+ seg = gizmos->get_gizmo(sp);
+ }
+
+ if (seg.is_valid()) {
+ sp->set_gizmo(seg);
+ }
+
+
+ if (seg.is_valid() && sp==selected) {
+ seg->set_selected(true);
+ selected->update_gizmo();
+ }
+
+ }
+}
+
+void SpatialEditor::_toggle_maximize_view(Object* p_viewport) {
+ if (!p_viewport) return;
+ SpatialEditorViewport *current_viewport = p_viewport->cast_to<SpatialEditorViewport>();
+ if (!current_viewport) return;
+
+ int index=-1;
+ bool maximized = false;
+ for(int i=0;i<4;i++) {
+ if (viewports[i]==current_viewport) {
+ index=i;
+ if ( current_viewport->get_global_rect() == viewport_base->get_global_rect() )
+ maximized=true;
+ break;
+ }
+ }
+ if (index==-1) return;
+
+ if (!maximized) {
+
+ for(int i=0;i<4;i++) {
+ if (i==index)
+ viewports[i]->set_area_as_parent_rect();
+ else
+ viewports[i]->hide();
+ }
+ } else {
+
+ for(int i=0;i<4;i++)
+ viewports[i]->show();
+
+ if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT) ))
+ _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS) ))
+ _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS);
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) ))
+ _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS) ))
+ _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) ))
+ _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
+ else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) ))
+ _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
+ }
+
+}
+
+
+void SpatialEditor::_node_removed(Node* p_node) {
+
+ if (p_node==selected)
+ selected=NULL;
+}
+
+void SpatialEditor::_bind_methods() {
+
+ //ClassDB::bind_method("_gui_input",&SpatialEditor::_gui_input);
+ ClassDB::bind_method("_unhandled_key_input",&SpatialEditor::_unhandled_key_input);
+ ClassDB::bind_method("_node_removed",&SpatialEditor::_node_removed);
+ ClassDB::bind_method("_menu_item_pressed",&SpatialEditor::_menu_item_pressed);
+ ClassDB::bind_method("_xform_dialog_action",&SpatialEditor::_xform_dialog_action);
+ ClassDB::bind_method("_instance_scene",&SpatialEditor::_instance_scene);
+ ClassDB::bind_method("_get_editor_data",&SpatialEditor::_get_editor_data);
+ ClassDB::bind_method("_request_gizmo",&SpatialEditor::_request_gizmo);
+ ClassDB::bind_method("_default_light_angle_input",&SpatialEditor::_default_light_angle_input);
+ ClassDB::bind_method("_update_ambient_light_color",&SpatialEditor::_update_ambient_light_color);
+ ClassDB::bind_method("_toggle_maximize_view",&SpatialEditor::_toggle_maximize_view);
+
+ ADD_SIGNAL( MethodInfo("transform_key_request") );
+
+
+}
+
+void SpatialEditor::clear() {
+
+ settings_fov->set_value(EDITOR_DEF("editors/3d/default_fov",60.0));
+ settings_znear->set_value(EDITOR_DEF("editors/3d/default_z_near",0.1));
+ settings_zfar->set_value(EDITOR_DEF("editors/3d/default_z_far",1500.0));
+
+ for(int i=0;i<4;i++) {
+ viewports[i]->reset();
+ }
+
+ _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
+ _menu_item_pressed(MENU_VIEW_DISPLAY_NORMAL);
+
+
+ VisualServer::get_singleton()->instance_set_visible(origin_instance,true);
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), true);
+ for(int i=0;i<3;++i) {
+ if (grid_enable[i]) {
+ VisualServer::get_singleton()->instance_set_visible(grid_instance[i],true);
+ grid_visible[i]=true;
+ }
+ }
+
+ for(int i=0;i<4;i++) {
+
+ viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER),i==0);
+ viewports[i]->viewport->set_as_audio_listener(i==0);
+ }
+
+ view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true );
+
+ settings_default_light_rot_x=Math_PI*0.3;
+ settings_default_light_rot_y=Math_PI*0.2;
+
+ //viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,Color(0.15,0.15,0.15));
+ settings_ambient_color->set_pick_color(Color(0.15,0.15,0.15));
+ if (!light_instance.is_valid())
+ _menu_item_pressed(MENU_VIEW_USE_DEFAULT_LIGHT);
+
+ _update_default_light_angle();
+
+
+}
+
+
+void SpatialEditor::_update_ambient_light_color(const Color& p_color) {
+
+ //viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,settings_ambient_color->get_color());
+
+}
+
+void SpatialEditor::_update_default_light_angle() {
+
+ Transform t;
+ t.basis.rotate(Vector3(1,0,0),-settings_default_light_rot_x);
+ t.basis.rotate(Vector3(0,1,0),-settings_default_light_rot_y);
+ settings_dlight->set_transform(t);
+ if (light_instance.is_valid()) {
+ VS::get_singleton()->instance_set_transform(light_instance,t);
+ }
+
+}
+
+void SpatialEditor::_default_light_angle_input(const InputEvent& p_event) {
+
+
+ if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&(0x1|0x2|0x4)) {
+
+ settings_default_light_rot_y = Math::fposmod(settings_default_light_rot_y - p_event.mouse_motion.relative_x*0.01,Math_PI*2.0);
+ settings_default_light_rot_x = Math::fposmod(settings_default_light_rot_x - p_event.mouse_motion.relative_y*0.01,Math_PI*2.0);
+ _update_default_light_angle();
+ }
+
+}
+
+
+SpatialEditor::SpatialEditor(EditorNode *p_editor) {
+
+ gizmo.visible=true;
+ gizmo.scale=1.0;
+
+ viewport_environment = Ref<Environment>( memnew( Environment ) );
+ undo_redo=p_editor->get_undo_redo();
+ VBoxContainer *vbc = this;
+
+ custom_camera=NULL;
+ singleton=this;
+ editor=p_editor;
+ editor_selection=editor->get_editor_selection();
+ editor_selection->add_editor_plugin(this);
+
+ snap_enabled=false;
+ tool_mode = TOOL_MODE_SELECT;
+
+ //set_focus_mode(FOCUS_ALL);
+
+ hbc_menu = memnew( HBoxContainer );
+ vbc->add_child(hbc_menu);
+
+
+ Vector<Variant> button_binds;
+ button_binds.resize(1);
+
+ tool_button[TOOL_MODE_SELECT] = memnew( ToolButton );
+ hbc_menu->add_child( tool_button[TOOL_MODE_SELECT] );
+ tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true);
+ tool_button[TOOL_MODE_SELECT]->set_flat(true);
+ 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)\n"+keycode_get_string(KEY_MASK_CMD)+"Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection");
+
+
+ tool_button[TOOL_MODE_MOVE] = memnew( ToolButton );
+
+ hbc_menu->add_child( tool_button[TOOL_MODE_MOVE] );
+ tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true);
+ tool_button[TOOL_MODE_MOVE]->set_flat(true);
+ button_binds[0]=MENU_TOOL_MOVE;
+ tool_button[TOOL_MODE_MOVE]->connect("pressed", this,"_menu_item_pressed",button_binds);
+ tool_button[TOOL_MODE_MOVE]->set_tooltip(TTR("Move Mode (W)"));
+
+ tool_button[TOOL_MODE_ROTATE] = memnew( ToolButton );
+ hbc_menu->add_child( tool_button[TOOL_MODE_ROTATE] );
+ tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true);
+ tool_button[TOOL_MODE_ROTATE]->set_flat(true);
+ button_binds[0]=MENU_TOOL_ROTATE;
+ tool_button[TOOL_MODE_ROTATE]->connect("pressed", this,"_menu_item_pressed",button_binds);
+ tool_button[TOOL_MODE_ROTATE]->set_tooltip(TTR("Rotate Mode (E)"));
+
+ tool_button[TOOL_MODE_SCALE] = memnew( ToolButton );
+ hbc_menu->add_child( tool_button[TOOL_MODE_SCALE] );
+ tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true);
+ tool_button[TOOL_MODE_SCALE]->set_flat(true);
+ button_binds[0]=MENU_TOOL_SCALE;
+ tool_button[TOOL_MODE_SCALE]->connect("pressed", this,"_menu_item_pressed",button_binds);
+ tool_button[TOOL_MODE_SCALE]->set_tooltip(TTR("Scale Mode (R)"));
+
+ instance_button = memnew( Button );
+ 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(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
+
+ vs = memnew( VSeparator );
+ hbc_menu->add_child(vs);
+
+
+ ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT+KEY_KP_7);
+ ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), KEY_KP_7);
+ ED_SHORTCUT("spatial_editor/rear_view", TTR("Rear View"), KEY_MASK_ALT+KEY_KP_1);
+ ED_SHORTCUT("spatial_editor/front_view", TTR("Front View"), KEY_KP_1);
+ ED_SHORTCUT("spatial_editor/left_view", TTR("Left View"), KEY_MASK_ALT+KEY_KP_3);
+ ED_SHORTCUT("spatial_editor/right_view", TTR("Right View"), KEY_KP_3);
+ ED_SHORTCUT("spatial_editor/switch_perspective_orthogonal", TTR("Switch Perspective/Orthogonal view"), KEY_KP_5);
+ ED_SHORTCUT("spatial_editor/snap", TTR("Snap"), KEY_S);
+ ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), KEY_K);
+ ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), KEY_O);
+ ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), KEY_F);
+ ED_SHORTCUT("spatial_editor/align_selection_with_view", TTR("Align Selection With View"), KEY_MASK_ALT+KEY_MASK_CMD+KEY_F);
+
+
+ PopupMenu *p;
+
+ transform_menu = memnew( MenuButton );
+ transform_menu->set_text(TTR("Transform"));
+ hbc_menu->add_child( transform_menu );
+
+ p = transform_menu->get_popup();
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_snap", TTR("Use Snap")), MENU_TRANSFORM_USE_SNAP);
+ p->add_shortcut(ED_SHORTCUT("spatial_editor/configure_snap", TTR("Configure Snap..")), MENU_TRANSFORM_CONFIGURE_SNAP);
+ p->add_separator();
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Local Coords")), MENU_TRANSFORM_LOCAL_COORDS);
+ //p->set_item_checked(p->get_item_count()-1,true);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("spatial_editor/transform_dialog", TTR("Transform Dialog..")), MENU_TRANSFORM_DIALOG);
+
+ p->connect("id_pressed", this,"_menu_item_pressed");
+
+ view_menu = memnew( MenuButton );
+ view_menu->set_text(TTR("View"));
+ view_menu->set_pos( Point2( 212,0) );
+ hbc_menu->add_child( view_menu );
+
+ p = view_menu->get_popup();
+
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_default_light", TTR("Use Default Light")), MENU_VIEW_USE_DEFAULT_LIGHT);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_default_srgb", TTR("Use Default sRGB")), MENU_VIEW_USE_DEFAULT_SRGB);
+ p->add_separator();
+
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD+KEY_1), MENU_VIEW_USE_1_VIEWPORT);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD+KEY_2), MENU_VIEW_USE_2_VIEWPORTS);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT+KEY_MASK_CMD+KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"),KEY_MASK_CMD+KEY_3), MENU_VIEW_USE_3_VIEWPORTS);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KEY_MASK_ALT+KEY_MASK_CMD+KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KEY_MASK_CMD+KEY_4), MENU_VIEW_USE_4_VIEWPORTS);
+ p->add_separator();
+
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_normal", TTR("Display Normal")), MENU_VIEW_DISPLAY_NORMAL);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_wireframe", TTR("Display Wireframe")), MENU_VIEW_DISPLAY_WIREFRAME);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_overdraw", TTR("Display Overdraw")), MENU_VIEW_DISPLAY_OVERDRAW);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_shadeless", TTR("Display Shadeless")), MENU_VIEW_DISPLAY_SHADELESS);
+ p->add_separator();
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN);
+ p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid")), MENU_VIEW_GRID);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings")), MENU_VIEW_CAMERA_SETTINGS);
+
+
+ p->set_item_checked( p->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), true );
+ p->set_item_checked( p->get_item_index(MENU_VIEW_DISPLAY_NORMAL), true );
+ p->set_item_checked( p->get_item_index(MENU_VIEW_ORIGIN), true );
+ p->set_item_checked( p->get_item_index(MENU_VIEW_GRID), true );
+
+
+ p->connect("id_pressed", this,"_menu_item_pressed");
+
+
+ /* REST OF MENU */
+
+ palette_split = memnew( HSplitContainer);
+ palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
+ vbc->add_child(palette_split);
+
+ shader_split = memnew( VSplitContainer );
+ shader_split->set_h_size_flags(SIZE_EXPAND_FILL);
+ palette_split->add_child(shader_split);
+ viewport_base = memnew( Control );
+ shader_split->add_child(viewport_base);
+ viewport_base->set_v_size_flags(SIZE_EXPAND_FILL);
+ for(int i=0;i<4;i++) {
+
+ viewports[i] = memnew( SpatialEditorViewport(this,editor,i) );
+ viewports[i]->connect("toggle_maximize_view",this,"_toggle_maximize_view");
+ viewport_base->add_child(viewports[i]);
+ }
+ //vbc->add_child(viewport_base);
+
+
+
+
+ /* SNAP DIALOG */
+
+ snap_dialog = memnew( ConfirmationDialog );
+ snap_dialog->set_title(TTR("Snap Settings"));
+ add_child(snap_dialog);
+
+ VBoxContainer *snap_dialog_vbc = memnew( VBoxContainer );
+ snap_dialog->add_child(snap_dialog_vbc);
+ //snap_dialog->set_child_rect(snap_dialog_vbc);
+
+ snap_translate = memnew( LineEdit );
+ snap_translate->set_text("1");
+ snap_dialog_vbc->add_margin_child(TTR("Translate Snap:"),snap_translate);
+
+ snap_rotate = memnew( LineEdit );
+ snap_rotate->set_text("5");
+ snap_dialog_vbc->add_margin_child(TTR("Rotate Snap (deg.):"),snap_rotate);
+
+ snap_scale = memnew( LineEdit );
+ snap_scale->set_text("5");
+ snap_dialog_vbc->add_margin_child(TTR("Scale Snap (%):"),snap_scale);
+
+ /* SETTINGS DIALOG */
+
+ settings_dialog = memnew( ConfirmationDialog );
+ settings_dialog->set_title(TTR("Viewport Settings"));
+ add_child(settings_dialog);
+ settings_vbc = memnew( VBoxContainer );
+ settings_vbc->set_custom_minimum_size(Size2(200,0));
+ settings_dialog->add_child(settings_vbc);
+ //settings_dialog->set_child_rect(settings_vbc);
+
+
+
+ settings_light_base = memnew( ViewportContainer );
+ settings_light_base->set_custom_minimum_size(Size2(128,128));
+ settings_light_base->connect("gui_input",this,"_default_light_angle_input");
+ settings_vbc->add_margin_child(TTR("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);
+
+ settings_dlight = memnew( DirectionalLight );
+ settings_light_vp->add_child(settings_dlight);
+ settings_sphere = memnew( ImmediateGeometry );
+ settings_sphere->begin(Mesh::PRIMITIVE_TRIANGLES,Ref<Texture>());
+ settings_sphere->set_color(Color(1,1,1));
+ settings_sphere->add_sphere(32,16,1);
+ settings_sphere->end();
+ settings_light_vp->add_child(settings_sphere);
+ settings_camera = memnew( Camera );
+ settings_light_vp->add_child(settings_camera);
+ settings_camera->set_translation(Vector3(0,0,2));
+ settings_camera->set_orthogonal(2.1,0.1,5);
+
+ settings_default_light_rot_x=Math_PI*0.3;
+ settings_default_light_rot_y=Math_PI*0.2;
+
+
+
+ settings_ambient_color = memnew( ColorPickerButton );
+ settings_vbc->add_margin_child(TTR("Ambient Light Color:"),settings_ambient_color);
+ settings_ambient_color->connect("color_changed",this,"_update_ambient_light_color");
+ settings_ambient_color->set_pick_color(Color(0.15,0.15,0.15));
+
+
+ settings_fov = memnew( SpinBox );
+ settings_fov->set_max(179);
+ settings_fov->set_min(1);
+ settings_fov->set_step(0.01);
+ settings_fov->set_value(EDITOR_DEF("editors/3d/default_fov",60.0));
+ settings_vbc->add_margin_child(TTR("Perspective FOV (deg.):"),settings_fov);
+
+ settings_znear = memnew( SpinBox );
+ settings_znear->set_max(10000);
+ settings_znear->set_min(0.1);
+ settings_znear->set_step(0.01);
+ settings_znear->set_value(EDITOR_DEF("editors/3d/default_z_near",0.1));
+ settings_vbc->add_margin_child(TTR("View Z-Near:"),settings_znear);
+
+ settings_zfar = memnew( SpinBox );
+ settings_zfar->set_max(10000);
+ settings_zfar->set_min(0.1);
+ settings_zfar->set_step(0.01);
+ settings_zfar->set_value(EDITOR_DEF("editors/3d/default_z_far",1500));
+ settings_vbc->add_margin_child(TTR("View Z-Far:"),settings_zfar);
+
+ //settings_dialog->get_cancel()->hide();
+ /* XFORM DIALOG */
+
+ xform_dialog = memnew( ConfirmationDialog );
+ xform_dialog->set_title(TTR("Transform Change"));
+ add_child(xform_dialog);
+ Label *l = memnew(Label);
+ l->set_text(TTR("Translate:"));
+ l->set_pos(Point2(5,5));
+ xform_dialog->add_child(l);
+
+ for(int i=0;i<3;i++) {
+
+ xform_translate[i] = memnew( LineEdit );
+ xform_translate[i]->set_pos( Point2(15+i*60,22) );
+ xform_translate[i]->set_size( Size2(50,12 ) );
+ xform_dialog->add_child( xform_translate[i] );
+ }
+
+ l = memnew(Label);
+ l->set_text(TTR("Rotate (deg.):"));
+ l->set_pos(Point2(5,45));
+ xform_dialog->add_child(l);
+
+ for(int i=0;i<3;i++) {
+ xform_rotate[i] = memnew( LineEdit );
+ xform_rotate[i]->set_pos( Point2(15+i*60,62) );
+ xform_rotate[i]->set_size( Size2(50,22 ) );
+ xform_dialog->add_child(xform_rotate[i]);
+ }
+
+ l = memnew(Label);
+ l->set_text(TTR("Scale (ratio):"));
+ l->set_pos(Point2(5,85));
+ xform_dialog->add_child(l);
+
+ for(int i=0;i<3;i++) {
+ xform_scale[i] = memnew( LineEdit );
+ xform_scale[i]->set_pos( Point2(15+i*60,102) );
+ xform_scale[i]->set_size( Size2(50,22 ) );
+ xform_dialog->add_child(xform_scale[i]);
+ }
+
+ l = memnew(Label);
+ l->set_text(TTR("Transform Type"));
+ l->set_pos(Point2(5,125));
+ xform_dialog->add_child(l);
+
+ xform_type = memnew( OptionButton );
+ xform_type->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ xform_type->set_begin( Point2(15,142) );
+ xform_type->set_end( Point2(15,75) );
+ xform_type->add_item(TTR("Pre"));
+ xform_type->add_item(TTR("Post"));
+ xform_dialog->add_child(xform_type);
+
+ xform_dialog->connect("confirmed", this,"_xform_dialog_action");
+
+ scenario_debug=VisualServer::SCENARIO_DEBUG_DISABLED;
+
+ selected=NULL;
+
+ set_process_unhandled_key_input(true);
+ add_to_group("_spatial_editor_group");
+
+ EDITOR_DEF("editors/3d/manipulator_gizmo_size",80);
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT,"editors/3d/manipulator_gizmo_size",PROPERTY_HINT_RANGE,"16,1024,1"));
+ EDITOR_DEF("editors/3d/manipulator_gizmo_opacity",0.2);
+
+ over_gizmo_handle=-1;
+}
+
+SpatialEditor::~SpatialEditor() {
+
+
+}
+
+
+
+
+void SpatialEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+
+ spatial_editor->show();
+ spatial_editor->set_process(true);
+ //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),false);
+ spatial_editor->grab_focus();
+
+ } else {
+
+ spatial_editor->hide();
+ spatial_editor->set_process(false);
+ //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),true);
+
+ }
+
+}
+void SpatialEditorPlugin::edit(Object *p_object) {
+
+ spatial_editor->edit(p_object->cast_to<Spatial>());
+}
+
+bool SpatialEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Spatial");
+}
+
+Dictionary SpatialEditorPlugin::get_state() const {
+ return spatial_editor->get_state();
+}
+
+void SpatialEditorPlugin::set_state(const Dictionary& p_state) {
+
+ spatial_editor->set_state(p_state);
+}
+
+void SpatialEditor::snap_cursor_to_plane(const Plane& p_plane) {
+
+ //cursor.pos=p_plane.project(cursor.pos);
+}
+
+void SpatialEditorPlugin::_bind_methods() {
+
+ ClassDB::bind_method("snap_cursor_to_plane",&SpatialEditorPlugin::snap_cursor_to_plane);
+
+}
+
+void SpatialEditorPlugin::snap_cursor_to_plane(const Plane& p_plane) {
+
+
+ spatial_editor->snap_cursor_to_plane(p_plane);
+}
+
+
+
+
+SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ spatial_editor = memnew( SpatialEditor(p_node) );
+ spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ editor->get_viewport()->add_child(spatial_editor);
+
+ //spatial_editor->set_area_as_parent_rect();
+ spatial_editor->hide();
+ spatial_editor->connect("transform_key_request",editor,"_transform_keyed");
+
+ //spatial_editor->set_process(true);
+}
+
+
+SpatialEditorPlugin::~SpatialEditorPlugin() {
+
+}
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
new file mode 100644
index 0000000000..44ce4a0281
--- /dev/null
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -0,0 +1,574 @@
+/*************************************************************************/
+/* spatial_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SPATIAL_EDITOR_PLUGIN_H
+#define SPATIAL_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/3d/visual_instance.h"
+#include "scene/3d/immediate_geometry.h"
+#include "scene/3d/light.h"
+#include "scene/gui/panel_container.h"
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class Camera;
+class SpatialEditor;
+class SpatialEditorGizmos;
+
+class SpatialEditorGizmo : public SpatialGizmo {
+
+ GDCLASS(SpatialEditorGizmo,SpatialGizmo);
+
+ bool selected;
+public:
+
+ void set_selected(bool p_selected) { selected=p_selected; }
+ bool is_selected() const { return selected; }
+
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+
+ virtual bool intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum);
+ virtual bool intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle=NULL,bool p_sec_first=false);
+ SpatialEditorGizmo();
+};
+
+
+class SpatialEditorViewport : public Control {
+
+ GDCLASS( SpatialEditorViewport, Control );
+friend class SpatialEditor;
+ enum {
+
+ VIEW_TOP,
+ VIEW_BOTTOM,
+ VIEW_LEFT,
+ VIEW_RIGHT,
+ VIEW_FRONT,
+ VIEW_REAR,
+ VIEW_CENTER_TO_ORIGIN,
+ VIEW_CENTER_TO_SELECTION,
+ VIEW_ALIGN_SELECTION_WITH_VIEW,
+ VIEW_PERSPECTIVE,
+ VIEW_ENVIRONMENT,
+ VIEW_ORTHOGONAL,
+ VIEW_AUDIO_LISTENER,
+ VIEW_GIZMOS,
+ };
+public:
+ enum {
+ GIZMO_BASE_LAYER=27,
+ GIZMO_EDIT_LAYER=26,
+ GIZMO_GRID_LAYER=25
+ };
+private:
+ int index;
+ String name;
+ void _menu_option(int p_option);
+ Size2 prev_size;
+
+ EditorNode *editor;
+ EditorSelection *editor_selection;
+ UndoRedo *undo_redo;
+
+ Button *preview_camera;
+
+ MenuButton *view_menu;
+
+ Control *surface;
+ Viewport *viewport;
+ Camera *camera;
+ bool transforming;
+ bool orthogonal;
+ float gizmo_scale;
+
+ struct _RayResult {
+
+ Spatial* item;
+ float depth;
+ int handle;
+ _FORCE_INLINE_ bool operator<(const _RayResult& p_rr) const { return depth<p_rr.depth; }
+ };
+
+ void _update_name();
+ void _compute_edit(const Point2& p_point);
+ void _clear_selected();
+ void _select_clicked(bool p_append,bool p_single);
+ void _select(Spatial *p_node, bool p_append,bool p_single);
+ ObjectID _select_ray(const Point2& p_pos, bool p_append,bool &r_includes_current,int *r_gizmo_handle=NULL,bool p_alt_select=false);
+ void _find_items_at_pos(const Point2& p_pos,bool &r_includes_current,Vector<_RayResult> &results,bool p_alt_select=false);
+ Vector3 _get_ray_pos(const Vector2& p_pos) const;
+ Vector3 _get_ray(const Vector2& p_pos);
+ Point2 _point_to_screen(const Vector3& p_point);
+ Transform _get_camera_transform() const;
+ int get_selected_count() const;
+
+ Vector3 _get_camera_pos() const;
+ Vector3 _get_camera_normal() const;
+ Vector3 _get_screen_to_space(const Vector3& p_vector3);
+
+ void _select_region();
+ bool _gizmo_select(const Vector2& p_screenpos,bool p_hilite_only=false);
+
+ float get_znear() const;
+ float get_zfar() const;
+ float get_fov() const;
+
+ ObjectID clicked;
+ Vector<_RayResult> selection_results;
+ bool clicked_includes_current;
+ bool clicked_wants_append;
+
+ PopupMenu *selection_menu;
+
+ enum NavigationScheme {
+ NAVIGATION_GODOT,
+ NAVIGATION_MAYA,
+ NAVIGATION_MODO,
+ };
+
+ enum NavigationZoomStyle {
+ NAVIGATION_ZOOM_VERTICAL,
+ NAVIGATION_ZOOM_HORIZONTAL
+ };
+
+ enum NavigationMode {
+ NAVIGATION_NONE,
+ NAVIGATION_PAN,
+ NAVIGATION_ZOOM,
+ NAVIGATION_ORBIT
+ };
+ enum TransformMode {
+ TRANSFORM_NONE,
+ TRANSFORM_ROTATE,
+ TRANSFORM_TRANSLATE,
+ TRANSFORM_SCALE
+
+ };
+ enum TransformPlane {
+ TRANSFORM_VIEW,
+ TRANSFORM_X_AXIS,
+ TRANSFORM_Y_AXIS,
+ TRANSFORM_Z_AXIS,
+ };
+
+ struct EditData {
+ TransformMode mode;
+ TransformPlane plane;
+ Transform original;
+ Vector3 click_ray;
+ Vector3 click_ray_pos;
+ Vector3 center;
+ Vector3 orig_gizmo_pos;
+ int edited_gizmo;
+ Point2 mouse_pos;
+ bool snap;
+ Ref<SpatialEditorGizmo> gizmo;
+ int gizmo_handle;
+ Variant gizmo_initial_value;
+ Vector3 gizmo_initial_pos;
+ } _edit;
+
+ struct Cursor {
+
+ Vector3 cursor_pos;
+
+ Vector3 pos;
+ float x_rot,y_rot,distance;
+ bool region_select;
+ Point2 region_begin,region_end;
+
+ Cursor() { x_rot=y_rot=0.5; distance=4; region_select=false; }
+ } cursor;
+
+ RID move_gizmo_instance[3], rotate_gizmo_instance[3];
+
+
+ String last_message;
+ String message;
+ float message_time;
+
+ void set_message(String p_message,float p_time=5);
+
+ //
+ void _update_camera();
+ void _draw();
+
+ void _smouseenter();
+ void _sinput(const InputEvent& p_ie);
+ SpatialEditor *spatial_editor;
+
+ Camera* previewing;
+ Camera* preview;
+
+ void _preview_exited_scene();
+ void _toggle_camera_preview(bool);
+ void _init_gizmo_instance(int p_idx);
+ void _finish_gizmo_instances();
+ void _selection_result_pressed(int);
+ void _selection_menu_hide();
+ void _list_select(InputEventMouseButton b);
+
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void update_transform_gizmo_view();
+
+ void set_can_preview(Camera* p_preview);
+ void set_state(const Dictionary& p_state);
+ Dictionary get_state() const;
+ void reset();
+
+ void focus_selection();
+
+ Viewport *get_viewport_node() { return viewport; }
+
+
+ SpatialEditorViewport(SpatialEditor *p_spatial_editor,EditorNode *p_editor,int p_index);
+};
+
+
+
+class SpatialEditorSelectedItem : public Object {
+
+ GDCLASS(SpatialEditorSelectedItem,Object);
+
+public:
+
+ Rect3 aabb;
+ Transform original; // original location when moving
+ Transform last_xform; // last transform
+ Spatial *sp;
+ RID sbox_instance;
+
+ SpatialEditorSelectedItem() { sp=NULL; }
+ ~SpatialEditorSelectedItem();
+};
+
+class SpatialEditor : public VBoxContainer {
+
+ GDCLASS(SpatialEditor, VBoxContainer );
+public:
+
+ enum ToolMode {
+
+ TOOL_MODE_SELECT,
+ TOOL_MODE_MOVE,
+ TOOL_MODE_ROTATE,
+ TOOL_MODE_SCALE,
+ TOOL_MODE_LIST_SELECT,
+ TOOL_MAX
+
+ };
+
+
+private:
+ EditorNode *editor;
+ EditorSelection *editor_selection;
+
+
+
+ Control *viewport_base;
+ SpatialEditorViewport *viewports[4];
+ VSplitContainer *shader_split;
+ HSplitContainer *palette_split;
+
+ /////
+
+ ToolMode tool_mode;
+ bool orthogonal;
+
+
+ VisualServer::ScenarioDebugMode scenario_debug;
+
+ RID light;
+ RID light_instance;
+ Transform light_transform;
+
+
+ RID origin;
+ RID origin_instance;
+ RID grid[3];
+ RID grid_instance[3];
+ bool grid_visible[3]; //currently visible
+ float last_grid_snap;
+ bool grid_enable[3]; //should be always visible if true
+ bool grid_enabled;
+
+ Ref<Mesh> move_gizmo[3], rotate_gizmo[3];
+ Ref<FixedSpatialMaterial> gizmo_color[3];
+ Ref<FixedSpatialMaterial> gizmo_hl;
+
+
+ int over_gizmo_handle;
+
+
+
+ Ref<Mesh> selection_box;
+ RID indicators;
+ RID indicators_instance;
+ RID cursor_mesh;
+ RID cursor_instance;
+ Ref<FixedSpatialMaterial> indicator_mat;
+ Ref<FixedSpatialMaterial> cursor_material;
+
+/*
+ struct Selected {
+ AABB aabb;
+ Transform original; // original location when moving
+ Transform last_xform; // last transform
+ Spatial *sp;
+ RID poly_instance;
+ };
+
+ Map<uint32_t,Selected> selected;
+*/
+ struct Gizmo {
+
+ bool visible;
+ float scale;
+ Transform transform;
+ } gizmo;
+
+
+
+
+ enum MenuOption {
+
+ MENU_TOOL_SELECT,
+ 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,
+ MENU_TRANSFORM_DIALOG,
+ MENU_VIEW_USE_1_VIEWPORT,
+ MENU_VIEW_USE_2_VIEWPORTS,
+ MENU_VIEW_USE_2_VIEWPORTS_ALT,
+ MENU_VIEW_USE_3_VIEWPORTS,
+ MENU_VIEW_USE_3_VIEWPORTS_ALT,
+ MENU_VIEW_USE_4_VIEWPORTS,
+ MENU_VIEW_USE_DEFAULT_LIGHT,
+ MENU_VIEW_USE_DEFAULT_SRGB,
+ MENU_VIEW_DISPLAY_NORMAL,
+ MENU_VIEW_DISPLAY_WIREFRAME,
+ MENU_VIEW_DISPLAY_OVERDRAW,
+ MENU_VIEW_DISPLAY_SHADELESS,
+ MENU_VIEW_ORIGIN,
+ MENU_VIEW_GRID,
+ MENU_VIEW_CAMERA_SETTINGS,
+
+ };
+
+
+ Button *tool_button[TOOL_MAX];
+ Button *instance_button;
+
+
+ MenuButton* transform_menu;
+ MenuButton* view_menu;
+
+ ConfirmationDialog *snap_dialog;
+ ConfirmationDialog *xform_dialog;
+ ConfirmationDialog *settings_dialog;
+
+ bool snap_enabled;
+ LineEdit *snap_translate;
+ LineEdit *snap_rotate;
+ LineEdit *snap_scale;
+ PanelContainer* menu_panel;
+
+ LineEdit *xform_translate[3];
+ LineEdit *xform_rotate[3];
+ LineEdit *xform_scale[3];
+ OptionButton *xform_type;
+
+ VBoxContainer *settings_vbc;
+ SpinBox *settings_fov;
+ SpinBox *settings_znear;
+ SpinBox *settings_zfar;
+ DirectionalLight *settings_dlight;
+ ImmediateGeometry *settings_sphere;
+ Camera *settings_camera;
+ float settings_default_light_rot_x;
+ float settings_default_light_rot_y;
+
+ ViewportContainer *settings_light_base;
+ Viewport *settings_light_vp;
+ ColorPickerButton *settings_ambient_color;
+ Image settings_light_dir_image;
+
+
+ void _xform_dialog_action();
+ void _menu_item_pressed(int p_option);
+
+ HBoxContainer *hbc_menu;
+
+
+
+//
+//
+ void _generate_selection_box();
+ UndoRedo *undo_redo;
+
+ void _instance_scene();
+ void _init_indicators();
+ void _finish_indicators();
+
+ void _toggle_maximize_view(Object* p_viewport);
+
+ Node *custom_camera;
+
+ Object *_get_editor_data(Object *p_what);
+
+ Ref<Environment> viewport_environment;
+
+ Spatial *selected;
+
+ void _request_gizmo(Object* p_obj);
+
+ static SpatialEditor *singleton;
+
+ void _node_removed(Node* p_node);
+ SpatialEditorGizmos *gizmos;
+ SpatialEditor();
+
+ void _update_ambient_light_color(const Color& p_color);
+ void _update_default_light_angle();
+ void _default_light_angle_input(const InputEvent& p_event);
+
+protected:
+
+
+
+
+ void _notification(int p_what);
+ //void _gui_input(InputEvent p_event);
+ void _unhandled_key_input(InputEvent p_event);
+
+ static void _bind_methods();
+public:
+
+
+ static SpatialEditor *get_singleton() { return singleton; }
+ void snap_cursor_to_plane(const Plane& p_plane);
+
+ float get_znear() const { return settings_znear->get_value(); }
+ float get_zfar() const { return settings_zfar->get_value(); }
+ float get_fov() const { return settings_fov->get_value(); }
+
+ Transform get_gizmo_transform() const { return gizmo.transform; }
+ bool is_gizmo_visible() const { return gizmo.visible; }
+
+ ToolMode get_tool_mode() const { return tool_mode; }
+ bool is_snap_enabled() const { return snap_enabled; }
+ float get_translate_snap() const { return snap_translate->get_text().to_double(); }
+ float get_rotate_snap() const { return snap_rotate->get_text().to_double(); }
+ float get_scale_snap() const { return snap_scale->get_text().to_double(); }
+
+ Ref<Mesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
+ Ref<Mesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }
+
+ void update_transform_gizmo();
+
+ void select_gizmo_hilight_axis(int p_axis);
+ void set_custom_camera(Node *p_camera) { custom_camera=p_camera; }
+
+ void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
+ Dictionary get_state() const;
+ void set_state(const Dictionary& p_state);
+
+ Ref<Environment> get_viewport_environment() { return viewport_environment; }
+
+ UndoRedo *get_undo_redo() { return undo_redo; }
+
+ void add_control_to_menu_panel(Control *p_control);
+
+ VSplitContainer *get_shader_split();
+ HSplitContainer *get_palette_split();
+
+ Spatial *get_selected() { return selected; }
+
+ int get_over_gizmo_handle() const { return over_gizmo_handle; }
+ void set_over_gizmo_handle(int idx) { over_gizmo_handle=idx; }
+
+ void set_can_preview(Camera* p_preview);
+
+ SpatialEditorViewport *get_editor_viewport(int p_idx) {
+ ERR_FAIL_INDEX_V(p_idx,4,NULL);
+ return viewports[p_idx];
+ }
+
+ Camera *get_camera() { return NULL; }
+ void edit(Spatial *p_spatial);
+ void clear();
+ SpatialEditor(EditorNode *p_editor);
+ ~SpatialEditor();
+};
+
+class SpatialEditorPlugin : public EditorPlugin {
+
+ GDCLASS( SpatialEditorPlugin, EditorPlugin );
+
+ SpatialEditor *spatial_editor;
+ EditorNode *editor;
+protected:
+ static void _bind_methods();
+public:
+
+ void snap_cursor_to_plane(const Plane& p_plane);
+
+ SpatialEditor *get_spatial_editor() { return spatial_editor; }
+ virtual String get_name() const { return "3D"; }
+ bool has_main_screen() const { return true; }
+ virtual void make_visible(bool p_visible);
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+
+ virtual Dictionary get_state() const;
+ virtual void set_state(const Dictionary& p_state);
+ virtual void clear() { spatial_editor->clear(); }
+
+
+ SpatialEditorPlugin(EditorNode *p_node);
+ ~SpatialEditorPlugin();
+
+};
+
+#endif
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
new file mode 100644
index 0000000000..44d6d3c6e1
--- /dev/null
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -0,0 +1,969 @@
+/*************************************************************************/
+/* sprite_frames_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "sprite_frames_editor_plugin.h"
+
+#include "io/resource_loader.h"
+#include "global_config.h"
+#include "editor/editor_settings.h"
+#include "scene/3d/sprite_3d.h"
+
+
+
+void SpriteFramesEditor::_gui_input(InputEvent p_event) {
+
+
+}
+
+void SpriteFramesEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+ }
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ load->set_icon( get_icon("Folder","EditorIcons") );
+ _delete->set_icon( get_icon("Del","EditorIcons") );
+ new_anim->set_icon( get_icon("New","EditorIcons") );
+ remove_anim->set_icon( get_icon("Del","EditorIcons") );
+
+ }
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //NodePath("/root")->connect("node_removed", this,"_node_removed",Vector<Variant>(),true);
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ }
+}
+
+void SpriteFramesEditor::_file_load_request(const PoolVector<String>& p_path,int p_at_pos) {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ List< Ref<Texture> > resources;
+
+ for(int i=0;i<p_path.size();i++) {
+
+ Ref<Texture> resource;
+ resource = ResourceLoader::load(p_path[i]);
+
+ if (resource.is_null()) {
+ dialog->set_text(TTR("ERROR: Couldn't load frame resource!"));
+ dialog->set_title(TTR("Error!"));
+ //dialog->get_cancel()->set_text("Close");
+ dialog->get_ok()->set_text(TTR("Close"));
+ dialog->popup_centered_minsize();
+ return; ///beh should show an error i guess
+ }
+
+ resources.push_back(resource);
+ }
+
+
+ if (resources.empty()) {
+ //print_line("added frames!");
+ return;
+ }
+
+ undo_redo->create_action(TTR("Add Frame"));
+ int fc=frames->get_frame_count(edited_anim);
+
+ int count=0;
+
+ for(List< Ref<Texture> >::Element *E=resources.front();E;E=E->next() ) {
+
+ undo_redo->add_do_method(frames,"add_frame",edited_anim,E->get(),p_at_pos==-1?-1:p_at_pos+count);
+ undo_redo->add_undo_method(frames,"remove_frame",edited_anim,p_at_pos==-1?fc:p_at_pos);
+ count++;
+
+ }
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+
+ undo_redo->commit_action();
+ //print_line("added frames!");
+}
+
+void SpriteFramesEditor::_load_pressed() {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+ loading_scene=false;
+
+ file->clear_filters();
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Texture",&extensions);
+ for(int i=0;i<extensions.size();i++)
+ file->add_filter("*."+extensions[i]);
+
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+
+ file->popup_centered_ratio();
+
+}
+
+
+void SpriteFramesEditor::_item_edited() {
+
+#if 0
+ if (!tree->get_selected())
+ return;
+
+ TreeItem *s = tree->get_selected();
+
+ if (tree->get_selected_column()==0) {
+ // renamed
+ String old_name=s->get_metadata(0);
+ String new_name=s->get_text(0);
+ if (old_name==new_name)
+ return;
+
+ if (new_name=="" || new_name.find("\\")!=-1 || new_name.find("/")!=-1 || frames->has_resource(new_name)) {
+
+ s->set_text(0,old_name);
+ return;
+ }
+
+ RES samp = frames->get_resource(old_name);
+ undo_redo->create_action("Rename Resource");
+ undo_redo->add_do_method(frames,"remove_resource",old_name);
+ undo_redo->add_do_method(frames,"add_resource",new_name,samp);
+ undo_redo->add_undo_method(frames,"remove_resource",new_name);
+ undo_redo->add_undo_method(frames,"add_resource",old_name,samp);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+ }
+#endif
+
+}
+
+void SpriteFramesEditor::_delete_confirm_pressed() {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ if (tree->get_current()<0)
+ return;
+
+ sel-=1;
+ if (sel<0 && frames->get_frame_count(edited_anim))
+ sel=0;
+
+ int to_remove = tree->get_current();
+ sel=to_remove;
+ Ref<Texture> r = frames->get_frame(edited_anim,to_remove);
+ undo_redo->create_action(TTR("Delete Resource"));
+ undo_redo->add_do_method(frames,"remove_frame",edited_anim,to_remove);
+ undo_redo->add_undo_method(frames,"add_frame",edited_anim,r,to_remove);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+}
+
+
+void SpriteFramesEditor::_paste_pressed() {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ Ref<Texture> r=EditorSettings::get_singleton()->get_resource_clipboard();
+ if (!r.is_valid()) {
+ dialog->set_text(TTR("Resource clipboard is empty or not a texture!"));
+ dialog->set_title(TTR("Error!"));
+ //dialog->get_cancel()->set_text("Close");
+ dialog->get_ok()->set_text(TTR("Close"));
+ dialog->popup_centered_minsize();
+ return; ///beh should show an error i guess
+ }
+
+
+ undo_redo->create_action(TTR("Paste Frame"));
+ undo_redo->add_do_method(frames,"add_frame",edited_anim,r);
+ undo_redo->add_undo_method(frames,"remove_frame",edited_anim,frames->get_frame_count(edited_anim));
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+}
+
+void SpriteFramesEditor::_empty_pressed() {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ int from=-1;
+
+ if (tree->get_current()>=0) {
+
+ from = tree->get_current();
+ sel=from;
+
+ } else {
+ from=frames->get_frame_count(edited_anim);
+ }
+
+
+
+ Ref<Texture> r;
+
+ undo_redo->create_action(TTR("Add Empty"));
+ undo_redo->add_do_method(frames,"add_frame",edited_anim,r,from);
+ undo_redo->add_undo_method(frames,"remove_frame",edited_anim,from);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+}
+
+void SpriteFramesEditor::_empty2_pressed() {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ int from=-1;
+
+ if (tree->get_current()>=0) {
+
+ from = tree->get_current();
+ sel=from;
+
+ } else {
+ from=frames->get_frame_count(edited_anim);
+ }
+
+
+
+ Ref<Texture> r;
+
+ undo_redo->create_action(TTR("Add Empty"));
+ undo_redo->add_do_method(frames,"add_frame",edited_anim,r,from+1);
+ undo_redo->add_undo_method(frames,"remove_frame",edited_anim,from+1);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+}
+
+void SpriteFramesEditor::_up_pressed() {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ if (tree->get_current()<0)
+ return;
+
+ int to_move = tree->get_current();
+ if (to_move<1)
+ return;
+
+ sel=to_move;
+ sel-=1;
+
+ Ref<Texture> r = frames->get_frame(edited_anim,to_move);
+ undo_redo->create_action(TTR("Delete Resource"));
+ undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move-1));
+ undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move-1,frames->get_frame(edited_anim,to_move));
+ undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move));
+ undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move-1,frames->get_frame(edited_anim,to_move-1));
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+}
+
+void SpriteFramesEditor::_down_pressed() {
+
+ ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
+ if (tree->get_current()<0)
+ return;
+
+ int to_move = tree->get_current();
+ if (to_move<0 || to_move>=frames->get_frame_count(edited_anim)-1)
+ return;
+
+ sel=to_move;
+ sel+=1;
+
+ Ref<Texture> r = frames->get_frame(edited_anim,to_move);
+ undo_redo->create_action(TTR("Delete Resource"));
+ undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move+1));
+ undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move+1,frames->get_frame(edited_anim,to_move));
+ undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move));
+ undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move+1,frames->get_frame(edited_anim,to_move+1));
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+
+
+}
+
+
+void SpriteFramesEditor::_delete_pressed() {
+
+
+ if (tree->get_current()<0)
+ return;
+
+ _delete_confirm_pressed(); //it has undo.. why bother with a dialog..
+ /*
+ dialog->set_title("Confirm...");
+ dialog->set_text("Remove Resource '"+tree->get_selected()->get_text(0)+"' ?");
+ //dialog->get_cancel()->set_text("Cancel");
+ //dialog->get_ok()->show();
+ dialog->get_ok()->set_text("Remove");
+ dialog->popup_centered(Size2(300,60));*/
+
+}
+
+
+void SpriteFramesEditor::_animation_select() {
+
+ if (updating)
+ return;
+
+ TreeItem *selected = animations->get_selected();
+ ERR_FAIL_COND(!selected);
+ edited_anim=selected->get_text(0);
+ _update_library(true);
+
+}
+
+
+static void _find_anim_sprites(Node* p_node,List<Node*> *r_nodes,Ref<SpriteFrames> p_sfames) {
+
+ Node *edited = EditorNode::get_singleton()->get_edited_scene();
+ if (!edited)
+ return;
+ if (p_node!=edited && p_node->get_owner()!=edited)
+ return;
+
+ {
+ AnimatedSprite *as = p_node->cast_to<AnimatedSprite>();
+ if (as && as->get_sprite_frames()==p_sfames) {
+ r_nodes->push_back(p_node);
+ }
+ }
+
+ {
+ AnimatedSprite3D *as = p_node->cast_to<AnimatedSprite3D>();
+ if (as && as->get_sprite_frames()==p_sfames) {
+ r_nodes->push_back(p_node);
+ }
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+ _find_anim_sprites(p_node->get_child(i),r_nodes,p_sfames);
+ }
+
+}
+
+void SpriteFramesEditor::_animation_name_edited(){
+
+ if (updating)
+ return;
+
+ if (!frames->has_animation(edited_anim))
+ return;
+
+ TreeItem *edited = animations->get_edited();
+ if (!edited)
+ return;
+
+ String new_name = edited->get_text(0);
+
+ if (new_name==String(edited_anim))
+ return;
+
+ new_name=new_name.replace("/","_").replace(","," ");
+
+ String name=new_name;
+ int counter=0;
+ while(frames->has_animation(name)) {
+ counter++;
+ name=new_name+" "+itos(counter);
+ }
+
+ List<Node*> nodes;
+ _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(),&nodes,Ref<SpriteFrames>(frames));
+
+ undo_redo->create_action(TTR("Rename Animation"));
+ undo_redo->add_do_method(frames,"rename_animation",edited_anim,name);
+ undo_redo->add_undo_method(frames,"rename_animation",name,edited_anim);
+
+ for(List<Node*>::Element *E=nodes.front();E;E=E->next()) {
+
+ String current = E->get()->call("get_animation");
+ if (current!=edited_anim)
+ continue;
+
+ undo_redo->add_do_method(E->get(),"set_animation",name);
+ undo_redo->add_undo_method(E->get(),"set_animation",edited_anim);
+
+ }
+
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+
+ edited_anim=new_name;
+
+ undo_redo->commit_action();
+
+
+
+}
+void SpriteFramesEditor::_animation_add(){
+
+
+ String new_name = "New Anim";
+
+ String name=new_name;
+ int counter=0;
+ while(frames->has_animation(name)) {
+ counter++;
+ name=new_name+" "+itos(counter);
+ }
+
+ List<Node*> nodes;
+ _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(),&nodes,Ref<SpriteFrames>(frames));
+
+
+ undo_redo->create_action(TTR("Add Animation"));
+ undo_redo->add_do_method(frames,"add_animation",name);
+ undo_redo->add_undo_method(frames,"remove_animation",name);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+
+
+ for(List<Node*>::Element *E=nodes.front();E;E=E->next()) {
+
+ String current = E->get()->call("get_animation");
+ if (frames->has_animation(current))
+ continue;
+
+ undo_redo->add_do_method(E->get(),"set_animation",name);
+ undo_redo->add_undo_method(E->get(),"set_animation",current);
+
+ }
+
+ edited_anim=new_name;
+
+ undo_redo->commit_action();
+
+}
+void SpriteFramesEditor::_animation_remove(){
+
+ //fuck everything
+ if (updating)
+ return;
+
+ if (!frames->has_animation(edited_anim))
+ return;
+
+
+ undo_redo->create_action(TTR("Remove Animation"));
+ undo_redo->add_do_method(frames,"remove_animation",edited_anim);
+ undo_redo->add_undo_method(frames,"add_animation",edited_anim);
+ undo_redo->add_undo_method(frames,"set_animation_speed",edited_anim,frames->get_animation_speed(edited_anim));
+ undo_redo->add_undo_method(frames,"set_animation_loop",edited_anim,frames->get_animation_loop(edited_anim));
+ int fc = frames->get_frame_count(edited_anim);
+ for(int i=0;i<fc;i++) {
+ Ref<Texture> frame = frames->get_frame(edited_anim,i);
+ undo_redo->add_undo_method(frames,"add_frame",edited_anim,frame);
+ }
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+
+ undo_redo->commit_action();
+
+}
+
+
+void SpriteFramesEditor::_animation_loop_changed() {
+
+ if (updating)
+ return;
+
+ undo_redo->create_action(TTR("Change Animation Loop"));
+ undo_redo->add_do_method(frames,"set_animation_loop",edited_anim,anim_loop->is_pressed());
+ undo_redo->add_undo_method(frames,"set_animation_loop",edited_anim,frames->get_animation_loop(edited_anim));
+ undo_redo->add_do_method(this,"_update_library",true);
+ undo_redo->add_undo_method(this,"_update_library",true);
+ undo_redo->commit_action();
+
+}
+
+void SpriteFramesEditor::_animation_fps_changed(double p_value) {
+
+ if (updating)
+ return;
+
+ undo_redo->create_action(TTR("Change Animation FPS"),UndoRedo::MERGE_ENDS);
+ undo_redo->add_do_method(frames,"set_animation_speed",edited_anim,p_value);
+ undo_redo->add_undo_method(frames,"set_animation_speed",edited_anim,frames->get_animation_speed(edited_anim));
+ undo_redo->add_do_method(this,"_update_library",true);
+ undo_redo->add_undo_method(this,"_update_library",true);
+
+ undo_redo->commit_action();
+
+}
+
+void SpriteFramesEditor::_update_library(bool p_skip_selector) {
+
+ updating=true;
+
+ if (!p_skip_selector) {
+ animations->clear();
+
+ TreeItem *anim_root=animations->create_item();
+
+ List<StringName> anim_names;
+
+ anim_names.sort_custom<StringName::AlphCompare>();
+
+ frames->get_animation_list(&anim_names);
+
+ anim_names.sort_custom<StringName::AlphCompare>();
+
+ for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
+
+ String name = E->get();
+
+ TreeItem *it = animations->create_item(anim_root);
+
+ it->set_metadata(0,name);
+
+ it->set_text(0,name);
+ it->set_editable(0,true);
+
+ if (E->get()==edited_anim) {
+ it->select(0);
+ }
+ }
+ }
+
+
+ tree->clear();
+
+ if (!frames->has_animation(edited_anim)) {
+ updating=false;
+ return;
+ }
+
+
+ if (sel>=frames->get_frame_count(edited_anim))
+ sel=frames->get_frame_count(edited_anim)-1;
+ else if (sel<0 && frames->get_frame_count(edited_anim))
+ sel=0;
+
+ for(int i=0;i<frames->get_frame_count(edited_anim);i++) {
+
+
+ String name;
+ Ref<Texture> icon;
+
+
+ if (frames->get_frame(edited_anim,i).is_null()) {
+
+ name=itos(i)+": "+TTR("(empty)");
+
+ } else {
+ name=itos(i)+": "+frames->get_frame(edited_anim,i)->get_name();
+ icon=frames->get_frame(edited_anim,i);
+ }
+
+ tree->add_item(name,icon);
+ if (frames->get_frame(edited_anim,i).is_valid())
+ tree->set_item_tooltip(tree->get_item_count()-1,frames->get_frame(edited_anim,i)->get_path());
+ if (sel==i)
+ tree->select(tree->get_item_count()-1);
+ }
+
+ anim_speed->set_value(frames->get_animation_speed(edited_anim));
+ anim_loop->set_pressed(frames->get_animation_loop(edited_anim));
+
+ updating=false;
+ //player->add_resource("default",resource);
+}
+
+
+
+void SpriteFramesEditor::edit(SpriteFrames* p_frames) {
+
+ if (frames==p_frames)
+ return;
+
+ frames=p_frames;
+
+
+ if (p_frames) {
+
+ if (!p_frames->has_animation(edited_anim)) {
+
+ List<StringName> anim_names;
+ frames->get_animation_list(&anim_names);
+ anim_names.sort_custom<StringName::AlphCompare>();
+ if (anim_names.size()) {
+ edited_anim=anim_names.front()->get();
+ } else {
+ edited_anim=StringName();
+ }
+
+ }
+
+ _update_library();
+ } else {
+
+ hide();
+ //set_fixed_process(false);
+ }
+
+}
+
+
+Variant SpriteFramesEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ if (!frames->has_animation(edited_anim))
+ return false;
+
+ int idx = tree->get_item_at_pos(p_point,true);
+
+ if (idx<0 || idx>=frames->get_frame_count(edited_anim))
+ return Variant();
+
+ RES frame = frames->get_frame(edited_anim,idx);
+
+ if (frame.is_null())
+ return Variant();
+
+ return EditorNode::get_singleton()->drag_resource(frame,p_from);
+
+
+}
+
+bool SpriteFramesEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ Dictionary d = p_data;
+
+ if (!d.has("type"))
+ return false;
+
+ if (d.has("from") && (Object*)(d["from"])==tree)
+ return false;
+
+ if (String(d["type"])=="resource" && d.has("resource")) {
+ RES r=d["resource"];
+
+ Ref<Texture> texture = r;
+
+ if (texture.is_valid()) {
+
+ return true;
+ }
+ }
+
+
+ if (String(d["type"])=="files") {
+
+ Vector<String> files = d["files"];
+
+ if (files.size()==0)
+ return false;
+
+ for(int i=0;i<files.size();i++) {
+ String file = files[0];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+
+ if (!ClassDB::is_parent_class(ftype,"Texture")) {
+ return false;
+ }
+
+ }
+
+ return true;
+
+ }
+ return false;
+}
+
+void SpriteFramesEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ if (!can_drop_data_fw(p_point,p_data,p_from))
+ return;
+
+ Dictionary d = p_data;
+
+ if (!d.has("type"))
+ return;
+
+ int at_pos = tree->get_item_at_pos(p_point,true);
+
+ if (String(d["type"])=="resource" && d.has("resource")) {
+ RES r=d["resource"];
+
+ Ref<Texture> texture = r;
+
+ if (texture.is_valid()) {
+
+ undo_redo->create_action(TTR("Add Frame"));
+ undo_redo->add_do_method(frames,"add_frame",edited_anim,texture,at_pos==-1?-1:at_pos);
+ undo_redo->add_undo_method(frames,"remove_frame",edited_anim,at_pos==-1?frames->get_frame_count(edited_anim):at_pos);
+ undo_redo->add_do_method(this,"_update_library");
+ undo_redo->add_undo_method(this,"_update_library");
+ undo_redo->commit_action();
+
+ }
+ }
+
+
+ if (String(d["type"])=="files") {
+
+ PoolVector<String> files = d["files"];
+
+ _file_load_request(files,at_pos);
+ }
+
+}
+
+
+void SpriteFramesEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&SpriteFramesEditor::_gui_input);
+ ClassDB::bind_method(D_METHOD("_load_pressed"),&SpriteFramesEditor::_load_pressed);
+ ClassDB::bind_method(D_METHOD("_empty_pressed"),&SpriteFramesEditor::_empty_pressed);
+ ClassDB::bind_method(D_METHOD("_empty2_pressed"),&SpriteFramesEditor::_empty2_pressed);
+ ClassDB::bind_method(D_METHOD("_item_edited"),&SpriteFramesEditor::_item_edited);
+ ClassDB::bind_method(D_METHOD("_delete_pressed"),&SpriteFramesEditor::_delete_pressed);
+ ClassDB::bind_method(D_METHOD("_paste_pressed"),&SpriteFramesEditor::_paste_pressed);
+ ClassDB::bind_method(D_METHOD("_delete_confirm_pressed"),&SpriteFramesEditor::_delete_confirm_pressed);
+ ClassDB::bind_method(D_METHOD("_file_load_request","files","atpos"),&SpriteFramesEditor::_file_load_request,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("_update_library","skipsel"),&SpriteFramesEditor::_update_library,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("_up_pressed"),&SpriteFramesEditor::_up_pressed);
+ ClassDB::bind_method(D_METHOD("_down_pressed"),&SpriteFramesEditor::_down_pressed);
+ ClassDB::bind_method(D_METHOD("_animation_select"),&SpriteFramesEditor::_animation_select);
+ ClassDB::bind_method(D_METHOD("_animation_name_edited"),&SpriteFramesEditor::_animation_name_edited);
+ ClassDB::bind_method(D_METHOD("_animation_add"),&SpriteFramesEditor::_animation_add);
+ ClassDB::bind_method(D_METHOD("_animation_remove"),&SpriteFramesEditor::_animation_remove);
+ ClassDB::bind_method(D_METHOD("_animation_loop_changed"),&SpriteFramesEditor::_animation_loop_changed);
+ ClassDB::bind_method(D_METHOD("_animation_fps_changed"),&SpriteFramesEditor::_animation_fps_changed);
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpriteFramesEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpriteFramesEditor::drop_data_fw);
+
+
+}
+
+
+SpriteFramesEditor::SpriteFramesEditor() {
+
+ //add_style_override("panel", get_stylebox("panel","Panel"));
+
+ split = memnew( HSplitContainer );
+ add_child(split);
+
+ VBoxContainer *vbc_animlist = memnew( VBoxContainer );
+ split->add_child(vbc_animlist);
+ vbc_animlist->set_custom_minimum_size(Size2(150,0));
+ //vbc_animlist->set_v_size_flags(SIZE_EXPAND_FILL);
+
+
+ VBoxContainer *sub_vb = memnew( VBoxContainer );
+ vbc_animlist->add_margin_child(TTR("Animations"),sub_vb,true);
+ sub_vb->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *hbc_animlist = memnew( HBoxContainer );
+ sub_vb->add_child(hbc_animlist);
+
+ new_anim = memnew( Button );
+ hbc_animlist->add_child(new_anim);
+ new_anim->connect("pressed",this,"_animation_add");
+
+
+ hbc_animlist->add_spacer();
+
+ remove_anim = memnew( Button );
+ hbc_animlist->add_child(remove_anim);
+ remove_anim->connect("pressed",this,"_animation_remove");
+
+ animations = memnew( Tree );
+ sub_vb->add_child(animations);
+ animations->set_v_size_flags(SIZE_EXPAND_FILL);
+ animations->set_hide_root(true);
+ animations->connect("cell_selected",this,"_animation_select");
+ animations->connect("item_edited",this,"_animation_name_edited");
+ animations->set_single_select_cell_editing_only_when_already_selected(true);
+
+
+ anim_speed = memnew( SpinBox);
+ vbc_animlist->add_margin_child(TTR("Speed (FPS):"),anim_speed);
+ anim_speed->set_min(0);
+ anim_speed->set_max(100);
+ anim_speed->set_step(0.01);
+ anim_speed->connect("value_changed",this,"_animation_fps_changed");
+
+ anim_loop = memnew( CheckButton );
+ anim_loop->set_text(TTR("Loop"));
+ vbc_animlist->add_child(anim_loop);
+ anim_loop->connect("pressed",this,"_animation_loop_changed");
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ split->add_child(vbc);
+ vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ sub_vb = memnew( VBoxContainer );
+ vbc->add_margin_child(TTR("Animation Frames"),sub_vb,true);
+
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ sub_vb->add_child(hbc);
+
+ //animations = memnew( ItemList );
+
+
+ load = memnew( Button );
+ load->set_tooltip(TTR("Load Resource"));
+ hbc->add_child(load);
+
+ paste = memnew( Button );
+ paste->set_text(TTR("Paste"));
+ hbc->add_child(paste);
+
+ empty = memnew( Button );
+ empty->set_text(TTR("Insert Empty (Before)"));
+ hbc->add_child(empty);
+
+ empty2 = memnew( Button );
+ empty2->set_text(TTR("Insert Empty (After)"));
+ hbc->add_child(empty2);
+
+ move_up = memnew( Button );
+ move_up->set_text(TTR("Up"));
+ hbc->add_child(move_up);
+
+ move_down = memnew( Button );
+ move_down->set_text(TTR("Down"));
+ hbc->add_child(move_down);
+
+ _delete = memnew( Button );
+ hbc->add_child(_delete);
+
+ file = memnew( EditorFileDialog );
+ add_child(file);
+
+
+ tree = memnew( ItemList );
+ tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ tree->set_icon_mode(ItemList::ICON_MODE_TOP);
+
+ int thumbnail_size = 96;
+ tree->set_max_columns(0);
+ tree->set_icon_mode(ItemList::ICON_MODE_TOP);
+ tree->set_fixed_column_width(thumbnail_size*3/2);
+ tree->set_max_text_lines(2);
+ tree->set_fixed_icon_size(Size2(thumbnail_size,thumbnail_size));
+ //tree->set_min_icon_size(Size2(thumbnail_size,thumbnail_size));
+ tree->set_drag_forwarding(this);
+
+
+
+ sub_vb->add_child(tree);
+
+ dialog = memnew( AcceptDialog );
+ add_child( dialog );
+
+ load->connect("pressed", this,"_load_pressed");
+ _delete->connect("pressed", this,"_delete_pressed");
+ paste->connect("pressed", this,"_paste_pressed");
+ empty->connect("pressed", this,"_empty_pressed");
+ empty2->connect("pressed", this,"_empty2_pressed");
+ move_up->connect("pressed", this,"_up_pressed");
+ move_down->connect("pressed", this,"_down_pressed");
+ file->connect("files_selected", this,"_file_load_request");
+ //dialog->connect("confirmed", this,"_delete_confirm_pressed");
+ //tree->connect("item_selected", this,"_item_edited");
+ loading_scene=false;
+ sel=-1;
+
+ updating=false;
+
+ edited_anim="default";
+
+}
+
+
+void SpriteFramesEditorPlugin::edit(Object *p_object) {
+
+ frames_editor->set_undo_redo(&get_undo_redo());
+ SpriteFrames * s = p_object->cast_to<SpriteFrames>();
+ if (!s)
+ return;
+
+ frames_editor->edit(s);
+}
+
+bool SpriteFramesEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("SpriteFrames");
+}
+
+void SpriteFramesEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ button->show();
+ editor->make_bottom_panel_item_visible(frames_editor);
+ //frames_editor->set_process(true);
+ } else {
+
+ button->hide();
+ if (frames_editor->is_visible_in_tree())
+ editor->hide_bottom_panel();
+
+ //frames_editor->set_process(false);
+ }
+
+}
+
+SpriteFramesEditorPlugin::SpriteFramesEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ frames_editor = memnew( SpriteFramesEditor );
+ frames_editor->set_custom_minimum_size(Size2(0,300));
+ button=editor->add_bottom_panel_item("SpriteFrames",frames_editor);
+ button->hide();
+
+
+
+}
+
+
+SpriteFramesEditorPlugin::~SpriteFramesEditorPlugin()
+{
+}
+
+
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
new file mode 100644
index 0000000000..11f545b443
--- /dev/null
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* sprite_frames_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SPRITE_FRAMES_EDITOR_PLUGIN_H
+#define SPRITE_FRAMES_EDITOR_PLUGIN_H
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/gui/tree.h"
+#include "scene/2d/animated_sprite.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/split_container.h"
+
+
+class SpriteFramesEditor : public PanelContainer {
+
+ GDCLASS(SpriteFramesEditor, PanelContainer );
+
+ Button *load;
+ Button *_delete;
+ Button *paste;
+ Button *empty;
+ Button *empty2;
+ Button *move_up;
+ Button *move_down;
+ ItemList *tree;
+ bool loading_scene;
+ int sel;
+
+ HSplitContainer *split;
+ Button *new_anim;
+ Button *remove_anim;
+
+
+ Tree *animations;
+ SpinBox *anim_speed;
+ CheckButton *anim_loop;
+
+ EditorFileDialog *file;
+
+ AcceptDialog *dialog;
+
+ SpriteFrames *frames;
+
+ StringName edited_anim;
+
+ void _load_pressed();
+ void _load_scene_pressed();
+ void _file_load_request(const PoolVector<String>& p_path, int p_at_pos=-1);
+ void _paste_pressed();
+ void _empty_pressed();
+ void _empty2_pressed();
+ void _delete_pressed();
+ void _delete_confirm_pressed();
+ void _up_pressed();
+ void _down_pressed();
+ void _update_library(bool p_skip_selector=false);
+ void _item_edited();
+
+
+
+ void _animation_select();
+ void _animation_name_edited();
+ void _animation_add();
+ void _animation_remove();
+ void _animation_loop_changed();
+ void _animation_fps_changed(double p_value);
+
+ bool updating;
+
+ UndoRedo *undo_redo;
+
+ bool _is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const;
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+ void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
+
+ void edit(SpriteFrames* p_frames);
+ SpriteFramesEditor();
+};
+
+class SpriteFramesEditorPlugin : public EditorPlugin {
+
+ GDCLASS( SpriteFramesEditorPlugin, EditorPlugin );
+
+ SpriteFramesEditor *frames_editor;
+ EditorNode *editor;
+ Button *button;
+
+public:
+
+ virtual String get_name() const { return "SpriteFrames"; }
+ 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);
+
+ SpriteFramesEditorPlugin(EditorNode *p_node);
+ ~SpriteFramesEditorPlugin();
+
+};
+
+#endif // SPRITE_FRAMES_EDITOR_PLUGIN_H
diff --git a/editor/plugins/stream_editor_plugin.cpp b/editor/plugins/stream_editor_plugin.cpp
new file mode 100644
index 0000000000..449f6f610e
--- /dev/null
+++ b/editor/plugins/stream_editor_plugin.cpp
@@ -0,0 +1,149 @@
+/*************************************************************************/
+/* stream_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "stream_editor_plugin.h"
+
+#if 0
+
+void StreamEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ play->set_icon( get_icon("Play","EditorIcons") );
+ stop->set_icon( get_icon("Stop","EditorIcons") );
+ }
+
+}
+void StreamEditor::_node_removed(Node *p_node) {
+
+ if(p_node==node) {
+ node=NULL;
+ hide();
+ }
+
+}
+
+void StreamEditor::_play() {
+
+ node->call("play");
+}
+
+void StreamEditor::_stop() {
+
+ node->call("stop");
+}
+
+void StreamEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_play"),&StreamEditor::_play);
+ ClassDB::bind_method(D_METHOD("_stop"),&StreamEditor::_stop);
+
+}
+
+void StreamEditor::edit(Node *p_stream) {
+
+ node=p_stream;
+
+}
+StreamEditor::StreamEditor() {
+
+ play = memnew( Button );
+
+
+ play->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,60);
+ play->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,40);
+ play->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
+ play->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
+
+ add_child(play);
+
+ stop = memnew( Button );
+
+ stop->set_pos(Point2( 35, 5 ));
+ stop->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,30);
+ stop->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,10);
+ stop->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
+ stop->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
+ add_child(stop);
+
+
+ play->connect("pressed", this,"_play");
+ stop->connect("pressed", this,"_stop");
+
+}
+
+
+void StreamEditorPlugin::edit(Object *p_object) {
+
+ stream_editor->edit(p_object->cast_to<Node>());
+}
+
+bool StreamEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("StreamPlayer") || p_object->is_class("SpatialStreamPlayer");
+}
+
+void StreamEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ stream_editor->show();
+ stream_editor->set_fixed_process(true);
+ } else {
+
+ stream_editor->hide();
+ stream_editor->set_fixed_process(false);
+ stream_editor->edit(NULL);
+ }
+
+}
+
+StreamEditorPlugin::StreamEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ stream_editor = memnew( StreamEditor );
+ editor->get_viewport()->add_child(stream_editor);
+
+ stream_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
+ stream_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
+ stream_editor->set_margin(MARGIN_LEFT,60);
+ stream_editor->set_margin(MARGIN_RIGHT,0);
+ stream_editor->set_margin(MARGIN_TOP,0);
+ stream_editor->set_margin(MARGIN_BOTTOM,10);
+
+
+ stream_editor->hide();
+
+
+
+}
+
+
+StreamEditorPlugin::~StreamEditorPlugin()
+{
+}
+
+#endif
diff --git a/editor/plugins/stream_editor_plugin.h b/editor/plugins/stream_editor_plugin.h
new file mode 100644
index 0000000000..2ae3b7100e
--- /dev/null
+++ b/editor/plugins/stream_editor_plugin.h
@@ -0,0 +1,84 @@
+/*************************************************************************/
+/* stream_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 STREAM_EDITOR_PLUGIN_H
+#define STREAM_EDITOR_PLUGIN_H
+
+#if 0
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/audio/stream_player.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class StreamEditor : public Control {
+
+ GDCLASS(StreamEditor, Control );
+
+ Button * play;
+ Button * stop;
+
+ Panel *panel;
+ Node *node;
+
+ void _play();
+ void _stop();
+protected:
+ void _notification(int p_what);
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+public:
+
+ void edit(Node *p_stream);
+ StreamEditor();
+};
+
+class StreamEditorPlugin : public EditorPlugin {
+
+ GDCLASS( StreamEditorPlugin, EditorPlugin );
+
+ StreamEditor *stream_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "Stream"; }
+ 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);
+
+ StreamEditorPlugin(EditorNode *p_node);
+ ~StreamEditorPlugin();
+
+};
+
+#endif // STREAM_EDITOR_PLUGIN_H
+#endif
diff --git a/tools/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index 396ebd0052..396ebd0052 100644
--- a/tools/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h
new file mode 100644
index 0000000000..01e636472b
--- /dev/null
+++ b/editor/plugins/style_box_editor_plugin.h
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* style_box_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 STYLE_BOX_EDITOR_PLUGIN_H
+#define STYLE_BOX_EDITOR_PLUGIN_H
+
+#include "scene/resources/style_box.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/gui/option_button.h"
+#include "editor/editor_node.h"
+
+
+class StyleBoxEditor : public Control {
+
+ GDCLASS( StyleBoxEditor, Control );
+
+ Panel *panel;
+ Panel *preview;
+
+ Ref<StyleBox> stylebox;
+
+ void _sb_changed();
+
+protected:
+
+
+ static void _bind_methods();
+public:
+
+ void edit(const Ref<StyleBox>& p_stylebox);
+
+ StyleBoxEditor();
+};
+
+
+
+class StyleBoxEditorPlugin : public EditorPlugin {
+
+ GDCLASS( StyleBoxEditorPlugin, EditorPlugin );
+
+ StyleBoxEditor *stylebox_editor;
+ EditorNode *editor;
+ Button *button;
+
+public:
+
+ virtual String get_name() const { return "StyleBox"; }
+ 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);
+
+ StyleBoxEditorPlugin(EditorNode *p_node);
+
+};
+
+
+#endif // STYLE_BOX_EDITOR_PLUGIN_H
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
new file mode 100644
index 0000000000..af05094e5e
--- /dev/null
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -0,0 +1,169 @@
+/*************************************************************************/
+/* texture_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "texture_editor_plugin.h"
+
+#include "io/resource_loader.h"
+#include "global_config.h"
+#include "editor/editor_settings.h"
+
+void TextureEditor::_gui_input(InputEvent p_event) {
+
+
+}
+
+void TextureEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+ }
+
+
+ if (p_what==NOTIFICATION_READY) {
+
+ //get_scene()->connect("node_removed",this,"_node_removed");
+
+ }
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+
+ Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons");
+ Size2 size = get_size();
+
+ draw_texture_rect(checkerboard,Rect2(Point2(),size),true);
+
+ int tex_width = texture->get_width() * size.height / texture ->get_height();
+ int tex_height = size.height;
+
+ if (tex_width>size.width) {
+ tex_width=size.width;
+ tex_height=texture->get_height() * tex_width / texture->get_width();
+ }
+
+ int ofs_x = (size.width - tex_width)/2;
+ int ofs_y = (size.height - tex_height)/2;
+
+ draw_texture_rect(texture,Rect2(ofs_x,ofs_y,tex_width,tex_height));
+
+ Ref<Font> font = get_font("font","Label");
+
+ String format;
+ if (texture->cast_to<ImageTexture>()) {
+ format = Image::get_format_name(texture->cast_to<ImageTexture>()->get_format());
+ } else {
+ format=texture->get_class();
+ }
+ String text = itos(texture->get_width())+"x"+itos(texture->get_height())+" "+format;
+
+ Size2 rect = font->get_string_size(text);
+
+ Vector2 draw_from = size-rect+Size2(-2,font->get_ascent()-2);
+ if (draw_from.x<0)
+ draw_from.x=0;
+
+ draw_string(font,draw_from+Vector2(2,2),text,Color(0,0,0,0.5),size.width);
+ draw_string(font,draw_from-Vector2(2,2),text,Color(0,0,0,0.5),size.width);
+ draw_string(font,draw_from,text,Color(1,1,1,1),size.width);
+ }
+}
+
+
+
+void TextureEditor::edit(Ref<Texture> p_texture) {
+
+ texture=p_texture;
+
+ if (!texture.is_null())
+ update();
+ else {
+
+ hide();
+ }
+
+}
+
+
+
+void TextureEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&TextureEditor::_gui_input);
+
+}
+
+TextureEditor::TextureEditor() {
+
+ set_custom_minimum_size(Size2(1,150));
+
+}
+
+
+void TextureEditorPlugin::edit(Object *p_object) {
+
+ Texture * s = p_object->cast_to<Texture>();
+ if (!s)
+ return;
+
+ texture_editor->edit(Ref<Texture>(s));
+}
+
+bool TextureEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Texture");
+}
+
+void TextureEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ texture_editor->show();
+ //texture_editor->set_process(true);
+ } else {
+
+ texture_editor->hide();
+ //texture_editor->set_process(false);
+ }
+
+}
+
+TextureEditorPlugin::TextureEditorPlugin(EditorNode *p_node) {
+
+ editor=p_node;
+ texture_editor = memnew( TextureEditor );
+ add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,texture_editor);
+ texture_editor->hide();
+
+
+
+}
+
+
+TextureEditorPlugin::~TextureEditorPlugin()
+{
+}
+
+
diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h
new file mode 100644
index 0000000000..7ad0e918cf
--- /dev/null
+++ b/editor/plugins/texture_editor_plugin.h
@@ -0,0 +1,77 @@
+/*************************************************************************/
+/* texture_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 TEXTURE_EDITOR_PLUGIN_H
+#define TEXTURE_EDITOR_PLUGIN_H
+
+
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/resources/texture.h"
+
+
+class TextureEditor : public Control {
+
+ GDCLASS(TextureEditor, Control);
+
+
+ Ref<Texture> texture;
+
+protected:
+ void _notification(int p_what);
+ void _gui_input(InputEvent p_event);
+ static void _bind_methods();
+public:
+
+ void edit(Ref<Texture> p_texture);
+ TextureEditor();
+};
+
+
+class TextureEditorPlugin : public EditorPlugin {
+
+ GDCLASS( TextureEditorPlugin, EditorPlugin );
+
+ TextureEditor *texture_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "Texture"; }
+ 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);
+
+ TextureEditorPlugin(EditorNode *p_node);
+ ~TextureEditorPlugin();
+
+};
+
+#endif // TEXTURE_EDITOR_PLUGIN_H
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
new file mode 100644
index 0000000000..aabf938577
--- /dev/null
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -0,0 +1,1012 @@
+/*************************************************************************/
+/* texture_region_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Author: Mariano Suligoy */
+/* */
+/* 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 "texture_region_editor_plugin.h"
+
+#include "core/core_string_names.h"
+#include "scene/gui/check_box.h"
+#include "os/input.h"
+#include "os/keyboard.h"
+
+void draw_margin_line(Control *edit_draw, Vector2 from, Vector2 to){
+ Vector2 line = (to-from).normalized() * 10;
+ while ((to - from).length_squared() > 200) {
+ edit_draw->draw_line(from, from + line,Color(0.97, 0.2, 0.2),2);
+ from += line*2;
+ }
+}
+
+void TextureRegionEditor::_region_draw()
+{
+ Ref<Texture> base_tex = NULL;
+ if(node_sprite)
+ base_tex = node_sprite->get_texture();
+ else if(node_patch9)
+ base_tex = node_patch9->get_texture();
+ else if(obj_styleBox.is_valid())
+ base_tex = obj_styleBox->get_texture();
+ else if(atlas_tex.is_valid())
+ base_tex = atlas_tex->get_atlas();
+ if (base_tex.is_null())
+ return;
+
+ Transform2D mtx;
+ mtx.elements[2]=-draw_ofs;
+ mtx.scale_basis(Vector2(draw_zoom,draw_zoom));
+
+ VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),mtx);
+ edit_draw->draw_texture(base_tex,Point2());
+ VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),Transform2D());
+
+ if (snap_mode == SNAP_GRID) {
+ Size2 s = edit_draw->get_size();
+ int last_cell;
+
+ if (snap_step.x!=0) {
+ if (snap_separation.x == 0)
+ for(int i=0;i<s.width;i++) {
+ int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ else
+ for(int i=0;i<s.width;i++) {
+ int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/(snap_step.x+snap_separation.x)));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ edit_draw->draw_rect(Rect2(i-snap_separation.x*draw_zoom,0,snap_separation.x*draw_zoom,s.height),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ }
+
+ if (snap_step.y!=0) {
+ if (snap_separation.y == 0)
+ for(int i=0;i<s.height;i++) {
+ int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ else
+ for(int i=0;i<s.height;i++) {
+ int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/(snap_step.y+snap_separation.y)));
+ if (i==0)
+ last_cell=cell;
+ if (last_cell!=cell)
+ edit_draw->draw_rect(Rect2(0,i-snap_separation.y*draw_zoom,s.width,snap_separation.y*draw_zoom),Color(0.3,0.7,1,0.3));
+ last_cell=cell;
+ }
+ }
+ } else if (snap_mode == SNAP_AUTOSLICE) {
+ for (List<Rect2>::Element *E = autoslice_cache.front();E;E=E->next()) {
+ Rect2 r = E->get();
+ Vector2 endpoints[4]={
+ mtx.basis_xform(r.pos),
+ mtx.basis_xform(r.pos+Vector2(r.size.x,0)),
+ mtx.basis_xform(r.pos+r.size),
+ mtx.basis_xform(r.pos+Vector2(0,r.size.y))
+ };
+ for(int i=0;i<4;i++) {
+ int next = (i+1)%4;
+ edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, Color(0.3,0.7,1,1) , 2);
+ }
+ }
+ }
+
+ Ref<Texture> select_handle = get_icon("EditorHandle","EditorIcons");
+
+ Rect2 scroll_rect(Point2(),mtx.basis_xform(base_tex->get_size()));
+ scroll_rect.expand_to(mtx.basis_xform(edit_draw->get_size()));
+
+ Vector2 endpoints[4]={
+ mtx.basis_xform(rect.pos),
+ mtx.basis_xform(rect.pos+Vector2(rect.size.x,0)),
+ mtx.basis_xform(rect.pos+rect.size),
+ mtx.basis_xform(rect.pos+Vector2(0,rect.size.y))
+ };
+ Color color(0.9,0.5,0.5);
+ for(int i=0;i<4;i++) {
+
+ int prev = (i+3)%4;
+ int next = (i+1)%4;
+
+ Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
+ ofs*=1.4144*(select_handle->get_size().width/2);
+
+ edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, color , 2);
+
+ if (snap_mode != SNAP_AUTOSLICE)
+ edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs);
+
+ ofs = (endpoints[next]-endpoints[i])/2;
+ ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2);
+
+ if (snap_mode != SNAP_AUTOSLICE)
+ edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs);
+
+ scroll_rect.expand_to(endpoints[i]);
+ }
+
+ scroll_rect=scroll_rect.grow(200);
+ updating_scroll=true;
+ hscroll->set_min(scroll_rect.pos.x);
+ hscroll->set_max(scroll_rect.pos.x+scroll_rect.size.x);
+ hscroll->set_page(edit_draw->get_size().x);
+ hscroll->set_value(draw_ofs.x);
+ hscroll->set_step(0.001);
+
+ vscroll->set_min(scroll_rect.pos.y);
+ vscroll->set_max(scroll_rect.pos.y+scroll_rect.size.y);
+ vscroll->set_page(edit_draw->get_size().y);
+ vscroll->set_value(draw_ofs.y);
+ vscroll->set_step(0.001);
+ updating_scroll=false;
+
+ float margins[4];
+ if (node_patch9 || obj_styleBox.is_valid()) {
+ if (node_patch9) {
+ margins[0] = node_patch9->get_patch_margin(MARGIN_TOP);
+ margins[1] = node_patch9->get_patch_margin(MARGIN_BOTTOM);
+ margins[2] = node_patch9->get_patch_margin(MARGIN_LEFT);
+ margins[3] = node_patch9->get_patch_margin(MARGIN_RIGHT);
+ } else if (obj_styleBox.is_valid()) {
+ margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
+ margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
+ margins[2] = obj_styleBox->get_margin_size(MARGIN_LEFT);
+ margins[3] = obj_styleBox->get_margin_size(MARGIN_RIGHT);
+ }
+ Vector2 pos[4] = {
+ mtx.basis_xform(Vector2(0,margins[0]))+Vector2(0,endpoints[0].y-draw_ofs.y),
+ -mtx.basis_xform(Vector2(0,margins[1]))+Vector2(0,endpoints[2].y-draw_ofs.y),
+ mtx.basis_xform(Vector2(margins[2],0))+Vector2(endpoints[0].x-draw_ofs.x,0),
+ -mtx.basis_xform(Vector2(margins[3],0))+Vector2(endpoints[2].x-draw_ofs.x,0)};
+
+ draw_margin_line(edit_draw,pos[0],pos[0]+Vector2(edit_draw->get_size().x,0));
+ draw_margin_line(edit_draw,pos[1],pos[1]+Vector2(edit_draw->get_size().x,0));
+ draw_margin_line(edit_draw,pos[2],pos[2]+Vector2(0,edit_draw->get_size().y));
+ draw_margin_line(edit_draw,pos[3],pos[3]+Vector2(0,edit_draw->get_size().y));
+ }
+}
+
+void TextureRegionEditor::_region_input(const InputEvent& p_input)
+{
+ Transform2D mtx;
+ mtx.elements[2]=-draw_ofs;
+ mtx.scale_basis(Vector2(draw_zoom,draw_zoom));
+
+ Vector2 endpoints[8]={
+ mtx.xform(rect.pos)+Vector2(-4,-4),
+ mtx.xform(rect.pos+Vector2(rect.size.x/2,0))+Vector2(0,-4),
+ mtx.xform(rect.pos+Vector2(rect.size.x,0))+Vector2(4,-4),
+ mtx.xform(rect.pos+Vector2(rect.size.x,rect.size.y/2))+Vector2(4,0),
+ mtx.xform(rect.pos+rect.size)+Vector2(4,4),
+ mtx.xform(rect.pos+Vector2(rect.size.x/2,rect.size.y))+Vector2(0,4),
+ mtx.xform(rect.pos+Vector2(0,rect.size.y))+Vector2(-4,4),
+ mtx.xform(rect.pos+Vector2(0,rect.size.y/2))+Vector2(-4,0)
+ };
+
+ if (p_input.type==InputEvent::MOUSE_BUTTON) {
+
+ const InputEventMouseButton &mb=p_input.mouse_button;
+
+ if (mb.button_index==BUTTON_LEFT) {
+
+ if (mb.pressed) {
+ if (node_patch9 || obj_styleBox.is_valid()) {
+ edited_margin = -1;
+ float margins[4];
+ if (node_patch9) {
+ margins[0] = node_patch9->get_patch_margin(MARGIN_TOP);
+ margins[1] = node_patch9->get_patch_margin(MARGIN_BOTTOM);
+ margins[2] = node_patch9->get_patch_margin(MARGIN_LEFT);
+ margins[3] = node_patch9->get_patch_margin(MARGIN_RIGHT);
+ } else if (obj_styleBox.is_valid()) {
+ margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
+ margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
+ margins[2] = obj_styleBox->get_margin_size(MARGIN_LEFT);
+ margins[3] = obj_styleBox->get_margin_size(MARGIN_RIGHT);
+ }
+ Vector2 pos[4] = {
+ mtx.basis_xform(rect.pos+Vector2(0,margins[0]))-draw_ofs,
+ mtx.basis_xform(rect.pos+rect.size-Vector2(0,margins[1]))-draw_ofs,
+ mtx.basis_xform(rect.pos+Vector2(margins[2],0))-draw_ofs,
+ mtx.basis_xform(rect.pos+rect.size-Vector2(margins[3],0))-draw_ofs};
+ if (Math::abs(mb.y - pos[0].y) < 8) {
+ edited_margin = 0;
+ prev_margin = margins[0];
+ } else if (Math::abs(mb.y - pos[1].y) < 8) {
+ edited_margin = 1;
+ prev_margin = margins[1];
+ } else if (Math::abs(mb.x - pos[2].x) < 8) {
+ edited_margin = 2;
+ prev_margin = margins[2];
+ } else if (Math::abs(mb.x - pos[3].x) < 8) {
+ edited_margin = 3;
+ prev_margin = margins[3];
+ }
+ if (edited_margin >= 0) {
+ drag_from=Vector2(mb.x,mb.y);
+ drag=true;
+ }
+ }
+ if ( edited_margin < 0 && snap_mode == SNAP_AUTOSLICE) {
+ Vector2 point = mtx.affine_inverse().xform(Vector2(mb.x,mb.y));
+ for (List<Rect2>::Element *E=autoslice_cache.front();E;E=E->next()) {
+ if (E->get().has_point(point)) {
+ rect = E->get();
+ if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)&&!(Input::get_singleton()->is_key_pressed(KEY_SHIFT|KEY_ALT))) {
+ Rect2 r;
+ if(node_sprite )
+ r=node_sprite->get_region_rect();
+ else if(node_patch9)
+ r=node_patch9->get_region_rect();
+ else if(obj_styleBox.is_valid())
+ r=obj_styleBox->get_region_rect();
+ else if(atlas_tex.is_valid())
+ r =atlas_tex->get_region();
+ rect.expand_to(r.pos);
+ rect.expand_to(r.pos+r.size);
+ }
+ undo_redo->create_action("Set Region Rect");
+ if(node_sprite){
+ undo_redo->add_do_method(node_sprite ,"set_region_rect",rect);
+ undo_redo->add_undo_method(node_sprite,"set_region_rect",node_sprite->get_region_rect());
+ } else if(node_patch9){
+ undo_redo->add_do_method(node_patch9 ,"set_region_rect",rect);
+ undo_redo->add_undo_method(node_patch9,"set_region_rect",node_patch9->get_region_rect());
+ } else if (obj_styleBox.is_valid()) {
+ undo_redo->add_do_method(obj_styleBox.ptr(),"set_region_rect",rect);
+ undo_redo->add_undo_method(obj_styleBox.ptr(),"set_region_rect",obj_styleBox->get_region_rect());
+ } else if (atlas_tex.is_valid()) {
+ undo_redo->add_do_method(atlas_tex.ptr(),"set_region",rect);
+ undo_redo->add_undo_method(atlas_tex.ptr(),"set_region",atlas_tex->get_region());
+ }
+ undo_redo->add_do_method(edit_draw,"update");
+ undo_redo->add_undo_method(edit_draw,"update");
+ undo_redo->commit_action();
+ break;
+ }
+ }
+ } else if (edited_margin < 0) {
+ drag_from=mtx.affine_inverse().xform(Vector2(mb.x,mb.y));
+ if (snap_mode == SNAP_PIXEL)
+ drag_from = drag_from.snapped(Vector2(1,1));
+ else if (snap_mode == SNAP_GRID)
+ drag_from=snap_point(drag_from);
+ drag=true;
+ if(node_sprite )
+ rect_prev=node_sprite->get_region_rect();
+ else if(node_patch9)
+ rect_prev=node_patch9->get_region_rect();
+ else if(obj_styleBox.is_valid())
+ rect_prev=obj_styleBox->get_region_rect();
+ else if(atlas_tex.is_valid())
+ rect_prev=atlas_tex->get_region();
+
+ for (int i=0; i<8;i++) {
+ Vector2 tuv=endpoints[i];
+ if (tuv.distance_to(Vector2(mb.x,mb.y))<8) {
+ drag_index=i;
+ }
+ }
+
+ if (drag_index==-1) {
+ creating = true;
+ rect = Rect2(drag_from,Size2());
+ }
+ }
+
+ } else if (drag) {
+ if (edited_margin >= 0) {
+ undo_redo->create_action("Set Margin");
+ static Margin m[4] = {MARGIN_TOP,MARGIN_BOTTOM,MARGIN_LEFT,MARGIN_RIGHT};
+ if (node_patch9) {
+ undo_redo->add_do_method(node_patch9 ,"set_patch_margin",m[edited_margin],node_patch9->get_patch_margin(m[edited_margin]));
+ undo_redo->add_undo_method(node_patch9,"set_patch_margin",m[edited_margin],prev_margin);
+ } else if (obj_styleBox.is_valid()) {
+ undo_redo->add_do_method(obj_styleBox.ptr() ,"set_margin_size",m[edited_margin],obj_styleBox->get_margin_size(m[edited_margin]));
+ undo_redo->add_undo_method(obj_styleBox.ptr(),"set_margin_size",m[edited_margin],prev_margin);
+ obj_styleBox->emit_signal(CoreStringNames::get_singleton()->changed);
+ }
+ edited_margin = -1;
+ } else {
+ undo_redo->create_action("Set Region Rect");
+ if(node_sprite){
+ undo_redo->add_do_method(node_sprite ,"set_region_rect",node_sprite->get_region_rect());
+ undo_redo->add_undo_method(node_sprite,"set_region_rect",rect_prev);
+ }
+ else if(atlas_tex.is_valid()){
+ undo_redo->add_do_method(atlas_tex.ptr() ,"set_region",atlas_tex->get_region());
+ undo_redo->add_undo_method(atlas_tex.ptr(),"set_region",rect_prev);
+ }
+ else if(node_patch9){
+ // FIXME: Is this intentional?
+ } else if(node_patch9){
+ undo_redo->add_do_method(node_patch9 ,"set_region_rect",node_patch9->get_region_rect());
+ undo_redo->add_undo_method(node_patch9,"set_region_rect",rect_prev);
+ } else if (obj_styleBox.is_valid()) {
+ undo_redo->add_do_method(obj_styleBox.ptr() ,"set_region_rect",obj_styleBox->get_region_rect());
+ undo_redo->add_undo_method(obj_styleBox.ptr(),"set_region_rect",rect_prev);
+ }
+ drag_index = -1;
+ }
+ undo_redo->add_do_method(edit_draw,"update");
+ undo_redo->add_undo_method(edit_draw,"update");
+ undo_redo->commit_action();
+ drag=false;
+ creating = false;
+ }
+
+ } else if (mb.button_index==BUTTON_RIGHT && mb.pressed) {
+
+ if (drag) {
+ drag=false;
+ if (edited_margin >= 0) {
+ static Margin m[4] = {MARGIN_TOP,MARGIN_BOTTOM,MARGIN_LEFT,MARGIN_RIGHT};
+ if (node_patch9)
+ node_patch9->set_patch_margin(m[edited_margin],prev_margin);
+ if (obj_styleBox.is_valid())
+ obj_styleBox->set_margin_size(m[edited_margin],prev_margin);
+ edited_margin = -1;
+ } else {
+ apply_rect(rect_prev);
+ rect=rect_prev;
+ edit_draw->update();
+ drag_index = -1;
+ }
+ }
+ } else if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) {
+ _zoom_in();
+ } else if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) {
+ _zoom_out();
+ }
+ } else if (p_input.type==InputEvent::MOUSE_MOTION) {
+
+ const InputEventMouseMotion &mm=p_input.mouse_motion;
+
+ if (mm.button_mask&BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+
+ Vector2 draged(mm.relative_x,mm.relative_y);
+ hscroll->set_value( hscroll->get_value()-draged.x );
+ vscroll->set_value( vscroll->get_value()-draged.y );
+
+ } else if (drag) {
+
+ if (edited_margin >= 0) {
+ float new_margin;
+ if (edited_margin == 0)
+ new_margin = prev_margin + (mm.y-drag_from.y) / draw_zoom;
+ else if (edited_margin == 1)
+ new_margin = prev_margin - (mm.y-drag_from.y) / draw_zoom;
+ else if (edited_margin == 2)
+ new_margin = prev_margin + (mm.x-drag_from.x) / draw_zoom;
+ else if (edited_margin == 3)
+ new_margin = prev_margin - (mm.x-drag_from.x) / draw_zoom;
+ if (new_margin < 0)
+ new_margin = 0;
+ static Margin m[4] = {MARGIN_TOP,MARGIN_BOTTOM,MARGIN_LEFT,MARGIN_RIGHT};
+ if (node_patch9)
+ node_patch9->set_patch_margin(m[edited_margin],new_margin);
+ if (obj_styleBox.is_valid())
+ obj_styleBox->set_margin_size(m[edited_margin],new_margin);
+ } else {
+ Vector2 new_pos = mtx.affine_inverse().xform(Vector2(mm.x,mm.y));
+ if (snap_mode == SNAP_PIXEL)
+ new_pos = new_pos.snapped(Vector2(1,1));
+ else if (snap_mode == SNAP_GRID)
+ new_pos=snap_point(new_pos);
+
+ if (creating) {
+ rect = Rect2(drag_from,Size2());
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ edit_draw->update();
+ return;
+ }
+
+ switch(drag_index) {
+ case 0: {
+ Vector2 p=rect_prev.pos+rect_prev.size;
+ rect = Rect2(p,Size2());
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+ case 1: {
+ Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
+ rect = Rect2(p,Size2(rect_prev.size.x,0));
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+ case 2: {
+ Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
+ rect = Rect2(p,Size2());
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+ case 3: {
+ Vector2 p=rect_prev.pos;
+ rect = Rect2(p,Size2(0,rect_prev.size.y));
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+ case 4: {
+ Vector2 p=rect_prev.pos;
+ rect = Rect2(p,Size2());
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+ case 5: {
+ Vector2 p=rect_prev.pos;
+ rect = Rect2(p,Size2(rect_prev.size.x,0));
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+ case 6: {
+ Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
+ rect = Rect2(p,Size2());
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+ case 7: {
+ Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
+ rect = Rect2(p,Size2(0,rect_prev.size.y));
+ rect.expand_to(new_pos);
+ apply_rect(rect);
+ } break;
+
+ }
+ }
+ edit_draw->update();
+ }
+
+ }
+}
+
+void TextureRegionEditor::_scroll_changed(float)
+{
+ if (updating_scroll)
+ return;
+
+ draw_ofs.x=hscroll->get_value();
+ draw_ofs.y=vscroll->get_value();
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_set_snap_mode(int p_mode)
+{
+ snap_mode_button->get_popup()->set_item_checked(snap_mode,false);
+ snap_mode = p_mode;
+ snap_mode_button->set_text(snap_mode_button->get_popup()->get_item_text(p_mode));
+ snap_mode_button->get_popup()->set_item_checked(snap_mode,true);
+
+ if (snap_mode == SNAP_GRID)
+ hb_grid->show();
+ else
+ hb_grid->hide();
+
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_set_snap_off_x(float p_val)
+{
+ snap_offset.x=p_val;
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_set_snap_off_y(float p_val)
+{
+ snap_offset.y=p_val;
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_set_snap_step_x(float p_val)
+{
+ snap_step.x=p_val;
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_set_snap_step_y(float p_val)
+{
+ snap_step.y=p_val;
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_set_snap_sep_x(float p_val)
+{
+ snap_separation.x = p_val;
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_set_snap_sep_y(float p_val)
+{
+ snap_separation.y = p_val;
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_zoom_in()
+{
+ if (draw_zoom < 8) {
+ draw_zoom *= 2;
+ edit_draw->update();
+ }
+}
+
+void TextureRegionEditor::_zoom_reset()
+{
+ if (draw_zoom == 1) return;
+ draw_zoom = 1;
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_zoom_out()
+{
+ if (draw_zoom > 0.25) {
+ draw_zoom /= 2;
+ edit_draw->update();
+ }
+}
+
+void TextureRegionEditor::apply_rect(const Rect2& rect){
+ if(node_sprite)
+ node_sprite->set_region_rect(rect);
+ else if(node_patch9)
+ node_patch9->set_region_rect(rect);
+ else if(obj_styleBox.is_valid())
+ obj_styleBox->set_region_rect(rect);
+ else if(atlas_tex.is_valid())
+ atlas_tex->set_region(rect);
+}
+
+void TextureRegionEditor::_notification(int p_what)
+{
+ switch(p_what) {
+ case NOTIFICATION_READY: {
+ zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons"));
+ zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
+ zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons"));
+ icon_zoom->set_texture( get_icon("Zoom", "EditorIcons"));
+ } break;
+ }
+}
+
+void TextureRegionEditor::_node_removed(Object *p_obj)
+{
+ if(p_obj == node_sprite || p_obj == node_patch9 || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) {
+ node_patch9 = NULL;
+ node_sprite = NULL;
+ obj_styleBox = Ref<StyleBox>(NULL);
+ atlas_tex = Ref<AtlasTexture>(NULL);
+ hide();
+ }
+}
+
+void TextureRegionEditor::_bind_methods()
+{
+ ClassDB::bind_method(D_METHOD("_edit_region"),&TextureRegionEditor::_edit_region);
+ ClassDB::bind_method(D_METHOD("_region_draw"),&TextureRegionEditor::_region_draw);
+ ClassDB::bind_method(D_METHOD("_region_input"),&TextureRegionEditor::_region_input);
+ ClassDB::bind_method(D_METHOD("_scroll_changed"),&TextureRegionEditor::_scroll_changed);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&TextureRegionEditor::_node_removed);
+ ClassDB::bind_method(D_METHOD("_set_snap_mode"),&TextureRegionEditor::_set_snap_mode);
+ ClassDB::bind_method(D_METHOD("_set_snap_off_x"),&TextureRegionEditor::_set_snap_off_x);
+ ClassDB::bind_method(D_METHOD("_set_snap_off_y"),&TextureRegionEditor::_set_snap_off_y);
+ ClassDB::bind_method(D_METHOD("_set_snap_step_x"),&TextureRegionEditor::_set_snap_step_x);
+ ClassDB::bind_method(D_METHOD("_set_snap_step_y"),&TextureRegionEditor::_set_snap_step_y);
+ ClassDB::bind_method(D_METHOD("_set_snap_sep_x"),&TextureRegionEditor::_set_snap_sep_x);
+ ClassDB::bind_method(D_METHOD("_set_snap_sep_y"),&TextureRegionEditor::_set_snap_sep_y);
+ ClassDB::bind_method(D_METHOD("_zoom_in"),&TextureRegionEditor::_zoom_in);
+ ClassDB::bind_method(D_METHOD("_zoom_reset"),&TextureRegionEditor::_zoom_reset);
+ ClassDB::bind_method(D_METHOD("_zoom_out"),&TextureRegionEditor::_zoom_out);
+}
+
+void TextureRegionEditor::edit(Object *p_obj)
+{
+ if (node_sprite && node_sprite->is_connected("texture_changed",this,"_edit_region"))
+ node_sprite->disconnect("texture_changed",this,"_edit_region");
+ if (node_patch9 && node_patch9->is_connected("texture_changed",this,"_edit_region"))
+ node_patch9->disconnect("texture_changed",this,"_edit_region");
+ if (obj_styleBox.is_valid() && obj_styleBox->is_connected("texture_changed",this,"_edit_region"))
+ obj_styleBox->disconnect("texture_changed",this,"_edit_region");
+ if (atlas_tex.is_valid() && atlas_tex->is_connected("atlas_changed",this,"_edit_region"))
+ atlas_tex->disconnect("atlas_changed",this,"_edit_region");
+ if (p_obj) {
+ node_sprite = p_obj->cast_to<Sprite>();
+ node_patch9 = p_obj->cast_to<NinePatchRect>();
+ if (p_obj->cast_to<StyleBoxTexture>())
+ obj_styleBox = Ref<StyleBoxTexture>(p_obj->cast_to<StyleBoxTexture>());
+ if (p_obj->cast_to<AtlasTexture>()) {
+ atlas_tex = Ref<AtlasTexture>(p_obj->cast_to<AtlasTexture>());
+ atlas_tex->connect("atlas_changed",this,"_edit_region");
+ } else {
+ p_obj->connect("texture_changed",this,"_edit_region");
+ }
+ p_obj->add_change_receptor(this);
+ p_obj->connect("tree_exited",this,"_node_removed",varray(p_obj),CONNECT_ONESHOT);
+ _edit_region();
+ } else {
+ if(node_sprite)
+ node_sprite->disconnect("tree_exited",this,"_node_removed");
+ else if(node_patch9)
+ node_patch9->disconnect("tree_exited",this,"_node_removed");
+ else if(obj_styleBox.is_valid())
+ obj_styleBox->disconnect("tree_exited",this,"_node_removed");
+ else if(atlas_tex.is_valid())
+ atlas_tex->disconnect("tree_exited",this,"_node_removed");
+
+ node_sprite = NULL;
+ node_patch9 = NULL;
+ obj_styleBox = Ref<StyleBoxTexture>(NULL);
+ atlas_tex = Ref<AtlasTexture>(NULL);
+ }
+ edit_draw->update();
+}
+
+void TextureRegionEditor::_changed_callback(Object *p_changed, const char *p_prop) {
+ if ((String)p_prop == "region_rect") {
+ _edit_region();
+ }
+}
+
+void TextureRegionEditor::_edit_region()
+{
+ Ref<Texture> texture = NULL;
+ if(node_sprite )
+ texture = node_sprite->get_texture();
+ else if(node_patch9 )
+ texture = node_patch9->get_texture();
+ else if(obj_styleBox.is_valid())
+ texture = obj_styleBox->get_texture();
+ else if(atlas_tex.is_valid())
+ texture = atlas_tex->get_atlas();
+
+ if (texture.is_null()) {
+ return;
+ }
+
+ autoslice_cache.clear();
+ Image i;
+ if (i.load(texture->get_path()) == OK) {
+ BitMap bm;
+ bm.create_from_image_alpha(i);
+ for (int y = 0; y < i.get_height(); y++) {
+ for (int x = 0; x < i.get_width(); x++) {
+ if (bm.get_bit(Point2(x,y))) {
+ bool found = false;
+ for (List<Rect2>::Element *E = autoslice_cache.front(); E; E=E->next()) {
+ Rect2 grown = E->get().grow(1.5);
+ if (grown.has_point(Point2(x,y))) {
+ E->get().expand_to(Point2(x,y));
+ E->get().expand_to(Point2(x+1,y+1));
+ x = E->get().pos.x+E->get().size.x-1;
+ bool merged = true;
+ while (merged) {
+ merged = false;
+ bool queue_erase = false;
+ for (List<Rect2>::Element *F = autoslice_cache.front(); F; F=F->next()) {
+ if (queue_erase){
+ autoslice_cache.erase(F->prev());
+ queue_erase = false;
+ }
+ if (F==E)
+ continue;
+ if (E->get().grow(1).intersects(F->get())) {
+ E->get().expand_to(F->get().pos);
+ E->get().expand_to(F->get().pos+F->get().size);
+ if (F->prev()) {
+ F=F->prev();
+ autoslice_cache.erase(F->next());
+ } else {
+ queue_erase = true;
+ //Cant delete the first rect in the list.
+ }
+ merged = true;
+ }
+ }
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ Rect2 new_rect(x,y,1,1);
+ autoslice_cache.push_back(new_rect);
+ }
+ }
+ }
+ }
+ }
+
+
+ if(node_sprite )
+ rect = node_sprite->get_region_rect();
+ else if(node_patch9 )
+ rect = node_patch9->get_region_rect();
+ else if(obj_styleBox.is_valid())
+ rect = obj_styleBox->get_region_rect();
+ else if (atlas_tex.is_valid())
+ rect = atlas_tex->get_region();
+
+ edit_draw->update();
+}
+
+inline float _snap_scalar(float p_offset, float p_step, float separation, float p_target) {
+ if (p_step != 0) {
+ float a = Math::stepify(p_target - p_offset, p_step+separation) + p_offset;
+ float b = a;
+ if (p_target >= 0)
+ b -= separation;
+ else
+ b += p_step;
+ return (Math::abs(p_target-a) < Math::abs(p_target-b)) ? a : b;
+ }
+ return p_target;
+}
+
+Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
+ if (snap_mode == SNAP_GRID) {
+ p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_separation.x, p_target.x);
+ p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_separation.y, p_target.y);
+ }
+
+ return p_target;
+}
+
+TextureRegionEditor::TextureRegionEditor(EditorNode* p_editor)
+{
+ node_sprite = NULL;
+ node_patch9 = NULL;
+ obj_styleBox = Ref<StyleBoxTexture>(NULL);
+ atlas_tex = Ref<AtlasTexture>(NULL);
+ editor=p_editor;
+ undo_redo = editor->get_undo_redo();
+
+ snap_step=Vector2(10,10);
+ snap_separation = Vector2(0,0);
+ edited_margin = -1;
+ drag_index = -1;
+ drag=false;
+
+ VBoxContainer *main_vb = memnew( VBoxContainer );
+ add_child(main_vb);
+ main_vb->set_area_as_parent_rect(0);
+ HBoxContainer *hb_tools = memnew( HBoxContainer );
+ main_vb->add_child(hb_tools);
+
+ hb_tools->add_child(memnew( Label(TTR("Snap Mode:")) ));
+
+ snap_mode_button = memnew( MenuButton );
+ hb_tools->add_child(snap_mode_button);
+ snap_mode_button->set_text(TTR("<None>"));
+ PopupMenu *p = snap_mode_button->get_popup();
+ p->add_item(TTR("<None>"),0);
+ p->add_item(TTR("Pixel Snap"),1);
+ p->add_item(TTR("Grid Snap"),2);
+ p->add_item(TTR("Auto Slice"),3);
+ for (int i = 0; i < 4; i++)
+ p->set_item_as_checkable(i,true);
+ p->set_item_checked(0,true);
+ p->connect("id_pressed", this, "_set_snap_mode");
+ hb_grid = memnew( HBoxContainer );
+ hb_tools->add_child(hb_grid);
+ hb_grid->add_child( memnew( VSeparator ));
+
+ hb_grid->add_child( memnew( Label(TTR("Offset:")) ) );
+
+ sb_off_x = memnew( SpinBox );
+ sb_off_x->set_min(-256);
+ sb_off_x->set_max(256);
+ sb_off_x->set_step(1);
+ sb_off_x->set_value(snap_offset.x);
+ sb_off_x->set_suffix("px");
+ sb_off_x->connect("value_changed", this, "_set_snap_off_x");
+ hb_grid->add_child(sb_off_x);
+
+ sb_off_y = memnew( SpinBox );
+ sb_off_y->set_min(-256);
+ sb_off_y->set_max(256);
+ sb_off_y->set_step(1);
+ sb_off_y->set_value(snap_offset.y);
+ sb_off_y->set_suffix("px");
+ sb_off_y->connect("value_changed", this, "_set_snap_off_y");
+ hb_grid->add_child(sb_off_y);
+
+ hb_grid->add_child( memnew( VSeparator ));
+ hb_grid->add_child( memnew( Label(TTR("Step:")) ) );
+
+ sb_step_x = memnew( SpinBox );
+ sb_step_x->set_min(-256);
+ sb_step_x->set_max(256);
+ sb_step_x->set_step(1);
+ sb_step_x->set_value(snap_step.x);
+ sb_step_x->set_suffix("px");
+ sb_step_x->connect("value_changed", this, "_set_snap_step_x");
+ hb_grid->add_child(sb_step_x);
+
+ sb_step_y = memnew( SpinBox );
+ sb_step_y->set_min(-256);
+ sb_step_y->set_max(256);
+ sb_step_y->set_step(1);
+ sb_step_y->set_value(snap_step.y);
+ sb_step_y->set_suffix("px");
+ sb_step_y->connect("value_changed", this, "_set_snap_step_y");
+ hb_grid->add_child(sb_step_y);
+
+ hb_grid->add_child( memnew( VSeparator ));
+ hb_grid->add_child( memnew( Label(TTR("Separation:")) ) );
+
+ sb_sep_x = memnew( SpinBox );
+ sb_sep_x->set_min(0);
+ sb_sep_x->set_max(256);
+ sb_sep_x->set_step(1);
+ sb_sep_x->set_value(snap_separation.x);
+ sb_sep_x->set_suffix("px");
+ sb_sep_x->connect("value_changed", this, "_set_snap_sep_x");
+ hb_grid->add_child(sb_sep_x);
+
+ sb_sep_y = memnew( SpinBox );
+ sb_sep_y->set_min(0);
+ sb_sep_y->set_max(256);
+ sb_sep_y->set_step(1);
+ sb_sep_y->set_value(snap_separation.y);
+ sb_sep_y->set_suffix("px");
+ sb_sep_y->connect("value_changed", this, "_set_snap_sep_y");
+ hb_grid->add_child(sb_sep_y);
+
+ hb_grid->hide();
+
+ HBoxContainer *main_hb = memnew( HBoxContainer );
+ main_vb->add_child(main_hb);
+ edit_draw = memnew( Control );
+ main_hb->add_child(edit_draw);
+ main_hb->set_v_size_flags(SIZE_EXPAND_FILL);
+ edit_draw->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ Control * separator = memnew( Control );
+ separator->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb_tools->add_child(separator);
+
+ icon_zoom = memnew( TextureRect );
+ hb_tools->add_child(icon_zoom);
+
+ zoom_out = memnew( ToolButton );
+ zoom_out->connect("pressed", this, "_zoom_out");
+ hb_tools->add_child(zoom_out);
+
+ zoom_reset = memnew( ToolButton );
+ zoom_reset->connect("pressed", this, "_zoom_reset");
+ hb_tools->add_child(zoom_reset);
+
+ zoom_in = memnew( ToolButton );
+ zoom_in->connect("pressed", this, "_zoom_in");
+ hb_tools->add_child(zoom_in);
+
+ vscroll = memnew( VScrollBar);
+ main_hb->add_child(vscroll);
+ vscroll->connect("value_changed",this,"_scroll_changed");
+ hscroll = memnew( HScrollBar );
+ main_vb->add_child(hscroll);
+ hscroll->connect("value_changed",this,"_scroll_changed");
+
+ edit_draw->connect("draw",this,"_region_draw");
+ edit_draw->connect("gui_input",this,"_region_input");
+ draw_zoom=1.0;
+ updating_scroll=false;
+
+ edit_draw->set_clip_contents(true);
+
+}
+
+void TextureRegionEditorPlugin::edit(Object *p_node)
+{
+ region_editor->edit(p_node);
+}
+
+bool TextureRegionEditorPlugin::handles(Object *p_obj) const
+{
+ return p_obj->is_class("Sprite") || p_obj->is_class("Patch9Rect") || p_obj->is_class("StyleBoxTexture") || p_obj->is_class("AtlasTexture");
+}
+
+void TextureRegionEditorPlugin::make_visible(bool p_visible)
+{
+ if (p_visible) {
+ region_button->show();
+ if (region_button->is_pressed())
+ region_editor->show();
+ } else {
+ region_button->hide();
+ region_editor->edit(NULL);
+ region_editor->hide();
+ }
+}
+
+
+Dictionary TextureRegionEditorPlugin::get_state() const {
+
+ Dictionary state;
+ state["zoom"]=region_editor->draw_zoom;
+ state["snap_offset"]=region_editor->snap_offset;
+ state["snap_step"]=region_editor->snap_step;
+ state["snap_separation"]=region_editor->snap_separation;
+ state["snap_mode"]=region_editor->snap_mode;
+ return state;
+}
+
+void TextureRegionEditorPlugin::set_state(const Dictionary& p_state){
+
+ Dictionary state=p_state;
+ if (state.has("zoom")) {
+ region_editor->draw_zoom = p_state["zoom"];
+ }
+
+ if (state.has("snap_step")) {
+ Vector2 s = state["snap_step"];
+ region_editor->sb_step_x->set_value(s.x);
+ region_editor->sb_step_y->set_value(s.y);
+ region_editor->snap_step = s;
+ }
+
+ if (state.has("snap_offset")) {
+ Vector2 ofs = state["snap_offset"];
+ region_editor->sb_off_x->set_value(ofs.x);
+ region_editor->sb_off_y->set_value(ofs.y);
+ region_editor->snap_offset = ofs;
+ }
+
+ if (state.has("snap_separation")) {
+ Vector2 sep = state["snap_separation"];
+ region_editor->sb_sep_x->set_value(sep.x);
+ region_editor->sb_sep_y->set_value(sep.y);
+ region_editor->snap_separation = sep;
+ }
+
+ if (state.has("snap_mode")) {
+ region_editor->_set_snap_mode(state["snap_mode"]);
+ }
+
+}
+
+TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node)
+{
+ editor = p_node;
+ region_editor = memnew ( TextureRegionEditor(p_node) );
+
+ region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), region_editor);
+ region_button->set_tooltip(TTR("Texture Region Editor"));
+
+ region_editor->set_custom_minimum_size(Size2(0,200));
+ region_editor->hide();
+ region_button->hide();
+}
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
new file mode 100644
index 0000000000..8e88f0b707
--- /dev/null
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -0,0 +1,153 @@
+/*************************************************************************/
+/* texture_region_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Author: Mariano Suligoy */
+/* */
+/* 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 TEXTURE_REGION_EDITOR_PLUGIN_H
+#define TEXTURE_REGION_EDITOR_PLUGIN_H
+
+#include "canvas_item_editor_plugin.h"
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+#include "scene/2d/sprite.h"
+#include "scene/gui/patch_9_rect.h"
+#include "scene/resources/style_box.h"
+#include "scene/resources/texture.h"
+
+class TextureRegionEditor : public Control {
+
+ GDCLASS(TextureRegionEditor, Control );
+
+ enum SnapMode {
+ SNAP_NONE,
+ SNAP_PIXEL,
+ SNAP_GRID,
+ SNAP_AUTOSLICE
+ };
+
+ friend class TextureRegionEditorPlugin;
+ MenuButton *snap_mode_button;
+ TextureRect *icon_zoom;
+ ToolButton *zoom_in;
+ ToolButton *zoom_reset;
+ ToolButton *zoom_out;
+ HBoxContainer * hb_grid; //For showing/hiding the grid controls when changing the SnapMode
+ SpinBox *sb_step_y;
+ SpinBox *sb_step_x;
+ SpinBox *sb_off_y;
+ SpinBox *sb_off_x;
+ SpinBox *sb_sep_y;
+ SpinBox *sb_sep_x;
+ Control *edit_draw;
+
+ VScrollBar *vscroll;
+ HScrollBar *hscroll;
+
+ EditorNode *editor;
+ UndoRedo* undo_redo;
+
+ Vector2 draw_ofs;
+ float draw_zoom;
+ bool updating_scroll;
+
+ int snap_mode;
+ Vector2 snap_offset;
+ Vector2 snap_step;
+ Vector2 snap_separation;
+
+ NinePatchRect *node_patch9;
+ Sprite *node_sprite;
+ Ref<StyleBoxTexture> obj_styleBox;
+ Ref<AtlasTexture> atlas_tex;
+
+ Rect2 rect;
+ Rect2 rect_prev;
+ float prev_margin;
+ int edited_margin;
+ List<Rect2> autoslice_cache;
+
+ bool drag;
+ bool creating;
+ Vector2 drag_from;
+ int drag_index;
+
+ void _set_snap_mode(int p_mode);
+ void _set_snap_off_x(float p_val);
+ void _set_snap_off_y(float p_val);
+ void _set_snap_step_x(float p_val);
+ void _set_snap_step_y(float p_val);
+ void _set_snap_sep_x(float p_val);
+ void _set_snap_sep_y(float p_val);
+ void _zoom_in();
+ void _zoom_reset();
+ void _zoom_out();
+ void apply_rect(const Rect2& rect);
+protected:
+
+ void _notification(int p_what);
+ void _node_removed(Object *p_obj);
+ static void _bind_methods();
+
+ Vector2 snap_point(Vector2 p_target) const;
+
+ virtual void _changed_callback(Object *p_changed, const char *p_prop);
+
+public:
+
+ void _edit_region();
+ void _region_draw();
+ void _region_input(const InputEvent &p_input);
+ void _scroll_changed(float);
+
+ void edit(Object *p_obj);
+ TextureRegionEditor(EditorNode* p_editor);
+
+};
+
+class TextureRegionEditorPlugin : public EditorPlugin
+{
+ GDCLASS( TextureRegionEditorPlugin, EditorPlugin );
+
+ Button *region_button;
+ TextureRegionEditor *region_editor;
+ EditorNode *editor;
+public:
+
+ virtual String get_name() const { return "TextureRegion"; }
+ 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;
+
+ TextureRegionEditorPlugin(EditorNode *p_node);
+};
+
+#endif // TEXTURE_REGION_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 4b8fea5a45..4b8fea5a45 100644
--- a/tools/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
new file mode 100644
index 0000000000..f661da4cd5
--- /dev/null
+++ b/editor/plugins/theme_editor_plugin.h
@@ -0,0 +1,125 @@
+/*************************************************************************/
+/* theme_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 THEME_EDITOR_PLUGIN_H
+#define THEME_EDITOR_PLUGIN_H
+
+#include "scene/resources/theme.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/button_group.h"
+#include "scene/gui/scroll_container.h"
+
+#include "editor/editor_node.h"
+
+
+
+
+class ThemeEditor : public Control {
+
+ GDCLASS( ThemeEditor, Control );
+
+
+ ScrollContainer *scroll;
+ VBoxContainer *main_vb;
+ Ref<Theme> theme;
+
+ EditorFileDialog *file_dialog;
+
+ double time_left;
+
+ MenuButton *theme_menu;
+ ConfirmationDialog *add_del_dialog;
+ MenuButton *type_menu;
+ LineEdit *type_edit;
+ MenuButton *name_menu;
+ LineEdit *name_edit;
+ OptionButton *type_select;
+ Label * type_select_label;
+ Label * name_select_label;
+ Label * dtype_select_label;
+
+ enum PopupMode {
+ POPUP_ADD,
+ POPUP_CLASS_ADD,
+ POPUP_REMOVE,
+ POPUP_CLASS_REMOVE,
+ POPUP_CREATE_EMPTY,
+ POPUP_CREATE_EDITOR_EMPTY
+ };
+
+ int popup_mode;
+
+ Tree *test_tree;
+
+ void _save_template_cbk(String fname);
+ void _dialog_cbk();
+ void _type_menu_cbk(int p_option);
+ void _name_menu_about_to_show();
+ void _name_menu_cbk(int p_option);
+ void _theme_menu_cbk(int p_option);
+ void _propagate_redraw(Control *p_at);
+ void _refresh_interval();
+
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void edit(const Ref<Theme>& p_theme);
+
+ ThemeEditor();
+};
+
+
+
+class ThemeEditorPlugin : public EditorPlugin {
+
+ GDCLASS( ThemeEditorPlugin, EditorPlugin );
+
+ ThemeEditor *theme_editor;
+ EditorNode *editor;
+ Button *button;
+
+public:
+
+ virtual String get_name() const { return "Theme"; }
+ 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);
+
+ ThemeEditorPlugin(EditorNode *p_node);
+
+};
+
+
+#endif // THEME_EDITOR_PLUGIN_H
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
new file mode 100644
index 0000000000..fb6d5a786a
--- /dev/null
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -0,0 +1,1593 @@
+/*************************************************************************/
+/* tile_map_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "tile_map_editor_plugin.h"
+
+#include "os/keyboard.h"
+#include "os/input.h"
+#include "canvas_item_editor_plugin.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_scale.h"
+
+void TileMapEditor::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_ENTER_TREE: {
+
+ transp->set_icon(get_icon("Transpose","EditorIcons"));
+ mirror_x->set_icon(get_icon("MirrorX","EditorIcons"));
+ mirror_y->set_icon(get_icon("MirrorY","EditorIcons"));
+ rotate_0->set_icon(get_icon("Rotate0","EditorIcons"));
+ rotate_90->set_icon(get_icon("Rotate90","EditorIcons"));
+ rotate_180->set_icon(get_icon("Rotate180","EditorIcons"));
+ rotate_270->set_icon(get_icon("Rotate270","EditorIcons"));
+
+ } break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+
+ if (is_visible_in_tree()) {
+ _update_palette();
+ }
+ } break;
+ }
+}
+
+void TileMapEditor::_menu_option(int p_option) {
+
+ switch(p_option) {
+
+ case OPTION_BUCKET: {
+
+ tool=TOOL_BUCKET;
+
+ canvas_item_editor->update();
+ } break;
+ case OPTION_PICK_TILE: {
+
+ tool=TOOL_PICKING;
+
+ canvas_item_editor->update();
+ } break;
+ case OPTION_SELECT: {
+
+ tool=TOOL_SELECTING;
+ selection_active=false;
+
+ canvas_item_editor->update();
+ } break;
+ case OPTION_DUPLICATE: {
+
+ _update_copydata();
+
+ if (selection_active) {
+ tool=TOOL_DUPLICATING;
+
+ canvas_item_editor->update();
+ }
+ } break;
+ case OPTION_ERASE_SELECTION: {
+
+ if (!selection_active)
+ return;
+
+ undo_redo->create_action("Erase Selection");
+ for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
+ for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
+
+ _set_cell(Point2i(j, i), TileMap::INVALID_CELL, false, false, false, true);
+ }
+ }
+ undo_redo->commit_action();
+
+ selection_active=false;
+ copydata.clear();
+
+ canvas_item_editor->update();
+ } break;
+ }
+}
+
+void TileMapEditor::_canvas_mouse_enter() {
+
+ mouse_over=true;
+ canvas_item_editor->update();
+}
+
+void TileMapEditor::_canvas_mouse_exit() {
+
+ mouse_over=false;
+ canvas_item_editor->update();
+}
+
+int TileMapEditor::get_selected_tile() const {
+
+ int item = palette->get_current();
+
+ if (item==-1)
+ return TileMap::INVALID_CELL;
+
+ return palette->get_item_metadata(item);
+}
+
+void TileMapEditor::set_selected_tile(int p_tile) {
+
+ int idx = palette->find_metadata(p_tile);
+
+ if (idx >= 0) {
+ palette->select(idx, true);
+ palette->ensure_current_is_visible();
+ }
+}
+
+void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose,bool p_with_undo) {
+
+ ERR_FAIL_COND(!node);
+
+ int prev_val=node->get_cell(p_pos.x,p_pos.y);
+
+ bool prev_flip_h=node->is_cell_x_flipped(p_pos.x,p_pos.y);
+ bool prev_flip_v=node->is_cell_y_flipped(p_pos.x,p_pos.y);
+ bool prev_transpose=node->is_cell_transposed(p_pos.x,p_pos.y);
+
+ if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_flip_v && p_transpose==prev_transpose)
+ return; //check that it's actually different
+
+ if (p_with_undo) {
+
+ undo_redo->add_do_method(node,"set_cellv",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose);
+ undo_redo->add_undo_method(node,"set_cellv",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose);
+ } else {
+
+ node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose);
+ }
+
+}
+
+void TileMapEditor::_text_entered(const String& p_text) {
+
+ canvas_item_editor->grab_focus();
+}
+
+void TileMapEditor::_text_changed(const String& p_text) {
+
+ _update_palette();
+}
+
+void TileMapEditor::_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 ) ) {
+
+ palette->call("_gui_input", p_ie);
+ search_box->accept_event();
+ }
+}
+
+void TileMapEditor::_update_palette() {
+
+ if (!node)
+ return;
+
+ int selected = get_selected_tile();
+ palette->clear();
+
+ Ref<TileSet> tileset=node->get_tileset();
+ if (tileset.is_null())
+ return;
+
+ List<int> tiles;
+ tileset->get_tile_list(&tiles);
+
+ if (tiles.empty())
+ return;
+
+ float min_size = EDITOR_DEF("editors/tile_map/preview_size", 64);
+ min_size *= EDSCALE;
+ int hseparation = EDITOR_DEF("editors/tile_map/palette_item_hseparation",8);
+ bool show_tile_names = bool(EDITOR_DEF("editors/tile_map/show_tile_names", true));
+
+ palette->add_constant_override("hseparation", hseparation*EDSCALE);
+ palette->add_constant_override("vseparation", 8*EDSCALE);
+
+ palette->set_fixed_icon_size(Size2(min_size, min_size));
+ palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1));
+
+ String filter = search_box->get_text().strip_edges();
+
+ for (List<int>::Element *E=tiles.front();E;E=E->next()) {
+
+ String name;
+
+ if (tileset->tile_get_name(E->get())!="") {
+ name = itos(E->get())+" - "+tileset->tile_get_name(E->get());
+ } else {
+ name = "#"+itos(E->get());
+ }
+
+ if (filter != "" && !filter.is_subsequence_ofi(name))
+ continue;
+
+ if (show_tile_names) {
+ palette->add_item(name);
+ } else {
+ palette->add_item(String());
+ }
+
+ Ref<Texture> tex = tileset->tile_get_texture(E->get());
+
+ if (tex.is_valid()) {
+ Rect2 region = tileset->tile_get_region(E->get());
+
+ if (!region.has_no_area())
+ palette->set_item_icon_region(palette->get_item_count()-1, region);
+
+ palette->set_item_icon(palette->get_item_count()-1, tex);
+ }
+
+ palette->set_item_metadata(palette->get_item_count()-1, E->get());
+ }
+
+ palette->set_same_column_width(true);
+
+ if (selected != -1)
+ set_selected_tile(selected);
+ else
+ palette->select(0);
+}
+
+void TileMapEditor::_pick_tile(const Point2& p_pos) {
+
+ int id = node->get_cell(p_pos.x, p_pos.y);
+
+ if (id==TileMap::INVALID_CELL)
+ return;
+
+ if (search_box->get_text().strip_edges() != "") {
+
+ search_box->set_text("");
+ _update_palette();
+ }
+
+ set_selected_tile(id);
+
+ mirror_x->set_pressed(node->is_cell_x_flipped(p_pos.x, p_pos.y));
+ mirror_y->set_pressed(node->is_cell_y_flipped(p_pos.x, p_pos.y));
+ transp->set_pressed(node->is_cell_transposed(p_pos.x, p_pos.y));
+
+ _update_transform_buttons();
+ canvas_item_editor->update();
+}
+
+PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase, bool preview) {
+
+ int prev_id = node->get_cell(p_start.x, p_start.y);
+ int id = TileMap::INVALID_CELL;
+ if (!erase) {
+ id = get_selected_tile();
+
+ if (id == TileMap::INVALID_CELL)
+ return PoolVector<Vector2>();
+ }
+
+ Rect2i r = node->get_item_rect();
+ r.pos = r.pos/node->get_cell_size();
+ r.size = r.size/node->get_cell_size();
+
+ int area = r.get_area();
+ if(preview) {
+ // Test if we can re-use the result from preview bucket fill
+ bool invalidate_cache = false;
+ // Area changed
+ if(r != bucket_cache_rect)
+ _clear_bucket_cache();
+ // Cache grid is not initialized
+ if(bucket_cache_visited == 0) {
+ bucket_cache_visited = new bool[area];
+ invalidate_cache = true;
+ }
+ // Tile ID changed or position wasn't visited by the previous fill
+ int loc = (p_start.x - r.get_pos().x) + (p_start.y - r.get_pos().y) * r.get_size().x;
+ if(prev_id != bucket_cache_tile || !bucket_cache_visited[loc]) {
+ invalidate_cache = true;
+ }
+ if(invalidate_cache) {
+ for(int i = 0; i < area; ++i)
+ bucket_cache_visited[i] = false;
+ bucket_cache = PoolVector<Vector2>();
+ bucket_cache_tile = prev_id;
+ bucket_cache_rect = r;
+ }
+ else {
+ return bucket_cache;
+ }
+ }
+
+ PoolVector<Vector2> points;
+
+ List<Point2i> queue;
+ queue.push_back(p_start);
+
+ while (queue.size()) {
+
+ Point2i n = queue.front()->get();
+ queue.pop_front();
+
+ if (!r.has_point(n))
+ continue;
+
+ if (node->get_cell(n.x, n.y) == prev_id) {
+
+ if(preview) {
+ int loc = (n.x - r.get_pos().x) + (n.y - r.get_pos().y) * r.get_size().x;
+ if(bucket_cache_visited[loc])
+ continue;
+ bucket_cache_visited[loc] = true;
+ bucket_cache.push_back(n);
+ }
+ else {
+ node->set_cellv(n, id, flip_h, flip_v, transpose);
+ points.push_back(n);
+ }
+
+ queue.push_back(n + Point2i(0, 1));
+ queue.push_back(n + Point2i(0, -1));
+ queue.push_back(n + Point2i(1, 0));
+ queue.push_back(n + Point2i(-1, 0));
+ }
+ }
+
+ return preview ? bucket_cache : points;
+}
+
+void TileMapEditor::_fill_points(const PoolVector<Vector2> p_points, const Dictionary& p_op) {
+
+ int len = p_points.size();
+ PoolVector<Vector2>::Read pr = p_points.read();
+
+ int id = p_op["id"];
+ bool xf = p_op["flip_h"];
+ bool yf = p_op["flip_v"];
+ bool tr = p_op["transpose"];
+
+ for (int i=0;i<len;i++) {
+
+ _set_cell(pr[i], id, xf, yf, tr);
+ }
+}
+
+void TileMapEditor::_erase_points(const PoolVector<Vector2> p_points) {
+
+ int len = p_points.size();
+ PoolVector<Vector2>::Read pr = p_points.read();
+
+ for (int i=0;i<len;i++) {
+
+ _set_cell(pr[i], TileMap::INVALID_CELL);
+ }
+}
+
+void TileMapEditor::_select(const Point2i& p_from, const Point2i& p_to) {
+
+ Point2i begin=p_from;
+ Point2i end=p_to;
+
+ if (begin.x > end.x) {
+
+ SWAP( begin.x, end.x);
+ }
+ if (begin.y > end.y) {
+
+ SWAP( begin.y, end.y);
+ }
+
+ rectangle.pos=begin;
+ rectangle.size=end-begin;
+
+ canvas_item_editor->update();
+}
+
+void TileMapEditor::_draw_cell(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform) {
+
+ Ref<Texture> t = node->get_tileset()->tile_get_texture(p_cell);
+
+ if (t.is_null())
+ return;
+
+ Vector2 tile_ofs = node->get_tileset()->tile_get_texture_offset(p_cell);
+
+ Rect2 r = node->get_tileset()->tile_get_region(p_cell);
+ Size2 sc = p_xform.get_scale();
+
+ Rect2 rect = Rect2();
+ rect.pos = node->map_to_world(p_point) + node->get_cell_draw_offset();
+
+ if (r.has_no_area()) {
+ rect.size = t->get_size();
+ } else {
+ rect.size = r.size;
+ }
+
+ if (rect.size.y > rect.size.x) {
+ if ((p_flip_h && (p_flip_v || p_transpose)) || (p_flip_v && !p_transpose))
+ tile_ofs.y += rect.size.y - rect.size.x;
+ } else if (rect.size.y < rect.size.x) {
+ if ((p_flip_v && (p_flip_h || p_transpose)) || (p_flip_h && !p_transpose))
+ tile_ofs.x += rect.size.x - rect.size.y;
+ }
+
+ if (p_transpose) {
+ SWAP(tile_ofs.x, tile_ofs.y);
+ }
+ if (p_flip_h) {
+ sc.x*=-1.0;
+ tile_ofs.x*=-1.0;
+ }
+ if (p_flip_v) {
+ sc.y*=-1.0;
+ tile_ofs.y*=-1.0;
+ }
+
+ if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) {
+
+ rect.pos+=tile_ofs;
+ } else if (node->get_tile_origin()==TileMap::TILE_ORIGIN_BOTTOM_LEFT) {
+ Size2 cell_size = node->get_cell_size();
+
+ rect.pos+=tile_ofs;
+
+ if(p_transpose)
+ {
+ if(p_flip_h)
+ rect.pos.x-=cell_size.x;
+ else
+ rect.pos.x+=cell_size.x;
+ } else {
+ if(p_flip_v)
+ rect.pos.y-=cell_size.y;
+ else
+ rect.pos.y+=cell_size.y;
+ }
+
+ } 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) - tile_ofs;
+
+ if (p_flip_h)
+ rect.pos.x-=s.x-center.x;
+ else
+ rect.pos.x-=center.x;
+
+ if (p_flip_v)
+ rect.pos.y-=s.y-center.y;
+ else
+ rect.pos.y-=center.y;
+ }
+
+ rect.pos=p_xform.xform(rect.pos);
+ rect.size*=sc;
+
+ if (r.has_no_area())
+ canvas_item_editor->draw_texture_rect(t, rect, false, Color(1,1,1,0.5), p_transpose);
+ else
+ canvas_item_editor->draw_texture_rect_region(t, rect, r, Color(1,1,1,0.5), p_transpose);
+}
+
+void TileMapEditor::_draw_fill_preview(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform) {
+
+ PoolVector<Vector2> points = _bucket_fill(p_point, false, true);
+ PoolVector<Vector2>::Read pr = points.read();
+ int len = points.size();
+ int time_after = OS::get_singleton()->get_ticks_msec();
+
+ for(int i = 0; i < len; ++i) {
+ _draw_cell(p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform);
+ }
+}
+
+void TileMapEditor::_clear_bucket_cache() {
+ if(bucket_cache_visited) {
+ delete[] bucket_cache_visited;
+ bucket_cache_visited = 0;
+ }
+}
+
+void TileMapEditor::_update_copydata() {
+
+ copydata.clear();
+
+ if (!selection_active)
+ return;
+
+ for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
+
+ for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
+
+ TileData tcd;
+
+ tcd.cell=node->get_cell(j, i);
+
+ if (tcd.cell!=TileMap::INVALID_CELL) {
+ tcd.pos=Point2i(j, i);
+ tcd.flip_h=node->is_cell_x_flipped(j,i);
+ tcd.flip_v=node->is_cell_y_flipped(j,i);
+ tcd.transpose=node->is_cell_transposed(j,i);
+ }
+
+ copydata.push_back(tcd);
+ }
+ }
+}
+
+static inline Vector<Point2i> line(int x0, int x1, int y0, int y1) {
+
+ Vector<Point2i> points;
+
+ float dx = ABS(x1 - x0);
+ float dy = ABS(y1 - y0);
+
+ int x = x0;
+ int y = y0;
+
+ int sx = x0 > x1 ? -1 : 1;
+ int sy = y0 > y1 ? -1 : 1;
+
+ if (dx > dy) {
+ float err = dx/2;
+
+ for (; x != x1; x += sx) {
+ points.push_back(Vector2(x, y));
+
+ err -= dy;
+ if (err < 0) {
+ y += sy;
+ err += dx;
+ }
+ }
+ } else {
+ float err = dy/2;
+
+ for (; y != y1; y += sy) {
+ points.push_back(Vector2(x, y));
+
+ err -= dx;
+ if (err < 0) {
+ x += sx;
+ err += dy;
+ }
+ }
+ }
+
+ points.push_back(Vector2(x, y));
+
+ return points;
+}
+
+bool TileMapEditor::forward_gui_input(const InputEvent& p_event) {
+
+ if (!node || !node->get_tileset().is_valid() || !node->is_visible_in_tree())
+ return false;
+
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
+ Transform2D xform_inv = xform.affine_inverse();
+
+ switch(p_event.type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+ const InputEventMouseButton &mb=p_event.mouse_button;
+
+ if (mb.button_index==BUTTON_LEFT) {
+
+ if (mb.pressed) {
+
+ if (Input::get_singleton()->is_key_pressed(KEY_SPACE))
+ return false; //drag
+
+ if (tool==TOOL_NONE) {
+
+ if (mb.mod.shift) {
+
+ if (mb.mod.control)
+ tool=TOOL_RECTANGLE_PAINT;
+ else
+ tool=TOOL_LINE_PAINT;
+
+ selection_active=false;
+ rectangle_begin=over_tile;
+
+ return true;
+ }
+
+ if (mb.mod.control) {
+
+ tool=TOOL_PICKING;
+ _pick_tile(over_tile);
+
+ return true;
+ }
+
+ tool=TOOL_PAINTING;
+ }
+
+ if (tool==TOOL_PAINTING) {
+
+ int id = get_selected_tile();
+
+ if (id!=TileMap::INVALID_CELL) {
+
+ tool=TOOL_PAINTING;
+
+ paint_undo.clear();
+ paint_undo[over_tile]=_get_op_from_cell(over_tile);
+
+ _set_cell(over_tile, id, flip_h, flip_v, transpose);
+ }
+ } else if (tool==TOOL_PICKING) {
+
+ _pick_tile(over_tile);
+ } else if (tool==TOOL_SELECTING) {
+
+ selection_active=true;
+ rectangle_begin=over_tile;
+ }
+
+ return true;
+
+ } else {
+
+ if (tool!=TOOL_NONE) {
+
+ if (tool==TOOL_PAINTING) {
+
+ int id=get_selected_tile();
+
+ if (id!=TileMap::INVALID_CELL && paint_undo.size()) {
+
+ undo_redo->create_action(TTR("Paint TileMap"));
+ for (Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
+
+ Point2 p=E->key();
+ undo_redo->add_do_method(node,"set_cellv",p,id,flip_h,flip_v,transpose);
+ undo_redo->add_undo_method(node,"set_cellv",p,E->get().idx,E->get().xf,E->get().yf,E->get().tr);
+ }
+ undo_redo->commit_action();
+
+ paint_undo.clear();
+ }
+ } else if (tool==TOOL_LINE_PAINT) {
+
+ int id=get_selected_tile();
+
+ if (id!=TileMap::INVALID_CELL) {
+
+ undo_redo->create_action("Line Draw");
+ for (Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
+
+ _set_cell(E->key(), id, flip_h, flip_v, transpose, true);
+ }
+ undo_redo->commit_action();
+
+ paint_undo.clear();
+
+ canvas_item_editor->update();
+ }
+ } else if (tool==TOOL_RECTANGLE_PAINT) {
+
+ int id=get_selected_tile();
+
+ if (id!=TileMap::INVALID_CELL) {
+
+ undo_redo->create_action("Rectangle Paint");
+ for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
+ for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
+
+ _set_cell(Point2i(j, i), id, flip_h, flip_v, transpose, true);
+ }
+ }
+ undo_redo->commit_action();
+
+ canvas_item_editor->update();
+ }
+ } else if (tool==TOOL_DUPLICATING) {
+
+ Point2 ofs = over_tile-rectangle.pos;
+
+ undo_redo->create_action(TTR("Duplicate"));
+ for (List<TileData>::Element *E=copydata.front();E;E=E->next()) {
+
+ _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,E->get().transpose,true);
+ }
+ undo_redo->commit_action();
+
+ copydata.clear();
+
+ canvas_item_editor->update();
+
+ } else if (tool==TOOL_SELECTING) {
+
+ canvas_item_editor->update();
+
+ } else if (tool==TOOL_BUCKET) {
+
+ Dictionary pop;
+ pop["id"] = node->get_cell(over_tile.x, over_tile.y);
+ pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
+ pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
+ pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
+
+ PoolVector<Vector2> points = _bucket_fill(over_tile);
+
+ if (points.size() == 0)
+ return false;
+
+ Dictionary op;
+ op["id"] = get_selected_tile();
+ op["flip_h"] = flip_h;
+ op["flip_v"] = flip_v;
+ op["transpose"] = transpose;
+
+ undo_redo->create_action("Bucket Fill");
+
+ undo_redo->add_do_method(this, "_fill_points", points, op);
+ undo_redo->add_undo_method(this, "_fill_points", points, pop);
+
+ undo_redo->commit_action();
+ }
+
+ tool=TOOL_NONE;
+
+ return true;
+ }
+ }
+ } else if (mb.button_index==BUTTON_RIGHT) {
+
+ if (mb.pressed) {
+
+ if (tool==TOOL_SELECTING || selection_active) {
+
+ tool=TOOL_NONE;
+ selection_active=false;
+
+ canvas_item_editor->update();
+
+ return true;
+ }
+
+ if (tool==TOOL_DUPLICATING) {
+
+ tool=TOOL_NONE;
+ copydata.clear();
+
+ canvas_item_editor->update();
+
+ return true;
+ }
+
+ if (tool==TOOL_NONE) {
+
+ paint_undo.clear();
+
+ Point2 local = node->world_to_map(xform_inv.xform(Point2(mb.x, mb.y)));
+
+ if (mb.mod.shift) {
+
+ if (mb.mod.control)
+ tool=TOOL_RECTANGLE_ERASE;
+ else
+ tool=TOOL_LINE_ERASE;
+
+ selection_active=false;
+ rectangle_begin=local;
+ } else {
+
+ tool=TOOL_ERASING;
+
+ paint_undo[local]=_get_op_from_cell(local);
+ _set_cell(local, TileMap::INVALID_CELL);
+ }
+
+ return true;
+ }
+
+ } else {
+ if (tool==TOOL_ERASING || tool==TOOL_RECTANGLE_ERASE || tool==TOOL_LINE_ERASE) {
+
+ if (paint_undo.size()) {
+ undo_redo->create_action(TTR("Erase TileMap"));
+ for (Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
+
+ Point2 p=E->key();
+ undo_redo->add_do_method(node,"set_cellv",p,TileMap::INVALID_CELL,false,false,false);
+ undo_redo->add_undo_method(node,"set_cellv",p,E->get().idx,E->get().xf,E->get().yf,E->get().tr);
+ }
+
+ undo_redo->commit_action();
+ paint_undo.clear();
+ }
+
+ if (tool==TOOL_RECTANGLE_ERASE || tool==TOOL_LINE_ERASE) {
+ canvas_item_editor->update();
+ }
+
+ tool=TOOL_NONE;
+
+ return true;
+
+ } else if (tool==TOOL_BUCKET) {
+
+ Dictionary pop;
+ pop["id"] = node->get_cell(over_tile.x, over_tile.y);
+ pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
+ pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
+ pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
+
+ PoolVector<Vector2> points = _bucket_fill(over_tile, true);
+
+ if (points.size() == 0)
+ return false;
+
+ undo_redo->create_action("Bucket Fill");
+
+ undo_redo->add_do_method(this, "_erase_points", points);
+ undo_redo->add_undo_method(this, "_fill_points", points, pop);
+
+ undo_redo->commit_action();
+ }
+ }
+ }
+ } break;
+ case InputEvent::MOUSE_MOTION: {
+
+ const InputEventMouseMotion &mm=p_event.mouse_motion;
+
+ Point2i new_over_tile = node->world_to_map(xform_inv.xform(Point2(mm.x,mm.y)));
+
+ if (new_over_tile!=over_tile) {
+
+ over_tile=new_over_tile;
+ canvas_item_editor->update();
+ }
+
+ int tile_under = node->get_cell(over_tile.x, over_tile.y);
+ String tile_name = "none";
+
+ if (node->get_tileset()->has_tile(tile_under))
+ tile_name = node->get_tileset()->tile_get_name(tile_under);
+ tile_info->set_text(String::num(over_tile.x)+", "+String::num(over_tile.y)+" ["+tile_name+"]");
+
+ if (tool==TOOL_PAINTING) {
+
+ int id = get_selected_tile();
+ if (id!=TileMap::INVALID_CELL) {
+
+ if (!paint_undo.has(over_tile)) {
+ paint_undo[over_tile]=_get_op_from_cell(over_tile);
+ }
+
+ _set_cell(over_tile, id, flip_h, flip_v, transpose);
+
+ return true;
+ }
+ }
+
+ if (tool==TOOL_SELECTING) {
+
+ _select(rectangle_begin, over_tile);
+
+ return true;
+ }
+
+ if (tool==TOOL_LINE_PAINT || tool==TOOL_LINE_ERASE) {
+
+ int id = get_selected_tile();
+ bool erasing = (tool==TOOL_LINE_ERASE);
+
+ if (erasing && paint_undo.size()) {
+
+ for (Map<Point2i, CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
+
+ _set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
+ }
+ }
+
+ paint_undo.clear();
+
+ if (id!=TileMap::INVALID_CELL) {
+
+ Vector<Point2i> points = line(rectangle_begin.x, over_tile.x, rectangle_begin.y, over_tile.y);
+
+ for (int i=0;i<points.size();i++) {
+
+ paint_undo[points[i]]=_get_op_from_cell(points[i]);
+
+ if (erasing)
+ _set_cell(points[i], TileMap::INVALID_CELL);
+ }
+
+ canvas_item_editor->update();
+ }
+
+ return true;
+ }
+ if (tool==TOOL_RECTANGLE_PAINT || tool==TOOL_RECTANGLE_ERASE) {
+
+ _select(rectangle_begin, over_tile);
+
+ if (tool==TOOL_RECTANGLE_ERASE) {
+
+ if (paint_undo.size()) {
+
+ for (Map<Point2i, CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
+
+ _set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
+ }
+ }
+
+ paint_undo.clear();
+
+ for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
+ for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
+
+ Point2i tile = Point2i(j, i);
+ paint_undo[tile]=_get_op_from_cell(tile);
+
+ _set_cell(tile, TileMap::INVALID_CELL);
+ }
+ }
+ }
+
+ return true;
+ }
+ if (tool==TOOL_ERASING) {
+
+ if (!paint_undo.has(over_tile)) {
+ paint_undo[over_tile]=_get_op_from_cell(over_tile);
+ }
+
+ _set_cell(over_tile, TileMap::INVALID_CELL);
+
+ return true;
+ }
+ if (tool==TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+
+ _pick_tile(over_tile);
+
+ return true;
+ }
+ } break;
+ case InputEvent::KEY: {
+
+ const InputEventKey &k = p_event.key;
+
+ if (!k.pressed)
+ break;
+
+ if (k.scancode==KEY_ESCAPE) {
+
+ if (tool==TOOL_DUPLICATING)
+ copydata.clear();
+ else if (tool==TOOL_SELECTING || selection_active)
+ selection_active=false;
+
+ tool=TOOL_NONE;
+
+ canvas_item_editor->update();
+
+ return true;
+ }
+
+ if (tool!=TOOL_NONE || !mouse_over)
+ return false;
+
+ if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
+ _menu_option(OPTION_ERASE_SELECTION);
+
+ return true;
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/select", p_event)) {
+ tool=TOOL_SELECTING;
+ selection_active=false;
+
+ canvas_item_editor->update();
+
+ return true;
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/duplicate_selection", p_event)) {
+ _update_copydata();
+
+ if (selection_active) {
+ tool=TOOL_DUPLICATING;
+
+ canvas_item_editor->update();
+
+ return true;
+ }
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/find_tile", p_event)) {
+ search_box->select_all();
+ search_box->grab_focus();
+
+ return true;
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/mirror_x", p_event)) {
+ flip_h=!flip_h;
+ mirror_x->set_pressed(flip_h);
+ canvas_item_editor->update();
+ return true;
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/mirror_y", p_event)) {
+ flip_v=!flip_v;
+ mirror_y->set_pressed(flip_v);
+ canvas_item_editor->update();
+ return true;
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) {
+ transpose = !transpose;
+ transp->set_pressed(transpose);
+ canvas_item_editor->update();
+ return true;
+ }
+ } break;
+ }
+
+ return false;
+}
+
+void TileMapEditor::_canvas_draw() {
+
+ if (!node)
+ return;
+
+ Transform2D cell_xf = node->get_cell_transform();
+
+ Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
+ Transform2D xform_inv = xform.affine_inverse();
+
+
+ Size2 screen_size=canvas_item_editor->get_size();
+ {
+ Rect2 aabb;
+ aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
+ aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
+ aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
+ aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
+ Rect2i si=aabb.grow(1.0);
+
+ if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) {
+
+ int max_lines=2000; //avoid crash if size too smal
+
+ for (int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
+
+ Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y)));
+ Vector2 to = xform.xform(node->map_to_world(Vector2(i,si.pos.y+si.size.y+1)));
+
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+ if (max_lines--==0)
+ break;
+ }
+ } else {
+
+ int max_lines=10000; //avoid crash if size too smal
+
+ for (int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
+
+ for (int j=(si.pos.y)-1;j<=(si.pos.y+si.size.y);j++) {
+
+ Vector2 ofs;
+ if (ABS(j)&1) {
+ ofs=cell_xf[0]*0.5;
+ }
+
+ Vector2 from = xform.xform(node->map_to_world(Vector2(i,j),true)+ofs);
+ Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs);
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+
+ if (max_lines--==0)
+ break;
+
+ }
+
+ }
+ }
+
+ int max_lines=10000; //avoid crash if size too smal
+
+ if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) {
+
+ for (int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
+
+ Vector2 from = xform.xform(node->map_to_world(Vector2(si.pos.x,i)));
+ Vector2 to = xform.xform(node->map_to_world(Vector2(si.pos.x+si.size.x+1,i)));
+
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+
+ if (max_lines--==0)
+ break;
+
+ }
+ } else {
+
+
+ for (int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
+
+ for (int j=(si.pos.x)-1;j<=(si.pos.x+si.size.x);j++) {
+
+ Vector2 ofs;
+ if (ABS(j)&1) {
+ ofs=cell_xf[1]*0.5;
+ }
+
+ Vector2 from = xform.xform(node->map_to_world(Vector2(j,i),true)+ofs);
+ Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs);
+ Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+ canvas_item_editor->draw_line(from,to,col,1);
+
+ if (max_lines--==0)
+ break;
+
+ }
+ }
+ }
+ }
+
+ if (selection_active) {
+
+ Vector<Vector2> points;
+ points.push_back( xform.xform( node->map_to_world(( rectangle.pos ) )));
+ points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(rectangle.size.x+1,0)) ) ));
+ points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(rectangle.size.x+1,rectangle.size.y+1)) ) ));
+ points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(0,rectangle.size.y+1)) ) ));
+
+ canvas_item_editor->draw_colored_polygon(points, Color(0.2,0.8,1,0.4));
+ }
+
+ if (mouse_over){
+
+ Vector2 endpoints[4]={
+ node->map_to_world(over_tile, true),
+ node->map_to_world((over_tile+Point2(1,0)), true),
+ node->map_to_world((over_tile+Point2(1,1)), true),
+ node->map_to_world((over_tile+Point2(0,1)), true)
+ };
+
+ for (int i=0;i<4;i++) {
+ if (node->get_half_offset()==TileMap::HALF_OFFSET_X && ABS(over_tile.y)&1)
+ endpoints[i]+=cell_xf[0]*0.5;
+ if (node->get_half_offset()==TileMap::HALF_OFFSET_Y && ABS(over_tile.x)&1)
+ endpoints[i]+=cell_xf[1]*0.5;
+ endpoints[i]=xform.xform(endpoints[i]);
+ }
+ Color col;
+ if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
+ col=Color(0.2,0.8,1.0,0.8);
+ else
+ col=Color(1.0,0.4,0.2,0.8);
+
+ for (int i=0;i<4;i++)
+ canvas_item_editor->draw_line(endpoints[i],endpoints[(i+1)%4],col,2);
+
+
+ bool bucket_preview = EditorSettings::get_singleton()->get("editors/tile_map/bucket_fill_preview");
+ if (tool==TOOL_SELECTING || tool==TOOL_PICKING || !bucket_preview) {
+ return;
+ }
+
+ if (tool==TOOL_LINE_PAINT) {
+
+ if (paint_undo.empty())
+ return;
+
+ int id = get_selected_tile();
+
+ if (id==TileMap::INVALID_CELL)
+ return;
+
+ for (Map<Point2i, CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
+
+ _draw_cell(id, E->key(), flip_h, flip_v, transpose, xform);
+ }
+
+ } else if (tool==TOOL_RECTANGLE_PAINT) {
+
+ int id = get_selected_tile();
+
+ if (id==TileMap::INVALID_CELL)
+ return;
+
+ for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
+ for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
+
+ _draw_cell(id, Point2i(j, i), flip_h, flip_v, transpose, xform);
+ }
+ }
+ } else if (tool==TOOL_DUPLICATING) {
+
+ if (copydata.empty())
+ return;
+
+ Ref<TileSet> ts = node->get_tileset();
+
+ if (ts.is_null())
+ return;
+
+ Point2 ofs = over_tile-rectangle.pos;
+
+ for (List<TileData>::Element *E=copydata.front();E;E=E->next()) {
+
+ if (!ts->has_tile(E->get().cell))
+ continue;
+
+ TileData tcd = E->get();
+
+ _draw_cell(tcd.cell, tcd.pos+ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform);
+ }
+
+ Rect2i duplicate=rectangle;
+ duplicate.pos=over_tile;
+
+ Vector<Vector2> points;
+ points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
+ points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
+ points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1))) ));
+ points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(0,duplicate.size.y+1))) ));
+
+ canvas_item_editor->draw_colored_polygon(points, Color(0.2,1.0,0.8,0.2));
+
+ } else if(tool == TOOL_BUCKET) {
+
+ int tile = get_selected_tile();
+ _draw_fill_preview(tile, over_tile, flip_h, flip_v, transpose, xform);
+
+ } else {
+
+ int st = get_selected_tile();
+
+ if (st==TileMap::INVALID_CELL)
+ return;
+
+ _draw_cell(st, over_tile, flip_h, flip_v, transpose, xform);
+ }
+ }
+}
+
+void TileMapEditor::edit(Node *p_tile_map) {
+
+ search_box->set_text("");
+
+ if (!canvas_item_editor) {
+ canvas_item_editor=CanvasItemEditor::get_singleton()->get_viewport_control();
+ }
+
+ if (node)
+ node->disconnect("settings_changed",this,"_tileset_settings_changed");
+ if (p_tile_map) {
+
+ node=p_tile_map->cast_to<TileMap>();
+ if (!canvas_item_editor->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->connect("draw",this,"_canvas_draw");
+ if (!canvas_item_editor->is_connected("mouse_entered",this,"_canvas_mouse_enter"))
+ canvas_item_editor->connect("mouse_entered",this,"_canvas_mouse_enter");
+ if (!canvas_item_editor->is_connected("mouse_exited",this,"_canvas_mouse_exit"))
+ canvas_item_editor->connect("mouse_exited",this,"_canvas_mouse_exit");
+
+ _update_palette();
+
+ } else {
+ node=NULL;
+
+ if (canvas_item_editor->is_connected("draw",this,"_canvas_draw"))
+ canvas_item_editor->disconnect("draw",this,"_canvas_draw");
+ if (canvas_item_editor->is_connected("mouse_entered",this,"_canvas_mouse_enter"))
+ canvas_item_editor->disconnect("mouse_entered",this,"_canvas_mouse_enter");
+ if (canvas_item_editor->is_connected("mouse_exited",this,"_canvas_mouse_exit"))
+ canvas_item_editor->disconnect("mouse_exited",this,"_canvas_mouse_exit");
+
+ _update_palette();
+ }
+
+ if (node)
+ node->connect("settings_changed",this,"_tileset_settings_changed");
+
+ _clear_bucket_cache();
+
+}
+
+void TileMapEditor::_tileset_settings_changed() {
+
+ _update_palette();
+
+ if (canvas_item_editor)
+ canvas_item_editor->update();
+}
+
+void TileMapEditor::_icon_size_changed(float p_value) {
+ if (node) {
+ palette->set_icon_scale(p_value);
+ _update_palette();
+ }
+}
+
+void TileMapEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_text_entered"),&TileMapEditor::_text_entered);
+ ClassDB::bind_method(D_METHOD("_text_changed"),&TileMapEditor::_text_changed);
+ ClassDB::bind_method(D_METHOD("_sbox_input"),&TileMapEditor::_sbox_input);
+ ClassDB::bind_method(D_METHOD("_menu_option"),&TileMapEditor::_menu_option);
+ ClassDB::bind_method(D_METHOD("_canvas_draw"),&TileMapEditor::_canvas_draw);
+ ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"),&TileMapEditor::_canvas_mouse_enter);
+ ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"),&TileMapEditor::_canvas_mouse_exit);
+ ClassDB::bind_method(D_METHOD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed);
+ ClassDB::bind_method(D_METHOD("_update_transform_buttons"),&TileMapEditor::_update_transform_buttons);
+
+ ClassDB::bind_method(D_METHOD("_fill_points"),&TileMapEditor::_fill_points);
+ ClassDB::bind_method(D_METHOD("_erase_points"),&TileMapEditor::_erase_points);
+
+ ClassDB::bind_method(D_METHOD("_icon_size_changed"), &TileMapEditor::_icon_size_changed);
+}
+
+TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i& p_pos)
+{
+ CellOp op;
+ op.idx = node->get_cell(p_pos.x,p_pos.y);
+ if (op.idx!=TileMap::INVALID_CELL) {
+ if (node->is_cell_x_flipped(p_pos.x,p_pos.y))
+ op.xf=true;
+ if (node->is_cell_y_flipped(p_pos.x,p_pos.y))
+ op.yf=true;
+ if (node->is_cell_transposed(p_pos.x,p_pos.y))
+ op.tr=true;
+ }
+ return op;
+}
+
+void TileMapEditor::_update_transform_buttons(Object *p_button) {
+ //ERR_FAIL_NULL(p_button);
+ ToolButton *b=p_button->cast_to<ToolButton>();
+ //ERR_FAIL_COND(!b);
+
+ if (b == rotate_0) {
+ mirror_x->set_pressed(false);
+ mirror_y->set_pressed(false);
+ transp->set_pressed(false);
+ }
+ else if (b == rotate_90) {
+ mirror_x->set_pressed(true);
+ mirror_y->set_pressed(false);
+ transp->set_pressed(true);
+ }
+ else if (b == rotate_180) {
+ mirror_x->set_pressed(true);
+ mirror_y->set_pressed(true);
+ transp->set_pressed(false);
+ }
+ else if (b == rotate_270) {
+ mirror_x->set_pressed(false);
+ mirror_y->set_pressed(true);
+ transp->set_pressed(true);
+ }
+
+ flip_h=mirror_x->is_pressed();
+ flip_v=mirror_y->is_pressed();
+ transpose=transp->is_pressed();
+
+ rotate_0->set_pressed(!flip_h && !flip_v && !transpose);
+ rotate_90->set_pressed(flip_h && !flip_v && transpose);
+ rotate_180->set_pressed(flip_h && flip_v && !transpose);
+ rotate_270->set_pressed(!flip_h && flip_v && transpose);
+}
+
+TileMapEditor::TileMapEditor(EditorNode *p_editor) {
+
+ node=NULL;
+ canvas_item_editor=NULL;
+ editor=p_editor;
+ undo_redo=editor->get_undo_redo();
+
+ tool=TOOL_NONE;
+ selection_active=false;
+ mouse_over=false;
+
+ flip_h=false;
+ flip_v=false;
+ transpose=false;
+
+ bucket_cache_tile = -1;
+ bucket_cache_visited = 0;
+
+ ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase selection"), KEY_DELETE);
+ ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find tile"), KEY_MASK_CMD+KEY_F);
+ ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose"));
+ ED_SHORTCUT("tile_map_editor/mirror_x", TTR("Mirror X"), KEY_A);
+ ED_SHORTCUT("tile_map_editor/mirror_y", TTR("Mirror Y"), KEY_S);
+
+ search_box = memnew( LineEdit );
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ search_box->connect("text_entered", this, "_text_entered");
+ search_box->connect("text_changed", this, "_text_changed");
+ search_box->connect("gui_input", this, "_sbox_input");
+ add_child(search_box);
+
+ size_slider = memnew( HSlider );
+ size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
+ size_slider->set_min(0.1f);
+ size_slider->set_max(4.0f);
+ size_slider->set_step(0.1f);
+ size_slider->set_value(1.0f);
+ size_slider->connect("value_changed", this, "_icon_size_changed");
+ add_child(size_slider);
+
+ int mw = EDITOR_DEF("editors/tile_map/palette_min_width", 80);
+
+ // Add tile palette
+ palette = memnew( ItemList );
+ palette->set_v_size_flags(SIZE_EXPAND_FILL);
+ palette->set_custom_minimum_size(Size2(mw,0));
+ palette->set_max_columns(0);
+ palette->set_icon_mode(ItemList::ICON_MODE_TOP);
+ palette->set_max_text_lines(2);
+ add_child(palette);
+
+ // Add menu items
+ toolbar = memnew( HBoxContainer );
+ toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
+ toolbar->set_alignment(BoxContainer::ALIGN_END);
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar);
+
+ // Tile position
+ tile_info = memnew( Label );
+ toolbar->add_child(tile_info);
+
+ options = memnew( MenuButton );
+ options->set_text("Tile Map");
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons"));
+ options->set_process_unhandled_key_input(false);
+
+ PopupMenu *p = options->get_popup();
+
+ p->add_item(TTR("Bucket"), OPTION_BUCKET);
+ p->add_separator();
+ p->add_item(TTR("Pick Tile"), OPTION_PICK_TILE, KEY_CONTROL);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_MASK_CMD+KEY_B), OPTION_SELECT);
+ p->add_shortcut(ED_SHORTCUT("tile_map_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_CMD+KEY_D), OPTION_DUPLICATE);
+ p->add_shortcut(ED_GET_SHORTCUT("tile_map_editor/erase_selection"), OPTION_ERASE_SELECTION);
+
+ p->connect("id_pressed", this, "_menu_option");
+
+ toolbar->add_child(options);
+
+ toolbar->add_child( memnew( VSeparator ) );
+
+ transp = memnew( ToolButton );
+ transp->set_toggle_mode(true);
+ transp->set_tooltip(TTR("Transpose") + " ("+ED_GET_SHORTCUT("tile_map_editor/transpose")->get_as_text()+")");
+ transp->set_focus_mode(FOCUS_NONE);
+ transp->connect("pressed", this, "_update_transform_buttons", make_binds(transp));
+ toolbar->add_child(transp);
+ mirror_x = memnew( ToolButton );
+ mirror_x->set_toggle_mode(true);
+ mirror_x->set_tooltip(TTR("Mirror X") + " ("+ED_GET_SHORTCUT("tile_map_editor/mirror_x")->get_as_text()+")");
+ mirror_x->set_focus_mode(FOCUS_NONE);
+ mirror_x->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_x));
+ toolbar->add_child(mirror_x);
+ mirror_y = memnew( ToolButton );
+ mirror_y->set_toggle_mode(true);
+ mirror_y->set_tooltip(TTR("Mirror Y") + " ("+ED_GET_SHORTCUT("tile_map_editor/mirror_y")->get_as_text()+")");
+ mirror_y->set_focus_mode(FOCUS_NONE);
+ mirror_y->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_y));
+ toolbar->add_child(mirror_y);
+
+ toolbar->add_child( memnew( VSeparator ) );
+
+ rotate_0 = memnew( ToolButton );
+ rotate_0->set_toggle_mode(true);
+ rotate_0->set_tooltip(TTR("Rotate 0 degrees"));
+ rotate_0->set_focus_mode(FOCUS_NONE);
+ rotate_0->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_0));
+ toolbar->add_child(rotate_0);
+ rotate_90 = memnew( ToolButton );
+ rotate_90->set_toggle_mode(true);
+ rotate_90->set_tooltip(TTR("Rotate 90 degrees"));
+ rotate_90->set_focus_mode(FOCUS_NONE);
+ rotate_90->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_90));
+ toolbar->add_child(rotate_90);
+ rotate_180 = memnew( ToolButton );
+ rotate_180->set_toggle_mode(true);
+ rotate_180->set_tooltip(TTR("Rotate 180 degrees"));
+ rotate_180->set_focus_mode(FOCUS_NONE);
+ rotate_180->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_180));
+ toolbar->add_child(rotate_180);
+ rotate_270 = memnew( ToolButton );
+ rotate_270->set_toggle_mode(true);
+ rotate_270->set_tooltip(TTR("Rotate 270 degrees"));
+ rotate_270->set_focus_mode(FOCUS_NONE);
+ rotate_270->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_270));
+ toolbar->add_child(rotate_270);
+ toolbar->hide();
+
+ rotate_0->set_pressed(true);
+}
+
+TileMapEditor::~TileMapEditor() {
+ _clear_bucket_cache();
+}
+
+///////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////
+
+void TileMapEditorPlugin::edit(Object *p_object) {
+
+ tile_map_editor->edit(p_object->cast_to<Node>());
+}
+
+bool TileMapEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("TileMap");
+}
+
+void TileMapEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+
+ tile_map_editor->show();
+ tile_map_editor->get_toolbar()->show();
+ } else {
+
+ tile_map_editor->hide();
+ tile_map_editor->get_toolbar()->hide();
+ tile_map_editor->edit(NULL);
+ }
+}
+
+TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) {
+
+ EDITOR_DEF("editors/tile_map/preview_size",64);
+ EDITOR_DEF("editors/tile_map/palette_item_hseparation",8);
+ EDITOR_DEF("editors/tile_map/show_tile_names", true);
+ EDITOR_DEF("editors/tile_map/bucket_fill_preview", true);
+
+ tile_map_editor = memnew( TileMapEditor(p_node) );
+ add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE, tile_map_editor);
+ tile_map_editor->hide();
+}
+
+TileMapEditorPlugin::~TileMapEditorPlugin()
+{
+}
+
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
new file mode 100644
index 0000000000..82e2a396d1
--- /dev/null
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -0,0 +1,207 @@
+/*************************************************************************/
+/* tile_map_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 TILE_MAP_EDITOR_PLUGIN_H
+#define TILE_MAP_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
+
+#include "scene/2d/tile_map.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/label.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class TileMapEditor : public VBoxContainer {
+
+ GDCLASS(TileMapEditor, VBoxContainer );
+
+ enum Tool {
+
+ TOOL_NONE,
+ TOOL_PAINTING,
+ TOOL_ERASING,
+ TOOL_RECTANGLE_PAINT,
+ TOOL_RECTANGLE_ERASE,
+ TOOL_LINE_PAINT,
+ TOOL_LINE_ERASE,
+ TOOL_SELECTING,
+ TOOL_BUCKET,
+ TOOL_PICKING,
+ TOOL_DUPLICATING,
+ };
+
+ enum Options {
+
+ OPTION_BUCKET,
+ OPTION_PICK_TILE,
+ OPTION_SELECT,
+ OPTION_DUPLICATE,
+ OPTION_ERASE_SELECTION
+ };
+
+ TileMap *node;
+
+ EditorNode *editor;
+ UndoRedo *undo_redo;
+ Control *canvas_item_editor;
+
+ LineEdit *search_box;
+ HSlider *size_slider;
+ ItemList *palette;
+
+ HBoxContainer *toolbar;
+
+ Label *tile_info;
+ MenuButton *options;
+ ToolButton *transp;
+ ToolButton *mirror_x;
+ ToolButton *mirror_y;
+ ToolButton *rotate_0;
+ ToolButton *rotate_90;
+ ToolButton *rotate_180;
+ ToolButton *rotate_270;
+
+ Tool tool;
+
+ bool selection_active;
+ bool mouse_over;
+
+ bool flip_h;
+ bool flip_v;
+ bool transpose;
+
+ Point2i rectangle_begin;
+ Rect2i rectangle;
+
+ Point2i over_tile;
+
+ bool * bucket_cache_visited;
+ Rect2i bucket_cache_rect;
+ int bucket_cache_tile;
+ PoolVector<Vector2> bucket_cache;
+
+ struct CellOp {
+ int idx;
+ bool xf;
+ bool yf;
+ bool tr;
+
+ CellOp() { idx=-1; xf=false; yf=false; tr=false; }
+ };
+
+ Map<Point2i, CellOp> paint_undo;
+
+ struct TileData {
+ Point2i pos;
+ int cell;
+ bool flip_h;
+ bool flip_v;
+ bool transpose;
+ };
+
+ List<TileData> copydata;
+
+ void _pick_tile(const Point2& p_pos);
+
+ PoolVector<Vector2> _bucket_fill(const Point2i& p_start, bool erase=false, bool preview=false);
+
+ void _fill_points(const PoolVector<Vector2> p_points, const Dictionary& p_op);
+ void _erase_points(const PoolVector<Vector2> p_points);
+
+ void _select(const Point2i& p_from, const Point2i& p_to);
+
+ void _draw_cell(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform);
+ void _draw_fill_preview(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform);
+ void _clear_bucket_cache();
+
+ void _update_copydata();
+
+ int get_selected_tile() const;
+ void set_selected_tile(int p_tile);
+
+ void _text_entered(const String& p_text);
+ void _text_changed(const String& p_text);
+ void _sbox_input(const InputEvent& p_ie);
+ void _update_palette();
+ void _canvas_draw();
+ void _menu_option(int p_option);
+
+ void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_transpose=false, bool p_with_undo=false);
+
+ void _canvas_mouse_enter();
+ void _canvas_mouse_exit();
+ void _tileset_settings_changed();
+ void _icon_size_changed(float p_value);
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+ CellOp _get_op_from_cell(const Point2i& p_pos);
+ void _update_transform_buttons(Object *p_button=NULL);
+
+public:
+
+ HBoxContainer *get_toolbar() const { return toolbar; }
+
+ bool forward_gui_input(const InputEvent& p_event);
+ void edit(Node *p_tile_map);
+
+ TileMapEditor(EditorNode *p_editor);
+ ~TileMapEditor();
+};
+
+class TileMapEditorPlugin : public EditorPlugin {
+
+ GDCLASS( TileMapEditorPlugin, EditorPlugin );
+
+ TileMapEditor *tile_map_editor;
+
+public:
+
+ virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return tile_map_editor->forward_gui_input(p_event); }
+
+ virtual String get_name() const { return "TileMap"; }
+ 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);
+
+ TileMapEditorPlugin(EditorNode *p_node);
+ ~TileMapEditorPlugin();
+
+};
+
+
+#endif // TILE_MAP_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 3db6c94917..3db6c94917 100644
--- a/tools/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h
new file mode 100644
index 0000000000..02a82ebd6b
--- /dev/null
+++ b/editor/plugins/tile_set_editor_plugin.h
@@ -0,0 +1,101 @@
+/*************************************************************************/
+/* tile_set_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 TILE_SET_EDITOR_PLUGIN_H
+#define TILE_SET_EDITOR_PLUGIN_H
+
+
+
+#include "scene/resources/tile_set.h"
+#include "editor/editor_node.h"
+#include "editor/editor_name_dialog.h"
+
+
+class TileSetEditor : public Control {
+
+ GDCLASS( TileSetEditor, Control );
+
+ Ref<TileSet> tileset;
+
+ EditorNode *editor;
+ MenuButton *menu;
+ ConfirmationDialog *cd;
+ EditorNameDialog *nd;
+ AcceptDialog *err_dialog;
+
+ enum {
+
+ MENU_OPTION_ADD_ITEM,
+ MENU_OPTION_REMOVE_ITEM,
+ MENU_OPTION_CREATE_FROM_SCENE,
+ MENU_OPTION_MERGE_FROM_SCENE
+ };
+
+ int option;
+ void _menu_cbk(int p_option);
+ void _menu_confirm();
+ void _name_dialog_confirm(const String& name);
+
+ static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge);
+
+
+protected:
+ static void _bind_methods();
+public:
+
+ void edit(const Ref<TileSet>& p_tileset);
+ static Error update_library_file(Node *p_base_scene, Ref<TileSet> ml,bool p_merge=true);
+
+ TileSetEditor(EditorNode *p_editor);
+};
+
+
+
+class TileSetEditorPlugin : public EditorPlugin {
+
+ GDCLASS( TileSetEditorPlugin, EditorPlugin );
+
+ TileSetEditor *tileset_editor;
+ EditorNode *editor;
+
+public:
+
+ virtual String get_name() const { return "TileSet"; }
+ 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);
+
+
+
+ TileSetEditorPlugin(EditorNode *p_node);
+
+};
+
+
+#endif // TILE_SET_EDITOR_PLUGIN_H
diff --git a/tools/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index 76626c4556..76626c4556 100644
--- a/tools/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
diff --git a/tools/editor/progress_dialog.h b/editor/progress_dialog.h
index 60acf825a9..60acf825a9 100644
--- a/tools/editor/progress_dialog.h
+++ b/editor/progress_dialog.h
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
new file mode 100644
index 0000000000..fc6d8793d8
--- /dev/null
+++ b/editor/project_export.cpp
@@ -0,0 +1,828 @@
+/*************************************************************************/
+/* project_export.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "project_export.h"
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "global_config.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "os/os.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/margin_container.h"
+#include "editor_data.h"
+#include "io/image_loader.h"
+#include "compressed_translation.h"
+#include "editor_node.h"
+#include "io_plugins/editor_texture_import_plugin.h"
+#include "editor_settings.h"
+
+void ProjectExportDialog::_notification(int p_what) {
+
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ delete_preset->set_icon(get_icon("Del","EditorIcons"));
+ connect("confirmed",this,"_export_pck_zip");
+ } break;
+ case NOTIFICATION_POPUP_HIDE: {
+ EditorSettings::get_singleton()->set("interface/dialogs/export_bounds", get_rect());
+ } break;
+ }
+}
+
+
+void ProjectExportDialog::popup_export() {
+
+ add_preset->get_popup()->clear();
+ for(int i=0;i<EditorExport::get_singleton()->get_export_platform_count();i++) {
+
+ Ref<EditorExportPlatform> plat = EditorExport::get_singleton()->get_export_platform(i);
+
+ add_preset->get_popup()->add_icon_item(plat->get_logo(),plat->get_name());
+
+ }
+
+ _update_presets();
+
+ // Restore valid window bounds or pop up at default size.
+ if (EditorSettings::get_singleton()->has("interface/dialogs/export_bounds")) {
+ popup(EditorSettings::get_singleton()->get("interface/dialogs/export_bounds"));
+ } else {
+ popup_centered_ratio();
+ }
+}
+
+void ProjectExportDialog::_add_preset(int p_platform) {
+
+ Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_platform(p_platform)->create_preset();
+ ERR_FAIL_COND(!preset.is_valid());
+
+ String name = EditorExport::get_singleton()->get_export_platform(p_platform)->get_name();
+ bool make_runnable=true;
+ int attempt=1;
+ while(true) {
+
+ bool valid=true;
+
+ for(int i=0;i<EditorExport::get_singleton()->get_export_preset_count();i++) {
+ Ref<EditorExportPreset> p = EditorExport::get_singleton()->get_export_preset(i);
+ if (p->get_platform()==preset->get_platform() && p->is_runnable()) {
+ make_runnable=false;
+ }
+ if (p->get_name()==name) {
+ valid=false;
+ break;
+ }
+
+ }
+
+ if (valid)
+ break;
+
+ attempt++;
+ name = EditorExport::get_singleton()->get_export_platform(p_platform)->get_name()+" "+itos(attempt);
+
+ }
+
+ preset->set_name(name);
+ if (make_runnable)
+ preset->set_runnable(make_runnable);
+ EditorExport::get_singleton()->add_export_preset(preset);
+ _update_presets();
+ _edit_preset(EditorExport::get_singleton()->get_export_preset_count()-1);
+
+}
+
+
+void ProjectExportDialog::_update_presets() {
+
+ updating=true;
+
+ Ref<EditorExportPreset> current;
+ if (presets->get_current()>=0 && presets->get_current()<presets->get_item_count())
+ current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+
+ int current_idx=-1;
+ presets->clear();
+ for(int i=0;i<EditorExport::get_singleton()->get_export_preset_count();i++) {
+ Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_preset(i);
+ if (preset==current) {
+ current_idx=i;
+ }
+
+ String name = preset->get_name();
+ if (preset->is_runnable())
+ name+=" ("+TTR("Runnable")+")";
+ presets->add_item(name,preset->get_platform()->get_logo());
+ }
+
+ if (current_idx!=-1) {
+ presets->select(current_idx);
+ //_edit_preset(current_idx);
+ }
+
+ updating=false;
+
+}
+
+void ProjectExportDialog::_edit_preset(int p_index) {
+
+ if (p_index<0 || p_index>=presets->get_item_count()) {
+ name->set_text("");
+ name->set_editable(false);
+ runnable->set_disabled(true);
+ parameters->edit(NULL);
+ delete_preset->set_disabled(true);
+ sections->hide();
+ patches->clear();
+ return;
+ }
+
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(p_index);
+ ERR_FAIL_COND(current.is_null());
+
+
+ updating=true;
+
+ presets->select(p_index);
+ sections->show();
+
+ name->set_editable(true);
+ delete_preset->set_disabled(false);
+ name->set_text(current->get_name());
+ runnable->set_disabled(false);
+ runnable->set_pressed(current->is_runnable());
+ parameters->edit(current.ptr());
+
+ export_filter->select(current->get_export_filter());
+ include_filters->set_text(current->get_include_filter());
+ exclude_filters->set_text(current->get_exclude_filter());
+
+
+ patches->clear();
+ TreeItem *patch_root = patches->create_item();
+ Vector<String> patchlist = current->get_patches();
+ for(int i=0;i<patchlist.size();i++) {
+ TreeItem *patch = patches->create_item(patch_root);
+ patch->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ String file = patchlist[i].get_file();
+ patch->set_editable(0,true);
+ patch->set_text(0,file.get_file().replace("*",""));
+ if (file.ends_with("*"))
+ patch->set_checked(0,true);
+ patch->set_tooltip(0,patchlist[i]);
+ patch->set_metadata(0,i);
+ patch->add_button(0,get_icon("Del","EditorIcons"),0);
+ patch->add_button(0,get_icon("folder","FileDialog"),1);
+ }
+
+ TreeItem *patch_add = patches->create_item(patch_root);
+ patch_add->set_metadata(0,patchlist.size());
+ if (patchlist.size()==0)
+ patch_add->set_text(0,"Add initial export..");
+ else
+ patch_add->set_text(0,"Add previous patches..");
+
+ patch_add->add_button(0,get_icon("folder","FileDialog"),1);
+
+ _fill_resource_tree();
+
+ updating=false;
+
+}
+
+void ProjectExportDialog::_patch_button_pressed(Object* p_item,int p_column,int p_id) {
+
+
+ TreeItem *ti = (TreeItem*)p_item;
+
+ patch_index=ti->get_metadata(0);
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ ERR_FAIL_COND(current.is_null());
+
+ if (p_id==0) {
+ Vector<String> patches = current->get_patches();
+ ERR_FAIL_INDEX(patch_index,patches.size());
+ patch_erase->set_text(vformat(TTR("Delete patch '"+patches[patch_index].get_file()+"' from list?")));
+ patch_erase->popup_centered_minsize();
+ } else {
+ patch_dialog->popup_centered_ratio();
+ }
+}
+
+void ProjectExportDialog::_patch_edited() {
+
+ TreeItem *item = patches->get_edited();
+ if (!item)
+ return;
+ int index = item->get_metadata(0);
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ ERR_FAIL_COND(current.is_null());
+
+ Vector<String> patches = current->get_patches();
+
+ ERR_FAIL_INDEX(index,patches.size());
+
+ String patch = patches[index].replace("*","");
+
+ if (item->is_checked(0)) {
+ patch+="*";
+ }
+
+ current->set_patch(index,patch);
+
+
+
+}
+
+void ProjectExportDialog::_patch_selected(const String& p_path) {
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ ERR_FAIL_COND(current.is_null());
+
+ Vector<String> patches = current->get_patches();
+
+ if (patch_index >=patches.size()) {
+
+ current->add_patch(GlobalConfig::get_singleton()->get_resource_path().path_to(p_path)+"*");
+ } else {
+ String enabled = patches[patch_index].ends_with("*") ? String("*") : String();
+ current->set_patch(patch_index,GlobalConfig::get_singleton()->get_resource_path().path_to(p_path)+enabled);
+
+ }
+
+ _edit_preset(presets->get_current());
+
+}
+
+void ProjectExportDialog::_patch_deleted() {
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ ERR_FAIL_COND(current.is_null());
+
+ Vector<String> patches = current->get_patches();
+ if (patch_index <patches.size()) {
+
+ current->remove_patch(patch_index);
+ _edit_preset(presets->get_current());
+ }
+
+}
+
+void ProjectExportDialog::_runnable_pressed() {
+
+ if (updating)
+ return;
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ ERR_FAIL_COND(current.is_null());
+
+ if (runnable->is_pressed()) {
+
+ for(int i=0;i<EditorExport::get_singleton()->get_export_preset_count();i++) {
+ Ref<EditorExportPreset> p = EditorExport::get_singleton()->get_export_preset(i);
+ if (p->get_platform()==current->get_platform()) {
+ p->set_runnable(current==p);
+ }
+ }
+ } else {
+
+ current->set_runnable(false);
+ }
+
+ _update_presets();
+}
+
+void ProjectExportDialog::_name_changed(const String& p_string) {
+
+ if (updating)
+ return;
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ ERR_FAIL_COND(current.is_null());
+
+ current->set_name(p_string);
+ _update_presets();
+
+
+}
+
+void ProjectExportDialog::_delete_preset() {
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ if (current.is_null())
+ return;
+
+ delete_confirm->set_text(vformat(TTR("Delete preset '%s'?"),current->get_name()));
+ delete_confirm->popup_centered_minsize();
+
+}
+
+void ProjectExportDialog::_delete_preset_confirm() {
+
+ int idx = presets->get_current();
+ parameters->edit(NULL);//to avoid crash
+ EditorExport::get_singleton()->remove_export_preset(idx);
+ _update_presets();
+ _edit_preset(-1);
+}
+
+
+Variant ProjectExportDialog::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ if (p_from==presets) {
+ int pos = presets->get_item_at_pos(p_point,true);
+
+ if (pos>=0) {
+ Dictionary d;
+ d["type"]="export_preset";
+ d["preset"]=pos;
+
+ HBoxContainer *drag = memnew( HBoxContainer);
+ TextureRect *tr = memnew(TextureRect);
+ tr->set_texture(presets->get_item_icon(pos));
+ drag->add_child(tr);
+ Label *label = memnew( Label );
+ label->set_text(presets->get_item_text(pos));
+ drag->add_child(label);
+
+ set_drag_preview(drag);
+
+ return d;
+
+ }
+ } else if (p_from==patches) {
+
+ TreeItem *item = patches->get_item_at_pos(p_point);
+
+ if (item && item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK) {
+
+ int metadata = item->get_metadata(0);
+ Dictionary d;
+ d["type"]="export_patch";
+ d["patch"]=metadata;
+
+ Label *label = memnew( Label );
+ label->set_text(item->get_text(0));
+ set_drag_preview(label);
+
+ return d;
+ }
+
+ }
+
+ return Variant();
+}
+
+bool ProjectExportDialog::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ if (p_from==presets) {
+ Dictionary d = p_data;
+ if (!d.has("type") || String(d["type"])!="export_preset")
+ return false;
+
+
+ if (presets->get_item_at_pos(p_point,true)<0 && !presets->is_pos_at_end_of_items(p_point))
+ return false;
+ } else if (p_from==patches) {
+
+ Dictionary d = p_data;
+ if (!d.has("type") || String(d["type"])!="export_patch")
+ return false;
+
+ patches->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
+
+ TreeItem *item = patches->get_item_at_pos(p_point);
+
+ if (!item) {
+
+ return false;
+ }
+
+ }
+
+ return true;
+}
+
+void ProjectExportDialog::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ if (p_from==presets) {
+ Dictionary d=p_data;
+ int from_pos = d["preset"];
+
+ int to_pos=-1;
+
+ if (presets->get_item_at_pos(p_point,true)>=0) {
+ to_pos = presets->get_item_at_pos(p_point,true);
+ }
+
+ if (to_pos==-1 && !presets->is_pos_at_end_of_items(p_point))
+ return;
+
+ if (to_pos==from_pos)
+ return;
+ else if (to_pos>from_pos) {
+ to_pos--;
+ }
+
+
+ Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_preset(from_pos);
+ EditorExport::get_singleton()->remove_export_preset(from_pos);
+ EditorExport::get_singleton()->add_export_preset(preset,to_pos);
+
+ _update_presets();
+ if (to_pos>=0)
+ _edit_preset(to_pos);
+ else
+ _edit_preset(presets->get_item_count()-1);
+ } else if (p_from==patches) {
+
+ Dictionary d = p_data;
+ if (!d.has("type") || String(d["type"])!="export_patch")
+ return;
+
+ int from_pos = d["patch"];
+
+ TreeItem *item = patches->get_item_at_pos(p_point);
+ if (!item)
+ return;
+
+ int to_pos = item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK ? int(item->get_metadata(0)) : -1;
+
+ if (to_pos==from_pos)
+ return;
+ else if (to_pos>from_pos) {
+ to_pos--;
+ }
+
+ Ref<EditorExportPreset> preset = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ String patch = preset->get_patch(from_pos);
+ preset->remove_patch(from_pos);
+ preset->add_patch(patch,to_pos);
+
+ _edit_preset(presets->get_current());
+
+ }
+
+}
+
+void ProjectExportDialog::_export_type_changed(int p_which) {
+
+ if (updating)
+ return;
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ if (current.is_null())
+ return;
+
+ current->set_export_filter(EditorExportPreset::ExportFilter(p_which));
+ updating=true;
+ _fill_resource_tree();
+ updating=false;
+
+}
+
+void ProjectExportDialog::_filter_changed(const String& p_filter) {
+
+ if (updating)
+ return;
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ if (current.is_null())
+ return;
+
+ current->set_include_filter(include_filters->get_text());
+ current->set_exclude_filter(exclude_filters->get_text());
+
+
+
+}
+
+void ProjectExportDialog::_fill_resource_tree() {
+
+ include_files->clear();
+ include_label->hide();
+ include_margin->hide();
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ if (current.is_null())
+ return;
+
+ EditorExportPreset::ExportFilter f = current->get_export_filter();
+
+ if (f==EditorExportPreset::EXPORT_ALL_RESOURCES) {
+ return;
+ }
+
+ include_label->show();
+ include_margin->show();
+
+ TreeItem *root = include_files->create_item();
+
+
+ _fill_tree(EditorFileSystem::get_singleton()->get_filesystem(),root,current,f==EditorExportPreset::EXPORT_SELECTED_SCENES);
+
+}
+
+
+bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir,TreeItem *p_item,Ref<EditorExportPreset> &current,bool p_only_scenes) {
+
+ p_item->set_icon(0,get_icon("folder","FileDialog"));
+ p_item->set_text(0,p_dir->get_name()+"/");
+
+ bool used=false;
+ for(int i=0;i<p_dir->get_subdir_count();i++) {
+
+ TreeItem *subdir = include_files->create_item(p_item);
+ if (_fill_tree(p_dir->get_subdir(i),subdir,current,p_only_scenes)==false) {
+ memdelete(subdir);
+ } else {
+ used=true;
+ }
+ }
+
+
+
+ for(int i=0;i<p_dir->get_file_count();i++) {
+
+ String type = p_dir->get_file_type(i);
+ if (p_only_scenes && type!="PackedScene")
+ continue;
+
+ TreeItem *file = include_files->create_item(p_item);
+ file->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ file->set_text(0,p_dir->get_file(i));
+
+ Ref<Texture> tex;
+ if (has_icon(type,editor_icons)) {
+ tex = get_icon(type,editor_icons);
+ } else {
+ tex = get_icon("Object",editor_icons);
+ }
+
+ String path = p_dir->get_file_path(i);
+
+ file->set_icon(0,tex);
+ file->set_editable(0,true);
+ file->set_checked(0,current->has_export_file(path));
+ file->set_metadata(0,path);
+
+ used=true;
+
+ }
+
+ return used;
+}
+
+void ProjectExportDialog::_tree_changed() {
+
+ if (updating)
+ return;
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ if (current.is_null())
+ return;
+
+ TreeItem *item = include_files->get_edited();
+ if (!item)
+ return;
+
+ String path = item->get_metadata(0);
+ bool added = item->is_checked(0);
+
+ if (added) {
+ current->add_export_file(path);
+ } else {
+ current->remove_export_file(path);
+
+ }
+}
+
+
+void ProjectExportDialog::_export_pck_zip() {
+
+ export_pck_zip->popup_centered_ratio();
+}
+
+void ProjectExportDialog::_export_pck_zip_selected(const String& p_path) {
+
+ Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current());
+ ERR_FAIL_COND (current.is_null());
+ Ref<EditorExportPlatform> platform = current->get_platform();
+ ERR_FAIL_COND( platform.is_null() );
+
+ if (p_path.ends_with(".zip")) {
+ platform->save_zip(current,p_path);
+ } else if (p_path.ends_with(".pck")) {
+ platform->save_pack(current,p_path);
+ }
+}
+
+
+void ProjectExportDialog::_bind_methods() {
+
+ ClassDB::bind_method("_add_preset",&ProjectExportDialog::_add_preset);
+ ClassDB::bind_method("_edit_preset",&ProjectExportDialog::_edit_preset);
+ ClassDB::bind_method("_runnable_pressed",&ProjectExportDialog::_runnable_pressed);
+ ClassDB::bind_method("_name_changed",&ProjectExportDialog::_name_changed);
+ ClassDB::bind_method("_delete_preset",&ProjectExportDialog::_delete_preset);
+ ClassDB::bind_method("_delete_preset_confirm",&ProjectExportDialog::_delete_preset_confirm);
+ ClassDB::bind_method("get_drag_data_fw",&ProjectExportDialog::get_drag_data_fw);
+ ClassDB::bind_method("can_drop_data_fw",&ProjectExportDialog::can_drop_data_fw);
+ ClassDB::bind_method("drop_data_fw",&ProjectExportDialog::drop_data_fw);
+ ClassDB::bind_method("_export_type_changed",&ProjectExportDialog::_export_type_changed);
+ ClassDB::bind_method("_filter_changed",&ProjectExportDialog::_filter_changed);
+ ClassDB::bind_method("_tree_changed",&ProjectExportDialog::_tree_changed);
+ ClassDB::bind_method("_patch_button_pressed",&ProjectExportDialog::_patch_button_pressed);
+ ClassDB::bind_method("_patch_selected",&ProjectExportDialog::_patch_selected);
+ ClassDB::bind_method("_patch_deleted",&ProjectExportDialog::_patch_deleted);
+ ClassDB::bind_method("_patch_edited",&ProjectExportDialog::_patch_edited);
+ ClassDB::bind_method("_export_pck_zip",&ProjectExportDialog::_export_pck_zip);
+ ClassDB::bind_method("_export_pck_zip_selected",&ProjectExportDialog::_export_pck_zip_selected);
+
+
+}
+ProjectExportDialog::ProjectExportDialog() {
+
+ set_title(TTR("Export"));
+ set_resizable(true);
+
+ HBoxContainer *hbox = memnew( HBoxContainer );
+ add_child(hbox);
+
+ VBoxContainer *preset_vb = memnew( VBoxContainer );
+ preset_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbox->add_child(preset_vb);
+
+ HBoxContainer *preset_hb = memnew( HBoxContainer );
+ preset_hb->add_child(memnew(Label(TTR("Presets"))));
+ preset_hb->add_spacer();
+ preset_vb->add_child(preset_hb);
+
+ add_preset = memnew( MenuButton );
+ add_preset->set_text(TTR("Add.."));
+ add_preset->get_popup()->connect("index_pressed",this,"_add_preset");
+ preset_hb->add_child(add_preset);
+ MarginContainer *mc = memnew( MarginContainer );
+ preset_vb->add_child(mc);
+ mc->set_v_size_flags(SIZE_EXPAND_FILL);
+ presets = memnew( ItemList );
+ presets->set_drag_forwarding(this);
+ mc->add_child(presets);
+ presets->connect("item_selected",this,"_edit_preset");
+ delete_preset = memnew( ToolButton );
+ preset_hb->add_child(delete_preset);
+ delete_preset->connect("pressed",this,"_delete_preset");
+
+ VBoxContainer *settings_vb = memnew( VBoxContainer );
+ settings_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbox->add_child(settings_vb);
+
+ name = memnew(LineEdit);
+ settings_vb->add_margin_child(TTR("Name:"),name);
+ name->connect("text_changed",this,"_name_changed");
+ runnable = memnew(CheckButton);
+ runnable->set_text(TTR("Runnable"));
+ runnable->connect("pressed",this,"_runnable_pressed");
+ settings_vb->add_child(runnable);
+
+ sections = memnew (TabContainer );
+ settings_vb->add_child(sections);
+ sections->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ parameters = memnew (PropertyEditor );
+ sections->add_child(parameters);
+ parameters->set_name(TTR("Options"));
+ parameters->hide_top_label();
+ parameters->set_v_size_flags(SIZE_EXPAND_FILL);
+ parameters->set_hide_script(true);
+
+ VBoxContainer *resources_vb = memnew( VBoxContainer );
+ sections->add_child(resources_vb);
+ resources_vb->set_name(TTR("Resources"));
+
+ export_filter = memnew( OptionButton );
+ export_filter->add_item(TTR("Export all resources in the project"));
+ export_filter->add_item(TTR("Export selected scenes (and dependencies)"));
+ export_filter->add_item(TTR("Export selected resources (and dependencies)"));
+ resources_vb->add_margin_child(TTR("Export Mode:"),export_filter);
+ export_filter->connect("item_selected",this,"_export_type_changed");
+
+ include_label = memnew( Label );
+ include_label->set_text(TTR("Resources to export:"));
+ resources_vb->add_child(include_label);
+ include_margin = memnew( MarginContainer );
+ include_margin->set_v_size_flags(SIZE_EXPAND_FILL);
+ resources_vb->add_child(include_margin);
+
+ include_files = memnew(Tree);
+ include_margin->add_child(include_files);
+ include_files->connect("item_edited",this,"_tree_changed");
+
+ include_filters = memnew( LineEdit );
+ resources_vb->add_margin_child(TTR("Filters to export non-resource files (comma separated, e.g: *.json, *.txt)"),include_filters);
+ include_filters->connect("text_changed",this,"_filter_changed");
+
+ exclude_filters = memnew( LineEdit );
+ resources_vb->add_margin_child(TTR("Filters to exclude files from project (comma separated, e.g: *.json, *.txt)"),exclude_filters);
+ exclude_filters->connect("text_changed",this,"_filter_changed");
+
+ VBoxContainer *patch_vb = memnew( VBoxContainer );
+ sections->add_child(patch_vb);
+ patch_vb->set_name(TTR("Patches"));
+
+ patches = memnew( Tree );
+ patch_vb->add_child(patches);
+ patches->set_v_size_flags(SIZE_EXPAND_FILL);
+ patches->set_hide_root(true);
+ patches->connect("button_pressed",this,"_patch_button_pressed");
+ patches->connect("item_edited",this,"_patch_edited");
+ patches->set_drag_forwarding(this);
+ patches->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
+
+ HBoxContainer *patches_hb = memnew( HBoxContainer );
+ patch_vb->add_child(patches_hb);
+ patches_hb->add_spacer();
+ patch_export = memnew( Button );
+ patch_export->set_text(TTR("Make Patch"));
+ patches_hb->add_child(patch_export);
+ patches_hb->add_spacer();
+
+ patch_dialog = memnew( FileDialog );
+ patch_dialog->add_filter("*.pck ; Pack File");
+ patch_dialog->set_mode(FileDialog::MODE_OPEN_FILE);
+ patch_dialog->connect("file_selected",this,"_patch_selected");
+ add_child(patch_dialog);
+
+ patch_erase = memnew( ConfirmationDialog );
+ patch_erase->get_ok()->set_text(TTR("Delete"));
+ patch_erase->connect("confirmed",this,"_patch_deleted");
+ add_child(patch_erase);
+
+
+ //disable by default
+ name->set_editable(false);
+ runnable->set_disabled(true);
+ delete_preset->set_disabled(true);
+ sections->hide();
+ parameters->edit(NULL);
+
+ delete_confirm = memnew( ConfirmationDialog );
+ add_child(delete_confirm);
+ delete_confirm->get_ok()->set_text(TTR("Delete"));
+ delete_confirm->connect("confirmed",this,"_delete_preset_confirm");
+
+ updating=false;
+
+ get_ok()->set_text("Export PCK/Zip");
+ export_button = add_button("Export Project",!OS::get_singleton()->get_swap_ok_cancel(),"export");
+
+ export_pck_zip = memnew( FileDialog );
+ export_pck_zip->add_filter("*.zip ; ZIP File");
+ export_pck_zip->add_filter("*.pck ; Godot Game Pack");
+ export_pck_zip->set_access(FileDialog::ACCESS_FILESYSTEM);
+ export_pck_zip->set_mode(FileDialog::MODE_SAVE_FILE);
+ add_child(export_pck_zip);
+ export_pck_zip->connect("file_selected",this,"_export_pck_zip_selected");
+
+ set_hide_on_ok(false);
+
+
+
+ editor_icons = "EditorIcons";
+}
+
+ProjectExportDialog::~ProjectExportDialog() {
+
+
+}
diff --git a/editor/project_export.h b/editor/project_export.h
new file mode 100644
index 0000000000..b58ce2dc9d
--- /dev/null
+++ b/editor/project_export.h
@@ -0,0 +1,142 @@
+/*************************************************************************/
+/* project_export.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PROJECT_EXPORT_SETTINGS_H
+#define PROJECT_EXPORT_SETTINGS_H
+
+#include "scene/main/timer.h"
+#include "scene/gui/control.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/label.h"
+#include "editor/editor_file_dialog.h"
+#include "scene/gui/button.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tab_container.h"
+#include "os/dir_access.h"
+#include "os/thread.h"
+#include "scene/gui/option_button.h"
+
+#include "scene/gui/slider.h"
+#include "editor/editor_file_system.h"
+#include "property_editor.h"
+#include "editor_export.h"
+
+
+class EditorNode;
+
+class ProjectExportDialog : public ConfirmationDialog {
+ GDCLASS( ProjectExportDialog, ConfirmationDialog );
+
+private:
+
+
+ TabContainer *sections;
+
+ MenuButton *add_preset;
+ Button *delete_preset;
+ ItemList *presets;
+
+ LineEdit *name;
+ PropertyEditor *parameters;
+ CheckButton *runnable;
+
+
+ EditorFileDialog *pck_export;
+ EditorFileDialog *file_export;
+
+ Button *button_export;
+ bool updating;
+
+ ConfirmationDialog *delete_confirm;
+
+ OptionButton *export_filter;
+ LineEdit *include_filters;
+ LineEdit *exclude_filters;
+ Tree *include_files;
+
+ Label* include_label;
+ MarginContainer *include_margin;
+
+ StringName editor_icons;
+
+ Tree *patches;
+ Button *patch_export;
+ int patch_index;
+ FileDialog *patch_dialog;
+ ConfirmationDialog *patch_erase;
+
+ Button *export_button;
+
+ void _patch_selected(const String& p_path);
+ void _patch_deleted();
+
+ void _runnable_pressed();
+ void _name_changed(const String& p_string);
+ void _add_preset(int p_platform);
+ void _edit_preset(int p_index);
+ void _delete_preset();
+ void _delete_preset_confirm();
+
+ void _update_presets();
+
+ void _export_type_changed(int p_which);
+ void _filter_changed(const String& p_filter);
+ void _fill_resource_tree();
+ bool _fill_tree(EditorFileSystemDirectory *p_dir,TreeItem *p_item,Ref<EditorExportPreset> &current,bool p_only_scenes);
+ void _tree_changed();
+
+ void _patch_button_pressed(Object* p_item,int p_column,int p_id);
+ void _patch_edited();
+
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+ FileDialog *export_pck_zip;
+
+ void _export_pck_zip();
+ void _export_pck_zip_selected(const String& p_path);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void popup_export();
+
+ ProjectExportDialog();
+ ~ProjectExportDialog();
+};
+
+
+
+
+#endif // PROJECT_EXPORT_SETTINGS_H
+
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
new file mode 100644
index 0000000000..34b2d3e82c
--- /dev/null
+++ b/editor/project_manager.cpp
@@ -0,0 +1,1516 @@
+/*************************************************************************/
+/* project_manager.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "project_manager.h"
+
+#include "version.h"
+#include "os/os.h"
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/keyboard.h"
+#include "editor_settings.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/tool_button.h"
+#include "io/config_file.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/center_container.h"
+#include "io/stream_peer_ssl.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/gui/margin_container.h"
+#include "io/resource_saver.h"
+#include "editor_themes.h"
+#include "editor_initialize_ssl.h"
+#include "editor_scale.h"
+#include "io/zip_io.h"
+
+class NewProjectDialog : public ConfirmationDialog {
+
+ GDCLASS(NewProjectDialog,ConfirmationDialog);
+
+public:
+
+ enum Mode {
+ MODE_NEW,
+ MODE_IMPORT,
+ MODE_INSTALL
+ };
+private:
+
+ Mode mode;
+ Label *pp,*pn;
+ Label *error;
+ LineEdit *project_path;
+ LineEdit *project_name;
+ FileDialog *fdialog;
+ String zip_path;
+ String zip_title;
+ AcceptDialog *dialog_error;
+
+ String _test_path() {
+
+ error->set_text("");
+ get_ok()->set_disabled(true);
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ String valid_path;
+ if (d->change_dir(project_path->get_text())==OK){
+ valid_path=project_path->get_text();
+ } else if (d->change_dir(project_path->get_text().strip_edges())==OK) {
+ valid_path=project_path->get_text().strip_edges();
+ }
+
+ if (valid_path == "") {
+ error->set_text(TTR("Invalid project path, the path must exist!"));
+ memdelete(d);
+ return "";
+ }
+
+ if (mode!=MODE_IMPORT) {
+
+ if (d->file_exists("godot.cfg")) {
+
+ error->set_text(TTR("Invalid project path, godot.cfg must not exist."));
+ memdelete(d);
+ return "";
+ }
+
+ } else {
+
+ if (valid_path != "" && !d->file_exists("godot.cfg")) {
+
+ error->set_text(TTR("Invalid project path, godot.cfg must exist."));
+ memdelete(d);
+ return "";
+ }
+ }
+
+ memdelete(d);
+ get_ok()->set_disabled(false);
+ return valid_path;
+
+ }
+
+ void _path_text_changed(const String& p_path) {
+
+ String sp=_test_path();
+ if ( sp!="" ) {
+
+ sp=sp.replace("\\","/");
+ int lidx=sp.find_last("/");
+
+ if (lidx!=-1) {
+ sp=sp.substr(lidx+1,sp.length());
+ }
+ if (sp=="" && mode==MODE_IMPORT )
+ sp=TTR("Imported Project");
+
+ project_name->set_text(sp);
+ }
+ }
+
+ void _file_selected(const String& p_path) {
+
+ String p = p_path;
+ if (mode==MODE_IMPORT) {
+ if (p.ends_with("godot.cfg")) {
+
+ p=p.get_base_dir();
+ }
+ }
+ String sp = p.simplify_path();
+ project_path->set_text(sp);
+ _path_text_changed(sp);
+ get_ok()->call_deferred("grab_focus");
+ }
+
+ void _path_selected(const String& p_path) {
+
+ String p = p_path;
+ String sp = p.simplify_path();
+ project_path->set_text(sp);
+ _path_text_changed(sp);
+ get_ok()->call_deferred("grab_focus");
+ }
+
+ void _browse_path() {
+
+ if (mode==MODE_IMPORT) {
+
+ fdialog->set_mode(FileDialog::MODE_OPEN_FILE);
+ fdialog->clear_filters();
+ fdialog->add_filter("godot.cfg ; " _MKSTR(VERSION_NAME) " Project");
+ } else {
+ fdialog->set_mode(FileDialog::MODE_OPEN_DIR);
+ }
+ fdialog->popup_centered_ratio();
+ }
+
+ void _text_changed(const String& p_text) {
+ _test_path();
+ }
+
+ void ok_pressed() {
+
+ String dir=_test_path();
+ if (dir=="") {
+ error->set_text(TTR("Invalid project path (changed anything?)."));
+ return;
+ }
+
+ if (mode==MODE_IMPORT) {
+ // nothing to do
+ } else {
+ if (mode==MODE_NEW) {
+
+
+
+
+ FileAccess *f = FileAccess::open(dir.plus_file("/godot.cfg"),FileAccess::WRITE);
+ if (!f) {
+ error->set_text(TTR("Couldn't create godot.cfg in project path."));
+ } else {
+
+ f->store_line("; Engine configuration file.");
+ f->store_line("; It's best edited using the editor UI and not directly,");
+ f->store_line("; since the parameters that go here are not all obvious.");
+ f->store_line("; ");
+ f->store_line("; Format: ");
+ f->store_line("; [section] ; section goes between []");
+ f->store_line("; param=value ; assign values to parameters");
+ f->store_line("\n");
+ f->store_line("[application]");
+ f->store_line("\n");
+ f->store_line("name=\""+project_name->get_text()+"\"");
+ f->store_line("icon=\"res://icon.png\"");
+
+ memdelete(f);
+
+ ResourceSaver::save(dir.plus_file("/icon.png"),get_icon("DefaultProjectIcon","EditorIcons"));
+ }
+
+ } else if (mode==MODE_INSTALL) {
+
+
+ FileAccess *src_f=NULL;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+
+ unzFile pkg = unzOpen2(zip_path.utf8().get_data(), &io);
+ if (!pkg) {
+
+ dialog_error->set_text("Error opening package file, not in zip format.");
+ return;
+ }
+
+ int ret = unzGoToFirstFile(pkg);
+
+ Vector<String> failed_files;
+
+ int idx=0;
+ while(ret==UNZ_OK) {
+
+ //get filename
+ unz_file_info info;
+ char fname[16384];
+ ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
+
+ String path=fname;
+
+ int depth=1; //stuff from github comes with tag
+ bool skip=false;
+ while(depth>0) {
+ int pp = path.find("/");
+ if (pp==-1) {
+ skip=true;
+ break;
+ }
+ path=path.substr(pp+1,path.length());
+ depth--;
+ }
+
+
+ if (skip || path==String()) {
+ //
+ } else if (path.ends_with("/")) { // a dir
+
+ path=path.substr(0,path.length()-1);
+
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->make_dir(dir.plus_file(path));
+ memdelete(da);
+
+ } else {
+
+ Vector<uint8_t> data;
+ data.resize(info.uncompressed_size);
+
+ //read
+ unzOpenCurrentFile(pkg);
+ unzReadCurrentFile(pkg,data.ptr(),data.size());
+ unzCloseCurrentFile(pkg);
+
+ FileAccess *f=FileAccess::open(dir.plus_file(path),FileAccess::WRITE);
+
+ if (f) {
+ f->store_buffer(data.ptr(),data.size());
+ memdelete(f);
+ } else {
+ failed_files.push_back(path);
+ }
+
+
+ }
+
+ idx++;
+ ret = unzGoToNextFile(pkg);
+ }
+
+ unzClose(pkg);
+
+ if (failed_files.size()) {
+ String msg=TTR("The following files failed extraction from package:")+"\n\n";
+ for(int i=0;i<failed_files.size();i++) {
+
+ if (i>15) {
+ msg+="\nAnd "+itos(failed_files.size()-i)+" more files.";
+ break;
+ }
+ msg+=failed_files[i]+"\n";
+ }
+
+ dialog_error->set_text(msg);
+ dialog_error->popup_centered_minsize();
+
+ } else {
+ dialog_error->set_text(TTR("Package Installed Successfully!"));
+ dialog_error->popup_centered_minsize();
+ }
+
+ }
+
+ }
+
+ dir=dir.replace("\\","/");
+ if (dir.ends_with("/"))
+ dir=dir.substr(0,dir.length()-1);
+ String proj=dir.replace("/","::");
+ EditorSettings::get_singleton()->set("projects/"+proj,dir);
+ EditorSettings::get_singleton()->save();
+
+
+
+ hide();
+ emit_signal("project_created", dir);
+
+ }
+
+protected:
+
+ static void _bind_methods() {
+
+ ClassDB::bind_method("_browse_path",&NewProjectDialog::_browse_path);
+ ClassDB::bind_method("_text_changed",&NewProjectDialog::_text_changed);
+ ClassDB::bind_method("_path_text_changed",&NewProjectDialog::_path_text_changed);
+ ClassDB::bind_method("_path_selected",&NewProjectDialog::_path_selected);
+ ClassDB::bind_method("_file_selected",&NewProjectDialog::_file_selected);
+ ADD_SIGNAL( MethodInfo("project_created") );
+ }
+
+public:
+
+ void set_zip_path(const String& p_path) {
+ zip_path=p_path;
+ }
+ void set_zip_title(const String& p_title) {
+ zip_title=p_title;
+ }
+
+ void set_mode(Mode p_mode) {
+
+ mode=p_mode;
+ }
+
+ void show_dialog() {
+
+
+ project_path->clear();
+ project_name->clear();
+
+ if (mode==MODE_IMPORT) {
+ set_title(TTR("Import Existing Project"));
+ get_ok()->set_text(TTR("Import"));
+ pp->set_text(TTR("Project Path (Must Exist):"));
+ pn->set_text(TTR("Project Name:"));
+ pn->hide();
+ project_name->hide();
+
+ popup_centered(Size2(500,125)*EDSCALE);
+
+ } else if (mode==MODE_NEW){
+
+ set_title(TTR("Create New Project"));
+ get_ok()->set_text(TTR("Create"));
+ pp->set_text(TTR("Project Path:"));
+ pn->set_text(TTR("Project Name:"));
+ pn->show();
+ project_name->show();
+
+ popup_centered(Size2(500,145)*EDSCALE);
+ } else if (mode==MODE_INSTALL){
+
+ set_title(TTR("Install Project:")+" "+zip_title);
+ get_ok()->set_text(TTR("Install"));
+ pp->set_text(TTR("Project Path:"));
+ pn->hide();
+ project_name->hide();
+
+ popup_centered(Size2(500,125)*EDSCALE);
+
+ }
+ project_path->grab_focus();
+
+ _test_path();
+ }
+
+ NewProjectDialog() {
+
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+ //set_child_rect(vb);
+
+ Label* l = memnew(Label);
+ l->set_text(TTR("Project Path:"));
+ vb->add_child(l);
+ pp=l;
+
+ project_path = memnew( LineEdit );
+ MarginContainer *mc = memnew( MarginContainer );
+ vb->add_child(mc);
+ HBoxContainer *pphb = memnew( HBoxContainer );
+ mc->add_child(pphb);
+ pphb->add_child(project_path);
+ project_path->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ Button* browse = memnew( Button );
+ pphb->add_child(browse);
+ browse->set_text(TTR("Browse"));
+ browse->connect("pressed", this,"_browse_path");
+
+ l = memnew(Label);
+ l->set_text(TTR("Project Name:"));
+ l->set_pos(Point2(5,50));
+ vb->add_child(l);
+ pn=l;
+
+ project_name = memnew( LineEdit );
+ mc = memnew( MarginContainer );
+ vb->add_child(mc);
+ mc->add_child(project_name);
+ project_name->set_text(TTR("New Game Project"));
+
+
+ l = memnew(Label);
+ l->set_text(TTR("That's a BINGO!"));
+ vb->add_child(l);
+ error=l;
+ l->add_color_override("font_color",Color(1,0.4,0.3,0.8));
+ l->set_align(Label::ALIGN_CENTER);
+
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ project_path->set_text(d->get_current_dir());
+ memdelete(d);
+
+ fdialog = memnew( FileDialog );
+ add_child(fdialog);
+ fdialog->set_access(FileDialog::ACCESS_FILESYSTEM);
+ fdialog->set_current_dir( EditorSettings::get_singleton()->get("filesystem/directories/default_project_path") );
+ project_name->connect("text_changed", this,"_text_changed");
+ project_path->connect("text_changed", this,"_path_text_changed");
+ fdialog->connect("dir_selected", this,"_path_selected");
+ fdialog->connect("file_selected", this,"_file_selected");
+ set_hide_on_ok(false);
+ mode=MODE_NEW;
+
+ dialog_error = memnew( AcceptDialog );
+ add_child(dialog_error);
+ }
+
+
+};
+
+struct ProjectItem {
+ String project;
+ String path;
+ String conf;
+ uint64_t last_modified;
+ bool favorite;
+ ProjectItem() {}
+ ProjectItem(const String &p_project, const String &p_path, const String &p_conf, uint64_t p_last_modified, bool p_favorite=false) {
+ project = p_project; path = p_path; conf = p_conf; last_modified = p_last_modified; favorite=p_favorite;
+ }
+ _FORCE_INLINE_ bool operator <(const ProjectItem& l) const { return last_modified > l.last_modified; }
+ _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);
+
+ } else if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ set_process_unhandled_input(is_visible_in_tree());
+ }
+}
+
+void ProjectManager::_panel_draw(Node *p_hb) {
+
+ HBoxContainer *hb = p_hb->cast_to<HBoxContainer>();
+
+ hb->draw_line(Point2(0,hb->get_size().y+1),Point2(hb->get_size().x-10,hb->get_size().y+1),get_color("guide_color","Tree"));
+
+ if (selected_list.has(hb->get_meta("name"))) {
+ hb->draw_style_box( gui_base->get_stylebox("selected","Tree"),Rect2(Point2(),hb->get_size()-Size2(10,0)));
+ }
+}
+
+void ProjectManager::_update_project_buttons()
+{
+ for(int i=0;i<scroll_childs->get_child_count();i++) {
+
+ CanvasItem *item = scroll_childs->get_child(i)->cast_to<CanvasItem>();
+ item->update();
+ }
+
+ bool has_runnable_scene = false;
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
+ const String &selected_main = E->get();
+ if (selected_main == "") continue;
+ has_runnable_scene = true;
+ break;
+ }
+
+ erase_btn->set_disabled(selected_list.size()<1);
+ open_btn->set_disabled(selected_list.size()<1);
+ run_btn->set_disabled(!has_runnable_scene);
+}
+
+void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) {
+
+ if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
+
+ String clicked = p_hb->get_meta("name");
+ String clicked_main_scene = p_hb->get_meta("main_scene");
+
+ if (p_ev.key.mod.shift && selected_list.size()>0 && last_clicked!="" && clicked != last_clicked) {
+
+ int clicked_id = -1;
+ int last_clicked_id = -1;
+ for(int i=0;i<scroll_childs->get_child_count();i++) {
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+ if (hb->get_meta("name") == clicked) clicked_id = i;
+ if (hb->get_meta("name") == last_clicked) last_clicked_id = i;
+ }
+
+ if (last_clicked_id!=-1 && clicked_id!=-1) {
+ int min = clicked_id < last_clicked_id? clicked_id : last_clicked_id;
+ int max = clicked_id > last_clicked_id? clicked_id : last_clicked_id;
+ for(int i=0; i<scroll_childs->get_child_count(); ++i) {
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+ if (i!=clicked_id && (i<min || i>max) && !p_ev.key.mod.control) {
+ selected_list.erase(hb->get_meta("name"));
+ } else if (i>=min && i<=max) {
+ selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ }
+ }
+ }
+
+ } else if (selected_list.has(clicked) && p_ev.key.mod.control) {
+
+ selected_list.erase(clicked);
+
+ } else {
+
+ last_clicked = clicked;
+ if (p_ev.key.mod.control || selected_list.size()==0) {
+ selected_list.insert(clicked, clicked_main_scene);
+ } else {
+ selected_list.clear();
+ selected_list.insert(clicked, clicked_main_scene);
+ }
+ }
+
+ _update_project_buttons();
+
+ if (p_ev.mouse_button.doubleclick)
+ _open_project(); //open if doubleclicked
+
+ }
+}
+
+void ProjectManager::_unhandled_input(const InputEvent& p_ev) {
+
+ if (p_ev.type==InputEvent::KEY) {
+
+ const InputEventKey &k = p_ev.key;
+
+ if (!k.pressed)
+ return;
+
+ bool scancode_handled = true;
+
+ switch (k.scancode) {
+
+ case KEY_RETURN: {
+
+ _open_project();
+ } break;
+ case KEY_HOME: {
+
+ for (int i=0; i<scroll_childs->get_child_count(); i++) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (hb) {
+ selected_list.clear();
+ selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ scroll->set_v_scroll(0);
+ _update_project_buttons();
+ break;
+ }
+ }
+
+ } break;
+ case KEY_END: {
+
+ for (int i=scroll_childs->get_child_count()-1; i>=0; i--) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (hb) {
+ selected_list.clear();
+ selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ scroll->set_v_scroll(scroll_childs->get_size().y);
+ _update_project_buttons();
+ break;
+ }
+ }
+
+ } break;
+ case KEY_UP: {
+
+ if (k.mod.shift)
+ break;
+
+ if (selected_list.size()) {
+
+ bool found = false;
+
+ for (int i=scroll_childs->get_child_count()-1; i>=0; i--) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+
+ String current = hb->get_meta("name");
+
+ if (found) {
+ selected_list.clear();
+ selected_list.insert(current, hb->get_meta("main_scene"));
+
+ int offset_diff = scroll->get_v_scroll() - hb->get_pos().y;
+
+ if (offset_diff > 0)
+ scroll->set_v_scroll(scroll->get_v_scroll() - offset_diff);
+
+ _update_project_buttons();
+
+ break;
+
+ } else if (current==selected_list.back()->key()) {
+
+ found = true;
+ }
+ }
+
+ break;
+ }
+ // else fallthrough to key_down
+ }
+ case KEY_DOWN: {
+
+ if (k.mod.shift)
+ break;
+
+ bool found = selected_list.empty();
+
+ for (int i=0; i<scroll_childs->get_child_count(); i++) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+
+ String current = hb->get_meta("name");
+
+ if (found) {
+ selected_list.clear();
+ selected_list.insert(current, hb->get_meta("main_scene"));
+
+ int last_y_visible = scroll->get_v_scroll() + scroll->get_size().y;
+ int offset_diff = (hb->get_pos().y + hb->get_size().y) - last_y_visible;
+
+ if (offset_diff > 0)
+ scroll->set_v_scroll(scroll->get_v_scroll() + offset_diff);
+
+ _update_project_buttons();
+
+ break;
+
+ } else if (current==selected_list.back()->key()) {
+
+ found = true;
+ }
+ }
+
+ } break;
+ case KEY_F: {
+ if (k.mod.command) this->project_filter->search_box->grab_focus();
+ else scancode_handled = false;
+ } break;
+ default: {
+ scancode_handled = false;
+ } break;
+ }
+
+ if (scancode_handled) {
+ accept_event();
+ }
+ }
+}
+
+void ProjectManager::_favorite_pressed(Node *p_hb) {
+
+ String clicked = p_hb->get_meta("name");
+ bool favorite = !p_hb->get_meta("favorite");
+ String proj=clicked.replace(":::",":/");
+ proj=proj.replace("::","/");
+
+ if (favorite) {
+ EditorSettings::get_singleton()->set("favorite_projects/"+clicked,proj);
+ } else {
+ EditorSettings::get_singleton()->erase("favorite_projects/"+clicked);
+ }
+ EditorSettings::get_singleton()->save();
+ call_deferred("_load_recent_projects");
+}
+
+
+void ProjectManager::_load_recent_projects() {
+
+ ProjectListFilter::FilterOption filter_option = project_filter->get_filter_option();
+ String search_term = project_filter->get_search_term();
+
+ while(scroll_childs->get_child_count()>0) {
+ memdelete( scroll_childs->get_child(0));
+ }
+
+ Map<String, String> selected_list_copy = selected_list;
+
+ List<PropertyInfo> properties;
+ EditorSettings::get_singleton()->get_property_list(&properties);
+
+ Color font_color = gui_base->get_color("font_color","Tree");
+
+ List<ProjectItem> projects;
+ List<ProjectItem> favorite_projects;
+
+ for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
+
+ String _name = E->get().name;
+ if (!_name.begins_with("projects/") && !_name.begins_with("favorite_projects/"))
+ continue;
+
+ String path = EditorSettings::get_singleton()->get(_name);
+ if (filter_option == ProjectListFilter::FILTER_PATH && search_term!="" && path.findn(search_term)==-1)
+ continue;
+
+ String project = _name.get_slice("/",1);
+ String conf=path.plus_file("godot.cfg");
+ bool favorite = (_name.begins_with("favorite_projects/"))?true:false;
+
+ uint64_t last_modified = 0;
+ if (FileAccess::exists(conf)) {
+ last_modified = FileAccess::get_modified_time(conf);
+
+ String fscache = path.plus_file(".fscache");
+ if (FileAccess::exists(fscache)) {
+ uint64_t cache_modified = FileAccess::get_modified_time(fscache);
+ if ( cache_modified > last_modified )
+ last_modified = cache_modified;
+ }
+
+ ProjectItem item(project, path, conf, last_modified, favorite);
+ if (favorite)
+ favorite_projects.push_back(item);
+ else
+ projects.push_back(item);
+ } else {
+ //project doesn't exist on disk but it's in the XML settings file
+ EditorSettings::get_singleton()->erase(_name); //remove it
+ }
+ }
+
+ projects.sort();
+ favorite_projects.sort();
+
+ for(List<ProjectItem>::Element *E=projects.front();E;) {
+ List<ProjectItem>::Element *next = E->next();
+ if (favorite_projects.find(E->get()) != NULL)
+ projects.erase(E->get());
+ E=next;
+ }
+ for(List<ProjectItem>::Element *E=favorite_projects.back();E;E=E->prev()) {
+ projects.push_front(E->get());
+ }
+
+ Ref<Texture> favorite_icon = get_icon("Favorites","EditorIcons");
+
+ for(List<ProjectItem>::Element *E=projects.front();E;E=E->next()) {
+
+ ProjectItem &item = E->get();
+ String project = item.project;
+ String path = item.path;
+ String conf = item.conf;
+ bool is_favorite = item.favorite;
+
+ Ref<ConfigFile> cf = memnew( ConfigFile );
+ Error err = cf->load(conf);
+ ERR_CONTINUE(err!=OK);
+
+
+ String project_name=TTR("Unnamed Project");
+
+ if (cf->has_section_key("application","name")) {
+ project_name = static_cast<String>(cf->get_value("application","name")).xml_unescape();
+ }
+
+ if (filter_option==ProjectListFilter::FILTER_NAME && search_term!="" && project_name.findn(search_term)==-1)
+ continue;
+
+ Ref<Texture> icon;
+ if (cf->has_section_key("application","icon")) {
+ String appicon = cf->get_value("application","icon");
+ if (appicon!="") {
+ Image img;
+ Error err = img.load(appicon.replace_first("res://",path+"/"));
+ if (err==OK) {
+
+ img.resize(64,64);
+ Ref<ImageTexture> it = memnew( ImageTexture );
+ it->create_from_image(img);
+ icon=it;
+ }
+ }
+ }
+
+ if (icon.is_null()) {
+ icon=get_icon("DefaultProjectIcon","EditorIcons");
+ }
+
+ String main_scene;
+ if (cf->has_section_key("application","main_scene")) {
+ main_scene = cf->get_value("application","main_scene");
+ }
+
+ selected_list_copy.erase(project);
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ hb->set_meta("name",project);
+ hb->set_meta("main_scene",main_scene);
+ hb->set_meta("favorite",is_favorite);
+ hb->connect("draw",this,"_panel_draw",varray(hb));
+ hb->connect("gui_input",this,"_panel_input",varray(hb));
+ hb->add_constant_override("separation",10*EDSCALE);
+
+ VBoxContainer *favorite_box = memnew( VBoxContainer );
+ TextureButton *favorite = memnew( TextureButton );
+ favorite->set_normal_texture(favorite_icon);
+ if (!is_favorite)
+ favorite->set_modulate(Color(1,1,1,0.2));
+ favorite->set_v_size_flags(SIZE_EXPAND);
+ favorite->connect("pressed",this,"_favorite_pressed",varray(hb));
+ favorite_box->add_child(favorite);
+ hb->add_child(favorite_box);
+
+ TextureRect *tf = memnew( TextureRect );
+ tf->set_texture(icon);
+ hb->add_child(tf);
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+ vb->set_name("project");
+ hb->add_child(vb);
+ Control *ec = memnew( Control );
+ ec->set_custom_minimum_size(Size2(0,1));
+ vb->add_child(ec);
+ Label *title = memnew( Label(project_name) );
+ title->add_font_override("font", gui_base->get_font("large","Fonts"));
+ title->add_color_override("font_color",font_color);
+ vb->add_child(title);
+ Label *fpath = memnew( Label(path) );
+ fpath->set_name("path");
+ vb->add_child(fpath);
+ fpath->set_modulate(Color(1,1,1,0.5));
+ fpath->add_color_override("font_color",font_color);
+
+ scroll_childs->add_child(hb);
+ }
+
+ for (Map<String,String>::Element *E = selected_list_copy.front();E;E = E->next()) {
+ String key = E->key();
+ selected_list.erase(key);
+ }
+
+ scroll->set_v_scroll(0);
+
+ _update_project_buttons();
+
+ EditorSettings::get_singleton()->save();
+
+ tabs->set_current_tab(0);
+}
+
+void ProjectManager::_on_project_created(const String& dir) {
+ bool has_already=false;
+ for (int i=0;i<scroll_childs->get_child_count();i++) {
+ HBoxContainer *hb=scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ Label *fpath=hb->get_node(NodePath("project/path"))->cast_to<Label>();
+ if (fpath->get_text()==dir) {
+ has_already=true;
+ break;
+ }
+ }
+ if (has_already) {
+ _update_scroll_pos(dir);
+ } else {
+ _load_recent_projects();
+ scroll->connect("draw", this, "_update_scroll_pos", varray(dir), CONNECT_ONESHOT);
+ }
+}
+
+void ProjectManager::_update_scroll_pos(const String& dir) {
+ for (int i=0;i<scroll_childs->get_child_count();i++) {
+ HBoxContainer *hb=scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ Label *fpath=hb->get_node(NodePath("project/path"))->cast_to<Label>();
+ if (fpath->get_text()==dir) {
+ last_clicked=hb->get_meta("name");
+ selected_list.clear();
+ selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ _update_project_buttons();
+ int last_y_visible=scroll->get_v_scroll()+scroll->get_size().y;
+ int offset_diff=(hb->get_pos().y + hb->get_size().y)-last_y_visible;
+
+ if (offset_diff>0)
+ scroll->set_v_scroll(scroll->get_v_scroll()+offset_diff);
+ break;
+ }
+ }
+}
+
+void ProjectManager::_open_project_confirm() {
+
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
+ const String &selected = E->key();
+ String path = EditorSettings::get_singleton()->get("projects/"+selected);
+ print_line("OPENING: "+path+" ("+selected+")");
+
+ List<String> args;
+
+ args.push_back("-path");
+ args.push_back(path);
+
+ args.push_back("-editor");
+
+ String exec = OS::get_singleton()->get_executable_path();
+
+ OS::ProcessID pid=0;
+ Error err = OS::get_singleton()->execute(exec,args,false,&pid);
+ ERR_FAIL_COND(err);
+ }
+
+ get_tree()->quit();
+}
+
+void ProjectManager::_open_project() {
+
+ if (selected_list.size()<1) {
+ return;
+ }
+
+ if (selected_list.size()>1) {
+ multi_open_ask->set_text(TTR("Are you sure to open more than one project?"));
+ multi_open_ask->popup_centered_minsize();
+ } else {
+ _open_project_confirm();
+ }
+}
+
+void ProjectManager::_run_project_confirm() {
+
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
+
+ const String &selected_main = E->get();
+ if (selected_main == "") continue;
+
+ const String &selected = E->key();
+ String path = EditorSettings::get_singleton()->get("projects/"+selected);
+ print_line("OPENING: "+path+" ("+selected+")");
+
+ List<String> args;
+
+ args.push_back("-path");
+ args.push_back(path);
+
+ String exec = OS::get_singleton()->get_executable_path();
+
+ OS::ProcessID pid=0;
+ Error err = OS::get_singleton()->execute(exec,args,false,&pid);
+ ERR_FAIL_COND(err);
+ }
+ //get_scene()->quit(); do not quit
+}
+
+void ProjectManager::_run_project() {
+
+
+ if (selected_list.size()<1) {
+ return;
+ }
+
+ if (selected_list.size()>1) {
+ multi_run_ask->set_text(TTR("Are you sure to run more than one project?"));
+ multi_run_ask->popup_centered_minsize();
+ } else {
+ _run_project_confirm();
+ }
+}
+
+void ProjectManager::_scan_dir(DirAccess *da,float pos, float total,List<String> *r_projects) {
+
+
+ List<String> subdirs;
+ da->list_dir_begin();
+ String n = da->get_next();
+ while(n!=String()) {
+ if (da->current_is_dir() && !n.begins_with(".")) {
+ subdirs.push_front(n);
+ } else if (n=="godot.cfg") {
+ r_projects->push_back(da->get_current_dir());
+ }
+ n=da->get_next();
+ }
+ da->list_dir_end();
+ int m=0;
+ for(List<String>::Element *E=subdirs.front();E;E=E->next()) {
+
+ da->change_dir(E->get());
+
+ float slice=total/subdirs.size();
+ _scan_dir(da,pos+slice*m,slice,r_projects);
+ da->change_dir("..");
+ m++;
+ }
+
+
+}
+
+
+void ProjectManager::_scan_begin(const String& p_base) {
+
+ print_line("SCAN PROJECTS AT: "+p_base);
+ List<String> projects;
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->change_dir(p_base);
+ _scan_dir(da,0,1,&projects);
+ memdelete(da);
+ print_line("found: "+itos(projects.size())+" projects.");
+
+ for(List<String>::Element *E=projects.front();E;E=E->next()) {
+ String proj=E->get().replace("/","::");
+ EditorSettings::get_singleton()->set("projects/"+proj,E->get());
+
+ }
+ EditorSettings::get_singleton()->save();
+ _load_recent_projects();
+
+}
+
+void ProjectManager::_scan_projects() {
+
+ scan_dir->popup_centered_ratio();
+
+}
+
+
+void ProjectManager::_new_project() {
+
+ npdialog->set_mode(NewProjectDialog::MODE_NEW);
+ npdialog->show_dialog();
+}
+
+
+void ProjectManager::_import_project() {
+
+ npdialog->set_mode(NewProjectDialog::MODE_IMPORT);
+ npdialog->show_dialog();
+}
+
+void ProjectManager::_erase_project_confirm() {
+
+ if (selected_list.size()==0) {
+ return;
+ }
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
+ EditorSettings::get_singleton()->erase("projects/"+E->key());
+ EditorSettings::get_singleton()->erase("favorite_projects/"+E->key());
+ }
+ EditorSettings::get_singleton()->save();
+ selected_list.clear();
+ last_clicked = "";
+ _load_recent_projects();
+
+}
+
+void ProjectManager::_erase_project() {
+
+ if (selected_list.size()==0)
+ return;
+
+
+ erase_ask->set_text(TTR("Remove project from the list? (Folder contents will not be modified)"));
+ erase_ask->popup_centered_minsize();
+
+}
+
+
+void ProjectManager::_exit_dialog() {
+
+ get_tree()->quit();
+}
+
+
+void ProjectManager::_install_project(const String& p_zip_path,const String& p_title) {
+
+ npdialog->set_mode(NewProjectDialog::MODE_INSTALL);
+ npdialog->set_zip_path(p_zip_path);
+ npdialog->set_zip_title(p_title);
+ npdialog->show_dialog();
+}
+
+void ProjectManager::_files_dropped(PoolStringArray p_files, int p_screen) {
+ Set<String> folders_set;
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < p_files.size(); i++) {
+ String file = p_files[i];
+ folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
+ }
+ memdelete(da);
+ if (folders_set.size()>0) {
+ PoolStringArray folders;
+ for (Set<String>::Element *E=folders_set.front();E;E=E->next()) {
+ folders.append(E->get());
+ }
+
+ bool confirm = true;
+ if (folders.size()==1) {
+ DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (dir->change_dir(folders[0])==OK) {
+ dir->list_dir_begin();
+ String file = dir->get_next();
+ while(confirm && file!=String()) {
+ if (!dir->current_is_dir() && file.ends_with("godot.cfg")) {
+ confirm = false;
+ }
+ file = dir->get_next();
+ }
+ dir->list_dir_end();
+ }
+ memdelete(dir);
+ }
+ if (confirm) {
+ multi_scan_ask->get_ok()->disconnect("pressed", this, "_scan_multiple_folders");
+ multi_scan_ask->get_ok()->connect("pressed", this, "_scan_multiple_folders", varray(folders));
+ multi_scan_ask->set_text(vformat(TTR("You are about the scan %s folders for existing Godot projects. Do you confirm?"), folders.size()));
+ multi_scan_ask->popup_centered_minsize();
+ } else {
+ _scan_multiple_folders(folders);
+ }
+ }
+}
+
+void ProjectManager::_scan_multiple_folders(PoolStringArray p_files)
+{
+ for (int i = 0; i < p_files.size(); i++) {
+ _scan_begin(p_files.get(i));
+ }
+}
+
+void ProjectManager::_bind_methods() {
+
+ ClassDB::bind_method("_open_project",&ProjectManager::_open_project);
+ ClassDB::bind_method("_open_project_confirm",&ProjectManager::_open_project_confirm);
+ ClassDB::bind_method("_run_project",&ProjectManager::_run_project);
+ ClassDB::bind_method("_run_project_confirm",&ProjectManager::_run_project_confirm);
+ ClassDB::bind_method("_scan_projects",&ProjectManager::_scan_projects);
+ ClassDB::bind_method("_scan_begin",&ProjectManager::_scan_begin);
+ ClassDB::bind_method("_import_project",&ProjectManager::_import_project);
+ ClassDB::bind_method("_new_project",&ProjectManager::_new_project);
+ ClassDB::bind_method("_erase_project",&ProjectManager::_erase_project);
+ ClassDB::bind_method("_erase_project_confirm",&ProjectManager::_erase_project_confirm);
+ ClassDB::bind_method("_exit_dialog",&ProjectManager::_exit_dialog);
+ ClassDB::bind_method("_load_recent_projects",&ProjectManager::_load_recent_projects);
+ ClassDB::bind_method("_on_project_created",&ProjectManager::_on_project_created);
+ ClassDB::bind_method("_update_scroll_pos",&ProjectManager::_update_scroll_pos);
+ ClassDB::bind_method("_panel_draw",&ProjectManager::_panel_draw);
+ ClassDB::bind_method("_panel_input",&ProjectManager::_panel_input);
+ ClassDB::bind_method("_unhandled_input",&ProjectManager::_unhandled_input);
+ ClassDB::bind_method("_favorite_pressed",&ProjectManager::_favorite_pressed);
+ ClassDB::bind_method("_install_project",&ProjectManager::_install_project);
+ ClassDB::bind_method("_files_dropped",&ProjectManager::_files_dropped);
+ ClassDB::bind_method(D_METHOD("_scan_multiple_folders", "files"),&ProjectManager::_scan_multiple_folders);
+
+
+}
+
+ProjectManager::ProjectManager() {
+
+ // load settings
+ if (!EditorSettings::get_singleton())
+ EditorSettings::create();
+
+
+ EditorSettings::get_singleton()->set_optimize_save(false); //just write settings as they came
+
+ {
+ int dpi_mode = EditorSettings::get_singleton()->get("interface/hidpi_mode");
+ if (dpi_mode==0) {
+ editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 );
+ } else if (dpi_mode==1) {
+ editor_set_scale(0.75);
+ } else if (dpi_mode==2) {
+ editor_set_scale(1.0);
+ } else if (dpi_mode==3) {
+ editor_set_scale(1.5);
+ } else if (dpi_mode==4) {
+ editor_set_scale(2.0);
+ }
+ }
+
+ FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesytem/file_dialog/show_hidden_files"));
+
+ set_area_as_parent_rect();
+ set_theme(create_editor_theme());
+
+ gui_base = memnew( Control );
+ add_child(gui_base);
+ gui_base->set_area_as_parent_rect();
+ gui_base->set_theme(create_custom_theme());
+
+ Panel *panel = memnew( Panel );
+ gui_base->add_child(panel);
+ panel->set_area_as_parent_rect();
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ panel->add_child(vb);
+ vb->set_area_as_parent_rect(20*EDSCALE);
+ vb->set_margin(MARGIN_TOP,4*EDSCALE);
+ vb->set_margin(MARGIN_BOTTOM,4*EDSCALE);
+ vb->add_constant_override("separation",15*EDSCALE);
+
+ String cp;
+ cp.push_back(0xA9);
+ cp.push_back(0);
+ OS::get_singleton()->set_window_title(_MKSTR(VERSION_NAME)+String(" - ")+TTR("Project Manager")+" - "+cp+" 2008-2017 Juan Linietsky, Ariel Manzur.");
+
+ HBoxContainer *top_hb = memnew( HBoxContainer);
+ vb->add_child(top_hb);
+ CenterContainer *ccl = memnew( CenterContainer );
+ Label *l = memnew( Label );
+ l->set_text(_MKSTR(VERSION_NAME)+String(" - ")+TTR("Project Manager"));
+ l->add_font_override("font", gui_base->get_font("doc","EditorFonts"));
+ ccl->add_child(l);
+ top_hb->add_child(ccl);
+ top_hb->add_spacer();
+ l = memnew( Label );
+ l->set_text("v" VERSION_MKSTRING);
+ //l->add_font_override("font",get_font("bold","Fonts"));
+ l->set_align(Label::ALIGN_CENTER);
+ top_hb->add_child(l);
+ //vb->add_child(memnew(HSeparator));
+ //vb->add_margin_child("\n",memnew(Control));
+
+ tabs = memnew( TabContainer );
+ vb->add_child(tabs);
+ tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *tree_hb = memnew( HBoxContainer);
+ projects_hb = tree_hb;
+
+ projects_hb->set_name(TTR("Project List"));
+
+ tabs->add_child(tree_hb);
+
+ VBoxContainer *search_tree_vb = memnew(VBoxContainer);
+ search_tree_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ tree_hb->add_child(search_tree_vb);
+
+ HBoxContainer *search_box = memnew(HBoxContainer);
+ search_box->add_spacer(true);
+ project_filter = memnew(ProjectListFilter);
+ search_box->add_child(project_filter);
+ project_filter->connect("filter_changed", this, "_load_recent_projects");
+ project_filter->set_custom_minimum_size(Size2(250,10));
+ search_tree_vb->add_child(search_box);
+
+ PanelContainer *pc = memnew( PanelContainer);
+ pc->add_style_override("panel", gui_base->get_stylebox("bg","Tree"));
+ search_tree_vb->add_child(pc);
+ pc->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ scroll = memnew( ScrollContainer );
+ pc->add_child(scroll);
+ scroll->set_enable_h_scroll(false);
+
+ VBoxContainer *tree_vb = memnew( VBoxContainer);
+ tree_hb->add_child(tree_vb);
+ scroll_childs = memnew( VBoxContainer );
+ scroll_childs->set_h_size_flags(SIZE_EXPAND_FILL);
+ scroll->add_child(scroll_childs);
+
+ //HBoxContainer *hb = memnew( HBoxContainer );
+ //vb->add_child(hb);
+
+ Button *open = memnew( Button );
+ open->set_text(TTR("Edit"));
+ tree_vb->add_child(open);
+ open->connect("pressed", this,"_open_project");
+ open_btn=open;
+
+ Button *run = memnew( Button );
+ run->set_text(TTR("Run"));
+ tree_vb->add_child(run);
+ run->connect("pressed", this,"_run_project");
+ run_btn=run;
+
+ tree_vb->add_child(memnew( HSeparator ));
+
+ Button *scan = memnew( Button );
+ scan->set_text(TTR("Scan"));
+ tree_vb->add_child(scan);
+ scan->connect("pressed", this,"_scan_projects");
+
+ tree_vb->add_child(memnew( HSeparator ));
+
+ scan_dir = memnew( FileDialog );
+ scan_dir->set_access(FileDialog::ACCESS_FILESYSTEM);
+ scan_dir->set_mode(FileDialog::MODE_OPEN_DIR);
+ scan_dir->set_title(TTR("Select a Folder to Scan")); // must be after mode or it's overridden
+ scan_dir->set_current_dir( EditorSettings::get_singleton()->get("filesystem/directories/default_project_path") );
+ gui_base->add_child(scan_dir);
+ scan_dir->connect("dir_selected",this,"_scan_begin");
+
+
+ Button* create = memnew( Button );
+ create->set_text(TTR("New Project"));
+ tree_vb->add_child(create);
+ create->connect("pressed", this,"_new_project");
+
+ Button* import = memnew( Button );
+ import->set_text(TTR("Import"));
+ tree_vb->add_child(import);
+ import->connect("pressed", this,"_import_project");
+
+
+ Button* erase = memnew( Button );
+ erase->set_text(TTR("Remove"));
+ tree_vb->add_child(erase);
+ erase->connect("pressed", this,"_erase_project");
+ erase_btn=erase;
+
+
+ tree_vb->add_spacer();
+
+
+ if (StreamPeerSSL::is_available()) {
+ asset_library = memnew( EditorAssetLibrary(true) );
+ asset_library->set_name("Templates");
+ tabs->add_child(asset_library);
+ asset_library->connect("install_asset",this,"_install_project");
+ } else {
+ WARN_PRINT("Asset Library not available, as it requires SSL to work.");
+ }
+
+
+ CenterContainer *cc = memnew( CenterContainer );
+ Button * cancel = memnew( Button );
+ cancel->set_text(TTR("Exit"));
+ cancel->set_custom_minimum_size(Size2(100,1)*EDSCALE);
+ cc->add_child(cancel);
+ cancel->connect("pressed", this,"_exit_dialog");
+ vb->add_child(cc);
+
+ //
+
+ erase_ask = memnew( ConfirmationDialog );
+ erase_ask->get_ok()->set_text(TTR("Remove"));
+ erase_ask->get_ok()->connect("pressed", this,"_erase_project_confirm");
+
+ gui_base->add_child(erase_ask);
+
+ multi_open_ask = memnew( ConfirmationDialog );
+ multi_open_ask->get_ok()->set_text(TTR("Edit"));
+ multi_open_ask->get_ok()->connect("pressed", this, "_open_project_confirm");
+
+ gui_base->add_child(multi_open_ask);
+
+ multi_run_ask = memnew( ConfirmationDialog );
+ multi_run_ask->get_ok()->set_text(TTR("Run"));
+ multi_run_ask->get_ok()->connect("pressed", this, "_run_project_confirm");
+
+ gui_base->add_child(multi_run_ask);
+
+ multi_scan_ask = memnew( ConfirmationDialog );
+ multi_scan_ask->get_ok()->set_text(TTR("Scan"));
+
+ gui_base->add_child(multi_scan_ask);
+
+ OS::get_singleton()->set_low_processor_usage_mode(true);
+
+ npdialog = memnew( NewProjectDialog );
+ gui_base->add_child(npdialog);
+
+ npdialog->connect("project_created", this,"_on_project_created");
+ _load_recent_projects();
+
+ if ( EditorSettings::get_singleton()->get("filesystem/directories/autoscan_project_path") ) {
+ _scan_begin( EditorSettings::get_singleton()->get("filesystem/directories/autoscan_project_path") );
+ }
+
+ //get_ok()->set_text("Open");
+ //get_ok()->set_text("Exit");
+
+ last_clicked = "";
+
+ SceneTree::get_singleton()->connect("files_dropped", this, "_files_dropped");
+}
+
+
+ProjectManager::~ProjectManager() {
+
+ if (EditorSettings::get_singleton())
+ EditorSettings::destroy();
+}
+
+void ProjectListFilter::_setup_filters() {
+
+ filter_option->clear();
+ filter_option->add_item(TTR("Name"));
+ filter_option->add_item(TTR("Path"));
+}
+
+void ProjectListFilter::_command(int p_command) {
+ switch (p_command) {
+
+ case CMD_CLEAR_FILTER: {
+ if (search_box->get_text()!="") {
+ search_box->clear();
+ emit_signal("filter_changed");
+ }
+ }break;
+ }
+}
+
+void ProjectListFilter::_search_text_changed(const String &p_newtext) {
+ emit_signal("filter_changed");
+}
+
+String ProjectListFilter::get_search_term() {
+ return search_box->get_text().strip_edges();
+}
+
+ProjectListFilter::FilterOption ProjectListFilter::get_filter_option() {
+ return _current_filter;
+}
+
+void ProjectListFilter::_filter_option_selected(int p_idx) {
+ FilterOption selected = (FilterOption)(filter_option->get_selected());
+ if (_current_filter != selected ) {
+ _current_filter = selected;
+ emit_signal("filter_changed");
+ }
+}
+
+void ProjectListFilter::_notification(int p_what) {
+ switch(p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ clear_search_button->set_icon(get_icon("CloseHover","EditorIcons"));
+ } break;
+ }
+}
+
+void ProjectListFilter::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_command"),&ProjectListFilter::_command);
+ ClassDB::bind_method(D_METHOD("_search_text_changed"), &ProjectListFilter::_search_text_changed);
+ ClassDB::bind_method(D_METHOD("_filter_option_selected"), &ProjectListFilter::_filter_option_selected);
+
+ ADD_SIGNAL( MethodInfo("filter_changed") );
+}
+
+ProjectListFilter::ProjectListFilter() {
+
+ editor_initialize_certificates(); //for asset sharing
+
+ _current_filter = FILTER_NAME;
+
+ filter_option = memnew(OptionButton);
+ filter_option->set_custom_minimum_size(Size2(80,10));
+ filter_option->set_clip_text(true);
+ filter_option->connect("item_selected", this, "_filter_option_selected");
+ add_child(filter_option);
+
+ _setup_filters();
+
+ search_box = memnew( LineEdit );
+ search_box->connect("text_changed",this,"_search_text_changed");
+ search_box->set_h_size_flags(SIZE_EXPAND_FILL);
+ add_child(search_box);
+
+ clear_search_button = memnew( ToolButton );
+ clear_search_button->connect("pressed",this,"_command",make_binds(CMD_CLEAR_FILTER));
+ add_child(clear_search_button);
+
+}
diff --git a/editor/project_manager.h b/editor/project_manager.h
new file mode 100644
index 0000000000..cb6c0b7f26
--- /dev/null
+++ b/editor/project_manager.h
@@ -0,0 +1,148 @@
+/*************************************************************************/
+/* project_manager.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PROJECT_MANAGER_H
+#define PROJECT_MANAGER_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/file_dialog.h"
+#include "scene/gui/tool_button.h"
+#include "editor/asset_library_editor_plugin.h"
+
+class NewProjectDialog;
+class ProjectListFilter;
+
+class ProjectManager : public Control {
+ GDCLASS( ProjectManager, Control );
+
+ Button *erase_btn;
+ Button *open_btn;
+ Button *run_btn;
+
+ FileDialog *scan_dir;
+
+ EditorAssetLibrary *asset_library;
+
+ ProjectListFilter *project_filter;
+
+ ConfirmationDialog *erase_ask;
+ ConfirmationDialog *multi_open_ask;
+ ConfirmationDialog *multi_run_ask;
+ ConfirmationDialog *multi_scan_ask;
+ NewProjectDialog *npdialog;
+ ScrollContainer *scroll;
+ VBoxContainer *scroll_childs;
+ Map<String, String> selected_list; // name -> main_scene
+ String last_clicked;
+ bool importing;
+
+ HBoxContainer *projects_hb;
+
+ TabContainer *tabs;
+
+ Control *gui_base;
+
+
+
+ void _scan_projects();
+ void _run_project();
+ void _run_project_confirm();
+ void _open_project();
+ void _open_project_confirm();
+ void _import_project();
+ void _new_project();
+ void _erase_project();
+ void _erase_project_confirm();
+ void _update_project_buttons();
+ void _exit_dialog();
+ void _scan_begin(const String& p_base);
+
+ void _load_recent_projects();
+ void _on_project_created(const String& dir);
+ void _update_scroll_pos(const String& dir);
+ void _scan_dir(DirAccess *da,float pos, float total,List<String> *r_projects);
+
+ void _install_project(const String& p_zip_path,const String& p_title);
+
+ void _panel_draw(Node *p_hb);
+ void _panel_input(const InputEvent& p_ev,Node *p_hb);
+ void _unhandled_input(const InputEvent& p_ev);
+ void _favorite_pressed(Node *p_hb);
+ void _files_dropped(PoolStringArray p_files, int p_screen);
+ void _scan_multiple_folders(PoolStringArray p_files);
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+ ProjectManager();
+ ~ProjectManager();
+};
+
+class ProjectListFilter : public HBoxContainer {
+
+ GDCLASS( ProjectListFilter, HBoxContainer );
+
+private:
+
+ friend class ProjectManager;
+
+ enum Command {
+ CMD_CLEAR_FILTER,
+ };
+
+ OptionButton *filter_option;
+ LineEdit *search_box;
+ ToolButton *clear_search_button;
+
+ enum FilterOption {
+ FILTER_NAME,
+ FILTER_PATH,
+ };
+ FilterOption _current_filter;
+
+ void _command(int p_command);
+ void _search_text_changed(const String& p_newtext);
+ void _setup_filters();
+ void _filter_option_selected(int p_idx);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+
+ String get_search_term();
+ FilterOption get_filter_option();
+ ProjectListFilter();
+};
+
+#endif // PROJECT_MANAGER_H
diff --git a/editor/project_settings.cpp b/editor/project_settings.cpp
new file mode 100644
index 0000000000..15019b8ca8
--- /dev/null
+++ b/editor/project_settings.cpp
@@ -0,0 +1,1603 @@
+/*************************************************************************/
+/* project_settings.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "project_settings.h"
+
+#include "scene/gui/tab_container.h"
+#include "global_config.h"
+#include "os/keyboard.h"
+#include "editor_node.h"
+#include "scene/gui/margin_container.h"
+#include "translation.h"
+#include "global_constants.h"
+
+ProjectSettings *ProjectSettings::singleton=NULL;
+
+static const char* _button_names[JOY_BUTTON_MAX]={
+"PS X, XBox A, Nintendo B",
+"PS Circle, XBox B, Nintendo A",
+"PS Square, XBox X, Nintendo Y",
+"PS Triangle, XBox Y, Nintendo X",
+"L, L1",
+"R, R1",
+"L2",
+"R2",
+"L3",
+"R3",
+"Select, Nintendo -",
+"Start, Nintendo +",
+"D-Pad Up",
+"D-Pad Down",
+"D-Pad Left",
+"D-Pad Right"
+};
+
+static const char* _axis_names[JOY_AXIS_MAX*2] = {
+ " (Left Stick Left)",
+ " (Left Stick Right)",
+ " (Left Stick Up)",
+ " (Left Stick Down)",
+ " (Right Stick Left)",
+ " (Right Stick Right)",
+ " (Right Stick Up)",
+ " (Right Stick Down)",
+ "","","","",
+ "", " (L2)",
+ "", " (R2)"
+};
+
+void ProjectSettings::_notification(int p_what) {
+
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ globals_editor->edit(GlobalConfig::get_singleton());
+
+ search_button->set_icon(get_icon("Zoom","EditorIcons"));
+ clear_button->set_icon(get_icon("Close","EditorIcons"));
+
+ translation_list->connect("button_pressed",this,"_translation_delete");
+ _update_actions();
+ popup_add->add_icon_item(get_icon("Keyboard","EditorIcons"),TTR("Key "),InputEvent::KEY);//"Key " - because the word 'key' has already been used as a key animation
+ popup_add->add_icon_item(get_icon("JoyButton","EditorIcons"),TTR("Joy Button"),InputEvent::JOYPAD_BUTTON);
+ popup_add->add_icon_item(get_icon("JoyAxis","EditorIcons"),TTR("Joy Axis"),InputEvent::JOYPAD_MOTION);
+ popup_add->add_icon_item(get_icon("Mouse","EditorIcons"),TTR("Mouse Button"),InputEvent::MOUSE_BUTTON);
+
+ List<String> tfn;
+ ResourceLoader::get_recognized_extensions_for_type("Translation",&tfn);
+ for (List<String>::Element *E=tfn.front();E;E=E->next()) {
+
+ translation_file_open->add_filter("*."+E->get());
+ }
+
+ List<String> rfn;
+ ResourceLoader::get_recognized_extensions_for_type("Resource",&rfn);
+ for (List<String>::Element *E=rfn.front();E;E=E->next()) {
+
+ translation_res_file_open->add_filter("*."+E->get());
+ translation_res_option_file_open->add_filter("*."+E->get());
+ }
+ } break;
+ case NOTIFICATION_POPUP_HIDE: {
+ EditorSettings::get_singleton()->set("interface/dialogs/project_settings_bounds", get_rect());
+ } break;
+ }
+}
+
+void ProjectSettings::_action_selected() {
+
+ TreeItem *ti=input_editor->get_selected();
+ if (!ti || !ti->is_editable(0))
+ return;
+
+ add_at="input/"+ti->get_text(0);
+}
+
+void ProjectSettings::_action_edited() {
+
+ TreeItem *ti=input_editor->get_selected();
+ if (!ti)
+ return;
+
+ String new_name=ti->get_text(0);
+ String old_name=add_at.substr(add_at.find("/")+1,add_at.length());
+
+ if (new_name==old_name)
+ return;
+
+ if (new_name.find("/")!=-1 || new_name.find(":")!=-1 || new_name=="") {
+
+ ti->set_text(0,old_name);
+ add_at="input/"+old_name;
+
+ message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ String action_prop="input/"+new_name;
+
+ if (GlobalConfig::get_singleton()->has(action_prop)) {
+
+ ti->set_text(0,old_name);
+ add_at="input/"+old_name;
+
+ message->set_text(vformat(TTR("Action '%s' already exists!"),new_name));
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ int order = GlobalConfig::get_singleton()->get_order(add_at);
+ Array va = GlobalConfig::get_singleton()->get(add_at);
+
+ setting=true;
+ undo_redo->create_action(TTR("Rename Input Action Event"));
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"clear",add_at);
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",action_prop,va);
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"set_order",action_prop,order);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"clear",action_prop);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",add_at,va);
+ undo_redo->add_undo_method(GlobalConfig::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();
+ setting=false;
+
+ add_at=action_prop;
+
+}
+
+
+void ProjectSettings::_device_input_add() {
+
+
+
+
+ InputEvent ie;
+ String name=add_at;
+ Variant old_val = GlobalConfig::get_singleton()->get(name);
+ Array arr=old_val;
+ ie.device=device_id->get_value();
+
+ ie.type=add_type;
+
+ switch(add_type) {
+
+ case InputEvent::MOUSE_BUTTON: {
+
+
+ ie.mouse_button.button_index=device_index->get_selected()+1;
+
+ for(int i=0;i<arr.size();i++) {
+
+ InputEvent aie=arr[i];
+ if (aie.device == ie.device && aie.type==InputEvent::MOUSE_BUTTON && aie.mouse_button.button_index==ie.mouse_button.button_index) {
+ return;
+ }
+ }
+
+ } break;
+ case InputEvent::JOYPAD_MOTION: {
+
+ 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::JOYPAD_MOTION && aie.joy_motion.axis==ie.joy_motion.axis && aie.joy_motion.axis_value==ie.joy_motion.axis_value) {
+ return;
+ }
+ }
+
+ } break;
+ case InputEvent::JOYPAD_BUTTON: {
+
+ ie.joy_button.button_index=device_index->get_selected();
+
+ for(int i=0;i<arr.size();i++) {
+
+ InputEvent aie=arr[i];
+ if (aie.device == ie.device && aie.type==InputEvent::JOYPAD_BUTTON && aie.joy_button.button_index==ie.joy_button.button_index) {
+ return;
+ }
+ }
+
+ } break;
+ default:{}
+ }
+
+
+ arr.push_back(ie);
+
+ undo_redo->create_action(TTR("Add Input Action Event"));
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,arr);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
+ 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();
+
+ _show_last_added(ie, name);
+}
+
+
+void ProjectSettings::_press_a_key_confirm() {
+
+ if (last_wait_for_key.type!=InputEvent::KEY)
+ return;
+
+ InputEvent ie;
+ ie.type=InputEvent::KEY;
+ ie.key.scancode=last_wait_for_key.key.scancode;
+ ie.key.mod=last_wait_for_key.key.mod;
+ String name=add_at;
+
+ Variant old_val = GlobalConfig::get_singleton()->get(name);
+ Array arr=old_val;
+
+ for(int i=0;i<arr.size();i++) {
+
+ InputEvent aie=arr[i];
+ if (aie.type==InputEvent::KEY && aie.key.scancode==ie.key.scancode && aie.key.mod==ie.key.mod) {
+ return;
+ }
+ }
+
+ arr.push_back(ie);
+
+ undo_redo->create_action(TTR("Add Input Action Event"));
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,arr);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
+ 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();
+
+ _show_last_added(ie, name);
+}
+
+void ProjectSettings::_show_last_added(const InputEvent& p_event, const String &p_name) {
+ TreeItem *r = input_editor->get_root();
+
+ String name = p_name;
+ name.erase(0,6);
+ if (!r)
+ return;
+ r=r->get_children();
+ if (!r)
+ return;
+ bool found = false;
+ while(r){
+ if (r->get_text(0) != name) {
+ r=r->get_next();
+ continue;
+ }
+ TreeItem *child = r->get_children();
+ while(child){
+ Variant input = child->get_meta("__input");
+ if (p_event==input){
+ child->select(0);
+ found = true;
+ break;
+ }
+ child=child->get_next();
+ }
+ if (found) break;
+ r=r->get_next();
+ }
+
+ if (found) input_editor->ensure_cursor_is_visible();
+}
+
+void ProjectSettings::_wait_for_key(const InputEvent& p_event) {
+
+
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode!=0) {
+
+ last_wait_for_key=p_event;
+ String str=keycode_get_string(p_event.key.scancode).capitalize();
+ if (p_event.key.mod.meta)
+ str=TTR("Meta+")+str;
+ if (p_event.key.mod.shift)
+ str=TTR("Shift+")+str;
+ if (p_event.key.mod.alt)
+ str=TTR("Alt+")+str;
+ if (p_event.key.mod.control)
+ str=TTR("Control+")+str;
+
+
+ press_a_key_label->set_text(str);
+ press_a_key->accept_event();
+
+ }
+}
+
+
+void ProjectSettings::_add_item(int p_item){
+
+ add_type=InputEvent::Type(p_item);
+
+ switch(add_type) {
+
+ case InputEvent::KEY: {
+
+ press_a_key_label->set_text(TTR("Press a Key.."));
+ last_wait_for_key=InputEvent();
+ press_a_key->popup_centered(Size2(250,80)*EDSCALE);
+ press_a_key->grab_focus();
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ device_id->set_value(0);
+ device_index_label->set_text(TTR("Mouse Button Index:"));
+ device_index->clear();
+ device_index->add_item(TTR("Left Button"));
+ device_index->add_item(TTR("Right Button"));
+ device_index->add_item(TTR("Middle Button"));
+ device_index->add_item(TTR("Wheel Up Button"));
+ device_index->add_item(TTR("Wheel Down Button"));
+ device_index->add_item(TTR("Button 6"));
+ device_index->add_item(TTR("Button 7"));
+ device_index->add_item(TTR("Button 8"));
+ device_index->add_item(TTR("Button 9"));
+ device_input->popup_centered_minsize(Size2(350,95));
+ } break;
+ case InputEvent::JOYPAD_MOTION: {
+
+ device_id->set_value(0);
+ device_index_label->set_text(TTR("Joypad Axis Index:"));
+ device_index->clear();
+ for(int i=0;i<JOY_AXIS_MAX*2;i++) {
+
+ String desc = _axis_names[i];
+ device_index->add_item(TTR("Axis")+" "+itos(i/2)+" "+(i&1?"+":"-")+desc);
+ }
+ device_input->popup_centered_minsize(Size2(350,95));
+
+ } break;
+ case InputEvent::JOYPAD_BUTTON: {
+
+ device_id->set_value(0);
+ device_index_label->set_text(TTR("Joypad Button Index:"));
+ device_index->clear();
+
+ for(int i=0;i<JOY_BUTTON_MAX;i++) {
+
+ device_index->add_item(itos(i)+": "+String(_button_names[i]));
+ }
+ device_input->popup_centered_minsize(Size2(350,95));
+
+ } break;
+ default:{}
+ }
+}
+
+
+
+
+void ProjectSettings::_action_button_pressed(Object* p_obj, int p_column,int p_id) {
+
+ TreeItem *ti=p_obj->cast_to<TreeItem>();
+
+ ERR_FAIL_COND(!ti);
+
+ if (p_id==1) {
+ Point2 ofs = input_editor->get_global_pos();
+ Rect2 ir=input_editor->get_item_rect(ti);
+ ir.pos.y-=input_editor->get_scroll().y;
+ ofs+=ir.pos+ir.size;
+ ofs.x-=100;
+ popup_add->set_pos(ofs);
+ popup_add->popup();
+ add_at="input/"+ti->get_text(0);
+
+ } else if (p_id==2) {
+ //remove
+
+ if (ti->get_parent()==input_editor->get_root()) {
+
+ //remove main thing
+
+ String name="input/"+ti->get_text(0);
+ Variant old_val = GlobalConfig::get_singleton()->get(name);
+ int order=GlobalConfig::get_singleton()->get_order(name);
+
+ undo_redo->create_action(TTR("Add Input Action"));
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"clear",name);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set_order",name,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();
+
+ } else {
+ //remove action
+ String name="input/"+ti->get_parent()->get_text(0);
+ Variant old_val = GlobalConfig::get_singleton()->get(name);
+ int idx = ti->get_metadata(0);
+
+ Array va = old_val;
+
+ ERR_FAIL_INDEX(idx,va.size());
+
+ for(int i=idx;i<va.size()-1;i++) {
+
+ va[i]=va[i+1];
+ }
+
+ va.resize(va.size()-1);
+
+
+ undo_redo->create_action(TTR("Erase Input Action Event"));
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,va);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
+ 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();
+
+ }
+ }
+
+}
+
+
+void ProjectSettings::_update_actions() {
+
+ if (setting)
+ return;
+
+ input_editor->clear();
+ TreeItem *root = input_editor->create_item();
+ input_editor->set_hide_root(true);
+
+ List<PropertyInfo> props;
+ GlobalConfig::get_singleton()->get_property_list(&props);
+
+ for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+
+ const PropertyInfo &pi=E->get();
+ if (!pi.name.begins_with("input/"))
+ continue;
+
+ String name = pi.name.get_slice("/",1);
+ if (name=="")
+ continue;
+
+ TreeItem *item=input_editor->create_item(root);
+ //item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ item->set_text(0,name);
+ item->add_button(0,get_icon("Add","EditorIcons"),1);
+ if (!GlobalConfig::get_singleton()->get_input_presets().find(pi.name)) {
+ item->add_button(0,get_icon("Remove","EditorIcons"),2);
+ item->set_editable(0,true);
+ }
+ item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
+ //item->set_checked(0,pi.usage&PROPERTY_USAGE_CHECKED);
+
+
+ Array actions=GlobalConfig::get_singleton()->get(pi.name);
+
+ for(int i=0;i<actions.size();i++) {
+
+ if (actions[i].get_type()!=Variant::INPUT_EVENT)
+ continue;
+ InputEvent ie = actions[i];
+
+ TreeItem *action = input_editor->create_item(item);
+
+ switch(ie.type) {
+
+ case InputEvent::KEY: {
+
+ String str=keycode_get_string(ie.key.scancode).capitalize();
+ if (ie.key.mod.meta)
+ str=TTR("Meta+")+str;
+ if (ie.key.mod.shift)
+ str=TTR("Shift+")+str;
+ if (ie.key.mod.alt)
+ str=TTR("Alt+")+str;
+ if (ie.key.mod.control)
+ str=TTR("Control+")+str;
+
+ action->set_text(0,str);
+ action->set_icon(0,get_icon("Keyboard","EditorIcons"));
+
+ } break;
+ case InputEvent::JOYPAD_BUTTON: {
+
+ String str = TTR("Device")+" "+itos(ie.device)+", "+TTR("Button")+" "+itos(ie.joy_button.button_index);
+ if (ie.joy_button.button_index>=0 && ie.joy_button.button_index<JOY_BUTTON_MAX)
+ str+=String()+" ("+_button_names[ie.joy_button.button_index]+").";
+ else
+ str+=".";
+
+ action->set_text(0,str);
+ action->set_icon(0,get_icon("JoyButton","EditorIcons"));
+ } break;
+ case InputEvent::MOUSE_BUTTON: {
+
+ String str = TTR("Device")+" "+itos(ie.device)+", ";
+ switch (ie.mouse_button.button_index) {
+ case BUTTON_LEFT: str+=TTR("Left Button."); break;
+ case BUTTON_RIGHT: str+=TTR("Right Button."); break;
+ case BUTTON_MIDDLE: str+=TTR("Middle Button."); break;
+ case BUTTON_WHEEL_UP: str+=TTR("Wheel Up."); break;
+ case BUTTON_WHEEL_DOWN: str+=TTR("Wheel Down."); break;
+ default: str+=TTR("Button")+" "+itos(ie.mouse_button.button_index)+".";
+ }
+
+ action->set_text(0,str);
+ action->set_icon(0,get_icon("Mouse","EditorIcons"));
+ } break;
+ case InputEvent::JOYPAD_MOTION: {
+
+ int ax = ie.joy_motion.axis;
+ int n = 2*ax + (ie.joy_motion.axis_value<0 ? 0:1);
+ String desc = _axis_names[n];
+ String str = TTR("Device")+" "+itos(ie.device)+", "+TTR("Axis")+" "+itos(ax)+" "+(ie.joy_motion.axis_value<0?"-":"+")+desc +".";
+ action->set_text(0,str);
+ action->set_icon(0,get_icon("JoyAxis","EditorIcons"));
+ } break;
+ }
+ action->add_button(0,get_icon("Remove","EditorIcons"),2);
+ action->set_metadata(0,i);
+ action->set_meta("__input", ie);
+ }
+ }
+}
+
+
+void ProjectSettings::popup_project_settings() {
+
+ // Restore valid window bounds or pop up at default size.
+ if (EditorSettings::get_singleton()->has("interface/dialogs/project_settings_bounds")) {
+ popup(EditorSettings::get_singleton()->get("interface/dialogs/project_settings_bounds"));
+ } else {
+ popup_centered_ratio();
+ }
+ globals_editor->update_category_list();
+ _update_translations();
+ autoload_settings->update_autoload();
+ plugin_settings->update_plugins();
+}
+
+
+void ProjectSettings::_item_selected() {
+
+
+ TreeItem *ti = globals_editor->get_property_editor()->get_scene_tree()->get_selected();
+ if (!ti)
+ return;
+ if (!ti->get_parent())
+ return;
+ category->set_text(globals_editor->get_current_section());
+ property->set_text(ti->get_text(0));
+ popup_platform->set_disabled(false);
+
+
+}
+
+
+void ProjectSettings::_item_adds(String) {
+
+ _item_add();
+}
+
+void ProjectSettings::_item_add() {
+
+ Variant value;
+ switch(type->get_selected()) {
+ case 0: value=false; break;
+ case 1: value=0; break;
+ case 2: value=0.0; break;
+ case 3: value=""; break;
+ }
+
+ String catname = category->get_text().strip_edges();
+ /*if (!catname.is_valid_identifier()) {
+ message->set_text("Invalid Category.\nValid characters: a-z,A-Z,0-9 or _");
+ message->popup_centered(Size2(300,100));
+ return;
+ }*/
+
+ String propname = property->get_text().strip_edges();
+ /*if (!propname.is_valid_identifier()) {
+ message->set_text("Invalid Property.\nValid characters: a-z,A-Z,0-9 or _");
+ message->popup_centered(Size2(300,100));
+ return;
+ }*/
+
+ String name = catname!="" ? catname+"/"+propname : propname;
+
+ undo_redo->create_action("Add Global Property");
+
+ undo_redo->add_do_property(GlobalConfig::get_singleton(), name, value);
+
+ if (GlobalConfig::get_singleton()->has(name)) {
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
+ } else {
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, Variant());
+ }
+
+ undo_redo->add_do_method(globals_editor, "update_category_list");
+ undo_redo->add_undo_method(globals_editor, "update_category_list");
+
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+
+ undo_redo->commit_action();
+
+ globals_editor->set_current_section(catname);
+
+ _settings_changed();
+}
+
+void ProjectSettings::_item_del() {
+
+ String catname = category->get_text().strip_edges();
+ //ERR_FAIL_COND(!catname.is_valid_identifier());
+ String propname = property->get_text().strip_edges();
+ //ERR_FAIL_COND(!propname.is_valid_identifier());
+
+ String name = catname!="" ? catname+"/"+propname : propname;
+
+ undo_redo->create_action("Delete Global Property");
+
+ undo_redo->add_do_property(GlobalConfig::get_singleton(), name, Variant());
+
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
+
+ undo_redo->add_do_method(globals_editor, "update_category_list");
+ undo_redo->add_undo_method(globals_editor, "update_category_list");
+
+ undo_redo->add_do_method(this, "_settings_changed");
+ undo_redo->add_undo_method(this, "_settings_changed");
+
+ undo_redo->commit_action();
+
+ _settings_changed();
+}
+
+void ProjectSettings::_action_adds(String) {
+
+ _action_add();
+}
+
+void ProjectSettings::_action_add() {
+
+ String action = action_name->get_text();
+ if (action.find("/")!=-1 || action.find(":")!=-1 || action=="") {
+ message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ if (GlobalConfig::get_singleton()->has("input/"+action)) {
+ message->set_text(vformat(TTR("Action '%s' already exists!"),action));
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ Array va;
+ String name = "input/"+action;
+ undo_redo->create_action(TTR("Add Input Action Event"));
+ undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,va);
+ undo_redo->add_undo_method(GlobalConfig::get_singleton(),"clear",name);
+ 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();
+
+ TreeItem *r = input_editor->get_root();
+
+ if (!r)
+ return;
+ r=r->get_children();
+ if (!r)
+ return;
+ while(r->get_next())
+ r=r->get_next();
+
+ if (!r)
+ return;
+ r->select(0);
+ input_editor->ensure_cursor_is_visible();
+
+}
+
+
+void ProjectSettings::_item_checked(const String& p_item, bool p_check) {
+
+
+
+}
+
+
+void ProjectSettings::_save() {
+
+ Error err = GlobalConfig::get_singleton()->save();
+ message->set_text(err!=OK?TTR("Error saving settings."):TTR("Settings saved OK."));
+ message->popup_centered(Size2(300,100));
+}
+
+
+
+void ProjectSettings::_settings_prop_edited(const String& p_name) {
+
+ String full_item = globals_editor->get_full_item_path(p_name);
+
+ _settings_changed();
+}
+
+void ProjectSettings::_settings_changed() {
+
+ timer->start();
+}
+
+void ProjectSettings::queue_save() {
+ _settings_changed();
+}
+
+
+void ProjectSettings::_copy_to_platform(int p_which) {
+
+ String catname = category->get_text();
+ if (!catname.is_valid_identifier()) {
+ message->set_text("Invalid Category.\nValid characters: a-z,A-Z,0-9 or _");
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+
+ String propname = property->get_text();
+ if (!propname.is_valid_identifier()) {
+ message->set_text("Invalid Property.\nValid characters: a-z,A-Z,0-9 or _");
+ message->popup_centered(Size2(300,100));
+ return;
+ }
+
+ String name = catname+"/"+propname;
+ Variant value=GlobalConfig::get_singleton()->get(name);
+
+ catname+="."+popup_platform->get_popup()->get_item_text(p_which);
+ name = catname+"/"+propname;
+
+ GlobalConfig::get_singleton()->set(name,value);
+ globals_editor->get_property_editor()->update_tree();
+
+}
+
+
+void ProjectSettings::add_translation(const String& p_translation) {
+
+ _translation_add(p_translation);
+}
+
+void ProjectSettings::_translation_add(const String& p_path) {
+
+ PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
+
+
+ for(int i=0;i<translations.size();i++) {
+
+ if (translations[i]==p_path)
+ return; //exists
+ }
+
+ translations.push_back(p_path);
+ undo_redo->create_action(TTR("Add Translation"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translations",translations);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translations",GlobalConfig::get_singleton()->get("locale/translations"));
+ undo_redo->add_do_method(this,"_update_translations");
+ undo_redo->add_undo_method(this,"_update_translations");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+
+}
+
+void ProjectSettings::_translation_file_open() {
+
+ translation_file_open->popup_centered_ratio();
+}
+
+void ProjectSettings::_translation_delete(Object *p_item,int p_column, int p_button) {
+
+ TreeItem *ti = p_item->cast_to<TreeItem>();
+ ERR_FAIL_COND(!ti);
+
+ int idx=ti->get_metadata(0);
+
+ PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
+
+ ERR_FAIL_INDEX(idx,translations.size());
+
+ translations.remove(idx);
+
+ undo_redo->create_action(TTR("Remove Translation"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translations",translations);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translations",GlobalConfig::get_singleton()->get("locale/translations"));
+ undo_redo->add_do_method(this,"_update_translations");
+ undo_redo->add_undo_method(this,"_update_translations");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+
+
+}
+
+void ProjectSettings::_translation_res_file_open() {
+
+ translation_res_file_open->popup_centered_ratio();
+
+}
+
+void ProjectSettings::_translation_res_add(const String& p_path){
+
+ Variant prev;
+ Dictionary remaps;
+
+ if (GlobalConfig::get_singleton()->has("locale/translation_remaps")) {
+ remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
+ prev=remaps;
+ }
+
+ if (remaps.has(p_path))
+ return; //pointless already has it
+
+ remaps[p_path]=PoolStringArray();
+
+ undo_redo->create_action(TTR("Add Remapped Path"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",prev);
+ undo_redo->add_do_method(this,"_update_translations");
+ undo_redo->add_undo_method(this,"_update_translations");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+
+}
+
+void ProjectSettings::_translation_res_option_file_open(){
+
+ translation_res_option_file_open->popup_centered_ratio();
+
+}
+void ProjectSettings::_translation_res_option_add(const String& p_path) {
+
+ ERR_FAIL_COND(!GlobalConfig::get_singleton()->has("locale/translation_remaps"));
+
+ Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
+
+ TreeItem *k = translation_remap->get_selected();
+ ERR_FAIL_COND(!k);
+
+ String key = k->get_metadata(0);
+
+ ERR_FAIL_COND(!remaps.has(key));
+ PoolStringArray r = remaps[key];
+ r.push_back(p_path+":"+"en");
+ remaps[key]=r;
+
+
+ undo_redo->create_action(TTR("Resource Remap Add Remap"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_method(this,"_update_translations");
+ undo_redo->add_undo_method(this,"_update_translations");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+
+}
+
+
+
+void ProjectSettings::_translation_res_select() {
+
+ if (updating_translations)
+ return;
+
+
+ call_deferred("_update_translations");
+}
+
+void ProjectSettings::_translation_res_option_changed() {
+
+ if (updating_translations)
+ return;
+
+ if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
+ return;
+
+ Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
+
+ TreeItem *k = translation_remap->get_selected();
+ ERR_FAIL_COND(!k);
+ TreeItem *ed = translation_remap_options->get_edited();
+ ERR_FAIL_COND(!ed);
+
+ String key = k->get_metadata(0);
+ int idx = ed->get_metadata(0);
+ String path = ed->get_metadata(1);
+ int which = ed->get_range(1);
+
+ Vector<String> langs = TranslationServer::get_all_locales();
+
+ ERR_FAIL_INDEX(which,langs.size());
+
+
+ ERR_FAIL_COND(!remaps.has(key));
+ PoolStringArray r = remaps[key];
+ ERR_FAIL_INDEX(idx,r.size());
+ r.set(idx,path+":"+langs[which]);
+ remaps[key]=r;
+
+ updating_translations=true;
+ undo_redo->create_action(TTR("Change Resource Remap Language"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_method(this,"_update_translations");
+ undo_redo->add_undo_method(this,"_update_translations");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+ updating_translations=false;
+
+}
+
+
+void ProjectSettings::_translation_res_delete(Object *p_item,int p_column, int p_button) {
+
+
+ if (updating_translations)
+ return;
+
+ if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
+ return;
+
+ Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
+
+ TreeItem *k = p_item->cast_to<TreeItem>();
+
+ String key = k->get_metadata(0);
+ ERR_FAIL_COND(!remaps.has(key));
+
+ remaps.erase(key);
+
+ undo_redo->create_action(TTR("Remove Resource Remap"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_method(this,"_update_translations");
+ undo_redo->add_undo_method(this,"_update_translations");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+}
+
+void ProjectSettings::_translation_res_option_delete(Object *p_item,int p_column, int p_button) {
+
+ if (updating_translations)
+ return;
+
+ if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
+ return;
+
+ Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
+
+ TreeItem *k = translation_remap->get_selected();
+ ERR_FAIL_COND(!k);
+ TreeItem *ed = p_item->cast_to<TreeItem>();
+ ERR_FAIL_COND(!ed);
+
+ String key = k->get_metadata(0);
+ int idx = ed->get_metadata(0);
+
+ ERR_FAIL_COND(!remaps.has(key));
+ PoolStringArray r = remaps[key];
+ ERR_FAIL_INDEX(idx,remaps.size());
+ r.remove(idx);
+ remaps[key]=r;
+
+
+ undo_redo->create_action(TTR("Remove Resource Remap Option"));
+ undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
+ undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
+ undo_redo->add_do_method(this,"_update_translations");
+ undo_redo->add_undo_method(this,"_update_translations");
+ undo_redo->add_do_method(this,"_settings_changed");
+ undo_redo->add_undo_method(this,"_settings_changed");
+ undo_redo->commit_action();
+
+}
+
+void ProjectSettings::_update_translations() {
+
+ //update translations
+
+ if (updating_translations)
+ return;
+
+ updating_translations=true;
+
+ translation_list->clear();
+ TreeItem *root = translation_list->create_item(NULL);
+ translation_list->set_hide_root(true);
+ if (GlobalConfig::get_singleton()->has("locale/translations")) {
+
+ PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
+ for(int i=0;i<translations.size();i++) {
+
+ TreeItem *t = translation_list->create_item(root);
+ t->set_editable(0,false);
+ t->set_text(0,translations[i].replace_first("res://",""));
+ t->set_tooltip(0,translations[i]);
+ t->set_metadata(0,i);
+ t->add_button(0,get_icon("Del","EditorIcons"),0);
+ }
+ }
+
+
+ //update translation remaps
+
+ String remap_selected;
+ if (translation_remap->get_selected()) {
+ remap_selected = translation_remap->get_selected()->get_metadata(0);
+ }
+
+ translation_remap->clear();
+ translation_remap_options->clear();
+ root = translation_remap->create_item(NULL);
+ TreeItem *root2 = translation_remap_options->create_item(NULL);
+ translation_remap->set_hide_root(true);
+ translation_remap_options->set_hide_root(true);
+ translation_res_option_add_button->set_disabled(true);
+
+ Vector<String> langs = TranslationServer::get_all_locales();
+ Vector<String> names = TranslationServer::get_all_locale_names();
+ String langnames;
+ for(int i=0;i<names.size();i++) {
+ if (i>0)
+ langnames+=",";
+ langnames+=names[i];
+ }
+
+ if (GlobalConfig::get_singleton()->has("locale/translation_remaps")) {
+
+ Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
+ List<Variant> rk;
+ remaps.get_key_list(&rk);
+ Vector<String> keys;
+ for(List<Variant>::Element *E=rk.front();E;E=E->next()) {
+ keys.push_back(E->get());
+ }
+ keys.sort();
+
+ for(int i=0;i<keys.size();i++) {
+
+ TreeItem *t = translation_remap->create_item(root);
+ t->set_editable(0,false);
+ t->set_text(0,keys[i].replace_first("res://",""));
+ t->set_tooltip(0,keys[i]);
+ t->set_metadata(0,keys[i]);
+ t->add_button(0,get_icon("Del","EditorIcons"),0);
+ if (keys[i]==remap_selected) {
+ t->select(0);
+ translation_res_option_add_button->set_disabled(false);
+
+ PoolStringArray selected = remaps[keys[i]];
+ for(int j=0;j<selected.size();j++) {
+
+ String s = selected[j];
+ int qp = s.find_last(":");
+ String path = s.substr(0,qp);
+ String locale = s.substr(qp+1,s.length());
+
+ TreeItem *t2 = translation_remap_options->create_item(root2);
+ t2->set_editable(0,false);
+ t2->set_text(0,path.replace_first("res://",""));
+ t2->set_tooltip(0,path);
+ t2->set_metadata(0,j);
+ t2->add_button(0,get_icon("Del","EditorIcons"),0);
+ t2->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+ t2->set_text(1,langnames);
+ t2->set_editable(1,true);
+ t2->set_metadata(1,path);
+ int idx = langs.find(locale);
+ print_line("find "+locale+" at "+itos(idx));
+ if (idx<0)
+ idx=0;
+
+ t2->set_range(1,idx);
+ }
+ }
+
+
+ }
+ }
+
+
+ updating_translations=false;
+
+}
+
+void ProjectSettings::_toggle_search_bar(bool p_pressed) {
+
+ globals_editor->get_property_editor()->set_use_filter(p_pressed);
+
+ if (p_pressed) {
+
+ search_bar->show();
+ add_prop_bar->hide();
+ search_box->grab_focus();
+ search_box->select_all();
+ } else {
+
+ search_bar->hide();
+ add_prop_bar->show();
+ }
+}
+
+void ProjectSettings::_clear_search_box() {
+
+ if (search_box->get_text()=="")
+ return;
+
+ search_box->clear();
+ globals_editor->get_property_editor()->update_tree();
+}
+
+void ProjectSettings::set_plugins_page() {
+
+ tab_container->set_current_tab( plugin_settings->get_index() );
+}
+
+void ProjectSettings::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_item_selected"),&ProjectSettings::_item_selected);
+ ClassDB::bind_method(D_METHOD("_item_add"),&ProjectSettings::_item_add);
+ ClassDB::bind_method(D_METHOD("_item_adds"),&ProjectSettings::_item_adds);
+ ClassDB::bind_method(D_METHOD("_item_del"),&ProjectSettings::_item_del);
+ ClassDB::bind_method(D_METHOD("_item_checked"),&ProjectSettings::_item_checked);
+ ClassDB::bind_method(D_METHOD("_save"),&ProjectSettings::_save);
+ ClassDB::bind_method(D_METHOD("_action_add"),&ProjectSettings::_action_add);
+ ClassDB::bind_method(D_METHOD("_action_adds"),&ProjectSettings::_action_adds);
+ ClassDB::bind_method(D_METHOD("_action_selected"),&ProjectSettings::_action_selected);
+ ClassDB::bind_method(D_METHOD("_action_edited"),&ProjectSettings::_action_edited);
+ ClassDB::bind_method(D_METHOD("_action_button_pressed"),&ProjectSettings::_action_button_pressed);
+ ClassDB::bind_method(D_METHOD("_update_actions"),&ProjectSettings::_update_actions);
+ ClassDB::bind_method(D_METHOD("_wait_for_key"),&ProjectSettings::_wait_for_key);
+ ClassDB::bind_method(D_METHOD("_add_item"),&ProjectSettings::_add_item);
+ ClassDB::bind_method(D_METHOD("_device_input_add"),&ProjectSettings::_device_input_add);
+ ClassDB::bind_method(D_METHOD("_press_a_key_confirm"),&ProjectSettings::_press_a_key_confirm);
+ ClassDB::bind_method(D_METHOD("_settings_prop_edited"),&ProjectSettings::_settings_prop_edited);
+ ClassDB::bind_method(D_METHOD("_copy_to_platform"),&ProjectSettings::_copy_to_platform);
+ ClassDB::bind_method(D_METHOD("_update_translations"),&ProjectSettings::_update_translations);
+ ClassDB::bind_method(D_METHOD("_translation_delete"),&ProjectSettings::_translation_delete);
+ ClassDB::bind_method(D_METHOD("_settings_changed"),&ProjectSettings::_settings_changed);
+ ClassDB::bind_method(D_METHOD("_translation_add"),&ProjectSettings::_translation_add);
+ ClassDB::bind_method(D_METHOD("_translation_file_open"),&ProjectSettings::_translation_file_open);
+
+ ClassDB::bind_method(D_METHOD("_translation_res_add"),&ProjectSettings::_translation_res_add);
+ ClassDB::bind_method(D_METHOD("_translation_res_file_open"),&ProjectSettings::_translation_res_file_open);
+ ClassDB::bind_method(D_METHOD("_translation_res_option_add"),&ProjectSettings::_translation_res_option_add);
+ ClassDB::bind_method(D_METHOD("_translation_res_option_file_open"),&ProjectSettings::_translation_res_option_file_open);
+ ClassDB::bind_method(D_METHOD("_translation_res_select"),&ProjectSettings::_translation_res_select);
+ ClassDB::bind_method(D_METHOD("_translation_res_option_changed"),&ProjectSettings::_translation_res_option_changed);
+ ClassDB::bind_method(D_METHOD("_translation_res_delete"),&ProjectSettings::_translation_res_delete);
+ ClassDB::bind_method(D_METHOD("_translation_res_option_delete"),&ProjectSettings::_translation_res_option_delete);
+
+ ClassDB::bind_method(D_METHOD("_clear_search_box"),&ProjectSettings::_clear_search_box);
+ ClassDB::bind_method(D_METHOD("_toggle_search_bar"),&ProjectSettings::_toggle_search_bar);
+
+}
+
+ProjectSettings::ProjectSettings(EditorData *p_data) {
+
+
+ singleton=this;
+ set_title(TTR("Project Settings (godot.cfg)"));
+ set_resizable(true);
+ undo_redo=&p_data->get_undo_redo();
+ data=p_data;
+
+
+ tab_container = memnew( TabContainer );
+ add_child(tab_container);
+ //set_child_rect(tab_container);
+
+ //tab_container->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 15 );
+ //tab_container->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 15 );
+ //tab_container->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 15 );
+ //tab_container->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
+
+ VBoxContainer *props_base = memnew( VBoxContainer );
+ props_base->set_alignment(BoxContainer::ALIGN_BEGIN);
+ props_base->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ tab_container->add_child(props_base);
+ props_base->set_name(TTR("General"));
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ props_base->add_child(hbc);
+
+ search_button = memnew( ToolButton );
+ search_button->set_toggle_mode(true);
+ search_button->set_pressed(false);
+ search_button->set_text(TTR("Search"));
+ hbc->add_child(search_button);
+ search_button->connect("toggled",this,"_toggle_search_bar");
+
+ hbc->add_child( memnew( VSeparator ) );
+
+ add_prop_bar = memnew( HBoxContainer );
+ add_prop_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbc->add_child(add_prop_bar);
+
+ Label *l = memnew( Label );
+ add_prop_bar->add_child(l);
+ l->set_text(TTR("Category:"));
+
+ category = memnew( LineEdit );
+ category->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ add_prop_bar->add_child(category);
+ category->connect("text_entered",this,"_item_adds");
+
+ l = memnew( Label );
+ add_prop_bar->add_child(l);
+ l->set_text(TTR("Property:"));
+
+ property = memnew( LineEdit );
+ property->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ add_prop_bar->add_child(property);
+ property->connect("text_entered",this,"_item_adds");
+
+ l = memnew( Label );
+ add_prop_bar->add_child(l);
+ l->set_text(TTR("Type:"));
+
+ type = memnew( OptionButton );
+ type->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ add_prop_bar->add_child(type);
+ type->add_item("bool");
+ type->add_item("int");
+ type->add_item("float");
+ type->add_item("string");
+
+ Button *add = memnew( Button );
+ add_prop_bar->add_child(add);
+ add->set_text(TTR("Add"));
+ add->connect("pressed",this,"_item_add");
+
+ Button *del = memnew( Button );
+ add_prop_bar->add_child(del);
+ del->set_text(TTR("Del"));
+ del->connect("pressed",this,"_item_del");
+
+ search_bar = memnew( HBoxContainer );
+ search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbc->add_child(search_bar);
+ search_bar->hide();
+
+ search_box = memnew( LineEdit );
+ search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ search_bar->add_child(search_box);
+
+ clear_button = memnew( ToolButton );
+ search_bar->add_child(clear_button);
+ clear_button->connect("pressed",this,"_clear_search_box");
+
+ globals_editor = memnew( SectionedPropertyEditor );
+ props_base->add_child(globals_editor);
+ globals_editor->get_property_editor()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
+ //globals_editor->hide_top_label();
+ globals_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ 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 );
+ props_base->add_child(save);
+
+ save->set_anchor(MARGIN_LEFT,ANCHOR_END);
+ save->set_anchor(MARGIN_RIGHT,ANCHOR_END);
+ save->set_anchor(MARGIN_TOP,ANCHOR_END);
+ save->set_anchor(MARGIN_BOTTOM,ANCHOR_END);
+ save->set_begin( Point2(80,28) );
+ save->set_end( Point2(10,20) );
+ save->set_text("Save");
+ save->connect("pressed",this,"_save");
+*/
+
+ hbc = memnew( HBoxContainer );
+ props_base->add_child(hbc);
+
+ popup_platform = memnew( MenuButton );
+ popup_platform->set_text(TTR("Copy To Platform.."));
+ popup_platform->set_disabled(true);
+ hbc->add_child(popup_platform);
+
+ hbc->add_spacer();
+
+ /*List<StringName> ep;
+ EditorImportExport::get_singleton()->get_export_platforms(&ep);
+ ep.sort_custom<StringName::AlphCompare>();
+
+ for(List<StringName>::Element *E=ep.front();E;E=E->next()) {
+
+ popup_platform->get_popup()->add_item( E->get() );
+
+ }*/
+
+ popup_platform->get_popup()->connect("id_pressed",this,"_copy_to_platform");
+ get_ok()->set_text(TTR("Close"));
+ set_hide_on_ok(true);
+
+ message = memnew( ConfirmationDialog );
+ add_child(message);
+ //message->get_cancel()->hide();
+ message->set_hide_on_ok(true);
+
+ Control *input_base = memnew( Control );
+ input_base->set_name(TTR("Input Map"));
+ input_base->set_area_as_parent_rect();
+ tab_container->add_child(input_base);
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ input_base->add_child(vbc);
+ vbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 5 );
+ vbc->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 5 );
+ vbc->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 );
+ vbc->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 );
+
+ l = memnew( Label );
+ vbc->add_child(l);
+ l->set_pos(Point2(6,5));
+ l->set_text(TTR("Action:"));
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
+
+ action_name = memnew( LineEdit );
+ action_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(action_name);
+ action_name->connect("text_entered",this,"_action_adds");
+
+ add = memnew( Button );
+ hbc->add_child(add);
+ add->set_custom_minimum_size(Size2(150, 0));
+ add->set_text(TTR("Add"));
+ add->connect("pressed",this,"_action_add");
+
+ input_editor = memnew( Tree );
+ vbc->add_child(input_editor);
+ input_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ input_editor->connect("item_edited",this,"_action_edited");
+ input_editor->connect("cell_selected",this,"_action_selected");
+ input_editor->connect("button_pressed",this,"_action_button_pressed");
+ popup_add = memnew( PopupMenu );
+ add_child(popup_add);
+ popup_add->connect("id_pressed",this,"_add_item");
+
+ press_a_key = memnew( ConfirmationDialog );
+ press_a_key->set_focus_mode(FOCUS_ALL);
+ add_child(press_a_key);
+
+ l = memnew( Label );
+ l->set_text(TTR("Press a Key.."));
+ l->set_area_as_parent_rect();
+ l->set_align(Label::ALIGN_CENTER);
+ l->set_margin(MARGIN_TOP,20);
+ l->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,30);
+ press_a_key_label=l;
+ press_a_key->add_child(l);
+ press_a_key->connect("gui_input",this,"_wait_for_key");
+ press_a_key->connect("confirmed",this,"_press_a_key_confirm");
+
+
+ device_input=memnew( ConfirmationDialog );
+ add_child(device_input);
+ device_input->get_ok()->set_text(TTR("Add"));
+ device_input->connect("confirmed",this,"_device_input_add");
+
+ hbc = memnew( HBoxContainer );
+ device_input->add_child(hbc);
+ //device_input->set_child_rect(hbc);
+
+ VBoxContainer *vbc_left = memnew( VBoxContainer );
+ hbc->add_child(vbc_left);
+
+ l = memnew( Label );
+ l->set_text(TTR("Device:"));
+ vbc_left->add_child(l);
+
+ device_id = memnew( SpinBox );
+ device_id->set_value(0);
+ vbc_left->add_child(device_id);
+
+ VBoxContainer *vbc_right = memnew( VBoxContainer );
+ hbc->add_child(vbc_right);
+ vbc_right->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ l = memnew( Label );
+ l->set_text(TTR("Index:"));
+ vbc_right->add_child(l);
+ device_index_label=l;
+
+ device_index = memnew( OptionButton );
+ vbc_right->add_child(device_index);
+
+ /*
+ save = memnew( Button );
+ input_base->add_child(save);
+ save->set_anchor(MARGIN_LEFT,ANCHOR_END);
+ save->set_anchor(MARGIN_RIGHT,ANCHOR_END);
+ save->set_anchor(MARGIN_TOP,ANCHOR_END);
+ save->set_anchor(MARGIN_BOTTOM,ANCHOR_END);
+ save->set_begin( Point2(80,28) );
+ save->set_end( Point2(10,20) );
+ save->set_text("Save");
+ save->connect("pressed",this,"_save");
+*/
+ setting=false;
+
+ //translations
+ TabContainer *translations = memnew( TabContainer );
+ translations->set_name(TTR("Localization"));
+ tab_container->add_child(translations);
+
+ {
+
+ VBoxContainer *tvb = memnew( VBoxContainer );
+ translations->add_child(tvb);
+ tvb->set_name(TTR("Translations"));
+ HBoxContainer *thb = memnew( HBoxContainer);
+ tvb->add_child(thb);
+ thb->add_child( memnew( Label(TTR("Translations:"))));
+ thb->add_spacer();
+ Button *addtr = memnew( Button(TTR("Add..")) );
+ addtr->connect("pressed",this,"_translation_file_open");
+ thb->add_child(addtr);
+ MarginContainer *tmc = memnew( MarginContainer );
+ tvb->add_child(tmc);
+ tmc->set_v_size_flags(SIZE_EXPAND_FILL);
+ translation_list = memnew( Tree );
+ translation_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ tmc->add_child(translation_list);
+
+ translation_file_open=memnew( EditorFileDialog );
+ add_child(translation_file_open);
+ translation_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ translation_file_open->connect("file_selected",this,"_translation_add");
+
+ }
+
+ {
+ VBoxContainer *tvb = memnew( VBoxContainer );
+ translations->add_child(tvb);
+ tvb->set_name(TTR("Remaps"));
+ HBoxContainer *thb = memnew( HBoxContainer);
+ tvb->add_child(thb);
+ thb->add_child( memnew( Label(TTR("Resources:"))));
+ thb->add_spacer();
+ Button *addtr = memnew( Button(TTR("Add..")) );
+ addtr->connect("pressed",this,"_translation_res_file_open");
+ thb->add_child(addtr);
+ MarginContainer *tmc = memnew( MarginContainer );
+ tvb->add_child(tmc);
+ tmc->set_v_size_flags(SIZE_EXPAND_FILL);
+ translation_remap = memnew( Tree );
+ translation_remap->set_v_size_flags(SIZE_EXPAND_FILL);
+ translation_remap->connect("cell_selected",this,"_translation_res_select");
+ tmc->add_child(translation_remap);
+ translation_remap->connect("button_pressed",this,"_translation_res_delete");
+
+ translation_res_file_open=memnew( EditorFileDialog );
+ add_child(translation_res_file_open);
+ translation_res_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ translation_res_file_open->connect("file_selected",this,"_translation_res_add");
+
+ thb = memnew( HBoxContainer);
+ tvb->add_child(thb);
+ thb->add_child( memnew( Label(TTR("Remaps by Locale:"))));
+ thb->add_spacer();
+ addtr = memnew( Button(TTR("Add..")) );
+ addtr->connect("pressed",this,"_translation_res_option_file_open");
+ translation_res_option_add_button=addtr;
+ thb->add_child(addtr);
+ tmc = memnew( MarginContainer );
+ tvb->add_child(tmc);
+ tmc->set_v_size_flags(SIZE_EXPAND_FILL);
+ translation_remap_options = memnew( Tree );
+ translation_remap_options->set_v_size_flags(SIZE_EXPAND_FILL);
+ tmc->add_child(translation_remap_options);
+
+ translation_remap_options->set_columns(2);
+ translation_remap_options->set_column_title(0,TTR("Path"));
+ translation_remap_options->set_column_title(1,TTR("Locale"));
+ translation_remap_options->set_column_titles_visible(true);
+ translation_remap_options->set_column_expand(0,true);
+ translation_remap_options->set_column_expand(1,false);
+ translation_remap_options->set_column_min_width(1,200);
+ translation_remap_options->connect("item_edited",this,"_translation_res_option_changed");
+ translation_remap_options->connect("button_pressed",this,"_translation_res_option_delete");
+
+ translation_res_option_file_open=memnew( EditorFileDialog );
+ add_child(translation_res_option_file_open);
+ translation_res_option_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ translation_res_option_file_open->connect("file_selected",this,"_translation_res_option_add");
+
+ }
+
+
+ {
+ autoload_settings = memnew( EditorAutoloadSettings );
+ autoload_settings->set_name(TTR("AutoLoad"));
+ tab_container->add_child(autoload_settings);
+ autoload_settings->connect("autoload_changed", this, "_settings_changed");
+ }
+
+ {
+
+ plugin_settings = memnew( EditorPluginSettings );
+ plugin_settings->set_name(TTR("Plugins"));
+ tab_container->add_child(plugin_settings);
+ }
+
+ timer = memnew( Timer );
+ timer->set_wait_time(1.5);
+ timer->connect("timeout",GlobalConfig::get_singleton(),"save");
+ timer->set_one_shot(true);
+ add_child(timer);
+
+ updating_translations=false;
+
+
+ /*
+ Control * es = memnew( Control );
+ es->set_name("Export");
+ tab_container->add_child(es);
+ export_settings = memnew( ProjectExportSettings );
+ es->add_child(export_settings);
+ export_settings->set_area_as_parent_rect();
+ export_settings->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
+*/
+}
diff --git a/editor/project_settings.h b/editor/project_settings.h
new file mode 100644
index 0000000000..96ac2e2c11
--- /dev/null
+++ b/editor/project_settings.h
@@ -0,0 +1,164 @@
+/*************************************************************************/
+/* project_settings.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PROJECT_SETTINGS_H
+#define PROJECT_SETTINGS_H
+
+#include "scene/gui/dialogs.h"
+#include "property_editor.h"
+#include "undo_redo.h"
+#include "editor_data.h"
+#include "scene/gui/tab_container.h"
+#include "editor_autoload_settings.h"
+#include "editor_plugin_settings.h"
+
+//#include "project_export_settings.h"
+
+class ProjectSettings : public AcceptDialog {
+ GDCLASS( ProjectSettings, AcceptDialog );
+
+
+ TabContainer *tab_container;
+
+ Timer *timer;
+ InputEvent::Type add_type;
+ String add_at;
+
+ EditorData *data;
+ UndoRedo *undo_redo;
+ SectionedPropertyEditor *globals_editor;
+
+ HBoxContainer *search_bar;
+ ToolButton *search_button;
+ LineEdit *search_box;
+ ToolButton *clear_button;
+
+ HBoxContainer *add_prop_bar;
+ ConfirmationDialog *message;
+ LineEdit *category;
+ LineEdit *property;
+ OptionButton *type;
+ PopupMenu *popup_add;
+ ConfirmationDialog *press_a_key;
+ Label*press_a_key_label;
+ ConfirmationDialog *device_input;
+ SpinBox *device_id;
+ OptionButton *device_index;
+ Label *device_index_label;
+ MenuButton *popup_platform;
+
+ LineEdit *action_name;
+ Tree *input_editor;
+ bool setting;
+ bool updating_translations;
+
+ InputEvent last_wait_for_key;
+
+ EditorFileDialog *translation_file_open;
+ Tree *translation_list;
+
+
+ Button *translation_res_option_add_button;
+ EditorFileDialog *translation_res_file_open;
+ EditorFileDialog *translation_res_option_file_open;
+ Tree *translation_remap;
+ Tree *translation_remap_options;
+
+ EditorAutoloadSettings *autoload_settings;
+
+ EditorPluginSettings *plugin_settings;
+
+ void _item_selected();
+ void _item_adds(String);
+ void _item_add();
+ void _item_del();
+ void _update_actions();
+ void _save();
+ void _add_item(int p_item);
+
+ void _action_adds(String);
+ void _action_add();
+ void _device_input_add();
+
+ void _item_checked(const String& p_item, bool p_check);
+ void _action_selected();
+ void _action_edited();
+ void _action_button_pressed(Object* p_obj, int p_column,int p_id);
+ void _wait_for_key(const InputEvent& p_event);
+ void _press_a_key_confirm();
+ void _show_last_added(const InputEvent& p_event, const String& p_name);
+
+ void _settings_prop_edited(const String& p_name);
+ void _settings_changed();
+
+ //ProjectExportSettings *export_settings;
+ void _copy_to_platform(int p_which);
+
+
+ void _translation_file_open();
+ void _translation_add(const String& p_path);
+ void _translation_delete(Object *p_item,int p_column, int p_button);
+ void _update_translations();
+
+ void _translation_res_file_open();
+ void _translation_res_add(const String& p_path);
+ void _translation_res_delete(Object *p_item,int p_column, int p_button);
+ void _translation_res_select();
+ void _translation_res_option_file_open();
+ void _translation_res_option_add(const String& p_path);
+ void _translation_res_option_changed();
+ void _translation_res_option_delete(Object *p_item,int p_column, int p_button);
+
+ void _toggle_search_bar(bool p_pressed);
+ void _clear_search_box();
+
+
+
+ ProjectSettings();
+
+
+ static ProjectSettings *singleton;
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+
+ void add_translation(const String& p_translation);
+ static ProjectSettings *get_singleton() { return singleton; }
+ void popup_project_settings();
+ void set_plugins_page();
+
+ void queue_save();
+
+
+ ProjectSettings(EditorData *p_data);
+};
+
+#endif // PROJECT_SETTINGS_H
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
new file mode 100644
index 0000000000..533a5b156b
--- /dev/null
+++ b/editor/property_editor.cpp
@@ -0,0 +1,4960 @@
+/*************************************************************************/
+/* property_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "property_editor.h"
+
+#include "scene/gui/label.h"
+#include "io/resource_loader.h"
+#include "io/image_loader.h"
+#include "os/input.h"
+#include "os/keyboard.h"
+#include "class_db.h"
+#include "print_string.h"
+#include "global_config.h"
+#include "scene/resources/font.h"
+#include "pair.h"
+#include "scene/scene_string_names.h"
+#include "editor_settings.h"
+#include "editor_export.h"
+#include "editor_node.h"
+#include "multi_node_edit.h"
+#include "array_property_edit.h"
+#include "editor_help.h"
+#include "scene/resources/packed_scene.h"
+#include "scene/main/viewport.h"
+#include "editor_file_system.h"
+#include "create_dialog.h"
+#include "property_selector.h"
+#include "global_config.h"
+
+void CustomPropertyEditor::_notification(int p_what) {
+
+
+ if (p_what==NOTIFICATION_DRAW) {
+
+ RID ci = get_canvas_item();
+ get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
+ /*
+ if (v.get_type()==Variant::COLOR) {
+
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( 10,10,60, get_size().height-20 ), v );
+ }*/
+ }
+}
+
+
+void CustomPropertyEditor::_menu_option(int p_which) {
+
+
+ switch(type) {
+
+ case Variant::INT: {
+
+ if (hint==PROPERTY_HINT_FLAGS) {
+
+ int val = v;
+
+ if (val&(1<<p_which)) {
+
+ val&=~(1<<p_which);
+ } else {
+ val|=(1<<p_which);
+ }
+
+ v=val;
+ emit_signal("variant_changed");
+ } else if (hint==PROPERTY_HINT_ENUM) {
+
+ v=p_which;
+ emit_signal("variant_changed");
+
+ }
+ } break;
+ case Variant::STRING: {
+
+ if (hint==PROPERTY_HINT_ENUM) {
+
+ v=hint_text.get_slice(",",p_which);
+ emit_signal("variant_changed");
+
+ }
+ } break;
+ case Variant::OBJECT: {
+
+ switch(p_which) {
+ case OBJ_MENU_LOAD: {
+
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ String type=(hint==PROPERTY_HINT_RESOURCE_TYPE)?hint_text:String();
+
+ 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()) {
+ print_line("found: "+E->get());
+ 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() );
+
+ }
+
+ file->popup_centered_ratio();
+ } break;
+
+ case OBJ_MENU_EDIT: {
+
+ RefPtr RefPtr=v;
+
+ if (!RefPtr.is_null()) {
+
+ emit_signal("resource_edit_request");
+ hide();
+ }
+ } break;
+ case OBJ_MENU_CLEAR: {
+
+
+ v=Variant();
+ emit_signal("variant_changed");
+ hide();
+ } break;
+
+ case OBJ_MENU_MAKE_UNIQUE: {
+
+
+ RefPtr RefPtr=v;
+ Ref<Resource> res_orig = RefPtr;
+ if (res_orig.is_null())
+ return;
+
+ List<PropertyInfo> property_list;
+ res_orig->get_property_list(&property_list);
+ List< Pair<String,Variant> > propvalues;
+
+ for(List<PropertyInfo>::Element *E=property_list.front();E;E=E->next()) {
+
+ Pair<String,Variant> p;
+ PropertyInfo &pi = E->get();
+ if (pi.usage&PROPERTY_USAGE_STORAGE) {
+
+ p.first=pi.name;
+ p.second=res_orig->get(pi.name);
+ }
+
+ propvalues.push_back(p);
+ }
+
+ String orig_type = res_orig->get_class();
+
+ Object *inst = ClassDB::instance( orig_type );
+
+ Ref<Resource> res = Ref<Resource>( inst->cast_to<Resource>() );
+
+ ERR_FAIL_COND(res.is_null());
+
+ for(List< Pair<String,Variant> >::Element *E=propvalues.front();E;E=E->next()) {
+
+ Pair<String,Variant> &p=E->get();
+ res->set(p.first,p.second);
+ }
+
+ v=res.get_ref_ptr();
+ emit_signal("variant_changed");
+ hide();
+ } break;
+
+ case OBJ_MENU_COPY: {
+
+ EditorSettings::get_singleton()->set_resource_clipboard(v);
+
+ } break;
+ case OBJ_MENU_PASTE: {
+
+ v=EditorSettings::get_singleton()->get_resource_clipboard();
+ emit_signal("variant_changed");
+
+ } break;
+ case OBJ_MENU_REIMPORT: {
+
+ RES r=v;
+/* if (r.is_valid() && r->get_import_metadata().is_valid()) {
+ Ref<ResourceImportMetadata> rimd = r->get_import_metadata();
+ Ref<EditorImportPlugin> eip = EditorImportExport::get_singleton()->get_import_plugin_by_name(rimd->get_editor());
+ if (eip.is_valid()) {
+ eip->import_dialog(r->get_path());
+ }
+ }*/
+ } break;
+ case OBJ_MENU_NEW_SCRIPT: {
+
+ if (owner->cast_to<Node>())
+ EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(owner->cast_to<Node>());
+
+ } break;
+ case OBJ_MENU_SHOW_IN_FILE_SYSTEM: {
+ RES r=v;
+ FileSystemDock *file_system_dock=EditorNode::get_singleton()->get_filesystem_dock();
+ file_system_dock->navigate_to_path(r->get_path());
+ // Ensure that the FileSystem dock is visible.
+ TabContainer* tab_container=(TabContainer*)file_system_dock->get_parent_control();
+ tab_container->set_current_tab(file_system_dock->get_position_in_parent());
+ } break;
+ default: {
+
+
+ ERR_FAIL_COND( inheritors_array.empty() );
+
+
+
+
+ String intype=inheritors_array[p_which-TYPE_BASE_ID];
+
+ if (intype=="ViewportTexture") {
+
+ scene_tree->set_title(TTR("Pick a Viewport"));
+ scene_tree->popup_centered_ratio();
+ picking_viewport=true;
+ return;
+
+ }
+
+ Object *obj = ClassDB::instance(intype);
+ ERR_BREAK( !obj );
+ Resource *res=obj->cast_to<Resource>();
+ ERR_BREAK( !res );
+ if (owner && hint==PROPERTY_HINT_RESOURCE_TYPE && hint_text=="Script") {
+ //make visual script the right type
+ res->call("set_instance_base_type",owner->get_class());
+ }
+
+ v=Ref<Resource>(res).get_ref_ptr();
+ emit_signal("variant_changed");
+
+ } break;
+ }
+
+
+ } break;
+ default:{}
+ }
+
+
+}
+
+void CustomPropertyEditor::hide_menu() {
+ menu->hide();
+}
+
+Variant CustomPropertyEditor::get_variant() const {
+
+ return v;
+}
+
+String CustomPropertyEditor::get_name() const {
+
+ return name;
+}
+
+bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Type p_type, const Variant& p_variant,int p_hint,String p_hint_text) {
+
+ owner=p_owner;
+ updating=true;
+ name=p_name;
+ v=p_variant;
+ field_names.clear();
+ hint=p_hint;
+ hint_text=p_hint_text;
+ type_button->hide();
+ if (color_picker)
+ color_picker->hide();
+ texture_preview->hide();
+ inheritors_array.clear();
+ text_edit->hide();
+ easing_draw->hide();
+ spinbox->hide();
+ slider->hide();
+
+ for (int i=0;i<MAX_VALUE_EDITORS;i++) {
+
+ value_editor[i]->hide();
+ value_label[i]->hide();
+ if (i<4)
+ scroll[i]->hide();
+ }
+
+ for (int i=0;i<MAX_ACTION_BUTTONS;i++) {
+
+ action_buttons[i]->hide();
+ }
+
+ checks20gc->hide();
+ for(int i=0;i<20;i++)
+ checks20[i]->hide();
+
+ type = (p_variant.get_type()!=Variant::NIL && p_variant.get_type()!=Variant::_RID && p_type!=Variant::OBJECT)? p_variant.get_type() : p_type;
+
+
+ switch(type) {
+
+ case Variant::BOOL: {
+
+ checks20gc->show();
+
+ CheckBox *c=checks20[0];
+ c->set_text("True");
+ checks20gc->set_pos(Vector2(4,4));
+ c->set_pressed(v);
+ c->show();
+
+ checks20gc->set_size(checks20gc->get_minimum_size());
+ set_size(checks20gc->get_pos()+checks20gc->get_size()+Vector2(4,4)*EDSCALE);
+
+ } break;
+ case Variant::INT:
+ case Variant::REAL: {
+
+ if (hint==PROPERTY_HINT_RANGE) {
+
+ int c = hint_text.get_slice_count(",");
+ float min=0,max=100,step=1;
+ if (c>=1) {
+
+ if (!hint_text.get_slice(",",0).empty())
+ min=hint_text.get_slice(",",0).to_double();
+ }
+ if (c>=2) {
+
+ if (!hint_text.get_slice(",",1).empty())
+ max=hint_text.get_slice(",",1).to_double();
+ }
+
+ if (c>=3) {
+
+ if (!hint_text.get_slice(",",2).empty())
+ step= hint_text.get_slice(",",2).to_double();
+ }
+
+ if (c>=4 && hint_text.get_slice(",",3)=="slider") {
+ slider->set_min(min);
+ slider->set_max(max);
+ slider->set_step(step);
+ slider->set_value(v);
+ slider->show();
+ set_size(Size2(110,30)*EDSCALE);
+ } else {
+ spinbox->set_min(min);
+ spinbox->set_max(max);
+ spinbox->set_step(step);
+ spinbox->set_value(v);
+ spinbox->show();
+ set_size(Size2(70,35)*EDSCALE);
+ }
+
+ } else if (hint==PROPERTY_HINT_ENUM) {
+
+ menu->clear();
+ Vector<String> options = hint_text.split(",");
+ for(int i=0;i<options.size();i++) {
+ menu->add_item(options[i],i);
+ }
+ menu->set_pos(get_pos());
+ menu->popup();
+ hide();
+ updating=false;
+ return false;
+
+
+ } else if (hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || hint==PROPERTY_HINT_LAYERS_2D_RENDER || hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
+
+
+ String title;
+ String basename;
+ switch (hint) {
+ case PROPERTY_HINT_LAYERS_2D_RENDER: basename="layer_names/2d_render"; title="2D Render Layers"; break;
+ case PROPERTY_HINT_LAYERS_2D_PHYSICS: basename="layer_names/2d_physics"; title="2D Physics Layers"; break;
+ case PROPERTY_HINT_LAYERS_3D_RENDER: basename="layer_names/3d_render"; title="3D Render Layers"; break;
+ case PROPERTY_HINT_LAYERS_3D_PHYSICS: basename="layer_names/3d_physics";title="3D Physics Layers"; break;
+ }
+
+ checks20gc->show();
+ uint32_t flgs = v;
+ for(int i=0;i<2;i++) {
+
+ Point2 ofs(4,4);
+ ofs.y+=22*i;
+ for(int j=0;j<10;j++) {
+
+ int idx = i*10+j;
+ CheckBox *c=checks20[idx];
+ c->set_text(GlobalConfig::get_singleton()->get(basename+"/layer_"+itos(idx+1)));
+ c->set_pressed( flgs & (1<<(i*10+j)) );
+ c->show();
+ }
+
+
+ }
+
+ show();
+
+ value_label[0]->set_text(title);
+ value_label[0]->show();
+ value_label[0]->set_pos(Vector2(4,4)*EDSCALE);
+
+ checks20gc->set_pos(Vector2(4,4)*EDSCALE+Vector2(0,value_label[0]->get_size().height+4*EDSCALE));
+ checks20gc->set_size(checks20gc->get_minimum_size());
+
+ set_size(Vector2(4,4)*EDSCALE+checks20gc->get_pos()+checks20gc->get_size());
+
+
+ } else if (hint==PROPERTY_HINT_EXP_EASING) {
+
+ easing_draw->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
+ easing_draw->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
+ easing_draw->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,5);
+ easing_draw->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,30);
+ type_button->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,3);
+ type_button->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,3);
+ type_button->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,25);
+ type_button->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,7);
+ type_button->set_text(TTR("Preset.."));
+ type_button->get_popup()->clear();
+ type_button->get_popup()->add_item(TTR("Linear"),EASING_LINEAR);
+ type_button->get_popup()->add_item(TTR("Ease In"),EASING_EASE_IN);
+ type_button->get_popup()->add_item(TTR("Ease Out"),EASING_EASE_OUT);
+ if (hint_text!="attenuation") {
+ type_button->get_popup()->add_item(TTR("Zero"),EASING_ZERO);
+ type_button->get_popup()->add_item(TTR("Easing In-Out"),EASING_IN_OUT);
+ type_button->get_popup()->add_item(TTR("Easing Out-In"),EASING_OUT_IN);
+ }
+
+ type_button->show();
+ easing_draw->show();
+ set_size(Size2(200,150)*EDSCALE);
+ } else if (hint==PROPERTY_HINT_FLAGS) {
+ menu->clear();
+ Vector<String> flags = hint_text.split(",");
+ for(int i=0;i<flags.size();i++) {
+ String flag = flags[i];
+ if (flag=="")
+ continue;
+ menu->add_check_item(flag,i);
+ int f = v;
+ if (f&(1<<i))
+ menu->set_item_checked(menu->get_item_index(i),true);
+ }
+ menu->set_pos(get_pos());
+ menu->popup();
+ hide();
+ updating=false;
+ return false;
+
+ } else {
+ List<String> names;
+ names.push_back("value:");
+ config_value_editors(1,1,50,names);
+ value_editor[0]->set_text( String::num(v) );
+ }
+
+ } break;
+ case Variant::STRING: {
+
+ if (hint==PROPERTY_HINT_FILE || hint==PROPERTY_HINT_GLOBAL_FILE) {
+
+ List<String> names;
+ names.push_back(TTR("File.."));
+ names.push_back(TTR("Clear"));
+ config_action_buttons(names);
+
+ } else if (hint==PROPERTY_HINT_DIR || hint==PROPERTY_HINT_GLOBAL_DIR) {
+
+ List<String> names;
+ names.push_back(TTR("Dir.."));
+ names.push_back(TTR("Clear"));
+ config_action_buttons(names);
+ } else if (hint==PROPERTY_HINT_ENUM) {
+
+ menu->clear();
+ Vector<String> options = hint_text.split(",");
+ for(int i=0;i<options.size();i++) {
+ menu->add_item(options[i],i);
+ }
+ menu->set_pos(get_pos());
+ menu->popup();
+ hide();
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_MULTILINE_TEXT) {
+
+ text_edit->show();
+ text_edit->set_text(v);
+
+ //action_buttons[0];
+
+ int button_margin = get_constant("button_margin","Dialogs");
+ int margin = get_constant("margin","Dialogs");
+
+ action_buttons[0]->set_anchor( MARGIN_LEFT, ANCHOR_END );
+ action_buttons[0]->set_anchor( MARGIN_TOP, ANCHOR_END );
+ action_buttons[0]->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ action_buttons[0]->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
+ action_buttons[0]->set_begin( Point2( 70, button_margin-5 ) );
+ action_buttons[0]->set_end( Point2( margin, margin ) );
+ action_buttons[0]->set_text(TTR("Close"));
+ action_buttons[0]->show();
+
+ } else if (hint==PROPERTY_HINT_TYPE_STRING) {
+
+ /* FIXME: This is repeated twice, with slightly different behavior! Which one? Check line 644 */
+ if (!create_dialog) {
+ create_dialog = memnew( CreateDialog );
+ create_dialog->connect("create",this,"_create_dialog_callback");
+ add_child(create_dialog);
+ }
+
+ if (hint_text!=String()) {
+ create_dialog->set_base_type(hint_text);
+ } else {
+ create_dialog->set_base_type("Object");
+ }
+
+ create_dialog->popup(false);
+ hide();
+ updating=false;
+ return false;
+
+
+ } else if (hint==PROPERTY_HINT_METHOD_OF_VARIANT_TYPE) {
+#define MAKE_PROPSELECT if (!property_select) { property_select = memnew(PropertySelector); property_select->connect("selected",this,"_create_selected_property"); add_child(property_select); } hide();
+
+ MAKE_PROPSELECT;
+
+ Variant::Type type=Variant::NIL;
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+ if (hint_text==Variant::get_type_name(Variant::Type(i))) {
+ type=Variant::Type(i);
+ }
+ }
+ if (type)
+ property_select->select_method_from_basic_type(type,v);
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_METHOD_OF_BASE_TYPE) {
+ MAKE_PROPSELECT
+
+ property_select->select_method_from_base_type(hint_text,v);
+
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_METHOD_OF_INSTANCE) {
+
+ MAKE_PROPSELECT
+
+ Object *instance = ObjectDB::get_instance(hint_text.to_int64());
+ if (instance)
+ property_select->select_method_from_instance(instance,v);
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_METHOD_OF_SCRIPT) {
+ MAKE_PROPSELECT
+
+ Object *obj = ObjectDB::get_instance(hint_text.to_int64());
+ if (obj && obj->cast_to<Script>()) {
+ property_select->select_method_from_script(obj->cast_to<Script>(),v);
+ }
+
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE) {
+
+ MAKE_PROPSELECT
+ Variant::Type type=Variant::NIL;
+ String tname=hint_text;
+ if (tname.find(".")!=-1)
+ tname=tname.get_slice(".",0);
+ for(int i=0;i<Variant::VARIANT_MAX;i++) {
+ if (tname==Variant::get_type_name(Variant::Type(i))) {
+ type=Variant::Type(Variant::Type(i));
+ }
+ }
+ InputEvent::Type iet = InputEvent::NONE;
+ if (hint_text.find(".")!=-1) {
+ iet=InputEvent::Type(int(hint_text.get_slice(".",1).to_int()));
+ }
+ if (type)
+ property_select->select_property_from_basic_type(type,iet,v);
+
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_PROPERTY_OF_BASE_TYPE) {
+
+ MAKE_PROPSELECT
+
+ property_select->select_property_from_base_type(hint_text,v);
+
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_PROPERTY_OF_INSTANCE) {
+
+ Object *instance = ObjectDB::get_instance(hint_text.to_int64());
+ if (instance)
+ property_select->select_property_from_instance(instance,v);
+
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_PROPERTY_OF_SCRIPT) {
+ MAKE_PROPSELECT
+
+ Object *obj = ObjectDB::get_instance(hint_text.to_int64());
+ if (obj && obj->cast_to<Script>()) {
+ property_select->select_property_from_script(obj->cast_to<Script>(),v);
+ }
+
+ updating=false;
+ return false;
+
+ } else if (hint==PROPERTY_HINT_TYPE_STRING) {
+ if (!create_dialog) {
+ /* FIXME: ... and here. See line 529 */
+ create_dialog = memnew( CreateDialog );
+ create_dialog->connect("create",this,"_create_dialog_callback");
+ add_child(create_dialog);
+ }
+
+ } else {
+ List<String> names;
+ names.push_back("string:");
+ config_value_editors(1,1,50,names);
+ value_editor[0]->set_text( v );
+ }
+
+ } break;
+ case Variant::VECTOR2: {
+
+ field_names.push_back("x");
+ field_names.push_back("y");
+ config_value_editors(2,2,10,field_names);
+ Vector2 vec=v;
+ value_editor[0]->set_text( String::num( vec.x) );
+ value_editor[1]->set_text( String::num( vec.y) );
+ } break;
+ case Variant::RECT2: {
+
+ field_names.push_back("x");
+ field_names.push_back("y");
+ field_names.push_back("w");
+ field_names.push_back("h");
+ config_value_editors(4,4,10,field_names);
+ Rect2 r=v;
+ value_editor[0]->set_text( String::num( r.pos.x) );
+ value_editor[1]->set_text( String::num( r.pos.y) );
+ value_editor[2]->set_text( String::num( r.size.x) );
+ value_editor[3]->set_text( String::num( r.size.y) );
+ } break;
+ case Variant::VECTOR3: {
+
+ field_names.push_back("x");
+ field_names.push_back("y");
+ field_names.push_back("z");
+ config_value_editors(3,3,10,field_names);
+ Vector3 vec=v;
+ value_editor[0]->set_text( String::num( vec.x) );
+ value_editor[1]->set_text( String::num( vec.y) );
+ value_editor[2]->set_text( String::num( vec.z) );
+ } break;
+ case Variant::PLANE: {
+
+ field_names.push_back("x");
+ field_names.push_back("y");
+ field_names.push_back("z");
+ field_names.push_back("d");
+ config_value_editors(4,4,10,field_names);
+ Plane plane=v;
+ value_editor[0]->set_text( String::num( plane.normal.x ) );
+ value_editor[1]->set_text( String::num( plane.normal.y ) );
+ value_editor[2]->set_text( String::num( plane.normal.z ) );
+ value_editor[3]->set_text( String::num( plane.d ) );
+
+ } break;
+ case Variant::QUAT: {
+
+ field_names.push_back("x");
+ field_names.push_back("y");
+ field_names.push_back("z");
+ field_names.push_back("w");
+ config_value_editors(4,4,10,field_names);
+ Quat q=v;
+ value_editor[0]->set_text( String::num( q.x ) );
+ value_editor[1]->set_text( String::num( q.y ) );
+ value_editor[2]->set_text( String::num( q.z ) );
+ value_editor[3]->set_text( String::num( q.w ) );
+
+ } break;
+ case Variant::RECT3: {
+
+ field_names.push_back("px");
+ field_names.push_back("py");
+ field_names.push_back("pz");
+ field_names.push_back("sx");
+ field_names.push_back("sy");
+ field_names.push_back("sz");
+ config_value_editors(6,3,16,field_names);
+
+ Rect3 aabb=v;
+ value_editor[0]->set_text( String::num( aabb.pos.x ) );
+ value_editor[1]->set_text( String::num( aabb.pos.y ) );
+ value_editor[2]->set_text( String::num( aabb.pos.z ) );
+ value_editor[3]->set_text( String::num( aabb.size.x ) );
+ value_editor[4]->set_text( String::num( aabb.size.y ) );
+ value_editor[5]->set_text( String::num( aabb.size.z ) );
+
+ } break;
+ case Variant::TRANSFORM2D: {
+
+ field_names.push_back("xx");
+ field_names.push_back("xy");
+ field_names.push_back("yx");
+ field_names.push_back("yy");
+ field_names.push_back("ox");
+ field_names.push_back("oy");
+ config_value_editors(6,2,16,field_names);
+
+ Transform2D basis=v;
+ for(int i=0;i<6;i++) {
+
+ value_editor[i]->set_text( String::num( basis.elements[i/2][i%2] ) );
+ }
+
+ } break;
+ case Variant::BASIS: {
+
+ field_names.push_back("xx");
+ field_names.push_back("xy");
+ field_names.push_back("xz");
+ field_names.push_back("yx");
+ field_names.push_back("yy");
+ field_names.push_back("yz");
+ field_names.push_back("zx");
+ field_names.push_back("zy");
+ field_names.push_back("zz");
+ config_value_editors(9,3,16,field_names);
+
+ Basis basis=v;
+ for(int i=0;i<9;i++) {
+
+ value_editor[i]->set_text( String::num( basis.elements[i/3][i%3] ) );
+ }
+
+ } break;
+ case Variant::TRANSFORM: {
+
+
+ field_names.push_back("xx");
+ field_names.push_back("xy");
+ field_names.push_back("xz");
+ field_names.push_back("xo");
+ field_names.push_back("yx");
+ field_names.push_back("yy");
+ field_names.push_back("yz");
+ field_names.push_back("yo");
+ field_names.push_back("zx");
+ field_names.push_back("zy");
+ field_names.push_back("zz");
+ field_names.push_back("zo");
+ config_value_editors(12,4,16,field_names);
+
+ Transform tr=v;
+ for(int i=0;i<9;i++) {
+
+ value_editor[(i/3)*4+i%3]->set_text( String::num( tr.basis.elements[i/3][i%3] ) );
+ }
+
+ value_editor[3]->set_text( String::num( tr.origin.x ) );
+ value_editor[7]->set_text( String::num( tr.origin.y ) );
+ value_editor[11]->set_text( String::num( tr.origin.z ) );
+
+ } break;
+ case Variant::COLOR: {
+
+ if (!color_picker) {
+ //late init for performance
+ color_picker = memnew( ColorPicker );
+ add_child(color_picker);
+ color_picker->hide();
+ color_picker->set_area_as_parent_rect();
+ for(int i=0;i<4;i++)
+ color_picker->set_margin((Margin)i,5);
+ color_picker->connect("color_changed",this,"_color_changed");
+ }
+
+ color_picker->show();
+ color_picker->set_edit_alpha(hint!=PROPERTY_HINT_COLOR_NO_ALPHA);
+ color_picker->set_pick_color(v);
+ set_size( Size2(300*EDSCALE, color_picker->get_combined_minimum_size().height+10*EDSCALE));
+ color_picker->set_focus_on_line_edit();
+ /*
+ int ofs=80;
+ int m=10;
+ int h=20;
+ Color c=v;
+ float values[4]={c.r,c.g,c.b,c.a};
+ for (int i=0;i<4;i++) {
+ int y=m+i*h;
+
+ value_editor[i]->show();
+ value_label[i]->show();
+ value_label[i]->set_pos(Point2(ofs,y));
+ scroll[i]->set_min(0);
+ scroll[i]->set_max(1.0);
+ scroll[i]->set_page(0);
+ scroll[i]->set_pos(Point2(ofs+15,y+Math::floor((h-scroll[i]->get_minimum_size().height)/2.0)));
+ scroll[i]->set_val(values[i]);
+ scroll[i]->set_size(Size2(120,1));
+ scroll[i]->show();
+ value_editor[i]->set_pos(Point2(ofs+140,y));
+ value_editor[i]->set_size(Size2(40,h));
+ value_editor[i]->set_text( String::num(values[i],2 ));
+
+ }
+
+ value_label[0]->set_text("R");
+ value_label[1]->set_text("G");
+ value_label[2]->set_text("B");
+ value_label[3]->set_text("A");
+
+ Size2 new_size = value_editor[3]->get_pos() + value_editor[3]->get_size() + Point2(10,10);
+ set_size( new_size );
+ */
+
+ } break;
+ case Variant::IMAGE: {
+
+ List<String> names;
+ names.push_back(TTR("New"));
+ names.push_back(TTR("Load"));
+ names.push_back(TTR("Clear"));
+ config_action_buttons(names);
+
+ } break;
+ case Variant::NODE_PATH: {
+
+ List<String> names;
+ names.push_back(TTR("Assign"));
+ names.push_back(TTR("Clear"));
+ config_action_buttons(names);
+
+ } break;
+ case Variant::OBJECT: {
+
+ if (hint!=PROPERTY_HINT_RESOURCE_TYPE)
+ break;
+
+
+ menu->clear();
+ menu->set_size(Size2(1,1));
+
+ if (p_name=="script" && hint_text=="Script" && owner->cast_to<Node>()) {
+ menu->add_icon_item(get_icon("Script","EditorIcons"),TTR("New Script"),OBJ_MENU_NEW_SCRIPT);
+ menu->add_separator();
+ } else if (hint_text!="") {
+ int idx=0;
+
+ for(int i=0;i<hint_text.get_slice_count(",");i++) {
+
+
+
+ String base=hint_text.get_slice(",",i);
+
+ Set<String> valid_inheritors;
+ valid_inheritors.insert(base);
+ List<StringName> inheritors;
+ ClassDB::get_inheriters_from_class(base.strip_edges(),&inheritors);
+ List<StringName>::Element *E=inheritors.front();
+ while(E) {
+ valid_inheritors.insert(E->get());
+ E=E->next();
+ }
+
+ for(Set<String>::Element *E=valid_inheritors.front();E;E=E->next()) {
+ String t = E->get();
+ if (!ClassDB::can_instance(t))
+ continue;
+ inheritors_array.push_back(t);
+
+ int id = TYPE_BASE_ID+idx;
+ if (has_icon(t,"EditorIcons")) {
+
+ menu->add_icon_item(get_icon(t,"EditorIcons"),TTR("New")+" "+t,id);
+ } else {
+
+ menu->add_item(TTR("New")+" "+t,id);
+ }
+
+ idx++;
+ }
+
+
+ }
+
+ if (menu->get_item_count())
+ menu->add_separator();
+ }
+
+ menu->add_icon_item(get_icon("Load","EditorIcons"),"Load",OBJ_MENU_LOAD);
+
+ if (!RES(v).is_null()) {
+
+
+
+ menu->add_icon_item(get_icon("EditResource","EditorIcons"),"Edit",OBJ_MENU_EDIT);
+ menu->add_icon_item(get_icon("Del","EditorIcons"),"Clear",OBJ_MENU_CLEAR);
+ menu->add_icon_item(get_icon("Duplicate","EditorIcons"),"Make Unique",OBJ_MENU_MAKE_UNIQUE);
+ RES r = v;
+ if (r.is_valid() && r->get_path().is_resource_file()) {
+ /*if (r->get_import_metadata().is_valid()) {
+ menu->add_separator();
+ menu->add_icon_item(get_icon("ReloadSmall","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT);
+ }*/
+ menu->add_separator();
+ menu->add_item(TTR("Show in File System"),OBJ_MENU_SHOW_IN_FILE_SYSTEM);
+ }
+ /*if (r.is_valid() && r->get_path().is_resource_file()) {
+ menu->set_item_tooltip(1,r->get_path());
+ } else if (r.is_valid()) {
+ menu->set_item_tooltip(1,r->get_name()+" ("+r->get_type()+")");
+ }*/
+ } else {
+
+ }
+
+
+ RES cb=EditorSettings::get_singleton()->get_resource_clipboard();
+ 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 (ClassDB::is_parent_class(cb->get_class(),hint_text.get_slice(",",i))) {
+ paste_valid=true;
+ break;
+ }
+ }
+
+ if (!RES(v).is_null() || paste_valid) {
+ menu->add_separator();
+
+
+ if (!RES(v).is_null()) {
+
+ menu->add_item(TTR("Copy"),OBJ_MENU_COPY);
+ }
+
+ if (paste_valid) {
+
+ menu->add_item(TTR("Paste"),OBJ_MENU_PASTE);
+ }
+ }
+
+
+
+ menu->set_pos(get_pos());
+ menu->popup();
+ hide();
+ updating=false;
+ return false;
+
+
+ } break;
+ case Variant::INPUT_EVENT: {
+
+
+ } break;
+ case Variant::DICTIONARY: {
+
+
+ } break;
+ case Variant::POOL_BYTE_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_INT_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+
+
+ } break;
+ default: {}
+ }
+
+ updating=false;
+ return true;
+}
+
+////void CustomPropertyEditor::_save_properties_values(List<String> p_names) {
+////
+//// field_names=p_names;
+//// for (int i=0;i<p_names.size();i++) {
+//// field_values.push_back(v.get(p_names[i]));
+//// }
+////}
+
+void CustomPropertyEditor::_file_selected(String p_file) {
+
+ switch(type) {
+
+ case Variant::STRING: {
+
+ if (hint==PROPERTY_HINT_FILE || hint==PROPERTY_HINT_DIR) {
+
+ v=GlobalConfig::get_singleton()->localize_path(p_file);
+ emit_signal("variant_changed");
+ hide();
+ }
+
+ if (hint==PROPERTY_HINT_GLOBAL_FILE || hint==PROPERTY_HINT_GLOBAL_DIR) {
+
+ v=p_file;
+ emit_signal("variant_changed");
+ hide();
+ }
+
+ } break;
+ case Variant::OBJECT: {
+
+ String type=(hint==PROPERTY_HINT_RESOURCE_TYPE)?hint_text:String();
+
+ RES res = ResourceLoader::load(p_file,type);
+ if (res.is_null()) {
+ error->set_text(TTR("Error loading file: Not a resource!"));
+ error->popup_centered_minsize();
+ break;
+ }
+ v=res.get_ref_ptr();
+ emit_signal("variant_changed");
+ hide();
+ } break;
+ case Variant::IMAGE: {
+
+ Image image;
+ Error err = ImageLoader::load_image(p_file,&image);
+ ERR_EXPLAIN(TTR("Couldn't load image"));
+ ERR_FAIL_COND(err);
+ v=image;
+ emit_signal("variant_changed");
+ hide();
+ } break;
+ default: {}
+ }
+}
+
+void CustomPropertyEditor::_type_create_selected(int p_idx) {
+
+
+ if (type==Variant::INT || type==Variant::REAL) {
+
+
+ float newval=0;
+ switch(p_idx) {
+
+ case EASING_LINEAR: {
+
+ newval=1;
+ } break;
+ case EASING_EASE_IN: {
+
+ newval=2.0;
+ } break;
+ case EASING_EASE_OUT: {
+ newval=0.5;
+ } break;
+ case EASING_ZERO: {
+
+ newval=0;
+ } break;
+ case EASING_IN_OUT: {
+
+ newval=-0.5;
+ } break;
+ case EASING_OUT_IN: {
+ newval=-2.0;
+ } break;
+ }
+
+ v=newval;
+ emit_signal("variant_changed");
+ easing_draw->update();
+
+ } else if (type==Variant::OBJECT) {
+
+ ERR_FAIL_INDEX(p_idx,inheritors_array.size());
+
+ //List<String> inheritors;
+ //ClassDB::get_inheriters_from(hint_text,&inheritors);
+ //inheritors.push_front(hint_text);
+
+ //ERR_FAIL_INDEX( p_idx, inheritors.size() );
+ String intype=inheritors_array[p_idx];
+
+ Object *obj = ClassDB::instance(intype);
+
+ ERR_FAIL_COND( !obj );
+
+
+ Resource *res=obj->cast_to<Resource>();
+ ERR_FAIL_COND( !res );
+
+ v=Ref<Resource>(res).get_ref_ptr();
+ emit_signal("variant_changed");
+ hide();
+ }
+
+}
+
+
+void CustomPropertyEditor::_color_changed(const Color& p_color) {
+
+ v=p_color;
+ emit_signal("variant_changed");
+
+}
+
+void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
+
+ if (picking_viewport) {
+
+ Node* to_node=get_node(p_path);
+ if (!to_node->cast_to<Viewport>()) {
+ EditorNode::get_singleton()->show_warning("Selected node is not a Viewport!");
+ return;
+ }
+
+ Ref<ViewportTexture> vt;
+ vt.instance();
+ vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node));
+ vt->setup_local_to_scene();
+ v=vt;
+ emit_signal("variant_changed");
+ return;
+ }
+
+ if (hint==PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && hint_text!=String()) {
+
+ Node* node=get_node(hint_text);
+ if (node) {
+
+ Node *tonode=node->get_node(p_path);
+ if (tonode) {
+ p_path=node->get_path_to(tonode);
+ }
+ }
+
+ } else if (owner) {
+
+ Node *node=NULL;
+
+ if (owner->is_class("Node"))
+ node = owner->cast_to<Node>();
+ else if (owner->is_class("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 *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
+
+}
+
+void CustomPropertyEditor::_action_pressed(int p_which) {
+
+
+ if (updating)
+ return;
+
+ switch(type) {
+ case Variant::BOOL: {
+ v=checks20[0]->is_pressed();
+ emit_signal("variant_changed");
+ } break;
+ case Variant::INT: {
+
+ if (hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || hint==PROPERTY_HINT_LAYERS_2D_RENDER || hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
+
+ uint32_t f = v;
+ if (checks20[p_which]->is_pressed())
+ f|=(1<<p_which);
+ else
+ f&=~(1<<p_which);
+
+ v=f;
+ emit_signal("variant_changed");
+ }
+
+ } break;
+ case Variant::STRING: {
+
+ if (hint==PROPERTY_HINT_MULTILINE_TEXT) {
+
+ hide();
+
+ } else if (hint==PROPERTY_HINT_FILE || hint==PROPERTY_HINT_GLOBAL_FILE) {
+ if (p_which==0) {
+
+ if (hint==PROPERTY_HINT_FILE)
+ file->set_access(EditorFileDialog::ACCESS_RESOURCES);
+ else
+ file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ file->clear_filters();
+
+ file->clear_filters();
+
+
+ if (hint_text!="") {
+ Vector<String> extensions=hint_text.split(",");
+ for(int i=0;i<extensions.size();i++) {
+
+ String filter = extensions[i];
+ if (filter.begins_with("."))
+ filter="*"+extensions[i];
+ else if (!filter.begins_with("*"))
+ filter="*."+extensions[i];
+
+
+ file->add_filter(filter+" ; "+extensions[i].to_upper() );
+
+ }
+ }
+ file->popup_centered_ratio();
+ } else {
+
+ v="";
+ emit_signal("variant_changed");
+ hide();
+
+ }
+
+ } else if (hint==PROPERTY_HINT_DIR || hint==PROPERTY_HINT_GLOBAL_DIR) {
+
+ if (p_which==0) {
+
+ if (hint==PROPERTY_HINT_DIR)
+ file->set_access(EditorFileDialog::ACCESS_RESOURCES);
+ else
+ file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file->set_mode(EditorFileDialog::MODE_OPEN_DIR);
+ file->clear_filters();
+ file->popup_centered_ratio();
+ } else {
+
+ v="";
+ emit_signal("variant_changed");
+ hide();
+
+ }
+
+ }
+
+ } break;
+ case Variant::NODE_PATH: {
+
+ if (p_which==0) {
+
+ picking_viewport=false;
+ scene_tree->set_title(TTR("Pick a Node"));
+ scene_tree->popup_centered_ratio();
+
+ } else if (p_which==1) {
+
+
+ v=NodePath();
+ emit_signal("variant_changed");
+ hide();
+ }
+ } break;
+ case Variant::OBJECT: {
+
+ if (p_which==0) {
+
+
+ ERR_FAIL_COND( inheritors_array.empty() );
+
+ String intype=inheritors_array[0];
+
+
+ if (hint==PROPERTY_HINT_RESOURCE_TYPE) {
+
+ Object *obj = ClassDB::instance(intype);
+ ERR_BREAK( !obj );
+ Resource *res=obj->cast_to<Resource>();
+ ERR_BREAK( !res );
+
+ v=Ref<Resource>(res).get_ref_ptr();
+ emit_signal("variant_changed");
+ hide();
+
+ }
+ } else if (p_which==1) {
+
+ file->set_access(EditorFileDialog::ACCESS_RESOURCES);
+ 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();
+ for (List<String>::Element *E=extensions.front();E;E=E->next()) {
+
+ file->add_filter("*."+E->get()+" ; "+E->get().to_upper() );
+
+ }
+
+ file->popup_centered_ratio();
+
+ } else if (p_which==2) {
+
+ RefPtr RefPtr=v;
+
+ if (!RefPtr.is_null()) {
+
+ emit_signal("resource_edit_request");
+ hide();
+ }
+
+ } else if (p_which==3) {
+
+
+ v=Variant();
+ emit_signal("variant_changed");
+ hide();
+ } else if (p_which==4) {
+
+
+ RefPtr RefPtr=v;
+ Ref<Resource> res_orig = RefPtr;
+ if (res_orig.is_null())
+ return;
+
+ List<PropertyInfo> property_list;
+ res_orig->get_property_list(&property_list);
+ List< Pair<String,Variant> > propvalues;
+
+ for(List<PropertyInfo>::Element *E=property_list.front();E;E=E->next()) {
+
+ Pair<String,Variant> p;
+ PropertyInfo &pi = E->get();
+ if (pi.usage&PROPERTY_USAGE_STORAGE) {
+
+ p.first=pi.name;
+ p.second=res_orig->get(pi.name);
+ }
+
+ propvalues.push_back(p);
+ }
+
+ Ref<Resource> res = Ref<Resource>( ClassDB::instance( res_orig->get_class() ));
+
+ ERR_FAIL_COND(res.is_null());
+
+ for(List< Pair<String,Variant> >::Element *E=propvalues.front();E;E=E->next()) {
+
+ Pair<String,Variant> &p=E->get();
+ res->set(p.first,p.second);
+ }
+
+ v=res.get_ref_ptr();
+ emit_signal("variant_changed");
+ hide();
+ }
+
+ } break;
+ case Variant::IMAGE: {
+
+ if (p_which==0) {
+ //new image too difficult
+ ERR_PRINT("New Image Unimplemented");
+
+ } else if (p_which==1) {
+
+ file->set_access(EditorFileDialog::ACCESS_RESOURCES);
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ List<String> extensions;
+ ImageLoader::get_recognized_extensions(&extensions);
+
+ file->clear_filters();
+
+ for (List<String>::Element *E=extensions.front();E;E=E->next()) {
+
+ file->add_filter("*."+E->get()+" ; "+E->get().to_upper() );
+
+ }
+
+ file->popup_centered_ratio();
+
+ } else if (p_which==2) {
+
+ v=Image();
+ emit_signal("variant_changed");
+ hide();
+ }
+
+ } break;
+ default: {};
+ }
+
+}
+
+void CustomPropertyEditor::_scroll_modified(double p_value) {
+
+ if (updating)
+ return;
+ /*
+ switch(type) {
+
+ case Variant::COLOR: {
+
+ for (int i=0;i<4;i++) {
+
+ value_editor[i]->set_text( String::num(scroll[i]->get_val(),2) );
+ }
+ Color c;
+ c.r=scroll[0]->get_val();
+ c.g=scroll[1]->get_val();
+ c.b=scroll[2]->get_val();
+ c.a=scroll[3]->get_val();
+ v=c;
+ update();
+ emit_signal("variant_changed");
+ } break;
+ default: {}
+ }
+ */
+}
+
+
+void CustomPropertyEditor::_drag_easing(const InputEvent& p_ev) {
+
+
+ if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
+
+ float rel = p_ev.mouse_motion.relative_x;
+ if (rel==0)
+ return;
+
+ bool flip=hint_text=="attenuation";
+
+ if (flip)
+ rel=-rel;
+
+ float val = v;
+ if (val==0)
+ return;
+ bool sg = val < 0;
+ val = Math::absf(val);
+
+ val = Math::log(val)/Math::log((float)2.0);
+ //logspace
+ val+=rel*0.05;
+ //
+
+ val = Math::pow(2.0f,val);
+ if (sg)
+ val=-val;
+
+ v=val;
+ easing_draw->update();
+ //emit_signal("variant_changed");
+ emit_signal("variant_changed");
+ }
+ if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT) {
+
+
+ }
+
+}
+
+
+void CustomPropertyEditor::_draw_easing() {
+
+
+ RID ci = easing_draw->get_canvas_item();
+
+ Size2 s = easing_draw->get_size();
+ Rect2 r(Point2(),s);
+ r=r.grow(3);
+ get_stylebox("normal","LineEdit")->draw(ci,r);
+ //VisualServer::get_singleton()->canvas_item_add
+
+
+ int points = 48;
+
+ float prev=1.0;
+ float exp=v;
+ bool flip=hint_text=="attenuation";
+
+ Ref<Font> f = get_font("font","Label");
+ Color color = get_color("font_color","Label");
+
+ for(int i=1;i<=points;i++) {
+
+ float ifl = i/float(points);
+ float iflp = (i-1)/float(points);
+
+ float h = 1.0-Math::ease(ifl,exp);
+
+ if (flip) {
+ ifl=1.0-ifl;
+ iflp=1.0-iflp;
+ }
+
+ VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(iflp*s.width,prev*s.height),Point2(ifl*s.width,h*s.height),color);
+ prev=h;
+ }
+
+ f->draw(ci,Point2(10,10+f->get_ascent()),String::num(exp,2),color);
+}
+
+void CustomPropertyEditor::_text_edit_changed() {
+
+ v=text_edit->get_text();
+ emit_signal("variant_changed");
+
+}
+
+void CustomPropertyEditor::_create_dialog_callback() {
+
+
+ v=create_dialog->get_selected_type();
+ emit_signal("variant_changed");
+}
+
+void CustomPropertyEditor::_create_selected_property(const String& p_prop) {
+
+
+ v=p_prop;
+ emit_signal("variant_changed");
+}
+
+void CustomPropertyEditor::_modified(String p_string) {
+
+ if (updating)
+ return;
+ updating=true;
+ switch(type) {
+ case Variant::INT: {
+
+ if (evaluator)
+ v=evaluator->eval(value_editor[0]->get_text());
+ else
+ v=value_editor[0]->get_text().to_int();
+ emit_signal("variant_changed");
+
+
+ } break;
+ case Variant::REAL: {
+
+ if (hint!=PROPERTY_HINT_EXP_EASING) {
+ if (evaluator)
+ v=evaluator->eval(value_editor[0]->get_text());
+ else
+ v=value_editor[0]->get_text().to_double();
+ emit_signal("variant_changed");
+
+ }
+
+ } break;
+ case Variant::STRING: {
+
+ v=value_editor[0]->get_text();
+ emit_signal("variant_changed");
+ } break;
+ case Variant::VECTOR2: {
+
+ Vector2 vec;
+ if (evaluator) {
+ vec.x=evaluator->eval(value_editor[0]->get_text());
+ vec.y=evaluator->eval(value_editor[1]->get_text());
+ } else {
+ vec.x=value_editor[0]->get_text().to_double();
+ vec.y=value_editor[1]->get_text().to_double();
+ }
+ v=vec;
+ _emit_changed_whole_or_field();
+
+ } break;
+ case Variant::RECT2: {
+
+ Rect2 r2;
+ if (evaluator) {
+ r2.pos.x=evaluator->eval(value_editor[0]->get_text());
+ r2.pos.y=evaluator->eval(value_editor[1]->get_text());
+ r2.size.x=evaluator->eval(value_editor[2]->get_text());
+ r2.size.y=evaluator->eval(value_editor[3]->get_text());
+ } else {
+ r2.pos.x=value_editor[0]->get_text().to_double();
+ r2.pos.y=value_editor[1]->get_text().to_double();
+ r2.size.x=value_editor[2]->get_text().to_double();
+ r2.size.y=value_editor[3]->get_text().to_double();
+ }
+ v=r2;
+ _emit_changed_whole_or_field();
+
+ } break;
+
+ case Variant::VECTOR3: {
+
+ Vector3 vec;
+ if (evaluator) {
+ vec.x=evaluator->eval(value_editor[0]->get_text());
+ vec.y=evaluator->eval(value_editor[1]->get_text());
+ vec.z=evaluator->eval(value_editor[2]->get_text());
+ } else {
+ vec.x=value_editor[0]->get_text().to_double();
+ vec.y=value_editor[1]->get_text().to_double();
+ vec.z=value_editor[2]->get_text().to_double();
+ }
+ v=vec;
+ _emit_changed_whole_or_field();
+
+ } break;
+ case Variant::PLANE: {
+
+ Plane pl;
+ if (evaluator) {
+ pl.normal.x=evaluator->eval(value_editor[0]->get_text());
+ pl.normal.y=evaluator->eval(value_editor[1]->get_text());
+ pl.normal.z=evaluator->eval(value_editor[2]->get_text());
+ pl.d=evaluator->eval(value_editor[3]->get_text());
+ } else {
+ pl.normal.x=value_editor[0]->get_text().to_double();
+ pl.normal.y=value_editor[1]->get_text().to_double();
+ pl.normal.z=value_editor[2]->get_text().to_double();
+ pl.d=value_editor[3]->get_text().to_double();
+ }
+ v=pl;
+ _emit_changed_whole_or_field();
+
+ } break;
+ case Variant::QUAT: {
+
+ Quat q;
+ if (evaluator) {
+ q.x=evaluator->eval(value_editor[0]->get_text());
+ q.y=evaluator->eval(value_editor[1]->get_text());
+ q.z=evaluator->eval(value_editor[2]->get_text());
+ q.w=evaluator->eval(value_editor[3]->get_text());
+ } else {
+ q.x=value_editor[0]->get_text().to_double();
+ q.y=value_editor[1]->get_text().to_double();
+ q.z=value_editor[2]->get_text().to_double();
+ q.w=value_editor[3]->get_text().to_double();
+ }
+ v=q;
+ _emit_changed_whole_or_field();
+
+ } break;
+ case Variant::RECT3: {
+
+ Vector3 pos;
+ Vector3 size;
+
+ if (evaluator) {
+ pos.x=evaluator->eval(value_editor[0]->get_text());
+ pos.y=evaluator->eval(value_editor[1]->get_text());
+ pos.z=evaluator->eval(value_editor[2]->get_text());
+ size.x=evaluator->eval(value_editor[3]->get_text());
+ size.y=evaluator->eval(value_editor[4]->get_text());
+ size.z=evaluator->eval(value_editor[5]->get_text());
+ } else {
+ pos.x=value_editor[0]->get_text().to_double();
+ pos.y=value_editor[1]->get_text().to_double();
+ pos.z=value_editor[2]->get_text().to_double();
+ size.x=value_editor[3]->get_text().to_double();
+ size.y=value_editor[4]->get_text().to_double();
+ size.z=value_editor[5]->get_text().to_double();
+ }
+ v=Rect3(pos,size);
+ _emit_changed_whole_or_field();
+
+ } break;
+ case Variant::TRANSFORM2D: {
+
+ Transform2D m;
+ for(int i=0;i<6;i++) {
+ if (evaluator) {
+ m.elements[i/2][i%2]=evaluator->eval(value_editor[i]->get_text());
+ } else {
+ m.elements[i/2][i%2]=value_editor[i]->get_text().to_double();
+ }
+ }
+
+ v=m;
+ _emit_changed_whole_or_field();
+
+ } break;
+ case Variant::BASIS: {
+
+ Basis m;
+ for(int i=0;i<9;i++) {
+
+ if (evaluator) {
+ m.elements[i/3][i%3]=evaluator->eval(value_editor[i]->get_text());
+ } else {
+ m.elements[i/3][i%3]=value_editor[i]->get_text().to_double();
+ }
+ }
+
+ v=m;
+ _emit_changed_whole_or_field();
+
+ } break;
+ case Variant::TRANSFORM: {
+
+ Basis basis;
+ for(int i=0;i<9;i++) {
+
+ if (evaluator) {
+ basis.elements[i/3][i%3]=evaluator->eval(value_editor[(i/3)*4+i%3]->get_text());
+ } else {
+ basis.elements[i/3][i%3]=value_editor[(i/3)*4+i%3]->get_text().to_double();
+ }
+ }
+
+ Vector3 origin;
+
+ if (evaluator) {
+ origin.x=evaluator->eval(value_editor[3]->get_text());
+ origin.y=evaluator->eval(value_editor[7]->get_text());
+ origin.z=evaluator->eval(value_editor[11]->get_text());
+ } else {
+ origin.x=value_editor[3]->get_text().to_double();
+ origin.y=value_editor[7]->get_text().to_double();
+ origin.z=value_editor[11]->get_text().to_double();
+ }
+
+ v=Transform(basis,origin);
+ _emit_changed_whole_or_field();
+
+
+ } break;
+ case Variant::COLOR: {
+ /*
+ for (int i=0;i<4;i++) {
+
+ scroll[i]->set_val( value_editor[i]->get_text().to_double() );
+ }
+ Color c;
+ c.r=value_editor[0]->get_text().to_double();
+ c.g=value_editor[1]->get_text().to_double();
+ c.b=value_editor[2]->get_text().to_double();
+ c.a=value_editor[3]->get_text().to_double();
+ v=c;
+ update();
+ emit_signal("variant_changed");
+ */
+ } break;
+ case Variant::IMAGE: {
+
+
+ } break;
+ case Variant::NODE_PATH: {
+
+ v=NodePath(value_editor[0]->get_text());
+ emit_signal("variant_changed");
+ } break;
+ case Variant::INPUT_EVENT: {
+
+
+ } break;
+ case Variant::DICTIONARY: {
+
+
+ } break;
+ case Variant::POOL_BYTE_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_INT_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+
+
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+
+
+ } break;
+ default: {}
+ }
+
+ updating=false;
+}
+
+void CustomPropertyEditor::_emit_changed_whole_or_field() {
+
+ if (!Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ emit_signal("variant_changed");
+ } else {
+ emit_signal("variant_field_changed",field_names[focused_value_editor]);
+ }
+}
+
+void CustomPropertyEditor::_range_modified(double p_value)
+{
+ v=p_value;
+ emit_signal("variant_changed");
+}
+
+void CustomPropertyEditor::_focus_enter() {
+ switch(type) {
+ case Variant::REAL:
+ case Variant::STRING:
+ case Variant::VECTOR2:
+ case Variant::RECT2:
+ case Variant::VECTOR3:
+ case Variant::PLANE:
+ case Variant::QUAT:
+ case Variant::RECT3:
+ case Variant::TRANSFORM2D:
+ case Variant::BASIS:
+ case Variant::TRANSFORM: {
+ for (int i=0;i<MAX_VALUE_EDITORS;++i) {
+ if (value_editor[i]->has_focus()) {
+ focused_value_editor=i;
+ value_editor[i]->select_all();
+ break;
+ }
+ }
+ } break;
+ default: {}
+ }
+
+}
+
+void CustomPropertyEditor::_focus_exit() {
+ switch(type) {
+ case Variant::REAL:
+ case Variant::STRING:
+ case Variant::VECTOR2:
+ case Variant::RECT2:
+ case Variant::VECTOR3:
+ case Variant::PLANE:
+ case Variant::QUAT:
+ case Variant::RECT3:
+ case Variant::TRANSFORM2D:
+ case Variant::BASIS:
+ case Variant::TRANSFORM: {
+ for (int i=0;i<MAX_VALUE_EDITORS;++i) {
+ value_editor[i]->select(0, 0);
+ }
+ } break;
+ default: {}
+ }
+
+}
+
+void CustomPropertyEditor::config_action_buttons(const List<String>& p_strings) {
+
+ int w=100;
+ int h=18;
+ int m=5;
+
+ set_size( Size2( w, m*2+(h+m)*p_strings.size() ) );
+
+ for (int i=0;i<MAX_ACTION_BUTTONS;i++) {
+
+ if (i<p_strings.size()) {
+ action_buttons[i]->show();
+ action_buttons[i]->set_text(p_strings[i]);
+ action_buttons[i]->set_pos( Point2( m, m+i*(h+m) ));
+ action_buttons[i]->set_size( Size2( w-m*2, h ) );
+ action_buttons[i]->set_flat(true);
+ } else {
+ action_buttons[i]->hide();
+ }
+ }
+
+
+}
+
+void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns,int p_label_w,const List<String>& p_strings) {
+
+ int w=80;
+ int h=20;
+ int m=10;
+
+ int rows=((p_amount-1)/p_columns)+1;
+
+ set_size( Size2( m*(1+p_columns)+(w+p_label_w)*p_columns, m*(1+rows)+h*rows ) );
+
+ for (int i=0;i<MAX_VALUE_EDITORS;i++) {
+
+ int c=i%p_columns;
+ int r=i/p_columns;
+
+ if (i<p_amount) {
+ value_editor[i]->show();
+ value_label[i]->show();
+ value_label[i]->set_text(i<p_strings.size()?p_strings[i]:String(""));
+ value_editor[i]->set_pos( Point2( m+p_label_w+c*(w+m+p_label_w), m+r*(h+m) ));
+ value_editor[i]->set_size( Size2( w, h ) );
+ value_label[i]->set_pos( Point2( m+c*(w+m+p_label_w), m+r*(h+m) ) );
+ value_editor[i]->set_editable(!read_only);
+ } else {
+ value_editor[i]->hide();
+ value_label[i]->hide();
+ }
+ }
+
+
+
+}
+
+
+void CustomPropertyEditor::_bind_methods() {
+
+ ClassDB::bind_method("_focus_enter", &CustomPropertyEditor::_focus_enter);
+ ClassDB::bind_method("_focus_exit", &CustomPropertyEditor::_focus_exit);
+ ClassDB::bind_method("_modified",&CustomPropertyEditor::_modified);
+ ClassDB::bind_method("_range_modified", &CustomPropertyEditor::_range_modified);
+ ClassDB::bind_method("_scroll_modified",&CustomPropertyEditor::_scroll_modified);
+ ClassDB::bind_method("_action_pressed",&CustomPropertyEditor::_action_pressed);
+ ClassDB::bind_method("_file_selected",&CustomPropertyEditor::_file_selected);
+ ClassDB::bind_method("_type_create_selected",&CustomPropertyEditor::_type_create_selected);
+ ClassDB::bind_method("_node_path_selected",&CustomPropertyEditor::_node_path_selected);
+ ClassDB::bind_method("_color_changed",&CustomPropertyEditor::_color_changed);
+ ClassDB::bind_method("_draw_easing",&CustomPropertyEditor::_draw_easing);
+ ClassDB::bind_method("_drag_easing",&CustomPropertyEditor::_drag_easing);
+ ClassDB::bind_method( "_text_edit_changed",&CustomPropertyEditor::_text_edit_changed);
+ ClassDB::bind_method( "_menu_option",&CustomPropertyEditor::_menu_option);
+ ClassDB::bind_method( "_create_dialog_callback",&CustomPropertyEditor::_create_dialog_callback);
+ ClassDB::bind_method( "_create_selected_property",&CustomPropertyEditor::_create_selected_property);
+
+
+
+ ADD_SIGNAL( MethodInfo("variant_changed") );
+ ADD_SIGNAL( MethodInfo("variant_field_changed",PropertyInfo(Variant::STRING,"field")) );
+ ADD_SIGNAL( MethodInfo("resource_edit_request") );
+}
+CustomPropertyEditor::CustomPropertyEditor() {
+
+
+ read_only=false;
+ updating=false;
+
+ for (int i=0;i<MAX_VALUE_EDITORS;i++) {
+
+ value_editor[i]=memnew( LineEdit );
+ add_child( value_editor[i] );
+ value_label[i]=memnew( Label );
+ add_child( value_label[i] );
+ value_editor[i]->hide();
+ value_label[i]->hide();
+ value_editor[i]->connect("text_entered", this,"_modified");
+ value_editor[i]->connect("focus_entered", this, "_focus_enter");
+ value_editor[i]->connect("focus_exited", this, "_focus_exit");
+ }
+ focused_value_editor=-1;
+
+ for(int i=0;i<4;i++) {
+
+ scroll[i] = memnew( HScrollBar );
+ scroll[i]->hide();
+ scroll[i]->set_min(0);
+ scroll[i]->set_max(1.0);
+ scroll[i]->set_step(0.01);
+ add_child(scroll[i]);
+ scroll[i]->connect("value_changed", this,"_scroll_modified");
+
+ }
+
+ checks20gc = memnew( GridContainer );
+ add_child(checks20gc);
+ checks20gc->set_columns(11);
+
+ for(int i=0;i<20;i++) {
+ if (i==5 || i==15) {
+ Control *space = memnew( Control );
+ space->set_custom_minimum_size(Size2(20,0)*EDSCALE);
+ checks20gc->add_child(space);
+ }
+
+ checks20[i]=memnew( CheckBox );
+ checks20[i]->set_toggle_mode(true);
+ checks20[i]->set_focus_mode(FOCUS_NONE);
+ checks20gc->add_child(checks20[i]);
+ checks20[i]->hide();
+ checks20[i]->connect("pressed",this,"_action_pressed",make_binds(i));
+ checks20[i]->set_tooltip(vformat(TTR("Bit %d, val %d."), i, 1<<i));
+ }
+
+ text_edit = memnew( TextEdit );
+ add_child(text_edit);
+ text_edit->set_area_as_parent_rect();
+ for(int i=0;i<4;i++)
+ text_edit->set_margin((Margin)i,5);
+ text_edit->set_margin(MARGIN_BOTTOM,30);
+
+ text_edit->hide();
+ text_edit->connect("text_changed",this,"_text_edit_changed");
+
+ for (int i=0;i<MAX_ACTION_BUTTONS;i++) {
+
+ action_buttons[i]=memnew(Button);
+ action_buttons[i]->hide();
+ add_child(action_buttons[i]);
+ Vector<Variant> binds;
+ binds.push_back(i);
+ action_buttons[i]->connect("pressed", this,"_action_pressed",binds);
+ }
+
+ color_picker=NULL;
+
+
+
+ set_as_toplevel(true);
+ file = memnew ( EditorFileDialog );
+ add_child(file);
+ file->hide();
+
+ file->connect("file_selected", this,"_file_selected");
+ file->connect("dir_selected", this,"_file_selected");
+
+ error = memnew( ConfirmationDialog );
+ error->set_title(TTR("Error!"));
+ add_child(error);
+ //error->get_cancel()->hide();
+
+ type_button = memnew( MenuButton );
+ add_child(type_button);
+ type_button->hide();
+ type_button->get_popup()->connect("id_pressed", this,"_type_create_selected");
+
+
+ scene_tree = memnew( SceneTreeDialog );
+ add_child(scene_tree);
+ scene_tree->connect("selected", this,"_node_path_selected");
+ scene_tree->get_scene_tree()->set_show_enabled_subscene(true);
+
+ texture_preview = memnew( TextureRect );
+ add_child( texture_preview);
+ texture_preview->hide();
+
+ easing_draw=memnew( Control );
+ add_child(easing_draw);
+ easing_draw->hide();
+ easing_draw->connect("draw",this,"_draw_easing");
+ easing_draw->connect("gui_input",this,"_drag_easing");
+ //easing_draw->emit_signal(SceneStringNames::get_singleton()->input_event,InputEvent());
+ easing_draw->set_default_cursor_shape(Control::CURSOR_MOVE);
+
+ menu = memnew(PopupMenu);
+ add_child(menu);
+ menu->connect("id_pressed",this,"_menu_option");
+
+ evaluator = NULL;
+
+ spinbox = memnew ( SpinBox );
+ add_child(spinbox);
+ spinbox->set_area_as_parent_rect(5);
+ spinbox->connect("value_changed",this,"_range_modified");
+
+ slider = memnew ( HSlider );
+ add_child(slider);
+ slider->set_area_as_parent_rect(5);
+ slider->connect("value_changed",this,"_range_modified");
+
+ create_dialog = NULL;
+ property_select = NULL;
+}
+
+bool PropertyEditor::_might_be_in_instance() {
+
+ if (!obj)
+ return false;
+
+ Node *node = obj->cast_to<Node>();
+
+ Node* edited_scene =EditorNode::get_singleton()->get_edited_scene();
+
+ bool might_be=false;
+
+ while(node) {
+
+ if (node->get_scene_instance_state().is_valid()) {
+ might_be=true;
+ break;
+ }
+ if (node==edited_scene) {
+ if (node->get_scene_inherited_state().is_valid()) {
+ might_be=true;
+ break;
+ }
+ might_be=false;
+ break;
+ }
+ node=node->get_owner();
+ }
+
+ return might_be;
+
+}
+
+bool PropertyEditor::_get_instanced_node_original_property(const StringName& p_prop, Variant& value) {
+
+ Node *node = obj->cast_to<Node>();
+
+ if (!node)
+ return false;
+
+ Node *orig=node;
+
+ Node* edited_scene =EditorNode::get_singleton()->get_edited_scene();
+
+ bool found=false;
+
+ //print_line("for prop - "+String(p_prop));
+
+
+ while(node) {
+
+ Ref<SceneState> ss;
+
+ if (node==edited_scene) {
+ ss=node->get_scene_inherited_state();
+
+ } else {
+ ss=node->get_scene_instance_state();
+ }
+ //print_line("at - "+String(edited_scene->get_path_to(node)));
+
+ if (ss.is_valid()) {
+
+ NodePath np = node->get_path_to(orig);
+ int node_idx = ss->find_node_by_path(np);
+ //print_line("\t valid, nodeidx "+itos(node_idx));
+ if (node_idx>=0) {
+ bool lfound=false;
+ Variant lvar;
+ lvar=ss->get_property_value(node_idx,p_prop,lfound);
+ if (lfound) {
+
+ found=true;
+ value=lvar;
+ //print_line("\t found value "+String(value));
+ }
+ }
+ }
+ if (node==edited_scene) {
+ //just in case
+ break;
+ }
+ node=node->get_owner();
+
+ }
+
+ return found;
+}
+
+bool PropertyEditor::_is_property_different(const Variant& p_current, const Variant& p_orig,int p_usage) {
+
+
+ {
+ Node *node = obj->cast_to<Node>();
+ if (!node)
+ return false;
+
+ Node* edited_scene =EditorNode::get_singleton()->get_edited_scene();
+ bool found_state=false;
+
+ //print_line("for prop - "+String(p_prop));
+
+
+ while(node) {
+
+ Ref<SceneState> ss;
+
+ if (node==edited_scene) {
+ ss=node->get_scene_inherited_state();
+
+ } else {
+ ss=node->get_scene_instance_state();
+ }
+
+ if (ss.is_valid()) {
+ found_state=true;
+ }
+ if (node==edited_scene) {
+ //just in case
+ break;
+ }
+ node=node->get_owner();
+ }
+
+ if (!found_state)
+ return false; //pointless to check if we are not comparing against anything.
+ }
+
+ if (p_orig.get_type()==Variant::NIL) {
+
+
+
+ //special cases
+ if (p_current.is_zero() && p_usage&PROPERTY_USAGE_STORE_IF_NONZERO)
+ return false;
+ if (p_current.is_one() && p_usage&PROPERTY_USAGE_STORE_IF_NONONE)
+ return false;
+ }
+
+ if (p_current.get_type()==Variant::REAL && p_orig.get_type()==Variant::REAL) {
+ float a = p_current;
+ float b = p_orig;
+
+ return Math::abs(a-b)>CMP_EPSILON; //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error
+ }
+
+ return bool(Variant::evaluate(Variant::OP_NOT_EQUAL,p_current,p_orig));
+}
+
+TreeItem *PropertyEditor::find_item(TreeItem *p_item,const String& p_name) {
+
+
+ if (!p_item)
+ return NULL;
+
+ String name = p_item->get_metadata(1);
+
+ if (name==p_name) {
+
+ return p_item;
+ }
+
+ TreeItem *c=p_item->get_children();
+
+ while (c) {
+
+ TreeItem *found = find_item(c,p_name);
+ if (found)
+ return found;
+ c=c->get_next();
+ }
+
+ return NULL;
+}
+
+
+void PropertyEditor::_changed_callback(Object *p_changed,const char * p_prop) {
+
+
+ _changed_callbacks(p_changed,p_prop);
+}
+
+void PropertyEditor::_changed_callbacks(Object *p_changed,const String& p_prop) {
+
+
+ if (p_changed!=obj)
+ return;
+
+ if (changing)
+ return;
+
+ if (p_prop==String())
+ update_tree_pending=true;
+ else {
+
+ pending[p_prop]=p_prop;
+
+ }
+}
+
+void PropertyEditor::update_property(const String& p_prop) {
+
+ if (obj)
+ _changed_callbacks(obj,p_prop);
+}
+
+
+void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p_name, int p_hint, const String& p_hint_text) {
+
+ switch( p_type ) {
+
+ case Variant::BOOL: {
+
+ p_item->set_checked( 1, obj->get( p_name ) );
+ } break;
+ case Variant::REAL:
+ case Variant::INT: {
+
+ if (p_hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || p_hint==PROPERTY_HINT_LAYERS_2D_RENDER || p_hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || p_hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
+ tree->update();
+ break;
+ }
+
+ if (p_hint==PROPERTY_HINT_FLAGS) {
+ Vector<String> values = p_hint_text.split(",");
+ String flags;
+ int val = obj->get(p_name);
+ for(int i=0;i<values.size();i++) {
+
+ String v = values[i];
+ if (v=="")
+ continue;
+ if (!(val&(1<<i)))
+ continue;
+
+ if (flags!="")
+ flags+=", ";
+ flags+=v;
+ }
+ p_item->set_text(1, flags );
+ break;
+ }
+
+ if (p_hint==PROPERTY_HINT_EXP_EASING) {
+
+ p_item->set_text(1, String::num(obj->get( p_name ),2) );
+ break;
+ }
+
+
+ //p_item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
+
+ if (p_type==Variant::REAL) {
+ p_item->set_range(1, obj->get( p_name ) );
+
+ } else {
+ /* FIXME: Why are both statements equal? */
+ p_item->set_range(1, obj->get( p_name ) );
+ }
+
+
+ p_item->set_editable(1,!read_only);
+
+
+ } break;
+ case Variant::STRING:
+
+
+ if (p_hint==PROPERTY_HINT_TYPE_STRING) {
+
+ p_item->set_text(1,obj->get(p_name));
+ }
+
+ if ( p_hint==PROPERTY_HINT_METHOD_OF_VARIANT_TYPE ||
+ p_hint==PROPERTY_HINT_METHOD_OF_BASE_TYPE ||
+ p_hint==PROPERTY_HINT_METHOD_OF_INSTANCE ||
+ p_hint==PROPERTY_HINT_METHOD_OF_SCRIPT ||
+ p_hint==PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE ||
+ p_hint==PROPERTY_HINT_PROPERTY_OF_BASE_TYPE ||
+ p_hint==PROPERTY_HINT_PROPERTY_OF_INSTANCE ||
+ p_hint==PROPERTY_HINT_PROPERTY_OF_SCRIPT ) {
+
+ p_item->set_text(1,obj->get(p_name));
+ }
+
+
+ if (p_hint==PROPERTY_HINT_ENUM) {
+
+ Vector<String> strings = p_hint_text.split(",");
+ String current = obj->get(p_name);
+ int idx=0;
+ for(int x=0;x<strings.size();x++) {
+ if (strings[x]==current) {
+ idx=x;
+ break;
+ }
+ }
+ p_item->set_text(1, p_hint_text);
+ p_item->set_range(1,idx);
+ break;
+ }
+
+ case Variant::VECTOR3:
+ case Variant::QUAT:
+ case Variant::VECTOR2:
+ case Variant::RECT3:
+ case Variant::RECT2:
+ case Variant::TRANSFORM2D:
+ case Variant::BASIS:
+ case Variant::TRANSFORM: {
+
+ p_item->set_text(1,obj->get(p_name));
+
+ } break;
+ case Variant::COLOR: {
+
+ tree->update();
+ //p_item->set_text(1,obj->get(p_name));
+
+ } break;
+ case Variant::IMAGE: {
+
+ Image img = obj->get( p_name );
+ 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())+"-"+String(Image::get_format_name(img.get_format()))+"]");
+
+ } break;
+ case Variant::NODE_PATH: {
+
+ p_item->set_text(1,obj->get(p_name));
+ } break;
+ case Variant::OBJECT: {
+
+
+ if (obj->get( p_name ).get_type() == Variant::NIL || obj->get( p_name ).operator RefPtr().is_null()) {
+ p_item->set_text(1,"<null>");
+ p_item->set_icon(1,Ref<Texture>());
+
+ Dictionary d = p_item->get_metadata(0);
+ int hint=d.has("hint")?d["hint"].operator int():-1;
+ String hint_text=d.has("hint_text")?d["hint_text"]:"";
+ if (hint==PROPERTY_HINT_RESOURCE_TYPE && hint_text == "Texture") {
+ p_item->set_icon(1,NULL);
+ }
+
+ } else {
+ RES res = obj->get( p_name ).operator RefPtr();
+ if (res->is_class("Texture")) {
+ int tw = EditorSettings::get_singleton()->get("docks/property_editor/texture_preview_width");
+ p_item->set_icon_max_width(1,tw);
+ p_item->set_icon(1,res);
+ p_item->set_text(1,"");
+
+ } else if (res->get_name() != "") {
+
+ p_item->set_text(1, res->get_name());
+ } else if (res->get_path()!="" && !res->get_path().begins_with("local://")) {
+ p_item->set_text(1, res->get_path().get_file());
+ } else {
+ p_item->set_text(1,"<"+res->get_class()+">");
+ };
+
+
+ if (res.is_valid() && res->get_path().is_resource_file()) {
+ p_item->set_tooltip(1,res->get_path());
+ } else if (res.is_valid()) {
+ p_item->set_tooltip(1,res->get_name()+" ("+res->get_class()+")");
+ }
+
+
+ if (has_icon(res->get_class(),"EditorIcons")) {
+
+ p_item->set_icon(0,get_icon(res->get_class(),"EditorIcons"));
+ } else {
+
+ Dictionary d = p_item->get_metadata(0);
+ int hint=d.has("hint")?d["hint"].operator int():-1;
+ String hint_text=d.has("hint_text")?d["hint_text"]:"";
+ if (hint==PROPERTY_HINT_RESOURCE_TYPE) {
+
+ if (has_icon(hint_text,"EditorIcons")) {
+
+ p_item->set_icon(0,get_icon(hint_text,"EditorIcons"));
+
+ } else {
+ p_item->set_icon(0,get_icon("Object","EditorIcons"));
+
+ }
+ }
+ }
+
+ if (!res->is_class("Texture")) {
+ //texture already previews via itself
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res,this,"_resource_preview_done",p_item->get_instance_ID());
+ }
+
+
+
+ }
+
+
+ } break;
+ default: {};
+ }
+
+}
+
+
+void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
+
+ bool has_reload=false;
+ int found=-1;
+ bool is_disabled=false;
+
+ for(int i=0;i<item->get_button_count(1);i++) {
+
+ if (item->get_button_id(1,i)==3) {
+ found=i;
+ is_disabled=item->is_button_disabled(1,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 && !is_disabled)!=changed) {
+
+ if (changed) {
+
+ has_reload=true;
+ } else {
+
+ }
+
+ //}
+
+ }
+
+ }
+
+ if (obj->call("property_can_revert",p_name).operator bool()) {
+
+ 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)) {
+ has_reload=true;
+ }
+ }
+ }
+
+ //print_line("found: "+itos(found)+" has reload: "+itos(has_reload)+" is_disabled "+itos(is_disabled));
+ if (found!=-1 && !has_reload) {
+
+ if (!is_disabled) {
+ item->erase_button(1,found);
+ if (item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) {
+ item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true);
+ }
+ }
+ } else if (found==-1 && has_reload) {
+ item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
+ } else if (found!=-1 && has_reload && is_disabled) {
+ item->erase_button(1,found);
+ item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
+ }
+}
+
+
+
+bool PropertyEditor::_is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const {
+
+ Dictionary d = p_item_data;
+
+ if (d.has("type")) {
+
+ int type = d["type"];
+ if (type==Variant::OBJECT && d.has("hint") && d.has("hint_text") && int(d["hint"])==PROPERTY_HINT_RESOURCE_TYPE) {
+
+
+ String allowed_type=d["hint_text"];
+
+ Dictionary drag_data = p_drag_data;
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ Ref<Resource> res = drag_data["resource"];
+ for(int i=0;i<allowed_type.get_slice_count(",");i++) {
+ String at = allowed_type.get_slice(",",i).strip_edges();
+ if (res.is_valid() && ClassDB::is_parent_class(res->get_class(),at)) {
+ return true;
+ }
+ }
+
+ }
+
+ if (drag_data.has("type") && String(drag_data["type"])=="files") {
+
+ Vector<String> files = drag_data["files"];
+
+ if (files.size()==1) {
+ String file = files[0];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+ if (ftype!="") {
+
+ for(int i=0;i<allowed_type.get_slice_count(",");i++) {
+ String at = allowed_type.get_slice(",",i).strip_edges();
+ if (ClassDB::is_parent_class(ftype,at)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ return false;
+
+}
+void PropertyEditor::_mark_drop_fields(TreeItem* p_at) {
+
+ if (_is_drop_valid(get_viewport()->gui_get_drag_data(),p_at->get_metadata(0)))
+ p_at->set_custom_bg_color(1,Color(0.7,0.5,0.2),true);
+
+ if (p_at->get_children()) {
+ _mark_drop_fields(p_at->get_children());
+ }
+
+ if (p_at->get_next()) {
+ _mark_drop_fields(p_at->get_next());
+ }
+}
+
+Variant PropertyEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return Variant();
+
+ Dictionary d = item->get_metadata(0);
+ if (!d.has("name"))
+ return Variant();
+
+ int col = tree->get_column_at_pos(p_point);
+ if (col==0) {
+
+ Dictionary dp;
+ dp["type"]="obj_property";
+ dp["object"]=obj;
+ dp["property"]=d["name"];
+ dp["value"]=obj->get(d["name"]);
+
+ Label *label =memnew( Label );
+ label->set_text(d["name"]);
+ set_drag_preview(label);
+ return dp;
+ }
+
+
+
+ Variant val = obj->get(d["name"]);
+
+ if (val.get_type()==Variant::OBJECT) {
+ RES res = val;
+ if (res.is_valid()) {
+
+ custom_editor->hide_menu();
+ return EditorNode::get_singleton()->drag_resource(res,p_from);
+ }
+ }
+
+ return Variant();
+}
+
+bool PropertyEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return false;
+
+ int col = tree->get_column_at_pos(p_point);
+ if (col!=1)
+ return false;
+
+ return _is_drop_valid(p_data,item->get_metadata(0));
+
+}
+void PropertyEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return;
+
+ int col = tree->get_column_at_pos(p_point);
+ if (col!=1)
+ return;
+
+ if (!_is_drop_valid(p_data,item->get_metadata(0)))
+ return;
+
+ Dictionary d = item->get_metadata(0);
+
+ if (!d.has("name"))
+ return;
+
+ String name=d["name"];
+
+ Dictionary drag_data = p_data;
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ Ref<Resource> res = drag_data["resource"];
+ if (res.is_valid()) {
+ _edit_set(name,res);
+ return;
+ }
+ }
+
+ if (drag_data.has("type") && String(drag_data["type"])=="files") {
+
+ Vector<String> files = drag_data["files"];
+
+ if (files.size()==1) {
+ String file = files[0];
+ RES res = ResourceLoader::load(file);
+ if (res.is_valid()) {
+ _edit_set(name,res);
+ return;
+ }
+ }
+ }
+}
+
+
+void PropertyEditor::_clear_drop_fields(TreeItem* p_at) {
+
+ Dictionary d = p_at->get_metadata(0);
+
+ if (d.has("type")) {
+
+ int type = d["type"];
+ if (type==Variant::OBJECT) {
+ p_at->clear_custom_bg_color(1);
+ }
+
+ }
+
+ if (p_at->get_children()) {
+ _clear_drop_fields(p_at->get_children());
+ }
+
+ if (p_at->get_next()) {
+ _clear_drop_fields(p_at->get_next());
+ }
+}
+
+void PropertyEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ get_tree()->connect("node_removed",this,"_node_removed");
+ }
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ get_tree()->disconnect("node_removed",this,"_node_removed");
+ edit(NULL);
+ }
+
+
+ if (p_what==NOTIFICATION_DRAG_BEGIN) {
+
+ if (is_visible_in_tree() && tree->get_root()) {
+ _mark_drop_fields(tree->get_root());
+ }
+ }
+
+ if (p_what==NOTIFICATION_DRAG_END) {
+ if (is_visible_in_tree() && tree->get_root()) {
+ _clear_drop_fields(tree->get_root());
+ }
+
+ }
+
+ if (p_what==NOTIFICATION_FIXED_PROCESS) {
+
+
+ if (refresh_countdown>0) {
+ refresh_countdown-=get_fixed_process_delta_time();
+ if (refresh_countdown<=0) {
+ TreeItem *root = tree->get_root();
+ _refresh_item(root);
+ }
+ }
+
+ changing=true;
+
+ if (update_tree_pending) {
+
+ update_tree();
+ update_tree_pending=false;
+
+ } else {
+
+ const String *k=NULL;
+ while ((k=pending.next(k))) {
+
+ TreeItem * item = find_item(tree->get_root(),*k);
+ if (!item)
+ continue;
+
+ _check_reload_status(*k,item);
+
+ Dictionary d=item->get_metadata(0);
+ set_item_text(item,d["type"],d["name"],d["hint"],d["hint_text"]);
+ }
+ }
+
+ pending.clear();
+
+ changing=false;
+
+ }
+}
+
+TreeItem *PropertyEditor::get_parent_node(String p_path,HashMap<String,TreeItem*>& item_paths,TreeItem *root) {
+
+ TreeItem *item=NULL;
+
+ if (p_path=="") {
+
+ item = root;
+ } else if (item_paths.has(p_path)) {
+
+ item = item_paths.get(p_path);
+ } else {
+
+ //printf("path %s parent path %s - item name %s\n",p_path.ascii().get_data(),p_path.left( p_path.find_last("/") ).ascii().get_data(),p_path.right( p_path.find_last("/") ).ascii().get_data() );
+ TreeItem *parent = get_parent_node( p_path.left( p_path.find_last("/") ),item_paths,root );
+ item = tree->create_item( parent );
+
+ String name = (p_path.find("/")!=-1)?p_path.right( p_path.find_last("/")+1 ):p_path;
+ if (capitalize_paths)
+ item->set_text(0, name.capitalize() );
+ else
+ item->set_text(0, name );
+ item->set_tooltip(0, p_path);
+ if (item->get_parent()!=root) {
+ item->set_icon( 0, get_icon("Folder","EditorIcons"));
+ }
+
+ item->set_editable(0,false);
+ item->set_selectable(0,subsection_selectable);
+ item->set_editable(1,false);
+ item->set_selectable(1,subsection_selectable);
+
+ if (item->get_parent()==root) {
+
+ item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
+ item->set_custom_bg_color(1,get_color("prop_subsection","Editor"));
+ }
+
+ item_paths[p_path]=item;
+ }
+
+ return item;
+
+}
+
+
+void PropertyEditor::_refresh_item(TreeItem *p_item) {
+
+ if (!p_item)
+ return;
+
+ String name = p_item->get_metadata(1);
+
+ 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);
+
+
+ bool changed = _is_property_different(v,vorig,usage);
+
+ if ((found!=-1)!=changed) {
+
+ if (changed) {
+
+ has_reload=true;
+
+ } else {
+
+ //p_item->erase_button(1,found);
+ }
+
+ }
+
+ }
+
+ }
+
+ 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("ReloadSmall","EditorIcons"),3);
+ }
+#endif
+ Dictionary d=p_item->get_metadata(0);
+ set_item_text(p_item,d["type"],d["name"],d["hint"],d["hint_text"]);
+ }
+
+ TreeItem *c=p_item->get_children();
+
+ while (c) {
+
+ _refresh_item(c);
+
+ c=c->get_next();
+ }
+
+}
+
+void PropertyEditor::refresh() {
+
+ if (refresh_countdown>0)
+ return;
+ refresh_countdown=EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval");
+
+}
+
+void PropertyEditor::update_tree() {
+
+
+ tree->clear();
+
+ if (!obj)
+ return;
+
+ HashMap<String,TreeItem*> item_path;
+
+ TreeItem *root = tree->create_item(NULL);
+ tree->set_hide_root(true);
+
+ /*
+ TreeItem *title = tree->create_item(root);
+
+ title->set_custom_bg_color(0,get_color("prop_section","Editor"));
+ title->set_text(0,"Property"); // todo, fetch name if ID exists in database
+ title->set_editable(0,false);
+ title->set_selectable(0,false);
+ title->set_custom_bg_color(1,get_color("prop_section","Editor"));
+ title->set_text(1,"Value"); // todo, fetch name if ID exists in database
+ title->set_editable(1,false);
+ title->set_selectable(1,false);
+*/
+
+ /*
+ if (obj->cast_to<Node>() || obj->cast_to<Resource>()) {
+ TreeItem *type = tree->create_item(root);
+
+ type->set_text(0,"Type"); // todo, fetch name if ID exists in database
+ type->set_text(1,obj->get_type()); // todo, fetch name if ID exists in database
+ if (has_icon(obj->get_type(),"EditorIcons"))
+ type->set_icon(1,get_icon(obj->get_type(),"EditorIcons") );
+ else
+ type->set_icon(1,get_icon("Object","EditorIcons") );
+
+ type->set_selectable(0,false);
+ type->set_selectable(1,false);
+
+
+ TreeItem *name = tree->create_item(root);
+
+ name->set_text(0,"Name"); // todo, fetch name if ID exists in database
+ if (obj->is_type("Resource"))
+ name->set_text(1,obj->cast_to<Resource>()->get_name());
+ else if (obj->is_type("Node"))
+ name->set_text(1,obj->cast_to<Node>()->get_name());
+ name->set_selectable(0,false);
+ name->set_selectable(1,false);
+ }
+*/
+ List<PropertyInfo> plist;
+ obj->get_property_list(&plist,true);
+
+ bool draw_red=false;
+
+ {
+ Node *nod = obj->cast_to<Node>();
+ Node *es = EditorNode::get_singleton()->get_edited_scene();
+ if (nod && es!=nod && nod->get_owner()!=es) {
+ draw_red=true;
+ }
+ }
+
+
+ Color sscolor=get_color("prop_subsection","Editor");
+
+ TreeItem * current_category=NULL;
+
+ String filter = search_box ? search_box->get_text() : "";
+ String group;
+ String group_base;
+
+ for (List<PropertyInfo>::Element *I=plist.front() ; I ; I=I->next()) {
+
+ PropertyInfo& p = I->get();
+
+ //make sure the property can be edited
+
+ if (p.usage&PROPERTY_USAGE_GROUP) {
+
+ group=p.name;
+ group_base=p.hint_string;
+
+ continue;
+
+ } else if (p.usage&PROPERTY_USAGE_CATEGORY) {
+
+ group="";
+ group_base="";
+
+ if (!show_categories)
+ continue;
+
+ List<PropertyInfo>::Element *N=I->next();
+ bool valid=true;
+ //if no properties in category, skip
+ while(N) {
+ if (N->get().usage&PROPERTY_USAGE_EDITOR)
+ break;
+ if (N->get().usage&PROPERTY_USAGE_CATEGORY) {
+ valid=false;
+ break;
+ }
+ N=N->next();
+ }
+ if (!valid)
+ continue; //empty, ignore
+ TreeItem * sep = tree->create_item(root);
+ current_category=sep;
+ String type=p.name;
+ /*if (has_icon(type,"EditorIcons"))
+ sep->set_icon(0,get_icon(type,"EditorIcons") );
+ else
+ sep->set_icon(0,get_icon("Object","EditorIcons") );
+ print_line("CATEGORY: "+type);
+ */
+ sep->set_text(0,type);
+ sep->set_selectable(0,false);
+ sep->set_selectable(1,false);
+ sep->set_custom_bg_color(0,get_color("prop_category","Editor"));
+ sep->set_custom_bg_color(1,get_color("prop_category","Editor"));
+
+ if (use_doc_hints) {
+ StringName type=p.name;
+ if (!class_descr_cache.has(type)) {
+
+ String descr;
+ DocData *dd=EditorHelp::get_doc_data();
+ Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
+ if (E) {
+ descr=E->get().brief_description;
+ }
+ class_descr_cache[type]=descr.word_wrap(80);
+
+ }
+
+ sep->set_tooltip(0,TTR("Class:")+" "+p.name+":\n\n"+class_descr_cache[type]);
+ }
+ //sep->set_custom_color(0,Color(1,1,1));
+
+
+ continue;
+ } else if ( ! (p.usage&PROPERTY_USAGE_EDITOR ) )
+ continue;
+
+
+ if (hide_script && p.name=="script")
+ continue;
+
+ String basename=p.name;
+ if (group!="") {
+ if (group_base!="") {
+ if (basename.begins_with(group_base)) {
+ basename=basename.replace_first(group_base,"");
+ } else {
+ group=""; //no longer using group base, clear
+ }
+ }
+ }
+
+ if (group!="") {
+ basename=group+"/"+basename;
+ }
+
+ String name = (basename.find("/")!=-1)?basename.right( basename.find_last("/")+1 ):basename;
+
+ if (capitalize_paths)
+ name = name.camelcase_to_underscore().capitalize();
+
+ String path=basename.left( basename.find_last("/") ) ;
+
+ if (use_filter && filter!="") {
+
+ String cat = path;
+
+ if (capitalize_paths)
+ cat = cat.capitalize();
+
+ if (!filter.is_subsequence_ofi(cat) && !filter.is_subsequence_ofi(name))
+ continue;
+ }
+
+ //printf("property %s\n",basename.ascii().get_data());
+ TreeItem * parent = get_parent_node(path,item_path,current_category?current_category:root );
+ /*
+ if (parent->get_parent()==root)
+ parent=root;
+ */
+ int level = 0;
+ if (parent!=root) {
+ level++;
+ TreeItem *parent_lev=parent;
+ while(parent_lev->get_parent()!=root) {
+ parent_lev=parent_lev->get_parent();
+ level++;
+ }
+ }
+ if (level>4)
+ level=4;
+
+ Color col = sscolor;
+ col.a=(level/4.0)*0.7;
+
+ TreeItem * item = tree->create_item( parent );
+
+ if (level>0) {
+ item->set_custom_bg_color(0,col);
+ //item->set_custom_bg_color(1,col);
+ }
+ item->set_editable(0,false);
+ item->set_selectable(0,false);
+
+ if (p.usage&PROPERTY_USAGE_CHECKABLE) {
+
+ item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
+ item->set_selectable(0,true);
+ item->set_editable(0,true);
+ item->set_checked(0,p.usage&PROPERTY_USAGE_CHECKED);
+ }
+
+ item->set_text(0, name);
+ item->set_tooltip(0, p.name);
+
+ if (use_doc_hints) {
+ StringName setter;
+ StringName type;
+ if (ClassDB::get_setter_and_type_for_property(obj->get_class_name(),p.name,type,setter)) {
+
+ String descr;
+ bool found=false;
+ Map<StringName,Map<StringName,String> >::Element *E=descr_cache.find(type);
+ if (E) {
+
+ Map<StringName,String>::Element *F=E->get().find(setter);
+ if (F) {
+ found=true;
+ descr=F->get();
+ }
+ }
+ if (!found) {
+
+ DocData *dd=EditorHelp::get_doc_data();
+ Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
+ if (E) {
+ for(int i=0;i<E->get().methods.size();i++) {
+ if (E->get().methods[i].name==setter.operator String()) {
+ descr=E->get().methods[i].description.strip_edges().word_wrap(80);
+ }
+ }
+ }
+
+ descr_cache[type][setter]=descr;
+ }
+
+ item->set_tooltip(0, TTR("Property:")+" "+p.name+"\n\n"+descr);
+ }
+ }
+ //EditorHelp::get_doc_data();
+
+ Dictionary d;
+ d["name"]=p.name;
+ d["type"]=(int)p.type;
+ d["hint"]=(int)p.hint;
+ d["hint_text"]=p.hint_string;
+ d["usage"]=(int)p.usage;
+
+ item->set_metadata( 0, d );
+ item->set_metadata( 1, p.name );
+
+ if (draw_red)
+ item->set_custom_color(0,Color(0.8,0.4,0.20));
+
+
+ if (p.name==selected_property) {
+
+ item->select(1);
+ }
+
+
+ //printf("property %s type %i\n",p.name.ascii().get_data(),p.type);
+ switch( p.type ) {
+
+ case Variant::BOOL: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CHECK );
+ item->set_text(1,TTR("On"));
+ item->set_tooltip(1, obj->get(p.name) ? "True" : "False");
+ item->set_checked( 1, obj->get( p.name ) );
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Bool","EditorIcons") );
+ item->set_editable(1,!read_only);
+
+ } break;
+ case Variant::REAL:
+ case Variant::INT: {
+
+ if (p.hint==PROPERTY_HINT_EXP_EASING) {
+
+ 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);
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Curve","EditorIcons"));
+
+ break;
+
+ }
+
+ if (p.hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || p.hint==PROPERTY_HINT_LAYERS_2D_RENDER || p.hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || p.hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable(1,!read_only);
+ item->set_custom_draw(1,this,"_draw_flags");
+ break;
+ }
+
+ if (p.hint==PROPERTY_HINT_FLAGS) {
+
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable(1,!read_only);
+ //item->set_icon( 0, get_icon("Curve","EditorIcons"));
+
+ Vector<String> values = p.hint_string.split(",");
+ String flags;
+ int val = obj->get(p.name);
+ for(int i=0;i<values.size();i++) {
+
+ String v = values[i];
+ if (v=="")
+ continue;
+ if (!(val&(1<<i)))
+ continue;
+
+ if (flags!="")
+ flags+=", ";
+ flags+=v;
+ }
+ item->set_text(1, flags );
+ break;
+
+ }
+
+ if (p.hint==PROPERTY_HINT_ENUM)
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
+ else
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE_EXPRESSION );
+
+
+ if (p.hint==PROPERTY_HINT_SPRITE_FRAME || p.hint==PROPERTY_HINT_RANGE || p.hint==PROPERTY_HINT_EXP_RANGE) {
+
+ int c = p.hint_string.get_slice_count(",");
+ float min=0,max=100,step=1;
+ if (c>=1) {
+
+ min=p.hint_string.get_slice(",",0).to_double();
+ }
+ if (c>=2) {
+
+ max=p.hint_string.get_slice(",",1).to_double();
+ }
+
+ if (p.hint!=PROPERTY_HINT_SPRITE_FRAME && c>=3) {
+
+ step= p.hint_string.get_slice(",",2).to_double();
+ }
+
+
+ item->set_range_config(1,min,max,step,p.hint==PROPERTY_HINT_EXP_RANGE);
+ } else if (p.hint==PROPERTY_HINT_ENUM) {
+
+ //int c = p.hint_string.get_slice_count(",");
+ item->set_text(1,p.hint_string);
+ 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;
+ } else if (p.hint==PROPERTY_HINT_OBJECT_ID) {
+
+ //int c = p.hint_string.get_slice_count(",");
+ item->set_cell_mode(1,TreeItem::CELL_MODE_CUSTOM);
+
+ String type=p.hint_string;
+ if (type=="")
+ type="Object";
+
+ ObjectID id = obj->get( p.name );
+ if (id!=0) {
+ item->set_text(1,type+" ID: "+itos(id));
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+ } else {
+ item->set_text(1,"[Empty]");
+ }
+
+ if (has_icon(p.hint_string,"EditorIcons")) {
+ type=p.hint_string;
+ } else {
+ type="Object";
+ }
+
+ item->set_icon(0,get_icon(type,"EditorIcons"));
+
+ break;
+
+ } else {
+ if (p.type == Variant::REAL) {
+
+ item->set_range_config(1, -16777216, 16777216, 0.001);
+ } else {
+
+ item->set_range_config(1, -2147483647, 2147483647, 1);
+ }
+ };
+
+ if (p.type==Variant::REAL) {
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Real","EditorIcons"));
+ item->set_range(1, obj->get( p.name ) );
+
+ } else {
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Integer","EditorIcons") );
+ item->set_range(1, obj->get( p.name ) );
+ }
+
+
+ item->set_editable(1,!read_only);
+
+
+ } break;
+ case Variant::STRING: {
+
+ switch (p.hint) {
+
+ case PROPERTY_HINT_DIR:
+ case PROPERTY_HINT_FILE:
+ case PROPERTY_HINT_GLOBAL_DIR:
+ case PROPERTY_HINT_GLOBAL_FILE: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_STRING );
+ item->set_editable(1,!read_only);
+ 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"));
+
+ } break;
+ case PROPERTY_HINT_ENUM: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
+ Vector<String> strings = p.hint_string.split(",");
+ String current = obj->get(p.name);
+ int idx=0;
+ for(int x=0;x<strings.size();x++) {
+ if (strings[x]==current) {
+ idx=x;
+ break;
+ }
+ }
+ item->set_text(1, p.hint_string);
+ item->set_range(1,idx);
+ item->set_editable( 1, !read_only );
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Enum","EditorIcons") );
+
+
+ } break;
+ case PROPERTY_HINT_METHOD_OF_VARIANT_TYPE: ///< a property of a type
+ case PROPERTY_HINT_METHOD_OF_BASE_TYPE: ///< a method of a base type
+ case PROPERTY_HINT_METHOD_OF_INSTANCE: ///< a method of an instance
+ case PROPERTY_HINT_METHOD_OF_SCRIPT: ///< a method of a script & base
+ case PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE: ///< a property of a type
+ case PROPERTY_HINT_PROPERTY_OF_BASE_TYPE: ///< a property of a base type
+ case PROPERTY_HINT_PROPERTY_OF_INSTANCE: ///< a property of an instance
+ case PROPERTY_HINT_PROPERTY_OF_SCRIPT: ///< a property of a script & base
+ case PROPERTY_HINT_TYPE_STRING: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM);
+ item->set_editable(1,!read_only);
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("String","EditorIcons") );
+ item->set_text(1,obj->get(p.name));
+
+ } break;
+
+ default: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_STRING );
+ item->set_editable(1,!read_only);
+ 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") );
+
+ } break;
+ }
+
+ } break;
+ case Variant::ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+
+ Variant v = obj->get(p.name);
+ String type_name = "Array";
+ String type_name_suffix = "";
+
+ String hint = p.hint_string;
+ while(hint.begins_with(itos(Variant::ARRAY)+":")) {
+ type_name += "<Array";
+ type_name_suffix += ">";
+ hint = hint.substr(2, hint.size()-2);
+ }
+ if(hint.find(":") >= 0) {
+ hint = hint.substr(0,hint.find(":"));
+ if(hint.find("/") >= 0) {
+ hint = hint.substr(0,hint.find("/"));
+ }
+ type_name += "<" + Variant::get_type_name(Variant::Type(hint.to_int()));
+ type_name_suffix += ">";
+ }
+ type_name += type_name_suffix;
+
+ if (v.is_array())
+ item->set_text(1,type_name+"["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,type_name+"[]");
+
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
+
+
+ } break;
+
+ case Variant::POOL_INT_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"IntArray["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"IntArray[]");
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayInt","EditorIcons") );
+
+
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"FloatArray["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"FloatArray[]");
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayReal","EditorIcons") );
+
+
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"String["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"String[]");
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayString","EditorIcons") );
+
+
+ } break;
+ case Variant::POOL_BYTE_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Byte["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Byte[]");
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
+
+
+ } break;
+ case Variant::POOL_VECTOR2_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Vector2["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Vector2[]");
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Vector2","EditorIcons") );
+
+
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Vector3["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Vector3[]");
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Vector","EditorIcons") );
+
+
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+
+ Variant v = obj->get(p.name);
+ if (v.is_array())
+ item->set_text(1,"Color["+itos(v.call("size"))+"]");
+ else
+ item->set_text(1,"Color[]");
+ if (show_type_icons)
+ item->set_icon( 0, get_icon("Color","EditorIcons") );
+
+
+ } break;
+ case Variant::VECTOR2: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1,obj->get(p.name));
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Vector2","EditorIcons") );
+
+ } break;
+ case Variant::RECT2: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1,obj->get(p.name));
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Rect2","EditorIcons") );
+
+ } break;
+ case Variant::VECTOR3: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1,obj->get(p.name));
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Vector","EditorIcons") );
+
+ } break;
+ case Variant::TRANSFORM2D:
+ case Variant::BASIS: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1, obj->get(p.name));
+ } break;
+ case Variant::TRANSFORM: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1,obj->get(p.name));
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Matrix","EditorIcons") );
+
+ } break;
+ case Variant::PLANE: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1,obj->get(p.name));
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Plane","EditorIcons") );
+
+ } break;
+ case Variant::RECT3: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1,"Rect3");
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Rect3","EditorIcons") );
+ } break;
+
+ case Variant::QUAT: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, true );
+ item->set_text(1,obj->get(p.name));
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Quat","EditorIcons") );
+
+ } break;
+ case Variant::COLOR: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, !read_only );
+ //item->set_text(1,obj->get(p.name));
+ item->set_custom_draw(1,this,"_draw_transparency");
+ if (show_type_icons)
+ item->set_icon( 0,get_icon("Color","EditorIcons") );
+
+ } break;
+ case Variant::IMAGE: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, !read_only );
+ Image img = obj->get( p.name );
+ if (img.empty())
+ item->set_text(1,"[Image (empty)]");
+ else
+ 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: {
+
+ item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
+ item->set_editable( 1, !read_only );
+ item->set_text(1,obj->get(p.name));
+ item->add_button(1, get_icon("CopyNodePath", "EditorIcons"));
+
+ } break;
+ case Variant::OBJECT: {
+
+ item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
+ item->set_editable( 1, !read_only );
+ item->add_button(1,get_icon("EditResource","EditorIcons"));
+ String type;
+ if (p.hint==PROPERTY_HINT_RESOURCE_TYPE)
+ type=p.hint_string;
+
+ if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) {
+ item->set_text(1,"<null>");
+ item->set_icon(1,Ref<Texture>());
+
+ } else {
+ RES res = obj->get( p.name ).operator RefPtr();
+
+ if (res->is_class("Texture")) {
+ int tw = EditorSettings::get_singleton()->get("docks/property_editor/texture_preview_width");
+ item->set_icon_max_width(1,tw);
+ item->set_icon(1,res);
+ item->set_text(1,"");
+
+ } else if (res->get_name() != "") {
+
+ item->set_text(1, res->get_name());
+ } else if (res->get_path()!="" && !res->get_path().begins_with("local://")) {
+ item->set_text(1, res->get_path().get_file());
+
+ } else {
+ item->set_text(1,"<"+res->get_class()+">");
+ }
+
+ if (has_icon(res->get_class(),"EditorIcons")) {
+ type=res->get_class();
+ }
+
+ if (res.is_valid() && res->get_path().is_resource_file()) {
+ item->set_tooltip(1,res->get_path());
+ } else if (res.is_valid()) {
+ item->set_tooltip(1,res->get_name()+" ("+res->get_class()+")");
+ }
+ if (!res->is_class("Texture")) {
+ //texture already previews via itself
+ EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res,this,"_resource_preview_done",item->get_instance_ID());
+ }
+
+ }
+
+
+ if (type!=String()) {
+ if (type.find(",")!=-1)
+ type=type.get_slice(",",0);
+ //printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data());
+ if (has_icon(type,"EditorIcons"))
+ item->set_icon( 0, get_icon(type,"EditorIcons") );
+ else
+ item->set_icon( 0, get_icon("Object","EditorIcons") );
+ }
+
+ //item->double_click_signal.connect( Method1<int>( Method2<int,String>( this, &Editoritem_obj_edited ), p.name ) );
+
+ } break;
+ default: {};
+ }
+
+ if (keying) {
+
+ if (p.hint==PROPERTY_HINT_SPRITE_FRAME) {
+
+ item->add_button(1,get_icon("KeyNext","EditorIcons"),5);
+ } else {
+ item->add_button(1,get_icon("Key","EditorIcons"),2);
+ }
+ }
+
+ bool has_reload=false;
+
+ bool mbi = _might_be_in_instance();
+ if (mbi) {
+
+ 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);
+
+
+ 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("ReloadSmall","EditorIcons"),3);
+ has_reload=true;
+ }
+ }
+
+ }
+
+ if (obj->call("property_can_revert",p.name).operator bool()) {
+
+ item->add_button(1,get_icon("ReloadSmall","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("ReloadSmall","EditorIcons"),3);
+ has_reload=true;
+ }
+ }
+ }
+
+ if (mbi && !has_reload && item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) {
+ item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true);
+ }
+
+
+
+ }
+}
+
+void PropertyEditor::_draw_transparency(Object *t, const Rect2& p_rect) {
+
+ TreeItem *ti=t->cast_to<TreeItem>();
+ if (!ti)
+ return;
+
+ Color color=obj->get(ti->get_metadata(1));
+ Ref<Texture> arrow=tree->get_icon("select_arrow");
+
+ // make a little space between consecutive color fields
+ Rect2 area=p_rect;
+ area.pos.y+=1;
+ area.size.height-=2;
+ area.size.width-=arrow->get_size().width+5;
+ tree->draw_texture_rect(get_icon("Transparent", "EditorIcons"), area, true);
+ tree->draw_rect(area, color);
+
+}
+
+
+void PropertyEditor::_item_selected() {
+
+
+ TreeItem *item = tree->get_selected();
+ ERR_FAIL_COND(!item);
+ selected_property=item->get_metadata(1);
+
+}
+
+
+void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value, bool p_refresh_all, const String& p_changed_field) {
+
+ if (autoclear) {
+ TreeItem *item = tree->get_selected();
+ if (item && item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK) {
+
+ item->set_checked(0,true);
+ }
+ }
+
+ if (!undo_redo|| obj->cast_to<ArrayPropertyEdit>()) { //kind of hacky
+
+ obj->set(p_name,p_value);
+ if (p_refresh_all)
+ _changed_callbacks(obj,"");
+ else
+ _changed_callbacks(obj,p_name);
+
+ emit_signal(_prop_edited,p_name);
+
+ } else if (obj->cast_to<MultiNodeEdit>()) {
+
+ obj->cast_to<MultiNodeEdit>()->set_property_field(p_name,p_value,p_changed_field);
+ _changed_callbacks(obj,p_name);
+ emit_signal(_prop_edited,p_name);
+ } else {
+
+ undo_redo->create_action(TTR("Set")+" "+p_name,UndoRedo::MERGE_ENDS);
+ undo_redo->add_do_property(obj,p_name,p_value);
+ undo_redo->add_undo_property(obj,p_name,obj->get(p_name));
+
+ if (p_refresh_all) {
+ undo_redo->add_do_method(this,"_changed_callback",obj,"");
+ undo_redo->add_undo_method(this,"_changed_callback",obj,"");
+ } else {
+
+ undo_redo->add_do_method(this,"_changed_callback",obj,p_name);
+ undo_redo->add_undo_method(this,"_changed_callback",obj,p_name);
+ }
+
+ Resource *r = obj->cast_to<Resource>();
+ if (r) {
+ if (!r->is_edited() && String(p_name)!="resource/edited") {
+ undo_redo->add_do_method(r,"set_edited",true);
+ undo_redo->add_undo_method(r,"set_edited",false);
+ }
+
+ if (String(p_name)=="resource_local_to_scene") {
+ bool prev = obj->get(p_name);
+ bool next = p_value;
+ if (next) {
+ undo_redo->add_do_method(this,"setup_local_to_scene");
+ }
+ if (prev) {
+ undo_redo->add_undo_method(this,"setup_local_to_scene");
+ }
+ }
+ }
+ undo_redo->add_do_method(this,"emit_signal",_prop_edited,p_name);
+ undo_redo->add_undo_method(this,"emit_signal",_prop_edited,p_name);
+ undo_redo->commit_action();
+ }
+}
+
+
+void PropertyEditor::_item_edited() {
+
+
+ TreeItem * item = tree->get_edited();
+ if (!item)
+ return; //it all happened too fast..
+
+ Dictionary d = item->get_metadata(0);
+
+ String name=d["name"];
+
+ if (tree->get_edited_column()==0) {
+ //property checked
+ if (autoclear) {
+ if (!item->is_checked(0)) {
+ obj->set(name,Variant());
+ update_property(name);
+ } else {
+ Variant::CallError ce;
+ obj->set(name,Variant::construct(Variant::Type(int(d["type"])),NULL,0,ce));
+ }
+ } else {
+ emit_signal("property_toggled",name,item->is_checked(0));
+ }
+ return;
+ }
+
+ if (autoclear && item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK && item->get_cell_mode(1)!=TreeItem::CELL_MODE_CUSTOM) {
+ item->set_checked(0,true);
+
+ }
+
+
+ int type=d["type"];
+ int hint= d["hint"];
+ int usage = d["usage"];
+ bool refresh_all = usage&PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED;
+
+ String hint_text=d["hint_text"];
+ switch(type) {
+
+ case Variant::NIL: {
+
+ } break;
+ case Variant::BOOL: {
+
+ _edit_set(name,item->is_checked(1),refresh_all);
+ item->set_tooltip(1, item->is_checked(1) ? "True" : "False");
+ } break;
+ case Variant::INT:
+ case Variant::REAL: {
+
+ if (hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || hint==PROPERTY_HINT_LAYERS_2D_RENDER || hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || hint==PROPERTY_HINT_LAYERS_3D_RENDER)
+ break;
+ if (hint==PROPERTY_HINT_EXP_EASING)
+ break;
+ if (hint==PROPERTY_HINT_FLAGS)
+ break;
+
+ if (type==Variant::INT)
+ _edit_set(name,int(item->get_range(1)),refresh_all);
+ else
+ _edit_set(name,item->get_range(1),refresh_all);
+ } break;
+ case Variant::STRING: {
+
+ if (hint==PROPERTY_HINT_ENUM) {
+
+ int idx= item->get_range(1);
+
+ Vector<String> strings = hint_text.split(",");
+ String txt;
+ if (idx>=0 && idx<strings.size()) {
+
+ txt=strings[idx];
+ }
+
+ _edit_set(name,txt,refresh_all);
+ } else {
+ _edit_set(name,item->get_text(1),refresh_all);
+ }
+ } break;
+ // math types
+
+ case Variant::VECTOR3: {
+
+ } break;
+ case Variant::PLANE: {
+
+ } break;
+ case Variant::QUAT: {
+
+ } break;
+ case Variant::RECT3: {
+
+ } break;
+ case Variant::BASIS: {
+
+ } break;
+ case Variant::TRANSFORM: {
+
+ } break;
+
+ case Variant::COLOR: {
+ //_edit_set(name,item->get_custom_bg_color(0));
+ } break;
+ case Variant::IMAGE: {
+
+ } break;
+ case Variant::NODE_PATH: {
+ _edit_set(name, NodePath(item->get_text(1)),refresh_all);
+
+ } break;
+
+ case Variant::INPUT_EVENT: {
+
+ } break;
+ case Variant::DICTIONARY: {
+
+ } break;
+
+ // arrays
+ case Variant::POOL_BYTE_ARRAY: {
+
+ } break;
+ case Variant::POOL_INT_ARRAY: {
+
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+
+ } break;
+
+
+ };
+}
+
+
+void PropertyEditor::_resource_edit_request() {
+
+ RES res=custom_editor->get_variant();
+ if (res.is_null())
+ return;
+
+ String name=custom_editor->get_name();
+
+
+ emit_signal("resource_selected",res.get_ref_ptr(),name);
+}
+
+void PropertyEditor::_custom_editor_edited() {
+
+
+ if (!obj)
+ return;
+
+ _edit_set(custom_editor->get_name(), custom_editor->get_variant());
+}
+
+void PropertyEditor::_custom_editor_edited_field(const String& p_field_name) {
+
+ ERR_FAIL_COND(p_field_name=="");
+
+ if (!obj)
+ return;
+
+ _edit_set(custom_editor->get_name(), custom_editor->get_variant(), false, p_field_name);
+}
+
+void PropertyEditor::_custom_editor_request(bool p_arrow) {
+
+ TreeItem * item = tree->get_edited();
+ ERR_FAIL_COND(!item);
+ Dictionary d = item->get_metadata(0);
+
+ //int type=d["type"];
+ String name=d["name"];
+ Variant::Type type=Variant::NIL;
+ if (d.has("type"))
+ type=(Variant::Type)((int)(d["type"]));
+
+ Variant v=obj->get(name);
+ int hint=d.has("hint")?d["hint"].operator int():-1;
+ String hint_text=d.has("hint_text")?d["hint_text"]:"";
+ Rect2 where=tree->get_custom_popup_rect();
+ custom_editor->set_pos(where.pos);
+
+ if (custom_editor->edit(obj,name,type,v,hint,hint_text)) {
+ custom_editor->popup();
+ }
+}
+
+void PropertyEditor::edit(Object* p_object) {
+
+
+ if (obj==p_object)
+ return;
+ if (obj) {
+
+ obj->remove_change_receptor(this);
+ }
+
+ obj=p_object;
+
+ evaluator->edit(p_object);
+
+ update_tree();
+
+ if (obj) {
+
+ obj->add_change_receptor(this);
+ }
+
+
+}
+
+void PropertyEditor::_set_range_def(Object *p_item, String prop,float p_frame) {
+
+ TreeItem *ti = p_item->cast_to<TreeItem>();
+ ERR_FAIL_COND(!ti);
+
+ ti->call_deferred("set_range",1, p_frame);
+ obj->call_deferred("set",prop,p_frame);
+
+}
+
+void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
+ TreeItem *ti = p_item->cast_to<TreeItem>();
+ ERR_FAIL_COND(!ti);
+
+ Dictionary d = ti->get_metadata(0);
+
+ if (p_button==2) {
+
+ if (!d.has("name"))
+ return;
+ String prop=d["name"];
+ emit_signal("property_keyed",prop,obj->get(prop),false);
+ } else if (p_button==5) {
+ print_line("PB5");
+ if (!d.has("name"))
+ return;
+ String prop=d["name"];
+ emit_signal("property_keyed",prop,obj->get(prop),true);
+ //set_range(p_column, ti->get_range(p_column)+1.0 );
+ call_deferred("_set_range_def",ti,prop,ti->get_range(p_column)+1.0);
+ } else if (p_button==3) {
+
+ if (!d.has("name"))
+ return;
+
+ String prop=d["name"];
+
+ Variant vorig;
+
+ if (_might_be_in_instance() && _get_instanced_node_original_property(prop,vorig)) {
+
+ _edit_set(prop,vorig);
+ return;
+ }
+
+ if (obj->call("property_can_revert",prop).operator bool()) {
+ Variant rev = obj->call("property_get_revert",prop);
+ _edit_set(prop,rev);
+ }
+
+ 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);
+ if (!d.has("type"))
+ return;
+ if (!d.has("hint"))
+ return;
+ if (!d.has("name"))
+ return;
+ if (!d.has("hint_text"))
+ return;
+
+ int t = d["type"];
+ int h = d["hint"];
+ String n = d["name"];
+ String ht = d["hint_text"];
+
+ if(t == Variant::NODE_PATH) {
+
+ Variant v = obj->get(n);
+ custom_editor->edit(obj, n, (Variant::Type)t, v, h, ht);
+ Rect2 where = tree->get_item_rect(ti, 1);
+ where.pos -= tree->get_scroll();
+ where.pos += tree->get_global_pos();
+ custom_editor->set_pos(where.pos);
+ custom_editor->popup();
+
+ } else if (t==Variant::STRING) {
+
+
+ Variant v = obj->get(n);
+ custom_editor->edit(obj,n,(Variant::Type)t,v,h,ht);
+ //Rect2 where=tree->get_custom_popup_rect();
+ if (h==PROPERTY_HINT_FILE || h==PROPERTY_HINT_DIR || h==PROPERTY_HINT_GLOBAL_DIR || h==PROPERTY_HINT_GLOBAL_FILE) {
+
+ Rect2 where=tree->get_item_rect(ti,1);
+ where.pos-=tree->get_scroll();
+ where.pos+=tree->get_global_pos();
+ custom_editor->set_pos(where.pos);
+ custom_editor->popup();
+ } else {
+ custom_editor->popup_centered_ratio();
+ }
+
+ } else if (t==Variant::OBJECT) {
+
+ RES r = obj->get(n);
+ if (r.is_valid()) {
+
+ emit_signal("resource_selected",r,n);
+ }
+ } else if (t==Variant::INT && h==PROPERTY_HINT_OBJECT_ID) {
+
+ emit_signal("object_id_selected",obj->get(n));
+ print_line("OBJ ID SELECTED");
+
+ } else if (t==Variant::ARRAY || t==Variant::POOL_INT_ARRAY || t==Variant::POOL_REAL_ARRAY || t==Variant::POOL_STRING_ARRAY || t==Variant::POOL_VECTOR2_ARRAY || t==Variant::POOL_VECTOR3_ARRAY || t==Variant::POOL_COLOR_ARRAY || t==Variant::POOL_BYTE_ARRAY) {
+
+ Variant v = obj->get(n);
+
+ if (v.get_type()!=t) {
+ Variant::CallError ce;
+ v=Variant::construct(Variant::Type(t),NULL,0,ce);
+ }
+
+ Ref<ArrayPropertyEdit> ape = memnew( ArrayPropertyEdit );
+ ape->edit(obj,n,ht,Variant::Type(t));
+
+ EditorNode::get_singleton()->push_item(ape.ptr());
+ }
+ }
+}
+
+
+void PropertyEditor::_node_removed(Node *p_node) {
+
+ if (p_node==obj) {
+
+ edit(NULL);
+ }
+}
+
+
+void PropertyEditor::set_keying(bool p_active) {
+
+ if (keying==p_active)
+ return;
+
+ keying=p_active;
+ update_tree();
+}
+
+void PropertyEditor::_draw_flags(Object *t,const Rect2& p_rect) {
+
+ TreeItem *ti = t->cast_to<TreeItem>();
+ if (!ti)
+ return;
+
+ Dictionary d = ti->get_metadata(0);
+
+ if (!d.has("name"))
+ return;
+
+ uint32_t f = obj->get(d["name"]);
+
+ int bsize = (p_rect.size.height*80/100)/2;
+
+ int h = bsize*2+1;
+ int vofs = (p_rect.size.height-h)/2;
+
+ for(int i=0;i<2;i++) {
+
+ Point2 ofs(4,vofs);
+ if (i==1)
+ ofs.y+=bsize+1;
+
+ ofs+=p_rect.pos;
+ for(int j=0;j<10;j++) {
+
+ Point2 o = ofs+Point2(j*(bsize+1),0);
+ if (j>=5)
+ o.x+=1;
+
+ uint32_t idx=i*10+j;
+ bool on=f&(1<<idx);
+ tree->draw_rect(Rect2(o,Size2(bsize,bsize)),Color(0,0,0,on?0.8:0.3));
+ }
+ }
+
+
+}
+
+void PropertyEditor::_filter_changed(const String& p_text) {
+
+ update_tree();
+}
+
+
+
+void PropertyEditor::_resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud) {
+
+ if (p_preview.is_null())
+ return; //don't bother with empty preview
+
+ ObjectID id = p_ud;
+ Object *obj = ObjectDB::get_instance(id);
+
+ if (!obj)
+ return;
+
+ TreeItem *ti = obj->cast_to<TreeItem>();
+
+ ERR_FAIL_COND(!ti);
+
+ int tw = EditorSettings::get_singleton()->get("docks/property_editor/texture_preview_width");
+
+ ti->set_icon(1,p_preview); //should be scaled I think?
+ ti->set_icon_max_width(1,tw);
+ ti->set_text(1,"");
+}
+void PropertyEditor::_bind_methods() {
+
+ ClassDB::bind_method( "_item_edited",&PropertyEditor::_item_edited);
+ ClassDB::bind_method( "_item_selected",&PropertyEditor::_item_selected);
+ ClassDB::bind_method( "_custom_editor_request",&PropertyEditor::_custom_editor_request);
+ ClassDB::bind_method( "_custom_editor_edited",&PropertyEditor::_custom_editor_edited);
+ ClassDB::bind_method( "_custom_editor_edited_field",&PropertyEditor::_custom_editor_edited_field,DEFVAL(""));
+ ClassDB::bind_method( "_resource_edit_request",&PropertyEditor::_resource_edit_request);
+ ClassDB::bind_method( "_node_removed",&PropertyEditor::_node_removed);
+ ClassDB::bind_method( "_edit_button",&PropertyEditor::_edit_button);
+ ClassDB::bind_method( "_changed_callback",&PropertyEditor::_changed_callbacks);
+ ClassDB::bind_method( "_draw_flags",&PropertyEditor::_draw_flags);
+ ClassDB::bind_method( "_set_range_def",&PropertyEditor::_set_range_def);
+ ClassDB::bind_method( "_filter_changed",&PropertyEditor::_filter_changed);
+ ClassDB::bind_method( "update_tree",&PropertyEditor::update_tree);
+ ClassDB::bind_method( "_resource_preview_done",&PropertyEditor::_resource_preview_done);
+ ClassDB::bind_method( "refresh",&PropertyEditor::refresh);
+ ClassDB::bind_method( "_draw_transparency",&PropertyEditor::_draw_transparency);
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &PropertyEditor::drop_data_fw);
+
+ 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") ) );
+ ADD_SIGNAL( MethodInfo("object_id_selected", PropertyInfo( Variant::INT, "id")) );
+ ADD_SIGNAL( MethodInfo("property_keyed",PropertyInfo( Variant::STRING, "property")));
+ ADD_SIGNAL( MethodInfo("property_edited",PropertyInfo( Variant::STRING, "property")));
+}
+
+Tree *PropertyEditor::get_scene_tree() {
+
+ return tree;
+}
+
+Label* PropertyEditor::get_top_label() {
+
+ return top_label;
+}
+
+void PropertyEditor::hide_top_label() {
+
+ top_label->hide();
+ tree->set_begin( Point2(0,0 ));
+}
+
+String PropertyEditor::get_selected_path() const {
+
+
+ TreeItem *ti = tree->get_selected();
+ if (!ti)
+ return "";
+
+ Dictionary d = ti->get_metadata(0);
+
+ if (d.has("name"))
+ return d["name"];
+ else
+ return "";
+}
+
+void PropertyEditor::set_capitalize_paths(bool p_capitalize) {
+
+ capitalize_paths=p_capitalize;
+}
+
+void PropertyEditor::set_autoclear(bool p_enable) {
+
+ autoclear=p_enable;
+}
+
+void PropertyEditor::set_show_categories(bool p_show) {
+
+ show_categories=p_show;
+ update_tree();
+}
+
+void PropertyEditor::set_use_filter(bool p_use) {
+
+ if (p_use==use_filter)
+ return;
+
+ use_filter=p_use;
+ update_tree();
+}
+
+void PropertyEditor::register_text_enter(Node* p_line_edit) {
+
+ ERR_FAIL_NULL(p_line_edit);
+ search_box=p_line_edit->cast_to<LineEdit>();
+
+ 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() {
+
+ _prop_edited="property_edited";
+
+ hide_script=false;
+
+ undo_redo=NULL;
+ obj=NULL;
+ search_box=NULL;
+ changing=false;
+ update_tree_pending=false;
+
+ top_label = memnew( Label );
+ top_label->set_text(TTR("Properties:"));
+ top_label->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ top_label->set_begin( Point2( 10,0) );
+ top_label->set_end( Point2( 0,12) );
+
+ add_child(top_label);
+
+
+ tree = memnew( Tree );
+ tree->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ tree->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
+ tree->set_begin( Point2(0,19 ));
+ tree->set_end( Point2(0,0 ));
+
+ tree->set_columns(2);
+ tree->set_column_expand(0,true);
+ tree->set_column_min_width(0,30);
+ tree->set_column_expand(1,true);
+ tree->set_column_min_width(1,18);
+
+ //tree->set_hide_root(true);
+ add_child( tree );
+
+ tree->connect("item_edited", this,"_item_edited",varray(),CONNECT_DEFERRED);
+ tree->connect("cell_selected", this,"_item_selected");
+
+ tree->set_drag_forwarding(this);
+
+ set_fixed_process(true);
+
+ custom_editor = memnew( CustomPropertyEditor );
+ add_child(custom_editor);
+
+ tree->connect("custom_popup_edited", this,"_custom_editor_request");
+ tree->connect("button_pressed", this,"_edit_button");
+ custom_editor->connect("variant_changed", this,"_custom_editor_edited");
+ custom_editor->connect("variant_field_changed", this,"_custom_editor_edited_field");
+ custom_editor->connect("resource_edit_request", this,"_resource_edit_request",make_binds(),CONNECT_DEFERRED);
+ tree->set_hide_folding(true);
+
+ evaluator = memnew (PropertyValueEvaluator);
+ tree->set_value_evaluator(evaluator);
+ custom_editor->set_value_evaluator(evaluator);
+
+ capitalize_paths=true;
+ autoclear=false;
+ tree->set_column_titles_visible(false);
+
+ keying=false;
+ read_only=false;
+ show_categories=false;
+ refresh_countdown=0;
+ use_doc_hints=false;
+ use_filter=false;
+ subsection_selectable=false;
+ show_type_icons=EDITOR_DEF("interface/show_type_icons",false);
+
+}
+
+
+PropertyEditor::~PropertyEditor()
+{
+ memdelete(evaluator);
+}
+
+
+/////////////////////////////
+
+
+
+
+
+class SectionedPropertyEditorFilter : public Object {
+
+ GDCLASS( SectionedPropertyEditorFilter, Object );
+
+ Object *edited;
+ String section;
+ bool allow_sub;
+
+ 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);
+ //_change_notify(p_name.operator String().utf8().get_data());
+ 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 (pi.name=="resource_path" || pi.name=="resource_name" || pi.name.begins_with("script/")) //skip resource stuff
+ continue;
+
+ if (sp==-1) {
+ pi.name="Global/"+pi.name;
+
+ }
+
+ if (pi.name.begins_with(section+"/")) {
+ pi.name=pi.name.replace_first(section+"/","");
+ if (!allow_sub && pi.name.find("/")!=-1)
+ continue;
+ p_list->push_back(pi);
+ }
+ }
+
+ }
+
+ bool property_can_revert(const String& p_name) {
+
+ return edited->call("property_can_revert",section+"/"+p_name);
+ }
+
+ Variant property_get_revert(const String& p_name) {
+
+ return edited->call("property_get_revert",section+"/"+p_name);
+ }
+
+protected:
+ static void _bind_methods() {
+
+ ClassDB::bind_method("property_can_revert",&SectionedPropertyEditorFilter::property_can_revert);
+ ClassDB::bind_method("property_get_revert",&SectionedPropertyEditorFilter::property_get_revert);
+ }
+
+public:
+
+ void set_section(const String& p_section,bool p_allow_sub) {
+
+ section=p_section;
+ allow_sub=p_allow_sub;
+ _change_notify();
+ }
+
+ void set_edited(Object* p_edited) {
+ edited=p_edited;
+ _change_notify();
+ }
+
+ SectionedPropertyEditorFilter() {
+ edited=NULL;
+ }
+
+};
+
+
+void SectionedPropertyEditor::_bind_methods() {
+
+ ClassDB::bind_method("_section_selected",&SectionedPropertyEditor::_section_selected);
+
+ ClassDB::bind_method("update_category_list", &SectionedPropertyEditor::update_category_list);
+}
+
+void SectionedPropertyEditor::_section_selected() {
+
+ if (!sections->get_selected())
+ return;
+
+ filter->set_section( sections->get_selected()->get_metadata(0), sections->get_selected()->get_children()==NULL);
+}
+
+void SectionedPropertyEditor::set_current_section(const String& p_section) {
+
+ if (section_map.has(p_section)) {
+ section_map[p_section]->select(0);
+ }
+}
+
+String SectionedPropertyEditor::get_current_section() const {
+
+ if (sections->get_selected())
+ return sections->get_selected()->get_metadata(0);
+ else
+ return "";
+}
+
+String SectionedPropertyEditor::get_full_item_path(const String& p_item) {
+
+ String base = get_current_section();
+
+ if (base!="")
+ return base+"/"+p_item;
+ else
+ return p_item;
+}
+
+void SectionedPropertyEditor::edit(Object* p_object) {
+
+ if (!p_object) {
+ obj = -1;
+ sections->clear();
+
+ filter->set_edited(NULL);
+ editor->edit(NULL);
+
+ return;
+ }
+
+ ObjectID id = p_object->get_instance_ID();
+
+ if (obj != id) {
+
+ obj = id;
+ update_category_list();
+
+ filter->set_edited(p_object);
+ editor->edit(filter);
+
+ if (sections->get_root()->get_children()) {
+ sections->get_root()->get_children()->select(0);
+ }
+ } else {
+
+ update_category_list();
+ }
+}
+
+void SectionedPropertyEditor::update_category_list() {
+
+ String selected_category=get_current_section();
+ sections->clear();
+
+ Object *o = ObjectDB::get_instance(obj);
+
+ if (!o)
+ return;
+
+ List<PropertyInfo> pinfo;
+ o->get_property_list(&pinfo);
+
+ section_map.clear();
+
+ TreeItem *root = sections->create_item();
+ section_map[""]=root;
+
+
+ for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+
+ PropertyInfo pi=E->get();
+
+ if (pi.usage&PROPERTY_USAGE_CATEGORY)
+ continue;
+ else if ( !(pi.usage&PROPERTY_USAGE_EDITOR) )
+ continue;
+
+ if (pi.name.find(":")!=-1 || pi.name=="script" || pi.name=="resource_name" || pi.name=="resource_path")
+ continue;
+ int sp = pi.name.find("/");
+ if (sp==-1)
+ pi.name="Global/"+pi.name;
+
+ Vector<String> sectionarr = pi.name.split("/");
+ String metasection;
+
+
+ for(int i=0;i<MIN(2,sectionarr.size()-1);i++) {
+
+ TreeItem *parent = section_map[metasection];
+
+ if (i>0) {
+ metasection+="/"+sectionarr[i];
+ } else {
+ metasection=sectionarr[i];
+ }
+
+
+ if (!section_map.has(metasection)) {
+ TreeItem *ms = sections->create_item(parent);
+ section_map[metasection]=ms;
+ ms->set_text(0,sectionarr[i].capitalize());
+ ms->set_metadata(0,metasection);
+
+ }
+ }
+
+ }
+
+ if (section_map.has(selected_category)) {
+ section_map[selected_category]->select(0);
+ }
+}
+
+PropertyEditor *SectionedPropertyEditor::get_property_editor() {
+
+ return editor;
+}
+
+SectionedPropertyEditor::SectionedPropertyEditor() {
+
+ obj = -1;
+
+ VBoxContainer *left_vb = memnew( VBoxContainer);
+ left_vb->set_custom_minimum_size(Size2(160,0)*EDSCALE);
+ add_child(left_vb);
+
+ sections = memnew( Tree );
+ sections->set_v_size_flags(SIZE_EXPAND_FILL);
+ sections->set_hide_root(true);
+
+ left_vb->add_margin_child(TTR("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(TTR("Properties:"),editor,true);
+
+ editor->get_scene_tree()->set_column_titles_visible(false);
+
+
+ editor->hide_top_label();
+
+ sections->connect("cell_selected",this,"_section_selected");
+
+}
+
+SectionedPropertyEditor::~SectionedPropertyEditor() {
+
+ memdelete(filter);
+}
+
+double PropertyValueEvaluator::eval(const String& p_text) {
+
+ if (!obj || !script_language)
+ return _default_eval(p_text);
+
+ Ref<Script> script= Ref<Script>(script_language ->create_script());
+ script->set_source_code(_build_script(p_text));
+ Error err = script->reload();
+ if (err) {
+ print_line("[PropertyValueEvaluator] Error loading script for expression: " + p_text);
+ return _default_eval(p_text);
+ }
+
+ ScriptInstance *script_instance = script->instance_create(this);
+ if (!script_instance)
+ return _default_eval(p_text);
+
+ Variant::CallError call_err;
+ script_instance->call("set_this",obj);
+ double result = script_instance->call("e", NULL, 0, call_err );
+ if (call_err.error == Variant::CallError::CALL_OK) {
+ return result;
+ }
+ print_line("[PropertyValueEvaluator]: Error eval! Error code: " + itos(call_err.error));
+
+ memdelete(script_instance);
+
+ return _default_eval(p_text);
+}
+
+
+void PropertyValueEvaluator::edit(Object *p_obj) {
+ obj = p_obj;
+}
+
+String PropertyValueEvaluator::_build_script(const String& p_text) {
+ String script_text = "tool\nvar this\nfunc set_this(p_this):\n\tthis=p_this\nfunc e():\n\treturn ";
+ script_text += p_text.strip_edges();
+ script_text += "\n";
+ return script_text;
+}
+
+PropertyValueEvaluator::PropertyValueEvaluator() {
+ script_language=NULL;
+
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+ if (ScriptServer::get_language(i)->get_name()=="GDScript") {
+ script_language=ScriptServer::get_language(i);
+ }
+ }
+}
+
+PropertyValueEvaluator::~PropertyValueEvaluator() {
+
+}
diff --git a/editor/property_editor.h b/editor/property_editor.h
new file mode 100644
index 0000000000..c9ae9a85cc
--- /dev/null
+++ b/editor/property_editor.h
@@ -0,0 +1,352 @@
+/*************************************************************************/
+/* property_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PROPERTY_EDITOR_H
+#define PROPERTY_EDITOR_H
+
+#include "scene/gui/tree.h"
+#include "scene/gui/button.h"
+#include "scene/gui/check_box.h"
+#include "scene/gui/label.h"
+#include "editor/editor_file_dialog.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/color_picker.h"
+#include "scene/gui/menu_button.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/gui/text_edit.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/grid_container.h"
+#include "scene_tree_editor.h"
+
+/**
+ @author Juan Linietsky <reduzio@gmail.com>
+*/
+
+class PropertyValueEvaluator;
+class CreateDialog;
+class PropertySelector;
+
+class CustomPropertyEditor : public Popup {
+
+ GDCLASS( CustomPropertyEditor, Popup );
+
+ enum {
+ MAX_VALUE_EDITORS=12,
+ MAX_ACTION_BUTTONS=5,
+ OBJ_MENU_LOAD=0,
+ OBJ_MENU_EDIT=1,
+ OBJ_MENU_CLEAR=2,
+ OBJ_MENU_MAKE_UNIQUE=3,
+ OBJ_MENU_COPY=4,
+ OBJ_MENU_PASTE=5,
+ OBJ_MENU_REIMPORT=6,
+ OBJ_MENU_NEW_SCRIPT=7,
+ OBJ_MENU_SHOW_IN_FILE_SYSTEM=8,
+ TYPE_BASE_ID=100
+ };
+
+ enum {
+ EASING_LINEAR,
+ EASING_EASE_IN,
+ EASING_EASE_OUT,
+ EASING_ZERO,
+ EASING_IN_OUT,
+ EASING_OUT_IN
+ };
+
+
+ PopupMenu *menu;
+ SceneTreeDialog *scene_tree;
+ EditorFileDialog *file;
+ ConfirmationDialog *error;
+ String name;
+ Variant::Type type;
+ Variant v;
+ List<String> field_names;
+ int hint;
+ String hint_text;
+ LineEdit *value_editor[MAX_VALUE_EDITORS];
+ int focused_value_editor;
+ Label *value_label[MAX_VALUE_EDITORS];
+ HScrollBar *scroll[4];
+ Button *action_buttons[MAX_ACTION_BUTTONS];
+ MenuButton *type_button;
+ Vector<String> inheritors_array;
+ TextureRect *texture_preview;
+ ColorPicker *color_picker;
+ TextEdit *text_edit;
+ bool read_only;
+ bool picking_viewport;
+ GridContainer *checks20gc;
+ CheckBox *checks20[20];
+ SpinBox *spinbox;
+ HSlider *slider;
+
+
+ Control *easing_draw;
+ CreateDialog *create_dialog;
+ PropertySelector *property_select;
+
+ Object* owner;
+
+ bool updating;
+
+ PropertyValueEvaluator *evaluator;
+
+ void _text_edit_changed();
+ void _file_selected(String p_file);
+ void _scroll_modified(double p_value);
+ void _modified(String p_string);
+ void _range_modified(double p_value);
+ void _focus_enter();
+ void _focus_exit();
+ void _action_pressed(int p_which);
+ void _type_create_selected(int p_idx);
+ void _create_dialog_callback();
+ void _create_selected_property(const String &p_prop);
+
+
+ void _color_changed(const Color& p_color);
+ void _draw_easing();
+ void _menu_option(int p_which);
+
+ void _drag_easing(const InputEvent& p_ev);
+
+ void _node_path_selected(NodePath p_path);
+ void show_value_editors(int p_amount);
+ void config_value_editors(int p_amount, int p_columns,int p_label_w,const List<String>& p_strings);
+ void config_action_buttons(const List<String>& p_strings);
+
+ void _emit_changed_whole_or_field();
+
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+
+
+ void hide_menu();
+
+ Variant get_variant() const;
+ String get_name() const;
+
+ void set_read_only(bool p_read_only) { read_only=p_read_only; }
+
+ void set_value_evaluator( PropertyValueEvaluator *p_evaluator) { evaluator=p_evaluator; }
+
+ bool edit(Object* p_owner,const String& p_name,Variant::Type p_type, const Variant& p_variant,int p_hint,String p_hint_text);
+
+ CustomPropertyEditor();
+};
+
+class PropertyEditor : public Control {
+
+ GDCLASS( PropertyEditor, Control );
+
+ Tree *tree;
+ Label *top_label;
+ //Object *object;
+ LineEdit *search_box;
+
+ PropertyValueEvaluator *evaluator;
+
+ Object* obj;
+
+
+ StringName _prop_edited;
+
+ bool capitalize_paths;
+ bool changing;
+ bool update_tree_pending;
+ bool autoclear;
+ 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;
+ bool hide_script;
+
+ HashMap<String,String> pending;
+ String selected_property;
+
+ Map<StringName,Map<StringName,String> > descr_cache;
+ Map<StringName,String > class_descr_cache;
+
+ CustomPropertyEditor *custom_editor;
+
+ void _resource_edit_request();
+ void _custom_editor_edited();
+ void _custom_editor_edited_field(const String& p_field_name);
+ void _custom_editor_request(bool p_arrow);
+
+ void _item_selected();
+ void _item_edited();
+ TreeItem *get_parent_node(String p_path,HashMap<String,TreeItem*>& item_paths,TreeItem *root);
+
+ void set_item_text(TreeItem *p_item, int p_type, const String& p_name, int p_hint=PROPERTY_HINT_NONE, const String& p_hint_text="");
+
+ TreeItem *find_item(TreeItem *p_item,const String& p_name);
+
+
+ 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);
+
+ void _node_removed(Node *p_node);
+
+friend class ProjectExportDialog;
+ void _edit_set(const String& p_name, const Variant& p_value,bool p_refresh_all=false, const String& p_changed_field="");
+ void _draw_flags(Object *ti,const Rect2& p_rect);
+
+ bool _might_be_in_instance();
+ bool _get_instanced_node_original_property(const StringName& p_prop,Variant& value);
+ bool _is_property_different(const Variant& p_current, const Variant& p_orig,int p_usage=0);
+
+ void _refresh_item(TreeItem *p_item);
+ void _set_range_def(Object *p_item, String prop, float p_frame);
+
+ void _filter_changed(const String& p_text);
+
+ void _mark_drop_fields(TreeItem* p_at);
+ void _clear_drop_fields(TreeItem* p_at);
+
+ bool _is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const;
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+ void _resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud);
+ void _draw_transparency(Object *t, const Rect2& p_rect);
+
+ UndoRedo *undo_redo;
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
+
+ String get_selected_path() const;
+
+ Tree *get_scene_tree();
+ Label* get_top_label();
+ void hide_top_label();
+ void update_tree();
+ void update_property(const String& p_prop);
+
+ void refresh();
+
+ void edit(Object* p_object);
+
+ void set_keying(bool p_active);
+ void set_read_only(bool p_read_only) { read_only=p_read_only; custom_editor->set_read_only(p_read_only);}
+
+ void set_capitalize_paths(bool p_capitalize);
+ void set_autoclear(bool p_enable);
+
+ void set_show_categories(bool p_show);
+ void set_use_doc_hints(bool p_enable) { use_doc_hints=p_enable; }
+ void set_hide_script(bool p_hide) { hide_script=p_hide; }
+
+ 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 {
+
+
+ GDCLASS(SectionedPropertyEditor,HBoxContainer);
+
+ ObjectID obj;
+
+ Tree *sections;
+ SectionedPropertyEditorFilter *filter;
+
+ Map<String,TreeItem*> section_map;
+ PropertyEditor *editor;
+
+
+ static void _bind_methods();
+ void _section_selected();
+
+public:
+
+ PropertyEditor *get_property_editor();
+ void edit(Object* p_object);
+ String get_full_item_path(const String& p_item);
+
+ void set_current_section(const String& p_section);
+ String get_current_section() const;
+
+ void update_category_list();
+
+ SectionedPropertyEditor();
+ ~SectionedPropertyEditor();
+};
+
+class PropertyValueEvaluator : public ValueEvaluator {
+ GDCLASS( PropertyValueEvaluator, ValueEvaluator );
+
+ Object *obj;
+ ScriptLanguage *script_language;
+ String _build_script(const String& p_text);
+
+ _FORCE_INLINE_ double _default_eval(const String& p_text) {
+ return p_text.to_double();
+ }
+
+public:
+
+ void edit(Object *p_obj);
+ double eval(const String& p_text);
+
+ PropertyValueEvaluator();
+ ~PropertyValueEvaluator();
+};
+
+#endif
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
new file mode 100644
index 0000000000..71ffae4729
--- /dev/null
+++ b/editor/property_selector.cpp
@@ -0,0 +1,626 @@
+/*************************************************************************/
+/* property_selector.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "property_selector.h"
+
+#include "editor_scale.h"
+#include "os/keyboard.h"
+
+void PropertySelector::_text_changed(const String& p_newtext) {
+
+ _update_search();
+}
+
+void PropertySelector::_sbox_input(const InputEvent& p_ie) {
+
+ if (p_ie.type==InputEvent::KEY) {
+
+ switch(p_ie.key.scancode) {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN: {
+
+ search_options->call("_gui_input", 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;
+ }
+ }
+}
+
+
+void PropertySelector::_update_search() {
+
+
+ if (properties)
+ set_title(TTR("Select Property"));
+ else
+ set_title(TTR("Select Method"));
+
+ search_options->clear();
+ help_bit->set_text("");
+
+
+ TreeItem *root = search_options->create_item();
+
+
+ if (properties) {
+
+ List<PropertyInfo> props;
+
+ if (instance) {
+ instance->get_property_list(&props,true);
+ } else if (type!=Variant::NIL) {
+ Variant v;
+ if (type==Variant::INPUT_EVENT) {
+ InputEvent ie;
+ ie.type=event_type;
+ v=ie;
+ } else {
+ Variant::CallError ce;
+ v=Variant::construct(type,NULL,0,ce);
+ }
+
+ v.get_property_list(&props);
+ } else {
+
+
+ Object *obj = ObjectDB::get_instance(script);
+ if (obj && obj->cast_to<Script>()) {
+
+ props.push_back(PropertyInfo(Variant::NIL,"Script Variables",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_CATEGORY));
+ obj->cast_to<Script>()->get_script_property_list(&props);
+ }
+
+ StringName base=base_type;
+ while(base) {
+ props.push_back(PropertyInfo(Variant::NIL,base,PROPERTY_HINT_NONE,"",PROPERTY_USAGE_CATEGORY));
+ ClassDB::get_property_list(base,&props,true);
+ base=ClassDB::get_parent_class(base);
+ }
+
+ }
+
+ TreeItem *category=NULL;
+
+ bool found=false;
+
+ Ref<Texture> type_icons[Variant::VARIANT_MAX]={
+ Control::get_icon("MiniVariant","EditorIcons"),
+ Control::get_icon("MiniBoolean","EditorIcons"),
+ Control::get_icon("MiniInteger","EditorIcons"),
+ Control::get_icon("MiniFloat","EditorIcons"),
+ Control::get_icon("MiniString","EditorIcons"),
+ Control::get_icon("MiniVector2","EditorIcons"),
+ Control::get_icon("MiniRect2","EditorIcons"),
+ Control::get_icon("MiniVector3","EditorIcons"),
+ Control::get_icon("MiniMatrix2","EditorIcons"),
+ Control::get_icon("MiniPlane","EditorIcons"),
+ Control::get_icon("MiniQuat","EditorIcons"),
+ Control::get_icon("MiniAabb","EditorIcons"),
+ Control::get_icon("MiniMatrix3","EditorIcons"),
+ Control::get_icon("MiniTransform","EditorIcons"),
+ Control::get_icon("MiniColor","EditorIcons"),
+ Control::get_icon("MiniImage","EditorIcons"),
+ Control::get_icon("MiniPath","EditorIcons"),
+ Control::get_icon("MiniRid","EditorIcons"),
+ Control::get_icon("MiniObject","EditorIcons"),
+ Control::get_icon("MiniInput","EditorIcons"),
+ Control::get_icon("MiniDictionary","EditorIcons"),
+ Control::get_icon("MiniArray","EditorIcons"),
+ Control::get_icon("MiniRawArray","EditorIcons"),
+ Control::get_icon("MiniIntArray","EditorIcons"),
+ Control::get_icon("MiniFloatArray","EditorIcons"),
+ Control::get_icon("MiniStringArray","EditorIcons"),
+ Control::get_icon("MiniVector2Array","EditorIcons"),
+ Control::get_icon("MiniVector3Array","EditorIcons"),
+ Control::get_icon("MiniColorArray","EditorIcons")
+ };
+
+
+ for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+ if (E->get().usage==PROPERTY_USAGE_CATEGORY) {
+ if (category && category->get_children()==NULL) {
+ memdelete(category); //old category was unused
+ }
+ category = search_options->create_item(root);
+ category->set_text(0,E->get().name);
+ category->set_selectable(0,false);
+
+ Ref<Texture> icon;
+ if (E->get().name=="Script Variables") {
+ icon=get_icon("Script","EditorIcons");
+ } else if (has_icon(E->get().name,"EditorIcons")) {
+ icon=get_icon(E->get().name,"EditorIcons");
+ } else {
+ icon=get_icon("Object","EditorIcons");
+ }
+ category->set_icon(0,icon);
+ continue;
+ }
+
+ if (!(E->get().usage&PROPERTY_USAGE_EDITOR))
+ continue;
+
+ if (search_box->get_text()!=String() && E->get().name.find(search_box->get_text())==-1)
+ continue;
+ TreeItem *item = search_options->create_item(category?category:root);
+ item->set_text(0,E->get().name);
+ item->set_metadata(0,E->get().name);
+ item->set_icon(0,type_icons[E->get().type]);
+
+ if (!found && search_box->get_text()!=String() && E->get().name.find(search_box->get_text())!=-1) {
+ item->select(0);
+ found=true;
+ }
+
+ item->set_selectable(0,true);
+ }
+
+ if (category && category->get_children()==NULL) {
+ memdelete(category); //old category was unused
+ }
+ } else {
+
+ List<MethodInfo> methods;
+
+ if (type!=Variant::NIL) {
+ Variant v;
+ Variant::CallError ce;
+ v=Variant::construct(type,NULL,0,ce);
+ v.get_method_list(&methods);
+ } else {
+
+
+ Object *obj = ObjectDB::get_instance(script);
+ if (obj && obj->cast_to<Script>()) {
+
+ methods.push_back(MethodInfo("*Script Methods"));
+ obj->cast_to<Script>()->get_script_method_list(&methods);
+ }
+
+ StringName base=base_type;
+ while(base) {
+ methods.push_back(MethodInfo("*"+String(base)));
+ ClassDB::get_method_list(base,&methods,true);
+ base=ClassDB::get_parent_class(base);
+ }
+
+ }
+
+ TreeItem *category=NULL;
+
+ bool found=false;
+ bool script_methods=false;
+
+ for (List<MethodInfo>::Element *E=methods.front();E;E=E->next()) {
+ if (E->get().name.begins_with("*")) {
+ if (category && category->get_children()==NULL) {
+ memdelete(category); //old category was unused
+ }
+ category = search_options->create_item(root);
+ category->set_text(0,E->get().name.replace_first("*",""));
+ category->set_selectable(0,false);
+
+ Ref<Texture> icon;
+ script_methods=false;
+ if (E->get().name=="*Script Methods") {
+ icon=get_icon("Script","EditorIcons");
+ script_methods=true;
+ } else if (has_icon(E->get().name,"EditorIcons")) {
+ icon=get_icon(E->get().name,"EditorIcons");
+ } else {
+ icon=get_icon("Object","EditorIcons");
+ }
+ category->set_icon(0,icon);
+
+ continue;
+ }
+
+ String name = E->get().name.get_slice(":",0);
+ if (!script_methods && name.begins_with("_") && !(E->get().flags&METHOD_FLAG_VIRTUAL))
+ continue;
+
+ if (search_box->get_text()!=String() && name.find(search_box->get_text())==-1)
+ continue;
+
+ TreeItem *item = search_options->create_item(category?category:root);
+
+ MethodInfo mi=E->get();
+
+ String desc;
+ if (mi.name.find(":")!=-1) {
+ desc=mi.name.get_slice(":",1)+" ";
+ mi.name=mi.name.get_slice(":",0);
+ } else if (mi.return_val.type!=Variant::NIL)
+ desc=Variant::get_type_name(mi.return_val.type);
+ else
+ desc="void ";
+
+
+
+ desc+=" "+mi.name+" ( ";
+
+ for(int i=0;i<mi.arguments.size();i++) {
+
+ if (i>0)
+ desc+=", ";
+
+ if (mi.arguments[i].type==Variant::NIL)
+ desc+="var ";
+ else if (mi.arguments[i].name.find(":")!=-1) {
+ desc+=mi.arguments[i].name.get_slice(":",1)+" ";
+ mi.arguments[i].name=mi.arguments[i].name.get_slice(":",0);
+ } else
+ desc+=Variant::get_type_name(mi.arguments[i].type)+" ";
+
+ desc+=mi.arguments[i].name;
+
+ }
+
+ desc+=" )";
+
+ item->set_text(0,desc);
+ item->set_metadata(0,name);
+ item->set_selectable(0,true);
+
+ if (!found && search_box->get_text()!=String() && name.find(search_box->get_text())!=-1) {
+ item->select(0);
+ found=true;
+ }
+
+ }
+
+ if (category && category->get_children()==NULL) {
+ memdelete(category); //old category was unused
+ }
+
+ }
+
+ get_ok()->set_disabled(root->get_children()==NULL);
+
+}
+
+
+
+void PropertySelector::_confirmed() {
+
+ TreeItem *ti = search_options->get_selected();
+ if (!ti)
+ return;
+ emit_signal("selected",ti->get_metadata(0));
+ hide();
+}
+
+void PropertySelector::_item_selected() {
+
+ help_bit->set_text("");
+
+ TreeItem *item=search_options->get_selected();
+ if (!item)
+ return;
+ String name = item->get_metadata(0);
+
+ String class_type;
+ if (properties && type==Variant::INPUT_EVENT) {
+
+ switch(event_type) {
+ case InputEvent::NONE: class_type="InputEvent"; break;
+ case InputEvent::KEY: class_type="InputEventKey"; break;
+ case InputEvent::MOUSE_MOTION: class_type="InputEventMouseMotion"; break;
+ case InputEvent::MOUSE_BUTTON: class_type="InputEventMouseButton"; break;
+ case InputEvent::JOYPAD_MOTION: class_type="InputEventJoypadMotion"; break;
+ case InputEvent::JOYPAD_BUTTON: class_type="InputEventJoypadButton"; break;
+ case InputEvent::SCREEN_TOUCH: class_type="InputEventScreenTouch"; break;
+ case InputEvent::SCREEN_DRAG: class_type="InputEventScreenDrag"; break;
+ case InputEvent::ACTION: class_type="InputEventAction"; break;
+ default: {}
+ }
+
+ } else if (type) {
+ class_type=Variant::get_type_name(type);
+
+ } else {
+ class_type=base_type;
+ }
+
+ DocData *dd=EditorHelp::get_doc_data();
+ String text;
+
+
+ if (properties) {
+
+ String at_class=class_type;
+
+
+
+ while(at_class!=String()) {
+
+
+ Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(at_class);
+ if (E) {
+ for(int i=0;i<E->get().properties.size();i++) {
+ if (E->get().properties[i].name==name) {
+ text=E->get().properties[i].description;
+ }
+ }
+ }
+
+ at_class=ClassDB::get_parent_class(at_class);
+ }
+
+ if (text==String()) {
+
+ StringName setter;
+ StringName type;
+ if (ClassDB::get_setter_and_type_for_property(class_type,name,type,setter)) {
+ Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
+ if (E) {
+ for(int i=0;i<E->get().methods.size();i++) {
+ if (E->get().methods[i].name==setter.operator String()) {
+ text=E->get().methods[i].description;
+ }
+ }
+ }
+
+
+ }
+ }
+
+ } else {
+
+
+ String at_class=class_type;
+
+ while(at_class!=String()) {
+
+ Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(at_class);
+ if (E) {
+ for(int i=0;i<E->get().methods.size();i++) {
+ if (E->get().methods[i].name==name) {
+ text=E->get().methods[i].description;
+ }
+ }
+ }
+
+ at_class=ClassDB::get_parent_class(at_class);
+ }
+ }
+
+
+ if (text==String())
+ return;
+
+ help_bit->set_text(text);
+
+}
+
+
+void PropertySelector::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ connect("confirmed",this,"_confirmed");
+
+ }
+}
+
+
+
+void PropertySelector::select_method_from_base_type(const String& p_base,const String& p_current) {
+
+ base_type=p_base;
+ selected=p_current;
+ type=Variant::NIL;
+ script=0;
+ properties=false;
+ instance=NULL;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+}
+
+void PropertySelector::select_method_from_script(const Ref<Script>& p_script,const String& p_current){
+
+ ERR_FAIL_COND( p_script.is_null() );
+ base_type=p_script->get_instance_base_type();
+ selected=p_current;
+ type=Variant::NIL;
+ script=p_script->get_instance_ID();
+ properties=false;
+ instance=NULL;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+
+}
+void PropertySelector::select_method_from_basic_type(Variant::Type p_type, const String &p_current){
+
+ ERR_FAIL_COND(p_type==Variant::NIL);
+ base_type="";
+ selected=p_current;
+ type=p_type;
+ script=0;
+ properties=false;
+ instance=NULL;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+
+}
+
+void PropertySelector::select_method_from_instance(Object* p_instance, const String &p_current){
+
+
+ base_type=p_instance->get_class();
+ selected=p_current;
+ type=Variant::NIL;
+ script=0;
+ {
+ Ref<Script> scr = p_instance->get_script();
+ if (scr.is_valid())
+ script=scr->get_instance_ID();
+ }
+ properties=false;
+ instance=NULL;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+
+}
+
+
+void PropertySelector::select_property_from_base_type(const String& p_base,const String& p_current) {
+
+ base_type=p_base;
+ selected=p_current;
+ type=Variant::NIL;
+ script=0;
+ properties=true;
+ instance=NULL;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+}
+
+void PropertySelector::select_property_from_script(const Ref<Script>& p_script,const String& p_current){
+
+ ERR_FAIL_COND( p_script.is_null() );
+
+ base_type=p_script->get_instance_base_type();
+ selected=p_current;
+ type=Variant::NIL;
+ script=p_script->get_instance_ID();
+ properties=true;
+ instance=NULL;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+
+}
+void PropertySelector::select_property_from_basic_type(Variant::Type p_type, InputEvent::Type p_event_type, const String &p_current){
+
+ ERR_FAIL_COND(p_type==Variant::NIL);
+ base_type="";
+ selected=p_current;
+ type=p_type;
+ event_type=p_event_type;
+ script=0;
+ properties=true;
+ instance=NULL;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+
+}
+
+void PropertySelector::select_property_from_instance(Object* p_instance, const String &p_current){
+
+
+ base_type="";
+ selected=p_current;
+ type=Variant::NIL;
+ script=0;
+ properties=true;
+ instance=p_instance;
+
+ popup_centered_ratio(0.6);
+ search_box->set_text("");
+ search_box->grab_focus();
+ _update_search();
+
+}
+
+void PropertySelector::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_text_changed"),&PropertySelector::_text_changed);
+ ClassDB::bind_method(D_METHOD("_confirmed"),&PropertySelector::_confirmed);
+ ClassDB::bind_method(D_METHOD("_sbox_input"),&PropertySelector::_sbox_input);
+ ClassDB::bind_method(D_METHOD("_item_selected"),&PropertySelector::_item_selected);
+
+ ADD_SIGNAL(MethodInfo("selected",PropertyInfo(Variant::STRING,"name")));
+
+}
+
+
+PropertySelector::PropertySelector() {
+
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ //set_child_rect(vbc);
+ search_box = memnew( LineEdit );
+ vbc->add_margin_child(TTR("Search:"),search_box);
+ search_box->connect("text_changed",this,"_text_changed");
+ search_box->connect("gui_input",this,"_sbox_input");
+ search_options = memnew( Tree );
+ vbc->add_margin_child(TTR("Matches:"),search_options,true);
+ get_ok()->set_text(TTR("Open"));
+ get_ok()->set_disabled(true);
+ register_text_enter(search_box);
+ set_hide_on_ok(false);
+ search_options->connect("item_activated",this,"_confirmed");
+ search_options->connect("cell_selected",this,"_item_selected");
+ search_options->set_hide_root(true);
+ search_options->set_hide_folding(true);
+
+ help_bit = memnew( EditorHelpBit );
+ vbc->add_margin_child(TTR("Description:"),help_bit);
+ help_bit->connect("request_hide",this,"_closed");
+
+
+}
diff --git a/editor/property_selector.h b/editor/property_selector.h
new file mode 100644
index 0000000000..c2ce996be2
--- /dev/null
+++ b/editor/property_selector.h
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* property_selector.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PROPERTYSELECTOR_H
+#define PROPERTYSELECTOR_H
+
+#include "editor/property_editor.h"
+#include "scene/gui/rich_text_label.h"
+#include "editor_help.h"
+
+class PropertySelector : public ConfirmationDialog {
+ GDCLASS(PropertySelector,ConfirmationDialog )
+
+
+ LineEdit *search_box;
+ Tree *search_options;
+
+ void _update_search();
+
+ void _sbox_input(const InputEvent& p_ie);
+
+ void _confirmed();
+ void _text_changed(const String& p_newtext);
+
+ EditorHelpBit *help_bit;
+
+ bool properties;
+ String selected;
+ Variant::Type type;
+ InputEvent::Type event_type;
+ String base_type;
+ ObjectID script;
+ Object *instance;
+
+ void _item_selected();
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+
+
+public:
+
+
+ void select_method_from_base_type(const String& p_base,const String& p_current="");
+ void select_method_from_script(const Ref<Script>& p_script,const String& p_current="");
+ void select_method_from_basic_type(Variant::Type p_type,const String& p_current="");
+ void select_method_from_instance(Object* p_instance, const String &p_current="");
+
+ void select_property_from_base_type(const String& p_base,const String& p_current="");
+ void select_property_from_script(const Ref<Script>& p_script,const String& p_current="");
+ void select_property_from_basic_type(Variant::Type p_type,InputEvent::Type p_event_type,const String& p_current="");
+ void select_property_from_instance(Object* p_instance, const String &p_current="");
+
+ PropertySelector();
+};
+
+#endif // PROPERTYSELECTOR_H
diff --git a/tools/editor/pvrtc_compress.cpp b/editor/pvrtc_compress.cpp
index b130f6c773..b130f6c773 100644
--- a/tools/editor/pvrtc_compress.cpp
+++ b/editor/pvrtc_compress.cpp
diff --git a/tools/editor/pvrtc_compress.h b/editor/pvrtc_compress.h
index 4ba29026c5..4ba29026c5 100644
--- a/tools/editor/pvrtc_compress.h
+++ b/editor/pvrtc_compress.h
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
new file mode 100644
index 0000000000..f43189a7bf
--- /dev/null
+++ b/editor/quick_open.cpp
@@ -0,0 +1,285 @@
+/*************************************************************************/
+/* quick_open.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "quick_open.h"
+
+#include "os/keyboard.h"
+
+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);
+ if (p_dontclear)
+ 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) {
+
+ _update_search();
+}
+
+void EditorQuickOpen::_sbox_input(const InputEvent& p_ie) {
+
+ if (p_ie.type==InputEvent::KEY) {
+
+ switch(p_ie.key.scancode) {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN: {
+
+ search_options->call("_gui_input", 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;
+ }
+ }
+
+}
+
+float EditorQuickOpen::_path_cmp(String search, String path) const {
+
+ if (search == path) {
+ return 1.2f;
+ }
+ if (path.findn(search) != -1) {
+ return 1.1f;
+ }
+ return path.to_lower().similarity(search.to_lower());
+}
+
+void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector< Pair< String, Ref<Texture> > > &list) {
+
+ if (!add_directories) {
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+
+ _parse_fs(efsd->get_subdir(i), list);
+ }
+ }
+
+ String search_text = search_box->get_text();
+
+ if (add_directories) {
+ String path = efsd->get_path();
+ if (!path.ends_with("/"))
+ path+="/";
+ if (path!="res://") {
+ path=path.substr(6,path.length());
+ if (search_text.is_subsequence_ofi(path)) {
+ Pair< String, Ref<Texture> > pair;
+ pair.first = path;
+ pair.second = get_icon("folder", "FileDialog");
+
+ if (search_text != String() && list.size() > 0) {
+
+ float this_sim = _path_cmp(search_text, path);
+ float other_sim = _path_cmp(list[0].first, path);
+ int pos = 1;
+
+ while (pos < list.size() && this_sim <= other_sim) {
+ other_sim = _path_cmp(list[pos++].first, path);
+ }
+
+ pos = this_sim >= other_sim ? pos - 1 : pos;
+ list.insert(pos, pair);
+
+ } else {
+ list.push_back(pair);
+ }
+ }
+ }
+ }
+ for(int i=0;i<efsd->get_file_count();i++) {
+
+ String file = efsd->get_file_path(i);
+ file=file.substr(6,file.length());
+
+ if (ClassDB::is_parent_class(efsd->get_file_type(i),base_type) && (search_text.is_subsequence_ofi(file))) {
+ Pair< String, Ref<Texture> > pair;
+ pair.first = file;
+ pair.second = get_icon((has_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei);
+
+ if (search_text != String() && list.size() > 0) {
+
+ float this_sim = _path_cmp(search_text, file);
+ float other_sim = _path_cmp(list[0].first, file);
+ int pos = 1;
+
+ while (pos < list.size() && this_sim <= other_sim) {
+ other_sim = _path_cmp(list[pos++].first, file);
+ }
+
+ pos = this_sim >= other_sim ? pos - 1 : pos;
+ list.insert(pos, pair);
+
+ } else {
+
+ list.push_back(pair);
+ }
+ }
+ }
+
+
+ if (add_directories) {
+ for(int i=0;i<efsd->get_subdir_count();i++) {
+
+ _parse_fs(efsd->get_subdir(i), list);
+ }
+ }
+
+}
+
+void EditorQuickOpen::_update_search() {
+
+ search_options->clear();
+ TreeItem *root = search_options->create_item();
+ EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem();
+ Vector< Pair< String, Ref<Texture> > > list;
+
+ _parse_fs(efsd, list);
+
+ for (int i = 0; i < list.size(); i++) {
+ TreeItem *ti = search_options->create_item(root);
+ ti->set_text(0, list[i].first);
+ ti->set_icon(0, list[i].second);
+ }
+
+ 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);
+
+}
+
+void EditorQuickOpen::_confirmed() {
+
+ TreeItem *ti = search_options->get_selected();
+ if (!ti)
+ return;
+ emit_signal("quick_open");
+ hide();
+}
+
+void EditorQuickOpen::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ connect("confirmed",this,"_confirmed");
+ }
+}
+
+
+StringName EditorQuickOpen::get_base_type() const {
+
+ return base_type;
+}
+
+void EditorQuickOpen::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_text_changed"),&EditorQuickOpen::_text_changed);
+ ClassDB::bind_method(D_METHOD("_confirmed"),&EditorQuickOpen::_confirmed);
+ ClassDB::bind_method(D_METHOD("_sbox_input"),&EditorQuickOpen::_sbox_input);
+
+ ADD_SIGNAL(MethodInfo("quick_open"));
+
+}
+
+
+EditorQuickOpen::EditorQuickOpen() {
+
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ //set_child_rect(vbc);
+ search_box = memnew( LineEdit );
+ vbc->add_margin_child(TTR("Search:"),search_box);
+ search_box->connect("text_changed",this,"_text_changed");
+ search_box->connect("gui_input",this,"_sbox_input");
+ search_options = memnew( Tree );
+ vbc->add_margin_child(TTR("Matches:"),search_options,true);
+ get_ok()->set_text(TTR("Open"));
+ get_ok()->set_disabled(true);
+ register_text_enter(search_box);
+ set_hide_on_ok(false);
+ search_options->connect("item_activated",this,"_confirmed");
+ search_options->set_hide_root(true);
+ ei="EditorIcons";
+ ot="Object";
+ add_directories=false;
+}
diff --git a/tools/editor/quick_open.h b/editor/quick_open.h
index ef91d910b1..ef91d910b1 100644
--- a/tools/editor/quick_open.h
+++ b/editor/quick_open.h
diff --git a/tools/editor/register_exporters.h b/editor/register_exporters.h
index 30ec522a00..30ec522a00 100644
--- a/tools/editor/register_exporters.h
+++ b/editor/register_exporters.h
diff --git a/tools/editor/reparent_dialog.cpp b/editor/reparent_dialog.cpp
index c5b74d9006..c5b74d9006 100644
--- a/tools/editor/reparent_dialog.cpp
+++ b/editor/reparent_dialog.cpp
diff --git a/editor/reparent_dialog.h b/editor/reparent_dialog.h
new file mode 100644
index 0000000000..200760314c
--- /dev/null
+++ b/editor/reparent_dialog.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* reparent_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 REPARENT_DIALOG_H
+#define REPARENT_DIALOG_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/button.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/check_box.h"
+#include "editor/scene_tree_editor.h"
+#include "scene/gui/line_edit.h"
+/**
+@author Juan Linietsky <reduzio@gmail.com>
+*/
+class ReparentDialog : public ConfirmationDialog {
+
+ GDCLASS( ReparentDialog, ConfirmationDialog );
+
+ SceneTreeEditor *tree;
+ CheckBox *keep_transform;
+
+
+ void update_tree();
+ void _reparent();
+ void _cancel();
+
+
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void set_current(const Set<Node*>& p_selection);
+ String get_selected_type();
+
+ ReparentDialog();
+ ~ReparentDialog();
+
+};
+
+#endif
diff --git a/editor/resources_dock.cpp b/editor/resources_dock.cpp
new file mode 100644
index 0000000000..8648361bae
--- /dev/null
+++ b/editor/resources_dock.cpp
@@ -0,0 +1,409 @@
+/*************************************************************************/
+/* resources_dock.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resources_dock.h"
+
+#include "editor_node.h"
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "editor_settings.h"
+#include "project_settings.h"
+#include "global_config.h"
+#include "editor_file_system.h"
+
+
+void ResourcesDock::_tool_selected(int p_tool) {
+
+ current_action=p_tool;
+
+ switch(p_tool) {
+
+ case TOOL_NEW: {
+
+ create_dialog->popup_centered_ratio();
+ } break;
+ case TOOL_OPEN: {
+ editor->open_resource();
+
+ } break;
+ case TOOL_SAVE: {
+
+ TreeItem *ti = resources->get_selected();
+ if (!ti)
+ break;
+ Ref<Resource> current_res = ti->get_metadata(0);
+
+
+ if (current_res->get_path()!="" && current_res->get_path().find("::")==-1) {
+ _file_action(current_res->get_path());
+ break;
+ };
+
+ }; /* fallthrough */
+ case TOOL_SAVE_AS: {
+
+ TreeItem *ti = resources->get_selected();
+ if (!ti)
+ break;
+
+ save_resource_as(ti->get_metadata(0));
+
+
+ } break;
+ case TOOL_MAKE_LOCAL: {
+
+ TreeItem *ti = resources->get_selected();
+ if (!ti)
+ break;
+ Ref<Resource> current_res = ti->get_metadata(0);
+ current_res->set_path("");
+ _update_name(ti);
+ } break;
+ case TOOL_COPY: {
+
+ TreeItem *ti = resources->get_selected();
+ if (!ti)
+ break;
+ Ref<Resource> current_res = ti->get_metadata(0);
+ EditorSettings::get_singleton()->set_resource_clipboard(current_res);
+
+ } break;
+ case TOOL_PASTE: {
+
+ add_resource(EditorSettings::get_singleton()->get_resource_clipboard());
+ } break;
+
+ }
+}
+
+
+
+void ResourcesDock::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_ENTER_TREE: {
+
+ button_new->set_icon(get_icon("New","EditorIcons"));
+ button_open->set_icon(get_icon("Folder","EditorIcons"));
+ button_save->set_icon(get_icon("Save","EditorIcons"));
+ button_tools->set_icon(get_icon("Tools","EditorIcons"));
+
+
+ } break;
+ }
+
+}
+
+
+void ResourcesDock::save_resource(const String& p_path,const Ref<Resource>& p_resource) {
+
+ editor->get_editor_data().apply_changes_in_editors();
+ 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;
+ */
+
+ String path = GlobalConfig::get_singleton()->localize_path(p_path);
+ Error err = ResourceSaver::save(path,p_resource,flg|ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
+
+ if (err!=OK) {
+ accept->set_text(TTR("Error saving resource!"));
+ accept->popup_centered_minsize();
+ return;
+ }
+ //EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
+
+ ((Resource*)p_resource.ptr())->set_path(path);
+ editor->emit_signal("resource_saved",p_resource);
+
+}
+
+void ResourcesDock::save_resource_as(const Ref<Resource>& p_resource) {
+
+ current_action=TOOL_SAVE_AS;
+
+ RES res(p_resource);
+
+ List<String> extensions;
+ ResourceSaver::get_recognized_extensions(res,&extensions);
+ file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+
+ if (p_resource->get_path()!="" && p_resource->get_path().find("::")==-1) {
+
+ file->set_current_path(p_resource->get_path());
+ } else {
+
+ String existing;
+ if (extensions.size()) {
+ existing="new_"+res->get_class().to_lower()+"."+extensions.front()->get().to_lower();
+ }
+
+ file->set_current_file(existing);
+ }
+
+ file->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+ file->popup_centered_ratio();
+
+}
+
+void ResourcesDock::_file_action(const String& p_path) {
+
+
+ switch(current_action) {
+
+ case TOOL_OPEN: {
+
+ } break;
+ case TOOL_SAVE:
+ case TOOL_SAVE_AS: {
+
+ TreeItem *ti = resources->get_selected();
+ if (!ti)
+ break;
+ Ref<Resource> current_res = ti->get_metadata(0);
+
+ RES res(current_res);
+
+ save_resource(p_path,res);
+
+ _update_name(ti);
+
+ } break;
+
+ }
+}
+
+void ResourcesDock::_update_name(TreeItem *item) {
+
+ Ref<Resource> res = item->get_metadata(0);
+
+
+ if (res->get_name()!="")
+ item->set_text(0,res->get_name());
+ else if (res->get_path()!="" && res->get_path().find("::")==-1)
+ item->set_text(0,res->get_path().get_file());
+ else
+ item->set_text(0,res->get_class()+" ("+itos(res->get_instance_ID())+")");
+
+}
+
+
+void ResourcesDock::remove_resource(const Ref<Resource>& p_resource) {
+
+ TreeItem *root = resources->get_root();
+ ERR_FAIL_COND(!root);
+
+ TreeItem *existing=root->get_children();
+
+ while(existing) {
+
+ Ref<Resource> r = existing->get_metadata(0);
+ if (r==p_resource) {
+ //existing->move_to_top();
+ memdelete(existing);
+ return;
+ }
+ existing=existing->get_next();
+ }
+
+
+}
+
+void ResourcesDock::add_resource(const Ref<Resource>& p_resource) {
+
+ if (block_add)
+ return;
+ if (!p_resource.is_valid())
+ return;
+
+ TreeItem *root = resources->get_root();
+ ERR_FAIL_COND(!root);
+
+ TreeItem *existing=root->get_children();
+
+ while(existing) {
+
+ Ref<Resource> r = existing->get_metadata(0);
+ if (r==p_resource) {
+ //existing->move_to_top();
+ existing->select(0);
+ resources->ensure_cursor_is_visible();
+ return; // existing
+ }
+ existing=existing->get_next();
+ }
+
+ TreeItem *res = resources->create_item(root);
+ res->set_metadata(0,p_resource);
+
+ if (has_icon(p_resource->get_class(),"EditorIcons")) {
+ res->set_icon(0,get_icon(p_resource->get_class(),"EditorIcons"));
+ }
+
+ _update_name(res);
+ res->add_button(0,get_icon("Del","EditorIcons"));
+ res->move_to_top();
+ res->select(0);
+ resources->ensure_cursor_is_visible();
+
+}
+
+void ResourcesDock::_resource_selected() {
+
+ TreeItem *sel = resources->get_selected();
+ ERR_FAIL_COND(!sel);
+
+
+ Ref<Resource> r = sel->get_metadata(0);
+ if (r.is_null())
+ return;
+ block_add=true;
+ editor->push_item(r.ptr());
+ block_add=false;
+}
+
+void ResourcesDock::_delete(Object* p_item, int p_column, int p_id) {
+
+ TreeItem *ti = p_item->cast_to<TreeItem>();
+ ERR_FAIL_COND(!ti);
+
+
+ call_deferred("remove_resource",ti->get_metadata(0));
+
+}
+
+void ResourcesDock::_create() {
+
+ Object *c = create_dialog->instance_selected();
+
+ ERR_FAIL_COND(!c);
+ Resource *r = c->cast_to<Resource>();
+ ERR_FAIL_COND(!r);
+
+ REF res( r );
+
+ editor->push_item(c);
+
+}
+
+void ResourcesDock::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_tool_selected"),&ResourcesDock::_tool_selected);
+ ClassDB::bind_method(D_METHOD("_create"),&ResourcesDock::_create);
+ ClassDB::bind_method(D_METHOD("_resource_selected"),&ResourcesDock::_resource_selected);
+ ClassDB::bind_method(D_METHOD("_delete"),&ResourcesDock::_delete);
+ ClassDB::bind_method(D_METHOD("remove_resource"),&ResourcesDock::remove_resource);
+ ClassDB::bind_method(D_METHOD("_file_action"),&ResourcesDock::_file_action);
+
+
+
+}
+
+void ResourcesDock::cleanup() {
+
+
+ resources->clear();
+ resources->create_item(); //root
+
+}
+
+
+ResourcesDock::ResourcesDock(EditorNode *p_editor) {
+
+ editor=p_editor;
+
+ VBoxContainer *vbc = this;
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
+
+
+ Button *b;
+ b = memnew( ToolButton );
+ b->set_tooltip(TTR("Create New Resource"));
+ b->connect("pressed",this,"_tool_selected",make_binds(TOOL_NEW));
+ hbc->add_child( b );
+ button_new=b;
+
+ b = memnew( ToolButton );
+ b->set_tooltip(TTR("Open Resource"));
+ b->connect("pressed",this,"_tool_selected",make_binds(TOOL_OPEN));
+ hbc->add_child( b );
+ button_open=b;
+
+ MenuButton *mb = memnew( MenuButton );
+ mb->set_tooltip(TTR("Save Resource"));
+ mb->get_popup()->add_item(TTR("Save Resource"),TOOL_SAVE);
+ mb->get_popup()->add_item(TTR("Save Resource As.."),TOOL_SAVE_AS);
+ mb->get_popup()->connect("id_pressed",this,"_tool_selected" );
+ hbc->add_child( mb );
+ button_save=mb;
+
+ hbc->add_spacer();
+
+ mb = memnew( MenuButton );
+ mb->set_tooltip(TTR("Resource Tools"));
+ mb->get_popup()->add_item(TTR("Make Local"),TOOL_MAKE_LOCAL);
+ mb->get_popup()->add_item(TTR("Copy"),TOOL_COPY);
+ mb->get_popup()->add_item(TTR("Paste"),TOOL_PASTE);
+ mb->get_popup()->connect("id_pressed",this,"_tool_selected" );
+ hbc->add_child( mb );
+ button_tools=mb;
+
+ resources = memnew( Tree );
+ vbc->add_child(resources);
+ resources->set_v_size_flags(SIZE_EXPAND_FILL);
+ resources->create_item(); //root
+ resources->set_hide_root(true);
+ resources->connect("cell_selected",this,"_resource_selected");
+ resources->connect("button_pressed",this,"_delete");
+
+ create_dialog = memnew( CreateDialog );
+ add_child(create_dialog);
+ create_dialog->set_base_type("Resource");
+ create_dialog->connect("create",this,"_create");
+ accept = memnew (AcceptDialog);
+ add_child(accept);
+
+ file = memnew( EditorFileDialog );
+ add_child(file);
+ file->connect("file_selected",this,"_file_action");
+
+
+ block_add=false;
+}
+
diff --git a/tools/editor/resources_dock.h b/editor/resources_dock.h
index e225786583..e225786583 100644
--- a/tools/editor/resources_dock.h
+++ b/editor/resources_dock.h
diff --git a/tools/editor/run_settings_dialog.cpp b/editor/run_settings_dialog.cpp
index 4d69c7ad84..4d69c7ad84 100644
--- a/tools/editor/run_settings_dialog.cpp
+++ b/editor/run_settings_dialog.cpp
diff --git a/tools/editor/run_settings_dialog.h b/editor/run_settings_dialog.h
index 2efc18e43f..2efc18e43f 100644
--- a/tools/editor/run_settings_dialog.h
+++ b/editor/run_settings_dialog.h
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
new file mode 100644
index 0000000000..47eb84ab79
--- /dev/null
+++ b/editor/scene_tree_dock.cpp
@@ -0,0 +1,2061 @@
+/*************************************************************************/
+/* scene_tree_dock.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "scene_tree_dock.h"
+
+#include "editor_node.h"
+#include "global_config.h"
+#include "os/keyboard.h"
+#include "scene/resources/packed_scene.h"
+#include "editor_settings.h"
+#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/plugins/spatial_editor_plugin.h"
+#include "script_editor_debugger.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "core/io/resource_saver.h"
+#include "multi_node_edit.h"
+#include "editor/plugins/animation_player_editor_plugin.h"
+#include "animation_editor.h"
+#include "scene/main/viewport.h"
+
+
+void SceneTreeDock::_nodes_drag_begin() {
+
+
+ if (restore_script_editor_on_drag) {
+ EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
+ restore_script_editor_on_drag=false;
+ }
+
+}
+
+void SceneTreeDock::_input(InputEvent p_event) {
+
+ if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==BUTTON_LEFT) {
+ restore_script_editor_on_drag=false; //lost chance
+ }
+}
+
+void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
+
+ if (get_viewport()->get_modal_stack_top())
+ return; //ignore because of modal window
+
+ if (!p_event.key.pressed || p_event.key.echo)
+ return;
+
+ if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
+ _tool_selected(TOOL_NEW);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) {
+ _tool_selected(TOOL_INSTANCE);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/change_node_type", p_event)) {
+ _tool_selected(TOOL_REPLACE);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/duplicate", p_event)) {
+ _tool_selected(TOOL_DUPLICATE);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/attach_script", p_event)) {
+ _tool_selected(TOOL_ATTACH_SCRIPT);
+ }
+ else if(ED_IS_SHORTCUT("scene_tree/clear_script", p_event)) {
+ _tool_selected(TOOL_CLEAR_SCRIPT);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/move_up", p_event)) {
+ _tool_selected(TOOL_MOVE_UP);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/move_down", p_event)) {
+ _tool_selected(TOOL_MOVE_DOWN);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/reparent", p_event)) {
+ _tool_selected(TOOL_REPARENT);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/merge_from_scene", p_event)) {
+ _tool_selected(TOOL_MERGE_FROM_SCENE);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/save_branch_as_scene", p_event)) {
+ _tool_selected(TOOL_NEW_SCENE_FROM);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/delete_no_confirm", p_event)) {
+ _tool_selected(TOOL_ERASE, true);
+ }
+ else if(ED_IS_SHORTCUT("scene_tree/copy_node_path", p_event)) {
+ _tool_selected(TOOL_COPY_NODE_PATH);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/delete", p_event)) {
+ _tool_selected(TOOL_ERASE);
+ }
+}
+
+void SceneTreeDock::instance(const String& p_file) {
+
+ Node *parent = scene_tree->get_selected();
+ if (!parent || !edited_scene) {
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("OK :("));
+ accept->set_text(TTR("No parent to instance a child at."));
+ accept->popup_centered_minsize();
+ return;
+ };
+
+ ERR_FAIL_COND(!parent);
+
+ Vector<String> scenes;
+ scenes.push_back(p_file);
+ _perform_instance_scenes(scenes,parent,-1);
+
+}
+
+void SceneTreeDock::instance_scenes(const Vector<String>& p_files, Node *p_parent) {
+
+ Node *parent = p_parent;
+
+ if (!parent) {
+ parent = scene_tree->get_selected();
+ }
+
+ if (!parent || !edited_scene) {
+
+ accept->get_ok()->set_text(TTR("OK"));
+ accept->set_text(TTR("No parent to instance the scenes at."));
+ accept->popup_centered_minsize();
+ return;
+ };
+
+ _perform_instance_scenes(p_files, parent, -1);
+}
+
+void SceneTreeDock::_perform_instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos) {
+
+
+
+ ERR_FAIL_COND(!parent);
+
+
+ Vector<Node*> instances;
+
+ bool error=false;
+
+ for(int i=0;i<p_files.size();i++) {
+
+ Ref<PackedScene> sdata = ResourceLoader::load(p_files[i]);
+ if (!sdata.is_valid()) {
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(vformat(TTR("Error loading scene from %s"),p_files[i]));
+ accept->popup_centered_minsize();
+ error=true;
+ break;
+
+ }
+
+ Node*instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ if (!instanced_scene) {
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(vformat(TTR("Error instancing scene from %s"),p_files[i]));
+ accept->popup_centered_minsize();
+ error=true;
+ break;
+
+ }
+
+ if (edited_scene->get_filename()!="") {
+
+ if (_cyclical_dependency_exists(edited_scene->get_filename(), instanced_scene)) {
+
+ accept->get_ok()->set_text(TTR("Ok"));
+ accept->set_text(vformat(TTR("Cannot instance the scene '%s' because the current scene exists within one of its nodes."),p_files[i]));
+ accept->popup_centered_minsize();
+ error=true;
+ break;
+ }
+ }
+
+ instanced_scene->set_filename( GlobalConfig::get_singleton()->localize_path(p_files[i]) );
+
+ instances.push_back(instanced_scene);
+ }
+
+ if (error) {
+ for(int i=0;i<instances.size();i++) {
+ memdelete(instances[i]);
+ }
+ return;
+ }
+
+
+
+ //instanced_scene->generate_instance_state();
+
+ editor_data->get_undo_redo().create_action(TTR("Instance Scene(s)"));
+
+ for(int i=0;i<instances.size();i++) {
+
+ Node* instanced_scene=instances[i];
+
+ editor_data->get_undo_redo().add_do_method(parent,"add_child",instanced_scene);
+ if (p_pos>=0) {
+ editor_data->get_undo_redo().add_do_method(parent,"move_child",instanced_scene,p_pos+i);
+ }
+ editor_data->get_undo_redo().add_do_method(instanced_scene,"set_owner",edited_scene);
+ editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
+ editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",instanced_scene);
+ editor_data->get_undo_redo().add_do_reference(instanced_scene);
+ editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene);
+
+ String new_name = parent->validate_child_name(instanced_scene);
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",edited_scene->get_path_to(parent),p_files[i],new_name);
+ editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name));
+ }
+
+ editor_data->get_undo_redo().commit_action();
+
+
+}
+
+void SceneTreeDock::_replace_with_branch_scene(const String& p_file,Node* base) {
+ Ref<PackedScene> sdata = ResourceLoader::load(p_file);
+ if (!sdata.is_valid()) {
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(vformat(TTR("Error loading scene from %s"),p_file));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ Node *instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ if (!instanced_scene) {
+ accept->get_ok()->set_text(TTR("Ugh"));
+ accept->set_text(vformat(TTR("Error instancing scene from %s"),p_file));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ Node *parent = base->get_parent();
+ int pos = base->get_index();
+ memdelete(base);
+ parent->add_child(instanced_scene);
+ parent->move_child(instanced_scene, pos);
+ instanced_scene->set_owner(edited_scene);
+ editor_selection->clear();
+ editor_selection->add_node(instanced_scene);
+ scene_tree->set_selected(instanced_scene);
+}
+
+bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) {
+ int childCount = p_desired_node->get_child_count();
+
+ if (p_desired_node->get_filename()==p_target_scene_path) {
+ return true;
+ }
+
+ for (int i=0;i<childCount;i++) {
+ Node* child=p_desired_node->get_child(i);
+
+ if(_cyclical_dependency_exists(p_target_scene_path,child)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
+
+ current_option=p_tool;
+
+ switch(p_tool) {
+
+ case TOOL_NEW: {
+ /*
+ if (!_validate_no_foreign())
+ break;
+ */
+ create_dialog->popup(true);
+ } break;
+ case TOOL_INSTANCE: {
+
+ Node *scene = edited_scene;
+
+ if (!scene) {
+
+ EditorNode::get_singleton()->new_inherited_scene();
+
+ /* should be legal now
+ 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 tree root.");
+ accept->popup_centered_minsize();
+ */
+ break;
+ }
+
+ /*
+ if (!_validate_no_foreign())
+ break;
+ */
+
+ file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
+ file->clear_filters();
+ for(int i=0;i<extensions.size();i++) {
+
+ file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
+ }
+
+ //file->set_current_path(current_path);
+ file->popup_centered_ratio();
+
+ } break;
+ case TOOL_REPLACE: {
+
+ create_dialog->popup(false);
+ } break;
+ case TOOL_CONNECT: {
+
+ Node *current = scene_tree->get_selected();
+ if (!current)
+ break;
+
+ /*
+ if (!_validate_no_foreign())
+ break;
+ connect_dialog->popup_centered_ratio();
+ connect_dialog->set_node(current);
+ */
+
+ } break;
+ case TOOL_GROUP: {
+
+ Node *current = scene_tree->get_selected();
+ if (!current)
+ break;
+ /*
+ if (!_validate_no_foreign())
+ break;
+ groups_editor->set_current(current);
+ groups_editor->popup_centered_ratio();
+ */
+ } break;
+ case TOOL_ATTACH_SCRIPT: {
+
+ Node *selected = scene_tree->get_selected();
+ if (!selected)
+ break;
+
+ /*
+ if (!_validate_no_foreign())
+ break;
+ */
+
+ Ref<Script> existing = selected->get_script();
+ if (existing.is_valid())
+ editor->push_item(existing.ptr());
+ else {
+ String path = selected->get_filename();
+ script_create_dialog->config(selected->get_class(),path);
+ script_create_dialog->popup_centered(Size2(300,290));
+ //script_create_dialog->popup_centered_minsize();
+
+ }
+
+ } break;
+ case TOOL_CLEAR_SCRIPT: {
+ Node *selected = scene_tree->get_selected();
+ if(!selected)
+ break;
+
+ Ref<Script> existing = selected->get_script();
+ if(existing.is_valid()) {
+ const RefPtr empty;
+ selected->set_script(empty);
+ button_create_script->show();
+ button_clear_script->hide();
+ }
+
+ } break;
+ case TOOL_MOVE_UP:
+ case TOOL_MOVE_DOWN: {
+
+ if (!scene_tree->get_selected())
+ break;
+
+
+ if (scene_tree->get_selected()==edited_scene) {
+
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("This operation can't be done on the tree root."));
+ accept->popup_centered_minsize();
+ break;
+ }
+
+
+ if (!_validate_no_foreign())
+ break;
+
+ bool MOVING_DOWN = (p_tool == TOOL_MOVE_DOWN);
+ bool MOVING_UP = !MOVING_DOWN;
+
+ Node *common_parent = scene_tree->get_selected()->get_parent();
+ List<Node*> selection = editor_selection->get_selected_node_list();
+ selection.sort_custom<Node::Comparator>(); // sort by index
+ if (MOVING_DOWN)
+ selection.invert();
+
+ int lowest_id = common_parent->get_child_count() - 1;
+ int highest_id = 0;
+ for (List<Node*>::Element *E = selection.front(); E; E = E->next()) {
+ int index = E->get()->get_index();
+
+ if (index > highest_id) highest_id = index;
+ if (index < lowest_id) lowest_id = index;
+
+ if (E->get()->get_parent() != common_parent)
+ common_parent = NULL;
+ }
+
+ if (!common_parent || (MOVING_DOWN && highest_id >= common_parent->get_child_count() - MOVING_DOWN) || (MOVING_UP && lowest_id == 0))
+ break; // one or more nodes can not be moved
+
+ if (selection.size() == 1) editor_data->get_undo_redo().create_action(TTR("Move Node In Parent"));
+ if (selection.size() > 1) editor_data->get_undo_redo().create_action(TTR("Move Nodes In Parent"));
+
+ for (int i = 0; i < selection.size(); i++) {
+ Node *top_node = selection[i];
+ Node *bottom_node = selection[selection.size() - 1 - i];
+
+ ERR_FAIL_COND(!top_node->get_parent());
+ ERR_FAIL_COND(!bottom_node->get_parent());
+
+ int bottom_node_pos = bottom_node->get_index();
+ int top_node_pos_next = top_node->get_index() + (MOVING_DOWN ? 1 : -1);
+
+ editor_data->get_undo_redo().add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next);
+ editor_data->get_undo_redo().add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos);
+ }
+
+ editor_data->get_undo_redo().commit_action();
+
+ } break;
+ case TOOL_DUPLICATE: {
+
+ if (!edited_scene)
+ break;
+
+
+ if (editor_selection->is_selected(edited_scene)) {
+
+
+ current_option=-1;
+ //accept->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("This operation can't be done on the tree root."));
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ if (!_validate_no_foreign())
+ break;
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+ if (selection.size()==0)
+ break;
+
+ List<Node*> reselect;
+
+ editor_data->get_undo_redo().create_action(TTR("Duplicate Node(s)"));
+ editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
+
+ Node *dupsingle=NULL;
+
+
+ for (List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ Node *node = E->get();
+ Node *parent = node->get_parent();
+
+ List<Node*> owned;
+ node->get_owned_by(node->get_owner(),&owned);
+
+ Map<Node*,Node*> duplimap;
+ Node * dup = _duplicate(node,duplimap);
+
+ ERR_CONTINUE(!dup);
+
+ if (selection.size()==1)
+ dupsingle=dup;
+
+ dup->set_name(parent->validate_child_name(dup));
+
+ editor_data->get_undo_redo().add_do_method(parent,"_add_child_below_node",node, dup);
+ for (List<Node*>::Element *F=owned.front();F;F=F->next()) {
+
+ if (!duplimap.has(F->get())) {
+
+ continue;
+ }
+ Node *d=duplimap[F->get()];
+ 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_do_reference(dup);
+
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+
+ editor_data->get_undo_redo().add_do_method(sed,"live_debug_duplicate_node",edited_scene->get_path_to(node),dup->get_name());
+ editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+dup->get_name()));
+
+ //parent->add_child(dup);
+ //reselect.push_back(dup);
+ }
+
+ editor_data->get_undo_redo().commit_action();
+
+ if (dupsingle)
+ editor->push_item(dupsingle);
+
+
+
+
+
+ } break;
+ case TOOL_REPARENT: {
+
+
+ if (!scene_tree->get_selected())
+ break;
+
+
+ if (editor_selection->is_selected(edited_scene)) {
+
+
+ current_option=-1;
+ //confirmation->get_cancel()->hide();
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("This operation can't be done on the tree root."));
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ if (!_validate_no_foreign())
+ break;
+
+ List<Node*> nodes = editor_selection->get_selected_node_list();
+ Set<Node*> nodeset;
+ for(List<Node*>::Element *E=nodes.front();E;E=E->next()) {
+
+ nodeset.insert(E->get());
+ }
+ reparent_dialog->popup_centered_ratio();
+ reparent_dialog->set_current( nodeset );
+
+ } break;
+ case TOOL_MULTI_EDIT: {
+
+ Node*root=EditorNode::get_singleton()->get_edited_scene();
+ if (!root)
+ break;
+ Ref<MultiNodeEdit> mne = memnew( MultiNodeEdit );
+ for (const Map<Node*,Object*>::Element *E=EditorNode::get_singleton()->get_editor_selection()->get_selection().front();E;E=E->next()) {
+ mne->add_node(root->get_path_to(E->key()));
+ }
+
+ EditorNode::get_singleton()->push_item(mne.ptr());
+
+ } break;
+
+ case TOOL_ERASE: {
+
+ List<Node*> remove_list = editor_selection->get_selected_node_list();
+
+ if (remove_list.empty())
+ return;
+
+ if (!_validate_no_foreign())
+ break;
+
+ if (p_confirm_override) {
+ _delete_confirm();
+
+ // hack, force 2d editor viewport to refresh after deletion
+ if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton())
+ editor->get_viewport_control()->update();
+
+ } else {
+ delete_dialog->set_text(TTR("Delete Node(s)?"));
+ delete_dialog->popup_centered_minsize();
+ }
+
+ } break;
+ case TOOL_MERGE_FROM_SCENE: {
+
+ EditorNode::get_singleton()->merge_from_scene();
+ } break;
+ case TOOL_NEW_SCENE_FROM: {
+
+ Node *scene = editor_data->get_edited_scene_root();
+
+ if (!scene) {
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("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(TTR("I see.."));
+ accept->set_text(TTR("This operation requires a single selected node."));
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ Node *tocopy = selection.front()->get();
+
+ if (tocopy==scene){
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Can not perform with the root node."));
+ accept->popup_centered_minsize();
+ break;
+ }
+
+ if (tocopy!=editor_data->get_edited_scene_root() && tocopy->get_filename()!="") {
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("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()) {
+ String root_name(tocopy->get_name());
+ existing=root_name+"."+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(TTR("Save New Scene As.."));
+
+ } break;
+ case TOOL_COPY_NODE_PATH: {
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ if(List<Node*>::Element *e = selection.front()) {
+ if(Node *node = e->get()) {
+ Node *root = EditorNode::get_singleton()->get_edited_scene();
+ NodePath path = root->get_path().rel_path_to(node->get_path());
+ OS::get_singleton()->set_clipboard(path);
+ }
+ }
+ } break;
+ }
+
+}
+
+void SceneTreeDock::_notification(int p_what) {
+
+ switch(p_what) {
+
+ case NOTIFICATION_READY: {
+
+ if (!first_enter)
+ break;
+ first_enter=false;
+
+ CanvasItemEditorPlugin *canvas_item_plugin = editor_data->get_editor("2D")->cast_to<CanvasItemEditorPlugin>();
+ if (canvas_item_plugin) {
+ canvas_item_plugin->get_canvas_item_editor()->connect("item_lock_status_changed", scene_tree, "_update_tree");
+ canvas_item_plugin->get_canvas_item_editor()->connect("item_group_status_changed", scene_tree, "_update_tree");
+ scene_tree->connect("node_changed", canvas_item_plugin->get_canvas_item_editor()->get_viewport_control(), "update");
+ }
+ button_add->set_icon(get_icon("Add","EditorIcons"));
+ button_instance->set_icon(get_icon("Instance","EditorIcons"));
+ button_create_script->set_icon(get_icon("ScriptCreate","EditorIcons"));
+ button_clear_script->set_icon(get_icon("ScriptRemove", "EditorIcons"));
+
+
+ filter_icon->set_texture(get_icon("Zoom","EditorIcons"));
+
+ EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed",this,"_selection_changed");
+
+ } break;
+ }
+}
+
+
+void SceneTreeDock::_load_request(const String& p_path) {
+
+ editor->open_request(p_path);
+}
+
+void SceneTreeDock::_script_open_request(const Ref<Script>& p_script) {
+
+ editor->edit_resource(p_script);
+}
+
+void SceneTreeDock::_node_selected() {
+
+
+ Node *node=scene_tree->get_selected();
+
+ if (!node) {
+
+ editor->push_item(NULL);
+ return;
+ }
+
+ if (ScriptEditor::get_singleton()->is_visible_in_tree()) {
+ restore_script_editor_on_drag=true;
+ }
+
+ editor->push_item(node);
+
+
+}
+
+void SceneTreeDock::_node_renamed() {
+
+ _node_selected();
+}
+
+Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node*,Node*> &duplimap) {
+
+ Node *node=NULL;
+
+ if (p_node->get_filename()!="") { //an instance
+
+ Ref<PackedScene> sd = ResourceLoader::load( p_node->get_filename() );
+ ERR_FAIL_COND_V(!sd.is_valid(),NULL);
+ node = sd->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ ERR_FAIL_COND_V(!node,NULL);
+ node->set_scene_instance_load_placeholder(p_node->get_scene_instance_load_placeholder());
+ //node->generate_instance_state();
+ } else {
+ Object *obj = ClassDB::instance(p_node->get_class());
+ ERR_FAIL_COND_V(!obj,NULL);
+ node = obj->cast_to<Node>();
+ if (!node)
+ memdelete(obj);
+ ERR_FAIL_COND_V(!node,NULL);
+
+ }
+
+ List<PropertyInfo> plist;
+
+ p_node->get_property_list(&plist);
+
+ for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
+
+ if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
+ continue;
+ String name = E->get().name;
+ node->set( name, p_node->get(name) );
+
+ }
+
+
+ List<Node::GroupInfo> group_info;
+ p_node->get_groups(&group_info);
+ for (List<Node::GroupInfo>::Element *E=group_info.front();E;E=E->next()) {
+
+ if (E->get().persistent)
+ node->add_to_group(E->get().name,true);
+ }
+
+
+ node->set_name(p_node->get_name());
+ duplimap[p_node]=node;
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ Node *child = p_node->get_child(i);
+ if (p_node->get_owner()!=child->get_owner())
+ continue; //don't bother with not in-scene nodes.
+
+ Node *dup = _duplicate(child,duplimap);
+ if (!dup) {
+ memdelete(node);
+ return NULL;
+ }
+
+ node->add_child(dup);
+ }
+
+ return node;
+
+}
+
+
+void SceneTreeDock::_set_owners(Node *p_owner, const Array& p_nodes) {
+
+ for(int i=0;i<p_nodes.size();i++) {
+
+ Object *obj=p_nodes[i];
+ if (!obj)
+ continue;
+
+ Node *n=obj->cast_to<Node>();
+ if (!n)
+ continue;
+ n->set_owner(p_owner);
+ }
+}
+
+
+void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path,Vector<StringName> new_base_path,Node * p_node, List<Pair<NodePath,NodePath> > *p_renames) {
+
+ base_path.push_back(p_node->get_name());
+ if (new_base_path.size())
+ new_base_path.push_back(p_node->get_name());
+
+ NodePath from( base_path,true );
+ NodePath to;
+ if (new_base_path.size())
+ to=NodePath( new_base_path,true );
+
+ Pair<NodePath,NodePath> npp;
+ npp.first=from;
+ npp.second=to;
+
+ p_renames->push_back(npp);
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ _fill_path_renames(base_path,new_base_path,p_node->get_child(i),p_renames);
+ }
+
+
+}
+
+void SceneTreeDock::fill_path_renames(Node* p_node, Node *p_new_parent, List<Pair<NodePath,NodePath> > *p_renames) {
+
+ if (!bool(EDITOR_DEF("editors/animation/autorename_animation_tracks",true)))
+ return;
+
+
+ Vector<StringName> base_path;
+ Node *n = p_node->get_parent();
+ while(n) {
+ base_path.push_back(n->get_name());
+ n=n->get_parent();
+ }
+ base_path.invert();
+
+ Vector<StringName> new_base_path;
+ if (p_new_parent) {
+ n = p_new_parent;
+ while(n) {
+ new_base_path.push_back(n->get_name());
+ n=n->get_parent();
+ }
+
+ new_base_path.invert();
+ }
+
+ _fill_path_renames(base_path,new_base_path,p_node,p_renames);
+}
+
+void SceneTreeDock::perform_node_renames(Node* p_base,List<Pair<NodePath,NodePath> > *p_renames, Map<Ref<Animation>, Set<int> > *r_rem_anims) {
+
+ Map<Ref<Animation>, Set<int> > rem_anims;
+
+ if (!r_rem_anims)
+ r_rem_anims=&rem_anims;
+
+ if (!bool(EDITOR_DEF("editors/animation/autorename_animation_tracks",true)))
+ return;
+
+ if (!p_base) {
+
+ p_base=edited_scene;
+ }
+
+ if (!p_base)
+ return;
+
+
+ if (p_base->cast_to<AnimationPlayer>()) {
+
+ AnimationPlayer *ap=p_base->cast_to<AnimationPlayer>();
+ List<StringName> anims;
+ ap->get_animation_list(&anims);
+ Node *root = ap->get_node(ap->get_root());
+
+
+ if (root) {
+
+
+ NodePath root_path=root->get_path();
+ NodePath new_root_path=root_path;
+
+
+ for(List<Pair<NodePath,NodePath> >::Element* E=p_renames->front();E;E=E->next()) {
+
+ if (E->get().first==root_path) {
+ new_root_path=E->get().second;
+ break;
+ }
+ }
+
+ if (new_root_path!=NodePath()) {
+ //will not be erased
+
+ for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
+
+ Ref<Animation> anim=ap->get_animation(E->get());
+ if (!r_rem_anims->has(anim)) {
+ r_rem_anims->insert(anim,Set<int>());
+ Set<int> &ran = r_rem_anims->find(anim)->get();
+ for(int i=0;i<anim->get_track_count();i++)
+ ran.insert(i);
+ }
+
+ Set<int> &ran = r_rem_anims->find(anim)->get();
+
+ if (anim.is_null())
+ continue;
+
+ for(int i=0;i<anim->get_track_count();i++) {
+
+ NodePath track_np=anim->track_get_path(i);
+ Node *n = root->get_node(track_np);
+ if (!n) {
+ continue;
+ }
+
+ NodePath old_np = n->get_path();
+
+ if (!ran.has(i))
+ continue; //channel was removed
+
+ for(List<Pair<NodePath,NodePath> >::Element* E=p_renames->front();E;E=E->next()) {
+
+ if (E->get().first==old_np) {
+
+
+ if (E->get().second==NodePath()) {
+ //will be erased
+
+ int idx=0;
+ Set<int>::Element *EI=ran.front();
+ ERR_FAIL_COND(!EI); //bug
+ while(EI->get()!=i) {
+ idx++;
+ EI=EI->next();
+ ERR_FAIL_COND(!EI); //another bug
+
+ }
+
+ editor_data->get_undo_redo().add_do_method(anim.ptr(),"remove_track",idx);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(),"add_track",anim->track_get_type(i),idx);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_path",idx,track_np);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_interpolation_type",idx,anim->track_get_interpolation_type(i));
+ for(int j=0;j<anim->track_get_key_count(i);j++) {
+
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_insert_key",idx,anim->track_get_key_time(i,j),anim->track_get_key_value(i,j),anim->track_get_key_transition(i,j));
+ }
+
+ ran.erase(i); //byebye channel
+
+ } else {
+ //will be renamed
+ NodePath rel_path = new_root_path.rel_path_to(E->get().second);
+
+ NodePath new_path = NodePath( rel_path.get_names(), track_np.get_subnames(), false, track_np.get_property() );
+ if (new_path==track_np)
+ continue; //bleh
+ editor_data->get_undo_redo().add_do_method(anim.ptr(),"track_set_path",i,new_path);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_path",i,track_np);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ for(int i=0;i<p_base->get_child_count();i++)
+ perform_node_renames(p_base->get_child(i),p_renames,r_rem_anims);
+
+}
+
+
+void SceneTreeDock::_node_prerenamed(Node* p_node, const String& p_new_name) {
+
+
+ List<Pair<NodePath,NodePath> > path_renames;
+
+ Vector<StringName> base_path;
+ Node *n = p_node->get_parent();
+ while(n) {
+ base_path.push_back(n->get_name());
+ n=n->get_parent();
+ }
+ base_path.invert();
+
+
+ Vector<StringName> new_base_path=base_path;
+ base_path.push_back(p_node->get_name());
+
+ new_base_path.push_back(p_new_name);
+
+ Pair<NodePath,NodePath> npp;
+ npp.first = NodePath(base_path,true);
+ npp.second = NodePath(new_base_path,true);
+ path_renames.push_back(npp);
+
+
+ for(int i=0;i<p_node->get_child_count();i++)
+ _fill_path_renames(base_path,new_base_path,p_node->get_child(i),&path_renames);
+
+ perform_node_renames(NULL,&path_renames);
+
+}
+
+bool SceneTreeDock::_validate_no_foreign() {
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ for (List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+ if (E->get()!=edited_scene && E->get()->get_owner()!=edited_scene) {
+
+ accept->get_ok()->set_text(TTR("Makes Sense!"));
+ accept->set_text(TTR("Can't operate on nodes from a foreign scene!"));
+ accept->popup_centered_minsize();
+ return false;
+
+ }
+
+ 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(TTR("Makes Sense!"));
+ accept->set_text(TTR("Can't operate on nodes the current scene inherits from!"));
+ accept->popup_centered_minsize();
+ return false;
+
+ }
+
+ }
+
+ return true;
+}
+
+void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
+
+
+ Node *new_parent = scene_root->get_node(p_path);
+ ERR_FAIL_COND(!new_parent);
+
+ //ok all valid
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ if (selection.empty())
+ return; //nothing to reparent
+
+ Vector<Node*> nodes;
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+ nodes.push_back(E->get());
+ }
+
+ _do_reparent(new_parent,-1,nodes,p_keep_global_xform);
+
+}
+
+
+void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vector<Node*> p_nodes,bool p_keep_global_xform) {
+
+
+ Node *new_parent = p_new_parent;
+ ERR_FAIL_COND(!new_parent);
+
+ Node *validate=new_parent;
+ while(validate) {
+
+ if (p_nodes.find(validate)!=-1) {
+ ERR_EXPLAIN("Selection changed at some point.. can't reparent");
+ ERR_FAIL();
+ return;
+ }
+ validate=validate->get_parent();
+ }
+
+ //ok all valid
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ if (p_nodes.size()==0)
+ return; //nothing to reparent
+
+ //sort by tree order, so re-adding is easy
+ p_nodes.sort_custom<Node::Comparator>();
+
+ editor_data->get_undo_redo().create_action(TTR("Reparent Node"));
+
+ List<Pair<NodePath,NodePath> > path_renames;
+ Vector<StringName> former_names;
+
+ int inc=0;
+
+ for(int ni=0;ni<p_nodes.size();ni++) {
+
+ //no undo for now, sorry
+ Node *node = p_nodes[ni];
+
+ fill_path_renames(node,new_parent,&path_renames);
+ former_names.push_back(node->get_name());
+
+ List<Node*> owned;
+ node->get_owned_by(node->get_owner(),&owned);
+ Array owners;
+ for(List<Node*>::Element *E=owned.front();E;E=E->next()) {
+
+ owners.push_back(E->get());
+ }
+
+
+ if (new_parent==node->get_parent() && node->get_index() < p_position_in_parent+ni) {
+ //if child will generate a gap when moved, adjust
+ inc--;
+ }
+
+ editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node);
+ editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node);
+
+ if (p_position_in_parent>=0)
+ editor_data->get_undo_redo().add_do_method(new_parent,"move_child",node,p_position_in_parent+inc);
+
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ String new_name = new_parent->validate_child_name(node);
+ 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>())
+ 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 (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);
+ editor_data->get_undo_redo().add_undo_method(node,"set_name",former_names[ni]);
+
+ inc++;
+
+ }
+
+ //add and move in a second step.. (so old order is preserved)
+
+
+
+ for(int ni=0;ni<p_nodes.size();ni++) {
+
+ Node *node = p_nodes[ni];
+
+ List<Node*> owned;
+ node->get_owned_by(node->get_owner(),&owned);
+ Array owners;
+ for(List<Node*>::Element *E=owned.front();E;E=E->next()) {
+
+ owners.push_back(E->get());
+ }
+
+ int child_pos = node->get_position_in_parent();
+
+ 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 (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>())
+ editor_data->get_undo_redo().add_undo_method(node,"set_pos",node->cast_to<Control>()->get_pos());
+ }
+
+
+
+ }
+
+ perform_node_renames(NULL,&path_renames);
+
+ editor_data->get_undo_redo().commit_action();
+ //node->set_owner(owner);
+}
+
+void SceneTreeDock::_script_created(Ref<Script> p_script) {
+
+ Node *selected = scene_tree->get_selected();
+ if (!selected)
+ return;
+ selected->set_script(p_script.get_ref_ptr());
+ editor->push_item(p_script.operator->());
+ button_create_script->hide();
+ button_clear_script->show();
+
+}
+
+
+void SceneTreeDock::_delete_confirm() {
+
+ List<Node*> remove_list = editor_selection->get_selected_node_list();
+
+ if (remove_list.empty())
+ return;
+
+
+ editor->get_editor_plugins_over()->make_visible(false);
+
+ editor_data->get_undo_redo().create_action(TTR("Remove Node(s)"));
+
+ bool entire_scene=false;
+
+ for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
+
+ if (E->get()==edited_scene) {
+ entire_scene=true;
+ }
+ }
+
+ if (entire_scene) {
+
+ editor_data->get_undo_redo().add_do_method(editor,"set_edited_scene",(Object*)NULL);
+ editor_data->get_undo_redo().add_undo_method(editor,"set_edited_scene",edited_scene);
+ editor_data->get_undo_redo().add_undo_method(edited_scene,"set_owner",edited_scene->get_owner());
+ editor_data->get_undo_redo().add_undo_reference(edited_scene);
+
+ } else {
+
+ remove_list.sort_custom<Node::Comparator>(); //sort nodes to keep positions
+ List<Pair<NodePath,NodePath> > path_renames;
+
+
+ //delete from animation
+ for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
+ Node *n = E->get();
+ if (!n->is_inside_tree() || !n->get_parent())
+ continue;
+
+ fill_path_renames(n,NULL,&path_renames);
+
+ }
+
+ perform_node_renames(NULL,&path_renames);
+ //delete for read
+ for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
+ Node *n = E->get();
+ if (!n->is_inside_tree() || !n->get_parent())
+ continue;
+
+ List<Node*> owned;
+ n->get_owned_by(n->get_owner(),&owned);
+ Array owners;
+ for(List<Node*>::Element *E=owned.front();E;E=E->next()) {
+
+ owners.push_back(E->get());
+ }
+
+
+ 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 (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);
+
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed,"live_debug_remove_and_keep_node",edited_scene->get_path_to(n),n->get_instance_ID());
+ editor_data->get_undo_redo().add_undo_method(sed,"live_debug_restore_node",n->get_instance_ID(),edited_scene->get_path_to(n->get_parent()),n->get_index());
+
+ }
+
+
+ }
+ editor_data->get_undo_redo().commit_action();
+
+
+}
+
+
+
+
+void SceneTreeDock::_selection_changed() {
+
+ int selection_size = EditorNode::get_singleton()->get_editor_selection()->get_selection().size();
+ if (selection_size>1) {
+ //automatically turn on multi-edit
+ _tool_selected(TOOL_MULTI_EDIT);
+ }
+
+ if (selection_size==1) {
+ if(EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) {
+ button_create_script->show();
+ button_clear_script->hide();
+ }
+ else {
+ button_create_script->hide();
+ button_clear_script->show();
+ }
+ } else {
+ button_create_script->hide();
+ button_clear_script->hide();
+ }
+
+ //tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
+
+}
+
+
+void SceneTreeDock::_create() {
+
+
+ if (current_option==TOOL_NEW) {
+
+ Node *parent=NULL;
+
+
+ if (edited_scene) {
+ // If root exists in edited scene
+ parent = scene_tree->get_selected();
+ if( !parent )
+ parent = edited_scene;
+
+ } else {
+ // If no root exist in edited scene
+ parent = scene_root;
+ ERR_FAIL_COND(!parent);
+ }
+
+ Object *c = create_dialog->instance_selected();
+
+ ERR_FAIL_COND(!c);
+ Node *child=c->cast_to<Node>();
+ ERR_FAIL_COND(!child);
+
+ editor_data->get_undo_redo().create_action(TTR("Create Node"));
+
+ if (edited_scene) {
+
+ editor_data->get_undo_redo().add_do_method(parent,"add_child",child);
+ editor_data->get_undo_redo().add_do_method(child,"set_owner",edited_scene);
+ editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
+ editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",child);
+ editor_data->get_undo_redo().add_do_reference(child);
+ editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child);
+
+
+ String new_name = parent->validate_child_name(child);
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",edited_scene->get_path_to(parent),child->get_class(),new_name);
+ editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name));
+
+ } else {
+
+ editor_data->get_undo_redo().add_do_method(editor,"set_edited_scene",child);
+ editor_data->get_undo_redo().add_do_reference(child);
+ editor_data->get_undo_redo().add_undo_method(editor,"set_edited_scene",(Object*)NULL);
+
+ }
+
+ editor_data->get_undo_redo().commit_action();
+ editor->push_item(c);
+
+ if (c->cast_to<Control>()) {
+ //make editor more comfortable, so some controls don't appear super shrunk
+ Control *ct = c->cast_to<Control>();
+
+ Size2 ms = ct->get_minimum_size();
+ if (ms.width<4)
+ ms.width=40;
+ if (ms.height<4)
+ ms.height=40;
+ ct->set_size(ms);
+ }
+
+
+ } else if (current_option==TOOL_REPLACE) {
+ Node * n = scene_tree->get_selected();
+ ERR_FAIL_COND(!n);
+
+ Object *c = create_dialog->instance_selected();
+
+ ERR_FAIL_COND(!c);
+ Node *newnode=c->cast_to<Node>();
+ ERR_FAIL_COND(!newnode);
+
+ List<PropertyInfo> pinfo;
+ n->get_property_list(&pinfo);
+
+ for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+ if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
+ continue;
+ newnode->set(E->get().name,n->get(E->get().name));
+ }
+
+ editor->push_item(NULL);
+
+ //reconnect signals
+ List<MethodInfo> sl;
+
+ n->get_signal_list(&sl);
+ for (List<MethodInfo>::Element *E=sl.front();E;E=E->next()) {
+
+ List<Object::Connection> cl;
+ n->get_signal_connection_list(E->get().name,&cl);
+
+ for(List<Object::Connection>::Element *F=cl.front();F;F=F->next()) {
+
+ Object::Connection &c=F->get();
+ if (!(c.flags&Object::CONNECT_PERSIST))
+ continue;
+ newnode->connect(c.signal,c.target,c.method,varray(),Object::CONNECT_PERSIST);
+ }
+
+ }
+
+ String newname=n->get_name();
+
+ List<Node*> to_erase;
+ for(int i=0;i<n->get_child_count();i++) {
+ if (n->get_child(i)->get_owner()==NULL && n->is_owned_by_parent()) {
+ to_erase.push_back(n->get_child(i));
+ }
+ }
+ n->replace_by(newnode,true);
+
+ if (n==edited_scene) {
+ edited_scene=newnode;
+ editor->set_edited_scene(newnode);
+ newnode->set_editable_instances(n->get_editable_instances());
+ }
+
+ //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);
+
+ while(to_erase.front()) {
+ memdelete(to_erase.front()->get());
+ to_erase.pop_front();
+ }
+
+
+
+ }
+
+}
+
+
+void SceneTreeDock::set_edited_scene(Node* p_scene) {
+
+ edited_scene=p_scene;
+}
+
+void SceneTreeDock::set_selected(Node *p_node, bool p_emit_selected ) {
+
+ scene_tree->set_selected(p_node,p_emit_selected);
+
+}
+
+void SceneTreeDock::import_subscene() {
+
+ import_subscene_dialog->popup_centered_ratio();
+}
+
+void SceneTreeDock::_import_subscene() {
+
+ Node* parent = scene_tree->get_selected();
+ if (!parent) {
+ parent = editor_data->get_edited_scene_root();
+ ERR_FAIL_COND(!parent);
+ }
+
+ import_subscene_dialog->move(parent,edited_scene);
+ editor_data->get_undo_redo().clear_history(); //no undo for now..
+
+
+/*
+ editor_data->get_undo_redo().create_action("Import Subscene");
+ editor_data->get_undo_redo().add_do_method(parent,"add_child",ss);
+ //editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
+ //editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",child);
+ editor_data->get_undo_redo().add_do_reference(ss);
+ editor_data->get_undo_redo().add_undo_method(parent,"remove_child",ss);
+ editor_data->get_undo_redo().commit_action();
+*/
+}
+
+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(TTR("I see.."));
+ accept->set_text(TTR("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(TTR("I see.."));
+ accept->set_text(TTR("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("filesystem/on_save/compress_binary_resources"))
+ flg|=ResourceSaver::FLAG_COMPRESS;
+ /*
+ if (EditorSettings::get_singleton()->get("filesystem/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(TTR("I see.."));
+ accept->set_text(TTR("Error saving scene."));
+ accept->popup_centered_minsize();
+ return;
+ }
+ _replace_with_branch_scene(p_file, base);
+ } else {
+ accept->get_ok()->set_text(TTR("I see.."));
+ accept->set_text(TTR("Error duplicating scene to save it."));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+}
+
+static bool _is_node_visible(Node* p_node) {
+
+ if (!p_node->get_owner())
+ return false;
+ if (p_node->get_owner()!=EditorNode::get_singleton()->get_edited_scene() && !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node->get_owner()))
+ return false;
+
+ return true;
+
+}
+
+static bool _has_visible_children(Node* p_node) {
+
+ bool collapsed = p_node->is_displayed_folded();
+ if (collapsed)
+ return false;
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ Node* child = p_node->get_child(i);
+ if (!_is_node_visible(child))
+ continue;
+
+ return true;
+ }
+
+ return false;
+
+}
+
+
+
+static Node* _find_last_visible(Node* p_node) {
+
+ Node* last=NULL;
+
+ bool collapsed = p_node->is_displayed_folded();
+
+ if (!collapsed) {
+ for(int i=0;i<p_node->get_child_count();i++) {
+ if (_is_node_visible(p_node->get_child(i))) {
+ last=p_node->get_child(i);
+ }
+ }
+ }
+
+ if (last) {
+ Node* lastc=_find_last_visible(last);
+ if (lastc)
+ last=lastc;
+
+
+ } else {
+ last=p_node;
+ }
+
+ return last;
+}
+
+
+void SceneTreeDock::_normalize_drop(Node*& to_node, int &to_pos, int p_type) {
+
+ to_pos=-1;
+
+ if (p_type==-1) {
+ //drop at above selected node
+ if (to_node==EditorNode::get_singleton()->get_edited_scene()) {
+ to_node=NULL;
+ ERR_EXPLAIN("Cannot perform drop above the root node!");
+ ERR_FAIL();
+ }
+
+ to_pos=to_node->get_index();
+ to_node=to_node->get_parent();
+
+ } else if (p_type==1) {
+ //drop at below selected node
+ if (to_node==EditorNode::get_singleton()->get_edited_scene()) {
+ //if at lower sibling of root node
+ to_pos=0; //just insert at begining of root node
+ return;
+ }
+
+
+ Node* lower_sibling=NULL;
+
+
+
+ if (_has_visible_children(to_node) ) {
+ to_pos=0;
+ } else {
+
+
+ for(int i=to_node->get_index()+1;i<to_node->get_parent()->get_child_count();i++) {
+ Node *c =to_node->get_parent()->get_child(i);
+ if (_is_node_visible(c)) {
+ lower_sibling=c;
+ break;
+ }
+ }
+ if (lower_sibling) {
+ to_pos=lower_sibling->get_index();
+ }
+
+ to_node=to_node->get_parent();
+
+
+ }
+#if 0
+ //quite complicated, look for next visible in tree
+ upper_sibling=_find_last_visible(upper_sibling);
+
+ if (upper_sibling->get_parent()==to_node->get_parent()) {
+ //just insert over this node because nothing is above at an upper level
+ to_pos=to_node->get_index();
+ to_node=to_node->get_parent();
+ } else {
+ to_pos=-1; //insert last in whathever is up
+ to_node=upper_sibling->get_parent(); //insert at a parent of whathever is up
+ }
+
+
+ } else {
+ //just insert over this node because nothing is above at the same level
+ to_pos=to_node->get_index();
+ to_node=to_node->get_parent();
+ }
+#endif
+
+ }
+
+}
+
+void SceneTreeDock::_files_dropped(Vector<String> p_files,NodePath p_to,int p_type) {
+
+ Node *node = get_node(p_to);
+ ERR_FAIL_COND(!node);
+
+ int to_pos=-1;
+ _normalize_drop(node,to_pos,p_type);
+ _perform_instance_scenes(p_files,node,to_pos);
+}
+
+void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
+ Ref<Script> scr = ResourceLoader::load(p_file);
+ ERR_FAIL_COND(!scr.is_valid());
+ Node *n = get_node(p_to);
+ if (n) {
+ n->set_script(scr.get_ref_ptr());
+ }
+}
+
+void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) {
+
+ Vector<Node*> nodes;
+ Node *to_node;
+
+ for(int i=0;i<p_nodes.size();i++) {
+ Node *n=get_node((p_nodes[i]));
+ if (n) {
+ nodes.push_back(n);
+ }
+ }
+
+ if (nodes.size()==0)
+ return;
+
+ to_node=get_node(p_to);
+ if (!to_node)
+ return;
+
+ int to_pos=-1;
+
+ _normalize_drop(to_node,to_pos,p_type);
+ _do_reparent(to_node,to_pos,nodes,true);
+
+}
+
+void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) {
+ if (!EditorNode::get_singleton()->get_edited_scene()) {
+
+ menu->clear();
+ menu->add_icon_shortcut(get_icon("Add","EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
+ menu->add_icon_shortcut(get_icon("Instance","EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
+
+ menu->set_size(Size2(1,1));
+ menu->set_pos(p_menu_pos);
+ menu->popup();
+ return;
+ }
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ if (selection.size()==0)
+ return;
+
+ menu->clear();
+
+
+ if (selection.size()==1) {
+ menu->add_icon_shortcut(get_icon("Add","EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
+ menu->add_icon_shortcut(get_icon("Instance","EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Reload","EditorIcons"),ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
+ //menu->add_separator(); moved to their own dock
+ //menu->add_icon_item(get_icon("Groups","EditorIcons"),TTR("Edit Groups"),TOOL_GROUP);
+ //menu->add_icon_item(get_icon("Connect","EditorIcons"),TTR("Edit Connections"),TOOL_CONNECT);
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
+ menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
+ menu->add_separator();
+ }
+
+ menu->add_icon_shortcut(get_icon("Up","EditorIcons"),ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
+ menu->add_icon_shortcut(get_icon("Down","EditorIcons"),ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
+ menu->add_icon_shortcut(get_icon("Duplicate","EditorIcons"),ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
+ menu->add_icon_shortcut(get_icon("Reparent","EditorIcons"),ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
+
+ if (selection.size()==1) {
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Blend","EditorIcons"),ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
+ menu->add_icon_shortcut(get_icon("CreateNewSceneFrom","EditorIcons"),ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("CopyNodePath","EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
+ }
+ menu->add_separator();
+ menu->add_icon_shortcut(get_icon("Remove","EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
+ menu->set_size(Size2(1,1));
+ menu->set_pos(p_menu_pos);
+ menu->popup();
+
+}
+
+
+void SceneTreeDock::_filter_changed(const String& p_filter) {
+
+ scene_tree->set_filter(p_filter);
+}
+
+String SceneTreeDock::get_filter() {
+
+ return filter->get_text();
+}
+
+void SceneTreeDock::set_filter(const String& p_filter){
+
+ filter->set_text(p_filter);
+ scene_tree->set_filter(p_filter);
+}
+
+
+void SceneTreeDock::_focus_node() {
+
+ Node *node = scene_tree->get_selected();
+ ERR_FAIL_COND(!node);
+
+ if (node->is_class("CanvasItem")) {
+ CanvasItemEditorPlugin *editor = editor_data->get_editor("2D")->cast_to<CanvasItemEditorPlugin>();
+ editor->get_canvas_item_editor()->focus_selection();
+ } else {
+ SpatialEditorPlugin *editor = editor_data->get_editor("3D")->cast_to<SpatialEditorPlugin>();
+ editor->get_spatial_editor()->get_editor_viewport(0)->focus_selection();
+ }
+}
+
+void SceneTreeDock::open_script_dialog(Node* p_for_node) {
+
+ scene_tree->set_selected(p_for_node,false);
+ _tool_selected(TOOL_ATTACH_SCRIPT);
+}
+
+void SceneTreeDock::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_tool_selected"),&SceneTreeDock::_tool_selected,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("_create"),&SceneTreeDock::_create);
+ //ClassDB::bind_method(D_METHOD("_script_created"),&SceneTreeDock::_script_created);
+ ClassDB::bind_method(D_METHOD("_node_reparent"),&SceneTreeDock::_node_reparent);
+ ClassDB::bind_method(D_METHOD("_set_owners"),&SceneTreeDock::_set_owners);
+ ClassDB::bind_method(D_METHOD("_node_selected"),&SceneTreeDock::_node_selected);
+ ClassDB::bind_method(D_METHOD("_node_renamed"),&SceneTreeDock::_node_renamed);
+ ClassDB::bind_method(D_METHOD("_script_created"),&SceneTreeDock::_script_created);
+ ClassDB::bind_method(D_METHOD("_load_request"),&SceneTreeDock::_load_request);
+ ClassDB::bind_method(D_METHOD("_script_open_request"),&SceneTreeDock::_script_open_request);
+ ClassDB::bind_method(D_METHOD("_unhandled_key_input"),&SceneTreeDock::_unhandled_key_input);
+ ClassDB::bind_method(D_METHOD("_input"),&SceneTreeDock::_input);
+ ClassDB::bind_method(D_METHOD("_nodes_drag_begin"),&SceneTreeDock::_nodes_drag_begin);
+ ClassDB::bind_method(D_METHOD("_delete_confirm"),&SceneTreeDock::_delete_confirm);
+ ClassDB::bind_method(D_METHOD("_node_prerenamed"),&SceneTreeDock::_node_prerenamed);
+ ClassDB::bind_method(D_METHOD("_import_subscene"),&SceneTreeDock::_import_subscene);
+ ClassDB::bind_method(D_METHOD("_selection_changed"),&SceneTreeDock::_selection_changed);
+ ClassDB::bind_method(D_METHOD("_new_scene_from"),&SceneTreeDock::_new_scene_from);
+ ClassDB::bind_method(D_METHOD("_nodes_dragged"),&SceneTreeDock::_nodes_dragged);
+ ClassDB::bind_method(D_METHOD("_files_dropped"),&SceneTreeDock::_files_dropped);
+ ClassDB::bind_method(D_METHOD("_script_dropped"),&SceneTreeDock::_script_dropped);
+ ClassDB::bind_method(D_METHOD("_tree_rmb"),&SceneTreeDock::_tree_rmb);
+ ClassDB::bind_method(D_METHOD("_filter_changed"),&SceneTreeDock::_filter_changed);
+ ClassDB::bind_method(D_METHOD("_focus_node"),&SceneTreeDock::_focus_node);
+
+
+ ClassDB::bind_method(D_METHOD("instance"),&SceneTreeDock::instance);
+}
+
+
+
+SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelection *p_editor_selection,EditorData &p_editor_data) {
+
+ editor=p_editor;
+ edited_scene=NULL;
+ editor_data=&p_editor_data;
+ editor_selection=p_editor_selection;
+ scene_root=p_scene_root;
+
+ VBoxContainer *vbc = this;
+
+ HBoxContainer *filter_hbc = memnew( HBoxContainer );
+ ToolButton *tb;
+
+ ED_SHORTCUT("scene_tree/add_child_node",TTR("Add Child Node"), KEY_MASK_CMD|KEY_A);
+ ED_SHORTCUT("scene_tree/instance_scene",TTR("Instance Child Scene"));
+ ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type"));
+ ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script"));
+ ED_SHORTCUT("scene_tree/clear_script", TTR("Clear Script"));
+ ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KEY_MASK_CMD | KEY_UP);
+ ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KEY_MASK_CMD | KEY_DOWN);
+ ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"),KEY_MASK_CMD | KEY_D);
+ ED_SHORTCUT("scene_tree/reparent", TTR("Reparent"));
+ ED_SHORTCUT("scene_tree/merge_from_scene", TTR("Merge From Scene"));
+ ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene"));
+ ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KEY_MASK_CMD|KEY_C);
+ ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KEY_MASK_SHIFT|KEY_DELETE);
+ ED_SHORTCUT("scene_tree/delete", TTR("Delete"), KEY_DELETE);
+
+ tb = memnew( ToolButton );
+ tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_NEW, false));
+ tb->set_tooltip(TTR("Add/Create a New Node"));
+ tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_child_node"));
+ filter_hbc->add_child(tb);
+ button_add=tb;
+
+ tb = memnew( ToolButton );
+ tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_INSTANCE, false));
+ tb->set_tooltip(TTR("Instance a scene file as a Node. Creates an inherited scene if no root node exists."));
+ tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/instance_scene"));
+ filter_hbc->add_child(tb);
+ button_instance=tb;
+
+
+
+ vbc->add_child(filter_hbc);
+ filter = memnew( LineEdit );
+ filter->set_h_size_flags(SIZE_EXPAND_FILL);
+ filter_hbc->add_child(filter);
+ filter_icon = memnew( TextureRect );
+ filter_hbc->add_child(filter_icon);
+ filter_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+ filter->connect("text_changed",this,"_filter_changed");
+
+
+ tb = memnew( ToolButton );
+ tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_ATTACH_SCRIPT, false));
+ tb->set_tooltip(TTR("Attach a new or existing script for the selected node."));
+ tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script"));
+ filter_hbc->add_child(tb);
+ button_create_script=tb;
+
+ tb = memnew(ToolButton);
+ tb->connect("pressed", this, "_tool_selected", make_binds(TOOL_CLEAR_SCRIPT, false));
+ tb->set_tooltip(TTR("Clear a script for the selected node."));
+ tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/clear_script"));
+ filter_hbc->add_child(tb);
+ button_clear_script = tb;
+
+
+ scene_tree = memnew( SceneTreeEditor(false,true,true ));
+ vbc->add_child(scene_tree);
+ scene_tree->set_v_size_flags(SIZE_EXPAND|SIZE_FILL);
+ scene_tree->connect("rmb_pressed",this,"_tree_rmb");
+
+ scene_tree->connect("node_selected", this,"_node_selected",varray(),CONNECT_DEFERRED);
+ scene_tree->connect("node_renamed", this,"_node_renamed",varray(),CONNECT_DEFERRED);
+ scene_tree->connect("node_prerename", this,"_node_prerenamed");
+ scene_tree->connect("open",this,"_load_request");
+ scene_tree->connect("open_script",this,"_script_open_request");
+ scene_tree->connect("nodes_rearranged",this,"_nodes_dragged");
+ scene_tree->connect("files_dropped",this,"_files_dropped");
+ scene_tree->connect("script_dropped",this,"_script_dropped");
+ scene_tree->connect("nodes_dragged",this,"_nodes_drag_begin");
+
+ scene_tree->get_scene_tree()->connect("item_double_clicked", this, "_focus_node");
+
+ scene_tree->set_undo_redo(&editor_data->get_undo_redo());
+ scene_tree->set_editor_selection(editor_selection);
+
+
+ create_dialog = memnew( CreateDialog );
+ create_dialog->set_base_type("Node");
+ add_child(create_dialog);
+ create_dialog->connect("create",this,"_create");
+
+ //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");
+
+ accept = memnew( AcceptDialog );
+ add_child(accept);
+
+ file = memnew( EditorFileDialog );
+ add_child(file);
+ file->connect("file_selected",this,"instance");
+ set_process_unhandled_key_input(true);
+
+ 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");
+
+
+ menu = memnew( PopupMenu );
+ add_child(menu);
+ menu->connect("id_pressed",this,"_tool_selected");
+ first_enter=true;
+ restore_script_editor_on_drag=false;
+
+ vbc->add_constant_override("separation",4);
+ set_process_input(true);
+}
diff --git a/tools/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 2ee7ba3d06..2ee7ba3d06 100644
--- a/tools/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
new file mode 100644
index 0000000000..fb21747ebb
--- /dev/null
+++ b/editor/scene_tree_editor.cpp
@@ -0,0 +1,1316 @@
+/*************************************************************************/
+/* scene_tree_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "scene_tree_editor.h"
+
+#include "scene/gui/label.h"
+#include "editor_node.h"
+#include "print_string.h"
+#include "message_queue.h"
+#include "scene/main/viewport.h"
+#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "scene/resources/packed_scene.h"
+
+Node *SceneTreeEditor::get_scene_node() {
+
+ ERR_FAIL_COND_V(!is_inside_tree(),NULL);
+
+ return get_tree()->get_edited_scene_root();
+}
+
+
+void SceneTreeEditor::_subscene_option(int p_idx) {
+
+ Object *obj = ObjectDB::get_instance(instance_node);
+ if (!obj)
+ return;
+ Node *node = obj->cast_to<Node>();
+ if (!node)
+ return;
+
+ switch(p_idx) {
+
+ case SCENE_MENU_EDITABLE_CHILDREN: {
+
+ bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node);
+ editable = !editable;
+
+ //node->set_instance_children_editable(editable);
+ EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node,editable);
+ instance_menu->set_item_checked(0,editable);
+ if (editable) {
+ node->set_scene_instance_load_placeholder(false);
+ instance_menu->set_item_checked(1,false);
+ }
+
+ _update_tree();
+
+ } break;
+ case SCENE_MENU_USE_PLACEHOLDER: {
+
+ bool placeholder = node->get_scene_instance_load_placeholder();
+ placeholder = !placeholder;
+
+ //node->set_instance_children_editable(editable);
+ if (placeholder) {
+ EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node,false);
+ }
+ node->set_scene_instance_load_placeholder(placeholder);
+ instance_menu->set_item_checked(0,false);
+ instance_menu->set_item_checked(1,placeholder);
+
+ _update_tree();
+
+ } break;
+ case SCENE_MENU_OPEN: {
+
+ emit_signal("open",node->get_filename());
+ } break;
+ case SCENE_MENU_CLEAR_INHERITANCE: {
+ clear_inherit_confirm->popup_centered_minsize();
+ } break;
+ case SCENE_MENU_CLEAR_INSTANCING: {
+
+ Node*root=EditorNode::get_singleton()->get_edited_scene();
+ if (!root)
+ break;
+
+
+ ERR_FAIL_COND(node->get_filename()==String());
+
+ undo_redo->create_action("Discard Instancing");
+
+ undo_redo->add_do_method(node,"set_filename","");
+ undo_redo->add_undo_method(node,"set_filename",node->get_filename());
+
+ _node_replace_owner(node,node,root);
+
+ undo_redo->add_do_method(this,"update_tree");
+ undo_redo->add_undo_method(this,"update_tree");
+
+ undo_redo->commit_action();
+
+
+ } break;
+ case SCENE_MENU_OPEN_INHERITED: {
+ if (node && node->get_scene_inherited_state().is_valid()) {
+ emit_signal("open",node->get_scene_inherited_state()->get_path());
+ }
+ } break;
+ case SCENE_MENU_CLEAR_INHERITANCE_CONFIRM: {
+ if (node && node->get_scene_inherited_state().is_valid()) {
+ node->set_scene_inherited_state(Ref<SceneState>());
+ update_tree();
+ EditorNode::get_singleton()->get_property_editor()->update_tree();
+ }
+
+ } break;
+
+
+ }
+
+}
+
+
+void SceneTreeEditor::_node_replace_owner(Node* p_base,Node* p_node,Node* p_root) {
+
+ if (p_base!=p_node) {
+
+ if (p_node->get_owner()==p_base) {
+
+ undo_redo->add_do_method(p_node,"set_owner",p_root);
+ undo_redo->add_undo_method(p_node,"set_owner",p_base);
+ }
+ }
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ _node_replace_owner(p_base,p_node->get_child(i),p_root);
+ }
+}
+
+
+void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id) {
+
+ TreeItem *item=p_item->cast_to<TreeItem>();
+ ERR_FAIL_COND(!item);
+
+ NodePath np = item->get_metadata(0);
+
+ Node *n=get_node(np);
+ ERR_FAIL_COND(!n);
+
+ if (p_id==BUTTON_SUBSCENE) {
+ //open scene request
+ Rect2 item_rect = tree->get_item_rect(item,0);
+ item_rect.pos.y-=tree->get_scroll().y;
+ item_rect.pos+=tree->get_global_pos();
+
+ if (n==get_scene_node()) {
+ inheritance_menu->set_pos(item_rect.pos+Vector2(0,item_rect.size.y));
+ inheritance_menu->set_size(Vector2(item_rect.size.x,0));
+ inheritance_menu->popup();
+ instance_node=n->get_instance_ID();
+
+ } else {
+ instance_menu->set_pos(item_rect.pos+Vector2(0,item_rect.size.y));
+ instance_menu->set_size(Vector2(item_rect.size.x,0));
+ if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(n))
+ instance_menu->set_item_checked(0,true);
+ else
+ instance_menu->set_item_checked(0,false);
+
+ if (n->get_owner()==get_scene_node()) {
+ instance_menu->set_item_checked(1,n->get_scene_instance_load_placeholder());
+ instance_menu->set_item_disabled(1,false);
+ } else {
+
+ instance_menu->set_item_checked(1,false);
+ instance_menu->set_item_disabled(1,true);
+ }
+
+ instance_menu->popup();
+ instance_node=n->get_instance_ID();
+ }
+ //emit_signal("open",n->get_filename());
+ } else if (p_id==BUTTON_SCRIPT) {
+ RefPtr script=n->get_script();
+ if (!script.is_null())
+ emit_signal("open_script",script);
+
+ } else if (p_id==BUTTON_VISIBILITY) {
+
+
+ if (n->is_class("Spatial")) {
+
+ bool v = bool(n->call("is_visible"));
+ undo_redo->create_action(TTR("Toggle Spatial Visible"));
+ undo_redo->add_do_method(n,"set_visible",!v);
+ undo_redo->add_undo_method(n,"set_visible",v);
+ undo_redo->commit_action();
+
+ } else if (n->is_class("CanvasItem")) {
+
+ bool v = bool(n->call("is_visible"));
+ undo_redo->create_action(TTR("Toggle CanvasItem Visible"));
+ undo_redo->add_do_method(n,v?"hide":"show");
+ undo_redo->add_undo_method(n,v?"show":"hide");
+ undo_redo->commit_action();
+ }
+
+ } else if (p_id==BUTTON_LOCK) {
+
+ if (n->is_class("CanvasItem")) {
+ n->set_meta("_edit_lock_", Variant());
+ _update_tree();
+ emit_signal("node_changed");
+ }
+
+ } else if (p_id==BUTTON_GROUP) {
+ if (n->is_class("CanvasItem")) {
+ n->set_meta("_edit_group_", Variant());
+ _update_tree();
+ emit_signal("node_changed");
+ }
+ } else if (p_id==BUTTON_WARNING) {
+
+ String config_err = n->get_configuration_warning();
+ if (config_err==String())
+ return;
+ config_err=config_err.word_wrap(80);
+ warning->set_text(config_err);
+ warning->popup_centered_minsize();
+
+ } else if (p_id==BUTTON_SIGNALS) {
+
+ editor_selection->clear();
+ editor_selection->add_node(n);
+
+ set_selected(n);
+
+ NodeDock::singleton->get_parent()->call("set_current_tab",NodeDock::singleton->get_index());
+ NodeDock::singleton->show_connections();
+
+ } else if (p_id==BUTTON_GROUPS) {
+
+ editor_selection->clear();
+ editor_selection->add_node(n);
+
+ set_selected(n);
+
+ NodeDock::singleton->get_parent()->call("set_current_tab",NodeDock::singleton->get_index());
+ NodeDock::singleton->show_groups();
+ }
+}
+
+bool SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
+
+ if (!p_node)
+ return false;
+
+ // only owned nodes are editable, since nodes can create their own (manually owned) child nodes,
+ // which the editor needs not to know about.
+
+ bool part_of_subscene=false;
+
+ if (!display_foreign && p_node->get_owner()!=get_scene_node() && p_node!=get_scene_node()) {
+
+ if ((show_enabled_subscene || can_open_instance) && p_node->get_owner() && (get_scene_node()->is_editable_instance(p_node->get_owner()))) {
+
+ part_of_subscene=true;
+ //allow
+ } else {
+ return false;
+ }
+ } else {
+ part_of_subscene = p_node!=get_scene_node() && get_scene_node()->get_scene_inherited_state().is_valid() && get_scene_node()->get_scene_inherited_state()->find_node_by_path(get_scene_node()->get_path_to(p_node))>=0;
+ }
+
+ TreeItem *item = tree->create_item(p_parent);
+ item->set_text(0, p_node->get_name() );
+ if (can_rename && !part_of_subscene /*(p_node->get_owner() == get_scene_node() || p_node==get_scene_node())*/)
+ item->set_editable(0, true);
+
+ item->set_selectable(0,true);
+ if (can_rename) {
+#ifdef ENABLE_DEPRECATED
+ if (p_node->has_meta("_editor_collapsed")) {
+ //remove previous way of storing folding, which did not get along with scene inheritance and instancing
+ if ((bool)p_node->get_meta("_editor_collapsed"))
+ p_node->set_display_folded(true);
+ p_node->set_meta("_editor_collapsed",Variant());
+ }
+#endif
+ bool collapsed = p_node->is_displayed_folded();
+ if (collapsed)
+ item->set_collapsed(true);
+ }
+
+ Ref<Texture> icon;
+ if (p_node->has_meta("_editor_icon"))
+ icon=p_node->get_meta("_editor_icon");
+ else
+ icon=get_icon( (has_icon(p_node->get_class(),"EditorIcons")?p_node->get_class():String("Object")),"EditorIcons");
+ item->set_icon(0, icon );
+ item->set_metadata( 0,p_node->get_path() );
+
+ if (part_of_subscene) {
+
+ //item->set_selectable(0,marked_selectable);
+ item->set_custom_color(0,Color(0.8,0.4,0.20));
+
+ } else if (marked.has(p_node)) {
+
+ item->set_selectable(0,marked_selectable);
+ item->set_custom_color(0,Color(0.8,0.1,0.10));
+ } else if (!marked_selectable && !marked_children_selectable) {
+
+ Node *node=p_node;
+ while(node) {
+ if (marked.has(node)) {
+ item->set_selectable(0,false);
+ item->set_custom_color(0,Color(0.8,0.1,0.10));
+ break;
+ }
+ node=node->get_parent();
+ }
+ }
+
+
+
+ if (can_rename) { //should be can edit..
+
+ String warning = p_node->get_configuration_warning();
+ if (warning!=String()) {
+ item->add_button(0,get_icon("NodeWarning","EditorIcons"),BUTTON_WARNING);
+ }
+
+ bool has_connections = p_node->has_persistent_signal_connections();
+ bool has_groups = p_node->has_persistent_groups();
+
+ if (has_connections && has_groups) {
+ item->add_button(0,get_icon("ConnectionAndGroups","EditorIcons"),BUTTON_SIGNALS);
+ } else if (has_connections) {
+ item->add_button(0,get_icon("Connect","EditorIcons"),BUTTON_SIGNALS);
+ } else if (has_groups) {
+ item->add_button(0,get_icon("Groups","EditorIcons"),BUTTON_GROUPS);
+ }
+ }
+
+ if (p_node==get_scene_node() && p_node->get_scene_inherited_state().is_valid()) {
+ item->add_button(0,get_icon("InstanceOptions","EditorIcons"),BUTTON_SUBSCENE);
+ item->set_tooltip(0,TTR("Inherits:")+" "+p_node->get_scene_inherited_state()->get_path()+"\n"+TTR("Type:")+" "+p_node->get_class());
+ } else if (p_node!=get_scene_node() && p_node->get_filename()!="" && can_open_instance) {
+
+ item->add_button(0,get_icon("InstanceOptions","EditorIcons"),BUTTON_SUBSCENE);
+ item->set_tooltip(0,TTR("Instance:")+" "+p_node->get_filename()+"\n"+TTR("Type:")+" "+p_node->get_class());
+ } else {
+ item->set_tooltip(0,String(p_node->get_name())+"\n"+TTR("Type:")+" "+p_node->get_class());
+ }
+
+ if (can_open_instance) {
+
+ if (!p_node->is_connected("script_changed",this,"_node_script_changed"))
+ p_node->connect("script_changed",this,"_node_script_changed",varray(p_node));
+
+
+ if (!p_node->get_script().is_null()) {
+
+ item->add_button(0,get_icon("Script","EditorIcons"),BUTTON_SCRIPT);
+ }
+
+ if (p_node->is_class("CanvasItem")) {
+
+ bool is_locked = p_node->has_meta("_edit_lock_");//_edit_group_
+ if (is_locked)
+ item->add_button(0,get_icon("Lock", "EditorIcons"), BUTTON_LOCK);
+
+ bool is_grouped = p_node->has_meta("_edit_group_");
+ if (is_grouped)
+ item->add_button(0,get_icon("Group", "EditorIcons"), BUTTON_GROUP);
+
+ bool v = p_node->call("is_visible");
+ if (v)
+ item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY);
+ else
+ item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
+
+ if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
+ p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
+
+ _update_visibility_color(p_node, item);
+ } else if (p_node->is_class("Spatial")) {
+
+ bool v = p_node->call("is_visible");
+ if (v)
+ item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY);
+ else
+ item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
+
+ if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
+ p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
+
+ _update_visibility_color(p_node, item);
+ }
+
+ }
+
+ if (editor_selection) {
+ if (editor_selection->is_selected(p_node)) {
+
+ item->select(0);
+ }
+ }
+
+ if (selected==p_node) {
+ if (!editor_selection)
+ item->select(0);
+ item->set_as_cursor(0);
+ }
+
+ bool keep= (filter.is_subsequence_ofi(String(p_node->get_name())));
+
+ for (int i=0;i<p_node->get_child_count();i++) {
+
+ bool child_keep = _add_nodes(p_node->get_child(i),item);
+
+ keep = keep || child_keep;
+
+ }
+
+ if (!keep) {
+ memdelete(item);
+ return false;
+ } else {
+ return true;
+ }
+
+}
+
+
+void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
+
+
+ if (p_node!=get_scene_node() && !p_node->get_owner()) {
+
+ return;
+ }
+ TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
+ if (!item) {
+
+ return;
+ }
+ int idx=item->get_button_by_id(0,BUTTON_VISIBILITY);
+ ERR_FAIL_COND(idx==-1);
+
+ bool visible=false;
+
+ if (p_node->is_class("CanvasItem")) {
+ visible = p_node->call("is_visible");
+ CanvasItemEditor::get_singleton()->get_viewport_control()->update();
+ } else if (p_node->is_class("Spatial")) {
+ visible = p_node->call("is_visible");
+ }
+
+ if (visible)
+ item->set_button(0,idx,get_icon("Visible","EditorIcons"));
+ else
+ item->set_button(0,idx,get_icon("Hidden","EditorIcons"));
+
+ _update_visibility_color(p_node, item);
+}
+
+void SceneTreeEditor::_update_visibility_color(Node *p_node, TreeItem *p_item) {
+ if (p_node->is_class("CanvasItem") || p_node->is_class("Spatial")) {
+ Color color(1,1,1,1);
+ bool visible_on_screen = p_node->call("is_visible");
+ if (!visible_on_screen) {
+ color = Color(0.6,0.6,0.6,1);
+ }
+ int idx=p_item->get_button_by_id(0,BUTTON_VISIBILITY);
+ p_item->set_button_color(0,idx,color);
+ }
+}
+
+void SceneTreeEditor::_node_script_changed(Node *p_node) {
+
+ _update_tree();
+ /*
+ changes the order :|
+ TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
+ if (p_node->get_script().is_null()) {
+
+ int idx=item->get_button_by_id(0,2);
+ if (idx>=0)
+ item->erase_button(0,idx);
+ } else {
+
+ int idx=item->get_button_by_id(0,2);
+ if (idx<0)
+ item->add_button(0,get_icon("Script","EditorIcons"),2);
+
+ }*/
+
+}
+
+void SceneTreeEditor::_node_removed(Node *p_node) {
+
+ if (EditorNode::get_singleton()->is_exiting())
+ return; //speed up exit
+
+ if (p_node->is_connected("script_changed",this,"_node_script_changed"))
+ p_node->disconnect("script_changed",this,"_node_script_changed");
+
+ if (p_node->is_class("Spatial") || p_node->is_class("CanvasItem")) {
+ if (p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
+ p_node->disconnect("visibility_changed",this,"_node_visibility_changed");
+ }
+
+ if (p_node==selected) {
+ selected=NULL;
+ emit_signal("node_selected");
+ }
+
+
+}
+void SceneTreeEditor::_update_tree() {
+
+
+ if (!is_inside_tree()) {
+ tree_dirty=false;
+ return;
+ }
+
+ updating_tree=true;
+ tree->clear();
+ if (get_scene_node()) {
+ _add_nodes( get_scene_node(), NULL );
+ last_hash = hash_djb2_one_64(0);
+ _compute_hash(get_scene_node(),last_hash);
+
+ }
+ updating_tree=false;
+
+ tree_dirty=false;
+
+}
+
+void SceneTreeEditor::_compute_hash(Node *p_node,uint64_t &hash) {
+
+ hash=hash_djb2_one_64(p_node->get_instance_ID(),hash);
+ if (p_node->get_parent())
+ hash=hash_djb2_one_64(p_node->get_parent()->get_instance_ID(),hash); //so a reparent still produces a different hash
+
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ _compute_hash(p_node->get_child(i),hash);
+ }
+}
+
+void SceneTreeEditor::_test_update_tree() {
+
+ pending_test_update=false;
+
+ if (!is_inside_tree())
+ return;
+
+ if(tree_dirty)
+ return; // don't even bother
+
+ uint64_t hash = hash_djb2_one_64(0);
+ if (get_scene_node())
+ _compute_hash(get_scene_node(),hash);
+ //test hash
+ if (hash==last_hash)
+ return; // did not change
+
+ MessageQueue::get_singleton()->push_call(this,"_update_tree");
+ tree_dirty=true;
+}
+
+void SceneTreeEditor::_tree_changed() {
+
+ if (EditorNode::get_singleton()->is_exiting())
+ return; //speed up exit
+ if (pending_test_update)
+ return;
+ if (tree_dirty)
+ return;
+
+ MessageQueue::get_singleton()->push_call(this,"_test_update_tree");
+ pending_test_update=true;
+
+}
+
+void SceneTreeEditor::_selected_changed() {
+
+
+ TreeItem *s = tree->get_selected();
+ ERR_FAIL_COND(!s);
+ NodePath np = s->get_metadata(0);
+
+ Node *n=get_node(np);
+
+
+ if (n==selected)
+ return;
+
+
+ selected = get_node(np);
+
+ blocked++;
+ emit_signal("node_selected");
+ blocked--;
+
+
+}
+
+
+void SceneTreeEditor::_cell_multi_selected(Object *p_object,int p_cell,bool p_selected) {
+
+ TreeItem *item = p_object->cast_to<TreeItem>();
+ ERR_FAIL_COND(!item);
+
+ NodePath np = item->get_metadata(0);
+
+ Node *n=get_node(np);
+
+ if (!n)
+ return;
+
+ if (!editor_selection)
+ return;
+
+ if (p_selected) {
+ editor_selection->add_node(n);
+
+ } else {
+ editor_selection->remove_node(n);
+
+ }
+
+}
+
+void SceneTreeEditor::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ get_tree()->connect("tree_changed",this,"_tree_changed");
+ get_tree()->connect("node_removed",this,"_node_removed");
+ get_tree()->connect("node_configuration_warning_changed",this,"_warning_changed");
+
+ instance_menu->set_item_icon(5,get_icon("Load","EditorIcons"));
+ tree->connect("item_collapsed",this,"_cell_collapsed");
+ inheritance_menu->set_item_icon(2,get_icon("Load","EditorIcons"));
+ clear_inherit_confirm->connect("confirmed",this,"_subscene_option",varray(SCENE_MENU_CLEAR_INHERITANCE_CONFIRM));
+
+ EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed");
+
+
+ //get_scene()->connect("tree_changed",this,"_tree_changed",Vector<Variant>(),CONNECT_DEFERRED);
+ //get_scene()->connect("node_removed",this,"_node_removed",Vector<Variant>(),CONNECT_DEFERRED);
+ _update_tree();
+ }
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+
+ get_tree()->disconnect("tree_changed",this,"_tree_changed");
+ get_tree()->disconnect("node_removed",this,"_node_removed");
+ tree->disconnect("item_collapsed",this,"_cell_collapsed");
+ clear_inherit_confirm->disconnect("confirmed",this,"_subscene_option");
+ get_tree()->disconnect("node_configuration_warning_changed",this,"_warning_changed");
+ EditorSettings::get_singleton()->disconnect("settings_changed",this,"_editor_settings_changed");
+ }
+
+}
+
+
+TreeItem* SceneTreeEditor::_find(TreeItem *p_node,const NodePath& p_path) {
+
+ if (!p_node)
+ return NULL;
+
+ NodePath np=p_node->get_metadata(0);
+ if (np==p_path)
+ return p_node;
+
+ TreeItem *children=p_node->get_children();
+ while(children) {
+
+ TreeItem *n=_find(children,p_path);
+ if (n)
+ return n;
+ children=children->get_next();
+ }
+
+ return NULL;
+}
+
+void SceneTreeEditor::set_selected(Node *p_node,bool p_emit_selected) {
+
+ ERR_FAIL_COND(blocked>0);
+
+ if (pending_test_update)
+ _test_update_tree();
+ if (tree_dirty)
+ _update_tree();
+
+ if (selected==p_node)
+ return;
+
+
+ TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
+
+ if (item) {
+ // make visible when it's collapsed
+ TreeItem* node=item->get_parent();
+ while (node && node!=tree->get_root()) {
+ node->set_collapsed(false);
+ node=node->get_parent();
+ }
+ item->select(0);
+ item->set_as_cursor(0);
+ selected=p_node;
+ tree->ensure_cursor_is_visible();
+ } else {
+ if (!p_node)
+ selected=NULL;
+ _update_tree();
+ selected=p_node;
+ if (p_emit_selected)
+ emit_signal("node_selected");
+ }
+
+}
+
+void SceneTreeEditor::_rename_node(ObjectID p_node,const String& p_name) {
+
+ Object *o = ObjectDB::get_instance(p_node);
+ ERR_FAIL_COND(!o);
+ Node *n = o->cast_to<Node>();
+ ERR_FAIL_COND(!n);
+ TreeItem* item=_find(tree->get_root(),n->get_path());
+ ERR_FAIL_COND(!item);
+
+ n->set_name( p_name );
+ item->set_metadata(0,n->get_path());
+ item->set_text(0,p_name);
+ emit_signal("node_renamed");
+
+ if (!tree_dirty) {
+ MessageQueue::get_singleton()->push_call(this,"_update_tree");
+ tree_dirty=true;
+ }
+
+
+}
+
+
+void SceneTreeEditor::_renamed() {
+
+ TreeItem *which=tree->get_edited();
+
+ ERR_FAIL_COND(!which);
+ NodePath np = which->get_metadata(0);
+ Node *n=get_node(np);
+ ERR_FAIL_COND(!n);
+
+ String new_name=which->get_text(0);
+ if (new_name.find(".") != -1 || new_name.find("/") != -1) {
+
+ error->set_text(TTR("Invalid node name, the following characters are not allowed:")+"\n \".\", \"/\"");
+ error->popup_centered_minsize();
+ new_name=n->get_name();
+ }
+
+ if (new_name==n->get_name())
+ return;
+
+ if (!undo_redo) {
+ n->set_name( new_name );
+ which->set_metadata(0,n->get_path());
+ emit_signal("node_renamed");
+ } else {
+ undo_redo->create_action(TTR("Rename Node"));
+ emit_signal("node_prerename",n,new_name);
+ undo_redo->add_do_method(this,"_rename_node",n->get_instance_ID(),new_name);
+ undo_redo->add_undo_method(this,"_rename_node",n->get_instance_ID(),n->get_name());
+ undo_redo->commit_action();
+ }
+}
+
+
+Node *SceneTreeEditor::get_selected() {
+
+ return selected;
+}
+
+void SceneTreeEditor::set_marked(const Set<Node*>& p_marked,bool p_selectable,bool p_children_selectable) {
+
+ if (tree_dirty)
+ _update_tree();
+ marked=p_marked;
+ marked_selectable=p_selectable;
+ marked_children_selectable=p_children_selectable;
+ _update_tree();
+}
+
+void SceneTreeEditor::set_marked(Node *p_marked,bool p_selectable,bool p_children_selectable) {
+
+ Set<Node*> s;
+ if (p_marked)
+ s.insert(p_marked);
+ set_marked(s,p_selectable,p_children_selectable);
+
+
+}
+
+void SceneTreeEditor::set_filter(const String& p_filter) {
+
+ filter=p_filter;
+ _update_tree();
+}
+
+String SceneTreeEditor::get_filter() const {
+
+ return filter;
+}
+
+
+void SceneTreeEditor::set_display_foreign_nodes(bool p_display) {
+
+ display_foreign=p_display;
+ _update_tree();
+}
+bool SceneTreeEditor::get_display_foreign_nodes() const {
+
+ return display_foreign;
+}
+
+void SceneTreeEditor::set_editor_selection(EditorSelection *p_selection) {
+
+ editor_selection=p_selection;
+ tree->set_select_mode(Tree::SELECT_MULTI);
+ tree->set_cursor_can_exit_tree(false);
+ editor_selection->connect("selection_changed",this,"_selection_changed");
+}
+
+void SceneTreeEditor::_update_selection(TreeItem *item) {
+
+ ERR_FAIL_COND(!item);
+
+ NodePath np = item->get_metadata(0);
+
+ if (!has_node(np))
+ return;
+
+ Node *n=get_node(np);
+
+ if (!n)
+ return;
+
+ if (editor_selection->is_selected(n))
+ item->select(0);
+ else
+ item->deselect(0);
+
+ TreeItem *c=item->get_children();
+
+
+ while(c) {
+
+ _update_selection(c);
+ c=c->get_next();
+ }
+}
+
+void SceneTreeEditor::_selection_changed() {
+
+ if (!editor_selection)
+ return;
+
+ TreeItem *root=tree->get_root();
+
+ if (!root)
+ return;
+ _update_selection(root);
+}
+
+void SceneTreeEditor::_cell_collapsed(Object *p_obj) {
+
+ if (updating_tree)
+ return;
+ if (!can_rename)
+ return;
+
+ TreeItem *ti=p_obj->cast_to<TreeItem>();
+ if (!ti)
+ return;
+
+ bool collapsed=ti->is_collapsed();
+
+ NodePath np = ti->get_metadata(0);
+
+ Node *n=get_node(np);
+ ERR_FAIL_COND(!n);
+
+ n->set_display_folded(collapsed);
+
+}
+
+Variant SceneTreeEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+ if (!can_rename)
+ return Variant(); //not editable tree
+
+ Vector<Node*> selected;
+ Vector<Ref<Texture> > icons;
+ TreeItem *next=tree->get_next_selected(NULL);
+ while (next) {
+
+ NodePath np = next->get_metadata(0);
+
+ Node *n=get_node(np);
+ if (n) {
+
+ selected.push_back(n);
+ icons.push_back(next->get_icon(0));
+ }
+ next=tree->get_next_selected(next);
+ }
+
+ if (selected.empty())
+ return Variant();
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ Array objs;
+ int list_max = 10;
+ float opacity_step = 1.0f / list_max;
+ float opacity_item = 1.0f;
+ for(int i=0;i<selected.size();i++) {
+
+ if (i<list_max){
+ HBoxContainer *hb = memnew( HBoxContainer );
+ TextureRect *tf = memnew(TextureRect);
+ tf->set_texture(icons[i]);
+ hb->add_child(tf);
+ Label *label = memnew( Label( selected[i]->get_name() ) );
+ hb->add_child(label);
+ vb->add_child(hb);
+ hb->set_modulate(Color(1,1,1,opacity_item));
+ opacity_item -= opacity_step;
+ }
+ NodePath p = selected[i]->get_path();
+ objs.push_back(p);
+ }
+
+ set_drag_preview(vb);
+ Dictionary drag_data;
+ drag_data["type"]="nodes";
+ drag_data["nodes"]=objs;
+
+ tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN|Tree::DROP_MODE_ON_ITEM);
+ emit_signal("nodes_dragged");
+
+ return drag_data;
+}
+
+bool SceneTreeEditor::_is_script_type(const StringName &p_type) const {
+ return (script_types->find(p_type));
+}
+
+bool SceneTreeEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
+
+ if (!can_rename)
+ return false; //not editable tree
+ if (filter!=String())
+ return false; //can't rearrange tree with filter turned on
+
+
+ Dictionary d=p_data;
+ if (!d.has("type"))
+ return false;
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return false;
+
+ int section = tree->get_drop_section_at_pos(p_point);
+ if (section<-1 || (section==-1 && !item->get_parent()))
+ return false;
+
+ if (String(d["type"])=="files") {
+
+ Vector<String> files = d["files"];
+
+ if (files.size()==0)
+ return false; //weird
+
+ if (_is_script_type(EditorFileSystem::get_singleton()->get_file_type(files[0]))) {
+ tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
+ return true;
+ }
+
+ for(int i=0;i<files.size();i++) {
+ String file = files[i];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+ if (ftype!="PackedScene")
+ return false;
+ }
+
+ tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN|Tree::DROP_MODE_ON_ITEM); //so it works..
+
+ return true;
+ }
+
+
+ if (String(d["type"])=="nodes") {
+ return true;
+ }
+
+ return false;
+}
+void SceneTreeEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
+
+ if (!can_drop_data_fw(p_point,p_data,p_from))
+ return;
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return;
+ int section = tree->get_drop_section_at_pos(p_point);
+ if (section<-1)
+ return;
+
+ NodePath np = item->get_metadata(0);
+ Node *n=get_node(np);
+ if (!n)
+ return;
+
+ Dictionary d=p_data;
+
+ if (String(d["type"])=="nodes") {
+ Array nodes=d["nodes"];
+ emit_signal("nodes_rearranged",nodes,np,section);
+ }
+
+ if (String(d["type"])=="files") {
+
+ Vector<String> files = d["files"];
+
+
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(files[0]);
+ if (_is_script_type(ftype)) {
+ emit_signal("script_dropped", files[0],np);
+ } else {
+ emit_signal("files_dropped",files,np,section);
+ }
+ }
+
+}
+
+void SceneTreeEditor::_rmb_select(const Vector2& p_pos) {
+
+ emit_signal("rmb_pressed",tree->get_global_transform().xform(p_pos));
+}
+
+
+void SceneTreeEditor::_warning_changed(Node* p_for_node) {
+
+ //should use a timer
+ update_timer->start();
+ //print_line("WARNING CHANGED "+String(p_for_node->get_name()));
+
+}
+
+
+void SceneTreeEditor::_editor_settings_changed() {
+ bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines");
+ Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color");
+
+ if (enable_rl) {
+ tree->add_constant_override("draw_relationship_lines",1);
+ tree->add_color_override("relationship_line_color", rl_color);
+ }
+ else
+ tree->add_constant_override("draw_relationship_lines",0);
+
+}
+
+
+void SceneTreeEditor::_bind_methods() {
+
+ ClassDB::bind_method("_tree_changed",&SceneTreeEditor::_tree_changed);
+ ClassDB::bind_method("_update_tree",&SceneTreeEditor::_update_tree);
+ ClassDB::bind_method("_node_removed",&SceneTreeEditor::_node_removed);
+ ClassDB::bind_method("_selected_changed",&SceneTreeEditor::_selected_changed);
+ ClassDB::bind_method("_renamed",&SceneTreeEditor::_renamed);
+ ClassDB::bind_method("_rename_node",&SceneTreeEditor::_rename_node);
+ ClassDB::bind_method("_test_update_tree",&SceneTreeEditor::_test_update_tree);
+ ClassDB::bind_method("_cell_multi_selected",&SceneTreeEditor::_cell_multi_selected);
+ ClassDB::bind_method("_selection_changed",&SceneTreeEditor::_selection_changed);
+ ClassDB::bind_method("_cell_button_pressed",&SceneTreeEditor::_cell_button_pressed);
+ ClassDB::bind_method("_cell_collapsed",&SceneTreeEditor::_cell_collapsed);
+ ClassDB::bind_method("_subscene_option",&SceneTreeEditor::_subscene_option);
+ ClassDB::bind_method("_rmb_select",&SceneTreeEditor::_rmb_select);
+ ClassDB::bind_method("_warning_changed",&SceneTreeEditor::_warning_changed);
+
+ ClassDB::bind_method("_node_script_changed",&SceneTreeEditor::_node_script_changed);
+ ClassDB::bind_method("_node_visibility_changed",&SceneTreeEditor::_node_visibility_changed);
+
+ ClassDB::bind_method("_editor_settings_changed", &SceneTreeEditor::_editor_settings_changed);
+
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SceneTreeEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SceneTreeEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw"), &SceneTreeEditor::drop_data_fw);
+
+ ClassDB::bind_method(D_METHOD("update_tree"), &SceneTreeEditor::update_tree);
+
+ ADD_SIGNAL( MethodInfo("node_selected") );
+ ADD_SIGNAL( MethodInfo("node_renamed") );
+ ADD_SIGNAL( MethodInfo("node_prerename") );
+ ADD_SIGNAL( MethodInfo("node_changed") );
+ ADD_SIGNAL( MethodInfo("nodes_dragged") );
+ ADD_SIGNAL( MethodInfo("nodes_rearranged",PropertyInfo(Variant::ARRAY,"paths"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) );
+ ADD_SIGNAL( MethodInfo("files_dropped",PropertyInfo(Variant::POOL_STRING_ARRAY,"files"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) );
+ ADD_SIGNAL( MethodInfo("script_dropped",PropertyInfo(Variant::STRING,"file"),PropertyInfo(Variant::NODE_PATH,"to_path")));
+ ADD_SIGNAL( MethodInfo("rmb_pressed",PropertyInfo(Variant::VECTOR2,"pos")) ) ;
+
+ ADD_SIGNAL( MethodInfo("open") );
+ ADD_SIGNAL( MethodInfo("open_script") );
+
+
+}
+
+
+SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open_instance) {
+
+
+ undo_redo=NULL;
+ tree_dirty=true;
+ selected=NULL;
+
+ marked_selectable=false;
+ marked_children_selectable=false;
+ can_rename=p_can_rename;
+ can_open_instance=p_can_open_instance;
+ display_foreign=false;
+ editor_selection=NULL;
+
+ if (p_label) {
+ Label *label = memnew( Label );
+ label->set_pos( Point2(10, 0));
+ label->set_text(TTR("Scene Tree (Nodes):"));
+
+ add_child(label);
+ }
+
+ tree = memnew( Tree );
+ tree->set_anchor( MARGIN_RIGHT, ANCHOR_END );
+ tree->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
+ tree->set_begin( Point2(0,p_label?18:0 ));
+ tree->set_end( Point2(0,0 ));
+
+ add_child( tree );
+
+ tree->set_drag_forwarding(this);
+ if (p_can_rename) {
+ tree->set_allow_rmb_select(true);
+ tree->connect("item_rmb_selected",this,"_rmb_select");
+ tree->connect("empty_tree_rmb_selected",this,"_rmb_select");
+ }
+
+ tree->connect("cell_selected", this,"_selected_changed");
+ tree->connect("item_edited", this,"_renamed",varray(),CONNECT_DEFERRED);
+ tree->connect("multi_selected",this,"_cell_multi_selected");
+ tree->connect("button_pressed",this,"_cell_button_pressed");
+ //tree->connect("item_edited", this,"_renamed",Vector<Variant>(),true);
+
+ error = memnew( AcceptDialog );
+ add_child(error);
+
+ warning = memnew( AcceptDialog );
+ add_child(warning);
+ warning->set_title("Node Configuration Warning!");
+
+
+ show_enabled_subscene=false;
+
+ last_hash=0;
+ pending_test_update=false;
+ updating_tree=false;
+ blocked=0;
+
+ instance_menu = memnew( PopupMenu );
+ instance_menu->add_check_item(TTR("Editable Children"),SCENE_MENU_EDITABLE_CHILDREN);
+ instance_menu->add_check_item(TTR("Load As Placeholder"),SCENE_MENU_USE_PLACEHOLDER);
+ instance_menu->add_separator();
+ instance_menu->add_item(TTR("Discard Instancing"),SCENE_MENU_CLEAR_INSTANCING);
+ instance_menu->add_separator();
+ instance_menu->add_item(TTR("Open in Editor"),SCENE_MENU_OPEN);
+ instance_menu->connect("id_pressed",this,"_subscene_option");
+ add_child(instance_menu);
+
+ inheritance_menu = memnew( PopupMenu );
+ inheritance_menu->add_item(TTR("Clear Inheritance"),SCENE_MENU_CLEAR_INHERITANCE);
+ inheritance_menu->add_separator();
+ inheritance_menu->add_item(TTR("Open in Editor"),SCENE_MENU_OPEN_INHERITED);
+ inheritance_menu->connect("id_pressed",this,"_subscene_option");
+
+ add_child(inheritance_menu);
+
+ clear_inherit_confirm = memnew( ConfirmationDialog );
+ clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)"));
+ clear_inherit_confirm->get_ok()->set_text(TTR("Clear!"));
+ add_child(clear_inherit_confirm);
+
+ update_timer = memnew(Timer);
+ update_timer->connect("timeout",this,"_update_tree");
+ update_timer->set_one_shot(true);
+ update_timer->set_wait_time(0.5);
+ add_child(update_timer);
+
+ script_types = memnew(List<StringName>);
+ ClassDB::get_inheriters_from_class("Script", script_types);
+
+}
+
+
+
+SceneTreeEditor::~SceneTreeEditor() {
+
+ memdelete(script_types);
+}
+
+
+/******** DIALOG *********/
+
+void SceneTreeDialog::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ connect("confirmed", this,"_select");
+
+ }
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+ disconnect("confirmed", this,"_select");
+
+ }
+ if (p_what==NOTIFICATION_DRAW) {
+
+ RID ci = get_canvas_item();
+ get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
+ }
+
+ if (p_what==NOTIFICATION_VISIBILITY_CHANGED && is_visible_in_tree()) {
+
+ tree->update_tree();
+ }
+
+
+}
+
+void SceneTreeDialog::_cancel() {
+
+ hide();
+
+
+
+}
+void SceneTreeDialog::_select() {
+
+ if (tree->get_selected()) {
+ emit_signal("selected",tree->get_selected()->get_path());
+ hide();
+ }
+}
+
+void SceneTreeDialog::_bind_methods() {
+
+ ClassDB::bind_method("_select",&SceneTreeDialog::_select);
+ ClassDB::bind_method("_cancel",&SceneTreeDialog::_cancel);
+ ADD_SIGNAL( MethodInfo("selected",PropertyInfo(Variant::NODE_PATH,"path")));
+
+}
+
+
+SceneTreeDialog::SceneTreeDialog() {
+
+ set_title(TTR("Select a Node"));
+
+ tree = memnew( SceneTreeEditor(false,false) );
+ add_child(tree);
+ //set_child_rect(tree);
+
+ tree->get_scene_tree()->connect("item_activated",this,"_select");
+
+}
+
+
+SceneTreeDialog::~SceneTreeDialog()
+{
+}
diff --git a/tools/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 5586f02c00..5586f02c00 100644
--- a/tools/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
new file mode 100644
index 0000000000..dfaa1f645c
--- /dev/null
+++ b/editor/script_create_dialog.cpp
@@ -0,0 +1,437 @@
+/*************************************************************************/
+/* script_create_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "script_create_dialog.h"
+
+#include "script_language.h"
+#include "global_config.h"
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "editor_file_system.h"
+
+void ScriptCreateDialog::config(const String& p_base_name,const String&p_base_path) {
+
+ class_name->set_text("");
+ parent_name->set_text(p_base_name);
+ if (p_base_path!="") {
+ initial_bp=p_base_path.get_basename();
+ file_path->set_text(initial_bp+"."+ScriptServer::get_language( language_menu->get_selected() )->get_extension());
+ } else {
+ initial_bp="";
+ file_path->set_text("");
+ }
+ _class_name_changed("");
+ _path_changed(file_path->get_text());
+}
+
+bool ScriptCreateDialog::_validate(const String& p_string) {
+
+ if (p_string.length()==0)
+ return false;
+
+
+ for(int i=0;i<p_string.length();i++) {
+
+ if (i==0) {
+ if (p_string[0]>='0' && p_string[0]<='9')
+ return false; // no start with number plz
+ }
+
+ bool valid_char = (p_string[i]>='0' && p_string[i]<='9') || (p_string[i]>='a' && p_string[i]<='z') || (p_string[i]>='A' && p_string[i]<='Z') || p_string[i]=='_';
+
+ if (!valid_char)
+ return false;
+
+ }
+
+ return true;
+}
+
+void ScriptCreateDialog::_class_name_changed(const String& p_name) {
+
+ if (!_validate(parent_name->get_text())) {
+ error_label->set_text(TTR("Invalid parent class name"));
+ error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
+ } else if (class_name->is_editable()) {
+ if (class_name->get_text()=="") {
+ error_label->set_text(TTR("Valid chars:")+" a-z A-Z 0-9 _");
+ error_label->add_color_override("font_color",Color(1,1,1,0.6));
+ } else if (!_validate(class_name->get_text())) {
+ error_label->set_text(TTR("Invalid class name"));
+ error_label->add_color_override("font_color",Color(1,0.2,0.2,0.8));
+ } else {
+ error_label->set_text(TTR("Valid name"));
+ error_label->add_color_override("font_color",Color(0,1.0,0.8,0.8));
+ }
+ } else {
+
+ error_label->set_text(TTR("N/A"));
+ error_label->add_color_override("font_color",Color(0,1.0,0.8,0.8));
+ }
+}
+
+void ScriptCreateDialog::ok_pressed() {
+
+ if (create_new){
+ _create_new();
+ } else {
+ _load_exist();
+ }
+
+ create_new=true;
+ _update_controls();
+
+}
+
+void ScriptCreateDialog::_create_new() {
+
+ if (class_name->is_editable() && !_validate(class_name->get_text())) {
+ alert->set_text(TTR("Class name is invalid!"));
+ alert->popup_centered_minsize();
+ return;
+ }
+ if (!_validate(parent_name->get_text())) {
+ alert->set_text(TTR("Parent class name is invalid!"));
+ alert->popup_centered_minsize();
+ return;
+ }
+
+ String cname;
+ if (class_name->is_editable())
+ cname=class_name->get_text();
+
+ Ref<Script> scr = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text());
+
+ String selected_language = language_menu->get_item_text(language_menu->get_selected());
+ editor_settings->set_project_metadata("script_setup", "last_selected_language", selected_language);
+
+ if (cname!="")
+ scr->set_name(cname);
+
+ if (!internal->is_pressed()) {
+ String lpath = GlobalConfig::get_singleton()->localize_path(file_path->get_text());
+ scr->set_path(lpath);
+ if (!path_valid) {
+ alert->set_text(TTR("Invalid path!"));
+ alert->popup_centered_minsize();
+ return;
+ }
+ Error err = ResourceSaver::save(lpath,scr,ResourceSaver::FLAG_CHANGE_PATH);
+ if (err!=OK) {
+ alert->set_text(TTR("Could not create script in filesystem."));
+ alert->popup_centered_minsize();
+ return;
+ }
+ }
+
+ hide();
+ emit_signal("script_created",scr);
+
+}
+
+void ScriptCreateDialog::_load_exist() {
+
+ String path=file_path->get_text();
+ RES p_script = ResourceLoader::load(path, "Script");
+ if (p_script.is_null()) {
+ alert->get_ok()->set_text(TTR("Ugh"));
+ alert->set_text(vformat(TTR("Error loading script from %s"), path));
+ alert->popup_centered_minsize();
+ return;
+ }
+
+ hide();
+ emit_signal("script_created",p_script.get_ref_ptr());
+
+}
+
+void ScriptCreateDialog::_lang_changed(int l) {
+
+ l=language_menu->get_selected();
+ if (ScriptServer::get_language( l )->has_named_classes()) {
+ class_name->set_editable(true);
+ } else {
+ class_name->set_editable(false);
+ }
+
+ String selected_ext="."+ScriptServer::get_language( l )->get_extension();
+ String path=file_path->get_text();
+ String extension="";
+ if (path.find(".")>=0) {
+ extension=path.get_extension();
+ }
+
+ if (extension.length()==0) {
+ // add extension if none
+ path+=selected_ext;
+ _path_changed(path);
+ } else {
+ // change extension by selected language
+ List<String> extensions;
+ // get all possible extensions for script
+ for (int l=0;l<language_menu->get_item_count();l++) {
+ ScriptServer::get_language( l )->get_recognized_extensions(&extensions);
+ }
+
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+ if (E->get().nocasecmp_to(extension)==0) {
+ path=path.get_basename()+selected_ext;
+ _path_changed(path);
+ break;
+ }
+ }
+ }
+ file_path->set_text(path);
+ _class_name_changed(class_name->get_text());
+
+}
+
+void ScriptCreateDialog::_built_in_pressed() {
+
+ if (internal->is_pressed()) {
+ path_vb->hide();
+ } else {
+ path_vb->show();
+ }
+
+}
+
+void ScriptCreateDialog::_browse_path() {
+
+ file_browse->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ file_browse->set_disable_overwrite_warning(true);
+ file_browse->clear_filters();
+ List<String> extensions;
+
+ // get all possible extensions for script
+ for (int l=0;l<language_menu->get_item_count();l++) {
+ ScriptServer::get_language( l )->get_recognized_extensions(&extensions);
+ }
+
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+ file_browse->add_filter("*."+E->get());
+ }
+
+ file_browse->set_current_path(file_path->get_text());
+ file_browse->popup_centered_ratio();
+
+}
+
+void ScriptCreateDialog::_file_selected(const String& p_file) {
+
+ String p = GlobalConfig::get_singleton()->localize_path(p_file);
+ file_path->set_text(p);
+ _path_changed(p);
+
+}
+
+void ScriptCreateDialog::_path_changed(const String& p_path) {
+
+ path_valid=false;
+ String p =p_path;
+
+ if (p=="") {
+
+ path_error_label->set_text(TTR("Path is empty"));
+ path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
+ return;
+
+ }
+
+ p = GlobalConfig::get_singleton()->localize_path(p);
+ if (!p.begins_with("res://")) {
+
+ path_error_label->set_text(TTR("Path is not local"));
+ path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
+ return;
+ }
+
+ if (p.find("/") || p.find("\\")) {
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+
+ if (d->change_dir(p.get_base_dir())!=OK) {
+
+ path_error_label->set_text(TTR("Invalid base path"));
+ path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
+ memdelete(d);
+ return;
+
+ }
+ memdelete(d);
+ }
+
+ FileAccess *f = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+ create_new=!f->file_exists(p);
+ memdelete(f);
+
+ String extension=p.get_extension();
+ List<String> extensions;
+
+ // get all possible extensions for script
+ for (int l=0;l<language_menu->get_item_count();l++) {
+ ScriptServer::get_language( l )->get_recognized_extensions(&extensions);
+ }
+
+ bool found=false;
+ int index=0;
+ for(List<String>::Element *E=extensions.front();E;E=E->next()) {
+ if (E->get().nocasecmp_to(extension)==0) {
+ language_menu->select(index); // change Language option by extension
+ found=true;
+ break;
+ }
+ index++;
+ }
+
+ if (!found) {
+ path_error_label->set_text(TTR("Invalid extension"));
+ path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
+ return;
+ }
+
+ _update_controls();
+
+ path_error_label->add_color_override("font_color",Color(0,1.0,0.8,0.8));
+
+ path_valid=true;
+
+}
+
+void ScriptCreateDialog::_update_controls() {
+
+ if (create_new) {
+ path_error_label->set_text(TTR("Create new script"));
+ get_ok()->set_text(TTR("Create"));
+ } else {
+ path_error_label->set_text(TTR("Load existing script"));
+ get_ok()->set_text(TTR("Load"));
+ }
+ parent_name->set_editable(create_new);
+ internal->set_disabled(!create_new);
+
+}
+
+
+void ScriptCreateDialog::_bind_methods() {
+
+ ClassDB::bind_method("_class_name_changed",&ScriptCreateDialog::_class_name_changed);
+ ClassDB::bind_method("_lang_changed",&ScriptCreateDialog::_lang_changed);
+ ClassDB::bind_method("_built_in_pressed",&ScriptCreateDialog::_built_in_pressed);
+ ClassDB::bind_method("_browse_path",&ScriptCreateDialog::_browse_path);
+ ClassDB::bind_method("_file_selected",&ScriptCreateDialog::_file_selected);
+ ClassDB::bind_method("_path_changed",&ScriptCreateDialog::_path_changed);
+ ADD_SIGNAL(MethodInfo("script_created",PropertyInfo(Variant::OBJECT,"script",PROPERTY_HINT_RESOURCE_TYPE,"Script")));
+}
+
+ScriptCreateDialog::ScriptCreateDialog() {
+
+ /* SNAP DIALOG */
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ add_child(vb);
+ //set_child_rect(vb);
+
+
+ class_name = memnew( LineEdit );
+ VBoxContainer *vb2 = memnew( VBoxContainer );
+ vb2->add_child(class_name);
+ class_name->connect("text_changed", this,"_class_name_changed");
+ error_label = memnew(Label);
+ error_label->set_text("valid chars: a-z A-Z 0-9 _");
+ error_label->set_align(Label::ALIGN_CENTER);
+ vb2->add_child(error_label);
+ vb->add_margin_child(TTR("Class Name:"),vb2);
+
+ parent_name = memnew( LineEdit );
+ vb->add_margin_child(TTR("Inherits:"),parent_name);
+ parent_name->connect("text_changed", this,"_class_name_changed");
+
+ language_menu = memnew( OptionButton );
+ vb->add_margin_child(TTR("Language"),language_menu);
+
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+
+ language_menu->add_item(ScriptServer::get_language(i)->get_name());
+ }
+
+ editor_settings = EditorSettings::get_singleton();
+ String last_selected_language = editor_settings->get_project_metadata("script_setup", "last_selected_language", "");
+ if (last_selected_language != "")
+ for (int i = 0; i < language_menu->get_item_count(); i++)
+ if (language_menu->get_item_text(i) == last_selected_language)
+ {
+ language_menu->select(i);
+ break;
+ }
+ else language_menu->select(0);
+
+ language_menu->connect("item_selected",this,"_lang_changed");
+
+ //parent_name->set_text();
+
+ vb2 = memnew( VBoxContainer );
+ path_vb = memnew( VBoxContainer );
+ vb2->add_child(path_vb);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ file_path = memnew( LineEdit );
+ file_path->connect("text_changed",this,"_path_changed");
+ hbc->add_child(file_path);
+ file_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *b = memnew( Button );
+ b->set_text(" .. ");
+ b->connect("pressed",this,"_browse_path");
+ hbc->add_child(b);
+ path_vb->add_child(hbc);
+ path_error_label = memnew( Label );
+ path_vb->add_child( path_error_label );
+ path_error_label->set_text(TTR("Error!"));
+ path_error_label->set_align(Label::ALIGN_CENTER);
+
+
+ internal = memnew( CheckButton );
+ internal->set_text(TTR("Built-In Script"));
+ vb2->add_child(internal);
+ internal->connect("pressed",this,"_built_in_pressed");
+
+ vb->add_margin_child(TTR("Path:"),vb2);
+
+ set_size(Size2(200,150));
+ set_hide_on_ok(false);
+ set_title(TTR("Attach Node Script"));
+
+ file_browse = memnew( EditorFileDialog );
+ file_browse->connect("file_selected",this,"_file_selected");
+ add_child(file_browse);
+ get_ok()->set_text(TTR("Create"));
+ alert = memnew( AcceptDialog );
+ add_child(alert);
+ _lang_changed(0);
+
+ create_new=true;
+}
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
new file mode 100644
index 0000000000..ad9616c071
--- /dev/null
+++ b/editor/script_create_dialog.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* script_create_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SCRIPT_CREATE_DIALOG_H
+#define SCRIPT_CREATE_DIALOG_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/option_button.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/check_button.h"
+
+class ScriptCreateDialog : public ConfirmationDialog {
+ GDCLASS(ScriptCreateDialog,ConfirmationDialog);
+
+ LineEdit *class_name;
+ Label *error_label;
+ Label *path_error_label;
+ LineEdit *parent_name;
+ OptionButton *language_menu;
+ LineEdit *file_path;
+ EditorFileDialog *file_browse;
+ CheckButton *internal;
+ VBoxContainer *path_vb;
+ AcceptDialog *alert;
+ bool path_valid;
+ bool create_new;
+ String initial_bp;
+ EditorSettings *editor_settings;
+
+
+ void _path_changed(const String& p_path=String());
+ void _lang_changed(int l=0);
+ void _built_in_pressed();
+ bool _validate(const String& p_strin);
+ void _class_name_changed(const String& p_name);
+ void _browse_path();
+ void _file_selected(const String& p_file);
+ virtual void ok_pressed();
+ void _create_new();
+ void _load_exist();
+ void _update_controls();
+protected:
+
+ static void _bind_methods();
+public:
+
+ void config(const String& p_base_name,const String&p_base_path);
+
+ ScriptCreateDialog();
+};
+
+#endif // SCRIPT_CREATE_DIALOG_H
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
new file mode 100644
index 0000000000..fa33ffe5c7
--- /dev/null
+++ b/editor/script_editor_debugger.cpp
@@ -0,0 +1,1998 @@
+/*************************************************************************/
+/* script_editor_debugger.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "script_editor_debugger.h"
+
+#include "scene/gui/separator.h"
+#include "scene/gui/label.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/tree.h"
+#include "scene/gui/texture_button.h"
+#include "scene/gui/tab_container.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/rich_text_label.h"
+#include "scene/gui/margin_container.h"
+#include "property_editor.h"
+#include "global_config.h"
+#include "editor_node.h"
+#include "main/performance.h"
+#include "editor_profiler.h"
+#include "editor_settings.h"
+
+class ScriptEditorDebuggerVariables : public Object {
+
+ GDCLASS( ScriptEditorDebuggerVariables, Object );
+
+ List<PropertyInfo> props;
+ Map<StringName,Variant> values;
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ return false;
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const {
+
+ if (!values.has(p_name))
+ return false;
+ r_ret=values[p_name];
+ return true;
+ }
+ void _get_property_list( List<PropertyInfo> *p_list) const {
+
+ for(const List<PropertyInfo>::Element *E=props.front();E;E=E->next() )
+ p_list->push_back(E->get());
+ }
+
+
+public:
+
+
+ void clear() {
+
+ props.clear();
+ values.clear();
+ }
+
+ String get_var_value(const String& p_var) const {
+
+ for(Map<StringName,Variant>::Element *E=values.front();E;E=E->next()) {
+ String v = E->key().operator String().get_slice("/",1);
+ if (v==p_var)
+ return E->get();
+ }
+
+ return "";
+ }
+
+ void add_property(const String &p_name, const Variant& p_value) {
+
+ PropertyInfo pinfo;
+ pinfo.name=p_name;
+ pinfo.type=p_value.get_type();
+ props.push_back(pinfo);
+ values[p_name]=p_value;
+
+ }
+
+ void update() {
+ _change_notify();
+ }
+
+
+ ScriptEditorDebuggerVariables() {
+
+ }
+};
+
+
+class ScriptEditorDebuggerInspectedObject : public Object {
+
+ GDCLASS( ScriptEditorDebuggerInspectedObject, Object);
+
+
+
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value) {
+
+ if (!prop_values.has(p_name))
+ return false;
+
+ emit_signal("value_edited",p_name,p_value);
+ prop_values[p_name]=p_value;
+ return true;
+ }
+
+ bool _get(const StringName& p_name,Variant &r_ret) const {
+
+ if (!prop_values.has(p_name))
+ return false;
+
+ r_ret=prop_values[p_name];
+ return true;
+
+ }
+ void _get_property_list( List<PropertyInfo> *p_list) const {
+
+ p_list->clear(); //sorry, no want category
+ for (const List<PropertyInfo>::Element *E=prop_list.front();E;E=E->next()) {
+ p_list->push_back(E->get());
+ }
+ }
+
+
+ static void _bind_methods() {
+
+ ADD_SIGNAL(MethodInfo("value_edited"));
+ }
+
+public:
+
+ ObjectID last_edited_id;
+ List<PropertyInfo> prop_list;
+ Map<StringName,Variant> prop_values;
+
+ void update() {
+ _change_notify();
+ }
+
+ void update_single(const char* p_prop) {
+ _change_notify(p_prop);
+ }
+
+ ScriptEditorDebuggerInspectedObject() { last_edited_id=0; }
+
+
+};
+
+void ScriptEditorDebugger::debug_next() {
+
+ ERR_FAIL_COND(!breaked);
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+ Array msg;
+ msg.push_back("next");
+ ppeer->put_var(msg);
+ stack_dump->clear();
+ inspector->edit(NULL);
+
+}
+void ScriptEditorDebugger::debug_step() {
+
+ ERR_FAIL_COND(!breaked);
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+
+ Array msg;
+ msg.push_back("step");
+ ppeer->put_var(msg);
+ stack_dump->clear();
+ inspector->edit(NULL);
+}
+
+void ScriptEditorDebugger::debug_break() {
+
+ ERR_FAIL_COND(breaked);
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+
+ Array msg;
+ msg.push_back("break");
+ ppeer->put_var(msg);
+
+}
+
+void ScriptEditorDebugger::debug_continue() {
+
+ ERR_FAIL_COND(!breaked);
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+
+ OS::get_singleton()->enable_for_stealing_focus(EditorNode::get_singleton()->get_child_process_id());
+
+ Array msg;
+ msg.push_back("continue");
+ ppeer->put_var(msg);
+
+
+}
+
+void ScriptEditorDebugger::_scene_tree_folded(Object* obj) {
+
+
+ if (updating_scene_tree) {
+
+ return;
+ }
+ TreeItem *item=obj->cast_to<TreeItem>();
+
+ if (!item)
+ return;
+
+ ObjectID id = item->get_metadata(0);
+ if (item->is_collapsed()) {
+ unfold_cache.erase(id);
+ } else {
+ unfold_cache.insert(id);
+ }
+
+
+}
+
+void ScriptEditorDebugger::_scene_tree_selected() {
+
+
+ if (updating_scene_tree) {
+
+ return;
+ }
+ TreeItem *item = inspect_scene_tree->get_selected();
+ if (!item) {
+
+ return;
+ }
+
+ inspected_object_id = item->get_metadata(0);
+
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+
+}
+
+void ScriptEditorDebugger::_scene_tree_property_value_edited(const String& p_prop,const Variant& p_value) {
+
+
+ Array msg;
+ msg.push_back("set_object_property");
+ msg.push_back(inspected_object_id);
+ msg.push_back(p_prop);
+ msg.push_back(p_value);
+ ppeer->put_var(msg);
+ inspect_edited_object_timeout=0.7; //avoid annoyance, don't request soon after editing
+}
+
+void ScriptEditorDebugger::_scene_tree_property_select_object(ObjectID p_object) {
+
+ inspected_object_id=p_object;
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+
+}
+
+void ScriptEditorDebugger::_scene_tree_request() {
+
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+
+ Array msg;
+ msg.push_back("request_scene_tree");
+ ppeer->put_var(msg);
+
+}
+
+void ScriptEditorDebugger::_video_mem_request() {
+
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+
+ Array msg;
+ msg.push_back("request_video_mem");
+ ppeer->put_var(msg);
+
+}
+
+Size2 ScriptEditorDebugger::get_minimum_size() const {
+
+ Size2 ms = Control::get_minimum_size();
+ ms.y = MAX(ms.y , 250 );
+ return ms;
+
+}
+void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_data) {
+
+
+
+ if (p_msg=="debug_enter") {
+
+ Array msg;
+ msg.push_back("get_stack_dump");
+ ppeer->put_var(msg);
+ ERR_FAIL_COND(p_data.size()!=2);
+ bool can_continue=p_data[0];
+ String error = p_data[1];
+ step->set_disabled(!can_continue);
+ next->set_disabled(!can_continue);
+ reason->set_text(error);
+ reason->set_tooltip(error);
+ breaked=true;
+ dobreak->set_disabled(true);
+ docontinue->set_disabled(false);
+ emit_signal("breaked",true,can_continue);
+ OS::get_singleton()->move_window_to_foreground();
+ if (error!="") {
+ tabs->set_current_tab(0);
+ }
+
+ profiler->set_enabled(false);
+
+ EditorNode::get_singleton()->get_pause_button()->set_pressed(true);
+
+
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+
+ } else if (p_msg=="debug_exit") {
+
+ breaked=false;
+ step->set_disabled(true);
+ next->set_disabled(true);
+ reason->set_text("");
+ reason->set_tooltip("");
+ back->set_disabled(true);
+ forward->set_disabled(true);
+ dobreak->set_disabled(false);
+ docontinue->set_disabled(true);
+ emit_signal("breaked",false,false,Variant());
+ //tabs->set_current_tab(0);
+ profiler->set_enabled(true);
+ profiler->disable_seeking();
+
+ EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
+
+
+ } else if (p_msg=="message:click_ctrl") {
+
+ clicked_ctrl->set_text(p_data[0]);
+ clicked_ctrl_type->set_text(p_data[1]);
+
+ } else if (p_msg=="message:scene_tree") {
+
+ inspect_scene_tree->clear();
+ Map<int,TreeItem*> lv;
+
+ updating_scene_tree=true;
+
+ for(int i=0;i<p_data.size();i+=4) {
+
+ TreeItem *p;
+ int level = p_data[i];
+ if (level==0) {
+ p = NULL;
+ } else {
+ ERR_CONTINUE(!lv.has(level-1));
+ p=lv[level-1];
+ }
+
+
+ TreeItem *it = inspect_scene_tree->create_item(p);
+
+ ObjectID id = ObjectID(p_data[i+3]);
+
+ it->set_text(0,p_data[i+1]);
+ if (has_icon(p_data[i+2],"EditorIcons"))
+ it->set_icon(0,get_icon(p_data[i+2],"EditorIcons"));
+ it->set_metadata(0,id);
+ if (id==inspected_object_id) {
+ it->select(0);
+ }
+
+ if (p) {
+ if (!unfold_cache.has(id)) {
+ it->set_collapsed(true);
+ }
+ } else {
+ if (unfold_cache.has(id)) { //reverse for root
+ it->set_collapsed(true);
+ }
+ }
+ lv[level]=it;
+ }
+ updating_scene_tree=false;
+
+ le_clear->set_disabled(false);
+ le_set->set_disabled(false);
+ } else if (p_msg=="message:inspect_object") {
+
+
+ ObjectID id = p_data[0];
+ String type = p_data[1];
+ Variant path = p_data[2]; //what to do yet, i don't know
+ int prop_count=p_data[3];
+
+ int idx=4;
+
+
+ if (inspected_object->last_edited_id!=id) {
+ inspected_object->prop_list.clear();
+ inspected_object->prop_values.clear();
+ }
+
+ for(int i=0;i<prop_count;i++) {
+
+ PropertyInfo pinfo;
+ pinfo.name=p_data[idx++];
+ pinfo.type=Variant::Type(int(p_data[idx++]));
+ pinfo.hint=PropertyHint(int(p_data[idx++]));
+ pinfo.hint_string=p_data[idx++];
+ if (pinfo.name.begins_with("*")) {
+ pinfo.name=pinfo.name.substr(1,pinfo.name.length());
+ pinfo.usage=PROPERTY_USAGE_CATEGORY;
+ } else {
+ pinfo.usage=PROPERTY_USAGE_EDITOR;
+ }
+
+ if (inspected_object->last_edited_id!=id) {
+ //don't update.. it's the same, instead refresh
+ inspected_object->prop_list.push_back(pinfo);
+ }
+
+
+ inspected_object->prop_values[pinfo.name]=p_data[idx++];
+
+ if (inspected_object->last_edited_id==id) {
+ //same, just update value, don't rebuild
+ inspected_object->update_single(pinfo.name.ascii().get_data());
+ }
+
+ }
+
+
+
+ if (inspected_object->last_edited_id!=id) {
+ //only if different
+ inspected_object->update();
+ }
+
+ inspected_object->last_edited_id=id;
+
+
+ inspect_properties->edit(inspected_object);
+
+ } else if (p_msg=="message:video_mem") {
+
+ vmem_tree->clear();
+ TreeItem* root=vmem_tree->create_item();
+
+ int total=0;
+
+ for(int i=0;i<p_data.size();i+=4) {
+
+ TreeItem *it = vmem_tree->create_item(root);
+ String type=p_data[i+1];
+ int bytes=p_data[i+3].operator int();
+ it->set_text(0,p_data[i+0]); //path
+ it->set_text(1,type); //type
+ it->set_text(2,p_data[i+2]); //type
+ it->set_text(3,String::humanize_size(bytes)); //type
+ total+=bytes;
+
+ if (has_icon(type,"EditorIcons"))
+ it->set_icon(0,get_icon(type,"EditorIcons"));
+ }
+
+ vmem_total->set_tooltip(TTR("Bytes:")+" "+itos(total));
+ vmem_total->set_text(String::humanize_size(total));
+
+ } else if (p_msg=="stack_dump") {
+
+ stack_dump->clear();
+ TreeItem *r = stack_dump->create_item();
+
+ for(int i=0;i<p_data.size();i++) {
+
+ Dictionary d = p_data[i];
+ ERR_CONTINUE(!d.has("function"));
+ ERR_CONTINUE(!d.has("file"));
+ ERR_CONTINUE(!d.has("line"));
+ ERR_CONTINUE(!d.has("id"));
+ TreeItem *s = stack_dump->create_item(r);
+ d["frame"]=i;
+ s->set_metadata(0,d);
+
+ //String line = itos(i)+" - "+String(d["file"])+":"+itos(d["line"])+" - at func: "+d["function"];
+ String line = itos(i)+" - "+String(d["file"])+":"+itos(d["line"]);
+ s->set_text(0,line);
+
+ if (i==0)
+ s->select(0);
+ }
+ } else if (p_msg=="stack_frame_vars") {
+
+
+ variables->clear();
+
+
+
+ int ofs =0;
+ int mcount = p_data[ofs];
+
+ ofs++;
+ for(int i=0;i<mcount;i++) {
+
+ String n = p_data[ofs+i*2+0];
+ Variant v = p_data[ofs+i*2+1];
+
+ if (n.begins_with("*")) {
+
+ n=n.substr(1,n.length());
+ }
+
+ variables->add_property("members/"+n,v);
+ }
+ ofs+=mcount*2;
+
+ mcount = p_data[ofs];
+
+ ofs++;
+ for(int i=0;i<mcount;i++) {
+
+ String n = p_data[ofs+i*2+0];
+ Variant v = p_data[ofs+i*2+1];
+
+ if (n.begins_with("*")) {
+
+ n=n.substr(1,n.length());
+ }
+
+
+ variables->add_property("locals/"+n,v);
+ }
+
+ variables->update();
+ inspector->edit(variables);
+
+ } else if (p_msg=="output") {
+
+ //OUT
+ for(int i=0;i<p_data.size();i++) {
+
+ String t = p_data[i];
+ //LOG
+
+ if (!EditorNode::get_log()->is_visible()) {
+ if (EditorNode::get_singleton()->are_bottom_panels_hidden()) {
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log());
+ }
+ }
+ EditorNode::get_log()->add_message(t);
+
+ }
+
+ } else if (p_msg=="performance") {
+ Array arr = p_data[0];
+ Vector<float> p;
+ p.resize(arr.size());
+ for(int i=0;i<arr.size();i++) {
+ p[i]=arr[i];
+ if (i<perf_items.size()) {
+ perf_items[i]->set_text(1,rtos(p[i]));
+ if (p[i]>perf_max[i])
+ perf_max[i]=p[i];
+ }
+
+ }
+ perf_history.push_front(p);
+ perf_draw->update();
+
+ } else if (p_msg=="error") {
+
+ Array err = p_data[0];
+
+ Array vals;
+ vals.push_back(err[0]);
+ vals.push_back(err[1]);
+ vals.push_back(err[2]);
+ vals.push_back(err[3]);
+
+ bool warning = err[9];
+ bool e;
+ String time = String("%d:%02d:%02d:%04d").sprintf(vals,&e);
+ String txt=time+" - "+(err[8].is_zero()?String(err[7]):String(err[8]));
+
+ String tooltip=TTR("Type:")+String(warning?TTR("Warning"):TTR("Error"));
+ tooltip+="\n"+TTR("Description:")+" "+String(err[8]);
+ tooltip+="\n"+TTR("Time:")+" "+time;
+ tooltip+="\nC "+TTR("Error:")+" "+String(err[7]);
+ tooltip+="\nC "+TTR("Source:")+" "+String(err[5])+":"+String(err[6]);
+ tooltip+="\nC "+TTR("Function:")+" "+String(err[4]);
+
+
+
+ error_list->add_item(txt,EditorNode::get_singleton()->get_gui_base()->get_icon(warning?"Warning":"Error","EditorIcons"));
+ error_list->set_item_tooltip( error_list->get_item_count() -1,tooltip );
+
+ int scc = p_data[1];
+
+ Array stack;
+ stack.resize(scc);
+ for(int i=0;i<scc;i++) {
+ stack[i]=p_data[2+i];
+ }
+
+ error_list->set_item_metadata( error_list->get_item_count() -1,stack );
+
+ error_count++;
+ /*
+ int count = p_data[1];
+
+ Array cstack;
+
+ OutputError oe = errors.front()->get();
+
+ packet_peer_stream->put_var(oe.hr);
+ packet_peer_stream->put_var(oe.min);
+ packet_peer_stream->put_var(oe.sec);
+ packet_peer_stream->put_var(oe.msec);
+ packet_peer_stream->put_var(oe.source_func);
+ packet_peer_stream->put_var(oe.source_file);
+ packet_peer_stream->put_var(oe.source_line);
+ packet_peer_stream->put_var(oe.error);
+ packet_peer_stream->put_var(oe.error_descr);
+ packet_peer_stream->put_var(oe.warning);
+ packet_peer_stream->put_var(oe.callstack);
+ */
+
+ } else if (p_msg=="profile_sig") {
+ //cache a signature
+ print_line("SIG: "+String(Variant(p_data)));
+ profiler_signature[p_data[1]]=p_data[0];
+
+ } else if (p_msg=="profile_frame" || p_msg=="profile_total") {
+
+ EditorProfiler::Metric metric;
+ metric.valid=true;
+ metric.frame_number=p_data[0];
+ metric.frame_time=p_data[1];
+ metric.idle_time=p_data[2];
+ metric.fixed_time=p_data[3];
+ metric.fixed_frame_time=p_data[4];
+ int frame_data_amount = p_data[6];
+ int frame_function_amount = p_data[7];
+
+
+ if (frame_data_amount) {
+ EditorProfiler::Metric::Category frame_time;
+ frame_time.signature="category_frame_time";
+ frame_time.name="Frame Time";
+ frame_time.total_time=metric.frame_time;
+
+ EditorProfiler::Metric::Category::Item item;
+ item.calls=1;
+ item.line=0;
+ item.name="Fixed Time";
+ item.total=metric.fixed_time;
+ item.self=item.total;
+ item.signature="fixed_time";
+
+
+ frame_time.items.push_back(item);
+
+ item.name="Idle Time";
+ item.total=metric.idle_time;
+ item.self=item.total;
+ item.signature="idle_time";
+
+ frame_time.items.push_back(item);
+
+ item.name="Fixed Frame Time";
+ item.total=metric.fixed_frame_time;
+ item.self=item.total;
+ item.signature="fixed_frame_time";
+
+ frame_time.items.push_back(item);
+
+ metric.categories.push_back(frame_time);
+
+ }
+
+
+
+ int idx=8;
+ for(int i=0;i<frame_data_amount;i++) {
+
+ EditorProfiler::Metric::Category c;
+ String name=p_data[idx++];
+ Array values=p_data[idx++];
+ c.name=name.capitalize();
+ c.items.resize(values.size()/2);
+ c.total_time=0;
+ c.signature="categ::"+name;
+ for(int i=0;i<values.size();i+=2) {
+
+ EditorProfiler::Metric::Category::Item item;
+ item.name=values[i];
+ item.calls=1;
+ item.self=values[i+1];
+ item.total=item.self;
+ item.signature="categ::"+name+"::"+item.name;
+ item.name=item.name.capitalize();
+ c.total_time+=item.total;
+ c.items[i/2]=item;
+
+
+ }
+ metric.categories.push_back(c);
+ }
+
+ EditorProfiler::Metric::Category funcs;
+ funcs.total_time=p_data[5]; //script time
+ funcs.items.resize(frame_function_amount);
+ funcs.name="Script Functions";
+ funcs.signature="script_functions";
+ for(int i=0;i<frame_function_amount;i++) {
+
+ int signature = p_data[idx++];
+ int calls = p_data[idx++];
+ float total = p_data[idx++];
+ float self = p_data[idx++];
+
+
+
+ EditorProfiler::Metric::Category::Item item;
+ if (profiler_signature.has(signature)) {
+
+ item.signature=profiler_signature[signature];
+
+ String name = profiler_signature[signature];
+ Vector<String> strings = name.split("::");
+ if (strings.size()==3) {
+ item.name=strings[2];
+ item.script=strings[0];
+ item.line=strings[1].to_int();
+ }
+
+ } else {
+ item.name="SigErr "+itos(signature);
+ }
+
+
+
+
+ item.calls=calls;
+ item.self=self;
+ item.total=total;
+ funcs.items[i]=item;
+
+ }
+
+ metric.categories.push_back(funcs);
+
+ if (p_msg=="profile_frame")
+ profiler->add_frame_metric(metric,false);
+ else
+ profiler->add_frame_metric(metric,true);
+
+ } else if (p_msg=="kill_me") {
+
+ editor->call_deferred("stop_child_process");
+ }
+
+}
+
+
+void ScriptEditorDebugger::_performance_select(Object*,int,bool) {
+
+ perf_draw->update();
+
+}
+
+void ScriptEditorDebugger::_performance_draw() {
+
+
+ Vector<int> which;
+ for(int i=0;i<perf_items.size();i++) {
+
+
+ if (perf_items[i]->is_selected(0))
+ which.push_back(i);
+ }
+
+
+ if(which.empty())
+ return;
+
+ Ref<StyleBox> graph_sb = get_stylebox("normal","TextEdit");
+ Ref<Font> graph_font = get_font("font","TextEdit");
+
+ int cols = Math::ceil(Math::sqrt((float)which.size()));
+ int rows = (which.size()+1)/cols;
+ if (which.size()==1)
+ rows=1;
+
+
+ int margin =3;
+ int point_sep=5;
+ Size2i s = Size2i(perf_draw->get_size())/Size2i(cols,rows);
+ for(int i=0;i<which.size();i++) {
+
+ Point2i p(i%cols,i/cols);
+ Rect2i r(p*s,s);
+ r.pos+=Point2(margin,margin);
+ r.size-=Point2(margin,margin)*2.0;
+ perf_draw->draw_style_box(graph_sb,r);
+ r.pos+=graph_sb->get_offset();
+ r.size-=graph_sb->get_minimum_size();
+ int pi=which[i];
+ Color c = Color(0.7,0.9,0.5);
+ c.set_hsv(Math::fmod(c.get_h()+pi*0.7654,1),c.get_s(),c.get_v());
+
+ c.a=0.8;
+ perf_draw->draw_string(graph_font,r.pos+Point2(0,graph_font->get_ascent()),perf_items[pi]->get_text(0),c,r.size.x);
+ c.a=0.6;
+ perf_draw->draw_string(graph_font,r.pos+Point2(graph_font->get_char_size('X').width,graph_font->get_ascent()+graph_font->get_height()),perf_items[pi]->get_text(1),c,r.size.y);
+
+ float spacing=point_sep/float(cols);
+ float from = r.size.width;
+
+ List<Vector<float> >::Element *E=perf_history.front();
+ float prev=-1;
+ while(from>=0 && E) {
+
+ float m = perf_max[pi];
+ if (m==0)
+ m=0.00001;
+ float h = E->get()[pi]/m;
+ h=(1.0-h)*r.size.y;
+
+ c.a=0.7;
+ if (E!=perf_history.front())
+ perf_draw->draw_line(r.pos+Point2(from,h),r.pos+Point2(from+spacing,prev),c,2.0);
+ prev=h;
+ E=E->next();
+ from-=spacing;
+ }
+
+ }
+
+}
+
+void ScriptEditorDebugger::_notification(int p_what) {
+
+ switch(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"));
+ forward->set_icon( get_icon("Forward","EditorIcons"));
+ dobreak->set_icon( get_icon("Pause","EditorIcons"));
+ docontinue->set_icon( get_icon("DebugContinue","EditorIcons"));
+ //scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons"));
+ le_set->connect("pressed",this,"_live_edit_set");
+ le_clear->connect("pressed",this,"_live_edit_clear");
+ error_list->connect("item_selected",this,"_error_selected");
+ error_stack->connect("item_selected",this,"_error_stack_selected");
+ vmem_refresh->set_icon( get_icon("Reload","EditorIcons"));
+
+ } break;
+ case NOTIFICATION_PROCESS: {
+
+ if (connection.is_valid()) {
+ inspect_scene_tree_timeout-=get_process_delta_time();
+ if (inspect_scene_tree_timeout<0) {
+ inspect_scene_tree_timeout=EditorSettings::get_singleton()->get("debugger/scene_tree_refresh_interval");
+ if (inspect_scene_tree->is_visible_in_tree()) {
+ _scene_tree_request();
+
+ if (inspected_object_id!=0) {
+ //take the chance and re-inspect selected object
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+ }
+ }
+ }
+
+ inspect_edited_object_timeout-=get_process_delta_time();
+ if (inspect_edited_object_timeout<0) {
+ inspect_edited_object_timeout=EditorSettings::get_singleton()->get("debugger/remote_inspect_refresh_interval");
+ if (inspect_scene_tree->is_visible_in_tree() && inspected_object_id) {
+ //take the chance and re-inspect selected object
+ Array msg;
+ msg.push_back("inspect_object");
+ msg.push_back(inspected_object_id);
+ ppeer->put_var(msg);
+ }
+ }
+ }
+
+ if (error_count!=last_error_count) {
+
+ if (error_count==0) {
+ error_split->set_name(TTR("Errors"));
+ debugger_button->set_text(TTR("Debugger"));
+ debugger_button->set_icon(Ref<Texture>());
+ tabs->set_tab_icon(error_split->get_index(),Ref<Texture>());
+ } else {
+ error_split->set_name(TTR("Errors")+" ("+itos(error_count)+")");
+ debugger_button->set_text(TTR("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;
+ }
+
+ if (connection.is_null()) {
+
+ if (server->is_connection_available()) {
+
+ connection = server->take_connection();
+ if (connection.is_null())
+ break;
+
+ EditorNode::get_log()->add_message("** Debug Process Started **");
+
+ ppeer->set_stream_peer(connection);
+
+ //EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ //emit_signal("show_debugger",true);
+
+ dobreak->set_disabled(false);
+ tabs->set_current_tab(0);
+
+ reason->set_text(TTR("Child Process Connected"));
+ reason->set_tooltip(TTR("Child Process Connected"));
+ profiler->clear();
+
+ inspect_scene_tree->clear();
+ le_set->set_disabled(true);
+ le_clear->set_disabled(false);
+ error_list->clear();
+ error_stack->clear();
+ error_count=0;
+ profiler_signature.clear();
+ //live_edit_root->set_text("/root");
+
+ EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
+ EditorNode::get_singleton()->get_pause_button()->set_disabled(false);
+
+ update_live_edit_root();
+ if (profiler->is_profiling()) {
+ _profiler_activate(true);
+ }
+
+
+ } else {
+
+ break;
+ }
+ };
+
+ if (!connection->is_connected_to_host()) {
+ stop();
+ editor->notify_child_process_exited(); //somehow, exited
+ break;
+ };
+
+ if (ppeer->get_available_packet_count() <= 0) {
+ break;
+ };
+
+ while(ppeer->get_available_packet_count() > 0) {
+
+ if (pending_in_queue) {
+
+ int todo = MIN( ppeer->get_available_packet_count(), pending_in_queue );
+
+ for(int i=0;i<todo;i++) {
+
+ Variant cmd;
+ Error ret = ppeer->get_var(cmd);
+ if (ret!=OK) {
+ stop();
+ ERR_FAIL_COND(ret!=OK);
+ }
+
+ message.push_back(cmd);
+ pending_in_queue--;
+ }
+
+
+ if (pending_in_queue==0) {
+ _parse_message(message_type,message);
+ message.clear();
+
+ }
+
+
+ } else {
+
+ if (ppeer->get_available_packet_count()>=2) {
+
+
+ Variant cmd;
+ Error ret = ppeer->get_var(cmd);
+ if (ret!=OK) {
+ stop();
+ ERR_FAIL_COND(ret!=OK);
+ }
+ if (cmd.get_type()!=Variant::STRING) {
+ stop();
+ ERR_FAIL_COND(cmd.get_type()!=Variant::STRING);
+ }
+
+ message_type=cmd;
+ //print_line("GOT: "+message_type);
+
+ ret = ppeer->get_var(cmd);
+ if (ret!=OK) {
+ stop();
+ ERR_FAIL_COND(ret!=OK);
+ }
+ if (cmd.get_type()!=Variant::INT) {
+ stop();
+ ERR_FAIL_COND(cmd.get_type()!=Variant::INT);
+ }
+
+ pending_in_queue=cmd;
+
+ if (pending_in_queue==0) {
+ _parse_message(message_type,Array());
+ message.clear();
+ }
+
+ } else {
+
+
+ break;
+ }
+
+ }
+ }
+
+
+
+ } break;
+ }
+
+}
+
+
+void ScriptEditorDebugger::start() {
+
+ stop();
+
+ if (is_visible_in_tree()) {
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ }
+
+ uint16_t port = GLOBAL_GET("network/debug/remote_port");
+ perf_history.clear();
+ for(int i=0;i<Performance::MONITOR_MAX;i++) {
+
+ perf_max[i]=0;
+ }
+
+ server->listen(port);
+ set_process(true);
+
+}
+
+void ScriptEditorDebugger::pause(){
+
+
+}
+
+void ScriptEditorDebugger::unpause(){
+
+
+}
+
+void ScriptEditorDebugger::stop(){
+
+
+ set_process(false);
+
+ server->stop();
+
+ ppeer->set_stream_peer(Ref<StreamPeer>());
+
+ if (connection.is_valid()) {
+ EditorNode::get_log()->add_message("** Debug Process Stopped **");
+ connection.unref();
+ }
+
+ pending_in_queue=0;
+ message.clear();
+
+ node_path_cache.clear();
+ res_path_cache.clear();
+ profiler_signature.clear();
+ le_clear->set_disabled(false);
+ le_set->set_disabled(true);
+ profiler->set_enabled(true);
+
+ inspect_properties->edit(NULL);
+ inspect_scene_tree->clear();
+
+ EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
+ EditorNode::get_singleton()->get_pause_button()->set_disabled(true);
+
+
+
+ if (hide_on_stop) {
+ if (is_visible_in_tree())
+ EditorNode::get_singleton()->hide_bottom_panel();
+ emit_signal("show_debugger",false);
+ }
+
+}
+
+void ScriptEditorDebugger::_profiler_activate(bool p_enable) {
+
+ if (!connection.is_valid())
+ return;
+
+
+ if (p_enable) {
+ profiler_signature.clear();
+ Array msg;
+ msg.push_back("start_profiling");
+ int max_funcs = EditorSettings::get_singleton()->get("debugger/profiler_frame_max_functions");
+ max_funcs = CLAMP(max_funcs,16,512);
+ msg.push_back(max_funcs);
+ ppeer->put_var(msg);
+
+ print_line("BEGIN PROFILING!");
+
+ } else {
+ Array msg;
+ msg.push_back("stop_profiling");
+ ppeer->put_var(msg);
+
+ print_line("END PROFILING!");
+
+ }
+
+}
+
+void ScriptEditorDebugger::_profiler_seeked() {
+
+ if (!connection.is_valid() || !connection->is_connected_to_host())
+ return;
+
+ if (breaked)
+ return;
+ debug_break();
+}
+
+
+void ScriptEditorDebugger::_stack_dump_frame_selected() {
+
+ TreeItem *ti = stack_dump->get_selected();
+ if (!ti)
+ return;
+
+
+ Dictionary d = ti->get_metadata(0);
+
+ Ref<Script> s = ResourceLoader::load(d["file"]);
+ emit_signal("goto_script_line",s,int(d["line"])-1);
+
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+ ///
+
+ Array msg;
+ msg.push_back("get_stack_frame_vars");
+ msg.push_back(d["frame"]);
+ ppeer->put_var(msg);
+
+}
+
+void ScriptEditorDebugger::_output_clear() {
+
+ //output->clear();
+ //output->push_color(Color(0,0,0));
+
+}
+
+String ScriptEditorDebugger::get_var_value(const String& p_var) const {
+ if (!breaked)
+ return String();
+ return variables->get_var_value(p_var);
+}
+
+int ScriptEditorDebugger::_get_node_path_cache(const NodePath& p_path) {
+
+ const int *r = node_path_cache.getptr(p_path);
+ if (r)
+ return *r;
+
+ last_path_id++;
+
+ node_path_cache[p_path]=last_path_id;
+ Array msg;
+ msg.push_back("live_node_path");
+ msg.push_back(p_path);
+ msg.push_back(last_path_id);
+ ppeer->put_var(msg);
+
+
+ return last_path_id;
+}
+
+int ScriptEditorDebugger::_get_res_path_cache(const String& p_path) {
+
+ Map<String,int>::Element *E=res_path_cache.find(p_path);
+
+ if (E)
+ return E->get();
+
+ last_path_id++;
+
+ res_path_cache[p_path]=last_path_id;
+ Array msg;
+ msg.push_back("live_res_path");
+ msg.push_back(p_path);
+ msg.push_back(last_path_id);
+ ppeer->put_var(msg);
+
+
+ return last_path_id;
+}
+
+void ScriptEditorDebugger::_method_changed(Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) {
+
+ if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene())
+ return;
+
+ Node *node = p_base->cast_to<Node>();
+
+ VARIANT_ARGPTRS
+
+ for(int i=0;i<VARIANT_ARG_MAX;i++) {
+ //no pointers, sorry
+ if (argptr[i] && (argptr[i]->get_type()==Variant::OBJECT || argptr[i]->get_type()==Variant::_RID))
+ return;
+ }
+
+ if (node) {
+
+ NodePath path = editor->get_edited_scene()->get_path_to(node);
+ int pathid = _get_node_path_cache(path);
+
+
+
+ Array msg;
+ msg.push_back("live_node_call");
+ msg.push_back(pathid);
+ msg.push_back(p_name);
+ for(int i=0;i<VARIANT_ARG_MAX;i++) {
+ //no pointers, sorry
+ msg.push_back(*argptr[i]);
+ }
+ ppeer->put_var(msg);
+
+ return;
+
+ }
+
+ Resource *res = p_base->cast_to<Resource>();
+
+ if (res && res->get_path()!=String()) {
+
+ String respath = res->get_path();
+ int pathid = _get_res_path_cache(respath);
+
+ Array msg;
+ msg.push_back("live_res_call");
+ msg.push_back(pathid);
+ msg.push_back(p_name);
+ for(int i=0;i<VARIANT_ARG_MAX;i++) {
+ //no pointers, sorry
+ msg.push_back(*argptr[i]);
+ }
+ ppeer->put_var(msg);
+
+ return;
+ }
+
+ //print_line("method");
+}
+
+void ScriptEditorDebugger::_property_changed(Object*p_base,const StringName& p_property,const Variant& p_value){
+
+ if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene())
+ return;
+
+ Node *node = p_base->cast_to<Node>();
+
+ if (node) {
+
+ NodePath path = editor->get_edited_scene()->get_path_to(node);
+ int pathid = _get_node_path_cache(path);
+
+
+ if (p_value.is_ref()) {
+ Ref<Resource> res = p_value;
+ if (res.is_valid() && res->get_path()!=String()) {
+
+ Array msg;
+ msg.push_back("live_node_prop_res");
+ msg.push_back(pathid);
+ msg.push_back(p_property);
+ msg.push_back(res->get_path());
+ ppeer->put_var(msg);
+ }
+ } else {
+
+ Array msg;
+ msg.push_back("live_node_prop");
+ msg.push_back(pathid);
+ msg.push_back(p_property);
+ msg.push_back(p_value);
+ ppeer->put_var(msg);
+ }
+
+
+ return;
+
+ }
+
+ Resource *res = p_base->cast_to<Resource>();
+
+ if (res && res->get_path()!=String()) {
+
+ String respath = res->get_path();
+ int pathid = _get_res_path_cache(respath);
+
+
+ if (p_value.is_ref()) {
+ Ref<Resource> res = p_value;
+ if (res.is_valid() && res->get_path()!=String()) {
+
+ Array msg;
+ msg.push_back("live_res_prop_res");
+ msg.push_back(pathid);
+ msg.push_back(p_property);
+ msg.push_back(res->get_path());
+ ppeer->put_var(msg);
+ }
+ } else {
+
+ Array msg;
+ msg.push_back("live_res_prop");
+ msg.push_back(pathid);
+ msg.push_back(p_property);
+ msg.push_back(p_value);
+ ppeer->put_var(msg);
+ }
+
+
+ return;
+ }
+
+
+ //print_line("prop");
+}
+
+void ScriptEditorDebugger::_method_changeds(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) {
+
+ ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud;
+ sed->_method_changed(p_base,p_name,VARIANT_ARG_PASS);
+
+
+}
+
+void ScriptEditorDebugger::_property_changeds(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value){
+
+ ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud;
+ sed->_property_changed(p_base,p_property,p_value);
+
+}
+
+void ScriptEditorDebugger::set_live_debugging(bool p_enable) {
+
+ live_debug=p_enable;
+}
+
+void ScriptEditorDebugger::_live_edit_set() {
+
+ if (!connection.is_valid())
+ return;
+
+ TreeItem* ti = inspect_scene_tree->get_selected();
+ if (!ti)
+ return;
+ String path;
+
+ while(ti) {
+ String lp=ti->get_text(0);
+ path="/"+lp+path;
+ ti=ti->get_parent();
+
+ }
+
+ NodePath np = path;
+
+ editor->get_editor_data().set_edited_scene_live_edit_root(np);
+
+ update_live_edit_root();
+
+
+}
+
+void ScriptEditorDebugger::_live_edit_clear() {
+
+ NodePath np = NodePath("/root");
+ editor->get_editor_data().set_edited_scene_live_edit_root(np);
+
+ update_live_edit_root();
+
+}
+
+void ScriptEditorDebugger::update_live_edit_root() {
+
+ NodePath np = editor->get_editor_data().get_edited_scene_live_edit_root();
+
+ if (connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_set_root");
+ msg.push_back(np);
+ if (editor->get_edited_scene())
+ msg.push_back(editor->get_edited_scene()->get_filename());
+ else
+ msg.push_back("");
+ ppeer->put_var(msg);
+ }
+ live_edit_root->set_text(np);
+
+}
+
+void ScriptEditorDebugger::live_debug_create_node(const NodePath& p_parent,const String& p_type,const String& p_name) {
+
+ if (live_debug && connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_create_node");
+ msg.push_back(p_parent);
+ msg.push_back(p_type);
+ msg.push_back(p_name);
+ ppeer->put_var(msg);
+ }
+}
+
+void ScriptEditorDebugger::live_debug_instance_node(const NodePath& p_parent,const String& p_path,const String& p_name){
+
+ if (live_debug && connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_instance_node");
+ msg.push_back(p_parent);
+ msg.push_back(p_path);
+ msg.push_back(p_name);
+ ppeer->put_var(msg);
+ }
+
+}
+void ScriptEditorDebugger::live_debug_remove_node(const NodePath& p_at){
+
+ if (live_debug && connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_remove_node");
+ msg.push_back(p_at);
+ ppeer->put_var(msg);
+ }
+
+}
+void ScriptEditorDebugger::live_debug_remove_and_keep_node(const NodePath& p_at,ObjectID p_keep_id) {
+
+ if (live_debug && connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_remove_and_keep_node");
+ msg.push_back(p_at);
+ msg.push_back(p_keep_id);
+ ppeer->put_var(msg);
+ }
+
+}
+void ScriptEditorDebugger::live_debug_restore_node(ObjectID p_id, const NodePath& p_at, int p_at_pos){
+
+ if (live_debug && connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_restore_node");
+ msg.push_back(p_id);
+ msg.push_back(p_at);
+ msg.push_back(p_at_pos);
+ ppeer->put_var(msg);
+ }
+
+}
+void ScriptEditorDebugger::live_debug_duplicate_node(const NodePath& p_at,const String& p_new_name){
+
+ if (live_debug && connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_duplicate_node");
+ msg.push_back(p_at);
+ msg.push_back(p_new_name);
+ ppeer->put_var(msg);
+ }
+
+}
+void ScriptEditorDebugger::live_debug_reparent_node(const NodePath& p_at, const NodePath& p_new_place, const String &p_new_name, int p_at_pos){
+
+ if (live_debug && connection.is_valid()) {
+ Array msg;
+ msg.push_back("live_reparent_node");
+ msg.push_back(p_at);
+ msg.push_back(p_new_place);
+ msg.push_back(p_new_name);
+ msg.push_back(p_at_pos);
+ ppeer->put_var(msg);
+ }
+
+}
+
+void ScriptEditorDebugger::set_breakpoint(const String& p_path,int p_line,bool p_enabled) {
+
+ if (connection.is_valid()) {
+ Array msg;
+ msg.push_back("breakpoint");
+ msg.push_back(p_path);
+ msg.push_back(p_line);
+ msg.push_back(p_enabled);
+ ppeer->put_var(msg);
+ }
+}
+
+
+void ScriptEditorDebugger::reload_scripts() {
+
+ if (connection.is_valid()) {
+ Array msg;
+ msg.push_back("reload_scripts");
+ ppeer->put_var(msg);
+ }
+}
+
+
+void ScriptEditorDebugger::_error_selected(int p_idx) {
+
+ error_stack->clear();
+ Array st=error_list->get_item_metadata(p_idx);
+ for(int i=0;i<st.size();i+=2) {
+
+ String script=st[i];
+ int line=st[i+1];
+ Array md;
+ md.push_back(st[i]);
+ md.push_back(st[i+1]);
+
+ String str = script.get_file()+":"+itos(line);
+
+ error_stack->add_item(str);
+ error_stack->set_item_metadata(error_stack->get_item_count()-1,md);
+ error_stack->set_item_tooltip(error_stack->get_item_count()-1,TTR("File:")+" "+String(st[i])+"\n"+TTR("Line:")+" "+itos(line));
+ }
+}
+
+void ScriptEditorDebugger:: _error_stack_selected(int p_idx){
+
+ Array arr = error_stack->get_item_metadata(p_idx);
+ if (arr.size()!=2)
+ return;
+
+
+ Ref<Script> s = ResourceLoader::load(arr[0]);
+ emit_signal("goto_script_line",s,int(arr[1])-1);
+
+}
+
+void ScriptEditorDebugger::set_hide_on_stop(bool p_hide) {
+
+ hide_on_stop=p_hide;
+}
+
+void ScriptEditorDebugger::_paused() {
+
+ ERR_FAIL_COND(connection.is_null());
+ ERR_FAIL_COND(!connection->is_connected_to_host());
+
+ if (!breaked && EditorNode::get_singleton()->get_pause_button()->is_pressed()) {
+ debug_break();
+ }
+
+ if (breaked && !EditorNode::get_singleton()->get_pause_button()->is_pressed()) {
+ debug_continue();
+ }
+
+}
+
+void ScriptEditorDebugger::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_stack_dump_frame_selected"),&ScriptEditorDebugger::_stack_dump_frame_selected);
+ ClassDB::bind_method(D_METHOD("debug_next"),&ScriptEditorDebugger::debug_next);
+ ClassDB::bind_method(D_METHOD("debug_step"),&ScriptEditorDebugger::debug_step);
+ ClassDB::bind_method(D_METHOD("debug_break"),&ScriptEditorDebugger::debug_break);
+ ClassDB::bind_method(D_METHOD("debug_continue"),&ScriptEditorDebugger::debug_continue);
+ ClassDB::bind_method(D_METHOD("_output_clear"),&ScriptEditorDebugger::_output_clear);
+ ClassDB::bind_method(D_METHOD("_performance_draw"),&ScriptEditorDebugger::_performance_draw);
+ ClassDB::bind_method(D_METHOD("_performance_select"),&ScriptEditorDebugger::_performance_select);
+ ClassDB::bind_method(D_METHOD("_scene_tree_request"),&ScriptEditorDebugger::_scene_tree_request);
+ ClassDB::bind_method(D_METHOD("_video_mem_request"),&ScriptEditorDebugger::_video_mem_request);
+ ClassDB::bind_method(D_METHOD("_live_edit_set"),&ScriptEditorDebugger::_live_edit_set);
+ ClassDB::bind_method(D_METHOD("_live_edit_clear"),&ScriptEditorDebugger::_live_edit_clear);
+
+ ClassDB::bind_method(D_METHOD("_error_selected"),&ScriptEditorDebugger::_error_selected);
+ ClassDB::bind_method(D_METHOD("_error_stack_selected"),&ScriptEditorDebugger::_error_stack_selected);
+ ClassDB::bind_method(D_METHOD("_profiler_activate"),&ScriptEditorDebugger::_profiler_activate);
+ ClassDB::bind_method(D_METHOD("_profiler_seeked"),&ScriptEditorDebugger::_profiler_seeked);
+
+ ClassDB::bind_method(D_METHOD("_paused"),&ScriptEditorDebugger::_paused);
+
+ ClassDB::bind_method(D_METHOD("_scene_tree_selected"),&ScriptEditorDebugger::_scene_tree_selected);
+ ClassDB::bind_method(D_METHOD("_scene_tree_folded"),&ScriptEditorDebugger::_scene_tree_folded);
+
+
+ ClassDB::bind_method(D_METHOD("live_debug_create_node"),&ScriptEditorDebugger::live_debug_create_node);
+ ClassDB::bind_method(D_METHOD("live_debug_instance_node"),&ScriptEditorDebugger::live_debug_instance_node);
+ ClassDB::bind_method(D_METHOD("live_debug_remove_node"),&ScriptEditorDebugger::live_debug_remove_node);
+ ClassDB::bind_method(D_METHOD("live_debug_remove_and_keep_node"),&ScriptEditorDebugger::live_debug_remove_and_keep_node);
+ ClassDB::bind_method(D_METHOD("live_debug_restore_node"),&ScriptEditorDebugger::live_debug_restore_node);
+ ClassDB::bind_method(D_METHOD("live_debug_duplicate_node"),&ScriptEditorDebugger::live_debug_duplicate_node);
+ ClassDB::bind_method(D_METHOD("live_debug_reparent_node"),&ScriptEditorDebugger::live_debug_reparent_node);
+ ClassDB::bind_method(D_METHOD("_scene_tree_property_select_object"),&ScriptEditorDebugger::_scene_tree_property_select_object);
+ ClassDB::bind_method(D_METHOD("_scene_tree_property_value_edited"),&ScriptEditorDebugger::_scene_tree_property_value_edited);
+
+ ADD_SIGNAL(MethodInfo("goto_script_line"));
+ ADD_SIGNAL(MethodInfo("breaked",PropertyInfo(Variant::BOOL,"reallydid"),PropertyInfo(Variant::BOOL,"can_debug")));
+ ADD_SIGNAL(MethodInfo("show_debugger",PropertyInfo(Variant::BOOL,"reallydid")));
+}
+
+ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
+
+
+
+ ppeer = Ref<PacketPeerStream>( memnew( PacketPeerStream ) );
+ editor=p_editor;
+
+ tabs = memnew( TabContainer );
+ tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ tabs->set_area_as_parent_rect();
+ add_child(tabs);
+
+
+ { //debugger
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ vbc->set_name(TTR("Debugger"));
+ //tabs->add_child(vbc);
+ Control *dbg=vbc;
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
+
+
+ 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);
+
+ hbc->add_child( memnew( VSeparator) );
+
+ step = memnew( Button );
+ hbc->add_child(step);
+ step->set_tooltip(TTR("Step Into"));
+ step->connect("pressed",this,"debug_step");
+
+ next = memnew( Button );
+ hbc->add_child(next);
+ next->set_tooltip(TTR("Step Over"));
+ next->connect("pressed",this,"debug_next");
+
+ hbc->add_child( memnew( VSeparator) );
+
+ dobreak = memnew( Button );
+ hbc->add_child(dobreak);
+ dobreak->set_tooltip(TTR("Break"));
+ dobreak->connect("pressed",this,"debug_break");
+
+ docontinue = memnew( Button );
+ hbc->add_child(docontinue);
+ docontinue->set_tooltip(TTR("Continue"));
+ docontinue->connect("pressed",this,"debug_continue");
+
+ //hbc->add_child( memnew( VSeparator) );
+
+ back = memnew( Button );
+ hbc->add_child(back);
+ back->set_tooltip(TTR("Inspect Previous Instance"));
+ back->hide();
+
+ forward = memnew( Button );
+ hbc->add_child(forward);
+ forward->set_tooltip(TTR("Inspect Next Instance"));
+ forward->hide();
+
+
+ HSplitContainer *sc = memnew( HSplitContainer );
+ vbc->add_child(sc);
+ sc->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ stack_dump = memnew( Tree );
+ stack_dump->set_columns(1);
+ stack_dump->set_column_titles_visible(true);
+ stack_dump->set_column_title(0,TTR("Stack Frames"));
+ stack_dump->set_h_size_flags(SIZE_EXPAND_FILL);
+ stack_dump->set_hide_root(true);
+ stack_dump->connect("cell_selected",this,"_stack_dump_frame_selected");
+ sc->add_child(stack_dump);
+
+ inspector = memnew( PropertyEditor );
+ inspector->set_h_size_flags(SIZE_EXPAND_FILL);
+ inspector->hide_top_label();
+ inspector->get_scene_tree()->set_column_title(0,TTR("Variable"));
+ inspector->set_capitalize_paths(false);
+ inspector->set_read_only(true);
+ sc->add_child(inspector);
+
+ server = TCP_Server::create_ref();
+
+ pending_in_queue=0;
+
+ variables = memnew( ScriptEditorDebuggerVariables );
+
+ breaked=false;
+
+ tabs->add_child(dbg);
+ //tabs->move_child(vbc,0);
+
+ hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
+
+ }
+
+ { //errors
+
+
+ error_split = memnew( HSplitContainer );
+ VBoxContainer *errvb = memnew( VBoxContainer );
+ errvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ error_list = memnew( ItemList );
+ errvb->add_margin_child(TTR("Errors:"),error_list,true);
+ error_split->add_child(errvb);
+
+ errvb = memnew( VBoxContainer );
+ errvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ error_stack = memnew( ItemList );
+ errvb->add_margin_child(TTR("Stack Trace (if applicable):"),error_stack,true);
+ error_split->add_child(errvb);
+
+ error_split->set_name(TTR("Errors"));
+ tabs->add_child(error_split);
+ }
+
+
+ { // inquire
+
+
+ inspect_info = memnew( HSplitContainer );
+ inspect_info->set_name(TTR("Remote Inspector"));
+ tabs->add_child(inspect_info);
+
+ VBoxContainer *info_left = memnew(VBoxContainer);
+ info_left->set_h_size_flags(SIZE_EXPAND_FILL);
+ inspect_info->add_child(info_left);
+
+ inspect_scene_tree = memnew( Tree );
+ info_left->add_margin_child(TTR("Live Scene Tree:"),inspect_scene_tree,true);
+ inspect_scene_tree->connect("cell_selected",this,"_scene_tree_selected");
+ inspect_scene_tree->connect("item_collapsed",this,"_scene_tree_folded");
+
+ //
+
+ VBoxContainer *info_right = memnew(VBoxContainer);
+ info_right->set_h_size_flags(SIZE_EXPAND_FILL);
+ inspect_info->add_child(info_right);
+
+ inspect_properties = memnew( PropertyEditor );
+ inspect_properties->hide_top_label();
+ inspect_properties->set_show_categories(true);
+ inspect_properties->connect("object_id_selected",this,"_scene_tree_property_select_object");
+
+ info_right->add_margin_child(TTR("Remote Object Properties: "),inspect_properties,true);
+
+ inspect_scene_tree_timeout=EDITOR_DEF("debugger/scene_tree_refresh_interval",1.0);
+ inspect_edited_object_timeout=EDITOR_DEF("debugger/remote_inspect_refresh_interval",0.2);
+ inspected_object_id=0;
+ updating_scene_tree=false;
+
+ inspected_object = memnew( ScriptEditorDebuggerInspectedObject );
+ inspected_object->connect("value_edited",this,"_scene_tree_property_value_edited");
+ }
+
+ { //profiler
+ profiler = memnew( EditorProfiler );
+ profiler->set_name(TTR("Profiler"));
+ tabs->add_child(profiler);
+ profiler->connect("enable_profiling",this,"_profiler_activate");
+ profiler->connect("break_request",this,"_profiler_seeked");
+ }
+
+
+ { //monitors
+
+ HSplitContainer *hsp = memnew( HSplitContainer );
+
+ perf_monitors = memnew(Tree);
+ perf_monitors->set_columns(2);
+ perf_monitors->set_column_title(0,TTR("Monitor"));
+ perf_monitors->set_column_title(1,TTR("Value"));
+ perf_monitors->set_column_titles_visible(true);
+ hsp->add_child(perf_monitors);
+ perf_monitors->set_select_mode(Tree::SELECT_MULTI);
+ perf_monitors->connect("multi_selected",this,"_performance_select");
+ perf_draw = memnew( Control );
+ perf_draw->connect("draw",this,"_performance_draw");
+ hsp->add_child(perf_draw);
+ hsp->set_name(TTR("Monitors"));
+ hsp->set_split_offset(300);
+ tabs->add_child(hsp);
+ perf_max.resize(Performance::MONITOR_MAX);
+
+ Map<String,TreeItem*> bases;
+ TreeItem *root=perf_monitors->create_item();
+ perf_monitors->set_hide_root(true);
+ for(int i=0;i<Performance::MONITOR_MAX;i++) {
+
+ String n = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i));
+ String base = n.get_slice("/",0);
+ String name = n.get_slice("/",1);
+ if (!bases.has(base)) {
+ TreeItem *b = perf_monitors->create_item(root);
+ b->set_text(0,base.capitalize());
+ b->set_editable(0,false);
+ b->set_selectable(0,false);
+ bases[base]=b;
+ }
+
+ TreeItem *it = perf_monitors->create_item(bases[base]);
+ it->set_editable(0,false);
+ it->set_selectable(0,true);
+ it->set_text(0,name.capitalize());
+ perf_items.push_back(it);
+ perf_max[i]=0;
+
+ }
+ }
+
+ { //vmem inspect
+ VBoxContainer *vmem_vb = memnew( VBoxContainer );
+ HBoxContainer *vmem_hb = memnew( HBoxContainer );
+ Label *vmlb = memnew(Label(TTR("List of Video Memory Usage by Resource:")+" ") );
+ vmlb->set_h_size_flags(SIZE_EXPAND_FILL);
+ vmem_hb->add_child( vmlb );
+ vmem_hb->add_child( memnew(Label(TTR("Total:")+" ")) );
+ vmem_total = memnew( LineEdit );
+ vmem_total->set_editable(false);
+ vmem_total->set_custom_minimum_size(Size2(100,1)*EDSCALE);
+ vmem_hb->add_child(vmem_total);
+ vmem_refresh = memnew( Button );
+ vmem_hb->add_child(vmem_refresh);
+ vmem_vb->add_child(vmem_hb);
+ vmem_refresh->connect("pressed",this,"_video_mem_request");
+
+ MarginContainer *vmmc = memnew( MarginContainer );
+ vmem_tree = memnew( Tree );
+ vmem_tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ vmem_tree->set_h_size_flags(SIZE_EXPAND_FILL);
+ vmmc->add_child(vmem_tree);
+ vmmc->set_v_size_flags(SIZE_EXPAND_FILL);
+ vmem_vb->add_child(vmmc);
+
+ vmem_vb->set_name(TTR("Video Mem"));
+ vmem_tree->set_columns(4);
+ vmem_tree->set_column_titles_visible(true);
+ vmem_tree->set_column_title(0,TTR("Resource Path"));
+ vmem_tree->set_column_expand(0,true);
+ vmem_tree->set_column_expand(1,false);
+ vmem_tree->set_column_title(1,TTR("Type"));
+ vmem_tree->set_column_min_width(1,100);
+ vmem_tree->set_column_expand(2,false);
+ vmem_tree->set_column_title(2,TTR("Format"));
+ vmem_tree->set_column_min_width(2,150);
+ vmem_tree->set_column_expand(3,false);
+ vmem_tree->set_column_title(3,TTR("Usage"));
+ vmem_tree->set_column_min_width(3,80);
+ vmem_tree->set_hide_root(true);
+
+ tabs->add_child(vmem_vb);
+ }
+
+ { // misc
+ VBoxContainer *info_left = memnew( VBoxContainer );
+ info_left->set_h_size_flags(SIZE_EXPAND_FILL);
+ info_left->set_name(TTR("Misc"));
+ tabs->add_child(info_left);
+ clicked_ctrl = memnew( LineEdit );
+ info_left->add_margin_child(TTR("Clicked Control:"),clicked_ctrl);
+ clicked_ctrl_type = memnew( LineEdit );
+ info_left->add_margin_child(TTR("Clicked Control Type:"),clicked_ctrl_type);
+
+ live_edit_root = memnew( LineEdit );
+
+ {
+ HBoxContainer *lehb = memnew( HBoxContainer );
+ Label *l = memnew( Label(TTR("Live Edit Root:")) );
+ lehb->add_child(l);
+ l->set_h_size_flags(SIZE_EXPAND_FILL);
+ le_set = memnew( Button(TTR("Set From Tree")) );
+ lehb->add_child(le_set);
+ le_clear = memnew( Button(TTR("Clear")) );
+ lehb->add_child(le_clear);
+ info_left->add_child(lehb);
+ MarginContainer *mc = memnew( MarginContainer );
+ mc->add_child(live_edit_root);
+ info_left->add_child(mc);
+ le_set->set_disabled(true);
+ le_clear->set_disabled(true);
+ }
+
+ }
+
+
+
+ msgdialog = memnew( AcceptDialog );
+ add_child(msgdialog);
+
+ p_editor->get_undo_redo()->set_method_notify_callback(_method_changeds,this);
+ p_editor->get_undo_redo()->set_property_notify_callback(_property_changeds,this);
+ live_debug=false;
+ last_path_id=false;
+ error_count=0;
+ hide_on_stop=true;
+ last_error_count=0;
+
+ EditorNode::get_singleton()->get_pause_button()->connect("pressed",this,"_paused");
+
+
+}
+
+ScriptEditorDebugger::~ScriptEditorDebugger() {
+
+ //inspector->edit(NULL);
+ memdelete(variables);
+
+ ppeer->set_stream_peer(Ref<StreamPeer>());
+
+ server->stop();
+ memdelete(inspected_object);
+
+}
diff --git a/tools/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index a02934bbaf..a02934bbaf 100644
--- a/tools/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
new file mode 100644
index 0000000000..7d8d6ffcec
--- /dev/null
+++ b/editor/settings_config_dialog.cpp
@@ -0,0 +1,415 @@
+/*************************************************************************/
+/* settings_config_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "settings_config_dialog.h"
+
+#include "editor_settings.h"
+#include "scene/gui/margin_container.h"
+#include "global_config.h"
+#include "editor_file_system.h"
+#include "editor_node.h"
+#include "os/keyboard.h"
+
+void EditorSettingsDialog::ok_pressed() {
+
+ if (!EditorSettings::get_singleton())
+ return;
+
+ _settings_save();
+ timer->stop();
+
+}
+
+void EditorSettingsDialog::_settings_changed() {
+
+ timer->start();
+}
+
+void EditorSettingsDialog::_settings_property_edited(const String& p_name) {
+
+ String full_name = property_editor->get_full_item_path(p_name);
+
+ // Small usability workaround to update the text color settings when the
+ // color theme is changed
+ if (full_name == "text_editor/theme/color_theme") {
+ property_editor->get_property_editor()->update_tree();
+ }
+}
+
+void EditorSettingsDialog::_settings_save() {
+
+
+ EditorSettings::get_singleton()->notify_changes();
+ EditorSettings::get_singleton()->save();
+
+}
+
+void EditorSettingsDialog::cancel_pressed() {
+
+ if (!EditorSettings::get_singleton())
+ return;
+
+ EditorSettings::get_singleton()->notify_changes();
+
+}
+
+
+void EditorSettingsDialog::popup_edit_settings() {
+
+ if (!EditorSettings::get_singleton())
+ return;
+
+ EditorSettings::get_singleton()->list_text_editor_themes(); // make sure we have an up to date list of themes
+
+ property_editor->edit(EditorSettings::get_singleton());
+ property_editor->get_property_editor()->update_tree();
+
+ search_box->select_all();
+ search_box->grab_focus();
+
+ _update_shortcuts();
+
+ // Restore valid window bounds or pop up at default size.
+ if (EditorSettings::get_singleton()->has("interface/dialogs/editor_settings_bounds")) {
+ popup(EditorSettings::get_singleton()->get("interface/dialogs/editor_settings_bounds"));
+ } else {
+ popup_centered_ratio(0.7);
+ }
+}
+
+void EditorSettingsDialog::_clear_search_box() {
+
+ if (search_box->get_text()=="")
+ return;
+
+ search_box->clear();
+ property_editor->get_property_editor()->update_tree();
+}
+
+void EditorSettingsDialog::_clear_shortcut_search_box() {
+ if (shortcut_search_box->get_text()=="")
+ return;
+
+ shortcut_search_box->clear();
+}
+
+void EditorSettingsDialog::_filter_shortcuts(const String& p_filter) {
+ shortcut_filter = p_filter;
+ _update_shortcuts();
+}
+
+void EditorSettingsDialog::_notification(int p_what) {
+
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ clear_button->set_icon(get_icon("Close", "EditorIcons"));
+ shortcut_clear_button->set_icon(get_icon("Close", "EditorIcons"));
+ } break;
+ case NOTIFICATION_POPUP_HIDE: {
+ EditorSettings::get_singleton()->set("interface/dialogs/editor_settings_bounds", get_rect());
+ } break;
+ }
+}
+
+
+void EditorSettingsDialog::_update_shortcuts() {
+
+ shortcuts->clear();
+
+ List<String> slist;
+ EditorSettings::get_singleton()->get_shortcut_list(&slist);
+ TreeItem *root = shortcuts->create_item();
+
+ Map<String,TreeItem*> sections;
+
+ for(List<String>::Element *E=slist.front();E;E=E->next()) {
+
+ Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(E->get());
+ if (!sc->has_meta("original"))
+ continue;
+
+ InputEvent original = sc->get_meta("original");
+
+ String section_name = E->get().get_slice("/",0);
+
+ TreeItem *section;
+
+ if (sections.has(section_name)) {
+ section=sections[section_name];
+ } else {
+ section = shortcuts->create_item(root);
+ section->set_text(0,section_name.capitalize());
+
+ sections[section_name]=section;
+ section->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
+ section->set_custom_bg_color(1,get_color("prop_subsection","Editor"));
+ }
+
+ if (shortcut_filter.is_subsequence_ofi(sc->get_name())) {
+ TreeItem *item = shortcuts->create_item(section);
+
+ item->set_text(0,sc->get_name());
+ item->set_text(1,sc->get_as_text());
+ if (!sc->is_shortcut(original) && !(sc->get_shortcut().type==InputEvent::NONE && original.type==InputEvent::NONE)) {
+ item->add_button(1,get_icon("Reload","EditorIcons"),2);
+ }
+ item->add_button(1,get_icon("Edit","EditorIcons"),0);
+ item->add_button(1,get_icon("Close","EditorIcons"),1);
+ item->set_tooltip(0,E->get());
+ item->set_metadata(0,E->get());
+ }
+ }
+
+ // remove sections with no shortcuts
+ for(Map<String,TreeItem*>::Element *E=sections.front();E;E=E->next()) {
+ TreeItem *section = E->get();
+ if (section->get_children() == NULL) {
+ root->remove_child(section);
+ }
+ }
+}
+
+void EditorSettingsDialog::_shortcut_button_pressed(Object* p_item,int p_column,int p_idx) {
+
+ TreeItem *ti=p_item->cast_to<TreeItem>();
+ ERR_FAIL_COND(!ti);
+
+ String item = ti->get_metadata(0);
+ Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(item);
+
+ if (p_idx==0) {
+ press_a_key_label->set_text(TTR("Press a Key.."));
+ last_wait_for_key=InputEvent();
+ press_a_key->popup_centered(Size2(250,80)*EDSCALE);
+ press_a_key->grab_focus();
+ press_a_key->get_ok()->set_focus_mode(FOCUS_NONE);
+ press_a_key->get_cancel()->set_focus_mode(FOCUS_NONE);
+ shortcut_configured=item;
+
+ } else if (p_idx==1) {//erase
+ if (!sc.is_valid())
+ return; //pointless, there is nothing
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Erase Shortcut");
+ ur->add_do_method(sc.ptr(),"set_shortcut",InputEvent());
+ ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut());
+ ur->add_do_method(this,"_update_shortcuts");
+ ur->add_undo_method(this,"_update_shortcuts");
+ ur->add_do_method(this,"_settings_changed");
+ ur->add_undo_method(this,"_settings_changed");
+ ur->commit_action();
+ } else if (p_idx==2) {//revert to original
+ if (!sc.is_valid())
+ return; //pointless, there is nothing
+
+ InputEvent original = sc->get_meta("original");
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Restore Shortcut");
+ ur->add_do_method(sc.ptr(),"set_shortcut",original);
+ ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut());
+ ur->add_do_method(this,"_update_shortcuts");
+ ur->add_undo_method(this,"_update_shortcuts");
+ ur->add_do_method(this,"_settings_changed");
+ ur->add_undo_method(this,"_settings_changed");
+ ur->commit_action();
+ }
+}
+
+
+void EditorSettingsDialog::_wait_for_key(const InputEvent& p_event) {
+
+
+ if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode!=0) {
+
+ last_wait_for_key=p_event;
+ String str=keycode_get_string(p_event.key.scancode).capitalize();
+ if (p_event.key.mod.meta)
+ str=TTR("Meta+")+str;
+ if (p_event.key.mod.shift)
+ str=TTR("Shift+")+str;
+ if (p_event.key.mod.alt)
+ str=TTR("Alt+")+str;
+ if (p_event.key.mod.control)
+ str=TTR("Control+")+str;
+
+
+ press_a_key_label->set_text(str);
+ press_a_key->accept_event();
+
+ }
+}
+
+
+
+
+void EditorSettingsDialog::_press_a_key_confirm() {
+
+ if (last_wait_for_key.type!=InputEvent::KEY)
+ return;
+
+ InputEvent ie;
+ ie.type=InputEvent::KEY;
+ ie.key.scancode=last_wait_for_key.key.scancode;
+ ie.key.mod=last_wait_for_key.key.mod;
+
+ Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured);
+
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Shortcut '"+shortcut_configured+"'");
+ ur->add_do_method(sc.ptr(),"set_shortcut",ie);
+ ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut());
+ ur->add_do_method(this,"_update_shortcuts");
+ ur->add_undo_method(this,"_update_shortcuts");
+ ur->add_do_method(this,"_settings_changed");
+ ur->add_undo_method(this,"_settings_changed");
+ ur->commit_action();
+
+
+
+}
+
+void EditorSettingsDialog::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_settings_save"),&EditorSettingsDialog::_settings_save);
+ ClassDB::bind_method(D_METHOD("_settings_changed"),&EditorSettingsDialog::_settings_changed);
+ ClassDB::bind_method(D_METHOD("_settings_property_edited"),&EditorSettingsDialog::_settings_property_edited);
+ ClassDB::bind_method(D_METHOD("_clear_search_box"),&EditorSettingsDialog::_clear_search_box);
+ ClassDB::bind_method(D_METHOD("_clear_shortcut_search_box"),&EditorSettingsDialog::_clear_shortcut_search_box);
+ ClassDB::bind_method(D_METHOD("_shortcut_button_pressed"),&EditorSettingsDialog::_shortcut_button_pressed);
+ ClassDB::bind_method(D_METHOD("_filter_shortcuts"),&EditorSettingsDialog::_filter_shortcuts);
+ ClassDB::bind_method(D_METHOD("_update_shortcuts"),&EditorSettingsDialog::_update_shortcuts);
+ ClassDB::bind_method(D_METHOD("_press_a_key_confirm"),&EditorSettingsDialog::_press_a_key_confirm);
+ ClassDB::bind_method(D_METHOD("_wait_for_key"),&EditorSettingsDialog::_wait_for_key);
+
+}
+
+EditorSettingsDialog::EditorSettingsDialog() {
+
+ set_title(TTR("Editor Settings"));
+ set_resizable(true);
+
+ tabs = memnew( TabContainer );
+ add_child(tabs);
+ //set_child_rect(tabs);
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ tabs->add_child(vbc);
+ vbc->set_name(TTR("General"));
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vbc->add_child(hbc);
+
+ Label *l = memnew( Label );
+ l->set_text(TTR("Search:")+" ");
+ hbc->add_child(l);
+
+ search_box = memnew( LineEdit );
+ search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbc->add_child(search_box);
+
+ clear_button = memnew( ToolButton );
+ hbc->add_child(clear_button);
+ clear_button->connect("pressed",this,"_clear_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);
+ property_editor->get_property_editor()->connect("property_edited", this, "_settings_property_edited");
+
+ vbc = memnew( VBoxContainer );
+ tabs->add_child(vbc);
+ vbc->set_name(TTR("Shortcuts"));
+
+ hbc = memnew( HBoxContainer );
+ hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vbc->add_child(hbc);
+
+ l = memnew( Label );
+ l->set_text(TTR("Search:")+" ");
+ hbc->add_child(l);
+
+ shortcut_search_box = memnew( LineEdit );
+ shortcut_search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hbc->add_child(shortcut_search_box);
+ shortcut_search_box->connect("text_changed", this, "_filter_shortcuts");
+
+ shortcut_clear_button = memnew( ToolButton );
+ hbc->add_child(shortcut_clear_button);
+ shortcut_clear_button->connect("pressed",this,"_clear_shortcut_search_box");
+
+ shortcuts = memnew( Tree );
+ vbc->add_margin_child("Shortcut List:",shortcuts,true);
+ shortcuts->set_columns(2);
+ shortcuts->set_hide_root(true);
+ //shortcuts->set_hide_folding(true);
+ shortcuts->set_column_titles_visible(true);
+ shortcuts->set_column_title(0,"Name");
+ shortcuts->set_column_title(1,"Binding");
+ shortcuts->connect("button_pressed",this,"_shortcut_button_pressed");
+
+ press_a_key = memnew( ConfirmationDialog );
+ press_a_key->set_focus_mode(FOCUS_ALL);
+ add_child(press_a_key);
+
+ l = memnew( Label );
+ l->set_text(TTR("Press a Key.."));
+ l->set_area_as_parent_rect();
+ l->set_align(Label::ALIGN_CENTER);
+ l->set_margin(MARGIN_TOP,20);
+ l->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,30);
+ press_a_key_label=l;
+ press_a_key->add_child(l);
+ press_a_key->connect("gui_input",this,"_wait_for_key");
+ press_a_key->connect("confirmed",this,"_press_a_key_confirm");
+ //Button *load = memnew( Button );
+
+ //load->set_text("Load..");
+ //hbc->add_child(load);
+
+
+ //get_ok()->set_text("Apply");
+ set_hide_on_ok(true);
+ //get_cancel()->set_text("Close");
+
+ timer = memnew( Timer );
+ timer->set_wait_time(1.5);
+ timer->connect("timeout",this,"_settings_save");
+ timer->set_one_shot(true);
+ add_child(timer);
+ EditorSettings::get_singleton()->connect("settings_changed",this,"_settings_changed");
+ get_ok()->set_text(TTR("Close"));
+
+ updating=false;
+
+}
diff --git a/tools/editor/settings_config_dialog.h b/editor/settings_config_dialog.h
index 17a05c27d3..17a05c27d3 100644
--- a/tools/editor/settings_config_dialog.h
+++ b/editor/settings_config_dialog.h
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
new file mode 100644
index 0000000000..825db5356b
--- /dev/null
+++ b/editor/spatial_editor_gizmos.cpp
@@ -0,0 +1,3483 @@
+/*************************************************************************/
+/* spatial_editor_gizmos.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "spatial_editor_gizmos.h"
+
+#include "geometry.h"
+#include "scene/3d/camera.h"
+#include "scene/resources/surface_tool.h"
+#include "scene/resources/sphere_shape.h"
+#include "scene/resources/box_shape.h"
+#include "scene/resources/capsule_shape.h"
+#include "scene/resources/ray_shape.h"
+#include "scene/resources/convex_polygon_shape.h"
+#include "scene/resources/plane_shape.h"
+#include "quick_hull.h"
+
+// Keep small children away from this file.
+// It's so ugly it will eat them alive
+
+
+
+#define HANDLE_HALF_SIZE 0.05
+
+void EditorSpatialGizmo::clear() {
+
+ for(int i=0;i<instances.size();i++) {
+
+ if (instances[i].instance.is_valid())
+ VS::get_singleton()->free(instances[i].instance);
+
+
+ }
+
+ billboard_handle=false;
+ collision_segments.clear();
+ collision_mesh=Ref<TriangleMesh>();
+ instances.clear();
+ handles.clear();
+ secondary_handles.clear();
+}
+
+void EditorSpatialGizmo::redraw() {
+
+ if (get_script_instance() && get_script_instance()->has_method("redraw"))
+ get_script_instance()->call("redraw");
+
+
+}
+
+void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) {
+
+ instance = VS::get_singleton()->instance_create2(mesh->get_rid(),p_base->get_world()->get_scenario());
+ VS::get_singleton()->instance_attach_object_instance_ID(instance,p_base->get_instance_ID());
+ if (billboard)
+ VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_BILLBOARD,true);
+ if (unscaled)
+ VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_DEPH_SCALE,true);
+ if (skeleton.is_valid())
+ VS::get_singleton()->instance_attach_skeleton(instance,skeleton);
+ if (extra_margin)
+ VS::get_singleton()->instance_set_extra_visibility_margin(instance,1);
+ VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance,VS::SHADOW_CASTING_SETTING_OFF);
+ VS::get_singleton()->instance_set_layer_mask(instance,1<<SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26
+}
+
+
+
+void EditorSpatialGizmo::add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard, const RID &p_skeleton) {
+
+ ERR_FAIL_COND(!spatial_node);
+ Instance ins;
+
+ ins.billboard=p_billboard;
+ ins.mesh=p_mesh;
+ ins.skeleton=p_skeleton;
+ if (valid) {
+ ins.create_instance(spatial_node);
+ VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
+ }
+
+ instances.push_back(ins);
+
+}
+
+void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material,bool p_billboard){
+
+ ERR_FAIL_COND(!spatial_node);
+ Instance ins;
+
+ Ref<Mesh> mesh = memnew( Mesh );
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+
+ a[Mesh::ARRAY_VERTEX]=p_lines;
+
+ PoolVector<Color> color;
+ color.resize(p_lines.size());
+ {
+ PoolVector<Color>::Write w = color.write();
+ for(int i=0;i<p_lines.size();i++) {
+ if (is_selected())
+ w[i]=Color(1,1,1,0.6);
+ else
+ w[i]=Color(1,1,1,0.25);
+ }
+
+ }
+
+ a[Mesh::ARRAY_COLOR]=color;
+
+
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,a);
+ mesh->surface_set_material(0,p_material);
+
+ if (p_billboard) {
+ float md=0;
+ for(int i=0;i<p_lines.size();i++) {
+
+ md=MAX(0,p_lines[i].length());
+
+ }
+ if (md) {
+ mesh->set_custom_aabb(Rect3(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
+ }
+ }
+
+ ins.billboard=p_billboard;
+ ins.mesh=mesh;
+ if (valid) {
+ ins.create_instance(spatial_node);
+ VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
+ }
+
+ instances.push_back(ins);
+
+}
+
+void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material>& p_material,float p_scale) {
+
+ ERR_FAIL_COND(!spatial_node);
+ Instance ins;
+
+ Vector<Vector3 > vs;
+ Vector<Vector2 > uv;
+
+ vs.push_back(Vector3(-p_scale,p_scale,0));
+ vs.push_back(Vector3(p_scale,p_scale,0));
+ vs.push_back(Vector3(p_scale,-p_scale,0));
+ vs.push_back(Vector3(-p_scale,-p_scale,0));
+
+ uv.push_back(Vector2(1,0));
+ uv.push_back(Vector2(0,0));
+ uv.push_back(Vector2(0,1));
+ uv.push_back(Vector2(1,1));
+
+ Ref<Mesh> mesh = memnew( Mesh );
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[Mesh::ARRAY_VERTEX]=vs;
+ a[Mesh::ARRAY_TEX_UV]=uv;
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLE_FAN,a);
+ mesh->surface_set_material(0,p_material);
+
+ if (true) {
+ float md=0;
+ for(int i=0;i<vs.size();i++) {
+
+ md=MAX(0,vs[i].length());
+
+ }
+ if (md) {
+ mesh->set_custom_aabb(Rect3(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
+ }
+ }
+
+ ins.mesh=mesh;
+ ins.unscaled=true;
+ ins.billboard=true;
+ if (valid) {
+ ins.create_instance(spatial_node);
+ VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
+ }
+
+ instances.push_back(ins);
+
+
+}
+
+void EditorSpatialGizmo::add_collision_triangles(const Ref<TriangleMesh>& p_tmesh) {
+
+ collision_mesh=p_tmesh;
+}
+
+void EditorSpatialGizmo::add_collision_segments(const Vector<Vector3> &p_lines) {
+
+ int from=collision_segments.size();
+ collision_segments.resize(from+p_lines.size());
+ for(int i=0;i<p_lines.size();i++) {
+
+ collision_segments[from+i]=p_lines[i];
+ }
+}
+
+
+void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_billboard,bool p_secondary){
+
+ billboard_handle=p_billboard;
+
+ if (!is_selected())
+ return;
+
+ ERR_FAIL_COND(!spatial_node);
+
+ ERR_FAIL_COND(!spatial_node);
+ Instance ins;
+
+
+ Ref<Mesh> mesh = memnew( Mesh );
+#if 1
+
+ Array a;
+ a.resize(VS::ARRAY_MAX);
+ a[VS::ARRAY_VERTEX]=p_handles;
+ print_line("handles?: "+itos(p_handles.size()));
+ PoolVector<Color> colors;
+ {
+ colors.resize(p_handles.size());
+ PoolVector<Color>::Write w=colors.write();
+ for(int i=0;i<p_handles.size();i++) {
+
+ Color col(1,1,1,1);
+ if (SpatialEditor::get_singleton()->get_over_gizmo_handle()!=i)
+ col=Color(0.9,0.9,0.9,0.9);
+ w[i]=col;
+ }
+
+ }
+ a[VS::ARRAY_COLOR]=colors;
+ mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS,a);
+ mesh->surface_set_material(0,SpatialEditorGizmos::singleton->handle2_material);
+
+ if (p_billboard) {
+ float md=0;
+ for(int i=0;i<p_handles.size();i++) {
+
+ md=MAX(0,p_handles[i].length());
+
+ }
+ if (md) {
+ mesh->set_custom_aabb(Rect3(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
+ }
+ }
+
+
+
+#else
+ for(int ih=0;ih<p_handles.size();ih++) {
+
+
+ Vector<Vector3> vertices;
+ Vector<Vector3> normals;
+
+ int vtx_idx=0;
+
+#define ADD_VTX(m_idx) \
+ vertices.push_back( (face_points[m_idx]*HANDLE_HALF_SIZE+p_handles[ih]) );\
+ normals.push_back( normal_points[m_idx] );\
+ vtx_idx++;\
+
+ for (int i=0;i<6;i++) {
+
+
+ Vector3 face_points[4];
+ Vector3 normal_points[4];
+ float uv_points[8]={0,0,0,1,1,1,1,0};
+
+ for (int j=0;j<4;j++) {
+
+ float v[3];
+ v[0]=1.0;
+ v[1]=1-2*((j>>1)&1);
+ v[2]=v[1]*(1-2*(j&1));
+
+ for (int k=0;k<3;k++) {
+
+ if (i<3)
+ face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ else
+ face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ }
+ normal_points[j]=Vector3();
+ normal_points[j][i%3]=(i>=3?-1:1);
+ }
+ //tri 1
+ ADD_VTX(0);
+ ADD_VTX(1);
+ ADD_VTX(2);
+ //tri 2
+ ADD_VTX(2);
+ ADD_VTX(3);
+ ADD_VTX(0);
+
+ }
+
+
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+ d[VisualServer::ARRAY_NORMAL]= normals ;
+ d[VisualServer::ARRAY_VERTEX]= vertices ;
+
+ mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d);
+ mesh->surface_set_material(ih,SpatialEditorGizmos::singleton->handle_material);
+
+
+ }
+#endif
+ ins.mesh=mesh;
+ ins.billboard=p_billboard;
+ ins.extra_margin=true;
+ if (valid) {
+ ins.create_instance(spatial_node);
+ VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
+ }
+ instances.push_back(ins);
+ if (!p_secondary) {
+ int chs=handles.size();
+ handles.resize(chs+p_handles.size());
+ for(int i=0;i<p_handles.size();i++) {
+ handles[i+chs]=p_handles[i];
+ }
+ } else {
+
+ int chs=secondary_handles.size();
+ secondary_handles.resize(chs+p_handles.size());
+ for(int i=0;i<p_handles.size();i++) {
+ secondary_handles[i+chs]=p_handles[i];
+ }
+
+ }
+
+}
+
+
+void EditorSpatialGizmo::set_spatial_node(Spatial *p_node){
+
+ ERR_FAIL_NULL(p_node);
+ spatial_node=p_node;
+
+}
+
+bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum) {
+
+ ERR_FAIL_COND_V(!spatial_node,false);
+ ERR_FAIL_COND_V(!valid,false);
+
+ if (collision_segments.size()) {
+
+ const Plane *p=p_frustum.ptr();
+ int fc=p_frustum.size();
+
+ int vc=collision_segments.size();
+ const Vector3* vptr=collision_segments.ptr();
+ Transform t = spatial_node->get_global_transform();
+
+ for(int i=0;i<vc/2;i++) {
+
+
+ Vector3 a=t.xform(vptr[i*2+0]);
+ Vector3 b=t.xform(vptr[i*2+1]);
+
+ bool any_out=false;
+ for(int j=0;j<fc;j++) {
+
+ if (p[j].distance_to(a) > 0 && p[j].distance_to(b) >0) {
+
+ any_out=true;
+ break;
+ }
+ }
+
+ if (!any_out)
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+
+bool EditorSpatialGizmo::intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle,bool p_sec_first) {
+
+ ERR_FAIL_COND_V(!spatial_node,false);
+ ERR_FAIL_COND_V(!valid,false);
+
+ if (r_gizmo_handle) {
+
+ Transform t = spatial_node->get_global_transform();
+ t.orthonormalize();
+ if (billboard_handle) {
+ t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
+ }
+
+ float min_d=1e20;
+ int idx=-1;
+
+ for(int i=0;i<secondary_handles.size();i++) {
+
+ Vector3 hpos = t.xform(secondary_handles[i]);
+ Vector2 p = p_camera->unproject_position(hpos);
+ if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) {
+
+
+ real_t dp = p_camera->get_transform().origin.distance_to(hpos);
+ if (dp<min_d) {
+
+ r_pos=t.xform(hpos);
+ r_normal=p_camera->get_transform().basis.get_axis(2);
+ min_d=dp;
+ idx=i+handles.size();
+
+ }
+ }
+ }
+
+ if (p_sec_first && idx!=-1) {
+
+ *r_gizmo_handle=idx;
+ return true;
+ }
+
+ min_d=1e20;
+
+ for(int i=0;i<handles.size();i++) {
+
+ Vector3 hpos = t.xform(handles[i]);
+ Vector2 p = p_camera->unproject_position(hpos);
+ if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) {
+
+
+ real_t dp = p_camera->get_transform().origin.distance_to(hpos);
+ if (dp<min_d) {
+
+ r_pos=t.xform(hpos);
+ r_normal=p_camera->get_transform().basis.get_axis(2);
+ min_d=dp;
+ idx=i;
+
+ }
+ }
+ }
+
+ if (idx>=0) {
+ *r_gizmo_handle=idx;
+ return true;
+ }
+
+
+ }
+
+ if (collision_segments.size()) {
+
+ Plane camp(p_camera->get_transform().origin,(-p_camera->get_transform().basis.get_axis(2)).normalized());
+
+ int vc=collision_segments.size();
+ const Vector3* vptr=collision_segments.ptr();
+ Transform t = spatial_node->get_global_transform();
+ if (billboard_handle) {
+ t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
+ }
+
+ Vector3 cp;
+ float cpd=1e20;
+
+ for(int i=0;i<vc/2;i++) {
+
+
+ Vector3 a=t.xform(vptr[i*2+0]);
+ Vector3 b=t.xform(vptr[i*2+1]);
+ Vector2 s[2];
+ s[0] = p_camera->unproject_position(a);
+ s[1] = p_camera->unproject_position(b);
+
+
+ Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point,s);
+
+ float pd = p.distance_to(p_point);
+
+ if (pd<cpd) {
+
+
+ float d = s[0].distance_to(s[1]);
+ Vector3 tcp;
+ if (d>0) {
+
+ float d2=s[0].distance_to(p)/d;
+ tcp = a+(b-a)*d2;
+
+ } else {
+ tcp=a;
+
+ }
+
+ if (camp.distance_to(tcp)<p_camera->get_znear())
+ continue;
+ cp=tcp;
+ cpd=pd;
+ }
+ }
+
+ if (cpd<8) {
+
+ r_pos=cp;
+ r_normal=-p_camera->project_ray_normal(p_point);
+ return true;
+ }
+
+ return false;
+ }
+
+
+ if (collision_mesh.is_valid()) {
+ Transform gt = spatial_node->get_global_transform();
+
+ if (billboard_handle) {
+ gt.set_look_at(gt.origin,gt.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
+ }
+
+ Transform ai=gt.affine_inverse();
+ Vector3 ray_from = ai.xform(p_camera->project_ray_origin(p_point));
+ Vector3 ray_dir=ai.basis.xform(p_camera->project_ray_normal(p_point)).normalized();
+ Vector3 rpos,rnorm;
+
+
+ if (collision_mesh->intersect_ray(ray_from,ray_dir,rpos,rnorm)) {
+
+ r_pos=gt.xform(rpos);
+ r_normal=gt.basis.xform(rnorm).normalized();
+ return true;
+ }
+ }
+
+ return false;
+
+}
+
+
+
+void EditorSpatialGizmo::create() {
+
+ ERR_FAIL_COND(!spatial_node);
+ ERR_FAIL_COND(valid);
+ valid=true;
+
+ for(int i=0;i<instances.size();i++) {
+
+ instances[i].create_instance(spatial_node);
+ }
+
+ transform();
+
+}
+
+void EditorSpatialGizmo::transform(){
+
+ ERR_FAIL_COND(!spatial_node);
+ ERR_FAIL_COND(!valid);
+ for(int i=0;i<instances.size();i++) {
+ VS::get_singleton()->instance_set_transform(instances[i].instance,spatial_node->get_global_transform());
+ }
+
+}
+
+
+void EditorSpatialGizmo::free(){
+
+ ERR_FAIL_COND(!spatial_node);
+ ERR_FAIL_COND(!valid);
+
+ for(int i=0;i<instances.size();i++) {
+
+ if (instances[i].instance.is_valid())
+ VS::get_singleton()->free(instances[i].instance);
+ instances[i].instance=RID();
+ }
+
+ valid=false;
+
+
+}
+
+
+void EditorSpatialGizmo::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("add_lines","lines","material:Material","billboard"),&EditorSpatialGizmo::add_lines,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_mesh","mesh:Mesh","billboard","skeleton"),&EditorSpatialGizmo::add_mesh,DEFVAL(false),DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("add_collision_segments","segments"),&EditorSpatialGizmo::add_collision_segments);
+ ClassDB::bind_method(D_METHOD("add_collision_triangles","triangles:TriangleMesh"),&EditorSpatialGizmo::add_collision_triangles);
+ ClassDB::bind_method(D_METHOD("add_unscaled_billboard","material:Material","default_scale"),&EditorSpatialGizmo::add_unscaled_billboard,DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("add_handles","handles","billboard","secondary"),&EditorSpatialGizmo::add_handles,DEFVAL(false),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_spatial_node","node:Spatial"),&EditorSpatialGizmo::_set_spatial_node);
+ ClassDB::bind_method(D_METHOD("clear"),&EditorSpatialGizmo::clear);
+
+ BIND_VMETHOD( MethodInfo("redraw"));
+ BIND_VMETHOD( MethodInfo(Variant::STRING,"get_handle_name",PropertyInfo(Variant::INT,"index")));
+ BIND_VMETHOD( MethodInfo("get_handle_value:Variant",PropertyInfo(Variant::INT,"index")));
+ BIND_VMETHOD( MethodInfo("set_handle",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::OBJECT,"camera:Camera"),PropertyInfo(Variant::VECTOR2,"point")));
+ MethodInfo cm = MethodInfo("commit_handle",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::NIL,"restore:Variant"),PropertyInfo(Variant::BOOL,"cancel"));
+ cm.default_arguments.push_back(false);
+ BIND_VMETHOD( cm );
+}
+
+EditorSpatialGizmo::EditorSpatialGizmo() {
+ valid=false;
+ billboard_handle=false;
+ base=NULL;
+ spatial_node=NULL;
+}
+
+EditorSpatialGizmo::~EditorSpatialGizmo(){
+
+ clear();
+}
+
+Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const {
+
+ ERR_FAIL_INDEX_V(p_idx,handles.size(),Vector3());
+
+ return handles[p_idx];
+
+}
+
+//// light gizmo
+
+
+String LightSpatialGizmo::get_handle_name(int p_idx) const {
+
+ if (p_idx==0)
+ return "Radius";
+ else
+ return "Aperture";
+}
+
+
+Variant LightSpatialGizmo::get_handle_value(int p_idx) const{
+
+ if (p_idx==0)
+ return light->get_param(Light::PARAM_RANGE);
+ if (p_idx==1)
+ return light->get_param(Light::PARAM_SPOT_ANGLE);
+
+ return Variant();
+}
+
+
+static float _find_closest_angle_to_half_pi_arc(const Vector3& p_from, const Vector3& p_to, float p_arc_radius,const Transform& p_arc_xform) {
+
+ //bleh, discrete is simpler
+ static const int arc_test_points=64;
+ float min_d = 1e20;
+ Vector3 min_p;
+
+
+ for(int i=0;i<arc_test_points;i++) {
+
+ float a = i*Math_PI*0.5/arc_test_points;
+ float an = (i+1)*Math_PI*0.5/arc_test_points;
+ Vector3 p=Vector3( Math::cos(a), 0, -Math::sin(a) )*p_arc_radius;
+ Vector3 n=Vector3( Math::cos(an), 0,- Math::sin(an) )*p_arc_radius;
+
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(p,n,p_from,p_to,ra,rb);
+
+ float d = ra.distance_to(rb);
+ if (d<min_d) {
+ min_d=d;
+ min_p=ra;
+ }
+
+ }
+
+ //min_p = p_arc_xform.affine_inverse().xform(min_p);
+ float a = Vector2(min_p.x,-min_p.z).angle();
+ return a*180.0/Math_PI;
+}
+
+
+void LightSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point) {
+
+ Transform gt = light->get_global_transform();
+ gt.orthonormalize();
+ Transform gi = gt.affine_inverse();
+
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
+ if (p_idx==0) {
+
+ if (light->cast_to<SpotLight>()) {
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,-4096),s[0],s[1],ra,rb);
+
+ float d = -ra.z;
+ if (d<0)
+ d=0;
+
+ light->set_param(Light::PARAM_RANGE,d);
+ } else if (light->cast_to<OmniLight>()) {
+
+ Plane cp=Plane( gt.origin, p_camera->get_transform().basis.get_axis(2));
+
+ Vector3 inters;
+ if (cp.intersects_ray(ray_from,ray_dir,&inters)) {
+
+ float r = inters.distance_to(gt.origin);
+ light->set_param(Light::PARAM_RANGE,r);
+ }
+
+ }
+
+ } else if (p_idx==1) {
+
+ float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],light->get_param(Light::PARAM_RANGE),gt);
+ light->set_param(Light::PARAM_SPOT_ANGLE,CLAMP(a,0.01,89.99));
+ }
+}
+
+void LightSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+
+ if (p_cancel) {
+
+ light->set_param(p_idx==0?Light::PARAM_RANGE:Light::PARAM_SPOT_ANGLE,p_restore);
+
+ } else if (p_idx==0) {
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Light Radius"));
+ ur->add_do_method(light,"set_param",Light::PARAM_RANGE,light->get_param(Light::PARAM_RANGE));
+ ur->add_undo_method(light,"set_param",Light::PARAM_RANGE,p_restore);
+ ur->commit_action();
+ } else if (p_idx==1) {
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Light Radius"));
+ ur->add_do_method(light,"set_param",Light::PARAM_SPOT_ANGLE,light->get_param(Light::PARAM_SPOT_ANGLE));
+ ur->add_undo_method(light,"set_param",Light::PARAM_SPOT_ANGLE,p_restore);
+ ur->commit_action();
+
+ }
+}
+
+
+
+void LightSpatialGizmo::redraw() {
+
+
+ if (light->cast_to<DirectionalLight>()) {
+
+
+
+ const int arrow_points=5;
+ Vector3 arrow[arrow_points]={
+ Vector3(0,0,2),
+ Vector3(1,1,2),
+ Vector3(1,1,-1),
+ Vector3(2,2,-1),
+ Vector3(0,0,-3)
+ };
+
+ int arrow_sides=4;
+
+ Vector<Vector3> lines;
+
+
+ for(int i = 0; i < arrow_sides ; i++) {
+
+
+ Basis ma(Vector3(0,0,1),Math_PI*2*float(i)/arrow_sides);
+ Basis mb(Vector3(0,0,1),Math_PI*2*float(i+1)/arrow_sides);
+
+
+ for(int j=1;j<arrow_points-1;j++) {
+
+ if (j!=2) {
+ lines.push_back(ma.xform(arrow[j]));
+ lines.push_back(ma.xform(arrow[j+1]));
+ }
+ if (j<arrow_points-1) {
+ lines.push_back(ma.xform(arrow[j]));
+ lines.push_back(mb.xform(arrow[j]));
+ }
+
+ }
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->light_material);
+ add_collision_segments(lines);
+ add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_directional_icon,0.05);
+
+ }
+
+ if (light->cast_to<OmniLight>()) {
+
+ clear();
+
+
+ OmniLight *on = light->cast_to<OmniLight>();
+
+ float r = on->get_param(Light::PARAM_RANGE);
+
+ Vector<Vector3> points;
+
+ for(int i=0;i<=360;i++) {
+
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
+
+ /*points.push_back(Vector3(a.x,0,a.y));
+ points.push_back(Vector3(b.x,0,b.y));
+ points.push_back(Vector3(0,a.x,a.y));
+ points.push_back(Vector3(0,b.x,b.y));*/
+ points.push_back(Vector3(a.x,a.y,0));
+ points.push_back(Vector3(b.x,b.y,0));
+
+ }
+
+ add_lines(points,SpatialEditorGizmos::singleton->light_material,true);
+ add_collision_segments(points);
+
+ add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05);
+
+ Vector<Vector3> handles;
+ handles.push_back(Vector3(r,0,0));
+ add_handles(handles,true);
+
+
+ }
+
+
+ if (light->cast_to<SpotLight>()) {
+
+ clear();
+
+ Vector<Vector3> points;
+ SpotLight *on = light->cast_to<SpotLight>();
+
+ float r = on->get_param(Light::PARAM_RANGE);
+ float w = r*Math::sin(Math::deg2rad(on->get_param(Light::PARAM_SPOT_ANGLE)));
+ float d = r*Math::cos(Math::deg2rad(on->get_param(Light::PARAM_SPOT_ANGLE)));
+
+
+
+ for(int i=0;i<360;i++) {
+
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
+
+ /*points.push_back(Vector3(a.x,0,a.y));
+ points.push_back(Vector3(b.x,0,b.y));
+ points.push_back(Vector3(0,a.x,a.y));
+ points.push_back(Vector3(0,b.x,b.y));*/
+ points.push_back(Vector3(a.x,a.y,-d));
+ points.push_back(Vector3(b.x,b.y,-d));
+
+ if (i%90==0) {
+
+ points.push_back(Vector3(a.x,a.y,-d));
+ points.push_back(Vector3());
+
+ }
+
+
+ }
+
+ points.push_back(Vector3(0,0,-r));
+ points.push_back(Vector3());
+
+ add_lines(points,SpatialEditorGizmos::singleton->light_material);
+
+ Vector<Vector3> handles;
+ handles.push_back(Vector3(0,0,-r));
+
+ Vector<Vector3> collision_segments;
+
+ for(int i=0;i<64;i++) {
+
+ float ra=i*Math_PI*2.0/64.0;
+ float rb=(i+1)*Math_PI*2.0/64.0;
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
+
+ collision_segments.push_back(Vector3(a.x,a.y,-d));
+ collision_segments.push_back(Vector3(b.x,b.y,-d));
+
+ if (i%16==0) {
+
+ collision_segments.push_back(Vector3(a.x,a.y,-d));
+ collision_segments.push_back(Vector3());
+
+ }
+
+ if (i==16) {
+
+ handles.push_back(Vector3(a.x,a.y,-d));
+ }
+
+ }
+
+ collision_segments.push_back(Vector3(0,0,-r));
+ collision_segments.push_back(Vector3());
+
+
+ add_handles(handles);
+ add_collision_segments(collision_segments);
+ add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05);
+
+ }
+
+}
+
+LightSpatialGizmo::LightSpatialGizmo(Light* p_light){
+
+ light=p_light;
+ set_spatial_node(p_light);
+
+}
+
+//////
+
+String CameraSpatialGizmo::get_handle_name(int p_idx) const {
+
+ if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
+ return "FOV";
+ } else {
+ return "Size";
+ }
+}
+Variant CameraSpatialGizmo::get_handle_value(int p_idx) const{
+
+ if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
+ return camera->get_fov();
+ } else {
+
+ return camera->get_size();
+ }
+}
+void CameraSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
+
+ Transform gt = camera->get_global_transform();
+ gt.orthonormalize();
+ Transform gi = gt.affine_inverse();
+
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
+
+ if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
+ Transform gt=camera->get_global_transform();
+ float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],1.0,gt);
+ camera->set("fov",a);
+ } else {
+
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(0,0,-1),Vector3(4096,0,-1),s[0],s[1],ra,rb);
+ float d = ra.x * 2.0;
+ if (d<0)
+ d=0;
+
+ camera->set("size",d);
+ }
+
+}
+void CameraSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+
+ if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
+
+ if (p_cancel) {
+
+ camera->set("fov",p_restore);
+ } else {
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Camera FOV"));
+ ur->add_do_property(camera,"fov",camera->get_fov());
+ ur->add_undo_property(camera,"fov",p_restore);
+ ur->commit_action();
+ }
+
+ } else {
+
+ if (p_cancel) {
+
+ camera->set("size",p_restore);
+ } else {
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Camera Size"));
+ ur->add_do_property(camera,"size",camera->get_size());
+ ur->add_undo_property(camera,"size",p_restore);
+ ur->commit_action();
+ }
+
+ }
+
+}
+
+void CameraSpatialGizmo::redraw(){
+
+ clear();
+
+ Vector<Vector3> lines;
+ Vector<Vector3> handles;
+
+
+ switch(camera->get_projection()) {
+
+ case Camera::PROJECTION_PERSPECTIVE: {
+
+ float fov = camera->get_fov();
+
+ Vector3 side=Vector3( Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov)) );
+ Vector3 nside=side;
+ nside.x=-nside.x;
+ Vector3 up=Vector3(0,side.x,0);
+
+
+#define ADD_TRIANGLE( m_a, m_b, m_c)\
+{\
+ lines.push_back(m_a);\
+ lines.push_back(m_b);\
+ lines.push_back(m_b);\
+ lines.push_back(m_c);\
+ lines.push_back(m_c);\
+ lines.push_back(m_a);\
+}
+
+ ADD_TRIANGLE( Vector3(), side+up, side-up );
+ ADD_TRIANGLE( Vector3(), nside+up, nside-up );
+ ADD_TRIANGLE( Vector3(), side+up, nside+up );
+ ADD_TRIANGLE( Vector3(), side-up, nside-up );
+
+ handles.push_back(side);
+ side.x*=0.25;
+ nside.x*=0.25;
+ Vector3 tup( 0, up.y*3/2,side.z);
+ ADD_TRIANGLE( tup, side+up, nside+up );
+
+ } break;
+ case Camera::PROJECTION_ORTHOGONAL: {
+
+#define ADD_QUAD( m_a, m_b, m_c, m_d)\
+{\
+ lines.push_back(m_a);\
+ lines.push_back(m_b);\
+ lines.push_back(m_b);\
+ lines.push_back(m_c);\
+ lines.push_back(m_c);\
+ lines.push_back(m_d);\
+ lines.push_back(m_d);\
+ lines.push_back(m_a);\
+}
+ float size = camera->get_size();
+
+ float hsize=size*0.5;
+ Vector3 right(hsize,0,0);
+ Vector3 up(0,hsize,0);
+ Vector3 back(0,0,-1.0);
+ Vector3 front(0,0,0);
+
+ ADD_QUAD( -up-right,-up+right,up+right,up-right);
+ ADD_QUAD( -up-right+back,-up+right+back,up+right+back,up-right+back);
+ ADD_QUAD( up+right,up+right+back,up-right+back,up-right);
+ ADD_QUAD( -up+right,-up+right+back,-up-right+back,-up-right);
+ handles.push_back(right+back);
+
+ right.x*=0.25;
+ Vector3 tup( 0, up.y*3/2,back.z );
+ ADD_TRIANGLE( tup, right+up+back, -right+up+back );
+
+ } break;
+
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->camera_material);
+ add_collision_segments(lines);
+ add_handles(handles);
+}
+
+
+CameraSpatialGizmo::CameraSpatialGizmo(Camera* p_camera){
+
+ camera=p_camera;
+ set_spatial_node(camera);
+}
+
+
+
+
+//////
+
+void MeshInstanceSpatialGizmo::redraw() {
+
+ Ref<Mesh> m = mesh->get_mesh();
+ if (!m.is_valid())
+ return; //none
+
+ Ref<TriangleMesh> tm = m->generate_triangle_mesh();
+ if (tm.is_valid())
+ add_collision_triangles(tm);
+}
+
+MeshInstanceSpatialGizmo::MeshInstanceSpatialGizmo(MeshInstance* p_mesh) {
+
+ mesh=p_mesh;
+ set_spatial_node(p_mesh);
+}
+
+/////
+
+
+void Position3DSpatialGizmo::redraw() {
+
+ clear();
+ add_mesh(SpatialEditorGizmos::singleton->pos3d_mesh);
+ Vector<Vector3> cursor_points;
+ float cs = 0.25;
+ cursor_points.push_back(Vector3(+cs,0,0));
+ cursor_points.push_back(Vector3(-cs,0,0));
+ cursor_points.push_back(Vector3(0,+cs,0));
+ cursor_points.push_back(Vector3(0,-cs,0));
+ cursor_points.push_back(Vector3(0,0,+cs));
+ cursor_points.push_back(Vector3(0,0,-cs));
+ add_collision_segments(cursor_points);
+
+}
+
+
+Position3DSpatialGizmo::Position3DSpatialGizmo(Position3D* p_p3d) {
+
+ p3d=p_p3d;
+ set_spatial_node(p3d);
+}
+
+
+/////
+
+void SkeletonSpatialGizmo::redraw() {
+
+ clear();
+
+ Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
+
+
+ surface_tool->begin(Mesh::PRIMITIVE_LINES);
+ surface_tool->set_material(SpatialEditorGizmos::singleton->skeleton_material);
+ Vector<Transform> grests;
+ grests.resize(skel->get_bone_count());
+
+ Vector<int> bones;
+ Vector<float> weights;
+ bones.resize(4);
+ weights.resize(4);
+
+ for(int i=0;i<4;i++) {
+ bones[i]=0;
+ weights[i]=0;
+ }
+
+ weights[0]=1;
+
+
+ Rect3 aabb;
+
+ Color bonecolor = Color(1.0,0.4,0.4,0.3);
+ Color rootcolor = Color(0.4,1.0,0.4,0.1);
+
+ for (int i=0;i<skel->get_bone_count();i++) {
+
+ int parent = skel->get_bone_parent(i);
+
+ if (parent>=0) {
+ grests[i]=grests[parent] * skel->get_bone_rest(i);
+
+ Vector3 v0 = grests[parent].origin;
+ Vector3 v1 = grests[i].origin;
+ Vector3 d = (v1-v0).normalized();
+ float dist = v0.distance_to(v1);
+
+ //find closest axis
+ int closest=-1;
+ float closest_d = 0.0;
+
+ for(int j=0;j<3;j++) {
+ float dp = Math::abs(grests[parent].basis[j].normalized().dot(d));
+ if (j==0 || dp>closest_d)
+ closest=j;
+ }
+
+ //find closest other
+ Vector3 first;
+ Vector3 points[4];
+ int pointidx=0;
+ for(int j=0;j<3;j++) {
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(rootcolor);
+ surface_tool->add_vertex(v0-grests[parent].basis[j].normalized()*dist*0.05);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(rootcolor);
+ surface_tool->add_vertex(v0+grests[parent].basis[j].normalized()*dist*0.05);
+
+ if (j==closest)
+ continue;
+
+ Vector3 axis;
+ if (first==Vector3()) {
+ axis = d.cross(d.cross(grests[parent].basis[j])).normalized();
+ first=axis;
+ } else {
+ axis = d.cross(first).normalized();
+ }
+
+ for(int k=0;k<2;k++) {
+
+ if (k==1)
+ axis=-axis;
+ Vector3 point = v0+d*dist*0.2;
+ point+=axis*dist*0.1;
+
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(v0);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(point);
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(point);
+ bones[0]=i;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(v1);
+ points[pointidx++]=point;
+
+ }
+
+ }
+
+ SWAP( points[1],points[2] );
+ for(int j=0;j<4;j++) {
+
+
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(points[j]);
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(bonecolor);
+ surface_tool->add_vertex(points[(j+1)%4]);
+ }
+
+
+/*
+ bones[0]=parent;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(Color(0.4,1,0.4,0.4));
+ surface_tool->add_vertex(v0);
+ bones[0]=i;
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(Color(0.4,1,0.4,0.4));
+ surface_tool->add_vertex(v1);
+*/
+ } else {
+
+ grests[i]=skel->get_bone_rest(i);
+ bones[0]=i;
+ }
+/*
+ Transform t = grests[i];
+ t.orthonormalize();
+
+ for (int i=0;i<6;i++) {
+
+
+ Vector3 face_points[4];
+
+ for (int j=0;j<4;j++) {
+
+ float v[3];
+ v[0]=1.0;
+ v[1]=1-2*((j>>1)&1);
+ v[2]=v[1]*(1-2*(j&1));
+
+ for (int k=0;k<3;k++) {
+
+ if (i<3)
+ face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ else
+ face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ }
+ }
+
+ for(int j=0;j<4;j++) {
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
+ surface_tool->add_vertex(t.xform(face_points[j]*0.04));
+ surface_tool->add_bones(bones);
+ surface_tool->add_weights(weights);
+ surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
+ surface_tool->add_vertex(t.xform(face_points[(j+1)%4]*0.04));
+ }
+
+ }
+ */
+ }
+
+ Ref<Mesh> m = surface_tool->commit();
+ add_mesh(m,false,skel->get_skeleton());
+
+}
+
+SkeletonSpatialGizmo::SkeletonSpatialGizmo(Skeleton* p_skel) {
+
+ skel=p_skel;
+ set_spatial_node(p_skel);
+}
+
+
+
+void RoomSpatialGizmo::redraw() {
+
+ clear();
+ Ref<RoomBounds> roomie = room->get_room();
+ if (roomie.is_null())
+ return;
+ PoolVector<Face3> faces = roomie->get_geometry_hint();
+
+ Vector<Vector3> lines;
+ int fc=faces.size();
+ PoolVector<Face3>::Read r =faces.read();
+
+ Map<_EdgeKey,Vector3> edge_map;
+
+ for(int i=0;i<fc;i++) {
+
+ Vector3 fn = r[i].get_plane().normal;
+
+ for(int j=0;j<3;j++) {
+
+ _EdgeKey ek;
+ ek.from=r[i].vertex[j].snapped(CMP_EPSILON);
+ ek.to=r[i].vertex[(j+1)%3].snapped(CMP_EPSILON);
+ if (ek.from<ek.to)
+ SWAP(ek.from,ek.to);
+
+ Map<_EdgeKey,Vector3>::Element *E=edge_map.find(ek);
+
+ if (E) {
+
+ if (E->get().dot(fn) >0.9) {
+
+ E->get()=Vector3();
+ }
+
+ } else {
+
+ edge_map[ek]=fn;
+ }
+
+ }
+ }
+
+ for(Map<_EdgeKey,Vector3>::Element *E=edge_map.front();E;E=E->next()) {
+
+ if (E->get()!=Vector3()) {
+ lines.push_back(E->key().from);
+ lines.push_back(E->key().to);
+ }
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->room_material);
+ add_collision_segments(lines);
+
+}
+
+RoomSpatialGizmo::RoomSpatialGizmo(Room* p_room){
+
+ set_spatial_node(p_room);
+ room=p_room;
+}
+
+/////
+
+
+void PortalSpatialGizmo::redraw() {
+
+ clear();
+
+ Vector<Point2> points = portal->get_shape();
+ if (points.size()==0) {
+ return;
+ }
+
+ Vector<Vector3> lines;
+
+ Vector3 center;
+ for(int i=0;i<points.size();i++) {
+
+ Vector3 f;
+ f.x=points[i].x;
+ f.y=points[i].y;
+ Vector3 fn;
+ fn.x=points[(i+1)%points.size()].x;
+ fn.y=points[(i+1)%points.size()].y;
+ center+=f;
+
+ lines.push_back(f);
+ lines.push_back(fn);
+ }
+
+ center/=points.size();
+ lines.push_back(center);
+ lines.push_back(center+Vector3(0,0,1));
+
+ add_lines(lines,SpatialEditorGizmos::singleton->portal_material);
+ add_collision_segments(lines);
+
+}
+
+PortalSpatialGizmo::PortalSpatialGizmo(Portal* p_portal){
+
+ set_spatial_node(p_portal);
+ portal=p_portal;
+}
+
+/////
+
+
+void RayCastSpatialGizmo::redraw() {
+
+ clear();
+
+
+ Vector<Vector3> lines;
+
+ lines.push_back(Vector3());
+ lines.push_back(raycast->get_cast_to());
+
+ add_lines(lines,SpatialEditorGizmos::singleton->raycast_material);
+ add_collision_segments(lines);
+
+}
+
+RayCastSpatialGizmo::RayCastSpatialGizmo(RayCast* p_raycast) {
+
+ set_spatial_node(p_raycast);
+ raycast=p_raycast;
+}
+
+
+
+/////
+
+
+void VehicleWheelSpatialGizmo::redraw() {
+
+ clear();
+
+
+ Vector<Vector3> points;
+
+ float r = car_wheel->get_radius();
+ const int skip=10;
+ for(int i=0;i<=360;i+=skip) {
+
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+skip);
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
+
+ points.push_back(Vector3(0,a.x,a.y));
+ points.push_back(Vector3(0,b.x,b.y));
+
+ const int springsec=4;
+
+ for(int j=0;j<springsec;j++) {
+ float t = car_wheel->get_suspension_rest_length()*5;
+ points.push_back(Vector3(a.x,i/360.0*t/springsec+j*(t/springsec),a.y)*0.2);
+ points.push_back(Vector3(b.x,(i+skip)/360.0*t/springsec+j*(t/springsec),b.y)*0.2);
+ }
+
+
+ }
+
+ //travel
+ points.push_back(Vector3(0,0,0));
+ points.push_back(Vector3(0,car_wheel->get_suspension_rest_length(),0));
+
+ //axis
+ points.push_back(Vector3(r*0.2,car_wheel->get_suspension_rest_length(),0));
+ points.push_back(Vector3(-r*0.2,car_wheel->get_suspension_rest_length(),0));
+ //axis
+ points.push_back(Vector3(r*0.2,0,0));
+ points.push_back(Vector3(-r*0.2,0,0));
+
+ //forward line
+ points.push_back(Vector3(0,-r,0));
+ points.push_back(Vector3(0,-r,r*2));
+ points.push_back(Vector3(0,-r,r*2));
+ points.push_back(Vector3(r*2*0.2,-r,r*2*0.8));
+ points.push_back(Vector3(0,-r,r*2));
+ points.push_back(Vector3(-r*2*0.2,-r,r*2*0.8));
+
+ add_lines(points,SpatialEditorGizmos::singleton->car_wheel_material);
+ add_collision_segments(points);
+
+}
+
+VehicleWheelSpatialGizmo::VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel){
+
+ set_spatial_node(p_car_wheel);
+ car_wheel=p_car_wheel;
+}
+
+
+
+///
+
+void TestCubeSpatialGizmo::redraw() {
+
+ clear();
+ add_collision_triangles(SpatialEditorGizmos::singleton->test_cube_tm);
+}
+
+TestCubeSpatialGizmo::TestCubeSpatialGizmo(TestCube* p_tc) {
+
+ tc=p_tc;
+ set_spatial_node(p_tc);
+}
+
+
+///////////
+
+
+
+
+
+
+String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const {
+
+ Ref<Shape> s = cs->get_shape();
+ if (s.is_null())
+ return "";
+
+ if (s->cast_to<SphereShape>()) {
+
+ return "Radius";
+ }
+
+ if (s->cast_to<BoxShape>()) {
+
+ return "Extents";
+ }
+
+ if (s->cast_to<CapsuleShape>()) {
+
+ return p_idx==0?"Radius":"Height";
+ }
+
+ if (s->cast_to<RayShape>()) {
+
+ return "Length";
+ }
+
+ return "";
+}
+Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const{
+
+ Ref<Shape> s = cs->get_shape();
+ if (s.is_null())
+ return Variant();
+
+ if (s->cast_to<SphereShape>()) {
+
+ Ref<SphereShape> ss = s;
+ return ss->get_radius();
+ }
+
+ if (s->cast_to<BoxShape>()) {
+
+ Ref<BoxShape> bs = s;
+ return bs->get_extents();
+ }
+
+ if (s->cast_to<CapsuleShape>()) {
+
+ Ref<CapsuleShape> cs = s;
+ return p_idx==0?cs->get_radius():cs->get_height();
+ }
+
+ if (s->cast_to<RayShape>()) {
+
+ Ref<RayShape> cs = s;
+ return cs->get_length();
+ }
+
+ return Variant();
+}
+void CollisionShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
+ Ref<Shape> s = cs->get_shape();
+ if (s.is_null())
+ return;
+
+ Transform gt = cs->get_global_transform();
+ gt.orthonormalize();
+ Transform gi = gt.affine_inverse();
+
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
+
+ if (s->cast_to<SphereShape>()) {
+
+ Ref<SphereShape> ss = s;
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(),Vector3(4096,0,0),sg[0],sg[1],ra,rb);
+ float d = ra.x;
+ if (d<0.001)
+ d=0.001;
+
+ ss->set_radius(d);
+ }
+
+ if (s->cast_to<RayShape>()) {
+
+ Ref<RayShape> rs = s;
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,4096),sg[0],sg[1],ra,rb);
+ float d = ra.z;
+ if (d<0.001)
+ d=0.001;
+
+ rs->set_length(d);
+ }
+
+
+ if (s->cast_to<BoxShape>()) {
+
+ Vector3 axis;
+ axis[p_idx]=1.0;
+ Ref<BoxShape> bs = s;
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
+ float d = ra[p_idx];
+ if (d<0.001)
+ d=0.001;
+
+ Vector3 he = bs->get_extents();
+ he[p_idx]=d;
+ bs->set_extents(he);
+
+ }
+
+ if (s->cast_to<CapsuleShape>()) {
+
+ Vector3 axis;
+ axis[p_idx==0?0:2]=1.0;
+ Ref<CapsuleShape> cs = s;
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
+ float d = axis.dot(ra);
+ if (p_idx==1)
+ d-=cs->get_radius();
+ if (d<0.001)
+ d=0.001;
+
+ if (p_idx==0)
+ cs->set_radius(d);
+ else if (p_idx==1)
+ cs->set_height(d*2.0);
+
+ }
+
+}
+void CollisionShapeSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+ Ref<Shape> s = cs->get_shape();
+ if (s.is_null())
+ return;
+
+ if (s->cast_to<SphereShape>()) {
+
+ Ref<SphereShape> ss=s;
+ if (p_cancel) {
+ ss->set_radius(p_restore);
+ return;
+ }
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Sphere Shape Radius"));
+ ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius());
+ ur->add_undo_method(ss.ptr(),"set_radius",p_restore);
+ ur->commit_action();
+
+ }
+
+ if (s->cast_to<BoxShape>()) {
+
+ Ref<BoxShape> ss=s;
+ if (p_cancel) {
+ ss->set_extents(p_restore);
+ return;
+ }
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Box Shape Extents"));
+ ur->add_do_method(ss.ptr(),"set_extents",ss->get_extents());
+ ur->add_undo_method(ss.ptr(),"set_extents",p_restore);
+ ur->commit_action();
+ }
+
+ if (s->cast_to<CapsuleShape>()) {
+
+ Ref<CapsuleShape> ss=s;
+ if (p_cancel) {
+ if (p_idx==0)
+ ss->set_radius(p_restore);
+ else
+ ss->set_height(p_restore);
+ return;
+ }
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ if (p_idx==0) {
+ ur->create_action(TTR("Change Capsule Shape Radius"));
+ ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius());
+ ur->add_undo_method(ss.ptr(),"set_radius",p_restore);
+ } else {
+ ur->create_action(TTR("Change Capsule Shape Height"));
+ ur->add_do_method(ss.ptr(),"set_height",ss->get_height());
+ ur->add_undo_method(ss.ptr(),"set_height",p_restore);
+
+ }
+
+ ur->commit_action();
+
+ }
+
+ if (s->cast_to<RayShape>()) {
+
+ Ref<RayShape> ss=s;
+ if (p_cancel) {
+ ss->set_length(p_restore);
+ return;
+ }
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Ray Shape Length"));
+ ur->add_do_method(ss.ptr(),"set_length",ss->get_length());
+ ur->add_undo_method(ss.ptr(),"set_length",p_restore);
+ ur->commit_action();
+
+ }
+
+}
+void CollisionShapeSpatialGizmo::redraw(){
+
+ clear();
+
+ Ref<Shape> s = cs->get_shape();
+ if (s.is_null())
+ return;
+
+ if (s->cast_to<SphereShape>()) {
+
+ Ref<SphereShape> sp= s;
+ float r=sp->get_radius();
+
+ Vector<Vector3> points;
+
+ for(int i=0;i<=360;i++) {
+
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
+
+ points.push_back(Vector3(a.x,0,a.y));
+ points.push_back(Vector3(b.x,0,b.y));
+ points.push_back(Vector3(0,a.x,a.y));
+ points.push_back(Vector3(0,b.x,b.y));
+ points.push_back(Vector3(a.x,a.y,0));
+ points.push_back(Vector3(b.x,b.y,0));
+
+ }
+
+ Vector<Vector3> collision_segments;
+
+ for(int i=0;i<64;i++) {
+
+ float ra=i*Math_PI*2.0/64.0;
+ float rb=(i+1)*Math_PI*2.0/64.0;
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
+
+ collision_segments.push_back(Vector3(a.x,0,a.y));
+ collision_segments.push_back(Vector3(b.x,0,b.y));
+ collision_segments.push_back(Vector3(0,a.x,a.y));
+ collision_segments.push_back(Vector3(0,b.x,b.y));
+ collision_segments.push_back(Vector3(a.x,a.y,0));
+ collision_segments.push_back(Vector3(b.x,b.y,0));
+ }
+
+ add_lines(points,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(collision_segments);
+ Vector<Vector3> handles;
+ handles.push_back(Vector3(r,0,0));
+ add_handles(handles);
+
+ }
+
+ if (s->cast_to<BoxShape>()) {
+
+ Ref<BoxShape> bs=s;
+ Vector<Vector3> lines;
+ Rect3 aabb;
+ aabb.pos=-bs->get_extents();
+ aabb.size=aabb.pos*-2;
+
+ for(int i=0;i<12;i++) {
+ Vector3 a,b;
+ aabb.get_edge(i,a,b);
+ lines.push_back(a);
+ lines.push_back(b);
+ }
+
+ Vector<Vector3> handles;
+
+ for(int i=0;i<3;i++) {
+
+ Vector3 ax;
+ ax[i]=bs->get_extents()[i];
+ handles.push_back(ax);
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(lines);
+ add_handles(handles);
+
+ }
+
+ if (s->cast_to<CapsuleShape>()) {
+
+ Ref<CapsuleShape> cs=s;
+ float radius = cs->get_radius();
+ float height = cs->get_height();
+
+
+ Vector<Vector3> points;
+
+ Vector3 d(0,0,height*0.5);
+ for(int i=0;i<360;i++) {
+
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+1);
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
+
+ points.push_back(Vector3(a.x,a.y,0)+d);
+ points.push_back(Vector3(b.x,b.y,0)+d);
+
+ points.push_back(Vector3(a.x,a.y,0)-d);
+ points.push_back(Vector3(b.x,b.y,0)-d);
+
+ if (i%90==0) {
+
+ points.push_back(Vector3(a.x,a.y,0)+d);
+ points.push_back(Vector3(a.x,a.y,0)-d);
+ }
+
+ Vector3 dud = i<180?d:-d;
+
+ points.push_back(Vector3(0,a.y,a.x)+dud);
+ points.push_back(Vector3(0,b.y,b.x)+dud);
+ points.push_back(Vector3(a.y,0,a.x)+dud);
+ points.push_back(Vector3(b.y,0,b.x)+dud);
+
+ }
+
+ add_lines(points,SpatialEditorGizmos::singleton->shape_material);
+
+ Vector<Vector3> collision_segments;
+
+ for(int i=0;i<64;i++) {
+
+ float ra=i*Math_PI*2.0/64.0;
+ float rb=(i+1)*Math_PI*2.0/64.0;
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
+
+ collision_segments.push_back(Vector3(a.x,a.y,0)+d);
+ collision_segments.push_back(Vector3(b.x,b.y,0)+d);
+
+ collision_segments.push_back(Vector3(a.x,a.y,0)-d);
+ collision_segments.push_back(Vector3(b.x,b.y,0)-d);
+
+ if (i%16==0) {
+
+ collision_segments.push_back(Vector3(a.x,a.y,0)+d);
+ collision_segments.push_back(Vector3(a.x,a.y,0)-d);
+ }
+
+ Vector3 dud = i<32?d:-d;
+
+ collision_segments.push_back(Vector3(0,a.y,a.x)+dud);
+ collision_segments.push_back(Vector3(0,b.y,b.x)+dud);
+ collision_segments.push_back(Vector3(a.y,0,a.x)+dud);
+ collision_segments.push_back(Vector3(b.y,0,b.x)+dud);
+
+ }
+
+ add_collision_segments(collision_segments);
+
+ Vector<Vector3> handles;
+ handles.push_back(Vector3(cs->get_radius(),0,0));
+ handles.push_back(Vector3(0,0,cs->get_height()*0.5+cs->get_radius()));
+ add_handles(handles);
+
+
+ }
+
+ if (s->cast_to<PlaneShape>()) {
+
+ Ref<PlaneShape> ps=s;
+ Plane p = ps->get_plane();
+ Vector<Vector3> points;
+
+ Vector3 n1 = p.get_any_perpendicular_normal();
+ Vector3 n2 = p.normal.cross(n1).normalized();
+
+ Vector3 pface[4]={
+ p.normal*p.d+n1*10.0+n2*10.0,
+ p.normal*p.d+n1*10.0+n2*-10.0,
+ p.normal*p.d+n1*-10.0+n2*-10.0,
+ p.normal*p.d+n1*-10.0+n2*10.0,
+ };
+
+ points.push_back(pface[0]);
+ points.push_back(pface[1]);
+ points.push_back(pface[1]);
+ points.push_back(pface[2]);
+ points.push_back(pface[2]);
+ points.push_back(pface[3]);
+ points.push_back(pface[3]);
+ points.push_back(pface[0]);
+ points.push_back(p.normal*p.d);
+ points.push_back(p.normal*p.d+p.normal*3);
+
+ add_lines(points,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(points);
+
+ }
+
+
+ if (s->cast_to<ConvexPolygonShape>()) {
+
+ PoolVector<Vector3> points = s->cast_to<ConvexPolygonShape>()->get_points();
+
+ if (points.size()>3) {
+
+ QuickHull qh;
+ Vector<Vector3> varr = Variant(points);
+ Geometry::MeshData md;
+ Error err = qh.build(varr,md);
+ if (err==OK) {
+ Vector<Vector3> points;
+ points.resize(md.edges.size()*2);
+ for(int i=0;i<md.edges.size();i++) {
+ points[i*2+0]=md.vertices[md.edges[i].a];
+ points[i*2+1]=md.vertices[md.edges[i].b];
+ }
+
+
+ add_lines(points,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(points);
+
+ }
+ }
+
+ }
+
+
+ if (s->cast_to<RayShape>()) {
+
+ Ref<RayShape> rs=s;
+
+ Vector<Vector3> points;
+ points.push_back(Vector3());
+ points.push_back(Vector3(0,0,rs->get_length()));
+ add_lines(points,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(points);
+ Vector<Vector3> handles;
+ handles.push_back(Vector3(0,0,rs->get_length()));
+ add_handles(handles);
+
+
+ }
+
+}
+CollisionShapeSpatialGizmo::CollisionShapeSpatialGizmo(CollisionShape* p_cs) {
+
+ cs=p_cs;
+ set_spatial_node(p_cs);
+}
+
+
+
+/////
+
+
+void CollisionPolygonSpatialGizmo::redraw() {
+
+ clear();
+
+ Vector<Vector2> points = polygon->get_polygon();
+ float depth = polygon->get_depth()*0.5;
+
+ Vector<Vector3> lines;
+ for(int i=0;i<points.size();i++) {
+
+ int n = (i+1)%points.size();
+ lines.push_back(Vector3(points[i].x,points[i].y,depth));
+ lines.push_back(Vector3(points[n].x,points[n].y,depth));
+ lines.push_back(Vector3(points[i].x,points[i].y,-depth));
+ lines.push_back(Vector3(points[n].x,points[n].y,-depth));
+ lines.push_back(Vector3(points[i].x,points[i].y,depth));
+ lines.push_back(Vector3(points[i].x,points[i].y,-depth));
+
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
+ add_collision_segments(lines);
+}
+
+CollisionPolygonSpatialGizmo::CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon){
+
+ set_spatial_node(p_polygon);
+ polygon=p_polygon;
+}
+///
+
+
+String VisibilityNotifierGizmo::get_handle_name(int p_idx) const {
+
+ switch(p_idx) {
+ case 0: return "X";
+ case 1: return "Y";
+ case 2: return "Z";
+ }
+
+ return "";
+}
+Variant VisibilityNotifierGizmo::get_handle_value(int p_idx) const{
+
+ return notifier->get_aabb();
+}
+void VisibilityNotifierGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
+
+
+ Transform gt = notifier->get_global_transform();
+ //gt.orthonormalize();
+ Transform gi = gt.affine_inverse();
+
+ Rect3 aabb = notifier->get_aabb();
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
+ Vector3 ofs = aabb.pos+aabb.size*0.5;
+
+ Vector3 axis;
+ axis[p_idx]=1.0;
+
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(ofs,ofs+axis*4096,sg[0],sg[1],ra,rb);
+ float d = ra[p_idx];
+ if (d<0.001)
+ d=0.001;
+
+ aabb.pos[p_idx]=(aabb.pos[p_idx]+aabb.size[p_idx]*0.5)-d;
+ aabb.size[p_idx]=d*2;
+ notifier->set_aabb(aabb);
+}
+
+void VisibilityNotifierGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+
+
+ if (p_cancel) {
+ notifier->set_aabb(p_restore);
+ return;
+ }
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Notifier Extents"));
+ ur->add_do_method(notifier,"set_aabb",notifier->get_aabb());
+ ur->add_undo_method(notifier,"set_aabb",p_restore);
+ ur->commit_action();
+
+}
+
+void VisibilityNotifierGizmo::redraw(){
+
+ clear();
+
+ Vector<Vector3> lines;
+ Rect3 aabb = notifier->get_aabb();
+
+ for(int i=0;i<12;i++) {
+ Vector3 a,b;
+ aabb.get_edge(i,a,b);
+ lines.push_back(a);
+ lines.push_back(b);
+ }
+
+ Vector<Vector3> handles;
+
+
+ for(int i=0;i<3;i++) {
+
+ Vector3 ax;
+ ax[i]=aabb.pos[i]+aabb.size[i];
+ handles.push_back(ax);
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->visibility_notifier_material);
+ //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
+ add_collision_segments(lines);
+ add_handles(handles);
+
+}
+VisibilityNotifierGizmo::VisibilityNotifierGizmo(VisibilityNotifier* p_notifier){
+
+ notifier=p_notifier;
+ set_spatial_node(p_notifier);
+}
+
+////////
+
+
+///
+
+
+String ReflectionProbeGizmo::get_handle_name(int p_idx) const {
+
+ switch(p_idx) {
+ case 0: return "Extents X";
+ case 1: return "Extents Y";
+ case 2: return "Extents Z";
+ case 3: return "Origin X";
+ case 4: return "Origin Y";
+ case 5: return "Origin Z";
+ }
+
+ return "";
+}
+Variant ReflectionProbeGizmo::get_handle_value(int p_idx) const{
+
+ return Rect3(probe->get_extents(),probe->get_origin_offset());
+}
+void ReflectionProbeGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
+
+ Transform gt = probe->get_global_transform();
+ //gt.orthonormalize();
+ Transform gi = gt.affine_inverse();
+
+
+ if (p_idx<3) {
+ Vector3 extents = probe->get_extents();
+
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*16384)};
+
+ Vector3 axis;
+ axis[p_idx]=1.0;
+
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(),axis*16384,sg[0],sg[1],ra,rb);
+ float d = ra[p_idx];
+ if (d<0.001)
+ d=0.001;
+
+ extents[p_idx]=d;
+ probe->set_extents(extents);
+ } else {
+
+ p_idx-=3;
+
+ Vector3 origin = probe->get_origin_offset();
+ origin[p_idx]=0;
+
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*16384)};
+
+ Vector3 axis;
+ axis[p_idx]=1.0;
+
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(origin-axis*16384,origin+axis*16384,sg[0],sg[1],ra,rb);
+ float d = ra[p_idx];
+ d+=0.25;
+
+ origin[p_idx]=d;
+ probe->set_origin_offset(origin);
+
+ }
+}
+
+void ReflectionProbeGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+
+ Rect3 restore = p_restore;
+
+ if (p_cancel) {
+ probe->set_extents(restore.pos);
+ probe->set_origin_offset(restore.size);
+ return;
+ }
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Probe Extents"));
+ ur->add_do_method(probe,"set_extents",probe->get_extents());
+ ur->add_do_method(probe,"set_origin_offset",probe->get_origin_offset());
+ ur->add_undo_method(probe,"set_extents",restore.pos);
+ ur->add_undo_method(probe,"set_origin_offset",restore.size);
+ ur->commit_action();
+
+}
+
+void ReflectionProbeGizmo::redraw(){
+
+ clear();
+
+ Vector<Vector3> lines;
+ Vector<Vector3> internal_lines;
+ Vector3 extents = probe->get_extents();
+
+ Rect3 aabb;
+ aabb.pos=-extents;
+ aabb.size=extents*2;
+
+ for(int i=0;i<12;i++) {
+ Vector3 a,b;
+ aabb.get_edge(i,a,b);
+ lines.push_back(a);
+ lines.push_back(b);
+ }
+
+ for(int i=0;i<8;i++) {
+ Vector3 ep = aabb.get_endpoint(i);
+ internal_lines.push_back(probe->get_origin_offset());
+ internal_lines.push_back(ep);
+
+
+ }
+
+ Vector<Vector3> handles;
+
+
+ for(int i=0;i<3;i++) {
+
+ Vector3 ax;
+ ax[i]=aabb.pos[i]+aabb.size[i];
+ handles.push_back(ax);
+ }
+
+ for(int i=0;i<3;i++) {
+
+
+ Vector3 orig_handle=probe->get_origin_offset();
+ orig_handle[i]-=0.25;
+ lines.push_back(orig_handle);
+ handles.push_back(orig_handle);
+
+ orig_handle[i]+=0.5;
+ lines.push_back(orig_handle);
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->reflection_probe_material);
+ add_lines(internal_lines,SpatialEditorGizmos::singleton->reflection_probe_material_internal);
+ //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
+ add_collision_segments(lines);
+ add_handles(handles);
+
+}
+ReflectionProbeGizmo::ReflectionProbeGizmo(ReflectionProbe* p_probe){
+
+ probe=p_probe;
+ set_spatial_node(p_probe);
+}
+
+////////
+
+
+
+///
+
+
+String GIProbeGizmo::get_handle_name(int p_idx) const {
+
+ switch(p_idx) {
+ case 0: return "Extents X";
+ case 1: return "Extents Y";
+ case 2: return "Extents Z";
+ }
+
+ return "";
+}
+Variant GIProbeGizmo::get_handle_value(int p_idx) const{
+
+ return probe->get_extents();
+}
+void GIProbeGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
+
+ Transform gt = probe->get_global_transform();
+ //gt.orthonormalize();
+ Transform gi = gt.affine_inverse();
+
+
+ Vector3 extents = probe->get_extents();
+
+ Vector3 ray_from = p_camera->project_ray_origin(p_point);
+ Vector3 ray_dir = p_camera->project_ray_normal(p_point);
+
+ Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*16384)};
+
+ Vector3 axis;
+ axis[p_idx]=1.0;
+
+ Vector3 ra,rb;
+ Geometry::get_closest_points_between_segments(Vector3(),axis*16384,sg[0],sg[1],ra,rb);
+ float d = ra[p_idx];
+ if (d<0.001)
+ d=0.001;
+
+ extents[p_idx]=d;
+ probe->set_extents(extents);
+
+}
+
+void GIProbeGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
+
+ Vector3 restore = p_restore;
+
+ if (p_cancel) {
+ probe->set_extents(restore);
+ return;
+ }
+
+ UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+ ur->create_action(TTR("Change Probe Extents"));
+ ur->add_do_method(probe,"set_extents",probe->get_extents());
+ ur->add_undo_method(probe,"set_extents",restore);
+ ur->commit_action();
+
+}
+
+void GIProbeGizmo::redraw(){
+
+ clear();
+
+ Vector<Vector3> lines;
+ Vector3 extents = probe->get_extents();
+
+ static const int subdivs[GIProbe::SUBDIV_MAX]={64,128,256,512};
+
+ Rect3 aabb = Rect3(-extents,extents*2);
+ int subdiv = subdivs[probe->get_subdiv()];
+ float cell_size = aabb.get_longest_axis_size()/subdiv;
+
+
+ for(int i=0;i<12;i++) {
+ Vector3 a,b;
+ aabb.get_edge(i,a,b);
+ lines.push_back(a);
+ lines.push_back(b);
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->gi_probe_material);
+ add_collision_segments(lines);
+
+ lines.clear();
+
+ for(int i=1;i<subdiv;i++) {
+
+ for(int j=0;j<3;j++) {
+
+
+
+ if (cell_size*i>aabb.size[j]) {
+ continue;
+ }
+
+ Vector2 dir;
+ dir[j]=1.0;
+ Vector2 ta,tb;
+ int j_n1=(j+1)%3;
+ int j_n2=(j+2)%3;
+ ta[j_n1]=1.0;
+ tb[j_n2]=1.0;
+
+
+ for(int k=0;k<4;k++) {
+
+ Vector3 from=aabb.pos,to=aabb.pos;
+ from[j]+= cell_size*i;
+ to[j]+=cell_size*i;
+
+ if (k&1) {
+ to[j_n1]+=aabb.size[j_n1];
+ } else {
+
+ to[j_n2]+=aabb.size[j_n2];
+ }
+
+ if (k&2) {
+ from[j_n1]+=aabb.size[j_n1];
+ from[j_n2]+=aabb.size[j_n2];
+ }
+
+ lines.push_back(from);
+ lines.push_back(to);
+ }
+
+ }
+
+ }
+
+ add_lines(lines,SpatialEditorGizmos::singleton->gi_probe_material_internal);
+
+ Vector<Vector3> handles;
+
+
+ for(int i=0;i<3;i++) {
+
+ Vector3 ax;
+ ax[i]=aabb.pos[i]+aabb.size[i];
+ handles.push_back(ax);
+ }
+
+
+ add_handles(handles);
+
+}
+GIProbeGizmo::GIProbeGizmo(GIProbe* p_probe){
+
+ probe=p_probe;
+ set_spatial_node(p_probe);
+}
+
+////////
+
+
+void NavigationMeshSpatialGizmo::redraw() {
+
+ clear();
+ Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh();
+ if (navmeshie.is_null())
+ return;
+
+ PoolVector<Vector3> vertices = navmeshie->get_vertices();
+ PoolVector<Vector3>::Read vr=vertices.read();
+ List<Face3> faces;
+ for(int i=0;i<navmeshie->get_polygon_count();i++) {
+ Vector<int> p = navmeshie->get_polygon(i);
+
+ for(int j=2;j<p.size();j++) {
+ Face3 f;
+ f.vertex[0]=vr[p[0]];
+ f.vertex[1]=vr[p[j-1]];
+ f.vertex[2]=vr[p[j]];
+
+ faces.push_back(f);
+ }
+ }
+
+ if (faces.empty())
+ return;
+
+ Map<_EdgeKey,bool> edge_map;
+ PoolVector<Vector3> tmeshfaces;
+ tmeshfaces.resize(faces.size()*3);
+
+ {
+ PoolVector<Vector3>::Write tw=tmeshfaces.write();
+ int tidx=0;
+
+
+ for(List<Face3>::Element *E=faces.front();E;E=E->next()) {
+
+ const Face3 &f = E->get();
+
+ for(int j=0;j<3;j++) {
+
+ tw[tidx++]=f.vertex[j];
+ _EdgeKey ek;
+ ek.from=f.vertex[j].snapped(CMP_EPSILON);
+ ek.to=f.vertex[(j+1)%3].snapped(CMP_EPSILON);
+ if (ek.from<ek.to)
+ SWAP(ek.from,ek.to);
+
+ Map<_EdgeKey,bool>::Element *E=edge_map.find(ek);
+
+ if (E) {
+
+ E->get()=false;
+
+ } else {
+
+ edge_map[ek]=true;
+ }
+
+ }
+ }
+ }
+ Vector<Vector3> lines;
+
+ for(Map<_EdgeKey,bool>::Element *E=edge_map.front();E;E=E->next()) {
+
+ if (E->get()) {
+ lines.push_back(E->key().from);
+ lines.push_back(E->key().to);
+ }
+ }
+
+ Ref<TriangleMesh> tmesh = memnew( TriangleMesh );
+ tmesh->create(tmeshfaces);
+
+ if (lines.size())
+ add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
+ add_collision_triangles(tmesh);
+ Ref<Mesh> m = memnew( Mesh );
+ Array a;
+ a.resize(Mesh::ARRAY_MAX);
+ a[0]=tmeshfaces;
+ m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,a);
+ m->surface_set_material(0,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_solid_material:SpatialEditorGizmos::singleton->navmesh_solid_material_disabled);
+ add_mesh(m);
+ add_collision_segments(lines);
+
+}
+
+NavigationMeshSpatialGizmo::NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh){
+
+ set_spatial_node(p_navmesh);
+ navmesh=p_navmesh;
+}
+
+//////
+///
+///
+
+
+
+void PinJointSpatialGizmo::redraw() {
+
+ clear();
+ Vector<Vector3> cursor_points;
+ float cs = 0.25;
+ cursor_points.push_back(Vector3(+cs,0,0));
+ cursor_points.push_back(Vector3(-cs,0,0));
+ cursor_points.push_back(Vector3(0,+cs,0));
+ cursor_points.push_back(Vector3(0,-cs,0));
+ cursor_points.push_back(Vector3(0,0,+cs));
+ cursor_points.push_back(Vector3(0,0,-cs));
+ add_collision_segments(cursor_points);
+ add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
+
+}
+
+
+PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint* p_p3d) {
+
+ p3d=p_p3d;
+ set_spatial_node(p3d);
+}
+
+////
+
+void HingeJointSpatialGizmo::redraw() {
+
+ clear();
+ Vector<Vector3> cursor_points;
+ float cs = 0.25;
+ /*cursor_points.push_back(Vector3(+cs,0,0));
+ cursor_points.push_back(Vector3(-cs,0,0));
+ cursor_points.push_back(Vector3(0,+cs,0));
+ cursor_points.push_back(Vector3(0,-cs,0));*/
+ cursor_points.push_back(Vector3(0,0,+cs*2));
+ cursor_points.push_back(Vector3(0,0,-cs*2));
+
+ float ll = p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER);
+ float ul = p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER);
+
+ if (p3d->get_flag(HingeJoint::FLAG_USE_LIMIT) && ll<ul) {
+
+ const int points = 32;
+
+ for(int i=0;i<points;i++) {
+
+ float s = ll+i*(ul-ll)/points;
+ float n = ll+(i+1)*(ul-ll)/points;
+
+ Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs;
+ Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs;
+
+ if (i==points-1) {
+ cursor_points.push_back(to);
+ cursor_points.push_back(Vector3());
+ }
+ if (i==0) {
+ cursor_points.push_back(from);
+ cursor_points.push_back(Vector3());
+ }
+
+
+ cursor_points.push_back(from);
+ cursor_points.push_back(to);
+
+
+ }
+
+ cursor_points.push_back(Vector3(0,cs*1.5,0));
+ cursor_points.push_back(Vector3());
+
+ } else {
+
+
+ const int points = 32;
+
+ for(int i=0;i<points;i++) {
+
+ float s = ll+i*(Math_PI*2.0)/points;
+ float n = ll+(i+1)*(Math_PI*2.0)/points;
+
+ Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs;
+ Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs;
+
+ cursor_points.push_back(from);
+ cursor_points.push_back(to);
+
+ }
+
+ }
+ add_collision_segments(cursor_points);
+ add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
+
+}
+
+
+HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint* p_p3d) {
+
+ p3d=p_p3d;
+ set_spatial_node(p3d);
+}
+
+///////
+///
+////
+
+void SliderJointSpatialGizmo::redraw() {
+
+ clear();
+ Vector<Vector3> cursor_points;
+ float cs = 0.25;
+ /*cursor_points.push_back(Vector3(+cs,0,0));
+ cursor_points.push_back(Vector3(-cs,0,0));
+ cursor_points.push_back(Vector3(0,+cs,0));
+ cursor_points.push_back(Vector3(0,-cs,0));*/
+ cursor_points.push_back(Vector3(0,0,+cs*2));
+ cursor_points.push_back(Vector3(0,0,-cs*2));
+
+ float ll = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER);
+ float ul = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER);
+ float lll = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER);
+ float lul = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER);
+
+ if (lll>lul) {
+
+ cursor_points.push_back(Vector3(lul,0,0));
+ cursor_points.push_back(Vector3(lll,0,0));
+
+ cursor_points.push_back(Vector3(lul,-cs,-cs));
+ cursor_points.push_back(Vector3(lul,-cs,cs));
+ cursor_points.push_back(Vector3(lul,-cs,cs));
+ cursor_points.push_back(Vector3(lul,cs,cs));
+ cursor_points.push_back(Vector3(lul,cs,cs));
+ cursor_points.push_back(Vector3(lul,cs,-cs));
+ cursor_points.push_back(Vector3(lul,cs,-cs));
+ cursor_points.push_back(Vector3(lul,-cs,-cs));
+
+
+ cursor_points.push_back(Vector3(lll,-cs,-cs));
+ cursor_points.push_back(Vector3(lll,-cs,cs));
+ cursor_points.push_back(Vector3(lll,-cs,cs));
+ cursor_points.push_back(Vector3(lll,cs,cs));
+ cursor_points.push_back(Vector3(lll,cs,cs));
+ cursor_points.push_back(Vector3(lll,cs,-cs));
+ cursor_points.push_back(Vector3(lll,cs,-cs));
+ cursor_points.push_back(Vector3(lll,-cs,-cs));
+
+
+ } else {
+
+ cursor_points.push_back(Vector3(+cs*2,0,0));
+ cursor_points.push_back(Vector3(-cs*2,0,0));
+
+ }
+
+ if (ll<ul) {
+
+ const int points = 32;
+
+ for(int i=0;i<points;i++) {
+
+ float s = ll+i*(ul-ll)/points;
+ float n = ll+(i+1)*(ul-ll)/points;
+
+ Vector3 from=Vector3(0, Math::cos(s), -Math::sin(s) )*cs;
+ Vector3 to=Vector3(0,Math::cos(n), -Math::sin(n) )*cs;
+
+ if (i==points-1) {
+ cursor_points.push_back(to);
+ cursor_points.push_back(Vector3());
+ }
+ if (i==0) {
+ cursor_points.push_back(from);
+ cursor_points.push_back(Vector3());
+ }
+
+
+ cursor_points.push_back(from);
+ cursor_points.push_back(to);
+
+
+ }
+
+ cursor_points.push_back(Vector3(0,cs*1.5,0));
+ cursor_points.push_back(Vector3());
+
+ } else {
+
+
+ const int points = 32;
+
+ for(int i=0;i<points;i++) {
+
+ float s = ll+i*(Math_PI*2.0)/points;
+ float n = ll+(i+1)*(Math_PI*2.0)/points;
+
+ Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
+ Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
+
+ cursor_points.push_back(from);
+ cursor_points.push_back(to);
+
+ }
+
+ }
+ add_collision_segments(cursor_points);
+ add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
+
+}
+
+
+SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint* p_p3d) {
+
+ p3d=p_p3d;
+ set_spatial_node(p3d);
+}
+
+///////
+///
+////
+
+void ConeTwistJointSpatialGizmo::redraw() {
+
+ clear();
+ Vector<Vector3> points;
+
+ float r = 1.0;
+ float w = r*Math::sin(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
+ float d = r*Math::cos(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
+
+
+ //swing
+ for(int i=0;i<360;i+=10) {
+
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+10);
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
+
+ /*points.push_back(Vector3(a.x,0,a.y));
+ points.push_back(Vector3(b.x,0,b.y));
+ points.push_back(Vector3(0,a.x,a.y));
+ points.push_back(Vector3(0,b.x,b.y));*/
+ points.push_back(Vector3(d,a.x,a.y));
+ points.push_back(Vector3(d,b.x,b.y));
+
+ if (i%90==0) {
+
+ points.push_back(Vector3(d,a.x,a.y));
+ points.push_back(Vector3());
+
+ }
+ }
+
+ points.push_back(Vector3());
+ points.push_back(Vector3(1,0,0));
+
+ //twist
+ /*
+ */
+ float ts=Math::rad2deg(p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN));
+ ts=MIN(ts,720);
+
+
+ for(int i=0;i<int(ts);i+=5) {
+
+ float ra=Math::deg2rad((float)i);
+ float rb=Math::deg2rad((float)i+5);
+ float c = i/720.0;
+ float cn = (i+5)/720.0;
+ Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w*c;
+ Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w*cn;
+
+ /*points.push_back(Vector3(a.x,0,a.y));
+ points.push_back(Vector3(b.x,0,b.y));
+ points.push_back(Vector3(0,a.x,a.y));
+ points.push_back(Vector3(0,b.x,b.y));*/
+
+ points.push_back(Vector3(c,a.x,a.y));
+ points.push_back(Vector3(cn,b.x,b.y));
+
+ }
+
+
+ add_collision_segments(points);
+ add_lines(points,SpatialEditorGizmos::singleton->joint_material);
+
+}
+
+
+ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d) {
+
+ p3d=p_p3d;
+ set_spatial_node(p3d);
+}
+
+////////
+/// \brief SpatialEditorGizmos::singleton
+///
+///////
+///
+////
+
+void Generic6DOFJointSpatialGizmo::redraw() {
+
+ clear();
+ Vector<Vector3> cursor_points;
+ float cs = 0.25;
+
+ for(int ax=0;ax<3;ax++) {
+ /*cursor_points.push_back(Vector3(+cs,0,0));
+ cursor_points.push_back(Vector3(-cs,0,0));
+ cursor_points.push_back(Vector3(0,+cs,0));
+ cursor_points.push_back(Vector3(0,-cs,0));
+ cursor_points.push_back(Vector3(0,0,+cs*2));
+ cursor_points.push_back(Vector3(0,0,-cs*2)); */
+
+ float ll;
+ float ul;
+ float lll;
+ float lul;
+
+ int a1,a2,a3;
+ bool enable_ang;
+ bool enable_lin;
+
+ switch(ax) {
+ case 0:
+ ll = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
+ ul = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
+ lll = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
+ lul = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
+ enable_ang = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
+ enable_lin = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
+ a1=0;
+ a2=1;
+ a3=2;
+ break;
+ case 1:
+ ll = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
+ ul = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
+ lll = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
+ lul = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
+ enable_ang = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
+ enable_lin = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
+ a1=2;
+ a2=0;
+ a3=1;
+ break;
+ case 2:
+ ll = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
+ ul = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
+ lll = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
+ lul = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
+ enable_ang = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
+ enable_lin = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
+
+ a1=1;
+ a2=2;
+ a3=0;
+ break;
+ }
+
+#define ADD_VTX(x,y,z)\
+ {\
+ Vector3 v;\
+ v[a1]=(x);\
+ v[a2]=(y);\
+ v[a3]=(z);\
+ cursor_points.push_back(v);\
+ }
+
+#define SET_VTX(what,x,y,z)\
+ {\
+ Vector3 v;\
+ v[a1]=(x);\
+ v[a2]=(y);\
+ v[a3]=(z);\
+ what=v;\
+ }
+
+
+
+
+ if (enable_lin && lll>=lul) {
+
+ ADD_VTX(lul,0,0);
+ ADD_VTX(lll,0,0);
+
+ ADD_VTX(lul,-cs,-cs);
+ ADD_VTX(lul,-cs,cs);
+ ADD_VTX(lul,-cs,cs);
+ ADD_VTX(lul,cs,cs);
+ ADD_VTX(lul,cs,cs);
+ ADD_VTX(lul,cs,-cs);
+ ADD_VTX(lul,cs,-cs);
+ ADD_VTX(lul,-cs,-cs);
+
+
+ ADD_VTX(lll,-cs,-cs);
+ ADD_VTX(lll,-cs,cs);
+ ADD_VTX(lll,-cs,cs);
+ ADD_VTX(lll,cs,cs);
+ ADD_VTX(lll,cs,cs);
+ ADD_VTX(lll,cs,-cs);
+ ADD_VTX(lll,cs,-cs);
+ ADD_VTX(lll,-cs,-cs);
+
+
+ } else {
+
+ ADD_VTX(+cs*2,0,0);
+ ADD_VTX(-cs*2,0,0);
+
+ }
+
+ if (enable_ang && ll<=ul) {
+
+ const int points = 32;
+
+ for(int i=0;i<points;i++) {
+
+ float s = ll+i*(ul-ll)/points;
+ float n = ll+(i+1)*(ul-ll)/points;
+
+ Vector3 from;
+ SET_VTX(from,0, Math::cos(s), -Math::sin(s) );
+ from*=cs;
+ Vector3 to;
+ SET_VTX(to,0,Math::cos(n), -Math::sin(n));
+ to*=cs;
+
+ if (i==points-1) {
+ cursor_points.push_back(to);
+ cursor_points.push_back(Vector3());
+ }
+ if (i==0) {
+ cursor_points.push_back(from);
+ cursor_points.push_back(Vector3());
+ }
+
+
+ cursor_points.push_back(from);
+ cursor_points.push_back(to);
+
+
+ }
+
+ ADD_VTX(0,cs*1.5,0);
+ cursor_points.push_back(Vector3());
+
+ } else {
+
+
+ const int points = 32;
+
+ for(int i=0;i<points;i++) {
+
+ float s = ll+i*(Math_PI*2.0)/points;
+ float n = ll+(i+1)*(Math_PI*2.0)/points;
+
+ //Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
+ //Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
+
+ Vector3 from;
+ SET_VTX(from,0, Math::cos(s), -Math::sin(s) );
+ from*=cs;
+ Vector3 to;
+ SET_VTX(to,0,Math::cos(n), -Math::sin(n));
+ to*=cs;
+
+ cursor_points.push_back(from);
+ cursor_points.push_back(to);
+
+ }
+
+ }
+ }
+
+#undef ADD_VTX
+#undef SET_VTX
+
+ add_collision_segments(cursor_points);
+ add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
+
+}
+
+
+Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d) {
+
+ p3d=p_p3d;
+ set_spatial_node(p3d);
+}
+
+///////
+///
+////
+
+
+SpatialEditorGizmos *SpatialEditorGizmos::singleton=NULL;
+
+Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) {
+
+ if (p_spatial->cast_to<Light>()) {
+
+ Ref<LightSpatialGizmo> lsg = memnew( LightSpatialGizmo(p_spatial->cast_to<Light>()) );
+ return lsg;
+ }
+
+
+
+ if (p_spatial->cast_to<Camera>()) {
+
+ Ref<CameraSpatialGizmo> lsg = memnew( CameraSpatialGizmo(p_spatial->cast_to<Camera>()) );
+ return lsg;
+ }
+
+ if (p_spatial->cast_to<Skeleton>()) {
+
+ Ref<SkeletonSpatialGizmo> lsg = memnew( SkeletonSpatialGizmo(p_spatial->cast_to<Skeleton>()) );
+ return lsg;
+ }
+
+
+ if (p_spatial->cast_to<Position3D>()) {
+
+ Ref<Position3DSpatialGizmo> lsg = memnew( Position3DSpatialGizmo(p_spatial->cast_to<Position3D>()) );
+ return lsg;
+ }
+
+ if (p_spatial->cast_to<MeshInstance>()) {
+
+ Ref<MeshInstanceSpatialGizmo> misg = memnew( MeshInstanceSpatialGizmo(p_spatial->cast_to<MeshInstance>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<Room>()) {
+
+ Ref<RoomSpatialGizmo> misg = memnew( RoomSpatialGizmo(p_spatial->cast_to<Room>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<NavigationMeshInstance>()) {
+
+ Ref<NavigationMeshSpatialGizmo> misg = memnew( NavigationMeshSpatialGizmo(p_spatial->cast_to<NavigationMeshInstance>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<RayCast>()) {
+
+ Ref<RayCastSpatialGizmo> misg = memnew( RayCastSpatialGizmo(p_spatial->cast_to<RayCast>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<Portal>()) {
+
+ Ref<PortalSpatialGizmo> misg = memnew( PortalSpatialGizmo(p_spatial->cast_to<Portal>()) );
+ return misg;
+ }
+
+
+ if (p_spatial->cast_to<TestCube>()) {
+
+ Ref<TestCubeSpatialGizmo> misg = memnew( TestCubeSpatialGizmo(p_spatial->cast_to<TestCube>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<CollisionShape>()) {
+
+ Ref<CollisionShapeSpatialGizmo> misg = memnew( CollisionShapeSpatialGizmo(p_spatial->cast_to<CollisionShape>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<VisibilityNotifier>()) {
+
+ Ref<VisibilityNotifierGizmo> misg = memnew( VisibilityNotifierGizmo(p_spatial->cast_to<VisibilityNotifier>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<ReflectionProbe>()) {
+
+ Ref<ReflectionProbeGizmo> misg = memnew( ReflectionProbeGizmo(p_spatial->cast_to<ReflectionProbe>()) );
+ return misg;
+ }
+ if (p_spatial->cast_to<GIProbe>()) {
+
+ Ref<GIProbeGizmo> misg = memnew( GIProbeGizmo(p_spatial->cast_to<GIProbe>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<VehicleWheel>()) {
+
+ Ref<VehicleWheelSpatialGizmo> misg = memnew( VehicleWheelSpatialGizmo(p_spatial->cast_to<VehicleWheel>()) );
+ return misg;
+ }
+ if (p_spatial->cast_to<PinJoint>()) {
+
+ Ref<PinJointSpatialGizmo> misg = memnew( PinJointSpatialGizmo(p_spatial->cast_to<PinJoint>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<HingeJoint>()) {
+
+ Ref<HingeJointSpatialGizmo> misg = memnew( HingeJointSpatialGizmo(p_spatial->cast_to<HingeJoint>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<SliderJoint>()) {
+
+ Ref<SliderJointSpatialGizmo> misg = memnew( SliderJointSpatialGizmo(p_spatial->cast_to<SliderJoint>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<ConeTwistJoint>()) {
+
+ Ref<ConeTwistJointSpatialGizmo> misg = memnew( ConeTwistJointSpatialGizmo(p_spatial->cast_to<ConeTwistJoint>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<Generic6DOFJoint>()) {
+
+ Ref<Generic6DOFJointSpatialGizmo> misg = memnew( Generic6DOFJointSpatialGizmo(p_spatial->cast_to<Generic6DOFJoint>()) );
+ return misg;
+ }
+
+ if (p_spatial->cast_to<CollisionPolygon>()) {
+
+ Ref<CollisionPolygonSpatialGizmo> misg = memnew( CollisionPolygonSpatialGizmo(p_spatial->cast_to<CollisionPolygon>()) );
+ return misg;
+ }
+
+
+ return Ref<SpatialEditorGizmo>();
+}
+
+
+Ref<FixedSpatialMaterial> SpatialEditorGizmos::create_line_material(const Color& p_base_color) {
+
+ Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ line_material->set_line_width(3.0);
+ line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ //line_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ //->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
+ line_material->set_albedo(p_base_color);
+
+ return line_material;
+
+}
+
+Ref<FixedSpatialMaterial> SpatialEditorGizmos::create_solid_material(const Color& p_base_color) {
+
+ Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ line_material->set_albedo(p_base_color);
+
+ return line_material;
+
+}
+
+SpatialEditorGizmos::SpatialEditorGizmos() {
+
+ singleton=this;
+
+ handle_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ handle_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ handle_material->set_albedo(Color(0.8,0.8,0.8));
+
+ handle2_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ handle2_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ handle2_material->set_flag(FixedSpatialMaterial::FLAG_USE_POINT_SIZE, true);
+ handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle","EditorIcons");
+ handle2_material->set_point_size(handle_t->get_width());
+ handle2_material->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,handle_t);
+ handle2_material->set_albedo(Color(1,1,1));
+ handle2_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ handle2_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ handle2_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
+
+ light_material = create_line_material(Color(1,1,0.2));
+
+ light_material_omni_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ light_material_omni_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ light_material_omni_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ light_material_omni_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
+ light_material_omni_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ light_material_omni_icon->set_albedo(Color(1,1,1,0.9));
+ light_material_omni_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoLight","EditorIcons"));
+
+
+ light_material_directional_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ light_material_directional_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ light_material_directional_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ light_material_directional_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
+ light_material_directional_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ light_material_directional_icon->set_albedo(Color(1,1,1,0.9));
+ light_material_directional_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight","EditorIcons"));
+
+ camera_material = create_line_material(Color(1.0,0.5,1.0));
+
+
+ navmesh_edge_material = create_line_material(Color(0.1,0.8,1.0));
+ navmesh_solid_material = create_solid_material(Color(0.1,0.8,1.0,0.4));
+ navmesh_edge_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false);
+ navmesh_edge_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false);
+ navmesh_solid_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+
+ navmesh_edge_material_disabled = create_line_material(Color(1.0,0.8,0.1));
+ navmesh_solid_material_disabled = create_solid_material(Color(1.0,0.8,0.1,0.4));
+ navmesh_edge_material_disabled->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false);
+ navmesh_edge_material_disabled->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false);
+ navmesh_solid_material_disabled->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+
+ skeleton_material = create_line_material(Color(0.6,1.0,0.3));
+ skeleton_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ skeleton_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+ skeleton_material->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true);
+ skeleton_material->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
+
+ //position 3D Shared mesh
+
+ pos3d_mesh = Ref<Mesh>( memnew( Mesh ) );
+ {
+
+ PoolVector<Vector3> cursor_points;
+ PoolVector<Color> cursor_colors;
+ float cs = 0.25;
+ cursor_points.push_back(Vector3(+cs,0,0));
+ cursor_points.push_back(Vector3(-cs,0,0));
+ cursor_points.push_back(Vector3(0,+cs,0));
+ cursor_points.push_back(Vector3(0,-cs,0));
+ cursor_points.push_back(Vector3(0,0,+cs));
+ cursor_points.push_back(Vector3(0,0,-cs));
+ cursor_colors.push_back(Color(1,0.5,0.5,0.7));
+ cursor_colors.push_back(Color(1,0.5,0.5,0.7));
+ cursor_colors.push_back(Color(0.5,1,0.5,0.7));
+ cursor_colors.push_back(Color(0.5,1,0.5,0.7));
+ cursor_colors.push_back(Color(0.5,0.5,1,0.7));
+ cursor_colors.push_back(Color(0.5,0.5,1,0.7));
+
+ Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
+ mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
+ mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
+ mat->set_line_width(3);
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+ d[Mesh::ARRAY_VERTEX]=cursor_points;
+ d[Mesh::ARRAY_COLOR]=cursor_colors;
+ pos3d_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,d);
+ pos3d_mesh->surface_set_material(0,mat);
+ }
+
+ listener_line_mesh = Ref<Mesh>(memnew(Mesh));
+ {
+
+ PoolVector<Vector3> cursor_points;
+ PoolVector<Color> cursor_colors;
+ cursor_points.push_back(Vector3(0, 0, 0));
+ cursor_points.push_back(Vector3(0, 0, -1.0));
+ cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7));
+ cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7));
+
+ Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial);
+ mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
+ mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_line_width(3);
+ Array d;
+ d.resize(VS::ARRAY_MAX);
+ d[Mesh::ARRAY_VERTEX] = cursor_points;
+ d[Mesh::ARRAY_COLOR] = cursor_colors;
+ listener_line_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d);
+ listener_line_mesh->surface_set_material(0, mat);
+ }
+
+
+ sample_player_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ sample_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ sample_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ sample_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
+ sample_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ sample_player_icon->set_albedo(Color(1,1,1,0.9));
+ sample_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer","EditorIcons"));
+
+ room_material = create_line_material(Color(1.0,0.6,0.9));
+ portal_material = create_line_material(Color(1.0,0.8,0.6));
+ raycast_material = create_line_material(Color(1.0,0.8,0.6));
+ car_wheel_material = create_line_material(Color(0.6,0.8,1.0));
+ visibility_notifier_material = create_line_material(Color(1.0,0.5,1.0));
+ reflection_probe_material = create_line_material(Color(0.5,1.0,0.7));
+ reflection_probe_material_internal = create_line_material(Color(0.3,0.8,0.5,0.15));
+ gi_probe_material = create_line_material(Color(0.7,1.0,0.5));
+ gi_probe_material_internal = create_line_material(Color(0.5,0.8,0.3,0.1));
+ joint_material = create_line_material(Color(0.6,0.8,1.0));
+
+ stream_player_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ stream_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ stream_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ stream_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
+ stream_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ stream_player_icon->set_albedo(Color(1,1,1,0.9));
+ stream_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer","EditorIcons"));
+
+ visibility_notifier_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
+ visibility_notifier_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ visibility_notifier_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ visibility_notifier_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
+ visibility_notifier_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ visibility_notifier_icon->set_albedo(Color(1,1,1,0.9));
+ visibility_notifier_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("Visible","EditorIcons"));
+
+ listener_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial));
+ listener_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
+ listener_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
+ listener_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
+ listener_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
+ listener_icon->set_albedo( Color(1, 1, 1, 0.9));
+ listener_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoListener", "EditorIcons"));
+
+ {
+
+ PoolVector<Vector3> vertices;
+
+#undef ADD_VTX
+#define ADD_VTX(m_idx) \
+ vertices.push_back( face_points[m_idx] );
+
+ for (int i=0;i<6;i++) {
+
+
+ Vector3 face_points[4];
+
+ for (int j=0;j<4;j++) {
+
+ float v[3];
+ v[0]=1.0;
+ v[1]=1-2*((j>>1)&1);
+ v[2]=v[1]*(1-2*(j&1));
+
+ for (int k=0;k<3;k++) {
+
+ if (i<3)
+ face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ else
+ face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
+ }
+ }
+ //tri 1
+ ADD_VTX(0);
+ ADD_VTX(1);
+ ADD_VTX(2);
+ //tri 2
+ ADD_VTX(2);
+ ADD_VTX(3);
+ ADD_VTX(0);
+
+ }
+
+ test_cube_tm = Ref<TriangleMesh>( memnew( TriangleMesh ) );
+ test_cube_tm->create(vertices);
+ }
+
+ shape_material = create_line_material(Color(0.2,1,1.0));
+
+
+}
+
diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h
new file mode 100644
index 0000000000..c44a987144
--- /dev/null
+++ b/editor/spatial_editor_gizmos.h
@@ -0,0 +1,521 @@
+/*************************************************************************/
+/* spatial_editor_gizmos.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SPATIAL_EDITOR_GIZMOS_H
+#define SPATIAL_EDITOR_GIZMOS_H
+
+
+#include "editor/plugins/spatial_editor_plugin.h"
+#include "scene/3d/light.h"
+#include "scene/3d/listener.h"
+#include "scene/3d/camera.h"
+#include "scene/3d/position_3d.h"
+#include "scene/3d/test_cube.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/body_shape.h"
+#include "scene/3d/room_instance.h"
+#include "scene/3d/visibility_notifier.h"
+#include "scene/3d/portal.h"
+#include "scene/3d/ray_cast.h"
+#include "scene/3d/navigation_mesh.h"
+#include "scene/3d/reflection_probe.h"
+#include "scene/3d/gi_probe.h"
+
+#include "scene/3d/vehicle_body.h"
+#include "scene/3d/collision_polygon.h"
+#include "scene/3d/physics_joint.h"
+
+
+class Camera;
+
+class EditorSpatialGizmo : public SpatialEditorGizmo {
+
+ GDCLASS(EditorSpatialGizmo,SpatialGizmo);
+
+ struct Instance{
+
+ RID instance;
+ Ref<Mesh> mesh;
+ RID skeleton;
+ bool billboard;
+ bool unscaled;
+ bool can_intersect;
+ bool extra_margin;
+ Instance() {
+
+ billboard=false;
+ unscaled=false;
+ can_intersect=false;
+ extra_margin=false;
+ }
+
+ void create_instance(Spatial *p_base);
+
+ };
+
+ Vector<Vector3> collision_segments;
+ Ref<TriangleMesh> collision_mesh;
+
+ struct Handle {
+ Vector3 pos;
+ bool billboard;
+ };
+
+ Vector<Vector3> handles;
+ Vector<Vector3> secondary_handles;
+ bool billboard_handle;
+
+ bool valid;
+ Spatial *base;
+ Vector<Instance> instances;
+ Spatial *spatial_node;
+
+ void _set_spatial_node(Node *p_node) { set_spatial_node(p_node->cast_to<Spatial>()); }
+protected:
+ void add_lines(const Vector<Vector3> &p_lines,const Ref<Material>& p_material,bool p_billboard=false);
+ void add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard=false,const RID& p_skeleton=RID());
+ void add_collision_segments(const Vector<Vector3> &p_lines);
+ void add_collision_triangles(const Ref<TriangleMesh>& p_tmesh);
+ void add_unscaled_billboard(const Ref<Material>& p_material,float p_scale=1);
+ void add_handles(const Vector<Vector3> &p_handles,bool p_billboard=false,bool p_secondary=false);
+
+ void set_spatial_node(Spatial *p_node);
+
+ static void _bind_methods();
+public:
+
+ virtual Vector3 get_handle_pos(int p_idx) const;
+ virtual bool intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum);
+ virtual bool intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle=NULL,bool p_sec_first=false);
+
+ void clear();
+ void create();
+ void transform();
+ virtual void redraw();
+ void free();
+
+ EditorSpatialGizmo();
+ ~EditorSpatialGizmo();
+};
+
+
+
+class LightSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(LightSpatialGizmo,EditorSpatialGizmo);
+
+ Light* light;
+
+public:
+
+
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+
+ void redraw();
+ LightSpatialGizmo(Light* p_light=NULL);
+
+};
+
+class CameraSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(CameraSpatialGizmo,EditorSpatialGizmo);
+
+ Camera* camera;
+
+public:
+
+
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+
+ void redraw();
+ CameraSpatialGizmo(Camera* p_camera=NULL);
+
+};
+
+
+
+class MeshInstanceSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(MeshInstanceSpatialGizmo,EditorSpatialGizmo);
+
+ MeshInstance* mesh;
+
+public:
+
+ void redraw();
+ MeshInstanceSpatialGizmo(MeshInstance* p_mesh=NULL);
+
+};
+
+class Position3DSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(Position3DSpatialGizmo,EditorSpatialGizmo);
+
+ Position3D* p3d;
+
+public:
+
+ void redraw();
+ Position3DSpatialGizmo(Position3D* p_p3d=NULL);
+
+};
+
+class SkeletonSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(SkeletonSpatialGizmo,EditorSpatialGizmo);
+
+ Skeleton* skel;
+
+public:
+
+ void redraw();
+ SkeletonSpatialGizmo(Skeleton* p_skel=NULL);
+
+};
+
+
+class TestCubeSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(TestCubeSpatialGizmo,EditorSpatialGizmo);
+
+ TestCube* tc;
+
+public:
+ void redraw();
+ TestCubeSpatialGizmo(TestCube* p_tc=NULL);
+
+};
+
+
+class RoomSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(RoomSpatialGizmo,EditorSpatialGizmo);
+
+
+ struct _EdgeKey {
+
+ Vector3 from;
+ Vector3 to;
+
+ bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; }
+ };
+
+
+
+ Room* room;
+
+public:
+
+ void redraw();
+ RoomSpatialGizmo(Room* p_room=NULL);
+
+};
+
+
+class PortalSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(PortalSpatialGizmo,EditorSpatialGizmo);
+
+ Portal* portal;
+
+public:
+
+ void redraw();
+ PortalSpatialGizmo(Portal* p_portal=NULL);
+
+};
+
+
+class VisibilityNotifierGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(VisibilityNotifierGizmo ,EditorSpatialGizmo);
+
+
+ VisibilityNotifier* notifier;
+
+public:
+
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+
+ void redraw();
+ VisibilityNotifierGizmo(VisibilityNotifier* p_notifier=NULL);
+
+};
+
+
+class ReflectionProbeGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(ReflectionProbeGizmo ,EditorSpatialGizmo);
+
+
+ ReflectionProbe* probe;
+
+public:
+
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+
+ void redraw();
+ ReflectionProbeGizmo(ReflectionProbe* p_notifier=NULL);
+
+};
+
+class GIProbeGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(GIProbeGizmo ,EditorSpatialGizmo);
+
+
+ GIProbe* probe;
+
+public:
+
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+
+ void redraw();
+ GIProbeGizmo(GIProbe* p_notifier=NULL);
+
+};
+
+
+class CollisionShapeSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(CollisionShapeSpatialGizmo,EditorSpatialGizmo);
+
+ CollisionShape* cs;
+
+public:
+ virtual String get_handle_name(int p_idx) const;
+ virtual Variant get_handle_value(int p_idx) const;
+ virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
+ virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
+ void redraw();
+ CollisionShapeSpatialGizmo(CollisionShape* p_cs=NULL);
+
+};
+
+
+class CollisionPolygonSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(CollisionPolygonSpatialGizmo,EditorSpatialGizmo);
+
+ CollisionPolygon* polygon;
+
+public:
+
+ void redraw();
+ CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon=NULL);
+
+};
+
+
+
+class RayCastSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(RayCastSpatialGizmo,EditorSpatialGizmo);
+
+ RayCast* raycast;
+
+public:
+
+ void redraw();
+ RayCastSpatialGizmo(RayCast* p_raycast=NULL);
+
+};
+
+
+
+class VehicleWheelSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(VehicleWheelSpatialGizmo,EditorSpatialGizmo);
+
+ VehicleWheel* car_wheel;
+
+public:
+
+ void redraw();
+ VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel=NULL);
+
+};
+
+
+class NavigationMeshSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(NavigationMeshSpatialGizmo,EditorSpatialGizmo);
+
+
+ struct _EdgeKey {
+
+ Vector3 from;
+ Vector3 to;
+
+ bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; }
+ };
+
+
+
+ NavigationMeshInstance* navmesh;
+
+public:
+
+ void redraw();
+ NavigationMeshSpatialGizmo(NavigationMeshInstance* p_navmesh=NULL);
+
+};
+
+
+class PinJointSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(PinJointSpatialGizmo,EditorSpatialGizmo);
+
+ PinJoint* p3d;
+
+public:
+
+ void redraw();
+ PinJointSpatialGizmo(PinJoint* p_p3d=NULL);
+
+};
+
+
+class HingeJointSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(HingeJointSpatialGizmo,EditorSpatialGizmo);
+
+ HingeJoint* p3d;
+
+public:
+
+ void redraw();
+ HingeJointSpatialGizmo(HingeJoint* p_p3d=NULL);
+
+};
+
+class SliderJointSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(SliderJointSpatialGizmo,EditorSpatialGizmo);
+
+ SliderJoint* p3d;
+
+public:
+
+ void redraw();
+ SliderJointSpatialGizmo(SliderJoint* p_p3d=NULL);
+
+};
+
+class ConeTwistJointSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(ConeTwistJointSpatialGizmo,EditorSpatialGizmo);
+
+ ConeTwistJoint* p3d;
+
+public:
+
+ void redraw();
+ ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d=NULL);
+
+};
+
+
+class Generic6DOFJointSpatialGizmo : public EditorSpatialGizmo {
+
+ GDCLASS(Generic6DOFJointSpatialGizmo,EditorSpatialGizmo);
+
+ Generic6DOFJoint* p3d;
+
+public:
+
+ void redraw();
+ Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d=NULL);
+
+};
+
+
+class SpatialEditorGizmos {
+public:
+
+ Ref<FixedSpatialMaterial> create_line_material(const Color& p_base_color);
+ Ref<FixedSpatialMaterial> create_solid_material(const Color& p_base_color);
+ Ref<FixedSpatialMaterial> handle2_material;
+ Ref<FixedSpatialMaterial> handle_material;
+ Ref<FixedSpatialMaterial> light_material;
+ Ref<FixedSpatialMaterial> light_material_omni_icon;
+ Ref<FixedSpatialMaterial> light_material_directional_icon;
+ Ref<FixedSpatialMaterial> camera_material;
+ Ref<FixedSpatialMaterial> skeleton_material;
+ Ref<FixedSpatialMaterial> reflection_probe_material;
+ Ref<FixedSpatialMaterial> reflection_probe_material_internal;
+ Ref<FixedSpatialMaterial> gi_probe_material;
+ Ref<FixedSpatialMaterial> gi_probe_material_internal;
+ Ref<FixedSpatialMaterial> room_material;
+ Ref<FixedSpatialMaterial> portal_material;
+ Ref<FixedSpatialMaterial> raycast_material;
+ Ref<FixedSpatialMaterial> visibility_notifier_material;
+ Ref<FixedSpatialMaterial> car_wheel_material;
+ Ref<FixedSpatialMaterial> joint_material;
+
+ Ref<FixedSpatialMaterial> navmesh_edge_material;
+ Ref<FixedSpatialMaterial> navmesh_solid_material;
+ Ref<FixedSpatialMaterial> navmesh_edge_material_disabled;
+ Ref<FixedSpatialMaterial> navmesh_solid_material_disabled;
+
+ Ref<FixedSpatialMaterial> listener_icon;
+
+ Ref<FixedSpatialMaterial> sample_player_icon;
+ Ref<FixedSpatialMaterial> stream_player_icon;
+ Ref<FixedSpatialMaterial> visibility_notifier_icon;
+
+ Ref<FixedSpatialMaterial> shape_material;
+ Ref<Texture> handle_t;
+
+ Ref<Mesh> pos3d_mesh;
+ Ref<Mesh> listener_line_mesh;
+ static SpatialEditorGizmos *singleton;
+
+ Ref<TriangleMesh> test_cube_tm;
+
+
+ Ref<SpatialEditorGizmo> get_gizmo(Spatial *p_spatial);
+
+ SpatialEditorGizmos();
+};
+#endif // SPATIAL_EDITOR_GIZMOS_H
diff --git a/editor/translations/Makefile b/editor/translations/Makefile
new file mode 100644
index 0000000000..4f5d9f165f
--- /dev/null
+++ b/editor/translations/Makefile
@@ -0,0 +1,20 @@
+# Makefile providing various facilities to manage translations
+
+TEMPLATE = editor.pot
+POFILES = $(wildcard *.po)
+LANGS = $(POFILES:%.po=%)
+
+all: update merge
+
+update:
+ @cd ../..; python2 editor/translations/extract.py
+
+merge:
+ @for po in $(POFILES); do \
+ echo -e "\nMerging $$po..."; \
+ msgmerge -w 79 -C $$po $$po $(TEMPLATE) > "$$po".new; \
+ mv -f "$$po".new $$po; \
+ done
+
+check:
+ @for po in $(POFILES); do msgfmt -c $$po -o /dev/null; done
diff --git a/tools/editor/translations/README.md b/editor/translations/README.md
index 351bc9e2d1..351bc9e2d1 100644
--- a/tools/editor/translations/README.md
+++ b/editor/translations/README.md
diff --git a/tools/editor/translations/ar.po b/editor/translations/ar.po
index 539b94ab62..539b94ab62 100644
--- a/tools/editor/translations/ar.po
+++ b/editor/translations/ar.po
diff --git a/tools/editor/translations/bg.po b/editor/translations/bg.po
index fe711e1b30..fe711e1b30 100644
--- a/tools/editor/translations/bg.po
+++ b/editor/translations/bg.po
diff --git a/tools/editor/translations/bn.po b/editor/translations/bn.po
index 0b1993caa0..0b1993caa0 100644
--- a/tools/editor/translations/bn.po
+++ b/editor/translations/bn.po
diff --git a/tools/editor/translations/ca.po b/editor/translations/ca.po
index c45cad964b..c45cad964b 100644
--- a/tools/editor/translations/ca.po
+++ b/editor/translations/ca.po
diff --git a/tools/editor/translations/cs.po b/editor/translations/cs.po
index 3dc52fa536..3dc52fa536 100644
--- a/tools/editor/translations/cs.po
+++ b/editor/translations/cs.po
diff --git a/tools/editor/translations/da.po b/editor/translations/da.po
index 6148d0b82d..6148d0b82d 100644
--- a/tools/editor/translations/da.po
+++ b/editor/translations/da.po
diff --git a/tools/editor/translations/de.po b/editor/translations/de.po
index 0545ea2f21..0545ea2f21 100644
--- a/tools/editor/translations/de.po
+++ b/editor/translations/de.po
diff --git a/tools/editor/translations/de_CH.po b/editor/translations/de_CH.po
index 0420d3fc97..0420d3fc97 100644
--- a/tools/editor/translations/de_CH.po
+++ b/editor/translations/de_CH.po
diff --git a/tools/editor/translations/tools.pot b/editor/translations/editor.pot
index 8e54d88989..8e54d88989 100644
--- a/tools/editor/translations/tools.pot
+++ b/editor/translations/editor.pot
diff --git a/tools/editor/translations/es.po b/editor/translations/es.po
index a1108822fa..a1108822fa 100644
--- a/tools/editor/translations/es.po
+++ b/editor/translations/es.po
diff --git a/tools/editor/translations/es_AR.po b/editor/translations/es_AR.po
index d921254859..d921254859 100644
--- a/tools/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
diff --git a/editor/translations/extract.py b/editor/translations/extract.py
new file mode 100755
index 0000000000..616fec17a0
--- /dev/null
+++ b/editor/translations/extract.py
@@ -0,0 +1,121 @@
+#!/bin/python
+
+import fnmatch
+import os
+import shutil
+import subprocess
+import sys
+
+
+line_nb = False
+
+for arg in sys.argv[1:]:
+ if (arg == "--with-line-nb"):
+ print("Enabling line numbers in the context locations.")
+ line_nb = True
+ else:
+ os.sys.exit("Non supported argument '" + arg + "'. Aborting.")
+
+
+if (not os.path.exists("editor")):
+ os.sys.exit("ERROR: This script should be started from the root of the git repo.")
+
+
+matches = []
+for root, dirnames, filenames in os.walk('.'):
+ for filename in fnmatch.filter(filenames, '*.cpp'):
+ if (filename.find("collada") != -1):
+ continue
+ matches.append(os.path.join(root, filename))
+ for filename in fnmatch.filter(filenames, '*.h'):
+ if (filename.find("collada") != -1):
+ continue
+ matches.append(os.path.join(root, filename))
+matches.sort()
+
+
+unique_str = []
+unique_loc = {}
+main_po = """
+# LANGUAGE translation of the Godot Engine editor
+# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
+# This file is distributed under the same license as the Godot source code.
+#
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Godot Engine editor\\n"
+"Content-Type: text/plain; charset=UTF-8\\n"
+"Content-Transfer-Encoding: 8-bit\\n"
+"""
+
+print("Updating the editor.pot template...")
+
+for fname in matches:
+
+ f = open(fname, "rb")
+
+ l = f.readline()
+ lc = 1
+ while (l):
+
+ patterns = ['RTR(\"', 'TTR(\"']
+ idx = 0
+ pos = 0
+ while (pos >= 0):
+ pos = l.find(patterns[idx], pos)
+ if (pos == -1):
+ if (idx < len(patterns) - 1):
+ idx += 1
+ pos = 0
+ continue
+ pos += 5
+
+ msg = ""
+ while (pos < len(l) and (l[pos] != '"' or l[pos - 1] == '\\')):
+ msg += l[pos]
+ pos += 1
+
+ location = os.path.relpath(fname).replace('\\', '/')
+ if (line_nb):
+ location += ":" + str(lc)
+
+ if (not msg in unique_str):
+ main_po += "\n#: " + location + "\n"
+ main_po += 'msgid "' + msg + '"\n'
+ main_po += 'msgstr ""\n'
+ unique_str.append(msg)
+ unique_loc[msg] = [location]
+ elif (not location in unique_loc[msg]):
+ # Add additional location to previous occurence too
+ msg_pos = main_po.find('\nmsgid "' + msg + '"')
+ if (msg_pos == -1):
+ print("Someone apparently thought writing Python was as easy as GDScript. Ping Akien.")
+ main_po = main_po[:msg_pos] + ' ' + location + main_po[msg_pos:]
+ unique_loc[msg].append(location)
+
+ l = f.readline()
+ lc += 1
+
+ f.close()
+
+
+f = open("editor.pot", "wb")
+f.write(main_po)
+f.close()
+
+if (os.name == "posix"):
+ print("Wrapping template at 79 characters for compatibility with Weblate.")
+ os.system("msgmerge -w79 editor.pot editor.pot > editor.pot.wrap")
+ shutil.move("editor.pot.wrap", "editor.pot")
+
+shutil.move("editor.pot", "editor/translations/editor.pot")
+
+# TODO: Make that in a portable way, if we care; if not, kudos to Unix users
+if (os.name == "posix"):
+ added = subprocess.check_output("git diff editor/translations/editor.pot | grep \+msgid | wc -l", shell=True)
+ removed = subprocess.check_output("git diff editor/translations/editor.pot | grep \\\-msgid | wc -l", shell=True)
+ print("\n# Template changes compared to the staged status:")
+ print("# Additions: %s msgids.\n# Deletions: %s msgids." % (int(added), int(removed)))
diff --git a/tools/editor/translations/fa.po b/editor/translations/fa.po
index 41a686ba52..41a686ba52 100644
--- a/tools/editor/translations/fa.po
+++ b/editor/translations/fa.po
diff --git a/tools/editor/translations/fr.po b/editor/translations/fr.po
index 2c4f7144fe..2c4f7144fe 100644
--- a/tools/editor/translations/fr.po
+++ b/editor/translations/fr.po
diff --git a/tools/editor/translations/hu.po b/editor/translations/hu.po
index 335ab25c6a..335ab25c6a 100644
--- a/tools/editor/translations/hu.po
+++ b/editor/translations/hu.po
diff --git a/tools/editor/translations/id.po b/editor/translations/id.po
index 30bd357a21..30bd357a21 100644
--- a/tools/editor/translations/id.po
+++ b/editor/translations/id.po
diff --git a/tools/editor/translations/it.po b/editor/translations/it.po
index 8fefe67677..8fefe67677 100644
--- a/tools/editor/translations/it.po
+++ b/editor/translations/it.po
diff --git a/tools/editor/translations/ja.po b/editor/translations/ja.po
index ea314db101..ea314db101 100644
--- a/tools/editor/translations/ja.po
+++ b/editor/translations/ja.po
diff --git a/tools/editor/translations/ko.po b/editor/translations/ko.po
index a0ecb70bf5..a0ecb70bf5 100644
--- a/tools/editor/translations/ko.po
+++ b/editor/translations/ko.po
diff --git a/tools/editor/translations/nb.po b/editor/translations/nb.po
index cbd2a09951..cbd2a09951 100644
--- a/tools/editor/translations/nb.po
+++ b/editor/translations/nb.po
diff --git a/tools/editor/translations/pl.po b/editor/translations/pl.po
index 50afecad1b..50afecad1b 100644
--- a/tools/editor/translations/pl.po
+++ b/editor/translations/pl.po
diff --git a/tools/editor/translations/pr.po b/editor/translations/pr.po
index 8ea2967a22..8ea2967a22 100644
--- a/tools/editor/translations/pr.po
+++ b/editor/translations/pr.po
diff --git a/tools/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 9ab81786b1..9ab81786b1 100644
--- a/tools/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
diff --git a/tools/editor/translations/pt_PT.po b/editor/translations/pt_PT.po
index da9d971347..da9d971347 100644
--- a/tools/editor/translations/pt_PT.po
+++ b/editor/translations/pt_PT.po
diff --git a/tools/editor/translations/ru.po b/editor/translations/ru.po
index 0595a675b3..0595a675b3 100644
--- a/tools/editor/translations/ru.po
+++ b/editor/translations/ru.po
diff --git a/tools/editor/translations/sk.po b/editor/translations/sk.po
index 6aa2e16664..6aa2e16664 100644
--- a/tools/editor/translations/sk.po
+++ b/editor/translations/sk.po
diff --git a/tools/editor/translations/sl.po b/editor/translations/sl.po
index 4934be97d7..4934be97d7 100644
--- a/tools/editor/translations/sl.po
+++ b/editor/translations/sl.po
diff --git a/tools/editor/translations/tr.po b/editor/translations/tr.po
index 5c0b6ebca8..5c0b6ebca8 100644
--- a/tools/editor/translations/tr.po
+++ b/editor/translations/tr.po
diff --git a/tools/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index b898301d0c..b898301d0c 100644
--- a/tools/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
diff --git a/tools/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index 47c77f6170..47c77f6170 100644
--- a/tools/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
diff --git a/tools/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index b0bb11d527..b0bb11d527 100644
--- a/tools/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
diff --git a/tools/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index 3e9b61ec0f..3e9b61ec0f 100644
--- a/tools/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 0561f2bb34..a9f643c785 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -1214,6 +1214,15 @@ int InputDefault::get_joy_button_index_from_string(String p_button) {
ERR_FAIL_V(-1);
}
+int InputDefault::get_unused_joy_id() {
+ for (int i=0;i<JOYPADS_MAX;i++) {
+ if (!joy_names.has(i) || !joy_names[i].connected) {
+ return i;
+ }
+ }
+ return -1;
+}
+
String InputDefault::get_joy_axis_string(int p_axis) {
ERR_FAIL_INDEX_V(p_axis, JOY_AXIS_MAX, "");
return _axes[p_axis];
diff --git a/main/input_default.h b/main/input_default.h
index 3e41c494c1..78bc0f4355 100644
--- a/main/input_default.h
+++ b/main/input_default.h
@@ -134,6 +134,11 @@ public:
HAT_LEFT,
HAT_MAX,
};
+
+ enum {
+ JOYPADS_MAX = 16,
+ };
+
struct JoyAxis {
int min;
float value;
@@ -243,6 +248,8 @@ public:
virtual int get_joy_axis_index_from_string(String p_axis);
virtual int get_joy_button_index_from_string(String p_button);
+ int get_unused_joy_id();
+
bool is_joy_mapped(int p_device);
String get_joy_guid_remapped(int p_device) const;
void set_fallback_mapping(String p_guid);
diff --git a/main/main.cpp b/main/main.cpp
index 21a839a25f..32aea6a4a5 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "main.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include "splash.h"
#include "core/register_core_types.h"
#include "scene/register_scene_types.h"
@@ -54,9 +54,9 @@
#include "scene/main/viewport.h"
#ifdef TOOLS_ENABLED
-#include "tools/editor/doc/doc_data.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/project_manager.h"
+#include "editor/doc/doc_data.h"
+#include "editor/editor_node.h"
+#include "editor/project_manager.h"
#endif
#include "io/file_access_network.h"
@@ -1063,6 +1063,7 @@ bool Main::start() {
bool editor=false;
String doc_tool;
+ List<String> removal_docs;
bool doc_base=true;
String game_path;
String script;
@@ -1093,6 +1094,8 @@ bool Main::start() {
bool parsed_pair=true;
if (args[i]=="-doctool") {
doc_tool=args[i+1];
+ for(int j=i+2; j<args.size();j++)
+ removal_docs.push_back(args[j]);
} else if (args[i]=="-script" || args[i]=="-s") {
script=args[i+1];
} else if (args[i]=="-level" || args[i]=="-l") {
@@ -1141,6 +1144,14 @@ bool Main::start() {
}
+ for(List<String>::Element* E= removal_docs.front(); E; E=E->next()) {
+ DocData rmdoc;
+ if (rmdoc.load(E->get()) == OK) {
+ print_line(String("Removing classes in ") + E->get());
+ doc.remove_from(rmdoc);
+ }
+ }
+
doc.save(doc_tool);
return false;
diff --git a/main/performance.cpp b/main/performance.cpp
index 50ca594f8e..bc5d8c33c4 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -40,7 +40,7 @@ Performance *Performance::singleton=NULL;
void Performance::_bind_methods() {
- ClassDB::bind_method(_MD("get_monitor","monitor"),&Performance::get_monitor);
+ ClassDB::bind_method(D_METHOD("get_monitor","monitor"),&Performance::get_monitor);
BIND_CONSTANT( TIME_FPS );
BIND_CONSTANT( TIME_PROCESS );
diff --git a/main/tests/test_containers.cpp b/main/tests/test_containers.cpp
index 2711d107e4..8926066fe6 100644
--- a/main/tests/test_containers.cpp
+++ b/main/tests/test_containers.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan 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,6 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_containers.h"
+
#include "dvector.h"
#include "set.h"
#include "print_string.h"
diff --git a/main/tests/test_containers.h b/main/tests/test_containers.h
index 72d5c0ff7a..bbc132f1c2 100644
--- a/main/tests/test_containers.h
+++ b/main/tests/test_containers.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_gdscript.cpp b/main/tests/test_gdscript.cpp
index 7fdfef5f3c..e9ac238f2a 100644
--- a/main/tests/test_gdscript.cpp
+++ b/main/tests/test_gdscript.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_gdscript.h b/main/tests/test_gdscript.h
index 225654e2a8..7541e7b20f 100644
--- a/main/tests/test_gdscript.h
+++ b/main/tests/test_gdscript.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_gui.cpp b/main/tests/test_gui.cpp
index 899bdc37b9..6833558f07 100644
--- a/main/tests/test_gui.cpp
+++ b/main/tests/test_gui.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_gui.h b/main/tests/test_gui.h
index 5526320b0c..d053770bdd 100644
--- a/main/tests/test_gui.h
+++ b/main/tests/test_gui.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_image.cpp b/main/tests/test_image.cpp
index bf9851cf01..dbe0111367 100644
--- a/main/tests/test_image.cpp
+++ b/main/tests/test_image.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan 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,10 +27,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_image.h"
+
#include "os/main_loop.h"
#include "math_funcs.h"
#include "print_string.h"
#include "io/image_loader.h"
+
namespace TestImage {
diff --git a/main/tests/test_image.h b/main/tests/test_image.h
index 09b33e799e..51ce6d5cc7 100644
--- a/main/tests/test_image.h
+++ b/main/tests/test_image.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_io.cpp b/main/tests/test_io.cpp
index 42664e73cd..af4742afa7 100644
--- a/main/tests/test_io.cpp
+++ b/main/tests/test_io.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan 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,7 +39,7 @@
#include "io/resource_loader.h"
#include "io/resource_saver.h"
#include "os/dir_access.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#include "io/file_access_memory.h"
diff --git a/main/tests/test_io.h b/main/tests/test_io.h
index c839590ab9..bb6a4a4474 100644
--- a/main/tests/test_io.h
+++ b/main/tests/test_io.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_main.cpp b/main/tests/test_main.cpp
index 763616dd46..27f7c2d025 100644
--- a/main/tests/test_main.cpp
+++ b/main/tests/test_main.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_main.h b/main/tests/test_main.h
index c8d571a7dd..4d9419a4f6 100644
--- a/main/tests/test_main.h
+++ b/main/tests/test_main.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_math.cpp b/main/tests/test_math.cpp
index 89513b81d9..43164bb2e6 100644
--- a/main/tests/test_math.cpp
+++ b/main/tests/test_math.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan 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,6 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_math.h"
+
#include "ustring.h"
#include "print_string.h"
#include "transform.h"
@@ -144,11 +145,11 @@ class GetClassAndNamespace {
error_str="Unterminated comment";
error=true;
return TK_ERROR;
- } if (code[idx]=='*' &&code[idx+1]=='/') {
+ } else if (code[idx]=='*' &&code[idx+1]=='/') {
idx+=2;
break;
- } if (code[idx]=='\n') {
+ } else if (code[idx]=='\n') {
line++;
}
diff --git a/main/tests/test_math.h b/main/tests/test_math.h
index 492c3a1837..1ca8a8c12a 100644
--- a/main/tests/test_math.h
+++ b/main/tests/test_math.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_physics.cpp b/main/tests/test_physics.cpp
index 95ce540b16..fe0fad9bc8 100644
--- a/main/tests/test_physics.cpp
+++ b/main/tests/test_physics.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_physics.h b/main/tests/test_physics.h
index 5b6a54f2d4..68693fd931 100644
--- a/main/tests/test_physics.h
+++ b/main/tests/test_physics.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_physics_2d.cpp b/main/tests/test_physics_2d.cpp
index 76d1afd2ac..4321a356f5 100644
--- a/main/tests/test_physics_2d.cpp
+++ b/main/tests/test_physics_2d.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan 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,6 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_physics_2d.h"
+
#include "servers/visual_server.h"
#include "servers/physics_2d_server.h"
#include "os/main_loop.h"
@@ -356,8 +357,8 @@ protected:
static void _bind_methods() {
- ClassDB::bind_method(_MD("_body_moved"),&TestPhysics2DMainLoop::_body_moved);
- ClassDB::bind_method(_MD("_ray_query_callback"),&TestPhysics2DMainLoop::_ray_query_callback);
+ ClassDB::bind_method(D_METHOD("_body_moved"),&TestPhysics2DMainLoop::_body_moved);
+ ClassDB::bind_method(D_METHOD("_ray_query_callback"),&TestPhysics2DMainLoop::_ray_query_callback);
}
diff --git a/main/tests/test_physics_2d.h b/main/tests/test_physics_2d.h
index e2eb1f4023..dee18edfe0 100644
--- a/main/tests/test_physics_2d.h
+++ b/main/tests/test_physics_2d.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_render.cpp b/main/tests/test_render.cpp
index 7380c1ff6a..512c48b116 100644
--- a/main/tests/test_render.cpp
+++ b/main/tests/test_render.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan 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,6 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "test_render.h"
+
#include "servers/visual_server.h"
#include "os/main_loop.h"
#include "math_funcs.h"
diff --git a/main/tests/test_render.h b/main/tests/test_render.h
index 6993e75b9f..b6f6d81881 100644
--- a/main/tests/test_render.h
+++ b/main/tests/test_render.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_shader_lang.cpp b/main/tests/test_shader_lang.cpp
index 1a677bcbe2..64c3853065 100644
--- a/main/tests/test_shader_lang.cpp
+++ b/main/tests/test_shader_lang.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_shader_lang.h b/main/tests/test_shader_lang.h
index f129fb224a..aae047ce10 100644
--- a/main/tests/test_shader_lang.h
+++ b/main/tests/test_shader_lang.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_sound.cpp b/main/tests/test_sound.cpp
index 6b0cf0a324..095ce001ba 100644
--- a/main/tests/test_sound.cpp
+++ b/main/tests/test_sound.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_sound.h b/main/tests/test_sound.h
index 91b87a2261..167751bd1d 100644
--- a/main/tests/test_sound.h
+++ b/main/tests/test_sound.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* 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/tests/test_string.cpp b/main/tests/test_string.cpp
index a4a8ceb072..ca7fdedcb8 100644
--- a/main/tests/test_string.cpp
+++ b/main/tests/test_string.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -835,7 +835,6 @@ bool test_28() {
bool test_29() {
- bool error = false;
bool state = true;
bool success = false;
diff --git a/main/tests/test_string.h b/main/tests/test_string.h
index 7b3cd9a019..12df7f126f 100644
--- a/main/tests/test_string.h
+++ b/main/tests/test_string.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/misc/dist/appimage/AppRun b/misc/dist/appimage/AppRun
new file mode 100755
index 0000000000..db3398a92a
--- /dev/null
+++ b/misc/dist/appimage/AppRun
@@ -0,0 +1,3 @@
+#!/bin/sh
+HERE="$(dirname "$(readlink -f "${0}")")"
+"${HERE}"/godot $@
diff --git a/misc/dist/appimage/godot.desktop b/misc/dist/appimage/godot.desktop
new file mode 100644
index 0000000000..545c491256
--- /dev/null
+++ b/misc/dist/appimage/godot.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=Godot Engine
+GenericName=Libre game engine
+Comment=Multi-platform 2D and 3D game engine with a feature rich editor
+Exec=godot -pm
+Icon=godot
+Terminal=false
+Type=Application
+Categories=Development;IDE;
diff --git a/misc/dist/appimage/godot.png b/misc/dist/appimage/godot.png
new file mode 100644
index 0000000000..e334f5fa78
--- /dev/null
+++ b/misc/dist/appimage/godot.png
Binary files differ
diff --git a/modules/cscript/godot_c.cpp b/modules/cscript/godot_c.cpp
index d5c1b53dfe..85ee28d6d2 100644
--- a/modules/cscript/godot_c.cpp
+++ b/modules/cscript/godot_c.cpp
@@ -1,2 +1,30 @@
+/*************************************************************************/
+/* godot_c.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "godot_c.h"
diff --git a/modules/cscript/godot_c.h b/modules/cscript/godot_c.h
index 3bf86d1aeb..97a63a439f 100644
--- a/modules/cscript/godot_c.h
+++ b/modules/cscript/godot_c.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* godot_c.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 GODOT_C_H
#define GODOT_C_H
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 5295183c35..600cae991e 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -114,7 +114,7 @@ RES ResourceFormatDDS::load(const String &p_path, const String& p_original_path,
uint32_t width = f->get_32();
uint32_t height = f->get_32();
uint32_t pitch = f->get_32();
- uint32_t depth = f->get_32();
+ /* uint32_t depth = */ f->get_32();
uint32_t mipmaps = f->get_32();
//skip 11
@@ -130,7 +130,7 @@ RES ResourceFormatDDS::load(const String &p_path, const String& p_original_path,
}
- uint32_t format_size = f->get_32();
+ /* uint32_t format_size = */ f->get_32();
uint32_t format_flags = f->get_32();
uint32_t format_fourcc = f->get_32();
uint32_t format_rgb_bits = f->get_32();
@@ -139,9 +139,9 @@ RES ResourceFormatDDS::load(const String &p_path, const String& p_original_path,
uint32_t format_blue_mask = f->get_32();
uint32_t format_alpha_mask = f->get_32();
- uint32_t caps_1 = f->get_32();
- uint32_t caps_2 = f->get_32();
- uint32_t caps_ddsx = f->get_32();
+ /* uint32_t caps_1 = */ f->get_32();
+ /* uint32_t caps_2 = */ f->get_32();
+ /* uint32_t caps_ddsx = */ f->get_32();
//reserved skip
f->get_32();
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index d10634e9ea..af555b7eb6 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -645,12 +645,12 @@ void NetworkedMultiplayerENet::enet_compressor_destroy(void * context){
void NetworkedMultiplayerENet::_bind_methods() {
- ClassDB::bind_method(_MD("create_server","port","max_clients","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_server,DEFVAL(32),DEFVAL(0),DEFVAL(0));
- ClassDB::bind_method(_MD("create_client","ip","port","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_client,DEFVAL(0),DEFVAL(0));
- ClassDB::bind_method(_MD("close_connection"),&NetworkedMultiplayerENet::close_connection);
- ClassDB::bind_method(_MD("set_compression_mode","mode"),&NetworkedMultiplayerENet::set_compression_mode);
- ClassDB::bind_method(_MD("get_compression_mode"),&NetworkedMultiplayerENet::get_compression_mode);
- ClassDB::bind_method(_MD("set_bind_ip", "ip"),&NetworkedMultiplayerENet::set_bind_ip);
+ ClassDB::bind_method(D_METHOD("create_server","port","max_clients","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_server,DEFVAL(32),DEFVAL(0),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("create_client","ip","port","in_bandwidth","out_bandwidth"),&NetworkedMultiplayerENet::create_client,DEFVAL(0),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("close_connection"),&NetworkedMultiplayerENet::close_connection);
+ ClassDB::bind_method(D_METHOD("set_compression_mode","mode"),&NetworkedMultiplayerENet::set_compression_mode);
+ ClassDB::bind_method(D_METHOD("get_compression_mode"),&NetworkedMultiplayerENet::get_compression_mode);
+ ClassDB::bind_method(D_METHOD("set_bind_ip", "ip"),&NetworkedMultiplayerENet::set_bind_ip);
BIND_CONSTANT( COMPRESS_NONE );
BIND_CONSTANT( COMPRESS_RANGE_CODER );
diff --git a/modules/etc1/texture_loader_pkm.cpp b/modules/etc1/texture_loader_pkm.cpp
index e720e1fb4c..b00e71c485 100644
--- a/modules/etc1/texture_loader_pkm.cpp
+++ b/modules/etc1/texture_loader_pkm.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* texture_loader_pkm.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "texture_loader_pkm.h"
+
#include "os/file_access.h"
#include <string.h>
diff --git a/modules/etc1/texture_loader_pkm.h b/modules/etc1/texture_loader_pkm.h
index 5788716d9f..9be7b051d3 100644
--- a/modules/etc1/texture_loader_pkm.h
+++ b/modules/etc1/texture_loader_pkm.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* texture_loader_pkm.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 TEXTURE_LOADER_PKM_H
#define TEXTURE_LOADER_PKM_H
diff --git a/modules/gdscript/gd_compiler.h b/modules/gdscript/gd_compiler.h
index dd211a852c..eb6079e8e0 100644
--- a/modules/gdscript/gd_compiler.h
+++ b/modules/gdscript/gd_compiler.h
@@ -93,7 +93,7 @@ class GDCompiler {
//int get_identifier_pos(const StringName& p_dentifier) const;
- HashMap<Variant,int,VariantHasher> constant_map;
+ HashMap<Variant,int,VariantHasher,VariantComparator> constant_map;
Map<StringName,int> name_map;
int get_name_map_pos(const StringName& p_identifier) {
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index 114a25feeb..9dd41847d7 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "gd_script.h"
#include "gd_compiler.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
@@ -323,6 +323,16 @@ void GDScriptLanguage::get_public_constants(List<Pair<String,Variant> > *p_const
pi.first="PI";
pi.second=Math_PI;
p_constants->push_back(pi);
+
+ Pair<String, Variant> infinity;
+ infinity.first = "INF";
+ infinity.second = Math_INF;
+ p_constants->push_back(infinity);
+
+ Pair<String, Variant> nan;
+ nan.first = "NAN";
+ nan.second = Math_NAN;
+ p_constants->push_back(nan);
}
String GDScriptLanguage::make_function(const String& p_class,const String& p_name,const PoolStringArray& p_args) const {
@@ -2645,6 +2655,7 @@ Error GDScriptLanguage::lookup_code(const String& p_code, const String& p_symbol
switch(p.get_completion_type()) {
+ case GDParser::COMPLETION_GET_NODE:
case GDParser::COMPLETION_NONE: {
} break;
case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: {
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp
index 51e2c1e2be..519fb1cd8c 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gd_function.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* gd_function.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "gd_function.h"
+
#include "gd_script.h"
#include "os/os.h"
#include "gd_functions.h"
@@ -171,7 +200,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (p_state) {
//use existing (supplied) state (yielded)
stack=(Variant*)p_state->stack.ptr();
- call_args=(Variant**)&p_state->stack[sizeof(Variant)*p_state->stack_size];
+ call_args=(Variant**)stack + sizeof(Variant)*p_state->stack_size;
line=p_state->line;
ip=p_state->ip;
alloca_size=p_state->stack.size();
@@ -725,7 +754,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
err.argument-=1;
}
}
- } if (methodstr=="free") {
+ } else if (methodstr=="free") {
if (err.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) {
@@ -1490,8 +1519,8 @@ Variant GDFunctionState::resume(const Variant& p_arg) {
void GDFunctionState::_bind_methods() {
- ClassDB::bind_method(_MD("resume:Variant","arg"),&GDFunctionState::resume,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("is_valid"),&GDFunctionState::is_valid);
+ ClassDB::bind_method(D_METHOD("resume:Variant","arg"),&GDFunctionState::resume,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("is_valid"),&GDFunctionState::is_valid);
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&GDFunctionState::_signal_callback,MethodInfo("_signal_callback"));
}
diff --git a/modules/gdscript/gd_function.h b/modules/gdscript/gd_function.h
index e5262e8ad7..aff6341601 100644
--- a/modules/gdscript/gd_function.h
+++ b/modules/gdscript/gd_function.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* gd_function.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 GD_FUNCTION_H
#define GD_FUNCTION_H
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index 34c39c8024..5147ccd63f 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -375,6 +375,22 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
constant->value=Math_PI;
tokenizer->advance();
expr=constant;
+ }
+ else if (tokenizer->get_token() == GDTokenizer::TK_CONST_INF) {
+
+ //constant defined by tokenizer
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ constant->value = Math_INF;
+ tokenizer->advance();
+ expr = constant;
+ }
+ else if (tokenizer->get_token() == GDTokenizer::TK_CONST_NAN) {
+
+ //constant defined by tokenizer
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ constant->value = Math_NAN;
+ tokenizer->advance();
+ expr = constant;
} else if (tokenizer->get_token()==GDTokenizer::TK_PR_PRELOAD) {
//constant defined by tokenizer
@@ -386,21 +402,42 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
tokenizer->advance();
String path;
+ bool found_constant = false;
bool valid = false;
+ ConstantNode *cn;
+
Node *subexpr = _parse_and_reduce_expression(p_parent, p_static);
if (subexpr) {
if (subexpr->type == Node::TYPE_CONSTANT) {
- ConstantNode *cn = static_cast<ConstantNode*>(subexpr);
- if (cn->value.get_type() == Variant::STRING) {
- valid = true;
- path = (String) cn->value;
+ cn = static_cast<ConstantNode*>(subexpr);
+ found_constant = true;
+ }
+ if (subexpr->type == Node::TYPE_IDENTIFIER) {
+ IdentifierNode *in = static_cast<IdentifierNode*>(subexpr);
+ Vector<ClassNode::Constant> ce = current_class->constant_expressions;
+
+ // Try to find the constant expression by the identifier
+ for(int i=0; i < ce.size(); ++i){
+ if(ce[i].identifier == in->name) {
+ if(ce[i].expression->type == Node::TYPE_CONSTANT) {
+ cn = static_cast<ConstantNode*>(ce[i].expression);
+ found_constant = true;
+ }
+ }
}
}
+
+ if (found_constant && cn->value.get_type() == Variant::STRING) {
+ valid = true;
+ path = (String) cn->value;
+ }
}
+
if (!valid) {
_set_error("expected string constant as 'preload' argument.");
return NULL;
}
+
if (!path.is_abs_path() && base_path!="")
path=base_path+"/"+path;
path = path.replace("///","//").simplify_path();
@@ -2577,7 +2614,7 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
Vector<Node*> args;
Vector<double> constants;
- bool constant=true;
+ bool constant=false;
for(int i=1;i<op->arguments.size();i++) {
args.push_back(op->arguments[i]);
@@ -2585,13 +2622,14 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
ConstantNode *c = static_cast<ConstantNode*>(op->arguments[i]);
if (c->value.get_type()==Variant::REAL || c->value.get_type()==Variant::INT) {
constants.push_back(c->value);
- } else {
- constant=false;
+ constant=true;
}
+ } else {
+ constant=false;
}
}
- if (args.size()>0 || args.size()<4) {
+ if (args.size()>0 && args.size()<4) {
if (constant) {
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 89df7e962a..4e72bc39a4 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "gd_script.h"
-#include "globals.h"
+#include "global_config.h"
#include "global_constants.h"
#include "gd_compiler.h"
#include "os/file_access.h"
@@ -63,7 +63,7 @@ bool GDNativeClass::_get(const StringName& p_name,Variant &r_ret) const {
void GDNativeClass::_bind_methods() {
- ClassDB::bind_method(_MD("new"),&GDNativeClass::_new);
+ ClassDB::bind_method(D_METHOD("new"),&GDNativeClass::_new);
}
@@ -789,7 +789,7 @@ void GDScript::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo(Variant::OBJECT,"new"));
- ClassDB::bind_method(_MD("get_as_byte_code"),&GDScript::get_as_byte_code);
+ ClassDB::bind_method(D_METHOD("get_as_byte_code"),&GDScript::get_as_byte_code);
}
@@ -1517,6 +1517,8 @@ void GDScriptLanguage::init() {
}
_add_global(StaticCString::create("PI"),Math_PI);
+ _add_global(StaticCString::create("INF"),Math_INF);
+ _add_global(StaticCString::create("NAN"),Math_NAN);
//populate native classes
@@ -1909,6 +1911,8 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"bool",
"null",
"PI",
+ "INF",
+ "NAN",
"self",
"true",
// functions
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index 5be2a2beae..54b9624e8e 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -120,6 +120,8 @@ const char* GDTokenizer::token_names[TK_MAX]={
"'\\n'",
"PI",
"_",
+"INF",
+"NAN",
"Error",
"EOF",
"Cursor"};
@@ -901,6 +903,8 @@ void GDTokenizerText::_advance() {
{TK_SELF,"self"},
{TK_CONST_PI,"PI"},
{TK_WILDCARD,"_"},
+ {TK_CONST_INF,"INF"},
+ {TK_CONST_NAN,"NAN"},
{TK_ERROR,NULL}
};
@@ -1169,7 +1173,7 @@ Vector<uint8_t> GDTokenizerBuffer::parse_code_string(const String& p_code) {
Map<StringName,int> identifier_map;
- HashMap<Variant,int,VariantHasher> constant_map;
+ HashMap<Variant,int,VariantHasher,VariantComparator> constant_map;
Map<uint32_t,int> line_map;
Vector<uint32_t> token_array;
diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h
index 5d955ff1ae..1e9eda7947 100644
--- a/modules/gdscript/gd_tokenizer.h
+++ b/modules/gdscript/gd_tokenizer.h
@@ -128,6 +128,8 @@ public:
TK_NEWLINE,
TK_CONST_PI,
TK_WILDCARD,
+ TK_CONST_INF,
+ TK_CONST_NAN,
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 db47ee43ce..d1d69c6709 100644
--- a/modules/gdscript/register_types.cpp
+++ b/modules/gdscript/register_types.cpp
@@ -41,10 +41,10 @@ ResourceFormatSaverGDScript *resource_saver_gd=NULL;
#if 0
#ifdef TOOLS_ENABLED
-#include "tools/editor/editor_import_export.h"
+#include "editor/editor_import_export.h"
#include "gd_tokenizer.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/editor_settings.h"
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
class EditorExportGDScript : public EditorExportPlugin {
diff --git a/modules/gridmap/config.py b/modules/gridmap/config.py
index 1ab13c4aeb..5698a37295 100644
--- a/modules/gridmap/config.py
+++ b/modules/gridmap/config.py
@@ -1,8 +1,7 @@
def can_build(platform):
- # FIXME: Disabled temporary for gles3 implementation
- return False
+ return True
def configure(env):
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 2dd7e951ab..d4fb174bfe 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -31,7 +31,7 @@
#include "scene/resources/surface_tool.h"
#include "message_queue.h"
#include "scene/3d/light.h"
-#include "scene/3d/baked_light_instance.h"
+
#include "io/marshalls.h"
#include "scene/scene_string_names.h"
#include "os/os.h"
@@ -41,25 +41,21 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
String name=p_name;
- if (name=="theme/theme") {
+ if (name=="theme") {
set_theme(p_value);
- } else if (name=="cell/size") {
+ } else if (name=="cell_size") {
set_cell_size(p_value);
- } else if (name=="cell/octant_size") {
+ } else if (name=="cell_octant_size") {
set_octant_size(p_value);
- } else if (name=="cell/center_x") {
+ } else if (name=="cell_center_x") {
set_center_x(p_value);
- } else if (name=="cell/center_y") {
+ } else if (name=="cell_center_y") {
set_center_y(p_value);
- } else if (name=="cell/center_z") {
+ } else if (name=="cell_center_z") {
set_center_z(p_value);
- } else if (name=="cell/scale") {
+ } else if (name=="cell_scale") {
set_cell_scale(p_value);
- } else if (name=="lighting/bake") {
- set_use_baked_light(p_value);
- } else if (name=="theme/bake") {
- set_bake(p_value);
/* } else if (name=="cells") {
PoolVector<int> cells = p_value;
int amount=cells.size();
@@ -81,9 +77,6 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
Dictionary d = p_value;
- Dictionary baked;
- if (d.has("baked"))
- baked=d["baked"];
if (d.has("cells")) {
PoolVector<int> cells = d["cells"];
@@ -101,33 +94,7 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
}
}
- baked_lock=baked.size()!=0;
_recreate_octant_data();
- baked_lock=false;
- if (!baked.empty()) {
- List<Variant> kl;
- baked.get_key_list(&kl);
- for (List<Variant>::Element *E=kl.front();E;E=E->next()) {
-
- Plane ikv = E->get();
- Ref<Mesh> b=baked[ikv];
- ERR_CONTINUE(!b.is_valid());
- OctantKey ok;
- ok.x=ikv.normal.x;
- ok.y=ikv.normal.y;
- ok.z=ikv.normal.z;
- ok.area=ikv.d;
-
- ERR_CONTINUE(!octant_map.has(ok));
-
- Octant &g = *octant_map[ok];
-
- g.baked=b;
- g.bake_instance=VS::get_singleton()->instance_create();
- VS::get_singleton()->instance_set_base(g.bake_instance,g.baked->get_rid());
- VS::get_singleton()->instance_geometry_set_baked_light(g.bake_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID());
- }
- }
} else if (name.begins_with("areas/")) {
@@ -161,24 +128,20 @@ bool GridMap::_get(const StringName& p_name,Variant &r_ret) const {
String name=p_name;
- if (name=="theme/theme") {
+ if (name=="theme") {
r_ret= get_theme();
- } else if (name=="cell/size") {
+ } else if (name=="cell_size") {
r_ret= get_cell_size();
- } else if (name=="cell/octant_size") {
+ } else if (name=="cell_octant_size") {
r_ret= get_octant_size();
- } else if (name=="cell/center_x") {
+ } else if (name=="cell_center_x") {
r_ret= get_center_x();
- } else if (name=="cell/center_y") {
+ } else if (name=="cell_center_y") {
r_ret= get_center_y();
- } else if (name=="cell/center_z") {
+ } else if (name=="cell_center_z") {
r_ret= get_center_z();
- } else if (name=="cell/scale") {
+ } else if (name=="cell_scale") {
r_ret= cell_scale;
- } else if (name=="lighting/bake") {
- r_ret=is_using_baked_light();
- } else if (name=="theme/bake") {
- r_ret= bake;
} else if (name=="data") {
Dictionary d;
@@ -197,23 +160,8 @@ bool GridMap::_get(const StringName& p_name,Variant &r_ret) const {
d["cells"]=cells;
- Dictionary baked;
- for(Map<OctantKey,Octant*>::Element *E=octant_map.front();E;E=E->next()) {
-
- Octant &g=*E->get();
-
- if (g.baked.is_valid()) {
-
- baked[Plane(E->key().x,E->key().y,E->key().z,E->key().area)]=g.baked;
- }
- }
-
- if (baked.size()) {
- d["baked"]=baked;
- }
-
r_ret= d;
} else if (name.begins_with("areas/")) {
int which = name.get_slicec('/',1).to_int();
@@ -237,15 +185,14 @@ bool GridMap::_get(const StringName& p_name,Variant &r_ret) const {
void GridMap::_get_property_list( List<PropertyInfo> *p_list) const {
- p_list->push_back( PropertyInfo( Variant::OBJECT, "theme/theme", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"));
- p_list->push_back( PropertyInfo( Variant::BOOL, "theme/bake"));
- p_list->push_back( PropertyInfo( Variant::BOOL, "lighting/bake"));
- p_list->push_back( PropertyInfo( Variant::REAL, "cell/size",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
- p_list->push_back( PropertyInfo( Variant::INT, "cell/octant_size",PROPERTY_HINT_RANGE,"1,1024,1") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "cell/center_x") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "cell/center_y") );
- p_list->push_back( PropertyInfo( Variant::BOOL, "cell/center_z") );
- p_list->push_back( PropertyInfo( Variant::REAL, "cell/scale") );
+ p_list->push_back( PropertyInfo( Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary"));
+ p_list->push_back( PropertyInfo( Variant::NIL, "Cell", PROPERTY_HINT_NONE,"cell_",PROPERTY_USAGE_GROUP));
+ p_list->push_back( PropertyInfo( Variant::REAL, "cell_size",PROPERTY_HINT_RANGE,"0.01,16384,0.01") );
+ p_list->push_back( PropertyInfo( Variant::INT, "cell_octant_size",PROPERTY_HINT_RANGE,"1,1024,1") );
+ p_list->push_back( PropertyInfo( Variant::BOOL, "cell_center_x") );
+ p_list->push_back( PropertyInfo( Variant::BOOL, "cell_center_y") );
+ p_list->push_back( PropertyInfo( Variant::BOOL, "cell_center_z") );
+ p_list->push_back( PropertyInfo( Variant::REAL, "cell_scale") );
p_list->push_back( PropertyInfo( Variant::DICTIONARY, "data", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_STORAGE) );
@@ -380,17 +327,6 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
g.items.erase(prev_item);
}
-
- if (g.items.empty() || !baked_lock) {
- //unbake just in case
- if (g.baked.is_valid()) {
- VS::get_singleton()->free(g.bake_instance);
- g.bake_instance=RID();
- g.baked=Ref<Mesh>();
- }
-
-
- }
if (g.items.empty()) {
PhysicsServer::get_singleton()->free(g.static_body);
@@ -454,24 +390,12 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
ii.navmesh=theme->get_item_navmesh(p_item);
}
ii.multimesh = Ref<MultiMesh>( memnew( MultiMesh ) );
+ ii.multimesh->set_color_format(MultiMesh::COLOR_NONE);
+ ii.multimesh->set_transform_format(MultiMesh::TRANSFORM_3D);
ii.multimesh->set_mesh(ii.mesh);
ii.multimesh_instance = VS::get_singleton()->instance_create();
VS::get_singleton()->instance_set_base(ii.multimesh_instance,ii.multimesh->get_rid());
- VS::get_singleton()->instance_geometry_set_baked_light(ii.multimesh_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID());
-
- if (!baked_lock) {
- //unbake just in case
- if (g.bake_instance.is_valid())
- VS::get_singleton()->free(g.bake_instance);
- g.baked=Ref<Mesh>();
- if (is_inside_world()) {
- VS::get_singleton()->instance_set_scenario(ii.multimesh_instance,get_world()->get_scenario());
- if (ok.area) {
- VS::get_singleton()->instance_set_room( ii.multimesh_instance,area_map[ok.area]->instance);
- }
- }
- }
g.items[p_item]=ii;
}
@@ -585,27 +509,14 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
VS::get_singleton()->instance_set_room(g.collision_debug_instance,area_map[p_key.area]->instance);
}
}
- if (g.baked.is_valid()) {
+ for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
- Transform xf = get_global_transform();
- xf.translate(_octant_get_offset(p_key));
+ VS::get_singleton()->instance_set_scenario(E->get().multimesh_instance,get_world()->get_scenario());
+ VS::get_singleton()->instance_set_transform(E->get().multimesh_instance,get_global_transform());
+ //print_line("INSTANCEPOS: "+get_global_transform());
- VS::get_singleton()->instance_set_transform(g.bake_instance,xf);
- VS::get_singleton()->instance_set_scenario(g.bake_instance,get_world()->get_scenario());
if (area_map.has(p_key.area)) {
- VS::get_singleton()->instance_set_room(g.bake_instance,area_map[p_key.area]->instance);
-
- }
- } else {
- for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
-
- VS::get_singleton()->instance_set_scenario(E->get().multimesh_instance,get_world()->get_scenario());
- VS::get_singleton()->instance_set_transform(E->get().multimesh_instance,get_global_transform());
- //print_line("INSTANCEPOS: "+get_global_transform());
-
- if (area_map.has(p_key.area)) {
- VS::get_singleton()->instance_set_room(E->get().multimesh_instance,area_map[p_key.area]->instance);
- }
+ VS::get_singleton()->instance_set_room(E->get().multimesh_instance,area_map[p_key.area]->instance);
}
}
}
@@ -621,17 +532,10 @@ void GridMap::_octant_transform(const OctantKey &p_key) {
VS::get_singleton()->instance_set_transform(g.collision_debug_instance,get_global_transform());
}
- if (g.baked.is_valid()) {
-
- Transform xf = get_global_transform();
- xf.origin+=_octant_get_offset(p_key);
- VS::get_singleton()->instance_set_transform(g.bake_instance,xf);
- } else {
- for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
+ for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
- VS::get_singleton()->instance_set_transform(E->get().multimesh_instance,get_global_transform());
- //print_line("UPDATEPOS: "+get_global_transform());
- }
+ VS::get_singleton()->instance_set_transform(E->get().multimesh_instance,get_global_transform());
+ //print_line("UPDATEPOS: "+get_global_transform());
}
}
@@ -711,7 +615,7 @@ void GridMap::_octant_update(const OctantKey &p_key) {
ii.multimesh->set_instance_transform(idx,xform);
//ii.multimesh->set_instance_transform(idx,Transform() );
- ii.multimesh->set_instance_color(idx,Color(1,1,1,1));
+ //ii.multimesh->set_instance_color(idx,Color(1,1,1,1));
//print_line("MMINST: "+xform);
@@ -748,7 +652,7 @@ void GridMap::_octant_update(const OctantKey &p_key) {
idx++;
}
- ii.multimesh->set_aabb(aabb);
+ //ii.multimesh->set_aabb(aabb);
}
@@ -760,7 +664,7 @@ void GridMap::_octant_update(const OctantKey &p_key) {
arr.resize(VS::ARRAY_MAX);
arr[VS::ARRAY_VERTEX]=col_debug;
- VS::get_singleton()->mesh_add_surface(g.collision_debug,VS::PRIMITIVE_LINES,arr);
+ VS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug,VS::PRIMITIVE_LINES,arr);
SceneTree *st=SceneTree::get_singleton();
if (st) {
VS::get_singleton()->mesh_surface_set_material( g.collision_debug, 0,st->get_debug_collision_material()->get_rid() );
@@ -780,13 +684,6 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
PhysicsServer::get_singleton()->body_set_space(g.static_body,RID());
- if (g.baked.is_valid()) {
-
- VS::get_singleton()->instance_set_room(g.bake_instance,RID());
- VS::get_singleton()->instance_set_scenario(g.bake_instance,RID());
-
- }
-
if (g.collision_debug_instance.is_valid()) {
VS::get_singleton()->instance_set_room(g.collision_debug_instance,RID());
@@ -802,194 +699,6 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
}
-void GridMap::_octant_clear_baked(const OctantKey &p_key) {
-
-
- ERR_FAIL_COND(!octant_map.has(p_key));
- Octant&g = *octant_map[p_key];
-
- if (!g.baked.is_valid())
- return;
-
- VS::get_singleton()->free(g.bake_instance);
- g.bake_instance=RID();
- g.baked=Ref<Mesh>();
-
- if (is_inside_tree())
- _octant_enter_world(p_key);
- g.dirty=true;
- _queue_dirty_map();
-}
-
-void GridMap::_octant_bake(const OctantKey &p_key, const Ref<TriangleMesh>& p_tmesh,const Vector<BakeLight> &p_lights,List<Vector3> *p_prebake) {
-
-
- ERR_FAIL_COND(!octant_map.has(p_key));
- Octant&g = *octant_map[p_key];
-
- Ref<TriangleMesh> tm=p_tmesh;
- if (!p_prebake && is_inside_world())
- _octant_exit_world(p_key);
-
- Map< Ref<Material>, Ref<SurfaceTool> > surfaces;
- Vector3 ofs(cell_size*0.5*int(center_x),cell_size*0.5*int(center_y),cell_size*0.5*int(center_z));
- Vector3 octant_ofs=_octant_get_offset(p_key);
-
- for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
-
- Octant::ItemInstances &ii=E->get();
-
- if (ii.mesh.is_null())
- continue;
-
- for(Set<IndexKey>::Element *F=ii.cells.front();F;F=F->next()) {
-
- IndexKey ik=F->get();
- Map<IndexKey,Cell>::Element *C=cell_map.find(ik);
- ERR_CONTINUE(!C);
- Vector3 cellpos = Vector3(ik.x,ik.y,ik.z );
-
- Transform xform;
- xform.basis.set_orthogonal_index(C->get().rot);
- xform.set_origin( cellpos*cell_size+ofs);
- if (!p_prebake)
- xform.origin-=octant_ofs;
-
-
- for(int i=0;i<ii.mesh->get_surface_count();i++) {
-
- if (p_prebake) {
-
- if (ii.mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES)
- continue;
- Array a = ii.mesh->surface_get_arrays(i);
- PoolVector<Vector3> av=a[VS::ARRAY_VERTEX];
- int avs = av.size();
- PoolVector<Vector3>::Read vr = av.read();
-
- PoolVector<int> ai=a[VS::ARRAY_INDEX];
- int ais=ai.size();
- if (ais) {
-
- PoolVector<int>::Read ir=ai.read();
- for(int j=0;j<ais;j++) {
-
- p_prebake->push_back(xform.xform(vr[ir[j]]));
- //print_line("V SET: "+xform.xform(vr[ir[j]]));
- }
-
- } else {
-
- for(int j=0;j<avs;j++) {
-
- p_prebake->push_back(xform.xform(vr[j]));
- }
- }
-
- } else {
-
- Ref<Material> m = ii.mesh->surface_get_material(i);
-
- Map< Ref<Material>, Ref<SurfaceTool> >::Element *S=surfaces.find(m);
-
- if (!S) {
-
- S=surfaces.insert(m,Ref<SurfaceTool>( memnew( SurfaceTool )));
- }
-
- Ref<SurfaceTool> st = S->get();
- List<SurfaceTool::Vertex>::Element *V=st->get_vertex_array().back();
- st->append_from(ii.mesh,i,xform);
- st->set_material(m);
-
-
- if (tm.is_valid()) {
-
- if (V)
- V=V->next();
- else
- V=st->get_vertex_array().front();
- int lc = p_lights.size();
- const BakeLight* bl = p_lights.ptr();
- float ofs = cell_size*0.02;
-
-
- for(;V;V=V->next()) {
-
- SurfaceTool::Vertex &v=V->get();
-
- Vector3 vertex = v.vertex + octant_ofs;
- //print_line("V GET: "+vertex);
- Vector3 normal = tm->get_area_normal( Rect3( Vector3(-ofs,-ofs,-ofs)+vertex,Vector3(ofs,ofs,ofs)*2.0));
- if (normal==Vector3()) {
- print_line("couldn't find for vertex: "+vertex);
- }
- ERR_CONTINUE( normal== Vector3());
-
- float max_l=1.0;
- float max_dist=1.0;
-
- if (lc) {
-
- for(int j=0;j<lc;j++) {
- const BakeLight &l=bl[j];
- switch(l.type) {
- case VS::LIGHT_DIRECTIONAL: {
-
- Vector3 ray_from=vertex + normal *ofs;
- Vector3 ray_to=l.dir*5000;
- Vector3 n;
- Vector3 p;
- if (tm->intersect_segment(ray_from,ray_to,p,n)) {
-
- float dist = 1.0-l.param[VS::LIGHT_PARAM_SHADOW_DARKENING];
- if (dist<=max_dist) {
- max_dist=dist;
- max_l=1.0-dist;
- }
- }
- } break;
- }
-
- }
- }
-
- v.color=Color(max_l,max_l,max_l,1.0);
-
- }
-
- st->add_to_format(VS::ARRAY_FORMAT_COLOR);
- if (m.is_valid()) {
- Ref<FixedSpatialMaterial> fm = m;
- if (fm.is_valid())
- fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true);
- }
- }
- }
- }
- }
- }
-
- if (p_prebake)
- return;
-
- g.baked = Ref<Mesh>( memnew( Mesh ));
-
- for(Map< Ref<Material>, Ref<SurfaceTool> >::Element *E=surfaces.front();E;E=E->next()) {
-
- Ref<SurfaceTool> st = E->get();
- st->commit(g.baked);
- }
-
- g.bake_instance = VS::get_singleton()->instance_create();
- VS::get_singleton()->instance_set_base(g.bake_instance,g.baked->get_rid());
-
- if (is_inside_world())
- _octant_enter_world(p_key);
-
- g.dirty=true;
- _queue_dirty_map();
-}
void GridMap::_notification(int p_what) {
@@ -1011,10 +720,6 @@ void GridMap::_notification(int p_what) {
last_transform=get_global_transform();
- if (use_baked_light) {
-
- _find_baked_light();
- }
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -1036,15 +741,6 @@ void GridMap::_notification(int p_what) {
_octant_exit_world(E->key());
}
- if (use_baked_light) {
-
- if (baked_light_instance) {
- baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed);
- baked_light_instance=NULL;
- }
- _baked_light_changed();
-
- }
//_queue_dirty_map(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
//_update_dirty_map_callback();
@@ -1122,9 +818,6 @@ void GridMap::_clear_internal(bool p_keep_areas) {
VS::get_singleton()->free(F->get().multimesh_instance);
}
- //unbake just in case
- if (E->get()->bake_instance.is_valid())
- VS::get_singleton()->free(E->get()->bake_instance);
if (E->get()->collision_debug.is_valid())
VS::get_singleton()->free(E->get()->collision_debug);
@@ -1185,60 +878,48 @@ void GridMap::_update_dirty_map_callback() {
void GridMap::_bind_methods() {
- ClassDB::bind_method(_MD("set_theme","theme:MeshLibrary"),&GridMap::set_theme);
- ClassDB::bind_method(_MD("get_theme:MeshLibrary"),&GridMap::get_theme);
-
- ClassDB::bind_method(_MD("set_bake","enable"),&GridMap::set_bake);
- ClassDB::bind_method(_MD("is_baking_enabled"),&GridMap::is_baking_enabled);
-
- ClassDB::bind_method(_MD("set_cell_size","size"),&GridMap::set_cell_size);
- ClassDB::bind_method(_MD("get_cell_size"),&GridMap::get_cell_size);
-
- ClassDB::bind_method(_MD("set_octant_size","size"),&GridMap::set_octant_size);
- ClassDB::bind_method(_MD("get_octant_size"),&GridMap::get_octant_size);
-
- ClassDB::bind_method(_MD("set_cell_item","x","y","z","item","orientation"),&GridMap::set_cell_item,DEFVAL(0));
- ClassDB::bind_method(_MD("get_cell_item","x","y","z"),&GridMap::get_cell_item);
- ClassDB::bind_method(_MD("get_cell_item_orientation","x","y","z"),&GridMap::get_cell_item_orientation);
-
- //ClassDB::bind_method(_MD("_recreate_octants"),&GridMap::_recreate_octants);
- ClassDB::bind_method(_MD("_update_dirty_map_callback"),&GridMap::_update_dirty_map_callback);
- ClassDB::bind_method(_MD("resource_changed","resource"),&GridMap::resource_changed);
+ ClassDB::bind_method(D_METHOD("set_theme","theme:MeshLibrary"),&GridMap::set_theme);
+ ClassDB::bind_method(D_METHOD("get_theme:MeshLibrary"),&GridMap::get_theme);
- ClassDB::bind_method(_MD("set_center_x","enable"),&GridMap::set_center_x);
- ClassDB::bind_method(_MD("get_center_x"),&GridMap::get_center_x);
- ClassDB::bind_method(_MD("set_center_y","enable"),&GridMap::set_center_y);
- ClassDB::bind_method(_MD("get_center_y"),&GridMap::get_center_y);
- ClassDB::bind_method(_MD("set_center_z","enable"),&GridMap::set_center_z);
- ClassDB::bind_method(_MD("get_center_z"),&GridMap::get_center_z);
+ ClassDB::bind_method(D_METHOD("set_cell_size","size"),&GridMap::set_cell_size);
+ ClassDB::bind_method(D_METHOD("get_cell_size"),&GridMap::get_cell_size);
- ClassDB::bind_method(_MD("set_clip","enabled","clipabove","floor","axis"),&GridMap::set_clip,DEFVAL(true),DEFVAL(0),DEFVAL(Vector3::AXIS_X));
+ ClassDB::bind_method(D_METHOD("set_octant_size","size"),&GridMap::set_octant_size);
+ ClassDB::bind_method(D_METHOD("get_octant_size"),&GridMap::get_octant_size);
- ClassDB::bind_method(_MD("create_area","id","area"),&GridMap::create_area);
- ClassDB::bind_method(_MD("area_get_bounds","area","bounds"),&GridMap::area_get_bounds);
- ClassDB::bind_method(_MD("area_set_exterior_portal","area","enable"),&GridMap::area_set_exterior_portal);
- ClassDB::bind_method(_MD("area_set_name","area","name"),&GridMap::area_set_name);
- ClassDB::bind_method(_MD("area_get_name","area"),&GridMap::area_get_name);
- ClassDB::bind_method(_MD("area_is_exterior_portal","area"),&GridMap::area_is_exterior_portal);
- ClassDB::bind_method(_MD("area_set_portal_disable_distance","area","distance"),&GridMap::area_set_portal_disable_distance);
- ClassDB::bind_method(_MD("area_get_portal_disable_distance","area"),&GridMap::area_get_portal_disable_distance);
- ClassDB::bind_method(_MD("area_set_portal_disable_color","area","color"),&GridMap::area_set_portal_disable_color);
- ClassDB::bind_method(_MD("area_get_portal_disable_color","area"),&GridMap::area_get_portal_disable_color);
- ClassDB::bind_method(_MD("erase_area","area"),&GridMap::erase_area);
- ClassDB::bind_method(_MD("get_unused_area_id","area"),&GridMap::get_unused_area_id);
- ClassDB::bind_method(_MD("bake_geometry"),&GridMap::bake_geometry);
+ ClassDB::bind_method(D_METHOD("set_cell_item","x","y","z","item","orientation"),&GridMap::set_cell_item,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_cell_item","x","y","z"),&GridMap::get_cell_item);
+ ClassDB::bind_method(D_METHOD("get_cell_item_orientation","x","y","z"),&GridMap::get_cell_item_orientation);
- ClassDB::bind_method(_MD("_baked_light_changed"),&GridMap::_baked_light_changed);
- ClassDB::bind_method(_MD("set_use_baked_light","use"),&GridMap::set_use_baked_light);
- ClassDB::bind_method(_MD("is_using_baked_light","use"),&GridMap::is_using_baked_light);
+ //ClassDB::bind_method(D_METHOD("_recreate_octants"),&GridMap::_recreate_octants);
+ ClassDB::bind_method(D_METHOD("_update_dirty_map_callback"),&GridMap::_update_dirty_map_callback);
+ ClassDB::bind_method(D_METHOD("resource_changed","resource"),&GridMap::resource_changed);
- ClassDB::bind_method(_MD("_get_baked_light_meshes"),&GridMap::_get_baked_light_meshes);
+ ClassDB::bind_method(D_METHOD("set_center_x","enable"),&GridMap::set_center_x);
+ ClassDB::bind_method(D_METHOD("get_center_x"),&GridMap::get_center_x);
+ ClassDB::bind_method(D_METHOD("set_center_y","enable"),&GridMap::set_center_y);
+ ClassDB::bind_method(D_METHOD("get_center_y"),&GridMap::get_center_y);
+ ClassDB::bind_method(D_METHOD("set_center_z","enable"),&GridMap::set_center_z);
+ ClassDB::bind_method(D_METHOD("get_center_z"),&GridMap::get_center_z);
+ ClassDB::bind_method(D_METHOD("set_clip","enabled","clipabove","floor","axis"),&GridMap::set_clip,DEFVAL(true),DEFVAL(0),DEFVAL(Vector3::AXIS_X));
+ ClassDB::bind_method(D_METHOD("create_area","id","area"),&GridMap::create_area);
+ ClassDB::bind_method(D_METHOD("area_get_bounds","area","bounds"),&GridMap::area_get_bounds);
+ ClassDB::bind_method(D_METHOD("area_set_exterior_portal","area","enable"),&GridMap::area_set_exterior_portal);
+ ClassDB::bind_method(D_METHOD("area_set_name","area","name"),&GridMap::area_set_name);
+ ClassDB::bind_method(D_METHOD("area_get_name","area"),&GridMap::area_get_name);
+ ClassDB::bind_method(D_METHOD("area_is_exterior_portal","area"),&GridMap::area_is_exterior_portal);
+ ClassDB::bind_method(D_METHOD("area_set_portal_disable_distance","area","distance"),&GridMap::area_set_portal_disable_distance);
+ ClassDB::bind_method(D_METHOD("area_get_portal_disable_distance","area"),&GridMap::area_get_portal_disable_distance);
+ ClassDB::bind_method(D_METHOD("area_set_portal_disable_color","area","color"),&GridMap::area_set_portal_disable_color);
+ ClassDB::bind_method(D_METHOD("area_get_portal_disable_color","area"),&GridMap::area_get_portal_disable_color);
+ ClassDB::bind_method(D_METHOD("erase_area","area"),&GridMap::erase_area);
+ ClassDB::bind_method(D_METHOD("get_unused_area_id","area"),&GridMap::get_unused_area_id);
- ClassDB::set_method_flags("GridMap","bake_geometry",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("clear"),&GridMap::clear);
- ClassDB::bind_method(_MD("clear"),&GridMap::clear);
+ ClassDB::bind_method(D_METHOD("get_meshes"),&GridMap::get_meshes);
BIND_CONSTANT( INVALID_CELL_ITEM );
@@ -1622,23 +1303,6 @@ int GridMap::get_unused_area_id() const {
return area_map.back()->key()+1;
}
-
-void GridMap::set_bake(bool p_bake) {
-
- bake=p_bake;
- if (bake==false) {
- for(Map<OctantKey,Octant*>::Element *E=octant_map.front();E;E=E->next()) {
-
- _octant_clear_baked(E->key());
- }
- }
-}
-
-bool GridMap::is_baking_enabled() const {
-
- return bake;
-}
-
void GridMap::set_cell_scale(float p_scale) {
cell_scale=p_scale;
@@ -1652,100 +1316,8 @@ float GridMap::get_cell_scale() const{
-void GridMap::bake_geometry() {
-
- //used to compute vertex occlusion
- Ref<TriangleMesh> tmesh;
- Vector<BakeLight> lights;
-
- if (true) {
-
- List<Vector3> vertices;
-
- for(Map<OctantKey,Octant*>::Element *E=octant_map.front();E;E=E->next()) {
- _octant_bake(E->key(),tmesh,lights,&vertices);
-
- }
-
- PoolVector<Vector3> vv;
- vv.fill_with(vertices);
- //print_line("TOTAL VERTICES: "+itos(vv.size()));
- tmesh = Ref<TriangleMesh>( memnew( TriangleMesh ));
- tmesh->create(vv);
-
- for(int i=0;i<get_child_count();i++) {
-
- if (get_child(i)->cast_to<Light>()) {
- Light *l = get_child(i)->cast_to<Light>();
- BakeLight bl;
- for(int i=0;i<Light::PARAM_MAX;i++) {
- bl.param[i]=l->get_parameter(Light::Parameter(i));
- }
- Transform t=l->get_global_transform();
- bl.pos=t.origin;
- bl.dir=t.basis.get_axis(2);
- bl.type=l->get_light_type();
- lights.push_back(bl);
-
- }
- }
- }
-
- int idx=0;
- for(Map<OctantKey,Octant*>::Element *E=octant_map.front();E;E=E->next()) {
- if (E->get()->baked.is_valid())
- _octant_clear_baked(E->key());
-
- _octant_bake(E->key(),tmesh,lights);
- print_line("baking "+itos(idx)+"/"+itos(octant_map.size()));
- idx++;
- }
-
-}
-
-void GridMap::_baked_light_changed() {
-
- /*
- if (!baked_light_instance)
- VS::get_singleton()->instance_geometry_set_baked_light(get_instance(),RID());
- else
- VS::get_singleton()->instance_geometry_set_baked_light(get_instance(),baked_light_instance->get_baked_light_instance());
- */
- for(Map<OctantKey,Octant*>::Element *E=octant_map.front();E;E=E->next()) {
-
- for(Map<int,Octant::ItemInstances>::Element *F=E->get()->items.front();F;F=F->next()) {
-
- VS::get_singleton()->instance_geometry_set_baked_light(F->get().multimesh_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID());
- }
-
- }
-
-}
-
-void GridMap::_find_baked_light() {
-
- Node *n=get_parent();
- while(n) {
-
- BakedLightInstance *bl=n->cast_to<BakedLightInstance>();
- if (bl) {
-
- baked_light_instance=bl;
- baked_light_instance->connect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed);
- _baked_light_changed();
-
- return;
- }
-
- n=n->get_parent();
- }
-
- _baked_light_changed();
-}
-
-
-Array GridMap::_get_baked_light_meshes() {
+Array GridMap::get_meshes() {
if (theme.is_null())
return Array();
@@ -1783,31 +1355,6 @@ Array GridMap::_get_baked_light_meshes() {
return meshes;
}
-void GridMap::set_use_baked_light(bool p_use) {
-
- if (use_baked_light==p_use)
- return;
-
- use_baked_light=p_use;
-
- if (is_inside_world()) {
- if (!p_use) {
- if (baked_light_instance) {
- baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed);
- baked_light_instance=NULL;
- }
- _baked_light_changed();
- } else {
- _find_baked_light();
- }
- }
-
-}
-
-bool GridMap::is_using_baked_light() const{
-
- return use_baked_light;
-}
@@ -1825,12 +1372,8 @@ GridMap::GridMap() {
clip_floor=0;
clip_axis=Vector3::AXIS_Z;
clip_above=true;
- baked_lock=false;
- bake=false;
cell_scale=1.0;
- baked_light_instance=NULL;
- use_baked_light=false;
navigation = NULL;
set_notify_transform(true);
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 04d140cdc6..5d4133383b 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -103,8 +103,6 @@ class GridMap : public Spatial {
Ref<NavigationMesh> navmesh;
};
- Ref<Mesh> baked;
- RID bake_instance;
RID collision_debug;
RID collision_debug_instance;
@@ -140,14 +138,12 @@ class GridMap : public Spatial {
float cell_size;
int octant_size;
bool center_x,center_y,center_z;
- bool bake;
float cell_scale;
Navigation *navigation;
bool clip;
bool clip_above;
int clip_floor;
- bool baked_lock;
Vector3::Axis clip_axis;
@@ -205,9 +201,7 @@ class GridMap : public Spatial {
void _octant_exit_world(const OctantKey &p_key);
void _octant_update(const OctantKey &p_key);
void _octant_transform(const OctantKey &p_key);
- void _octant_clear_baked(const OctantKey &p_key);
void _octant_clear_navmesh(const GridMap::OctantKey&);
- void _octant_bake(const OctantKey &p_key,const Ref<TriangleMesh>& p_tmesh=RES(),const Vector<BakeLight> &p_lights=Vector<BakeLight>(),List<Vector3> *r_prebake=NULL);
bool awaiting_update;
void _queue_dirty_map();
@@ -221,14 +215,6 @@ class GridMap : public Spatial {
void _clear_internal(bool p_keep_areas=false);
- BakedLightInstance *baked_light_instance;
- bool use_baked_light;
- void _find_baked_light();
- void _baked_light_changed();
-
-
- Array _get_baked_light_meshes();
-
protected:
bool _set(const StringName& p_name, const Variant& p_value);
@@ -285,13 +271,11 @@ public:
void set_cell_scale(float p_scale);
float get_cell_scale() const;
- void set_bake(bool p_bake);
- bool is_baking_enabled() const;
- void bake_geometry();
- void set_use_baked_light(bool p_use);
- bool is_using_baked_light() const;
+ Array get_meshes();
+
+
void clear();
GridMap();
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 0d57ffa394..a5d2f84c68 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -27,9 +27,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "grid_map_editor_plugin.h"
-#include "tools/editor/plugins/spatial_editor_plugin.h"
+#include "editor/plugins/spatial_editor_plugin.h"
#include "scene/3d/camera.h"
-#include "tools/editor/editor_settings.h"
+#include "editor/editor_settings.h"
#include "os/keyboard.h"
#include "geometry.h"
@@ -249,7 +249,7 @@ void GridMapEditor::_update_cursor_transform() {
if (cursor_instance.is_valid()) {
VisualServer::get_singleton()->instance_set_transform(cursor_instance,cursor_transform);
- VisualServer::get_singleton()->instance_geometry_set_flag(cursor_instance,VS::INSTANCE_FLAG_VISIBLE,cursor_visible);
+ VisualServer::get_singleton()->instance_set_visible(cursor_instance,cursor_visible);
}
}
@@ -852,11 +852,11 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
if (!node) {
set_process(false);
for(int i=0;i<3;i++) {
- VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i],VS::INSTANCE_FLAG_VISIBLE,false);
+ VisualServer::get_singleton()->instance_set_visible(grid_instance[i],false);
}
- VisualServer::get_singleton()->instance_geometry_set_flag(cursor_instance, VS::INSTANCE_FLAG_VISIBLE,false);
+ VisualServer::get_singleton()->instance_set_visible(cursor_instance,false);
_clear_areas();
@@ -884,13 +884,11 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
{
//update grids
- indicator_mat = VisualServer::get_singleton()->fixed_material_create();
- VisualServer::get_singleton()->material_set_flag( indicator_mat, VisualServer::MATERIAL_FLAG_UNSHADED, true );
- VisualServer::get_singleton()->material_set_flag( indicator_mat, VisualServer::MATERIAL_FLAG_ONTOP, false );
-
- VisualServer::get_singleton()->fixed_material_set_param(indicator_mat,VisualServer::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0.8,0.5,0.1));
- VisualServer::get_singleton()->fixed_material_set_flag( indicator_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true );
- VisualServer::get_singleton()->fixed_material_set_flag( indicator_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, true );
+ indicator_mat.instance();
+ indicator_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+ indicator_mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
+ indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
+ indicator_mat->set_albedo(Color(0.8,0.5,0.1));
Vector<Vector3> grid_points[3];
@@ -937,8 +935,8 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
d.resize(VS::ARRAY_MAX);
d[VS::ARRAY_VERTEX]=grid_points[i];
d[VS::ARRAY_COLOR]=grid_colors[i];
- VisualServer::get_singleton()->mesh_add_surface(grid[i],VisualServer::PRIMITIVE_LINES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(grid[i],0,indicator_mat);
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i],VisualServer::PRIMITIVE_LINES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(grid[i],0,indicator_mat->get_rid());
}
@@ -976,7 +974,7 @@ void GridMapEditor::update_grid() {
for(int i=0;i<3;i++) {
- VisualServer::get_singleton()->instance_geometry_set_flag(grid_instance[i],VS::INSTANCE_FLAG_VISIBLE,i==edit_axis);
+ VisualServer::get_singleton()->instance_set_visible(grid_instance[i],i==edit_axis);
}
@@ -1103,7 +1101,7 @@ void GridMapEditor::_update_areas_display() {
if (!node) {
return;
}
-
+#if 0
_clear_areas();
List<int> areas;
node->get_area_list(&areas);
@@ -1118,6 +1116,8 @@ void GridMapEditor::_update_areas_display() {
color=Color(1,1,1,0.2);
else
color.set_hsv(Math::fmod(area*0.37,1),Math::fmod(area*0.75,1),1.0,0.2);
+
+
RID material = VisualServer::get_singleton()->fixed_material_create();
VisualServer::get_singleton()->fixed_material_set_param( material, VS::FIXED_MATERIAL_PARAM_DIFFUSE,color );
VisualServer::get_singleton()->fixed_material_set_param( material, VS::FIXED_MATERIAL_PARAM_EMISSION,0.5 );
@@ -1149,7 +1149,7 @@ void GridMapEditor::_update_areas_display() {
this->areas.push_back(ad);
}
-
+#endif
}
void GridMapEditor::_edit_mode_changed(int p_what) {
@@ -1189,7 +1189,7 @@ void GridMapEditor::_bind_methods() {
ClassDB::bind_method("_area_selected",&GridMapEditor::_area_selected);
ClassDB::bind_method("_floor_changed",&GridMapEditor::_floor_changed);
- ClassDB::bind_method(_MD("_set_display_mode","mode"), &GridMapEditor::_set_display_mode);
+ ClassDB::bind_method(D_METHOD("_set_display_mode","mode"), &GridMapEditor::_set_display_mode);
}
@@ -1295,7 +1295,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
hb->add_child(mode_list);
mode_list->connect("pressed", this, "_set_display_mode", varray(DISPLAY_LIST));
- EDITOR_DEF("editors/grid_map/preview_size",64)
+ EDITOR_DEF("editors/grid_map/preview_size",64);
display_mode = DISPLAY_THUMBNAIL;
selected_area=-1;
@@ -1387,52 +1387,36 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
Array d;
d.resize(VS::ARRAY_MAX);
- inner_mat = VisualServer::get_singleton()->fixed_material_create();
- VisualServer::get_singleton()->fixed_material_set_param(inner_mat,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0.7,0.7,1.0,0.3));
- VisualServer::get_singleton()->material_set_flag(inner_mat,VS::MATERIAL_FLAG_ONTOP,true);
- VisualServer::get_singleton()->material_set_flag(inner_mat,VS::MATERIAL_FLAG_UNSHADED,true);
- VisualServer::get_singleton()->fixed_material_set_flag( inner_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true );
+ inner_mat.instance();
+ inner_mat->set_albedo(Color(0.7,0.7,1.0,0.3));
+ inner_mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true);
+ inner_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+ inner_mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
d[VS::ARRAY_VERTEX]=triangles;
- VisualServer::get_singleton()->mesh_add_surface(selection_mesh,VS::PRIMITIVE_TRIANGLES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh,0,inner_mat);
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh,VS::PRIMITIVE_TRIANGLES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh,0,inner_mat->get_rid());
- outer_mat = VisualServer::get_singleton()->fixed_material_create();
- VisualServer::get_singleton()->fixed_material_set_param(outer_mat,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0.7,0.7,1.0,0.8));
- VisualServer::get_singleton()->material_set_line_width(outer_mat,3.0);
- VisualServer::get_singleton()->material_set_flag(outer_mat,VS::MATERIAL_FLAG_ONTOP,true);
- VisualServer::get_singleton()->material_set_flag(outer_mat,VS::MATERIAL_FLAG_UNSHADED,true);
- VisualServer::get_singleton()->fixed_material_set_flag( outer_mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true );
+ outer_mat.instance();
+ outer_mat->set_albedo(Color(0.7,0.7,1.0,0.3));
+ outer_mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true);
+ outer_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
+ outer_mat->set_line_width(3.0);
+ outer_mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
d[VS::ARRAY_VERTEX]=lines;
- VisualServer::get_singleton()->mesh_add_surface(selection_mesh,VS::PRIMITIVE_LINES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh,1,outer_mat);
-
-
- inner_mat_dup = VisualServer::get_singleton()->fixed_material_create();
- VisualServer::get_singleton()->fixed_material_set_param(inner_mat_dup,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(1.0,0.7,0.7,0.3));
- VisualServer::get_singleton()->material_set_flag(inner_mat_dup,VS::MATERIAL_FLAG_ONTOP,true);
- VisualServer::get_singleton()->material_set_flag(inner_mat_dup,VS::MATERIAL_FLAG_UNSHADED,true);
- VisualServer::get_singleton()->fixed_material_set_flag( inner_mat_dup, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true );
-
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh,VS::PRIMITIVE_LINES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh,1,outer_mat->get_rid());
d[VS::ARRAY_VERTEX]=triangles;
- VisualServer::get_singleton()->mesh_add_surface(duplicate_mesh,VS::PRIMITIVE_TRIANGLES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh,0,inner_mat_dup);
-
- outer_mat_dup = VisualServer::get_singleton()->fixed_material_create();
- VisualServer::get_singleton()->fixed_material_set_param(outer_mat_dup,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(1.0,0.7,0.7,0.8));
- VisualServer::get_singleton()->material_set_line_width(outer_mat_dup,3.0);
- VisualServer::get_singleton()->material_set_flag(outer_mat_dup,VS::MATERIAL_FLAG_ONTOP,true);
- VisualServer::get_singleton()->material_set_flag(outer_mat_dup,VS::MATERIAL_FLAG_UNSHADED,true);
- VisualServer::get_singleton()->fixed_material_set_flag( outer_mat_dup, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA, true );
-
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(duplicate_mesh,VS::PRIMITIVE_TRIANGLES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh,0,inner_mat->get_rid());
d[VS::ARRAY_VERTEX]=lines;
- VisualServer::get_singleton()->mesh_add_surface(duplicate_mesh,VS::PRIMITIVE_LINES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh,1,outer_mat_dup);
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(duplicate_mesh,VS::PRIMITIVE_LINES,d);
+ VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh,1,outer_mat->get_rid());
}
@@ -1452,14 +1436,10 @@ GridMapEditor::~GridMapEditor() {
VisualServer::get_singleton()->free(grid[i]);
if (grid_instance[i].is_valid())
VisualServer::get_singleton()->free(grid_instance[i]);
- if (cursor_instance)
+ if (cursor_instance.is_valid())
VisualServer::get_singleton()->free(cursor_instance);
}
- VisualServer::get_singleton()->free(inner_mat);
- VisualServer::get_singleton()->free(outer_mat);
- VisualServer::get_singleton()->free(inner_mat_dup);
- VisualServer::get_singleton()->free(outer_mat_dup);
VisualServer::get_singleton()->free(selection_mesh);
if (selection_instance.is_valid())
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 2c0ff99dc6..07ac34cd4e 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -29,10 +29,10 @@
#ifndef GRID_MAP_EDITOR_PLUGIN_H
#define GRID_MAP_EDITOR_PLUGIN_H
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "editor/editor_node.h"
#include "grid_map.h"
-#include "tools/editor/pane_drag.h"
+#include "editor/pane_drag.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -112,12 +112,9 @@ class GridMapEditor : public VBoxContainer {
RID duplicate_mesh;
RID duplicate_instance;
- RID indicator_mat;
-
- RID inner_mat;
- RID outer_mat;
- RID inner_mat_dup;
- RID outer_mat_dup;
+ Ref<FixedSpatialMaterial> indicator_mat;
+ Ref<FixedSpatialMaterial> inner_mat;
+ Ref<FixedSpatialMaterial> outer_mat;
bool updating;
diff --git a/modules/openssl/stream_peer_openssl.h b/modules/openssl/stream_peer_openssl.h
index 3d6875698c..84ae03fe07 100644
--- a/modules/openssl/stream_peer_openssl.h
+++ b/modules/openssl/stream_peer_openssl.h
@@ -31,7 +31,7 @@
#include <stdio.h> // If you don't know what this is for stop reading now.
#include "io/stream_peer_ssl.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
#include "curl_hostcheck.h"
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index e67040b5a3..3d1dd048a8 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -321,7 +321,7 @@ struct RegExNodeClass : public RegExNode {
case Type_lower:
return ('a' <= c && c <= 'z');
case Type_print:
- return (0x1F < c && c < 0x1F);
+ return (0x20 < c && c < 0x7f);
case Type_punct:
return (REGEX_NODE_PUNCT.find(c) >= 0);
case Type_space:
@@ -1481,27 +1481,27 @@ RegEx::~RegEx() {
void RegExMatch::_bind_methods() {
- ClassDB::bind_method(_MD("expand","template"),&RegExMatch::expand);
- ClassDB::bind_method(_MD("get_group_count"),&RegExMatch::get_group_count);
- ClassDB::bind_method(_MD("get_group_array"),&RegExMatch::get_group_array);
- ClassDB::bind_method(_MD("get_names"),&RegExMatch::get_names);
- ClassDB::bind_method(_MD("get_name_dict"),&RegExMatch::get_name_dict);
- ClassDB::bind_method(_MD("get_string","name"),&RegExMatch::get_string, DEFVAL(0));
- ClassDB::bind_method(_MD("get_start","name"),&RegExMatch::get_start, DEFVAL(0));
- ClassDB::bind_method(_MD("get_end","name"),&RegExMatch::get_end, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("expand","template"),&RegExMatch::expand);
+ ClassDB::bind_method(D_METHOD("get_group_count"),&RegExMatch::get_group_count);
+ ClassDB::bind_method(D_METHOD("get_group_array"),&RegExMatch::get_group_array);
+ ClassDB::bind_method(D_METHOD("get_names"),&RegExMatch::get_names);
+ ClassDB::bind_method(D_METHOD("get_name_dict"),&RegExMatch::get_name_dict);
+ ClassDB::bind_method(D_METHOD("get_string","name"),&RegExMatch::get_string, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_start","name"),&RegExMatch::get_start, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_end","name"),&RegExMatch::get_end, DEFVAL(0));
}
void RegEx::_bind_methods() {
- ClassDB::bind_method(_MD("clear"),&RegEx::clear);
- ClassDB::bind_method(_MD("compile","pattern"),&RegEx::compile);
- ClassDB::bind_method(_MD("search","text","start","end"),&RegEx::search, DEFVAL(0), DEFVAL(-1));
- ClassDB::bind_method(_MD("sub","text","replacement","all","start","end"),&RegEx::sub, DEFVAL(false), DEFVAL(0), DEFVAL(-1));
- ClassDB::bind_method(_MD("is_valid"),&RegEx::is_valid);
- ClassDB::bind_method(_MD("get_pattern"),&RegEx::get_pattern);
- ClassDB::bind_method(_MD("get_group_count"),&RegEx::get_group_count);
- ClassDB::bind_method(_MD("get_names"),&RegEx::get_names);
+ ClassDB::bind_method(D_METHOD("clear"),&RegEx::clear);
+ ClassDB::bind_method(D_METHOD("compile","pattern"),&RegEx::compile);
+ ClassDB::bind_method(D_METHOD("search","text","start","end"),&RegEx::search, DEFVAL(0), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("sub","text","replacement","all","start","end"),&RegEx::sub, DEFVAL(false), DEFVAL(0), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("is_valid"),&RegEx::is_valid);
+ ClassDB::bind_method(D_METHOD("get_pattern"),&RegEx::get_pattern);
+ ClassDB::bind_method(D_METHOD("get_group_count"),&RegEx::get_group_count);
+ ClassDB::bind_method(D_METHOD("get_names"),&RegEx::get_names);
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "pattern"), _SCS("compile"), _SCS("get_pattern"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "pattern"), "compile", "get_pattern");
}
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
index 4b4c57fbdd..d3d7ab2307 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
@@ -1,5 +1,33 @@
-
+/*************************************************************************/
+/* audio_stream_ogg_vorbis.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_stream_ogg_vorbis.h"
+
#include "thirdparty/stb_vorbis/stb_vorbis.c"
#include "os/file_access.h"
@@ -205,14 +233,14 @@ bool AudioStreamOGGVorbis::has_loop() const {
void AudioStreamOGGVorbis::_bind_methods() {
- ClassDB::bind_method(_MD("set_data","data"),&AudioStreamOGGVorbis::set_data);
- ClassDB::bind_method(_MD("get_data"),&AudioStreamOGGVorbis::get_data);
+ ClassDB::bind_method(D_METHOD("set_data","data"),&AudioStreamOGGVorbis::set_data);
+ ClassDB::bind_method(D_METHOD("get_data"),&AudioStreamOGGVorbis::get_data);
- ClassDB::bind_method(_MD("set_loop","enable"),&AudioStreamOGGVorbis::set_loop);
- ClassDB::bind_method(_MD("has_loop"),&AudioStreamOGGVorbis::has_loop);
+ ClassDB::bind_method(D_METHOD("set_loop","enable"),&AudioStreamOGGVorbis::set_loop);
+ ClassDB::bind_method(D_METHOD("has_loop"),&AudioStreamOGGVorbis::has_loop);
- ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_data"),_SCS("get_data"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"loop",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_loop"),_SCS("has_loop"));
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_data","get_data");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"loop",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_loop","has_loop");
}
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
index 21ce23740c..2313fc4ae3 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_stream_ogg_vorbis.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIO_STREAM_STB_VORBIS_H
#define AUDIO_STREAM_STB_VORBIS_H
diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
index 6f90c8587b..03495652d4 100644
--- a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* resource_importer_ogg_vorbis.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "resource_importer_ogg_vorbis.h"
#include "io/resource_saver.h"
diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.h b/modules/stb_vorbis/resource_importer_ogg_vorbis.h
index 8a3b2d8ec6..15fc2cd2f3 100644
--- a/modules/stb_vorbis/resource_importer_ogg_vorbis.h
+++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* resource_importer_ogg_vorbis.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 RESOURCEIMPORTEROGGVORBIS_H
#define RESOURCEIMPORTEROGGVORBIS_H
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 9d2dfc7f56..2a7b2707bf 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "video_stream_theora.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
#include "yuv2rgb.h"
diff --git a/modules/theora/yuv2rgb.h b/modules/theora/yuv2rgb.h
index 3b81607a65..a9bef76da8 100644
--- a/modules/theora/yuv2rgb.h
+++ b/modules/theora/yuv2rgb.h
@@ -1,3 +1,6 @@
+/* Thirdparty code presumably from http://wss.co.uk/pinknoise/yuv2rgb/ */
+/* FIXME: Move to thirdparty dir */
+
#ifndef YUV2RGB_H
#define YUV2RGB_H
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index e1e180432a..9f742591d5 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -1,8 +1,37 @@
+/*************************************************************************/
+/* visual_script.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script.h"
+
#include "visual_script_nodes.h"
#include "scene/main/node.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
@@ -104,13 +133,13 @@ Array VisualScriptNode::_get_default_input_values() const {
void VisualScriptNode::_bind_methods() {
- ClassDB::bind_method(_MD("get_visual_script:VisualScript"),&VisualScriptNode::get_visual_script);
- ClassDB::bind_method(_MD("set_default_input_value","port_idx","value:Variant"),&VisualScriptNode::set_default_input_value);
- ClassDB::bind_method(_MD("get_default_input_value:Variant","port_idx"),&VisualScriptNode::get_default_input_value);
- ClassDB::bind_method(_MD("_set_default_input_values","values"),&VisualScriptNode::_set_default_input_values);
- ClassDB::bind_method(_MD("_get_default_input_values"),&VisualScriptNode::_get_default_input_values);
+ ClassDB::bind_method(D_METHOD("get_visual_script:VisualScript"),&VisualScriptNode::get_visual_script);
+ ClassDB::bind_method(D_METHOD("set_default_input_value","port_idx","value:Variant"),&VisualScriptNode::set_default_input_value);
+ ClassDB::bind_method(D_METHOD("get_default_input_value:Variant","port_idx"),&VisualScriptNode::get_default_input_value);
+ ClassDB::bind_method(D_METHOD("_set_default_input_values","values"),&VisualScriptNode::_set_default_input_values);
+ ClassDB::bind_method(D_METHOD("_get_default_input_values"),&VisualScriptNode::_get_default_input_values);
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"_default_input_values",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_default_input_values"),_SCS("_get_default_input_values"));
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"_default_input_values",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_default_input_values","_get_default_input_values");
ADD_SIGNAL(MethodInfo("ports_changed"));
}
@@ -1317,65 +1346,65 @@ void VisualScript::_bind_methods() {
- ClassDB::bind_method(_MD("_node_ports_changed"),&VisualScript::_node_ports_changed);
+ ClassDB::bind_method(D_METHOD("_node_ports_changed"),&VisualScript::_node_ports_changed);
- ClassDB::bind_method(_MD("add_function","name"),&VisualScript::add_function);
- ClassDB::bind_method(_MD("has_function","name"),&VisualScript::has_function);
- ClassDB::bind_method(_MD("remove_function","name"),&VisualScript::remove_function);
- ClassDB::bind_method(_MD("rename_function","name","new_name"),&VisualScript::rename_function);
- ClassDB::bind_method(_MD("set_function_scroll","ofs"),&VisualScript::set_function_scroll);
- ClassDB::bind_method(_MD("get_function_scroll"),&VisualScript::get_function_scroll);
+ ClassDB::bind_method(D_METHOD("add_function","name"),&VisualScript::add_function);
+ ClassDB::bind_method(D_METHOD("has_function","name"),&VisualScript::has_function);
+ ClassDB::bind_method(D_METHOD("remove_function","name"),&VisualScript::remove_function);
+ ClassDB::bind_method(D_METHOD("rename_function","name","new_name"),&VisualScript::rename_function);
+ ClassDB::bind_method(D_METHOD("set_function_scroll","ofs"),&VisualScript::set_function_scroll);
+ ClassDB::bind_method(D_METHOD("get_function_scroll"),&VisualScript::get_function_scroll);
- ClassDB::bind_method(_MD("add_node","func","id","node","pos"),&VisualScript::add_node,DEFVAL(Point2()));
- ClassDB::bind_method(_MD("remove_node","func","id"),&VisualScript::remove_node);
- ClassDB::bind_method(_MD("get_function_node_id","name"),&VisualScript::get_function_node_id);
+ ClassDB::bind_method(D_METHOD("add_node","func","id","node","pos"),&VisualScript::add_node,DEFVAL(Point2()));
+ ClassDB::bind_method(D_METHOD("remove_node","func","id"),&VisualScript::remove_node);
+ ClassDB::bind_method(D_METHOD("get_function_node_id","name"),&VisualScript::get_function_node_id);
- ClassDB::bind_method(_MD("get_node","func","id"),&VisualScript::get_node);
- ClassDB::bind_method(_MD("has_node","func","id"),&VisualScript::has_node);
- ClassDB::bind_method(_MD("set_node_pos","func","id","pos"),&VisualScript::set_node_pos);
- ClassDB::bind_method(_MD("get_node_pos","func","id"),&VisualScript::get_node_pos);
+ ClassDB::bind_method(D_METHOD("get_node","func","id"),&VisualScript::get_node);
+ ClassDB::bind_method(D_METHOD("has_node","func","id"),&VisualScript::has_node);
+ ClassDB::bind_method(D_METHOD("set_node_pos","func","id","pos"),&VisualScript::set_node_pos);
+ ClassDB::bind_method(D_METHOD("get_node_pos","func","id"),&VisualScript::get_node_pos);
- ClassDB::bind_method(_MD("sequence_connect","func","from_node","from_output","to_node"),&VisualScript::sequence_connect);
- ClassDB::bind_method(_MD("sequence_disconnect","func","from_node","from_output","to_node"),&VisualScript::sequence_disconnect);
- ClassDB::bind_method(_MD("has_sequence_connection","func","from_node","from_output","to_node"),&VisualScript::has_sequence_connection);
+ ClassDB::bind_method(D_METHOD("sequence_connect","func","from_node","from_output","to_node"),&VisualScript::sequence_connect);
+ ClassDB::bind_method(D_METHOD("sequence_disconnect","func","from_node","from_output","to_node"),&VisualScript::sequence_disconnect);
+ ClassDB::bind_method(D_METHOD("has_sequence_connection","func","from_node","from_output","to_node"),&VisualScript::has_sequence_connection);
- ClassDB::bind_method(_MD("data_connect","func","from_node","from_port","to_node","to_port"),&VisualScript::data_connect);
- ClassDB::bind_method(_MD("data_disconnect","func","from_node","from_port","to_node","to_port"),&VisualScript::data_disconnect);
- ClassDB::bind_method(_MD("has_data_connection","func","from_node","from_port","to_node","to_port"),&VisualScript::has_data_connection);
+ ClassDB::bind_method(D_METHOD("data_connect","func","from_node","from_port","to_node","to_port"),&VisualScript::data_connect);
+ ClassDB::bind_method(D_METHOD("data_disconnect","func","from_node","from_port","to_node","to_port"),&VisualScript::data_disconnect);
+ ClassDB::bind_method(D_METHOD("has_data_connection","func","from_node","from_port","to_node","to_port"),&VisualScript::has_data_connection);
- ClassDB::bind_method(_MD("add_variable","name","default_value","export"),&VisualScript::add_variable,DEFVAL(Variant()),DEFVAL(false));
- ClassDB::bind_method(_MD("has_variable","name"),&VisualScript::has_variable);
- ClassDB::bind_method(_MD("remove_variable","name"),&VisualScript::remove_variable);
- ClassDB::bind_method(_MD("set_variable_default_value","name","value"),&VisualScript::set_variable_default_value);
- ClassDB::bind_method(_MD("get_variable_default_value","name"),&VisualScript::get_variable_default_value);
- ClassDB::bind_method(_MD("set_variable_info","name","value"),&VisualScript::_set_variable_info);
- ClassDB::bind_method(_MD("get_variable_info","name"),&VisualScript::_get_variable_info);
- ClassDB::bind_method(_MD("set_variable_export","name","enable"),&VisualScript::set_variable_export);
- ClassDB::bind_method(_MD("get_variable_export","name"),&VisualScript::get_variable_export);
- ClassDB::bind_method(_MD("rename_variable","name","new_name"),&VisualScript::rename_variable);
+ ClassDB::bind_method(D_METHOD("add_variable","name","default_value","export"),&VisualScript::add_variable,DEFVAL(Variant()),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("has_variable","name"),&VisualScript::has_variable);
+ ClassDB::bind_method(D_METHOD("remove_variable","name"),&VisualScript::remove_variable);
+ ClassDB::bind_method(D_METHOD("set_variable_default_value","name","value"),&VisualScript::set_variable_default_value);
+ ClassDB::bind_method(D_METHOD("get_variable_default_value","name"),&VisualScript::get_variable_default_value);
+ ClassDB::bind_method(D_METHOD("set_variable_info","name","value"),&VisualScript::_set_variable_info);
+ ClassDB::bind_method(D_METHOD("get_variable_info","name"),&VisualScript::_get_variable_info);
+ ClassDB::bind_method(D_METHOD("set_variable_export","name","enable"),&VisualScript::set_variable_export);
+ ClassDB::bind_method(D_METHOD("get_variable_export","name"),&VisualScript::get_variable_export);
+ ClassDB::bind_method(D_METHOD("rename_variable","name","new_name"),&VisualScript::rename_variable);
- ClassDB::bind_method(_MD("add_custom_signal","name"),&VisualScript::add_custom_signal);
- ClassDB::bind_method(_MD("has_custom_signal","name"),&VisualScript::has_custom_signal);
- ClassDB::bind_method(_MD("custom_signal_add_argument","name","type","argname","index"),&VisualScript::custom_signal_add_argument,DEFVAL(-1));
- ClassDB::bind_method(_MD("custom_signal_set_argument_type","name","argidx","type"),&VisualScript::custom_signal_set_argument_type);
- ClassDB::bind_method(_MD("custom_signal_get_argument_type","name","argidx"),&VisualScript::custom_signal_get_argument_type);
- ClassDB::bind_method(_MD("custom_signal_set_argument_name","name","argidx","argname"),&VisualScript::custom_signal_set_argument_name);
- ClassDB::bind_method(_MD("custom_signal_get_argument_name","name","argidx"),&VisualScript::custom_signal_get_argument_name);
- ClassDB::bind_method(_MD("custom_signal_remove_argument","argidx"),&VisualScript::custom_signal_remove_argument);
- ClassDB::bind_method(_MD("custom_signal_get_argument_count","name"),&VisualScript::custom_signal_get_argument_count);
- ClassDB::bind_method(_MD("custom_signal_swap_argument","name","argidx","withidx"),&VisualScript::custom_signal_swap_argument);
- ClassDB::bind_method(_MD("remove_custom_signal","name"),&VisualScript::remove_custom_signal);
- ClassDB::bind_method(_MD("rename_custom_signal","name","new_name"),&VisualScript::rename_custom_signal);
+ ClassDB::bind_method(D_METHOD("add_custom_signal","name"),&VisualScript::add_custom_signal);
+ ClassDB::bind_method(D_METHOD("has_custom_signal","name"),&VisualScript::has_custom_signal);
+ ClassDB::bind_method(D_METHOD("custom_signal_add_argument","name","type","argname","index"),&VisualScript::custom_signal_add_argument,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("custom_signal_set_argument_type","name","argidx","type"),&VisualScript::custom_signal_set_argument_type);
+ ClassDB::bind_method(D_METHOD("custom_signal_get_argument_type","name","argidx"),&VisualScript::custom_signal_get_argument_type);
+ ClassDB::bind_method(D_METHOD("custom_signal_set_argument_name","name","argidx","argname"),&VisualScript::custom_signal_set_argument_name);
+ ClassDB::bind_method(D_METHOD("custom_signal_get_argument_name","name","argidx"),&VisualScript::custom_signal_get_argument_name);
+ ClassDB::bind_method(D_METHOD("custom_signal_remove_argument","argidx"),&VisualScript::custom_signal_remove_argument);
+ ClassDB::bind_method(D_METHOD("custom_signal_get_argument_count","name"),&VisualScript::custom_signal_get_argument_count);
+ ClassDB::bind_method(D_METHOD("custom_signal_swap_argument","name","argidx","withidx"),&VisualScript::custom_signal_swap_argument);
+ ClassDB::bind_method(D_METHOD("remove_custom_signal","name"),&VisualScript::remove_custom_signal);
+ ClassDB::bind_method(D_METHOD("rename_custom_signal","name","new_name"),&VisualScript::rename_custom_signal);
- //ClassDB::bind_method(_MD("set_variable_info","name","info"),&VScript::set_variable_info);
- //ClassDB::bind_method(_MD("get_variable_info","name"),&VScript::set_variable_info);
+ //ClassDB::bind_method(D_METHOD("set_variable_info","name","info"),&VScript::set_variable_info);
+ //ClassDB::bind_method(D_METHOD("get_variable_info","name"),&VScript::set_variable_info);
- ClassDB::bind_method(_MD("set_instance_base_type","type"),&VisualScript::set_instance_base_type);
+ ClassDB::bind_method(D_METHOD("set_instance_base_type","type"),&VisualScript::set_instance_base_type);
- ClassDB::bind_method(_MD("_set_data","data"),&VisualScript::_set_data);
- ClassDB::bind_method(_MD("_get_data"),&VisualScript::_get_data);
+ ClassDB::bind_method(D_METHOD("_set_data","data"),&VisualScript::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"),&VisualScript::_get_data);
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_data"),_SCS("_get_data"));
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_data","_get_data");
ADD_SIGNAL(MethodInfo("node_ports_changed",PropertyInfo(Variant::STRING,"function"),PropertyInfo(Variant::INT,"id")));
}
@@ -2436,9 +2465,9 @@ Variant VisualScriptFunctionState::resume(Array p_args) {
void VisualScriptFunctionState::_bind_methods() {
- ClassDB::bind_method(_MD("connect_to_signal","obj","signals","args"),&VisualScriptFunctionState::connect_to_signal);
- ClassDB::bind_method(_MD("resume:Array","args"),&VisualScriptFunctionState::resume,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("is_valid"),&VisualScriptFunctionState::is_valid);
+ ClassDB::bind_method(D_METHOD("connect_to_signal","obj","signals","args"),&VisualScriptFunctionState::connect_to_signal);
+ ClassDB::bind_method(D_METHOD("resume:Array","args"),&VisualScriptFunctionState::resume,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("is_valid"),&VisualScriptFunctionState::is_valid);
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"_signal_callback",&VisualScriptFunctionState::_signal_callback,MethodInfo("_signal_callback"));
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index acd1c3a670..ef73a89048 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VSCRIPT_H
#define VSCRIPT_H
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index a0f23a511f..e83cd3e614 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* visual_script_builtin_funcs.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script_builtin_funcs.h"
+
#include "math_funcs.h"
#include "class_db.h"
#include "reference.h"
@@ -329,7 +358,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
case LOGIC_CLAMP: {
if (p_idx==0)
return PropertyInfo(Variant::REAL,"a");
- else if (p_idx==0)
+ else if (p_idx==0) // FIXME: is it ok to test p_idx == 0 twice?
return PropertyInfo(Variant::REAL,"min");
else
return PropertyInfo(Variant::REAL,"max");
@@ -1166,8 +1195,8 @@ VisualScriptNodeInstance* VisualScriptBuiltinFunc::instance(VisualScriptInstance
void VisualScriptBuiltinFunc::_bind_methods() {
- ClassDB::bind_method(_MD("set_func","which"),&VisualScriptBuiltinFunc::set_func);
- ClassDB::bind_method(_MD("get_func"),&VisualScriptBuiltinFunc::get_func);
+ ClassDB::bind_method(D_METHOD("set_func","which"),&VisualScriptBuiltinFunc::set_func);
+ ClassDB::bind_method(D_METHOD("get_func"),&VisualScriptBuiltinFunc::get_func);
String cc;
@@ -1177,7 +1206,7 @@ void VisualScriptBuiltinFunc::_bind_methods() {
cc+=",";
cc+=func_name[i];
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"function",PROPERTY_HINT_ENUM,cc),_SCS("set_func"),_SCS("get_func"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"function",PROPERTY_HINT_ENUM,cc),"set_func","get_func");
}
VisualScriptBuiltinFunc::VisualScriptBuiltinFunc() {
diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h
index a285517c7e..75bea4b1b5 100644
--- a/modules/visual_script/visual_script_builtin_funcs.h
+++ b/modules/visual_script/visual_script_builtin_funcs.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script_builtin_funcs.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUAL_SCRIPT_BUILTIN_FUNCS_H
#define VISUAL_SCRIPT_BUILTIN_FUNCS_H
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index eadc9a8892..7dd7059c31 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -1,11 +1,40 @@
+/*************************************************************************/
+/* visual_script_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script_editor.h"
-#include "tools/editor/editor_node.h"
+
+#include "editor/editor_node.h"
#include "visual_script_nodes.h"
#include "visual_script_flow_control.h"
#include "visual_script_func_nodes.h"
#include "visual_script_expression.h"
#include "os/input.h"
-#include "tools/editor/editor_resource_preview.h"
+#include "editor/editor_resource_preview.h"
#include "os/keyboard.h"
#ifdef TOOLS_ENABLED
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index 1dc62b3e69..cdaef8d0ce 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -1,12 +1,40 @@
-#ifndef VisualSCRIPT_EDITOR_H
-#define VisualSCRIPT_EDITOR_H
-
-#include "tools/editor/plugins/script_editor_plugin.h"
+/*************************************************************************/
+/* visual_script_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUALSCRIPT_EDITOR_H
+#define VISUALSCRIPT_EDITOR_H
+
+#include "editor/plugins/script_editor_plugin.h"
#include "visual_script.h"
-#include "tools/editor/property_editor.h"
+#include "editor/property_editor.h"
#include "scene/gui/graph_edit.h"
-#include "tools/editor/create_dialog.h"
-#include "tools/editor/property_selector.h"
+#include "editor/create_dialog.h"
+#include "editor/property_selector.h"
class VisualScriptEditorSignalEdit;
class VisualScriptEditorVariableEdit;
@@ -241,4 +269,4 @@ public:
};
#endif
-#endif // VisualSCRIPT_EDITOR_H
+#endif // VISUALSCRIPT_EDITOR_H
diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp
index cc3b5f2174..3d15e696ef 100644
--- a/modules/visual_script/visual_script_expression.cpp
+++ b/modules/visual_script/visual_script_expression.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script_expression.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script_expression.h"
@@ -558,6 +586,12 @@ Error VisualScriptExpression::_get_token(Token& r_token) {
} else if (id=="PI") {
r_token.type=TK_CONSTANT;
r_token.value=Math_PI;
+ } else if (id == "INF") {
+ r_token.type = TK_CONSTANT;
+ r_token.value = Math_INF;
+ } else if (id == "NAN") {
+ r_token.type = TK_CONSTANT;
+ r_token.value = Math_NAN;
} else if (id=="not") {
r_token.type=TK_OP_NOT;
} else if (id=="or") {
diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h
index a67656a4b1..5bd960f60c 100644
--- a/modules/visual_script/visual_script_expression.h
+++ b/modules/visual_script/visual_script_expression.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script_expression.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUALSCRIPTEXPRESSION_H
#define VISUALSCRIPTEXPRESSION_H
diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp
index 0e526f8a42..8aff96b70c 100644
--- a/modules/visual_script/visual_script_flow_control.cpp
+++ b/modules/visual_script/visual_script_flow_control.cpp
@@ -1,6 +1,35 @@
+/*************************************************************************/
+/* visual_script_flow_control.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script_flow_control.h"
+
#include "os/keyboard.h"
-#include "globals.h"
+#include "global_config.h"
//////////////////////////////////////////
@@ -81,18 +110,18 @@ bool VisualScriptReturn::is_return_value_enabled() const {
void VisualScriptReturn::_bind_methods() {
- ClassDB::bind_method(_MD("set_return_type","type"),&VisualScriptReturn::set_return_type);
- ClassDB::bind_method(_MD("get_return_type"),&VisualScriptReturn::get_return_type);
- ClassDB::bind_method(_MD("set_enable_return_value","enable"),&VisualScriptReturn::set_enable_return_value);
- ClassDB::bind_method(_MD("is_return_value_enabled"),&VisualScriptReturn::is_return_value_enabled);
+ ClassDB::bind_method(D_METHOD("set_return_type","type"),&VisualScriptReturn::set_return_type);
+ ClassDB::bind_method(D_METHOD("get_return_type"),&VisualScriptReturn::get_return_type);
+ ClassDB::bind_method(D_METHOD("set_enable_return_value","enable"),&VisualScriptReturn::set_enable_return_value);
+ ClassDB::bind_method(D_METHOD("is_return_value_enabled"),&VisualScriptReturn::is_return_value_enabled);
String argt="Any";
for(int i=1;i<Variant::VARIANT_MAX;i++) {
argt+=","+Variant::get_type_name(Variant::Type(i));
}
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"return_value/enabled"),_SCS("set_enable_return_value"),_SCS("is_return_value_enabled"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"return_value/type",PROPERTY_HINT_ENUM,argt),_SCS("set_return_type"),_SCS("get_return_type"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"return_value/enabled"),"set_enable_return_value","is_return_value_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"return_value/type",PROPERTY_HINT_ENUM,argt),"set_return_type","get_return_type");
}
@@ -544,10 +573,10 @@ int VisualScriptSequence::get_steps() const {
void VisualScriptSequence::_bind_methods() {
- ClassDB::bind_method(_MD("set_steps","steps"),&VisualScriptSequence::set_steps);
- ClassDB::bind_method(_MD("get_steps"),&VisualScriptSequence::get_steps);
+ ClassDB::bind_method(D_METHOD("set_steps","steps"),&VisualScriptSequence::set_steps);
+ ClassDB::bind_method(D_METHOD("get_steps"),&VisualScriptSequence::get_steps);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"steps",PROPERTY_HINT_RANGE,"1,64,1"),_SCS("set_steps"),_SCS("get_steps"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"steps",PROPERTY_HINT_RANGE,"1,64,1"),"set_steps","get_steps");
}
@@ -1893,11 +1922,11 @@ VisualScriptNodeInstance* VisualScriptTypeCast::instance(VisualScriptInstance* p
void VisualScriptTypeCast::_bind_methods() {
- ClassDB::bind_method(_MD("set_base_type","type"),&VisualScriptTypeCast::set_base_type);
- ClassDB::bind_method(_MD("get_base_type"),&VisualScriptTypeCast::get_base_type);
+ ClassDB::bind_method(D_METHOD("set_base_type","type"),&VisualScriptTypeCast::set_base_type);
+ ClassDB::bind_method(D_METHOD("get_base_type"),&VisualScriptTypeCast::get_base_type);
- ClassDB::bind_method(_MD("set_base_script","path"),&VisualScriptTypeCast::set_base_script);
- ClassDB::bind_method(_MD("get_base_script"),&VisualScriptTypeCast::get_base_script);
+ ClassDB::bind_method(D_METHOD("set_base_script","path"),&VisualScriptTypeCast::set_base_script);
+ ClassDB::bind_method(D_METHOD("get_base_script"),&VisualScriptTypeCast::get_base_script);
List<String> script_extensions;
@@ -1912,8 +1941,8 @@ void VisualScriptTypeCast::_bind_methods() {
script_ext_hint+="*."+E->get();
}
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),"set_base_type","get_base_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),"set_base_script","get_base_script");
}
diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h
index 26e981cb1e..8406bb5a5b 100644
--- a/modules/visual_script/visual_script_flow_control.h
+++ b/modules/visual_script/visual_script_flow_control.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script_flow_control.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUAL_SCRIPT_FLOW_CONTROL_H
#define VISUAL_SCRIPT_FLOW_CONTROL_H
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index a8d78b9298..c9ed49ee5c 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -1,10 +1,39 @@
+/*************************************************************************/
+/* visual_script_func_nodes.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script_func_nodes.h"
+
#include "scene/main/scene_main_loop.h"
#include "os/os.h"
#include "scene/main/node.h"
#include "visual_script_nodes.h"
#include "io/resource_loader.h"
-#include "globals.h"
+#include "global_config.h"
//////////////////////////////////////////
////////////////CALL//////////////////////
@@ -687,38 +716,38 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo& property) const
void VisualScriptFunctionCall::_bind_methods() {
- ClassDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptFunctionCall::set_base_type);
- ClassDB::bind_method(_MD("get_base_type"),&VisualScriptFunctionCall::get_base_type);
+ ClassDB::bind_method(D_METHOD("set_base_type","base_type"),&VisualScriptFunctionCall::set_base_type);
+ ClassDB::bind_method(D_METHOD("get_base_type"),&VisualScriptFunctionCall::get_base_type);
- ClassDB::bind_method(_MD("set_base_script","base_script"),&VisualScriptFunctionCall::set_base_script);
- ClassDB::bind_method(_MD("get_base_script"),&VisualScriptFunctionCall::get_base_script);
+ ClassDB::bind_method(D_METHOD("set_base_script","base_script"),&VisualScriptFunctionCall::set_base_script);
+ ClassDB::bind_method(D_METHOD("get_base_script"),&VisualScriptFunctionCall::get_base_script);
- ClassDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptFunctionCall::set_basic_type);
- ClassDB::bind_method(_MD("get_basic_type"),&VisualScriptFunctionCall::get_basic_type);
+ ClassDB::bind_method(D_METHOD("set_basic_type","basic_type"),&VisualScriptFunctionCall::set_basic_type);
+ ClassDB::bind_method(D_METHOD("get_basic_type"),&VisualScriptFunctionCall::get_basic_type);
- ClassDB::bind_method(_MD("set_singleton","singleton"),&VisualScriptFunctionCall::set_singleton);
- ClassDB::bind_method(_MD("get_singleton"),&VisualScriptFunctionCall::get_singleton);
+ ClassDB::bind_method(D_METHOD("set_singleton","singleton"),&VisualScriptFunctionCall::set_singleton);
+ ClassDB::bind_method(D_METHOD("get_singleton"),&VisualScriptFunctionCall::get_singleton);
- ClassDB::bind_method(_MD("set_function","function"),&VisualScriptFunctionCall::set_function);
- ClassDB::bind_method(_MD("get_function"),&VisualScriptFunctionCall::get_function);
+ ClassDB::bind_method(D_METHOD("set_function","function"),&VisualScriptFunctionCall::set_function);
+ ClassDB::bind_method(D_METHOD("get_function"),&VisualScriptFunctionCall::get_function);
- ClassDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptFunctionCall::set_call_mode);
- ClassDB::bind_method(_MD("get_call_mode"),&VisualScriptFunctionCall::get_call_mode);
+ ClassDB::bind_method(D_METHOD("set_call_mode","mode"),&VisualScriptFunctionCall::set_call_mode);
+ ClassDB::bind_method(D_METHOD("get_call_mode"),&VisualScriptFunctionCall::get_call_mode);
- ClassDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptFunctionCall::set_base_path);
- ClassDB::bind_method(_MD("get_base_path"),&VisualScriptFunctionCall::get_base_path);
+ ClassDB::bind_method(D_METHOD("set_base_path","base_path"),&VisualScriptFunctionCall::set_base_path);
+ ClassDB::bind_method(D_METHOD("get_base_path"),&VisualScriptFunctionCall::get_base_path);
- ClassDB::bind_method(_MD("set_use_default_args","amount"),&VisualScriptFunctionCall::set_use_default_args);
- ClassDB::bind_method(_MD("get_use_default_args"),&VisualScriptFunctionCall::get_use_default_args);
+ ClassDB::bind_method(D_METHOD("set_use_default_args","amount"),&VisualScriptFunctionCall::set_use_default_args);
+ ClassDB::bind_method(D_METHOD("get_use_default_args"),&VisualScriptFunctionCall::get_use_default_args);
- ClassDB::bind_method(_MD("_set_argument_cache","argument_cache"),&VisualScriptFunctionCall::_set_argument_cache);
- ClassDB::bind_method(_MD("_get_argument_cache"),&VisualScriptFunctionCall::_get_argument_cache);
+ ClassDB::bind_method(D_METHOD("_set_argument_cache","argument_cache"),&VisualScriptFunctionCall::_set_argument_cache);
+ ClassDB::bind_method(D_METHOD("_get_argument_cache"),&VisualScriptFunctionCall::_get_argument_cache);
- ClassDB::bind_method(_MD("set_rpc_call_mode","mode"),&VisualScriptFunctionCall::set_rpc_call_mode);
- ClassDB::bind_method(_MD("get_rpc_call_mode"),&VisualScriptFunctionCall::get_rpc_call_mode);
+ ClassDB::bind_method(D_METHOD("set_rpc_call_mode","mode"),&VisualScriptFunctionCall::set_rpc_call_mode);
+ ClassDB::bind_method(D_METHOD("get_rpc_call_mode"),&VisualScriptFunctionCall::get_rpc_call_mode);
- ClassDB::bind_method(_MD("set_validate","enable"),&VisualScriptFunctionCall::set_validate);
- ClassDB::bind_method(_MD("get_validate"),&VisualScriptFunctionCall::get_validate);
+ ClassDB::bind_method(D_METHOD("set_validate","enable"),&VisualScriptFunctionCall::set_validate);
+ ClassDB::bind_method(D_METHOD("get_validate"),&VisualScriptFunctionCall::get_validate);
String bt;
for(int i=0;i<Variant::VARIANT_MAX;i++) {
@@ -743,17 +772,17 @@ void VisualScriptFunctionCall::_bind_methods() {
- ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type,Singleton"),_SCS("set_call_mode"),_SCS("get_call_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/singleton"),_SCS("set_singleton"),_SCS("get_singleton"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"function/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"function/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"function/argument_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_argument_cache"),_SCS("_get_argument_cache"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/function"),_SCS("set_function"),_SCS("get_function")); //when set, if loaded properly, will override argument count.
- ADD_PROPERTY(PropertyInfo(Variant::INT,"function/use_default_args"),_SCS("set_use_default_args"),_SCS("get_use_default_args"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"function/validate"),_SCS("set_validate"),_SCS("get_validate"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"rpc/call_mode",PROPERTY_HINT_ENUM,"Disabled,Reliable,Unreliable,ReliableToID,UnreliableToID"),_SCS("set_rpc_call_mode"),_SCS("get_rpc_call_mode")); //when set, if loaded properly, will override argument count.
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"function/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type,Singleton"),"set_call_mode","get_call_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),"set_base_type","get_base_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/base_script",PROPERTY_HINT_FILE,script_ext_hint),"set_base_script","get_base_script");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/singleton"),"set_singleton","get_singleton");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"function/basic_type",PROPERTY_HINT_ENUM,bt),"set_basic_type","get_basic_type");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"function/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),"set_base_path","get_base_path");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"function/argument_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_argument_cache","_get_argument_cache");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"function/function"),"set_function","get_function"); //when set, if loaded properly, will override argument count.
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"function/use_default_args"),"set_use_default_args","get_use_default_args");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"function/validate"),"set_validate","get_validate");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"rpc/call_mode",PROPERTY_HINT_ENUM,"Disabled,Reliable,Unreliable,ReliableToID,UnreliableToID"),"set_rpc_call_mode","get_rpc_call_mode"); //when set, if loaded properly, will override argument count.
BIND_CONSTANT( CALL_MODE_SELF );
BIND_CONSTANT( CALL_MODE_NODE_PATH);
@@ -1453,29 +1482,29 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo& property) const {
void VisualScriptPropertySet::_bind_methods() {
- ClassDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptPropertySet::set_base_type);
- ClassDB::bind_method(_MD("get_base_type"),&VisualScriptPropertySet::get_base_type);
+ ClassDB::bind_method(D_METHOD("set_base_type","base_type"),&VisualScriptPropertySet::set_base_type);
+ ClassDB::bind_method(D_METHOD("get_base_type"),&VisualScriptPropertySet::get_base_type);
- ClassDB::bind_method(_MD("set_base_script","base_script"),&VisualScriptPropertySet::set_base_script);
- ClassDB::bind_method(_MD("get_base_script"),&VisualScriptPropertySet::get_base_script);
+ ClassDB::bind_method(D_METHOD("set_base_script","base_script"),&VisualScriptPropertySet::set_base_script);
+ ClassDB::bind_method(D_METHOD("get_base_script"),&VisualScriptPropertySet::get_base_script);
- ClassDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertySet::set_basic_type);
- ClassDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertySet::get_basic_type);
+ ClassDB::bind_method(D_METHOD("set_basic_type","basic_type"),&VisualScriptPropertySet::set_basic_type);
+ ClassDB::bind_method(D_METHOD("get_basic_type"),&VisualScriptPropertySet::get_basic_type);
- ClassDB::bind_method(_MD("_set_type_cache","type_cache"),&VisualScriptPropertySet::_set_type_cache);
- ClassDB::bind_method(_MD("_get_type_cache"),&VisualScriptPropertySet::_get_type_cache);
+ ClassDB::bind_method(D_METHOD("_set_type_cache","type_cache"),&VisualScriptPropertySet::_set_type_cache);
+ ClassDB::bind_method(D_METHOD("_get_type_cache"),&VisualScriptPropertySet::_get_type_cache);
- ClassDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertySet::set_event_type);
- ClassDB::bind_method(_MD("get_event_type"),&VisualScriptPropertySet::get_event_type);
+ ClassDB::bind_method(D_METHOD("set_event_type","event_type"),&VisualScriptPropertySet::set_event_type);
+ ClassDB::bind_method(D_METHOD("get_event_type"),&VisualScriptPropertySet::get_event_type);
- ClassDB::bind_method(_MD("set_property","property"),&VisualScriptPropertySet::set_property);
- ClassDB::bind_method(_MD("get_property"),&VisualScriptPropertySet::get_property);
+ ClassDB::bind_method(D_METHOD("set_property","property"),&VisualScriptPropertySet::set_property);
+ ClassDB::bind_method(D_METHOD("get_property"),&VisualScriptPropertySet::get_property);
- ClassDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptPropertySet::set_call_mode);
- ClassDB::bind_method(_MD("get_call_mode"),&VisualScriptPropertySet::get_call_mode);
+ ClassDB::bind_method(D_METHOD("set_call_mode","mode"),&VisualScriptPropertySet::set_call_mode);
+ ClassDB::bind_method(D_METHOD("get_call_mode"),&VisualScriptPropertySet::get_call_mode);
- ClassDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptPropertySet::set_base_path);
- ClassDB::bind_method(_MD("get_base_path"),&VisualScriptPropertySet::get_base_path);
+ ClassDB::bind_method(D_METHOD("set_base_path","base_path"),&VisualScriptPropertySet::set_base_path);
+ ClassDB::bind_method(D_METHOD("get_base_path"),&VisualScriptPropertySet::get_base_path);
@@ -1507,14 +1536,14 @@ void VisualScriptPropertySet::_bind_methods() {
script_ext_hint+="*."+E->get();
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),_SCS("set_call_mode"),_SCS("get_call_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/type_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_type_cache"),_SCS("_get_type_cache"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type"));
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),"set_call_mode","get_call_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),"set_base_type","get_base_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),"set_base_script","get_base_script");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/type_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_type_cache","_get_type_cache");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),"set_basic_type","get_basic_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),"set_event_type","get_event_type");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),"set_base_path","get_base_path");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),"set_property","get_property");
BIND_CONSTANT( CALL_MODE_SELF );
BIND_CONSTANT( CALL_MODE_NODE_PATH);
@@ -2117,30 +2146,30 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo& property) const {
void VisualScriptPropertyGet::_bind_methods() {
- ClassDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptPropertyGet::set_base_type);
- ClassDB::bind_method(_MD("get_base_type"),&VisualScriptPropertyGet::get_base_type);
+ ClassDB::bind_method(D_METHOD("set_base_type","base_type"),&VisualScriptPropertyGet::set_base_type);
+ ClassDB::bind_method(D_METHOD("get_base_type"),&VisualScriptPropertyGet::get_base_type);
- ClassDB::bind_method(_MD("set_base_script","base_script"),&VisualScriptPropertyGet::set_base_script);
- ClassDB::bind_method(_MD("get_base_script"),&VisualScriptPropertyGet::get_base_script);
+ ClassDB::bind_method(D_METHOD("set_base_script","base_script"),&VisualScriptPropertyGet::set_base_script);
+ ClassDB::bind_method(D_METHOD("get_base_script"),&VisualScriptPropertyGet::get_base_script);
- ClassDB::bind_method(_MD("set_basic_type","basic_type"),&VisualScriptPropertyGet::set_basic_type);
- ClassDB::bind_method(_MD("get_basic_type"),&VisualScriptPropertyGet::get_basic_type);
+ ClassDB::bind_method(D_METHOD("set_basic_type","basic_type"),&VisualScriptPropertyGet::set_basic_type);
+ ClassDB::bind_method(D_METHOD("get_basic_type"),&VisualScriptPropertyGet::get_basic_type);
- ClassDB::bind_method(_MD("_set_type_cache","type_cache"),&VisualScriptPropertyGet::_set_type_cache);
- ClassDB::bind_method(_MD("_get_type_cache"),&VisualScriptPropertyGet::_get_type_cache);
+ ClassDB::bind_method(D_METHOD("_set_type_cache","type_cache"),&VisualScriptPropertyGet::_set_type_cache);
+ ClassDB::bind_method(D_METHOD("_get_type_cache"),&VisualScriptPropertyGet::_get_type_cache);
- ClassDB::bind_method(_MD("set_event_type","event_type"),&VisualScriptPropertyGet::set_event_type);
- ClassDB::bind_method(_MD("get_event_type"),&VisualScriptPropertyGet::get_event_type);
+ ClassDB::bind_method(D_METHOD("set_event_type","event_type"),&VisualScriptPropertyGet::set_event_type);
+ ClassDB::bind_method(D_METHOD("get_event_type"),&VisualScriptPropertyGet::get_event_type);
- ClassDB::bind_method(_MD("set_property","property"),&VisualScriptPropertyGet::set_property);
- ClassDB::bind_method(_MD("get_property"),&VisualScriptPropertyGet::get_property);
+ ClassDB::bind_method(D_METHOD("set_property","property"),&VisualScriptPropertyGet::set_property);
+ ClassDB::bind_method(D_METHOD("get_property"),&VisualScriptPropertyGet::get_property);
- ClassDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptPropertyGet::set_call_mode);
- ClassDB::bind_method(_MD("get_call_mode"),&VisualScriptPropertyGet::get_call_mode);
+ ClassDB::bind_method(D_METHOD("set_call_mode","mode"),&VisualScriptPropertyGet::set_call_mode);
+ ClassDB::bind_method(D_METHOD("get_call_mode"),&VisualScriptPropertyGet::get_call_mode);
- ClassDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptPropertyGet::set_base_path);
- ClassDB::bind_method(_MD("get_base_path"),&VisualScriptPropertyGet::get_base_path);
+ ClassDB::bind_method(D_METHOD("set_base_path","base_path"),&VisualScriptPropertyGet::set_base_path);
+ ClassDB::bind_method(D_METHOD("get_base_path"),&VisualScriptPropertyGet::get_base_path);
String bt;
for(int i=0;i<Variant::VARIANT_MAX;i++) {
@@ -2170,14 +2199,14 @@ void VisualScriptPropertyGet::_bind_methods() {
script_ext_hint+="."+E->get();
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),_SCS("set_call_mode"),_SCS("get_call_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),_SCS("set_base_script"),_SCS("get_base_script"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/type_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_type_cache"),_SCS("_get_type_cache"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),_SCS("set_basic_type"),_SCS("get_basic_type"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),_SCS("set_event_type"),_SCS("get_event_type"));
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),_SCS("set_property"),_SCS("get_property"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/set_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance,Basic Type"),"set_call_mode","get_call_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),"set_base_type","get_base_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/base_script",PROPERTY_HINT_FILE,script_ext_hint),"set_base_script","get_base_script");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/type_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_type_cache","_get_type_cache");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/basic_type",PROPERTY_HINT_ENUM,bt),"set_basic_type","get_basic_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"property/event_type",PROPERTY_HINT_ENUM,et),"set_event_type","get_event_type");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"property/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),"set_base_path","get_base_path");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"property/property"),"set_property","get_property");
BIND_CONSTANT( CALL_MODE_SELF );
BIND_CONSTANT( CALL_MODE_NODE_PATH);
@@ -2420,11 +2449,11 @@ void VisualScriptEmitSignal::_validate_property(PropertyInfo& property) const {
void VisualScriptEmitSignal::_bind_methods() {
- ClassDB::bind_method(_MD("set_signal","name"),&VisualScriptEmitSignal::set_signal);
- ClassDB::bind_method(_MD("get_signal"),&VisualScriptEmitSignal::get_signal);
+ ClassDB::bind_method(D_METHOD("set_signal","name"),&VisualScriptEmitSignal::set_signal);
+ ClassDB::bind_method(D_METHOD("get_signal"),&VisualScriptEmitSignal::get_signal);
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),_SCS("set_signal"),_SCS("get_signal"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),"set_signal","get_signal");
}
diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h
index 7d33549e21..7c1d4511cb 100644
--- a/modules/visual_script/visual_script_func_nodes.h
+++ b/modules/visual_script/visual_script_func_nodes.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script_func_nodes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUAL_SCRIPT_FUNC_NODES_H
#define VISUAL_SCRIPT_FUNC_NODES_H
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index ce33b2e5ae..824dfe88a9 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -1,6 +1,35 @@
+/*************************************************************************/
+/* visual_script_nodes.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script_nodes.h"
+
#include "global_constants.h"
-#include "globals.h"
+#include "global_config.h"
#include "scene/main/scene_main_loop.h"
#include "os/os.h"
#include "scene/main/node.h"
@@ -539,11 +568,11 @@ Variant::Type VisualScriptOperator::get_typed() const {
void VisualScriptOperator::_bind_methods() {
- ClassDB::bind_method(_MD("set_operator","op"),&VisualScriptOperator::set_operator);
- ClassDB::bind_method(_MD("get_operator"),&VisualScriptOperator::get_operator);
+ ClassDB::bind_method(D_METHOD("set_operator","op"),&VisualScriptOperator::set_operator);
+ ClassDB::bind_method(D_METHOD("get_operator"),&VisualScriptOperator::get_operator);
- ClassDB::bind_method(_MD("set_typed","type"),&VisualScriptOperator::set_typed);
- ClassDB::bind_method(_MD("get_typed"),&VisualScriptOperator::get_typed);
+ ClassDB::bind_method(D_METHOD("set_typed","type"),&VisualScriptOperator::set_typed);
+ ClassDB::bind_method(D_METHOD("get_typed"),&VisualScriptOperator::get_typed);
String types;
for(int i=0;i<Variant::OP_MAX;i++) {
@@ -557,8 +586,8 @@ void VisualScriptOperator::_bind_methods() {
argt+=","+Variant::get_type_name(Variant::Type(i));
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types),_SCS("set_operator"),_SCS("get_operator"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"typed_value/typed",PROPERTY_HINT_ENUM,argt),_SCS("set_typed"),_SCS("get_typed"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"operator_value/type",PROPERTY_HINT_ENUM,types),"set_operator","get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"typed_value/typed",PROPERTY_HINT_ENUM,argt),"set_typed","get_typed");
}
@@ -717,11 +746,11 @@ void VisualScriptVariableGet::_validate_property(PropertyInfo& property) const {
void VisualScriptVariableGet::_bind_methods() {
- ClassDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableGet::set_variable);
- ClassDB::bind_method(_MD("get_variable"),&VisualScriptVariableGet::get_variable);
+ ClassDB::bind_method(D_METHOD("set_variable","name"),&VisualScriptVariableGet::set_variable);
+ ClassDB::bind_method(D_METHOD("get_variable"),&VisualScriptVariableGet::get_variable);
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),"set_variable","get_variable");
}
@@ -853,11 +882,11 @@ void VisualScriptVariableSet::_validate_property(PropertyInfo& property) const {
void VisualScriptVariableSet::_bind_methods() {
- ClassDB::bind_method(_MD("set_variable","name"),&VisualScriptVariableSet::set_variable);
- ClassDB::bind_method(_MD("get_variable"),&VisualScriptVariableSet::get_variable);
+ ClassDB::bind_method(D_METHOD("set_variable","name"),&VisualScriptVariableSet::set_variable);
+ ClassDB::bind_method(D_METHOD("get_variable"),&VisualScriptVariableSet::get_variable);
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_variable"),_SCS("get_variable"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"variable/name"),"set_variable","get_variable");
}
@@ -995,11 +1024,11 @@ void VisualScriptConstant::_validate_property(PropertyInfo& property) const {
void VisualScriptConstant::_bind_methods() {
- ClassDB::bind_method(_MD("set_constant_type","type"),&VisualScriptConstant::set_constant_type);
- ClassDB::bind_method(_MD("get_constant_type"),&VisualScriptConstant::get_constant_type);
+ ClassDB::bind_method(D_METHOD("set_constant_type","type"),&VisualScriptConstant::set_constant_type);
+ ClassDB::bind_method(D_METHOD("get_constant_type"),&VisualScriptConstant::get_constant_type);
- ClassDB::bind_method(_MD("set_constant_value","value"),&VisualScriptConstant::set_constant_value);
- ClassDB::bind_method(_MD("get_constant_value"),&VisualScriptConstant::get_constant_value);
+ ClassDB::bind_method(D_METHOD("set_constant_value","value"),&VisualScriptConstant::set_constant_value);
+ ClassDB::bind_method(D_METHOD("get_constant_value"),&VisualScriptConstant::get_constant_value);
String argt="Null";
for(int i=1;i<Variant::VARIANT_MAX;i++) {
@@ -1007,8 +1036,8 @@ void VisualScriptConstant::_bind_methods() {
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"constant/type",PROPERTY_HINT_ENUM,argt),_SCS("set_constant_type"),_SCS("get_constant_type"));
- ADD_PROPERTY(PropertyInfo(Variant::NIL,"constant/value"),_SCS("set_constant_value"),_SCS("get_constant_value"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"constant/type",PROPERTY_HINT_ENUM,argt),"set_constant_type","get_constant_type");
+ ADD_PROPERTY(PropertyInfo(Variant::NIL,"constant/value"),"set_constant_value","get_constant_value");
}
@@ -1123,11 +1152,11 @@ Ref<Resource> VisualScriptPreload::get_preload() const{
void VisualScriptPreload::_bind_methods() {
- ClassDB::bind_method(_MD("set_preload","resource"),&VisualScriptPreload::set_preload);
- ClassDB::bind_method(_MD("get_preload"),&VisualScriptPreload::get_preload);
+ ClassDB::bind_method(D_METHOD("set_preload","resource"),&VisualScriptPreload::set_preload);
+ ClassDB::bind_method(D_METHOD("get_preload"),&VisualScriptPreload::get_preload);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"resource",PROPERTY_HINT_RESOURCE_TYPE,"Resource"),_SCS("set_preload"),_SCS("get_preload"));
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"resource",PROPERTY_HINT_RESOURCE_TYPE,"Resource"),"set_preload","get_preload");
}
@@ -1425,8 +1454,8 @@ VisualScriptNodeInstance* VisualScriptGlobalConstant::instance(VisualScriptInsta
void VisualScriptGlobalConstant::_bind_methods() {
- ClassDB::bind_method(_MD("set_global_constant","index"),&VisualScriptGlobalConstant::set_global_constant);
- ClassDB::bind_method(_MD("get_global_constant"),&VisualScriptGlobalConstant::get_global_constant);
+ ClassDB::bind_method(D_METHOD("set_global_constant","index"),&VisualScriptGlobalConstant::set_global_constant);
+ ClassDB::bind_method(D_METHOD("get_global_constant"),&VisualScriptGlobalConstant::get_global_constant);
String cc;
@@ -1436,7 +1465,7 @@ void VisualScriptGlobalConstant::_bind_methods() {
cc+=",";
cc+=GlobalConstants::get_global_constant_name(i);
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_global_constant"),_SCS("get_global_constant"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),"set_global_constant","get_global_constant");
}
VisualScriptGlobalConstant::VisualScriptGlobalConstant() {
@@ -1563,14 +1592,14 @@ void VisualScriptClassConstant::_validate_property(PropertyInfo& property) const
void VisualScriptClassConstant::_bind_methods() {
- ClassDB::bind_method(_MD("set_class_constant","name"),&VisualScriptClassConstant::set_class_constant);
- ClassDB::bind_method(_MD("get_class_constant"),&VisualScriptClassConstant::get_class_constant);
+ ClassDB::bind_method(D_METHOD("set_class_constant","name"),&VisualScriptClassConstant::set_class_constant);
+ ClassDB::bind_method(D_METHOD("get_class_constant"),&VisualScriptClassConstant::get_class_constant);
- ClassDB::bind_method(_MD("set_base_type","name"),&VisualScriptClassConstant::set_base_type);
- ClassDB::bind_method(_MD("get_base_type"),&VisualScriptClassConstant::get_base_type);
+ ClassDB::bind_method(D_METHOD("set_base_type","name"),&VisualScriptClassConstant::set_base_type);
+ ClassDB::bind_method(D_METHOD("get_base_type"),&VisualScriptClassConstant::get_base_type);
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,""),_SCS("set_class_constant"),_SCS("get_class_constant"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"base_type",PROPERTY_HINT_TYPE_STRING,"Object"),"set_base_type","get_base_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,""),"set_class_constant","get_class_constant");
}
VisualScriptClassConstant::VisualScriptClassConstant() {
@@ -1703,11 +1732,11 @@ void VisualScriptBasicTypeConstant::_validate_property(PropertyInfo& property) c
void VisualScriptBasicTypeConstant::_bind_methods() {
- ClassDB::bind_method(_MD("set_basic_type","name"),&VisualScriptBasicTypeConstant::set_basic_type);
- ClassDB::bind_method(_MD("get_basic_type"),&VisualScriptBasicTypeConstant::get_basic_type);
+ ClassDB::bind_method(D_METHOD("set_basic_type","name"),&VisualScriptBasicTypeConstant::set_basic_type);
+ ClassDB::bind_method(D_METHOD("get_basic_type"),&VisualScriptBasicTypeConstant::get_basic_type);
- ClassDB::bind_method(_MD("set_basic_type_constant","name"),&VisualScriptBasicTypeConstant::set_basic_type_constant);
- ClassDB::bind_method(_MD("get_basic_type_constant"),&VisualScriptBasicTypeConstant::get_basic_type_constant);
+ ClassDB::bind_method(D_METHOD("set_basic_type_constant","name"),&VisualScriptBasicTypeConstant::set_basic_type_constant);
+ ClassDB::bind_method(D_METHOD("get_basic_type_constant"),&VisualScriptBasicTypeConstant::get_basic_type_constant);
String argt="Null";
@@ -1715,8 +1744,8 @@ void VisualScriptBasicTypeConstant::_bind_methods() {
argt+=","+Variant::get_type_name(Variant::Type(i));
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"basic_type",PROPERTY_HINT_ENUM,argt),_SCS("set_basic_type"),_SCS("get_basic_type"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,""),_SCS("set_basic_type_constant"),_SCS("get_basic_type_constant"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"basic_type",PROPERTY_HINT_ENUM,argt),"set_basic_type","get_basic_type");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,""),"set_basic_type_constant","get_basic_type_constant");
}
VisualScriptBasicTypeConstant::VisualScriptBasicTypeConstant() {
@@ -1738,6 +1767,8 @@ const char* VisualScriptMathConstant::const_name[MATH_CONSTANT_MAX]={
"PI/2",
"E",
"Sqrt2",
+ "INF",
+ "NAN"
};
double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX]={
@@ -1746,7 +1777,9 @@ double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX]={
Math_PI*2,
Math_PI*0.5,
2.71828182845904523536,
- Math::sqrt(2.0)
+ Math::sqrt(2.0),
+ Math_INF,
+ Math_NAN
};
@@ -1831,8 +1864,8 @@ VisualScriptNodeInstance* VisualScriptMathConstant::instance(VisualScriptInstanc
void VisualScriptMathConstant::_bind_methods() {
- ClassDB::bind_method(_MD("set_math_constant","which"),&VisualScriptMathConstant::set_math_constant);
- ClassDB::bind_method(_MD("get_math_constant"),&VisualScriptMathConstant::get_math_constant);
+ ClassDB::bind_method(D_METHOD("set_math_constant","which"),&VisualScriptMathConstant::set_math_constant);
+ ClassDB::bind_method(D_METHOD("get_math_constant"),&VisualScriptMathConstant::get_math_constant);
String cc;
@@ -1842,7 +1875,7 @@ void VisualScriptMathConstant::_bind_methods() {
cc+=",";
cc+=const_name[i];
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_math_constant"),_SCS("get_math_constant"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"constant",PROPERTY_HINT_ENUM,cc),"set_math_constant","get_math_constant");
}
VisualScriptMathConstant::VisualScriptMathConstant() {
@@ -1953,8 +1986,8 @@ VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output
void VisualScriptEngineSingleton::_bind_methods() {
- ClassDB::bind_method(_MD("set_singleton","name"),&VisualScriptEngineSingleton::set_singleton);
- ClassDB::bind_method(_MD("get_singleton"),&VisualScriptEngineSingleton::get_singleton);
+ ClassDB::bind_method(D_METHOD("set_singleton","name"),&VisualScriptEngineSingleton::set_singleton);
+ ClassDB::bind_method(D_METHOD("get_singleton"),&VisualScriptEngineSingleton::get_singleton);
String cc;
@@ -1971,7 +2004,7 @@ void VisualScriptEngineSingleton::_bind_methods() {
cc+=E->get().name;
}
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,cc),_SCS("set_singleton"),_SCS("get_singleton"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"constant",PROPERTY_HINT_ENUM,cc),"set_singleton","get_singleton");
}
VisualScriptEngineSingleton::VisualScriptEngineSingleton() {
@@ -2190,10 +2223,10 @@ void VisualScriptSceneNode::_validate_property(PropertyInfo& property) const {
void VisualScriptSceneNode::_bind_methods() {
- ClassDB::bind_method(_MD("set_node_path","path"),&VisualScriptSceneNode::set_node_path);
- ClassDB::bind_method(_MD("get_node_path"),&VisualScriptSceneNode::get_node_path);
+ ClassDB::bind_method(D_METHOD("set_node_path","path"),&VisualScriptSceneNode::set_node_path);
+ ClassDB::bind_method(D_METHOD("get_node_path"),&VisualScriptSceneNode::get_node_path);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_node_path"),_SCS("get_node_path"));
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),"set_node_path","get_node_path");
}
VisualScriptSceneNode::VisualScriptSceneNode() {
@@ -2401,10 +2434,10 @@ VisualScriptNodeInstance* VisualScriptResourcePath::instance(VisualScriptInstanc
void VisualScriptResourcePath::_bind_methods() {
- ClassDB::bind_method(_MD("set_resource_path","path"),&VisualScriptResourcePath::set_resource_path);
- ClassDB::bind_method(_MD("get_resource_path"),&VisualScriptResourcePath::get_resource_path);
+ ClassDB::bind_method(D_METHOD("set_resource_path","path"),&VisualScriptResourcePath::set_resource_path);
+ ClassDB::bind_method(D_METHOD("get_resource_path"),&VisualScriptResourcePath::get_resource_path);
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"path",PROPERTY_HINT_FILE),_SCS("set_resource_path"),_SCS("get_resource_path"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"path",PROPERTY_HINT_FILE),"set_resource_path","get_resource_path");
}
VisualScriptResourcePath::VisualScriptResourcePath() {
@@ -3001,18 +3034,18 @@ VisualScriptNodeInstance* VisualScriptComment::instance(VisualScriptInstance* p_
void VisualScriptComment::_bind_methods() {
- ClassDB::bind_method(_MD("set_title","title"),&VisualScriptComment::set_title);
- ClassDB::bind_method(_MD("get_title"),&VisualScriptComment::get_title);
+ ClassDB::bind_method(D_METHOD("set_title","title"),&VisualScriptComment::set_title);
+ ClassDB::bind_method(D_METHOD("get_title"),&VisualScriptComment::get_title);
- ClassDB::bind_method(_MD("set_description","description"),&VisualScriptComment::set_description);
- ClassDB::bind_method(_MD("get_description"),&VisualScriptComment::get_description);
+ ClassDB::bind_method(D_METHOD("set_description","description"),&VisualScriptComment::set_description);
+ ClassDB::bind_method(D_METHOD("get_description"),&VisualScriptComment::get_description);
- ClassDB::bind_method(_MD("set_size","size"),&VisualScriptComment::set_size);
- ClassDB::bind_method(_MD("get_size"),&VisualScriptComment::get_size);
+ ClassDB::bind_method(D_METHOD("set_size","size"),&VisualScriptComment::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"),&VisualScriptComment::get_size);
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title"));
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"description",PROPERTY_HINT_MULTILINE_TEXT),_SCS("set_description"),_SCS("get_description"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"size"),_SCS("set_size"),_SCS("get_size"));
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),"set_title","get_title");
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"description",PROPERTY_HINT_MULTILINE_TEXT),"set_description","get_description");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"size"),"set_size","get_size");
}
@@ -3140,14 +3173,14 @@ VisualScriptNodeInstance* VisualScriptConstructor::instance(VisualScriptInstance
void VisualScriptConstructor::_bind_methods() {
- ClassDB::bind_method(_MD("set_constructor_type","type"),&VisualScriptConstructor::set_constructor_type);
- ClassDB::bind_method(_MD("get_constructor_type"),&VisualScriptConstructor::get_constructor_type);
+ ClassDB::bind_method(D_METHOD("set_constructor_type","type"),&VisualScriptConstructor::set_constructor_type);
+ ClassDB::bind_method(D_METHOD("get_constructor_type"),&VisualScriptConstructor::get_constructor_type);
- ClassDB::bind_method(_MD("set_constructor","constructor"),&VisualScriptConstructor::set_constructor);
- ClassDB::bind_method(_MD("get_constructor"),&VisualScriptConstructor::get_constructor);
+ ClassDB::bind_method(D_METHOD("set_constructor","constructor"),&VisualScriptConstructor::set_constructor);
+ ClassDB::bind_method(D_METHOD("get_constructor"),&VisualScriptConstructor::get_constructor);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"type",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_constructor_type"),_SCS("get_constructor_type"));
- ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"constructor",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_constructor"),_SCS("get_constructor"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"type",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_constructor_type","get_constructor_type");
+ ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"constructor",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_constructor","get_constructor");
}
@@ -3283,19 +3316,19 @@ VisualScriptNodeInstance* VisualScriptLocalVar::instance(VisualScriptInstance* p
void VisualScriptLocalVar::_bind_methods() {
- ClassDB::bind_method(_MD("set_var_name","name"),&VisualScriptLocalVar::set_var_name);
- ClassDB::bind_method(_MD("get_var_name"),&VisualScriptLocalVar::get_var_name);
+ ClassDB::bind_method(D_METHOD("set_var_name","name"),&VisualScriptLocalVar::set_var_name);
+ ClassDB::bind_method(D_METHOD("get_var_name"),&VisualScriptLocalVar::get_var_name);
- ClassDB::bind_method(_MD("set_var_type","type"),&VisualScriptLocalVar::set_var_type);
- ClassDB::bind_method(_MD("get_var_type"),&VisualScriptLocalVar::get_var_type);
+ ClassDB::bind_method(D_METHOD("set_var_type","type"),&VisualScriptLocalVar::set_var_type);
+ ClassDB::bind_method(D_METHOD("get_var_type"),&VisualScriptLocalVar::get_var_type);
String argt="Any";
for(int i=1;i<Variant::VARIANT_MAX;i++) {
argt+=","+Variant::get_type_name(Variant::Type(i));
}
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_var_name"),_SCS("get_var_name"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"variable/type",PROPERTY_HINT_ENUM,argt),_SCS("set_var_type"),_SCS("get_var_type"));
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"variable/name"),"set_var_name","get_var_name");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"variable/type",PROPERTY_HINT_ENUM,argt),"set_var_type","get_var_type");
}
@@ -3420,19 +3453,19 @@ VisualScriptNodeInstance* VisualScriptLocalVarSet::instance(VisualScriptInstance
void VisualScriptLocalVarSet::_bind_methods() {
- ClassDB::bind_method(_MD("set_var_name","name"),&VisualScriptLocalVarSet::set_var_name);
- ClassDB::bind_method(_MD("get_var_name"),&VisualScriptLocalVarSet::get_var_name);
+ ClassDB::bind_method(D_METHOD("set_var_name","name"),&VisualScriptLocalVarSet::set_var_name);
+ ClassDB::bind_method(D_METHOD("get_var_name"),&VisualScriptLocalVarSet::get_var_name);
- ClassDB::bind_method(_MD("set_var_type","type"),&VisualScriptLocalVarSet::set_var_type);
- ClassDB::bind_method(_MD("get_var_type"),&VisualScriptLocalVarSet::get_var_type);
+ ClassDB::bind_method(D_METHOD("set_var_type","type"),&VisualScriptLocalVarSet::set_var_type);
+ ClassDB::bind_method(D_METHOD("get_var_type"),&VisualScriptLocalVarSet::get_var_type);
String argt="Any";
for(int i=1;i<Variant::VARIANT_MAX;i++) {
argt+=","+Variant::get_type_name(Variant::Type(i));
}
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"variable/name"),_SCS("set_var_name"),_SCS("get_var_name"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"variable/type",PROPERTY_HINT_ENUM,argt),_SCS("set_var_type"),_SCS("get_var_type"));
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"variable/name"),"set_var_name","get_var_name");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"variable/type",PROPERTY_HINT_ENUM,argt),"set_var_type","get_var_type");
}
@@ -3630,14 +3663,14 @@ void VisualScriptInputAction::_validate_property(PropertyInfo& property) const {
void VisualScriptInputAction::_bind_methods() {
- ClassDB::bind_method(_MD("set_action_name","name"),&VisualScriptInputAction::set_action_name);
- ClassDB::bind_method(_MD("get_action_name"),&VisualScriptInputAction::get_action_name);
+ ClassDB::bind_method(D_METHOD("set_action_name","name"),&VisualScriptInputAction::set_action_name);
+ ClassDB::bind_method(D_METHOD("get_action_name"),&VisualScriptInputAction::get_action_name);
- ClassDB::bind_method(_MD("set_action_mode","mode"),&VisualScriptInputAction::set_action_mode);
- ClassDB::bind_method(_MD("get_action_mode"),&VisualScriptInputAction::get_action_mode);
+ ClassDB::bind_method(D_METHOD("set_action_mode","mode"),&VisualScriptInputAction::set_action_mode);
+ ClassDB::bind_method(D_METHOD("get_action_mode"),&VisualScriptInputAction::get_action_mode);
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"action"),_SCS("set_action_name"),_SCS("get_action_name"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Pressed,Released,JustPressed,JustReleased"),_SCS("set_action_mode"),_SCS("get_action_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"action"),"set_action_name","get_action_name");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Pressed,Released,JustPressed,JustReleased"),"set_action_mode","get_action_mode");
}
@@ -3834,14 +3867,14 @@ void VisualScriptDeconstruct::_validate_property(PropertyInfo& property) const {
void VisualScriptDeconstruct::_bind_methods() {
- ClassDB::bind_method(_MD("set_deconstruct_type","type"),&VisualScriptDeconstruct::set_deconstruct_type);
- ClassDB::bind_method(_MD("get_deconstruct_type"),&VisualScriptDeconstruct::get_deconstruct_type);
+ ClassDB::bind_method(D_METHOD("set_deconstruct_type","type"),&VisualScriptDeconstruct::set_deconstruct_type);
+ ClassDB::bind_method(D_METHOD("get_deconstruct_type"),&VisualScriptDeconstruct::get_deconstruct_type);
- ClassDB::bind_method(_MD("set_deconstruct_input_type","input_type"),&VisualScriptDeconstruct::set_deconstruct_input_type);
- ClassDB::bind_method(_MD("get_deconstruct_input_type"),&VisualScriptDeconstruct::get_deconstruct_input_type);
+ ClassDB::bind_method(D_METHOD("set_deconstruct_input_type","input_type"),&VisualScriptDeconstruct::set_deconstruct_input_type);
+ ClassDB::bind_method(D_METHOD("get_deconstruct_input_type"),&VisualScriptDeconstruct::get_deconstruct_input_type);
- ClassDB::bind_method(_MD("_set_elem_cache","_cache"),&VisualScriptDeconstruct::_set_elem_cache);
- ClassDB::bind_method(_MD("_get_elem_cache"),&VisualScriptDeconstruct::_get_elem_cache);
+ ClassDB::bind_method(D_METHOD("_set_elem_cache","_cache"),&VisualScriptDeconstruct::_set_elem_cache);
+ ClassDB::bind_method(D_METHOD("_get_elem_cache"),&VisualScriptDeconstruct::_get_elem_cache);
String argt="Any";
for(int i=1;i<Variant::VARIANT_MAX;i++) {
@@ -3850,9 +3883,9 @@ void VisualScriptDeconstruct::_bind_methods() {
String iet="None,Key,MouseMotion,MouseButton,JoypadMotion,JoypadButton,ScreenTouch,ScreenDrag,Action";
- ADD_PROPERTY( PropertyInfo(Variant::INT,"type",PROPERTY_HINT_ENUM,argt),_SCS("set_deconstruct_type"),_SCS("get_deconstruct_type"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"input_type",PROPERTY_HINT_ENUM,iet),_SCS("set_deconstruct_input_type"),_SCS("get_deconstruct_input_type"));
- ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"elem_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_elem_cache"),_SCS("_get_elem_cache"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"type",PROPERTY_HINT_ENUM,argt),"set_deconstruct_type","get_deconstruct_type");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"input_type",PROPERTY_HINT_ENUM,iet),"set_deconstruct_input_type","get_deconstruct_input_type");
+ ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"elem_cache",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_elem_cache","_get_elem_cache");
}
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index 7a06fbf5e8..2e7fb0536c 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script_nodes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUAL_SCRIPT_NODES_H
#define VISUAL_SCRIPT_NODES_H
@@ -467,7 +495,9 @@ public:
MATH_CONSTANT_HALF_PI,
MATH_CONSTANT_E,
MATH_CONSTANT_SQRT2,
- MATH_CONSTANT_MAX,
+ MATH_CONSTANT_INF,
+ MATH_CONSTANT_NAN,
+ MATH_CONSTANT_MAX
};
private:
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index 8b251e667c..35335fd9bc 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* visual_script_yield_nodes.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_script_yield_nodes.h"
+
#include "scene/main/scene_main_loop.h"
#include "os/os.h"
#include "scene/main/node.h"
@@ -157,14 +186,14 @@ void VisualScriptYield::_validate_property(PropertyInfo& property) const {
void VisualScriptYield::_bind_methods() {
- ClassDB::bind_method(_MD("set_yield_mode","mode"),&VisualScriptYield::set_yield_mode);
- ClassDB::bind_method(_MD("get_yield_mode"),&VisualScriptYield::get_yield_mode);
+ ClassDB::bind_method(D_METHOD("set_yield_mode","mode"),&VisualScriptYield::set_yield_mode);
+ ClassDB::bind_method(D_METHOD("get_yield_mode"),&VisualScriptYield::get_yield_mode);
- ClassDB::bind_method(_MD("set_wait_time","sec"),&VisualScriptYield::set_wait_time);
- ClassDB::bind_method(_MD("get_wait_time"),&VisualScriptYield::get_wait_time);
+ ClassDB::bind_method(D_METHOD("set_wait_time","sec"),&VisualScriptYield::set_wait_time);
+ ClassDB::bind_method(D_METHOD("get_wait_time"),&VisualScriptYield::get_wait_time);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Frame,FixedFrame,Time",PROPERTY_USAGE_NOEDITOR),_SCS("set_yield_mode"),_SCS("get_yield_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"wait_time"),_SCS("set_wait_time"),_SCS("get_wait_time"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Frame,FixedFrame,Time",PROPERTY_USAGE_NOEDITOR),"set_yield_mode","get_yield_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wait_time"),"set_wait_time","get_wait_time");
BIND_CONSTANT( YIELD_FRAME );
@@ -468,17 +497,17 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo& property) const {
void VisualScriptYieldSignal::_bind_methods() {
- ClassDB::bind_method(_MD("set_base_type","base_type"),&VisualScriptYieldSignal::set_base_type);
- ClassDB::bind_method(_MD("get_base_type"),&VisualScriptYieldSignal::get_base_type);
+ ClassDB::bind_method(D_METHOD("set_base_type","base_type"),&VisualScriptYieldSignal::set_base_type);
+ ClassDB::bind_method(D_METHOD("get_base_type"),&VisualScriptYieldSignal::get_base_type);
- ClassDB::bind_method(_MD("set_signal","signal"),&VisualScriptYieldSignal::set_signal);
- ClassDB::bind_method(_MD("get_signal"),&VisualScriptYieldSignal::get_signal);
+ ClassDB::bind_method(D_METHOD("set_signal","signal"),&VisualScriptYieldSignal::set_signal);
+ ClassDB::bind_method(D_METHOD("get_signal"),&VisualScriptYieldSignal::get_signal);
- ClassDB::bind_method(_MD("set_call_mode","mode"),&VisualScriptYieldSignal::set_call_mode);
- ClassDB::bind_method(_MD("get_call_mode"),&VisualScriptYieldSignal::get_call_mode);
+ ClassDB::bind_method(D_METHOD("set_call_mode","mode"),&VisualScriptYieldSignal::set_call_mode);
+ ClassDB::bind_method(D_METHOD("get_call_mode"),&VisualScriptYieldSignal::get_call_mode);
- ClassDB::bind_method(_MD("set_base_path","base_path"),&VisualScriptYieldSignal::set_base_path);
- ClassDB::bind_method(_MD("get_base_path"),&VisualScriptYieldSignal::get_base_path);
+ ClassDB::bind_method(D_METHOD("set_base_path","base_path"),&VisualScriptYieldSignal::set_base_path);
+ ClassDB::bind_method(D_METHOD("get_base_path"),&VisualScriptYieldSignal::get_base_path);
@@ -490,10 +519,10 @@ void VisualScriptYieldSignal::_bind_methods() {
bt+=Variant::get_type_name(Variant::Type(i));
}
- ADD_PROPERTY(PropertyInfo(Variant::INT,"signal/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance"),_SCS("set_call_mode"),_SCS("get_call_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),_SCS("set_base_type"),_SCS("get_base_type"));
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"signal/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),_SCS("set_base_path"),_SCS("get_base_path"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),_SCS("set_signal"),_SCS("get_signal"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"signal/call_mode",PROPERTY_HINT_ENUM,"Self,Node Path,Instance"),"set_call_mode","get_call_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/base_type",PROPERTY_HINT_TYPE_STRING,"Object"),"set_base_type","get_base_type");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"signal/node_path",PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE),"set_base_path","get_base_path");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"signal/signal"),"set_signal","get_signal");
BIND_CONSTANT( CALL_MODE_SELF );
diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h
index 210d6ec995..80ac879aad 100644
--- a/modules/visual_script/visual_script_yield_nodes.h
+++ b/modules/visual_script/visual_script_yield_nodes.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_script_yield_nodes.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUAL_SCRIPT_YIELD_NODES_H
#define VISUAL_SCRIPT_YIELD_NODES_H
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index bdd97f1df7..d4995ad798 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -35,7 +35,7 @@
#include "../theora/yuv2rgb.h"
#include "os/file_access.h"
-#include "globals.h"
+#include "global_config.h"
#include <string.h>
diff --git a/modules/webp/SCsub b/modules/webp/SCsub
index 92f34c4da1..aa3486a2c5 100644
--- a/modules/webp/SCsub
+++ b/modules/webp/SCsub
@@ -9,108 +9,118 @@ env_webp = env_modules.Clone()
if (env['builtin_libwebp'] != 'no'):
thirdparty_dir = "#thirdparty/libwebp/"
thirdparty_sources = [
- "enc/webpenc.c",
- "enc/near_lossless.c",
- "enc/frame.c",
- "enc/alpha.c",
- "enc/picture_csp.c",
- "enc/vp8l.c",
- "enc/picture_psnr.c",
- "enc/delta_palettization.c",
- "enc/syntax.c",
- "enc/backward_references.c",
- "enc/token.c",
- "enc/analysis.c",
- "enc/iterator.c",
- "enc/picture_tools.c",
- "enc/picture_rescale.c",
- "enc/config.c",
- "enc/tree.c",
- "enc/cost.c",
- "enc/picture.c",
- "enc/quant.c",
- "enc/filter.c",
- "enc/histogram.c",
- "utils/rescaler.c",
- "utils/filters.c",
- "utils/quant_levels_dec.c",
- "utils/huffman.c",
- "utils/thread.c",
- "utils/quant_levels.c",
- "utils/bit_writer.c",
- "utils/bit_reader.c",
- "utils/random.c",
- "utils/utils.c",
- "utils/huffman_encode.c",
- "utils/color_cache.c",
- "mux/muxinternal.c",
- "mux/muxread.c",
- "mux/anim_encode.c",
- "mux/muxedit.c",
- "dec/webp.c",
- "dec/frame.c",
- "dec/alpha.c",
- "dec/vp8l.c",
- "dec/io.c",
- "dec/vp8.c",
- "dec/idec.c",
- "dec/tree.c",
- "dec/buffer.c",
- "dec/quant.c",
- "demux/demux.c",
+ "dec/alpha_dec.c",
+ "dec/buffer_dec.c",
+ "dec/frame_dec.c",
+ "dec/idec_dec.c",
+ "dec/io_dec.c",
+ "dec/quant_dec.c",
+ "dec/tree_dec.c",
+ "dec/vp8_dec.c",
+ "dec/vp8l_dec.c",
+ "dec/webp_dec.c",
"demux/anim_decode.c",
- "dsp/yuv.c",
- "dsp/filters_sse2.c",
- "dsp/dec_sse41.c",
- "dsp/rescaler.c",
- "dsp/lossless_sse2.c",
- "dsp/alpha_processing_sse41.c",
- "dsp/alpha_processing_sse2.c",
- "dsp/filters.c",
- "dsp/upsampling_mips_dsp_r2.c",
- "dsp/dec_neon.c",
- "dsp/enc_neon.c",
- "dsp/lossless_enc_mips32.c",
- "dsp/lossless_enc_sse2.c",
- "dsp/upsampling.c",
- "dsp/lossless_enc_neon.c",
+ "demux/demux.c",
"dsp/alpha_processing.c",
+ "dsp/alpha_processing_mips_dsp_r2.c",
+ "dsp/alpha_processing_neon.c",
+ "dsp/alpha_processing_sse2.c",
+ "dsp/alpha_processing_sse41.c",
+ "dsp/argb.c",
+ "dsp/argb_mips_dsp_r2.c",
+ "dsp/argb_sse2.c",
+ "dsp/cost.c",
+ "dsp/cost_mips32.c",
+ "dsp/cost_mips_dsp_r2.c",
"dsp/cost_sse2.c",
+ "dsp/cpu.c",
+ "dsp/dec.c",
+ "dsp/dec_clip_tables.c",
"dsp/dec_mips32.c",
+ "dsp/dec_mips_dsp_r2.c",
+ "dsp/dec_msa.c",
+ "dsp/dec_neon.c",
+ "dsp/dec_sse2.c",
+ "dsp/dec_sse41.c",
"dsp/enc_avx2.c",
- "dsp/rescaler_mips32.c",
"dsp/enc.c",
- "dsp/lossless_enc_sse41.c",
- "dsp/cost_mips32.c",
- "dsp/lossless_mips_dsp_r2.c",
- "dsp/filters_mips_dsp_r2.c",
- "dsp/upsampling_neon.c",
- "dsp/alpha_processing_mips_dsp_r2.c",
+ "dsp/enc_mips32.c",
"dsp/enc_mips_dsp_r2.c",
- "dsp/lossless.c",
- "dsp/yuv_mips_dsp_r2.c",
- "dsp/cost_mips_dsp_r2.c",
- "dsp/argb.c",
- "dsp/dec_sse2.c",
- "dsp/rescaler_sse2.c",
+ "dsp/enc_msa.c",
+ "dsp/enc_neon.c",
+ "dsp/enc_sse2.c",
"dsp/enc_sse41.c",
- "dsp/argb_mips_dsp_r2.c",
+ "dsp/filters.c",
+ "dsp/filters_mips_dsp_r2.c",
+ "dsp/filters_msa.c",
+ "dsp/filters_neon.c",
+ "dsp/filters_sse2.c",
+ "dsp/lossless.c",
+ "dsp/lossless_enc.c",
+ "dsp/lossless_enc_mips32.c",
"dsp/lossless_enc_mips_dsp_r2.c",
- "dsp/dec_clip_tables.c",
- "dsp/yuv_mips32.c",
- "dsp/cpu.c",
- "dsp/dec.c",
- "dsp/argb_sse2.c",
+ "dsp/lossless_enc_msa.c",
+ "dsp/lossless_enc_neon.c",
+ "dsp/lossless_enc_sse2.c",
+ "dsp/lossless_enc_sse41.c",
+ "dsp/lossless_mips_dsp_r2.c",
+ "dsp/lossless_msa.c",
"dsp/lossless_neon.c",
- "dsp/lossless_enc.c",
- "dsp/enc_mips32.c",
- "dsp/cost.c",
+ "dsp/lossless_sse2.c",
+ "dsp/rescaler.c",
+ "dsp/rescaler_mips32.c",
"dsp/rescaler_mips_dsp_r2.c",
- "dsp/dec_mips_dsp_r2.c",
+ "dsp/rescaler_msa.c",
"dsp/rescaler_neon.c",
- "dsp/yuv_sse2.c",
- "dsp/enc_sse2.c",
+ "dsp/rescaler_sse2.c",
+ "dsp/upsampling.c",
+ "dsp/upsampling_mips_dsp_r2.c",
+ "dsp/upsampling_msa.c",
+ "dsp/upsampling_neon.c",
"dsp/upsampling_sse2.c",
+ "dsp/yuv.c",
+ "dsp/yuv_mips32.c",
+ "dsp/yuv_mips_dsp_r2.c",
+ "dsp/yuv_sse2.c",
+ "enc/alpha_enc.c",
+ "enc/analysis_enc.c",
+ "enc/backward_references_enc.c",
+ "enc/config_enc.c",
+ "enc/cost_enc.c",
+ "enc/delta_palettization_enc.c",
+ "enc/filter_enc.c",
+ "enc/frame_enc.c",
+ "enc/histogram_enc.c",
+ "enc/iterator_enc.c",
+ "enc/near_lossless_enc.c",
+ "enc/picture_csp_enc.c",
+ "enc/picture_enc.c",
+ "enc/picture_psnr_enc.c",
+ "enc/picture_rescale_enc.c",
+ "enc/picture_tools_enc.c",
+ "enc/predictor_enc.c",
+ "enc/quant_enc.c",
+ "enc/syntax_enc.c",
+ "enc/token_enc.c",
+ "enc/tree_enc.c",
+ "enc/vp8l_enc.c",
+ "enc/webp_enc.c",
+ "mux/anim_encode.c",
+ "mux/muxedit.c",
+ "mux/muxinternal.c",
+ "mux/muxread.c",
+ "utils/bit_reader_utils.c",
+ "utils/bit_writer_utils.c",
+ "utils/color_cache_utils.c",
+ "utils/filters_utils.c",
+ "utils/huffman_encode_utils.c",
+ "utils/huffman_utils.c",
+ "utils/quant_levels_dec_utils.c",
+ "utils/quant_levels_utils.c",
+ "utils/random_utils.c",
+ "utils/rescaler_utils.c",
+ "utils/thread_utils.c",
+ "utils/utils.c",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 146f7c25a3..86f8c40f83 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -20,6 +20,7 @@ android_files = [
'java_glue.cpp',
'cpu-features.c',
'java_class_wrapper.cpp'
+ 'power_android.cpp'
]
# env.Depends('#core/math/vector3.h', 'vector3_psp.h')
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp
index e0e89e6344..415223c1da 100644
--- a/platform/android/audio_driver_jandroid.cpp
+++ b/platform/android/audio_driver_jandroid.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "audio_driver_jandroid.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
#include "thread_jandroid.h"
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 8e1fda74ed..3fc822860d 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -28,12 +28,12 @@
/*************************************************************************/
#include "version.h"
#include "export.h"
-#include "tools/editor/editor_settings.h"
-#include "tools/editor/editor_import_export.h"
-#include "tools/editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_export.h"
+#include "editor/editor_node.h"
#include "io/zip_io.h"
#include "io/marshalls.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
#include "os/os.h"
#include "platform/android/logo.h"
@@ -1892,9 +1892,11 @@ EditorExportPlatformAndroid::~EditorExportPlatformAndroid() {
memdelete(device_thread);
}
+#endif
void register_android_exporter() {
+#if 0
String exe_ext=OS::get_singleton()->get_name()=="Windows"?"exe":"";
EDITOR_DEF("export/android/adb","");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"android/adb",PROPERTY_HINT_GLOBAL_FILE,exe_ext));
@@ -1913,6 +1915,6 @@ void register_android_exporter() {
Ref<EditorExportPlatformAndroid> exporter = Ref<EditorExportPlatformAndroid>( memnew(EditorExportPlatformAndroid) );
EditorImportExport::get_singleton()->add_export_platform(exporter);
-
-}
#endif
+}
+
diff --git a/platform/android/globals/global_defaults.cpp b/platform/android/globals/global_defaults.cpp
index bbf9bd5b0b..01daac9260 100644
--- a/platform/android/globals/global_defaults.cpp
+++ b/platform/android/globals/global_defaults.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "global_defaults.h"
-#include "globals.h"
+#include "global_config.h"
void register_android_global_defaults() {
diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp
index 3c7f7f5854..83d5a413c0 100644
--- a/platform/android/godot_android.cpp
+++ b/platform/android/godot_android.cpp
@@ -43,7 +43,7 @@
#include <unistd.h>
#include <stdlib.h>
#include "os_android.h"
-#include "globals.h"
+#include "global_config.h"
#include "main/main.h"
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "godot", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "godot", __VA_ARGS__))
diff --git a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
index 80cded6fb5..3c8207fae1 100644
--- a/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
+++ b/platform/android/java/src/org/godotengine/godot/input/GodotTextInputWrapper.java
@@ -49,7 +49,6 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
// ===========================================================
private final GodotView mView;
private final GodotEditText mEdit;
- private String mText;
private String mOriginText;
// ===========================================================
@@ -81,52 +80,28 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
@Override
public void afterTextChanged(final Editable s) {
- if (this.isFullScreenEdit()) {
- return;
- }
- //if (BuildConfig.DEBUG) {
- //Log.d(TAG, "afterTextChanged: " + s);
- //}
- int nModified = s.length() - this.mText.length();
- if (nModified > 0) {
- final String insertText = s.subSequence(this.mText.length(), s.length()).toString();
- for(int i = 0; i < insertText.length(); i++) {
- int ch = insertText.codePointAt(i);
- GodotLib.key(0, ch, true);
- GodotLib.key(0, ch, false);
- }
- /*
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "insertText(" + insertText + ")");
- }
- */
- } else {
- for (; nModified < 0; ++nModified) {
- GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
- GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
- /*
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "deleteBackward");
- }
- */
- }
- }
- this.mText = s.toString();
}
@Override
public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) {
- /*
- if (BuildConfig.DEBUG) {
- Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
+ //Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after);
+
+ for (int i=0;i<count;i++){
+ GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
+ GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
}
- */
- this.mText = pCharSequence.toString();
}
@Override
public void onTextChanged(final CharSequence pCharSequence, final int start, final int before, final int count) {
+ //Log.d(TAG, "onTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",before: " + before);
+
+ for (int i=start;i<start+count;i++){
+ int ch = pCharSequence.charAt(i);
+ GodotLib.key(0, ch, true);
+ GodotLib.key(0, ch, false);
+ }
}
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index 9acda005f1..2923ef6a91 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -562,7 +562,7 @@ JavaObject::~JavaObject(){
void JavaClassWrapper::_bind_methods() {
- ClassDB::bind_method(_MD("wrap:JavaClass","name"),&JavaClassWrapper::wrap);
+ ClassDB::bind_method(D_METHOD("wrap:JavaClass","name"),&JavaClassWrapper::wrap);
}
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index dfbb437344..41558cf86a 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -36,7 +36,7 @@
#include "file_access_android.h"
#include "dir_access_jandroid.h"
#include "audio_driver_jandroid.h"
-#include "globals.h"
+#include "global_config.h"
#include "thread_jandroid.h"
#include "core/os/keyboard.h"
#include "java_class_wrapper.h"
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 1095689a5b..a10f27424c 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -36,7 +36,7 @@
#include "servers/visual/visual_server_wrap_mt.h"
#include "main/main.h"
#include "file_access_android.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#ifdef ANDROID_NATIVE_ACTIVITY
#include "file_access_android.h"
@@ -159,6 +159,8 @@ void OS_Android::initialize(const VideoMode& p_desired,int p_video_driver,int p_
input = memnew( InputDefault );
input->set_fallback_mapping("Default Android Gamepad");
+
+ power_manager = memnew( power_android );
}
void OS_Android::set_main_loop( MainLoop * p_main_loop ) {
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index bf1db57ba5..ead3969744 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -32,6 +32,7 @@
#include "os/input.h"
#include "drivers/unix/os_unix.h"
#include "os/main_loop.h"
+#include "power_android.h"
#include "servers/physics/physics_server_sw.h"
#include "servers/audio_server.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
@@ -142,6 +143,8 @@ private:
SetKeepScreenOnFunc set_keep_screen_on_func;
AlertFunc alert_func;
+ power_android *power_manager;
+
public:
// functions used by main to initialize/deintialize the OS
diff --git a/platform/android/power_android.cpp b/platform/android/power_android.cpp
new file mode 100644
index 0000000000..dc3a4ec90c
--- /dev/null
+++ b/platform/android/power_android.cpp
@@ -0,0 +1,238 @@
+/*************************************************************************/
+/* power_android.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "core/error_macros.h"
+
+#include "power_android.h"
+
+static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder) {
+ if (refholder->m_env) {
+ JNIEnv* env = refholder->m_env;
+ (*env)->PopLocalFrame(env, NULL);
+ --s_active;
+ }
+}
+
+static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func)
+{
+ struct LocalReferenceHolder refholder;
+ refholder.m_env = NULL;
+ refholder.m_func = func;
+ return refholder;
+}
+
+static bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env)
+{
+ const int capacity = 16;
+ if ((*env)->PushLocalFrame(env, capacity) < 0) {
+ return false;
+ }
+ ++s_active;
+ refholder->m_env = env;
+ return true;
+}
+
+
+static SDL_bool LocalReferenceHolder_IsActive(void)
+{
+ return s_active > 0;
+}
+
+ANativeWindow* Android_JNI_GetNativeWindow(void)
+{
+ ANativeWindow* anw;
+ jobject s;
+ JNIEnv *env = Android_JNI_GetEnv();
+
+ s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
+ anw = ANativeWindow_fromSurface(env, s);
+ (*env)->DeleteLocalRef(env, s);
+
+ return anw;
+}
+
+
+/*
+ * CODE CHUNK IMPORTED FROM SDL 2.0
+ * returns 0 on success or -1 on error (others undefined then)
+ * returns truthy or falsy value in plugged, charged and battery
+ * returns the value in seconds and percent or -1 if not available
+ */
+int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
+{
+ env = Android_JNI_GetEnv();
+ refs = LocalReferenceHolder_Setup(__FUNCTION__);
+
+ if (!LocalReferenceHolder_Init(&refs, env)) {
+ LocalReferenceHolder_Cleanup(&refs);
+ return -1;
+ }
+ mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
+ context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+ action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
+ cls = (*env)->FindClass(env, "android/content/IntentFilter");
+ mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
+ filter = (*env)->NewObject(env, cls, mid, action);
+ (*env)->DeleteLocalRef(env, action);
+ mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
+ intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
+ (*env)->DeleteLocalRef(env, filter);
+ cls = (*env)->GetObjectClass(env, intent);
+ imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
+ // Watch out for C89 scoping rules because of the macro
+#define GET_INT_EXTRA(var, key) \
+ int var; \
+ iname = (*env)->NewStringUTF(env, key); \
+ var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
+ (*env)->DeleteLocalRef(env, iname);
+ bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
+ // Watch out for C89 scoping rules because of the macro
+#define GET_BOOL_EXTRA(var, key) \
+ int var; \
+ bname = (*env)->NewStringUTF(env, key); \
+ var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
+ (*env)->DeleteLocalRef(env, bname);
+ if (plugged) {
+ // Watch out for C89 scoping rules because of the macro
+ GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5)
+ if (plug == -1) {
+ LocalReferenceHolder_Cleanup(&refs);
+ return -1;
+ }
+ // 1 == BatteryManager.BATTERY_PLUGGED_AC
+ // 2 == BatteryManager.BATTERY_PLUGGED_USB
+ *plugged = (0 < plug) ? 1 : 0;
+ }
+ if (charged) {
+ // Watch out for C89 scoping rules because of the macro
+ GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5)
+ if (status == -1) {
+ LocalReferenceHolder_Cleanup(&refs);
+ return -1;
+ }
+ // 5 == BatteryManager.BATTERY_STATUS_FULL
+ *charged = (status == 5) ? 1 : 0;
+ }
+ if (battery) {
+ GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5)
+ *battery = present ? 1 : 0;
+ }
+ if (seconds) {
+ *seconds = -1; // not possible
+ }
+ if (percent) {
+ int level;
+ int scale;
+ // Watch out for C89 scoping rules because of the macro
+ {
+ GET_INT_EXTRA(level_temp, "level") // == BatteryManager.EXTRA_LEVEL (API 5)
+ level = level_temp;
+ }
+ // Watch out for C89 scoping rules because of the macro
+ {
+ GET_INT_EXTRA(scale_temp, "scale") // == BatteryManager.EXTRA_SCALE (API 5)
+ scale = scale_temp;
+ }
+ if ((level == -1) || (scale == -1)) {
+ LocalReferenceHolder_Cleanup(&refs);
+ return -1;
+ }
+ *percent = level * 100 / scale;
+ }
+ (*env)->DeleteLocalRef(env, intent);
+ LocalReferenceHolder_Cleanup(&refs);
+
+ return 0;
+}
+
+
+bool power_android::GetPowerInfo_Android() {
+ int battery;
+ int plugged;
+ int charged;
+
+ if (Android_JNI_GetPowerInfo(&plugged, &charged, &battery, &this->nsecs_left, &this->percent_left) != -1) {
+ if (plugged) {
+ if (charged) {
+ this->power_state = POWERSTATE_CHARGED;
+ } else if (battery) {
+ this->power_state = POWERSTATE_CHARGING;
+ } else {
+ this->power_state = POWERSTATE_NO_BATTERY;
+ this->nsecs_left = -1;
+ this->percent_left = -1;
+ }
+ } else {
+ this->power_state = POWERSTATE_ON_BATTERY;
+ }
+ } else {
+ this->power_state = POWERSTATE_UNKNOWN;
+ this->nsecs_left = -1;
+ this->percent_left = -1;
+ }
+
+ return true;
+}
+
+PowerState power_android::get_power_state() {
+ if (GetPowerInfo_Android()) {
+ return power_state;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN");
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int power_android::get_power_seconds_left() {
+ if (GetPowerInfo_Android()) {
+ return nsecs_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+int power_android::get_power_percent_left() {
+ if (GetPowerInfo_Android()) {
+ return percent_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+power_android::power_android() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+
+}
+
+power_android::~power_android() {
+}
diff --git a/platform/android/power_android.h b/platform/android/power_android.h
new file mode 100644
index 0000000000..c59bdf3888
--- /dev/null
+++ b/platform/android/power_android.h
@@ -0,0 +1,82 @@
+/*************************************************************************/
+/* power_android.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PLATFORM_ANDROID_POWER_ANDROID_H_
+#define PLATFORM_ANDROID_POWER_ANDROID_H_
+
+#include "os/power.h"
+#include <android/native_window_jni.h>
+
+class power_android {
+
+struct LocalReferenceHolder
+{
+ JNIEnv *m_env;
+ const char *m_func;
+};
+
+private:
+ static struct LocalReferenceHolder refs;
+ static JNIEnv* env;
+ static jmethodID mid;
+ static jobject context;
+ static jstring action;
+ static jclass cls;
+ static jobject filter;
+ static jobject intent;
+ static jstring iname;
+ static jmethodID imid;
+ static jstring bname;
+ static jmethodID bmid;
+
+
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+ bool GetPowerInfo_Android();
+ bool UpdatePowerInfo();
+
+public:
+
+ static int s_active;
+
+
+ power_android();
+ virtual ~power_android();
+ static bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env);
+ static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func);
+ static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder);
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_ANDROID_POWER_ANDROID_H_ */
diff --git a/platform/bb10/export/export.cpp b/platform/bb10/export/export.cpp
index 3e6dadb094..cf8e2fcc0a 100644
--- a/platform/bb10/export/export.cpp
+++ b/platform/bb10/export/export.cpp
@@ -28,12 +28,12 @@
/*************************************************************************/
#include "version.h"
#include "export.h"
-#include "tools/editor/editor_settings.h"
-#include "tools/editor/editor_import_export.h"
-#include "tools/editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_export.h"
+#include "editor/editor_node.h"
#include "io/zip_io.h"
#include "io/marshalls.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
#include "os/os.h"
#include "platform/bb10/logo.h"
@@ -803,9 +803,9 @@ EditorExportPlatformBB10::~EditorExportPlatformBB10() {
memdelete(device_thread);
}
-
+#endif
void register_bb10_exporter() {
-
+#if 0
EDITOR_DEF("export/blackberry/host_tools","");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"export/blackberry/host_tools",PROPERTY_HINT_GLOBAL_DIR));
EDITOR_DEF("export/blackberry/debug_token","");
@@ -824,7 +824,7 @@ void register_bb10_exporter() {
Ref<EditorExportPlatformBB10> exporter = Ref<EditorExportPlatformBB10>( memnew(EditorExportPlatformBB10) );
EditorImportExport::get_singleton()->add_export_platform(exporter);
-
+#endif
}
-#endif
+
diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp
index c51f1c6092..bf7bfb6909 100644
--- a/platform/bb10/os_bb10.cpp
+++ b/platform/bb10/os_bb10.cpp
@@ -31,7 +31,7 @@
#include "drivers/gles2/rasterizer_gles2.h"
#include "servers/visual/visual_server_raster.h"
#include "core/os/dir_access.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#include "main/main.h"
#include "bbutil.h"
#include "core/os/keyboard.h"
@@ -146,6 +146,8 @@ void OSBB10::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
physics_2d_server->init();
input = memnew( InputDefault );
+
+ power_manager = memnew( PowerBB10 );
#ifdef PAYMENT_SERVICE_ENABLED
payment_service = memnew(PaymentService);
@@ -587,6 +589,18 @@ Size2 OSBB10::get_window_size() const {
return Vector2(default_videomode.width, default_videomode.height);
}
+PowerState OSBB10::get_power_state() {
+ return power_manager->get_power_state();
+}
+
+int OSBB10::get_power_seconds_left() {
+ return power_manager->get_power_seconds_left();
+}
+
+int OSBB10::get_power_percent_left() {
+ return power_manager->get_power_percent_left();
+}
+
OSBB10::OSBB10() {
main_loop=NULL;
diff --git a/platform/bb10/os_bb10.h b/platform/bb10/os_bb10.h
index 9cf2091d49..678b8c9fc2 100644
--- a/platform/bb10/os_bb10.h
+++ b/platform/bb10/os_bb10.h
@@ -39,6 +39,7 @@
#include "servers/visual/rasterizer.h"
#include "audio_driver_bb10.h"
#include "payment_service.h"
+#include "power_bb10.h"
#include <screen/screen.h>
#include <sys/platform.h>
@@ -58,6 +59,7 @@ class OSBB10 : public OS_Unix {
PhysicsServer *physics_server;
Physics2DServer *physics_2d_server;
AudioDriverBB10* audio_driver;
+ PowerBB10 *power_manager;
#ifdef PAYMENT_SERVICE_ENABLED
PaymentService* payment_service;
@@ -142,6 +144,10 @@ public:
void run();
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
+
OSBB10();
~OSBB10();
diff --git a/platform/bb10/payment_service.cpp b/platform/bb10/payment_service.cpp
index 3138dc2c1d..131c9712a5 100644
--- a/platform/bb10/payment_service.cpp
+++ b/platform/bb10/payment_service.cpp
@@ -38,11 +38,11 @@ extern char* launch_dir_ptr;
void PaymentService::_bind_methods() {
- ClassDB::bind_method(_MD("request_product_info"),&PaymentService::request_product_info);
- ClassDB::bind_method(_MD("purchase"),&PaymentService::purchase);
+ ClassDB::bind_method(D_METHOD("request_product_info"),&PaymentService::request_product_info);
+ ClassDB::bind_method(D_METHOD("purchase"),&PaymentService::purchase);
- ClassDB::bind_method(_MD("get_pending_event_count"),&PaymentService::get_pending_event_count);
- ClassDB::bind_method(_MD("pop_pending_event"),&PaymentService::pop_pending_event);
+ ClassDB::bind_method(D_METHOD("get_pending_event_count"),&PaymentService::get_pending_event_count);
+ ClassDB::bind_method(D_METHOD("pop_pending_event"),&PaymentService::pop_pending_event);
};
Error PaymentService::request_product_info(Variant p_params) {
diff --git a/platform/bb10/power_bb10.cpp b/platform/bb10/power_bb10.cpp
new file mode 100644
index 0000000000..5cd84d6246
--- /dev/null
+++ b/platform/bb10/power_bb10.cpp
@@ -0,0 +1,76 @@
+/*************************************************************************/
+/* power_bb10.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "power_bb10.h"
+
+#include "core/error_macros.h"
+
+
+bool PowerBB10::UpdatePowerInfo() {
+
+ return false;
+}
+
+PowerState PowerBB10::get_power_state() {
+ if (UpdatePowerInfo()) {
+ return power_state;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN");
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int PowerBB10::get_power_seconds_left() {
+ if (UpdatePowerInfo()) {
+ return nsecs_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+int PowerBB10::get_power_percent_left() {
+ if (UpdatePowerInfo()) {
+ return percent_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+PowerBB10::PowerBB10() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+
+}
+
+PowerBB10::~PowerBB10() {
+}
+
diff --git a/platform/bb10/power_bb10.h b/platform/bb10/power_bb10.h
new file mode 100644
index 0000000000..0e6eb53d03
--- /dev/null
+++ b/platform/bb10/power_bb10.h
@@ -0,0 +1,49 @@
+/*************************************************************************/
+/* power_bb10.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PLATFORM_BB10_POWER_BB10_H_
+#define PLATFORM_BB10_POWER_BB10_H_
+
+class PowerBB10 {
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+ bool UpdatePowerInfo();
+public:
+ PowerBB10();
+ virtual ~PowerBB10();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_BB10_POWER_BB10_H_ */
diff --git a/platform/haiku/audio_driver_media_kit.cpp b/platform/haiku/audio_driver_media_kit.cpp
index c6afe7a261..bd485214c8 100644
--- a/platform/haiku/audio_driver_media_kit.cpp
+++ b/platform/haiku/audio_driver_media_kit.cpp
@@ -30,7 +30,7 @@
#ifdef MEDIA_KIT_ENABLED
-#include "globals.h"
+#include "global_config.h"
int32_t* AudioDriverMediaKit::samples_in = NULL;
diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp
index 9f218aeff4..b9b95ddacd 100644
--- a/platform/haiku/os_haiku.cpp
+++ b/platform/haiku/os_haiku.cpp
@@ -143,6 +143,8 @@ void OS_Haiku::initialize(const VideoMode& p_desired, int p_video_driver, int p_
if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
ERR_PRINT("Initializing audio failed.");
}
+
+ power_manager = memnew( PowerHaiku );
}
void OS_Haiku::finalize() {
diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h
index 531c7a56c3..2c84e95ac3 100644
--- a/platform/haiku/os_haiku.h
+++ b/platform/haiku/os_haiku.h
@@ -40,6 +40,7 @@
#include "context_gl_haiku.h"
#include "haiku_application.h"
#include "haiku_direct_window.h"
+#include "power_haiku.h"
class OS_Haiku : public OS_Unix {
@@ -53,6 +54,7 @@ private:
VideoMode current_video_mode;
PhysicsServer* physics_server;
Physics2DServer* physics_2d_server;
+ PowerHaiku* power_manager;
#ifdef MEDIA_KIT_ENABLED
AudioDriverMediaKit driver_media_kit;
@@ -114,6 +116,10 @@ public:
virtual VideoMode get_video_mode(int p_screen=0) const;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen=0) const;
virtual String get_executable_path() const;
+
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
};
#endif
diff --git a/platform/haiku/power_haiku.cpp b/platform/haiku/power_haiku.cpp
new file mode 100644
index 0000000000..6a54c7b360
--- /dev/null
+++ b/platform/haiku/power_haiku.cpp
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* power_haiku.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "core/error_macros.h"
+
+#include "power_haiku.h"
+
+bool PowerHaiku::UpdatePowerInfo() {
+
+ return false;
+}
+
+PowerState PowerHaiku::get_power_state() {
+ if (UpdatePowerInfo()) {
+ return power_state;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN");
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int PowerX11::get_power_seconds_left() {
+ if (UpdatePowerInfo()) {
+ return nsecs_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+int PowerX11::get_power_percent_left() {
+ if (UpdatePowerInfo()) {
+ return percent_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+PowerHaiku::PowerHaiku() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+
+}
+
+PowerHaiku::~PowerHaiku() {
+}
diff --git a/platform/haiku/power_haiku.h b/platform/haiku/power_haiku.h
new file mode 100644
index 0000000000..b46cfa3454
--- /dev/null
+++ b/platform/haiku/power_haiku.h
@@ -0,0 +1,49 @@
+/*************************************************************************/
+/* power_haiku.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PLATFORM_HAIKU_POWER_HAIKU_H_
+#define PLATFORM_HAIKU_POWER_HAIKU_H_
+
+class PowerHaiku {
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+ bool UpdatePowerInfo();
+public:
+ PowerHaiku();
+ virtual ~PowerHaiku();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_HAIKU_POWER_HAIKU_H_ */
diff --git a/platform/iphone/Appirater.h b/platform/iphone/Appirater.h
deleted file mode 100644
index 96dd30e7c7..0000000000
--- a/platform/iphone/Appirater.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- This file is part of Appirater.
-
- Copyright (c) 2010, Arash Payan
- All rights reserved.
-
- 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.
- */
-/*
- * Appirater.h
- * appirater
- *
- * Created by Arash Payan on 9/5/09.
- * http://arashpayan.com
- * Copyright 2010 Arash Payan. All rights reserved.
- */
-
-#import <Foundation/Foundation.h>
-#import <UIKit/UIKit.h>
-
-extern NSString *const kAppiraterFirstUseDate;
-extern NSString *const kAppiraterUseCount;
-extern NSString *const kAppiraterSignificantEventCount;
-extern NSString *const kAppiraterCurrentVersion;
-extern NSString *const kAppiraterRatedCurrentVersion;
-extern NSString *const kAppiraterDeclinedToRate;
-
-/*
- Place your Apple generated software id here.
- */
-#define APPIRATER_APP_ID 301377083
-
-/*
- Your app's name.
- */
-#define APPIRATER_APP_NAME [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]
-
-/*
- This is the message your users will see once they've passed the day+launches
- threshold.
- */
-#define APPIRATER_MESSAGE [NSString stringWithFormat:@"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!", APPIRATER_APP_NAME]
-
-/*
- This is the title of the message alert that users will see.
- */
-#define APPIRATER_MESSAGE_TITLE [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME]
-
-/*
- The text of the button that rejects reviewing the app.
- */
-#define APPIRATER_CANCEL_BUTTON @"No, Thanks"
-
-/*
- Text of button that will send user to app review page.
- */
-#define APPIRATER_RATE_BUTTON [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME]
-
-/*
- Text for button to remind the user to review later.
- */
-#define APPIRATER_RATE_LATER @"Remind me later"
-
-/*
- Users will need to have the same version of your app installed for this many
- days before they will be prompted to rate it.
- */
-#define APPIRATER_DAYS_UNTIL_PROMPT 30 // double
-
-/*
- An example of a 'use' would be if the user launched the app. Bringing the app
- into the foreground (on devices that support it) would also be considered
- a 'use'. You tell Appirater about these events using the two methods:
- [Appirater appLaunched:]
- [Appirater appEnteredForeground:]
-
- Users need to 'use' the same version of the app this many times before
- before they will be prompted to rate it.
- */
-#define APPIRATER_USES_UNTIL_PROMPT 20 // integer
-
-/*
- A significant event can be anything you want to be in your app. In a
- telephone app, a significant event might be placing or receiving a call.
- In a game, it might be beating a level or a boss. This is just another
- layer of filtering that can be used to make sure that only the most
- loyal of your users are being prompted to rate you on the app store.
- If you leave this at a value of -1, then this won't be a criteria
- used for rating. To tell Appirater that the user has performed
- a significant event, call the method:
- [Appirater userDidSignificantEvent:];
- */
-#define APPIRATER_SIG_EVENTS_UNTIL_PROMPT -1 // integer
-
-/*
- Once the rating alert is presented to the user, they might select
- 'Remind me later'. This value specifies how long (in days) Appirater
- will wait before reminding them.
- */
-#define APPIRATER_TIME_BEFORE_REMINDING 1 // double
-
-/*
- 'YES' will show the Appirater alert everytime. Useful for testing how your message
- looks and making sure the link to your app's review page works.
- */
-#define APPIRATER_DEBUG NO
-
-@interface Appirater : NSObject <UIAlertViewDelegate> {
-
- UIAlertView *ratingAlert;
-}
-
-@property(nonatomic, retain) UIAlertView *ratingAlert;
-
-/*
- DEPRECATED: While still functional, it's better to use
- appLaunched:(BOOL)canPromptForRating instead.
-
- Calls [Appirater appLaunched:YES]. See appLaunched: for details of functionality.
- */
-+ (void)appLaunched:(int)p_app_id;
-
-/*
- Tells Appirater that the app has launched, and on devices that do NOT
- support multitasking, the 'uses' count will be incremented. You should
- call this method at the end of your application delegate's
- application:didFinishLaunchingWithOptions: method.
-
- If the app has been used enough to be rated (and enough significant events),
- you can suppress the rating alert
- by passing NO for canPromptForRating. The rating alert will simply be postponed
- until it is called again with YES for canPromptForRating. The rating alert
- can also be triggered by appEnteredForeground: and userDidSignificantEvent:
- (as long as you pass YES for canPromptForRating in those methods).
- */
-+ (void)appLaunched:(BOOL)canPromptForRating app_id:(int)p_app_id;
-
-/*
- Tells Appirater that the app was brought to the foreground on multitasking
- devices. You should call this method from the application delegate's
- applicationWillEnterForeground: method.
-
- If the app has been used enough to be rated (and enough significant events),
- you can suppress the rating alert
- by passing NO for canPromptForRating. The rating alert will simply be postponed
- until it is called again with YES for canPromptForRating. The rating alert
- can also be triggered by appLaunched: and userDidSignificantEvent:
- (as long as you pass YES for canPromptForRating in those methods).
- */
-+ (void)appEnteredForeground:(BOOL)canPromptForRating;
-
-/*
- Tells Appirater that the user performed a significant event. A significant
- event is whatever you want it to be. If you're app is used to make VoIP
- calls, then you might want to call this method whenever the user places
- a call. If it's a game, you might want to call this whenever the user
- beats a level boss.
-
- If the user has performed enough significant events and used the app enough,
- you can suppress the rating alert by passing NO for canPromptForRating. The
- rating alert will simply be postponed until it is called again with YES for
- canPromptForRating. The rating alert can also be triggered by appLaunched:
- and appEnteredForeground: (as long as you pass YES for canPromptForRating
- in those methods).
- */
-+ (void)userDidSignificantEvent:(BOOL)canPromptForRating;
-
-/*
- Tells Appirater to open the App Store page where the user can specify a
- rating for the app. Also records the fact that this has happened, so the
- user won't be prompted again to rate the app.
-
- The only case where you should call this directly is if your app has an
- explicit "Rate this app" command somewhere. In all other cases, don't worry
- about calling this -- instead, just call the other functions listed above,
- and let Appirater handle the bookkeeping of deciding when to ask the user
- whether to rate the app.
- */
-+ (void)rateApp;
-
-@end
diff --git a/platform/iphone/Appirater.m b/platform/iphone/Appirater.m
deleted file mode 100644
index 951b892032..0000000000
--- a/platform/iphone/Appirater.m
+++ /dev/null
@@ -1,732 +0,0 @@
-/*
- This file is part of Appirater.
-
- Copyright (c) 2012, Arash Payan
- All rights reserved.
-
- 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.
- */
-/*
- * Appirater.m
- * appirater
- *
- * Created by Arash Payan on 9/5/09.
- * http://arashpayan.com
- * Copyright 2012 Arash Payan. All rights reserved.
- */
-
-#import "Appirater.h"
-#import <SystemConfiguration/SCNetworkReachability.h>
-#include <netinet/in.h>
-
-#if ! __has_feature(objc_arc)
-#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
-#endif
-
-NSString *const kAppiraterFirstUseDate = @"kAppiraterFirstUseDate";
-NSString *const kAppiraterUseCount = @"kAppiraterUseCount";
-NSString *const kAppiraterSignificantEventCount = @"kAppiraterSignificantEventCount";
-NSString *const kAppiraterCurrentVersion = @"kAppiraterCurrentVersion";
-NSString *const kAppiraterRatedCurrentVersion = @"kAppiraterRatedCurrentVersion";
-NSString *const kAppiraterDeclinedToRate = @"kAppiraterDeclinedToRate";
-NSString *const kAppiraterReminderRequestDate = @"kAppiraterReminderRequestDate";
-
-NSString *templateReviewURL = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID";
-NSString *templateReviewURLiOS7 = @"itms-apps://itunes.apple.com/app/idAPP_ID";
-NSString *templateReviewURLiOS8 = @"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APP_ID&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software";
-
-static NSString *_appId;
-static double _daysUntilPrompt = 30;
-static NSInteger _usesUntilPrompt = 20;
-static NSInteger _significantEventsUntilPrompt = -1;
-static double _timeBeforeReminding = 1;
-static BOOL _debug = NO;
-#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0
- static id<AppiraterDelegate> _delegate;
-#else
- __weak static id<AppiraterDelegate> _delegate;
-#endif
-static BOOL _usesAnimation = TRUE;
-static UIStatusBarStyle _statusBarStyle;
-static BOOL _modalOpen = false;
-static BOOL _alwaysUseMainBundle = NO;
-
-@interface Appirater ()
-@property (nonatomic, copy) NSString *alertTitle;
-@property (nonatomic, copy) NSString *alertMessage;
-@property (nonatomic, copy) NSString *alertCancelTitle;
-@property (nonatomic, copy) NSString *alertRateTitle;
-@property (nonatomic, copy) NSString *alertRateLaterTitle;
-- (BOOL)connectedToNetwork;
-+ (Appirater*)sharedInstance;
-- (void)showPromptWithChecks:(BOOL)withChecks
- displayRateLaterButton:(BOOL)displayRateLaterButton;
-- (void)showRatingAlert:(BOOL)displayRateLaterButton;
-- (void)showRatingAlert;
-- (BOOL)ratingAlertIsAppropriate;
-- (BOOL)ratingConditionsHaveBeenMet;
-- (void)incrementUseCount;
-- (void)hideRatingAlert;
-@end
-
-@implementation Appirater
-
-@synthesize ratingAlert;
-
-+ (void) setAppId:(NSString *)appId {
- _appId = appId;
-}
-
-+ (void) setDaysUntilPrompt:(double)value {
- _daysUntilPrompt = value;
-}
-
-+ (void) setUsesUntilPrompt:(NSInteger)value {
- _usesUntilPrompt = value;
-}
-
-+ (void) setSignificantEventsUntilPrompt:(NSInteger)value {
- _significantEventsUntilPrompt = value;
-}
-
-+ (void) setTimeBeforeReminding:(double)value {
- _timeBeforeReminding = value;
-}
-
-+ (void) setCustomAlertTitle:(NSString *)title
-{
- [self sharedInstance].alertTitle = title;
-}
-
-+ (void) setCustomAlertMessage:(NSString *)message
-{
- [self sharedInstance].alertMessage = message;
-}
-
-+ (void) setCustomAlertCancelButtonTitle:(NSString *)cancelTitle
-{
- [self sharedInstance].alertCancelTitle = cancelTitle;
-}
-
-+ (void) setCustomAlertRateButtonTitle:(NSString *)rateTitle
-{
- [self sharedInstance].alertRateTitle = rateTitle;
-}
-
-+ (void) setCustomAlertRateLaterButtonTitle:(NSString *)rateLaterTitle
-{
- [self sharedInstance].alertRateLaterTitle = rateLaterTitle;
-}
-
-+ (void) setDebug:(BOOL)debug {
- _debug = debug;
-}
-+ (void)setDelegate:(id<AppiraterDelegate>)delegate{
- _delegate = delegate;
-}
-+ (void)setUsesAnimation:(BOOL)animation {
- _usesAnimation = animation;
-}
-+ (void)setOpenInAppStore:(BOOL)openInAppStore {
- [Appirater sharedInstance].openInAppStore = openInAppStore;
-}
-+ (void)setStatusBarStyle:(UIStatusBarStyle)style {
- _statusBarStyle = style;
-}
-+ (void)setModalOpen:(BOOL)open {
- _modalOpen = open;
-}
-+ (void)setAlwaysUseMainBundle:(BOOL)alwaysUseMainBundle {
- _alwaysUseMainBundle = alwaysUseMainBundle;
-}
-
-+ (NSBundle *)bundle
-{
- NSBundle *bundle;
-
- if (_alwaysUseMainBundle) {
- bundle = [NSBundle mainBundle];
- } else {
- NSURL *appiraterBundleURL = [[NSBundle mainBundle] URLForResource:@"Appirater" withExtension:@"bundle"];
-
- if (appiraterBundleURL) {
- // Appirater.bundle will likely only exist when used via CocoaPods
- bundle = [NSBundle bundleWithURL:appiraterBundleURL];
- } else {
- bundle = [NSBundle mainBundle];
- }
- }
-
- return bundle;
-}
-
-- (NSString *)alertTitle
-{
- return _alertTitle ? _alertTitle : APPIRATER_MESSAGE_TITLE;
-}
-
-- (NSString *)alertMessage
-{
- return _alertMessage ? _alertMessage : APPIRATER_MESSAGE;
-}
-
-- (NSString *)alertCancelTitle
-{
- return _alertCancelTitle ? _alertCancelTitle : APPIRATER_CANCEL_BUTTON;
-}
-
-- (NSString *)alertRateTitle
-{
- return _alertRateTitle ? _alertRateTitle : APPIRATER_RATE_BUTTON;
-}
-
-- (NSString *)alertRateLaterTitle
-{
- return _alertRateLaterTitle ? _alertRateLaterTitle : APPIRATER_RATE_LATER;
-}
-
-- (void)dealloc {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
-}
-
-- (id)init {
- self = [super init];
- if (self) {
- if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) {
- self.openInAppStore = YES;
- } else {
- self.openInAppStore = NO;
- }
- }
-
- return self;
-}
-
-- (BOOL)connectedToNetwork {
- // Create zero addy
- struct sockaddr_in zeroAddress;
- bzero(&zeroAddress, sizeof(zeroAddress));
- zeroAddress.sin_len = sizeof(zeroAddress);
- zeroAddress.sin_family = AF_INET;
-
- // Recover reachability flags
- SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
- SCNetworkReachabilityFlags flags;
-
- Boolean didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
- CFRelease(defaultRouteReachability);
-
- if (!didRetrieveFlags)
- {
- NSLog(@"Error. Could not recover network reachability flags");
- return NO;
- }
-
- BOOL isReachable = flags & kSCNetworkFlagsReachable;
- BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
- BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;
-
- NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"];
- NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
- NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self];
-
- return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;
-}
-
-+ (Appirater*)sharedInstance {
- static Appirater *appirater = nil;
- if (appirater == nil)
- {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- appirater = [[Appirater alloc] init];
- appirater.delegate = _delegate;
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive) name:
- UIApplicationWillResignActiveNotification object:nil];
- });
- }
-
- return appirater;
-}
-
-- (void)showRatingAlert:(BOOL)displayRateLaterButton {
- UIAlertView *alertView = nil;
- id <AppiraterDelegate> delegate = _delegate;
-
- if(delegate && [delegate respondsToSelector:@selector(appiraterShouldDisplayAlert:)] && ![delegate appiraterShouldDisplayAlert:self]) {
- return;
- }
-
- if (displayRateLaterButton) {
- alertView = [[UIAlertView alloc] initWithTitle:self.alertTitle
- message:self.alertMessage
- delegate:self
- cancelButtonTitle:self.alertCancelTitle
- otherButtonTitles:self.alertRateTitle, self.alertRateLaterTitle, nil];
- } else {
- alertView = [[UIAlertView alloc] initWithTitle:self.alertTitle
- message:self.alertMessage
- delegate:self
- cancelButtonTitle:self.alertCancelTitle
- otherButtonTitles:self.alertRateTitle, nil];
- }
-
- self.ratingAlert = alertView;
- [alertView show];
-
- if (delegate && [delegate respondsToSelector:@selector(appiraterDidDisplayAlert:)]) {
- [delegate appiraterDidDisplayAlert:self];
- }
-}
-
-- (void)showRatingAlert
-{
- [self showRatingAlert:true];
-}
-
-// is this an ok time to show the alert? (regardless of whether the rating conditions have been met)
-//
-// things checked here:
-// * connectivity with network
-// * whether user has rated before
-// * whether user has declined to rate
-// * whether rating alert is currently showing visibly
-// things NOT checked here:
-// * time since first launch
-// * number of uses of app
-// * number of significant events
-// * time since last reminder
-- (BOOL)ratingAlertIsAppropriate {
- return ([self connectedToNetwork]
- && ![self userHasDeclinedToRate]
- && !self.ratingAlert.visible
- && ![self userHasRatedCurrentVersion]);
-}
-
-// have the rating conditions been met/earned? (regardless of whether this would be a moment when it's appropriate to show a new rating alert)
-//
-// things checked here:
-// * time since first launch
-// * number of uses of app
-// * number of significant events
-// * time since last reminder
-// things NOT checked here:
-// * connectivity with network
-// * whether user has rated before
-// * whether user has declined to rate
-// * whether rating alert is currently showing visibly
-- (BOOL)ratingConditionsHaveBeenMet {
- if (_debug)
- return YES;
-
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
-
- NSDate *dateOfFirstLaunch = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterFirstUseDate]];
- NSTimeInterval timeSinceFirstLaunch = [[NSDate date] timeIntervalSinceDate:dateOfFirstLaunch];
- NSTimeInterval timeUntilRate = 60 * 60 * 24 * _daysUntilPrompt;
- if (timeSinceFirstLaunch < timeUntilRate)
- return NO;
-
- // check if the app has been used enough
- NSInteger useCount = [userDefaults integerForKey:kAppiraterUseCount];
- if (useCount < _usesUntilPrompt)
- return NO;
-
- // check if the user has done enough significant events
- NSInteger sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount];
- if (sigEventCount < _significantEventsUntilPrompt)
- return NO;
-
- // if the user wanted to be reminded later, has enough time passed?
- NSDate *reminderRequestDate = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterReminderRequestDate]];
- NSTimeInterval timeSinceReminderRequest = [[NSDate date] timeIntervalSinceDate:reminderRequestDate];
- NSTimeInterval timeUntilReminder = 60 * 60 * 24 * _timeBeforeReminding;
- if (timeSinceReminderRequest < timeUntilReminder)
- return NO;
-
- return YES;
-}
-
-- (void)incrementUseCount {
- // get the app's version
- NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey];
-
- // get the version number that we've been tracking
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion];
- if (trackingVersion == nil)
- {
- trackingVersion = version;
- [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
- }
-
- if (_debug)
- NSLog(@"APPIRATER Tracking version: %@", trackingVersion);
-
- if ([trackingVersion isEqualToString:version])
- {
- // check if the first use date has been set. if not, set it.
- NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate];
- if (timeInterval == 0)
- {
- timeInterval = [[NSDate date] timeIntervalSince1970];
- [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate];
- }
-
- // increment the use count
- NSInteger useCount = [userDefaults integerForKey:kAppiraterUseCount];
- useCount++;
- [userDefaults setInteger:useCount forKey:kAppiraterUseCount];
- if (_debug)
- NSLog(@"APPIRATER Use count: %@", @(useCount));
- }
- else
- {
- // it's a new version of the app, so restart tracking
- [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
- [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterFirstUseDate];
- [userDefaults setInteger:1 forKey:kAppiraterUseCount];
- [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount];
- [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion];
- [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate];
- [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate];
- }
-
- [userDefaults synchronize];
-}
-
-- (void)incrementSignificantEventCount {
- // get the app's version
- NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey];
-
- // get the version number that we've been tracking
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion];
- if (trackingVersion == nil)
- {
- trackingVersion = version;
- [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
- }
-
- if (_debug)
- NSLog(@"APPIRATER Tracking version: %@", trackingVersion);
-
- if ([trackingVersion isEqualToString:version])
- {
- // check if the first use date has been set. if not, set it.
- NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate];
- if (timeInterval == 0)
- {
- timeInterval = [[NSDate date] timeIntervalSince1970];
- [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate];
- }
-
- // increment the significant event count
- NSInteger sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount];
- sigEventCount++;
- [userDefaults setInteger:sigEventCount forKey:kAppiraterSignificantEventCount];
- if (_debug)
- NSLog(@"APPIRATER Significant event count: %@", @(sigEventCount));
- }
- else
- {
- // it's a new version of the app, so restart tracking
- [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
- [userDefaults setDouble:0 forKey:kAppiraterFirstUseDate];
- [userDefaults setInteger:0 forKey:kAppiraterUseCount];
- [userDefaults setInteger:1 forKey:kAppiraterSignificantEventCount];
- [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion];
- [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate];
- [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate];
- }
-
- [userDefaults synchronize];
-}
-
-- (void)incrementAndRate:(BOOL)canPromptForRating {
- [self incrementUseCount];
-
- if (canPromptForRating &&
- [self ratingConditionsHaveBeenMet] &&
- [self ratingAlertIsAppropriate])
- {
- dispatch_async(dispatch_get_main_queue(),
- ^{
- [self showRatingAlert];
- });
- }
-}
-
-- (void)incrementSignificantEventAndRate:(BOOL)canPromptForRating {
- [self incrementSignificantEventCount];
-
- if (canPromptForRating &&
- [self ratingConditionsHaveBeenMet] &&
- [self ratingAlertIsAppropriate])
- {
- dispatch_async(dispatch_get_main_queue(),
- ^{
- [self showRatingAlert];
- });
- }
-}
-
-- (BOOL)userHasDeclinedToRate {
- return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterDeclinedToRate];
-}
-
-- (BOOL)userHasRatedCurrentVersion {
- return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterRatedCurrentVersion];
-}
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
-+ (void)appLaunched {
- [Appirater appLaunched:YES];
-}
-#pragma GCC diagnostic pop
-
-+ (void)appLaunched:(BOOL)canPromptForRating {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
- ^{
- Appirater *a = [Appirater sharedInstance];
- if (_debug) {
- dispatch_async(dispatch_get_main_queue(),
- ^{
- [a showRatingAlert];
- });
- } else {
- [a incrementAndRate:canPromptForRating];
- }
- });
-}
-
-- (void)hideRatingAlert {
- if (self.ratingAlert.visible) {
- if (_debug)
- NSLog(@"APPIRATER Hiding Alert");
- [self.ratingAlert dismissWithClickedButtonIndex:-1 animated:NO];
- }
-}
-
-+ (void)appWillResignActive {
- if (_debug)
- NSLog(@"APPIRATER appWillResignActive");
- [[Appirater sharedInstance] hideRatingAlert];
-}
-
-+ (void)appEnteredForeground:(BOOL)canPromptForRating {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
- ^{
- [[Appirater sharedInstance] incrementAndRate:canPromptForRating];
- });
-}
-
-+ (void)userDidSignificantEvent:(BOOL)canPromptForRating {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
- ^{
- [[Appirater sharedInstance] incrementSignificantEventAndRate:canPromptForRating];
- });
-}
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
-+ (void)showPrompt {
- [Appirater tryToShowPrompt];
-}
-#pragma GCC diagnostic pop
-
-+ (void)tryToShowPrompt {
- [[Appirater sharedInstance] showPromptWithChecks:true
- displayRateLaterButton:true];
-}
-
-+ (void)forceShowPrompt:(BOOL)displayRateLaterButton {
- [[Appirater sharedInstance] showPromptWithChecks:false
- displayRateLaterButton:displayRateLaterButton];
-}
-
-- (void)showPromptWithChecks:(BOOL)withChecks
- displayRateLaterButton:(BOOL)displayRateLaterButton {
- if (withChecks == NO || [self ratingAlertIsAppropriate]) {
- [self showRatingAlert:displayRateLaterButton];
- }
-}
-
-+ (id)getRootViewController {
- UIWindow *window = [[UIApplication sharedApplication] keyWindow];
- if (window.windowLevel != UIWindowLevelNormal) {
- NSArray *windows = [[UIApplication sharedApplication] windows];
- for(window in windows) {
- if (window.windowLevel == UIWindowLevelNormal) {
- break;
- }
- }
- }
-
- return [Appirater iterateSubViewsForViewController:window]; // iOS 8+ deep traverse
-}
-
-+ (id)iterateSubViewsForViewController:(UIView *) parentView {
- for (UIView *subView in [parentView subviews]) {
- UIResponder *responder = [subView nextResponder];
- if([responder isKindOfClass:[UIViewController class]]) {
- return [self topMostViewController: (UIViewController *) responder];
- }
- id found = [Appirater iterateSubViewsForViewController:subView];
- if( nil != found) {
- return found;
- }
- }
- return nil;
-}
-
-+ (UIViewController *) topMostViewController: (UIViewController *) controller {
- BOOL isPresenting = NO;
- do {
- // this path is called only on iOS 6+, so -presentedViewController is fine here.
- UIViewController *presented = [controller presentedViewController];
- isPresenting = presented != nil;
- if(presented != nil) {
- controller = presented;
- }
-
- } while (isPresenting);
-
- return controller;
-}
-
-+ (void)rateApp {
-
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion];
- [userDefaults synchronize];
-
- //Use the in-app StoreKit view if available (iOS 6) and imported. This works in the simulator.
- if (![Appirater sharedInstance].openInAppStore && NSStringFromClass([SKStoreProductViewController class]) != nil) {
-
- SKStoreProductViewController *storeViewController = [[SKStoreProductViewController alloc] init];
- NSNumber *appId = [NSNumber numberWithInteger:_appId.integerValue];
- [storeViewController loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier:appId} completionBlock:nil];
- storeViewController.delegate = self.sharedInstance;
-
- id <AppiraterDelegate> delegate = self.sharedInstance.delegate;
- if ([delegate respondsToSelector:@selector(appiraterWillPresentModalView:animated:)]) {
- [delegate appiraterWillPresentModalView:self.sharedInstance animated:_usesAnimation];
- }
- [[self getRootViewController] presentViewController:storeViewController animated:_usesAnimation completion:^{
- [self setModalOpen:YES];
- //Temporarily use a black status bar to match the StoreKit view.
- [self setStatusBarStyle:[UIApplication sharedApplication].statusBarStyle];
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
- [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent animated:_usesAnimation];
-#endif
- }];
-
- //Use the standard openUrl method if StoreKit is unavailable.
- } else {
-
- #if TARGET_IPHONE_SIMULATOR
- NSLog(@"APPIRATER NOTE: iTunes App Store is not supported on the iOS simulator. Unable to open App Store page.");
- #else
- NSString *reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
-
- // iOS 7 needs a different templateReviewURL @see https://github.com/arashpayan/appirater/issues/131
- // Fixes condition @see https://github.com/arashpayan/appirater/issues/205
- if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 && [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
- reviewURL = [templateReviewURLiOS7 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
- }
- // iOS 8 needs a different templateReviewURL also @see https://github.com/arashpayan/appirater/issues/182
- else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
- {
- reviewURL = [templateReviewURLiOS8 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
- }
-
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:reviewURL]];
- #endif
- }
-}
-
-- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
- NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
-
- id <AppiraterDelegate> delegate = _delegate;
-
- switch (buttonIndex) {
- case 0:
- {
- // they don't want to rate it
- [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate];
- [userDefaults synchronize];
- if(delegate && [delegate respondsToSelector:@selector(appiraterDidDeclineToRate:)]){
- [delegate appiraterDidDeclineToRate:self];
- }
- break;
- }
- case 1:
- {
- // they want to rate it
- [Appirater rateApp];
- if(delegate&& [delegate respondsToSelector:@selector(appiraterDidOptToRate:)]){
- [delegate appiraterDidOptToRate:self];
- }
- break;
- }
- case 2:
- // remind them later
- [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterReminderRequestDate];
- [userDefaults synchronize];
- if(delegate && [delegate respondsToSelector:@selector(appiraterDidOptToRemindLater:)]){
- [delegate appiraterDidOptToRemindLater:self];
- }
- break;
- default:
- break;
- }
-}
-
-//Delegate call from the StoreKit view.
-- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
- [Appirater closeModal];
-}
-
-//Close the in-app rating (StoreKit) view and restore the previous status bar style.
-+ (void)closeModal {
- if (_modalOpen) {
- [[UIApplication sharedApplication]setStatusBarStyle:_statusBarStyle animated:_usesAnimation];
- BOOL usedAnimation = _usesAnimation;
- [self setModalOpen:NO];
-
- // get the top most controller (= the StoreKit Controller) and dismiss it
- UIViewController *presentingController = [UIApplication sharedApplication].keyWindow.rootViewController;
- presentingController = [self topMostViewController: presentingController];
- [presentingController dismissViewControllerAnimated:_usesAnimation completion:^{
- id <AppiraterDelegate> delegate = self.sharedInstance.delegate;
- if ([delegate respondsToSelector:@selector(appiraterDidDismissModalView:animated:)]) {
- [delegate appiraterDidDismissModalView:(Appirater *)self animated:usedAnimation];
- }
- }];
- [self.class setStatusBarStyle:(UIStatusBarStyle)nil];
- }
-}
-
-@end
diff --git a/platform/iphone/AppiraterDelegate.h b/platform/iphone/AppiraterDelegate.h
deleted file mode 100644
index cbe0cfad5b..0000000000
--- a/platform/iphone/AppiraterDelegate.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// AppiraterDelegate.h
-// Banana Stand
-//
-// Created by Robert Haining on 9/25/12.
-// Copyright (c) 2012 News.me. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@class Appirater;
-
-@protocol AppiraterDelegate <NSObject>
-
-@optional
--(BOOL)appiraterShouldDisplayAlert:(Appirater *)appirater;
--(void)appiraterDidDisplayAlert:(Appirater *)appirater;
--(void)appiraterDidDeclineToRate:(Appirater *)appirater;
--(void)appiraterDidOptToRate:(Appirater *)appirater;
--(void)appiraterDidOptToRemindLater:(Appirater *)appirater;
--(void)appiraterWillPresentModalView:(Appirater *)appirater animated:(BOOL)animated;
--(void)appiraterDidDismissModalView:(Appirater *)appirater animated:(BOOL)animated;
-@end
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 38f789259c..5d3267cff3 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -15,7 +15,6 @@ iphone_lib = [
'game_center.mm',
'in_app_store.mm',
'icloud.mm',
- #'Appirater.m',
'ios.mm',
]
@@ -30,10 +29,6 @@ if env['ios_gles22_override'] == "yes":
env_ios.Append(CPPFLAGS=['-DGLES2_OVERRIDE'])
-# if env['ios_appirater'] == "yes":
-# env_ios.Append(CPPFLAGS=['-DAPPIRATER_ENABLED'])
-
-
obj = env_ios.Object('godot_iphone.cpp')
prog = None
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index 740f1d7edc..00bb4b9fad 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -30,7 +30,7 @@
#import "gl_view.h"
#include "os_iphone.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#include "main/main.h"
#ifdef MODULE_FACEBOOKSCORER_IOS_ENABLED
@@ -52,10 +52,6 @@
#define kRenderingFrequency 60
#define kAccelerometerFrequency 100.0 // Hz
-#ifdef APPIRATER_ENABLED
-#import "Appirater.h"
-#endif
-
Error _shell_open(String);
void _set_keep_screen_on(bool p_enabled);
@@ -188,11 +184,6 @@ static int frame_count = 0;
Main::start();
++frame_count;
- #ifdef APPIRATER_ENABLED
- int aid = GlobalConfig::get_singleton()->get("ios/app_id");
- [Appirater appLaunched:YES app_id:aid];
- #endif
-
}; break; // no fallthrough
default: {
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 20fa45d708..fa6082a5a7 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -30,7 +30,6 @@ def get_opts():
('store_kit', 'Support for in-app store', 'yes'),
('icloud', 'Support for iCloud', 'yes'),
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
- ('ios_appirater', 'Enable Appirater', 'no'),
('ios_exceptions', 'Use exceptions when compiling on playbook', 'yes'),
('ios_triple', 'Triple for ios toolchain', ''),
('ios_sim', 'Build simulator binary', 'no'),
diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm
index de6ea73c20..4cfa64ae4b 100644
--- a/platform/iphone/game_center.mm
+++ b/platform/iphone/game_center.mm
@@ -48,18 +48,18 @@ extern "C" {
GameCenter* GameCenter::instance = NULL;
void GameCenter::_bind_methods() {
- ClassDB::bind_method(_MD("connect"),&GameCenter::connect);
- ClassDB::bind_method(_MD("is_connected"),&GameCenter::is_connected);
-
- ClassDB::bind_method(_MD("post_score"),&GameCenter::post_score);
- ClassDB::bind_method(_MD("award_achievement"),&GameCenter::award_achievement);
- ClassDB::bind_method(_MD("reset_achievements"),&GameCenter::reset_achievements);
- ClassDB::bind_method(_MD("request_achievements"),&GameCenter::request_achievements);
- ClassDB::bind_method(_MD("request_achievement_descriptions"),&GameCenter::request_achievement_descriptions);
- ClassDB::bind_method(_MD("show_game_center"),&GameCenter::show_game_center);
-
- ClassDB::bind_method(_MD("get_pending_event_count"),&GameCenter::get_pending_event_count);
- ClassDB::bind_method(_MD("pop_pending_event"),&GameCenter::pop_pending_event);
+ ClassDB::bind_method(D_METHOD("connect"),&GameCenter::connect);
+ ClassDB::bind_method(D_METHOD("is_connected"),&GameCenter::is_connected);
+
+ ClassDB::bind_method(D_METHOD("post_score"),&GameCenter::post_score);
+ ClassDB::bind_method(D_METHOD("award_achievement"),&GameCenter::award_achievement);
+ ClassDB::bind_method(D_METHOD("reset_achievements"),&GameCenter::reset_achievements);
+ ClassDB::bind_method(D_METHOD("request_achievements"),&GameCenter::request_achievements);
+ ClassDB::bind_method(D_METHOD("request_achievement_descriptions"),&GameCenter::request_achievement_descriptions);
+ ClassDB::bind_method(D_METHOD("show_game_center"),&GameCenter::show_game_center);
+
+ ClassDB::bind_method(D_METHOD("get_pending_event_count"),&GameCenter::get_pending_event_count);
+ ClassDB::bind_method(D_METHOD("pop_pending_event"),&GameCenter::pop_pending_event);
};
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index a3af8f4aa8..adc76a622e 100755
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -31,7 +31,7 @@
#import <OpenGLES/EAGLDrawable.h>
#include "os_iphone.h"
#include "core/os/keyboard.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#include "servers/audio_server.h"
#import "gl_view.h"
diff --git a/platform/iphone/globals/global_defaults.cpp b/platform/iphone/globals/global_defaults.cpp
index 76b5c9aa01..bf716c36f0 100755
--- a/platform/iphone/globals/global_defaults.cpp
+++ b/platform/iphone/globals/global_defaults.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "global_defaults.h"
-#include "globals.h"
+#include "global_config.h"
void register_iphone_global_defaults() {
diff --git a/platform/iphone/icloud.mm b/platform/iphone/icloud.mm
index 0d1825dd6b..a9b23baaeb 100644
--- a/platform/iphone/icloud.mm
+++ b/platform/iphone/icloud.mm
@@ -44,14 +44,14 @@ extern "C" {
ICloud* ICloud::instance = NULL;
void ICloud::_bind_methods() {
- ClassDB::bind_method(_MD("remove_key"),&ICloud::remove_key);
- ClassDB::bind_method(_MD("set_key_values"),&ICloud::set_key_values);
- ClassDB::bind_method(_MD("get_key_value"),&ICloud::get_key_value);
- ClassDB::bind_method(_MD("synchronize_key_values"),&ICloud::synchronize_key_values);
- ClassDB::bind_method(_MD("get_all_key_values"),&ICloud::get_all_key_values);
-
- ClassDB::bind_method(_MD("get_pending_event_count"),&ICloud::get_pending_event_count);
- ClassDB::bind_method(_MD("pop_pending_event"),&ICloud::pop_pending_event);
+ ClassDB::bind_method(D_METHOD("remove_key"),&ICloud::remove_key);
+ ClassDB::bind_method(D_METHOD("set_key_values"),&ICloud::set_key_values);
+ ClassDB::bind_method(D_METHOD("get_key_value"),&ICloud::get_key_value);
+ ClassDB::bind_method(D_METHOD("synchronize_key_values"),&ICloud::synchronize_key_values);
+ ClassDB::bind_method(D_METHOD("get_all_key_values"),&ICloud::get_all_key_values);
+
+ ClassDB::bind_method(D_METHOD("get_pending_event_count"),&ICloud::get_pending_event_count);
+ ClassDB::bind_method(D_METHOD("pop_pending_event"),&ICloud::pop_pending_event);
};
int ICloud::get_pending_event_count() {
diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm
index 050498c125..b63d7b42ab 100644
--- a/platform/iphone/in_app_store.mm
+++ b/platform/iphone/in_app_store.mm
@@ -66,13 +66,13 @@ NSMutableDictionary* pending_transactions = [NSMutableDictionary dictionary];
InAppStore* InAppStore::instance = NULL;
void InAppStore::_bind_methods() {
- ClassDB::bind_method(_MD("request_product_info"),&InAppStore::request_product_info);
- ClassDB::bind_method(_MD("purchase"),&InAppStore::purchase);
+ ClassDB::bind_method(D_METHOD("request_product_info"),&InAppStore::request_product_info);
+ ClassDB::bind_method(D_METHOD("purchase"),&InAppStore::purchase);
- ClassDB::bind_method(_MD("get_pending_event_count"),&InAppStore::get_pending_event_count);
- ClassDB::bind_method(_MD("pop_pending_event"),&InAppStore::pop_pending_event);
- ClassDB::bind_method(_MD("finish_transaction"),&InAppStore::finish_transaction);
- ClassDB::bind_method(_MD("set_auto_finish_transaction"),&InAppStore::set_auto_finish_transaction);
+ ClassDB::bind_method(D_METHOD("get_pending_event_count"),&InAppStore::get_pending_event_count);
+ ClassDB::bind_method(D_METHOD("pop_pending_event"),&InAppStore::pop_pending_event);
+ ClassDB::bind_method(D_METHOD("finish_transaction"),&InAppStore::finish_transaction);
+ ClassDB::bind_method(D_METHOD("set_auto_finish_transaction"),&InAppStore::set_auto_finish_transaction);
};
@interface ProductsDelegate : NSObject<SKProductsRequestDelegate> {
diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm
index a068d4aa31..4aca85dafc 100644
--- a/platform/iphone/ios.mm
+++ b/platform/iphone/ios.mm
@@ -32,7 +32,7 @@
void iOS::_bind_methods() {
- ClassDB::bind_method(_MD("get_rate_url","app_id"),&iOS::get_rate_url);
+ ClassDB::bind_method(D_METHOD("get_rate_url","app_id"),&iOS::get_rate_url);
};
String iOS::get_rate_url(int p_app_id) const {
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index e34dbae017..816e456838 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -40,7 +40,7 @@
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/io/file_access_pack.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#include "sem_iphone.h"
diff --git a/platform/iphone/power_iphone.cpp b/platform/iphone/power_iphone.cpp
new file mode 100644
index 0000000000..db555f30c2
--- /dev/null
+++ b/platform/iphone/power_iphone.cpp
@@ -0,0 +1,71 @@
+/*************************************************************************/
+/* power_iphone.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "power_iphone.h"
+
+bool PowerState::UpdatePowerInfo() {
+ return false;
+}
+
+
+PowerState PowerIphone::get_power_state() {
+ if (UpdatePowerInfo()) {
+ return power_state;
+ }
+ else {
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int PowerIphone::get_power_seconds_left() {
+ if (UpdatePowerInfo()) {
+ return nsecs_left;
+ }
+ else {
+ return -1;
+ }
+}
+
+int PowerIphone::get_power_percent_left() {
+ if (UpdatePowerInfo()) {
+ return percent_left;
+ }
+ else {
+ return -1;
+ }
+}
+
+PowerIphone::PowerIphone() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+ // TODO Auto-generated constructor stub
+
+}
+
+PowerIphone::~PowerIphone() {
+ // TODO Auto-generated destructor stub
+}
diff --git a/platform/iphone/power_iphone.h b/platform/iphone/power_iphone.h
new file mode 100644
index 0000000000..8890c33e74
--- /dev/null
+++ b/platform/iphone/power_iphone.h
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* power_iphone.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PLATFORM_IPHONE_POWER_IPHONE_H_
+#define PLATFORM_IPHONE_POWER_IPHONE_H_
+
+class PowerIphone {
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+ bool UpdatePowerInfo();
+
+public:
+ PowerIphone();
+ virtual ~PowerIphone();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_IPHONE_POWER_IPHONE_H_ */
diff --git a/platform/iphone/rasterizer_iphone.cpp b/platform/iphone/rasterizer_iphone.cpp
index ee0457cfb1..b8f3dd0d05 100644
--- a/platform/iphone/rasterizer_iphone.cpp
+++ b/platform/iphone/rasterizer_iphone.cpp
@@ -30,7 +30,7 @@
#include "rasterizer_iphone.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include <stdio.h>
_FORCE_INLINE_ static void _gl_load_transform(const Transform& tr) {
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index a20c0f7a70..bd7b0c304d 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -2,6 +2,9 @@
Import('env')
+env.Tool('textfile')
+env.Tool('zip')
+
javascript_files = [
"os_javascript.cpp",
"audio_driver_javascript.cpp",
@@ -21,18 +24,26 @@ for x in javascript_files:
env.Append(LINKFLAGS=["-s", "EXPORTED_FUNCTIONS=\"['_main','_audio_server_mix_function','_main_after_fs_sync']\""])
env.Append(LINKFLAGS=["--shell-file", '"platform/javascript/godot_shell.html"'])
-build = env.Program('#bin/godot', javascript_objects, PROGSUFFIX=env["PROGSUFFIX"] + ".html")
-Depends(build, "godot_shell.html")
-
-def make_html_shell(target, source, env):
- html_path = target[0].rstr()
- assert html_path[:4] == 'bin/'
- assert html_path[-5:] == '.html'
- basename = html_path[4:-5]
- with open(html_path, 'r+') as html_file:
- fixed_html = html_file.read().replace('.html.mem', '.mem').replace(basename, '$GODOT_BASE')
- html_file.seek(0)
- html_file.truncate()
- html_file.write(fixed_html)
-
-env.AddPostAction(build, Action(make_html_shell, "Creating HTML shell file"))
+html_file = env.Program('#bin/godot', javascript_objects, PROGSUFFIX=env["PROGSUFFIX"] + ".html")[0]
+Depends(html_file, "godot_shell.html")
+basename = "godot" + env["PROGSUFFIX"] # output file name without file extension
+
+# Emscripten hardcodes file names, so replace common base name with
+# placeholder while leaving extension; also change `.html.mem` to just `.mem`
+fixup_html = env.Substfile(html_file, SUBST_DICT=[(basename, '$$GODOT_BASE'), ('.html.mem', '.mem')], SUBSTFILESUFFIX='.fixup.html')
+
+zip_dir = env.Dir('#bin/.javascript_zip')
+zip_files = []
+js_file = env.SideEffect(html_file.File(basename+'.js'), html_file)
+zip_files.append(env.InstallAs(
+ [zip_dir.File('godot.html'), zip_dir.File('godot.js'), zip_dir.File('godotfs.js')],
+ [fixup_html, js_file, '#misc/dist/html_fs/godotfs.js']))
+
+if env['wasm'] == 'yes':
+ wasm_file = env.SideEffect(html_file.File(basename+'.wasm'), html_file)
+ zip_files.append(env.InstallAs(zip_dir.File('godot.wasm'), wasm_file))
+else:
+ asmjs_files = env.SideEffect([html_file.File(basename+'.asm.js'), html_file.File(basename+'.html.mem')], html_file)
+ zip_files.append(env.InstallAs([zip_dir.File('godot.asm.js'), zip_dir.File('godot.mem')], asmjs_files))
+
+Zip('#bin/godot', zip_files, ZIPSUFFIX=env['PROGSUFFIX']+env['ZIPSUFFIX'], ZIPROOT=zip_dir)
diff --git a/platform/javascript/audio_server_javascript.cpp b/platform/javascript/audio_server_javascript.cpp
index d5940fb102..bb238ede0c 100644
--- a/platform/javascript/audio_server_javascript.cpp
+++ b/platform/javascript/audio_server_javascript.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "audio_server_javascript.h"
-
+#if 0
#include "emscripten.h"
AudioMixer *AudioServerJavascript::get_mixer() {
@@ -847,3 +847,4 @@ AudioServerJavascript::AudioServerJavascript() {
stream_volume_scale=1.0;
}
+#endif
diff --git a/platform/javascript/audio_server_javascript.h b/platform/javascript/audio_server_javascript.h
index f8c8774e4c..2f48e7e79e 100644
--- a/platform/javascript/audio_server_javascript.h
+++ b/platform/javascript/audio_server_javascript.h
@@ -28,7 +28,7 @@
/*************************************************************************/
#ifndef AUDIO_SERVER_JAVASCRIPT_H
#define AUDIO_SERVER_JAVASCRIPT_H
-
+#if 0
#include "servers/audio_server.h"
class AudioServerJavascript : public AudioServer {
@@ -223,3 +223,4 @@ public:
};
#endif // AUDIO_SERVER_JAVASCRIPT_H
+#endif
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index a701823b2e..799b550899 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -12,8 +12,6 @@ def get_name():
def can_build():
-
- import os
return os.environ.has_key("EMSCRIPTEN_ROOT")
@@ -35,31 +33,41 @@ def get_flags():
]
+def create(env):
+ # remove Windows' .exe suffix
+ return env.Clone(PROGSUFFIX='')
+
+
+def escape_sources_backslashes(target, source, env, for_signature):
+ return [path.replace('\\','\\\\') for path in env.GetBuildPath(source)]
+
+def escape_target_backslashes(target, source, env, for_signature):
+ return env.GetBuildPath(target[0]).replace('\\','\\\\')
+
+
def configure(env):
env['ENV'] = os.environ
- env.use_windows_spawn_fix('javascript')
env.Append(CPPPATH=['#platform/javascript'])
- em_path = os.environ["EMSCRIPTEN_ROOT"]
-
- env['ENV']['PATH'] = em_path + ":" + env['ENV']['PATH']
- env['CC'] = em_path + '/emcc'
- env['CXX'] = em_path + '/emcc'
- #env['AR'] = em_path+"/emar"
- env['AR'] = em_path + "/emcc"
- env['ARFLAGS'] = "-o"
+ env.PrependENVPath('PATH', os.environ['EMSCRIPTEN_ROOT'])
+ env['CC'] = 'emcc'
+ env['CXX'] = 'em++'
+ env['LINK'] = 'emcc'
+ env['RANLIB'] = 'emranlib'
+ # Emscripten's ar has issues with duplicate file names, so use cc
+ env['AR'] = 'emcc'
+ env['ARFLAGS'] = '-o'
+ if (os.name == 'nt'):
+ # use TempFileMunge on Windows since some commands get too long for
+ # cmd.exe even with spawn_fix
+ # need to escape backslashes for this
+ env['ESCAPED_SOURCES'] = escape_sources_backslashes
+ env['ESCAPED_TARGET'] = escape_target_backslashes
+ env['ARCOM'] = '${TEMPFILE("%s")}' % env['ARCOM'].replace('$SOURCES', '$ESCAPED_SOURCES').replace('$TARGET', '$ESCAPED_TARGET')
-# env['RANLIB'] = em_path+"/emranlib"
- env['RANLIB'] = em_path + "/emcc"
env['OBJSUFFIX'] = '.bc'
env['LIBSUFFIX'] = '.bc'
- env['CCCOM'] = "$CC -o $TARGET $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES"
- env['CXXCOM'] = "$CC -o $TARGET $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES"
-
-# env.Append(LIBS=['c','m','stdc++','log','GLESv1_CM','GLESv2'])
-
-# env["LINKFLAGS"]= string.split(" -g --sysroot="+ld_sysroot+" -Wl,--no-undefined -Wl,-z,noexecstack ")
if (env["target"] == "release"):
env.Append(CCFLAGS=['-O2'])
@@ -78,7 +86,6 @@ def configure(env):
env.Append(CPPFLAGS=["-fno-exceptions", '-DNO_SAFE_CAST', '-fno-rtti'])
env.Append(CPPFLAGS=['-DJAVASCRIPT_ENABLED', '-DUNIX_ENABLED', '-DPTHREAD_NO_RENAME', '-DNO_FCNTL', '-DMPC_FIXED_POINT', '-DTYPED_METHOD_BIND', '-DNO_THREADS'])
env.Append(CPPFLAGS=['-DGLES3_ENABLED'])
- env.Append(CPPFLAGS=['-DGLES_NO_CLIENT_ARRAYS'])
if env['wasm'] == 'yes':
env.Append(LINKFLAGS=['-s', 'BINARYEN=1'])
@@ -88,7 +95,7 @@ def configure(env):
# what is set during compilation, check TOTAL_MEMORY in Emscripten's
# src/settings.js for the default.
env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1'])
- env["PROGSUFFIX"] += ".webassembly"
+ env.extra_suffix = '.webassembly' + env.extra_suffix
else:
env.Append(CPPFLAGS=['-s', 'ASM_JS=1'])
env.Append(LINKFLAGS=['-s', 'ASM_JS=1'])
@@ -101,7 +108,4 @@ def configure(env):
env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1'])
# env.Append(LINKFLAGS=['-g4'])
- # print "CCCOM is:", env.subst('$CCCOM')
- # print "P: ", env['p'], " Platofrm: ", env['platform']
-
import methods
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index e487383ef4..b9ef63fe2f 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -28,12 +28,12 @@
/*************************************************************************/
#include "version.h"
#include "export.h"
-#include "tools/editor/editor_settings.h"
-#include "tools/editor/editor_import_export.h"
-#include "tools/editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_export.h"
+#include "editor/editor_node.h"
#include "io/zip_io.h"
#include "io/marshalls.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
#include "os/os.h"
#include "platform/javascript/logo.h"
@@ -417,14 +417,14 @@ EditorExportPlatformJavaScript::~EditorExportPlatformJavaScript() {
}
-
+#endif
void register_javascript_exporter() {
- Ref<EditorExportPlatformJavaScript> exporter = Ref<EditorExportPlatformJavaScript>( memnew(EditorExportPlatformJavaScript) );
- EditorImportExport::get_singleton()->add_export_platform(exporter);
+ //Ref<EditorExportPlatformJavaScript> exporter = Ref<EditorExportPlatformJavaScript>( memnew(EditorExportPlatformJavaScript) );
+ //EditorImportExport::get_singleton()->add_export_platform(exporter);
}
-#endif
+
diff --git a/platform/javascript/javascript_eval.cpp b/platform/javascript/javascript_eval.cpp
index 72b7ab06cd..d84c8bf040 100644
--- a/platform/javascript/javascript_eval.cpp
+++ b/platform/javascript/javascript_eval.cpp
@@ -156,7 +156,7 @@ Variant JavaScript::eval(const String& p_code, bool p_use_global_exec_context) {
void JavaScript::_bind_methods() {
- ClassDB::bind_method(_MD("eval", "code", "use_global_execution_context"), &JavaScript::eval, false);
+ ClassDB::bind_method(D_METHOD("eval", "code", "use_global_execution_context"), &JavaScript::eval, false);
}
JavaScript::JavaScript() {
diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp
index 94320d53c1..076f93f0df 100644
--- a/platform/javascript/javascript_main.cpp
+++ b/platform/javascript/javascript_main.cpp
@@ -151,16 +151,15 @@ int main(int argc, char *argv[]) {
/* Initialize the window */
- printf("let it go!\n");
+ printf("let it go dude!\n");
glutInit(&argc, argv);
os = new OS_JavaScript(_gfx_init,NULL,NULL);
#if 0
char *args[]={"-test","gui","-v",NULL};
Error err = Main::setup("apk",3,args);
#else
- //char *args[]={"-v",NULL};//
- //Error err = Main::setup("",1,args);
- Error err = Main::setup("",0,NULL);
+ char *args[]={"-main_pack","data.pck",NULL}; //pass location of main pack manually, because it wont get an executable name
+ Error err = Main::setup("",2,args);
#endif
ResourceLoader::set_abort_on_missing_resources(false); //ease up compatibility
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index b8c3dea3b4..d570d64acf 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -34,7 +34,7 @@
#include "drivers/unix/dir_access_unix.h"
#include "servers/visual/visual_server_raster.h"
#include "main/main.h"
-#include "core/globals.h"
+#include "core/global_config.h"
#include "dom_keys.h"
#include <stdlib.h>
@@ -259,6 +259,8 @@ void OS_JavaScript::initialize(const VideoMode& p_desired,int p_video_driver,int
physics_2d_server->init();
input = memnew( InputDefault );
+
+ power_manager = memnew( PowerJavascript );
#define EM_CHECK(ev) if (result!=EMSCRIPTEN_RESULT_SUCCESS)\
ERR_PRINTS("Error while setting " #ev " callback: Code " + itos(result))
@@ -282,6 +284,8 @@ void OS_JavaScript::initialize(const VideoMode& p_desired,int p_video_driver,int
javascript_eval = memnew(JavaScript);
GlobalConfig::get_singleton()->add_singleton(GlobalConfig::Singleton("JavaScript", javascript_eval));
#endif
+
+ visual_server->init();
}
void OS_JavaScript::set_main_loop( MainLoop * p_main_loop ) {
@@ -851,8 +855,19 @@ 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, GetDataDirFunc p_get_data_dir_func) {
+PowerState OS_JavaScript::get_power_state() {
+ return power_manager->get_power_state();
+}
+
+int OS_JavaScript::get_power_seconds_left() {
+ return power_manager->get_power_seconds_left();
+}
+
+int OS_JavaScript::get_power_percent_left() {
+ return power_manager->get_power_percent_left();
+}
+OS_JavaScript::OS_JavaScript(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, GetDataDirFunc p_get_data_dir_func) {
gfx_init_func=p_gfx_init_func;
gfx_init_ud=p_gfx_init_ud;
last_button_mask=0;
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 582f128ce8..5f6051bedb 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -32,6 +32,7 @@
#include "os/input.h"
#include "drivers/unix/os_unix.h"
#include "os/main_loop.h"
+#include "power_javascript.h"
#include "servers/physics/physics_server_sw.h"
#include "servers/audio_server.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
@@ -81,6 +82,8 @@ private:
GetDataDirFunc get_data_dir_func;
+ PowerJavascript *power_manager;
+
#ifdef JAVASCRIPT_EVAL_ENABLED
JavaScript* javascript_eval;
#endif
@@ -174,6 +177,10 @@ public:
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);
+
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
OS_JavaScript(GFXInitFunc p_gfx_init_func,void*p_gfx_init_ud, GetDataDirFunc p_get_data_dir_func);
~OS_JavaScript();
diff --git a/platform/javascript/power_javascript.cpp b/platform/javascript/power_javascript.cpp
new file mode 100644
index 0000000000..9d2d0364aa
--- /dev/null
+++ b/platform/javascript/power_javascript.cpp
@@ -0,0 +1,76 @@
+/*************************************************************************/
+/* power_javascript.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "core/error_macros.h"
+#include "power_javascript.h"
+
+
+bool PowerJavascript::UpdatePowerInfo() {
+ // TODO Javascript implementation
+ return false;
+}
+
+PowerState PowerJavascript::get_power_state() {
+ if (UpdatePowerInfo()) {
+ return power_state;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN");
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int PowerJavascript::get_power_seconds_left() {
+ if (UpdatePowerInfo()) {
+ return nsecs_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+int PowerJavascript::get_power_percent_left() {
+ if (UpdatePowerInfo()) {
+ return percent_left;
+ }
+ else {
+ WARN_PRINT("Power management is not implemented on this platform, defaulting to -1");
+ return -1;
+ }
+}
+
+
+PowerJavascript::PowerJavascript() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+
+}
+
+PowerJavascript::~PowerJavascript() {
+}
diff --git a/platform/javascript/power_javascript.h b/platform/javascript/power_javascript.h
new file mode 100644
index 0000000000..bdef2be7e1
--- /dev/null
+++ b/platform/javascript/power_javascript.h
@@ -0,0 +1,51 @@
+/*************************************************************************/
+/* power_javascript.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_
+#define PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_
+
+class PowerJavascript {
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+ bool UpdatePowerInfo();
+
+public:
+ PowerJavascript();
+ virtual ~PowerJavascript();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_ */
diff --git a/platform/osx/SCsub b/platform/osx/SCsub
index 00f23687cf..1427c2e00d 100644
--- a/platform/osx/SCsub
+++ b/platform/osx/SCsub
@@ -10,6 +10,7 @@ files = [
# 'context_gl_osx.cpp',
'dir_access_osx.mm',
'joypad_osx.cpp',
+ 'power_osx.cpp',
]
env.Program('#bin/godot', files)
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index ccd86177ab..b59dfe1afb 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -100,3 +100,4 @@ def configure(env):
#env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } )
env["x86_libtheora_opt_gcc"] = True
+
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 3a97827c16..4af2aaca63 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -28,13 +28,13 @@
/*************************************************************************/
#include "version.h"
#include "export.h"
-#include "tools/editor/editor_settings.h"
-#include "tools/editor/editor_import_export.h"
-#include "tools/editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_export.h"
+#include "editor/editor_node.h"
#include "io/zip_io.h"
#include "io/marshalls.h"
#include "io/resource_saver.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/file_access.h"
#include "os/os.h"
#include "platform/osx/logo.h"
@@ -536,14 +536,14 @@ EditorExportPlatformOSX::~EditorExportPlatformOSX() {
}
-
+#endif
void register_osx_exporter() {
-
+#if 0
Ref<EditorExportPlatformOSX> exporter = Ref<EditorExportPlatformOSX>( memnew(EditorExportPlatformOSX) );
EditorImportExport::get_singleton()->add_export_platform(exporter);
-
+#endif
}
-#endif
+
diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp
index 5d25017aa6..98bcc8dc73 100644
--- a/platform/osx/joypad_osx.cpp
+++ b/platform/osx/joypad_osx.cpp
@@ -275,7 +275,6 @@ void JoypadOSX::_device_removed(int p_id) {
input->joy_connection_changed(p_id, false, "");
device_list[device].free();
device_list.remove(device);
- attached_devices[p_id] = false;
}
static String _hex_str(uint8_t p_byte) {
@@ -307,7 +306,7 @@ bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad* p_joy) {
}
name = c_name;
- int id = get_free_joy_id();
+ int id = input->get_unused_joy_id();
ERR_FAIL_COND_V(id == -1, false);
p_joy->id = id;
int vendor = 0;
@@ -510,16 +509,6 @@ void JoypadOSX::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
FFEffectStop(joy->ff_object);
}
-int JoypadOSX::get_free_joy_id() {
- for (int i = 0; i < JOYPADS_MAX; i++) {
- if (!attached_devices[i]) {
- attached_devices[i] = true;
- return i;
- }
- }
- return -1;
-}
-
int JoypadOSX::get_joy_index(int p_id) const {
for (int i = 0; i < device_list.size(); i++) {
if (device_list[i].id == p_id) return i;
@@ -582,10 +571,6 @@ JoypadOSX::JoypadOSX()
self = this;
input = (InputDefault*)Input::get_singleton();
- for (int i = 0; i < JOYPADS_MAX; i++) {
- attached_devices[i] = false;
- }
-
int okay = 1;
const void *vals[] = {
(void *) create_match_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, &okay),
diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h
index aafd82880d..71a0335316 100644
--- a/platform/osx/joypad_osx.h
+++ b/platform/osx/joypad_osx.h
@@ -95,14 +95,11 @@ private:
InputDefault *input;
IOHIDManagerRef hid_manager;
- bool attached_devices[JOYPADS_MAX];
Vector<joypad> device_list;
bool have_device(IOHIDDeviceRef p_device) const;
bool configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy);
-
- int get_free_joy_id();
int get_joy_index(int p_id) const;
void poll_joypads() const;
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index d8c35472f2..9941774b40 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -32,6 +32,7 @@
#include "os/input.h"
#include "joypad_osx.h"
+#include "power_osx.h"
#include "drivers/unix/os_unix.h"
#include "main/input_default.h"
#include "servers/visual_server.h"
@@ -107,6 +108,8 @@ public:
Size2 window_size;
int current_screen;
Rect2 restore_rect;
+
+ power_osx *power_manager;
float _mouse_scale(float p_scale) {
if (display_scale>1.0)
@@ -200,6 +203,10 @@ public:
virtual bool is_window_maximized() const;
virtual void request_attention();
virtual String get_joy_guid(int p_device) const;
+
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
void run();
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 854ccacbf1..0699978caf 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1119,6 +1119,8 @@ void OS_OSX::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
input = memnew( InputDefault );
joypad_osx = memnew( JoypadOSX );
+ power_manager = memnew( power_osx );
+
_ensure_data_dir();
NSArray *screenArray = [NSScreen screens];
@@ -1758,14 +1760,28 @@ OS::MouseMode OS_OSX::get_mouse_mode() const {
return mouse_mode;
}
+
String OS_OSX::get_joy_guid(int p_device) const {
return input->get_joy_guid_remapped(p_device);
}
+PowerState OS_OSX::get_power_state() {
+ return power_manager->get_power_state();
+}
+
+int OS_OSX::get_power_seconds_left() {
+ return power_manager->get_power_seconds_left();
+}
+
+int OS_OSX::get_power_percent_left() {
+ return power_manager->get_power_percent_left();
+}
+
OS_OSX* OS_OSX::singleton=NULL;
OS_OSX::OS_OSX() {
-
+
+ mouse_mode=OS::MOUSE_MODE_VISIBLE;
main_loop=NULL;
singleton=this;
autoreleasePool = [[NSAutoreleasePool alloc] init];
diff --git a/platform/osx/power_osx.cpp b/platform/osx/power_osx.cpp
new file mode 100644
index 0000000000..5c8f067f24
--- /dev/null
+++ b/platform/osx/power_osx.cpp
@@ -0,0 +1,233 @@
+/*************************************************************************/
+/* power_osx.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "power_osx.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/ps/IOPowerSources.h>
+#include <IOKit/ps/IOPSKeys.h>
+
+// CODE CHUNK IMPORTED FROM SDL 2.0
+
+/* CoreFoundation is so verbose... */
+#define STRMATCH(a,b) (CFStringCompare(a, b, 0) == kCFCompareEqualTo)
+#define GETVAL(k,v) \
+ CFDictionaryGetValueIfPresent(dict, CFSTR(k), (const void **) v)
+
+/* Note that AC power sources also include a laptop battery it is charging. */
+void power_osx::checkps(CFDictionaryRef dict, bool * have_ac, bool * have_battery, bool * charging)
+{
+ CFStringRef strval; /* don't CFRelease() this. */
+ CFBooleanRef bval;
+ CFNumberRef numval;
+ bool charge = false;
+ bool choose = false;
+ bool is_ac = false;
+ int secs = -1;
+ int maxpct = -1;
+ int pct = -1;
+
+ if ((GETVAL(kIOPSIsPresentKey, &bval)) && (bval == kCFBooleanFalse)) {
+ return; /* nothing to see here. */
+ }
+
+ if (!GETVAL(kIOPSPowerSourceStateKey, &strval)) {
+ return;
+ }
+
+ if (STRMATCH(strval, CFSTR(kIOPSACPowerValue))) {
+ is_ac = *have_ac = true;
+ } else if (!STRMATCH(strval, CFSTR(kIOPSBatteryPowerValue))) {
+ return; /* not a battery? */
+ }
+
+ if ((GETVAL(kIOPSIsChargingKey, &bval)) && (bval == kCFBooleanTrue)) {
+ charge = true;
+ }
+
+ if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
+ SInt32 val = -1;
+ CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+ if (val > 0) {
+ *have_battery = true;
+ maxpct = (int) val;
+ }
+ }
+
+ if (GETVAL(kIOPSMaxCapacityKey, &numval)) {
+ SInt32 val = -1;
+ CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+ if (val > 0) {
+ *have_battery = true;
+ maxpct = (int) val;
+ }
+ }
+
+ if (GETVAL(kIOPSTimeToEmptyKey, &numval)) {
+ SInt32 val = -1;
+ CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+
+ /* Mac OS X reports 0 minutes until empty if you're plugged in. :( */
+ if ((val == 0) && (is_ac)) {
+ val = -1; /* !!! FIXME: calc from timeToFull and capacity? */
+ }
+
+ secs = (int) val;
+ if (secs > 0) {
+ secs *= 60; /* value is in minutes, so convert to seconds. */
+ }
+ }
+
+ if (GETVAL(kIOPSCurrentCapacityKey, &numval)) {
+ SInt32 val = -1;
+ CFNumberGetValue(numval, kCFNumberSInt32Type, &val);
+ pct = (int) val;
+ }
+
+ if ((pct > 0) && (maxpct > 0)) {
+ pct = (int) ((((double) pct) / ((double) maxpct)) * 100.0);
+ }
+
+ if (pct > 100) {
+ pct = 100;
+ }
+
+ /*
+ * We pick the battery that claims to have the most minutes left.
+ * (failing a report of minutes, we'll take the highest percent.)
+ */
+ if ((secs < 0) && (nsecs_left < 0)) {
+ if ((pct < 0) && (percent_left < 0)) {
+ choose = true; /* at least we know there's a battery. */
+ }
+ if (pct > percent_left) {
+ choose = true;
+ }
+ } else if (secs > nsecs_left) {
+ choose = true;
+ }
+
+ if (choose) {
+ nsecs_left = secs;
+ percent_left = pct;
+ *charging = charge;
+ }
+}
+
+#undef GETVAL
+#undef STRMATCH
+
+// CODE CHUNK IMPORTED FROM SDL 2.0
+bool power_osx::GetPowerInfo_MacOSX()
+{
+ CFTypeRef blob = IOPSCopyPowerSourcesInfo();
+
+ nsecs_left = -1;
+ percent_left = -1;
+ power_state = POWERSTATE_UNKNOWN;
+
+ if (blob != NULL) {
+ CFArrayRef list = IOPSCopyPowerSourcesList(blob);
+ if (list != NULL) {
+ /* don't CFRelease() the list items, or dictionaries! */
+ bool have_ac = false;
+ bool have_battery = false;
+ bool charging = false;
+ const CFIndex total = CFArrayGetCount(list);
+ CFIndex i;
+ for (i = 0; i < total; i++) {
+ CFTypeRef ps = (CFTypeRef) CFArrayGetValueAtIndex(list, i);
+ CFDictionaryRef dict = IOPSGetPowerSourceDescription(blob, ps);
+ if (dict != NULL) {
+ checkps(dict, &have_ac, &have_battery, &charging);
+ }
+ }
+
+ if (!have_battery) {
+ power_state = POWERSTATE_NO_BATTERY;
+ } else if (charging) {
+ power_state = POWERSTATE_CHARGING;
+ } else if (have_ac) {
+ power_state = POWERSTATE_CHARGED;
+ } else {
+ power_state = POWERSTATE_ON_BATTERY;
+ }
+
+ CFRelease(list);
+ }
+ CFRelease(blob);
+ }
+
+ return true; /* always the definitive answer on Mac OS X. */
+}
+
+
+
+bool power_osx::UpdatePowerInfo() {
+ if (GetPowerInfo_MacOSX()) {
+ return true;
+ }
+ return false;
+}
+
+
+PowerState power_osx::get_power_state() {
+ if (UpdatePowerInfo()) {
+ return power_state;
+ }
+ else {
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int power_osx::get_power_seconds_left() {
+ if (UpdatePowerInfo()) {
+ return nsecs_left;
+ }
+ else {
+ return -1;
+ }
+}
+
+int power_osx::get_power_percent_left() {
+ if (UpdatePowerInfo()) {
+ return percent_left;
+ }
+ else {
+ return -1;
+ }
+}
+
+
+power_osx::power_osx() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+
+}
+
+power_osx::~power_osx() {
+
+}
diff --git a/platform/osx/power_osx.h b/platform/osx/power_osx.h
new file mode 100644
index 0000000000..a4aee31117
--- /dev/null
+++ b/platform/osx/power_osx.h
@@ -0,0 +1,57 @@
+/*************************************************************************/
+/* power_osx.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PLATFORM_OSX_POWER_OSX_H_
+#define PLATFORM_OSX_POWER_OSX_H_
+
+#include "dir_access_osx.h"
+#include "os/file_access.h"
+#include "os/power.h"
+#include <CoreFoundation/CoreFoundation.h>
+
+class power_osx {
+
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+ void checkps(CFDictionaryRef dict, bool * have_ac, bool * have_battery, bool * charging);
+ bool GetPowerInfo_MacOSX(/*PowerState * state, int *seconds, int *percent*/);
+ bool UpdatePowerInfo();
+
+public:
+ power_osx();
+ virtual ~power_osx();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_OSX_POWER_OSX_H_ */
diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp
index d691ae35bd..ee80080b4e 100644
--- a/platform/server/os_server.cpp
+++ b/platform/server/os_server.cpp
@@ -217,6 +217,18 @@ void OS_Server::set_cursor_shape(CursorShape p_shape) {
}
+PowerState OS_Server::get_power_state() {
+ return power_manager->get_power_state();
+}
+
+int OS_Server::get_power_seconds_left() {
+ return power_manager->get_power_seconds_left();
+}
+
+int OS_Server::get_power_percent_left() {
+ return power_manager->get_power_percent_left();
+}
+
void OS_Server::run() {
force_quit = false;
diff --git a/platform/server/os_server.h b/platform/server/os_server.h
index 2b6225c48d..a035076726 100644
--- a/platform/server/os_server.h
+++ b/platform/server/os_server.h
@@ -38,6 +38,7 @@
#include "servers/audio_server.h"
#include "drivers/rtaudio/audio_driver_rtaudio.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
+#include "../x11/power_x11.h"
//bitch
#undef CursorShape
@@ -65,6 +66,8 @@ class OS_Server : public OS_Unix {
bool force_quit;
InputDefault *input;
+
+ PowerX11 *power_manager;
@@ -105,6 +108,10 @@ public:
virtual void move_window_to_foreground();
void run();
+
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
OS_Server();
};
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 167a5831cf..52a22a1942 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -69,8 +69,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "version.h"
#include "export.h"
#include "object.h"
-#include "tools/editor/editor_import_export.h"
-#include "tools/editor/editor_node.h"
+#include "editor/editor_import_export.h"
+#include "editor/editor_node.h"
#include "platform/uwp/logo.h"
#include "os/file_access.h"
#include "io/zip.h"
@@ -79,7 +79,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "io/sha256.h"
#include "io/base64.h"
#include "bind/core_bind.h"
-#include "globals.h"
+#include "global_config.h"
#include "io/marshalls.h"
#include <zlib.h>
@@ -2384,10 +2384,11 @@ EditorExportPlatformUWP::EditorExportPlatformUWP() {
EditorExportPlatformUWP::~EditorExportPlatformUWP() {}
-
+#endif
void register_uwp_exporter() {
-
+#if 0
Ref<EditorExportPlatformUWP> exporter = Ref<EditorExportPlatformUWP>(memnew(EditorExportPlatformUWP));
EditorImportExport::get_singleton()->add_export_platform(exporter);
-}
#endif
+}
+
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index 90c21e11a1..eb62164fd5 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -28,7 +28,6 @@
/*************************************************************************/
#include "drivers/gles2/rasterizer_gles2.h"
#include "os_uwp.h"
-#include "drivers/unix/memory_pool_static_malloc.h"
#include "os/memory_pool_dynamic_static.h"
#include "thread_uwp.h"
#include "drivers/windows/semaphore_windows.h"
@@ -40,7 +39,7 @@
#include "servers/audio_server.h"
//#include "servers/visual/visual_server_wrap_mt.h"
#include "os/memory_pool_dynamic_prealloc.h"
-#include "globals.h"
+#include "global_config.h"
#include "io/marshalls.h"
#include "platform/windows/packet_peer_udp_winsock.h"
#include "platform/windows/stream_peer_winsock.h"
@@ -292,6 +291,8 @@ void OSUWP::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio
ERR_PRINT("Initializing audio failed.");
}
+ power_manager = memnew ( PowerWinRT );
+
managed_object->update_clipboard();
Clipboard::ContentChanged += ref new EventHandler<Platform::Object^>(managed_object, &ManagedType::on_clipboard_changed);
@@ -919,6 +920,18 @@ String OSUWP::get_data_dir() const {
return String(data_folder->Path->Data()).replace("\\", "/");
}
+PowerState OSWinrt::get_power_state() {
+ return power_manager->get_power_state();
+}
+
+int OSWinrt::get_power_seconds_left() {
+ return power_manager->get_power_seconds_left();
+}
+
+int OSWinrt::get_power_percent_left() {
+ return power_manager->get_power_percent_left();
+}
+
OSUWP::OSUWP() {
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index f65aa2d8d9..72cc8a7854 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -42,12 +42,14 @@
#include "core/ustring.h"
#include "main/input_default.h"
#include "joypad_uwp.h"
+#include "power_winrt.h"
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -111,6 +113,8 @@ private:
AudioDriverXAudio2 audio_driver;
+ PowerWinRT *power_manager;
+
MouseMode mouse_mode;
bool alt_mem;
bool gr_mem;
@@ -260,6 +264,10 @@ public:
virtual bool get_swap_ok_cancel() { return true; }
void input_event(InputEvent &p_event);
+
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
void queue_key_event(KeyEvent &p_event);
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index ae8c07384f..befbe00183 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -12,6 +12,7 @@ common_win = [
"packet_peer_udp_winsock.cpp",
"stream_peer_winsock.cpp",
"joypad.cpp",
+ "power_windows.cpp",
]
restarget = "godot_res" + env["OBJSUFFIX"]
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 88d534887b..44c0acdb2e 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -28,10 +28,11 @@
/*************************************************************************/
#include "export.h"
#include "platform/windows/logo.h"
-#include "tools/editor/editor_import_export.h"
-#if 0
+#include "editor/editor_export.h"
+
void register_windows_exporter() {
+#if 0
Image img(_windows_logo);
Ref<ImageTexture> logo = memnew( ImageTexture );
logo->create_from_image(img);
@@ -48,6 +49,6 @@ void register_windows_exporter() {
EditorImportExport::get_singleton()->add_export_platform(exporter);
}
-
-}
#endif
+}
+
diff --git a/platform/windows/joypad.cpp b/platform/windows/joypad.cpp
index f2848268fc..4c1eeb425a 100644
--- a/platform/windows/joypad.cpp
+++ b/platform/windows/joypad.cpp
@@ -87,16 +87,6 @@ bool JoypadWindows::have_device(const GUID &p_guid) {
return false;
}
-int JoypadWindows::check_free_joy_slot() const {
-
- for (int i = 0; i < JOYPADS_MAX; i++) {
-
- if (!attached_joypads[i])
- return i;
- }
- return -1;
-}
-
// adapted from SDL2, works a lot better than the MSDN version
bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
@@ -146,7 +136,7 @@ bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
bool JoypadWindows::setup_dinput_joypad(const DIDEVICEINSTANCE* instance) {
HRESULT hr;
- int num = check_free_joy_slot();
+ int num = input->get_unused_joy_id();
if (have_device(instance->guidInstance) || num == -1)
return false;
@@ -296,7 +286,7 @@ void JoypadWindows::probe_joypads() {
dwResult = xinput_get_state(i, &x_joypads[i].state);
if ( dwResult == ERROR_SUCCESS) {
- int id = check_free_joy_slot();
+ int id = input->get_unused_joy_id();
if (id != -1 && !x_joypads[i].attached) {
x_joypads[i].attached = true;
diff --git a/platform/windows/joypad.h b/platform/windows/joypad.h
index 63eee8c015..d6670c90db 100644
--- a/platform/windows/joypad.h
+++ b/platform/windows/joypad.h
@@ -132,7 +132,6 @@ private:
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);
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index b230dda9cb..8a347e5f32 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -44,7 +44,7 @@
#include "packet_peer_udp_winsock.h"
#include "stream_peer_winsock.h"
#include "lang_table.h"
-#include "globals.h"
+#include "global_config.h"
#include "io/marshalls.h"
#include "joypad.h"
@@ -400,14 +400,15 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (mouse_mode==MOUSE_MODE_CAPTURED) {
Point2i c(video_mode.width/2,video_mode.height/2);
+ old_x = c.x;
+ old_y = c.y;
+
if (Point2i(mm.x,mm.y)==c) {
center=c;
return 0;
}
Point2i ncenter(mm.x,mm.y);
- mm.x = old_x + (mm.x-center.x);
- mm.y = old_y + (mm.y-center.y);
center=ncenter;
POINT pos = { (int) c.x, (int) c.y };
ClientToScreen(hWnd, &pos);
@@ -1092,11 +1093,6 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
-#else
- // FIXME: Does DX support still work now that rasterizer is no longer used?
-#ifdef DX9_ENABLED
- rasterizer = memnew( RasterizerDX9(hWnd) );
-#endif
#endif
visual_server = memnew( VisualServerRaster );
@@ -1138,6 +1134,8 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
input = memnew( InputDefault );
joypad = memnew (JoypadWindows(input, &hWnd));
+ power_manager = memnew( PowerWindows );
+
AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
if (AudioDriverManager::get_driver(p_audio_driver)->init()!=OK) {
@@ -1259,6 +1257,10 @@ void OS_Windows::finalize() {
main_loop=NULL;
+ for (int i = 0; i < get_audio_driver_count(); i++) {
+ AudioDriverManager::get_driver(i)->finish();
+ }
+
memdelete(joypad);
memdelete(input);
@@ -1268,8 +1270,6 @@ void OS_Windows::finalize() {
if (gl_context)
memdelete(gl_context);
#endif
- if (rasterizer)
- memdelete(rasterizer);
if (user_proc) {
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
@@ -1288,8 +1288,8 @@ void OS_Windows::finalize() {
memdelete(physics_2d_server);
monitor_info.clear();
-
}
+
void OS_Windows::finalize_core() {
memdelete(process_map);
@@ -1970,10 +1970,10 @@ Error OS_Windows::execute(const String& p_path, const List<String>& p_arguments,
String argss;
argss="\"\""+p_path+"\"";
+
+ for (const List<String>::Element* E=p_arguments.front(); E; E=E->next()) {
- for(int i=0;i<p_arguments.size();i++) {
-
- argss+=String(" \"")+p_arguments[i]+"\"";
+ argss+=String(" \"")+E->get()+"\"";
}
//print_line("ARGS: "+argss);
@@ -2395,6 +2395,23 @@ bool OS_Windows::is_vsync_enabled() const{
return true;
}
+PowerState OS_Windows::get_power_state() {
+ return power_manager->get_power_state();
+}
+
+int OS_Windows::get_power_seconds_left() {
+ return power_manager->get_power_seconds_left();
+}
+
+int OS_Windows::get_power_percent_left() {
+ return power_manager->get_power_percent_left();
+}
+
+bool OS_Windows::check_feature_support(const String& p_feature) {
+
+ return VisualServer::get_singleton()->has_os_feature(p_feature);
+
+}
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 2c8fa64f8e..c8cacac7a2 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -31,6 +31,7 @@
#include "os/input.h"
#include "os/os.h"
+#include "power_windows.h"
#include "context_gl_win.h"
#include "servers/visual_server.h"
#include "servers/visual/rasterizer.h"
@@ -92,7 +93,6 @@ class OS_Windows : public OS {
ContextGL_Win *gl_context;
#endif
VisualServer *visual_server;
- Rasterizer *rasterizer;
PhysicsServer *physics_server;
Physics2DServer *physics_2d_server;
int pressrc;
@@ -126,6 +126,8 @@ class OS_Windows : public OS {
InputDefault *input;
JoypadWindows *joypad;
+ PowerWindows *power_manager;
+
#ifdef RTAUDIO_ENABLED
AudioDriverRtAudio driver_rtaudio;
#endif
@@ -286,6 +288,12 @@ public:
virtual void set_use_vsync(bool p_enable);
virtual bool is_vsync_enabled() const;
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
+
+ virtual bool check_feature_support(const String& p_feature);
+
OS_Windows(HINSTANCE _hInstance);
~OS_Windows();
diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp
index 5baa01c289..276b9b6634 100644
--- a/platform/windows/packet_peer_udp_winsock.cpp
+++ b/platform/windows/packet_peer_udp_winsock.cpp
@@ -73,10 +73,15 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si
}
Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){
+ ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED);
+
+ if(sock_type==IP::TYPE_NONE)
+ sock_type = peer_addr.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
+
int sock = _get_socket();
ERR_FAIL_COND_V( sock == -1, FAILED );
struct sockaddr_storage addr;
- size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, ip_type);
+ size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, sock_type);
_set_blocking(true);
@@ -114,15 +119,22 @@ void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) {
};
}
-Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size) {
+Error PacketPeerUDPWinsock::listen(int p_port, IP_Address p_bind_address, int p_recv_buffer_size) {
+
+ ERR_FAIL_COND_V(sockfd!=-1,ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(),ERR_INVALID_PARAMETER);
+
+ sock_type = IP::TYPE_ANY;
+
+ if(p_bind_address.is_valid())
+ sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
- close();
int sock = _get_socket();
if (sock == -1 )
return ERR_CANT_CREATE;
struct sockaddr_storage addr = {0};
- size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL);
+ size_t addr_size = _set_listen_sockaddr(&addr, p_port, sock_type, IP_Address());
if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) {
close();
@@ -141,7 +153,8 @@ void PacketPeerUDPWinsock::close(){
if (sockfd != -1)
::closesocket(sockfd);
sockfd=-1;
- rb.resize(8);
+ sock_type = IP::TYPE_NONE;
+ rb.resize(16);
queue_count=0;
}
@@ -152,6 +165,9 @@ Error PacketPeerUDPWinsock::wait() {
}
Error PacketPeerUDPWinsock::_poll(bool p_wait) {
+ if (sockfd==-1) {
+ return FAILED;
+ }
_set_blocking(p_wait);
@@ -159,7 +175,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) {
struct sockaddr_storage from = {0};
int len = sizeof(struct sockaddr_storage);
int ret;
- while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-12, 0)), 0, (struct sockaddr*)&from, &len)) > 0) {
+ while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN((int)sizeof(recv_buffer),MAX(rb.space_left()-24, 0)), 0, (struct sockaddr*)&from, &len)) > 0) {
uint32_t port = 0;
@@ -238,10 +254,12 @@ int PacketPeerUDPWinsock::get_packet_port() const{
int PacketPeerUDPWinsock::_get_socket() {
+ ERR_FAIL_COND_V(sock_type==IP::TYPE_NONE,-1);
+
if (sockfd != -1)
return sockfd;
- sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP);
+ sockfd = _socket_create(sock_type, SOCK_DGRAM, IPPROTO_UDP);
return sockfd;
}
@@ -271,7 +289,8 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
packet_port=0;
queue_count=0;
peer_port=0;
- ip_type = IP::TYPE_ANY;
+ sock_type = IP::TYPE_NONE;
+ rb.resize(16);
}
PacketPeerUDPWinsock::~PacketPeerUDPWinsock() {
diff --git a/platform/windows/packet_peer_udp_winsock.h b/platform/windows/packet_peer_udp_winsock.h
index 18e6bd8f3d..dcd9da9a79 100644
--- a/platform/windows/packet_peer_udp_winsock.h
+++ b/platform/windows/packet_peer_udp_winsock.h
@@ -46,6 +46,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
mutable int packet_port;
mutable int queue_count;
int sockfd;
+ IP::Type sock_type;
IP_Address peer_addr;
int peer_port;
@@ -67,7 +68,7 @@ public:
virtual int get_max_packet_size() const;
- virtual Error listen(int p_port, int p_recv_buffer_size=65536);
+ virtual Error listen(int p_port, IP_Address p_bind_address=IP_Address("*"), int p_recv_buffer_size=65536);
virtual void close();
virtual Error wait();
virtual bool is_listening() const;
diff --git a/platform/windows/power_windows.cpp b/platform/windows/power_windows.cpp
new file mode 100644
index 0000000000..899b620a24
--- /dev/null
+++ b/platform/windows/power_windows.cpp
@@ -0,0 +1,108 @@
+/*************************************************************************/
+/* power_windows.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "power_windows.h"
+
+// CODE CHUNK IMPORTED FROM SDL 2.0
+
+bool PowerWindows::GetPowerInfo_Windows()
+{
+ SYSTEM_POWER_STATUS status;
+ bool need_details = FALSE;
+
+ /* This API should exist back to Win95. */
+ if (!GetSystemPowerStatus(&status))
+ {
+ /* !!! FIXME: push GetLastError() into GetError() */
+ power_state = POWERSTATE_UNKNOWN;
+ } else if (status.BatteryFlag == 0xFF) { /* unknown state */
+ power_state = POWERSTATE_UNKNOWN;
+ } else if (status.BatteryFlag & (1 << 7)) { /* no battery */
+ power_state = POWERSTATE_NO_BATTERY;
+ } else if (status.BatteryFlag & (1 << 3)) { /* charging */
+ power_state = POWERSTATE_CHARGING;
+ need_details = TRUE;
+ } else if (status.ACLineStatus == 1) {
+ power_state = POWERSTATE_CHARGED; /* on AC, not charging. */
+ need_details = TRUE;
+ } else {
+ power_state = POWERSTATE_ON_BATTERY; /* not on AC. */
+ need_details = TRUE;
+ }
+
+ percent_left = -1;
+ nsecs_left = -1;
+ if (need_details) {
+ const int pct = (int) status.BatteryLifePercent;
+ const int secs = (int) status.BatteryLifeTime;
+
+ if (pct != 255) { /* 255 == unknown */
+ percent_left = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */
+ }
+ if (secs != 0xFFFFFFFF) { /* ((DWORD)-1) == unknown */
+ nsecs_left = secs;
+ }
+ }
+
+ return TRUE; /* always the definitive answer on Windows. */
+}
+
+PowerState PowerWindows::get_power_state() {
+ if (GetPowerInfo_Windows()) {
+ return power_state;
+ }
+ else {
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int PowerWindows::get_power_seconds_left() {
+ if (GetPowerInfo_Windows()) {
+ return nsecs_left;
+ }
+ else {
+ return -1;
+ }
+}
+
+int PowerWindows::get_power_percent_left() {
+ if (GetPowerInfo_Windows()) {
+ return percent_left;
+ }
+ else {
+ return -1;
+ }
+}
+
+PowerWindows::PowerWindows() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+
+}
+
+PowerWindows::~PowerWindows() {
+}
diff --git a/platform/windows/power_windows.h b/platform/windows/power_windows.h
new file mode 100644
index 0000000000..5c26faa3d1
--- /dev/null
+++ b/platform/windows/power_windows.h
@@ -0,0 +1,57 @@
+/*************************************************************************/
+/* power_windows.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 PLATFORM_WINDOWS_POWER_WINDOWS_H_
+#define PLATFORM_WINDOWS_POWER_WINDOWS_H_
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/power.h"
+
+#include <windows.h>
+
+class PowerWindows {
+
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+ bool GetPowerInfo_Windows();
+
+public:
+ PowerWindows();
+ virtual ~PowerWindows();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* PLATFORM_WINDOWS_POWER_WINDOWS_H_ */
diff --git a/platform/windows/stream_peer_winsock.cpp b/platform/windows/stream_peer_winsock.cpp
index 9d3e3623da..106eb6a5f5 100644
--- a/platform/windows/stream_peer_winsock.cpp
+++ b/platform/windows/stream_peer_winsock.cpp
@@ -78,15 +78,10 @@ Error StreamPeerWinsock::_block(int p_sockfd, bool p_read, bool p_write) const {
return ret < 0 ? FAILED : OK;
};
-Error StreamPeerWinsock::_poll_connection(bool p_block) const {
+Error StreamPeerWinsock::_poll_connection() const {
ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == INVALID_SOCKET, FAILED);
- if (p_block) {
-
- _block(sockfd, false, true);
- };
-
struct sockaddr_storage their_addr;
size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, sock_type);
@@ -122,7 +117,7 @@ Error StreamPeerWinsock::write(const uint8_t* p_data,int p_bytes, int &r_sent, b
if (status != STATUS_CONNECTED) {
- if (_poll_connection(p_block) != OK) {
+ if (_poll_connection() != OK) {
return FAILED;
};
@@ -180,7 +175,7 @@ Error StreamPeerWinsock::read(uint8_t* p_buffer, int p_bytes,int &r_received, bo
if (status != STATUS_CONNECTED) {
- if (_poll_connection(p_block) != OK) {
+ if (_poll_connection() != OK) {
return FAILED;
};
@@ -254,7 +249,7 @@ Error StreamPeerWinsock::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_
StreamPeerTCP::Status StreamPeerWinsock::get_status() const {
if (status == STATUS_CONNECTING) {
- _poll_connection(false);
+ _poll_connection();
};
return status;
@@ -287,11 +282,10 @@ void StreamPeerWinsock::disconnect_from_host() {
peer_port = 0;
};
-void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) {
+void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type) {
- ip_type = p_ip_type;
sockfd = p_sockfd;
- sock_type = p_ip_type;
+ sock_type = p_sock_type;
status = STATUS_CONNECTING;
peer_host = p_host;
peer_port = p_port;
@@ -299,7 +293,7 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port,
Error StreamPeerWinsock::connect_to_host(const IP_Address& p_host, uint16_t p_port) {
- ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V( !p_host.is_valid(), ERR_INVALID_PARAMETER);
sock_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
@@ -369,7 +363,6 @@ StreamPeerWinsock::StreamPeerWinsock() {
sockfd = INVALID_SOCKET;
status = STATUS_NONE;
peer_port = 0;
- ip_type = IP::TYPE_ANY;
};
StreamPeerWinsock::~StreamPeerWinsock() {
diff --git a/platform/windows/stream_peer_winsock.h b/platform/windows/stream_peer_winsock.h
index 59e4dc0d09..7cf60fc10e 100644
--- a/platform/windows/stream_peer_winsock.h
+++ b/platform/windows/stream_peer_winsock.h
@@ -47,7 +47,7 @@ protected:
Error _block(int p_sockfd, bool p_read, bool p_write) const;
- Error _poll_connection(bool p_block) const;
+ Error _poll_connection() const;
IP_Address peer_host;
int peer_port;
@@ -69,7 +69,7 @@ public:
virtual int get_available_bytes() const;
- void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type);
+ void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_sock_type);
virtual IP_Address get_connected_host() const;
virtual uint16_t get_connected_port() const;
diff --git a/platform/windows/tcp_server_winsock.cpp b/platform/windows/tcp_server_winsock.cpp
index 1c3682adfa..883741b115 100644
--- a/platform/windows/tcp_server_winsock.cpp
+++ b/platform/windows/tcp_server_winsock.cpp
@@ -63,10 +63,20 @@ void TCPServerWinsock::cleanup() {
};
-Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
+Error TCPServerWinsock::listen(uint16_t p_port,const IP_Address p_bind_address) {
+
+ ERR_FAIL_COND_V(listen_sockfd!=-1,ERR_ALREADY_IN_USE);
+ ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
int sockfd;
- sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP);
+ sock_type = IP::TYPE_ANY;
+
+ // If the bind address is valid use its type as the socket type
+ if (p_bind_address.is_valid())
+ sock_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
+
+
+ sockfd = _socket_create(sock_type, SOCK_STREAM, IPPROTO_TCP);
ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED);
unsigned long par = 1;
@@ -77,7 +87,7 @@ Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_ho
};
struct sockaddr_storage my_addr;
- size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, ip_type, p_accepted_hosts);
+ size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, sock_type, p_bind_address);
int reuse=1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
@@ -150,7 +160,7 @@ Ref<StreamPeerTCP> TCPServerWinsock::take_connection() {
int port;
_set_ip_addr_port(ip, port, &their_addr);
- conn->set_socket(fd, ip, port, ip_type);
+ conn->set_socket(fd, ip, port, sock_type);
return conn;
};
@@ -162,13 +172,14 @@ void TCPServerWinsock::stop() {
};
listen_sockfd = -1;
+ sock_type = IP::TYPE_NONE;
};
TCPServerWinsock::TCPServerWinsock() {
listen_sockfd = INVALID_SOCKET;
- ip_type = IP::TYPE_ANY;
+ sock_type = IP::TYPE_NONE;
};
TCPServerWinsock::~TCPServerWinsock() {
diff --git a/platform/windows/tcp_server_winsock.h b/platform/windows/tcp_server_winsock.h
index 5c544436a7..afbd1e9c87 100644
--- a/platform/windows/tcp_server_winsock.h
+++ b/platform/windows/tcp_server_winsock.h
@@ -34,12 +34,13 @@
class TCPServerWinsock : public TCP_Server {
int listen_sockfd;
+ IP::Type sock_type;
static TCP_Server* _create();
public:
- virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
+ virtual Error listen(uint16_t p_port, const IP_Address p_bind_address=IP_Address("*"));
virtual bool is_connection_available() const;
virtual Ref<StreamPeerTCP> take_connection();
diff --git a/platform/x11/SCsub b/platform/x11/SCsub
index 4ae8ac07f7..fc9208c563 100644
--- a/platform/x11/SCsub
+++ b/platform/x11/SCsub
@@ -8,6 +8,7 @@ common_x11 = [\
"os_x11.cpp",\
"key_mapping_x11.cpp",\
"joypad_linux.cpp",\
+ "power_x11.cpp",\
]
env.Program('#bin/godot', ['godot_x11.cpp'] + common_x11)
diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp
index 5a4751b387..c40b8f3c1f 100644
--- a/platform/x11/export/export.cpp
+++ b/platform/x11/export/export.cpp
@@ -28,11 +28,27 @@
/*************************************************************************/
#include "export.h"
#include "platform/x11/logo.h"
-#include "tools/editor/editor_import_export.h"
+#include "editor/editor_export.h"
#include "scene/resources/texture.h"
-#if 0
+
+
+
void register_x11_exporter() {
+ Ref<EditorExportPlatformPC> platform;
+ platform.instance();
+
+ Image img(_x11_logo);
+ Ref<ImageTexture> logo;
+ logo.instance();
+ logo->create_from_image(img);
+ platform->set_logo(logo);
+ platform->set_name("Linux/X11");
+ platform->set_extension("");
+
+ EditorExport::get_singleton()->add_export_platform(platform);
+
+ #if 0
Image img(_x11_logo);
Ref<ImageTexture> logo = memnew( ImageTexture );
logo->create_from_image(img);
@@ -49,5 +65,6 @@ void register_x11_exporter() {
EditorImportExport::get_singleton()->add_export_platform(exporter);
}
+ #endif
}
-#endif
+
diff --git a/platform/x11/godot_x11.cpp b/platform/x11/godot_x11.cpp
index f85ba17020..adb919c2f1 100644
--- a/platform/x11/godot_x11.cpp
+++ b/platform/x11/godot_x11.cpp
@@ -26,6 +26,10 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+
#include "main/main.h"
#include "os_x11.h"
@@ -33,6 +37,9 @@ int main(int argc, char* argv[]) {
OS_X11 os;
+ char *cwd = (char*)malloc(PATH_MAX);
+ getcwd(cwd, PATH_MAX);
+
Error err = Main::setup(argv[0],argc-1,&argv[1]);
if (err!=OK)
return 255;
@@ -41,5 +48,8 @@ int main(int argc, char* argv[]) {
os.run(); // it is actually the OS that decides how to run
Main::cleanup();
+ chdir(cwd);
+ free(cwd);
+
return os.get_exit_code();
}
diff --git a/platform/x11/joypad_linux.cpp b/platform/x11/joypad_linux.cpp
index 362999661e..bdbd2912a6 100644
--- a/platform/x11/joypad_linux.cpp
+++ b/platform/x11/joypad_linux.cpp
@@ -219,15 +219,6 @@ void JoypadLinux::monitor_joypads() {
}
}
-int JoypadLinux::get_free_joy_slot() const {
-
- for (int i = 0; i < JOYPADS_MAX; i++) {
-
- if (joypads[i].fd == -1) return i;
- }
- return -1;
-}
-
int JoypadLinux::get_joy_from_path(String p_path) const {
for (int i = 0; i < JOYPADS_MAX; i++) {
@@ -329,7 +320,7 @@ void JoypadLinux::setup_joypad_properties(int p_id) {
void JoypadLinux::open_joypad(const char *p_path) {
- int joy_num = get_free_joy_slot();
+ int joy_num = input->get_unused_joy_id();
int fd = open(p_path, O_RDWR | O_NONBLOCK);
if (fd != -1 && joy_num != -1) {
diff --git a/platform/x11/joypad_linux.h b/platform/x11/joypad_linux.h
index 18ad199f6b..310f5c1488 100644
--- a/platform/x11/joypad_linux.h
+++ b/platform/x11/joypad_linux.h
@@ -81,7 +81,6 @@ private:
static void joy_thread_func(void *p_user);
int get_joy_from_path(String path) const;
- int get_free_joy_slot() const;
void setup_joypad_properties(int p_id);
void close_joypad(int p_id = -1);
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index e792d0465e..689fe076f1 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -464,6 +464,9 @@ void OS_X11::finalize() {
memdelete(main_loop);
main_loop=NULL;
+ for (int i = 0; i < get_audio_driver_count(); i++) {
+ AudioDriverManager::get_driver(i)->finish();
+ }
/*
if (debugger_connection_console) {
@@ -476,7 +479,6 @@ void OS_X11::finalize() {
#endif
memdelete(input);
-
visual_server->finish();
memdelete(visual_server);
//memdelete(rasterizer);
@@ -512,6 +514,7 @@ void OS_X11::finalize() {
args.clear();
+
}
@@ -1238,7 +1241,7 @@ static Property read_property(Display* p_display, Window p_window, Atom p_proper
}while(bytes_after != 0);
- Property p = {ret, actual_format, nitems, actual_type};
+ Property p = {ret, actual_format, (int)nitems, actual_type};
return p;
}
@@ -2004,6 +2007,18 @@ void OS_X11::set_context(int p_context) {
}
}
+PowerState OS_X11::get_power_state() {
+ return power_manager->get_power_state();
+}
+
+int OS_X11::get_power_seconds_left() {
+ return power_manager->get_power_seconds_left();
+}
+
+int OS_X11::get_power_percent_left() {
+ return power_manager->get_power_percent_left();
+}
+
OS_X11::OS_X11() {
#ifdef RTAUDIO_ENABLED
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 3ec358f103..ce2e2df6e9 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -46,6 +46,7 @@
#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
#include "main/input_default.h"
#include "joypad_linux.h"
+#include "power_x11.h"
#include <X11/keysym.h>
#include <X11/Xlib.h>
@@ -164,6 +165,8 @@ class OS_X11 : public OS_Unix {
AudioDriverDummy driver_dummy;
Atom net_wm_icon;
+
+ PowerX11 *power_manager;
int audio_driver_index;
unsigned int capture_idle;
@@ -260,6 +263,10 @@ public:
virtual void set_use_vsync(bool p_enable);
virtual bool is_vsync_enabled() const;
+ virtual PowerState get_power_state();
+ virtual int get_power_seconds_left();
+ virtual int get_power_percent_left();
+
void run();
OS_X11();
diff --git a/platform/x11/power_x11.cpp b/platform/x11/power_x11.cpp
new file mode 100644
index 0000000000..472a32bb48
--- /dev/null
+++ b/platform/x11/power_x11.cpp
@@ -0,0 +1,575 @@
+/*************************************************************************/
+/* power_x11.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "power_x11.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+// CODE CHUNK IMPORTED FROM SDL 2.0
+
+static const char* proc_apm_path = "/proc/apm";
+static const char* proc_acpi_battery_path = "/proc/acpi/battery";
+static const char* proc_acpi_ac_adapter_path = "/proc/acpi/ac_adapter";
+static const char* sys_class_power_supply_path = "/sys/class/power_supply";
+
+FileAccessRef PowerX11::open_power_file(const char* base, const char* node, const char* key)
+{
+ String path = String(base) + String("/") + String(node) + String("/") + String(key);
+ FileAccessRef f = FileAccess::open(path,FileAccess::READ);
+ return f;
+}
+
+
+bool PowerX11::read_power_file(const char* base, const char* node, const char* key, char* buf, size_t buflen)
+{
+ ssize_t br = 0;
+ FileAccessRef fd = open_power_file(base, node, key);
+ if (!fd) {
+ return false;
+ }
+ br = fd->get_buffer(reinterpret_cast<uint8_t*>(buf), buflen-1);
+ fd->close();
+ if (br < 0) {
+ return false;
+ }
+ buf[br] = '\0'; // null-terminate the string
+ return true;
+}
+
+
+bool PowerX11::make_proc_acpi_key_val(char **_ptr, char **_key, char **_val)
+{
+ char *ptr = *_ptr;
+
+ while (*ptr == ' ') {
+ ptr++; /* skip whitespace. */
+ }
+
+ if (*ptr == '\0') {
+ return false; /* EOF. */
+ }
+
+ *_key = ptr;
+
+ while ((*ptr != ':') && (*ptr != '\0')) {
+ ptr++;
+ }
+
+ if (*ptr == '\0') {
+ return false; /* (unexpected) EOF. */
+ }
+
+ *(ptr++) = '\0'; /* terminate the key. */
+
+ while ((*ptr == ' ') && (*ptr != '\0')) {
+ ptr++; /* skip whitespace. */
+ }
+
+ if (*ptr == '\0') {
+ return false; /* (unexpected) EOF. */
+ }
+
+ *_val = ptr;
+
+ while ((*ptr != '\n') && (*ptr != '\0')) {
+ ptr++;
+ }
+
+ if (*ptr != '\0') {
+ *(ptr++) = '\0'; /* terminate the value. */
+ }
+
+ *_ptr = ptr; /* store for next time. */
+ return true;
+}
+
+void
+PowerX11::check_proc_acpi_battery(const char * node, bool * have_battery, bool * charging)
+{
+ const char *base = proc_acpi_battery_path;
+ char info[1024];
+ char state[1024];
+ char *ptr = NULL;
+ char *key = NULL;
+ char *val = NULL;
+ bool charge = false;
+ bool choose = false;
+ int maximum = -1;
+ int remaining = -1;
+ int secs = -1;
+ int pct = -1;
+
+ if (!read_power_file(base, node, "state", state, sizeof (state))) {
+ return;
+ } else {
+ if (!read_power_file(base, node, "info", info, sizeof (info)))
+ return;
+ }
+
+ ptr = &state[0];
+ while (make_proc_acpi_key_val(&ptr, &key, &val)) {
+ if (String(key) == "present") {
+ if (String(val) == "yes") {
+ *have_battery = true;
+ }
+ } else if (String(key) == "charging state") {
+ /* !!! FIXME: what exactly _does_ charging/discharging mean? */
+ if (String(val) == "charging/discharging") {
+ charge = true;
+ } else if (String(val) == "charging") {
+ charge = true;
+ }
+ } else if (String(key) == "remaining capacity") {
+ char *endptr = NULL;
+ //const int cvt = (int) strtol(val, &endptr, 10);
+ String sval = val;
+ const int cvt = sval.to_int();
+ if (*endptr == ' ') {
+ remaining = cvt;
+ }
+ }
+ }
+
+ ptr = &info[0];
+ while (make_proc_acpi_key_val(&ptr, &key, &val)) {
+ if (String(key) == "design capacity") {
+ char *endptr = NULL;
+ String sval = val;
+ const int cvt = sval.to_int();
+ if (*endptr == ' ') {
+ maximum = cvt;
+ }
+ }
+ }
+
+ if ((maximum >= 0) && (remaining >= 0)) {
+ pct = (int) ((((float) remaining) / ((float) maximum)) * 100.0f);
+ if (pct < 0) {
+ pct = 0;
+ } else if (pct > 100) {
+ pct = 100;
+ }
+ }
+
+ /* !!! FIXME: calculate (secs). */
+
+ /*
+ * We pick the battery that claims to have the most minutes left.
+ * (failing a report of minutes, we'll take the highest percent.)
+ */
+ if ((secs < 0) && (this->nsecs_left < 0)) {
+ if ((pct < 0) && (this->percent_left < 0)) {
+ choose = true; /* at least we know there's a battery. */
+ }
+ if (pct > this->percent_left) {
+ choose = true;
+ }
+ } else if (secs > this->nsecs_left) {
+ choose = true;
+ }
+
+ if (choose) {
+ this->nsecs_left = secs;
+ this->percent_left = pct;
+ *charging = charge;
+ }
+}
+
+void PowerX11::check_proc_acpi_ac_adapter(const char * node, bool * have_ac)
+{
+ const char *base = proc_acpi_ac_adapter_path;
+ char state[256];
+ char *ptr = NULL;
+ char *key = NULL;
+ char *val = NULL;
+
+ if (!read_power_file(base, node, "state", state, sizeof (state))) {
+ return;
+ }
+
+ ptr = &state[0];
+ while (make_proc_acpi_key_val(&ptr, &key, &val)) {
+ String skey = key;
+ if (skey == "state") {
+ String sval = val;
+ if (sval == "on-line") {
+ *have_ac = true;
+ }
+ }
+ }
+}
+
+
+bool PowerX11::GetPowerInfo_Linux_proc_acpi()
+{
+ String node;
+ DirAccess *dirp = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ bool have_battery = false;
+ bool have_ac = false;
+ bool charging = false;
+
+ this->nsecs_left = -1;
+ this->percent_left = -1;
+ this->power_state = POWERSTATE_UNKNOWN;
+
+
+ dirp->change_dir(proc_acpi_battery_path);
+ dirp->list_dir_begin();
+
+ if (dirp == NULL) {
+ return false; /* can't use this interface. */
+ } else {
+ node = dirp->get_next();
+ while (node != "") {
+ check_proc_acpi_battery(node.utf8().get_data(), &have_battery, &charging/*, seconds, percent*/);
+ node = dirp->get_next();
+ }
+ memdelete(dirp);
+ }
+
+ dirp->change_dir(proc_acpi_ac_adapter_path);
+ dirp->list_dir_begin();
+ if (dirp == NULL) {
+ return false; /* can't use this interface. */
+ } else {
+ node = dirp->get_next();
+ while (node != "") {
+ check_proc_acpi_ac_adapter(node.utf8().get_data(), &have_ac);
+ node = dirp->get_next();
+ }
+ memdelete(dirp);
+ }
+
+ if (!have_battery) {
+ this->power_state = POWERSTATE_NO_BATTERY;
+ } else if (charging) {
+ this->power_state = POWERSTATE_CHARGING;
+ } else if (have_ac) {
+ this->power_state = POWERSTATE_CHARGED;
+ } else {
+ this->power_state = POWERSTATE_ON_BATTERY;
+ }
+
+ return true; /* definitive answer. */
+}
+
+
+bool PowerX11::next_string(char **_ptr, char **_str)
+{
+ char *ptr = *_ptr;
+ char *str = *_str;
+
+ while (*ptr == ' ') { /* skip any spaces... */
+ ptr++;
+ }
+
+ if (*ptr == '\0') {
+ return false;
+ }
+
+ str = ptr;
+ while ((*ptr != ' ') && (*ptr != '\n') && (*ptr != '\0'))
+ ptr++;
+
+ if (*ptr != '\0')
+ *(ptr++) = '\0';
+
+ *_str = str;
+ *_ptr = ptr;
+ return true;
+}
+
+bool PowerX11::int_string(char *str, int *val)
+{
+ String sval = str;
+ *val = sval.to_int();
+ return (*str != '\0');
+}
+
+/* http://lxr.linux.no/linux+v2.6.29/drivers/char/apm-emulation.c */
+bool PowerX11::GetPowerInfo_Linux_proc_apm()
+{
+ bool need_details = false;
+ int ac_status = 0;
+ int battery_status = 0;
+ int battery_flag = 0;
+ int battery_percent = 0;
+ int battery_time = 0;
+ FileAccessRef fd = FileAccess::open(proc_apm_path,FileAccess::READ);
+ char buf[128];
+ char *ptr = &buf[0];
+ char *str = NULL;
+ ssize_t br;
+
+ if (!fd) {
+ return false; /* can't use this interface. */
+ }
+
+ br = fd->get_buffer(reinterpret_cast<uint8_t*>(buf), sizeof (buf) - 1);
+ fd->close();
+
+ if (br < 0) {
+ return false;
+ }
+
+ buf[br] = '\0'; /* null-terminate the string. */
+ if (!next_string(&ptr, &str)) { /* driver version */
+ return false;
+ }
+ if (!next_string(&ptr, &str)) { /* BIOS version */
+ return false;
+ }
+ if (!next_string(&ptr, &str)) { /* APM flags */
+ return false;
+ }
+
+ if (!next_string(&ptr, &str)) { /* AC line status */
+ return false;
+ } else if (!int_string(str, &ac_status)) {
+ return false;
+ }
+
+ if (!next_string(&ptr, &str)) { /* battery status */
+ return false;
+ } else if (!int_string(str, &battery_status)) {
+ return false;
+ }
+ if (!next_string(&ptr, &str)) { /* battery flag */
+ return false;
+ } else if (!int_string(str, &battery_flag)) {
+ return false;
+ }
+ if (!next_string(&ptr, &str)) { /* remaining battery life percent */
+ return false;
+ }
+ String sstr = str;
+ if (sstr[sstr.length() - 1] == '%') {
+ sstr[sstr.length() - 1] = '\0';
+ }
+ if (!int_string(str, &battery_percent)) {
+ return false;
+ }
+
+ if (!next_string(&ptr, &str)) { /* remaining battery life time */
+ return false;
+ } else if (!int_string(str, &battery_time)) {
+ return false;
+ }
+
+ if (!next_string(&ptr, &str)) { /* remaining battery life time units */
+ return false;
+ } else if (String(str) == "min") {
+ battery_time *= 60;
+ }
+
+ if (battery_flag == 0xFF) { /* unknown state */
+ this->power_state = POWERSTATE_UNKNOWN;
+ } else if (battery_flag & (1 << 7)) { /* no battery */
+ this->power_state = POWERSTATE_NO_BATTERY;
+ } else if (battery_flag & (1 << 3)) { /* charging */
+ this->power_state = POWERSTATE_CHARGING;
+ need_details = true;
+ } else if (ac_status == 1) {
+ this->power_state = POWERSTATE_CHARGED; /* on AC, not charging. */
+ need_details = true;
+ } else {
+ this->power_state = POWERSTATE_ON_BATTERY;
+ need_details = true;
+ }
+
+ this->percent_left = -1;
+ this->nsecs_left = -1;
+ if (need_details) {
+ const int pct = battery_percent;
+ const int secs = battery_time;
+
+ if (pct >= 0) { /* -1 == unknown */
+ this->percent_left = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */
+ }
+ if (secs >= 0) { /* -1 == unknown */
+ this->nsecs_left = secs;
+ }
+ }
+
+ return true;
+}
+
+/* !!! FIXME: implement d-bus queries to org.freedesktop.UPower. */
+
+bool PowerX11::GetPowerInfo_Linux_sys_class_power_supply(/*PowerState *state, int *seconds, int *percent*/)
+{
+ const char* base = sys_class_power_supply_path;
+ String name;
+
+ DirAccess *dirp = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ dirp->change_dir(base);
+ dirp->list_dir_begin();
+
+ if (!dirp) {
+ return false;
+ }
+
+ this->power_state = POWERSTATE_NO_BATTERY; /* assume we're just plugged in. */
+ this->nsecs_left = -1;
+ this->percent_left = -1;
+
+ name = dirp->get_next();
+
+ while (name != "") {
+ bool choose = false;
+ char str[64];
+ PowerState st;
+ int secs;
+ int pct;
+
+ if ((name == ".") || (name == "..")) {
+ name = dirp->get_next();
+ continue; //skip these, of course.
+ } else {
+ if (!read_power_file(base, name.utf8().get_data(), "type", str, sizeof (str))) {
+ name = dirp->get_next();
+ continue; // Don't know _what_ we're looking at. Give up on it.
+ } else {
+ if (String(str) != "Battery\n") {
+ name = dirp->get_next();
+ continue; // we don't care about UPS and such.
+ }
+ }
+ }
+
+ /* some drivers don't offer this, so if it's not explicitly reported assume it's present. */
+ if (read_power_file(base, name.utf8().get_data(), "present", str, sizeof (str)) && (String(str) == "0\n")) {
+ st = POWERSTATE_NO_BATTERY;
+ } else if (!read_power_file(base, name.utf8().get_data(), "status", str, sizeof (str))) {
+ st = POWERSTATE_UNKNOWN; /* uh oh */
+ } else if (String(str) == "Charging\n") {
+ st = POWERSTATE_CHARGING;
+ } else if (String(str) == "Discharging\n") {
+ st = POWERSTATE_ON_BATTERY;
+ } else if ((String(str) == "Full\n") || (String(str) == "Not charging\n")) {
+ st = POWERSTATE_CHARGED;
+ } else {
+ st = POWERSTATE_UNKNOWN; /* uh oh */
+ }
+
+ if (!read_power_file(base, name.utf8().get_data(), "capacity", str, sizeof (str))) {
+ pct = -1;
+ } else {
+ pct = String(str).to_int();
+ pct = (pct > 100) ? 100 : pct; /* clamp between 0%, 100% */
+ }
+
+ if (!read_power_file(base, name.utf8().get_data(), "time_to_empty_now", str, sizeof (str))) {
+ secs = -1;
+ } else {
+ secs = String(str).to_int();
+ secs = (secs <= 0) ? -1 : secs; /* 0 == unknown */
+ }
+
+ /*
+ * We pick the battery that claims to have the most minutes left.
+ * (failing a report of minutes, we'll take the highest percent.)
+ */
+ if ((secs < 0) && (this->nsecs_left < 0)) {
+ if ((pct < 0) && (this->percent_left < 0)) {
+ choose = true; /* at least we know there's a battery. */
+ } else if (pct > this->percent_left) {
+ choose = true;
+ }
+ } else if (secs > this->nsecs_left) {
+ choose = true;
+ }
+
+ if (choose) {
+ this->nsecs_left = secs;
+ this->percent_left = pct;
+ this->power_state = st;
+ }
+
+ name = dirp->get_next();
+ }
+
+ memdelete(dirp);
+ return true; /* don't look any further*/
+}
+
+
+
+bool PowerX11::UpdatePowerInfo()
+{
+ if (GetPowerInfo_Linux_sys_class_power_supply()) { // try method 1
+ return true;
+ }
+ if (GetPowerInfo_Linux_proc_acpi()) { // try further
+ return true;
+ }
+ if (GetPowerInfo_Linux_proc_apm()) { // try even further
+ return true;
+ }
+ return false;
+}
+
+PowerX11::PowerX11() : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) {
+}
+
+PowerX11::~PowerX11() {
+}
+
+PowerState PowerX11::get_power_state() {
+ if (UpdatePowerInfo()) {
+ return power_state;
+ }
+ else {
+ return POWERSTATE_UNKNOWN;
+ }
+}
+
+int PowerX11::get_power_seconds_left() {
+ if (UpdatePowerInfo()) {
+ return nsecs_left;
+ }
+ else {
+ return -1;
+ }
+}
+
+int PowerX11::get_power_percent_left() {
+ if (UpdatePowerInfo()) {
+ return percent_left;
+ }
+ else {
+ return -1;
+ }
+}
diff --git a/platform/x11/power_x11.h b/platform/x11/power_x11.h
new file mode 100644
index 0000000000..6efb2de348
--- /dev/null
+++ b/platform/x11/power_x11.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* power_x11.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 X11_POWER_H_
+#define X11_POWER_H_
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/power.h"
+
+
+class PowerX11 {
+
+private:
+ int nsecs_left;
+ int percent_left;
+ PowerState power_state;
+
+
+ FileAccessRef open_power_file(const char* base, const char* node, const char* key);
+ bool read_power_file(const char* base, const char* node, const char* key, char* buf, size_t buflen);
+ bool make_proc_acpi_key_val(char **_ptr, char **_key, char **_val);
+ void check_proc_acpi_battery(const char * node, bool * have_battery, bool * charging);
+ void check_proc_acpi_ac_adapter(const char * node, bool * have_ac);
+ bool GetPowerInfo_Linux_proc_acpi();
+ bool next_string(char **_ptr, char **_str);
+ bool int_string(char *str, int *val);
+ bool GetPowerInfo_Linux_proc_apm();
+ bool GetPowerInfo_Linux_sys_class_power_supply();
+ bool UpdatePowerInfo();
+
+
+public:
+ PowerX11();
+ virtual ~PowerX11();
+
+ PowerState get_power_state();
+ int get_power_seconds_left();
+ int get_power_percent_left();
+};
+
+#endif /* X11_POWER_H_ */
diff --git a/prop_renames.txt b/prop_renames.txt
deleted file mode 100644
index e2156f2368..0000000000
--- a/prop_renames.txt
+++ /dev/null
@@ -1,524 +0,0 @@
-[Object]
-script/script = script
-
-[Node]
-pause/pause_mode = pause_mode
-
-[Control]
-
-anchor/left = anchor_left
-anchor/right = anchor_right
-anchor/bottom = anchor_bottom
-anchor/top = anchor_top
-
-focus_neighbour/left=focus_neighbour_left
-focus_neighbour/right=focus_neighbour_right
-focus_neighbour/bottom=focus_neighbour_bottom
-focus_neighbour/top=focus_neighbour_top
-focus/ignore_mouse = focus_ignore_mouse
-focus/stop_mouse = focus_stop_mouse
-
-size_flags/horizontal = size_flags_horizontal
-size_flags/vertical = size_flags_vertical
-size_flags/stretch_ratio = size_flags_stretch_ratio
-theme/theme = theme
-
-[CanvasItem]
-
-visibility/visible = visible
-visibility/behind_parent = show_behind_parent
-visibility/on_top = show_on_top
-visibility/light_mask = light_mask
-material/material = material
-material/use_parent = use_parent_material
-
-
-[Resource]
-
-resource/path = resource_path
-resource/name = resource_name
-
-
-[Area2D]
-
-collision/layers = collision_layers
-collision/mask = collision_mask
-
-[Camera2D]
-
-limit/left = limit_left
-limit/right = limit_right
-limit/bottom = limit_bottom
-limit/top = limit_top
-limit/smoothed = limit_smoothed
-
-draw_margin/h_enabled = draw_margin_h_enabled
-draw_margin/v_enabled = draw_margin_v_enabled
-
-smoothing/enable = smoothing_enabled
-smoothing/speed = smoothing_speed
-
-drag_margin/left = drag_margin_left
-drag_margin/top = drag_margin_top
-drag_margin/right = drag_margin_right
-drag_margin/bottom = drag_margin_bottom
-
-[CollisionObject2D]
-
-input/pickable = input_pickable
-
-[Joint2D]
-
-bias/bias = bias
-collision/exclude_nodes = disable_collision
-
-[Light2D]
-
-range/height = range_height
-range/z_min = range_z_min
-range/z_max = range_z_max
-range/layer_max = range_layer_max
-range/item_cull_mask = range_item_cull_max
-
-shadow/enabled = shadow_enabled
-shadow/color = shadow_color
-shadow/buffer_size = shadow_buffer_size
-shadow/gradient_length = shadow_gradient_length
-shadow/filter = shadow_filter
-shadow/item_cull_mask = shadow_item_cull_mask
-
-[Node2D]
-
-transform/pos = position
-transform/rot = rotation
-transform/scale = scale
-z/z = z
-z/relative = z_as_relative
-
-[ParallaxBackground]
-
-scroll/offset = scroll_offset
-scroll/base_offset = scroll_base_offset
-scroll/base_scale = scroll_base_scale
-scroll/limit_begin = scroll_limit_begin
-scroll/limit_end = scroll_limit_end
-scroll/ignore_camera_zoom = scroll_ignore_camera_zoom
-
-[ParallaxLayer]
-
-motion/scale = motion_scale
-motion/offset = motion_offset
-motion/mirroring = motion_mirroring
-
-[PhysicsBody2D]
-
-collision/layers = collision_layer
-collision/mask = collision_mask
-
-[Polygon2D]
-
-texture/texture = texture
-texture/offset = texture_offset
-texture/rotation = texture_rotation
-texture/scale = texture_scale
-
-invert/enable = invert_enable
-invert/border = invert_border
-
-[SamplePlayer2D]
-
-config/polyphony = polyphony
-config/samples = samples
-config/pitch_random = random_pitch
-
-[SoundPlayer2D]
-
-params/volume_db = volume_db
-params/pitch_scale = pitch_scale
-params/attenuation/min_distance = attenuation_min_distance
-params/attenuation/max_distance = attenuation_max_distance
-params/attenuation/distance_exp = attenuation_distance_exp
-
-[TileMap]
-
-cell/size = cell_size
-cell/quadrant_size = cell_quadrant_size
-cell/half_offset = cell_half_offset
-cell/tile_origin = cell_tile_origin
-cell/y_sort = cell_y_sort
-
-collision/use_kinematic = collision_use_kinematic
-collision/friction = collision_friction
-collision/bounce = collision_bounce
-collision/layers = collision_layers
-collision/mask = collision_mask
-
-occluder/light_mask = occluder_light_mask
-
-[VisibilityEnabler2D]
-
-enabler/pause_animations = pause_animations
-enabler/freeze_bodies = freeze_bodies
-enabler/pause_particles = pause_particles
-enabler/pause_animated_sprites = pause_animated_sprites
-enabler/process_parent = process_parent
-enabler/fixed_process_parent = fixed_process_parent
-
-
-[YSort]
-
-sort/enabled = sort_enabled
-
-
-[Area]
-
-collision/layers = collision_layers
-collision/mask = collision_mask
-
-
-[CollisionObject]
-
-input/ray_pickable = input_ray_pickable
-input/capture_on_drag = input_capture_on_drag
-
-[Light]
-
-light/color = light_color
-light/energy = light_energy
-light/negative = light_negative
-light/specular = light_specular
-light/cull_mask = light_cull_mask
-
-shadow/enabled = shadow_enabled
-shadow/color = shadow_color
-shadow/bias = shadow_bias
-shadow/max_distance = shadow_max_distance
-editor/editor_only = editor_only
-
-[DirectionalLight]
-
-directional_shadow/mode = directional_shadow_mode
-directional_shadow/split_1 = directional_shadow_split_1
-directional_shadow/split_2 = directional_shadow_split_2
-directional_shadow/split_3 = directional_shadow_split_3
-directional_shadow/blend_splits = directional_shadow_blend_splits
-directional_shadow/normal_bias = directional_shadow_normal_bias
-directional_shadow/bias_split_scale = directional_shadow_bias_split_scale
-
-[OmniLight]
-
-omni/range = omni_range
-omni/attenuation = omni_attenuation
-omni/shadow_mode = omni_shadow_mode
-omni/shadow_detail = omni_shadow_detail
-
-[SpotLight]
-
-spot/range = spot_range
-spot/attenuation = spot_attenuation
-spot/angle = spot_angle
-spot/spot_attenuation = spot_angle_attenuation
-
-[MeshInstance]
-
-mesh/mesh = mesh
-mesh/skeleton = skeleton
-
-
-[PhysicsBody]
-
-collision/layers = collision_layer
-collision/mask = collision_mask
-
-[Quad]
-
-quad/axis = axis
-quad/size = size
-quad/offset = offset
-quad/centered = centered
-
-[Spatial]
-
-transform/local = transform
-transform/transiation = translation
-transform/rotation = rotation
-transform/scale = scale
-visibility/visible = visible
-
-[SpatialPlayer]
-
-params/volume_db = volume_db
-params/pitch_scale = pitch_scale
-params/attenuation/min_distance = attenuation_min_distance
-params/attenuation/max_distance = attenuation_max_distance
-params/attenuation/distance_exp = attenuation_distance_exp
-params/emission_cone/degrees = emission_cone_degrees
-params/emission_cone/attenuation_db = emission_cone_attenuation_db
-
-[SpatialSamplePlayer]
-
-config/polyphony = polyphony
-config/samples = samples
-
-[Sprite3D]
-
-flags/transparent = transparent
-flags/shaded = shaded
-flags/alpha_cut = alpha_cut
-
-[VehicleWheel]
-
-type/traction = use_as_traction
-type/steering = use_as_steering
-
-wheel/radius = wheel_radius
-wheel/rest_length = wheel_rest_length
-wheel/friction_slip = wheel_friction_sleep
-
-suspension/travel = suspension_travel
-suspension/stiffness = suspension_stiffness
-suspension/max_force = suspension_max_force
-damping/compression = damping_compression
-damping/relaxation = damping_relaxation
-
-[VehicleBody]
-
-motion/engine_force = engine_force
-motion/breake = breake
-motion/steering = steering
-body/mass = mass
-body/friction = friction
-
-[VisibilityEnabler]
-
-enabler/pause_animations = pause_animations
-enabler/freeze_bodies = freeze_bodies
-
-[GeometryInstance]
-
-geometry/material_override = material_override
-geometry/cast_shadow = cast_shadow
-geometry/extra_cull_margin = extra_cull_margin
-geometry/billboard = use_as_billboard
-geometry/billboard_y = use_as_y_billboard
-geometry/depth_scale = use_depth_scale
-geometry/visible_in_all_rooms = visible_in_all_rooms
-geometry/use_baked_light = use_in_baked_light
-
-
-
-[AnimationPlayer]
-
-playback/process_mode = playback_process_mode
-playback/default_blend_time = playback_default_blend_time
-root/root = root_node
-
-[AnimationTreePlayer]
-
-playback/process_mode = playback_process_mode
-
-[EventPlayer]
-
-stream/stream = stream
-stream/play = play
-stream/loop = loop
-stream/volume_db = volume_db
-stream/pitch_scale = pitch_scale
-stream/tempo_scale = tempo_scale
-stream/autoplay = autoplay
-stream/paused = paused
-
-[StreamPlayer]
-
-stream/stream = stream
-stream/play = play
-stream/loop = loop
-stream/volume_db = volume_db
-stream/autoplay = autoplay
-stream/paused = paused
-stream/loop_restart_time = loop_restart_time
-stream/buffering_ms = buffering_ms
-
-[SpatialStreamPlayer]
-
-stream/stream = stream
-stream/play = play
-stream/loop = loop
-stream/volume_db = volume_db
-stream/autoplay = autoplay
-stream/paused = paused
-stream/loop_restart_time = loop_restart_time
-stream/buffering_ms = buffering_ms
-
-[WindowDialog]
-
-window/title = window_title
-
-[AcceptDialog]
-
-dialog/text = dialog_text
-dialog/hide_on_ok = dialog_hide_on_ok
-
-[LineEdit]
-
-placeholder/text = placeholder_text
-placeholder/alpha = placeholder_alpha
-caret/caret_blink = caret_blink
-caret/caret_blink_speed = caret_blink_speed
-
-[Patch9Frame]
-
-patch_margin/left = patch_margin_left
-patch_margin/right = patch_margin_right
-patch_margin/top = patch_margin_top
-patch_margin/bottom = patch_margin_bottom
-
-
-[Popup]
-
-popup/exclusive = popup_exclusive
-
-[ProgressBar]
-
-percent/visible = percent_visible
-
-[Range]
-
-range/min = min_value
-range/max = max_value
-range/step = step
-range/page = page
-range/value = value
-range/exp_edit = exp_edit
-range/rounded = rounded
-
-
-[RigidBody2D]
-
-velocity/linear = linear_velocity
-velocity/angular = angular_velocity
-damp_override_linear = linear_damp
-damp_override_angular = angular_damp
-
-
-[RigidBody]
-
-velocity/linear = linear_velocity
-velocity/angular = angular_velocity
-damp_override_linear = linear_damp
-damp_override_angular = angular_damp
-
-[Tween]
-
-playback/process_mode = playback_process_mode
-
-[RichTextLabel]
-
-bbcode/enabled = bbcode_enabled
-bbcode/bbcode = bbcode_text
-
-[ScrollContainer]
-
-scroll/horizontal = scroll_horizontal
-scroll/vertical = scroll_vertical
-
-[SplitContainer]
-
-split/offset = split_offset
-split/collapsed = collapsed
-split/dragger_visibility = dragger_visibility
-
-[TextEdit]
-
-caret/block_caret = caret_block_mode
-caret/caret_blink = caret_blink
-caret/caret_blink_speed = caret_blink_speed
-
-[TextureButton]
-
-textures/normal = texture_normal
-textures/pressed = texture_pressed
-textures/hover = texture_hover
-textures/disabled = texture_disabled
-textures/focused = texture_focused
-textures/click_mask = texture_click_mask
-params/scale = texture_scale
-params/modulate = self_modulate
-
-[TextureProgress]
-
-texture/under = texture_under
-texture/over = texture_over
-texture/progress = texture_progress
-mode = fill_mode
-radial_fill/initial_angle = radial_initial_angle
-radial_fill/fill_degrees = radial_fill_degrees
-radial_fill/center_offset = radial_center_offset
-
-[VideoPlayer]
-
-stream/audio_track = audio_track
-stream/stream = stream
-stream/volume_db = volume_db
-stream/autoplay = stream_autoplay
-stream/paused = stream_paused
-
-[DynamicFont]
-
-font/size = size
-extra_spacing/top = extra_spacing_top
-extra_spacing/bottom = extra_spacing_bottom
-extra_spacing/char = extra_spacing_char
-extra_spacing/space = extra_spacing_space
-font/use_mipmaps = use_mipmaps
-font/use_filter = use_filter
-font/font=font_data
-
-[StyleBox]
-
-content_margin/left = content_margin_left
-content_margin/right = content_margin_right
-content_margin/bottom = content_margin_bottom
-content_margin/top = content_margin_top
-
-
-[StyleBoxTexture]
-
-margin/left = margin_left
-margin/top = margin_top
-margin/bottom = margin_bottom
-margin/right = margin_right
-
-expand_margin/left = expand_margin_left
-expand_margin/top = expand_margin_top
-expand_margin/bottom = expand_margin_bottom
-expand_margin/right = expand_margin_right
-
-modulate/color = modulate_color
-
-
-[AnimatedSprite]
-
-modulate = self_modulate
-
-[Sprite]
-
-modulate = self_modulate
-
-[Patch9Frame]
-
-modulate = self_modulate
-
-[TextureRect]
-
-modulate = self_modulate
-
-
-
-
-
-
-
-
-
-
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 64d6ef5560..faecbf3e6d 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -222,34 +222,34 @@ void SpriteFrames::_set_animations(const Array& p_animations) {
void SpriteFrames::_bind_methods() {
- ClassDB::bind_method(_MD("add_animation","anim"),&SpriteFrames::add_animation);
- ClassDB::bind_method(_MD("has_animation","anim"),&SpriteFrames::has_animation);
- ClassDB::bind_method(_MD("remove_animation","anim"),&SpriteFrames::remove_animation);
- ClassDB::bind_method(_MD("rename_animation","anim","newname"),&SpriteFrames::rename_animation);
+ ClassDB::bind_method(D_METHOD("add_animation","anim"),&SpriteFrames::add_animation);
+ ClassDB::bind_method(D_METHOD("has_animation","anim"),&SpriteFrames::has_animation);
+ ClassDB::bind_method(D_METHOD("remove_animation","anim"),&SpriteFrames::remove_animation);
+ ClassDB::bind_method(D_METHOD("rename_animation","anim","newname"),&SpriteFrames::rename_animation);
- ClassDB::bind_method(_MD("set_animation_speed","anim","speed"),&SpriteFrames::set_animation_speed);
- ClassDB::bind_method(_MD("get_animation_speed","anim"),&SpriteFrames::get_animation_speed);
+ ClassDB::bind_method(D_METHOD("set_animation_speed","anim","speed"),&SpriteFrames::set_animation_speed);
+ ClassDB::bind_method(D_METHOD("get_animation_speed","anim"),&SpriteFrames::get_animation_speed);
- ClassDB::bind_method(_MD("set_animation_loop","anim","loop"),&SpriteFrames::set_animation_loop);
- ClassDB::bind_method(_MD("get_animation_loop","anim"),&SpriteFrames::get_animation_loop);
+ ClassDB::bind_method(D_METHOD("set_animation_loop","anim","loop"),&SpriteFrames::set_animation_loop);
+ ClassDB::bind_method(D_METHOD("get_animation_loop","anim"),&SpriteFrames::get_animation_loop);
- ClassDB::bind_method(_MD("add_frame","anim","frame","atpos"),&SpriteFrames::add_frame,DEFVAL(-1));
- ClassDB::bind_method(_MD("get_frame_count","anim"),&SpriteFrames::get_frame_count);
- ClassDB::bind_method(_MD("get_frame","anim","idx"),&SpriteFrames::get_frame);
- ClassDB::bind_method(_MD("set_frame","anim","idx","txt"),&SpriteFrames::set_frame);
- ClassDB::bind_method(_MD("remove_frame","anim","idx"),&SpriteFrames::remove_frame);
- ClassDB::bind_method(_MD("clear","anim"),&SpriteFrames::clear);
- ClassDB::bind_method(_MD("clear_all"),&SpriteFrames::clear_all);
+ ClassDB::bind_method(D_METHOD("add_frame","anim","frame","atpos"),&SpriteFrames::add_frame,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_frame_count","anim"),&SpriteFrames::get_frame_count);
+ ClassDB::bind_method(D_METHOD("get_frame","anim","idx"),&SpriteFrames::get_frame);
+ ClassDB::bind_method(D_METHOD("set_frame","anim","idx","txt"),&SpriteFrames::set_frame);
+ ClassDB::bind_method(D_METHOD("remove_frame","anim","idx"),&SpriteFrames::remove_frame);
+ ClassDB::bind_method(D_METHOD("clear","anim"),&SpriteFrames::clear);
+ ClassDB::bind_method(D_METHOD("clear_all"),&SpriteFrames::clear_all);
- ClassDB::bind_method(_MD("_set_frames"),&SpriteFrames::_set_frames);
- ClassDB::bind_method(_MD("_get_frames"),&SpriteFrames::_get_frames);
+ ClassDB::bind_method(D_METHOD("_set_frames"),&SpriteFrames::_set_frames);
+ ClassDB::bind_method(D_METHOD("_get_frames"),&SpriteFrames::_get_frames);
- ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"frames",PROPERTY_HINT_NONE,"",0),_SCS("_set_frames"),_SCS("_get_frames")); //compatibility
+ ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"frames",PROPERTY_HINT_NONE,"",0),"_set_frames","_get_frames"); //compatibility
- ClassDB::bind_method(_MD("_set_animations"),&SpriteFrames::_set_animations);
- ClassDB::bind_method(_MD("_get_animations"),&SpriteFrames::_get_animations);
+ ClassDB::bind_method(D_METHOD("_set_animations"),&SpriteFrames::_set_animations);
+ ClassDB::bind_method(D_METHOD("_get_animations"),&SpriteFrames::_get_animations);
- ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"animations",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_animations"),_SCS("_get_animations")); //compatibility
+ ADD_PROPERTYNZ( PropertyInfo(Variant::ARRAY,"animations",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_animations","_get_animations"); //compatibility
}
@@ -653,48 +653,48 @@ String AnimatedSprite::get_configuration_warning() const {
void AnimatedSprite::_bind_methods() {
- ClassDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite::set_sprite_frames);
- ClassDB::bind_method(_MD("get_sprite_frames:SpriteFrames"),&AnimatedSprite::get_sprite_frames);
+ ClassDB::bind_method(D_METHOD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite::set_sprite_frames);
+ ClassDB::bind_method(D_METHOD("get_sprite_frames:SpriteFrames"),&AnimatedSprite::get_sprite_frames);
- ClassDB::bind_method(_MD("set_animation","animation"),&AnimatedSprite::set_animation);
- ClassDB::bind_method(_MD("get_animation"),&AnimatedSprite::get_animation);
+ ClassDB::bind_method(D_METHOD("set_animation","animation"),&AnimatedSprite::set_animation);
+ ClassDB::bind_method(D_METHOD("get_animation"),&AnimatedSprite::get_animation);
- ClassDB::bind_method(_MD("_set_playing","playing"),&AnimatedSprite::_set_playing);
- ClassDB::bind_method(_MD("_is_playing"),&AnimatedSprite::_is_playing);
+ ClassDB::bind_method(D_METHOD("_set_playing","playing"),&AnimatedSprite::_set_playing);
+ ClassDB::bind_method(D_METHOD("_is_playing"),&AnimatedSprite::_is_playing);
- ClassDB::bind_method(_MD("play","anim"),&AnimatedSprite::play,DEFVAL(StringName()));
- ClassDB::bind_method(_MD("stop"),&AnimatedSprite::stop);
- ClassDB::bind_method(_MD("is_playing"),&AnimatedSprite::is_playing);
+ ClassDB::bind_method(D_METHOD("play","anim"),&AnimatedSprite::play,DEFVAL(StringName()));
+ ClassDB::bind_method(D_METHOD("stop"),&AnimatedSprite::stop);
+ ClassDB::bind_method(D_METHOD("is_playing"),&AnimatedSprite::is_playing);
- ClassDB::bind_method(_MD("set_centered","centered"),&AnimatedSprite::set_centered);
- ClassDB::bind_method(_MD("is_centered"),&AnimatedSprite::is_centered);
+ ClassDB::bind_method(D_METHOD("set_centered","centered"),&AnimatedSprite::set_centered);
+ ClassDB::bind_method(D_METHOD("is_centered"),&AnimatedSprite::is_centered);
- ClassDB::bind_method(_MD("set_offset","offset"),&AnimatedSprite::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&AnimatedSprite::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&AnimatedSprite::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&AnimatedSprite::get_offset);
- ClassDB::bind_method(_MD("set_flip_h","flip_h"),&AnimatedSprite::set_flip_h);
- ClassDB::bind_method(_MD("is_flipped_h"),&AnimatedSprite::is_flipped_h);
+ ClassDB::bind_method(D_METHOD("set_flip_h","flip_h"),&AnimatedSprite::set_flip_h);
+ ClassDB::bind_method(D_METHOD("is_flipped_h"),&AnimatedSprite::is_flipped_h);
- ClassDB::bind_method(_MD("set_flip_v","flip_v"),&AnimatedSprite::set_flip_v);
- ClassDB::bind_method(_MD("is_flipped_v"),&AnimatedSprite::is_flipped_v);
+ ClassDB::bind_method(D_METHOD("set_flip_v","flip_v"),&AnimatedSprite::set_flip_v);
+ ClassDB::bind_method(D_METHOD("is_flipped_v"),&AnimatedSprite::is_flipped_v);
- ClassDB::bind_method(_MD("set_frame","frame"),&AnimatedSprite::set_frame);
- ClassDB::bind_method(_MD("get_frame"),&AnimatedSprite::get_frame);
+ ClassDB::bind_method(D_METHOD("set_frame","frame"),&AnimatedSprite::set_frame);
+ ClassDB::bind_method(D_METHOD("get_frame"),&AnimatedSprite::get_frame);
- ClassDB::bind_method(_MD("_res_changed"),&AnimatedSprite::_res_changed);
+ ClassDB::bind_method(D_METHOD("_res_changed"),&AnimatedSprite::_res_changed);
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_SIGNAL(MethodInfo("animation_finished"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames"));
- ADD_PROPERTY( PropertyInfo( Variant::STRING, "animation"), _SCS("set_animation"),_SCS("get_animation"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "playing"), _SCS("_set_playing"),_SCS("_is_playing"));
- ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), "set_sprite_frames","get_sprite_frames");
+ ADD_PROPERTY( PropertyInfo( Variant::STRING, "animation"), "set_animation","get_animation");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), "set_frame","get_frame");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "playing"), "_set_playing","_is_playing");
+ ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), "set_centered","is_centered");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), "set_offset","get_offset");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), "set_flip_h","is_flipped_h");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), "set_flip_v","is_flipped_v");
}
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 61ed362cf0..55c7716b6b 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -357,6 +357,10 @@ void Area2D::_clear_monitoring() {
Object *obj = ObjectDB::get_instance(E->key());
Node *node = obj ? obj->cast_to<Node>() : NULL;
ERR_CONTINUE(!node);
+
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered,this,SceneStringNames::get_singleton()->_body_enter_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_exited,this,SceneStringNames::get_singleton()->_body_exit_tree);
+
if (!E->get().in_tree)
continue;
@@ -366,9 +370,6 @@ void Area2D::_clear_monitoring() {
}
emit_signal(SceneStringNames::get_singleton()->body_exited,obj);
-
- node->disconnect(SceneStringNames::get_singleton()->tree_entered,this,SceneStringNames::get_singleton()->_body_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exited,this,SceneStringNames::get_singleton()->_body_exit_tree);
}
}
@@ -388,6 +389,9 @@ void Area2D::_clear_monitoring() {
continue;
//ERR_CONTINUE(!node);
+ node->disconnect(SceneStringNames::get_singleton()->tree_entered,this,SceneStringNames::get_singleton()->_area_enter_tree);
+ node->disconnect(SceneStringNames::get_singleton()->tree_exited,this,SceneStringNames::get_singleton()->_area_exit_tree);
+
if (!E->get().in_tree)
continue;
@@ -397,9 +401,6 @@ void Area2D::_clear_monitoring() {
}
emit_signal(SceneStringNames::get_singleton()->area_exited,obj);
-
- node->disconnect(SceneStringNames::get_singleton()->tree_entered,this,SceneStringNames::get_singleton()->_area_enter_tree);
- node->disconnect(SceneStringNames::get_singleton()->tree_exited,this,SceneStringNames::get_singleton()->_area_exit_tree);
}
}
@@ -587,62 +588,62 @@ bool Area2D::get_layer_mask_bit(int p_bit) const{
void Area2D::_bind_methods() {
- ClassDB::bind_method(_MD("_body_enter_tree","id"),&Area2D::_body_enter_tree);
- ClassDB::bind_method(_MD("_body_exit_tree","id"),&Area2D::_body_exit_tree);
+ ClassDB::bind_method(D_METHOD("_body_enter_tree","id"),&Area2D::_body_enter_tree);
+ ClassDB::bind_method(D_METHOD("_body_exit_tree","id"),&Area2D::_body_exit_tree);
- ClassDB::bind_method(_MD("_area_enter_tree","id"),&Area2D::_area_enter_tree);
- ClassDB::bind_method(_MD("_area_exit_tree","id"),&Area2D::_area_exit_tree);
+ ClassDB::bind_method(D_METHOD("_area_enter_tree","id"),&Area2D::_area_enter_tree);
+ ClassDB::bind_method(D_METHOD("_area_exit_tree","id"),&Area2D::_area_exit_tree);
- ClassDB::bind_method(_MD("set_space_override_mode","enable"),&Area2D::set_space_override_mode);
- ClassDB::bind_method(_MD("get_space_override_mode"),&Area2D::get_space_override_mode);
+ ClassDB::bind_method(D_METHOD("set_space_override_mode","enable"),&Area2D::set_space_override_mode);
+ ClassDB::bind_method(D_METHOD("get_space_override_mode"),&Area2D::get_space_override_mode);
- ClassDB::bind_method(_MD("set_gravity_is_point","enable"),&Area2D::set_gravity_is_point);
- ClassDB::bind_method(_MD("is_gravity_a_point"),&Area2D::is_gravity_a_point);
+ ClassDB::bind_method(D_METHOD("set_gravity_is_point","enable"),&Area2D::set_gravity_is_point);
+ ClassDB::bind_method(D_METHOD("is_gravity_a_point"),&Area2D::is_gravity_a_point);
- ClassDB::bind_method(_MD("set_gravity_distance_scale","distance_scale"),&Area2D::set_gravity_distance_scale);
- ClassDB::bind_method(_MD("get_gravity_distance_scale"),&Area2D::get_gravity_distance_scale);
+ ClassDB::bind_method(D_METHOD("set_gravity_distance_scale","distance_scale"),&Area2D::set_gravity_distance_scale);
+ ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"),&Area2D::get_gravity_distance_scale);
- ClassDB::bind_method(_MD("set_gravity_vector","vector"),&Area2D::set_gravity_vector);
- ClassDB::bind_method(_MD("get_gravity_vector"),&Area2D::get_gravity_vector);
+ ClassDB::bind_method(D_METHOD("set_gravity_vector","vector"),&Area2D::set_gravity_vector);
+ ClassDB::bind_method(D_METHOD("get_gravity_vector"),&Area2D::get_gravity_vector);
- ClassDB::bind_method(_MD("set_gravity","gravity"),&Area2D::set_gravity);
- ClassDB::bind_method(_MD("get_gravity"),&Area2D::get_gravity);
+ ClassDB::bind_method(D_METHOD("set_gravity","gravity"),&Area2D::set_gravity);
+ ClassDB::bind_method(D_METHOD("get_gravity"),&Area2D::get_gravity);
- ClassDB::bind_method(_MD("set_linear_damp","linear_damp"),&Area2D::set_linear_damp);
- ClassDB::bind_method(_MD("get_linear_damp"),&Area2D::get_linear_damp);
+ ClassDB::bind_method(D_METHOD("set_linear_damp","linear_damp"),&Area2D::set_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_linear_damp"),&Area2D::get_linear_damp);
- ClassDB::bind_method(_MD("set_angular_damp","angular_damp"),&Area2D::set_angular_damp);
- ClassDB::bind_method(_MD("get_angular_damp"),&Area2D::get_angular_damp);
+ ClassDB::bind_method(D_METHOD("set_angular_damp","angular_damp"),&Area2D::set_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_angular_damp"),&Area2D::get_angular_damp);
- ClassDB::bind_method(_MD("set_priority","priority"),&Area2D::set_priority);
- ClassDB::bind_method(_MD("get_priority"),&Area2D::get_priority);
+ ClassDB::bind_method(D_METHOD("set_priority","priority"),&Area2D::set_priority);
+ ClassDB::bind_method(D_METHOD("get_priority"),&Area2D::get_priority);
- ClassDB::bind_method(_MD("set_collision_mask","collision_mask"),&Area2D::set_collision_mask);
- ClassDB::bind_method(_MD("get_collision_mask"),&Area2D::get_collision_mask);
+ ClassDB::bind_method(D_METHOD("set_collision_mask","collision_mask"),&Area2D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"),&Area2D::get_collision_mask);
- ClassDB::bind_method(_MD("set_layer_mask","layer_mask"),&Area2D::set_layer_mask);
- ClassDB::bind_method(_MD("get_layer_mask"),&Area2D::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&Area2D::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&Area2D::get_layer_mask);
- ClassDB::bind_method(_MD("set_collision_mask_bit","bit","value"),&Area2D::set_collision_mask_bit);
- ClassDB::bind_method(_MD("get_collision_mask_bit","bit"),&Area2D::get_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit","bit","value"),&Area2D::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit","bit"),&Area2D::get_collision_mask_bit);
- ClassDB::bind_method(_MD("set_layer_mask_bit","bit","value"),&Area2D::set_layer_mask_bit);
- ClassDB::bind_method(_MD("get_layer_mask_bit","bit"),&Area2D::get_layer_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_layer_mask_bit","bit","value"),&Area2D::set_layer_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_layer_mask_bit","bit"),&Area2D::get_layer_mask_bit);
- ClassDB::bind_method(_MD("set_monitoring","enable"),&Area2D::set_monitoring);
- ClassDB::bind_method(_MD("is_monitoring"),&Area2D::is_monitoring);
+ ClassDB::bind_method(D_METHOD("set_monitoring","enable"),&Area2D::set_monitoring);
+ ClassDB::bind_method(D_METHOD("is_monitoring"),&Area2D::is_monitoring);
- ClassDB::bind_method(_MD("set_monitorable","enable"),&Area2D::set_monitorable);
- ClassDB::bind_method(_MD("is_monitorable"),&Area2D::is_monitorable);
+ ClassDB::bind_method(D_METHOD("set_monitorable","enable"),&Area2D::set_monitorable);
+ ClassDB::bind_method(D_METHOD("is_monitorable"),&Area2D::is_monitorable);
- ClassDB::bind_method(_MD("get_overlapping_bodies"),&Area2D::get_overlapping_bodies);
- ClassDB::bind_method(_MD("get_overlapping_areas"),&Area2D::get_overlapping_areas);
+ ClassDB::bind_method(D_METHOD("get_overlapping_bodies"),&Area2D::get_overlapping_bodies);
+ ClassDB::bind_method(D_METHOD("get_overlapping_areas"),&Area2D::get_overlapping_areas);
- ClassDB::bind_method(_MD("overlaps_body","body"),&Area2D::overlaps_body);
- ClassDB::bind_method(_MD("overlaps_area","area"),&Area2D::overlaps_area);
+ ClassDB::bind_method(D_METHOD("overlaps_body","body"),&Area2D::overlaps_body);
+ ClassDB::bind_method(D_METHOD("overlaps_area","area"),&Area2D::overlaps_area);
- ClassDB::bind_method(_MD("_body_inout"),&Area2D::_body_inout);
- ClassDB::bind_method(_MD("_area_inout"),&Area2D::_area_inout);
+ ClassDB::bind_method(D_METHOD("_body_inout"),&Area2D::_body_inout);
+ ClassDB::bind_method(D_METHOD("_area_inout"),&Area2D::_area_inout);
ADD_SIGNAL( MethodInfo("body_shape_entered",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body",PROPERTY_HINT_RESOURCE_TYPE,"PhysicsBody2D"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
@@ -656,19 +657,19 @@ void Area2D::_bind_methods() {
ADD_SIGNAL( MethodInfo("area_exited",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area2D")));
- 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"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.001"),_SCS("set_gravity"),_SCS("get_gravity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,100,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,100,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
- ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
- ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_monitoring"),_SCS("is_monitoring"));
- ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
+ ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Combine-Replace,Replace,Replace-Combine"),"set_space_override_mode","get_space_override_mode");
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"gravity_point"),"set_gravity_is_point","is_gravity_a_point");
+ ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),"set_gravity_distance_scale","get_gravity_distance_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"gravity_vec"),"set_gravity_vector","get_gravity_vector");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.001"),"set_gravity","get_gravity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,100,0.01"),"set_linear_damp","get_linear_damp");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,100,0.01"),"set_angular_damp","get_angular_damp");
+ ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),"set_priority","get_priority");
+ ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitoring"),"set_monitoring","is_monitoring");
+ ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitorable"),"set_monitorable","is_monitorable");
ADD_GROUP("Collision","collision_");
- ADD_PROPERTYNO( PropertyInfo(Variant::INT,"collision_layers",PROPERTY_HINT_LAYERS_2D_PHYSICS),_SCS("set_layer_mask"),_SCS("get_layer_mask"));
- ADD_PROPERTYNO( PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
+ ADD_PROPERTYNO( PropertyInfo(Variant::INT,"collision_layers",PROPERTY_HINT_LAYERS_2D_PHYSICS),"set_layer_mask","get_layer_mask");
+ ADD_PROPERTYNO( PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),"set_collision_mask","get_collision_mask");
}
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
index bbeed322b1..eaa33fe70a 100644
--- a/scene/2d/back_buffer_copy.cpp
+++ b/scene/2d/back_buffer_copy.cpp
@@ -77,14 +77,14 @@ BackBufferCopy::CopyMode BackBufferCopy::get_copy_mode() const{
void BackBufferCopy::_bind_methods() {
- ClassDB::bind_method(_MD("set_rect","rect"),&BackBufferCopy::set_rect);
- ClassDB::bind_method(_MD("get_rect"),&BackBufferCopy::get_rect);
+ ClassDB::bind_method(D_METHOD("set_rect","rect"),&BackBufferCopy::set_rect);
+ ClassDB::bind_method(D_METHOD("get_rect"),&BackBufferCopy::get_rect);
- ClassDB::bind_method(_MD("set_copy_mode","copy_mode"),&BackBufferCopy::set_copy_mode);
- ClassDB::bind_method(_MD("get_copy_mode"),&BackBufferCopy::get_copy_mode);
+ ClassDB::bind_method(D_METHOD("set_copy_mode","copy_mode"),&BackBufferCopy::set_copy_mode);
+ ClassDB::bind_method(D_METHOD("get_copy_mode"),&BackBufferCopy::get_copy_mode);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"copy_mode",PROPERTY_HINT_ENUM,"Disabled,Rect,Viewport"),_SCS("set_copy_mode"),_SCS("get_copy_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),_SCS("set_rect"),_SCS("get_rect"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"copy_mode",PROPERTY_HINT_ENUM,"Disabled,Rect,Viewport"),"set_copy_mode","get_copy_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),"set_rect","get_rect");
BIND_CONSTANT( COPY_MODE_DISABLED );
BIND_CONSTANT( COPY_MODE_RECT );
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 0bafef1b83..9ae2315867 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -590,92 +590,92 @@ Node* Camera2D::get_custom_viewport() const {
void Camera2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_offset","offset"),&Camera2D::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&Camera2D::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&Camera2D::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&Camera2D::get_offset);
- ClassDB::bind_method(_MD("set_anchor_mode","anchor_mode"),&Camera2D::set_anchor_mode);
- ClassDB::bind_method(_MD("get_anchor_mode"),&Camera2D::get_anchor_mode);
+ ClassDB::bind_method(D_METHOD("set_anchor_mode","anchor_mode"),&Camera2D::set_anchor_mode);
+ ClassDB::bind_method(D_METHOD("get_anchor_mode"),&Camera2D::get_anchor_mode);
- ClassDB::bind_method(_MD("set_rotating","rotating"),&Camera2D::set_rotating);
- ClassDB::bind_method(_MD("is_rotating"),&Camera2D::is_rotating);
+ ClassDB::bind_method(D_METHOD("set_rotating","rotating"),&Camera2D::set_rotating);
+ ClassDB::bind_method(D_METHOD("is_rotating"),&Camera2D::is_rotating);
- ClassDB::bind_method(_MD("make_current"),&Camera2D::make_current);
- ClassDB::bind_method(_MD("clear_current"),&Camera2D::clear_current);
- ClassDB::bind_method(_MD("_make_current"),&Camera2D::_make_current);
+ ClassDB::bind_method(D_METHOD("make_current"),&Camera2D::make_current);
+ ClassDB::bind_method(D_METHOD("clear_current"),&Camera2D::clear_current);
+ ClassDB::bind_method(D_METHOD("_make_current"),&Camera2D::_make_current);
- ClassDB::bind_method(_MD("_update_scroll"),&Camera2D::_update_scroll);
+ ClassDB::bind_method(D_METHOD("_update_scroll"),&Camera2D::_update_scroll);
- ClassDB::bind_method(_MD("_set_current","current"),&Camera2D::_set_current);
- ClassDB::bind_method(_MD("is_current"),&Camera2D::is_current);
+ ClassDB::bind_method(D_METHOD("_set_current","current"),&Camera2D::_set_current);
+ ClassDB::bind_method(D_METHOD("is_current"),&Camera2D::is_current);
- ClassDB::bind_method(_MD("set_limit","margin","limit"),&Camera2D::set_limit);
- ClassDB::bind_method(_MD("get_limit","margin"),&Camera2D::get_limit);
+ ClassDB::bind_method(D_METHOD("set_limit","margin","limit"),&Camera2D::set_limit);
+ ClassDB::bind_method(D_METHOD("get_limit","margin"),&Camera2D::get_limit);
- ClassDB::bind_method(_MD("set_limit_smoothing_enabled","limit_smoothing_enabled"),&Camera2D::set_limit_smoothing_enabled);
- ClassDB::bind_method(_MD("is_limit_smoothing_enabled"),&Camera2D::is_limit_smoothing_enabled);
+ ClassDB::bind_method(D_METHOD("set_limit_smoothing_enabled","limit_smoothing_enabled"),&Camera2D::set_limit_smoothing_enabled);
+ ClassDB::bind_method(D_METHOD("is_limit_smoothing_enabled"),&Camera2D::is_limit_smoothing_enabled);
- ClassDB::bind_method(_MD("set_v_drag_enabled","enabled"),&Camera2D::set_v_drag_enabled);
- ClassDB::bind_method(_MD("is_v_drag_enabled"),&Camera2D::is_v_drag_enabled);
+ ClassDB::bind_method(D_METHOD("set_v_drag_enabled","enabled"),&Camera2D::set_v_drag_enabled);
+ ClassDB::bind_method(D_METHOD("is_v_drag_enabled"),&Camera2D::is_v_drag_enabled);
- ClassDB::bind_method(_MD("set_h_drag_enabled","enabled"),&Camera2D::set_h_drag_enabled);
- ClassDB::bind_method(_MD("is_h_drag_enabled"),&Camera2D::is_h_drag_enabled);
+ ClassDB::bind_method(D_METHOD("set_h_drag_enabled","enabled"),&Camera2D::set_h_drag_enabled);
+ ClassDB::bind_method(D_METHOD("is_h_drag_enabled"),&Camera2D::is_h_drag_enabled);
- ClassDB::bind_method(_MD("set_v_offset","ofs"),&Camera2D::set_v_offset);
- ClassDB::bind_method(_MD("get_v_offset"),&Camera2D::get_v_offset);
+ ClassDB::bind_method(D_METHOD("set_v_offset","ofs"),&Camera2D::set_v_offset);
+ ClassDB::bind_method(D_METHOD("get_v_offset"),&Camera2D::get_v_offset);
- ClassDB::bind_method(_MD("set_h_offset","ofs"),&Camera2D::set_h_offset);
- ClassDB::bind_method(_MD("get_h_offset"),&Camera2D::get_h_offset);
+ ClassDB::bind_method(D_METHOD("set_h_offset","ofs"),&Camera2D::set_h_offset);
+ ClassDB::bind_method(D_METHOD("get_h_offset"),&Camera2D::get_h_offset);
- ClassDB::bind_method(_MD("set_drag_margin","margin","drag_margin"),&Camera2D::set_drag_margin);
- ClassDB::bind_method(_MD("get_drag_margin","margin"),&Camera2D::get_drag_margin);
+ ClassDB::bind_method(D_METHOD("set_drag_margin","margin","drag_margin"),&Camera2D::set_drag_margin);
+ ClassDB::bind_method(D_METHOD("get_drag_margin","margin"),&Camera2D::get_drag_margin);
- ClassDB::bind_method(_MD("get_camera_pos"),&Camera2D::get_camera_pos);
- ClassDB::bind_method(_MD("get_camera_screen_center"),&Camera2D::get_camera_screen_center);
+ ClassDB::bind_method(D_METHOD("get_camera_pos"),&Camera2D::get_camera_pos);
+ ClassDB::bind_method(D_METHOD("get_camera_screen_center"),&Camera2D::get_camera_screen_center);
- ClassDB::bind_method(_MD("set_zoom","zoom"),&Camera2D::set_zoom);
- ClassDB::bind_method(_MD("get_zoom"),&Camera2D::get_zoom);
+ ClassDB::bind_method(D_METHOD("set_zoom","zoom"),&Camera2D::set_zoom);
+ ClassDB::bind_method(D_METHOD("get_zoom"),&Camera2D::get_zoom);
- ClassDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&Camera2D::set_custom_viewport);
- ClassDB::bind_method(_MD("get_custom_viewport:Viewport"),&Camera2D::get_custom_viewport);
+ ClassDB::bind_method(D_METHOD("set_custom_viewport","viewport:Viewport"),&Camera2D::set_custom_viewport);
+ ClassDB::bind_method(D_METHOD("get_custom_viewport:Viewport"),&Camera2D::get_custom_viewport);
- ClassDB::bind_method(_MD("set_follow_smoothing","follow_smoothing"),&Camera2D::set_follow_smoothing);
- ClassDB::bind_method(_MD("get_follow_smoothing"),&Camera2D::get_follow_smoothing);
+ ClassDB::bind_method(D_METHOD("set_follow_smoothing","follow_smoothing"),&Camera2D::set_follow_smoothing);
+ ClassDB::bind_method(D_METHOD("get_follow_smoothing"),&Camera2D::get_follow_smoothing);
- ClassDB::bind_method(_MD("set_enable_follow_smoothing","follow_smoothing"),&Camera2D::set_enable_follow_smoothing);
- ClassDB::bind_method(_MD("is_follow_smoothing_enabled"),&Camera2D::is_follow_smoothing_enabled);
+ ClassDB::bind_method(D_METHOD("set_enable_follow_smoothing","follow_smoothing"),&Camera2D::set_enable_follow_smoothing);
+ ClassDB::bind_method(D_METHOD("is_follow_smoothing_enabled"),&Camera2D::is_follow_smoothing_enabled);
- ClassDB::bind_method(_MD("force_update_scroll"),&Camera2D::force_update_scroll);
- ClassDB::bind_method(_MD("reset_smoothing"),&Camera2D::reset_smoothing);
- ClassDB::bind_method(_MD("align"),&Camera2D::align);
+ ClassDB::bind_method(D_METHOD("force_update_scroll"),&Camera2D::force_update_scroll);
+ ClassDB::bind_method(D_METHOD("reset_smoothing"),&Camera2D::reset_smoothing);
+ ClassDB::bind_method(D_METHOD("align"),&Camera2D::align);
- ClassDB::bind_method(_MD("_set_old_smoothing","follow_smoothing"),&Camera2D::_set_old_smoothing);
+ ClassDB::bind_method(D_METHOD("_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::VECTOR2,"zoom"),_SCS("set_zoom"),_SCS("get_zoom") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"offset"),"set_offset","get_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"anchor_mode",PROPERTY_HINT_ENUM,"Fixed TopLeft,Drag Center"),"set_anchor_mode","get_anchor_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"rotating"),"set_rotating","is_rotating");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"current"),"_set_current","is_current");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"zoom"),"set_zoom","get_zoom") ;
ADD_GROUP("Limit","limit_");
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_left"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_LEFT);
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_top"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_TOP);
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_right"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_RIGHT);
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_bottom"),_SCS("set_limit"),_SCS("get_limit"),MARGIN_BOTTOM);
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"limit_smoothed"),_SCS("set_limit_smoothing_enabled"),_SCS("is_limit_smoothing_enabled") );
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_left"),"set_limit","get_limit",MARGIN_LEFT);
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_top"),"set_limit","get_limit",MARGIN_TOP);
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_right"),"set_limit","get_limit",MARGIN_RIGHT);
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"limit_bottom"),"set_limit","get_limit",MARGIN_BOTTOM);
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"limit_smoothed"),"set_limit_smoothing_enabled","is_limit_smoothing_enabled") ;
ADD_GROUP("Draw Margin","draw_margin_");
- 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,"drag_margin_h_enabled"),"set_h_drag_enabled","is_h_drag_enabled") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"drag_margin_v_enabled"),"set_v_drag_enabled","is_v_drag_enabled") ;
ADD_GROUP("Smoothing","smoothing_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"smoothing_enabled"),_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") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"smoothing_enabled"),"set_enable_follow_smoothing","is_follow_smoothing_enabled") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"smoothing_speed"),"set_follow_smoothing","get_follow_smoothing") ;
ADD_GROUP("Drag Margin","drag_margin_");
- 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);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin_bottom",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drag_margin"),_SCS("get_drag_margin"),MARGIN_BOTTOM);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin_left",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_drag_margin","get_drag_margin",MARGIN_LEFT);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin_top",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_drag_margin","get_drag_margin",MARGIN_TOP);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin_right",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_drag_margin","get_drag_margin",MARGIN_RIGHT);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"drag_margin_bottom",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_drag_margin","get_drag_margin",MARGIN_BOTTOM);
BIND_CONSTANT( ANCHOR_MODE_DRAG_CENTER );
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 817707f96e..4f7acf7f97 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -135,10 +135,10 @@ Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
void CanvasItemMaterial::_bind_methods() {
- ClassDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
- ClassDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
- ClassDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
- ClassDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
+ ClassDB::bind_method(D_METHOD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader);
+ ClassDB::bind_method(D_METHOD("get_shader:Shader"),&CanvasItemMaterial::get_shader);
+ ClassDB::bind_method(D_METHOD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param);
+ ClassDB::bind_method(D_METHOD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param);
@@ -747,12 +747,12 @@ float CanvasItem::draw_char(const Ref<Font>& p_font,const Point2& p_pos, const S
void CanvasItem::_notify_transform(CanvasItem *p_node) {
- if (p_node->xform_change.in_list() && p_node->global_invalid)
+ if (/*p_node->xform_change.in_list() &&*/ p_node->global_invalid)
return; //nothing to do
p_node->global_invalid=true;
- if (notify_transform && !p_node->xform_change.in_list()) {
+ if (p_node->notify_transform && !p_node->xform_change.in_list()) {
if (!p_node->block_transform_notify) {
if (p_node->is_inside_tree())
get_tree()->xform_change_list.add(&p_node->xform_change);
@@ -905,105 +905,105 @@ Vector2 CanvasItem::get_local_mouse_pos() const{
void CanvasItem::_bind_methods() {
- ClassDB::bind_method(_MD("_toplevel_raise_self"),&CanvasItem::_toplevel_raise_self);
- ClassDB::bind_method(_MD("_update_callback"),&CanvasItem::_update_callback);
-
- ClassDB::bind_method(_MD("edit_set_state","state"),&CanvasItem::edit_set_state);
- ClassDB::bind_method(_MD("edit_get_state:Variant"),&CanvasItem::edit_get_state);
- ClassDB::bind_method(_MD("edit_set_rect","rect"),&CanvasItem::edit_set_rect);
- ClassDB::bind_method(_MD("edit_rotate","degrees"),&CanvasItem::edit_rotate);
-
- ClassDB::bind_method(_MD("get_item_rect"),&CanvasItem::get_item_rect);
- ClassDB::bind_method(_MD("get_item_and_children_rect"),&CanvasItem::get_item_and_children_rect);
- //ClassDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
-
- ClassDB::bind_method(_MD("get_canvas_item"),&CanvasItem::get_canvas_item);
-
- ClassDB::bind_method(_MD("set_visible"),&CanvasItem::set_visible);
- ClassDB::bind_method(_MD("is_visible"),&CanvasItem::is_visible);
- ClassDB::bind_method(_MD("is_visible_in_tree"),&CanvasItem::is_visible_in_tree);
- ClassDB::bind_method(_MD("show"),&CanvasItem::show);
- ClassDB::bind_method(_MD("hide"),&CanvasItem::hide);
-
- ClassDB::bind_method(_MD("update"),&CanvasItem::update);
-
- ClassDB::bind_method(_MD("set_as_toplevel","enable"),&CanvasItem::set_as_toplevel);
- ClassDB::bind_method(_MD("is_set_as_toplevel"),&CanvasItem::is_set_as_toplevel);
-
- ClassDB::bind_method(_MD("set_light_mask","light_mask"),&CanvasItem::set_light_mask);
- ClassDB::bind_method(_MD("get_light_mask"),&CanvasItem::get_light_mask);
-
- ClassDB::bind_method(_MD("set_modulate","modulate"),&CanvasItem::set_modulate);
- ClassDB::bind_method(_MD("get_modulate"),&CanvasItem::get_modulate);
- ClassDB::bind_method(_MD("set_self_modulate","self_modulate"),&CanvasItem::set_self_modulate);
- ClassDB::bind_method(_MD("get_self_modulate"),&CanvasItem::get_self_modulate);
-
- ClassDB::bind_method(_MD("set_draw_behind_parent","enable"),&CanvasItem::set_draw_behind_parent);
- ClassDB::bind_method(_MD("is_draw_behind_parent_enabled"),&CanvasItem::is_draw_behind_parent_enabled);
-
- ClassDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
- ClassDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top);
- //ClassDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
-
- ClassDB::bind_method(_MD("draw_line","from","to","color","width","antialiased"),&CanvasItem::draw_line,DEFVAL(1.0),DEFVAL(false));
- ClassDB::bind_method(_MD("draw_rect","rect","color"),&CanvasItem::draw_rect);
- ClassDB::bind_method(_MD("draw_circle","pos","radius","color"),&CanvasItem::draw_circle);
- ClassDB::bind_method(_MD("draw_texture","texture:Texture","pos","modulate"),&CanvasItem::draw_texture,DEFVAL(Color(1,1,1,1)));
- ClassDB::bind_method(_MD("draw_texture_rect","texture:Texture","rect","tile","modulate","transpose"),&CanvasItem::draw_texture_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
- ClassDB::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));
- ClassDB::bind_method(_MD("draw_style_box","style_box:StyleBox","rect"),&CanvasItem::draw_style_box);
- ClassDB::bind_method(_MD("draw_primitive","points","colors","uvs","texture:Texture","width"),&CanvasItem::draw_primitive,DEFVAL(Variant()),DEFVAL(1.0));
- ClassDB::bind_method(_MD("draw_polygon","points","colors","uvs","texture:Texture"),&CanvasItem::draw_polygon,DEFVAL(PoolVector2Array()),DEFVAL(Variant()));
- ClassDB::bind_method(_MD("draw_colored_polygon","points","color","uvs","texture:Texture"),&CanvasItem::draw_colored_polygon,DEFVAL(PoolVector2Array()),DEFVAL(Variant()));
- ClassDB::bind_method(_MD("draw_string","font:Font","pos","text","modulate","clip_w"),&CanvasItem::draw_string,DEFVAL(Color(1,1,1)),DEFVAL(-1));
- ClassDB::bind_method(_MD("draw_char","font:Font","pos","char","next","modulate"),&CanvasItem::draw_char,DEFVAL(Color(1,1,1)));
-
- ClassDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
- ClassDB::bind_method(_MD("draw_set_transform_matrix","xform"),&CanvasItem::draw_set_transform_matrix);
- ClassDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
- ClassDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform);
- ClassDB::bind_method(_MD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas);
- ClassDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform);
- ClassDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
- ClassDB::bind_method(_MD("get_canvas_transform"),&CanvasItem::get_canvas_transform);
- ClassDB::bind_method(_MD("get_local_mouse_pos"),&CanvasItem::get_local_mouse_pos);
- ClassDB::bind_method(_MD("get_global_mouse_pos"),&CanvasItem::get_global_mouse_pos);
- ClassDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas);
- ClassDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d);
- //ClassDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
-
- ClassDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material);
- ClassDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material);
-
- ClassDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material);
- ClassDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material);
-
- ClassDB::bind_method(_MD("set_notify_local_transform","enable"),&CanvasItem::set_notify_local_transform);
- ClassDB::bind_method(_MD("is_local_transform_notification_enabled"),&CanvasItem::is_local_transform_notification_enabled);
-
- ClassDB::bind_method(_MD("set_notify_transform","enable"),&CanvasItem::set_notify_transform);
- ClassDB::bind_method(_MD("is_transform_notification_enabled"),&CanvasItem::is_transform_notification_enabled);
-
- ClassDB::bind_method(_MD("make_canvas_pos_local","screen_point"),
+ ClassDB::bind_method(D_METHOD("_toplevel_raise_self"),&CanvasItem::_toplevel_raise_self);
+ ClassDB::bind_method(D_METHOD("_update_callback"),&CanvasItem::_update_callback);
+
+ ClassDB::bind_method(D_METHOD("edit_set_state","state"),&CanvasItem::edit_set_state);
+ ClassDB::bind_method(D_METHOD("edit_get_state:Variant"),&CanvasItem::edit_get_state);
+ ClassDB::bind_method(D_METHOD("edit_set_rect","rect"),&CanvasItem::edit_set_rect);
+ ClassDB::bind_method(D_METHOD("edit_rotate","degrees"),&CanvasItem::edit_rotate);
+
+ ClassDB::bind_method(D_METHOD("get_item_rect"),&CanvasItem::get_item_rect);
+ ClassDB::bind_method(D_METHOD("get_item_and_children_rect"),&CanvasItem::get_item_and_children_rect);
+ //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform);
+
+ ClassDB::bind_method(D_METHOD("get_canvas_item"),&CanvasItem::get_canvas_item);
+
+ ClassDB::bind_method(D_METHOD("set_visible"),&CanvasItem::set_visible);
+ ClassDB::bind_method(D_METHOD("is_visible"),&CanvasItem::is_visible);
+ ClassDB::bind_method(D_METHOD("is_visible_in_tree"),&CanvasItem::is_visible_in_tree);
+ ClassDB::bind_method(D_METHOD("show"),&CanvasItem::show);
+ ClassDB::bind_method(D_METHOD("hide"),&CanvasItem::hide);
+
+ ClassDB::bind_method(D_METHOD("update"),&CanvasItem::update);
+
+ ClassDB::bind_method(D_METHOD("set_as_toplevel","enable"),&CanvasItem::set_as_toplevel);
+ ClassDB::bind_method(D_METHOD("is_set_as_toplevel"),&CanvasItem::is_set_as_toplevel);
+
+ ClassDB::bind_method(D_METHOD("set_light_mask","light_mask"),&CanvasItem::set_light_mask);
+ ClassDB::bind_method(D_METHOD("get_light_mask"),&CanvasItem::get_light_mask);
+
+ ClassDB::bind_method(D_METHOD("set_modulate","modulate"),&CanvasItem::set_modulate);
+ ClassDB::bind_method(D_METHOD("get_modulate"),&CanvasItem::get_modulate);
+ ClassDB::bind_method(D_METHOD("set_self_modulate","self_modulate"),&CanvasItem::set_self_modulate);
+ ClassDB::bind_method(D_METHOD("get_self_modulate"),&CanvasItem::get_self_modulate);
+
+ ClassDB::bind_method(D_METHOD("set_draw_behind_parent","enable"),&CanvasItem::set_draw_behind_parent);
+ ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"),&CanvasItem::is_draw_behind_parent_enabled);
+
+ ClassDB::bind_method(D_METHOD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
+ ClassDB::bind_method(D_METHOD("_is_on_top"),&CanvasItem::_is_on_top);
+ //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform);
+
+ ClassDB::bind_method(D_METHOD("draw_line","from","to","color","width","antialiased"),&CanvasItem::draw_line,DEFVAL(1.0),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_rect","rect","color"),&CanvasItem::draw_rect);
+ ClassDB::bind_method(D_METHOD("draw_circle","pos","radius","color"),&CanvasItem::draw_circle);
+ ClassDB::bind_method(D_METHOD("draw_texture","texture:Texture","pos","modulate"),&CanvasItem::draw_texture,DEFVAL(Color(1,1,1,1)));
+ ClassDB::bind_method(D_METHOD("draw_texture_rect","texture:Texture","rect","tile","modulate","transpose"),&CanvasItem::draw_texture_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_texture_rect_region","texture:Texture","rect","src_rect","modulate","transpose"),&CanvasItem::draw_texture_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_style_box","style_box:StyleBox","rect"),&CanvasItem::draw_style_box);
+ ClassDB::bind_method(D_METHOD("draw_primitive","points","colors","uvs","texture:Texture","width"),&CanvasItem::draw_primitive,DEFVAL(Variant()),DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("draw_polygon","points","colors","uvs","texture:Texture"),&CanvasItem::draw_polygon,DEFVAL(PoolVector2Array()),DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("draw_colored_polygon","points","color","uvs","texture:Texture"),&CanvasItem::draw_colored_polygon,DEFVAL(PoolVector2Array()),DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("draw_string","font:Font","pos","text","modulate","clip_w"),&CanvasItem::draw_string,DEFVAL(Color(1,1,1)),DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("draw_char","font:Font","pos","char","next","modulate"),&CanvasItem::draw_char,DEFVAL(Color(1,1,1)));
+
+ ClassDB::bind_method(D_METHOD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform);
+ ClassDB::bind_method(D_METHOD("draw_set_transform_matrix","xform"),&CanvasItem::draw_set_transform_matrix);
+ ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform);
+ ClassDB::bind_method(D_METHOD("get_global_transform"),&CanvasItem::get_global_transform);
+ ClassDB::bind_method(D_METHOD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas);
+ ClassDB::bind_method(D_METHOD("get_viewport_transform"),&CanvasItem::get_viewport_transform);
+ ClassDB::bind_method(D_METHOD("get_viewport_rect"),&CanvasItem::get_viewport_rect);
+ ClassDB::bind_method(D_METHOD("get_canvas_transform"),&CanvasItem::get_canvas_transform);
+ ClassDB::bind_method(D_METHOD("get_local_mouse_pos"),&CanvasItem::get_local_mouse_pos);
+ ClassDB::bind_method(D_METHOD("get_global_mouse_pos"),&CanvasItem::get_global_mouse_pos);
+ ClassDB::bind_method(D_METHOD("get_canvas"),&CanvasItem::get_canvas);
+ ClassDB::bind_method(D_METHOD("get_world_2d"),&CanvasItem::get_world_2d);
+ //ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasItem::get_viewport);
+
+ ClassDB::bind_method(D_METHOD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material);
+ ClassDB::bind_method(D_METHOD("get_material:CanvasItemMaterial"),&CanvasItem::get_material);
+
+ ClassDB::bind_method(D_METHOD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material);
+ ClassDB::bind_method(D_METHOD("get_use_parent_material"),&CanvasItem::get_use_parent_material);
+
+ ClassDB::bind_method(D_METHOD("set_notify_local_transform","enable"),&CanvasItem::set_notify_local_transform);
+ ClassDB::bind_method(D_METHOD("is_local_transform_notification_enabled"),&CanvasItem::is_local_transform_notification_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_notify_transform","enable"),&CanvasItem::set_notify_transform);
+ ClassDB::bind_method(D_METHOD("is_transform_notification_enabled"),&CanvasItem::is_transform_notification_enabled);
+
+ ClassDB::bind_method(D_METHOD("make_canvas_pos_local","screen_point"),
&CanvasItem::make_canvas_pos_local);
- ClassDB::bind_method(_MD("make_input_local","event"),&CanvasItem::make_input_local);
+ ClassDB::bind_method(D_METHOD("make_input_local","event"),&CanvasItem::make_input_local);
BIND_VMETHOD(MethodInfo("_draw"));
ADD_GROUP("Visibility","");
- ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"visible"), _SCS("set_visible"),_SCS("is_visible") );
- ADD_PROPERTYNO( PropertyInfo(Variant::COLOR,"modulate"), _SCS("set_modulate"),_SCS("get_modulate") );
- ADD_PROPERTYNO( PropertyInfo(Variant::COLOR,"self_modulate"), _SCS("set_self_modulate"),_SCS("get_self_modulate") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"show_behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility
- ADD_PROPERTYNO( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_LAYERS_2D_RENDER), _SCS("set_light_mask"),_SCS("get_light_mask") );
+ ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"visible"), "set_visible","is_visible") ;
+ ADD_PROPERTYNO( PropertyInfo(Variant::COLOR,"modulate"), "set_modulate","get_modulate") ;
+ ADD_PROPERTYNO( PropertyInfo(Variant::COLOR,"self_modulate"), "set_self_modulate","get_self_modulate") ;
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"show_behind_parent"), "set_draw_behind_parent","is_draw_behind_parent_enabled") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_on_top",PROPERTY_HINT_NONE,"",0), "_set_on_top","_is_on_top") ; //compatibility
+ ADD_PROPERTYNO( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask","get_light_mask") ;
ADD_GROUP("Material","");
- ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"use_parent_material"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), "set_material","get_material") ;
+ ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"use_parent_material"), "set_use_parent_material","get_use_parent_material") ;
//exporting these two things doesn't really make much sense i think
- //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
- //ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
+ //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), "set_as_toplevel","is_set_as_toplevel") ;
+ //ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),"set_transform_notify","is_transform_notify_enabled");
ADD_SIGNAL( MethodInfo("draw") );
ADD_SIGNAL( MethodInfo("visibility_changed") );
diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp
index 138589651c..ecc11ea60f 100644
--- a/scene/2d/canvas_modulate.cpp
+++ b/scene/2d/canvas_modulate.cpp
@@ -62,10 +62,10 @@ void CanvasModulate::_notification(int p_what) {
void CanvasModulate::_bind_methods(){
- ClassDB::bind_method(_MD("set_color","color"),&CanvasModulate::set_color);
- ClassDB::bind_method(_MD("get_color"),&CanvasModulate::get_color);
+ ClassDB::bind_method(D_METHOD("set_color","color"),&CanvasModulate::set_color);
+ ClassDB::bind_method(D_METHOD("get_color"),&CanvasModulate::get_color);
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),"set_color","get_color");
}
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 3668963251..f9e1cc0bd7 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -221,20 +221,20 @@ void CollisionObject2D::_update_pickable() {
void CollisionObject2D::_bind_methods() {
- ClassDB::bind_method(_MD("add_shape","shape:Shape2D","transform"),&CollisionObject2D::add_shape,DEFVAL(Transform2D()));
- ClassDB::bind_method(_MD("get_shape_count"),&CollisionObject2D::get_shape_count);
- ClassDB::bind_method(_MD("set_shape","shape_idx","shape:Shape"),&CollisionObject2D::set_shape);
- ClassDB::bind_method(_MD("set_shape_transform","shape_idx","transform"),&CollisionObject2D::set_shape_transform);
- ClassDB::bind_method(_MD("set_shape_as_trigger","shape_idx","enable"),&CollisionObject2D::set_shape_as_trigger);
- ClassDB::bind_method(_MD("get_shape:Shape2D","shape_idx"),&CollisionObject2D::get_shape);
- ClassDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject2D::get_shape_transform);
- ClassDB::bind_method(_MD("is_shape_set_as_trigger","shape_idx"),&CollisionObject2D::is_shape_set_as_trigger);
- ClassDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject2D::remove_shape);
- ClassDB::bind_method(_MD("clear_shapes"),&CollisionObject2D::clear_shapes);
- ClassDB::bind_method(_MD("get_rid"),&CollisionObject2D::get_rid);
-
- ClassDB::bind_method(_MD("set_pickable","enabled"),&CollisionObject2D::set_pickable);
- ClassDB::bind_method(_MD("is_pickable"),&CollisionObject2D::is_pickable);
+ ClassDB::bind_method(D_METHOD("add_shape","shape:Shape2D","transform"),&CollisionObject2D::add_shape,DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("get_shape_count"),&CollisionObject2D::get_shape_count);
+ ClassDB::bind_method(D_METHOD("set_shape","shape_idx","shape:Shape"),&CollisionObject2D::set_shape);
+ ClassDB::bind_method(D_METHOD("set_shape_transform","shape_idx","transform"),&CollisionObject2D::set_shape_transform);
+ ClassDB::bind_method(D_METHOD("set_shape_as_trigger","shape_idx","enable"),&CollisionObject2D::set_shape_as_trigger);
+ ClassDB::bind_method(D_METHOD("get_shape:Shape2D","shape_idx"),&CollisionObject2D::get_shape);
+ ClassDB::bind_method(D_METHOD("get_shape_transform","shape_idx"),&CollisionObject2D::get_shape_transform);
+ ClassDB::bind_method(D_METHOD("is_shape_set_as_trigger","shape_idx"),&CollisionObject2D::is_shape_set_as_trigger);
+ ClassDB::bind_method(D_METHOD("remove_shape","shape_idx"),&CollisionObject2D::remove_shape);
+ ClassDB::bind_method(D_METHOD("clear_shapes"),&CollisionObject2D::clear_shapes);
+ ClassDB::bind_method(D_METHOD("get_rid"),&CollisionObject2D::get_rid);
+
+ ClassDB::bind_method(D_METHOD("set_pickable","enabled"),&CollisionObject2D::set_pickable);
+ ClassDB::bind_method(D_METHOD("is_pickable"),&CollisionObject2D::is_pickable);
BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"viewport"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::INT,"shape_idx")));
@@ -243,7 +243,7 @@ void CollisionObject2D::_bind_methods() {
ADD_SIGNAL( MethodInfo("mouse_exited"));
ADD_GROUP("Pickable","input_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input_pickable"),_SCS("set_pickable"),_SCS("is_pickable"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input_pickable"),"set_pickable","is_pickable");
ADD_GROUP("","");
}
@@ -348,6 +348,8 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
rid=p_rid;
area=p_area;
pickable=true;
+ set_notify_transform(true);
+
if (p_area) {
Physics2DServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 4364e5f1fc..85241a79e0 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -314,26 +314,26 @@ String CollisionPolygon2D::get_configuration_warning() const {
void CollisionPolygon2D::_bind_methods() {
- ClassDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object);
- ClassDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon2D::set_polygon);
- ClassDB::bind_method(_MD("get_polygon"),&CollisionPolygon2D::get_polygon);
+ ClassDB::bind_method(D_METHOD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object);
+ ClassDB::bind_method(D_METHOD("set_polygon","polygon"),&CollisionPolygon2D::set_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon"),&CollisionPolygon2D::get_polygon);
- ClassDB::bind_method(_MD("set_build_mode","build_mode"),&CollisionPolygon2D::set_build_mode);
- ClassDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode);
+ ClassDB::bind_method(D_METHOD("set_build_mode","build_mode"),&CollisionPolygon2D::set_build_mode);
+ ClassDB::bind_method(D_METHOD("get_build_mode"),&CollisionPolygon2D::get_build_mode);
- ClassDB::bind_method(_MD("set_trigger","trigger"),&CollisionPolygon2D::set_trigger);
- ClassDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger);
+ ClassDB::bind_method(D_METHOD("set_trigger","trigger"),&CollisionPolygon2D::set_trigger);
+ ClassDB::bind_method(D_METHOD("is_trigger"),&CollisionPolygon2D::is_trigger);
- ClassDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon2D::_set_shape_range);
- ClassDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon2D::_get_shape_range);
+ ClassDB::bind_method(D_METHOD("_set_shape_range","shape_range"),&CollisionPolygon2D::_set_shape_range);
+ ClassDB::bind_method(D_METHOD("_get_shape_range"),&CollisionPolygon2D::_get_shape_range);
- ClassDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon2D::get_collision_object_first_shape);
- ClassDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon2D::get_collision_object_last_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_object_first_shape"),&CollisionPolygon2D::get_collision_object_first_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_object_last_shape"),&CollisionPolygon2D::get_collision_object_last_shape);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),"set_build_mode","get_build_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),"set_polygon","get_polygon");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_shape_range","_get_shape_range");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),"set_trigger","is_trigger");
}
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 45fc734aef..37a49577b5 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -218,21 +218,21 @@ String CollisionShape2D::get_configuration_warning() const {
void CollisionShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_shape","shape"),&CollisionShape2D::set_shape);
- ClassDB::bind_method(_MD("get_shape"),&CollisionShape2D::get_shape);
- ClassDB::bind_method(_MD("_shape_changed"),&CollisionShape2D::_shape_changed);
- ClassDB::bind_method(_MD("_add_to_collision_object"),&CollisionShape2D::_add_to_collision_object);
- ClassDB::bind_method(_MD("set_trigger","enable"),&CollisionShape2D::set_trigger);
- ClassDB::bind_method(_MD("is_trigger"),&CollisionShape2D::is_trigger);
+ ClassDB::bind_method(D_METHOD("set_shape","shape"),&CollisionShape2D::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape"),&CollisionShape2D::get_shape);
+ ClassDB::bind_method(D_METHOD("_shape_changed"),&CollisionShape2D::_shape_changed);
+ ClassDB::bind_method(D_METHOD("_add_to_collision_object"),&CollisionShape2D::_add_to_collision_object);
+ ClassDB::bind_method(D_METHOD("set_trigger","enable"),&CollisionShape2D::set_trigger);
+ ClassDB::bind_method(D_METHOD("is_trigger"),&CollisionShape2D::is_trigger);
- ClassDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape2D::_set_update_shape_index);
- ClassDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape2D::_get_update_shape_index);
+ ClassDB::bind_method(D_METHOD("_set_update_shape_index","index"),&CollisionShape2D::_set_update_shape_index);
+ ClassDB::bind_method(D_METHOD("_get_update_shape_index"),&CollisionShape2D::_get_update_shape_index);
- ClassDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape2D::get_collision_object_shape_index);
+ ClassDB::bind_method(D_METHOD("get_collision_object_shape_index"),&CollisionShape2D::get_collision_object_shape_index);
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D"),_SCS("set_shape"),_SCS("get_shape"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D"),"set_shape","get_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),"set_trigger","is_trigger");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), "_set_update_shape_index", "_get_update_shape_index");
}
diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp
index 987672df38..6754eb3981 100644
--- a/scene/2d/joints_2d.cpp
+++ b/scene/2d/joints_2d.cpp
@@ -128,22 +128,22 @@ bool Joint2D::get_exclude_nodes_from_collision() const{
void Joint2D::_bind_methods() {
- ClassDB::bind_method( _MD("set_node_a","node"), &Joint2D::set_node_a );
- ClassDB::bind_method( _MD("get_node_a"), &Joint2D::get_node_a );
+ ClassDB::bind_method( D_METHOD("set_node_a","node"), &Joint2D::set_node_a );
+ ClassDB::bind_method( D_METHOD("get_node_a"), &Joint2D::get_node_a );
- ClassDB::bind_method( _MD("set_node_b","node"), &Joint2D::set_node_b );
- ClassDB::bind_method( _MD("get_node_b"), &Joint2D::get_node_b );
+ ClassDB::bind_method( D_METHOD("set_node_b","node"), &Joint2D::set_node_b );
+ ClassDB::bind_method( D_METHOD("get_node_b"), &Joint2D::get_node_b );
- ClassDB::bind_method( _MD("set_bias","bias"), &Joint2D::set_bias );
- ClassDB::bind_method( _MD("get_bias"), &Joint2D::get_bias );
+ ClassDB::bind_method( D_METHOD("set_bias","bias"), &Joint2D::set_bias );
+ ClassDB::bind_method( D_METHOD("get_bias"), &Joint2D::get_bias );
- ClassDB::bind_method( _MD("set_exclude_nodes_from_collision","enable"), &Joint2D::set_exclude_nodes_from_collision );
- ClassDB::bind_method( _MD("get_exclude_nodes_from_collision"), &Joint2D::get_exclude_nodes_from_collision );
+ ClassDB::bind_method( D_METHOD("set_exclude_nodes_from_collision","enable"), &Joint2D::set_exclude_nodes_from_collision );
+ ClassDB::bind_method( D_METHOD("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",PROPERTY_HINT_RANGE,"0,0.9,0.001"), _SCS("set_bias"),_SCS("get_bias") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disable_collision"), _SCS("set_exclude_nodes_from_collision"),_SCS("get_exclude_nodes_from_collision") );
+ ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_a"), "set_node_a","get_node_a") ;
+ ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "node_b"), "set_node_b","get_node_b") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "bias",PROPERTY_HINT_RANGE,"0,0.9,0.001"), "set_bias","get_bias") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disable_collision"), "set_exclude_nodes_from_collision","get_exclude_nodes_from_collision") ;
}
@@ -225,10 +225,10 @@ real_t PinJoint2D::get_softness() const {
void PinJoint2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_softness","softness"), &PinJoint2D::set_softness);
- ClassDB::bind_method(_MD("get_softness"), &PinJoint2D::get_softness);
+ ClassDB::bind_method(D_METHOD("set_softness","softness"), &PinJoint2D::set_softness);
+ ClassDB::bind_method(D_METHOD("get_softness"), &PinJoint2D::get_softness);
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "softness", PROPERTY_HINT_EXP_RANGE,"0.00,16,0.01"), _SCS("set_softness"), _SCS("get_softness"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "softness", PROPERTY_HINT_EXP_RANGE,"0.00,16,0.01"), "set_softness", "get_softness");
}
PinJoint2D::PinJoint2D() {
@@ -321,13 +321,13 @@ real_t GrooveJoint2D::get_initial_offset() const {
void GrooveJoint2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_length","length"),&GrooveJoint2D::set_length);
- ClassDB::bind_method(_MD("get_length"),&GrooveJoint2D::get_length);
- ClassDB::bind_method(_MD("set_initial_offset","offset"),&GrooveJoint2D::set_initial_offset);
- ClassDB::bind_method(_MD("get_initial_offset"),&GrooveJoint2D::get_initial_offset);
+ ClassDB::bind_method(D_METHOD("set_length","length"),&GrooveJoint2D::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"),&GrooveJoint2D::get_length);
+ ClassDB::bind_method(D_METHOD("set_initial_offset","offset"),&GrooveJoint2D::set_initial_offset);
+ ClassDB::bind_method(D_METHOD("get_initial_offset"),&GrooveJoint2D::get_initial_offset);
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_length"),_SCS("get_length"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "initial_offset", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_initial_offset"),_SCS("get_initial_offset"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), "set_length","get_length");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "initial_offset", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), "set_initial_offset","get_initial_offset");
}
GrooveJoint2D::GrooveJoint2D() {
@@ -453,19 +453,19 @@ real_t DampedSpringJoint2D::get_damping() const {
void DampedSpringJoint2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_length","length"),&DampedSpringJoint2D::set_length);
- ClassDB::bind_method(_MD("get_length"),&DampedSpringJoint2D::get_length);
- ClassDB::bind_method(_MD("set_rest_length","rest_length"),&DampedSpringJoint2D::set_rest_length);
- ClassDB::bind_method(_MD("get_rest_length"),&DampedSpringJoint2D::get_rest_length);
- ClassDB::bind_method(_MD("set_stiffness","stiffness"),&DampedSpringJoint2D::set_stiffness);
- ClassDB::bind_method(_MD("get_stiffness"),&DampedSpringJoint2D::get_stiffness);
- ClassDB::bind_method(_MD("set_damping","damping"),&DampedSpringJoint2D::set_damping);
- ClassDB::bind_method(_MD("get_damping"),&DampedSpringJoint2D::get_damping);
+ ClassDB::bind_method(D_METHOD("set_length","length"),&DampedSpringJoint2D::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"),&DampedSpringJoint2D::get_length);
+ ClassDB::bind_method(D_METHOD("set_rest_length","rest_length"),&DampedSpringJoint2D::set_rest_length);
+ ClassDB::bind_method(D_METHOD("get_rest_length"),&DampedSpringJoint2D::get_rest_length);
+ ClassDB::bind_method(D_METHOD("set_stiffness","stiffness"),&DampedSpringJoint2D::set_stiffness);
+ ClassDB::bind_method(D_METHOD("get_stiffness"),&DampedSpringJoint2D::get_stiffness);
+ ClassDB::bind_method(D_METHOD("set_damping","damping"),&DampedSpringJoint2D::set_damping);
+ ClassDB::bind_method(D_METHOD("get_damping"),&DampedSpringJoint2D::get_damping);
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), _SCS("set_length"),_SCS("get_length"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "rest_length", PROPERTY_HINT_EXP_RANGE,"0,65535,1"), _SCS("set_rest_length"),_SCS("get_rest_length"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "stiffness", PROPERTY_HINT_EXP_RANGE,"0.1,64,0.1"), _SCS("set_stiffness"),_SCS("get_stiffness"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "damping", PROPERTY_HINT_EXP_RANGE,"0.01,16,0.01"), _SCS("set_damping"),_SCS("get_damping"));
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "length", PROPERTY_HINT_EXP_RANGE,"1,65535,1"), "set_length","get_length");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "rest_length", PROPERTY_HINT_EXP_RANGE,"0,65535,1"), "set_rest_length","get_rest_length");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "stiffness", PROPERTY_HINT_EXP_RANGE,"0.1,64,0.1"), "set_stiffness","get_stiffness");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "damping", PROPERTY_HINT_EXP_RANGE,"0.01,16,0.01"), "set_damping","get_damping");
}
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 2935f6b9f7..d7f5a890e8 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -365,92 +365,92 @@ String Light2D::get_configuration_warning() const {
void Light2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_enabled","enabled"),&Light2D::set_enabled);
- ClassDB::bind_method(_MD("is_enabled"),&Light2D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled","enabled"),&Light2D::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"),&Light2D::is_enabled);
- ClassDB::bind_method(_MD("set_editor_only","editor_only"), &Light2D::set_editor_only );
- ClassDB::bind_method(_MD("is_editor_only"), &Light2D::is_editor_only );
+ ClassDB::bind_method(D_METHOD("set_editor_only","editor_only"), &Light2D::set_editor_only );
+ ClassDB::bind_method(D_METHOD("is_editor_only"), &Light2D::is_editor_only );
- ClassDB::bind_method(_MD("set_texture","texture"),&Light2D::set_texture);
- ClassDB::bind_method(_MD("get_texture"),&Light2D::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture","texture"),&Light2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"),&Light2D::get_texture);
- ClassDB::bind_method(_MD("set_texture_offset","texture_offset"),&Light2D::set_texture_offset);
- ClassDB::bind_method(_MD("get_texture_offset"),&Light2D::get_texture_offset);
+ ClassDB::bind_method(D_METHOD("set_texture_offset","texture_offset"),&Light2D::set_texture_offset);
+ ClassDB::bind_method(D_METHOD("get_texture_offset"),&Light2D::get_texture_offset);
- ClassDB::bind_method(_MD("set_color","color"),&Light2D::set_color);
- ClassDB::bind_method(_MD("get_color"),&Light2D::get_color);
+ ClassDB::bind_method(D_METHOD("set_color","color"),&Light2D::set_color);
+ ClassDB::bind_method(D_METHOD("get_color"),&Light2D::get_color);
- ClassDB::bind_method(_MD("set_height","height"),&Light2D::set_height);
- ClassDB::bind_method(_MD("get_height"),&Light2D::get_height);
+ ClassDB::bind_method(D_METHOD("set_height","height"),&Light2D::set_height);
+ ClassDB::bind_method(D_METHOD("get_height"),&Light2D::get_height);
- ClassDB::bind_method(_MD("set_energy","energy"),&Light2D::set_energy);
- ClassDB::bind_method(_MD("get_energy"),&Light2D::get_energy);
+ ClassDB::bind_method(D_METHOD("set_energy","energy"),&Light2D::set_energy);
+ ClassDB::bind_method(D_METHOD("get_energy"),&Light2D::get_energy);
- ClassDB::bind_method(_MD("set_texture_scale","texture_scale"),&Light2D::set_texture_scale);
- ClassDB::bind_method(_MD("get_texture_scale"),&Light2D::get_texture_scale);
+ ClassDB::bind_method(D_METHOD("set_texture_scale","texture_scale"),&Light2D::set_texture_scale);
+ ClassDB::bind_method(D_METHOD("get_texture_scale"),&Light2D::get_texture_scale);
- ClassDB::bind_method(_MD("set_z_range_min","z"),&Light2D::set_z_range_min);
- ClassDB::bind_method(_MD("get_z_range_min"),&Light2D::get_z_range_min);
+ ClassDB::bind_method(D_METHOD("set_z_range_min","z"),&Light2D::set_z_range_min);
+ ClassDB::bind_method(D_METHOD("get_z_range_min"),&Light2D::get_z_range_min);
- ClassDB::bind_method(_MD("set_z_range_max","z"),&Light2D::set_z_range_max);
- ClassDB::bind_method(_MD("get_z_range_max"),&Light2D::get_z_range_max);
+ ClassDB::bind_method(D_METHOD("set_z_range_max","z"),&Light2D::set_z_range_max);
+ ClassDB::bind_method(D_METHOD("get_z_range_max"),&Light2D::get_z_range_max);
- ClassDB::bind_method(_MD("set_layer_range_min","layer"),&Light2D::set_layer_range_min);
- ClassDB::bind_method(_MD("get_layer_range_min"),&Light2D::get_layer_range_min);
+ ClassDB::bind_method(D_METHOD("set_layer_range_min","layer"),&Light2D::set_layer_range_min);
+ ClassDB::bind_method(D_METHOD("get_layer_range_min"),&Light2D::get_layer_range_min);
- ClassDB::bind_method(_MD("set_layer_range_max","layer"),&Light2D::set_layer_range_max);
- ClassDB::bind_method(_MD("get_layer_range_max"),&Light2D::get_layer_range_max);
+ ClassDB::bind_method(D_METHOD("set_layer_range_max","layer"),&Light2D::set_layer_range_max);
+ ClassDB::bind_method(D_METHOD("get_layer_range_max"),&Light2D::get_layer_range_max);
- ClassDB::bind_method(_MD("set_item_cull_mask","item_cull_mask"),&Light2D::set_item_cull_mask);
- ClassDB::bind_method(_MD("get_item_cull_mask"),&Light2D::get_item_cull_mask);
+ ClassDB::bind_method(D_METHOD("set_item_cull_mask","item_cull_mask"),&Light2D::set_item_cull_mask);
+ ClassDB::bind_method(D_METHOD("get_item_cull_mask"),&Light2D::get_item_cull_mask);
- ClassDB::bind_method(_MD("set_item_shadow_cull_mask","item_shadow_cull_mask"),&Light2D::set_item_shadow_cull_mask);
- ClassDB::bind_method(_MD("get_item_shadow_cull_mask"),&Light2D::get_item_shadow_cull_mask);
+ ClassDB::bind_method(D_METHOD("set_item_shadow_cull_mask","item_shadow_cull_mask"),&Light2D::set_item_shadow_cull_mask);
+ ClassDB::bind_method(D_METHOD("get_item_shadow_cull_mask"),&Light2D::get_item_shadow_cull_mask);
- ClassDB::bind_method(_MD("set_mode","mode"),&Light2D::set_mode);
- ClassDB::bind_method(_MD("get_mode"),&Light2D::get_mode);
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&Light2D::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&Light2D::get_mode);
- ClassDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
- ClassDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
+ ClassDB::bind_method(D_METHOD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
+ ClassDB::bind_method(D_METHOD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
- ClassDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size);
- ClassDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size);
+ ClassDB::bind_method(D_METHOD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size);
+ ClassDB::bind_method(D_METHOD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size);
- ClassDB::bind_method(_MD("set_shadow_gradient_length","multiplier"),&Light2D::set_shadow_gradient_length);
- ClassDB::bind_method(_MD("get_shadow_gradient_length"),&Light2D::get_shadow_gradient_length);
+ ClassDB::bind_method(D_METHOD("set_shadow_gradient_length","multiplier"),&Light2D::set_shadow_gradient_length);
+ ClassDB::bind_method(D_METHOD("get_shadow_gradient_length"),&Light2D::get_shadow_gradient_length);
- ClassDB::bind_method(_MD("set_shadow_filter","filter"),&Light2D::set_shadow_filter);
- ClassDB::bind_method(_MD("get_shadow_filter"),&Light2D::get_shadow_filter);
+ ClassDB::bind_method(D_METHOD("set_shadow_filter","filter"),&Light2D::set_shadow_filter);
+ ClassDB::bind_method(D_METHOD("get_shadow_filter"),&Light2D::get_shadow_filter);
- ClassDB::bind_method(_MD("set_shadow_color","shadow_color"),&Light2D::set_shadow_color);
- ClassDB::bind_method(_MD("get_shadow_color"),&Light2D::get_shadow_color);
+ ClassDB::bind_method(D_METHOD("set_shadow_color","shadow_color"),&Light2D::set_shadow_color);
+ ClassDB::bind_method(D_METHOD("get_shadow_color"),&Light2D::get_shadow_color);
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "editor_only"),_SCS("set_editor_only"),_SCS("is_editor_only"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,50,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",PROPERTY_HINT_RANGE,"0.01,100,0.01"),_SCS("set_energy"),_SCS("get_energy"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix,Mask"),_SCS("set_mode"),_SCS("get_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),"set_enabled","is_enabled");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "editor_only"),"set_editor_only","is_editor_only");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),"set_texture_offset","get_texture_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,50,0.01"),"set_texture_scale","get_texture_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),"set_color","get_color");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_RANGE,"0.01,100,0.01"),"set_energy","get_energy");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix,Mask"),"set_mode","get_mode");
ADD_GROUP("Range","range_");
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"range_height",PROPERTY_HINT_RANGE,"-100,100,0.1"),_SCS("set_height"),_SCS("get_height"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"range_z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"range_z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"range_layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"range_layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"range_item_cull_mask",PROPERTY_HINT_LAYERS_2D_RENDER),_SCS("set_item_cull_mask"),_SCS("get_item_cull_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"range_height",PROPERTY_HINT_RANGE,"-100,100,0.1"),"set_height","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"),"set_z_range_min","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"),"set_z_range_max","get_z_range_max");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range_layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),"set_layer_range_min","get_layer_range_min");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range_layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),"set_layer_range_max","get_layer_range_max");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"range_item_cull_mask",PROPERTY_HINT_LAYERS_2D_RENDER),"set_item_cull_mask","get_item_cull_mask");
ADD_GROUP("Shadow","shadow_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::COLOR,"shadow_color"),_SCS("set_shadow_color"),_SCS("get_shadow_color"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow_buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow_gradient_length",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_gradient_length"),_SCS("get_shadow_gradient_length"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow_filter",PROPERTY_HINT_ENUM,"None,PCF3,PCF5,PCF9,PCF13"),_SCS("set_shadow_filter"),_SCS("get_shadow_filter"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow_item_cull_mask",PROPERTY_HINT_LAYERS_2D_RENDER),_SCS("set_item_shadow_cull_mask"),_SCS("get_item_shadow_cull_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),"set_shadow_enabled","is_shadow_enabled");
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR,"shadow_color"),"set_shadow_color","get_shadow_color");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow_buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),"set_shadow_buffer_size","get_shadow_buffer_size");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow_gradient_length",PROPERTY_HINT_RANGE,"1,4096,0.1"),"set_shadow_gradient_length","get_shadow_gradient_length");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow_filter",PROPERTY_HINT_ENUM,"None,PCF3,PCF5,PCF9,PCF13"),"set_shadow_filter","get_shadow_filter");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow_item_cull_mask",PROPERTY_HINT_LAYERS_2D_RENDER),"set_item_shadow_cull_mask","get_item_shadow_cull_mask");
BIND_CONSTANT( MODE_ADD );
BIND_CONSTANT( MODE_SUB );
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
index 77c9b8184a..6a024fe330 100644
--- a/scene/2d/light_occluder_2d.cpp
+++ b/scene/2d/light_occluder_2d.cpp
@@ -78,18 +78,18 @@ RID OccluderPolygon2D::get_rid() const {
void OccluderPolygon2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_closed","closed"),&OccluderPolygon2D::set_closed);
- ClassDB::bind_method(_MD("is_closed"),&OccluderPolygon2D::is_closed);
+ ClassDB::bind_method(D_METHOD("set_closed","closed"),&OccluderPolygon2D::set_closed);
+ ClassDB::bind_method(D_METHOD("is_closed"),&OccluderPolygon2D::is_closed);
- ClassDB::bind_method(_MD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode);
- ClassDB::bind_method(_MD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode);
+ ClassDB::bind_method(D_METHOD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode);
+ ClassDB::bind_method(D_METHOD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode);
- ClassDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon);
- ClassDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon);
+ ClassDB::bind_method(D_METHOD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon"),&OccluderPolygon2D::get_polygon);
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),"set_closed","is_closed");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),"set_cull_mode","get_cull_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),"set_polygon","get_polygon");
BIND_CONSTANT(CULL_DISABLED);
BIND_CONSTANT(CULL_CLOCKWISE);
@@ -224,18 +224,18 @@ String LightOccluder2D::get_configuration_warning() const {
void LightOccluder2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon);
- ClassDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon);
+ ClassDB::bind_method(D_METHOD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon);
+ ClassDB::bind_method(D_METHOD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon);
- ClassDB::bind_method(_MD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask);
- ClassDB::bind_method(_MD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask);
+ ClassDB::bind_method(D_METHOD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask);
+ ClassDB::bind_method(D_METHOD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask);
#ifdef DEBUG_ENABLED
ClassDB::bind_method("_poly_changed",&LightOccluder2D::_poly_changed);
#endif
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),_SCS("set_occluder_polygon"),_SCS("get_occluder_polygon"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_LAYERS_2D_RENDER),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),"set_occluder_polygon","get_occluder_polygon");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_LAYERS_2D_RENDER),"set_occluder_light_mask","get_occluder_light_mask");
}
LightOccluder2D::LightOccluder2D() {
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
new file mode 100644
index 0000000000..059711549f
--- /dev/null
+++ b/scene/2d/line_2d.cpp
@@ -0,0 +1,336 @@
+/*************************************************************************/
+/* line_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "line_2d.h"
+
+#include "core_string_names.h"
+
+
+// Needed so we can bind functions
+VARIANT_ENUM_CAST(LineJointMode)
+VARIANT_ENUM_CAST(LineCapMode)
+VARIANT_ENUM_CAST(LineTextureMode)
+
+
+Line2D::Line2D() : Node2D() {
+ _joint_mode = LINE_JOINT_SHARP;
+ _begin_cap_mode = LINE_CAP_NONE;
+ _end_cap_mode = LINE_CAP_NONE;
+ _width = 10;
+ _default_color = Color(0.4,0.5,1);
+ _sharp_limit = 2.f;
+ _round_precision = 8;
+}
+
+void Line2D::set_points(const PoolVector<Vector2> &p_points) {
+ _points = p_points;
+ update();
+}
+
+void Line2D::set_width(float width) {
+ if(width < 0.0)
+ width = 0.0;
+ _width = width;
+ update();
+}
+
+float Line2D::get_width() const {
+ return _width;
+}
+
+PoolVector<Vector2> Line2D::get_points() const {
+ return _points;
+}
+
+void Line2D::set_point_pos(int i, Vector2 pos) {
+ _points.set(i, pos);
+ update();
+}
+
+Vector2 Line2D::get_point_pos(int i) const {
+ return _points.get(i);
+}
+
+int Line2D::get_point_count() const {
+ return _points.size();
+}
+
+void Line2D::add_point(Vector2 pos) {
+ _points.append(pos);
+ update();
+}
+
+void Line2D::remove_point(int i) {
+ _points.remove(i);
+ update();
+}
+
+void Line2D::set_default_color(Color color) {
+ _default_color = color;
+ update();
+}
+
+Color Line2D::get_default_color() const {
+ return _default_color;
+}
+
+void Line2D::set_gradient(const Ref<ColorRamp>& gradient) {
+
+ // Cleanup previous connection if any
+ if(_gradient.is_valid()) {
+ (**_gradient).disconnect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
+ }
+
+ _gradient = gradient;
+
+ // Connect to the gradient so the line will update when the ColorRamp is changed
+ if(_gradient.is_valid()) {
+ (**_gradient).connect(CoreStringNames::get_singleton()->changed, this, "_gradient_changed");
+ }
+
+ update();
+}
+
+Ref<ColorRamp> Line2D::get_gradient() const {
+ return _gradient;
+}
+
+void Line2D::set_texture(const Ref<Texture>& texture) {
+ _texture = texture;
+ update();
+}
+
+Ref<Texture> Line2D::get_texture() const {
+ return _texture;
+}
+
+void Line2D::set_texture_mode(const LineTextureMode mode) {
+ _texture_mode = mode;
+ update();
+}
+
+LineTextureMode Line2D::get_texture_mode() const {
+ return _texture_mode;
+}
+
+void Line2D::set_joint_mode(LineJointMode mode) {
+ _joint_mode = mode;
+ update();
+}
+
+LineJointMode Line2D::get_joint_mode() const {
+ return _joint_mode;
+}
+
+void Line2D::set_begin_cap_mode(LineCapMode mode) {
+ _begin_cap_mode = mode;
+ update();
+}
+
+LineCapMode Line2D::get_begin_cap_mode() const {
+ return _begin_cap_mode;
+}
+
+void Line2D::set_end_cap_mode(LineCapMode mode) {
+ _end_cap_mode = mode;
+ update();
+}
+
+LineCapMode Line2D::get_end_cap_mode() const {
+ return _end_cap_mode;
+}
+
+void Line2D::_notification(int p_what) {
+ switch(p_what) {
+ case NOTIFICATION_DRAW:
+ _draw();
+ break;
+ }
+}
+
+void Line2D::set_sharp_limit(float limit) {
+ if(limit < 0.f)
+ limit = 0.f;
+ _sharp_limit = limit;
+ update();
+}
+
+float Line2D::get_sharp_limit() const {
+ return _sharp_limit;
+}
+
+void Line2D::set_round_precision(int precision) {
+ if(precision < 1)
+ precision = 1;
+ _round_precision = precision;
+ update();
+}
+
+int Line2D::get_round_precision() const {
+ return _round_precision;
+}
+
+void Line2D::_draw() {
+ if(_points.size() <= 1 || _width == 0.f)
+ return;
+
+ // TODO Is this really needed?
+ // Copy points for faster access
+ Vector<Vector2> points;
+ points.resize(_points.size());
+ int len = points.size(); {
+ PoolVector<Vector2>::Read points_read = _points.read();
+ for(int i = 0; i < len; ++i) {
+ points[i] = points_read[i];
+ }
+ }
+
+ // TODO Maybe have it as member rather than copying parameters and allocating memory?
+ LineBuilder lb;
+ lb.points = points;
+ lb.default_color = _default_color;
+ lb.gradient = *_gradient;
+ lb.texture_mode = _texture_mode;
+ lb.joint_mode = _joint_mode;
+ lb.begin_cap_mode = _begin_cap_mode;
+ lb.end_cap_mode = _end_cap_mode;
+ lb.round_precision = _round_precision;
+ lb.sharp_limit = _sharp_limit;
+ lb.width = _width;
+
+ lb.build();
+
+ RID texture_rid;
+ if(_texture.is_valid())
+ texture_rid = (**_texture).get_rid();
+
+ VS::get_singleton()->canvas_item_add_triangle_array(
+ get_canvas_item(),
+ lb.indices,
+ lb.vertices,
+ lb.colors,
+ lb.uvs,
+ texture_rid);
+
+ // DEBUG
+ // Draw wireframe
+// if(lb.indices.size() % 3 == 0) {
+// Color col(0,0,0);
+// for(int i = 0; i < lb.indices.size(); i += 3) {
+// int vi = lb.indices[i];
+// int lbvsize = lb.vertices.size();
+// Vector2 a = lb.vertices[lb.indices[i]];
+// Vector2 b = lb.vertices[lb.indices[i+1]];
+// Vector2 c = lb.vertices[lb.indices[i+2]];
+// draw_line(a, b, col);
+// draw_line(b, c, col);
+// draw_line(c, a, col);
+// }
+// for(int i = 0; i < lb.vertices.size(); ++i) {
+// Vector2 p = lb.vertices[i];
+// draw_rect(Rect2(p.x-1, p.y-1, 2, 2), Color(0,0,0,0.5));
+// }
+// }
+}
+
+void Line2D::_gradient_changed() {
+ update();
+}
+
+// static
+void Line2D::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_points","points"), &Line2D::set_points);
+ ClassDB::bind_method(D_METHOD("get_points"), &Line2D::get_points);
+
+ ClassDB::bind_method(D_METHOD("set_point_pos","i", "pos"), &Line2D::set_point_pos);
+ ClassDB::bind_method(D_METHOD("get_point_pos", "i"), &Line2D::get_point_pos);
+
+ ClassDB::bind_method(D_METHOD("get_point_count"), &Line2D::get_point_count);
+
+ ClassDB::bind_method(D_METHOD("add_point", "pos"), &Line2D::add_point);
+ ClassDB::bind_method(D_METHOD("remove_point", "i"), &Line2D::remove_point);
+
+ ClassDB::bind_method(D_METHOD("set_width","width"), &Line2D::set_width);
+ ClassDB::bind_method(D_METHOD("get_width"), &Line2D::get_width);
+
+ ClassDB::bind_method(D_METHOD("set_default_color", "color"), &Line2D::set_default_color);
+ ClassDB::bind_method(D_METHOD("get_default_color"), &Line2D::get_default_color);
+
+ ClassDB::bind_method(D_METHOD("set_gradient", "color"), &Line2D::set_gradient);
+ ClassDB::bind_method(D_METHOD("get_gradient"), &Line2D::get_gradient);
+
+ ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Line2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"), &Line2D::get_texture);
+
+ ClassDB::bind_method(D_METHOD("set_texture_mode", "mode"), &Line2D::set_texture_mode);
+ ClassDB::bind_method(D_METHOD("get_texture_mode"), &Line2D::get_texture_mode);
+
+ ClassDB::bind_method(D_METHOD("set_joint_mode", "mode"), &Line2D::set_joint_mode);
+ ClassDB::bind_method(D_METHOD("get_joint_mode"), &Line2D::get_joint_mode);
+
+ ClassDB::bind_method(D_METHOD("set_begin_cap_mode", "mode"), &Line2D::set_begin_cap_mode);
+ ClassDB::bind_method(D_METHOD("get_begin_cap_mode"), &Line2D::get_begin_cap_mode);
+
+ ClassDB::bind_method(D_METHOD("set_end_cap_mode", "mode"), &Line2D::set_end_cap_mode);
+ ClassDB::bind_method(D_METHOD("get_end_cap_mode"), &Line2D::get_end_cap_mode);
+
+ ClassDB::bind_method(D_METHOD("set_sharp_limit", "limit"), &Line2D::set_sharp_limit);
+ ClassDB::bind_method(D_METHOD("get_sharp_limit"), &Line2D::get_sharp_limit);
+
+ ClassDB::bind_method(D_METHOD("set_round_precision", "precision"), &Line2D::set_round_precision);
+ ClassDB::bind_method(D_METHOD("get_round_precision"), &Line2D::get_round_precision);
+
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "width"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_color"), "set_default_color", "get_default_color");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "gradient", PROPERTY_HINT_RESOURCE_TYPE, "ColorRamp"), "set_gradient", "get_gradient");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "texture_mode", PROPERTY_HINT_ENUM, "None,Tile" ), "set_texture_mode","get_texture_mode");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "joint_mode", PROPERTY_HINT_ENUM, "Sharp,Bevel,Round" ), "set_joint_mode","get_joint_mode");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "begin_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round" ), "set_begin_cap_mode","get_begin_cap_mode");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "end_cap_mode", PROPERTY_HINT_ENUM, "None,Box,Round" ), "set_end_cap_mode","get_end_cap_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "sharp_limit"), "set_sharp_limit", "get_sharp_limit");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "round_precision"), "set_round_precision", "get_round_precision");
+
+ BIND_CONSTANT(LINE_JOINT_SHARP);
+ BIND_CONSTANT(LINE_JOINT_BEVEL);
+ BIND_CONSTANT(LINE_JOINT_ROUND);
+
+ BIND_CONSTANT(LINE_CAP_NONE);
+ BIND_CONSTANT(LINE_CAP_BOX);
+ BIND_CONSTANT(LINE_CAP_ROUND);
+
+ BIND_CONSTANT(LINE_TEXTURE_NONE);
+ BIND_CONSTANT(LINE_TEXTURE_TILE);
+
+ ClassDB::bind_method(D_METHOD("_gradient_changed"), &Line2D::_gradient_changed);
+
+}
+
+
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
new file mode 100644
index 0000000000..5435c7489f
--- /dev/null
+++ b/scene/2d/line_2d.h
@@ -0,0 +1,108 @@
+/*************************************************************************/
+/* line_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 LINE2D_H
+#define LINE2D_H
+
+#include "node_2d.h"
+#include "line_builder.h"
+
+
+class Line2D : public Node2D {
+
+ GDCLASS(Line2D, Node2D)
+
+public:
+ Line2D();
+
+ void set_points(const PoolVector<Vector2> & p_points);
+ PoolVector<Vector2> get_points() const;
+
+ void set_point_pos(int i, Vector2 pos);
+ Vector2 get_point_pos(int i) const;
+
+ int get_point_count() const;
+
+ void add_point(Vector2 pos);
+ void remove_point(int i);
+
+ void set_width(float width);
+ float get_width() const;
+
+ void set_default_color(Color color);
+ Color get_default_color() const;
+
+ void set_gradient(const Ref<ColorRamp>& gradient);
+ Ref<ColorRamp> get_gradient() const;
+
+ void set_texture(const Ref<Texture>& texture);
+ Ref<Texture> get_texture() const;
+
+ void set_texture_mode(const LineTextureMode mode);
+ LineTextureMode get_texture_mode() const;
+
+ void set_joint_mode(LineJointMode mode);
+ LineJointMode get_joint_mode() const;
+
+ void set_begin_cap_mode(LineCapMode mode);
+ LineCapMode get_begin_cap_mode() const;
+
+ void set_end_cap_mode(LineCapMode mode);
+ LineCapMode get_end_cap_mode() const;
+
+ void set_sharp_limit(float limit);
+ float get_sharp_limit() const;
+
+ void set_round_precision(int precision);
+ int get_round_precision() const;
+
+protected:
+ void _notification(int p_what);
+ void _draw();
+
+ static void _bind_methods();
+
+private:
+ void _gradient_changed();
+
+private:
+ PoolVector<Vector2> _points;
+ LineJointMode _joint_mode;
+ LineCapMode _begin_cap_mode;
+ LineCapMode _end_cap_mode;
+ float _width;
+ Color _default_color;
+ Ref<ColorRamp> _gradient;
+ Ref<Texture> _texture;
+ LineTextureMode _texture_mode;
+ float _sharp_limit;
+ int _round_precision;
+
+};
+
+#endif // LINE2D_H
diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp
new file mode 100644
index 0000000000..69543f004d
--- /dev/null
+++ b/scene/2d/line_builder.cpp
@@ -0,0 +1,591 @@
+/*************************************************************************/
+/* line_builder.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "line_builder.h"
+
+//----------------------------------------------------------------------------
+// Util
+//----------------------------------------------------------------------------
+
+enum SegmentIntersectionResult {
+ SEGMENT_PARALLEL = 0,
+ SEGMENT_NO_INTERSECT = 1,
+ SEGMENT_INTERSECT = 2
+};
+
+static SegmentIntersectionResult segment_intersection(
+ Vector2 a, Vector2 b, Vector2 c, Vector2 d,
+ Vector2 * out_intersection)
+{
+ // http://paulbourke.net/geometry/pointlineplane/ <-- Good stuff
+ Vector2 cd = d - c;
+ Vector2 ab = b - a;
+ float div = cd.y*ab.x - cd.x*ab.y;
+
+ if(Math::abs(div) > 0.001f) {
+ float ua = (cd.x * (a.y-c.y) - cd.y * (a.x-c.x)) / div;
+ float ub = (ab.x * (a.y-c.y) - ab.y * (a.x-c.x)) / div;
+ *out_intersection = a + ua * ab;
+ if(ua >= 0.f && ua <= 1.f &&
+ ub >= 0.f && ub <= 1.f)
+ return SEGMENT_INTERSECT;
+ return SEGMENT_NO_INTERSECT;
+ }
+
+ return SEGMENT_PARALLEL;
+}
+
+// TODO I'm pretty sure there is an even faster way to swap things
+template <typename T>
+static inline void swap(T & a, T & b) {
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+static float calculate_total_distance(const Vector<Vector2> & points) {
+ float d = 0.f;
+ for(int i = 1; i < points.size(); ++i) {
+ d += points[i].distance_to(points[i-1]);
+ }
+ return d;
+}
+
+static inline Vector2 rotate90(const Vector2 & v) {
+ // Note: the 2D referential is X-right, Y-down
+ return Vector2(v.y, -v.x);
+}
+
+static inline Vector2 interpolate(const Rect2 & r, const Vector2 & v) {
+ return Vector2(
+ Math::lerp(r.get_pos().x, r.get_pos().x + r.get_size().x, v.x),
+ Math::lerp(r.get_pos().y, r.get_pos().y + r.get_size().y, v.y)
+ );
+}
+
+//----------------------------------------------------------------------------
+// LineBuilder
+//----------------------------------------------------------------------------
+
+LineBuilder::LineBuilder() {
+ joint_mode = LINE_JOINT_SHARP;
+ width = 10;
+ default_color = Color(0.4,0.5,1);
+ gradient = NULL;
+ sharp_limit = 2.f;
+ round_precision = 8;
+ begin_cap_mode = LINE_CAP_NONE;
+ end_cap_mode = LINE_CAP_NONE;
+
+ _interpolate_color = false;
+ _last_index[0] = 0;
+ _last_index[1] = 0;
+}
+
+
+void LineBuilder::clear_output() {
+ vertices.clear();
+ colors.clear();
+ indices.clear();
+}
+
+void LineBuilder::build() {
+
+ // Need at least 2 points to draw a line
+ if(points.size() < 2) {
+ clear_output();
+ return;
+ }
+
+ const float hw = width / 2.f;
+ const float hw_sq = hw*hw;
+ const float sharp_limit_sq = sharp_limit * sharp_limit;
+ const int len = points.size();
+
+ // Initial values
+
+ Vector2 pos0 = points[0];
+ Vector2 pos1 = points[1];
+ Vector2 f0 = (pos1 - pos0).normalized();
+ Vector2 u0 = rotate90(f0);
+ Vector2 pos_up0 = pos0 + u0 * hw;
+ Vector2 pos_down0 = pos0 - u0 * hw;
+
+ Color color0;
+ Color color1;
+
+ float current_distance0 = 0.f;
+ float current_distance1 = 0.f;
+ float total_distance;
+ _interpolate_color = gradient != NULL;
+ bool distance_required = _interpolate_color || texture_mode == LINE_TEXTURE_TILE;
+ if(distance_required)
+ total_distance = calculate_total_distance(points);
+ if(_interpolate_color)
+ color0 = gradient->get_color(0);
+ else
+ colors.push_back(default_color);
+
+ float uvx0 = 0.f;
+ float uvx1 = 0.f;
+
+ // Begin cap
+ if(begin_cap_mode == LINE_CAP_BOX) {
+ // Push back first vertices a little bit
+ pos_up0 -= f0 * hw;
+ pos_down0 -= f0 * hw;
+ // The line's outer length will be a little higher due to begin and end caps
+ total_distance += width;
+ current_distance0 += hw;
+ current_distance1 = current_distance0;
+ }
+ else if(begin_cap_mode == LINE_CAP_ROUND) {
+ if(texture_mode == LINE_TEXTURE_TILE) {
+ uvx0 = 0.5f;
+ }
+ new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, 1.f, 1.f));
+ total_distance += width;
+ current_distance0 += hw;
+ current_distance1 = current_distance0;
+ }
+
+ strip_begin(pos_up0, pos_down0, color0, uvx0);
+
+ // pos_up0 ------------- pos_up1 --------------------
+ // | |
+ // pos0 - - - - - - - - - pos1 - - - - - - - - - pos2
+ // | |
+ // pos_down0 ------------ pos_down1 ------------------
+ //
+ // i-1 i i+1
+
+ // http://labs.hyperandroid.com/tag/opengl-lines
+ // (not the same implementation but visuals help a lot)
+
+ // For each additional segment
+ for(int i = 1; i < len-1; ++i) {
+
+ pos1 = points[i];
+ Vector2 pos2 = points[i+1];
+
+ Vector2 f1 = (pos2 - pos1).normalized();
+ Vector2 u1 = rotate90(f1);
+
+ // Determine joint orientation
+ const float dp = u0.dot(f1);
+ const Orientation orientation = (dp > 0.f ? UP : DOWN);
+
+ Vector2 inner_normal0, inner_normal1;
+ if(orientation == UP) {
+ inner_normal0 = u0 * hw;
+ inner_normal1 = u1 * hw;
+ }
+ else {
+ inner_normal0 = -u0 * hw;
+ inner_normal1 = -u1 * hw;
+ }
+
+ // ---------------------------
+ // /
+ // 0 / 1
+ // / /
+ // --------------------x------ /
+ // / / (here shown with orientation == DOWN)
+ // / /
+ // / /
+ // / /
+ // 2 /
+ // /
+
+ // Find inner intersection at the joint
+ Vector2 corner_pos_in, corner_pos_out;
+ SegmentIntersectionResult intersection_result = segment_intersection(
+ pos0 + inner_normal0, pos1 + inner_normal0,
+ pos1 + inner_normal1, pos2 + inner_normal1,
+ &corner_pos_in);
+
+ if(intersection_result == SEGMENT_INTERSECT)
+ // Inner parts of the segments intersect
+ corner_pos_out = 2.f * pos1 - corner_pos_in;
+ else {
+ // No intersection, segments are either parallel or too sharp
+ corner_pos_in = pos1 + inner_normal0;
+ corner_pos_out = pos1 - inner_normal0;
+ }
+
+ Vector2 corner_pos_up, corner_pos_down;
+ if(orientation == UP) {
+ corner_pos_up = corner_pos_in;
+ corner_pos_down = corner_pos_out;
+ }
+ else {
+ corner_pos_up = corner_pos_out;
+ corner_pos_down = corner_pos_in;
+ }
+
+ LineJointMode current_joint_mode = joint_mode;
+
+ Vector2 pos_up1, pos_down1;
+ if(intersection_result == SEGMENT_INTERSECT) {
+ // Fallback on bevel if sharp angle is too high (because it would produce very long miters)
+ if(current_joint_mode == LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / hw_sq > sharp_limit_sq) {
+ current_joint_mode = LINE_JOINT_BEVEL;
+ }
+ if(current_joint_mode == LINE_JOINT_SHARP) {
+ // In this case, we won't create joint geometry,
+ // The previous and next line quads will directly share an edge.
+ pos_up1 = corner_pos_up;
+ pos_down1 = corner_pos_down;
+ }
+ else {
+ // Bevel or round
+ if(orientation == UP) {
+ pos_up1 = corner_pos_up;
+ pos_down1 = pos1 - u0 * hw;
+ }
+ else {
+ pos_up1 = pos1 + u0 * hw;
+ pos_down1 = corner_pos_down;
+ }
+ }
+ }
+ else {
+ // No intersection: fallback
+ pos_up1 = corner_pos_up;
+ pos_down1 = corner_pos_down;
+ }
+
+ // Add current line body quad
+ // Triangles are clockwise
+ if(distance_required) {
+ current_distance1 += pos0.distance_to(pos1);
+ }
+ if(_interpolate_color) {
+ color1 = gradient->get_color_at_offset(current_distance1 / total_distance);
+ }
+ if(texture_mode == LINE_TEXTURE_TILE) {
+ uvx0 = current_distance0 / width;
+ uvx1 = current_distance1 / width;
+ }
+
+ strip_add_quad(pos_up1, pos_down1, color1, uvx1);
+
+ // Swap vars for use in the next line
+ color0 = color1;
+ u0 = u1;
+ f0 = f1;
+ pos0 = pos1;
+ current_distance0 = current_distance1;
+ if(intersection_result == SEGMENT_INTERSECT) {
+ if(current_joint_mode == LINE_JOINT_SHARP) {
+ pos_up0 = pos_up1;
+ pos_down0 = pos_down1;
+ }
+ else {
+ if(orientation == UP) {
+ pos_up0 = corner_pos_up;
+ pos_down0 = pos1 - u1 * hw;
+ }
+ else {
+ pos_up0 = pos1 + u1 * hw;
+ pos_down0 = corner_pos_down;
+ }
+ }
+ }
+ else {
+ pos_up0 = pos1 + u1 * hw;
+ pos_down0 = pos1 - u1 * hw;
+ }
+ // From this point, bu0 and bd0 concern the next segment
+
+ // Add joint geometry
+ if(current_joint_mode != LINE_JOINT_SHARP) {
+
+ // ________________ cbegin
+ // / \
+ // / \
+ // ____________/_ _ _\ cend
+ // | |
+ // | |
+ // | |
+
+ Vector2 cbegin, cend;
+ if(orientation == UP) {
+ cbegin = pos_down1;
+ cend = pos_down0;
+ }
+ else {
+ cbegin = pos_up1;
+ cend = pos_up0;
+ }
+
+ if(current_joint_mode == LINE_JOINT_BEVEL) {
+ strip_add_tri(cend, orientation);
+ }
+ else if(current_joint_mode == LINE_JOINT_ROUND) {
+ Vector2 vbegin = cbegin - pos1;
+ Vector2 vend = cend - pos1;
+ strip_add_arc(pos1, vend.angle_to(vbegin), orientation);
+ }
+
+ if(intersection_result != SEGMENT_INTERSECT)
+ // In this case the joint is too fucked up to be re-used,
+ // start again the strip with fallback points
+ strip_begin(pos_up0, pos_down0, color1, uvx1);
+ }
+ }
+
+ // Last (or only) segment
+
+ pos1 = points[points.size()-1];
+
+ Vector2 pos_up1 = pos1 + u0 * hw;
+ Vector2 pos_down1 = pos1 - u0 * hw;
+
+ // End cap (box)
+ if(end_cap_mode == LINE_CAP_BOX) {
+ pos_up1 += f0 * hw;
+ pos_down1 += f0 * hw;
+ }
+
+ if(distance_required) {
+ current_distance1 += pos0.distance_to(pos1);
+ }
+ if(_interpolate_color) {
+ color1 = gradient->get_color(gradient->get_points_count()-1);
+ }
+ if(texture_mode == LINE_TEXTURE_TILE) {
+ uvx1 = current_distance1 / width;
+ }
+
+ strip_add_quad(pos_up1, pos_down1, color1, uvx1);
+
+ // End cap (round)
+ if(end_cap_mode == LINE_CAP_ROUND) {
+ // Note: color is not used in case we don't interpolate...
+ Color color = _interpolate_color ? gradient->get_color(gradient->get_points_count()-1) : Color(0,0,0);
+ new_arc(pos1, pos_up1 - pos1, Math_PI, color, Rect2(uvx1-0.5f, 0.f, 1.f, 1.f));
+ }
+}
+
+void LineBuilder::strip_begin(Vector2 up, Vector2 down, Color color, float uvx) {
+ int vi = vertices.size();
+
+ vertices.push_back(up);
+ vertices.push_back(down);
+
+ if(_interpolate_color) {
+ colors.push_back(color);
+ colors.push_back(color);
+ }
+
+ if(texture_mode != LINE_TEXTURE_NONE) {
+ uvs.push_back(Vector2(uvx, 0.f));
+ uvs.push_back(Vector2(uvx, 1.f));
+ }
+
+ _last_index[UP] = vi;
+ _last_index[DOWN] = vi+1;
+}
+
+void LineBuilder::strip_new_quad(Vector2 up, Vector2 down, Color color, float uvx) {
+ int vi = vertices.size();
+
+ vertices.push_back(vertices[_last_index[UP]]);
+ vertices.push_back(vertices[_last_index[DOWN]]);
+ vertices.push_back(up);
+ vertices.push_back(down);
+
+ if(_interpolate_color) {
+ colors.push_back(color);
+ colors.push_back(color);
+ colors.push_back(color);
+ colors.push_back(color);
+ }
+
+ if(texture_mode != LINE_TEXTURE_NONE) {
+ uvs.push_back(uvs[_last_index[UP]]);
+ uvs.push_back(uvs[_last_index[DOWN]]);
+ uvs.push_back(Vector2(uvx, UP));
+ uvs.push_back(Vector2(uvx, DOWN));
+ }
+
+ indices.push_back(vi);
+ indices.push_back(vi+3);
+ indices.push_back(vi+1);
+ indices.push_back(vi);
+ indices.push_back(vi+2);
+ indices.push_back(vi+3);
+
+ _last_index[UP] = vi+2;
+ _last_index[DOWN] = vi+3;
+}
+
+void LineBuilder::strip_add_quad(Vector2 up, Vector2 down, Color color, float uvx) {
+ int vi = vertices.size();
+
+ vertices.push_back(up);
+ vertices.push_back(down);
+
+ if(_interpolate_color) {
+ colors.push_back(color);
+ colors.push_back(color);
+ }
+
+ if(texture_mode != LINE_TEXTURE_NONE) {
+ uvs.push_back(Vector2(uvx, 0.f));
+ uvs.push_back(Vector2(uvx, 1.f));
+ }
+
+ indices.push_back(_last_index[UP]);
+ indices.push_back(vi+1);
+ indices.push_back(_last_index[DOWN]);
+ indices.push_back(_last_index[UP]);
+ indices.push_back(vi);
+ indices.push_back(vi+1);
+
+ _last_index[UP] = vi;
+ _last_index[DOWN] = vi+1;
+}
+
+void LineBuilder::strip_add_tri(Vector2 up, Orientation orientation) {
+ int vi = vertices.size();
+
+ vertices.push_back(up);
+
+ if(_interpolate_color) {
+ colors.push_back(colors[colors.size()-1]);
+ }
+
+ Orientation opposite_orientation = orientation == UP ? DOWN : UP;
+
+ if(texture_mode != LINE_TEXTURE_NONE) {
+ // UVs are just one slice of the texture all along
+ // (otherwise we can't share the bottom vertice)
+ uvs.push_back(uvs[_last_index[opposite_orientation]]);
+ }
+
+ indices.push_back(_last_index[opposite_orientation]);
+ indices.push_back(vi);
+ indices.push_back(_last_index[orientation]);
+
+ _last_index[opposite_orientation] = vi;
+}
+
+void LineBuilder::strip_add_arc(Vector2 center, float angle_delta, Orientation orientation) {
+
+ // Take the two last vertices and extrude an arc made of triangles
+ // that all share one of the initial vertices
+
+ Orientation opposite_orientation = orientation == UP ? DOWN : UP;
+ Vector2 vbegin = vertices[_last_index[opposite_orientation]] - center;
+ float radius = vbegin.length();
+ float angle_step = Math_PI / static_cast<float>(round_precision);
+ float steps = Math::abs(angle_delta) / angle_step;
+
+ if(angle_delta < 0.f)
+ angle_step = -angle_step;
+
+ float t = vbegin.angle_to(Vector2(1, 0));
+ float end_angle = t + angle_delta;
+ Vector2 rpos(0,0);
+
+ // Arc vertices
+ for(int ti = 0; ti < steps; ++ti, t += angle_step) {
+ rpos = center + Vector2(Math::cos(t), Math::sin(t)) * radius;
+ strip_add_tri(rpos, orientation);
+ }
+
+ // Last arc vertice
+ rpos = center + Vector2(Math::cos(end_angle), Math::sin(end_angle)) * radius;
+ strip_add_tri(rpos, orientation);
+}
+
+void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Color color, Rect2 uv_rect) {
+
+ // Make a standalone arc that doesn't use existing vertices,
+ // with undistorted UVs from withing a square section
+
+ float radius = vbegin.length();
+ float angle_step = Math_PI / static_cast<float>(round_precision);
+ float steps = Math::abs(angle_delta) / angle_step;
+
+ if(angle_delta < 0.f)
+ angle_step = -angle_step;
+
+ float t = vbegin.angle_to(Vector2(1, 0));
+ float end_angle = t + angle_delta;
+ Vector2 rpos(0,0);
+ float tt_begin = -Math_PI / 2.f;
+ float tt = tt_begin;
+
+ // Center vertice
+ int vi = vertices.size();
+ vertices.push_back(center);
+ if(_interpolate_color)
+ colors.push_back(color);
+ if(texture_mode != LINE_TEXTURE_NONE)
+ uvs.push_back(interpolate(uv_rect, Vector2(0.5f, 0.5f)));
+
+ // Arc vertices
+ for(int ti = 0; ti < steps; ++ti, t += angle_step) {
+ Vector2 sc = Vector2(Math::cos(t), Math::sin(t));
+ rpos = center + sc * radius;
+
+ vertices.push_back(rpos);
+ if(_interpolate_color)
+ colors.push_back(color);
+ if(texture_mode != LINE_TEXTURE_NONE) {
+ Vector2 tsc = Vector2(Math::cos(tt), Math::sin(tt));
+ uvs.push_back(interpolate(uv_rect, 0.5f*(tsc+Vector2(1.f,1.f))));
+ tt += angle_step;
+ }
+ }
+
+ // Last arc vertice
+ Vector2 sc = Vector2(Math::cos(end_angle), Math::sin(end_angle));
+ rpos = center + sc * radius;
+ vertices.push_back(rpos);
+ if(_interpolate_color)
+ colors.push_back(color);
+ if(texture_mode != LINE_TEXTURE_NONE) {
+ tt = tt_begin + angle_delta;
+ Vector2 tsc = Vector2(Math::cos(tt), Math::sin(tt));
+ uvs.push_back(interpolate(uv_rect, 0.5f*(tsc+Vector2(1.f,1.f))));
+ }
+
+ // Make up triangles
+ int vi0 = vi;
+ for(int ti = 0; ti < steps; ++ti) {
+ indices.push_back(vi0);
+ indices.push_back(++vi);
+ indices.push_back(vi+1);
+ }
+}
+
+
diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h
new file mode 100644
index 0000000000..3fc9e4bb85
--- /dev/null
+++ b/scene/2d/line_builder.h
@@ -0,0 +1,104 @@
+/*************************************************************************/
+/* line_builder.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 LINE_BUILDER_H
+#define LINE_BUILDER_H
+
+#include "math_2d.h"
+#include "color.h"
+#include "scene/resources/color_ramp.h"
+
+enum LineJointMode {
+ LINE_JOINT_SHARP = 0,
+ LINE_JOINT_BEVEL,
+ LINE_JOINT_ROUND
+};
+
+enum LineCapMode {
+ LINE_CAP_NONE = 0,
+ LINE_CAP_BOX,
+ LINE_CAP_ROUND
+};
+
+enum LineTextureMode {
+ LINE_TEXTURE_NONE = 0,
+ LINE_TEXTURE_TILE
+ // TODO STRETCH mode
+};
+
+class LineBuilder {
+public:
+ // TODO Move in a struct and reference it
+ // Input
+ Vector<Vector2> points;
+ LineJointMode joint_mode;
+ LineCapMode begin_cap_mode;
+ LineCapMode end_cap_mode;
+ float width;
+ Color default_color;
+ ColorRamp* gradient;
+ LineTextureMode texture_mode;
+ float sharp_limit;
+ int round_precision;
+ // TODO offset_joints option (offers alternative implementation of round joints)
+
+ // TODO Move in a struct and reference it
+ // Output
+ Vector<Vector2> vertices;
+ Vector<Color> colors;
+ Vector<Vector2> uvs;
+ Vector<int> indices;
+
+ LineBuilder();
+
+ void build();
+ void clear_output();
+
+private:
+ enum Orientation {
+ UP = 0,
+ DOWN = 1
+ };
+
+ // Triangle-strip methods
+ void strip_begin(Vector2 up, Vector2 down, Color color, float uvx);
+ void strip_new_quad(Vector2 up, Vector2 down, Color color, float uvx);
+ void strip_add_quad(Vector2 up, Vector2 down, Color color, float uvx);
+ void strip_add_tri(Vector2 up, Orientation orientation);
+ void strip_add_arc(Vector2 center, float angle_delta, Orientation orientation);
+
+ void new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Color color, Rect2 uv_rect);
+
+private:
+ bool _interpolate_color;
+ int _last_index[2]; // Index of last up and down vertices of the strip
+
+};
+
+
+#endif // LINE_BUILDER_H
diff --git a/scene/2d/navigation2d.cpp b/scene/2d/navigation2d.cpp
index ec1109b41b..7f48749dc3 100644
--- a/scene/2d/navigation2d.cpp
+++ b/scene/2d/navigation2d.cpp
@@ -804,13 +804,13 @@ Object* Navigation2D::get_closest_point_owner(const Vector2& p_point) {
void Navigation2D::_bind_methods() {
- ClassDB::bind_method(_MD("navpoly_create","mesh:NavigationPolygon","xform","owner"),&Navigation2D::navpoly_create,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("navpoly_set_transform","id","xform"),&Navigation2D::navpoly_set_transform);
- ClassDB::bind_method(_MD("navpoly_remove","id"),&Navigation2D::navpoly_remove);
+ ClassDB::bind_method(D_METHOD("navpoly_create","mesh:NavigationPolygon","xform","owner"),&Navigation2D::navpoly_create,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("navpoly_set_transform","id","xform"),&Navigation2D::navpoly_set_transform);
+ ClassDB::bind_method(D_METHOD("navpoly_remove","id"),&Navigation2D::navpoly_remove);
- ClassDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation2D::get_simple_path,DEFVAL(true));
- ClassDB::bind_method(_MD("get_closest_point","to_point"),&Navigation2D::get_closest_point);
- ClassDB::bind_method(_MD("get_closest_point_owner","to_point"),&Navigation2D::get_closest_point_owner);
+ ClassDB::bind_method(D_METHOD("get_simple_path","start","end","optimize"),&Navigation2D::get_simple_path,DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_closest_point","to_point"),&Navigation2D::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_point_owner","to_point"),&Navigation2D::get_closest_point_owner);
}
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index 88d6a90e81..9dbbd34ae9 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -247,32 +247,32 @@ void NavigationPolygon::make_polygons_from_outlines(){
void NavigationPolygon::_bind_methods() {
- ClassDB::bind_method(_MD("set_vertices","vertices"),&NavigationPolygon::set_vertices);
- ClassDB::bind_method(_MD("get_vertices"),&NavigationPolygon::get_vertices);
-
- ClassDB::bind_method(_MD("add_polygon","polygon"),&NavigationPolygon::add_polygon);
- ClassDB::bind_method(_MD("get_polygon_count"),&NavigationPolygon::get_polygon_count);
- ClassDB::bind_method(_MD("get_polygon","idx"),&NavigationPolygon::get_polygon);
- ClassDB::bind_method(_MD("clear_polygons"),&NavigationPolygon::clear_polygons);
-
- ClassDB::bind_method(_MD("add_outline","outline"),&NavigationPolygon::add_outline);
- ClassDB::bind_method(_MD("add_outline_at_index","outline","index"),&NavigationPolygon::add_outline_at_index);
- ClassDB::bind_method(_MD("get_outline_count"),&NavigationPolygon::get_outline_count);
- ClassDB::bind_method(_MD("set_outline","idx","outline"),&NavigationPolygon::set_outline);
- ClassDB::bind_method(_MD("get_outline","idx"),&NavigationPolygon::get_outline);
- ClassDB::bind_method(_MD("remove_outline","idx"),&NavigationPolygon::remove_outline);
- ClassDB::bind_method(_MD("clear_outlines"),&NavigationPolygon::clear_outlines);
- ClassDB::bind_method(_MD("make_polygons_from_outlines"),&NavigationPolygon::make_polygons_from_outlines);
-
- ClassDB::bind_method(_MD("_set_polygons","polygons"),&NavigationPolygon::_set_polygons);
- ClassDB::bind_method(_MD("_get_polygons"),&NavigationPolygon::_get_polygons);
-
- ClassDB::bind_method(_MD("_set_outlines","outlines"),&NavigationPolygon::_set_outlines);
- ClassDB::bind_method(_MD("_get_outlines"),&NavigationPolygon::_get_outlines);
-
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_vertices"),_SCS("get_vertices"));
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_polygons"),_SCS("_get_polygons"));
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"outlines",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_outlines"),_SCS("_get_outlines"));
+ ClassDB::bind_method(D_METHOD("set_vertices","vertices"),&NavigationPolygon::set_vertices);
+ ClassDB::bind_method(D_METHOD("get_vertices"),&NavigationPolygon::get_vertices);
+
+ ClassDB::bind_method(D_METHOD("add_polygon","polygon"),&NavigationPolygon::add_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon_count"),&NavigationPolygon::get_polygon_count);
+ ClassDB::bind_method(D_METHOD("get_polygon","idx"),&NavigationPolygon::get_polygon);
+ ClassDB::bind_method(D_METHOD("clear_polygons"),&NavigationPolygon::clear_polygons);
+
+ ClassDB::bind_method(D_METHOD("add_outline","outline"),&NavigationPolygon::add_outline);
+ ClassDB::bind_method(D_METHOD("add_outline_at_index","outline","index"),&NavigationPolygon::add_outline_at_index);
+ ClassDB::bind_method(D_METHOD("get_outline_count"),&NavigationPolygon::get_outline_count);
+ ClassDB::bind_method(D_METHOD("set_outline","idx","outline"),&NavigationPolygon::set_outline);
+ ClassDB::bind_method(D_METHOD("get_outline","idx"),&NavigationPolygon::get_outline);
+ ClassDB::bind_method(D_METHOD("remove_outline","idx"),&NavigationPolygon::remove_outline);
+ ClassDB::bind_method(D_METHOD("clear_outlines"),&NavigationPolygon::clear_outlines);
+ ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"),&NavigationPolygon::make_polygons_from_outlines);
+
+ ClassDB::bind_method(D_METHOD("_set_polygons","polygons"),&NavigationPolygon::_set_polygons);
+ ClassDB::bind_method(D_METHOD("_get_polygons"),&NavigationPolygon::_get_polygons);
+
+ ClassDB::bind_method(D_METHOD("_set_outlines","outlines"),&NavigationPolygon::_set_outlines);
+ ClassDB::bind_method(D_METHOD("_get_outlines"),&NavigationPolygon::_get_outlines);
+
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_vertices","get_vertices");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_polygons","_get_polygons");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"outlines",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_outlines","_get_outlines");
}
NavigationPolygon::NavigationPolygon() {
@@ -480,16 +480,16 @@ String NavigationPolygonInstance::get_configuration_warning() const {
void NavigationPolygonInstance::_bind_methods() {
- ClassDB::bind_method(_MD("set_navigation_polygon","navpoly:NavigationPolygon"),&NavigationPolygonInstance::set_navigation_polygon);
- ClassDB::bind_method(_MD("get_navigation_polygon:NavigationPolygon"),&NavigationPolygonInstance::get_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("set_navigation_polygon","navpoly:NavigationPolygon"),&NavigationPolygonInstance::set_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("get_navigation_polygon:NavigationPolygon"),&NavigationPolygonInstance::get_navigation_polygon);
- ClassDB::bind_method(_MD("set_enabled","enabled"),&NavigationPolygonInstance::set_enabled);
- ClassDB::bind_method(_MD("is_enabled"),&NavigationPolygonInstance::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled","enabled"),&NavigationPolygonInstance::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"),&NavigationPolygonInstance::is_enabled);
- ClassDB::bind_method(_MD("_navpoly_changed"),&NavigationPolygonInstance::_navpoly_changed);
+ ClassDB::bind_method(D_METHOD("_navpoly_changed"),&NavigationPolygonInstance::_navpoly_changed);
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navpoly",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon"),_SCS("set_navigation_polygon"),_SCS("get_navigation_polygon"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navpoly",PROPERTY_HINT_RESOURCE_TYPE,"NavigationPolygon"),"set_navigation_polygon","get_navigation_polygon");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),"set_enabled","is_enabled");
}
NavigationPolygonInstance::NavigationPolygonInstance() {
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index fb71a5b536..710f9731c5 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -423,67 +423,67 @@ void Node2D::_bind_methods() {
// TODO: Obsolete those two methods (old name) properly (GH-4397)
- ClassDB::bind_method(_MD("_get_rotd"),&Node2D::_get_rotd);
- ClassDB::bind_method(_MD("_set_rotd","degrees"),&Node2D::_set_rotd);
+ ClassDB::bind_method(D_METHOD("_get_rotd"),&Node2D::_get_rotd);
+ ClassDB::bind_method(D_METHOD("_set_rotd","degrees"),&Node2D::_set_rotd);
- ClassDB::bind_method(_MD("set_position","pos"),&Node2D::set_position);
- ClassDB::bind_method(_MD("set_rotation","radians"),&Node2D::set_rotation);
- ClassDB::bind_method(_MD("set_rotation_in_degrees","degrees"),&Node2D::set_rotation_in_degrees);
- ClassDB::bind_method(_MD("set_scale","scale"),&Node2D::set_scale);
+ ClassDB::bind_method(D_METHOD("set_position","pos"),&Node2D::set_position);
+ ClassDB::bind_method(D_METHOD("set_rotation","radians"),&Node2D::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_in_degrees","degrees"),&Node2D::set_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("set_scale","scale"),&Node2D::set_scale);
- ClassDB::bind_method(_MD("get_position"),&Node2D::get_position);
- ClassDB::bind_method(_MD("get_rotation"),&Node2D::get_rotation);
- ClassDB::bind_method(_MD("get_rotation_in_degrees"),&Node2D::get_rotation_in_degrees);
- ClassDB::bind_method(_MD("get_scale"),&Node2D::get_scale);
+ ClassDB::bind_method(D_METHOD("get_position"),&Node2D::get_position);
+ ClassDB::bind_method(D_METHOD("get_rotation"),&Node2D::get_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation_in_degrees"),&Node2D::get_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("get_scale"),&Node2D::get_scale);
- ClassDB::bind_method(_MD("rotate","radians"),&Node2D::rotate);
- ClassDB::bind_method(_MD("move_local_x","delta","scaled"),&Node2D::move_x,DEFVAL(false));
- ClassDB::bind_method(_MD("move_local_y","delta","scaled"),&Node2D::move_y,DEFVAL(false));
- ClassDB::bind_method(_MD("translate","offset"),&Node2D::translate);
- ClassDB::bind_method(_MD("global_translate","offset"),&Node2D::global_translate);
- ClassDB::bind_method(_MD("scale","ratio"),&Node2D::scale);
+ ClassDB::bind_method(D_METHOD("rotate","radians"),&Node2D::rotate);
+ ClassDB::bind_method(D_METHOD("move_local_x","delta","scaled"),&Node2D::move_x,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("move_local_y","delta","scaled"),&Node2D::move_y,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("translate","offset"),&Node2D::translate);
+ ClassDB::bind_method(D_METHOD("global_translate","offset"),&Node2D::global_translate);
+ ClassDB::bind_method(D_METHOD("scale","ratio"),&Node2D::scale);
- ClassDB::bind_method(_MD("set_global_position","pos"),&Node2D::set_global_position);
- ClassDB::bind_method(_MD("get_global_position"),&Node2D::get_global_position);
- ClassDB::bind_method(_MD("set_global_rotation","radians"),&Node2D::set_global_rotation);
- ClassDB::bind_method(_MD("get_global_rotation"),&Node2D::get_global_rotation);
- ClassDB::bind_method(_MD("set_global_rotation_in_degrees","degrees"),&Node2D::set_global_rotation_in_degrees);
- ClassDB::bind_method(_MD("get_global_rotation_in_degrees"),&Node2D::get_global_rotation_in_degrees);
- ClassDB::bind_method(_MD("set_global_scale","scale"),&Node2D::set_global_scale);
- ClassDB::bind_method(_MD("get_global_scale"),&Node2D::get_global_scale);
+ ClassDB::bind_method(D_METHOD("set_global_position","pos"),&Node2D::set_global_position);
+ ClassDB::bind_method(D_METHOD("get_global_position"),&Node2D::get_global_position);
+ ClassDB::bind_method(D_METHOD("set_global_rotation","radians"),&Node2D::set_global_rotation);
+ ClassDB::bind_method(D_METHOD("get_global_rotation"),&Node2D::get_global_rotation);
+ ClassDB::bind_method(D_METHOD("set_global_rotation_in_degrees","degrees"),&Node2D::set_global_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("get_global_rotation_in_degrees"),&Node2D::get_global_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("set_global_scale","scale"),&Node2D::set_global_scale);
+ ClassDB::bind_method(D_METHOD("get_global_scale"),&Node2D::get_global_scale);
- ClassDB::bind_method(_MD("set_transform","xform"),&Node2D::set_transform);
- ClassDB::bind_method(_MD("set_global_transform","xform"),&Node2D::set_global_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","xform"),&Node2D::set_transform);
+ ClassDB::bind_method(D_METHOD("set_global_transform","xform"),&Node2D::set_global_transform);
- ClassDB::bind_method(_MD("look_at","point"),&Node2D::look_at);
- ClassDB::bind_method(_MD("get_angle_to","point"),&Node2D::get_angle_to);
+ ClassDB::bind_method(D_METHOD("look_at","point"),&Node2D::look_at);
+ ClassDB::bind_method(D_METHOD("get_angle_to","point"),&Node2D::get_angle_to);
- ClassDB::bind_method(_MD("set_z","z"),&Node2D::set_z);
- ClassDB::bind_method(_MD("get_z"),&Node2D::get_z);
+ ClassDB::bind_method(D_METHOD("set_z","z"),&Node2D::set_z);
+ ClassDB::bind_method(D_METHOD("get_z"),&Node2D::get_z);
- ClassDB::bind_method(_MD("set_z_as_relative","enable"),&Node2D::set_z_as_relative);
- ClassDB::bind_method(_MD("is_z_relative"),&Node2D::is_z_relative);
+ ClassDB::bind_method(D_METHOD("set_z_as_relative","enable"),&Node2D::set_z_as_relative);
+ ClassDB::bind_method(D_METHOD("is_z_relative"),&Node2D::is_z_relative);
- ClassDB::bind_method(_MD("edit_set_pivot","pivot"),&Node2D::edit_set_pivot);
+ ClassDB::bind_method(D_METHOD("edit_set_pivot","pivot"),&Node2D::edit_set_pivot);
- ClassDB::bind_method(_MD("get_relative_transform_to_parent","parent"),&Node2D::get_relative_transform_to_parent);
+ ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent","parent"),&Node2D::get_relative_transform_to_parent);
ADD_GROUP("Transform","");
- ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"position"),_SCS("set_position"),_SCS("get_position"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"rotation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_rotation"),_SCS("get_rotation"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"rotation_deg",PROPERTY_HINT_RANGE,"-1440,1440,0.1",PROPERTY_USAGE_EDITOR),_SCS("set_rotation_in_degrees"),_SCS("get_rotation_in_degrees"));
- ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"scale"),_SCS("set_scale"),_SCS("get_scale"));
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D,"transform",PROPERTY_HINT_NONE,"",0),_SCS("set_transform"),_SCS("get_transform"));
-
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_position",PROPERTY_HINT_NONE,"",0),_SCS("set_global_position"),_SCS("get_global_position"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_rotation",PROPERTY_HINT_NONE,"",0),_SCS("set_global_rotation"),_SCS("get_global_rotation"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_rotation_deg",PROPERTY_HINT_NONE,"",0),_SCS("set_global_rotation_in_degrees"),_SCS("get_global_rotation_in_degrees"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_scale",PROPERTY_HINT_NONE,"",0),_SCS("set_global_scale"),_SCS("get_global_scale"));
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D,"global_transform",PROPERTY_HINT_NONE,"",0),_SCS("set_global_transform"),_SCS("get_global_transform"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"position"),"set_position","get_position");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"rotation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_rotation","get_rotation");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"rotation_deg",PROPERTY_HINT_RANGE,"-1440,1440,0.1",PROPERTY_USAGE_EDITOR),"set_rotation_in_degrees","get_rotation_in_degrees");
+ ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"scale"),"set_scale","get_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D,"transform",PROPERTY_HINT_NONE,"",0),"set_transform","get_transform");
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_position",PROPERTY_HINT_NONE,"",0),"set_global_position","get_global_position");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_rotation",PROPERTY_HINT_NONE,"",0),"set_global_rotation","get_global_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_rotation_deg",PROPERTY_HINT_NONE,"",0),"set_global_rotation_in_degrees","get_global_rotation_in_degrees");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"global_scale",PROPERTY_HINT_NONE,"",0),"set_global_scale","get_global_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D,"global_transform",PROPERTY_HINT_NONE,"",0),"set_global_transform","get_global_transform");
ADD_GROUP("Z","");
- ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"z",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z"),_SCS("get_z"));
- ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"z_as_relative"),_SCS("set_z_as_relative"),_SCS("is_z_relative"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"z",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),"set_z","get_z");
+ ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"z_as_relative"),"set_z_as_relative","is_z_relative");
}
diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index 1e6a449fce..9336dc51af 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -189,28 +189,28 @@ Vector2 ParallaxBackground::get_final_offset() const {
void ParallaxBackground::_bind_methods() {
- ClassDB::bind_method(_MD("_camera_moved"),&ParallaxBackground::_camera_moved);
- ClassDB::bind_method(_MD("set_scroll_offset","ofs"),&ParallaxBackground::set_scroll_offset);
- ClassDB::bind_method(_MD("get_scroll_offset"),&ParallaxBackground::get_scroll_offset);
- ClassDB::bind_method(_MD("set_scroll_base_offset","ofs"),&ParallaxBackground::set_scroll_base_offset);
- ClassDB::bind_method(_MD("get_scroll_base_offset"),&ParallaxBackground::get_scroll_base_offset);
- ClassDB::bind_method(_MD("set_scroll_base_scale","scale"),&ParallaxBackground::set_scroll_base_scale);
- ClassDB::bind_method(_MD("get_scroll_base_scale"),&ParallaxBackground::get_scroll_base_scale);
- ClassDB::bind_method(_MD("set_limit_begin","ofs"),&ParallaxBackground::set_limit_begin);
- ClassDB::bind_method(_MD("get_limit_begin"),&ParallaxBackground::get_limit_begin);
- ClassDB::bind_method(_MD("set_limit_end","ofs"),&ParallaxBackground::set_limit_end);
- ClassDB::bind_method(_MD("get_limit_end"),&ParallaxBackground::get_limit_end);
- ClassDB::bind_method(_MD("set_ignore_camera_zoom","ignore"), &ParallaxBackground::set_ignore_camera_zoom);
- ClassDB::bind_method(_MD("is_ignore_camera_zoom"), &ParallaxBackground::is_ignore_camera_zoom);
+ ClassDB::bind_method(D_METHOD("_camera_moved"),&ParallaxBackground::_camera_moved);
+ ClassDB::bind_method(D_METHOD("set_scroll_offset","ofs"),&ParallaxBackground::set_scroll_offset);
+ ClassDB::bind_method(D_METHOD("get_scroll_offset"),&ParallaxBackground::get_scroll_offset);
+ ClassDB::bind_method(D_METHOD("set_scroll_base_offset","ofs"),&ParallaxBackground::set_scroll_base_offset);
+ ClassDB::bind_method(D_METHOD("get_scroll_base_offset"),&ParallaxBackground::get_scroll_base_offset);
+ ClassDB::bind_method(D_METHOD("set_scroll_base_scale","scale"),&ParallaxBackground::set_scroll_base_scale);
+ ClassDB::bind_method(D_METHOD("get_scroll_base_scale"),&ParallaxBackground::get_scroll_base_scale);
+ ClassDB::bind_method(D_METHOD("set_limit_begin","ofs"),&ParallaxBackground::set_limit_begin);
+ ClassDB::bind_method(D_METHOD("get_limit_begin"),&ParallaxBackground::get_limit_begin);
+ ClassDB::bind_method(D_METHOD("set_limit_end","ofs"),&ParallaxBackground::set_limit_end);
+ ClassDB::bind_method(D_METHOD("get_limit_end"),&ParallaxBackground::get_limit_end);
+ ClassDB::bind_method(D_METHOD("set_ignore_camera_zoom","ignore"), &ParallaxBackground::set_ignore_camera_zoom);
+ ClassDB::bind_method(D_METHOD("is_ignore_camera_zoom"), &ParallaxBackground::is_ignore_camera_zoom);
ADD_GROUP("Scroll","scroll_");
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_offset"),_SCS("set_scroll_offset"),_SCS("get_scroll_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_base_offset"),_SCS("set_scroll_base_offset"),_SCS("get_scroll_base_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_base_scale"),_SCS("set_scroll_base_scale"),_SCS("get_scroll_base_scale"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_limit_begin"),_SCS("set_limit_begin"),_SCS("get_limit_begin"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_limit_end"),_SCS("set_limit_end"),_SCS("get_limit_end"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "scroll_ignore_camera_zoom"), _SCS("set_ignore_camera_zoom"), _SCS("is_ignore_camera_zoom"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_offset"),"set_scroll_offset","get_scroll_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_base_offset"),"set_scroll_base_offset","get_scroll_base_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_base_scale"),"set_scroll_base_scale","get_scroll_base_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_limit_begin"),"set_limit_begin","get_limit_begin");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scroll_limit_end"),"set_limit_end","get_limit_end");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "scroll_ignore_camera_zoom"), "set_ignore_camera_zoom", "is_ignore_camera_zoom");
}
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index 9aa6640727..37d8fb52f1 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -150,17 +150,17 @@ String ParallaxLayer::get_configuration_warning() const {
void ParallaxLayer::_bind_methods() {
- ClassDB::bind_method(_MD("set_motion_scale","scale"),&ParallaxLayer::set_motion_scale);
- ClassDB::bind_method(_MD("get_motion_scale"),&ParallaxLayer::get_motion_scale);
- ClassDB::bind_method(_MD("set_motion_offset","offset"),&ParallaxLayer::set_motion_offset);
- ClassDB::bind_method(_MD("get_motion_offset"),&ParallaxLayer::get_motion_offset);
- ClassDB::bind_method(_MD("set_mirroring","mirror"),&ParallaxLayer::set_mirroring);
- ClassDB::bind_method(_MD("get_mirroring"),&ParallaxLayer::get_mirroring);
+ ClassDB::bind_method(D_METHOD("set_motion_scale","scale"),&ParallaxLayer::set_motion_scale);
+ ClassDB::bind_method(D_METHOD("get_motion_scale"),&ParallaxLayer::get_motion_scale);
+ ClassDB::bind_method(D_METHOD("set_motion_offset","offset"),&ParallaxLayer::set_motion_offset);
+ ClassDB::bind_method(D_METHOD("get_motion_offset"),&ParallaxLayer::get_motion_offset);
+ ClassDB::bind_method(D_METHOD("set_mirroring","mirror"),&ParallaxLayer::set_mirroring);
+ ClassDB::bind_method(D_METHOD("get_mirroring"),&ParallaxLayer::get_mirroring);
ADD_GROUP("Motion","motion_");
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion_scale"),_SCS("set_motion_scale"),_SCS("get_motion_scale"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion_offset"),_SCS("set_motion_offset"),_SCS("get_motion_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion_mirroring"),_SCS("set_mirroring"),_SCS("get_mirroring"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion_scale"),"set_motion_scale","get_motion_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion_offset"),"set_motion_offset","get_motion_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"motion_mirroring"),"set_mirroring","get_mirroring");
}
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index 1051d3f5ff..77ace0348a 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -27,6 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "particles_2d.h"
+#include "scene/scene_string_names.h"
@@ -113,30 +114,30 @@ void ParticleAttractor2D::_set_owner(Particles2D* p_owner) {
void ParticleAttractor2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_enabled","enabled"),&ParticleAttractor2D::set_enabled);
- ClassDB::bind_method(_MD("is_enabled"),&ParticleAttractor2D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled","enabled"),&ParticleAttractor2D::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"),&ParticleAttractor2D::is_enabled);
- ClassDB::bind_method(_MD("set_radius","radius"),&ParticleAttractor2D::set_radius);
- ClassDB::bind_method(_MD("get_radius"),&ParticleAttractor2D::get_radius);
+ ClassDB::bind_method(D_METHOD("set_radius","radius"),&ParticleAttractor2D::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"),&ParticleAttractor2D::get_radius);
- ClassDB::bind_method(_MD("set_disable_radius","radius"),&ParticleAttractor2D::set_disable_radius);
- ClassDB::bind_method(_MD("get_disable_radius"),&ParticleAttractor2D::get_disable_radius);
+ ClassDB::bind_method(D_METHOD("set_disable_radius","radius"),&ParticleAttractor2D::set_disable_radius);
+ ClassDB::bind_method(D_METHOD("get_disable_radius"),&ParticleAttractor2D::get_disable_radius);
- ClassDB::bind_method(_MD("set_gravity","gravity"),&ParticleAttractor2D::set_gravity);
- ClassDB::bind_method(_MD("get_gravity"),&ParticleAttractor2D::get_gravity);
+ ClassDB::bind_method(D_METHOD("set_gravity","gravity"),&ParticleAttractor2D::set_gravity);
+ ClassDB::bind_method(D_METHOD("get_gravity"),&ParticleAttractor2D::get_gravity);
- ClassDB::bind_method(_MD("set_absorption","absorption"),&ParticleAttractor2D::set_absorption);
- ClassDB::bind_method(_MD("get_absorption"),&ParticleAttractor2D::get_absorption);
+ ClassDB::bind_method(D_METHOD("set_absorption","absorption"),&ParticleAttractor2D::set_absorption);
+ ClassDB::bind_method(D_METHOD("get_absorption"),&ParticleAttractor2D::get_absorption);
- ClassDB::bind_method(_MD("set_particles_path","path"),&ParticleAttractor2D::set_particles_path);
- ClassDB::bind_method(_MD("get_particles_path"),&ParticleAttractor2D::get_particles_path);
+ ClassDB::bind_method(D_METHOD("set_particles_path","path"),&ParticleAttractor2D::set_particles_path);
+ ClassDB::bind_method(D_METHOD("get_particles_path"),&ParticleAttractor2D::get_particles_path);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.1,16000,0.1"),_SCS("set_radius"),_SCS("get_radius"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"disable_radius",PROPERTY_HINT_RANGE,"0.1,16000,0.1"),_SCS("set_disable_radius"),_SCS("get_disable_radius"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-512,512,0.01"),_SCS("set_gravity"),_SCS("get_gravity"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"absorption",PROPERTY_HINT_RANGE,"0,512,0.01"),_SCS("set_absorption"),_SCS("get_absorption"));
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"particles_path",PROPERTY_HINT_RESOURCE_TYPE,"Particles2D"),_SCS("set_particles_path"),_SCS("get_particles_path"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),"set_enabled","is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.1,16000,0.1"),"set_radius","get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"disable_radius",PROPERTY_HINT_RANGE,"0.1,16000,0.1"),"set_disable_radius","get_disable_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-512,512,0.01"),"set_gravity","get_gravity");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"absorption",PROPERTY_HINT_RANGE,"0,512,0.01"),"set_absorption","get_absorption");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"particles_path",PROPERTY_HINT_RESOURCE_TYPE,"Particles2D"),"set_particles_path","get_particles_path");
@@ -227,21 +228,10 @@ ParticleAttractor2D::ParticleAttractor2D() {
/****************************************/
-_FORCE_INLINE_ static float _rand_from_seed(uint32_t *seed) {
+_FORCE_INLINE_ static float _rand_from_seed(uint64_t *seed) {
- uint32_t k;
- uint32_t s = (*seed);
- if (s == 0)
- s = 0x12345987;
- k = s / 127773;
- s = 16807 * (s - k * 127773) - 2836 * k;
- if (s < 0)
- s += 2147483647;
- (*seed) = s;
-
- float v=((float)((*seed) & 0xFFFFF))/(float)0xFFFFF;
- v=v*2.0-1.0;
- return v;
+ uint32_t r = Math::rand_from_seed(seed);
+ return 2.0f * (float)r / (float)Math::RANDOM_MAX - 1.0f;
}
void Particles2D::_process_particles(float p_delta) {
@@ -348,7 +338,7 @@ void Particles2D::_process_particles(float p_delta) {
}
}
p.seed=Math::rand() % 12345678;
- uint32_t rand_seed=p.seed*(i+1);
+ uint64_t rand_seed=p.seed*(i+1);
float angle = Math::deg2rad(param[PARAM_DIRECTION]+_rand_from_seed(&rand_seed)*param[PARAM_SPREAD]);
@@ -377,7 +367,7 @@ void Particles2D::_process_particles(float p_delta) {
if (!p.active)
continue;
- uint32_t rand_seed=p.seed*(i+1);
+ uint64_t rand_seed=p.seed*(i+1);
Vector2 force;
@@ -451,8 +441,9 @@ void Particles2D::_process_particles(float p_delta) {
time=Math::fmod( time+frame_time, lifetime );
if (!emitting && active_count==0) {
+ emit_signal(SceneStringNames::get_singleton()->emission_finished);
set_process(false);
-
+ set_fixed_process(false);
}
update();
@@ -470,6 +461,11 @@ void Particles2D::_notification(int p_what) {
_process_particles( get_process_delta_time() );
} break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+ _process_particles( get_fixed_process_delta_time() );
+ } break;
+
case NOTIFICATION_ENTER_TREE: {
float ppt=preprocess;
@@ -530,7 +526,7 @@ void Particles2D::_notification(int p_what) {
else
ptime=(1.0-ptime)+time_pos;
- uint32_t rand_seed=p.seed*(i+1);
+ uint64_t rand_seed=p.seed*(i+1);
Color color;
@@ -607,6 +603,10 @@ void Particles2D::_notification(int p_what) {
src_rect.pos.y = size.y * (frame/h_frames);
}
+ if (flip_h)
+ src_rect.size.x=-src_rect.size.x;
+ if (flip_v)
+ src_rect.size.y=-src_rect.size.y;
texture->draw_rect_region(ci,Rect2(Point2(),size),src_rect,color);
//VisualServer::get_singleton()->canvas_item_add_texture_rect(ci,r,texrid,false,color);
@@ -691,7 +691,8 @@ void Particles2D::set_emitting(bool p_emitting) {
if (active_count==0)
time=0;
- set_process(true);
+ set_process(process_mode==PROCESS_IDLE);
+ set_fixed_process(process_mode==PROCESS_FIXED);
time_to_live = emit_timeout;
};
emitting=p_emitting;
@@ -703,6 +704,19 @@ bool Particles2D::is_emitting() const {
return emitting;
}
+void Particles2D::set_process_mode(ProcessMode p_mode) {
+
+ process_mode=p_mode;
+ const bool should_process=emitting || active_count!=0;
+ set_process(should_process && process_mode==PROCESS_IDLE);
+ set_fixed_process(should_process && process_mode==PROCESS_FIXED);
+}
+
+Particles2D::ProcessMode Particles2D::get_process_mode() const {
+
+ return process_mode;
+}
+
void Particles2D::set_amount(int p_amount) {
ERR_FAIL_INDEX(p_amount,1024+1);
@@ -914,15 +928,6 @@ Vector2 Particles2D::get_emission_half_extents() const {
return extents;
}
-void Particles2D::testee(int a, int b, int c, int d, int e) {
-
- print_line(itos(a));
- print_line(itos(b));
- print_line(itos(c));
- print_line(itos(d));
- print_line(itos(e));
-}
-
void Particles2D::set_initial_velocity(const Vector2& p_velocity) {
@@ -1013,119 +1018,125 @@ void Particles2D::reset() {
void Particles2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_emitting","active"),&Particles2D::set_emitting);
- ClassDB::bind_method(_MD("is_emitting"),&Particles2D::is_emitting);
+ ClassDB::bind_method(D_METHOD("set_emitting","active"),&Particles2D::set_emitting);
+ ClassDB::bind_method(D_METHOD("is_emitting"),&Particles2D::is_emitting);
+
+ ClassDB::bind_method(D_METHOD("set_process_mode","mode"),&Particles2D::set_process_mode);
+ ClassDB::bind_method(D_METHOD("get_process_mode"),&Particles2D::get_process_mode);
+
+ ClassDB::bind_method(D_METHOD("set_amount","amount"),&Particles2D::set_amount);
+ ClassDB::bind_method(D_METHOD("get_amount"),&Particles2D::get_amount);
- ClassDB::bind_method(_MD("set_amount","amount"),&Particles2D::set_amount);
- ClassDB::bind_method(_MD("get_amount"),&Particles2D::get_amount);
+ ClassDB::bind_method(D_METHOD("set_lifetime","lifetime"),&Particles2D::set_lifetime);
+ ClassDB::bind_method(D_METHOD("get_lifetime"),&Particles2D::get_lifetime);
- ClassDB::bind_method(_MD("set_lifetime","lifetime"),&Particles2D::set_lifetime);
- ClassDB::bind_method(_MD("get_lifetime"),&Particles2D::get_lifetime);
+ ClassDB::bind_method(D_METHOD("set_time_scale","time_scale"),&Particles2D::set_time_scale);
+ ClassDB::bind_method(D_METHOD("get_time_scale"),&Particles2D::get_time_scale);
- ClassDB::bind_method(_MD("set_time_scale","time_scale"),&Particles2D::set_time_scale);
- ClassDB::bind_method(_MD("get_time_scale"),&Particles2D::get_time_scale);
+ ClassDB::bind_method(D_METHOD("set_pre_process_time","time"),&Particles2D::set_pre_process_time);
+ ClassDB::bind_method(D_METHOD("get_pre_process_time"),&Particles2D::get_pre_process_time);
- ClassDB::bind_method(_MD("set_pre_process_time","time"),&Particles2D::set_pre_process_time);
- ClassDB::bind_method(_MD("get_pre_process_time"),&Particles2D::get_pre_process_time);
+ ClassDB::bind_method(D_METHOD("set_emit_timeout","value"),&Particles2D::set_emit_timeout);
+ ClassDB::bind_method(D_METHOD("get_emit_timeout"),&Particles2D::get_emit_timeout);
- ClassDB::bind_method(_MD("set_emit_timeout","value"),&Particles2D::set_emit_timeout);
- ClassDB::bind_method(_MD("get_emit_timeout"),&Particles2D::get_emit_timeout);
+ ClassDB::bind_method(D_METHOD("set_param","param","value"),&Particles2D::set_param);
+ ClassDB::bind_method(D_METHOD("get_param","param"),&Particles2D::get_param);
- ClassDB::bind_method(_MD("set_param","param","value"),&Particles2D::set_param);
- ClassDB::bind_method(_MD("get_param","param"),&Particles2D::get_param);
+ ClassDB::bind_method(D_METHOD("set_randomness","param","value"),&Particles2D::set_randomness);
+ ClassDB::bind_method(D_METHOD("get_randomness","param"),&Particles2D::get_randomness);
- ClassDB::bind_method(_MD("set_randomness","param","value"),&Particles2D::set_randomness);
- ClassDB::bind_method(_MD("get_randomness","param"),&Particles2D::get_randomness);
+ ClassDB::bind_method(D_METHOD("set_texture:Texture","texture"),&Particles2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"),&Particles2D::get_texture);
- ClassDB::bind_method(_MD("set_texture:Texture","texture"),&Particles2D::set_texture);
- ClassDB::bind_method(_MD("get_texture:Texture"),&Particles2D::get_texture);
+ ClassDB::bind_method(D_METHOD("set_color","color"),&Particles2D::set_color);
+ ClassDB::bind_method(D_METHOD("get_color"),&Particles2D::get_color);
- ClassDB::bind_method(_MD("set_color","color"),&Particles2D::set_color);
- ClassDB::bind_method(_MD("get_color"),&Particles2D::get_color);
+ ClassDB::bind_method(D_METHOD("set_color_ramp:ColorRamp","color_ramp"),&Particles2D::set_color_ramp);
+ ClassDB::bind_method(D_METHOD("get_color_ramp:ColorRamp"),&Particles2D::get_color_ramp);
- ClassDB::bind_method(_MD("set_color_ramp:ColorRamp","color_ramp"),&Particles2D::set_color_ramp);
- ClassDB::bind_method(_MD("get_color_ramp:ColorRamp"),&Particles2D::get_color_ramp);
+ ClassDB::bind_method(D_METHOD("set_emissor_offset","offset"),&Particles2D::set_emissor_offset);
+ ClassDB::bind_method(D_METHOD("get_emissor_offset"),&Particles2D::get_emissor_offset);
- ClassDB::bind_method(_MD("set_emissor_offset","offset"),&Particles2D::set_emissor_offset);
- ClassDB::bind_method(_MD("get_emissor_offset"),&Particles2D::get_emissor_offset);
+ ClassDB::bind_method(D_METHOD("set_flip_h","enable"),&Particles2D::set_flip_h);
+ ClassDB::bind_method(D_METHOD("is_flipped_h"),&Particles2D::is_flipped_h);
- ClassDB::bind_method(_MD("set_flip_h","enable"),&Particles2D::set_flip_h);
- ClassDB::bind_method(_MD("is_flipped_h"),&Particles2D::is_flipped_h);
+ ClassDB::bind_method(D_METHOD("set_flip_v","enable"),&Particles2D::set_flip_v);
+ ClassDB::bind_method(D_METHOD("is_flipped_v"),&Particles2D::is_flipped_v);
- ClassDB::bind_method(_MD("set_flip_v","enable"),&Particles2D::set_flip_v);
- ClassDB::bind_method(_MD("is_flipped_v"),&Particles2D::is_flipped_v);
+ ClassDB::bind_method(D_METHOD("set_h_frames","enable"),&Particles2D::set_h_frames);
+ ClassDB::bind_method(D_METHOD("get_h_frames"),&Particles2D::get_h_frames);
- ClassDB::bind_method(_MD("set_h_frames","enable"),&Particles2D::set_h_frames);
- ClassDB::bind_method(_MD("get_h_frames"),&Particles2D::get_h_frames);
+ ClassDB::bind_method(D_METHOD("set_v_frames","enable"),&Particles2D::set_v_frames);
+ ClassDB::bind_method(D_METHOD("get_v_frames"),&Particles2D::get_v_frames);
- ClassDB::bind_method(_MD("set_v_frames","enable"),&Particles2D::set_v_frames);
- ClassDB::bind_method(_MD("get_v_frames"),&Particles2D::get_v_frames);
+ ClassDB::bind_method(D_METHOD("set_emission_half_extents","extents"),&Particles2D::set_emission_half_extents);
+ ClassDB::bind_method(D_METHOD("get_emission_half_extents"),&Particles2D::get_emission_half_extents);
- ClassDB::bind_method(_MD("set_emission_half_extents","extents"),&Particles2D::set_emission_half_extents);
- ClassDB::bind_method(_MD("get_emission_half_extents"),&Particles2D::get_emission_half_extents);
+ ClassDB::bind_method(D_METHOD("set_color_phases","phases"),&Particles2D::set_color_phases);
+ ClassDB::bind_method(D_METHOD("get_color_phases"),&Particles2D::get_color_phases);
- ClassDB::bind_method(_MD("set_color_phases","phases"),&Particles2D::set_color_phases);
- ClassDB::bind_method(_MD("get_color_phases"),&Particles2D::get_color_phases);
+ ClassDB::bind_method(D_METHOD("set_color_phase_color","phase","color"),&Particles2D::set_color_phase_color);
+ ClassDB::bind_method(D_METHOD("get_color_phase_color","phase"),&Particles2D::get_color_phase_color);
- ClassDB::bind_method(_MD("set_color_phase_color","phase","color"),&Particles2D::set_color_phase_color);
- ClassDB::bind_method(_MD("get_color_phase_color","phase"),&Particles2D::get_color_phase_color);
+ ClassDB::bind_method(D_METHOD("set_color_phase_pos","phase","pos"),&Particles2D::set_color_phase_pos);
+ ClassDB::bind_method(D_METHOD("get_color_phase_pos","phase"),&Particles2D::get_color_phase_pos);
- ClassDB::bind_method(_MD("set_color_phase_pos","phase","pos"),&Particles2D::set_color_phase_pos);
- ClassDB::bind_method(_MD("get_color_phase_pos","phase"),&Particles2D::get_color_phase_pos);
+ ClassDB::bind_method(D_METHOD("pre_process","time"),&Particles2D::pre_process);
+ ClassDB::bind_method(D_METHOD("reset"),&Particles2D::reset);
- ClassDB::bind_method(_MD("pre_process","time"),&Particles2D::pre_process);
- ClassDB::bind_method(_MD("reset"),&Particles2D::reset);
+ ClassDB::bind_method(D_METHOD("set_use_local_space","enable"),&Particles2D::set_use_local_space);
+ ClassDB::bind_method(D_METHOD("is_using_local_space"),&Particles2D::is_using_local_space);
- ClassDB::bind_method(_MD("set_use_local_space","enable"),&Particles2D::set_use_local_space);
- ClassDB::bind_method(_MD("is_using_local_space"),&Particles2D::is_using_local_space);
+ ClassDB::bind_method(D_METHOD("set_initial_velocity","velocity"),&Particles2D::set_initial_velocity);
+ ClassDB::bind_method(D_METHOD("get_initial_velocity"),&Particles2D::get_initial_velocity);
- ClassDB::bind_method(_MD("set_initial_velocity","velocity"),&Particles2D::set_initial_velocity);
- ClassDB::bind_method(_MD("get_initial_velocity"),&Particles2D::get_initial_velocity);
+ ClassDB::bind_method(D_METHOD("set_explosiveness","amount"),&Particles2D::set_explosiveness);
+ ClassDB::bind_method(D_METHOD("get_explosiveness"),&Particles2D::get_explosiveness);
- ClassDB::bind_method(_MD("set_explosiveness","amount"),&Particles2D::set_explosiveness);
- ClassDB::bind_method(_MD("get_explosiveness"),&Particles2D::get_explosiveness);
+ ClassDB::bind_method(D_METHOD("set_emission_points","points"),&Particles2D::set_emission_points);
+ ClassDB::bind_method(D_METHOD("get_emission_points"),&Particles2D::get_emission_points);
- ClassDB::bind_method(_MD("set_emission_points","points"),&Particles2D::set_emission_points);
- ClassDB::bind_method(_MD("get_emission_points"),&Particles2D::get_emission_points);
+ ADD_SIGNAL(MethodInfo("emission_finished"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"config/amount",PROPERTY_HINT_EXP_RANGE,"1,1024"),_SCS("set_amount"),_SCS("get_amount") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"config/lifetime",PROPERTY_HINT_EXP_RANGE,"0.1,3600,0.1"),_SCS("set_lifetime"),_SCS("get_lifetime") );
- ADD_PROPERTYNO(PropertyInfo(Variant::REAL,"config/time_scale",PROPERTY_HINT_EXP_RANGE,"0.01,128,0.01"),_SCS("set_time_scale"),_SCS("get_time_scale") );
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"config/preprocess",PROPERTY_HINT_EXP_RANGE,"0.1,3600,0.1"),_SCS("set_pre_process_time"),_SCS("get_pre_process_time") );
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"config/emit_timeout",PROPERTY_HINT_RANGE,"0,3600,0.1"),_SCS("set_emit_timeout"),_SCS("get_emit_timeout") );
- ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"config/emitting"),_SCS("set_emitting"),_SCS("is_emitting") );
- ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"config/offset"),_SCS("set_emissor_offset"),_SCS("get_emissor_offset"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"config/half_extents"),_SCS("set_emission_half_extents"),_SCS("get_emission_half_extents"));
- ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"config/local_space"),_SCS("set_use_local_space"),_SCS("is_using_local_space"));
- ADD_PROPERTYNO(PropertyInfo(Variant::REAL,"config/explosiveness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_explosiveness"),_SCS("get_explosiveness"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL,"config/flip_h"),_SCS("set_flip_h"),_SCS("is_flipped_h"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL,"config/flip_v"),_SCS("set_flip_v"),_SCS("is_flipped_v"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"config/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
- ADD_PROPERTYNO(PropertyInfo(Variant::INT,"config/h_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_h_frames"),_SCS("get_h_frames"));
- ADD_PROPERTYNO(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"config/amount",PROPERTY_HINT_EXP_RANGE,"1,1024"),"set_amount","get_amount") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"config/lifetime",PROPERTY_HINT_EXP_RANGE,"0.1,3600,0.1"),"set_lifetime","get_lifetime") ;
+ ADD_PROPERTYNO(PropertyInfo(Variant::REAL,"config/time_scale",PROPERTY_HINT_EXP_RANGE,"0.01,128,0.01"),"set_time_scale","get_time_scale") ;
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"config/preprocess",PROPERTY_HINT_EXP_RANGE,"0.1,3600,0.1"),"set_pre_process_time","get_pre_process_time") ;
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"config/emit_timeout",PROPERTY_HINT_RANGE,"0,3600,0.1"),"set_emit_timeout","get_emit_timeout") ;
+ ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"config/emitting"),"set_emitting","is_emitting") ;
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"config/process_mode",PROPERTY_HINT_ENUM, "Fixed,Idle"),"set_process_mode","get_process_mode");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"config/offset"),"set_emissor_offset","get_emissor_offset");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"config/half_extents"),"set_emission_half_extents","get_emission_half_extents");
+ ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"config/local_space"),"set_use_local_space","is_using_local_space");
+ ADD_PROPERTYNO(PropertyInfo(Variant::REAL,"config/explosiveness",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_explosiveness","get_explosiveness");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL,"config/flip_h"),"set_flip_h","is_flipped_h");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL,"config/flip_v"),"set_flip_v","is_flipped_v");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"config/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture");
+ ADD_PROPERTYNO(PropertyInfo(Variant::INT,"config/h_frames",PROPERTY_HINT_RANGE,"1,512,1"),"set_h_frames","get_h_frames");
+ ADD_PROPERTYNO(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),"set_v_frames","get_v_frames");
for(int i=0;i<PARAM_MAX;i++) {
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,_particlesframe_property_names[i],PROPERTY_HINT_RANGE,_particlesframe_property_ranges[i]),_SCS("set_param"),_SCS("get_param"),i);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,_particlesframe_property_names[i],PROPERTY_HINT_RANGE,_particlesframe_property_ranges[i]),"set_param","get_param",i);
}
for(int i=0;i<PARAM_MAX;i++) {
- ADD_PROPERTYINZ(PropertyInfo(Variant::REAL,_particlesframe_property_rnames[i],PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_randomness"),_SCS("get_randomness"),i);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::REAL,_particlesframe_property_rnames[i],PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_randomness","get_randomness",i);
}
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1", 0), _SCS("set_color_phases"), _SCS("get_color_phases"));
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1", 0), "set_color_phases", "get_color_phases");
//Backward compatibility. They will be converted to color ramp
for(int i=0;i<MAX_COLOR_PHASES;i++) {
String phase="phase_"+itos(i)+"/";
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01", 0),_SCS("set_color_phase_pos"),_SCS("get_color_phase_pos"),i );
- ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color", PROPERTY_HINT_NONE, "", 0),_SCS("set_color_phase_color"),_SCS("get_color_phase_color"),i );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01", 0),"set_color_phase_pos","get_color_phase_pos",i );
+ ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color", PROPERTY_HINT_NONE, "", 0),"set_color_phase_color","get_color_phase_color",i );
}
- ADD_PROPERTYNO(PropertyInfo(Variant::COLOR, "color/color"),_SCS("set_color"),_SCS("get_color"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"color/color_ramp",PROPERTY_HINT_RESOURCE_TYPE,"ColorRamp"),_SCS("set_color_ramp"),_SCS("get_color_ramp"));
+ ADD_PROPERTYNO(PropertyInfo(Variant::COLOR, "color/color"),"set_color","get_color");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"color/color_ramp",PROPERTY_HINT_RESOURCE_TYPE,"ColorRamp"),"set_color_ramp","get_color_ramp");
- ADD_PROPERTYNZ(PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"emission_points",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_emission_points"),_SCS("get_emission_points"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"emission_points",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_emission_points","get_emission_points");
BIND_CONSTANT( PARAM_DIRECTION );
BIND_CONSTANT( PARAM_SPREAD );
@@ -1176,6 +1187,7 @@ Particles2D::Particles2D() {
particles.resize(32);
active_count=-1;
set_emitting(true);
+ process_mode=PROCESS_IDLE;
local_space=true;
preprocess=0;
time_scale=1.0;
diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h
index 91f42c5222..c6ababe3be 100644
--- a/scene/2d/particles_2d.h
+++ b/scene/2d/particles_2d.h
@@ -111,6 +111,11 @@ public:
MAX_COLOR_PHASES=4
};
+ enum ProcessMode {
+ PROCESS_FIXED,
+ PROCESS_IDLE,
+ };
+
private:
float param[PARAM_MAX];
@@ -122,7 +127,7 @@ private:
Vector2 velocity;
float rot;
float frame;
- uint32_t seed;
+ uint64_t seed;
Particle() { active=false; seed=123465789; rot=0; frame=0;}
};
@@ -153,6 +158,8 @@ private:
Vector2 extents;
PoolVector<Vector2> emission_points;
+ ProcessMode process_mode;
+
float time;
int active_count;
@@ -162,7 +169,6 @@ private:
Color default_color;
Ref<ColorRamp> color_ramp;
- void testee(int a, int b, int c, int d, int e);
void _process_particles(float p_delta);
friend class ParticleAttractor2D;
@@ -178,6 +184,9 @@ public:
void set_emitting(bool p_emitting);
bool is_emitting() const;
+ void set_process_mode(ProcessMode p_mode);
+ ProcessMode get_process_mode() const;
+
void set_amount(int p_amount);
int get_amount() const;
@@ -254,6 +263,7 @@ public:
Particles2D();
};
+VARIANT_ENUM_CAST( Particles2D::ProcessMode );
VARIANT_ENUM_CAST( Particles2D::Parameter );
#endif // PARTICLES_FRAME_H
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index e1d1920cc5..63531ae599 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -85,11 +85,11 @@ Ref<Curve2D> Path2D::get_curve() const{
void Path2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_curve","curve:Curve2D"),&Path2D::set_curve);
- ClassDB::bind_method(_MD("get_curve:Curve2D","curve"),&Path2D::get_curve);
- ClassDB::bind_method(_MD("_curve_changed"),&Path2D::_curve_changed);
+ ClassDB::bind_method(D_METHOD("set_curve","curve:Curve2D"),&Path2D::set_curve);
+ ClassDB::bind_method(D_METHOD("get_curve:Curve2D","curve"),&Path2D::get_curve);
+ ClassDB::bind_method(D_METHOD("_curve_changed"),&Path2D::_curve_changed);
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve2D"), _SCS("set_curve"),_SCS("get_curve"));
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve2D"), "set_curve","get_curve");
}
Path2D::Path2D() {
@@ -252,26 +252,26 @@ String PathFollow2D::get_configuration_warning() const {
void PathFollow2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_offset","offset"),&PathFollow2D::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&PathFollow2D::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&PathFollow2D::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&PathFollow2D::get_offset);
- ClassDB::bind_method(_MD("set_h_offset","h_offset"),&PathFollow2D::set_h_offset);
- ClassDB::bind_method(_MD("get_h_offset"),&PathFollow2D::get_h_offset);
+ ClassDB::bind_method(D_METHOD("set_h_offset","h_offset"),&PathFollow2D::set_h_offset);
+ ClassDB::bind_method(D_METHOD("get_h_offset"),&PathFollow2D::get_h_offset);
- ClassDB::bind_method(_MD("set_v_offset","v_offset"),&PathFollow2D::set_v_offset);
- ClassDB::bind_method(_MD("get_v_offset"),&PathFollow2D::get_v_offset);
+ ClassDB::bind_method(D_METHOD("set_v_offset","v_offset"),&PathFollow2D::set_v_offset);
+ ClassDB::bind_method(D_METHOD("get_v_offset"),&PathFollow2D::get_v_offset);
- ClassDB::bind_method(_MD("set_unit_offset","unit_offset"),&PathFollow2D::set_unit_offset);
- ClassDB::bind_method(_MD("get_unit_offset"),&PathFollow2D::get_unit_offset);
+ ClassDB::bind_method(D_METHOD("set_unit_offset","unit_offset"),&PathFollow2D::set_unit_offset);
+ ClassDB::bind_method(D_METHOD("get_unit_offset"),&PathFollow2D::get_unit_offset);
- ClassDB::bind_method(_MD("set_rotate","enable"),&PathFollow2D::set_rotate);
- ClassDB::bind_method(_MD("is_rotating"),&PathFollow2D::is_rotating);
+ ClassDB::bind_method(D_METHOD("set_rotate","enable"),&PathFollow2D::set_rotate);
+ ClassDB::bind_method(D_METHOD("is_rotating"),&PathFollow2D::is_rotating);
- ClassDB::bind_method(_MD("set_cubic_interpolation","enable"),&PathFollow2D::set_cubic_interpolation);
- ClassDB::bind_method(_MD("get_cubic_interpolation"),&PathFollow2D::get_cubic_interpolation);
+ ClassDB::bind_method(D_METHOD("set_cubic_interpolation","enable"),&PathFollow2D::set_cubic_interpolation);
+ ClassDB::bind_method(D_METHOD("get_cubic_interpolation"),&PathFollow2D::get_cubic_interpolation);
- ClassDB::bind_method(_MD("set_loop","loop"),&PathFollow2D::set_loop);
- ClassDB::bind_method(_MD("has_loop"),&PathFollow2D::has_loop);
+ ClassDB::bind_method(D_METHOD("set_loop","loop"),&PathFollow2D::set_loop);
+ ClassDB::bind_method(D_METHOD("has_loop"),&PathFollow2D::has_loop);
}
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 96d90a1de6..0ffaf81e3d 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -81,34 +81,34 @@ uint32_t PhysicsBody2D::_get_layers() const{
void PhysicsBody2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_collision_layer","mask"),&PhysicsBody2D::set_collision_layer);
- ClassDB::bind_method(_MD("get_collision_layer"),&PhysicsBody2D::get_collision_layer);
- ClassDB::bind_method(_MD("set_collision_mask","mask"),&PhysicsBody2D::set_collision_mask);
- ClassDB::bind_method(_MD("get_collision_mask"),&PhysicsBody2D::get_collision_mask);
+ ClassDB::bind_method(D_METHOD("set_collision_layer","mask"),&PhysicsBody2D::set_collision_layer);
+ ClassDB::bind_method(D_METHOD("get_collision_layer"),&PhysicsBody2D::get_collision_layer);
+ ClassDB::bind_method(D_METHOD("set_collision_mask","mask"),&PhysicsBody2D::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"),&PhysicsBody2D::get_collision_mask);
- ClassDB::bind_method(_MD("set_collision_mask_bit","bit","value"),&PhysicsBody2D::set_collision_mask_bit);
- ClassDB::bind_method(_MD("get_collision_mask_bit","bit"),&PhysicsBody2D::get_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit","bit","value"),&PhysicsBody2D::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit","bit"),&PhysicsBody2D::get_collision_mask_bit);
- ClassDB::bind_method(_MD("set_collision_layer_bit","bit","value"),&PhysicsBody2D::set_collision_layer_bit);
- ClassDB::bind_method(_MD("get_collision_layer_bit","bit"),&PhysicsBody2D::get_collision_layer_bit);
+ ClassDB::bind_method(D_METHOD("set_collision_layer_bit","bit","value"),&PhysicsBody2D::set_collision_layer_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_layer_bit","bit"),&PhysicsBody2D::get_collision_layer_bit);
- ClassDB::bind_method(_MD("_set_layers","mask"),&PhysicsBody2D::_set_layers);
- ClassDB::bind_method(_MD("_get_layers"),&PhysicsBody2D::_get_layers);
- ClassDB::bind_method(_MD("set_one_way_collision_direction","dir"),&PhysicsBody2D::set_one_way_collision_direction);
- ClassDB::bind_method(_MD("get_one_way_collision_direction"),&PhysicsBody2D::get_one_way_collision_direction);
- ClassDB::bind_method(_MD("set_one_way_collision_max_depth","depth"),&PhysicsBody2D::set_one_way_collision_max_depth);
- ClassDB::bind_method(_MD("get_one_way_collision_max_depth"),&PhysicsBody2D::get_one_way_collision_max_depth);
- ClassDB::bind_method(_MD("add_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::add_collision_exception_with);
- ClassDB::bind_method(_MD("remove_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::remove_collision_exception_with);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_LAYERS_2D_PHYSICS,"",0),_SCS("_set_layers"),_SCS("_get_layers")); //for backwards compat
+ ClassDB::bind_method(D_METHOD("_set_layers","mask"),&PhysicsBody2D::_set_layers);
+ ClassDB::bind_method(D_METHOD("_get_layers"),&PhysicsBody2D::_get_layers);
+ ClassDB::bind_method(D_METHOD("set_one_way_collision_direction","dir"),&PhysicsBody2D::set_one_way_collision_direction);
+ ClassDB::bind_method(D_METHOD("get_one_way_collision_direction"),&PhysicsBody2D::get_one_way_collision_direction);
+ ClassDB::bind_method(D_METHOD("set_one_way_collision_max_depth","depth"),&PhysicsBody2D::set_one_way_collision_max_depth);
+ ClassDB::bind_method(D_METHOD("get_one_way_collision_max_depth"),&PhysicsBody2D::get_one_way_collision_max_depth);
+ ClassDB::bind_method(D_METHOD("add_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::add_collision_exception_with);
+ ClassDB::bind_method(D_METHOD("remove_collision_exception_with","body:PhysicsBody2D"),&PhysicsBody2D::remove_collision_exception_with);
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"layers",PROPERTY_HINT_LAYERS_2D_PHYSICS,"",0),"_set_layers","_get_layers"); //for backwards compat
ADD_GROUP("Collision","collision_");
- ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_layer",PROPERTY_HINT_LAYERS_2D_PHYSICS),_SCS("set_collision_layer"),_SCS("get_collision_layer"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_layer",PROPERTY_HINT_LAYERS_2D_PHYSICS),"set_collision_layer","get_collision_layer");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),"set_collision_mask","get_collision_mask");
ADD_GROUP("","");
- ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"one_way_collision/direction"),_SCS("set_one_way_collision_direction"),_SCS("get_one_way_collision_direction"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"one_way_collision/max_depth"),_SCS("set_one_way_collision_max_depth"),_SCS("get_one_way_collision_max_depth"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"one_way_collision/direction"),"set_one_way_collision_direction","get_one_way_collision_direction");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"one_way_collision/max_depth"),"set_one_way_collision_max_depth","get_one_way_collision_max_depth");
}
void PhysicsBody2D::set_collision_layer(uint32_t p_mask) {
@@ -271,20 +271,20 @@ real_t StaticBody2D::get_bounce() const{
void StaticBody2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_constant_linear_velocity","vel"),&StaticBody2D::set_constant_linear_velocity);
- ClassDB::bind_method(_MD("set_constant_angular_velocity","vel"),&StaticBody2D::set_constant_angular_velocity);
- ClassDB::bind_method(_MD("get_constant_linear_velocity"),&StaticBody2D::get_constant_linear_velocity);
- ClassDB::bind_method(_MD("get_constant_angular_velocity"),&StaticBody2D::get_constant_angular_velocity);
- ClassDB::bind_method(_MD("set_friction","friction"),&StaticBody2D::set_friction);
- ClassDB::bind_method(_MD("get_friction"),&StaticBody2D::get_friction);
+ ClassDB::bind_method(D_METHOD("set_constant_linear_velocity","vel"),&StaticBody2D::set_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_constant_angular_velocity","vel"),&StaticBody2D::set_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"),&StaticBody2D::get_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"),&StaticBody2D::get_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_friction","friction"),&StaticBody2D::set_friction);
+ ClassDB::bind_method(D_METHOD("get_friction"),&StaticBody2D::get_friction);
- ClassDB::bind_method(_MD("set_bounce","bounce"),&StaticBody2D::set_bounce);
- ClassDB::bind_method(_MD("get_bounce"),&StaticBody2D::get_bounce);
+ ClassDB::bind_method(D_METHOD("set_bounce","bounce"),&StaticBody2D::set_bounce);
+ ClassDB::bind_method(D_METHOD("get_bounce"),&StaticBody2D::get_bounce);
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"constant_linear_velocity"),_SCS("set_constant_linear_velocity"),_SCS("get_constant_linear_velocity"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"constant_angular_velocity"),_SCS("set_constant_angular_velocity"),_SCS("get_constant_angular_velocity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"constant_linear_velocity"),"set_constant_linear_velocity","get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"constant_angular_velocity"),"set_constant_angular_velocity","get_constant_angular_velocity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_friction","get_friction");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_bounce","get_bounce");
}
StaticBody2D::StaticBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_STATIC) {
@@ -882,96 +882,96 @@ bool RigidBody2D::is_contact_monitor_enabled() const {
void RigidBody2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_mode","mode"),&RigidBody2D::set_mode);
- ClassDB::bind_method(_MD("get_mode"),&RigidBody2D::get_mode);
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&RigidBody2D::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&RigidBody2D::get_mode);
- ClassDB::bind_method(_MD("set_mass","mass"),&RigidBody2D::set_mass);
- ClassDB::bind_method(_MD("get_mass"),&RigidBody2D::get_mass);
+ ClassDB::bind_method(D_METHOD("set_mass","mass"),&RigidBody2D::set_mass);
+ ClassDB::bind_method(D_METHOD("get_mass"),&RigidBody2D::get_mass);
- ClassDB::bind_method(_MD("get_inertia"),&RigidBody2D::get_inertia);
- ClassDB::bind_method(_MD("set_inertia","inertia"),&RigidBody2D::set_inertia);
+ ClassDB::bind_method(D_METHOD("get_inertia"),&RigidBody2D::get_inertia);
+ ClassDB::bind_method(D_METHOD("set_inertia","inertia"),&RigidBody2D::set_inertia);
- ClassDB::bind_method(_MD("set_weight","weight"),&RigidBody2D::set_weight);
- ClassDB::bind_method(_MD("get_weight"),&RigidBody2D::get_weight);
+ ClassDB::bind_method(D_METHOD("set_weight","weight"),&RigidBody2D::set_weight);
+ ClassDB::bind_method(D_METHOD("get_weight"),&RigidBody2D::get_weight);
- ClassDB::bind_method(_MD("set_friction","friction"),&RigidBody2D::set_friction);
- ClassDB::bind_method(_MD("get_friction"),&RigidBody2D::get_friction);
+ ClassDB::bind_method(D_METHOD("set_friction","friction"),&RigidBody2D::set_friction);
+ ClassDB::bind_method(D_METHOD("get_friction"),&RigidBody2D::get_friction);
- ClassDB::bind_method(_MD("set_bounce","bounce"),&RigidBody2D::set_bounce);
- ClassDB::bind_method(_MD("get_bounce"),&RigidBody2D::get_bounce);
+ ClassDB::bind_method(D_METHOD("set_bounce","bounce"),&RigidBody2D::set_bounce);
+ ClassDB::bind_method(D_METHOD("get_bounce"),&RigidBody2D::get_bounce);
- ClassDB::bind_method(_MD("set_gravity_scale","gravity_scale"),&RigidBody2D::set_gravity_scale);
- ClassDB::bind_method(_MD("get_gravity_scale"),&RigidBody2D::get_gravity_scale);
+ ClassDB::bind_method(D_METHOD("set_gravity_scale","gravity_scale"),&RigidBody2D::set_gravity_scale);
+ ClassDB::bind_method(D_METHOD("get_gravity_scale"),&RigidBody2D::get_gravity_scale);
- ClassDB::bind_method(_MD("set_linear_damp","linear_damp"),&RigidBody2D::set_linear_damp);
- ClassDB::bind_method(_MD("get_linear_damp"),&RigidBody2D::get_linear_damp);
+ ClassDB::bind_method(D_METHOD("set_linear_damp","linear_damp"),&RigidBody2D::set_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_linear_damp"),&RigidBody2D::get_linear_damp);
- ClassDB::bind_method(_MD("set_angular_damp","angular_damp"),&RigidBody2D::set_angular_damp);
- ClassDB::bind_method(_MD("get_angular_damp"),&RigidBody2D::get_angular_damp);
+ ClassDB::bind_method(D_METHOD("set_angular_damp","angular_damp"),&RigidBody2D::set_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_angular_damp"),&RigidBody2D::get_angular_damp);
- ClassDB::bind_method(_MD("set_linear_velocity","linear_velocity"),&RigidBody2D::set_linear_velocity);
- ClassDB::bind_method(_MD("get_linear_velocity"),&RigidBody2D::get_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_linear_velocity","linear_velocity"),&RigidBody2D::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"),&RigidBody2D::get_linear_velocity);
- ClassDB::bind_method(_MD("set_angular_velocity","angular_velocity"),&RigidBody2D::set_angular_velocity);
- ClassDB::bind_method(_MD("get_angular_velocity"),&RigidBody2D::get_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_angular_velocity","angular_velocity"),&RigidBody2D::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"),&RigidBody2D::get_angular_velocity);
- ClassDB::bind_method(_MD("set_max_contacts_reported","amount"),&RigidBody2D::set_max_contacts_reported);
- ClassDB::bind_method(_MD("get_max_contacts_reported"),&RigidBody2D::get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("set_max_contacts_reported","amount"),&RigidBody2D::set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_max_contacts_reported"),&RigidBody2D::get_max_contacts_reported);
- ClassDB::bind_method(_MD("set_use_custom_integrator","enable"),&RigidBody2D::set_use_custom_integrator);
- ClassDB::bind_method(_MD("is_using_custom_integrator"),&RigidBody2D::is_using_custom_integrator);
+ ClassDB::bind_method(D_METHOD("set_use_custom_integrator","enable"),&RigidBody2D::set_use_custom_integrator);
+ ClassDB::bind_method(D_METHOD("is_using_custom_integrator"),&RigidBody2D::is_using_custom_integrator);
- ClassDB::bind_method(_MD("set_contact_monitor","enabled"),&RigidBody2D::set_contact_monitor);
- ClassDB::bind_method(_MD("is_contact_monitor_enabled"),&RigidBody2D::is_contact_monitor_enabled);
+ ClassDB::bind_method(D_METHOD("set_contact_monitor","enabled"),&RigidBody2D::set_contact_monitor);
+ ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"),&RigidBody2D::is_contact_monitor_enabled);
- ClassDB::bind_method(_MD("set_continuous_collision_detection_mode","mode"),&RigidBody2D::set_continuous_collision_detection_mode);
- ClassDB::bind_method(_MD("get_continuous_collision_detection_mode"),&RigidBody2D::get_continuous_collision_detection_mode);
+ ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode","mode"),&RigidBody2D::set_continuous_collision_detection_mode);
+ ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"),&RigidBody2D::get_continuous_collision_detection_mode);
- ClassDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody2D::set_axis_velocity);
- ClassDB::bind_method(_MD("apply_impulse","offset","impulse"),&RigidBody2D::apply_impulse);
+ ClassDB::bind_method(D_METHOD("set_axis_velocity","axis_velocity"),&RigidBody2D::set_axis_velocity);
+ ClassDB::bind_method(D_METHOD("apply_impulse","offset","impulse"),&RigidBody2D::apply_impulse);
- ClassDB::bind_method(_MD("set_applied_force","force"),&RigidBody2D::set_applied_force);
- ClassDB::bind_method(_MD("get_applied_force"),&RigidBody2D::get_applied_force);
+ ClassDB::bind_method(D_METHOD("set_applied_force","force"),&RigidBody2D::set_applied_force);
+ ClassDB::bind_method(D_METHOD("get_applied_force"),&RigidBody2D::get_applied_force);
- ClassDB::bind_method(_MD("set_applied_torque","torque"),&RigidBody2D::set_applied_torque);
- ClassDB::bind_method(_MD("get_applied_torque"),&RigidBody2D::get_applied_torque);
+ ClassDB::bind_method(D_METHOD("set_applied_torque","torque"),&RigidBody2D::set_applied_torque);
+ ClassDB::bind_method(D_METHOD("get_applied_torque"),&RigidBody2D::get_applied_torque);
- ClassDB::bind_method(_MD("add_force","offset","force"),&RigidBody2D::add_force);
+ ClassDB::bind_method(D_METHOD("add_force","offset","force"),&RigidBody2D::add_force);
- ClassDB::bind_method(_MD("set_sleeping","sleeping"),&RigidBody2D::set_sleeping);
- ClassDB::bind_method(_MD("is_sleeping"),&RigidBody2D::is_sleeping);
+ ClassDB::bind_method(D_METHOD("set_sleeping","sleeping"),&RigidBody2D::set_sleeping);
+ ClassDB::bind_method(D_METHOD("is_sleeping"),&RigidBody2D::is_sleeping);
- ClassDB::bind_method(_MD("set_can_sleep","able_to_sleep"),&RigidBody2D::set_can_sleep);
- ClassDB::bind_method(_MD("is_able_to_sleep"),&RigidBody2D::is_able_to_sleep);
+ ClassDB::bind_method(D_METHOD("set_can_sleep","able_to_sleep"),&RigidBody2D::set_can_sleep);
+ ClassDB::bind_method(D_METHOD("is_able_to_sleep"),&RigidBody2D::is_able_to_sleep);
- ClassDB::bind_method(_MD("test_motion","motion","margin","result:Physics2DTestMotionResult"),&RigidBody2D::_test_motion,DEFVAL(0.08),DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("test_motion","motion","margin","result:Physics2DTestMotionResult"),&RigidBody2D::_test_motion,DEFVAL(0.08),DEFVAL(Variant()));
- ClassDB::bind_method(_MD("_direct_state_changed"),&RigidBody2D::_direct_state_changed);
- ClassDB::bind_method(_MD("_body_enter_tree"),&RigidBody2D::_body_enter_tree);
- ClassDB::bind_method(_MD("_body_exit_tree"),&RigidBody2D::_body_exit_tree);
+ ClassDB::bind_method(D_METHOD("_direct_state_changed"),&RigidBody2D::_direct_state_changed);
+ ClassDB::bind_method(D_METHOD("_body_enter_tree"),&RigidBody2D::_body_enter_tree);
+ ClassDB::bind_method(D_METHOD("_body_exit_tree"),&RigidBody2D::_body_exit_tree);
- ClassDB::bind_method(_MD("get_colliding_bodies"),&RigidBody2D::get_colliding_bodies);
+ ClassDB::bind_method(D_METHOD("get_colliding_bodies"),&RigidBody2D::get_colliding_bodies);
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:Physics2DDirectBodyState")));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),_SCS("set_gravity_scale"),_SCS("get_gravity_scale"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"continuous_cd",PROPERTY_HINT_ENUM,"Disabled,Cast Ray,Cast Shape"),_SCS("set_continuous_collision_detection_mode"),_SCS("get_continuous_collision_detection_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),_SCS("set_contact_monitor"),_SCS("is_contact_monitor_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"sleeping"),_SCS("set_sleeping"),_SCS("is_sleeping"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"can_sleep"),_SCS("set_can_sleep"),_SCS("is_able_to_sleep"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),"set_mode","get_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),"set_mass","get_mass");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),"set_weight","get_weight");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_friction","get_friction");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_bounce","get_bounce");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),"set_gravity_scale","get_gravity_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),"set_use_custom_integrator","is_using_custom_integrator");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"continuous_cd",PROPERTY_HINT_ENUM,"Disabled,Cast Ray,Cast Shape"),"set_continuous_collision_detection_mode","get_continuous_collision_detection_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),"set_max_contacts_reported","get_max_contacts_reported");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),"set_contact_monitor","is_contact_monitor_enabled");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"sleeping"),"set_sleeping","is_sleeping");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"can_sleep"),"set_can_sleep","is_able_to_sleep");
ADD_GROUP("Linear","linear_");
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"linear_velocity"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"linear_velocity"),"set_linear_velocity","get_linear_velocity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),"set_linear_damp","get_linear_damp");
ADD_GROUP("Angular","angular_");
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_velocity"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_velocity"),"set_angular_velocity","get_angular_velocity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),"set_angular_damp","get_angular_damp");
ADD_SIGNAL( MethodInfo("body_shape_entered",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
ADD_SIGNAL( MethodInfo("body_shape_exited",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
@@ -1388,31 +1388,31 @@ float KinematicBody2D::get_collision_margin() const{
void KinematicBody2D::_bind_methods() {
- ClassDB::bind_method(_MD("move","rel_vec"),&KinematicBody2D::move);
- ClassDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to);
- ClassDB::bind_method(_MD("move_and_slide","linear_velocity","floor_normal","slope_stop_min_velocity","max_bounces"),&KinematicBody2D::move_and_slide,DEFVAL(Vector2(0,0)),DEFVAL(5),DEFVAL(4));
+ ClassDB::bind_method(D_METHOD("move","rel_vec"),&KinematicBody2D::move);
+ ClassDB::bind_method(D_METHOD("move_to","position"),&KinematicBody2D::move_to);
+ ClassDB::bind_method(D_METHOD("move_and_slide","linear_velocity","floor_normal","slope_stop_min_velocity","max_bounces"),&KinematicBody2D::move_and_slide,DEFVAL(Vector2(0,0)),DEFVAL(5),DEFVAL(4));
- ClassDB::bind_method(_MD("test_move","from","rel_vec"),&KinematicBody2D::test_move);
- ClassDB::bind_method(_MD("get_travel"),&KinematicBody2D::get_travel);
- ClassDB::bind_method(_MD("revert_motion"),&KinematicBody2D::revert_motion);
+ ClassDB::bind_method(D_METHOD("test_move","from","rel_vec"),&KinematicBody2D::test_move);
+ ClassDB::bind_method(D_METHOD("get_travel"),&KinematicBody2D::get_travel);
+ ClassDB::bind_method(D_METHOD("revert_motion"),&KinematicBody2D::revert_motion);
- ClassDB::bind_method(_MD("is_colliding"),&KinematicBody2D::is_colliding);
+ ClassDB::bind_method(D_METHOD("is_colliding"),&KinematicBody2D::is_colliding);
- ClassDB::bind_method(_MD("get_collision_pos"),&KinematicBody2D::get_collision_pos);
- ClassDB::bind_method(_MD("get_collision_normal"),&KinematicBody2D::get_collision_normal);
- ClassDB::bind_method(_MD("get_collider_velocity"),&KinematicBody2D::get_collider_velocity);
- ClassDB::bind_method(_MD("get_collider:Variant"),&KinematicBody2D::_get_collider);
- ClassDB::bind_method(_MD("get_collider_shape"),&KinematicBody2D::get_collider_shape);
- ClassDB::bind_method(_MD("get_collider_metadata:Variant"),&KinematicBody2D::get_collider_metadata);
- ClassDB::bind_method(_MD("get_move_and_slide_colliders"),&KinematicBody2D::get_move_and_slide_colliders);
- ClassDB::bind_method(_MD("is_move_and_slide_on_floor"),&KinematicBody2D::is_move_and_slide_on_floor);
- ClassDB::bind_method(_MD("is_move_and_slide_on_ceiling"),&KinematicBody2D::is_move_and_slide_on_ceiling);
- ClassDB::bind_method(_MD("is_move_and_slide_on_wall"),&KinematicBody2D::is_move_and_slide_on_wall);
+ ClassDB::bind_method(D_METHOD("get_collision_pos"),&KinematicBody2D::get_collision_pos);
+ ClassDB::bind_method(D_METHOD("get_collision_normal"),&KinematicBody2D::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collider_velocity"),&KinematicBody2D::get_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collider:Variant"),&KinematicBody2D::_get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"),&KinematicBody2D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collider_metadata:Variant"),&KinematicBody2D::get_collider_metadata);
+ ClassDB::bind_method(D_METHOD("get_move_and_slide_colliders"),&KinematicBody2D::get_move_and_slide_colliders);
+ ClassDB::bind_method(D_METHOD("is_move_and_slide_on_floor"),&KinematicBody2D::is_move_and_slide_on_floor);
+ ClassDB::bind_method(D_METHOD("is_move_and_slide_on_ceiling"),&KinematicBody2D::is_move_and_slide_on_ceiling);
+ ClassDB::bind_method(D_METHOD("is_move_and_slide_on_wall"),&KinematicBody2D::is_move_and_slide_on_wall);
- ClassDB::bind_method(_MD("set_collision_margin","pixels"),&KinematicBody2D::set_collision_margin);
- ClassDB::bind_method(_MD("get_collision_margin","pixels"),&KinematicBody2D::get_collision_margin);
+ ClassDB::bind_method(D_METHOD("set_collision_margin","pixels"),&KinematicBody2D::set_collision_margin);
+ ClassDB::bind_method(D_METHOD("get_collision_margin","pixels"),&KinematicBody2D::get_collision_margin);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.001,256,0.001"),_SCS("set_collision_margin"),_SCS("get_collision_margin"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.001,256,0.001"),"set_collision_margin","get_collision_margin");
}
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 30e22a8437..ec6729844b 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -333,60 +333,60 @@ Vector2 Polygon2D::get_offset() const {
void Polygon2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_polygon","polygon"),&Polygon2D::set_polygon);
- ClassDB::bind_method(_MD("get_polygon"),&Polygon2D::get_polygon);
+ ClassDB::bind_method(D_METHOD("set_polygon","polygon"),&Polygon2D::set_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon"),&Polygon2D::get_polygon);
- ClassDB::bind_method(_MD("set_uv","uv"),&Polygon2D::set_uv);
- ClassDB::bind_method(_MD("get_uv"),&Polygon2D::get_uv);
+ ClassDB::bind_method(D_METHOD("set_uv","uv"),&Polygon2D::set_uv);
+ ClassDB::bind_method(D_METHOD("get_uv"),&Polygon2D::get_uv);
- ClassDB::bind_method(_MD("set_color","color"),&Polygon2D::set_color);
- ClassDB::bind_method(_MD("get_color"),&Polygon2D::get_color);
+ ClassDB::bind_method(D_METHOD("set_color","color"),&Polygon2D::set_color);
+ ClassDB::bind_method(D_METHOD("get_color"),&Polygon2D::get_color);
- ClassDB::bind_method(_MD("set_vertex_colors","vertex_colors"),&Polygon2D::set_vertex_colors);
- ClassDB::bind_method(_MD("get_vertex_colors"),&Polygon2D::get_vertex_colors);
+ ClassDB::bind_method(D_METHOD("set_vertex_colors","vertex_colors"),&Polygon2D::set_vertex_colors);
+ ClassDB::bind_method(D_METHOD("get_vertex_colors"),&Polygon2D::get_vertex_colors);
- ClassDB::bind_method(_MD("set_texture","texture"),&Polygon2D::set_texture);
- ClassDB::bind_method(_MD("get_texture"),&Polygon2D::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture","texture"),&Polygon2D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"),&Polygon2D::get_texture);
- ClassDB::bind_method(_MD("set_texture_offset","texture_offset"),&Polygon2D::set_texture_offset);
- ClassDB::bind_method(_MD("get_texture_offset"),&Polygon2D::get_texture_offset);
+ ClassDB::bind_method(D_METHOD("set_texture_offset","texture_offset"),&Polygon2D::set_texture_offset);
+ ClassDB::bind_method(D_METHOD("get_texture_offset"),&Polygon2D::get_texture_offset);
- ClassDB::bind_method(_MD("set_texture_rotation","texture_rotation"),&Polygon2D::set_texture_rotation);
- ClassDB::bind_method(_MD("get_texture_rotation"),&Polygon2D::get_texture_rotation);
+ ClassDB::bind_method(D_METHOD("set_texture_rotation","texture_rotation"),&Polygon2D::set_texture_rotation);
+ ClassDB::bind_method(D_METHOD("get_texture_rotation"),&Polygon2D::get_texture_rotation);
- ClassDB::bind_method(_MD("_set_texture_rotationd","texture_rotation"),&Polygon2D::_set_texture_rotationd);
- ClassDB::bind_method(_MD("_get_texture_rotationd"),&Polygon2D::_get_texture_rotationd);
+ ClassDB::bind_method(D_METHOD("_set_texture_rotationd","texture_rotation"),&Polygon2D::_set_texture_rotationd);
+ ClassDB::bind_method(D_METHOD("_get_texture_rotationd"),&Polygon2D::_get_texture_rotationd);
- ClassDB::bind_method(_MD("set_texture_scale","texture_scale"),&Polygon2D::set_texture_scale);
- ClassDB::bind_method(_MD("get_texture_scale"),&Polygon2D::get_texture_scale);
+ ClassDB::bind_method(D_METHOD("set_texture_scale","texture_scale"),&Polygon2D::set_texture_scale);
+ ClassDB::bind_method(D_METHOD("get_texture_scale"),&Polygon2D::get_texture_scale);
- ClassDB::bind_method(_MD("set_invert","invert"),&Polygon2D::set_invert);
- ClassDB::bind_method(_MD("get_invert"),&Polygon2D::get_invert);
+ ClassDB::bind_method(D_METHOD("set_invert","invert"),&Polygon2D::set_invert);
+ ClassDB::bind_method(D_METHOD("get_invert"),&Polygon2D::get_invert);
- ClassDB::bind_method(_MD("set_invert_border","invert_border"),&Polygon2D::set_invert_border);
- ClassDB::bind_method(_MD("get_invert_border"),&Polygon2D::get_invert_border);
+ ClassDB::bind_method(D_METHOD("set_invert_border","invert_border"),&Polygon2D::set_invert_border);
+ ClassDB::bind_method(D_METHOD("get_invert_border"),&Polygon2D::get_invert_border);
- ClassDB::bind_method(_MD("set_offset","offset"),&Polygon2D::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&Polygon2D::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&Polygon2D::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&Polygon2D::get_offset);
- ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
- ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"uv"),_SCS("set_uv"),_SCS("get_uv"));
- ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
- ADD_PROPERTY( PropertyInfo(Variant::POOL_COLOR_ARRAY,"vertex_colors"),_SCS("set_vertex_colors"),_SCS("get_vertex_colors"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset"));
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),"set_polygon","get_polygon");
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"uv"),"set_uv","get_uv");
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),"set_color","get_color");
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_COLOR_ARRAY,"vertex_colors"),"set_vertex_colors","get_vertex_colors");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),"set_offset","get_offset");
ADD_GROUP("Texture","");
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture");
ADD_GROUP("Texture","texture_");
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_scale"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"texture_rotation",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_texture_rotationd"),_SCS("_get_texture_rotationd"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_offset"),"set_texture_offset","get_texture_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_scale"),"set_texture_scale","get_texture_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"texture_rotation",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),"_set_texture_rotationd","_get_texture_rotationd");
ADD_GROUP("Invert","invert_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"invert_enable"),_SCS("set_invert"),_SCS("get_invert"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"invert_border",PROPERTY_HINT_RANGE,"0.1,16384,0.1"),_SCS("set_invert_border"),_SCS("get_invert_border"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"invert_enable"),"set_invert","get_invert");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"invert_border",PROPERTY_HINT_RANGE,"0.1,16384,0.1"),"set_invert_border","get_invert_border");
}
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 14dfc10d9f..72247811dc 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -263,42 +263,42 @@ void RayCast2D::clear_exceptions(){
void RayCast2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_enabled","enabled"),&RayCast2D::set_enabled);
- ClassDB::bind_method(_MD("is_enabled"),&RayCast2D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled","enabled"),&RayCast2D::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"),&RayCast2D::is_enabled);
- ClassDB::bind_method(_MD("set_cast_to","local_point"),&RayCast2D::set_cast_to);
- ClassDB::bind_method(_MD("get_cast_to"),&RayCast2D::get_cast_to);
+ ClassDB::bind_method(D_METHOD("set_cast_to","local_point"),&RayCast2D::set_cast_to);
+ ClassDB::bind_method(D_METHOD("get_cast_to"),&RayCast2D::get_cast_to);
- ClassDB::bind_method(_MD("is_colliding"),&RayCast2D::is_colliding);
- ClassDB::bind_method(_MD("force_raycast_update"),&RayCast2D::force_raycast_update);
+ ClassDB::bind_method(D_METHOD("is_colliding"),&RayCast2D::is_colliding);
+ ClassDB::bind_method(D_METHOD("force_raycast_update"),&RayCast2D::force_raycast_update);
- ClassDB::bind_method(_MD("get_collider"),&RayCast2D::get_collider);
- ClassDB::bind_method(_MD("get_collider_shape"),&RayCast2D::get_collider_shape);
- ClassDB::bind_method(_MD("get_collision_point"),&RayCast2D::get_collision_point);
- ClassDB::bind_method(_MD("get_collision_normal"),&RayCast2D::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collider"),&RayCast2D::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"),&RayCast2D::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_point"),&RayCast2D::get_collision_point);
+ ClassDB::bind_method(D_METHOD("get_collision_normal"),&RayCast2D::get_collision_normal);
- ClassDB::bind_method(_MD("add_exception_rid","rid"),&RayCast2D::add_exception_rid);
- ClassDB::bind_method(_MD("add_exception","node"),&RayCast2D::add_exception);
+ ClassDB::bind_method(D_METHOD("add_exception_rid","rid"),&RayCast2D::add_exception_rid);
+ ClassDB::bind_method(D_METHOD("add_exception","node"),&RayCast2D::add_exception);
- ClassDB::bind_method(_MD("remove_exception_rid","rid"),&RayCast2D::remove_exception_rid);
- ClassDB::bind_method(_MD("remove_exception","node"),&RayCast2D::remove_exception);
+ ClassDB::bind_method(D_METHOD("remove_exception_rid","rid"),&RayCast2D::remove_exception_rid);
+ ClassDB::bind_method(D_METHOD("remove_exception","node"),&RayCast2D::remove_exception);
- ClassDB::bind_method(_MD("clear_exceptions"),&RayCast2D::clear_exceptions);
+ ClassDB::bind_method(D_METHOD("clear_exceptions"),&RayCast2D::clear_exceptions);
- ClassDB::bind_method(_MD("set_layer_mask","mask"),&RayCast2D::set_layer_mask);
- ClassDB::bind_method(_MD("get_layer_mask"),&RayCast2D::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","mask"),&RayCast2D::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&RayCast2D::get_layer_mask);
- ClassDB::bind_method(_MD("set_type_mask","mask"),&RayCast2D::set_type_mask);
- ClassDB::bind_method(_MD("get_type_mask"),&RayCast2D::get_type_mask);
+ ClassDB::bind_method(D_METHOD("set_type_mask","mask"),&RayCast2D::set_type_mask);
+ ClassDB::bind_method(D_METHOD("get_type_mask"),&RayCast2D::get_type_mask);
- ClassDB::bind_method(_MD("set_exclude_parent_body","mask"),&RayCast2D::set_exclude_parent_body);
- ClassDB::bind_method(_MD("get_exclude_parent_body"),&RayCast2D::get_exclude_parent_body);
+ ClassDB::bind_method(D_METHOD("set_exclude_parent_body","mask"),&RayCast2D::set_exclude_parent_body);
+ ClassDB::bind_method(D_METHOD("get_exclude_parent_body"),&RayCast2D::get_exclude_parent_body);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"exclude_parent"),_SCS("set_exclude_parent_body"),_SCS("get_exclude_parent_body"));
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"layer_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),_SCS("set_layer_mask"),_SCS("get_layer_mask"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"type_mask",PROPERTY_HINT_FLAGS,"Static,Kinematic,Rigid,Character,Area"),_SCS("set_type_mask"),_SCS("get_type_mask"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),"set_enabled","is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"exclude_parent"),"set_exclude_parent_body","get_exclude_parent_body");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"cast_to"),"set_cast_to","get_cast_to");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"layer_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),"set_layer_mask","get_layer_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"type_mask",PROPERTY_HINT_FLAGS,"Static,Kinematic,Rigid,Character,Area"),"set_type_mask","get_type_mask");
}
RayCast2D::RayCast2D() {
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index 77f1a9d500..e1f360c0c1 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -118,10 +118,10 @@ String RemoteTransform2D::get_configuration_warning() const {
void RemoteTransform2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_remote_node","path"),&RemoteTransform2D::set_remote_node);
- ClassDB::bind_method(_MD("get_remote_node"),&RemoteTransform2D::get_remote_node);
+ ClassDB::bind_method(D_METHOD("set_remote_node","path"),&RemoteTransform2D::set_remote_node);
+ ClassDB::bind_method(D_METHOD("get_remote_node"),&RemoteTransform2D::get_remote_node);
- ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"remote_path"),_SCS("set_remote_node"),_SCS("get_remote_node"));
+ ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"remote_path"),"set_remote_node","get_remote_node");
}
RemoteTransform2D::RemoteTransform2D() {
diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp
index 20db63b66f..4b607e9261 100644
--- a/scene/2d/screen_button.cpp
+++ b/scene/2d/screen_button.cpp
@@ -63,6 +63,38 @@ Ref<BitMap> TouchScreenButton::get_bitmask() const{
return bitmask;
}
+void TouchScreenButton::set_shape(const Ref<Shape2D>& p_shape){
+
+ shape=p_shape;
+
+ if (!is_inside_tree())
+ return;
+ if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint())
+ return;
+ update();
+}
+
+Ref<Shape2D> TouchScreenButton::get_shape() const{
+
+ return shape;
+}
+
+void TouchScreenButton::set_shape_centered(bool p_shape_centered) {
+
+ shape_centered=p_shape_centered;
+
+ if (!is_inside_tree())
+ return;
+ if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint())
+ return;
+ update();
+}
+
+bool TouchScreenButton::is_shape_centered() const {
+
+ return shape_centered;
+}
+
void TouchScreenButton::_notification(int p_what) {
switch(p_what) {
@@ -86,6 +118,15 @@ void TouchScreenButton::_notification(int p_what) {
draw_texture(texture,Point2());
}
+ if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint())
+ return;
+ if (shape.is_valid()) {
+ Color draw_col=get_tree()->get_debug_collisions_color();
+ Vector2 pos=shape_centered ? get_item_rect().size*0.5f : Vector2();
+ draw_set_transform_matrix(get_canvas_transform().translated(pos));
+ shape->draw(get_canvas_item(),draw_col);
+ }
+
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -104,8 +145,12 @@ void TouchScreenButton::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
if (is_pressed())
- Input::get_singleton()->action_release(action);
+ _release(true);
} break;
+ case NOTIFICATION_PAUSED: {
+ // So the button can be pressed again even though the release gets unhandled because of coming during pause
+ allow_repress=true;
+ }
}
}
@@ -143,22 +188,7 @@ void TouchScreenButton::_input(const InputEvent& p_event) {
if (p_event.type==InputEvent::SCREEN_TOUCH && !p_event.screen_touch.pressed && finger_pressed==p_event.screen_touch.index) {
- emit_signal("released");
-
- if (action_id!=-1) {
-
- Input::get_singleton()->action_release(action);
- InputEvent ie;
- ie.type=InputEvent::ACTION;
- ie.ID=0;
- ie.action.action=action_id;
- ie.action.pressed=false;
- get_tree()->input_event(ie);
- }
- finger_pressed=-1;
-
- update();
-
+ _release();
}
if ((p_event.type==InputEvent::SCREEN_TOUCH && p_event.screen_touch.pressed)|| p_event.type==InputEvent::SCREEN_DRAG) {
@@ -184,44 +214,12 @@ void TouchScreenButton::_input(const InputEvent& p_event) {
if (touched) {
-
if (finger_pressed==-1) {
- finger_pressed=p_event.screen_touch.index;
- //emit change stuff
- emit_signal("pressed");
- if (action_id!=-1) {
-
- Input::get_singleton()->action_press(action);
- InputEvent ie;
- ie.type=InputEvent::ACTION;
- ie.ID=0;
- ie.action.action=action_id;
- ie.action.pressed=true;
- get_tree()->input_event(ie);
- }
-
- update();
+ _press(p_event.screen_touch.index);
}
-
} else {
-
if (finger_pressed!=-1) {
-
- emit_signal("released");
-
- if (action_id!=-1) {
-
- Input::get_singleton()->action_release(action);
- InputEvent ie;
- ie.type=InputEvent::ACTION;
- ie.ID=0;
- ie.action.action=action_id;
- ie.action.pressed=false;
- get_tree()->input_event(ie);
- }
- finger_pressed=-1;
-
- update();
+ _release();
}
}
@@ -239,68 +237,91 @@ void TouchScreenButton::_input(const InputEvent& p_event) {
if (!is_visible_in_tree())
return;
- if (finger_pressed!=-1)
+ const bool can_press=finger_pressed==-1 || allow_repress;
+ if (!can_press)
return; //already fingering
Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(Point2(p_event.screen_touch.x,p_event.screen_touch.y));
+ Rect2 item_rect = get_item_rect();
bool touched=false;
+ bool check_rect=true;
+ if (shape.is_valid()) {
+
+ check_rect=false;
+ Transform2D xform=shape_centered ? Transform2D().translated(get_item_rect().size*0.5f) : Transform2D();
+ touched=shape->collide(xform, unit_rect, Transform2D(0, coord + Vector2(0.5,0.5)));
+ }
+
if (bitmask.is_valid()) {
- if (Rect2(Point2(),bitmask->get_size()).has_point(coord)) {
+ check_rect=false;
+ if (!touched && Rect2(Point2(),bitmask->get_size()).has_point(coord)) {
if (bitmask->get_bit(coord))
touched=true;
}
- } else {
- if (!texture.is_null())
- touched=Rect2(Point2(),texture->get_size()).has_point(coord);
}
+ if (!touched && check_rect) {
+ if (!texture.is_null())
+ touched=item_rect.has_point(coord);
+ }
if (touched) {
-
- finger_pressed=p_event.screen_touch.index;
- //emit change stuff
- emit_signal("pressed");
- if (action_id!=-1) {
-
- Input::get_singleton()->action_press(action);
- InputEvent ie;
- ie.type=InputEvent::ACTION;
- ie.ID=0;
- ie.action.action=action_id;
- ie.action.pressed=true;
- get_tree()->input_event(ie);
- }
- update();
-
+ _press(p_event.screen_touch.index);
}
} else {
+ if (p_event.screen_touch.index==finger_pressed) {
+ _release();
+ }
+ }
+ }
+ }
+}
+void TouchScreenButton::_press(int p_finger_pressed) {
- if (p_event.screen_touch.index==finger_pressed) {
- //untouch
+ finger_pressed=p_finger_pressed;
+ allow_repress=false;
- emit_signal("released");
+ if (action_id!=-1) {
- if (action_id!=-1) {
+ Input::get_singleton()->action_press(action);
+ InputEvent ie;
+ ie.type=InputEvent::ACTION;
+ ie.ID=0;
+ ie.action.action=action_id;
+ ie.action.pressed=true;
+ get_tree()->input_event(ie);
+ }
- Input::get_singleton()->action_release(action);
- InputEvent ie;
- ie.type=InputEvent::ACTION;
- ie.ID=0;
- ie.action.action=action_id;
- ie.action.pressed=false;
- get_tree()->input_event(ie);
- }
- finger_pressed=-1;
- update();
- }
- }
+ emit_signal("pressed");
+ update();
+}
+
+void TouchScreenButton::_release(bool p_exiting_tree) {
+
+ finger_pressed=-1;
+
+ if (action_id!=-1) {
+
+ Input::get_singleton()->action_release(action);
+ if (!p_exiting_tree) {
+ InputEvent ie;
+ ie.type=InputEvent::ACTION;
+ ie.ID=0;
+ ie.action.action=action_id;
+ ie.action.pressed=false;
+ get_tree()->input_event(ie);
}
}
+
+ if (!p_exiting_tree) {
+ emit_signal("released");
+ update();
+ }
}
Rect2 TouchScreenButton::get_item_rect() const {
@@ -340,34 +361,42 @@ bool TouchScreenButton::is_passby_press_enabled() const{
void TouchScreenButton::_bind_methods() {
- ClassDB::bind_method(_MD("set_texture","texture"),&TouchScreenButton::set_texture);
- ClassDB::bind_method(_MD("get_texture"),&TouchScreenButton::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture","texture"),&TouchScreenButton::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture"),&TouchScreenButton::get_texture);
+
+ ClassDB::bind_method(D_METHOD("set_texture_pressed","texture_pressed"),&TouchScreenButton::set_texture_pressed);
+ ClassDB::bind_method(D_METHOD("get_texture_pressed"),&TouchScreenButton::get_texture_pressed);
+
+ ClassDB::bind_method(D_METHOD("set_bitmask","bitmask"),&TouchScreenButton::set_bitmask);
+ ClassDB::bind_method(D_METHOD("get_bitmask"),&TouchScreenButton::get_bitmask);
- ClassDB::bind_method(_MD("set_texture_pressed","texture_pressed"),&TouchScreenButton::set_texture_pressed);
- ClassDB::bind_method(_MD("get_texture_pressed"),&TouchScreenButton::get_texture_pressed);
+ ClassDB::bind_method(D_METHOD("set_shape","shape"),&TouchScreenButton::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape"),&TouchScreenButton::get_shape);
- ClassDB::bind_method(_MD("set_bitmask","bitmask"),&TouchScreenButton::set_bitmask);
- ClassDB::bind_method(_MD("get_bitmask"),&TouchScreenButton::get_bitmask);
+ ClassDB::bind_method(D_METHOD("set_shape_centered","bool"),&TouchScreenButton::set_shape_centered);
+ ClassDB::bind_method(D_METHOD("is_shape_centered"),&TouchScreenButton::is_shape_centered);
- ClassDB::bind_method(_MD("set_action","action"),&TouchScreenButton::set_action);
- ClassDB::bind_method(_MD("get_action"),&TouchScreenButton::get_action);
+ ClassDB::bind_method(D_METHOD("set_action","action"),&TouchScreenButton::set_action);
+ ClassDB::bind_method(D_METHOD("get_action"),&TouchScreenButton::get_action);
- ClassDB::bind_method(_MD("set_visibility_mode","mode"),&TouchScreenButton::set_visibility_mode);
- ClassDB::bind_method(_MD("get_visibility_mode"),&TouchScreenButton::get_visibility_mode);
+ ClassDB::bind_method(D_METHOD("set_visibility_mode","mode"),&TouchScreenButton::set_visibility_mode);
+ ClassDB::bind_method(D_METHOD("get_visibility_mode"),&TouchScreenButton::get_visibility_mode);
- ClassDB::bind_method(_MD("set_passby_press","enabled"),&TouchScreenButton::set_passby_press);
- ClassDB::bind_method(_MD("is_passby_press_enabled"),&TouchScreenButton::is_passby_press_enabled);
+ ClassDB::bind_method(D_METHOD("set_passby_press","enabled"),&TouchScreenButton::set_passby_press);
+ ClassDB::bind_method(D_METHOD("is_passby_press_enabled"),&TouchScreenButton::is_passby_press_enabled);
- ClassDB::bind_method(_MD("is_pressed"),&TouchScreenButton::is_pressed);
+ ClassDB::bind_method(D_METHOD("is_pressed"),&TouchScreenButton::is_pressed);
- ClassDB::bind_method(_MD("_input"),&TouchScreenButton::_input);
+ ClassDB::bind_method(D_METHOD("_input"),&TouchScreenButton::_input);
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture_pressed"),_SCS("get_texture_pressed"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"bitmask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"),_SCS("set_bitmask"),_SCS("get_bitmask"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"passby_press"),_SCS("set_passby_press"),_SCS("is_passby_press_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"action"),_SCS("set_action"),_SCS("get_action"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"visibility_mode",PROPERTY_HINT_ENUM,"Always,TouchScreen Only"),_SCS("set_visibility_mode"),_SCS("get_visibility_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture_pressed","get_texture_pressed");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"bitmask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"),"set_bitmask","get_bitmask");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D"),"set_shape","get_shape");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shape_centered"),"set_shape_centered","is_shape_centered");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"passby_press"),"set_passby_press","is_passby_press_enabled");
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"action"),"set_action","get_action");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"visibility_mode",PROPERTY_HINT_ENUM,"Always,TouchScreen Only"),"set_visibility_mode","get_visibility_mode");
ADD_SIGNAL( MethodInfo("pressed" ) );
ADD_SIGNAL( MethodInfo("released" ) );
@@ -379,7 +408,11 @@ void TouchScreenButton::_bind_methods() {
TouchScreenButton::TouchScreenButton() {
finger_pressed=-1;
+ allow_repress=false;
action_id=-1;
passby_press=false;
visibility=VISIBILITY_ALWAYS;
+ shape_centered=true;
+ unit_rect=Ref<RectangleShape2D>(memnew(RectangleShape2D));
+ unit_rect->set_extents(Vector2(0.5,0.5));
}
diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h
index 34e02d644b..8ce378c660 100644
--- a/scene/2d/screen_button.h
+++ b/scene/2d/screen_button.h
@@ -32,6 +32,7 @@
#include "scene/2d/node_2d.h"
#include "scene/resources/texture.h"
#include "scene/resources/bit_mask.h"
+#include "scene/resources/rectangle_shape_2d.h"
class TouchScreenButton : public Node2D {
@@ -47,16 +48,24 @@ private:
Ref<Texture> texture;
Ref<Texture> texture_pressed;
Ref<BitMap> bitmask;
+ Ref<Shape2D> shape;
+ bool shape_centered;
+
+ Ref<RectangleShape2D> unit_rect;
StringName action;
bool passby_press;
int finger_pressed;
+ bool allow_repress;
int action_id;
VisibilityMode visibility;
void _input(const InputEvent& p_Event);
+ void _press(int p_finger_pressed);
+ void _release(bool p_exiting_tree=false);
+
protected:
void _notification(int p_what);
@@ -73,6 +82,12 @@ public:
void set_bitmask(const Ref<BitMap>& p_bitmask);
Ref<BitMap> get_bitmask() const;
+ void set_shape(const Ref<Shape2D>& p_shape);
+ Ref<Shape2D> get_shape() const;
+
+ void set_shape_centered(bool p_shape_centered);
+ bool is_shape_centered() const;
+
void set_action(const String& p_action);
String get_action() const;
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index bea45aae4e..26c2756acd 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -294,49 +294,49 @@ void Sprite::_validate_property(PropertyInfo& property) const {
void Sprite::_bind_methods() {
- ClassDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite::set_texture);
- ClassDB::bind_method(_MD("get_texture:Texture"),&Sprite::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture","texture:Texture"),&Sprite::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"),&Sprite::get_texture);
- ClassDB::bind_method(_MD("set_centered","centered"),&Sprite::set_centered);
- ClassDB::bind_method(_MD("is_centered"),&Sprite::is_centered);
+ ClassDB::bind_method(D_METHOD("set_centered","centered"),&Sprite::set_centered);
+ ClassDB::bind_method(D_METHOD("is_centered"),&Sprite::is_centered);
- ClassDB::bind_method(_MD("set_offset","offset"),&Sprite::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&Sprite::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&Sprite::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&Sprite::get_offset);
- ClassDB::bind_method(_MD("set_flip_h","flip_h"),&Sprite::set_flip_h);
- ClassDB::bind_method(_MD("is_flipped_h"),&Sprite::is_flipped_h);
+ ClassDB::bind_method(D_METHOD("set_flip_h","flip_h"),&Sprite::set_flip_h);
+ ClassDB::bind_method(D_METHOD("is_flipped_h"),&Sprite::is_flipped_h);
- ClassDB::bind_method(_MD("set_flip_v","flip_v"),&Sprite::set_flip_v);
- ClassDB::bind_method(_MD("is_flipped_v"),&Sprite::is_flipped_v);
+ ClassDB::bind_method(D_METHOD("set_flip_v","flip_v"),&Sprite::set_flip_v);
+ ClassDB::bind_method(D_METHOD("is_flipped_v"),&Sprite::is_flipped_v);
- ClassDB::bind_method(_MD("set_region","enabled"),&Sprite::set_region);
- ClassDB::bind_method(_MD("is_region"),&Sprite::is_region);
+ ClassDB::bind_method(D_METHOD("set_region","enabled"),&Sprite::set_region);
+ ClassDB::bind_method(D_METHOD("is_region"),&Sprite::is_region);
- ClassDB::bind_method(_MD("set_region_rect","rect"),&Sprite::set_region_rect);
- ClassDB::bind_method(_MD("get_region_rect"),&Sprite::get_region_rect);
+ ClassDB::bind_method(D_METHOD("set_region_rect","rect"),&Sprite::set_region_rect);
+ ClassDB::bind_method(D_METHOD("get_region_rect"),&Sprite::get_region_rect);
- ClassDB::bind_method(_MD("set_frame","frame"),&Sprite::set_frame);
- ClassDB::bind_method(_MD("get_frame"),&Sprite::get_frame);
+ ClassDB::bind_method(D_METHOD("set_frame","frame"),&Sprite::set_frame);
+ ClassDB::bind_method(D_METHOD("get_frame"),&Sprite::get_frame);
- ClassDB::bind_method(_MD("set_vframes","vframes"),&Sprite::set_vframes);
- ClassDB::bind_method(_MD("get_vframes"),&Sprite::get_vframes);
+ ClassDB::bind_method(D_METHOD("set_vframes","vframes"),&Sprite::set_vframes);
+ ClassDB::bind_method(D_METHOD("get_vframes"),&Sprite::get_vframes);
- ClassDB::bind_method(_MD("set_hframes","hframes"),&Sprite::set_hframes);
- ClassDB::bind_method(_MD("get_hframes"),&Sprite::get_hframes);
+ ClassDB::bind_method(D_METHOD("set_hframes","hframes"),&Sprite::set_hframes);
+ ClassDB::bind_method(D_METHOD("get_hframes"),&Sprite::get_hframes);
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_SIGNAL(MethodInfo("texture_changed"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
- ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
- ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes"));
- ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_texture","get_texture");
+ ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), "set_centered","is_centered");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), "set_offset","get_offset");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), "set_flip_h","is_flipped_h");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), "set_flip_v","is_flipped_v");
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), "set_vframes","get_vframes");
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), "set_hframes","get_hframes");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), "set_frame","get_frame");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), "set_region","is_region");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), "set_region_rect","get_region_rect");
}
@@ -552,22 +552,22 @@ String ViewportSprite::get_configuration_warning() const {
void ViewportSprite::_bind_methods() {
- ClassDB::bind_method(_MD("set_viewport_path","path"),&ViewportSprite::set_viewport_path);
- ClassDB::bind_method(_MD("get_viewport_path"),&ViewportSprite::get_viewport_path);
+ ClassDB::bind_method(D_METHOD("set_viewport_path","path"),&ViewportSprite::set_viewport_path);
+ ClassDB::bind_method(D_METHOD("get_viewport_path"),&ViewportSprite::get_viewport_path);
- ClassDB::bind_method(_MD("set_centered","centered"),&ViewportSprite::set_centered);
- ClassDB::bind_method(_MD("is_centered"),&ViewportSprite::is_centered);
+ ClassDB::bind_method(D_METHOD("set_centered","centered"),&ViewportSprite::set_centered);
+ ClassDB::bind_method(D_METHOD("is_centered"),&ViewportSprite::is_centered);
- ClassDB::bind_method(_MD("set_offset","offset"),&ViewportSprite::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&ViewportSprite::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&ViewportSprite::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&ViewportSprite::get_offset);
- ClassDB::bind_method(_MD("set_modulate","modulate"),&ViewportSprite::set_modulate);
- ClassDB::bind_method(_MD("get_modulate"),&ViewportSprite::get_modulate);
+ ClassDB::bind_method(D_METHOD("set_modulate","modulate"),&ViewportSprite::set_modulate);
+ ClassDB::bind_method(D_METHOD("get_modulate"),&ViewportSprite::get_modulate);
- ADD_PROPERTYNZ( PropertyInfo( Variant::NODE_PATH, "viewport"), _SCS("set_viewport_path"),_SCS("get_viewport_path"));
- ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
- ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
+ ADD_PROPERTYNZ( PropertyInfo( Variant::NODE_PATH, "viewport"), "set_viewport_path","get_viewport_path");
+ ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), "set_centered","is_centered");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), "set_offset","get_offset");
+ ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), "set_modulate","get_modulate");
}
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index d6d713920c..f89a72e1b9 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -458,6 +458,9 @@ void TileMap::_update_dirty_quadrants() {
Color modulate = tile_set->tile_get_modulate(c.id);
+ Color self_modulate = get_self_modulate();
+ modulate = Color(modulate.r*self_modulate.r, modulate.g*self_modulate.g,
+ modulate.b*self_modulate.b, modulate.a*self_modulate.a);
if (r==Rect2()) {
tex->draw_rect(canvas_item,rect,false,modulate,c.transpose);
} else {
@@ -730,6 +733,7 @@ void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bo
c.transpose=p_transpose;
_make_quadrant_dirty(Q);
+ used_size_cache_dirty=true;
}
@@ -818,6 +822,7 @@ void TileMap::clear() {
_clear_quadrants();
tile_map.clear();
+ used_size_cache_dirty=true;
}
void TileMap::_set_tile_data(const PoolVector<int>& p_data) {
@@ -1159,6 +1164,28 @@ Array TileMap::get_used_cells() const {
return a;
}
+Rect2 TileMap::get_used_rect() { // Not const because of cache
+
+ if (used_size_cache_dirty) {
+ if(tile_map.size() > 0) {
+ used_size_cache = Rect2(tile_map.front()->key().x, tile_map.front()->key().y, 0, 0);
+
+ for (Map<PosKey,Cell>::Element *E=tile_map.front();E;E=E->next()) {
+ used_size_cache.expand_to(Vector2(E->key().x, E->key().y));
+ }
+
+ used_size_cache.size += Vector2(1,1);
+ } else {
+ used_size_cache = Rect2();
+ }
+
+ used_size_cache_dirty = false;
+ }
+
+ return used_size_cache;
+}
+
+
void TileMap::set_occluder_light_mask(int p_mask) {
occluder_light_mask=p_mask;
@@ -1189,101 +1216,102 @@ void TileMap::set_light_mask(int p_light_mask) {
void TileMap::_bind_methods() {
- ClassDB::bind_method(_MD("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
- ClassDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_tileset);
+ ClassDB::bind_method(D_METHOD("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
+ ClassDB::bind_method(D_METHOD("get_tileset:TileSet"),&TileMap::get_tileset);
- ClassDB::bind_method(_MD("set_mode","mode"),&TileMap::set_mode);
- ClassDB::bind_method(_MD("get_mode"),&TileMap::get_mode);
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&TileMap::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&TileMap::get_mode);
- ClassDB::bind_method(_MD("set_half_offset","half_offset"),&TileMap::set_half_offset);
- ClassDB::bind_method(_MD("get_half_offset"),&TileMap::get_half_offset);
+ ClassDB::bind_method(D_METHOD("set_half_offset","half_offset"),&TileMap::set_half_offset);
+ ClassDB::bind_method(D_METHOD("get_half_offset"),&TileMap::get_half_offset);
- ClassDB::bind_method(_MD("set_custom_transform","custom_transform"),&TileMap::set_custom_transform);
- ClassDB::bind_method(_MD("get_custom_transform"),&TileMap::get_custom_transform);
+ ClassDB::bind_method(D_METHOD("set_custom_transform","custom_transform"),&TileMap::set_custom_transform);
+ ClassDB::bind_method(D_METHOD("get_custom_transform"),&TileMap::get_custom_transform);
- ClassDB::bind_method(_MD("set_cell_size","size"),&TileMap::set_cell_size);
- ClassDB::bind_method(_MD("get_cell_size"),&TileMap::get_cell_size);
+ ClassDB::bind_method(D_METHOD("set_cell_size","size"),&TileMap::set_cell_size);
+ ClassDB::bind_method(D_METHOD("get_cell_size"),&TileMap::get_cell_size);
- ClassDB::bind_method(_MD("_set_old_cell_size","size"),&TileMap::_set_old_cell_size);
- ClassDB::bind_method(_MD("_get_old_cell_size"),&TileMap::_get_old_cell_size);
+ ClassDB::bind_method(D_METHOD("_set_old_cell_size","size"),&TileMap::_set_old_cell_size);
+ ClassDB::bind_method(D_METHOD("_get_old_cell_size"),&TileMap::_get_old_cell_size);
- ClassDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
- ClassDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size);
+ ClassDB::bind_method(D_METHOD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
+ ClassDB::bind_method(D_METHOD("get_quadrant_size"),&TileMap::get_quadrant_size);
- ClassDB::bind_method(_MD("set_tile_origin","origin"),&TileMap::set_tile_origin);
- ClassDB::bind_method(_MD("get_tile_origin"),&TileMap::get_tile_origin);
+ ClassDB::bind_method(D_METHOD("set_tile_origin","origin"),&TileMap::set_tile_origin);
+ ClassDB::bind_method(D_METHOD("get_tile_origin"),&TileMap::get_tile_origin);
- ClassDB::bind_method(_MD("set_center_x","enable"),&TileMap::set_center_x);
- ClassDB::bind_method(_MD("get_center_x"),&TileMap::get_center_x);
+ ClassDB::bind_method(D_METHOD("set_center_x","enable"),&TileMap::set_center_x);
+ ClassDB::bind_method(D_METHOD("get_center_x"),&TileMap::get_center_x);
- ClassDB::bind_method(_MD("set_center_y","enable"),&TileMap::set_center_y);
- ClassDB::bind_method(_MD("get_center_y"),&TileMap::get_center_y);
+ ClassDB::bind_method(D_METHOD("set_center_y","enable"),&TileMap::set_center_y);
+ ClassDB::bind_method(D_METHOD("get_center_y"),&TileMap::get_center_y);
- ClassDB::bind_method(_MD("set_y_sort_mode","enable"),&TileMap::set_y_sort_mode);
- ClassDB::bind_method(_MD("is_y_sort_mode_enabled"),&TileMap::is_y_sort_mode_enabled);
+ ClassDB::bind_method(D_METHOD("set_y_sort_mode","enable"),&TileMap::set_y_sort_mode);
+ ClassDB::bind_method(D_METHOD("is_y_sort_mode_enabled"),&TileMap::is_y_sort_mode_enabled);
- ClassDB::bind_method(_MD("set_collision_use_kinematic","use_kinematic"),&TileMap::set_collision_use_kinematic);
- ClassDB::bind_method(_MD("get_collision_use_kinematic"),&TileMap::get_collision_use_kinematic);
+ ClassDB::bind_method(D_METHOD("set_collision_use_kinematic","use_kinematic"),&TileMap::set_collision_use_kinematic);
+ ClassDB::bind_method(D_METHOD("get_collision_use_kinematic"),&TileMap::get_collision_use_kinematic);
- ClassDB::bind_method(_MD("set_collision_layer","mask"),&TileMap::set_collision_layer);
- ClassDB::bind_method(_MD("get_collision_layer"),&TileMap::get_collision_layer);
+ ClassDB::bind_method(D_METHOD("set_collision_layer","mask"),&TileMap::set_collision_layer);
+ ClassDB::bind_method(D_METHOD("get_collision_layer"),&TileMap::get_collision_layer);
- ClassDB::bind_method(_MD("set_collision_mask","mask"),&TileMap::set_collision_mask);
- ClassDB::bind_method(_MD("get_collision_mask"),&TileMap::get_collision_mask);
+ ClassDB::bind_method(D_METHOD("set_collision_mask","mask"),&TileMap::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"),&TileMap::get_collision_mask);
- ClassDB::bind_method(_MD("set_collision_friction","value"),&TileMap::set_collision_friction);
- ClassDB::bind_method(_MD("get_collision_friction"),&TileMap::get_collision_friction);
+ ClassDB::bind_method(D_METHOD("set_collision_friction","value"),&TileMap::set_collision_friction);
+ ClassDB::bind_method(D_METHOD("get_collision_friction"),&TileMap::get_collision_friction);
- ClassDB::bind_method(_MD("set_collision_bounce","value"),&TileMap::set_collision_bounce);
- ClassDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce);
+ ClassDB::bind_method(D_METHOD("set_collision_bounce","value"),&TileMap::set_collision_bounce);
+ ClassDB::bind_method(D_METHOD("get_collision_bounce"),&TileMap::get_collision_bounce);
- ClassDB::bind_method(_MD("set_occluder_light_mask","mask"),&TileMap::set_occluder_light_mask);
- ClassDB::bind_method(_MD("get_occluder_light_mask"),&TileMap::get_occluder_light_mask);
+ ClassDB::bind_method(D_METHOD("set_occluder_light_mask","mask"),&TileMap::set_occluder_light_mask);
+ ClassDB::bind_method(D_METHOD("get_occluder_light_mask"),&TileMap::get_occluder_light_mask);
- ClassDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
- ClassDB::bind_method(_MD("set_cellv","pos","tile","flip_x","flip_y","transpose"),&TileMap::set_cellv,DEFVAL(false),DEFVAL(false),DEFVAL(false));
- ClassDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
- ClassDB::bind_method(_MD("get_cellv","pos"),&TileMap::get_cellv);
- ClassDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
- ClassDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);
- ClassDB::bind_method(_MD("is_cell_transposed","x","y"),&TileMap::is_cell_transposed);
+ ClassDB::bind_method(D_METHOD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_cellv","pos","tile","flip_x","flip_y","transpose"),&TileMap::set_cellv,DEFVAL(false),DEFVAL(false),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_cell","x","y"),&TileMap::get_cell);
+ ClassDB::bind_method(D_METHOD("get_cellv","pos"),&TileMap::get_cellv);
+ ClassDB::bind_method(D_METHOD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
+ ClassDB::bind_method(D_METHOD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);
+ ClassDB::bind_method(D_METHOD("is_cell_transposed","x","y"),&TileMap::is_cell_transposed);
- ClassDB::bind_method(_MD("clear"),&TileMap::clear);
+ ClassDB::bind_method(D_METHOD("clear"),&TileMap::clear);
- ClassDB::bind_method(_MD("get_used_cells"),&TileMap::get_used_cells);
+ ClassDB::bind_method(D_METHOD("get_used_cells"),&TileMap::get_used_cells);
+ ClassDB::bind_method(D_METHOD("get_used_rect"),&TileMap::get_used_rect);
- ClassDB::bind_method(_MD("map_to_world","mappos","ignore_half_ofs"),&TileMap::map_to_world,DEFVAL(false));
- ClassDB::bind_method(_MD("world_to_map","worldpos"),&TileMap::world_to_map);
+ ClassDB::bind_method(D_METHOD("map_to_world","mappos","ignore_half_ofs"),&TileMap::map_to_world,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("world_to_map","worldpos"),&TileMap::world_to_map);
- ClassDB::bind_method(_MD("_clear_quadrants"),&TileMap::_clear_quadrants);
- ClassDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
- ClassDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants);
+ ClassDB::bind_method(D_METHOD("_clear_quadrants"),&TileMap::_clear_quadrants);
+ ClassDB::bind_method(D_METHOD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
+ ClassDB::bind_method(D_METHOD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants);
- ClassDB::bind_method(_MD("_set_tile_data"),&TileMap::_set_tile_data);
- ClassDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_tile_data);
+ ClassDB::bind_method(D_METHOD("_set_tile_data"),&TileMap::_set_tile_data);
+ ClassDB::bind_method(D_METHOD("_get_tile_data"),&TileMap::_get_tile_data);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),_SCS("set_mode"),_SCS("get_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),"set_mode","get_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),"set_tileset","get_tileset");
ADD_GROUP("Cell","cell_");
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
- ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM2D,"cell_custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_tile_origin",PROPERTY_HINT_ENUM,"Top Left,Center,Bottom Left"),_SCS("set_tile_origin"),_SCS("get_tile_origin"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"cell_y_sort"),_SCS("set_y_sort_mode"),_SCS("is_y_sort_mode_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1"),"set_cell_size","get_cell_size");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),"set_quadrant_size","get_quadrant_size");
+ ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM2D,"cell_custom_transform"),"set_custom_transform","get_custom_transform");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),"set_half_offset","get_half_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_tile_origin",PROPERTY_HINT_ENUM,"Top Left,Center,Bottom Left"),"set_tile_origin","get_tile_origin");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"cell_y_sort"),"set_y_sort_mode","is_y_sort_mode_enabled");
ADD_GROUP("Collision","collision_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision_use_kinematic",PROPERTY_HINT_NONE,""),_SCS("set_collision_use_kinematic"),_SCS("get_collision_use_kinematic"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision_friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision_bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_layers",PROPERTY_HINT_LAYERS_2D_PHYSICS),_SCS("set_collision_layer"),_SCS("get_collision_layer"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collision_use_kinematic",PROPERTY_HINT_NONE,""),"set_collision_use_kinematic","get_collision_use_kinematic");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision_friction",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_collision_friction","get_collision_friction");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision_bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_collision_bounce","get_collision_bounce");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_layers",PROPERTY_HINT_LAYERS_2D_PHYSICS),"set_collision_layer","get_collision_layer");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_2D_PHYSICS),"set_collision_mask","get_collision_mask");
ADD_GROUP("Occluder","occluder_");
- ADD_PROPERTY( PropertyInfo(Variant::INT,"occluder_light_mask",PROPERTY_HINT_LAYERS_2D_RENDER),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"occluder_light_mask",PROPERTY_HINT_LAYERS_2D_RENDER),"set_occluder_light_mask","get_occluder_light_mask");
ADD_GROUP("","");
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_tile_data","_get_tile_data");
ADD_SIGNAL(MethodInfo("settings_changed"));
@@ -1305,6 +1333,7 @@ TileMap::TileMap() {
rect_cache_dirty=true;
+ used_size_cache_dirty=true;
pending_update=false;
quadrant_order_dirty=false;
quadrant_size=16;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index ba6de62f8e..c581aa8056 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -141,6 +141,8 @@ private:
Rect2 rect_cache;
bool rect_cache_dirty;
+ Rect2 used_size_cache;
+ bool used_size_cache_dirty;
bool quadrant_order_dirty;
bool y_sort_mode;
float fp_adjust;
@@ -176,8 +178,6 @@ private:
_FORCE_INLINE_ Vector2 _map_to_world(int p_x,int p_y,bool p_ignore_ofs=false) const;
- Array get_used_cells() const;
-
protected:
@@ -252,6 +252,9 @@ public:
void set_y_sort_mode(bool p_enable);
bool is_y_sort_mode_enabled() const;
+ Array get_used_cells() const;
+ Rect2 get_used_rect(); // Not const because of cache
+
void set_occluder_light_mask(int p_mask);
int get_occluder_light_mask() const;
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index f1c70a8f60..64ab333e48 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -129,11 +129,11 @@ bool VisibilityNotifier2D::is_on_screen() const {
void VisibilityNotifier2D::_bind_methods(){
- ClassDB::bind_method(_MD("set_rect","rect"),&VisibilityNotifier2D::set_rect);
- ClassDB::bind_method(_MD("get_rect"),&VisibilityNotifier2D::get_rect);
- ClassDB::bind_method(_MD("is_on_screen"),&VisibilityNotifier2D::is_on_screen);
+ ClassDB::bind_method(D_METHOD("set_rect","rect"),&VisibilityNotifier2D::set_rect);
+ ClassDB::bind_method(D_METHOD("get_rect"),&VisibilityNotifier2D::get_rect);
+ ClassDB::bind_method(D_METHOD("is_on_screen"),&VisibilityNotifier2D::is_on_screen);
- ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),_SCS("set_rect"),_SCS("get_rect"));
+ ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),"set_rect","get_rect");
ADD_SIGNAL( MethodInfo("viewport_entered",PropertyInfo(Variant::OBJECT,"viewport",PROPERTY_HINT_RESOURCE_TYPE,"Viewport")) );
ADD_SIGNAL( MethodInfo("viewport_exited",PropertyInfo(Variant::OBJECT,"viewport",PROPERTY_HINT_RESOURCE_TYPE,"Viewport")) );
@@ -355,16 +355,16 @@ String VisibilityEnabler2D::get_configuration_warning() const {
void VisibilityEnabler2D::_bind_methods(){
- ClassDB::bind_method(_MD("set_enabler","enabler","enabled"),&VisibilityEnabler2D::set_enabler);
- ClassDB::bind_method(_MD("is_enabler_enabled","enabler"),&VisibilityEnabler2D::is_enabler_enabled);
- ClassDB::bind_method(_MD("_node_removed"),&VisibilityEnabler2D::_node_removed);
+ ClassDB::bind_method(D_METHOD("set_enabler","enabler","enabled"),&VisibilityEnabler2D::set_enabler);
+ ClassDB::bind_method(D_METHOD("is_enabler_enabled","enabler"),&VisibilityEnabler2D::is_enabler_enabled);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&VisibilityEnabler2D::_node_removed);
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_animations"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATIONS );
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"freeze_bodies"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_FREEZE_BODIES);
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_particles"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_PARTICLES);
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_animated_sprites"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATED_SPRITES);
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"process_parent"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PARENT_PROCESS);
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"fixed_process_parent"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PARENT_FIXED_PROCESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_animations"),"set_enabler","is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS );
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"freeze_bodies"),"set_enabler","is_enabler_enabled", ENABLER_FREEZE_BODIES);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_particles"),"set_enabler","is_enabler_enabled", ENABLER_PAUSE_PARTICLES);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_animated_sprites"),"set_enabler","is_enabler_enabled", ENABLER_PAUSE_ANIMATED_SPRITES);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"process_parent"),"set_enabler","is_enabler_enabled", ENABLER_PARENT_PROCESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"fixed_process_parent"),"set_enabler","is_enabler_enabled", ENABLER_PARENT_FIXED_PROCESS);
BIND_CONSTANT( ENABLER_FREEZE_BODIES );
BIND_CONSTANT( ENABLER_PAUSE_ANIMATIONS );
diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp
index 588f343048..cb9a494e87 100644
--- a/scene/2d/y_sort.cpp
+++ b/scene/2d/y_sort.cpp
@@ -43,11 +43,11 @@ bool YSort::is_sort_enabled() const {
void YSort::_bind_methods() {
- ClassDB::bind_method(_MD("set_sort_enabled","enabled"),&YSort::set_sort_enabled);
- ClassDB::bind_method(_MD("is_sort_enabled"),&YSort::is_sort_enabled);
+ ClassDB::bind_method(D_METHOD("set_sort_enabled","enabled"),&YSort::set_sort_enabled);
+ ClassDB::bind_method(D_METHOD("is_sort_enabled"),&YSort::is_sort_enabled);
ADD_GROUP("Sort","sort_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"sort_enabled"),_SCS("set_sort_enabled"),_SCS("is_sort_enabled"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"sort_enabled"),"set_sort_enabled","is_sort_enabled");
}
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index 3301c4d754..92ac091fc5 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -576,63 +576,63 @@ bool Area::get_layer_mask_bit(int p_bit) const{
void Area::_bind_methods() {
- ClassDB::bind_method(_MD("_body_enter_tree","id"),&Area::_body_enter_tree);
- ClassDB::bind_method(_MD("_body_exit_tree","id"),&Area::_body_exit_tree);
+ ClassDB::bind_method(D_METHOD("_body_enter_tree","id"),&Area::_body_enter_tree);
+ ClassDB::bind_method(D_METHOD("_body_exit_tree","id"),&Area::_body_exit_tree);
- ClassDB::bind_method(_MD("_area_enter_tree","id"),&Area::_area_enter_tree);
- ClassDB::bind_method(_MD("_area_exit_tree","id"),&Area::_area_exit_tree);
+ ClassDB::bind_method(D_METHOD("_area_enter_tree","id"),&Area::_area_enter_tree);
+ ClassDB::bind_method(D_METHOD("_area_exit_tree","id"),&Area::_area_exit_tree);
- ClassDB::bind_method(_MD("set_space_override_mode","enable"),&Area::set_space_override_mode);
- ClassDB::bind_method(_MD("get_space_override_mode"),&Area::get_space_override_mode);
+ ClassDB::bind_method(D_METHOD("set_space_override_mode","enable"),&Area::set_space_override_mode);
+ ClassDB::bind_method(D_METHOD("get_space_override_mode"),&Area::get_space_override_mode);
- ClassDB::bind_method(_MD("set_gravity_is_point","enable"),&Area::set_gravity_is_point);
- ClassDB::bind_method(_MD("is_gravity_a_point"),&Area::is_gravity_a_point);
+ ClassDB::bind_method(D_METHOD("set_gravity_is_point","enable"),&Area::set_gravity_is_point);
+ ClassDB::bind_method(D_METHOD("is_gravity_a_point"),&Area::is_gravity_a_point);
- ClassDB::bind_method(_MD("set_gravity_distance_scale","distance_scale"),&Area::set_gravity_distance_scale);
- ClassDB::bind_method(_MD("get_gravity_distance_scale"),&Area::get_gravity_distance_scale);
+ ClassDB::bind_method(D_METHOD("set_gravity_distance_scale","distance_scale"),&Area::set_gravity_distance_scale);
+ ClassDB::bind_method(D_METHOD("get_gravity_distance_scale"),&Area::get_gravity_distance_scale);
- ClassDB::bind_method(_MD("set_gravity_vector","vector"),&Area::set_gravity_vector);
- ClassDB::bind_method(_MD("get_gravity_vector"),&Area::get_gravity_vector);
+ ClassDB::bind_method(D_METHOD("set_gravity_vector","vector"),&Area::set_gravity_vector);
+ ClassDB::bind_method(D_METHOD("get_gravity_vector"),&Area::get_gravity_vector);
- ClassDB::bind_method(_MD("set_gravity","gravity"),&Area::set_gravity);
- ClassDB::bind_method(_MD("get_gravity"),&Area::get_gravity);
+ ClassDB::bind_method(D_METHOD("set_gravity","gravity"),&Area::set_gravity);
+ ClassDB::bind_method(D_METHOD("get_gravity"),&Area::get_gravity);
- ClassDB::bind_method(_MD("set_angular_damp","angular_damp"),&Area::set_angular_damp);
- ClassDB::bind_method(_MD("get_angular_damp"),&Area::get_angular_damp);
+ ClassDB::bind_method(D_METHOD("set_angular_damp","angular_damp"),&Area::set_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_angular_damp"),&Area::get_angular_damp);
- ClassDB::bind_method(_MD("set_linear_damp","linear_damp"),&Area::set_linear_damp);
- ClassDB::bind_method(_MD("get_linear_damp"),&Area::get_linear_damp);
+ ClassDB::bind_method(D_METHOD("set_linear_damp","linear_damp"),&Area::set_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_linear_damp"),&Area::get_linear_damp);
- ClassDB::bind_method(_MD("set_priority","priority"),&Area::set_priority);
- ClassDB::bind_method(_MD("get_priority"),&Area::get_priority);
+ ClassDB::bind_method(D_METHOD("set_priority","priority"),&Area::set_priority);
+ ClassDB::bind_method(D_METHOD("get_priority"),&Area::get_priority);
- ClassDB::bind_method(_MD("set_collision_mask","collision_mask"),&Area::set_collision_mask);
- ClassDB::bind_method(_MD("get_collision_mask"),&Area::get_collision_mask);
+ ClassDB::bind_method(D_METHOD("set_collision_mask","collision_mask"),&Area::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"),&Area::get_collision_mask);
- ClassDB::bind_method(_MD("set_layer_mask","layer_mask"),&Area::set_layer_mask);
- ClassDB::bind_method(_MD("get_layer_mask"),&Area::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&Area::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&Area::get_layer_mask);
- ClassDB::bind_method(_MD("set_collision_mask_bit","bit","value"),&Area::set_collision_mask_bit);
- ClassDB::bind_method(_MD("get_collision_mask_bit","bit"),&Area::get_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit","bit","value"),&Area::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit","bit"),&Area::get_collision_mask_bit);
- ClassDB::bind_method(_MD("set_layer_mask_bit","bit","value"),&Area::set_layer_mask_bit);
- ClassDB::bind_method(_MD("get_layer_mask_bit","bit"),&Area::get_layer_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_layer_mask_bit","bit","value"),&Area::set_layer_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_layer_mask_bit","bit"),&Area::get_layer_mask_bit);
- ClassDB::bind_method(_MD("set_monitorable","enable"),&Area::set_monitorable);
- ClassDB::bind_method(_MD("is_monitorable"),&Area::is_monitorable);
+ ClassDB::bind_method(D_METHOD("set_monitorable","enable"),&Area::set_monitorable);
+ ClassDB::bind_method(D_METHOD("is_monitorable"),&Area::is_monitorable);
- ClassDB::bind_method(_MD("set_monitoring","enable"),&Area::set_monitoring);
- ClassDB::bind_method(_MD("is_monitoring"),&Area::is_monitoring);
+ ClassDB::bind_method(D_METHOD("set_monitoring","enable"),&Area::set_monitoring);
+ ClassDB::bind_method(D_METHOD("is_monitoring"),&Area::is_monitoring);
- ClassDB::bind_method(_MD("get_overlapping_bodies"),&Area::get_overlapping_bodies);
- ClassDB::bind_method(_MD("get_overlapping_areas"),&Area::get_overlapping_areas);
+ ClassDB::bind_method(D_METHOD("get_overlapping_bodies"),&Area::get_overlapping_bodies);
+ ClassDB::bind_method(D_METHOD("get_overlapping_areas"),&Area::get_overlapping_areas);
- ClassDB::bind_method(_MD("overlaps_body","body"),&Area::overlaps_body);
- ClassDB::bind_method(_MD("overlaps_area","area"),&Area::overlaps_area);
+ ClassDB::bind_method(D_METHOD("overlaps_body","body"),&Area::overlaps_body);
+ ClassDB::bind_method(D_METHOD("overlaps_area","area"),&Area::overlaps_area);
- ClassDB::bind_method(_MD("_body_inout"),&Area::_body_inout);
- ClassDB::bind_method(_MD("_area_inout"),&Area::_area_inout);
+ ClassDB::bind_method(D_METHOD("_body_inout"),&Area::_body_inout);
+ ClassDB::bind_method(D_METHOD("_area_inout"),&Area::_area_inout);
ADD_SIGNAL( MethodInfo("body_shape_entered",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"area_shape")));
@@ -645,19 +645,19 @@ void Area::_bind_methods() {
ADD_SIGNAL( MethodInfo("area_entered",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area")));
ADD_SIGNAL( MethodInfo("area_exited",PropertyInfo(Variant::OBJECT,"area",PROPERTY_HINT_RESOURCE_TYPE,"Area")));
- 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"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_monitoring"),_SCS("is_monitoring"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Combine-Replace,Replace,Replace-Combine"),"set_space_override_mode","get_space_override_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),"set_gravity_is_point","is_gravity_a_point");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),"set_gravity_distance_scale","get_gravity_distance_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"gravity_vec"),"set_gravity_vector","get_gravity_vector");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),"set_gravity","get_gravity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),"set_linear_damp","get_linear_damp");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),"set_angular_damp","get_angular_damp");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),"set_priority","get_priority");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),"set_monitoring","is_monitoring");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),"set_monitorable","is_monitorable");
ADD_GROUP("Collision","collision_");
- ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_layers",PROPERTY_HINT_LAYERS_3D_PHYSICS),_SCS("set_layer_mask"),_SCS("get_layer_mask"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_3D_PHYSICS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_layers",PROPERTY_HINT_LAYERS_3D_PHYSICS),"set_layer_mask","get_layer_mask");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_3D_PHYSICS),"set_collision_mask","get_collision_mask");
}
diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp
index b67b75d48f..e20d8faafd 100644
--- a/scene/3d/baked_light_instance.cpp
+++ b/scene/3d/baked_light_instance.cpp
@@ -1718,26 +1718,26 @@ void BakedLight::_debug_mesh_light() {
void BakedLight::_bind_methods() {
- ClassDB::bind_method(_MD("set_cell_subdiv","steps"),&BakedLight::set_cell_subdiv);
- ClassDB::bind_method(_MD("get_cell_subdiv"),&BakedLight::get_cell_subdiv);
+ ClassDB::bind_method(D_METHOD("set_cell_subdiv","steps"),&BakedLight::set_cell_subdiv);
+ ClassDB::bind_method(D_METHOD("get_cell_subdiv"),&BakedLight::get_cell_subdiv);
- ClassDB::bind_method(_MD("bake"),&BakedLight::bake);
- ClassDB::set_method_flags(get_class_static(),_SCS("bake"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("bake"),&BakedLight::bake);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("bake"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::bind_method(_MD("bake_lights"),&BakedLight::bake_lights);
- ClassDB::set_method_flags(get_class_static(),_SCS("bake_lights"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("bake_lights"),&BakedLight::bake_lights);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("bake_lights"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::bind_method(_MD("bake_radiance"),&BakedLight::bake_radiance);
- ClassDB::set_method_flags(get_class_static(),_SCS("bake_radiance"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("bake_radiance"),&BakedLight::bake_radiance);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("bake_radiance"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::bind_method(_MD("debug_mesh_albedo"),&BakedLight::_debug_mesh_albedo);
- ClassDB::set_method_flags(get_class_static(),_SCS("debug_mesh_albedo"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("debug_mesh_albedo"),&BakedLight::_debug_mesh_albedo);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("debug_mesh_albedo"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::bind_method(_MD("debug_mesh_light"),&BakedLight::_debug_mesh_light);
- ClassDB::set_method_flags(get_class_static(),_SCS("debug_mesh_light"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("debug_mesh_light"),&BakedLight::_debug_mesh_light);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("debug_mesh_light"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"cell_subdiv"),_SCS("set_cell_subdiv"),_SCS("get_cell_subdiv"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"cell_subdiv"),"set_cell_subdiv","get_cell_subdiv");
ADD_SIGNAL( MethodInfo("baked_light_changed"));
}
@@ -1797,11 +1797,11 @@ DVector<Face3> BakedLightSampler::get_faces(uint32_t p_usage_flags) const {
void BakedLightSampler::_bind_methods() {
- ClassDB::bind_method(_MD("set_param","param","value"),&BakedLightSampler::set_param);
- ClassDB::bind_method(_MD("get_param","param"),&BakedLightSampler::get_param);
+ ClassDB::bind_method(D_METHOD("set_param","param","value"),&BakedLightSampler::set_param);
+ ClassDB::bind_method(D_METHOD("get_param","param"),&BakedLightSampler::get_param);
- ClassDB::bind_method(_MD("set_resolution","resolution"),&BakedLightSampler::set_resolution);
- ClassDB::bind_method(_MD("get_resolution"),&BakedLightSampler::get_resolution);
+ ClassDB::bind_method(D_METHOD("set_resolution","resolution"),&BakedLightSampler::set_resolution);
+ ClassDB::bind_method(D_METHOD("get_resolution"),&BakedLightSampler::get_resolution);
BIND_CONSTANT( PARAM_RADIUS );
@@ -1810,12 +1810,12 @@ void BakedLightSampler::_bind_methods() {
BIND_CONSTANT( PARAM_DETAIL_RATIO );
BIND_CONSTANT( PARAM_MAX );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_RADIUS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/strength",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_STRENGTH);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/attenuation",PROPERTY_HINT_EXP_EASING),_SCS("set_param"),_SCS("get_param"),PARAM_ATTENUATION);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO);
- //ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0,20,1"),_SCS("set_param"),_SCS("get_param"),PARAM_DETAIL_RATIO);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/resolution",PROPERTY_HINT_RANGE,"4,32,1"),_SCS("set_resolution"),_SCS("get_resolution"));
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),"set_param","get_param",PARAM_RADIUS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/strength",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param","get_param",PARAM_STRENGTH);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/attenuation",PROPERTY_HINT_EXP_EASING),"set_param","get_param",PARAM_ATTENUATION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0.01,1.0,0.01"),"set_param","get_param",PARAM_DETAIL_RATIO);
+ //ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/detail_ratio",PROPERTY_HINT_RANGE,"0,20,1"),"set_param","get_param",PARAM_DETAIL_RATIO);
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"params/resolution",PROPERTY_HINT_RANGE,"4,32,1"),"set_resolution","get_resolution");
}
diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp
index f3c839d525..af3fe3c0a4 100644
--- a/scene/3d/body_shape.cpp
+++ b/scene/3d/body_shape.cpp
@@ -414,22 +414,22 @@ String CollisionShape::get_configuration_warning() const {
void CollisionShape::_bind_methods() {
//not sure if this should do anything
- ClassDB::bind_method(_MD("resource_changed","resource"),&CollisionShape::resource_changed);
- ClassDB::bind_method(_MD("set_shape","shape"),&CollisionShape::set_shape);
- ClassDB::bind_method(_MD("get_shape"),&CollisionShape::get_shape);
- ClassDB::bind_method(_MD("_add_to_collision_object"),&CollisionShape::_add_to_collision_object);
- ClassDB::bind_method(_MD("set_trigger","enable"),&CollisionShape::set_trigger);
- ClassDB::bind_method(_MD("is_trigger"),&CollisionShape::is_trigger);
- ClassDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers);
+ ClassDB::bind_method(D_METHOD("resource_changed","resource"),&CollisionShape::resource_changed);
+ ClassDB::bind_method(D_METHOD("set_shape","shape"),&CollisionShape::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape"),&CollisionShape::get_shape);
+ ClassDB::bind_method(D_METHOD("_add_to_collision_object"),&CollisionShape::_add_to_collision_object);
+ ClassDB::bind_method(D_METHOD("set_trigger","enable"),&CollisionShape::set_trigger);
+ ClassDB::bind_method(D_METHOD("is_trigger"),&CollisionShape::is_trigger);
+ ClassDB::bind_method(D_METHOD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers);
ClassDB::set_method_flags("CollisionShape","make_convex_from_brothers",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape::_set_update_shape_index);
- ClassDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape::_get_update_shape_index);
+ ClassDB::bind_method(D_METHOD("_set_update_shape_index","index"),&CollisionShape::_set_update_shape_index);
+ ClassDB::bind_method(D_METHOD("_get_update_shape_index"),&CollisionShape::_get_update_shape_index);
- ClassDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape::get_collision_object_shape_index);
+ ClassDB::bind_method(D_METHOD("get_collision_object_shape_index"),&CollisionShape::get_collision_object_shape_index);
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), _SCS("set_shape"), _SCS("get_shape"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index"));
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),"set_trigger","is_trigger");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), "_set_update_shape_index", "_get_update_shape_index");
}
diff --git a/scene/3d/bone_attachment.cpp b/scene/3d/bone_attachment.cpp
index 825cf1c535..1a2680e3b8 100644
--- a/scene/3d/bone_attachment.cpp
+++ b/scene/3d/bone_attachment.cpp
@@ -139,6 +139,6 @@ BoneAttachment::BoneAttachment()
}
void BoneAttachment::_bind_methods(){
- ClassDB::bind_method(_MD("set_bone_name","bone_name"),&BoneAttachment::set_bone_name);
- ClassDB::bind_method(_MD("get_bone_name"),&BoneAttachment::get_bone_name);
+ ClassDB::bind_method(D_METHOD("set_bone_name","bone_name"),&BoneAttachment::set_bone_name);
+ ClassDB::bind_method(D_METHOD("get_bone_name"),&BoneAttachment::get_bone_name);
}
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 5bd2c771ee..2e04f2d8bc 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -548,34 +548,34 @@ Camera::KeepAspect Camera::get_keep_aspect_mode() const{
void Camera::_bind_methods() {
- ClassDB::bind_method( _MD("project_ray_normal","screen_point"), &Camera::project_ray_normal);
- ClassDB::bind_method( _MD("project_local_ray_normal","screen_point"), &Camera::project_local_ray_normal);
- ClassDB::bind_method( _MD("project_ray_origin","screen_point"), &Camera::project_ray_origin);
- ClassDB::bind_method( _MD("unproject_position","world_point"), &Camera::unproject_position);
- ClassDB::bind_method( _MD("is_position_behind","world_point"), &Camera::is_position_behind);
- ClassDB::bind_method( _MD("project_position","screen_point"), &Camera::project_position);
- ClassDB::bind_method( _MD("set_perspective","fov","z_near","z_far"),&Camera::set_perspective );
- ClassDB::bind_method( _MD("set_orthogonal","size","z_near","z_far"),&Camera::set_orthogonal );
- ClassDB::bind_method( _MD("make_current"),&Camera::make_current );
- ClassDB::bind_method( _MD("clear_current"),&Camera::clear_current );
- ClassDB::bind_method( _MD("is_current"),&Camera::is_current );
- ClassDB::bind_method( _MD("get_camera_transform"),&Camera::get_camera_transform );
- ClassDB::bind_method( _MD("get_fov"),&Camera::get_fov );
- ClassDB::bind_method( _MD("get_size"),&Camera::get_size );
- ClassDB::bind_method( _MD("get_zfar"),&Camera::get_zfar );
- ClassDB::bind_method( _MD("get_znear"),&Camera::get_znear );
- ClassDB::bind_method( _MD("get_projection"),&Camera::get_projection );
- ClassDB::bind_method( _MD("set_h_offset","ofs"),&Camera::set_h_offset );
- ClassDB::bind_method( _MD("get_h_offset"),&Camera::get_h_offset );
- ClassDB::bind_method( _MD("set_v_offset","ofs"),&Camera::set_v_offset );
- ClassDB::bind_method( _MD("get_v_offset"),&Camera::get_v_offset );
- ClassDB::bind_method( _MD("set_cull_mask","mask"),&Camera::set_cull_mask );
- ClassDB::bind_method( _MD("get_cull_mask"),&Camera::get_cull_mask );
- ClassDB::bind_method( _MD("set_environment","env:Environment"),&Camera::set_environment );
- ClassDB::bind_method( _MD("get_environment:Environment"),&Camera::get_environment );
- ClassDB::bind_method( _MD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode );
- ClassDB::bind_method( _MD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode );
- //ClassDB::bind_method( _MD("_camera_make_current"),&Camera::_camera_make_current );
+ ClassDB::bind_method(D_METHOD("project_ray_normal","screen_point"), &Camera::project_ray_normal);
+ ClassDB::bind_method(D_METHOD("project_local_ray_normal","screen_point"), &Camera::project_local_ray_normal);
+ ClassDB::bind_method(D_METHOD("project_ray_origin","screen_point"), &Camera::project_ray_origin);
+ ClassDB::bind_method(D_METHOD("unproject_position","world_point"), &Camera::unproject_position);
+ ClassDB::bind_method(D_METHOD("is_position_behind","world_point"), &Camera::is_position_behind);
+ ClassDB::bind_method(D_METHOD("project_position","screen_point"), &Camera::project_position);
+ ClassDB::bind_method(D_METHOD("set_perspective","fov","z_near","z_far"),&Camera::set_perspective );
+ ClassDB::bind_method(D_METHOD("set_orthogonal","size","z_near","z_far"),&Camera::set_orthogonal );
+ ClassDB::bind_method(D_METHOD("make_current"),&Camera::make_current );
+ ClassDB::bind_method(D_METHOD("clear_current"),&Camera::clear_current );
+ ClassDB::bind_method(D_METHOD("is_current"),&Camera::is_current );
+ ClassDB::bind_method(D_METHOD("get_camera_transform"),&Camera::get_camera_transform );
+ ClassDB::bind_method(D_METHOD("get_fov"),&Camera::get_fov );
+ ClassDB::bind_method(D_METHOD("get_size"),&Camera::get_size );
+ ClassDB::bind_method(D_METHOD("get_zfar"),&Camera::get_zfar );
+ ClassDB::bind_method(D_METHOD("get_znear"),&Camera::get_znear );
+ ClassDB::bind_method(D_METHOD("get_projection"),&Camera::get_projection );
+ ClassDB::bind_method(D_METHOD("set_h_offset","ofs"),&Camera::set_h_offset );
+ ClassDB::bind_method(D_METHOD("get_h_offset"),&Camera::get_h_offset );
+ ClassDB::bind_method(D_METHOD("set_v_offset","ofs"),&Camera::set_v_offset );
+ ClassDB::bind_method(D_METHOD("get_v_offset"),&Camera::get_v_offset );
+ ClassDB::bind_method(D_METHOD("set_cull_mask","mask"),&Camera::set_cull_mask );
+ ClassDB::bind_method(D_METHOD("get_cull_mask"),&Camera::get_cull_mask );
+ ClassDB::bind_method(D_METHOD("set_environment","env:Environment"),&Camera::set_environment );
+ ClassDB::bind_method(D_METHOD("get_environment:Environment"),&Camera::get_environment );
+ ClassDB::bind_method(D_METHOD("set_keep_aspect_mode","mode"),&Camera::set_keep_aspect_mode );
+ ClassDB::bind_method(D_METHOD("get_keep_aspect_mode"),&Camera::get_keep_aspect_mode );
+ //ClassDB::bind_method(D_METHOD("_camera_make_current"),&Camera::_camera_make_current );
BIND_CONSTANT( PROJECTION_PERSPECTIVE );
BIND_CONSTANT( PROJECTION_ORTHOGONAL );
diff --git a/scene/3d/character_camera.cpp b/scene/3d/character_camera.cpp
index 211619d0df..424a7fc79c 100644
--- a/scene/3d/character_camera.cpp
+++ b/scene/3d/character_camera.cpp
@@ -634,30 +634,30 @@ float CharacterCamera::get_autoturn_speed() const {
void CharacterCamera::_bind_methods() {
- ClassDB::bind_method(_MD("set_camera_type","type"),&CharacterCamera::set_camera_type);
- ClassDB::bind_method(_MD("get_camera_type"),&CharacterCamera::get_camera_type);
- ClassDB::bind_method(_MD("set_orbit","orbit"),&CharacterCamera::set_orbit);
- ClassDB::bind_method(_MD("get_orbit"),&CharacterCamera::get_orbit);
- ClassDB::bind_method(_MD("set_orbit_x","x"),&CharacterCamera::set_orbit_x);
- ClassDB::bind_method(_MD("set_orbit_y","y"),&CharacterCamera::set_orbit_y);
- ClassDB::bind_method(_MD("set_min_orbit_x","x"),&CharacterCamera::set_min_orbit_x);
- ClassDB::bind_method(_MD("get_min_orbit_x"),&CharacterCamera::get_min_orbit_x);
- ClassDB::bind_method(_MD("set_max_orbit_x","x"),&CharacterCamera::set_max_orbit_x);
- ClassDB::bind_method(_MD("get_max_orbit_x"),&CharacterCamera::get_max_orbit_x);
- ClassDB::bind_method(_MD("rotate_orbit"),&CharacterCamera::rotate_orbit);
- ClassDB::bind_method(_MD("set_distance","distance"),&CharacterCamera::set_distance);
- ClassDB::bind_method(_MD("get_distance"),&CharacterCamera::get_distance);
- ClassDB::bind_method(_MD("set_clip","enable"),&CharacterCamera::set_clip);
- ClassDB::bind_method(_MD("has_clip"),&CharacterCamera::has_clip);
- ClassDB::bind_method(_MD("set_autoturn","enable"),&CharacterCamera::set_autoturn);
- ClassDB::bind_method(_MD("has_autoturn"),&CharacterCamera::has_autoturn);
- ClassDB::bind_method(_MD("set_autoturn_tolerance","degrees"),&CharacterCamera::set_autoturn_tolerance);
- ClassDB::bind_method(_MD("get_autoturn_tolerance"),&CharacterCamera::get_autoturn_tolerance);
- ClassDB::bind_method(_MD("set_autoturn_speed","speed"),&CharacterCamera::set_autoturn_speed);
- ClassDB::bind_method(_MD("get_autoturn_speed"),&CharacterCamera::get_autoturn_speed);
- ClassDB::bind_method(_MD("set_use_lookat_target","use","lookat"),&CharacterCamera::set_use_lookat_target, DEFVAL(Vector3()));
-
- ClassDB::bind_method(_MD("_ray_collision"),&CharacterCamera::_ray_collision);
+ ClassDB::bind_method(D_METHOD("set_camera_type","type"),&CharacterCamera::set_camera_type);
+ ClassDB::bind_method(D_METHOD("get_camera_type"),&CharacterCamera::get_camera_type);
+ ClassDB::bind_method(D_METHOD("set_orbit","orbit"),&CharacterCamera::set_orbit);
+ ClassDB::bind_method(D_METHOD("get_orbit"),&CharacterCamera::get_orbit);
+ ClassDB::bind_method(D_METHOD("set_orbit_x","x"),&CharacterCamera::set_orbit_x);
+ ClassDB::bind_method(D_METHOD("set_orbit_y","y"),&CharacterCamera::set_orbit_y);
+ ClassDB::bind_method(D_METHOD("set_min_orbit_x","x"),&CharacterCamera::set_min_orbit_x);
+ ClassDB::bind_method(D_METHOD("get_min_orbit_x"),&CharacterCamera::get_min_orbit_x);
+ ClassDB::bind_method(D_METHOD("set_max_orbit_x","x"),&CharacterCamera::set_max_orbit_x);
+ ClassDB::bind_method(D_METHOD("get_max_orbit_x"),&CharacterCamera::get_max_orbit_x);
+ ClassDB::bind_method(D_METHOD("rotate_orbit"),&CharacterCamera::rotate_orbit);
+ ClassDB::bind_method(D_METHOD("set_distance","distance"),&CharacterCamera::set_distance);
+ ClassDB::bind_method(D_METHOD("get_distance"),&CharacterCamera::get_distance);
+ ClassDB::bind_method(D_METHOD("set_clip","enable"),&CharacterCamera::set_clip);
+ ClassDB::bind_method(D_METHOD("has_clip"),&CharacterCamera::has_clip);
+ ClassDB::bind_method(D_METHOD("set_autoturn","enable"),&CharacterCamera::set_autoturn);
+ ClassDB::bind_method(D_METHOD("has_autoturn"),&CharacterCamera::has_autoturn);
+ ClassDB::bind_method(D_METHOD("set_autoturn_tolerance","degrees"),&CharacterCamera::set_autoturn_tolerance);
+ ClassDB::bind_method(D_METHOD("get_autoturn_tolerance"),&CharacterCamera::get_autoturn_tolerance);
+ ClassDB::bind_method(D_METHOD("set_autoturn_speed","speed"),&CharacterCamera::set_autoturn_speed);
+ ClassDB::bind_method(D_METHOD("get_autoturn_speed"),&CharacterCamera::get_autoturn_speed);
+ ClassDB::bind_method(D_METHOD("set_use_lookat_target","use","lookat"),&CharacterCamera::set_use_lookat_target, DEFVAL(Vector3()));
+
+ ClassDB::bind_method(D_METHOD("_ray_collision"),&CharacterCamera::_ray_collision);
BIND_CONSTANT( CAMERA_FIXED );
BIND_CONSTANT( CAMERA_FOLLOW );
diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp
index 7bba382db0..32e60f0d57 100644
--- a/scene/3d/collision_object.cpp
+++ b/scene/3d/collision_object.cpp
@@ -228,30 +228,30 @@ bool CollisionObject::is_ray_pickable() const {
void CollisionObject::_bind_methods() {
- ClassDB::bind_method(_MD("add_shape","shape:Shape","transform"),&CollisionObject::add_shape,DEFVAL(Transform()));
- ClassDB::bind_method(_MD("get_shape_count"),&CollisionObject::get_shape_count);
- ClassDB::bind_method(_MD("set_shape","shape_idx","shape:Shape"),&CollisionObject::set_shape);
- ClassDB::bind_method(_MD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform);
-// ClassDB::bind_method(_MD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform);
- ClassDB::bind_method(_MD("set_shape_as_trigger","shape_idx","enable"),&CollisionObject::set_shape_as_trigger);
- ClassDB::bind_method(_MD("is_shape_set_as_trigger","shape_idx"),&CollisionObject::is_shape_set_as_trigger);
- ClassDB::bind_method(_MD("get_shape:Shape","shape_idx"),&CollisionObject::get_shape);
- ClassDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform);
- ClassDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape);
- ClassDB::bind_method(_MD("clear_shapes"),&CollisionObject::clear_shapes);
- ClassDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&CollisionObject::set_ray_pickable);
- ClassDB::bind_method(_MD("is_ray_pickable"),&CollisionObject::is_ray_pickable);
- ClassDB::bind_method(_MD("set_capture_input_on_drag","enable"),&CollisionObject::set_capture_input_on_drag);
- ClassDB::bind_method(_MD("get_capture_input_on_drag"),&CollisionObject::get_capture_input_on_drag);
- ClassDB::bind_method(_MD("get_rid"),&CollisionObject::get_rid);
+ ClassDB::bind_method(D_METHOD("add_shape","shape:Shape","transform"),&CollisionObject::add_shape,DEFVAL(Transform()));
+ ClassDB::bind_method(D_METHOD("get_shape_count"),&CollisionObject::get_shape_count);
+ ClassDB::bind_method(D_METHOD("set_shape","shape_idx","shape:Shape"),&CollisionObject::set_shape);
+ ClassDB::bind_method(D_METHOD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform);
+// ClassDB::bind_method(D_METHOD("set_shape_transform","shape_idx","transform"),&CollisionObject::set_shape_transform);
+ ClassDB::bind_method(D_METHOD("set_shape_as_trigger","shape_idx","enable"),&CollisionObject::set_shape_as_trigger);
+ ClassDB::bind_method(D_METHOD("is_shape_set_as_trigger","shape_idx"),&CollisionObject::is_shape_set_as_trigger);
+ ClassDB::bind_method(D_METHOD("get_shape:Shape","shape_idx"),&CollisionObject::get_shape);
+ ClassDB::bind_method(D_METHOD("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform);
+ ClassDB::bind_method(D_METHOD("remove_shape","shape_idx"),&CollisionObject::remove_shape);
+ ClassDB::bind_method(D_METHOD("clear_shapes"),&CollisionObject::clear_shapes);
+ ClassDB::bind_method(D_METHOD("set_ray_pickable","ray_pickable"),&CollisionObject::set_ray_pickable);
+ ClassDB::bind_method(D_METHOD("is_ray_pickable"),&CollisionObject::is_ray_pickable);
+ ClassDB::bind_method(D_METHOD("set_capture_input_on_drag","enable"),&CollisionObject::set_capture_input_on_drag);
+ ClassDB::bind_method(D_METHOD("get_capture_input_on_drag"),&CollisionObject::get_capture_input_on_drag);
+ ClassDB::bind_method(D_METHOD("get_rid"),&CollisionObject::get_rid);
BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
ADD_SIGNAL( MethodInfo("mouse_entered"));
ADD_SIGNAL( MethodInfo("mouse_exited"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input_ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"input_capture_on_drag"),_SCS("set_capture_input_on_drag"),_SCS("get_capture_input_on_drag"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input_ray_pickable"),"set_ray_pickable","is_ray_pickable");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"input_capture_on_drag"),"set_capture_input_on_drag","get_capture_input_on_drag");
}
@@ -334,6 +334,7 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) {
area=p_area;
capture_input_on_drag=false;
ray_pickable=true;
+ set_notify_transform(true);
if (p_area) {
PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
} else {
diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp
index d0612986df..82637c2488 100644
--- a/scene/3d/collision_polygon.cpp
+++ b/scene/3d/collision_polygon.cpp
@@ -275,27 +275,27 @@ String CollisionPolygon::get_configuration_warning() const {
void CollisionPolygon::_bind_methods() {
- ClassDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object);
+ ClassDB::bind_method(D_METHOD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object);
- ClassDB::bind_method(_MD("set_build_mode","build_mode"),&CollisionPolygon::set_build_mode);
- ClassDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode);
+ ClassDB::bind_method(D_METHOD("set_build_mode","build_mode"),&CollisionPolygon::set_build_mode);
+ ClassDB::bind_method(D_METHOD("get_build_mode"),&CollisionPolygon::get_build_mode);
- ClassDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth);
- ClassDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_depth);
+ ClassDB::bind_method(D_METHOD("set_depth","depth"),&CollisionPolygon::set_depth);
+ ClassDB::bind_method(D_METHOD("get_depth"),&CollisionPolygon::get_depth);
- ClassDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon);
- ClassDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon);
+ ClassDB::bind_method(D_METHOD("set_polygon","polygon"),&CollisionPolygon::set_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon"),&CollisionPolygon::get_polygon);
- ClassDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon::_set_shape_range);
- ClassDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon::_get_shape_range);
+ ClassDB::bind_method(D_METHOD("_set_shape_range","shape_range"),&CollisionPolygon::_set_shape_range);
+ ClassDB::bind_method(D_METHOD("_get_shape_range"),&CollisionPolygon::_get_shape_range);
- ClassDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon::get_collision_object_first_shape);
- ClassDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon::get_collision_object_last_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_object_first_shape"),&CollisionPolygon::get_collision_object_first_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_object_last_shape"),&CollisionPolygon::get_collision_object_last_shape);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),_SCS("set_build_mode"),_SCS("get_build_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),_SCS("set_depth"),_SCS("get_depth"));
- ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),"set_build_mode","get_build_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),"set_depth","get_depth");
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"polygon"),"set_polygon","get_polygon");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_shape_range","_get_shape_range");
}
CollisionPolygon::CollisionPolygon() {
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 4c33590568..b22795e74d 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -1,4 +1,33 @@
+/*************************************************************************/
+/* gi_probe.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "gi_probe.h"
+
#include "mesh_instance.h"
@@ -64,6 +93,19 @@ float GIProbeData::get_energy() const{
}
+
+void GIProbeData::set_bias(float p_range) {
+
+ VS::get_singleton()->gi_probe_set_bias(probe,p_range);
+}
+
+float GIProbeData::get_bias() const{
+
+ return VS::get_singleton()->gi_probe_get_bias(probe);
+
+}
+
+
void GIProbeData::set_propagation(float p_range) {
VS::get_singleton()->gi_probe_set_propagation(probe,p_range);
@@ -115,43 +157,47 @@ RID GIProbeData::get_rid() const {
void GIProbeData::_bind_methods() {
- ClassDB::bind_method(_MD("set_bounds","bounds"),&GIProbeData::set_bounds);
- ClassDB::bind_method(_MD("get_bounds"),&GIProbeData::get_bounds);
+ ClassDB::bind_method(D_METHOD("set_bounds","bounds"),&GIProbeData::set_bounds);
+ ClassDB::bind_method(D_METHOD("get_bounds"),&GIProbeData::get_bounds);
+
+ ClassDB::bind_method(D_METHOD("set_cell_size","cell_size"),&GIProbeData::set_cell_size);
+ ClassDB::bind_method(D_METHOD("get_cell_size"),&GIProbeData::get_cell_size);
- ClassDB::bind_method(_MD("set_cell_size","cell_size"),&GIProbeData::set_cell_size);
- ClassDB::bind_method(_MD("get_cell_size"),&GIProbeData::get_cell_size);
+ ClassDB::bind_method(D_METHOD("set_to_cell_xform","to_cell_xform"),&GIProbeData::set_to_cell_xform);
+ ClassDB::bind_method(D_METHOD("get_to_cell_xform"),&GIProbeData::get_to_cell_xform);
- ClassDB::bind_method(_MD("set_to_cell_xform","to_cell_xform"),&GIProbeData::set_to_cell_xform);
- ClassDB::bind_method(_MD("get_to_cell_xform"),&GIProbeData::get_to_cell_xform);
+ ClassDB::bind_method(D_METHOD("set_dynamic_data","dynamic_data"),&GIProbeData::set_dynamic_data);
+ ClassDB::bind_method(D_METHOD("get_dynamic_data"),&GIProbeData::get_dynamic_data);
- ClassDB::bind_method(_MD("set_dynamic_data","dynamic_data"),&GIProbeData::set_dynamic_data);
- ClassDB::bind_method(_MD("get_dynamic_data"),&GIProbeData::get_dynamic_data);
+ ClassDB::bind_method(D_METHOD("set_dynamic_range","dynamic_range"),&GIProbeData::set_dynamic_range);
+ ClassDB::bind_method(D_METHOD("get_dynamic_range"),&GIProbeData::get_dynamic_range);
- ClassDB::bind_method(_MD("set_dynamic_range","dynamic_range"),&GIProbeData::set_dynamic_range);
- ClassDB::bind_method(_MD("get_dynamic_range"),&GIProbeData::get_dynamic_range);
+ ClassDB::bind_method(D_METHOD("set_energy","energy"),&GIProbeData::set_energy);
+ ClassDB::bind_method(D_METHOD("get_energy"),&GIProbeData::get_energy);
- ClassDB::bind_method(_MD("set_energy","energy"),&GIProbeData::set_energy);
- ClassDB::bind_method(_MD("get_energy"),&GIProbeData::get_energy);
+ ClassDB::bind_method(D_METHOD("set_bias","bias"),&GIProbeData::set_bias);
+ ClassDB::bind_method(D_METHOD("get_bias"),&GIProbeData::get_bias);
- ClassDB::bind_method(_MD("set_propagation","propagation"),&GIProbeData::set_propagation);
- ClassDB::bind_method(_MD("get_propagation"),&GIProbeData::get_propagation);
+ ClassDB::bind_method(D_METHOD("set_propagation","propagation"),&GIProbeData::set_propagation);
+ ClassDB::bind_method(D_METHOD("get_propagation"),&GIProbeData::get_propagation);
- ClassDB::bind_method(_MD("set_interior","interior"),&GIProbeData::set_interior);
- ClassDB::bind_method(_MD("is_interior"),&GIProbeData::is_interior);
+ ClassDB::bind_method(D_METHOD("set_interior","interior"),&GIProbeData::set_interior);
+ ClassDB::bind_method(D_METHOD("is_interior"),&GIProbeData::is_interior);
- ClassDB::bind_method(_MD("set_compress","compress"),&GIProbeData::set_compress);
- ClassDB::bind_method(_MD("is_compressed"),&GIProbeData::is_compressed);
+ ClassDB::bind_method(D_METHOD("set_compress","compress"),&GIProbeData::set_compress);
+ ClassDB::bind_method(D_METHOD("is_compressed"),&GIProbeData::is_compressed);
- ADD_PROPERTY(PropertyInfo(Variant::RECT3,"bounds",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_bounds"),_SCS("get_bounds"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"cell_size",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_cell_size"),_SCS("get_cell_size"));
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM,"to_cell_xform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_to_cell_xform"),_SCS("get_to_cell_xform"));
+ ADD_PROPERTY(PropertyInfo(Variant::RECT3,"bounds",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_bounds","get_bounds");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"cell_size",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_cell_size","get_cell_size");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM,"to_cell_xform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_to_cell_xform","get_to_cell_xform");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY,"dynamic_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_dynamic_data"),_SCS("get_dynamic_data"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_dynamic_range"),_SCS("get_dynamic_range"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_energy"),_SCS("get_energy"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"propagation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_propagation"),_SCS("get_propagation"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"interior",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_interior"),_SCS("is_interior"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"compress",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_compress"),_SCS("is_compressed"));
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY,"dynamic_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_dynamic_data","get_dynamic_data");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_dynamic_range","get_dynamic_range");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_energy","get_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"bias",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_bias","get_bias");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"propagation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_propagation","get_propagation");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"interior",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_interior","is_interior");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"compress",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_compress","is_compressed");
}
@@ -230,6 +276,18 @@ float GIProbe::get_energy() const {
return energy;
}
+void GIProbe::set_bias(float p_bias) {
+
+ bias=p_bias;
+ if (probe_data.is_valid()) {
+ probe_data->set_bias(bias);
+ }
+}
+float GIProbe::get_bias() const {
+
+ return bias;
+}
+
void GIProbe::set_propagation(float p_propagation) {
propagation=p_propagation;
@@ -466,7 +524,8 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
int closest_axis;
float closest_dot;
- Vector3 normal = Plane(p_vtx[0],p_vtx[1],p_vtx[2]).normal;
+ Plane plane = Plane(p_vtx[0],p_vtx[1],p_vtx[2]);
+ Vector3 normal = plane.normal;
for(int i=0;i<3;i++) {
@@ -479,6 +538,7 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
}
}
+
Vector3 axis;
axis[closest_axis]=1.0;
Vector3 t1;
@@ -517,24 +577,23 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
Vector3 ray_from = from + (t1+t2)*0.5 - axis * p_aabb.size[closest_axis];
Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis]*2;
+ if (normal.dot(ray_from-ray_to)<0) {
+ SWAP(ray_from,ray_to);
+ }
+
Vector3 intersection;
- if (!Geometry::ray_intersects_triangle(ray_from,ray_to,p_vtx[0],p_vtx[1],p_vtx[2],&intersection)) {
- //no intersect? look in edges
-
- float closest_dist=1e20;
- for(int j=0;j<3;j++) {
- Vector3 c;
- Vector3 inters;
- Geometry::get_closest_points_between_segments(p_vtx[j],p_vtx[(j+1)%3],ray_from,ray_to,inters,c);
- float d=c.distance_to(intersection);
- if (j==0 || d<closest_dist) {
- closest_dist=d;
- intersection=inters;
- }
+ if (!plane.intersects_segment(ray_from,ray_to,&intersection)) {
+ if (ABS(plane.distance_to(ray_from)) < ABS(plane.distance_to(ray_to))) {
+ intersection = plane.project(ray_from);
+ } else {
+
+ intersection = plane.project(ray_to);
}
}
+ intersection=Face3(p_vtx[0],p_vtx[1],p_vtx[2]).get_closest_point_to(intersection);
+
Vector2 uv = get_uv(intersection,p_vtx,p_uv);
@@ -856,6 +915,10 @@ Vector<Color> GIProbe::_get_bake_texture(Image &p_image,const Color& p_color) {
return ret;
}
+ if (p_image.is_compressed()) {
+ print_line("DECOMPRESSING!!!!");
+ p_image.decompress();
+ }
p_image.convert(Image::FORMAT_RGBA8);
p_image.resize(bake_texture_size,bake_texture_size,Image::INTERPOLATE_CUBIC);
@@ -892,13 +955,14 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater
if (mat.is_valid()) {
-
- Ref<ImageTexture> albedo_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_ALBEDO);
+ Ref<Texture> albedo_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_ALBEDO);
Image img_albedo;
if (albedo_tex.is_valid()) {
img_albedo = albedo_tex->get_data();
+ } else {
+
}
mc.albedo=_get_bake_texture(img_albedo,mat->get_albedo());
@@ -950,6 +1014,7 @@ void GIProbe::_plot_mesh(const Transform& p_xform, Ref<Mesh>& p_mesh, Baker *p_b
src_material=p_materials[i];
} else {
src_material=p_mesh->surface_get_material(i);
+
}
Baker::MaterialCache material = _get_material_cache(src_material,p_baker);
@@ -1056,6 +1121,31 @@ void GIProbe::_find_meshes(Node *p_at_node,Baker *p_baker){
}
}
+ if (p_at_node->cast_to<Spatial>()) {
+
+ Spatial *s = p_at_node->cast_to<Spatial>();
+ Array meshes = p_at_node->call("get_meshes");
+ for(int i=0;i<meshes.size();i+=2) {
+
+ Transform mxf = meshes[i];
+ Ref<Mesh> mesh = meshes[i+1];
+ if (!mesh.is_valid())
+ continue;
+
+ Rect3 aabb = mesh->get_aabb();
+
+ Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf);
+
+ if (Rect3(-extents,extents*2).intersects(xf.xform(aabb))) {
+ Baker::PlotMesh pm;
+ pm.local_xform=xf;
+ pm.mesh=mesh;
+ p_baker->mesh_list.push_back(pm);
+
+ }
+ }
+ }
+
for(int i=0;i<p_at_node->get_child_count();i++) {
Node *child = p_at_node->get_child(i);
@@ -1208,26 +1298,30 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug){
}
- Ref<GIProbeData> probe_data;
- probe_data.instance();
- probe_data->set_bounds(Rect3(-extents,extents*2.0));
- probe_data->set_cell_size(baker.po2_bounds.size[longest_axis]/baker.axis_cell_size[longest_axis]);
- probe_data->set_dynamic_data(data);
- probe_data->set_dynamic_range(dynamic_range);
- probe_data->set_energy(energy);
- probe_data->set_interior(interior);
- probe_data->set_compress(compress);
- probe_data->set_to_cell_xform(baker.to_cell_space);
-
- set_probe_data(probe_data);
+ if (p_create_visual_debug) {
+ _create_debug_mesh(&baker);
+ } else {
+ Ref<GIProbeData> probe_data;
+ probe_data.instance();
+ probe_data->set_bounds(Rect3(-extents,extents*2.0));
+ probe_data->set_cell_size(baker.po2_bounds.size[longest_axis]/baker.axis_cell_size[longest_axis]);
+ probe_data->set_dynamic_data(data);
+ probe_data->set_dynamic_range(dynamic_range);
+ probe_data->set_energy(energy);
+ probe_data->set_bias(bias);
+ probe_data->set_propagation(propagation);
+ probe_data->set_interior(interior);
+ probe_data->set_compress(compress);
+ probe_data->set_to_cell_xform(baker.to_cell_space);
- if (p_create_visual_debug) {
- //_create_debug_mesh(&baker);
+ set_probe_data(probe_data);
}
+
+
}
@@ -1384,42 +1478,46 @@ PoolVector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
void GIProbe::_bind_methods() {
- ClassDB::bind_method(_MD("set_probe_data","data"),&GIProbe::set_probe_data);
- ClassDB::bind_method(_MD("get_probe_data"),&GIProbe::get_probe_data);
+ ClassDB::bind_method(D_METHOD("set_probe_data","data"),&GIProbe::set_probe_data);
+ ClassDB::bind_method(D_METHOD("get_probe_data"),&GIProbe::get_probe_data);
+
+ ClassDB::bind_method(D_METHOD("set_subdiv","subdiv"),&GIProbe::set_subdiv);
+ ClassDB::bind_method(D_METHOD("get_subdiv"),&GIProbe::get_subdiv);
- ClassDB::bind_method(_MD("set_subdiv","subdiv"),&GIProbe::set_subdiv);
- ClassDB::bind_method(_MD("get_subdiv"),&GIProbe::get_subdiv);
+ ClassDB::bind_method(D_METHOD("set_extents","extents"),&GIProbe::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"),&GIProbe::get_extents);
- ClassDB::bind_method(_MD("set_extents","extents"),&GIProbe::set_extents);
- ClassDB::bind_method(_MD("get_extents"),&GIProbe::get_extents);
+ ClassDB::bind_method(D_METHOD("set_dynamic_range","max"),&GIProbe::set_dynamic_range);
+ ClassDB::bind_method(D_METHOD("get_dynamic_range"),&GIProbe::get_dynamic_range);
- ClassDB::bind_method(_MD("set_dynamic_range","max"),&GIProbe::set_dynamic_range);
- ClassDB::bind_method(_MD("get_dynamic_range"),&GIProbe::get_dynamic_range);
+ ClassDB::bind_method(D_METHOD("set_energy","max"),&GIProbe::set_energy);
+ ClassDB::bind_method(D_METHOD("get_energy"),&GIProbe::get_energy);
- ClassDB::bind_method(_MD("set_energy","max"),&GIProbe::set_energy);
- ClassDB::bind_method(_MD("get_energy"),&GIProbe::get_energy);
+ ClassDB::bind_method(D_METHOD("set_bias","max"),&GIProbe::set_bias);
+ ClassDB::bind_method(D_METHOD("get_bias"),&GIProbe::get_bias);
- ClassDB::bind_method(_MD("set_propagation","max"),&GIProbe::set_propagation);
- ClassDB::bind_method(_MD("get_propagation"),&GIProbe::get_propagation);
+ ClassDB::bind_method(D_METHOD("set_propagation","max"),&GIProbe::set_propagation);
+ ClassDB::bind_method(D_METHOD("get_propagation"),&GIProbe::get_propagation);
- ClassDB::bind_method(_MD("set_interior","enable"),&GIProbe::set_interior);
- ClassDB::bind_method(_MD("is_interior"),&GIProbe::is_interior);
+ ClassDB::bind_method(D_METHOD("set_interior","enable"),&GIProbe::set_interior);
+ ClassDB::bind_method(D_METHOD("is_interior"),&GIProbe::is_interior);
- ClassDB::bind_method(_MD("set_compress","enable"),&GIProbe::set_compress);
- ClassDB::bind_method(_MD("is_compressed"),&GIProbe::is_compressed);
+ ClassDB::bind_method(D_METHOD("set_compress","enable"),&GIProbe::set_compress);
+ ClassDB::bind_method(D_METHOD("is_compressed"),&GIProbe::is_compressed);
- ClassDB::bind_method(_MD("bake","from_node","create_visual_debug"),&GIProbe::bake,DEFVAL(Variant()),DEFVAL(false));
- ClassDB::bind_method(_MD("debug_bake"),&GIProbe::_debug_bake);
- ClassDB::set_method_flags(get_class_static(),_SCS("debug_bake"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("bake","from_node","create_visual_debug"),&GIProbe::bake,DEFVAL(Variant()),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("debug_bake"),&GIProbe::_debug_bake);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("debug_bake"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"subdiv",PROPERTY_HINT_ENUM,"64,128,256,512"),_SCS("set_subdiv"),_SCS("get_subdiv"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"extents"),_SCS("set_extents"),_SCS("get_extents"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_RANGE,"1,16,1"),_SCS("set_dynamic_range"),_SCS("get_dynamic_range"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_energy"),_SCS("get_energy"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"propagation",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_propagation"),_SCS("get_propagation"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior"),_SCS("set_interior"),_SCS("is_interior"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"compress"),_SCS("set_compress"),_SCS("is_compressed"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"data",PROPERTY_HINT_RESOURCE_TYPE,"GIProbeData"),_SCS("set_probe_data"),_SCS("get_probe_data"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"subdiv",PROPERTY_HINT_ENUM,"64,128,256,512"),"set_subdiv","get_subdiv");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"extents"),"set_extents","get_extents");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_RANGE,"1,16,1"),"set_dynamic_range","get_dynamic_range");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_energy","get_energy");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"propagation",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_propagation","get_propagation");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"bias",PROPERTY_HINT_RANGE,"0,4,0.001"),"set_bias","get_bias");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior"),"set_interior","is_interior");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"compress"),"set_compress","is_compressed");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"data",PROPERTY_HINT_RESOURCE_TYPE,"GIProbeData"),"set_probe_data","get_probe_data");
BIND_CONSTANT( SUBDIV_64 );
@@ -1434,6 +1532,7 @@ GIProbe::GIProbe() {
subdiv=SUBDIV_128;
dynamic_range=4;
energy=1.0;
+ bias=0.4;
propagation=1.0;
extents=Vector3(10,10,10);
color_scan_cell_width=4;
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index f03a558908..a45e80806a 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* gi_probe.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 GIPROBE_H
#define GIPROBE_H
@@ -38,6 +66,9 @@ public:
void set_energy(float p_range);
float get_energy() const;
+ void set_bias(float p_range);
+ float get_bias() const;
+
void set_interior(bool p_enable);
bool is_interior() const;
@@ -137,6 +168,7 @@ private:
Vector3 extents;
int dynamic_range;
float energy;
+ float bias;
float propagation;
bool interior;
bool compress;
@@ -176,6 +208,9 @@ public:
void set_energy(float p_energy);
float get_energy() const;
+ void set_bias(float p_bias);
+ float get_bias() const;
+
void set_propagation(float p_propagation);
float get_propagation() const;
diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp
index 08fc1f59e8..6adbbe9ccf 100644
--- a/scene/3d/immediate_geometry.cpp
+++ b/scene/3d/immediate_geometry.cpp
@@ -154,16 +154,16 @@ void ImmediateGeometry::add_sphere(int p_lats, int p_lons, float p_radius, bool
void ImmediateGeometry::_bind_methods() {
- ClassDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin,DEFVAL(Ref<Texture>()));
- ClassDB::bind_method(_MD("set_normal","normal"),&ImmediateGeometry::set_normal);
- ClassDB::bind_method(_MD("set_tangent","tangent"),&ImmediateGeometry::set_tangent);
- ClassDB::bind_method(_MD("set_color","color"),&ImmediateGeometry::set_color);
- ClassDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv);
- ClassDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2);
- ClassDB::bind_method(_MD("add_vertex","pos"),&ImmediateGeometry::add_vertex);
- ClassDB::bind_method(_MD("add_sphere","lats","lons","radius","add_uv"),&ImmediateGeometry::add_sphere,DEFVAL(true));
- ClassDB::bind_method(_MD("end"),&ImmediateGeometry::end);
- ClassDB::bind_method(_MD("clear"),&ImmediateGeometry::clear);
+ ClassDB::bind_method(D_METHOD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin,DEFVAL(Ref<Texture>()));
+ ClassDB::bind_method(D_METHOD("set_normal","normal"),&ImmediateGeometry::set_normal);
+ ClassDB::bind_method(D_METHOD("set_tangent","tangent"),&ImmediateGeometry::set_tangent);
+ ClassDB::bind_method(D_METHOD("set_color","color"),&ImmediateGeometry::set_color);
+ ClassDB::bind_method(D_METHOD("set_uv","uv"),&ImmediateGeometry::set_uv);
+ ClassDB::bind_method(D_METHOD("set_uv2","uv"),&ImmediateGeometry::set_uv2);
+ ClassDB::bind_method(D_METHOD("add_vertex","pos"),&ImmediateGeometry::add_vertex);
+ ClassDB::bind_method(D_METHOD("add_sphere","lats","lons","radius","add_uv"),&ImmediateGeometry::add_sphere,DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("end"),&ImmediateGeometry::end);
+ ClassDB::bind_method(D_METHOD("clear"),&ImmediateGeometry::clear);
}
diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp
index c7464d3c5d..15ee971b7e 100644
--- a/scene/3d/interpolated_camera.cpp
+++ b/scene/3d/interpolated_camera.cpp
@@ -134,19 +134,19 @@ real_t InterpolatedCamera::get_speed() const {
void InterpolatedCamera::_bind_methods() {
- ClassDB::bind_method(_MD("set_target_path","target_path"),&InterpolatedCamera::set_target_path);
- ClassDB::bind_method(_MD("get_target_path"),&InterpolatedCamera::get_target_path);
- ClassDB::bind_method(_MD("set_target","target:Camera"),&InterpolatedCamera::_set_target);
+ ClassDB::bind_method(D_METHOD("set_target_path","target_path"),&InterpolatedCamera::set_target_path);
+ ClassDB::bind_method(D_METHOD("get_target_path"),&InterpolatedCamera::get_target_path);
+ ClassDB::bind_method(D_METHOD("set_target","target:Camera"),&InterpolatedCamera::_set_target);
- ClassDB::bind_method(_MD("set_speed","speed"),&InterpolatedCamera::set_speed);
- ClassDB::bind_method(_MD("get_speed"),&InterpolatedCamera::get_speed);
+ ClassDB::bind_method(D_METHOD("set_speed","speed"),&InterpolatedCamera::set_speed);
+ ClassDB::bind_method(D_METHOD("get_speed"),&InterpolatedCamera::get_speed);
- ClassDB::bind_method(_MD("set_interpolation_enabled","target_path"),&InterpolatedCamera::set_interpolation_enabled);
- ClassDB::bind_method(_MD("is_interpolation_enabled"),&InterpolatedCamera::is_interpolation_enabled);
+ ClassDB::bind_method(D_METHOD("set_interpolation_enabled","target_path"),&InterpolatedCamera::set_interpolation_enabled);
+ ClassDB::bind_method(D_METHOD("is_interpolation_enabled"),&InterpolatedCamera::is_interpolation_enabled);
- ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"target"), _SCS("set_target_path"), _SCS("get_target_path") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"speed"), _SCS("set_speed"), _SCS("get_speed") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"), _SCS("set_interpolation_enabled"), _SCS("is_interpolation_enabled") );
+ ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"target"), "set_target_path", "get_target_path") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"speed"), "set_speed", "get_speed") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"), "set_interpolation_enabled", "is_interpolation_enabled") ;
}
InterpolatedCamera::InterpolatedCamera() {
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 799c00d266..473bca8d3b 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "light.h"
-#include "globals.h"
+#include "global_config.h"
#include "scene/resources/surface_tool.h"
#include "baked_light_instance.h"
@@ -221,42 +221,42 @@ bool Light::is_editor_only() const{
void Light::_bind_methods() {
- ClassDB::bind_method(_MD("set_editor_only","editor_only"), &Light::set_editor_only );
- ClassDB::bind_method(_MD("is_editor_only"), &Light::is_editor_only );
+ ClassDB::bind_method(D_METHOD("set_editor_only","editor_only"), &Light::set_editor_only );
+ ClassDB::bind_method(D_METHOD("is_editor_only"), &Light::is_editor_only );
- ClassDB::bind_method(_MD("set_param","param","value"), &Light::set_param );
- ClassDB::bind_method(_MD("get_param","param"), &Light::get_param );
+ ClassDB::bind_method(D_METHOD("set_param","param","value"), &Light::set_param );
+ ClassDB::bind_method(D_METHOD("get_param","param"), &Light::get_param );
- ClassDB::bind_method(_MD("set_shadow","enabled"), &Light::set_shadow );
- ClassDB::bind_method(_MD("has_shadow"), &Light::has_shadow );
+ ClassDB::bind_method(D_METHOD("set_shadow","enabled"), &Light::set_shadow );
+ ClassDB::bind_method(D_METHOD("has_shadow"), &Light::has_shadow );
- ClassDB::bind_method(_MD("set_negative","enabled"), &Light::set_negative );
- ClassDB::bind_method(_MD("is_negative"), &Light::is_negative );
+ ClassDB::bind_method(D_METHOD("set_negative","enabled"), &Light::set_negative );
+ ClassDB::bind_method(D_METHOD("is_negative"), &Light::is_negative );
- ClassDB::bind_method(_MD("set_cull_mask","cull_mask"), &Light::set_cull_mask );
- ClassDB::bind_method(_MD("get_cull_mask"), &Light::get_cull_mask );
+ ClassDB::bind_method(D_METHOD("set_cull_mask","cull_mask"), &Light::set_cull_mask );
+ ClassDB::bind_method(D_METHOD("get_cull_mask"), &Light::get_cull_mask );
- ClassDB::bind_method(_MD("set_color","color"), &Light::set_color );
- ClassDB::bind_method(_MD("get_color"), &Light::get_color );
+ ClassDB::bind_method(D_METHOD("set_color","color"), &Light::set_color );
+ ClassDB::bind_method(D_METHOD("get_color"), &Light::get_color );
- ClassDB::bind_method(_MD("set_shadow_color","shadow_color"), &Light::set_shadow_color );
- ClassDB::bind_method(_MD("get_shadow_color"), &Light::get_shadow_color );
+ ClassDB::bind_method(D_METHOD("set_shadow_color","shadow_color"), &Light::set_shadow_color );
+ ClassDB::bind_method(D_METHOD("get_shadow_color"), &Light::get_shadow_color );
ADD_GROUP("Light","light_");
- ADD_PROPERTY( PropertyInfo( Variant::COLOR, "light_color",PROPERTY_HINT_COLOR_NO_ALPHA), _SCS("set_color"), _SCS("get_color"));
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light_energy",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_ENERGY);
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "light_negative"), _SCS("set_negative"), _SCS("is_negative"));
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light_specular",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SPECULAR);
- ADD_PROPERTY( PropertyInfo( Variant::INT, "light_cull_mask",PROPERTY_HINT_LAYERS_3D_RENDER), _SCS("set_cull_mask"), _SCS("get_cull_mask"));
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "light_color",PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color");
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light_energy",PROPERTY_HINT_RANGE,"0,16,0.01"), "set_param", "get_param", PARAM_ENERGY);
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "light_negative"), "set_negative", "is_negative");
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light_specular",PROPERTY_HINT_RANGE,"0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR);
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "light_cull_mask",PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_GROUP("Shadow","shadow_");
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow_enabled"), _SCS("set_shadow"), _SCS("has_shadow"));
- ADD_PROPERTY( PropertyInfo( Variant::COLOR, "shadow_color",PROPERTY_HINT_COLOR_NO_ALPHA), _SCS("set_shadow_color"), _SCS("get_shadow_color"));
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_bias",PROPERTY_HINT_RANGE,"-16,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_contact",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_CONTACT_SHADOW_SIZE);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_max_distance",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_MAX_DISTANCE);
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "shadow_color",PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color");
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_bias",PROPERTY_HINT_RANGE,"-16,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_contact",PROPERTY_HINT_RANGE,"0,16,0.01"), "set_param", "get_param", PARAM_CONTACT_SHADOW_SIZE);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow_max_distance",PROPERTY_HINT_RANGE,"0,65536,0.1"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
ADD_GROUP("Editor","");
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editor_only"), _SCS("set_editor_only"), _SCS("is_editor_only"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
ADD_GROUP("","");
BIND_CONSTANT( PARAM_ENERGY );
@@ -352,20 +352,20 @@ bool DirectionalLight::is_blend_splits_enabled() const {
void DirectionalLight::_bind_methods() {
- ClassDB::bind_method( _MD("set_shadow_mode","mode"),&DirectionalLight::set_shadow_mode);
- ClassDB::bind_method( _MD("get_shadow_mode"),&DirectionalLight::get_shadow_mode);
+ ClassDB::bind_method( D_METHOD("set_shadow_mode","mode"),&DirectionalLight::set_shadow_mode);
+ ClassDB::bind_method( D_METHOD("get_shadow_mode"),&DirectionalLight::get_shadow_mode);
- ClassDB::bind_method( _MD("set_blend_splits","enabled"),&DirectionalLight::set_blend_splits);
- ClassDB::bind_method( _MD("is_blend_splits_enabled"),&DirectionalLight::is_blend_splits_enabled);
+ ClassDB::bind_method( D_METHOD("set_blend_splits","enabled"),&DirectionalLight::set_blend_splits);
+ ClassDB::bind_method( D_METHOD("is_blend_splits_enabled"),&DirectionalLight::is_blend_splits_enabled);
ADD_GROUP("Directional Shadow","directional_shadow_");
- ADD_PROPERTY( PropertyInfo( Variant::INT, "directional_shadow_mode",PROPERTY_HINT_ENUM,"Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), _SCS("set_shadow_mode"), _SCS("get_shadow_mode"));
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_split_1",PROPERTY_HINT_RANGE,"0,1,0.001"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_1_OFFSET);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_split_2",PROPERTY_HINT_RANGE,"0,1,0.001"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_2_OFFSET);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_split_3",PROPERTY_HINT_RANGE,"0,1,0.001"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_3_OFFSET);
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "directional_shadow_blend_splits"), _SCS("set_blend_splits"), _SCS("is_blend_splits_enabled"));
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_normal_bias",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_NORMAL_BIAS);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_bias_split_scale",PROPERTY_HINT_RANGE,"0,16,0.01"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS_SPLIT_SCALE);
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "directional_shadow_mode",PROPERTY_HINT_ENUM,"Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), "set_shadow_mode", "get_shadow_mode");
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_split_1",PROPERTY_HINT_RANGE,"0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_split_2",PROPERTY_HINT_RANGE,"0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_split_3",PROPERTY_HINT_RANGE,"0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_normal_bias",PROPERTY_HINT_RANGE,"0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional_shadow_bias_split_scale",PROPERTY_HINT_RANGE,"0,16,0.01"), "set_param", "get_param", PARAM_SHADOW_BIAS_SPLIT_SCALE);
BIND_CONSTANT( SHADOW_ORTHOGONAL );
BIND_CONSTANT( SHADOW_PARALLEL_2_SPLITS );
@@ -406,17 +406,17 @@ OmniLight::ShadowDetail OmniLight::get_shadow_detail() const{
void OmniLight::_bind_methods() {
- ClassDB::bind_method( _MD("set_shadow_mode","mode"),&OmniLight::set_shadow_mode);
- ClassDB::bind_method( _MD("get_shadow_mode"),&OmniLight::get_shadow_mode);
+ ClassDB::bind_method( D_METHOD("set_shadow_mode","mode"),&OmniLight::set_shadow_mode);
+ ClassDB::bind_method( D_METHOD("get_shadow_mode"),&OmniLight::get_shadow_mode);
- ClassDB::bind_method( _MD("set_shadow_detail","detail"),&OmniLight::set_shadow_detail);
- ClassDB::bind_method( _MD("get_shadow_detail"),&OmniLight::get_shadow_detail);
+ ClassDB::bind_method( D_METHOD("set_shadow_detail","detail"),&OmniLight::set_shadow_detail);
+ ClassDB::bind_method( D_METHOD("get_shadow_detail"),&OmniLight::get_shadow_detail);
ADD_GROUP("Omni","omni_");
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni_range",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni_attenuation",PROPERTY_HINT_EXP_EASING), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION);
- ADD_PROPERTY( PropertyInfo( Variant::INT, "omni_shadow_mode",PROPERTY_HINT_ENUM,"Dual Paraboloid,Cube"), _SCS("set_shadow_mode"), _SCS("get_shadow_mode"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "omni_shadow_detail",PROPERTY_HINT_ENUM,"Vertical,Horizontal"), _SCS("set_shadow_detail"), _SCS("get_shadow_detail"));
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni_range",PROPERTY_HINT_RANGE,"0,65536,0.1"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni_attenuation",PROPERTY_HINT_EXP_EASING), "set_param", "get_param", PARAM_ATTENUATION);
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "omni_shadow_mode",PROPERTY_HINT_ENUM,"Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "omni_shadow_detail",PROPERTY_HINT_ENUM,"Vertical,Horizontal"), "set_shadow_detail", "get_shadow_detail");
}
@@ -430,9 +430,9 @@ OmniLight::OmniLight() : Light( VisualServer::LIGHT_OMNI ) {
void SpotLight::_bind_methods() {
ADD_GROUP("Spot","spot_");
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_range",PROPERTY_HINT_RANGE,"0,65536,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_attenuation",PROPERTY_HINT_EXP_EASING), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_angle",PROPERTY_HINT_RANGE,"0,180,0.1"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ANGLE);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_angle_attenuation",PROPERTY_HINT_EXP_EASING), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ATTENUATION);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_range",PROPERTY_HINT_RANGE,"0,65536,0.1"), "set_param", "get_param", PARAM_RANGE);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_attenuation",PROPERTY_HINT_EXP_EASING), "set_param", "get_param", PARAM_ATTENUATION);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_angle",PROPERTY_HINT_RANGE,"0,180,0.1"), "set_param", "get_param", PARAM_SPOT_ANGLE);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot_angle_attenuation",PROPERTY_HINT_EXP_EASING), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
}
diff --git a/scene/3d/listener.cpp b/scene/3d/listener.cpp
index 0aa1128bdb..578044ad09 100644
--- a/scene/3d/listener.cpp
+++ b/scene/3d/listener.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* listener.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "listener.h"
#include "scene/resources/mesh.h"
@@ -146,10 +174,10 @@ RES Listener::_get_gizmo_geometry() const {
void Listener::_bind_methods() {
- ClassDB::bind_method( _MD("make_current"),&Listener::make_current );
- ClassDB::bind_method( _MD("clear_current"),&Listener::clear_current );
- ClassDB::bind_method( _MD("is_current"),&Listener::is_current );
- ClassDB::bind_method( _MD("get_listener_transform"),&Listener::get_listener_transform );
+ ClassDB::bind_method( D_METHOD("make_current"),&Listener::make_current );
+ ClassDB::bind_method( D_METHOD("clear_current"),&Listener::clear_current );
+ ClassDB::bind_method( D_METHOD("is_current"),&Listener::is_current );
+ ClassDB::bind_method( D_METHOD("get_listener_transform"),&Listener::get_listener_transform );
}
Listener::Listener() {
diff --git a/scene/3d/listener.h b/scene/3d/listener.h
index be1b793716..3b6e39bec5 100644
--- a/scene/3d/listener.h
+++ b/scene/3d/listener.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* listener.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 LISTENER_H
#define LISTENER_H
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index 2198f538b8..e6bd69aed2 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -294,19 +294,19 @@ void MeshInstance::_mesh_changed() {
void MeshInstance::_bind_methods() {
- ClassDB::bind_method(_MD("set_mesh","mesh:Mesh"),&MeshInstance::set_mesh);
- ClassDB::bind_method(_MD("get_mesh:Mesh"),&MeshInstance::get_mesh);
- ClassDB::bind_method(_MD("set_skeleton_path","skeleton_path:NodePath"),&MeshInstance::set_skeleton_path);
- ClassDB::bind_method(_MD("get_skeleton_path:NodePath"),&MeshInstance::get_skeleton_path);
+ ClassDB::bind_method(D_METHOD("set_mesh","mesh:Mesh"),&MeshInstance::set_mesh);
+ ClassDB::bind_method(D_METHOD("get_mesh:Mesh"),&MeshInstance::get_mesh);
+ ClassDB::bind_method(D_METHOD("set_skeleton_path","skeleton_path:NodePath"),&MeshInstance::set_skeleton_path);
+ ClassDB::bind_method(D_METHOD("get_skeleton_path:NodePath"),&MeshInstance::get_skeleton_path);
- ClassDB::bind_method(_MD("create_trimesh_collision"),&MeshInstance::create_trimesh_collision);
+ ClassDB::bind_method(D_METHOD("create_trimesh_collision"),&MeshInstance::create_trimesh_collision);
ClassDB::set_method_flags("MeshInstance","create_trimesh_collision",METHOD_FLAGS_DEFAULT);
- ClassDB::bind_method(_MD("create_convex_collision"),&MeshInstance::create_convex_collision);
+ ClassDB::bind_method(D_METHOD("create_convex_collision"),&MeshInstance::create_convex_collision);
ClassDB::set_method_flags("MeshInstance","create_convex_collision",METHOD_FLAGS_DEFAULT);
- ClassDB::bind_method(_MD("_mesh_changed"),&MeshInstance::_mesh_changed);
+ ClassDB::bind_method(D_METHOD("_mesh_changed"),&MeshInstance::_mesh_changed);
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), _SCS("set_mesh"), _SCS("get_mesh"));
- ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "skeleton"), _SCS("set_skeleton_path"), _SCS("get_skeleton_path"));
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh" ), "set_mesh", "get_mesh");
+ ADD_PROPERTY( PropertyInfo (Variant::NODE_PATH, "skeleton"), "set_skeleton_path", "get_skeleton_path");
}
MeshInstance::MeshInstance()
diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp
index 31843fadaa..e1acdfca53 100644
--- a/scene/3d/multimesh_instance.cpp
+++ b/scene/3d/multimesh_instance.cpp
@@ -34,9 +34,9 @@
void MultiMeshInstance::_bind_methods() {
- ClassDB::bind_method(_MD("set_multimesh","multimesh"),&MultiMeshInstance::set_multimesh);
- ClassDB::bind_method(_MD("get_multimesh"),&MultiMeshInstance::get_multimesh);
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"multimesh",PROPERTY_HINT_RESOURCE_TYPE,"MultiMesh"), _SCS("set_multimesh"), _SCS("get_multimesh"));
+ ClassDB::bind_method(D_METHOD("set_multimesh","multimesh"),&MultiMeshInstance::set_multimesh);
+ ClassDB::bind_method(D_METHOD("get_multimesh"),&MultiMeshInstance::get_multimesh);
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"multimesh",PROPERTY_HINT_RESOURCE_TYPE,"MultiMesh"), "set_multimesh", "get_multimesh");
}
diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp
index 38893598d6..5c8fe6bb67 100644
--- a/scene/3d/navigation.cpp
+++ b/scene/3d/navigation.cpp
@@ -730,20 +730,20 @@ Vector3 Navigation::get_up_vector() const{
void Navigation::_bind_methods() {
- ClassDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform","owner"),&Navigation::navmesh_create,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform);
- ClassDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);
+ ClassDB::bind_method(D_METHOD("navmesh_create","mesh:NavigationMesh","xform","owner"),&Navigation::navmesh_create,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform);
+ ClassDB::bind_method(D_METHOD("navmesh_remove","id"),&Navigation::navmesh_remove);
- ClassDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation::get_simple_path,DEFVAL(true));
- ClassDB::bind_method(_MD("get_closest_point_to_segment","start","end","use_collision"),&Navigation::get_closest_point_to_segment,DEFVAL(false));
- ClassDB::bind_method(_MD("get_closest_point","to_point"),&Navigation::get_closest_point);
- ClassDB::bind_method(_MD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal);
- ClassDB::bind_method(_MD("get_closest_point_owner","to_point"),&Navigation::get_closest_point_owner);
+ ClassDB::bind_method(D_METHOD("get_simple_path","start","end","optimize"),&Navigation::get_simple_path,DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_closest_point_to_segment","start","end","use_collision"),&Navigation::get_closest_point_to_segment,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_closest_point","to_point"),&Navigation::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal);
+ ClassDB::bind_method(D_METHOD("get_closest_point_owner","to_point"),&Navigation::get_closest_point_owner);
- ClassDB::bind_method(_MD("set_up_vector","up"),&Navigation::set_up_vector);
- ClassDB::bind_method(_MD("get_up_vector"),&Navigation::get_up_vector);
+ ClassDB::bind_method(D_METHOD("set_up_vector","up"),&Navigation::set_up_vector);
+ ClassDB::bind_method(D_METHOD("get_up_vector"),&Navigation::get_up_vector);
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"up_vector"),_SCS("set_up_vector"),_SCS("get_up_vector"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"up_vector"),"set_up_vector","get_up_vector");
}
Navigation::Navigation() {
diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp
index 4018045390..8efb9bb333 100644
--- a/scene/3d/navigation_mesh.cpp
+++ b/scene/3d/navigation_mesh.cpp
@@ -208,19 +208,19 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() {
void NavigationMesh::_bind_methods() {
- ClassDB::bind_method(_MD("set_vertices","vertices"),&NavigationMesh::set_vertices);
- ClassDB::bind_method(_MD("get_vertices"),&NavigationMesh::get_vertices);
+ ClassDB::bind_method(D_METHOD("set_vertices","vertices"),&NavigationMesh::set_vertices);
+ ClassDB::bind_method(D_METHOD("get_vertices"),&NavigationMesh::get_vertices);
- ClassDB::bind_method(_MD("add_polygon","polygon"),&NavigationMesh::add_polygon);
- ClassDB::bind_method(_MD("get_polygon_count"),&NavigationMesh::get_polygon_count);
- ClassDB::bind_method(_MD("get_polygon","idx"),&NavigationMesh::get_polygon);
- ClassDB::bind_method(_MD("clear_polygons"),&NavigationMesh::clear_polygons);
+ ClassDB::bind_method(D_METHOD("add_polygon","polygon"),&NavigationMesh::add_polygon);
+ ClassDB::bind_method(D_METHOD("get_polygon_count"),&NavigationMesh::get_polygon_count);
+ ClassDB::bind_method(D_METHOD("get_polygon","idx"),&NavigationMesh::get_polygon);
+ ClassDB::bind_method(D_METHOD("clear_polygons"),&NavigationMesh::clear_polygons);
- ClassDB::bind_method(_MD("_set_polygons","polygons"),&NavigationMesh::_set_polygons);
- ClassDB::bind_method(_MD("_get_polygons"),&NavigationMesh::_get_polygons);
+ ClassDB::bind_method(D_METHOD("_set_polygons","polygons"),&NavigationMesh::_set_polygons);
+ ClassDB::bind_method(D_METHOD("_get_polygons"),&NavigationMesh::_get_polygons);
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_vertices"),_SCS("get_vertices"));
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_polygons"),_SCS("_get_polygons"));
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_vertices","get_vertices");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_polygons","_get_polygons");
}
NavigationMesh::NavigationMesh() {
@@ -394,14 +394,14 @@ String NavigationMeshInstance::get_configuration_warning() const {
void NavigationMeshInstance::_bind_methods() {
- ClassDB::bind_method(_MD("set_navigation_mesh","navmesh"),&NavigationMeshInstance::set_navigation_mesh);
- ClassDB::bind_method(_MD("get_navigation_mesh"),&NavigationMeshInstance::get_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("set_navigation_mesh","navmesh"),&NavigationMeshInstance::set_navigation_mesh);
+ ClassDB::bind_method(D_METHOD("get_navigation_mesh"),&NavigationMeshInstance::get_navigation_mesh);
- ClassDB::bind_method(_MD("set_enabled","enabled"),&NavigationMeshInstance::set_enabled);
- ClassDB::bind_method(_MD("is_enabled"),&NavigationMeshInstance::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled","enabled"),&NavigationMeshInstance::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"),&NavigationMeshInstance::is_enabled);
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navmesh",PROPERTY_HINT_RESOURCE_TYPE,"NavigationMesh"),_SCS("set_navigation_mesh"),_SCS("get_navigation_mesh"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navmesh",PROPERTY_HINT_RESOURCE_TYPE,"NavigationMesh"),"set_navigation_mesh","get_navigation_mesh");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),"set_enabled","is_enabled");
}
NavigationMeshInstance::NavigationMeshInstance() {
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index 72fab4cccc..0e0c1e9dc6 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -406,79 +406,79 @@ RES Particles::_get_gizmo_geometry() const {
void Particles::_bind_methods() {
- ClassDB::bind_method(_MD("set_amount","amount"),&Particles::set_amount);
- ClassDB::bind_method(_MD("get_amount"),&Particles::get_amount);
- ClassDB::bind_method(_MD("set_emitting","enabled"),&Particles::set_emitting);
- ClassDB::bind_method(_MD("is_emitting"),&Particles::is_emitting);
- ClassDB::bind_method(_MD("set_visibility_aabb","aabb"),&Particles::set_visibility_aabb);
- ClassDB::bind_method(_MD("get_visibility_aabb"),&Particles::get_visibility_aabb);
- ClassDB::bind_method(_MD("set_emission_half_extents","half_extents"),&Particles::set_emission_half_extents);
- ClassDB::bind_method(_MD("get_emission_half_extents"),&Particles::get_emission_half_extents);
- ClassDB::bind_method(_MD("set_emission_base_velocity","base_velocity"),&Particles::set_emission_base_velocity);
- ClassDB::bind_method(_MD("get_emission_base_velocity"),&Particles::get_emission_base_velocity);
- ClassDB::bind_method(_MD("set_emission_points","points"),&Particles::set_emission_points);
- ClassDB::bind_method(_MD("get_emission_points"),&Particles::get_emission_points);
- ClassDB::bind_method(_MD("set_gravity_normal","normal"),&Particles::set_gravity_normal);
- ClassDB::bind_method(_MD("get_gravity_normal"),&Particles::get_gravity_normal);
- ClassDB::bind_method(_MD("set_variable","variable","value"),&Particles::set_variable);
- ClassDB::bind_method(_MD("get_variable","variable"),&Particles::get_variable);
- ClassDB::bind_method(_MD("set_randomness","variable","randomness"),&Particles::set_randomness);
- ClassDB::bind_method(_MD("get_randomness","variable"),&Particles::get_randomness);
- ClassDB::bind_method(_MD("set_color_phase_pos","phase","pos"),&Particles::set_color_phase_pos);
- ClassDB::bind_method(_MD("get_color_phase_pos","phase"),&Particles::get_color_phase_pos);
- ClassDB::bind_method(_MD("set_color_phase_color","phase","color"),&Particles::set_color_phase_color);
- ClassDB::bind_method(_MD("get_color_phase_color","phase"),&Particles::get_color_phase_color);
- ClassDB::bind_method(_MD("set_material","material:Material"),&Particles::set_material);
- ClassDB::bind_method(_MD("get_material:Material"),&Particles::get_material);
- ClassDB::bind_method(_MD("set_emit_timeout","timeout"),&Particles::set_emit_timeout);
- ClassDB::bind_method(_MD("get_emit_timeout"),&Particles::get_emit_timeout);
- ClassDB::bind_method(_MD("set_height_from_velocity","enable"),&Particles::set_height_from_velocity);
- ClassDB::bind_method(_MD("has_height_from_velocity"),&Particles::has_height_from_velocity);
- ClassDB::bind_method(_MD("set_use_local_coordinates","enable"),&Particles::set_use_local_coordinates);
- ClassDB::bind_method(_MD("is_using_local_coordinates"),&Particles::is_using_local_coordinates);
-
- ClassDB::bind_method(_MD("set_color_phases","count"),&Particles::set_color_phases);
- ClassDB::bind_method(_MD("get_color_phases"),&Particles::get_color_phases);
-
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material" ), _SCS("set_material"), _SCS("get_material") );
-
- ADD_PROPERTY( PropertyInfo( Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1024,1" ), _SCS("set_amount"), _SCS("get_amount") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "emitting" ), _SCS("set_emitting"), _SCS("is_emitting") );
- ADD_PROPERTY( PropertyInfo( Variant::_AABB, "visibility" ), _SCS("set_visibility_aabb"), _SCS("get_visibility_aabb") );
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_extents" ), _SCS("set_emission_half_extents"), _SCS("get_emission_half_extents") );
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_base_velocity" ), _SCS("set_emission_base_velocity"), _SCS("get_emission_base_velocity") );
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "emission_points" ), _SCS("set_emission_points"), _SCS("get_emission_points") );
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "gravity_normal" ), _SCS("set_gravity_normal"), _SCS("get_gravity_normal") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "local_coords" ), _SCS("set_use_local_coordinates"), _SCS("is_using_local_coordinates") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "emit_timeout",PROPERTY_HINT_RANGE,"0,256,0.01"), _SCS("set_emit_timeout"), _SCS("get_emit_timeout") );
-
-
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/lifetime", PROPERTY_HINT_RANGE,"0.1,60,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LIFETIME );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/spread", PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_SPREAD );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/gravity", PROPERTY_HINT_RANGE,"-48,48,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_GRAVITY );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LINEAR_VELOCITY );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/angular_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_ANGULAR_VELOCITY );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_LINEAR_ACCELERATION );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/radial_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_DRAG );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/tan_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_TANGENTIAL_ACCELERATION );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/damping", PROPERTY_HINT_RANGE,"0,128,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_DAMPING );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_size", PROPERTY_HINT_RANGE,"0,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_INITIAL_SIZE );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/final_size", PROPERTY_HINT_RANGE,"0,100,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_FINAL_SIZE );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_angle",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_INITIAL_ANGLE );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "vars/height_from_velocity"), _SCS("set_height_from_velocity"), _SCS("has_height_from_velocity") );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height",PROPERTY_HINT_RANGE,"0,4096,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_HEIGHT);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height_speed_scale",PROPERTY_HINT_RANGE,"0,4096,0.01"), _SCS("set_variable"), _SCS("get_variable"), VAR_HEIGHT_SPEED_SCALE );
+ ClassDB::bind_method(D_METHOD("set_amount","amount"),&Particles::set_amount);
+ ClassDB::bind_method(D_METHOD("get_amount"),&Particles::get_amount);
+ ClassDB::bind_method(D_METHOD("set_emitting","enabled"),&Particles::set_emitting);
+ ClassDB::bind_method(D_METHOD("is_emitting"),&Particles::is_emitting);
+ ClassDB::bind_method(D_METHOD("set_visibility_aabb","aabb"),&Particles::set_visibility_aabb);
+ ClassDB::bind_method(D_METHOD("get_visibility_aabb"),&Particles::get_visibility_aabb);
+ ClassDB::bind_method(D_METHOD("set_emission_half_extents","half_extents"),&Particles::set_emission_half_extents);
+ ClassDB::bind_method(D_METHOD("get_emission_half_extents"),&Particles::get_emission_half_extents);
+ ClassDB::bind_method(D_METHOD("set_emission_base_velocity","base_velocity"),&Particles::set_emission_base_velocity);
+ ClassDB::bind_method(D_METHOD("get_emission_base_velocity"),&Particles::get_emission_base_velocity);
+ ClassDB::bind_method(D_METHOD("set_emission_points","points"),&Particles::set_emission_points);
+ ClassDB::bind_method(D_METHOD("get_emission_points"),&Particles::get_emission_points);
+ ClassDB::bind_method(D_METHOD("set_gravity_normal","normal"),&Particles::set_gravity_normal);
+ ClassDB::bind_method(D_METHOD("get_gravity_normal"),&Particles::get_gravity_normal);
+ ClassDB::bind_method(D_METHOD("set_variable","variable","value"),&Particles::set_variable);
+ ClassDB::bind_method(D_METHOD("get_variable","variable"),&Particles::get_variable);
+ ClassDB::bind_method(D_METHOD("set_randomness","variable","randomness"),&Particles::set_randomness);
+ ClassDB::bind_method(D_METHOD("get_randomness","variable"),&Particles::get_randomness);
+ ClassDB::bind_method(D_METHOD("set_color_phase_pos","phase","pos"),&Particles::set_color_phase_pos);
+ ClassDB::bind_method(D_METHOD("get_color_phase_pos","phase"),&Particles::get_color_phase_pos);
+ ClassDB::bind_method(D_METHOD("set_color_phase_color","phase","color"),&Particles::set_color_phase_color);
+ ClassDB::bind_method(D_METHOD("get_color_phase_color","phase"),&Particles::get_color_phase_color);
+ ClassDB::bind_method(D_METHOD("set_material","material:Material"),&Particles::set_material);
+ ClassDB::bind_method(D_METHOD("get_material:Material"),&Particles::get_material);
+ ClassDB::bind_method(D_METHOD("set_emit_timeout","timeout"),&Particles::set_emit_timeout);
+ ClassDB::bind_method(D_METHOD("get_emit_timeout"),&Particles::get_emit_timeout);
+ ClassDB::bind_method(D_METHOD("set_height_from_velocity","enable"),&Particles::set_height_from_velocity);
+ ClassDB::bind_method(D_METHOD("has_height_from_velocity"),&Particles::has_height_from_velocity);
+ ClassDB::bind_method(D_METHOD("set_use_local_coordinates","enable"),&Particles::set_use_local_coordinates);
+ ClassDB::bind_method(D_METHOD("is_using_local_coordinates"),&Particles::is_using_local_coordinates);
+
+ ClassDB::bind_method(D_METHOD("set_color_phases","count"),&Particles::set_color_phases);
+ ClassDB::bind_method(D_METHOD("get_color_phases"),&Particles::get_color_phases);
+
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material" ), "set_material", "get_material") ;
+
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1024,1" ), "set_amount", "get_amount") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "emitting" ), "set_emitting", "is_emitting") ;
+ ADD_PROPERTY( PropertyInfo( Variant::_AABB, "visibility" ), "set_visibility_aabb", "get_visibility_aabb") ;
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_extents" ), "set_emission_half_extents", "get_emission_half_extents") ;
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_base_velocity" ), "set_emission_base_velocity", "get_emission_base_velocity") ;
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "emission_points" ), "set_emission_points", "get_emission_points") ;
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "gravity_normal" ), "set_gravity_normal", "get_gravity_normal") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "local_coords" ), "set_use_local_coordinates", "is_using_local_coordinates") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "emit_timeout",PROPERTY_HINT_RANGE,"0,256,0.01"), "set_emit_timeout", "get_emit_timeout") ;
+
+
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/lifetime", PROPERTY_HINT_RANGE,"0.1,60,0.01"), "set_variable", "get_variable", VAR_LIFETIME );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/spread", PROPERTY_HINT_RANGE,"0,1,0.01"), "set_variable", "get_variable", VAR_SPREAD );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/gravity", PROPERTY_HINT_RANGE,"-48,48,0.01"), "set_variable", "get_variable", VAR_GRAVITY );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_LINEAR_VELOCITY );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/angular_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_ANGULAR_VELOCITY );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_LINEAR_ACCELERATION );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/radial_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_DRAG );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/tan_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_TANGENTIAL_ACCELERATION );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/damping", PROPERTY_HINT_RANGE,"0,128,0.01"), "set_variable", "get_variable", VAR_DAMPING );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_size", PROPERTY_HINT_RANGE,"0,100,0.01"), "set_variable", "get_variable", VAR_INITIAL_SIZE );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/final_size", PROPERTY_HINT_RANGE,"0,100,0.01"), "set_variable", "get_variable", VAR_FINAL_SIZE );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_angle",PROPERTY_HINT_RANGE,"0,1,0.01"), "set_variable", "get_variable", VAR_INITIAL_ANGLE );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "vars/height_from_velocity"), "set_height_from_velocity", "has_height_from_velocity") ;
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_variable", "get_variable", VAR_HEIGHT);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height_speed_scale",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_variable", "get_variable", VAR_HEIGHT_SPEED_SCALE );
for(int i=0;i<VAR_MAX;i++)
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, _rand_names[i], PROPERTY_HINT_RANGE,"-16.0,16.0,0.01"),_SCS("set_randomness"), _SCS("get_randomness"),_var_indices[i] );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, _rand_names[i], PROPERTY_HINT_RANGE,"-16.0,16.0,0.01"),"set_randomness", "get_randomness",_var_indices[i] );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1"), _SCS("set_color_phases"), _SCS("get_color_phases"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1"), "set_color_phases", "get_color_phases");
for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) {
String phase="phase_"+itos(i)+"/";
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_color_phase_pos"),_SCS("get_color_phase_pos"),i );
- ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color"),_SCS("set_color_phase_color"),_SCS("get_color_phase_color"),i );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01"),"set_color_phase_pos","get_color_phase_pos",i );
+ ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color"),"set_color_phase_color","get_color_phase_color",i );
}
BIND_CONSTANT( VAR_LIFETIME );
diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp
index 5e8ded3867..ead150e40b 100644
--- a/scene/3d/path.cpp
+++ b/scene/3d/path.cpp
@@ -80,11 +80,11 @@ Ref<Curve3D> Path::get_curve() const{
void Path::_bind_methods() {
- ClassDB::bind_method(_MD("set_curve","curve:Curve3D"),&Path::set_curve);
- ClassDB::bind_method(_MD("get_curve:Curve3D","curve"),&Path::get_curve);
- ClassDB::bind_method(_MD("_curve_changed"),&Path::_curve_changed);
+ ClassDB::bind_method(D_METHOD("set_curve","curve:Curve3D"),&Path::set_curve);
+ ClassDB::bind_method(D_METHOD("get_curve:Curve3D","curve"),&Path::get_curve);
+ ClassDB::bind_method(D_METHOD("_curve_changed"),&Path::_curve_changed);
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), _SCS("set_curve"),_SCS("get_curve"));
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve","get_curve");
}
Path::Path() {
@@ -257,26 +257,26 @@ void PathFollow::_get_property_list( List<PropertyInfo> *p_list) const{
void PathFollow::_bind_methods() {
- ClassDB::bind_method(_MD("set_offset","offset"),&PathFollow::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&PathFollow::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&PathFollow::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&PathFollow::get_offset);
- ClassDB::bind_method(_MD("set_h_offset","h_offset"),&PathFollow::set_h_offset);
- ClassDB::bind_method(_MD("get_h_offset"),&PathFollow::get_h_offset);
+ ClassDB::bind_method(D_METHOD("set_h_offset","h_offset"),&PathFollow::set_h_offset);
+ ClassDB::bind_method(D_METHOD("get_h_offset"),&PathFollow::get_h_offset);
- ClassDB::bind_method(_MD("set_v_offset","v_offset"),&PathFollow::set_v_offset);
- ClassDB::bind_method(_MD("get_v_offset"),&PathFollow::get_v_offset);
+ ClassDB::bind_method(D_METHOD("set_v_offset","v_offset"),&PathFollow::set_v_offset);
+ ClassDB::bind_method(D_METHOD("get_v_offset"),&PathFollow::get_v_offset);
- ClassDB::bind_method(_MD("set_unit_offset","unit_offset"),&PathFollow::set_unit_offset);
- ClassDB::bind_method(_MD("get_unit_offset"),&PathFollow::get_unit_offset);
+ ClassDB::bind_method(D_METHOD("set_unit_offset","unit_offset"),&PathFollow::set_unit_offset);
+ ClassDB::bind_method(D_METHOD("get_unit_offset"),&PathFollow::get_unit_offset);
- ClassDB::bind_method(_MD("set_rotation_mode","rotation_mode"),&PathFollow::set_rotation_mode);
- ClassDB::bind_method(_MD("get_rotation_mode"),&PathFollow::get_rotation_mode);
+ ClassDB::bind_method(D_METHOD("set_rotation_mode","rotation_mode"),&PathFollow::set_rotation_mode);
+ ClassDB::bind_method(D_METHOD("get_rotation_mode"),&PathFollow::get_rotation_mode);
- ClassDB::bind_method(_MD("set_cubic_interpolation","enable"),&PathFollow::set_cubic_interpolation);
- ClassDB::bind_method(_MD("get_cubic_interpolation"),&PathFollow::get_cubic_interpolation);
+ ClassDB::bind_method(D_METHOD("set_cubic_interpolation","enable"),&PathFollow::set_cubic_interpolation);
+ ClassDB::bind_method(D_METHOD("get_cubic_interpolation"),&PathFollow::get_cubic_interpolation);
- ClassDB::bind_method(_MD("set_loop","loop"),&PathFollow::set_loop);
- ClassDB::bind_method(_MD("has_loop"),&PathFollow::has_loop);
+ ClassDB::bind_method(D_METHOD("set_loop","loop"),&PathFollow::set_loop);
+ ClassDB::bind_method(D_METHOD("has_loop"),&PathFollow::has_loop);
BIND_CONSTANT( ROTATION_NONE );
BIND_CONSTANT( ROTATION_Y );
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 0a44ad9c3d..af514a171f 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -147,24 +147,24 @@ uint32_t PhysicsBody::_get_layers() const{
}
void PhysicsBody::_bind_methods() {
- ClassDB::bind_method(_MD("set_collision_layer","layer"),&PhysicsBody::set_collision_layer);
- ClassDB::bind_method(_MD("get_collision_layer"),&PhysicsBody::get_collision_layer);
+ ClassDB::bind_method(D_METHOD("set_collision_layer","layer"),&PhysicsBody::set_collision_layer);
+ ClassDB::bind_method(D_METHOD("get_collision_layer"),&PhysicsBody::get_collision_layer);
- ClassDB::bind_method(_MD("set_collision_mask","mask"),&PhysicsBody::set_collision_mask);
- ClassDB::bind_method(_MD("get_collision_mask"),&PhysicsBody::get_collision_mask);
+ ClassDB::bind_method(D_METHOD("set_collision_mask","mask"),&PhysicsBody::set_collision_mask);
+ ClassDB::bind_method(D_METHOD("get_collision_mask"),&PhysicsBody::get_collision_mask);
- ClassDB::bind_method(_MD("set_collision_mask_bit","bit","value"),&PhysicsBody::set_collision_mask_bit);
- ClassDB::bind_method(_MD("get_collision_mask_bit","bit"),&PhysicsBody::get_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("set_collision_mask_bit","bit","value"),&PhysicsBody::set_collision_mask_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_mask_bit","bit"),&PhysicsBody::get_collision_mask_bit);
- ClassDB::bind_method(_MD("set_collision_layer_bit","bit","value"),&PhysicsBody::set_collision_layer_bit);
- ClassDB::bind_method(_MD("get_collision_layer_bit","bit"),&PhysicsBody::get_collision_layer_bit);
+ ClassDB::bind_method(D_METHOD("set_collision_layer_bit","bit","value"),&PhysicsBody::set_collision_layer_bit);
+ ClassDB::bind_method(D_METHOD("get_collision_layer_bit","bit"),&PhysicsBody::get_collision_layer_bit);
- ClassDB::bind_method(_MD("_set_layers","mask"),&PhysicsBody::_set_layers);
- ClassDB::bind_method(_MD("_get_layers"),&PhysicsBody::_get_layers);
+ ClassDB::bind_method(D_METHOD("_set_layers","mask"),&PhysicsBody::_set_layers);
+ ClassDB::bind_method(D_METHOD("_get_layers"),&PhysicsBody::_get_layers);
ADD_GROUP("Collision","collision_");
- ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_layer",PROPERTY_HINT_LAYERS_3D_PHYSICS),_SCS("set_collision_layer"),_SCS("get_collision_layer"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_3D_PHYSICS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_layer",PROPERTY_HINT_LAYERS_3D_PHYSICS),"set_collision_layer","get_collision_layer");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"collision_mask",PROPERTY_HINT_LAYERS_3D_PHYSICS),"set_collision_mask","get_collision_mask");
}
@@ -230,25 +230,25 @@ Vector3 StaticBody::get_constant_angular_velocity() const {
void StaticBody::_bind_methods() {
- ClassDB::bind_method(_MD("set_constant_linear_velocity","vel"),&StaticBody::set_constant_linear_velocity);
- ClassDB::bind_method(_MD("set_constant_angular_velocity","vel"),&StaticBody::set_constant_angular_velocity);
- ClassDB::bind_method(_MD("get_constant_linear_velocity"),&StaticBody::get_constant_linear_velocity);
- ClassDB::bind_method(_MD("get_constant_angular_velocity"),&StaticBody::get_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_constant_linear_velocity","vel"),&StaticBody::set_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_constant_angular_velocity","vel"),&StaticBody::set_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"),&StaticBody::get_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"),&StaticBody::get_constant_angular_velocity);
- ClassDB::bind_method(_MD("set_friction","friction"),&StaticBody::set_friction);
- ClassDB::bind_method(_MD("get_friction"),&StaticBody::get_friction);
+ ClassDB::bind_method(D_METHOD("set_friction","friction"),&StaticBody::set_friction);
+ ClassDB::bind_method(D_METHOD("get_friction"),&StaticBody::get_friction);
- ClassDB::bind_method(_MD("set_bounce","bounce"),&StaticBody::set_bounce);
- ClassDB::bind_method(_MD("get_bounce"),&StaticBody::get_bounce);
+ ClassDB::bind_method(D_METHOD("set_bounce","bounce"),&StaticBody::set_bounce);
+ ClassDB::bind_method(D_METHOD("get_bounce"),&StaticBody::get_bounce);
- ClassDB::bind_method(_MD("add_collision_exception_with","body:PhysicsBody"),&PhysicsBody::add_collision_exception_with);
- ClassDB::bind_method(_MD("remove_collision_exception_with","body:PhysicsBody"),&PhysicsBody::remove_collision_exception_with);
+ ClassDB::bind_method(D_METHOD("add_collision_exception_with","body:PhysicsBody"),&PhysicsBody::add_collision_exception_with);
+ ClassDB::bind_method(D_METHOD("remove_collision_exception_with","body:PhysicsBody"),&PhysicsBody::remove_collision_exception_with);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_friction","get_friction");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_bounce","get_bounce");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_linear_velocity"),_SCS("set_constant_linear_velocity"),_SCS("get_constant_linear_velocity"));
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_angular_velocity"),_SCS("set_constant_angular_velocity"),_SCS("get_constant_angular_velocity"));
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_linear_velocity"),"set_constant_linear_velocity","get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"constant_angular_velocity"),"set_constant_angular_velocity","get_constant_angular_velocity");
}
StaticBody::StaticBody() : PhysicsBody(PhysicsServer::BODY_MODE_STATIC) {
@@ -800,88 +800,88 @@ Array RigidBody::get_colliding_bodies() const {
void RigidBody::_bind_methods() {
- ClassDB::bind_method(_MD("set_mode","mode"),&RigidBody::set_mode);
- ClassDB::bind_method(_MD("get_mode"),&RigidBody::get_mode);
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&RigidBody::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&RigidBody::get_mode);
- ClassDB::bind_method(_MD("set_mass","mass"),&RigidBody::set_mass);
- ClassDB::bind_method(_MD("get_mass"),&RigidBody::get_mass);
+ ClassDB::bind_method(D_METHOD("set_mass","mass"),&RigidBody::set_mass);
+ ClassDB::bind_method(D_METHOD("get_mass"),&RigidBody::get_mass);
- ClassDB::bind_method(_MD("set_weight","weight"),&RigidBody::set_weight);
- ClassDB::bind_method(_MD("get_weight"),&RigidBody::get_weight);
+ ClassDB::bind_method(D_METHOD("set_weight","weight"),&RigidBody::set_weight);
+ ClassDB::bind_method(D_METHOD("get_weight"),&RigidBody::get_weight);
- ClassDB::bind_method(_MD("set_friction","friction"),&RigidBody::set_friction);
- ClassDB::bind_method(_MD("get_friction"),&RigidBody::get_friction);
+ ClassDB::bind_method(D_METHOD("set_friction","friction"),&RigidBody::set_friction);
+ ClassDB::bind_method(D_METHOD("get_friction"),&RigidBody::get_friction);
- ClassDB::bind_method(_MD("set_bounce","bounce"),&RigidBody::set_bounce);
- ClassDB::bind_method(_MD("get_bounce"),&RigidBody::get_bounce);
+ ClassDB::bind_method(D_METHOD("set_bounce","bounce"),&RigidBody::set_bounce);
+ ClassDB::bind_method(D_METHOD("get_bounce"),&RigidBody::get_bounce);
- ClassDB::bind_method(_MD("set_linear_velocity","linear_velocity"),&RigidBody::set_linear_velocity);
- ClassDB::bind_method(_MD("get_linear_velocity"),&RigidBody::get_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_linear_velocity","linear_velocity"),&RigidBody::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"),&RigidBody::get_linear_velocity);
- ClassDB::bind_method(_MD("set_angular_velocity","angular_velocity"),&RigidBody::set_angular_velocity);
- ClassDB::bind_method(_MD("get_angular_velocity"),&RigidBody::get_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_angular_velocity","angular_velocity"),&RigidBody::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"),&RigidBody::get_angular_velocity);
- ClassDB::bind_method(_MD("set_gravity_scale","gravity_scale"),&RigidBody::set_gravity_scale);
- ClassDB::bind_method(_MD("get_gravity_scale"),&RigidBody::get_gravity_scale);
+ ClassDB::bind_method(D_METHOD("set_gravity_scale","gravity_scale"),&RigidBody::set_gravity_scale);
+ ClassDB::bind_method(D_METHOD("get_gravity_scale"),&RigidBody::get_gravity_scale);
- ClassDB::bind_method(_MD("set_linear_damp","linear_damp"),&RigidBody::set_linear_damp);
- ClassDB::bind_method(_MD("get_linear_damp"),&RigidBody::get_linear_damp);
+ ClassDB::bind_method(D_METHOD("set_linear_damp","linear_damp"),&RigidBody::set_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_linear_damp"),&RigidBody::get_linear_damp);
- ClassDB::bind_method(_MD("set_angular_damp","angular_damp"),&RigidBody::set_angular_damp);
- ClassDB::bind_method(_MD("get_angular_damp"),&RigidBody::get_angular_damp);
+ ClassDB::bind_method(D_METHOD("set_angular_damp","angular_damp"),&RigidBody::set_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_angular_damp"),&RigidBody::get_angular_damp);
- ClassDB::bind_method(_MD("set_max_contacts_reported","amount"),&RigidBody::set_max_contacts_reported);
- ClassDB::bind_method(_MD("get_max_contacts_reported"),&RigidBody::get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("set_max_contacts_reported","amount"),&RigidBody::set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_max_contacts_reported"),&RigidBody::get_max_contacts_reported);
- ClassDB::bind_method(_MD("set_use_custom_integrator","enable"),&RigidBody::set_use_custom_integrator);
- ClassDB::bind_method(_MD("is_using_custom_integrator"),&RigidBody::is_using_custom_integrator);
+ ClassDB::bind_method(D_METHOD("set_use_custom_integrator","enable"),&RigidBody::set_use_custom_integrator);
+ ClassDB::bind_method(D_METHOD("is_using_custom_integrator"),&RigidBody::is_using_custom_integrator);
- ClassDB::bind_method(_MD("set_contact_monitor","enabled"),&RigidBody::set_contact_monitor);
- ClassDB::bind_method(_MD("is_contact_monitor_enabled"),&RigidBody::is_contact_monitor_enabled);
+ ClassDB::bind_method(D_METHOD("set_contact_monitor","enabled"),&RigidBody::set_contact_monitor);
+ ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"),&RigidBody::is_contact_monitor_enabled);
- ClassDB::bind_method(_MD("set_use_continuous_collision_detection","enable"),&RigidBody::set_use_continuous_collision_detection);
- ClassDB::bind_method(_MD("is_using_continuous_collision_detection"),&RigidBody::is_using_continuous_collision_detection);
+ ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection","enable"),&RigidBody::set_use_continuous_collision_detection);
+ ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"),&RigidBody::is_using_continuous_collision_detection);
- ClassDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody::set_axis_velocity);
- ClassDB::bind_method(_MD("apply_impulse","pos","impulse"),&RigidBody::apply_impulse);
+ ClassDB::bind_method(D_METHOD("set_axis_velocity","axis_velocity"),&RigidBody::set_axis_velocity);
+ ClassDB::bind_method(D_METHOD("apply_impulse","pos","impulse"),&RigidBody::apply_impulse);
- ClassDB::bind_method(_MD("set_sleeping","sleeping"),&RigidBody::set_sleeping);
- ClassDB::bind_method(_MD("is_sleeping"),&RigidBody::is_sleeping);
+ ClassDB::bind_method(D_METHOD("set_sleeping","sleeping"),&RigidBody::set_sleeping);
+ ClassDB::bind_method(D_METHOD("is_sleeping"),&RigidBody::is_sleeping);
- ClassDB::bind_method(_MD("set_can_sleep","able_to_sleep"),&RigidBody::set_can_sleep);
- ClassDB::bind_method(_MD("is_able_to_sleep"),&RigidBody::is_able_to_sleep);
+ ClassDB::bind_method(D_METHOD("set_can_sleep","able_to_sleep"),&RigidBody::set_can_sleep);
+ ClassDB::bind_method(D_METHOD("is_able_to_sleep"),&RigidBody::is_able_to_sleep);
- ClassDB::bind_method(_MD("_direct_state_changed"),&RigidBody::_direct_state_changed);
- ClassDB::bind_method(_MD("_body_enter_tree"),&RigidBody::_body_enter_tree);
- ClassDB::bind_method(_MD("_body_exit_tree"),&RigidBody::_body_exit_tree);
+ ClassDB::bind_method(D_METHOD("_direct_state_changed"),&RigidBody::_direct_state_changed);
+ ClassDB::bind_method(D_METHOD("_body_enter_tree"),&RigidBody::_body_enter_tree);
+ ClassDB::bind_method(D_METHOD("_body_exit_tree"),&RigidBody::_body_exit_tree);
- ClassDB::bind_method(_MD("set_axis_lock","axis_lock"),&RigidBody::set_axis_lock);
- ClassDB::bind_method(_MD("get_axis_lock"),&RigidBody::get_axis_lock);
+ ClassDB::bind_method(D_METHOD("set_axis_lock","axis_lock"),&RigidBody::set_axis_lock);
+ ClassDB::bind_method(D_METHOD("get_axis_lock"),&RigidBody::get_axis_lock);
- ClassDB::bind_method(_MD("get_colliding_bodies"),&RigidBody::get_colliding_bodies);
+ ClassDB::bind_method(D_METHOD("get_colliding_bodies"),&RigidBody::get_colliding_bodies);
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState")));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),_SCS("set_gravity_scale"),_SCS("get_gravity_scale"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),_SCS("set_use_continuous_collision_detection"),_SCS("is_using_continuous_collision_detection"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),_SCS("set_contact_monitor"),_SCS("is_contact_monitor_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"sleeping"),_SCS("set_sleeping"),_SCS("is_sleeping"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"can_sleep"),_SCS("set_can_sleep"),_SCS("is_able_to_sleep"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"axis_lock",PROPERTY_HINT_ENUM,"Disabled,Lock X,Lock Y,Lock Z"),_SCS("set_axis_lock"),_SCS("get_axis_lock"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),"set_mode","get_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),"set_mass","get_mass");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),"set_weight","get_weight");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_friction","get_friction");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_bounce","get_bounce");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_scale",PROPERTY_HINT_RANGE,"-128,128,0.01"),"set_gravity_scale","get_gravity_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),"set_use_custom_integrator","is_using_custom_integrator");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),"set_use_continuous_collision_detection","is_using_continuous_collision_detection");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),"set_max_contacts_reported","get_max_contacts_reported");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),"set_contact_monitor","is_contact_monitor_enabled");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"sleeping"),"set_sleeping","is_sleeping");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"can_sleep"),"set_can_sleep","is_able_to_sleep");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"axis_lock",PROPERTY_HINT_ENUM,"Disabled,Lock X,Lock Y,Lock Z"),"set_axis_lock","get_axis_lock");
ADD_GROUP("Linear","linear_");
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"linear_velocity"),_SCS("set_linear_velocity"),_SCS("get_linear_velocity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"linear_velocity"),"set_linear_velocity","get_linear_velocity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),"set_linear_damp","get_linear_damp");
ADD_GROUP("Angular","angular_");
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"angular_velocity"),_SCS("set_angular_velocity"),_SCS("get_angular_velocity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"angular_velocity"),"set_angular_velocity","get_angular_velocity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"-1,128,0.01"),"set_angular_damp","get_angular_damp");
ADD_SIGNAL( MethodInfo("body_shape_entered",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
ADD_SIGNAL( MethodInfo("body_shape_exited",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape")));
@@ -1298,40 +1298,40 @@ float KinematicBody::get_collision_margin() const{
void KinematicBody::_bind_methods() {
- ClassDB::bind_method(_MD("move","rel_vec"),&KinematicBody::move);
- ClassDB::bind_method(_MD("move_to","position"),&KinematicBody::move_to);
+ ClassDB::bind_method(D_METHOD("move","rel_vec"),&KinematicBody::move);
+ ClassDB::bind_method(D_METHOD("move_to","position"),&KinematicBody::move_to);
- ClassDB::bind_method(_MD("can_teleport_to","position"),&KinematicBody::can_teleport_to);
+ ClassDB::bind_method(D_METHOD("can_teleport_to","position"),&KinematicBody::can_teleport_to);
- ClassDB::bind_method(_MD("is_colliding"),&KinematicBody::is_colliding);
+ ClassDB::bind_method(D_METHOD("is_colliding"),&KinematicBody::is_colliding);
- ClassDB::bind_method(_MD("get_collision_pos"),&KinematicBody::get_collision_pos);
- ClassDB::bind_method(_MD("get_collision_normal"),&KinematicBody::get_collision_normal);
- ClassDB::bind_method(_MD("get_collider_velocity"),&KinematicBody::get_collider_velocity);
- ClassDB::bind_method(_MD("get_collider:Variant"),&KinematicBody::_get_collider);
- ClassDB::bind_method(_MD("get_collider_shape"),&KinematicBody::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_pos"),&KinematicBody::get_collision_pos);
+ ClassDB::bind_method(D_METHOD("get_collision_normal"),&KinematicBody::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collider_velocity"),&KinematicBody::get_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collider:Variant"),&KinematicBody::_get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"),&KinematicBody::get_collider_shape);
- ClassDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody::set_collide_with_static_bodies);
- ClassDB::bind_method(_MD("can_collide_with_static_bodies"),&KinematicBody::can_collide_with_static_bodies);
+ ClassDB::bind_method(D_METHOD("set_collide_with_static_bodies","enable"),&KinematicBody::set_collide_with_static_bodies);
+ ClassDB::bind_method(D_METHOD("can_collide_with_static_bodies"),&KinematicBody::can_collide_with_static_bodies);
- ClassDB::bind_method(_MD("set_collide_with_kinematic_bodies","enable"),&KinematicBody::set_collide_with_kinematic_bodies);
- ClassDB::bind_method(_MD("can_collide_with_kinematic_bodies"),&KinematicBody::can_collide_with_kinematic_bodies);
+ ClassDB::bind_method(D_METHOD("set_collide_with_kinematic_bodies","enable"),&KinematicBody::set_collide_with_kinematic_bodies);
+ ClassDB::bind_method(D_METHOD("can_collide_with_kinematic_bodies"),&KinematicBody::can_collide_with_kinematic_bodies);
- ClassDB::bind_method(_MD("set_collide_with_rigid_bodies","enable"),&KinematicBody::set_collide_with_rigid_bodies);
- ClassDB::bind_method(_MD("can_collide_with_rigid_bodies"),&KinematicBody::can_collide_with_rigid_bodies);
+ ClassDB::bind_method(D_METHOD("set_collide_with_rigid_bodies","enable"),&KinematicBody::set_collide_with_rigid_bodies);
+ ClassDB::bind_method(D_METHOD("can_collide_with_rigid_bodies"),&KinematicBody::can_collide_with_rigid_bodies);
- ClassDB::bind_method(_MD("set_collide_with_character_bodies","enable"),&KinematicBody::set_collide_with_character_bodies);
- ClassDB::bind_method(_MD("can_collide_with_character_bodies"),&KinematicBody::can_collide_with_character_bodies);
+ ClassDB::bind_method(D_METHOD("set_collide_with_character_bodies","enable"),&KinematicBody::set_collide_with_character_bodies);
+ ClassDB::bind_method(D_METHOD("can_collide_with_character_bodies"),&KinematicBody::can_collide_with_character_bodies);
- ClassDB::bind_method(_MD("set_collision_margin","pixels"),&KinematicBody::set_collision_margin);
- ClassDB::bind_method(_MD("get_collision_margin","pixels"),&KinematicBody::get_collision_margin);
+ ClassDB::bind_method(D_METHOD("set_collision_margin","pixels"),&KinematicBody::set_collision_margin);
+ ClassDB::bind_method(D_METHOD("get_collision_margin","pixels"),&KinematicBody::get_collision_margin);
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/static"),_SCS("set_collide_with_static_bodies"),_SCS("can_collide_with_static_bodies"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/kinematic"),_SCS("set_collide_with_kinematic_bodies"),_SCS("can_collide_with_kinematic_bodies"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/rigid"),_SCS("set_collide_with_rigid_bodies"),_SCS("can_collide_with_rigid_bodies"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/character"),_SCS("set_collide_with_character_bodies"),_SCS("can_collide_with_character_bodies"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.001,256,0.001"),_SCS("set_collision_margin"),_SCS("get_collision_margin"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/static"),"set_collide_with_static_bodies","can_collide_with_static_bodies");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/kinematic"),"set_collide_with_kinematic_bodies","can_collide_with_kinematic_bodies");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/rigid"),"set_collide_with_rigid_bodies","can_collide_with_rigid_bodies");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/character"),"set_collide_with_character_bodies","can_collide_with_character_bodies");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.001,256,0.001"),"set_collision_margin","get_collision_margin");
}
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index f2668480f5..d48d75f464 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -167,23 +167,23 @@ bool Joint::get_exclude_nodes_from_collision() const{
void Joint::_bind_methods() {
- ClassDB::bind_method( _MD("set_node_a","node"), &Joint::set_node_a );
- ClassDB::bind_method( _MD("get_node_a"), &Joint::get_node_a );
+ ClassDB::bind_method( D_METHOD("set_node_a","node"), &Joint::set_node_a );
+ ClassDB::bind_method( D_METHOD("get_node_a"), &Joint::get_node_a );
- ClassDB::bind_method( _MD("set_node_b","node"), &Joint::set_node_b );
- ClassDB::bind_method( _MD("get_node_b"), &Joint::get_node_b );
+ ClassDB::bind_method( D_METHOD("set_node_b","node"), &Joint::set_node_b );
+ ClassDB::bind_method( D_METHOD("get_node_b"), &Joint::get_node_b );
- ClassDB::bind_method( _MD("set_solver_priority","priority"), &Joint::set_solver_priority );
- ClassDB::bind_method( _MD("get_solver_priority"), &Joint::get_solver_priority );
+ ClassDB::bind_method( D_METHOD("set_solver_priority","priority"), &Joint::set_solver_priority );
+ ClassDB::bind_method( D_METHOD("get_solver_priority"), &Joint::get_solver_priority );
- ClassDB::bind_method( _MD("set_exclude_nodes_from_collision","enable"), &Joint::set_exclude_nodes_from_collision );
- ClassDB::bind_method( _MD("get_exclude_nodes_from_collision"), &Joint::get_exclude_nodes_from_collision );
+ ClassDB::bind_method( D_METHOD("set_exclude_nodes_from_collision","enable"), &Joint::set_exclude_nodes_from_collision );
+ ClassDB::bind_method( D_METHOD("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::NODE_PATH, "nodes/node_a"), "set_node_a","get_node_a") ;
+ ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_b"), "set_node_b","get_node_b") ;
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "solver/priority",PROPERTY_HINT_RANGE,"1,8,1"), "set_solver_priority","get_solver_priority") ;
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "collision/exclude_nodes"), _SCS("set_exclude_nodes_from_collision"),_SCS("get_exclude_nodes_from_collision") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "collision/exclude_nodes"), "set_exclude_nodes_from_collision","get_exclude_nodes_from_collision") ;
@@ -203,12 +203,12 @@ Joint::Joint() {
void PinJoint::_bind_methods() {
- ClassDB::bind_method(_MD("set_param","param","value"),&PinJoint::set_param);
- ClassDB::bind_method(_MD("get_param","param"),&PinJoint::get_param);
+ ClassDB::bind_method(D_METHOD("set_param","param","value"),&PinJoint::set_param);
+ ClassDB::bind_method(D_METHOD("get_param","param"),&PinJoint::get_param);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_BIAS );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/damping",PROPERTY_HINT_RANGE,"0.01,8.0,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_DAMPING );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/impulse_clamp",PROPERTY_HINT_RANGE,"0.0,64.0,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_IMPULSE_CLAMP );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),"set_param","get_param", PARAM_BIAS );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/damping",PROPERTY_HINT_RANGE,"0.01,8.0,0.01"),"set_param","get_param", PARAM_DAMPING );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/impulse_clamp",PROPERTY_HINT_RANGE,"0.0,64.0,0.01"),"set_param","get_param", PARAM_IMPULSE_CLAMP );
BIND_CONSTANT( PARAM_BIAS );
BIND_CONSTANT( PARAM_DAMPING );
@@ -292,30 +292,30 @@ float HingeJoint::_get_lower_limit() const {
void HingeJoint::_bind_methods() {
- ClassDB::bind_method(_MD("set_param","param","value"),&HingeJoint::set_param);
- ClassDB::bind_method(_MD("get_param","param"),&HingeJoint::get_param);
+ ClassDB::bind_method(D_METHOD("set_param","param","value"),&HingeJoint::set_param);
+ ClassDB::bind_method(D_METHOD("get_param","param"),&HingeJoint::get_param);
- ClassDB::bind_method(_MD("set_flag","flag","enabled"),&HingeJoint::set_flag);
- ClassDB::bind_method(_MD("get_flag","flag"),&HingeJoint::get_flag);
+ ClassDB::bind_method(D_METHOD("set_flag","flag","enabled"),&HingeJoint::set_flag);
+ ClassDB::bind_method(D_METHOD("get_flag","flag"),&HingeJoint::get_flag);
- ClassDB::bind_method(_MD("_set_upper_limit","upper_limit"),&HingeJoint::_set_upper_limit);
- ClassDB::bind_method(_MD("_get_upper_limit"),&HingeJoint::_get_upper_limit);
+ ClassDB::bind_method(D_METHOD("_set_upper_limit","upper_limit"),&HingeJoint::_set_upper_limit);
+ ClassDB::bind_method(D_METHOD("_get_upper_limit"),&HingeJoint::_get_upper_limit);
- ClassDB::bind_method(_MD("_set_lower_limit","lower_limit"),&HingeJoint::_set_lower_limit);
- ClassDB::bind_method(_MD("_get_lower_limit"),&HingeJoint::_get_lower_limit);
+ ClassDB::bind_method(D_METHOD("_set_lower_limit","lower_limit"),&HingeJoint::_set_lower_limit);
+ ClassDB::bind_method(D_METHOD("_get_lower_limit"),&HingeJoint::_get_lower_limit);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_BIAS );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"params/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),"set_param","get_param", PARAM_BIAS );
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"angular_limit/enable"),_SCS("set_flag"),_SCS("get_flag"), FLAG_USE_LIMIT );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/upper",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_upper_limit"),_SCS("_get_upper_limit") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/lower",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_lower_limit"),_SCS("_get_lower_limit") );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LIMIT_BIAS );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LIMIT_SOFTNESS );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/relaxation",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LIMIT_RELAXATION );
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"angular_limit/enable"),"set_flag","get_flag", FLAG_USE_LIMIT );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/upper",PROPERTY_HINT_RANGE,"-180,180,0.1"),"_set_upper_limit","_get_upper_limit") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/lower",PROPERTY_HINT_RANGE,"-180,180,0.1"),"_set_lower_limit","_get_lower_limit") ;
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/bias",PROPERTY_HINT_RANGE,"0.01,0.99,0.01"),"set_param","get_param", PARAM_LIMIT_BIAS );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param","get_param", PARAM_LIMIT_SOFTNESS );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/relaxation",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param","get_param", PARAM_LIMIT_RELAXATION );
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"motor/enable"),_SCS("set_flag"),_SCS("get_flag"), FLAG_ENABLE_MOTOR );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"motor/target_velocity",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_MOTOR_TARGET_VELOCITY );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"motor/max_impulse",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_MOTOR_MAX_IMPULSE);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"motor/enable"),"set_flag","get_flag", FLAG_ENABLE_MOTOR );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"motor/target_velocity",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),"set_param","get_param", PARAM_MOTOR_TARGET_VELOCITY );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"motor/max_impulse",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),"set_param","get_param", PARAM_MOTOR_MAX_IMPULSE);
BIND_CONSTANT( PARAM_BIAS );
@@ -447,40 +447,40 @@ float SliderJoint::_get_lower_limit_angular() const {
void SliderJoint::_bind_methods() {
- ClassDB::bind_method(_MD("set_param","param","value"),&SliderJoint::set_param);
- ClassDB::bind_method(_MD("get_param","param"),&SliderJoint::get_param);
+ ClassDB::bind_method(D_METHOD("set_param","param","value"),&SliderJoint::set_param);
+ ClassDB::bind_method(D_METHOD("get_param","param"),&SliderJoint::get_param);
- ClassDB::bind_method(_MD("_set_upper_limit_angular","upper_limit_angular"),&SliderJoint::_set_upper_limit_angular);
- ClassDB::bind_method(_MD("_get_upper_limit_angular"),&SliderJoint::_get_upper_limit_angular);
+ ClassDB::bind_method(D_METHOD("_set_upper_limit_angular","upper_limit_angular"),&SliderJoint::_set_upper_limit_angular);
+ ClassDB::bind_method(D_METHOD("_get_upper_limit_angular"),&SliderJoint::_get_upper_limit_angular);
- ClassDB::bind_method(_MD("_set_lower_limit_angular","lower_limit_angular"),&SliderJoint::_set_lower_limit_angular);
- ClassDB::bind_method(_MD("_get_lower_limit_angular"),&SliderJoint::_get_lower_limit_angular);
+ ClassDB::bind_method(D_METHOD("_set_lower_limit_angular","lower_limit_angular"),&SliderJoint::_set_lower_limit_angular);
+ ClassDB::bind_method(D_METHOD("_get_lower_limit_angular"),&SliderJoint::_get_lower_limit_angular);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/upper_distance",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_UPPER);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/lower_distance",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_LOWER);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_RESTITUTION);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_LIMIT_DAMPING);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_MOTION_SOFTNESS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_MOTION_RESTITUTION);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_MOTION_DAMPING);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_LINEAR_ORTHOGONAL_DAMPING);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/upper_distance",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),"set_param","get_param", PARAM_LINEAR_LIMIT_UPPER);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/lower_distance",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),"set_param","get_param", PARAM_LINEAR_LIMIT_LOWER);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_LIMIT_RESTITUTION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_limit/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_LIMIT_DAMPING);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_MOTION_SOFTNESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_MOTION_RESTITUTION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_motion/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_MOTION_DAMPING);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_ORTHOGONAL_SOFTNESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_ORTHOGONAL_RESTITUTION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"linear_ortho/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,"set_param","get_param", PARAM_LINEAR_ORTHOGONAL_DAMPING);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_upper_limit_angular"),_SCS("_get_upper_limit_angular") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_lower_limit_angular"),_SCS("_get_lower_limit_angular") );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_LIMIT_RESTITUTION);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_LIMIT_DAMPING);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_MOTION_SOFTNESS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_MOTION_RESTITUTION);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_MOTION_DAMPING);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_ANGULAR_ORTHOGONAL_DAMPING);
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.1"),"_set_upper_limit_angular","_get_upper_limit_angular") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_limit/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.1"),"_set_lower_limit_angular","_get_lower_limit_angular") ;
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_LIMIT_RESTITUTION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_limit/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_LIMIT_DAMPING);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_MOTION_SOFTNESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_MOTION_RESTITUTION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_motion/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_MOTION_DAMPING);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_ORTHOGONAL_SOFTNESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/restitution",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_ORTHOGONAL_RESTITUTION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"angular_ortho/damping",PROPERTY_HINT_RANGE,"0,16.0,0.01") ,"set_param","get_param", PARAM_ANGULAR_ORTHOGONAL_DAMPING);
BIND_CONSTANT( PARAM_LINEAR_LIMIT_UPPER);
@@ -612,24 +612,24 @@ float ConeTwistJoint::_get_twist_span() const {
void ConeTwistJoint::_bind_methods() {
- ClassDB::bind_method(_MD("set_param","param","value"),&ConeTwistJoint::set_param);
- ClassDB::bind_method(_MD("get_param","param"),&ConeTwistJoint::get_param);
+ ClassDB::bind_method(D_METHOD("set_param","param","value"),&ConeTwistJoint::set_param);
+ ClassDB::bind_method(D_METHOD("get_param","param"),&ConeTwistJoint::get_param);
- ClassDB::bind_method(_MD("_set_swing_span","swing_span"),&ConeTwistJoint::_set_swing_span);
- ClassDB::bind_method(_MD("_get_swing_span"),&ConeTwistJoint::_get_swing_span);
+ ClassDB::bind_method(D_METHOD("_set_swing_span","swing_span"),&ConeTwistJoint::_set_swing_span);
+ ClassDB::bind_method(D_METHOD("_get_swing_span"),&ConeTwistJoint::_get_swing_span);
- ClassDB::bind_method(_MD("_set_twist_span","twist_span"),&ConeTwistJoint::_set_twist_span);
- ClassDB::bind_method(_MD("_get_twist_span"),&ConeTwistJoint::_get_twist_span);
+ ClassDB::bind_method(D_METHOD("_set_twist_span","twist_span"),&ConeTwistJoint::_set_twist_span);
+ ClassDB::bind_method(D_METHOD("_get_twist_span"),&ConeTwistJoint::_get_twist_span);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"swing_span",PROPERTY_HINT_RANGE,"-180,180,0.1"),_SCS("_set_swing_span"),_SCS("_get_swing_span") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"twist_span",PROPERTY_HINT_RANGE,"-40000,40000,0.1"),_SCS("_set_twist_span"),_SCS("_get_twist_span") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"swing_span",PROPERTY_HINT_RANGE,"-180,180,0.1"),"_set_swing_span","_get_swing_span") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"twist_span",PROPERTY_HINT_RANGE,"-40000,40000,0.1"),"_set_twist_span","_get_twist_span") ;
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bias",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_BIAS );
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_SOFTNESS);
- ADD_PROPERTYI( PropertyInfo(Variant::REAL,"relaxation",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,_SCS("set_param"),_SCS("get_param"), PARAM_RELAXATION);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bias",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_BIAS );
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"softness",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_SOFTNESS);
+ ADD_PROPERTYI( PropertyInfo(Variant::REAL,"relaxation",PROPERTY_HINT_RANGE,"0.01,16.0,0.01") ,"set_param","get_param", PARAM_RELAXATION);
BIND_CONSTANT( PARAM_SWING_SPAN );
BIND_CONSTANT( PARAM_TWIST_SPAN );
@@ -771,96 +771,96 @@ float Generic6DOFJoint::_get_angular_lo_limit_z() const{
void Generic6DOFJoint::_bind_methods(){
- ClassDB::bind_method(_MD("_set_angular_hi_limit_x","angle"),&Generic6DOFJoint::_set_angular_hi_limit_x);
- ClassDB::bind_method(_MD("_get_angular_hi_limit_x"),&Generic6DOFJoint::_get_angular_hi_limit_x);
-
- ClassDB::bind_method(_MD("_set_angular_lo_limit_x","angle"),&Generic6DOFJoint::_set_angular_lo_limit_x);
- ClassDB::bind_method(_MD("_get_angular_lo_limit_x"),&Generic6DOFJoint::_get_angular_lo_limit_x);
-
- ClassDB::bind_method(_MD("_set_angular_hi_limit_y","angle"),&Generic6DOFJoint::_set_angular_hi_limit_y);
- ClassDB::bind_method(_MD("_get_angular_hi_limit_y"),&Generic6DOFJoint::_get_angular_hi_limit_y);
-
- ClassDB::bind_method(_MD("_set_angular_lo_limit_y","angle"),&Generic6DOFJoint::_set_angular_lo_limit_y);
- ClassDB::bind_method(_MD("_get_angular_lo_limit_y"),&Generic6DOFJoint::_get_angular_lo_limit_y);
-
- ClassDB::bind_method(_MD("_set_angular_hi_limit_z","angle"),&Generic6DOFJoint::_set_angular_hi_limit_z);
- ClassDB::bind_method(_MD("_get_angular_hi_limit_z"),&Generic6DOFJoint::_get_angular_hi_limit_z);
-
- ClassDB::bind_method(_MD("_set_angular_lo_limit_z","angle"),&Generic6DOFJoint::_set_angular_lo_limit_z);
- ClassDB::bind_method(_MD("_get_angular_lo_limit_z"),&Generic6DOFJoint::_get_angular_lo_limit_z);
-
- ClassDB::bind_method(_MD("set_param_x","param","value"),&Generic6DOFJoint::set_param_x);
- ClassDB::bind_method(_MD("get_param_x","param"),&Generic6DOFJoint::get_param_x);
-
- ClassDB::bind_method(_MD("set_param_y","param","value"),&Generic6DOFJoint::set_param_y);
- ClassDB::bind_method(_MD("get_param_y","param"),&Generic6DOFJoint::get_param_y);
-
- ClassDB::bind_method(_MD("set_param_z","param","value"),&Generic6DOFJoint::set_param_z);
- ClassDB::bind_method(_MD("get_param_z","param"),&Generic6DOFJoint::get_param_z);
-
- ClassDB::bind_method(_MD("set_flag_x","flag","value"),&Generic6DOFJoint::set_flag_x);
- ClassDB::bind_method(_MD("get_flag_x","flag"),&Generic6DOFJoint::get_flag_x);
-
- ClassDB::bind_method(_MD("set_flag_y","flag","value"),&Generic6DOFJoint::set_flag_y);
- ClassDB::bind_method(_MD("get_flag_y","flag"),&Generic6DOFJoint::get_flag_y);
-
- ClassDB::bind_method(_MD("set_flag_z","flag","value"),&Generic6DOFJoint::set_flag_z);
- ClassDB::bind_method(_MD("get_flag_z","flag"),&Generic6DOFJoint::get_flag_z);
-
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_x/enabled"),_SCS("set_flag_x"),_SCS("get_flag_x"),FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/upper_distance"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/lower_distance"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_LINEAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_x/enabled"),_SCS("set_flag_x"),_SCS("get_flag_x"),FLAG_ENABLE_ANGULAR_LIMIT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_x/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_hi_limit_x"),_SCS("_get_angular_hi_limit_x"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_x/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_lo_limit_x"),_SCS("_get_angular_lo_limit_x"));
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/force_limit"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_FORCE_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/erp"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_ERP);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_x/enabled"),_SCS("set_flag_x"),_SCS("get_flag_x"),FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_x/target_velocity"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_x/force_limit"),_SCS("set_param_x"),_SCS("get_param_x"),PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_y/enabled"),_SCS("set_flag_y"),_SCS("get_flag_y"),FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/upper_distance"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/lower_distance"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_LINEAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_y/enabled"),_SCS("set_flag_y"),_SCS("get_flag_y"),FLAG_ENABLE_ANGULAR_LIMIT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_y/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_hi_limit_y"),_SCS("_get_angular_hi_limit_y"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_y/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_lo_limit_y"),_SCS("_get_angular_lo_limit_y"));
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/force_limit"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_FORCE_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/erp"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_ERP);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_y/enabled"),_SCS("set_flag_y"),_SCS("get_flag_y"),FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_y/target_velocity"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_y/force_limit"),_SCS("set_param_y"),_SCS("get_param_y"),PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_z/enabled"),_SCS("set_flag_z"),_SCS("get_flag_z"),FLAG_ENABLE_LINEAR_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/upper_distance"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_UPPER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/lower_distance"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_LOWER_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_LINEAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_z/enabled"),_SCS("set_flag_z"),_SCS("get_flag_z"),FLAG_ENABLE_ANGULAR_LIMIT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_z/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_hi_limit_z"),_SCS("_get_angular_hi_limit_z"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_z/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),_SCS("_set_angular_lo_limit_z"),_SCS("_get_angular_lo_limit_z"));
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_LIMIT_SOFTNESS);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_RESTITUTION);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_DAMPING);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/force_limit"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_FORCE_LIMIT);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/erp"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_ERP);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_z/enabled"),_SCS("set_flag_z"),_SCS("get_flag_z"),FLAG_ENABLE_MOTOR);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_z/target_velocity"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_z/force_limit"),_SCS("set_param_z"),_SCS("get_param_z"),PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+ ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_x","angle"),&Generic6DOFJoint::_set_angular_hi_limit_x);
+ ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_x"),&Generic6DOFJoint::_get_angular_hi_limit_x);
+
+ ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_x","angle"),&Generic6DOFJoint::_set_angular_lo_limit_x);
+ ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_x"),&Generic6DOFJoint::_get_angular_lo_limit_x);
+
+ ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_y","angle"),&Generic6DOFJoint::_set_angular_hi_limit_y);
+ ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_y"),&Generic6DOFJoint::_get_angular_hi_limit_y);
+
+ ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_y","angle"),&Generic6DOFJoint::_set_angular_lo_limit_y);
+ ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_y"),&Generic6DOFJoint::_get_angular_lo_limit_y);
+
+ ClassDB::bind_method(D_METHOD("_set_angular_hi_limit_z","angle"),&Generic6DOFJoint::_set_angular_hi_limit_z);
+ ClassDB::bind_method(D_METHOD("_get_angular_hi_limit_z"),&Generic6DOFJoint::_get_angular_hi_limit_z);
+
+ ClassDB::bind_method(D_METHOD("_set_angular_lo_limit_z","angle"),&Generic6DOFJoint::_set_angular_lo_limit_z);
+ ClassDB::bind_method(D_METHOD("_get_angular_lo_limit_z"),&Generic6DOFJoint::_get_angular_lo_limit_z);
+
+ ClassDB::bind_method(D_METHOD("set_param_x","param","value"),&Generic6DOFJoint::set_param_x);
+ ClassDB::bind_method(D_METHOD("get_param_x","param"),&Generic6DOFJoint::get_param_x);
+
+ ClassDB::bind_method(D_METHOD("set_param_y","param","value"),&Generic6DOFJoint::set_param_y);
+ ClassDB::bind_method(D_METHOD("get_param_y","param"),&Generic6DOFJoint::get_param_y);
+
+ ClassDB::bind_method(D_METHOD("set_param_z","param","value"),&Generic6DOFJoint::set_param_z);
+ ClassDB::bind_method(D_METHOD("get_param_z","param"),&Generic6DOFJoint::get_param_z);
+
+ ClassDB::bind_method(D_METHOD("set_flag_x","flag","value"),&Generic6DOFJoint::set_flag_x);
+ ClassDB::bind_method(D_METHOD("get_flag_x","flag"),&Generic6DOFJoint::get_flag_x);
+
+ ClassDB::bind_method(D_METHOD("set_flag_y","flag","value"),&Generic6DOFJoint::set_flag_y);
+ ClassDB::bind_method(D_METHOD("get_flag_y","flag"),&Generic6DOFJoint::get_flag_y);
+
+ ClassDB::bind_method(D_METHOD("set_flag_z","flag","value"),&Generic6DOFJoint::set_flag_z);
+ ClassDB::bind_method(D_METHOD("get_flag_z","flag"),&Generic6DOFJoint::get_flag_z);
+
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_x/enabled"),"set_flag_x","get_flag_x",FLAG_ENABLE_LINEAR_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/upper_distance"),"set_param_x","get_param_x",PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/lower_distance"),"set_param_x","get_param_x",PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_x","get_param_x",PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_x","get_param_x",PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_x/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_x","get_param_x",PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_x/enabled"),"set_flag_x","get_flag_x",FLAG_ENABLE_ANGULAR_LIMIT);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_x/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),"_set_angular_hi_limit_x","_get_angular_hi_limit_x");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_x/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),"_set_angular_lo_limit_x","_get_angular_lo_limit_x");
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_x","get_param_x",PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_x","get_param_x",PARAM_ANGULAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_x","get_param_x",PARAM_ANGULAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/force_limit"),"set_param_x","get_param_x",PARAM_ANGULAR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_x/erp"),"set_param_x","get_param_x",PARAM_ANGULAR_ERP);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_x/enabled"),"set_flag_x","get_flag_x",FLAG_ENABLE_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_x/target_velocity"),"set_param_x","get_param_x",PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_x/force_limit"),"set_param_x","get_param_x",PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_y/enabled"),"set_flag_y","get_flag_y",FLAG_ENABLE_LINEAR_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/upper_distance"),"set_param_y","get_param_y",PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/lower_distance"),"set_param_y","get_param_y",PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_y","get_param_y",PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_y","get_param_y",PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_y/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_y","get_param_y",PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_y/enabled"),"set_flag_y","get_flag_y",FLAG_ENABLE_ANGULAR_LIMIT);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_y/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),"_set_angular_hi_limit_y","_get_angular_hi_limit_y");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_y/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),"_set_angular_lo_limit_y","_get_angular_lo_limit_y");
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_y","get_param_y",PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_y","get_param_y",PARAM_ANGULAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_y","get_param_y",PARAM_ANGULAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/force_limit"),"set_param_y","get_param_y",PARAM_ANGULAR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_y/erp"),"set_param_y","get_param_y",PARAM_ANGULAR_ERP);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_y/enabled"),"set_flag_y","get_flag_y",FLAG_ENABLE_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_y/target_velocity"),"set_param_y","get_param_y",PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_y/force_limit"),"set_param_y","get_param_y",PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"linear_limit_z/enabled"),"set_flag_z","get_flag_z",FLAG_ENABLE_LINEAR_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/upper_distance"),"set_param_z","get_param_z",PARAM_LINEAR_UPPER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/lower_distance"),"set_param_z","get_param_z",PARAM_LINEAR_LOWER_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_z","get_param_z",PARAM_LINEAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_z","get_param_z",PARAM_LINEAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"linear_limit_z/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_z","get_param_z",PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_limit_z/enabled"),"set_flag_z","get_flag_z",FLAG_ENABLE_ANGULAR_LIMIT);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_z/upper_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),"_set_angular_hi_limit_z","_get_angular_hi_limit_z");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"angular_limit_z/lower_angle",PROPERTY_HINT_RANGE,"-180,180,0.01"),"_set_angular_lo_limit_z","_get_angular_lo_limit_z");
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/softness",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_z","get_param_z",PARAM_ANGULAR_LIMIT_SOFTNESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/restitution",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_z","get_param_z",PARAM_ANGULAR_RESTITUTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/damping",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_param_z","get_param_z",PARAM_ANGULAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/force_limit"),"set_param_z","get_param_z",PARAM_ANGULAR_FORCE_LIMIT);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_limit_z/erp"),"set_param_z","get_param_z",PARAM_ANGULAR_ERP);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"angular_motor_z/enabled"),"set_flag_z","get_flag_z",FLAG_ENABLE_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_z/target_velocity"),"set_param_z","get_param_z",PARAM_ANGULAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"angular_motor_z/force_limit"),"set_param_z","get_param_z",PARAM_ANGULAR_MOTOR_FORCE_LIMIT);
BIND_CONSTANT( PARAM_LINEAR_LOWER_LIMIT);
@@ -1171,22 +1171,22 @@ RID PhysicsJoint::_get_visual_instance_rid() const {
void PhysicsJoint::_bind_methods() {
- ClassDB::bind_method(_MD("_get_visual_instance_rid"),&PhysicsJoint::_get_visual_instance_rid);
- ClassDB::bind_method(_MD("set_body_A","path"),&PhysicsJoint::set_body_A);
- ClassDB::bind_method(_MD("set_body_B"),&PhysicsJoint::set_body_B);
- ClassDB::bind_method(_MD("get_body_A","path"),&PhysicsJoint::get_body_A);
- ClassDB::bind_method(_MD("get_body_B"),&PhysicsJoint::get_body_B);
+ ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"),&PhysicsJoint::_get_visual_instance_rid);
+ ClassDB::bind_method(D_METHOD("set_body_A","path"),&PhysicsJoint::set_body_A);
+ ClassDB::bind_method(D_METHOD("set_body_B"),&PhysicsJoint::set_body_B);
+ ClassDB::bind_method(D_METHOD("get_body_A","path"),&PhysicsJoint::get_body_A);
+ ClassDB::bind_method(D_METHOD("get_body_B"),&PhysicsJoint::get_body_B);
- ClassDB::bind_method(_MD("set_active","active"),&PhysicsJoint::set_active);
- ClassDB::bind_method(_MD("is_active"),&PhysicsJoint::is_active);
+ ClassDB::bind_method(D_METHOD("set_active","active"),&PhysicsJoint::set_active);
+ ClassDB::bind_method(D_METHOD("is_active"),&PhysicsJoint::is_active);
- ClassDB::bind_method(_MD("set_disable_collision","disable"),&PhysicsJoint::set_disable_collision);
- ClassDB::bind_method(_MD("has_disable_collision"),&PhysicsJoint::has_disable_collision);
+ ClassDB::bind_method(D_METHOD("set_disable_collision","disable"),&PhysicsJoint::set_disable_collision);
+ ClassDB::bind_method(D_METHOD("has_disable_collision"),&PhysicsJoint::has_disable_collision);
ClassDB::bind_method("reconnect",&PhysicsJoint::reconnect);
- ClassDB::bind_method(_MD("get_rid"),&PhysicsJoint::get_rid);
+ ClassDB::bind_method(D_METHOD("get_rid"),&PhysicsJoint::get_rid);
}
diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp
index 054b61a4ed..19f1261238 100644
--- a/scene/3d/portal.cpp
+++ b/scene/3d/portal.cpp
@@ -29,7 +29,7 @@
#include "portal.h"
#include "servers/visual_server.h"
#include "scene/resources/surface_tool.h"
-#include "globals.h"
+#include "global_config.h"
bool Portal::_set(const StringName& p_name, const Variant& p_value) {
@@ -197,20 +197,20 @@ Color Portal::get_disabled_color() const {
void Portal::_bind_methods() {
- ClassDB::bind_method(_MD("set_shape","points"),&Portal::set_shape);
- ClassDB::bind_method(_MD("get_shape"),&Portal::get_shape);
+ ClassDB::bind_method(D_METHOD("set_shape","points"),&Portal::set_shape);
+ ClassDB::bind_method(D_METHOD("get_shape"),&Portal::get_shape);
- ClassDB::bind_method(_MD("set_enabled","enable"),&Portal::set_enabled);
- ClassDB::bind_method(_MD("is_enabled"),&Portal::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled","enable"),&Portal::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"),&Portal::is_enabled);
- ClassDB::bind_method(_MD("set_disable_distance","distance"),&Portal::set_disable_distance);
- ClassDB::bind_method(_MD("get_disable_distance"),&Portal::get_disable_distance);
+ ClassDB::bind_method(D_METHOD("set_disable_distance","distance"),&Portal::set_disable_distance);
+ ClassDB::bind_method(D_METHOD("get_disable_distance"),&Portal::get_disable_distance);
- ClassDB::bind_method(_MD("set_disabled_color","color"),&Portal::set_disabled_color);
- ClassDB::bind_method(_MD("get_disabled_color"),&Portal::get_disabled_color);
+ ClassDB::bind_method(D_METHOD("set_disabled_color","color"),&Portal::set_disabled_color);
+ ClassDB::bind_method(D_METHOD("get_disabled_color"),&Portal::get_disabled_color);
- ClassDB::bind_method(_MD("set_connect_range","range"),&Portal::set_connect_range);
- ClassDB::bind_method(_MD("get_connect_range"),&Portal::get_connect_range);
+ ClassDB::bind_method(D_METHOD("set_connect_range","range"),&Portal::set_connect_range);
+ ClassDB::bind_method(D_METHOD("get_connect_range"),&Portal::get_connect_range);
}
diff --git a/scene/3d/proximity_group.cpp b/scene/3d/proximity_group.cpp
index 9f4b5c7a03..f0dc8cb2ed 100644
--- a/scene/3d/proximity_group.cpp
+++ b/scene/3d/proximity_group.cpp
@@ -171,14 +171,14 @@ Vector3 ProximityGroup::get_grid_radius() const {
void ProximityGroup::_bind_methods() {
- ClassDB::bind_method(_MD("set_group_name","name"), &ProximityGroup::set_group_name);
- ClassDB::bind_method(_MD("broadcast","name", "parameters"), &ProximityGroup::broadcast);
- ClassDB::bind_method(_MD("set_dispatch_mode","mode"), &ProximityGroup::set_dispatch_mode);
- ClassDB::bind_method(_MD("_proximity_group_broadcast","name","params"), &ProximityGroup::_proximity_group_broadcast);
- ClassDB::bind_method(_MD("set_grid_radius","radius"), &ProximityGroup::set_grid_radius);
- ClassDB::bind_method(_MD("get_grid_radius"), &ProximityGroup::get_grid_radius);
-
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "grid_radius"), _SCS("set_grid_radius"), _SCS("get_grid_radius"));
+ ClassDB::bind_method(D_METHOD("set_group_name","name"), &ProximityGroup::set_group_name);
+ ClassDB::bind_method(D_METHOD("broadcast","name", "parameters"), &ProximityGroup::broadcast);
+ ClassDB::bind_method(D_METHOD("set_dispatch_mode","mode"), &ProximityGroup::set_dispatch_mode);
+ ClassDB::bind_method(D_METHOD("_proximity_group_broadcast","name","params"), &ProximityGroup::_proximity_group_broadcast);
+ ClassDB::bind_method(D_METHOD("set_grid_radius","radius"), &ProximityGroup::set_grid_radius);
+ ClassDB::bind_method(D_METHOD("get_grid_radius"), &ProximityGroup::get_grid_radius);
+
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "grid_radius"), "set_grid_radius", "get_grid_radius");
ADD_SIGNAL( MethodInfo("broadcast", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::ARRAY, "parameters")) );
};
diff --git a/scene/3d/quad.cpp b/scene/3d/quad.cpp
index d1cef0e851..e740769bd4 100644
--- a/scene/3d/quad.cpp
+++ b/scene/3d/quad.cpp
@@ -199,22 +199,22 @@ Rect3 Quad::get_aabb() const {
void Quad::_bind_methods(){
- ClassDB::bind_method(_MD("set_axis","axis"),&Quad::set_axis);
- ClassDB::bind_method(_MD("get_axis"),&Quad::get_axis);
+ ClassDB::bind_method(D_METHOD("set_axis","axis"),&Quad::set_axis);
+ ClassDB::bind_method(D_METHOD("get_axis"),&Quad::get_axis);
- ClassDB::bind_method(_MD("set_size","size"),&Quad::set_size);
- ClassDB::bind_method(_MD("get_size"),&Quad::get_size);
+ ClassDB::bind_method(D_METHOD("set_size","size"),&Quad::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"),&Quad::get_size);
- ClassDB::bind_method(_MD("set_centered","centered"),&Quad::set_centered);
- ClassDB::bind_method(_MD("is_centered"),&Quad::is_centered);
+ ClassDB::bind_method(D_METHOD("set_centered","centered"),&Quad::set_centered);
+ ClassDB::bind_method(D_METHOD("is_centered"),&Quad::is_centered);
- ClassDB::bind_method(_MD("set_offset","offset"),&Quad::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&Quad::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&Quad::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&Quad::get_offset);
- ADD_PROPERTY( PropertyInfo( Variant::INT, "axis", PROPERTY_HINT_ENUM,"X,Y,Z" ), _SCS("set_axis"), _SCS("get_axis"));
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "size" ), _SCS("set_size"), _SCS("get_size"));
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset" ), _SCS("set_offset"), _SCS("get_offset"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered" ), _SCS("set_centered"), _SCS("is_centered"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "axis", PROPERTY_HINT_ENUM,"X,Y,Z" ), "set_axis", "get_axis");
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "size" ), "set_size", "get_size");
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset" ), "set_offset", "get_offset");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered" ), "set_centered", "is_centered");
}
diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp
index 8216d7295f..6be8b89441 100644
--- a/scene/3d/ray_cast.cpp
+++ b/scene/3d/ray_cast.cpp
@@ -210,38 +210,38 @@ void RayCast::clear_exceptions(){
void RayCast::_bind_methods() {
- ClassDB::bind_method(_MD("set_enabled","enabled"),&RayCast::set_enabled);
- ClassDB::bind_method(_MD("is_enabled"),&RayCast::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled","enabled"),&RayCast::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"),&RayCast::is_enabled);
- ClassDB::bind_method(_MD("set_cast_to","local_point"),&RayCast::set_cast_to);
- ClassDB::bind_method(_MD("get_cast_to"),&RayCast::get_cast_to);
+ ClassDB::bind_method(D_METHOD("set_cast_to","local_point"),&RayCast::set_cast_to);
+ ClassDB::bind_method(D_METHOD("get_cast_to"),&RayCast::get_cast_to);
- ClassDB::bind_method(_MD("is_colliding"),&RayCast::is_colliding);
- ClassDB::bind_method(_MD("force_raycast_update"),&RayCast::force_raycast_update);
+ ClassDB::bind_method(D_METHOD("is_colliding"),&RayCast::is_colliding);
+ ClassDB::bind_method(D_METHOD("force_raycast_update"),&RayCast::force_raycast_update);
- ClassDB::bind_method(_MD("get_collider"),&RayCast::get_collider);
- ClassDB::bind_method(_MD("get_collider_shape"),&RayCast::get_collider_shape);
- ClassDB::bind_method(_MD("get_collision_point"),&RayCast::get_collision_point);
- ClassDB::bind_method(_MD("get_collision_normal"),&RayCast::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collider"),&RayCast::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"),&RayCast::get_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_collision_point"),&RayCast::get_collision_point);
+ ClassDB::bind_method(D_METHOD("get_collision_normal"),&RayCast::get_collision_normal);
- ClassDB::bind_method(_MD("add_exception_rid","rid"),&RayCast::add_exception_rid);
- ClassDB::bind_method(_MD("add_exception","node"),&RayCast::add_exception);
+ ClassDB::bind_method(D_METHOD("add_exception_rid","rid"),&RayCast::add_exception_rid);
+ ClassDB::bind_method(D_METHOD("add_exception","node"),&RayCast::add_exception);
- ClassDB::bind_method(_MD("remove_exception_rid","rid"),&RayCast::remove_exception_rid);
- ClassDB::bind_method(_MD("remove_exception","node"),&RayCast::remove_exception);
+ ClassDB::bind_method(D_METHOD("remove_exception_rid","rid"),&RayCast::remove_exception_rid);
+ ClassDB::bind_method(D_METHOD("remove_exception","node"),&RayCast::remove_exception);
- ClassDB::bind_method(_MD("clear_exceptions"),&RayCast::clear_exceptions);
+ ClassDB::bind_method(D_METHOD("clear_exceptions"),&RayCast::clear_exceptions);
- ClassDB::bind_method(_MD("set_layer_mask","mask"),&RayCast::set_layer_mask);
- ClassDB::bind_method(_MD("get_layer_mask"),&RayCast::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","mask"),&RayCast::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&RayCast::get_layer_mask);
- ClassDB::bind_method(_MD("set_type_mask","mask"),&RayCast::set_type_mask);
- ClassDB::bind_method(_MD("get_type_mask"),&RayCast::get_type_mask);
+ ClassDB::bind_method(D_METHOD("set_type_mask","mask"),&RayCast::set_type_mask);
+ ClassDB::bind_method(D_METHOD("get_type_mask"),&RayCast::get_type_mask);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled"));
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"layer_mask",PROPERTY_HINT_LAYERS_3D_PHYSICS),_SCS("set_layer_mask"),_SCS("get_layer_mask"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"type_mask",PROPERTY_HINT_FLAGS,"Static,Kinematic,Rigid,Character,Area"),_SCS("set_type_mask"),_SCS("get_type_mask"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),"set_enabled","is_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"cast_to"),"set_cast_to","get_cast_to");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"layer_mask",PROPERTY_HINT_LAYERS_3D_PHYSICS),"set_layer_mask","get_layer_mask");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"type_mask",PROPERTY_HINT_FLAGS,"Static,Kinematic,Rigid,Character,Area"),"set_type_mask","get_type_mask");
}
RayCast::RayCast() {
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index d9592d9484..db18e70ae1 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* reflection_probe.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "reflection_probe.h"
@@ -185,57 +213,57 @@ void ReflectionProbe::_validate_property(PropertyInfo& property) const {
void ReflectionProbe::_bind_methods() {
- ClassDB::bind_method(_MD("set_intensity","intensity"),&ReflectionProbe::set_intensity);
- ClassDB::bind_method(_MD("get_intensity"),&ReflectionProbe::get_intensity);
+ ClassDB::bind_method(D_METHOD("set_intensity","intensity"),&ReflectionProbe::set_intensity);
+ ClassDB::bind_method(D_METHOD("get_intensity"),&ReflectionProbe::get_intensity);
- ClassDB::bind_method(_MD("set_interior_ambient","ambient"),&ReflectionProbe::set_interior_ambient);
- ClassDB::bind_method(_MD("get_interior_ambient"),&ReflectionProbe::get_interior_ambient);
+ ClassDB::bind_method(D_METHOD("set_interior_ambient","ambient"),&ReflectionProbe::set_interior_ambient);
+ ClassDB::bind_method(D_METHOD("get_interior_ambient"),&ReflectionProbe::get_interior_ambient);
- ClassDB::bind_method(_MD("set_interior_ambient_energy","ambient_energy"),&ReflectionProbe::set_interior_ambient_energy);
- ClassDB::bind_method(_MD("get_interior_ambient_energy"),&ReflectionProbe::get_interior_ambient_energy);
+ ClassDB::bind_method(D_METHOD("set_interior_ambient_energy","ambient_energy"),&ReflectionProbe::set_interior_ambient_energy);
+ ClassDB::bind_method(D_METHOD("get_interior_ambient_energy"),&ReflectionProbe::get_interior_ambient_energy);
- ClassDB::bind_method(_MD("set_interior_ambient_probe_contribution","ambient_probe_contribution"),&ReflectionProbe::set_interior_ambient_probe_contribution);
- ClassDB::bind_method(_MD("get_interior_ambient_probe_contribution"),&ReflectionProbe::get_interior_ambient_probe_contribution);
+ ClassDB::bind_method(D_METHOD("set_interior_ambient_probe_contribution","ambient_probe_contribution"),&ReflectionProbe::set_interior_ambient_probe_contribution);
+ ClassDB::bind_method(D_METHOD("get_interior_ambient_probe_contribution"),&ReflectionProbe::get_interior_ambient_probe_contribution);
- ClassDB::bind_method(_MD("set_max_distance","max_distance"),&ReflectionProbe::set_max_distance);
- ClassDB::bind_method(_MD("get_max_distance"),&ReflectionProbe::get_max_distance);
+ ClassDB::bind_method(D_METHOD("set_max_distance","max_distance"),&ReflectionProbe::set_max_distance);
+ ClassDB::bind_method(D_METHOD("get_max_distance"),&ReflectionProbe::get_max_distance);
- ClassDB::bind_method(_MD("set_extents","extents"),&ReflectionProbe::set_extents);
- ClassDB::bind_method(_MD("get_extents"),&ReflectionProbe::get_extents);
+ ClassDB::bind_method(D_METHOD("set_extents","extents"),&ReflectionProbe::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"),&ReflectionProbe::get_extents);
- ClassDB::bind_method(_MD("set_origin_offset","origin_offset"),&ReflectionProbe::set_origin_offset);
- ClassDB::bind_method(_MD("get_origin_offset"),&ReflectionProbe::get_origin_offset);
+ ClassDB::bind_method(D_METHOD("set_origin_offset","origin_offset"),&ReflectionProbe::set_origin_offset);
+ ClassDB::bind_method(D_METHOD("get_origin_offset"),&ReflectionProbe::get_origin_offset);
- ClassDB::bind_method(_MD("set_as_interior","enable"),&ReflectionProbe::set_as_interior);
- ClassDB::bind_method(_MD("is_set_as_interior"),&ReflectionProbe::is_set_as_interior);
+ ClassDB::bind_method(D_METHOD("set_as_interior","enable"),&ReflectionProbe::set_as_interior);
+ ClassDB::bind_method(D_METHOD("is_set_as_interior"),&ReflectionProbe::is_set_as_interior);
- ClassDB::bind_method(_MD("set_enable_box_projection","enable"),&ReflectionProbe::set_enable_box_projection);
- ClassDB::bind_method(_MD("is_box_projection_enabled"),&ReflectionProbe::is_box_projection_enabled);
+ ClassDB::bind_method(D_METHOD("set_enable_box_projection","enable"),&ReflectionProbe::set_enable_box_projection);
+ ClassDB::bind_method(D_METHOD("is_box_projection_enabled"),&ReflectionProbe::is_box_projection_enabled);
- ClassDB::bind_method(_MD("set_enable_shadows","enable"),&ReflectionProbe::set_enable_shadows);
- ClassDB::bind_method(_MD("are_shadows_enabled"),&ReflectionProbe::are_shadows_enabled);
+ ClassDB::bind_method(D_METHOD("set_enable_shadows","enable"),&ReflectionProbe::set_enable_shadows);
+ ClassDB::bind_method(D_METHOD("are_shadows_enabled"),&ReflectionProbe::are_shadows_enabled);
- ClassDB::bind_method(_MD("set_cull_mask","layers"),&ReflectionProbe::set_cull_mask);
- ClassDB::bind_method(_MD("get_cull_mask"),&ReflectionProbe::get_cull_mask);
+ ClassDB::bind_method(D_METHOD("set_cull_mask","layers"),&ReflectionProbe::set_cull_mask);
+ ClassDB::bind_method(D_METHOD("get_cull_mask"),&ReflectionProbe::get_cull_mask);
- ClassDB::bind_method(_MD("set_update_mode","mode"),&ReflectionProbe::set_update_mode);
- ClassDB::bind_method(_MD("get_update_mode"),&ReflectionProbe::get_update_mode);
+ ClassDB::bind_method(D_METHOD("set_update_mode","mode"),&ReflectionProbe::set_update_mode);
+ ClassDB::bind_method(D_METHOD("get_update_mode"),&ReflectionProbe::get_update_mode);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"update_mode",PROPERTY_HINT_ENUM,"Once,Always"),_SCS("set_update_mode"),_SCS("get_update_mode"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"intensity",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_intensity"),_SCS("get_intensity"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"max_distance",PROPERTY_HINT_RANGE,"0,16384,0.1"),_SCS("set_max_distance"),_SCS("get_max_distance"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"extents"),_SCS("set_extents"),_SCS("get_extents"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"origin_offset"),_SCS("set_origin_offset"),_SCS("get_origin_offset"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"box_projection"),_SCS("set_enable_box_projection"),_SCS("is_box_projection_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enable_shadows"),_SCS("set_enable_shadows"),_SCS("are_shadows_enabled"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mask",PROPERTY_HINT_LAYERS_3D_RENDER),_SCS("set_cull_mask"),_SCS("get_cull_mask"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"update_mode",PROPERTY_HINT_ENUM,"Once,Always"),"set_update_mode","get_update_mode");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"intensity",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_intensity","get_intensity");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"max_distance",PROPERTY_HINT_RANGE,"0,16384,0.1"),"set_max_distance","get_max_distance");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"extents"),"set_extents","get_extents");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"origin_offset"),"set_origin_offset","get_origin_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"box_projection"),"set_enable_box_projection","is_box_projection_enabled");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enable_shadows"),"set_enable_shadows","are_shadows_enabled");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mask",PROPERTY_HINT_LAYERS_3D_RENDER),"set_cull_mask","get_cull_mask");
ADD_GROUP("Interior","interior_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior_enable"),_SCS("set_as_interior"),_SCS("is_set_as_interior"));
- ADD_PROPERTY( PropertyInfo(Variant::COLOR,"interior_ambient_color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_interior_ambient"),_SCS("get_interior_ambient"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"interior_ambient_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_interior_ambient_energy"),_SCS("get_interior_ambient_energy"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"interior_ambient_contrib",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_interior_ambient_probe_contribution"),_SCS("get_interior_ambient_probe_contribution"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior_enable"),"set_as_interior","is_set_as_interior");
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR,"interior_ambient_color",PROPERTY_HINT_COLOR_NO_ALPHA),"set_interior_ambient","get_interior_ambient");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"interior_ambient_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_interior_ambient_energy","get_interior_ambient_energy");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"interior_ambient_contrib",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_interior_ambient_probe_contribution","get_interior_ambient_probe_contribution");
BIND_CONSTANT( UPDATE_ONCE );
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index 410f590431..cfda186d87 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* reflection_probe.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 REFLECTIONPROBE_H
#define REFLECTIONPROBE_H
diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp
index b91d90ae8e..21ec65f5e0 100644
--- a/scene/3d/remote_transform.cpp
+++ b/scene/3d/remote_transform.cpp
@@ -118,10 +118,10 @@ String RemoteTransform::get_configuration_warning() const {
void RemoteTransform::_bind_methods() {
- ClassDB::bind_method(_MD("set_remote_node","path"),&RemoteTransform::set_remote_node);
- ClassDB::bind_method(_MD("get_remote_node"),&RemoteTransform::get_remote_node);
+ ClassDB::bind_method(D_METHOD("set_remote_node","path"),&RemoteTransform::set_remote_node);
+ ClassDB::bind_method(D_METHOD("get_remote_node"),&RemoteTransform::get_remote_node);
- ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"remote_path"),_SCS("set_remote_node"),_SCS("get_remote_node"));
+ ADD_PROPERTY( PropertyInfo(Variant::NODE_PATH,"remote_path"),"set_remote_node","get_remote_node");
}
RemoteTransform::RemoteTransform() {
diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h
index e7aa95ad6e..6bc4763e2d 100644
--- a/scene/3d/remote_transform.h
+++ b/scene/3d/remote_transform.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* remote_transform.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 REMOTETRANSFORM_H
#define REMOTETRANSFORM_H
diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp
index a2e1a48781..b363c05ef7 100644
--- a/scene/3d/room_instance.cpp
+++ b/scene/3d/room_instance.cpp
@@ -31,7 +31,7 @@
#include "servers/visual_server.h"
#include "geometry.h"
-#include "globals.h"
+#include "global_config.h"
#include "scene/resources/surface_tool.h"
@@ -161,11 +161,11 @@ void Room::_bounds_changed() {
void Room::_bind_methods() {
- ClassDB::bind_method(_MD("set_room","room:Room"),&Room::set_room );
- ClassDB::bind_method(_MD("get_room:Room"),&Room::get_room );
+ ClassDB::bind_method(D_METHOD("set_room","room:Room"),&Room::set_room );
+ ClassDB::bind_method(D_METHOD("get_room:Room"),&Room::get_room );
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "room/room", PROPERTY_HINT_RESOURCE_TYPE, "Area" ), _SCS("set_room"), _SCS("get_room") );
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "room/room", PROPERTY_HINT_RESOURCE_TYPE, "Area" ), "set_room", "get_room") ;
}
diff --git a/scene/3d/scenario_fx.cpp b/scene/3d/scenario_fx.cpp
index bda7d43570..145242ba7c 100644
--- a/scene/3d/scenario_fx.cpp
+++ b/scene/3d/scenario_fx.cpp
@@ -99,9 +99,9 @@ String WorldEnvironment::get_configuration_warning() const {
void WorldEnvironment::_bind_methods() {
- ClassDB::bind_method(_MD("set_environment","env:Environment"),&WorldEnvironment::set_environment);
- ClassDB::bind_method(_MD("get_environment:Environment"),&WorldEnvironment::get_environment);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment"),_SCS("set_environment"),_SCS("get_environment"));
+ ClassDB::bind_method(D_METHOD("set_environment","env:Environment"),&WorldEnvironment::set_environment);
+ ClassDB::bind_method(D_METHOD("get_environment:Environment"),&WorldEnvironment::get_environment);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment"),"set_environment","get_environment");
}
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index f2e339604e..04e82ba914 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -31,7 +31,7 @@
#include "message_queue.h"
#include "scene/resources/surface_tool.h"
-#include "core/globals.h"
+#include "core/global_config.h"
bool Skeleton::_set(const StringName& p_path, const Variant& p_value) {
@@ -530,39 +530,39 @@ void Skeleton::_bind_methods() {
- ClassDB::bind_method(_MD("add_bone","name"),&Skeleton::add_bone);
- ClassDB::bind_method(_MD("find_bone","name"),&Skeleton::find_bone);
- ClassDB::bind_method(_MD("get_bone_name","bone_idx"),&Skeleton::get_bone_name);
+ ClassDB::bind_method(D_METHOD("add_bone","name"),&Skeleton::add_bone);
+ ClassDB::bind_method(D_METHOD("find_bone","name"),&Skeleton::find_bone);
+ ClassDB::bind_method(D_METHOD("get_bone_name","bone_idx"),&Skeleton::get_bone_name);
- ClassDB::bind_method(_MD("get_bone_parent","bone_idx"),&Skeleton::get_bone_parent);
- ClassDB::bind_method(_MD("set_bone_parent","bone_idx","parent_idx"),&Skeleton::set_bone_parent);
+ ClassDB::bind_method(D_METHOD("get_bone_parent","bone_idx"),&Skeleton::get_bone_parent);
+ ClassDB::bind_method(D_METHOD("set_bone_parent","bone_idx","parent_idx"),&Skeleton::set_bone_parent);
- ClassDB::bind_method(_MD("get_bone_count"),&Skeleton::get_bone_count);
+ ClassDB::bind_method(D_METHOD("get_bone_count"),&Skeleton::get_bone_count);
- ClassDB::bind_method(_MD("unparent_bone_and_rest","bone_idx"),&Skeleton::unparent_bone_and_rest);
+ ClassDB::bind_method(D_METHOD("unparent_bone_and_rest","bone_idx"),&Skeleton::unparent_bone_and_rest);
- ClassDB::bind_method(_MD("get_bone_rest","bone_idx"),&Skeleton::get_bone_rest);
- ClassDB::bind_method(_MD("set_bone_rest","bone_idx","rest"),&Skeleton::set_bone_rest);
+ ClassDB::bind_method(D_METHOD("get_bone_rest","bone_idx"),&Skeleton::get_bone_rest);
+ ClassDB::bind_method(D_METHOD("set_bone_rest","bone_idx","rest"),&Skeleton::set_bone_rest);
- ClassDB::bind_method(_MD("set_bone_disable_rest","bone_idx","disable"),&Skeleton::set_bone_disable_rest);
- ClassDB::bind_method(_MD("is_bone_rest_disabled","bone_idx"),&Skeleton::is_bone_rest_disabled);
+ ClassDB::bind_method(D_METHOD("set_bone_disable_rest","bone_idx","disable"),&Skeleton::set_bone_disable_rest);
+ ClassDB::bind_method(D_METHOD("is_bone_rest_disabled","bone_idx"),&Skeleton::is_bone_rest_disabled);
- ClassDB::bind_method(_MD("bind_child_node_to_bone","bone_idx","node:Node"),&Skeleton::bind_child_node_to_bone);
- ClassDB::bind_method(_MD("unbind_child_node_from_bone","bone_idx","node:Node"),&Skeleton::unbind_child_node_from_bone);
- ClassDB::bind_method(_MD("get_bound_child_nodes_to_bone","bone_idx"),&Skeleton::_get_bound_child_nodes_to_bone);
+ ClassDB::bind_method(D_METHOD("bind_child_node_to_bone","bone_idx","node:Node"),&Skeleton::bind_child_node_to_bone);
+ ClassDB::bind_method(D_METHOD("unbind_child_node_from_bone","bone_idx","node:Node"),&Skeleton::unbind_child_node_from_bone);
+ ClassDB::bind_method(D_METHOD("get_bound_child_nodes_to_bone","bone_idx"),&Skeleton::_get_bound_child_nodes_to_bone);
- ClassDB::bind_method(_MD("clear_bones"),&Skeleton::clear_bones);
+ ClassDB::bind_method(D_METHOD("clear_bones"),&Skeleton::clear_bones);
- ClassDB::bind_method(_MD("get_bone_pose","bone_idx"),&Skeleton::get_bone_pose);
- ClassDB::bind_method(_MD("set_bone_pose","bone_idx","pose"),&Skeleton::set_bone_pose);
+ ClassDB::bind_method(D_METHOD("get_bone_pose","bone_idx"),&Skeleton::get_bone_pose);
+ ClassDB::bind_method(D_METHOD("set_bone_pose","bone_idx","pose"),&Skeleton::set_bone_pose);
- ClassDB::bind_method(_MD("set_bone_global_pose","bone_idx","pose"),&Skeleton::set_bone_global_pose);
- ClassDB::bind_method(_MD("get_bone_global_pose","bone_idx"),&Skeleton::get_bone_global_pose);
+ ClassDB::bind_method(D_METHOD("set_bone_global_pose","bone_idx","pose"),&Skeleton::set_bone_global_pose);
+ ClassDB::bind_method(D_METHOD("get_bone_global_pose","bone_idx"),&Skeleton::get_bone_global_pose);
- ClassDB::bind_method(_MD("get_bone_custom_pose","bone_idx"),&Skeleton::get_bone_custom_pose);
- ClassDB::bind_method(_MD("set_bone_custom_pose","bone_idx","custom_pose"),&Skeleton::set_bone_custom_pose);
+ ClassDB::bind_method(D_METHOD("get_bone_custom_pose","bone_idx"),&Skeleton::get_bone_custom_pose);
+ ClassDB::bind_method(D_METHOD("set_bone_custom_pose","bone_idx","custom_pose"),&Skeleton::set_bone_custom_pose);
- ClassDB::bind_method(_MD("get_bone_transform","bone_idx"),&Skeleton::get_bone_transform);
+ ClassDB::bind_method(D_METHOD("get_bone_transform","bone_idx"),&Skeleton::get_bone_transform);
BIND_CONSTANT( NOTIFICATION_UPDATE_SKELETON );
}
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 69706a6039..58a6a24567 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -742,50 +742,50 @@ bool Spatial::is_local_transform_notification_enabled() const {
void Spatial::_bind_methods() {
- ClassDB::bind_method(_MD("set_transform","local"), &Spatial::set_transform);
- ClassDB::bind_method(_MD("get_transform"), &Spatial::get_transform);
- ClassDB::bind_method(_MD("set_translation","translation"), &Spatial::set_translation);
- ClassDB::bind_method(_MD("get_translation"), &Spatial::get_translation);
- ClassDB::bind_method(_MD("set_rotation","rotation_rad"), &Spatial::set_rotation);
- ClassDB::bind_method(_MD("get_rotation"), &Spatial::get_rotation);
- ClassDB::bind_method(_MD("set_rotation_deg","rotation_deg"), &Spatial::set_rotation_in_degrees);
- ClassDB::bind_method(_MD("get_rotation_deg"), &Spatial::get_rotation_in_degrees);
- ClassDB::bind_method(_MD("set_scale","scale"), &Spatial::set_scale);
- ClassDB::bind_method(_MD("get_scale"), &Spatial::get_scale);
- ClassDB::bind_method(_MD("set_global_transform","global"), &Spatial::set_global_transform);
- ClassDB::bind_method(_MD("get_global_transform"), &Spatial::get_global_transform);
- ClassDB::bind_method(_MD("get_parent_spatial"), &Spatial::get_parent_spatial);
- ClassDB::bind_method(_MD("set_ignore_transform_notification","enabled"), &Spatial::set_ignore_transform_notification);
- ClassDB::bind_method(_MD("set_as_toplevel","enable"), &Spatial::set_as_toplevel);
- ClassDB::bind_method(_MD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel);
- ClassDB::bind_method(_MD("get_world:World"), &Spatial::get_world);
+ ClassDB::bind_method(D_METHOD("set_transform","local"), &Spatial::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"), &Spatial::get_transform);
+ ClassDB::bind_method(D_METHOD("set_translation","translation"), &Spatial::set_translation);
+ ClassDB::bind_method(D_METHOD("get_translation"), &Spatial::get_translation);
+ ClassDB::bind_method(D_METHOD("set_rotation","rotation_rad"), &Spatial::set_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation"), &Spatial::get_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_deg","rotation_deg"), &Spatial::set_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("get_rotation_deg"), &Spatial::get_rotation_in_degrees);
+ ClassDB::bind_method(D_METHOD("set_scale","scale"), &Spatial::set_scale);
+ ClassDB::bind_method(D_METHOD("get_scale"), &Spatial::get_scale);
+ ClassDB::bind_method(D_METHOD("set_global_transform","global"), &Spatial::set_global_transform);
+ ClassDB::bind_method(D_METHOD("get_global_transform"), &Spatial::get_global_transform);
+ ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Spatial::get_parent_spatial);
+ ClassDB::bind_method(D_METHOD("set_ignore_transform_notification","enabled"), &Spatial::set_ignore_transform_notification);
+ ClassDB::bind_method(D_METHOD("set_as_toplevel","enable"), &Spatial::set_as_toplevel);
+ ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel);
+ ClassDB::bind_method(D_METHOD("get_world:World"), &Spatial::get_world);
// TODO: Obsolete those two methods (old name) properly (GH-4397)
- ClassDB::bind_method(_MD("_set_rotation_deg","rotation_deg"), &Spatial::_set_rotation_deg);
- ClassDB::bind_method(_MD("_get_rotation_deg"), &Spatial::_get_rotation_deg);
+ ClassDB::bind_method(D_METHOD("_set_rotation_deg","rotation_deg"), &Spatial::_set_rotation_deg);
+ ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Spatial::_get_rotation_deg);
#ifdef TOOLS_ENABLED
- ClassDB::bind_method(_MD("_update_gizmo"), &Spatial::_update_gizmo);
- ClassDB::bind_method(_MD("_set_import_transform"), &Spatial::set_import_transform);
- ClassDB::bind_method(_MD("_get_import_transform"), &Spatial::get_import_transform);
- ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"_import_transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_import_transform"),_SCS("_get_import_transform"));
+ ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo);
+ ClassDB::bind_method(D_METHOD("_set_import_transform"), &Spatial::set_import_transform);
+ ClassDB::bind_method(D_METHOD("_get_import_transform"), &Spatial::get_import_transform);
+ ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"_import_transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_import_transform","_get_import_transform");
#endif
- ClassDB::bind_method(_MD("update_gizmo"), &Spatial::update_gizmo);
- ClassDB::bind_method(_MD("set_gizmo","gizmo:SpatialGizmo"), &Spatial::set_gizmo);
- ClassDB::bind_method(_MD("get_gizmo:SpatialGizmo"), &Spatial::get_gizmo);
+ ClassDB::bind_method(D_METHOD("update_gizmo"), &Spatial::update_gizmo);
+ ClassDB::bind_method(D_METHOD("set_gizmo","gizmo:SpatialGizmo"), &Spatial::set_gizmo);
+ ClassDB::bind_method(D_METHOD("get_gizmo:SpatialGizmo"), &Spatial::get_gizmo);
- ClassDB::bind_method(_MD("set_visible"), &Spatial::set_visible);
- ClassDB::bind_method(_MD("is_visible"), &Spatial::is_visible);
- ClassDB::bind_method(_MD("is_visible_in_tree"), &Spatial::is_visible_in_tree);
- ClassDB::bind_method(_MD("show"), &Spatial::show);
- ClassDB::bind_method(_MD("hide"), &Spatial::hide);
+ ClassDB::bind_method(D_METHOD("set_visible"), &Spatial::set_visible);
+ ClassDB::bind_method(D_METHOD("is_visible"), &Spatial::is_visible);
+ ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &Spatial::is_visible_in_tree);
+ ClassDB::bind_method(D_METHOD("show"), &Spatial::show);
+ ClassDB::bind_method(D_METHOD("hide"), &Spatial::hide);
- ClassDB::bind_method(_MD("set_notify_local_transform","enable"), &Spatial::set_notify_local_transform);
- ClassDB::bind_method(_MD("is_local_transform_notification_enabled"), &Spatial::is_local_transform_notification_enabled);
+ ClassDB::bind_method(D_METHOD("set_notify_local_transform","enable"), &Spatial::set_notify_local_transform);
+ ClassDB::bind_method(D_METHOD("is_local_transform_notification_enabled"), &Spatial::is_local_transform_notification_enabled);
- ClassDB::bind_method(_MD("set_notify_transform","enable"), &Spatial::set_notify_transform);
- ClassDB::bind_method(_MD("is_transform_notification_enabled"), &Spatial::is_transform_notification_enabled);
+ ClassDB::bind_method(D_METHOD("set_notify_transform","enable"), &Spatial::set_notify_transform);
+ ClassDB::bind_method(D_METHOD("is_transform_notification_enabled"), &Spatial::is_transform_notification_enabled);
void rotate(const Vector3& p_normal,float p_radians);
void rotate_x(float p_radians);
@@ -796,35 +796,35 @@ void Spatial::_bind_methods() {
void global_rotate(const Vector3& p_normal,float p_radians);
void global_translate(const Vector3& p_offset);
- ClassDB::bind_method( _MD("rotate","normal","radians"),&Spatial::rotate );
- ClassDB::bind_method( _MD("global_rotate","normal","radians"),&Spatial::global_rotate );
- ClassDB::bind_method( _MD("rotate_x","radians"),&Spatial::rotate_x );
- ClassDB::bind_method( _MD("rotate_y","radians"),&Spatial::rotate_y );
- ClassDB::bind_method( _MD("rotate_z","radians"),&Spatial::rotate_z );
- ClassDB::bind_method( _MD("translate","offset"),&Spatial::translate );
- ClassDB::bind_method( _MD("global_translate","offset"),&Spatial::global_translate );
- ClassDB::bind_method( _MD("orthonormalize"),&Spatial::orthonormalize );
- ClassDB::bind_method( _MD("set_identity"),&Spatial::set_identity );
+ ClassDB::bind_method( D_METHOD("rotate","normal","radians"),&Spatial::rotate );
+ ClassDB::bind_method( D_METHOD("global_rotate","normal","radians"),&Spatial::global_rotate );
+ ClassDB::bind_method( D_METHOD("rotate_x","radians"),&Spatial::rotate_x );
+ ClassDB::bind_method( D_METHOD("rotate_y","radians"),&Spatial::rotate_y );
+ ClassDB::bind_method( D_METHOD("rotate_z","radians"),&Spatial::rotate_z );
+ ClassDB::bind_method( D_METHOD("translate","offset"),&Spatial::translate );
+ ClassDB::bind_method( D_METHOD("global_translate","offset"),&Spatial::global_translate );
+ ClassDB::bind_method( D_METHOD("orthonormalize"),&Spatial::orthonormalize );
+ ClassDB::bind_method( D_METHOD("set_identity"),&Spatial::set_identity );
- ClassDB::bind_method( _MD("look_at","target","up"),&Spatial::look_at );
- ClassDB::bind_method( _MD("look_at_from_pos","pos","target","up"),&Spatial::look_at_from_pos );
+ ClassDB::bind_method( D_METHOD("look_at","target","up"),&Spatial::look_at );
+ ClassDB::bind_method( D_METHOD("look_at_from_pos","pos","target","up"),&Spatial::look_at_from_pos );
BIND_CONSTANT( NOTIFICATION_TRANSFORM_CHANGED );
BIND_CONSTANT( NOTIFICATION_ENTER_WORLD );
BIND_CONSTANT( NOTIFICATION_EXIT_WORLD );
BIND_CONSTANT( NOTIFICATION_VISIBILITY_CHANGED );
- //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), _SCS("set_global_transform"), _SCS("get_global_transform") );
+ //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ;
ADD_GROUP("Transform","");
- ADD_PROPERTYNZ( PropertyInfo(Variant::TRANSFORM,"transform",PROPERTY_HINT_NONE,""), _SCS("set_transform"), _SCS("get_transform") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::TRANSFORM,"global_transform",PROPERTY_HINT_NONE,"",0), _SCS("set_global_transform"), _SCS("get_global_transform") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"translation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_translation"), _SCS("get_translation") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"rotation_deg",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_rotation_deg"), _SCS("get_rotation_deg") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"rotation",PROPERTY_HINT_NONE,"",0), _SCS("set_rotation"), _SCS("get_rotation") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"scale",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_scale"), _SCS("get_scale") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::TRANSFORM,"transform",PROPERTY_HINT_NONE,""), "set_transform", "get_transform") ;
+ ADD_PROPERTYNZ( PropertyInfo(Variant::TRANSFORM,"global_transform",PROPERTY_HINT_NONE,"",0), "set_global_transform", "get_global_transform") ;
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"translation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), "set_translation", "get_translation") ;
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"rotation_deg",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), "set_rotation_deg", "get_rotation_deg") ;
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"rotation",PROPERTY_HINT_NONE,"",0), "set_rotation", "get_rotation") ;
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"scale",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), "set_scale", "get_scale") ;
ADD_GROUP("Visibility","");
- ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"visible"), _SCS("set_visible"), _SCS("is_visible") );
- //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/local"), _SCS("set_transform"), _SCS("get_transform") );
+ ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"visible"), "set_visible", "is_visible") ;
+ //ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/local"), "set_transform", "get_transform") ;
ADD_SIGNAL( MethodInfo("visibility_changed" ) );
diff --git a/scene/3d/spatial_indexer.cpp b/scene/3d/spatial_indexer.cpp
index 0cc6d1abd0..6d6c272c25 100644
--- a/scene/3d/spatial_indexer.cpp
+++ b/scene/3d/spatial_indexer.cpp
@@ -112,7 +112,7 @@ void SpatialIndexer::_update_pairs() {
void SpatialIndexer::_bind_methods() {
- ClassDB::bind_method(_MD("_update_pairs"),&SpatialIndexer::_update_pairs);
+ ClassDB::bind_method(D_METHOD("_update_pairs"),&SpatialIndexer::_update_pairs);
}
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 479fe1fed9..5adb7050f8 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -246,55 +246,55 @@ SpriteBase3D::AlphaCutMode SpriteBase3D::get_alpha_cut_mode() const{
void SpriteBase3D::_bind_methods() {
- ClassDB::bind_method(_MD("set_centered","centered"),&SpriteBase3D::set_centered);
- ClassDB::bind_method(_MD("is_centered"),&SpriteBase3D::is_centered);
+ ClassDB::bind_method(D_METHOD("set_centered","centered"),&SpriteBase3D::set_centered);
+ ClassDB::bind_method(D_METHOD("is_centered"),&SpriteBase3D::is_centered);
- ClassDB::bind_method(_MD("set_offset","offset"),&SpriteBase3D::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&SpriteBase3D::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&SpriteBase3D::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&SpriteBase3D::get_offset);
- ClassDB::bind_method(_MD("set_flip_h","flip_h"),&SpriteBase3D::set_flip_h);
- ClassDB::bind_method(_MD("is_flipped_h"),&SpriteBase3D::is_flipped_h);
+ ClassDB::bind_method(D_METHOD("set_flip_h","flip_h"),&SpriteBase3D::set_flip_h);
+ ClassDB::bind_method(D_METHOD("is_flipped_h"),&SpriteBase3D::is_flipped_h);
- ClassDB::bind_method(_MD("set_flip_v","flip_v"),&SpriteBase3D::set_flip_v);
- ClassDB::bind_method(_MD("is_flipped_v"),&SpriteBase3D::is_flipped_v);
+ ClassDB::bind_method(D_METHOD("set_flip_v","flip_v"),&SpriteBase3D::set_flip_v);
+ ClassDB::bind_method(D_METHOD("is_flipped_v"),&SpriteBase3D::is_flipped_v);
- ClassDB::bind_method(_MD("set_modulate","modulate"),&SpriteBase3D::set_modulate);
- ClassDB::bind_method(_MD("get_modulate"),&SpriteBase3D::get_modulate);
+ ClassDB::bind_method(D_METHOD("set_modulate","modulate"),&SpriteBase3D::set_modulate);
+ ClassDB::bind_method(D_METHOD("get_modulate"),&SpriteBase3D::get_modulate);
- ClassDB::bind_method(_MD("set_opacity","opacity"),&SpriteBase3D::set_opacity);
- ClassDB::bind_method(_MD("get_opacity"),&SpriteBase3D::get_opacity);
+ ClassDB::bind_method(D_METHOD("set_opacity","opacity"),&SpriteBase3D::set_opacity);
+ ClassDB::bind_method(D_METHOD("get_opacity"),&SpriteBase3D::get_opacity);
- ClassDB::bind_method(_MD("set_pixel_size","pixel_size"),&SpriteBase3D::set_pixel_size);
- ClassDB::bind_method(_MD("get_pixel_size"),&SpriteBase3D::get_pixel_size);
+ ClassDB::bind_method(D_METHOD("set_pixel_size","pixel_size"),&SpriteBase3D::set_pixel_size);
+ ClassDB::bind_method(D_METHOD("get_pixel_size"),&SpriteBase3D::get_pixel_size);
- ClassDB::bind_method(_MD("set_axis","axis"),&SpriteBase3D::set_axis);
- ClassDB::bind_method(_MD("get_axis"),&SpriteBase3D::get_axis);
+ ClassDB::bind_method(D_METHOD("set_axis","axis"),&SpriteBase3D::set_axis);
+ ClassDB::bind_method(D_METHOD("get_axis"),&SpriteBase3D::get_axis);
- ClassDB::bind_method(_MD("set_draw_flag","flag","enabled"),&SpriteBase3D::set_draw_flag);
- ClassDB::bind_method(_MD("get_draw_flag","flag"),&SpriteBase3D::get_draw_flag);
+ ClassDB::bind_method(D_METHOD("set_draw_flag","flag","enabled"),&SpriteBase3D::set_draw_flag);
+ ClassDB::bind_method(D_METHOD("get_draw_flag","flag"),&SpriteBase3D::get_draw_flag);
- ClassDB::bind_method(_MD("set_alpha_cut_mode","mode"),&SpriteBase3D::set_alpha_cut_mode);
- ClassDB::bind_method(_MD("get_alpha_cut_mode"),&SpriteBase3D::get_alpha_cut_mode);
+ ClassDB::bind_method(D_METHOD("set_alpha_cut_mode","mode"),&SpriteBase3D::set_alpha_cut_mode);
+ ClassDB::bind_method(D_METHOD("get_alpha_cut_mode"),&SpriteBase3D::get_alpha_cut_mode);
- ClassDB::bind_method(_MD("get_item_rect"),&SpriteBase3D::get_item_rect);
+ ClassDB::bind_method(D_METHOD("get_item_rect"),&SpriteBase3D::get_item_rect);
- ClassDB::bind_method(_MD("_queue_update"),&SpriteBase3D::_queue_update);
- ClassDB::bind_method(_MD("_im_update"),&SpriteBase3D::_im_update);
+ ClassDB::bind_method(D_METHOD("_queue_update"),&SpriteBase3D::_queue_update);
+ ClassDB::bind_method(D_METHOD("_im_update"),&SpriteBase3D::_im_update);
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
- ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "opacity",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "pixel_size",PROPERTY_HINT_RANGE,"0.0001,128,0.0001"), _SCS("set_pixel_size"),_SCS("get_pixel_size"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "axis",PROPERTY_HINT_ENUM,"X-Axis,Y-Axis,Z-Axis"), _SCS("set_axis"),_SCS("get_axis"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), "set_centered","is_centered");
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), "set_offset","get_offset");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), "set_flip_h","is_flipped_h");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), "set_flip_v","is_flipped_v");
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), "set_modulate","get_modulate");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "opacity",PROPERTY_HINT_RANGE,"0,1,0.01"), "set_opacity","get_opacity");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "pixel_size",PROPERTY_HINT_RANGE,"0.0001,128,0.0001"), "set_pixel_size","get_pixel_size");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "axis",PROPERTY_HINT_ENUM,"X-Axis,Y-Axis,Z-Axis"), "set_axis","get_axis");
ADD_GROUP("Flags","");
- ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "transparent"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_TRANSPARENT);
- ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "shaded"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_SHADED);
- ADD_PROPERTY( PropertyInfo( Variant::INT, "alpha_cut",PROPERTY_HINT_ENUM,"Disabled,Discard,Opaque Pre-Pass"), _SCS("set_alpha_cut_mode"),_SCS("get_alpha_cut_mode"));
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "transparent"), "set_draw_flag","get_draw_flag",FLAG_TRANSPARENT);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "shaded"), "set_draw_flag","get_draw_flag",FLAG_SHADED);
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "alpha_cut",PROPERTY_HINT_ENUM,"Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode","get_alpha_cut_mode");
BIND_CONSTANT( FLAG_TRANSPARENT );
@@ -601,30 +601,30 @@ void Sprite3D::_validate_property(PropertyInfo& property) const {
void Sprite3D::_bind_methods() {
- ClassDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite3D::set_texture);
- ClassDB::bind_method(_MD("get_texture:Texture"),&Sprite3D::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture","texture:Texture"),&Sprite3D::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"),&Sprite3D::get_texture);
- ClassDB::bind_method(_MD("set_region","enabled"),&Sprite3D::set_region);
- ClassDB::bind_method(_MD("is_region"),&Sprite3D::is_region);
+ ClassDB::bind_method(D_METHOD("set_region","enabled"),&Sprite3D::set_region);
+ ClassDB::bind_method(D_METHOD("is_region"),&Sprite3D::is_region);
- ClassDB::bind_method(_MD("set_region_rect","rect"),&Sprite3D::set_region_rect);
- ClassDB::bind_method(_MD("get_region_rect"),&Sprite3D::get_region_rect);
+ ClassDB::bind_method(D_METHOD("set_region_rect","rect"),&Sprite3D::set_region_rect);
+ ClassDB::bind_method(D_METHOD("get_region_rect"),&Sprite3D::get_region_rect);
- ClassDB::bind_method(_MD("set_frame","frame"),&Sprite3D::set_frame);
- ClassDB::bind_method(_MD("get_frame"),&Sprite3D::get_frame);
+ ClassDB::bind_method(D_METHOD("set_frame","frame"),&Sprite3D::set_frame);
+ ClassDB::bind_method(D_METHOD("get_frame"),&Sprite3D::get_frame);
- ClassDB::bind_method(_MD("set_vframes","vframes"),&Sprite3D::set_vframes);
- ClassDB::bind_method(_MD("get_vframes"),&Sprite3D::get_vframes);
+ ClassDB::bind_method(D_METHOD("set_vframes","vframes"),&Sprite3D::set_vframes);
+ ClassDB::bind_method(D_METHOD("get_vframes"),&Sprite3D::get_vframes);
- ClassDB::bind_method(_MD("set_hframes","hframes"),&Sprite3D::set_hframes);
- ClassDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes);
+ ClassDB::bind_method(D_METHOD("set_hframes","hframes"),&Sprite3D::set_hframes);
+ ClassDB::bind_method(D_METHOD("get_hframes"),&Sprite3D::get_hframes);
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
- ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_texture","get_texture");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), "set_vframes","get_vframes");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), "set_hframes","get_hframes");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), "set_frame","get_frame");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), "set_region","is_region");
+ ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), "set_region_rect","get_region_rect");
ADD_SIGNAL(MethodInfo("frame_changed"));
@@ -764,13 +764,13 @@ void AnimatedSprite3D::_draw() {
void AnimatedSprite3D::_bind_methods(){
- ClassDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames);
- ClassDB::bind_method(_MD("get_sprite_frames:Texture"),&AnimatedSprite3D::get_sprite_frames);
- ClassDB::bind_method(_MD("set_frame","frame"),&AnimatedSprite3D::set_frame);
- ClassDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame);
+ ClassDB::bind_method(D_METHOD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames);
+ ClassDB::bind_method(D_METHOD("get_sprite_frames:Texture"),&AnimatedSprite3D::get_sprite_frames);
+ ClassDB::bind_method(D_METHOD("set_frame","frame"),&AnimatedSprite3D::set_frame);
+ ClassDB::bind_method(D_METHOD("get_frame"),&AnimatedSprite3D::get_frame);
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), "set_sprite_frames","get_sprite_frames");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), "set_frame","get_frame");
ADD_SIGNAL(MethodInfo("frame_changed"));
@@ -1312,31 +1312,31 @@ String AnimatedSprite3D::get_configuration_warning() const {
void AnimatedSprite3D::_bind_methods() {
- ClassDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames);
- ClassDB::bind_method(_MD("get_sprite_frames:SpriteFrames"),&AnimatedSprite3D::get_sprite_frames);
+ ClassDB::bind_method(D_METHOD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames);
+ ClassDB::bind_method(D_METHOD("get_sprite_frames:SpriteFrames"),&AnimatedSprite3D::get_sprite_frames);
- ClassDB::bind_method(_MD("set_animation","animation"),&AnimatedSprite3D::set_animation);
- ClassDB::bind_method(_MD("get_animation"),&AnimatedSprite3D::get_animation);
+ ClassDB::bind_method(D_METHOD("set_animation","animation"),&AnimatedSprite3D::set_animation);
+ ClassDB::bind_method(D_METHOD("get_animation"),&AnimatedSprite3D::get_animation);
- ClassDB::bind_method(_MD("_set_playing","playing"),&AnimatedSprite3D::_set_playing);
- ClassDB::bind_method(_MD("_is_playing"),&AnimatedSprite3D::_is_playing);
+ ClassDB::bind_method(D_METHOD("_set_playing","playing"),&AnimatedSprite3D::_set_playing);
+ ClassDB::bind_method(D_METHOD("_is_playing"),&AnimatedSprite3D::_is_playing);
- ClassDB::bind_method(_MD("play","anim"),&AnimatedSprite3D::play,DEFVAL(StringName()));
- ClassDB::bind_method(_MD("stop"),&AnimatedSprite3D::stop);
- ClassDB::bind_method(_MD("is_playing"),&AnimatedSprite3D::is_playing);
+ ClassDB::bind_method(D_METHOD("play","anim"),&AnimatedSprite3D::play,DEFVAL(StringName()));
+ ClassDB::bind_method(D_METHOD("stop"),&AnimatedSprite3D::stop);
+ ClassDB::bind_method(D_METHOD("is_playing"),&AnimatedSprite3D::is_playing);
- ClassDB::bind_method(_MD("set_frame","frame"),&AnimatedSprite3D::set_frame);
- ClassDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame);
+ ClassDB::bind_method(D_METHOD("set_frame","frame"),&AnimatedSprite3D::set_frame);
+ ClassDB::bind_method(D_METHOD("get_frame"),&AnimatedSprite3D::get_frame);
- ClassDB::bind_method(_MD("_res_changed"),&AnimatedSprite3D::_res_changed);
+ ClassDB::bind_method(D_METHOD("_res_changed"),&AnimatedSprite3D::_res_changed);
ADD_SIGNAL(MethodInfo("frame_changed"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames"));
- ADD_PROPERTY( PropertyInfo( Variant::STRING, "animation"), _SCS("set_animation"),_SCS("get_animation"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "playing"), _SCS("_set_playing"),_SCS("_is_playing"));
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), "set_sprite_frames","get_sprite_frames");
+ ADD_PROPERTY( PropertyInfo( Variant::STRING, "animation"), "set_animation","get_animation");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), "set_frame","get_frame");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "playing"), "_set_playing","_is_playing");
}
diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index a3f05f719d..4b32c62d14 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -232,52 +232,52 @@ float VehicleWheel::get_friction_slip() const{
void VehicleWheel::_bind_methods() {
- ClassDB::bind_method(_MD("set_radius","length"),&VehicleWheel::set_radius);
- ClassDB::bind_method(_MD("get_radius"),&VehicleWheel::get_radius);
+ ClassDB::bind_method(D_METHOD("set_radius","length"),&VehicleWheel::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"),&VehicleWheel::get_radius);
- ClassDB::bind_method(_MD("set_suspension_rest_length","length"),&VehicleWheel::set_suspension_rest_length);
- ClassDB::bind_method(_MD("get_suspension_rest_length"),&VehicleWheel::get_suspension_rest_length);
+ ClassDB::bind_method(D_METHOD("set_suspension_rest_length","length"),&VehicleWheel::set_suspension_rest_length);
+ ClassDB::bind_method(D_METHOD("get_suspension_rest_length"),&VehicleWheel::get_suspension_rest_length);
- ClassDB::bind_method(_MD("set_suspension_travel","length"),&VehicleWheel::set_suspension_travel);
- ClassDB::bind_method(_MD("get_suspension_travel"),&VehicleWheel::get_suspension_travel);
+ ClassDB::bind_method(D_METHOD("set_suspension_travel","length"),&VehicleWheel::set_suspension_travel);
+ ClassDB::bind_method(D_METHOD("get_suspension_travel"),&VehicleWheel::get_suspension_travel);
- ClassDB::bind_method(_MD("set_suspension_stiffness","length"),&VehicleWheel::set_suspension_stiffness);
- ClassDB::bind_method(_MD("get_suspension_stiffness"),&VehicleWheel::get_suspension_stiffness);
+ ClassDB::bind_method(D_METHOD("set_suspension_stiffness","length"),&VehicleWheel::set_suspension_stiffness);
+ ClassDB::bind_method(D_METHOD("get_suspension_stiffness"),&VehicleWheel::get_suspension_stiffness);
- ClassDB::bind_method(_MD("set_suspension_max_force","length"),&VehicleWheel::set_suspension_max_force);
- ClassDB::bind_method(_MD("get_suspension_max_force"),&VehicleWheel::get_suspension_max_force);
+ ClassDB::bind_method(D_METHOD("set_suspension_max_force","length"),&VehicleWheel::set_suspension_max_force);
+ ClassDB::bind_method(D_METHOD("get_suspension_max_force"),&VehicleWheel::get_suspension_max_force);
- ClassDB::bind_method(_MD("set_damping_compression","length"),&VehicleWheel::set_damping_compression);
- ClassDB::bind_method(_MD("get_damping_compression"),&VehicleWheel::get_damping_compression);
+ ClassDB::bind_method(D_METHOD("set_damping_compression","length"),&VehicleWheel::set_damping_compression);
+ ClassDB::bind_method(D_METHOD("get_damping_compression"),&VehicleWheel::get_damping_compression);
- ClassDB::bind_method(_MD("set_damping_relaxation","length"),&VehicleWheel::set_damping_relaxation);
- ClassDB::bind_method(_MD("get_damping_relaxation"),&VehicleWheel::get_damping_relaxation);
+ ClassDB::bind_method(D_METHOD("set_damping_relaxation","length"),&VehicleWheel::set_damping_relaxation);
+ ClassDB::bind_method(D_METHOD("get_damping_relaxation"),&VehicleWheel::get_damping_relaxation);
- ClassDB::bind_method(_MD("set_use_as_traction","enable"),&VehicleWheel::set_use_as_traction);
- ClassDB::bind_method(_MD("is_used_as_traction"),&VehicleWheel::is_used_as_traction);
+ ClassDB::bind_method(D_METHOD("set_use_as_traction","enable"),&VehicleWheel::set_use_as_traction);
+ ClassDB::bind_method(D_METHOD("is_used_as_traction"),&VehicleWheel::is_used_as_traction);
- ClassDB::bind_method(_MD("set_use_as_steering","enable"),&VehicleWheel::set_use_as_steering);
- ClassDB::bind_method(_MD("is_used_as_steering"),&VehicleWheel::is_used_as_steering);
+ ClassDB::bind_method(D_METHOD("set_use_as_steering","enable"),&VehicleWheel::set_use_as_steering);
+ ClassDB::bind_method(D_METHOD("is_used_as_steering"),&VehicleWheel::is_used_as_steering);
- ClassDB::bind_method(_MD("set_friction_slip","length"),&VehicleWheel::set_friction_slip);
- ClassDB::bind_method(_MD("get_friction_slip"),&VehicleWheel::get_friction_slip);
+ ClassDB::bind_method(D_METHOD("set_friction_slip","length"),&VehicleWheel::set_friction_slip);
+ ClassDB::bind_method(D_METHOD("get_friction_slip"),&VehicleWheel::get_friction_slip);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_as_traction"),_SCS("set_use_as_traction"),_SCS("is_used_as_traction"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_as_steering"),_SCS("set_use_as_steering"),_SCS("is_used_as_steering"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_as_traction"),"set_use_as_traction","is_used_as_traction");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_as_steering"),"set_use_as_steering","is_used_as_steering");
ADD_GROUP("Wheel","wheel_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel_radius"),_SCS("set_radius"),_SCS("get_radius"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel_rest_length"),_SCS("set_suspension_rest_length"),_SCS("get_suspension_rest_length"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel_friction_slip"),_SCS("set_friction_slip"),_SCS("get_friction_slip"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel_radius"),"set_radius","get_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel_rest_length"),"set_suspension_rest_length","get_suspension_rest_length");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wheel_friction_slip"),"set_friction_slip","get_friction_slip");
ADD_GROUP("Suspension","suspension_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension_travel"),_SCS("set_suspension_travel"),_SCS("get_suspension_travel"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension_stiffness"),_SCS("set_suspension_stiffness"),_SCS("get_suspension_stiffness"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension_max_force"),_SCS("set_suspension_max_force"),_SCS("get_suspension_max_force"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension_travel"),"set_suspension_travel","get_suspension_travel");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension_stiffness"),"set_suspension_stiffness","get_suspension_stiffness");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"suspension_max_force"),"set_suspension_max_force","get_suspension_max_force");
ADD_GROUP("Damping","damping_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping_compression"),_SCS("set_damping_compression"),_SCS("get_damping_compression"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping_relaxation"),_SCS("set_damping_relaxation"),_SCS("get_damping_relaxation"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping_compression"),"set_damping_compression","get_damping_compression");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping_relaxation"),"set_damping_relaxation","get_damping_relaxation");
}
@@ -1026,32 +1026,32 @@ Vector3 VehicleBody::get_linear_velocity() const
void VehicleBody::_bind_methods(){
- ClassDB::bind_method(_MD("set_mass","mass"),&VehicleBody::set_mass);
- ClassDB::bind_method(_MD("get_mass"),&VehicleBody::get_mass);
+ ClassDB::bind_method(D_METHOD("set_mass","mass"),&VehicleBody::set_mass);
+ ClassDB::bind_method(D_METHOD("get_mass"),&VehicleBody::get_mass);
- ClassDB::bind_method(_MD("set_friction","friction"),&VehicleBody::set_friction);
- ClassDB::bind_method(_MD("get_friction"),&VehicleBody::get_friction);
+ ClassDB::bind_method(D_METHOD("set_friction","friction"),&VehicleBody::set_friction);
+ ClassDB::bind_method(D_METHOD("get_friction"),&VehicleBody::get_friction);
- ClassDB::bind_method(_MD("set_engine_force","engine_force"),&VehicleBody::set_engine_force);
- ClassDB::bind_method(_MD("get_engine_force"),&VehicleBody::get_engine_force);
+ ClassDB::bind_method(D_METHOD("set_engine_force","engine_force"),&VehicleBody::set_engine_force);
+ ClassDB::bind_method(D_METHOD("get_engine_force"),&VehicleBody::get_engine_force);
- ClassDB::bind_method(_MD("set_brake","brake"),&VehicleBody::set_brake);
- ClassDB::bind_method(_MD("get_brake"),&VehicleBody::get_brake);
+ ClassDB::bind_method(D_METHOD("set_brake","brake"),&VehicleBody::set_brake);
+ ClassDB::bind_method(D_METHOD("get_brake"),&VehicleBody::get_brake);
- ClassDB::bind_method(_MD("set_steering","steering"),&VehicleBody::set_steering);
- ClassDB::bind_method(_MD("get_steering"),&VehicleBody::get_steering);
+ ClassDB::bind_method(D_METHOD("set_steering","steering"),&VehicleBody::set_steering);
+ ClassDB::bind_method(D_METHOD("get_steering"),&VehicleBody::get_steering);
- ClassDB::bind_method(_MD("get_linear_velocity"),&VehicleBody::get_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"),&VehicleBody::get_linear_velocity);
- ClassDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
+ ClassDB::bind_method(D_METHOD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
ADD_GROUP("Motion","");
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"engine_force",PROPERTY_HINT_RANGE,"0.00,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"brake",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_brake"),_SCS("get_brake"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"steering",PROPERTY_HINT_RANGE,"-180,180.0,0.01"),_SCS("set_steering"),_SCS("get_steering"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"engine_force",PROPERTY_HINT_RANGE,"0.00,1024.0,0.01"),"set_engine_force","get_engine_force");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"brake",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),"set_brake","get_brake");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"steering",PROPERTY_HINT_RANGE,"-180,180.0,0.01"),"set_steering","get_steering");
ADD_GROUP("Mass","");
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),"set_mass","get_mass");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),"set_friction","get_friction");
}
diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp
index c7c083732e..0633846b5a 100644
--- a/scene/3d/visibility_notifier.cpp
+++ b/scene/3d/visibility_notifier.cpp
@@ -109,11 +109,11 @@ bool VisibilityNotifier::is_on_screen() const {
void VisibilityNotifier::_bind_methods(){
- ClassDB::bind_method(_MD("set_aabb","rect"),&VisibilityNotifier::set_aabb);
- ClassDB::bind_method(_MD("get_aabb"),&VisibilityNotifier::get_aabb);
- ClassDB::bind_method(_MD("is_on_screen"),&VisibilityNotifier::is_on_screen);
+ ClassDB::bind_method(D_METHOD("set_aabb","rect"),&VisibilityNotifier::set_aabb);
+ ClassDB::bind_method(D_METHOD("get_aabb"),&VisibilityNotifier::get_aabb);
+ ClassDB::bind_method(D_METHOD("is_on_screen"),&VisibilityNotifier::is_on_screen);
- ADD_PROPERTY( PropertyInfo(Variant::RECT3,"aabb"),_SCS("set_aabb"),_SCS("get_aabb"));
+ ADD_PROPERTY( PropertyInfo(Variant::RECT3,"aabb"),"set_aabb","get_aabb");
ADD_SIGNAL( MethodInfo("camera_entered",PropertyInfo(Variant::OBJECT,"camera",PROPERTY_HINT_RESOURCE_TYPE,"Camera")) );
ADD_SIGNAL( MethodInfo("camera_exited",PropertyInfo(Variant::OBJECT,"camera",PROPERTY_HINT_RESOURCE_TYPE,"Camera")) );
@@ -268,12 +268,12 @@ void VisibilityEnabler::_node_removed(Node* p_node) {
void VisibilityEnabler::_bind_methods(){
- ClassDB::bind_method(_MD("set_enabler","enabler","enabled"),&VisibilityEnabler::set_enabler);
- ClassDB::bind_method(_MD("is_enabler_enabled","enabler"),&VisibilityEnabler::is_enabler_enabled);
- ClassDB::bind_method(_MD("_node_removed"),&VisibilityEnabler::_node_removed);
+ ClassDB::bind_method(D_METHOD("set_enabler","enabler","enabled"),&VisibilityEnabler::set_enabler);
+ ClassDB::bind_method(D_METHOD("is_enabler_enabled","enabler"),&VisibilityEnabler::is_enabler_enabled);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&VisibilityEnabler::_node_removed);
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_animations"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_PAUSE_ANIMATIONS );
- ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"freeze_bodies"),_SCS("set_enabler"),_SCS("is_enabler_enabled"), ENABLER_FREEZE_BODIES);
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"pause_animations"),"set_enabler","is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS );
+ ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"freeze_bodies"),"set_enabler","is_enabler_enabled", ENABLER_FREEZE_BODIES);
BIND_CONSTANT( ENABLER_FREEZE_BODIES );
BIND_CONSTANT( ENABLER_PAUSE_ANIMATIONS );
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index ec37aa2bc4..bbcd54b36b 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -137,14 +137,14 @@ uint32_t VisualInstance::get_layer_mask() const {
void VisualInstance::_bind_methods() {
- ClassDB::bind_method(_MD("_get_visual_instance_rid"),&VisualInstance::_get_visual_instance_rid);
- ClassDB::bind_method(_MD("set_base","base"), &VisualInstance::set_base);
- ClassDB::bind_method(_MD("set_layer_mask","mask"), &VisualInstance::set_layer_mask);
- ClassDB::bind_method(_MD("get_layer_mask"), &VisualInstance::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"),&VisualInstance::_get_visual_instance_rid);
+ ClassDB::bind_method(D_METHOD("set_base","base"), &VisualInstance::set_base);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","mask"), &VisualInstance::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"), &VisualInstance::get_layer_mask);
- ClassDB::bind_method(_MD("get_transformed_aabb"), &VisualInstance::get_transformed_aabb);
+ ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance::get_transformed_aabb);
- ADD_PROPERTY( PropertyInfo( Variant::INT, "layers",PROPERTY_HINT_LAYERS_3D_RENDER), _SCS("set_layer_mask"), _SCS("get_layer_mask"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "layers",PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask");
}
@@ -324,49 +324,49 @@ float GeometryInstance::get_extra_cull_margin() const{
void GeometryInstance::_bind_methods() {
- ClassDB::bind_method(_MD("set_material_override","material"), &GeometryInstance::set_material_override);
- ClassDB::bind_method(_MD("get_material_override"), &GeometryInstance::get_material_override);
+ ClassDB::bind_method(D_METHOD("set_material_override","material"), &GeometryInstance::set_material_override);
+ ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance::get_material_override);
- ClassDB::bind_method(_MD("set_flag","flag","value"), &GeometryInstance::set_flag);
- ClassDB::bind_method(_MD("get_flag","flag"), &GeometryInstance::get_flag);
+ ClassDB::bind_method(D_METHOD("set_flag","flag","value"), &GeometryInstance::set_flag);
+ ClassDB::bind_method(D_METHOD("get_flag","flag"), &GeometryInstance::get_flag);
- ClassDB::bind_method(_MD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance::set_cast_shadows_setting);
- ClassDB::bind_method(_MD("get_cast_shadows_setting"), &GeometryInstance::get_cast_shadows_setting);
+ ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance::set_cast_shadows_setting);
+ ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance::get_cast_shadows_setting);
- ClassDB::bind_method(_MD("set_lod_max_hysteresis","mode"), &GeometryInstance::set_lod_max_hysteresis);
- ClassDB::bind_method(_MD("get_lod_max_hysteresis"), &GeometryInstance::get_lod_max_hysteresis);
+ ClassDB::bind_method(D_METHOD("set_lod_max_hysteresis","mode"), &GeometryInstance::set_lod_max_hysteresis);
+ ClassDB::bind_method(D_METHOD("get_lod_max_hysteresis"), &GeometryInstance::get_lod_max_hysteresis);
- ClassDB::bind_method(_MD("set_lod_max_distance","mode"), &GeometryInstance::set_lod_max_distance);
- ClassDB::bind_method(_MD("get_lod_max_distance"), &GeometryInstance::get_lod_max_distance);
+ ClassDB::bind_method(D_METHOD("set_lod_max_distance","mode"), &GeometryInstance::set_lod_max_distance);
+ ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance::get_lod_max_distance);
- ClassDB::bind_method(_MD("set_lod_min_hysteresis","mode"), &GeometryInstance::set_lod_min_hysteresis);
- ClassDB::bind_method(_MD("get_lod_min_hysteresis"), &GeometryInstance::get_lod_min_hysteresis);
+ ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis","mode"), &GeometryInstance::set_lod_min_hysteresis);
+ ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance::get_lod_min_hysteresis);
- ClassDB::bind_method(_MD("set_lod_min_distance","mode"), &GeometryInstance::set_lod_min_distance);
- ClassDB::bind_method(_MD("get_lod_min_distance"), &GeometryInstance::get_lod_min_distance);
+ ClassDB::bind_method(D_METHOD("set_lod_min_distance","mode"), &GeometryInstance::set_lod_min_distance);
+ ClassDB::bind_method(D_METHOD("get_lod_min_distance"), &GeometryInstance::get_lod_min_distance);
- ClassDB::bind_method(_MD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin);
- ClassDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
+ ClassDB::bind_method(D_METHOD("set_extra_cull_margin","margin"), &GeometryInstance::set_extra_cull_margin);
+ ClassDB::bind_method(D_METHOD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
- ClassDB::bind_method(_MD("get_aabb"),&GeometryInstance::get_aabb);
+ ClassDB::bind_method(D_METHOD("get_aabb"),&GeometryInstance::get_aabb);
ADD_GROUP("Geometry","");
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material_override",PROPERTY_HINT_RESOURCE_TYPE,"Material"), _SCS("set_material_override"), _SCS("get_material_override"));
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), _SCS("set_cast_shadows_setting"), _SCS("get_cast_shadows_setting"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "extra_cull_margin",PROPERTY_HINT_RANGE,"0,16384,0"), _SCS("set_extra_cull_margin"), _SCS("get_extra_cull_margin"));
- ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_as_billboard"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD);
- ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_as_y_billboard"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD_FIX_Y);
- ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE);
- ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "visible_in_all_rooms"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE_IN_ALL_ROOMS);
- ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_in_baked_light"), _SCS("set_flag"), _SCS("get_flag"),FLAG_USE_BAKED_LIGHT);
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material_override",PROPERTY_HINT_RESOURCE_TYPE,"Material"), "set_material_override", "get_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "extra_cull_margin",PROPERTY_HINT_RANGE,"0,16384,0"), "set_extra_cull_margin", "get_extra_cull_margin");
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_as_billboard"), "set_flag", "get_flag",FLAG_BILLBOARD);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_as_y_billboard"), "set_flag", "get_flag",FLAG_BILLBOARD_FIX_Y);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_depth_scale"), "set_flag", "get_flag",FLAG_DEPH_SCALE);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "visible_in_all_rooms"), "set_flag", "get_flag",FLAG_VISIBLE_IN_ALL_ROOMS);
+ ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag",FLAG_USE_BAKED_LIGHT);
ADD_GROUP("LOD","lod_");
- ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_min_distance",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_lod_min_distance"), _SCS("get_lod_min_distance"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_min_hysteresis",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_lod_min_hysteresis"), _SCS("get_lod_min_hysteresis"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_max_distance",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_lod_max_distance"), _SCS("get_lod_max_distance"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_max_hysteresis",PROPERTY_HINT_RANGE,"0,32768,0.01"), _SCS("set_lod_max_hysteresis"), _SCS("get_lod_max_hysteresis"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_min_distance",PROPERTY_HINT_RANGE,"0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_min_hysteresis",PROPERTY_HINT_RANGE,"0,32768,0.01"), "set_lod_min_hysteresis", "get_lod_min_hysteresis");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_max_distance",PROPERTY_HINT_RANGE,"0,32768,0.01"), "set_lod_max_distance", "get_lod_max_distance");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "lod_max_hysteresis",PROPERTY_HINT_RANGE,"0,32768,0.01"), "set_lod_max_hysteresis", "get_lod_max_hysteresis");
//ADD_SIGNAL( MethodInfo("visibility_changed"));
diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp
index bcbda5a781..960356d9cf 100644
--- a/scene/animation/animation_cache.cpp
+++ b/scene/animation/animation_cache.cpp
@@ -368,8 +368,8 @@ void AnimationCache::set_animation(const Ref<Animation>& p_animation) {
void AnimationCache::_bind_methods() {
- ClassDB::bind_method(_MD("_node_exit_tree"),&AnimationCache::_node_exit_tree);
- ClassDB::bind_method(_MD("_animation_changed"),&AnimationCache::_animation_changed);
+ ClassDB::bind_method(D_METHOD("_node_exit_tree"),&AnimationCache::_node_exit_tree);
+ ClassDB::bind_method(D_METHOD("_animation_changed"),&AnimationCache::_animation_changed);
}
void AnimationCache::set_root(Node* p_root) {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index e02b2b2b41..e9f1904fe9 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -588,35 +588,26 @@ void AnimationPlayer::_animation_process2(float p_delta) {
Playback &c=playback;
- float prev_blend=1.0;
accum_pass++;
- int pop_count=1;
- int pop=0; // if >0, then amount of elements to pop from the back
+ _animation_process_data(c.current,p_delta,1.0f);
-
- for (List<Blend>::Element *E=c.blend.back();E;E=E->prev(),pop_count++) {
+ List<Blend>::Element *prev = NULL;
+ for (List<Blend>::Element *E=c.blend.back();E;E=prev) {
Blend& b=E->get();
- _animation_process_data(b.data,p_delta,prev_blend);
-
- prev_blend=1.0-b.blend_left/b.blend_time;
+ float blend=b.blend_left/b.blend_time;
+ _animation_process_data(b.data,p_delta,blend);
b.blend_left-=Math::absf(speed_scale*p_delta);
+ prev = E->prev();
if (b.blend_left<0) {
- pop=pop_count;
+ c.blend.erase(E);
}
}
-
- while(pop--) {
-
- c.blend.pop_back();
- }
-
-
- _animation_process_data(c.current,p_delta,prev_blend);
+
}
@@ -1296,67 +1287,67 @@ void AnimationPlayer::get_argument_options(const StringName& p_function,int p_id
void AnimationPlayer::_bind_methods() {
- ClassDB::bind_method(_MD("_node_removed"),&AnimationPlayer::_node_removed);
- ClassDB::bind_method(_MD("_animation_changed"),&AnimationPlayer::_animation_changed);
+ ClassDB::bind_method(D_METHOD("_node_removed"),&AnimationPlayer::_node_removed);
+ ClassDB::bind_method(D_METHOD("_animation_changed"),&AnimationPlayer::_animation_changed);
- ClassDB::bind_method(_MD("add_animation","name","animation:Animation"),&AnimationPlayer::add_animation);
- ClassDB::bind_method(_MD("remove_animation","name"),&AnimationPlayer::remove_animation);
- ClassDB::bind_method(_MD("rename_animation","name","newname"),&AnimationPlayer::rename_animation);
- ClassDB::bind_method(_MD("has_animation","name"),&AnimationPlayer::has_animation);
- ClassDB::bind_method(_MD("get_animation:Animation","name"),&AnimationPlayer::get_animation);
- ClassDB::bind_method(_MD("get_animation_list"),&AnimationPlayer::_get_animation_list);
+ ClassDB::bind_method(D_METHOD("add_animation","name","animation:Animation"),&AnimationPlayer::add_animation);
+ ClassDB::bind_method(D_METHOD("remove_animation","name"),&AnimationPlayer::remove_animation);
+ ClassDB::bind_method(D_METHOD("rename_animation","name","newname"),&AnimationPlayer::rename_animation);
+ ClassDB::bind_method(D_METHOD("has_animation","name"),&AnimationPlayer::has_animation);
+ ClassDB::bind_method(D_METHOD("get_animation:Animation","name"),&AnimationPlayer::get_animation);
+ ClassDB::bind_method(D_METHOD("get_animation_list"),&AnimationPlayer::_get_animation_list);
- ClassDB::bind_method(_MD("animation_set_next", "anim_from", "anim_to"), &AnimationPlayer::animation_set_next);
- ClassDB::bind_method(_MD("animation_get_next", "anim_from"), &AnimationPlayer::animation_get_next);
+ ClassDB::bind_method(D_METHOD("animation_set_next", "anim_from", "anim_to"), &AnimationPlayer::animation_set_next);
+ ClassDB::bind_method(D_METHOD("animation_get_next", "anim_from"), &AnimationPlayer::animation_get_next);
- ClassDB::bind_method(_MD("set_blend_time","anim_from","anim_to","sec"),&AnimationPlayer::set_blend_time);
- ClassDB::bind_method(_MD("get_blend_time","anim_from","anim_to"),&AnimationPlayer::get_blend_time);
+ ClassDB::bind_method(D_METHOD("set_blend_time","anim_from","anim_to","sec"),&AnimationPlayer::set_blend_time);
+ ClassDB::bind_method(D_METHOD("get_blend_time","anim_from","anim_to"),&AnimationPlayer::get_blend_time);
- ClassDB::bind_method(_MD("set_default_blend_time","sec"),&AnimationPlayer::set_default_blend_time);
- ClassDB::bind_method(_MD("get_default_blend_time"),&AnimationPlayer::get_default_blend_time);
+ ClassDB::bind_method(D_METHOD("set_default_blend_time","sec"),&AnimationPlayer::set_default_blend_time);
+ ClassDB::bind_method(D_METHOD("get_default_blend_time"),&AnimationPlayer::get_default_blend_time);
- ClassDB::bind_method(_MD("play","name","custom_blend","custom_speed","from_end"),&AnimationPlayer::play,DEFVAL(""),DEFVAL(-1),DEFVAL(1.0),DEFVAL(false));
- ClassDB::bind_method(_MD("play_backwards","name","custom_blend"),&AnimationPlayer::play_backwards,DEFVAL(""),DEFVAL(-1));
- ClassDB::bind_method(_MD("stop","reset"),&AnimationPlayer::stop,DEFVAL(true));
- ClassDB::bind_method(_MD("stop_all"),&AnimationPlayer::stop_all);
- ClassDB::bind_method(_MD("is_playing"),&AnimationPlayer::is_playing);
- ClassDB::bind_method(_MD("set_current_animation","anim"),&AnimationPlayer::set_current_animation);
- ClassDB::bind_method(_MD("get_current_animation"),&AnimationPlayer::get_current_animation);
- ClassDB::bind_method(_MD("queue","name"),&AnimationPlayer::queue);
- ClassDB::bind_method(_MD("clear_queue"),&AnimationPlayer::clear_queue);
+ ClassDB::bind_method(D_METHOD("play","name","custom_blend","custom_speed","from_end"),&AnimationPlayer::play,DEFVAL(""),DEFVAL(-1),DEFVAL(1.0),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("play_backwards","name","custom_blend"),&AnimationPlayer::play_backwards,DEFVAL(""),DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("stop","reset"),&AnimationPlayer::stop,DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("stop_all"),&AnimationPlayer::stop_all);
+ ClassDB::bind_method(D_METHOD("is_playing"),&AnimationPlayer::is_playing);
+ ClassDB::bind_method(D_METHOD("set_current_animation","anim"),&AnimationPlayer::set_current_animation);
+ ClassDB::bind_method(D_METHOD("get_current_animation"),&AnimationPlayer::get_current_animation);
+ ClassDB::bind_method(D_METHOD("queue","name"),&AnimationPlayer::queue);
+ ClassDB::bind_method(D_METHOD("clear_queue"),&AnimationPlayer::clear_queue);
- ClassDB::bind_method(_MD("set_active","active"),&AnimationPlayer::set_active);
- ClassDB::bind_method(_MD("is_active"),&AnimationPlayer::is_active);
+ ClassDB::bind_method(D_METHOD("set_active","active"),&AnimationPlayer::set_active);
+ ClassDB::bind_method(D_METHOD("is_active"),&AnimationPlayer::is_active);
- ClassDB::bind_method(_MD("set_speed_scale","speed"),&AnimationPlayer::set_speed_scale);
- ClassDB::bind_method(_MD("get_speed_scale"),&AnimationPlayer::get_speed_scale);
+ ClassDB::bind_method(D_METHOD("set_speed_scale","speed"),&AnimationPlayer::set_speed_scale);
+ ClassDB::bind_method(D_METHOD("get_speed_scale"),&AnimationPlayer::get_speed_scale);
- ClassDB::bind_method(_MD("set_autoplay","name"),&AnimationPlayer::set_autoplay);
- ClassDB::bind_method(_MD("get_autoplay"),&AnimationPlayer::get_autoplay);
+ ClassDB::bind_method(D_METHOD("set_autoplay","name"),&AnimationPlayer::set_autoplay);
+ ClassDB::bind_method(D_METHOD("get_autoplay"),&AnimationPlayer::get_autoplay);
- ClassDB::bind_method(_MD("set_root","path"),&AnimationPlayer::set_root);
- ClassDB::bind_method(_MD("get_root"),&AnimationPlayer::get_root);
+ ClassDB::bind_method(D_METHOD("set_root","path"),&AnimationPlayer::set_root);
+ ClassDB::bind_method(D_METHOD("get_root"),&AnimationPlayer::get_root);
- ClassDB::bind_method(_MD("seek","pos_sec","update"),&AnimationPlayer::seek,DEFVAL(false));
- ClassDB::bind_method(_MD("get_pos"),&AnimationPlayer::get_current_animation_pos);
+ ClassDB::bind_method(D_METHOD("seek","pos_sec","update"),&AnimationPlayer::seek,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_pos"),&AnimationPlayer::get_current_animation_pos);
- ClassDB::bind_method(_MD("find_animation","animation:Animation"),&AnimationPlayer::find_animation);
+ ClassDB::bind_method(D_METHOD("find_animation","animation:Animation"),&AnimationPlayer::find_animation);
- ClassDB::bind_method(_MD("clear_caches"),&AnimationPlayer::clear_caches);
+ ClassDB::bind_method(D_METHOD("clear_caches"),&AnimationPlayer::clear_caches);
- ClassDB::bind_method(_MD("set_animation_process_mode","mode"),&AnimationPlayer::set_animation_process_mode);
- ClassDB::bind_method(_MD("get_animation_process_mode"),&AnimationPlayer::get_animation_process_mode);
+ ClassDB::bind_method(D_METHOD("set_animation_process_mode","mode"),&AnimationPlayer::set_animation_process_mode);
+ ClassDB::bind_method(D_METHOD("get_animation_process_mode"),&AnimationPlayer::get_animation_process_mode);
- ClassDB::bind_method(_MD("get_current_animation_pos"),&AnimationPlayer::get_current_animation_pos);
- ClassDB::bind_method(_MD("get_current_animation_length"),&AnimationPlayer::get_current_animation_length);
+ ClassDB::bind_method(D_METHOD("get_current_animation_pos"),&AnimationPlayer::get_current_animation_pos);
+ ClassDB::bind_method(D_METHOD("get_current_animation_length"),&AnimationPlayer::get_current_animation_length);
- ClassDB::bind_method(_MD("advance","delta"),&AnimationPlayer::advance);
+ ClassDB::bind_method(D_METHOD("advance","delta"),&AnimationPlayer::advance);
ADD_GROUP("Playback","playback_");
- ADD_PROPERTY( PropertyInfo( Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), _SCS("set_default_blend_time"), _SCS("get_default_blend_time"));
- ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "root_node"), _SCS("set_root"), _SCS("get_root"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_animation_process_mode", "get_animation_process_mode");
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_default_blend_time", "get_default_blend_time");
+ ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "root_node"), "set_root", "get_root");
ADD_SIGNAL( MethodInfo("animation_finished", PropertyInfo(Variant::STRING,"name")) );
ADD_SIGNAL( MethodInfo("animation_changed", PropertyInfo(Variant::STRING,"old_name"), PropertyInfo(Variant::STRING,"new_name")) );
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index a3347dadcf..d7e98ddd2b 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -711,7 +711,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
else
rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_time*tsn->scale,false,p_fallback_weight,p_weights);
if (tsn->scale == 0)
- return INFINITY;
+ return Math_INF;
else
return rem / tsn->scale;
@@ -1828,106 +1828,106 @@ Error AnimationTreePlayer::node_rename(const StringName& p_node,const StringName
void AnimationTreePlayer::_bind_methods() {
- ClassDB::bind_method(_MD("add_node","type","id"),&AnimationTreePlayer::add_node);
+ ClassDB::bind_method(D_METHOD("add_node","type","id"),&AnimationTreePlayer::add_node);
- ClassDB::bind_method(_MD("node_exists","node"),&AnimationTreePlayer::node_exists);
- ClassDB::bind_method(_MD("node_rename","node","new_name"),&AnimationTreePlayer::node_rename);
+ ClassDB::bind_method(D_METHOD("node_exists","node"),&AnimationTreePlayer::node_exists);
+ ClassDB::bind_method(D_METHOD("node_rename","node","new_name"),&AnimationTreePlayer::node_rename);
- ClassDB::bind_method(_MD("node_get_type","id"),&AnimationTreePlayer::node_get_type);
- ClassDB::bind_method(_MD("node_get_input_count","id"),&AnimationTreePlayer::node_get_input_count);
- ClassDB::bind_method(_MD("node_get_input_source","id","idx"),&AnimationTreePlayer::node_get_input_source);
+ ClassDB::bind_method(D_METHOD("node_get_type","id"),&AnimationTreePlayer::node_get_type);
+ ClassDB::bind_method(D_METHOD("node_get_input_count","id"),&AnimationTreePlayer::node_get_input_count);
+ ClassDB::bind_method(D_METHOD("node_get_input_source","id","idx"),&AnimationTreePlayer::node_get_input_source);
- ClassDB::bind_method(_MD("animation_node_set_animation","id","animation:Animation"),&AnimationTreePlayer::animation_node_set_animation);
- ClassDB::bind_method(_MD("animation_node_get_animation:Animation","id"),&AnimationTreePlayer::animation_node_get_animation);
+ ClassDB::bind_method(D_METHOD("animation_node_set_animation","id","animation:Animation"),&AnimationTreePlayer::animation_node_set_animation);
+ ClassDB::bind_method(D_METHOD("animation_node_get_animation:Animation","id"),&AnimationTreePlayer::animation_node_get_animation);
- ClassDB::bind_method(_MD("animation_node_set_master_animation","id","source"),&AnimationTreePlayer::animation_node_set_master_animation);
- ClassDB::bind_method(_MD("animation_node_get_master_animation","id"),&AnimationTreePlayer::animation_node_get_master_animation);
- ClassDB::bind_method(_MD("animation_node_set_filter_path","id","path","enable"),&AnimationTreePlayer::animation_node_set_filter_path);
+ ClassDB::bind_method(D_METHOD("animation_node_set_master_animation","id","source"),&AnimationTreePlayer::animation_node_set_master_animation);
+ ClassDB::bind_method(D_METHOD("animation_node_get_master_animation","id"),&AnimationTreePlayer::animation_node_get_master_animation);
+ ClassDB::bind_method(D_METHOD("animation_node_set_filter_path","id","path","enable"),&AnimationTreePlayer::animation_node_set_filter_path);
- ClassDB::bind_method(_MD("oneshot_node_set_fadein_time","id","time_sec"),&AnimationTreePlayer::oneshot_node_set_fadein_time);
- ClassDB::bind_method(_MD("oneshot_node_get_fadein_time","id"),&AnimationTreePlayer::oneshot_node_get_fadein_time);
+ ClassDB::bind_method(D_METHOD("oneshot_node_set_fadein_time","id","time_sec"),&AnimationTreePlayer::oneshot_node_set_fadein_time);
+ ClassDB::bind_method(D_METHOD("oneshot_node_get_fadein_time","id"),&AnimationTreePlayer::oneshot_node_get_fadein_time);
- ClassDB::bind_method(_MD("oneshot_node_set_fadeout_time","id","time_sec"),&AnimationTreePlayer::oneshot_node_set_fadeout_time);
- ClassDB::bind_method(_MD("oneshot_node_get_fadeout_time","id"),&AnimationTreePlayer::oneshot_node_get_fadeout_time);
+ ClassDB::bind_method(D_METHOD("oneshot_node_set_fadeout_time","id","time_sec"),&AnimationTreePlayer::oneshot_node_set_fadeout_time);
+ ClassDB::bind_method(D_METHOD("oneshot_node_get_fadeout_time","id"),&AnimationTreePlayer::oneshot_node_get_fadeout_time);
- ClassDB::bind_method(_MD("oneshot_node_set_autorestart","id","enable"),&AnimationTreePlayer::oneshot_node_set_autorestart);
- ClassDB::bind_method(_MD("oneshot_node_set_autorestart_delay","id","delay_sec"),&AnimationTreePlayer::oneshot_node_set_autorestart_delay);
- ClassDB::bind_method(_MD("oneshot_node_set_autorestart_random_delay","id","rand_sec"),&AnimationTreePlayer::oneshot_node_set_autorestart_random_delay);
+ ClassDB::bind_method(D_METHOD("oneshot_node_set_autorestart","id","enable"),&AnimationTreePlayer::oneshot_node_set_autorestart);
+ ClassDB::bind_method(D_METHOD("oneshot_node_set_autorestart_delay","id","delay_sec"),&AnimationTreePlayer::oneshot_node_set_autorestart_delay);
+ ClassDB::bind_method(D_METHOD("oneshot_node_set_autorestart_random_delay","id","rand_sec"),&AnimationTreePlayer::oneshot_node_set_autorestart_random_delay);
- ClassDB::bind_method(_MD("oneshot_node_has_autorestart","id"),&AnimationTreePlayer::oneshot_node_has_autorestart);
- ClassDB::bind_method(_MD("oneshot_node_get_autorestart_delay","id"),&AnimationTreePlayer::oneshot_node_get_autorestart_delay);
- ClassDB::bind_method(_MD("oneshot_node_get_autorestart_random_delay","id"),&AnimationTreePlayer::oneshot_node_get_autorestart_random_delay);
+ ClassDB::bind_method(D_METHOD("oneshot_node_has_autorestart","id"),&AnimationTreePlayer::oneshot_node_has_autorestart);
+ ClassDB::bind_method(D_METHOD("oneshot_node_get_autorestart_delay","id"),&AnimationTreePlayer::oneshot_node_get_autorestart_delay);
+ ClassDB::bind_method(D_METHOD("oneshot_node_get_autorestart_random_delay","id"),&AnimationTreePlayer::oneshot_node_get_autorestart_random_delay);
- ClassDB::bind_method(_MD("oneshot_node_start","id"),&AnimationTreePlayer::oneshot_node_start);
- ClassDB::bind_method(_MD("oneshot_node_stop","id"),&AnimationTreePlayer::oneshot_node_stop);
- ClassDB::bind_method(_MD("oneshot_node_is_active","id"),&AnimationTreePlayer::oneshot_node_is_active);
- ClassDB::bind_method(_MD("oneshot_node_set_filter_path","id","path","enable"),&AnimationTreePlayer::oneshot_node_set_filter_path);
+ ClassDB::bind_method(D_METHOD("oneshot_node_start","id"),&AnimationTreePlayer::oneshot_node_start);
+ ClassDB::bind_method(D_METHOD("oneshot_node_stop","id"),&AnimationTreePlayer::oneshot_node_stop);
+ ClassDB::bind_method(D_METHOD("oneshot_node_is_active","id"),&AnimationTreePlayer::oneshot_node_is_active);
+ ClassDB::bind_method(D_METHOD("oneshot_node_set_filter_path","id","path","enable"),&AnimationTreePlayer::oneshot_node_set_filter_path);
- ClassDB::bind_method(_MD("mix_node_set_amount","id","ratio"),&AnimationTreePlayer::mix_node_set_amount);
- ClassDB::bind_method(_MD("mix_node_get_amount","id"),&AnimationTreePlayer::mix_node_get_amount);
+ ClassDB::bind_method(D_METHOD("mix_node_set_amount","id","ratio"),&AnimationTreePlayer::mix_node_set_amount);
+ ClassDB::bind_method(D_METHOD("mix_node_get_amount","id"),&AnimationTreePlayer::mix_node_get_amount);
- ClassDB::bind_method(_MD("blend2_node_set_amount","id","blend"),&AnimationTreePlayer::blend2_node_set_amount);
- ClassDB::bind_method(_MD("blend2_node_get_amount","id"),&AnimationTreePlayer::blend2_node_get_amount);
- ClassDB::bind_method(_MD("blend2_node_set_filter_path","id","path","enable"),&AnimationTreePlayer::blend2_node_set_filter_path);
+ ClassDB::bind_method(D_METHOD("blend2_node_set_amount","id","blend"),&AnimationTreePlayer::blend2_node_set_amount);
+ ClassDB::bind_method(D_METHOD("blend2_node_get_amount","id"),&AnimationTreePlayer::blend2_node_get_amount);
+ ClassDB::bind_method(D_METHOD("blend2_node_set_filter_path","id","path","enable"),&AnimationTreePlayer::blend2_node_set_filter_path);
- ClassDB::bind_method(_MD("blend3_node_set_amount","id","blend"),&AnimationTreePlayer::blend3_node_set_amount);
- ClassDB::bind_method(_MD("blend3_node_get_amount","id"),&AnimationTreePlayer::blend3_node_get_amount);
+ ClassDB::bind_method(D_METHOD("blend3_node_set_amount","id","blend"),&AnimationTreePlayer::blend3_node_set_amount);
+ ClassDB::bind_method(D_METHOD("blend3_node_get_amount","id"),&AnimationTreePlayer::blend3_node_get_amount);
- ClassDB::bind_method(_MD("blend4_node_set_amount","id","blend"),&AnimationTreePlayer::blend4_node_set_amount);
- ClassDB::bind_method(_MD("blend4_node_get_amount","id"),&AnimationTreePlayer::blend4_node_get_amount);
+ ClassDB::bind_method(D_METHOD("blend4_node_set_amount","id","blend"),&AnimationTreePlayer::blend4_node_set_amount);
+ ClassDB::bind_method(D_METHOD("blend4_node_get_amount","id"),&AnimationTreePlayer::blend4_node_get_amount);
- ClassDB::bind_method(_MD("timescale_node_set_scale","id","scale"),&AnimationTreePlayer::timescale_node_set_scale);
- ClassDB::bind_method(_MD("timescale_node_get_scale","id"),&AnimationTreePlayer::timescale_node_get_scale);
+ ClassDB::bind_method(D_METHOD("timescale_node_set_scale","id","scale"),&AnimationTreePlayer::timescale_node_set_scale);
+ ClassDB::bind_method(D_METHOD("timescale_node_get_scale","id"),&AnimationTreePlayer::timescale_node_get_scale);
- ClassDB::bind_method(_MD("timeseek_node_seek","id","pos_sec"),&AnimationTreePlayer::timeseek_node_seek);
+ ClassDB::bind_method(D_METHOD("timeseek_node_seek","id","pos_sec"),&AnimationTreePlayer::timeseek_node_seek);
- ClassDB::bind_method(_MD("transition_node_set_input_count","id","count"),&AnimationTreePlayer::transition_node_set_input_count);
- ClassDB::bind_method(_MD("transition_node_get_input_count","id"),&AnimationTreePlayer::transition_node_get_input_count);
- ClassDB::bind_method(_MD("transition_node_delete_input","id","input_idx"),&AnimationTreePlayer::transition_node_delete_input);
+ ClassDB::bind_method(D_METHOD("transition_node_set_input_count","id","count"),&AnimationTreePlayer::transition_node_set_input_count);
+ ClassDB::bind_method(D_METHOD("transition_node_get_input_count","id"),&AnimationTreePlayer::transition_node_get_input_count);
+ ClassDB::bind_method(D_METHOD("transition_node_delete_input","id","input_idx"),&AnimationTreePlayer::transition_node_delete_input);
- ClassDB::bind_method(_MD("transition_node_set_input_auto_advance","id","input_idx","enable"),&AnimationTreePlayer::transition_node_set_input_auto_advance);
- ClassDB::bind_method(_MD("transition_node_has_input_auto_advance","id","input_idx"),&AnimationTreePlayer::transition_node_has_input_auto_advance);
+ ClassDB::bind_method(D_METHOD("transition_node_set_input_auto_advance","id","input_idx","enable"),&AnimationTreePlayer::transition_node_set_input_auto_advance);
+ ClassDB::bind_method(D_METHOD("transition_node_has_input_auto_advance","id","input_idx"),&AnimationTreePlayer::transition_node_has_input_auto_advance);
- ClassDB::bind_method(_MD("transition_node_set_xfade_time","id","time_sec"),&AnimationTreePlayer::transition_node_set_xfade_time);
- ClassDB::bind_method(_MD("transition_node_get_xfade_time","id"),&AnimationTreePlayer::transition_node_get_xfade_time);
+ ClassDB::bind_method(D_METHOD("transition_node_set_xfade_time","id","time_sec"),&AnimationTreePlayer::transition_node_set_xfade_time);
+ ClassDB::bind_method(D_METHOD("transition_node_get_xfade_time","id"),&AnimationTreePlayer::transition_node_get_xfade_time);
- ClassDB::bind_method(_MD("transition_node_set_current","id","input_idx"),&AnimationTreePlayer::transition_node_set_current);
- ClassDB::bind_method(_MD("transition_node_get_current","id"),&AnimationTreePlayer::transition_node_get_current);
+ ClassDB::bind_method(D_METHOD("transition_node_set_current","id","input_idx"),&AnimationTreePlayer::transition_node_set_current);
+ ClassDB::bind_method(D_METHOD("transition_node_get_current","id"),&AnimationTreePlayer::transition_node_get_current);
- ClassDB::bind_method(_MD("node_set_pos","id","screen_pos"),&AnimationTreePlayer::node_set_pos);
- ClassDB::bind_method(_MD("node_get_pos","id"),&AnimationTreePlayer::node_get_pos);
+ ClassDB::bind_method(D_METHOD("node_set_pos","id","screen_pos"),&AnimationTreePlayer::node_set_pos);
+ ClassDB::bind_method(D_METHOD("node_get_pos","id"),&AnimationTreePlayer::node_get_pos);
- ClassDB::bind_method(_MD("remove_node","id"),&AnimationTreePlayer::remove_node);
- ClassDB::bind_method(_MD("connect_nodes","id","dst_id","dst_input_idx"),&AnimationTreePlayer::connect_nodes);
- ClassDB::bind_method(_MD("are_nodes_connected","id","dst_id","dst_input_idx"),&AnimationTreePlayer::are_nodes_connected);
- ClassDB::bind_method(_MD("disconnect_nodes","id","dst_input_idx"),&AnimationTreePlayer::disconnect_nodes);
+ ClassDB::bind_method(D_METHOD("remove_node","id"),&AnimationTreePlayer::remove_node);
+ ClassDB::bind_method(D_METHOD("connect_nodes","id","dst_id","dst_input_idx"),&AnimationTreePlayer::connect_nodes);
+ ClassDB::bind_method(D_METHOD("are_nodes_connected","id","dst_id","dst_input_idx"),&AnimationTreePlayer::are_nodes_connected);
+ ClassDB::bind_method(D_METHOD("disconnect_nodes","id","dst_input_idx"),&AnimationTreePlayer::disconnect_nodes);
- ClassDB::bind_method(_MD("set_active","enabled"),&AnimationTreePlayer::set_active);
- ClassDB::bind_method(_MD("is_active"),&AnimationTreePlayer::is_active);
+ ClassDB::bind_method(D_METHOD("set_active","enabled"),&AnimationTreePlayer::set_active);
+ ClassDB::bind_method(D_METHOD("is_active"),&AnimationTreePlayer::is_active);
- ClassDB::bind_method(_MD("set_base_path","path"),&AnimationTreePlayer::set_base_path);
- ClassDB::bind_method(_MD("get_base_path"),&AnimationTreePlayer::get_base_path);
+ ClassDB::bind_method(D_METHOD("set_base_path","path"),&AnimationTreePlayer::set_base_path);
+ ClassDB::bind_method(D_METHOD("get_base_path"),&AnimationTreePlayer::get_base_path);
- ClassDB::bind_method(_MD("set_master_player","nodepath"),&AnimationTreePlayer::set_master_player);
- ClassDB::bind_method(_MD("get_master_player"),&AnimationTreePlayer::get_master_player);
+ ClassDB::bind_method(D_METHOD("set_master_player","nodepath"),&AnimationTreePlayer::set_master_player);
+ ClassDB::bind_method(D_METHOD("get_master_player"),&AnimationTreePlayer::get_master_player);
- ClassDB::bind_method(_MD("get_node_list"),&AnimationTreePlayer::_get_node_list);
+ ClassDB::bind_method(D_METHOD("get_node_list"),&AnimationTreePlayer::_get_node_list);
- ClassDB::bind_method(_MD("set_animation_process_mode","mode"),&AnimationTreePlayer::set_animation_process_mode);
- ClassDB::bind_method(_MD("get_animation_process_mode"),&AnimationTreePlayer::get_animation_process_mode);
+ ClassDB::bind_method(D_METHOD("set_animation_process_mode","mode"),&AnimationTreePlayer::set_animation_process_mode);
+ ClassDB::bind_method(D_METHOD("get_animation_process_mode"),&AnimationTreePlayer::get_animation_process_mode);
- ClassDB::bind_method(_MD("advance", "delta"), &AnimationTreePlayer::advance);
+ ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationTreePlayer::advance);
- ClassDB::bind_method(_MD("reset"),&AnimationTreePlayer::reset);
+ ClassDB::bind_method(D_METHOD("reset"),&AnimationTreePlayer::reset);
- ClassDB::bind_method(_MD("recompute_caches"),&AnimationTreePlayer::recompute_caches);
+ ClassDB::bind_method(D_METHOD("recompute_caches"),&AnimationTreePlayer::recompute_caches);
ADD_GROUP("Playback","playback_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_animation_process_mode", "get_animation_process_mode");
BIND_CONSTANT( NODE_OUTPUT );
BIND_CONSTANT( NODE_ANIMATION );
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 0916119db3..c422e765b5 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -186,46 +186,46 @@ void Tween::_notification(int p_what) {
void Tween::_bind_methods() {
- ClassDB::bind_method(_MD("is_active"),&Tween::is_active );
- ClassDB::bind_method(_MD("set_active","active"),&Tween::set_active );
-
- ClassDB::bind_method(_MD("is_repeat"),&Tween::is_repeat );
- ClassDB::bind_method(_MD("set_repeat","repeat"),&Tween::set_repeat );
-
- ClassDB::bind_method(_MD("set_speed_scale","speed"),&Tween::set_speed_scale);
- ClassDB::bind_method(_MD("get_speed_scale"),&Tween::get_speed_scale);
-
- ClassDB::bind_method(_MD("set_tween_process_mode","mode"),&Tween::set_tween_process_mode);
- ClassDB::bind_method(_MD("get_tween_process_mode"),&Tween::get_tween_process_mode);
-
- ClassDB::bind_method(_MD("start"),&Tween::start );
- ClassDB::bind_method(_MD("reset","object","key"),&Tween::reset, DEFVAL("") );
- ClassDB::bind_method(_MD("reset_all"),&Tween::reset_all );
- ClassDB::bind_method(_MD("stop","object","key"),&Tween::stop, DEFVAL("") );
- ClassDB::bind_method(_MD("stop_all"),&Tween::stop_all );
- ClassDB::bind_method(_MD("resume","object","key"),&Tween::resume, DEFVAL("") );
- ClassDB::bind_method(_MD("resume_all"),&Tween::resume_all );
- ClassDB::bind_method(_MD("remove","object","key"),&Tween::remove, DEFVAL("") );
- ClassDB::bind_method(_MD("_remove","object","key","first_only"),&Tween::_remove );
- ClassDB::bind_method(_MD("remove_all"),&Tween::remove_all );
- ClassDB::bind_method(_MD("seek","time"),&Tween::seek );
- ClassDB::bind_method(_MD("tell"),&Tween::tell );
- ClassDB::bind_method(_MD("get_runtime"),&Tween::get_runtime );
-
- ClassDB::bind_method(_MD("interpolate_property","object","property","initial_val","final_val","duration","trans_type","ease_type","delay"),&Tween::interpolate_property, DEFVAL(0) );
- ClassDB::bind_method(_MD("interpolate_method","object","method","initial_val","final_val","duration","trans_type","ease_type","delay"),&Tween::interpolate_method, DEFVAL(0) );
- ClassDB::bind_method(_MD("interpolate_callback","object","duration","callback","arg1", "arg2","arg3","arg4","arg5"),&Tween::interpolate_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()) );
- ClassDB::bind_method(_MD("interpolate_deferred_callback","object","duration","callback","arg1","arg2","arg3","arg4","arg5"),&Tween::interpolate_deferred_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()) );
- ClassDB::bind_method(_MD("follow_property","object","property","initial_val","target","target_property","duration","trans_type","ease_type","delay"),&Tween::follow_property, DEFVAL(0) );
- ClassDB::bind_method(_MD("follow_method","object","method","initial_val","target","target_method","duration","trans_type","ease_type","delay"),&Tween::follow_method, DEFVAL(0) );
- ClassDB::bind_method(_MD("targeting_property","object","property","initial","initial_val","final_val","duration","trans_type","ease_type","delay"),&Tween::targeting_property, DEFVAL(0) );
- ClassDB::bind_method(_MD("targeting_method","object","method","initial","initial_method","final_val","duration","trans_type","ease_type","delay"),&Tween::targeting_method, DEFVAL(0) );
+ ClassDB::bind_method(D_METHOD("is_active"),&Tween::is_active );
+ ClassDB::bind_method(D_METHOD("set_active","active"),&Tween::set_active );
+
+ ClassDB::bind_method(D_METHOD("is_repeat"),&Tween::is_repeat );
+ ClassDB::bind_method(D_METHOD("set_repeat","repeat"),&Tween::set_repeat );
+
+ ClassDB::bind_method(D_METHOD("set_speed_scale","speed"),&Tween::set_speed_scale);
+ ClassDB::bind_method(D_METHOD("get_speed_scale"),&Tween::get_speed_scale);
+
+ ClassDB::bind_method(D_METHOD("set_tween_process_mode","mode"),&Tween::set_tween_process_mode);
+ ClassDB::bind_method(D_METHOD("get_tween_process_mode"),&Tween::get_tween_process_mode);
+
+ ClassDB::bind_method(D_METHOD("start"),&Tween::start );
+ ClassDB::bind_method(D_METHOD("reset","object","key"),&Tween::reset, DEFVAL("") );
+ ClassDB::bind_method(D_METHOD("reset_all"),&Tween::reset_all );
+ ClassDB::bind_method(D_METHOD("stop","object","key"),&Tween::stop, DEFVAL("") );
+ ClassDB::bind_method(D_METHOD("stop_all"),&Tween::stop_all );
+ ClassDB::bind_method(D_METHOD("resume","object","key"),&Tween::resume, DEFVAL("") );
+ ClassDB::bind_method(D_METHOD("resume_all"),&Tween::resume_all );
+ ClassDB::bind_method(D_METHOD("remove","object","key"),&Tween::remove, DEFVAL("") );
+ ClassDB::bind_method(D_METHOD("_remove","object","key","first_only"),&Tween::_remove );
+ ClassDB::bind_method(D_METHOD("remove_all"),&Tween::remove_all );
+ ClassDB::bind_method(D_METHOD("seek","time"),&Tween::seek );
+ ClassDB::bind_method(D_METHOD("tell"),&Tween::tell );
+ ClassDB::bind_method(D_METHOD("get_runtime"),&Tween::get_runtime );
+
+ ClassDB::bind_method(D_METHOD("interpolate_property","object","property","initial_val","final_val","duration","trans_type","ease_type","delay"),&Tween::interpolate_property, DEFVAL(0) );
+ ClassDB::bind_method(D_METHOD("interpolate_method","object","method","initial_val","final_val","duration","trans_type","ease_type","delay"),&Tween::interpolate_method, DEFVAL(0) );
+ ClassDB::bind_method(D_METHOD("interpolate_callback","object","duration","callback","arg1", "arg2","arg3","arg4","arg5"),&Tween::interpolate_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()) );
+ ClassDB::bind_method(D_METHOD("interpolate_deferred_callback","object","duration","callback","arg1","arg2","arg3","arg4","arg5"),&Tween::interpolate_deferred_callback, DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Variant()) );
+ ClassDB::bind_method(D_METHOD("follow_property","object","property","initial_val","target","target_property","duration","trans_type","ease_type","delay"),&Tween::follow_property, DEFVAL(0) );
+ ClassDB::bind_method(D_METHOD("follow_method","object","method","initial_val","target","target_method","duration","trans_type","ease_type","delay"),&Tween::follow_method, DEFVAL(0) );
+ ClassDB::bind_method(D_METHOD("targeting_property","object","property","initial","initial_val","final_val","duration","trans_type","ease_type","delay"),&Tween::targeting_property, DEFVAL(0) );
+ ClassDB::bind_method(D_METHOD("targeting_method","object","method","initial","initial_method","final_val","duration","trans_type","ease_type","delay"),&Tween::targeting_method, DEFVAL(0) );
ADD_SIGNAL( MethodInfo("tween_started", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key")) );
ADD_SIGNAL( MethodInfo("tween_step", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key"), PropertyInfo( Variant::REAL,"elapsed"), PropertyInfo( Variant::OBJECT,"value")) );
ADD_SIGNAL( MethodInfo("tween_completed", PropertyInfo( Variant::OBJECT,"object"), PropertyInfo( Variant::STRING,"key")) );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_tween_process_mode"), _SCS("get_tween_process_mode"));
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_tween_process_mode", "get_tween_process_mode");
BIND_CONSTANT(TWEEN_PROCESS_FIXED);
BIND_CONSTANT(TWEEN_PROCESS_IDLE);
@@ -405,9 +405,9 @@ Variant Tween::_run_equation(InterpolateData& p_data) {
case Variant::TRANSFORM2D:
{
- Basis i = initial_val;
- Basis d = delta_val;
- Basis r;
+ Transform2D i = initial_val;
+ Transform2D d = delta_val;
+ Transform2D r;
APPLY_EQUATION(elements[0][0]);
APPLY_EQUATION(elements[0][1]);
diff --git a/scene/animation/tween_interpolaters.cpp b/scene/animation/tween_interpolaters.cpp
index 5ba9673014..25a27252f5 100644
--- a/scene/animation/tween_interpolaters.cpp
+++ b/scene/animation/tween_interpolaters.cpp
@@ -262,7 +262,8 @@ namespace cubic {
static real_t out(real_t t, real_t b, real_t c, real_t d)
{
- return c * ((t = t / d - 1) * t * t + 1) + b;
+ t = t / d - 1;
+ return c * (t * t * t + 1) + b;
}
static real_t in_out(real_t t, real_t b, real_t c, real_t d)
diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp
index 9fd005e6fb..97eaea70b1 100644
--- a/scene/audio/audio_player.cpp
+++ b/scene/audio/audio_player.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_player.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_player.h"
@@ -243,40 +271,40 @@ void AudioPlayer::_bus_layout_changed() {
void AudioPlayer::_bind_methods() {
- ClassDB::bind_method(_MD("set_stream","stream:AudioStream"),&AudioPlayer::set_stream);
- ClassDB::bind_method(_MD("get_stream"),&AudioPlayer::get_stream);
+ ClassDB::bind_method(D_METHOD("set_stream","stream:AudioStream"),&AudioPlayer::set_stream);
+ ClassDB::bind_method(D_METHOD("get_stream"),&AudioPlayer::get_stream);
- ClassDB::bind_method(_MD("set_volume_db","volume_db"),&AudioPlayer::set_volume_db);
- ClassDB::bind_method(_MD("get_volume_db"),&AudioPlayer::get_volume_db);
+ ClassDB::bind_method(D_METHOD("set_volume_db","volume_db"),&AudioPlayer::set_volume_db);
+ ClassDB::bind_method(D_METHOD("get_volume_db"),&AudioPlayer::get_volume_db);
- ClassDB::bind_method(_MD("play","from_pos"),&AudioPlayer::play,DEFVAL(0.0));
- ClassDB::bind_method(_MD("seek","to_pos"),&AudioPlayer::seek);
- ClassDB::bind_method(_MD("stop"),&AudioPlayer::stop);
+ ClassDB::bind_method(D_METHOD("play","from_pos"),&AudioPlayer::play,DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("seek","to_pos"),&AudioPlayer::seek);
+ ClassDB::bind_method(D_METHOD("stop"),&AudioPlayer::stop);
- ClassDB::bind_method(_MD("is_playing"),&AudioPlayer::is_playing);
- ClassDB::bind_method(_MD("get_pos"),&AudioPlayer::get_pos);
+ ClassDB::bind_method(D_METHOD("is_playing"),&AudioPlayer::is_playing);
+ ClassDB::bind_method(D_METHOD("get_pos"),&AudioPlayer::get_pos);
- ClassDB::bind_method(_MD("set_bus","bus"),&AudioPlayer::set_bus);
- ClassDB::bind_method(_MD("get_bus"),&AudioPlayer::get_bus);
+ ClassDB::bind_method(D_METHOD("set_bus","bus"),&AudioPlayer::set_bus);
+ ClassDB::bind_method(D_METHOD("get_bus"),&AudioPlayer::get_bus);
- ClassDB::bind_method(_MD("set_autoplay","enable"),&AudioPlayer::set_autoplay);
- ClassDB::bind_method(_MD("is_autoplay_enabled"),&AudioPlayer::is_autoplay_enabled);
+ ClassDB::bind_method(D_METHOD("set_autoplay","enable"),&AudioPlayer::set_autoplay);
+ ClassDB::bind_method(D_METHOD("is_autoplay_enabled"),&AudioPlayer::is_autoplay_enabled);
- ClassDB::bind_method(_MD("set_mix_target","mix_target"),&AudioPlayer::set_mix_target);
- ClassDB::bind_method(_MD("get_mix_target"),&AudioPlayer::get_mix_target);
+ ClassDB::bind_method(D_METHOD("set_mix_target","mix_target"),&AudioPlayer::set_mix_target);
+ ClassDB::bind_method(D_METHOD("get_mix_target"),&AudioPlayer::get_mix_target);
- ClassDB::bind_method(_MD("_set_playing","enable"),&AudioPlayer::_set_playing);
- ClassDB::bind_method(_MD("_is_active"),&AudioPlayer::_is_active);
+ ClassDB::bind_method(D_METHOD("_set_playing","enable"),&AudioPlayer::_set_playing);
+ ClassDB::bind_method(D_METHOD("_is_active"),&AudioPlayer::_is_active);
- ClassDB::bind_method(_MD("_bus_layout_changed"),&AudioPlayer::_bus_layout_changed);
+ ClassDB::bind_method(D_METHOD("_bus_layout_changed"),&AudioPlayer::_bus_layout_changed);
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"stream",PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"),_SCS("set_stream"),_SCS("get_stream") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24"),_SCS("set_volume_db"),_SCS("get_volume_db") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"playing",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR),_SCS("_set_playing"),_SCS("_is_active" ));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"autoplay"),_SCS("set_autoplay"),_SCS("is_autoplay_enabled") );
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mix_target",PROPERTY_HINT_ENUM,"Stereo,Surround,Center"),_SCS("set_mix_target"),_SCS("get_mix_target"));
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"bus",PROPERTY_HINT_ENUM,""),_SCS("set_bus"),_SCS("get_bus"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"stream",PROPERTY_HINT_RESOURCE_TYPE,"AudioStream"),"set_stream","get_stream") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24"),"set_volume_db","get_volume_db") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"playing",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR),"_set_playing","_is_active" );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"autoplay"),"set_autoplay","is_autoplay_enabled") ;
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mix_target",PROPERTY_HINT_ENUM,"Stereo,Surround,Center"),"set_mix_target","get_mix_target");
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"bus",PROPERTY_HINT_ENUM,""),"set_bus","get_bus");
}
diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h
index 249e5d0381..6e34dfce19 100644
--- a/scene/audio/audio_player.h
+++ b/scene/audio/audio_player.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_player.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOPLAYER_H
#define AUDIOPLAYER_H
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 0b40983ddf..79b607e2e6 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -505,26 +505,26 @@ Ref<ButtonGroup> BaseButton::get_button_group() const {
void BaseButton::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&BaseButton::_gui_input);
- ClassDB::bind_method(_MD("_unhandled_input"),&BaseButton::_unhandled_input);
- ClassDB::bind_method(_MD("set_pressed","pressed"),&BaseButton::set_pressed);
- ClassDB::bind_method(_MD("is_pressed"),&BaseButton::is_pressed);
- ClassDB::bind_method(_MD("is_hovered"),&BaseButton::is_hovered);
- ClassDB::bind_method(_MD("set_toggle_mode","enabled"),&BaseButton::set_toggle_mode);
- ClassDB::bind_method(_MD("is_toggle_mode"),&BaseButton::is_toggle_mode);
- ClassDB::bind_method(_MD("set_disabled","disabled"),&BaseButton::set_disabled);
- ClassDB::bind_method(_MD("is_disabled"),&BaseButton::is_disabled);
- ClassDB::bind_method(_MD("set_action_mode","mode"),&BaseButton::set_action_mode);
- ClassDB::bind_method(_MD("get_action_mode"),&BaseButton::get_action_mode);
- ClassDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode);
- ClassDB::bind_method(_MD("set_enabled_focus_mode","mode"),&BaseButton::set_enabled_focus_mode);
- ClassDB::bind_method(_MD("get_enabled_focus_mode"),&BaseButton::get_enabled_focus_mode);
-
- ClassDB::bind_method(_MD("set_shortcut","shortcut"),&BaseButton::set_shortcut);
- ClassDB::bind_method(_MD("get_shortcut"),&BaseButton::get_shortcut);
-
- ClassDB::bind_method(_MD("set_button_group","button_group"),&BaseButton::set_button_group);
- ClassDB::bind_method(_MD("get_button_group"),&BaseButton::get_button_group);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&BaseButton::_gui_input);
+ ClassDB::bind_method(D_METHOD("_unhandled_input"),&BaseButton::_unhandled_input);
+ ClassDB::bind_method(D_METHOD("set_pressed","pressed"),&BaseButton::set_pressed);
+ ClassDB::bind_method(D_METHOD("is_pressed"),&BaseButton::is_pressed);
+ ClassDB::bind_method(D_METHOD("is_hovered"),&BaseButton::is_hovered);
+ ClassDB::bind_method(D_METHOD("set_toggle_mode","enabled"),&BaseButton::set_toggle_mode);
+ ClassDB::bind_method(D_METHOD("is_toggle_mode"),&BaseButton::is_toggle_mode);
+ ClassDB::bind_method(D_METHOD("set_disabled","disabled"),&BaseButton::set_disabled);
+ ClassDB::bind_method(D_METHOD("is_disabled"),&BaseButton::is_disabled);
+ ClassDB::bind_method(D_METHOD("set_action_mode","mode"),&BaseButton::set_action_mode);
+ ClassDB::bind_method(D_METHOD("get_action_mode"),&BaseButton::get_action_mode);
+ ClassDB::bind_method(D_METHOD("get_draw_mode"),&BaseButton::get_draw_mode);
+ ClassDB::bind_method(D_METHOD("set_enabled_focus_mode","mode"),&BaseButton::set_enabled_focus_mode);
+ ClassDB::bind_method(D_METHOD("get_enabled_focus_mode"),&BaseButton::get_enabled_focus_mode);
+
+ ClassDB::bind_method(D_METHOD("set_shortcut","shortcut"),&BaseButton::set_shortcut);
+ ClassDB::bind_method(D_METHOD("get_shortcut"),&BaseButton::get_shortcut);
+
+ ClassDB::bind_method(D_METHOD("set_button_group","button_group"),&BaseButton::set_button_group);
+ ClassDB::bind_method(D_METHOD("get_button_group"),&BaseButton::get_button_group);
BIND_VMETHOD(MethodInfo("_pressed"));
BIND_VMETHOD(MethodInfo("_toggled",PropertyInfo(Variant::BOOL,"pressed")));
@@ -533,13 +533,13 @@ void BaseButton::_bind_methods() {
ADD_SIGNAL( MethodInfo("button_up") );
ADD_SIGNAL( MethodInfo("button_down") );
ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed"));
- ADD_PROPERTYNO( PropertyInfo( Variant::INT, "action_mode",PROPERTY_HINT_ENUM,"Button Press,Button Release"), _SCS("set_action_mode"), _SCS("get_action_mode"));
- ADD_PROPERTY( PropertyInfo( Variant::INT,"enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_enabled_focus_mode"), _SCS("get_enabled_focus_mode") );
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shortcut",PROPERTY_HINT_RESOURCE_TYPE,"ShortCut"), _SCS("set_shortcut"), _SCS("get_shortcut"));
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "group",PROPERTY_HINT_RESOURCE_TYPE,"ButtonGroup"), _SCS("set_button_group"), _SCS("get_button_group"));
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "is_pressed"), "set_pressed", "is_pressed");
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "action_mode",PROPERTY_HINT_ENUM,"Button Press,Button Release"), "set_action_mode", "get_action_mode");
+ ADD_PROPERTY( PropertyInfo( Variant::INT,"enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), "set_enabled_focus_mode", "get_enabled_focus_mode") ;
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shortcut",PROPERTY_HINT_RESOURCE_TYPE,"ShortCut"), "set_shortcut", "get_shortcut");
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "group",PROPERTY_HINT_RESOURCE_TYPE,"ButtonGroup"), "set_button_group", "get_button_group");
BIND_CONSTANT( DRAW_NORMAL );
@@ -598,7 +598,7 @@ BaseButton* ButtonGroup::get_pressed_button() {
void ButtonGroup::_bind_methods() {
- ClassDB::bind_method(_MD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button);
+ ClassDB::bind_method(D_METHOD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button);
}
ButtonGroup::ButtonGroup() {
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index 9c5ddb3e7c..1f6e0392d8 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -302,15 +302,15 @@ BoxContainer::BoxContainer(bool p_vertical) {
void BoxContainer::_bind_methods() {
- ClassDB::bind_method(_MD("add_spacer","begin"),&BoxContainer::add_spacer);
- ClassDB::bind_method(_MD("get_alignment"),&BoxContainer::get_alignment);
- ClassDB::bind_method(_MD("set_alignment","alignment"),&BoxContainer::set_alignment);
+ ClassDB::bind_method(D_METHOD("add_spacer","begin"),&BoxContainer::add_spacer);
+ ClassDB::bind_method(D_METHOD("get_alignment"),&BoxContainer::get_alignment);
+ ClassDB::bind_method(D_METHOD("set_alignment","alignment"),&BoxContainer::set_alignment);
BIND_CONSTANT( ALIGN_BEGIN );
BIND_CONSTANT( ALIGN_CENTER );
BIND_CONSTANT( ALIGN_END );
- ADD_PROPERTY( PropertyInfo(Variant::INT,"alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), _SCS("set_alignment"),_SCS("get_alignment") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment","get_alignment") ;
}
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 2d1d437668..de2ccfb0b5 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -228,26 +228,26 @@ Button::TextAlign Button::get_text_align() const {
void Button::_bind_methods() {
- ClassDB::bind_method(_MD("set_text","text"),&Button::set_text);
- ClassDB::bind_method(_MD("get_text"),&Button::get_text);
- ClassDB::bind_method(_MD("set_button_icon","texture:Texture"),&Button::set_icon);
- ClassDB::bind_method(_MD("get_button_icon:Texture"),&Button::get_icon);
- ClassDB::bind_method(_MD("set_flat","enabled"),&Button::set_flat);
- ClassDB::bind_method(_MD("set_clip_text","enabled"),&Button::set_clip_text);
- ClassDB::bind_method(_MD("get_clip_text"),&Button::get_clip_text);
- ClassDB::bind_method(_MD("set_text_align","align"),&Button::set_text_align);
- ClassDB::bind_method(_MD("get_text_align"),&Button::get_text_align);
- ClassDB::bind_method(_MD("is_flat"),&Button::is_flat);
+ ClassDB::bind_method(D_METHOD("set_text","text"),&Button::set_text);
+ ClassDB::bind_method(D_METHOD("get_text"),&Button::get_text);
+ ClassDB::bind_method(D_METHOD("set_button_icon","texture:Texture"),&Button::set_icon);
+ ClassDB::bind_method(D_METHOD("get_button_icon:Texture"),&Button::get_icon);
+ ClassDB::bind_method(D_METHOD("set_flat","enabled"),&Button::set_flat);
+ ClassDB::bind_method(D_METHOD("set_clip_text","enabled"),&Button::set_clip_text);
+ ClassDB::bind_method(D_METHOD("get_clip_text"),&Button::get_clip_text);
+ ClassDB::bind_method(D_METHOD("set_text_align","align"),&Button::set_text_align);
+ ClassDB::bind_method(D_METHOD("get_text_align"),&Button::get_text_align);
+ ClassDB::bind_method(D_METHOD("is_flat"),&Button::is_flat);
BIND_CONSTANT( ALIGN_LEFT );
BIND_CONSTANT( ALIGN_CENTER );
BIND_CONSTANT( ALIGN_RIGHT );
- ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL ), _SCS("set_text"),_SCS("get_text") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_button_icon"),_SCS("get_button_icon") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flat" ), _SCS("set_flat"),_SCS("is_flat") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "clip_text" ), _SCS("set_clip_text"),_SCS("get_clip_text") );
- ADD_PROPERTYNO( PropertyInfo( Variant::INT, "align",PROPERTY_HINT_ENUM,"Left,Center,Right" ), _SCS("set_text_align"),_SCS("get_text_align") );
+ ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL ), "set_text","get_text") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), "set_button_icon","get_button_icon") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flat" ), "set_flat","is_flat") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "clip_text" ), "set_clip_text","get_clip_text") ;
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "align",PROPERTY_HINT_ENUM,"Left,Center,Right" ), "set_text_align","get_text_align") ;
}
diff --git a/scene/gui/button_array.cpp b/scene/gui/button_array.cpp
index 3d7c0e2825..2fd5f0df83 100644
--- a/scene/gui/button_array.cpp
+++ b/scene/gui/button_array.cpp
@@ -58,9 +58,10 @@ bool ButtonArray::_set(const StringName& p_name, const Variant& p_value) {
int idx=what.to_int();
ERR_FAIL_INDEX_V(idx,buttons.size(),false);
String f = n.get_slicec('/',2);
- if (f=="text")
+ if (f=="text") {
buttons[idx].text=p_value;
- else if (f=="tooltip")
+ buttons[idx].xl_text=XL_MESSAGE(p_value);
+ } else if (f=="tooltip")
buttons[idx].tooltip=p_value;
else if (f=="icon")
buttons[idx].icon=p_value;
@@ -146,7 +147,7 @@ Size2 ButtonArray::get_minimum_size() const {
Ref<Font> f = i==selected ? font_selected : font_normal;
Size2 ms;
- ms = f->get_string_size(buttons[i].text);
+ ms = f->get_string_size(buttons[i].xl_text);
if (buttons[i].icon.is_valid()) {
Size2 bs = buttons[i].icon->get_size();
@@ -275,7 +276,7 @@ void ButtonArray::_notification(int p_what) {
c=color_normal;
}
- Size2 ssize = f->get_string_size(buttons[i].text);
+ Size2 ssize = f->get_string_size(buttons[i].xl_text);
if (buttons[i].icon.is_valid()) {
ssize.x+=buttons[i].icon->get_width();
@@ -287,7 +288,7 @@ void ButtonArray::_notification(int p_what) {
text_ofs.x+=buttons[i].icon->get_width()+icon_sep;
}
- draw_string(f,text_ofs+r.pos,buttons[i].text,c);
+ draw_string(f,text_ofs+r.pos,buttons[i].xl_text,c);
buttons[i]._pos_cache=ofs;
buttons[i]._size_cache=s;
@@ -404,6 +405,7 @@ void ButtonArray::add_button(const String& p_text,const String& p_tooltip) {
Button button;
button.text=p_text;
+ button.xl_text=XL_MESSAGE(p_text);
button.tooltip=p_tooltip;
buttons.push_back(button);
update();
@@ -418,6 +420,7 @@ void ButtonArray::add_icon_button(const Ref<Texture>& p_icon,const String& p_tex
Button button;
button.text=p_text;
+ button.xl_text=XL_MESSAGE(p_text);
button.icon=p_icon;
button.tooltip=p_tooltip;
buttons.push_back(button);
@@ -432,6 +435,7 @@ void ButtonArray::set_button_text(int p_button, const String& p_text) {
ERR_FAIL_INDEX(p_button,buttons.size());
buttons[p_button].text=p_text;
+ buttons[p_button].xl_text=XL_MESSAGE(p_text);
update();
minimum_size_changed();
@@ -527,24 +531,24 @@ void ButtonArray::get_translatable_strings(List<String> *p_strings) const {
void ButtonArray::_bind_methods() {
- ClassDB::bind_method(_MD("add_button","text","tooltip"),&ButtonArray::add_button,DEFVAL(""));
- ClassDB::bind_method(_MD("add_icon_button","icon:Texture","text","tooltip"),&ButtonArray::add_icon_button,DEFVAL(""),DEFVAL(""));
- ClassDB::bind_method(_MD("set_button_text","button_idx","text"),&ButtonArray::set_button_text);
- ClassDB::bind_method(_MD("set_button_tooltip","button_idx","text"),&ButtonArray::set_button_tooltip);
- ClassDB::bind_method(_MD("set_button_icon","button_idx","icon:Texture"),&ButtonArray::set_button_icon);
- ClassDB::bind_method(_MD("get_button_text","button_idx"),&ButtonArray::get_button_text);
- ClassDB::bind_method(_MD("get_button_tooltip","button_idx"),&ButtonArray::get_button_tooltip);
- ClassDB::bind_method(_MD("get_button_icon:Texture","button_idx"),&ButtonArray::get_button_icon);
- ClassDB::bind_method(_MD("get_button_count"),&ButtonArray::get_button_count);
- ClassDB::bind_method(_MD("set_flat","enabled"),&ButtonArray::set_flat);
- ClassDB::bind_method(_MD("is_flat"),&ButtonArray::is_flat);
- ClassDB::bind_method(_MD("get_selected"),&ButtonArray::get_selected);
- ClassDB::bind_method(_MD("get_hovered"),&ButtonArray::get_hovered);
- ClassDB::bind_method(_MD("set_selected","button_idx"),&ButtonArray::set_selected);
- ClassDB::bind_method(_MD("erase_button","button_idx"),&ButtonArray::erase_button);
- ClassDB::bind_method(_MD("clear"),&ButtonArray::clear);
-
- ClassDB::bind_method(_MD("_gui_input"),&ButtonArray::_gui_input);
+ ClassDB::bind_method(D_METHOD("add_button","text","tooltip"),&ButtonArray::add_button,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_icon_button","icon:Texture","text","tooltip"),&ButtonArray::add_icon_button,DEFVAL(""),DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("set_button_text","button_idx","text"),&ButtonArray::set_button_text);
+ ClassDB::bind_method(D_METHOD("set_button_tooltip","button_idx","text"),&ButtonArray::set_button_tooltip);
+ ClassDB::bind_method(D_METHOD("set_button_icon","button_idx","icon:Texture"),&ButtonArray::set_button_icon);
+ ClassDB::bind_method(D_METHOD("get_button_text","button_idx"),&ButtonArray::get_button_text);
+ ClassDB::bind_method(D_METHOD("get_button_tooltip","button_idx"),&ButtonArray::get_button_tooltip);
+ ClassDB::bind_method(D_METHOD("get_button_icon:Texture","button_idx"),&ButtonArray::get_button_icon);
+ ClassDB::bind_method(D_METHOD("get_button_count"),&ButtonArray::get_button_count);
+ ClassDB::bind_method(D_METHOD("set_flat","enabled"),&ButtonArray::set_flat);
+ ClassDB::bind_method(D_METHOD("is_flat"),&ButtonArray::is_flat);
+ ClassDB::bind_method(D_METHOD("get_selected"),&ButtonArray::get_selected);
+ ClassDB::bind_method(D_METHOD("get_hovered"),&ButtonArray::get_hovered);
+ ClassDB::bind_method(D_METHOD("set_selected","button_idx"),&ButtonArray::set_selected);
+ ClassDB::bind_method(D_METHOD("erase_button","button_idx"),&ButtonArray::erase_button);
+ ClassDB::bind_method(D_METHOD("clear"),&ButtonArray::clear);
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&ButtonArray::_gui_input);
BIND_CONSTANT( ALIGN_BEGIN );
BIND_CONSTANT( ALIGN_CENTER );
@@ -552,7 +556,7 @@ void ButtonArray::_bind_methods() {
BIND_CONSTANT( ALIGN_FILL );
BIND_CONSTANT( ALIGN_EXPAND_FILL );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flat" ), _SCS("set_flat"),_SCS("is_flat") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flat" ), "set_flat","is_flat") ;
ADD_SIGNAL( MethodInfo("button_selected",PropertyInfo(Variant::INT,"button_idx")));
diff --git a/scene/gui/button_array.h b/scene/gui/button_array.h
index 37533695c9..4865ef0373 100644
--- a/scene/gui/button_array.h
+++ b/scene/gui/button_array.h
@@ -50,6 +50,7 @@ private:
struct Button {
String text;
+ String xl_text;
String tooltip;
Ref<Texture> icon;
mutable int _ms_cache;
diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp
index 01a3f633c3..21c1559b8f 100644
--- a/scene/gui/button_group.cpp
+++ b/scene/gui/button_group.cpp
@@ -151,12 +151,12 @@ int ButtonGroup::get_pressed_button_index() const {
void ButtonGroup::_bind_methods() {
- ClassDB::bind_method(_MD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button);
- ClassDB::bind_method(_MD("get_pressed_button_index"),&ButtonGroup::get_pressed_button_index);
- ClassDB::bind_method(_MD("get_focused_button:BaseButton"),&ButtonGroup::get_focused_button);
- ClassDB::bind_method(_MD("get_button_list"),&ButtonGroup::_get_button_list);
- ClassDB::bind_method(_MD("_pressed"),&ButtonGroup::_pressed);
- ClassDB::bind_method(_MD("set_pressed_button","button:BaseButton"),&ButtonGroup::_pressed);
+ ClassDB::bind_method(D_METHOD("get_pressed_button:BaseButton"),&ButtonGroup::get_pressed_button);
+ ClassDB::bind_method(D_METHOD("get_pressed_button_index"),&ButtonGroup::get_pressed_button_index);
+ ClassDB::bind_method(D_METHOD("get_focused_button:BaseButton"),&ButtonGroup::get_focused_button);
+ ClassDB::bind_method(D_METHOD("get_button_list"),&ButtonGroup::_get_button_list);
+ ClassDB::bind_method(D_METHOD("_pressed"),&ButtonGroup::_pressed);
+ ClassDB::bind_method(D_METHOD("set_pressed_button","button:BaseButton"),&ButtonGroup::_pressed);
ADD_SIGNAL( MethodInfo("button_selected",PropertyInfo(Variant::OBJECT,"button",PROPERTY_HINT_RESOURCE_TYPE,"BaseButton")));
}
diff --git a/scene/gui/center_container.cpp b/scene/gui/center_container.cpp
index 4d4abb6484..c1c04ced84 100644
--- a/scene/gui/center_container.cpp
+++ b/scene/gui/center_container.cpp
@@ -92,10 +92,10 @@ void CenterContainer::_notification(int p_what) {
void CenterContainer::_bind_methods() {
- ClassDB::bind_method(_MD("set_use_top_left","enable"),&CenterContainer::set_use_top_left);
- ClassDB::bind_method(_MD("is_using_top_left"),&CenterContainer::is_using_top_left);
+ ClassDB::bind_method(D_METHOD("set_use_top_left","enable"),&CenterContainer::set_use_top_left);
+ ClassDB::bind_method(D_METHOD("is_using_top_left"),&CenterContainer::is_using_top_left);
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"use_top_left"),_SCS("set_use_top_left"),_SCS("is_using_top_left"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"use_top_left"),"set_use_top_left","is_using_top_left");
}
CenterContainer::CenterContainer() {
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index da2fb1bc91..d9da583bf5 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -451,24 +451,24 @@ void ColorPicker::_screen_pick_pressed()
void ColorPicker::_bind_methods() {
- ClassDB::bind_method(_MD("set_pick_color","color"),&ColorPicker::set_pick_color);
- ClassDB::bind_method(_MD("get_pick_color"),&ColorPicker::get_pick_color);
- ClassDB::bind_method(_MD("set_raw_mode","mode"),&ColorPicker::set_raw_mode);
- ClassDB::bind_method(_MD("is_raw_mode"),&ColorPicker::is_raw_mode);
- ClassDB::bind_method(_MD("set_edit_alpha","show"),&ColorPicker::set_edit_alpha);
- ClassDB::bind_method(_MD("is_editing_alpha"),&ColorPicker::is_editing_alpha);
- ClassDB::bind_method(_MD("add_preset"), &ColorPicker::add_preset);
- ClassDB::bind_method(_MD("_value_changed"),&ColorPicker::_value_changed);
- ClassDB::bind_method(_MD("_html_entered"),&ColorPicker::_html_entered);
- ClassDB::bind_method(_MD("_text_type_toggled"),&ColorPicker::_text_type_toggled);
- ClassDB::bind_method(_MD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed);
- ClassDB::bind_method(_MD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed);
- ClassDB::bind_method(_MD("_sample_draw"),&ColorPicker::_sample_draw);
- ClassDB::bind_method(_MD("_hsv_draw"),&ColorPicker::_hsv_draw);
- ClassDB::bind_method(_MD("_uv_input"),&ColorPicker::_uv_input);
- ClassDB::bind_method(_MD("_w_input"),&ColorPicker::_w_input);
- ClassDB::bind_method(_MD("_preset_input"),&ColorPicker::_preset_input);
- ClassDB::bind_method(_MD("_screen_input"),&ColorPicker::_screen_input);
+ ClassDB::bind_method(D_METHOD("set_pick_color","color"),&ColorPicker::set_pick_color);
+ ClassDB::bind_method(D_METHOD("get_pick_color"),&ColorPicker::get_pick_color);
+ ClassDB::bind_method(D_METHOD("set_raw_mode","mode"),&ColorPicker::set_raw_mode);
+ ClassDB::bind_method(D_METHOD("is_raw_mode"),&ColorPicker::is_raw_mode);
+ ClassDB::bind_method(D_METHOD("set_edit_alpha","show"),&ColorPicker::set_edit_alpha);
+ ClassDB::bind_method(D_METHOD("is_editing_alpha"),&ColorPicker::is_editing_alpha);
+ ClassDB::bind_method(D_METHOD("add_preset"), &ColorPicker::add_preset);
+ ClassDB::bind_method(D_METHOD("_value_changed"),&ColorPicker::_value_changed);
+ ClassDB::bind_method(D_METHOD("_html_entered"),&ColorPicker::_html_entered);
+ ClassDB::bind_method(D_METHOD("_text_type_toggled"),&ColorPicker::_text_type_toggled);
+ ClassDB::bind_method(D_METHOD("_add_preset_pressed"), &ColorPicker::_add_preset_pressed);
+ ClassDB::bind_method(D_METHOD("_screen_pick_pressed"), &ColorPicker::_screen_pick_pressed);
+ ClassDB::bind_method(D_METHOD("_sample_draw"),&ColorPicker::_sample_draw);
+ ClassDB::bind_method(D_METHOD("_hsv_draw"),&ColorPicker::_hsv_draw);
+ ClassDB::bind_method(D_METHOD("_uv_input"),&ColorPicker::_uv_input);
+ ClassDB::bind_method(D_METHOD("_w_input"),&ColorPicker::_w_input);
+ ClassDB::bind_method(D_METHOD("_preset_input"),&ColorPicker::_preset_input);
+ ClassDB::bind_method(D_METHOD("_screen_input"),&ColorPicker::_screen_input);
ADD_SIGNAL( MethodInfo("color_changed",PropertyInfo(Variant::COLOR,"color")));
}
@@ -665,16 +665,16 @@ ColorPicker *ColorPickerButton::get_picker() {
void ColorPickerButton::_bind_methods(){
- ClassDB::bind_method(_MD("set_pick_color","color"),&ColorPickerButton::set_pick_color);
- ClassDB::bind_method(_MD("get_pick_color"),&ColorPickerButton::get_pick_color);
- ClassDB::bind_method(_MD("get_picker:ColorPicker"),&ColorPickerButton::get_picker);
- ClassDB::bind_method(_MD("set_edit_alpha","show"),&ColorPickerButton::set_edit_alpha);
- ClassDB::bind_method(_MD("is_editing_alpha"),&ColorPickerButton::is_editing_alpha);
- ClassDB::bind_method(_MD("_color_changed"),&ColorPickerButton::_color_changed);
+ ClassDB::bind_method(D_METHOD("set_pick_color","color"),&ColorPickerButton::set_pick_color);
+ ClassDB::bind_method(D_METHOD("get_pick_color"),&ColorPickerButton::get_pick_color);
+ ClassDB::bind_method(D_METHOD("get_picker:ColorPicker"),&ColorPickerButton::get_picker);
+ ClassDB::bind_method(D_METHOD("set_edit_alpha","show"),&ColorPickerButton::set_edit_alpha);
+ ClassDB::bind_method(D_METHOD("is_editing_alpha"),&ColorPickerButton::is_editing_alpha);
+ ClassDB::bind_method(D_METHOD("_color_changed"),&ColorPickerButton::_color_changed);
ADD_SIGNAL( MethodInfo("color_changed",PropertyInfo(Variant::COLOR,"color")));
- ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_pick_color"),_SCS("get_pick_color") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"edit_alpha"),_SCS("set_edit_alpha"),_SCS("is_editing_alpha") );
+ ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),"set_pick_color","get_pick_color") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"edit_alpha"),"set_edit_alpha","is_editing_alpha") ;
}
diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp
index 5d5d6c31a2..81bc5ca9bb 100644
--- a/scene/gui/color_ramp_edit.cpp
+++ b/scene/gui/color_ramp_edit.cpp
@@ -446,7 +446,7 @@ Vector<ColorRamp::Point>& ColorRampEdit::get_points() {
}
void ColorRampEdit::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&ColorRampEdit::_gui_input);
- ClassDB::bind_method(_MD("_color_changed"),&ColorRampEdit::_color_changed);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&ColorRampEdit::_gui_input);
+ ClassDB::bind_method(D_METHOD("_color_changed"),&ColorRampEdit::_color_changed);
ADD_SIGNAL(MethodInfo("ramp_changed"));
}
diff --git a/scene/gui/color_rect.cpp b/scene/gui/color_rect.cpp
index 99797aa9c1..d72dffcae3 100644
--- a/scene/gui/color_rect.cpp
+++ b/scene/gui/color_rect.cpp
@@ -49,10 +49,10 @@ void ColorRect::_notification(int p_what) {
void ColorRect::_bind_methods() {
- ClassDB::bind_method(_MD("set_frame_color","color"),&ColorRect::set_frame_color);
- ClassDB::bind_method(_MD("get_frame_color"),&ColorRect::get_frame_color);
+ ClassDB::bind_method(D_METHOD("set_frame_color","color"),&ColorRect::set_frame_color);
+ ClassDB::bind_method(D_METHOD("get_frame_color"),&ColorRect::get_frame_color);
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),_SCS("set_frame_color"),_SCS("get_frame_color") );
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),"set_frame_color","get_frame_color") ;
}
ColorRect::ColorRect() {
diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp
index de5f35933c..655c6e1bbf 100644
--- a/scene/gui/container.cpp
+++ b/scene/gui/container.cpp
@@ -156,11 +156,11 @@ void Container::_notification(int p_what) {
void Container::_bind_methods() {
- ClassDB::bind_method(_MD("_sort_children"),&Container::_sort_children);
- ClassDB::bind_method(_MD("_child_minsize_changed"),&Container::_child_minsize_changed);
+ ClassDB::bind_method(D_METHOD("_sort_children"),&Container::_sort_children);
+ ClassDB::bind_method(D_METHOD("_child_minsize_changed"),&Container::_child_minsize_changed);
- ClassDB::bind_method(_MD("queue_sort"),&Container::queue_sort);
- ClassDB::bind_method(_MD("fit_child_in_rect","child:Control","rect"),&Container::fit_child_in_rect);
+ ClassDB::bind_method(D_METHOD("queue_sort"),&Container::queue_sort);
+ ClassDB::bind_method(D_METHOD("fit_child_in_rect","child:Control","rect"),&Container::fit_child_in_rect);
BIND_CONSTANT( NOTIFICATION_SORT_CHILDREN );
ADD_SIGNAL(MethodInfo("sort_children"));
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index e012874f5b..496b1e03cf 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -30,7 +30,7 @@
#include "servers/visual_server.h"
#include "scene/main/viewport.h"
#include "scene/main/canvas_layer.h"
-#include "globals.h"
+#include "global_config.h"
#include "print_string.h"
#include "os/keyboard.h"
@@ -40,7 +40,7 @@
#include "scene/gui/panel.h"
#include "scene/gui/label.h"
#ifdef TOOLS_ENABLED
-#include "tools/editor/editor_settings.h"
+#include "editor/editor_settings.h"
#endif
#include <stdio.h>
@@ -2421,8 +2421,6 @@ void Control::get_argument_options(const StringName& p_function,int p_idx,List<S
Theme::get_default()->get_font_list(get_class(),&sn);
} else if (pf=="add_constant_override" || pf=="has_constant" || pf=="has_constant_override" || pf=="get_constant") {
Theme::get_default()->get_constant_list(get_class(),&sn);
- } else if (pf=="add_color_override" || pf=="has_color" || pf=="has_color_override" || pf=="get_color") {
- Theme::get_default()->get_color_list(get_class(),&sn);
}
sn.sort_custom<StringName::AlphCompare>();
@@ -2448,125 +2446,125 @@ bool Control::is_clipping_contents() {
void Control::_bind_methods() {
- //ClassDB::bind_method(_MD("_window_resize_event"),&Control::_window_resize_event);
- ClassDB::bind_method(_MD("_size_changed"),&Control::_size_changed);
- ClassDB::bind_method(_MD("_update_minimum_size"),&Control::_update_minimum_size);
-
- ClassDB::bind_method(_MD("accept_event"),&Control::accept_event);
- ClassDB::bind_method(_MD("get_minimum_size"),&Control::get_minimum_size);
- ClassDB::bind_method(_MD("get_combined_minimum_size"),&Control::get_combined_minimum_size);
- ClassDB::bind_method(_MD("set_anchor","margin","anchor_mode","keep_margin"),&Control::set_anchor,DEFVAL(false));
- ClassDB::bind_method(_MD("_set_anchor","margin","anchor_mode"),&Control::_set_anchor);
- ClassDB::bind_method(_MD("get_anchor","margin"),&Control::get_anchor);
- ClassDB::bind_method(_MD("set_margin","margin","offset"),&Control::set_margin);
- ClassDB::bind_method(_MD("set_anchor_and_margin","margin","anchor_mode","offset"),&Control::set_anchor_and_margin);
- ClassDB::bind_method(_MD("set_begin","pos"),&Control::set_begin);
- ClassDB::bind_method(_MD("set_end","pos"),&Control::set_end);
- ClassDB::bind_method(_MD("set_pos","pos"),&Control::set_pos);
- ClassDB::bind_method(_MD("set_size","size"),&Control::set_size);
- ClassDB::bind_method(_MD("set_custom_minimum_size","size"),&Control::set_custom_minimum_size);
- ClassDB::bind_method(_MD("set_global_pos","pos"),&Control::set_global_pos);
- ClassDB::bind_method(_MD("set_rotation","radians"),&Control::set_rotation);
- ClassDB::bind_method(_MD("set_rotation_deg","degrees"),&Control::set_rotation_deg);
+ //ClassDB::bind_method(D_METHOD("_window_resize_event"),&Control::_window_resize_event);
+ ClassDB::bind_method(D_METHOD("_size_changed"),&Control::_size_changed);
+ ClassDB::bind_method(D_METHOD("_update_minimum_size"),&Control::_update_minimum_size);
+
+ ClassDB::bind_method(D_METHOD("accept_event"),&Control::accept_event);
+ ClassDB::bind_method(D_METHOD("get_minimum_size"),&Control::get_minimum_size);
+ ClassDB::bind_method(D_METHOD("get_combined_minimum_size"),&Control::get_combined_minimum_size);
+ ClassDB::bind_method(D_METHOD("set_anchor","margin","anchor_mode","keep_margin"),&Control::set_anchor,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("_set_anchor","margin","anchor_mode"),&Control::_set_anchor);
+ ClassDB::bind_method(D_METHOD("get_anchor","margin"),&Control::get_anchor);
+ ClassDB::bind_method(D_METHOD("set_margin","margin","offset"),&Control::set_margin);
+ ClassDB::bind_method(D_METHOD("set_anchor_and_margin","margin","anchor_mode","offset"),&Control::set_anchor_and_margin);
+ ClassDB::bind_method(D_METHOD("set_begin","pos"),&Control::set_begin);
+ ClassDB::bind_method(D_METHOD("set_end","pos"),&Control::set_end);
+ ClassDB::bind_method(D_METHOD("set_pos","pos"),&Control::set_pos);
+ ClassDB::bind_method(D_METHOD("set_size","size"),&Control::set_size);
+ ClassDB::bind_method(D_METHOD("set_custom_minimum_size","size"),&Control::set_custom_minimum_size);
+ ClassDB::bind_method(D_METHOD("set_global_pos","pos"),&Control::set_global_pos);
+ ClassDB::bind_method(D_METHOD("set_rotation","radians"),&Control::set_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_deg","degrees"),&Control::set_rotation_deg);
// TODO: Obsolete this method (old name) properly (GH-4397)
- ClassDB::bind_method(_MD("_set_rotation_deg","degrees"),&Control::_set_rotation_deg);
- ClassDB::bind_method(_MD("set_scale","scale"),&Control::set_scale);
- ClassDB::bind_method(_MD("get_margin","margin"),&Control::get_margin);
- ClassDB::bind_method(_MD("get_begin"),&Control::get_begin);
- ClassDB::bind_method(_MD("get_end"),&Control::get_end);
- ClassDB::bind_method(_MD("get_pos"),&Control::get_pos);
- ClassDB::bind_method(_MD("get_size"),&Control::get_size);
- ClassDB::bind_method(_MD("get_rotation"),&Control::get_rotation);
- ClassDB::bind_method(_MD("get_rotation_deg"),&Control::get_rotation_deg);
+ ClassDB::bind_method(D_METHOD("_set_rotation_deg","degrees"),&Control::_set_rotation_deg);
+ ClassDB::bind_method(D_METHOD("set_scale","scale"),&Control::set_scale);
+ ClassDB::bind_method(D_METHOD("get_margin","margin"),&Control::get_margin);
+ ClassDB::bind_method(D_METHOD("get_begin"),&Control::get_begin);
+ ClassDB::bind_method(D_METHOD("get_end"),&Control::get_end);
+ ClassDB::bind_method(D_METHOD("get_pos"),&Control::get_pos);
+ ClassDB::bind_method(D_METHOD("get_size"),&Control::get_size);
+ ClassDB::bind_method(D_METHOD("get_rotation"),&Control::get_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation_deg"),&Control::get_rotation_deg);
// TODO: Obsolete this method (old name) properly (GH-4397)
- ClassDB::bind_method(_MD("_get_rotation_deg"),&Control::_get_rotation_deg);
- ClassDB::bind_method(_MD("get_scale"),&Control::get_scale);
- ClassDB::bind_method(_MD("get_custom_minimum_size"),&Control::get_custom_minimum_size);
- ClassDB::bind_method(_MD("get_parent_area_size"),&Control::get_size);
- ClassDB::bind_method(_MD("get_global_pos"),&Control::get_global_pos);
- ClassDB::bind_method(_MD("get_rect"),&Control::get_rect);
- ClassDB::bind_method(_MD("get_global_rect"),&Control::get_global_rect);
- ClassDB::bind_method(_MD("set_area_as_parent_rect","margin"),&Control::set_area_as_parent_rect,DEFVAL(0));
- ClassDB::bind_method(_MD("show_modal","exclusive"),&Control::show_modal,DEFVAL(false));
- ClassDB::bind_method(_MD("set_focus_mode","mode"),&Control::set_focus_mode);
- ClassDB::bind_method(_MD("get_focus_mode"),&Control::get_focus_mode);
- ClassDB::bind_method(_MD("has_focus"),&Control::has_focus);
- ClassDB::bind_method(_MD("grab_focus"),&Control::grab_focus);
- ClassDB::bind_method(_MD("release_focus"),&Control::release_focus);
- ClassDB::bind_method(_MD("get_focus_owner:Control"),&Control::get_focus_owner);
+ ClassDB::bind_method(D_METHOD("_get_rotation_deg"),&Control::_get_rotation_deg);
+ ClassDB::bind_method(D_METHOD("get_scale"),&Control::get_scale);
+ ClassDB::bind_method(D_METHOD("get_custom_minimum_size"),&Control::get_custom_minimum_size);
+ ClassDB::bind_method(D_METHOD("get_parent_area_size"),&Control::get_size);
+ ClassDB::bind_method(D_METHOD("get_global_pos"),&Control::get_global_pos);
+ ClassDB::bind_method(D_METHOD("get_rect"),&Control::get_rect);
+ ClassDB::bind_method(D_METHOD("get_global_rect"),&Control::get_global_rect);
+ ClassDB::bind_method(D_METHOD("set_area_as_parent_rect","margin"),&Control::set_area_as_parent_rect,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("show_modal","exclusive"),&Control::show_modal,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_focus_mode","mode"),&Control::set_focus_mode);
+ ClassDB::bind_method(D_METHOD("get_focus_mode"),&Control::get_focus_mode);
+ ClassDB::bind_method(D_METHOD("has_focus"),&Control::has_focus);
+ ClassDB::bind_method(D_METHOD("grab_focus"),&Control::grab_focus);
+ ClassDB::bind_method(D_METHOD("release_focus"),&Control::release_focus);
+ ClassDB::bind_method(D_METHOD("get_focus_owner:Control"),&Control::get_focus_owner);
- ClassDB::bind_method(_MD("set_h_size_flags","flags"),&Control::set_h_size_flags);
- ClassDB::bind_method(_MD("get_h_size_flags"),&Control::get_h_size_flags);
+ ClassDB::bind_method(D_METHOD("set_h_size_flags","flags"),&Control::set_h_size_flags);
+ ClassDB::bind_method(D_METHOD("get_h_size_flags"),&Control::get_h_size_flags);
- ClassDB::bind_method(_MD("set_stretch_ratio","ratio"),&Control::set_stretch_ratio);
- ClassDB::bind_method(_MD("get_stretch_ratio"),&Control::get_stretch_ratio);
+ ClassDB::bind_method(D_METHOD("set_stretch_ratio","ratio"),&Control::set_stretch_ratio);
+ ClassDB::bind_method(D_METHOD("get_stretch_ratio"),&Control::get_stretch_ratio);
- ClassDB::bind_method(_MD("set_v_size_flags","flags"),&Control::set_v_size_flags);
- ClassDB::bind_method(_MD("get_v_size_flags"),&Control::get_v_size_flags);
+ ClassDB::bind_method(D_METHOD("set_v_size_flags","flags"),&Control::set_v_size_flags);
+ ClassDB::bind_method(D_METHOD("get_v_size_flags"),&Control::get_v_size_flags);
- ClassDB::bind_method(_MD("set_theme","theme:Theme"),&Control::set_theme);
- ClassDB::bind_method(_MD("get_theme:Theme"),&Control::get_theme);
+ ClassDB::bind_method(D_METHOD("set_theme","theme:Theme"),&Control::set_theme);
+ ClassDB::bind_method(D_METHOD("get_theme:Theme"),&Control::get_theme);
- ClassDB::bind_method(_MD("add_icon_override","name","texture:Texture"),&Control::add_icon_override);
- ClassDB::bind_method(_MD("add_shader_override","name","shader:Shader"),&Control::add_shader_override);
- ClassDB::bind_method(_MD("add_style_override","name","stylebox:StyleBox"),&Control::add_style_override);
- ClassDB::bind_method(_MD("add_font_override","name","font:Font"),&Control::add_font_override);
- ClassDB::bind_method(_MD("add_color_override","name","color"),&Control::add_color_override);
- ClassDB::bind_method(_MD("add_constant_override","name","constant"),&Control::add_constant_override);
+ ClassDB::bind_method(D_METHOD("add_icon_override","name","texture:Texture"),&Control::add_icon_override);
+ ClassDB::bind_method(D_METHOD("add_shader_override","name","shader:Shader"),&Control::add_shader_override);
+ ClassDB::bind_method(D_METHOD("add_style_override","name","stylebox:StyleBox"),&Control::add_style_override);
+ ClassDB::bind_method(D_METHOD("add_font_override","name","font:Font"),&Control::add_font_override);
+ ClassDB::bind_method(D_METHOD("add_color_override","name","color"),&Control::add_color_override);
+ ClassDB::bind_method(D_METHOD("add_constant_override","name","constant"),&Control::add_constant_override);
- ClassDB::bind_method(_MD("get_icon:Texture","name","type"),&Control::get_icon,DEFVAL(""));
- ClassDB::bind_method(_MD("get_stylebox:StyleBox","name","type"),&Control::get_stylebox,DEFVAL(""));
- ClassDB::bind_method(_MD("get_font:Font","name","type"),&Control::get_font,DEFVAL(""));
- ClassDB::bind_method(_MD("get_color","name","type"),&Control::get_color,DEFVAL(""));
- ClassDB::bind_method(_MD("get_constant","name","type"),&Control::get_constant,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_icon:Texture","name","type"),&Control::get_icon,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_stylebox:StyleBox","name","type"),&Control::get_stylebox,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_font:Font","name","type"),&Control::get_font,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_color","name","type"),&Control::get_color,DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_constant","name","type"),&Control::get_constant,DEFVAL(""));
- ClassDB::bind_method(_MD("has_icon_override", "name"), &Control::has_icon_override);
- ClassDB::bind_method(_MD("has_stylebox_override", "name"), &Control::has_stylebox_override);
- ClassDB::bind_method(_MD("has_font_override", "name"), &Control::has_font_override);
- ClassDB::bind_method(_MD("has_color_override", "name"), &Control::has_color_override);
- ClassDB::bind_method(_MD("has_constant_override", "name"), &Control::has_constant_override);
+ ClassDB::bind_method(D_METHOD("has_icon_override", "name"), &Control::has_icon_override);
+ ClassDB::bind_method(D_METHOD("has_stylebox_override", "name"), &Control::has_stylebox_override);
+ ClassDB::bind_method(D_METHOD("has_font_override", "name"), &Control::has_font_override);
+ ClassDB::bind_method(D_METHOD("has_color_override", "name"), &Control::has_color_override);
+ ClassDB::bind_method(D_METHOD("has_constant_override", "name"), &Control::has_constant_override);
- ClassDB::bind_method(_MD("has_icon", "name", "type"), &Control::has_icon, DEFVAL(""));
- ClassDB::bind_method(_MD("has_stylebox", "name", "type"), &Control::has_stylebox, DEFVAL(""));
- ClassDB::bind_method(_MD("has_font", "name", "type"), &Control::has_font, DEFVAL(""));
- ClassDB::bind_method(_MD("has_color", "name", "type"), &Control::has_color, DEFVAL(""));
- ClassDB::bind_method(_MD("has_constant", "name", "type"), &Control::has_constant, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_icon", "name", "type"), &Control::has_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_stylebox", "name", "type"), &Control::has_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_font", "name", "type"), &Control::has_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_color", "name", "type"), &Control::has_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_constant", "name", "type"), &Control::has_constant, DEFVAL(""));
- ClassDB::bind_method(_MD("get_parent_control:Control"),&Control::get_parent_control);
+ ClassDB::bind_method(D_METHOD("get_parent_control:Control"),&Control::get_parent_control);
- ClassDB::bind_method(_MD("set_tooltip","tooltip"),&Control::set_tooltip);
- ClassDB::bind_method(_MD("get_tooltip","atpos"),&Control::get_tooltip,DEFVAL(Point2()));
- ClassDB::bind_method(_MD("_get_tooltip"),&Control::_get_tooltip);
+ ClassDB::bind_method(D_METHOD("set_tooltip","tooltip"),&Control::set_tooltip);
+ ClassDB::bind_method(D_METHOD("get_tooltip","atpos"),&Control::get_tooltip,DEFVAL(Point2()));
+ ClassDB::bind_method(D_METHOD("_get_tooltip"),&Control::_get_tooltip);
- ClassDB::bind_method(_MD("set_default_cursor_shape","shape"),&Control::set_default_cursor_shape);
- ClassDB::bind_method(_MD("get_default_cursor_shape"),&Control::get_default_cursor_shape);
- ClassDB::bind_method(_MD("get_cursor_shape","pos"),&Control::get_cursor_shape,DEFVAL(Point2()));
+ ClassDB::bind_method(D_METHOD("set_default_cursor_shape","shape"),&Control::set_default_cursor_shape);
+ ClassDB::bind_method(D_METHOD("get_default_cursor_shape"),&Control::get_default_cursor_shape);
+ ClassDB::bind_method(D_METHOD("get_cursor_shape","pos"),&Control::get_cursor_shape,DEFVAL(Point2()));
- ClassDB::bind_method(_MD("set_focus_neighbour","margin","neighbour"),&Control::set_focus_neighbour);
- ClassDB::bind_method(_MD("get_focus_neighbour","margin"),&Control::get_focus_neighbour);
+ ClassDB::bind_method(D_METHOD("set_focus_neighbour","margin","neighbour"),&Control::set_focus_neighbour);
+ ClassDB::bind_method(D_METHOD("get_focus_neighbour","margin"),&Control::get_focus_neighbour);
- ClassDB::bind_method(_MD("force_drag","data","preview"),&Control::force_drag);
+ ClassDB::bind_method(D_METHOD("force_drag","data","preview"),&Control::force_drag);
- ClassDB::bind_method(_MD("set_mouse_filter","filter"),&Control::set_mouse_filter);
- ClassDB::bind_method(_MD("get_mouse_filter"),&Control::get_mouse_filter);
+ ClassDB::bind_method(D_METHOD("set_mouse_filter","filter"),&Control::set_mouse_filter);
+ ClassDB::bind_method(D_METHOD("get_mouse_filter"),&Control::get_mouse_filter);
- ClassDB::bind_method(_MD("set_clip_contents","enable"),&Control::set_clip_contents);
- ClassDB::bind_method(_MD("is_clipping_contents"),&Control::is_clipping_contents);
+ ClassDB::bind_method(D_METHOD("set_clip_contents","enable"),&Control::set_clip_contents);
+ ClassDB::bind_method(D_METHOD("is_clipping_contents"),&Control::is_clipping_contents);
- ClassDB::bind_method(_MD("grab_click_focus"),&Control::grab_click_focus);
+ ClassDB::bind_method(D_METHOD("grab_click_focus"),&Control::grab_click_focus);
- ClassDB::bind_method(_MD("set_drag_forwarding","target:Control"),&Control::set_drag_forwarding);
- ClassDB::bind_method(_MD("set_drag_preview","control:Control"),&Control::set_drag_preview);
+ ClassDB::bind_method(D_METHOD("set_drag_forwarding","target:Control"),&Control::set_drag_forwarding);
+ ClassDB::bind_method(D_METHOD("set_drag_preview","control:Control"),&Control::set_drag_preview);
- ClassDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse);
+ ClassDB::bind_method(D_METHOD("warp_mouse","to_pos"),&Control::warp_mouse);
- ClassDB::bind_method(_MD("minimum_size_changed"), &Control::minimum_size_changed);
+ ClassDB::bind_method(D_METHOD("minimum_size_changed"), &Control::minimum_size_changed);
- ClassDB::bind_method(_MD("_theme_changed"), &Control::_theme_changed);
+ ClassDB::bind_method(D_METHOD("_theme_changed"), &Control::_theme_changed);
- ClassDB::bind_method(_MD("_font_changed"), &Control::_font_changed);
+ ClassDB::bind_method(D_METHOD("_font_changed"), &Control::_font_changed);
BIND_VMETHOD(MethodInfo("_gui_input",PropertyInfo(Variant::INPUT_EVENT,"event")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size"));
@@ -2575,44 +2573,44 @@ void Control::_bind_methods() {
BIND_VMETHOD(MethodInfo("drop_data",PropertyInfo(Variant::VECTOR2,"pos"),PropertyInfo(Variant::NIL,"data")));
ADD_GROUP("Anchor","anchor_");
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_left", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_LEFT );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_top", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_TOP );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_right", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_RIGHT );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_bottom", PROPERTY_HINT_ENUM, "Begin,End,Center"), _SCS("_set_anchor"),_SCS("get_anchor"), MARGIN_BOTTOM );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_left", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor","get_anchor", MARGIN_LEFT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_top", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor","get_anchor", MARGIN_TOP );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_right", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor","get_anchor", MARGIN_RIGHT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"anchor_bottom", PROPERTY_HINT_ENUM, "Begin,End,Center"), "_set_anchor","get_anchor", MARGIN_BOTTOM );
ADD_GROUP("Margin","margin_");
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_left", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_LEFT );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_top", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_TOP );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_RIGHT );
- ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), _SCS("set_margin"),_SCS("get_margin"),MARGIN_BOTTOM );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_left", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin","get_margin",MARGIN_LEFT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_top", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin","get_margin",MARGIN_TOP );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin","get_margin",MARGIN_RIGHT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::INT,"margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin","get_margin",MARGIN_BOTTOM );
ADD_GROUP("Rect","rect_");
- 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_PROPERTYNO( PropertyInfo(Variant::BOOL,"rect_clip_content"), _SCS("set_clip_contents"),_SCS("is_clipping_contents") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect_pos", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), "set_pos","get_pos") ;
+ ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect_size", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), "set_size","get_size") ;
+ ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect_min_size"), "set_custom_minimum_size","get_custom_minimum_size") ;
+ ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"rect_rotation",PROPERTY_HINT_RANGE,"-1080,1080,0.01"), "set_rotation_deg","get_rotation_deg") ;
+ ADD_PROPERTYNO( PropertyInfo(Variant::VECTOR2,"rect_scale"), "set_scale","get_scale") ;
+ ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"rect_clip_content"), "set_clip_contents","is_clipping_contents") ;
ADD_GROUP("Hint","hint_");
- ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), _SCS("set_tooltip"),_SCS("_get_tooltip") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip","_get_tooltip") ;
ADD_GROUP("Focus","focus_");
- 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 );
- ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour_right" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_RIGHT );
- ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour_bottom" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_BOTTOM );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour_left" ), "set_focus_neighbour","get_focus_neighbour",MARGIN_LEFT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour_top" ), "set_focus_neighbour","get_focus_neighbour",MARGIN_TOP );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour_right" ), "set_focus_neighbour","get_focus_neighbour",MARGIN_RIGHT );
+ ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour_bottom" ), "set_focus_neighbour","get_focus_neighbour",MARGIN_BOTTOM );
ADD_GROUP("Mouse","mouse_");
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mouse_filter",PROPERTY_HINT_ENUM,"Stop,Pass,Ignore"), _SCS("set_mouse_filter"),_SCS("get_mouse_filter") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mouse_filter",PROPERTY_HINT_ENUM,"Stop,Pass,Ignore"), "set_mouse_filter","get_mouse_filter") ;
ADD_GROUP("Size Flags","size_flags_");
- ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand"), _SCS("set_h_size_flags"),_SCS("get_h_size_flags") );
- ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand"), _SCS("set_v_size_flags"),_SCS("get_v_size_flags") );
- ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), _SCS("set_stretch_ratio"),_SCS("get_stretch_ratio") );
+ ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_h_size_flags","get_h_size_flags") ;
+ ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_v_size_flags","get_v_size_flags") ;
+ ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), "set_stretch_ratio","get_stretch_ratio") ;
ADD_GROUP("Theme","");
- ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), _SCS("set_theme"),_SCS("get_theme") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme","get_theme") ;
ADD_GROUP("","");
BIND_CONSTANT( ANCHOR_BEGIN );
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index cc6fe7cae8..6d06f8c59c 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -33,76 +33,173 @@
void WindowDialog::_post_popup() {
- dragging=false; //just in case
+ drag_type = DRAG_NONE; // just in case
+}
+
+void WindowDialog::_fix_size() {
+
+ // Perhaps this should be called when the viewport resizes aswell or windows go out of bounds...
+
+ // Ensure the whole window is visible.
+ Point2i pos = get_global_pos();
+ Size2i size = get_size();
+ Size2i viewport_size = get_viewport_rect().size;
+
+ // Windows require additional padding to keep the window chrome visible.
+ Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog");
+ float top = panel->get_margin(MARGIN_TOP);
+ float left = panel->get_margin(MARGIN_LEFT);
+ float bottom = panel->get_margin(MARGIN_BOTTOM);
+ float right = panel->get_margin(MARGIN_RIGHT);
+
+ pos.x = MAX(left, MIN(pos.x, viewport_size.x - size.x - right));
+ pos.y = MAX(top, MIN(pos.y, viewport_size.y - size.y - bottom));
+ set_global_pos(pos);
+
+ // Also resize the window to fit if a resize should be possible at all.
+ if (resizable) {
+ size.x = MIN(size.x, viewport_size.x - left - right);
+ size.y = MIN(size.y, viewport_size.y - top - bottom);
+ set_size(size);
+ }
}
bool WindowDialog::has_point(const Point2& p_point) const {
+ Rect2 r(Point2(), get_size());
- int extra = get_constant("titlebar_height","WindowDialog");
- Rect2 r( Point2(), get_size() );
- r.pos.y-=extra;
- r.size.y+=extra;
- return r.has_point(p_point);
+ // Enlarge upwards for title bar.
+ int titlebar_height = get_constant("titlebar_height", "WindowDialog");
+ r.pos.y -= titlebar_height;
+ r.size.y += titlebar_height;
+ // Inflate by the resizable border thickness.
+ if (resizable) {
+ int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
+ r.pos.x -= scaleborder_size;
+ r.size.width += scaleborder_size * 2;
+ r.pos.y -= scaleborder_size;
+ r.size.height += scaleborder_size * 2;
+ }
+
+ return r.has_point(p_point);
}
void WindowDialog::_gui_input(const InputEvent& p_event) {
- if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT) {
-
- if (p_event.mouse_button.pressed && p_event.mouse_button.y < 0)
- dragging=true;
- else if (dragging && !p_event.mouse_button.pressed)
- dragging=false;
+ if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_LEFT) {
+
+ if (p_event.mouse_button.pressed) {
+ // Begin a possible dragging operation.
+ drag_type = _drag_hit_test(Point2(p_event.mouse_button.x, p_event.mouse_button.y));
+ if (drag_type != DRAG_NONE)
+ drag_offset = get_global_mouse_pos() - get_pos();
+ drag_offset_far = get_pos() + get_size() - get_global_mouse_pos();
+ } else if (drag_type != DRAG_NONE && !p_event.mouse_button.pressed) {
+ // End a dragging operation.
+ drag_type = DRAG_NONE;
+ }
}
-
- if (p_event.type == InputEvent::MOUSE_MOTION && dragging) {
-
- Point2 rel( p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y );
- Point2 pos = get_pos();
-
- pos+=rel;
-
- if (pos.y<0)
- pos.y=0;
-
- set_pos(pos);
+ if (p_event.type == InputEvent::MOUSE_MOTION) {
+
+ if (drag_type == DRAG_NONE) {
+ // Update the cursor while moving along the borders.
+ CursorShape cursor = CURSOR_ARROW;
+ if (resizable) {
+ int preview_drag_type = _drag_hit_test(Point2(p_event.mouse_button.x, p_event.mouse_button.y));
+ switch (preview_drag_type) {
+ case DRAG_RESIZE_TOP:
+ case DRAG_RESIZE_BOTTOM:
+ cursor = CURSOR_VSIZE;
+ break;
+ case DRAG_RESIZE_LEFT:
+ case DRAG_RESIZE_RIGHT:
+ cursor = CURSOR_HSIZE;
+ break;
+ case DRAG_RESIZE_TOP + DRAG_RESIZE_LEFT:
+ case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_RIGHT:
+ cursor = CURSOR_FDIAGSIZE;
+ break;
+ case DRAG_RESIZE_TOP + DRAG_RESIZE_RIGHT:
+ case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_LEFT:
+ cursor = CURSOR_BDIAGSIZE;
+ break;
+ }
+ }
+ if (get_cursor_shape() != cursor)
+ set_default_cursor_shape(cursor);
+ } else {
+ // Update while in a dragging operation.
+ Point2 global_pos = get_global_mouse_pos();
+ global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible.
+
+ Rect2 rect = get_rect();
+ Size2 min_size = get_minimum_size();
+
+ if (drag_type == DRAG_MOVE) {
+ rect.pos = global_pos - drag_offset;
+ } else {
+ if (drag_type & DRAG_RESIZE_TOP) {
+ int bottom = rect.pos.y + rect.size.height;
+ int max_y = bottom - min_size.height;
+ rect.pos.y = MIN(global_pos.y - drag_offset.y, max_y);
+ rect.size.height = bottom - rect.pos.y;
+ } else if (drag_type & DRAG_RESIZE_BOTTOM) {
+ rect.size.height = global_pos.y - rect.pos.y + drag_offset_far.y;
+ }
+ if (drag_type & DRAG_RESIZE_LEFT) {
+ int right = rect.pos.x + rect.size.width;
+ int max_x = right - min_size.width;
+ rect.pos.x = MIN(global_pos.x - drag_offset.x, max_x);
+ rect.size.width = right - rect.pos.x;
+ } else if (drag_type & DRAG_RESIZE_RIGHT) {
+ rect.size.width = global_pos.x - rect.pos.x + drag_offset_far.x;
+ }
+ }
+
+ set_size(rect.size);
+ set_pos(rect.pos);
+ }
}
}
void WindowDialog::_notification(int p_what) {
- switch(p_what) {
-
+ switch (p_what) {
case NOTIFICATION_DRAW: {
- RID ci = get_canvas_item();
- Size2 s = get_size();
- Ref<StyleBox> st = get_stylebox("panel","WindowDialog");
- st->draw(ci,Rect2(Point2(),s));
- int th = get_constant("title_height","WindowDialog");
- Color tc = get_color("title_color","WindowDialog");
- Ref<Font> font = get_font("title_font","WindowDialog");
- int ofs = (s.width-font->get_string_size(title).width)/2;
- //int ofs = st->get_margin(MARGIN_LEFT);
- draw_string(font,Point2(ofs,-th+font->get_ascent()),title,tc,s.width - st->get_minimum_size().width);
+ RID canvas = get_canvas_item();
+ Size2 size = get_size();
+
+ Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog");
+ panel->draw(canvas, Rect2(Point2(), size));
+ int title_height = get_constant("title_height", "WindowDialog");
+ Color title_color = get_color("title_color", "WindowDialog");
+ Ref<Font> font = get_font("title_font", "WindowDialog");
+ int ofs = (size.width - font->get_string_size(title).width) / 2;
+ draw_string(font, Point2(ofs, -title_height + font->get_ascent()), title, title_color, size.width - panel->get_minimum_size().width);
} break;
+
case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_ENTER_TREE: {
+ close_button->set_normal_texture(get_icon("close", "WindowDialog"));
+ close_button->set_pressed_texture(get_icon("close", "WindowDialog"));
+ close_button->set_hover_texture(get_icon("close_hilite", "WindowDialog"));
+ close_button->set_anchor(MARGIN_LEFT, ANCHOR_END);
+ close_button->set_begin(Point2(get_constant("close_h_ofs", "WindowDialog"), -get_constant("close_v_ofs", "WindowDialog")));
+ } break;
- close_button->set_normal_texture( get_icon("close","WindowDialog"));
- close_button->set_pressed_texture( get_icon("close","WindowDialog"));
- close_button->set_hover_texture( get_icon("close_hilite","WindowDialog"));
- close_button->set_anchor(MARGIN_LEFT,ANCHOR_END);
- close_button->set_begin( Point2( get_constant("close_h_ofs","WindowDialog"), -get_constant("close_v_ofs","WindowDialog") ));
-
+ case NOTIFICATION_MOUSE_EXIT: {
+ // Reset the mouse cursor when leaving the resizable window border.
+ if (resizable && !drag_type) {
+ if (get_default_cursor_shape() != CURSOR_ARROW)
+ set_default_cursor_shape(CURSOR_ARROW);
+ }
} break;
}
-
}
void WindowDialog::_closed() {
@@ -111,11 +208,48 @@ void WindowDialog::_closed() {
hide();
}
+int WindowDialog::_drag_hit_test(const Point2& pos) const {
+ int drag_type = DRAG_NONE;
+
+ if (resizable) {
+ int titlebar_height = get_constant("titlebar_height", "WindowDialog");
+ int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
+
+ Rect2 rect = get_rect();
+
+ if (pos.y < (-titlebar_height + scaleborder_size))
+ drag_type = DRAG_RESIZE_TOP;
+ else if (pos.y >= (rect.size.height - scaleborder_size))
+ drag_type = DRAG_RESIZE_BOTTOM;
+ if (pos.x < scaleborder_size)
+ drag_type |= DRAG_RESIZE_LEFT;
+ else if (pos.x >= (rect.size.width - scaleborder_size))
+ drag_type |= DRAG_RESIZE_RIGHT;
+ }
+
+ if (drag_type == DRAG_NONE && pos.y < 0)
+ drag_type = DRAG_MOVE;
+
+ return drag_type;
+}
+
void WindowDialog::set_title(const String& p_title) {
title=XL_MESSAGE(p_title);
update();
}
+String WindowDialog::get_title() const {
+
+ return title;
+}
+
+void WindowDialog::set_resizable(bool p_resizable) {
+ resizable = p_resizable;
+}
+bool WindowDialog::get_resizable() const {
+ return resizable;
+}
+
Size2 WindowDialog::get_minimum_size() const {
@@ -127,11 +261,6 @@ Size2 WindowDialog::get_minimum_size() const {
}
-String WindowDialog::get_title() const {
-
- return title;
-}
-
TextureButton *WindowDialog::get_close_button() {
@@ -141,22 +270,26 @@ TextureButton *WindowDialog::get_close_button() {
void WindowDialog::_bind_methods() {
- ClassDB::bind_method( _MD("_gui_input"),&WindowDialog::_gui_input);
- ClassDB::bind_method( _MD("set_title","title"),&WindowDialog::set_title);
- ClassDB::bind_method( _MD("get_title"),&WindowDialog::get_title);
- ClassDB::bind_method( _MD("_closed"),&WindowDialog::_closed);
- ClassDB::bind_method( _MD("get_close_button:TextureButton"),&WindowDialog::get_close_button);
+ ClassDB::bind_method( D_METHOD("_gui_input"),&WindowDialog::_gui_input);
+ ClassDB::bind_method( D_METHOD("set_title","title"),&WindowDialog::set_title);
+ ClassDB::bind_method( D_METHOD("get_title"),&WindowDialog::get_title);
+ ClassDB::bind_method( D_METHOD("set_resizable","resizable"),&WindowDialog::set_resizable);
+ ClassDB::bind_method( D_METHOD("get_resizable"), &WindowDialog::get_resizable);
+ ClassDB::bind_method( D_METHOD("_closed"),&WindowDialog::_closed);
+ ClassDB::bind_method( D_METHOD("get_close_button:TextureButton"),&WindowDialog::get_close_button);
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"window_title",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_title"),_SCS("get_title"));
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"window_title",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL),"set_title","get_title");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"resizable",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL),"set_resizable","get_resizable");
}
WindowDialog::WindowDialog() {
//title="Hello!";
- dragging=false;
- close_button = memnew( TextureButton );
+ drag_type = DRAG_NONE;
+ resizable = false;
+ close_button = memnew(TextureButton);
add_child(close_button);
- close_button->connect("pressed",this,"_closed");
+ close_button->connect("pressed", this, "_closed");
}
@@ -186,7 +319,7 @@ PopupDialog::~PopupDialog() {
}
-//
+// AcceptDialog
void AcceptDialog::_post_popup() {
@@ -201,7 +334,7 @@ void AcceptDialog::_notification(int p_what) {
if (p_what==NOTIFICATION_MODAL_CLOSE) {
cancel_pressed();
- } if (p_what==NOTIFICATION_RESIZED) {
+ } else if (p_what==NOTIFICATION_RESIZED) {
_update_child_rects();
}
@@ -272,7 +405,7 @@ void AcceptDialog::_update_child_rects() {
if (!c)
continue;
- if (c==hbc || c==label || c==get_close_button())
+ if (c==hbc || c==label || c==get_close_button() || c->is_set_as_toplevel())
continue;
c->set_pos(cpos);
@@ -299,7 +432,7 @@ Size2 AcceptDialog::get_minimum_size() const {
if (!c)
continue;
- if (c==hbc || c==label || c==const_cast<AcceptDialog*>(this)->get_close_button())
+ if (c==hbc || c==label || c==const_cast<AcceptDialog*>(this)->get_close_button() || c->is_set_as_toplevel())
continue;
Size2 cminsize = c->get_combined_minimum_size();
@@ -361,25 +494,25 @@ Button* AcceptDialog::add_cancel(const String &p_cancel) {
void AcceptDialog::_bind_methods() {
- ClassDB::bind_method(_MD("_ok"),&AcceptDialog::_ok_pressed);
- ClassDB::bind_method(_MD("get_ok"),&AcceptDialog::get_ok);
- ClassDB::bind_method(_MD("get_label"),&AcceptDialog::get_label);
- ClassDB::bind_method(_MD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok);
- ClassDB::bind_method(_MD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok);
- ClassDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL(""));
- ClassDB::bind_method(_MD("add_cancel:Button","name"),&AcceptDialog::add_cancel);
- ClassDB::bind_method(_MD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered);
- ClassDB::bind_method(_MD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter);
- ClassDB::bind_method(_MD("_custom_action"),&AcceptDialog::_custom_action);
- ClassDB::bind_method(_MD("set_text","text"),&AcceptDialog::set_text);
- ClassDB::bind_method(_MD("get_text"),&AcceptDialog::get_text);
+ ClassDB::bind_method(D_METHOD("_ok"),&AcceptDialog::_ok_pressed);
+ ClassDB::bind_method(D_METHOD("get_ok"),&AcceptDialog::get_ok);
+ ClassDB::bind_method(D_METHOD("get_label"),&AcceptDialog::get_label);
+ ClassDB::bind_method(D_METHOD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok);
+ ClassDB::bind_method(D_METHOD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok);
+ ClassDB::bind_method(D_METHOD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_cancel:Button","name"),&AcceptDialog::add_cancel);
+ ClassDB::bind_method(D_METHOD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered);
+ ClassDB::bind_method(D_METHOD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter);
+ ClassDB::bind_method(D_METHOD("_custom_action"),&AcceptDialog::_custom_action);
+ ClassDB::bind_method(D_METHOD("set_text","text"),&AcceptDialog::set_text);
+ ClassDB::bind_method(D_METHOD("get_text"),&AcceptDialog::get_text);
ADD_SIGNAL( MethodInfo("confirmed") );
ADD_SIGNAL( MethodInfo("custom_action",PropertyInfo(Variant::STRING,"action")) );
ADD_GROUP("Dialog","dialog");
- ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"dialog_text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_text"),_SCS("get_text"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"),_SCS("set_hide_on_ok"),_SCS("get_hide_on_ok") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"dialog_text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL),"set_text","get_text");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"),"set_hide_on_ok","get_hide_on_ok") ;
}
@@ -429,7 +562,7 @@ AcceptDialog::~AcceptDialog()
void ConfirmationDialog::_bind_methods() {
- ClassDB::bind_method(_MD("get_cancel:Button"),&ConfirmationDialog::get_cancel);
+ ClassDB::bind_method(D_METHOD("get_cancel:Button"),&ConfirmationDialog::get_cancel);
}
Button *ConfirmationDialog::get_cancel() {
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 6650c5eb5d..dd75b76c8e 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -44,15 +44,29 @@ class WindowDialog : public Popup {
GDCLASS(WindowDialog,Popup);
+ enum DRAG_TYPE {
+ DRAG_NONE = 0,
+ DRAG_MOVE = 1,
+ DRAG_RESIZE_TOP = 1 << 1,
+ DRAG_RESIZE_RIGHT = 1 << 2,
+ DRAG_RESIZE_BOTTOM = 1 << 3,
+ DRAG_RESIZE_LEFT = 1 << 4
+ };
+
TextureButton *close_button;
String title;
- bool dragging;
+ int drag_type;
+ Point2 drag_offset;
+ Point2 drag_offset_far;
+ bool resizable;
void _gui_input(const InputEvent& p_event);
void _closed();
+ int _drag_hit_test(const Point2& pos) const;
+
protected:
virtual void _post_popup();
-
+ virtual void _fix_size();
virtual void _close_pressed() {}
virtual bool has_point(const Point2& p_point) const;
void _notification(int p_what);
@@ -63,6 +77,8 @@ public:
void set_title(const String& p_title);
String get_title() const;
+ void set_resizable(bool p_resizable);
+ bool get_resizable() const;
Size2 get_minimum_size() const;
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 393f14bee2..357a70a25b 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -686,41 +686,41 @@ bool FileDialog::default_show_hidden_files=false;
void FileDialog::_bind_methods() {
- ClassDB::bind_method(_MD("_unhandled_input"),&FileDialog::_unhandled_input);
-
- ClassDB::bind_method(_MD("_tree_selected"),&FileDialog::_tree_selected);
- ClassDB::bind_method(_MD("_tree_db_selected"),&FileDialog::_tree_dc_selected);
- ClassDB::bind_method(_MD("_dir_entered"),&FileDialog::_dir_entered);
- ClassDB::bind_method(_MD("_file_entered"),&FileDialog::_file_entered);
- ClassDB::bind_method(_MD("_action_pressed"),&FileDialog::_action_pressed);
- ClassDB::bind_method(_MD("_cancel_pressed"),&FileDialog::_cancel_pressed);
- ClassDB::bind_method(_MD("_filter_selected"),&FileDialog::_filter_selected);
- ClassDB::bind_method(_MD("_save_confirm_pressed"),&FileDialog::_save_confirm_pressed);
-
- ClassDB::bind_method(_MD("clear_filters"),&FileDialog::clear_filters);
- ClassDB::bind_method(_MD("add_filter","filter"),&FileDialog::add_filter);
- ClassDB::bind_method(_MD("set_filters","filters"),&FileDialog::set_filters);
- ClassDB::bind_method(_MD("get_filters"),&FileDialog::get_filters);
- ClassDB::bind_method(_MD("get_current_dir"),&FileDialog::get_current_dir);
- ClassDB::bind_method(_MD("get_current_file"),&FileDialog::get_current_file);
- ClassDB::bind_method(_MD("get_current_path"),&FileDialog::get_current_path);
- ClassDB::bind_method(_MD("set_current_dir","dir"),&FileDialog::set_current_dir);
- ClassDB::bind_method(_MD("set_current_file","file"),&FileDialog::set_current_file);
- ClassDB::bind_method(_MD("set_current_path","path"),&FileDialog::set_current_path);
- ClassDB::bind_method(_MD("set_mode","mode"),&FileDialog::set_mode);
- ClassDB::bind_method(_MD("get_mode"),&FileDialog::get_mode);
- ClassDB::bind_method(_MD("get_vbox:VBoxContainer"),&FileDialog::get_vbox);
- ClassDB::bind_method(_MD("set_access","access"),&FileDialog::set_access);
- ClassDB::bind_method(_MD("get_access"),&FileDialog::get_access);
- ClassDB::bind_method(_MD("set_show_hidden_files","show"),&FileDialog::set_show_hidden_files);
- ClassDB::bind_method(_MD("is_showing_hidden_files"),&FileDialog::is_showing_hidden_files);
- ClassDB::bind_method(_MD("_select_drive"),&FileDialog::_select_drive);
- ClassDB::bind_method(_MD("_make_dir"),&FileDialog::_make_dir);
- ClassDB::bind_method(_MD("_make_dir_confirm"),&FileDialog::_make_dir_confirm);
- ClassDB::bind_method(_MD("_update_file_list"),&FileDialog::update_file_list);
- ClassDB::bind_method(_MD("_update_dir"),&FileDialog::update_dir);
-
- ClassDB::bind_method(_MD("invalidate"),&FileDialog::invalidate);
+ ClassDB::bind_method(D_METHOD("_unhandled_input"),&FileDialog::_unhandled_input);
+
+ ClassDB::bind_method(D_METHOD("_tree_selected"),&FileDialog::_tree_selected);
+ ClassDB::bind_method(D_METHOD("_tree_db_selected"),&FileDialog::_tree_dc_selected);
+ ClassDB::bind_method(D_METHOD("_dir_entered"),&FileDialog::_dir_entered);
+ ClassDB::bind_method(D_METHOD("_file_entered"),&FileDialog::_file_entered);
+ ClassDB::bind_method(D_METHOD("_action_pressed"),&FileDialog::_action_pressed);
+ ClassDB::bind_method(D_METHOD("_cancel_pressed"),&FileDialog::_cancel_pressed);
+ ClassDB::bind_method(D_METHOD("_filter_selected"),&FileDialog::_filter_selected);
+ ClassDB::bind_method(D_METHOD("_save_confirm_pressed"),&FileDialog::_save_confirm_pressed);
+
+ ClassDB::bind_method(D_METHOD("clear_filters"),&FileDialog::clear_filters);
+ ClassDB::bind_method(D_METHOD("add_filter","filter"),&FileDialog::add_filter);
+ ClassDB::bind_method(D_METHOD("set_filters","filters"),&FileDialog::set_filters);
+ ClassDB::bind_method(D_METHOD("get_filters"),&FileDialog::get_filters);
+ ClassDB::bind_method(D_METHOD("get_current_dir"),&FileDialog::get_current_dir);
+ ClassDB::bind_method(D_METHOD("get_current_file"),&FileDialog::get_current_file);
+ ClassDB::bind_method(D_METHOD("get_current_path"),&FileDialog::get_current_path);
+ ClassDB::bind_method(D_METHOD("set_current_dir","dir"),&FileDialog::set_current_dir);
+ ClassDB::bind_method(D_METHOD("set_current_file","file"),&FileDialog::set_current_file);
+ ClassDB::bind_method(D_METHOD("set_current_path","path"),&FileDialog::set_current_path);
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&FileDialog::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&FileDialog::get_mode);
+ ClassDB::bind_method(D_METHOD("get_vbox:VBoxContainer"),&FileDialog::get_vbox);
+ ClassDB::bind_method(D_METHOD("set_access","access"),&FileDialog::set_access);
+ ClassDB::bind_method(D_METHOD("get_access"),&FileDialog::get_access);
+ ClassDB::bind_method(D_METHOD("set_show_hidden_files","show"),&FileDialog::set_show_hidden_files);
+ ClassDB::bind_method(D_METHOD("is_showing_hidden_files"),&FileDialog::is_showing_hidden_files);
+ ClassDB::bind_method(D_METHOD("_select_drive"),&FileDialog::_select_drive);
+ ClassDB::bind_method(D_METHOD("_make_dir"),&FileDialog::_make_dir);
+ ClassDB::bind_method(D_METHOD("_make_dir_confirm"),&FileDialog::_make_dir_confirm);
+ ClassDB::bind_method(D_METHOD("_update_file_list"),&FileDialog::update_file_list);
+ ClassDB::bind_method(D_METHOD("_update_dir"),&FileDialog::update_dir);
+
+ ClassDB::bind_method(D_METHOD("invalidate"),&FileDialog::invalidate);
ADD_SIGNAL(MethodInfo("file_selected",PropertyInfo( Variant::STRING,"path")));
ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::POOL_STRING_ARRAY,"paths")));
@@ -737,10 +737,10 @@ void FileDialog::_bind_methods() {
BIND_CONSTANT( ACCESS_USERDATA );
BIND_CONSTANT( ACCESS_FILESYSTEM );
- ADD_PROPERTY( PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"),_SCS("set_mode"),_SCS("get_mode") );
- ADD_PROPERTY( PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"),_SCS("set_access"),_SCS("get_access") );
- ADD_PROPERTY( PropertyInfo(Variant::POOL_STRING_ARRAY, "filters"),_SCS("set_filters"),_SCS("get_filters") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "show_hidden_files"),_SCS("set_show_hidden_files"),_SCS("is_showing_hidden_files") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"),"set_mode","get_mode") ;
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"),"set_access","get_access") ;
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_STRING_ARRAY, "filters"),"set_filters","get_filters") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "show_hidden_files"),"set_show_hidden_files","is_showing_hidden_files") ;
}
@@ -868,11 +868,11 @@ FileDialog::~FileDialog() {
void LineEditFileChooser::_bind_methods() {
- ClassDB::bind_method(_MD("_browse"),&LineEditFileChooser::_browse);
- ClassDB::bind_method(_MD("_chosen"),&LineEditFileChooser::_chosen);
- ClassDB::bind_method(_MD("get_button:Button"),&LineEditFileChooser::get_button);
- ClassDB::bind_method(_MD("get_line_edit:LineEdit"),&LineEditFileChooser::get_line_edit);
- ClassDB::bind_method(_MD("get_file_dialog:FileDialog"),&LineEditFileChooser::get_file_dialog);
+ ClassDB::bind_method(D_METHOD("_browse"),&LineEditFileChooser::_browse);
+ ClassDB::bind_method(D_METHOD("_chosen"),&LineEditFileChooser::_chosen);
+ ClassDB::bind_method(D_METHOD("get_button:Button"),&LineEditFileChooser::get_button);
+ ClassDB::bind_method(D_METHOD("get_line_edit:LineEdit"),&LineEditFileChooser::get_line_edit);
+ ClassDB::bind_method(D_METHOD("get_file_dialog:FileDialog"),&LineEditFileChooser::get_file_dialog);
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index ba1ab1afa8..a6954a2c77 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1201,44 +1201,44 @@ void GraphEdit::_snap_value_changed(double) {
void GraphEdit::_bind_methods() {
- ClassDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node);
- ClassDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected);
- ClassDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node);
- ClassDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list);
- ClassDB::bind_method(_MD("get_scroll_ofs"),&GraphEdit::get_scroll_ofs);
- ClassDB::bind_method(_MD("set_scroll_ofs","ofs"),&GraphEdit::set_scroll_ofs);
+ ClassDB::bind_method(D_METHOD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node);
+ ClassDB::bind_method(D_METHOD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected);
+ ClassDB::bind_method(D_METHOD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node);
+ ClassDB::bind_method(D_METHOD("get_connection_list"),&GraphEdit::_get_connection_list);
+ ClassDB::bind_method(D_METHOD("get_scroll_ofs"),&GraphEdit::get_scroll_ofs);
+ ClassDB::bind_method(D_METHOD("set_scroll_ofs","ofs"),&GraphEdit::set_scroll_ofs);
- ClassDB::bind_method(_MD("set_zoom","p_zoom"),&GraphEdit::set_zoom);
- ClassDB::bind_method(_MD("get_zoom"),&GraphEdit::get_zoom);
+ ClassDB::bind_method(D_METHOD("set_zoom","p_zoom"),&GraphEdit::set_zoom);
+ ClassDB::bind_method(D_METHOD("get_zoom"),&GraphEdit::get_zoom);
- ClassDB::bind_method(_MD("set_snap","pixels"),&GraphEdit::set_snap);
- ClassDB::bind_method(_MD("get_snap"),&GraphEdit::get_snap);
+ ClassDB::bind_method(D_METHOD("set_snap","pixels"),&GraphEdit::set_snap);
+ ClassDB::bind_method(D_METHOD("get_snap"),&GraphEdit::get_snap);
- ClassDB::bind_method(_MD("set_use_snap","enable"),&GraphEdit::set_use_snap);
- ClassDB::bind_method(_MD("is_using_snap"),&GraphEdit::is_using_snap);
+ ClassDB::bind_method(D_METHOD("set_use_snap","enable"),&GraphEdit::set_use_snap);
+ ClassDB::bind_method(D_METHOD("is_using_snap"),&GraphEdit::is_using_snap);
- ClassDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects);
- ClassDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled);
+ ClassDB::bind_method(D_METHOD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects);
+ ClassDB::bind_method(D_METHOD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled);
- ClassDB::bind_method(_MD("_graph_node_moved"),&GraphEdit::_graph_node_moved);
- ClassDB::bind_method(_MD("_graph_node_raised"),&GraphEdit::_graph_node_raised);
+ ClassDB::bind_method(D_METHOD("_graph_node_moved"),&GraphEdit::_graph_node_moved);
+ ClassDB::bind_method(D_METHOD("_graph_node_raised"),&GraphEdit::_graph_node_raised);
- ClassDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input);
- ClassDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw);
- ClassDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved);
- ClassDB::bind_method(_MD("_zoom_minus"),&GraphEdit::_zoom_minus);
- ClassDB::bind_method(_MD("_zoom_reset"),&GraphEdit::_zoom_reset);
- ClassDB::bind_method(_MD("_zoom_plus"),&GraphEdit::_zoom_plus);
- ClassDB::bind_method(_MD("_snap_toggled"),&GraphEdit::_snap_toggled);
- ClassDB::bind_method(_MD("_snap_value_changed"),&GraphEdit::_snap_value_changed);
+ ClassDB::bind_method(D_METHOD("_top_layer_input"),&GraphEdit::_top_layer_input);
+ ClassDB::bind_method(D_METHOD("_top_layer_draw"),&GraphEdit::_top_layer_draw);
+ ClassDB::bind_method(D_METHOD("_scroll_moved"),&GraphEdit::_scroll_moved);
+ ClassDB::bind_method(D_METHOD("_zoom_minus"),&GraphEdit::_zoom_minus);
+ ClassDB::bind_method(D_METHOD("_zoom_reset"),&GraphEdit::_zoom_reset);
+ ClassDB::bind_method(D_METHOD("_zoom_plus"),&GraphEdit::_zoom_plus);
+ ClassDB::bind_method(D_METHOD("_snap_toggled"),&GraphEdit::_snap_toggled);
+ ClassDB::bind_method(D_METHOD("_snap_value_changed"),&GraphEdit::_snap_value_changed);
- ClassDB::bind_method(_MD("_gui_input"),&GraphEdit::_gui_input);
- ClassDB::bind_method(_MD("_update_scroll_offset"),&GraphEdit::_update_scroll_offset);
- ClassDB::bind_method(_MD("_connections_layer_draw"),&GraphEdit::_connections_layer_draw);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&GraphEdit::_gui_input);
+ ClassDB::bind_method(D_METHOD("_update_scroll_offset"),&GraphEdit::_update_scroll_offset);
+ ClassDB::bind_method(D_METHOD("_connections_layer_draw"),&GraphEdit::_connections_layer_draw);
- ClassDB::bind_method(_MD("set_selected","node"),&GraphEdit::set_selected);
+ ClassDB::bind_method(D_METHOD("set_selected","node"),&GraphEdit::set_selected);
ADD_SIGNAL(MethodInfo("connection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot")));
ADD_SIGNAL(MethodInfo("disconnection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot")));
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index aa8c875f40..58d3f42483 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -712,51 +712,51 @@ bool GraphNode::is_resizeable() const{
void GraphNode::_bind_methods() {
- ClassDB::bind_method(_MD("set_title","title"),&GraphNode::set_title);
- ClassDB::bind_method(_MD("get_title"),&GraphNode::get_title);
- ClassDB::bind_method(_MD("_gui_input"),&GraphNode::_gui_input);
-
- ClassDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right","custom_left","custom_right"),&GraphNode::set_slot,DEFVAL(Ref<Texture>()),DEFVAL(Ref<Texture>()));
- ClassDB::bind_method(_MD("clear_slot","idx"),&GraphNode::clear_slot);
- ClassDB::bind_method(_MD("clear_all_slots","idx"),&GraphNode::clear_all_slots);
- ClassDB::bind_method(_MD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left);
- ClassDB::bind_method(_MD("get_slot_type_left","idx"),&GraphNode::get_slot_type_left);
- ClassDB::bind_method(_MD("get_slot_color_left","idx"),&GraphNode::get_slot_color_left);
- ClassDB::bind_method(_MD("is_slot_enabled_right","idx"),&GraphNode::is_slot_enabled_right);
- ClassDB::bind_method(_MD("get_slot_type_right","idx"),&GraphNode::get_slot_type_right);
- ClassDB::bind_method(_MD("get_slot_color_right","idx"),&GraphNode::get_slot_color_right);
-
- ClassDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&GraphNode::get_offset);
-
- ClassDB::bind_method(_MD("set_comment","comment"),&GraphNode::set_comment);
- ClassDB::bind_method(_MD("is_comment"),&GraphNode::is_comment);
-
- ClassDB::bind_method(_MD("set_resizeable","resizeable"),&GraphNode::set_resizeable);
- ClassDB::bind_method(_MD("is_resizeable"),&GraphNode::is_resizeable);
-
- ClassDB::bind_method(_MD("set_selected","selected"),&GraphNode::set_selected);
- ClassDB::bind_method(_MD("is_selected"),&GraphNode::is_selected);
-
- ClassDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count);
- ClassDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count);
-
- ClassDB::bind_method(_MD("get_connection_output_pos","idx"),&GraphNode::get_connection_output_pos);
- ClassDB::bind_method(_MD("get_connection_output_type","idx"),&GraphNode::get_connection_output_type);
- ClassDB::bind_method(_MD("get_connection_output_color","idx"),&GraphNode::get_connection_output_color);
- ClassDB::bind_method(_MD("get_connection_input_pos","idx"),&GraphNode::get_connection_input_pos);
- ClassDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type);
- ClassDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color);
-
- ClassDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button);
- ClassDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible);
-
- ClassDB::bind_method(_MD("set_overlay","overlay"),&GraphNode::set_overlay);
- ClassDB::bind_method(_MD("get_overlay"),&GraphNode::get_overlay);
-
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"resizeable"),_SCS("set_resizeable"),_SCS("is_resizeable"));
+ ClassDB::bind_method(D_METHOD("set_title","title"),&GraphNode::set_title);
+ ClassDB::bind_method(D_METHOD("get_title"),&GraphNode::get_title);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&GraphNode::_gui_input);
+
+ ClassDB::bind_method(D_METHOD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right","custom_left","custom_right"),&GraphNode::set_slot,DEFVAL(Ref<Texture>()),DEFVAL(Ref<Texture>()));
+ ClassDB::bind_method(D_METHOD("clear_slot","idx"),&GraphNode::clear_slot);
+ ClassDB::bind_method(D_METHOD("clear_all_slots","idx"),&GraphNode::clear_all_slots);
+ ClassDB::bind_method(D_METHOD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left);
+ ClassDB::bind_method(D_METHOD("get_slot_type_left","idx"),&GraphNode::get_slot_type_left);
+ ClassDB::bind_method(D_METHOD("get_slot_color_left","idx"),&GraphNode::get_slot_color_left);
+ ClassDB::bind_method(D_METHOD("is_slot_enabled_right","idx"),&GraphNode::is_slot_enabled_right);
+ ClassDB::bind_method(D_METHOD("get_slot_type_right","idx"),&GraphNode::get_slot_type_right);
+ ClassDB::bind_method(D_METHOD("get_slot_color_right","idx"),&GraphNode::get_slot_color_right);
+
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&GraphNode::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&GraphNode::get_offset);
+
+ ClassDB::bind_method(D_METHOD("set_comment","comment"),&GraphNode::set_comment);
+ ClassDB::bind_method(D_METHOD("is_comment"),&GraphNode::is_comment);
+
+ ClassDB::bind_method(D_METHOD("set_resizeable","resizeable"),&GraphNode::set_resizeable);
+ ClassDB::bind_method(D_METHOD("is_resizeable"),&GraphNode::is_resizeable);
+
+ ClassDB::bind_method(D_METHOD("set_selected","selected"),&GraphNode::set_selected);
+ ClassDB::bind_method(D_METHOD("is_selected"),&GraphNode::is_selected);
+
+ ClassDB::bind_method(D_METHOD("get_connection_output_count"),&GraphNode::get_connection_output_count);
+ ClassDB::bind_method(D_METHOD("get_connection_input_count"),&GraphNode::get_connection_input_count);
+
+ ClassDB::bind_method(D_METHOD("get_connection_output_pos","idx"),&GraphNode::get_connection_output_pos);
+ ClassDB::bind_method(D_METHOD("get_connection_output_type","idx"),&GraphNode::get_connection_output_type);
+ ClassDB::bind_method(D_METHOD("get_connection_output_color","idx"),&GraphNode::get_connection_output_color);
+ ClassDB::bind_method(D_METHOD("get_connection_input_pos","idx"),&GraphNode::get_connection_input_pos);
+ ClassDB::bind_method(D_METHOD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type);
+ ClassDB::bind_method(D_METHOD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color);
+
+ ClassDB::bind_method(D_METHOD("set_show_close_button","show"),&GraphNode::set_show_close_button);
+ ClassDB::bind_method(D_METHOD("is_close_button_visible"),&GraphNode::is_close_button_visible);
+
+ ClassDB::bind_method(D_METHOD("set_overlay","overlay"),&GraphNode::set_overlay);
+ ClassDB::bind_method(D_METHOD("get_overlay"),&GraphNode::get_overlay);
+
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),"set_title","get_title");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),"set_show_close_button","is_close_button_visible");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"resizeable"),"set_resizeable","is_resizeable");
ADD_SIGNAL(MethodInfo("offset_changed"));
ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to")));
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 597169ca83..ee1d642110 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -170,10 +170,10 @@ int GridContainer::get_columns() const{
void GridContainer::_bind_methods(){
- ClassDB::bind_method(_MD("set_columns","columns"),&GridContainer::set_columns);
- ClassDB::bind_method(_MD("get_columns"),&GridContainer::get_columns);
+ ClassDB::bind_method(D_METHOD("set_columns","columns"),&GridContainer::set_columns);
+ ClassDB::bind_method(D_METHOD("get_columns"),&GridContainer::get_columns);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"columns",PROPERTY_HINT_RANGE,"1,1024,1"),_SCS("set_columns"),_SCS("get_columns"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"columns",PROPERTY_HINT_RANGE,"1,1024,1"),"set_columns","get_columns");
}
Size2 GridContainer::get_minimum_size() const {
diff --git a/scene/gui/input_action.cpp b/scene/gui/input_action.cpp
index 77026dfdb1..afdffd9a53 100644
--- a/scene/gui/input_action.cpp
+++ b/scene/gui/input_action.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* input_action.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "input_action.h"
#include "os/keyboard.h"
@@ -109,15 +137,15 @@ bool ShortCut::is_valid() const {
void ShortCut::_bind_methods() {
- ClassDB::bind_method(_MD("set_shortcut","event"),&ShortCut::set_shortcut);
- ClassDB::bind_method(_MD("get_shortcut"),&ShortCut::get_shortcut);
+ ClassDB::bind_method(D_METHOD("set_shortcut","event"),&ShortCut::set_shortcut);
+ ClassDB::bind_method(D_METHOD("get_shortcut"),&ShortCut::get_shortcut);
- ClassDB::bind_method(_MD("is_valid"),&ShortCut::is_valid);
+ ClassDB::bind_method(D_METHOD("is_valid"),&ShortCut::is_valid);
- ClassDB::bind_method(_MD("is_shortcut","event"),&ShortCut::is_shortcut);
- ClassDB::bind_method(_MD("get_as_text"),&ShortCut::get_as_text);
+ ClassDB::bind_method(D_METHOD("is_shortcut","event"),&ShortCut::is_shortcut);
+ ClassDB::bind_method(D_METHOD("get_as_text"),&ShortCut::get_as_text);
- ADD_PROPERTY(PropertyInfo(Variant::INPUT_EVENT,"shortcut"),_SCS("set_shortcut"),_SCS("get_shortcut"));
+ ADD_PROPERTY(PropertyInfo(Variant::INPUT_EVENT,"shortcut"),"set_shortcut","get_shortcut");
}
ShortCut::ShortCut(){
diff --git a/scene/gui/input_action.h b/scene/gui/input_action.h
index a83b3a70cd..3cdbc755ef 100644
--- a/scene/gui/input_action.h
+++ b/scene/gui/input_action.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* input_action.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 INPUTACTION_H
#define INPUTACTION_H
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index a42ef08bf3..91bd16ee0b 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "item_list.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool p_selectable) {
@@ -314,7 +314,7 @@ void ItemList::move_item(int p_item,int p_to_pos) {
if (current<0) {
//do none
- } if (p_item==current) {
+ } else if (p_item==current) {
current=p_to_pos;
} else if (p_to_pos>p_item && current>p_item && current<p_to_pos) {
current--;
@@ -1204,6 +1204,22 @@ int ItemList::get_item_at_pos(const Point2& p_pos, bool p_exact) const {
return closest;
}
+bool ItemList::is_pos_at_end_of_items(const Point2& p_pos) const {
+
+ if (items.empty())
+ return true;
+
+ Vector2 pos=p_pos;
+ Ref<StyleBox> bg = get_stylebox("bg");
+ pos-=bg->get_offset();
+ pos.y+=scroll_bar->get_value();
+
+ Rect2 endrect = items[items.size()-1].rect_cache;
+ return (pos.y > endrect.pos.y + endrect.size.y);
+
+}
+
+
String ItemList::get_tooltip(const Point2& p_pos) const {
int closest = get_item_at_pos(p_pos);
@@ -1284,83 +1300,83 @@ Vector<int> ItemList::get_selected_items() {
void ItemList::_bind_methods(){
- ClassDB::bind_method(_MD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true));
- ClassDB::bind_method(_MD("add_icon_item","icon:Texture","selectable"),&ItemList::add_icon_item,DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("add_item","text","icon:Texture","selectable"),&ItemList::add_item,DEFVAL(Variant()),DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("add_icon_item","icon:Texture","selectable"),&ItemList::add_icon_item,DEFVAL(true));
- ClassDB::bind_method(_MD("set_item_text","idx","text"),&ItemList::set_item_text);
- ClassDB::bind_method(_MD("get_item_text","idx"),&ItemList::get_item_text);
+ ClassDB::bind_method(D_METHOD("set_item_text","idx","text"),&ItemList::set_item_text);
+ ClassDB::bind_method(D_METHOD("get_item_text","idx"),&ItemList::get_item_text);
- ClassDB::bind_method(_MD("set_item_icon","idx","icon:Texture"),&ItemList::set_item_icon);
- ClassDB::bind_method(_MD("get_item_icon:Texture","idx"),&ItemList::get_item_icon);
+ ClassDB::bind_method(D_METHOD("set_item_icon","idx","icon:Texture"),&ItemList::set_item_icon);
+ ClassDB::bind_method(D_METHOD("get_item_icon:Texture","idx"),&ItemList::get_item_icon);
- ClassDB::bind_method(_MD("set_item_icon_region","idx","rect"),&ItemList::set_item_icon_region);
- ClassDB::bind_method(_MD("get_item_icon_region","idx"),&ItemList::get_item_icon_region);
+ ClassDB::bind_method(D_METHOD("set_item_icon_region","idx","rect"),&ItemList::set_item_icon_region);
+ ClassDB::bind_method(D_METHOD("get_item_icon_region","idx"),&ItemList::get_item_icon_region);
- ClassDB::bind_method(_MD("set_item_selectable","idx","selectable"),&ItemList::set_item_selectable);
- ClassDB::bind_method(_MD("is_item_selectable","idx"),&ItemList::is_item_selectable);
+ ClassDB::bind_method(D_METHOD("set_item_selectable","idx","selectable"),&ItemList::set_item_selectable);
+ ClassDB::bind_method(D_METHOD("is_item_selectable","idx"),&ItemList::is_item_selectable);
- ClassDB::bind_method(_MD("set_item_disabled","idx","disabled"),&ItemList::set_item_disabled);
- ClassDB::bind_method(_MD("is_item_disabled","idx"),&ItemList::is_item_disabled);
+ ClassDB::bind_method(D_METHOD("set_item_disabled","idx","disabled"),&ItemList::set_item_disabled);
+ ClassDB::bind_method(D_METHOD("is_item_disabled","idx"),&ItemList::is_item_disabled);
- ClassDB::bind_method(_MD("set_item_metadata","idx","metadata"),&ItemList::set_item_metadata);
- ClassDB::bind_method(_MD("get_item_metadata","idx"),&ItemList::get_item_metadata);
+ ClassDB::bind_method(D_METHOD("set_item_metadata","idx","metadata"),&ItemList::set_item_metadata);
+ ClassDB::bind_method(D_METHOD("get_item_metadata","idx"),&ItemList::get_item_metadata);
- ClassDB::bind_method(_MD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color);
- ClassDB::bind_method(_MD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color);
+ ClassDB::bind_method(D_METHOD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color);
+ ClassDB::bind_method(D_METHOD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color);
- ClassDB::bind_method(_MD("set_item_tooltip_enabled","idx","enable"),&ItemList::set_item_tooltip_enabled);
- ClassDB::bind_method(_MD("is_item_tooltip_enabled","idx"),&ItemList::is_item_tooltip_enabled);
+ ClassDB::bind_method(D_METHOD("set_item_tooltip_enabled","idx","enable"),&ItemList::set_item_tooltip_enabled);
+ ClassDB::bind_method(D_METHOD("is_item_tooltip_enabled","idx"),&ItemList::is_item_tooltip_enabled);
- ClassDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip);
- ClassDB::bind_method(_MD("get_item_tooltip","idx"),&ItemList::get_item_tooltip);
+ ClassDB::bind_method(D_METHOD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip);
+ ClassDB::bind_method(D_METHOD("get_item_tooltip","idx"),&ItemList::get_item_tooltip);
- ClassDB::bind_method(_MD("select","idx","single"),&ItemList::select,DEFVAL(true));
- ClassDB::bind_method(_MD("unselect","idx"),&ItemList::unselect);
- ClassDB::bind_method(_MD("is_selected","idx"),&ItemList::is_selected);
- ClassDB::bind_method(_MD("get_selected_items"),&ItemList::get_selected_items);
+ ClassDB::bind_method(D_METHOD("select","idx","single"),&ItemList::select,DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("unselect","idx"),&ItemList::unselect);
+ ClassDB::bind_method(D_METHOD("is_selected","idx"),&ItemList::is_selected);
+ ClassDB::bind_method(D_METHOD("get_selected_items"),&ItemList::get_selected_items);
- ClassDB::bind_method(_MD("get_item_count"),&ItemList::get_item_count);
- ClassDB::bind_method(_MD("remove_item","idx"),&ItemList::remove_item);
+ ClassDB::bind_method(D_METHOD("get_item_count"),&ItemList::get_item_count);
+ ClassDB::bind_method(D_METHOD("remove_item","idx"),&ItemList::remove_item);
- ClassDB::bind_method(_MD("clear"),&ItemList::clear);
- ClassDB::bind_method(_MD("sort_items_by_text"),&ItemList::sort_items_by_text);
+ ClassDB::bind_method(D_METHOD("clear"),&ItemList::clear);
+ ClassDB::bind_method(D_METHOD("sort_items_by_text"),&ItemList::sort_items_by_text);
- ClassDB::bind_method(_MD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width);
- ClassDB::bind_method(_MD("get_fixed_column_width"),&ItemList::get_fixed_column_width);
+ ClassDB::bind_method(D_METHOD("set_fixed_column_width","width"),&ItemList::set_fixed_column_width);
+ ClassDB::bind_method(D_METHOD("get_fixed_column_width"),&ItemList::get_fixed_column_width);
- ClassDB::bind_method(_MD("set_same_column_width","enable"),&ItemList::set_same_column_width);
- ClassDB::bind_method(_MD("is_same_column_width"),&ItemList::is_same_column_width);
+ ClassDB::bind_method(D_METHOD("set_same_column_width","enable"),&ItemList::set_same_column_width);
+ ClassDB::bind_method(D_METHOD("is_same_column_width"),&ItemList::is_same_column_width);
- ClassDB::bind_method(_MD("set_max_text_lines","lines"),&ItemList::set_max_text_lines);
- ClassDB::bind_method(_MD("get_max_text_lines"),&ItemList::get_max_text_lines);
+ ClassDB::bind_method(D_METHOD("set_max_text_lines","lines"),&ItemList::set_max_text_lines);
+ ClassDB::bind_method(D_METHOD("get_max_text_lines"),&ItemList::get_max_text_lines);
- ClassDB::bind_method(_MD("set_max_columns","amount"),&ItemList::set_max_columns);
- ClassDB::bind_method(_MD("get_max_columns"),&ItemList::get_max_columns);
+ ClassDB::bind_method(D_METHOD("set_max_columns","amount"),&ItemList::set_max_columns);
+ ClassDB::bind_method(D_METHOD("get_max_columns"),&ItemList::get_max_columns);
- ClassDB::bind_method(_MD("set_select_mode","mode"),&ItemList::set_select_mode);
- ClassDB::bind_method(_MD("get_select_mode"),&ItemList::get_select_mode);
+ ClassDB::bind_method(D_METHOD("set_select_mode","mode"),&ItemList::set_select_mode);
+ ClassDB::bind_method(D_METHOD("get_select_mode"),&ItemList::get_select_mode);
- ClassDB::bind_method(_MD("set_icon_mode","mode"),&ItemList::set_icon_mode);
- ClassDB::bind_method(_MD("get_icon_mode"),&ItemList::get_icon_mode);
+ ClassDB::bind_method(D_METHOD("set_icon_mode","mode"),&ItemList::set_icon_mode);
+ ClassDB::bind_method(D_METHOD("get_icon_mode"),&ItemList::get_icon_mode);
- ClassDB::bind_method(_MD("set_fixed_icon_size","size"),&ItemList::set_fixed_icon_size);
- ClassDB::bind_method(_MD("get_fixed_icon_size"),&ItemList::get_fixed_icon_size);
+ ClassDB::bind_method(D_METHOD("set_fixed_icon_size","size"),&ItemList::set_fixed_icon_size);
+ ClassDB::bind_method(D_METHOD("get_fixed_icon_size"),&ItemList::get_fixed_icon_size);
- ClassDB::bind_method(_MD("set_icon_scale","scale"),&ItemList::set_icon_scale);
- ClassDB::bind_method(_MD("get_icon_scale"),&ItemList::get_icon_scale);
+ ClassDB::bind_method(D_METHOD("set_icon_scale","scale"),&ItemList::set_icon_scale);
+ ClassDB::bind_method(D_METHOD("get_icon_scale"),&ItemList::get_icon_scale);
- ClassDB::bind_method(_MD("set_allow_rmb_select","allow"),&ItemList::set_allow_rmb_select);
- ClassDB::bind_method(_MD("get_allow_rmb_select"),&ItemList::get_allow_rmb_select);
+ ClassDB::bind_method(D_METHOD("set_allow_rmb_select","allow"),&ItemList::set_allow_rmb_select);
+ ClassDB::bind_method(D_METHOD("get_allow_rmb_select"),&ItemList::get_allow_rmb_select);
- ClassDB::bind_method(_MD("get_item_at_pos","pos","exact"),&ItemList::get_item_at_pos,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_item_at_pos","pos","exact"),&ItemList::get_item_at_pos,DEFVAL(false));
- ClassDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible);
+ ClassDB::bind_method(D_METHOD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible);
- ClassDB::bind_method(_MD("get_v_scroll"),&ItemList::get_v_scroll);
+ ClassDB::bind_method(D_METHOD("get_v_scroll"),&ItemList::get_v_scroll);
- ClassDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed);
- ClassDB::bind_method(_MD("_gui_input"),&ItemList::_gui_input);
+ ClassDB::bind_method(D_METHOD("_scroll_changed"),&ItemList::_scroll_changed);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&ItemList::_gui_input);
BIND_CONSTANT( ICON_MODE_TOP );
BIND_CONSTANT( ICON_MODE_LEFT );
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index f4a864c782..35ffb1be9c 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -191,6 +191,7 @@ public:
virtual String get_tooltip(const Point2& p_pos) const;
int get_item_at_pos(const Point2& p_pos,bool p_exact=false) const;
+ bool is_pos_at_end_of_items(const Point2& p_pos) const;
void set_icon_scale(real_t p_scale);
real_t get_icon_scale() const;
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index d32b4c6de4..915eaa2f45 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "label.h"
#include "print_string.h"
-#include "globals.h"
+#include "global_config.h"
#include "translation.h"
@@ -648,30 +648,30 @@ int Label::get_total_character_count() const {
void Label::_bind_methods() {
- ClassDB::bind_method(_MD("set_align","align"),&Label::set_align);
- ClassDB::bind_method(_MD("get_align"),&Label::get_align);
- ClassDB::bind_method(_MD("set_valign","valign"),&Label::set_valign);
- ClassDB::bind_method(_MD("get_valign"),&Label::get_valign);
- ClassDB::bind_method(_MD("set_text","text"),&Label::set_text);
- ClassDB::bind_method(_MD("get_text"),&Label::get_text);
- ClassDB::bind_method(_MD("set_autowrap","enable"),&Label::set_autowrap);
- ClassDB::bind_method(_MD("has_autowrap"),&Label::has_autowrap);
- ClassDB::bind_method(_MD("set_clip_text","enable"),&Label::set_clip_text);
- ClassDB::bind_method(_MD("is_clipping_text"),&Label::is_clipping_text);
- ClassDB::bind_method(_MD("set_uppercase","enable"),&Label::set_uppercase);
- ClassDB::bind_method(_MD("is_uppercase"),&Label::is_uppercase);
- ClassDB::bind_method(_MD("get_line_height"),&Label::get_line_height);
- ClassDB::bind_method(_MD("get_line_count"),&Label::get_line_count);
- ClassDB::bind_method(_MD("get_visible_line_count"),&Label::get_visible_line_count);
- ClassDB::bind_method(_MD("get_total_character_count"),&Label::get_total_character_count);
- ClassDB::bind_method(_MD("set_visible_characters","amount"),&Label::set_visible_characters);
- ClassDB::bind_method(_MD("get_visible_characters"),&Label::get_visible_characters);
- ClassDB::bind_method(_MD("set_percent_visible","percent_visible"),&Label::set_percent_visible);
- ClassDB::bind_method(_MD("get_percent_visible"),&Label::get_percent_visible);
- ClassDB::bind_method(_MD("set_lines_skipped","lines_skipped"),&Label::set_lines_skipped);
- ClassDB::bind_method(_MD("get_lines_skipped"),&Label::get_lines_skipped);
- ClassDB::bind_method(_MD("set_max_lines_visible","lines_visible"),&Label::set_max_lines_visible);
- ClassDB::bind_method(_MD("get_max_lines_visible"),&Label::get_max_lines_visible);
+ ClassDB::bind_method(D_METHOD("set_align","align"),&Label::set_align);
+ ClassDB::bind_method(D_METHOD("get_align"),&Label::get_align);
+ ClassDB::bind_method(D_METHOD("set_valign","valign"),&Label::set_valign);
+ ClassDB::bind_method(D_METHOD("get_valign"),&Label::get_valign);
+ ClassDB::bind_method(D_METHOD("set_text","text"),&Label::set_text);
+ ClassDB::bind_method(D_METHOD("get_text"),&Label::get_text);
+ ClassDB::bind_method(D_METHOD("set_autowrap","enable"),&Label::set_autowrap);
+ ClassDB::bind_method(D_METHOD("has_autowrap"),&Label::has_autowrap);
+ ClassDB::bind_method(D_METHOD("set_clip_text","enable"),&Label::set_clip_text);
+ ClassDB::bind_method(D_METHOD("is_clipping_text"),&Label::is_clipping_text);
+ ClassDB::bind_method(D_METHOD("set_uppercase","enable"),&Label::set_uppercase);
+ ClassDB::bind_method(D_METHOD("is_uppercase"),&Label::is_uppercase);
+ ClassDB::bind_method(D_METHOD("get_line_height"),&Label::get_line_height);
+ ClassDB::bind_method(D_METHOD("get_line_count"),&Label::get_line_count);
+ ClassDB::bind_method(D_METHOD("get_visible_line_count"),&Label::get_visible_line_count);
+ ClassDB::bind_method(D_METHOD("get_total_character_count"),&Label::get_total_character_count);
+ ClassDB::bind_method(D_METHOD("set_visible_characters","amount"),&Label::set_visible_characters);
+ ClassDB::bind_method(D_METHOD("get_visible_characters"),&Label::get_visible_characters);
+ ClassDB::bind_method(D_METHOD("set_percent_visible","percent_visible"),&Label::set_percent_visible);
+ ClassDB::bind_method(D_METHOD("get_percent_visible"),&Label::get_percent_visible);
+ ClassDB::bind_method(D_METHOD("set_lines_skipped","lines_skipped"),&Label::set_lines_skipped);
+ ClassDB::bind_method(D_METHOD("get_lines_skipped"),&Label::get_lines_skipped);
+ ClassDB::bind_method(D_METHOD("set_max_lines_visible","lines_visible"),&Label::set_max_lines_visible);
+ ClassDB::bind_method(D_METHOD("get_max_lines_visible"),&Label::get_max_lines_visible);
BIND_CONSTANT( ALIGN_LEFT );
BIND_CONSTANT( ALIGN_CENTER );
@@ -683,15 +683,15 @@ void Label::_bind_methods() {
BIND_CONSTANT( VALIGN_BOTTOM );
BIND_CONSTANT( VALIGN_FILL );
- ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL), _SCS("set_text"),_SCS("get_text") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "align", PROPERTY_HINT_ENUM,"Left,Center,Right,Fill" ),_SCS("set_align"),_SCS("get_align") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "valign", PROPERTY_HINT_ENUM,"Top,Center,Bottom,Fill" ),_SCS("set_valign"),_SCS("get_valign") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "autowrap"),_SCS("set_autowrap"),_SCS("has_autowrap") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "clip_text"),_SCS("set_clip_text"),_SCS("is_clipping_text") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "uppercase"),_SCS("set_uppercase"),_SCS("is_uppercase") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_percent_visible"),_SCS("get_percent_visible") );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE,"0,999,1"),_SCS("set_lines_skipped"),_SCS("get_lines_skipped") );
- ADD_PROPERTY( PropertyInfo( Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE,"-1,999,1"),_SCS("set_max_lines_visible"),_SCS("get_max_lines_visible") );
+ ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL), "set_text","get_text") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "align", PROPERTY_HINT_ENUM,"Left,Center,Right,Fill" ),"set_align","get_align") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "valign", PROPERTY_HINT_ENUM,"Top,Center,Bottom,Fill" ),"set_valign","get_valign") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "autowrap"),"set_autowrap","has_autowrap") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "clip_text"),"set_clip_text","is_clipping_text") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "uppercase"),"set_uppercase","is_uppercase") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE,"0,1,0.001"),"set_percent_visible","get_percent_visible") ;
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE,"0,999,1"),"set_lines_skipped","get_lines_skipped") ;
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE,"-1,999,1"),"set_max_lines_visible","get_max_lines_visible") ;
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index fe242ee708..7f61cf80ec 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -33,7 +33,7 @@
#include "label.h"
#include "translation.h"
#ifdef TOOLS_ENABLED
-#include "tools/editor/editor_settings.h"
+#include "editor/editor_settings.h"
#endif
static bool _is_text_char(CharType c) {
@@ -1256,42 +1256,42 @@ void LineEdit::_text_changed() {
void LineEdit::_bind_methods() {
- ClassDB::bind_method(_MD("_toggle_draw_caret"),&LineEdit::_toggle_draw_caret);
+ ClassDB::bind_method(D_METHOD("_toggle_draw_caret"),&LineEdit::_toggle_draw_caret);
#ifdef TOOLS_ENABLED
ClassDB::bind_method("_editor_settings_changed",&LineEdit::_editor_settings_changed);
#endif
- ClassDB::bind_method(_MD("set_align", "align"), &LineEdit::set_align);
- ClassDB::bind_method(_MD("get_align"), &LineEdit::get_align);
-
- ClassDB::bind_method(_MD("_gui_input"),&LineEdit::_gui_input);
- ClassDB::bind_method(_MD("clear"),&LineEdit::clear);
- ClassDB::bind_method(_MD("select_all"),&LineEdit::select_all);
- ClassDB::bind_method(_MD("set_text","text"),&LineEdit::set_text);
- ClassDB::bind_method(_MD("get_text"),&LineEdit::get_text);
- ClassDB::bind_method(_MD("set_placeholder","text"),&LineEdit::set_placeholder);
- ClassDB::bind_method(_MD("get_placeholder"),&LineEdit::get_placeholder);
- ClassDB::bind_method(_MD("set_placeholder_alpha","alpha"),&LineEdit::set_placeholder_alpha);
- ClassDB::bind_method(_MD("get_placeholder_alpha"),&LineEdit::get_placeholder_alpha);
- ClassDB::bind_method(_MD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos);
- ClassDB::bind_method(_MD("get_cursor_pos"),&LineEdit::get_cursor_pos);
- ClassDB::bind_method(_MD("set_expand_to_text_length","enabled"),&LineEdit::set_expand_to_text_length);
- ClassDB::bind_method(_MD("get_expand_to_text_length"),&LineEdit::get_expand_to_text_length);
- ClassDB::bind_method(_MD("cursor_set_blink_enabled", "enabled"),&LineEdit::cursor_set_blink_enabled);
- ClassDB::bind_method(_MD("cursor_get_blink_enabled"),&LineEdit::cursor_get_blink_enabled);
- ClassDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&LineEdit::cursor_set_blink_speed);
- ClassDB::bind_method(_MD("cursor_get_blink_speed"),&LineEdit::cursor_get_blink_speed);
- ClassDB::bind_method(_MD("set_max_length","chars"),&LineEdit::set_max_length);
- ClassDB::bind_method(_MD("get_max_length"),&LineEdit::get_max_length);
- ClassDB::bind_method(_MD("append_at_cursor","text"),&LineEdit::append_at_cursor);
- ClassDB::bind_method(_MD("set_editable","enabled"),&LineEdit::set_editable);
- ClassDB::bind_method(_MD("is_editable"),&LineEdit::is_editable);
- ClassDB::bind_method(_MD("set_secret","enabled"),&LineEdit::set_secret);
- ClassDB::bind_method(_MD("is_secret"),&LineEdit::is_secret);
- ClassDB::bind_method(_MD("select","from","to"),&LineEdit::select,DEFVAL(0),DEFVAL(-1));
- ClassDB::bind_method(_MD("menu_option","option"),&LineEdit::menu_option);
- ClassDB::bind_method(_MD("get_menu:PopupMenu"),&LineEdit::get_menu);
+ ClassDB::bind_method(D_METHOD("set_align", "align"), &LineEdit::set_align);
+ ClassDB::bind_method(D_METHOD("get_align"), &LineEdit::get_align);
+
+ ClassDB::bind_method(D_METHOD("_gui_input"),&LineEdit::_gui_input);
+ ClassDB::bind_method(D_METHOD("clear"),&LineEdit::clear);
+ ClassDB::bind_method(D_METHOD("select_all"),&LineEdit::select_all);
+ ClassDB::bind_method(D_METHOD("set_text","text"),&LineEdit::set_text);
+ ClassDB::bind_method(D_METHOD("get_text"),&LineEdit::get_text);
+ ClassDB::bind_method(D_METHOD("set_placeholder","text"),&LineEdit::set_placeholder);
+ ClassDB::bind_method(D_METHOD("get_placeholder"),&LineEdit::get_placeholder);
+ ClassDB::bind_method(D_METHOD("set_placeholder_alpha","alpha"),&LineEdit::set_placeholder_alpha);
+ ClassDB::bind_method(D_METHOD("get_placeholder_alpha"),&LineEdit::get_placeholder_alpha);
+ ClassDB::bind_method(D_METHOD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos);
+ ClassDB::bind_method(D_METHOD("get_cursor_pos"),&LineEdit::get_cursor_pos);
+ ClassDB::bind_method(D_METHOD("set_expand_to_text_length","enabled"),&LineEdit::set_expand_to_text_length);
+ ClassDB::bind_method(D_METHOD("get_expand_to_text_length"),&LineEdit::get_expand_to_text_length);
+ ClassDB::bind_method(D_METHOD("cursor_set_blink_enabled", "enabled"),&LineEdit::cursor_set_blink_enabled);
+ ClassDB::bind_method(D_METHOD("cursor_get_blink_enabled"),&LineEdit::cursor_get_blink_enabled);
+ ClassDB::bind_method(D_METHOD("cursor_set_blink_speed", "blink_speed"),&LineEdit::cursor_set_blink_speed);
+ ClassDB::bind_method(D_METHOD("cursor_get_blink_speed"),&LineEdit::cursor_get_blink_speed);
+ ClassDB::bind_method(D_METHOD("set_max_length","chars"),&LineEdit::set_max_length);
+ ClassDB::bind_method(D_METHOD("get_max_length"),&LineEdit::get_max_length);
+ ClassDB::bind_method(D_METHOD("append_at_cursor","text"),&LineEdit::append_at_cursor);
+ ClassDB::bind_method(D_METHOD("set_editable","enabled"),&LineEdit::set_editable);
+ ClassDB::bind_method(D_METHOD("is_editable"),&LineEdit::is_editable);
+ ClassDB::bind_method(D_METHOD("set_secret","enabled"),&LineEdit::set_secret);
+ ClassDB::bind_method(D_METHOD("is_secret"),&LineEdit::is_secret);
+ ClassDB::bind_method(D_METHOD("select","from","to"),&LineEdit::select,DEFVAL(0),DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("menu_option","option"),&LineEdit::menu_option);
+ ClassDB::bind_method(D_METHOD("get_menu:PopupMenu"),&LineEdit::get_menu);
ADD_SIGNAL( MethodInfo("text_changed", PropertyInfo( Variant::STRING, "text" )) );
ADD_SIGNAL( MethodInfo("text_entered", PropertyInfo( Variant::STRING, "text" )) );
@@ -1309,19 +1309,19 @@ void LineEdit::_bind_methods() {
BIND_CONSTANT( MENU_UNDO );
BIND_CONSTANT( MENU_MAX );
- ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") );
- ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), _SCS("set_align"), _SCS("get_align"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") );
- ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") );
- ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "expand_to_len" ), _SCS("set_expand_to_text_length"),_SCS("get_expand_to_text_length") );
- ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") );
+ ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text" ), "set_text","get_text") ;
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "max_length" ), "set_max_length","get_max_length") ;
+ ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "editable" ), "set_editable","is_editable") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "secret" ), "set_secret","is_secret") ;
+ ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "expand_to_len" ), "set_expand_to_text_length","get_expand_to_text_length") ;
+ ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), "set_focus_mode", "get_focus_mode") ;
ADD_GROUP("Placeholder","placeholder_");
- ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "placeholder_text" ), _SCS("set_placeholder"),_SCS("get_placeholder") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::REAL, "placeholder_alpha",PROPERTY_HINT_RANGE,"0,1,0.001" ), _SCS("set_placeholder_alpha"),_SCS("get_placeholder_alpha") );
+ ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "placeholder_text" ), "set_placeholder","get_placeholder") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::REAL, "placeholder_alpha",PROPERTY_HINT_RANGE,"0,1,0.001" ), "set_placeholder_alpha","get_placeholder_alpha") ;
ADD_GROUP("Caret","caret_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), "cursor_set_blink_speed","cursor_get_blink_speed") ;
}
LineEdit::LineEdit() {
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 5b791064a8..7ea88f35f3 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -130,19 +130,19 @@ void LinkButton::_notification(int p_what) {
void LinkButton::_bind_methods() {
- ClassDB::bind_method(_MD("set_text","text"),&LinkButton::set_text);
- ClassDB::bind_method(_MD("get_text"),&LinkButton::get_text);
+ ClassDB::bind_method(D_METHOD("set_text","text"),&LinkButton::set_text);
+ ClassDB::bind_method(D_METHOD("get_text"),&LinkButton::get_text);
- ClassDB::bind_method(_MD("set_underline_mode","underline_mode"),&LinkButton::set_underline_mode);
- ClassDB::bind_method(_MD("get_underline_mode"),&LinkButton::get_underline_mode);
+ ClassDB::bind_method(D_METHOD("set_underline_mode","underline_mode"),&LinkButton::set_underline_mode);
+ ClassDB::bind_method(D_METHOD("get_underline_mode"),&LinkButton::get_underline_mode);
BIND_CONSTANT( UNDERLINE_MODE_ALWAYS );
BIND_CONSTANT( UNDERLINE_MODE_ON_HOVER );
BIND_CONSTANT( UNDERLINE_MODE_NEVER );
- ADD_PROPERTYNZ(PropertyInfo(Variant::STRING,"text"), _SCS("set_text"), _SCS("get_text"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"underline",PROPERTY_HINT_ENUM,"Always,On Hover,Never"), _SCS("set_underline_mode"), _SCS("get_underline_mode"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::STRING,"text"), "set_text", "get_text");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"underline",PROPERTY_HINT_ENUM,"Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
}
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 4a366c55c6..f15b864b95 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -98,12 +98,12 @@ void MenuButton::_set_items(const Array& p_items) {
void MenuButton::_bind_methods() {
- ClassDB::bind_method(_MD("get_popup:PopupMenu"),&MenuButton::get_popup);
- ClassDB::bind_method(_MD("_unhandled_key_input"),&MenuButton::_unhandled_key_input);
- ClassDB::bind_method(_MD("_set_items"),&MenuButton::_set_items);
- ClassDB::bind_method(_MD("_get_items"),&MenuButton::_get_items);
+ ClassDB::bind_method(D_METHOD("get_popup:PopupMenu"),&MenuButton::get_popup);
+ ClassDB::bind_method(D_METHOD("_unhandled_key_input"),&MenuButton::_unhandled_key_input);
+ ClassDB::bind_method(D_METHOD("_set_items"),&MenuButton::_set_items);
+ ClassDB::bind_method(D_METHOD("_get_items"),&MenuButton::_get_items);
- ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_items"),_SCS("_get_items") );
+ ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_items","_get_items") ;
ADD_SIGNAL( MethodInfo("about_to_show") );
}
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 1b5b21ae92..9ead79b491 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -287,35 +287,35 @@ void OptionButton::get_translatable_strings(List<String> *p_strings) const {
void OptionButton::_bind_methods() {
- ClassDB::bind_method(_MD("_selected"),&OptionButton::_selected);
-
- ClassDB::bind_method(_MD("add_item","label","id"),&OptionButton::add_item,DEFVAL(-1));
- ClassDB::bind_method(_MD("add_icon_item","texture:Texture","label","id"),&OptionButton::add_icon_item);
- ClassDB::bind_method(_MD("set_item_text","idx","text"),&OptionButton::set_item_text);
- ClassDB::bind_method(_MD("set_item_icon","idx","texture:Texture"),&OptionButton::set_item_icon);
- ClassDB::bind_method(_MD("set_item_disabled","idx","disabled"),&OptionButton::set_item_disabled);
- ClassDB::bind_method(_MD("set_item_ID","idx","id"),&OptionButton::set_item_ID);
- ClassDB::bind_method(_MD("set_item_metadata","idx","metadata"),&OptionButton::set_item_metadata);
- ClassDB::bind_method(_MD("get_item_text","idx"),&OptionButton::get_item_text);
- ClassDB::bind_method(_MD("get_item_icon:Texture","idx"),&OptionButton::get_item_icon);
- ClassDB::bind_method(_MD("get_item_ID","idx"),&OptionButton::get_item_ID);
- ClassDB::bind_method(_MD("get_item_metadata","idx"),&OptionButton::get_item_metadata);
- ClassDB::bind_method(_MD("is_item_disabled","idx"),&OptionButton::is_item_disabled);
- ClassDB::bind_method(_MD("get_item_count"),&OptionButton::get_item_count);
- ClassDB::bind_method(_MD("add_separator"),&OptionButton::add_separator);
- ClassDB::bind_method(_MD("clear"),&OptionButton::clear);
- ClassDB::bind_method(_MD("select","idx"),&OptionButton::select);
- ClassDB::bind_method(_MD("get_selected"),&OptionButton::get_selected);
- ClassDB::bind_method(_MD("get_selected_ID"),&OptionButton::get_selected_ID);
- ClassDB::bind_method(_MD("get_selected_metadata"),&OptionButton::get_selected_metadata);
- ClassDB::bind_method(_MD("remove_item","idx"),&OptionButton::remove_item);
- ClassDB::bind_method(_MD("_select_int"),&OptionButton::_select_int);
-
- ClassDB::bind_method(_MD("_set_items"),&OptionButton::_set_items);
- ClassDB::bind_method(_MD("_get_items"),&OptionButton::_get_items);
-
- ADD_PROPERTY( PropertyInfo(Variant::INT,"selected"), _SCS("_select_int"),_SCS("get_selected") );
- ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_items"),_SCS("_get_items") );
+ ClassDB::bind_method(D_METHOD("_selected"),&OptionButton::_selected);
+
+ ClassDB::bind_method(D_METHOD("add_item","label","id"),&OptionButton::add_item,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_icon_item","texture:Texture","label","id"),&OptionButton::add_icon_item);
+ ClassDB::bind_method(D_METHOD("set_item_text","idx","text"),&OptionButton::set_item_text);
+ ClassDB::bind_method(D_METHOD("set_item_icon","idx","texture:Texture"),&OptionButton::set_item_icon);
+ ClassDB::bind_method(D_METHOD("set_item_disabled","idx","disabled"),&OptionButton::set_item_disabled);
+ ClassDB::bind_method(D_METHOD("set_item_ID","idx","id"),&OptionButton::set_item_ID);
+ ClassDB::bind_method(D_METHOD("set_item_metadata","idx","metadata"),&OptionButton::set_item_metadata);
+ ClassDB::bind_method(D_METHOD("get_item_text","idx"),&OptionButton::get_item_text);
+ ClassDB::bind_method(D_METHOD("get_item_icon:Texture","idx"),&OptionButton::get_item_icon);
+ ClassDB::bind_method(D_METHOD("get_item_ID","idx"),&OptionButton::get_item_ID);
+ ClassDB::bind_method(D_METHOD("get_item_metadata","idx"),&OptionButton::get_item_metadata);
+ ClassDB::bind_method(D_METHOD("is_item_disabled","idx"),&OptionButton::is_item_disabled);
+ ClassDB::bind_method(D_METHOD("get_item_count"),&OptionButton::get_item_count);
+ ClassDB::bind_method(D_METHOD("add_separator"),&OptionButton::add_separator);
+ ClassDB::bind_method(D_METHOD("clear"),&OptionButton::clear);
+ ClassDB::bind_method(D_METHOD("select","idx"),&OptionButton::select);
+ ClassDB::bind_method(D_METHOD("get_selected"),&OptionButton::get_selected);
+ ClassDB::bind_method(D_METHOD("get_selected_ID"),&OptionButton::get_selected_ID);
+ ClassDB::bind_method(D_METHOD("get_selected_metadata"),&OptionButton::get_selected_metadata);
+ ClassDB::bind_method(D_METHOD("remove_item","idx"),&OptionButton::remove_item);
+ ClassDB::bind_method(D_METHOD("_select_int"),&OptionButton::_select_int);
+
+ ClassDB::bind_method(D_METHOD("_set_items"),&OptionButton::_set_items);
+ ClassDB::bind_method(D_METHOD("_get_items"),&OptionButton::_get_items);
+
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"selected"), "_select_int","get_selected") ;
+ ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_items","_get_items") ;
ADD_SIGNAL( MethodInfo("item_selected", PropertyInfo( Variant::INT,"ID") ) );
}
diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/patch_9_rect.cpp
index 4e1856778e..6fb35f72e5 100644
--- a/scene/gui/patch_9_rect.cpp
+++ b/scene/gui/patch_9_rect.cpp
@@ -68,26 +68,26 @@ Size2 NinePatchRect::get_minimum_size() const {
void NinePatchRect::_bind_methods() {
- ClassDB::bind_method(_MD("set_texture","texture"), & NinePatchRect::set_texture );
- ClassDB::bind_method(_MD("get_texture"), & NinePatchRect::get_texture );
- ClassDB::bind_method(_MD("set_patch_margin","margin","value"), & NinePatchRect::set_patch_margin );
- ClassDB::bind_method(_MD("get_patch_margin","margin"), & NinePatchRect::get_patch_margin );
- ClassDB::bind_method(_MD("set_region_rect","rect"),&NinePatchRect::set_region_rect);
- ClassDB::bind_method(_MD("get_region_rect"),&NinePatchRect::get_region_rect);
- ClassDB::bind_method(_MD("set_draw_center","draw_center"), & NinePatchRect::set_draw_center );
- ClassDB::bind_method(_MD("get_draw_center"), & NinePatchRect::get_draw_center );
+ ClassDB::bind_method(D_METHOD("set_texture","texture"), & NinePatchRect::set_texture );
+ ClassDB::bind_method(D_METHOD("get_texture"), & NinePatchRect::get_texture );
+ ClassDB::bind_method(D_METHOD("set_patch_margin","margin","value"), & NinePatchRect::set_patch_margin );
+ ClassDB::bind_method(D_METHOD("get_patch_margin","margin"), & NinePatchRect::get_patch_margin );
+ ClassDB::bind_method(D_METHOD("set_region_rect","rect"),&NinePatchRect::set_region_rect);
+ ClassDB::bind_method(D_METHOD("get_region_rect"),&NinePatchRect::get_region_rect);
+ ClassDB::bind_method(D_METHOD("set_draw_center","draw_center"), & NinePatchRect::set_draw_center );
+ ClassDB::bind_method(D_METHOD("get_draw_center"), & NinePatchRect::get_draw_center );
ADD_SIGNAL(MethodInfo("texture_changed"));
- ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") );
- ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture","get_texture") ;
+ ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), "set_draw_center","get_draw_center") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), "set_region_rect","get_region_rect");
ADD_GROUP("Patch Margin","patch_margin_");
- ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT );
- ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP );
- ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT );
- ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_bottom",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_BOTTOM );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_left",PROPERTY_HINT_RANGE,"0,16384,1"), "set_patch_margin","get_patch_margin",MARGIN_LEFT );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_top",PROPERTY_HINT_RANGE,"0,16384,1"), "set_patch_margin","get_patch_margin",MARGIN_TOP );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_right",PROPERTY_HINT_RANGE,"0,16384,1"), "set_patch_margin","get_patch_margin",MARGIN_RIGHT );
+ ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin_bottom",PROPERTY_HINT_RANGE,"0,16384,1"), "set_patch_margin","get_patch_margin",MARGIN_BOTTOM );
}
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 3f0f76f184..1f0daa99ba 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -226,12 +226,16 @@ void Popup::popup_centered_ratio(float p_screen_ratio) {
}
-void Popup::popup() {
+void Popup::popup(const Rect2& bounds) {
emit_signal("about_to_show");
show_modal(exclusive);
-
+ // Fit the popup into the optionally provided bounds.
+ if (!bounds.has_no_area()) {
+ set_pos(bounds.pos);
+ set_size(bounds.size);
+ }
_fix_size();
Control *focusable = find_next_valid_focus();
@@ -257,16 +261,16 @@ bool Popup::is_exclusive() const {
void Popup::_bind_methods() {
- ClassDB::bind_method(_MD("popup_centered","size"),&Popup::popup_centered,DEFVAL(Size2()));
- ClassDB::bind_method(_MD("popup_centered_ratio","ratio"),&Popup::popup_centered_ratio,DEFVAL(0.75));
- ClassDB::bind_method(_MD("popup_centered_minsize","minsize"),&Popup::popup_centered_minsize,DEFVAL(Size2()));
- ClassDB::bind_method(_MD("popup"),&Popup::popup);
- ClassDB::bind_method(_MD("set_exclusive","enable"),&Popup::set_exclusive);
- ClassDB::bind_method(_MD("is_exclusive"),&Popup::is_exclusive);
+ ClassDB::bind_method(D_METHOD("popup_centered","size"),&Popup::popup_centered,DEFVAL(Size2()));
+ ClassDB::bind_method(D_METHOD("popup_centered_ratio","ratio"),&Popup::popup_centered_ratio,DEFVAL(0.75));
+ ClassDB::bind_method(D_METHOD("popup_centered_minsize","minsize"),&Popup::popup_centered_minsize,DEFVAL(Size2()));
+ ClassDB::bind_method(D_METHOD("popup","bounds"),&Popup::popup,DEFVAL(Rect2()));
+ ClassDB::bind_method(D_METHOD("set_exclusive","enable"),&Popup::set_exclusive);
+ ClassDB::bind_method(D_METHOD("is_exclusive"),&Popup::is_exclusive);
ADD_SIGNAL( MethodInfo("about_to_show") );
ADD_SIGNAL( MethodInfo("popup_hide") );
ADD_GROUP("Popup","popup_");
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "popup_exclusive"), _SCS("set_exclusive"),_SCS("is_exclusive") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "popup_exclusive"), "set_exclusive","is_exclusive") ;
BIND_CONSTANT(NOTIFICATION_POST_POPUP);
BIND_CONSTANT(NOTIFICATION_POPUP_HIDE);
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index 17ae4a938a..4e4c8b0292 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -47,7 +47,7 @@ protected:
void _gui_input(InputEvent p_event);
void _notification(int p_what);
- void _fix_size();
+ virtual void _fix_size();
static void _bind_methods();
public:
@@ -63,7 +63,7 @@ public:
void popup_centered(const Size2& p_size=Size2());
void popup_centered_minsize(const Size2& p_minsize=Size2());
void set_as_minsize();
- virtual void popup();
+ virtual void popup(const Rect2& p_bounds=Rect2());
virtual String get_configuration_warning() const;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 65e7c3ab39..884cf0312a 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1114,64 +1114,64 @@ void PopupMenu::clear_autohide_areas(){
void PopupMenu::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&PopupMenu::_gui_input);
- ClassDB::bind_method(_MD("add_icon_item","texture","label","id","accel"),&PopupMenu::add_icon_item,DEFVAL(-1),DEFVAL(0));
- ClassDB::bind_method(_MD("add_item","label","id","accel"),&PopupMenu::add_item,DEFVAL(-1),DEFVAL(0));
- ClassDB::bind_method(_MD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0));
- ClassDB::bind_method(_MD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0));
- ClassDB::bind_method(_MD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1));
-
- ClassDB::bind_method(_MD("add_icon_shortcut","texture","shortcut:ShortCut","id","global"),&PopupMenu::add_icon_shortcut,DEFVAL(-1),DEFVAL(false));
- ClassDB::bind_method(_MD("add_shortcut","shortcut:ShortCut","id","global"),&PopupMenu::add_shortcut,DEFVAL(-1),DEFVAL(false));
- ClassDB::bind_method(_MD("add_icon_check_shortcut","texture","shortcut:ShortCut","id","global"),&PopupMenu::add_icon_check_shortcut,DEFVAL(-1),DEFVAL(false));
- ClassDB::bind_method(_MD("add_check_shortcut","shortcut:ShortCut","id","global"),&PopupMenu::add_check_shortcut,DEFVAL(-1),DEFVAL(false));
-
- ClassDB::bind_method(_MD("set_item_text","idx","text"),&PopupMenu::set_item_text);
- ClassDB::bind_method(_MD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon);
- ClassDB::bind_method(_MD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked);
- ClassDB::bind_method(_MD("set_item_ID","idx","id"),&PopupMenu::set_item_ID);
- ClassDB::bind_method(_MD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator);
- ClassDB::bind_method(_MD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata);
- ClassDB::bind_method(_MD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled);
- ClassDB::bind_method(_MD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu);
- ClassDB::bind_method(_MD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator);
- ClassDB::bind_method(_MD("set_item_as_checkable","idx","enable"),&PopupMenu::set_item_as_checkable);
- ClassDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&PopupMenu::set_item_tooltip);
- ClassDB::bind_method(_MD("set_item_shortcut","idx","shortcut:ShortCut","global"),&PopupMenu::set_item_shortcut,DEFVAL(false));
-
- ClassDB::bind_method(_MD("toggle_item_checked","idx"), &PopupMenu::toggle_item_checked);
-
- ClassDB::bind_method(_MD("get_item_text","idx"),&PopupMenu::get_item_text);
- ClassDB::bind_method(_MD("get_item_icon","idx"),&PopupMenu::get_item_icon);
- ClassDB::bind_method(_MD("is_item_checked","idx"),&PopupMenu::is_item_checked);
- ClassDB::bind_method(_MD("get_item_ID","idx"),&PopupMenu::get_item_ID);
- ClassDB::bind_method(_MD("get_item_index","id"),&PopupMenu::get_item_index);
- ClassDB::bind_method(_MD("get_item_accelerator","idx"),&PopupMenu::get_item_accelerator);
- ClassDB::bind_method(_MD("get_item_metadata","idx"),&PopupMenu::get_item_metadata);
- ClassDB::bind_method(_MD("is_item_disabled","idx"),&PopupMenu::is_item_disabled);
- ClassDB::bind_method(_MD("get_item_submenu","idx"),&PopupMenu::get_item_submenu);
- ClassDB::bind_method(_MD("is_item_separator","idx"),&PopupMenu::is_item_separator);
- ClassDB::bind_method(_MD("is_item_checkable","idx"),&PopupMenu::is_item_checkable);
- ClassDB::bind_method(_MD("get_item_tooltip","idx"),&PopupMenu::get_item_tooltip);
- ClassDB::bind_method(_MD("get_item_shortcut:ShortCut","idx"),&PopupMenu::get_item_shortcut);
-
- ClassDB::bind_method(_MD("get_item_count"),&PopupMenu::get_item_count);
-
- ClassDB::bind_method(_MD("remove_item","idx"),&PopupMenu::remove_item);
-
- ClassDB::bind_method(_MD("add_separator"),&PopupMenu::add_separator);
- ClassDB::bind_method(_MD("clear"),&PopupMenu::clear);
-
- ClassDB::bind_method(_MD("_set_items"),&PopupMenu::_set_items);
- ClassDB::bind_method(_MD("_get_items"),&PopupMenu::_get_items);
-
- ClassDB::bind_method(_MD("set_hide_on_item_selection","enable"),&PopupMenu::set_hide_on_item_selection);
- ClassDB::bind_method(_MD("is_hide_on_item_selection"),&PopupMenu::is_hide_on_item_selection);
-
- ClassDB::bind_method(_MD("_submenu_timeout"),&PopupMenu::_submenu_timeout);
-
- ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_items"),_SCS("_get_items") );
- ADD_PROPERTYNO( PropertyInfo(Variant::BOOL, "hide_on_item_selection" ), _SCS("set_hide_on_item_selection"), _SCS("is_hide_on_item_selection") );
+ ClassDB::bind_method(D_METHOD("_gui_input"),&PopupMenu::_gui_input);
+ ClassDB::bind_method(D_METHOD("add_icon_item","texture","label","id","accel"),&PopupMenu::add_icon_item,DEFVAL(-1),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_item","label","id","accel"),&PopupMenu::add_item,DEFVAL(-1),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_icon_check_item","texture","label","id","accel"),&PopupMenu::add_icon_check_item,DEFVAL(-1),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_check_item","label","id","accel"),&PopupMenu::add_check_item,DEFVAL(-1),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("add_submenu_item","label","submenu","id"),&PopupMenu::add_submenu_item,DEFVAL(-1));
+
+ ClassDB::bind_method(D_METHOD("add_icon_shortcut","texture","shortcut:ShortCut","id","global"),&PopupMenu::add_icon_shortcut,DEFVAL(-1),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_shortcut","shortcut:ShortCut","id","global"),&PopupMenu::add_shortcut,DEFVAL(-1),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_icon_check_shortcut","texture","shortcut:ShortCut","id","global"),&PopupMenu::add_icon_check_shortcut,DEFVAL(-1),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_check_shortcut","shortcut:ShortCut","id","global"),&PopupMenu::add_check_shortcut,DEFVAL(-1),DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("set_item_text","idx","text"),&PopupMenu::set_item_text);
+ ClassDB::bind_method(D_METHOD("set_item_icon","idx","icon"),&PopupMenu::set_item_icon);
+ ClassDB::bind_method(D_METHOD("set_item_checked","idx","checked"),&PopupMenu::set_item_checked);
+ ClassDB::bind_method(D_METHOD("set_item_ID","idx","id"),&PopupMenu::set_item_ID);
+ ClassDB::bind_method(D_METHOD("set_item_accelerator","idx","accel"),&PopupMenu::set_item_accelerator);
+ ClassDB::bind_method(D_METHOD("set_item_metadata","idx","metadata"),&PopupMenu::set_item_metadata);
+ ClassDB::bind_method(D_METHOD("set_item_disabled","idx","disabled"),&PopupMenu::set_item_disabled);
+ ClassDB::bind_method(D_METHOD("set_item_submenu","idx","submenu"),&PopupMenu::set_item_submenu);
+ ClassDB::bind_method(D_METHOD("set_item_as_separator","idx","enable"),&PopupMenu::set_item_as_separator);
+ ClassDB::bind_method(D_METHOD("set_item_as_checkable","idx","enable"),&PopupMenu::set_item_as_checkable);
+ ClassDB::bind_method(D_METHOD("set_item_tooltip","idx","tooltip"),&PopupMenu::set_item_tooltip);
+ ClassDB::bind_method(D_METHOD("set_item_shortcut","idx","shortcut:ShortCut","global"),&PopupMenu::set_item_shortcut,DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("toggle_item_checked","idx"), &PopupMenu::toggle_item_checked);
+
+ ClassDB::bind_method(D_METHOD("get_item_text","idx"),&PopupMenu::get_item_text);
+ ClassDB::bind_method(D_METHOD("get_item_icon","idx"),&PopupMenu::get_item_icon);
+ ClassDB::bind_method(D_METHOD("is_item_checked","idx"),&PopupMenu::is_item_checked);
+ ClassDB::bind_method(D_METHOD("get_item_ID","idx"),&PopupMenu::get_item_ID);
+ ClassDB::bind_method(D_METHOD("get_item_index","id"),&PopupMenu::get_item_index);
+ ClassDB::bind_method(D_METHOD("get_item_accelerator","idx"),&PopupMenu::get_item_accelerator);
+ ClassDB::bind_method(D_METHOD("get_item_metadata","idx"),&PopupMenu::get_item_metadata);
+ ClassDB::bind_method(D_METHOD("is_item_disabled","idx"),&PopupMenu::is_item_disabled);
+ ClassDB::bind_method(D_METHOD("get_item_submenu","idx"),&PopupMenu::get_item_submenu);
+ ClassDB::bind_method(D_METHOD("is_item_separator","idx"),&PopupMenu::is_item_separator);
+ ClassDB::bind_method(D_METHOD("is_item_checkable","idx"),&PopupMenu::is_item_checkable);
+ ClassDB::bind_method(D_METHOD("get_item_tooltip","idx"),&PopupMenu::get_item_tooltip);
+ ClassDB::bind_method(D_METHOD("get_item_shortcut:ShortCut","idx"),&PopupMenu::get_item_shortcut);
+
+ ClassDB::bind_method(D_METHOD("get_item_count"),&PopupMenu::get_item_count);
+
+ ClassDB::bind_method(D_METHOD("remove_item","idx"),&PopupMenu::remove_item);
+
+ ClassDB::bind_method(D_METHOD("add_separator"),&PopupMenu::add_separator);
+ ClassDB::bind_method(D_METHOD("clear"),&PopupMenu::clear);
+
+ ClassDB::bind_method(D_METHOD("_set_items"),&PopupMenu::_set_items);
+ ClassDB::bind_method(D_METHOD("_get_items"),&PopupMenu::_get_items);
+
+ ClassDB::bind_method(D_METHOD("set_hide_on_item_selection","enable"),&PopupMenu::set_hide_on_item_selection);
+ ClassDB::bind_method(D_METHOD("is_hide_on_item_selection"),&PopupMenu::is_hide_on_item_selection);
+
+ ClassDB::bind_method(D_METHOD("_submenu_timeout"),&PopupMenu::_submenu_timeout);
+
+ ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"items",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_items","_get_items") ;
+ ADD_PROPERTYNO( PropertyInfo(Variant::BOOL, "hide_on_item_selection" ), "set_hide_on_item_selection", "is_hide_on_item_selection") ;
ADD_SIGNAL( MethodInfo("id_pressed", PropertyInfo( Variant::INT,"ID") ) );
ADD_SIGNAL( MethodInfo("index_pressed", PropertyInfo( Variant::INT,"index") ) );
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index 0f99d4f19e..61776d3ae6 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -82,10 +82,10 @@ bool ProgressBar::is_percent_visible() const{
void ProgressBar::_bind_methods() {
- ClassDB::bind_method(_MD("set_percent_visible","visible"),&ProgressBar::set_percent_visible);
- ClassDB::bind_method(_MD("is_percent_visible"),&ProgressBar::is_percent_visible);
+ ClassDB::bind_method(D_METHOD("set_percent_visible","visible"),&ProgressBar::set_percent_visible);
+ ClassDB::bind_method(D_METHOD("is_percent_visible"),&ProgressBar::is_percent_visible);
ADD_GROUP("Percent","percent_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"percent_visible"),_SCS("set_percent_visible"),_SCS("is_percent_visible"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"percent_visible"),"set_percent_visible","is_percent_visible");
}
ProgressBar::ProgressBar() {
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 5ecafccaca..f434aff08d 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -222,36 +222,36 @@ void Range::_unref_shared() {
void Range::_bind_methods() {
- ClassDB::bind_method(_MD("get_value"),&Range::get_value);
- ClassDB::bind_method(_MD("get_min"),&Range::get_min);
- ClassDB::bind_method(_MD("get_max"),&Range::get_max);
- ClassDB::bind_method(_MD("get_step"),&Range::get_step);
- ClassDB::bind_method(_MD("get_page"),&Range::get_page);
- ClassDB::bind_method(_MD("get_as_ratio"),&Range::get_as_ratio);
- ClassDB::bind_method(_MD("set_value","value"),&Range::set_value);
- ClassDB::bind_method(_MD("set_min","minimum"),&Range::set_min);
- ClassDB::bind_method(_MD("set_max","maximum"),&Range::set_max);
- ClassDB::bind_method(_MD("set_step","step"),&Range::set_step);
- ClassDB::bind_method(_MD("set_page","pagesize"),&Range::set_page);
- ClassDB::bind_method(_MD("set_as_ratio","value"),&Range::set_as_ratio);
- ClassDB::bind_method(_MD("set_use_rounded_values","enabled"),&Range::set_use_rounded_values);
- ClassDB::bind_method(_MD("is_using_rounded_values"),&Range::is_using_rounded_values);
- ClassDB::bind_method(_MD("set_exp_ratio","enabled"),&Range::set_exp_ratio);
- ClassDB::bind_method(_MD("is_ratio_exp"),&Range::is_ratio_exp);
-
- ClassDB::bind_method(_MD("share","with"),&Range::_share);
- ClassDB::bind_method(_MD("unshare"),&Range::unshare);
+ ClassDB::bind_method(D_METHOD("get_value"),&Range::get_value);
+ ClassDB::bind_method(D_METHOD("get_min"),&Range::get_min);
+ ClassDB::bind_method(D_METHOD("get_max"),&Range::get_max);
+ ClassDB::bind_method(D_METHOD("get_step"),&Range::get_step);
+ ClassDB::bind_method(D_METHOD("get_page"),&Range::get_page);
+ ClassDB::bind_method(D_METHOD("get_as_ratio"),&Range::get_as_ratio);
+ ClassDB::bind_method(D_METHOD("set_value","value"),&Range::set_value);
+ ClassDB::bind_method(D_METHOD("set_min","minimum"),&Range::set_min);
+ ClassDB::bind_method(D_METHOD("set_max","maximum"),&Range::set_max);
+ ClassDB::bind_method(D_METHOD("set_step","step"),&Range::set_step);
+ ClassDB::bind_method(D_METHOD("set_page","pagesize"),&Range::set_page);
+ ClassDB::bind_method(D_METHOD("set_as_ratio","value"),&Range::set_as_ratio);
+ ClassDB::bind_method(D_METHOD("set_use_rounded_values","enabled"),&Range::set_use_rounded_values);
+ ClassDB::bind_method(D_METHOD("is_using_rounded_values"),&Range::is_using_rounded_values);
+ ClassDB::bind_method(D_METHOD("set_exp_ratio","enabled"),&Range::set_exp_ratio);
+ ClassDB::bind_method(D_METHOD("is_ratio_exp"),&Range::is_ratio_exp);
+
+ ClassDB::bind_method(D_METHOD("share","with"),&Range::_share);
+ ClassDB::bind_method(D_METHOD("unshare"),&Range::unshare);
ADD_SIGNAL( MethodInfo("value_changed", PropertyInfo(Variant::REAL,"value")));
ADD_SIGNAL( MethodInfo("changed"));
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_value" ), _SCS("set_min"), _SCS("get_min") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_value" ), _SCS("set_max"), _SCS("get_max") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "step" ), _SCS("set_step"), _SCS("get_step") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "page" ), _SCS("set_page"), _SCS("get_page") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "value" ), _SCS("set_value"), _SCS("get_value") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "exp_edit" ), _SCS("set_exp_ratio"), _SCS("is_ratio_exp") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "rounded" ), _SCS("set_use_rounded_values"), _SCS("is_using_rounded_values") );
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "min_value" ), "set_min", "get_min") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "max_value" ), "set_max", "get_max") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "step" ), "set_step", "get_step") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "page" ), "set_page", "get_page") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "value" ), "set_value", "get_value") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "exp_edit" ), "set_exp_ratio", "is_ratio_exp") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "rounded" ), "set_use_rounded_values", "is_using_rounded_values") ;
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 5fe5f47d1b..17ec71f4a4 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1214,6 +1214,28 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline)
}
+void RichTextLabel::_remove_item(Item* p_item, const int p_line, const int p_subitem_line) {
+
+
+ int size = p_item->subitems.size();
+ if (size == 0) {
+ p_item->parent->subitems.erase(p_item);
+ if (p_item->type == ITEM_NEWLINE) {
+ current_frame->lines.remove(p_line);
+ for (int i = p_subitem_line; i < current->subitems.size(); i++) {
+ if (current->subitems[i]->line > 0)
+ current->subitems[i]->line--;
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < size; i++) {
+ _remove_item(p_item->subitems.front()->get(), p_line, p_subitem_line);
+ }
+ }
+
+}
+
void RichTextLabel::add_image(const Ref<Texture>& p_image) {
if (current->type==ITEM_TABLE)
@@ -1238,6 +1260,26 @@ void RichTextLabel::add_newline() {
}
+bool RichTextLabel::remove_line(const int p_line) {
+
+ if (p_line >= current_frame->lines.size() || p_line < 0)
+ return false;
+
+ int lines = p_line * 2;
+
+ if (current->subitems[lines]->type != ITEM_NEWLINE)
+ _remove_item(current->subitems[lines], current->subitems[lines]->line, lines);
+
+ _remove_item(current->subitems[lines], current->subitems[lines]->line, lines);
+
+ if (p_line == 0) {
+ main->lines[0].from = main;
+ }
+
+ main->first_invalid_line = 0;
+ return true;
+}
+
void RichTextLabel::push_font(const Ref<Font>& p_font) {
ERR_FAIL_COND(current->type==ITEM_TABLE);
@@ -1900,63 +1942,64 @@ String RichTextLabel::get_text() {
void RichTextLabel::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&RichTextLabel::_gui_input);
- ClassDB::bind_method(_MD("_scroll_changed"),&RichTextLabel::_scroll_changed);
- ClassDB::bind_method(_MD("get_text"),&RichTextLabel::get_text);
- ClassDB::bind_method(_MD("add_text","text"),&RichTextLabel::add_text);
- ClassDB::bind_method(_MD("add_image","image:Texture"),&RichTextLabel::add_image);
- ClassDB::bind_method(_MD("newline"),&RichTextLabel::add_newline);
- ClassDB::bind_method(_MD("push_font","font"),&RichTextLabel::push_font);
- ClassDB::bind_method(_MD("push_color","color"),&RichTextLabel::push_color);
- ClassDB::bind_method(_MD("push_align","align"),&RichTextLabel::push_align);
- ClassDB::bind_method(_MD("push_indent","level"),&RichTextLabel::push_indent);
- ClassDB::bind_method(_MD("push_list","type"),&RichTextLabel::push_list);
- ClassDB::bind_method(_MD("push_meta","data"),&RichTextLabel::push_meta);
- ClassDB::bind_method(_MD("push_underline"),&RichTextLabel::push_underline);
- ClassDB::bind_method(_MD("push_table","columns"),&RichTextLabel::push_table);
- ClassDB::bind_method(_MD("set_table_column_expand","column","expand","ratio"),&RichTextLabel::set_table_column_expand);
- ClassDB::bind_method(_MD("push_cell"),&RichTextLabel::push_cell);
- ClassDB::bind_method(_MD("pop"),&RichTextLabel::pop);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&RichTextLabel::_gui_input);
+ ClassDB::bind_method(D_METHOD("_scroll_changed"),&RichTextLabel::_scroll_changed);
+ ClassDB::bind_method(D_METHOD("get_text"),&RichTextLabel::get_text);
+ ClassDB::bind_method(D_METHOD("add_text","text"),&RichTextLabel::add_text);
+ ClassDB::bind_method(D_METHOD("add_image","image:Texture"),&RichTextLabel::add_image);
+ ClassDB::bind_method(D_METHOD("newline"),&RichTextLabel::add_newline);
+ ClassDB::bind_method(D_METHOD("remove_line"),&RichTextLabel::remove_line);
+ ClassDB::bind_method(D_METHOD("push_font","font"),&RichTextLabel::push_font);
+ ClassDB::bind_method(D_METHOD("push_color","color"),&RichTextLabel::push_color);
+ ClassDB::bind_method(D_METHOD("push_align","align"),&RichTextLabel::push_align);
+ ClassDB::bind_method(D_METHOD("push_indent","level"),&RichTextLabel::push_indent);
+ ClassDB::bind_method(D_METHOD("push_list","type"),&RichTextLabel::push_list);
+ ClassDB::bind_method(D_METHOD("push_meta","data"),&RichTextLabel::push_meta);
+ ClassDB::bind_method(D_METHOD("push_underline"),&RichTextLabel::push_underline);
+ ClassDB::bind_method(D_METHOD("push_table","columns"),&RichTextLabel::push_table);
+ ClassDB::bind_method(D_METHOD("set_table_column_expand","column","expand","ratio"),&RichTextLabel::set_table_column_expand);
+ ClassDB::bind_method(D_METHOD("push_cell"),&RichTextLabel::push_cell);
+ ClassDB::bind_method(D_METHOD("pop"),&RichTextLabel::pop);
- ClassDB::bind_method(_MD("clear"),&RichTextLabel::clear);
+ ClassDB::bind_method(D_METHOD("clear"),&RichTextLabel::clear);
- ClassDB::bind_method(_MD("set_meta_underline","enable"),&RichTextLabel::set_meta_underline);
- ClassDB::bind_method(_MD("is_meta_underlined"),&RichTextLabel::is_meta_underlined);
+ ClassDB::bind_method(D_METHOD("set_meta_underline","enable"),&RichTextLabel::set_meta_underline);
+ ClassDB::bind_method(D_METHOD("is_meta_underlined"),&RichTextLabel::is_meta_underlined);
- ClassDB::bind_method(_MD("set_scroll_active","active"),&RichTextLabel::set_scroll_active);
- ClassDB::bind_method(_MD("is_scroll_active"),&RichTextLabel::is_scroll_active);
+ ClassDB::bind_method(D_METHOD("set_scroll_active","active"),&RichTextLabel::set_scroll_active);
+ ClassDB::bind_method(D_METHOD("is_scroll_active"),&RichTextLabel::is_scroll_active);
- ClassDB::bind_method(_MD("set_scroll_follow","follow"),&RichTextLabel::set_scroll_follow);
- ClassDB::bind_method(_MD("is_scroll_following"),&RichTextLabel::is_scroll_following);
+ ClassDB::bind_method(D_METHOD("set_scroll_follow","follow"),&RichTextLabel::set_scroll_follow);
+ ClassDB::bind_method(D_METHOD("is_scroll_following"),&RichTextLabel::is_scroll_following);
- ClassDB::bind_method(_MD("get_v_scroll"),&RichTextLabel::get_v_scroll);
+ ClassDB::bind_method(D_METHOD("get_v_scroll"),&RichTextLabel::get_v_scroll);
- ClassDB::bind_method(_MD("scroll_to_line","line"),&RichTextLabel::scroll_to_line);
+ ClassDB::bind_method(D_METHOD("scroll_to_line","line"),&RichTextLabel::scroll_to_line);
- ClassDB::bind_method(_MD("set_tab_size","spaces"),&RichTextLabel::set_tab_size);
- ClassDB::bind_method(_MD("get_tab_size"),&RichTextLabel::get_tab_size);
+ ClassDB::bind_method(D_METHOD("set_tab_size","spaces"),&RichTextLabel::set_tab_size);
+ ClassDB::bind_method(D_METHOD("get_tab_size"),&RichTextLabel::get_tab_size);
- ClassDB::bind_method(_MD("set_selection_enabled","enabled"),&RichTextLabel::set_selection_enabled);
- ClassDB::bind_method(_MD("is_selection_enabled"),&RichTextLabel::is_selection_enabled);
+ ClassDB::bind_method(D_METHOD("set_selection_enabled","enabled"),&RichTextLabel::set_selection_enabled);
+ ClassDB::bind_method(D_METHOD("is_selection_enabled"),&RichTextLabel::is_selection_enabled);
- ClassDB::bind_method(_MD("parse_bbcode", "bbcode"),&RichTextLabel::parse_bbcode);
- ClassDB::bind_method(_MD("append_bbcode", "bbcode"),&RichTextLabel::append_bbcode);
+ ClassDB::bind_method(D_METHOD("parse_bbcode", "bbcode"),&RichTextLabel::parse_bbcode);
+ ClassDB::bind_method(D_METHOD("append_bbcode", "bbcode"),&RichTextLabel::append_bbcode);
- ClassDB::bind_method(_MD("set_bbcode","text"),&RichTextLabel::set_bbcode);
- ClassDB::bind_method(_MD("get_bbcode"),&RichTextLabel::get_bbcode);
+ ClassDB::bind_method(D_METHOD("set_bbcode","text"),&RichTextLabel::set_bbcode);
+ ClassDB::bind_method(D_METHOD("get_bbcode"),&RichTextLabel::get_bbcode);
- ClassDB::bind_method(_MD("set_visible_characters","amount"),&RichTextLabel::set_visible_characters);
- ClassDB::bind_method(_MD("get_visible_characters"),&RichTextLabel::get_visible_characters);
+ ClassDB::bind_method(D_METHOD("set_visible_characters","amount"),&RichTextLabel::set_visible_characters);
+ ClassDB::bind_method(D_METHOD("get_visible_characters"),&RichTextLabel::get_visible_characters);
- ClassDB::bind_method(_MD("get_total_character_count"),&RichTextLabel::get_total_character_count);
+ ClassDB::bind_method(D_METHOD("get_total_character_count"),&RichTextLabel::get_total_character_count);
- ClassDB::bind_method(_MD("set_use_bbcode","enable"),&RichTextLabel::set_use_bbcode);
- ClassDB::bind_method(_MD("is_using_bbcode"),&RichTextLabel::is_using_bbcode);
+ ClassDB::bind_method(D_METHOD("set_use_bbcode","enable"),&RichTextLabel::set_use_bbcode);
+ ClassDB::bind_method(D_METHOD("is_using_bbcode"),&RichTextLabel::is_using_bbcode);
ADD_GROUP("BBCode","bbcode_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"bbcode_enabled"),_SCS("set_use_bbcode"),_SCS("is_using_bbcode"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"bbcode_text",PROPERTY_HINT_MULTILINE_TEXT),_SCS("set_bbcode"),_SCS("get_bbcode"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"visible_characters",PROPERTY_HINT_RANGE,"-1,128000,1"),_SCS("set_visible_characters"),_SCS("get_visible_characters"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"bbcode_enabled"),"set_use_bbcode","is_using_bbcode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"bbcode_text",PROPERTY_HINT_MULTILINE_TEXT),"set_bbcode","get_bbcode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"visible_characters",PROPERTY_HINT_RANGE,"-1,128000,1"),"set_visible_characters","get_visible_characters");
ADD_SIGNAL( MethodInfo("meta_clicked",PropertyInfo(Variant::NIL,"meta")));
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 39032185f8..3bdd2cd7e3 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -173,7 +173,7 @@ private:
struct ItemNewline : public Item {
- int line;
+ int line; // FIXME: Overriding base's line ?
ItemNewline() { type=ITEM_NEWLINE; }
};
@@ -217,6 +217,7 @@ private:
void _validate_line_caches(ItemFrame *p_frame);
void _add_item(Item *p_item, bool p_enter=false,bool p_ensure_newline=false);
+ void _remove_item(Item *p_item, const int p_line, const int p_subitem_line);
@@ -284,6 +285,7 @@ public:
void add_text(const String& p_text);
void add_image(const Ref<Texture>& p_image);
void add_newline();
+ bool remove_line(const int p_line);
void push_font(const Ref<Font>& p_font);
void push_color(const Color& p_color);
void push_underline();
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index fc406ff0f5..b2ad74eaa8 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -814,13 +814,13 @@ bool ScrollBar::key(unsigned long p_unicode, unsigned long p_scan_code,bool b.pr
void ScrollBar::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&ScrollBar::_gui_input);
- ClassDB::bind_method(_MD("set_custom_step","step"),&ScrollBar::set_custom_step);
- ClassDB::bind_method(_MD("get_custom_step"),&ScrollBar::get_custom_step);
- ClassDB::bind_method(_MD("_drag_slave_input"),&ScrollBar::_drag_slave_input);
- ClassDB::bind_method(_MD("_drag_slave_exit"),&ScrollBar::_drag_slave_exit);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&ScrollBar::_gui_input);
+ ClassDB::bind_method(D_METHOD("set_custom_step","step"),&ScrollBar::set_custom_step);
+ ClassDB::bind_method(D_METHOD("get_custom_step"),&ScrollBar::get_custom_step);
+ ClassDB::bind_method(D_METHOD("_drag_slave_input"),&ScrollBar::_drag_slave_input);
+ ClassDB::bind_method(D_METHOD("_drag_slave_exit"),&ScrollBar::_drag_slave_exit);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_step",PROPERTY_HINT_RANGE,"-1,4096"), _SCS("set_custom_step"),_SCS("get_custom_step"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_step",PROPERTY_HINT_RANGE,"-1,4096"), "set_custom_step","get_custom_step");
}
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 46312933a7..2296c9742d 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -459,21 +459,21 @@ String ScrollContainer::get_configuration_warning() const {
void ScrollContainer::_bind_methods() {
- ClassDB::bind_method(_MD("_scroll_moved"),&ScrollContainer::_scroll_moved);
- ClassDB::bind_method(_MD("_gui_input"),&ScrollContainer::_gui_input);
- ClassDB::bind_method(_MD("set_enable_h_scroll","enable"),&ScrollContainer::set_enable_h_scroll);
- ClassDB::bind_method(_MD("is_h_scroll_enabled"),&ScrollContainer::is_h_scroll_enabled);
- ClassDB::bind_method(_MD("set_enable_v_scroll","enable"),&ScrollContainer::set_enable_v_scroll);
- ClassDB::bind_method(_MD("is_v_scroll_enabled"),&ScrollContainer::is_v_scroll_enabled);
- ClassDB::bind_method(_MD("_update_scrollbar_pos"),&ScrollContainer::_update_scrollbar_pos);
- ClassDB::bind_method(_MD("set_h_scroll","val"),&ScrollContainer::set_h_scroll);
- ClassDB::bind_method(_MD("get_h_scroll"),&ScrollContainer::get_h_scroll);
- ClassDB::bind_method(_MD("set_v_scroll","val"),&ScrollContainer::set_v_scroll);
- ClassDB::bind_method(_MD("get_v_scroll"),&ScrollContainer::get_v_scroll);
+ ClassDB::bind_method(D_METHOD("_scroll_moved"),&ScrollContainer::_scroll_moved);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&ScrollContainer::_gui_input);
+ ClassDB::bind_method(D_METHOD("set_enable_h_scroll","enable"),&ScrollContainer::set_enable_h_scroll);
+ ClassDB::bind_method(D_METHOD("is_h_scroll_enabled"),&ScrollContainer::is_h_scroll_enabled);
+ ClassDB::bind_method(D_METHOD("set_enable_v_scroll","enable"),&ScrollContainer::set_enable_v_scroll);
+ ClassDB::bind_method(D_METHOD("is_v_scroll_enabled"),&ScrollContainer::is_v_scroll_enabled);
+ ClassDB::bind_method(D_METHOD("_update_scrollbar_pos"),&ScrollContainer::_update_scrollbar_pos);
+ ClassDB::bind_method(D_METHOD("set_h_scroll","val"),&ScrollContainer::set_h_scroll);
+ ClassDB::bind_method(D_METHOD("get_h_scroll"),&ScrollContainer::get_h_scroll);
+ ClassDB::bind_method(D_METHOD("set_v_scroll","val"),&ScrollContainer::set_v_scroll);
+ ClassDB::bind_method(D_METHOD("get_v_scroll"),&ScrollContainer::get_v_scroll);
ADD_GROUP("Scroll","scroll_");
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll_horizontal"), _SCS("set_enable_h_scroll"),_SCS("is_h_scroll_enabled"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll_vertical"), _SCS("set_enable_v_scroll"),_SCS("is_v_scroll_enabled"));
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll_horizontal"), "set_enable_h_scroll","is_h_scroll_enabled");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "scroll_vertical"), "set_enable_v_scroll","is_v_scroll_enabled");
};
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index ad6e8786d7..a6d6864b16 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -235,16 +235,16 @@ void Slider::set_ticks_on_borders(bool _tob){
void Slider::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&Slider::_gui_input);
- ClassDB::bind_method(_MD("set_ticks","count"),&Slider::set_ticks);
- ClassDB::bind_method(_MD("get_ticks"),&Slider::get_ticks);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&Slider::_gui_input);
+ ClassDB::bind_method(D_METHOD("set_ticks","count"),&Slider::set_ticks);
+ ClassDB::bind_method(D_METHOD("get_ticks"),&Slider::get_ticks);
- ClassDB::bind_method(_MD("get_ticks_on_borders"),&Slider::get_ticks_on_borders);
- ClassDB::bind_method(_MD("set_ticks_on_borders","ticks_on_border"),&Slider::set_ticks_on_borders);
+ ClassDB::bind_method(D_METHOD("get_ticks_on_borders"),&Slider::get_ticks_on_borders);
+ ClassDB::bind_method(D_METHOD("set_ticks_on_borders","ticks_on_border"),&Slider::set_ticks_on_borders);
- ADD_PROPERTY( PropertyInfo( Variant::INT, "tick_count", PROPERTY_HINT_RANGE,"0,4096,1"), _SCS("set_ticks"), _SCS("get_ticks") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "ticks_on_borders" ), _SCS("set_ticks_on_borders"), _SCS("get_ticks_on_borders") );
- ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") );
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "tick_count", PROPERTY_HINT_RANGE,"0,4096,1"), "set_ticks", "get_ticks") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "ticks_on_borders" ), "set_ticks_on_borders", "get_ticks_on_borders") ;
+ ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), "set_focus_mode", "get_focus_mode") ;
}
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 8920f8f056..f2c04d2f76 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -100,8 +100,6 @@ void SpinBox::_gui_input(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) {
const InputEventMouseButton &mb=p_event.mouse_button;
- if (mb.doubleclick)
- return; //ignore doubleclick
bool up = mb.y < (get_size().height/2);
@@ -253,24 +251,24 @@ bool SpinBox::is_editable() const {
void SpinBox::_bind_methods() {
- //ClassDB::bind_method(_MD("_value_changed"),&SpinBox::_value_changed);
- ClassDB::bind_method(_MD("_gui_input"),&SpinBox::_gui_input);
- ClassDB::bind_method(_MD("_text_entered"),&SpinBox::_text_entered);
- ClassDB::bind_method(_MD("set_suffix","suffix"),&SpinBox::set_suffix);
- ClassDB::bind_method(_MD("get_suffix"),&SpinBox::get_suffix);
- ClassDB::bind_method(_MD("set_prefix","prefix"),&SpinBox::set_prefix);
- ClassDB::bind_method(_MD("get_prefix"),&SpinBox::get_prefix);
- ClassDB::bind_method(_MD("set_editable","editable"),&SpinBox::set_editable);
- ClassDB::bind_method(_MD("is_editable"),&SpinBox::is_editable);
- ClassDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
- ClassDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
- ClassDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
- ClassDB::bind_method(_MD("_range_click_timeout"),&SpinBox::_range_click_timeout);
-
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"prefix"),_SCS("set_prefix"),_SCS("get_prefix"));
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"suffix"),_SCS("set_suffix"),_SCS("get_suffix"));
+ //ClassDB::bind_method(D_METHOD("_value_changed"),&SpinBox::_value_changed);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&SpinBox::_gui_input);
+ ClassDB::bind_method(D_METHOD("_text_entered"),&SpinBox::_text_entered);
+ ClassDB::bind_method(D_METHOD("set_suffix","suffix"),&SpinBox::set_suffix);
+ ClassDB::bind_method(D_METHOD("get_suffix"),&SpinBox::get_suffix);
+ ClassDB::bind_method(D_METHOD("set_prefix","prefix"),&SpinBox::set_prefix);
+ ClassDB::bind_method(D_METHOD("get_prefix"),&SpinBox::get_prefix);
+ ClassDB::bind_method(D_METHOD("set_editable","editable"),&SpinBox::set_editable);
+ ClassDB::bind_method(D_METHOD("is_editable"),&SpinBox::is_editable);
+ ClassDB::bind_method(D_METHOD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
+ ClassDB::bind_method(D_METHOD("get_line_edit"),&SpinBox::get_line_edit);
+ ClassDB::bind_method(D_METHOD("_line_edit_input"),&SpinBox::_line_edit_input);
+ ClassDB::bind_method(D_METHOD("_range_click_timeout"),&SpinBox::_range_click_timeout);
+
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),"set_editable","is_editable");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"prefix"),"set_prefix","get_prefix");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"suffix"),"set_suffix","get_suffix");
}
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index a39ad2fe99..14ea96a4e6 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -422,21 +422,21 @@ bool SplitContainer::is_collapsed() const {
void SplitContainer::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&SplitContainer::_gui_input);
- ClassDB::bind_method(_MD("set_split_offset","offset"),&SplitContainer::set_split_offset);
- ClassDB::bind_method(_MD("get_split_offset"),&SplitContainer::get_split_offset);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&SplitContainer::_gui_input);
+ ClassDB::bind_method(D_METHOD("set_split_offset","offset"),&SplitContainer::set_split_offset);
+ ClassDB::bind_method(D_METHOD("get_split_offset"),&SplitContainer::get_split_offset);
- ClassDB::bind_method(_MD("set_collapsed","collapsed"),&SplitContainer::set_collapsed);
- ClassDB::bind_method(_MD("is_collapsed"),&SplitContainer::is_collapsed);
+ ClassDB::bind_method(D_METHOD("set_collapsed","collapsed"),&SplitContainer::set_collapsed);
+ ClassDB::bind_method(D_METHOD("is_collapsed"),&SplitContainer::is_collapsed);
- ClassDB::bind_method(_MD("set_dragger_visibility","mode"),&SplitContainer::set_dragger_visibility);
- ClassDB::bind_method(_MD("get_dragger_visibility"),&SplitContainer::get_dragger_visibility);
+ ClassDB::bind_method(D_METHOD("set_dragger_visibility","mode"),&SplitContainer::set_dragger_visibility);
+ ClassDB::bind_method(D_METHOD("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,"collapsed"),_SCS("set_collapsed"),_SCS("is_collapsed"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"dragger_visibility",PROPERTY_HINT_ENUM,"Visible,Hidden,Hidden & Collapsed"),_SCS("set_dragger_visibility"),_SCS("get_dragger_visibility"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"split_offset"),"set_split_offset","get_split_offset");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collapsed"),"set_collapsed","is_collapsed");
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"dragger_visibility",PROPERTY_HINT_ENUM,"Visible,Hidden,Hidden & Collapsed"),"set_dragger_visibility","get_dragger_visibility");
BIND_CONSTANT( DRAGGER_VISIBLE );
BIND_CONSTANT( DRAGGER_HIDDEN );
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 11802ab0fb..fc25b68db9 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -31,368 +31,322 @@
#include "message_queue.h"
-
int TabContainer::_get_top_margin() const {
+ if (!tabs_visible)
+ return 0;
+
+ // Respect the minimum tab height.
Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<Font> font = get_font("font");
+ Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
- int h = MAX( tab_bg->get_minimum_size().height,tab_fg->get_minimum_size().height);
+ int tab_height = MAX(MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height), tab_disabled->get_minimum_size().height);
- int ch = font->get_height();
- for(int i=0;i<get_child_count();i++) {
+ // Font height or higher icon wins.
+ Ref<Font> font = get_font("font");
+ int content_height = font->get_height();
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
+ Vector<Control*> tabs = _get_tabs();
+ for (int i = 0; i < tabs.size(); i++) {
+
+ Control *c = tabs[i];
if (!c->has_meta("_tab_icon"))
continue;
Ref<Texture> tex = c->get_meta("_tab_icon");
if (!tex.is_valid())
continue;
- ch = MAX( ch, tex->get_size().height );
+ content_height = MAX(content_height, tex->get_size().height);
}
- h+=ch;
-
- return h;
-
+ return tab_height + content_height;
}
void TabContainer::_gui_input(const InputEvent& p_event) {
- if (p_event.type==InputEvent::MOUSE_BUTTON &&
- p_event.mouse_button.pressed &&
- p_event.mouse_button.button_index==BUTTON_LEFT) {
-
- // clicks
- Point2 pos( p_event.mouse_button.x, p_event.mouse_button.y );
+ if (p_event.type == InputEvent::MOUSE_BUTTON
+ && p_event.mouse_button.pressed
+ && p_event.mouse_button.button_index == BUTTON_LEFT) {
- int top_margin = _get_top_margin();
- if (pos.y>top_margin)
- return; // no click (too far down)
+ Point2 pos(p_event.mouse_button.x, p_event.mouse_button.y);
+ Size2 size = get_size();
- if (pos.x<tabs_ofs_cache)
- return; // no click (too far left)
+ // Click must be on tabs in the tab header area.
+ if (pos.x < tabs_ofs_cache || pos.y > _get_top_margin())
+ return;
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<Font> font = get_font("font");
- Ref<Texture> incr = get_icon("increment");
- Ref<Texture> decr = get_icon("decrement");
+ // Handle menu button.
Ref<Texture> menu = get_icon("menu");
- Ref<Texture> menu_hl = get_icon("menu_hl");
-
- if (popup && pos.x>get_size().width-menu->get_width()) {
-
-
+ if (popup && pos.x > size.width - menu->get_width()) {
emit_signal("pre_popup_pressed");
- Vector2 pp_pos = get_global_pos();
- pp_pos.x+=get_size().width;
- pp_pos.x-=popup->get_size().width;
- pp_pos.y+=menu->get_height();
- popup->set_global_pos( pp_pos );
+ Vector2 popup_pos = get_global_pos();
+ popup_pos.x += size.width - popup->get_size().width;
+ popup_pos.y += menu->get_height();
+
+ popup->set_global_pos(popup_pos);
popup->popup();
return;
}
- pos.x-=tabs_ofs_cache;
-
- int idx=0;
- int found=-1;
- bool rightroom=false;
-
- for(int i=0;i<get_child_count();i++) {
-
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
-
- if (idx<tab_display_ofs) {
- idx++;
- continue;
- }
-
- if (idx>last_tab_cache) {
- rightroom=true;
- break;
- }
-
- String s = c->has_meta("_tab_name")?String(XL_MESSAGE(String(c->get_meta("_tab_name")))):String(c->get_name());
- int tab_width=font->get_string_size(s).width;
-
- if (c->has_meta("_tab_icon")) {
- Ref<Texture> icon = c->get_meta("_tab_icon");
- if (icon.is_valid()) {
- tab_width+=icon->get_width();
- if (s!="")
- tab_width+=get_constant("hseparation");
-
- }
- }
- if (idx==current) {
-
- tab_width+=tab_fg->get_minimum_size().width;
- } else {
- tab_width+=tab_bg->get_minimum_size().width;
- }
-
- if (pos.x < tab_width) {
-
- found=idx;
- break;
- }
-
- pos.x-=tab_width;
- idx++;
- }
+ Vector<Control*> tabs = _get_tabs();
+ // Handle navigation buttons.
if (buttons_visible_cache) {
-
- if (p_event.mouse_button.x>get_size().width-incr->get_width()) {
- if (rightroom) {
- tab_display_ofs+=1;
+ Ref<Texture> increment = get_icon("increment");
+ Ref<Texture> decrement = get_icon("decrement");
+ if (pos.x > size.width - increment->get_width()) {
+ if (last_tab_cache < tabs.size() - 1) {
+ first_tab_cache += 1;
update();
}
- } else if (p_event.mouse_button.x>get_size().width-incr->get_width()-decr->get_width()) {
-
- if (tab_display_ofs>0) {
- tab_display_ofs-=1;
+ return;
+ } else if (pos.x > size.width - increment->get_width() - decrement->get_width()) {
+ if (first_tab_cache > 0) {
+ first_tab_cache -= 1;
update();
}
-
+ return;
}
}
-
- if (found!=-1) {
-
- set_current_tab(found);
+ // Activate the clicked tab.
+ pos.x -= tabs_ofs_cache;
+ for (int i = first_tab_cache; i <= last_tab_cache; i++) {
+ int tab_width = _get_tab_width(i);
+ if (pos.x < tab_width) {
+ if (!get_tab_disabled(i)) {
+ set_current_tab(i);
+ }
+ break;
+ }
+ pos.x -= tab_width;
}
}
-
}
void TabContainer::_notification(int p_what) {
-
- switch(p_what) {
-
+ switch (p_what) {
case NOTIFICATION_DRAW: {
- RID ci = get_canvas_item();
- Ref<StyleBox> panel = get_stylebox("panel");
+ RID canvas = get_canvas_item();
Size2 size = get_size();
+ // Draw only the tab area if the header is hidden.
+ Ref<StyleBox> panel = get_stylebox("panel");
if (!tabs_visible) {
-
- panel->draw(ci, Rect2( 0, 0, size.width, size.height));
+ panel->draw(canvas, Rect2(0, 0, size.width, size.height));
return;
}
-
-
+ Vector<Control*> tabs = _get_tabs();
Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<Texture> incr = get_icon("increment");
- Ref<Texture> decr = get_icon("decrement");
+ Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
+ Ref<Texture> increment = get_icon("increment");
+ Ref<Texture> decrement = get_icon("decrement");
Ref<Texture> menu = get_icon("menu");
Ref<Texture> menu_hl = get_icon("menu_hl");
Ref<Font> font = get_font("font");
- Color color_fg = get_color("font_color_fg");
- Color color_bg = get_color("font_color_bg");
-
+ Color font_color_fg = get_color("font_color_fg");
+ Color font_color_bg = get_color("font_color_bg");
+ Color font_color_disabled = get_color("font_color_disabled");
int side_margin = get_constant("side_margin");
- int top_margin = _get_top_margin();
-
-
- Size2 top_size = Size2( size.width, top_margin );
-
-
-
- int w=0;
- int idx=0;
- Vector<int> offsets;
- Vector<Control*> controls;
- int from=0;
- int limit=get_size().width;
- if (popup) {
- top_size.width-=menu->get_width();
- limit-=menu->get_width();
- }
-
- bool notdone=false;
- last_tab_cache=-1;
-
- for(int i=0;i<get_child_count();i++) {
-
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
- if (idx<tab_display_ofs) {
- idx++;
- from=idx;
- continue;
- }
-
- if (w>=get_size().width) {
- buttons_visible_cache=true;
- notdone=true;
+ int icon_text_distance = get_constant("hseparation");
+
+ // Find out start and width of the header area.
+ int header_x = side_margin;
+ int header_width = size.width - side_margin * 2;
+ int header_height = _get_top_margin();
+ if (popup)
+ header_width -= menu->get_width();
+
+ // Check if all tabs would fit into the header area.
+ int all_tabs_width = 0;
+ for (int i = 0; i < tabs.size(); i++) {
+ int tab_width = _get_tab_width(i);
+ all_tabs_width += tab_width;
+
+ if (all_tabs_width > header_width) {
+ // Not all tabs are visible at the same time - reserve space for navigation buttons.
+ buttons_visible_cache = true;
+ header_width -= decrement->get_width() + increment->get_width();
break;
- }
-
- offsets.push_back(w);
- controls.push_back(c);
-
- String s = c->has_meta("_tab_name")?String(XL_MESSAGE(String(c->get_meta("_tab_name")))):String(c->get_name());
- w+=font->get_string_size(s).width;
- if (c->has_meta("_tab_icon")) {
- Ref<Texture> icon = c->get_meta("_tab_icon");
- if (icon.is_valid()) {
- w+=icon->get_width();
- if (s!="")
- w+=get_constant("hseparation");
-
- }
- }
-
- if (idx==current) {
-
- w+=tab_fg->get_minimum_size().width;
} else {
- w+=tab_bg->get_minimum_size().width;
+ buttons_visible_cache = false;
}
-
- if (idx<tab_display_ofs) {
-
- }
- last_tab_cache=idx;
-
- idx++;
+ }
+ // With buttons, a right side margin does not need to be respected.
+ if (popup || buttons_visible_cache) {
+ header_width += side_margin;
}
+ // Go through the visible tabs to find the width they occupy.
+ all_tabs_width = 0;
+ Vector<int> tab_widths;
+ for (int i = first_tab_cache; i < tabs.size(); i++) {
+ int tab_width = _get_tab_width(i);
+ if (all_tabs_width + tab_width > header_width && tab_widths.size() > 0)
+ break;
+ all_tabs_width += tab_width;
+ tab_widths.push_back(tab_width);
+ }
- int ofs;
-
- switch(align) {
-
- case ALIGN_LEFT: ofs = side_margin; break;
- case ALIGN_CENTER: ofs = (int(limit) - w)/2; break;
- case ALIGN_RIGHT: ofs = int(limit) - w - side_margin; break;
- };
-
- tab_display_ofs=0;
-
-
- tabs_ofs_cache=ofs;
- idx=0;
-
-
-
- for(int i=0;i<controls.size();i++) {
-
- idx=i+from;
- if (current>=from && current<from+controls.size()-1) {
- //current is visible! draw it last.
- if (i==controls.size()-1) {
- idx=current;
- } else if (idx>=current) {
- idx+=1;
- }
- }
-
- Control *c = controls[idx-from];
-
- String s = c->has_meta("_tab_name")?String(c->get_meta("_tab_name")):String(c->get_name());
- int w=font->get_string_size(s).width;
- Ref<Texture> icon;
- if (c->has_meta("_tab_icon")) {
- icon = c->get_meta("_tab_icon");
- if (icon.is_valid()) {
-
- w+=icon->get_width();
- if (s!="")
- w+=get_constant("hseparation");
-
- }
- }
-
-
- Ref<StyleBox> sb;
- Color col;
-
- if (idx==current) {
+ // Find the offset at which to draw tabs, according to the alignment.
+ switch (align) {
+ case ALIGN_LEFT:
+ tabs_ofs_cache = header_x;
+ break;
+ case ALIGN_CENTER:
+ tabs_ofs_cache = header_x + (header_width / 2) - (all_tabs_width / 2);
+ break;
+ case ALIGN_RIGHT:
+ tabs_ofs_cache = header_x + header_width - all_tabs_width;
+ break;
+ }
- sb=tab_fg;
- col=color_fg;
+ // Draw all visible tabs.
+ int x = 0;
+ for (int i = 0; i < tab_widths.size(); i++) {
+ Ref<StyleBox> tab_style;
+ Color font_color;
+ if (get_tab_disabled(i + first_tab_cache)) {
+ tab_style = tab_disabled;
+ font_color = font_color_disabled;
+ } else if (i + first_tab_cache == current) {
+ tab_style = tab_fg;
+ font_color = font_color_fg;
} else {
- sb=tab_bg;
- col=color_bg;
+ tab_style = tab_bg;
+ font_color = font_color_bg;
}
- int lofs = ofs + offsets[idx-from];
+ // Draw the tab background.
+ int tab_width = tab_widths[i];
+ Rect2 tab_rect(tabs_ofs_cache + x, 0, tab_width, header_height);
+ tab_style->draw(canvas, tab_rect);
- Size2i sb_ms = sb->get_minimum_size();
- Rect2 sb_rect = Rect2( lofs, 0, w+sb_ms.width, top_margin);
+ // Draw the tab contents.
+ Control *control = tabs[i + first_tab_cache]->cast_to<Control>();
+ String text = control->has_meta("_tab_name")
+ ? String(XL_MESSAGE(String(control->get_meta("_tab_name"))))
+ : String(control->get_name());
+ int x_content = tab_rect.pos.x + tab_style->get_margin(MARGIN_LEFT);
+ int top_margin = tab_style->get_margin(MARGIN_TOP);
+ int y_center = top_margin + (tab_rect.size.y - tab_style->get_minimum_size().y) / 2;
- sb->draw(ci, sb_rect );
-
- Point2i lpos = sb_rect.pos;
- lpos.x+=sb->get_margin(MARGIN_LEFT);
- if (icon.is_valid()) {
-
- icon->draw(ci, Point2i( lpos.x, sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-icon->get_height())/2 ) );
- if (s!="")
- lpos.x+=icon->get_width()+get_constant("hseparation");
-
+ // Draw the tab icon.
+ if (control->has_meta("_tab_icon")) {
+ Ref<Texture> icon = control->get_meta("_tab_icon");
+ if (icon.is_valid()) {
+ int y = y_center - (icon->get_height() / 2);
+ icon->draw(canvas, Point2i(x_content, y));
+ if (text != "")
+ x_content += icon->get_width() + icon_text_distance;
+ }
}
- font->draw(ci, Point2i( lpos.x, sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-font->get_height())/2+font->get_ascent() ), s, col );
+ // Draw the tab text.
+ Point2i text_pos(x_content, y_center - (font->get_height() / 2) + font->get_ascent());
+ font->draw(canvas, text_pos, text, font_color);
- idx++;
+ x += tab_width;
+ last_tab_cache = i + first_tab_cache;
}
+ // Draw the popup menu.
+ x = get_size().width;
+ if (popup) {
+ x -= menu->get_width();
+ if (mouse_x_cache > x)
+ menu_hl->draw(get_canvas_item(), Size2(x, 0));
+ else
+ menu->draw(get_canvas_item(), Size2(x, 0));
+ }
+ // Draw the navigation buttons.
if (buttons_visible_cache) {
+ int y_center = header_height / 2;
- int vofs = (top_margin-incr->get_height())/2;
- decr->draw(ci,Point2(limit,vofs),Color(1,1,1,tab_display_ofs==0?0.5:1.0));
- incr->draw(ci,Point2(limit+incr->get_width(),vofs),Color(1,1,1,notdone?1.0:0.5));
- }
+ x -= increment->get_width();
+ increment->draw(canvas,
+ Point2(x, y_center - (increment->get_height() / 2)),
+ Color(1, 1, 1, last_tab_cache < tabs.size() - 1 ? 1.0 : 0.5));
- if (popup) {
- int from = get_size().width-menu->get_width();
-
- if (mouse_x_cache > from)
- menu_hl->draw(get_canvas_item(),Size2(from,0));
- else
- menu->draw(get_canvas_item(),Size2(from,0));
+ x -= decrement->get_width();
+ decrement->draw(canvas,
+ Point2(x, y_center - (decrement->get_height() / 2)),
+ Color(1, 1, 1, first_tab_cache > 0 ? 1.0 : 0.5));
}
- panel->draw(ci, Rect2( 0, top_size.height, size.width, size.height-top_size.height));
-
+ // Draw the tab area.
+ panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
} break;
case NOTIFICATION_THEME_CHANGED: {
if (get_tab_count() > 0) {
- call_deferred("set_current_tab",get_current_tab()); //wait until all changed theme
+ call_deferred("set_current_tab", get_current_tab()); //wait until all changed theme
}
} break;
}
}
+int TabContainer::_get_tab_width(int p_index) const {
+ Control *control = _get_tabs()[p_index]->cast_to<Control>();
+ if (!control || control->is_set_as_toplevel())
+ return 0;
+
+ // Get the width of the text displayed on the tab.
+ Ref<Font> font = get_font("font");
+ String text = control->has_meta("_tab_name")
+ ? String(XL_MESSAGE(String(control->get_meta("_tab_name"))))
+ : String(control->get_name());
+ int width = font->get_string_size(text).width;
+
+ // Add space for a tab icon.
+ if (control->has_meta("_tab_icon")) {
+ Ref<Texture> icon = control->get_meta("_tab_icon");
+ if (icon.is_valid()) {
+ width += icon->get_width();
+ if (text != "")
+ width += get_constant("hseparation");
+ }
+ }
+
+ // Respect a minimum size.
+ Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
+ if (get_tab_disabled(p_index)) {
+ width += tab_disabled->get_minimum_size().width;
+ } else if (p_index == current) {
+ width += tab_fg->get_minimum_size().width;
+ } else {
+ width += tab_bg->get_minimum_size().width;
+ }
+
+ return width;
+}
+
+Vector<Control*> TabContainer::_get_tabs() const {
+
+ Vector<Control*> controls;
+ for (int i = 0; i < get_child_count(); i++) {
+
+ Control *control = get_child(i)->cast_to<Control>();
+ if (!control || control->is_toplevel_control())
+ continue;
+
+ controls.push_back(control);
+ }
+ return controls;
+}
+
void TabContainer::_child_renamed_callback() {
update();
@@ -408,78 +362,73 @@ void TabContainer::add_child_notify(Node *p_child) {
if (c->is_set_as_toplevel())
return;
- bool first=false;
+ bool first = false;
- if (get_tab_count()!=1)
+ if (get_tab_count() != 1)
c->hide();
else {
c->show();
//call_deferred("set_current_tab",0);
- first=true;
- current=0;
+ first = true;
+ current = 0;
+ previous = 0;
}
c->set_area_as_parent_rect();
if (tabs_visible)
- c->set_margin(MARGIN_TOP,_get_top_margin());
+ c->set_margin(MARGIN_TOP, _get_top_margin());
Ref<StyleBox> sb = get_stylebox("panel");
- for(int i=0;i<4;i++)
- c->set_margin(Margin(i),c->get_margin(Margin(i))+sb->get_margin(Margin(i)));
+ for (int i = 0; i < 4; i++)
+ c->set_margin(Margin(i), c->get_margin(Margin(i)) + sb->get_margin(Margin(i)));
update();
- p_child->connect("renamed", this,"_child_renamed_callback");
- if(first)
- emit_signal("tab_changed",current);
+ p_child->connect("renamed", this, "_child_renamed_callback");
+ if (first)
+ emit_signal("tab_changed", current);
}
int TabContainer::get_tab_count() const {
- int count=0;
-
- for(int i=0;i<get_child_count();i++) {
-
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- count++;
- }
-
- return count;
+ return _get_tabs().size();
}
void TabContainer::set_current_tab(int p_current) {
- ERR_FAIL_INDEX( p_current, get_tab_count() );
+ ERR_FAIL_INDEX(p_current, get_tab_count());
- current=p_current;
+ int pending_previous = current;
+ current = p_current;
- int idx=0;
-
- Ref<StyleBox> sb=get_stylebox("panel");
- for(int i=0;i<get_child_count();i++) {
+ Ref<StyleBox> sb = get_stylebox("panel");
+ Vector<Control*> tabs = _get_tabs();
+ for (int i = 0; i < tabs.size(); i++) {
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
- if (idx==current) {
+ Control *c = tabs[i];
+ if (i == current) {
c->show();
c->set_area_as_parent_rect();
if (tabs_visible)
- c->set_margin(MARGIN_TOP,_get_top_margin());
- for(int i=0;i<4;i++)
- c->set_margin(Margin(i),c->get_margin(Margin(i))+sb->get_margin(Margin(i)));
+ c->set_margin(MARGIN_TOP, _get_top_margin());
+ for (int i = 0; i < 4; i++)
+ c->set_margin(Margin(i), c->get_margin(Margin(i)) + sb->get_margin(Margin(i)));
- } else
+ }
+ else
c->hide();
- idx++;
}
_change_notify("current_tab");
- emit_signal("tab_changed",current);
+
+ if (pending_previous == current)
+ emit_signal("tab_selected", current);
+ else {
+ previous = pending_previous;
+ emit_signal("tab_selected", current);
+ emit_signal("tab_changed", current);
+ }
+
update();
}
@@ -488,47 +437,27 @@ int TabContainer::get_current_tab() const {
return current;
}
-Control* TabContainer::get_tab_control(int p_idx) const {
-
- int idx=0;
-
-
- for(int i=0;i<get_child_count();i++) {
-
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
- if (idx==p_idx) {
- return c;
-
- }
- idx++;
- }
-
- return NULL;
+int TabContainer::get_previous_tab() const {
+
+ return previous;
}
-Control* TabContainer::get_current_tab_control() const {
- int idx=0;
-
-
- for(int i=0;i<get_child_count();i++) {
+Control* TabContainer::get_tab_control(int p_idx) const {
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
- if (idx==current) {
- return c;
+ Vector<Control*> tabs = _get_tabs();
+ if (p_idx >= 0 && p_idx < tabs.size())
+ return tabs[p_idx];
+ else
+ return NULL;
+}
- }
- idx++;
- }
+Control* TabContainer::get_current_tab_control() const {
- return NULL;
+ Vector<Control*> tabs = _get_tabs();
+ if (current >= 0 && current < tabs.size())
+ return tabs[current];
+ else
+ return NULL;
}
void TabContainer::remove_child_notify(Node *p_child) {
@@ -536,24 +465,24 @@ void TabContainer::remove_child_notify(Node *p_child) {
Control::remove_child_notify(p_child);
int tc = get_tab_count();
- if (current==tc-1) {
+ if (current == tc - 1) {
current--;
- if (current<0)
- current=0;
+ if (current < 0)
+ current = 0;
else {
- call_deferred("set_current_tab",current);
+ call_deferred("set_current_tab", current);
}
}
- p_child->disconnect("renamed", this,"_child_renamed_callback");
+ p_child->disconnect("renamed", this, "_child_renamed_callback");
update();
}
void TabContainer::set_tab_align(TabAlign p_align) {
- ERR_FAIL_INDEX(p_align,3);
- align=p_align;
+ ERR_FAIL_INDEX(p_align, 3);
+ align = p_align;
update();
_change_notify("tab_align");
@@ -565,20 +494,19 @@ TabContainer::TabAlign TabContainer::get_tab_align() const {
void TabContainer::set_tabs_visible(bool p_visibe) {
- if (p_visibe==tabs_visible)
+ if (p_visibe == tabs_visible)
return;
- tabs_visible=p_visibe;
+ tabs_visible = p_visibe;
- for(int i=0;i<get_child_count();i++) {
+ Vector<Control*> tabs = _get_tabs();
+ for (int i = 0; i < tabs.size(); i++) {
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
+ Control *c = tabs[i];
if (p_visibe)
- c->set_margin(MARGIN_TOP,_get_top_margin());
+ c->set_margin(MARGIN_TOP, _get_top_margin());
else
- c->set_margin(MARGIN_TOP,0);
+ c->set_margin(MARGIN_TOP, 0);
}
update();
@@ -590,39 +518,24 @@ bool TabContainer::are_tabs_visible() const {
}
-
Control *TabContainer::_get_tab(int p_idx) const {
- int idx=0;
-
- for(int i=0;i<get_child_count();i++) {
-
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
- if (idx==p_idx)
- return c;
- idx++;
-
- }
- return NULL;
+ return get_tab_control(p_idx);
}
-void TabContainer::set_tab_title(int p_tab,const String& p_title) {
+void TabContainer::set_tab_title(int p_tab, const String& p_title) {
Control *child = _get_tab(p_tab);
ERR_FAIL_COND(!child);
- child->set_meta("_tab_name",p_title);
+ child->set_meta("_tab_name", p_title);
}
-String TabContainer::get_tab_title(int p_tab) const{
+String TabContainer::get_tab_title(int p_tab) const {
Control *child = _get_tab(p_tab);
- ERR_FAIL_COND_V(!child,"");
+ ERR_FAIL_COND_V(!child, "");
if (child->has_meta("_tab_name"))
return child->get_meta("_tab_name");
else
@@ -630,80 +543,92 @@ String TabContainer::get_tab_title(int p_tab) const{
}
-void TabContainer::set_tab_icon(int p_tab,const Ref<Texture>& p_icon){
+void TabContainer::set_tab_icon(int p_tab, const Ref<Texture>& p_icon) {
Control *child = _get_tab(p_tab);
ERR_FAIL_COND(!child);
- child->set_meta("_tab_icon",p_icon);
+ child->set_meta("_tab_icon", p_icon);
}
-Ref<Texture> TabContainer::get_tab_icon(int p_tab) const{
+Ref<Texture> TabContainer::get_tab_icon(int p_tab) const {
Control *child = _get_tab(p_tab);
- ERR_FAIL_COND_V(!child,Ref<Texture>());
+ ERR_FAIL_COND_V(!child, Ref<Texture>());
if (child->has_meta("_tab_icon"))
return child->get_meta("_tab_icon");
else
return Ref<Texture>();
}
+void TabContainer::set_tab_disabled(int p_tab, bool p_enabled) {
+
+ Control *child = _get_tab(p_tab);
+ ERR_FAIL_COND(!child);
+ child->set_meta("_tab_disabled", p_enabled);
+ update();
+}
+
+bool TabContainer::get_tab_disabled(int p_tab) const {
+
+ Control *child = _get_tab(p_tab);
+ ERR_FAIL_COND_V(!child, false);
+ if (child->has_meta("_tab_disabled"))
+ return child->get_meta("_tab_disabled");
+ else
+ return false;
+}
+
void TabContainer::get_translatable_strings(List<String> *p_strings) const {
- for(int i=0;i<get_child_count();i++) {
+ Vector<Control*> tabs = _get_tabs();
+ for (int i = 0; i < tabs.size(); i++) {
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
+ Control *c = tabs[i];
if (!c->has_meta("_tab_name"))
continue;
String name = c->get_meta("_tab_name");
- if (name!="")
+ if (name != "")
p_strings->push_back(name);
}
}
-
Size2 TabContainer::get_minimum_size() const {
Size2 ms;
- for(int i=0;i<get_child_count();i++) {
+ Vector<Control*> tabs = _get_tabs();
+ for (int i = 0; i < tabs.size(); i++) {
- Control *c = get_child(i)->cast_to<Control>();
- if (!c)
- continue;
- if (c->is_set_as_toplevel())
- continue;
+ Control *c = tabs[i];
if (!c->is_visible_in_tree())
continue;
Size2 cms = c->get_combined_minimum_size();
- ms.x=MAX(ms.x,cms.x);
- ms.y=MAX(ms.y,cms.y);
+ ms.x = MAX(ms.x, cms.x);
+ ms.y = MAX(ms.y, cms.y);
}
Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
Ref<Font> font = get_font("font");
- ms.y+=MAX(tab_bg->get_minimum_size().y,tab_fg->get_minimum_size().y);
- ms.y+=font->get_height();
+ ms.y += MAX(MAX(tab_bg->get_minimum_size().y, tab_fg->get_minimum_size().y), tab_disabled->get_minimum_size().y);
+ ms.y += font->get_height();
Ref<StyleBox> sb = get_stylebox("panel");
- ms+=sb->get_minimum_size();
+ ms += sb->get_minimum_size();
return ms;
}
void TabContainer::set_popup(Node *p_popup) {
ERR_FAIL_NULL(p_popup);
- popup=p_popup->cast_to<Popup>();
+ popup = p_popup->cast_to<Popup>();
update();
}
@@ -711,46 +636,50 @@ Popup* TabContainer::get_popup() const {
return popup;
}
-
void TabContainer::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&TabContainer::_gui_input);
- ClassDB::bind_method(_MD("get_tab_count"),&TabContainer::get_tab_count);
- ClassDB::bind_method(_MD("set_current_tab","tab_idx"),&TabContainer::set_current_tab);
- ClassDB::bind_method(_MD("get_current_tab"),&TabContainer::get_current_tab);
- ClassDB::bind_method(_MD("get_current_tab_control:Control"),&TabContainer::get_current_tab_control);
- ClassDB::bind_method(_MD("get_tab_control:Control","idx"),&TabContainer::get_tab_control);
- ClassDB::bind_method(_MD("set_tab_align","align"),&TabContainer::set_tab_align);
- ClassDB::bind_method(_MD("get_tab_align"),&TabContainer::get_tab_align);
- ClassDB::bind_method(_MD("set_tabs_visible","visible"),&TabContainer::set_tabs_visible);
- ClassDB::bind_method(_MD("are_tabs_visible"),&TabContainer::are_tabs_visible);
- ClassDB::bind_method(_MD("set_tab_title","tab_idx","title"),&TabContainer::set_tab_title);
- ClassDB::bind_method(_MD("get_tab_title","tab_idx"),&TabContainer::get_tab_title);
- ClassDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&TabContainer::set_tab_icon);
- ClassDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&TabContainer::get_tab_icon);
- ClassDB::bind_method(_MD("set_popup","popup:Popup"),&TabContainer::set_popup);
- ClassDB::bind_method(_MD("get_popup:Popup"),&TabContainer::get_popup);
-
- ClassDB::bind_method(_MD("_child_renamed_callback"),&TabContainer::_child_renamed_callback);
-
- ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab")));
+ ClassDB::bind_method(D_METHOD("_gui_input"), &TabContainer::_gui_input);
+ ClassDB::bind_method(D_METHOD("get_tab_count"), &TabContainer::get_tab_count);
+ ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &TabContainer::set_current_tab);
+ ClassDB::bind_method(D_METHOD("get_current_tab"), &TabContainer::get_current_tab);
+ ClassDB::bind_method(D_METHOD("get_previous_tab"), &TabContainer::get_previous_tab);
+ ClassDB::bind_method(D_METHOD("get_current_tab_control:Control"), &TabContainer::get_current_tab_control);
+ ClassDB::bind_method(D_METHOD("get_tab_control:Control", "idx"), &TabContainer::get_tab_control);
+ ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &TabContainer::set_tab_align);
+ ClassDB::bind_method(D_METHOD("get_tab_align"), &TabContainer::get_tab_align);
+ ClassDB::bind_method(D_METHOD("set_tabs_visible", "visible"), &TabContainer::set_tabs_visible);
+ ClassDB::bind_method(D_METHOD("are_tabs_visible"), &TabContainer::are_tabs_visible);
+ ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &TabContainer::set_tab_title);
+ ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &TabContainer::get_tab_title);
+ ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon:Texture"), &TabContainer::set_tab_icon);
+ ClassDB::bind_method(D_METHOD("get_tab_icon:Texture", "tab_idx"), &TabContainer::get_tab_icon);
+ ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabContainer::set_tab_disabled);
+ ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabContainer::get_tab_disabled);
+ ClassDB::bind_method(D_METHOD("set_popup", "popup:Popup"), &TabContainer::set_popup);
+ ClassDB::bind_method(D_METHOD("get_popup:Popup"), &TabContainer::get_popup);
+
+ ClassDB::bind_method(D_METHOD("_child_renamed_callback"), &TabContainer::_child_renamed_callback);
+
+ ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
+ ADD_SIGNAL(MethodInfo("tab_selected", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("pre_popup_pressed"));
- ADD_PROPERTY( PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM,"Left,Center,Right"), _SCS("set_tab_align"), _SCS("get_tab_align") );
- ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "tabs_visible"), _SCS("set_tabs_visible"), _SCS("are_tabs_visible") );
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible");
}
TabContainer::TabContainer() {
- tab_display_ofs=0;
- buttons_visible_cache=false;
- tabs_ofs_cache=0;
- current=0;
- mouse_x_cache=0;
- align=ALIGN_CENTER;
- tabs_visible=true;
- popup=NULL;
-
-}
+ first_tab_cache = 0;
+ buttons_visible_cache = false;
+ tabs_ofs_cache = 0;
+ current = 0;
+ previous = 0;
+ mouse_x_cache = 0;
+ align = ALIGN_CENTER;
+ tabs_visible = true;
+ popup = NULL;
+
+} \ No newline at end of file
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index 8b6ca7704e..d5a2801bbe 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -46,10 +46,11 @@ public:
private:
int mouse_x_cache;
- int tab_display_ofs;
+ int first_tab_cache;
int tabs_ofs_cache;
int last_tab_cache;
int current;
+ int previous;
bool tabs_visible;
bool buttons_visible_cache;
TabAlign align;
@@ -57,6 +58,8 @@ private:
int _get_top_margin() const;
Popup *popup;
+ Vector<Control*> _get_tabs() const;
+ int _get_tab_width(int p_index) const;
protected:
@@ -83,9 +86,13 @@ public:
void set_tab_icon(int p_tab,const Ref<Texture>& p_icon);
Ref<Texture> get_tab_icon(int p_tab) const;
+ void set_tab_disabled(int p_tab, bool p_disabled);
+ bool get_tab_disabled(int p_tab) const;
+
int get_tab_count() const;
void set_current_tab(int p_current);
int get_current_tab() const;
+ int get_previous_tab() const;
Control* get_tab_control(int p_idx) const;
Control* get_current_tab_control() const;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 98d3f6230d..4e07a495ed 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -34,9 +34,10 @@ Size2 Tabs::get_minimum_size() const {
Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
Ref<Font> font = get_font("font");
- Size2 ms(0, MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height)+font->get_height());
+ Size2 ms(0, MAX(MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height), tab_disabled->get_minimum_size().height)+font->get_height());
for(int i=0;i<tabs.size();i++) {
@@ -49,7 +50,9 @@ Size2 Tabs::get_minimum_size() const {
ms.width+=font->get_string_size(tabs[i].text).width;
- if (current==i)
+ if (tabs[i].disabled)
+ ms.width += tab_disabled->get_minimum_size().width;
+ else if (current==i)
ms.width+=tab_fg->get_minimum_size().width;
else
ms.width+=tab_bg->get_minimum_size().width;
@@ -111,7 +114,7 @@ void Tabs::_gui_input(const InputEvent& p_event) {
hover_buttons = i;
break;
}
- else if (tabs[i].cb_rect.has_point(pos)) {
+ else if (!tabs[i].disabled && tabs[i].cb_rect.has_point(pos)) {
cb_hover=i;
rb_hover=-1;
hover_buttons = i;
@@ -206,7 +209,9 @@ void Tabs::_gui_input(const InputEvent& p_event) {
}
if (pos.x >=tabs[i].ofs_cache && pos.x<tabs[i].ofs_cache+tabs[i].size_cache) {
- found=i;
+ if (!tabs[i].disabled) {
+ found = i;
+ }
break;
}
}
@@ -242,9 +247,11 @@ void Tabs::_notification(int p_what) {
Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
Ref<Font> font = get_font("font");
Color color_fg = get_color("font_color_fg");
Color color_bg = get_color("font_color_bg");
+ Color color_disabled = get_color("font_color_disabled");
Ref<Texture> close=get_icon("close");
int h = get_size().height;
@@ -301,7 +308,10 @@ void Tabs::_notification(int p_what) {
Ref<StyleBox> sb;
Color col;
- if (i==current) {
+ if (tabs[i].disabled) {
+ sb = tab_disabled;
+ col = color_disabled;
+ } else if (i == current) {
sb=tab_fg;
col=color_fg;
} else {
@@ -366,7 +376,7 @@ void Tabs::_notification(int p_what) {
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 (!tabs[i].disabled && cb_hover == i) {
if (cb_pressing)
get_stylebox("button_pressed")->draw(ci,cb_rect);
else
@@ -463,6 +473,18 @@ Ref<Texture> Tabs::get_tab_icon(int p_tab) const{
}
+void Tabs::set_tab_disabled(int p_tab, bool p_disabled) {
+
+ ERR_FAIL_INDEX(p_tab, tabs.size());
+ tabs[p_tab].disabled = p_disabled;
+ update();
+}
+bool Tabs::get_tab_disabled(int p_tab) const {
+
+ ERR_FAIL_INDEX_V(p_tab, tabs.size(), false);
+ return tabs[p_tab].disabled;
+}
+
void Tabs::set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button){
ERR_FAIL_INDEX(p_tab,tabs.size());
@@ -484,6 +506,7 @@ void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) {
Tab t;
t.text=p_str;
t.icon=p_icon;
+ t.disabled = false;
tabs.push_back(t);
@@ -534,6 +557,7 @@ int Tabs::get_tab_width(int p_idx) const {
Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
Ref<Font> font = get_font("font");
@@ -549,7 +573,9 @@ int Tabs::get_tab_width(int p_idx) const {
x+=font->get_string_size(tabs[p_idx].text).width;
- if (current==p_idx)
+ if (tabs[p_idx].disabled)
+ x += tab_disabled->get_minimum_size().width;
+ else if (current==p_idx)
x+=tab_fg->get_minimum_size().width;
else
x+=tab_bg->get_minimum_size().width;
@@ -649,25 +675,27 @@ void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
void Tabs::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&Tabs::_gui_input);
- ClassDB::bind_method(_MD("get_tab_count"),&Tabs::get_tab_count);
- ClassDB::bind_method(_MD("set_current_tab","tab_idx"),&Tabs::set_current_tab);
- ClassDB::bind_method(_MD("get_current_tab"),&Tabs::get_current_tab);
- ClassDB::bind_method(_MD("set_tab_title","tab_idx","title"),&Tabs::set_tab_title);
- ClassDB::bind_method(_MD("get_tab_title","tab_idx"),&Tabs::get_tab_title);
- ClassDB::bind_method(_MD("set_tab_icon","tab_idx","icon:Texture"),&Tabs::set_tab_icon);
- ClassDB::bind_method(_MD("get_tab_icon:Texture","tab_idx"),&Tabs::get_tab_icon);
- ClassDB::bind_method(_MD("remove_tab","tab_idx"),&Tabs::remove_tab);
- ClassDB::bind_method(_MD("add_tab","title","icon:Texture"),&Tabs::add_tab);
- ClassDB::bind_method(_MD("set_tab_align","align"),&Tabs::set_tab_align);
- ClassDB::bind_method(_MD("get_tab_align"),&Tabs::get_tab_align);
- ClassDB::bind_method(_MD("ensure_tab_visible","idx"),&Tabs::ensure_tab_visible);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&Tabs::_gui_input);
+ ClassDB::bind_method(D_METHOD("get_tab_count"),&Tabs::get_tab_count);
+ ClassDB::bind_method(D_METHOD("set_current_tab","tab_idx"),&Tabs::set_current_tab);
+ ClassDB::bind_method(D_METHOD("get_current_tab"),&Tabs::get_current_tab);
+ ClassDB::bind_method(D_METHOD("set_tab_title","tab_idx","title"),&Tabs::set_tab_title);
+ ClassDB::bind_method(D_METHOD("get_tab_title","tab_idx"),&Tabs::get_tab_title);
+ ClassDB::bind_method(D_METHOD("set_tab_icon","tab_idx","icon:Texture"),&Tabs::set_tab_icon);
+ ClassDB::bind_method(D_METHOD("get_tab_icon:Texture","tab_idx"),&Tabs::get_tab_icon);
+ ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &Tabs::set_tab_disabled);
+ ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &Tabs::get_tab_disabled);
+ ClassDB::bind_method(D_METHOD("remove_tab","tab_idx"),&Tabs::remove_tab);
+ ClassDB::bind_method(D_METHOD("add_tab","title","icon:Texture"),&Tabs::add_tab);
+ ClassDB::bind_method(D_METHOD("set_tab_align","align"),&Tabs::set_tab_align);
+ ClassDB::bind_method(D_METHOD("get_tab_align"),&Tabs::get_tab_align);
+ ClassDB::bind_method(D_METHOD("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")));
ADD_SIGNAL(MethodInfo("tab_close",PropertyInfo(Variant::INT,"tab")));
- ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab") ;
BIND_CONSTANT( ALIGN_LEFT );
BIND_CONSTANT( ALIGN_CENTER );
diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h
index 9ba32297dc..83dcce2613 100644
--- a/scene/gui/tabs.h
+++ b/scene/gui/tabs.h
@@ -57,6 +57,7 @@ private:
String text;
Ref<Texture> icon;
int ofs_cache;
+ bool disabled;
int size_cache;
int x_cache;
int x_size_cache;
@@ -105,6 +106,9 @@ public:
void set_tab_icon(int p_tab,const Ref<Texture>& p_icon);
Ref<Texture> get_tab_icon(int p_tab) const;
+
+ void set_tab_disabled(int p_tab, bool p_disabled);
+ bool get_tab_disabled(int p_tab) const;
void set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button);
Ref<Texture> get_tab_right_button(int p_tab) const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 6036b3f9df..f1b061c506 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -32,7 +32,7 @@
#include "os/input.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include "message_queue.h"
#include "scene/main/viewport.h"
@@ -2431,6 +2431,8 @@ void TextEdit::_gui_input(const InputEvent& p_gui_input) {
if (k.mod.shift)
_post_shift_selection();
+ else if(k.mod.command || k.mod.control)
+ deselect();
} break;
#else
@@ -2440,25 +2442,30 @@ void TextEdit::_gui_input(const InputEvent& p_gui_input) {
if (k.mod.shift)
_pre_shift_selection();
- // compute whitespace symbols seq length
- int current_line_whitespace_len = 0;
- while(current_line_whitespace_len < text[cursor.line].length()) {
- CharType c = text[cursor.line][current_line_whitespace_len];
- if(c != '\t' && c != ' ')
- break;
- current_line_whitespace_len++;
- }
-
- if(cursor_get_column() == current_line_whitespace_len)
+ if (k.mod.command) {
+ cursor_set_line(0);
cursor_set_column(0);
- else
- cursor_set_column(current_line_whitespace_len);
+ }
+ else {
+ // compute whitespace symbols seq length
+ int current_line_whitespace_len = 0;
+ while( current_line_whitespace_len < text[cursor.line].length() ) {
+ CharType c = text[cursor.line][current_line_whitespace_len];
+ if( c != '\t' && c != ' ' )
+ break;
+ current_line_whitespace_len++;
+ }
- if (k.mod.command)
- cursor_set_line(0);
+ if( cursor_get_column() == current_line_whitespace_len )
+ cursor_set_column(0);
+ else
+ cursor_set_column(current_line_whitespace_len);
+ }
if (k.mod.shift)
_post_shift_selection();
+ else if(k.mod.command || k.mod.control)
+ deselect();
_cancel_completion();
completion_hint="";
@@ -2481,6 +2488,8 @@ void TextEdit::_gui_input(const InputEvent& p_gui_input) {
if (k.mod.shift)
_post_shift_selection();
+ else if(k.mod.command || k.mod.control)
+ deselect();
} break;
#else
@@ -2495,6 +2504,8 @@ void TextEdit::_gui_input(const InputEvent& p_gui_input) {
if (k.mod.shift)
_post_shift_selection();
+ else if(k.mod.command || k.mod.control)
+ deselect();
_cancel_completion();
completion_hint="";
@@ -4256,7 +4267,7 @@ void TextEdit::_update_completion_candidates() {
//no completion here
//print_line("cancel!");
cancel=true;
- } if (inquote && first_quote!=-1) {
+ } else if (inquote && first_quote!=-1) {
s=l.substr(first_quote,cofs-first_quote);
//print_line("s: 1"+s);
@@ -4609,90 +4620,90 @@ PopupMenu *TextEdit::get_menu() const {
void TextEdit::_bind_methods() {
- ClassDB::bind_method(_MD("_gui_input"),&TextEdit::_gui_input);
- ClassDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved);
- ClassDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit);
- ClassDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit);
- ClassDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op);
- ClassDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held);
- ClassDB::bind_method(_MD("_toggle_draw_caret"),&TextEdit::_toggle_draw_caret);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&TextEdit::_gui_input);
+ ClassDB::bind_method(D_METHOD("_scroll_moved"),&TextEdit::_scroll_moved);
+ ClassDB::bind_method(D_METHOD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit);
+ ClassDB::bind_method(D_METHOD("_text_changed_emit"),&TextEdit::_text_changed_emit);
+ ClassDB::bind_method(D_METHOD("_push_current_op"),&TextEdit::_push_current_op);
+ ClassDB::bind_method(D_METHOD("_click_selection_held"),&TextEdit::_click_selection_held);
+ ClassDB::bind_method(D_METHOD("_toggle_draw_caret"),&TextEdit::_toggle_draw_caret);
BIND_CONSTANT( SEARCH_MATCH_CASE );
BIND_CONSTANT( SEARCH_WHOLE_WORDS );
BIND_CONSTANT( SEARCH_BACKWARDS );
/*
- ClassDB::bind_method(_MD("delete_char"),&TextEdit::delete_char);
- ClassDB::bind_method(_MD("delete_line"),&TextEdit::delete_line);
+ ClassDB::bind_method(D_METHOD("delete_char"),&TextEdit::delete_char);
+ ClassDB::bind_method(D_METHOD("delete_line"),&TextEdit::delete_line);
*/
- ClassDB::bind_method(_MD("set_text","text"),&TextEdit::set_text);
- ClassDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor);
+ ClassDB::bind_method(D_METHOD("set_text","text"),&TextEdit::set_text);
+ ClassDB::bind_method(D_METHOD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor);
- ClassDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count);
- ClassDB::bind_method(_MD("get_text"),&TextEdit::get_text);
- ClassDB::bind_method(_MD("get_line","line"),&TextEdit::get_line);
+ ClassDB::bind_method(D_METHOD("get_line_count"),&TextEdit::get_line_count);
+ ClassDB::bind_method(D_METHOD("get_text"),&TextEdit::get_text);
+ ClassDB::bind_method(D_METHOD("get_line","line"),&TextEdit::get_line);
- ClassDB::bind_method(_MD("cursor_set_column","column","adjust_viewport"),&TextEdit::cursor_set_column,DEFVAL(false));
- ClassDB::bind_method(_MD("cursor_set_line","line","adjust_viewport"),&TextEdit::cursor_set_line,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("cursor_set_column","column","adjust_viewport"),&TextEdit::cursor_set_column,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("cursor_set_line","line","adjust_viewport"),&TextEdit::cursor_set_line,DEFVAL(false));
- ClassDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column);
- ClassDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line);
- ClassDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&TextEdit::cursor_set_blink_enabled);
- ClassDB::bind_method(_MD("cursor_get_blink_enabled"),&TextEdit::cursor_get_blink_enabled);
- ClassDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&TextEdit::cursor_set_blink_speed);
- ClassDB::bind_method(_MD("cursor_get_blink_speed"),&TextEdit::cursor_get_blink_speed);
- ClassDB::bind_method(_MD("cursor_set_block_mode", "enable"), &TextEdit::cursor_set_block_mode);
- ClassDB::bind_method(_MD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode);
+ ClassDB::bind_method(D_METHOD("cursor_get_column"),&TextEdit::cursor_get_column);
+ ClassDB::bind_method(D_METHOD("cursor_get_line"),&TextEdit::cursor_get_line);
+ ClassDB::bind_method(D_METHOD("cursor_set_blink_enabled", "enable"),&TextEdit::cursor_set_blink_enabled);
+ ClassDB::bind_method(D_METHOD("cursor_get_blink_enabled"),&TextEdit::cursor_get_blink_enabled);
+ ClassDB::bind_method(D_METHOD("cursor_set_blink_speed", "blink_speed"),&TextEdit::cursor_set_blink_speed);
+ ClassDB::bind_method(D_METHOD("cursor_get_blink_speed"),&TextEdit::cursor_get_blink_speed);
+ ClassDB::bind_method(D_METHOD("cursor_set_block_mode", "enable"), &TextEdit::cursor_set_block_mode);
+ ClassDB::bind_method(D_METHOD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode);
- ClassDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly);
- ClassDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap);
- ClassDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars);
+ ClassDB::bind_method(D_METHOD("set_readonly","enable"),&TextEdit::set_readonly);
+ ClassDB::bind_method(D_METHOD("set_wrap","enable"),&TextEdit::set_wrap);
+ ClassDB::bind_method(D_METHOD("set_max_chars","amount"),&TextEdit::set_max_chars);
- ClassDB::bind_method(_MD("cut"),&TextEdit::cut);
- ClassDB::bind_method(_MD("copy"),&TextEdit::copy);
- ClassDB::bind_method(_MD("paste"),&TextEdit::paste);
- ClassDB::bind_method(_MD("select_all"),&TextEdit::select_all);
- ClassDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select);
+ ClassDB::bind_method(D_METHOD("cut"),&TextEdit::cut);
+ ClassDB::bind_method(D_METHOD("copy"),&TextEdit::copy);
+ ClassDB::bind_method(D_METHOD("paste"),&TextEdit::paste);
+ ClassDB::bind_method(D_METHOD("select_all"),&TextEdit::select_all);
+ ClassDB::bind_method(D_METHOD("select","from_line","from_column","to_line","to_column"),&TextEdit::select);
- ClassDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active);
- ClassDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line);
- ClassDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column);
- ClassDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line);
- ClassDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column);
- ClassDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text);
- ClassDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor);
- ClassDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind);
+ ClassDB::bind_method(D_METHOD("is_selection_active"),&TextEdit::is_selection_active);
+ ClassDB::bind_method(D_METHOD("get_selection_from_line"),&TextEdit::get_selection_from_line);
+ ClassDB::bind_method(D_METHOD("get_selection_from_column"),&TextEdit::get_selection_from_column);
+ ClassDB::bind_method(D_METHOD("get_selection_to_line"),&TextEdit::get_selection_to_line);
+ ClassDB::bind_method(D_METHOD("get_selection_to_column"),&TextEdit::get_selection_to_column);
+ ClassDB::bind_method(D_METHOD("get_selection_text"),&TextEdit::get_selection_text);
+ ClassDB::bind_method(D_METHOD("get_word_under_cursor"),&TextEdit::get_word_under_cursor);
+ ClassDB::bind_method(D_METHOD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind);
- ClassDB::bind_method(_MD("undo"),&TextEdit::undo);
- ClassDB::bind_method(_MD("redo"),&TextEdit::redo);
- ClassDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history);
+ ClassDB::bind_method(D_METHOD("undo"),&TextEdit::undo);
+ ClassDB::bind_method(D_METHOD("redo"),&TextEdit::redo);
+ ClassDB::bind_method(D_METHOD("clear_undo_history"),&TextEdit::clear_undo_history);
- ClassDB::bind_method(_MD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers);
- ClassDB::bind_method(_MD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled);
+ ClassDB::bind_method(D_METHOD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers);
+ ClassDB::bind_method(D_METHOD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled);
- ClassDB::bind_method(_MD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences);
- ClassDB::bind_method(_MD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled);
+ ClassDB::bind_method(D_METHOD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences);
+ ClassDB::bind_method(D_METHOD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled);
- ClassDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring);
- ClassDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled);
+ ClassDB::bind_method(D_METHOD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring);
+ ClassDB::bind_method(D_METHOD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled);
- ClassDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color);
- ClassDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false));
- ClassDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors);
- ClassDB::bind_method(_MD("menu_option"),&TextEdit::menu_option);
- ClassDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu);
+ ClassDB::bind_method(D_METHOD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color);
+ ClassDB::bind_method(D_METHOD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("clear_colors"),&TextEdit::clear_colors);
+ ClassDB::bind_method(D_METHOD("menu_option"),&TextEdit::menu_option);
+ ClassDB::bind_method(D_METHOD("get_menu:PopupMenu"),&TextEdit::get_menu);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), _SCS("set_syntax_coloring"), _SCS("is_syntax_coloring_enabled"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), _SCS("set_show_line_numbers"), _SCS("is_show_line_numbers_enabled"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), _SCS("set_highlight_all_occurrences"), _SCS("is_highlight_all_occurrences_enabled"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled");
ADD_GROUP("Caret","caret_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), _SCS("cursor_set_block_mode"), _SCS("cursor_is_block_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), "cursor_set_blink_speed","cursor_get_blink_speed") ;
ADD_SIGNAL(MethodInfo("cursor_changed"));
ADD_SIGNAL(MethodInfo("text_changed"));
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 03e37e9d9f..2f10de054a 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -28,40 +28,35 @@
/*************************************************************************/
#include "texture_button.h"
-
Size2 TextureButton::get_minimum_size() const {
- Size2 rscale;
- if (normal.is_null()) {
- if (pressed.is_null()) {
- if (hover.is_null())
- if (click_mask.is_null())
- rscale= Size2();
+ Size2 rscale = Control::get_minimum_size();
+
+ if (!expand) {
+ if (normal.is_null()) {
+ if (pressed.is_null()) {
+ if (hover.is_null())
+ if (click_mask.is_null())
+ rscale= Size2();
+ else
+ rscale= click_mask->get_size();
else
- rscale= click_mask->get_size();
- else
- rscale= hover->get_size();
- } else
- rscale=pressed->get_size();
+ rscale= hover->get_size();
+ } else
+ rscale=pressed->get_size();
- } else
- rscale= normal->get_size();
+ } else
+ rscale= normal->get_size();
+ }
- return rscale*scale.abs();
+ return rscale.abs();
}
-
bool TextureButton::has_point(const Point2& p_point) const {
- if (scale[0] == 0 || scale[1] == 0) {
- return false;
- }
-
- Point2 ppos = p_point/scale.abs();
-
if (click_mask.is_valid()) {
- Point2i p =ppos;
+ Point2i p =p_point;
if (p.x<0 || p.x>=click_mask->get_size().width || p.y<0 || p.y>=click_mask->get_size().height)
return false;
@@ -119,47 +114,107 @@ void TextureButton::_notification(int p_what) {
}
if (texdraw.is_valid()) {
- Rect2 drect(Point2(),texdraw->get_size()*scale);
- draw_texture_rect(texdraw,drect,false);
-
+ Point2 ofs;
+ Size2 size = texdraw->get_size();
+ Rect2 tex_regin = Rect2(Point2(), texdraw->get_size());
+ bool tile = false;
+ if (expand) {
+ switch (stretch_mode) {
+ case STRETCH_KEEP:
+ size = texdraw->get_size();
+ break;
+ case STRETCH_SCALE:
+ size = get_size();
+ break;
+ case STRETCH_TILE:
+ size = get_size();
+ tile = true;
+ break;
+ case STRETCH_KEEP_CENTERED:
+ ofs = (get_size() - texdraw->get_size())/2;
+ size = texdraw->get_size();
+ break;
+ case STRETCH_KEEP_ASPECT_CENTERED:
+ case STRETCH_KEEP_ASPECT: {
+ Size2 _size=get_size();
+ float tex_width = texdraw->get_width() * _size.height / texdraw->get_height();
+ float tex_height = _size.height;
+
+ if (tex_width > _size.width) {
+ tex_width = _size.width;
+ tex_height = texdraw->get_height() * tex_width / texdraw->get_width();
+ }
+
+ if (stretch_mode==STRETCH_KEEP_ASPECT_CENTERED) {
+ ofs.x = (_size.width - tex_width)/2;
+ ofs.y = (_size.height - tex_height)/2;
+ }
+ size.width = tex_width;
+ size.height = tex_height;
+ } break;
+ case STRETCH_KEEP_ASPECT_COVERED:{
+ size = get_size();
+ Size2 tex_size = texdraw->get_size();
+ Size2 scaleSize(size.width/tex_size.width, size.height/tex_size.height);
+ float scale = scaleSize.width > scaleSize.height? scaleSize.width : scaleSize.height;
+ Size2 scaledTexSize = tex_size * scale;
+ Point2 ofs = ((scaledTexSize - size) / scale).abs() / 2.0f;
+ tex_regin = Rect2(ofs, size/scale);
+ } break;
+ }
+ }
+ if (tile)
+ draw_texture_rect(texdraw,Rect2(ofs,size),tile);
+ else
+ draw_texture_rect_region(texdraw, Rect2(ofs, size), tex_regin);
}
if (has_focus() && focused.is_valid()) {
- Rect2 drect(Point2(),focused->get_size()*scale);
+ Rect2 drect(Point2(), get_size());
draw_texture_rect(focused,drect,false);
};
-
} break;
}
}
void TextureButton::_bind_methods() {
- ClassDB::bind_method(_MD("set_normal_texture","texture:Texture"),&TextureButton::set_normal_texture);
- ClassDB::bind_method(_MD("set_pressed_texture","texture:Texture"),&TextureButton::set_pressed_texture);
- ClassDB::bind_method(_MD("set_hover_texture","texture:Texture"),&TextureButton::set_hover_texture);
- ClassDB::bind_method(_MD("set_disabled_texture","texture:Texture"),&TextureButton::set_disabled_texture);
- ClassDB::bind_method(_MD("set_focused_texture","texture:Texture"),&TextureButton::set_focused_texture);
- ClassDB::bind_method(_MD("set_click_mask","mask:BitMap"),&TextureButton::set_click_mask);
- ClassDB::bind_method(_MD("set_texture_scale","scale"),&TextureButton::set_texture_scale);
-
- ClassDB::bind_method(_MD("get_normal_texture:Texture"),&TextureButton::get_normal_texture);
- ClassDB::bind_method(_MD("get_pressed_texture:Texture"),&TextureButton::get_pressed_texture);
- ClassDB::bind_method(_MD("get_hover_texture:Texture"),&TextureButton::get_hover_texture);
- ClassDB::bind_method(_MD("get_disabled_texture:Texture"),&TextureButton::get_disabled_texture);
- ClassDB::bind_method(_MD("get_focused_texture:Texture"),&TextureButton::get_focused_texture);
- ClassDB::bind_method(_MD("get_click_mask:BitMap"),&TextureButton::get_click_mask);
- ClassDB::bind_method(_MD("get_texture_scale"),&TextureButton::get_texture_scale);
+ ClassDB::bind_method(D_METHOD("set_normal_texture","texture:Texture"),&TextureButton::set_normal_texture);
+ ClassDB::bind_method(D_METHOD("set_pressed_texture","texture:Texture"),&TextureButton::set_pressed_texture);
+ ClassDB::bind_method(D_METHOD("set_hover_texture","texture:Texture"),&TextureButton::set_hover_texture);
+ ClassDB::bind_method(D_METHOD("set_disabled_texture","texture:Texture"),&TextureButton::set_disabled_texture);
+ ClassDB::bind_method(D_METHOD("set_focused_texture","texture:Texture"),&TextureButton::set_focused_texture);
+ ClassDB::bind_method(D_METHOD("set_click_mask","mask:BitMap"),&TextureButton::set_click_mask);
+ ClassDB::bind_method(D_METHOD("set_expand","p_expand"),&TextureButton::set_expand);
+ ClassDB::bind_method(D_METHOD("set_stretch_mode","p_mode"),&TextureButton::set_stretch_mode);
+
+ ClassDB::bind_method(D_METHOD("get_normal_texture:Texture"),&TextureButton::get_normal_texture);
+ ClassDB::bind_method(D_METHOD("get_pressed_texture:Texture"),&TextureButton::get_pressed_texture);
+ ClassDB::bind_method(D_METHOD("get_hover_texture:Texture"),&TextureButton::get_hover_texture);
+ ClassDB::bind_method(D_METHOD("get_disabled_texture:Texture"),&TextureButton::get_disabled_texture);
+ ClassDB::bind_method(D_METHOD("get_focused_texture:Texture"),&TextureButton::get_focused_texture);
+ ClassDB::bind_method(D_METHOD("get_click_mask:BitMap"),&TextureButton::get_click_mask);
+ ClassDB::bind_method(D_METHOD("get_expand"),&TextureButton::get_expand);
+ ClassDB::bind_method(D_METHOD("get_stretch_mode"),&TextureButton::get_stretch_mode);
ADD_GROUP("Textures","texture_");
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_normal_texture"), _SCS("get_normal_texture"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_pressed_texture"), _SCS("get_pressed_texture"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_hover",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_hover_texture"), _SCS("get_hover_texture"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ;
- ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"texture_scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_texture_scale"), _SCS("get_texture_scale"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_normal_texture", "get_normal_texture");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_pressed_texture", "get_pressed_texture");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_hover",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_hover_texture", "get_hover_texture");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_disabled_texture", "get_disabled_texture");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_focused_texture", "get_focused_texture");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"texture_click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), "set_click_mask", "get_click_mask") ;
+ ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL,"expand",PROPERTY_HINT_RESOURCE_TYPE,"bool"), "set_expand", "get_expand") ;
+ ADD_PROPERTYNO(PropertyInfo(Variant::INT,"stretch_mode",PROPERTY_HINT_ENUM,"Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
+
+ BIND_CONSTANT(STRETCH_SCALE);
+ BIND_CONSTANT(STRETCH_TILE);
+ BIND_CONSTANT(STRETCH_KEEP);
+ BIND_CONSTANT(STRETCH_KEEP_CENTERED);
+ BIND_CONSTANT(STRETCH_KEEP_ASPECT);
+ BIND_CONSTANT(STRETCH_KEEP_ASPECT_CENTERED);
+ BIND_CONSTANT(STRETCH_KEEP_ASPECT_COVERED);
}
@@ -227,19 +282,26 @@ void TextureButton::set_focused_texture(const Ref<Texture>& p_focused) {
focused = p_focused;
};
-void TextureButton::set_texture_scale(Size2 p_scale) {
+bool TextureButton::get_expand() const {
+ return expand;
+}
- scale=p_scale;
+void TextureButton::set_expand(bool p_expand) {
+ expand = p_expand;
minimum_size_changed();
update();
}
-Size2 TextureButton::get_texture_scale() const{
+void TextureButton::set_stretch_mode(StretchMode p_mode) {
+ stretch_mode = p_mode;
+ update();
+}
- return scale;
+TextureButton::StretchMode TextureButton::get_stretch_mode() const {
+ return stretch_mode;
}
TextureButton::TextureButton() {
- scale=Size2(1.0, 1.0);
-
+ expand = false;
+ stretch_mode = STRETCH_SCALE;
}
diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h
index ef4d4d5b5b..64103860bf 100644
--- a/scene/gui/texture_button.h
+++ b/scene/gui/texture_button.h
@@ -35,18 +35,31 @@ class TextureButton : public BaseButton {
GDCLASS( TextureButton, BaseButton );
+public:
+ enum StretchMode {
+ STRETCH_SCALE,
+ STRETCH_TILE,
+ STRETCH_KEEP,
+ STRETCH_KEEP_CENTERED,
+ STRETCH_KEEP_ASPECT,
+ STRETCH_KEEP_ASPECT_CENTERED,
+ STRETCH_KEEP_ASPECT_COVERED,
+ };
+
+private:
Ref<Texture> normal;
Ref<Texture> pressed;
Ref<Texture> hover;
Ref<Texture> disabled;
Ref<Texture> focused;
Ref<BitMap> click_mask;
- Size2 scale;
+ bool expand;
+ StretchMode stretch_mode;
protected:
- virtual bool has_point(const Point2& p_point) const;
virtual Size2 get_minimum_size() const;
+ virtual bool has_point(const Point2& p_point) const;
void _notification(int p_what);
static void _bind_methods();
@@ -66,10 +79,15 @@ public:
Ref<Texture> get_focused_texture() const;
Ref<BitMap> get_click_mask() const;
- void set_texture_scale(Size2 p_scale);
- Size2 get_texture_scale() const;
+ bool get_expand() const;
+ void set_expand(bool p_expand);
+
+ void set_stretch_mode(StretchMode stretch_mode);
+ StretchMode get_stretch_mode() const;
TextureButton();
};
+
+VARIANT_ENUM_CAST( TextureButton::StretchMode );
#endif // TEXTURE_BUTTON_H
diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp
index 7d8373976b..3897647502 100644
--- a/scene/gui/texture_progress.cpp
+++ b/scene/gui/texture_progress.cpp
@@ -257,36 +257,36 @@ Point2 TextureProgress::get_radial_center_offset()
void TextureProgress::_bind_methods() {
- ClassDB::bind_method(_MD("set_under_texture","tex"),&TextureProgress::set_under_texture);
- ClassDB::bind_method(_MD("get_under_texture"),&TextureProgress::get_under_texture);
+ ClassDB::bind_method(D_METHOD("set_under_texture","tex"),&TextureProgress::set_under_texture);
+ ClassDB::bind_method(D_METHOD("get_under_texture"),&TextureProgress::get_under_texture);
- ClassDB::bind_method(_MD("set_progress_texture","tex"),&TextureProgress::set_progress_texture);
- ClassDB::bind_method(_MD("get_progress_texture"),&TextureProgress::get_progress_texture);
+ ClassDB::bind_method(D_METHOD("set_progress_texture","tex"),&TextureProgress::set_progress_texture);
+ ClassDB::bind_method(D_METHOD("get_progress_texture"),&TextureProgress::get_progress_texture);
- ClassDB::bind_method(_MD("set_over_texture","tex"),&TextureProgress::set_over_texture);
- ClassDB::bind_method(_MD("get_over_texture"),&TextureProgress::get_over_texture);
+ ClassDB::bind_method(D_METHOD("set_over_texture","tex"),&TextureProgress::set_over_texture);
+ ClassDB::bind_method(D_METHOD("get_over_texture"),&TextureProgress::get_over_texture);
- ClassDB::bind_method(_MD("set_fill_mode","mode"),&TextureProgress::set_fill_mode);
- ClassDB::bind_method(_MD("get_fill_mode"), &TextureProgress::get_fill_mode);
+ ClassDB::bind_method(D_METHOD("set_fill_mode","mode"),&TextureProgress::set_fill_mode);
+ ClassDB::bind_method(D_METHOD("get_fill_mode"), &TextureProgress::get_fill_mode);
- ClassDB::bind_method(_MD("set_radial_initial_angle","mode"),&TextureProgress::set_radial_initial_angle);
- ClassDB::bind_method(_MD("get_radial_initial_angle"), &TextureProgress::get_radial_initial_angle);
+ ClassDB::bind_method(D_METHOD("set_radial_initial_angle","mode"),&TextureProgress::set_radial_initial_angle);
+ ClassDB::bind_method(D_METHOD("get_radial_initial_angle"), &TextureProgress::get_radial_initial_angle);
- ClassDB::bind_method(_MD("set_radial_center_offset","mode"),&TextureProgress::set_radial_center_offset);
- ClassDB::bind_method(_MD("get_radial_center_offset"), &TextureProgress::get_radial_center_offset);
+ ClassDB::bind_method(D_METHOD("set_radial_center_offset","mode"),&TextureProgress::set_radial_center_offset);
+ ClassDB::bind_method(D_METHOD("get_radial_center_offset"), &TextureProgress::get_radial_center_offset);
- ClassDB::bind_method(_MD("set_fill_degrees","mode"),&TextureProgress::set_fill_degrees);
- ClassDB::bind_method(_MD("get_fill_degrees"), &TextureProgress::get_fill_degrees);
+ ClassDB::bind_method(D_METHOD("set_fill_degrees","mode"),&TextureProgress::set_fill_degrees);
+ ClassDB::bind_method(D_METHOD("get_fill_degrees"), &TextureProgress::get_fill_degrees);
ADD_GROUP("Textures","texture_");
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_under",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_under_texture"),_SCS("get_under_texture"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_over",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_over_texture"),_SCS("get_over_texture"));
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_progress",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_progress_texture"),_SCS("get_progress_texture"));
- ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"fill_mode",PROPERTY_HINT_ENUM,"Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise"),_SCS("set_fill_mode"),_SCS("get_fill_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_under",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_under_texture","get_under_texture");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_over",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_over_texture","get_over_texture");
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture_progress",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_progress_texture","get_progress_texture");
+ ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"fill_mode",PROPERTY_HINT_ENUM,"Left to Right,Right to Left,Top to Bottom,Bottom to Top,Clockwise,Counter Clockwise"),"set_fill_mode","get_fill_mode");
ADD_GROUP("Radial Fill","radial_");
- ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_initial_angle",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),_SCS("set_radial_initial_angle"),_SCS("get_radial_initial_angle"));
- ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_fill_degrees",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),_SCS("set_fill_degrees"),_SCS("get_fill_degrees"));
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"radial_center_offset"),_SCS("set_radial_center_offset"),_SCS("get_radial_center_offset"));
+ ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_initial_angle",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),"set_radial_initial_angle","get_radial_initial_angle");
+ ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"radial_fill_degrees",PROPERTY_HINT_RANGE,"0.0,360.0,0.1,slider"),"set_fill_degrees","get_fill_degrees");
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"radial_center_offset"),"set_radial_center_offset","get_radial_center_offset");
BIND_CONSTANT( FILL_LEFT_TO_RIGHT );
BIND_CONSTANT( FILL_RIGHT_TO_LEFT );
diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp
index 6a4b59c5ec..f2fe3eae12 100644
--- a/scene/gui/texture_rect.cpp
+++ b/scene/gui/texture_rect.cpp
@@ -79,7 +79,15 @@ void TextureRect::_notification(int p_what) {
draw_texture_rect(texture,Rect2(ofs_x,ofs_y,tex_width,tex_height));
} break;
-
+ case STRETCH_KEEP_ASPECT_COVERED: {
+ Size2 size = get_size();
+ Size2 tex_size = texture->get_size();
+ Size2 scaleSize(size.width/tex_size.width, size.height/tex_size.height);
+ float scale = scaleSize.width > scaleSize.height? scaleSize.width : scaleSize.height;
+ Size2 scaledTexSize = tex_size * scale;
+ Point2 ofs = ((scaledTexSize - size) / scale).abs() / 2.0f;
+ draw_texture_rect_region(texture, Rect2(Point2(), size), Rect2(ofs, size/scale));
+ } break;
}
}
@@ -95,16 +103,16 @@ Size2 TextureRect::get_minimum_size() const {
void TextureRect::_bind_methods() {
- ClassDB::bind_method(_MD("set_texture","texture"), & TextureRect::set_texture );
- ClassDB::bind_method(_MD("get_texture"), & TextureRect::get_texture );
- ClassDB::bind_method(_MD("set_expand","enable"), & TextureRect::set_expand );
- ClassDB::bind_method(_MD("has_expand"), & TextureRect::has_expand );
- ClassDB::bind_method(_MD("set_stretch_mode","stretch_mode"), & TextureRect::set_stretch_mode );
- ClassDB::bind_method(_MD("get_stretch_mode"), & TextureRect::get_stretch_mode );
+ ClassDB::bind_method(D_METHOD("set_texture","texture"), & TextureRect::set_texture );
+ ClassDB::bind_method(D_METHOD("get_texture"), & TextureRect::get_texture );
+ ClassDB::bind_method(D_METHOD("set_expand","enable"), & TextureRect::set_expand );
+ ClassDB::bind_method(D_METHOD("has_expand"), & TextureRect::has_expand );
+ ClassDB::bind_method(D_METHOD("set_stretch_mode","stretch_mode"), & TextureRect::set_stretch_mode );
+ ClassDB::bind_method(D_METHOD("get_stretch_mode"), & TextureRect::get_stretch_mode );
- ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") );
- ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered"), _SCS("set_stretch_mode"),_SCS("get_stretch_mode") );
+ ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "expand" ), "set_expand","has_expand");
+ ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
BIND_CONSTANT( STRETCH_SCALE_ON_EXPAND );
BIND_CONSTANT( STRETCH_SCALE );
@@ -113,7 +121,7 @@ void TextureRect::_bind_methods() {
BIND_CONSTANT( STRETCH_KEEP_CENTERED );
BIND_CONSTANT( STRETCH_KEEP_ASPECT );
BIND_CONSTANT( STRETCH_KEEP_ASPECT_CENTERED );
-
+ BIND_CONSTANT( STRETCH_KEEP_ASPECT_COVERED );
}
diff --git a/scene/gui/texture_rect.h b/scene/gui/texture_rect.h
index e95d742759..0d72458909 100644
--- a/scene/gui/texture_rect.h
+++ b/scene/gui/texture_rect.h
@@ -45,7 +45,7 @@ public:
STRETCH_KEEP_CENTERED,
STRETCH_KEEP_ASPECT,
STRETCH_KEEP_ASPECT_CENTERED,
-
+ STRETCH_KEEP_ASPECT_COVERED,
};
private:
bool expand;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 1a7392f27e..292efdcc01 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -30,7 +30,7 @@
#include "print_string.h"
#include "os/os.h"
#include "os/keyboard.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/input.h"
#include "scene/main/viewport.h"
@@ -657,76 +657,76 @@ Color TreeItem::get_custom_bg_color(int p_column) const {
void TreeItem::_bind_methods() {
- ClassDB::bind_method(_MD("set_cell_mode","column","mode"),&TreeItem::set_cell_mode);
- ClassDB::bind_method(_MD("get_cell_mode","column"),&TreeItem::get_cell_mode);
+ ClassDB::bind_method(D_METHOD("set_cell_mode","column","mode"),&TreeItem::set_cell_mode);
+ ClassDB::bind_method(D_METHOD("get_cell_mode","column"),&TreeItem::get_cell_mode);
- ClassDB::bind_method(_MD("set_checked","column","checked"),&TreeItem::set_checked);
- ClassDB::bind_method(_MD("is_checked","column"),&TreeItem::is_checked);
+ ClassDB::bind_method(D_METHOD("set_checked","column","checked"),&TreeItem::set_checked);
+ ClassDB::bind_method(D_METHOD("is_checked","column"),&TreeItem::is_checked);
- ClassDB::bind_method(_MD("set_text","column","text"),&TreeItem::set_text);
- ClassDB::bind_method(_MD("get_text","column"),&TreeItem::get_text);
+ ClassDB::bind_method(D_METHOD("set_text","column","text"),&TreeItem::set_text);
+ ClassDB::bind_method(D_METHOD("get_text","column"),&TreeItem::get_text);
- ClassDB::bind_method(_MD("set_icon","column","texture:Texture"),&TreeItem::set_icon);
- ClassDB::bind_method(_MD("get_icon:Texture","column"),&TreeItem::get_icon);
+ ClassDB::bind_method(D_METHOD("set_icon","column","texture:Texture"),&TreeItem::set_icon);
+ ClassDB::bind_method(D_METHOD("get_icon:Texture","column"),&TreeItem::get_icon);
- ClassDB::bind_method(_MD("set_icon_region","column","region"),&TreeItem::set_icon_region);
- ClassDB::bind_method(_MD("get_icon_region","column"),&TreeItem::get_icon_region);
+ ClassDB::bind_method(D_METHOD("set_icon_region","column","region"),&TreeItem::set_icon_region);
+ ClassDB::bind_method(D_METHOD("get_icon_region","column"),&TreeItem::get_icon_region);
- ClassDB::bind_method(_MD("set_icon_max_width","column","width"),&TreeItem::set_icon_max_width);
- ClassDB::bind_method(_MD("get_icon_max_width","column"),&TreeItem::get_icon_max_width);
+ ClassDB::bind_method(D_METHOD("set_icon_max_width","column","width"),&TreeItem::set_icon_max_width);
+ ClassDB::bind_method(D_METHOD("get_icon_max_width","column"),&TreeItem::get_icon_max_width);
- ClassDB::bind_method(_MD("set_range","column","value"),&TreeItem::set_range);
- ClassDB::bind_method(_MD("get_range","column"),&TreeItem::get_range);
- ClassDB::bind_method(_MD("set_range_config","column","min","max","step","expr"),&TreeItem::set_range_config,DEFVAL(false));
- ClassDB::bind_method(_MD("get_range_config","column"),&TreeItem::_get_range_config);
+ ClassDB::bind_method(D_METHOD("set_range","column","value"),&TreeItem::set_range);
+ ClassDB::bind_method(D_METHOD("get_range","column"),&TreeItem::get_range);
+ ClassDB::bind_method(D_METHOD("set_range_config","column","min","max","step","expr"),&TreeItem::set_range_config,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_range_config","column"),&TreeItem::_get_range_config);
- ClassDB::bind_method(_MD("set_metadata","column","meta"),&TreeItem::set_metadata);
- ClassDB::bind_method(_MD("get_metadata","column"),&TreeItem::get_metadata);
+ ClassDB::bind_method(D_METHOD("set_metadata","column","meta"),&TreeItem::set_metadata);
+ ClassDB::bind_method(D_METHOD("get_metadata","column"),&TreeItem::get_metadata);
- ClassDB::bind_method(_MD("set_custom_draw","column","object","callback"),&TreeItem::set_custom_draw);
+ ClassDB::bind_method(D_METHOD("set_custom_draw","column","object","callback"),&TreeItem::set_custom_draw);
- ClassDB::bind_method(_MD("set_collapsed","enable"),&TreeItem::set_collapsed);
- ClassDB::bind_method(_MD("is_collapsed"),&TreeItem::is_collapsed);
+ ClassDB::bind_method(D_METHOD("set_collapsed","enable"),&TreeItem::set_collapsed);
+ ClassDB::bind_method(D_METHOD("is_collapsed"),&TreeItem::is_collapsed);
- ClassDB::bind_method(_MD("get_next:TreeItem"),&TreeItem::get_next);
- ClassDB::bind_method(_MD("get_prev:TreeItem"),&TreeItem::get_prev);
- ClassDB::bind_method(_MD("get_parent:TreeItem"),&TreeItem::get_parent);
- ClassDB::bind_method(_MD("get_children:TreeItem"),&TreeItem::get_children);
+ ClassDB::bind_method(D_METHOD("get_next:TreeItem"),&TreeItem::get_next);
+ ClassDB::bind_method(D_METHOD("get_prev:TreeItem"),&TreeItem::get_prev);
+ ClassDB::bind_method(D_METHOD("get_parent:TreeItem"),&TreeItem::get_parent);
+ ClassDB::bind_method(D_METHOD("get_children:TreeItem"),&TreeItem::get_children);
- ClassDB::bind_method(_MD("get_next_visible:TreeItem"),&TreeItem::get_next_visible);
- ClassDB::bind_method(_MD("get_prev_visible:TreeItem"),&TreeItem::get_prev_visible);
+ ClassDB::bind_method(D_METHOD("get_next_visible:TreeItem"),&TreeItem::get_next_visible);
+ ClassDB::bind_method(D_METHOD("get_prev_visible:TreeItem"),&TreeItem::get_prev_visible);
- ClassDB::bind_method(_MD("remove_child:TreeItem","child"),&TreeItem::_remove_child);
+ ClassDB::bind_method(D_METHOD("remove_child:TreeItem","child"),&TreeItem::_remove_child);
- ClassDB::bind_method(_MD("set_selectable","column","selectable"),&TreeItem::set_selectable);
- ClassDB::bind_method(_MD("is_selectable","column"),&TreeItem::is_selectable);
+ ClassDB::bind_method(D_METHOD("set_selectable","column","selectable"),&TreeItem::set_selectable);
+ ClassDB::bind_method(D_METHOD("is_selectable","column"),&TreeItem::is_selectable);
- ClassDB::bind_method(_MD("is_selected","column"),&TreeItem::is_selected);
- ClassDB::bind_method(_MD("select","column"),&TreeItem::select);
- ClassDB::bind_method(_MD("deselect","column"),&TreeItem::deselect);
+ ClassDB::bind_method(D_METHOD("is_selected","column"),&TreeItem::is_selected);
+ ClassDB::bind_method(D_METHOD("select","column"),&TreeItem::select);
+ ClassDB::bind_method(D_METHOD("deselect","column"),&TreeItem::deselect);
- ClassDB::bind_method(_MD("set_editable","column","enabled"),&TreeItem::set_editable);
- ClassDB::bind_method(_MD("is_editable","column"),&TreeItem::is_editable);
+ ClassDB::bind_method(D_METHOD("set_editable","column","enabled"),&TreeItem::set_editable);
+ ClassDB::bind_method(D_METHOD("is_editable","column"),&TreeItem::is_editable);
- ClassDB::bind_method(_MD("set_custom_color","column","color"),&TreeItem::set_custom_color);
- ClassDB::bind_method(_MD("clear_custom_color","column"),&TreeItem::clear_custom_color);
+ ClassDB::bind_method(D_METHOD("set_custom_color","column","color"),&TreeItem::set_custom_color);
+ ClassDB::bind_method(D_METHOD("clear_custom_color","column"),&TreeItem::clear_custom_color);
- ClassDB::bind_method(_MD("set_custom_bg_color","column","color","just_outline"),&TreeItem::set_custom_bg_color,DEFVAL(false));
- ClassDB::bind_method(_MD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color);
- ClassDB::bind_method(_MD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color);
+ ClassDB::bind_method(D_METHOD("set_custom_bg_color","column","color","just_outline"),&TreeItem::set_custom_bg_color,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color);
+ ClassDB::bind_method(D_METHOD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color);
- ClassDB::bind_method(_MD("add_button","column","button:Texture","button_idx","disabled"),&TreeItem::add_button,DEFVAL(-1),DEFVAL(false));
- ClassDB::bind_method(_MD("get_button_count","column"),&TreeItem::get_button_count);
- ClassDB::bind_method(_MD("get_button:Texture","column","button_idx"),&TreeItem::get_button);
- ClassDB::bind_method(_MD("set_button","column","button_idx","button:Texture"),&TreeItem::set_button);
- ClassDB::bind_method(_MD("erase_button","column","button_idx"),&TreeItem::erase_button);
- ClassDB::bind_method(_MD("is_button_disabled","column","button_idx"),&TreeItem::is_button_disabled);
+ ClassDB::bind_method(D_METHOD("add_button","column","button:Texture","button_idx","disabled"),&TreeItem::add_button,DEFVAL(-1),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_button_count","column"),&TreeItem::get_button_count);
+ ClassDB::bind_method(D_METHOD("get_button:Texture","column","button_idx"),&TreeItem::get_button);
+ ClassDB::bind_method(D_METHOD("set_button","column","button_idx","button:Texture"),&TreeItem::set_button);
+ ClassDB::bind_method(D_METHOD("erase_button","column","button_idx"),&TreeItem::erase_button);
+ ClassDB::bind_method(D_METHOD("is_button_disabled","column","button_idx"),&TreeItem::is_button_disabled);
- ClassDB::bind_method(_MD("set_tooltip","column","tooltip"),&TreeItem::set_tooltip);
- ClassDB::bind_method(_MD("get_tooltip","column"),&TreeItem::get_tooltip);
+ ClassDB::bind_method(D_METHOD("set_tooltip","column","tooltip"),&TreeItem::set_tooltip);
+ ClassDB::bind_method(D_METHOD("get_tooltip","column"),&TreeItem::get_tooltip);
- ClassDB::bind_method(_MD("move_to_top"),&TreeItem::move_to_top);
- ClassDB::bind_method(_MD("move_to_bottom"),&TreeItem::move_to_bottom);
+ ClassDB::bind_method(D_METHOD("move_to_top"),&TreeItem::move_to_top);
+ ClassDB::bind_method(D_METHOD("move_to_bottom"),&TreeItem::move_to_bottom);
BIND_CONSTANT( CELL_MODE_STRING );
BIND_CONSTANT( CELL_MODE_CHECK );
@@ -1610,6 +1610,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
cache.click_id=c.buttons[j].id;
cache.click_item=p_item;
cache.click_column=col;
+ cache.click_pos=get_global_mouse_pos()-get_global_pos();
update();
//emit_signal("button_pressed");
return -1;
@@ -2390,6 +2391,8 @@ void Tree::_gui_input(InputEvent p_event) {
if (cache.click_type==Cache::CLICK_BUTTON) {
+ // make sure in case of wrong reference after reconstructing whole TreeItems
+ cache.click_item=get_item_at_pos(cache.click_pos);
emit_signal("button_pressed",cache.click_item,cache.click_column,cache.click_id);
}
@@ -2970,7 +2973,6 @@ void Tree::clear() {
selected_item=NULL;
edited_item=NULL;
popup_edited_item=NULL;
- selected_item=NULL;
update();
};
@@ -3586,59 +3588,59 @@ bool Tree::get_allow_rmb_select() const{
void Tree::_bind_methods() {
- ClassDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout);
- ClassDB::bind_method(_MD("_gui_input"),&Tree::_gui_input);
- ClassDB::bind_method(_MD("_popup_select"),&Tree::popup_select);
- ClassDB::bind_method(_MD("_text_editor_enter"),&Tree::text_editor_enter);
- ClassDB::bind_method(_MD("_text_editor_modal_close"),&Tree::_text_editor_modal_close);
- ClassDB::bind_method(_MD("_value_editor_changed"),&Tree::value_editor_changed);
- ClassDB::bind_method(_MD("_scroll_moved"),&Tree::_scroll_moved);
+ ClassDB::bind_method(D_METHOD("_range_click_timeout"),&Tree::_range_click_timeout);
+ ClassDB::bind_method(D_METHOD("_gui_input"),&Tree::_gui_input);
+ ClassDB::bind_method(D_METHOD("_popup_select"),&Tree::popup_select);
+ ClassDB::bind_method(D_METHOD("_text_editor_enter"),&Tree::text_editor_enter);
+ ClassDB::bind_method(D_METHOD("_text_editor_modal_close"),&Tree::_text_editor_modal_close);
+ ClassDB::bind_method(D_METHOD("_value_editor_changed"),&Tree::value_editor_changed);
+ ClassDB::bind_method(D_METHOD("_scroll_moved"),&Tree::_scroll_moved);
- ClassDB::bind_method(_MD("clear"),&Tree::clear);
- ClassDB::bind_method(_MD("create_item:TreeItem","parent:TreeItem"),&Tree::_create_item,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("clear"),&Tree::clear);
+ ClassDB::bind_method(D_METHOD("create_item:TreeItem","parent:TreeItem"),&Tree::_create_item,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("get_root:TreeItem"),&Tree::get_root);
- ClassDB::bind_method(_MD("set_column_min_width","column","min_width"),&Tree::set_column_min_width);
- ClassDB::bind_method(_MD("set_column_expand","column","expand"),&Tree::set_column_expand);
- ClassDB::bind_method(_MD("get_column_width","column"),&Tree::get_column_width);
+ ClassDB::bind_method(D_METHOD("get_root:TreeItem"),&Tree::get_root);
+ ClassDB::bind_method(D_METHOD("set_column_min_width","column","min_width"),&Tree::set_column_min_width);
+ ClassDB::bind_method(D_METHOD("set_column_expand","column","expand"),&Tree::set_column_expand);
+ ClassDB::bind_method(D_METHOD("get_column_width","column"),&Tree::get_column_width);
- ClassDB::bind_method(_MD("set_hide_root","enable"),&Tree::set_hide_root);
- ClassDB::bind_method(_MD("get_next_selected:TreeItem","from:TreeItem"),&Tree::_get_next_selected);
- ClassDB::bind_method(_MD("get_selected:TreeItem"),&Tree::get_selected);
- ClassDB::bind_method(_MD("get_selected_column"),&Tree::get_selected_column);
- ClassDB::bind_method(_MD("get_pressed_button"),&Tree::get_pressed_button);
- ClassDB::bind_method(_MD("set_select_mode","mode"),&Tree::set_select_mode);
+ ClassDB::bind_method(D_METHOD("set_hide_root","enable"),&Tree::set_hide_root);
+ ClassDB::bind_method(D_METHOD("get_next_selected:TreeItem","from:TreeItem"),&Tree::_get_next_selected);
+ ClassDB::bind_method(D_METHOD("get_selected:TreeItem"),&Tree::get_selected);
+ ClassDB::bind_method(D_METHOD("get_selected_column"),&Tree::get_selected_column);
+ ClassDB::bind_method(D_METHOD("get_pressed_button"),&Tree::get_pressed_button);
+ ClassDB::bind_method(D_METHOD("set_select_mode","mode"),&Tree::set_select_mode);
- ClassDB::bind_method(_MD("set_columns","amount"),&Tree::set_columns);
- ClassDB::bind_method(_MD("get_columns"),&Tree::get_columns);
+ ClassDB::bind_method(D_METHOD("set_columns","amount"),&Tree::set_columns);
+ ClassDB::bind_method(D_METHOD("get_columns"),&Tree::get_columns);
- ClassDB::bind_method(_MD("get_edited:TreeItem"),&Tree::get_edited);
- ClassDB::bind_method(_MD("get_edited_column"),&Tree::get_edited_column);
- ClassDB::bind_method(_MD("get_custom_popup_rect"),&Tree::get_custom_popup_rect);
- ClassDB::bind_method(_MD("get_item_area_rect","item:TreeItem","column"),&Tree::_get_item_rect,DEFVAL(-1));
- ClassDB::bind_method(_MD("get_item_at_pos:TreeItem","pos"),&Tree::get_item_at_pos);
- ClassDB::bind_method(_MD("get_column_at_pos","pos"),&Tree::get_column_at_pos);
+ ClassDB::bind_method(D_METHOD("get_edited:TreeItem"),&Tree::get_edited);
+ ClassDB::bind_method(D_METHOD("get_edited_column"),&Tree::get_edited_column);
+ ClassDB::bind_method(D_METHOD("get_custom_popup_rect"),&Tree::get_custom_popup_rect);
+ ClassDB::bind_method(D_METHOD("get_item_area_rect","item:TreeItem","column"),&Tree::_get_item_rect,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_item_at_pos:TreeItem","pos"),&Tree::get_item_at_pos);
+ ClassDB::bind_method(D_METHOD("get_column_at_pos","pos"),&Tree::get_column_at_pos);
- ClassDB::bind_method(_MD("ensure_cursor_is_visible"),&Tree::ensure_cursor_is_visible);
+ ClassDB::bind_method(D_METHOD("ensure_cursor_is_visible"),&Tree::ensure_cursor_is_visible);
- ClassDB::bind_method(_MD("set_column_titles_visible","visible"),&Tree::set_column_titles_visible);
- ClassDB::bind_method(_MD("are_column_titles_visible"),&Tree::are_column_titles_visible);
+ ClassDB::bind_method(D_METHOD("set_column_titles_visible","visible"),&Tree::set_column_titles_visible);
+ ClassDB::bind_method(D_METHOD("are_column_titles_visible"),&Tree::are_column_titles_visible);
- ClassDB::bind_method(_MD("set_column_title","column","title"),&Tree::set_column_title);
- ClassDB::bind_method(_MD("get_column_title","column"),&Tree::get_column_title);
- ClassDB::bind_method(_MD("get_scroll"),&Tree::get_scroll);
+ ClassDB::bind_method(D_METHOD("set_column_title","column","title"),&Tree::set_column_title);
+ ClassDB::bind_method(D_METHOD("get_column_title","column"),&Tree::get_column_title);
+ ClassDB::bind_method(D_METHOD("get_scroll"),&Tree::get_scroll);
- ClassDB::bind_method(_MD("set_hide_folding","hide"),&Tree::set_hide_folding);
- ClassDB::bind_method(_MD("is_folding_hidden"),&Tree::is_folding_hidden);
+ ClassDB::bind_method(D_METHOD("set_hide_folding","hide"),&Tree::set_hide_folding);
+ ClassDB::bind_method(D_METHOD("is_folding_hidden"),&Tree::is_folding_hidden);
- ClassDB::bind_method(_MD("set_drop_mode_flags","flags"),&Tree::set_drop_mode_flags);
- ClassDB::bind_method(_MD("get_drop_mode_flags"),&Tree::get_drop_mode_flags);
+ ClassDB::bind_method(D_METHOD("set_drop_mode_flags","flags"),&Tree::set_drop_mode_flags);
+ ClassDB::bind_method(D_METHOD("get_drop_mode_flags"),&Tree::get_drop_mode_flags);
- ClassDB::bind_method(_MD("set_allow_rmb_select","allow"),&Tree::set_allow_rmb_select);
- ClassDB::bind_method(_MD("get_allow_rmb_select"),&Tree::get_allow_rmb_select);
+ ClassDB::bind_method(D_METHOD("set_allow_rmb_select","allow"),&Tree::set_allow_rmb_select);
+ ClassDB::bind_method(D_METHOD("get_allow_rmb_select"),&Tree::get_allow_rmb_select);
- ClassDB::bind_method(_MD("set_single_select_cell_editing_only_when_already_selected","enable"),&Tree::set_single_select_cell_editing_only_when_already_selected);
- ClassDB::bind_method(_MD("get_single_select_cell_editing_only_when_already_selected"),&Tree::get_single_select_cell_editing_only_when_already_selected);
+ ClassDB::bind_method(D_METHOD("set_single_select_cell_editing_only_when_already_selected","enable"),&Tree::set_single_select_cell_editing_only_when_already_selected);
+ ClassDB::bind_method(D_METHOD("get_single_select_cell_editing_only_when_already_selected"),&Tree::get_single_select_cell_editing_only_when_already_selected);
ADD_SIGNAL( MethodInfo("item_selected"));
ADD_SIGNAL( MethodInfo("cell_selected"));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 351cc4cb50..14bd2efbaa 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -409,6 +409,7 @@ friend class TreeItem;
TreeItem *click_item;
int click_column;
int hover_index;
+ Point2 click_pos;
} cache;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index 46c0eeca65..063ad8c44a 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -358,48 +358,48 @@ bool VideoPlayer::has_autoplay() const {
void VideoPlayer::_bind_methods() {
- ClassDB::bind_method(_MD("set_stream","stream:VideoStream"),&VideoPlayer::set_stream);
- ClassDB::bind_method(_MD("get_stream:VideoStream"),&VideoPlayer::get_stream);
+ ClassDB::bind_method(D_METHOD("set_stream","stream:VideoStream"),&VideoPlayer::set_stream);
+ ClassDB::bind_method(D_METHOD("get_stream:VideoStream"),&VideoPlayer::get_stream);
- ClassDB::bind_method(_MD("play"),&VideoPlayer::play);
- ClassDB::bind_method(_MD("stop"),&VideoPlayer::stop);
+ ClassDB::bind_method(D_METHOD("play"),&VideoPlayer::play);
+ ClassDB::bind_method(D_METHOD("stop"),&VideoPlayer::stop);
- ClassDB::bind_method(_MD("is_playing"),&VideoPlayer::is_playing);
+ ClassDB::bind_method(D_METHOD("is_playing"),&VideoPlayer::is_playing);
- ClassDB::bind_method(_MD("set_paused","paused"),&VideoPlayer::set_paused);
- ClassDB::bind_method(_MD("is_paused"),&VideoPlayer::is_paused);
+ ClassDB::bind_method(D_METHOD("set_paused","paused"),&VideoPlayer::set_paused);
+ ClassDB::bind_method(D_METHOD("is_paused"),&VideoPlayer::is_paused);
- ClassDB::bind_method(_MD("set_volume","volume"),&VideoPlayer::set_volume);
- ClassDB::bind_method(_MD("get_volume"),&VideoPlayer::get_volume);
+ ClassDB::bind_method(D_METHOD("set_volume","volume"),&VideoPlayer::set_volume);
+ ClassDB::bind_method(D_METHOD("get_volume"),&VideoPlayer::get_volume);
- ClassDB::bind_method(_MD("set_volume_db","db"),&VideoPlayer::set_volume_db);
- ClassDB::bind_method(_MD("get_volume_db"),&VideoPlayer::get_volume_db);
+ ClassDB::bind_method(D_METHOD("set_volume_db","db"),&VideoPlayer::set_volume_db);
+ ClassDB::bind_method(D_METHOD("get_volume_db"),&VideoPlayer::get_volume_db);
- ClassDB::bind_method(_MD("set_audio_track","track"),&VideoPlayer::set_audio_track);
- ClassDB::bind_method(_MD("get_audio_track"),&VideoPlayer::get_audio_track);
+ ClassDB::bind_method(D_METHOD("set_audio_track","track"),&VideoPlayer::set_audio_track);
+ ClassDB::bind_method(D_METHOD("get_audio_track"),&VideoPlayer::get_audio_track);
- ClassDB::bind_method(_MD("get_stream_name"),&VideoPlayer::get_stream_name);
+ ClassDB::bind_method(D_METHOD("get_stream_name"),&VideoPlayer::get_stream_name);
- ClassDB::bind_method(_MD("get_stream_pos"),&VideoPlayer::get_stream_pos);
+ ClassDB::bind_method(D_METHOD("get_stream_pos"),&VideoPlayer::get_stream_pos);
- ClassDB::bind_method(_MD("set_autoplay","enabled"),&VideoPlayer::set_autoplay);
- ClassDB::bind_method(_MD("has_autoplay"),&VideoPlayer::has_autoplay);
+ ClassDB::bind_method(D_METHOD("set_autoplay","enabled"),&VideoPlayer::set_autoplay);
+ ClassDB::bind_method(D_METHOD("has_autoplay"),&VideoPlayer::has_autoplay);
- ClassDB::bind_method(_MD("set_expand","enable"), &VideoPlayer::set_expand );
- ClassDB::bind_method(_MD("has_expand"), &VideoPlayer::has_expand );
+ ClassDB::bind_method(D_METHOD("set_expand","enable"), &VideoPlayer::set_expand );
+ ClassDB::bind_method(D_METHOD("has_expand"), &VideoPlayer::has_expand );
- ClassDB::bind_method(_MD("set_buffering_msec","msec"),&VideoPlayer::set_buffering_msec);
- ClassDB::bind_method(_MD("get_buffering_msec"),&VideoPlayer::get_buffering_msec);
+ ClassDB::bind_method(D_METHOD("set_buffering_msec","msec"),&VideoPlayer::set_buffering_msec);
+ ClassDB::bind_method(D_METHOD("get_buffering_msec"),&VideoPlayer::get_buffering_msec);
- ClassDB::bind_method(_MD("get_video_texture:Texture"), &VideoPlayer::get_video_texture );
+ ClassDB::bind_method(D_METHOD("get_video_texture:Texture"), &VideoPlayer::get_video_texture );
- ADD_PROPERTY( PropertyInfo(Variant::INT, "audio_track",PROPERTY_HINT_RANGE,"0,128,1"), _SCS("set_audio_track"), _SCS("get_audio_track") );
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "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") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "paused"), _SCS("set_paused"), _SCS("is_paused") );
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "audio_track",PROPERTY_HINT_RANGE,"0,128,1"), "set_audio_track", "get_audio_track") ;
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE,"VideoStream"), "set_stream", "get_stream") ;
+ //ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), "set_loop", "has_loop") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), "set_volume_db", "get_volume_db") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "has_autoplay") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "paused"), "set_paused", "is_paused") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "expand" ), "set_expand","has_expand") ;
}
diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp
index 9e89de66dd..adc4a14a60 100644
--- a/scene/gui/viewport_container.cpp
+++ b/scene/gui/viewport_container.cpp
@@ -1,7 +1,36 @@
+/*************************************************************************/
+/* viewport_container.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "viewport_container.h"
+
#include "scene/main/viewport.h"
-Size2 ViewportContainer::get_minimum_size() const {
+Size2 ViewportContainer::get_minimum_size() const {
if (stretch)
return Size2();
@@ -91,10 +120,10 @@ void ViewportContainer::_notification(int p_what) {
void ViewportContainer::_bind_methods() {
- ClassDB::bind_method(_MD("set_stretch","enable"),&ViewportContainer::set_stretch);
- ClassDB::bind_method(_MD("is_stretch_enabled"),&ViewportContainer::is_stretch_enabled);
+ ClassDB::bind_method(D_METHOD("set_stretch","enable"),&ViewportContainer::set_stretch);
+ ClassDB::bind_method(D_METHOD("is_stretch_enabled"),&ViewportContainer::is_stretch_enabled);
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"stretch"),_SCS("set_stretch"),_SCS("is_stretch_enabled"));
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"stretch"),"set_stretch","is_stretch_enabled");
}
ViewportContainer::ViewportContainer() {
diff --git a/scene/gui/viewport_container.h b/scene/gui/viewport_container.h
index 632c54f2f4..bcd41fa4a8 100644
--- a/scene/gui/viewport_container.h
+++ b/scene/gui/viewport_container.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* viewport_container.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VIEWPORTCONTAINER_H
#define VIEWPORTCONTAINER_H
diff --git a/scene/io/resource_format_image.cpp b/scene/io/resource_format_image.cpp
index 4d15ab86fd..8bb07adb5f 100644
--- a/scene/io/resource_format_image.cpp
+++ b/scene/io/resource_format_image.cpp
@@ -31,7 +31,7 @@
#if 0
#include "scene/resources/texture.h"
#include "io/image_loader.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) {
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 84fe2a00f6..04d72b5a3d 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -259,39 +259,39 @@ int CanvasLayer::get_sort_index() {
void CanvasLayer::_bind_methods() {
- ClassDB::bind_method(_MD("set_layer","layer"),&CanvasLayer::set_layer);
- ClassDB::bind_method(_MD("get_layer"),&CanvasLayer::get_layer);
+ ClassDB::bind_method(D_METHOD("set_layer","layer"),&CanvasLayer::set_layer);
+ ClassDB::bind_method(D_METHOD("get_layer"),&CanvasLayer::get_layer);
- ClassDB::bind_method(_MD("set_transform","transform"),&CanvasLayer::set_transform);
- ClassDB::bind_method(_MD("get_transform"),&CanvasLayer::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&CanvasLayer::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&CanvasLayer::get_transform);
- ClassDB::bind_method(_MD("set_offset","offset"),&CanvasLayer::set_offset);
- ClassDB::bind_method(_MD("get_offset"),&CanvasLayer::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","offset"),&CanvasLayer::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset"),&CanvasLayer::get_offset);
- ClassDB::bind_method(_MD("set_rotation","radians"),&CanvasLayer::set_rotation);
- ClassDB::bind_method(_MD("get_rotation"),&CanvasLayer::get_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation","radians"),&CanvasLayer::set_rotation);
+ ClassDB::bind_method(D_METHOD("get_rotation"),&CanvasLayer::get_rotation);
- ClassDB::bind_method(_MD("set_rotationd","degrees"),&CanvasLayer::set_rotationd);
- ClassDB::bind_method(_MD("get_rotationd"),&CanvasLayer::get_rotationd);
+ ClassDB::bind_method(D_METHOD("set_rotationd","degrees"),&CanvasLayer::set_rotationd);
+ ClassDB::bind_method(D_METHOD("get_rotationd"),&CanvasLayer::get_rotationd);
// TODO: Obsolete those two methods (old name) properly (GH-4397)
- ClassDB::bind_method(_MD("_set_rotationd","degrees"),&CanvasLayer::_set_rotationd);
- ClassDB::bind_method(_MD("_get_rotationd"),&CanvasLayer::_get_rotationd);
+ ClassDB::bind_method(D_METHOD("_set_rotationd","degrees"),&CanvasLayer::_set_rotationd);
+ ClassDB::bind_method(D_METHOD("_get_rotationd"),&CanvasLayer::_get_rotationd);
- ClassDB::bind_method(_MD("set_scale","scale"),&CanvasLayer::set_scale);
- ClassDB::bind_method(_MD("get_scale"),&CanvasLayer::get_scale);
+ ClassDB::bind_method(D_METHOD("set_scale","scale"),&CanvasLayer::set_scale);
+ ClassDB::bind_method(D_METHOD("get_scale"),&CanvasLayer::get_scale);
- ClassDB::bind_method(_MD("set_custom_viewport","viewport:Viewport"),&CanvasLayer::set_custom_viewport);
- ClassDB::bind_method(_MD("get_custom_viewport:Viewport"),&CanvasLayer::get_custom_viewport);
+ ClassDB::bind_method(D_METHOD("set_custom_viewport","viewport:Viewport"),&CanvasLayer::set_custom_viewport);
+ ClassDB::bind_method(D_METHOD("get_custom_viewport:Viewport"),&CanvasLayer::get_custom_viewport);
- ClassDB::bind_method(_MD("get_world_2d:World2D"),&CanvasLayer::get_world_2d);
- //ClassDB::bind_method(_MD("get_viewport"),&CanvasLayer::get_viewport);
+ ClassDB::bind_method(D_METHOD("get_world_2d:World2D"),&CanvasLayer::get_world_2d);
+ //ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasLayer::get_viewport);
- ADD_PROPERTY( PropertyInfo(Variant::INT,"layer",PROPERTY_HINT_RANGE,"-128,128,1"),_SCS("set_layer"),_SCS("get_layer") );
- //ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),_SCS("set_transform"),_SCS("get_transform") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"rotation"),_SCS("set_rotationd"),_SCS("get_rotationd") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scale"),_SCS("set_scale"),_SCS("get_scale") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"layer",PROPERTY_HINT_RANGE,"-128,128,1"),"set_layer","get_layer") ;
+ //ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),"set_transform","get_transform") ;
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),"set_offset","get_offset") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"rotation"),"set_rotationd","get_rotationd") ;
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scale"),"set_scale","get_scale") ;
}
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 63a81a139d..77b08fd58b 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -28,10 +28,6 @@
/*************************************************************************/
#include "http_request.h"
-void HTTPRequest::set_ip_type(IP::Type p_type) {
- client->set_ip_type(p_type);
-}
-
void HTTPRequest::_redirect_request(const String& p_new_url) {
@@ -539,33 +535,32 @@ int HTTPRequest::get_body_size() const{
void HTTPRequest::_bind_methods() {
- ClassDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPRequest::set_ip_type);
- ClassDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain","method","request_data"),&HTTPRequest::request,DEFVAL(PoolStringArray()),DEFVAL(true),DEFVAL(HTTPClient::METHOD_GET),DEFVAL(String()));
- ClassDB::bind_method(_MD("cancel_request"),&HTTPRequest::cancel_request);
+ ClassDB::bind_method(D_METHOD("request","url","custom_headers","ssl_validate_domain","method","request_data"),&HTTPRequest::request,DEFVAL(PoolStringArray()),DEFVAL(true),DEFVAL(HTTPClient::METHOD_GET),DEFVAL(String()));
+ ClassDB::bind_method(D_METHOD("cancel_request"),&HTTPRequest::cancel_request);
- ClassDB::bind_method(_MD("get_http_client_status"),&HTTPRequest::get_http_client_status);
+ ClassDB::bind_method(D_METHOD("get_http_client_status"),&HTTPRequest::get_http_client_status);
- ClassDB::bind_method(_MD("set_use_threads","enable"),&HTTPRequest::set_use_threads);
- ClassDB::bind_method(_MD("is_using_threads"),&HTTPRequest::is_using_threads);
+ ClassDB::bind_method(D_METHOD("set_use_threads","enable"),&HTTPRequest::set_use_threads);
+ ClassDB::bind_method(D_METHOD("is_using_threads"),&HTTPRequest::is_using_threads);
- ClassDB::bind_method(_MD("set_body_size_limit","bytes"),&HTTPRequest::set_body_size_limit);
- ClassDB::bind_method(_MD("get_body_size_limit"),&HTTPRequest::get_body_size_limit);
+ ClassDB::bind_method(D_METHOD("set_body_size_limit","bytes"),&HTTPRequest::set_body_size_limit);
+ ClassDB::bind_method(D_METHOD("get_body_size_limit"),&HTTPRequest::get_body_size_limit);
- ClassDB::bind_method(_MD("set_max_redirects","amount"),&HTTPRequest::set_max_redirects);
- ClassDB::bind_method(_MD("get_max_redirects"),&HTTPRequest::get_max_redirects);
+ ClassDB::bind_method(D_METHOD("set_max_redirects","amount"),&HTTPRequest::set_max_redirects);
+ ClassDB::bind_method(D_METHOD("get_max_redirects"),&HTTPRequest::get_max_redirects);
- ClassDB::bind_method(_MD("set_download_file","path"),&HTTPRequest::set_download_file);
- ClassDB::bind_method(_MD("get_download_file"),&HTTPRequest::get_download_file);
+ ClassDB::bind_method(D_METHOD("set_download_file","path"),&HTTPRequest::set_download_file);
+ ClassDB::bind_method(D_METHOD("get_download_file"),&HTTPRequest::get_download_file);
- ClassDB::bind_method(_MD("get_downloaded_bytes"),&HTTPRequest::get_downloaded_bytes);
- ClassDB::bind_method(_MD("get_body_size"),&HTTPRequest::get_body_size);
+ ClassDB::bind_method(D_METHOD("get_downloaded_bytes"),&HTTPRequest::get_downloaded_bytes);
+ ClassDB::bind_method(D_METHOD("get_body_size"),&HTTPRequest::get_body_size);
- ClassDB::bind_method(_MD("_redirect_request"),&HTTPRequest::_redirect_request);
- ClassDB::bind_method(_MD("_request_done"),&HTTPRequest::_request_done);
+ ClassDB::bind_method(D_METHOD("_redirect_request"),&HTTPRequest::_redirect_request);
+ ClassDB::bind_method(D_METHOD("_request_done"),&HTTPRequest::_request_done);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_threads"),_SCS("set_use_threads"),_SCS("is_using_threads"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"body_size_limit",PROPERTY_HINT_RANGE,"-1,2000000000"),_SCS("set_body_size_limit"),_SCS("get_body_size_limit"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"max_redirects",PROPERTY_HINT_RANGE,"-1,1024"),_SCS("set_max_redirects"),_SCS("get_max_redirects"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_threads"),"set_use_threads","is_using_threads");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"body_size_limit",PROPERTY_HINT_RANGE,"-1,2000000000"),"set_body_size_limit","get_body_size_limit");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"max_redirects",PROPERTY_HINT_RANGE,"-1,1024"),"set_max_redirects","get_max_redirects");
ADD_SIGNAL(MethodInfo("request_completed",PropertyInfo(Variant::INT,"result"),PropertyInfo(Variant::INT,"response_code"),PropertyInfo(Variant::POOL_STRING_ARRAY,"headers"),PropertyInfo(Variant::POOL_BYTE_ARRAY,"body")));
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 51c5ddeb69..a9c495fd81 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -116,7 +116,6 @@ protected:
static void _bind_methods();
public:
- void set_ip_type(IP::Type p_type);
Error request(const String& p_url, const Vector<String>& p_custom_headers=Vector<String>(), bool p_ssl_validate_domain=true, HTTPClient::Method p_method=HTTPClient::METHOD_GET, const String& p_request_data=""); //connects to a full url and perform request
void cancel_request();
HTTPClient::Status get_http_client_status() const;
diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp
index 5d1b0495c0..935811009b 100644
--- a/scene/main/instance_placeholder.cpp
+++ b/scene/main/instance_placeholder.cpp
@@ -122,9 +122,9 @@ Dictionary InstancePlaceholder::get_stored_values(bool p_with_order) {
void InstancePlaceholder::_bind_methods() {
- ClassDB::bind_method(_MD("get_stored_values","with_order"),&InstancePlaceholder::get_stored_values,DEFVAL(false));
- ClassDB::bind_method(_MD("replace_by_instance","custom_scene:PackedScene"),&InstancePlaceholder::replace_by_instance,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("get_instance_path"),&InstancePlaceholder::get_instance_path);
+ ClassDB::bind_method(D_METHOD("get_stored_values","with_order"),&InstancePlaceholder::get_stored_values,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("replace_by_instance","custom_scene:PackedScene"),&InstancePlaceholder::replace_by_instance,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("get_instance_path"),&InstancePlaceholder::get_instance_path);
}
InstancePlaceholder::InstancePlaceholder() {
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 039dce37de..a189702894 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2288,7 +2288,7 @@ int Node::get_position_in_parent() const {
-Node *Node::_duplicate(bool p_use_instancing) const {
+Node *Node::_duplicate(int p_flags) const {
Node *node=NULL;
@@ -2302,7 +2302,7 @@ Node *Node::_duplicate(bool p_use_instancing) const {
nip->set_instance_path( ip->get_instance_path() );
node=nip;
- } else if (p_use_instancing && get_filename()!=String()) {
+ } else if ((p_flags&DUPLICATE_USE_INSTANCING) && get_filename()!=String()) {
Ref<PackedScene> res = ResourceLoader::load(get_filename());
ERR_FAIL_COND_V(res.is_null(),NULL);
@@ -2335,20 +2335,26 @@ Node *Node::_duplicate(bool p_use_instancing) const {
if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
continue;
String name = E->get().name;
+ if (!(p_flags&DUPLICATE_SCRIPTS) && name=="script/script")
+ continue;
+
node->set( name, get(name) );
}
node->set_name(get_name());
- List<GroupInfo> gi;
- get_groups(&gi);
- for (List<GroupInfo>::Element *E=gi.front();E;E=E->next()) {
+ if (p_flags & DUPLICATE_GROUPS) {
+ 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);
+ node->add_to_group(E->get().name, E->get().persistent);
+ }
}
- _duplicate_signals(this, node);
+ if (p_flags & DUPLICATE_SIGNALS)
+ _duplicate_signals(this, node);
for(int i=0;i<get_child_count();i++) {
@@ -2357,7 +2363,7 @@ Node *Node::_duplicate(bool p_use_instancing) const {
if (instanced && get_child(i)->data.owner==this)
continue; //part of instance
- Node *dup = get_child(i)->duplicate(p_use_instancing);
+ Node *dup = get_child(i)->duplicate(p_flags);
if (!dup) {
memdelete(node);
@@ -2371,11 +2377,11 @@ Node *Node::_duplicate(bool p_use_instancing) const {
return node;
}
-Node *Node::duplicate(bool p_use_instancing) const {
+Node *Node::duplicate(int p_flags) const {
- Node* dupe = _duplicate(p_use_instancing);
+ Node* dupe = _duplicate(p_flags);
- if (dupe) {
+ if (dupe && (p_flags&DUPLICATE_SIGNALS)) {
_duplicate_signals(this,dupe);
}
@@ -2904,96 +2910,96 @@ void Node::_bind_methods() {
GLOBAL_DEF("node/name_casing",NAME_CASING_PASCAL_CASE);
GlobalConfig::get_singleton()->set_custom_property_info("node/name_casing",PropertyInfo(Variant::INT,"node/name_casing",PROPERTY_HINT_ENUM,"PascalCase,camelCase,snake_case"));
- ClassDB::bind_method(_MD("_add_child_below_node","node:Node","child_node:Node","legible_unique_name"),&Node::add_child_below_node,DEFVAL(false));
-
- ClassDB::bind_method(_MD("set_name","name"),&Node::set_name);
- ClassDB::bind_method(_MD("get_name"),&Node::get_name);
- ClassDB::bind_method(_MD("add_child","node:Node","legible_unique_name"),&Node::add_child,DEFVAL(false));
- ClassDB::bind_method(_MD("remove_child","node:Node"),&Node::remove_child);
- //ClassDB::bind_method(_MD("remove_and_delete_child","node:Node"),&Node::remove_and_delete_child);
- ClassDB::bind_method(_MD("get_child_count"),&Node::get_child_count);
- ClassDB::bind_method(_MD("get_children"),&Node::_get_children);
- ClassDB::bind_method(_MD("get_child:Node","idx"),&Node::get_child);
- ClassDB::bind_method(_MD("has_node","path"),&Node::has_node);
- ClassDB::bind_method(_MD("get_node:Node","path"),&Node::get_node);
- ClassDB::bind_method(_MD("get_parent:Node"),&Node::get_parent);
- ClassDB::bind_method(_MD("find_node:Node","mask","recursive","owned"),&Node::find_node,DEFVAL(true),DEFVAL(true));
- ClassDB::bind_method(_MD("has_node_and_resource","path"),&Node::has_node_and_resource);
- ClassDB::bind_method(_MD("get_node_and_resource","path"),&Node::_get_node_and_resource);
-
- ClassDB::bind_method(_MD("is_inside_tree"),&Node::is_inside_tree);
- ClassDB::bind_method(_MD("is_a_parent_of","node:Node"),&Node::is_a_parent_of);
- ClassDB::bind_method(_MD("is_greater_than","node:Node"),&Node::is_greater_than);
- ClassDB::bind_method(_MD("get_path"),&Node::get_path);
- ClassDB::bind_method(_MD("get_path_to","node:Node"),&Node::get_path_to);
- ClassDB::bind_method(_MD("add_to_group","group","persistent"),&Node::add_to_group,DEFVAL(false));
- ClassDB::bind_method(_MD("remove_from_group","group"),&Node::remove_from_group);
- ClassDB::bind_method(_MD("is_in_group","group"),&Node::is_in_group);
- ClassDB::bind_method(_MD("move_child","child_node:Node","to_pos"),&Node::move_child);
- ClassDB::bind_method(_MD("get_groups"),&Node::_get_groups);
- ClassDB::bind_method(_MD("raise"),&Node::raise);
- ClassDB::bind_method(_MD("set_owner","owner:Node"),&Node::set_owner);
- ClassDB::bind_method(_MD("get_owner:Node"),&Node::get_owner);
- ClassDB::bind_method(_MD("remove_and_skip"),&Node::remove_and_skip);
- ClassDB::bind_method(_MD("get_index"),&Node::get_index);
- ClassDB::bind_method(_MD("print_tree"),&Node::print_tree);
- ClassDB::bind_method(_MD("set_filename","filename"),&Node::set_filename);
- ClassDB::bind_method(_MD("get_filename"),&Node::get_filename);
- ClassDB::bind_method(_MD("propagate_notification","what"),&Node::propagate_notification);
- ClassDB::bind_method(_MD("set_fixed_process","enable"),&Node::set_fixed_process);
- ClassDB::bind_method(_MD("get_fixed_process_delta_time"),&Node::get_fixed_process_delta_time);
- ClassDB::bind_method(_MD("is_fixed_processing"),&Node::is_fixed_processing);
- ClassDB::bind_method(_MD("get_process_delta_time"),&Node::get_process_delta_time);
- ClassDB::bind_method(_MD("set_process","enable"),&Node::set_process);
- ClassDB::bind_method(_MD("is_processing"),&Node::is_processing);
- ClassDB::bind_method(_MD("set_process_input","enable"),&Node::set_process_input);
- ClassDB::bind_method(_MD("is_processing_input"),&Node::is_processing_input);
- ClassDB::bind_method(_MD("set_process_unhandled_input","enable"),&Node::set_process_unhandled_input);
- ClassDB::bind_method(_MD("is_processing_unhandled_input"),&Node::is_processing_unhandled_input);
- ClassDB::bind_method(_MD("set_process_unhandled_key_input","enable"),&Node::set_process_unhandled_key_input);
- ClassDB::bind_method(_MD("is_processing_unhandled_key_input"),&Node::is_processing_unhandled_key_input);
- ClassDB::bind_method(_MD("set_pause_mode","mode"),&Node::set_pause_mode);
- ClassDB::bind_method(_MD("get_pause_mode"),&Node::get_pause_mode);
- ClassDB::bind_method(_MD("can_process"),&Node::can_process);
- ClassDB::bind_method(_MD("print_stray_nodes"),&Node::_print_stray_nodes);
- ClassDB::bind_method(_MD("get_position_in_parent"),&Node::get_position_in_parent);
- ClassDB::bind_method(_MD("set_display_folded","fold"),&Node::set_display_folded);
- ClassDB::bind_method(_MD("is_displayed_folded"),&Node::is_displayed_folded);
-
- ClassDB::bind_method(_MD("set_process_internal","enable"),&Node::set_process_internal);
- ClassDB::bind_method(_MD("is_processing_internal"),&Node::is_processing_internal);
-
- ClassDB::bind_method(_MD("set_fixed_process_internal","enable"),&Node::set_fixed_process_internal);
- ClassDB::bind_method(_MD("is_fixed_processing_internal"),&Node::is_fixed_processing_internal);
-
- ClassDB::bind_method(_MD("get_tree:SceneTree"),&Node::get_tree);
-
- ClassDB::bind_method(_MD("duplicate:Node","use_instancing"),&Node::duplicate,DEFVAL(false));
- ClassDB::bind_method(_MD("replace_by","node:Node","keep_data"),&Node::replace_by,DEFVAL(false));
-
- ClassDB::bind_method(_MD("set_scene_instance_load_placeholder","load_placeholder"),&Node::set_scene_instance_load_placeholder);
- ClassDB::bind_method(_MD("get_scene_instance_load_placeholder"),&Node::get_scene_instance_load_placeholder);
-
-
- ClassDB::bind_method(_MD("get_viewport"),&Node::get_viewport);
-
- ClassDB::bind_method(_MD("queue_free"),&Node::queue_delete);
-
- ClassDB::bind_method(_MD("request_ready"),&Node::request_ready);
-
- ClassDB::bind_method(_MD("set_network_mode","mode"),&Node::set_network_mode);
- ClassDB::bind_method(_MD("get_network_mode"),&Node::get_network_mode);
-
- ClassDB::bind_method(_MD("is_network_master"),&Node::is_network_master);
-
- ClassDB::bind_method(_MD("rpc_config","method","mode"),&Node::rpc_config);
- ClassDB::bind_method(_MD("rset_config","property","mode"),&Node::rset_config);
+ ClassDB::bind_method(D_METHOD("_add_child_below_node","node:Node","child_node:Node","legible_unique_name"),&Node::add_child_below_node,DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("set_name","name"),&Node::set_name);
+ ClassDB::bind_method(D_METHOD("get_name"),&Node::get_name);
+ ClassDB::bind_method(D_METHOD("add_child","node:Node","legible_unique_name"),&Node::add_child,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("remove_child","node:Node"),&Node::remove_child);
+ //ClassDB::bind_method(D_METHOD("remove_and_delete_child","node:Node"),&Node::remove_and_delete_child);
+ ClassDB::bind_method(D_METHOD("get_child_count"),&Node::get_child_count);
+ ClassDB::bind_method(D_METHOD("get_children"),&Node::_get_children);
+ ClassDB::bind_method(D_METHOD("get_child:Node","idx"),&Node::get_child);
+ ClassDB::bind_method(D_METHOD("has_node","path"),&Node::has_node);
+ ClassDB::bind_method(D_METHOD("get_node:Node","path"),&Node::get_node);
+ ClassDB::bind_method(D_METHOD("get_parent:Node"),&Node::get_parent);
+ ClassDB::bind_method(D_METHOD("find_node:Node","mask","recursive","owned"),&Node::find_node,DEFVAL(true),DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("has_node_and_resource","path"),&Node::has_node_and_resource);
+ ClassDB::bind_method(D_METHOD("get_node_and_resource","path"),&Node::_get_node_and_resource);
+
+ ClassDB::bind_method(D_METHOD("is_inside_tree"),&Node::is_inside_tree);
+ ClassDB::bind_method(D_METHOD("is_a_parent_of","node:Node"),&Node::is_a_parent_of);
+ ClassDB::bind_method(D_METHOD("is_greater_than","node:Node"),&Node::is_greater_than);
+ ClassDB::bind_method(D_METHOD("get_path"),&Node::get_path);
+ ClassDB::bind_method(D_METHOD("get_path_to","node:Node"),&Node::get_path_to);
+ ClassDB::bind_method(D_METHOD("add_to_group","group","persistent"),&Node::add_to_group,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("remove_from_group","group"),&Node::remove_from_group);
+ ClassDB::bind_method(D_METHOD("is_in_group","group"),&Node::is_in_group);
+ ClassDB::bind_method(D_METHOD("move_child","child_node:Node","to_pos"),&Node::move_child);
+ ClassDB::bind_method(D_METHOD("get_groups"),&Node::_get_groups);
+ ClassDB::bind_method(D_METHOD("raise"),&Node::raise);
+ ClassDB::bind_method(D_METHOD("set_owner","owner:Node"),&Node::set_owner);
+ ClassDB::bind_method(D_METHOD("get_owner:Node"),&Node::get_owner);
+ ClassDB::bind_method(D_METHOD("remove_and_skip"),&Node::remove_and_skip);
+ ClassDB::bind_method(D_METHOD("get_index"),&Node::get_index);
+ ClassDB::bind_method(D_METHOD("print_tree"),&Node::print_tree);
+ ClassDB::bind_method(D_METHOD("set_filename","filename"),&Node::set_filename);
+ ClassDB::bind_method(D_METHOD("get_filename"),&Node::get_filename);
+ ClassDB::bind_method(D_METHOD("propagate_notification","what"),&Node::propagate_notification);
+ ClassDB::bind_method(D_METHOD("set_fixed_process","enable"),&Node::set_fixed_process);
+ ClassDB::bind_method(D_METHOD("get_fixed_process_delta_time"),&Node::get_fixed_process_delta_time);
+ ClassDB::bind_method(D_METHOD("is_fixed_processing"),&Node::is_fixed_processing);
+ ClassDB::bind_method(D_METHOD("get_process_delta_time"),&Node::get_process_delta_time);
+ ClassDB::bind_method(D_METHOD("set_process","enable"),&Node::set_process);
+ ClassDB::bind_method(D_METHOD("is_processing"),&Node::is_processing);
+ ClassDB::bind_method(D_METHOD("set_process_input","enable"),&Node::set_process_input);
+ ClassDB::bind_method(D_METHOD("is_processing_input"),&Node::is_processing_input);
+ ClassDB::bind_method(D_METHOD("set_process_unhandled_input","enable"),&Node::set_process_unhandled_input);
+ ClassDB::bind_method(D_METHOD("is_processing_unhandled_input"),&Node::is_processing_unhandled_input);
+ ClassDB::bind_method(D_METHOD("set_process_unhandled_key_input","enable"),&Node::set_process_unhandled_key_input);
+ ClassDB::bind_method(D_METHOD("is_processing_unhandled_key_input"),&Node::is_processing_unhandled_key_input);
+ ClassDB::bind_method(D_METHOD("set_pause_mode","mode"),&Node::set_pause_mode);
+ ClassDB::bind_method(D_METHOD("get_pause_mode"),&Node::get_pause_mode);
+ ClassDB::bind_method(D_METHOD("can_process"),&Node::can_process);
+ ClassDB::bind_method(D_METHOD("print_stray_nodes"),&Node::_print_stray_nodes);
+ ClassDB::bind_method(D_METHOD("get_position_in_parent"),&Node::get_position_in_parent);
+ ClassDB::bind_method(D_METHOD("set_display_folded","fold"),&Node::set_display_folded);
+ ClassDB::bind_method(D_METHOD("is_displayed_folded"),&Node::is_displayed_folded);
+
+ ClassDB::bind_method(D_METHOD("set_process_internal","enable"),&Node::set_process_internal);
+ ClassDB::bind_method(D_METHOD("is_processing_internal"),&Node::is_processing_internal);
+
+ ClassDB::bind_method(D_METHOD("set_fixed_process_internal","enable"),&Node::set_fixed_process_internal);
+ ClassDB::bind_method(D_METHOD("is_fixed_processing_internal"),&Node::is_fixed_processing_internal);
+
+ ClassDB::bind_method(D_METHOD("get_tree:SceneTree"),&Node::get_tree);
+
+ ClassDB::bind_method(D_METHOD("duplicate:Node","flags"),&Node::duplicate,DEFVAL(DUPLICATE_USE_INSTANCING|DUPLICATE_SIGNALS|DUPLICATE_GROUPS|DUPLICATE_SCRIPTS));
+ ClassDB::bind_method(D_METHOD("replace_by","node:Node","keep_data"),&Node::replace_by,DEFVAL(false));
+
+ ClassDB::bind_method(D_METHOD("set_scene_instance_load_placeholder","load_placeholder"),&Node::set_scene_instance_load_placeholder);
+ ClassDB::bind_method(D_METHOD("get_scene_instance_load_placeholder"),&Node::get_scene_instance_load_placeholder);
+
+
+ ClassDB::bind_method(D_METHOD("get_viewport"),&Node::get_viewport);
+
+ ClassDB::bind_method(D_METHOD("queue_free"),&Node::queue_delete);
+
+ ClassDB::bind_method(D_METHOD("request_ready"),&Node::request_ready);
+
+ ClassDB::bind_method(D_METHOD("set_network_mode","mode"),&Node::set_network_mode);
+ ClassDB::bind_method(D_METHOD("get_network_mode"),&Node::get_network_mode);
+
+ ClassDB::bind_method(D_METHOD("is_network_master"),&Node::is_network_master);
+
+ ClassDB::bind_method(D_METHOD("rpc_config","method","mode"),&Node::rpc_config);
+ ClassDB::bind_method(D_METHOD("rset_config","property","mode"),&Node::rset_config);
#ifdef TOOLS_ENABLED
- ClassDB::bind_method(_MD("_set_import_path","import_path"),&Node::set_import_path);
- ClassDB::bind_method(_MD("_get_import_path"),&Node::get_import_path);
- ADD_PROPERTYNZ( PropertyInfo(Variant::NODE_PATH,"_import_path",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_import_path"),_SCS("_get_import_path"));
+ ClassDB::bind_method(D_METHOD("_set_import_path","import_path"),&Node::set_import_path);
+ ClassDB::bind_method(D_METHOD("_get_import_path"),&Node::get_import_path);
+ ADD_PROPERTYNZ( PropertyInfo(Variant::NODE_PATH,"_import_path",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_import_path","_get_import_path");
#endif
@@ -3018,10 +3024,10 @@ void Node::_bind_methods() {
}
- ClassDB::bind_method(_MD("rset","property","value:Variant"),&Node::rset);
- ClassDB::bind_method(_MD("rset_id","peer_id","property","value:Variant"),&Node::rset_id);
- ClassDB::bind_method(_MD("rset_unreliable","property","value:Variant"),&Node::rset_unreliable);
- ClassDB::bind_method(_MD("rset_unreliable_id","peer_id","property","value:Variant"),&Node::rset_unreliable_id);
+ ClassDB::bind_method(D_METHOD("rset","property","value:Variant"),&Node::rset);
+ ClassDB::bind_method(D_METHOD("rset_id","peer_id","property","value:Variant"),&Node::rset_id);
+ ClassDB::bind_method(D_METHOD("rset_unreliable","property","value:Variant"),&Node::rset_unreliable);
+ ClassDB::bind_method(D_METHOD("rset_unreliable_id","peer_id","property","value:Variant"),&Node::rset_unreliable_id);
BIND_CONSTANT( NOTIFICATION_ENTER_TREE );
@@ -3058,17 +3064,21 @@ void Node::_bind_methods() {
BIND_CONSTANT( PAUSE_MODE_STOP );
BIND_CONSTANT( PAUSE_MODE_PROCESS );
+ BIND_CONSTANT( DUPLICATE_SIGNALS );
+ BIND_CONSTANT( DUPLICATE_GROUPS );
+ BIND_CONSTANT( DUPLICATE_SCRIPTS );
+
ADD_SIGNAL( MethodInfo("renamed") );
ADD_SIGNAL( MethodInfo("tree_entered") );
ADD_SIGNAL( MethodInfo("tree_exited") );
- //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/process" ),_SCS("set_process"),_SCS("is_processing") );
- //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/fixed_process" ), _SCS("set_fixed_process"),_SCS("is_fixed_processing") );
- //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/input" ), _SCS("set_process_input"),_SCS("is_processing_input" ) );
- //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/unhandled_input" ), _SCS("set_process_unhandled_input"),_SCS("is_processing_unhandled_input" ) );
+ //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/process" ),"set_process","is_processing") ;
+ //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/fixed_process" ), "set_fixed_process","is_fixed_processing") ;
+ //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/input" ), "set_process_input","is_processing_input" ) ;
+ //ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "process/unhandled_input" ), "set_process_unhandled_input","is_processing_unhandled_input" ) ;
ADD_GROUP("Pause","pause_");
- ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "pause_mode",PROPERTY_HINT_ENUM,"Inherit,Stop,Process" ), _SCS("set_pause_mode"),_SCS("get_pause_mode" ) );
- ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "editor/display_folded",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR ), _SCS("set_display_folded"),_SCS("is_displayed_folded" ) );
+ ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "pause_mode",PROPERTY_HINT_ENUM,"Inherit,Stop,Process" ), "set_pause_mode", "get_pause_mode" );
+ ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "editor/display_folded",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR ), "set_display_folded", "is_displayed_folded");
BIND_VMETHOD( MethodInfo("_process",PropertyInfo(Variant::REAL,"delta")) );
BIND_VMETHOD( MethodInfo("_fixed_process",PropertyInfo(Variant::REAL,"delta")) );
@@ -3079,8 +3089,8 @@ void Node::_bind_methods() {
BIND_VMETHOD( MethodInfo("_unhandled_input",PropertyInfo(Variant::INPUT_EVENT,"event")) );
BIND_VMETHOD( MethodInfo("_unhandled_key_input",PropertyInfo(Variant::INPUT_EVENT,"key_event")) );
- //ClassDB::bind_method(_MD("get_child",&Node::get_child,PH("index")));
- //ClassDB::bind_method(_MD("get_node",&Node::get_node,PH("path")));
+ //ClassDB::bind_method(D_METHOD("get_child",&Node::get_child,PH("index")));
+ //ClassDB::bind_method(D_METHOD("get_node",&Node::get_node,PH("path")));
}
diff --git a/scene/main/node.h b/scene/main/node.h
index d88db8ecb0..b042cabb6f 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -29,7 +29,7 @@
#ifndef NODE_H
#define NODE_H
-#include "globals.h"
+#include "global_config.h"
#include "object.h"
#include "path_db.h"
#include "map.h"
@@ -54,6 +54,14 @@ public:
PAUSE_MODE_PROCESS
};
+ enum DuplicateFlags {
+
+ DUPLICATE_SIGNALS=1,
+ DUPLICATE_GROUPS=2,
+ DUPLICATE_SCRIPTS=4,
+ DUPLICATE_USE_INSTANCING=8
+ };
+
enum NetworkMode {
NETWORK_MODE_INHERIT,
@@ -177,7 +185,7 @@ private:
void _duplicate_signals(const Node* p_original,Node* p_copy) const;
void _duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_reown_map) const;
- Node *_duplicate(bool p_use_instancing) const;
+ Node *_duplicate(int p_flags) const;
Array _get_children() const;
Array _get_groups() const;
@@ -332,7 +340,7 @@ public:
int get_position_in_parent() const;
- Node *duplicate(bool p_use_instancing=false) const;
+ Node *duplicate(int p_flags=DUPLICATE_GROUPS|DUPLICATE_SIGNALS|DUPLICATE_SCRIPTS) const;
Node *duplicate_and_reown(const Map<Node*,Node*>& p_reown_map) const;
//Node *clone_tree() const;
diff --git a/scene/main/resource_preloader.cpp b/scene/main/resource_preloader.cpp
index 93a836a2eb..29333ff4bc 100644
--- a/scene/main/resource_preloader.cpp
+++ b/scene/main/resource_preloader.cpp
@@ -163,18 +163,18 @@ void ResourcePreloader::get_resource_list(List<StringName> *p_list) {
void ResourcePreloader::_bind_methods() {
- ClassDB::bind_method(_MD("_set_resources"),&ResourcePreloader::_set_resources);
- ClassDB::bind_method(_MD("_get_resources"),&ResourcePreloader::_get_resources);
+ ClassDB::bind_method(D_METHOD("_set_resources"),&ResourcePreloader::_set_resources);
+ ClassDB::bind_method(D_METHOD("_get_resources"),&ResourcePreloader::_get_resources);
- ClassDB::bind_method(_MD("add_resource","name","resource"),&ResourcePreloader::add_resource);
- ClassDB::bind_method(_MD("remove_resource","name"),&ResourcePreloader::remove_resource);
- ClassDB::bind_method(_MD("rename_resource","name","newname"),&ResourcePreloader::rename_resource);
- ClassDB::bind_method(_MD("has_resource","name"),&ResourcePreloader::has_resource);
- ClassDB::bind_method(_MD("get_resource","name"),&ResourcePreloader::get_resource);
- ClassDB::bind_method(_MD("get_resource_list"),&ResourcePreloader::_get_resource_list);
+ ClassDB::bind_method(D_METHOD("add_resource","name","resource"),&ResourcePreloader::add_resource);
+ ClassDB::bind_method(D_METHOD("remove_resource","name"),&ResourcePreloader::remove_resource);
+ ClassDB::bind_method(D_METHOD("rename_resource","name","newname"),&ResourcePreloader::rename_resource);
+ ClassDB::bind_method(D_METHOD("has_resource","name"),&ResourcePreloader::has_resource);
+ ClassDB::bind_method(D_METHOD("get_resource","name"),&ResourcePreloader::get_resource);
+ ClassDB::bind_method(D_METHOD("get_resource_list"),&ResourcePreloader::_get_resource_list);
- ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"resources",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_resources"), _SCS("_get_resources"));
+ ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"resources",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_resources", "_get_resources");
}
diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp
index 9db1d3fd77..093359ab16 100644
--- a/scene/main/scene_main_loop.cpp
+++ b/scene/main/scene_main_loop.cpp
@@ -32,7 +32,7 @@
#include "os/os.h"
#include "message_queue.h"
#include "node.h"
-#include "globals.h"
+#include "global_config.h"
#include <stdio.h>
#include "os/keyboard.h"
//#include "servers/spatial_sound_2d_server.h"
@@ -48,8 +48,8 @@
void SceneTreeTimer::_bind_methods() {
- ClassDB::bind_method(_MD("set_time_left","time"),&SceneTreeTimer::set_time_left);
- ClassDB::bind_method(_MD("get_time_left"),&SceneTreeTimer::get_time_left);
+ ClassDB::bind_method(D_METHOD("set_time_left","time"),&SceneTreeTimer::set_time_left);
+ ClassDB::bind_method(D_METHOD("get_time_left"),&SceneTreeTimer::get_time_left);
ADD_SIGNAL(MethodInfo("timeout"));
}
@@ -63,9 +63,19 @@ float SceneTreeTimer::get_time_left() const {
return time_left;
}
+void SceneTreeTimer::set_pause_mode_process(bool p_pause_mode_process) {
+ if (process_pause != p_pause_mode_process) {
+ process_pause = p_pause_mode_process;
+ }
+}
+
+bool SceneTreeTimer::is_pause_mode_process() {
+ return process_pause;
+}
SceneTreeTimer::SceneTreeTimer() {
time_left=0;
+ process_pause = true;
}
@@ -602,7 +612,10 @@ bool SceneTree::idle(float p_time){
for (List<Ref<SceneTreeTimer> >::Element *E=timers.front();E;) {
List<Ref<SceneTreeTimer> >::Element *N = E->next();
-
+ if (pause && !E->get()->is_pause_mode_process()) {
+ E=N;
+ continue;
+ }
float time_left = E->get()->get_time_left();
time_left-=p_time;
E->get()->set_time_left(time_left);
@@ -1714,10 +1727,11 @@ void SceneTree::drop_files(const Vector<String>& p_files,int p_from_screen) {
}
-Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec) {
+Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) {
Ref<SceneTreeTimer> stt;
stt.instance();
+ stt->set_pause_mode_process(p_process_pause);
stt->set_time_left(p_delay_sec);
timers.push_back(stt);
return stt;
@@ -1789,6 +1803,10 @@ bool SceneTree::is_network_server() const {
}
+bool SceneTree::has_network_peer() const {
+ return network_peer.is_valid();
+}
+
int SceneTree::get_network_unique_id() const {
ERR_FAIL_COND_V(!network_peer.is_valid(),0);
@@ -2220,39 +2238,39 @@ void SceneTree::_network_poll() {
void SceneTree::_bind_methods() {
- //ClassDB::bind_method(_MD("call_group","call_flags","group","method","arg1","arg2"),&SceneMainLoop::_call_group,DEFVAL(Variant()),DEFVAL(Variant()));
+ //ClassDB::bind_method(D_METHOD("call_group","call_flags","group","method","arg1","arg2"),&SceneMainLoop::_call_group,DEFVAL(Variant()),DEFVAL(Variant()));
- ClassDB::bind_method(_MD("get_root:Viewport"),&SceneTree::get_root);
- ClassDB::bind_method(_MD("has_group","name"),&SceneTree::has_group);
+ ClassDB::bind_method(D_METHOD("get_root:Viewport"),&SceneTree::get_root);
+ ClassDB::bind_method(D_METHOD("has_group","name"),&SceneTree::has_group);
- ClassDB::bind_method(_MD("set_auto_accept_quit","enabled"),&SceneTree::set_auto_accept_quit);
+ ClassDB::bind_method(D_METHOD("set_auto_accept_quit","enabled"),&SceneTree::set_auto_accept_quit);
- ClassDB::bind_method(_MD("set_editor_hint","enable"),&SceneTree::set_editor_hint);
- ClassDB::bind_method(_MD("is_editor_hint"),&SceneTree::is_editor_hint);
- ClassDB::bind_method(_MD("set_debug_collisions_hint","enable"),&SceneTree::set_debug_collisions_hint);
- ClassDB::bind_method(_MD("is_debugging_collisions_hint"),&SceneTree::is_debugging_collisions_hint);
- ClassDB::bind_method(_MD("set_debug_navigation_hint","enable"),&SceneTree::set_debug_navigation_hint);
- ClassDB::bind_method(_MD("is_debugging_navigation_hint"),&SceneTree::is_debugging_navigation_hint);
+ ClassDB::bind_method(D_METHOD("set_editor_hint","enable"),&SceneTree::set_editor_hint);
+ ClassDB::bind_method(D_METHOD("is_editor_hint"),&SceneTree::is_editor_hint);
+ ClassDB::bind_method(D_METHOD("set_debug_collisions_hint","enable"),&SceneTree::set_debug_collisions_hint);
+ ClassDB::bind_method(D_METHOD("is_debugging_collisions_hint"),&SceneTree::is_debugging_collisions_hint);
+ ClassDB::bind_method(D_METHOD("set_debug_navigation_hint","enable"),&SceneTree::set_debug_navigation_hint);
+ ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"),&SceneTree::is_debugging_navigation_hint);
#ifdef TOOLS_ENABLED
- ClassDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneTree::set_edited_scene_root);
- ClassDB::bind_method(_MD("get_edited_scene_root"),&SceneTree::get_edited_scene_root);
+ ClassDB::bind_method(D_METHOD("set_edited_scene_root","scene"),&SceneTree::set_edited_scene_root);
+ ClassDB::bind_method(D_METHOD("get_edited_scene_root"),&SceneTree::get_edited_scene_root);
#endif
- ClassDB::bind_method(_MD("set_pause","enable"),&SceneTree::set_pause);
- ClassDB::bind_method(_MD("is_paused"),&SceneTree::is_paused);
- ClassDB::bind_method(_MD("set_input_as_handled"),&SceneTree::set_input_as_handled);
+ ClassDB::bind_method(D_METHOD("set_pause","enable"),&SceneTree::set_pause);
+ ClassDB::bind_method(D_METHOD("is_paused"),&SceneTree::is_paused);
+ ClassDB::bind_method(D_METHOD("set_input_as_handled"),&SceneTree::set_input_as_handled);
- ClassDB::bind_method(_MD("create_timer:SceneTreeTimer","time_sec"),&SceneTree::create_timer);
+ ClassDB::bind_method(D_METHOD("create_timer:SceneTreeTimer","time_sec", "pause_mode_process"),&SceneTree::create_timer, DEFVAL(true));
- ClassDB::bind_method(_MD("get_node_count"),&SceneTree::get_node_count);
- ClassDB::bind_method(_MD("get_frame"),&SceneTree::get_frame);
- ClassDB::bind_method(_MD("quit"),&SceneTree::quit);
+ ClassDB::bind_method(D_METHOD("get_node_count"),&SceneTree::get_node_count);
+ ClassDB::bind_method(D_METHOD("get_frame"),&SceneTree::get_frame);
+ ClassDB::bind_method(D_METHOD("quit"),&SceneTree::quit);
- ClassDB::bind_method(_MD("set_screen_stretch","mode","aspect","minsize"),&SceneTree::set_screen_stretch);
+ ClassDB::bind_method(D_METHOD("set_screen_stretch","mode","aspect","minsize"),&SceneTree::set_screen_stretch);
- ClassDB::bind_method(_MD("queue_delete","obj"),&SceneTree::queue_delete);
+ ClassDB::bind_method(D_METHOD("queue_delete","obj"),&SceneTree::queue_delete);
@@ -2266,8 +2284,8 @@ void SceneTree::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_group_flags",&SceneTree::_call_group_flags,mi);
- ClassDB::bind_method(_MD("notify_group_flags","call_flags","group","notification"),&SceneTree::notify_group_flags);
- ClassDB::bind_method(_MD("set_group_flags","call_flags","group","property","value"),&SceneTree::set_group_flags);
+ ClassDB::bind_method(D_METHOD("notify_group_flags","call_flags","group","notification"),&SceneTree::notify_group_flags);
+ ClassDB::bind_method(D_METHOD("set_group_flags","call_flags","group","property","value"),&SceneTree::set_group_flags);
MethodInfo mi2;
mi2.name="call_group";
@@ -2277,33 +2295,34 @@ void SceneTree::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_group",&SceneTree::_call_group,mi2);
- ClassDB::bind_method(_MD("notify_group","call_flags","group","notification"),&SceneTree::notify_group);
- ClassDB::bind_method(_MD("set_group","call_flags","group","property","value"),&SceneTree::set_group);
+ ClassDB::bind_method(D_METHOD("notify_group","call_flags","group","notification"),&SceneTree::notify_group);
+ ClassDB::bind_method(D_METHOD("set_group","call_flags","group","property","value"),&SceneTree::set_group);
- ClassDB::bind_method(_MD("get_nodes_in_group","group"),&SceneTree::_get_nodes_in_group);
+ ClassDB::bind_method(D_METHOD("get_nodes_in_group","group"),&SceneTree::_get_nodes_in_group);
- ClassDB::bind_method(_MD("set_current_scene","child_node:Node"),&SceneTree::set_current_scene);
- ClassDB::bind_method(_MD("get_current_scene:Node"),&SceneTree::get_current_scene);
+ ClassDB::bind_method(D_METHOD("set_current_scene","child_node:Node"),&SceneTree::set_current_scene);
+ ClassDB::bind_method(D_METHOD("get_current_scene:Node"),&SceneTree::get_current_scene);
- ClassDB::bind_method(_MD("change_scene","path"),&SceneTree::change_scene);
- ClassDB::bind_method(_MD("change_scene_to","packed_scene:PackedScene"),&SceneTree::change_scene_to);
+ ClassDB::bind_method(D_METHOD("change_scene","path"),&SceneTree::change_scene);
+ ClassDB::bind_method(D_METHOD("change_scene_to","packed_scene:PackedScene"),&SceneTree::change_scene_to);
- ClassDB::bind_method(_MD("reload_current_scene"),&SceneTree::reload_current_scene);
+ ClassDB::bind_method(D_METHOD("reload_current_scene"),&SceneTree::reload_current_scene);
- ClassDB::bind_method(_MD("_change_scene"),&SceneTree::_change_scene);
+ ClassDB::bind_method(D_METHOD("_change_scene"),&SceneTree::_change_scene);
- ClassDB::bind_method(_MD("set_network_peer","peer:NetworkedMultiplayerPeer"),&SceneTree::set_network_peer);
- ClassDB::bind_method(_MD("is_network_server"),&SceneTree::is_network_server);
- ClassDB::bind_method(_MD("get_network_unique_id"),&SceneTree::get_network_unique_id);
- ClassDB::bind_method(_MD("set_refuse_new_network_connections","refuse"),&SceneTree::set_refuse_new_network_connections);
- ClassDB::bind_method(_MD("is_refusing_new_network_connections"),&SceneTree::is_refusing_new_network_connections);
- ClassDB::bind_method(_MD("_network_peer_connected"),&SceneTree::_network_peer_connected);
- ClassDB::bind_method(_MD("_network_peer_disconnected"),&SceneTree::_network_peer_disconnected);
- ClassDB::bind_method(_MD("_connected_to_server"),&SceneTree::_connected_to_server);
- ClassDB::bind_method(_MD("_connection_failed"),&SceneTree::_connection_failed);
- ClassDB::bind_method(_MD("_server_disconnected"),&SceneTree::_server_disconnected);
+ ClassDB::bind_method(D_METHOD("set_network_peer","peer:NetworkedMultiplayerPeer"),&SceneTree::set_network_peer);
+ ClassDB::bind_method(D_METHOD("is_network_server"),&SceneTree::is_network_server);
+ ClassDB::bind_method(D_METHOD("has_network_peer"),&SceneTree::has_network_peer);
+ ClassDB::bind_method(D_METHOD("get_network_unique_id"),&SceneTree::get_network_unique_id);
+ ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections","refuse"),&SceneTree::set_refuse_new_network_connections);
+ ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"),&SceneTree::is_refusing_new_network_connections);
+ ClassDB::bind_method(D_METHOD("_network_peer_connected"),&SceneTree::_network_peer_connected);
+ ClassDB::bind_method(D_METHOD("_network_peer_disconnected"),&SceneTree::_network_peer_disconnected);
+ ClassDB::bind_method(D_METHOD("_connected_to_server"),&SceneTree::_connected_to_server);
+ ClassDB::bind_method(D_METHOD("_connection_failed"),&SceneTree::_connection_failed);
+ ClassDB::bind_method(D_METHOD("_server_disconnected"),&SceneTree::_server_disconnected);
ADD_SIGNAL( MethodInfo("tree_changed") );
ADD_SIGNAL( MethodInfo("node_removed",PropertyInfo( Variant::OBJECT, "node") ) );
diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h
index f4271e5454..7f69f5eef7 100644
--- a/scene/main/scene_main_loop.h
+++ b/scene/main/scene_main_loop.h
@@ -56,6 +56,7 @@ class SceneTreeTimer : public Reference {
GDCLASS(SceneTreeTimer,Reference);
float time_left;
+ bool process_pause;
protected:
static void _bind_methods();
public:
@@ -63,6 +64,9 @@ public:
void set_time_left(float p_time);
float get_time_left() const;
+ void set_pause_mode_process(bool p_pause_mode_process);
+ bool is_pause_mode_process();
+
SceneTreeTimer();
};
@@ -430,7 +434,7 @@ public:
Error change_scene_to(const Ref<PackedScene>& p_scene);
Error reload_current_scene();
- Ref<SceneTreeTimer> create_timer(float p_delay_sec);
+ Ref<SceneTreeTimer> create_timer(float p_delay_sec, bool p_process_pause=true);
//used by Main::start, don't use otherwise
void add_current_scene(Node * p_current);
@@ -443,6 +447,7 @@ public:
void set_network_peer(const Ref<NetworkedMultiplayerPeer>& p_network_peer);
bool is_network_server() const;
+ bool has_network_peer() const;
int get_network_unique_id() const;
void set_refuse_new_network_connections(bool p_refuse);
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index 7852e2b46b..d27b53d48b 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -179,32 +179,32 @@ void Timer::_set_process(bool p_process, bool p_force)
void Timer::_bind_methods() {
- ClassDB::bind_method(_MD("set_wait_time","time_sec"),&Timer::set_wait_time);
- ClassDB::bind_method(_MD("get_wait_time"),&Timer::get_wait_time);
+ ClassDB::bind_method(D_METHOD("set_wait_time","time_sec"),&Timer::set_wait_time);
+ ClassDB::bind_method(D_METHOD("get_wait_time"),&Timer::get_wait_time);
- ClassDB::bind_method(_MD("set_one_shot","enable"),&Timer::set_one_shot);
- ClassDB::bind_method(_MD("is_one_shot"),&Timer::is_one_shot);
+ ClassDB::bind_method(D_METHOD("set_one_shot","enable"),&Timer::set_one_shot);
+ ClassDB::bind_method(D_METHOD("is_one_shot"),&Timer::is_one_shot);
- ClassDB::bind_method(_MD("set_autostart","enable"),&Timer::set_autostart);
- ClassDB::bind_method(_MD("has_autostart"),&Timer::has_autostart);
+ ClassDB::bind_method(D_METHOD("set_autostart","enable"),&Timer::set_autostart);
+ ClassDB::bind_method(D_METHOD("has_autostart"),&Timer::has_autostart);
- ClassDB::bind_method(_MD("start"),&Timer::start);
- ClassDB::bind_method(_MD("stop"),&Timer::stop);
+ ClassDB::bind_method(D_METHOD("start"),&Timer::start);
+ ClassDB::bind_method(D_METHOD("stop"),&Timer::stop);
- ClassDB::bind_method(_MD("set_active", "active"), &Timer::set_active);
- ClassDB::bind_method(_MD("is_active"), &Timer::is_active);
+ ClassDB::bind_method(D_METHOD("set_active", "active"), &Timer::set_active);
+ ClassDB::bind_method(D_METHOD("is_active"), &Timer::is_active);
- ClassDB::bind_method(_MD("get_time_left"),&Timer::get_time_left);
+ ClassDB::bind_method(D_METHOD("get_time_left"),&Timer::get_time_left);
- ClassDB::bind_method(_MD("set_timer_process_mode", "mode"), &Timer::set_timer_process_mode);
- ClassDB::bind_method(_MD("get_timer_process_mode"), &Timer::get_timer_process_mode);
+ ClassDB::bind_method(D_METHOD("set_timer_process_mode", "mode"), &Timer::set_timer_process_mode);
+ ClassDB::bind_method(D_METHOD("get_timer_process_mode"), &Timer::get_timer_process_mode);
ADD_SIGNAL( MethodInfo("timeout") );
- ADD_PROPERTY( PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_timer_process_mode"), _SCS("get_timer_process_mode") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.01,4096,0.01" ), _SCS("set_wait_time"), _SCS("get_wait_time") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "one_shot" ), _SCS("set_one_shot"), _SCS("is_one_shot") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autostart" ), _SCS("set_autostart"), _SCS("has_autostart") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_timer_process_mode", "get_timer_process_mode") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.01,4096,0.01" ), "set_wait_time", "get_wait_time") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "one_shot" ), "set_one_shot", "is_one_shot") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "autostart" ), "set_autostart", "has_autostart") ;
BIND_CONSTANT( TIMER_PROCESS_FIXED );
BIND_CONSTANT( TIMER_PROCESS_IDLE );
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 989c048682..ef39dcde4b 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -48,7 +48,7 @@
#include "scene/main/timer.h"
#include "scene/scene_string_names.h"
-#include "globals.h"
+#include "global_config.h"
void ViewportTexture::setup_local_to_scene() {
@@ -139,10 +139,10 @@ uint32_t ViewportTexture::get_flags() const{
void ViewportTexture::_bind_methods() {
- ClassDB::bind_method(_MD("set_viewport_path_in_scene","path"),&ViewportTexture::set_viewport_path_in_scene);
- ClassDB::bind_method(_MD("get_viewport_path_in_scene"),&ViewportTexture::get_viewport_path_in_scene);
+ ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene","path"),&ViewportTexture::set_viewport_path_in_scene);
+ ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"),&ViewportTexture::get_viewport_path_in_scene);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"viewport_path"),_SCS("set_viewport_path_in_scene"),_SCS("get_viewport_path_in_scene"));
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH,"viewport_path"),"set_viewport_path_in_scene","get_viewport_path_in_scene");
}
@@ -2774,128 +2774,128 @@ bool Viewport::get_hdr() const{
void Viewport::_bind_methods() {
- ClassDB::bind_method(_MD("set_size","size"), &Viewport::set_size);
- ClassDB::bind_method(_MD("get_size"), &Viewport::get_size);
- ClassDB::bind_method(_MD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d);
- ClassDB::bind_method(_MD("get_world_2d:World2D"), &Viewport::get_world_2d);
- ClassDB::bind_method(_MD("find_world_2d:World2D"), &Viewport::find_world_2d);
- ClassDB::bind_method(_MD("set_world","world:World"), &Viewport::set_world);
- ClassDB::bind_method(_MD("get_world:World"), &Viewport::get_world);
- ClassDB::bind_method(_MD("find_world:World"), &Viewport::find_world);
+ ClassDB::bind_method(D_METHOD("set_size","size"), &Viewport::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"), &Viewport::get_size);
+ ClassDB::bind_method(D_METHOD("set_world_2d","world_2d:World2D"), &Viewport::set_world_2d);
+ ClassDB::bind_method(D_METHOD("get_world_2d:World2D"), &Viewport::get_world_2d);
+ ClassDB::bind_method(D_METHOD("find_world_2d:World2D"), &Viewport::find_world_2d);
+ ClassDB::bind_method(D_METHOD("set_world","world:World"), &Viewport::set_world);
+ ClassDB::bind_method(D_METHOD("get_world:World"), &Viewport::get_world);
+ ClassDB::bind_method(D_METHOD("find_world:World"), &Viewport::find_world);
- ClassDB::bind_method(_MD("set_canvas_transform","xform"), &Viewport::set_canvas_transform);
- ClassDB::bind_method(_MD("get_canvas_transform"), &Viewport::get_canvas_transform);
+ ClassDB::bind_method(D_METHOD("set_canvas_transform","xform"), &Viewport::set_canvas_transform);
+ ClassDB::bind_method(D_METHOD("get_canvas_transform"), &Viewport::get_canvas_transform);
- ClassDB::bind_method(_MD("set_global_canvas_transform","xform"), &Viewport::set_global_canvas_transform);
- ClassDB::bind_method(_MD("get_global_canvas_transform"), &Viewport::get_global_canvas_transform);
- ClassDB::bind_method(_MD("get_final_transform"), &Viewport::get_final_transform);
+ ClassDB::bind_method(D_METHOD("set_global_canvas_transform","xform"), &Viewport::set_global_canvas_transform);
+ ClassDB::bind_method(D_METHOD("get_global_canvas_transform"), &Viewport::get_global_canvas_transform);
+ ClassDB::bind_method(D_METHOD("get_final_transform"), &Viewport::get_final_transform);
- ClassDB::bind_method(_MD("get_visible_rect"), &Viewport::get_visible_rect);
- ClassDB::bind_method(_MD("set_transparent_background","enable"), &Viewport::set_transparent_background);
- ClassDB::bind_method(_MD("has_transparent_background"), &Viewport::has_transparent_background);
+ ClassDB::bind_method(D_METHOD("get_visible_rect"), &Viewport::get_visible_rect);
+ ClassDB::bind_method(D_METHOD("set_transparent_background","enable"), &Viewport::set_transparent_background);
+ ClassDB::bind_method(D_METHOD("has_transparent_background"), &Viewport::has_transparent_background);
- ClassDB::bind_method(_MD("_parent_visibility_changed"), &Viewport::_parent_visibility_changed);
+ ClassDB::bind_method(D_METHOD("_parent_visibility_changed"), &Viewport::_parent_visibility_changed);
- ClassDB::bind_method(_MD("_parent_resized"), &Viewport::_parent_resized);
- ClassDB::bind_method(_MD("_vp_input"), &Viewport::_vp_input);
- ClassDB::bind_method(_MD("_vp_input_text","text"), &Viewport::_vp_input_text);
- ClassDB::bind_method(_MD("_vp_unhandled_input"), &Viewport::_vp_unhandled_input);
+ ClassDB::bind_method(D_METHOD("_parent_resized"), &Viewport::_parent_resized);
+ ClassDB::bind_method(D_METHOD("_vp_input"), &Viewport::_vp_input);
+ ClassDB::bind_method(D_METHOD("_vp_input_text","text"), &Viewport::_vp_input_text);
+ ClassDB::bind_method(D_METHOD("_vp_unhandled_input"), &Viewport::_vp_unhandled_input);
- ClassDB::bind_method(_MD("set_size_override","enable","size","margin"), &Viewport::set_size_override,DEFVAL(Size2(-1,-1)),DEFVAL(Size2(0,0)));
- ClassDB::bind_method(_MD("get_size_override"), &Viewport::get_size_override);
- ClassDB::bind_method(_MD("is_size_override_enabled"), &Viewport::is_size_override_enabled);
- ClassDB::bind_method(_MD("set_size_override_stretch","enabled"), &Viewport::set_size_override_stretch);
- ClassDB::bind_method(_MD("is_size_override_stretch_enabled"), &Viewport::is_size_override_stretch_enabled);
- ClassDB::bind_method(_MD("queue_screen_capture"), &Viewport::queue_screen_capture);
- ClassDB::bind_method(_MD("get_screen_capture"), &Viewport::get_screen_capture);
+ ClassDB::bind_method(D_METHOD("set_size_override","enable","size","margin"), &Viewport::set_size_override,DEFVAL(Size2(-1,-1)),DEFVAL(Size2(0,0)));
+ ClassDB::bind_method(D_METHOD("get_size_override"), &Viewport::get_size_override);
+ ClassDB::bind_method(D_METHOD("is_size_override_enabled"), &Viewport::is_size_override_enabled);
+ ClassDB::bind_method(D_METHOD("set_size_override_stretch","enabled"), &Viewport::set_size_override_stretch);
+ ClassDB::bind_method(D_METHOD("is_size_override_stretch_enabled"), &Viewport::is_size_override_stretch_enabled);
+ ClassDB::bind_method(D_METHOD("queue_screen_capture"), &Viewport::queue_screen_capture);
+ ClassDB::bind_method(D_METHOD("get_screen_capture"), &Viewport::get_screen_capture);
- ClassDB::bind_method(_MD("set_vflip","enable"), &Viewport::set_vflip);
- ClassDB::bind_method(_MD("get_vflip"), &Viewport::get_vflip);
+ ClassDB::bind_method(D_METHOD("set_vflip","enable"), &Viewport::set_vflip);
+ ClassDB::bind_method(D_METHOD("get_vflip"), &Viewport::get_vflip);
- ClassDB::bind_method(_MD("set_clear_on_new_frame","enable"), &Viewport::set_clear_on_new_frame);
- ClassDB::bind_method(_MD("get_clear_on_new_frame"), &Viewport::get_clear_on_new_frame);
+ ClassDB::bind_method(D_METHOD("set_clear_on_new_frame","enable"), &Viewport::set_clear_on_new_frame);
+ ClassDB::bind_method(D_METHOD("get_clear_on_new_frame"), &Viewport::get_clear_on_new_frame);
- ClassDB::bind_method(_MD("clear"), &Viewport::clear);
- ClassDB::bind_method(_MD("set_update_mode","mode"), &Viewport::set_update_mode);
- ClassDB::bind_method(_MD("get_update_mode"), &Viewport::get_update_mode);
+ ClassDB::bind_method(D_METHOD("clear"), &Viewport::clear);
+ ClassDB::bind_method(D_METHOD("set_update_mode","mode"), &Viewport::set_update_mode);
+ ClassDB::bind_method(D_METHOD("get_update_mode"), &Viewport::get_update_mode);
- ClassDB::bind_method(_MD("set_msaa","msaa"), &Viewport::set_msaa);
- ClassDB::bind_method(_MD("get_msaa"), &Viewport::get_msaa);
+ ClassDB::bind_method(D_METHOD("set_msaa","msaa"), &Viewport::set_msaa);
+ ClassDB::bind_method(D_METHOD("get_msaa"), &Viewport::get_msaa);
- ClassDB::bind_method(_MD("set_hdr","enable"), &Viewport::set_hdr);
- ClassDB::bind_method(_MD("get_hdr"), &Viewport::get_hdr);
+ ClassDB::bind_method(D_METHOD("set_hdr","enable"), &Viewport::set_hdr);
+ ClassDB::bind_method(D_METHOD("get_hdr"), &Viewport::get_hdr);
- ClassDB::bind_method(_MD("get_texture:ViewportTexture"), &Viewport::get_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:ViewportTexture"), &Viewport::get_texture);
- ClassDB::bind_method(_MD("set_physics_object_picking","enable"), &Viewport::set_physics_object_picking);
- ClassDB::bind_method(_MD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
+ ClassDB::bind_method(D_METHOD("set_physics_object_picking","enable"), &Viewport::set_physics_object_picking);
+ ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
- ClassDB::bind_method(_MD("get_viewport_rid"), &Viewport::get_viewport_rid);
- ClassDB::bind_method(_MD("input","local_event"), &Viewport::input);
- ClassDB::bind_method(_MD("unhandled_input","local_event"), &Viewport::unhandled_input);
+ ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid);
+ ClassDB::bind_method(D_METHOD("input","local_event"), &Viewport::input);
+ ClassDB::bind_method(D_METHOD("unhandled_input","local_event"), &Viewport::unhandled_input);
- ClassDB::bind_method(_MD("update_worlds"), &Viewport::update_worlds);
+ ClassDB::bind_method(D_METHOD("update_worlds"), &Viewport::update_worlds);
- ClassDB::bind_method(_MD("set_use_own_world","enable"), &Viewport::set_use_own_world);
- ClassDB::bind_method(_MD("is_using_own_world"), &Viewport::is_using_own_world);
+ ClassDB::bind_method(D_METHOD("set_use_own_world","enable"), &Viewport::set_use_own_world);
+ ClassDB::bind_method(D_METHOD("is_using_own_world"), &Viewport::is_using_own_world);
- ClassDB::bind_method(_MD("get_camera:Camera"), &Viewport::get_camera);
+ ClassDB::bind_method(D_METHOD("get_camera:Camera"), &Viewport::get_camera);
- ClassDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener);
- ClassDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener);
+ ClassDB::bind_method(D_METHOD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener);
+ ClassDB::bind_method(D_METHOD("is_audio_listener","enable"), &Viewport::is_audio_listener);
- ClassDB::bind_method(_MD("set_as_audio_listener_2d","enable"), &Viewport::set_as_audio_listener_2d);
- ClassDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d);
- ClassDB::bind_method(_MD("set_attach_to_screen_rect","rect"), &Viewport::set_attach_to_screen_rect);
+ ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d","enable"), &Viewport::set_as_audio_listener_2d);
+ ClassDB::bind_method(D_METHOD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d);
+ ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect","rect"), &Viewport::set_attach_to_screen_rect);
- ClassDB::bind_method(_MD("get_mouse_pos"), &Viewport::get_mouse_pos);
- ClassDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse);
+ ClassDB::bind_method(D_METHOD("get_mouse_pos"), &Viewport::get_mouse_pos);
+ ClassDB::bind_method(D_METHOD("warp_mouse","to_pos"), &Viewport::warp_mouse);
- ClassDB::bind_method(_MD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
- ClassDB::bind_method(_MD("gui_get_drag_data:Variant"), &Viewport::gui_get_drag_data);
+ ClassDB::bind_method(D_METHOD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
+ ClassDB::bind_method(D_METHOD("gui_get_drag_data:Variant"), &Viewport::gui_get_drag_data);
- ClassDB::bind_method(_MD("set_disable_input","disable"), &Viewport::set_disable_input);
- ClassDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled);
+ ClassDB::bind_method(D_METHOD("set_disable_input","disable"), &Viewport::set_disable_input);
+ ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled);
- ClassDB::bind_method(_MD("set_disable_3d","disable"), &Viewport::set_disable_3d);
- ClassDB::bind_method(_MD("is_3d_disabled"), &Viewport::is_3d_disabled);
+ ClassDB::bind_method(D_METHOD("set_disable_3d","disable"), &Viewport::set_disable_3d);
+ ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
- ClassDB::bind_method(_MD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
- ClassDB::bind_method(_MD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
+ ClassDB::bind_method(D_METHOD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
+ ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
- ClassDB::bind_method(_MD("set_shadow_atlas_size","size"), &Viewport::set_shadow_atlas_size);
- ClassDB::bind_method(_MD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);
+ ClassDB::bind_method(D_METHOD("set_shadow_atlas_size","size"), &Viewport::set_shadow_atlas_size);
+ ClassDB::bind_method(D_METHOD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);
- ClassDB::bind_method(_MD("set_shadow_atlas_quadrant_subdiv","quadrant","subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
- ClassDB::bind_method(_MD("get_shadow_atlas_quadrant_subdiv","quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
+ ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv","quadrant","subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
+ ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv","quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
- ADD_PROPERTY( PropertyInfo(Variant::RECT2,"size"), _SCS("set_size"), _SCS("get_size") );
- 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") );
- //ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world_2d",PROPERTY_HINT_RESOURCE_TYPE,"World2D"), _SCS("set_world_2d"), _SCS("get_world_2d") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") );
+ ADD_PROPERTY( PropertyInfo(Variant::RECT2,"size"), "set_size", "get_size") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), "set_use_own_world", "is_using_own_world") ;
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world",PROPERTY_HINT_RESOURCE_TYPE,"World"), "set_world", "get_world") ;
+ //ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world_2d",PROPERTY_HINT_RESOURCE_TYPE,"World2D"), "set_world_2d", "get_world_2d") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), "set_transparent_background", "has_transparent_background") ;
ADD_GROUP("Rendering","");
- ADD_PROPERTY( PropertyInfo(Variant::INT,"msaa",PROPERTY_HINT_ENUM,"Disabled,2x,4x,8x,16x"), _SCS("set_msaa"), _SCS("get_msaa") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"hdr"), _SCS("set_hdr"), _SCS("get_hdr") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"disable_3d"), _SCS("set_disable_3d"), _SCS("is_3d_disabled") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"msaa",PROPERTY_HINT_ENUM,"Disabled,2x,4x,8x,16x"), "set_msaa", "get_msaa") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"hdr"), "set_hdr", "get_hdr") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"disable_3d"), "set_disable_3d", "is_3d_disabled") ;
ADD_GROUP("Render Target","render_target_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target_v_flip"), _SCS("set_vflip"), _SCS("get_vflip") );
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target_clear_on_new_frame"), _SCS("set_clear_on_new_frame"), _SCS("get_clear_on_new_frame") );
- ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target_update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_update_mode"), _SCS("get_update_mode") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target_v_flip"), "set_vflip", "get_vflip") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target_clear_on_new_frame"), "set_clear_on_new_frame", "get_clear_on_new_frame") ;
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target_update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode") ;
ADD_GROUP("Audio Listener","audio_listener_");
- 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,"audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d") ;
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"audio_listener_enable_3d"), "set_as_audio_listener", "is_audio_listener") ;
ADD_GROUP("Physics","physics_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"physics_object_picking"), _SCS("set_physics_object_picking"), _SCS("get_physics_object_picking") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking") ;
ADD_GROUP("GUI","gui_");
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gui_disable_input"), _SCS("set_disable_input"), _SCS("is_input_disabled") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gui_disable_input"), "set_disable_input", "is_input_disabled") ;
ADD_GROUP("Shadow Atlas","shadow_atlas_");
- ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow_atlas_size"), _SCS("set_shadow_atlas_size"), _SCS("get_shadow_atlas_size") );
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_0",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),0 );
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_1",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),1 );
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_2",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),2 );
- ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_3",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),3 );
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size") ;
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_0",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv",0 );
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_1",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv",1 );
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_2",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv",2 );
+ ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas_quad_3",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv",3 );
ADD_SIGNAL(MethodInfo("size_changed"));
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index c0eaca24a3..ffdc85301a 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "register_scene_types.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include "scene/io/resource_format_image.h"
#include "scene/io/resource_format_wav.h"
@@ -121,6 +121,8 @@
#include "scene/2d/position_2d.h"
#include "scene/2d/tile_map.h"
//#include "scene/2d/tile_map.h"
+#include "scene/2d/line_2d.h"
+
#include "scene/resources/tile_set.h"
#include "scene/animation/animation_player.h"
@@ -494,6 +496,7 @@ void register_scene_types() {
ClassDB::register_class<SpriteFrames>();
ClassDB::register_class<AnimatedSprite>();
ClassDB::register_class<Position2D>();
+ ClassDB::register_class<Line2D>();
ClassDB::register_virtual_class<CollisionObject2D>();
ClassDB::register_virtual_class<PhysicsBody2D>();
ClassDB::register_class<StaticBody2D>();
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 5b9baa6a67..b743834e63 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1698,61 +1698,61 @@ float Animation::get_step() const{
void Animation::_bind_methods() {
- ClassDB::bind_method(_MD("add_track","type","at_pos"),&Animation::add_track,DEFVAL(-1));
- ClassDB::bind_method(_MD("remove_track","idx"),&Animation::remove_track);
- ClassDB::bind_method(_MD("get_track_count"),&Animation::get_track_count);
- ClassDB::bind_method(_MD("track_get_type","idx"),&Animation::track_get_type);
- ClassDB::bind_method(_MD("track_get_path","idx"),&Animation::track_get_path);
- ClassDB::bind_method(_MD("track_set_path","idx","path"),&Animation::track_set_path);
- ClassDB::bind_method(_MD("find_track","path"),&Animation::find_track);
+ ClassDB::bind_method(D_METHOD("add_track","type","at_pos"),&Animation::add_track,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("remove_track","idx"),&Animation::remove_track);
+ ClassDB::bind_method(D_METHOD("get_track_count"),&Animation::get_track_count);
+ ClassDB::bind_method(D_METHOD("track_get_type","idx"),&Animation::track_get_type);
+ ClassDB::bind_method(D_METHOD("track_get_path","idx"),&Animation::track_get_path);
+ ClassDB::bind_method(D_METHOD("track_set_path","idx","path"),&Animation::track_set_path);
+ ClassDB::bind_method(D_METHOD("find_track","path"),&Animation::find_track);
- ClassDB::bind_method(_MD("track_move_up","idx"),&Animation::track_move_up);
- ClassDB::bind_method(_MD("track_move_down","idx"),&Animation::track_move_down);
+ ClassDB::bind_method(D_METHOD("track_move_up","idx"),&Animation::track_move_up);
+ ClassDB::bind_method(D_METHOD("track_move_down","idx"),&Animation::track_move_down);
- ClassDB::bind_method(_MD("track_set_imported","idx","imported"),&Animation::track_set_imported);
- ClassDB::bind_method(_MD("track_is_imported","idx"),&Animation::track_is_imported);
+ ClassDB::bind_method(D_METHOD("track_set_imported","idx","imported"),&Animation::track_set_imported);
+ ClassDB::bind_method(D_METHOD("track_is_imported","idx"),&Animation::track_is_imported);
- ClassDB::bind_method(_MD("transform_track_insert_key","idx","time","loc","rot","scale"),&Animation::transform_track_insert_key);
- ClassDB::bind_method(_MD("track_insert_key","idx","time","key","transition"),&Animation::track_insert_key,DEFVAL(1));
- ClassDB::bind_method(_MD("track_remove_key","idx","key_idx"),&Animation::track_remove_key);
- ClassDB::bind_method(_MD("track_remove_key_at_pos","idx","pos"),&Animation::track_remove_key_at_pos);
- ClassDB::bind_method(_MD("track_set_key_value","idx","key","value"),&Animation::track_set_key_value);
- ClassDB::bind_method(_MD("track_set_key_transition","idx","key_idx","transition"),&Animation::track_set_key_transition);
- ClassDB::bind_method(_MD("track_get_key_transition","idx","key_idx"),&Animation::track_get_key_transition);
+ ClassDB::bind_method(D_METHOD("transform_track_insert_key","idx","time","loc","rot","scale"),&Animation::transform_track_insert_key);
+ ClassDB::bind_method(D_METHOD("track_insert_key","idx","time","key","transition"),&Animation::track_insert_key,DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("track_remove_key","idx","key_idx"),&Animation::track_remove_key);
+ ClassDB::bind_method(D_METHOD("track_remove_key_at_pos","idx","pos"),&Animation::track_remove_key_at_pos);
+ ClassDB::bind_method(D_METHOD("track_set_key_value","idx","key","value"),&Animation::track_set_key_value);
+ ClassDB::bind_method(D_METHOD("track_set_key_transition","idx","key_idx","transition"),&Animation::track_set_key_transition);
+ ClassDB::bind_method(D_METHOD("track_get_key_transition","idx","key_idx"),&Animation::track_get_key_transition);
- ClassDB::bind_method(_MD("track_get_key_count","idx"),&Animation::track_get_key_count);
- ClassDB::bind_method(_MD("track_get_key_value","idx","key_idx"),&Animation::track_get_key_value);
- ClassDB::bind_method(_MD("track_get_key_time","idx","key_idx"),&Animation::track_get_key_time);
- ClassDB::bind_method(_MD("track_find_key","idx","time","exact"),&Animation::track_find_key,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("track_get_key_count","idx"),&Animation::track_get_key_count);
+ ClassDB::bind_method(D_METHOD("track_get_key_value","idx","key_idx"),&Animation::track_get_key_value);
+ ClassDB::bind_method(D_METHOD("track_get_key_time","idx","key_idx"),&Animation::track_get_key_time);
+ ClassDB::bind_method(D_METHOD("track_find_key","idx","time","exact"),&Animation::track_find_key,DEFVAL(false));
- ClassDB::bind_method(_MD("track_set_interpolation_type","idx","interpolation"),&Animation::track_set_interpolation_type);
- ClassDB::bind_method(_MD("track_get_interpolation_type","idx"),&Animation::track_get_interpolation_type);
+ ClassDB::bind_method(D_METHOD("track_set_interpolation_type","idx","interpolation"),&Animation::track_set_interpolation_type);
+ ClassDB::bind_method(D_METHOD("track_get_interpolation_type","idx"),&Animation::track_get_interpolation_type);
- ClassDB::bind_method(_MD("track_set_interpolation_loop_wrap","idx","interpolation"),&Animation::track_set_interpolation_loop_wrap);
- ClassDB::bind_method(_MD("track_get_interpolation_loop_wrap","idx"),&Animation::track_get_interpolation_loop_wrap);
+ ClassDB::bind_method(D_METHOD("track_set_interpolation_loop_wrap","idx","interpolation"),&Animation::track_set_interpolation_loop_wrap);
+ ClassDB::bind_method(D_METHOD("track_get_interpolation_loop_wrap","idx"),&Animation::track_get_interpolation_loop_wrap);
- ClassDB::bind_method(_MD("transform_track_interpolate","idx","time_sec"),&Animation::_transform_track_interpolate);
- ClassDB::bind_method(_MD("value_track_set_update_mode","idx","mode"),&Animation::value_track_set_update_mode);
- ClassDB::bind_method(_MD("value_track_get_update_mode","idx"),&Animation::value_track_get_update_mode);
+ ClassDB::bind_method(D_METHOD("transform_track_interpolate","idx","time_sec"),&Animation::_transform_track_interpolate);
+ ClassDB::bind_method(D_METHOD("value_track_set_update_mode","idx","mode"),&Animation::value_track_set_update_mode);
+ ClassDB::bind_method(D_METHOD("value_track_get_update_mode","idx"),&Animation::value_track_get_update_mode);
- ClassDB::bind_method(_MD("value_track_get_key_indices","idx","time_sec","delta"),&Animation::_value_track_get_key_indices);
+ ClassDB::bind_method(D_METHOD("value_track_get_key_indices","idx","time_sec","delta"),&Animation::_value_track_get_key_indices);
- ClassDB::bind_method(_MD("method_track_get_key_indices","idx","time_sec","delta"),&Animation::_method_track_get_key_indices);
- ClassDB::bind_method(_MD("method_track_get_name","idx","key_idx"),&Animation::method_track_get_name);
- ClassDB::bind_method(_MD("method_track_get_params","idx","key_idx"),&Animation::method_track_get_params);
+ ClassDB::bind_method(D_METHOD("method_track_get_key_indices","idx","time_sec","delta"),&Animation::_method_track_get_key_indices);
+ ClassDB::bind_method(D_METHOD("method_track_get_name","idx","key_idx"),&Animation::method_track_get_name);
+ ClassDB::bind_method(D_METHOD("method_track_get_params","idx","key_idx"),&Animation::method_track_get_params);
- ClassDB::bind_method(_MD("set_length","time_sec"),&Animation::set_length);
- ClassDB::bind_method(_MD("get_length"),&Animation::get_length);
+ ClassDB::bind_method(D_METHOD("set_length","time_sec"),&Animation::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"),&Animation::get_length);
- ClassDB::bind_method(_MD("set_loop","enabled"),&Animation::set_loop);
- ClassDB::bind_method(_MD("has_loop"),&Animation::has_loop);
+ ClassDB::bind_method(D_METHOD("set_loop","enabled"),&Animation::set_loop);
+ ClassDB::bind_method(D_METHOD("has_loop"),&Animation::has_loop);
- ClassDB::bind_method(_MD("set_step","size_sec"),&Animation::set_step);
- ClassDB::bind_method(_MD("get_step"),&Animation::get_step);
+ ClassDB::bind_method(D_METHOD("set_step","size_sec"),&Animation::set_step);
+ ClassDB::bind_method(D_METHOD("get_step"),&Animation::get_step);
- ClassDB::bind_method(_MD("clear"),&Animation::clear);
+ ClassDB::bind_method(D_METHOD("clear"),&Animation::clear);
BIND_CONSTANT( TYPE_VALUE );
BIND_CONSTANT( TYPE_TRANSFORM );
diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp
index 7b49ec0849..b2f314a55e 100644
--- a/scene/resources/audio_stream_resampled.cpp
+++ b/scene/resources/audio_stream_resampled.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "audio_stream_resampled.h"
-#include "globals.h"
+#include "global_config.h"
#if 0
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index 21339cb90b..4aee119b0e 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_stream_sample.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_stream_sample.h"
void AudioStreamPlaybackSample::start(float p_from_pos) {
@@ -504,34 +532,34 @@ String AudioStreamSample::get_stream_name() const {
void AudioStreamSample::_bind_methods() {
- ClassDB::bind_method(_MD("set_format","format"),&AudioStreamSample::set_format);
- ClassDB::bind_method(_MD("get_format"),&AudioStreamSample::get_format);
+ ClassDB::bind_method(D_METHOD("set_format","format"),&AudioStreamSample::set_format);
+ ClassDB::bind_method(D_METHOD("get_format"),&AudioStreamSample::get_format);
- ClassDB::bind_method(_MD("set_loop_mode","loop_mode"),&AudioStreamSample::set_loop_mode);
- ClassDB::bind_method(_MD("get_loop_mode"),&AudioStreamSample::get_loop_mode);
+ ClassDB::bind_method(D_METHOD("set_loop_mode","loop_mode"),&AudioStreamSample::set_loop_mode);
+ ClassDB::bind_method(D_METHOD("get_loop_mode"),&AudioStreamSample::get_loop_mode);
- ClassDB::bind_method(_MD("set_loop_begin","loop_begin"),&AudioStreamSample::set_loop_begin);
- ClassDB::bind_method(_MD("get_loop_begin"),&AudioStreamSample::get_loop_begin);
+ ClassDB::bind_method(D_METHOD("set_loop_begin","loop_begin"),&AudioStreamSample::set_loop_begin);
+ ClassDB::bind_method(D_METHOD("get_loop_begin"),&AudioStreamSample::get_loop_begin);
- ClassDB::bind_method(_MD("set_loop_end","loop_end"),&AudioStreamSample::set_loop_end);
- ClassDB::bind_method(_MD("get_loop_end"),&AudioStreamSample::get_loop_end);
+ ClassDB::bind_method(D_METHOD("set_loop_end","loop_end"),&AudioStreamSample::set_loop_end);
+ ClassDB::bind_method(D_METHOD("get_loop_end"),&AudioStreamSample::get_loop_end);
- ClassDB::bind_method(_MD("set_mix_rate","mix_rate"),&AudioStreamSample::set_mix_rate);
- ClassDB::bind_method(_MD("get_mix_rate"),&AudioStreamSample::get_mix_rate);
+ ClassDB::bind_method(D_METHOD("set_mix_rate","mix_rate"),&AudioStreamSample::set_mix_rate);
+ ClassDB::bind_method(D_METHOD("get_mix_rate"),&AudioStreamSample::get_mix_rate);
- ClassDB::bind_method(_MD("set_stereo","stereo"),&AudioStreamSample::set_stereo);
- ClassDB::bind_method(_MD("is_stereo"),&AudioStreamSample::is_stereo);
+ ClassDB::bind_method(D_METHOD("set_stereo","stereo"),&AudioStreamSample::set_stereo);
+ ClassDB::bind_method(D_METHOD("is_stereo"),&AudioStreamSample::is_stereo);
- ClassDB::bind_method(_MD("set_data","data"),&AudioStreamSample::set_data);
- ClassDB::bind_method(_MD("get_data"),&AudioStreamSample::get_data);
+ ClassDB::bind_method(D_METHOD("set_data","data"),&AudioStreamSample::set_data);
+ ClassDB::bind_method(D_METHOD("get_data"),&AudioStreamSample::get_data);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"format",PROPERTY_HINT_ENUM,"8-Bit,16-Bit,IMA-ADPCM"),_SCS("set_format"),_SCS("get_format"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"loop_mode",PROPERTY_HINT_ENUM,"Disabled,Forward,Ping-Pong"),_SCS("set_loop_mode"),_SCS("get_loop_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"loop_begin"),_SCS("set_loop_begin"),_SCS("get_loop_begin"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"loop_end"),_SCS("set_loop_end"),_SCS("get_loop_end"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"mix_rate"),_SCS("set_mix_rate"),_SCS("get_mix_rate"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"stereo"),_SCS("set_stereo"),_SCS("is_stereo"));
- ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_data"),_SCS("get_data"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"format",PROPERTY_HINT_ENUM,"8-Bit,16-Bit,IMA-ADPCM"),"set_format","get_format");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"loop_mode",PROPERTY_HINT_ENUM,"Disabled,Forward,Ping-Pong"),"set_loop_mode","get_loop_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"loop_begin"),"set_loop_begin","get_loop_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"loop_end"),"set_loop_end","get_loop_end");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"mix_rate"),"set_mix_rate","get_mix_rate");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"stereo"),"set_stereo","is_stereo");
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"set_data","get_data");
}
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h
index 8c1e74608b..53e628c0e4 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_sample.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_stream_sample.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOSTREAMSAMPLE_H
#define AUDIOSTREAMSAMPLE_H
diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp
index d669ab771c..4ceac5af0c 100644
--- a/scene/resources/bit_mask.cpp
+++ b/scene/resources/bit_mask.cpp
@@ -177,21 +177,21 @@ Dictionary BitMap::_get_data() const{
void BitMap::_bind_methods() {
- ClassDB::bind_method(_MD("create","size"),&BitMap::create);
- ClassDB::bind_method(_MD("create_from_image_alpha","image"),&BitMap::create_from_image_alpha);
+ ClassDB::bind_method(D_METHOD("create","size"),&BitMap::create);
+ ClassDB::bind_method(D_METHOD("create_from_image_alpha","image"),&BitMap::create_from_image_alpha);
- ClassDB::bind_method(_MD("set_bit","pos","bit"),&BitMap::set_bit);
- ClassDB::bind_method(_MD("get_bit","pos"),&BitMap::get_bit);
+ ClassDB::bind_method(D_METHOD("set_bit","pos","bit"),&BitMap::set_bit);
+ ClassDB::bind_method(D_METHOD("get_bit","pos"),&BitMap::get_bit);
- ClassDB::bind_method(_MD("set_bit_rect","p_rect","bit"),&BitMap::set_bit_rect);
- ClassDB::bind_method(_MD("get_true_bit_count"),&BitMap::get_true_bit_count);
+ ClassDB::bind_method(D_METHOD("set_bit_rect","p_rect","bit"),&BitMap::set_bit_rect);
+ ClassDB::bind_method(D_METHOD("get_true_bit_count"),&BitMap::get_true_bit_count);
- ClassDB::bind_method(_MD("get_size"),&BitMap::get_size);
+ ClassDB::bind_method(D_METHOD("get_size"),&BitMap::get_size);
- ClassDB::bind_method(_MD("_set_data"),&BitMap::_set_data);
- ClassDB::bind_method(_MD("_get_data"),&BitMap::_get_data);
+ ClassDB::bind_method(D_METHOD("_set_data"),&BitMap::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"),&BitMap::_get_data);
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_data"),_SCS("_get_data"));
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_data","_get_data");
}
diff --git a/scene/resources/bounds.cpp b/scene/resources/bounds.cpp
index 03d819451d..26bf6270e9 100644
--- a/scene/resources/bounds.cpp
+++ b/scene/resources/bounds.cpp
@@ -31,10 +31,10 @@
void Bounds::_bind_methods() {
- ClassDB::bind_method( _MD("set_bsp_tree","bsp_tree"),&Bounds::set_bsp_tree);
- ClassDB::bind_method( _MD("get_bsp_tree"),&Bounds::get_bsp_tree );
+ ClassDB::bind_method( D_METHOD("set_bsp_tree","bsp_tree"),&Bounds::set_bsp_tree);
+ ClassDB::bind_method( D_METHOD("get_bsp_tree"),&Bounds::get_bsp_tree );
- ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "bsp_tree" ), _SCS("set_bsp_tree"), _SCS("get_bsp_tree"));
+ ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "bsp_tree" ), "set_bsp_tree", "get_bsp_tree");
}
diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp
index 87585af862..e8eccaceae 100644
--- a/scene/resources/box_shape.cpp
+++ b/scene/resources/box_shape.cpp
@@ -70,10 +70,10 @@ Vector3 BoxShape::get_extents() const {
void BoxShape::_bind_methods() {
- ClassDB::bind_method(_MD("set_extents","extents"),&BoxShape::set_extents);
- ClassDB::bind_method(_MD("get_extents"),&BoxShape::get_extents);
+ ClassDB::bind_method(D_METHOD("set_extents","extents"),&BoxShape::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"),&BoxShape::get_extents);
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"extents"), _SCS("set_extents"), _SCS("get_extents") );
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"extents"), "set_extents", "get_extents") ;
}
diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp
index 23538c1957..bd30f009c4 100644
--- a/scene/resources/capsule_shape.cpp
+++ b/scene/resources/capsule_shape.cpp
@@ -107,13 +107,13 @@ float CapsuleShape::get_height() const {
void CapsuleShape::_bind_methods() {
- ClassDB::bind_method(_MD("set_radius","radius"),&CapsuleShape::set_radius);
- ClassDB::bind_method(_MD("get_radius"),&CapsuleShape::get_radius);
- ClassDB::bind_method(_MD("set_height","height"),&CapsuleShape::set_height);
- ClassDB::bind_method(_MD("get_height"),&CapsuleShape::get_height);
+ ClassDB::bind_method(D_METHOD("set_radius","radius"),&CapsuleShape::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"),&CapsuleShape::get_radius);
+ ClassDB::bind_method(D_METHOD("set_height","height"),&CapsuleShape::set_height);
+ ClassDB::bind_method(D_METHOD("get_height"),&CapsuleShape::get_height);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,4096,0.01"), _SCS("set_radius"),_SCS("get_radius") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,4096,0.01"), _SCS("set_height"),_SCS("get_height") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,4096,0.01"), "set_radius","get_radius") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,4096,0.01"), "set_height","get_height") ;
}
diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp
index 27dcff0ce0..523d6d7455 100644
--- a/scene/resources/capsule_shape_2d.cpp
+++ b/scene/resources/capsule_shape_2d.cpp
@@ -89,15 +89,15 @@ Rect2 CapsuleShape2D::get_rect() const {
void CapsuleShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_radius","radius"),&CapsuleShape2D::set_radius);
- ClassDB::bind_method(_MD("get_radius"),&CapsuleShape2D::get_radius);
+ ClassDB::bind_method(D_METHOD("set_radius","radius"),&CapsuleShape2D::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"),&CapsuleShape2D::get_radius);
- ClassDB::bind_method(_MD("set_height","height"),&CapsuleShape2D::set_height);
- ClassDB::bind_method(_MD("get_height"),&CapsuleShape2D::get_height);
+ ClassDB::bind_method(D_METHOD("set_height","height"),&CapsuleShape2D::set_height);
+ ClassDB::bind_method(D_METHOD("get_height"),&CapsuleShape2D::get_height);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius"),_SCS("set_radius"),_SCS("get_radius") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),_SCS("set_height"),_SCS("get_height") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius"),"set_radius","get_radius") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),"set_height","get_height") ;
}
diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp
index a82f3f5e2d..cd707b1032 100644
--- a/scene/resources/circle_shape_2d.cpp
+++ b/scene/resources/circle_shape_2d.cpp
@@ -51,10 +51,10 @@ real_t CircleShape2D::get_radius() const {
void CircleShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_radius","radius"),&CircleShape2D::set_radius);
- ClassDB::bind_method(_MD("get_radius"),&CircleShape2D::get_radius);
+ ClassDB::bind_method(D_METHOD("set_radius","radius"),&CircleShape2D::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"),&CircleShape2D::get_radius);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.5"),_SCS("set_radius"),_SCS("get_radius") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.5"),"set_radius","get_radius") ;
}
diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp
index 1144ea41f1..b14ba4c8ed 100644
--- a/scene/resources/color_ramp.cpp
+++ b/scene/resources/color_ramp.cpp
@@ -27,6 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "color_ramp.h"
+#include "core_string_names.h"
//setter and getter names for property serialization
#define COLOR_RAMP_GET_OFFSETS "get_offsets"
@@ -54,27 +55,27 @@ void ColorRamp::_bind_methods() {
- ClassDB::bind_method(_MD("add_point","offset","color"),&ColorRamp::add_point);
- ClassDB::bind_method(_MD("remove_point","offset","color"),&ColorRamp::remove_point);
+ ClassDB::bind_method(D_METHOD("add_point","offset","color"),&ColorRamp::add_point);
+ ClassDB::bind_method(D_METHOD("remove_point","offset","color"),&ColorRamp::remove_point);
- ClassDB::bind_method(_MD("set_offset","point","offset"),&ColorRamp::set_offset);
- ClassDB::bind_method(_MD("get_offset","point"),&ColorRamp::get_offset);
+ ClassDB::bind_method(D_METHOD("set_offset","point","offset"),&ColorRamp::set_offset);
+ ClassDB::bind_method(D_METHOD("get_offset","point"),&ColorRamp::get_offset);
- ClassDB::bind_method(_MD("set_color","point","color"),&ColorRamp::set_color);
- ClassDB::bind_method(_MD("get_color","point"),&ColorRamp::get_color);
+ ClassDB::bind_method(D_METHOD("set_color","point","color"),&ColorRamp::set_color);
+ ClassDB::bind_method(D_METHOD("get_color","point"),&ColorRamp::get_color);
- ClassDB::bind_method(_MD("interpolate","offset"),&ColorRamp::get_color_at_offset);
+ ClassDB::bind_method(D_METHOD("interpolate","offset"),&ColorRamp::get_color_at_offset);
- ClassDB::bind_method(_MD("get_point_count"),&ColorRamp::get_points_count);
+ ClassDB::bind_method(D_METHOD("get_point_count"),&ColorRamp::get_points_count);
- ClassDB::bind_method(_MD(COLOR_RAMP_SET_OFFSETS,"offsets"),&ColorRamp::set_offsets);
- ClassDB::bind_method(_MD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offsets);
+ ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_OFFSETS,"offsets"),&ColorRamp::set_offsets);
+ ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_OFFSETS),&ColorRamp::get_offsets);
- ClassDB::bind_method(_MD(COLOR_RAMP_SET_COLORS,"colors"),&ColorRamp::set_colors);
- ClassDB::bind_method(_MD(COLOR_RAMP_GET_COLORS),&ColorRamp::get_colors);
+ ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS,"colors"),&ColorRamp::set_colors);
+ ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS),&ColorRamp::get_colors);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"offsets"),_SCS(COLOR_RAMP_SET_OFFSETS),_SCS(COLOR_RAMP_GET_OFFSETS) );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"colors"),_SCS(COLOR_RAMP_SET_COLORS),_SCS(COLOR_RAMP_GET_COLORS) );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"offsets"),COLOR_RAMP_SET_OFFSETS,COLOR_RAMP_GET_OFFSETS) ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"colors"),COLOR_RAMP_SET_COLORS,COLOR_RAMP_GET_COLORS) ;
}
Vector<float> ColorRamp::get_offsets() const {
@@ -104,6 +105,7 @@ void ColorRamp::set_offsets(const Vector<float>& p_offsets) {
points[i].offset = p_offsets[i];
}
is_sorted = false;
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
void ColorRamp::set_colors(const Vector<Color>& p_colors) {
@@ -114,6 +116,7 @@ void ColorRamp::set_colors(const Vector<Color>& p_colors) {
{
points[i].color = p_colors[i];
}
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
Vector<ColorRamp::Point>& ColorRamp::get_points() {
@@ -128,6 +131,7 @@ void ColorRamp::add_point(float p_offset, const Color& p_color) {
is_sorted=false;
points.push_back(p);
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
void ColorRamp::remove_point(int p_index) {
@@ -135,11 +139,13 @@ void ColorRamp::remove_point(int p_index) {
ERR_FAIL_INDEX(p_index,points.size());
ERR_FAIL_COND(points.size()<=2);
points.remove(p_index);
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
void ColorRamp::set_points(Vector<ColorRamp::Point>& p_points) {
points = p_points;
is_sorted = false;
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
void ColorRamp::set_offset(int pos, const float offset) {
@@ -147,6 +153,7 @@ void ColorRamp::set_offset(int pos, const float offset) {
points.resize(pos + 1);
points[pos].offset = offset;
is_sorted = false;
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
float ColorRamp::get_offset(int pos) const {
@@ -162,6 +169,7 @@ void ColorRamp::set_color(int pos, const Color& color) {
is_sorted = false;
}
points[pos].color = color;
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
Color ColorRamp::get_color(int pos) const {
diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp
index 5190bba6a5..3945ade215 100644
--- a/scene/resources/concave_polygon_shape.cpp
+++ b/scene/resources/concave_polygon_shape.cpp
@@ -110,8 +110,8 @@ PoolVector<Vector3> ConcavePolygonShape::get_faces() const {
void ConcavePolygonShape::_bind_methods() {
- ClassDB::bind_method(_MD("set_faces","faces"),&ConcavePolygonShape::set_faces);
- ClassDB::bind_method(_MD("get_faces"),&ConcavePolygonShape::get_faces);
+ ClassDB::bind_method(D_METHOD("set_faces","faces"),&ConcavePolygonShape::set_faces);
+ ClassDB::bind_method(D_METHOD("get_faces"),&ConcavePolygonShape::get_faces);
}
ConcavePolygonShape::ConcavePolygonShape() : Shape( PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON)) {
diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp
index 6866750006..f3dfa8a2b3 100644
--- a/scene/resources/concave_polygon_shape_2d.cpp
+++ b/scene/resources/concave_polygon_shape_2d.cpp
@@ -82,10 +82,10 @@ Rect2 ConcavePolygonShape2D::get_rect() const {
void ConcavePolygonShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_segments","segments"),&ConcavePolygonShape2D::set_segments);
- ClassDB::bind_method(_MD("get_segments"),&ConcavePolygonShape2D::get_segments);
+ ClassDB::bind_method(D_METHOD("set_segments","segments"),&ConcavePolygonShape2D::set_segments);
+ ClassDB::bind_method(D_METHOD("get_segments"),&ConcavePolygonShape2D::get_segments);
- ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"segments"),_SCS("set_segments"),_SCS("get_segments") );
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"segments"),"set_segments","get_segments") ;
}
diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp
index ca9897bf97..207419f8cd 100644
--- a/scene/resources/convex_polygon_shape.cpp
+++ b/scene/resources/convex_polygon_shape.cpp
@@ -79,10 +79,10 @@ PoolVector<Vector3> ConvexPolygonShape::get_points() const {
void ConvexPolygonShape::_bind_methods() {
- ClassDB::bind_method(_MD("set_points","points"),&ConvexPolygonShape::set_points);
- ClassDB::bind_method(_MD("get_points"),&ConvexPolygonShape::get_points);
+ ClassDB::bind_method(D_METHOD("set_points","points"),&ConvexPolygonShape::set_points);
+ ClassDB::bind_method(D_METHOD("get_points"),&ConvexPolygonShape::get_points);
- ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"points"), _SCS("set_points"), _SCS("get_points") );
+ ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"points"), "set_points", "get_points") ;
}
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index 0d3ba238f6..2a4b181611 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -61,13 +61,13 @@ Vector<Vector2> ConvexPolygonShape2D::get_points() const {
void ConvexPolygonShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_point_cloud","point_cloud"),&ConvexPolygonShape2D::set_point_cloud);
- ClassDB::bind_method(_MD("set_points","points"),&ConvexPolygonShape2D::set_points);
- ClassDB::bind_method(_MD("get_points"),&ConvexPolygonShape2D::get_points);
+ ClassDB::bind_method(D_METHOD("set_point_cloud","point_cloud"),&ConvexPolygonShape2D::set_point_cloud);
+ ClassDB::bind_method(D_METHOD("set_points","points"),&ConvexPolygonShape2D::set_points);
+ ClassDB::bind_method(D_METHOD("get_points"),&ConvexPolygonShape2D::get_points);
- ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"points"),_SCS("set_points"),_SCS("get_points") );
+ ADD_PROPERTY( PropertyInfo(Variant::POOL_VECTOR2_ARRAY,"points"),"set_points","get_points") ;
}
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 3392c68e75..9311ab4dd7 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -349,30 +349,30 @@ Vector2Array Curve2D::get_points_pos() const {
void Curve2D::_bind_methods() {
- ClassDB::bind_method(_MD("get_point_count"),&Curve2D::get_point_count);
- ClassDB::bind_method(_MD("add_point","pos","in","out"),&Curve2D::add_point,DEFVAL(Vector2()),DEFVAL(Vector2()));
- ClassDB::bind_method(_MD("set_point_pos","idx","pos"),&Curve2D::set_point_pos);
- ClassDB::bind_method(_MD("get_point_pos","idx"),&Curve2D::get_point_pos);
- ClassDB::bind_method(_MD("set_point_in","idx","pos"),&Curve2D::set_point_in);
- ClassDB::bind_method(_MD("get_point_in","idx"),&Curve2D::get_point_in);
- ClassDB::bind_method(_MD("set_point_out","idx","pos"),&Curve2D::set_point_out);
- ClassDB::bind_method(_MD("get_point_out","idx"),&Curve2D::get_point_out);
- ClassDB::bind_method(_MD("remove_point","idx"),&Curve2D::remove_point);
- ClassDB::bind_method(_MD("interpolate","idx","t"),&Curve2D::interpolate);
- ClassDB::bind_method(_MD("bake","subdivs"),&Curve2D::bake,DEFVAL(10));
+ ClassDB::bind_method(D_METHOD("get_point_count"),&Curve2D::get_point_count);
+ ClassDB::bind_method(D_METHOD("add_point","pos","in","out"),&Curve2D::add_point,DEFVAL(Vector2()),DEFVAL(Vector2()));
+ ClassDB::bind_method(D_METHOD("set_point_pos","idx","pos"),&Curve2D::set_point_pos);
+ ClassDB::bind_method(D_METHOD("get_point_pos","idx"),&Curve2D::get_point_pos);
+ ClassDB::bind_method(D_METHOD("set_point_in","idx","pos"),&Curve2D::set_point_in);
+ ClassDB::bind_method(D_METHOD("get_point_in","idx"),&Curve2D::get_point_in);
+ ClassDB::bind_method(D_METHOD("set_point_out","idx","pos"),&Curve2D::set_point_out);
+ ClassDB::bind_method(D_METHOD("get_point_out","idx"),&Curve2D::get_point_out);
+ ClassDB::bind_method(D_METHOD("remove_point","idx"),&Curve2D::remove_point);
+ ClassDB::bind_method(D_METHOD("interpolate","idx","t"),&Curve2D::interpolate);
+ ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve2D::bake,DEFVAL(10));
- ClassDB::bind_method(_MD("set_points_in"),&Curve2D::set_points_in);
- ClassDB::bind_method(_MD("set_points_out"),&Curve2D::set_points_out);
- ClassDB::bind_method(_MD("set_points_pos"),&Curve2D::set_points_pos);
+ ClassDB::bind_method(D_METHOD("set_points_in"),&Curve2D::set_points_in);
+ ClassDB::bind_method(D_METHOD("set_points_out"),&Curve2D::set_points_out);
+ ClassDB::bind_method(D_METHOD("set_points_pos"),&Curve2D::set_points_pos);
- ClassDB::bind_method(_MD("get_points_in"),&Curve2D::get_points_in);
- ClassDB::bind_method(_MD("get_points_out"),&Curve2D::get_points_out);
- ClassDB::bind_method(_MD("get_points_pos"),&Curve2D::get_points_pos);
+ ClassDB::bind_method(D_METHOD("get_points_in"),&Curve2D::get_points_in);
+ ClassDB::bind_method(D_METHOD("get_points_out"),&Curve2D::get_points_out);
+ ClassDB::bind_method(D_METHOD("get_points_pos"),&Curve2D::get_points_pos);
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR2_ARRAY, "points_in"), _SCS("set_points_in"),_SCS("get_points_in"));
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR2_ARRAY, "points_out"), _SCS("set_points_out"),_SCS("get_points_out"));
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR2_ARRAY, "points_pos"), _SCS("set_points_pos"),_SCS("get_points_pos"));
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2_ARRAY, "points_in"), "set_points_in","get_points_in");
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2_ARRAY, "points_out"), "set_points_out","get_points_out");
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR2_ARRAY, "points_pos"), "set_points_pos","get_points_pos");
}
@@ -789,35 +789,35 @@ PoolVector2Array Curve2D::tesselate(int p_max_stages,float p_tolerance) const {
void Curve2D::_bind_methods() {
- ClassDB::bind_method(_MD("get_point_count"),&Curve2D::get_point_count);
- ClassDB::bind_method(_MD("add_point","pos","in","out","atpos"),&Curve2D::add_point,DEFVAL(Vector2()),DEFVAL(Vector2()),DEFVAL(-1));
- ClassDB::bind_method(_MD("set_point_pos","idx","pos"),&Curve2D::set_point_pos);
- ClassDB::bind_method(_MD("get_point_pos","idx"),&Curve2D::get_point_pos);
- ClassDB::bind_method(_MD("set_point_in","idx","pos"),&Curve2D::set_point_in);
- ClassDB::bind_method(_MD("get_point_in","idx"),&Curve2D::get_point_in);
- ClassDB::bind_method(_MD("set_point_out","idx","pos"),&Curve2D::set_point_out);
- ClassDB::bind_method(_MD("get_point_out","idx"),&Curve2D::get_point_out);
- ClassDB::bind_method(_MD("remove_point","idx"),&Curve2D::remove_point);
- ClassDB::bind_method(_MD("clear_points"),&Curve2D::clear_points);
- ClassDB::bind_method(_MD("interpolate","idx","t"),&Curve2D::interpolate);
- ClassDB::bind_method(_MD("interpolatef","fofs"),&Curve2D::interpolatef);
- //ClassDB::bind_method(_MD("bake","subdivs"),&Curve2D::bake,DEFVAL(10));
- ClassDB::bind_method(_MD("set_bake_interval","distance"),&Curve2D::set_bake_interval);
- ClassDB::bind_method(_MD("get_bake_interval"),&Curve2D::get_bake_interval);
-
- ClassDB::bind_method(_MD("get_baked_length"),&Curve2D::get_baked_length);
- ClassDB::bind_method(_MD("interpolate_baked","offset","cubic"),&Curve2D::interpolate_baked,DEFVAL(false));
- ClassDB::bind_method(_MD("get_baked_points"),&Curve2D::get_baked_points);
- ClassDB::bind_method(_MD("tesselate","max_stages","tolerance_degrees"),&Curve2D::tesselate,DEFVAL(5),DEFVAL(4));
-
- ClassDB::bind_method(_MD("_get_data"),&Curve2D::_get_data);
- ClassDB::bind_method(_MD("_set_data"),&Curve2D::_set_data);
-
-
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "bake_interval",PROPERTY_HINT_RANGE,"0.01,512,0.01"), _SCS("set_bake_interval"),_SCS("get_bake_interval"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"),_SCS("_get_data"));
- /*ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_out"), _SCS("set_points_out"),_SCS("get_points_out"));
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_pos"), _SCS("set_points_pos"),_SCS("get_points_pos"));
+ ClassDB::bind_method(D_METHOD("get_point_count"),&Curve2D::get_point_count);
+ ClassDB::bind_method(D_METHOD("add_point","pos","in","out","atpos"),&Curve2D::add_point,DEFVAL(Vector2()),DEFVAL(Vector2()),DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("set_point_pos","idx","pos"),&Curve2D::set_point_pos);
+ ClassDB::bind_method(D_METHOD("get_point_pos","idx"),&Curve2D::get_point_pos);
+ ClassDB::bind_method(D_METHOD("set_point_in","idx","pos"),&Curve2D::set_point_in);
+ ClassDB::bind_method(D_METHOD("get_point_in","idx"),&Curve2D::get_point_in);
+ ClassDB::bind_method(D_METHOD("set_point_out","idx","pos"),&Curve2D::set_point_out);
+ ClassDB::bind_method(D_METHOD("get_point_out","idx"),&Curve2D::get_point_out);
+ ClassDB::bind_method(D_METHOD("remove_point","idx"),&Curve2D::remove_point);
+ ClassDB::bind_method(D_METHOD("clear_points"),&Curve2D::clear_points);
+ ClassDB::bind_method(D_METHOD("interpolate","idx","t"),&Curve2D::interpolate);
+ ClassDB::bind_method(D_METHOD("interpolatef","fofs"),&Curve2D::interpolatef);
+ //ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve2D::bake,DEFVAL(10));
+ ClassDB::bind_method(D_METHOD("set_bake_interval","distance"),&Curve2D::set_bake_interval);
+ ClassDB::bind_method(D_METHOD("get_bake_interval"),&Curve2D::get_bake_interval);
+
+ ClassDB::bind_method(D_METHOD("get_baked_length"),&Curve2D::get_baked_length);
+ ClassDB::bind_method(D_METHOD("interpolate_baked","offset","cubic"),&Curve2D::interpolate_baked,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_baked_points"),&Curve2D::get_baked_points);
+ ClassDB::bind_method(D_METHOD("tesselate","max_stages","tolerance_degrees"),&Curve2D::tesselate,DEFVAL(5),DEFVAL(4));
+
+ ClassDB::bind_method(D_METHOD("_get_data"),&Curve2D::_get_data);
+ ClassDB::bind_method(D_METHOD("_set_data"),&Curve2D::_set_data);
+
+
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "bake_interval",PROPERTY_HINT_RANGE,"0.01,512,0.01"), "set_bake_interval","get_bake_interval");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_data","_get_data");
+ /*ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_out"), "set_points_out","get_points_out");
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_pos"), "set_points_pos","get_points_pos");
*/
}
@@ -1329,38 +1329,38 @@ PoolVector3Array Curve3D::tesselate(int p_max_stages,float p_tolerance) const {
void Curve3D::_bind_methods() {
- ClassDB::bind_method(_MD("get_point_count"),&Curve3D::get_point_count);
- ClassDB::bind_method(_MD("add_point","pos","in","out","atpos"),&Curve3D::add_point,DEFVAL(Vector3()),DEFVAL(Vector3()),DEFVAL(-1));
- ClassDB::bind_method(_MD("set_point_pos","idx","pos"),&Curve3D::set_point_pos);
- ClassDB::bind_method(_MD("get_point_pos","idx"),&Curve3D::get_point_pos);
- ClassDB::bind_method(_MD("set_point_tilt","idx","tilt"),&Curve3D::set_point_tilt);
- ClassDB::bind_method(_MD("get_point_tilt","idx"),&Curve3D::get_point_tilt);
- ClassDB::bind_method(_MD("set_point_in","idx","pos"),&Curve3D::set_point_in);
- ClassDB::bind_method(_MD("get_point_in","idx"),&Curve3D::get_point_in);
- ClassDB::bind_method(_MD("set_point_out","idx","pos"),&Curve3D::set_point_out);
- ClassDB::bind_method(_MD("get_point_out","idx"),&Curve3D::get_point_out);
- ClassDB::bind_method(_MD("remove_point","idx"),&Curve3D::remove_point);
- ClassDB::bind_method(_MD("clear_points"),&Curve3D::clear_points);
- ClassDB::bind_method(_MD("interpolate","idx","t"),&Curve3D::interpolate);
- ClassDB::bind_method(_MD("interpolatef","fofs"),&Curve3D::interpolatef);
- //ClassDB::bind_method(_MD("bake","subdivs"),&Curve3D::bake,DEFVAL(10));
- ClassDB::bind_method(_MD("set_bake_interval","distance"),&Curve3D::set_bake_interval);
- ClassDB::bind_method(_MD("get_bake_interval"),&Curve3D::get_bake_interval);
-
- ClassDB::bind_method(_MD("get_baked_length"),&Curve3D::get_baked_length);
- ClassDB::bind_method(_MD("interpolate_baked","offset","cubic"),&Curve3D::interpolate_baked,DEFVAL(false));
- ClassDB::bind_method(_MD("get_baked_points"),&Curve3D::get_baked_points);
- ClassDB::bind_method(_MD("get_baked_tilts"),&Curve3D::get_baked_tilts);
- ClassDB::bind_method(_MD("tesselate","max_stages","tolerance_degrees"),&Curve3D::tesselate,DEFVAL(5),DEFVAL(4));
-
- ClassDB::bind_method(_MD("_get_data"),&Curve3D::_get_data);
- ClassDB::bind_method(_MD("_set_data"),&Curve3D::_set_data);
-
-
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "bake_interval",PROPERTY_HINT_RANGE,"0.01,512,0.01"), _SCS("set_bake_interval"),_SCS("get_bake_interval"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"),_SCS("_get_data"));
- /*ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_out"), _SCS("set_points_out"),_SCS("get_points_out"));
- ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_pos"), _SCS("set_points_pos"),_SCS("get_points_pos"));
+ ClassDB::bind_method(D_METHOD("get_point_count"),&Curve3D::get_point_count);
+ ClassDB::bind_method(D_METHOD("add_point","pos","in","out","atpos"),&Curve3D::add_point,DEFVAL(Vector3()),DEFVAL(Vector3()),DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("set_point_pos","idx","pos"),&Curve3D::set_point_pos);
+ ClassDB::bind_method(D_METHOD("get_point_pos","idx"),&Curve3D::get_point_pos);
+ ClassDB::bind_method(D_METHOD("set_point_tilt","idx","tilt"),&Curve3D::set_point_tilt);
+ ClassDB::bind_method(D_METHOD("get_point_tilt","idx"),&Curve3D::get_point_tilt);
+ ClassDB::bind_method(D_METHOD("set_point_in","idx","pos"),&Curve3D::set_point_in);
+ ClassDB::bind_method(D_METHOD("get_point_in","idx"),&Curve3D::get_point_in);
+ ClassDB::bind_method(D_METHOD("set_point_out","idx","pos"),&Curve3D::set_point_out);
+ ClassDB::bind_method(D_METHOD("get_point_out","idx"),&Curve3D::get_point_out);
+ ClassDB::bind_method(D_METHOD("remove_point","idx"),&Curve3D::remove_point);
+ ClassDB::bind_method(D_METHOD("clear_points"),&Curve3D::clear_points);
+ ClassDB::bind_method(D_METHOD("interpolate","idx","t"),&Curve3D::interpolate);
+ ClassDB::bind_method(D_METHOD("interpolatef","fofs"),&Curve3D::interpolatef);
+ //ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve3D::bake,DEFVAL(10));
+ ClassDB::bind_method(D_METHOD("set_bake_interval","distance"),&Curve3D::set_bake_interval);
+ ClassDB::bind_method(D_METHOD("get_bake_interval"),&Curve3D::get_bake_interval);
+
+ ClassDB::bind_method(D_METHOD("get_baked_length"),&Curve3D::get_baked_length);
+ ClassDB::bind_method(D_METHOD("interpolate_baked","offset","cubic"),&Curve3D::interpolate_baked,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_baked_points"),&Curve3D::get_baked_points);
+ ClassDB::bind_method(D_METHOD("get_baked_tilts"),&Curve3D::get_baked_tilts);
+ ClassDB::bind_method(D_METHOD("tesselate","max_stages","tolerance_degrees"),&Curve3D::tesselate,DEFVAL(5),DEFVAL(4));
+
+ ClassDB::bind_method(D_METHOD("_get_data"),&Curve3D::_get_data);
+ ClassDB::bind_method(D_METHOD("_set_data"),&Curve3D::_set_data);
+
+
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "bake_interval",PROPERTY_HINT_RANGE,"0.01,512,0.01"), "set_bake_interval","get_bake_interval");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_data","_get_data");
+ /*ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_out"), "set_points_out","get_points_out");
+ ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "points_pos"), "set_points_pos","get_points_pos");
*/
}
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 50c6a6c725..dbe0f3e33e 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -583,24 +583,19 @@ void fill_default_theme(Ref<Theme>& t, const Ref<Font> & default_font, const Ref
// WindowDialog
- Ref<StyleBoxTexture> style_pp_win = sb_expand(make_stylebox( popup_window_png,10,30,10,8),8,26,8,4);
- /*for(int i=0;i<4;i++)
- style_pp_win->set_expand_margin_size((Margin)i,3);
- style_pp_win->set_expand_margin_size(MARGIN_TOP,26);*/
+ Ref<StyleBoxTexture> style_pp_win = sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6);
+ t->set_stylebox("panel", "WindowDialog", style_pp_win);
+ t->set_constant("titlebar_height", "WindowDialog", 20 * scale);
+ t->set_constant("scaleborder_size", "WindowDialog", 4);
- t->set_stylebox("panel","WindowDialog", style_pp_win );
+ t->set_font("title_font", "WindowDialog", large_font);
+ t->set_color("title_color", "WindowDialog", Color(0, 0, 0));
+ t->set_constant("title_height", "WindowDialog", 18 * scale);
- t->set_icon("close","WindowDialog", make_icon( close_png ) );
- t->set_icon("close_hilite","WindowDialog", make_icon( close_hl_png ) );
-
- t->set_font("title_font","WindowDialog", large_font );
-
- t->set_color("title_color","WindowDialog", Color(0,0,0) );
-
- t->set_constant("close_h_ofs","WindowDialog", 22 *scale);
- t->set_constant("close_v_ofs","WindowDialog", 20 *scale);
- t->set_constant("titlebar_height","WindowDialog", 18 *scale);
- t->set_constant("title_height","WindowDialog", 20 *scale);
+ t->set_icon("close", "WindowDialog", make_icon(close_png));
+ t->set_icon("close_hilite", "WindowDialog", make_icon(close_hl_png));
+ t->set_constant("close_h_ofs", "WindowDialog", 18 * scale);
+ t->set_constant("close_v_ofs", "WindowDialog", 18 * scale);
// File Dialog
@@ -750,6 +745,7 @@ void fill_default_theme(Ref<Theme>& t, const Ref<Font> & default_font, const Ref
t->set_stylebox("tab_fg","TabContainer", sb_expand( make_stylebox( tab_current_png,4,4,4,1,16,4,16,4),2,2,2,2) );
t->set_stylebox("tab_bg","TabContainer", sb_expand( make_stylebox( tab_behind_png,5,5,5,1,16,6,16,4),3,0,3,3) );
+ t->set_stylebox("tab_disabled", "TabContainer", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3));
t->set_stylebox("panel","TabContainer", tc_sb );
t->set_icon("increment","TabContainer",make_icon( scroll_button_right_png));
@@ -763,6 +759,7 @@ void fill_default_theme(Ref<Theme>& t, const Ref<Font> & default_font, const Ref
t->set_color("font_color_fg","TabContainer", control_font_color_hover );
t->set_color("font_color_bg","TabContainer", control_font_color_low );
+ t->set_color("font_color_disabled", "TabContainer", control_font_color_disabled);
t->set_constant("side_margin","TabContainer", 8 *scale);
t->set_constant("top_margin","TabContainer", 24 *scale);
@@ -776,6 +773,7 @@ void fill_default_theme(Ref<Theme>& t, const Ref<Font> & default_font, const Ref
t->set_stylebox("tab_fg","Tabs", sb_expand( make_stylebox( tab_current_png,4,3,4,1,16,3,16,2),2,2,2,2) );
t->set_stylebox("tab_bg","Tabs", sb_expand( make_stylebox( tab_behind_png,5,4,5,1,16,5,16,2),3,3,3,3) );
+ t->set_stylebox("tab_disabled", "Tabs", sb_expand(make_stylebox(tab_disabled_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3));
t->set_stylebox("panel","Tabs",tc_sb );
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) );
@@ -790,6 +788,7 @@ void fill_default_theme(Ref<Theme>& t, const Ref<Font> & default_font, const Ref
t->set_color("font_color_fg","Tabs", control_font_color_hover );
t->set_color("font_color_bg","Tabs", control_font_color_low );
+ t->set_color("font_color_disabled", "Tabs", control_font_color_disabled);
t->set_constant("top_margin","Tabs", 24 *scale);
t->set_constant("label_valign_fg","Tabs", 0 *scale);
@@ -982,7 +981,7 @@ void make_default_theme(bool p_hidpi,Ref<Font> p_font) {
Ref<BitmapFont> default_font;
if (p_font.is_valid()) {
default_font=p_font;
- } if (p_hidpi) {
+ } else if (p_hidpi) {
default_font=make_font2(_hidpi_font_height,_hidpi_font_ascent,_hidpi_font_charcount,&_hidpi_font_charrects[0][0],_hidpi_font_kerning_pair_count,&_hidpi_font_kerning_pairs[0][0],_hidpi_font_img_width,_hidpi_font_img_height,_hidpi_font_img_data);
} else {
default_font=make_font2(_lodpi_font_height,_lodpi_font_ascent,_lodpi_font_charcount,&_lodpi_font_charrects[0][0],_lodpi_font_kerning_pair_count,&_lodpi_font_kerning_pairs[0][0],_lodpi_font_img_width,_lodpi_font_img_height,_lodpi_font_img_data);
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index 5b5868ba14..394cfaf424 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -458,6 +458,10 @@ static const unsigned char tab_current_png[]={
0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x3,0x0,0x0,0x0,0x28,0x2d,0xf,0x53,0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0,0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa,0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a,0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x9c,0x50,0x4c,0x54,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0x3d,0x48,0x5b,0x58,0x66,0x5b,0x57,0x65,0x57,0x54,0x62,0x55,0x53,0x62,0x4a,0x46,0x52,0x46,0x41,0x4e,0x45,0x41,0x4d,0x55,0x52,0x60,0x44,0x41,0x4c,0x53,0x50,0x5e,0x43,0x40,0x4b,0x52,0x4e,0x5d,0x41,0x3e,0x4a,0x4f,0x4d,0x5a,0x3f,0x3d,0x48,0x4e,0x4b,0x59,0x3e,0x3c,0x47,0x4d,0x4a,0x58,0x3d,0x3b,0x46,0x4b,0x49,0x54,0x3c,0x3a,0x44,0x4b,0x47,0x54,0x3b,0x39,0x43,0x3b,0x39,0x42,0x3b,0x38,0x43,0x3b,0x38,0x42,0x3a,0x37,0x41,0x39,0x37,0x41,0x3a,0x38,0x41,0x39,0x36,0x3f,0x38,0x36,0x3f,0x39,0x36,0x40,0x38,0x36,0x40,0x37,0x35,0x3e,0x37,0x34,0x3e,0x36,0x35,0x3d,0x35,0x32,0x3b,0x59,0xdd,0xd3,0xff,0x0,0x0,0x0,0x11,0x74,0x52,0x4e,0x53,0x4,0xa,0x11,0x19,0x1f,0x22,0x24,0x15,0x25,0x34,0x3f,0x46,0x47,0x48,0x77,0xef,0xef,0xa3,0x31,0x6b,0xc2,0x0,0x0,0x0,0x1,0x62,0x4b,0x47,0x44,0x33,0x37,0xd5,0x7c,0x5e,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,0xe0,0x6,0x16,0x12,0x2b,0x5,0x39,0x1a,0x32,0x39,0x0,0x0,0x0,0xa2,0x49,0x44,0x41,0x54,0x18,0xd3,0x45,0xcd,0xd9,0x12,0x82,0x30,0xc,0x40,0xd1,0x0,0x2d,0x4b,0x5b,0x36,0x59,0x44,0x44,0x44,0xa4,0x68,0x59,0x54,0xfc,0xff,0x8f,0x33,0x30,0x4c,0x3d,0x93,0xa7,0x3b,0x93,0x4,0xc0,0x30,0x2d,0x42,0x6d,0x44,0x89,0x65,0x1a,0x0,0x86,0xe3,0x7a,0x8c,0xb,0xdf,0x17,0x9c,0x79,0xae,0x63,0x80,0xe9,0x6,0x61,0x7c,0xd8,0xc4,0x61,0xe0,0x9a,0x60,0x79,0x51,0x92,0x66,0x9b,0x34,0x89,0x3c,0xb,0x8,0xcb,0xb3,0xe3,0x2e,0xcb,0x19,0x1,0xca,0x8b,0x93,0x56,0x70,0xa,0xb6,0x28,0xcf,0x5a,0x29,0x6c,0xb0,0xfd,0xea,0xa2,0x55,0xfe,0x1a,0xea,0xab,0x56,0xaf,0x41,0x34,0x37,0xad,0xc1,0x15,0xca,0xdb,0xbb,0xd6,0xe2,0x51,0xc2,0xba,0x7f,0xe8,0xf0,0x2d,0x6,0x29,0xfb,0x5e,0xca,0xc7,0x53,0xca,0x3d,0xa8,0x61,0x50,0xc3,0xa8,0xc6,0x41,0xed,0x61,0x9a,0xa6,0x19,0xbd,0xe6,0xf7,0x1e,0x3e,0xcb,0x82,0x83,0xbe,0x18,0x7e,0xa1,0xe5,0x17,0x1f,0xcf,0x5d,0x82,0x6b,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x63,0x72,0x65,0x61,0x74,0x65,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xc9,0xad,0xc8,0x52,0x0,0x0,0x0,0x25,0x74,0x45,0x58,0x74,0x64,0x61,0x74,0x65,0x3a,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0,0x32,0x30,0x31,0x36,0x2d,0x30,0x36,0x2d,0x32,0x32,0x54,0x32,0x30,0x3a,0x33,0x39,0x3a,0x32,0x36,0x2b,0x30,0x32,0x3a,0x30,0x30,0xb8,0xf0,0x70,0xee,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
+static const unsigned char tab_disabled_png[] = {
+0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x8,0x6,0x0,0x0,0x0,0x1f,0xf3,0xff,0x61,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x12,0x0,0x0,0xb,0x12,0x1,0xd2,0xdd,0x7e,0xfc,0x0,0x0,0x0,0xd2,0x49,0x44,0x41,0x54,0x38,0xcb,0xd5,0x90,0x51,0xa,0xc2,0x30,0xc,0x86,0xd3,0x2e,0xdb,0x4,0x1f,0xb6,0x57,0x75,0x77,0xd9,0x1d,0x3c,0x8d,0x47,0xd8,0x69,0xbc,0x81,0xf,0xbb,0xcb,0xf0,0x6d,0xa8,0xa0,0xa0,0x6b,0xd7,0x9a,0x40,0x26,0xa,0xdb,0x98,0x22,0x88,0x81,0xf,0x92,0xf2,0xe7,0x4f,0x13,0x5,0x0,0x48,0x44,0x44,0x4c,0xcc,0x24,0xf,0x8,0xd,0xaf,0xe1,0x88,0x96,0x68,0x88,0x2b,0x71,0xe3,0xbc,0x6b,0x9e,0x13,0x29,0x91,0x48,0xce,0x66,0x4a,0xe0,0xf0,0x2,0x37,0x5d,0x88,0x13,0x71,0x4,0x99,0xce,0xe2,0x34,0xcf,0xf3,0x75,0xb6,0xcc,0xa,0xd3,0x1a,0x18,0x8b,0x30,0x8,0xa1,0xda,0x57,0x9b,0xb2,0x2c,0xb7,0x54,0x5a,0x94,0x6f,0x27,0xab,0xc5,0xaa,0xa8,0xf,0x35,0x58,0x6b,0xc1,0x7b,0xdf,0xdb,0xac,0x94,0x2,0x44,0x4,0xd6,0x52,0xb9,0x23,0xce,0x8f,0x15,0x1a,0xdb,0x80,0x31,0xe3,0xd3,0xd9,0x98,0x35,0xac,0x95,0x55,0x23,0x2d,0x7,0x8b,0x87,0xa6,0xe,0x19,0xc9,0xea,0x1,0xca,0xb5,0x15,0x3f,0x4e,0x35,0x11,0x1d,0x1f,0x58,0x63,0xb7,0xde,0x87,0x6,0x80,0xcf,0x8f,0x6f,0x1a,0xc0,0x77,0xd,0x9c,0x73,0x93,0xd,0x58,0xdb,0x85,0xee,0x73,0xfd,0xcd,0xa,0xff,0x6b,0x70,0x7,0xd6,0xd5,0x90,0x3b,0x10,0xe9,0x51,0x80,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
+};
+
static const unsigned char tab_menu_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,0x6f,0x49,0x44,0x41,0x54,0x38,0x8d,0x63,0x60,0x18,0x5,0xa3,0x80,0x81,0x81,0x11,0x5d,0xe0,0xc1,0x83,0x7,0xff,0xf1,0x69,0x50,0x50,0x50,0x40,0xd1,0xc3,0x44,0xa9,0xb,0xa8,0x6f,0x0,0x23,0x23,0x63,0x3c,0x3,0x3,0xc3,0x57,0x2c,0x6a,0xbf,0x33,0x32,0x32,0xa6,0x63,0xa8,0xc7,0x66,0xea,0xfd,0xfb,0xf7,0x35,0x18,0x18,0x18,0x56,0x31,0x32,0x32,0xea,0x42,0x85,0x6e,0x30,0x33,0x33,0x87,0xc9,0xca,0xca,0x5e,0x26,0xca,0x0,0x6,0x6,0x6,0x86,0x17,0x2f,0x5e,0x70,0xff,0xfc,0xf9,0x73,0xa,0x3,0x3,0x3,0x3,0x3b,0x3b,0x7b,0x8e,0x84,0x84,0x4,0x36,0x57,0xd,0x2,0x0,0x0,0x67,0xf2,0x14,0xc2,0xc2,0xbe,0xf5,0xb5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index ba4b12900f..02149f5748 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -84,10 +84,10 @@ void DynamicFontData::set_force_autohinter(bool p_force) {
}
void DynamicFontData::_bind_methods() {
- ClassDB::bind_method(_MD("set_font_path","path"),&DynamicFontData::set_font_path);
- ClassDB::bind_method(_MD("get_font_path"),&DynamicFontData::get_font_path);
+ ClassDB::bind_method(D_METHOD("set_font_path","path"),&DynamicFontData::set_font_path);
+ ClassDB::bind_method(D_METHOD("get_font_path"),&DynamicFontData::get_font_path);
- ADD_PROPERTY(PropertyInfo(Variant::STRING,"font_path",PROPERTY_HINT_FILE,"*.ttf,*.otf"),_SCS("set_font_path"),_SCS("get_font_path"));
+ ADD_PROPERTY(PropertyInfo(Variant::STRING,"font_path",PROPERTY_HINT_FILE,"*.ttf,*.otf"),"set_font_path","get_font_path");
}
DynamicFontData::DynamicFontData()
@@ -879,37 +879,37 @@ void DynamicFont::_get_property_list( List<PropertyInfo> *p_list) const{
void DynamicFont::_bind_methods() {
- ClassDB::bind_method(_MD("set_font_data","data:DynamicFontData"),&DynamicFont::set_font_data);
- ClassDB::bind_method(_MD("get_font_data:DynamicFontData"),&DynamicFont::get_font_data);
+ ClassDB::bind_method(D_METHOD("set_font_data","data:DynamicFontData"),&DynamicFont::set_font_data);
+ ClassDB::bind_method(D_METHOD("get_font_data:DynamicFontData"),&DynamicFont::get_font_data);
- ClassDB::bind_method(_MD("set_size","data"),&DynamicFont::set_size);
- ClassDB::bind_method(_MD("get_size"),&DynamicFont::get_size);
+ ClassDB::bind_method(D_METHOD("set_size","data"),&DynamicFont::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"),&DynamicFont::get_size);
- ClassDB::bind_method(_MD("set_use_mipmaps","enable"),&DynamicFont::set_use_mipmaps);
- ClassDB::bind_method(_MD("get_use_mipmaps"),&DynamicFont::get_use_mipmaps);
- ClassDB::bind_method(_MD("set_use_filter","enable"),&DynamicFont::set_use_filter);
- ClassDB::bind_method(_MD("get_use_filter"),&DynamicFont::get_use_filter);
- ClassDB::bind_method(_MD("set_spacing","type","value"),&DynamicFont::set_spacing);
- ClassDB::bind_method(_MD("get_spacing","type"),&DynamicFont::get_spacing);
+ ClassDB::bind_method(D_METHOD("set_use_mipmaps","enable"),&DynamicFont::set_use_mipmaps);
+ ClassDB::bind_method(D_METHOD("get_use_mipmaps"),&DynamicFont::get_use_mipmaps);
+ ClassDB::bind_method(D_METHOD("set_use_filter","enable"),&DynamicFont::set_use_filter);
+ ClassDB::bind_method(D_METHOD("get_use_filter"),&DynamicFont::get_use_filter);
+ ClassDB::bind_method(D_METHOD("set_spacing","type","value"),&DynamicFont::set_spacing);
+ ClassDB::bind_method(D_METHOD("get_spacing","type"),&DynamicFont::get_spacing);
- ClassDB::bind_method(_MD("add_fallback","data:DynamicFontData"),&DynamicFont::add_fallback);
- ClassDB::bind_method(_MD("set_fallback","idx","data:DynamicFontData"),&DynamicFont::set_fallback);
- ClassDB::bind_method(_MD("get_fallback:DynamicFontData","idx"),&DynamicFont::get_fallback);
- ClassDB::bind_method(_MD("remove_fallback","idx"),&DynamicFont::remove_fallback);
- ClassDB::bind_method(_MD("get_fallback_count"),&DynamicFont::get_fallback_count);
+ ClassDB::bind_method(D_METHOD("add_fallback","data:DynamicFontData"),&DynamicFont::add_fallback);
+ ClassDB::bind_method(D_METHOD("set_fallback","idx","data:DynamicFontData"),&DynamicFont::set_fallback);
+ ClassDB::bind_method(D_METHOD("get_fallback:DynamicFontData","idx"),&DynamicFont::get_fallback);
+ ClassDB::bind_method(D_METHOD("remove_fallback","idx"),&DynamicFont::remove_fallback);
+ ClassDB::bind_method(D_METHOD("get_fallback_count"),&DynamicFont::get_fallback_count);
ADD_GROUP("Settings","");
- ADD_PROPERTY(PropertyInfo(Variant::INT,"size"),_SCS("set_size"),_SCS("get_size"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_mipmaps"),_SCS("set_use_mipmaps"),_SCS("get_use_mipmaps"));
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_filter"),_SCS("set_use_filter"),_SCS("get_use_filter"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"size"),"set_size","get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_mipmaps"),"set_use_mipmaps","get_use_mipmaps");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_filter"),"set_use_filter","get_use_filter");
ADD_GROUP("Extra Spacing","extra_spacing");
- ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_top"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_TOP);
- ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_bottom"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_BOTTOM);
- ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_char"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_CHAR);
- ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_space"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_SPACE);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_top"),"set_spacing","get_spacing",SPACING_TOP);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_bottom"),"set_spacing","get_spacing",SPACING_BOTTOM);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_char"),"set_spacing","get_spacing",SPACING_CHAR);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing_space"),"set_spacing","get_spacing",SPACING_SPACE);
ADD_GROUP("Font","");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font_data",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),_SCS("set_font_data"),_SCS("get_font_data"));
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font_data",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),"set_font_data","get_font_data");
BIND_CONSTANT( SPACING_TOP );
BIND_CONSTANT( SPACING_BOTTOM );
diff --git a/scene/resources/dynamic_font_stb.cpp b/scene/resources/dynamic_font_stb.cpp
index cbbca49f0f..2d659a7e97 100644
--- a/scene/resources/dynamic_font_stb.cpp
+++ b/scene/resources/dynamic_font_stb.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* dynamic_font_stb.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "dynamic_font_stb.h"
#ifndef FREETYPE_ENABLED
@@ -378,14 +406,14 @@ DynamicFontAtSize::~DynamicFontAtSize(){
void DynamicFont::_bind_methods() {
- ClassDB::bind_method(_MD("set_font_data","data:DynamicFontData"),&DynamicFont::set_font_data);
- ClassDB::bind_method(_MD("get_font_data:DynamicFontData"),&DynamicFont::get_font_data);
+ ClassDB::bind_method(D_METHOD("set_font_data","data:DynamicFontData"),&DynamicFont::set_font_data);
+ ClassDB::bind_method(D_METHOD("get_font_data:DynamicFontData"),&DynamicFont::get_font_data);
- ClassDB::bind_method(_MD("set_size","data"),&DynamicFont::set_size);
- ClassDB::bind_method(_MD("get_size"),&DynamicFont::get_size);
+ ClassDB::bind_method(D_METHOD("set_size","data"),&DynamicFont::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"),&DynamicFont::get_size);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"font/size"),_SCS("set_size"),_SCS("get_size"));
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font/font",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),_SCS("set_font_data"),_SCS("get_font_data"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"font/size"),"set_size","get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font/font",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),"set_font_data","get_font_data");
}
diff --git a/scene/resources/dynamic_font_stb.h b/scene/resources/dynamic_font_stb.h
index 07a3e5ee6c..4eb0575d8e 100644
--- a/scene/resources/dynamic_font_stb.h
+++ b/scene/resources/dynamic_font_stb.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* dynamic_font_stb.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 DYNAMICFONT_STB_H
#define DYNAMICFONT_STB_H
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index ffc0a38fc2..f44b37f6f5 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "environment.h"
#include "texture.h"
-#include "globals.h"
+#include "global_config.h"
#include "servers/visual_server.h"
RID Environment::get_rid() const {
@@ -701,257 +701,257 @@ Environment::DOFBlurQuality Environment::get_dof_blur_near_quality() const {
void Environment::_bind_methods() {
- ClassDB::bind_method(_MD("set_background","mode"),&Environment::set_background);
- ClassDB::bind_method(_MD("set_skybox","skybox:CubeMap"),&Environment::set_skybox);
- ClassDB::bind_method(_MD("set_skybox_scale","scale"),&Environment::set_skybox_scale);
- ClassDB::bind_method(_MD("set_bg_color","color"),&Environment::set_bg_color);
- ClassDB::bind_method(_MD("set_bg_energy","energy"),&Environment::set_bg_energy);
- ClassDB::bind_method(_MD("set_canvas_max_layer","layer"),&Environment::set_canvas_max_layer);
- ClassDB::bind_method(_MD("set_ambient_light_color","color"),&Environment::set_ambient_light_color);
- ClassDB::bind_method(_MD("set_ambient_light_energy","energy"),&Environment::set_ambient_light_energy);
- ClassDB::bind_method(_MD("set_ambient_light_skybox_contribution","energy"),&Environment::set_ambient_light_skybox_contribution);
+ ClassDB::bind_method(D_METHOD("set_background","mode"),&Environment::set_background);
+ ClassDB::bind_method(D_METHOD("set_skybox","skybox:CubeMap"),&Environment::set_skybox);
+ ClassDB::bind_method(D_METHOD("set_skybox_scale","scale"),&Environment::set_skybox_scale);
+ ClassDB::bind_method(D_METHOD("set_bg_color","color"),&Environment::set_bg_color);
+ ClassDB::bind_method(D_METHOD("set_bg_energy","energy"),&Environment::set_bg_energy);
+ ClassDB::bind_method(D_METHOD("set_canvas_max_layer","layer"),&Environment::set_canvas_max_layer);
+ ClassDB::bind_method(D_METHOD("set_ambient_light_color","color"),&Environment::set_ambient_light_color);
+ ClassDB::bind_method(D_METHOD("set_ambient_light_energy","energy"),&Environment::set_ambient_light_energy);
+ ClassDB::bind_method(D_METHOD("set_ambient_light_skybox_contribution","energy"),&Environment::set_ambient_light_skybox_contribution);
- ClassDB::bind_method(_MD("get_background"),&Environment::get_background);
- ClassDB::bind_method(_MD("get_skybox:CubeMap"),&Environment::get_skybox);
- ClassDB::bind_method(_MD("get_skybox_scale"),&Environment::get_skybox_scale);
- ClassDB::bind_method(_MD("get_bg_color"),&Environment::get_bg_color);
- ClassDB::bind_method(_MD("get_bg_energy"),&Environment::get_bg_energy);
- ClassDB::bind_method(_MD("get_canvas_max_layer"),&Environment::get_canvas_max_layer);
- ClassDB::bind_method(_MD("get_ambient_light_color"),&Environment::get_ambient_light_color);
- ClassDB::bind_method(_MD("get_ambient_light_energy"),&Environment::get_ambient_light_energy);
- ClassDB::bind_method(_MD("get_ambient_light_skybox_contribution"),&Environment::get_ambient_light_skybox_contribution);
+ ClassDB::bind_method(D_METHOD("get_background"),&Environment::get_background);
+ ClassDB::bind_method(D_METHOD("get_skybox:CubeMap"),&Environment::get_skybox);
+ ClassDB::bind_method(D_METHOD("get_skybox_scale"),&Environment::get_skybox_scale);
+ ClassDB::bind_method(D_METHOD("get_bg_color"),&Environment::get_bg_color);
+ ClassDB::bind_method(D_METHOD("get_bg_energy"),&Environment::get_bg_energy);
+ ClassDB::bind_method(D_METHOD("get_canvas_max_layer"),&Environment::get_canvas_max_layer);
+ ClassDB::bind_method(D_METHOD("get_ambient_light_color"),&Environment::get_ambient_light_color);
+ ClassDB::bind_method(D_METHOD("get_ambient_light_energy"),&Environment::get_ambient_light_energy);
+ ClassDB::bind_method(D_METHOD("get_ambient_light_skybox_contribution"),&Environment::get_ambient_light_skybox_contribution);
ADD_GROUP("Background","background_");
- ADD_PROPERTY(PropertyInfo(Variant::INT,"background_mode",PROPERTY_HINT_ENUM,"Clear Color,Custom Color,Skybox,Canvas,Keep"),_SCS("set_background"),_SCS("get_background") );
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"background_skybox",PROPERTY_HINT_RESOURCE_TYPE,"SkyBox"),_SCS("set_skybox"),_SCS("get_skybox") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"background_skybox_scale",PROPERTY_HINT_RANGE,"0,32,0.01"),_SCS("set_skybox_scale"),_SCS("get_skybox_scale") );
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"background_color"),_SCS("set_bg_color"),_SCS("get_bg_color") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"background_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_bg_energy"),_SCS("get_bg_energy") );
- ADD_PROPERTY(PropertyInfo(Variant::INT,"background_canvas_max_layer",PROPERTY_HINT_RANGE,"-1000,1000,1"),_SCS("set_canvas_max_layer"),_SCS("get_canvas_max_layer") );
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"background_mode",PROPERTY_HINT_ENUM,"Clear Color,Custom Color,Skybox,Canvas,Keep"),"set_background","get_background") ;
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"background_skybox",PROPERTY_HINT_RESOURCE_TYPE,"SkyBox"),"set_skybox","get_skybox") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"background_skybox_scale",PROPERTY_HINT_RANGE,"0,32,0.01"),"set_skybox_scale","get_skybox_scale") ;
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"background_color"),"set_bg_color","get_bg_color") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"background_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_bg_energy","get_bg_energy") ;
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"background_canvas_max_layer",PROPERTY_HINT_RANGE,"-1000,1000,1"),"set_canvas_max_layer","get_canvas_max_layer") ;
ADD_GROUP("Ambient Light","ambient_light_");
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"ambient_light_color"),_SCS("set_ambient_light_color"),_SCS("get_ambient_light_color") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_ambient_light_energy"),_SCS("get_ambient_light_energy") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light_skybox_contribution",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_ambient_light_skybox_contribution"),_SCS("get_ambient_light_skybox_contribution") );
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"ambient_light_color"),"set_ambient_light_color","get_ambient_light_color") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_ambient_light_energy","get_ambient_light_energy") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light_skybox_contribution",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_ambient_light_skybox_contribution","get_ambient_light_skybox_contribution") ;
- ClassDB::bind_method(_MD("set_ssr_enabled","enabled"),&Environment::set_ssr_enabled);
- ClassDB::bind_method(_MD("is_ssr_enabled"),&Environment::is_ssr_enabled);
+ ClassDB::bind_method(D_METHOD("set_ssr_enabled","enabled"),&Environment::set_ssr_enabled);
+ ClassDB::bind_method(D_METHOD("is_ssr_enabled"),&Environment::is_ssr_enabled);
- ClassDB::bind_method(_MD("set_ssr_max_steps","max_steps"),&Environment::set_ssr_max_steps);
- ClassDB::bind_method(_MD("get_ssr_max_steps"),&Environment::get_ssr_max_steps);
+ ClassDB::bind_method(D_METHOD("set_ssr_max_steps","max_steps"),&Environment::set_ssr_max_steps);
+ ClassDB::bind_method(D_METHOD("get_ssr_max_steps"),&Environment::get_ssr_max_steps);
- ClassDB::bind_method(_MD("set_ssr_accel","accel"),&Environment::set_ssr_accel);
- ClassDB::bind_method(_MD("get_ssr_accel"),&Environment::get_ssr_accel);
+ ClassDB::bind_method(D_METHOD("set_ssr_accel","accel"),&Environment::set_ssr_accel);
+ ClassDB::bind_method(D_METHOD("get_ssr_accel"),&Environment::get_ssr_accel);
- ClassDB::bind_method(_MD("set_ssr_fade","fade"),&Environment::set_ssr_fade);
- ClassDB::bind_method(_MD("get_ssr_fade"),&Environment::get_ssr_fade);
+ ClassDB::bind_method(D_METHOD("set_ssr_fade","fade"),&Environment::set_ssr_fade);
+ ClassDB::bind_method(D_METHOD("get_ssr_fade"),&Environment::get_ssr_fade);
- ClassDB::bind_method(_MD("set_ssr_depth_tolerance","depth_tolerance"),&Environment::set_ssr_depth_tolerance);
- ClassDB::bind_method(_MD("get_ssr_depth_tolerance"),&Environment::get_ssr_depth_tolerance);
+ ClassDB::bind_method(D_METHOD("set_ssr_depth_tolerance","depth_tolerance"),&Environment::set_ssr_depth_tolerance);
+ ClassDB::bind_method(D_METHOD("get_ssr_depth_tolerance"),&Environment::get_ssr_depth_tolerance);
- ClassDB::bind_method(_MD("set_ssr_smooth","smooth"),&Environment::set_ssr_smooth);
- ClassDB::bind_method(_MD("is_ssr_smooth"),&Environment::is_ssr_smooth);
+ ClassDB::bind_method(D_METHOD("set_ssr_smooth","smooth"),&Environment::set_ssr_smooth);
+ ClassDB::bind_method(D_METHOD("is_ssr_smooth"),&Environment::is_ssr_smooth);
- ClassDB::bind_method(_MD("set_ssr_rough","rough"),&Environment::set_ssr_rough);
- ClassDB::bind_method(_MD("is_ssr_rough"),&Environment::is_ssr_rough);
+ ClassDB::bind_method(D_METHOD("set_ssr_rough","rough"),&Environment::set_ssr_rough);
+ ClassDB::bind_method(D_METHOD("is_ssr_rough"),&Environment::is_ssr_rough);
ADD_GROUP("SS Reflections","ss_reflections_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections_enabled"),_SCS("set_ssr_enabled"),_SCS("is_ssr_enabled") );
- ADD_PROPERTY(PropertyInfo(Variant::INT,"ss_reflections_max_steps",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_ssr_max_steps"),_SCS("get_ssr_max_steps") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections_accel",PROPERTY_HINT_RANGE,"0,4,0.01"),_SCS("set_ssr_accel"),_SCS("get_ssr_accel") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections_fade",PROPERTY_HINT_EXP_EASING),_SCS("set_ssr_fade"),_SCS("get_ssr_fade") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections_depth_tolerance",PROPERTY_HINT_RANGE,"0.1,128,0.1"),_SCS("set_ssr_depth_tolerance"),_SCS("get_ssr_depth_tolerance") );
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections_accel_smooth"),_SCS("set_ssr_smooth"),_SCS("is_ssr_smooth") );
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections_roughness"),_SCS("set_ssr_rough"),_SCS("is_ssr_rough") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections_enabled"),"set_ssr_enabled","is_ssr_enabled") ;
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"ss_reflections_max_steps",PROPERTY_HINT_RANGE,"1,512,1"),"set_ssr_max_steps","get_ssr_max_steps") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections_accel",PROPERTY_HINT_RANGE,"0,4,0.01"),"set_ssr_accel","get_ssr_accel") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections_fade",PROPERTY_HINT_EXP_EASING),"set_ssr_fade","get_ssr_fade") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections_depth_tolerance",PROPERTY_HINT_RANGE,"0.1,128,0.1"),"set_ssr_depth_tolerance","get_ssr_depth_tolerance") ;
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections_accel_smooth"),"set_ssr_smooth","is_ssr_smooth") ;
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections_roughness"),"set_ssr_rough","is_ssr_rough") ;
- ClassDB::bind_method(_MD("set_ssao_enabled","enabled"),&Environment::set_ssao_enabled);
- ClassDB::bind_method(_MD("is_ssao_enabled"),&Environment::is_ssao_enabled);
+ ClassDB::bind_method(D_METHOD("set_ssao_enabled","enabled"),&Environment::set_ssao_enabled);
+ ClassDB::bind_method(D_METHOD("is_ssao_enabled"),&Environment::is_ssao_enabled);
- ClassDB::bind_method(_MD("set_ssao_radius","radius"),&Environment::set_ssao_radius);
- ClassDB::bind_method(_MD("get_ssao_radius"),&Environment::get_ssao_radius);
+ ClassDB::bind_method(D_METHOD("set_ssao_radius","radius"),&Environment::set_ssao_radius);
+ ClassDB::bind_method(D_METHOD("get_ssao_radius"),&Environment::get_ssao_radius);
- ClassDB::bind_method(_MD("set_ssao_intensity","intensity"),&Environment::set_ssao_intensity);
- ClassDB::bind_method(_MD("get_ssao_intensity"),&Environment::get_ssao_intensity);
+ ClassDB::bind_method(D_METHOD("set_ssao_intensity","intensity"),&Environment::set_ssao_intensity);
+ ClassDB::bind_method(D_METHOD("get_ssao_intensity"),&Environment::get_ssao_intensity);
- ClassDB::bind_method(_MD("set_ssao_radius2","radius"),&Environment::set_ssao_radius2);
- ClassDB::bind_method(_MD("get_ssao_radius2"),&Environment::get_ssao_radius2);
+ ClassDB::bind_method(D_METHOD("set_ssao_radius2","radius"),&Environment::set_ssao_radius2);
+ ClassDB::bind_method(D_METHOD("get_ssao_radius2"),&Environment::get_ssao_radius2);
- ClassDB::bind_method(_MD("set_ssao_intensity2","intensity"),&Environment::set_ssao_intensity2);
- ClassDB::bind_method(_MD("get_ssao_intensity2"),&Environment::get_ssao_intensity2);
+ ClassDB::bind_method(D_METHOD("set_ssao_intensity2","intensity"),&Environment::set_ssao_intensity2);
+ ClassDB::bind_method(D_METHOD("get_ssao_intensity2"),&Environment::get_ssao_intensity2);
- ClassDB::bind_method(_MD("set_ssao_bias","bias"),&Environment::set_ssao_bias);
- ClassDB::bind_method(_MD("get_ssao_bias"),&Environment::get_ssao_bias);
+ ClassDB::bind_method(D_METHOD("set_ssao_bias","bias"),&Environment::set_ssao_bias);
+ ClassDB::bind_method(D_METHOD("get_ssao_bias"),&Environment::get_ssao_bias);
- ClassDB::bind_method(_MD("set_ssao_direct_light_affect","amount"),&Environment::set_ssao_direct_light_affect);
- ClassDB::bind_method(_MD("get_ssao_direct_light_affect"),&Environment::get_ssao_direct_light_affect);
+ ClassDB::bind_method(D_METHOD("set_ssao_direct_light_affect","amount"),&Environment::set_ssao_direct_light_affect);
+ ClassDB::bind_method(D_METHOD("get_ssao_direct_light_affect"),&Environment::get_ssao_direct_light_affect);
- ClassDB::bind_method(_MD("set_ssao_color","color"),&Environment::set_ssao_color);
- ClassDB::bind_method(_MD("get_ssao_color"),&Environment::get_ssao_color);
+ ClassDB::bind_method(D_METHOD("set_ssao_color","color"),&Environment::set_ssao_color);
+ ClassDB::bind_method(D_METHOD("get_ssao_color"),&Environment::get_ssao_color);
- ClassDB::bind_method(_MD("set_ssao_blur","enabled"),&Environment::set_ssao_blur);
- ClassDB::bind_method(_MD("is_ssao_blur_enabled"),&Environment::is_ssao_blur_enabled);
+ ClassDB::bind_method(D_METHOD("set_ssao_blur","enabled"),&Environment::set_ssao_blur);
+ ClassDB::bind_method(D_METHOD("is_ssao_blur_enabled"),&Environment::is_ssao_blur_enabled);
ADD_GROUP("SSAO","ssao_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ssao_enabled"),_SCS("set_ssao_enabled"),_SCS("is_ssao_enabled") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_radius",PROPERTY_HINT_RANGE,"0.1,16,0.1"),_SCS("set_ssao_radius"),_SCS("get_ssao_radius") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_intensity",PROPERTY_HINT_RANGE,"0.0,9,0.1"),_SCS("set_ssao_intensity"),_SCS("get_ssao_intensity") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_radius2",PROPERTY_HINT_RANGE,"0.0,16,0.1"),_SCS("set_ssao_radius2"),_SCS("get_ssao_radius2") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_intensity2",PROPERTY_HINT_RANGE,"0.0,9,0.1"),_SCS("set_ssao_intensity2"),_SCS("get_ssao_intensity2") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_bias",PROPERTY_HINT_RANGE,"0.001,8,0.001"),_SCS("set_ssao_bias"),_SCS("get_ssao_bias") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_light_affect",PROPERTY_HINT_RANGE,"0.00,1,0.01"),_SCS("set_ssao_direct_light_affect"),_SCS("get_ssao_direct_light_affect") );
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"ssao_color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_ssao_color"),_SCS("get_ssao_color") );
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ssao_blur"),_SCS("set_ssao_blur"),_SCS("is_ssao_blur_enabled") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ssao_enabled"),"set_ssao_enabled","is_ssao_enabled") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_radius",PROPERTY_HINT_RANGE,"0.1,16,0.1"),"set_ssao_radius","get_ssao_radius") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_intensity",PROPERTY_HINT_RANGE,"0.0,9,0.1"),"set_ssao_intensity","get_ssao_intensity") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_radius2",PROPERTY_HINT_RANGE,"0.0,16,0.1"),"set_ssao_radius2","get_ssao_radius2") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_intensity2",PROPERTY_HINT_RANGE,"0.0,9,0.1"),"set_ssao_intensity2","get_ssao_intensity2") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_bias",PROPERTY_HINT_RANGE,"0.001,8,0.001"),"set_ssao_bias","get_ssao_bias") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ssao_light_affect",PROPERTY_HINT_RANGE,"0.00,1,0.01"),"set_ssao_direct_light_affect","get_ssao_direct_light_affect") ;
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"ssao_color",PROPERTY_HINT_COLOR_NO_ALPHA),"set_ssao_color","get_ssao_color") ;
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ssao_blur"),"set_ssao_blur","is_ssao_blur_enabled") ;
- ClassDB::bind_method(_MD("set_dof_blur_far_enabled","enabled"),&Environment::set_dof_blur_far_enabled);
- ClassDB::bind_method(_MD("is_dof_blur_far_enabled"),&Environment::is_dof_blur_far_enabled);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled","enabled"),&Environment::set_dof_blur_far_enabled);
+ ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"),&Environment::is_dof_blur_far_enabled);
- ClassDB::bind_method(_MD("set_dof_blur_far_distance","intensity"),&Environment::set_dof_blur_far_distance);
- ClassDB::bind_method(_MD("get_dof_blur_far_distance"),&Environment::get_dof_blur_far_distance);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance","intensity"),&Environment::set_dof_blur_far_distance);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"),&Environment::get_dof_blur_far_distance);
- ClassDB::bind_method(_MD("set_dof_blur_far_transition","intensity"),&Environment::set_dof_blur_far_transition);
- ClassDB::bind_method(_MD("get_dof_blur_far_transition"),&Environment::get_dof_blur_far_transition);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition","intensity"),&Environment::set_dof_blur_far_transition);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"),&Environment::get_dof_blur_far_transition);
- ClassDB::bind_method(_MD("set_dof_blur_far_amount","intensity"),&Environment::set_dof_blur_far_amount);
- ClassDB::bind_method(_MD("get_dof_blur_far_amount"),&Environment::get_dof_blur_far_amount);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_amount","intensity"),&Environment::set_dof_blur_far_amount);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_far_amount"),&Environment::get_dof_blur_far_amount);
- ClassDB::bind_method(_MD("set_dof_blur_far_quality","intensity"),&Environment::set_dof_blur_far_quality);
- ClassDB::bind_method(_MD("get_dof_blur_far_quality"),&Environment::get_dof_blur_far_quality);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_far_quality","intensity"),&Environment::set_dof_blur_far_quality);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_far_quality"),&Environment::get_dof_blur_far_quality);
- ClassDB::bind_method(_MD("set_dof_blur_near_enabled","enabled"),&Environment::set_dof_blur_near_enabled);
- ClassDB::bind_method(_MD("is_dof_blur_near_enabled"),&Environment::is_dof_blur_near_enabled);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled","enabled"),&Environment::set_dof_blur_near_enabled);
+ ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"),&Environment::is_dof_blur_near_enabled);
- ClassDB::bind_method(_MD("set_dof_blur_near_distance","intensity"),&Environment::set_dof_blur_near_distance);
- ClassDB::bind_method(_MD("get_dof_blur_near_distance"),&Environment::get_dof_blur_near_distance);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance","intensity"),&Environment::set_dof_blur_near_distance);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"),&Environment::get_dof_blur_near_distance);
- ClassDB::bind_method(_MD("set_dof_blur_near_transition","intensity"),&Environment::set_dof_blur_near_transition);
- ClassDB::bind_method(_MD("get_dof_blur_near_transition"),&Environment::get_dof_blur_near_transition);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition","intensity"),&Environment::set_dof_blur_near_transition);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"),&Environment::get_dof_blur_near_transition);
- ClassDB::bind_method(_MD("set_dof_blur_near_amount","intensity"),&Environment::set_dof_blur_near_amount);
- ClassDB::bind_method(_MD("get_dof_blur_near_amount"),&Environment::get_dof_blur_near_amount);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_amount","intensity"),&Environment::set_dof_blur_near_amount);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_near_amount"),&Environment::get_dof_blur_near_amount);
- ClassDB::bind_method(_MD("set_dof_blur_near_quality","level"),&Environment::set_dof_blur_near_quality);
- ClassDB::bind_method(_MD("get_dof_blur_near_quality"),&Environment::get_dof_blur_near_quality);
+ ClassDB::bind_method(D_METHOD("set_dof_blur_near_quality","level"),&Environment::set_dof_blur_near_quality);
+ ClassDB::bind_method(D_METHOD("get_dof_blur_near_quality"),&Environment::get_dof_blur_near_quality);
ADD_GROUP("DOF Far Blur","dof_blur_far_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"dof_blur_far_enabled"),_SCS("set_dof_blur_far_enabled"),_SCS("is_dof_blur_far_enabled") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far_distance",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_far_distance"),_SCS("get_dof_blur_far_distance") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far_transition",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_far_transition"),_SCS("get_dof_blur_far_transition") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dof_blur_far_amount"),_SCS("get_dof_blur_far_amount") );
- ADD_PROPERTY(PropertyInfo(Variant::INT,"dof_blur_far_quality",PROPERTY_HINT_ENUM,"Low,Medium,High"),_SCS("set_dof_blur_far_quality"),_SCS("get_dof_blur_far_quality") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"dof_blur_far_enabled"),"set_dof_blur_far_enabled","is_dof_blur_far_enabled") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far_distance",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),"set_dof_blur_far_distance","get_dof_blur_far_distance") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far_transition",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),"set_dof_blur_far_transition","get_dof_blur_far_transition") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dof_blur_far_amount","get_dof_blur_far_amount") ;
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"dof_blur_far_quality",PROPERTY_HINT_ENUM,"Low,Medium,High"),"set_dof_blur_far_quality","get_dof_blur_far_quality") ;
ADD_GROUP("DOF Far Near","dof_blur_near_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"dof_blur_near_enabled"),_SCS("set_dof_blur_near_enabled"),_SCS("is_dof_blur_near_enabled") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near_distance",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_near_distance"),_SCS("get_dof_blur_near_distance") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near_transition",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_near_transition"),_SCS("get_dof_blur_near_transition") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dof_blur_near_amount"),_SCS("get_dof_blur_near_amount") );
- ADD_PROPERTY(PropertyInfo(Variant::INT,"dof_blur_near_quality",PROPERTY_HINT_ENUM,"Low,Medium,High"),_SCS("set_dof_blur_near_quality"),_SCS("get_dof_blur_near_quality") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"dof_blur_near_enabled"),"set_dof_blur_near_enabled","is_dof_blur_near_enabled") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near_distance",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),"set_dof_blur_near_distance","get_dof_blur_near_distance") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near_transition",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),"set_dof_blur_near_transition","get_dof_blur_near_transition") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dof_blur_near_amount","get_dof_blur_near_amount") ;
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"dof_blur_near_quality",PROPERTY_HINT_ENUM,"Low,Medium,High"),"set_dof_blur_near_quality","get_dof_blur_near_quality") ;
- ClassDB::bind_method(_MD("set_glow_enabled","enabled"),&Environment::set_glow_enabled);
- ClassDB::bind_method(_MD("is_glow_enabled"),&Environment::is_glow_enabled);
+ ClassDB::bind_method(D_METHOD("set_glow_enabled","enabled"),&Environment::set_glow_enabled);
+ ClassDB::bind_method(D_METHOD("is_glow_enabled"),&Environment::is_glow_enabled);
- ClassDB::bind_method(_MD("set_glow_level","idx","enabled"),&Environment::set_glow_level);
- ClassDB::bind_method(_MD("is_glow_level_enabled","idx"),&Environment::is_glow_level_enabled);
+ ClassDB::bind_method(D_METHOD("set_glow_level","idx","enabled"),&Environment::set_glow_level);
+ ClassDB::bind_method(D_METHOD("is_glow_level_enabled","idx"),&Environment::is_glow_level_enabled);
- ClassDB::bind_method(_MD("set_glow_intensity","intensity"),&Environment::set_glow_intensity);
- ClassDB::bind_method(_MD("get_glow_intensity"),&Environment::get_glow_intensity);
+ ClassDB::bind_method(D_METHOD("set_glow_intensity","intensity"),&Environment::set_glow_intensity);
+ ClassDB::bind_method(D_METHOD("get_glow_intensity"),&Environment::get_glow_intensity);
- ClassDB::bind_method(_MD("set_glow_strength","strength"),&Environment::set_glow_strength);
- ClassDB::bind_method(_MD("get_glow_strength"),&Environment::get_glow_strength);
+ ClassDB::bind_method(D_METHOD("set_glow_strength","strength"),&Environment::set_glow_strength);
+ ClassDB::bind_method(D_METHOD("get_glow_strength"),&Environment::get_glow_strength);
- ClassDB::bind_method(_MD("set_glow_bloom","amount"),&Environment::set_glow_bloom);
- ClassDB::bind_method(_MD("get_glow_bloom"),&Environment::get_glow_bloom);
+ ClassDB::bind_method(D_METHOD("set_glow_bloom","amount"),&Environment::set_glow_bloom);
+ ClassDB::bind_method(D_METHOD("get_glow_bloom"),&Environment::get_glow_bloom);
- ClassDB::bind_method(_MD("set_glow_blend_mode","mode"),&Environment::set_glow_blend_mode);
- ClassDB::bind_method(_MD("get_glow_blend_mode"),&Environment::get_glow_blend_mode);
+ ClassDB::bind_method(D_METHOD("set_glow_blend_mode","mode"),&Environment::set_glow_blend_mode);
+ ClassDB::bind_method(D_METHOD("get_glow_blend_mode"),&Environment::get_glow_blend_mode);
- ClassDB::bind_method(_MD("set_glow_hdr_bleed_treshold","treshold"),&Environment::set_glow_hdr_bleed_treshold);
- ClassDB::bind_method(_MD("get_glow_hdr_bleed_treshold"),&Environment::get_glow_hdr_bleed_treshold);
+ ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_treshold","treshold"),&Environment::set_glow_hdr_bleed_treshold);
+ ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_treshold"),&Environment::get_glow_hdr_bleed_treshold);
- ClassDB::bind_method(_MD("set_glow_hdr_bleed_scale","scale"),&Environment::set_glow_hdr_bleed_scale);
- ClassDB::bind_method(_MD("get_glow_hdr_bleed_scale"),&Environment::get_glow_hdr_bleed_scale);
+ ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_scale","scale"),&Environment::set_glow_hdr_bleed_scale);
+ ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_scale"),&Environment::get_glow_hdr_bleed_scale);
- ClassDB::bind_method(_MD("set_glow_bicubic_upscale","enabled"),&Environment::set_glow_bicubic_upscale);
- ClassDB::bind_method(_MD("is_glow_bicubic_upscale_enabled"),&Environment::is_glow_bicubic_upscale_enabled);
+ ClassDB::bind_method(D_METHOD("set_glow_bicubic_upscale","enabled"),&Environment::set_glow_bicubic_upscale);
+ ClassDB::bind_method(D_METHOD("is_glow_bicubic_upscale_enabled"),&Environment::is_glow_bicubic_upscale_enabled);
ADD_GROUP("Glow","glow_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"glow_enabled"),_SCS("set_glow_enabled"),_SCS("is_glow_enabled") );
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/1"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),0 );
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/2"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),1 );
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/3"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),2 );
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/4"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),3 );
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/5"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),4 );
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/6"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),5 );
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/7"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),6 );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"glow_enabled"),"set_glow_enabled","is_glow_enabled") ;
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/1"),"set_glow_level","is_glow_level_enabled",0 );
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/2"),"set_glow_level","is_glow_level_enabled",1 );
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/3"),"set_glow_level","is_glow_level_enabled",2 );
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/4"),"set_glow_level","is_glow_level_enabled",3 );
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/5"),"set_glow_level","is_glow_level_enabled",4 );
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/6"),"set_glow_level","is_glow_level_enabled",5 );
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow_levels/7"),"set_glow_level","is_glow_level_enabled",6 );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_intensity",PROPERTY_HINT_RANGE,"0.0,8.0,0.01"),_SCS("set_glow_intensity"),_SCS("get_glow_intensity") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_strength",PROPERTY_HINT_RANGE,"0.0,2.0,0.01"),_SCS("set_glow_strength"),_SCS("get_glow_strength") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_bloom",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_glow_bloom"),_SCS("get_glow_bloom") );
- ADD_PROPERTY(PropertyInfo(Variant::INT,"glow_blend_mode",PROPERTY_HINT_ENUM,"Additive,Screen,Softlight,Replace"),_SCS("set_glow_blend_mode"),_SCS("get_glow_blend_mode") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_hdr_treshold",PROPERTY_HINT_RANGE,"0.0,4.0,0.01"),_SCS("set_glow_hdr_bleed_treshold"),_SCS("get_glow_hdr_bleed_treshold") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_hdr_scale",PROPERTY_HINT_RANGE,"0.0,4.0,0.01"),_SCS("set_glow_hdr_bleed_scale"),_SCS("get_glow_hdr_bleed_scale") );
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"glow_bicubic_upscale"),_SCS("set_glow_bicubic_upscale"),_SCS("is_glow_bicubic_upscale_enabled") );
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_intensity",PROPERTY_HINT_RANGE,"0.0,8.0,0.01"),"set_glow_intensity","get_glow_intensity") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_strength",PROPERTY_HINT_RANGE,"0.0,2.0,0.01"),"set_glow_strength","get_glow_strength") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_bloom",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),"set_glow_bloom","get_glow_bloom") ;
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"glow_blend_mode",PROPERTY_HINT_ENUM,"Additive,Screen,Softlight,Replace"),"set_glow_blend_mode","get_glow_blend_mode") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_hdr_treshold",PROPERTY_HINT_RANGE,"0.0,4.0,0.01"),"set_glow_hdr_bleed_treshold","get_glow_hdr_bleed_treshold") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow_hdr_scale",PROPERTY_HINT_RANGE,"0.0,4.0,0.01"),"set_glow_hdr_bleed_scale","get_glow_hdr_bleed_scale") ;
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"glow_bicubic_upscale"),"set_glow_bicubic_upscale","is_glow_bicubic_upscale_enabled") ;
- ClassDB::bind_method(_MD("set_tonemapper","mode"),&Environment::set_tonemapper);
- ClassDB::bind_method(_MD("get_tonemapper"),&Environment::get_tonemapper);
+ ClassDB::bind_method(D_METHOD("set_tonemapper","mode"),&Environment::set_tonemapper);
+ ClassDB::bind_method(D_METHOD("get_tonemapper"),&Environment::get_tonemapper);
- ClassDB::bind_method(_MD("set_tonemap_exposure","exposure"),&Environment::set_tonemap_exposure);
- ClassDB::bind_method(_MD("get_tonemap_exposure"),&Environment::get_tonemap_exposure);
+ ClassDB::bind_method(D_METHOD("set_tonemap_exposure","exposure"),&Environment::set_tonemap_exposure);
+ ClassDB::bind_method(D_METHOD("get_tonemap_exposure"),&Environment::get_tonemap_exposure);
- ClassDB::bind_method(_MD("set_tonemap_white","white"),&Environment::set_tonemap_white);
- ClassDB::bind_method(_MD("get_tonemap_white"),&Environment::get_tonemap_white);
+ ClassDB::bind_method(D_METHOD("set_tonemap_white","white"),&Environment::set_tonemap_white);
+ ClassDB::bind_method(D_METHOD("get_tonemap_white"),&Environment::get_tonemap_white);
- ClassDB::bind_method(_MD("set_tonemap_auto_exposure","auto_exposure"),&Environment::set_tonemap_auto_exposure);
- ClassDB::bind_method(_MD("get_tonemap_auto_exposure"),&Environment::get_tonemap_auto_exposure);
+ ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure","auto_exposure"),&Environment::set_tonemap_auto_exposure);
+ ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure"),&Environment::get_tonemap_auto_exposure);
- ClassDB::bind_method(_MD("set_tonemap_auto_exposure_max","exposure_max"),&Environment::set_tonemap_auto_exposure_max);
- ClassDB::bind_method(_MD("get_tonemap_auto_exposure_max"),&Environment::get_tonemap_auto_exposure_max);
+ ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_max","exposure_max"),&Environment::set_tonemap_auto_exposure_max);
+ ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_max"),&Environment::get_tonemap_auto_exposure_max);
- ClassDB::bind_method(_MD("set_tonemap_auto_exposure_min","exposure_min"),&Environment::set_tonemap_auto_exposure_min);
- ClassDB::bind_method(_MD("get_tonemap_auto_exposure_min"),&Environment::get_tonemap_auto_exposure_min);
+ ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_min","exposure_min"),&Environment::set_tonemap_auto_exposure_min);
+ ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_min"),&Environment::get_tonemap_auto_exposure_min);
- ClassDB::bind_method(_MD("set_tonemap_auto_exposure_speed","exposure_speed"),&Environment::set_tonemap_auto_exposure_speed);
- ClassDB::bind_method(_MD("get_tonemap_auto_exposure_speed"),&Environment::get_tonemap_auto_exposure_speed);
+ ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_speed","exposure_speed"),&Environment::set_tonemap_auto_exposure_speed);
+ ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_speed"),&Environment::get_tonemap_auto_exposure_speed);
- ClassDB::bind_method(_MD("set_tonemap_auto_exposure_grey","exposure_grey"),&Environment::set_tonemap_auto_exposure_grey);
- ClassDB::bind_method(_MD("get_tonemap_auto_exposure_grey"),&Environment::get_tonemap_auto_exposure_grey);
+ ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_grey","exposure_grey"),&Environment::set_tonemap_auto_exposure_grey);
+ ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_grey"),&Environment::get_tonemap_auto_exposure_grey);
ADD_GROUP("Tonemap","tonemap_");
- ADD_PROPERTY(PropertyInfo(Variant::INT,"tonemap_mode",PROPERTY_HINT_ENUM,"Linear,Reindhart,Filmic,Aces"),_SCS("set_tonemapper"),_SCS("get_tonemapper") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap_exposure",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_exposure"),_SCS("get_tonemap_exposure") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap_white",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_white"),_SCS("get_tonemap_white") );
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"tonemap_mode",PROPERTY_HINT_ENUM,"Linear,Reindhart,Filmic,Aces"),"set_tonemapper","get_tonemapper") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap_exposure",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_tonemap_exposure","get_tonemap_exposure") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap_white",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_tonemap_white","get_tonemap_white") ;
ADD_GROUP("Auto Exposure","auto_exposure_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"auto_expoure_enabled"),_SCS("set_tonemap_auto_exposure"),_SCS("get_tonemap_auto_exposure") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_tonemap_auto_exposure_grey"),_SCS("get_tonemap_auto_exposure_grey") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_min_luma",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_auto_exposure_min"),_SCS("get_tonemap_auto_exposure_min") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_max_luma",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_auto_exposure_max"),_SCS("get_tonemap_auto_exposure_max") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_speed",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_tonemap_auto_exposure_speed"),_SCS("get_tonemap_auto_exposure_speed") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"auto_expoure_enabled"),"set_tonemap_auto_exposure","get_tonemap_auto_exposure") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),"set_tonemap_auto_exposure_grey","get_tonemap_auto_exposure_grey") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_min_luma",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_tonemap_auto_exposure_min","get_tonemap_auto_exposure_min") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_max_luma",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_tonemap_auto_exposure_max","get_tonemap_auto_exposure_max") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_expoure_speed",PROPERTY_HINT_RANGE,"0.01,64,0.01"),"set_tonemap_auto_exposure_speed","get_tonemap_auto_exposure_speed") ;
- ClassDB::bind_method(_MD("set_adjustment_enable","enabled"),&Environment::set_adjustment_enable);
- ClassDB::bind_method(_MD("is_adjustment_enabled"),&Environment::is_adjustment_enabled);
+ ClassDB::bind_method(D_METHOD("set_adjustment_enable","enabled"),&Environment::set_adjustment_enable);
+ ClassDB::bind_method(D_METHOD("is_adjustment_enabled"),&Environment::is_adjustment_enabled);
- ClassDB::bind_method(_MD("set_adjustment_brightness","brightness"),&Environment::set_adjustment_brightness);
- ClassDB::bind_method(_MD("get_adjustment_brightness"),&Environment::get_adjustment_brightness);
+ ClassDB::bind_method(D_METHOD("set_adjustment_brightness","brightness"),&Environment::set_adjustment_brightness);
+ ClassDB::bind_method(D_METHOD("get_adjustment_brightness"),&Environment::get_adjustment_brightness);
- ClassDB::bind_method(_MD("set_adjustment_contrast","contrast"),&Environment::set_adjustment_contrast);
- ClassDB::bind_method(_MD("get_adjustment_contrast"),&Environment::get_adjustment_contrast);
+ ClassDB::bind_method(D_METHOD("set_adjustment_contrast","contrast"),&Environment::set_adjustment_contrast);
+ ClassDB::bind_method(D_METHOD("get_adjustment_contrast"),&Environment::get_adjustment_contrast);
- ClassDB::bind_method(_MD("set_adjustment_saturation","saturation"),&Environment::set_adjustment_saturation);
- ClassDB::bind_method(_MD("get_adjustment_saturation"),&Environment::get_adjustment_saturation);
+ ClassDB::bind_method(D_METHOD("set_adjustment_saturation","saturation"),&Environment::set_adjustment_saturation);
+ ClassDB::bind_method(D_METHOD("get_adjustment_saturation"),&Environment::get_adjustment_saturation);
- ClassDB::bind_method(_MD("set_adjustment_color_correction","color_correction"),&Environment::set_adjustment_color_correction);
- ClassDB::bind_method(_MD("get_adjustment_color_correction"),&Environment::get_adjustment_color_correction);
+ ClassDB::bind_method(D_METHOD("set_adjustment_color_correction","color_correction"),&Environment::set_adjustment_color_correction);
+ ClassDB::bind_method(D_METHOD("get_adjustment_color_correction"),&Environment::get_adjustment_color_correction);
ADD_GROUP("Adjustments","adjustment_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"adjustment_enabled"),_SCS("set_adjustment_enable"),_SCS("is_adjustment_enabled") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"adjustment_brightness",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("set_adjustment_brightness"),_SCS("get_adjustment_brightness") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"adjustment_contrast",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("set_adjustment_contrast"),_SCS("get_adjustment_contrast") );
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"adjustment_saturation",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("set_adjustment_saturation"),_SCS("get_adjustment_saturation") );
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"adjustment_color_correction",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_adjustment_color_correction"),_SCS("get_adjustment_color_correction") );
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"adjustment_enabled"),"set_adjustment_enable","is_adjustment_enabled") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"adjustment_brightness",PROPERTY_HINT_RANGE,"0.01,8,0.01"),"set_adjustment_brightness","get_adjustment_brightness") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"adjustment_contrast",PROPERTY_HINT_RANGE,"0.01,8,0.01"),"set_adjustment_contrast","get_adjustment_contrast") ;
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"adjustment_saturation",PROPERTY_HINT_RANGE,"0.01,8,0.01"),"set_adjustment_saturation","get_adjustment_saturation") ;
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"adjustment_color_correction",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_adjustment_color_correction","get_adjustment_color_correction") ;
GLOBAL_DEF("rendering/skybox/irradiance_cube_resolution",256);
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index b1d0611f48..d94e046b98 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -78,14 +78,14 @@ void Font::update_changes() {
void Font::_bind_methods() {
- ClassDB::bind_method(_MD("draw","canvas_item","pos","string","modulate","clip_w"),&Font::draw,DEFVAL(Color(1,1,1)),DEFVAL(-1));
- ClassDB::bind_method(_MD("get_ascent"),&Font::get_ascent);
- ClassDB::bind_method(_MD("get_descent"),&Font::get_descent);
- ClassDB::bind_method(_MD("get_height"),&Font::get_height);
- ClassDB::bind_method(_MD("is_distance_field_hint"),&Font::is_distance_field_hint);
- ClassDB::bind_method(_MD("get_string_size","string"),&Font::get_string_size);
- ClassDB::bind_method(_MD("draw_char","canvas_item","pos","char","next","modulate"),&Font::draw_char,DEFVAL(-1),DEFVAL(Color(1,1,1)));
- ClassDB::bind_method(_MD("update_changes"),&Font::update_changes);
+ ClassDB::bind_method(D_METHOD("draw","canvas_item","pos","string","modulate","clip_w"),&Font::draw,DEFVAL(Color(1,1,1)),DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_ascent"),&Font::get_ascent);
+ ClassDB::bind_method(D_METHOD("get_descent"),&Font::get_descent);
+ ClassDB::bind_method(D_METHOD("get_height"),&Font::get_height);
+ ClassDB::bind_method(D_METHOD("is_distance_field_hint"),&Font::is_distance_field_hint);
+ ClassDB::bind_method(D_METHOD("get_string_size","string"),&Font::get_string_size);
+ ClassDB::bind_method(D_METHOD("draw_char","canvas_item","pos","char","next","modulate"),&Font::draw_char,DEFVAL(-1),DEFVAL(Color(1,1,1)));
+ ClassDB::bind_method(D_METHOD("update_changes"),&Font::update_changes);
}
@@ -566,48 +566,48 @@ Size2 BitmapFont::get_char_size(CharType p_char,CharType p_next) const {
void BitmapFont::_bind_methods() {
- ClassDB::bind_method(_MD("create_from_fnt","path"),&BitmapFont::create_from_fnt);
- ClassDB::bind_method(_MD("set_height","px"),&BitmapFont::set_height);
+ ClassDB::bind_method(D_METHOD("create_from_fnt","path"),&BitmapFont::create_from_fnt);
+ ClassDB::bind_method(D_METHOD("set_height","px"),&BitmapFont::set_height);
- ClassDB::bind_method(_MD("set_ascent","px"),&BitmapFont::set_ascent);
+ ClassDB::bind_method(D_METHOD("set_ascent","px"),&BitmapFont::set_ascent);
- ClassDB::bind_method(_MD("add_kerning_pair","char_a","char_b","kerning"),&BitmapFont::add_kerning_pair);
- ClassDB::bind_method(_MD("get_kerning_pair","char_a","char_b"),&BitmapFont::get_kerning_pair);
+ ClassDB::bind_method(D_METHOD("add_kerning_pair","char_a","char_b","kerning"),&BitmapFont::add_kerning_pair);
+ ClassDB::bind_method(D_METHOD("get_kerning_pair","char_a","char_b"),&BitmapFont::get_kerning_pair);
- ClassDB::bind_method(_MD("add_texture","texture:Texture"),&BitmapFont::add_texture);
- ClassDB::bind_method(_MD("add_char","character","texture","rect","align","advance"),&BitmapFont::add_char,DEFVAL(Point2()),DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_texture","texture:Texture"),&BitmapFont::add_texture);
+ ClassDB::bind_method(D_METHOD("add_char","character","texture","rect","align","advance"),&BitmapFont::add_char,DEFVAL(Point2()),DEFVAL(-1));
- ClassDB::bind_method(_MD("get_texture_count"),&BitmapFont::get_texture_count);
- ClassDB::bind_method(_MD("get_texture:Texture","idx"),&BitmapFont::get_texture);
+ ClassDB::bind_method(D_METHOD("get_texture_count"),&BitmapFont::get_texture_count);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture","idx"),&BitmapFont::get_texture);
- ClassDB::bind_method(_MD("get_char_size","char","next"),&BitmapFont::get_char_size,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_char_size","char","next"),&BitmapFont::get_char_size,DEFVAL(0));
- ClassDB::bind_method(_MD("set_distance_field_hint","enable"),&BitmapFont::set_distance_field_hint);
+ ClassDB::bind_method(D_METHOD("set_distance_field_hint","enable"),&BitmapFont::set_distance_field_hint);
- ClassDB::bind_method(_MD("clear"),&BitmapFont::clear);
+ ClassDB::bind_method(D_METHOD("clear"),&BitmapFont::clear);
- ClassDB::bind_method(_MD("_set_chars"),&BitmapFont::_set_chars);
- ClassDB::bind_method(_MD("_get_chars"),&BitmapFont::_get_chars);
+ ClassDB::bind_method(D_METHOD("_set_chars"),&BitmapFont::_set_chars);
+ ClassDB::bind_method(D_METHOD("_get_chars"),&BitmapFont::_get_chars);
- ClassDB::bind_method(_MD("_set_kernings"),&BitmapFont::_set_kernings);
- ClassDB::bind_method(_MD("_get_kernings"),&BitmapFont::_get_kernings);
+ ClassDB::bind_method(D_METHOD("_set_kernings"),&BitmapFont::_set_kernings);
+ ClassDB::bind_method(D_METHOD("_get_kernings"),&BitmapFont::_get_kernings);
- ClassDB::bind_method(_MD("_set_textures"),&BitmapFont::_set_textures);
- ClassDB::bind_method(_MD("_get_textures"),&BitmapFont::_get_textures);
+ ClassDB::bind_method(D_METHOD("_set_textures"),&BitmapFont::_set_textures);
+ ClassDB::bind_method(D_METHOD("_get_textures"),&BitmapFont::_get_textures);
- ClassDB::bind_method(_MD("set_fallback","fallback"),&BitmapFont::set_fallback);
- ClassDB::bind_method(_MD("get_fallback"),&BitmapFont::get_fallback);
+ ClassDB::bind_method(D_METHOD("set_fallback","fallback"),&BitmapFont::set_fallback);
+ ClassDB::bind_method(D_METHOD("get_fallback"),&BitmapFont::get_fallback);
- ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "textures", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), _SCS("_set_textures"), _SCS("_get_textures") );
- ADD_PROPERTY( PropertyInfo( Variant::POOL_INT_ARRAY, "chars", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), _SCS("_set_chars"), _SCS("_get_chars") );
- ADD_PROPERTY( PropertyInfo( Variant::POOL_INT_ARRAY, "kernings", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), _SCS("_set_kernings"), _SCS("_get_kernings") );
+ ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "textures", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), "_set_textures", "_get_textures") ;
+ ADD_PROPERTY( PropertyInfo( Variant::POOL_INT_ARRAY, "chars", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), "_set_chars", "_get_chars") ;
+ ADD_PROPERTY( PropertyInfo( Variant::POOL_INT_ARRAY, "kernings", PROPERTY_HINT_NONE,"", PROPERTY_USAGE_NOEDITOR ), "_set_kernings", "_get_kernings") ;
- 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,"BitmapFont" ), _SCS("set_fallback"), _SCS("get_fallback") );
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "height", PROPERTY_HINT_RANGE,"-1024,1024,1" ), "set_height", "get_height") ;
+ ADD_PROPERTY( PropertyInfo( Variant::REAL, "ascent", PROPERTY_HINT_RANGE,"-1024,1024,1" ), "set_ascent", "get_ascent") ;
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "distance_field" ), "set_distance_field_hint", "is_distance_field_hint") ;
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "fallback", PROPERTY_HINT_RESOURCE_TYPE,"BitmapFont" ), "set_fallback", "get_fallback") ;
}
diff --git a/scene/resources/gibberish_stream.cpp b/scene/resources/gibberish_stream.cpp
index 3a6a6df7ea..fdc5bf01e8 100644
--- a/scene/resources/gibberish_stream.cpp
+++ b/scene/resources/gibberish_stream.cpp
@@ -305,22 +305,22 @@ float AudioStreamGibberish::get_pitch_random_scale() const {
void AudioStreamGibberish::_bind_methods() {
- ClassDB::bind_method(_MD("set_phonemes","phonemes"),&AudioStreamGibberish::set_phonemes);
- ClassDB::bind_method(_MD("get_phonemes"),&AudioStreamGibberish::get_phonemes);
+ ClassDB::bind_method(D_METHOD("set_phonemes","phonemes"),&AudioStreamGibberish::set_phonemes);
+ ClassDB::bind_method(D_METHOD("get_phonemes"),&AudioStreamGibberish::get_phonemes);
- ClassDB::bind_method(_MD("set_pitch_scale","pitch_scale"),&AudioStreamGibberish::set_pitch_scale);
- ClassDB::bind_method(_MD("get_pitch_scale"),&AudioStreamGibberish::get_pitch_scale);
+ ClassDB::bind_method(D_METHOD("set_pitch_scale","pitch_scale"),&AudioStreamGibberish::set_pitch_scale);
+ ClassDB::bind_method(D_METHOD("get_pitch_scale"),&AudioStreamGibberish::get_pitch_scale);
- ClassDB::bind_method(_MD("set_pitch_random_scale","pitch_random_scale"),&AudioStreamGibberish::set_pitch_random_scale);
- ClassDB::bind_method(_MD("get_pitch_random_scale"),&AudioStreamGibberish::get_pitch_random_scale);
+ ClassDB::bind_method(D_METHOD("set_pitch_random_scale","pitch_random_scale"),&AudioStreamGibberish::set_pitch_random_scale);
+ ClassDB::bind_method(D_METHOD("get_pitch_random_scale"),&AudioStreamGibberish::get_pitch_random_scale);
- ClassDB::bind_method(_MD("set_xfade_time","sec"),&AudioStreamGibberish::set_xfade_time);
- ClassDB::bind_method(_MD("get_xfade_time"),&AudioStreamGibberish::get_xfade_time);
+ ClassDB::bind_method(D_METHOD("set_xfade_time","sec"),&AudioStreamGibberish::set_xfade_time);
+ ClassDB::bind_method(D_METHOD("get_xfade_time"),&AudioStreamGibberish::get_xfade_time);
- ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"phonemes",PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),_SCS("set_phonemes"),_SCS("get_phonemes"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_pitch_scale"),_SCS("get_pitch_scale"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_random_scale",PROPERTY_HINT_RANGE,"0,64,0.01"),_SCS("set_pitch_random_scale"),_SCS("get_pitch_random_scale"));
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"xfade_sec",PROPERTY_HINT_RANGE,"0.001,0.5,0.001"),_SCS("set_xfade_time"),_SCS("get_xfade_time"));
+ ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"phonemes",PROPERTY_HINT_RESOURCE_TYPE,"SampleLibrary"),"set_phonemes","get_phonemes");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),"set_pitch_scale","get_pitch_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"pitch_random_scale",PROPERTY_HINT_RANGE,"0,64,0.01"),"set_pitch_random_scale","get_pitch_random_scale");
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"xfade_sec",PROPERTY_HINT_RANGE,"0.001,0.5,0.001"),"set_xfade_time","get_xfade_time");
}
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index e2e79970f9..3780c466a5 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -339,7 +339,7 @@ void FixedSpatialMaterial::_update_shader() {
code+="\tROUGHNESS = specular_tex.a * roughness;\n";
} else {
code+="\tvec4 specular_tex = texture(texture_specular,UV);\n";
- code+="\tSPECULAR = vec3(metalness * specular_tex.r);\n";
+ code+="\tSPECULAR = vec3(ALBEDO.rgb * metalness * specular_tex.r);\n";
code+="\tROUGHNESS = specular_tex.a * roughness;\n";
}
@@ -831,193 +831,193 @@ Vector2 FixedSpatialMaterial::get_uv2_offset() const{
void FixedSpatialMaterial::_bind_methods() {
- ClassDB::bind_method(_MD("set_albedo","albedo"),&FixedSpatialMaterial::set_albedo);
- ClassDB::bind_method(_MD("get_albedo"),&FixedSpatialMaterial::get_albedo);
+ ClassDB::bind_method(D_METHOD("set_albedo","albedo"),&FixedSpatialMaterial::set_albedo);
+ ClassDB::bind_method(D_METHOD("get_albedo"),&FixedSpatialMaterial::get_albedo);
- ClassDB::bind_method(_MD("set_specular_mode","specular_mode"),&FixedSpatialMaterial::set_specular_mode);
- ClassDB::bind_method(_MD("get_specular_mode"),&FixedSpatialMaterial::get_specular_mode);
+ ClassDB::bind_method(D_METHOD("set_specular_mode","specular_mode"),&FixedSpatialMaterial::set_specular_mode);
+ ClassDB::bind_method(D_METHOD("get_specular_mode"),&FixedSpatialMaterial::get_specular_mode);
- ClassDB::bind_method(_MD("set_specular","specular"),&FixedSpatialMaterial::set_specular);
- ClassDB::bind_method(_MD("get_specular"),&FixedSpatialMaterial::get_specular);
+ ClassDB::bind_method(D_METHOD("set_specular","specular"),&FixedSpatialMaterial::set_specular);
+ ClassDB::bind_method(D_METHOD("get_specular"),&FixedSpatialMaterial::get_specular);
- ClassDB::bind_method(_MD("set_metalness","metalness"),&FixedSpatialMaterial::set_metalness);
- ClassDB::bind_method(_MD("get_metalness"),&FixedSpatialMaterial::get_metalness);
+ ClassDB::bind_method(D_METHOD("set_metalness","metalness"),&FixedSpatialMaterial::set_metalness);
+ ClassDB::bind_method(D_METHOD("get_metalness"),&FixedSpatialMaterial::get_metalness);
- ClassDB::bind_method(_MD("set_roughness","roughness"),&FixedSpatialMaterial::set_roughness);
- ClassDB::bind_method(_MD("get_roughness"),&FixedSpatialMaterial::get_roughness);
+ ClassDB::bind_method(D_METHOD("set_roughness","roughness"),&FixedSpatialMaterial::set_roughness);
+ ClassDB::bind_method(D_METHOD("get_roughness"),&FixedSpatialMaterial::get_roughness);
- ClassDB::bind_method(_MD("set_emission","emission"),&FixedSpatialMaterial::set_emission);
- ClassDB::bind_method(_MD("get_emission"),&FixedSpatialMaterial::get_emission);
+ ClassDB::bind_method(D_METHOD("set_emission","emission"),&FixedSpatialMaterial::set_emission);
+ ClassDB::bind_method(D_METHOD("get_emission"),&FixedSpatialMaterial::get_emission);
- ClassDB::bind_method(_MD("set_emission_energy","emission_energy"),&FixedSpatialMaterial::set_emission_energy);
- ClassDB::bind_method(_MD("get_emission_energy"),&FixedSpatialMaterial::get_emission_energy);
+ ClassDB::bind_method(D_METHOD("set_emission_energy","emission_energy"),&FixedSpatialMaterial::set_emission_energy);
+ ClassDB::bind_method(D_METHOD("get_emission_energy"),&FixedSpatialMaterial::get_emission_energy);
- ClassDB::bind_method(_MD("set_normal_scale","normal_scale"),&FixedSpatialMaterial::set_normal_scale);
- ClassDB::bind_method(_MD("get_normal_scale"),&FixedSpatialMaterial::get_normal_scale);
+ ClassDB::bind_method(D_METHOD("set_normal_scale","normal_scale"),&FixedSpatialMaterial::set_normal_scale);
+ ClassDB::bind_method(D_METHOD("get_normal_scale"),&FixedSpatialMaterial::get_normal_scale);
- ClassDB::bind_method(_MD("set_rim","rim"),&FixedSpatialMaterial::set_rim);
- ClassDB::bind_method(_MD("get_rim"),&FixedSpatialMaterial::get_rim);
+ ClassDB::bind_method(D_METHOD("set_rim","rim"),&FixedSpatialMaterial::set_rim);
+ ClassDB::bind_method(D_METHOD("get_rim"),&FixedSpatialMaterial::get_rim);
- ClassDB::bind_method(_MD("set_rim_tint","rim_tint"),&FixedSpatialMaterial::set_rim_tint);
- ClassDB::bind_method(_MD("get_rim_tint"),&FixedSpatialMaterial::get_rim_tint);
+ ClassDB::bind_method(D_METHOD("set_rim_tint","rim_tint"),&FixedSpatialMaterial::set_rim_tint);
+ ClassDB::bind_method(D_METHOD("get_rim_tint"),&FixedSpatialMaterial::get_rim_tint);
- ClassDB::bind_method(_MD("set_clearcoat","clearcoat"),&FixedSpatialMaterial::set_clearcoat);
- ClassDB::bind_method(_MD("get_clearcoat"),&FixedSpatialMaterial::get_clearcoat);
+ ClassDB::bind_method(D_METHOD("set_clearcoat","clearcoat"),&FixedSpatialMaterial::set_clearcoat);
+ ClassDB::bind_method(D_METHOD("get_clearcoat"),&FixedSpatialMaterial::get_clearcoat);
- ClassDB::bind_method(_MD("set_clearcoat_gloss","clearcoat_gloss"),&FixedSpatialMaterial::set_clearcoat_gloss);
- ClassDB::bind_method(_MD("get_clearcoat_gloss"),&FixedSpatialMaterial::get_clearcoat_gloss);
+ ClassDB::bind_method(D_METHOD("set_clearcoat_gloss","clearcoat_gloss"),&FixedSpatialMaterial::set_clearcoat_gloss);
+ ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"),&FixedSpatialMaterial::get_clearcoat_gloss);
- ClassDB::bind_method(_MD("set_anisotropy","anisotropy"),&FixedSpatialMaterial::set_anisotropy);
- ClassDB::bind_method(_MD("get_anisotropy"),&FixedSpatialMaterial::get_anisotropy);
+ ClassDB::bind_method(D_METHOD("set_anisotropy","anisotropy"),&FixedSpatialMaterial::set_anisotropy);
+ ClassDB::bind_method(D_METHOD("get_anisotropy"),&FixedSpatialMaterial::get_anisotropy);
- ClassDB::bind_method(_MD("set_height_scale","height_scale"),&FixedSpatialMaterial::set_height_scale);
- ClassDB::bind_method(_MD("get_height_scale"),&FixedSpatialMaterial::get_height_scale);
+ ClassDB::bind_method(D_METHOD("set_height_scale","height_scale"),&FixedSpatialMaterial::set_height_scale);
+ ClassDB::bind_method(D_METHOD("get_height_scale"),&FixedSpatialMaterial::get_height_scale);
- ClassDB::bind_method(_MD("set_subsurface_scattering_strength","strength"),&FixedSpatialMaterial::set_subsurface_scattering_strength);
- ClassDB::bind_method(_MD("get_subsurface_scattering_strength"),&FixedSpatialMaterial::get_subsurface_scattering_strength);
+ ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength","strength"),&FixedSpatialMaterial::set_subsurface_scattering_strength);
+ ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"),&FixedSpatialMaterial::get_subsurface_scattering_strength);
- ClassDB::bind_method(_MD("set_refraction","refraction"),&FixedSpatialMaterial::set_refraction);
- ClassDB::bind_method(_MD("get_refraction"),&FixedSpatialMaterial::get_refraction);
+ ClassDB::bind_method(D_METHOD("set_refraction","refraction"),&FixedSpatialMaterial::set_refraction);
+ ClassDB::bind_method(D_METHOD("get_refraction"),&FixedSpatialMaterial::get_refraction);
- ClassDB::bind_method(_MD("set_refraction_roughness","refraction_roughness"),&FixedSpatialMaterial::set_refraction_roughness);
- ClassDB::bind_method(_MD("get_refraction_roughness"),&FixedSpatialMaterial::get_refraction_roughness);
+ ClassDB::bind_method(D_METHOD("set_refraction_roughness","refraction_roughness"),&FixedSpatialMaterial::set_refraction_roughness);
+ ClassDB::bind_method(D_METHOD("get_refraction_roughness"),&FixedSpatialMaterial::get_refraction_roughness);
- ClassDB::bind_method(_MD("set_line_width","line_width"),&FixedSpatialMaterial::set_line_width);
- ClassDB::bind_method(_MD("get_line_width"),&FixedSpatialMaterial::get_line_width);
+ ClassDB::bind_method(D_METHOD("set_line_width","line_width"),&FixedSpatialMaterial::set_line_width);
+ ClassDB::bind_method(D_METHOD("get_line_width"),&FixedSpatialMaterial::get_line_width);
- ClassDB::bind_method(_MD("set_point_size","point_size"),&FixedSpatialMaterial::set_point_size);
- ClassDB::bind_method(_MD("get_point_size"),&FixedSpatialMaterial::get_point_size);
+ ClassDB::bind_method(D_METHOD("set_point_size","point_size"),&FixedSpatialMaterial::set_point_size);
+ ClassDB::bind_method(D_METHOD("get_point_size"),&FixedSpatialMaterial::get_point_size);
- ClassDB::bind_method(_MD("set_detail_uv","detail_uv"),&FixedSpatialMaterial::set_detail_uv);
- ClassDB::bind_method(_MD("get_detail_uv"),&FixedSpatialMaterial::get_detail_uv);
+ ClassDB::bind_method(D_METHOD("set_detail_uv","detail_uv"),&FixedSpatialMaterial::set_detail_uv);
+ ClassDB::bind_method(D_METHOD("get_detail_uv"),&FixedSpatialMaterial::get_detail_uv);
- ClassDB::bind_method(_MD("set_blend_mode","blend_mode"),&FixedSpatialMaterial::set_blend_mode);
- ClassDB::bind_method(_MD("get_blend_mode"),&FixedSpatialMaterial::get_blend_mode);
+ ClassDB::bind_method(D_METHOD("set_blend_mode","blend_mode"),&FixedSpatialMaterial::set_blend_mode);
+ ClassDB::bind_method(D_METHOD("get_blend_mode"),&FixedSpatialMaterial::get_blend_mode);
- ClassDB::bind_method(_MD("set_depth_draw_mode","depth_draw_mode"),&FixedSpatialMaterial::set_depth_draw_mode);
- ClassDB::bind_method(_MD("get_depth_draw_mode"),&FixedSpatialMaterial::get_depth_draw_mode);
+ ClassDB::bind_method(D_METHOD("set_depth_draw_mode","depth_draw_mode"),&FixedSpatialMaterial::set_depth_draw_mode);
+ ClassDB::bind_method(D_METHOD("get_depth_draw_mode"),&FixedSpatialMaterial::get_depth_draw_mode);
- ClassDB::bind_method(_MD("set_cull_mode","cull_mode"),&FixedSpatialMaterial::set_cull_mode);
- ClassDB::bind_method(_MD("get_cull_mode"),&FixedSpatialMaterial::get_cull_mode);
+ ClassDB::bind_method(D_METHOD("set_cull_mode","cull_mode"),&FixedSpatialMaterial::set_cull_mode);
+ ClassDB::bind_method(D_METHOD("get_cull_mode"),&FixedSpatialMaterial::get_cull_mode);
- ClassDB::bind_method(_MD("set_diffuse_mode","diffuse_mode"),&FixedSpatialMaterial::set_diffuse_mode);
- ClassDB::bind_method(_MD("get_diffuse_mode"),&FixedSpatialMaterial::get_diffuse_mode);
+ ClassDB::bind_method(D_METHOD("set_diffuse_mode","diffuse_mode"),&FixedSpatialMaterial::set_diffuse_mode);
+ ClassDB::bind_method(D_METHOD("get_diffuse_mode"),&FixedSpatialMaterial::get_diffuse_mode);
- ClassDB::bind_method(_MD("set_flag","flag","enable"),&FixedSpatialMaterial::set_flag);
- ClassDB::bind_method(_MD("get_flag"),&FixedSpatialMaterial::get_flag);
+ ClassDB::bind_method(D_METHOD("set_flag","flag","enable"),&FixedSpatialMaterial::set_flag);
+ ClassDB::bind_method(D_METHOD("get_flag"),&FixedSpatialMaterial::get_flag);
- ClassDB::bind_method(_MD("set_feature","feature","enable"),&FixedSpatialMaterial::set_feature);
- ClassDB::bind_method(_MD("get_feature","feature"),&FixedSpatialMaterial::get_feature);
+ ClassDB::bind_method(D_METHOD("set_feature","feature","enable"),&FixedSpatialMaterial::set_feature);
+ ClassDB::bind_method(D_METHOD("get_feature","feature"),&FixedSpatialMaterial::get_feature);
- ClassDB::bind_method(_MD("set_texture","param:Texture","texture"),&FixedSpatialMaterial::set_texture);
- ClassDB::bind_method(_MD("get_texture:Texture","param:Texture"),&FixedSpatialMaterial::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture","param:Texture","texture"),&FixedSpatialMaterial::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture","param:Texture"),&FixedSpatialMaterial::get_texture);
- ClassDB::bind_method(_MD("set_detail_blend_mode","detail_blend_mode"),&FixedSpatialMaterial::set_detail_blend_mode);
- ClassDB::bind_method(_MD("get_detail_blend_mode"),&FixedSpatialMaterial::get_detail_blend_mode);
+ ClassDB::bind_method(D_METHOD("set_detail_blend_mode","detail_blend_mode"),&FixedSpatialMaterial::set_detail_blend_mode);
+ ClassDB::bind_method(D_METHOD("get_detail_blend_mode"),&FixedSpatialMaterial::get_detail_blend_mode);
- ClassDB::bind_method(_MD("set_uv1_scale","scale"),&FixedSpatialMaterial::set_uv1_scale);
- ClassDB::bind_method(_MD("get_uv1_scale"),&FixedSpatialMaterial::get_uv1_scale);
+ ClassDB::bind_method(D_METHOD("set_uv1_scale","scale"),&FixedSpatialMaterial::set_uv1_scale);
+ ClassDB::bind_method(D_METHOD("get_uv1_scale"),&FixedSpatialMaterial::get_uv1_scale);
- ClassDB::bind_method(_MD("set_uv1_offset","offset"),&FixedSpatialMaterial::set_uv1_offset);
- ClassDB::bind_method(_MD("get_uv1_offset"),&FixedSpatialMaterial::get_uv1_offset);
+ ClassDB::bind_method(D_METHOD("set_uv1_offset","offset"),&FixedSpatialMaterial::set_uv1_offset);
+ ClassDB::bind_method(D_METHOD("get_uv1_offset"),&FixedSpatialMaterial::get_uv1_offset);
- ClassDB::bind_method(_MD("set_uv2_scale","scale"),&FixedSpatialMaterial::set_uv2_scale);
- ClassDB::bind_method(_MD("get_uv2_scale"),&FixedSpatialMaterial::get_uv2_scale);
+ ClassDB::bind_method(D_METHOD("set_uv2_scale","scale"),&FixedSpatialMaterial::set_uv2_scale);
+ ClassDB::bind_method(D_METHOD("get_uv2_scale"),&FixedSpatialMaterial::get_uv2_scale);
- ClassDB::bind_method(_MD("set_uv2_offset","offset"),&FixedSpatialMaterial::set_uv2_offset);
- ClassDB::bind_method(_MD("get_uv2_offset"),&FixedSpatialMaterial::get_uv2_offset);
+ ClassDB::bind_method(D_METHOD("set_uv2_offset","offset"),&FixedSpatialMaterial::set_uv2_offset);
+ ClassDB::bind_method(D_METHOD("get_uv2_offset"),&FixedSpatialMaterial::get_uv2_offset);
ADD_GROUP("Flags","flags_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_transparent"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_TRANSPARENT);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_unshaded"),_SCS("set_flag"),_SCS("get_flag"),FLAG_UNSHADED);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_on_top"),_SCS("set_flag"),_SCS("get_flag"),FLAG_ONTOP);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_use_point_size"),_SCS("set_flag"),_SCS("get_flag"),FLAG_USE_POINT_SIZE);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_transparent"),"set_feature","get_feature",FEATURE_TRANSPARENT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_unshaded"),"set_flag","get_flag",FLAG_UNSHADED);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_on_top"),"set_flag","get_flag",FLAG_ONTOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags_use_point_size"),"set_flag","get_flag",FLAG_USE_POINT_SIZE);
ADD_GROUP("Vertex Color","vertex_color");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"vertex_color_use_as_albedo"),_SCS("set_flag"),_SCS("get_flag"),FLAG_ALBEDO_FROM_VERTEX_COLOR);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"vertex_color_is_srgb"),_SCS("set_flag"),_SCS("get_flag"),FLAG_SRGB_VERTEX_COLOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"vertex_color_use_as_albedo"),"set_flag","get_flag",FLAG_ALBEDO_FROM_VERTEX_COLOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"vertex_color_is_srgb"),"set_flag","get_flag",FLAG_SRGB_VERTEX_COLOR);
ADD_GROUP("Parameters","params_");
- ADD_PROPERTY(PropertyInfo(Variant::INT,"params_diffuse_mode",PROPERTY_HINT_ENUM,"Labert,Lambert Wrap,Oren Nayar,Burley"),_SCS("set_diffuse_mode"),_SCS("get_diffuse_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"params_blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub,Mul"),_SCS("set_blend_mode"),_SCS("get_blend_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"params_cull_mode",PROPERTY_HINT_ENUM,"Back,Front,Disabled"),_SCS("set_cull_mode"),_SCS("get_cull_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"params_depth_draw_mode",PROPERTY_HINT_ENUM,"Opaque Only,Always,Never,Opaque Pre-Pass"),_SCS("set_depth_draw_mode"),_SCS("get_depth_draw_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"params_line_width",PROPERTY_HINT_RANGE,"0.1,128,0.1"),_SCS("set_line_width"),_SCS("get_line_width"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"params_point_size",PROPERTY_HINT_RANGE,"0.1,128,0.1"),_SCS("set_point_size"),_SCS("get_point_size"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"params_diffuse_mode",PROPERTY_HINT_ENUM,"Labert,Lambert Wrap,Oren Nayar,Burley"),"set_diffuse_mode","get_diffuse_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"params_blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub,Mul"),"set_blend_mode","get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"params_cull_mode",PROPERTY_HINT_ENUM,"Back,Front,Disabled"),"set_cull_mode","get_cull_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"params_depth_draw_mode",PROPERTY_HINT_ENUM,"Opaque Only,Always,Never,Opaque Pre-Pass"),"set_depth_draw_mode","get_depth_draw_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"params_line_width",PROPERTY_HINT_RANGE,"0.1,128,0.1"),"set_line_width","get_line_width");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"params_point_size",PROPERTY_HINT_RANGE,"0.1,128,0.1"),"set_point_size","get_point_size");
ADD_GROUP("Albedo","albedo_");
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"albedo_color"),_SCS("set_albedo"),_SCS("get_albedo"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"albedo_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_ALBEDO);
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"albedo_color"),"set_albedo","get_albedo");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"albedo_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_ALBEDO);
ADD_GROUP("Specular","specular_");
- ADD_PROPERTY(PropertyInfo(Variant::INT,"specular_mode",PROPERTY_HINT_ENUM,"Metallic,Specular"),_SCS("set_specular_mode"),_SCS("get_specular_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"specular_color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_specular"),_SCS("get_specular"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular_metalness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_metalness"),_SCS("get_metalness"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular_roughness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_roughness"),_SCS("get_roughness"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"specular_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_SPECULAR);
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"specular_mode",PROPERTY_HINT_ENUM,"Metallic,Specular"),"set_specular_mode","get_specular_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"specular_color",PROPERTY_HINT_COLOR_NO_ALPHA),"set_specular","get_specular");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular_metalness",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_metalness","get_metalness");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular_roughness",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_roughness","get_roughness");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"specular_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_SPECULAR);
ADD_GROUP("Emission","emission_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"emission_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_EMISSION);
- ADD_PROPERTY(PropertyInfo(Variant::COLOR,"emission_color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_emission"),_SCS("get_emission"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"emission_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_emission_energy"),_SCS("get_emission_energy"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"emission_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_EMISSION);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"emission_enabled"),"set_feature","get_feature",FEATURE_EMISSION);
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR,"emission_color",PROPERTY_HINT_COLOR_NO_ALPHA),"set_emission","get_emission");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"emission_energy",PROPERTY_HINT_RANGE,"0,16,0.01"),"set_emission_energy","get_emission_energy");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"emission_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_EMISSION);
ADD_GROUP("NormapMap","normal_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"normal_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_NORMAL_MAPPING);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"normal_scale",PROPERTY_HINT_RANGE,"-16,16,0.01"),_SCS("set_normal_scale"),_SCS("get_normal_scale"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"normal_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_NORMAL);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"normal_enabled"),"set_feature","get_feature",FEATURE_NORMAL_MAPPING);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"normal_scale",PROPERTY_HINT_RANGE,"-16,16,0.01"),"set_normal_scale","get_normal_scale");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"normal_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_NORMAL);
ADD_GROUP("Rim","rim_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"rim_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_RIM);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"rim_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_rim"),_SCS("get_rim"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"rim_tint",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_rim_tint"),_SCS("get_rim_tint"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"rim_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_RIM);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"rim_enabled"),"set_feature","get_feature",FEATURE_RIM);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"rim_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_rim","get_rim");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"rim_tint",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_rim_tint","get_rim_tint");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"rim_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_RIM);
ADD_GROUP("Clearcoat","clearcoat_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"clearcoat_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_CLEARCOAT);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"clearcoat_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_clearcoat"),_SCS("get_clearcoat"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"clearcoat_gloss",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_clearcoat_gloss"),_SCS("get_clearcoat_gloss"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"clearcoat_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_CLEARCOAT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"clearcoat_enabled"),"set_feature","get_feature",FEATURE_CLEARCOAT);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"clearcoat_amount",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_clearcoat","get_clearcoat");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"clearcoat_gloss",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_clearcoat_gloss","get_clearcoat_gloss");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"clearcoat_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_CLEARCOAT);
ADD_GROUP("Anisotropy","anisotropy_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"anisotropy_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_ANISOTROPY);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"anisotropy_anisotropy",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_anisotropy"),_SCS("get_anisotropy"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"anisotropy_flowmap",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_FLOWMAP);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"anisotropy_enabled"),"set_feature","get_feature",FEATURE_ANISOTROPY);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"anisotropy_anisotropy",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_anisotropy","get_anisotropy");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"anisotropy_flowmap",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_FLOWMAP);
ADD_GROUP("Ambient Occlusion","ao_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"ao_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_AMBIENT_OCCLUSION);
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"ao_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_AMBIENT_OCCLUSION);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"ao_enabled"),"set_feature","get_feature",FEATURE_AMBIENT_OCCLUSION);
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"ao_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_AMBIENT_OCCLUSION);
ADD_GROUP("Height","height_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"height_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_HEIGHT_MAPPING);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"height_scale",PROPERTY_HINT_RANGE,"-16,16,0.01"),_SCS("set_height_scale"),_SCS("get_height_scale"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"height_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_HEIGHT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"height_enabled"),"set_feature","get_feature",FEATURE_HEIGHT_MAPPING);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"height_scale",PROPERTY_HINT_RANGE,"-16,16,0.01"),"set_height_scale","get_height_scale");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"height_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_HEIGHT);
ADD_GROUP("Subsurf Scatter","subsurf_scatter_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"subsurf_scatter_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_SUBSURACE_SCATTERING);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"subsurf_scatter_strength",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_subsurface_scattering_strength"),_SCS("get_subsurface_scattering_strength"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"subsurf_scatter_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_SUBSURFACE_SCATTERING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"subsurf_scatter_enabled"),"set_feature","get_feature",FEATURE_SUBSURACE_SCATTERING);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"subsurf_scatter_strength",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_subsurface_scattering_strength","get_subsurface_scattering_strength");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"subsurf_scatter_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_SUBSURFACE_SCATTERING);
ADD_GROUP("Refraction","refraction_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"refraction_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_REFRACTION);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"refraction_displacement",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_refraction"),_SCS("get_refraction"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"refraction_roughness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_refraction_roughness"),_SCS("get_refraction_roughness"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"refraction_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_REFRACTION);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"refraction_enabled"),"set_feature","get_feature",FEATURE_REFRACTION);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"refraction_displacement",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_refraction","get_refraction");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"refraction_roughness",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_refraction_roughness","get_refraction_roughness");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"refraction_texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_REFRACTION);
ADD_GROUP("Detail","detail_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"detail_enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_DETAIL);
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail_mask",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_DETAIL_MASK);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"detail_blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub,Mul"),_SCS("set_detail_blend_mode"),_SCS("get_detail_blend_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"detail_uv_layer",PROPERTY_HINT_ENUM,"UV1,UV2"),_SCS("set_detail_uv"),_SCS("get_detail_uv"));
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail_albedo",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_DETAIL_ALBEDO);
- ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail_normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_DETAIL_NORMAL);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"detail_enabled"),"set_feature","get_feature",FEATURE_DETAIL);
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail_mask",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_DETAIL_MASK);
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"detail_blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub,Mul"),"set_detail_blend_mode","get_detail_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"detail_uv_layer",PROPERTY_HINT_ENUM,"UV1,UV2"),"set_detail_uv","get_detail_uv");
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail_albedo",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_DETAIL_ALBEDO);
+ ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail_normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),"set_texture","get_texture",TEXTURE_DETAIL_NORMAL);
ADD_GROUP("UV1","uv1_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv1_scale"),_SCS("set_uv1_scale"),_SCS("get_uv1_scale"));
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv1_offset"),_SCS("set_uv1_offset"),_SCS("get_uv1_offset"));
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv1_scale"),"set_uv1_scale","get_uv1_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv1_offset"),"set_uv1_offset","get_uv1_offset");
ADD_GROUP("UV2","uv2_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv2_scale"),_SCS("set_uv2_scale"),_SCS("get_uv2_scale"));
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv2_offset"),_SCS("set_uv2_offset"),_SCS("get_uv2_offset"));
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv2_scale"),"set_uv2_scale","get_uv2_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv2_offset"),"set_uv2_offset","get_uv2_offset");
BIND_CONSTANT( TEXTURE_ALBEDO );
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 99911eddeb..9990a6e796 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -128,8 +128,8 @@ bool Mesh::_set(const StringName& p_name, const Variant& p_value) {
if (d.has("arrays")) {
//old format
- ERR_FAIL_COND_V(!d.has("blend_shape_arrays"),false);
- add_surface_from_arrays(PrimitiveType(int(d["primitive"])),d["arrays"],d["blend_shape_arrays"]);
+ ERR_FAIL_COND_V(!d.has("morph_arrays"),false);
+ add_surface_from_arrays(PrimitiveType(int(d["primitive"])),d["arrays"],d["morph_arrays"]);
} else if (d.has("array_data")) {
@@ -1019,31 +1019,31 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
void Mesh::_bind_methods() {
- ClassDB::bind_method(_MD("add_blend_shape","name"),&Mesh::add_blend_shape);
- ClassDB::bind_method(_MD("get_blend_shape_count"),&Mesh::get_blend_shape_count);
- ClassDB::bind_method(_MD("get_blend_shape_name","index"),&Mesh::get_blend_shape_name);
- ClassDB::bind_method(_MD("clear_blend_shapes"),&Mesh::clear_blend_shapes);
- ClassDB::bind_method(_MD("set_blend_shape_mode","mode"),&Mesh::set_blend_shape_mode);
- ClassDB::bind_method(_MD("get_blend_shape_mode"),&Mesh::get_blend_shape_mode);
-
- ClassDB::bind_method(_MD("add_surface_from_arrays","primitive","arrays","blend_shapes","compress_flags"),&Mesh::add_surface_from_arrays,DEFVAL(Array()),DEFVAL(ARRAY_COMPRESS_DEFAULT));
- ClassDB::bind_method(_MD("get_surface_count"),&Mesh::get_surface_count);
- ClassDB::bind_method(_MD("surface_remove","surf_idx"),&Mesh::surface_remove);
- ClassDB::bind_method(_MD("surface_get_array_len","surf_idx"),&Mesh::surface_get_array_len);
- ClassDB::bind_method(_MD("surface_get_array_index_len","surf_idx"),&Mesh::surface_get_array_index_len);
- ClassDB::bind_method(_MD("surface_get_format","surf_idx"),&Mesh::surface_get_format);
- ClassDB::bind_method(_MD("surface_get_primitive_type","surf_idx"),&Mesh::surface_get_primitive_type);
- ClassDB::bind_method(_MD("surface_set_material","surf_idx","material:Material"),&Mesh::surface_set_material);
- ClassDB::bind_method(_MD("surface_get_material:Material","surf_idx"),&Mesh::surface_get_material);
- ClassDB::bind_method(_MD("surface_set_name","surf_idx","name"),&Mesh::surface_set_name);
- ClassDB::bind_method(_MD("surface_get_name","surf_idx"),&Mesh::surface_get_name);
- ClassDB::bind_method(_MD("center_geometry"),&Mesh::center_geometry);
- ClassDB::set_method_flags(get_class_static(),_SCS("center_geometry"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::bind_method(_MD("regen_normalmaps"),&Mesh::regen_normalmaps);
- ClassDB::set_method_flags(get_class_static(),_SCS("regen_normalmaps"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
-
- ClassDB::bind_method(_MD("set_custom_aabb","aabb"),&Mesh::set_custom_aabb);
- ClassDB::bind_method(_MD("get_custom_aabb"),&Mesh::get_custom_aabb);
+ ClassDB::bind_method(D_METHOD("add_blend_shape","name"),&Mesh::add_blend_shape);
+ ClassDB::bind_method(D_METHOD("get_blend_shape_count"),&Mesh::get_blend_shape_count);
+ ClassDB::bind_method(D_METHOD("get_blend_shape_name","index"),&Mesh::get_blend_shape_name);
+ ClassDB::bind_method(D_METHOD("clear_blend_shapes"),&Mesh::clear_blend_shapes);
+ ClassDB::bind_method(D_METHOD("set_blend_shape_mode","mode"),&Mesh::set_blend_shape_mode);
+ ClassDB::bind_method(D_METHOD("get_blend_shape_mode"),&Mesh::get_blend_shape_mode);
+
+ ClassDB::bind_method(D_METHOD("add_surface_from_arrays","primitive","arrays","blend_shapes","compress_flags"),&Mesh::add_surface_from_arrays,DEFVAL(Array()),DEFVAL(ARRAY_COMPRESS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("get_surface_count"),&Mesh::get_surface_count);
+ ClassDB::bind_method(D_METHOD("surface_remove","surf_idx"),&Mesh::surface_remove);
+ ClassDB::bind_method(D_METHOD("surface_get_array_len","surf_idx"),&Mesh::surface_get_array_len);
+ ClassDB::bind_method(D_METHOD("surface_get_array_index_len","surf_idx"),&Mesh::surface_get_array_index_len);
+ ClassDB::bind_method(D_METHOD("surface_get_format","surf_idx"),&Mesh::surface_get_format);
+ ClassDB::bind_method(D_METHOD("surface_get_primitive_type","surf_idx"),&Mesh::surface_get_primitive_type);
+ ClassDB::bind_method(D_METHOD("surface_set_material","surf_idx","material:Material"),&Mesh::surface_set_material);
+ ClassDB::bind_method(D_METHOD("surface_get_material:Material","surf_idx"),&Mesh::surface_get_material);
+ ClassDB::bind_method(D_METHOD("surface_set_name","surf_idx","name"),&Mesh::surface_set_name);
+ ClassDB::bind_method(D_METHOD("surface_get_name","surf_idx"),&Mesh::surface_get_name);
+ ClassDB::bind_method(D_METHOD("center_geometry"),&Mesh::center_geometry);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("center_geometry"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("regen_normalmaps"),&Mesh::regen_normalmaps);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("regen_normalmaps"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+
+ ClassDB::bind_method(D_METHOD("set_custom_aabb","aabb"),&Mesh::set_custom_aabb);
+ ClassDB::bind_method(D_METHOD("get_custom_aabb"),&Mesh::get_custom_aabb);
BIND_CONSTANT( NO_INDEX_ARRAY );
diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp
index ec699ee8e3..abe335aa5b 100644
--- a/scene/resources/mesh_data_tool.cpp
+++ b/scene/resources/mesh_data_tool.cpp
@@ -565,62 +565,62 @@ void MeshDataTool::set_material(const Ref<Material> &p_material) {
void MeshDataTool::_bind_methods() {
- ClassDB::bind_method(_MD("clear"),&MeshDataTool::clear);
- ClassDB::bind_method(_MD("create_from_surface","mesh","surface"),&MeshDataTool::create_from_surface);
- ClassDB::bind_method(_MD("commit_to_surface","mesh"),&MeshDataTool::commit_to_surface);
+ ClassDB::bind_method(D_METHOD("clear"),&MeshDataTool::clear);
+ ClassDB::bind_method(D_METHOD("create_from_surface","mesh","surface"),&MeshDataTool::create_from_surface);
+ ClassDB::bind_method(D_METHOD("commit_to_surface","mesh"),&MeshDataTool::commit_to_surface);
- ClassDB::bind_method(_MD("get_format"),&MeshDataTool::get_format);
+ ClassDB::bind_method(D_METHOD("get_format"),&MeshDataTool::get_format);
- ClassDB::bind_method(_MD("get_vertex_count"),&MeshDataTool::get_vertex_count);
- ClassDB::bind_method(_MD("get_edge_count"),&MeshDataTool::get_edge_count);
- ClassDB::bind_method(_MD("get_face_count"),&MeshDataTool::get_face_count);
+ ClassDB::bind_method(D_METHOD("get_vertex_count"),&MeshDataTool::get_vertex_count);
+ ClassDB::bind_method(D_METHOD("get_edge_count"),&MeshDataTool::get_edge_count);
+ ClassDB::bind_method(D_METHOD("get_face_count"),&MeshDataTool::get_face_count);
- ClassDB::bind_method(_MD("set_vertex","idx","vertex"),&MeshDataTool::set_vertex);
- ClassDB::bind_method(_MD("get_vertex","idx"),&MeshDataTool::get_vertex);
+ ClassDB::bind_method(D_METHOD("set_vertex","idx","vertex"),&MeshDataTool::set_vertex);
+ ClassDB::bind_method(D_METHOD("get_vertex","idx"),&MeshDataTool::get_vertex);
- ClassDB::bind_method(_MD("set_vertex_normal","idx","normal"),&MeshDataTool::set_vertex_normal);
- ClassDB::bind_method(_MD("get_vertex_normal","idx"),&MeshDataTool::get_vertex_normal);
+ ClassDB::bind_method(D_METHOD("set_vertex_normal","idx","normal"),&MeshDataTool::set_vertex_normal);
+ ClassDB::bind_method(D_METHOD("get_vertex_normal","idx"),&MeshDataTool::get_vertex_normal);
- ClassDB::bind_method(_MD("set_vertex_tangent","idx","tangent"),&MeshDataTool::set_vertex_tangent);
- ClassDB::bind_method(_MD("get_vertex_tangent","idx"),&MeshDataTool::get_vertex_tangent);
+ ClassDB::bind_method(D_METHOD("set_vertex_tangent","idx","tangent"),&MeshDataTool::set_vertex_tangent);
+ ClassDB::bind_method(D_METHOD("get_vertex_tangent","idx"),&MeshDataTool::get_vertex_tangent);
- ClassDB::bind_method(_MD("set_vertex_uv","idx","uv"),&MeshDataTool::set_vertex_uv);
- ClassDB::bind_method(_MD("get_vertex_uv","idx"),&MeshDataTool::get_vertex_uv);
+ ClassDB::bind_method(D_METHOD("set_vertex_uv","idx","uv"),&MeshDataTool::set_vertex_uv);
+ ClassDB::bind_method(D_METHOD("get_vertex_uv","idx"),&MeshDataTool::get_vertex_uv);
- ClassDB::bind_method(_MD("set_vertex_uv2","idx","uv2"),&MeshDataTool::set_vertex_uv2);
- ClassDB::bind_method(_MD("get_vertex_uv2","idx"),&MeshDataTool::get_vertex_uv2);
+ ClassDB::bind_method(D_METHOD("set_vertex_uv2","idx","uv2"),&MeshDataTool::set_vertex_uv2);
+ ClassDB::bind_method(D_METHOD("get_vertex_uv2","idx"),&MeshDataTool::get_vertex_uv2);
- ClassDB::bind_method(_MD("set_vertex_color","idx","color"),&MeshDataTool::set_vertex_color);
- ClassDB::bind_method(_MD("get_vertex_color","idx"),&MeshDataTool::get_vertex_color);
+ ClassDB::bind_method(D_METHOD("set_vertex_color","idx","color"),&MeshDataTool::set_vertex_color);
+ ClassDB::bind_method(D_METHOD("get_vertex_color","idx"),&MeshDataTool::get_vertex_color);
- ClassDB::bind_method(_MD("set_vertex_bones","idx","bones"),&MeshDataTool::set_vertex_bones);
- ClassDB::bind_method(_MD("get_vertex_bones","idx"),&MeshDataTool::get_vertex_bones);
+ ClassDB::bind_method(D_METHOD("set_vertex_bones","idx","bones"),&MeshDataTool::set_vertex_bones);
+ ClassDB::bind_method(D_METHOD("get_vertex_bones","idx"),&MeshDataTool::get_vertex_bones);
- ClassDB::bind_method(_MD("set_vertex_weights","idx","weights"),&MeshDataTool::set_vertex_weights);
- ClassDB::bind_method(_MD("get_vertex_weights","idx"),&MeshDataTool::get_vertex_weights);
+ ClassDB::bind_method(D_METHOD("set_vertex_weights","idx","weights"),&MeshDataTool::set_vertex_weights);
+ ClassDB::bind_method(D_METHOD("get_vertex_weights","idx"),&MeshDataTool::get_vertex_weights);
- ClassDB::bind_method(_MD("set_vertex_meta","idx","meta"),&MeshDataTool::set_vertex_meta);
- ClassDB::bind_method(_MD("get_vertex_meta","idx"),&MeshDataTool::get_vertex_meta);
+ ClassDB::bind_method(D_METHOD("set_vertex_meta","idx","meta"),&MeshDataTool::set_vertex_meta);
+ ClassDB::bind_method(D_METHOD("get_vertex_meta","idx"),&MeshDataTool::get_vertex_meta);
- ClassDB::bind_method(_MD("get_vertex_edges","idx"),&MeshDataTool::get_vertex_edges);
- ClassDB::bind_method(_MD("get_vertex_faces","idx"),&MeshDataTool::get_vertex_faces);
+ ClassDB::bind_method(D_METHOD("get_vertex_edges","idx"),&MeshDataTool::get_vertex_edges);
+ ClassDB::bind_method(D_METHOD("get_vertex_faces","idx"),&MeshDataTool::get_vertex_faces);
- ClassDB::bind_method(_MD("get_edge_vertex","idx","vertex"),&MeshDataTool::get_edge_vertex);
- ClassDB::bind_method(_MD("get_edge_faces","idx","faces"),&MeshDataTool::get_edge_faces);
+ ClassDB::bind_method(D_METHOD("get_edge_vertex","idx","vertex"),&MeshDataTool::get_edge_vertex);
+ ClassDB::bind_method(D_METHOD("get_edge_faces","idx","faces"),&MeshDataTool::get_edge_faces);
- ClassDB::bind_method(_MD("set_edge_meta","idx","meta"),&MeshDataTool::set_edge_meta);
- ClassDB::bind_method(_MD("get_edge_meta","idx"),&MeshDataTool::get_edge_meta);
+ ClassDB::bind_method(D_METHOD("set_edge_meta","idx","meta"),&MeshDataTool::set_edge_meta);
+ ClassDB::bind_method(D_METHOD("get_edge_meta","idx"),&MeshDataTool::get_edge_meta);
- ClassDB::bind_method(_MD("get_face_vertex","idx","vertex"),&MeshDataTool::get_face_vertex);
- ClassDB::bind_method(_MD("get_face_edge","idx","edge"),&MeshDataTool::get_face_edge);
+ ClassDB::bind_method(D_METHOD("get_face_vertex","idx","vertex"),&MeshDataTool::get_face_vertex);
+ ClassDB::bind_method(D_METHOD("get_face_edge","idx","edge"),&MeshDataTool::get_face_edge);
- ClassDB::bind_method(_MD("set_face_meta","idx","meta"),&MeshDataTool::set_face_meta);
- ClassDB::bind_method(_MD("get_face_meta","idx"),&MeshDataTool::get_face_meta);
+ ClassDB::bind_method(D_METHOD("set_face_meta","idx","meta"),&MeshDataTool::set_face_meta);
+ ClassDB::bind_method(D_METHOD("get_face_meta","idx"),&MeshDataTool::get_face_meta);
- ClassDB::bind_method(_MD("get_face_normal","idx"),&MeshDataTool::get_face_normal);
+ ClassDB::bind_method(D_METHOD("get_face_normal","idx"),&MeshDataTool::get_face_normal);
- ClassDB::bind_method(_MD("set_material","material:Material"),&MeshDataTool::set_material);
- ClassDB::bind_method(_MD("get_material","material"),&MeshDataTool::get_material);
+ ClassDB::bind_method(D_METHOD("set_material","material:Material"),&MeshDataTool::set_material);
+ ClassDB::bind_method(D_METHOD("get_material","material"),&MeshDataTool::get_material);
}
MeshDataTool::MeshDataTool(){
diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp
index cc357c4d9b..becbf39dad 100644
--- a/scene/resources/mesh_library.cpp
+++ b/scene/resources/mesh_library.cpp
@@ -244,19 +244,19 @@ int MeshLibrary::get_last_unused_item_id() const {
void MeshLibrary::_bind_methods() {
- ClassDB::bind_method(_MD("create_item","id"),&MeshLibrary::create_item);
- ClassDB::bind_method(_MD("set_item_name","id","name"),&MeshLibrary::set_item_name);
- ClassDB::bind_method(_MD("set_item_mesh","id","mesh:Mesh"),&MeshLibrary::set_item_mesh);
- ClassDB::bind_method(_MD("set_item_navmesh","id","navmesh:NavigationMesh"),&MeshLibrary::set_item_navmesh);
- ClassDB::bind_method(_MD("set_item_shape","id","shape:Shape"),&MeshLibrary::set_item_shape);
- ClassDB::bind_method(_MD("get_item_name","id"),&MeshLibrary::get_item_name);
- ClassDB::bind_method(_MD("get_item_mesh:Mesh","id"),&MeshLibrary::get_item_mesh);
- ClassDB::bind_method(_MD("get_item_navmesh:NavigationMesh","id"),&MeshLibrary::get_item_navmesh);
- ClassDB::bind_method(_MD("get_item_shape:Shape","id"),&MeshLibrary::get_item_shape);
- ClassDB::bind_method(_MD("remove_item","id"),&MeshLibrary::remove_item);
- ClassDB::bind_method(_MD("clear"),&MeshLibrary::clear);
- ClassDB::bind_method(_MD("get_item_list"),&MeshLibrary::get_item_list);
- ClassDB::bind_method(_MD("get_last_unused_item_id"),&MeshLibrary::get_last_unused_item_id);
+ ClassDB::bind_method(D_METHOD("create_item","id"),&MeshLibrary::create_item);
+ ClassDB::bind_method(D_METHOD("set_item_name","id","name"),&MeshLibrary::set_item_name);
+ ClassDB::bind_method(D_METHOD("set_item_mesh","id","mesh:Mesh"),&MeshLibrary::set_item_mesh);
+ ClassDB::bind_method(D_METHOD("set_item_navmesh","id","navmesh:NavigationMesh"),&MeshLibrary::set_item_navmesh);
+ ClassDB::bind_method(D_METHOD("set_item_shape","id","shape:Shape"),&MeshLibrary::set_item_shape);
+ ClassDB::bind_method(D_METHOD("get_item_name","id"),&MeshLibrary::get_item_name);
+ ClassDB::bind_method(D_METHOD("get_item_mesh:Mesh","id"),&MeshLibrary::get_item_mesh);
+ ClassDB::bind_method(D_METHOD("get_item_navmesh:NavigationMesh","id"),&MeshLibrary::get_item_navmesh);
+ ClassDB::bind_method(D_METHOD("get_item_shape:Shape","id"),&MeshLibrary::get_item_shape);
+ ClassDB::bind_method(D_METHOD("remove_item","id"),&MeshLibrary::remove_item);
+ ClassDB::bind_method(D_METHOD("clear"),&MeshLibrary::clear);
+ ClassDB::bind_method(D_METHOD("get_item_list"),&MeshLibrary::get_item_list);
+ ClassDB::bind_method(D_METHOD("get_last_unused_item_id"),&MeshLibrary::get_last_unused_item_id);
}
MeshLibrary::MeshLibrary() {
diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp
index 75df4a4e60..69ef3f18a6 100644
--- a/scene/resources/multimesh.cpp
+++ b/scene/resources/multimesh.cpp
@@ -211,34 +211,34 @@ MultiMesh::TransformFormat MultiMesh::get_transform_format() const{
void MultiMesh::_bind_methods() {
- ClassDB::bind_method(_MD("set_mesh","mesh:Mesh"),&MultiMesh::set_mesh);
- ClassDB::bind_method(_MD("get_mesh:Mesh"),&MultiMesh::get_mesh);
- ClassDB::bind_method(_MD("set_color_format","format"),&MultiMesh::set_color_format);
- ClassDB::bind_method(_MD("get_color_format"),&MultiMesh::get_color_format);
- ClassDB::bind_method(_MD("set_transform_format","format"),&MultiMesh::set_transform_format);
- ClassDB::bind_method(_MD("get_transform_format"),&MultiMesh::get_transform_format);
-
- ClassDB::bind_method(_MD("set_instance_count","count"),&MultiMesh::set_instance_count);
- ClassDB::bind_method(_MD("get_instance_count"),&MultiMesh::get_instance_count);
- ClassDB::bind_method(_MD("set_instance_transform","instance","transform"),&MultiMesh::set_instance_transform);
- ClassDB::bind_method(_MD("get_instance_transform","instance"),&MultiMesh::get_instance_transform);
- ClassDB::bind_method(_MD("set_instance_color","instance","color"),&MultiMesh::set_instance_color);
- ClassDB::bind_method(_MD("get_instance_color","instance"),&MultiMesh::get_instance_color);
- ClassDB::bind_method(_MD("get_aabb"),&MultiMesh::get_aabb);
-
-
- ClassDB::bind_method(_MD("_set_transform_array"),&MultiMesh::_set_transform_array);
- ClassDB::bind_method(_MD("_get_transform_array"),&MultiMesh::_get_transform_array);
- ClassDB::bind_method(_MD("_set_color_array"),&MultiMesh::_set_color_array);
- ClassDB::bind_method(_MD("_get_color_array"),&MultiMesh::_get_color_array);
-
-
- ADD_PROPERTY(PropertyInfo(Variant::INT,"color_format",PROPERTY_HINT_ENUM,"None,Byte,Float"), _SCS("set_color_format"), _SCS("get_color_format"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"transform_format",PROPERTY_HINT_ENUM,"2D,3D"), _SCS("set_transform_format"), _SCS("get_transform_format"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"instance_count",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_instance_count"), _SCS("get_instance_count"));
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"mesh",PROPERTY_HINT_RESOURCE_TYPE,"Mesh"), _SCS("set_mesh"), _SCS("get_mesh"));
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY,"transform_array",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_transform_array"), _SCS("_get_transform_array"));
- ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY,"color_array",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_color_array"), _SCS("_get_color_array"));
+ ClassDB::bind_method(D_METHOD("set_mesh","mesh:Mesh"),&MultiMesh::set_mesh);
+ ClassDB::bind_method(D_METHOD("get_mesh:Mesh"),&MultiMesh::get_mesh);
+ ClassDB::bind_method(D_METHOD("set_color_format","format"),&MultiMesh::set_color_format);
+ ClassDB::bind_method(D_METHOD("get_color_format"),&MultiMesh::get_color_format);
+ ClassDB::bind_method(D_METHOD("set_transform_format","format"),&MultiMesh::set_transform_format);
+ ClassDB::bind_method(D_METHOD("get_transform_format"),&MultiMesh::get_transform_format);
+
+ ClassDB::bind_method(D_METHOD("set_instance_count","count"),&MultiMesh::set_instance_count);
+ ClassDB::bind_method(D_METHOD("get_instance_count"),&MultiMesh::get_instance_count);
+ ClassDB::bind_method(D_METHOD("set_instance_transform","instance","transform"),&MultiMesh::set_instance_transform);
+ ClassDB::bind_method(D_METHOD("get_instance_transform","instance"),&MultiMesh::get_instance_transform);
+ ClassDB::bind_method(D_METHOD("set_instance_color","instance","color"),&MultiMesh::set_instance_color);
+ ClassDB::bind_method(D_METHOD("get_instance_color","instance"),&MultiMesh::get_instance_color);
+ ClassDB::bind_method(D_METHOD("get_aabb"),&MultiMesh::get_aabb);
+
+
+ ClassDB::bind_method(D_METHOD("_set_transform_array"),&MultiMesh::_set_transform_array);
+ ClassDB::bind_method(D_METHOD("_get_transform_array"),&MultiMesh::_get_transform_array);
+ ClassDB::bind_method(D_METHOD("_set_color_array"),&MultiMesh::_set_color_array);
+ ClassDB::bind_method(D_METHOD("_get_color_array"),&MultiMesh::_get_color_array);
+
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"color_format",PROPERTY_HINT_ENUM,"None,Byte,Float"), "set_color_format", "get_color_format");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"transform_format",PROPERTY_HINT_ENUM,"2D,3D"), "set_transform_format", "get_transform_format");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"instance_count",PROPERTY_HINT_RANGE,"0,16384,1"), "set_instance_count", "get_instance_count");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"mesh",PROPERTY_HINT_RESOURCE_TYPE,"Mesh"), "set_mesh", "get_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY,"transform_array",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_transform_array", "_get_transform_array");
+ ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY,"color_array",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_color_array", "_get_color_array");
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 2707dd6198..5e3347687a 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "packed_scene.h"
-#include "globals.h"
+#include "global_config.h"
#include "io/resource_loader.h"
#include "scene/3d/spatial.h"
#include "scene/gui/control.h"
@@ -177,6 +177,9 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
node = obj->cast_to<Node>();
+ } else {
+ print_line("wtf class is disabled for: "+itos(n.type));
+ print_line("name: "+String(snames[n.type]));
}
@@ -196,6 +199,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
ERR_FAIL_INDEX_V( nprops[j].name, sname_count, NULL );
ERR_FAIL_INDEX_V( nprops[j].value, prop_count, NULL );
+
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
@@ -357,7 +361,7 @@ static int _nm_get_string(const String& p_string, Map<StringName,int> &name_map)
return idx;
}
-static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher> &variant_map) {
+static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,VariantHasher,VariantComparator> &variant_map) {
if (variant_map.has(p_variant))
return variant_map[p_variant];
@@ -367,7 +371,7 @@ static int _vm_get_variant(const Variant& p_variant, HashMap<Variant,int,Variant
return idx;
}
-Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map) {
+Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher,VariantComparator> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map) {
// this function handles all the work related to properly packing scenes, be it
@@ -743,7 +747,7 @@ Error SceneState::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<S
}
-Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map) {
+Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher,VariantComparator> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map) {
if (p_node!=p_owner && p_node->get_owner() && p_node->get_owner()!=p_owner && !p_owner->is_editable_instance(p_node->get_owner()))
return OK;
@@ -948,7 +952,7 @@ Error SceneState::pack(Node *p_scene) {
Node *scene = p_scene;
Map<StringName,int> name_map;
- HashMap<Variant,int,VariantHasher> variant_map;
+ HashMap<Variant,int,VariantHasher,VariantComparator> variant_map;
Map<Node*,int> node_map;
Map<Node*,int> nodepath_map;
@@ -1716,25 +1720,25 @@ void SceneState::_bind_methods() {
//unbuild API
- ClassDB::bind_method(_MD("get_node_count"),&SceneState::get_node_count);
- ClassDB::bind_method(_MD("get_node_type","idx"),&SceneState::get_node_type);
- ClassDB::bind_method(_MD("get_node_name","idx"),&SceneState::get_node_name);
- ClassDB::bind_method(_MD("get_node_path","idx","for_parent"),&SceneState::get_node_path,DEFVAL(false));
- ClassDB::bind_method(_MD("get_node_owner_path","idx"),&SceneState::get_node_owner_path);
- ClassDB::bind_method(_MD("is_node_instance_placeholder","idx"),&SceneState::is_node_instance_placeholder);
- ClassDB::bind_method(_MD("get_node_instance_placeholder","idx"),&SceneState::get_node_instance_placeholder);
- ClassDB::bind_method(_MD("get_node_instance:PackedScene","idx"),&SceneState::get_node_instance);
- ClassDB::bind_method(_MD("get_node_groups","idx"),&SceneState::_get_node_groups);
- ClassDB::bind_method(_MD("get_node_property_count","idx"),&SceneState::get_node_property_count);
- ClassDB::bind_method(_MD("get_node_property_name","idx","prop_idx"),&SceneState::get_node_property_name);
- ClassDB::bind_method(_MD("get_node_property_value","idx","prop_idx"),&SceneState::get_node_property_value);
- ClassDB::bind_method(_MD("get_connection_count"),&SceneState::get_connection_count);
- ClassDB::bind_method(_MD("get_connection_source","idx"),&SceneState::get_connection_source);
- ClassDB::bind_method(_MD("get_connection_signal","idx"),&SceneState::get_connection_signal);
- ClassDB::bind_method(_MD("get_connection_target","idx"),&SceneState::get_connection_target);
- ClassDB::bind_method(_MD("get_connection_method","idx"),&SceneState::get_connection_method);
- ClassDB::bind_method(_MD("get_connection_flags","idx"),&SceneState::get_connection_flags);
- ClassDB::bind_method(_MD("get_connection_binds","idx"),&SceneState::get_connection_binds);
+ ClassDB::bind_method(D_METHOD("get_node_count"),&SceneState::get_node_count);
+ ClassDB::bind_method(D_METHOD("get_node_type","idx"),&SceneState::get_node_type);
+ ClassDB::bind_method(D_METHOD("get_node_name","idx"),&SceneState::get_node_name);
+ ClassDB::bind_method(D_METHOD("get_node_path","idx","for_parent"),&SceneState::get_node_path,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_node_owner_path","idx"),&SceneState::get_node_owner_path);
+ ClassDB::bind_method(D_METHOD("is_node_instance_placeholder","idx"),&SceneState::is_node_instance_placeholder);
+ ClassDB::bind_method(D_METHOD("get_node_instance_placeholder","idx"),&SceneState::get_node_instance_placeholder);
+ ClassDB::bind_method(D_METHOD("get_node_instance:PackedScene","idx"),&SceneState::get_node_instance);
+ ClassDB::bind_method(D_METHOD("get_node_groups","idx"),&SceneState::_get_node_groups);
+ ClassDB::bind_method(D_METHOD("get_node_property_count","idx"),&SceneState::get_node_property_count);
+ ClassDB::bind_method(D_METHOD("get_node_property_name","idx","prop_idx"),&SceneState::get_node_property_name);
+ ClassDB::bind_method(D_METHOD("get_node_property_value","idx","prop_idx"),&SceneState::get_node_property_value);
+ ClassDB::bind_method(D_METHOD("get_connection_count"),&SceneState::get_connection_count);
+ ClassDB::bind_method(D_METHOD("get_connection_source","idx"),&SceneState::get_connection_source);
+ ClassDB::bind_method(D_METHOD("get_connection_signal","idx"),&SceneState::get_connection_signal);
+ ClassDB::bind_method(D_METHOD("get_connection_target","idx"),&SceneState::get_connection_target);
+ ClassDB::bind_method(D_METHOD("get_connection_method","idx"),&SceneState::get_connection_method);
+ ClassDB::bind_method(D_METHOD("get_connection_flags","idx"),&SceneState::get_connection_flags);
+ ClassDB::bind_method(D_METHOD("get_connection_binds","idx"),&SceneState::get_connection_binds);
BIND_CONSTANT( GEN_EDIT_STATE_DISABLED );
BIND_CONSTANT( GEN_EDIT_STATE_INSTANCE );
@@ -1837,14 +1841,14 @@ void PackedScene::set_path(const String& p_path,bool p_take_over) {
void PackedScene::_bind_methods() {
- ClassDB::bind_method(_MD("pack","path:Node"),&PackedScene::pack);
- ClassDB::bind_method(_MD("instance:Node","edit_state"),&PackedScene::instance,DEFVAL(false));
- ClassDB::bind_method(_MD("can_instance"),&PackedScene::can_instance);
- ClassDB::bind_method(_MD("_set_bundled_scene"),&PackedScene::_set_bundled_scene);
- ClassDB::bind_method(_MD("_get_bundled_scene"),&PackedScene::_get_bundled_scene);
- ClassDB::bind_method(_MD("get_state:SceneState"),&PackedScene::get_state);
+ ClassDB::bind_method(D_METHOD("pack","path:Node"),&PackedScene::pack);
+ ClassDB::bind_method(D_METHOD("instance:Node","edit_state"),&PackedScene::instance,DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("can_instance"),&PackedScene::can_instance);
+ ClassDB::bind_method(D_METHOD("_set_bundled_scene"),&PackedScene::_set_bundled_scene);
+ ClassDB::bind_method(D_METHOD("_get_bundled_scene"),&PackedScene::_get_bundled_scene);
+ ClassDB::bind_method(D_METHOD("get_state:SceneState"),&PackedScene::get_state);
- ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled"),_SCS("_set_bundled_scene"),_SCS("_get_bundled_scene"));
+ ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_bundled"),"_set_bundled_scene","_get_bundled_scene");
BIND_CONSTANT( GEN_EDIT_STATE_DISABLED );
BIND_CONSTANT( GEN_EDIT_STATE_INSTANCE );
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index 381b356b1e..4a3841abe9 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -91,8 +91,8 @@ class SceneState : public Reference {
Vector<ConnectionData> connections;
- Error _parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map);
- Error _parse_connections(Node *p_owner,Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map);
+ Error _parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher,VariantComparator> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map);
+ Error _parse_connections(Node *p_owner,Node *p_node, Map<StringName,int> &name_map,HashMap<Variant,int,VariantHasher,VariantComparator> &variant_map,Map<Node*,int> &node_map,Map<Node*,int> &nodepath_map);
String path;
diff --git a/scene/resources/plane_shape.cpp b/scene/resources/plane_shape.cpp
index 1814eea66c..f1bb6d60c0 100644
--- a/scene/resources/plane_shape.cpp
+++ b/scene/resources/plane_shape.cpp
@@ -80,10 +80,10 @@ Plane PlaneShape::get_plane() const {
void PlaneShape::_bind_methods() {
- ClassDB::bind_method(_MD("set_plane","plane"),&PlaneShape::set_plane);
- ClassDB::bind_method(_MD("get_plane"),&PlaneShape::get_plane);
+ ClassDB::bind_method(D_METHOD("set_plane","plane"),&PlaneShape::set_plane);
+ ClassDB::bind_method(D_METHOD("get_plane"),&PlaneShape::get_plane);
- ADD_PROPERTY( PropertyInfo(Variant::PLANE,"plane"), _SCS("set_plane"), _SCS("get_plane") );
+ ADD_PROPERTY( PropertyInfo(Variant::PLANE,"plane"), "set_plane", "get_plane") ;
}
diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp
index 568f086d34..6dac8a9779 100644
--- a/scene/resources/polygon_path_finder.cpp
+++ b/scene/resources/polygon_path_finder.cpp
@@ -618,19 +618,19 @@ float PolygonPathFinder::get_point_penalty(int p_point) const {
void PolygonPathFinder::_bind_methods() {
- ClassDB::bind_method(_MD("setup","points","connections"),&PolygonPathFinder::setup);
- ClassDB::bind_method(_MD("find_path","from","to"),&PolygonPathFinder::find_path);
- ClassDB::bind_method(_MD("get_intersections","from","to"),&PolygonPathFinder::get_intersections);
- ClassDB::bind_method(_MD("get_closest_point","point"),&PolygonPathFinder::get_closest_point);
- ClassDB::bind_method(_MD("is_point_inside","point"),&PolygonPathFinder::is_point_inside);
- ClassDB::bind_method(_MD("set_point_penalty","idx","penalty"),&PolygonPathFinder::set_point_penalty);
- ClassDB::bind_method(_MD("get_point_penalty","idx"),&PolygonPathFinder::get_point_penalty);
-
- ClassDB::bind_method(_MD("get_bounds"),&PolygonPathFinder::get_bounds);
- ClassDB::bind_method(_MD("_set_data"),&PolygonPathFinder::_set_data);
- ClassDB::bind_method(_MD("_get_data"),&PolygonPathFinder::_get_data);
-
- ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_data"),_SCS("_get_data"));
+ ClassDB::bind_method(D_METHOD("setup","points","connections"),&PolygonPathFinder::setup);
+ ClassDB::bind_method(D_METHOD("find_path","from","to"),&PolygonPathFinder::find_path);
+ ClassDB::bind_method(D_METHOD("get_intersections","from","to"),&PolygonPathFinder::get_intersections);
+ ClassDB::bind_method(D_METHOD("get_closest_point","point"),&PolygonPathFinder::get_closest_point);
+ ClassDB::bind_method(D_METHOD("is_point_inside","point"),&PolygonPathFinder::is_point_inside);
+ ClassDB::bind_method(D_METHOD("set_point_penalty","idx","penalty"),&PolygonPathFinder::set_point_penalty);
+ ClassDB::bind_method(D_METHOD("get_point_penalty","idx"),&PolygonPathFinder::get_point_penalty);
+
+ ClassDB::bind_method(D_METHOD("get_bounds"),&PolygonPathFinder::get_bounds);
+ ClassDB::bind_method(D_METHOD("_set_data"),&PolygonPathFinder::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"),&PolygonPathFinder::_get_data);
+
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),"_set_data","_get_data");
}
diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp
index 226062bed3..52ce736925 100644
--- a/scene/resources/ray_shape.cpp
+++ b/scene/resources/ray_shape.cpp
@@ -60,10 +60,10 @@ float RayShape::get_length() const {
void RayShape::_bind_methods() {
- ClassDB::bind_method(_MD("set_length","length"),&RayShape::set_length);
- ClassDB::bind_method(_MD("get_length"),&RayShape::get_length);
+ ClassDB::bind_method(D_METHOD("set_length","length"),&RayShape::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"),&RayShape::get_length);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"length",PROPERTY_HINT_RANGE,"0,4096,0.01"), _SCS("set_length"), _SCS("get_length") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"length",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_length", "get_length") ;
}
diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp
index 3272125b33..1161843a2b 100644
--- a/scene/resources/rectangle_shape_2d.cpp
+++ b/scene/resources/rectangle_shape_2d.cpp
@@ -64,12 +64,12 @@ Rect2 RectangleShape2D::get_rect() const {
void RectangleShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_extents","extents"),&RectangleShape2D::set_extents);
- ClassDB::bind_method(_MD("get_extents"),&RectangleShape2D::get_extents);
+ ClassDB::bind_method(D_METHOD("set_extents","extents"),&RectangleShape2D::set_extents);
+ ClassDB::bind_method(D_METHOD("get_extents"),&RectangleShape2D::get_extents);
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"extents"),_SCS("set_extents"),_SCS("get_extents") );
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"extents"),"set_extents","get_extents") ;
}
diff --git a/scene/resources/room.cpp b/scene/resources/room.cpp
index 069127f291..e677f92c31 100644
--- a/scene/resources/room.cpp
+++ b/scene/resources/room.cpp
@@ -52,11 +52,11 @@ PoolVector<Face3> RoomBounds::get_geometry_hint() const {
void RoomBounds::_bind_methods() {
- ClassDB::bind_method(_MD("set_geometry_hint","triangles"),&RoomBounds::set_geometry_hint);
- ClassDB::bind_method(_MD("get_geometry_hint"),&RoomBounds::get_geometry_hint);
+ ClassDB::bind_method(D_METHOD("set_geometry_hint","triangles"),&RoomBounds::set_geometry_hint);
+ ClassDB::bind_method(D_METHOD("get_geometry_hint"),&RoomBounds::get_geometry_hint);
- //ADD_PROPERTY( PropertyInfo( Variant::DICTIONARY, "bounds"), _SCS("set_bounds"),_SCS("get_bounds") );
- ADD_PROPERTY( PropertyInfo( Variant::POOL_VECTOR3_ARRAY, "geometry_hint"),_SCS("set_geometry_hint"),_SCS("get_geometry_hint") );
+ //ADD_PROPERTY( PropertyInfo( Variant::DICTIONARY, "bounds"), "set_bounds","get_bounds") ;
+ ADD_PROPERTY( PropertyInfo( Variant::POOL_VECTOR3_ARRAY, "geometry_hint"),"set_geometry_hint","get_geometry_hint") ;
}
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index 9719f321d6..3a254836a2 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "scene_format_text.h"
-#include "globals.h"
+#include "global_config.h"
#include "version.h"
#include "os/dir_access.h"
diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp
index 71d5a8efa8..fbe1efe5d1 100644
--- a/scene/resources/segment_shape_2d.cpp
+++ b/scene/resources/segment_shape_2d.cpp
@@ -82,15 +82,15 @@ Rect2 SegmentShape2D::get_rect() const{
void SegmentShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_a","a"),&SegmentShape2D::set_a);
- ClassDB::bind_method(_MD("get_a"),&SegmentShape2D::get_a);
+ ClassDB::bind_method(D_METHOD("set_a","a"),&SegmentShape2D::set_a);
+ ClassDB::bind_method(D_METHOD("get_a"),&SegmentShape2D::get_a);
- ClassDB::bind_method(_MD("set_b","b"),&SegmentShape2D::set_b);
- ClassDB::bind_method(_MD("get_b"),&SegmentShape2D::get_b);
+ ClassDB::bind_method(D_METHOD("set_b","b"),&SegmentShape2D::set_b);
+ ClassDB::bind_method(D_METHOD("get_b"),&SegmentShape2D::get_b);
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"a"),_SCS("set_a"),_SCS("get_a") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"b"),_SCS("set_b"),_SCS("get_b") );
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"a"),"set_a","get_a") ;
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"b"),"set_b","get_b") ;
}
@@ -145,10 +145,10 @@ Rect2 RayShape2D::get_rect() const {
void RayShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_length","length"),&RayShape2D::set_length);
- ClassDB::bind_method(_MD("get_length"),&RayShape2D::get_length);
+ ClassDB::bind_method(D_METHOD("set_length","length"),&RayShape2D::set_length);
+ ClassDB::bind_method(D_METHOD("get_length"),&RayShape2D::get_length);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"length"),_SCS("set_length"),_SCS("get_length") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"length"),"set_length","get_length") ;
}
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 6afbf32c35..375a9a1cb0 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -116,20 +116,20 @@ bool Shader::has_param(const StringName& p_param) const {
void Shader::_bind_methods() {
- ClassDB::bind_method(_MD("get_mode"),&Shader::get_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&Shader::get_mode);
- ClassDB::bind_method(_MD("set_code","code"),&Shader::set_code);
- ClassDB::bind_method(_MD("get_code"),&Shader::get_code);
+ ClassDB::bind_method(D_METHOD("set_code","code"),&Shader::set_code);
+ ClassDB::bind_method(D_METHOD("get_code"),&Shader::get_code);
- ClassDB::bind_method(_MD("set_default_texture_param","param","texture:Texture"),&Shader::set_default_texture_param);
- ClassDB::bind_method(_MD("get_default_texture_param:Texture","param"),&Shader::get_default_texture_param);
+ ClassDB::bind_method(D_METHOD("set_default_texture_param","param","texture:Texture"),&Shader::set_default_texture_param);
+ ClassDB::bind_method(D_METHOD("get_default_texture_param:Texture","param"),&Shader::get_default_texture_param);
- ClassDB::bind_method(_MD("has_param","name"),&Shader::has_param);
+ ClassDB::bind_method(D_METHOD("has_param","name"),&Shader::has_param);
- //ClassDB::bind_method(_MD("get_param_list"),&Shader::get_fragment_code);
+ //ClassDB::bind_method(D_METHOD("get_param_list"),&Shader::get_fragment_code);
- ADD_PROPERTY( PropertyInfo(Variant::STRING, "code",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("set_code"), _SCS("get_code") );
+ ADD_PROPERTY( PropertyInfo(Variant::STRING, "code",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "set_code", "get_code") ;
BIND_CONSTANT( MODE_SPATIAL);
BIND_CONSTANT( MODE_CANVAS_ITEM );
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index 22ee253b1a..c21feb0bf5 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -165,108 +165,108 @@ int ShaderGraph::node_count(ShaderType p_which, int p_type)
void ShaderGraph::_bind_methods() {
- ClassDB::bind_method(_MD("_update_shader"),&ShaderGraph::_update_shader);
+ ClassDB::bind_method(D_METHOD("_update_shader"),&ShaderGraph::_update_shader);
- ClassDB::bind_method(_MD("node_add","shader_type","node_type","id"),&ShaderGraph::node_add);
- ClassDB::bind_method(_MD("node_remove","shader_type","id"),&ShaderGraph::node_remove);
- ClassDB::bind_method(_MD("node_set_pos","shader_type","id","pos"),&ShaderGraph::node_set_pos);
- ClassDB::bind_method(_MD("node_get_pos","shader_type","id"),&ShaderGraph::node_get_pos);
+ ClassDB::bind_method(D_METHOD("node_add","shader_type","node_type","id"),&ShaderGraph::node_add);
+ ClassDB::bind_method(D_METHOD("node_remove","shader_type","id"),&ShaderGraph::node_remove);
+ ClassDB::bind_method(D_METHOD("node_set_pos","shader_type","id","pos"),&ShaderGraph::node_set_pos);
+ ClassDB::bind_method(D_METHOD("node_get_pos","shader_type","id"),&ShaderGraph::node_get_pos);
- ClassDB::bind_method(_MD("node_get_type","shader_type","id"),&ShaderGraph::node_get_type);
+ ClassDB::bind_method(D_METHOD("node_get_type","shader_type","id"),&ShaderGraph::node_get_type);
- ClassDB::bind_method(_MD("get_node_list","shader_type"),&ShaderGraph::_get_node_list);
+ ClassDB::bind_method(D_METHOD("get_node_list","shader_type"),&ShaderGraph::_get_node_list);
- ClassDB::bind_method(_MD("default_set_value","shader_type","id","param_id","value"), &ShaderGraph::default_set_value);
- ClassDB::bind_method(_MD("default_get_value","shader_type","id","param_id"), &ShaderGraph::default_get_value);
+ ClassDB::bind_method(D_METHOD("default_set_value","shader_type","id","param_id","value"), &ShaderGraph::default_set_value);
+ ClassDB::bind_method(D_METHOD("default_get_value","shader_type","id","param_id"), &ShaderGraph::default_get_value);
- ClassDB::bind_method(_MD("scalar_const_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_const_node_set_value);
- ClassDB::bind_method(_MD("scalar_const_node_get_value","shader_type","id"),&ShaderGraph::scalar_const_node_get_value);
+ ClassDB::bind_method(D_METHOD("scalar_const_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_const_node_set_value);
+ ClassDB::bind_method(D_METHOD("scalar_const_node_get_value","shader_type","id"),&ShaderGraph::scalar_const_node_get_value);
- ClassDB::bind_method(_MD("vec_const_node_set_value","shader_type","id","value"),&ShaderGraph::vec_const_node_set_value);
- ClassDB::bind_method(_MD("vec_const_node_get_value","shader_type","id"),&ShaderGraph::vec_const_node_get_value);
+ ClassDB::bind_method(D_METHOD("vec_const_node_set_value","shader_type","id","value"),&ShaderGraph::vec_const_node_set_value);
+ ClassDB::bind_method(D_METHOD("vec_const_node_get_value","shader_type","id"),&ShaderGraph::vec_const_node_get_value);
- ClassDB::bind_method(_MD("rgb_const_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_const_node_set_value);
- ClassDB::bind_method(_MD("rgb_const_node_get_value","shader_type","id"),&ShaderGraph::rgb_const_node_get_value);
+ ClassDB::bind_method(D_METHOD("rgb_const_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_const_node_set_value);
+ ClassDB::bind_method(D_METHOD("rgb_const_node_get_value","shader_type","id"),&ShaderGraph::rgb_const_node_get_value);
- ClassDB::bind_method(_MD("xform_const_node_set_value","shader_type","id","value"),&ShaderGraph::xform_const_node_set_value);
- ClassDB::bind_method(_MD("xform_const_node_get_value","shader_type","id"),&ShaderGraph::xform_const_node_get_value);
+ ClassDB::bind_method(D_METHOD("xform_const_node_set_value","shader_type","id","value"),&ShaderGraph::xform_const_node_set_value);
+ ClassDB::bind_method(D_METHOD("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;
- ClassDB::bind_method(_MD("texture_node_set_filter_size","shader_type","id","filter_size"),&ShaderGraph::texture_node_set_filter_size);
- ClassDB::bind_method(_MD("texture_node_get_filter_size","shader_type","id"),&ShaderGraph::texture_node_get_filter_size);
+ ClassDB::bind_method(D_METHOD("texture_node_set_filter_size","shader_type","id","filter_size"),&ShaderGraph::texture_node_set_filter_size);
+ ClassDB::bind_method(D_METHOD("texture_node_get_filter_size","shader_type","id"),&ShaderGraph::texture_node_get_filter_size);
- ClassDB::bind_method(_MD("texture_node_set_filter_strength","shader_type","id","filter_strength"),&ShaderGraph::texture_node_set_filter_strength);
- ClassDB::bind_method(_MD("texture_node_get_filter_strength","shader_type","id"),&ShaderGraph::texture_node_get_filter_strength);
+ ClassDB::bind_method(D_METHOD("texture_node_set_filter_strength","shader_type","id","filter_strength"),&ShaderGraph::texture_node_set_filter_strength);
+ ClassDB::bind_method(D_METHOD("texture_node_get_filter_strength","shader_type","id"),&ShaderGraph::texture_node_get_filter_strength);
- ClassDB::bind_method(_MD("scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::scalar_op_node_set_op);
- ClassDB::bind_method(_MD("scalar_op_node_get_op","shader_type","id"),&ShaderGraph::scalar_op_node_get_op);
+ ClassDB::bind_method(D_METHOD("scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::scalar_op_node_set_op);
+ ClassDB::bind_method(D_METHOD("scalar_op_node_get_op","shader_type","id"),&ShaderGraph::scalar_op_node_get_op);
- ClassDB::bind_method(_MD("vec_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_op_node_set_op);
- ClassDB::bind_method(_MD("vec_op_node_get_op","shader_type","id"),&ShaderGraph::vec_op_node_get_op);
+ ClassDB::bind_method(D_METHOD("vec_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_op_node_set_op);
+ ClassDB::bind_method(D_METHOD("vec_op_node_get_op","shader_type","id"),&ShaderGraph::vec_op_node_get_op);
- ClassDB::bind_method(_MD("vec_scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_scalar_op_node_set_op);
- ClassDB::bind_method(_MD("vec_scalar_op_node_get_op","shader_type","id"),&ShaderGraph::vec_scalar_op_node_get_op);
+ ClassDB::bind_method(D_METHOD("vec_scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_scalar_op_node_set_op);
+ ClassDB::bind_method(D_METHOD("vec_scalar_op_node_get_op","shader_type","id"),&ShaderGraph::vec_scalar_op_node_get_op);
- ClassDB::bind_method(_MD("rgb_op_node_set_op","shader_type","id","op"),&ShaderGraph::rgb_op_node_set_op);
- ClassDB::bind_method(_MD("rgb_op_node_get_op","shader_type","id"),&ShaderGraph::rgb_op_node_get_op);
+ ClassDB::bind_method(D_METHOD("rgb_op_node_set_op","shader_type","id","op"),&ShaderGraph::rgb_op_node_set_op);
+ ClassDB::bind_method(D_METHOD("rgb_op_node_get_op","shader_type","id"),&ShaderGraph::rgb_op_node_get_op);
- ClassDB::bind_method(_MD("xform_vec_mult_node_set_no_translation","shader_type","id","disable"),&ShaderGraph::xform_vec_mult_node_set_no_translation);
- ClassDB::bind_method(_MD("xform_vec_mult_node_get_no_translation","shader_type","id"),&ShaderGraph::xform_vec_mult_node_get_no_translation);
+ ClassDB::bind_method(D_METHOD("xform_vec_mult_node_set_no_translation","shader_type","id","disable"),&ShaderGraph::xform_vec_mult_node_set_no_translation);
+ ClassDB::bind_method(D_METHOD("xform_vec_mult_node_get_no_translation","shader_type","id"),&ShaderGraph::xform_vec_mult_node_get_no_translation);
- ClassDB::bind_method(_MD("scalar_func_node_set_function","shader_type","id","func"),&ShaderGraph::scalar_func_node_set_function);
- ClassDB::bind_method(_MD("scalar_func_node_get_function","shader_type","id"),&ShaderGraph::scalar_func_node_get_function);
+ ClassDB::bind_method(D_METHOD("scalar_func_node_set_function","shader_type","id","func"),&ShaderGraph::scalar_func_node_set_function);
+ ClassDB::bind_method(D_METHOD("scalar_func_node_get_function","shader_type","id"),&ShaderGraph::scalar_func_node_get_function);
- ClassDB::bind_method(_MD("vec_func_node_set_function","shader_type","id","func"),&ShaderGraph::vec_func_node_set_function);
- ClassDB::bind_method(_MD("vec_func_node_get_function","shader_type","id"),&ShaderGraph::vec_func_node_get_function);
+ ClassDB::bind_method(D_METHOD("vec_func_node_set_function","shader_type","id","func"),&ShaderGraph::vec_func_node_set_function);
+ ClassDB::bind_method(D_METHOD("vec_func_node_get_function","shader_type","id"),&ShaderGraph::vec_func_node_get_function);
- ClassDB::bind_method(_MD("input_node_set_name","shader_type","id","name"),&ShaderGraph::input_node_set_name);
- ClassDB::bind_method(_MD("input_node_get_name","shader_type","id"),&ShaderGraph::input_node_get_name);
+ ClassDB::bind_method(D_METHOD("input_node_set_name","shader_type","id","name"),&ShaderGraph::input_node_set_name);
+ ClassDB::bind_method(D_METHOD("input_node_get_name","shader_type","id"),&ShaderGraph::input_node_get_name);
- ClassDB::bind_method(_MD("scalar_input_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_input_node_set_value);
- ClassDB::bind_method(_MD("scalar_input_node_get_value","shader_type","id"),&ShaderGraph::scalar_input_node_get_value);
+ ClassDB::bind_method(D_METHOD("scalar_input_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_input_node_set_value);
+ ClassDB::bind_method(D_METHOD("scalar_input_node_get_value","shader_type","id"),&ShaderGraph::scalar_input_node_get_value);
- ClassDB::bind_method(_MD("vec_input_node_set_value","shader_type","id","value"),&ShaderGraph::vec_input_node_set_value);
- ClassDB::bind_method(_MD("vec_input_node_get_value","shader_type","id"),&ShaderGraph::vec_input_node_get_value);
+ ClassDB::bind_method(D_METHOD("vec_input_node_set_value","shader_type","id","value"),&ShaderGraph::vec_input_node_set_value);
+ ClassDB::bind_method(D_METHOD("vec_input_node_get_value","shader_type","id"),&ShaderGraph::vec_input_node_get_value);
- ClassDB::bind_method(_MD("rgb_input_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_input_node_set_value);
- ClassDB::bind_method(_MD("rgb_input_node_get_value","shader_type","id"),&ShaderGraph::rgb_input_node_get_value);
+ ClassDB::bind_method(D_METHOD("rgb_input_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_input_node_set_value);
+ ClassDB::bind_method(D_METHOD("rgb_input_node_get_value","shader_type","id"),&ShaderGraph::rgb_input_node_get_value);
- ClassDB::bind_method(_MD("xform_input_node_set_value","shader_type","id","value"),&ShaderGraph::xform_input_node_set_value);
- ClassDB::bind_method(_MD("xform_input_node_get_value","shader_type","id"),&ShaderGraph::xform_input_node_get_value);
+ ClassDB::bind_method(D_METHOD("xform_input_node_set_value","shader_type","id","value"),&ShaderGraph::xform_input_node_set_value);
+ ClassDB::bind_method(D_METHOD("xform_input_node_get_value","shader_type","id"),&ShaderGraph::xform_input_node_get_value);
- ClassDB::bind_method(_MD("texture_input_node_set_value","shader_type","id","value:Texture"),&ShaderGraph::texture_input_node_set_value);
- ClassDB::bind_method(_MD("texture_input_node_get_value:Texture","shader_type","id"),&ShaderGraph::texture_input_node_get_value);
+ ClassDB::bind_method(D_METHOD("texture_input_node_set_value","shader_type","id","value:Texture"),&ShaderGraph::texture_input_node_set_value);
+ ClassDB::bind_method(D_METHOD("texture_input_node_get_value:Texture","shader_type","id"),&ShaderGraph::texture_input_node_get_value);
- ClassDB::bind_method(_MD("cubemap_input_node_set_value","shader_type","id","value:CubeMap"),&ShaderGraph::cubemap_input_node_set_value);
- ClassDB::bind_method(_MD("cubemap_input_node_get_value:CubeMap","shader_type","id"),&ShaderGraph::cubemap_input_node_get_value);
+ ClassDB::bind_method(D_METHOD("cubemap_input_node_set_value","shader_type","id","value:CubeMap"),&ShaderGraph::cubemap_input_node_set_value);
+ ClassDB::bind_method(D_METHOD("cubemap_input_node_get_value:CubeMap","shader_type","id"),&ShaderGraph::cubemap_input_node_get_value);
- ClassDB::bind_method(_MD("comment_node_set_text","shader_type","id","text"),&ShaderGraph::comment_node_set_text);
- ClassDB::bind_method(_MD("comment_node_get_text","shader_type","id"),&ShaderGraph::comment_node_get_text);
+ ClassDB::bind_method(D_METHOD("comment_node_set_text","shader_type","id","text"),&ShaderGraph::comment_node_set_text);
+ ClassDB::bind_method(D_METHOD("comment_node_get_text","shader_type","id"),&ShaderGraph::comment_node_get_text);
- ClassDB::bind_method(_MD("color_ramp_node_set_ramp","shader_type","id","colors","offsets"),&ShaderGraph::color_ramp_node_set_ramp);
- ClassDB::bind_method(_MD("color_ramp_node_get_colors","shader_type","id"),&ShaderGraph::color_ramp_node_get_colors);
- ClassDB::bind_method(_MD("color_ramp_node_get_offsets","shader_type","id"),&ShaderGraph::color_ramp_node_get_offsets);
+ ClassDB::bind_method(D_METHOD("color_ramp_node_set_ramp","shader_type","id","colors","offsets"),&ShaderGraph::color_ramp_node_set_ramp);
+ ClassDB::bind_method(D_METHOD("color_ramp_node_get_colors","shader_type","id"),&ShaderGraph::color_ramp_node_get_colors);
+ ClassDB::bind_method(D_METHOD("color_ramp_node_get_offsets","shader_type","id"),&ShaderGraph::color_ramp_node_get_offsets);
- ClassDB::bind_method(_MD("curve_map_node_set_points","shader_type","id","points"),&ShaderGraph::curve_map_node_set_points);
- ClassDB::bind_method(_MD("curve_map_node_get_points","shader_type","id"),&ShaderGraph::curve_map_node_get_points);
+ ClassDB::bind_method(D_METHOD("curve_map_node_set_points","shader_type","id","points"),&ShaderGraph::curve_map_node_set_points);
+ ClassDB::bind_method(D_METHOD("curve_map_node_get_points","shader_type","id"),&ShaderGraph::curve_map_node_get_points);
- ClassDB::bind_method(_MD("connect_node:Error","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::connect_node);
- ClassDB::bind_method(_MD("is_node_connected","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::is_node_connected);
- ClassDB::bind_method(_MD("disconnect_node","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::disconnect_node);
- ClassDB::bind_method(_MD("get_node_connections","shader_type"),&ShaderGraph::_get_connections);
+ ClassDB::bind_method(D_METHOD("connect_node:Error","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::connect_node);
+ ClassDB::bind_method(D_METHOD("is_node_connected","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::is_node_connected);
+ ClassDB::bind_method(D_METHOD("disconnect_node","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::disconnect_node);
+ ClassDB::bind_method(D_METHOD("get_node_connections","shader_type"),&ShaderGraph::_get_connections);
- ClassDB::bind_method(_MD("clear","shader_type"),&ShaderGraph::clear);
+ ClassDB::bind_method(D_METHOD("clear","shader_type"),&ShaderGraph::clear);
- ClassDB::bind_method(_MD("node_set_state","shader_type","id","state"),&ShaderGraph::node_set_state);
- ClassDB::bind_method(_MD("node_get_state:Variant","shader_type","id"),&ShaderGraph::node_get_state);
+ ClassDB::bind_method(D_METHOD("node_set_state","shader_type","id","state"),&ShaderGraph::node_set_state);
+ ClassDB::bind_method(D_METHOD("node_get_state:Variant","shader_type","id"),&ShaderGraph::node_get_state);
- ClassDB::bind_method(_MD("_set_data"),&ShaderGraph::_set_data);
- ClassDB::bind_method(_MD("_get_data"),&ShaderGraph::_get_data);
+ ClassDB::bind_method(D_METHOD("_set_data"),&ShaderGraph::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"),&ShaderGraph::_get_data);
- ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"),_SCS("_get_data"));
+ ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_data","_get_data");
//void get_connections(ShaderType p_which,List<Connection> *p_connections) const;
@@ -399,21 +399,21 @@ void ShaderGraph::_bind_methods() {
#if 0
- ClassDB::bind_method(_MD("node_add"),&ShaderGraph::node_add );
- ClassDB::bind_method(_MD("node_remove"),&ShaderGraph::node_remove );
- ClassDB::bind_method(_MD("node_set_param"),&ShaderGraph::node_set_param );
- ClassDB::bind_method(_MD("node_set_pos"),&ShaderGraph::node_set_pos );
+ ClassDB::bind_method(D_METHOD("node_add"),&ShaderGraph::node_add );
+ ClassDB::bind_method(D_METHOD("node_remove"),&ShaderGraph::node_remove );
+ ClassDB::bind_method(D_METHOD("node_set_param"),&ShaderGraph::node_set_param );
+ ClassDB::bind_method(D_METHOD("node_set_pos"),&ShaderGraph::node_set_pos );
- ClassDB::bind_method(_MD("node_get_pos"),&ShaderGraph::node_get_pos );
- ClassDB::bind_method(_MD("node_get_param"),&ShaderGraph::node_get_param);
- ClassDB::bind_method(_MD("node_get_type"),&ShaderGraph::node_get_type);
+ ClassDB::bind_method(D_METHOD("node_get_pos"),&ShaderGraph::node_get_pos );
+ ClassDB::bind_method(D_METHOD("node_get_param"),&ShaderGraph::node_get_param);
+ ClassDB::bind_method(D_METHOD("node_get_type"),&ShaderGraph::node_get_type);
- ClassDB::bind_method(_MD("connect"),&ShaderGraph::connect );
- ClassDB::bind_method(_MD("disconnect"),&ShaderGraph::disconnect );
+ ClassDB::bind_method(D_METHOD("connect"),&ShaderGraph::connect );
+ ClassDB::bind_method(D_METHOD("disconnect"),&ShaderGraph::disconnect );
- ClassDB::bind_method(_MD("get_connections"),&ShaderGraph::_get_connections_helper );
+ ClassDB::bind_method(D_METHOD("get_connections"),&ShaderGraph::_get_connections_helper );
- ClassDB::bind_method(_MD("clear"),&ShaderGraph::clear );
+ ClassDB::bind_method(D_METHOD("clear"),&ShaderGraph::clear );
BIND_CONSTANT( NODE_IN ); ///< param 0: name
BIND_CONSTANT( NODE_OUT ); ///< param 0: name
diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp
index b5a886b4b9..ec1568e218 100644
--- a/scene/resources/shape_2d.cpp
+++ b/scene/resources/shape_2d.cpp
@@ -104,14 +104,14 @@ Variant Shape2D::collide_and_get_contacts(const Transform2D& p_local_xform, con
void Shape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_custom_solver_bias","bias"),&Shape2D::set_custom_solver_bias);
- ClassDB::bind_method(_MD("get_custom_solver_bias"),&Shape2D::get_custom_solver_bias);
- ClassDB::bind_method(_MD("collide","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide);
- ClassDB::bind_method(_MD("collide_with_motion","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion);
- ClassDB::bind_method(_MD("collide_and_get_contacts:Variant","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts);
- ClassDB::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"));
+ ClassDB::bind_method(D_METHOD("set_custom_solver_bias","bias"),&Shape2D::set_custom_solver_bias);
+ ClassDB::bind_method(D_METHOD("get_custom_solver_bias"),&Shape2D::get_custom_solver_bias);
+ ClassDB::bind_method(D_METHOD("collide","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide);
+ ClassDB::bind_method(D_METHOD("collide_with_motion","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion);
+ ClassDB::bind_method(D_METHOD("collide_and_get_contacts:Variant","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts);
+ ClassDB::bind_method(D_METHOD("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"),"set_custom_solver_bias","get_custom_solver_bias");
}
diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp
index b2270d00c0..64e50e62c8 100644
--- a/scene/resources/shape_line_2d.cpp
+++ b/scene/resources/shape_line_2d.cpp
@@ -90,14 +90,14 @@ Rect2 LineShape2D::get_rect() const{
void LineShape2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_normal","normal"),&LineShape2D::set_normal);
- ClassDB::bind_method(_MD("get_normal"),&LineShape2D::get_normal);
+ ClassDB::bind_method(D_METHOD("set_normal","normal"),&LineShape2D::set_normal);
+ ClassDB::bind_method(D_METHOD("get_normal"),&LineShape2D::get_normal);
- ClassDB::bind_method(_MD("set_d","d"),&LineShape2D::set_d);
- ClassDB::bind_method(_MD("get_d"),&LineShape2D::get_d);
+ ClassDB::bind_method(D_METHOD("set_d","d"),&LineShape2D::set_d);
+ ClassDB::bind_method(D_METHOD("get_d"),&LineShape2D::get_d);
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"normal"),_SCS("set_normal"),_SCS("get_normal") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"d"),_SCS("set_d"),_SCS("get_d") );
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"normal"),"set_normal","get_normal") ;
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"d"),"set_d","get_d") ;
}
diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp
index 2a4fbfa8d4..0f8a1e5339 100644
--- a/scene/resources/sky_box.cpp
+++ b/scene/resources/sky_box.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* sky_box.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "sky_box.h"
#include "io/image_loader.h"
@@ -16,10 +44,10 @@ SkyBox::RadianceSize SkyBox::get_radiance_size() const {
void SkyBox::_bind_methods() {
- ClassDB::bind_method(_MD("set_radiance_size","size"),&SkyBox::set_radiance_size);
- ClassDB::bind_method(_MD("get_radiance_size"),&SkyBox::get_radiance_size);
+ ClassDB::bind_method(D_METHOD("set_radiance_size","size"),&SkyBox::set_radiance_size);
+ ClassDB::bind_method(D_METHOD("get_radiance_size"),&SkyBox::get_radiance_size);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"radiance_size",PROPERTY_HINT_ENUM,"256,512,1024,2048"),_SCS("set_radiance_size"),_SCS("get_radiance_size"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"radiance_size",PROPERTY_HINT_ENUM,"256,512,1024,2048"),"set_radiance_size","get_radiance_size");
BIND_CONSTANT( RADIANCE_SIZE_256 );
@@ -113,8 +141,8 @@ RID ImageSkyBox::get_rid() const {
void ImageSkyBox::_bind_methods() {
- ClassDB::bind_method(_MD("set_image_path","image","path"),&ImageSkyBox::set_image_path);
- ClassDB::bind_method(_MD("get_image_path","image"),&ImageSkyBox::get_image_path);
+ ClassDB::bind_method(D_METHOD("set_image_path","image","path"),&ImageSkyBox::set_image_path);
+ ClassDB::bind_method(D_METHOD("get_image_path","image"),&ImageSkyBox::get_image_path);
List<String> extensions;
ImageLoader::get_recognized_extensions(&extensions);
@@ -127,12 +155,12 @@ void ImageSkyBox::_bind_methods() {
}
ADD_GROUP("Image Path","image_path_");
- ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_negative_x",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_NEGATIVE_X);
- ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_positive_x",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_POSITIVE_X);
- ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_negative_y",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_NEGATIVE_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_positive_y",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_POSITIVE_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_negative_z",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_NEGATIVE_Z);
- ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_positive_z",PROPERTY_HINT_FILE,hints),_SCS("set_image_path"),_SCS("get_image_path"),IMAGE_PATH_POSITIVE_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_negative_x",PROPERTY_HINT_FILE,hints),"set_image_path","get_image_path",IMAGE_PATH_NEGATIVE_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_positive_x",PROPERTY_HINT_FILE,hints),"set_image_path","get_image_path",IMAGE_PATH_POSITIVE_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_negative_y",PROPERTY_HINT_FILE,hints),"set_image_path","get_image_path",IMAGE_PATH_NEGATIVE_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_positive_y",PROPERTY_HINT_FILE,hints),"set_image_path","get_image_path",IMAGE_PATH_POSITIVE_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_negative_z",PROPERTY_HINT_FILE,hints),"set_image_path","get_image_path",IMAGE_PATH_NEGATIVE_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::STRING,"image_path_positive_z",PROPERTY_HINT_FILE,hints),"set_image_path","get_image_path",IMAGE_PATH_POSITIVE_Z);
BIND_CONSTANT( IMAGE_PATH_NEGATIVE_X );
BIND_CONSTANT( IMAGE_PATH_POSITIVE_X );
diff --git a/scene/resources/sky_box.h b/scene/resources/sky_box.h
index a3caf15aa7..171782d132 100644
--- a/scene/resources/sky_box.h
+++ b/scene/resources/sky_box.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* sky_box.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SKYBOX_H
#define SKYBOX_H
diff --git a/scene/resources/space_2d.cpp b/scene/resources/space_2d.cpp
index 3f0d2824ce..f1fe9629dd 100644
--- a/scene/resources/space_2d.cpp
+++ b/scene/resources/space_2d.cpp
@@ -48,10 +48,10 @@ bool Space2D::is_active() const {
void Space2D::_bind_methods() {
- ClassDB::bind_method(_MD("set_active","active"),&Space2D::set_active);
- ClassDB::bind_method(_MD("is_active"),&Space2D::is_active);
+ ClassDB::bind_method(D_METHOD("set_active","active"),&Space2D::set_active);
+ ClassDB::bind_method(D_METHOD("is_active"),&Space2D::is_active);
- ADD_PROPERTY( PropertyInfo(Variant::BOOL,"active"),_SCS("set_active"),_SCS("is_active") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL,"active"),"set_active","is_active") ;
}
diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp
index c7c4d94aad..3029625928 100644
--- a/scene/resources/sphere_shape.cpp
+++ b/scene/resources/sphere_shape.cpp
@@ -75,10 +75,10 @@ float SphereShape::get_radius() const {
void SphereShape::_bind_methods() {
- ClassDB::bind_method(_MD("set_radius","radius"),&SphereShape::set_radius);
- ClassDB::bind_method(_MD("get_radius"),&SphereShape::get_radius);
+ ClassDB::bind_method(D_METHOD("set_radius","radius"),&SphereShape::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"),&SphereShape::get_radius);
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0,4096,0.01"), _SCS("set_radius"), _SCS("get_radius"));
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_radius", "get_radius");
}
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index e5e32ba4e9..34a4202942 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -70,26 +70,26 @@ Size2 StyleBox::get_center_size() const {
void StyleBox::_bind_methods() {
- ClassDB::bind_method(_MD("test_mask","point","rect"),&StyleBox::test_mask);
+ ClassDB::bind_method(D_METHOD("test_mask","point","rect"),&StyleBox::test_mask);
- ClassDB::bind_method(_MD("set_default_margin","margin","offset"),&StyleBox::set_default_margin);
- ClassDB::bind_method(_MD("get_default_margin","margin"),&StyleBox::get_default_margin);
+ ClassDB::bind_method(D_METHOD("set_default_margin","margin","offset"),&StyleBox::set_default_margin);
+ ClassDB::bind_method(D_METHOD("get_default_margin","margin"),&StyleBox::get_default_margin);
- //ClassDB::bind_method(_MD("set_default_margin"),&StyleBox::set_default_margin);
- //ClassDB::bind_method(_MD("get_default_margin"),&StyleBox::get_default_margin);
+ //ClassDB::bind_method(D_METHOD("set_default_margin"),&StyleBox::set_default_margin);
+ //ClassDB::bind_method(D_METHOD("get_default_margin"),&StyleBox::get_default_margin);
- ClassDB::bind_method(_MD("get_margin","margin"),&StyleBox::get_margin);
- ClassDB::bind_method(_MD("get_minimum_size"),&StyleBox::get_minimum_size);
- ClassDB::bind_method(_MD("get_center_size"),&StyleBox::get_center_size);
- ClassDB::bind_method(_MD("get_offset"),&StyleBox::get_offset);
+ ClassDB::bind_method(D_METHOD("get_margin","margin"),&StyleBox::get_margin);
+ ClassDB::bind_method(D_METHOD("get_minimum_size"),&StyleBox::get_minimum_size);
+ ClassDB::bind_method(D_METHOD("get_center_size"),&StyleBox::get_center_size);
+ ClassDB::bind_method(D_METHOD("get_offset"),&StyleBox::get_offset);
- ClassDB::bind_method(_MD("draw","canvas_item","rect"),&StyleBox::draw);
+ ClassDB::bind_method(D_METHOD("draw","canvas_item","rect"),&StyleBox::draw);
ADD_GROUP("Content Margin","content_margin_");
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_left", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_LEFT );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_right", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_RIGHT );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_top", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_TOP);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_bottom", PROPERTY_HINT_RANGE,"-1,2048,1" ), _SCS("set_default_margin"),_SCS("get_default_margin"), MARGIN_BOTTOM );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_left", PROPERTY_HINT_RANGE,"-1,2048,1" ), "set_default_margin","get_default_margin", MARGIN_LEFT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_right", PROPERTY_HINT_RANGE,"-1,2048,1" ), "set_default_margin","get_default_margin", MARGIN_RIGHT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_top", PROPERTY_HINT_RANGE,"-1,2048,1" ), "set_default_margin","get_default_margin", MARGIN_TOP);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "content_margin_bottom", PROPERTY_HINT_RANGE,"-1,2048,1" ), "set_default_margin","get_default_margin", MARGIN_BOTTOM );
}
@@ -209,42 +209,42 @@ Color StyleBoxTexture::get_modulate() const {
void StyleBoxTexture::_bind_methods() {
- ClassDB::bind_method(_MD("set_texture","texture:Texture"),&StyleBoxTexture::set_texture);
- ClassDB::bind_method(_MD("get_texture:Texture"),&StyleBoxTexture::get_texture);
+ ClassDB::bind_method(D_METHOD("set_texture","texture:Texture"),&StyleBoxTexture::set_texture);
+ ClassDB::bind_method(D_METHOD("get_texture:Texture"),&StyleBoxTexture::get_texture);
- ClassDB::bind_method(_MD("set_margin_size","margin","size"),&StyleBoxTexture::set_margin_size);
- ClassDB::bind_method(_MD("get_margin_size","margin"),&StyleBoxTexture::get_margin_size);
+ ClassDB::bind_method(D_METHOD("set_margin_size","margin","size"),&StyleBoxTexture::set_margin_size);
+ ClassDB::bind_method(D_METHOD("get_margin_size","margin"),&StyleBoxTexture::get_margin_size);
- ClassDB::bind_method(_MD("set_expand_margin_size","margin","size"),&StyleBoxTexture::set_expand_margin_size);
- ClassDB::bind_method(_MD("get_expand_margin_size","margin"),&StyleBoxTexture::get_expand_margin_size);
+ ClassDB::bind_method(D_METHOD("set_expand_margin_size","margin","size"),&StyleBoxTexture::set_expand_margin_size);
+ ClassDB::bind_method(D_METHOD("get_expand_margin_size","margin"),&StyleBoxTexture::get_expand_margin_size);
- ClassDB::bind_method(_MD("set_region_rect","region"),&StyleBoxTexture::set_region_rect);
- ClassDB::bind_method(_MD("get_region_rect"),&StyleBoxTexture::get_region_rect);
+ ClassDB::bind_method(D_METHOD("set_region_rect","region"),&StyleBoxTexture::set_region_rect);
+ ClassDB::bind_method(D_METHOD("get_region_rect"),&StyleBoxTexture::get_region_rect);
- ClassDB::bind_method(_MD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center);
- ClassDB::bind_method(_MD("get_draw_center"),&StyleBoxTexture::get_draw_center);
+ ClassDB::bind_method(D_METHOD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center);
+ ClassDB::bind_method(D_METHOD("get_draw_center"),&StyleBoxTexture::get_draw_center);
- ClassDB::bind_method(_MD("set_modulate","color"),&StyleBoxTexture::set_modulate);
- ClassDB::bind_method(_MD("get_modulate"),&StyleBoxTexture::get_modulate);
+ ClassDB::bind_method(D_METHOD("set_modulate","color"),&StyleBoxTexture::set_modulate);
+ ClassDB::bind_method(D_METHOD("get_modulate"),&StyleBoxTexture::get_modulate);
ADD_SIGNAL(MethodInfo("texture_changed"));
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_texture"),_SCS("get_texture") );
- ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), "set_texture","get_texture") ;
+ ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), "set_region_rect","get_region_rect");
ADD_GROUP("Margin","margin_");
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_left", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_LEFT );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_right", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_RIGHT );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_top", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_TOP);
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_bottom", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_BOTTOM );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_left", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_margin_size","get_margin_size", MARGIN_LEFT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_right", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_margin_size","get_margin_size", MARGIN_RIGHT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_top", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_margin_size","get_margin_size", MARGIN_TOP);
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin_bottom", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_margin_size","get_margin_size", MARGIN_BOTTOM );
ADD_GROUP("Expand Margin","expand_margin_");
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_left", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_LEFT );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_right", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_RIGHT );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_top", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_TOP );
- ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_bottom", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_expand_margin_size"),_SCS("get_expand_margin_size"), MARGIN_BOTTOM );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_left", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_expand_margin_size","get_expand_margin_size", MARGIN_LEFT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_right", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_expand_margin_size","get_expand_margin_size", MARGIN_RIGHT );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_top", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_expand_margin_size","get_expand_margin_size", MARGIN_TOP );
+ ADD_PROPERTYI( PropertyInfo( Variant::REAL, "expand_margin_bottom", PROPERTY_HINT_RANGE,"0,2048,1" ), "set_expand_margin_size","get_expand_margin_size", MARGIN_BOTTOM );
ADD_GROUP("Modulate","modulate_");
- ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate_color" ), _SCS("set_modulate"),_SCS("get_modulate"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "draw_center" ) , _SCS("set_draw_center"),_SCS("get_draw_center"));
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate_color" ), "set_modulate","get_modulate");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "draw_center" ) , "set_draw_center","get_draw_center");
}
@@ -390,25 +390,25 @@ float StyleBoxFlat::get_style_margin(Margin p_margin) const {
}
void StyleBoxFlat::_bind_methods() {
- ClassDB::bind_method(_MD("set_bg_color","color"),&StyleBoxFlat::set_bg_color);
- ClassDB::bind_method(_MD("get_bg_color"),&StyleBoxFlat::get_bg_color);
- ClassDB::bind_method(_MD("set_light_color","color"),&StyleBoxFlat::set_light_color);
- ClassDB::bind_method(_MD("get_light_color"),&StyleBoxFlat::get_light_color);
- ClassDB::bind_method(_MD("set_dark_color","color"),&StyleBoxFlat::set_dark_color);
- ClassDB::bind_method(_MD("get_dark_color"),&StyleBoxFlat::get_dark_color);
- ClassDB::bind_method(_MD("set_border_size","size"),&StyleBoxFlat::set_border_size);
- ClassDB::bind_method(_MD("get_border_size"),&StyleBoxFlat::get_border_size);
- ClassDB::bind_method(_MD("set_border_blend","blend"),&StyleBoxFlat::set_border_blend);
- ClassDB::bind_method(_MD("get_border_blend"),&StyleBoxFlat::get_border_blend);
- ClassDB::bind_method(_MD("set_draw_center","size"),&StyleBoxFlat::set_draw_center);
- ClassDB::bind_method(_MD("get_draw_center"),&StyleBoxFlat::get_draw_center);
-
- ADD_PROPERTY( PropertyInfo( Variant::COLOR, "bg_color"), _SCS("set_bg_color"),_SCS("get_bg_color") );
- ADD_PROPERTY( PropertyInfo( Variant::COLOR, "light_color"),_SCS("set_light_color"),_SCS("get_light_color"));
- ADD_PROPERTY( PropertyInfo( Variant::COLOR, "dark_color"),_SCS("set_dark_color"),_SCS("get_dark_color"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "border_size",PROPERTY_HINT_RANGE,"0,4096"),_SCS("set_border_size"),_SCS("get_border_size"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "border_blend"),_SCS("set_border_blend"),_SCS("get_border_blend"));
- ADD_PROPERTY( PropertyInfo( Variant::BOOL, "draw_bg"),_SCS("set_draw_center"),_SCS("get_draw_center"));
+ ClassDB::bind_method(D_METHOD("set_bg_color","color"),&StyleBoxFlat::set_bg_color);
+ ClassDB::bind_method(D_METHOD("get_bg_color"),&StyleBoxFlat::get_bg_color);
+ ClassDB::bind_method(D_METHOD("set_light_color","color"),&StyleBoxFlat::set_light_color);
+ ClassDB::bind_method(D_METHOD("get_light_color"),&StyleBoxFlat::get_light_color);
+ ClassDB::bind_method(D_METHOD("set_dark_color","color"),&StyleBoxFlat::set_dark_color);
+ ClassDB::bind_method(D_METHOD("get_dark_color"),&StyleBoxFlat::get_dark_color);
+ ClassDB::bind_method(D_METHOD("set_border_size","size"),&StyleBoxFlat::set_border_size);
+ ClassDB::bind_method(D_METHOD("get_border_size"),&StyleBoxFlat::get_border_size);
+ ClassDB::bind_method(D_METHOD("set_border_blend","blend"),&StyleBoxFlat::set_border_blend);
+ ClassDB::bind_method(D_METHOD("get_border_blend"),&StyleBoxFlat::get_border_blend);
+ ClassDB::bind_method(D_METHOD("set_draw_center","size"),&StyleBoxFlat::set_draw_center);
+ ClassDB::bind_method(D_METHOD("get_draw_center"),&StyleBoxFlat::get_draw_center);
+
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "bg_color"), "set_bg_color","get_bg_color") ;
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "light_color"),"set_light_color","get_light_color");
+ ADD_PROPERTY( PropertyInfo( Variant::COLOR, "dark_color"),"set_dark_color","get_dark_color");
+ ADD_PROPERTY( PropertyInfo( Variant::INT, "border_size",PROPERTY_HINT_RANGE,"0,4096"),"set_border_size","get_border_size");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "border_blend"),"set_border_blend","get_border_blend");
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "draw_bg"),"set_draw_center","get_draw_center");
}
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index 1d0d323546..cf07f1658b 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -862,25 +862,25 @@ void SurfaceTool::clear() {
void SurfaceTool::_bind_methods() {
- ClassDB::bind_method(_MD("begin","primitive"),&SurfaceTool::begin);
- ClassDB::bind_method(_MD("add_vertex","vertex"),&SurfaceTool::add_vertex);
- ClassDB::bind_method(_MD("add_color","color"),&SurfaceTool::add_color);
- ClassDB::bind_method(_MD("add_normal","normal"),&SurfaceTool::add_normal);
- ClassDB::bind_method(_MD("add_tangent","tangent"),&SurfaceTool::add_tangent);
- ClassDB::bind_method(_MD("add_uv","uv"),&SurfaceTool::add_uv);
- ClassDB::bind_method(_MD("add_uv2","uv2"),&SurfaceTool::add_uv2);
- ClassDB::bind_method(_MD("add_bones","bones"),&SurfaceTool::add_bones);
- ClassDB::bind_method(_MD("add_weights","weights"),&SurfaceTool::add_weights);
- ClassDB::bind_method(_MD("add_smooth_group","smooth"),&SurfaceTool::add_smooth_group);
- ClassDB::bind_method(_MD("add_triangle_fan", "vertexes", "uvs", "colors", "uv2s", "normals", "tangents"),&SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()),DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>()));
- ClassDB::bind_method(_MD("set_material","material:Material"),&SurfaceTool::set_material);
- ClassDB::bind_method(_MD("index"),&SurfaceTool::index);
- ClassDB::bind_method(_MD("deindex"),&SurfaceTool::deindex);
- ///ClassDB::bind_method(_MD("generate_flat_normals"),&SurfaceTool::generate_flat_normals);
- ClassDB::bind_method(_MD("generate_normals"),&SurfaceTool::generate_normals);
- ClassDB::bind_method(_MD("add_index", "index"), &SurfaceTool::add_index);
- ClassDB::bind_method(_MD("commit:Mesh","existing:Mesh"),&SurfaceTool::commit,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("clear"),&SurfaceTool::clear);
+ ClassDB::bind_method(D_METHOD("begin","primitive"),&SurfaceTool::begin);
+ ClassDB::bind_method(D_METHOD("add_vertex","vertex"),&SurfaceTool::add_vertex);
+ ClassDB::bind_method(D_METHOD("add_color","color"),&SurfaceTool::add_color);
+ ClassDB::bind_method(D_METHOD("add_normal","normal"),&SurfaceTool::add_normal);
+ ClassDB::bind_method(D_METHOD("add_tangent","tangent"),&SurfaceTool::add_tangent);
+ ClassDB::bind_method(D_METHOD("add_uv","uv"),&SurfaceTool::add_uv);
+ ClassDB::bind_method(D_METHOD("add_uv2","uv2"),&SurfaceTool::add_uv2);
+ ClassDB::bind_method(D_METHOD("add_bones","bones"),&SurfaceTool::add_bones);
+ ClassDB::bind_method(D_METHOD("add_weights","weights"),&SurfaceTool::add_weights);
+ ClassDB::bind_method(D_METHOD("add_smooth_group","smooth"),&SurfaceTool::add_smooth_group);
+ ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertexes", "uvs", "colors", "uv2s", "normals", "tangents"),&SurfaceTool::add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()),DEFVAL(Vector<Vector3>()), DEFVAL(Vector<Plane>()));
+ ClassDB::bind_method(D_METHOD("set_material","material:Material"),&SurfaceTool::set_material);
+ ClassDB::bind_method(D_METHOD("index"),&SurfaceTool::index);
+ ClassDB::bind_method(D_METHOD("deindex"),&SurfaceTool::deindex);
+ ///ClassDB::bind_method(D_METHOD("generate_flat_normals"),&SurfaceTool::generate_flat_normals);
+ ClassDB::bind_method(D_METHOD("generate_normals"),&SurfaceTool::generate_normals);
+ ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index);
+ ClassDB::bind_method(D_METHOD("commit:Mesh","existing:Mesh"),&SurfaceTool::commit,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("clear"),&SurfaceTool::clear);
}
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index fa89b7ba00..62feb7b37c 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -63,15 +63,15 @@ bool Texture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2
void Texture::_bind_methods() {
- ClassDB::bind_method(_MD("get_width"),&Texture::get_width);
- ClassDB::bind_method(_MD("get_height"),&Texture::get_height);
- ClassDB::bind_method(_MD("get_size"),&Texture::get_size);
- ClassDB::bind_method(_MD("has_alpha"),&Texture::has_alpha);
- ClassDB::bind_method(_MD("set_flags","flags"),&Texture::set_flags);
- ClassDB::bind_method(_MD("get_flags"),&Texture::get_flags);
- ClassDB::bind_method(_MD("draw","canvas_item","pos","modulate","transpose"),&Texture::draw,DEFVAL(Color(1,1,1)),DEFVAL(false));
- ClassDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate","transpose"),&Texture::draw_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
- ClassDB::bind_method(_MD("draw_rect_region","canvas_item","rect","src_rect","modulate","transpose"),&Texture::draw_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_width"),&Texture::get_width);
+ ClassDB::bind_method(D_METHOD("get_height"),&Texture::get_height);
+ ClassDB::bind_method(D_METHOD("get_size"),&Texture::get_size);
+ ClassDB::bind_method(D_METHOD("has_alpha"),&Texture::has_alpha);
+ ClassDB::bind_method(D_METHOD("set_flags","flags"),&Texture::set_flags);
+ ClassDB::bind_method(D_METHOD("get_flags"),&Texture::get_flags);
+ ClassDB::bind_method(D_METHOD("draw","canvas_item","pos","modulate","transpose"),&Texture::draw,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_rect","canvas_item","rect","tile","modulate","transpose"),&Texture::draw_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("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 );
@@ -406,27 +406,27 @@ void ImageTexture::_set_data(Dictionary p_data) {
void ImageTexture::_bind_methods() {
- ClassDB::bind_method(_MD("create","width","height","format","flags"),&ImageTexture::create,DEFVAL(FLAGS_DEFAULT));
- ClassDB::bind_method(_MD("create_from_image","image","flags"),&ImageTexture::create_from_image,DEFVAL(FLAGS_DEFAULT));
- ClassDB::bind_method(_MD("get_format"),&ImageTexture::get_format);
- ClassDB::bind_method(_MD("load","path"),&ImageTexture::load);
- ClassDB::bind_method(_MD("set_data","image"),&ImageTexture::set_data);
- ClassDB::bind_method(_MD("get_data","cube_side"),&ImageTexture::get_data);
- ClassDB::bind_method(_MD("set_storage","mode"),&ImageTexture::set_storage);
- ClassDB::bind_method(_MD("get_storage"),&ImageTexture::get_storage);
- ClassDB::bind_method(_MD("set_lossy_storage_quality","quality"),&ImageTexture::set_lossy_storage_quality);
- ClassDB::bind_method(_MD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality);
- ClassDB::bind_method(_MD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges);
- ClassDB::bind_method(_MD("premultiply_alpha"),&ImageTexture::premultiply_alpha);
- ClassDB::bind_method(_MD("normal_to_xy"),&ImageTexture::normal_to_xy);
- ClassDB::bind_method(_MD("shrink_x2_and_keep_size"),&ImageTexture::shrink_x2_and_keep_size);
-
- ClassDB::bind_method(_MD("set_size_override","size"),&ImageTexture::set_size_override);
- ClassDB::set_method_flags(get_class_static(),_SCS("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::set_method_flags(get_class_static(),_SCS("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::set_method_flags(get_class_static(),_SCS("normal_to_xy"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::set_method_flags(get_class_static(),_SCS("shrink_x2_and_keep_size"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
- ClassDB::bind_method(_MD("_reload_hook","rid"),&ImageTexture::_reload_hook);
+ ClassDB::bind_method(D_METHOD("create","width","height","format","flags"),&ImageTexture::create,DEFVAL(FLAGS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("create_from_image","image","flags"),&ImageTexture::create_from_image,DEFVAL(FLAGS_DEFAULT));
+ ClassDB::bind_method(D_METHOD("get_format"),&ImageTexture::get_format);
+ ClassDB::bind_method(D_METHOD("load","path"),&ImageTexture::load);
+ ClassDB::bind_method(D_METHOD("set_data","image"),&ImageTexture::set_data);
+ ClassDB::bind_method(D_METHOD("get_data","cube_side"),&ImageTexture::get_data);
+ ClassDB::bind_method(D_METHOD("set_storage","mode"),&ImageTexture::set_storage);
+ ClassDB::bind_method(D_METHOD("get_storage"),&ImageTexture::get_storage);
+ ClassDB::bind_method(D_METHOD("set_lossy_storage_quality","quality"),&ImageTexture::set_lossy_storage_quality);
+ ClassDB::bind_method(D_METHOD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality);
+ ClassDB::bind_method(D_METHOD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges);
+ ClassDB::bind_method(D_METHOD("premultiply_alpha"),&ImageTexture::premultiply_alpha);
+ ClassDB::bind_method(D_METHOD("normal_to_xy"),&ImageTexture::normal_to_xy);
+ ClassDB::bind_method(D_METHOD("shrink_x2_and_keep_size"),&ImageTexture::shrink_x2_and_keep_size);
+
+ ClassDB::bind_method(D_METHOD("set_size_override","size"),&ImageTexture::set_size_override);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("normal_to_xy"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::set_method_flags(get_class_static(),_scs_create("shrink_x2_and_keep_size"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("_reload_hook","rid"),&ImageTexture::_reload_hook);
BIND_CONSTANT( STORAGE_RAW );
@@ -559,6 +559,11 @@ Error StreamTexture::_load_data(const String& p_path,int &tw,int &th,int& flags,
int total_size=0;
for(int i=0;i<mipmaps;i++) {
+
+ if (i>0) {
+ size = f->get_32();
+ }
+
PoolVector<uint8_t> pv;
pv.resize(size);
{
@@ -754,6 +759,12 @@ bool StreamTexture::has_alpha() const {
return false;
}
+
+Image StreamTexture::get_data() const {
+
+ return VS::get_singleton()->texture_get_data(texture);
+}
+
void StreamTexture::set_flags(uint32_t p_flags){
}
@@ -771,10 +782,10 @@ void StreamTexture::reload_from_file() {
void StreamTexture::_bind_methods() {
- ClassDB::bind_method(_MD("load","path"),&StreamTexture::load);
- ClassDB::bind_method(_MD("get_load_path"),&StreamTexture::get_load_path);
+ ClassDB::bind_method(D_METHOD("load","path"),&StreamTexture::load);
+ ClassDB::bind_method(D_METHOD("get_load_path"),&StreamTexture::get_load_path);
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"load_path",PROPERTY_HINT_FILE,"*.stex"),_SCS("load"),_SCS("get_load_path"));
+ ADD_PROPERTY( PropertyInfo(Variant::STRING,"load_path",PROPERTY_HINT_FILE,"*.stex"),"load","get_load_path");
}
@@ -921,20 +932,20 @@ Rect2 AtlasTexture::get_margin() const {
void AtlasTexture::_bind_methods() {
- ClassDB::bind_method(_MD("set_atlas","atlas:Texture"),&AtlasTexture::set_atlas);
- ClassDB::bind_method(_MD("get_atlas:Texture"),&AtlasTexture::get_atlas);
+ ClassDB::bind_method(D_METHOD("set_atlas","atlas:Texture"),&AtlasTexture::set_atlas);
+ ClassDB::bind_method(D_METHOD("get_atlas:Texture"),&AtlasTexture::get_atlas);
- ClassDB::bind_method(_MD("set_region","region"),&AtlasTexture::set_region);
- ClassDB::bind_method(_MD("get_region"),&AtlasTexture::get_region);
+ ClassDB::bind_method(D_METHOD("set_region","region"),&AtlasTexture::set_region);
+ ClassDB::bind_method(D_METHOD("get_region"),&AtlasTexture::get_region);
- ClassDB::bind_method(_MD("set_margin","margin"),&AtlasTexture::set_margin);
- ClassDB::bind_method(_MD("get_margin"),&AtlasTexture::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin","margin"),&AtlasTexture::set_margin);
+ ClassDB::bind_method(D_METHOD("get_margin"),&AtlasTexture::get_margin);
ADD_SIGNAL(MethodInfo("atlas_changed"));
- ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_atlas"),_SCS("get_atlas") );
- ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region"), _SCS("set_region"),_SCS("get_region") );
- ADD_PROPERTY( PropertyInfo( Variant::RECT2, "margin"), _SCS("set_margin"),_SCS("get_margin") );
+ ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), "set_atlas","get_atlas") ;
+ ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region"), "set_region","get_region") ;
+ ADD_PROPERTY( PropertyInfo( Variant::RECT2, "margin"), "set_margin","get_margin") ;
}
@@ -1176,20 +1187,20 @@ Ref<Texture> LargeTexture::get_piece_texture(int p_idx) const{
void LargeTexture::_bind_methods() {
- ClassDB::bind_method(_MD("add_piece","ofs","texture:Texture"),&LargeTexture::add_piece);
- ClassDB::bind_method(_MD("set_piece_offset", "idx", "ofs"),&LargeTexture::set_piece_offset);
- ClassDB::bind_method(_MD("set_piece_texture","idx", "texture:Texture"),&LargeTexture::set_piece_texture);
- ClassDB::bind_method(_MD("set_size","size"),&LargeTexture::set_size);
- ClassDB::bind_method(_MD("clear"),&LargeTexture::clear);
+ ClassDB::bind_method(D_METHOD("add_piece","ofs","texture:Texture"),&LargeTexture::add_piece);
+ ClassDB::bind_method(D_METHOD("set_piece_offset", "idx", "ofs"),&LargeTexture::set_piece_offset);
+ ClassDB::bind_method(D_METHOD("set_piece_texture","idx", "texture:Texture"),&LargeTexture::set_piece_texture);
+ ClassDB::bind_method(D_METHOD("set_size","size"),&LargeTexture::set_size);
+ ClassDB::bind_method(D_METHOD("clear"),&LargeTexture::clear);
- ClassDB::bind_method(_MD("get_piece_count"),&LargeTexture::get_piece_count);
- ClassDB::bind_method(_MD("get_piece_offset","idx"),&LargeTexture::get_piece_offset);
- ClassDB::bind_method(_MD("get_piece_texture:Texture","idx"),&LargeTexture::get_piece_texture);
+ ClassDB::bind_method(D_METHOD("get_piece_count"),&LargeTexture::get_piece_count);
+ ClassDB::bind_method(D_METHOD("get_piece_offset","idx"),&LargeTexture::get_piece_offset);
+ ClassDB::bind_method(D_METHOD("get_piece_texture:Texture","idx"),&LargeTexture::get_piece_texture);
- ClassDB::bind_method(_MD("_set_data","data"),&LargeTexture::_set_data);
- ClassDB::bind_method(_MD("_get_data"),&LargeTexture::_get_data);
+ ClassDB::bind_method(D_METHOD("_set_data","data"),&LargeTexture::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"),&LargeTexture::_get_data);
- ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"),_SCS("_get_data") );
+ ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), "_set_data","_get_data") ;
}
@@ -1420,18 +1431,18 @@ void CubeMap::_get_property_list( List<PropertyInfo> *p_list) const {
void CubeMap::_bind_methods() {
- ClassDB::bind_method(_MD("get_width"),&CubeMap::get_width);
- ClassDB::bind_method(_MD("get_height"),&CubeMap::get_height);
- //ClassDB::bind_method(_MD("get_rid"),&CubeMap::get_rid);
- ClassDB::bind_method(_MD("set_flags","flags"),&CubeMap::set_flags);
- ClassDB::bind_method(_MD("get_flags"),&CubeMap::get_flags);
-
- ClassDB::bind_method(_MD("set_side","side","image"),&CubeMap::set_side);
- ClassDB::bind_method(_MD("get_side","side"),&CubeMap::get_side);
- ClassDB::bind_method(_MD("set_storage","mode"),&CubeMap::set_storage);
- ClassDB::bind_method(_MD("get_storage"),&CubeMap::get_storage);
- ClassDB::bind_method(_MD("set_lossy_storage_quality","quality"),&CubeMap::set_lossy_storage_quality);
- ClassDB::bind_method(_MD("get_lossy_storage_quality"),&CubeMap::get_lossy_storage_quality);
+ ClassDB::bind_method(D_METHOD("get_width"),&CubeMap::get_width);
+ ClassDB::bind_method(D_METHOD("get_height"),&CubeMap::get_height);
+ //ClassDB::bind_method(D_METHOD("get_rid"),&CubeMap::get_rid);
+ ClassDB::bind_method(D_METHOD("set_flags","flags"),&CubeMap::set_flags);
+ ClassDB::bind_method(D_METHOD("get_flags"),&CubeMap::get_flags);
+
+ ClassDB::bind_method(D_METHOD("set_side","side","image"),&CubeMap::set_side);
+ ClassDB::bind_method(D_METHOD("get_side","side"),&CubeMap::get_side);
+ ClassDB::bind_method(D_METHOD("set_storage","mode"),&CubeMap::set_storage);
+ ClassDB::bind_method(D_METHOD("get_storage"),&CubeMap::get_storage);
+ ClassDB::bind_method(D_METHOD("set_lossy_storage_quality","quality"),&CubeMap::set_lossy_storage_quality);
+ ClassDB::bind_method(D_METHOD("get_lossy_storage_quality"),&CubeMap::get_lossy_storage_quality);
BIND_CONSTANT( STORAGE_RAW );
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index f684aeb658..cae77ad5cf 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -76,7 +76,7 @@ public:
virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1), bool p_transpose=false) const;
virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const;
-
+ virtual Image get_data() const { return Image(); }
Texture();
};
@@ -224,6 +224,8 @@ public:
virtual bool has_alpha() const;
virtual void set_flags(uint32_t p_flags);
+ virtual Image get_data() const;
+
StreamTexture();
~StreamTexture();
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 4793f8143b..10ad38d498 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -664,50 +664,50 @@ void Theme::get_type_list(List<StringName> *p_list) const {
void Theme::_bind_methods() {
- ClassDB::bind_method(_MD("set_icon","name","type","texture:Texture"),&Theme::set_icon);
- ClassDB::bind_method(_MD("get_icon:Texture","name","type"),&Theme::get_icon);
- ClassDB::bind_method(_MD("has_icon","name","type"),&Theme::has_icon);
- ClassDB::bind_method(_MD("clear_icon","name","type"),&Theme::clear_icon);
- ClassDB::bind_method(_MD("get_icon_list","type"),&Theme::_get_icon_list);
+ ClassDB::bind_method(D_METHOD("set_icon","name","type","texture:Texture"),&Theme::set_icon);
+ ClassDB::bind_method(D_METHOD("get_icon:Texture","name","type"),&Theme::get_icon);
+ ClassDB::bind_method(D_METHOD("has_icon","name","type"),&Theme::has_icon);
+ ClassDB::bind_method(D_METHOD("clear_icon","name","type"),&Theme::clear_icon);
+ ClassDB::bind_method(D_METHOD("get_icon_list","type"),&Theme::_get_icon_list);
- ClassDB::bind_method(_MD("set_stylebox","name","type","texture:StyleBox"),&Theme::set_stylebox);
- ClassDB::bind_method(_MD("get_stylebox:StyleBox","name","type"),&Theme::get_stylebox);
- ClassDB::bind_method(_MD("has_stylebox","name","type"),&Theme::has_stylebox);
- ClassDB::bind_method(_MD("clear_stylebox","name","type"),&Theme::clear_stylebox);
- ClassDB::bind_method(_MD("get_stylebox_list","type"),&Theme::_get_stylebox_list);
- ClassDB::bind_method(_MD("get_stylebox_types"),&Theme::_get_stylebox_types);
+ ClassDB::bind_method(D_METHOD("set_stylebox","name","type","texture:StyleBox"),&Theme::set_stylebox);
+ ClassDB::bind_method(D_METHOD("get_stylebox:StyleBox","name","type"),&Theme::get_stylebox);
+ ClassDB::bind_method(D_METHOD("has_stylebox","name","type"),&Theme::has_stylebox);
+ ClassDB::bind_method(D_METHOD("clear_stylebox","name","type"),&Theme::clear_stylebox);
+ ClassDB::bind_method(D_METHOD("get_stylebox_list","type"),&Theme::_get_stylebox_list);
+ ClassDB::bind_method(D_METHOD("get_stylebox_types"),&Theme::_get_stylebox_types);
- ClassDB::bind_method(_MD("set_font","name","type","font:Font"),&Theme::set_font);
- ClassDB::bind_method(_MD("get_font:Font","name","type"),&Theme::get_font);
- ClassDB::bind_method(_MD("has_font","name","type"),&Theme::has_font);
- ClassDB::bind_method(_MD("clear_font","name","type"),&Theme::clear_font);
- ClassDB::bind_method(_MD("get_font_list","type"),&Theme::_get_font_list);
+ ClassDB::bind_method(D_METHOD("set_font","name","type","font:Font"),&Theme::set_font);
+ ClassDB::bind_method(D_METHOD("get_font:Font","name","type"),&Theme::get_font);
+ ClassDB::bind_method(D_METHOD("has_font","name","type"),&Theme::has_font);
+ ClassDB::bind_method(D_METHOD("clear_font","name","type"),&Theme::clear_font);
+ ClassDB::bind_method(D_METHOD("get_font_list","type"),&Theme::_get_font_list);
- ClassDB::bind_method(_MD("set_color","name","type","color"),&Theme::set_color);
- ClassDB::bind_method(_MD("get_color","name","type"),&Theme::get_color);
- ClassDB::bind_method(_MD("has_color","name","type"),&Theme::has_color);
- ClassDB::bind_method(_MD("clear_color","name","type"),&Theme::clear_color);
- ClassDB::bind_method(_MD("get_color_list","type"),&Theme::_get_color_list);
+ ClassDB::bind_method(D_METHOD("set_color","name","type","color"),&Theme::set_color);
+ ClassDB::bind_method(D_METHOD("get_color","name","type"),&Theme::get_color);
+ ClassDB::bind_method(D_METHOD("has_color","name","type"),&Theme::has_color);
+ ClassDB::bind_method(D_METHOD("clear_color","name","type"),&Theme::clear_color);
+ ClassDB::bind_method(D_METHOD("get_color_list","type"),&Theme::_get_color_list);
- ClassDB::bind_method(_MD("set_constant","name","type","constant"),&Theme::set_constant);
- ClassDB::bind_method(_MD("get_constant","name","type"),&Theme::get_constant);
- ClassDB::bind_method(_MD("has_constant","name","type"),&Theme::has_constant);
- ClassDB::bind_method(_MD("clear_constant","name","type"),&Theme::clear_constant);
- ClassDB::bind_method(_MD("get_constant_list","type"),&Theme::_get_constant_list);
+ ClassDB::bind_method(D_METHOD("set_constant","name","type","constant"),&Theme::set_constant);
+ ClassDB::bind_method(D_METHOD("get_constant","name","type"),&Theme::get_constant);
+ ClassDB::bind_method(D_METHOD("has_constant","name","type"),&Theme::has_constant);
+ ClassDB::bind_method(D_METHOD("clear_constant","name","type"),&Theme::clear_constant);
+ ClassDB::bind_method(D_METHOD("get_constant_list","type"),&Theme::_get_constant_list);
- ClassDB::bind_method(_MD("set_default_font","font"),&Theme::set_default_theme_font);
- ClassDB::bind_method(_MD("get_default_font"),&Theme::get_default_theme_font);
+ ClassDB::bind_method(D_METHOD("set_default_font","font"),&Theme::set_default_theme_font);
+ ClassDB::bind_method(D_METHOD("get_default_font"),&Theme::get_default_theme_font);
- ClassDB::bind_method(_MD("get_type_list","type"),&Theme::_get_type_list);
+ ClassDB::bind_method(D_METHOD("get_type_list","type"),&Theme::_get_type_list);
- ClassDB::bind_method(_MD("_emit_theme_changed"),&Theme::_emit_theme_changed);
+ ClassDB::bind_method(D_METHOD("_emit_theme_changed"),&Theme::_emit_theme_changed);
ClassDB::bind_method("copy_default_theme",&Theme::copy_default_theme);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"default_font",PROPERTY_HINT_RESOURCE_TYPE,"Font"),_SCS("set_default_font"),_SCS("get_default_font"));
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"default_font",PROPERTY_HINT_RESOURCE_TYPE,"Font"),"set_default_font","get_default_font");
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index c97682f504..e12d8057d8 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -426,37 +426,37 @@ void TileSet::clear() {
void TileSet::_bind_methods() {
- ClassDB::bind_method(_MD("create_tile","id"),&TileSet::create_tile);
- ClassDB::bind_method(_MD("tile_set_name","id","name"),&TileSet::tile_set_name);
- ClassDB::bind_method(_MD("tile_get_name","id"),&TileSet::tile_get_name);
- ClassDB::bind_method(_MD("tile_set_texture","id","texture:Texture"),&TileSet::tile_set_texture);
- ClassDB::bind_method(_MD("tile_get_texture:Texture","id"),&TileSet::tile_get_texture);
- ClassDB::bind_method(_MD("tile_set_material","id","material:CanvasItemMaterial"),&TileSet::tile_set_material);
- ClassDB::bind_method(_MD("tile_get_material:CanvasItemMaterial","id"),&TileSet::tile_get_material);
- ClassDB::bind_method(_MD("tile_set_texture_offset","id","texture_offset"),&TileSet::tile_set_texture_offset);
- ClassDB::bind_method(_MD("tile_get_texture_offset","id"),&TileSet::tile_get_texture_offset);
- ClassDB::bind_method(_MD("tile_set_shape_offset","id","shape_offset"),&TileSet::tile_set_shape_offset);
- ClassDB::bind_method(_MD("tile_get_shape_offset","id"),&TileSet::tile_get_shape_offset);
- ClassDB::bind_method(_MD("tile_set_region","id","region"),&TileSet::tile_set_region);
- ClassDB::bind_method(_MD("tile_get_region","id"),&TileSet::tile_get_region);
- ClassDB::bind_method(_MD("tile_set_shape","id","shape:Shape2D"),&TileSet::tile_set_shape);
- ClassDB::bind_method(_MD("tile_get_shape:Shape2D","id"),&TileSet::tile_get_shape);
- ClassDB::bind_method(_MD("tile_set_shapes","id","shapes"),&TileSet::_tile_set_shapes);
- ClassDB::bind_method(_MD("tile_get_shapes","id"),&TileSet::_tile_get_shapes);
- ClassDB::bind_method(_MD("tile_set_navigation_polygon","id","navigation_polygon:NavigationPolygon"),&TileSet::tile_set_navigation_polygon);
- ClassDB::bind_method(_MD("tile_get_navigation_polygon:NavigationPolygon","id"),&TileSet::tile_get_navigation_polygon);
- ClassDB::bind_method(_MD("tile_set_navigation_polygon_offset","id","navigation_polygon_offset"),&TileSet::tile_set_navigation_polygon_offset);
- ClassDB::bind_method(_MD("tile_get_navigation_polygon_offset","id"),&TileSet::tile_get_navigation_polygon_offset);
- ClassDB::bind_method(_MD("tile_set_light_occluder","id","light_occluder:OccluderPolygon2D"),&TileSet::tile_set_light_occluder);
- ClassDB::bind_method(_MD("tile_get_light_occluder:OccluderPolygon2D","id"),&TileSet::tile_get_light_occluder);
- ClassDB::bind_method(_MD("tile_set_occluder_offset","id","occluder_offset"),&TileSet::tile_set_occluder_offset);
- ClassDB::bind_method(_MD("tile_get_occluder_offset","id"),&TileSet::tile_get_occluder_offset);
-
- ClassDB::bind_method(_MD("remove_tile","id"),&TileSet::remove_tile);
- ClassDB::bind_method(_MD("clear"),&TileSet::clear);
- ClassDB::bind_method(_MD("get_last_unused_tile_id"),&TileSet::get_last_unused_tile_id);
- ClassDB::bind_method(_MD("find_tile_by_name","name"),&TileSet::find_tile_by_name);
- ClassDB::bind_method(_MD("get_tiles_ids", "name"), &TileSet::_get_tiles_ids);
+ ClassDB::bind_method(D_METHOD("create_tile","id"),&TileSet::create_tile);
+ ClassDB::bind_method(D_METHOD("tile_set_name","id","name"),&TileSet::tile_set_name);
+ ClassDB::bind_method(D_METHOD("tile_get_name","id"),&TileSet::tile_get_name);
+ ClassDB::bind_method(D_METHOD("tile_set_texture","id","texture:Texture"),&TileSet::tile_set_texture);
+ ClassDB::bind_method(D_METHOD("tile_get_texture:Texture","id"),&TileSet::tile_get_texture);
+ ClassDB::bind_method(D_METHOD("tile_set_material","id","material:CanvasItemMaterial"),&TileSet::tile_set_material);
+ ClassDB::bind_method(D_METHOD("tile_get_material:CanvasItemMaterial","id"),&TileSet::tile_get_material);
+ ClassDB::bind_method(D_METHOD("tile_set_texture_offset","id","texture_offset"),&TileSet::tile_set_texture_offset);
+ ClassDB::bind_method(D_METHOD("tile_get_texture_offset","id"),&TileSet::tile_get_texture_offset);
+ ClassDB::bind_method(D_METHOD("tile_set_shape_offset","id","shape_offset"),&TileSet::tile_set_shape_offset);
+ ClassDB::bind_method(D_METHOD("tile_get_shape_offset","id"),&TileSet::tile_get_shape_offset);
+ ClassDB::bind_method(D_METHOD("tile_set_region","id","region"),&TileSet::tile_set_region);
+ ClassDB::bind_method(D_METHOD("tile_get_region","id"),&TileSet::tile_get_region);
+ ClassDB::bind_method(D_METHOD("tile_set_shape","id","shape:Shape2D"),&TileSet::tile_set_shape);
+ ClassDB::bind_method(D_METHOD("tile_get_shape:Shape2D","id"),&TileSet::tile_get_shape);
+ ClassDB::bind_method(D_METHOD("tile_set_shapes","id","shapes"),&TileSet::_tile_set_shapes);
+ ClassDB::bind_method(D_METHOD("tile_get_shapes","id"),&TileSet::_tile_get_shapes);
+ ClassDB::bind_method(D_METHOD("tile_set_navigation_polygon","id","navigation_polygon:NavigationPolygon"),&TileSet::tile_set_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("tile_get_navigation_polygon:NavigationPolygon","id"),&TileSet::tile_get_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("tile_set_navigation_polygon_offset","id","navigation_polygon_offset"),&TileSet::tile_set_navigation_polygon_offset);
+ ClassDB::bind_method(D_METHOD("tile_get_navigation_polygon_offset","id"),&TileSet::tile_get_navigation_polygon_offset);
+ ClassDB::bind_method(D_METHOD("tile_set_light_occluder","id","light_occluder:OccluderPolygon2D"),&TileSet::tile_set_light_occluder);
+ ClassDB::bind_method(D_METHOD("tile_get_light_occluder:OccluderPolygon2D","id"),&TileSet::tile_get_light_occluder);
+ ClassDB::bind_method(D_METHOD("tile_set_occluder_offset","id","occluder_offset"),&TileSet::tile_set_occluder_offset);
+ ClassDB::bind_method(D_METHOD("tile_get_occluder_offset","id"),&TileSet::tile_get_occluder_offset);
+
+ ClassDB::bind_method(D_METHOD("remove_tile","id"),&TileSet::remove_tile);
+ ClassDB::bind_method(D_METHOD("clear"),&TileSet::clear);
+ ClassDB::bind_method(D_METHOD("get_last_unused_tile_id"),&TileSet::get_last_unused_tile_id);
+ ClassDB::bind_method(D_METHOD("find_tile_by_name","name"),&TileSet::find_tile_by_name);
+ ClassDB::bind_method(D_METHOD("get_tiles_ids", "name"), &TileSet::_get_tiles_ids);
}
diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp
index 72cb8cc906..f9233d950c 100644
--- a/scene/resources/world.cpp
+++ b/scene/resources/world.cpp
@@ -310,12 +310,12 @@ PhysicsDirectSpaceState *World::get_direct_space_state() {
void World::_bind_methods() {
- ClassDB::bind_method(_MD("get_space"),&World::get_space);
- ClassDB::bind_method(_MD("get_scenario"),&World::get_scenario);
- ClassDB::bind_method(_MD("set_environment","env:Environment"),&World::set_environment);
- ClassDB::bind_method(_MD("get_environment:Environment"),&World::get_environment);
- ClassDB::bind_method(_MD("get_direct_space_state:PhysicsDirectSpaceState"),&World::get_direct_space_state);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment"),_SCS("set_environment"),_SCS("get_environment"));
+ ClassDB::bind_method(D_METHOD("get_space"),&World::get_space);
+ ClassDB::bind_method(D_METHOD("get_scenario"),&World::get_scenario);
+ ClassDB::bind_method(D_METHOD("set_environment","env:Environment"),&World::set_environment);
+ ClassDB::bind_method(D_METHOD("get_environment:Environment"),&World::get_environment);
+ ClassDB::bind_method(D_METHOD("get_direct_space_state:PhysicsDirectSpaceState"),&World::get_direct_space_state);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment"),"set_environment","get_environment");
}
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index d4eff8d2b3..6b745d5d35 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -30,11 +30,11 @@
#include "servers/visual_server.h"
#include "servers/physics_2d_server.h"
//#include "servers/spatial_sound_2d_server.h"
-#include "globals.h"
+#include "global_config.h"
#include "scene/2d/visibility_notifier_2d.h"
#include "scene/main/viewport.h"
#include "scene/2d/camera_2d.h"
-#include "globals.h"
+#include "global_config.h"
struct SpatialIndexer2D {
@@ -382,11 +382,11 @@ RID World2D::get_sound_space() {
void World2D::_bind_methods() {
- ClassDB::bind_method(_MD("get_canvas"),&World2D::get_canvas);
- ClassDB::bind_method(_MD("get_space"),&World2D::get_space);
- ClassDB::bind_method(_MD("get_sound_space"),&World2D::get_sound_space);
+ ClassDB::bind_method(D_METHOD("get_canvas"),&World2D::get_canvas);
+ ClassDB::bind_method(D_METHOD("get_space"),&World2D::get_space);
+ ClassDB::bind_method(D_METHOD("get_sound_space"),&World2D::get_sound_space);
- ClassDB::bind_method(_MD("get_direct_space_state:Physics2DDirectSpaceState"),&World2D::get_direct_space_state);
+ ClassDB::bind_method(D_METHOD("get_direct_space_state:Physics2DDirectSpaceState"),&World2D::get_direct_space_state);
}
diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h
index a9110b3bd9..c02880e9ed 100644
--- a/scene/resources/world_2d.h
+++ b/scene/resources/world_2d.h
@@ -31,7 +31,7 @@
#include "resource.h"
#include "servers/physics_2d_server.h"
-#include "globals.h"
+#include "global_config.h"
class SpatialIndexer2D;
class VisibilityNotifier2D;
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index ffa35a93d8..d3a913680b 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -51,6 +51,7 @@ SceneStringNames::SceneStringNames() {
sleeping_state_changed=StaticCString::create("sleeping_state_changed");
finished=StaticCString::create("finished");
+ emission_finished=StaticCString::create("emission_finished");
animation_finished=StaticCString::create("animation_finished");
animation_changed=StaticCString::create("animation_changed");
animation_started=StaticCString::create("animation_started");
@@ -115,6 +116,7 @@ SceneStringNames::SceneStringNames() {
_area_enter_tree = StaticCString::create("_area_enter_tree");
_area_exit_tree = StaticCString::create("_area_exit_tree");
+ _input = StaticCString::create("_input");
_input_event=StaticCString::create("_input_event");
gui_input=StaticCString::create("gui_input");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 125d391294..624a9147d5 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -80,6 +80,7 @@ public:
StringName sort_children;
StringName finished;
+ StringName emission_finished;
StringName animation_finished;
StringName animation_changed;
StringName animation_started;
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 6e0c0089ca..6c12957851 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "audio_driver_dummy.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
index 372c0cbc13..b0844ff924 100644
--- a/servers/audio/audio_effect.cpp
+++ b/servers/audio/audio_effect.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect.h"
AudioEffect::AudioEffect()
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 02eb258f99..db3ec91195 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECT_H
#define AUDIOEFFECT_H
diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp
index d723f8d2fe..a0796f5224 100644
--- a/servers/audio/effects/audio_effect_amplify.cpp
+++ b/servers/audio/effects/audio_effect_amplify.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_amplify.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_amplify.h"
@@ -38,10 +66,10 @@ float AudioEffectAmplify::get_volume_db() const {
void AudioEffectAmplify::_bind_methods() {
- ClassDB::bind_method(_MD("set_volume_db","volume"),&AudioEffectAmplify::set_volume_db);
- ClassDB::bind_method(_MD("get_volume_db"),&AudioEffectAmplify::get_volume_db);
+ ClassDB::bind_method(D_METHOD("set_volume_db","volume"),&AudioEffectAmplify::set_volume_db);
+ ClassDB::bind_method(D_METHOD("get_volume_db"),&AudioEffectAmplify::get_volume_db);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24,0.01"),_SCS("set_volume_db"),_SCS("get_volume_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24,0.01"),"set_volume_db","get_volume_db");
}
AudioEffectAmplify::AudioEffectAmplify()
diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h
index 921054e2cd..03f558e52e 100644
--- a/servers/audio/effects/audio_effect_amplify.h
+++ b/servers/audio/effects/audio_effect_amplify.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_amplify.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTAMPLIFY_H
#define AUDIOEFFECTAMPLIFY_H
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index d3105343ae..20b45b5725 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_chorus.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_chorus.h"
#include "servers/audio_server.h"
#include "math_funcs.h"
@@ -284,65 +312,65 @@ void AudioEffectChorus::_validate_property(PropertyInfo& property) const {
void AudioEffectChorus::_bind_methods() {
- ClassDB::bind_method(_MD("set_voice_count","voices"),&AudioEffectChorus::set_voice_count);
- ClassDB::bind_method(_MD("get_voice_count"),&AudioEffectChorus::get_voice_count);
+ ClassDB::bind_method(D_METHOD("set_voice_count","voices"),&AudioEffectChorus::set_voice_count);
+ ClassDB::bind_method(D_METHOD("get_voice_count"),&AudioEffectChorus::get_voice_count);
- ClassDB::bind_method(_MD("set_voice_delay_ms","voice_idx","delay_ms"),&AudioEffectChorus::set_voice_delay_ms);
- ClassDB::bind_method(_MD("get_voice_delay_ms","voice_idx"),&AudioEffectChorus::get_voice_delay_ms);
+ ClassDB::bind_method(D_METHOD("set_voice_delay_ms","voice_idx","delay_ms"),&AudioEffectChorus::set_voice_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_voice_delay_ms","voice_idx"),&AudioEffectChorus::get_voice_delay_ms);
- ClassDB::bind_method(_MD("set_voice_rate_hz","voice_idx","rate_hz"),&AudioEffectChorus::set_voice_rate_hz);
- ClassDB::bind_method(_MD("get_voice_rate_hz","voice_idx"),&AudioEffectChorus::get_voice_rate_hz);
+ ClassDB::bind_method(D_METHOD("set_voice_rate_hz","voice_idx","rate_hz"),&AudioEffectChorus::set_voice_rate_hz);
+ ClassDB::bind_method(D_METHOD("get_voice_rate_hz","voice_idx"),&AudioEffectChorus::get_voice_rate_hz);
- ClassDB::bind_method(_MD("set_voice_depth_ms","voice_idx","depth_ms"),&AudioEffectChorus::set_voice_depth_ms);
- ClassDB::bind_method(_MD("get_voice_depth_ms","voice_idx"),&AudioEffectChorus::get_voice_depth_ms);
+ ClassDB::bind_method(D_METHOD("set_voice_depth_ms","voice_idx","depth_ms"),&AudioEffectChorus::set_voice_depth_ms);
+ ClassDB::bind_method(D_METHOD("get_voice_depth_ms","voice_idx"),&AudioEffectChorus::get_voice_depth_ms);
- ClassDB::bind_method(_MD("set_voice_level_db","voice_idx","level_db"),&AudioEffectChorus::set_voice_level_db);
- ClassDB::bind_method(_MD("get_voice_level_db","voice_idx"),&AudioEffectChorus::get_voice_level_db);
+ ClassDB::bind_method(D_METHOD("set_voice_level_db","voice_idx","level_db"),&AudioEffectChorus::set_voice_level_db);
+ ClassDB::bind_method(D_METHOD("get_voice_level_db","voice_idx"),&AudioEffectChorus::get_voice_level_db);
- ClassDB::bind_method(_MD("set_voice_cutoff_hz","voice_idx","cutoff_hz"),&AudioEffectChorus::set_voice_cutoff_hz);
- ClassDB::bind_method(_MD("get_voice_cutoff_hz","voice_idx"),&AudioEffectChorus::get_voice_cutoff_hz);
+ ClassDB::bind_method(D_METHOD("set_voice_cutoff_hz","voice_idx","cutoff_hz"),&AudioEffectChorus::set_voice_cutoff_hz);
+ ClassDB::bind_method(D_METHOD("get_voice_cutoff_hz","voice_idx"),&AudioEffectChorus::get_voice_cutoff_hz);
- ClassDB::bind_method(_MD("set_voice_pan","voice_idx","pan"),&AudioEffectChorus::set_voice_pan);
- ClassDB::bind_method(_MD("get_voice_pan","voice_idx"),&AudioEffectChorus::get_voice_pan);
+ ClassDB::bind_method(D_METHOD("set_voice_pan","voice_idx","pan"),&AudioEffectChorus::set_voice_pan);
+ ClassDB::bind_method(D_METHOD("get_voice_pan","voice_idx"),&AudioEffectChorus::get_voice_pan);
- ClassDB::bind_method(_MD("set_wet","amount"),&AudioEffectChorus::set_wet);
- ClassDB::bind_method(_MD("get_wet"),&AudioEffectChorus::get_wet);
+ ClassDB::bind_method(D_METHOD("set_wet","amount"),&AudioEffectChorus::set_wet);
+ ClassDB::bind_method(D_METHOD("get_wet"),&AudioEffectChorus::get_wet);
- ClassDB::bind_method(_MD("set_dry","amount"),&AudioEffectChorus::set_dry);
- ClassDB::bind_method(_MD("get_dry"),&AudioEffectChorus::get_dry);
+ ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectChorus::set_dry);
+ ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectChorus::get_dry);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"voice_count",PROPERTY_HINT_RANGE,"1,4,1"),_SCS("set_voice_count"),_SCS("get_voice_count"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dry"),_SCS("get_dry"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_wet"),_SCS("get_wet"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"voice_count",PROPERTY_HINT_RANGE,"1,4,1"),"set_voice_count","get_voice_count");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_wet","get_wet");
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),0);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),0);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),0);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),0);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),0);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("get_voice_pan"),0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",0);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),1);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),1);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),1);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),1);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),1);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("get_voice_pan"),1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",1);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),2);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),2);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),2);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),2);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),2);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("get_voice_pan"),2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",2);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_voice_delay_ms"),_SCS("get_voice_delay_ms"),3);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),_SCS("set_voice_rate_hz"),_SCS("get_voice_rate_hz"),3);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),_SCS("set_voice_depth_ms"),_SCS("get_voice_depth_ms"),3);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),_SCS("set_voice_level_db"),_SCS("get_voice_level_db"),3);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_voice_cutoff_hz"),_SCS("get_voice_cutoff_hz"),3);
- ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_voice_pan"),_SCS("get_voice_pan"),3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",3);
}
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
index 4cfba5d61a..ae0964bd53 100644
--- a/servers/audio/effects/audio_effect_chorus.h
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_chorus.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTCHORUS_H
#define AUDIOEFFECTCHORUS_H
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
index 5d116a9543..c08302c58e 100644
--- a/servers/audio/effects/audio_effect_compressor.cpp
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_compressor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_compressor.h"
#include "servers/audio_server.h"
@@ -185,34 +213,34 @@ void AudioEffectCompressor::_validate_property(PropertyInfo& property) const {
void AudioEffectCompressor::_bind_methods() {
- ClassDB::bind_method(_MD("set_treshold","treshold"),&AudioEffectCompressor::set_treshold);
- ClassDB::bind_method(_MD("get_treshold"),&AudioEffectCompressor::get_treshold);
+ ClassDB::bind_method(D_METHOD("set_treshold","treshold"),&AudioEffectCompressor::set_treshold);
+ ClassDB::bind_method(D_METHOD("get_treshold"),&AudioEffectCompressor::get_treshold);
- ClassDB::bind_method(_MD("set_ratio","ratio"),&AudioEffectCompressor::set_ratio);
- ClassDB::bind_method(_MD("get_ratio"),&AudioEffectCompressor::get_ratio);
+ ClassDB::bind_method(D_METHOD("set_ratio","ratio"),&AudioEffectCompressor::set_ratio);
+ ClassDB::bind_method(D_METHOD("get_ratio"),&AudioEffectCompressor::get_ratio);
- ClassDB::bind_method(_MD("set_gain","gain"),&AudioEffectCompressor::set_gain);
- ClassDB::bind_method(_MD("get_gain"),&AudioEffectCompressor::get_gain);
+ ClassDB::bind_method(D_METHOD("set_gain","gain"),&AudioEffectCompressor::set_gain);
+ ClassDB::bind_method(D_METHOD("get_gain"),&AudioEffectCompressor::get_gain);
- ClassDB::bind_method(_MD("set_attack_us","attack_us"),&AudioEffectCompressor::set_attack_us);
- ClassDB::bind_method(_MD("get_attack_us"),&AudioEffectCompressor::get_attack_us);
+ ClassDB::bind_method(D_METHOD("set_attack_us","attack_us"),&AudioEffectCompressor::set_attack_us);
+ ClassDB::bind_method(D_METHOD("get_attack_us"),&AudioEffectCompressor::get_attack_us);
- ClassDB::bind_method(_MD("set_release_ms","release_ms"),&AudioEffectCompressor::set_release_ms);
- ClassDB::bind_method(_MD("get_release_ms"),&AudioEffectCompressor::get_release_ms);
+ ClassDB::bind_method(D_METHOD("set_release_ms","release_ms"),&AudioEffectCompressor::set_release_ms);
+ ClassDB::bind_method(D_METHOD("get_release_ms"),&AudioEffectCompressor::get_release_ms);
- ClassDB::bind_method(_MD("set_mix","mix"),&AudioEffectCompressor::set_mix);
- ClassDB::bind_method(_MD("get_mix"),&AudioEffectCompressor::get_mix);
+ ClassDB::bind_method(D_METHOD("set_mix","mix"),&AudioEffectCompressor::set_mix);
+ ClassDB::bind_method(D_METHOD("get_mix"),&AudioEffectCompressor::get_mix);
- ClassDB::bind_method(_MD("set_sidechain","sidechain"),&AudioEffectCompressor::set_sidechain);
- ClassDB::bind_method(_MD("get_sidechain"),&AudioEffectCompressor::get_sidechain);
+ ClassDB::bind_method(D_METHOD("set_sidechain","sidechain"),&AudioEffectCompressor::set_sidechain);
+ ClassDB::bind_method(D_METHOD("get_sidechain"),&AudioEffectCompressor::get_sidechain);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold",PROPERTY_HINT_RANGE,"-60,0,0.1"),_SCS("set_treshold"),_SCS("get_treshold"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ratio",PROPERTY_HINT_RANGE,"1,48,0.1"),_SCS("set_ratio"),_SCS("get_ratio"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"-20,20,0.1"),_SCS("set_gain"),_SCS("get_gain"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"attack_us",PROPERTY_HINT_RANGE,"20,2000,1"),_SCS("set_attack_us"),_SCS("get_attack_us"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"release_ms",PROPERTY_HINT_RANGE,"20,2000,1"),_SCS("set_release_ms"),_SCS("get_release_ms"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"mix",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_mix"),_SCS("get_mix"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"sidechain",PROPERTY_HINT_ENUM),_SCS("set_sidechain"),_SCS("get_sidechain"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold",PROPERTY_HINT_RANGE,"-60,0,0.1"),"set_treshold","get_treshold");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ratio",PROPERTY_HINT_RANGE,"1,48,0.1"),"set_ratio","get_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"-20,20,0.1"),"set_gain","get_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"attack_us",PROPERTY_HINT_RANGE,"20,2000,1"),"set_attack_us","get_attack_us");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"release_ms",PROPERTY_HINT_RANGE,"20,2000,1"),"set_release_ms","get_release_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"mix",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_mix","get_mix");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"sidechain",PROPERTY_HINT_ENUM),"set_sidechain","get_sidechain");
}
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
index eb06b3db77..3988ad1526 100644
--- a/servers/audio/effects/audio_effect_compressor.h
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_compressor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTCOMPRESSOR_H
#define AUDIOEFFECTCOMPRESSOR_H
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
index aae2657a63..a6d2048896 100644
--- a/servers/audio/effects/audio_effect_delay.cpp
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_delay.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_delay.h"
#include "servers/audio_server.h"
#include "math_funcs.h"
@@ -244,62 +272,62 @@ float AudioEffectDelay::get_feedback_lowpass() const{
void AudioEffectDelay::_bind_methods() {
- ClassDB::bind_method(_MD("set_dry","amount"),&AudioEffectDelay::set_dry);
- ClassDB::bind_method(_MD("get_dry"),&AudioEffectDelay::get_dry);
+ ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectDelay::set_dry);
+ ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectDelay::get_dry);
- ClassDB::bind_method(_MD("set_tap1_active","amount"),&AudioEffectDelay::set_tap1_active);
- ClassDB::bind_method(_MD("is_tap1_active"),&AudioEffectDelay::is_tap1_active);
+ ClassDB::bind_method(D_METHOD("set_tap1_active","amount"),&AudioEffectDelay::set_tap1_active);
+ ClassDB::bind_method(D_METHOD("is_tap1_active"),&AudioEffectDelay::is_tap1_active);
- ClassDB::bind_method(_MD("set_tap1_delay_ms","amount"),&AudioEffectDelay::set_tap1_delay_ms);
- ClassDB::bind_method(_MD("get_tap1_delay_ms"),&AudioEffectDelay::get_tap1_delay_ms);
+ ClassDB::bind_method(D_METHOD("set_tap1_delay_ms","amount"),&AudioEffectDelay::set_tap1_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_tap1_delay_ms"),&AudioEffectDelay::get_tap1_delay_ms);
- ClassDB::bind_method(_MD("set_tap1_level_db","amount"),&AudioEffectDelay::set_tap1_level_db);
- ClassDB::bind_method(_MD("get_tap1_level_db"),&AudioEffectDelay::get_tap1_level_db);
+ ClassDB::bind_method(D_METHOD("set_tap1_level_db","amount"),&AudioEffectDelay::set_tap1_level_db);
+ ClassDB::bind_method(D_METHOD("get_tap1_level_db"),&AudioEffectDelay::get_tap1_level_db);
- ClassDB::bind_method(_MD("set_tap1_pan","amount"),&AudioEffectDelay::set_tap1_pan);
- ClassDB::bind_method(_MD("get_tap1_pan"),&AudioEffectDelay::get_tap1_pan);
+ ClassDB::bind_method(D_METHOD("set_tap1_pan","amount"),&AudioEffectDelay::set_tap1_pan);
+ ClassDB::bind_method(D_METHOD("get_tap1_pan"),&AudioEffectDelay::get_tap1_pan);
- ClassDB::bind_method(_MD("set_tap2_active","amount"),&AudioEffectDelay::set_tap2_active);
- ClassDB::bind_method(_MD("is_tap2_active"),&AudioEffectDelay::is_tap2_active);
+ ClassDB::bind_method(D_METHOD("set_tap2_active","amount"),&AudioEffectDelay::set_tap2_active);
+ ClassDB::bind_method(D_METHOD("is_tap2_active"),&AudioEffectDelay::is_tap2_active);
- ClassDB::bind_method(_MD("set_tap2_delay_ms","amount"),&AudioEffectDelay::set_tap2_delay_ms);
- ClassDB::bind_method(_MD("get_tap2_delay_ms"),&AudioEffectDelay::get_tap2_delay_ms);
+ ClassDB::bind_method(D_METHOD("set_tap2_delay_ms","amount"),&AudioEffectDelay::set_tap2_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_tap2_delay_ms"),&AudioEffectDelay::get_tap2_delay_ms);
- ClassDB::bind_method(_MD("set_tap2_level_db","amount"),&AudioEffectDelay::set_tap2_level_db);
- ClassDB::bind_method(_MD("get_tap2_level_db"),&AudioEffectDelay::get_tap2_level_db);
+ ClassDB::bind_method(D_METHOD("set_tap2_level_db","amount"),&AudioEffectDelay::set_tap2_level_db);
+ ClassDB::bind_method(D_METHOD("get_tap2_level_db"),&AudioEffectDelay::get_tap2_level_db);
- ClassDB::bind_method(_MD("set_tap2_pan","amount"),&AudioEffectDelay::set_tap2_pan);
- ClassDB::bind_method(_MD("get_tap2_pan"),&AudioEffectDelay::get_tap2_pan);
+ ClassDB::bind_method(D_METHOD("set_tap2_pan","amount"),&AudioEffectDelay::set_tap2_pan);
+ ClassDB::bind_method(D_METHOD("get_tap2_pan"),&AudioEffectDelay::get_tap2_pan);
- ClassDB::bind_method(_MD("set_feedback_active","amount"),&AudioEffectDelay::set_feedback_active);
- ClassDB::bind_method(_MD("is_feedback_active"),&AudioEffectDelay::is_feedback_active);
+ ClassDB::bind_method(D_METHOD("set_feedback_active","amount"),&AudioEffectDelay::set_feedback_active);
+ ClassDB::bind_method(D_METHOD("is_feedback_active"),&AudioEffectDelay::is_feedback_active);
- ClassDB::bind_method(_MD("set_feedback_delay_ms","amount"),&AudioEffectDelay::set_feedback_delay_ms);
- ClassDB::bind_method(_MD("get_feedback_delay_ms"),&AudioEffectDelay::get_feedback_delay_ms);
+ ClassDB::bind_method(D_METHOD("set_feedback_delay_ms","amount"),&AudioEffectDelay::set_feedback_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_feedback_delay_ms"),&AudioEffectDelay::get_feedback_delay_ms);
- ClassDB::bind_method(_MD("set_feedback_level_db","amount"),&AudioEffectDelay::set_feedback_level_db);
- ClassDB::bind_method(_MD("get_feedback_level_db"),&AudioEffectDelay::get_feedback_level_db);
+ ClassDB::bind_method(D_METHOD("set_feedback_level_db","amount"),&AudioEffectDelay::set_feedback_level_db);
+ ClassDB::bind_method(D_METHOD("get_feedback_level_db"),&AudioEffectDelay::get_feedback_level_db);
- ClassDB::bind_method(_MD("set_feedback_lowpass","amount"),&AudioEffectDelay::set_feedback_lowpass);
- ClassDB::bind_method(_MD("get_feedback_lowpass"),&AudioEffectDelay::get_feedback_lowpass);
+ ClassDB::bind_method(D_METHOD("set_feedback_lowpass","amount"),&AudioEffectDelay::set_feedback_lowpass);
+ ClassDB::bind_method(D_METHOD("get_feedback_lowpass"),&AudioEffectDelay::get_feedback_lowpass);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dry"),_SCS("get_dry"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap1/active"),_SCS("set_tap1_active"),_SCS("is_tap1_active"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),_SCS("set_tap1_delay_ms"),_SCS("get_tap1_delay_ms"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),_SCS("set_tap1_level_db"),_SCS("get_tap1_level_db"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_tap1_pan"),_SCS("get_tap1_pan"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap1/active"),"set_tap1_active","is_tap1_active");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_tap1_delay_ms","get_tap1_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_tap1_level_db","get_tap1_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_tap1_pan","get_tap1_pan");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap2/active"),_SCS("set_tap2_active"),_SCS("is_tap2_active"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),_SCS("set_tap2_delay_ms"),_SCS("get_tap2_delay_ms"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),_SCS("set_tap2_level_db"),_SCS("get_tap2_level_db"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_tap2_pan"),_SCS("get_tap2_pan"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap2/active"),"set_tap2_active","is_tap2_active");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_tap2_delay_ms","get_tap2_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_tap2_level_db","get_tap2_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_tap2_pan","get_tap2_pan");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL,"feedback/active"),_SCS("set_feedback_active"),_SCS("is_feedback_active"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),_SCS("set_feedback_delay_ms"),_SCS("get_feedback_delay_ms"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),_SCS("set_feedback_level_db"),_SCS("get_feedback_level_db"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/lowpass",PROPERTY_HINT_RANGE,"1,16000,1"),_SCS("set_feedback_lowpass"),_SCS("get_feedback_lowpass"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"feedback/active"),"set_feedback_active","is_feedback_active");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_feedback_delay_ms","get_feedback_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_feedback_level_db","get_feedback_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/lowpass",PROPERTY_HINT_RANGE,"1,16000,1"),"set_feedback_lowpass","get_feedback_lowpass");
}
diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h
index 645561138b..3e9f7f0584 100644
--- a/servers/audio/effects/audio_effect_delay.h
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -1,5 +1,33 @@
-#ifndef AUDIOEFFECTECHO_H
-#define AUDIOEFFECTECHO_H
+/*************************************************************************/
+/* audio_effect_delay.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTDELAY_H
+#define AUDIOEFFECTDELAY_H
#include "servers/audio/audio_effect.h"
@@ -109,4 +137,4 @@ public:
};
-#endif // AUDIOEFFECTECHO_H
+#endif // AUDIOEFFECTDELAY_H
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index 3ba409b0a5..b72cd8e0a6 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_distortion.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_distortion.h"
#include "servers/audio_server.h"
#include "math_funcs.h"
@@ -137,27 +165,27 @@ float AudioEffectDistortion::get_post_gain() const{
void AudioEffectDistortion::_bind_methods() {
- ClassDB::bind_method(_MD("set_mode","mode"),&AudioEffectDistortion::set_mode);
- ClassDB::bind_method(_MD("get_mode"),&AudioEffectDistortion::get_mode);
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&AudioEffectDistortion::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&AudioEffectDistortion::get_mode);
- ClassDB::bind_method(_MD("set_pre_gain","pre_gain"),&AudioEffectDistortion::set_pre_gain);
- ClassDB::bind_method(_MD("get_pre_gain"),&AudioEffectDistortion::get_pre_gain);
+ ClassDB::bind_method(D_METHOD("set_pre_gain","pre_gain"),&AudioEffectDistortion::set_pre_gain);
+ ClassDB::bind_method(D_METHOD("get_pre_gain"),&AudioEffectDistortion::get_pre_gain);
- ClassDB::bind_method(_MD("set_keep_hf_hz","keep_hf_hz"),&AudioEffectDistortion::set_keep_hf_hz);
- ClassDB::bind_method(_MD("get_keep_hf_hz"),&AudioEffectDistortion::get_keep_hf_hz);
+ ClassDB::bind_method(D_METHOD("set_keep_hf_hz","keep_hf_hz"),&AudioEffectDistortion::set_keep_hf_hz);
+ ClassDB::bind_method(D_METHOD("get_keep_hf_hz"),&AudioEffectDistortion::get_keep_hf_hz);
- ClassDB::bind_method(_MD("set_drive","drive"),&AudioEffectDistortion::set_drive);
- ClassDB::bind_method(_MD("get_drive"),&AudioEffectDistortion::get_drive);
+ ClassDB::bind_method(D_METHOD("set_drive","drive"),&AudioEffectDistortion::set_drive);
+ ClassDB::bind_method(D_METHOD("get_drive"),&AudioEffectDistortion::get_drive);
- ClassDB::bind_method(_MD("set_post_gain","post_gain"),&AudioEffectDistortion::set_post_gain);
- ClassDB::bind_method(_MD("get_post_gain"),&AudioEffectDistortion::get_post_gain);
+ ClassDB::bind_method(D_METHOD("set_post_gain","post_gain"),&AudioEffectDistortion::set_post_gain);
+ ClassDB::bind_method(D_METHOD("get_post_gain"),&AudioEffectDistortion::get_post_gain);
- ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Clip,ATan,LoFi,Overdrive,WaveShape"),_SCS("set_mode"),_SCS("get_mode"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"pre_gain",PROPERTY_HINT_RANGE,"-60,60,0.01"),_SCS("set_pre_gain"),_SCS("get_pre_gain"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"keep_hf_hz",PROPERTY_HINT_RANGE,"1,20000,1"),_SCS("set_keep_hf_hz"),_SCS("get_keep_hf_hz"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"drive",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_drive"),_SCS("get_drive"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"post_gain",PROPERTY_HINT_RANGE,"-80,24,0.01"),_SCS("set_post_gain"),_SCS("get_post_gain"));
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Clip,ATan,LoFi,Overdrive,WaveShape"),"set_mode","get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pre_gain",PROPERTY_HINT_RANGE,"-60,60,0.01"),"set_pre_gain","get_pre_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"keep_hf_hz",PROPERTY_HINT_RANGE,"1,20000,1"),"set_keep_hf_hz","get_keep_hf_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"drive",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_drive","get_drive");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"post_gain",PROPERTY_HINT_RANGE,"-80,24,0.01"),"set_post_gain","get_post_gain");
}
AudioEffectDistortion::AudioEffectDistortion()
diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h
index 1d2433faeb..c4388f0256 100644
--- a/servers/audio/effects/audio_effect_distortion.h
+++ b/servers/audio/effects/audio_effect_distortion.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_distortion.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTDISTORTION_H
#define AUDIOEFFECTDISTORTION_H
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index 3c6a684224..2caec9e49e 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_eq.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_eq.h"
#include "servers/audio_server.h"
@@ -100,9 +128,9 @@ void AudioEffectEQ::_get_property_list( List<PropertyInfo> *p_list) const{
void AudioEffectEQ::_bind_methods() {
- ClassDB::bind_method(_MD("set_band_gain_db","band_idx","volume_db"),&AudioEffectEQ::set_band_gain_db);
- ClassDB::bind_method(_MD("get_band_gain_db","band_idx"),&AudioEffectEQ::get_band_gain_db);
- ClassDB::bind_method(_MD("get_band_count"),&AudioEffectEQ::get_band_count);
+ ClassDB::bind_method(D_METHOD("set_band_gain_db","band_idx","volume_db"),&AudioEffectEQ::set_band_gain_db);
+ ClassDB::bind_method(D_METHOD("get_band_gain_db","band_idx"),&AudioEffectEQ::get_band_gain_db);
+ ClassDB::bind_method(D_METHOD("get_band_count"),&AudioEffectEQ::get_band_count);
}
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
index 3fcc2c0056..2f577ffd20 100644
--- a/servers/audio/effects/audio_effect_eq.h
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_eq.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTEQ_H
#define AUDIOEFFECTEQ_H
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
index 4e54ea1f3e..c854842943 100644
--- a/servers/audio/effects/audio_effect_filter.cpp
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_filter.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_filter.h"
#include "servers/audio_server.h"
@@ -122,22 +150,22 @@ AudioEffectFilter::FilterDB AudioEffectFilter::get_db() const {
void AudioEffectFilter::_bind_methods() {
- ClassDB::bind_method(_MD("set_cutoff","freq"),&AudioEffectFilter::set_cutoff);
- ClassDB::bind_method(_MD("get_cutoff"),&AudioEffectFilter::get_cutoff);
+ ClassDB::bind_method(D_METHOD("set_cutoff","freq"),&AudioEffectFilter::set_cutoff);
+ ClassDB::bind_method(D_METHOD("get_cutoff"),&AudioEffectFilter::get_cutoff);
- ClassDB::bind_method(_MD("set_resonance","amount"),&AudioEffectFilter::set_resonance);
- ClassDB::bind_method(_MD("get_resonance"),&AudioEffectFilter::get_resonance);
+ ClassDB::bind_method(D_METHOD("set_resonance","amount"),&AudioEffectFilter::set_resonance);
+ ClassDB::bind_method(D_METHOD("get_resonance"),&AudioEffectFilter::get_resonance);
- ClassDB::bind_method(_MD("set_gain","amount"),&AudioEffectFilter::set_gain);
- ClassDB::bind_method(_MD("get_gain"),&AudioEffectFilter::get_gain);
+ ClassDB::bind_method(D_METHOD("set_gain","amount"),&AudioEffectFilter::set_gain);
+ ClassDB::bind_method(D_METHOD("get_gain"),&AudioEffectFilter::get_gain);
- ClassDB::bind_method(_MD("set_db","amount"),&AudioEffectFilter::set_db);
- ClassDB::bind_method(_MD("get_db"),&AudioEffectFilter::get_db);
+ ClassDB::bind_method(D_METHOD("set_db","amount"),&AudioEffectFilter::set_db);
+ ClassDB::bind_method(D_METHOD("get_db"),&AudioEffectFilter::get_db);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"cutoff_hz",PROPERTY_HINT_RANGE,"1,40000,0.1"),_SCS("set_cutoff"),_SCS("get_cutoff"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"resonance",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_resonance"),_SCS("get_resonance"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"0,4,0.01"),_SCS("set_gain"),_SCS("get_gain"));
- ADD_PROPERTY(PropertyInfo(Variant::INT,"dB",PROPERTY_HINT_ENUM,"6db,12db,18db,24db"),_SCS("set_db"),_SCS("get_db"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"cutoff_hz",PROPERTY_HINT_RANGE,"1,40000,0.1"),"set_cutoff","get_cutoff");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"resonance",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_resonance","get_resonance");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"0,4,0.01"),"set_gain","get_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"dB",PROPERTY_HINT_ENUM,"6db,12db,18db,24db"),"set_db","get_db");
}
AudioEffectFilter::AudioEffectFilter(AudioFilterSW::Mode p_mode)
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index d0bc7a446a..0215f5a141 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_filter.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTFILTER_H
#define AUDIOEFFECTFILTER_H
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 5cd02682ab..a44bb51762 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_limiter.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_limiter.h"
void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
@@ -97,22 +125,22 @@ float AudioEffectLimiter::get_soft_clip_ratio() const{
void AudioEffectLimiter::_bind_methods() {
- ClassDB::bind_method(_MD("set_ceiling_db","ceiling"),&AudioEffectLimiter::set_ceiling_db);
- ClassDB::bind_method(_MD("get_ceiling_db"),&AudioEffectLimiter::get_ceiling_db);
+ ClassDB::bind_method(D_METHOD("set_ceiling_db","ceiling"),&AudioEffectLimiter::set_ceiling_db);
+ ClassDB::bind_method(D_METHOD("get_ceiling_db"),&AudioEffectLimiter::get_ceiling_db);
- ClassDB::bind_method(_MD("set_treshold_db","treshold"),&AudioEffectLimiter::set_treshold_db);
- ClassDB::bind_method(_MD("get_treshold_db"),&AudioEffectLimiter::get_treshold_db);
+ ClassDB::bind_method(D_METHOD("set_treshold_db","treshold"),&AudioEffectLimiter::set_treshold_db);
+ ClassDB::bind_method(D_METHOD("get_treshold_db"),&AudioEffectLimiter::get_treshold_db);
- ClassDB::bind_method(_MD("set_soft_clip_db","soft_clip"),&AudioEffectLimiter::set_soft_clip_db);
- ClassDB::bind_method(_MD("get_soft_clip_db"),&AudioEffectLimiter::get_soft_clip_db);
+ ClassDB::bind_method(D_METHOD("set_soft_clip_db","soft_clip"),&AudioEffectLimiter::set_soft_clip_db);
+ ClassDB::bind_method(D_METHOD("get_soft_clip_db"),&AudioEffectLimiter::get_soft_clip_db);
- ClassDB::bind_method(_MD("set_soft_clip_ratio","soft_clip"),&AudioEffectLimiter::set_soft_clip_ratio);
- ClassDB::bind_method(_MD("get_soft_clip_ratio"),&AudioEffectLimiter::get_soft_clip_ratio);
+ ClassDB::bind_method(D_METHOD("set_soft_clip_ratio","soft_clip"),&AudioEffectLimiter::set_soft_clip_ratio);
+ ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"),&AudioEffectLimiter::get_soft_clip_ratio);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"ceiling_db",PROPERTY_HINT_RANGE,"-20,-0.1,0.1"),_SCS("set_ceiling_db"),_SCS("get_ceiling_db"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold_db",PROPERTY_HINT_RANGE,"-30,0,0.1"),_SCS("set_treshold_db"),_SCS("get_treshold_db"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_db",PROPERTY_HINT_RANGE,"0,6,0.1"),_SCS("set_soft_clip_db"),_SCS("get_soft_clip_db"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_ratio",PROPERTY_HINT_RANGE,"3,20,0.1"),_SCS("set_soft_clip_ratio"),_SCS("get_soft_clip_ratio"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ceiling_db",PROPERTY_HINT_RANGE,"-20,-0.1,0.1"),"set_ceiling_db","get_ceiling_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold_db",PROPERTY_HINT_RANGE,"-30,0,0.1"),"set_treshold_db","get_treshold_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_db",PROPERTY_HINT_RANGE,"0,6,0.1"),"set_soft_clip_db","get_soft_clip_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_ratio",PROPERTY_HINT_RANGE,"3,20,0.1"),"set_soft_clip_ratio","get_soft_clip_ratio");
}
AudioEffectLimiter::AudioEffectLimiter()
diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h
index b0d7321205..12639498d9 100644
--- a/servers/audio/effects/audio_effect_limiter.h
+++ b/servers/audio/effects/audio_effect_limiter.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_limiter.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIO_EFFECT_LIMITER_H
#define AUDIO_EFFECT_LIMITER_H
diff --git a/servers/audio/effects/audio_effect_panner.cpp b/servers/audio/effects/audio_effect_panner.cpp
index e296b0d998..937575a5b5 100644
--- a/servers/audio/effects/audio_effect_panner.cpp
+++ b/servers/audio/effects/audio_effect_panner.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_panner.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_panner.h"
@@ -35,10 +63,10 @@ float AudioEffectPanner::get_pan() const {
void AudioEffectPanner::_bind_methods() {
- ClassDB::bind_method(_MD("set_pan","cpanume"),&AudioEffectPanner::set_pan);
- ClassDB::bind_method(_MD("get_pan"),&AudioEffectPanner::get_pan);
+ ClassDB::bind_method(D_METHOD("set_pan","cpanume"),&AudioEffectPanner::set_pan);
+ ClassDB::bind_method(D_METHOD("get_pan"),&AudioEffectPanner::get_pan);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_pan"),_SCS("get_pan"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_pan","get_pan");
}
AudioEffectPanner::AudioEffectPanner()
diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h
index bc1bb00815..999b5f5649 100644
--- a/servers/audio/effects/audio_effect_panner.h
+++ b/servers/audio/effects/audio_effect_panner.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_panner.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTPANNER_H
#define AUDIOEFFECTPANNER_H
diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp
index bfce608603..c9576404f1 100644
--- a/servers/audio/effects/audio_effect_phaser.cpp
+++ b/servers/audio/effects/audio_effect_phaser.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_phaser.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_phaser.h"
#include "servers/audio_server.h"
#include "math_funcs.h"
@@ -115,26 +143,26 @@ float AudioEffectPhaser::get_depth() const {
void AudioEffectPhaser::_bind_methods() {
- ClassDB::bind_method(_MD("set_range_min_hz","hz"),&AudioEffectPhaser::set_range_min_hz);
- ClassDB::bind_method(_MD("get_range_min_hz"),&AudioEffectPhaser::get_range_min_hz);
+ ClassDB::bind_method(D_METHOD("set_range_min_hz","hz"),&AudioEffectPhaser::set_range_min_hz);
+ ClassDB::bind_method(D_METHOD("get_range_min_hz"),&AudioEffectPhaser::get_range_min_hz);
- ClassDB::bind_method(_MD("set_range_max_hz","hz"),&AudioEffectPhaser::set_range_max_hz);
- ClassDB::bind_method(_MD("get_range_max_hz"),&AudioEffectPhaser::get_range_max_hz);
+ ClassDB::bind_method(D_METHOD("set_range_max_hz","hz"),&AudioEffectPhaser::set_range_max_hz);
+ ClassDB::bind_method(D_METHOD("get_range_max_hz"),&AudioEffectPhaser::get_range_max_hz);
- ClassDB::bind_method(_MD("set_rate_hz","hz"),&AudioEffectPhaser::set_rate_hz);
- ClassDB::bind_method(_MD("get_rate_hz"),&AudioEffectPhaser::get_rate_hz);
+ ClassDB::bind_method(D_METHOD("set_rate_hz","hz"),&AudioEffectPhaser::set_rate_hz);
+ ClassDB::bind_method(D_METHOD("get_rate_hz"),&AudioEffectPhaser::get_rate_hz);
- ClassDB::bind_method(_MD("set_feedback","fbk"),&AudioEffectPhaser::set_feedback);
- ClassDB::bind_method(_MD("get_feedback"),&AudioEffectPhaser::get_feedback);
+ ClassDB::bind_method(D_METHOD("set_feedback","fbk"),&AudioEffectPhaser::set_feedback);
+ ClassDB::bind_method(D_METHOD("get_feedback"),&AudioEffectPhaser::get_feedback);
- ClassDB::bind_method(_MD("set_depth","depth"),&AudioEffectPhaser::set_depth);
- ClassDB::bind_method(_MD("get_depth"),&AudioEffectPhaser::get_depth);
+ ClassDB::bind_method(D_METHOD("set_depth","depth"),&AudioEffectPhaser::set_depth);
+ ClassDB::bind_method(D_METHOD("get_depth"),&AudioEffectPhaser::get_depth);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_min_hz",PROPERTY_HINT_RANGE,"10,10000"),_SCS("set_range_min_hz"),_SCS("get_range_min_hz"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_max_hz",PROPERTY_HINT_RANGE,"10,10000"),_SCS("set_range_max_hz"),_SCS("get_range_max_hz"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"rate_hz",PROPERTY_HINT_RANGE,"0.01,20"),_SCS("set_rate_hz"),_SCS("get_rate_hz"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback",PROPERTY_HINT_RANGE,"0.1,0.9,0.1"),_SCS("set_feedback"),_SCS("get_feedback"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"depth",PROPERTY_HINT_RANGE,"0.1,4,0.1"),_SCS("set_depth"),_SCS("get_depth"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_min_hz",PROPERTY_HINT_RANGE,"10,10000"),"set_range_min_hz","get_range_min_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_max_hz",PROPERTY_HINT_RANGE,"10,10000"),"set_range_max_hz","get_range_max_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"rate_hz",PROPERTY_HINT_RANGE,"0.01,20"),"set_rate_hz","get_rate_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback",PROPERTY_HINT_RANGE,"0.1,0.9,0.1"),"set_feedback","get_feedback");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"depth",PROPERTY_HINT_RANGE,"0.1,4,0.1"),"set_depth","get_depth");
}
diff --git a/servers/audio/effects/audio_effect_phaser.h b/servers/audio/effects/audio_effect_phaser.h
index 53a8ab8bd8..a7294183f6 100644
--- a/servers/audio/effects/audio_effect_phaser.h
+++ b/servers/audio/effects/audio_effect_phaser.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_phaser.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIO_EFFECT_PHASER_H
#define AUDIO_EFFECT_PHASER_H
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
index 49a14cda04..e00755e1a0 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.cpp
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -1,6 +1,39 @@
+/*************************************************************************/
+/* audio_effect_pitch_shift.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_pitch_shift.h"
+
#include "servers/audio_server.h"
#include "math_funcs.h"
+
+/* Thirdparty code, so disable clang-format with Godot style */
+/* clang-format off */
+
/****************************************************************************
*
* NAME: smbPitchShift.cpp
@@ -39,7 +72,6 @@
*
*****************************************************************************/
-
void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata,int stride) {
@@ -220,7 +252,7 @@ void SMBPitchShift::smbFft(float *fftBuffer, long fftFrameSize, long sign)
*p1 = *p2; *p2 = temp;
}
}
- for (k = 0, le = 2; k < (long)(log(fftFrameSize)/log(2.)+.5); k++) {
+ for (k = 0, le = 2; k < (long)(log((double)fftFrameSize)/log(2.)+.5); k++) {
le <<= 1;
le2 = le>>1;
ur = 1.0;
@@ -246,6 +278,8 @@ void SMBPitchShift::smbFft(float *fftBuffer, long fftFrameSize, long sign)
}
}
+/* Godot code again */
+/* clang-format on */
void AudioEffectPitchShiftInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
@@ -285,10 +319,10 @@ float AudioEffectPitchShift::get_pitch_scale() const {
void AudioEffectPitchShift::_bind_methods() {
- ClassDB::bind_method(_MD("set_pitch_scale","rate"),&AudioEffectPitchShift::set_pitch_scale);
- ClassDB::bind_method(_MD("get_pitch_scale"),&AudioEffectPitchShift::get_pitch_scale);
+ ClassDB::bind_method(D_METHOD("set_pitch_scale","rate"),&AudioEffectPitchShift::set_pitch_scale);
+ ClassDB::bind_method(D_METHOD("get_pitch_scale"),&AudioEffectPitchShift::get_pitch_scale);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,16,0.01"),_SCS("set_pitch_scale"),_SCS("get_pitch_scale"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_pitch_scale","get_pitch_scale");
}
diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h
index d1343a0745..1320976f5f 100644
--- a/servers/audio/effects/audio_effect_pitch_shift.h
+++ b/servers/audio/effects/audio_effect_pitch_shift.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_pitch_shift.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIO_EFFECT_PITCH_SHIFT_H
#define AUDIO_EFFECT_PITCH_SHIFT_H
diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp
index 749814fd76..d668c63e8e 100644
--- a/servers/audio/effects/audio_effect_reverb.cpp
+++ b/servers/audio/effects/audio_effect_reverb.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_reverb.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_reverb.h"
#include "servers/audio_server.h"
void AudioEffectReverbInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
@@ -132,41 +160,41 @@ float AudioEffectReverb::get_hpf() const {
void AudioEffectReverb::_bind_methods() {
- ClassDB::bind_method(_MD("set_predelay_msec","msec"),&AudioEffectReverb::set_predelay_msec);
- ClassDB::bind_method(_MD("get_predelay_msec"),&AudioEffectReverb::get_predelay_msec);
+ ClassDB::bind_method(D_METHOD("set_predelay_msec","msec"),&AudioEffectReverb::set_predelay_msec);
+ ClassDB::bind_method(D_METHOD("get_predelay_msec"),&AudioEffectReverb::get_predelay_msec);
- ClassDB::bind_method(_MD("set_predelay_feedback","feedback"),&AudioEffectReverb::set_predelay_feedback);
- ClassDB::bind_method(_MD("get_predelay_feedback"),&AudioEffectReverb::get_predelay_feedback);
+ ClassDB::bind_method(D_METHOD("set_predelay_feedback","feedback"),&AudioEffectReverb::set_predelay_feedback);
+ ClassDB::bind_method(D_METHOD("get_predelay_feedback"),&AudioEffectReverb::get_predelay_feedback);
- ClassDB::bind_method(_MD("set_room_size","size"),&AudioEffectReverb::set_room_size);
- ClassDB::bind_method(_MD("get_room_size"),&AudioEffectReverb::get_room_size);
+ ClassDB::bind_method(D_METHOD("set_room_size","size"),&AudioEffectReverb::set_room_size);
+ ClassDB::bind_method(D_METHOD("get_room_size"),&AudioEffectReverb::get_room_size);
- ClassDB::bind_method(_MD("set_damping","amount"),&AudioEffectReverb::set_damping);
- ClassDB::bind_method(_MD("get_damping"),&AudioEffectReverb::get_damping);
+ ClassDB::bind_method(D_METHOD("set_damping","amount"),&AudioEffectReverb::set_damping);
+ ClassDB::bind_method(D_METHOD("get_damping"),&AudioEffectReverb::get_damping);
- ClassDB::bind_method(_MD("set_spread","amount"),&AudioEffectReverb::set_spread);
- ClassDB::bind_method(_MD("get_spread"),&AudioEffectReverb::get_spread);
+ ClassDB::bind_method(D_METHOD("set_spread","amount"),&AudioEffectReverb::set_spread);
+ ClassDB::bind_method(D_METHOD("get_spread"),&AudioEffectReverb::get_spread);
- ClassDB::bind_method(_MD("set_dry","amount"),&AudioEffectReverb::set_dry);
- ClassDB::bind_method(_MD("get_dry"),&AudioEffectReverb::get_dry);
+ ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectReverb::set_dry);
+ ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectReverb::get_dry);
- ClassDB::bind_method(_MD("set_wet","amount"),&AudioEffectReverb::set_wet);
- ClassDB::bind_method(_MD("get_wet"),&AudioEffectReverb::get_wet);
+ ClassDB::bind_method(D_METHOD("set_wet","amount"),&AudioEffectReverb::set_wet);
+ ClassDB::bind_method(D_METHOD("get_wet"),&AudioEffectReverb::get_wet);
- ClassDB::bind_method(_MD("set_hpf","amount"),&AudioEffectReverb::set_hpf);
- ClassDB::bind_method(_MD("get_hpf"),&AudioEffectReverb::get_hpf);
+ ClassDB::bind_method(D_METHOD("set_hpf","amount"),&AudioEffectReverb::set_hpf);
+ ClassDB::bind_method(D_METHOD("get_hpf"),&AudioEffectReverb::get_hpf);
ADD_GROUP("Predelay","predelay_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_msec",PROPERTY_HINT_RANGE,"20,500,1"),_SCS("set_predelay_msec"),_SCS("get_predelay_msec"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_feedback",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_predelay_msec"),_SCS("get_predelay_msec"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_msec",PROPERTY_HINT_RANGE,"20,500,1"),"set_predelay_msec","get_predelay_msec");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_feedback",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_predelay_msec","get_predelay_msec");
ADD_GROUP("","");
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"room_size",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_room_size"),_SCS("get_room_size"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_damping"),_SCS("get_damping"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"spread",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_spread"),_SCS("get_spread"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"hipass",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_hpf"),_SCS("get_hpf"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dry"),_SCS("get_dry"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_wet"),_SCS("get_wet"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"room_size",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_room_size","get_room_size");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_damping","get_damping");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"spread",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_spread","get_spread");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"hipass",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_hpf","get_hpf");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_wet","get_wet");
}
AudioEffectReverb::AudioEffectReverb() {
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
index e05ffe422f..41b4f15cf0 100644
--- a/servers/audio/effects/audio_effect_reverb.h
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_reverb.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTREVERB_H
#define AUDIOEFFECTREVERB_H
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp
index c5968aa772..388c38ed17 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.cpp
+++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_stereo_enhance.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
#include "audio_effect_stereo_enhance.h"
#include "servers/audio_server.h"
void AudioEffectStereoEnhanceInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
@@ -113,18 +141,18 @@ float AudioEffectStereoEnhance::get_surround() const {
void AudioEffectStereoEnhance::_bind_methods() {
- ClassDB::bind_method(_MD("set_pan_pullout","amount"),&AudioEffectStereoEnhance::set_pan_pullout);
- ClassDB::bind_method(_MD("get_pan_pullout"),&AudioEffectStereoEnhance::get_pan_pullout);
+ ClassDB::bind_method(D_METHOD("set_pan_pullout","amount"),&AudioEffectStereoEnhance::set_pan_pullout);
+ ClassDB::bind_method(D_METHOD("get_pan_pullout"),&AudioEffectStereoEnhance::get_pan_pullout);
- ClassDB::bind_method(_MD("set_time_pullout","amount"),&AudioEffectStereoEnhance::set_time_pullout);
- ClassDB::bind_method(_MD("get_time_pullout"),&AudioEffectStereoEnhance::get_time_pullout);
+ ClassDB::bind_method(D_METHOD("set_time_pullout","amount"),&AudioEffectStereoEnhance::set_time_pullout);
+ ClassDB::bind_method(D_METHOD("get_time_pullout"),&AudioEffectStereoEnhance::get_time_pullout);
- ClassDB::bind_method(_MD("set_surround","amount"),&AudioEffectStereoEnhance::set_surround);
- ClassDB::bind_method(_MD("get_surround"),&AudioEffectStereoEnhance::get_surround);
+ ClassDB::bind_method(D_METHOD("set_surround","amount"),&AudioEffectStereoEnhance::set_surround);
+ ClassDB::bind_method(D_METHOD("get_surround"),&AudioEffectStereoEnhance::get_surround);
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan_pullout",PROPERTY_HINT_RANGE,"0,4,0.01"),_SCS("set_pan_pullout"),_SCS("get_pan_pullout"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"time_pullout_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),_SCS("set_time_pullout"),_SCS("get_time_pullout"));
- ADD_PROPERTY(PropertyInfo(Variant::REAL,"surround",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_surround"),_SCS("get_surround"));
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan_pullout",PROPERTY_HINT_RANGE,"0,4,0.01"),"set_pan_pullout","get_pan_pullout");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"time_pullout_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_time_pullout","get_time_pullout");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"surround",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_surround","get_surround");
}
AudioEffectStereoEnhance::AudioEffectStereoEnhance()
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h
index 06762acbf3..5eef8a33b2 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.h
+++ b/servers/audio/effects/audio_effect_stereo_enhance.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* audio_effect_stereo_enhance.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 AUDIOEFFECTSTEREOENHANCE_H
#define AUDIOEFFECTSTEREOENHANCE_H
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp
index a6499a66b4..4b461e97bb 100644
--- a/servers/audio/effects/eq.cpp
+++ b/servers/audio/effects/eq.cpp
@@ -1,14 +1,34 @@
-//
-// C++ Interface: eq
-//
-// Description:
-//
-//
+/*************************************************************************/
+/* eq.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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: reduzio@gmail.com (C) 2006
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
+
#include "eq.h"
#include <math.h>
#include "error_macros.h"
@@ -47,7 +67,7 @@ EQ::BandProcess::BandProcess() {
void EQ::recalculate_band_coefficients() {
-#define BAND_LOG( m_f ) ( log((m_f)) / log(2) )
+#define BAND_LOG( m_f ) ( log((m_f)) / log(2.) )
for (int i=0;i<band.size();i++) {
diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h
index 2c4668cd0b..1a568ee213 100644
--- a/servers/audio/effects/eq.h
+++ b/servers/audio/effects/eq.h
@@ -1,14 +1,34 @@
-//
-// C++ Interface: eq
-//
-// Description:
-//
-//
+/*************************************************************************/
+/* eq.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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: reduzio@gmail.com (C) 2006
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
+
#ifndef EQ_FILTER_H
#define EQ_FILTER_H
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp
index 43ea0edb3a..bc3212201f 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb.cpp
@@ -1,14 +1,33 @@
-//
-// C++ Interface: reverb
-//
-// Description:
-//
-//
+/*************************************************************************/
+/* reverb.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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: Juan Linietsky <reduzio@gmail.com>, (C) 2006
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
#include "reverb.h"
#include <math.h>
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h
index 2c82be9156..f0a0466f8a 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb.h
@@ -1,14 +1,34 @@
-//
-// C++ Interface: reverb
-//
-// Description:
-//
-//
+/*************************************************************************/
+/* reverb.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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: Juan Linietsky <reduzio@gmail.com>, (C) 2006
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
+
#ifndef REVERB_H
#define REVERB_H
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 8a8b9ebf76..192d958a64 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "audio_server.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
#include "servers/audio/effects/audio_effect_compressor.h"
#include "io/resource_loader.h"
@@ -1019,52 +1019,52 @@ Ref<AudioBusLayout> AudioServer::generate_bus_layout() const {
void AudioServer::_bind_methods() {
- ClassDB::bind_method(_MD("set_bus_count","amount"),&AudioServer::set_bus_count);
- ClassDB::bind_method(_MD("get_bus_count"),&AudioServer::get_bus_count);
+ ClassDB::bind_method(D_METHOD("set_bus_count","amount"),&AudioServer::set_bus_count);
+ ClassDB::bind_method(D_METHOD("get_bus_count"),&AudioServer::get_bus_count);
- ClassDB::bind_method(_MD("remove_bus","index"),&AudioServer::remove_bus);
- ClassDB::bind_method(_MD("add_bus","at_pos"),&AudioServer::add_bus,DEFVAL(-1));
- ClassDB::bind_method(_MD("move_bus","index","to_index"),&AudioServer::move_bus);
+ ClassDB::bind_method(D_METHOD("remove_bus","index"),&AudioServer::remove_bus);
+ ClassDB::bind_method(D_METHOD("add_bus","at_pos"),&AudioServer::add_bus,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_bus","index","to_index"),&AudioServer::move_bus);
- ClassDB::bind_method(_MD("set_bus_name","bus_idx","name"),&AudioServer::set_bus_name);
- ClassDB::bind_method(_MD("get_bus_name","bus_idx"),&AudioServer::get_bus_name);
+ ClassDB::bind_method(D_METHOD("set_bus_name","bus_idx","name"),&AudioServer::set_bus_name);
+ ClassDB::bind_method(D_METHOD("get_bus_name","bus_idx"),&AudioServer::get_bus_name);
- ClassDB::bind_method(_MD("set_bus_volume_db","bus_idx","volume_db"),&AudioServer::set_bus_volume_db);
- ClassDB::bind_method(_MD("get_bus_volume_db","bus_idx"),&AudioServer::get_bus_volume_db);
+ ClassDB::bind_method(D_METHOD("set_bus_volume_db","bus_idx","volume_db"),&AudioServer::set_bus_volume_db);
+ ClassDB::bind_method(D_METHOD("get_bus_volume_db","bus_idx"),&AudioServer::get_bus_volume_db);
- ClassDB::bind_method(_MD("set_bus_send","bus_idx","send"),&AudioServer::set_bus_send);
- ClassDB::bind_method(_MD("get_bus_send","bus_idx"),&AudioServer::get_bus_send);
+ ClassDB::bind_method(D_METHOD("set_bus_send","bus_idx","send"),&AudioServer::set_bus_send);
+ ClassDB::bind_method(D_METHOD("get_bus_send","bus_idx"),&AudioServer::get_bus_send);
- ClassDB::bind_method(_MD("set_bus_solo","bus_idx","enable"),&AudioServer::set_bus_solo);
- ClassDB::bind_method(_MD("is_bus_solo","bus_idx"),&AudioServer::is_bus_solo);
+ ClassDB::bind_method(D_METHOD("set_bus_solo","bus_idx","enable"),&AudioServer::set_bus_solo);
+ ClassDB::bind_method(D_METHOD("is_bus_solo","bus_idx"),&AudioServer::is_bus_solo);
- ClassDB::bind_method(_MD("set_bus_mute","bus_idx","enable"),&AudioServer::set_bus_mute);
- ClassDB::bind_method(_MD("is_bus_mute","bus_idx"),&AudioServer::is_bus_mute);
+ ClassDB::bind_method(D_METHOD("set_bus_mute","bus_idx","enable"),&AudioServer::set_bus_mute);
+ ClassDB::bind_method(D_METHOD("is_bus_mute","bus_idx"),&AudioServer::is_bus_mute);
- ClassDB::bind_method(_MD("set_bus_bypass_effects","bus_idx","enable"),&AudioServer::set_bus_bypass_effects);
- ClassDB::bind_method(_MD("is_bus_bypassing_effects","bus_idx"),&AudioServer::is_bus_bypassing_effects);
+ ClassDB::bind_method(D_METHOD("set_bus_bypass_effects","bus_idx","enable"),&AudioServer::set_bus_bypass_effects);
+ ClassDB::bind_method(D_METHOD("is_bus_bypassing_effects","bus_idx"),&AudioServer::is_bus_bypassing_effects);
- ClassDB::bind_method(_MD("add_bus_effect","bus_idx","effect:AudioEffect"),&AudioServer::add_bus_effect,DEFVAL(-1));
- ClassDB::bind_method(_MD("remove_bus_effect","bus_idx","effect_idx"),&AudioServer::remove_bus_effect);
+ ClassDB::bind_method(D_METHOD("add_bus_effect","bus_idx","effect:AudioEffect"),&AudioServer::add_bus_effect,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("remove_bus_effect","bus_idx","effect_idx"),&AudioServer::remove_bus_effect);
- ClassDB::bind_method(_MD("get_bus_effect_count","bus_idx"),&AudioServer::add_bus_effect);
- ClassDB::bind_method(_MD("get_bus_effect:AudioEffect","bus_idx","effect_idx"),&AudioServer::get_bus_effect);
- ClassDB::bind_method(_MD("swap_bus_effects","bus_idx","effect_idx","by_effect_idx"),&AudioServer::swap_bus_effects);
+ ClassDB::bind_method(D_METHOD("get_bus_effect_count","bus_idx"),&AudioServer::add_bus_effect);
+ ClassDB::bind_method(D_METHOD("get_bus_effect:AudioEffect","bus_idx","effect_idx"),&AudioServer::get_bus_effect);
+ ClassDB::bind_method(D_METHOD("swap_bus_effects","bus_idx","effect_idx","by_effect_idx"),&AudioServer::swap_bus_effects);
- ClassDB::bind_method(_MD("set_bus_effect_enabled","bus_idx","effect_idx","enabled"),&AudioServer::set_bus_effect_enabled);
- ClassDB::bind_method(_MD("is_bus_effect_enabled","bus_idx","effect_idx"),&AudioServer::is_bus_effect_enabled);
+ ClassDB::bind_method(D_METHOD("set_bus_effect_enabled","bus_idx","effect_idx","enabled"),&AudioServer::set_bus_effect_enabled);
+ ClassDB::bind_method(D_METHOD("is_bus_effect_enabled","bus_idx","effect_idx"),&AudioServer::is_bus_effect_enabled);
- ClassDB::bind_method(_MD("get_bus_peak_volume_left_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_left_db);
- ClassDB::bind_method(_MD("get_bus_peak_volume_right_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_right_db);
+ ClassDB::bind_method(D_METHOD("get_bus_peak_volume_left_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_left_db);
+ ClassDB::bind_method(D_METHOD("get_bus_peak_volume_right_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_right_db);
- ClassDB::bind_method(_MD("lock"),&AudioServer::lock);
- ClassDB::bind_method(_MD("unlock"),&AudioServer::unlock);
+ ClassDB::bind_method(D_METHOD("lock"),&AudioServer::lock);
+ ClassDB::bind_method(D_METHOD("unlock"),&AudioServer::unlock);
- ClassDB::bind_method(_MD("get_speaker_mode"),&AudioServer::get_speaker_mode);
- ClassDB::bind_method(_MD("get_mix_rate"),&AudioServer::get_mix_rate);
+ ClassDB::bind_method(D_METHOD("get_speaker_mode"),&AudioServer::get_speaker_mode);
+ ClassDB::bind_method(D_METHOD("get_mix_rate"),&AudioServer::get_mix_rate);
- ClassDB::bind_method(_MD("set_state","state:AudioServerState"),&AudioServer::set_bus_layout);
- ClassDB::bind_method(_MD("generate_state:AudioServerState"),&AudioServer::generate_bus_layout);
+ ClassDB::bind_method(D_METHOD("set_state","state:AudioServerState"),&AudioServer::set_bus_layout);
+ ClassDB::bind_method(D_METHOD("generate_state:AudioServerState"),&AudioServer::generate_bus_layout);
ADD_SIGNAL(MethodInfo("bus_layout_changed") );
}
diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp
index e95c85d751..3aa0816b06 100644
--- a/servers/physics/area_pair_sw.cpp
+++ b/servers/physics/area_pair_sw.cpp
@@ -30,7 +30,7 @@
#include "collision_solver_sw.h"
-bool AreaPairSW::setup(float p_step) {
+bool AreaPairSW::setup(real_t p_step) {
if (!area->test_collision_mask(body)) {
colliding = false;
@@ -64,7 +64,7 @@ bool AreaPairSW::setup(float p_step) {
return false; //never do any post solving
}
-void AreaPairSW::solve(float p_step) {
+void AreaPairSW::solve(real_t p_step) {
}
@@ -103,7 +103,7 @@ AreaPairSW::~AreaPairSW() {
-bool Area2PairSW::setup(float p_step) {
+bool Area2PairSW::setup(real_t p_step) {
if (!area_a->test_collision_mask(area_b)) {
colliding = false;
@@ -139,7 +139,7 @@ bool Area2PairSW::setup(float p_step) {
return false; //never do any post solving
}
-void Area2PairSW::solve(float p_step) {
+void Area2PairSW::solve(real_t p_step) {
}
diff --git a/servers/physics/area_pair_sw.h b/servers/physics/area_pair_sw.h
index 17477dcbd2..637976a095 100644
--- a/servers/physics/area_pair_sw.h
+++ b/servers/physics/area_pair_sw.h
@@ -42,8 +42,8 @@ class AreaPairSW : public ConstraintSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape);
~AreaPairSW();
@@ -59,8 +59,8 @@ class Area2PairSW : public ConstraintSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
Area2PairSW(AreaSW *p_area_a,int p_shape_a, AreaSW *p_area_b,int p_shape_b);
~Area2PairSW();
diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h
index 5ac6985409..4e6f1c5a51 100644
--- a/servers/physics/area_sw.h
+++ b/servers/physics/area_sw.h
@@ -42,13 +42,13 @@ class AreaSW : public CollisionObjectSW{
PhysicsServer::AreaSpaceOverrideMode space_override_mode;
- float gravity;
+ real_t gravity;
Vector3 gravity_vector;
bool gravity_is_point;
- float gravity_distance_scale;
- float point_attenuation;
- float linear_damp;
- float angular_damp;
+ real_t gravity_distance_scale;
+ real_t point_attenuation;
+ real_t linear_damp;
+ real_t angular_damp;
int priority;
bool monitorable;
@@ -131,8 +131,8 @@ public:
void set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode);
PhysicsServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
- _FORCE_INLINE_ void set_gravity(float p_gravity) { gravity=p_gravity; }
- _FORCE_INLINE_ float get_gravity() const { return gravity; }
+ _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity=p_gravity; }
+ _FORCE_INLINE_ real_t get_gravity() const { return gravity; }
_FORCE_INLINE_ void set_gravity_vector(const Vector3& p_gravity) { gravity_vector=p_gravity; }
_FORCE_INLINE_ Vector3 get_gravity_vector() const { return gravity_vector; }
@@ -140,17 +140,17 @@ public:
_FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; }
_FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; }
- _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; }
- _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; }
+ _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale=scale; }
+ _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; }
- _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; }
- _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; }
+ _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation=p_point_attenuation; }
+ _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; }
- _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; }
- _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; }
+ _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp=p_linear_damp; }
+ _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
- _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; }
- _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; }
+ _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp=p_angular_damp; }
+ _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; }
_FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index 7defa87bb1..7fb3def387 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -105,7 +105,7 @@ void BodyPairSW::contact_added_callback(const Vector3& p_point_A,const Vector3&
// remove the contact with the minimum depth
int least_deep=-1;
- float min_depth=1e10;
+ real_t min_depth=1e10;
for (int i=0;i<=contact_count;i++) {
@@ -114,7 +114,7 @@ void BodyPairSW::contact_added_callback(const Vector3& p_point_A,const Vector3&
Vector3 global_B = B->get_transform().basis.xform(c.local_B)+offset_B;
Vector3 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
if (depth<min_depth) {
@@ -154,7 +154,7 @@ void BodyPairSW::validate_contacts() {
Vector3 global_A = A->get_transform().basis.xform(c.local_A);
Vector3 global_B = B->get_transform().basis.xform(c.local_B)+offset_B;
Vector3 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) {
// contact no longer needed, remove
@@ -173,7 +173,7 @@ void BodyPairSW::validate_contacts() {
}
-bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) {
+bool BodyPairSW::_test_ccd(real_t p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) {
@@ -211,14 +211,14 @@ bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transfo
//shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough
Vector3 hitpos = p_xform_B.xform(rpos);
- float newlen = hitpos.distance_to(from)-(max-min)*0.01;
+ real_t newlen = hitpos.distance_to(from)-(max-min)*0.01;
p_A->set_linear_velocity((mnormal*newlen)/p_step);
return true;
}
-bool BodyPairSW::setup(float p_step) {
+bool BodyPairSW::setup(real_t p_step) {
//cannot collide
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) {
@@ -264,7 +264,7 @@ bool BodyPairSW::setup(float p_step) {
real_t max_penetration = space->get_contact_max_allowed_penetration();
- float bias = 0.3f;
+ real_t bias = (real_t)0.3;
if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) {
@@ -356,7 +356,7 @@ bool BodyPairSW::setup(float p_step) {
if (depth > max_penetration) {
c.bias = (depth - max_penetration) * (1.0/(p_step*(1.0/RELAXATION_TIMESTEPS)));
} else {
- float approach = -0.1f * (depth - max_penetration) / (CMP_EPSILON + max_penetration);
+ real_t approach = -0.1 * (depth - max_penetration) / (CMP_EPSILON + max_penetration);
approach = CLAMP( approach, CMP_EPSILON, 1.0 );
c.bias = approach * (depth - max_penetration) * (1.0/p_step);
}
@@ -387,7 +387,7 @@ bool BodyPairSW::setup(float p_step) {
return true;
}
-void BodyPairSW::solve(float p_step) {
+void BodyPairSW::solve(real_t p_step) {
if (!collided)
return;
diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h
index a37f75d13c..f282a56b9e 100644
--- a/servers/physics/body_pair_sw.h
+++ b/servers/physics/body_pair_sw.h
@@ -82,14 +82,14 @@ class BodyPairSW : public ConstraintSW {
void contact_added_callback(const Vector3& p_point_A,const Vector3& p_point_B);
void validate_contacts();
- bool _test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B);
+ bool _test_ccd(real_t p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B);
SpaceSW *space;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
BodyPairSW(BodySW *p_A, int p_shape_A,BodySW *p_B, int p_shape_B);
~BodyPairSW();
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index a67dda3a01..7fcd767268 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -59,7 +59,7 @@ void BodySW::update_inertias() {
case PhysicsServer::BODY_MODE_RIGID: {
//update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet)
- float total_area=0;
+ real_t total_area=0;
for (int i=0;i<get_shape_count();i++) {
@@ -70,9 +70,9 @@ void BodySW::update_inertias() {
center_of_mass_local.zero();
for (int i=0; i<get_shape_count(); i++) {
- float area=get_shape_area(i);
+ real_t area=get_shape_area(i);
- float mass = area * this->mass / total_area;
+ real_t mass = area * this->mass / total_area;
// NOTE: we assume that the shape origin is also its center of mass
center_of_mass_local += mass * get_shape_transform(i).origin;
@@ -88,9 +88,9 @@ void BodySW::update_inertias() {
const ShapeSW* shape=get_shape(i);
- float area=get_shape_area(i);
+ real_t area=get_shape_area(i);
- float mass = area * this->mass / total_area;
+ real_t mass = area * this->mass / total_area;
Basis shape_inertia_tensor=shape->get_moment_of_inertia(mass).to_diagonal_matrix();
Transform shape_transform=get_shape_transform(i);
@@ -170,7 +170,7 @@ void BodySW::set_active(bool p_active) {
-void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) {
+void BodySW::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) {
switch(p_param) {
case PhysicsServer::BODY_PARAM_BOUNCE: {
@@ -202,7 +202,7 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) {
}
}
-float BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
+real_t BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
switch(p_param) {
case PhysicsServer::BODY_PARAM_BOUNCE: {
@@ -511,7 +511,7 @@ void BodySW::integrate_forces(real_t p_step) {
//compute a FAKE angular velocity, not so easy
Basis rot=new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized();
Vector3 axis;
- float angle;
+ real_t angle;
rot.get_axis_and_angle(axis,angle);
axis.normalize();
@@ -615,7 +615,7 @@ void BodySW::integrate_velocities(real_t p_step) {
- float ang_vel = total_angular_velocity.length();
+ real_t ang_vel = total_angular_velocity.length();
Transform transform = get_transform();
@@ -666,7 +666,7 @@ void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) {
//compute a FAKE angular velocity, not so easy
Matrix3 rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized();
Vector3 axis;
- float angle;
+ real_t angle;
rot.get_axis_and_angle(axis,angle);
axis.normalize();
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index e6ed3e75e5..2383d2d688 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -75,8 +75,8 @@ class BodySW : public CollisionObjectSW {
Vector3 applied_force;
Vector3 applied_torque;
- float area_angular_damp;
- float area_linear_damp;
+ real_t area_angular_damp;
+ real_t area_linear_damp;
SelfList<BodySW> active_list;
@@ -115,7 +115,7 @@ class BodySW : public CollisionObjectSW {
Vector3 local_pos;
Vector3 local_normal;
- float depth;
+ real_t depth;
int local_shape;
Vector3 collider_pos;
int collider_shape;
@@ -174,7 +174,7 @@ public:
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
- _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos);
+ _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, real_t p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos);
_FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);}
@@ -248,8 +248,8 @@ public:
set_active(true);
}
- void set_param(PhysicsServer::BodyParameter p_param, float);
- float get_param(PhysicsServer::BodyParameter p_param) const;
+ void set_param(PhysicsServer::BodyParameter p_param, real_t);
+ real_t get_param(PhysicsServer::BodyParameter p_param) const;
void set_mode(PhysicsServer::BodyMode p_mode);
PhysicsServer::BodyMode get_mode() const;
@@ -319,7 +319,7 @@ public:
//add contact inline
-void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) {
+void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, real_t p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) {
int c_max=contacts.size();
@@ -335,7 +335,7 @@ void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_norma
idx=contact_count++;
} else {
- float least_depth=1e20;
+ real_t least_depth=1e20;
int least_deep=-1;
for(int i=0;i<c_max;i++) {
@@ -377,13 +377,13 @@ public:
real_t step;
virtual Vector3 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area
- virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
- virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
+ virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
+ virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
virtual Vector3 get_center_of_mass() const { return body->get_center_of_mass(); }
virtual Basis get_principal_inertia_axes() const { return body->get_principal_inertia_axes(); }
- virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
+ virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
virtual Basis get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space
diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp
index d41012caa4..9d3e1db47b 100644
--- a/servers/physics/collision_solver_sat.cpp
+++ b/servers/physics/collision_solver_sat.cpp
@@ -122,9 +122,9 @@ static void _generate_contacts_edge_edge(const Vector3 * p_points_A,int p_point_
Vector3 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]);
//sort all 4 points in axis
- float dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
+ real_t dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
- SortArray<float> sa;
+ SortArray<real_t> sa;
sa.sort(dvec,4);
//use the middle ones as contacts
@@ -234,7 +234,7 @@ static void _generate_contacts_face_face(const Vector3 * p_points_A,int p_point_
for (int i=0;i<clipbuf_len;i++) {
- float d = plane_B.distance_to(clipbuf_src[i]);
+ real_t d = plane_B.distance_to(clipbuf_src[i]);
/*
if (d>CMP_EPSILON)
continue;
@@ -476,11 +476,11 @@ public:
/****** SAT TESTS *******/
-typedef void (*CollisionFunc)(const ShapeSW*,const Transform&,const ShapeSW*,const Transform&,_CollectorCallback *p_callback,float,float);
+typedef void (*CollisionFunc)(const ShapeSW*,const Transform&,const ShapeSW*,const Transform&,_CollectorCallback *p_callback,real_t,real_t);
template<bool withMargin>
-static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
@@ -500,7 +500,7 @@ static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_trans
}
template<bool withMargin>
-static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
@@ -555,7 +555,7 @@ static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transfor
}
template<bool withMargin>
-static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b);
@@ -595,7 +595,7 @@ static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_tran
}
template<bool withMargin>
-static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
@@ -666,7 +666,7 @@ static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform
}
template<bool withMargin>
-static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
const FaceShapeSW *face_B = static_cast<const FaceShapeSW*>(p_b);
@@ -710,7 +710,7 @@ static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transfo
template<bool withMargin>
-static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a);
@@ -818,7 +818,7 @@ static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a
}
template<bool withMargin>
-static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a);
const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b);
@@ -918,7 +918,7 @@ static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transfo
}
template<bool withMargin>
-static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
@@ -1046,7 +1046,7 @@ static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_
template<bool withMargin>
-static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a);
@@ -1158,7 +1158,7 @@ static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_
template<bool withMargin>
-static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a);
const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b);
@@ -1216,7 +1216,7 @@ static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_tra
}
template<bool withMargin>
-static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a);
@@ -1287,7 +1287,7 @@ static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform
template<bool withMargin>
-static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a);
const FaceShapeSW *face_B = static_cast<const FaceShapeSW*>(p_b);
@@ -1350,7 +1350,7 @@ static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transf
template<bool withMargin>
-static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const ConvexPolygonShapeSW *convex_polygon_A = static_cast<const ConvexPolygonShapeSW*>(p_a);
@@ -1474,7 +1474,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Tr
template<bool withMargin>
-static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const ConvexPolygonShapeSW *convex_polygon_A = static_cast<const ConvexPolygonShapeSW*>(p_a);
@@ -1585,7 +1585,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p
}
-bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata,bool p_swap,Vector3* r_prev_axis,float p_margin_a,float p_margin_b) {
+bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata,bool p_swap,Vector3* r_prev_axis,real_t p_margin_a,real_t p_margin_b) {
PhysicsServer::ShapeType type_A=p_shape_A->get_type();
@@ -1667,8 +1667,8 @@ bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_tran
const ShapeSW *B=p_shape_B;
const Transform *transform_A=&p_transform_A;
const Transform *transform_B=&p_transform_B;
- float margin_A=p_margin_a;
- float margin_B=p_margin_b;
+ real_t margin_A=p_margin_a;
+ real_t margin_B=p_margin_b;
if (type_A > type_B) {
SWAP(A,B);
diff --git a/servers/physics/collision_solver_sat.h b/servers/physics/collision_solver_sat.h
index 60387a978d..15fe7dc34a 100644
--- a/servers/physics/collision_solver_sat.h
+++ b/servers/physics/collision_solver_sat.h
@@ -32,6 +32,6 @@
#include "collision_solver_sw.h"
-bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector3* r_prev_axis=NULL,float p_margin_a=0,float p_margin_b=0);
+bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector3* r_prev_axis=NULL,real_t p_margin_a=0,real_t p_margin_b=0);
#endif // COLLISION_SOLVER_SAT_H
diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp
index 3399849ab7..f0ddde3a76 100644
--- a/servers/physics/collision_solver_sw.cpp
+++ b/servers/physics/collision_solver_sw.cpp
@@ -115,8 +115,8 @@ struct _ConcaveCollisionInfo {
int aabb_tests;
int collisions;
bool tested;
- float margin_A;
- float margin_B;
+ real_t margin_A;
+ real_t margin_B;
Vector3 close_A,close_B;
};
@@ -136,7 +136,7 @@ void CollisionSolverSW::concave_callback(void *p_userdata, ShapeSW *p_convex) {
}
-bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A,float p_margin_B) {
+bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,real_t p_margin_A,real_t p_margin_B) {
const ConcaveShapeSW *concave_B=static_cast<const ConcaveShapeSW*>(p_shape_B);
@@ -164,10 +164,10 @@ bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform&
for(int i=0;i<3;i++) {
Vector3 axis( p_transform_B.basis.get_axis(i) );
- float axis_scale = 1.0/axis.length();
+ real_t axis_scale = 1.0/axis.length();
axis*=axis_scale;
- float smin,smax;
+ real_t smin,smax;
p_shape_A->project_range(axis,rel_transform,smin,smax);
smin-=p_margin_A;
smax+=p_margin_A;
@@ -186,7 +186,7 @@ bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform&
}
-bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis,float p_margin_A,float p_margin_B) {
+bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis,real_t p_margin_A,real_t p_margin_B) {
PhysicsServer::ShapeType type_A=p_shape_A->get_type();
@@ -291,7 +291,7 @@ bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A,const Tran
bool collided=false;
Vector3 closest;
- float closest_d;
+ real_t closest_d;
for(int i=0;i<support_count;i++) {
@@ -362,10 +362,10 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform&
for(int i=0;i<3;i++) {
Vector3 axis( p_transform_B.basis.get_axis(i) );
- float axis_scale = 1.0/axis.length();
+ real_t axis_scale = ((real_t)1.0)/axis.length();
axis*=axis_scale;
- float smin,smax;
+ real_t smin,smax;
if (use_cc_hint) {
cc_hint_aabb.project_range_in_plane(Plane(axis,0),smin,smax);
diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h
index 16d2b92d70..b8d37a8a96 100644
--- a/servers/physics/collision_solver_sw.h
+++ b/servers/physics/collision_solver_sw.h
@@ -40,14 +40,14 @@ private:
static void concave_callback(void *p_userdata, ShapeSW *p_convex);
static bool solve_static_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
static bool solve_ray(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
- static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A=0,float p_margin_B=0);
+ static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,real_t p_margin_A=0,real_t p_margin_B=0);
static void concave_distance_callback(void *p_userdata, ShapeSW *p_convex);
static bool solve_distance_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B);
public:
- static bool solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
+ static bool solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
static bool solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const Rect3& p_concave_hint,Vector3 *r_sep_axis=NULL);
};
diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h
index adc17cb753..f5bbe4bbd0 100644
--- a/servers/physics/constraint_sw.h
+++ b/servers/physics/constraint_sw.h
@@ -67,8 +67,8 @@ public:
_FORCE_INLINE_ int get_priority() const { return priority; }
- virtual bool setup(float p_step)=0;
- virtual void solve(float p_step)=0;
+ virtual bool setup(real_t p_step)=0;
+ virtual void solve(real_t p_step)=0;
virtual ~ConstraintSW() {}
};
diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp
index cbf444f1e8..d78bcbd16d 100644
--- a/servers/physics/joints/cone_twist_joint_sw.cpp
+++ b/servers/physics/joints/cone_twist_joint_sw.cpp
@@ -96,7 +96,7 @@ ConeTwistJointSW::ConeTwistJointSW(BodySW* rbA,BodySW* rbB,const Transform& rbAF
}
-bool ConeTwistJointSW::setup(float p_step) {
+bool ConeTwistJointSW::setup(real_t p_step) {
m_appliedImpulse = real_t(0.);
//set bias, sign, clear accumulator
@@ -318,7 +318,7 @@ void ConeTwistJointSW::solve(real_t timeStep)
}
-void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, float p_value) {
+void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) {
switch(p_param) {
case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: {
@@ -345,7 +345,7 @@ void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, flo
}
}
-float ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) const{
+real_t ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) const{
switch(p_param) {
case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: {
diff --git a/servers/physics/joints/cone_twist_joint_sw.h b/servers/physics/joints/cone_twist_joint_sw.h
index 0d64d67443..eb7a5cd1b1 100644
--- a/servers/physics/joints/cone_twist_joint_sw.h
+++ b/servers/physics/joints/cone_twist_joint_sw.h
@@ -109,8 +109,8 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
ConeTwistJointSW(BodySW* rbA,BodySW* rbB,const Transform& rbAFrame, const Transform& rbBFrame);
@@ -146,8 +146,8 @@ public:
return m_twistLimitSign;
}
- void set_param(PhysicsServer::ConeTwistJointParam p_param, float p_value);
- float get_param(PhysicsServer::ConeTwistJointParam p_param) const;
+ void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const;
};
diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp
index 8d3fc4721a..bd07f3122a 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.cpp
+++ b/servers/physics/joints/generic_6dof_joint_sw.cpp
@@ -38,54 +38,6 @@ See corresponding header file for licensing info.
#define GENERIC_D6_DISABLE_WARMSTARTING 1
-real_t btGetMatrixElem(const Basis& mat, int index);
-real_t btGetMatrixElem(const Basis& mat, int index)
-{
- int i = index%3;
- int j = index/3;
- return mat[i][j];
-}
-
-///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-bool matrixToEulerXYZ(const Basis& mat,Vector3& xyz);
-bool matrixToEulerXYZ(const Basis& mat,Vector3& xyz)
-{
- // rot = cy*cz -cy*sz sy
- // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
- // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
-
- if (btGetMatrixElem(mat,2) < real_t(1.0))
- {
- if (btGetMatrixElem(mat,2) > real_t(-1.0))
- {
- xyz[0] = Math::atan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
- xyz[1] = Math::asin(btGetMatrixElem(mat,2));
- xyz[2] = Math::atan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
- return true;
- }
- else
- {
- // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -Math::atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
- xyz[1] = -Math_PI*0.5;
- xyz[2] = real_t(0.0);
- return false;
- }
- }
- else
- {
- // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = Math::atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
- xyz[1] = Math_PI*0.5;
- xyz[2] = 0.0;
-
- }
-
-
- return false;
-}
-
-
//////////////////////////// G6DOFRotationalLimitMotorSW ////////////////////////////////////
@@ -297,7 +249,7 @@ void Generic6DOFJointSW::calculateAngleInfo()
{
Basis relative_frame = m_calculatedTransformA.basis.inverse()*m_calculatedTransformB.basis;
- matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
+ m_calculatedAxisAngleDiff = relative_frame.get_euler();
@@ -385,7 +337,7 @@ bool Generic6DOFJointSW::testAngularLimitMotor(int axis_index)
return m_angularLimits[axis_index].needApplyTorques();
}
-bool Generic6DOFJointSW::setup(float p_step) {
+bool Generic6DOFJointSW::setup(real_t p_step) {
// Clear accumulated impulses for the next simulation step
m_linearLimits.m_accumulatedImpulse=Vector3(real_t(0.), real_t(0.), real_t(0.));
@@ -531,7 +483,7 @@ void Generic6DOFJointSW::calcAnchorPos(void)
} // Generic6DOFJointSW::calcAnchorPos()
-void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, float p_value) {
+void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) {
ERR_FAIL_INDEX(p_axis,3);
switch(p_param) {
@@ -607,7 +559,7 @@ void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJoin
}
}
-float Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const{
+real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const{
ERR_FAIL_INDEX_V(p_axis,3,0);
switch(p_param) {
case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {
diff --git a/servers/physics/joints/generic_6dof_joint_sw.h b/servers/physics/joints/generic_6dof_joint_sw.h
index 4ac727c124..207ae85a45 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.h
+++ b/servers/physics/joints/generic_6dof_joint_sw.h
@@ -295,8 +295,8 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
//! Calcs global transform of the offsets
@@ -449,8 +449,8 @@ public:
virtual void calcAnchorPos(void); // overridable
- void set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, float p_value);
- float get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const;
+ void set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value);
+ real_t get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const;
void set_flag(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value);
bool get_flag(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisFlag p_flag) const;
diff --git a/servers/physics/joints/hinge_joint_sw.cpp b/servers/physics/joints/hinge_joint_sw.cpp
index d50d5a1a73..9617eb8794 100644
--- a/servers/physics/joints/hinge_joint_sw.cpp
+++ b/servers/physics/joints/hinge_joint_sw.cpp
@@ -148,7 +148,7 @@ HingeJointSW::HingeJointSW(BodySW* rbA,BodySW* rbB, const Vector3& pivotInA,cons
-bool HingeJointSW::setup(float p_step) {
+bool HingeJointSW::setup(real_t p_step) {
m_appliedImpulse = real_t(0.);
@@ -262,7 +262,7 @@ bool HingeJointSW::setup(float p_step) {
return true;
}
-void HingeJointSW::solve(float p_step) {
+void HingeJointSW::solve(real_t p_step) {
Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin);
Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin);
@@ -418,7 +418,7 @@ real_t HingeJointSW::get_hinge_angle() {
}
-void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, float p_value) {
+void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) {
switch (p_param) {
@@ -434,7 +434,7 @@ void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, float p_val
}
}
-float HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const{
+real_t HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const{
switch (p_param) {
diff --git a/servers/physics/joints/hinge_joint_sw.h b/servers/physics/joints/hinge_joint_sw.h
index 60203e3cc4..8469fd1ca0 100644
--- a/servers/physics/joints/hinge_joint_sw.h
+++ b/servers/physics/joints/hinge_joint_sw.h
@@ -103,13 +103,13 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_HINGE; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
real_t get_hinge_angle();
- void set_param(PhysicsServer::HingeJointParam p_param, float p_value);
- float get_param(PhysicsServer::HingeJointParam p_param) const;
+ void set_param(PhysicsServer::HingeJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::HingeJointParam p_param) const;
void set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value);
bool get_flag(PhysicsServer::HingeJointFlag p_flag) const;
diff --git a/servers/physics/joints/pin_joint_sw.cpp b/servers/physics/joints/pin_joint_sw.cpp
index 9c7fe65684..b545ae630b 100644
--- a/servers/physics/joints/pin_joint_sw.cpp
+++ b/servers/physics/joints/pin_joint_sw.cpp
@@ -34,7 +34,7 @@ See corresponding header file for licensing info.
#include "pin_joint_sw.h"
-bool PinJointSW::setup(float p_step) {
+bool PinJointSW::setup(real_t p_step) {
m_appliedImpulse = real_t(0.);
@@ -59,7 +59,7 @@ bool PinJointSW::setup(float p_step) {
return true;
}
-void PinJointSW::solve(float p_step){
+void PinJointSW::solve(real_t p_step){
Vector3 pivotAInW = A->get_transform().xform(m_pivotInA);
Vector3 pivotBInW = B->get_transform().xform(m_pivotInB);
@@ -116,7 +116,7 @@ void PinJointSW::solve(float p_step){
}
}
-void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,float p_value) {
+void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,real_t p_value) {
switch(p_param) {
case PhysicsServer::PIN_JOINT_BIAS: m_tau=p_value; break;
@@ -125,7 +125,7 @@ void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,float p_value) {
}
}
-float PinJointSW::get_param(PhysicsServer::PinJointParam p_param) const{
+real_t PinJointSW::get_param(PhysicsServer::PinJointParam p_param) const{
switch(p_param) {
case PhysicsServer::PIN_JOINT_BIAS: return m_tau;
diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h
index 6797972496..b72b21219d 100644
--- a/servers/physics/joints/pin_joint_sw.h
+++ b/servers/physics/joints/pin_joint_sw.h
@@ -79,11 +79,11 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
- void set_param(PhysicsServer::PinJointParam p_param,float p_value);
- float get_param(PhysicsServer::PinJointParam p_param) const;
+ void set_param(PhysicsServer::PinJointParam p_param,real_t p_value);
+ real_t get_param(PhysicsServer::PinJointParam p_param) const;
void set_pos_A(const Vector3& p_pos) { m_pivotInA=p_pos; }
void set_pos_B(const Vector3& p_pos) { m_pivotInB=p_pos; }
diff --git a/servers/physics/joints/slider_joint_sw.cpp b/servers/physics/joints/slider_joint_sw.cpp
index bdcae08ca4..fc728ed0ba 100644
--- a/servers/physics/joints/slider_joint_sw.cpp
+++ b/servers/physics/joints/slider_joint_sw.cpp
@@ -112,7 +112,7 @@ SliderJointSW::SliderJointSW(BodySW* rbA, BodySW* rbB, const Transform& frameInA
//-----------------------------------------------------------------------------
-bool SliderJointSW::setup(float p_step)
+bool SliderJointSW::setup(real_t p_step)
{
//calculate transforms
@@ -406,7 +406,7 @@ Vector3 SliderJointSW::getAncorInB(void)
return ancorInB;
} // SliderJointSW::getAncorInB();
-void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, float p_value) {
+void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, real_t p_value) {
switch(p_param) {
case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: m_upperLinLimit=p_value; break;
@@ -437,7 +437,7 @@ void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, float p_v
}
-float SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const {
+real_t SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const {
switch(p_param) {
case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return m_upperLinLimit;
diff --git a/servers/physics/joints/slider_joint_sw.h b/servers/physics/joints/slider_joint_sw.h
index 4e697e6f64..d01038df59 100644
--- a/servers/physics/joints/slider_joint_sw.h
+++ b/servers/physics/joints/slider_joint_sw.h
@@ -237,11 +237,11 @@ public:
Vector3 getAncorInA(void);
Vector3 getAncorInB(void);
- void set_param(PhysicsServer::SliderJointParam p_param, float p_value);
- float get_param(PhysicsServer::SliderJointParam p_param) const;
+ void set_param(PhysicsServer::SliderJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::SliderJointParam p_param) const;
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_SLIDER; }
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index b71eae54b0..67e3b27852 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -727,7 +727,7 @@ uint32_t PhysicsServerSW::body_get_user_flags(RID p_body, uint32_t p_flags) cons
return 0;
};
-void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_value) {
+void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -735,7 +735,7 @@ void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_
body->set_param(p_param,p_value);
};
-float PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
+real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -879,14 +879,14 @@ void PhysicsServerSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exc
};
-void PhysicsServerSW::body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold) {
+void PhysicsServerSW::body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
};
-float PhysicsServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
+real_t PhysicsServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -971,7 +971,7 @@ RID PhysicsServerSW::joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID
return rid;
}
-void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, float p_value){
+void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -980,7 +980,7 @@ void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, flo
pin_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::pin_joint_get_param(RID p_joint,PinJointParam p_param) const{
+real_t PhysicsServerSW::pin_joint_get_param(RID p_joint,PinJointParam p_param) const{
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1074,7 +1074,7 @@ RID PhysicsServerSW::joint_create_hinge_simple(RID p_body_A,const Vector3& p_piv
}
-void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param, float p_value){
+void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1083,7 +1083,7 @@ void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param,
hinge_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const{
+real_t PhysicsServerSW::hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const{
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1154,7 +1154,7 @@ RID PhysicsServerSW::joint_create_slider(RID p_body_A,const Transform& p_local_f
return rid;
}
-void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_param, float p_value){
+void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1162,7 +1162,7 @@ void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_para
SliderJointSW *slider_joint = static_cast<SliderJointSW*>(joint);
slider_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::slider_joint_get_param(RID p_joint,SliderJointParam p_param) const{
+real_t PhysicsServerSW::slider_joint_get_param(RID p_joint,SliderJointParam p_param) const{
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1193,7 +1193,7 @@ RID PhysicsServerSW::joint_create_cone_twist(RID p_body_A,const Transform& p_loc
return rid;
}
-void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, float p_value) {
+void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, real_t p_value) {
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1201,7 +1201,7 @@ void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam
ConeTwistJointSW *cone_twist_joint = static_cast<ConeTwistJointSW*>(joint);
cone_twist_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const {
+real_t PhysicsServerSW::cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const {
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1232,7 +1232,7 @@ RID PhysicsServerSW::joint_create_generic_6dof(RID p_body_A,const Transform& p_l
return rid;
}
-void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param, float p_value){
+void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1240,7 +1240,7 @@ void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_a
Generic6DOFJointSW *generic_6dof_joint = static_cast<Generic6DOFJointSW*>(joint);
generic_6dof_joint->set_param(p_axis,p_param,p_value);
}
-float PhysicsServerSW::generic_6dof_joint_get_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param){
+real_t PhysicsServerSW::generic_6dof_joint_get_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1488,7 +1488,7 @@ void PhysicsServerSW::init() {
};
-void PhysicsServerSW::step(float p_step) {
+void PhysicsServerSW::step(real_t p_step) {
if (!active)
@@ -1611,11 +1611,11 @@ void PhysicsServerSW::_shape_col_cbk(const Vector3& p_point_A,const Vector3& p_p
if (cbk->amount == cbk->max) {
//find least deep
- float min_depth=1e20;
+ real_t min_depth=1e20;
int min_depth_idx=0;
for(int i=0;i<cbk->amount;i++) {
- float d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
+ real_t d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
if (d<min_depth) {
min_depth=d;
min_depth_idx=i;
@@ -1623,7 +1623,7 @@ void PhysicsServerSW::_shape_col_cbk(const Vector3& p_point_A,const Vector3& p_p
}
- float d = p_point_A.distance_squared_to(p_point_B);
+ real_t d = p_point_A.distance_squared_to(p_point_B);
if (d<min_depth)
return;
cbk->ptr[min_depth_idx*2+0]=p_point_A;
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 72b133c4b9..6e20474350 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -180,8 +180,8 @@ public:
virtual void body_set_user_flags(RID p_body, uint32_t p_flags);
virtual uint32_t body_get_user_flags(RID p_body, uint32_t p_flags) const;
- virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
- virtual float body_get_param(RID p_body, BodyParameter p_param) const;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
+ virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant);
virtual Variant body_get_state(RID p_body, BodyState p_state) const;
@@ -203,8 +203,8 @@ public:
virtual void body_remove_collision_exception(RID p_body, RID p_body_b);
virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions);
- virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold);
- virtual float body_get_contacts_reported_depth_treshold(RID p_body) const;
+ virtual void body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold);
+ virtual real_t body_get_contacts_reported_depth_treshold(RID p_body) const;
virtual void body_set_omit_force_integration(RID p_body,bool p_omit);
virtual bool body_is_omitting_force_integration(RID p_body) const;
@@ -221,8 +221,8 @@ public:
virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B);
- virtual void pin_joint_set_param(RID p_joint,PinJointParam p_param, float p_value);
- virtual float pin_joint_get_param(RID p_joint,PinJointParam p_param) const;
+ virtual void pin_joint_set_param(RID p_joint,PinJointParam p_param, real_t p_value);
+ virtual real_t pin_joint_get_param(RID p_joint,PinJointParam p_param) const;
virtual void pin_joint_set_local_A(RID p_joint, const Vector3& p_A);
virtual Vector3 pin_joint_get_local_A(RID p_joint) const;
@@ -233,8 +233,8 @@ public:
virtual RID joint_create_hinge(RID p_body_A,const Transform& p_frame_A,RID p_body_B,const Transform& p_frame_B);
virtual RID joint_create_hinge_simple(RID p_body_A,const Vector3& p_pivot_A,const Vector3& p_axis_A,RID p_body_B,const Vector3& p_pivot_B,const Vector3& p_axis_B);
- virtual void hinge_joint_set_param(RID p_joint,HingeJointParam p_param, float p_value);
- virtual float hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const;
+ virtual void hinge_joint_set_param(RID p_joint,HingeJointParam p_param, real_t p_value);
+ virtual real_t hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const;
virtual void hinge_joint_set_flag(RID p_joint,HingeJointFlag p_flag, bool p_value);
virtual bool hinge_joint_get_flag(RID p_joint,HingeJointFlag p_flag) const;
@@ -242,18 +242,18 @@ public:
virtual RID joint_create_slider(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A
- virtual void slider_joint_set_param(RID p_joint,SliderJointParam p_param, float p_value);
- virtual float slider_joint_get_param(RID p_joint,SliderJointParam p_param) const;
+ virtual void slider_joint_set_param(RID p_joint,SliderJointParam p_param, real_t p_value);
+ virtual real_t slider_joint_get_param(RID p_joint,SliderJointParam p_param) const;
virtual RID joint_create_cone_twist(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A
- virtual void cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, float p_value);
- virtual float cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const;
+ virtual void cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, real_t p_value);
+ virtual real_t cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const;
virtual RID joint_create_generic_6dof(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A
- virtual void generic_6dof_joint_set_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param, float p_value);
- virtual float generic_6dof_joint_get_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param);
+ virtual void generic_6dof_joint_set_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param, real_t p_value);
+ virtual real_t generic_6dof_joint_get_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param);
virtual void generic_6dof_joint_set_flag(RID p_joint,Vector3::Axis,G6DOFJointAxisFlag p_flag, bool p_enable);
virtual bool generic_6dof_joint_get_flag(RID p_joint,Vector3::Axis,G6DOFJointAxisFlag p_flag);
@@ -281,7 +281,7 @@ public:
virtual void set_active(bool p_active);
virtual void init();
- virtual void step(float p_step);
+ virtual void step(real_t p_step);
virtual void sync();
virtual void flush_queries();
virtual void finish();
diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp
index 4114980b82..dec1c75d9f 100644
--- a/servers/physics/shape_sw.cpp
+++ b/servers/physics/shape_sw.cpp
@@ -125,7 +125,7 @@ bool PlaneShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end
return inters;
}
-Vector3 PlaneShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 PlaneShapeSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(); //wtf
}
@@ -154,7 +154,7 @@ PlaneShapeSW::PlaneShapeSW() {
//
-float RayShapeSW::get_length() const {
+real_t RayShapeSW::get_length() const {
return length;
}
@@ -181,7 +181,7 @@ void RayShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo
r_amount=2;
r_supports[0]=Vector3(0,0,0);
r_supports[1]=Vector3(0,0,length);
- } if (p_normal.z>0) {
+ } else if (p_normal.z>0) {
r_amount=1;
*r_supports=Vector3(0,0,length);
} else {
@@ -196,12 +196,12 @@ bool RayShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,V
return false; //simply not possible
}
-Vector3 RayShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 RayShapeSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3();
}
-void RayShapeSW::_setup(float p_length) {
+void RayShapeSW::_setup(real_t p_length) {
length=p_length;
configure(Rect3(Vector3(0,0,0),Vector3(0.1,0.1,length)));
@@ -234,11 +234,11 @@ real_t SphereShapeSW::get_radius() const {
void SphereShapeSW::project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const {
- float d = p_normal.dot( p_transform.origin );
+ real_t d = p_normal.dot( p_transform.origin );
// figure out scale at point
Vector3 local_normal = p_transform.basis.xform_inv(p_normal);
- float scale = local_normal.length();
+ real_t scale = local_normal.length();
r_min = d - (radius) * scale;
r_max = d + (radius) * scale;
@@ -261,9 +261,9 @@ bool SphereShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_en
return Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(),radius,&r_result,&r_normal);
}
-Vector3 SphereShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 SphereShapeSW::get_moment_of_inertia(real_t p_mass) const {
- float s = 0.4 * p_mass * radius * radius;
+ real_t s = 0.4 * p_mass * radius * radius;
return Vector3(s,s,s);
}
@@ -299,8 +299,8 @@ void BoxShapeSW::project_range(const Vector3& p_normal, const Transform& p_trans
// no matter the angle, the box is mirrored anyway
Vector3 local_normal=p_transform.basis.xform_inv(p_normal);
- float length = local_normal.abs().dot(half_extents);
- float distance = p_normal.dot( p_transform.origin );
+ real_t length = local_normal.abs().dot(half_extents);
+ real_t distance = p_normal.dot( p_transform.origin );
r_min = distance - length;
r_max = distance + length;
@@ -329,7 +329,7 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo
Vector3 axis;
axis[i]=1.0;
- float dot = p_normal.dot( axis );
+ real_t dot = p_normal.dot( axis );
if ( Math::abs( dot ) > _FACE_IS_VALID_SUPPORT_TRESHOLD ) {
//Vector3 axis_b;
@@ -343,7 +343,7 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo
int i_n=next[i];
int i_n2=next2[i];
- static const float sign[4][2]={
+ static const real_t sign[4][2]={
{-1.0, 1.0},
{ 1.0, 1.0},
@@ -418,11 +418,11 @@ bool BoxShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,V
}
-Vector3 BoxShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 BoxShapeSW::get_moment_of_inertia(real_t p_mass) const {
- float lx=half_extents.x;
- float ly=half_extents.y;
- float lz=half_extents.z;
+ real_t lx=half_extents.x;
+ real_t ly=half_extents.y;
+ real_t lz=half_extents.z;
return Vector3( (p_mass/3.0) * (ly*ly + lz*lz), (p_mass/3.0) * (lx*lx + lz*lz), (p_mass/3.0) * (lx*lx + ly*ly) );
@@ -460,7 +460,7 @@ BoxShapeSW::BoxShapeSW() {
void CapsuleShapeSW::project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const {
Vector3 n=p_transform.basis.xform_inv(p_normal).normalized();
- float h = (n.z > 0) ? height : -height;
+ real_t h = (n.z > 0) ? height : -height;
n *= radius;
n.z += h * 0.5;
@@ -471,8 +471,8 @@ void CapsuleShapeSW::project_range(const Vector3& p_normal, const Transform& p_t
n = p_transform.basis.xform(n);
- float distance = p_normal.dot( p_transform.origin );
- float length = Math::abs(p_normal.dot(n));
+ real_t distance = p_normal.dot( p_transform.origin );
+ real_t length = Math::abs(p_normal.dot(n));
r_min = distance - length;
r_max = distance + length;
@@ -484,7 +484,7 @@ Vector3 CapsuleShapeSW::get_support(const Vector3& p_normal) const {
Vector3 n=p_normal;
- float h = (n.z > 0) ? height : -height;
+ real_t h = (n.z > 0) ? height : -height;
n*=radius;
n.z += h*0.5;
@@ -496,7 +496,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s
Vector3 n=p_normal;
- float d = n.z;
+ real_t d = n.z;
if (Math::abs( d )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) {
@@ -513,7 +513,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s
} else {
- float h = (d > 0) ? height : -height;
+ real_t h = (d > 0) ? height : -height;
n*=radius;
n.z += h*0.5;
@@ -528,7 +528,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s
bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const {
Vector3 norm=(p_end-p_begin).normalized();
- float min_d=1e20;
+ real_t min_d=1e20;
Vector3 res,n;
@@ -542,7 +542,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
collided = Geometry::segment_intersects_cylinder(p_begin,p_end,height,radius,&auxres,&auxn);
if (collided) {
- float d=norm.dot(auxres);
+ real_t d=norm.dot(auxres);
if (d<min_d) {
min_d=d;
res=auxres;
@@ -554,7 +554,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
collided = Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(0,0,height*0.5),radius,&auxres,&auxn);
if (collided) {
- float d=norm.dot(auxres);
+ real_t d=norm.dot(auxres);
if (d<min_d) {
min_d=d;
res=auxres;
@@ -566,7 +566,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
collided = Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(0,0,height*-0.5),radius,&auxres,&auxn);
if (collided) {
- float d=norm.dot(auxres);
+ real_t d=norm.dot(auxres);
if (d<min_d) {
min_d=d;
@@ -584,7 +584,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
return collision;
}
-Vector3 CapsuleShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 CapsuleShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
Vector3 extents=get_aabb().size*0.5;
@@ -647,7 +647,7 @@ void ConvexPolygonShapeSW::project_range(const Vector3& p_normal, const Transfor
for (int i=0;i<vertex_count;i++) {
- float d=p_normal.dot( p_transform.xform( vrts[i] ) );
+ real_t d=p_normal.dot( p_transform.xform( vrts[i] ) );
if (i==0 || d > r_max)
r_max=d;
@@ -661,7 +661,7 @@ Vector3 ConvexPolygonShapeSW::get_support(const Vector3& p_normal) const {
Vector3 n=p_normal;
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
int vertex_count=mesh.vertices.size();
if (vertex_count==0)
@@ -671,7 +671,7 @@ Vector3 ConvexPolygonShapeSW::get_support(const Vector3& p_normal) const {
for (int i=0;i<vertex_count;i++) {
- float d=n.dot(vrts[i]);
+ real_t d=n.dot(vrts[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -702,7 +702,7 @@ void ConvexPolygonShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector
for (int i=0;i<vc;i++) {
- float d=p_normal.dot(vertices[i]);
+ real_t d=p_normal.dot(vertices[i]);
if (i==0 || d > max) {
max=d;
@@ -742,7 +742,7 @@ void ConvexPolygonShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector
for(int i=0;i<ec;i++) {
- float dot=(vertices[edges[i].a]-vertices[edges[i].b]).normalized().dot(p_normal);
+ real_t dot=(vertices[edges[i].a]-vertices[edges[i].b]).normalized().dot(p_normal);
dot=ABS(dot);
if (dot < _EDGE_IS_VALID_SUPPORT_TRESHOLD && (edges[i].a==vtx || edges[i].b==vtx)) {
@@ -768,7 +768,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector
const Vector3 *vertices = mesh.vertices.ptr();
Vector3 n = p_end-p_begin;
- float min = 1e20;
+ real_t min = 1e20;
bool col=false;
for(int i=0;i<fc;i++) {
@@ -784,7 +784,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector
Face3 f(vertices[ind[0]],vertices[ind[j]],vertices[ind[j+1]]);
Vector3 result;
if (f.intersects_segment(p_begin,p_end,&result)) {
- float d = n.dot(result);
+ real_t d = n.dot(result);
if (d<min) {
min=d;
r_result=result;
@@ -802,7 +802,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector
}
-Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
Vector3 extents=get_aabb().size*0.5;
@@ -859,7 +859,7 @@ void FaceShapeSW::project_range(const Vector3& p_normal, const Transform& p_tran
for (int i=0;i<3;i++) {
Vector3 v=p_transform.xform(vertex[i]);
- float d=p_normal.dot(v);
+ real_t d=p_normal.dot(v);
if (i==0 || d > r_max)
r_max=d;
@@ -873,11 +873,11 @@ Vector3 FaceShapeSW::get_support(const Vector3& p_normal) const {
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
for (int i=0;i<3;i++) {
- float d=p_normal.dot(vertex[i]);
+ real_t d=p_normal.dot(vertex[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -907,11 +907,11 @@ void FaceShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supp
/** FIND SUPPORT VERTEX **/
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
for (int i=0;i<3;i++) {
- float d=n.dot(vertex[i]);
+ real_t d=n.dot(vertex[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -928,7 +928,7 @@ void FaceShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supp
continue;
// check if edge is valid as a support
- float dot=(vertex[i]-vertex[nx]).normalized().dot(n);
+ real_t dot=(vertex[i]-vertex[nx]).normalized().dot(n);
dot=ABS(dot);
if (dot < _EDGE_IS_VALID_SUPPORT_TRESHOLD) {
@@ -957,7 +957,7 @@ bool FaceShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,
return c;
}
-Vector3 FaceShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 FaceShapeSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(); // Sorry, but i don't think anyone cares, FaceShape!
@@ -1003,7 +1003,7 @@ void ConcavePolygonShapeSW::project_range(const Vector3& p_normal, const Transfo
for (int i=0;i<count;i++) {
- float d=p_normal.dot( p_transform.xform( vptr[i] ) );
+ real_t d=p_normal.dot( p_transform.xform( vptr[i] ) );
if (i==0 || d > r_max)
r_max=d;
@@ -1026,11 +1026,11 @@ Vector3 ConcavePolygonShapeSW::get_support(const Vector3& p_normal) const {
Vector3 n=p_normal;
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
for (int i=0;i<count;i++) {
- float d=n.dot(vptr[i]);
+ real_t d=n.dot(vptr[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -1080,7 +1080,7 @@ void ConcavePolygonShapeSW::_cull_segment(int p_idx,_SegmentCullParams *p_params
&res)) {
- float d=p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
+ real_t d=p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
//TODO, seems segmen/triangle intersection is broken :(
if (d>0 && d<p_params->min_d) {
@@ -1206,7 +1206,7 @@ void ConcavePolygonShapeSW::cull(const Rect3& p_local_aabb,Callback p_callback,v
}
-Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
Vector3 extents=get_aabb().size*0.5;
@@ -1555,7 +1555,7 @@ ConcavePolygonShapeSW::ConcavePolygonShapeSW() {
/* HEIGHT MAP SHAPE */
-PoolVector<float> HeightMapShapeSW::get_heights() const {
+PoolVector<real_t> HeightMapShapeSW::get_heights() const {
return heights;
}
@@ -1567,7 +1567,7 @@ int HeightMapShapeSW::get_depth() const {
return depth;
}
-float HeightMapShapeSW::get_cell_size() const {
+real_t HeightMapShapeSW::get_cell_size() const {
return cell_size;
}
@@ -1602,7 +1602,7 @@ void HeightMapShapeSW::cull(const Rect3& p_local_aabb,Callback p_callback,void*
}
-Vector3 HeightMapShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 HeightMapShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
@@ -1631,7 +1631,7 @@ void HeightMapShapeSW::_setup(PoolVector<real_t> p_heights,int p_width,int p_dep
for(int j=0;j<width;j++) {
- float h = r[i*width+j];
+ real_t h = r[i*width+j];
Vector3 pos( j*cell_size, h, i*cell_size );
if (i==0 || j==0)
@@ -1657,8 +1657,8 @@ void HeightMapShapeSW::set_data(const Variant& p_data) {
int width=d["width"];
int depth=d["depth"];
- float cell_size=d["cell_size"];
- PoolVector<float> heights=d["heights"];
+ real_t cell_size=d["cell_size"];
+ PoolVector<real_t> heights=d["heights"];
ERR_FAIL_COND( width<= 0);
ERR_FAIL_COND( depth<= 0);
diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h
index 919c681105..55daa5856d 100644
--- a/servers/physics/shape_sw.h
+++ b/servers/physics/shape_sw.h
@@ -35,8 +35,8 @@
/*
SHAPE_LINE, ///< plane:"plane"
-SHAPE_SEGMENT, ///< float:"length"
-SHAPE_CIRCLE, ///< float:"radius"
+SHAPE_SEGMENT, ///< real_t:"length"
+SHAPE_CIRCLE, ///< real_t:"radius"
SHAPE_RECTANGLE, ///< vec3:"extents"
SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
SHAPE_CONCAVE_POLYGON, ///< Vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array)
@@ -90,7 +90,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const=0;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const=0;
- virtual Vector3 get_moment_of_inertia(float p_mass) const=0;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const=0;
virtual void set_data(const Variant& p_data)=0;
virtual Variant get_data() const=0;
@@ -130,7 +130,7 @@ public:
Plane get_plane() const;
- virtual real_t get_area() const { return INFINITY; }
+ virtual real_t get_area() const { return Math_INF; }
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_PLANE; }
virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3& p_normal) const;
@@ -138,7 +138,7 @@ public:
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -148,12 +148,12 @@ public:
class RayShapeSW : public ShapeSW {
- float length;
+ real_t length;
- void _setup(float p_length);
+ void _setup(real_t p_length);
public:
- float get_length() const;
+ real_t get_length() const;
virtual real_t get_area() const { return 0.0; }
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_RAY; }
@@ -163,7 +163,7 @@ public:
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -189,7 +189,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -213,7 +213,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -242,7 +242,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -266,7 +266,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -349,7 +349,7 @@ public:
virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -364,18 +364,18 @@ struct HeightMapShapeSW : public ConcaveShapeSW {
PoolVector<real_t> heights;
int width;
int depth;
- float cell_size;
+ real_t cell_size;
//void _cull_segment(int p_idx,_SegmentCullParams *p_params) const;
//void _cull(int p_idx,_CullParams *p_params) const;
- void _setup(PoolVector<float> p_heights,int p_width,int p_depth,float p_cell_size);
+ void _setup(PoolVector<real_t> p_heights,int p_width,int p_depth,real_t p_cell_size);
public:
PoolVector<real_t> get_heights() const;
int get_width() const;
int get_depth() const;
- float get_cell_size() const;
+ real_t get_cell_size() const;
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_HEIGHTMAP; }
@@ -385,7 +385,7 @@ public:
virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -409,7 +409,7 @@ struct FaceShapeSW : public ShapeSW {
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- Vector3 get_moment_of_inertia(float p_mass) const;
+ Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data) {}
virtual Variant get_data() const { return Variant(); }
@@ -450,7 +450,7 @@ struct MotionShapeSW : public ShapeSW {
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const { r_amount=0; }
bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const { return false; }
- Vector3 get_moment_of_inertia(float p_mass) const { return Vector3(); }
+ Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); }
virtual void set_data(const Variant& p_data) {}
virtual Variant get_data() const { return Variant(); }
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index eaa3d3194c..0bc11041de 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -26,7 +26,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "globals.h"
+#include "global_config.h"
#include "space_sw.h"
#include "collision_solver_sw.h"
#include "physics_server_sw.h"
@@ -138,7 +138,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
}
-int PhysicsDirectSpaceStateSW::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,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform& p_xform,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
if (p_result_max<=0)
return 0;
@@ -193,7 +193,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transfo
}
-bool PhysicsDirectSpaceStateSW::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,uint32_t p_layer_mask,uint32_t p_object_type_mask,ShapeRestInfo *r_info) {
+bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,ShapeRestInfo *r_info) {
@@ -211,8 +211,8 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform&
int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
- float best_safe=1;
- float best_unsafe=1;
+ real_t best_safe=1;
+ real_t best_unsafe=1;
Transform xform_inv = p_xform.affine_inverse();
MotionShapeSW mshape;
@@ -264,13 +264,13 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform&
//just do kinematic solving
- float low=0;
- float hi=1;
+ real_t low=0;
+ real_t hi=1;
Vector3 mnormal=p_motion.normalized();
for(int i=0;i<8;i++) { //steps should be customizable..
- float ofs = (low+hi)*0.5;
+ real_t ofs = (low+hi)*0.5;
Vector3 sep=mnormal; //important optimization for this to work fast enough
@@ -323,7 +323,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform&
return true;
}
-bool PhysicsDirectSpaceStateSW::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,uint32_t p_layer_mask,uint32_t p_object_type_mask){
+bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_shape_xform,real_t p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask){
if (p_result_max<=0)
return 0;
@@ -388,7 +388,7 @@ struct _RestCallbackData {
int best_shape;
Vector3 best_contact;
Vector3 best_normal;
- float best_len;
+ real_t best_len;
};
static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,void *p_userdata) {
@@ -397,7 +397,7 @@ static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,v
_RestCallbackData *rd=(_RestCallbackData*)p_userdata;
Vector3 contact_rel = p_point_B - p_point_A;
- float len = contact_rel.length();
+ real_t len = contact_rel.length();
if (len <= rd->best_len)
return;
@@ -408,7 +408,7 @@ static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,v
rd->best_shape=rd->shape;
}
-bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform& p_shape_xform,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform& p_shape_xform,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h
index 0abc4726ea..208831914f 100644
--- a/servers/physics/space_sw.h
+++ b/servers/physics/space_sw.h
@@ -37,7 +37,7 @@
#include "area_pair_sw.h"
#include "broad_phase_sw.h"
#include "collision_object_sw.h"
-#include "globals.h"
+#include "global_config.h"
class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState {
@@ -48,10 +48,10 @@ 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,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);
- virtual bool rest_info(RID p_shape, const Transform& p_shape_xform,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual int intersect_shape(const RID& p_shape, const Transform& p_xform,real_t 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,real_t p_margin,real_t &p_closest_safe,real_t &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,real_t 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);
+ virtual bool rest_info(RID p_shape, const Transform& p_shape_xform,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
PhysicsDirectSpaceStateSW();
};
@@ -105,10 +105,10 @@ private:
CollisionObjectSW *intersection_query_results[INTERSECTION_QUERY_MAX];
int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
- float body_linear_velocity_sleep_threshold;
- float body_angular_velocity_sleep_threshold;
- float body_time_to_sleep;
- float body_angular_velocity_damp_ratio;
+ real_t body_linear_velocity_sleep_threshold;
+ real_t body_angular_velocity_sleep_threshold;
+ real_t body_time_to_sleep;
+ real_t body_angular_velocity_damp_ratio;
bool locked;
diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp
index 30ee33a7de..0bd5a874ea 100644
--- a/servers/physics/step_sw.cpp
+++ b/servers/physics/step_sw.cpp
@@ -58,7 +58,7 @@ void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_
}
}
-void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
+void StepSW::_setup_island(ConstraintSW *p_island,real_t p_delta) {
ConstraintSW *ci=p_island;
while(ci) {
@@ -68,7 +68,7 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
}
}
-void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){
+void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,real_t p_delta){
int at_priority=1;
@@ -107,7 +107,7 @@ void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta
}
-void StepSW::_check_suspend(BodySW *p_island,float p_delta) {
+void StepSW::_check_suspend(BodySW *p_island,real_t p_delta) {
bool can_sleep=true;
@@ -145,7 +145,7 @@ void StepSW::_check_suspend(BodySW *p_island,float p_delta) {
}
}
-void StepSW::step(SpaceSW* p_space,float p_delta,int p_iterations) {
+void StepSW::step(SpaceSW* p_space,real_t p_delta,int p_iterations) {
p_space->lock(); // can't access space during this
diff --git a/servers/physics/step_sw.h b/servers/physics/step_sw.h
index 2f67b3c8df..7048a76937 100644
--- a/servers/physics/step_sw.h
+++ b/servers/physics/step_sw.h
@@ -36,12 +36,12 @@ class StepSW {
uint64_t _step;
void _populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island);
- void _setup_island(ConstraintSW *p_island,float p_delta);
- void _solve_island(ConstraintSW *p_island,int p_iterations,float p_delta);
- void _check_suspend(BodySW *p_island,float p_delta);
+ void _setup_island(ConstraintSW *p_island,real_t p_delta);
+ void _solve_island(ConstraintSW *p_island,int p_iterations,real_t p_delta);
+ void _check_suspend(BodySW *p_island,real_t p_delta);
public:
- void step(SpaceSW* p_space,float p_delta,int p_iterations);
+ void step(SpaceSW* p_space,real_t p_delta,int p_iterations);
StepSW();
};
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index 6e79b28afc..02a65962e5 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -43,13 +43,13 @@ class Area2DSW : public CollisionObject2DSW{
Physics2DServer::AreaSpaceOverrideMode space_override_mode;
- float gravity;
+ real_t gravity;
Vector2 gravity_vector;
bool gravity_is_point;
- float gravity_distance_scale;
- float point_attenuation;
- float linear_damp;
- float angular_damp;
+ real_t gravity_distance_scale;
+ real_t point_attenuation;
+ real_t linear_damp;
+ real_t angular_damp;
int priority;
bool monitorable;
@@ -131,8 +131,8 @@ public:
void set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode);
Physics2DServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
- _FORCE_INLINE_ void set_gravity(float p_gravity) { gravity=p_gravity; }
- _FORCE_INLINE_ float get_gravity() const { return gravity; }
+ _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity=p_gravity; }
+ _FORCE_INLINE_ real_t get_gravity() const { return gravity; }
_FORCE_INLINE_ void set_gravity_vector(const Vector2& p_gravity) { gravity_vector=p_gravity; }
_FORCE_INLINE_ Vector2 get_gravity_vector() const { return gravity_vector; }
@@ -140,17 +140,17 @@ public:
_FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; }
_FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; }
- _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; }
- _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; }
+ _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale=scale; }
+ _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; }
- _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; }
- _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; }
+ _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation=p_point_attenuation; }
+ _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; }
- _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; }
- _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; }
+ _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp=p_linear_damp; }
+ _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
- _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; }
- _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; }
+ _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp=p_angular_damp; }
+ _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; }
_FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index c26f6c45fd..cb91caf626 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -30,7 +30,7 @@
#include "collision_solver_2d_sw.h"
-bool AreaPair2DSW::setup(float p_step) {
+bool AreaPair2DSW::setup(real_t p_step) {
bool result = area->test_collision_mask(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape),body->get_transform() * body->get_shape_transform(body_shape),Vector2(),area->get_shape(area_shape),area->get_transform() * area->get_shape_transform(area_shape),Vector2(),NULL,this);
@@ -59,7 +59,7 @@ bool AreaPair2DSW::setup(float p_step) {
return false; //never do any post solving
}
-void AreaPair2DSW::solve(float p_step) {
+void AreaPair2DSW::solve(real_t p_step) {
}
@@ -100,7 +100,7 @@ AreaPair2DSW::~AreaPair2DSW() {
-bool Area2Pair2DSW::setup(float p_step) {
+bool Area2Pair2DSW::setup(real_t p_step) {
bool result = area_a->test_collision_mask(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this);
@@ -130,7 +130,7 @@ bool Area2Pair2DSW::setup(float p_step) {
return false; //never do any post solving
}
-void Area2Pair2DSW::solve(float p_step) {
+void Area2Pair2DSW::solve(real_t p_step) {
}
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h
index db77bff5d4..219ca30c4b 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/area_pair_2d_sw.h
@@ -42,8 +42,8 @@ class AreaPair2DSW : public Constraint2DSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
AreaPair2DSW(Body2DSW *p_body,int p_body_shape, Area2DSW *p_area,int p_area_shape);
~AreaPair2DSW();
@@ -59,8 +59,8 @@ class Area2Pair2DSW : public Constraint2DSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
Area2Pair2DSW(Area2DSW *p_area_a,int p_shape_a, Area2DSW *p_area_b,int p_shape_b);
~Area2Pair2DSW();
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 093f69a169..0dab534ef9 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -51,7 +51,7 @@ void Body2DSW::update_inertias() {
if(user_inertia) break;
//update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
- float total_area=0;
+ real_t total_area=0;
for (int i=0;i<get_shape_count();i++) {
@@ -64,9 +64,9 @@ void Body2DSW::update_inertias() {
const Shape2DSW* shape=get_shape(i);
- float area=get_shape_aabb(i).get_area();
+ real_t area=get_shape_aabb(i).get_area();
- float mass = area * this->mass / total_area;
+ real_t mass = area * this->mass / total_area;
Transform2D mtx = get_shape_transform(i);
Vector2 scale = mtx.get_scale();
@@ -142,7 +142,7 @@ void Body2DSW::set_active(bool p_active) {
-void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) {
+void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) {
switch(p_param) {
case Physics2DServer::BODY_PARAM_BOUNCE: {
@@ -183,7 +183,7 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value)
}
}
-float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
+real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
switch(p_param) {
case Physics2DServer::BODY_PARAM_BOUNCE: {
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index bf9dcaa9b0..3fb01959a9 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -69,7 +69,7 @@ class Body2DSW : public CollisionObject2DSW {
real_t applied_torque;
Vector2 one_way_collision_direction;
- float one_way_collision_max_depth;
+ real_t one_way_collision_max_depth;
SelfList<Body2DSW> active_list;
@@ -109,7 +109,7 @@ class Body2DSW : public CollisionObject2DSW {
Vector2 local_pos;
Vector2 local_normal;
- float depth;
+ real_t depth;
int local_shape;
Vector2 collider_pos;
int collider_shape;
@@ -168,7 +168,7 @@ public:
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
- _FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos);
+ _FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, real_t p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos);
_FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);}
@@ -229,8 +229,8 @@ public:
- void set_param(Physics2DServer::BodyParameter p_param, float);
- float get_param(Physics2DServer::BodyParameter p_param) const;
+ void set_param(Physics2DServer::BodyParameter p_param, real_t);
+ real_t get_param(Physics2DServer::BodyParameter p_param) const;
void set_mode(Physics2DServer::BodyMode p_mode);
Physics2DServer::BodyMode get_mode() const;
@@ -259,8 +259,8 @@ public:
}
Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; }
- void set_one_way_collision_max_depth(float p_depth) { one_way_collision_max_depth=p_depth; }
- float get_one_way_collision_max_depth() const { return one_way_collision_max_depth; }
+ void set_one_way_collision_max_depth(real_t p_depth) { one_way_collision_max_depth=p_depth; }
+ real_t get_one_way_collision_max_depth() const { return one_way_collision_max_depth; }
_FORCE_INLINE_ bool is_using_one_way_collision() const { return using_one_way_cache; }
@@ -303,7 +303,7 @@ public:
//add contact inline
-void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) {
+void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, real_t p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) {
int c_max=contacts.size();
@@ -319,7 +319,7 @@ void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_nor
idx=contact_count++;
} else {
- float least_depth=1e20;
+ real_t least_depth=1e20;
int least_deep=-1;
for(int i=0;i<c_max;i++) {
@@ -361,10 +361,10 @@ public:
real_t step;
virtual Vector2 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area
- virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
- virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
+ virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
+ virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
- virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
+ virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
virtual void set_linear_velocity(const Vector2& p_velocity) { body->set_linear_velocity(p_velocity); }
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index e6b62ffa66..c05d61b658 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -99,7 +99,7 @@ void BodyPair2DSW::_contact_added_callback(const Vector2& p_point_A,const Vector
Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B;
Vector2 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
if (depth<min_depth) {
@@ -149,7 +149,7 @@ void BodyPair2DSW::_validate_contacts() {
Vector2 global_A = A->get_transform().basis_xform(c.local_A);
Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B;
Vector2 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
@@ -175,7 +175,7 @@ void BodyPair2DSW::_validate_contacts() {
}
-bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result) {
+bool BodyPair2DSW::_test_ccd(real_t p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result) {
@@ -230,7 +230,7 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Tra
return true;
}
-bool BodyPair2DSW::setup(float p_step) {
+bool BodyPair2DSW::setup(real_t p_step) {
//cannot collide
@@ -343,7 +343,7 @@ bool BodyPair2DSW::setup(float p_step) {
real_t max_penetration = space->get_contact_max_allowed_penetration();
- float bias = 0.3f;
+ real_t bias = 0.3;
if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) {
if (shape_A_ptr->get_custom_bias()==0)
@@ -464,7 +464,7 @@ bool BodyPair2DSW::setup(float p_step) {
return do_process;
}
-void BodyPair2DSW::solve(float p_step) {
+void BodyPair2DSW::solve(real_t p_step) {
if (!collided)
return;
diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h
index b9ff1bd758..7a4771782a 100644
--- a/servers/physics_2d/body_pair_2d_sw.h
+++ b/servers/physics_2d/body_pair_2d_sw.h
@@ -66,7 +66,7 @@ class BodyPair2DSW : public Constraint2DSW {
bool active;
Vector2 rA,rB;
bool reused;
- float bounce;
+ real_t bounce;
};
@@ -80,15 +80,15 @@ class BodyPair2DSW : public Constraint2DSW {
int cc;
- bool _test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result=false);
+ bool _test_ccd(real_t p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result=false);
void _validate_contacts();
static void _add_contact(const Vector2& p_point_A,const Vector2& p_point_B,void *p_self);
_FORCE_INLINE_ void _contact_added_callback(const Vector2& p_point_A,const Vector2& p_point_B);
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
BodyPair2DSW(Body2DSW *p_A, int p_shape_A,Body2DSW *p_B, int p_shape_B);
~BodyPair2DSW();
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index 8b7a410b3d..06eead64cd 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "broad_phase_2d_hash_grid.h"
-#include "globals.h"
+#include "global_config.h"
#define LARGE_ELEMENT_FI 1.01239812
diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp
index a09574a94c..4c116cee3f 100644
--- a/servers/physics_2d/collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/collision_solver_2d_sat.cpp
@@ -81,7 +81,7 @@ _FORCE_INLINE_ static void _generate_contacts_point_edge(const Vector2 * p_point
struct _generate_contacts_Pair {
bool a;
int idx;
- float d;
+ real_t d;
_FORCE_INLINE_ bool operator <(const _generate_contacts_Pair& l) const { return d< l.d; }
};
@@ -108,7 +108,7 @@ _FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 * p_points
SWAP(pA[0],pA[1]);
}
- float dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])};
+ real_t dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])};
Vector2 pB[2]={p_points_B[0],p_points_B[1]};
if (dB[0]>dB[1]) {
SWAP(dB[0],dB[1]);
@@ -265,10 +265,10 @@ _FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 * p_points
Vector2 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]);
//sort all 4 points in axis
- float dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
+ real_t dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
//todo , find max/min and then use 2 central points
- SortArray<float> sa;
+ SortArray<real_t> sa;
sa.sort(dvec,4);
//use the middle ones as contacts
@@ -596,11 +596,11 @@ public:
(castA && castB && !separator.test_axis(((m_a)+p_motion_a-((m_b)+p_motion_b)).normalized())) )
-typedef void (*CollisionFunc)(const Shape2DSW*,const Transform2D&,const Shape2DSW*,const Transform2D&,_CollectorCallback2D *p_collector,const Vector2&,const Vector2&,float,float);
+typedef void (*CollisionFunc)(const Shape2DSW*,const Transform2D&,const Shape2DSW*,const Transform2D&,_CollectorCallback2D *p_collector,const Vector2&,const Vector2&,real_t,real_t);
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_segment(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_segment(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW*>(p_b);
@@ -645,7 +645,7 @@ static void _collision_segment_segment(const Shape2DSW* p_a,const Transform2D& p
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
@@ -678,7 +678,7 @@ static void _collision_segment_circle(const Shape2DSW* p_a,const Transform2D& p_
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
@@ -743,7 +743,7 @@ static void _collision_segment_rectangle(const Shape2DSW* p_a,const Transform2D&
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -775,7 +775,7 @@ static void _collision_segment_capsule(const Shape2DSW* p_a,const Transform2D& p
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -815,7 +815,7 @@ static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Transfo
/////////
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b);
@@ -838,7 +838,7 @@ static void _collision_circle_circle(const Shape2DSW* p_a,const Transform2D& p_t
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
@@ -894,7 +894,7 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Transform2D&
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -924,7 +924,7 @@ static void _collision_circle_capsule(const Shape2DSW* p_a,const Transform2D& p_
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -956,7 +956,7 @@ static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Transfor
/////////
template<bool castA, bool castB,bool withMargin>
-static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
@@ -1027,7 +1027,7 @@ static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Transform2
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -1100,7 +1100,7 @@ static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Transform2D&
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -1162,7 +1162,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Trans
/////////
template<bool castA, bool castB,bool withMargin>
-static void _collision_capsule_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_capsule_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -1205,7 +1205,7 @@ static void _collision_capsule_capsule(const Shape2DSW* p_a,const Transform2D& p
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -1251,7 +1251,7 @@ static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Transfo
template<bool castA, bool castB,bool withMargin>
-static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW*>(p_a);
@@ -1298,7 +1298,7 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const
////////
-bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A, const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis,float p_margin_A,float p_margin_B) {
+bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A, const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) {
Physics2DServer::ShapeType type_A=p_shape_A->get_type();
diff --git a/servers/physics_2d/collision_solver_2d_sat.h b/servers/physics_2d/collision_solver_2d_sat.h
index 01acf319c7..6b698a09f2 100644
--- a/servers/physics_2d/collision_solver_2d_sat.h
+++ b/servers/physics_2d/collision_solver_2d_sat.h
@@ -32,6 +32,6 @@
#include "collision_solver_2d_sw.h"
-bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A,const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
+bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A,const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
#endif // COLLISION_SOLVER_2D_SAT_H
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index 20a5934eb8..3fdecdf413 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -181,7 +181,7 @@ void CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex
}
-bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis,float p_margin_A,float p_margin_B) {
+bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) {
const ConcaveShape2DSW *concave_B=static_cast<const ConcaveShape2DSW*>(p_shape_B);
@@ -211,10 +211,10 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Transfo
for(int i=0;i<2;i++) {
Vector2 axis( p_transform_B.elements[i] );
- float axis_scale = 1.0/axis.length();
+ real_t axis_scale = 1.0/axis.length();
axis*=axis_scale;
- float smin,smax;
+ real_t smin,smax;
p_shape_A->project_rangev(axis,rel_transform,smin,smax);
smin*=axis_scale;
smax*=axis_scale;
@@ -231,7 +231,7 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Transfo
}
-bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis,float p_margin_A,float p_margin_B) {
+bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) {
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h
index 085d3a49fb..2a5fc9fe1d 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/collision_solver_2d_sw.h
@@ -37,14 +37,14 @@ public:
private:
static bool solve_static_line(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
static void concave_callback(void *p_userdata, Shape2DSW *p_convex);
- static bool solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
+ static bool solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
static bool solve_raycast(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL);
public:
- static bool solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
+ static bool solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
};
diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h
index 4436f1f689..cce668405c 100644
--- a/servers/physics_2d/constraint_2d_sw.h
+++ b/servers/physics_2d/constraint_2d_sw.h
@@ -63,8 +63,8 @@ public:
_FORCE_INLINE_ int get_body_count() const { return _body_count; }
- virtual bool setup(float p_step)=0;
- virtual void solve(float p_step)=0;
+ virtual bool setup(real_t p_step)=0;
+ virtual void solve(real_t p_step)=0;
virtual ~Constraint2DSW() {}
};
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index f0703a0894..76adf06429 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -91,7 +91,7 @@ normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vecto
#if 0
-bool PinJoint2DSW::setup(float p_step) {
+bool PinJoint2DSW::setup(real_t p_step) {
Space2DSW *space = A->get_space();
ERR_FAIL_COND_V(!space,false;)
@@ -136,7 +136,7 @@ bool PinJoint2DSW::setup(float p_step) {
-void PinJoint2DSW::solve(float p_step){
+void PinJoint2DSW::solve(real_t p_step){
if (!correct)
return;
@@ -189,7 +189,7 @@ PinJoint2DSW::~PinJoint2DSW() {
#else
-bool PinJoint2DSW::setup(float p_step) {
+bool PinJoint2DSW::setup(real_t p_step) {
Space2DSW *space = A->get_space();
ERR_FAIL_COND_V(!space,false;)
@@ -257,7 +257,7 @@ bool PinJoint2DSW::setup(float p_step) {
return true;
}
-void PinJoint2DSW::solve(float p_step){
+void PinJoint2DSW::solve(real_t p_step){
// compute relative velocity
@@ -370,7 +370,7 @@ mult_k(const Vector2& vr, const Vector2 &k1, const Vector2 &k2)
return Vector2(vr.dot(k1), vr.dot(k2));
}
-bool GrooveJoint2DSW::setup(float p_step) {
+bool GrooveJoint2DSW::setup(real_t p_step) {
// calculate endpoints in worldspace
@@ -412,7 +412,7 @@ bool GrooveJoint2DSW::setup(float p_step) {
Vector2 delta = (B->get_transform().get_origin() +rB) - (A->get_transform().get_origin() + rA);
- float _b = get_bias();
+ real_t _b = get_bias();
_b=0.001;
gbias=(delta*-(_b==0?space->get_constraint_bias():_b)*(1.0/p_step)).clamped(get_max_bias());
@@ -424,7 +424,7 @@ bool GrooveJoint2DSW::setup(float p_step) {
return true;
}
-void GrooveJoint2DSW::solve(float p_step){
+void GrooveJoint2DSW::solve(real_t p_step){
// compute impulse
@@ -470,7 +470,7 @@ GrooveJoint2DSW::~GrooveJoint2DSW() {
//////////////////////////////////////////////
-bool DampedSpringJoint2DSW::setup(float p_step) {
+bool DampedSpringJoint2DSW::setup(real_t p_step) {
rA = A->get_transform().basis_xform(anchor_A);
rB = B->get_transform().basis_xform(anchor_B);
@@ -500,7 +500,7 @@ bool DampedSpringJoint2DSW::setup(float p_step) {
return true;
}
-void DampedSpringJoint2DSW::solve(float p_step) {
+void DampedSpringJoint2DSW::solve(real_t p_step) {
// compute relative velocity
real_t vrn = normal_relative_velocity(A, B, rA, rB, n) - target_vrn;
diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h
index 91113fa26d..1be15e4edc 100644
--- a/servers/physics_2d/joints_2d_sw.h
+++ b/servers/physics_2d/joints_2d_sw.h
@@ -85,8 +85,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_PIN; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
PinJoint2DSW(const Vector2& p_pos,Body2DSW* p_body_a,Body2DSW* p_body_b=NULL);
@@ -118,8 +118,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_PIN; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
void set_param(Physics2DServer::PinJointParam p_param, real_t p_value);
real_t get_param(Physics2DServer::PinJointParam p_param) const;
@@ -160,8 +160,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_GROOVE; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
GrooveJoint2DSW(const Vector2& p_a_groove1,const Vector2& p_a_groove2, const Vector2& p_b_anchor, Body2DSW* p_body_a,Body2DSW* p_body_b);
@@ -198,8 +198,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_DAMPED_SPRING; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
void set_param(Physics2DServer::DampedStringParam p_param, real_t p_value);
real_t get_param(Physics2DServer::DampedStringParam p_param) const;
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index d134ce7ea8..920742ea0b 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -30,7 +30,7 @@
#include "broad_phase_2d_basic.h"
#include "broad_phase_2d_hash_grid.h"
#include "collision_solver_2d_sw.h"
-#include "globals.h"
+#include "global_config.h"
#include "script_language.h"
#include "os/os.h"
@@ -158,11 +158,11 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p
if (cbk->amount == cbk->max) {
//find least deep
- float min_depth=1e20;
+ real_t min_depth=1e20;
int min_depth_idx=0;
for(int i=0;i<cbk->amount;i++) {
- float d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
+ real_t d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
if (d<min_depth) {
min_depth=d;
min_depth_idx=i;
@@ -170,7 +170,7 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p
}
- float d = p_point_A.distance_squared_to(p_point_B);
+ real_t d = p_point_A.distance_squared_to(p_point_B);
if (d<min_depth)
return;
cbk->ptr[min_depth_idx*2+0]=p_point_A;
@@ -785,7 +785,7 @@ uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body) const {
return body->get_collision_mask();
};
-void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_value) {
+void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -793,7 +793,7 @@ void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, float
body->set_param(p_param,p_value);
};
-float Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
+real_t Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -837,7 +837,7 @@ Vector2 Physics2DServerSW::body_get_applied_force(RID p_body) const {
return body->get_applied_force();
};
-void Physics2DServerSW::body_set_applied_torque(RID p_body, float p_torque) {
+void Physics2DServerSW::body_set_applied_torque(RID p_body, real_t p_torque) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -846,7 +846,7 @@ void Physics2DServerSW::body_set_applied_torque(RID p_body, float p_torque) {
body->wakeup();
};
-float Physics2DServerSW::body_get_applied_torque(RID p_body) const {
+real_t Physics2DServerSW::body_get_applied_torque(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -915,14 +915,14 @@ void Physics2DServerSW::body_get_collision_exceptions(RID p_body, List<RID> *p_e
};
-void Physics2DServerSW::body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold) {
+void Physics2DServerSW::body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
};
-float Physics2DServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
+real_t Physics2DServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -973,7 +973,7 @@ Vector2 Physics2DServerSW::body_get_one_way_collision_direction(RID p_body) cons
}
-void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_max_depth) {
+void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,real_t p_max_depth) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -981,7 +981,7 @@ void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_
}
-float Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const {
+real_t Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -1016,7 +1016,7 @@ void Physics2DServerSW::body_set_pickable(RID p_body,bool p_pickable) {
}
-bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2& p_motion, float p_margin, MotionResult *r_result) {
+bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2& p_motion, real_t p_margin, MotionResult *r_result) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,false);
@@ -1263,7 +1263,7 @@ void Physics2DServerSW::init() {
};
-void Physics2DServerSW::step(float p_step) {
+void Physics2DServerSW::step(real_t p_step) {
if (!active)
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 1da7d65dc8..e33e2d78c7 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -76,7 +76,7 @@ public:
struct CollCbkData {
Vector2 valid_dir;
- float valid_depth;
+ real_t valid_depth;
int max;
int amount;
Vector2 *ptr;
@@ -193,8 +193,8 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask);
virtual uint32_t body_get_collision_mask(RID p_) const;
- virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
- virtual float body_get_param(RID p_body, BodyParameter p_param) const;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
+ virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant);
@@ -203,8 +203,8 @@ public:
virtual void body_set_applied_force(RID p_body, const Vector2& p_force);
virtual Vector2 body_get_applied_force(RID p_body) const;
- virtual void body_set_applied_torque(RID p_body, float p_torque);
- virtual float body_get_applied_torque(RID p_body) const;
+ virtual void body_set_applied_torque(RID p_body, real_t p_torque);
+ virtual real_t body_get_applied_torque(RID p_body) const;
virtual void body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force);
@@ -215,8 +215,8 @@ public:
virtual void body_remove_collision_exception(RID p_body, RID p_body_b);
virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions);
- virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold);
- virtual float body_get_contacts_reported_depth_treshold(RID p_body) const;
+ virtual void body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold);
+ virtual real_t body_get_contacts_reported_depth_treshold(RID p_body) const;
virtual void body_set_omit_force_integration(RID p_body,bool p_omit);
virtual bool body_is_omitting_force_integration(RID p_body) const;
@@ -227,8 +227,8 @@ public:
virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction);
virtual Vector2 body_get_one_way_collision_direction(RID p_body) const;
- virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth);
- virtual float body_get_one_way_collision_max_depth(RID p_body) const;
+ virtual void body_set_one_way_collision_max_depth(RID p_body,real_t p_max_depth);
+ virtual real_t body_get_one_way_collision_max_depth(RID p_body) const;
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
@@ -236,7 +236,7 @@ public:
virtual void body_set_pickable(RID p_body,bool p_pickable);
- virtual bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL);
+ virtual bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,real_t p_margin=0.001,MotionResult *r_result=NULL);
/* JOINT API */
@@ -260,7 +260,7 @@ public:
virtual void set_active(bool p_active);
virtual void init();
- virtual void step(float p_step);
+ virtual void step(real_t p_step);
virtual void sync();
virtual void flush_queries();
virtual void end_sync();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
index 027f318d2d..34ba149d23 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
@@ -35,7 +35,7 @@ void Physics2DServerWrapMT::thread_exit() {
exit=true;
}
-void Physics2DServerWrapMT::thread_step(float p_delta) {
+void Physics2DServerWrapMT::thread_step(real_t p_delta) {
physics_2d_server->step(p_delta);
step_sem->post();
@@ -75,7 +75,7 @@ void Physics2DServerWrapMT::thread_loop() {
/* EVENT QUEUING */
-void Physics2DServerWrapMT::step(float p_step) {
+void Physics2DServerWrapMT::step(real_t p_step) {
if (create_thread) {
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 851ba901ec..f8b533080e 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -33,7 +33,7 @@
#include "servers/physics_2d_server.h"
#include "command_queue_mt.h"
#include "os/thread.h"
-#include "globals.h"
+#include "global_config.h"
#ifdef DEBUG_SYNC
#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__));
@@ -60,7 +60,7 @@ class Physics2DServerWrapMT : public Physics2DServer {
Semaphore *step_sem;
int step_pending;
- void thread_step(float p_delta);
+ void thread_step(real_t p_delta);
void thread_flush();
void thread_exit();
@@ -220,8 +220,8 @@ public:
FUNC1RC(uint32_t,body_get_collision_mask,RID);
- FUNC3(body_set_param,RID,BodyParameter,float);
- FUNC2RC(float,body_get_param,RID,BodyParameter);
+ FUNC3(body_set_param,RID,BodyParameter,real_t);
+ FUNC2RC(real_t,body_get_param,RID,BodyParameter);
FUNC3(body_set_state,RID,BodyState,const Variant&);
@@ -230,8 +230,8 @@ public:
FUNC2(body_set_applied_force,RID,const Vector2&);
FUNC1RC(Vector2,body_get_applied_force,RID);
- FUNC2(body_set_applied_torque,RID,float);
- FUNC1RC(float,body_get_applied_torque,RID);
+ FUNC2(body_set_applied_torque,RID,real_t);
+ FUNC1RC(real_t,body_get_applied_torque,RID);
FUNC3(body_add_force,RID,const Vector2&,const Vector2&);
FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&);
@@ -247,12 +247,12 @@ public:
FUNC2(body_set_one_way_collision_direction,RID,const Vector2&);
FUNC1RC(Vector2,body_get_one_way_collision_direction,RID);
- FUNC2(body_set_one_way_collision_max_depth,RID,float);
- FUNC1RC(float,body_get_one_way_collision_max_depth,RID);
+ FUNC2(body_set_one_way_collision_max_depth,RID,real_t);
+ FUNC1RC(real_t,body_get_one_way_collision_max_depth,RID);
- FUNC2(body_set_contacts_reported_depth_treshold,RID,float);
- FUNC1RC(float,body_get_contacts_reported_depth_treshold,RID);
+ FUNC2(body_set_contacts_reported_depth_treshold,RID,real_t);
+ FUNC1RC(real_t,body_get_contacts_reported_depth_treshold,RID);
FUNC2(body_set_omit_force_integration,RID,bool);
FUNC1RC(bool,body_is_omitting_force_integration,RID);
@@ -266,7 +266,7 @@ public:
FUNC2(body_set_pickable,RID,bool);
- bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) {
+ bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,real_t p_margin=0.001,MotionResult *r_result=NULL) {
ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false);
return physics_2d_server->body_test_motion(p_body,p_from,p_motion,p_margin,r_result);
@@ -303,7 +303,7 @@ public:
FUNC1(set_active,bool);
virtual void init();
- virtual void step(float p_step);
+ virtual void step(real_t p_step);
virtual void sync();
virtual void end_sync();
virtual void flush_queries();
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 886ae7730b..b6eb427131 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -136,7 +136,7 @@ bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_en
return true;
}
-real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const {
+real_t LineShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0;
}
@@ -191,7 +191,7 @@ bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end
}
-real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const {
+real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0; //rays are mass-less
}
@@ -224,7 +224,7 @@ void SegmentShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
}
- float dp=p_normal.dot(b-a);
+ real_t dp=p_normal.dot(b-a);
if (dp>0)
*r_supports=b;
else
@@ -252,14 +252,14 @@ bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
return true;
}
-real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const {
+real_t SegmentShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
Vector2 s[2]={a*p_scale,b*p_scale};
real_t l = s[1].distance_to(s[0]);
Vector2 ofs = (s[0]+s[1])*0.5;
- return p_mass*(l*l/12.0f + ofs.length_squared());
+ return p_mass*(l*l/12.0 + ofs.length_squared());
}
void SegmentShape2DSW::set_data(const Variant& p_data) {
@@ -336,7 +336,7 @@ bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_
return true;
}
-real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const {
+real_t CircleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return (radius*radius)*(p_scale.x*0.5+p_scale.y*0.5);
@@ -367,11 +367,11 @@ void RectangleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_support
Vector2 ag;
ag[i]=1.0;
- float dp = ag.dot(p_normal);
+ real_t dp = ag.dot(p_normal);
if (Math::abs(dp)<_SEGMENT_IS_VALID_SUPPORT_TRESHOLD)
continue;
- float sgn = dp>0 ? 1.0 : -1.0;
+ real_t sgn = dp>0 ? 1.0 : -1.0;
r_amount=2;
@@ -407,10 +407,10 @@ bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2&
return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal);
}
-real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Size2& p_scale) const {
+real_t RectangleShape2DSW::get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const {
Vector2 he2=half_extents*2*p_scale;
- return p_mass*he2.dot(he2)/12.0f;
+ return p_mass*he2.dot(he2)/12.0;
}
void RectangleShape2DSW::set_data(const Variant& p_data) {
@@ -438,7 +438,7 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
Vector2 n=p_normal;
- float d = n.y;
+ real_t d = n.y;
if (Math::abs( d )<(1.0-_SEGMENT_IS_VALID_SUPPORT_TRESHOLD) ) {
@@ -455,7 +455,7 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
} else {
- float h = (d > 0) ? height : -height;
+ real_t h = (d > 0) ? height : -height;
n*=radius;
n.y += h*0.5;
@@ -479,7 +479,7 @@ bool CapsuleShape2DSW::contains_point(const Vector2& p_point) const {
bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
- float d = 1e10;
+ real_t d = 1e10;
Vector2 n = (p_end-p_begin).normalized();
bool collided=false;
@@ -488,7 +488,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
Vector2 begin = p_begin;
Vector2 end = p_end;
- float ofs = (i==0)?-height*0.5:height*0.5;
+ real_t ofs = (i==0)?-height*0.5:height*0.5;
begin.y+=ofs;
end.y+=ofs;
@@ -540,10 +540,10 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
return collided; //todo
}
-real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Size2 &p_scale) const {
+real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
Vector2 he2=Vector2(radius*2,height+radius*2)*p_scale;
- return p_mass*he2.dot(he2)/12.0f;
+ return p_mass*he2.dot(he2)/12.0;
}
void CapsuleShape2DSW::set_data(const Variant& p_data) {
@@ -619,7 +619,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2& p_point) const {
for(int i=0;i<point_count;i++) {
- float d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos);
+ real_t d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos);
if (d>0)
out=true;
else
@@ -650,7 +650,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect
if (!Geometry::segment_intersects_segment_2d(p_begin,p_end,points[i].pos,points[(i+1)%point_count].pos,&res))
continue;
- float nd = n.dot(res);
+ real_t nd = n.dot(res);
if (nd<d) {
d=nd;
@@ -672,7 +672,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect
return inters; //todo
}
-real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Size2& p_scale) const {
+real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const {
Rect2 aabb;
aabb.pos=points[0].pos*p_scale;
@@ -681,7 +681,7 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Size2& p
aabb.expand_to(points[i].pos*p_scale);
}
- return p_mass*aabb.size.dot(aabb.size)/12.0f + p_mass * (aabb.pos+aabb.size*0.5).length_squared();
+ return p_mass*aabb.size.dot(aabb.size)/12.0 + p_mass * (aabb.pos+aabb.size*0.5).length_squared();
}
void ConvexPolygonShape2DSW::set_data(const Variant& p_data) {
@@ -859,7 +859,7 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vec
if (Geometry::segment_intersects_segment_2d(p_begin,p_end,a,b,&res)) {
- float nd = n.dot(res);
+ real_t nd = n.dot(res);
if (nd<d) {
d=nd;
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index 07a9d84ec8..c04cdfa456 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -35,8 +35,8 @@
/*
SHAPE_LINE, ///< plane:"plane"
-SHAPE_SEGMENT, ///< float:"length"
-SHAPE_CIRCLE, ///< float:"radius"
+SHAPE_SEGMENT, ///< real_t:"length"
+SHAPE_CIRCLE, ///< real_t:"radius"
SHAPE_RECTANGLE, ///< vec3:"extents"
SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
SHAPE_CONCAVE_POLYGON, ///< Vector2 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector2 array)
@@ -86,7 +86,7 @@ public:
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const=0;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const=0;
virtual void set_data(const Variant& p_data)=0;
virtual Variant get_data() const=0;
@@ -175,7 +175,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -218,7 +218,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -266,7 +266,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -304,7 +304,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -344,7 +344,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -432,7 +432,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -440,7 +440,7 @@ public:
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
// no matter the angle, the box is mirrored anyway
Vector2 n=p_transform.basis_xform_inv(p_normal).normalized();
- float h = (n.y > 0) ? height : -height;
+ real_t h = (n.y > 0) ? height : -height;
n *= radius;
n.y += h * 0.5;
@@ -495,7 +495,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -506,7 +506,7 @@ public:
r_min = r_max = p_normal.dot(p_transform.xform(points[0].pos));
for(int i=1;i<point_count;i++) {
- float d = p_normal.dot(p_transform.xform(points[i].pos));
+ real_t d = p_normal.dot(p_transform.xform(points[i].pos));
if (d>r_max)
r_max=d;
if (d<r_min)
@@ -584,7 +584,7 @@ public:
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Size2& p_scale) const { return 0; }
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const { return 0; }
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index a48b6d3827..9bced50061 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -190,7 +190,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec
}
-int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
if (p_result_max<=0)
return 0;
@@ -237,7 +237,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Trans
-bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
@@ -255,8 +255,8 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transfor
int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
- float best_safe=1;
- float best_unsafe=1;
+ real_t best_safe=1;
+ real_t best_unsafe=1;
for(int i=0;i<amount;i++) {
@@ -305,13 +305,13 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transfor
//just do kinematic solving
- float low=0;
- float hi=1;
+ real_t low=0;
+ real_t hi=1;
Vector2 mnormal=p_motion.normalized();
for(int i=0;i<8;i++) { //steps should be customizable..
- float ofs = (low+hi)*0.5;
+ real_t ofs = (low+hi)*0.5;
Vector2 sep=mnormal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,p_margin);
@@ -364,7 +364,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transfor
}
-bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
if (p_result_max<=0)
@@ -436,9 +436,9 @@ struct _RestCallbackData2D {
int best_shape;
Vector2 best_contact;
Vector2 best_normal;
- float best_len;
+ real_t best_len;
Vector2 valid_dir;
- float valid_depth;
+ real_t valid_depth;
};
static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) {
@@ -458,7 +458,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v
}
Vector2 contact_rel = p_point_B - p_point_A;
- float len = contact_rel.length();
+ real_t len = contact_rel.length();
if (len <= rd->best_len)
return;
@@ -473,7 +473,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 Transform2D& 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) {
+bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
@@ -594,7 +594,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb) {
return amount;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result) {
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
@@ -622,6 +622,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D body_transform = p_from;
+
{
//STEP 1, FREE BODY IF STUCK
@@ -645,6 +646,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool collided=false;
+
int amount = _cull_aabb_for_body(p_body,body_aabb);
for(int j=0;j<p_body->get_shape_count();j++) {
@@ -682,11 +684,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}
- if (!collided)
+ if (!collided) {
break;
+ }
Vector2 recover_motion;
+
for(int i=0;i<cbk.amount;i++) {
Vector2 a = sr[i*2+0];
@@ -694,15 +698,15 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
#if 0
Vector2 rel = b-a;
- float d = rel.length();
+ real_t d = rel.length();
if (d==0)
continue;
Vector2 n = rel/d;
- float traveled = n.dot(recover_motion);
+ real_t traveled = n.dot(recover_motion);
a+=n*traveled;
- float d = a.distance_to(b);
+ real_t d = a.distance_to(b);
if (d<margin)
continue;
#endif
@@ -724,8 +728,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
- float safe = 1.0;
- float unsafe = 1.0;
+ real_t safe = 1.0;
+ real_t unsafe = 1.0;
int best_shape=-1;
{
@@ -747,8 +751,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool stuck=false;
- float best_safe=1;
- float best_unsafe=1;
+ real_t best_safe=1;
+ real_t best_unsafe=1;
for(int i=0;i<amount;i++) {
@@ -780,13 +784,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//just do kinematic solving
- float low=0;
- float hi=1;
+ real_t low=0;
+ real_t hi=1;
Vector2 mnormal=p_motion.normalized();
for(int i=0;i<8;i++) { //steps should be customizable..
- float ofs = (low+hi)*0.5;
+ real_t ofs = (low+hi)*0.5;
Vector2 sep=mnormal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(body_shape,body_shape_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,0);
@@ -1000,7 +1004,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Vector2 a = sr[i*2+0];
Vector2 b = sr[i*2+1];
- float d = a.distance_to(b);
+ real_t d = a.distance_to(b);
/*
if (d<margin)
@@ -1024,8 +1028,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//move second
- float safe = 1.0;
- float unsafe = 1.0;
+ real_t safe = 1.0;
+ real_t unsafe = 1.0;
int best_shape=-1;
for(int i=0;i<get_shape_count();i++) {
@@ -1033,7 +1037,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (is_shape_set_as_trigger(i))
continue;
- float lsafe,lunsafe;
+ real_t lsafe,lunsafe;
bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,get_layer_mask(),mask);
//print_line("shape: "+itos(i)+" travel:"+rtos(ltravel));
if (!valid) {
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index 5dee3dea5a..071aa7bdfb 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -37,7 +37,7 @@
#include "area_pair_2d_sw.h"
#include "broad_phase_2d_sw.h"
#include "collision_object_2d_sw.h"
-#include "globals.h"
+#include "global_config.h"
class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
@@ -49,10 +49,10 @@ public:
virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION, bool p_pick_point=false);
virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual int intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual bool cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual bool collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *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);
- virtual bool rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual int intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t 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 Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &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);
+ virtual bool collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,Vector2 *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);
+ virtual bool rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
Physics2DDirectSpaceStateSW();
};
@@ -106,9 +106,9 @@ private:
CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX];
int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
- float body_linear_velocity_sleep_treshold;
- float body_angular_velocity_sleep_treshold;
- float body_time_to_sleep;
+ real_t body_linear_velocity_sleep_treshold;
+ real_t body_angular_velocity_sleep_treshold;
+ real_t body_time_to_sleep;
bool locked;
@@ -185,7 +185,7 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result);
+ bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result);
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp
index 8be4e2b5d5..355cc25a69 100644
--- a/servers/physics_2d/step_2d_sw.cpp
+++ b/servers/physics_2d/step_2d_sw.cpp
@@ -56,7 +56,7 @@ void Step2DSW::_populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2
}
}
-bool Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) {
+bool Step2DSW::_setup_island(Constraint2DSW *p_island,real_t p_delta) {
Constraint2DSW *ci=p_island;
Constraint2DSW *prev_ci=NULL;
@@ -81,7 +81,7 @@ bool Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) {
return removed_root;
}
-void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,float p_delta){
+void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,real_t p_delta){
for(int i=0;i<p_iterations;i++) {
@@ -94,7 +94,7 @@ void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,float p_d
}
}
-void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) {
+void Step2DSW::_check_suspend(Body2DSW *p_island,real_t p_delta) {
bool can_sleep=true;
@@ -132,7 +132,7 @@ void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) {
}
}
-void Step2DSW::step(Space2DSW* p_space,float p_delta,int p_iterations) {
+void Step2DSW::step(Space2DSW* p_space,real_t p_delta,int p_iterations) {
p_space->lock(); // can't access space during this
diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/step_2d_sw.h
index 917d69e7f1..0896e1016d 100644
--- a/servers/physics_2d/step_2d_sw.h
+++ b/servers/physics_2d/step_2d_sw.h
@@ -36,12 +36,12 @@ class Step2DSW {
uint64_t _step;
void _populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2DSW **p_constraint_island);
- 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);
+ bool _setup_island(Constraint2DSW *p_island,real_t p_delta);
+ void _solve_island(Constraint2DSW *p_island,int p_iterations,real_t p_delta);
+ void _check_suspend(Body2DSW *p_island,real_t p_delta);
public:
- void step(Space2DSW* p_space,float p_delta,int p_iterations);
+ void step(Space2DSW* p_space,real_t p_delta,int p_iterations);
Step2DSW();
};
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index 39b790111b..bdbe85612f 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -73,40 +73,40 @@ Physics2DServer * Physics2DServer::get_singleton() {
void Physics2DDirectBodyState::_bind_methods() {
- ClassDB::bind_method(_MD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity);
- ClassDB::bind_method(_MD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp);
- ClassDB::bind_method(_MD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity);
+ ClassDB::bind_method(D_METHOD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp);
- ClassDB::bind_method(_MD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass);
- ClassDB::bind_method(_MD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia);
+ ClassDB::bind_method(D_METHOD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass);
+ ClassDB::bind_method(D_METHOD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia);
- ClassDB::bind_method(_MD("set_linear_velocity","velocity"),&Physics2DDirectBodyState::set_linear_velocity);
- ClassDB::bind_method(_MD("get_linear_velocity"),&Physics2DDirectBodyState::get_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_linear_velocity","velocity"),&Physics2DDirectBodyState::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"),&Physics2DDirectBodyState::get_linear_velocity);
- ClassDB::bind_method(_MD("set_angular_velocity","velocity"),&Physics2DDirectBodyState::set_angular_velocity);
- ClassDB::bind_method(_MD("get_angular_velocity"),&Physics2DDirectBodyState::get_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_angular_velocity","velocity"),&Physics2DDirectBodyState::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"),&Physics2DDirectBodyState::get_angular_velocity);
- ClassDB::bind_method(_MD("set_transform","transform"),&Physics2DDirectBodyState::set_transform);
- ClassDB::bind_method(_MD("get_transform"),&Physics2DDirectBodyState::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&Physics2DDirectBodyState::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&Physics2DDirectBodyState::get_transform);
- ClassDB::bind_method(_MD("set_sleep_state","enabled"),&Physics2DDirectBodyState::set_sleep_state);
- ClassDB::bind_method(_MD("is_sleeping"),&Physics2DDirectBodyState::is_sleeping);
+ ClassDB::bind_method(D_METHOD("set_sleep_state","enabled"),&Physics2DDirectBodyState::set_sleep_state);
+ ClassDB::bind_method(D_METHOD("is_sleeping"),&Physics2DDirectBodyState::is_sleeping);
- ClassDB::bind_method(_MD("get_contact_count"),&Physics2DDirectBodyState::get_contact_count);
+ ClassDB::bind_method(D_METHOD("get_contact_count"),&Physics2DDirectBodyState::get_contact_count);
- ClassDB::bind_method(_MD("get_contact_local_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_local_pos);
- ClassDB::bind_method(_MD("get_contact_local_normal","contact_idx"),&Physics2DDirectBodyState::get_contact_local_normal);
- ClassDB::bind_method(_MD("get_contact_local_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_local_shape);
- ClassDB::bind_method(_MD("get_contact_collider","contact_idx"),&Physics2DDirectBodyState::get_contact_collider);
- ClassDB::bind_method(_MD("get_contact_collider_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_pos);
- ClassDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id);
- ClassDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object);
- ClassDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape);
- ClassDB::bind_method(_MD("get_contact_collider_shape_metadata:Variant","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata);
- ClassDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos);
- ClassDB::bind_method(_MD("get_step"),&Physics2DDirectBodyState::get_step);
- ClassDB::bind_method(_MD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces);
- ClassDB::bind_method(_MD("get_space_state:Physics2DDirectSpaceState"),&Physics2DDirectBodyState::get_space_state);
+ ClassDB::bind_method(D_METHOD("get_contact_local_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_local_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_local_normal","contact_idx"),&Physics2DDirectBodyState::get_contact_local_normal);
+ ClassDB::bind_method(D_METHOD("get_contact_local_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_local_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider","contact_idx"),&Physics2DDirectBodyState::get_contact_collider);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_shape_metadata:Variant","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos);
+ ClassDB::bind_method(D_METHOD("get_step"),&Physics2DDirectBodyState::get_step);
+ ClassDB::bind_method(D_METHOD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces);
+ ClassDB::bind_method(D_METHOD("get_space_state:Physics2DDirectSpaceState"),&Physics2DDirectBodyState::get_space_state);
}
@@ -198,27 +198,27 @@ Vector<RID> Physics2DShapeQueryParameters::get_exclude() const{
void Physics2DShapeQueryParameters::_bind_methods() {
- ClassDB::bind_method(_MD("set_shape","shape:Shape2D"),&Physics2DShapeQueryParameters::set_shape);
- ClassDB::bind_method(_MD("set_shape_rid","shape"),&Physics2DShapeQueryParameters::set_shape_rid);
- ClassDB::bind_method(_MD("get_shape_rid"),&Physics2DShapeQueryParameters::get_shape_rid);
+ ClassDB::bind_method(D_METHOD("set_shape","shape:Shape2D"),&Physics2DShapeQueryParameters::set_shape);
+ ClassDB::bind_method(D_METHOD("set_shape_rid","shape"),&Physics2DShapeQueryParameters::set_shape_rid);
+ ClassDB::bind_method(D_METHOD("get_shape_rid"),&Physics2DShapeQueryParameters::get_shape_rid);
- ClassDB::bind_method(_MD("set_transform","transform"),&Physics2DShapeQueryParameters::set_transform);
- ClassDB::bind_method(_MD("get_transform"),&Physics2DShapeQueryParameters::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&Physics2DShapeQueryParameters::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&Physics2DShapeQueryParameters::get_transform);
- ClassDB::bind_method(_MD("set_motion","motion"),&Physics2DShapeQueryParameters::set_motion);
- ClassDB::bind_method(_MD("get_motion"),&Physics2DShapeQueryParameters::get_motion);
+ ClassDB::bind_method(D_METHOD("set_motion","motion"),&Physics2DShapeQueryParameters::set_motion);
+ ClassDB::bind_method(D_METHOD("get_motion"),&Physics2DShapeQueryParameters::get_motion);
- ClassDB::bind_method(_MD("set_margin","margin"),&Physics2DShapeQueryParameters::set_margin);
- ClassDB::bind_method(_MD("get_margin"),&Physics2DShapeQueryParameters::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin","margin"),&Physics2DShapeQueryParameters::set_margin);
+ ClassDB::bind_method(D_METHOD("get_margin"),&Physics2DShapeQueryParameters::get_margin);
- ClassDB::bind_method(_MD("set_layer_mask","layer_mask"),&Physics2DShapeQueryParameters::set_layer_mask);
- ClassDB::bind_method(_MD("get_layer_mask"),&Physics2DShapeQueryParameters::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&Physics2DShapeQueryParameters::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&Physics2DShapeQueryParameters::get_layer_mask);
- ClassDB::bind_method(_MD("set_object_type_mask","object_type_mask"),&Physics2DShapeQueryParameters::set_object_type_mask);
- ClassDB::bind_method(_MD("get_object_type_mask"),&Physics2DShapeQueryParameters::get_object_type_mask);
+ ClassDB::bind_method(D_METHOD("set_object_type_mask","object_type_mask"),&Physics2DShapeQueryParameters::set_object_type_mask);
+ ClassDB::bind_method(D_METHOD("get_object_type_mask"),&Physics2DShapeQueryParameters::get_object_type_mask);
- ClassDB::bind_method(_MD("set_exclude","exclude"),&Physics2DShapeQueryParameters::set_exclude);
- ClassDB::bind_method(_MD("get_exclude"),&Physics2DShapeQueryParameters::get_exclude);
+ ClassDB::bind_method(D_METHOD("set_exclude","exclude"),&Physics2DShapeQueryParameters::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"),&Physics2DShapeQueryParameters::get_exclude);
}
@@ -366,13 +366,13 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() {
void Physics2DDirectSpaceState::_bind_methods() {
- ClassDB::bind_method(_MD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
- ClassDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
- ClassDB::bind_method(_MD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32));
- ClassDB::bind_method(_MD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion);
- ClassDB::bind_method(_MD("collide_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_collide_shape,DEFVAL(32));
- ClassDB::bind_method(_MD("get_rest_info","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_get_rest_info);
- //ClassDB::bind_method(_MD("cast_motion","shape","xform","motion","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
+ ClassDB::bind_method(D_METHOD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
+ ClassDB::bind_method(D_METHOD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion);
+ ClassDB::bind_method(D_METHOD("collide_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_collide_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("get_rest_info","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_get_rest_info);
+ //ClassDB::bind_method(D_METHOD("cast_motion","shape","xform","motion","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
BIND_CONSTANT( TYPE_MASK_STATIC_BODY );
BIND_CONSTANT( TYPE_MASK_KINEMATIC_BODY );
@@ -412,11 +412,11 @@ Physics2DShapeQueryResult::Physics2DShapeQueryResult() {
void Physics2DShapeQueryResult::_bind_methods() {
- ClassDB::bind_method(_MD("get_result_count"),&Physics2DShapeQueryResult::get_result_count);
- ClassDB::bind_method(_MD("get_result_rid","idx"),&Physics2DShapeQueryResult::get_result_rid);
- ClassDB::bind_method(_MD("get_result_object_id","idx"),&Physics2DShapeQueryResult::get_result_object_id);
- ClassDB::bind_method(_MD("get_result_object","idx"),&Physics2DShapeQueryResult::get_result_object);
- ClassDB::bind_method(_MD("get_result_object_shape","idx"),&Physics2DShapeQueryResult::get_result_object_shape);
+ ClassDB::bind_method(D_METHOD("get_result_count"),&Physics2DShapeQueryResult::get_result_count);
+ ClassDB::bind_method(D_METHOD("get_result_rid","idx"),&Physics2DShapeQueryResult::get_result_rid);
+ ClassDB::bind_method(D_METHOD("get_result_object_id","idx"),&Physics2DShapeQueryResult::get_result_object_id);
+ ClassDB::bind_method(D_METHOD("get_result_object","idx"),&Physics2DShapeQueryResult::get_result_object);
+ ClassDB::bind_method(D_METHOD("get_result_object_shape","idx"),&Physics2DShapeQueryResult::get_result_object_shape);
}
@@ -468,16 +468,16 @@ int Physics2DTestMotionResult::get_collider_shape() const{
void Physics2DTestMotionResult::_bind_methods() {
- //ClassDB::bind_method(_MD("is_colliding"),&Physics2DTestMotionResult::is_colliding);
- ClassDB::bind_method(_MD("get_motion"),&Physics2DTestMotionResult::get_motion);
- ClassDB::bind_method(_MD("get_motion_remainder"),&Physics2DTestMotionResult::get_motion_remainder);
- ClassDB::bind_method(_MD("get_collision_point"),&Physics2DTestMotionResult::get_collision_point);
- ClassDB::bind_method(_MD("get_collision_normal"),&Physics2DTestMotionResult::get_collision_normal);
- ClassDB::bind_method(_MD("get_collider_velocity"),&Physics2DTestMotionResult::get_collider_velocity);
- ClassDB::bind_method(_MD("get_collider_id"),&Physics2DTestMotionResult::get_collider_id);
- ClassDB::bind_method(_MD("get_collider_rid"),&Physics2DTestMotionResult::get_collider_rid);
- ClassDB::bind_method(_MD("get_collider"),&Physics2DTestMotionResult::get_collider);
- ClassDB::bind_method(_MD("get_collider_shape"),&Physics2DTestMotionResult::get_collider_shape);
+ //ClassDB::bind_method(D_METHOD("is_colliding"),&Physics2DTestMotionResult::is_colliding);
+ ClassDB::bind_method(D_METHOD("get_motion"),&Physics2DTestMotionResult::get_motion);
+ ClassDB::bind_method(D_METHOD("get_motion_remainder"),&Physics2DTestMotionResult::get_motion_remainder);
+ ClassDB::bind_method(D_METHOD("get_collision_point"),&Physics2DTestMotionResult::get_collision_point);
+ ClassDB::bind_method(D_METHOD("get_collision_normal"),&Physics2DTestMotionResult::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collider_velocity"),&Physics2DTestMotionResult::get_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collider_id"),&Physics2DTestMotionResult::get_collider_id);
+ ClassDB::bind_method(D_METHOD("get_collider_rid"),&Physics2DTestMotionResult::get_collider_rid);
+ ClassDB::bind_method(D_METHOD("get_collider"),&Physics2DTestMotionResult::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"),&Physics2DTestMotionResult::get_collider_shape);
}
@@ -504,147 +504,147 @@ bool Physics2DServer::_body_test_motion(RID p_body,const Transform2D& p_from,con
void Physics2DServer::_bind_methods() {
- ClassDB::bind_method(_MD("shape_create","type"),&Physics2DServer::shape_create);
- ClassDB::bind_method(_MD("shape_set_data","shape","data"),&Physics2DServer::shape_set_data);
+ ClassDB::bind_method(D_METHOD("shape_create","type"),&Physics2DServer::shape_create);
+ ClassDB::bind_method(D_METHOD("shape_set_data","shape","data"),&Physics2DServer::shape_set_data);
- ClassDB::bind_method(_MD("shape_get_type","shape"),&Physics2DServer::shape_get_type);
- ClassDB::bind_method(_MD("shape_get_data","shape"),&Physics2DServer::shape_get_data);
+ ClassDB::bind_method(D_METHOD("shape_get_type","shape"),&Physics2DServer::shape_get_type);
+ ClassDB::bind_method(D_METHOD("shape_get_data","shape"),&Physics2DServer::shape_get_data);
- ClassDB::bind_method(_MD("space_create"),&Physics2DServer::space_create);
- ClassDB::bind_method(_MD("space_set_active","space","active"),&Physics2DServer::space_set_active);
- ClassDB::bind_method(_MD("space_is_active","space"),&Physics2DServer::space_is_active);
- ClassDB::bind_method(_MD("space_set_param","space","param","value"),&Physics2DServer::space_set_param);
- ClassDB::bind_method(_MD("space_get_param","space","param"),&Physics2DServer::space_get_param);
- ClassDB::bind_method(_MD("space_get_direct_state:Physics2DDirectSpaceState","space"),&Physics2DServer::space_get_direct_state);
+ ClassDB::bind_method(D_METHOD("space_create"),&Physics2DServer::space_create);
+ ClassDB::bind_method(D_METHOD("space_set_active","space","active"),&Physics2DServer::space_set_active);
+ ClassDB::bind_method(D_METHOD("space_is_active","space"),&Physics2DServer::space_is_active);
+ ClassDB::bind_method(D_METHOD("space_set_param","space","param","value"),&Physics2DServer::space_set_param);
+ ClassDB::bind_method(D_METHOD("space_get_param","space","param"),&Physics2DServer::space_get_param);
+ ClassDB::bind_method(D_METHOD("space_get_direct_state:Physics2DDirectSpaceState","space"),&Physics2DServer::space_get_direct_state);
- ClassDB::bind_method(_MD("area_create"),&Physics2DServer::area_create);
- ClassDB::bind_method(_MD("area_set_space","area","space"),&Physics2DServer::area_set_space);
- ClassDB::bind_method(_MD("area_get_space","area"),&Physics2DServer::area_get_space);
+ ClassDB::bind_method(D_METHOD("area_create"),&Physics2DServer::area_create);
+ ClassDB::bind_method(D_METHOD("area_set_space","area","space"),&Physics2DServer::area_set_space);
+ ClassDB::bind_method(D_METHOD("area_get_space","area"),&Physics2DServer::area_get_space);
- ClassDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode);
- ClassDB::bind_method(_MD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode);
- ClassDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Transform2D()));
- ClassDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape);
- ClassDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape);
+ ClassDB::bind_method(D_METHOD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform);
- ClassDB::bind_method(_MD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count);
- ClassDB::bind_method(_MD("area_get_shape","area","shape_idx"),&Physics2DServer::area_get_shape);
- ClassDB::bind_method(_MD("area_get_shape_transform","area","shape_idx"),&Physics2DServer::area_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count);
+ ClassDB::bind_method(D_METHOD("area_get_shape","area","shape_idx"),&Physics2DServer::area_get_shape);
+ ClassDB::bind_method(D_METHOD("area_get_shape_transform","area","shape_idx"),&Physics2DServer::area_get_shape_transform);
- ClassDB::bind_method(_MD("area_remove_shape","area","shape_idx"),&Physics2DServer::area_remove_shape);
- ClassDB::bind_method(_MD("area_clear_shapes","area"),&Physics2DServer::area_clear_shapes);
+ ClassDB::bind_method(D_METHOD("area_remove_shape","area","shape_idx"),&Physics2DServer::area_remove_shape);
+ ClassDB::bind_method(D_METHOD("area_clear_shapes","area"),&Physics2DServer::area_clear_shapes);
- ClassDB::bind_method(_MD("area_set_layer_mask","area","mask"),&Physics2DServer::area_set_layer_mask);
- ClassDB::bind_method(_MD("area_set_collision_mask","area","mask"),&Physics2DServer::area_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("area_set_layer_mask","area","mask"),&Physics2DServer::area_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("area_set_collision_mask","area","mask"),&Physics2DServer::area_set_collision_mask);
- ClassDB::bind_method(_MD("area_set_param","area","param","value"),&Physics2DServer::area_set_param);
- ClassDB::bind_method(_MD("area_set_transform","area","transform"),&Physics2DServer::area_set_transform);
+ ClassDB::bind_method(D_METHOD("area_set_param","area","param","value"),&Physics2DServer::area_set_param);
+ ClassDB::bind_method(D_METHOD("area_set_transform","area","transform"),&Physics2DServer::area_set_transform);
- ClassDB::bind_method(_MD("area_get_param","area","param"),&Physics2DServer::area_get_param);
- ClassDB::bind_method(_MD("area_get_transform","area"),&Physics2DServer::area_get_transform);
+ ClassDB::bind_method(D_METHOD("area_get_param","area","param"),&Physics2DServer::area_get_param);
+ ClassDB::bind_method(D_METHOD("area_get_transform","area"),&Physics2DServer::area_get_transform);
- ClassDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&Physics2DServer::area_attach_object_instance_ID);
- ClassDB::bind_method(_MD("area_get_object_instance_ID","area"),&Physics2DServer::area_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_attach_object_instance_ID","area","id"),&Physics2DServer::area_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_get_object_instance_ID","area"),&Physics2DServer::area_get_object_instance_ID);
- ClassDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&Physics2DServer::area_set_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_monitor_callback","area","receiver","method"),&Physics2DServer::area_set_monitor_callback);
- ClassDB::bind_method(_MD("body_create","mode","init_sleeping"),&Physics2DServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("body_create","mode","init_sleeping"),&Physics2DServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
- ClassDB::bind_method(_MD("body_set_space","body","space"),&Physics2DServer::body_set_space);
- ClassDB::bind_method(_MD("body_get_space","body"),&Physics2DServer::body_get_space);
+ ClassDB::bind_method(D_METHOD("body_set_space","body","space"),&Physics2DServer::body_set_space);
+ ClassDB::bind_method(D_METHOD("body_get_space","body"),&Physics2DServer::body_get_space);
- ClassDB::bind_method(_MD("body_set_mode","body","mode"),&Physics2DServer::body_set_mode);
- ClassDB::bind_method(_MD("body_get_mode","body"),&Physics2DServer::body_get_mode);
+ ClassDB::bind_method(D_METHOD("body_set_mode","body","mode"),&Physics2DServer::body_set_mode);
+ ClassDB::bind_method(D_METHOD("body_get_mode","body"),&Physics2DServer::body_get_mode);
- ClassDB::bind_method(_MD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Transform2D()));
- ClassDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape);
- ClassDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform);
- ClassDB::bind_method(_MD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata);
+ ClassDB::bind_method(D_METHOD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape);
+ ClassDB::bind_method(D_METHOD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata);
- ClassDB::bind_method(_MD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count);
- ClassDB::bind_method(_MD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape);
- ClassDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform);
- ClassDB::bind_method(_MD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata);
+ ClassDB::bind_method(D_METHOD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count);
+ ClassDB::bind_method(D_METHOD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape);
+ ClassDB::bind_method(D_METHOD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata);
- ClassDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape);
- ClassDB::bind_method(_MD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes);
+ ClassDB::bind_method(D_METHOD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape);
+ ClassDB::bind_method(D_METHOD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes);
- ClassDB::bind_method(_MD("body_set_shape_as_trigger","body","shape_idx","enable"),&Physics2DServer::body_set_shape_as_trigger);
- ClassDB::bind_method(_MD("body_is_shape_set_as_trigger","body","shape_idx"),&Physics2DServer::body_is_shape_set_as_trigger);
+ ClassDB::bind_method(D_METHOD("body_set_shape_as_trigger","body","shape_idx","enable"),&Physics2DServer::body_set_shape_as_trigger);
+ ClassDB::bind_method(D_METHOD("body_is_shape_set_as_trigger","body","shape_idx"),&Physics2DServer::body_is_shape_set_as_trigger);
- ClassDB::bind_method(_MD("body_attach_object_instance_ID","body","id"),&Physics2DServer::body_attach_object_instance_ID);
- ClassDB::bind_method(_MD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_attach_object_instance_ID","body","id"),&Physics2DServer::body_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID);
- ClassDB::bind_method(_MD("body_set_continuous_collision_detection_mode","body","mode"),&Physics2DServer::body_set_continuous_collision_detection_mode);
- ClassDB::bind_method(_MD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode);
+ ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode","body","mode"),&Physics2DServer::body_set_continuous_collision_detection_mode);
+ ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode);
- ClassDB::bind_method(_MD("body_set_layer_mask","body","mask"),&Physics2DServer::body_set_layer_mask);
- ClassDB::bind_method(_MD("body_get_layer_mask","body"),&Physics2DServer::body_get_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_set_layer_mask","body","mask"),&Physics2DServer::body_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_get_layer_mask","body"),&Physics2DServer::body_get_layer_mask);
- ClassDB::bind_method(_MD("body_set_collision_mask","body","mask"),&Physics2DServer::body_set_collision_mask);
- ClassDB::bind_method(_MD("body_get_collision_mask","body"),&Physics2DServer::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_mask","body","mask"),&Physics2DServer::body_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_get_collision_mask","body"),&Physics2DServer::body_get_collision_mask);
- ClassDB::bind_method(_MD("body_set_param","body","param","value"),&Physics2DServer::body_set_param);
- ClassDB::bind_method(_MD("body_get_param","body","param"),&Physics2DServer::body_get_param);
+ ClassDB::bind_method(D_METHOD("body_set_param","body","param","value"),&Physics2DServer::body_set_param);
+ ClassDB::bind_method(D_METHOD("body_get_param","body","param"),&Physics2DServer::body_get_param);
- ClassDB::bind_method(_MD("body_set_state","body","state","value"),&Physics2DServer::body_set_state);
- ClassDB::bind_method(_MD("body_get_state","body","state"),&Physics2DServer::body_get_state);
+ ClassDB::bind_method(D_METHOD("body_set_state","body","state","value"),&Physics2DServer::body_set_state);
+ ClassDB::bind_method(D_METHOD("body_get_state","body","state"),&Physics2DServer::body_get_state);
- ClassDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse);
- ClassDB::bind_method(_MD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force);
- ClassDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity);
+ ClassDB::bind_method(D_METHOD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse);
+ ClassDB::bind_method(D_METHOD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force);
+ ClassDB::bind_method(D_METHOD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity);
- ClassDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception);
- ClassDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&Physics2DServer::body_remove_collision_exception);
+ ClassDB::bind_method(D_METHOD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception);
+ ClassDB::bind_method(D_METHOD("body_remove_collision_exception","body","excepted_body"),&Physics2DServer::body_remove_collision_exception);
//virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0;
- ClassDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported);
- ClassDB::bind_method(_MD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported);
- ClassDB::bind_method(_MD("body_set_one_way_collision_direction","body","normal"),&Physics2DServer::body_set_one_way_collision_direction);
- ClassDB::bind_method(_MD("body_get_one_way_collision_direction","body"),&Physics2DServer::body_get_one_way_collision_direction);
+ ClassDB::bind_method(D_METHOD("body_set_one_way_collision_direction","body","normal"),&Physics2DServer::body_set_one_way_collision_direction);
+ ClassDB::bind_method(D_METHOD("body_get_one_way_collision_direction","body"),&Physics2DServer::body_get_one_way_collision_direction);
- ClassDB::bind_method(_MD("body_set_one_way_collision_max_depth","body","depth"),&Physics2DServer::body_set_one_way_collision_max_depth);
- ClassDB::bind_method(_MD("body_get_one_way_collision_max_depth","body"),&Physics2DServer::body_get_one_way_collision_max_depth);
+ ClassDB::bind_method(D_METHOD("body_set_one_way_collision_max_depth","body","depth"),&Physics2DServer::body_set_one_way_collision_max_depth);
+ ClassDB::bind_method(D_METHOD("body_get_one_way_collision_max_depth","body"),&Physics2DServer::body_get_one_way_collision_max_depth);
- ClassDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration);
- ClassDB::bind_method(_MD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration);
+ ClassDB::bind_method(D_METHOD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration);
+ ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration);
- ClassDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&Physics2DServer::body_set_force_integration_callback,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_set_force_integration_callback","body","receiver","method","userdata"),&Physics2DServer::body_set_force_integration_callback,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("body_test_motion","body","from","motion","margin","result:Physics2DTestMotionResult"),&Physics2DServer::_body_test_motion,DEFVAL(0.08),DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_test_motion","body","from","motion","margin","result:Physics2DTestMotionResult"),&Physics2DServer::_body_test_motion,DEFVAL(0.08),DEFVAL(Variant()));
/* JOINT API */
- ClassDB::bind_method(_MD("joint_set_param","joint","param","value"),&Physics2DServer::joint_set_param);
- ClassDB::bind_method(_MD("joint_get_param","joint","param"),&Physics2DServer::joint_get_param);
+ ClassDB::bind_method(D_METHOD("joint_set_param","joint","param","value"),&Physics2DServer::joint_set_param);
+ ClassDB::bind_method(D_METHOD("joint_get_param","joint","param"),&Physics2DServer::joint_get_param);
- ClassDB::bind_method(_MD("pin_joint_create","anchor","body_a","body_b"),&Physics2DServer::pin_joint_create,DEFVAL(RID()));
- ClassDB::bind_method(_MD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&Physics2DServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
- ClassDB::bind_method(_MD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&Physics2DServer::damped_spring_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("pin_joint_create","anchor","body_a","body_b"),&Physics2DServer::pin_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&Physics2DServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&Physics2DServer::damped_spring_joint_create,DEFVAL(RID()));
- ClassDB::bind_method(_MD("damped_string_joint_set_param","joint","param","value"),&Physics2DServer::damped_string_joint_set_param);
- ClassDB::bind_method(_MD("damped_string_joint_get_param","joint","param"),&Physics2DServer::damped_string_joint_get_param);
+ ClassDB::bind_method(D_METHOD("damped_string_joint_set_param","joint","param","value"),&Physics2DServer::damped_string_joint_set_param);
+ ClassDB::bind_method(D_METHOD("damped_string_joint_get_param","joint","param"),&Physics2DServer::damped_string_joint_get_param);
- ClassDB::bind_method(_MD("joint_get_type","joint"),&Physics2DServer::joint_get_type);
+ ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&Physics2DServer::joint_get_type);
- ClassDB::bind_method(_MD("free_rid","rid"),&Physics2DServer::free);
+ ClassDB::bind_method(D_METHOD("free_rid","rid"),&Physics2DServer::free);
- ClassDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active);
+ ClassDB::bind_method(D_METHOD("set_active","active"),&Physics2DServer::set_active);
- ClassDB::bind_method(_MD("get_process_info","process_info"),&Physics2DServer::get_process_info);
+ ClassDB::bind_method(D_METHOD("get_process_info","process_info"),&Physics2DServer::get_process_info);
- //ClassDB::bind_method(_MD("init"),&Physics2DServer::init);
- //ClassDB::bind_method(_MD("step"),&Physics2DServer::step);
- //ClassDB::bind_method(_MD("sync"),&Physics2DServer::sync);
- //ClassDB::bind_method(_MD("flush_queries"),&Physics2DServer::flush_queries);
+ //ClassDB::bind_method(D_METHOD("init"),&Physics2DServer::init);
+ //ClassDB::bind_method(D_METHOD("step"),&Physics2DServer::step);
+ //ClassDB::bind_method(D_METHOD("sync"),&Physics2DServer::sync);
+ //ClassDB::bind_method(D_METHOD("flush_queries"),&Physics2DServer::flush_queries);
BIND_CONSTANT( SPACE_PARAM_CONTACT_RECYCLE_RADIUS );
BIND_CONSTANT( SPACE_PARAM_CONTACT_MAX_SEPARATION );
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index ab13e2b3a5..e76bfd113c 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -74,46 +74,46 @@ PhysicsServer * PhysicsServer::get_singleton() {
void PhysicsDirectBodyState::_bind_methods() {
- ClassDB::bind_method(_MD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity);
- ClassDB::bind_method(_MD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp);
- ClassDB::bind_method(_MD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity);
+ ClassDB::bind_method(D_METHOD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp);
- ClassDB::bind_method(_MD("get_center_of_mass"),&PhysicsDirectBodyState::get_center_of_mass);
- ClassDB::bind_method(_MD("get_principal_inetria_axes"),&PhysicsDirectBodyState::get_principal_inertia_axes);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass"),&PhysicsDirectBodyState::get_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_principal_inetria_axes"),&PhysicsDirectBodyState::get_principal_inertia_axes);
- ClassDB::bind_method(_MD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass);
- ClassDB::bind_method(_MD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia);
+ ClassDB::bind_method(D_METHOD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass);
+ ClassDB::bind_method(D_METHOD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia);
- ClassDB::bind_method(_MD("set_linear_velocity","velocity"),&PhysicsDirectBodyState::set_linear_velocity);
- ClassDB::bind_method(_MD("get_linear_velocity"),&PhysicsDirectBodyState::get_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_linear_velocity","velocity"),&PhysicsDirectBodyState::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"),&PhysicsDirectBodyState::get_linear_velocity);
- ClassDB::bind_method(_MD("set_angular_velocity","velocity"),&PhysicsDirectBodyState::set_angular_velocity);
- ClassDB::bind_method(_MD("get_angular_velocity"),&PhysicsDirectBodyState::get_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_angular_velocity","velocity"),&PhysicsDirectBodyState::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"),&PhysicsDirectBodyState::get_angular_velocity);
- ClassDB::bind_method(_MD("set_transform","transform"),&PhysicsDirectBodyState::set_transform);
- ClassDB::bind_method(_MD("get_transform"),&PhysicsDirectBodyState::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&PhysicsDirectBodyState::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&PhysicsDirectBodyState::get_transform);
- ClassDB::bind_method(_MD("add_force","force","pos"),&PhysicsDirectBodyState::add_force);
- ClassDB::bind_method(_MD("apply_impulse","pos","j"),&PhysicsDirectBodyState::apply_impulse);
- ClassDB::bind_method(_MD("apply_torqe_impulse","j"),&PhysicsDirectBodyState::apply_torque_impulse);
+ ClassDB::bind_method(D_METHOD("add_force","force","pos"),&PhysicsDirectBodyState::add_force);
+ ClassDB::bind_method(D_METHOD("apply_impulse","pos","j"),&PhysicsDirectBodyState::apply_impulse);
+ ClassDB::bind_method(D_METHOD("apply_torqe_impulse","j"),&PhysicsDirectBodyState::apply_torque_impulse);
- ClassDB::bind_method(_MD("set_sleep_state","enabled"),&PhysicsDirectBodyState::set_sleep_state);
- ClassDB::bind_method(_MD("is_sleeping"),&PhysicsDirectBodyState::is_sleeping);
+ ClassDB::bind_method(D_METHOD("set_sleep_state","enabled"),&PhysicsDirectBodyState::set_sleep_state);
+ ClassDB::bind_method(D_METHOD("is_sleeping"),&PhysicsDirectBodyState::is_sleeping);
- ClassDB::bind_method(_MD("get_contact_count"),&PhysicsDirectBodyState::get_contact_count);
+ ClassDB::bind_method(D_METHOD("get_contact_count"),&PhysicsDirectBodyState::get_contact_count);
- ClassDB::bind_method(_MD("get_contact_local_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_local_pos);
- ClassDB::bind_method(_MD("get_contact_local_normal","contact_idx"),&PhysicsDirectBodyState::get_contact_local_normal);
- ClassDB::bind_method(_MD("get_contact_local_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_local_shape);
- ClassDB::bind_method(_MD("get_contact_collider","contact_idx"),&PhysicsDirectBodyState::get_contact_collider);
- ClassDB::bind_method(_MD("get_contact_collider_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_pos);
- ClassDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_id);
- ClassDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_object);
- ClassDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_shape);
- ClassDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_velocity_at_pos);
- ClassDB::bind_method(_MD("get_step"),&PhysicsDirectBodyState::get_step);
- ClassDB::bind_method(_MD("integrate_forces"),&PhysicsDirectBodyState::integrate_forces);
- ClassDB::bind_method(_MD("get_space_state:PhysicsDirectSpaceState"),&PhysicsDirectBodyState::get_space_state);
+ ClassDB::bind_method(D_METHOD("get_contact_local_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_local_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_local_normal","contact_idx"),&PhysicsDirectBodyState::get_contact_local_normal);
+ ClassDB::bind_method(D_METHOD("get_contact_local_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_local_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider","contact_idx"),&PhysicsDirectBodyState::get_contact_collider);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_id","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_id);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_object","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_object);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_velocity_at_pos);
+ ClassDB::bind_method(D_METHOD("get_step"),&PhysicsDirectBodyState::get_step);
+ ClassDB::bind_method(D_METHOD("integrate_forces"),&PhysicsDirectBodyState::integrate_forces);
+ ClassDB::bind_method(D_METHOD("get_space_state:PhysicsDirectSpaceState"),&PhysicsDirectBodyState::get_space_state);
}
@@ -197,24 +197,24 @@ Vector<RID> PhysicsShapeQueryParameters::get_exclude() const{
void PhysicsShapeQueryParameters::_bind_methods() {
- ClassDB::bind_method(_MD("set_shape","shape:Shape"),&PhysicsShapeQueryParameters::set_shape);
- ClassDB::bind_method(_MD("set_shape_rid","shape"),&PhysicsShapeQueryParameters::set_shape_rid);
- ClassDB::bind_method(_MD("get_shape_rid"),&PhysicsShapeQueryParameters::get_shape_rid);
+ ClassDB::bind_method(D_METHOD("set_shape","shape:Shape"),&PhysicsShapeQueryParameters::set_shape);
+ ClassDB::bind_method(D_METHOD("set_shape_rid","shape"),&PhysicsShapeQueryParameters::set_shape_rid);
+ ClassDB::bind_method(D_METHOD("get_shape_rid"),&PhysicsShapeQueryParameters::get_shape_rid);
- ClassDB::bind_method(_MD("set_transform","transform"),&PhysicsShapeQueryParameters::set_transform);
- ClassDB::bind_method(_MD("get_transform"),&PhysicsShapeQueryParameters::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&PhysicsShapeQueryParameters::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&PhysicsShapeQueryParameters::get_transform);
- ClassDB::bind_method(_MD("set_margin","margin"),&PhysicsShapeQueryParameters::set_margin);
- ClassDB::bind_method(_MD("get_margin"),&PhysicsShapeQueryParameters::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin","margin"),&PhysicsShapeQueryParameters::set_margin);
+ ClassDB::bind_method(D_METHOD("get_margin"),&PhysicsShapeQueryParameters::get_margin);
- ClassDB::bind_method(_MD("set_layer_mask","layer_mask"),&PhysicsShapeQueryParameters::set_layer_mask);
- ClassDB::bind_method(_MD("get_layer_mask"),&PhysicsShapeQueryParameters::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&PhysicsShapeQueryParameters::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&PhysicsShapeQueryParameters::get_layer_mask);
- ClassDB::bind_method(_MD("set_object_type_mask","object_type_mask"),&PhysicsShapeQueryParameters::set_object_type_mask);
- ClassDB::bind_method(_MD("get_object_type_mask"),&PhysicsShapeQueryParameters::get_object_type_mask);
+ ClassDB::bind_method(D_METHOD("set_object_type_mask","object_type_mask"),&PhysicsShapeQueryParameters::set_object_type_mask);
+ ClassDB::bind_method(D_METHOD("get_object_type_mask"),&PhysicsShapeQueryParameters::get_object_type_mask);
- ClassDB::bind_method(_MD("set_exclude","exclude"),&PhysicsShapeQueryParameters::set_exclude);
- ClassDB::bind_method(_MD("get_exclude"),&PhysicsShapeQueryParameters::get_exclude);
+ ClassDB::bind_method(D_METHOD("set_exclude","exclude"),&PhysicsShapeQueryParameters::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"),&PhysicsShapeQueryParameters::get_exclude);
}
@@ -363,14 +363,14 @@ PhysicsDirectSpaceState::PhysicsDirectSpaceState() {
void PhysicsDirectSpaceState::_bind_methods() {
- //ClassDB::bind_method(_MD("intersect_ray","from","to","exclude","umask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0));
- //ClassDB::bind_method(_MD("intersect_shape:PhysicsShapeQueryResult","shape","xform","result_max","exclude","umask"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("intersect_ray","from","to","exclude","umask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("intersect_shape:PhysicsShapeQueryResult","shape","xform","result_max","exclude","umask"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
- ClassDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
- ClassDB::bind_method(_MD("intersect_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(32));
- ClassDB::bind_method(_MD("cast_motion","shape:PhysicsShapeQueryParameters","motion"),&PhysicsDirectSpaceState::_cast_motion);
- ClassDB::bind_method(_MD("collide_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_collide_shape,DEFVAL(32));
- ClassDB::bind_method(_MD("get_rest_info","shape:PhysicsShapeQueryParameters"),&PhysicsDirectSpaceState::_get_rest_info);
+ ClassDB::bind_method(D_METHOD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
+ ClassDB::bind_method(D_METHOD("intersect_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("cast_motion","shape:PhysicsShapeQueryParameters","motion"),&PhysicsDirectSpaceState::_cast_motion);
+ ClassDB::bind_method(D_METHOD("collide_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_collide_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("get_rest_info","shape:PhysicsShapeQueryParameters"),&PhysicsDirectSpaceState::_get_rest_info);
BIND_CONSTANT( TYPE_MASK_STATIC_BODY );
@@ -411,11 +411,11 @@ PhysicsShapeQueryResult::PhysicsShapeQueryResult() {
void PhysicsShapeQueryResult::_bind_methods() {
- ClassDB::bind_method(_MD("get_result_count"),&PhysicsShapeQueryResult::get_result_count);
- ClassDB::bind_method(_MD("get_result_rid","idx"),&PhysicsShapeQueryResult::get_result_rid);
- ClassDB::bind_method(_MD("get_result_object_id","idx"),&PhysicsShapeQueryResult::get_result_object_id);
- ClassDB::bind_method(_MD("get_result_object","idx"),&PhysicsShapeQueryResult::get_result_object);
- ClassDB::bind_method(_MD("get_result_object_shape","idx"),&PhysicsShapeQueryResult::get_result_object_shape);
+ ClassDB::bind_method(D_METHOD("get_result_count"),&PhysicsShapeQueryResult::get_result_count);
+ ClassDB::bind_method(D_METHOD("get_result_rid","idx"),&PhysicsShapeQueryResult::get_result_rid);
+ ClassDB::bind_method(D_METHOD("get_result_object_id","idx"),&PhysicsShapeQueryResult::get_result_object_id);
+ ClassDB::bind_method(D_METHOD("get_result_object","idx"),&PhysicsShapeQueryResult::get_result_object);
+ ClassDB::bind_method(D_METHOD("get_result_object_shape","idx"),&PhysicsShapeQueryResult::get_result_object_shape);
}
@@ -429,118 +429,118 @@ void PhysicsShapeQueryResult::_bind_methods() {
void PhysicsServer::_bind_methods() {
- ClassDB::bind_method(_MD("shape_create","type"),&PhysicsServer::shape_create);
- ClassDB::bind_method(_MD("shape_set_data","shape","data"),&PhysicsServer::shape_set_data);
+ ClassDB::bind_method(D_METHOD("shape_create","type"),&PhysicsServer::shape_create);
+ ClassDB::bind_method(D_METHOD("shape_set_data","shape","data"),&PhysicsServer::shape_set_data);
- ClassDB::bind_method(_MD("shape_get_type","shape"),&PhysicsServer::shape_get_type);
- ClassDB::bind_method(_MD("shape_get_data","shape"),&PhysicsServer::shape_get_data);
+ ClassDB::bind_method(D_METHOD("shape_get_type","shape"),&PhysicsServer::shape_get_type);
+ ClassDB::bind_method(D_METHOD("shape_get_data","shape"),&PhysicsServer::shape_get_data);
- ClassDB::bind_method(_MD("space_create"),&PhysicsServer::space_create);
- ClassDB::bind_method(_MD("space_set_active","space","active"),&PhysicsServer::space_set_active);
- ClassDB::bind_method(_MD("space_is_active","space"),&PhysicsServer::space_is_active);
- ClassDB::bind_method(_MD("space_set_param","space","param","value"),&PhysicsServer::space_set_param);
- ClassDB::bind_method(_MD("space_get_param","space","param"),&PhysicsServer::space_get_param);
- ClassDB::bind_method(_MD("space_get_direct_state:PhysicsDirectSpaceState","space"),&PhysicsServer::space_get_direct_state);
+ ClassDB::bind_method(D_METHOD("space_create"),&PhysicsServer::space_create);
+ ClassDB::bind_method(D_METHOD("space_set_active","space","active"),&PhysicsServer::space_set_active);
+ ClassDB::bind_method(D_METHOD("space_is_active","space"),&PhysicsServer::space_is_active);
+ ClassDB::bind_method(D_METHOD("space_set_param","space","param","value"),&PhysicsServer::space_set_param);
+ ClassDB::bind_method(D_METHOD("space_get_param","space","param"),&PhysicsServer::space_get_param);
+ ClassDB::bind_method(D_METHOD("space_get_direct_state:PhysicsDirectSpaceState","space"),&PhysicsServer::space_get_direct_state);
- ClassDB::bind_method(_MD("area_create"),&PhysicsServer::area_create);
- ClassDB::bind_method(_MD("area_set_space","area","space"),&PhysicsServer::area_set_space);
- ClassDB::bind_method(_MD("area_get_space","area"),&PhysicsServer::area_get_space);
+ ClassDB::bind_method(D_METHOD("area_create"),&PhysicsServer::area_create);
+ ClassDB::bind_method(D_METHOD("area_set_space","area","space"),&PhysicsServer::area_set_space);
+ ClassDB::bind_method(D_METHOD("area_get_space","area"),&PhysicsServer::area_get_space);
- ClassDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode);
- ClassDB::bind_method(_MD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode);
- ClassDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform()));
- ClassDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape);
- ClassDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform()));
+ ClassDB::bind_method(D_METHOD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape);
+ ClassDB::bind_method(D_METHOD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform);
- ClassDB::bind_method(_MD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count);
- ClassDB::bind_method(_MD("area_get_shape","area","shape_idx"),&PhysicsServer::area_get_shape);
- ClassDB::bind_method(_MD("area_get_shape_transform","area","shape_idx"),&PhysicsServer::area_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count);
+ ClassDB::bind_method(D_METHOD("area_get_shape","area","shape_idx"),&PhysicsServer::area_get_shape);
+ ClassDB::bind_method(D_METHOD("area_get_shape_transform","area","shape_idx"),&PhysicsServer::area_get_shape_transform);
- ClassDB::bind_method(_MD("area_remove_shape","area","shape_idx"),&PhysicsServer::area_remove_shape);
- ClassDB::bind_method(_MD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes);
+ ClassDB::bind_method(D_METHOD("area_remove_shape","area","shape_idx"),&PhysicsServer::area_remove_shape);
+ ClassDB::bind_method(D_METHOD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes);
- ClassDB::bind_method(_MD("area_set_layer_mask","area","mask"),&PhysicsServer::area_set_layer_mask);
- ClassDB::bind_method(_MD("area_set_collision_mask","area","mask"),&PhysicsServer::area_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("area_set_layer_mask","area","mask"),&PhysicsServer::area_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("area_set_collision_mask","area","mask"),&PhysicsServer::area_set_collision_mask);
- ClassDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_set_param);
- ClassDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform);
+ ClassDB::bind_method(D_METHOD("area_set_param","area","param","value"),&PhysicsServer::area_set_param);
+ ClassDB::bind_method(D_METHOD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform);
- ClassDB::bind_method(_MD("area_get_param","area","param"),&PhysicsServer::area_get_param);
- ClassDB::bind_method(_MD("area_get_transform","area"),&PhysicsServer::area_get_transform);
+ ClassDB::bind_method(D_METHOD("area_get_param","area","param"),&PhysicsServer::area_get_param);
+ ClassDB::bind_method(D_METHOD("area_get_transform","area"),&PhysicsServer::area_get_transform);
- ClassDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&PhysicsServer::area_attach_object_instance_ID);
- ClassDB::bind_method(_MD("area_get_object_instance_ID","area"),&PhysicsServer::area_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_attach_object_instance_ID","area","id"),&PhysicsServer::area_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_get_object_instance_ID","area"),&PhysicsServer::area_get_object_instance_ID);
- ClassDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&PhysicsServer::area_set_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_monitor_callback","area","receiver","method"),&PhysicsServer::area_set_monitor_callback);
- ClassDB::bind_method(_MD("area_set_ray_pickable","area","enable"),&PhysicsServer::area_set_ray_pickable);
- ClassDB::bind_method(_MD("area_is_ray_pickable","area"),&PhysicsServer::area_is_ray_pickable);
+ ClassDB::bind_method(D_METHOD("area_set_ray_pickable","area","enable"),&PhysicsServer::area_set_ray_pickable);
+ ClassDB::bind_method(D_METHOD("area_is_ray_pickable","area"),&PhysicsServer::area_is_ray_pickable);
- ClassDB::bind_method(_MD("body_create","mode","init_sleeping"),&PhysicsServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("body_create","mode","init_sleeping"),&PhysicsServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
- ClassDB::bind_method(_MD("body_set_space","body","space"),&PhysicsServer::body_set_space);
- ClassDB::bind_method(_MD("body_get_space","body"),&PhysicsServer::body_get_space);
+ ClassDB::bind_method(D_METHOD("body_set_space","body","space"),&PhysicsServer::body_set_space);
+ ClassDB::bind_method(D_METHOD("body_get_space","body"),&PhysicsServer::body_get_space);
- ClassDB::bind_method(_MD("body_set_mode","body","mode"),&PhysicsServer::body_set_mode);
- ClassDB::bind_method(_MD("body_get_mode","body"),&PhysicsServer::body_get_mode);
+ ClassDB::bind_method(D_METHOD("body_set_mode","body","mode"),&PhysicsServer::body_set_mode);
+ ClassDB::bind_method(D_METHOD("body_get_mode","body"),&PhysicsServer::body_get_mode);
- ClassDB::bind_method(_MD("body_set_layer_mask","body","mask"),&PhysicsServer::body_set_layer_mask);
- ClassDB::bind_method(_MD("body_get_layer_mask","body"),&PhysicsServer::body_get_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_set_layer_mask","body","mask"),&PhysicsServer::body_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_get_layer_mask","body"),&PhysicsServer::body_get_layer_mask);
- ClassDB::bind_method(_MD("body_set_collision_mask","body","mask"),&PhysicsServer::body_set_collision_mask);
- ClassDB::bind_method(_MD("body_get_collision_mask","body"),&PhysicsServer::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_mask","body","mask"),&PhysicsServer::body_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_get_collision_mask","body"),&PhysicsServer::body_get_collision_mask);
- ClassDB::bind_method(_MD("body_add_shape","body","shape","transform"),&PhysicsServer::body_add_shape,DEFVAL(Transform()));
- ClassDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&PhysicsServer::body_set_shape);
- ClassDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&PhysicsServer::body_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_add_shape","body","shape","transform"),&PhysicsServer::body_add_shape,DEFVAL(Transform()));
+ ClassDB::bind_method(D_METHOD("body_set_shape","body","shape_idx","shape"),&PhysicsServer::body_set_shape);
+ ClassDB::bind_method(D_METHOD("body_set_shape_transform","body","shape_idx","transform"),&PhysicsServer::body_set_shape_transform);
- ClassDB::bind_method(_MD("body_get_shape_count","body"),&PhysicsServer::body_get_shape_count);
- ClassDB::bind_method(_MD("body_get_shape","body","shape_idx"),&PhysicsServer::body_get_shape);
- ClassDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&PhysicsServer::body_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_get_shape_count","body"),&PhysicsServer::body_get_shape_count);
+ ClassDB::bind_method(D_METHOD("body_get_shape","body","shape_idx"),&PhysicsServer::body_get_shape);
+ ClassDB::bind_method(D_METHOD("body_get_shape_transform","body","shape_idx"),&PhysicsServer::body_get_shape_transform);
- ClassDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&PhysicsServer::body_remove_shape);
- ClassDB::bind_method(_MD("body_clear_shapes","body"),&PhysicsServer::body_clear_shapes);
+ ClassDB::bind_method(D_METHOD("body_remove_shape","body","shape_idx"),&PhysicsServer::body_remove_shape);
+ ClassDB::bind_method(D_METHOD("body_clear_shapes","body"),&PhysicsServer::body_clear_shapes);
- ClassDB::bind_method(_MD("body_attach_object_instance_ID","body","id"),&PhysicsServer::body_attach_object_instance_ID);
- ClassDB::bind_method(_MD("body_get_object_instance_ID","body"),&PhysicsServer::body_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_attach_object_instance_ID","body","id"),&PhysicsServer::body_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_get_object_instance_ID","body"),&PhysicsServer::body_get_object_instance_ID);
- ClassDB::bind_method(_MD("body_set_enable_continuous_collision_detection","body","enable"),&PhysicsServer::body_set_enable_continuous_collision_detection);
- ClassDB::bind_method(_MD("body_is_continuous_collision_detection_enabled","body"),&PhysicsServer::body_is_continuous_collision_detection_enabled);
+ ClassDB::bind_method(D_METHOD("body_set_enable_continuous_collision_detection","body","enable"),&PhysicsServer::body_set_enable_continuous_collision_detection);
+ ClassDB::bind_method(D_METHOD("body_is_continuous_collision_detection_enabled","body"),&PhysicsServer::body_is_continuous_collision_detection_enabled);
- //ClassDB::bind_method(_MD("body_set_user_flags","flags""),&PhysicsServer::body_set_shape,DEFVAL(Transform));
- //ClassDB::bind_method(_MD("body_get_user_flags","body","shape_idx","shape"),&PhysicsServer::body_get_shape);
+ //ClassDB::bind_method(D_METHOD("body_set_user_flags","flags""),&PhysicsServer::body_set_shape,DEFVAL(Transform));
+ //ClassDB::bind_method(D_METHOD("body_get_user_flags","body","shape_idx","shape"),&PhysicsServer::body_get_shape);
- ClassDB::bind_method(_MD("body_set_param","body","param","value"),&PhysicsServer::body_set_param);
- ClassDB::bind_method(_MD("body_get_param","body","param"),&PhysicsServer::body_get_param);
+ ClassDB::bind_method(D_METHOD("body_set_param","body","param","value"),&PhysicsServer::body_set_param);
+ ClassDB::bind_method(D_METHOD("body_get_param","body","param"),&PhysicsServer::body_get_param);
- ClassDB::bind_method(_MD("body_set_state","body","state","value"),&PhysicsServer::body_set_state);
- ClassDB::bind_method(_MD("body_get_state","body","state"),&PhysicsServer::body_get_state);
+ ClassDB::bind_method(D_METHOD("body_set_state","body","state","value"),&PhysicsServer::body_set_state);
+ ClassDB::bind_method(D_METHOD("body_get_state","body","state"),&PhysicsServer::body_get_state);
- ClassDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&PhysicsServer::body_apply_impulse);
- ClassDB::bind_method(_MD("body_apply_torque_impulse","body","impulse"),&PhysicsServer::body_apply_torque_impulse);
- ClassDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity);
+ ClassDB::bind_method(D_METHOD("body_apply_impulse","body","pos","impulse"),&PhysicsServer::body_apply_impulse);
+ ClassDB::bind_method(D_METHOD("body_apply_torque_impulse","body","impulse"),&PhysicsServer::body_apply_torque_impulse);
+ ClassDB::bind_method(D_METHOD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity);
- ClassDB::bind_method(_MD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock);
- ClassDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock);
+ ClassDB::bind_method(D_METHOD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock);
+ ClassDB::bind_method(D_METHOD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock);
- ClassDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception);
- ClassDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception);
+ ClassDB::bind_method(D_METHOD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception);
+ ClassDB::bind_method(D_METHOD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception);
//virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0;
- ClassDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&PhysicsServer::body_set_max_contacts_reported);
- ClassDB::bind_method(_MD("body_get_max_contacts_reported","body"),&PhysicsServer::body_get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported","body","amount"),&PhysicsServer::body_set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported","body"),&PhysicsServer::body_get_max_contacts_reported);
- ClassDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&PhysicsServer::body_set_omit_force_integration);
- ClassDB::bind_method(_MD("body_is_omitting_force_integration","body"),&PhysicsServer::body_is_omitting_force_integration);
+ ClassDB::bind_method(D_METHOD("body_set_omit_force_integration","body","enable"),&PhysicsServer::body_set_omit_force_integration);
+ ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration","body"),&PhysicsServer::body_is_omitting_force_integration);
- ClassDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable);
- ClassDB::bind_method(_MD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable);
+ ClassDB::bind_method(D_METHOD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable);
+ ClassDB::bind_method(D_METHOD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable);
/* JOINT API */
@@ -550,15 +550,15 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( JOINT_CONE_TWIST );
BIND_CONSTANT( JOINT_6DOF );
- ClassDB::bind_method(_MD("joint_create_pin","body_A","local_A","body_B","local_B"),&PhysicsServer::joint_create_pin);
- ClassDB::bind_method(_MD("pin_joint_set_param","joint","param","value"),&PhysicsServer::pin_joint_set_param);
- ClassDB::bind_method(_MD("pin_joint_get_param","joint","param"),&PhysicsServer::pin_joint_get_param);
+ ClassDB::bind_method(D_METHOD("joint_create_pin","body_A","local_A","body_B","local_B"),&PhysicsServer::joint_create_pin);
+ ClassDB::bind_method(D_METHOD("pin_joint_set_param","joint","param","value"),&PhysicsServer::pin_joint_set_param);
+ ClassDB::bind_method(D_METHOD("pin_joint_get_param","joint","param"),&PhysicsServer::pin_joint_get_param);
- ClassDB::bind_method(_MD("pin_joint_set_local_A","joint","local_A"),&PhysicsServer::pin_joint_set_local_A);
- ClassDB::bind_method(_MD("pin_joint_get_local_A","joint"),&PhysicsServer::pin_joint_get_local_A);
+ ClassDB::bind_method(D_METHOD("pin_joint_set_local_A","joint","local_A"),&PhysicsServer::pin_joint_set_local_A);
+ ClassDB::bind_method(D_METHOD("pin_joint_get_local_A","joint"),&PhysicsServer::pin_joint_get_local_A);
- ClassDB::bind_method(_MD("pin_joint_set_local_B","joint","local_B"),&PhysicsServer::pin_joint_set_local_B);
- ClassDB::bind_method(_MD("pin_joint_get_local_B","joint"),&PhysicsServer::pin_joint_get_local_B);
+ ClassDB::bind_method(D_METHOD("pin_joint_set_local_B","joint","local_B"),&PhysicsServer::pin_joint_set_local_B);
+ ClassDB::bind_method(D_METHOD("pin_joint_get_local_B","joint"),&PhysicsServer::pin_joint_get_local_B);
BIND_CONSTANT(PIN_JOINT_BIAS );
BIND_CONSTANT(PIN_JOINT_DAMPING );
@@ -576,18 +576,18 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT(HINGE_JOINT_FLAG_USE_LIMIT);
BIND_CONSTANT(HINGE_JOINT_FLAG_ENABLE_MOTOR);
- ClassDB::bind_method(_MD("joint_create_hinge","body_A","hinge_A","body_B","hinge_B"),&PhysicsServer::joint_create_hinge);
+ ClassDB::bind_method(D_METHOD("joint_create_hinge","body_A","hinge_A","body_B","hinge_B"),&PhysicsServer::joint_create_hinge);
- ClassDB::bind_method(_MD("hinge_joint_set_param","joint","param","value"),&PhysicsServer::hinge_joint_set_param);
- ClassDB::bind_method(_MD("hinge_joint_get_param","joint","param"),&PhysicsServer::hinge_joint_get_param);
+ ClassDB::bind_method(D_METHOD("hinge_joint_set_param","joint","param","value"),&PhysicsServer::hinge_joint_set_param);
+ ClassDB::bind_method(D_METHOD("hinge_joint_get_param","joint","param"),&PhysicsServer::hinge_joint_get_param);
- ClassDB::bind_method(_MD("hinge_joint_set_flag","joint","flag","enabled"),&PhysicsServer::hinge_joint_set_flag);
- ClassDB::bind_method(_MD("hinge_joint_get_flag","joint","flag"),&PhysicsServer::hinge_joint_get_flag);
+ ClassDB::bind_method(D_METHOD("hinge_joint_set_flag","joint","flag","enabled"),&PhysicsServer::hinge_joint_set_flag);
+ ClassDB::bind_method(D_METHOD("hinge_joint_get_flag","joint","flag"),&PhysicsServer::hinge_joint_get_flag);
- ClassDB::bind_method(_MD("joint_create_slider","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_slider);
+ ClassDB::bind_method(D_METHOD("joint_create_slider","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_slider);
- ClassDB::bind_method(_MD("slider_joint_set_param","joint","param","value"),&PhysicsServer::slider_joint_set_param);
- ClassDB::bind_method(_MD("slider_joint_get_param","joint","param"),&PhysicsServer::slider_joint_get_param);
+ ClassDB::bind_method(D_METHOD("slider_joint_set_param","joint","param","value"),&PhysicsServer::slider_joint_set_param);
+ ClassDB::bind_method(D_METHOD("slider_joint_get_param","joint","param"),&PhysicsServer::slider_joint_get_param);
BIND_CONSTANT( SLIDER_JOINT_LINEAR_LIMIT_UPPER );
BIND_CONSTANT( SLIDER_JOINT_LINEAR_LIMIT_LOWER );
@@ -615,10 +615,10 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( SLIDER_JOINT_MAX );
- ClassDB::bind_method(_MD("joint_create_cone_twist","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_cone_twist);
+ ClassDB::bind_method(D_METHOD("joint_create_cone_twist","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_cone_twist);
- ClassDB::bind_method(_MD("cone_twist_joint_set_param","joint","param","value"),&PhysicsServer::cone_twist_joint_set_param);
- ClassDB::bind_method(_MD("cone_twist_joint_get_param","joint","param"),&PhysicsServer::cone_twist_joint_get_param);
+ ClassDB::bind_method(D_METHOD("cone_twist_joint_set_param","joint","param","value"),&PhysicsServer::cone_twist_joint_set_param);
+ ClassDB::bind_method(D_METHOD("cone_twist_joint_get_param","joint","param"),&PhysicsServer::cone_twist_joint_get_param);
BIND_CONSTANT( CONE_TWIST_JOINT_SWING_SPAN );
BIND_CONSTANT( CONE_TWIST_JOINT_TWIST_SPAN );
@@ -647,44 +647,44 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT );
BIND_CONSTANT( G6DOF_JOINT_FLAG_ENABLE_MOTOR );
- ClassDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
+ ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
- ClassDB::bind_method(_MD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority);
- ClassDB::bind_method(_MD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority);
+ ClassDB::bind_method(D_METHOD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority);
+ ClassDB::bind_method(D_METHOD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority);
- ClassDB::bind_method(_MD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof);
+ ClassDB::bind_method(D_METHOD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof);
- ClassDB::bind_method(_MD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param);
- ClassDB::bind_method(_MD("generic_6dof_joint_get_param","joint","axis","param"),&PhysicsServer::generic_6dof_joint_get_param);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_param","joint","axis","param"),&PhysicsServer::generic_6dof_joint_get_param);
- ClassDB::bind_method(_MD("generic_6dof_joint_set_flag","joint","axis","flag","enable"),&PhysicsServer::generic_6dof_joint_set_flag);
- ClassDB::bind_method(_MD("generic_6dof_joint_get_flag","joint","axis","flag"),&PhysicsServer::generic_6dof_joint_get_flag);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_flag","joint","axis","flag","enable"),&PhysicsServer::generic_6dof_joint_set_flag);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_flag","joint","axis","flag"),&PhysicsServer::generic_6dof_joint_get_flag);
/*
- ClassDB::bind_method(_MD("joint_set_param","joint","param","value"),&PhysicsServer::joint_set_param);
- ClassDB::bind_method(_MD("joint_get_param","joint","param"),&PhysicsServer::joint_get_param);
+ ClassDB::bind_method(D_METHOD("joint_set_param","joint","param","value"),&PhysicsServer::joint_set_param);
+ ClassDB::bind_method(D_METHOD("joint_get_param","joint","param"),&PhysicsServer::joint_get_param);
- ClassDB::bind_method(_MD("pin_joint_create","anchor","body_a","body_b"),&PhysicsServer::pin_joint_create,DEFVAL(RID()));
- ClassDB::bind_method(_MD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&PhysicsServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
- ClassDB::bind_method(_MD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&PhysicsServer::damped_spring_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("pin_joint_create","anchor","body_a","body_b"),&PhysicsServer::pin_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&PhysicsServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&PhysicsServer::damped_spring_joint_create,DEFVAL(RID()));
- ClassDB::bind_method(_MD("damped_string_joint_set_param","joint","param","value"),&PhysicsServer::damped_string_joint_set_param,DEFVAL(RID()));
- ClassDB::bind_method(_MD("damped_string_joint_get_param","joint","param"),&PhysicsServer::damped_string_joint_get_param);
+ ClassDB::bind_method(D_METHOD("damped_string_joint_set_param","joint","param","value"),&PhysicsServer::damped_string_joint_set_param,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("damped_string_joint_get_param","joint","param"),&PhysicsServer::damped_string_joint_get_param);
- ClassDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
+ ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
*/
- ClassDB::bind_method(_MD("free_rid","rid"),&PhysicsServer::free);
+ ClassDB::bind_method(D_METHOD("free_rid","rid"),&PhysicsServer::free);
- ClassDB::bind_method(_MD("set_active","active"),&PhysicsServer::set_active);
+ ClassDB::bind_method(D_METHOD("set_active","active"),&PhysicsServer::set_active);
- //ClassDB::bind_method(_MD("init"),&PhysicsServer::init);
- //ClassDB::bind_method(_MD("step"),&PhysicsServer::step);
- //ClassDB::bind_method(_MD("sync"),&PhysicsServer::sync);
- //ClassDB::bind_method(_MD("flush_queries"),&PhysicsServer::flush_queries);
+ //ClassDB::bind_method(D_METHOD("init"),&PhysicsServer::init);
+ //ClassDB::bind_method(D_METHOD("step"),&PhysicsServer::step);
+ //ClassDB::bind_method(D_METHOD("sync"),&PhysicsServer::sync);
+ //ClassDB::bind_method(D_METHOD("flush_queries"),&PhysicsServer::flush_queries);
- ClassDB::bind_method(_MD("get_process_info","process_info"),&PhysicsServer::get_process_info);
+ ClassDB::bind_method(D_METHOD("get_process_info","process_info"),&PhysicsServer::get_process_info);
BIND_CONSTANT( SHAPE_PLANE );
BIND_CONSTANT( SHAPE_RAY );
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 01f8ffa504..0d0619e880 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_server_types.h"
-#include "globals.h"
+#include "global_config.h"
#include "visual_server.h"
#include "audio_server.h"
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 21f7f0769f..dd22986865 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -432,6 +432,9 @@ public:
virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
virtual float gi_probe_get_energy(RID p_probe) const=0;
+ virtual void gi_probe_set_bias(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_bias(RID p_probe) const=0;
+
virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0;
virtual float gi_probe_get_propagation(RID p_probe) const=0;
@@ -519,6 +522,8 @@ public:
virtual bool has_os_feature(const String& p_feature) const=0;
+ virtual void update_dirty_resources()=0;
+
static RasterizerStorage*base_signleton;
RasterizerStorage();
virtual ~RasterizerStorage() {}
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 7dfd9822f7..c680013efa 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -307,7 +307,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
} if (GETCHAR(0)=='*' && GETCHAR(1)=='/') {
char_idx+=2;
break;
- } if (GETCHAR(0)=='\n') {
+ } else if (GETCHAR(0)=='\n') {
tk_line++;
}
@@ -3241,7 +3241,7 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
_set_error("void datatype not allowed here");
return ERR_PARSE_ERROR;
}
- if (!uniform && type<TYPE_FLOAT && type>TYPE_VEC4) {
+ if (!uniform && type<TYPE_FLOAT && type>TYPE_VEC4) { // FIXME: always false! should it be || instead?
_set_error("Invalid type for varying, only float,vec2,vec3,vec4 allowed.");
return ERR_PARSE_ERROR;
}
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 0eb3e0fc5a..d119e81a4b 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* shader_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "shader_types.h"
diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h
index 411d5790a9..b8a96af922 100644
--- a/servers/visual/shader_types.h
+++ b/servers/visual/shader_types.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* shader_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 SHADERTYPES_H
#define SHADERTYPES_H
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index f4031b711d..84cc1a968d 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_canvas.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_server_canvas.h"
#include "visual_server_global.h"
#include "visual_server_viewport.h"
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 035c48d9ef..b405bc804d 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_canvas.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUALSERVERCANVAS_H
#define VISUALSERVERCANVAS_H
diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_global.cpp
index 32b9710f42..3704192c7e 100644
--- a/servers/visual/visual_server_global.cpp
+++ b/servers/visual/visual_server_global.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_global.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_server_global.h"
RasterizerStorage *VisualServerGlobals::storage=NULL;
diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_global.h
index d413334ac4..f95aed3ffb 100644
--- a/servers/visual/visual_server_global.h
+++ b/servers/visual/visual_server_global.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_global.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUALSERVERGLOBAL_H
#define VISUALSERVERGLOBAL_H
diff --git a/servers/visual/visual_server_light_baker.cpp b/servers/visual/visual_server_light_baker.cpp
index 4956d78ab0..bdf20df618 100644
--- a/servers/visual/visual_server_light_baker.cpp
+++ b/servers/visual/visual_server_light_baker.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_light_baker.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_server_light_baker.h"
VisualServerLightBaker::VisualServerLightBaker()
diff --git a/servers/visual/visual_server_light_baker.h b/servers/visual/visual_server_light_baker.h
index 42f016f614..416c16ed3a 100644
--- a/servers/visual/visual_server_light_baker.h
+++ b/servers/visual/visual_server_light_baker.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_light_baker.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUALSERVERLIGHTBAKER_H
#define VISUALSERVERLIGHTBAKER_H
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 8f87425212..3a5ffda8f5 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "visual_server_raster.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include "default_mouse_cursor.xpm"
#include "sort.h"
#include "io/marshalls.h"
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index ad0cb664c5..7d547e1862 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -825,6 +825,9 @@ public:
BIND2(gi_probe_set_energy,RID,float)
BIND1RC(float,gi_probe_get_energy,RID)
+ BIND2(gi_probe_set_bias,RID,float)
+ BIND1RC(float,gi_probe_get_bias,RID)
+
BIND2(gi_probe_set_propagation,RID,float)
BIND1RC(float,gi_probe_get_propagation,RID)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 297413effd..e004103508 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_scene.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_server_scene.h"
#include "visual_server_global.h"
#include "os/os.h"
@@ -1556,9 +1584,11 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const
cull_count--;
SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
j--;
+ continue;
}
+
instance->transformed_aabb.project_range_in_plane(Plane(z_vec,0),min,max);
if (max>z_max)
z_max=max;
@@ -2967,7 +2997,7 @@ void VisualServerScene::_bake_gi_downscale_light(int p_idx, int p_level, const G
}
- divisor=Math::lerp(8.0,divisor,p_propagate);
+ divisor=Math::lerp((float)8.0,divisor,p_propagate);
sum[0]/=divisor;
sum[1]/=divisor;
sum[2]/=divisor;
@@ -3475,6 +3505,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
} else if (p_instance->base_type==VS::INSTANCE_MULTIMESH) {
RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base);
if (mesh.is_valid()) {
+
bool cast_shadows=false;
int sc = VSG::storage->mesh_get_surface_count(mesh);
@@ -3491,6 +3522,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
cast_shadows=true;
break;
}
+
}
if (!cast_shadows) {
@@ -3538,6 +3570,8 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
void VisualServerScene::update_dirty_instances() {
+ VSG::storage->update_dirty_resources();
+
while(_instance_update_list.first()) {
_update_dirty_instance( _instance_update_list.first()->self() );
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index f9a5dde1ac..01ad400b80 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_scene.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUALSERVERSCENE_H
#define VISUALSERVERSCENE_H
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index d2ee32f9cc..a88fb69e93 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -1,8 +1,36 @@
+/*************************************************************************/
+/* visual_server_viewport.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 "visual_server_viewport.h"
#include "visual_server_global.h"
#include "visual_server_canvas.h"
#include "visual_server_scene.h"
-#include "globals.h"
+#include "global_config.h"
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index ff4bc2601d..1cee90b803 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -1,3 +1,31 @@
+/*************************************************************************/
+/* visual_server_viewport.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan 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 VISUALSERVERVIEWPORT_H
#define VISUALSERVERVIEWPORT_H
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 1799585576..5d231d208e 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "visual_server.h"
-#include "globals.h"
+#include "global_config.h"
#include "method_bind_ext.inc"
VisualServer *VisualServer::singleton=NULL;
@@ -712,7 +712,7 @@ Error VisualServer::_surface_set_data(Array p_arrays,uint32_t p_format,uint32_t
} break;
case VS::ARRAY_BONES: {
- ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_INT_ARRAY, ERR_INVALID_PARAMETER );
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_INT_ARRAY && p_arrays[ai].get_type() != Variant::POOL_REAL_ARRAY, ERR_INVALID_PARAMETER );
PoolVector<int> array = p_arrays[ai];
@@ -1566,17 +1566,17 @@ Array VisualServer::mesh_surface_get_arrays(RID p_mesh,int p_surface) const {
void VisualServer::_bind_methods() {
- ClassDB::bind_method(_MD("texture_create"),&VisualServer::texture_create);
- ClassDB::bind_method(_MD("texture_create_from_image"),&VisualServer::texture_create_from_image,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
- //ClassDB::bind_method(_MD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
- //ClassDB::bind_method(_MD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) );
- //ClassDB::bind_method(_MD("texture_get_rect"),&VisualServer::texture_get_rect );
- ClassDB::bind_method(_MD("texture_set_flags"),&VisualServer::texture_set_flags );
- ClassDB::bind_method(_MD("texture_get_flags"),&VisualServer::texture_get_flags );
- ClassDB::bind_method(_MD("texture_get_width"),&VisualServer::texture_get_width );
- ClassDB::bind_method(_MD("texture_get_height"),&VisualServer::texture_get_height );
+ ClassDB::bind_method(D_METHOD("texture_create"),&VisualServer::texture_create);
+ ClassDB::bind_method(D_METHOD("texture_create_from_image"),&VisualServer::texture_create_from_image,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
+ //ClassDB::bind_method(D_METHOD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
+ //ClassDB::bind_method(D_METHOD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) );
+ //ClassDB::bind_method(D_METHOD("texture_get_rect"),&VisualServer::texture_get_rect );
+ ClassDB::bind_method(D_METHOD("texture_set_flags"),&VisualServer::texture_set_flags );
+ ClassDB::bind_method(D_METHOD("texture_get_flags"),&VisualServer::texture_get_flags );
+ ClassDB::bind_method(D_METHOD("texture_get_width"),&VisualServer::texture_get_width );
+ ClassDB::bind_method(D_METHOD("texture_get_height"),&VisualServer::texture_get_height );
- ClassDB::bind_method(_MD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data );
+ ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data );
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 5c835c2287..08cf34a653 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -475,6 +475,9 @@ public:
virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
virtual float gi_probe_get_energy(RID p_probe) const=0;
+ virtual void gi_probe_set_bias(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_bias(RID p_probe) const=0;
+
virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0;
virtual float gi_probe_get_propagation(RID p_probe) const=0;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 54930c1ebe..8c2a3e6af3 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -124,15 +124,15 @@ Files extracted from upstream source:
## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/
-- Version: 0.5.2
+- Version: 0.6.0
- License: BSD-3-Clause
Files extracted from upstream source:
-- `src/*` except from: .am and .in, files, extras/, `webp/extras.h`
+- `src/*` except from: .am, .rc and .in files
- AUTHORS, COPYING, PATENTS
-Important: The files `utils/bit_reader.{c,h}` have Godot-made
+Important: The files `utils/bit_reader_utils.{c,h}` have Godot-made
changes to ensure they build for Javascript/HTML5. Those
changes are marked with `// -- GODOT --` comments.
diff --git a/thirdparty/libwebp/dec/alpha.c b/thirdparty/libwebp/dec/alpha.c
deleted file mode 100644
index d88f01d8de..0000000000
--- a/thirdparty/libwebp/dec/alpha.c
+++ /dev/null
@@ -1,232 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Alpha-plane decompression.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include "./alphai.h"
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "../dsp/dsp.h"
-#include "../utils/quant_levels_dec.h"
-#include "../utils/utils.h"
-#include "../webp/format_constants.h"
-
-//------------------------------------------------------------------------------
-// ALPHDecoder object.
-
-// Allocates a new alpha decoder instance.
-static ALPHDecoder* ALPHNew(void) {
- ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
- return dec;
-}
-
-// Clears and deallocates an alpha decoder instance.
-static void ALPHDelete(ALPHDecoder* const dec) {
- if (dec != NULL) {
- VP8LDelete(dec->vp8l_dec_);
- dec->vp8l_dec_ = NULL;
- WebPSafeFree(dec);
- }
-}
-
-//------------------------------------------------------------------------------
-// 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, const VP8Io* const src_io,
- uint8_t* output) {
- int ok = 0;
- const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
- const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
- int rsrv;
- VP8Io* const io = &dec->io_;
-
- assert(data != NULL && output != NULL && src_io != NULL);
-
- VP8FiltersInit();
- dec->output_ = output;
- dec->width_ = src_io->width;
- dec->height_ = src_io->height;
- assert(dec->width_ > 0 && dec->height_ > 0);
-
- if (data_size <= ALPHA_HEADER_LEN) {
- return 0;
- }
-
- dec->method_ = (data[0] >> 0) & 0x03;
- dec->filter_ = (WEBP_FILTER_TYPE)((data[0] >> 2) & 0x03);
- dec->pre_processing_ = (data[0] >> 4) & 0x03;
- rsrv = (data[0] >> 6) & 0x03;
- 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;
- }
-
- // Copy the necessary parameters from src_io to io
- VP8InitIo(io);
- WebPInitCustomIo(NULL, io);
- io->opaque = dec;
- io->width = src_io->width;
- io->height = src_io->height;
-
- io->use_cropping = src_io->use_cropping;
- io->crop_left = src_io->crop_left;
- io->crop_right = src_io->crop_right;
- io->crop_top = src_io->crop_top;
- io->crop_bottom = src_io->crop_bottom;
- // No need to copy the scaling parameters.
-
- if (dec->method_ == ALPHA_NO_COMPRESSION) {
- const size_t alpha_decoded_size = dec->width_ * dec->height_;
- ok = (alpha_data_size >= alpha_decoded_size);
- } else {
- assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION);
- ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size);
- }
-
- return ok;
-}
-
-// 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->io_.crop_bottom;
- if (alph_dec->method_ == ALPHA_NO_COMPRESSION) {
- int y;
- const uint8_t* prev_line = dec->alpha_prev_line_;
- const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width;
- uint8_t* dst = dec->alpha_plane_ + row * width;
- assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]);
- if (alph_dec->filter_ != WEBP_FILTER_NONE) {
- assert(WebPUnfilters[alph_dec->filter_] != NULL);
- for (y = 0; y < num_rows; ++y) {
- WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width);
- prev_line = dst;
- dst += width;
- deltas += width;
- }
- } else {
- for (y = 0; y < num_rows; ++y) {
- memcpy(dst, deltas, width * sizeof(*dst));
- prev_line = dst;
- dst += width;
- deltas += width;
- }
- }
- dec->alpha_prev_line_ = prev_line;
- } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
- assert(alph_dec->vp8l_dec_ != NULL);
- if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) {
- return 0;
- }
- }
-
- if (row + num_rows >= height) {
- dec->is_alpha_decoded_ = 1;
- }
- return 1;
-}
-
-static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
- const int stride = io->width;
- const int height = io->crop_bottom;
- const uint64_t alpha_size = (uint64_t)stride * height;
- assert(dec->alpha_plane_mem_ == NULL);
- dec->alpha_plane_mem_ =
- (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_));
- if (dec->alpha_plane_mem_ == NULL) {
- return 0;
- }
- dec->alpha_plane_ = dec->alpha_plane_mem_;
- dec->alpha_prev_line_ = NULL;
- return 1;
-}
-
-void WebPDeallocateAlphaMemory(VP8Decoder* const dec) {
- assert(dec != NULL);
- WebPSafeFree(dec->alpha_plane_mem_);
- dec->alpha_plane_mem_ = NULL;
- dec->alpha_plane_ = NULL;
- ALPHDelete(dec->alph_dec_);
- dec->alph_dec_ = NULL;
-}
-
-//------------------------------------------------------------------------------
-// Main entry point.
-
-const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
- const VP8Io* const io,
- int row, int num_rows) {
- const int width = io->width;
- const int height = io->crop_bottom;
-
- assert(dec != NULL && io != NULL);
-
- if (row < 0 || num_rows <= 0 || row + num_rows > height) {
- return NULL; // sanity check.
- }
-
- if (!dec->is_alpha_decoded_) {
- if (dec->alph_dec_ == NULL) { // Initialize decoder.
- dec->alph_dec_ = ALPHNew();
- if (dec->alph_dec_ == NULL) return NULL;
- if (!AllocateAlphaPlane(dec, io)) goto Error;
- if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
- io, dec->alpha_plane_)) {
- goto Error;
- }
- // 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 - row; // decode everything in one pass
- }
- }
-
- assert(dec->alph_dec_ != NULL);
- assert(row + num_rows <= height);
- if (!ALPHDecode(dec, row, num_rows)) goto Error;
-
- if (dec->is_alpha_decoded_) { // finished?
- ALPHDelete(dec->alph_dec_);
- dec->alph_dec_ = NULL;
- if (dec->alpha_dithering_ > 0) {
- uint8_t* const alpha = dec->alpha_plane_ + io->crop_top * width
- + io->crop_left;
- if (!WebPDequantizeLevels(alpha,
- io->crop_right - io->crop_left,
- io->crop_bottom - io->crop_top,
- width, dec->alpha_dithering_)) {
- goto Error;
- }
- }
- }
- }
-
- // Return a pointer to the current decoded row.
- return dec->alpha_plane_ + row * width;
-
- Error:
- WebPDeallocateAlphaMemory(dec);
- return NULL;
-}
diff --git a/thirdparty/libwebp/dec/alpha_dec.c b/thirdparty/libwebp/dec/alpha_dec.c
new file mode 100644
index 0000000000..83ffd4b609
--- /dev/null
+++ b/thirdparty/libwebp/dec/alpha_dec.c
@@ -0,0 +1,232 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Alpha-plane decompression.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+#include "./alphai_dec.h"
+#include "./vp8i_dec.h"
+#include "./vp8li_dec.h"
+#include "../dsp/dsp.h"
+#include "../utils/quant_levels_dec_utils.h"
+#include "../utils/utils.h"
+#include "../webp/format_constants.h"
+
+//------------------------------------------------------------------------------
+// ALPHDecoder object.
+
+// Allocates a new alpha decoder instance.
+static ALPHDecoder* ALPHNew(void) {
+ ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
+ return dec;
+}
+
+// Clears and deallocates an alpha decoder instance.
+static void ALPHDelete(ALPHDecoder* const dec) {
+ if (dec != NULL) {
+ VP8LDelete(dec->vp8l_dec_);
+ dec->vp8l_dec_ = NULL;
+ WebPSafeFree(dec);
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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, const VP8Io* const src_io,
+ uint8_t* output) {
+ int ok = 0;
+ const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
+ const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
+ int rsrv;
+ VP8Io* const io = &dec->io_;
+
+ assert(data != NULL && output != NULL && src_io != NULL);
+
+ VP8FiltersInit();
+ dec->output_ = output;
+ dec->width_ = src_io->width;
+ dec->height_ = src_io->height;
+ assert(dec->width_ > 0 && dec->height_ > 0);
+
+ if (data_size <= ALPHA_HEADER_LEN) {
+ return 0;
+ }
+
+ dec->method_ = (data[0] >> 0) & 0x03;
+ dec->filter_ = (WEBP_FILTER_TYPE)((data[0] >> 2) & 0x03);
+ dec->pre_processing_ = (data[0] >> 4) & 0x03;
+ rsrv = (data[0] >> 6) & 0x03;
+ 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;
+ }
+
+ // Copy the necessary parameters from src_io to io
+ VP8InitIo(io);
+ WebPInitCustomIo(NULL, io);
+ io->opaque = dec;
+ io->width = src_io->width;
+ io->height = src_io->height;
+
+ io->use_cropping = src_io->use_cropping;
+ io->crop_left = src_io->crop_left;
+ io->crop_right = src_io->crop_right;
+ io->crop_top = src_io->crop_top;
+ io->crop_bottom = src_io->crop_bottom;
+ // No need to copy the scaling parameters.
+
+ if (dec->method_ == ALPHA_NO_COMPRESSION) {
+ const size_t alpha_decoded_size = dec->width_ * dec->height_;
+ ok = (alpha_data_size >= alpha_decoded_size);
+ } else {
+ assert(dec->method_ == ALPHA_LOSSLESS_COMPRESSION);
+ ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size);
+ }
+
+ return ok;
+}
+
+// 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->io_.crop_bottom;
+ if (alph_dec->method_ == ALPHA_NO_COMPRESSION) {
+ int y;
+ const uint8_t* prev_line = dec->alpha_prev_line_;
+ const uint8_t* deltas = dec->alpha_data_ + ALPHA_HEADER_LEN + row * width;
+ uint8_t* dst = dec->alpha_plane_ + row * width;
+ assert(deltas <= &dec->alpha_data_[dec->alpha_data_size_]);
+ if (alph_dec->filter_ != WEBP_FILTER_NONE) {
+ assert(WebPUnfilters[alph_dec->filter_] != NULL);
+ for (y = 0; y < num_rows; ++y) {
+ WebPUnfilters[alph_dec->filter_](prev_line, deltas, dst, width);
+ prev_line = dst;
+ dst += width;
+ deltas += width;
+ }
+ } else {
+ for (y = 0; y < num_rows; ++y) {
+ memcpy(dst, deltas, width * sizeof(*dst));
+ prev_line = dst;
+ dst += width;
+ deltas += width;
+ }
+ }
+ dec->alpha_prev_line_ = prev_line;
+ } else { // alph_dec->method_ == ALPHA_LOSSLESS_COMPRESSION
+ assert(alph_dec->vp8l_dec_ != NULL);
+ if (!VP8LDecodeAlphaImageStream(alph_dec, row + num_rows)) {
+ return 0;
+ }
+ }
+
+ if (row + num_rows >= height) {
+ dec->is_alpha_decoded_ = 1;
+ }
+ return 1;
+}
+
+static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
+ const int stride = io->width;
+ const int height = io->crop_bottom;
+ const uint64_t alpha_size = (uint64_t)stride * height;
+ assert(dec->alpha_plane_mem_ == NULL);
+ dec->alpha_plane_mem_ =
+ (uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_));
+ if (dec->alpha_plane_mem_ == NULL) {
+ return 0;
+ }
+ dec->alpha_plane_ = dec->alpha_plane_mem_;
+ dec->alpha_prev_line_ = NULL;
+ return 1;
+}
+
+void WebPDeallocateAlphaMemory(VP8Decoder* const dec) {
+ assert(dec != NULL);
+ WebPSafeFree(dec->alpha_plane_mem_);
+ dec->alpha_plane_mem_ = NULL;
+ dec->alpha_plane_ = NULL;
+ ALPHDelete(dec->alph_dec_);
+ dec->alph_dec_ = NULL;
+}
+
+//------------------------------------------------------------------------------
+// Main entry point.
+
+const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
+ const VP8Io* const io,
+ int row, int num_rows) {
+ const int width = io->width;
+ const int height = io->crop_bottom;
+
+ assert(dec != NULL && io != NULL);
+
+ if (row < 0 || num_rows <= 0 || row + num_rows > height) {
+ return NULL; // sanity check.
+ }
+
+ if (!dec->is_alpha_decoded_) {
+ if (dec->alph_dec_ == NULL) { // Initialize decoder.
+ dec->alph_dec_ = ALPHNew();
+ if (dec->alph_dec_ == NULL) return NULL;
+ if (!AllocateAlphaPlane(dec, io)) goto Error;
+ if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
+ io, dec->alpha_plane_)) {
+ goto Error;
+ }
+ // 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 - row; // decode everything in one pass
+ }
+ }
+
+ assert(dec->alph_dec_ != NULL);
+ assert(row + num_rows <= height);
+ if (!ALPHDecode(dec, row, num_rows)) goto Error;
+
+ if (dec->is_alpha_decoded_) { // finished?
+ ALPHDelete(dec->alph_dec_);
+ dec->alph_dec_ = NULL;
+ if (dec->alpha_dithering_ > 0) {
+ uint8_t* const alpha = dec->alpha_plane_ + io->crop_top * width
+ + io->crop_left;
+ if (!WebPDequantizeLevels(alpha,
+ io->crop_right - io->crop_left,
+ io->crop_bottom - io->crop_top,
+ width, dec->alpha_dithering_)) {
+ goto Error;
+ }
+ }
+ }
+ }
+
+ // Return a pointer to the current decoded row.
+ return dec->alpha_plane_ + row * width;
+
+ Error:
+ WebPDeallocateAlphaMemory(dec);
+ return NULL;
+}
diff --git a/thirdparty/libwebp/dec/alphai.h b/thirdparty/libwebp/dec/alphai.h
deleted file mode 100644
index 69dd7c0f5d..0000000000
--- a/thirdparty/libwebp/dec/alphai.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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.
- uint8_t* output_;
- const uint8_t* prev_line_; // last output row (or NULL)
-};
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-// Deallocate memory associated to dec->alpha_plane_ decoding
-void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_ALPHAI_H_ */
diff --git a/thirdparty/libwebp/dec/alphai_dec.h b/thirdparty/libwebp/dec/alphai_dec.h
new file mode 100644
index 0000000000..561e8151ee
--- /dev/null
+++ b/thirdparty/libwebp/dec/alphai_dec.h
@@ -0,0 +1,54 @@
+// 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_dec.h"
+#include "../utils/filters_utils.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.
+ uint8_t* output_;
+ const uint8_t* prev_line_; // last output row (or NULL)
+};
+
+//------------------------------------------------------------------------------
+// internal functions. Not public.
+
+// Deallocate memory associated to dec->alpha_plane_ decoding
+void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_ALPHAI_H_ */
diff --git a/thirdparty/libwebp/dec/buffer.c b/thirdparty/libwebp/dec/buffer.c
deleted file mode 100644
index 547e69b434..0000000000
--- a/thirdparty/libwebp/dec/buffer.c
+++ /dev/null
@@ -1,300 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Everything about WebPDecBuffer
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./vp8i.h"
-#include "./webpi.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// 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);
-}
-
-// 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;
- 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 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 &= (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 &= (a_stride >= width);
- ok &= (a_size <= buf->a_size);
- ok &= (buf->a != NULL);
- }
- } else { // RGB checks
- const WebPRGBABuffer* const buf = &buffer->u.RGBA;
- const int stride = abs(buf->stride);
- const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
- ok &= (size <= buf->size);
- 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;
- 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 <= 0 && 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 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;
- }
- 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) {
- 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 = scaled_width;
- h = scaled_height;
- }
- }
- out->width = w;
- out->height = h;
-
- // 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;
-}
-
-//------------------------------------------------------------------------------
-// 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 <= 0) {
- WebPSafeFree(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;
- }
- }
-}
-
-VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src_buf,
- WebPDecBuffer* const dst_buf) {
- assert(src_buf != NULL && dst_buf != NULL);
- assert(src_buf->colorspace == dst_buf->colorspace);
-
- dst_buf->width = src_buf->width;
- dst_buf->height = src_buf->height;
- if (CheckDecBuffer(dst_buf) != VP8_STATUS_OK) {
- return VP8_STATUS_INVALID_PARAM;
- }
- if (WebPIsRGBMode(src_buf->colorspace)) {
- const WebPRGBABuffer* const src = &src_buf->u.RGBA;
- const WebPRGBABuffer* const dst = &dst_buf->u.RGBA;
- WebPCopyPlane(src->rgba, src->stride, dst->rgba, dst->stride,
- src_buf->width * kModeBpp[src_buf->colorspace],
- src_buf->height);
- } else {
- const WebPYUVABuffer* const src = &src_buf->u.YUVA;
- const WebPYUVABuffer* const dst = &dst_buf->u.YUVA;
- WebPCopyPlane(src->y, src->y_stride, dst->y, dst->y_stride,
- src_buf->width, src_buf->height);
- WebPCopyPlane(src->u, src->u_stride, dst->u, dst->u_stride,
- (src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
- WebPCopyPlane(src->v, src->v_stride, dst->v, dst->v_stride,
- (src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
- if (WebPIsAlphaMode(src_buf->colorspace)) {
- WebPCopyPlane(src->a, src->a_stride, dst->a, dst->a_stride,
- src_buf->width, src_buf->height);
- }
- }
- return VP8_STATUS_OK;
-}
-
-int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
- const WebPBitstreamFeatures* const features) {
- assert(output != NULL);
- return (output->is_external_memory >= 2) &&
- WebPIsPremultipliedMode(output->colorspace) &&
- (features != NULL && features->has_alpha);
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/buffer_dec.c b/thirdparty/libwebp/dec/buffer_dec.c
new file mode 100644
index 0000000000..c685fd5646
--- /dev/null
+++ b/thirdparty/libwebp/dec/buffer_dec.c
@@ -0,0 +1,300 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Everything about WebPDecBuffer
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+
+#include "./vp8i_dec.h"
+#include "./webpi_dec.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+// 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);
+}
+
+// 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;
+ 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 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 &= (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 &= (a_stride >= width);
+ ok &= (a_size <= buf->a_size);
+ ok &= (buf->a != NULL);
+ }
+ } else { // RGB checks
+ const WebPRGBABuffer* const buf = &buffer->u.RGBA;
+ const int stride = abs(buf->stride);
+ const uint64_t size = MIN_BUFFER_SIZE(width, height, stride);
+ ok &= (size <= buf->size);
+ 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;
+ 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 <= 0 && 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 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;
+ }
+ 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) {
+ 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 = scaled_width;
+ h = scaled_height;
+ }
+ }
+ out->width = w;
+ out->height = h;
+
+ // 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;
+}
+
+//------------------------------------------------------------------------------
+// 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 <= 0) {
+ WebPSafeFree(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;
+ }
+ }
+}
+
+VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src_buf,
+ WebPDecBuffer* const dst_buf) {
+ assert(src_buf != NULL && dst_buf != NULL);
+ assert(src_buf->colorspace == dst_buf->colorspace);
+
+ dst_buf->width = src_buf->width;
+ dst_buf->height = src_buf->height;
+ if (CheckDecBuffer(dst_buf) != VP8_STATUS_OK) {
+ return VP8_STATUS_INVALID_PARAM;
+ }
+ if (WebPIsRGBMode(src_buf->colorspace)) {
+ const WebPRGBABuffer* const src = &src_buf->u.RGBA;
+ const WebPRGBABuffer* const dst = &dst_buf->u.RGBA;
+ WebPCopyPlane(src->rgba, src->stride, dst->rgba, dst->stride,
+ src_buf->width * kModeBpp[src_buf->colorspace],
+ src_buf->height);
+ } else {
+ const WebPYUVABuffer* const src = &src_buf->u.YUVA;
+ const WebPYUVABuffer* const dst = &dst_buf->u.YUVA;
+ WebPCopyPlane(src->y, src->y_stride, dst->y, dst->y_stride,
+ src_buf->width, src_buf->height);
+ WebPCopyPlane(src->u, src->u_stride, dst->u, dst->u_stride,
+ (src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
+ WebPCopyPlane(src->v, src->v_stride, dst->v, dst->v_stride,
+ (src_buf->width + 1) / 2, (src_buf->height + 1) / 2);
+ if (WebPIsAlphaMode(src_buf->colorspace)) {
+ WebPCopyPlane(src->a, src->a_stride, dst->a, dst->a_stride,
+ src_buf->width, src_buf->height);
+ }
+ }
+ return VP8_STATUS_OK;
+}
+
+int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
+ const WebPBitstreamFeatures* const features) {
+ assert(output != NULL);
+ return (output->is_external_memory >= 2) &&
+ WebPIsPremultipliedMode(output->colorspace) &&
+ (features != NULL && features->has_alpha);
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/common.h b/thirdparty/libwebp/dec/common_dec.h
index 6961e22470..6961e22470 100644
--- a/thirdparty/libwebp/dec/common.h
+++ b/thirdparty/libwebp/dec/common_dec.h
diff --git a/thirdparty/libwebp/dec/frame.c b/thirdparty/libwebp/dec/frame.c
deleted file mode 100644
index 22d291d2cd..0000000000
--- a/thirdparty/libwebp/dec/frame.c
+++ /dev/null
@@ -1,812 +0,0 @@
-// Copyright 2010 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.
-// -----------------------------------------------------------------------------
-//
-// Frame-reconstruction function. Memory allocation.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-#include "./vp8i.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// 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;
-}
-
-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
-
-// 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 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_;
- 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 = 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);
- }
- 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_ + 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);
- }
- 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);
- }
-}
-
-//------------------------------------------------------------------------------
-// Precompute the filtering strength for each segment and each i4x4/i16x16 mode.
-
-static void PrecomputeFilterStrengths(VP8Decoder* const dec) {
- if (dec->filter_type_ > 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;
- }
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// Dithering
-
-// minimal amp that will provide a non-zero dithering effect
-#define MIN_DITHER_AMP 4
-
-#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 (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;
- }
- }
-}
-
-// Convert to range: [-2,2] for dither=50, [-4,4] for dither=100
-static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) {
- uint8_t dither[64];
- int i;
- for (i = 0; i < 8 * 8; ++i) {
- dither[i] = VP8RandomBits2(rg, VP8_DITHER_AMP_BITS + 1, amp);
- }
- VP8DitherCombine8x8(dither, dst, bps);
-}
-
-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_);
- }
- }
-}
-
-//------------------------------------------------------------------------------
-// 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 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 = 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 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 (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;
- 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 (!is_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): testing presence of alpha with dec->alpha_data_ is not a
- // good idea.
- io->a = VP8DecompressAlphaRows(dec, io, 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 (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);
- }
- }
-
- return ok;
-}
-
-#undef MACROBLOCK_VPOS
-
-//------------------------------------------------------------------------------
-
-int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 1;
- VP8ThreadContext* const ctx = &dec->thread_ctx_;
- 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_ = filter_row;
- ReconstructRow(dec, ctx);
- ok = FinishRow(dec, io);
- } else {
- WebPWorker* const worker = &dec->worker_;
- // Finish previous job *before* updating context
- 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_ = 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;
- }
- // (reconstruct)+filter in parallel
- WebPGetWorkerInterface()->Launch(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() no matter what.
- if (io->setup != NULL && !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 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_;
- }
- }
- PrecomputeFilterStrengths(dec);
- return VP8_STATUS_OK;
-}
-
-int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) {
- int ok = 1;
- if (dec->mt_method_ > 0) {
- ok = WebPGetWorkerInterface()->Sync(&dec->worker_);
- }
-
- if (io->teardown != NULL) {
- 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->mt_method_ > 0) {
- WebPWorker* const worker = &dec->worker_;
- if (!WebPGetWorkerInterface()->Reset(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;
-}
-
-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
-
-//------------------------------------------------------------------------------
-// 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 = 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->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo)
- : 0;
- const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_);
- 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;
- // 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 + 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_) {
- WebPSafeFree(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->yuv_t_ = (VP8TopSamples*)mem;
- mem += top_size;
-
- 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->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*)WEBP_ALIGN(mem);
- assert((yuv_size & WEBP_ALIGN_CST) == 0);
- dec->yuv_b_ = (uint8_t*)mem;
- mem += yuv_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;
- {
- 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;
- assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_);
-
- // 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);
-
- 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* const 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;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/frame_dec.c b/thirdparty/libwebp/dec/frame_dec.c
new file mode 100644
index 0000000000..f91e27f7c8
--- /dev/null
+++ b/thirdparty/libwebp/dec/frame_dec.c
@@ -0,0 +1,812 @@
+// Copyright 2010 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.
+// -----------------------------------------------------------------------------
+//
+// Frame-reconstruction function. Memory allocation.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+#include "./vp8i_dec.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+// 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;
+}
+
+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
+
+// 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 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_;
+ 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 = 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);
+ }
+ 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_ + 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);
+ }
+ 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);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Precompute the filtering strength for each segment and each i4x4/i16x16 mode.
+
+static void PrecomputeFilterStrengths(VP8Decoder* const dec) {
+ if (dec->filter_type_ > 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;
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Dithering
+
+// minimal amp that will provide a non-zero dithering effect
+#define MIN_DITHER_AMP 4
+
+#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 (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;
+ }
+ }
+}
+
+// Convert to range: [-2,2] for dither=50, [-4,4] for dither=100
+static void Dither8x8(VP8Random* const rg, uint8_t* dst, int bps, int amp) {
+ uint8_t dither[64];
+ int i;
+ for (i = 0; i < 8 * 8; ++i) {
+ dither[i] = VP8RandomBits2(rg, VP8_DITHER_AMP_BITS + 1, amp);
+ }
+ VP8DitherCombine8x8(dither, dst, bps);
+}
+
+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_);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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 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 = 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 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 (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;
+ 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 (!is_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): testing presence of alpha with dec->alpha_data_ is not a
+ // good idea.
+ io->a = VP8DecompressAlphaRows(dec, io, 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 (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);
+ }
+ }
+
+ return ok;
+}
+
+#undef MACROBLOCK_VPOS
+
+//------------------------------------------------------------------------------
+
+int VP8ProcessRow(VP8Decoder* const dec, VP8Io* const io) {
+ int ok = 1;
+ VP8ThreadContext* const ctx = &dec->thread_ctx_;
+ 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_ = filter_row;
+ ReconstructRow(dec, ctx);
+ ok = FinishRow(dec, io);
+ } else {
+ WebPWorker* const worker = &dec->worker_;
+ // Finish previous job *before* updating context
+ 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_ = 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;
+ }
+ // (reconstruct)+filter in parallel
+ WebPGetWorkerInterface()->Launch(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() no matter what.
+ if (io->setup != NULL && !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 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_;
+ }
+ }
+ PrecomputeFilterStrengths(dec);
+ return VP8_STATUS_OK;
+}
+
+int VP8ExitCritical(VP8Decoder* const dec, VP8Io* const io) {
+ int ok = 1;
+ if (dec->mt_method_ > 0) {
+ ok = WebPGetWorkerInterface()->Sync(&dec->worker_);
+ }
+
+ if (io->teardown != NULL) {
+ 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->mt_method_ > 0) {
+ WebPWorker* const worker = &dec->worker_;
+ if (!WebPGetWorkerInterface()->Reset(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;
+}
+
+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
+
+//------------------------------------------------------------------------------
+// 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 = 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->mt_method_ > 0 ? 2 : 1) * sizeof(VP8FInfo)
+ : 0;
+ const size_t yuv_size = YUV_SIZE * sizeof(*dec->yuv_b_);
+ 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;
+ // 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 + 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_) {
+ WebPSafeFree(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 WebPSafeMalloc() above.
+ dec->mem_size_ = (size_t)needed;
+ }
+
+ mem = (uint8_t*)dec->mem_;
+ dec->intra_t_ = (uint8_t*)mem;
+ mem += intra_pred_mode_size;
+
+ dec->yuv_t_ = (VP8TopSamples*)mem;
+ mem += top_size;
+
+ 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->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*)WEBP_ALIGN(mem);
+ assert((yuv_size & WEBP_ALIGN_CST) == 0);
+ dec->yuv_b_ = (uint8_t*)mem;
+ mem += yuv_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;
+ {
+ 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;
+ assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_);
+
+ // 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);
+
+ 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* const 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;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/idec.c b/thirdparty/libwebp/dec/idec.c
deleted file mode 100644
index 8de131916e..0000000000
--- a/thirdparty/libwebp/dec/idec.c
+++ /dev/null
@@ -1,892 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Incremental decoding
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "./alphai.h"
-#include "./webpi.h"
-#include "./vp8i.h"
-#include "../utils/utils.h"
-
-// 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 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_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,
- 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,
- // or if the external one has slow-memory)
- WebPDecBuffer* final_output_; // Slow-memory output to copy to eventually.
- 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_;
- VP8BitReader token_br_;
-} MBContext;
-
-//------------------------------------------------------------------------------
-// MemBuffer: incoming data handling
-
-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_;
- // 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 uint32_t last_part = dec->num_parts_minus_one_;
- if (offset != 0) {
- uint32_t p;
- for (p = 0; p <= last_part; ++p) {
- 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) {
- VP8RemapBitReader(&dec->br_, offset);
- }
- }
- {
- const uint8_t* const last_start = dec->parts_[last_part].buf_;
- 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.
- }
- }
- }
- } 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) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- MemBuffer* const mem = &idec->mem_;
- 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
- // 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 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);
- WebPSafeFree(mem->buf_);
- mem->buf_ = new_buf;
- mem->buf_size_ = (size_t)extra_size;
- mem->start_ = new_mem_start;
- 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_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_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!
-
- mem->buf_ = (uint8_t*)data;
- mem->end_ = mem->buf_size_ = data_size;
-
- DoRemap(idec, mem->buf_ + mem->start_ - old_start);
- 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) {
- WebPSafeFree(mem->buf_);
- WebPSafeFree((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;
-}
-
-// 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) {
- const VP8StatusCode status = WebPFlipBuffer(output);
- if (status != VP8_STATUS_OK) return status;
- }
- if (idec->final_output_ != NULL) {
- WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy
- WebPFreeDecBuffer(&idec->output_);
- *output = *idec->final_output_;
- idec->final_output_ = NULL;
- }
- return VP8_STATUS_OK;
-}
-
-//------------------------------------------------------------------------------
-// Macroblock-decoding contexts
-
-static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br,
- MBContext* const context) {
- context->left_ = dec->mb_info_[-1];
- context->info_ = dec->mb_info_[dec->mb_x_];
- context->token_br_ = *token_br;
-}
-
-static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
- VP8BitReader* const token_br) {
- dec->mb_info_[-1] = context->left_;
- dec->mb_info_[dec->mb_x_] = context->info_;
- *token_br = context->token_br_;
-}
-
-//------------------------------------------------------------------------------
-
-static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
- if (idec->state_ == STATE_VP8_DATA) {
- VP8Io* const io = &idec->io_;
- if (io->teardown != NULL) {
- 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;
- 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.
- } 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;
- dec->alpha_data_ = headers.alpha_data;
- dec->alpha_data_size_ = headers.alpha_data_size;
- ChangeState(idec, STATE_VP8_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_);
- 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_, &width, &height)) {
- 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 VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) {
- VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
- VP8BitReader* const br = &dec->br_;
- const size_t part_size = br->buf_end_ - br->buf_;
- MemBuffer* const mem = &idec->mem_;
- assert(!idec->is_lossless_);
- assert(mem->part0_buf_ == NULL);
- // 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*)WebPSafeMalloc(1ULL, part_size);
- if (part0_buf == NULL) {
- return VP8_STATUS_OUT_OF_MEMORY;
- }
- memcpy(part0_buf, br->buf_, part_size);
- mem->part0_buf_ = part0_buf;
- VP8BitReaderSetBuffer(br, part0_buf, part_size);
- } else {
- // Else: just keep pointers to the partition #0's data in dec_->br_.
- }
- mem->start_ += part_size;
- return VP8_STATUS_OK;
-}
-
-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_);
- }
- // This change must be done before calling VP8InitFrame()
- dec->mt_method_ = VP8GetThreadMethod(params->options, NULL,
- io->width, io->height);
- VP8InitDithering(params->options, dec);
-
- 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().
- 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_) {
- 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_) {
- VP8BitReader* const token_br =
- &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_];
- MBContext context;
- SaveContext(dec, token_br, &context);
- if (!VP8DecodeMB(dec, token_br)) {
- // We shouldn't fail when MAX_MB data was available
- if (dec->num_parts_minus_one_ == 0 &&
- MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
- return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
- }
- RestoreContext(&context, dec, token_br);
- return VP8_STATUS_SUSPENDED;
- }
- // Release buffer only if there is only one partition
- if (dec->num_parts_minus_one_ == 0) {
- 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);
- }
- }
- // Synchronize the thread and check for errors.
- if (!VP8ExitCritical(dec, io)) {
- return IDecError(idec, VP8_STATUS_USER_ABORT);
- }
- dec->ready_ = 0;
- return FinishDecoding(idec);
-}
-
-static VP8StatusCode 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)) {
- 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.
- 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_);
-
- // 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_);
- }
- 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_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_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;
-}
-
-//------------------------------------------------------------------------------
-// Internal constructor
-
-static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer,
- const WebPBitstreamFeatures* const features) {
- WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec));
- if (idec == NULL) {
- return NULL;
- }
-
- 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_);
- if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) {
- idec->params_.output = &idec->output_;
- idec->final_output_ = output_buffer;
- if (output_buffer != NULL) {
- idec->params_.output->colorspace = output_buffer->colorspace;
- }
- } else {
- idec->params_.output = output_buffer;
- idec->final_output_ = NULL;
- }
- WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions.
-
- return idec;
-}
-
-//------------------------------------------------------------------------------
-// Public functions
-
-WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) {
- return NewDecoder(output_buffer, NULL);
-}
-
-WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size,
- WebPDecoderConfig* config) {
- WebPIDecoder* idec;
- WebPBitstreamFeatures tmp_features;
- WebPBitstreamFeatures* const features =
- (config == NULL) ? &tmp_features : &config->input;
- memset(&tmp_features, 0, sizeof(tmp_features));
-
- // Parse the bitstream's features, if requested:
- if (data != NULL && data_size > 0) {
- if (WebPGetFeatures(data, data_size, features) != VP8_STATUS_OK) {
- return NULL;
- }
- }
-
- // Create an instance of the incremental decoder
- idec = (config != NULL) ? NewDecoder(&config->output, features)
- : NewDecoder(NULL, features);
- 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_) {
- 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((VP8LDecoder*)idec->dec_);
- }
- }
- ClearMemBuffer(&idec->mem_);
- WebPFreeDecBuffer(&idec->output_);
- WebPSafeFree(idec);
-}
-
-//------------------------------------------------------------------------------
-// Wrapper toward WebPINewDecoder
-
-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) ? 1 : 0;
- WebPIDecoder* idec;
-
- if (mode >= MODE_YUV) return NULL;
- if (is_external_memory == 0) { // 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 = 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;
- 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) {
- const int is_external_memory = (luma != NULL) ? 1 : 0;
- WebPIDecoder* idec;
- WEBP_CSP_MODE colorspace;
-
- if (is_external_memory == 0) { // 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 = 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;
- 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;
- }
- if (idec->final_output_ != NULL) {
- return NULL; // not yet slow-copied
- }
- 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;
- if (src != NULL) {
- 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_WEBP_HEADER) {
- return 0;
- }
-
- idec->io_.put = put;
- idec->io_.setup = setup;
- idec->io_.teardown = teardown;
- idec->io_.opaque = user_data;
-
- return 1;
-}
diff --git a/thirdparty/libwebp/dec/idec_dec.c b/thirdparty/libwebp/dec/idec_dec.c
new file mode 100644
index 0000000000..78fb2e7186
--- /dev/null
+++ b/thirdparty/libwebp/dec/idec_dec.c
@@ -0,0 +1,892 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Incremental decoding
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "./alphai_dec.h"
+#include "./webpi_dec.h"
+#include "./vp8i_dec.h"
+#include "../utils/utils.h"
+
+// 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 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_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,
+ 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,
+ // or if the external one has slow-memory)
+ WebPDecBuffer* final_output_; // Slow-memory output to copy to eventually.
+ 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_;
+ VP8BitReader token_br_;
+} MBContext;
+
+//------------------------------------------------------------------------------
+// MemBuffer: incoming data handling
+
+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_;
+ // 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 uint32_t last_part = dec->num_parts_minus_one_;
+ if (offset != 0) {
+ uint32_t p;
+ for (p = 0; p <= last_part; ++p) {
+ 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) {
+ VP8RemapBitReader(&dec->br_, offset);
+ }
+ }
+ {
+ const uint8_t* const last_start = dec->parts_[last_part].buf_;
+ 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.
+ }
+ }
+ }
+ } 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) {
+ VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ MemBuffer* const mem = &idec->mem_;
+ 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
+ // 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 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);
+ WebPSafeFree(mem->buf_);
+ mem->buf_ = new_buf;
+ mem->buf_size_ = (size_t)extra_size;
+ mem->start_ = new_mem_start;
+ 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_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_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!
+
+ mem->buf_ = (uint8_t*)data;
+ mem->end_ = mem->buf_size_ = data_size;
+
+ DoRemap(idec, mem->buf_ + mem->start_ - old_start);
+ 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) {
+ WebPSafeFree(mem->buf_);
+ WebPSafeFree((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;
+}
+
+// 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) {
+ const VP8StatusCode status = WebPFlipBuffer(output);
+ if (status != VP8_STATUS_OK) return status;
+ }
+ if (idec->final_output_ != NULL) {
+ WebPCopyDecBufferPixels(output, idec->final_output_); // do the slow-copy
+ WebPFreeDecBuffer(&idec->output_);
+ *output = *idec->final_output_;
+ idec->final_output_ = NULL;
+ }
+ return VP8_STATUS_OK;
+}
+
+//------------------------------------------------------------------------------
+// Macroblock-decoding contexts
+
+static void SaveContext(const VP8Decoder* dec, const VP8BitReader* token_br,
+ MBContext* const context) {
+ context->left_ = dec->mb_info_[-1];
+ context->info_ = dec->mb_info_[dec->mb_x_];
+ context->token_br_ = *token_br;
+}
+
+static void RestoreContext(const MBContext* context, VP8Decoder* const dec,
+ VP8BitReader* const token_br) {
+ dec->mb_info_[-1] = context->left_;
+ dec->mb_info_[dec->mb_x_] = context->info_;
+ *token_br = context->token_br_;
+}
+
+//------------------------------------------------------------------------------
+
+static VP8StatusCode IDecError(WebPIDecoder* const idec, VP8StatusCode error) {
+ if (idec->state_ == STATE_VP8_DATA) {
+ VP8Io* const io = &idec->io_;
+ if (io->teardown != NULL) {
+ 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;
+ 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.
+ } 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;
+ dec->alpha_data_ = headers.alpha_data;
+ dec->alpha_data_size_ = headers.alpha_data_size;
+ ChangeState(idec, STATE_VP8_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_);
+ 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_, &width, &height)) {
+ 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 VP8StatusCode CopyParts0Data(WebPIDecoder* const idec) {
+ VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
+ VP8BitReader* const br = &dec->br_;
+ const size_t part_size = br->buf_end_ - br->buf_;
+ MemBuffer* const mem = &idec->mem_;
+ assert(!idec->is_lossless_);
+ assert(mem->part0_buf_ == NULL);
+ // 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*)WebPSafeMalloc(1ULL, part_size);
+ if (part0_buf == NULL) {
+ return VP8_STATUS_OUT_OF_MEMORY;
+ }
+ memcpy(part0_buf, br->buf_, part_size);
+ mem->part0_buf_ = part0_buf;
+ VP8BitReaderSetBuffer(br, part0_buf, part_size);
+ } else {
+ // Else: just keep pointers to the partition #0's data in dec_->br_.
+ }
+ mem->start_ += part_size;
+ return VP8_STATUS_OK;
+}
+
+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_);
+ }
+ // This change must be done before calling VP8InitFrame()
+ dec->mt_method_ = VP8GetThreadMethod(params->options, NULL,
+ io->width, io->height);
+ VP8InitDithering(params->options, dec);
+
+ 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().
+ 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_) {
+ 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_) {
+ VP8BitReader* const token_br =
+ &dec->parts_[dec->mb_y_ & dec->num_parts_minus_one_];
+ MBContext context;
+ SaveContext(dec, token_br, &context);
+ if (!VP8DecodeMB(dec, token_br)) {
+ // We shouldn't fail when MAX_MB data was available
+ if (dec->num_parts_minus_one_ == 0 &&
+ MemDataSize(&idec->mem_) > MAX_MB_SIZE) {
+ return IDecError(idec, VP8_STATUS_BITSTREAM_ERROR);
+ }
+ RestoreContext(&context, dec, token_br);
+ return VP8_STATUS_SUSPENDED;
+ }
+ // Release buffer only if there is only one partition
+ if (dec->num_parts_minus_one_ == 0) {
+ 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);
+ }
+ }
+ // Synchronize the thread and check for errors.
+ if (!VP8ExitCritical(dec, io)) {
+ return IDecError(idec, VP8_STATUS_USER_ABORT);
+ }
+ dec->ready_ = 0;
+ return FinishDecoding(idec);
+}
+
+static VP8StatusCode 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)) {
+ 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.
+ 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_);
+
+ // 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_);
+ }
+ 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_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_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;
+}
+
+//------------------------------------------------------------------------------
+// Internal constructor
+
+static WebPIDecoder* NewDecoder(WebPDecBuffer* const output_buffer,
+ const WebPBitstreamFeatures* const features) {
+ WebPIDecoder* idec = (WebPIDecoder*)WebPSafeCalloc(1ULL, sizeof(*idec));
+ if (idec == NULL) {
+ return NULL;
+ }
+
+ 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_);
+ if (output_buffer == NULL || WebPAvoidSlowMemory(output_buffer, features)) {
+ idec->params_.output = &idec->output_;
+ idec->final_output_ = output_buffer;
+ if (output_buffer != NULL) {
+ idec->params_.output->colorspace = output_buffer->colorspace;
+ }
+ } else {
+ idec->params_.output = output_buffer;
+ idec->final_output_ = NULL;
+ }
+ WebPInitCustomIo(&idec->params_, &idec->io_); // Plug the I/O functions.
+
+ return idec;
+}
+
+//------------------------------------------------------------------------------
+// Public functions
+
+WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer) {
+ return NewDecoder(output_buffer, NULL);
+}
+
+WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size,
+ WebPDecoderConfig* config) {
+ WebPIDecoder* idec;
+ WebPBitstreamFeatures tmp_features;
+ WebPBitstreamFeatures* const features =
+ (config == NULL) ? &tmp_features : &config->input;
+ memset(&tmp_features, 0, sizeof(tmp_features));
+
+ // Parse the bitstream's features, if requested:
+ if (data != NULL && data_size > 0) {
+ if (WebPGetFeatures(data, data_size, features) != VP8_STATUS_OK) {
+ return NULL;
+ }
+ }
+
+ // Create an instance of the incremental decoder
+ idec = (config != NULL) ? NewDecoder(&config->output, features)
+ : NewDecoder(NULL, features);
+ 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_) {
+ 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((VP8LDecoder*)idec->dec_);
+ }
+ }
+ ClearMemBuffer(&idec->mem_);
+ WebPFreeDecBuffer(&idec->output_);
+ WebPSafeFree(idec);
+}
+
+//------------------------------------------------------------------------------
+// Wrapper toward WebPINewDecoder
+
+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) ? 1 : 0;
+ WebPIDecoder* idec;
+
+ if (mode >= MODE_YUV) return NULL;
+ if (is_external_memory == 0) { // 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 = 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;
+ 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) {
+ const int is_external_memory = (luma != NULL) ? 1 : 0;
+ WebPIDecoder* idec;
+ WEBP_CSP_MODE colorspace;
+
+ if (is_external_memory == 0) { // 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 = 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;
+ 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;
+ }
+ if (idec->final_output_ != NULL) {
+ return NULL; // not yet slow-copied
+ }
+ 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;
+ if (src != NULL) {
+ 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_WEBP_HEADER) {
+ return 0;
+ }
+
+ idec->io_.put = put;
+ idec->io_.setup = setup;
+ idec->io_.teardown = teardown;
+ idec->io_.opaque = user_data;
+
+ return 1;
+}
diff --git a/thirdparty/libwebp/dec/io.c b/thirdparty/libwebp/dec/io.c
deleted file mode 100644
index 8d5c43f325..0000000000
--- a/thirdparty/libwebp/dec/io.c
+++ /dev/null
@@ -1,624 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// 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* 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;
-}
-
-//------------------------------------------------------------------------------
-// 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(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,
- 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 void FillAlphaPlane(uint8_t* dst, int w, int h, int stride) {
- int j;
- for (j = 0; j < h; ++j) {
- memset(dst, 0xff, w * sizeof(*dst));
- dst += stride;
- }
-}
-
-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));
- alpha += io->width;
- dst += buf->a_stride;
- }
- } else if (buf->a != NULL) {
- // the user requested alpha, but there is none, set it to opaque.
- FillAlphaPlane(dst, mb_w, mb_h, 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,
- int expected_num_lines_out) {
- 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* 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);
- }
- }
- return 0;
-}
-
-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;
- 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;
-#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).
- 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;
- }
- (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);
- }
- }
- 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;
- 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,
- int expected_num_lines_out) {
- const WebPYUVABuffer* const buf = &p->output->u.YUVA;
- if (io->a != NULL) {
- 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);
- }
- } else if (buf->a != NULL) {
- // the user requested alpha, but there is none, set it to opaque.
- assert(p->last_y + expected_num_lines_out <= io->scaled_height);
- FillAlphaPlane(buf->a + p->last_y * buf->a_stride,
- io->scaled_width, expected_num_lines_out, buf->a_stride);
- }
- 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;
- rescaler_t* work;
-
- tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
- if (has_alpha) {
- tmp_size += work_size * sizeof(*work);
- }
- p->memory = WebPSafeMalloc(1ULL, tmp_size);
- if (p->memory == NULL) {
- return 0; // memory error
- }
- 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,
- work);
- WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
- buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
- 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,
- 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,
- work + work_size + 2 * uv_work_size);
- p->emit_alpha = EmitRescaledAlphaYUV;
- WebPInitAlphaProcessing();
- }
- 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 + 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(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);
- j += y_lines_in;
- 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, int max_lines_out) {
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- 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 non_opaque = 0;
- const int width = p->scaler_a.dst_width;
-
- while (WebPRescalerHasPendingOutput(&p->scaler_a) &&
- num_lines_out < max_lines_out) {
- assert(y_pos + num_lines_out < p->output->height);
- WebPRescalerExportRow(&p->scaler_a);
- non_opaque |= WebPDispatchAlpha(p->scaler_a.dst, 0, width, 1, dst, 0);
- dst += buf->stride;
- ++num_lines_out;
- }
- 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,
- int max_lines_out) {
- const WebPRGBABuffer* const buf = &p->output->u.RGBA;
- 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) &&
- num_lines_out < max_lines_out) {
- int i;
- 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).
- 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,
- int expected_num_out_lines) {
- if (io->a != NULL) {
- WebPRescaler* const scaler = &p->scaler_a;
- 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;
-}
-
-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
- rescaler_t* work; // rescalers work area
- uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
- size_t tmp_size1, tmp_size2, total_size;
-
- tmp_size1 = 3 * work_size;
- tmp_size2 = 3 * out_width;
- if (has_alpha) {
- tmp_size1 += work_size;
- tmp_size2 += out_width;
- }
- 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 = (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,
- work + 0 * work_size);
- WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
- tmp + 1 * out_width, out_width, out_height, 0, 1,
- work + 1 * work_size);
- WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height,
- tmp + 2 * out_width, out_width, out_height, 0, 1,
- 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,
- 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;
- }
- WebPInitAlphaProcessing();
- }
- 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 (is_alpha && WebPIsPremultipliedMode(colorspace)) {
- WebPInitUpsamplers();
- }
- 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) {
- WebPInitSamplers();
- p->emit = EmitSampledRGB; // default
- if (io->fancy_upsampling) {
-#ifdef FANCY_UPSAMPLING
- const int uv_width = (io->mb_w + 1) >> 1;
- p->memory = WebPSafeMalloc(1ULL, (size_t)(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
- p->emit_alpha =
- (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
- EmitAlphaRGBA4444
- : is_rgb ? EmitAlphaRGB
- : EmitAlphaYUV;
- if (is_rgb) {
- WebPInitAlphaProcessing();
- }
- }
- }
-
- 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 != NULL) {
- p->emit_alpha(io, p, num_lines_out);
- }
- p->last_y += num_lines_out;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-
-static void CustomTeardown(const VP8Io* io) {
- WebPDecParams* const p = (WebPDecParams*)io->opaque;
- WebPSafeFree(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;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/io_dec.c b/thirdparty/libwebp/dec/io_dec.c
new file mode 100644
index 0000000000..8bfab86959
--- /dev/null
+++ b/thirdparty/libwebp/dec/io_dec.c
@@ -0,0 +1,645 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// functions for sample output.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include "../dec/vp8i_dec.h"
+#include "./webpi_dec.h"
+#include "../dsp/dsp.h"
+#include "../dsp/yuv.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+// 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* 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;
+}
+
+//------------------------------------------------------------------------------
+// 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(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,
+ 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 void FillAlphaPlane(uint8_t* dst, int w, int h, int stride) {
+ int j;
+ for (j = 0; j < h; ++j) {
+ memset(dst, 0xff, w * sizeof(*dst));
+ dst += stride;
+ }
+}
+
+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));
+ alpha += io->width;
+ dst += buf->a_stride;
+ }
+ } else if (buf->a != NULL) {
+ // the user requested alpha, but there is none, set it to opaque.
+ FillAlphaPlane(dst, mb_w, mb_h, 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,
+ int expected_num_lines_out) {
+ 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* 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);
+ }
+ }
+ return 0;
+}
+
+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;
+ 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;
+#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).
+ 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;
+ }
+ (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);
+ }
+ }
+ 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;
+ 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,
+ int expected_num_lines_out) {
+ const WebPYUVABuffer* const buf = &p->output->u.YUVA;
+ uint8_t* const dst_a = buf->a + p->last_y * buf->a_stride;
+ if (io->a != NULL) {
+ uint8_t* const dst_y = buf->y + p->last_y * buf->y_stride;
+ const int num_lines_out = Rescale(io->a, io->width, io->mb_h, p->scaler_a);
+ assert(expected_num_lines_out == num_lines_out);
+ if (num_lines_out > 0) { // unmultiply the Y
+ WebPMultRows(dst_y, buf->y_stride, dst_a, buf->a_stride,
+ p->scaler_a->dst_width, num_lines_out, 1);
+ }
+ } else if (buf->a != NULL) {
+ // the user requested alpha, but there is none, set it to opaque.
+ assert(p->last_y + expected_num_lines_out <= io->scaled_height);
+ FillAlphaPlane(dst_a, io->scaled_width, expected_num_lines_out,
+ buf->a_stride);
+ }
+ 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, rescaler_size;
+ rescaler_t* work;
+ WebPRescaler* scalers;
+ const int num_rescalers = has_alpha ? 4 : 3;
+
+ tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work);
+ if (has_alpha) {
+ tmp_size += work_size * sizeof(*work);
+ }
+ rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
+
+ p->memory = WebPSafeMalloc(1ULL, tmp_size + rescaler_size);
+ if (p->memory == NULL) {
+ return 0; // memory error
+ }
+ work = (rescaler_t*)p->memory;
+
+ scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + tmp_size);
+ p->scaler_y = &scalers[0];
+ p->scaler_u = &scalers[1];
+ p->scaler_v = &scalers[2];
+ p->scaler_a = has_alpha ? &scalers[3] : NULL;
+
+ WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
+ buf->y, out_width, out_height, buf->y_stride, 1,
+ work);
+ WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
+ buf->u, uv_out_width, uv_out_height, buf->u_stride, 1,
+ 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,
+ 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,
+ work + work_size + 2 * uv_work_size);
+ p->emit_alpha = EmitRescaledAlphaYUV;
+ WebPInitAlphaProcessing();
+ }
+ 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 + 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(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);
+ j += y_lines_in;
+ 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, int max_lines_out) {
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ 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 non_opaque = 0;
+ const int width = p->scaler_a->dst_width;
+
+ while (WebPRescalerHasPendingOutput(p->scaler_a) &&
+ num_lines_out < max_lines_out) {
+ assert(y_pos + num_lines_out < p->output->height);
+ WebPRescalerExportRow(p->scaler_a);
+ non_opaque |= WebPDispatchAlpha(p->scaler_a->dst, 0, width, 1, dst, 0);
+ dst += buf->stride;
+ ++num_lines_out;
+ }
+ 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,
+ int max_lines_out) {
+ const WebPRGBABuffer* const buf = &p->output->u.RGBA;
+ 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) &&
+ num_lines_out < max_lines_out) {
+ int i;
+ 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).
+ 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,
+ int expected_num_out_lines) {
+ if (io->a != NULL) {
+ WebPRescaler* const scaler = p->scaler_a;
+ 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;
+}
+
+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
+ rescaler_t* work; // rescalers work area
+ uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
+ size_t tmp_size1, tmp_size2, total_size, rescaler_size;
+ WebPRescaler* scalers;
+ const int num_rescalers = has_alpha ? 4 : 3;
+
+ tmp_size1 = 3 * work_size;
+ tmp_size2 = 3 * out_width;
+ if (has_alpha) {
+ tmp_size1 += work_size;
+ tmp_size2 += out_width;
+ }
+ total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp);
+ rescaler_size = num_rescalers * sizeof(*p->scaler_y) + WEBP_ALIGN_CST;
+
+ p->memory = WebPSafeMalloc(1ULL, total_size + rescaler_size);
+ if (p->memory == NULL) {
+ return 0; // memory error
+ }
+ work = (rescaler_t*)p->memory;
+ tmp = (uint8_t*)(work + tmp_size1);
+
+ scalers = (WebPRescaler*)WEBP_ALIGN((const uint8_t*)work + total_size);
+ p->scaler_y = &scalers[0];
+ p->scaler_u = &scalers[1];
+ p->scaler_v = &scalers[2];
+ p->scaler_a = has_alpha ? &scalers[3] : NULL;
+
+ WebPRescalerInit(p->scaler_y, io->mb_w, io->mb_h,
+ tmp + 0 * out_width, out_width, out_height, 0, 1,
+ work + 0 * work_size);
+ WebPRescalerInit(p->scaler_u, uv_in_width, uv_in_height,
+ tmp + 1 * out_width, out_width, out_height, 0, 1,
+ work + 1 * work_size);
+ WebPRescalerInit(p->scaler_v, uv_in_width, uv_in_height,
+ tmp + 2 * out_width, out_width, out_height, 0, 1,
+ 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,
+ 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;
+ }
+ WebPInitAlphaProcessing();
+ }
+ 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 (is_alpha && WebPIsPremultipliedMode(colorspace)) {
+ WebPInitUpsamplers();
+ }
+ 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) {
+ WebPInitSamplers();
+ p->emit = EmitSampledRGB; // default
+ if (io->fancy_upsampling) {
+#ifdef FANCY_UPSAMPLING
+ const int uv_width = (io->mb_w + 1) >> 1;
+ p->memory = WebPSafeMalloc(1ULL, (size_t)(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
+ p->emit_alpha =
+ (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ?
+ EmitAlphaRGBA4444
+ : is_rgb ? EmitAlphaRGB
+ : EmitAlphaYUV;
+ if (is_rgb) {
+ WebPInitAlphaProcessing();
+ }
+ }
+ }
+
+ 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 != NULL) {
+ p->emit_alpha(io, p, num_lines_out);
+ }
+ p->last_y += num_lines_out;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+static void CustomTeardown(const VP8Io* io) {
+ WebPDecParams* const p = (WebPDecParams*)io->opaque;
+ WebPSafeFree(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;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/quant.c b/thirdparty/libwebp/dec/quant.c
deleted file mode 100644
index 5b648f942c..0000000000
--- a/thirdparty/libwebp/dec/quant.c
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2010 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.
-// -----------------------------------------------------------------------------
-//
-// Quantizer initialization
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./vp8i.h"
-
-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)];
-
- m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation
- }
- }
-}
-
-//------------------------------------------------------------------------------
-
diff --git a/thirdparty/libwebp/dec/quant_dec.c b/thirdparty/libwebp/dec/quant_dec.c
new file mode 100644
index 0000000000..14e3198946
--- /dev/null
+++ b/thirdparty/libwebp/dec/quant_dec.c
@@ -0,0 +1,110 @@
+// Copyright 2010 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.
+// -----------------------------------------------------------------------------
+//
+// Quantizer initialization
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./vp8i_dec.h"
+
+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)];
+
+ m->uv_quant_ = q + dquv_ac; // for dithering strength evaluation
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
diff --git a/thirdparty/libwebp/dec/tree.c b/thirdparty/libwebp/dec/tree.c
deleted file mode 100644
index c2007ea733..0000000000
--- a/thirdparty/libwebp/dec/tree.c
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright 2010 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.
-// -----------------------------------------------------------------------------
-//
-// Coding trees and probas
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./vp8i.h"
-#include "../utils/bit_reader_inl.h"
-
-#define USE_GENERIC_TREE
-
-#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
-
-//------------------------------------------------------------------------------
-// Default probabilities
-
-// Paragraph 13.5
-static const uint8_t
- CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- { { { 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_));
- // proba->bands_[][] is initialized later
-}
-
-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_;
- 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);
- block->imodes_[0] = ymode;
- memset(top, ymode, 4 * sizeof(*top));
- memset(left, ymode, 4 * sizeof(*left));
- } else {
- uint8_t* modes = block->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 = kYModesIntra4[VP8GetBit(br, prob[0])];
- while (i > 0) {
- i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
- }
- 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;
- }
- memcpy(modes, top, 4 * sizeof(*top));
- modes += 4;
- left[y] = ymode;
- }
- }
- // Hardcoded UVMode decision tree
- 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_;
-}
-
-//------------------------------------------------------------------------------
-// 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 }
- }
- }
-};
-
-// 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
-};
-
-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) {
- 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);
- }
-}
-
diff --git a/thirdparty/libwebp/dec/tree_dec.c b/thirdparty/libwebp/dec/tree_dec.c
new file mode 100644
index 0000000000..9e805f60f3
--- /dev/null
+++ b/thirdparty/libwebp/dec/tree_dec.c
@@ -0,0 +1,528 @@
+// Copyright 2010 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.
+// -----------------------------------------------------------------------------
+//
+// Coding trees and probas
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./vp8i_dec.h"
+#include "../utils/bit_reader_inl_utils.h"
+
+#if !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__)
+// using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then.
+#define USE_GENERIC_TREE
+#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
+
+//------------------------------------------------------------------------------
+// Default probabilities
+
+// Paragraph 13.5
+static const uint8_t
+ CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
+ { { { 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_));
+ // proba->bands_[][] is initialized later
+}
+
+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_;
+ 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);
+ block->imodes_[0] = ymode;
+ memset(top, ymode, 4 * sizeof(*top));
+ memset(left, ymode, 4 * sizeof(*left));
+ } else {
+ uint8_t* modes = block->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 = kYModesIntra4[VP8GetBit(br, prob[0])];
+ while (i > 0) {
+ i = kYModesIntra4[2 * i + VP8GetBit(br, prob[i])];
+ }
+ 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;
+ }
+ memcpy(modes, top, 4 * sizeof(*top));
+ modes += 4;
+ left[y] = ymode;
+ }
+ }
+ // Hardcoded UVMode decision tree
+ 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_;
+}
+
+//------------------------------------------------------------------------------
+// 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 }
+ }
+ }
+};
+
+// 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
+};
+
+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) {
+ 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);
+ }
+}
+
diff --git a/thirdparty/libwebp/dec/vp8.c b/thirdparty/libwebp/dec/vp8.c
deleted file mode 100644
index 336680c38c..0000000000
--- a/thirdparty/libwebp/dec/vp8.c
+++ /dev/null
@@ -1,667 +0,0 @@
-// Copyright 2010 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.
-// -----------------------------------------------------------------------------
-//
-// main entry for the decoder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <stdlib.h>
-
-#include "./alphai.h"
-#include "./vp8i.h"
-#include "./vp8li.h"
-#include "./webpi.h"
-#include "../utils/bit_reader_inl.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-
-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*)WebPSafeCalloc(1ULL, sizeof(*dec));
- if (dec != NULL) {
- SetOk(dec);
- WebPGetWorkerInterface()->Init(&dec->worker_);
- dec->ready_ = 0;
- dec->num_parts_minus_one_ = 0;
- }
- 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);
- WebPSafeFree(dec);
- }
-}
-
-int VP8SetError(VP8Decoder* const dec,
- VP8StatusCode error, const char* const msg) {
- // The oldest error reported takes precedence over the new one.
- 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 (w == 0 || h == 0) {
- return 0; // We don't support both width and height to be zero.
- }
-
- 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;
- size_t size_left = size;
- size_t last_part;
- size_t p;
-
- dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1;
- last_part = dec->num_parts_minus_one_;
- 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) {
- 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, size_left);
- 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;
- 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;
-
- if (dec == NULL) {
- return 0;
- }
- SetOk(dec);
- if (io == NULL) {
- return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
- "null VP8Io passed to VP8GetHeaders()");
- }
- buf = io->data;
- buf_size = io->data_size;
- 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_;
- // IMPORTANT! use some sane dimensions in crop_* and scaled_* fields.
- // So they can be used interchangeably without always testing for
- // 'use_cropping'.
- io->use_cropping = 0;
- io->crop_top = 0;
- io->crop_left = 0;
- io->crop_right = io->width;
- io->crop_bottom = io->height;
- io->use_scaling = 0;
- io->scaled_width = io->width;
- io->scaled_height = io->height;
-
- io->mb_w = io->width; // sanity check
- io->mb_h = io->height; // ditto
-
- VP8ResetProba(&dec->proba_);
- ResetSegmentHeader(&dec->segment_hdr_);
- }
-
- // 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, 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_) {
- return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
- "Not a key frame.");
- }
-
- VP8Get(br); // ignore the value of update_proba_
-
- VP8ParseProba(br, dec);
-
- // sanitized state
- dec->ready_ = 1;
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Residual decoding (Paragraph 13.2 / 13.3)
-
-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
-};
-
-// 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
-static int GetCoeffs(VP8BitReader* const br, const VP8BandProbas* const prob[],
- int ctx, const quant_t dq, int n, int16_t* out) {
- 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])) {
- v = 1;
- p = p_ctx[1];
- } else {
- v = GetLargeValue(br, p);
- p = p_ctx[2];
- }
- out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
- }
- }
- return 16;
-}
-
-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;
- 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;
-
- memset(dst, 0, 384 * sizeof(*dst));
- if (!block->is_i4x4_) { // parse DC
- int16_t dc[16] = { 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_proba = bands[0];
- } else {
- first = 0;
- ac_proba = bands[3];
- }
-
- tnz = mb->nz_ & 0x0f;
- lnz = left_mb->nz_ & 0x0f;
- for (y = 0; y < 4; ++y) {
- int l = lnz & 1;
- uint32_t nz_coeffs = 0;
- for (x = 0; x < 4; ++x) {
- 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;
- }
- tnz >>= 4;
- lnz = (lnz >> 1) | (l << 7);
- non_zero_y = (non_zero_y << 8) | nz_coeffs;
- }
- out_t_nz = tnz;
- out_l_nz = lnz >> 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 & 1;
- for (x = 0; x < 2; ++x) {
- 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;
- }
- tnz >>= 2;
- lnz = (lnz >> 1) | (l << 5);
- }
- // 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;
- }
- mb->nz_ = out_t_nz;
- left_mb->nz_ = out_l_nz;
-
- 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
-}
-
-//------------------------------------------------------------------------------
-// Main loop
-
-int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
- VP8MB* const left = dec->mb_info_ - 1;
- 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;
-
- if (!skip) {
- skip = ParseResiduals(dec, mb, token_br);
- } else {
- left->nz_ = mb->nz_ = 0;
- if (!block->is_i4x4_) {
- left->nz_dc_ = mb->nz_dc_ = 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_;
-}
-
-void VP8InitScanline(VP8Decoder* const dec) {
- VP8MB* const left = dec->mb_info_ - 1;
- left->nz_ = 0;
- left->nz_dc_ = 0;
- memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
- 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_minus_one_];
- 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.");
- }
- }
- 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->mt_method_ > 0) {
- if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0;
- }
-
- 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;
- }
- WebPGetWorkerInterface()->End(&dec->worker_);
- WebPDeallocateAlphaMemory(dec);
- WebPSafeFree(dec->mem_);
- dec->mem_ = NULL;
- dec->mem_size_ = 0;
- memset(&dec->br_, 0, sizeof(dec->br_));
- dec->ready_ = 0;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/vp8_dec.c b/thirdparty/libwebp/dec/vp8_dec.c
new file mode 100644
index 0000000000..fad8d9cf35
--- /dev/null
+++ b/thirdparty/libwebp/dec/vp8_dec.c
@@ -0,0 +1,721 @@
+// Copyright 2010 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.
+// -----------------------------------------------------------------------------
+//
+// main entry for the decoder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+
+#include "./alphai_dec.h"
+#include "./vp8i_dec.h"
+#include "./vp8li_dec.h"
+#include "./webpi_dec.h"
+#include "../utils/bit_reader_inl_utils.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+
+int WebPGetDecoderVersion(void) {
+ return (DEC_MAJ_VERSION << 16) | (DEC_MIN_VERSION << 8) | DEC_REV_VERSION;
+}
+
+//------------------------------------------------------------------------------
+// Signature and pointer-to-function for GetCoeffs() variants below.
+
+typedef int (*GetCoeffsFunc)(VP8BitReader* const br,
+ const VP8BandProbas* const prob[],
+ int ctx, const quant_t dq, int n, int16_t* out);
+static volatile GetCoeffsFunc GetCoeffs = NULL;
+
+static void InitGetCoeffs(void);
+
+//------------------------------------------------------------------------------
+// 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*)WebPSafeCalloc(1ULL, sizeof(*dec));
+ if (dec != NULL) {
+ SetOk(dec);
+ WebPGetWorkerInterface()->Init(&dec->worker_);
+ dec->ready_ = 0;
+ dec->num_parts_minus_one_ = 0;
+ InitGetCoeffs();
+ }
+ 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);
+ WebPSafeFree(dec);
+ }
+}
+
+int VP8SetError(VP8Decoder* const dec,
+ VP8StatusCode error, const char* const msg) {
+ // The oldest error reported takes precedence over the new one.
+ 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 (w == 0 || h == 0) {
+ return 0; // We don't support both width and height to be zero.
+ }
+
+ 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;
+ size_t size_left = size;
+ size_t last_part;
+ size_t p;
+
+ dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1;
+ last_part = dec->num_parts_minus_one_;
+ 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) {
+ 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, size_left);
+ 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;
+ 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;
+
+ if (dec == NULL) {
+ return 0;
+ }
+ SetOk(dec);
+ if (io == NULL) {
+ return VP8SetError(dec, VP8_STATUS_INVALID_PARAM,
+ "null VP8Io passed to VP8GetHeaders()");
+ }
+ buf = io->data;
+ buf_size = io->data_size;
+ 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_;
+ // IMPORTANT! use some sane dimensions in crop_* and scaled_* fields.
+ // So they can be used interchangeably without always testing for
+ // 'use_cropping'.
+ io->use_cropping = 0;
+ io->crop_top = 0;
+ io->crop_left = 0;
+ io->crop_right = io->width;
+ io->crop_bottom = io->height;
+ io->use_scaling = 0;
+ io->scaled_width = io->width;
+ io->scaled_height = io->height;
+
+ io->mb_w = io->width; // sanity check
+ io->mb_h = io->height; // ditto
+
+ VP8ResetProba(&dec->proba_);
+ ResetSegmentHeader(&dec->segment_hdr_);
+ }
+
+ // 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, 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_) {
+ return VP8SetError(dec, VP8_STATUS_UNSUPPORTED_FEATURE,
+ "Not a key frame.");
+ }
+
+ VP8Get(br); // ignore the value of update_proba_
+
+ VP8ParseProba(br, dec);
+
+ // sanitized state
+ dec->ready_ = 1;
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Residual decoding (Paragraph 13.2 / 13.3)
+
+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
+};
+
+// 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
+static int GetCoeffsFast(VP8BitReader* const br,
+ const VP8BandProbas* const prob[],
+ int ctx, const quant_t dq, int n, int16_t* out) {
+ 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])) {
+ v = 1;
+ p = p_ctx[1];
+ } else {
+ v = GetLargeValue(br, p);
+ p = p_ctx[2];
+ }
+ out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
+ }
+ }
+ return 16;
+}
+
+// This version of GetCoeffs() uses VP8GetBitAlt() which is an alternate version
+// of VP8GetBitAlt() targeting specific platforms.
+static int GetCoeffsAlt(VP8BitReader* const br,
+ const VP8BandProbas* const prob[],
+ int ctx, const quant_t dq, int n, int16_t* out) {
+ const uint8_t* p = prob[n]->probas_[ctx];
+ for (; n < 16; ++n) {
+ if (!VP8GetBitAlt(br, p[0])) {
+ return n; // previous coeff was last non-zero coeff
+ }
+ while (!VP8GetBitAlt(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 (!VP8GetBitAlt(br, p[2])) {
+ v = 1;
+ p = p_ctx[1];
+ } else {
+ v = GetLargeValue(br, p);
+ p = p_ctx[2];
+ }
+ out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0];
+ }
+ }
+ return 16;
+}
+
+WEBP_TSAN_IGNORE_FUNCTION static void InitGetCoeffs(void) {
+ if (GetCoeffs == NULL) {
+ if (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kSlowSSSE3)) {
+ GetCoeffs = GetCoeffsAlt;
+ } else {
+ GetCoeffs = GetCoeffsFast;
+ }
+ }
+}
+
+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;
+ 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;
+
+ memset(dst, 0, 384 * sizeof(*dst));
+ if (!block->is_i4x4_) { // parse DC
+ int16_t dc[16] = { 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_proba = bands[0];
+ } else {
+ first = 0;
+ ac_proba = bands[3];
+ }
+
+ tnz = mb->nz_ & 0x0f;
+ lnz = left_mb->nz_ & 0x0f;
+ for (y = 0; y < 4; ++y) {
+ int l = lnz & 1;
+ uint32_t nz_coeffs = 0;
+ for (x = 0; x < 4; ++x) {
+ 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;
+ }
+ tnz >>= 4;
+ lnz = (lnz >> 1) | (l << 7);
+ non_zero_y = (non_zero_y << 8) | nz_coeffs;
+ }
+ out_t_nz = tnz;
+ out_l_nz = lnz >> 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 & 1;
+ for (x = 0; x < 2; ++x) {
+ 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;
+ }
+ tnz >>= 2;
+ lnz = (lnz >> 1) | (l << 5);
+ }
+ // 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;
+ }
+ mb->nz_ = out_t_nz;
+ left_mb->nz_ = out_l_nz;
+
+ 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
+}
+
+//------------------------------------------------------------------------------
+// Main loop
+
+int VP8DecodeMB(VP8Decoder* const dec, VP8BitReader* const token_br) {
+ VP8MB* const left = dec->mb_info_ - 1;
+ 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;
+
+ if (!skip) {
+ skip = ParseResiduals(dec, mb, token_br);
+ } else {
+ left->nz_ = mb->nz_ = 0;
+ if (!block->is_i4x4_) {
+ left->nz_dc_ = mb->nz_dc_ = 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_;
+}
+
+void VP8InitScanline(VP8Decoder* const dec) {
+ VP8MB* const left = dec->mb_info_ - 1;
+ left->nz_ = 0;
+ left->nz_dc_ = 0;
+ memset(dec->intra_l_, B_DC_PRED, sizeof(dec->intra_l_));
+ 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_minus_one_];
+ 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.");
+ }
+ }
+ 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->mt_method_ > 0) {
+ if (!WebPGetWorkerInterface()->Sync(&dec->worker_)) return 0;
+ }
+
+ 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;
+ }
+ WebPGetWorkerInterface()->End(&dec->worker_);
+ WebPDeallocateAlphaMemory(dec);
+ WebPSafeFree(dec->mem_);
+ dec->mem_ = NULL;
+ dec->mem_size_ = 0;
+ memset(&dec->br_, 0, sizeof(dec->br_));
+ dec->ready_ = 0;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/decode_vp8.h b/thirdparty/libwebp/dec/vp8_dec.h
index b9337bbec0..b9337bbec0 100644
--- a/thirdparty/libwebp/dec/decode_vp8.h
+++ b/thirdparty/libwebp/dec/vp8_dec.h
diff --git a/thirdparty/libwebp/dec/vp8i.h b/thirdparty/libwebp/dec/vp8i.h
deleted file mode 100644
index 313d8a7b94..0000000000
--- a/thirdparty/libwebp/dec/vp8i.h
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2010 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.
-// -----------------------------------------------------------------------------
-//
-// 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 "./common.h"
-#include "./vp8li.h"
-#include "../utils/bit_reader.h"
-#include "../utils/random.h"
-#include "../utils/thread.h"
-#include "../dsp/dsp.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Various defines and enums
-
-// version numbers
-#define DEC_MAJ_VERSION 0
-#define DEC_MIN_VERSION 5
-#define DEC_REV_VERSION 2
-
-// 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
-// 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
-#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
-
-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;
-
-// 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
- VP8BandProbas bands_[NUM_TYPES][NUM_BANDS];
- const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1];
-} 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
- 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 { // 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 (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
-
-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 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
-
- // 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 minus one.
- uint32_t num_parts_minus_one_;
- // per-partition boolean decoders.
- VP8BitReader parts_[MAX_NUM_PARTITIONS];
-
- // 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];
-
- // probabilities
- VP8Proba proba_;
- int use_skip_proba_;
- uint8_t skip_p_;
-
- // 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
-
- VP8TopSamples* yuv_t_; // top y/u/v 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_;
- 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
- VP8MBData* mb_data_; // parsed reconstruction data
-
- // Filtering side-info
- int filter_type_; // 0=off, 1=simple, 2=complex
- VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type
-
- // Alpha
- struct ALPHDecoder* alph_dec_; // alpha-plane decoder object
- const uint8_t* alpha_data_; // compressed alpha data (if present)
- size_t alpha_data_size_;
- int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
- uint8_t* alpha_plane_mem_; // memory allocated for alpha_plane_
- uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
- const uint8_t* alpha_prev_line_; // last decoded alpha row (or NULL)
- int alpha_dithering_; // derived from decoding options (0=off, 100=full)
-};
-
-//------------------------------------------------------------------------------
-// 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);
-// 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* 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
-// 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);
-// 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);
-// 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,
- const VP8Io* const io,
- int row, int num_rows);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_VP8I_H_ */
diff --git a/thirdparty/libwebp/dec/vp8i_dec.h b/thirdparty/libwebp/dec/vp8i_dec.h
new file mode 100644
index 0000000000..555853e8f8
--- /dev/null
+++ b/thirdparty/libwebp/dec/vp8i_dec.h
@@ -0,0 +1,320 @@
+// Copyright 2010 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.
+// -----------------------------------------------------------------------------
+//
+// 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 "./common_dec.h"
+#include "./vp8li_dec.h"
+#include "../utils/bit_reader_utils.h"
+#include "../utils/random_utils.h"
+#include "../utils/thread_utils.h"
+#include "../dsp/dsp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Various defines and enums
+
+// version numbers
+#define DEC_MAJ_VERSION 0
+#define DEC_MIN_VERSION 6
+#define DEC_REV_VERSION 0
+
+// 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
+// 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
+#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
+
+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;
+
+// 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
+ VP8BandProbas bands_[NUM_TYPES][NUM_BANDS];
+ const VP8BandProbas* bands_ptr_[NUM_TYPES][16 + 1];
+} 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
+ 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 { // 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 (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
+
+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 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
+
+ // 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 minus one.
+ uint32_t num_parts_minus_one_;
+ // per-partition boolean decoders.
+ VP8BitReader parts_[MAX_NUM_PARTITIONS];
+
+ // 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];
+
+ // probabilities
+ VP8Proba proba_;
+ int use_skip_proba_;
+ uint8_t skip_p_;
+
+ // 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
+
+ VP8TopSamples* yuv_t_; // top y/u/v 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_;
+ 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
+ VP8MBData* mb_data_; // parsed reconstruction data
+
+ // Filtering side-info
+ int filter_type_; // 0=off, 1=simple, 2=complex
+ VP8FInfo fstrengths_[NUM_MB_SEGMENTS][2]; // precalculated per-segment/type
+
+ // Alpha
+ struct ALPHDecoder* alph_dec_; // alpha-plane decoder object
+ const uint8_t* alpha_data_; // compressed alpha data (if present)
+ size_t alpha_data_size_;
+ int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
+ uint8_t* alpha_plane_mem_; // memory allocated for alpha_plane_
+ uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
+ const uint8_t* alpha_prev_line_; // last decoded alpha row (or NULL)
+ int alpha_dithering_; // derived from decoding options (0=off, 100=full)
+};
+
+//------------------------------------------------------------------------------
+// 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);
+// 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* 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
+// 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);
+// 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);
+// 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,
+ const VP8Io* const io,
+ int row, int num_rows);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_VP8I_H_ */
diff --git a/thirdparty/libwebp/dec/vp8l.c b/thirdparty/libwebp/dec/vp8l.c
deleted file mode 100644
index cb2e3176b6..0000000000
--- a/thirdparty/libwebp/dec/vp8l.c
+++ /dev/null
@@ -1,1660 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// main entry for the decoder
-//
-// Authors: Vikas Arora (vikaas.arora@gmail.com)
-// Jyrki Alakuijala (jyrki@google.com)
-
-#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"
-
-#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
-};
-
-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] = {
- 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 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,
- int is_level0,
- VP8LDecoder* const dec,
- uint32_t** const decoded_data);
-
-//------------------------------------------------------------------------------
-
-int VP8LCheckSignature(const uint8_t* const data, size_t size) {
- 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) {
- 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);
- 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;
- 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 = 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; // 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 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;
-}
-
-// 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 {
- 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;
- }
- }
-}
-
-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;
- HuffmanCode table[1 << LENGTHS_TABLE_BITS];
-
- 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) {
- goto End;
- }
- } else {
- max_symbol = num_symbols;
- }
-
- symbol = 0;
- while (symbol < num_symbols) {
- const HuffmanCode* p;
- int code_len;
- if (max_symbol-- == 0) break;
- VP8LFillBitWindow(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;
- } 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) {
- goto End;
- } else {
- const int length = use_prev ? prev_code_len : 0;
- while (repeat-- > 0) code_lengths[symbol++] = length;
- }
- }
- }
- ok = 1;
-
- End:
- 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,
- 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.
- 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.
- 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) {
- symbol = VP8LReadBits(br, 8);
- code_lengths[symbol] = 1;
- }
- ok = 1;
- } else { // Decode Huffman-coded code lengths.
- 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;
- }
-
- 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);
- }
-
- 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 size;
-}
-
-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;
- 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.
- 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)) {
- 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 group = (huffman_image[i] >> 8) & 0xffff;
- huffman_image[i] = group;
- if (group >= num_htree_groups) {
- num_htree_groups = group + 1;
- }
- }
- }
-
- 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));
-
- 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) {
- 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;
- }
- size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
- if (size == 0) {
- goto Error;
- }
- if (is_trivial_literal && kLiteralMap[j] == 1) {
- is_trivial_literal = (next->bits == 0);
- }
- total_size += next->bits;
- next += size;
- 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:
- WebPSafeFree(code_lengths);
- WebPSafeFree(huffman_image);
- WebPSafeFree(huffman_tables);
- VP8LHtreeGroupsFree(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;
- 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*)WebPSafeMalloc(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 = (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, 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) {
- 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;
- }
- return num_lines_out;
-}
-
-// Emit scaled rows.
-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;
- int num_lines_in = 0;
- int num_lines_out = 0;
- while (num_lines_in < mb_h) {
- uint8_t* const row_in = in + num_lines_in * in_stride;
- uint8_t* const row_out = out + num_lines_out * out_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;
-}
-
-// Emit rows without any scaling.
-static int EmitRows(WEBP_CSP_MODE colorspace,
- 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;
- 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
- 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;
- // 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) {
- uint8_t* const a = buf->a + y_pos * buf->a_stride;
-#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;
- 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;
- }
- return num_lines_out;
-}
-
-static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
- 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 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 uint8_t* in, int in_stride,
- int mb_w, int num_rows) {
- int y_pos = dec->last_out_row_;
- while (num_rows-- > 0) {
- ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
- 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 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,
- 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) {
- 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 += delta * pixel_stride;
- }
- if (y_start >= y_end) return 0; // Crop window is empty.
-
- *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;
- 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->pixels_ + dec->width_ * dec->last_row_;
- const int num_rows = row - dec->last_row_;
-
- assert(row <= dec->io_->crop_bottom);
- // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size
- // of argb_cache_), but we currently don't need more than that.
- assert(num_rows <= NUM_ARGB_CACHE_ROWS);
- if (num_rows > 0) { // Emit output.
- VP8Io* const io = dec->io_;
- uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
- const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
-
- ApplyInverseTransforms(dec, num_rows, rows);
- if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
- // Nothing to output (this time).
- } else {
- const WebPDecBuffer* const output = dec->output_;
- 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 ?
- 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_'.
- 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_);
-}
-
-// 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 AlphaApplyFilter(ALPHDecoder* const alph_dec,
- int first_row, int last_row,
- uint8_t* out, int stride) {
- if (alph_dec->filter_ != WEBP_FILTER_NONE) {
- int y;
- const uint8_t* prev_line = alph_dec->prev_line_;
- assert(WebPUnfilters[alph_dec->filter_] != NULL);
- for (y = first_row; y < last_row; ++y) {
- WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride);
- prev_line = out;
- out += stride;
- }
- alph_dec->prev_line_ = prev_line;
- }
-}
-
-static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {
- // For vertical and gradient filtering, we need to decode the part above the
- // crop_top row, in order to have the correct spatial predictors.
- ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
- const int top_row =
- (alph_dec->filter_ == WEBP_FILTER_NONE ||
- alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top
- : dec->last_row_;
- const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;
- assert(last_row <= dec->io_->crop_bottom);
- if (last_row > first_row) {
- // Special method for paletted alpha data. We only process the cropped area.
- const int width = dec->io_->width;
- uint8_t* out = alph_dec->output_ + width * first_row;
- const uint8_t* const in =
- (uint8_t*)dec->pixels_ + dec->width_ * first_row;
- VP8LTransform* const transform = &dec->transforms_[0];
- assert(dec->next_transform_ == 1);
- assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
- VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,
- in, out);
- AlphaApplyFilter(alph_dec, first_row, last_row, out, width);
- }
- dec->last_row_ = dec->last_out_row_ = last_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 row = dec->last_pixel_ / width;
- int col = dec->last_pixel_ % width;
- VP8LBitReader* const br = &dec->br_;
- VP8LMetadata* const hdr = &dec->hdr_;
- 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 mask = hdr->huffman_mask_;
- const HTreeGroup* htree_group =
- (pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
- assert(pos <= end);
- assert(last_row <= height);
- assert(Is8bOptimizable(hdr));
-
- while (!br->eos_ && pos < last) {
- int code;
- // Only update when changing tile.
- if ((col & mask) == 0) {
- htree_group = GetHtreeGroupForPos(hdr, col, row);
- }
- assert(htree_group != NULL);
- VP8LFillBitWindow(br);
- 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 <= last_row && (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);
- 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 <= last_row && (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 > last_row ? last_row : 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_;
- 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_;
- const HTreeGroup* htree_group =
- (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
- assert(dec->last_row_ < last_row);
- 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);
- }
- assert(htree_group != NULL);
- 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) {
- if (row <= last_row && (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 (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) {
- if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
- process_func(dec, row);
- }
- }
- }
- // 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
- 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
- goto Error;
- }
- assert(br->eos_ == VP8LIsEndOfStream(br));
- }
-
- 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 > last_row ? last_row : 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;
-
- Error:
- dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
- return 0;
-}
-
-// -----------------------------------------------------------------------------
-// VP8LTransform
-
-static void ClearTransform(VP8LTransform* const transform) {
- WebPSafeFree(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.
- WebPSafeFree(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 != NULL);
- memset(hdr, 0, sizeof(*hdr));
-}
-
-static void ClearMetadata(VP8LMetadata* const hdr) {
- assert(hdr != NULL);
-
- WebPSafeFree(hdr->huffman_image_);
- WebPSafeFree(hdr->huffman_tables_);
- VP8LHtreeGroupsFree(hdr->htree_groups_);
- VP8LColorCacheClear(&hdr->color_cache_);
- VP8LColorCacheClear(&hdr->saved_color_cache_);
- InitMetadata(hdr);
-}
-
-// -----------------------------------------------------------------------------
-// VP8LDecoder
-
-VP8LDecoder* VP8LNew(void) {
- VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
- if (dec == NULL) return NULL;
- dec->status_ = VP8_STATUS_OK;
- dec->state_ = READ_DIM;
-
- VP8LDspInit(); // Init critical function pointers.
-
- return dec;
-}
-
-void VP8LClear(VP8LDecoder* const dec) {
- int i;
- if (dec == NULL) return;
- ClearMetadata(&dec->hdr_);
-
- 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;
-
- WebPSafeFree(dec->rescaler_memory);
- dec->rescaler_memory = NULL;
-
- dec->output_ = NULL; // leave no trace behind
-}
-
-void VP8LDelete(VP8LDecoder* const dec) {
- if (dec != NULL) {
- VP8LClear(dec);
- WebPSafeFree(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,
- transform_ysize, NULL);
- ok = ok && !br->eos_;
-
- End:
- if (!ok) {
- WebPSafeFree(data);
- ClearMetadata(hdr);
- } 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);
- }
- dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.
- if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// 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. 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->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->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.
-static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
- int cur_row = dec->last_row_;
- int num_rows = last_row - cur_row;
- const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;
-
- assert(last_row <= dec->io_->crop_bottom);
- while (num_rows > 0) {
- const int num_rows_to_process =
- (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;
- // Extract alpha (which is stored in the green plane).
- ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
- uint8_t* const output = alph_dec->output_;
- const int width = dec->io_->width; // the final width (!= dec->width_)
- const int cache_pixs = width * num_rows_to_process;
- uint8_t* const dst = output + width * cur_row;
- const uint32_t* const src = dec->argb_cache_;
- int i;
- ApplyInverseTransforms(dec, num_rows_to_process, in);
- for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
- AlphaApplyFilter(alph_dec,
- cur_row, cur_row + num_rows_to_process, dst, width);
- num_rows -= num_rows_to_process;
- in += num_rows_to_process * dec->width_;
- cur_row += num_rows_to_process;
- }
- assert(cur_row == last_row);
- dec->last_row_ = dec->last_out_row_ = last_row;
-}
-
-int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
- const uint8_t* const data, size_t data_size) {
- int ok = 0;
- VP8LDecoder* dec = VP8LNew();
-
- if (dec == NULL) return 0;
-
- assert(alph_dec != NULL);
- alph_dec->vp8l_dec_ = dec;
-
- dec->width_ = alph_dec->width_;
- dec->height_ = alph_dec->height_;
- dec->io_ = &alph_dec->io_;
- dec->io_->opaque = alph_dec;
- dec->io_->width = alph_dec->width_;
- dec->io_->height = alph_dec->height_;
-
- dec->status_ = VP8_STATUS_OK;
- VP8LInitBitReader(&dec->br_, data, data_size);
-
- if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
- 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_);
- }
-
- if (!ok) goto Err;
-
- return 1;
-
- Err:
- 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_row_ >= last_row) {
- 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);
-}
-
-//------------------------------------------------------------------------------
-
-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;
-
- 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;
-
- 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);
-
- // Initialization.
- 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 (!AllocateInternalBuffers32b(dec, io->width)) 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.
- if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
- io->crop_bottom, ProcessRows)) {
- goto Err;
- }
-
- params->last_y = dec->last_out_row_;
- return 1;
-
- Err:
- VP8LClear(dec);
- assert(dec->status_ != VP8_STATUS_OK);
- return 0;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/vp8l_dec.c b/thirdparty/libwebp/dec/vp8l_dec.c
new file mode 100644
index 0000000000..ef359a91f0
--- /dev/null
+++ b/thirdparty/libwebp/dec/vp8l_dec.c
@@ -0,0 +1,1671 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// main entry for the decoder
+//
+// Authors: Vikas Arora (vikaas.arora@gmail.com)
+// Jyrki Alakuijala (jyrki@google.com)
+
+#include <stdlib.h>
+
+#include "./alphai_dec.h"
+#include "./vp8li_dec.h"
+#include "../dsp/dsp.h"
+#include "../dsp/lossless.h"
+#include "../dsp/lossless_common.h"
+#include "../dsp/yuv.h"
+#include "../utils/endian_inl_utils.h"
+#include "../utils/huffman_utils.h"
+#include "../utils/utils.h"
+
+#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
+};
+
+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] = {
+ 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 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,
+ int is_level0,
+ VP8LDecoder* const dec,
+ uint32_t** const decoded_data);
+
+//------------------------------------------------------------------------------
+
+int VP8LCheckSignature(const uint8_t* const data, size_t size) {
+ 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) {
+ 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);
+ 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;
+ 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 = 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; // 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 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;
+}
+
+// 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 {
+ 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;
+ }
+ }
+}
+
+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;
+ HuffmanCode table[1 << LENGTHS_TABLE_BITS];
+
+ 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) {
+ goto End;
+ }
+ } else {
+ max_symbol = num_symbols;
+ }
+
+ symbol = 0;
+ while (symbol < num_symbols) {
+ const HuffmanCode* p;
+ int code_len;
+ if (max_symbol-- == 0) break;
+ VP8LFillBitWindow(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;
+ } 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) {
+ goto End;
+ } else {
+ const int length = use_prev ? prev_code_len : 0;
+ while (repeat-- > 0) code_lengths[symbol++] = length;
+ }
+ }
+ }
+ ok = 1;
+
+ End:
+ 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,
+ 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.
+ 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.
+ 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) {
+ symbol = VP8LReadBits(br, 8);
+ code_lengths[symbol] = 1;
+ }
+ ok = 1;
+ } else { // Decode Huffman-coded code lengths.
+ 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;
+ }
+
+ 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);
+ }
+
+ 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 size;
+}
+
+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;
+ 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.
+ 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)) {
+ 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 group = (huffman_image[i] >> 8) & 0xffff;
+ huffman_image[i] = group;
+ if (group >= num_htree_groups) {
+ num_htree_groups = group + 1;
+ }
+ }
+ }
+
+ 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));
+
+ 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) {
+ 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;
+ }
+ size = ReadHuffmanCode(alphabet_size, dec, code_lengths, next);
+ if (size == 0) {
+ goto Error;
+ }
+ if (is_trivial_literal && kLiteralMap[j] == 1) {
+ is_trivial_literal = (next->bits == 0);
+ }
+ total_size += next->bits;
+ next += size;
+ 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:
+ WebPSafeFree(code_lengths);
+ WebPSafeFree(huffman_image);
+ WebPSafeFree(huffman_tables);
+ VP8LHtreeGroupsFree(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;
+ 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*)WebPSafeMalloc(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 = (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, 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) {
+ 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;
+ }
+ return num_lines_out;
+}
+
+// Emit scaled rows.
+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;
+ int num_lines_in = 0;
+ int num_lines_out = 0;
+ while (num_lines_in < mb_h) {
+ uint8_t* const row_in = in + num_lines_in * in_stride;
+ uint8_t* const row_out = out + num_lines_out * out_stride;
+ const int lines_left = mb_h - num_lines_in;
+ const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
+ int lines_imported;
+ assert(needed_lines > 0 && needed_lines <= lines_left);
+ WebPMultARGBRows(row_in, in_stride,
+ dec->rescaler->src_width, needed_lines, 0);
+ lines_imported =
+ WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
+ assert(lines_imported == needed_lines);
+ num_lines_in += lines_imported;
+ 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 uint8_t* row_in, int in_stride,
+ int mb_w, int mb_h,
+ uint8_t* const out, int out_stride) {
+ int lines = mb_h;
+ 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
+ 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;
+ // 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) {
+ uint8_t* const a = buf->a + y_pos * buf->a_stride;
+#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;
+ 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;
+ }
+ return num_lines_out;
+}
+
+static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
+ 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 int lines_left = mb_h - num_lines_in;
+ const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
+ int lines_imported;
+ WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
+ lines_imported =
+ WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
+ assert(lines_imported == needed_lines);
+ num_lines_in += lines_imported;
+ in += needed_lines * in_stride;
+ y_pos += ExportYUVA(dec, y_pos);
+ }
+ return y_pos;
+}
+
+static int EmitRowsYUVA(const VP8LDecoder* const dec,
+ const uint8_t* in, int in_stride,
+ int mb_w, int num_rows) {
+ int y_pos = dec->last_out_row_;
+ while (num_rows-- > 0) {
+ ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
+ 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 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,
+ 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) {
+ 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 += delta * pixel_stride;
+ }
+ if (y_start >= y_end) return 0; // Crop window is empty.
+
+ *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;
+ 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.
+ while (n-- > 0) {
+ VP8LTransform* const transform = &dec->transforms_[n];
+ VP8LInverseTransform(transform, start_row, end_row, rows_in, rows_out);
+ rows_in = rows_out;
+ }
+ if (rows_in != rows_out) {
+ // No transform called, hence just copy.
+ memcpy(rows_out, rows_in, cache_pixs * sizeof(*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->pixels_ + dec->width_ * dec->last_row_;
+ const int num_rows = row - dec->last_row_;
+
+ assert(row <= dec->io_->crop_bottom);
+ // We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size
+ // of argb_cache_), but we currently don't need more than that.
+ assert(num_rows <= NUM_ARGB_CACHE_ROWS);
+ if (num_rows > 0) { // Emit output.
+ VP8Io* const io = dec->io_;
+ uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
+ const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
+
+ ApplyInverseTransforms(dec, num_rows, rows);
+ if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
+ // Nothing to output (this time).
+ } else {
+ const WebPDecBuffer* const output = dec->output_;
+ 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 ?
+ 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_'.
+ 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_);
+}
+
+// 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 AlphaApplyFilter(ALPHDecoder* const alph_dec,
+ int first_row, int last_row,
+ uint8_t* out, int stride) {
+ if (alph_dec->filter_ != WEBP_FILTER_NONE) {
+ int y;
+ const uint8_t* prev_line = alph_dec->prev_line_;
+ assert(WebPUnfilters[alph_dec->filter_] != NULL);
+ for (y = first_row; y < last_row; ++y) {
+ WebPUnfilters[alph_dec->filter_](prev_line, out, out, stride);
+ prev_line = out;
+ out += stride;
+ }
+ alph_dec->prev_line_ = prev_line;
+ }
+}
+
+static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int last_row) {
+ // For vertical and gradient filtering, we need to decode the part above the
+ // crop_top row, in order to have the correct spatial predictors.
+ ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
+ const int top_row =
+ (alph_dec->filter_ == WEBP_FILTER_NONE ||
+ alph_dec->filter_ == WEBP_FILTER_HORIZONTAL) ? dec->io_->crop_top
+ : dec->last_row_;
+ const int first_row = (dec->last_row_ < top_row) ? top_row : dec->last_row_;
+ assert(last_row <= dec->io_->crop_bottom);
+ if (last_row > first_row) {
+ // Special method for paletted alpha data. We only process the cropped area.
+ const int width = dec->io_->width;
+ uint8_t* out = alph_dec->output_ + width * first_row;
+ const uint8_t* const in =
+ (uint8_t*)dec->pixels_ + dec->width_ * first_row;
+ VP8LTransform* const transform = &dec->transforms_[0];
+ assert(dec->next_transform_ == 1);
+ assert(transform->type_ == COLOR_INDEXING_TRANSFORM);
+ VP8LColorIndexInverseTransformAlpha(transform, first_row, last_row,
+ in, out);
+ AlphaApplyFilter(alph_dec, first_row, last_row, out, width);
+ }
+ dec->last_row_ = dec->last_out_row_ = last_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 row = dec->last_pixel_ / width;
+ int col = dec->last_pixel_ % width;
+ VP8LBitReader* const br = &dec->br_;
+ VP8LMetadata* const hdr = &dec->hdr_;
+ 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 mask = hdr->huffman_mask_;
+ const HTreeGroup* htree_group =
+ (pos < last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
+ assert(pos <= end);
+ assert(last_row <= height);
+ assert(Is8bOptimizable(hdr));
+
+ while (!br->eos_ && pos < last) {
+ int code;
+ // Only update when changing tile.
+ if ((col & mask) == 0) {
+ htree_group = GetHtreeGroupForPos(hdr, col, row);
+ }
+ assert(htree_group != NULL);
+ VP8LFillBitWindow(br);
+ 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 <= last_row && (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);
+ 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 <= last_row && (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 > last_row ? last_row : 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_;
+ 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_;
+ const HTreeGroup* htree_group =
+ (src < src_last) ? GetHtreeGroupForPos(hdr, col, row) : NULL;
+ assert(dec->last_row_ < last_row);
+ 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);
+ }
+ assert(htree_group != NULL);
+ 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) {
+ if (row <= last_row && (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 (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) {
+ if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
+ process_func(dec, row);
+ }
+ }
+ }
+ // 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
+ 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
+ goto Error;
+ }
+ assert(br->eos_ == VP8LIsEndOfStream(br));
+ }
+
+ 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 > last_row ? last_row : 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;
+
+ Error:
+ dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+// VP8LTransform
+
+static void ClearTransform(VP8LTransform* const transform) {
+ WebPSafeFree(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.
+ }
+ WebPSafeFree(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 != NULL);
+ memset(hdr, 0, sizeof(*hdr));
+}
+
+static void ClearMetadata(VP8LMetadata* const hdr) {
+ assert(hdr != NULL);
+
+ WebPSafeFree(hdr->huffman_image_);
+ WebPSafeFree(hdr->huffman_tables_);
+ VP8LHtreeGroupsFree(hdr->htree_groups_);
+ VP8LColorCacheClear(&hdr->color_cache_);
+ VP8LColorCacheClear(&hdr->saved_color_cache_);
+ InitMetadata(hdr);
+}
+
+// -----------------------------------------------------------------------------
+// VP8LDecoder
+
+VP8LDecoder* VP8LNew(void) {
+ VP8LDecoder* const dec = (VP8LDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
+ if (dec == NULL) return NULL;
+ dec->status_ = VP8_STATUS_OK;
+ dec->state_ = READ_DIM;
+
+ VP8LDspInit(); // Init critical function pointers.
+
+ return dec;
+}
+
+void VP8LClear(VP8LDecoder* const dec) {
+ int i;
+ if (dec == NULL) return;
+ ClearMetadata(&dec->hdr_);
+
+ 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;
+
+ WebPSafeFree(dec->rescaler_memory);
+ dec->rescaler_memory = NULL;
+
+ dec->output_ = NULL; // leave no trace behind
+}
+
+void VP8LDelete(VP8LDecoder* const dec) {
+ if (dec != NULL) {
+ VP8LClear(dec);
+ WebPSafeFree(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,
+ transform_ysize, NULL);
+ ok = ok && !br->eos_;
+
+ End:
+ if (!ok) {
+ WebPSafeFree(data);
+ ClearMetadata(hdr);
+ } 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);
+ }
+ dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.
+ if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
+ }
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+// 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. 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->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->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.
+static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
+ int cur_row = dec->last_row_;
+ int num_rows = last_row - cur_row;
+ const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;
+
+ assert(last_row <= dec->io_->crop_bottom);
+ while (num_rows > 0) {
+ const int num_rows_to_process =
+ (num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;
+ // Extract alpha (which is stored in the green plane).
+ ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
+ uint8_t* const output = alph_dec->output_;
+ const int width = dec->io_->width; // the final width (!= dec->width_)
+ const int cache_pixs = width * num_rows_to_process;
+ uint8_t* const dst = output + width * cur_row;
+ const uint32_t* const src = dec->argb_cache_;
+ ApplyInverseTransforms(dec, num_rows_to_process, in);
+ WebPExtractGreen(src, dst, cache_pixs);
+ AlphaApplyFilter(alph_dec,
+ cur_row, cur_row + num_rows_to_process, dst, width);
+ num_rows -= num_rows_to_process;
+ in += num_rows_to_process * dec->width_;
+ cur_row += num_rows_to_process;
+ }
+ assert(cur_row == last_row);
+ dec->last_row_ = dec->last_out_row_ = last_row;
+}
+
+int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
+ const uint8_t* const data, size_t data_size) {
+ int ok = 0;
+ VP8LDecoder* dec = VP8LNew();
+
+ if (dec == NULL) return 0;
+
+ assert(alph_dec != NULL);
+ alph_dec->vp8l_dec_ = dec;
+
+ dec->width_ = alph_dec->width_;
+ dec->height_ = alph_dec->height_;
+ dec->io_ = &alph_dec->io_;
+ dec->io_->opaque = alph_dec;
+ dec->io_->width = alph_dec->width_;
+ dec->io_->height = alph_dec->height_;
+
+ dec->status_ = VP8_STATUS_OK;
+ VP8LInitBitReader(&dec->br_, data, data_size);
+
+ if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
+ 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_);
+ }
+
+ if (!ok) goto Err;
+
+ return 1;
+
+ Err:
+ 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_row_ >= last_row) {
+ return 1; // done
+ }
+
+ if (!alph_dec->use_8b_decode_) WebPInitAlphaProcessing();
+
+ // 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);
+}
+
+//------------------------------------------------------------------------------
+
+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;
+
+ 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;
+
+ 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);
+
+ // Initialization.
+ 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 (!AllocateInternalBuffers32b(dec, io->width)) 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.
+ if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
+ io->crop_bottom, ProcessRows)) {
+ goto Err;
+ }
+
+ params->last_y = dec->last_out_row_;
+ return 1;
+
+ Err:
+ VP8LClear(dec);
+ assert(dec->status_ != VP8_STATUS_OK);
+ return 0;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/vp8li.h b/thirdparty/libwebp/dec/vp8li.h
deleted file mode 100644
index 9313bdc0af..0000000000
--- a/thirdparty/libwebp/dec/vp8li.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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"
-
-#ifdef __cplusplus
-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 {
- int color_cache_size_;
- VP8LColorCache color_cache_;
- VP8LColorCache saved_color_cache_; // for incremental
-
- int huffman_mask_;
- int huffman_subsample_bits_;
- int huffman_xsize_;
- uint32_t *huffman_image_;
- int num_htree_groups_;
- HTreeGroup *htree_groups_;
- HuffmanCode *huffman_tables_;
-} VP8LMetadata;
-
-typedef struct VP8LDecoder VP8LDecoder;
-struct VP8LDecoder {
- VP8StatusCode status_;
- VP8LDecodeState state_;
- VP8Io *io_;
-
- const WebPDecBuffer *output_; // shortcut to io->opaque->output
-
- 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_;
-
- 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.
-};
-
-//------------------------------------------------------------------------------
-// internal functions. Not public.
-
-struct ALPHDecoder; // Defined in dec/alphai.h.
-
-// in vp8l.c
-
-// 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);
-
-// 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);
-
-// 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);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_VP8LI_H_ */
diff --git a/thirdparty/libwebp/dec/vp8li_dec.h b/thirdparty/libwebp/dec/vp8li_dec.h
new file mode 100644
index 0000000000..097a9d0589
--- /dev/null
+++ b/thirdparty/libwebp/dec/vp8li_dec.h
@@ -0,0 +1,135 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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_dec.h"
+#include "../utils/bit_reader_utils.h"
+#include "../utils/color_cache_utils.h"
+#include "../utils/huffman_utils.h"
+
+#ifdef __cplusplus
+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 {
+ int color_cache_size_;
+ VP8LColorCache color_cache_;
+ VP8LColorCache saved_color_cache_; // for incremental
+
+ int huffman_mask_;
+ int huffman_subsample_bits_;
+ int huffman_xsize_;
+ uint32_t *huffman_image_;
+ int num_htree_groups_;
+ HTreeGroup *htree_groups_;
+ HuffmanCode *huffman_tables_;
+} VP8LMetadata;
+
+typedef struct VP8LDecoder VP8LDecoder;
+struct VP8LDecoder {
+ VP8StatusCode status_;
+ VP8LDecodeState state_;
+ VP8Io *io_;
+
+ const WebPDecBuffer *output_; // shortcut to io->opaque->output
+
+ 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_;
+
+ 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.
+};
+
+//------------------------------------------------------------------------------
+// internal functions. Not public.
+
+struct ALPHDecoder; // Defined in dec/alphai.h.
+
+// in vp8l.c
+
+// 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);
+
+// 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);
+
+// 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);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_VP8LI_H_ */
diff --git a/thirdparty/libwebp/dec/webp.c b/thirdparty/libwebp/dec/webp.c
deleted file mode 100644
index d0b912f02f..0000000000
--- a/thirdparty/libwebp/dec/webp.c
+++ /dev/null
@@ -1,846 +0,0 @@
-// Copyright 2010 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.
-// -----------------------------------------------------------------------------
-//
-// 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 "../utils/utils.h"
-#include "../webp/mux_types.h" // ALPHA_FLAG
-
-//------------------------------------------------------------------------------
-// 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, 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.
-
-// Validates the RIFF container (if detected) and skips over it.
-// 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, int have_all_data,
- 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 = 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;
- *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 = GetLE32(*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 = 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
- }
-
- 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 = 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;
-
- // 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.
- }
-
- // 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;
- }
-
- if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header.
- *alpha_data = buf + CHUNK_HEADER_SIZE;
- *alpha_size = chunk_size;
- }
-
- // 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, 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);
- 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 = 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;
- *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,
- 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;
-
- 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, have_all_data, &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,
- &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);
- 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) {
- 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) ||
- (!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) {
- goto ReturnWidthHeight; // Invalid chunk size / insufficient data.
- }
- }
-
- // Skip over VP8/VP8L header.
- status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size,
- &hdrs.compressed_size, &hdrs.is_lossless);
- if (status != VP8_STATUS_OK) {
- 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) {
- status = VP8_STATUS_NOT_ENOUGH_DATA;
- goto ReturnWidthHeight;
- }
- // Validates raw VP8 data.
- 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) {
- status = VP8_STATUS_NOT_ENOUGH_DATA;
- goto ReturnWidthHeight;
- }
- // Validates raw VP8L data.
- if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) {
- return VP8_STATUS_BITSTREAM_ERROR;
- }
- }
- // 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;
- headers->offset = data - headers->data;
- assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
- assert(headers->offset == headers->data_size - data_size);
- }
- 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) {
- // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug
- volatile VP8StatusCode status;
- int has_animation = 0;
- assert(headers != NULL);
- // fill out headers, ignore width/height/has_alpha.
- 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 != NULL) {
- 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;
- headers.have_all_data = 1;
- 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;
- }
- 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
- // 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_;
- }
- }
- }
- 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);
- } else {
- if (params->options != NULL && params->options->flip) {
- // This restores the original stride values if options->flip was used
- // during the call to WebPAllocateDecBuffer above.
- status = WebPFlipBuffer(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));
-}
-
-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 the features.
- return ParseHeadersInternal(data, data_size,
- &features->width, &features->height,
- &features->has_alpha, &features->has_animation,
- &features->format, 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) {
- 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;
- }
- return GetFeatures(data, data_size, features);
-}
-
-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.options = &config->options;
- params.output = &config->output;
- if (WebPAvoidSlowMemory(params.output, &config->input)) {
- // decoding to slow memory: use a temporary in-mem buffer to decode into.
- WebPDecBuffer in_mem_buffer;
- WebPInitDecBuffer(&in_mem_buffer);
- in_mem_buffer.colorspace = config->output.colorspace;
- in_mem_buffer.width = config->input.width;
- in_mem_buffer.height = config->input.height;
- params.output = &in_mem_buffer;
- status = DecodeInto(data, data_size, &params);
- if (status == VP8_STATUS_OK) { // do the slow-copy
- status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output);
- }
- WebPFreeDecBuffer(&in_mem_buffer);
- } else {
- 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
- x &= ~1;
- y &= ~1;
- }
- 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) {
- 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 = scaled_width;
- io->scaled_height = scaled_height;
- }
-
- // Filter
- io->bypass_filtering = (options != NULL) && 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;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/webp_dec.c b/thirdparty/libwebp/dec/webp_dec.c
new file mode 100644
index 0000000000..a8e9c2c510
--- /dev/null
+++ b/thirdparty/libwebp/dec/webp_dec.c
@@ -0,0 +1,843 @@
+// Copyright 2010 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.
+// -----------------------------------------------------------------------------
+//
+// Main decoding functions for WEBP images.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+
+#include "./vp8i_dec.h"
+#include "./vp8li_dec.h"
+#include "./webpi_dec.h"
+#include "../utils/utils.h"
+#include "../webp/mux_types.h" // ALPHA_FLAG
+
+//------------------------------------------------------------------------------
+// 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, 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.
+
+// Validates the RIFF container (if detected) and skips over it.
+// 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, int have_all_data,
+ 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 = 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;
+ *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 = GetLE32(*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 = 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
+ }
+
+ 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 = 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;
+
+ // 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.
+ }
+
+ // 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;
+ }
+
+ if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header.
+ *alpha_data = buf + CHUNK_HEADER_SIZE;
+ *alpha_size = chunk_size;
+ }
+
+ // 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, 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);
+ 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 = 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;
+ *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,
+ 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;
+ const int have_all_data = (headers != NULL) ? headers->have_all_data : 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, have_all_data, &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,
+ &canvas_width, &canvas_height, &flags);
+ if (status != VP8_STATUS_OK) {
+ return status; // Wrong VP8X / insufficient data.
+ }
+ animation_present = !!(flags & ANIMATION_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);
+ 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 && headers == NULL) {
+ status = VP8_STATUS_OK;
+ goto ReturnWidthHeight; // Just return features from VP8X header.
+ }
+ }
+
+ 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) ||
+ (!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) {
+ goto ReturnWidthHeight; // Invalid chunk size / insufficient data.
+ }
+ }
+
+ // Skip over VP8/VP8L header.
+ status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size,
+ &hdrs.compressed_size, &hdrs.is_lossless);
+ if (status != VP8_STATUS_OK) {
+ 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) {
+ *format = hdrs.is_lossless ? 2 : 1;
+ }
+
+ if (!hdrs.is_lossless) {
+ if (data_size < VP8_FRAME_HEADER_SIZE) {
+ status = VP8_STATUS_NOT_ENOUGH_DATA;
+ goto ReturnWidthHeight;
+ }
+ // Validates raw VP8 data.
+ 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) {
+ status = VP8_STATUS_NOT_ENOUGH_DATA;
+ goto ReturnWidthHeight;
+ }
+ // Validates raw VP8L data.
+ if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) {
+ return VP8_STATUS_BITSTREAM_ERROR;
+ }
+ }
+ // 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;
+ headers->offset = data - headers->data;
+ assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD);
+ assert(headers->offset == headers->data_size - data_size);
+ }
+ 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) {
+ // status is marked volatile as a workaround for a clang-3.8 (aarch64) bug
+ volatile VP8StatusCode status;
+ int has_animation = 0;
+ assert(headers != NULL);
+ // fill out headers, ignore width/height/has_alpha.
+ 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 != NULL) {
+ 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;
+ headers.have_all_data = 1;
+ 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;
+ }
+ 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
+ // 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_;
+ }
+ }
+ }
+ 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);
+ } else {
+ if (params->options != NULL && params->options->flip) {
+ // This restores the original stride values if options->flip was used
+ // during the call to WebPAllocateDecBuffer above.
+ status = WebPFlipBuffer(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));
+}
+
+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 the features.
+ return ParseHeadersInternal(data, data_size,
+ &features->width, &features->height,
+ &features->has_alpha, &features->has_animation,
+ &features->format, 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) {
+ 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;
+ }
+ return GetFeatures(data, data_size, features);
+}
+
+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.options = &config->options;
+ params.output = &config->output;
+ if (WebPAvoidSlowMemory(params.output, &config->input)) {
+ // decoding to slow memory: use a temporary in-mem buffer to decode into.
+ WebPDecBuffer in_mem_buffer;
+ WebPInitDecBuffer(&in_mem_buffer);
+ in_mem_buffer.colorspace = config->output.colorspace;
+ in_mem_buffer.width = config->input.width;
+ in_mem_buffer.height = config->input.height;
+ params.output = &in_mem_buffer;
+ status = DecodeInto(data, data_size, &params);
+ if (status == VP8_STATUS_OK) { // do the slow-copy
+ status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output);
+ }
+ WebPFreeDecBuffer(&in_mem_buffer);
+ } else {
+ 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
+ x &= ~1;
+ y &= ~1;
+ }
+ 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) {
+ 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 = scaled_width;
+ io->scaled_height = scaled_height;
+ }
+
+ // Filter
+ io->bypass_filtering = (options != NULL) && 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;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dec/webpi.h b/thirdparty/libwebp/dec/webpi.h
deleted file mode 100644
index 991b194c22..0000000000
--- a/thirdparty/libwebp/dec/webpi.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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_
-
-#ifdef __cplusplus
-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 (*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.
- 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
- OutputAlphaFunc emit_alpha; // output alpha channel
- OutputRowFunc emit_alpha_row; // output one line of rescaled alpha values
-
- WebPDecBuffer* final_output; // In case the user supplied a slow-memory
- // output, we decode image in temporary buffer
- // (this::output) and copy it here.
- WebPDecBuffer tmp_buffer; // this::output will point to this one in case
- // of slow memory.
-};
-
-// Should be called first, before any use of the WebPDecParams object.
-void WebPResetDecParams(WebPDecParams* const params);
-
-// Delete all memory (after an error occurred, for instance)
-void WebPFreeDecParams(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
- 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
- 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, 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);
-
-//------------------------------------------------------------------------------
-// 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.
-// 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'). No pixels are copied.
-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);
-
-// Copy pixels from 'src' into a *preallocated* 'dst' buffer. Returns
-// VP8_STATUS_INVALID_PARAM if the 'dst' is not set up correctly for the copy.
-VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src,
- WebPDecBuffer* const dst);
-
-// Returns true if decoding will be slow with the current configuration
-// and bitstream features.
-int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
- const WebPBitstreamFeatures* const features);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_DEC_WEBPI_H_ */
diff --git a/thirdparty/libwebp/dec/webpi_dec.h b/thirdparty/libwebp/dec/webpi_dec.h
new file mode 100644
index 0000000000..696abc1958
--- /dev/null
+++ b/thirdparty/libwebp/dec/webpi_dec.h
@@ -0,0 +1,133 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../utils/rescaler_utils.h"
+#include "./vp8_dec.h"
+
+//------------------------------------------------------------------------------
+// WebPDecParams: Decoding output parameters. Transient internal object.
+
+typedef struct WebPDecParams WebPDecParams;
+typedef int (*OutputFunc)(const VP8Io* const io, WebPDecParams* const p);
+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.
+ 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
+
+ WebPRescaler* scaler_y, *scaler_u, *scaler_v, *scaler_a; // rescalers
+ void* memory; // overall scratch memory for the output work.
+
+ OutputFunc emit; // output RGB or YUV samples
+ OutputAlphaFunc 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
+ 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
+ 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, 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);
+
+//------------------------------------------------------------------------------
+// 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.
+// 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'). No pixels are copied.
+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);
+
+// Copy pixels from 'src' into a *preallocated* 'dst' buffer. Returns
+// VP8_STATUS_INVALID_PARAM if the 'dst' is not set up correctly for the copy.
+VP8StatusCode WebPCopyDecBufferPixels(const WebPDecBuffer* const src,
+ WebPDecBuffer* const dst);
+
+// Returns true if decoding will be slow with the current configuration
+// and bitstream features.
+int WebPAvoidSlowMemory(const WebPDecBuffer* const output,
+ const WebPBitstreamFeatures* const features);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_DEC_WEBPI_H_ */
diff --git a/thirdparty/libwebp/demux/demux.c b/thirdparty/libwebp/demux/demux.c
index 1cb9bd5780..100eab8c01 100644
--- a/thirdparty/libwebp/demux/demux.c
+++ b/thirdparty/libwebp/demux/demux.c
@@ -25,7 +25,7 @@
#define DMUX_MAJ_VERSION 0
#define DMUX_MIN_VERSION 3
-#define DMUX_REV_VERSION 1
+#define DMUX_REV_VERSION 2
typedef struct {
size_t start_; // start location of the data
@@ -590,7 +590,6 @@ static int CheckFrameBounds(const Frame* const frame, int exact,
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;
@@ -598,7 +597,7 @@ static int IsValidExtendedFormat(const WebPDemuxer* const dmux) {
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;
+ if (dmux->feature_flags_ & ~ALL_VALID_FLAGS) return 0; // invalid bitstream
while (f != NULL) {
const int cur_frame_set = f->frame_num_;
diff --git a/thirdparty/libwebp/dsp/alpha_processing.c b/thirdparty/libwebp/dsp/alpha_processing.c
index 1716cace8d..4b60e092be 100644
--- a/thirdparty/libwebp/dsp/alpha_processing.c
+++ b/thirdparty/libwebp/dsp/alpha_processing.c
@@ -284,9 +284,9 @@ static void ApplyAlphaMultiply_16b(uint8_t* rgba4444,
#endif
}
-static int DispatchAlpha(const uint8_t* alpha, int alpha_stride,
- int width, int height,
- uint8_t* dst, int dst_stride) {
+static int DispatchAlpha_C(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;
@@ -303,9 +303,9 @@ static int DispatchAlpha(const uint8_t* alpha, int alpha_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) {
+static void DispatchAlphaToGreen_C(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) {
@@ -316,9 +316,9 @@ static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride,
}
}
-static int ExtractAlpha(const uint8_t* argb, int argb_stride,
- int width, int height,
- uint8_t* alpha, int alpha_stride) {
+static int ExtractAlpha_C(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;
@@ -334,11 +334,17 @@ static int ExtractAlpha(const uint8_t* argb, int argb_stride,
return (alpha_mask == 0xff);
}
+static void ExtractGreen_C(const uint32_t* argb, uint8_t* alpha, int size) {
+ int i;
+ for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8;
+}
+
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);
+void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size);
//------------------------------------------------------------------------------
// Init function
@@ -346,6 +352,7 @@ int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
extern void WebPInitAlphaProcessingMIPSdspR2(void);
extern void WebPInitAlphaProcessingSSE2(void);
extern void WebPInitAlphaProcessingSSE41(void);
+extern void WebPInitAlphaProcessingNEON(void);
static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used =
(VP8CPUInfo)&alpha_processing_last_cpuinfo_used;
@@ -357,9 +364,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
WebPMultRow = WebPMultRowC;
WebPApplyAlphaMultiply = ApplyAlphaMultiply;
WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b;
- WebPDispatchAlpha = DispatchAlpha;
- WebPDispatchAlphaToGreen = DispatchAlphaToGreen;
- WebPExtractAlpha = ExtractAlpha;
+
+ WebPDispatchAlpha = DispatchAlpha_C;
+ WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C;
+ WebPExtractAlpha = ExtractAlpha_C;
+ WebPExtractGreen = ExtractGreen_C;
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
@@ -373,6 +382,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) {
#endif
}
#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ WebPInitAlphaProcessingNEON();
+ }
+#endif
#if defined(WEBP_USE_MIPS_DSP_R2)
if (VP8GetCPUInfo(kMIPSdspR2)) {
WebPInitAlphaProcessingMIPSdspR2();
diff --git a/thirdparty/libwebp/dsp/alpha_processing_neon.c b/thirdparty/libwebp/dsp/alpha_processing_neon.c
new file mode 100644
index 0000000000..606a401cf7
--- /dev/null
+++ b/thirdparty/libwebp/dsp/alpha_processing_neon.c
@@ -0,0 +1,191 @@
+// Copyright 2017 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, NEON version.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include "./neon.h"
+
+//------------------------------------------------------------------------------
+
+#define MULTIPLIER(a) ((a) * 0x8081)
+#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
+
+#define MULTIPLY_BY_ALPHA(V, ALPHA, OTHER) do { \
+ const uint8x8_t alpha = (V).val[(ALPHA)]; \
+ const uint16x8_t r1 = vmull_u8((V).val[1], alpha); \
+ const uint16x8_t g1 = vmull_u8((V).val[2], alpha); \
+ const uint16x8_t b1 = vmull_u8((V).val[(OTHER)], alpha); \
+ /* we use: v / 255 = (v + 1 + (v >> 8)) >> 8 */ \
+ const uint16x8_t r2 = vsraq_n_u16(r1, r1, 8); \
+ const uint16x8_t g2 = vsraq_n_u16(g1, g1, 8); \
+ const uint16x8_t b2 = vsraq_n_u16(b1, b1, 8); \
+ const uint16x8_t r3 = vaddq_u16(r2, kOne); \
+ const uint16x8_t g3 = vaddq_u16(g2, kOne); \
+ const uint16x8_t b3 = vaddq_u16(b2, kOne); \
+ (V).val[1] = vshrn_n_u16(r3, 8); \
+ (V).val[2] = vshrn_n_u16(g3, 8); \
+ (V).val[(OTHER)] = vshrn_n_u16(b3, 8); \
+} while (0)
+
+static void ApplyAlphaMultiply_NEON(uint8_t* rgba, int alpha_first,
+ int w, int h, int stride) {
+ const uint16x8_t kOne = vdupq_n_u16(1u);
+ while (h-- > 0) {
+ uint32_t* const rgbx = (uint32_t*)rgba;
+ int i = 0;
+ if (alpha_first) {
+ for (; i + 8 <= w; i += 8) {
+ // load aaaa...|rrrr...|gggg...|bbbb...
+ uint8x8x4_t RGBX = vld4_u8((const uint8_t*)(rgbx + i));
+ MULTIPLY_BY_ALPHA(RGBX, 0, 3);
+ vst4_u8((uint8_t*)(rgbx + i), RGBX);
+ }
+ } else {
+ for (; i + 8 <= w; i += 8) {
+ uint8x8x4_t RGBX = vld4_u8((const uint8_t*)(rgbx + i));
+ MULTIPLY_BY_ALPHA(RGBX, 3, 0);
+ vst4_u8((uint8_t*)(rgbx + i), RGBX);
+ }
+ }
+ // 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 MULTIPLY_BY_ALPHA
+#undef MULTIPLIER
+#undef PREMULTIPLY
+
+//------------------------------------------------------------------------------
+
+static int DispatchAlpha_NEON(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint8_t* dst, int dst_stride) {
+ uint32_t alpha_mask = 0xffffffffu;
+ uint8x8_t mask8 = vdup_n_u8(0xff);
+ uint32_t tmp[2];
+ int i, j;
+ for (j = 0; j < height; ++j) {
+ // We don't know if alpha is first or last in dst[] (depending on rgbA/Argb
+ // mode). So we must be sure dst[4*i + 8 - 1] is writable for the store.
+ // Hence the test with 'width - 1' instead of just 'width'.
+ for (i = 0; i + 8 <= width - 1; i += 8) {
+ uint8x8x4_t rgbX = vld4_u8((const uint8_t*)(dst + 4 * i));
+ const uint8x8_t alphas = vld1_u8(alpha + i);
+ rgbX.val[0] = alphas;
+ vst4_u8((uint8_t*)(dst + 4 * i), rgbX);
+ mask8 = vand_u8(mask8, alphas);
+ }
+ for (; 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;
+ }
+ vst1_u8((uint8_t*)tmp, mask8);
+ alpha_mask &= tmp[0];
+ alpha_mask &= tmp[1];
+ return (alpha_mask != 0xffffffffu);
+}
+
+static void DispatchAlphaToGreen_NEON(const uint8_t* alpha, int alpha_stride,
+ int width, int height,
+ uint32_t* dst, int dst_stride) {
+ int i, j;
+ uint8x8x4_t greens; // leave A/R/B channels zero'd.
+ greens.val[0] = vdup_n_u8(0);
+ greens.val[2] = vdup_n_u8(0);
+ greens.val[3] = vdup_n_u8(0);
+ for (j = 0; j < height; ++j) {
+ for (i = 0; i + 8 <= width; i += 8) {
+ greens.val[1] = vld1_u8(alpha + i);
+ vst4_u8((uint8_t*)(dst + i), greens);
+ }
+ for (; i < width; ++i) dst[i] = alpha[i] << 8;
+ alpha += alpha_stride;
+ dst += dst_stride;
+ }
+}
+
+static int ExtractAlpha_NEON(const uint8_t* argb, int argb_stride,
+ int width, int height,
+ uint8_t* alpha, int alpha_stride) {
+ uint32_t alpha_mask = 0xffffffffu;
+ uint8x8_t mask8 = vdup_n_u8(0xff);
+ uint32_t tmp[2];
+ int i, j;
+ for (j = 0; j < height; ++j) {
+ // We don't know if alpha is first or last in dst[] (depending on rgbA/Argb
+ // mode). So we must be sure dst[4*i + 8 - 1] is writable for the store.
+ // Hence the test with 'width - 1' instead of just 'width'.
+ for (i = 0; i + 8 <= width - 1; i += 8) {
+ const uint8x8x4_t rgbX = vld4_u8((const uint8_t*)(argb + 4 * i));
+ const uint8x8_t alphas = rgbX.val[0];
+ vst1_u8((uint8_t*)(alpha + i), alphas);
+ mask8 = vand_u8(mask8, alphas);
+ }
+ for (; i < width; ++i) {
+ alpha[i] = argb[4 * i];
+ alpha_mask &= alpha[i];
+ }
+ argb += argb_stride;
+ alpha += alpha_stride;
+ }
+ vst1_u8((uint8_t*)tmp, mask8);
+ alpha_mask &= tmp[0];
+ alpha_mask &= tmp[1];
+ return (alpha_mask == 0xffffffffu);
+}
+
+static void ExtractGreen_NEON(const uint32_t* argb,
+ uint8_t* alpha, int size) {
+ int i;
+ for (i = 0; i + 16 <= size; i += 16) {
+ const uint8x16x4_t rgbX = vld4q_u8((const uint8_t*)(argb + i));
+ const uint8x16_t greens = rgbX.val[1];
+ vst1q_u8(alpha + i, greens);
+ }
+ for (; i < size; ++i) alpha[i] = (argb[i] >> 8) & 0xff;
+}
+
+//------------------------------------------------------------------------------
+
+extern void WebPInitAlphaProcessingNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingNEON(void) {
+ WebPApplyAlphaMultiply = ApplyAlphaMultiply_NEON;
+ WebPDispatchAlpha = DispatchAlpha_NEON;
+ WebPDispatchAlphaToGreen = DispatchAlphaToGreen_NEON;
+ WebPExtractAlpha = ExtractAlpha_NEON;
+ WebPExtractGreen = ExtractGreen_NEON;
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(WebPInitAlphaProcessingNEON)
+
+#endif // WEBP_USE_NEON
diff --git a/thirdparty/libwebp/dsp/alpha_processing_sse2.c b/thirdparty/libwebp/dsp/alpha_processing_sse2.c
index 5acb481dcd..83dc559fac 100644
--- a/thirdparty/libwebp/dsp/alpha_processing_sse2.c
+++ b/thirdparty/libwebp/dsp/alpha_processing_sse2.c
@@ -150,46 +150,46 @@ static int ExtractAlpha(const uint8_t* argb, int argb_stride,
#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); \
+// immediate in the _mm_shufflexx_epi16() instruction. We really need a macro.
+// We use: v / 255 = (v * 0x8081) >> 23, where v = alpha * {r,g,b} is a 16bit
+// value.
+#define APPLY_ALPHA(RGBX, SHUFFLE) do { \
+ const __m128i argb0 = _mm_loadu_si128((const __m128i*)&(RGBX)); \
+ const __m128i argb1_lo = _mm_unpacklo_epi8(argb0, zero); \
+ const __m128i argb1_hi = _mm_unpackhi_epi8(argb0, zero); \
+ const __m128i alpha0_lo = _mm_or_si128(argb1_lo, kMask); \
+ const __m128i alpha0_hi = _mm_or_si128(argb1_hi, kMask); \
+ const __m128i alpha1_lo = _mm_shufflelo_epi16(alpha0_lo, SHUFFLE); \
+ const __m128i alpha1_hi = _mm_shufflelo_epi16(alpha0_hi, SHUFFLE); \
+ const __m128i alpha2_lo = _mm_shufflehi_epi16(alpha1_lo, SHUFFLE); \
+ const __m128i alpha2_hi = _mm_shufflehi_epi16(alpha1_hi, SHUFFLE); \
+ /* alpha2 = [ff a0 a0 a0][ff a1 a1 a1] */ \
+ const __m128i A0_lo = _mm_mullo_epi16(alpha2_lo, argb1_lo); \
+ const __m128i A0_hi = _mm_mullo_epi16(alpha2_hi, argb1_hi); \
+ const __m128i A1_lo = _mm_mulhi_epu16(A0_lo, kMult); \
+ const __m128i A1_hi = _mm_mulhi_epu16(A0_hi, kMult); \
+ const __m128i A2_lo = _mm_srli_epi16(A1_lo, 7); \
+ const __m128i A2_hi = _mm_srli_epi16(A1_hi, 7); \
+ const __m128i A3 = _mm_packus_epi16(A2_lo, A2_hi); \
+ _mm_storeu_si128((__m128i*)&(RGBX), A3); \
} while (0)
-static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
- int w, int h, int stride) {
+static void ApplyAlphaMultiply_SSE2(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);
+ const __m128i kMult = _mm_set1_epi16(0x8081u);
+ const __m128i kMask = _mm_set_epi16(0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0);
+ const int kSpan = 4;
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);
+ for (i = 0; i + kSpan <= w; i += kSpan) {
+ APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(2, 3, 3, 3));
}
} 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);
+ for (i = 0; i + kSpan <= w; i += kSpan) {
+ APPLY_ALPHA(rgbx[i], _MM_SHUFFLE(0, 0, 0, 1));
}
}
// Finish with left-overs.
@@ -213,64 +213,51 @@ static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first,
// -----------------------------------------------------------------------------
// 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) {
+static void MultARGBRow_SSE2(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);
+ const __m128i k128 = _mm_set1_epi16(128);
+ const __m128i kMult = _mm_set1_epi16(0x0101);
+ const __m128i kMask = _mm_set_epi16(0, 0xff, 0, 0, 0, 0xff, 0, 0);
+ for (x = 0; x + kSpan <= width; x += kSpan) {
+ // To compute 'result = (int)(a * x / 255. + .5)', we use:
+ // tmp = a * v + 128, result = (tmp * 0x0101u) >> 16
+ const __m128i A0 = _mm_loadl_epi64((const __m128i*)&ptr[x]);
+ const __m128i A1 = _mm_unpacklo_epi8(A0, zero);
+ const __m128i A2 = _mm_or_si128(A1, kMask);
+ const __m128i A3 = _mm_shufflelo_epi16(A2, _MM_SHUFFLE(2, 3, 3, 3));
+ const __m128i A4 = _mm_shufflehi_epi16(A3, _MM_SHUFFLE(2, 3, 3, 3));
+ // here, A4 = [ff a0 a0 a0][ff a1 a1 a1]
+ const __m128i A5 = _mm_mullo_epi16(A4, A1);
+ const __m128i A6 = _mm_add_epi16(A5, k128);
+ const __m128i A7 = _mm_mulhi_epu16(A6, kMult);
+ const __m128i A10 = _mm_packus_epi16(A7, zero);
+ _mm_storel_epi64((__m128i*)&ptr[x], A10);
}
}
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) {
+static void MultRow_SSE2(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 k128 = _mm_set1_epi16(128);
+ const __m128i kMult = _mm_set1_epi16(0x0101);
+ for (x = 0; x + 8 <= width; x += 8) {
const __m128i v0 = _mm_loadl_epi64((__m128i*)&ptr[x]);
+ const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[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);
+ const __m128i a1 = _mm_unpacklo_epi8(a0, zero);
+ const __m128i v2 = _mm_mullo_epi16(v1, a1);
+ const __m128i v3 = _mm_add_epi16(v2, k128);
+ const __m128i v4 = _mm_mulhi_epu16(v3, kMult);
+ const __m128i v5 = _mm_packus_epi16(v4, zero);
+ _mm_storel_epi64((__m128i*)&ptr[x], v5);
}
}
width -= x;
@@ -283,9 +270,9 @@ static void MultRow(uint8_t* const ptr, const uint8_t* const alpha,
extern void WebPInitAlphaProcessingSSE2(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) {
- WebPMultARGBRow = MultARGBRow;
- WebPMultRow = MultRow;
- WebPApplyAlphaMultiply = ApplyAlphaMultiply;
+ WebPMultARGBRow = MultARGBRow_SSE2;
+ WebPMultRow = MultRow_SSE2;
+ WebPApplyAlphaMultiply = ApplyAlphaMultiply_SSE2;
WebPDispatchAlpha = DispatchAlpha;
WebPDispatchAlphaToGreen = DispatchAlphaToGreen;
WebPExtractAlpha = ExtractAlpha;
diff --git a/thirdparty/libwebp/dsp/common_sse2.h b/thirdparty/libwebp/dsp/common_sse2.h
index 7cea13fb3c..995d7cf4ea 100644
--- a/thirdparty/libwebp/dsp/common_sse2.h
+++ b/thirdparty/libwebp/dsp/common_sse2.h
@@ -100,6 +100,91 @@ static WEBP_INLINE void VP8Transpose_2_4x4_16b(
// a03 a13 a23 a33 b03 b13 b23 b33
}
+//------------------------------------------------------------------------------
+// Channel mixing.
+
+// Function used several times in VP8PlanarTo24b.
+// It samples the in buffer as follows: one every two unsigned char is stored
+// at the beginning of the buffer, while the other half is stored at the end.
+#define VP8PlanarTo24bHelper(IN, OUT) \
+ do { \
+ const __m128i v_mask = _mm_set1_epi16(0x00ff); \
+ /* Take one every two upper 8b values.*/ \
+ (OUT##0) = _mm_packus_epi16(_mm_and_si128((IN##0), v_mask), \
+ _mm_and_si128((IN##1), v_mask)); \
+ (OUT##1) = _mm_packus_epi16(_mm_and_si128((IN##2), v_mask), \
+ _mm_and_si128((IN##3), v_mask)); \
+ (OUT##2) = _mm_packus_epi16(_mm_and_si128((IN##4), v_mask), \
+ _mm_and_si128((IN##5), v_mask)); \
+ /* Take one every two lower 8b values.*/ \
+ (OUT##3) = _mm_packus_epi16(_mm_srli_epi16((IN##0), 8), \
+ _mm_srli_epi16((IN##1), 8)); \
+ (OUT##4) = _mm_packus_epi16(_mm_srli_epi16((IN##2), 8), \
+ _mm_srli_epi16((IN##3), 8)); \
+ (OUT##5) = _mm_packus_epi16(_mm_srli_epi16((IN##4), 8), \
+ _mm_srli_epi16((IN##5), 8)); \
+ } while (0)
+
+// Pack the planar buffers
+// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
+// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
+static WEBP_INLINE void VP8PlanarTo24b(__m128i* const in0, __m128i* const in1,
+ __m128i* const in2, __m128i* const in3,
+ __m128i* const in4, __m128i* const in5) {
+ // The input is 6 registers of sixteen 8b but for the sake of explanation,
+ // let's take 6 registers of four 8b values.
+ // To pack, we will keep taking one every two 8b integer and move it
+ // around as follows:
+ // Input:
+ // r0r1r2r3 | r4r5r6r7 | g0g1g2g3 | g4g5g6g7 | b0b1b2b3 | b4b5b6b7
+ // Split the 6 registers in two sets of 3 registers: the first set as the even
+ // 8b bytes, the second the odd ones:
+ // r0r2r4r6 | g0g2g4g6 | b0b2b4b6 | r1r3r5r7 | g1g3g5g7 | b1b3b5b7
+ // Repeat the same permutations twice more:
+ // r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7
+ // r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
+ __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ VP8PlanarTo24bHelper(*in, tmp);
+ VP8PlanarTo24bHelper(tmp, *in);
+ VP8PlanarTo24bHelper(*in, tmp);
+ // We need to do it two more times than the example as we have sixteen bytes.
+ {
+ __m128i out0, out1, out2, out3, out4, out5;
+ VP8PlanarTo24bHelper(tmp, out);
+ VP8PlanarTo24bHelper(out, *in);
+ }
+}
+
+#undef VP8PlanarTo24bHelper
+
+// Convert four packed four-channel buffers like argbargbargbargb... into the
+// split channels aaaaa ... rrrr ... gggg .... bbbbb ......
+static WEBP_INLINE void VP8L32bToPlanar(__m128i* const in0,
+ __m128i* const in1,
+ __m128i* const in2,
+ __m128i* const in3) {
+ // Column-wise transpose.
+ const __m128i A0 = _mm_unpacklo_epi8(*in0, *in1);
+ const __m128i A1 = _mm_unpackhi_epi8(*in0, *in1);
+ const __m128i A2 = _mm_unpacklo_epi8(*in2, *in3);
+ const __m128i A3 = _mm_unpackhi_epi8(*in2, *in3);
+ const __m128i B0 = _mm_unpacklo_epi8(A0, A1);
+ const __m128i B1 = _mm_unpackhi_epi8(A0, A1);
+ const __m128i B2 = _mm_unpacklo_epi8(A2, A3);
+ const __m128i B3 = _mm_unpackhi_epi8(A2, A3);
+ // 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);
+ const __m128i C2 = _mm_unpacklo_epi8(B2, B3);
+ const __m128i C3 = _mm_unpackhi_epi8(B2, B3);
+ // Gather the channels.
+ *in0 = _mm_unpackhi_epi64(C1, C3);
+ *in1 = _mm_unpacklo_epi64(C1, C3);
+ *in2 = _mm_unpackhi_epi64(C0, C2);
+ *in3 = _mm_unpacklo_epi64(C0, C2);
+}
+
#endif // WEBP_USE_SSE2
#ifdef __cplusplus
diff --git a/thirdparty/libwebp/dsp/cost.c b/thirdparty/libwebp/dsp/cost.c
index fe72d26e79..58ddea7248 100644
--- a/thirdparty/libwebp/dsp/cost.c
+++ b/thirdparty/libwebp/dsp/cost.c
@@ -10,7 +10,7 @@
// Author: Skal (pascal.massimino@gmail.com)
#include "./dsp.h"
-#include "../enc/cost.h"
+#include "../enc/cost_enc.h"
//------------------------------------------------------------------------------
// Boolean-cost cost table
diff --git a/thirdparty/libwebp/dsp/cost_mips32.c b/thirdparty/libwebp/dsp/cost_mips32.c
index d1e240e191..3102da877a 100644
--- a/thirdparty/libwebp/dsp/cost_mips32.c
+++ b/thirdparty/libwebp/dsp/cost_mips32.c
@@ -13,7 +13,7 @@
#if defined(WEBP_USE_MIPS32)
-#include "../enc/cost.h"
+#include "../enc/cost_enc.h"
static int GetResidualCost(int ctx0, const VP8Residual* const res) {
int temp0, temp1;
diff --git a/thirdparty/libwebp/dsp/cost_mips_dsp_r2.c b/thirdparty/libwebp/dsp/cost_mips_dsp_r2.c
index ce64067756..6ec8aeb610 100644
--- a/thirdparty/libwebp/dsp/cost_mips_dsp_r2.c
+++ b/thirdparty/libwebp/dsp/cost_mips_dsp_r2.c
@@ -13,7 +13,7 @@
#if defined(WEBP_USE_MIPS_DSP_R2)
-#include "../enc/cost.h"
+#include "../enc/cost_enc.h"
static int GetResidualCost(int ctx0, const VP8Residual* const res) {
int temp0, temp1;
diff --git a/thirdparty/libwebp/dsp/cost_sse2.c b/thirdparty/libwebp/dsp/cost_sse2.c
index 0cb1c1fa04..421d51fdd5 100644
--- a/thirdparty/libwebp/dsp/cost_sse2.c
+++ b/thirdparty/libwebp/dsp/cost_sse2.c
@@ -16,8 +16,8 @@
#if defined(WEBP_USE_SSE2)
#include <emmintrin.h>
-#include "../enc/cost.h"
-#include "../enc/vp8enci.h"
+#include "../enc/cost_enc.h"
+#include "../enc/vp8i_enc.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dsp/cpu.c b/thirdparty/libwebp/dsp/cpu.c
index cbb08db90a..b5583b6e9b 100644
--- a/thirdparty/libwebp/dsp/cpu.c
+++ b/thirdparty/libwebp/dsp/cpu.c
@@ -95,26 +95,62 @@ static WEBP_INLINE uint64_t xgetbv(void) {
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2)
+
+// helper function for run-time detection of slow SSSE3 platforms
+static int CheckSlowModel(int info) {
+ // Table listing display models with longer latencies for the bsr instruction
+ // (ie 2 cycles vs 10/16 cycles) and some SSSE3 instructions like pshufb.
+ // Refer to Intel 64 and IA-32 Architectures Optimization Reference Manual.
+ static const uint8_t kSlowModels[] = {
+ 0x37, 0x4a, 0x4d, // Silvermont Microarchitecture
+ 0x1c, 0x26, 0x27 // Atom Microarchitecture
+ };
+ const uint32_t model = ((info & 0xf0000) >> 12) | ((info >> 4) & 0xf);
+ const uint32_t family = (info >> 8) & 0xf;
+ if (family == 0x06) {
+ size_t i;
+ for (i = 0; i < sizeof(kSlowModels) / sizeof(kSlowModels[0]); ++i) {
+ if (model == kSlowModels[i]) return 1;
+ }
+ }
+ return 0;
+}
+
static int x86CPUInfo(CPUFeature feature) {
int max_cpuid_value;
int cpu_info[4];
+ int is_intel = 0;
// get the highest feature value cpuid supports
GetCPUInfo(cpu_info, 0);
max_cpuid_value = cpu_info[0];
if (max_cpuid_value < 1) {
return 0;
+ } else {
+ const int VENDOR_ID_INTEL_EBX = 0x756e6547; // uneG
+ const int VENDOR_ID_INTEL_EDX = 0x49656e69; // Ieni
+ const int VENDOR_ID_INTEL_ECX = 0x6c65746e; // letn
+ is_intel = (cpu_info[1] == VENDOR_ID_INTEL_EBX &&
+ cpu_info[2] == VENDOR_ID_INTEL_ECX &&
+ cpu_info[3] == VENDOR_ID_INTEL_EDX); // genuine Intel?
}
GetCPUInfo(cpu_info, 1);
if (feature == kSSE2) {
- return 0 != (cpu_info[3] & 0x04000000);
+ return !!(cpu_info[3] & (1 << 26));
}
if (feature == kSSE3) {
- return 0 != (cpu_info[2] & 0x00000001);
+ return !!(cpu_info[2] & (1 << 0));
+ }
+ if (feature == kSlowSSSE3) {
+ if (is_intel && (cpu_info[2] & (1 << 0))) { // SSSE3?
+ return CheckSlowModel(cpu_info[0]);
+ }
+ return 0;
}
+
if (feature == kSSE4_1) {
- return 0 != (cpu_info[2] & 0x00080000);
+ return !!(cpu_info[2] & (1 << 19));
}
if (feature == kAVX) {
// bits 27 (OSXSAVE) & 28 (256-bit AVX)
@@ -126,7 +162,7 @@ static int x86CPUInfo(CPUFeature feature) {
if (feature == kAVX2) {
if (x86CPUInfo(kAVX) && max_cpuid_value >= 7) {
GetCPUInfo(cpu_info, 7);
- return ((cpu_info[1] & 0x00000020) == 0x00000020);
+ return !!(cpu_info[1] & (1 << 5));
}
}
return 0;
@@ -184,4 +220,3 @@ VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
#else
VP8CPUInfo VP8GetCPUInfo = NULL;
#endif
-
diff --git a/thirdparty/libwebp/dsp/dec.c b/thirdparty/libwebp/dsp/dec.c
index 49bd16d976..007e985d8b 100644
--- a/thirdparty/libwebp/dsp/dec.c
+++ b/thirdparty/libwebp/dsp/dec.c
@@ -12,7 +12,7 @@
// Author: Skal (pascal.massimino@gmail.com)
#include "./dsp.h"
-#include "../dec/vp8i.h"
+#include "../dec/vp8i_dec.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dsp/dec_clip_tables.c b/thirdparty/libwebp/dsp/dec_clip_tables.c
index 3b6dde86ba..74ba34c0bb 100644
--- a/thirdparty/libwebp/dsp/dec_clip_tables.c
+++ b/thirdparty/libwebp/dsp/dec_clip_tables.c
@@ -63,7 +63,7 @@ static const uint8_t abs0[255 + 255 + 1] = {
0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
-static const int8_t sclip1[1020 + 1020 + 1] = {
+static const uint8_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,
@@ -236,7 +236,7 @@ static const int8_t sclip1[1020 + 1020 + 1] = {
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f
};
-static const int8_t sclip2[112 + 112 + 1] = {
+static const uint8_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,
@@ -339,8 +339,8 @@ static volatile int tables_ok = 0;
#endif
-const int8_t* const VP8ksclip1 = &sclip1[1020];
-const int8_t* const VP8ksclip2 = &sclip2[112];
+const int8_t* const VP8ksclip1 = (const int8_t*)&sclip1[1020];
+const int8_t* const VP8ksclip2 = (const int8_t*)&sclip2[112];
const uint8_t* const VP8kclip1 = &clip1[255];
const uint8_t* const VP8kabs0 = &abs0[255];
diff --git a/thirdparty/libwebp/dsp/dec_msa.c b/thirdparty/libwebp/dsp/dec_msa.c
index f76055cab0..8d9c98c3cf 100644
--- a/thirdparty/libwebp/dsp/dec_msa.c
+++ b/thirdparty/libwebp/dsp/dec_msa.c
@@ -154,6 +154,820 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) {
}
//------------------------------------------------------------------------------
+// Edge filtering functions
+
+#define FLIP_SIGN2(in0, in1, out0, out1) { \
+ out0 = (v16i8)__msa_xori_b(in0, 0x80); \
+ out1 = (v16i8)__msa_xori_b(in1, 0x80); \
+}
+
+#define FLIP_SIGN4(in0, in1, in2, in3, out0, out1, out2, out3) { \
+ FLIP_SIGN2(in0, in1, out0, out1); \
+ FLIP_SIGN2(in2, in3, out2, out3); \
+}
+
+#define FILT_VAL(q0_m, p0_m, mask, filt) do { \
+ v16i8 q0_sub_p0; \
+ q0_sub_p0 = __msa_subs_s_b(q0_m, p0_m); \
+ filt = __msa_adds_s_b(filt, q0_sub_p0); \
+ filt = __msa_adds_s_b(filt, q0_sub_p0); \
+ filt = __msa_adds_s_b(filt, q0_sub_p0); \
+ filt = filt & mask; \
+} while (0)
+
+#define FILT2(q_m, p_m, q, p) do { \
+ u_r = SRAI_H(temp1, 7); \
+ u_r = __msa_sat_s_h(u_r, 7); \
+ u_l = SRAI_H(temp3, 7); \
+ u_l = __msa_sat_s_h(u_l, 7); \
+ u = __msa_pckev_b((v16i8)u_l, (v16i8)u_r); \
+ q_m = __msa_subs_s_b(q_m, u); \
+ p_m = __msa_adds_s_b(p_m, u); \
+ q = __msa_xori_b((v16u8)q_m, 0x80); \
+ p = __msa_xori_b((v16u8)p_m, 0x80); \
+} while (0)
+
+#define LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev) do { \
+ v16i8 p1_m, p0_m, q0_m, q1_m; \
+ v16i8 filt, t1, t2; \
+ const v16i8 cnst4b = __msa_ldi_b(4); \
+ const v16i8 cnst3b = __msa_ldi_b(3); \
+ \
+ FLIP_SIGN4(p1, p0, q0, q1, p1_m, p0_m, q0_m, q1_m); \
+ filt = __msa_subs_s_b(p1_m, q1_m); \
+ filt = filt & hev; \
+ FILT_VAL(q0_m, p0_m, mask, filt); \
+ t1 = __msa_adds_s_b(filt, cnst4b); \
+ t1 = SRAI_B(t1, 3); \
+ t2 = __msa_adds_s_b(filt, cnst3b); \
+ t2 = SRAI_B(t2, 3); \
+ q0_m = __msa_subs_s_b(q0_m, t1); \
+ q0 = __msa_xori_b((v16u8)q0_m, 0x80); \
+ p0_m = __msa_adds_s_b(p0_m, t2); \
+ p0 = __msa_xori_b((v16u8)p0_m, 0x80); \
+ filt = __msa_srari_b(t1, 1); \
+ hev = __msa_xori_b(hev, 0xff); \
+ filt = filt & hev; \
+ q1_m = __msa_subs_s_b(q1_m, filt); \
+ q1 = __msa_xori_b((v16u8)q1_m, 0x80); \
+ p1_m = __msa_adds_s_b(p1_m, filt); \
+ p1 = __msa_xori_b((v16u8)p1_m, 0x80); \
+} while (0)
+
+#define LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev) do { \
+ v16i8 p2_m, p1_m, p0_m, q2_m, q1_m, q0_m; \
+ v16i8 u, filt, t1, t2, filt_sign; \
+ v8i16 filt_r, filt_l, u_r, u_l; \
+ v8i16 temp0, temp1, temp2, temp3; \
+ const v16i8 cnst4b = __msa_ldi_b(4); \
+ const v16i8 cnst3b = __msa_ldi_b(3); \
+ const v8i16 cnst9h = __msa_ldi_h(9); \
+ \
+ FLIP_SIGN4(p1, p0, q0, q1, p1_m, p0_m, q0_m, q1_m); \
+ filt = __msa_subs_s_b(p1_m, q1_m); \
+ FILT_VAL(q0_m, p0_m, mask, filt); \
+ FLIP_SIGN2(p2, q2, p2_m, q2_m); \
+ t2 = filt & hev; \
+ /* filt_val &= ~hev */ \
+ hev = __msa_xori_b(hev, 0xff); \
+ filt = filt & hev; \
+ t1 = __msa_adds_s_b(t2, cnst4b); \
+ t1 = SRAI_B(t1, 3); \
+ t2 = __msa_adds_s_b(t2, cnst3b); \
+ t2 = SRAI_B(t2, 3); \
+ q0_m = __msa_subs_s_b(q0_m, t1); \
+ p0_m = __msa_adds_s_b(p0_m, t2); \
+ filt_sign = __msa_clti_s_b(filt, 0); \
+ ILVRL_B2_SH(filt_sign, filt, filt_r, filt_l); \
+ /* update q2/p2 */ \
+ temp0 = filt_r * cnst9h; \
+ temp1 = ADDVI_H(temp0, 63); \
+ temp2 = filt_l * cnst9h; \
+ temp3 = ADDVI_H(temp2, 63); \
+ FILT2(q2_m, p2_m, q2, p2); \
+ /* update q1/p1 */ \
+ temp1 = temp1 + temp0; \
+ temp3 = temp3 + temp2; \
+ FILT2(q1_m, p1_m, q1, p1); \
+ /* update q0/p0 */ \
+ temp1 = temp1 + temp0; \
+ temp3 = temp3 + temp2; \
+ FILT2(q0_m, p0_m, q0, p0); \
+} while (0)
+
+#define LPF_MASK_HEV(p3_in, p2_in, p1_in, p0_in, \
+ q0_in, q1_in, q2_in, q3_in, \
+ limit_in, b_limit_in, thresh_in, \
+ hev_out, mask_out) do { \
+ v16u8 p3_asub_p2_m, p2_asub_p1_m, p1_asub_p0_m, q1_asub_q0_m; \
+ v16u8 p1_asub_q1_m, p0_asub_q0_m, q3_asub_q2_m, q2_asub_q1_m; \
+ v16u8 flat_out; \
+ \
+ /* absolute subtraction of pixel values */ \
+ p3_asub_p2_m = __msa_asub_u_b(p3_in, p2_in); \
+ p2_asub_p1_m = __msa_asub_u_b(p2_in, p1_in); \
+ p1_asub_p0_m = __msa_asub_u_b(p1_in, p0_in); \
+ q1_asub_q0_m = __msa_asub_u_b(q1_in, q0_in); \
+ q2_asub_q1_m = __msa_asub_u_b(q2_in, q1_in); \
+ q3_asub_q2_m = __msa_asub_u_b(q3_in, q2_in); \
+ p0_asub_q0_m = __msa_asub_u_b(p0_in, q0_in); \
+ p1_asub_q1_m = __msa_asub_u_b(p1_in, q1_in); \
+ /* calculation of hev */ \
+ flat_out = __msa_max_u_b(p1_asub_p0_m, q1_asub_q0_m); \
+ hev_out = (thresh_in < flat_out); \
+ /* calculation of mask */ \
+ p0_asub_q0_m = __msa_adds_u_b(p0_asub_q0_m, p0_asub_q0_m); \
+ p1_asub_q1_m = SRAI_B(p1_asub_q1_m, 1); \
+ p0_asub_q0_m = __msa_adds_u_b(p0_asub_q0_m, p1_asub_q1_m); \
+ mask_out = (b_limit_in < p0_asub_q0_m); \
+ mask_out = __msa_max_u_b(flat_out, mask_out); \
+ p3_asub_p2_m = __msa_max_u_b(p3_asub_p2_m, p2_asub_p1_m); \
+ mask_out = __msa_max_u_b(p3_asub_p2_m, mask_out); \
+ q2_asub_q1_m = __msa_max_u_b(q2_asub_q1_m, q3_asub_q2_m); \
+ mask_out = __msa_max_u_b(q2_asub_q1_m, mask_out); \
+ mask_out = (limit_in < mask_out); \
+ mask_out = __msa_xori_b(mask_out, 0xff); \
+} while (0)
+
+#define ST6x1_UB(in0, in0_idx, in1, in1_idx, pdst, stride) do { \
+ const uint16_t tmp0_h = __msa_copy_s_h((v8i16)in1, in1_idx); \
+ const uint32_t tmp0_w = __msa_copy_s_w((v4i32)in0, in0_idx); \
+ SW(tmp0_w, pdst); \
+ SH(tmp0_h, pdst + stride); \
+} while (0)
+
+#define ST6x4_UB(in0, start_in0_idx, in1, start_in1_idx, pdst, stride) do { \
+ uint8_t* ptmp1 = (uint8_t*)pdst; \
+ ST6x1_UB(in0, start_in0_idx, in1, start_in1_idx, ptmp1, 4); \
+ ptmp1 += stride; \
+ ST6x1_UB(in0, start_in0_idx + 1, in1, start_in1_idx + 1, ptmp1, 4); \
+ ptmp1 += stride; \
+ ST6x1_UB(in0, start_in0_idx + 2, in1, start_in1_idx + 2, ptmp1, 4); \
+ ptmp1 += stride; \
+ ST6x1_UB(in0, start_in0_idx + 3, in1, start_in1_idx + 3, ptmp1, 4); \
+} while (0)
+
+#define LPF_SIMPLE_FILT(p1_in, p0_in, q0_in, q1_in, mask) do { \
+ v16i8 p1_m, p0_m, q0_m, q1_m, filt, filt1, filt2; \
+ const v16i8 cnst4b = __msa_ldi_b(4); \
+ const v16i8 cnst3b = __msa_ldi_b(3); \
+ \
+ FLIP_SIGN4(p1_in, p0_in, q0_in, q1_in, p1_m, p0_m, q0_m, q1_m); \
+ filt = __msa_subs_s_b(p1_m, q1_m); \
+ FILT_VAL(q0_m, p0_m, mask, filt); \
+ filt1 = __msa_adds_s_b(filt, cnst4b); \
+ filt1 = SRAI_B(filt1, 3); \
+ filt2 = __msa_adds_s_b(filt, cnst3b); \
+ filt2 = SRAI_B(filt2, 3); \
+ q0_m = __msa_subs_s_b(q0_m, filt1); \
+ p0_m = __msa_adds_s_b(p0_m, filt2); \
+ q0_in = __msa_xori_b((v16u8)q0_m, 0x80); \
+ p0_in = __msa_xori_b((v16u8)p0_m, 0x80); \
+} while (0)
+
+#define LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask) do { \
+ v16u8 p1_a_sub_q1, p0_a_sub_q0; \
+ \
+ p0_a_sub_q0 = __msa_asub_u_b(p0, q0); \
+ p1_a_sub_q1 = __msa_asub_u_b(p1, q1); \
+ p1_a_sub_q1 = (v16u8)__msa_srli_b((v16i8)p1_a_sub_q1, 1); \
+ p0_a_sub_q0 = __msa_adds_u_b(p0_a_sub_q0, p0_a_sub_q0); \
+ mask = __msa_adds_u_b(p0_a_sub_q0, p1_a_sub_q1); \
+ mask = (mask <= b_limit); \
+} while (0)
+
+static void VFilter16(uint8_t* src, int stride,
+ int b_limit_in, int limit_in, int thresh_in) {
+ uint8_t* ptemp = src - 4 * stride;
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
+ v16u8 mask, hev;
+ const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
+ const v16u8 limit = (v16u8)__msa_fill_b(limit_in);
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+
+ LD_UB8(ptemp, stride, p3, p2, p1, p0, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
+ hev, mask);
+ LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
+ ptemp = src - 3 * stride;
+ ST_UB4(p2, p1, p0, q0, ptemp, stride);
+ ptemp += (4 * stride);
+ ST_UB2(q1, q2, ptemp, stride);
+}
+
+static void HFilter16(uint8_t* src, int stride,
+ int b_limit_in, int limit_in, int thresh_in) {
+ uint8_t* ptmp = src - 4;
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
+ v16u8 mask, hev;
+ v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8;
+ v16u8 row9, row10, row11, row12, row13, row14, row15;
+ v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+ const v16u8 limit = (v16u8)__msa_fill_b(limit_in);
+ const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
+
+ LD_UB8(ptmp, stride, row0, row1, row2, row3, row4, row5, row6, row7);
+ ptmp += (8 * stride);
+ LD_UB8(ptmp, stride, row8, row9, row10, row11, row12, row13, row14, row15);
+ TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
+ row8, row9, row10, row11, row12, row13, row14, row15,
+ p3, p2, p1, p0, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
+ hev, mask);
+ LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
+ ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
+ ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4);
+ ILVL_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
+ ILVRL_H2_SH(tmp1, tmp0, tmp6, tmp7);
+ ILVRL_B2_SH(q2, q1, tmp2, tmp5);
+ ptmp = src - 3;
+ ST6x1_UB(tmp3, 0, tmp2, 0, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp3, 1, tmp2, 1, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp3, 2, tmp2, 2, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp3, 3, tmp2, 3, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp4, 0, tmp2, 4, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp4, 1, tmp2, 5, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp4, 2, tmp2, 6, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp4, 3, tmp2, 7, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp6, 0, tmp5, 0, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp6, 1, tmp5, 1, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp6, 2, tmp5, 2, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp6, 3, tmp5, 3, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp7, 0, tmp5, 4, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp7, 1, tmp5, 5, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp7, 2, tmp5, 6, ptmp, 4);
+ ptmp += stride;
+ ST6x1_UB(tmp7, 3, tmp5, 7, ptmp, 4);
+}
+
+// on three inner edges
+static void VFilterHorEdge16i(uint8_t* src, int stride,
+ int b_limit, int limit, int thresh) {
+ v16u8 mask, hev;
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
+ const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh);
+ const v16u8 b_limit0 = (v16u8)__msa_fill_b(b_limit);
+ const v16u8 limit0 = (v16u8)__msa_fill_b(limit);
+
+ LD_UB8((src - 4 * stride), stride, p3, p2, p1, p0, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0,
+ hev, mask);
+ LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
+ ST_UB4(p1, p0, q0, q1, (src - 2 * stride), stride);
+}
+
+static void VFilter16i(uint8_t* src_y, int stride,
+ int b_limit, int limit, int thresh) {
+ VFilterHorEdge16i(src_y + 4 * stride, stride, b_limit, limit, thresh);
+ VFilterHorEdge16i(src_y + 8 * stride, stride, b_limit, limit, thresh);
+ VFilterHorEdge16i(src_y + 12 * stride, stride, b_limit, limit, thresh);
+}
+
+static void HFilterVertEdge16i(uint8_t* src, int stride,
+ int b_limit, int limit, int thresh) {
+ v16u8 mask, hev;
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0;
+ v16u8 row0, row1, row2, row3, row4, row5, row6, row7;
+ v16u8 row8, row9, row10, row11, row12, row13, row14, row15;
+ v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ const v16u8 thresh0 = (v16u8)__msa_fill_b(thresh);
+ const v16u8 b_limit0 = (v16u8)__msa_fill_b(b_limit);
+ const v16u8 limit0 = (v16u8)__msa_fill_b(limit);
+
+ LD_UB8(src - 4, stride, row0, row1, row2, row3, row4, row5, row6, row7);
+ LD_UB8(src - 4 + (8 * stride), stride,
+ row8, row9, row10, row11, row12, row13, row14, row15);
+ TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
+ row8, row9, row10, row11, row12, row13, row14, row15,
+ p3, p2, p1, p0, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0,
+ hev, mask);
+ LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
+ ILVR_B2_SH(p0, p1, q1, q0, tmp0, tmp1);
+ ILVRL_H2_SH(tmp1, tmp0, tmp2, tmp3);
+ ILVL_B2_SH(p0, p1, q1, q0, tmp0, tmp1);
+ ILVRL_H2_SH(tmp1, tmp0, tmp4, tmp5);
+ src -= 2;
+ ST4x8_UB(tmp2, tmp3, src, stride);
+ src += (8 * stride);
+ ST4x8_UB(tmp4, tmp5, src, stride);
+}
+
+static void HFilter16i(uint8_t* src_y, int stride,
+ int b_limit, int limit, int thresh) {
+ HFilterVertEdge16i(src_y + 4, stride, b_limit, limit, thresh);
+ HFilterVertEdge16i(src_y + 8, stride, b_limit, limit, thresh);
+ HFilterVertEdge16i(src_y + 12, stride, b_limit, limit, thresh);
+}
+
+// 8-pixels wide variants, for chroma filtering
+static void VFilter8(uint8_t* src_u, uint8_t* src_v, int stride,
+ int b_limit_in, int limit_in, int thresh_in) {
+ uint8_t* ptmp_src_u = src_u - 4 * stride;
+ uint8_t* ptmp_src_v = src_v - 4 * stride;
+ uint64_t p2_d, p1_d, p0_d, q0_d, q1_d, q2_d;
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
+ v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u;
+ v16u8 p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v;
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+ const v16u8 limit = (v16u8)__msa_fill_b(limit_in);
+ const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
+
+ LD_UB8(ptmp_src_u, stride, p3_u, p2_u, p1_u, p0_u, q0_u, q1_u, q2_u, q3_u);
+ LD_UB8(ptmp_src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v);
+ ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0);
+ ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
+ hev, mask);
+ LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
+ p2_d = __msa_copy_s_d((v2i64)p2, 0);
+ p1_d = __msa_copy_s_d((v2i64)p1, 0);
+ p0_d = __msa_copy_s_d((v2i64)p0, 0);
+ q0_d = __msa_copy_s_d((v2i64)q0, 0);
+ q1_d = __msa_copy_s_d((v2i64)q1, 0);
+ q2_d = __msa_copy_s_d((v2i64)q2, 0);
+ ptmp_src_u += stride;
+ SD4(p2_d, p1_d, p0_d, q0_d, ptmp_src_u, stride);
+ ptmp_src_u += (4 * stride);
+ SD(q1_d, ptmp_src_u);
+ ptmp_src_u += stride;
+ SD(q2_d, ptmp_src_u);
+ p2_d = __msa_copy_s_d((v2i64)p2, 1);
+ p1_d = __msa_copy_s_d((v2i64)p1, 1);
+ p0_d = __msa_copy_s_d((v2i64)p0, 1);
+ q0_d = __msa_copy_s_d((v2i64)q0, 1);
+ q1_d = __msa_copy_s_d((v2i64)q1, 1);
+ q2_d = __msa_copy_s_d((v2i64)q2, 1);
+ ptmp_src_v += stride;
+ SD4(p2_d, p1_d, p0_d, q0_d, ptmp_src_v, stride);
+ ptmp_src_v += (4 * stride);
+ SD(q1_d, ptmp_src_v);
+ ptmp_src_v += stride;
+ SD(q2_d, ptmp_src_v);
+}
+
+static void HFilter8(uint8_t* src_u, uint8_t* src_v, int stride,
+ int b_limit_in, int limit_in, int thresh_in) {
+ uint8_t* ptmp_src_u = src_u - 4;
+ uint8_t* ptmp_src_v = src_v - 4;
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
+ v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8;
+ v16u8 row9, row10, row11, row12, row13, row14, row15;
+ v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+ const v16u8 limit = (v16u8)__msa_fill_b(limit_in);
+ const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
+
+ LD_UB8(ptmp_src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7);
+ LD_UB8(ptmp_src_v, stride,
+ row8, row9, row10, row11, row12, row13, row14, row15);
+ TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
+ row8, row9, row10, row11, row12, row13, row14, row15,
+ p3, p2, p1, p0, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
+ hev, mask);
+ LPF_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev);
+ ILVR_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
+ ILVRL_H2_SH(tmp1, tmp0, tmp3, tmp4);
+ ILVL_B2_SH(p1, p2, q0, p0, tmp0, tmp1);
+ ILVRL_H2_SH(tmp1, tmp0, tmp6, tmp7);
+ ILVRL_B2_SH(q2, q1, tmp2, tmp5);
+ ptmp_src_u += 1;
+ ST6x4_UB(tmp3, 0, tmp2, 0, ptmp_src_u, stride);
+ ptmp_src_u += 4 * stride;
+ ST6x4_UB(tmp4, 0, tmp2, 4, ptmp_src_u, stride);
+ ptmp_src_v += 1;
+ ST6x4_UB(tmp6, 0, tmp5, 0, ptmp_src_v, stride);
+ ptmp_src_v += 4 * stride;
+ ST6x4_UB(tmp7, 0, tmp5, 4, ptmp_src_v, stride);
+}
+
+static void VFilter8i(uint8_t* src_u, uint8_t* src_v, int stride,
+ int b_limit_in, int limit_in, int thresh_in) {
+ uint64_t p1_d, p0_d, q0_d, q1_d;
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
+ v16u8 p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u;
+ v16u8 p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v;
+ const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
+ const v16u8 limit = (v16u8)__msa_fill_b(limit_in);
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+
+ LD_UB8(src_u, stride, p3_u, p2_u, p1_u, p0_u, q0_u, q1_u, q2_u, q3_u);
+ src_u += (5 * stride);
+ LD_UB8(src_v, stride, p3_v, p2_v, p1_v, p0_v, q0_v, q1_v, q2_v, q3_v);
+ src_v += (5 * stride);
+ ILVR_D4_UB(p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0);
+ ILVR_D4_UB(q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
+ hev, mask);
+ LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
+ p1_d = __msa_copy_s_d((v2i64)p1, 0);
+ p0_d = __msa_copy_s_d((v2i64)p0, 0);
+ q0_d = __msa_copy_s_d((v2i64)q0, 0);
+ q1_d = __msa_copy_s_d((v2i64)q1, 0);
+ SD4(q1_d, q0_d, p0_d, p1_d, src_u, -stride);
+ p1_d = __msa_copy_s_d((v2i64)p1, 1);
+ p0_d = __msa_copy_s_d((v2i64)p0, 1);
+ q0_d = __msa_copy_s_d((v2i64)q0, 1);
+ q1_d = __msa_copy_s_d((v2i64)q1, 1);
+ SD4(q1_d, q0_d, p0_d, p1_d, src_v, -stride);
+}
+
+static void HFilter8i(uint8_t* src_u, uint8_t* src_v, int stride,
+ int b_limit_in, int limit_in, int thresh_in) {
+ v16u8 p3, p2, p1, p0, q3, q2, q1, q0, mask, hev;
+ v16u8 row0, row1, row2, row3, row4, row5, row6, row7, row8;
+ v16u8 row9, row10, row11, row12, row13, row14, row15;
+ v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ const v16u8 thresh = (v16u8)__msa_fill_b(thresh_in);
+ const v16u8 limit = (v16u8)__msa_fill_b(limit_in);
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+
+ LD_UB8(src_u, stride, row0, row1, row2, row3, row4, row5, row6, row7);
+ LD_UB8(src_v, stride,
+ row8, row9, row10, row11, row12, row13, row14, row15);
+ TRANSPOSE16x8_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
+ row8, row9, row10, row11, row12, row13, row14, row15,
+ p3, p2, p1, p0, q0, q1, q2, q3);
+ LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh,
+ hev, mask);
+ LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev);
+ ILVR_B2_SW(p0, p1, q1, q0, tmp0, tmp1);
+ ILVRL_H2_SW(tmp1, tmp0, tmp2, tmp3);
+ ILVL_B2_SW(p0, p1, q1, q0, tmp0, tmp1);
+ ILVRL_H2_SW(tmp1, tmp0, tmp4, tmp5);
+ src_u += 2;
+ ST4x4_UB(tmp2, tmp2, 0, 1, 2, 3, src_u, stride);
+ src_u += 4 * stride;
+ ST4x4_UB(tmp3, tmp3, 0, 1, 2, 3, src_u, stride);
+ src_v += 2;
+ ST4x4_UB(tmp4, tmp4, 0, 1, 2, 3, src_v, stride);
+ src_v += 4 * stride;
+ ST4x4_UB(tmp5, tmp5, 0, 1, 2, 3, src_v, stride);
+}
+
+static void SimpleVFilter16(uint8_t* src, int stride, int b_limit_in) {
+ v16u8 p1, p0, q1, q0, mask;
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+
+ LD_UB4(src - 2 * stride, stride, p1, p0, q0, q1);
+ LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask);
+ LPF_SIMPLE_FILT(p1, p0, q0, q1, mask);
+ ST_UB2(p0, q0, src - stride, stride);
+}
+
+static void SimpleHFilter16(uint8_t* src, int stride, int b_limit_in) {
+ v16u8 p1, p0, q1, q0, mask, row0, row1, row2, row3, row4, row5, row6, row7;
+ v16u8 row8, row9, row10, row11, row12, row13, row14, row15;
+ v8i16 tmp0, tmp1;
+ const v16u8 b_limit = (v16u8)__msa_fill_b(b_limit_in);
+ uint8_t* ptemp_src = src - 2;
+
+ LD_UB8(ptemp_src, stride, row0, row1, row2, row3, row4, row5, row6, row7);
+ LD_UB8(ptemp_src + 8 * stride, stride,
+ row8, row9, row10, row11, row12, row13, row14, row15);
+ TRANSPOSE16x4_UB_UB(row0, row1, row2, row3, row4, row5, row6, row7,
+ row8, row9, row10, row11, row12, row13, row14, row15,
+ p1, p0, q0, q1);
+ LPF_SIMPLE_MASK(p1, p0, q0, q1, b_limit, mask);
+ LPF_SIMPLE_FILT(p1, p0, q0, q1, mask);
+ ILVRL_B2_SH(q0, p0, tmp1, tmp0);
+ ptemp_src += 1;
+ ST2x4_UB(tmp1, 0, ptemp_src, stride);
+ ptemp_src += 4 * stride;
+ ST2x4_UB(tmp1, 4, ptemp_src, stride);
+ ptemp_src += 4 * stride;
+ ST2x4_UB(tmp0, 0, ptemp_src, stride);
+ ptemp_src += 4 * stride;
+ ST2x4_UB(tmp0, 4, ptemp_src, stride);
+ ptemp_src += 4 * stride;
+}
+
+static void SimpleVFilter16i(uint8_t* src_y, int stride, int b_limit_in) {
+ SimpleVFilter16(src_y + 4 * stride, stride, b_limit_in);
+ SimpleVFilter16(src_y + 8 * stride, stride, b_limit_in);
+ SimpleVFilter16(src_y + 12 * stride, stride, b_limit_in);
+}
+
+static void SimpleHFilter16i(uint8_t* src_y, int stride, int b_limit_in) {
+ SimpleHFilter16(src_y + 4, stride, b_limit_in);
+ SimpleHFilter16(src_y + 8, stride, b_limit_in);
+ SimpleHFilter16(src_y + 12, stride, b_limit_in);
+}
+
+//------------------------------------------------------------------------------
+// Intra predictions
+//------------------------------------------------------------------------------
+
+// 4x4
+
+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;
+ dc = dc | (dc << 8) | (dc << 16) | (dc << 24);
+ SW4(dc, dc, dc, dc, dst, BPS);
+}
+
+static void TM4(uint8_t* dst) {
+ const uint8_t* const ptemp = dst - BPS - 1;
+ v8i16 T, d, r0, r1, r2, r3;
+ const v16i8 zero = { 0 };
+ const v8i16 TL = (v8i16)__msa_fill_h(ptemp[0 * BPS]);
+ const v8i16 L0 = (v8i16)__msa_fill_h(ptemp[1 * BPS]);
+ const v8i16 L1 = (v8i16)__msa_fill_h(ptemp[2 * BPS]);
+ const v8i16 L2 = (v8i16)__msa_fill_h(ptemp[3 * BPS]);
+ const v8i16 L3 = (v8i16)__msa_fill_h(ptemp[4 * BPS]);
+ const v16u8 T1 = LD_UB(ptemp + 1);
+
+ T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1);
+ d = T - TL;
+ ADD4(d, L0, d, L1, d, L2, d, L3, r0, r1, r2, r3);
+ CLIP_SH4_0_255(r0, r1, r2, r3);
+ PCKEV_ST4x4_UB(r0, r1, r2, r3, dst, BPS);
+}
+
+static void VE4(uint8_t* dst) { // vertical
+ const uint8_t* const ptop = dst - BPS - 1;
+ const uint32_t val0 = LW(ptop + 0);
+ const uint32_t val1 = LW(ptop + 4);
+ uint32_t out;
+ v16u8 A, B, C, AC, B2, R;
+
+ INSERT_W2_UB(val0, val1, A);
+ B = SLDI_UB(A, A, 1);
+ C = SLDI_UB(A, A, 2);
+ AC = __msa_ave_u_b(A, C);
+ B2 = __msa_ave_u_b(B, B);
+ R = __msa_aver_u_b(AC, B2);
+ out = __msa_copy_s_w((v4i32)R, 0);
+ SW4(out, out, out, out, dst, BPS);
+}
+
+static void RD4(uint8_t* dst) { // Down-right
+ const uint8_t* const ptop = dst - 1 - BPS;
+ uint32_t val0 = LW(ptop + 0);
+ uint32_t val1 = LW(ptop + 4);
+ uint32_t val2, val3;
+ v16u8 A, B, C, AC, B2, R, A1;
+
+ INSERT_W2_UB(val0, val1, A1);
+ A = SLDI_UB(A1, A1, 12);
+ A = (v16u8)__msa_insert_b((v16i8)A, 3, ptop[1 * BPS]);
+ A = (v16u8)__msa_insert_b((v16i8)A, 2, ptop[2 * BPS]);
+ A = (v16u8)__msa_insert_b((v16i8)A, 1, ptop[3 * BPS]);
+ A = (v16u8)__msa_insert_b((v16i8)A, 0, ptop[4 * BPS]);
+ B = SLDI_UB(A, A, 1);
+ C = SLDI_UB(A, A, 2);
+ AC = __msa_ave_u_b(A, C);
+ B2 = __msa_ave_u_b(B, B);
+ R = __msa_aver_u_b(AC, B2);
+ val3 = __msa_copy_s_w((v4i32)R, 0);
+ R = SLDI_UB(R, R, 1);
+ val2 = __msa_copy_s_w((v4i32)R, 0);
+ R = SLDI_UB(R, R, 1);
+ val1 = __msa_copy_s_w((v4i32)R, 0);
+ R = SLDI_UB(R, R, 1);
+ val0 = __msa_copy_s_w((v4i32)R, 0);
+ SW4(val0, val1, val2, val3, dst, BPS);
+}
+
+static void LD4(uint8_t* dst) { // Down-Left
+ const uint8_t* const ptop = dst - BPS;
+ uint32_t val0 = LW(ptop + 0);
+ uint32_t val1 = LW(ptop + 4);
+ uint32_t val2, val3;
+ v16u8 A, B, C, AC, B2, R;
+
+ INSERT_W2_UB(val0, val1, A);
+ B = SLDI_UB(A, A, 1);
+ C = SLDI_UB(A, A, 2);
+ C = (v16u8)__msa_insert_b((v16i8)C, 6, ptop[7]);
+ AC = __msa_ave_u_b(A, C);
+ B2 = __msa_ave_u_b(B, B);
+ R = __msa_aver_u_b(AC, B2);
+ val0 = __msa_copy_s_w((v4i32)R, 0);
+ R = SLDI_UB(R, R, 1);
+ val1 = __msa_copy_s_w((v4i32)R, 0);
+ R = SLDI_UB(R, R, 1);
+ val2 = __msa_copy_s_w((v4i32)R, 0);
+ R = SLDI_UB(R, R, 1);
+ val3 = __msa_copy_s_w((v4i32)R, 0);
+ SW4(val0, val1, val2, val3, dst, BPS);
+}
+
+// 16x16
+
+static void DC16(uint8_t* dst) { // DC
+ uint32_t dc = 16;
+ int i;
+ const v16u8 rtop = LD_UB(dst - BPS);
+ const v8u16 dctop = __msa_hadd_u_h(rtop, rtop);
+ v16u8 out;
+
+ for (i = 0; i < 16; ++i) {
+ dc += dst[-1 + i * BPS];
+ }
+ dc += HADD_UH_U32(dctop);
+ out = (v16u8)__msa_fill_b(dc >> 5);
+ ST_UB8(out, out, out, out, out, out, out, out, dst, BPS);
+ ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS);
+}
+
+static void TM16(uint8_t* dst) {
+ int j;
+ v8i16 d1, d2;
+ const v16i8 zero = { 0 };
+ const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]);
+ const v16i8 T = LD_SB(dst - BPS);
+
+ ILVRL_B2_SH(zero, T, d1, d2);
+ SUB2(d1, TL, d2, TL, d1, d2);
+ for (j = 0; j < 16; j += 4) {
+ v16i8 t0, t1, t2, t3;
+ v8i16 r0, r1, r2, r3, r4, r5, r6, r7;
+ const v8i16 L0 = (v8i16)__msa_fill_h(dst[-1 + 0 * BPS]);
+ const v8i16 L1 = (v8i16)__msa_fill_h(dst[-1 + 1 * BPS]);
+ const v8i16 L2 = (v8i16)__msa_fill_h(dst[-1 + 2 * BPS]);
+ const v8i16 L3 = (v8i16)__msa_fill_h(dst[-1 + 3 * BPS]);
+ ADD4(d1, L0, d1, L1, d1, L2, d1, L3, r0, r1, r2, r3);
+ ADD4(d2, L0, d2, L1, d2, L2, d2, L3, r4, r5, r6, r7);
+ CLIP_SH4_0_255(r0, r1, r2, r3);
+ CLIP_SH4_0_255(r4, r5, r6, r7);
+ PCKEV_B4_SB(r4, r0, r5, r1, r6, r2, r7, r3, t0, t1, t2, t3);
+ ST_SB4(t0, t1, t2, t3, dst, BPS);
+ dst += 4 * BPS;
+ }
+}
+
+static void VE16(uint8_t* dst) { // vertical
+ const v16u8 rtop = LD_UB(dst - BPS);
+ ST_UB8(rtop, rtop, rtop, rtop, rtop, rtop, rtop, rtop, dst, BPS);
+ ST_UB8(rtop, rtop, rtop, rtop, rtop, rtop, rtop, rtop, dst + 8 * BPS, BPS);
+}
+
+static void HE16(uint8_t* dst) { // horizontal
+ int j;
+ for (j = 16; j > 0; j -= 4) {
+ const v16u8 L0 = (v16u8)__msa_fill_b(dst[-1 + 0 * BPS]);
+ const v16u8 L1 = (v16u8)__msa_fill_b(dst[-1 + 1 * BPS]);
+ const v16u8 L2 = (v16u8)__msa_fill_b(dst[-1 + 2 * BPS]);
+ const v16u8 L3 = (v16u8)__msa_fill_b(dst[-1 + 3 * BPS]);
+ ST_UB4(L0, L1, L2, L3, dst, BPS);
+ dst += 4 * BPS;
+ }
+}
+
+static void DC16NoTop(uint8_t* dst) { // DC with top samples not available
+ int j;
+ uint32_t dc = 8;
+ v16u8 out;
+
+ for (j = 0; j < 16; ++j) {
+ dc += dst[-1 + j * BPS];
+ }
+ out = (v16u8)__msa_fill_b(dc >> 4);
+ ST_UB8(out, out, out, out, out, out, out, out, dst, BPS);
+ ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS);
+}
+
+static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available
+ uint32_t dc = 8;
+ const v16u8 rtop = LD_UB(dst - BPS);
+ const v8u16 dctop = __msa_hadd_u_h(rtop, rtop);
+ v16u8 out;
+
+ dc += HADD_UH_U32(dctop);
+ out = (v16u8)__msa_fill_b(dc >> 4);
+ ST_UB8(out, out, out, out, out, out, out, out, dst, BPS);
+ ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS);
+}
+
+static void DC16NoTopLeft(uint8_t* dst) { // DC with nothing
+ const v16u8 out = (v16u8)__msa_fill_b(0x80);
+ ST_UB8(out, out, out, out, out, out, out, out, dst, BPS);
+ ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS);
+}
+
+// Chroma
+
+#define STORE8x8(out, dst) do { \
+ SD4(out, out, out, out, dst + 0 * BPS, BPS); \
+ SD4(out, out, out, out, dst + 4 * BPS, BPS); \
+} while (0)
+
+static void DC8uv(uint8_t* dst) { // DC
+ uint32_t dc = 8;
+ int i;
+ uint64_t out;
+ const v16u8 rtop = LD_UB(dst - BPS);
+ const v8u16 temp0 = __msa_hadd_u_h(rtop, rtop);
+ const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0);
+ const v2u64 temp2 = __msa_hadd_u_d(temp1, temp1);
+ v16u8 dctemp;
+
+ for (i = 0; i < 8; ++i) {
+ dc += dst[-1 + i * BPS];
+ }
+ dc += __msa_copy_s_w((v4i32)temp2, 0);
+ dctemp = (v16u8)__msa_fill_b(dc >> 4);
+ out = __msa_copy_s_d((v2i64)dctemp, 0);
+ STORE8x8(out, dst);
+}
+
+static void TM8uv(uint8_t* dst) {
+ int j;
+ const v16i8 T1 = LD_SB(dst - BPS);
+ const v16i8 zero = { 0 };
+ const v8i16 T = (v8i16)__msa_ilvr_b(zero, T1);
+ const v8i16 TL = (v8i16)__msa_fill_h(dst[-1 - BPS]);
+ const v8i16 d = T - TL;
+
+ for (j = 0; j < 8; j += 4) {
+ v16i8 t0, t1;
+ v8i16 r0 = (v8i16)__msa_fill_h(dst[-1 + 0 * BPS]);
+ v8i16 r1 = (v8i16)__msa_fill_h(dst[-1 + 1 * BPS]);
+ v8i16 r2 = (v8i16)__msa_fill_h(dst[-1 + 2 * BPS]);
+ v8i16 r3 = (v8i16)__msa_fill_h(dst[-1 + 3 * BPS]);
+ ADD4(d, r0, d, r1, d, r2, d, r3, r0, r1, r2, r3);
+ CLIP_SH4_0_255(r0, r1, r2, r3);
+ PCKEV_B2_SB(r1, r0, r3, r2, t0, t1);
+ ST4x4_UB(t0, t1, 0, 2, 0, 2, dst, BPS);
+ ST4x4_UB(t0, t1, 1, 3, 1, 3, dst + 4, BPS);
+ dst += 4 * BPS;
+ }
+}
+
+static void VE8uv(uint8_t* dst) { // vertical
+ const v16u8 rtop = LD_UB(dst - BPS);
+ const uint64_t out = __msa_copy_s_d((v2i64)rtop, 0);
+ STORE8x8(out, dst);
+}
+
+static void HE8uv(uint8_t* dst) { // horizontal
+ int j;
+ for (j = 0; j < 8; j += 4) {
+ const v16u8 L0 = (v16u8)__msa_fill_b(dst[-1 + 0 * BPS]);
+ const v16u8 L1 = (v16u8)__msa_fill_b(dst[-1 + 1 * BPS]);
+ const v16u8 L2 = (v16u8)__msa_fill_b(dst[-1 + 2 * BPS]);
+ const v16u8 L3 = (v16u8)__msa_fill_b(dst[-1 + 3 * BPS]);
+ const uint64_t out0 = __msa_copy_s_d((v2i64)L0, 0);
+ const uint64_t out1 = __msa_copy_s_d((v2i64)L1, 0);
+ const uint64_t out2 = __msa_copy_s_d((v2i64)L2, 0);
+ const uint64_t out3 = __msa_copy_s_d((v2i64)L3, 0);
+ SD4(out0, out1, out2, out3, dst, BPS);
+ dst += 4 * BPS;
+ }
+}
+
+static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples
+ const uint32_t dc = 4;
+ const v16u8 rtop = LD_UB(dst - BPS);
+ const v8u16 temp0 = __msa_hadd_u_h(rtop, rtop);
+ const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0);
+ const v2u64 temp2 = __msa_hadd_u_d(temp1, temp1);
+ const uint32_t sum_m = __msa_copy_s_w((v4i32)temp2, 0);
+ const v16u8 dcval = (v16u8)__msa_fill_b((dc + sum_m) >> 3);
+ const uint64_t out = __msa_copy_s_d((v2i64)dcval, 0);
+ STORE8x8(out, dst);
+}
+
+static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples
+ uint32_t dc = 4;
+ int i;
+ uint64_t out;
+ v16u8 dctemp;
+
+ for (i = 0; i < 8; ++i) {
+ dc += dst[-1 + i * BPS];
+ }
+ dctemp = (v16u8)__msa_fill_b(dc >> 3);
+ out = __msa_copy_s_d((v2i64)dctemp, 0);
+ STORE8x8(out, dst);
+}
+
+static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing
+ const uint64_t out = 0x8080808080808080ULL;
+ STORE8x8(out, dst);
+}
+
+//------------------------------------------------------------------------------
// Entry point
extern void VP8DspInitMSA(void);
@@ -163,6 +977,39 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitMSA(void) {
VP8Transform = TransformTwo;
VP8TransformDC = TransformDC;
VP8TransformAC3 = TransformAC3;
+
+ VP8VFilter16 = VFilter16;
+ VP8HFilter16 = HFilter16;
+ VP8VFilter16i = VFilter16i;
+ VP8HFilter16i = HFilter16i;
+ VP8VFilter8 = VFilter8;
+ VP8HFilter8 = HFilter8;
+ VP8VFilter8i = VFilter8i;
+ VP8HFilter8i = HFilter8i;
+ 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] = 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_MSA
diff --git a/thirdparty/libwebp/dsp/dec_neon.c b/thirdparty/libwebp/dsp/dec_neon.c
index a63f43fe17..34796cf4a2 100644
--- a/thirdparty/libwebp/dsp/dec_neon.c
+++ b/thirdparty/libwebp/dsp/dec_neon.c
@@ -17,7 +17,7 @@
#if defined(WEBP_USE_NEON)
#include "./neon.h"
-#include "../dec/vp8i.h"
+#include "../dec/vp8i_dec.h"
//------------------------------------------------------------------------------
// NxM Loading functions
@@ -666,9 +666,8 @@ static uint8x16_t NeedsHev(const uint8x16_t p1, const uint8x16_t p0,
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);
+ const uint8x16_t a_max = vmaxq_u8(a_p1_p0, a_q1_q0);
+ const uint8x16_t mask = vcgtq_u8(a_max, hev_thresh_v);
return mask;
}
@@ -756,24 +755,25 @@ static void ApplyFilter6(
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);
+ // We have to compute: X = (9*a+63) >> 7, Y = (18*a+63)>>7, Z = (27*a+63) >> 7
+ // Turns out, there's a common sub-expression S=9 * a - 1 that can be used
+ // with the special vqrshrn_n_s16 rounding-shift-and-narrow instruction:
+ // X = (S + 64) >> 7, Y = (S + 32) >> 6, Z = (18 * a + S + 64) >> 7
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 int8x8_t kCst9 = vdup_n_s8(9);
+ const int16x8_t kCstm1 = vdupq_n_s16(-1);
+ const int8x8_t kCst18 = vdup_n_s8(18);
+ const int16x8_t S_lo = vmlal_s8(kCstm1, kCst9, delta_lo); // S = 9 * a - 1
+ const int16x8_t S_hi = vmlal_s8(kCstm1, kCst9, delta_hi);
+ const int16x8_t Z_lo = vmlal_s8(S_lo, kCst18, delta_lo); // S + 18 * a
+ const int16x8_t Z_hi = vmlal_s8(S_hi, kCst18, delta_hi);
+ const int8x8_t a3_lo = vqrshrn_n_s16(S_lo, 7); // (9 * a + 63) >> 7
+ const int8x8_t a3_hi = vqrshrn_n_s16(S_hi, 7);
+ const int8x8_t a2_lo = vqrshrn_n_s16(S_lo, 6); // (9 * a + 31) >> 6
+ const int8x8_t a2_hi = vqrshrn_n_s16(S_hi, 6);
+ const int8x8_t a1_lo = vqrshrn_n_s16(Z_lo, 7); // (27 * a + 63) >> 7
+ const int8x8_t a1_hi = vqrshrn_n_s16(Z_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);
diff --git a/thirdparty/libwebp/dsp/dec_sse2.c b/thirdparty/libwebp/dsp/dec_sse2.c
index f0a8ddcaf3..411fb02768 100644
--- a/thirdparty/libwebp/dsp/dec_sse2.c
+++ b/thirdparty/libwebp/dsp/dec_sse2.c
@@ -22,7 +22,7 @@
#include <emmintrin.h>
#include "./common_sse2.h"
-#include "../dec/vp8i.h"
+#include "../dec/vp8i_dec.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
@@ -140,7 +140,7 @@ static void Transform(const int16_t* in, uint8_t* dst, int do_two) {
// Transpose the two 4x4.
VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1,
- &T2, &T3);
+ &T2, &T3);
}
// Add inverse transform to 'dst' and store.
diff --git a/thirdparty/libwebp/dsp/dec_sse41.c b/thirdparty/libwebp/dsp/dec_sse41.c
index 8d6aed13e6..4e81ec4d80 100644
--- a/thirdparty/libwebp/dsp/dec_sse41.c
+++ b/thirdparty/libwebp/dsp/dec_sse41.c
@@ -16,7 +16,7 @@
#if defined(WEBP_USE_SSE41)
#include <smmintrin.h>
-#include "../dec/vp8i.h"
+#include "../dec/vp8i_dec.h"
#include "../utils/utils.h"
static void HE16(uint8_t* dst) { // horizontal
diff --git a/thirdparty/libwebp/dsp/dsp.h b/thirdparty/libwebp/dsp/dsp.h
index 1faac27b2b..813fed4a35 100644
--- a/thirdparty/libwebp/dsp/dsp.h
+++ b/thirdparty/libwebp/dsp/dsp.h
@@ -111,8 +111,7 @@ extern "C" {
#define WEBP_UBSAN_IGNORE_UNDEF
#define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
-#if !defined(WEBP_FORCE_ALIGNED) && defined(__clang__) && \
- defined(__has_attribute)
+#if defined(__clang__) && defined(__has_attribute)
#if __has_attribute(no_sanitize)
// This macro prevents the undefined behavior sanitizer from reporting
// failures. This is only meant to silence unaligned loads on platforms that
@@ -133,6 +132,7 @@ extern "C" {
typedef enum {
kSSE2,
kSSE3,
+ kSlowSSSE3, // special feature for slow SSSE3 architectures
kSSE4_1,
kAVX,
kAVX2,
@@ -185,6 +185,11 @@ typedef int (*VP8WMetric)(const uint8_t* pix, const uint8_t* ref,
// 4 by 4 symmetric matrix.
extern VP8WMetric VP8TDisto4x4, VP8TDisto16x16;
+// Compute the average (DC) of four 4x4 blocks.
+// Each sub-4x4 block #i sum is stored in dc[i].
+typedef void (*VP8MeanMetric)(const uint8_t* ref, uint32_t dc[4]);
+extern VP8MeanMetric VP8Mean16x4;
+
typedef void (*VP8BlockCopy)(const uint8_t* src, uint8_t* dst);
extern VP8BlockCopy VP8Copy4x4;
extern VP8BlockCopy VP8Copy16x8;
@@ -246,30 +251,37 @@ extern VP8GetResidualCostFunc VP8GetResidualCost;
void VP8EncDspCostInit(void);
//------------------------------------------------------------------------------
-// SSIM utils
+// SSIM / PSNR utils
// struct for accumulating statistical moments
typedef struct {
- double w; // sum(w_i) : sum of weights
- double xm, ym; // sum(w_i * x_i), sum(w_i * y_i)
- double xxm, xym, yym; // sum(w_i * x_i * x_i), etc.
+ uint32_t w; // sum(w_i) : sum of weights
+ uint32_t xm, ym; // sum(w_i * x_i), sum(w_i * y_i)
+ uint32_t xxm, xym, yym; // sum(w_i * x_i * x_i), etc.
} VP8DistoStats;
+// Compute the final SSIM value
+// The non-clipped version assumes stats->w = (2 * VP8_SSIM_KERNEL + 1)^2.
+double VP8SSIMFromStats(const VP8DistoStats* const stats);
+double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats);
+
#define VP8_SSIM_KERNEL 3 // total size of the kernel: 2 * VP8_SSIM_KERNEL + 1
-typedef void (*VP8SSIMAccumulateClippedFunc)(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int xo, int yo, // center position
- int W, int H, // plane dimension
- VP8DistoStats* const stats);
+typedef double (*VP8SSIMGetClippedFunc)(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2,
+ int xo, int yo, // center position
+ int W, int H); // plane dimension
// This version is called with the guarantee that you can load 8 bytes and
// 8 rows at offset src1 and src2
-typedef void (*VP8SSIMAccumulateFunc)(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- VP8DistoStats* const stats);
+typedef double (*VP8SSIMGetFunc)(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2);
+
+extern VP8SSIMGetFunc VP8SSIMGet; // unclipped / unchecked
+extern VP8SSIMGetClippedFunc VP8SSIMGetClipped; // with clipping
-extern VP8SSIMAccumulateFunc VP8SSIMAccumulate; // unclipped / unchecked
-extern VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped; // with clipping
+typedef uint32_t (*VP8AccumulateSSEFunc)(const uint8_t* src1,
+ const uint8_t* src2, int len);
+extern VP8AccumulateSSEFunc VP8AccumulateSSE;
// must be called before using any of the above directly
void VP8SSIMDspInit(void);
@@ -416,6 +428,15 @@ extern void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v,
extern void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
uint8_t* u, uint8_t* v, int width);
+// utilities for accurate RGB->YUV conversion
+extern uint64_t (*WebPSharpYUVUpdateY)(const uint16_t* src, const uint16_t* ref,
+ uint16_t* dst, int len);
+extern void (*WebPSharpYUVUpdateRGB)(const int16_t* src, const int16_t* ref,
+ int16_t* dst, int len);
+extern void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B,
+ int len,
+ const uint16_t* best_y, uint16_t* out);
+
// Must be called before using the above.
void WebPInitConvertARGBToYUV(void);
@@ -488,6 +509,10 @@ extern int (*WebPExtractAlpha)(const uint8_t* argb, int argb_stride,
int width, int height,
uint8_t* alpha, int alpha_stride);
+// Extract the green values from 32b values in argb[] and pack them into alpha[]
+// (this is the opposite of WebPDispatchAlphaToGreen).
+extern void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size);
+
// 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.
diff --git a/thirdparty/libwebp/dsp/enc.c b/thirdparty/libwebp/dsp/enc.c
index db0e9e70ae..f31bc6de18 100644
--- a/thirdparty/libwebp/dsp/enc.c
+++ b/thirdparty/libwebp/dsp/enc.c
@@ -15,7 +15,7 @@
#include <stdlib.h> // for abs()
#include "./dsp.h"
-#include "../enc/vp8enci.h"
+#include "../enc/vp8i_enc.h"
static WEBP_INLINE uint8_t clip_8b(int v) {
return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255;
@@ -551,6 +551,20 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) {
return GetSSE(a, b, 4, 4);
}
+static void Mean16x4(const uint8_t* ref, uint32_t dc[4]) {
+ int k, x, y;
+ for (k = 0; k < 4; ++k) {
+ uint32_t avg = 0;
+ for (y = 0; y < 4; ++y) {
+ for (x = 0; x < 4; ++x) {
+ avg += ref[x + y * BPS];
+ }
+ }
+ dc[k] = avg;
+ ref += 4; // go to next 4x4 block.
+ }
+}
+
//------------------------------------------------------------------------------
// Texture distortion
//
@@ -656,32 +670,6 @@ static int Quantize2Blocks(int16_t in[32], int16_t out[32],
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);
- const uint32_t coeff = sign ? -in[j] : in[j];
- assert(mtx->sharpen_[j] == 0);
- 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 * (int)Q;
- out[n] = level;
- if (level) last = n;
- } else {
- out[n] = 0;
- in[j] = 0;
- }
- }
- return (last >= 0);
-}
-
//------------------------------------------------------------------------------
// Block copy
@@ -703,11 +691,51 @@ static void Copy16x8(const uint8_t* src, uint8_t* dst) {
}
//------------------------------------------------------------------------------
+// SSIM / PSNR
-static void SSIMAccumulateClipped(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int xo, int yo, int W, int H,
- VP8DistoStats* const stats) {
+// hat-shaped filter. Sum of coefficients is equal to 16.
+static const uint32_t kWeight[2 * VP8_SSIM_KERNEL + 1] = {
+ 1, 2, 3, 4, 3, 2, 1
+};
+static const uint32_t kWeightSum = 16 * 16; // sum{kWeight}^2
+
+static WEBP_INLINE double SSIMCalculation(
+ const VP8DistoStats* const stats, uint32_t N /*num samples*/) {
+ const uint32_t w2 = N * N;
+ const uint32_t C1 = 20 * w2;
+ const uint32_t C2 = 60 * w2;
+ const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6
+ const uint64_t xmxm = (uint64_t)stats->xm * stats->xm;
+ const uint64_t ymym = (uint64_t)stats->ym * stats->ym;
+ if (xmxm + ymym >= C3) {
+ const int64_t xmym = (int64_t)stats->xm * stats->ym;
+ const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative
+ const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm;
+ const uint64_t syy = (uint64_t)stats->yym * N - ymym;
+ // we descale by 8 to prevent overflow during the fnum/fden multiply.
+ const uint64_t num_S = (2 * (uint64_t)(sxy < 0 ? 0 : sxy) + C2) >> 8;
+ const uint64_t den_S = (sxx + syy + C2) >> 8;
+ const uint64_t fnum = (2 * xmym + C1) * num_S;
+ const uint64_t fden = (xmxm + ymym + C1) * den_S;
+ const double r = (double)fnum / fden;
+ assert(r >= 0. && r <= 1.0);
+ return r;
+ }
+ return 1.; // area is too dark to contribute meaningfully
+}
+
+double VP8SSIMFromStats(const VP8DistoStats* const stats) {
+ return SSIMCalculation(stats, kWeightSum);
+}
+
+double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats) {
+ return SSIMCalculation(stats, stats->w);
+}
+
+static double SSIMGetClipped_C(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2,
+ int xo, int yo, int W, int H) {
+ VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 };
const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL;
const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1
: yo + VP8_SSIM_KERNEL;
@@ -719,38 +747,61 @@ static void SSIMAccumulateClipped(const uint8_t* src1, int 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;
+ const uint32_t w = kWeight[VP8_SSIM_KERNEL + x - xo]
+ * kWeight[VP8_SSIM_KERNEL + y - yo];
+ const uint32_t s1 = src1[x];
+ const uint32_t s2 = src2[x];
+ stats.w += w;
+ stats.xm += w * s1;
+ stats.ym += w * s2;
+ stats.xxm += w * s1 * s1;
+ stats.xym += w * s1 * s2;
+ stats.yym += w * s2 * s2;
}
}
+ return VP8SSIMFromStatsClipped(&stats);
}
-static void SSIMAccumulate(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- VP8DistoStats* const stats) {
+static double SSIMGet_C(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2) {
+ VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 };
int x, y;
for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) {
for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++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;
+ const uint32_t w = kWeight[x] * kWeight[y];
+ const uint32_t s1 = src1[x];
+ const uint32_t s2 = src2[x];
+ stats.xm += w * s1;
+ stats.ym += w * s2;
+ stats.xxm += w * s1 * s1;
+ stats.xym += w * s1 * s2;
+ stats.yym += w * s2 * s2;
}
}
+ return VP8SSIMFromStats(&stats);
+}
+
+//------------------------------------------------------------------------------
+
+static uint32_t AccumulateSSE(const uint8_t* src1,
+ const uint8_t* src2, int len) {
+ int i;
+ uint32_t sse2 = 0;
+ assert(len <= 65535); // to ensure that accumulation fits within uint32_t
+ for (i = 0; i < len; ++i) {
+ const int32_t diff = src1[i] - src2[i];
+ sse2 += diff * diff;
+ }
+ return sse2;
}
-VP8SSIMAccumulateFunc VP8SSIMAccumulate;
-VP8SSIMAccumulateClippedFunc VP8SSIMAccumulateClipped;
+//------------------------------------------------------------------------------
+
+VP8SSIMGetFunc VP8SSIMGet;
+VP8SSIMGetClippedFunc VP8SSIMGetClipped;
+VP8AccumulateSSEFunc VP8AccumulateSSE;
+
+extern void VP8SSIMDspInitSSE2(void);
static volatile VP8CPUInfo ssim_last_cpuinfo_used =
(VP8CPUInfo)&ssim_last_cpuinfo_used;
@@ -758,8 +809,17 @@ static volatile VP8CPUInfo ssim_last_cpuinfo_used =
WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) {
if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return;
- VP8SSIMAccumulate = SSIMAccumulate;
- VP8SSIMAccumulateClipped = SSIMAccumulateClipped;
+ VP8SSIMGetClipped = SSIMGetClipped_C;
+ VP8SSIMGet = SSIMGet_C;
+
+ VP8AccumulateSSE = AccumulateSSE;
+ if (VP8GetCPUInfo != NULL) {
+#if defined(WEBP_USE_SSE2)
+ if (VP8GetCPUInfo(kSSE2)) {
+ VP8SSIMDspInitSSE2();
+ }
+#endif
+ }
ssim_last_cpuinfo_used = VP8GetCPUInfo;
}
@@ -783,6 +843,7 @@ VP8Metric VP8SSE16x8;
VP8Metric VP8SSE4x4;
VP8WMetric VP8TDisto4x4;
VP8WMetric VP8TDisto16x16;
+VP8MeanMetric VP8Mean16x4;
VP8QuantizeBlock VP8EncQuantizeBlock;
VP8Quantize2Blocks VP8EncQuantize2Blocks;
VP8QuantizeBlockWHT VP8EncQuantizeBlockWHT;
@@ -795,6 +856,7 @@ extern void VP8EncDspInitAVX2(void);
extern void VP8EncDspInitNEON(void);
extern void VP8EncDspInitMIPS32(void);
extern void VP8EncDspInitMIPSdspR2(void);
+extern void VP8EncDspInitMSA(void);
static volatile VP8CPUInfo enc_last_cpuinfo_used =
(VP8CPUInfo)&enc_last_cpuinfo_used;
@@ -820,9 +882,10 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
VP8SSE4x4 = SSE4x4;
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
+ VP8Mean16x4 = Mean16x4;
VP8EncQuantizeBlock = QuantizeBlock;
VP8EncQuantize2Blocks = Quantize2Blocks;
- VP8EncQuantizeBlockWHT = QuantizeBlockWHT;
+ VP8EncQuantizeBlockWHT = QuantizeBlock;
VP8Copy4x4 = Copy4x4;
VP8Copy16x8 = Copy16x8;
@@ -858,6 +921,11 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) {
VP8EncDspInitMIPSdspR2();
}
#endif
+#if defined(WEBP_USE_MSA)
+ if (VP8GetCPUInfo(kMSA)) {
+ VP8EncDspInitMSA();
+ }
+#endif
}
enc_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/dsp/enc_mips32.c b/thirdparty/libwebp/dsp/enc_mips32.c
index fd10143de9..752b14daf6 100644
--- a/thirdparty/libwebp/dsp/enc_mips32.c
+++ b/thirdparty/libwebp/dsp/enc_mips32.c
@@ -18,8 +18,8 @@
#if defined(WEBP_USE_MIPS32)
#include "./mips_macro.h"
-#include "../enc/vp8enci.h"
-#include "../enc/cost.h"
+#include "../enc/vp8i_enc.h"
+#include "../enc/cost_enc.h"
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
diff --git a/thirdparty/libwebp/dsp/enc_mips_dsp_r2.c b/thirdparty/libwebp/dsp/enc_mips_dsp_r2.c
index 7ab96f6800..6c8c1c6acd 100644
--- a/thirdparty/libwebp/dsp/enc_mips_dsp_r2.c
+++ b/thirdparty/libwebp/dsp/enc_mips_dsp_r2.c
@@ -17,8 +17,8 @@
#if defined(WEBP_USE_MIPS_DSP_R2)
#include "./mips_macro.h"
-#include "../enc/cost.h"
-#include "../enc/vp8enci.h"
+#include "../enc/cost_enc.h"
+#include "../enc/vp8i_enc.h"
static const int kC1 = 20091 + (1 << 16);
static const int kC2 = 35468;
diff --git a/thirdparty/libwebp/dsp/enc_msa.c b/thirdparty/libwebp/dsp/enc_msa.c
new file mode 100644
index 0000000000..909b46d5d9
--- /dev/null
+++ b/thirdparty/libwebp/dsp/enc_msa.c
@@ -0,0 +1,892 @@
+// Copyright 2016 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.
+// -----------------------------------------------------------------------------
+//
+// MSA version of encoder dsp functions.
+//
+// Author: Prashant Patil (prashant.patil@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MSA)
+
+#include <stdlib.h>
+#include "./msa_macro.h"
+#include "../enc/vp8i_enc.h"
+
+//------------------------------------------------------------------------------
+// Transforms
+
+#define IDCT_1D_W(in0, in1, in2, in3, out0, out1, out2, out3) do { \
+ v4i32 a1_m, b1_m, c1_m, d1_m; \
+ const v4i32 cospi8sqrt2minus1 = __msa_fill_w(20091); \
+ const v4i32 sinpi8sqrt2 = __msa_fill_w(35468); \
+ v4i32 c_tmp1_m = in1 * sinpi8sqrt2; \
+ v4i32 c_tmp2_m = in3 * cospi8sqrt2minus1; \
+ v4i32 d_tmp1_m = in1 * cospi8sqrt2minus1; \
+ v4i32 d_tmp2_m = in3 * sinpi8sqrt2; \
+ \
+ ADDSUB2(in0, in2, a1_m, b1_m); \
+ SRAI_W2_SW(c_tmp1_m, c_tmp2_m, 16); \
+ c_tmp2_m = c_tmp2_m + in3; \
+ c1_m = c_tmp1_m - c_tmp2_m; \
+ SRAI_W2_SW(d_tmp1_m, d_tmp2_m, 16); \
+ d_tmp1_m = d_tmp1_m + in1; \
+ d1_m = d_tmp1_m + d_tmp2_m; \
+ BUTTERFLY_4(a1_m, b1_m, c1_m, d1_m, out0, out1, out2, out3); \
+} while (0)
+
+static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in,
+ uint8_t* dst) {
+ v8i16 input0, input1;
+ v4i32 in0, in1, in2, in3, hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3;
+ v4i32 res0, res1, res2, res3;
+ v16i8 dest0, dest1, dest2, dest3;
+ const v16i8 zero = { 0 };
+
+ LD_SH2(in, 8, input0, input1);
+ UNPCK_SH_SW(input0, in0, in1);
+ UNPCK_SH_SW(input1, in2, in3);
+ IDCT_1D_W(in0, in1, in2, in3, hz0, hz1, hz2, hz3);
+ TRANSPOSE4x4_SW_SW(hz0, hz1, hz2, hz3, hz0, hz1, hz2, hz3);
+ IDCT_1D_W(hz0, hz1, hz2, hz3, vt0, vt1, vt2, vt3);
+ SRARI_W4_SW(vt0, vt1, vt2, vt3, 3);
+ TRANSPOSE4x4_SW_SW(vt0, vt1, vt2, vt3, vt0, vt1, vt2, vt3);
+ LD_SB4(ref, BPS, dest0, dest1, dest2, dest3);
+ ILVR_B4_SW(zero, dest0, zero, dest1, zero, dest2, zero, dest3,
+ res0, res1, res2, res3);
+ ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3,
+ res0, res1, res2, res3);
+ ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3);
+ CLIP_SW4_0_255(res0, res1, res2, res3);
+ PCKEV_B2_SW(res0, res1, res2, res3, vt0, vt1);
+ res0 = (v4i32)__msa_pckev_b((v16i8)vt0, (v16i8)vt1);
+ ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS);
+}
+
+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) {
+ uint64_t out0, out1, out2, out3;
+ uint32_t in0, in1, in2, in3;
+ v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ v8i16 t0, t1, t2, t3;
+ v16u8 srcl0, srcl1, src0, src1;
+ const v8i16 mask0 = { 0, 4, 8, 12, 1, 5, 9, 13 };
+ const v8i16 mask1 = { 3, 7, 11, 15, 2, 6, 10, 14 };
+ const v8i16 mask2 = { 4, 0, 5, 1, 6, 2, 7, 3 };
+ const v8i16 mask3 = { 0, 4, 1, 5, 2, 6, 3, 7 };
+ const v8i16 cnst0 = { 2217, -5352, 2217, -5352, 2217, -5352, 2217, -5352 };
+ const v8i16 cnst1 = { 5352, 2217, 5352, 2217, 5352, 2217, 5352, 2217 };
+
+ LW4(src, BPS, in0, in1, in2, in3);
+ INSERT_W4_UB(in0, in1, in2, in3, src0);
+ LW4(ref, BPS, in0, in1, in2, in3);
+ INSERT_W4_UB(in0, in1, in2, in3, src1);
+ ILVRL_B2_UB(src0, src1, srcl0, srcl1);
+ HSUB_UB2_SH(srcl0, srcl1, t0, t1);
+ VSHF_H2_SH(t0, t1, t0, t1, mask0, mask1, t2, t3);
+ ADDSUB2(t2, t3, t0, t1);
+ t0 = SRLI_H(t0, 3);
+ VSHF_H2_SH(t0, t0, t1, t1, mask2, mask3, t3, t2);
+ tmp0 = __msa_hadd_s_w(t3, t3);
+ tmp2 = __msa_hsub_s_w(t3, t3);
+ FILL_W2_SW(1812, 937, tmp1, tmp3);
+ DPADD_SH2_SW(t2, t2, cnst0, cnst1, tmp3, tmp1);
+ SRAI_W2_SW(tmp1, tmp3, 9);
+ PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, t0, t1);
+ VSHF_H2_SH(t0, t1, t0, t1, mask0, mask1, t2, t3);
+ ADDSUB2(t2, t3, t0, t1);
+ VSHF_H2_SH(t0, t0, t1, t1, mask2, mask3, t3, t2);
+ tmp0 = __msa_hadd_s_w(t3, t3);
+ tmp2 = __msa_hsub_s_w(t3, t3);
+ ADDVI_W2_SW(tmp0, 7, tmp2, 7, tmp0, tmp2);
+ SRAI_W2_SW(tmp0, tmp2, 4);
+ FILL_W2_SW(12000, 51000, tmp1, tmp3);
+ DPADD_SH2_SW(t2, t2, cnst0, cnst1, tmp3, tmp1);
+ SRAI_W2_SW(tmp1, tmp3, 16);
+ UNPCK_R_SH_SW(t1, tmp4);
+ tmp5 = __msa_ceqi_w(tmp4, 0);
+ tmp4 = (v4i32)__msa_nor_v((v16u8)tmp5, (v16u8)tmp5);
+ tmp5 = __msa_fill_w(1);
+ tmp5 = (v4i32)__msa_and_v((v16u8)tmp5, (v16u8)tmp4);
+ tmp1 += tmp5;
+ PCKEV_H2_SH(tmp1, tmp0, tmp3, tmp2, t0, t1);
+ out0 = __msa_copy_s_d((v2i64)t0, 0);
+ out1 = __msa_copy_s_d((v2i64)t0, 1);
+ out2 = __msa_copy_s_d((v2i64)t1, 0);
+ out3 = __msa_copy_s_d((v2i64)t1, 1);
+ SD4(out0, out1, out2, out3, out, 8);
+}
+
+static void FTransformWHT(const int16_t* in, int16_t* out) {
+ v8i16 in0 = { 0 };
+ v8i16 in1 = { 0 };
+ v8i16 tmp0, tmp1, tmp2, tmp3;
+ v8i16 out0, out1;
+ const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 };
+ const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 };
+ const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 };
+ const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 };
+
+ in0 = __msa_insert_h(in0, 0, in[ 0]);
+ in0 = __msa_insert_h(in0, 1, in[ 64]);
+ in0 = __msa_insert_h(in0, 2, in[128]);
+ in0 = __msa_insert_h(in0, 3, in[192]);
+ in0 = __msa_insert_h(in0, 4, in[ 16]);
+ in0 = __msa_insert_h(in0, 5, in[ 80]);
+ in0 = __msa_insert_h(in0, 6, in[144]);
+ in0 = __msa_insert_h(in0, 7, in[208]);
+ in1 = __msa_insert_h(in1, 0, in[ 48]);
+ in1 = __msa_insert_h(in1, 1, in[112]);
+ in1 = __msa_insert_h(in1, 2, in[176]);
+ in1 = __msa_insert_h(in1, 3, in[240]);
+ in1 = __msa_insert_h(in1, 4, in[ 32]);
+ in1 = __msa_insert_h(in1, 5, in[ 96]);
+ in1 = __msa_insert_h(in1, 6, in[160]);
+ in1 = __msa_insert_h(in1, 7, in[224]);
+ ADDSUB2(in0, in1, tmp0, tmp1);
+ VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3);
+ ADDSUB2(tmp2, tmp3, tmp0, tmp1);
+ VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1);
+ ADDSUB2(in0, in1, tmp0, tmp1);
+ VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3);
+ ADDSUB2(tmp2, tmp3, out0, out1);
+ SRAI_H2_SH(out0, out1, 1);
+ ST_SH2(out0, out1, out, 8);
+}
+
+static int TTransform(const uint8_t* in, const uint16_t* w) {
+ int sum;
+ uint32_t in0_m, in1_m, in2_m, in3_m;
+ v16i8 src0;
+ v8i16 in0, in1, tmp0, tmp1, tmp2, tmp3;
+ v4i32 dst0, dst1;
+ const v16i8 zero = { 0 };
+ const v8i16 mask0 = { 0, 1, 2, 3, 8, 9, 10, 11 };
+ const v8i16 mask1 = { 4, 5, 6, 7, 12, 13, 14, 15 };
+ const v8i16 mask2 = { 0, 4, 8, 12, 1, 5, 9, 13 };
+ const v8i16 mask3 = { 3, 7, 11, 15, 2, 6, 10, 14 };
+
+ LW4(in, BPS, in0_m, in1_m, in2_m, in3_m);
+ INSERT_W4_SB(in0_m, in1_m, in2_m, in3_m, src0);
+ ILVRL_B2_SH(zero, src0, tmp0, tmp1);
+ VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1);
+ ADDSUB2(in0, in1, tmp0, tmp1);
+ VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3);
+ ADDSUB2(tmp2, tmp3, tmp0, tmp1);
+ VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask2, mask3, in0, in1);
+ ADDSUB2(in0, in1, tmp0, tmp1);
+ VSHF_H2_SH(tmp0, tmp1, tmp0, tmp1, mask0, mask1, tmp2, tmp3);
+ ADDSUB2(tmp2, tmp3, tmp0, tmp1);
+ tmp0 = __msa_add_a_h(tmp0, (v8i16)zero);
+ tmp1 = __msa_add_a_h(tmp1, (v8i16)zero);
+ LD_SH2(w, 8, tmp2, tmp3);
+ DOTP_SH2_SW(tmp0, tmp1, tmp2, tmp3, dst0, dst1);
+ dst0 = dst0 + dst1;
+ sum = HADD_SW_S32(dst0);
+ 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) >> 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;
+}
+
+//------------------------------------------------------------------------------
+// Histogram
+
+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) {
+ int16_t out[16];
+ VP8FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out);
+ {
+ int k;
+ v8i16 coeff0, coeff1;
+ const v8i16 zero = { 0 };
+ const v8i16 max_coeff_thr = __msa_ldi_h(MAX_COEFF_THRESH);
+ LD_SH2(&out[0], 8, coeff0, coeff1);
+ coeff0 = __msa_add_a_h(coeff0, zero);
+ coeff1 = __msa_add_a_h(coeff1, zero);
+ SRAI_H2_SH(coeff0, coeff1, 3);
+ coeff0 = __msa_min_s_h(coeff0, max_coeff_thr);
+ coeff1 = __msa_min_s_h(coeff1, max_coeff_thr);
+ ST_SH2(coeff0, coeff1, &out[0], 8);
+ for (k = 0; k < 16; ++k) {
+ ++distribution[out[k]];
+ }
+ }
+ }
+ VP8SetHistogramData(distribution, histo);
+}
+
+//------------------------------------------------------------------------------
+// Intra predictions
+
+// 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)
+
+static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical
+ const uint64_t val_m = LD(top - 1);
+ const v16u8 A = (v16u8)__msa_insert_d((v2i64)A, 0, val_m);
+ const v16u8 B = SLDI_UB(A, A, 1);
+ const v16u8 C = SLDI_UB(A, A, 2);
+ const v16u8 AC = __msa_ave_u_b(A, C);
+ const v16u8 B2 = __msa_ave_u_b(B, B);
+ const v16u8 R = __msa_aver_u_b(AC, B2);
+ const uint32_t out = __msa_copy_s_w((v4i32)R, 0);
+ SW4(out, out, out, out, dst, BPS);
+}
+
+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];
+ WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J));
+ WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K));
+ WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L));
+ WebPUint32ToMem(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];
+ dc >>= 3;
+ dc = dc | (dc << 8) | (dc << 16) | (dc << 24);
+ SW4(dc, dc, dc, dc, dst, BPS);
+}
+
+static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) {
+ const uint64_t val_m = LD(top - 5);
+ const v16u8 A1 = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m);
+ const v16u8 A = (v16u8)__msa_insert_b((v16i8)A1, 8, top[3]);
+ const v16u8 B = SLDI_UB(A, A, 1);
+ const v16u8 C = SLDI_UB(A, A, 2);
+ const v16u8 AC = __msa_ave_u_b(A, C);
+ const v16u8 B2 = __msa_ave_u_b(B, B);
+ const v16u8 R0 = __msa_aver_u_b(AC, B2);
+ const v16u8 R1 = SLDI_UB(R0, R0, 1);
+ const v16u8 R2 = SLDI_UB(R1, R1, 1);
+ const v16u8 R3 = SLDI_UB(R2, R2, 1);
+ const uint32_t val0 = __msa_copy_s_w((v4i32)R0, 0);
+ const uint32_t val1 = __msa_copy_s_w((v4i32)R1, 0);
+ const uint32_t val2 = __msa_copy_s_w((v4i32)R2, 0);
+ const uint32_t val3 = __msa_copy_s_w((v4i32)R3, 0);
+ SW4(val3, val2, val1, val0, dst, BPS);
+}
+
+static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) {
+ const uint64_t val_m = LD(top);
+ const v16u8 A = (v16u8)__msa_insert_d((v2i64)A, 0, val_m);
+ const v16u8 B = SLDI_UB(A, A, 1);
+ const v16u8 C1 = SLDI_UB(A, A, 2);
+ const v16u8 C = (v16u8)__msa_insert_b((v16i8)C1, 6, top[7]);
+ const v16u8 AC = __msa_ave_u_b(A, C);
+ const v16u8 B2 = __msa_ave_u_b(B, B);
+ const v16u8 R0 = __msa_aver_u_b(AC, B2);
+ const v16u8 R1 = SLDI_UB(R0, R0, 1);
+ const v16u8 R2 = SLDI_UB(R1, R1, 1);
+ const v16u8 R3 = SLDI_UB(R2, R2, 1);
+ const uint32_t val0 = __msa_copy_s_w((v4i32)R0, 0);
+ const uint32_t val1 = __msa_copy_s_w((v4i32)R1, 0);
+ const uint32_t val2 = __msa_copy_s_w((v4i32)R2, 0);
+ const uint32_t val3 = __msa_copy_s_w((v4i32)R3, 0);
+ SW4(val0, val1, val2, val3, dst, BPS);
+}
+
+static WEBP_INLINE 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 WEBP_INLINE 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 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 v16i8 zero = { 0 };
+ const v8i16 TL = (v8i16)__msa_fill_h(top[-1]);
+ const v8i16 L0 = (v8i16)__msa_fill_h(top[-2]);
+ const v8i16 L1 = (v8i16)__msa_fill_h(top[-3]);
+ const v8i16 L2 = (v8i16)__msa_fill_h(top[-4]);
+ const v8i16 L3 = (v8i16)__msa_fill_h(top[-5]);
+ const v16u8 T1 = LD_UB(top);
+ const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1);
+ const v8i16 d = T - TL;
+ v8i16 r0, r1, r2, r3;
+ ADD4(d, L0, d, L1, d, L2, d, L3, r0, r1, r2, r3);
+ CLIP_SH4_0_255(r0, r1, r2, r3);
+ PCKEV_ST4x4_UB(r0, r1, r2, r3, dst, BPS);
+}
+
+#undef DST
+#undef AVG3
+#undef AVG2
+
+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);
+}
+
+// luma 16x16 prediction
+
+#define STORE16x16(out, dst) do { \
+ ST_UB8(out, out, out, out, out, out, out, out, dst + 0 * BPS, BPS); \
+ ST_UB8(out, out, out, out, out, out, out, out, dst + 8 * BPS, BPS); \
+} while (0)
+
+static WEBP_INLINE void VerticalPred16x16(uint8_t* dst, const uint8_t* top) {
+ if (top != NULL) {
+ const v16u8 out = LD_UB(top);
+ STORE16x16(out, dst);
+ } else {
+ const v16u8 out = (v16u8)__msa_fill_b(0x7f);
+ STORE16x16(out, dst);
+ }
+}
+
+static WEBP_INLINE void HorizontalPred16x16(uint8_t* dst,
+ const uint8_t* left) {
+ if (left != NULL) {
+ int j;
+ for (j = 0; j < 16; j += 4) {
+ const v16u8 L0 = (v16u8)__msa_fill_b(left[0]);
+ const v16u8 L1 = (v16u8)__msa_fill_b(left[1]);
+ const v16u8 L2 = (v16u8)__msa_fill_b(left[2]);
+ const v16u8 L3 = (v16u8)__msa_fill_b(left[3]);
+ ST_UB4(L0, L1, L2, L3, dst, BPS);
+ dst += 4 * BPS;
+ left += 4;
+ }
+ } else {
+ const v16u8 out = (v16u8)__msa_fill_b(0x81);
+ STORE16x16(out, dst);
+ }
+}
+
+static WEBP_INLINE void TrueMotion16x16(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ if (left != NULL) {
+ if (top != NULL) {
+ int j;
+ v8i16 d1, d2;
+ const v16i8 zero = { 0 };
+ const v8i16 TL = (v8i16)__msa_fill_h(left[-1]);
+ const v16u8 T = LD_UB(top);
+ ILVRL_B2_SH(zero, T, d1, d2);
+ SUB2(d1, TL, d2, TL, d1, d2);
+ for (j = 0; j < 16; j += 4) {
+ v16i8 t0, t1, t2, t3;
+ v8i16 r0, r1, r2, r3, r4, r5, r6, r7;
+ const v8i16 L0 = (v8i16)__msa_fill_h(left[j + 0]);
+ const v8i16 L1 = (v8i16)__msa_fill_h(left[j + 1]);
+ const v8i16 L2 = (v8i16)__msa_fill_h(left[j + 2]);
+ const v8i16 L3 = (v8i16)__msa_fill_h(left[j + 3]);
+ ADD4(d1, L0, d1, L1, d1, L2, d1, L3, r0, r1, r2, r3);
+ ADD4(d2, L0, d2, L1, d2, L2, d2, L3, r4, r5, r6, r7);
+ CLIP_SH4_0_255(r0, r1, r2, r3);
+ CLIP_SH4_0_255(r4, r5, r6, r7);
+ PCKEV_B4_SB(r4, r0, r5, r1, r6, r2, r7, r3, t0, t1, t2, t3);
+ ST_SB4(t0, t1, t2, t3, dst, BPS);
+ dst += 4 * BPS;
+ }
+ } else {
+ HorizontalPred16x16(dst, left);
+ }
+ } else {
+ if (top != NULL) {
+ VerticalPred16x16(dst, top);
+ } else {
+ const v16u8 out = (v16u8)__msa_fill_b(0x81);
+ STORE16x16(out, dst);
+ }
+ }
+}
+
+static WEBP_INLINE void DCMode16x16(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ int DC;
+ v16u8 out;
+ if (top != NULL && left != NULL) {
+ const v16u8 rtop = LD_UB(top);
+ const v8u16 dctop = __msa_hadd_u_h(rtop, rtop);
+ const v16u8 rleft = LD_UB(left);
+ const v8u16 dcleft = __msa_hadd_u_h(rleft, rleft);
+ const v8u16 dctemp = dctop + dcleft;
+ DC = HADD_UH_U32(dctemp);
+ DC = (DC + 16) >> 5;
+ } else if (left != NULL) { // left but no top
+ const v16u8 rleft = LD_UB(left);
+ const v8u16 dcleft = __msa_hadd_u_h(rleft, rleft);
+ DC = HADD_UH_U32(dcleft);
+ DC = (DC + DC + 16) >> 5;
+ } else if (top != NULL) { // top but no left
+ const v16u8 rtop = LD_UB(top);
+ const v8u16 dctop = __msa_hadd_u_h(rtop, rtop);
+ DC = HADD_UH_U32(dctop);
+ DC = (DC + DC + 16) >> 5;
+ } else { // no top, no left, nothing.
+ DC = 0x80;
+ }
+ out = (v16u8)__msa_fill_b(DC);
+ STORE16x16(out, dst);
+}
+
+static void Intra16Preds(uint8_t* dst,
+ const uint8_t* left, const uint8_t* top) {
+ DCMode16x16(I16DC16 + dst, left, top);
+ VerticalPred16x16(I16VE16 + dst, top);
+ HorizontalPred16x16(I16HE16 + dst, left);
+ TrueMotion16x16(I16TM16 + dst, left, top);
+}
+
+// Chroma 8x8 prediction
+
+#define CALC_DC8(in, out) do { \
+ const v8u16 temp0 = __msa_hadd_u_h(in, in); \
+ const v4u32 temp1 = __msa_hadd_u_w(temp0, temp0); \
+ const v2i64 temp2 = (v2i64)__msa_hadd_u_d(temp1, temp1); \
+ const v2i64 temp3 = __msa_splati_d(temp2, 1); \
+ const v2i64 temp4 = temp3 + temp2; \
+ const v16i8 temp5 = (v16i8)__msa_srari_d(temp4, 4); \
+ const v2i64 temp6 = (v2i64)__msa_splati_b(temp5, 0); \
+ out = __msa_copy_s_d(temp6, 0); \
+} while (0)
+
+#define STORE8x8(out, dst) do { \
+ SD4(out, out, out, out, dst + 0 * BPS, BPS); \
+ SD4(out, out, out, out, dst + 4 * BPS, BPS); \
+} while (0)
+
+static WEBP_INLINE void VerticalPred8x8(uint8_t* dst, const uint8_t* top) {
+ if (top != NULL) {
+ const uint64_t out = LD(top);
+ STORE8x8(out, dst);
+ } else {
+ const uint64_t out = 0x7f7f7f7f7f7f7f7fULL;
+ STORE8x8(out, dst);
+ }
+}
+
+static WEBP_INLINE void HorizontalPred8x8(uint8_t* dst, const uint8_t* left) {
+ if (left != NULL) {
+ int j;
+ for (j = 0; j < 8; j += 4) {
+ const v16u8 L0 = (v16u8)__msa_fill_b(left[0]);
+ const v16u8 L1 = (v16u8)__msa_fill_b(left[1]);
+ const v16u8 L2 = (v16u8)__msa_fill_b(left[2]);
+ const v16u8 L3 = (v16u8)__msa_fill_b(left[3]);
+ const uint64_t out0 = __msa_copy_s_d((v2i64)L0, 0);
+ const uint64_t out1 = __msa_copy_s_d((v2i64)L1, 0);
+ const uint64_t out2 = __msa_copy_s_d((v2i64)L2, 0);
+ const uint64_t out3 = __msa_copy_s_d((v2i64)L3, 0);
+ SD4(out0, out1, out2, out3, dst, BPS);
+ dst += 4 * BPS;
+ left += 4;
+ }
+ } else {
+ const uint64_t out = 0x8181818181818181ULL;
+ STORE8x8(out, dst);
+ }
+}
+
+static WEBP_INLINE void TrueMotion8x8(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ if (left != NULL) {
+ if (top != NULL) {
+ int j;
+ const v8i16 TL = (v8i16)__msa_fill_h(left[-1]);
+ const v16u8 T1 = LD_UB(top);
+ const v16i8 zero = { 0 };
+ const v8i16 T = (v8i16)__msa_ilvr_b(zero, (v16i8)T1);
+ const v8i16 d = T - TL;
+ for (j = 0; j < 8; j += 4) {
+ uint64_t out0, out1, out2, out3;
+ v16i8 t0, t1;
+ v8i16 r0 = (v8i16)__msa_fill_h(left[j + 0]);
+ v8i16 r1 = (v8i16)__msa_fill_h(left[j + 1]);
+ v8i16 r2 = (v8i16)__msa_fill_h(left[j + 2]);
+ v8i16 r3 = (v8i16)__msa_fill_h(left[j + 3]);
+ ADD4(d, r0, d, r1, d, r2, d, r3, r0, r1, r2, r3);
+ CLIP_SH4_0_255(r0, r1, r2, r3);
+ PCKEV_B2_SB(r1, r0, r3, r2, t0, t1);
+ out0 = __msa_copy_s_d((v2i64)t0, 0);
+ out1 = __msa_copy_s_d((v2i64)t0, 1);
+ out2 = __msa_copy_s_d((v2i64)t1, 0);
+ out3 = __msa_copy_s_d((v2i64)t1, 1);
+ SD4(out0, out1, out2, out3, dst, BPS);
+ dst += 4 * BPS;
+ }
+ } else {
+ HorizontalPred8x8(dst, left);
+ }
+ } else {
+ if (top != NULL) {
+ VerticalPred8x8(dst, top);
+ } else {
+ const uint64_t out = 0x8181818181818181ULL;
+ STORE8x8(out, dst);
+ }
+ }
+}
+
+static WEBP_INLINE void DCMode8x8(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ uint64_t out;
+ v16u8 src;
+ if (top != NULL && left != NULL) {
+ const uint64_t left_m = LD(left);
+ const uint64_t top_m = LD(top);
+ INSERT_D2_UB(left_m, top_m, src);
+ CALC_DC8(src, out);
+ } else if (left != NULL) { // left but no top
+ const uint64_t left_m = LD(left);
+ INSERT_D2_UB(left_m, left_m, src);
+ CALC_DC8(src, out);
+ } else if (top != NULL) { // top but no left
+ const uint64_t top_m = LD(top);
+ INSERT_D2_UB(top_m, top_m, src);
+ CALC_DC8(src, out);
+ } else { // no top, no left, nothing.
+ src = (v16u8)__msa_fill_b(0x80);
+ out = __msa_copy_s_d((v2i64)src, 0);
+ }
+ STORE8x8(out, dst);
+}
+
+static void IntraChromaPreds(uint8_t* dst, const uint8_t* left,
+ const uint8_t* top) {
+ // U block
+ DCMode8x8(C8DC8 + dst, left, top);
+ VerticalPred8x8(C8VE8 + dst, top);
+ HorizontalPred8x8(C8HE8 + dst, left);
+ TrueMotion8x8(C8TM8 + dst, left, top);
+ // V block
+ dst += 8;
+ if (top != NULL) top += 8;
+ if (left != NULL) left += 16;
+ DCMode8x8(C8DC8 + dst, left, top);
+ VerticalPred8x8(C8VE8 + dst, top);
+ HorizontalPred8x8(C8HE8 + dst, left);
+ TrueMotion8x8(C8TM8 + dst, left, top);
+}
+
+//------------------------------------------------------------------------------
+// Metric
+
+#define PACK_DOTP_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \
+ v16u8 tmp0, tmp1; \
+ v8i16 tmp2, tmp3; \
+ ILVRL_B2_UB(in0, in1, tmp0, tmp1); \
+ HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
+ DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out0, out1); \
+ ILVRL_B2_UB(in2, in3, tmp0, tmp1); \
+ HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
+ DOTP_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \
+} while (0)
+
+#define PACK_DPADD_UB4_SW(in0, in1, in2, in3, out0, out1, out2, out3) do { \
+ v16u8 tmp0, tmp1; \
+ v8i16 tmp2, tmp3; \
+ ILVRL_B2_UB(in0, in1, tmp0, tmp1); \
+ HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
+ DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out0, out1); \
+ ILVRL_B2_UB(in2, in3, tmp0, tmp1); \
+ HSUB_UB2_SH(tmp0, tmp1, tmp2, tmp3); \
+ DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \
+} while (0)
+
+static int SSE16x16(const uint8_t* a, const uint8_t* b) {
+ uint32_t sum;
+ v16u8 src0, src1, src2, src3, src4, src5, src6, src7;
+ v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7;
+ v4i32 out0, out1, out2, out3;
+
+ LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7);
+ LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7);
+ PACK_DOTP_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3);
+ a += 8 * BPS;
+ b += 8 * BPS;
+ LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7);
+ LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7);
+ PACK_DPADD_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3);
+ out0 += out1;
+ out2 += out3;
+ out0 += out2;
+ sum = HADD_SW_S32(out0);
+ return sum;
+}
+
+static int SSE16x8(const uint8_t* a, const uint8_t* b) {
+ uint32_t sum;
+ v16u8 src0, src1, src2, src3, src4, src5, src6, src7;
+ v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7;
+ v4i32 out0, out1, out2, out3;
+
+ LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7);
+ LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7);
+ PACK_DOTP_UB4_SW(src0, ref0, src1, ref1, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src2, ref2, src3, ref3, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src4, ref4, src5, ref5, out0, out1, out2, out3);
+ PACK_DPADD_UB4_SW(src6, ref6, src7, ref7, out0, out1, out2, out3);
+ out0 += out1;
+ out2 += out3;
+ out0 += out2;
+ sum = HADD_SW_S32(out0);
+ return sum;
+}
+
+static int SSE8x8(const uint8_t* a, const uint8_t* b) {
+ uint32_t sum;
+ v16u8 src0, src1, src2, src3, src4, src5, src6, src7;
+ v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7;
+ v16u8 t0, t1, t2, t3;
+ v4i32 out0, out1, out2, out3;
+
+ LD_UB8(a, BPS, src0, src1, src2, src3, src4, src5, src6, src7);
+ LD_UB8(b, BPS, ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7);
+ ILVR_B4_UB(src0, src1, src2, src3, ref0, ref1, ref2, ref3, t0, t1, t2, t3);
+ PACK_DOTP_UB4_SW(t0, t2, t1, t3, out0, out1, out2, out3);
+ ILVR_B4_UB(src4, src5, src6, src7, ref4, ref5, ref6, ref7, t0, t1, t2, t3);
+ PACK_DPADD_UB4_SW(t0, t2, t1, t3, out0, out1, out2, out3);
+ out0 += out1;
+ out2 += out3;
+ out0 += out2;
+ sum = HADD_SW_S32(out0);
+ return sum;
+}
+
+static int SSE4x4(const uint8_t* a, const uint8_t* b) {
+ uint32_t sum = 0;
+ uint32_t src0, src1, src2, src3, ref0, ref1, ref2, ref3;
+ v16u8 src, ref, tmp0, tmp1;
+ v8i16 diff0, diff1;
+ v4i32 out0, out1;
+
+ LW4(a, BPS, src0, src1, src2, src3);
+ LW4(b, BPS, ref0, ref1, ref2, ref3);
+ INSERT_W4_UB(src0, src1, src2, src3, src);
+ INSERT_W4_UB(ref0, ref1, ref2, ref3, ref);
+ ILVRL_B2_UB(src, ref, tmp0, tmp1);
+ HSUB_UB2_SH(tmp0, tmp1, diff0, diff1);
+ DOTP_SH2_SW(diff0, diff1, diff0, diff1, out0, out1);
+ out0 += out1;
+ sum = HADD_SW_S32(out0);
+ return sum;
+}
+
+//------------------------------------------------------------------------------
+// Quantization
+
+static int QuantizeBlock(int16_t in[16], int16_t out[16],
+ const VP8Matrix* const mtx) {
+ int sum;
+ v8i16 in0, in1, sh0, sh1, out0, out1;
+ v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, sign0, sign1;
+ v4i32 s0, s1, s2, s3, b0, b1, b2, b3, t0, t1, t2, t3;
+ const v8i16 zero = { 0 };
+ const v8i16 zigzag0 = { 0, 1, 4, 8, 5, 2, 3, 6 };
+ const v8i16 zigzag1 = { 9, 12, 13, 10, 7, 11, 14, 15 };
+ const v8i16 maxlevel = __msa_fill_h(MAX_LEVEL);
+
+ LD_SH2(&in[0], 8, in0, in1);
+ LD_SH2(&mtx->sharpen_[0], 8, sh0, sh1);
+ tmp4 = __msa_add_a_h(in0, zero);
+ tmp5 = __msa_add_a_h(in1, zero);
+ ILVRL_H2_SH(sh0, tmp4, tmp0, tmp1);
+ ILVRL_H2_SH(sh1, tmp5, tmp2, tmp3);
+ HADD_SH4_SW(tmp0, tmp1, tmp2, tmp3, s0, s1, s2, s3);
+ sign0 = (in0 < zero);
+ sign1 = (in1 < zero); // sign
+ LD_SH2(&mtx->iq_[0], 8, tmp0, tmp1); // iq
+ ILVRL_H2_SW(zero, tmp0, t0, t1);
+ ILVRL_H2_SW(zero, tmp1, t2, t3);
+ LD_SW4(&mtx->bias_[0], 4, b0, b1, b2, b3); // bias
+ MUL4(t0, s0, t1, s1, t2, s2, t3, s3, t0, t1, t2, t3);
+ ADD4(b0, t0, b1, t1, b2, t2, b3, t3, b0, b1, b2, b3);
+ SRAI_W4_SW(b0, b1, b2, b3, 17);
+ PCKEV_H2_SH(b1, b0, b3, b2, tmp2, tmp3);
+ tmp0 = (tmp2 > maxlevel);
+ tmp1 = (tmp3 > maxlevel);
+ tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)maxlevel, (v16u8)tmp0);
+ tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)maxlevel, (v16u8)tmp1);
+ SUB2(0, tmp2, 0, tmp3, tmp0, tmp1);
+ tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)tmp0, (v16u8)sign0);
+ tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)tmp1, (v16u8)sign1);
+ LD_SW4(&mtx->zthresh_[0], 4, t0, t1, t2, t3); // zthresh
+ t0 = (s0 > t0);
+ t1 = (s1 > t1);
+ t2 = (s2 > t2);
+ t3 = (s3 > t3);
+ PCKEV_H2_SH(t1, t0, t3, t2, tmp0, tmp1);
+ tmp4 = (v8i16)__msa_bmnz_v((v16u8)zero, (v16u8)tmp2, (v16u8)tmp0);
+ tmp5 = (v8i16)__msa_bmnz_v((v16u8)zero, (v16u8)tmp3, (v16u8)tmp1);
+ LD_SH2(&mtx->q_[0], 8, tmp0, tmp1);
+ MUL2(tmp4, tmp0, tmp5, tmp1, in0, in1);
+ VSHF_H2_SH(tmp4, tmp5, tmp4, tmp5, zigzag0, zigzag1, out0, out1);
+ ST_SH2(in0, in1, &in[0], 8);
+ ST_SH2(out0, out1, &out[0], 8);
+ out0 = __msa_add_a_h(out0, out1);
+ sum = HADD_SH_S32(out0);
+ return (sum > 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;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8EncDspInitMSA(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMSA(void) {
+ VP8ITransform = ITransform;
+ VP8FTransform = FTransform;
+ VP8FTransformWHT = FTransformWHT;
+
+ VP8TDisto4x4 = Disto4x4;
+ VP8TDisto16x16 = Disto16x16;
+ VP8CollectHistogram = CollectHistogram;
+
+ VP8EncPredLuma4 = Intra4Preds;
+ VP8EncPredLuma16 = Intra16Preds;
+ VP8EncPredChroma8 = IntraChromaPreds;
+
+ VP8SSE16x16 = SSE16x16;
+ VP8SSE16x8 = SSE16x8;
+ VP8SSE8x8 = SSE8x8;
+ VP8SSE4x4 = SSE4x4;
+
+ VP8EncQuantizeBlock = QuantizeBlock;
+ VP8EncQuantize2Blocks = Quantize2Blocks;
+ VP8EncQuantizeBlockWHT = QuantizeBlock;
+}
+
+#else // !WEBP_USE_MSA
+
+WEBP_DSP_INIT_STUB(VP8EncDspInitMSA)
+
+#endif // WEBP_USE_MSA
diff --git a/thirdparty/libwebp/dsp/enc_neon.c b/thirdparty/libwebp/dsp/enc_neon.c
index 46f6bf9a33..6a078d632d 100644
--- a/thirdparty/libwebp/dsp/enc_neon.c
+++ b/thirdparty/libwebp/dsp/enc_neon.c
@@ -18,7 +18,7 @@
#include <assert.h>
#include "./neon.h"
-#include "../enc/vp8enci.h"
+#include "../enc/vp8i_enc.h"
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
@@ -746,9 +746,14 @@ static WEBP_INLINE void AccumulateSSE16(const uint8_t* const a,
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
+ const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff),
+ vget_low_u8(abs_diff));
+ const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff),
+ vget_high_u8(abs_diff));
+ /* pair-wise adds and widen */
+ const uint32x4_t sum1 = vpaddlq_u16(prod1);
+ const uint32x4_t sum2 = vpaddlq_u16(prod2);
+ *sum = vaddq_u32(*sum, vaddq_u32(sum1, sum2));
}
// Horizontal sum of all four uint32_t values in 'sum'.
@@ -758,7 +763,7 @@ static int SumToInt(uint32x4_t sum) {
return (int)sum3;
}
-static int SSE16x16(const uint8_t* a, const uint8_t* b) {
+static int SSE16x16_NEON(const uint8_t* a, const uint8_t* b) {
uint32x4_t sum = vdupq_n_u32(0);
int y;
for (y = 0; y < 16; ++y) {
@@ -767,7 +772,7 @@ static int SSE16x16(const uint8_t* a, const uint8_t* b) {
return SumToInt(sum);
}
-static int SSE16x8(const uint8_t* a, const uint8_t* b) {
+static int SSE16x8_NEON(const uint8_t* a, const uint8_t* b) {
uint32x4_t sum = vdupq_n_u32(0);
int y;
for (y = 0; y < 8; ++y) {
@@ -776,7 +781,7 @@ static int SSE16x8(const uint8_t* a, const uint8_t* b) {
return SumToInt(sum);
}
-static int SSE8x8(const uint8_t* a, const uint8_t* b) {
+static int SSE8x8_NEON(const uint8_t* a, const uint8_t* b) {
uint32x4_t sum = vdupq_n_u32(0);
int y;
for (y = 0; y < 8; ++y) {
@@ -789,13 +794,18 @@ static int SSE8x8(const uint8_t* a, const uint8_t* b) {
return SumToInt(sum);
}
-static int SSE4x4(const uint8_t* a, const uint8_t* b) {
+static int SSE4x4_NEON(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));
+ const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff),
+ vget_low_u8(abs_diff));
+ const uint16x8_t prod2 = vmull_u8(vget_high_u8(abs_diff),
+ vget_high_u8(abs_diff));
+ /* pair-wise adds and widen */
+ const uint32x4_t sum1 = vpaddlq_u16(prod1);
+ const uint32x4_t sum2 = vpaddlq_u16(prod2);
+ return SumToInt(vaddq_u32(sum1, sum2));
}
//------------------------------------------------------------------------------
@@ -903,10 +913,12 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) {
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
VP8CollectHistogram = CollectHistogram;
- VP8SSE16x16 = SSE16x16;
- VP8SSE16x8 = SSE16x8;
- VP8SSE8x8 = SSE8x8;
- VP8SSE4x4 = SSE4x4;
+
+ VP8SSE16x16 = SSE16x16_NEON;
+ VP8SSE16x8 = SSE16x8_NEON;
+ VP8SSE8x8 = SSE8x8_NEON;
+ VP8SSE4x4 = SSE4x4_NEON;
+
#if !defined(WORK_AROUND_GCC)
VP8EncQuantizeBlock = QuantizeBlock;
VP8EncQuantize2Blocks = Quantize2Blocks;
diff --git a/thirdparty/libwebp/dsp/enc_sse2.c b/thirdparty/libwebp/dsp/enc_sse2.c
index 4a2e3ce14f..2026a74c91 100644
--- a/thirdparty/libwebp/dsp/enc_sse2.c
+++ b/thirdparty/libwebp/dsp/enc_sse2.c
@@ -14,12 +14,13 @@
#include "./dsp.h"
#if defined(WEBP_USE_SSE2)
+#include <assert.h>
#include <stdlib.h> // for abs()
#include <emmintrin.h>
#include "./common_sse2.h"
-#include "../enc/cost.h"
-#include "../enc/vp8enci.h"
+#include "../enc/cost_enc.h"
+#include "../enc/vp8i_enc.h"
//------------------------------------------------------------------------------
// Transforms (Paragraph 14.4)
@@ -139,7 +140,7 @@ static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst,
// Transpose the two 4x4.
VP8Transpose_2_4x4_16b(&shifted0, &shifted1, &shifted2, &shifted3, &T0, &T1,
- &T2, &T3);
+ &T2, &T3);
}
// Add inverse transform to 'ref' and store.
@@ -250,25 +251,11 @@ static void FTransformPass2(const __m128i* const v01, const __m128i* const v32,
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);
@@ -276,14 +263,28 @@ static void FTransformPass2(const __m128i* const v01, const __m128i* const v32,
const __m128i d3 = _mm_add_epi32(c3, k51000);
const __m128i e1 = _mm_srai_epi32(d1, 16);
const __m128i e3 = _mm_srai_epi32(d3, 16);
+ // f1 = ((b3 * 5352 + b2 * 2217 + 12000) >> 16)
+ // f3 = ((b3 * 2217 - b2 * 5352 + 51000) >> 16)
const __m128i f1 = _mm_packs_epi32(e1, e1);
const __m128i f3 = _mm_packs_epi32(e3, e3);
- // f1 = f1 + (a3 != 0);
+ // g1 = 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)
+ // -> g1 = f1 + 1 - (a3 == 0)
const __m128i g1 = _mm_add_epi16(f1, _mm_cmpeq_epi16(a32, zero));
+ // a0 = v0 + v3
+ // a1 = v1 + v2
+ const __m128i a01 = _mm_add_epi16(*v01, *v32);
+ const __m128i a01_plus_7 = _mm_add_epi16(a01, seven);
+ const __m128i a11 = _mm_unpackhi_epi64(a01, a01);
+ const __m128i c0 = _mm_add_epi16(a01_plus_7, a11);
+ const __m128i c2 = _mm_sub_epi16(a01_plus_7, a11);
+ // d0 = (a0 + a1 + 7) >> 4;
+ // d2 = (a0 - a1 + 7) >> 4;
+ const __m128i d0 = _mm_srai_epi16(c0, 4);
+ const __m128i d2 = _mm_srai_epi16(c2, 4);
+
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);
@@ -1046,6 +1047,37 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) {
}
//------------------------------------------------------------------------------
+
+static void Mean16x4(const uint8_t* ref, uint32_t dc[4]) {
+ const __m128i mask = _mm_set1_epi16(0x00ff);
+ const __m128i a0 = _mm_loadu_si128((const __m128i*)&ref[BPS * 0]);
+ const __m128i a1 = _mm_loadu_si128((const __m128i*)&ref[BPS * 1]);
+ const __m128i a2 = _mm_loadu_si128((const __m128i*)&ref[BPS * 2]);
+ const __m128i a3 = _mm_loadu_si128((const __m128i*)&ref[BPS * 3]);
+ const __m128i b0 = _mm_srli_epi16(a0, 8); // hi byte
+ const __m128i b1 = _mm_srli_epi16(a1, 8);
+ const __m128i b2 = _mm_srli_epi16(a2, 8);
+ const __m128i b3 = _mm_srli_epi16(a3, 8);
+ const __m128i c0 = _mm_and_si128(a0, mask); // lo byte
+ const __m128i c1 = _mm_and_si128(a1, mask);
+ const __m128i c2 = _mm_and_si128(a2, mask);
+ const __m128i c3 = _mm_and_si128(a3, mask);
+ const __m128i d0 = _mm_add_epi32(b0, c0);
+ const __m128i d1 = _mm_add_epi32(b1, c1);
+ const __m128i d2 = _mm_add_epi32(b2, c2);
+ const __m128i d3 = _mm_add_epi32(b3, c3);
+ const __m128i e0 = _mm_add_epi32(d0, d1);
+ const __m128i e1 = _mm_add_epi32(d2, d3);
+ const __m128i f0 = _mm_add_epi32(e0, e1);
+ uint16_t tmp[8];
+ _mm_storeu_si128((__m128i*)tmp, f0);
+ dc[0] = tmp[0] + tmp[1];
+ dc[1] = tmp[2] + tmp[3];
+ dc[2] = tmp[4] + tmp[5];
+ dc[3] = tmp[6] + tmp[7];
+}
+
+//------------------------------------------------------------------------------
// Texture distortion
//
// We try to match the spectral content (weighted) between source and
@@ -1331,10 +1363,122 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) {
VP8SSE4x4 = SSE4x4;
VP8TDisto4x4 = Disto4x4;
VP8TDisto16x16 = Disto16x16;
+ VP8Mean16x4 = Mean16x4;
+}
+
+//------------------------------------------------------------------------------
+// SSIM / PSNR entry point (TODO(skal): move to its own file later)
+
+static uint32_t AccumulateSSE_SSE2(const uint8_t* src1,
+ const uint8_t* src2, int len) {
+ int i = 0;
+ uint32_t sse2 = 0;
+ if (len >= 16) {
+ const int limit = len - 32;
+ int32_t tmp[4];
+ __m128i sum1;
+ __m128i sum = _mm_setzero_si128();
+ __m128i a0 = _mm_loadu_si128((const __m128i*)&src1[i]);
+ __m128i b0 = _mm_loadu_si128((const __m128i*)&src2[i]);
+ i += 16;
+ while (i <= limit) {
+ const __m128i a1 = _mm_loadu_si128((const __m128i*)&src1[i]);
+ const __m128i b1 = _mm_loadu_si128((const __m128i*)&src2[i]);
+ __m128i sum2;
+ i += 16;
+ SubtractAndAccumulate(a0, b0, &sum1);
+ sum = _mm_add_epi32(sum, sum1);
+ a0 = _mm_loadu_si128((const __m128i*)&src1[i]);
+ b0 = _mm_loadu_si128((const __m128i*)&src2[i]);
+ i += 16;
+ SubtractAndAccumulate(a1, b1, &sum2);
+ sum = _mm_add_epi32(sum, sum2);
+ }
+ SubtractAndAccumulate(a0, b0, &sum1);
+ sum = _mm_add_epi32(sum, sum1);
+ _mm_storeu_si128((__m128i*)tmp, sum);
+ sse2 += (tmp[3] + tmp[2] + tmp[1] + tmp[0]);
+ }
+
+ for (; i < len; ++i) {
+ const int32_t diff = src1[i] - src2[i];
+ sse2 += diff * diff;
+ }
+ return sse2;
+}
+
+static uint32_t HorizontalAdd16b(const __m128i* const m) {
+ uint16_t tmp[8];
+ const __m128i a = _mm_srli_si128(*m, 8);
+ const __m128i b = _mm_add_epi16(*m, a);
+ _mm_storeu_si128((__m128i*)tmp, b);
+ return (uint32_t)tmp[3] + tmp[2] + tmp[1] + tmp[0];
+}
+
+static uint32_t HorizontalAdd32b(const __m128i* const m) {
+ const __m128i a = _mm_srli_si128(*m, 8);
+ const __m128i b = _mm_add_epi32(*m, a);
+ const __m128i c = _mm_add_epi32(b, _mm_srli_si128(b, 4));
+ return (uint32_t)_mm_cvtsi128_si32(c);
+}
+
+static const uint16_t kWeight[] = { 1, 2, 3, 4, 3, 2, 1, 0 };
+
+#define ACCUMULATE_ROW(WEIGHT) do { \
+ /* compute row weight (Wx * Wy) */ \
+ const __m128i Wy = _mm_set1_epi16((WEIGHT)); \
+ const __m128i W = _mm_mullo_epi16(Wx, Wy); \
+ /* process 8 bytes at a time (7 bytes, actually) */ \
+ const __m128i a0 = _mm_loadl_epi64((const __m128i*)src1); \
+ const __m128i b0 = _mm_loadl_epi64((const __m128i*)src2); \
+ /* convert to 16b and multiply by weight */ \
+ const __m128i a1 = _mm_unpacklo_epi8(a0, zero); \
+ const __m128i b1 = _mm_unpacklo_epi8(b0, zero); \
+ const __m128i wa1 = _mm_mullo_epi16(a1, W); \
+ const __m128i wb1 = _mm_mullo_epi16(b1, W); \
+ /* accumulate */ \
+ xm = _mm_add_epi16(xm, wa1); \
+ ym = _mm_add_epi16(ym, wb1); \
+ xxm = _mm_add_epi32(xxm, _mm_madd_epi16(a1, wa1)); \
+ xym = _mm_add_epi32(xym, _mm_madd_epi16(a1, wb1)); \
+ yym = _mm_add_epi32(yym, _mm_madd_epi16(b1, wb1)); \
+ src1 += stride1; \
+ src2 += stride2; \
+} while (0)
+
+static double SSIMGet_SSE2(const uint8_t* src1, int stride1,
+ const uint8_t* src2, int stride2) {
+ VP8DistoStats stats;
+ const __m128i zero = _mm_setzero_si128();
+ __m128i xm = zero, ym = zero; // 16b accums
+ __m128i xxm = zero, yym = zero, xym = zero; // 32b accum
+ const __m128i Wx = _mm_loadu_si128((const __m128i*)kWeight);
+ assert(2 * VP8_SSIM_KERNEL + 1 == 7);
+ ACCUMULATE_ROW(1);
+ ACCUMULATE_ROW(2);
+ ACCUMULATE_ROW(3);
+ ACCUMULATE_ROW(4);
+ ACCUMULATE_ROW(3);
+ ACCUMULATE_ROW(2);
+ ACCUMULATE_ROW(1);
+ stats.xm = HorizontalAdd16b(&xm);
+ stats.ym = HorizontalAdd16b(&ym);
+ stats.xxm = HorizontalAdd32b(&xxm);
+ stats.xym = HorizontalAdd32b(&xym);
+ stats.yym = HorizontalAdd32b(&yym);
+ return VP8SSIMFromStats(&stats);
+}
+
+extern void VP8SSIMDspInitSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInitSSE2(void) {
+ VP8AccumulateSSE = AccumulateSSE_SSE2;
+ VP8SSIMGet = SSIMGet_SSE2;
}
#else // !WEBP_USE_SSE2
WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2)
+WEBP_DSP_INIT_STUB(VP8SSIMDspInitSSE2)
#endif // WEBP_USE_SSE2
diff --git a/thirdparty/libwebp/dsp/enc_sse41.c b/thirdparty/libwebp/dsp/enc_sse41.c
index a1783901a6..e32086d9fd 100644
--- a/thirdparty/libwebp/dsp/enc_sse41.c
+++ b/thirdparty/libwebp/dsp/enc_sse41.c
@@ -18,7 +18,7 @@
#include <stdlib.h> // for abs()
#include "./common_sse2.h"
-#include "../enc/vp8enci.h"
+#include "../enc/vp8i_enc.h"
//------------------------------------------------------------------------------
// Compute susceptibility based on DCT-coeff histograms.
diff --git a/thirdparty/libwebp/dsp/filters.c b/thirdparty/libwebp/dsp/filters.c
index 9f04faf0cb..65f34aad1f 100644
--- a/thirdparty/libwebp/dsp/filters.c
+++ b/thirdparty/libwebp/dsp/filters.c
@@ -227,6 +227,8 @@ WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
extern void VP8FiltersInitMIPSdspR2(void);
+extern void VP8FiltersInitMSA(void);
+extern void VP8FiltersInitNEON(void);
extern void VP8FiltersInitSSE2(void);
static volatile VP8CPUInfo filters_last_cpuinfo_used =
@@ -251,11 +253,21 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) {
VP8FiltersInitSSE2();
}
#endif
+#if defined(WEBP_USE_NEON)
+ if (VP8GetCPUInfo(kNEON)) {
+ VP8FiltersInitNEON();
+ }
+#endif
#if defined(WEBP_USE_MIPS_DSP_R2)
if (VP8GetCPUInfo(kMIPSdspR2)) {
VP8FiltersInitMIPSdspR2();
}
#endif
+#if defined(WEBP_USE_MSA)
+ if (VP8GetCPUInfo(kMSA)) {
+ VP8FiltersInitMSA();
+ }
+#endif
}
filters_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/dsp/filters_msa.c b/thirdparty/libwebp/dsp/filters_msa.c
new file mode 100644
index 0000000000..4b8922d0bc
--- /dev/null
+++ b/thirdparty/libwebp/dsp/filters_msa.c
@@ -0,0 +1,202 @@
+// Copyright 2016 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.
+// -----------------------------------------------------------------------------
+//
+// MSA variant of alpha filters
+//
+// Author: Prashant Patil (prashant.patil@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MSA)
+
+#include "./msa_macro.h"
+
+#include <assert.h>
+
+static WEBP_INLINE void PredictLineInverse0(const uint8_t* src,
+ const uint8_t* pred,
+ uint8_t* dst, int length) {
+ v16u8 src0, pred0, dst0;
+ assert(length >= 0);
+ while (length >= 32) {
+ v16u8 src1, pred1, dst1;
+ LD_UB2(src, 16, src0, src1);
+ LD_UB2(pred, 16, pred0, pred1);
+ SUB2(src0, pred0, src1, pred1, dst0, dst1);
+ ST_UB2(dst0, dst1, dst, 16);
+ src += 32;
+ pred += 32;
+ dst += 32;
+ length -= 32;
+ }
+ if (length > 0) {
+ int i;
+ if (length >= 16) {
+ src0 = LD_UB(src);
+ pred0 = LD_UB(pred);
+ dst0 = src0 - pred0;
+ ST_UB(dst0, dst);
+ src += 16;
+ pred += 16;
+ dst += 16;
+ length -= 16;
+ }
+ for (i = 0; i < length; i++) {
+ dst[i] = src[i] - pred[i];
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Helpful macro.
+
+#define SANITY_CHECK(in, out) \
+ assert(in != NULL); \
+ assert(out != NULL); \
+ assert(width > 0); \
+ assert(height > 0); \
+ assert(stride >= width);
+
+//------------------------------------------------------------------------------
+// Horrizontal filter
+
+static void HorizontalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ const uint8_t* preds = data;
+ const uint8_t* in = data;
+ uint8_t* out = filtered_data;
+ int row = 1;
+ SANITY_CHECK(in, out);
+
+ // Leftmost pixel is the same as input for topmost scanline.
+ out[0] = in[0];
+ PredictLineInverse0(in + 1, preds, out + 1, width - 1);
+ preds += stride;
+ in += stride;
+ out += stride;
+ // Filter line-by-line.
+ while (row < height) {
+ // Leftmost pixel is predicted from above.
+ PredictLineInverse0(in, preds - stride, out, 1);
+ PredictLineInverse0(in + 1, preds, out + 1, width - 1);
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Gradient filter
+
+static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput,
+ const uint8_t* ppred,
+ uint8_t* poutput, int stride,
+ int size) {
+ int w;
+ const v16i8 zero = { 0 };
+ while (size >= 16) {
+ v16u8 pred0, dst0;
+ v8i16 a0, a1, b0, b1, c0, c1;
+ const v16u8 tmp0 = LD_UB(ppred - 1);
+ const v16u8 tmp1 = LD_UB(ppred - stride);
+ const v16u8 tmp2 = LD_UB(ppred - stride - 1);
+ const v16u8 src0 = LD_UB(pinput);
+ ILVRL_B2_SH(zero, tmp0, a0, a1);
+ ILVRL_B2_SH(zero, tmp1, b0, b1);
+ ILVRL_B2_SH(zero, tmp2, c0, c1);
+ ADD2(a0, b0, a1, b1, a0, a1);
+ SUB2(a0, c0, a1, c1, a0, a1);
+ CLIP_SH2_0_255(a0, a1);
+ pred0 = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0);
+ dst0 = src0 - pred0;
+ ST_UB(dst0, poutput);
+ ppred += 16;
+ pinput += 16;
+ poutput += 16;
+ size -= 16;
+ }
+ for (w = 0; w < size; ++w) {
+ const int pred = ppred[w - 1] + ppred[w - stride] - ppred[w - stride - 1];
+ poutput[w] = pinput[w] - (pred < 0 ? 0 : pred > 255 ? 255 : pred);
+ }
+}
+
+
+static void GradientFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ const uint8_t* in = data;
+ const uint8_t* preds = data;
+ uint8_t* out = filtered_data;
+ int row = 1;
+ SANITY_CHECK(in, out);
+
+ // left prediction for top scan-line
+ out[0] = in[0];
+ PredictLineInverse0(in + 1, preds, out + 1, width - 1);
+ preds += stride;
+ in += stride;
+ out += stride;
+ // Filter line-by-line.
+ while (row < height) {
+ out[0] = in[0] - preds[- stride];
+ PredictLineGradient(preds + 1, in + 1, out + 1, stride, width - 1);
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Vertical filter
+
+static void VerticalFilter(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ const uint8_t* in = data;
+ const uint8_t* preds = data;
+ uint8_t* out = filtered_data;
+ int row = 1;
+ SANITY_CHECK(in, out);
+
+ // Very first top-left pixel is copied.
+ out[0] = in[0];
+ // Rest of top scan-line is left-predicted.
+ PredictLineInverse0(in + 1, preds, out + 1, width - 1);
+ in += stride;
+ out += stride;
+
+ // Filter line-by-line.
+ while (row < height) {
+ PredictLineInverse0(in, preds, out, width);
+ ++row;
+ preds += stride;
+ in += stride;
+ out += stride;
+ }
+}
+
+#undef SANITY_CHECK
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8FiltersInitMSA(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMSA(void) {
+ WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter;
+ WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter;
+ WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter;
+}
+
+#else // !WEBP_USE_MSA
+
+WEBP_DSP_INIT_STUB(VP8FiltersInitMSA)
+
+#endif // WEBP_USE_MSA
diff --git a/thirdparty/libwebp/dsp/filters_neon.c b/thirdparty/libwebp/dsp/filters_neon.c
new file mode 100644
index 0000000000..4d6e50cc76
--- /dev/null
+++ b/thirdparty/libwebp/dsp/filters_neon.c
@@ -0,0 +1,327 @@
+// Copyright 2017 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 alpha filters
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_NEON)
+
+#include <assert.h>
+#include "./neon.h"
+
+//------------------------------------------------------------------------------
+// Helpful macros.
+
+# 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.
+
+// load eight u8 and widen to s16
+#define U8_TO_S16(A) vreinterpretq_s16_u16(vmovl_u8(A))
+#define LOAD_U8_TO_S16(A) U8_TO_S16(vld1_u8(A))
+
+// shift left or right by N byte, inserting zeros
+#define SHIFT_RIGHT_N_Q(A, N) vextq_u8((A), zero, (N))
+#define SHIFT_LEFT_N_Q(A, N) vextq_u8(zero, (A), (16 - (N)) % 16)
+
+// rotate left by N bytes
+#define ROTATE_LEFT_N(A, N) vext_u8((A), (A), (N))
+// rotate right by N bytes
+#define ROTATE_RIGHT_N(A, N) vext_u8((A), (A), (8 - (N)) % 8)
+
+static void PredictLine_NEON(const uint8_t* src, const uint8_t* pred,
+ uint8_t* dst, int length) {
+ int i;
+ assert(length >= 0);
+ for (i = 0; i + 16 <= length; i += 16) {
+ const uint8x16_t A = vld1q_u8(&src[i]);
+ const uint8x16_t B = vld1q_u8(&pred[i]);
+ const uint8x16_t C = vsubq_u8(A, B);
+ vst1q_u8(&dst[i], C);
+ }
+ 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_NEON(const uint8_t* src, uint8_t* dst, int length) {
+ PredictLine_NEON(src, src - 1, dst, length);
+}
+
+//------------------------------------------------------------------------------
+// Horizontal filter.
+
+static WEBP_INLINE void DoHorizontalFilter_NEON(const uint8_t* in,
+ int width, int height,
+ int stride,
+ int row, int num_rows,
+ 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;
+
+ if (row == 0) {
+ // Leftmost pixel is the same as input for topmost scanline.
+ out[0] = in[0];
+ PredictLineLeft_NEON(in + 1, out + 1, width - 1);
+ row = 1;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ // Leftmost pixel is predicted from above.
+ out[0] = in[0] - in[-stride];
+ PredictLineLeft_NEON(in + 1, out + 1, width - 1);
+ ++row;
+ in += stride;
+ out += stride;
+ }
+}
+
+static void HorizontalFilter_NEON(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoHorizontalFilter_NEON(data, width, height, stride, 0, height,
+ filtered_data);
+}
+
+//------------------------------------------------------------------------------
+// Vertical filter.
+
+static WEBP_INLINE void DoVerticalFilter_NEON(const uint8_t* in,
+ int width, int height, int stride,
+ int row, int num_rows,
+ 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;
+
+ if (row == 0) {
+ // Very first top-left pixel is copied.
+ out[0] = in[0];
+ // Rest of top scan-line is left-predicted.
+ PredictLineLeft_NEON(in + 1, out + 1, width - 1);
+ row = 1;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ PredictLine_NEON(in, in - stride, out, width);
+ ++row;
+ in += stride;
+ out += stride;
+ }
+}
+
+static void VerticalFilter_NEON(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoVerticalFilter_NEON(data, width, height, stride, 0, height,
+ filtered_data);
+}
+
+//------------------------------------------------------------------------------
+// Gradient filter.
+
+static WEBP_INLINE int GradientPredictor_C(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_NEON(const uint8_t* const row,
+ const uint8_t* const top,
+ uint8_t* const out, int length) {
+ int i;
+ for (i = 0; i + 8 <= length; i += 8) {
+ const uint8x8_t A = vld1_u8(&row[i - 1]);
+ const uint8x8_t B = vld1_u8(&top[i + 0]);
+ const int16x8_t C = vreinterpretq_s16_u16(vaddl_u8(A, B));
+ const int16x8_t D = LOAD_U8_TO_S16(&top[i - 1]);
+ const uint8x8_t E = vqmovun_s16(vsubq_s16(C, D));
+ const uint8x8_t F = vld1_u8(&row[i + 0]);
+ vst1_u8(&out[i], vsub_u8(F, E));
+ }
+ for (; i < length; ++i) {
+ out[i] = row[i] - GradientPredictor_C(row[i - 1], top[i], top[i - 1]);
+ }
+}
+
+static WEBP_INLINE void DoGradientFilter_NEON(const uint8_t* in,
+ int width, int height,
+ int stride,
+ int row, int num_rows,
+ 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_NEON(in + 1, out + 1, width - 1);
+ row = 1;
+ in += stride;
+ out += stride;
+ }
+
+ // Filter line-by-line.
+ while (row < last_row) {
+ out[0] = in[0] - in[-stride];
+ GradientPredictDirect_NEON(in + 1, in + 1 - stride, out + 1, width - 1);
+ ++row;
+ in += stride;
+ out += stride;
+ }
+}
+
+static void GradientFilter_NEON(const uint8_t* data, int width, int height,
+ int stride, uint8_t* filtered_data) {
+ DoGradientFilter_NEON(data, width, height, stride, 0, height,
+ filtered_data);
+}
+
+#undef SANITY_CHECK
+
+//------------------------------------------------------------------------------
+// Inverse transforms
+
+static void HorizontalUnfilter_NEON(const uint8_t* prev, const uint8_t* in,
+ uint8_t* out, int width) {
+ int i;
+ const uint8x16_t zero = vdupq_n_u8(0);
+ uint8x16_t last;
+ out[0] = in[0] + (prev == NULL ? 0 : prev[0]);
+ if (width <= 1) return;
+ last = vsetq_lane_u8(out[0], zero, 0);
+ for (i = 1; i + 16 <= width; i += 16) {
+ const uint8x16_t A0 = vld1q_u8(&in[i]);
+ const uint8x16_t A1 = vaddq_u8(A0, last);
+ const uint8x16_t A2 = SHIFT_LEFT_N_Q(A1, 1);
+ const uint8x16_t A3 = vaddq_u8(A1, A2);
+ const uint8x16_t A4 = SHIFT_LEFT_N_Q(A3, 2);
+ const uint8x16_t A5 = vaddq_u8(A3, A4);
+ const uint8x16_t A6 = SHIFT_LEFT_N_Q(A5, 4);
+ const uint8x16_t A7 = vaddq_u8(A5, A6);
+ const uint8x16_t A8 = SHIFT_LEFT_N_Q(A7, 8);
+ const uint8x16_t A9 = vaddq_u8(A7, A8);
+ vst1q_u8(&out[i], A9);
+ last = SHIFT_RIGHT_N_Q(A9, 15);
+ }
+ for (; i < width; ++i) out[i] = in[i] + out[i - 1];
+}
+
+static void VerticalUnfilter_NEON(const uint8_t* prev, const uint8_t* in,
+ uint8_t* out, int width) {
+ if (prev == NULL) {
+ HorizontalUnfilter_NEON(NULL, in, out, width);
+ } else {
+ int i;
+ assert(width >= 0);
+ for (i = 0; i + 16 <= width; i += 16) {
+ const uint8x16_t A = vld1q_u8(&in[i]);
+ const uint8x16_t B = vld1q_u8(&prev[i]);
+ const uint8x16_t C = vaddq_u8(A, B);
+ vst1q_u8(&out[i], C);
+ }
+ for (; i < width; ++i) out[i] = in[i] + prev[i];
+ }
+}
+
+// GradientUnfilter_NEON is correct but slower than the C-version,
+// at least on ARM64. For armv7, it's a wash.
+// So best is to disable it for now, but keep the idea around...
+// #define USE_GRADIENT_UNFILTER
+
+#if defined(USE_GRADIENT_UNFILTER)
+#define GRAD_PROCESS_LANE(L) do { \
+ const uint8x8_t tmp1 = ROTATE_RIGHT_N(pred, 1); /* rotate predictor in */ \
+ const int16x8_t tmp2 = vaddq_s16(BC, U8_TO_S16(tmp1)); \
+ const uint8x8_t delta = vqmovun_s16(tmp2); \
+ pred = vadd_u8(D, delta); \
+ out = vext_u8(out, ROTATE_LEFT_N(pred, (L)), 1); \
+} while (0)
+
+static void GradientPredictInverse_NEON(const uint8_t* const in,
+ const uint8_t* const top,
+ uint8_t* const row, int length) {
+ if (length > 0) {
+ int i;
+ uint8x8_t pred = vdup_n_u8(row[-1]); // left sample
+ uint8x8_t out = vdup_n_u8(0);
+ for (i = 0; i + 8 <= length; i += 8) {
+ const int16x8_t B = LOAD_U8_TO_S16(&top[i + 0]);
+ const int16x8_t C = LOAD_U8_TO_S16(&top[i - 1]);
+ const int16x8_t BC = vsubq_s16(B, C); // unclipped gradient basis B - C
+ const uint8x8_t D = vld1_u8(&in[i]); // base input
+ GRAD_PROCESS_LANE(0);
+ GRAD_PROCESS_LANE(1);
+ GRAD_PROCESS_LANE(2);
+ GRAD_PROCESS_LANE(3);
+ GRAD_PROCESS_LANE(4);
+ GRAD_PROCESS_LANE(5);
+ GRAD_PROCESS_LANE(6);
+ GRAD_PROCESS_LANE(7);
+ vst1_u8(&row[i], out);
+ }
+ for (; i < length; ++i) {
+ row[i] = in[i] + GradientPredictor_C(row[i - 1], top[i], top[i - 1]);
+ }
+ }
+}
+#undef GRAD_PROCESS_LANE
+
+static void GradientUnfilter_NEON(const uint8_t* prev, const uint8_t* in,
+ uint8_t* out, int width) {
+ if (prev == NULL) {
+ HorizontalUnfilter_NEON(NULL, in, out, width);
+ } else {
+ out[0] = in[0] + prev[0]; // predict from above
+ GradientPredictInverse_NEON(in + 1, prev + 1, out + 1, width - 1);
+ }
+}
+
+#endif // USE_GRADIENT_UNFILTER
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8FiltersInitNEON(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitNEON(void) {
+ WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_NEON;
+ WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_NEON;
+#if defined(USE_GRADIENT_UNFILTER)
+ WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_NEON;
+#endif
+
+ WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_NEON;
+ WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_NEON;
+ WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_NEON;
+}
+
+#else // !WEBP_USE_NEON
+
+WEBP_DSP_INIT_STUB(VP8FiltersInitNEON)
+
+#endif // WEBP_USE_NEON
diff --git a/thirdparty/libwebp/dsp/lossless.c b/thirdparty/libwebp/dsp/lossless.c
index af913efccb..20d18f6ecd 100644
--- a/thirdparty/libwebp/dsp/lossless.c
+++ b/thirdparty/libwebp/dsp/lossless.c
@@ -17,20 +17,16 @@
#include <math.h>
#include <stdlib.h>
-#include "../dec/vp8li.h"
-#include "../utils/endian_inl.h"
+#include "../dec/vp8li_dec.h"
+#include "../utils/endian_inl_utils.h"
#include "./lossless.h"
+#include "./lossless_common.h"
#define MAX_DIFF_COST (1e30f)
//------------------------------------------------------------------------------
// Image transforms.
-// In-place sum of each component with mod 256.
-static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
- *a = VP8LAddPixels(*a, b);
-}
-
static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1);
}
@@ -171,21 +167,41 @@ static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
return pred;
}
+GENERATE_PREDICTOR_ADD(Predictor0, PredictorAdd0)
+static void PredictorAdd1(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint32_t left = out[-1];
+ for (i = 0; i < num_pixels; ++i) {
+ out[i] = left = VP8LAddPixels(in[i], left);
+ }
+ (void)upper;
+}
+GENERATE_PREDICTOR_ADD(Predictor2, PredictorAdd2)
+GENERATE_PREDICTOR_ADD(Predictor3, PredictorAdd3)
+GENERATE_PREDICTOR_ADD(Predictor4, PredictorAdd4)
+GENERATE_PREDICTOR_ADD(Predictor5, PredictorAdd5)
+GENERATE_PREDICTOR_ADD(Predictor6, PredictorAdd6)
+GENERATE_PREDICTOR_ADD(Predictor7, PredictorAdd7)
+GENERATE_PREDICTOR_ADD(Predictor8, PredictorAdd8)
+GENERATE_PREDICTOR_ADD(Predictor9, PredictorAdd9)
+GENERATE_PREDICTOR_ADD(Predictor10, PredictorAdd10)
+GENERATE_PREDICTOR_ADD(Predictor11, PredictorAdd11)
+GENERATE_PREDICTOR_ADD(Predictor12, PredictorAdd12)
+GENERATE_PREDICTOR_ADD(Predictor13, PredictorAdd13)
+
//------------------------------------------------------------------------------
// Inverse prediction.
static void PredictorInverseTransform(const VP8LTransform* const transform,
- int y_start, int y_end, uint32_t* data) {
+ int y_start, int y_end,
+ const uint32_t* in, uint32_t* out) {
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;
+ PredictorAdd0(in, NULL, 1, out);
+ PredictorAdd1(in + 1, NULL, width - 1, out + 1);
+ in += width;
+ out += width;
++y_start;
}
@@ -193,36 +209,26 @@ static void PredictorInverseTransform(const VP8LTransform* const transform,
int y = y_start;
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) {
- const uint32_t pred2 = Predictor2(data[-1], data - width);
const uint32_t* pred_mode_src = pred_mode_base;
- VP8LPredictorFunc pred_func;
int x = 1;
- int t = 1;
// First pixel follows the T (mode=2) mode.
- AddPixelsEq(data, pred2);
+ PredictorAdd2(in, out - width, 1, out);
// .. the rest:
- 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);
- }
+ while (x < width) {
+ const VP8LPredictorAddSubFunc pred_func =
+ VP8LPredictorsAdd[((*pred_mode_src++) >> 8) & 0xf];
+ int x_end = (x & ~mask) + tile_width;
+ if (x_end > width) x_end = width;
+ pred_func(in + x, out + x - width, x_end - x, out + x);
+ x = x_end;
}
- data += width;
+ in += width;
+ out += width;
++y;
if ((y & mask) == 0) { // Use the same mask, since tiles are squares.
pred_mode_base += tiles_per_row;
@@ -233,21 +239,22 @@ static void PredictorInverseTransform(const VP8LTransform* const transform,
// Add green to blue and red channels (i.e. perform the inverse transform of
// 'subtract green').
-void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) {
+void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels,
+ uint32_t* dst) {
int i;
for (i = 0; i < num_pixels; ++i) {
- const uint32_t argb = data[i];
+ const uint32_t argb = src[i];
const uint32_t green = ((argb >> 8) & 0xff);
uint32_t red_blue = (argb & 0x00ff00ffu);
red_blue += (green << 16) | green;
red_blue &= 0x00ff00ffu;
- data[i] = (argb & 0xff00ff00u) | red_blue;
+ dst[i] = (argb & 0xff00ff00u) | red_blue;
}
}
-static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
- int8_t color) {
- return (uint32_t)((int)(color_pred) * color) >> 5;
+static WEBP_INLINE int ColorTransformDelta(int8_t color_pred,
+ int8_t color) {
+ return ((int)color_pred * color) >> 5;
}
static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
@@ -257,27 +264,29 @@ static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
m->red_to_blue_ = (color_code >> 16) & 0xff;
}
-void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data,
- int num_pixels) {
+void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
+ const uint32_t* src, int num_pixels,
+ uint32_t* dst) {
int i;
for (i = 0; i < num_pixels; ++i) {
- const uint32_t argb = data[i];
+ const uint32_t argb = src[i];
const uint32_t green = argb >> 8;
const uint32_t red = argb >> 16;
- uint32_t new_red = red;
- uint32_t new_blue = argb;
+ int new_red = red;
+ int 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;
- data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
+ dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
}
}
// Color space inverse transform.
static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
- int y_start, int y_end, uint32_t* data) {
+ int y_start, int y_end,
+ const uint32_t* src, uint32_t* dst) {
const int width = transform->xsize_;
const int tile_width = 1 << transform->bits_;
const int mask = tile_width - 1;
@@ -291,17 +300,19 @@ static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
while (y < y_end) {
const uint32_t* pred = pred_row;
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) {
+ const uint32_t* const src_safe_end = src + safe_width;
+ const uint32_t* const src_end = src + width;
+ while (src < src_safe_end) {
ColorCodeToMultipliers(*pred++, &m);
- VP8LTransformColorInverse(&m, data, tile_width);
- data += tile_width;
+ VP8LTransformColorInverse(&m, src, tile_width, dst);
+ src += tile_width;
+ dst += tile_width;
}
- if (data < data_end) { // Left-overs using C-version.
+ if (src < src_end) { // Left-overs using C-version.
ColorCodeToMultipliers(*pred++, &m);
- VP8LTransformColorInverse(&m, data, remaining_width);
- data += remaining_width;
+ VP8LTransformColorInverse(&m, src, remaining_width, dst);
+ src += remaining_width;
+ dst += remaining_width;
}
++y;
if ((y & mask) == 0) pred_row += tiles_per_row;
@@ -366,10 +377,10 @@ void VP8LInverseTransform(const VP8LTransform* const transform,
assert(row_end <= transform->ysize_);
switch (transform->type_) {
case SUBTRACT_GREEN:
- VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width);
+ VP8LAddGreenToBlueAndRed(in, (row_end - row_start) * width, out);
break;
case PREDICTOR_TRANSFORM:
- PredictorInverseTransform(transform, row_start, row_end, out);
+ PredictorInverseTransform(transform, row_start, row_end, in, 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.
@@ -378,7 +389,7 @@ void VP8LInverseTransform(const VP8LTransform* const transform,
}
break;
case CROSS_COLOR_TRANSFORM:
- ColorSpaceInverseTransform(transform, row_start, row_end, out);
+ ColorSpaceInverseTransform(transform, row_start, row_end, in, out);
break;
case COLOR_INDEXING_TRANSFORM:
if (in == out && transform->bits_ > 0) {
@@ -555,10 +566,15 @@ void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
//------------------------------------------------------------------------------
-VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
+VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed;
+VP8LPredictorAddSubFunc VP8LPredictorsAdd[16];
VP8LPredictorFunc VP8LPredictors[16];
-VP8LTransformColorFunc VP8LTransformColorInverse;
+// exposed plain-C implementations
+VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16];
+VP8LPredictorFunc VP8LPredictors_C[16];
+
+VP8LTransformColorInverseFunc VP8LTransformColorInverse;
VP8LConvertFunc VP8LConvertBGRAToRGB;
VP8LConvertFunc VP8LConvertBGRAToRGBA;
@@ -572,29 +588,37 @@ VP8LMapAlphaFunc VP8LMapColor8b;
extern void VP8LDspInitSSE2(void);
extern void VP8LDspInitNEON(void);
extern void VP8LDspInitMIPSdspR2(void);
+extern void VP8LDspInitMSA(void);
static volatile VP8CPUInfo lossless_last_cpuinfo_used =
(VP8CPUInfo)&lossless_last_cpuinfo_used;
+#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \
+ (OUT)[0] = IN##0; \
+ (OUT)[1] = IN##1; \
+ (OUT)[2] = IN##2; \
+ (OUT)[3] = IN##3; \
+ (OUT)[4] = IN##4; \
+ (OUT)[5] = IN##5; \
+ (OUT)[6] = IN##6; \
+ (OUT)[7] = IN##7; \
+ (OUT)[8] = IN##8; \
+ (OUT)[9] = IN##9; \
+ (OUT)[10] = IN##10; \
+ (OUT)[11] = IN##11; \
+ (OUT)[12] = IN##12; \
+ (OUT)[13] = IN##13; \
+ (OUT)[14] = IN##0; /* <- padding security sentinels*/ \
+ (OUT)[15] = IN##0; \
+} while (0);
+
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;
+ COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors)
+ COPY_PREDICTOR_ARRAY(Predictor, VP8LPredictors_C)
+ COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd)
+ COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C)
VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C;
@@ -626,8 +650,14 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) {
VP8LDspInitMIPSdspR2();
}
#endif
+#if defined(WEBP_USE_MSA)
+ if (VP8GetCPUInfo(kMSA)) {
+ VP8LDspInitMSA();
+ }
+#endif
}
lossless_last_cpuinfo_used = VP8GetCPUInfo;
}
+#undef COPY_PREDICTOR_ARRAY
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dsp/lossless.h b/thirdparty/libwebp/dsp/lossless.h
index 9f0d7a25b7..352a54e509 100644
--- a/thirdparty/libwebp/dsp/lossless.h
+++ b/thirdparty/libwebp/dsp/lossless.h
@@ -18,7 +18,7 @@
#include "../webp/types.h"
#include "../webp/decode.h"
-#include "../enc/histogram.h"
+#include "../enc/histogram_enc.h"
#include "../utils/utils.h"
#ifdef __cplusplus
@@ -26,7 +26,7 @@ extern "C" {
#endif
#ifdef WEBP_EXPERIMENTAL_FEATURES
-#include "../enc/delta_palettization.h"
+#include "../enc/delta_palettization_enc.h"
#endif // WEBP_EXPERIMENTAL_FEATURES
//------------------------------------------------------------------------------
@@ -34,9 +34,17 @@ extern "C" {
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;
+extern VP8LPredictorFunc VP8LPredictors_C[16];
+// These Add/Sub function expects upper[-1] and out[-1] to be readable.
+typedef void (*VP8LPredictorAddSubFunc)(const uint32_t* in,
+ const uint32_t* upper, int num_pixels,
+ uint32_t* out);
+extern VP8LPredictorAddSubFunc VP8LPredictorsAdd[16];
+extern VP8LPredictorAddSubFunc VP8LPredictorsAdd_C[16];
+
+typedef void (*VP8LProcessDecBlueAndRedFunc)(const uint32_t* src,
+ int num_pixels, uint32_t* dst);
+extern VP8LProcessDecBlueAndRedFunc VP8LAddGreenToBlueAndRed;
typedef struct {
// Note: the members are uint8_t, so that any negative values are
@@ -45,9 +53,10 @@ typedef struct {
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;
+typedef void (*VP8LTransformColorInverseFunc)(const VP8LMultipliers* const m,
+ const uint32_t* src,
+ int num_pixels, uint32_t* dst);
+extern VP8LTransformColorInverseFunc VP8LTransformColorInverse;
struct VP8LTransform; // Defined in dec/vp8li.h.
@@ -72,23 +81,6 @@ extern VP8LConvertFunc VP8LConvertBGRAToBGR;
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,
@@ -110,7 +102,8 @@ void VP8LColorIndexInverseTransformAlpha(
// Expose some C-only fallback functions
void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
- uint32_t* data, int num_pixels);
+ const uint32_t* src, int num_pixels,
+ uint32_t* dst);
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);
@@ -119,7 +112,8 @@ void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
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);
+void VP8LAddGreenToBlueAndRed_C(const uint32_t* src, int num_pixels,
+ uint32_t* dst);
// Must be called before calling any of the above methods.
void VP8LDspInit(void);
@@ -127,7 +121,10 @@ void VP8LDspInit(void);
//------------------------------------------------------------------------------
// Encoding
-extern VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
+typedef void (*VP8LProcessEncBlueAndRedFunc)(uint32_t* dst, int num_pixels);
+extern VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
+typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m,
+ uint32_t* const dst, int num_pixels);
extern VP8LTransformColorFunc VP8LTransformColor;
typedef void (*VP8LCollectColorBlueTransformsFunc)(
const uint32_t* argb, int stride,
@@ -153,62 +150,8 @@ void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride,
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, int near_lossless, int exact,
- int used_subtract_green);
-
-void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
- uint32_t* const argb, uint32_t* image);
-
-//------------------------------------------------------------------------------
-// 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;
-}
-
-// Converts near lossless quality into max number of bits shaved off.
-static WEBP_INLINE int VP8LNearLosslessBits(int near_lossless_quality) {
- // 100 -> 0
- // 80..99 -> 1
- // 60..79 -> 2
- // 40..59 -> 3
- // 20..39 -> 4
- // 0..19 -> 5
- return 5 - near_lossless_quality / 20;
-}
-
-// -----------------------------------------------------------------------------
-// Faster logarithm for integers. Small values use a look-up table.
-
-// 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
-#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(uint32_t v) {
- return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v);
-}
+extern VP8LPredictorAddSubFunc VP8LPredictorsSub[16];
+extern VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16];
// -----------------------------------------------------------------------------
// Huffman-cost related functions.
@@ -228,11 +171,6 @@ typedef struct { // small struct to hold counters
int streaks[2][2]; // [zero/non-zero][streak<3 / streak>=3]
} VP8LStreaks;
-typedef VP8LStreaks (*VP8LCostCombinedCountFunc)(const uint32_t* X,
- const uint32_t* Y, int length);
-
-extern VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
-
typedef struct { // small struct to hold bit entropy results
double entropy; // entropy
uint32_t sum; // sum of the population
@@ -246,26 +184,20 @@ void VP8LBitEntropyInit(VP8LBitEntropy* const entropy);
// Get the combined symbol bit entropy and Huffman cost stats for the
// distributions 'X' and 'Y'. Those results can then be refined according to
// codec specific heuristics.
-void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X,
- const uint32_t* const Y, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats);
+typedef void (*VP8LGetCombinedEntropyUnrefinedFunc)(
+ const uint32_t X[], const uint32_t Y[], int length,
+ VP8LBitEntropy* const bit_entropy, VP8LStreaks* const stats);
+extern VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined;
+
// Get the entropy for the distribution 'X'.
-void VP8LGetEntropyUnrefined(const uint32_t* const X, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats);
+typedef void (*VP8LGetEntropyUnrefinedFunc)(const uint32_t X[], int length,
+ VP8LBitEntropy* const bit_entropy,
+ VP8LStreaks* const stats);
+extern VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
void VP8LBitsEntropyUnrefined(const uint32_t* const array, int n,
VP8LBitEntropy* const entropy);
-typedef void (*GetEntropyUnrefinedHelperFunc)(uint32_t val, int i,
- uint32_t* const val_prev,
- int* const i_prev,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats);
-// Internal function used by VP8LGet*EntropyUnrefined.
-extern GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper;
-
typedef void (*VP8LHistogramAddFunc)(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out);
@@ -279,86 +211,11 @@ typedef int (*VP8LVectorMismatchFunc)(const uint32_t* const array1,
// Returns the first index where array1 and array2 are different.
extern VP8LVectorMismatchFunc VP8LVectorMismatch;
-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);
- }
-}
-
-// Sum of each component, mod 256.
-static WEBP_INLINE uint32_t VP8LAddPixels(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);
- return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
-}
-
-// Difference of each component, 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);
-}
-
-void VP8LBundleColorMap(const uint8_t* const row, int width,
- int xbits, uint32_t* const dst);
+typedef void (*VP8LBundleColorMapFunc)(const uint8_t* const row, int width,
+ int xbits, uint32_t* dst);
+extern VP8LBundleColorMapFunc VP8LBundleColorMap;
+void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits,
+ uint32_t* dst);
// Must be called before calling any of the above methods.
void VP8LEncDspInit(void);
diff --git a/thirdparty/libwebp/dsp/lossless_common.h b/thirdparty/libwebp/dsp/lossless_common.h
new file mode 100644
index 0000000000..c40f711208
--- /dev/null
+++ b/thirdparty/libwebp/dsp/lossless_common.h
@@ -0,0 +1,210 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Image transforms and color space conversion methods for lossless decoder.
+//
+// Authors: Vikas Arora (vikaas.arora@gmail.com)
+// Jyrki Alakuijala (jyrki@google.com)
+// Vincent Rabaud (vrabaud@google.com)
+
+#ifndef WEBP_DSP_LOSSLESS_COMMON_H_
+#define WEBP_DSP_LOSSLESS_COMMON_H_
+
+#include "../webp/types.h"
+
+#include "../utils/utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Decoding
+
+// 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;
+}
+
+//------------------------------------------------------------------------------
+// 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;
+}
+
+// Converts near lossless quality into max number of bits shaved off.
+static WEBP_INLINE int VP8LNearLosslessBits(int near_lossless_quality) {
+ // 100 -> 0
+ // 80..99 -> 1
+ // 60..79 -> 2
+ // 40..59 -> 3
+ // 20..39 -> 4
+ // 0..19 -> 5
+ return 5 - near_lossless_quality / 20;
+}
+
+// -----------------------------------------------------------------------------
+// Faster logarithm for integers. Small values use a look-up table.
+
+// 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
+#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(uint32_t v) {
+ return (v < LOG_LOOKUP_IDX_MAX) ? kSLog2Table[v] : VP8LFastSLog2Slow(v);
+}
+
+// -----------------------------------------------------------------------------
+// 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;
+ }
+ 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);
+ }
+}
+
+// Sum of each component, mod 256.
+static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
+uint32_t VP8LAddPixels(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);
+ return (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
+}
+
+// Difference of each component, mod 256.
+static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW 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);
+}
+
+//------------------------------------------------------------------------------
+// Transform-related functions use din both encoding and decoding.
+
+// Macros used to create a batch predictor that iteratively uses a
+// one-pixel predictor.
+
+// The predictor is added to the output pixel (which
+// is therefore considered as a residual) to get the final prediction.
+#define GENERATE_PREDICTOR_ADD(PREDICTOR, PREDICTOR_ADD) \
+static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
+ int num_pixels, uint32_t* out) { \
+ int x; \
+ for (x = 0; x < num_pixels; ++x) { \
+ const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \
+ out[x] = VP8LAddPixels(in[x], pred); \
+ } \
+}
+
+// It subtracts the prediction from the input pixel and stores the residual
+// in the output pixel.
+#define GENERATE_PREDICTOR_SUB(PREDICTOR, PREDICTOR_SUB) \
+static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \
+ int num_pixels, uint32_t* out) { \
+ int x; \
+ for (x = 0; x < num_pixels; ++x) { \
+ const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \
+ out[x] = VP8LSubPixels(in[x], pred); \
+ } \
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // WEBP_DSP_LOSSLESS_COMMON_H_
diff --git a/thirdparty/libwebp/dsp/lossless_enc.c b/thirdparty/libwebp/dsp/lossless_enc.c
index 256f6f5f8b..4e46fbab8b 100644
--- a/thirdparty/libwebp/dsp/lossless_enc.c
+++ b/thirdparty/libwebp/dsp/lossless_enc.c
@@ -17,16 +17,12 @@
#include <math.h>
#include <stdlib.h>
-#include "../dec/vp8li.h"
-#include "../utils/endian_inl.h"
+#include "../dec/vp8li_dec.h"
+#include "../utils/endian_inl_utils.h"
#include "./lossless.h"
+#include "./lossless_common.h"
#include "./yuv.h"
-#define MAX_DIFF_COST (1e30f)
-
-static const int kPredLowEffort = 11;
-static const uint32_t kMaskAlpha = 0xff000000;
-
// lookup table for small values of log2(int)
const float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
0.0000000000000000f, 0.0000000000000000f,
@@ -380,26 +376,9 @@ static float FastLog2Slow(uint32_t v) {
}
}
-// Mostly used to reduce code size + readability
-static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; }
-static WEBP_INLINE int GetMax(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;
@@ -422,18 +401,6 @@ static float CombinedShannonEntropy(const int X[256], const int Y[256]) {
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 += VP8LCombinedShannonEntropy(tile[i], accumulated[i]);
- }
- return (float)retval;
-}
-
void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) {
entropy->entropy = 0.;
entropy->sum = 0;
@@ -486,9 +453,9 @@ static WEBP_INLINE void GetEntropyUnrefinedHelper(
*i_prev = i;
}
-void VP8LGetEntropyUnrefined(const uint32_t* const X, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats) {
+static void GetEntropyUnrefined(const uint32_t X[], int length,
+ VP8LBitEntropy* const bit_entropy,
+ VP8LStreaks* const stats) {
int i;
int i_prev = 0;
uint32_t x_prev = X[0];
@@ -499,18 +466,18 @@ void VP8LGetEntropyUnrefined(const uint32_t* const X, int length,
for (i = 1; i < length; ++i) {
const uint32_t x = X[i];
if (x != x_prev) {
- VP8LGetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats);
+ GetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats);
}
}
- VP8LGetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats);
+ GetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats);
bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum);
}
-void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X,
- const uint32_t* const Y, int length,
- VP8LBitEntropy* const bit_entropy,
- VP8LStreaks* const stats) {
+static void GetCombinedEntropyUnrefined(const uint32_t X[], const uint32_t Y[],
+ int length,
+ VP8LBitEntropy* const bit_entropy,
+ VP8LStreaks* const stats) {
int i = 1;
int i_prev = 0;
uint32_t xy_prev = X[0] + Y[0];
@@ -521,439 +488,29 @@ void VP8LGetCombinedEntropyUnrefined(const uint32_t* const X,
for (i = 1; i < length; ++i) {
const uint32_t xy = X[i] + Y[i];
if (xy != xy_prev) {
- VP8LGetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy,
- stats);
+ GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, stats);
}
}
- VP8LGetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats);
+ GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats);
bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum);
}
-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];
-}
-
//------------------------------------------------------------------------------
-static WEBP_INLINE uint32_t Predict(VP8LPredictorFunc pred_func,
- int x, int y,
- const uint32_t* current_row,
- const uint32_t* upper_row) {
- if (y == 0) {
- return (x == 0) ? ARGB_BLACK : current_row[x - 1]; // Left.
- } else if (x == 0) {
- return upper_row[x]; // Top.
- } else {
- return pred_func(current_row[x - 1], upper_row + x);
- }
-}
-
-static int MaxDiffBetweenPixels(uint32_t p1, uint32_t p2) {
- const int diff_a = abs((int)(p1 >> 24) - (int)(p2 >> 24));
- const int diff_r = abs((int)((p1 >> 16) & 0xff) - (int)((p2 >> 16) & 0xff));
- const int diff_g = abs((int)((p1 >> 8) & 0xff) - (int)((p2 >> 8) & 0xff));
- const int diff_b = abs((int)(p1 & 0xff) - (int)(p2 & 0xff));
- return GetMax(GetMax(diff_a, diff_r), GetMax(diff_g, diff_b));
-}
-
-static int MaxDiffAroundPixel(uint32_t current, uint32_t up, uint32_t down,
- uint32_t left, uint32_t right) {
- const int diff_up = MaxDiffBetweenPixels(current, up);
- const int diff_down = MaxDiffBetweenPixels(current, down);
- const int diff_left = MaxDiffBetweenPixels(current, left);
- const int diff_right = MaxDiffBetweenPixels(current, right);
- return GetMax(GetMax(diff_up, diff_down), GetMax(diff_left, diff_right));
-}
-
-static uint32_t AddGreenToBlueAndRed(uint32_t argb) {
- const uint32_t green = (argb >> 8) & 0xff;
- uint32_t red_blue = argb & 0x00ff00ffu;
- red_blue += (green << 16) | green;
- red_blue &= 0x00ff00ffu;
- return (argb & 0xff00ff00u) | red_blue;
-}
-
-static void MaxDiffsForRow(int width, int stride, const uint32_t* const argb,
- uint8_t* const max_diffs, int used_subtract_green) {
- uint32_t current, up, down, left, right;
- int x;
- if (width <= 2) return;
- current = argb[0];
- right = argb[1];
- if (used_subtract_green) {
- current = AddGreenToBlueAndRed(current);
- right = AddGreenToBlueAndRed(right);
- }
- // max_diffs[0] and max_diffs[width - 1] are never used.
- for (x = 1; x < width - 1; ++x) {
- up = argb[-stride + x];
- down = argb[stride + x];
- left = current;
- current = right;
- right = argb[x + 1];
- if (used_subtract_green) {
- up = AddGreenToBlueAndRed(up);
- down = AddGreenToBlueAndRed(down);
- right = AddGreenToBlueAndRed(right);
- }
- max_diffs[x] = MaxDiffAroundPixel(current, up, down, left, right);
- }
-}
-
-// Quantize the difference between the actual component value and its prediction
-// to a multiple of quantization, working modulo 256, taking care not to cross
-// a boundary (inclusive upper limit).
-static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict,
- uint8_t boundary, int quantization) {
- const int residual = (value - predict) & 0xff;
- const int boundary_residual = (boundary - predict) & 0xff;
- const int lower = residual & ~(quantization - 1);
- const int upper = lower + quantization;
- // Resolve ties towards a value closer to the prediction (i.e. towards lower
- // if value comes after prediction and towards upper otherwise).
- const int bias = ((boundary - value) & 0xff) < boundary_residual;
- if (residual - lower < upper - residual + bias) {
- // lower is closer to residual than upper.
- if (residual > boundary_residual && lower <= boundary_residual) {
- // Halve quantization step to avoid crossing boundary. This midpoint is
- // on the same side of boundary as residual because midpoint >= residual
- // (since lower is closer than upper) and residual is above the boundary.
- return lower + (quantization >> 1);
- }
- return lower;
- } else {
- // upper is closer to residual than lower.
- if (residual <= boundary_residual && upper > boundary_residual) {
- // Halve quantization step to avoid crossing boundary. This midpoint is
- // on the same side of boundary as residual because midpoint <= residual
- // (since upper is closer than lower) and residual is below the boundary.
- return lower + (quantization >> 1);
- }
- return upper & 0xff;
- }
-}
-
-// Quantize every component of the difference between the actual pixel value and
-// its prediction to a multiple of a quantization (a power of 2, not larger than
-// max_quantization which is a power of 2, smaller than max_diff). Take care if
-// value and predict have undergone subtract green, which means that red and
-// blue are represented as offsets from green.
-static uint32_t NearLossless(uint32_t value, uint32_t predict,
- int max_quantization, int max_diff,
- int used_subtract_green) {
- int quantization;
- uint8_t new_green = 0;
- uint8_t green_diff = 0;
- uint8_t a, r, g, b;
- if (max_diff <= 2) {
- return VP8LSubPixels(value, predict);
- }
- quantization = max_quantization;
- while (quantization >= max_diff) {
- quantization >>= 1;
- }
- if ((value >> 24) == 0 || (value >> 24) == 0xff) {
- // Preserve transparency of fully transparent or fully opaque pixels.
- a = ((value >> 24) - (predict >> 24)) & 0xff;
- } else {
- a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization);
- }
- g = NearLosslessComponent((value >> 8) & 0xff, (predict >> 8) & 0xff, 0xff,
- quantization);
- if (used_subtract_green) {
- // The green offset will be added to red and blue components during decoding
- // to obtain the actual red and blue values.
- new_green = ((predict >> 8) + g) & 0xff;
- // The amount by which green has been adjusted during quantization. It is
- // subtracted from red and blue for compensation, to avoid accumulating two
- // quantization errors in them.
- green_diff = (new_green - (value >> 8)) & 0xff;
- }
- r = NearLosslessComponent(((value >> 16) - green_diff) & 0xff,
- (predict >> 16) & 0xff, 0xff - new_green,
- quantization);
- b = NearLosslessComponent((value - green_diff) & 0xff, predict & 0xff,
- 0xff - new_green, quantization);
- return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
-}
-
-// Returns the difference between the pixel and its prediction. In case of a
-// lossy encoding, updates the source image to avoid propagating the deviation
-// further to pixels which depend on the current pixel for their predictions.
-static WEBP_INLINE uint32_t GetResidual(int width, int height,
- uint32_t* const upper_row,
- uint32_t* const current_row,
- const uint8_t* const max_diffs,
- int mode, VP8LPredictorFunc pred_func,
- int x, int y, int max_quantization,
- int exact, int used_subtract_green) {
- const uint32_t predict = Predict(pred_func, x, y, current_row, upper_row);
- uint32_t residual;
- if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 ||
- x == 0 || x == width - 1) {
- residual = VP8LSubPixels(current_row[x], predict);
- } else {
- residual = NearLossless(current_row[x], predict, max_quantization,
- max_diffs[x], used_subtract_green);
- // Update the source image.
- current_row[x] = VP8LAddPixels(predict, residual);
- // x is never 0 here so we do not need to update upper_row like below.
- }
- if (!exact && (current_row[x] & kMaskAlpha) == 0) {
- // If alpha is 0, cleanup RGB. We can choose the RGB values of the residual
- // for best compression. The prediction of alpha itself can be non-zero and
- // must be kept though. We choose RGB of the residual to be 0.
- residual &= kMaskAlpha;
- // Update the source image.
- current_row[x] = predict & ~kMaskAlpha;
- // The prediction for the rightmost pixel in a row uses the leftmost pixel
- // in that row as its top-right context pixel. Hence if we change the
- // leftmost pixel of current_row, the corresponding change must be applied
- // to upper_row as well where top-right context is being read from.
- if (x == 0 && y != 0) upper_row[width] = current_row[0];
- }
- return residual;
-}
-
-// Returns best predictor and updates the accumulated histogram.
-// If max_quantization > 1, assumes that near lossless processing will be
-// applied, quantizing residuals to multiples of quantization levels up to
-// max_quantization (the actual quantization level depends on smoothness near
-// the given pixel).
-static int GetBestPredictorForTile(int width, int height,
- int tile_x, int tile_y, int bits,
- int accumulated[4][256],
- uint32_t* const argb_scratch,
- const uint32_t* const argb,
- int max_quantization,
- int exact, int used_subtract_green) {
- const int kNumPredModes = 14;
- const int start_x = tile_x << bits;
- const int start_y = tile_y << bits;
- const int tile_size = 1 << bits;
- const int max_y = GetMin(tile_size, height - start_y);
- const int max_x = GetMin(tile_size, width - start_x);
- // Whether there exist columns just outside the tile.
- const int have_left = (start_x > 0);
- const int have_right = (max_x < width - start_x);
- // Position and size of the strip covering the tile and adjacent columns if
- // they exist.
- const int context_start_x = start_x - have_left;
- const int context_width = max_x + have_left + have_right;
- // The width of upper_row and current_row is one pixel larger than image width
- // to allow the top right pixel to point to the leftmost pixel of the next row
- // when at the right edge.
- uint32_t* upper_row = argb_scratch;
- uint32_t* current_row = upper_row + width + 1;
- uint8_t* const max_diffs = (uint8_t*)(current_row + width + 1);
- 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 VP8LPredictorFunc pred_func = VP8LPredictors[mode];
- float cur_diff;
- int relative_y;
- memset(histo_argb, 0, sizeof(histo_stack_1));
- if (start_y > 0) {
- // Read the row above the tile which will become the first upper_row.
- // Include a pixel to the left if it exists; include a pixel to the right
- // in all cases (wrapping to the leftmost pixel of the next row if it does
- // not exist).
- memcpy(current_row + context_start_x,
- argb + (start_y - 1) * width + context_start_x,
- sizeof(*argb) * (max_x + have_left + 1));
- }
- for (relative_y = 0; relative_y < max_y; ++relative_y) {
- const int y = start_y + relative_y;
- int relative_x;
- uint32_t* tmp = upper_row;
- upper_row = current_row;
- current_row = tmp;
- // Read current_row. Include a pixel to the left if it exists; include a
- // pixel to the right in all cases except at the bottom right corner of
- // the image (wrapping to the leftmost pixel of the next row if it does
- // not exist in the current row).
- memcpy(current_row + context_start_x,
- argb + y * width + context_start_x,
- sizeof(*argb) * (max_x + have_left + (y + 1 < height)));
- if (max_quantization > 1 && y >= 1 && y + 1 < height) {
- MaxDiffsForRow(context_width, width, argb + y * width + context_start_x,
- max_diffs + context_start_x, used_subtract_green);
- }
-
- for (relative_x = 0; relative_x < max_x; ++relative_x) {
- const int x = start_x + relative_x;
- UpdateHisto(histo_argb,
- GetResidual(width, height, upper_row, current_row,
- max_diffs, mode, pred_func, x, y,
- max_quantization, exact, used_subtract_green));
- }
- }
- 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;
-}
-
-// Converts pixels of the image to residuals with respect to predictions.
-// If max_quantization > 1, applies near lossless processing, quantizing
-// residuals to multiples of quantization levels up to max_quantization
-// (the actual quantization level depends on smoothness near the given pixel).
-static void CopyImageWithPrediction(int width, int height,
- int bits, uint32_t* const modes,
- uint32_t* const argb_scratch,
- uint32_t* const argb,
- int low_effort, int max_quantization,
- int exact, int used_subtract_green) {
- const int tiles_per_row = VP8LSubSampleSize(width, bits);
- const int mask = (1 << bits) - 1;
- // The width of upper_row and current_row is one pixel larger than image width
- // to allow the top right pixel to point to the leftmost pixel of the next row
- // when at the right edge.
- uint32_t* upper_row = argb_scratch;
- uint32_t* current_row = upper_row + width + 1;
- uint8_t* current_max_diffs = (uint8_t*)(current_row + width + 1);
- uint8_t* lower_max_diffs = current_max_diffs + width;
- int y;
- int mode = 0;
- VP8LPredictorFunc pred_func = NULL;
-
- for (y = 0; y < height; ++y) {
- int x;
- uint32_t* const tmp32 = upper_row;
- upper_row = current_row;
- current_row = tmp32;
- memcpy(current_row, argb + y * width,
- sizeof(*argb) * (width + (y + 1 < height)));
-
- if (low_effort) {
- for (x = 0; x < width; ++x) {
- const uint32_t predict = Predict(VP8LPredictors[kPredLowEffort], x, y,
- current_row, upper_row);
- argb[y * width + x] = VP8LSubPixels(current_row[x], predict);
- }
- } else {
- if (max_quantization > 1) {
- // Compute max_diffs for the lower row now, because that needs the
- // contents of argb for the current row, which we will overwrite with
- // residuals before proceeding with the next row.
- uint8_t* const tmp8 = current_max_diffs;
- current_max_diffs = lower_max_diffs;
- lower_max_diffs = tmp8;
- if (y + 2 < height) {
- MaxDiffsForRow(width, width, argb + (y + 1) * width, lower_max_diffs,
- used_subtract_green);
- }
- }
- for (x = 0; x < width; ++x) {
- if ((x & mask) == 0) {
- mode = (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff;
- pred_func = VP8LPredictors[mode];
- }
- argb[y * width + x] = GetResidual(
- width, height, upper_row, current_row, current_max_diffs, mode,
- pred_func, x, y, max_quantization, exact, used_subtract_green);
- }
- }
- }
-}
-
-// Finds the best predictor for each tile, and converts the image to residuals
-// with respect to predictions. If near_lossless_quality < 100, applies
-// near lossless processing, shaving off more bits of residuals for lower
-// qualities.
-void VP8LResidualImage(int width, int height, int bits, int low_effort,
- uint32_t* const argb, uint32_t* const argb_scratch,
- uint32_t* const image, int near_lossless_quality,
- int exact, int used_subtract_green) {
- const int tiles_per_row = VP8LSubSampleSize(width, bits);
- const int tiles_per_col = VP8LSubSampleSize(height, bits);
- int tile_y;
- int histo[4][256];
- const int max_quantization = 1 << VP8LNearLosslessBits(near_lossless_quality);
- if (low_effort) {
- int i;
- for (i = 0; i < tiles_per_row * tiles_per_col; ++i) {
- image[i] = ARGB_BLACK | (kPredLowEffort << 8);
- }
- } else {
- memset(histo, 0, sizeof(histo));
- for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
- int tile_x;
- for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
- const int pred = GetBestPredictorForTile(width, height, tile_x, tile_y,
- bits, histo, argb_scratch, argb, max_quantization, exact,
- used_subtract_green);
- image[tile_y * tiles_per_row + tile_x] = ARGB_BLACK | (pred << 8);
- }
- }
- }
-
- CopyImageWithPrediction(width, height, bits, image, argb_scratch, argb,
- low_effort, max_quantization, exact,
- used_subtract_green);
-}
-
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 int argb = argb_data[i];
+ const int 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;
+ const uint32_t new_b = (((argb >> 0) & 0xff) - green) & 0xff;
+ argb_data[i] = (argb & 0xff00ff00u) | (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_;
+static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) {
+ return ((int)color_pred * color) >> 5;
}
void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
@@ -963,8 +520,8 @@ void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
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;
+ int new_red = red;
+ int new_blue = argb;
new_red -= ColorTransformDelta(m->green_to_red_, green);
new_red &= 0xff;
new_blue -= ColorTransformDelta(m->green_to_blue_, green);
@@ -977,7 +534,7 @@ void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
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;
+ int new_red = argb >> 16;
new_red -= ColorTransformDelta(green_to_red, green);
return (new_red & 0xff);
}
@@ -993,15 +550,6 @@ static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
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 VP8LCombinedShannonEntropy(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[]) {
@@ -1014,59 +562,6 @@ void VP8LCollectColorRedTransforms_C(const uint32_t* argb, int 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,
@@ -1080,187 +575,6 @@ void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int 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];
- }
- }
- }
- }
-}
-
//------------------------------------------------------------------------------
static int VectorMismatch(const uint32_t* const array1,
@@ -1274,8 +588,8 @@ static int VectorMismatch(const uint32_t* const array1,
}
// 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) {
+void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits,
+ uint32_t* dst) {
int x;
if (xbits > 0) {
const int bit_depth = 1 << (3 - xbits);
@@ -1350,8 +664,172 @@ static void HistogramAdd(const VP8LHistogram* const a,
}
//------------------------------------------------------------------------------
+// Image transforms.
-VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
+static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
+ return (((a0 ^ a1) & 0xfefefefeu) >> 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 ((uint32_t)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 ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
+}
+
+// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined.
+#if defined(__arm__) && \
+ (LOCAL_GCC_VERSION == 0x409 || LOCAL_GCC_VERSION == 0x408)
+# 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;
+}
+
+//------------------------------------------------------------------------------
+// Predictors
+
+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;
+}
+
+//------------------------------------------------------------------------------
+
+static void PredictorSub0_C(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], ARGB_BLACK);
+ (void)upper;
+}
+
+static void PredictorSub1_C(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], in[i - 1]);
+ (void)upper;
+}
+
+GENERATE_PREDICTOR_SUB(Predictor2, PredictorSub2_C)
+GENERATE_PREDICTOR_SUB(Predictor3, PredictorSub3_C)
+GENERATE_PREDICTOR_SUB(Predictor4, PredictorSub4_C)
+GENERATE_PREDICTOR_SUB(Predictor5, PredictorSub5_C)
+GENERATE_PREDICTOR_SUB(Predictor6, PredictorSub6_C)
+GENERATE_PREDICTOR_SUB(Predictor7, PredictorSub7_C)
+GENERATE_PREDICTOR_SUB(Predictor8, PredictorSub8_C)
+GENERATE_PREDICTOR_SUB(Predictor9, PredictorSub9_C)
+GENERATE_PREDICTOR_SUB(Predictor10, PredictorSub10_C)
+GENERATE_PREDICTOR_SUB(Predictor11, PredictorSub11_C)
+GENERATE_PREDICTOR_SUB(Predictor12, PredictorSub12_C)
+GENERATE_PREDICTOR_SUB(Predictor13, PredictorSub13_C)
+
+//------------------------------------------------------------------------------
+
+VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
VP8LTransformColorFunc VP8LTransformColor;
@@ -1365,17 +843,23 @@ VP8LCostFunc VP8LExtraCost;
VP8LCostCombinedFunc VP8LExtraCostCombined;
VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;
-GetEntropyUnrefinedHelperFunc VP8LGetEntropyUnrefinedHelper;
+VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;
+VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined;
VP8LHistogramAddFunc VP8LHistogramAdd;
VP8LVectorMismatchFunc VP8LVectorMismatch;
+VP8LBundleColorMapFunc VP8LBundleColorMap;
+
+VP8LPredictorAddSubFunc VP8LPredictorsSub[16];
+VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16];
extern void VP8LEncDspInitSSE2(void);
extern void VP8LEncDspInitSSE41(void);
extern void VP8LEncDspInitNEON(void);
extern void VP8LEncDspInitMIPS32(void);
extern void VP8LEncDspInitMIPSdspR2(void);
+extern void VP8LEncDspInitMSA(void);
static volatile VP8CPUInfo lossless_enc_last_cpuinfo_used =
(VP8CPUInfo)&lossless_enc_last_cpuinfo_used;
@@ -1399,11 +883,47 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
VP8LExtraCostCombined = ExtraCostCombined;
VP8LCombinedShannonEntropy = CombinedShannonEntropy;
- VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper;
+ VP8LGetEntropyUnrefined = GetEntropyUnrefined;
+ VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined;
VP8LHistogramAdd = HistogramAdd;
VP8LVectorMismatch = VectorMismatch;
+ VP8LBundleColorMap = VP8LBundleColorMap_C;
+
+ VP8LPredictorsSub[0] = PredictorSub0_C;
+ VP8LPredictorsSub[1] = PredictorSub1_C;
+ VP8LPredictorsSub[2] = PredictorSub2_C;
+ VP8LPredictorsSub[3] = PredictorSub3_C;
+ VP8LPredictorsSub[4] = PredictorSub4_C;
+ VP8LPredictorsSub[5] = PredictorSub5_C;
+ VP8LPredictorsSub[6] = PredictorSub6_C;
+ VP8LPredictorsSub[7] = PredictorSub7_C;
+ VP8LPredictorsSub[8] = PredictorSub8_C;
+ VP8LPredictorsSub[9] = PredictorSub9_C;
+ VP8LPredictorsSub[10] = PredictorSub10_C;
+ VP8LPredictorsSub[11] = PredictorSub11_C;
+ VP8LPredictorsSub[12] = PredictorSub12_C;
+ VP8LPredictorsSub[13] = PredictorSub13_C;
+ VP8LPredictorsSub[14] = PredictorSub0_C; // <- padding security sentinels
+ VP8LPredictorsSub[15] = PredictorSub0_C;
+
+ VP8LPredictorsSub_C[0] = PredictorSub0_C;
+ VP8LPredictorsSub_C[1] = PredictorSub1_C;
+ VP8LPredictorsSub_C[2] = PredictorSub2_C;
+ VP8LPredictorsSub_C[3] = PredictorSub3_C;
+ VP8LPredictorsSub_C[4] = PredictorSub4_C;
+ VP8LPredictorsSub_C[5] = PredictorSub5_C;
+ VP8LPredictorsSub_C[6] = PredictorSub6_C;
+ VP8LPredictorsSub_C[7] = PredictorSub7_C;
+ VP8LPredictorsSub_C[8] = PredictorSub8_C;
+ VP8LPredictorsSub_C[9] = PredictorSub9_C;
+ VP8LPredictorsSub_C[10] = PredictorSub10_C;
+ VP8LPredictorsSub_C[11] = PredictorSub11_C;
+ VP8LPredictorsSub_C[12] = PredictorSub12_C;
+ VP8LPredictorsSub_C[13] = PredictorSub13_C;
+ VP8LPredictorsSub_C[14] = PredictorSub0_C; // <- padding security sentinels
+ VP8LPredictorsSub_C[15] = PredictorSub0_C;
// If defined, use CPUInfo() to overwrite some pointers with faster versions.
if (VP8GetCPUInfo != NULL) {
@@ -1432,6 +952,11 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) {
VP8LEncDspInitMIPSdspR2();
}
#endif
+#if defined(WEBP_USE_MSA)
+ if (VP8GetCPUInfo(kMSA)) {
+ VP8LEncDspInitMSA();
+ }
+#endif
}
lossless_enc_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/dsp/lossless_enc_mips32.c b/thirdparty/libwebp/dsp/lossless_enc_mips32.c
index 49c666d4fd..4186b9f50d 100644
--- a/thirdparty/libwebp/dsp/lossless_enc_mips32.c
+++ b/thirdparty/libwebp/dsp/lossless_enc_mips32.c
@@ -14,6 +14,7 @@
#include "./dsp.h"
#include "./lossless.h"
+#include "./lossless_common.h"
#if defined(WEBP_USE_MIPS32)
@@ -240,6 +241,49 @@ static WEBP_INLINE void GetEntropyUnrefinedHelper(
*i_prev = i;
}
+static void GetEntropyUnrefined(const uint32_t X[], int length,
+ VP8LBitEntropy* const bit_entropy,
+ VP8LStreaks* const stats) {
+ int i;
+ int i_prev = 0;
+ uint32_t x_prev = X[0];
+
+ memset(stats, 0, sizeof(*stats));
+ VP8LBitEntropyInit(bit_entropy);
+
+ for (i = 1; i < length; ++i) {
+ const uint32_t x = X[i];
+ if (x != x_prev) {
+ GetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats);
+ }
+ }
+ GetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats);
+
+ bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum);
+}
+
+static void GetCombinedEntropyUnrefined(const uint32_t X[], const uint32_t Y[],
+ int length,
+ VP8LBitEntropy* const bit_entropy,
+ VP8LStreaks* const stats) {
+ int i = 1;
+ int i_prev = 0;
+ uint32_t xy_prev = X[0] + Y[0];
+
+ memset(stats, 0, sizeof(*stats));
+ VP8LBitEntropyInit(bit_entropy);
+
+ for (i = 1; i < length; ++i) {
+ const uint32_t xy = X[i] + Y[i];
+ if (xy != xy_prev) {
+ GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, stats);
+ }
+ }
+ GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats);
+
+ bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum);
+}
+
#define ASM_START \
__asm__ volatile( \
".set push \n\t" \
@@ -375,7 +419,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) {
VP8LFastLog2Slow = FastLog2Slow;
VP8LExtraCost = ExtraCost;
VP8LExtraCostCombined = ExtraCostCombined;
- VP8LGetEntropyUnrefinedHelper = GetEntropyUnrefinedHelper;
+ VP8LGetEntropyUnrefined = GetEntropyUnrefined;
+ VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined;
VP8LHistogramAdd = HistogramAdd;
}
diff --git a/thirdparty/libwebp/dsp/lossless_enc_msa.c b/thirdparty/libwebp/dsp/lossless_enc_msa.c
new file mode 100644
index 0000000000..2f69ba3bca
--- /dev/null
+++ b/thirdparty/libwebp/dsp/lossless_enc_msa.c
@@ -0,0 +1,147 @@
+// Copyright 2016 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.
+// -----------------------------------------------------------------------------
+//
+// MSA variant of Image transform methods for lossless encoder.
+//
+// Authors: Prashant Patil (Prashant.Patil@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MSA)
+
+#include "./lossless.h"
+#include "./msa_macro.h"
+
+#define TRANSFORM_COLOR_8(src0, src1, dst0, dst1, c0, c1, mask0, mask1) do { \
+ v8i16 g0, g1, t0, t1, t2, t3; \
+ v4i32 t4, t5; \
+ VSHF_B2_SH(src0, src0, src1, src1, mask0, mask0, g0, g1); \
+ DOTP_SB2_SH(g0, g1, c0, c0, t0, t1); \
+ SRAI_H2_SH(t0, t1, 5); \
+ t0 = __msa_subv_h((v8i16)src0, t0); \
+ t1 = __msa_subv_h((v8i16)src1, t1); \
+ t4 = __msa_srli_w((v4i32)src0, 16); \
+ t5 = __msa_srli_w((v4i32)src1, 16); \
+ DOTP_SB2_SH(t4, t5, c1, c1, t2, t3); \
+ SRAI_H2_SH(t2, t3, 5); \
+ SUB2(t0, t2, t1, t3, t0, t1); \
+ VSHF_B2_UB(src0, t0, src1, t1, mask1, mask1, dst0, dst1); \
+} while (0)
+
+#define TRANSFORM_COLOR_4(src, dst, c0, c1, mask0, mask1) do { \
+ const v16i8 g0 = VSHF_SB(src, src, mask0); \
+ v8i16 t0 = __msa_dotp_s_h(c0, g0); \
+ v8i16 t1; \
+ v4i32 t2; \
+ t0 = SRAI_H(t0, 5); \
+ t0 = __msa_subv_h((v8i16)src, t0); \
+ t2 = __msa_srli_w((v4i32)src, 16); \
+ t1 = __msa_dotp_s_h(c1, (v16i8)t2); \
+ t1 = SRAI_H(t1, 5); \
+ t0 = t0 - t1; \
+ dst = VSHF_UB(src, t0, mask1); \
+} while (0)
+
+static void TransformColor(const VP8LMultipliers* const m, uint32_t* data,
+ int num_pixels) {
+ v16u8 src0, dst0;
+ const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ |
+ (m->green_to_red_ << 16));
+ const v16i8 r2b = (v16i8)__msa_fill_w(m->red_to_blue_);
+ const v16u8 mask0 = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255,
+ 13, 255, 13, 255 };
+ const v16u8 mask1 = { 16, 1, 18, 3, 20, 5, 22, 7, 24, 9, 26, 11,
+ 28, 13, 30, 15 };
+
+ while (num_pixels >= 8) {
+ v16u8 src1, dst1;
+ LD_UB2(data, 4, src0, src1);
+ TRANSFORM_COLOR_8(src0, src1, dst0, dst1, g2br, r2b, mask0, mask1);
+ ST_UB2(dst0, dst1, data, 4);
+ data += 8;
+ num_pixels -= 8;
+ }
+ if (num_pixels > 0) {
+ if (num_pixels >= 4) {
+ src0 = LD_UB(data);
+ TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1);
+ ST_UB(dst0, data);
+ data += 4;
+ num_pixels -= 4;
+ }
+ if (num_pixels > 0) {
+ src0 = LD_UB(data);
+ TRANSFORM_COLOR_4(src0, dst0, g2br, r2b, mask0, mask1);
+ if (num_pixels == 3) {
+ const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0);
+ const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2);
+ SD(pix_d, data + 0);
+ SW(pix_w, data + 2);
+ } else if (num_pixels == 2) {
+ const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0);
+ SD(pix_d, data);
+ } else {
+ const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 0);
+ SW(pix_w, data);
+ }
+ }
+ }
+}
+
+static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
+ int i;
+ uint8_t* ptemp_data = (uint8_t*)argb_data;
+ v16u8 src0, dst0, tmp0;
+ const v16u8 mask = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255,
+ 13, 255, 13, 255 };
+
+ while (num_pixels >= 8) {
+ v16u8 src1, dst1, tmp1;
+ LD_UB2(ptemp_data, 16, src0, src1);
+ VSHF_B2_UB(src0, src1, src1, src0, mask, mask, tmp0, tmp1);
+ SUB2(src0, tmp0, src1, tmp1, dst0, dst1);
+ ST_UB2(dst0, dst1, ptemp_data, 16);
+ ptemp_data += 8 * 4;
+ num_pixels -= 8;
+ }
+ if (num_pixels > 0) {
+ if (num_pixels >= 4) {
+ src0 = LD_UB(ptemp_data);
+ tmp0 = VSHF_UB(src0, src0, mask);
+ dst0 = src0 - tmp0;
+ ST_UB(dst0, ptemp_data);
+ ptemp_data += 4 * 4;
+ num_pixels -= 4;
+ }
+ for (i = 0; i < num_pixels; i++) {
+ const uint8_t b = ptemp_data[0];
+ const uint8_t g = ptemp_data[1];
+ const uint8_t r = ptemp_data[2];
+ ptemp_data[0] = (b - g) & 0xff;
+ ptemp_data[2] = (r - g) & 0xff;
+ ptemp_data += 4;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LEncDspInitMSA(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMSA(void) {
+ VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed;
+ VP8LTransformColor = TransformColor;
+}
+
+#else // !WEBP_USE_MSA
+
+WEBP_DSP_INIT_STUB(VP8LEncDspInitMSA)
+
+#endif // WEBP_USE_MSA
diff --git a/thirdparty/libwebp/dsp/lossless_enc_sse2.c b/thirdparty/libwebp/dsp/lossless_enc_sse2.c
index 7c894e7ca4..8ad85d94d7 100644
--- a/thirdparty/libwebp/dsp/lossless_enc_sse2.c
+++ b/thirdparty/libwebp/dsp/lossless_enc_sse2.c
@@ -17,6 +17,8 @@
#include <assert.h>
#include <emmintrin.h>
#include "./lossless.h"
+#include "./common_sse2.h"
+#include "./lossless_common.h"
// For sign-extended multiplying constants, pre-shifted by 5:
#define CST_5b(X) (((int16_t)((uint16_t)X << 8)) >> 5)
@@ -35,7 +37,9 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
_mm_storeu_si128((__m128i*)&argb_data[i], out);
}
// fallthrough and finish off with plain-C
- VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
+ if (i != num_pixels) {
+ VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
+ }
}
//------------------------------------------------------------------------------
@@ -69,7 +73,9 @@ static void TransformColor(const VP8LMultipliers* const m,
_mm_storeu_si128((__m128i*)&argb_data[i], out);
}
// fallthrough and finish off with plain-C
- VP8LTransformColor_C(m, argb_data + i, num_pixels - i);
+ if (i != num_pixels) {
+ VP8LTransformColor_C(m, argb_data + i, num_pixels - i);
+ }
}
//------------------------------------------------------------------------------
@@ -364,8 +370,9 @@ static int VectorMismatch(const uint32_t* const array1,
if (length >= 8 &&
_mm_movemask_epi8(_mm_cmpeq_epi32(
_mm_loadu_si128((const __m128i*)&array1[4]),
- _mm_loadu_si128((const __m128i*)&array2[4]))) == 0xffff)
+ _mm_loadu_si128((const __m128i*)&array2[4]))) == 0xffff) {
match_len = 8;
+ }
}
}
@@ -375,6 +382,295 @@ static int VectorMismatch(const uint32_t* const array1,
return match_len;
}
+// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
+static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits,
+ uint32_t* dst) {
+ int x;
+ assert(xbits >= 0);
+ assert(xbits <= 3);
+ switch (xbits) {
+ case 0: {
+ const __m128i ff = _mm_set1_epi16(0xff00);
+ const __m128i zero = _mm_setzero_si128();
+ // Store 0xff000000 | (row[x] << 8).
+ for (x = 0; x + 16 <= width; x += 16, dst += 16) {
+ const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]);
+ const __m128i in_lo = _mm_unpacklo_epi8(zero, in);
+ const __m128i dst0 = _mm_unpacklo_epi16(in_lo, ff);
+ const __m128i dst1 = _mm_unpackhi_epi16(in_lo, ff);
+ const __m128i in_hi = _mm_unpackhi_epi8(zero, in);
+ const __m128i dst2 = _mm_unpacklo_epi16(in_hi, ff);
+ const __m128i dst3 = _mm_unpackhi_epi16(in_hi, ff);
+ _mm_storeu_si128((__m128i*)&dst[0], dst0);
+ _mm_storeu_si128((__m128i*)&dst[4], dst1);
+ _mm_storeu_si128((__m128i*)&dst[8], dst2);
+ _mm_storeu_si128((__m128i*)&dst[12], dst3);
+ }
+ break;
+ }
+ case 1: {
+ const __m128i ff = _mm_set1_epi16(0xff00);
+ const __m128i mul = _mm_set1_epi16(0x110);
+ for (x = 0; x + 16 <= width; x += 16, dst += 8) {
+ // 0a0b | (where a/b are 4 bits).
+ const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]);
+ const __m128i tmp = _mm_mullo_epi16(in, mul); // aba0
+ const __m128i pack = _mm_and_si128(tmp, ff); // ab00
+ const __m128i dst0 = _mm_unpacklo_epi16(pack, ff);
+ const __m128i dst1 = _mm_unpackhi_epi16(pack, ff);
+ _mm_storeu_si128((__m128i*)&dst[0], dst0);
+ _mm_storeu_si128((__m128i*)&dst[4], dst1);
+ }
+ break;
+ }
+ case 2: {
+ const __m128i mask_or = _mm_set1_epi32(0xff000000);
+ const __m128i mul_cst = _mm_set1_epi16(0x0104);
+ const __m128i mask_mul = _mm_set1_epi16(0x0f00);
+ for (x = 0; x + 16 <= width; x += 16, dst += 4) {
+ // 000a000b000c000d | (where a/b/c/d are 2 bits).
+ const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]);
+ const __m128i mul = _mm_mullo_epi16(in, mul_cst); // 00ab00b000cd00d0
+ const __m128i tmp = _mm_and_si128(mul, mask_mul); // 00ab000000cd0000
+ const __m128i shift = _mm_srli_epi32(tmp, 12); // 00000000ab000000
+ const __m128i pack = _mm_or_si128(shift, tmp); // 00000000abcd0000
+ // Convert to 0xff00**00.
+ const __m128i res = _mm_or_si128(pack, mask_or);
+ _mm_storeu_si128((__m128i*)dst, res);
+ }
+ break;
+ }
+ default: {
+ assert(xbits == 3);
+ for (x = 0; x + 16 <= width; x += 16, dst += 2) {
+ // 0000000a00000000b... | (where a/b are 1 bit).
+ const __m128i in = _mm_loadu_si128((const __m128i*)&row[x]);
+ const __m128i shift = _mm_slli_epi64(in, 7);
+ const uint32_t move = _mm_movemask_epi8(shift);
+ dst[0] = 0xff000000 | ((move & 0xff) << 8);
+ dst[1] = 0xff000000 | (move & 0xff00);
+ }
+ break;
+ }
+ }
+ if (x != width) {
+ VP8LBundleColorMap_C(row + x, width - x, xbits, dst);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Batch version of Predictor Transform subtraction
+
+static WEBP_INLINE void Average2_m128i(const __m128i* const a0,
+ const __m128i* const a1,
+ __m128i* const avg) {
+ // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1)
+ const __m128i ones = _mm_set1_epi8(1);
+ const __m128i avg1 = _mm_avg_epu8(*a0, *a1);
+ const __m128i one = _mm_and_si128(_mm_xor_si128(*a0, *a1), ones);
+ *avg = _mm_sub_epi8(avg1, one);
+}
+
+// Predictor0: ARGB_BLACK.
+static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ const __m128i black = _mm_set1_epi32(ARGB_BLACK);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ const __m128i res = _mm_sub_epi8(src, black);
+ _mm_storeu_si128((__m128i*)&out[i], res);
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsSub_C[0](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+#define GENERATE_PREDICTOR_1(X, IN) \
+static void PredictorSub##X##_SSE2(const uint32_t* in, const uint32_t* upper, \
+ int num_pixels, uint32_t* out) { \
+ int i; \
+ for (i = 0; i + 4 <= num_pixels; i += 4) { \
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \
+ const __m128i pred = _mm_loadu_si128((const __m128i*)&(IN)); \
+ const __m128i res = _mm_sub_epi8(src, pred); \
+ _mm_storeu_si128((__m128i*)&out[i], res); \
+ } \
+ if (i != num_pixels) { \
+ VP8LPredictorsSub_C[(X)](in + i, upper + i, num_pixels - i, out + i); \
+ } \
+}
+
+GENERATE_PREDICTOR_1(1, in[i - 1]) // Predictor1: L
+GENERATE_PREDICTOR_1(2, upper[i]) // Predictor2: T
+GENERATE_PREDICTOR_1(3, upper[i + 1]) // Predictor3: TR
+GENERATE_PREDICTOR_1(4, upper[i - 1]) // Predictor4: TL
+#undef GENERATE_PREDICTOR_1
+
+// Predictor5: avg2(avg2(L, TR), T)
+static void PredictorSub5_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]);
+ const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
+ const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]);
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ __m128i avg, pred, res;
+ Average2_m128i(&L, &TR, &avg);
+ Average2_m128i(&avg, &T, &pred);
+ res = _mm_sub_epi8(src, pred);
+ _mm_storeu_si128((__m128i*)&out[i], res);
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsSub_C[5](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+#define GENERATE_PREDICTOR_2(X, A, B) \
+static void PredictorSub##X##_SSE2(const uint32_t* in, const uint32_t* upper, \
+ int num_pixels, uint32_t* out) { \
+ int i; \
+ for (i = 0; i + 4 <= num_pixels; i += 4) { \
+ const __m128i tA = _mm_loadu_si128((const __m128i*)&(A)); \
+ const __m128i tB = _mm_loadu_si128((const __m128i*)&(B)); \
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \
+ __m128i pred, res; \
+ Average2_m128i(&tA, &tB, &pred); \
+ res = _mm_sub_epi8(src, pred); \
+ _mm_storeu_si128((__m128i*)&out[i], res); \
+ } \
+ if (i != num_pixels) { \
+ VP8LPredictorsSub_C[(X)](in + i, upper + i, num_pixels - i, out + i); \
+ } \
+}
+
+GENERATE_PREDICTOR_2(6, in[i - 1], upper[i - 1]) // Predictor6: avg(L, TL)
+GENERATE_PREDICTOR_2(7, in[i - 1], upper[i]) // Predictor7: avg(L, T)
+GENERATE_PREDICTOR_2(8, upper[i - 1], upper[i]) // Predictor8: avg(TL, T)
+GENERATE_PREDICTOR_2(9, upper[i], upper[i + 1]) // Predictor9: average(T, TR)
+#undef GENERATE_PREDICTOR_2
+
+// Predictor10: avg(avg(L,TL), avg(T, TR)).
+static void PredictorSub10_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]);
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
+ const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
+ const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]);
+ __m128i avgTTR, avgLTL, avg, res;
+ Average2_m128i(&T, &TR, &avgTTR);
+ Average2_m128i(&L, &TL, &avgLTL);
+ Average2_m128i(&avgTTR, &avgLTL, &avg);
+ res = _mm_sub_epi8(src, avg);
+ _mm_storeu_si128((__m128i*)&out[i], res);
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsSub_C[10](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+// Predictor11: select.
+static void GetSumAbsDiff32(const __m128i* const A, const __m128i* const B,
+ __m128i* const out) {
+ // We can unpack with any value on the upper 32 bits, provided it's the same
+ // on both operands (to that their sum of abs diff is zero). Here we use *A.
+ const __m128i A_lo = _mm_unpacklo_epi32(*A, *A);
+ const __m128i B_lo = _mm_unpacklo_epi32(*B, *A);
+ const __m128i A_hi = _mm_unpackhi_epi32(*A, *A);
+ const __m128i B_hi = _mm_unpackhi_epi32(*B, *A);
+ const __m128i s_lo = _mm_sad_epu8(A_lo, B_lo);
+ const __m128i s_hi = _mm_sad_epu8(A_hi, B_hi);
+ *out = _mm_packs_epi32(s_lo, s_hi);
+}
+
+static void PredictorSub11_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]);
+ const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
+ const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ __m128i pa, pb;
+ GetSumAbsDiff32(&T, &TL, &pa); // pa = sum |T-TL|
+ GetSumAbsDiff32(&L, &TL, &pb); // pb = sum |L-TL|
+ {
+ const __m128i mask = _mm_cmpgt_epi32(pb, pa);
+ const __m128i A = _mm_and_si128(mask, L);
+ const __m128i B = _mm_andnot_si128(mask, T);
+ const __m128i pred = _mm_or_si128(A, B); // pred = (L > T)? L : T
+ const __m128i res = _mm_sub_epi8(src, pred);
+ _mm_storeu_si128((__m128i*)&out[i], res);
+ }
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsSub_C[11](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+// Predictor12: ClampedSubSubtractFull.
+static void PredictorSub12_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ const __m128i zero = _mm_setzero_si128();
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ const __m128i L = _mm_loadu_si128((const __m128i*)&in[i - 1]);
+ const __m128i L_lo = _mm_unpacklo_epi8(L, zero);
+ const __m128i L_hi = _mm_unpackhi_epi8(L, zero);
+ const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
+ const __m128i T_lo = _mm_unpacklo_epi8(T, zero);
+ const __m128i T_hi = _mm_unpackhi_epi8(T, zero);
+ const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
+ const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero);
+ const __m128i TL_hi = _mm_unpackhi_epi8(TL, zero);
+ const __m128i diff_lo = _mm_sub_epi16(T_lo, TL_lo);
+ const __m128i diff_hi = _mm_sub_epi16(T_hi, TL_hi);
+ const __m128i pred_lo = _mm_add_epi16(L_lo, diff_lo);
+ const __m128i pred_hi = _mm_add_epi16(L_hi, diff_hi);
+ const __m128i pred = _mm_packus_epi16(pred_lo, pred_hi);
+ const __m128i res = _mm_sub_epi8(src, pred);
+ _mm_storeu_si128((__m128i*)&out[i], res);
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsSub_C[12](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+// Predictors13: ClampedAddSubtractHalf
+static void PredictorSub13_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ const __m128i zero = _mm_setzero_si128();
+ for (i = 0; i + 2 <= num_pixels; i += 2) {
+ // we can only process two pixels at a time
+ const __m128i L = _mm_loadl_epi64((const __m128i*)&in[i - 1]);
+ const __m128i src = _mm_loadl_epi64((const __m128i*)&in[i]);
+ const __m128i T = _mm_loadl_epi64((const __m128i*)&upper[i]);
+ const __m128i TL = _mm_loadl_epi64((const __m128i*)&upper[i - 1]);
+ const __m128i L_lo = _mm_unpacklo_epi8(L, zero);
+ const __m128i T_lo = _mm_unpacklo_epi8(T, zero);
+ const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero);
+ const __m128i sum = _mm_add_epi16(T_lo, L_lo);
+ const __m128i avg = _mm_srli_epi16(sum, 1);
+ const __m128i A1 = _mm_sub_epi16(avg, TL_lo);
+ const __m128i bit_fix = _mm_cmpgt_epi16(TL_lo, avg);
+ const __m128i A2 = _mm_sub_epi16(A1, bit_fix);
+ const __m128i A3 = _mm_srai_epi16(A2, 1);
+ const __m128i A4 = _mm_add_epi16(avg, A3);
+ const __m128i pred = _mm_packus_epi16(A4, A4);
+ const __m128i res = _mm_sub_epi8(src, pred);
+ _mm_storel_epi64((__m128i*)&out[i], res);
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsSub_C[13](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
//------------------------------------------------------------------------------
// Entry point
@@ -388,6 +684,24 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
VP8LHistogramAdd = HistogramAdd;
VP8LCombinedShannonEntropy = CombinedShannonEntropy;
VP8LVectorMismatch = VectorMismatch;
+ VP8LBundleColorMap = BundleColorMap_SSE2;
+
+ VP8LPredictorsSub[0] = PredictorSub0_SSE2;
+ VP8LPredictorsSub[1] = PredictorSub1_SSE2;
+ VP8LPredictorsSub[2] = PredictorSub2_SSE2;
+ VP8LPredictorsSub[3] = PredictorSub3_SSE2;
+ VP8LPredictorsSub[4] = PredictorSub4_SSE2;
+ VP8LPredictorsSub[5] = PredictorSub5_SSE2;
+ VP8LPredictorsSub[6] = PredictorSub6_SSE2;
+ VP8LPredictorsSub[7] = PredictorSub7_SSE2;
+ VP8LPredictorsSub[8] = PredictorSub8_SSE2;
+ VP8LPredictorsSub[9] = PredictorSub9_SSE2;
+ VP8LPredictorsSub[10] = PredictorSub10_SSE2;
+ VP8LPredictorsSub[11] = PredictorSub11_SSE2;
+ VP8LPredictorsSub[12] = PredictorSub12_SSE2;
+ VP8LPredictorsSub[13] = PredictorSub13_SSE2;
+ VP8LPredictorsSub[14] = PredictorSub0_SSE2; // <- padding security sentinels
+ VP8LPredictorsSub[15] = PredictorSub0_SSE2;
}
#else // !WEBP_USE_SSE2
diff --git a/thirdparty/libwebp/dsp/lossless_enc_sse41.c b/thirdparty/libwebp/dsp/lossless_enc_sse41.c
index 3e493198db..821057ccd4 100644
--- a/thirdparty/libwebp/dsp/lossless_enc_sse41.c
+++ b/thirdparty/libwebp/dsp/lossless_enc_sse41.c
@@ -32,7 +32,9 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) {
_mm_storeu_si128((__m128i*)&argb_data[i], out);
}
// fallthrough and finish off with plain-C
- VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
+ if (i != num_pixels) {
+ VP8LSubtractGreenFromBlueAndRed_C(argb_data + i, num_pixels - i);
+ }
}
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c b/thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c
index 90aed7f151..2984ce8df7 100644
--- a/thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c
+++ b/thirdparty/libwebp/dsp/lossless_mips_dsp_r2.c
@@ -17,6 +17,7 @@
#if defined(WEBP_USE_MIPS_DSP_R2)
#include "./lossless.h"
+#include "./lossless_common.h"
#define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \
static void FUNC_NAME(const TYPE* src, \
@@ -227,25 +228,27 @@ static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
// 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) {
+static void AddGreenToBlueAndRed(const uint32_t* src, int num_pixels,
+ uint32_t* dst) {
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;
+ 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 %[data], %[p_loop1_end], 3f \n\t"
+ "beq %[src], %[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"
+ "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, 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"
+ "addiu %[src], %[src], 16 \n\t"
+ "addiu %[dst], %[dst], 16 \n\t"
"replv.ph %[temp4], %[temp4] \n\t"
"replv.ph %[temp5], %[temp5] \n\t"
"replv.ph %[temp6], %[temp6] \n\t"
@@ -254,44 +257,47 @@ static void AddGreenToBlueAndRed(uint32_t* data, int num_pixels) {
"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"
+ "sw %[temp0], -16(%[dst]) \n\t"
+ "sw %[temp1], -12(%[dst]) \n\t"
+ "sw %[temp2], -8(%[dst]) \n\t"
+ "bne %[src], %[p_loop1_end], 0b \n\t"
+ " sw %[temp3], -4(%[dst]) \n\t"
"3: \n\t"
- "beq %[data], %[p_loop2_end], 2f \n\t"
+ "beq %[src], %[p_loop2_end], 2f \n\t"
" nop \n\t"
"1: \n\t"
- "lw %[temp0], 0(%[data]) \n\t"
- "addiu %[data], %[data], 4 \n\t"
+ "lw %[temp0], 0(%[src]) \n\t"
+ "addiu %[src], %[src], 4 \n\t"
+ "addiu %[dst], %[dst], 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"
+ "bne %[src], %[p_loop2_end], 1b \n\t"
+ " sw %[temp0], -4(%[dst]) \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)
+ : [dst]"+&r"(dst), [src]"+&r"(src), [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) {
+ const uint32_t* src, int num_pixels,
+ uint32_t* dst) {
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);
+ const uint32_t* const p_loop_end = src + (num_pixels & ~1);
__asm__ volatile (
".set push \n\t"
".set noreorder \n\t"
- "beq %[data], %[p_loop_end], 1f \n\t"
+ "beq %[src], %[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"
@@ -303,9 +309,12 @@ static void TransformColorInverse(const VP8LMultipliers* const m,
"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"
+ "lw %[argb], 0(%[src]) \n\t"
+ "lw %[argb1], 4(%[src]) \n\t"
+ "sw %[argb], 0(%[dst]) \n\t"
+ "sw %[argb1], 4(%[dst]) \n\t"
+ "addiu %[src], %[src], 8 \n\t"
+ "addiu %[dst], %[dst], 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"
@@ -322,29 +331,29 @@ static void TransformColorInverse(const VP8LMultipliers* const m,
"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"
+ "sb %[temp5], -2(%[dst]) \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"
+ "sb %[temp5], -6(%[dst]) \n\t"
+ "sb %[temp3], -4(%[dst]) \n\t"
"sra %[temp3], %[temp3], 16 \n\t"
- "bne %[data], %[p_loop_end], 0b \n\t"
- " sb %[temp3], -8(%[data]) \n\t"
+ "bne %[src], %[p_loop_end], 0b \n\t"
+ " sb %[temp3], -8(%[dst]) \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)
+ [argb1]"=&r"(argb1), [dst]"+&r"(dst), [src]"+&r"(src)
: [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);
+ if (num_pixels & 1) VP8LTransformColorInverse_C(m, src, 1, dst);
}
static void ConvertBGRAToRGB(const uint32_t* src,
diff --git a/thirdparty/libwebp/dsp/lossless_msa.c b/thirdparty/libwebp/dsp/lossless_msa.c
new file mode 100644
index 0000000000..f6dd5649ac
--- /dev/null
+++ b/thirdparty/libwebp/dsp/lossless_msa.c
@@ -0,0 +1,355 @@
+// Copyright 2016 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.
+// -----------------------------------------------------------------------------
+//
+// MSA variant of methods for lossless decoder
+//
+// Author: Prashant Patil (prashant.patil@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MSA)
+
+#include "./lossless.h"
+#include "./msa_macro.h"
+
+//------------------------------------------------------------------------------
+// Colorspace conversion functions
+
+#define CONVERT16_BGRA_XXX(psrc, pdst, m0, m1, m2) do { \
+ v16u8 src0, src1, src2, src3, dst0, dst1, dst2; \
+ LD_UB4(psrc, 16, src0, src1, src2, src3); \
+ VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \
+ dst2 = VSHF_UB(src2, src3, m2); \
+ ST_UB2(dst0, dst1, pdst, 16); \
+ ST_UB(dst2, pdst + 32); \
+} while (0)
+
+#define CONVERT12_BGRA_XXX(psrc, pdst, m0, m1, m2) do { \
+ uint32_t pix_w; \
+ v16u8 src0, src1, src2, dst0, dst1, dst2; \
+ LD_UB3(psrc, 16, src0, src1, src2); \
+ VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \
+ dst2 = VSHF_UB(src2, src2, m2); \
+ ST_UB2(dst0, dst1, pdst, 16); \
+ pix_w = __msa_copy_s_w((v4i32)dst2, 0); \
+ SW(pix_w, pdst + 32); \
+} while (0)
+
+#define CONVERT8_BGRA_XXX(psrc, pdst, m0, m1) do { \
+ uint64_t pix_d; \
+ v16u8 src0, src1, src2, dst0, dst1; \
+ LD_UB2(psrc, 16, src0, src1); \
+ VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \
+ ST_UB(dst0, pdst); \
+ pix_d = __msa_copy_s_d((v2i64)dst1, 0); \
+ SD(pix_d, pdst + 16); \
+} while (0)
+
+#define CONVERT4_BGRA_XXX(psrc, pdst, m) do { \
+ const v16u8 src0 = LD_UB(psrc); \
+ const v16u8 dst0 = VSHF_UB(src0, src0, m); \
+ uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0); \
+ uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2); \
+ SD(pix_d, pdst + 0); \
+ SW(pix_w, pdst + 8); \
+} while (0)
+
+#define CONVERT1_BGRA_BGR(psrc, pdst) do { \
+ const int32_t b = (psrc)[0]; \
+ const int32_t g = (psrc)[1]; \
+ const int32_t r = (psrc)[2]; \
+ (pdst)[0] = b; \
+ (pdst)[1] = g; \
+ (pdst)[2] = r; \
+} while (0)
+
+#define CONVERT1_BGRA_RGB(psrc, pdst) do { \
+ const int32_t b = (psrc)[0]; \
+ const int32_t g = (psrc)[1]; \
+ const int32_t r = (psrc)[2]; \
+ (pdst)[0] = r; \
+ (pdst)[1] = g; \
+ (pdst)[2] = b; \
+} while (0)
+
+#define TRANSFORM_COLOR_INVERSE_8(src0, src1, dst0, dst1, \
+ c0, c1, mask0, mask1) do { \
+ v8i16 g0, g1, t0, t1, t2, t3; \
+ v4i32 t4, t5; \
+ VSHF_B2_SH(src0, src0, src1, src1, mask0, mask0, g0, g1); \
+ DOTP_SB2_SH(g0, g1, c0, c0, t0, t1); \
+ SRAI_H2_SH(t0, t1, 5); \
+ t0 = __msa_addv_h(t0, (v8i16)src0); \
+ t1 = __msa_addv_h(t1, (v8i16)src1); \
+ t4 = __msa_srli_w((v4i32)t0, 16); \
+ t5 = __msa_srli_w((v4i32)t1, 16); \
+ DOTP_SB2_SH(t4, t5, c1, c1, t2, t3); \
+ SRAI_H2_SH(t2, t3, 5); \
+ ADD2(t0, t2, t1, t3, t0, t1); \
+ VSHF_B2_UB(src0, t0, src1, t1, mask1, mask1, dst0, dst1); \
+} while (0)
+
+#define TRANSFORM_COLOR_INVERSE_4(src, dst, c0, c1, mask0, mask1) do { \
+ const v16i8 g0 = VSHF_SB(src, src, mask0); \
+ v8i16 t0 = __msa_dotp_s_h(c0, g0); \
+ v8i16 t1; \
+ v4i32 t2; \
+ t0 = SRAI_H(t0, 5); \
+ t0 = __msa_addv_h(t0, (v8i16)src); \
+ t2 = __msa_srli_w((v4i32)t0, 16); \
+ t1 = __msa_dotp_s_h(c1, (v16i8)t2); \
+ t1 = SRAI_H(t1, 5); \
+ t0 = t0 + t1; \
+ dst = VSHF_UB(src, t0, mask1); \
+} while (0)
+
+static void ConvertBGRAToRGBA(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ int i;
+ const uint8_t* ptemp_src = (const uint8_t*)src;
+ uint8_t* ptemp_dst = (uint8_t*)dst;
+ v16u8 src0, dst0;
+ const v16u8 mask = { 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15 };
+
+ while (num_pixels >= 8) {
+ v16u8 src1, dst1;
+ LD_UB2(ptemp_src, 16, src0, src1);
+ VSHF_B2_UB(src0, src0, src1, src1, mask, mask, dst0, dst1);
+ ST_UB2(dst0, dst1, ptemp_dst, 16);
+ ptemp_src += 32;
+ ptemp_dst += 32;
+ num_pixels -= 8;
+ }
+ if (num_pixels > 0) {
+ if (num_pixels >= 4) {
+ src0 = LD_UB(ptemp_src);
+ dst0 = VSHF_UB(src0, src0, mask);
+ ST_UB(dst0, ptemp_dst);
+ ptemp_src += 16;
+ ptemp_dst += 16;
+ num_pixels -= 4;
+ }
+ for (i = 0; i < num_pixels; i++) {
+ const uint8_t b = ptemp_src[2];
+ const uint8_t g = ptemp_src[1];
+ const uint8_t r = ptemp_src[0];
+ const uint8_t a = ptemp_src[3];
+ ptemp_dst[0] = b;
+ ptemp_dst[1] = g;
+ ptemp_dst[2] = r;
+ ptemp_dst[3] = a;
+ ptemp_src += 4;
+ ptemp_dst += 4;
+ }
+ }
+}
+
+static void ConvertBGRAToBGR(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint8_t* ptemp_src = (const uint8_t*)src;
+ uint8_t* ptemp_dst = (uint8_t*)dst;
+ const v16u8 mask0 = { 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14,
+ 16, 17, 18, 20 };
+ const v16u8 mask1 = { 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20,
+ 21, 22, 24, 25 };
+ const v16u8 mask2 = { 10, 12, 13, 14, 16, 17, 18, 20, 21, 22, 24, 25,
+ 26, 28, 29, 30 };
+
+ while (num_pixels >= 16) {
+ CONVERT16_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2);
+ ptemp_src += 64;
+ ptemp_dst += 48;
+ num_pixels -= 16;
+ }
+ if (num_pixels > 0) {
+ if (num_pixels >= 12) {
+ CONVERT12_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2);
+ ptemp_src += 48;
+ ptemp_dst += 36;
+ num_pixels -= 12;
+ } else if (num_pixels >= 8) {
+ CONVERT8_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1);
+ ptemp_src += 32;
+ ptemp_dst += 24;
+ num_pixels -= 8;
+ } else if (num_pixels >= 4) {
+ CONVERT4_BGRA_XXX(ptemp_src, ptemp_dst, mask0);
+ ptemp_src += 16;
+ ptemp_dst += 12;
+ num_pixels -= 4;
+ }
+ if (num_pixels == 3) {
+ CONVERT1_BGRA_BGR(ptemp_src + 0, ptemp_dst + 0);
+ CONVERT1_BGRA_BGR(ptemp_src + 4, ptemp_dst + 3);
+ CONVERT1_BGRA_BGR(ptemp_src + 8, ptemp_dst + 6);
+ } else if (num_pixels == 2) {
+ CONVERT1_BGRA_BGR(ptemp_src + 0, ptemp_dst + 0);
+ CONVERT1_BGRA_BGR(ptemp_src + 4, ptemp_dst + 3);
+ } else if (num_pixels == 1) {
+ CONVERT1_BGRA_BGR(ptemp_src, ptemp_dst);
+ }
+ }
+}
+
+static void ConvertBGRAToRGB(const uint32_t* src,
+ int num_pixels, uint8_t* dst) {
+ const uint8_t* ptemp_src = (const uint8_t*)src;
+ uint8_t* ptemp_dst = (uint8_t*)dst;
+ const v16u8 mask0 = { 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12,
+ 18, 17, 16, 22 };
+ const v16u8 mask1 = { 5, 4, 10, 9, 8, 14, 13, 12, 18, 17, 16, 22,
+ 21, 20, 26, 25 };
+ const v16u8 mask2 = { 8, 14, 13, 12, 18, 17, 16, 22, 21, 20, 26, 25,
+ 24, 30, 29, 28 };
+
+ while (num_pixels >= 16) {
+ CONVERT16_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2);
+ ptemp_src += 64;
+ ptemp_dst += 48;
+ num_pixels -= 16;
+ }
+ if (num_pixels) {
+ if (num_pixels >= 12) {
+ CONVERT12_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1, mask2);
+ ptemp_src += 48;
+ ptemp_dst += 36;
+ num_pixels -= 12;
+ } else if (num_pixels >= 8) {
+ CONVERT8_BGRA_XXX(ptemp_src, ptemp_dst, mask0, mask1);
+ ptemp_src += 32;
+ ptemp_dst += 24;
+ num_pixels -= 8;
+ } else if (num_pixels >= 4) {
+ CONVERT4_BGRA_XXX(ptemp_src, ptemp_dst, mask0);
+ ptemp_src += 16;
+ ptemp_dst += 12;
+ num_pixels -= 4;
+ }
+ if (num_pixels == 3) {
+ CONVERT1_BGRA_RGB(ptemp_src + 0, ptemp_dst + 0);
+ CONVERT1_BGRA_RGB(ptemp_src + 4, ptemp_dst + 3);
+ CONVERT1_BGRA_RGB(ptemp_src + 8, ptemp_dst + 6);
+ } else if (num_pixels == 2) {
+ CONVERT1_BGRA_RGB(ptemp_src + 0, ptemp_dst + 0);
+ CONVERT1_BGRA_RGB(ptemp_src + 4, ptemp_dst + 3);
+ } else if (num_pixels == 1) {
+ CONVERT1_BGRA_RGB(ptemp_src, ptemp_dst);
+ }
+ }
+}
+
+static void AddGreenToBlueAndRed(const uint32_t* const src, int num_pixels,
+ uint32_t* dst) {
+ int i;
+ const uint8_t* in = (const uint8_t*)src;
+ uint8_t* out = (uint8_t*)dst;
+ v16u8 src0, dst0, tmp0;
+ const v16u8 mask = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255,
+ 13, 255, 13, 255 };
+
+ while (num_pixels >= 8) {
+ v16u8 src1, dst1, tmp1;
+ LD_UB2(in, 16, src0, src1);
+ VSHF_B2_UB(src0, src1, src1, src0, mask, mask, tmp0, tmp1);
+ ADD2(src0, tmp0, src1, tmp1, dst0, dst1);
+ ST_UB2(dst0, dst1, out, 16);
+ in += 32;
+ out += 32;
+ num_pixels -= 8;
+ }
+ if (num_pixels > 0) {
+ if (num_pixels >= 4) {
+ src0 = LD_UB(in);
+ tmp0 = VSHF_UB(src0, src0, mask);
+ dst0 = src0 + tmp0;
+ ST_UB(dst0, out);
+ in += 16;
+ out += 16;
+ num_pixels -= 4;
+ }
+ for (i = 0; i < num_pixels; i++) {
+ const uint8_t b = in[0];
+ const uint8_t g = in[1];
+ const uint8_t r = in[2];
+ out[0] = (b + g) & 0xff;
+ out[1] = g;
+ out[2] = (r + g) & 0xff;
+ out[4] = in[4];
+ out += 4;
+ }
+ }
+}
+
+static void TransformColorInverse(const VP8LMultipliers* const m,
+ const uint32_t* src, int num_pixels,
+ uint32_t* dst) {
+ v16u8 src0, dst0;
+ const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ |
+ (m->green_to_red_ << 16));
+ const v16i8 r2b = (v16i8)__msa_fill_w(m->red_to_blue_);
+ const v16u8 mask0 = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255,
+ 13, 255, 13, 255 };
+ const v16u8 mask1 = { 16, 1, 18, 3, 20, 5, 22, 7, 24, 9, 26, 11,
+ 28, 13, 30, 15 };
+
+ while (num_pixels >= 8) {
+ v16u8 src1, dst1;
+ LD_UB2(src, 4, src0, src1);
+ TRANSFORM_COLOR_INVERSE_8(src0, src1, dst0, dst1, g2br, r2b, mask0, mask1);
+ ST_UB2(dst0, dst1, dst, 4);
+ src += 8;
+ dst += 8;
+ num_pixels -= 8;
+ }
+ if (num_pixels > 0) {
+ if (num_pixels >= 4) {
+ src0 = LD_UB(src);
+ TRANSFORM_COLOR_INVERSE_4(src0, dst0, g2br, r2b, mask0, mask1);
+ ST_UB(dst0, dst);
+ src += 4;
+ dst += 4;
+ num_pixels -= 4;
+ }
+ if (num_pixels > 0) {
+ src0 = LD_UB(src);
+ TRANSFORM_COLOR_INVERSE_4(src0, dst0, g2br, r2b, mask0, mask1);
+ if (num_pixels == 3) {
+ const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0);
+ const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 2);
+ SD(pix_d, dst + 0);
+ SW(pix_w, dst + 2);
+ } else if (num_pixels == 2) {
+ const uint64_t pix_d = __msa_copy_s_d((v2i64)dst0, 0);
+ SD(pix_d, dst);
+ } else {
+ const uint32_t pix_w = __msa_copy_s_w((v4i32)dst0, 0);
+ SW(pix_w, dst);
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void VP8LDspInitMSA(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMSA(void) {
+ VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
+ VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
+ VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
+ VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
+ VP8LTransformColorInverse = TransformColorInverse;
+}
+
+#else // !WEBP_USE_MSA
+
+WEBP_DSP_INIT_STUB(VP8LDspInitMSA)
+
+#endif // WEBP_USE_MSA
diff --git a/thirdparty/libwebp/dsp/lossless_neon.c b/thirdparty/libwebp/dsp/lossless_neon.c
index 6faccb8f97..1145d5fad0 100644
--- a/thirdparty/libwebp/dsp/lossless_neon.c
+++ b/thirdparty/libwebp/dsp/lossless_neon.c
@@ -139,6 +139,357 @@ static void ConvertBGRAToRGB(const uint32_t* src,
#endif // !WORK_AROUND_GCC
+
+//------------------------------------------------------------------------------
+// Predictor Transform
+
+#define LOAD_U32_AS_U8(IN) vreinterpret_u8_u32(vdup_n_u32((IN)))
+#define LOAD_U32P_AS_U8(IN) vreinterpret_u8_u32(vld1_u32((IN)))
+#define LOADQ_U32_AS_U8(IN) vreinterpretq_u8_u32(vdupq_n_u32((IN)))
+#define LOADQ_U32P_AS_U8(IN) vreinterpretq_u8_u32(vld1q_u32((IN)))
+#define GET_U8_AS_U32(IN) vget_lane_u32(vreinterpret_u32_u8((IN)), 0);
+#define GETQ_U8_AS_U32(IN) vgetq_lane_u32(vreinterpretq_u32_u8((IN)), 0);
+#define STOREQ_U8_AS_U32P(OUT, IN) vst1q_u32((OUT), vreinterpretq_u32_u8((IN)));
+#define ROTATE32_LEFT(L) vextq_u8((L), (L), 12) // D|C|B|A -> C|B|A|D
+
+static WEBP_INLINE uint8x8_t Average2_u8_NEON(uint32_t a0, uint32_t a1) {
+ const uint8x8_t A0 = LOAD_U32_AS_U8(a0);
+ const uint8x8_t A1 = LOAD_U32_AS_U8(a1);
+ return vhadd_u8(A0, A1);
+}
+
+static WEBP_INLINE uint32_t ClampedAddSubtractHalf_NEON(uint32_t c0,
+ uint32_t c1,
+ uint32_t c2) {
+ const uint8x8_t avg = Average2_u8_NEON(c0, c1);
+ // Remove one to c2 when bigger than avg.
+ const uint8x8_t C2 = LOAD_U32_AS_U8(c2);
+ const uint8x8_t cmp = vcgt_u8(C2, avg);
+ const uint8x8_t C2_1 = vadd_u8(C2, cmp);
+ // Compute half of the difference between avg and c2.
+ const int8x8_t diff_avg = vreinterpret_s8_u8(vhsub_u8(avg, C2_1));
+ // Compute the sum with avg and saturate.
+ const int16x8_t avg_16 = vreinterpretq_s16_u16(vmovl_u8(avg));
+ const uint8x8_t res = vqmovun_s16(vaddw_s8(avg_16, diff_avg));
+ const uint32_t output = GET_U8_AS_U32(res);
+ return output;
+}
+
+static WEBP_INLINE uint32_t Average2_NEON(uint32_t a0, uint32_t a1) {
+ const uint8x8_t avg_u8x8 = Average2_u8_NEON(a0, a1);
+ const uint32_t avg = GET_U8_AS_U32(avg_u8x8);
+ return avg;
+}
+
+static WEBP_INLINE uint32_t Average3_NEON(uint32_t a0, uint32_t a1,
+ uint32_t a2) {
+ const uint8x8_t avg0 = Average2_u8_NEON(a0, a2);
+ const uint8x8_t A1 = LOAD_U32_AS_U8(a1);
+ const uint32_t avg = GET_U8_AS_U32(vhadd_u8(avg0, A1));
+ return avg;
+}
+
+static uint32_t Predictor5_NEON(uint32_t left, const uint32_t* const top) {
+ return Average3_NEON(left, top[0], top[1]);
+}
+static uint32_t Predictor6_NEON(uint32_t left, const uint32_t* const top) {
+ return Average2_NEON(left, top[-1]);
+}
+static uint32_t Predictor7_NEON(uint32_t left, const uint32_t* const top) {
+ return Average2_NEON(left, top[0]);
+}
+static uint32_t Predictor13_NEON(uint32_t left, const uint32_t* const top) {
+ return ClampedAddSubtractHalf_NEON(left, top[0], top[-1]);
+}
+
+// Batch versions of those functions.
+
+// Predictor0: ARGB_BLACK.
+static void PredictorAdd0_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ const uint8x16_t black = vreinterpretq_u8_u32(vdupq_n_u32(ARGB_BLACK));
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ const uint8x16_t res = vaddq_u8(src, black);
+ STOREQ_U8_AS_U32P(&out[i], res);
+ }
+ VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i);
+}
+
+// Predictor1: left.
+static void PredictorAdd1_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ const uint8x16_t zero = LOADQ_U32_AS_U8(0);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ // a | b | c | d
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ // 0 | a | b | c
+ const uint8x16_t shift0 = vextq_u8(zero, src, 12);
+ // a | a + b | b + c | c + d
+ const uint8x16_t sum0 = vaddq_u8(src, shift0);
+ // 0 | 0 | a | a + b
+ const uint8x16_t shift1 = vextq_u8(zero, sum0, 8);
+ // a | a + b | a + b + c | a + b + c + d
+ const uint8x16_t sum1 = vaddq_u8(sum0, shift1);
+ const uint8x16_t prev = LOADQ_U32_AS_U8(out[i - 1]);
+ const uint8x16_t res = vaddq_u8(sum1, prev);
+ STOREQ_U8_AS_U32P(&out[i], res);
+ }
+ VP8LPredictorsAdd_C[1](in + i, upper + i, num_pixels - i, out + i);
+}
+
+// Macro that adds 32-bit integers from IN using mod 256 arithmetic
+// per 8 bit channel.
+#define GENERATE_PREDICTOR_1(X, IN) \
+static void PredictorAdd##X##_NEON(const uint32_t* in, \
+ const uint32_t* upper, int num_pixels, \
+ uint32_t* out) { \
+ int i; \
+ for (i = 0; i + 4 <= num_pixels; i += 4) { \
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); \
+ const uint8x16_t other = LOADQ_U32P_AS_U8(&(IN)); \
+ const uint8x16_t res = vaddq_u8(src, other); \
+ STOREQ_U8_AS_U32P(&out[i], res); \
+ } \
+ VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \
+}
+// Predictor2: Top.
+GENERATE_PREDICTOR_1(2, upper[i])
+// Predictor3: Top-right.
+GENERATE_PREDICTOR_1(3, upper[i + 1])
+// Predictor4: Top-left.
+GENERATE_PREDICTOR_1(4, upper[i - 1])
+#undef GENERATE_PREDICTOR_1
+
+// Predictor5: average(average(left, TR), T)
+#define DO_PRED5(LANE) do { \
+ const uint8x16_t avgLTR = vhaddq_u8(L, TR); \
+ const uint8x16_t avg = vhaddq_u8(avgLTR, T); \
+ const uint8x16_t res = vaddq_u8(avg, src); \
+ vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \
+ L = ROTATE32_LEFT(res); \
+} while (0)
+
+static void PredictorAdd5_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint8x16_t L = LOADQ_U32_AS_U8(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i + 0]);
+ const uint8x16_t TR = LOADQ_U32P_AS_U8(&upper[i + 1]);
+ DO_PRED5(0);
+ DO_PRED5(1);
+ DO_PRED5(2);
+ DO_PRED5(3);
+ }
+ VP8LPredictorsAdd_C[5](in + i, upper + i, num_pixels - i, out + i);
+}
+#undef DO_PRED5
+
+#define DO_PRED67(LANE) do { \
+ const uint8x16_t avg = vhaddq_u8(L, top); \
+ const uint8x16_t res = vaddq_u8(avg, src); \
+ vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \
+ L = ROTATE32_LEFT(res); \
+} while (0)
+
+// Predictor6: average(left, TL)
+static void PredictorAdd6_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint8x16_t L = LOADQ_U32_AS_U8(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ const uint8x16_t top = LOADQ_U32P_AS_U8(&upper[i - 1]);
+ DO_PRED67(0);
+ DO_PRED67(1);
+ DO_PRED67(2);
+ DO_PRED67(3);
+ }
+ VP8LPredictorsAdd_C[6](in + i, upper + i, num_pixels - i, out + i);
+}
+
+// Predictor7: average(left, T)
+static void PredictorAdd7_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint8x16_t L = LOADQ_U32_AS_U8(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ const uint8x16_t top = LOADQ_U32P_AS_U8(&upper[i]);
+ DO_PRED67(0);
+ DO_PRED67(1);
+ DO_PRED67(2);
+ DO_PRED67(3);
+ }
+ VP8LPredictorsAdd_C[7](in + i, upper + i, num_pixels - i, out + i);
+}
+#undef DO_PRED67
+
+#define GENERATE_PREDICTOR_2(X, IN) \
+static void PredictorAdd##X##_NEON(const uint32_t* in, \
+ const uint32_t* upper, int num_pixels, \
+ uint32_t* out) { \
+ int i; \
+ for (i = 0; i + 4 <= num_pixels; i += 4) { \
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]); \
+ const uint8x16_t Tother = LOADQ_U32P_AS_U8(&(IN)); \
+ const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]); \
+ const uint8x16_t avg = vhaddq_u8(T, Tother); \
+ const uint8x16_t res = vaddq_u8(avg, src); \
+ STOREQ_U8_AS_U32P(&out[i], res); \
+ } \
+ VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \
+}
+// Predictor8: average TL T.
+GENERATE_PREDICTOR_2(8, upper[i - 1])
+// Predictor9: average T TR.
+GENERATE_PREDICTOR_2(9, upper[i + 1])
+#undef GENERATE_PREDICTOR_2
+
+// Predictor10: average of (average of (L,TL), average of (T, TR)).
+#define DO_PRED10(LANE) do { \
+ const uint8x16_t avgLTL = vhaddq_u8(L, TL); \
+ const uint8x16_t avg = vhaddq_u8(avgTTR, avgLTL); \
+ const uint8x16_t res = vaddq_u8(avg, src); \
+ vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \
+ L = ROTATE32_LEFT(res); \
+} while (0)
+
+static void PredictorAdd10_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint8x16_t L = LOADQ_U32_AS_U8(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]);
+ const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]);
+ const uint8x16_t TR = LOADQ_U32P_AS_U8(&upper[i + 1]);
+ const uint8x16_t avgTTR = vhaddq_u8(T, TR);
+ DO_PRED10(0);
+ DO_PRED10(1);
+ DO_PRED10(2);
+ DO_PRED10(3);
+ }
+ VP8LPredictorsAdd_C[10](in + i, upper + i, num_pixels - i, out + i);
+}
+#undef DO_PRED10
+
+// Predictor11: select.
+#define DO_PRED11(LANE) do { \
+ const uint8x16_t sumLin = vaddq_u8(L, src); /* in + L */ \
+ const uint8x16_t pLTL = vabdq_u8(L, TL); /* |L - TL| */ \
+ const uint16x8_t sum_LTL = vpaddlq_u8(pLTL); \
+ const uint32x4_t pa = vpaddlq_u16(sum_LTL); \
+ const uint32x4_t mask = vcleq_u32(pa, pb); \
+ const uint8x16_t res = vbslq_u8(vreinterpretq_u8_u32(mask), sumTin, sumLin); \
+ vst1q_lane_u32(&out[i + (LANE)], vreinterpretq_u32_u8(res), (LANE)); \
+ L = ROTATE32_LEFT(res); \
+} while (0)
+
+static void PredictorAdd11_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint8x16_t L = LOADQ_U32_AS_U8(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]);
+ const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]);
+ const uint8x16_t pTTL = vabdq_u8(T, TL); // |T - TL|
+ const uint16x8_t sum_TTL = vpaddlq_u8(pTTL);
+ const uint32x4_t pb = vpaddlq_u16(sum_TTL);
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ const uint8x16_t sumTin = vaddq_u8(T, src); // in + T
+ DO_PRED11(0);
+ DO_PRED11(1);
+ DO_PRED11(2);
+ DO_PRED11(3);
+ }
+ VP8LPredictorsAdd_C[11](in + i, upper + i, num_pixels - i, out + i);
+}
+#undef DO_PRED11
+
+// Predictor12: ClampedAddSubtractFull.
+#define DO_PRED12(DIFF, LANE) do { \
+ const uint8x8_t pred = \
+ vqmovun_s16(vaddq_s16(vreinterpretq_s16_u16(L), (DIFF))); \
+ const uint8x8_t res = \
+ vadd_u8(pred, (LANE <= 1) ? vget_low_u8(src) : vget_high_u8(src)); \
+ const uint16x8_t res16 = vmovl_u8(res); \
+ vst1_lane_u32(&out[i + (LANE)], vreinterpret_u32_u8(res), (LANE) & 1); \
+ /* rotate in the left predictor for next iteration */ \
+ L = vextq_u16(res16, res16, 4); \
+} while (0)
+
+static void PredictorAdd12_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint16x8_t L = vmovl_u8(LOAD_U32_AS_U8(out[-1]));
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ // load four pixels of source
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ // precompute the difference T - TL once for all, stored as s16
+ const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]);
+ const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]);
+ const int16x8_t diff_lo =
+ vreinterpretq_s16_u16(vsubl_u8(vget_low_u8(T), vget_low_u8(TL)));
+ const int16x8_t diff_hi =
+ vreinterpretq_s16_u16(vsubl_u8(vget_high_u8(T), vget_high_u8(TL)));
+ // loop over the four reconstructed pixels
+ DO_PRED12(diff_lo, 0);
+ DO_PRED12(diff_lo, 1);
+ DO_PRED12(diff_hi, 2);
+ DO_PRED12(diff_hi, 3);
+ }
+ VP8LPredictorsAdd_C[12](in + i, upper + i, num_pixels - i, out + i);
+}
+#undef DO_PRED12
+
+// Predictor13: ClampedAddSubtractHalf
+#define DO_PRED13(LANE, LOW_OR_HI) do { \
+ const uint8x16_t avg = vhaddq_u8(L, T); \
+ const uint8x16_t cmp = vcgtq_u8(TL, avg); \
+ const uint8x16_t TL_1 = vaddq_u8(TL, cmp); \
+ /* Compute half of the difference between avg and TL'. */ \
+ const int8x8_t diff_avg = \
+ vreinterpret_s8_u8(LOW_OR_HI(vhsubq_u8(avg, TL_1))); \
+ /* Compute the sum with avg and saturate. */ \
+ const int16x8_t avg_16 = vreinterpretq_s16_u16(vmovl_u8(LOW_OR_HI(avg))); \
+ const uint8x8_t delta = vqmovun_s16(vaddw_s8(avg_16, diff_avg)); \
+ const uint8x8_t res = vadd_u8(LOW_OR_HI(src), delta); \
+ const uint8x16_t res2 = vcombine_u8(res, res); \
+ vst1_lane_u32(&out[i + (LANE)], vreinterpret_u32_u8(res), (LANE) & 1); \
+ L = ROTATE32_LEFT(res2); \
+} while (0)
+
+static void PredictorAdd13_NEON(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ uint8x16_t L = LOADQ_U32_AS_U8(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const uint8x16_t src = LOADQ_U32P_AS_U8(&in[i]);
+ const uint8x16_t T = LOADQ_U32P_AS_U8(&upper[i]);
+ const uint8x16_t TL = LOADQ_U32P_AS_U8(&upper[i - 1]);
+ DO_PRED13(0, vget_low_u8);
+ DO_PRED13(1, vget_low_u8);
+ DO_PRED13(2, vget_high_u8);
+ DO_PRED13(3, vget_high_u8);
+ }
+ VP8LPredictorsAdd_C[13](in + i, upper + i, num_pixels - i, out + i);
+}
+#undef DO_PRED13
+
+#undef LOAD_U32_AS_U8
+#undef LOAD_U32P_AS_U8
+#undef LOADQ_U32_AS_U8
+#undef LOADQ_U32P_AS_U8
+#undef GET_U8_AS_U32
+#undef GETQ_U8_AS_U32
+#undef STOREQ_U8_AS_U32P
+#undef ROTATE32_LEFT
+
//------------------------------------------------------------------------------
// Subtract-Green Transform
@@ -171,28 +522,30 @@ static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb,
}
#endif // USE_VTBLQ
-static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
- const uint32_t* const end = argb_data + (num_pixels & ~3);
+static void AddGreenToBlueAndRed(const uint32_t* src, int num_pixels,
+ uint32_t* dst) {
+ const uint32_t* const end = src + (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);
+ for (; src < end; src += 4, dst += 4) {
+ const uint8x16_t argb = vld1q_u8((const uint8_t*)src);
const uint8x16_t greens = DoGreenShuffle(argb, shuffle);
- vst1q_u8((uint8_t*)argb_data, vaddq_u8(argb, greens));
+ vst1q_u8((uint8_t*)dst, vaddq_u8(argb, greens));
}
// fallthrough and finish off with plain-C
- VP8LAddGreenToBlueAndRed_C(argb_data, num_pixels & 3);
+ VP8LAddGreenToBlueAndRed_C(src, num_pixels & 3, dst);
}
//------------------------------------------------------------------------------
// Color Transform
static void TransformColorInverse(const VP8LMultipliers* const m,
- uint32_t* argb_data, int num_pixels) {
- // sign-extended multiplying constants, pre-shifted by 6.
+ const uint32_t* const src, int num_pixels,
+ uint32_t* dst) {
+// 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_),
@@ -219,7 +572,7 @@ static void TransformColorInverse(const VP8LMultipliers* const m,
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 uint8x16_t in = vld1q_u8((const uint8_t*)(src + i));
const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag);
// 0 g 0 g
const uint8x16_t greens = DoGreenShuffle(in, shuffle);
@@ -240,10 +593,10 @@ static void TransformColorInverse(const VP8LMultipliers* const m,
// 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);
+ vst1q_u32(dst + i, out);
}
// Fall-back to C-version for left-overs.
- VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i);
+ VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i);
}
#undef USE_VTBLQ
@@ -254,6 +607,26 @@ static void TransformColorInverse(const VP8LMultipliers* const m,
extern void VP8LDspInitNEON(void);
WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) {
+ VP8LPredictors[5] = Predictor5_NEON;
+ VP8LPredictors[6] = Predictor6_NEON;
+ VP8LPredictors[7] = Predictor7_NEON;
+ VP8LPredictors[13] = Predictor13_NEON;
+
+ VP8LPredictorsAdd[0] = PredictorAdd0_NEON;
+ VP8LPredictorsAdd[1] = PredictorAdd1_NEON;
+ VP8LPredictorsAdd[2] = PredictorAdd2_NEON;
+ VP8LPredictorsAdd[3] = PredictorAdd3_NEON;
+ VP8LPredictorsAdd[4] = PredictorAdd4_NEON;
+ VP8LPredictorsAdd[5] = PredictorAdd5_NEON;
+ VP8LPredictorsAdd[6] = PredictorAdd6_NEON;
+ VP8LPredictorsAdd[7] = PredictorAdd7_NEON;
+ VP8LPredictorsAdd[8] = PredictorAdd8_NEON;
+ VP8LPredictorsAdd[9] = PredictorAdd9_NEON;
+ VP8LPredictorsAdd[10] = PredictorAdd10_NEON;
+ VP8LPredictorsAdd[11] = PredictorAdd11_NEON;
+ VP8LPredictorsAdd[12] = PredictorAdd12_NEON;
+ VP8LPredictorsAdd[13] = PredictorAdd13_NEON;
+
VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
VP8LConvertBGRAToBGR = ConvertBGRAToBGR;
VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
diff --git a/thirdparty/libwebp/dsp/lossless_sse2.c b/thirdparty/libwebp/dsp/lossless_sse2.c
index 2d016c2911..15aae93869 100644
--- a/thirdparty/libwebp/dsp/lossless_sse2.c
+++ b/thirdparty/libwebp/dsp/lossless_sse2.c
@@ -14,9 +14,12 @@
#include "./dsp.h"
#if defined(WEBP_USE_SSE2)
+
+#include "./common_sse2.h"
+#include "./lossless.h"
+#include "./lossless_common.h"
#include <assert.h>
#include <emmintrin.h>
-#include "./lossless.h"
//------------------------------------------------------------------------------
// Predictor Transform
@@ -75,25 +78,44 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
return (pa_minus_pb <= 0) ? a : b;
}
-static WEBP_INLINE __m128i Average2_128i(uint32_t a0, uint32_t a1) {
+static WEBP_INLINE void Average2_m128i(const __m128i* const a0,
+ const __m128i* const a1,
+ __m128i* const avg) {
+ // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1)
+ const __m128i ones = _mm_set1_epi8(1);
+ const __m128i avg1 = _mm_avg_epu8(*a0, *a1);
+ const __m128i one = _mm_and_si128(_mm_xor_si128(*a0, *a1), ones);
+ *avg = _mm_sub_epi8(avg1, one);
+}
+
+static WEBP_INLINE void Average2_uint32(const uint32_t a0, const uint32_t a1,
+ __m128i* const avg) {
+ // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1)
+ const __m128i ones = _mm_set1_epi8(1);
+ const __m128i A0 = _mm_cvtsi32_si128(a0);
+ const __m128i A1 = _mm_cvtsi32_si128(a1);
+ const __m128i avg1 = _mm_avg_epu8(A0, A1);
+ const __m128i one = _mm_and_si128(_mm_xor_si128(A0, A1), ones);
+ *avg = _mm_sub_epi8(avg1, one);
+}
+
+static WEBP_INLINE __m128i Average2_uint32_16(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;
+ return _mm_srli_epi16(sum, 1);
}
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;
+ __m128i output;
+ Average2_uint32(a0, a1, &output);
+ return _mm_cvtsi128_si32(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 avg1 = Average2_uint32_16(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);
@@ -104,8 +126,8 @@ static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
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 avg1 = Average2_uint32_16(a0, a1);
+ const __m128i avg2 = Average2_uint32_16(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);
@@ -113,68 +135,289 @@ static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
return output;
}
-static uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
+static uint32_t Predictor5_SSE2(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) {
+static uint32_t Predictor6_SSE2(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) {
+static uint32_t Predictor7_SSE2(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) {
+static uint32_t Predictor8_SSE2(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) {
+static uint32_t Predictor9_SSE2(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) {
+static uint32_t Predictor10_SSE2(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) {
+static uint32_t Predictor11_SSE2(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) {
+static uint32_t Predictor12_SSE2(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) {
+static uint32_t Predictor13_SSE2(uint32_t left, const uint32_t* const top) {
const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
return pred;
}
+// Batch versions of those functions.
+
+// Predictor0: ARGB_BLACK.
+static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ const __m128i black = _mm_set1_epi32(ARGB_BLACK);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ const __m128i res = _mm_add_epi8(src, black);
+ _mm_storeu_si128((__m128i*)&out[i], res);
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+// Predictor1: left.
+static void PredictorAdd1_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ __m128i prev = _mm_set1_epi32(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ // a | b | c | d
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ // 0 | a | b | c
+ const __m128i shift0 = _mm_slli_si128(src, 4);
+ // a | a + b | b + c | c + d
+ const __m128i sum0 = _mm_add_epi8(src, shift0);
+ // 0 | 0 | a | a + b
+ const __m128i shift1 = _mm_slli_si128(sum0, 8);
+ // a | a + b | a + b + c | a + b + c + d
+ const __m128i sum1 = _mm_add_epi8(sum0, shift1);
+ const __m128i res = _mm_add_epi8(sum1, prev);
+ _mm_storeu_si128((__m128i*)&out[i], res);
+ // replicate prev output on the four lanes
+ prev = _mm_shuffle_epi32(res, (3 << 0) | (3 << 2) | (3 << 4) | (3 << 6));
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsAdd_C[1](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+// Macro that adds 32-bit integers from IN using mod 256 arithmetic
+// per 8 bit channel.
+#define GENERATE_PREDICTOR_1(X, IN) \
+static void PredictorAdd##X##_SSE2(const uint32_t* in, const uint32_t* upper, \
+ int num_pixels, uint32_t* out) { \
+ int i; \
+ for (i = 0; i + 4 <= num_pixels; i += 4) { \
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \
+ const __m128i other = _mm_loadu_si128((const __m128i*)&(IN)); \
+ const __m128i res = _mm_add_epi8(src, other); \
+ _mm_storeu_si128((__m128i*)&out[i], res); \
+ } \
+ if (i != num_pixels) { \
+ VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \
+ } \
+}
+
+// Predictor2: Top.
+GENERATE_PREDICTOR_1(2, upper[i])
+// Predictor3: Top-right.
+GENERATE_PREDICTOR_1(3, upper[i + 1])
+// Predictor4: Top-left.
+GENERATE_PREDICTOR_1(4, upper[i - 1])
+#undef GENERATE_PREDICTOR_1
+
+// Due to averages with integers, values cannot be accumulated in parallel for
+// predictors 5 to 7.
+GENERATE_PREDICTOR_ADD(Predictor5_SSE2, PredictorAdd5_SSE2)
+GENERATE_PREDICTOR_ADD(Predictor6_SSE2, PredictorAdd6_SSE2)
+GENERATE_PREDICTOR_ADD(Predictor7_SSE2, PredictorAdd7_SSE2)
+
+#define GENERATE_PREDICTOR_2(X, IN) \
+static void PredictorAdd##X##_SSE2(const uint32_t* in, const uint32_t* upper, \
+ int num_pixels, uint32_t* out) { \
+ int i; \
+ for (i = 0; i + 4 <= num_pixels; i += 4) { \
+ const __m128i Tother = _mm_loadu_si128((const __m128i*)&(IN)); \
+ const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); \
+ const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); \
+ __m128i avg, res; \
+ Average2_m128i(&T, &Tother, &avg); \
+ res = _mm_add_epi8(avg, src); \
+ _mm_storeu_si128((__m128i*)&out[i], res); \
+ } \
+ if (i != num_pixels) { \
+ VP8LPredictorsAdd_C[(X)](in + i, upper + i, num_pixels - i, out + i); \
+ } \
+}
+// Predictor8: average TL T.
+GENERATE_PREDICTOR_2(8, upper[i - 1])
+// Predictor9: average T TR.
+GENERATE_PREDICTOR_2(9, upper[i + 1])
+#undef GENERATE_PREDICTOR_2
+
+// Predictor10: average of (average of (L,TL), average of (T, TR)).
+static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i, j;
+ __m128i L = _mm_cvtsi32_si128(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
+ const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
+ const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]);
+ __m128i avgTTR;
+ Average2_m128i(&T, &TR, &avgTTR);
+ for (j = 0; j < 4; ++j) {
+ __m128i avgLTL, avg;
+ Average2_m128i(&L, &TL, &avgLTL);
+ Average2_m128i(&avgTTR, &avgLTL, &avg);
+ L = _mm_add_epi8(avg, src);
+ out[i + j] = _mm_cvtsi128_si32(L);
+ // Rotate the pre-computed values for the next iteration.
+ avgTTR = _mm_srli_si128(avgTTR, 4);
+ TL = _mm_srli_si128(TL, 4);
+ src = _mm_srli_si128(src, 4);
+ }
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsAdd_C[10](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+// Predictor11: select.
+static void GetSumAbsDiff32(const __m128i* const A, const __m128i* const B,
+ __m128i* const out) {
+ // We can unpack with any value on the upper 32 bits, provided it's the same
+ // on both operands (to that their sum of abs diff is zero). Here we use *A.
+ const __m128i A_lo = _mm_unpacklo_epi32(*A, *A);
+ const __m128i B_lo = _mm_unpacklo_epi32(*B, *A);
+ const __m128i A_hi = _mm_unpackhi_epi32(*A, *A);
+ const __m128i B_hi = _mm_unpackhi_epi32(*B, *A);
+ const __m128i s_lo = _mm_sad_epu8(A_lo, B_lo);
+ const __m128i s_hi = _mm_sad_epu8(A_hi, B_hi);
+ *out = _mm_packs_epi32(s_lo, s_hi);
+}
+
+static void PredictorAdd11_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i, j;
+ __m128i L = _mm_cvtsi32_si128(out[-1]);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
+ __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
+ __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ __m128i pa;
+ GetSumAbsDiff32(&T, &TL, &pa); // pa = sum |T-TL|
+ for (j = 0; j < 4; ++j) {
+ const __m128i L_lo = _mm_unpacklo_epi32(L, L);
+ const __m128i TL_lo = _mm_unpacklo_epi32(TL, L);
+ const __m128i pb = _mm_sad_epu8(L_lo, TL_lo); // pb = sum |L-TL|
+ const __m128i mask = _mm_cmpgt_epi32(pb, pa);
+ const __m128i A = _mm_and_si128(mask, L);
+ const __m128i B = _mm_andnot_si128(mask, T);
+ const __m128i pred = _mm_or_si128(A, B); // pred = (L > T)? L : T
+ L = _mm_add_epi8(src, pred);
+ out[i + j] = _mm_cvtsi128_si32(L);
+ // Shift the pre-computed value for the next iteration.
+ T = _mm_srli_si128(T, 4);
+ TL = _mm_srli_si128(TL, 4);
+ src = _mm_srli_si128(src, 4);
+ pa = _mm_srli_si128(pa, 4);
+ }
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsAdd_C[11](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+
+// Predictor12: ClampedAddSubtractFull.
+#define DO_PRED12(DIFF, LANE, OUT) \
+do { \
+ const __m128i all = _mm_add_epi16(L, (DIFF)); \
+ const __m128i alls = _mm_packus_epi16(all, all); \
+ const __m128i res = _mm_add_epi8(src, alls); \
+ out[i + (OUT)] = _mm_cvtsi128_si32(res); \
+ L = _mm_unpacklo_epi8(res, zero); \
+ /* Shift the pre-computed value for the next iteration.*/ \
+ if (LANE == 0) (DIFF) = _mm_srli_si128((DIFF), 8); \
+ src = _mm_srli_si128(src, 4); \
+} while (0)
+
+static void PredictorAdd12_SSE2(const uint32_t* in, const uint32_t* upper,
+ int num_pixels, uint32_t* out) {
+ int i;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i L8 = _mm_cvtsi32_si128(out[-1]);
+ __m128i L = _mm_unpacklo_epi8(L8, zero);
+ for (i = 0; i + 4 <= num_pixels; i += 4) {
+ // Load 4 pixels at a time.
+ __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
+ const __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
+ const __m128i T_lo = _mm_unpacklo_epi8(T, zero);
+ const __m128i T_hi = _mm_unpackhi_epi8(T, zero);
+ const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
+ const __m128i TL_lo = _mm_unpacklo_epi8(TL, zero);
+ const __m128i TL_hi = _mm_unpackhi_epi8(TL, zero);
+ __m128i diff_lo = _mm_sub_epi16(T_lo, TL_lo);
+ __m128i diff_hi = _mm_sub_epi16(T_hi, TL_hi);
+ DO_PRED12(diff_lo, 0, 0);
+ DO_PRED12(diff_lo, 1, 1);
+ DO_PRED12(diff_hi, 0, 2);
+ DO_PRED12(diff_hi, 1, 3);
+ }
+ if (i != num_pixels) {
+ VP8LPredictorsAdd_C[12](in + i, upper + i, num_pixels - i, out + i);
+ }
+}
+#undef DO_PRED12
+
+// Due to averages with integers, values cannot be accumulated in parallel for
+// predictors 13.
+GENERATE_PREDICTOR_ADD(Predictor13_SSE2, PredictorAdd13_SSE2)
+
//------------------------------------------------------------------------------
// Subtract-Green Transform
-static void AddGreenToBlueAndRed(uint32_t* argb_data, int num_pixels) {
+static void AddGreenToBlueAndRed(const uint32_t* const src, int num_pixels,
+ uint32_t* dst) {
int i;
for (i = 0; i + 4 <= num_pixels; i += 4) {
- const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
+ const __m128i in = _mm_loadu_si128((const __m128i*)&src[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);
+ _mm_storeu_si128((__m128i*)&dst[i], out);
}
// fallthrough and finish off with plain-C
- VP8LAddGreenToBlueAndRed_C(argb_data + i, num_pixels - i);
+ if (i != num_pixels) {
+ VP8LAddGreenToBlueAndRed_C(src + i, num_pixels - i, dst + 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.
+ const uint32_t* const src, int num_pixels,
+ uint32_t* dst) {
+// 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_),
@@ -188,7 +431,7 @@ static void TransformColorInverse(const VP8LMultipliers* const m,
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 in = _mm_loadu_si128((const __m128i*)&src[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
@@ -200,15 +443,53 @@ static void TransformColorInverse(const VP8LMultipliers* const m,
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);
+ _mm_storeu_si128((__m128i*)&dst[i], out);
}
// Fall-back to C-version for left-overs.
- VP8LTransformColorInverse_C(m, argb_data + i, num_pixels - i);
+ if (i != num_pixels) {
+ VP8LTransformColorInverse_C(m, src + i, num_pixels - i, dst + i);
+ }
}
//------------------------------------------------------------------------------
// Color-space conversion functions
+static void ConvertBGRAToRGB(const uint32_t* src, int num_pixels,
+ uint8_t* dst) {
+ const __m128i* in = (const __m128i*)src;
+ __m128i* out = (__m128i*)dst;
+
+ while (num_pixels >= 32) {
+ // Load the BGRA buffers.
+ __m128i in0 = _mm_loadu_si128(in + 0);
+ __m128i in1 = _mm_loadu_si128(in + 1);
+ __m128i in2 = _mm_loadu_si128(in + 2);
+ __m128i in3 = _mm_loadu_si128(in + 3);
+ __m128i in4 = _mm_loadu_si128(in + 4);
+ __m128i in5 = _mm_loadu_si128(in + 5);
+ __m128i in6 = _mm_loadu_si128(in + 6);
+ __m128i in7 = _mm_loadu_si128(in + 7);
+ VP8L32bToPlanar(&in0, &in1, &in2, &in3);
+ VP8L32bToPlanar(&in4, &in5, &in6, &in7);
+ // At this points, in1/in5 contains red only, in2/in6 green only ...
+ // Pack the colors in 24b RGB.
+ VP8PlanarTo24b(&in1, &in5, &in2, &in6, &in3, &in7);
+ _mm_storeu_si128(out + 0, in1);
+ _mm_storeu_si128(out + 1, in5);
+ _mm_storeu_si128(out + 2, in2);
+ _mm_storeu_si128(out + 3, in6);
+ _mm_storeu_si128(out + 4, in3);
+ _mm_storeu_si128(out + 5, in7);
+ in += 8;
+ out += 6;
+ num_pixels -= 32;
+ }
+ // left-overs
+ if (num_pixels > 0) {
+ VP8LConvertBGRAToRGB_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+ }
+}
+
static void ConvertBGRAToRGBA(const uint32_t* src,
int num_pixels, uint8_t* dst) {
const __m128i* in = (const __m128i*)src;
@@ -233,7 +514,9 @@ static void ConvertBGRAToRGBA(const uint32_t* src,
num_pixels -= 8;
}
// left-overs
- VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+ if (num_pixels > 0) {
+ VP8LConvertBGRAToRGBA_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+ }
}
static void ConvertBGRAToRGBA4444(const uint32_t* src,
@@ -267,7 +550,9 @@ static void ConvertBGRAToRGBA4444(const uint32_t* src,
num_pixels -= 8;
}
// left-overs
- VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+ if (num_pixels > 0) {
+ VP8LConvertBGRAToRGBA4444_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+ }
}
static void ConvertBGRAToRGB565(const uint32_t* src,
@@ -306,7 +591,9 @@ static void ConvertBGRAToRGB565(const uint32_t* src,
num_pixels -= 8;
}
// left-overs
- VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+ if (num_pixels > 0) {
+ VP8LConvertBGRAToRGB565_C((const uint32_t*)in, num_pixels, (uint8_t*)out);
+ }
}
static void ConvertBGRAToBGR(const uint32_t* src,
@@ -337,7 +624,9 @@ static void ConvertBGRAToBGR(const uint32_t* src,
num_pixels -= 8;
}
// left-overs
- VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst);
+ if (num_pixels > 0) {
+ VP8LConvertBGRAToBGR_C((const uint32_t*)in, num_pixels, dst);
+ }
}
//------------------------------------------------------------------------------
@@ -346,19 +635,35 @@ static void ConvertBGRAToBGR(const uint32_t* src,
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;
+ VP8LPredictors[5] = Predictor5_SSE2;
+ VP8LPredictors[6] = Predictor6_SSE2;
+ VP8LPredictors[7] = Predictor7_SSE2;
+ VP8LPredictors[8] = Predictor8_SSE2;
+ VP8LPredictors[9] = Predictor9_SSE2;
+ VP8LPredictors[10] = Predictor10_SSE2;
+ VP8LPredictors[11] = Predictor11_SSE2;
+ VP8LPredictors[12] = Predictor12_SSE2;
+ VP8LPredictors[13] = Predictor13_SSE2;
+
+ VP8LPredictorsAdd[0] = PredictorAdd0_SSE2;
+ VP8LPredictorsAdd[1] = PredictorAdd1_SSE2;
+ VP8LPredictorsAdd[2] = PredictorAdd2_SSE2;
+ VP8LPredictorsAdd[3] = PredictorAdd3_SSE2;
+ VP8LPredictorsAdd[4] = PredictorAdd4_SSE2;
+ VP8LPredictorsAdd[5] = PredictorAdd5_SSE2;
+ VP8LPredictorsAdd[6] = PredictorAdd6_SSE2;
+ VP8LPredictorsAdd[7] = PredictorAdd7_SSE2;
+ VP8LPredictorsAdd[8] = PredictorAdd8_SSE2;
+ VP8LPredictorsAdd[9] = PredictorAdd9_SSE2;
+ VP8LPredictorsAdd[10] = PredictorAdd10_SSE2;
+ VP8LPredictorsAdd[11] = PredictorAdd11_SSE2;
+ VP8LPredictorsAdd[12] = PredictorAdd12_SSE2;
+ VP8LPredictorsAdd[13] = PredictorAdd13_SSE2;
VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed;
VP8LTransformColorInverse = TransformColorInverse;
+ VP8LConvertBGRAToRGB = ConvertBGRAToRGB;
VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA;
VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444;
VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565;
diff --git a/thirdparty/libwebp/dsp/msa_macro.h b/thirdparty/libwebp/dsp/msa_macro.h
index 5c707f476a..d0e5f45e01 100644
--- a/thirdparty/libwebp/dsp/msa_macro.h
+++ b/thirdparty/libwebp/dsp/msa_macro.h
@@ -23,12 +23,24 @@
#ifdef CLANG_BUILD
#define ADDVI_H(a, b) __msa_addvi_h((v8i16)a, b)
+ #define ADDVI_W(a, b) __msa_addvi_w((v4i32)a, b)
+ #define SRAI_B(a, b) __msa_srai_b((v16i8)a, b)
#define SRAI_H(a, b) __msa_srai_h((v8i16)a, b)
#define SRAI_W(a, b) __msa_srai_w((v4i32)a, b)
+ #define SRLI_H(a, b) __msa_srli_h((v8i16)a, b)
+ #define SLLI_B(a, b) __msa_slli_b((v4i32)a, b)
+ #define ANDI_B(a, b) __msa_andi_b((v16u8)a, b)
+ #define ORI_B(a, b) __msa_ori_b((v16u8)a, b)
#else
#define ADDVI_H(a, b) (a + b)
+ #define ADDVI_W(a, b) (a + b)
+ #define SRAI_B(a, b) (a >> b)
#define SRAI_H(a, b) (a >> b)
#define SRAI_W(a, b) (a >> b)
+ #define SRLI_H(a, b) (a << b)
+ #define SLLI_B(a, b) (a << b)
+ #define ANDI_B(a, b) (a & b)
+ #define ORI_B(a, b) (a | b)
#endif
#define LD_B(RTYPE, psrc) *((RTYPE*)(psrc))
@@ -116,13 +128,13 @@
#define SH(val, pdst) MSA_STORE(val, pdst, msa_ush)
MSA_STORE_FUNC(uint32_t, usw, msa_usw);
#define SW(val, pdst) MSA_STORE(val, pdst, msa_usw)
- #define SD(val, pdst) { \
+ #define SD(val, pdst) do { \
uint8_t* const pdst_sd_m = (uint8_t*)(pdst); \
const uint32_t val0_m = (uint32_t)(val & 0x00000000FFFFFFFF); \
const uint32_t val1_m = (uint32_t)((val >> 32) & 0x00000000FFFFFFFF); \
SW(val0_m, pdst_sd_m); \
SW(val1_m, pdst_sd_m + 4); \
- }
+ } while (0)
#endif // (__mips_isa_rev >= 6)
/* Description : Load 4 words with stride
@@ -133,34 +145,68 @@
* Load word in 'out2' from (psrc + 2 * stride)
* Load word in 'out3' from (psrc + 3 * stride)
*/
-#define LW4(psrc, stride, out0, out1, out2, out3) { \
- const uint8_t* ptmp = (const uint8_t*)psrc; \
- out0 = LW(ptmp); \
- ptmp += stride; \
- out1 = LW(ptmp); \
- ptmp += stride; \
- out2 = LW(ptmp); \
- ptmp += stride; \
- out3 = LW(ptmp); \
-}
+#define LW4(psrc, stride, out0, out1, out2, out3) do { \
+ const uint8_t* ptmp = (const uint8_t*)psrc; \
+ out0 = LW(ptmp); \
+ ptmp += stride; \
+ out1 = LW(ptmp); \
+ ptmp += stride; \
+ out2 = LW(ptmp); \
+ ptmp += stride; \
+ out3 = LW(ptmp); \
+} while (0)
-/* Description : Store 4 words with stride
+/* Description : Store words with stride
* Arguments : Inputs - in0, in1, in2, in3, pdst, stride
* Details : Store word from 'in0' to (pdst)
* Store word from 'in1' to (pdst + stride)
* Store word from 'in2' to (pdst + 2 * stride)
* Store word from 'in3' to (pdst + 3 * stride)
*/
-#define SW4(in0, in1, in2, in3, pdst, stride) { \
- uint8_t* ptmp = (uint8_t*)pdst; \
- SW(in0, ptmp); \
- ptmp += stride; \
- SW(in1, ptmp); \
- ptmp += stride; \
- SW(in2, ptmp); \
- ptmp += stride; \
- SW(in3, ptmp); \
-}
+#define SW4(in0, in1, in2, in3, pdst, stride) do { \
+ uint8_t* ptmp = (uint8_t*)pdst; \
+ SW(in0, ptmp); \
+ ptmp += stride; \
+ SW(in1, ptmp); \
+ ptmp += stride; \
+ SW(in2, ptmp); \
+ ptmp += stride; \
+ SW(in3, ptmp); \
+} while (0)
+
+#define SW3(in0, in1, in2, pdst, stride) do { \
+ uint8_t* ptmp = (uint8_t*)pdst; \
+ SW(in0, ptmp); \
+ ptmp += stride; \
+ SW(in1, ptmp); \
+ ptmp += stride; \
+ SW(in2, ptmp); \
+} while (0)
+
+#define SW2(in0, in1, pdst, stride) do { \
+ uint8_t* ptmp = (uint8_t*)pdst; \
+ SW(in0, ptmp); \
+ ptmp += stride; \
+ SW(in1, ptmp); \
+} while (0)
+
+/* Description : Store 4 double words with stride
+ * Arguments : Inputs - in0, in1, in2, in3, pdst, stride
+ * Details : Store double word from 'in0' to (pdst)
+ * Store double word from 'in1' to (pdst + stride)
+ * Store double word from 'in2' to (pdst + 2 * stride)
+ * Store double word from 'in3' to (pdst + 3 * stride)
+ */
+#define SD4(in0, in1, in2, in3, pdst, stride) do { \
+ uint8_t* ptmp = (uint8_t*)pdst; \
+ SD(in0, ptmp); \
+ ptmp += stride; \
+ SD(in1, ptmp); \
+ ptmp += stride; \
+ SD(in2, ptmp); \
+ ptmp += stride; \
+ SD(in3, ptmp); \
+} while (0)
/* Description : Load vectors with 16 byte elements with stride
* Arguments : Inputs - psrc, stride
@@ -169,33 +215,169 @@
* Details : Load 16 byte elements in 'out0' from (psrc)
* Load 16 byte elements in 'out1' from (psrc + stride)
*/
-#define LD_B2(RTYPE, psrc, stride, out0, out1) { \
- out0 = LD_B(RTYPE, psrc); \
- out1 = LD_B(RTYPE, psrc + stride); \
-}
+#define LD_B2(RTYPE, psrc, stride, out0, out1) do { \
+ out0 = LD_B(RTYPE, psrc); \
+ out1 = LD_B(RTYPE, psrc + stride); \
+} while (0)
#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__)
#define LD_SB2(...) LD_B2(v16i8, __VA_ARGS__)
-#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) { \
- LD_B2(RTYPE, psrc, stride, out0, out1); \
- LD_B2(RTYPE, psrc + 2 * stride , stride, out2, out3); \
-}
+#define LD_B3(RTYPE, psrc, stride, out0, out1, out2) do { \
+ LD_B2(RTYPE, psrc, stride, out0, out1); \
+ out2 = LD_B(RTYPE, psrc + 2 * stride); \
+} while (0)
+#define LD_UB3(...) LD_B3(v16u8, __VA_ARGS__)
+#define LD_SB3(...) LD_B3(v16i8, __VA_ARGS__)
+
+#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) do { \
+ LD_B2(RTYPE, psrc, stride, out0, out1); \
+ LD_B2(RTYPE, psrc + 2 * stride , stride, out2, out3); \
+} while (0)
#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__)
#define LD_SB4(...) LD_B4(v16i8, __VA_ARGS__)
+#define LD_B8(RTYPE, psrc, stride, \
+ out0, out1, out2, out3, out4, out5, out6, out7) do { \
+ LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3); \
+ LD_B4(RTYPE, psrc + 4 * stride, stride, out4, out5, out6, out7); \
+} while (0)
+#define LD_UB8(...) LD_B8(v16u8, __VA_ARGS__)
+#define LD_SB8(...) LD_B8(v16i8, __VA_ARGS__)
+
/* Description : Load vectors with 8 halfword elements with stride
* Arguments : Inputs - psrc, stride
* Outputs - out0, out1
* Details : Load 8 halfword elements in 'out0' from (psrc)
* Load 8 halfword elements in 'out1' from (psrc + stride)
*/
-#define LD_H2(RTYPE, psrc, stride, out0, out1) { \
- out0 = LD_H(RTYPE, psrc); \
- out1 = LD_H(RTYPE, psrc + stride); \
-}
+#define LD_H2(RTYPE, psrc, stride, out0, out1) do { \
+ out0 = LD_H(RTYPE, psrc); \
+ out1 = LD_H(RTYPE, psrc + stride); \
+} while (0)
#define LD_UH2(...) LD_H2(v8u16, __VA_ARGS__)
#define LD_SH2(...) LD_H2(v8i16, __VA_ARGS__)
+/* Description : Load vectors with 4 word elements with stride
+ * Arguments : Inputs - psrc, stride
+ * Outputs - out0, out1, out2, out3
+ * Details : Load 4 word elements in 'out0' from (psrc + 0 * stride)
+ * Load 4 word elements in 'out1' from (psrc + 1 * stride)
+ * Load 4 word elements in 'out2' from (psrc + 2 * stride)
+ * Load 4 word elements in 'out3' from (psrc + 3 * stride)
+ */
+#define LD_W2(RTYPE, psrc, stride, out0, out1) do { \
+ out0 = LD_W(RTYPE, psrc); \
+ out1 = LD_W(RTYPE, psrc + stride); \
+} while (0)
+#define LD_UW2(...) LD_W2(v4u32, __VA_ARGS__)
+#define LD_SW2(...) LD_W2(v4i32, __VA_ARGS__)
+
+#define LD_W3(RTYPE, psrc, stride, out0, out1, out2) do { \
+ LD_W2(RTYPE, psrc, stride, out0, out1); \
+ out2 = LD_W(RTYPE, psrc + 2 * stride); \
+} while (0)
+#define LD_UW3(...) LD_W3(v4u32, __VA_ARGS__)
+#define LD_SW3(...) LD_W3(v4i32, __VA_ARGS__)
+
+#define LD_W4(RTYPE, psrc, stride, out0, out1, out2, out3) do { \
+ LD_W2(RTYPE, psrc, stride, out0, out1); \
+ LD_W2(RTYPE, psrc + 2 * stride, stride, out2, out3); \
+} while (0)
+#define LD_UW4(...) LD_W4(v4u32, __VA_ARGS__)
+#define LD_SW4(...) LD_W4(v4i32, __VA_ARGS__)
+
+/* Description : Store vectors of 16 byte elements with stride
+ * Arguments : Inputs - in0, in1, pdst, stride
+ * Details : Store 16 byte elements from 'in0' to (pdst)
+ * Store 16 byte elements from 'in1' to (pdst + stride)
+ */
+#define ST_B2(RTYPE, in0, in1, pdst, stride) do { \
+ ST_B(RTYPE, in0, pdst); \
+ ST_B(RTYPE, in1, pdst + stride); \
+} while (0)
+#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__)
+#define ST_SB2(...) ST_B2(v16i8, __VA_ARGS__)
+
+#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) do { \
+ ST_B2(RTYPE, in0, in1, pdst, stride); \
+ ST_B2(RTYPE, in2, in3, pdst + 2 * stride, stride); \
+} while (0)
+#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__)
+#define ST_SB4(...) ST_B4(v16i8, __VA_ARGS__)
+
+#define ST_B8(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
+ pdst, stride) do { \
+ ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride); \
+ ST_B4(RTYPE, in4, in5, in6, in7, pdst + 4 * stride, stride); \
+} while (0)
+#define ST_UB8(...) ST_B8(v16u8, __VA_ARGS__)
+
+/* Description : Store vectors of 4 word elements with stride
+ * Arguments : Inputs - in0, in1, in2, in3, pdst, stride
+ * Details : Store 4 word elements from 'in0' to (pdst + 0 * stride)
+ * Store 4 word elements from 'in1' to (pdst + 1 * stride)
+ * Store 4 word elements from 'in2' to (pdst + 2 * stride)
+ * Store 4 word elements from 'in3' to (pdst + 3 * stride)
+ */
+#define ST_W2(RTYPE, in0, in1, pdst, stride) do { \
+ ST_W(RTYPE, in0, pdst); \
+ ST_W(RTYPE, in1, pdst + stride); \
+} while (0)
+#define ST_UW2(...) ST_W2(v4u32, __VA_ARGS__)
+#define ST_SW2(...) ST_W2(v4i32, __VA_ARGS__)
+
+#define ST_W3(RTYPE, in0, in1, in2, pdst, stride) do { \
+ ST_W2(RTYPE, in0, in1, pdst, stride); \
+ ST_W(RTYPE, in2, pdst + 2 * stride); \
+} while (0)
+#define ST_UW3(...) ST_W3(v4u32, __VA_ARGS__)
+#define ST_SW3(...) ST_W3(v4i32, __VA_ARGS__)
+
+#define ST_W4(RTYPE, in0, in1, in2, in3, pdst, stride) do { \
+ ST_W2(RTYPE, in0, in1, pdst, stride); \
+ ST_W2(RTYPE, in2, in3, pdst + 2 * stride, stride); \
+} while (0)
+#define ST_UW4(...) ST_W4(v4u32, __VA_ARGS__)
+#define ST_SW4(...) ST_W4(v4i32, __VA_ARGS__)
+
+/* Description : Store vectors of 8 halfword elements with stride
+ * Arguments : Inputs - in0, in1, pdst, stride
+ * Details : Store 8 halfword elements from 'in0' to (pdst)
+ * Store 8 halfword elements from 'in1' to (pdst + stride)
+ */
+#define ST_H2(RTYPE, in0, in1, pdst, stride) do { \
+ ST_H(RTYPE, in0, pdst); \
+ ST_H(RTYPE, in1, pdst + stride); \
+} while (0)
+#define ST_UH2(...) ST_H2(v8u16, __VA_ARGS__)
+#define ST_SH2(...) ST_H2(v8i16, __VA_ARGS__)
+
+/* Description : Store 2x4 byte block to destination memory from input vector
+ * Arguments : Inputs - in, stidx, pdst, stride
+ * Details : Index 'stidx' halfword element from 'in' vector is copied to
+ * the GP register and stored to (pdst)
+ * Index 'stidx+1' halfword element from 'in' vector is copied to
+ * the GP register and stored to (pdst + stride)
+ * Index 'stidx+2' halfword element from 'in' vector is copied to
+ * the GP register and stored to (pdst + 2 * stride)
+ * Index 'stidx+3' halfword element from 'in' vector is copied to
+ * the GP register and stored to (pdst + 3 * stride)
+ */
+#define ST2x4_UB(in, stidx, pdst, stride) do { \
+ uint8_t* pblk_2x4_m = (uint8_t*)pdst; \
+ const uint16_t out0_m = __msa_copy_s_h((v8i16)in, stidx); \
+ const uint16_t out1_m = __msa_copy_s_h((v8i16)in, stidx + 1); \
+ const uint16_t out2_m = __msa_copy_s_h((v8i16)in, stidx + 2); \
+ const uint16_t out3_m = __msa_copy_s_h((v8i16)in, stidx + 3); \
+ SH(out0_m, pblk_2x4_m); \
+ pblk_2x4_m += stride; \
+ SH(out1_m, pblk_2x4_m); \
+ pblk_2x4_m += stride; \
+ SH(out2_m, pblk_2x4_m); \
+ pblk_2x4_m += stride; \
+ SH(out3_m, pblk_2x4_m); \
+} while (0)
+
/* Description : Store 4x4 byte block to destination memory from input vector
* Arguments : Inputs - in0, in1, pdst, stride
* Details : 'Idx0' word element from input vector 'in0' is copied to the
@@ -207,14 +389,20 @@
* 'Idx3' word element from input vector 'in0' is copied to the
* GP register and stored to (pdst + 3 * stride)
*/
-#define ST4x4_UB(in0, in1, idx0, idx1, idx2, idx3, pdst, stride) { \
- uint8_t* const pblk_4x4_m = (uint8_t*)pdst; \
- const uint32_t out0_m = __msa_copy_s_w((v4i32)in0, idx0); \
- const uint32_t out1_m = __msa_copy_s_w((v4i32)in0, idx1); \
- const uint32_t out2_m = __msa_copy_s_w((v4i32)in1, idx2); \
- const uint32_t out3_m = __msa_copy_s_w((v4i32)in1, idx3); \
- SW4(out0_m, out1_m, out2_m, out3_m, pblk_4x4_m, stride); \
-}
+#define ST4x4_UB(in0, in1, idx0, idx1, idx2, idx3, pdst, stride) do { \
+ uint8_t* const pblk_4x4_m = (uint8_t*)pdst; \
+ const uint32_t out0_m = __msa_copy_s_w((v4i32)in0, idx0); \
+ const uint32_t out1_m = __msa_copy_s_w((v4i32)in0, idx1); \
+ const uint32_t out2_m = __msa_copy_s_w((v4i32)in1, idx2); \
+ const uint32_t out3_m = __msa_copy_s_w((v4i32)in1, idx3); \
+ SW4(out0_m, out1_m, out2_m, out3_m, pblk_4x4_m, stride); \
+} while (0)
+
+#define ST4x8_UB(in0, in1, pdst, stride) do { \
+ uint8_t* const pblk_4x8 = (uint8_t*)pdst; \
+ ST4x4_UB(in0, in0, 0, 1, 2, 3, pblk_4x8, stride); \
+ ST4x4_UB(in1, in1, 0, 1, 2, 3, pblk_4x8 + 4 * stride, stride); \
+} while (0)
/* Description : Immediate number of elements to slide
* Arguments : Inputs - in0, in1, slide_val
@@ -230,6 +418,30 @@
#define SLDI_SB(...) SLDI_B(v16i8, __VA_ARGS__)
#define SLDI_SH(...) SLDI_B(v8i16, __VA_ARGS__)
+/* Description : Shuffle byte vector elements as per mask vector
+ * Arguments : Inputs - in0, in1, in2, in3, mask0, mask1
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Byte elements from 'in0' & 'in1' are copied selectively to
+ * 'out0' as per control vector 'mask0'
+ */
+#define VSHF_B(RTYPE, in0, in1, mask) \
+ (RTYPE)__msa_vshf_b((v16i8)mask, (v16i8)in1, (v16i8)in0)
+
+#define VSHF_UB(...) VSHF_B(v16u8, __VA_ARGS__)
+#define VSHF_SB(...) VSHF_B(v16i8, __VA_ARGS__)
+#define VSHF_UH(...) VSHF_B(v8u16, __VA_ARGS__)
+#define VSHF_SH(...) VSHF_B(v8i16, __VA_ARGS__)
+
+#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) do { \
+ out0 = VSHF_B(RTYPE, in0, in1, mask0); \
+ out1 = VSHF_B(RTYPE, in2, in3, mask1); \
+} while (0)
+#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__)
+#define VSHF_B2_SB(...) VSHF_B2(v16i8, __VA_ARGS__)
+#define VSHF_B2_UH(...) VSHF_B2(v8u16, __VA_ARGS__)
+#define VSHF_B2_SH(...) VSHF_B2(v8i16, __VA_ARGS__)
+
/* Description : Shuffle halfword vector elements as per mask vector
* Arguments : Inputs - in0, in1, in2, in3, mask0, mask1
* Outputs - out0, out1
@@ -237,44 +449,219 @@
* Details : halfword elements from 'in0' & 'in1' are copied selectively to
* 'out0' as per control vector 'mask0'
*/
-#define VSHF_H2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) { \
- out0 = (RTYPE)__msa_vshf_h((v8i16)mask0, (v8i16)in1, (v8i16)in0); \
- out1 = (RTYPE)__msa_vshf_h((v8i16)mask1, (v8i16)in3, (v8i16)in2); \
-}
+#define VSHF_H2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) do { \
+ out0 = (RTYPE)__msa_vshf_h((v8i16)mask0, (v8i16)in1, (v8i16)in0); \
+ out1 = (RTYPE)__msa_vshf_h((v8i16)mask1, (v8i16)in3, (v8i16)in2); \
+} while (0)
#define VSHF_H2_UH(...) VSHF_H2(v8u16, __VA_ARGS__)
#define VSHF_H2_SH(...) VSHF_H2(v8i16, __VA_ARGS__)
+/* Description : Dot product of byte vector elements
+ * Arguments : Inputs - mult0, mult1, cnst0, cnst1
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Signed byte elements from 'mult0' are multiplied with
+ * signed byte elements from 'cnst0' producing a result
+ * twice the size of input i.e. signed halfword.
+ * The multiplication result of adjacent odd-even elements
+ * are added together and written to the 'out0' vector
+*/
+#define DOTP_SB2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \
+ out0 = (RTYPE)__msa_dotp_s_h((v16i8)mult0, (v16i8)cnst0); \
+ out1 = (RTYPE)__msa_dotp_s_h((v16i8)mult1, (v16i8)cnst1); \
+} while (0)
+#define DOTP_SB2_SH(...) DOTP_SB2(v8i16, __VA_ARGS__)
+
+/* Description : Dot product of halfword vector elements
+ * Arguments : Inputs - mult0, mult1, cnst0, cnst1
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Signed halfword elements from 'mult0' are multiplied with
+ * signed halfword elements from 'cnst0' producing a result
+ * twice the size of input i.e. signed word.
+ * The multiplication result of adjacent odd-even elements
+ * are added together and written to the 'out0' vector
+ */
+#define DOTP_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \
+ out0 = (RTYPE)__msa_dotp_s_w((v8i16)mult0, (v8i16)cnst0); \
+ out1 = (RTYPE)__msa_dotp_s_w((v8i16)mult1, (v8i16)cnst1); \
+} while (0)
+#define DOTP_SH2_SW(...) DOTP_SH2(v4i32, __VA_ARGS__)
+
+/* Description : Dot product of unsigned word vector elements
+ * Arguments : Inputs - mult0, mult1, cnst0, cnst1
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Unsigned word elements from 'mult0' are multiplied with
+ * unsigned word elements from 'cnst0' producing a result
+ * twice the size of input i.e. unsigned double word.
+ * The multiplication result of adjacent odd-even elements
+ * are added together and written to the 'out0' vector
+ */
+#define DOTP_UW2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \
+ out0 = (RTYPE)__msa_dotp_u_d((v4u32)mult0, (v4u32)cnst0); \
+ out1 = (RTYPE)__msa_dotp_u_d((v4u32)mult1, (v4u32)cnst1); \
+} while (0)
+#define DOTP_UW2_UD(...) DOTP_UW2(v2u64, __VA_ARGS__)
+
+/* Description : Dot product & addition of halfword vector elements
+ * Arguments : Inputs - mult0, mult1, cnst0, cnst1
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Signed halfword elements from 'mult0' are multiplied with
+ * signed halfword elements from 'cnst0' producing a result
+ * twice the size of input i.e. signed word.
+ * The multiplication result of adjacent odd-even elements
+ * are added to the 'out0' vector
+ */
+#define DPADD_SH2(RTYPE, mult0, mult1, cnst0, cnst1, out0, out1) do { \
+ out0 = (RTYPE)__msa_dpadd_s_w((v4i32)out0, (v8i16)mult0, (v8i16)cnst0); \
+ out1 = (RTYPE)__msa_dpadd_s_w((v4i32)out1, (v8i16)mult1, (v8i16)cnst1); \
+} while (0)
+#define DPADD_SH2_SW(...) DPADD_SH2(v4i32, __VA_ARGS__)
+
/* Description : Clips all signed halfword elements of input vector
* between 0 & 255
* Arguments : Input/output - val
* Return Type - signed halfword
*/
-#define CLIP_SH_0_255(val) { \
+#define CLIP_SH_0_255(val) do { \
const v8i16 max_m = __msa_ldi_h(255); \
val = __msa_maxi_s_h((v8i16)val, 0); \
val = __msa_min_s_h(max_m, (v8i16)val); \
-}
-#define CLIP_SH2_0_255(in0, in1) { \
- CLIP_SH_0_255(in0); \
- CLIP_SH_0_255(in1); \
-}
+} while (0)
+
+#define CLIP_SH2_0_255(in0, in1) do { \
+ CLIP_SH_0_255(in0); \
+ CLIP_SH_0_255(in1); \
+} while (0)
+
+#define CLIP_SH4_0_255(in0, in1, in2, in3) do { \
+ CLIP_SH2_0_255(in0, in1); \
+ CLIP_SH2_0_255(in2, in3); \
+} while (0)
+
+/* Description : Clips all unsigned halfword elements of input vector
+ * between 0 & 255
+ * Arguments : Input - in
+ * Output - out_m
+ * Return Type - unsigned halfword
+ */
+#define CLIP_UH_0_255(in) do { \
+ const v8u16 max_m = (v8u16)__msa_ldi_h(255); \
+ in = __msa_maxi_u_h((v8u16) in, 0); \
+ in = __msa_min_u_h((v8u16) max_m, (v8u16) in); \
+} while (0)
+
+#define CLIP_UH2_0_255(in0, in1) do { \
+ CLIP_UH_0_255(in0); \
+ CLIP_UH_0_255(in1); \
+} while (0)
/* Description : Clips all signed word elements of input vector
* between 0 & 255
* Arguments : Input/output - val
* Return Type - signed word
*/
-#define CLIP_SW_0_255(val) { \
+#define CLIP_SW_0_255(val) do { \
const v4i32 max_m = __msa_ldi_w(255); \
val = __msa_maxi_s_w((v4i32)val, 0); \
val = __msa_min_s_w(max_m, (v4i32)val); \
+} while (0)
+
+#define CLIP_SW4_0_255(in0, in1, in2, in3) do { \
+ CLIP_SW_0_255(in0); \
+ CLIP_SW_0_255(in1); \
+ CLIP_SW_0_255(in2); \
+ CLIP_SW_0_255(in3); \
+} while (0)
+
+/* Description : Horizontal addition of 4 signed word elements of input vector
+ * Arguments : Input - in (signed word vector)
+ * Output - sum_m (i32 sum)
+ * Return Type - signed word (GP)
+ * Details : 4 signed word elements of 'in' vector are added together and
+ * the resulting integer sum is returned
+ */
+static WEBP_INLINE int32_t func_hadd_sw_s32(v4i32 in) {
+ const v2i64 res0_m = __msa_hadd_s_d((v4i32)in, (v4i32)in);
+ const v2i64 res1_m = __msa_splati_d(res0_m, 1);
+ const v2i64 out = res0_m + res1_m;
+ int32_t sum_m = __msa_copy_s_w((v4i32)out, 0);
+ return sum_m;
}
-#define CLIP_SW4_0_255(in0, in1, in2, in3) { \
- CLIP_SW_0_255(in0); \
- CLIP_SW_0_255(in1); \
- CLIP_SW_0_255(in2); \
- CLIP_SW_0_255(in3); \
+#define HADD_SW_S32(in) func_hadd_sw_s32(in)
+
+/* Description : Horizontal addition of 8 signed halfword elements
+ * Arguments : Input - in (signed halfword vector)
+ * Output - sum_m (s32 sum)
+ * Return Type - signed word
+ * Details : 8 signed halfword elements of input vector are added
+ * together and the resulting integer sum is returned
+ */
+static WEBP_INLINE int32_t func_hadd_sh_s32(v8i16 in) {
+ const v4i32 res = __msa_hadd_s_w(in, in);
+ const v2i64 res0 = __msa_hadd_s_d(res, res);
+ const v2i64 res1 = __msa_splati_d(res0, 1);
+ const v2i64 res2 = res0 + res1;
+ const int32_t sum_m = __msa_copy_s_w((v4i32)res2, 0);
+ return sum_m;
+}
+#define HADD_SH_S32(in) func_hadd_sh_s32(in)
+
+/* Description : Horizontal addition of 8 unsigned halfword elements
+ * Arguments : Input - in (unsigned halfword vector)
+ * Output - sum_m (u32 sum)
+ * Return Type - unsigned word
+ * Details : 8 unsigned halfword elements of input vector are added
+ * together and the resulting integer sum is returned
+ */
+static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) {
+ uint32_t sum_m;
+ const v4u32 res_m = __msa_hadd_u_w(in, in);
+ v2u64 res0_m = __msa_hadd_u_d(res_m, res_m);
+ v2u64 res1_m = (v2u64)__msa_splati_d((v2i64)res0_m, 1);
+ res0_m = res0_m + res1_m;
+ sum_m = __msa_copy_s_w((v4i32)res0_m, 0);
+ return sum_m;
}
+#define HADD_UH_U32(in) func_hadd_uh_u32(in)
+
+/* Description : Horizontal addition of signed half word vector elements
+ Arguments : Inputs - in0, in1
+ Outputs - out0, out1
+ Return Type - as per RTYPE
+ Details : Each signed odd half word element from 'in0' is added to
+ even signed half word element from 'in0' (pairwise) and the
+ halfword result is written in 'out0'
+*/
+#define HADD_SH2(RTYPE, in0, in1, out0, out1) do { \
+ out0 = (RTYPE)__msa_hadd_s_w((v8i16)in0, (v8i16)in0); \
+ out1 = (RTYPE)__msa_hadd_s_w((v8i16)in1, (v8i16)in1); \
+} while (0)
+#define HADD_SH2_SW(...) HADD_SH2(v4i32, __VA_ARGS__)
+
+#define HADD_SH4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3) do { \
+ HADD_SH2(RTYPE, in0, in1, out0, out1); \
+ HADD_SH2(RTYPE, in2, in3, out2, out3); \
+} while (0)
+#define HADD_SH4_SW(...) HADD_SH4(v4i32, __VA_ARGS__)
+
+/* Description : Horizontal subtraction of unsigned byte vector elements
+ * Arguments : Inputs - in0, in1
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Each unsigned odd byte element from 'in0' is subtracted from
+ * even unsigned byte element from 'in0' (pairwise) and the
+ * halfword result is written to 'out0'
+ */
+#define HSUB_UB2(RTYPE, in0, in1, out0, out1) do { \
+ out0 = (RTYPE)__msa_hsub_u_h((v16u8)in0, (v16u8)in0); \
+ out1 = (RTYPE)__msa_hsub_u_h((v16u8)in1, (v16u8)in1); \
+} while (0)
+#define HSUB_UB2_UH(...) HSUB_UB2(v8u16, __VA_ARGS__)
+#define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__)
+#define HSUB_UB2_SW(...) HSUB_UB2(v4i32, __VA_ARGS__)
/* Description : Set element n input vector to GPR value
* Arguments : Inputs - in0, in1, in2, in3
@@ -282,23 +669,188 @@
* Return Type - as per RTYPE
* Details : Set element 0 in vector 'out' to value specified in 'in0'
*/
-#define INSERT_W2(RTYPE, in0, in1, out) { \
+#define INSERT_W2(RTYPE, in0, in1, out) do { \
out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \
out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \
-}
+} while (0)
#define INSERT_W2_UB(...) INSERT_W2(v16u8, __VA_ARGS__)
#define INSERT_W2_SB(...) INSERT_W2(v16i8, __VA_ARGS__)
-#define INSERT_W4(RTYPE, in0, in1, in2, in3, out) { \
- out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \
- out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \
- out = (RTYPE)__msa_insert_w((v4i32)out, 2, in2); \
- out = (RTYPE)__msa_insert_w((v4i32)out, 3, in3); \
-}
+#define INSERT_W4(RTYPE, in0, in1, in2, in3, out) do { \
+ out = (RTYPE)__msa_insert_w((v4i32)out, 0, in0); \
+ out = (RTYPE)__msa_insert_w((v4i32)out, 1, in1); \
+ out = (RTYPE)__msa_insert_w((v4i32)out, 2, in2); \
+ out = (RTYPE)__msa_insert_w((v4i32)out, 3, in3); \
+} while (0)
#define INSERT_W4_UB(...) INSERT_W4(v16u8, __VA_ARGS__)
#define INSERT_W4_SB(...) INSERT_W4(v16i8, __VA_ARGS__)
#define INSERT_W4_SW(...) INSERT_W4(v4i32, __VA_ARGS__)
+/* Description : Set element n of double word input vector to GPR value
+ * Arguments : Inputs - in0, in1
+ * Output - out
+ * Return Type - as per RTYPE
+ * Details : Set element 0 in vector 'out' to GPR value specified in 'in0'
+ * Set element 1 in vector 'out' to GPR value specified in 'in1'
+ */
+#define INSERT_D2(RTYPE, in0, in1, out) do { \
+ out = (RTYPE)__msa_insert_d((v2i64)out, 0, in0); \
+ out = (RTYPE)__msa_insert_d((v2i64)out, 1, in1); \
+} while (0)
+#define INSERT_D2_UB(...) INSERT_D2(v16u8, __VA_ARGS__)
+#define INSERT_D2_SB(...) INSERT_D2(v16i8, __VA_ARGS__)
+
+/* Description : Interleave even byte elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even byte elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ */
+#define ILVEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvev_b((v16i8)in1, (v16i8)in0); \
+ out1 = (RTYPE)__msa_ilvev_b((v16i8)in3, (v16i8)in2); \
+} while (0)
+#define ILVEV_B2_UB(...) ILVEV_B2(v16u8, __VA_ARGS__)
+#define ILVEV_B2_SB(...) ILVEV_B2(v16i8, __VA_ARGS__)
+#define ILVEV_B2_UH(...) ILVEV_B2(v8u16, __VA_ARGS__)
+#define ILVEV_B2_SH(...) ILVEV_B2(v8i16, __VA_ARGS__)
+#define ILVEV_B2_SD(...) ILVEV_B2(v2i64, __VA_ARGS__)
+
+/* Description : Interleave odd byte elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Odd byte elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ */
+#define ILVOD_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvod_b((v16i8)in1, (v16i8)in0); \
+ out1 = (RTYPE)__msa_ilvod_b((v16i8)in3, (v16i8)in2); \
+} while (0)
+#define ILVOD_B2_UB(...) ILVOD_B2(v16u8, __VA_ARGS__)
+#define ILVOD_B2_SB(...) ILVOD_B2(v16i8, __VA_ARGS__)
+#define ILVOD_B2_UH(...) ILVOD_B2(v8u16, __VA_ARGS__)
+#define ILVOD_B2_SH(...) ILVOD_B2(v8i16, __VA_ARGS__)
+#define ILVOD_B2_SD(...) ILVOD_B2(v2i64, __VA_ARGS__)
+
+/* Description : Interleave even halfword elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even halfword elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ */
+#define ILVEV_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvev_h((v8i16)in1, (v8i16)in0); \
+ out1 = (RTYPE)__msa_ilvev_h((v8i16)in3, (v8i16)in2); \
+} while (0)
+#define ILVEV_H2_UB(...) ILVEV_H2(v16u8, __VA_ARGS__)
+#define ILVEV_H2_UH(...) ILVEV_H2(v8u16, __VA_ARGS__)
+#define ILVEV_H2_SH(...) ILVEV_H2(v8i16, __VA_ARGS__)
+#define ILVEV_H2_SW(...) ILVEV_H2(v4i32, __VA_ARGS__)
+
+/* Description : Interleave odd halfword elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Odd halfword elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ */
+#define ILVOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvod_h((v8i16)in1, (v8i16)in0); \
+ out1 = (RTYPE)__msa_ilvod_h((v8i16)in3, (v8i16)in2); \
+} while (0)
+#define ILVOD_H2_UB(...) ILVOD_H2(v16u8, __VA_ARGS__)
+#define ILVOD_H2_UH(...) ILVOD_H2(v8u16, __VA_ARGS__)
+#define ILVOD_H2_SH(...) ILVOD_H2(v8i16, __VA_ARGS__)
+#define ILVOD_H2_SW(...) ILVOD_H2(v4i32, __VA_ARGS__)
+
+/* Description : Interleave even word elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even word elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ */
+#define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvev_w((v4i32)in1, (v4i32)in0); \
+ out1 = (RTYPE)__msa_ilvev_w((v4i32)in3, (v4i32)in2); \
+} while (0)
+#define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__)
+#define ILVEV_W2_SB(...) ILVEV_W2(v16i8, __VA_ARGS__)
+#define ILVEV_W2_UH(...) ILVEV_W2(v8u16, __VA_ARGS__)
+#define ILVEV_W2_SD(...) ILVEV_W2(v2i64, __VA_ARGS__)
+
+/* Description : Interleave even-odd word elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even word elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ * Odd word elements of 'in2' and 'in3' are interleaved
+ * and written to 'out1'
+ */
+#define ILVEVOD_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvev_w((v4i32)in1, (v4i32)in0); \
+ out1 = (RTYPE)__msa_ilvod_w((v4i32)in3, (v4i32)in2); \
+} while (0)
+#define ILVEVOD_W2_UB(...) ILVEVOD_W2(v16u8, __VA_ARGS__)
+#define ILVEVOD_W2_UH(...) ILVEVOD_W2(v8u16, __VA_ARGS__)
+#define ILVEVOD_W2_SH(...) ILVEVOD_W2(v8i16, __VA_ARGS__)
+#define ILVEVOD_W2_SW(...) ILVEVOD_W2(v4i32, __VA_ARGS__)
+
+/* Description : Interleave even-odd half-word elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even half-word elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ * Odd half-word elements of 'in2' and 'in3' are interleaved
+ * and written to 'out1'
+ */
+#define ILVEVOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvev_h((v8i16)in1, (v8i16)in0); \
+ out1 = (RTYPE)__msa_ilvod_h((v8i16)in3, (v8i16)in2); \
+} while (0)
+#define ILVEVOD_H2_UB(...) ILVEVOD_H2(v16u8, __VA_ARGS__)
+#define ILVEVOD_H2_UH(...) ILVEVOD_H2(v8u16, __VA_ARGS__)
+#define ILVEVOD_H2_SH(...) ILVEVOD_H2(v8i16, __VA_ARGS__)
+#define ILVEVOD_H2_SW(...) ILVEVOD_H2(v4i32, __VA_ARGS__)
+
+/* Description : Interleave even double word elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even double word elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'
+ */
+#define ILVEV_D2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvev_d((v2i64)in1, (v2i64)in0); \
+ out1 = (RTYPE)__msa_ilvev_d((v2i64)in3, (v2i64)in2); \
+} while (0)
+#define ILVEV_D2_UB(...) ILVEV_D2(v16u8, __VA_ARGS__)
+#define ILVEV_D2_SB(...) ILVEV_D2(v16i8, __VA_ARGS__)
+#define ILVEV_D2_SW(...) ILVEV_D2(v4i32, __VA_ARGS__)
+#define ILVEV_D2_SD(...) ILVEV_D2(v2i64, __VA_ARGS__)
+
+/* Description : Interleave left half of byte elements from vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Left half of byte elements of 'in0' and 'in1' are interleaved
+ * and written to 'out0'.
+ */
+#define ILVL_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvl_b((v16i8)in0, (v16i8)in1); \
+ out1 = (RTYPE)__msa_ilvl_b((v16i8)in2, (v16i8)in3); \
+} while (0)
+#define ILVL_B2_UB(...) ILVL_B2(v16u8, __VA_ARGS__)
+#define ILVL_B2_SB(...) ILVL_B2(v16i8, __VA_ARGS__)
+#define ILVL_B2_UH(...) ILVL_B2(v8u16, __VA_ARGS__)
+#define ILVL_B2_SH(...) ILVL_B2(v8i16, __VA_ARGS__)
+#define ILVL_B2_SW(...) ILVL_B2(v4i32, __VA_ARGS__)
+
/* Description : Interleave right half of byte elements from vectors
* Arguments : Inputs - in0, in1, in2, in3
* Outputs - out0, out1
@@ -306,10 +858,10 @@
* Details : Right half of byte elements of 'in0' and 'in1' are interleaved
* and written to out0.
*/
-#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \
- out1 = (RTYPE)__msa_ilvr_b((v16i8)in2, (v16i8)in3); \
-}
+#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \
+ out1 = (RTYPE)__msa_ilvr_b((v16i8)in2, (v16i8)in3); \
+} while (0)
#define ILVR_B2_UB(...) ILVR_B2(v16u8, __VA_ARGS__)
#define ILVR_B2_SB(...) ILVR_B2(v16i8, __VA_ARGS__)
#define ILVR_B2_UH(...) ILVR_B2(v8u16, __VA_ARGS__)
@@ -317,10 +869,10 @@
#define ILVR_B2_SW(...) ILVR_B2(v4i32, __VA_ARGS__)
#define ILVR_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
- out0, out1, out2, out3) { \
+ out0, out1, out2, out3) do { \
ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1); \
ILVR_B2(RTYPE, in4, in5, in6, in7, out2, out3); \
-}
+} while (0)
#define ILVR_B4_UB(...) ILVR_B4(v16u8, __VA_ARGS__)
#define ILVR_B4_SB(...) ILVR_B4(v16i8, __VA_ARGS__)
#define ILVR_B4_UH(...) ILVR_B4(v8u16, __VA_ARGS__)
@@ -334,19 +886,19 @@
* Details : Right half of halfword elements of 'in0' and 'in1' are
* interleaved and written to 'out0'.
*/
-#define ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \
- out1 = (RTYPE)__msa_ilvr_h((v8i16)in2, (v8i16)in3); \
-}
+#define ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \
+ out1 = (RTYPE)__msa_ilvr_h((v8i16)in2, (v8i16)in3); \
+} while (0)
#define ILVR_H2_UB(...) ILVR_H2(v16u8, __VA_ARGS__)
#define ILVR_H2_SH(...) ILVR_H2(v8i16, __VA_ARGS__)
#define ILVR_H2_SW(...) ILVR_H2(v4i32, __VA_ARGS__)
#define ILVR_H4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
- out0, out1, out2, out3) { \
+ out0, out1, out2, out3) do { \
ILVR_H2(RTYPE, in0, in1, in2, in3, out0, out1); \
ILVR_H2(RTYPE, in4, in5, in6, in7, out2, out3); \
-}
+} while (0)
#define ILVR_H4_UB(...) ILVR_H4(v16u8, __VA_ARGS__)
#define ILVR_H4_SH(...) ILVR_H4(v8i16, __VA_ARGS__)
#define ILVR_H4_SW(...) ILVR_H4(v4i32, __VA_ARGS__)
@@ -358,31 +910,57 @@
* Details : Right half of double word elements of 'in0' and 'in1' are
* interleaved and written to 'out0'.
*/
-#define ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_ilvr_d((v2i64)in0, (v2i64)in1); \
- out1 = (RTYPE)__msa_ilvr_d((v2i64)in2, (v2i64)in3); \
-}
+#define ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvr_d((v2i64)in0, (v2i64)in1); \
+ out1 = (RTYPE)__msa_ilvr_d((v2i64)in2, (v2i64)in3); \
+} while (0)
#define ILVR_D2_UB(...) ILVR_D2(v16u8, __VA_ARGS__)
#define ILVR_D2_SB(...) ILVR_D2(v16i8, __VA_ARGS__)
#define ILVR_D2_SH(...) ILVR_D2(v8i16, __VA_ARGS__)
-#define ILVRL_H2(RTYPE, in0, in1, out0, out1) { \
+#define ILVR_D4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
+ out0, out1, out2, out3) do { \
+ ILVR_D2(RTYPE, in0, in1, in2, in3, out0, out1); \
+ ILVR_D2(RTYPE, in4, in5, in6, in7, out2, out3); \
+} while (0)
+#define ILVR_D4_SB(...) ILVR_D4(v16i8, __VA_ARGS__)
+#define ILVR_D4_UB(...) ILVR_D4(v16u8, __VA_ARGS__)
+
+/* Description : Interleave both left and right half of input vectors
+ * Arguments : Inputs - in0, in1
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Right half of byte elements from 'in0' and 'in1' are
+ * interleaved and written to 'out0'
+ */
+#define ILVRL_B2(RTYPE, in0, in1, out0, out1) do { \
+ out0 = (RTYPE)__msa_ilvr_b((v16i8)in0, (v16i8)in1); \
+ out1 = (RTYPE)__msa_ilvl_b((v16i8)in0, (v16i8)in1); \
+} while (0)
+#define ILVRL_B2_UB(...) ILVRL_B2(v16u8, __VA_ARGS__)
+#define ILVRL_B2_SB(...) ILVRL_B2(v16i8, __VA_ARGS__)
+#define ILVRL_B2_UH(...) ILVRL_B2(v8u16, __VA_ARGS__)
+#define ILVRL_B2_SH(...) ILVRL_B2(v8i16, __VA_ARGS__)
+#define ILVRL_B2_SW(...) ILVRL_B2(v4i32, __VA_ARGS__)
+
+#define ILVRL_H2(RTYPE, in0, in1, out0, out1) do { \
out0 = (RTYPE)__msa_ilvr_h((v8i16)in0, (v8i16)in1); \
out1 = (RTYPE)__msa_ilvl_h((v8i16)in0, (v8i16)in1); \
-}
+} while (0)
#define ILVRL_H2_UB(...) ILVRL_H2(v16u8, __VA_ARGS__)
#define ILVRL_H2_SB(...) ILVRL_H2(v16i8, __VA_ARGS__)
#define ILVRL_H2_SH(...) ILVRL_H2(v8i16, __VA_ARGS__)
#define ILVRL_H2_SW(...) ILVRL_H2(v4i32, __VA_ARGS__)
#define ILVRL_H2_UW(...) ILVRL_H2(v4u32, __VA_ARGS__)
-#define ILVRL_W2(RTYPE, in0, in1, out0, out1) { \
+#define ILVRL_W2(RTYPE, in0, in1, out0, out1) do { \
out0 = (RTYPE)__msa_ilvr_w((v4i32)in0, (v4i32)in1); \
out1 = (RTYPE)__msa_ilvl_w((v4i32)in0, (v4i32)in1); \
-}
+} while (0)
#define ILVRL_W2_UB(...) ILVRL_W2(v16u8, __VA_ARGS__)
#define ILVRL_W2_SH(...) ILVRL_W2(v8i16, __VA_ARGS__)
#define ILVRL_W2_SW(...) ILVRL_W2(v4i32, __VA_ARGS__)
+#define ILVRL_W2_UW(...) ILVRL_W2(v4u32, __VA_ARGS__)
/* Description : Pack even byte elements of vector pairs
* Arguments : Inputs - in0, in1, in2, in3
@@ -392,15 +970,76 @@
* 'out0' & even byte elements of 'in1' are copied to the right
* half of 'out0'.
*/
-#define PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)__msa_pckev_b((v16i8)in0, (v16i8)in1); \
- out1 = (RTYPE)__msa_pckev_b((v16i8)in2, (v16i8)in3); \
-}
+#define PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_pckev_b((v16i8)in0, (v16i8)in1); \
+ out1 = (RTYPE)__msa_pckev_b((v16i8)in2, (v16i8)in3); \
+} while (0)
#define PCKEV_B2_SB(...) PCKEV_B2(v16i8, __VA_ARGS__)
#define PCKEV_B2_UB(...) PCKEV_B2(v16u8, __VA_ARGS__)
#define PCKEV_B2_SH(...) PCKEV_B2(v8i16, __VA_ARGS__)
#define PCKEV_B2_SW(...) PCKEV_B2(v4i32, __VA_ARGS__)
+#define PCKEV_B4(RTYPE, in0, in1, in2, in3, in4, in5, in6, in7, \
+ out0, out1, out2, out3) do { \
+ PCKEV_B2(RTYPE, in0, in1, in2, in3, out0, out1); \
+ PCKEV_B2(RTYPE, in4, in5, in6, in7, out2, out3); \
+} while (0)
+#define PCKEV_B4_SB(...) PCKEV_B4(v16i8, __VA_ARGS__)
+#define PCKEV_B4_UB(...) PCKEV_B4(v16u8, __VA_ARGS__)
+#define PCKEV_B4_SH(...) PCKEV_B4(v8i16, __VA_ARGS__)
+#define PCKEV_B4_SW(...) PCKEV_B4(v4i32, __VA_ARGS__)
+
+/* Description : Pack even halfword elements of vector pairs
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even halfword elements of 'in0' are copied to the left half of
+ * 'out0' & even halfword elements of 'in1' are copied to the
+ * right half of 'out0'.
+ */
+#define PCKEV_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_pckev_h((v8i16)in0, (v8i16)in1); \
+ out1 = (RTYPE)__msa_pckev_h((v8i16)in2, (v8i16)in3); \
+} while (0)
+#define PCKEV_H2_UH(...) PCKEV_H2(v8u16, __VA_ARGS__)
+#define PCKEV_H2_SH(...) PCKEV_H2(v8i16, __VA_ARGS__)
+#define PCKEV_H2_SW(...) PCKEV_H2(v4i32, __VA_ARGS__)
+#define PCKEV_H2_UW(...) PCKEV_H2(v4u32, __VA_ARGS__)
+
+/* Description : Pack even word elements of vector pairs
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Even word elements of 'in0' are copied to the left half of
+ * 'out0' & even word elements of 'in1' are copied to the
+ * right half of 'out0'.
+ */
+#define PCKEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_pckev_w((v4i32)in0, (v4i32)in1); \
+ out1 = (RTYPE)__msa_pckev_w((v4i32)in2, (v4i32)in3); \
+} while (0)
+#define PCKEV_W2_UH(...) PCKEV_W2(v8u16, __VA_ARGS__)
+#define PCKEV_W2_SH(...) PCKEV_W2(v8i16, __VA_ARGS__)
+#define PCKEV_W2_SW(...) PCKEV_W2(v4i32, __VA_ARGS__)
+#define PCKEV_W2_UW(...) PCKEV_W2(v4u32, __VA_ARGS__)
+
+/* Description : Pack odd halfword elements of vector pairs
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Odd halfword elements of 'in0' are copied to the left half of
+ * 'out0' & odd halfword elements of 'in1' are copied to the
+ * right half of 'out0'.
+ */
+#define PCKOD_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_pckod_h((v8i16)in0, (v8i16)in1); \
+ out1 = (RTYPE)__msa_pckod_h((v8i16)in2, (v8i16)in3); \
+} while (0)
+#define PCKOD_H2_UH(...) PCKOD_H2(v8u16, __VA_ARGS__)
+#define PCKOD_H2_SH(...) PCKOD_H2(v8i16, __VA_ARGS__)
+#define PCKOD_H2_SW(...) PCKOD_H2(v4i32, __VA_ARGS__)
+#define PCKOD_H2_UW(...) PCKOD_H2(v4u32, __VA_ARGS__)
+
/* Description : Arithmetic immediate shift right all elements of word vector
* Arguments : Inputs - in0, in1, shift
* Outputs - in place operation
@@ -408,17 +1047,17 @@
* Details : Each element of vector 'in0' is right shifted by 'shift' and
* the result is written in-place. 'shift' is a GP variable.
*/
-#define SRAI_W2(RTYPE, in0, in1, shift_val) { \
- in0 = (RTYPE)SRAI_W(in0, shift_val); \
- in1 = (RTYPE)SRAI_W(in1, shift_val); \
-}
+#define SRAI_W2(RTYPE, in0, in1, shift_val) do { \
+ in0 = (RTYPE)SRAI_W(in0, shift_val); \
+ in1 = (RTYPE)SRAI_W(in1, shift_val); \
+} while (0)
#define SRAI_W2_SW(...) SRAI_W2(v4i32, __VA_ARGS__)
#define SRAI_W2_UW(...) SRAI_W2(v4u32, __VA_ARGS__)
-#define SRAI_W4(RTYPE, in0, in1, in2, in3, shift_val) { \
- SRAI_W2(RTYPE, in0, in1, shift_val); \
- SRAI_W2(RTYPE, in2, in3, shift_val); \
-}
+#define SRAI_W4(RTYPE, in0, in1, in2, in3, shift_val) do { \
+ SRAI_W2(RTYPE, in0, in1, shift_val); \
+ SRAI_W2(RTYPE, in2, in3, shift_val); \
+} while (0)
#define SRAI_W4_SW(...) SRAI_W4(v4i32, __VA_ARGS__)
#define SRAI_W4_UW(...) SRAI_W4(v4u32, __VA_ARGS__)
@@ -429,10 +1068,10 @@
* Details : Each element of vector 'in0' is right shifted by 'shift' and
* the result is written in-place. 'shift' is a GP variable.
*/
-#define SRAI_H2(RTYPE, in0, in1, shift_val) { \
- in0 = (RTYPE)SRAI_H(in0, shift_val); \
- in1 = (RTYPE)SRAI_H(in1, shift_val); \
-}
+#define SRAI_H2(RTYPE, in0, in1, shift_val) do { \
+ in0 = (RTYPE)SRAI_H(in0, shift_val); \
+ in1 = (RTYPE)SRAI_H(in1, shift_val); \
+} while (0)
#define SRAI_H2_SH(...) SRAI_H2(v8i16, __VA_ARGS__)
#define SRAI_H2_UH(...) SRAI_H2(v8u16, __VA_ARGS__)
@@ -443,48 +1082,166 @@
* Details : Each element of vector 'in0' is right shifted by 'shift' and
* the result is written in-place. 'shift' is a GP variable.
*/
-#define SRARI_W2(RTYPE, in0, in1, shift) { \
+#define SRARI_W2(RTYPE, in0, in1, shift) do { \
in0 = (RTYPE)__msa_srari_w((v4i32)in0, shift); \
in1 = (RTYPE)__msa_srari_w((v4i32)in1, shift); \
-}
+} while (0)
#define SRARI_W2_SW(...) SRARI_W2(v4i32, __VA_ARGS__)
-#define SRARI_W4(RTYPE, in0, in1, in2, in3, shift) { \
- SRARI_W2(RTYPE, in0, in1, shift); \
- SRARI_W2(RTYPE, in2, in3, shift); \
-}
+#define SRARI_W4(RTYPE, in0, in1, in2, in3, shift) do { \
+ SRARI_W2(RTYPE, in0, in1, shift); \
+ SRARI_W2(RTYPE, in2, in3, shift); \
+} while (0)
#define SRARI_W4_SH(...) SRARI_W4(v8i16, __VA_ARGS__)
#define SRARI_W4_UW(...) SRARI_W4(v4u32, __VA_ARGS__)
#define SRARI_W4_SW(...) SRARI_W4(v4i32, __VA_ARGS__)
+/* Description : Shift right arithmetic rounded double words
+ * Arguments : Inputs - in0, in1, shift
+ * Outputs - in place operation
+ * Return Type - as per RTYPE
+ * Details : Each element of vector 'in0' is shifted right arithmetically by
+ * the number of bits in the corresponding element in the vector
+ * 'shift'. The last discarded bit is added to shifted value for
+ * rounding and the result is written in-place.
+ * 'shift' is a vector.
+ */
+#define SRAR_D2(RTYPE, in0, in1, shift) do { \
+ in0 = (RTYPE)__msa_srar_d((v2i64)in0, (v2i64)shift); \
+ in1 = (RTYPE)__msa_srar_d((v2i64)in1, (v2i64)shift); \
+} while (0)
+#define SRAR_D2_SW(...) SRAR_D2(v4i32, __VA_ARGS__)
+#define SRAR_D2_SD(...) SRAR_D2(v2i64, __VA_ARGS__)
+#define SRAR_D2_UD(...) SRAR_D2(v2u64, __VA_ARGS__)
+
+#define SRAR_D4(RTYPE, in0, in1, in2, in3, shift) do { \
+ SRAR_D2(RTYPE, in0, in1, shift); \
+ SRAR_D2(RTYPE, in2, in3, shift); \
+} while (0)
+#define SRAR_D4_SD(...) SRAR_D4(v2i64, __VA_ARGS__)
+#define SRAR_D4_UD(...) SRAR_D4(v2u64, __VA_ARGS__)
+
/* Description : Addition of 2 pairs of half-word vectors
* Arguments : Inputs - in0, in1, in2, in3
* Outputs - out0, out1
* Details : Each element in 'in0' is added to 'in1' and result is written
* to 'out0'.
*/
-#define ADDVI_H2(RTYPE, in0, in1, in2, in3, out0, out1) { \
- out0 = (RTYPE)ADDVI_H(in0, in1); \
- out1 = (RTYPE)ADDVI_H(in2, in3); \
-}
+#define ADDVI_H2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)ADDVI_H(in0, in1); \
+ out1 = (RTYPE)ADDVI_H(in2, in3); \
+} while (0)
#define ADDVI_H2_SH(...) ADDVI_H2(v8i16, __VA_ARGS__)
#define ADDVI_H2_UH(...) ADDVI_H2(v8u16, __VA_ARGS__)
+/* Description : Addition of 2 pairs of word vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Details : Each element in 'in0' is added to 'in1' and result is written
+ * to 'out0'.
+ */
+#define ADDVI_W2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)ADDVI_W(in0, in1); \
+ out1 = (RTYPE)ADDVI_W(in2, in3); \
+} while (0)
+#define ADDVI_W2_SW(...) ADDVI_W2(v4i32, __VA_ARGS__)
+
+/* Description : Fill 2 pairs of word vectors with GP registers
+ * Arguments : Inputs - in0, in1
+ * Outputs - out0, out1
+ * Details : GP register in0 is replicated in each word element of out0
+ * GP register in1 is replicated in each word element of out1
+ */
+#define FILL_W2(RTYPE, in0, in1, out0, out1) do { \
+ out0 = (RTYPE)__msa_fill_w(in0); \
+ out1 = (RTYPE)__msa_fill_w(in1); \
+} while (0)
+#define FILL_W2_SW(...) FILL_W2(v4i32, __VA_ARGS__)
+
/* Description : Addition of 2 pairs of vectors
* Arguments : Inputs - in0, in1, in2, in3
* Outputs - out0, out1
* Details : Each element in 'in0' is added to 'in1' and result is written
* to 'out0'.
*/
-#define ADD2(in0, in1, in2, in3, out0, out1) { \
- out0 = in0 + in1; \
- out1 = in2 + in3; \
-}
+#define ADD2(in0, in1, in2, in3, out0, out1) do { \
+ out0 = in0 + in1; \
+ out1 = in2 + in3; \
+} while (0)
+
#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, \
- out0, out1, out2, out3) { \
+ out0, out1, out2, out3) do { \
ADD2(in0, in1, in2, in3, out0, out1); \
ADD2(in4, in5, in6, in7, out2, out3); \
-}
+} while (0)
+
+/* Description : Subtraction of 2 pairs of vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Details : Each element in 'in1' is subtracted from 'in0' and result is
+ * written to 'out0'.
+ */
+#define SUB2(in0, in1, in2, in3, out0, out1) do { \
+ out0 = in0 - in1; \
+ out1 = in2 - in3; \
+} while (0)
+
+#define SUB3(in0, in1, in2, in3, in4, in5, out0, out1, out2) do { \
+ out0 = in0 - in1; \
+ out1 = in2 - in3; \
+ out2 = in4 - in5; \
+} while (0)
+
+#define SUB4(in0, in1, in2, in3, in4, in5, in6, in7, \
+ out0, out1, out2, out3) do { \
+ out0 = in0 - in1; \
+ out1 = in2 - in3; \
+ out2 = in4 - in5; \
+ out3 = in6 - in7; \
+} while (0)
+
+/* Description : Addition - Subtraction of input vectors
+ * Arguments : Inputs - in0, in1
+ * Outputs - out0, out1
+ * Details : Each element in 'in1' is added to 'in0' and result is
+ * written to 'out0'.
+ * Each element in 'in1' is subtracted from 'in0' and result is
+ * written to 'out1'.
+ */
+#define ADDSUB2(in0, in1, out0, out1) do { \
+ out0 = in0 + in1; \
+ out1 = in0 - in1; \
+} while (0)
+
+/* Description : Multiplication of pairs of vectors
+ * Arguments : Inputs - in0, in1, in2, in3
+ * Outputs - out0, out1
+ * Details : Each element from 'in0' is multiplied with elements from 'in1'
+ * and the result is written to 'out0'
+ */
+#define MUL2(in0, in1, in2, in3, out0, out1) do { \
+ out0 = in0 * in1; \
+ out1 = in2 * in3; \
+} while (0)
+
+#define MUL4(in0, in1, in2, in3, in4, in5, in6, in7, \
+ out0, out1, out2, out3) do { \
+ MUL2(in0, in1, in2, in3, out0, out1); \
+ MUL2(in4, in5, in6, in7, out2, out3); \
+} while (0)
+
+/* Description : Sign extend halfword elements from right half of the vector
+ * Arguments : Input - in (halfword vector)
+ * Output - out (sign extended word vector)
+ * Return Type - signed word
+ * Details : Sign bit of halfword elements from input vector 'in' is
+ * extracted and interleaved with same vector 'in0' to generate
+ * 4 word elements keeping sign intact
+ */
+#define UNPCK_R_SH_SW(in, out) do { \
+ const v8i16 sign_m = __msa_clti_s_h((v8i16)in, 0); \
+ out = (v4i32)__msa_ilvr_h(sign_m, (v8i16)in); \
+} while (0)
/* Description : Sign extend halfword elements from input vector and return
* the result in pair of vectors
@@ -497,29 +1254,82 @@
* Then interleaved left with same vector 'in0' to
* generate 4 signed word elements in 'out1'
*/
-#define UNPCK_SH_SW(in, out0, out1) { \
+#define UNPCK_SH_SW(in, out0, out1) do { \
const v8i16 tmp_m = __msa_clti_s_h((v8i16)in, 0); \
ILVRL_H2_SW(tmp_m, in, out0, out1); \
-}
+} while (0)
/* Description : Butterfly of 4 input vectors
* Arguments : Inputs - in0, in1, in2, in3
* Outputs - out0, out1, out2, out3
* Details : Butterfly operation
*/
-#define BUTTERFLY_4(in0, in1, in2, in3, out0, out1, out2, out3) { \
- out0 = in0 + in3; \
- out1 = in1 + in2; \
- out2 = in1 - in2; \
- out3 = in0 - in3; \
-}
+#define BUTTERFLY_4(in0, in1, in2, in3, out0, out1, out2, out3) do { \
+ out0 = in0 + in3; \
+ out1 = in1 + in2; \
+ out2 = in1 - in2; \
+ out3 = in0 - in3; \
+} while (0)
+
+/* Description : Transpose 16x4 block into 4x16 with byte elements in vectors
+ * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7,
+ * in8, in9, in10, in11, in12, in13, in14, in15
+ * Outputs - out0, out1, out2, out3
+ * Return Type - unsigned byte
+ */
+#define TRANSPOSE16x4_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7, \
+ in8, in9, in10, in11, in12, in13, in14, in15, \
+ out0, out1, out2, out3) do { \
+ v2i64 tmp0_m, tmp1_m, tmp2_m, tmp3_m, tmp4_m, tmp5_m; \
+ ILVEV_W2_SD(in0, in4, in8, in12, tmp2_m, tmp3_m); \
+ ILVEV_W2_SD(in1, in5, in9, in13, tmp0_m, tmp1_m); \
+ ILVEV_D2_UB(tmp2_m, tmp3_m, tmp0_m, tmp1_m, out1, out3); \
+ ILVEV_W2_SD(in2, in6, in10, in14, tmp4_m, tmp5_m); \
+ ILVEV_W2_SD(in3, in7, in11, in15, tmp0_m, tmp1_m); \
+ ILVEV_D2_SD(tmp4_m, tmp5_m, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \
+ ILVEV_B2_SD(out1, out3, tmp2_m, tmp3_m, tmp0_m, tmp1_m); \
+ ILVEVOD_H2_UB(tmp0_m, tmp1_m, tmp0_m, tmp1_m, out0, out2); \
+ ILVOD_B2_SD(out1, out3, tmp2_m, tmp3_m, tmp0_m, tmp1_m); \
+ ILVEVOD_H2_UB(tmp0_m, tmp1_m, tmp0_m, tmp1_m, out1, out3); \
+} while (0)
+
+/* Description : Transpose 16x8 block into 8x16 with byte elements in vectors
+ * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7,
+ * in8, in9, in10, in11, in12, in13, in14, in15
+ * Outputs - out0, out1, out2, out3, out4, out5, out6, out7
+ * Return Type - unsigned byte
+ */
+#define TRANSPOSE16x8_UB_UB(in0, in1, in2, in3, in4, in5, in6, in7, \
+ in8, in9, in10, in11, in12, in13, in14, in15, \
+ out0, out1, out2, out3, out4, out5, \
+ out6, out7) do { \
+ v8i16 tmp0_m, tmp1_m, tmp4_m, tmp5_m, tmp6_m, tmp7_m; \
+ v4i32 tmp2_m, tmp3_m; \
+ ILVEV_D2_UB(in0, in8, in1, in9, out7, out6); \
+ ILVEV_D2_UB(in2, in10, in3, in11, out5, out4); \
+ ILVEV_D2_UB(in4, in12, in5, in13, out3, out2); \
+ ILVEV_D2_UB(in6, in14, in7, in15, out1, out0); \
+ ILVEV_B2_SH(out7, out6, out5, out4, tmp0_m, tmp1_m); \
+ ILVOD_B2_SH(out7, out6, out5, out4, tmp4_m, tmp5_m); \
+ ILVEV_B2_UB(out3, out2, out1, out0, out5, out7); \
+ ILVOD_B2_SH(out3, out2, out1, out0, tmp6_m, tmp7_m); \
+ ILVEV_H2_SW(tmp0_m, tmp1_m, out5, out7, tmp2_m, tmp3_m); \
+ ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out0, out4); \
+ ILVOD_H2_SW(tmp0_m, tmp1_m, out5, out7, tmp2_m, tmp3_m); \
+ ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out2, out6); \
+ ILVEV_H2_SW(tmp4_m, tmp5_m, tmp6_m, tmp7_m, tmp2_m, tmp3_m); \
+ ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out1, out5); \
+ ILVOD_H2_SW(tmp4_m, tmp5_m, tmp6_m, tmp7_m, tmp2_m, tmp3_m); \
+ ILVEVOD_W2_UB(tmp2_m, tmp3_m, tmp2_m, tmp3_m, out3, out7); \
+} while (0)
/* Description : Transpose 4x4 block with word elements in vectors
* Arguments : Inputs - in0, in1, in2, in3
* Outputs - out0, out1, out2, out3
* Return Type - as per RTYPE
*/
-#define TRANSPOSE4x4_W(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3) { \
+#define TRANSPOSE4x4_W(RTYPE, in0, in1, in2, in3, \
+ out0, out1, out2, out3) do { \
v4i32 s0_m, s1_m, s2_m, s3_m; \
ILVRL_W2_SW(in1, in0, s0_m, s1_m); \
ILVRL_W2_SW(in3, in2, s2_m, s3_m); \
@@ -527,7 +1337,7 @@
out1 = (RTYPE)__msa_ilvl_d((v2i64)s2_m, (v2i64)s0_m); \
out2 = (RTYPE)__msa_ilvr_d((v2i64)s3_m, (v2i64)s1_m); \
out3 = (RTYPE)__msa_ilvl_d((v2i64)s3_m, (v2i64)s1_m); \
-}
+} while (0)
#define TRANSPOSE4x4_SW_SW(...) TRANSPOSE4x4_W(v4i32, __VA_ARGS__)
/* Description : Add block 4x4
@@ -535,7 +1345,7 @@
* Details : Least significant 4 bytes from each input vector are added to
* the destination bytes, clipped between 0-255 and stored.
*/
-#define ADDBLK_ST4x4_UB(in0, in1, in2, in3, pdst, stride) { \
+#define ADDBLK_ST4x4_UB(in0, in1, in2, in3, pdst, stride) do { \
uint32_t src0_m, src1_m, src2_m, src3_m; \
v8i16 inp0_m, inp1_m, res0_m, res1_m; \
v16i8 dst0_m = { 0 }; \
@@ -550,6 +1360,31 @@
CLIP_SH2_0_255(res0_m, res1_m); \
PCKEV_B2_SB(res0_m, res0_m, res1_m, res1_m, dst0_m, dst1_m); \
ST4x4_UB(dst0_m, dst1_m, 0, 1, 0, 1, pdst, stride); \
-}
+} while (0)
+
+/* Description : Pack even byte elements, extract 0 & 2 index words from pair
+ * of results and store 4 words in destination memory as per
+ * stride
+ * Arguments : Inputs - in0, in1, in2, in3, pdst, stride
+ */
+#define PCKEV_ST4x4_UB(in0, in1, in2, in3, pdst, stride) do { \
+ v16i8 tmp0_m, tmp1_m; \
+ PCKEV_B2_SB(in1, in0, in3, in2, tmp0_m, tmp1_m); \
+ ST4x4_UB(tmp0_m, tmp1_m, 0, 2, 0, 2, pdst, stride); \
+} while (0)
+
+/* Description : average with rounding (in0 + in1 + 1) / 2.
+ * Arguments : Inputs - in0, in1, in2, in3,
+ * Outputs - out0, out1
+ * Return Type - as per RTYPE
+ * Details : Each unsigned byte element from 'in0' vector is added with
+ * each unsigned byte element from 'in1' vector. Then the average
+ * with rounding is calculated and written to 'out0'
+ */
+#define AVER_UB2(RTYPE, in0, in1, in2, in3, out0, out1) do { \
+ out0 = (RTYPE)__msa_aver_u_b((v16u8)in0, (v16u8)in1); \
+ out1 = (RTYPE)__msa_aver_u_b((v16u8)in2, (v16u8)in3); \
+} while (0)
+#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)
#endif /* WEBP_DSP_MSA_MACRO_H_ */
diff --git a/thirdparty/libwebp/dsp/neon.h b/thirdparty/libwebp/dsp/neon.h
index 0a06266848..3b548a6855 100644
--- a/thirdparty/libwebp/dsp/neon.h
+++ b/thirdparty/libwebp/dsp/neon.h
@@ -79,4 +79,22 @@ static WEBP_INLINE int32x4x4_t Transpose4x4(const int32x4x4_t rows) {
}
}
+#if 0 // Useful debug macro.
+#include <stdio.h>
+#define PRINT_REG(REG, SIZE) do { \
+ int i; \
+ printf("%s \t[%d]: 0x", #REG, SIZE); \
+ if (SIZE == 8) { \
+ uint8_t _tmp[8]; \
+ vst1_u8(_tmp, (REG)); \
+ for (i = 0; i < 8; ++i) printf("%.2x ", _tmp[i]); \
+ } else if (SIZE == 16) { \
+ uint16_t _tmp[4]; \
+ vst1_u16(_tmp, (REG)); \
+ for (i = 0; i < 4; ++i) printf("%.4x ", _tmp[i]); \
+ } \
+ printf("\n"); \
+} while (0)
+#endif
+
#endif // WEBP_DSP_NEON_H_
diff --git a/thirdparty/libwebp/dsp/rescaler.c b/thirdparty/libwebp/dsp/rescaler.c
index f5b07756cf..0f54502352 100644
--- a/thirdparty/libwebp/dsp/rescaler.c
+++ b/thirdparty/libwebp/dsp/rescaler.c
@@ -14,7 +14,7 @@
#include <assert.h>
#include "./dsp.h"
-#include "../utils/rescaler.h"
+#include "../utils/rescaler_utils.h"
//------------------------------------------------------------------------------
// Implementations of critical functions ImportRow / ExportRow
@@ -199,6 +199,7 @@ WebPRescalerExportRowFunc WebPRescalerExportRowShrink;
extern void WebPRescalerDspInitSSE2(void);
extern void WebPRescalerDspInitMIPS32(void);
extern void WebPRescalerDspInitMIPSdspR2(void);
+extern void WebPRescalerDspInitMSA(void);
extern void WebPRescalerDspInitNEON(void);
static volatile VP8CPUInfo rescaler_last_cpuinfo_used =
@@ -233,6 +234,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) {
WebPRescalerDspInitMIPSdspR2();
}
#endif
+#if defined(WEBP_USE_MSA)
+ if (VP8GetCPUInfo(kMSA)) {
+ WebPRescalerDspInitMSA();
+ }
+#endif
}
rescaler_last_cpuinfo_used = VP8GetCPUInfo;
}
diff --git a/thirdparty/libwebp/dsp/rescaler_mips32.c b/thirdparty/libwebp/dsp/rescaler_mips32.c
index ddaa391336..e09ad5d19f 100644
--- a/thirdparty/libwebp/dsp/rescaler_mips32.c
+++ b/thirdparty/libwebp/dsp/rescaler_mips32.c
@@ -16,7 +16,7 @@
#if defined(WEBP_USE_MIPS32)
#include <assert.h>
-#include "../utils/rescaler.h"
+#include "../utils/rescaler_utils.h"
//------------------------------------------------------------------------------
// Row import
diff --git a/thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c b/thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c
index b457d0a30a..2308d64544 100644
--- a/thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c
+++ b/thirdparty/libwebp/dsp/rescaler_mips_dsp_r2.c
@@ -16,7 +16,7 @@
#if defined(WEBP_USE_MIPS_DSP_R2)
#include <assert.h>
-#include "../utils/rescaler.h"
+#include "../utils/rescaler_utils.h"
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
diff --git a/thirdparty/libwebp/dsp/rescaler_msa.c b/thirdparty/libwebp/dsp/rescaler_msa.c
new file mode 100644
index 0000000000..2c10e55d8c
--- /dev/null
+++ b/thirdparty/libwebp/dsp/rescaler_msa.c
@@ -0,0 +1,444 @@
+// Copyright 2016 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.
+// -----------------------------------------------------------------------------
+//
+// MSA version of rescaling functions
+//
+// Author: Prashant Patil (prashant.patil@imgtec.com)
+
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MSA)
+
+#include <assert.h>
+
+#include "../utils/rescaler_utils.h"
+#include "./msa_macro.h"
+
+#define ROUNDER (WEBP_RESCALER_ONE >> 1)
+#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
+
+#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \
+ v4u32 tmp0, tmp1, tmp2, tmp3; \
+ v16u8 t0, t1, t2, t3, t4, t5; \
+ v2u64 out0, out1, out2, out3; \
+ ILVRL_W2_UW(zero, in0, tmp0, tmp1); \
+ ILVRL_W2_UW(zero, in1, tmp2, tmp3); \
+ DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \
+ DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3); \
+ SRAR_D4_UD(out0, out1, out2, out3, shift); \
+ PCKEV_B2_UB(out1, out0, out3, out2, t0, t1); \
+ ILVRL_W2_UW(zero, in2, tmp0, tmp1); \
+ ILVRL_W2_UW(zero, in3, tmp2, tmp3); \
+ DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \
+ DOTP_UW2_UD(tmp2, tmp3, scale, scale, out2, out3); \
+ SRAR_D4_UD(out0, out1, out2, out3, shift); \
+ PCKEV_B2_UB(out1, out0, out3, out2, t2, t3); \
+ PCKEV_B2_UB(t1, t0, t3, t2, t4, t5); \
+ dst = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4); \
+} while (0)
+
+#define CALC_MULT_FIX_4(in0, scale, shift, dst) do { \
+ v4u32 tmp0, tmp1; \
+ v16i8 t0, t1; \
+ v2u64 out0, out1; \
+ ILVRL_W2_UW(zero, in0, tmp0, tmp1); \
+ DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \
+ SRAR_D2_UD(out0, out1, shift); \
+ t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0); \
+ t1 = __msa_pckev_b(t0, t0); \
+ t0 = __msa_pckev_b(t1, t1); \
+ dst = __msa_copy_s_w((v4i32)t0, 0); \
+} while (0)
+
+#define CALC_MULT_FIX1_16(in0, in1, in2, in3, fyscale, shift, \
+ dst0, dst1, dst2, dst3) do { \
+ v4u32 tmp0, tmp1, tmp2, tmp3; \
+ v2u64 out0, out1, out2, out3; \
+ ILVRL_W2_UW(zero, in0, tmp0, tmp1); \
+ ILVRL_W2_UW(zero, in1, tmp2, tmp3); \
+ DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1); \
+ DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3); \
+ SRAR_D4_UD(out0, out1, out2, out3, shift); \
+ PCKEV_W2_UW(out1, out0, out3, out2, dst0, dst1); \
+ ILVRL_W2_UW(zero, in2, tmp0, tmp1); \
+ ILVRL_W2_UW(zero, in3, tmp2, tmp3); \
+ DOTP_UW2_UD(tmp0, tmp1, fyscale, fyscale, out0, out1); \
+ DOTP_UW2_UD(tmp2, tmp3, fyscale, fyscale, out2, out3); \
+ SRAR_D4_UD(out0, out1, out2, out3, shift); \
+ PCKEV_W2_UW(out1, out0, out3, out2, dst2, dst3); \
+} while (0)
+
+#define CALC_MULT_FIX1_4(in0, scale, shift, dst) do { \
+ v4u32 tmp0, tmp1; \
+ v2u64 out0, out1; \
+ ILVRL_W2_UW(zero, in0, tmp0, tmp1); \
+ DOTP_UW2_UD(tmp0, tmp1, scale, scale, out0, out1); \
+ SRAR_D2_UD(out0, out1, shift); \
+ dst = (v4u32)__msa_pckev_w((v4i32)out1, (v4i32)out0); \
+} while (0)
+
+#define CALC_MULT_FIX2_16(in0, in1, in2, in3, mult, scale, shift, \
+ dst0, dst1) do { \
+ v4u32 tmp0, tmp1, tmp2, tmp3; \
+ v2u64 out0, out1, out2, out3; \
+ ILVRL_W2_UW(in0, in2, tmp0, tmp1); \
+ ILVRL_W2_UW(in1, in3, tmp2, tmp3); \
+ DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1); \
+ DOTP_UW2_UD(tmp2, tmp3, mult, mult, out2, out3); \
+ SRAR_D4_UD(out0, out1, out2, out3, shift); \
+ DOTP_UW2_UD(out0, out1, scale, scale, out0, out1); \
+ DOTP_UW2_UD(out2, out3, scale, scale, out2, out3); \
+ SRAR_D4_UD(out0, out1, out2, out3, shift); \
+ PCKEV_B2_UB(out1, out0, out3, out2, dst0, dst1); \
+} while (0)
+
+#define CALC_MULT_FIX2_4(in0, in1, mult, scale, shift, dst) do { \
+ v4u32 tmp0, tmp1; \
+ v2u64 out0, out1; \
+ v16i8 t0, t1; \
+ ILVRL_W2_UW(in0, in1, tmp0, tmp1); \
+ DOTP_UW2_UD(tmp0, tmp1, mult, mult, out0, out1); \
+ SRAR_D2_UD(out0, out1, shift); \
+ DOTP_UW2_UD(out0, out1, scale, scale, out0, out1); \
+ SRAR_D2_UD(out0, out1, shift); \
+ t0 = __msa_pckev_b((v16i8)out1, (v16i8)out0); \
+ t1 = __msa_pckev_b(t0, t0); \
+ t0 = __msa_pckev_b(t1, t1); \
+ dst = __msa_copy_s_w((v4i32)t0, 0); \
+} while (0)
+
+static WEBP_INLINE void ExportRowExpand_0(const uint32_t* frow, uint8_t* dst,
+ int length,
+ WebPRescaler* const wrk) {
+ const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale);
+ const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
+ const v4i32 zero = { 0 };
+
+ while (length >= 16) {
+ v4u32 src0, src1, src2, src3;
+ v16u8 out;
+ LD_UW4(frow, 4, src0, src1, src2, src3);
+ CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, out);
+ ST_UB(out, dst);
+ length -= 16;
+ frow += 16;
+ dst += 16;
+ }
+ if (length > 0) {
+ int x_out;
+ if (length >= 12) {
+ uint32_t val0_m, val1_m, val2_m;
+ v4u32 src0, src1, src2;
+ LD_UW3(frow, 4, src0, src1, src2);
+ CALC_MULT_FIX_4(src0, scale, shift, val0_m);
+ CALC_MULT_FIX_4(src1, scale, shift, val1_m);
+ CALC_MULT_FIX_4(src2, scale, shift, val2_m);
+ SW3(val0_m, val1_m, val2_m, dst, 4);
+ length -= 12;
+ frow += 12;
+ dst += 12;
+ } else if (length >= 8) {
+ uint32_t val0_m, val1_m;
+ v4u32 src0, src1;
+ LD_UW2(frow, 4, src0, src1);
+ CALC_MULT_FIX_4(src0, scale, shift, val0_m);
+ CALC_MULT_FIX_4(src1, scale, shift, val1_m);
+ SW2(val0_m, val1_m, dst, 4);
+ length -= 8;
+ frow += 8;
+ dst += 8;
+ } else if (length >= 4) {
+ uint32_t val0_m;
+ const v4u32 src0 = LD_UW(frow);
+ CALC_MULT_FIX_4(src0, scale, shift, val0_m);
+ SW(val0_m, dst);
+ length -= 4;
+ frow += 4;
+ dst += 4;
+ }
+ for (x_out = 0; x_out < length; ++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;
+ }
+ }
+}
+
+static WEBP_INLINE void ExportRowExpand_1(const uint32_t* frow, uint32_t* irow,
+ uint8_t* dst, int length,
+ WebPRescaler* const wrk) {
+ const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
+ const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
+ const v4i32 B1 = __msa_fill_w(B);
+ const v4i32 A1 = __msa_fill_w(A);
+ const v4i32 AB = __msa_ilvr_w(A1, B1);
+ const v4u32 scale = (v4u32)__msa_fill_w(wrk->fy_scale);
+ const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
+
+ while (length >= 16) {
+ v4u32 frow0, frow1, frow2, frow3, irow0, irow1, irow2, irow3;
+ v16u8 t0, t1, t2, t3, t4, t5;
+ LD_UW4(frow, 4, frow0, frow1, frow2, frow3);
+ LD_UW4(irow, 4, irow0, irow1, irow2, irow3);
+ CALC_MULT_FIX2_16(frow0, frow1, irow0, irow1, AB, scale, shift, t0, t1);
+ CALC_MULT_FIX2_16(frow2, frow3, irow2, irow3, AB, scale, shift, t2, t3);
+ PCKEV_B2_UB(t1, t0, t3, t2, t4, t5);
+ t0 = (v16u8)__msa_pckev_b((v16i8)t5, (v16i8)t4);
+ ST_UB(t0, dst);
+ frow += 16;
+ irow += 16;
+ dst += 16;
+ length -= 16;
+ }
+ if (length > 0) {
+ int x_out;
+ if (length >= 12) {
+ uint32_t val0_m, val1_m, val2_m;
+ v4u32 frow0, frow1, frow2, irow0, irow1, irow2;
+ LD_UW3(frow, 4, frow0, frow1, frow2);
+ LD_UW3(irow, 4, irow0, irow1, irow2);
+ CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m);
+ CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m);
+ CALC_MULT_FIX2_4(frow2, irow2, AB, scale, shift, val2_m);
+ SW3(val0_m, val1_m, val2_m, dst, 4);
+ frow += 12;
+ irow += 12;
+ dst += 12;
+ length -= 12;
+ } else if (length >= 8) {
+ uint32_t val0_m, val1_m;
+ v4u32 frow0, frow1, irow0, irow1;
+ LD_UW2(frow, 4, frow0, frow1);
+ LD_UW2(irow, 4, irow0, irow1);
+ CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m);
+ CALC_MULT_FIX2_4(frow1, irow1, AB, scale, shift, val1_m);
+ SW2(val0_m, val1_m, dst, 4);
+ frow += 4;
+ irow += 4;
+ dst += 4;
+ length -= 4;
+ } else if (length >= 4) {
+ uint32_t val0_m;
+ const v4u32 frow0 = LD_UW(frow + 0);
+ const v4u32 irow0 = LD_UW(irow + 0);
+ CALC_MULT_FIX2_4(frow0, irow0, AB, scale, shift, val0_m);
+ SW(val0_m, dst);
+ frow += 4;
+ irow += 4;
+ dst += 4;
+ length -= 4;
+ }
+ for (x_out = 0; x_out < length; ++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 RescalerExportRowExpand(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;
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(wrk->y_expand);
+ assert(wrk->y_sub != 0);
+ if (wrk->y_accum == 0) {
+ ExportRowExpand_0(frow, dst, x_out_max, wrk);
+ } else {
+ ExportRowExpand_1(frow, irow, dst, x_out_max, wrk);
+ }
+}
+
+static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
+ uint8_t* dst, int length,
+ const uint32_t yscale,
+ WebPRescaler* const wrk) {
+ const v4u32 y_scale = (v4u32)__msa_fill_w(yscale);
+ const v4u32 fxyscale = (v4u32)__msa_fill_w(wrk->fxy_scale);
+ const v4u32 shiftval = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
+ const v4i32 zero = { 0 };
+
+ while (length >= 16) {
+ v4u32 src0, src1, src2, src3, frac0, frac1, frac2, frac3;
+ v16u8 out;
+ LD_UW4(frow, 4, src0, src1, src2, src3);
+ CALC_MULT_FIX1_16(src0, src1, src2, src3, y_scale, shiftval,
+ frac0, frac1, frac2, frac3);
+ LD_UW4(irow, 4, src0, src1, src2, src3);
+ SUB4(src0, frac0, src1, frac1, src2, frac2, src3, frac3,
+ src0, src1, src2, src3);
+ CALC_MULT_FIX_16(src0, src1, src2, src3, fxyscale, shiftval, out);
+ ST_UB(out, dst);
+ ST_UW4(frac0, frac1, frac2, frac3, irow, 4);
+ frow += 16;
+ irow += 16;
+ dst += 16;
+ length -= 16;
+ }
+ if (length > 0) {
+ int x_out;
+ if (length >= 12) {
+ uint32_t val0_m, val1_m, val2_m;
+ v4u32 src0, src1, src2, frac0, frac1, frac2;
+ LD_UW3(frow, 4, src0, src1, src2);
+ CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0);
+ CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1);
+ CALC_MULT_FIX1_4(src2, y_scale, shiftval, frac2);
+ LD_UW3(irow, 4, src0, src1, src2);
+ SUB3(src0, frac0, src1, frac1, src2, frac2, src0, src1, src2);
+ CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m);
+ CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m);
+ CALC_MULT_FIX_4(src2, fxyscale, shiftval, val2_m);
+ SW3(val0_m, val1_m, val2_m, dst, 4);
+ ST_UW3(frac0, frac1, frac2, irow, 4);
+ frow += 12;
+ irow += 12;
+ dst += 12;
+ length -= 12;
+ } else if (length >= 8) {
+ uint32_t val0_m, val1_m;
+ v4u32 src0, src1, frac0, frac1;
+ LD_UW2(frow, 4, src0, src1);
+ CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0);
+ CALC_MULT_FIX1_4(src1, y_scale, shiftval, frac1);
+ LD_UW2(irow, 4, src0, src1);
+ SUB2(src0, frac0, src1, frac1, src0, src1);
+ CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m);
+ CALC_MULT_FIX_4(src1, fxyscale, shiftval, val1_m);
+ SW2(val0_m, val1_m, dst, 4);
+ ST_UW2(frac0, frac1, irow, 4);
+ frow += 8;
+ irow += 8;
+ dst += 8;
+ length -= 8;
+ } else if (length >= 4) {
+ uint32_t val0_m;
+ v4u32 frac0;
+ v4u32 src0 = LD_UW(frow);
+ CALC_MULT_FIX1_4(src0, y_scale, shiftval, frac0);
+ src0 = LD_UW(irow);
+ src0 = src0 - frac0;
+ CALC_MULT_FIX_4(src0, fxyscale, shiftval, val0_m);
+ SW(val0_m, dst);
+ ST_UW(frac0, irow);
+ frow += 4;
+ irow += 4;
+ dst += 4;
+ length -= 4;
+ }
+ for (x_out = 0; x_out < length; ++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;
+ }
+ }
+}
+
+static WEBP_INLINE void ExportRowShrink_1(uint32_t* irow, uint8_t* dst,
+ int length,
+ WebPRescaler* const wrk) {
+ const v4u32 scale = (v4u32)__msa_fill_w(wrk->fxy_scale);
+ const v4u32 shift = (v4u32)__msa_fill_w(WEBP_RESCALER_RFIX);
+ const v4i32 zero = { 0 };
+
+ while (length >= 16) {
+ v4u32 src0, src1, src2, src3;
+ v16u8 dst0;
+ LD_UW4(irow, 4, src0, src1, src2, src3);
+ CALC_MULT_FIX_16(src0, src1, src2, src3, scale, shift, dst0);
+ ST_UB(dst0, dst);
+ ST_SW4(zero, zero, zero, zero, irow, 4);
+ length -= 16;
+ irow += 16;
+ dst += 16;
+ }
+ if (length > 0) {
+ int x_out;
+ if (length >= 12) {
+ uint32_t val0_m, val1_m, val2_m;
+ v4u32 src0, src1, src2;
+ LD_UW3(irow, 4, src0, src1, src2);
+ CALC_MULT_FIX_4(src0, scale, shift, val0_m);
+ CALC_MULT_FIX_4(src1, scale, shift, val1_m);
+ CALC_MULT_FIX_4(src2, scale, shift, val2_m);
+ SW3(val0_m, val1_m, val2_m, dst, 4);
+ ST_SW3(zero, zero, zero, irow, 4);
+ length -= 12;
+ irow += 12;
+ dst += 12;
+ } else if (length >= 8) {
+ uint32_t val0_m, val1_m;
+ v4u32 src0, src1;
+ LD_UW2(irow, 4, src0, src1);
+ CALC_MULT_FIX_4(src0, scale, shift, val0_m);
+ CALC_MULT_FIX_4(src1, scale, shift, val1_m);
+ SW2(val0_m, val1_m, dst, 4);
+ ST_SW2(zero, zero, irow, 4);
+ length -= 8;
+ irow += 8;
+ dst += 8;
+ } else if (length >= 4) {
+ uint32_t val0_m;
+ const v4u32 src0 = LD_UW(irow + 0);
+ CALC_MULT_FIX_4(src0, scale, shift, val0_m);
+ SW(val0_m, dst);
+ ST_SW(zero, irow);
+ length -= 4;
+ irow += 4;
+ dst += 4;
+ }
+ for (x_out = 0; x_out < length; ++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;
+ }
+ }
+}
+
+static void RescalerExportRowShrink(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;
+ const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
+ assert(!WebPRescalerOutputDone(wrk));
+ assert(wrk->y_accum <= 0);
+ assert(!wrk->y_expand);
+ if (yscale) {
+ ExportRowShrink_0(frow, irow, dst, x_out_max, yscale, wrk);
+ } else {
+ ExportRowShrink_1(irow, dst, x_out_max, wrk);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern void WebPRescalerDspInitMSA(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) {
+ WebPRescalerExportRowExpand = RescalerExportRowExpand;
+ WebPRescalerExportRowShrink = RescalerExportRowShrink;
+}
+
+#else // !WEBP_USE_MSA
+
+WEBP_DSP_INIT_STUB(WebPRescalerDspInitMSA)
+
+#endif // WEBP_USE_MSA
diff --git a/thirdparty/libwebp/dsp/rescaler_neon.c b/thirdparty/libwebp/dsp/rescaler_neon.c
index 16fd450ea3..b2dd8f30cc 100644
--- a/thirdparty/libwebp/dsp/rescaler_neon.c
+++ b/thirdparty/libwebp/dsp/rescaler_neon.c
@@ -18,7 +18,7 @@
#include <arm_neon.h>
#include <assert.h>
#include "./neon.h"
-#include "../utils/rescaler.h"
+#include "../utils/rescaler_utils.h"
#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
diff --git a/thirdparty/libwebp/dsp/rescaler_sse2.c b/thirdparty/libwebp/dsp/rescaler_sse2.c
index 5b9702817c..8271c22e05 100644
--- a/thirdparty/libwebp/dsp/rescaler_sse2.c
+++ b/thirdparty/libwebp/dsp/rescaler_sse2.c
@@ -17,7 +17,7 @@
#include <emmintrin.h>
#include <assert.h>
-#include "../utils/rescaler.h"
+#include "../utils/rescaler_utils.h"
#include "../utils/utils.h"
//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/dsp/upsampling.c b/thirdparty/libwebp/dsp/upsampling.c
index 651274fcee..265e722c10 100644
--- a/thirdparty/libwebp/dsp/upsampling.c
+++ b/thirdparty/libwebp/dsp/upsampling.c
@@ -215,6 +215,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) {
extern void WebPInitUpsamplersSSE2(void);
extern void WebPInitUpsamplersNEON(void);
extern void WebPInitUpsamplersMIPSdspR2(void);
+extern void WebPInitUpsamplersMSA(void);
static volatile VP8CPUInfo upsampling_last_cpuinfo_used2 =
(VP8CPUInfo)&upsampling_last_cpuinfo_used2;
@@ -252,6 +253,11 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) {
WebPInitUpsamplersMIPSdspR2();
}
#endif
+#if defined(WEBP_USE_MSA)
+ if (VP8GetCPUInfo(kMSA)) {
+ WebPInitUpsamplersMSA();
+ }
+#endif
}
#endif // FANCY_UPSAMPLING
upsampling_last_cpuinfo_used2 = VP8GetCPUInfo;
diff --git a/thirdparty/libwebp/dsp/upsampling_msa.c b/thirdparty/libwebp/dsp/upsampling_msa.c
new file mode 100644
index 0000000000..f24926fa94
--- /dev/null
+++ b/thirdparty/libwebp/dsp/upsampling_msa.c
@@ -0,0 +1,678 @@
+// Copyright 2016 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.
+// -----------------------------------------------------------------------------
+//
+// MSA version of YUV to RGB upsampling functions.
+//
+// Author: Prashant Patil (prashant.patil@imgtec.com)
+
+#include <string.h>
+#include "./dsp.h"
+
+#if defined(WEBP_USE_MSA)
+
+#include "./msa_macro.h"
+#include "./yuv.h"
+
+#ifdef FANCY_UPSAMPLING
+
+#define ILVR_UW2(in, out0, out1) do { \
+ const v8i16 t0 = (v8i16)__msa_ilvr_b((v16i8)zero, (v16i8)in); \
+ out0 = (v4u32)__msa_ilvr_h((v8i16)zero, t0); \
+ out1 = (v4u32)__msa_ilvl_h((v8i16)zero, t0); \
+} while (0)
+
+#define ILVRL_UW4(in, out0, out1, out2, out3) do { \
+ v16u8 t0, t1; \
+ ILVRL_B2_UB(zero, in, t0, t1); \
+ ILVRL_H2_UW(zero, t0, out0, out1); \
+ ILVRL_H2_UW(zero, t1, out2, out3); \
+} while (0)
+
+#define MULTHI_16(in0, in1, in2, in3, cnst, out0, out1) do { \
+ const v4i32 const0 = (v4i32)__msa_fill_w(cnst * 256); \
+ v4u32 temp0, temp1, temp2, temp3; \
+ MUL4(in0, const0, in1, const0, in2, const0, in3, const0, \
+ temp0, temp1, temp2, temp3); \
+ PCKOD_H2_UH(temp1, temp0, temp3, temp2, out0, out1); \
+} while (0)
+
+#define MULTHI_8(in0, in1, cnst, out0) do { \
+ const v4i32 const0 = (v4i32)__msa_fill_w(cnst * 256); \
+ v4u32 temp0, temp1; \
+ MUL2(in0, const0, in1, const0, temp0, temp1); \
+ out0 = (v8u16)__msa_pckod_h((v8i16)temp1, (v8i16)temp0); \
+} while (0)
+
+#define CALC_R16(y0, y1, v0, v1, dst) do { \
+ const v8i16 const_a = (v8i16)__msa_fill_h(14234); \
+ const v8i16 a0 = __msa_adds_s_h((v8i16)y0, (v8i16)v0); \
+ const v8i16 a1 = __msa_adds_s_h((v8i16)y1, (v8i16)v1); \
+ v8i16 b0 = __msa_subs_s_h(a0, const_a); \
+ v8i16 b1 = __msa_subs_s_h(a1, const_a); \
+ SRAI_H2_SH(b0, b1, 6); \
+ CLIP_SH2_0_255(b0, b1); \
+ dst = (v16u8)__msa_pckev_b((v16i8)b1, (v16i8)b0); \
+} while (0)
+
+#define CALC_R8(y0, v0, dst) do { \
+ const v8i16 const_a = (v8i16)__msa_fill_h(14234); \
+ const v8i16 a0 = __msa_adds_s_h((v8i16)y0, (v8i16)v0); \
+ v8i16 b0 = __msa_subs_s_h(a0, const_a); \
+ b0 = SRAI_H(b0, 6); \
+ CLIP_SH_0_255(b0); \
+ dst = (v16u8)__msa_pckev_b((v16i8)b0, (v16i8)b0); \
+} while (0)
+
+#define CALC_G16(y0, y1, u0, u1, v0, v1, dst) do { \
+ const v8i16 const_a = (v8i16)__msa_fill_h(8708); \
+ v8i16 a0 = __msa_subs_s_h((v8i16)y0, (v8i16)u0); \
+ v8i16 a1 = __msa_subs_s_h((v8i16)y1, (v8i16)u1); \
+ const v8i16 b0 = __msa_subs_s_h(a0, (v8i16)v0); \
+ const v8i16 b1 = __msa_subs_s_h(a1, (v8i16)v1); \
+ a0 = __msa_adds_s_h(b0, const_a); \
+ a1 = __msa_adds_s_h(b1, const_a); \
+ SRAI_H2_SH(a0, a1, 6); \
+ CLIP_SH2_0_255(a0, a1); \
+ dst = (v16u8)__msa_pckev_b((v16i8)a1, (v16i8)a0); \
+} while (0)
+
+#define CALC_G8(y0, u0, v0, dst) do { \
+ const v8i16 const_a = (v8i16)__msa_fill_h(8708); \
+ v8i16 a0 = __msa_subs_s_h((v8i16)y0, (v8i16)u0); \
+ const v8i16 b0 = __msa_subs_s_h(a0, (v8i16)v0); \
+ a0 = __msa_adds_s_h(b0, const_a); \
+ a0 = SRAI_H(a0, 6); \
+ CLIP_SH_0_255(a0); \
+ dst = (v16u8)__msa_pckev_b((v16i8)a0, (v16i8)a0); \
+} while (0)
+
+#define CALC_B16(y0, y1, u0, u1, dst) do { \
+ const v8u16 const_a = (v8u16)__msa_fill_h(17685); \
+ const v8u16 a0 = __msa_adds_u_h((v8u16)y0, u0); \
+ const v8u16 a1 = __msa_adds_u_h((v8u16)y1, u1); \
+ v8u16 b0 = __msa_subs_u_h(a0, const_a); \
+ v8u16 b1 = __msa_subs_u_h(a1, const_a); \
+ SRAI_H2_UH(b0, b1, 6); \
+ CLIP_UH2_0_255(b0, b1); \
+ dst = (v16u8)__msa_pckev_b((v16i8)b1, (v16i8)b0); \
+} while (0)
+
+#define CALC_B8(y0, u0, dst) do { \
+ const v8u16 const_a = (v8u16)__msa_fill_h(17685); \
+ const v8u16 a0 = __msa_adds_u_h((v8u16)y0, u0); \
+ v8u16 b0 = __msa_subs_u_h(a0, const_a); \
+ b0 = SRAI_H(b0, 6); \
+ CLIP_UH_0_255(b0); \
+ dst = (v16u8)__msa_pckev_b((v16i8)b0, (v16i8)b0); \
+} while (0)
+
+#define CALC_RGB16(y, u, v, R, G, B) do { \
+ const v16u8 zero = { 0 }; \
+ v8u16 y0, y1, u0, u1, v0, v1; \
+ v4u32 p0, p1, p2, p3; \
+ const v16u8 in_y = LD_UB(y); \
+ const v16u8 in_u = LD_UB(u); \
+ const v16u8 in_v = LD_UB(v); \
+ ILVRL_UW4(in_y, p0, p1, p2, p3); \
+ MULTHI_16(p0, p1, p2, p3, 19077, y0, y1); \
+ ILVRL_UW4(in_v, p0, p1, p2, p3); \
+ MULTHI_16(p0, p1, p2, p3, 26149, v0, v1); \
+ CALC_R16(y0, y1, v0, v1, R); \
+ MULTHI_16(p0, p1, p2, p3, 13320, v0, v1); \
+ ILVRL_UW4(in_u, p0, p1, p2, p3); \
+ MULTHI_16(p0, p1, p2, p3, 6419, u0, u1); \
+ CALC_G16(y0, y1, u0, u1, v0, v1, G); \
+ MULTHI_16(p0, p1, p2, p3, 33050, u0, u1); \
+ CALC_B16(y0, y1, u0, u1, B); \
+} while (0)
+
+#define CALC_RGB8(y, u, v, R, G, B) do { \
+ const v16u8 zero = { 0 }; \
+ v8u16 y0, u0, v0; \
+ v4u32 p0, p1; \
+ const v16u8 in_y = LD_UB(y); \
+ const v16u8 in_u = LD_UB(u); \
+ const v16u8 in_v = LD_UB(v); \
+ ILVR_UW2(in_y, p0, p1); \
+ MULTHI_8(p0, p1, 19077, y0); \
+ ILVR_UW2(in_v, p0, p1); \
+ MULTHI_8(p0, p1, 26149, v0); \
+ CALC_R8(y0, v0, R); \
+ MULTHI_8(p0, p1, 13320, v0); \
+ ILVR_UW2(in_u, p0, p1); \
+ MULTHI_8(p0, p1, 6419, u0); \
+ CALC_G8(y0, u0, v0, G); \
+ MULTHI_8(p0, p1, 33050, u0); \
+ CALC_B8(y0, u0, B); \
+} while (0)
+
+#define STORE16_3(a0, a1, a2, dst) do { \
+ const v16u8 mask0 = { 0, 1, 16, 2, 3, 17, 4, 5, 18, 6, 7, 19, \
+ 8, 9, 20, 10 }; \
+ const v16u8 mask1 = { 0, 21, 1, 2, 22, 3, 4, 23, 5, 6, 24, 7, \
+ 8, 25, 9, 10 }; \
+ const v16u8 mask2 = { 26, 0, 1, 27, 2, 3, 28, 4, 5, 29, 6, 7, \
+ 30, 8, 9, 31 }; \
+ v16u8 out0, out1, out2, tmp0, tmp1, tmp2; \
+ ILVRL_B2_UB(a1, a0, tmp0, tmp1); \
+ out0 = VSHF_UB(tmp0, a2, mask0); \
+ tmp2 = SLDI_UB(tmp1, tmp0, 11); \
+ out1 = VSHF_UB(tmp2, a2, mask1); \
+ tmp2 = SLDI_UB(tmp1, tmp1, 6); \
+ out2 = VSHF_UB(tmp2, a2, mask2); \
+ ST_UB(out0, dst + 0); \
+ ST_UB(out1, dst + 16); \
+ ST_UB(out2, dst + 32); \
+} while (0)
+
+#define STORE8_3(a0, a1, a2, dst) do { \
+ int64_t out_m; \
+ const v16u8 mask0 = { 0, 1, 16, 2, 3, 17, 4, 5, 18, 6, 7, 19, \
+ 8, 9, 20, 10 }; \
+ const v16u8 mask1 = { 11, 21, 12, 13, 22, 14, 15, 23, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }; \
+ const v16u8 tmp0 = (v16u8)__msa_ilvr_b((v16i8)a1, (v16i8)a0); \
+ v16u8 out0, out1; \
+ VSHF_B2_UB(tmp0, a2, tmp0, a2, mask0, mask1, out0, out1); \
+ ST_UB(out0, dst); \
+ out_m = __msa_copy_s_d((v2i64)out1, 0); \
+ SD(out_m, dst + 16); \
+} while (0)
+
+#define STORE16_4(a0, a1, a2, a3, dst) do { \
+ v16u8 tmp0, tmp1, tmp2, tmp3; \
+ v16u8 out0, out1, out2, out3; \
+ ILVRL_B2_UB(a1, a0, tmp0, tmp1); \
+ ILVRL_B2_UB(a3, a2, tmp2, tmp3); \
+ ILVRL_H2_UB(tmp2, tmp0, out0, out1); \
+ ILVRL_H2_UB(tmp3, tmp1, out2, out3); \
+ ST_UB(out0, dst + 0); \
+ ST_UB(out1, dst + 16); \
+ ST_UB(out2, dst + 32); \
+ ST_UB(out3, dst + 48); \
+} while (0)
+
+#define STORE8_4(a0, a1, a2, a3, dst) do { \
+ v16u8 tmp0, tmp1, tmp2, tmp3; \
+ ILVR_B2_UB(a1, a0, a3, a2, tmp0, tmp1); \
+ ILVRL_H2_UB(tmp1, tmp0, tmp2, tmp3); \
+ ST_UB(tmp2, dst + 0); \
+ ST_UB(tmp3, dst + 16); \
+} while (0)
+
+#define STORE2_16(a0, a1, dst) do { \
+ v16u8 out0, out1; \
+ ILVRL_B2_UB(a1, a0, out0, out1); \
+ ST_UB(out0, dst + 0); \
+ ST_UB(out1, dst + 16); \
+} while (0)
+
+#define STORE2_8(a0, a1, dst) do { \
+ const v16u8 out0 = (v16u8)__msa_ilvr_b((v16i8)a1, (v16i8)a0); \
+ ST_UB(out0, dst); \
+} while (0)
+
+#define CALC_RGBA4444(y, u, v, out0, out1, N, dst) do { \
+ CALC_RGB##N(y, u, v, R, G, B); \
+ tmp0 = ANDI_B(R, 0xf0); \
+ tmp1 = SRAI_B(G, 4); \
+ RG = tmp0 | tmp1; \
+ tmp0 = ANDI_B(B, 0xf0); \
+ BA = ORI_B(tmp0, 0x0f); \
+ STORE2_##N(out0, out1, dst); \
+} while (0)
+
+#define CALC_RGB565(y, u, v, out0, out1, N, dst) do { \
+ CALC_RGB##N(y, u, v, R, G, B); \
+ tmp0 = ANDI_B(R, 0xf8); \
+ tmp1 = SRAI_B(G, 5); \
+ RG = tmp0 | tmp1; \
+ tmp0 = SLLI_B(G, 3); \
+ tmp1 = ANDI_B(tmp0, 0xe0); \
+ tmp0 = SRAI_B(B, 3); \
+ GB = tmp0 | tmp1; \
+ STORE2_##N(out0, out1, dst); \
+} while (0)
+
+static WEBP_INLINE int Clip8(int v) {
+ return v < 0 ? 0 : v > 255 ? 255 : v;
+}
+
+static void YuvToRgb(int y, int u, int v, uint8_t* const rgb) {
+ const int y1 = MultHi(y, 19077);
+ const int r1 = y1 + MultHi(v, 26149) - 14234;
+ const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708;
+ const int b1 = y1 + MultHi(u, 33050) - 17685;
+ rgb[0] = Clip8(r1 >> 6);
+ rgb[1] = Clip8(g1 >> 6);
+ rgb[2] = Clip8(b1 >> 6);
+}
+
+static void YuvToBgr(int y, int u, int v, uint8_t* const bgr) {
+ const int y1 = MultHi(y, 19077);
+ const int r1 = y1 + MultHi(v, 26149) - 14234;
+ const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708;
+ const int b1 = y1 + MultHi(u, 33050) - 17685;
+ bgr[0] = Clip8(b1 >> 6);
+ bgr[1] = Clip8(g1 >> 6);
+ bgr[2] = Clip8(r1 >> 6);
+}
+
+static void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) {
+ const int y1 = MultHi(y, 19077);
+ const int r1 = y1 + MultHi(v, 26149) - 14234;
+ const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708;
+ const int b1 = y1 + MultHi(u, 33050) - 17685;
+ const int r = Clip8(r1 >> 6);
+ const int g = Clip8(g1 >> 6);
+ const int b = Clip8(b1 >> 6);
+ 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 void YuvToRgba4444(int y, int u, int v, uint8_t* const argb) {
+ const int y1 = MultHi(y, 19077);
+ const int r1 = y1 + MultHi(v, 26149) - 14234;
+ const int g1 = y1 - MultHi(u, 6419) - MultHi(v, 13320) + 8708;
+ const int b1 = y1 + MultHi(u, 33050) - 17685;
+ const int r = Clip8(r1 >> 6);
+ const int g = Clip8(g1 >> 6);
+ const int b = Clip8(b1 >> 6);
+ 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
+}
+
+static void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, uint8_t* const argb) {
+ argb[0] = 0xff;
+ YuvToRgb(y, u, v, argb + 1);
+}
+
+static void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) {
+ YuvToBgr(y, u, v, bgra);
+ bgra[3] = 0xff;
+}
+
+static void YuvToRgba(uint8_t y, uint8_t u, uint8_t v, uint8_t* const rgba) {
+ YuvToRgb(y, u, v, rgba);
+ rgba[3] = 0xff;
+}
+
+static void YuvToRgbLine(const uint8_t* y, const uint8_t* u,
+ const uint8_t* v, uint8_t* dst, int length) {
+ v16u8 R, G, B;
+ while (length >= 16) {
+ CALC_RGB16(y, u, v, R, G, B);
+ STORE16_3(R, G, B, dst);
+ y += 16;
+ u += 16;
+ v += 16;
+ dst += 16 * 3;
+ length -= 16;
+ }
+ if (length > 8) {
+ uint8_t temp[3 * 16] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB16(temp, u, v, R, G, B);
+ STORE16_3(R, G, B, temp);
+ memcpy(dst, temp, length * 3 * sizeof(*dst));
+ } else if (length > 0) {
+ uint8_t temp[3 * 8] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB8(temp, u, v, R, G, B);
+ STORE8_3(R, G, B, temp);
+ memcpy(dst, temp, length * 3 * sizeof(*dst));
+ }
+}
+
+static void YuvToBgrLine(const uint8_t* y, const uint8_t* u,
+ const uint8_t* v, uint8_t* dst, int length) {
+ v16u8 R, G, B;
+ while (length >= 16) {
+ CALC_RGB16(y, u, v, R, G, B);
+ STORE16_3(B, G, R, dst);
+ y += 16;
+ u += 16;
+ v += 16;
+ dst += 16 * 3;
+ length -= 16;
+ }
+ if (length > 8) {
+ uint8_t temp[3 * 16] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB16(temp, u, v, R, G, B);
+ STORE16_3(B, G, R, temp);
+ memcpy(dst, temp, length * 3 * sizeof(*dst));
+ } else if (length > 0) {
+ uint8_t temp[3 * 8] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB8(temp, u, v, R, G, B);
+ STORE8_3(B, G, R, temp);
+ memcpy(dst, temp, length * 3 * sizeof(*dst));
+ }
+}
+
+static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u,
+ const uint8_t* v, uint8_t* dst, int length) {
+ v16u8 R, G, B;
+ const v16u8 A = (v16u8)__msa_ldi_b(0xff);
+ while (length >= 16) {
+ CALC_RGB16(y, u, v, R, G, B);
+ STORE16_4(R, G, B, A, dst);
+ y += 16;
+ u += 16;
+ v += 16;
+ dst += 16 * 4;
+ length -= 16;
+ }
+ if (length > 8) {
+ uint8_t temp[4 * 16] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB16(&temp[0], u, v, R, G, B);
+ STORE16_4(R, G, B, A, temp);
+ memcpy(dst, temp, length * 4 * sizeof(*dst));
+ } else if (length > 0) {
+ uint8_t temp[4 * 8] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB8(temp, u, v, R, G, B);
+ STORE8_4(R, G, B, A, temp);
+ memcpy(dst, temp, length * 4 * sizeof(*dst));
+ }
+}
+
+static void YuvToBgraLine(const uint8_t* y, const uint8_t* u,
+ const uint8_t* v, uint8_t* dst, int length) {
+ v16u8 R, G, B;
+ const v16u8 A = (v16u8)__msa_ldi_b(0xff);
+ while (length >= 16) {
+ CALC_RGB16(y, u, v, R, G, B);
+ STORE16_4(B, G, R, A, dst);
+ y += 16;
+ u += 16;
+ v += 16;
+ dst += 16 * 4;
+ length -= 16;
+ }
+ if (length > 8) {
+ uint8_t temp[4 * 16] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB16(temp, u, v, R, G, B);
+ STORE16_4(B, G, R, A, temp);
+ memcpy(dst, temp, length * 4 * sizeof(*dst));
+ } else if (length > 0) {
+ uint8_t temp[4 * 8] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB8(temp, u, v, R, G, B);
+ STORE8_4(B, G, R, A, temp);
+ memcpy(dst, temp, length * 4 * sizeof(*dst));
+ }
+}
+
+static void YuvToArgbLine(const uint8_t* y, const uint8_t* u,
+ const uint8_t* v, uint8_t* dst, int length) {
+ v16u8 R, G, B;
+ const v16u8 A = (v16u8)__msa_ldi_b(0xff);
+ while (length >= 16) {
+ CALC_RGB16(y, u, v, R, G, B);
+ STORE16_4(A, R, G, B, dst);
+ y += 16;
+ u += 16;
+ v += 16;
+ dst += 16 * 4;
+ length -= 16;
+ }
+ if (length > 8) {
+ uint8_t temp[4 * 16] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB16(temp, u, v, R, G, B);
+ STORE16_4(A, R, G, B, temp);
+ memcpy(dst, temp, length * 4 * sizeof(*dst));
+ } else if (length > 0) {
+ uint8_t temp[4 * 8] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+ CALC_RGB8(temp, u, v, R, G, B);
+ STORE8_4(A, R, G, B, temp);
+ memcpy(dst, temp, length * 4 * sizeof(*dst));
+ }
+}
+
+static void YuvToRgba4444Line(const uint8_t* y, const uint8_t* u,
+ const uint8_t* v, uint8_t* dst, int length) {
+ v16u8 R, G, B, RG, BA, tmp0, tmp1;
+ while (length >= 16) {
+ #ifdef WEBP_SWAP_16BIT_CSP
+ CALC_RGBA4444(y, u, v, BA, RG, 16, dst);
+ #else
+ CALC_RGBA4444(y, u, v, RG, BA, 16, dst);
+ #endif
+ y += 16;
+ u += 16;
+ v += 16;
+ dst += 16 * 2;
+ length -= 16;
+ }
+ if (length > 8) {
+ uint8_t temp[2 * 16] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+#ifdef WEBP_SWAP_16BIT_CSP
+ CALC_RGBA4444(temp, u, v, BA, RG, 16, temp);
+#else
+ CALC_RGBA4444(temp, u, v, RG, BA, 16, temp);
+#endif
+ memcpy(dst, temp, length * 2 * sizeof(*dst));
+ } else if (length > 0) {
+ uint8_t temp[2 * 8] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+#ifdef WEBP_SWAP_16BIT_CSP
+ CALC_RGBA4444(temp, u, v, BA, RG, 8, temp);
+#else
+ CALC_RGBA4444(temp, u, v, RG, BA, 8, temp);
+#endif
+ memcpy(dst, temp, length * 2 * sizeof(*dst));
+ }
+}
+
+static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u,
+ const uint8_t* v, uint8_t* dst, int length) {
+ v16u8 R, G, B, RG, GB, tmp0, tmp1;
+ while (length >= 16) {
+ #ifdef WEBP_SWAP_16BIT_CSP
+ CALC_RGB565(y, u, v, GB, RG, 16, dst);
+ #else
+ CALC_RGB565(y, u, v, RG, GB, 16, dst);
+ #endif
+ y += 16;
+ u += 16;
+ v += 16;
+ dst += 16 * 2;
+ length -= 16;
+ }
+ if (length > 8) {
+ uint8_t temp[2 * 16] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+#ifdef WEBP_SWAP_16BIT_CSP
+ CALC_RGB565(temp, u, v, GB, RG, 16, temp);
+#else
+ CALC_RGB565(temp, u, v, RG, GB, 16, temp);
+#endif
+ memcpy(dst, temp, length * 2 * sizeof(*dst));
+ } else if (length > 0) {
+ uint8_t temp[2 * 8] = { 0 };
+ memcpy(temp, y, length * sizeof(*temp));
+#ifdef WEBP_SWAP_16BIT_CSP
+ CALC_RGB565(temp, u, v, GB, RG, 8, temp);
+#else
+ CALC_RGB565(temp, u, v, RG, GB, 8, temp);
+#endif
+ memcpy(dst, temp, length * 2 * sizeof(*dst));
+ }
+}
+
+#define UPSAMPLE_32PIXELS(a, b, c, d) do { \
+ v16u8 s = __msa_aver_u_b(a, d); \
+ v16u8 t = __msa_aver_u_b(b, c); \
+ const v16u8 st = s ^ t; \
+ v16u8 ad = a ^ d; \
+ v16u8 bc = b ^ c; \
+ v16u8 t0 = ad | bc; \
+ v16u8 t1 = t0 | st; \
+ v16u8 t2 = ANDI_B(t1, 1); \
+ v16u8 t3 = __msa_aver_u_b(s, t); \
+ const v16u8 k = t3 - t2; \
+ v16u8 diag1, diag2; \
+ AVER_UB2_UB(t, k, s, k, t0, t1); \
+ bc = bc & st; \
+ ad = ad & st; \
+ t = t ^ k; \
+ s = s ^ k; \
+ t2 = bc | t; \
+ t3 = ad | s; \
+ t2 = ANDI_B(t2, 1); \
+ t3 = ANDI_B(t3, 1); \
+ SUB2(t0, t2, t1, t3, diag1, diag2); \
+ AVER_UB2_UB(a, diag1, b, diag2, t0, t1); \
+ ILVRL_B2_UB(t1, t0, a, b); \
+ if (pbot_y != NULL) { \
+ AVER_UB2_UB(c, diag2, d, diag1, t0, t1); \
+ ILVRL_B2_UB(t1, t0, c, d); \
+ } \
+} while (0)
+
+#define UPSAMPLE_FUNC(FUNC_NAME, FUNC, XSTEP) \
+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* cur_u, const uint8_t* cur_v, \
+ uint8_t* top_dst, uint8_t* bot_dst, int len) \
+{ \
+ int size = (len - 1) >> 1; \
+ uint8_t temp_u[64]; \
+ uint8_t temp_v[64]; \
+ const uint32_t tl_uv = ((top_u[0]) | ((top_v[0]) << 16)); \
+ const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \
+ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
+ const uint8_t* ptop_y = &top_y[1]; \
+ uint8_t *ptop_dst = top_dst + XSTEP; \
+ const uint8_t* pbot_y = &bot_y[1]; \
+ uint8_t *pbot_dst = bot_dst + XSTEP; \
+ \
+ FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
+ if (bot_y != NULL) { \
+ const uint32_t uv1 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \
+ FUNC(bot_y[0], uv1 & 0xff, (uv1 >> 16), bot_dst); \
+ } \
+ while (size >= 16) { \
+ v16u8 tu0, tu1, tv0, tv1, cu0, cu1, cv0, cv1; \
+ LD_UB2(top_u, 1, tu0, tu1); \
+ LD_UB2(cur_u, 1, cu0, cu1); \
+ LD_UB2(top_v, 1, tv0, tv1); \
+ LD_UB2(cur_v, 1, cv0, cv1); \
+ UPSAMPLE_32PIXELS(tu0, tu1, cu0, cu1); \
+ UPSAMPLE_32PIXELS(tv0, tv1, cv0, cv1); \
+ ST_UB4(tu0, tu1, cu0, cu1, &temp_u[0], 16); \
+ ST_UB4(tv0, tv1, cv0, cv1, &temp_v[0], 16); \
+ FUNC##Line(ptop_y, &temp_u[ 0], &temp_v[0], ptop_dst, 32); \
+ if (bot_y != NULL) { \
+ FUNC##Line(pbot_y, &temp_u[32], &temp_v[32], pbot_dst, 32); \
+ } \
+ ptop_y += 32; \
+ pbot_y += 32; \
+ ptop_dst += XSTEP * 32; \
+ pbot_dst += XSTEP * 32; \
+ top_u += 16; \
+ top_v += 16; \
+ cur_u += 16; \
+ cur_v += 16; \
+ size -= 16; \
+ } \
+ if (size > 0) { \
+ v16u8 tu0, tu1, tv0, tv1, cu0, cu1, cv0, cv1; \
+ memcpy(&temp_u[ 0], top_u, 17 * sizeof(uint8_t)); \
+ memcpy(&temp_u[32], cur_u, 17 * sizeof(uint8_t)); \
+ memcpy(&temp_v[ 0], top_v, 17 * sizeof(uint8_t)); \
+ memcpy(&temp_v[32], cur_v, 17 * sizeof(uint8_t)); \
+ LD_UB2(&temp_u[ 0], 1, tu0, tu1); \
+ LD_UB2(&temp_u[32], 1, cu0, cu1); \
+ LD_UB2(&temp_v[ 0], 1, tv0, tv1); \
+ LD_UB2(&temp_v[32], 1, cv0, cv1); \
+ UPSAMPLE_32PIXELS(tu0, tu1, cu0, cu1); \
+ UPSAMPLE_32PIXELS(tv0, tv1, cv0, cv1); \
+ ST_UB4(tu0, tu1, cu0, cu1, &temp_u[0], 16); \
+ ST_UB4(tv0, tv1, cv0, cv1, &temp_v[0], 16); \
+ FUNC##Line(ptop_y, &temp_u[ 0], &temp_v[0], ptop_dst, size * 2); \
+ if (bot_y != NULL) { \
+ FUNC##Line(pbot_y, &temp_u[32], &temp_v[32], pbot_dst, size * 2); \
+ } \
+ top_u += size; \
+ top_v += size; \
+ cur_u += size; \
+ cur_v += size; \
+ } \
+ if (!(len & 1)) { \
+ const uint32_t t0 = ((top_u[0]) | ((top_v[0]) << 16)); \
+ const uint32_t c0 = ((cur_u[0]) | ((cur_v[0]) << 16)); \
+ const uint32_t tmp0 = (3 * t0 + c0 + 0x00020002u) >> 2; \
+ FUNC(top_y[len - 1], tmp0 & 0xff, (tmp0 >> 16), \
+ top_dst + (len - 1) * XSTEP); \
+ if (bot_y != NULL) { \
+ const uint32_t tmp1 = (3 * c0 + t0 + 0x00020002u) >> 2; \
+ FUNC(bot_y[len - 1], tmp1 & 0xff, (tmp1 >> 16), \
+ bot_dst + (len - 1) * XSTEP); \
+ } \
+ } \
+}
+
+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)
+
+//------------------------------------------------------------------------------
+// Entry point
+
+extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */];
+
+extern void WebPInitUpsamplersMSA(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMSA(void) {
+ WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair;
+ WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair;
+ WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair;
+ WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair;
+ WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair;
+ WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair;
+ WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair;
+ WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair;
+ WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair;
+}
+
+#endif // FANCY_UPSAMPLING
+
+#endif // WEBP_USE_MSA
+
+#if !(defined(FANCY_UPSAMPLING) && defined(WEBP_USE_MSA))
+WEBP_DSP_INIT_STUB(WebPInitUpsamplersMSA)
+#endif
diff --git a/thirdparty/libwebp/dsp/upsampling_neon.c b/thirdparty/libwebp/dsp/upsampling_neon.c
index 2b0c99bddb..d371a834ff 100644
--- a/thirdparty/libwebp/dsp/upsampling_neon.c
+++ b/thirdparty/libwebp/dsp/upsampling_neon.c
@@ -28,47 +28,34 @@
// 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; \
- \
+#define UPSAMPLE_16PIXELS(r1, r2, out) do { \
+ const uint8x8_t a = vld1_u8(r1 + 0); \
+ const uint8x8_t b = vld1_u8(r1 + 1); \
+ const uint8x8_t c = vld1_u8(r2 + 0); \
+ const uint8x8_t d = vld1_u8(r2 + 1); \
/* 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 */ \
+ const uint16x8_t ad = vaddl_u8(a, d); \
+ const uint16x8_t bc = vaddl_u8(b, c); \
+ const uint16x8_t abcd = vaddq_u16(ad, bc); \
+ /* 3a + b + c + 3d */ \
+ const uint16x8_t al = vaddq_u16(abcd, vshlq_n_u16(ad, 1)); \
+ /* a + 3b + 3c + d */ \
+ const uint16x8_t bl = vaddq_u16(abcd, vshlq_n_u16(bc, 1)); \
\
- diag2 = vshrn_n_u16(al, 3); \
- diag1 = vshrn_n_u16(bl, 3); \
+ const uint8x8_t diag2 = vshrn_n_u16(al, 3); \
+ const uint8x8_t 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); \
+ const uint8x8_t A = vrhadd_u8(a, diag1); \
+ const uint8x8_t B = vrhadd_u8(b, diag2); \
+ const uint8x8_t C = vrhadd_u8(c, diag2); \
+ const uint8x8_t 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); \
- } \
-}
+ uint8x8x2_t A_B, C_D; \
+ INIT_VECTOR2(A_B, A, B); \
+ INIT_VECTOR2(C_D, C, D); \
+ vst2_u8(out + 0, A_B); \
+ vst2_u8(out + 32, C_D); \
+} while (0)
// Turn the macro into a function for reducing code-size when non-critical
static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2,
@@ -93,7 +80,6 @@ static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2,
static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 };
#define v255 vdup_n_u8(255)
-#define v_0x0f vdup_n_u8(15)
#define STORE_Rgb(out, r, g, b) do { \
uint8x8x3_t r_g_b; \
@@ -132,21 +118,16 @@ static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 };
#endif
#define STORE_Rgba4444(out, r, g, b) do { \
- const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 4), 4); /* 4bits */ \
- const uint8x8_t g1 = vshr_n_u8(g, 4); \
- const uint8x8_t ba = vorr_u8(b, v_0x0f); \
- const uint8x8_t rg = vorr_u8(r1, g1); \
+ const uint8x8_t rg = vsri_n_u8(r, g, 4); /* shift g, insert r */ \
+ const uint8x8_t ba = vsri_n_u8(b, v255, 4); /* shift a, insert b */ \
const uint8x8x2_t rgba4444 = ZIP_U8(rg, ba); \
vst1q_u8(out, vcombine_u8(rgba4444.val[0], rgba4444.val[1])); \
} while (0)
#define STORE_Rgb565(out, r, g, b) do { \
- const uint8x8_t r1 = vshl_n_u8(vshr_n_u8(r, 3), 3); /* 5bits */ \
- const uint8x8_t g1 = vshr_n_u8(g, 5); /* upper 3bits */\
- const uint8x8_t g2 = vshl_n_u8(vshr_n_u8(g, 2), 5); /* lower 3bits */\
- const uint8x8_t b1 = vshr_n_u8(b, 3); /* 5bits */ \
- const uint8x8_t rg = vorr_u8(r1, g1); \
- const uint8x8_t gb = vorr_u8(g2, b1); \
+ const uint8x8_t rg = vsri_n_u8(r, g, 5); /* shift g and insert r */ \
+ const uint8x8_t g1 = vshl_n_u8(g, 3); /* pre-shift g: 3bits */ \
+ const uint8x8_t gb = vsri_n_u8(g1, b, 3); /* shift b and insert g */ \
const uint8x8x2_t rgb565 = ZIP_U8(rg, gb); \
vst1q_u8(out, vcombine_u8(rgb565.val[0], rgb565.val[1])); \
} while (0)
diff --git a/thirdparty/libwebp/dsp/yuv.c b/thirdparty/libwebp/dsp/yuv.c
index f50a253168..dd7d9dedfa 100644
--- a/thirdparty/libwebp/dsp/yuv.c
+++ b/thirdparty/libwebp/dsp/yuv.c
@@ -13,6 +13,8 @@
#include "./yuv.h"
+#include <stdlib.h>
+
#if defined(WEBP_YUV_USE_TABLE)
static int done = 0;
@@ -244,6 +246,48 @@ void WebPConvertRGBA32ToUV_C(const uint16_t* rgb,
//-----------------------------------------------------------------------------
+#define MAX_Y ((1 << 10) - 1) // 10b precision over 16b-arithmetic
+static uint16_t clip_y(int v) {
+ return (v < 0) ? 0 : (v > MAX_Y) ? MAX_Y : (uint16_t)v;
+}
+
+static uint64_t SharpYUVUpdateY_C(const uint16_t* ref, const uint16_t* src,
+ uint16_t* dst, int len) {
+ uint64_t diff = 0;
+ int i;
+ for (i = 0; i < len; ++i) {
+ const int diff_y = ref[i] - src[i];
+ const int new_y = (int)dst[i] + diff_y;
+ dst[i] = clip_y(new_y);
+ diff += (uint64_t)abs(diff_y);
+ }
+ return diff;
+}
+
+static void SharpYUVUpdateRGB_C(const int16_t* ref, const int16_t* src,
+ int16_t* dst, int len) {
+ int i;
+ for (i = 0; i < len; ++i) {
+ const int diff_uv = ref[i] - src[i];
+ dst[i] += diff_uv;
+ }
+}
+
+static void SharpYUVFilterRow_C(const int16_t* A, const int16_t* B, int len,
+ const uint16_t* best_y, uint16_t* out) {
+ int i;
+ for (i = 0; i < len; ++i, ++A, ++B) {
+ const int v0 = (A[0] * 9 + A[1] * 3 + B[0] * 3 + B[1] + 8) >> 4;
+ const int v1 = (A[1] * 9 + A[0] * 3 + B[1] * 3 + B[0] + 8) >> 4;
+ out[2 * i + 0] = clip_y(best_y[2 * i + 0] + v0);
+ out[2 * i + 1] = clip_y(best_y[2 * i + 1] + v1);
+ }
+}
+
+#undef MAX_Y
+
+//-----------------------------------------------------------------------------
+
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,
@@ -253,10 +297,18 @@ 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);
+uint64_t (*WebPSharpYUVUpdateY)(const uint16_t* ref, const uint16_t* src,
+ uint16_t* dst, int len);
+void (*WebPSharpYUVUpdateRGB)(const int16_t* ref, const int16_t* src,
+ int16_t* dst, int len);
+void (*WebPSharpYUVFilterRow)(const int16_t* A, const int16_t* B, int len,
+ const uint16_t* best_y, uint16_t* out);
+
static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used =
(VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used;
extern void WebPInitConvertARGBToYUVSSE2(void);
+extern void WebPInitSharpYUVSSE2(void);
WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return;
@@ -269,10 +321,15 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) {
WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C;
+ WebPSharpYUVUpdateY = SharpYUVUpdateY_C;
+ WebPSharpYUVUpdateRGB = SharpYUVUpdateRGB_C;
+ WebPSharpYUVFilterRow = SharpYUVFilterRow_C;
+
if (VP8GetCPUInfo != NULL) {
#if defined(WEBP_USE_SSE2)
if (VP8GetCPUInfo(kSSE2)) {
WebPInitConvertARGBToYUVSSE2();
+ WebPInitSharpYUVSSE2();
}
#endif // WEBP_USE_SSE2
}
diff --git a/thirdparty/libwebp/dsp/yuv.h b/thirdparty/libwebp/dsp/yuv.h
index 01c40fcb84..1d33b5863b 100644
--- a/thirdparty/libwebp/dsp/yuv.h
+++ b/thirdparty/libwebp/dsp/yuv.h
@@ -36,7 +36,7 @@
#define WEBP_DSP_YUV_H_
#include "./dsp.h"
-#include "../dec/decode_vp8.h"
+#include "../dec/vp8_dec.h"
#if defined(WEBP_EXPERIMENTAL_FEATURES)
// Do NOT activate this feature for real compression. This is only experimental!
diff --git a/thirdparty/libwebp/dsp/yuv_sse2.c b/thirdparty/libwebp/dsp/yuv_sse2.c
index e19bddff6c..e33c2bbafd 100644
--- a/thirdparty/libwebp/dsp/yuv_sse2.c
+++ b/thirdparty/libwebp/dsp/yuv_sse2.c
@@ -15,6 +15,8 @@
#if defined(WEBP_USE_SSE2)
+#include "./common_sse2.h"
+#include <stdlib.h>
#include <emmintrin.h>
//-----------------------------------------------------------------------------
@@ -155,30 +157,13 @@ static WEBP_INLINE void PackAndStore565(const __m128i* const R,
_mm_storeu_si128((__m128i*)dst, rgb565);
}
-// Function used several times in PlanarTo24b.
-// It samples the in buffer as follows: one every two unsigned char is stored
-// at the beginning of the buffer, while the other half is stored at the end.
-static WEBP_INLINE void PlanarTo24bHelper(const __m128i* const in /*in[6]*/,
- __m128i* const out /*out[6]*/) {
- const __m128i v_mask = _mm_set1_epi16(0x00ff);
-
- // Take one every two upper 8b values.
- out[0] = _mm_packus_epi16(_mm_and_si128(in[0], v_mask),
- _mm_and_si128(in[1], v_mask));
- out[1] = _mm_packus_epi16(_mm_and_si128(in[2], v_mask),
- _mm_and_si128(in[3], v_mask));
- out[2] = _mm_packus_epi16(_mm_and_si128(in[4], v_mask),
- _mm_and_si128(in[5], v_mask));
- // Take one every two lower 8b values.
- out[3] = _mm_packus_epi16(_mm_srli_epi16(in[0], 8), _mm_srli_epi16(in[1], 8));
- out[4] = _mm_packus_epi16(_mm_srli_epi16(in[2], 8), _mm_srli_epi16(in[3], 8));
- out[5] = _mm_packus_epi16(_mm_srli_epi16(in[4], 8), _mm_srli_epi16(in[5], 8));
-}
-
// Pack the planar buffers
// rrrr... rrrr... gggg... gggg... bbbb... bbbb....
// triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ...
-static WEBP_INLINE void PlanarTo24b(__m128i* const in /*in[6]*/, uint8_t* rgb) {
+static WEBP_INLINE void PlanarTo24b(__m128i* const in0, __m128i* const in1,
+ __m128i* const in2, __m128i* const in3,
+ __m128i* const in4, __m128i* const in5,
+ uint8_t* const rgb) {
// The input is 6 registers of sixteen 8b but for the sake of explanation,
// let's take 6 registers of four 8b values.
// To pack, we will keep taking one every two 8b integer and move it
@@ -191,22 +176,15 @@ static WEBP_INLINE void PlanarTo24b(__m128i* const in /*in[6]*/, uint8_t* rgb) {
// Repeat the same permutations twice more:
// r0r4g0g4 | b0b4r1r5 | g1g5b1b5 | r2r6g2g6 | b2b6r3r7 | g3g7b3b7
// r0g0b0r1 | g1b1r2g2 | b2r3g3b3 | r4g4b4r5 | g5b5r6g6 | b6r7g7b7
- __m128i tmp[6];
- PlanarTo24bHelper(in, tmp);
- PlanarTo24bHelper(tmp, in);
- PlanarTo24bHelper(in, tmp);
- // We need to do it two more times than the example as we have sixteen bytes.
- PlanarTo24bHelper(tmp, in);
- PlanarTo24bHelper(in, tmp);
-
- _mm_storeu_si128((__m128i*)(rgb + 0), tmp[0]);
- _mm_storeu_si128((__m128i*)(rgb + 16), tmp[1]);
- _mm_storeu_si128((__m128i*)(rgb + 32), tmp[2]);
- _mm_storeu_si128((__m128i*)(rgb + 48), tmp[3]);
- _mm_storeu_si128((__m128i*)(rgb + 64), tmp[4]);
- _mm_storeu_si128((__m128i*)(rgb + 80), tmp[5]);
-}
-#undef MK_UINT32
+ VP8PlanarTo24b(in0, in1, in2, in3, in4, in5);
+
+ _mm_storeu_si128((__m128i*)(rgb + 0), *in0);
+ _mm_storeu_si128((__m128i*)(rgb + 16), *in1);
+ _mm_storeu_si128((__m128i*)(rgb + 32), *in2);
+ _mm_storeu_si128((__m128i*)(rgb + 48), *in3);
+ _mm_storeu_si128((__m128i*)(rgb + 64), *in4);
+ _mm_storeu_si128((__m128i*)(rgb + 80), *in5);
+}
void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
uint8_t* dst) {
@@ -265,29 +243,29 @@ void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v,
void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
uint8_t* dst) {
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i rgb[6];
+ __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5;
- YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
- YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1);
+ YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
+ YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1);
YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2);
YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3);
// Cast to 8b and store as RRRRGGGGBBBB.
- rgb[0] = _mm_packus_epi16(R0, R1);
- rgb[1] = _mm_packus_epi16(R2, R3);
- rgb[2] = _mm_packus_epi16(G0, G1);
- rgb[3] = _mm_packus_epi16(G2, G3);
- rgb[4] = _mm_packus_epi16(B0, B1);
- rgb[5] = _mm_packus_epi16(B2, B3);
+ rgb0 = _mm_packus_epi16(R0, R1);
+ rgb1 = _mm_packus_epi16(R2, R3);
+ rgb2 = _mm_packus_epi16(G0, G1);
+ rgb3 = _mm_packus_epi16(G2, G3);
+ rgb4 = _mm_packus_epi16(B0, B1);
+ rgb5 = _mm_packus_epi16(B2, B3);
// Pack as RGBRGBRGBRGB.
- PlanarTo24b(rgb, dst);
+ PlanarTo24b(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst);
}
void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
uint8_t* dst) {
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i bgr[6];
+ __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5;
YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1);
@@ -295,15 +273,15 @@ void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v,
YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3);
// Cast to 8b and store as BBBBGGGGRRRR.
- bgr[0] = _mm_packus_epi16(B0, B1);
- bgr[1] = _mm_packus_epi16(B2, B3);
- bgr[2] = _mm_packus_epi16(G0, G1);
- bgr[3] = _mm_packus_epi16(G2, G3);
- bgr[4] = _mm_packus_epi16(R0, R1);
- bgr[5] = _mm_packus_epi16(R2, R3);
+ bgr0 = _mm_packus_epi16(B0, B1);
+ bgr1 = _mm_packus_epi16(B2, B3);
+ bgr2 = _mm_packus_epi16(G0, G1);
+ bgr3 = _mm_packus_epi16(G2, G3);
+ bgr4 = _mm_packus_epi16(R0, R1);
+ bgr5= _mm_packus_epi16(R2, R3);
// Pack as BGRBGRBGRBGR.
- PlanarTo24b(bgr, dst);
+ PlanarTo24b(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst);
}
//-----------------------------------------------------------------------------
@@ -377,7 +355,7 @@ static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
int n;
for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i rgb[6];
+ __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5;
YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1);
@@ -385,15 +363,15 @@ static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3);
// Cast to 8b and store as RRRRGGGGBBBB.
- rgb[0] = _mm_packus_epi16(R0, R1);
- rgb[1] = _mm_packus_epi16(R2, R3);
- rgb[2] = _mm_packus_epi16(G0, G1);
- rgb[3] = _mm_packus_epi16(G2, G3);
- rgb[4] = _mm_packus_epi16(B0, B1);
- rgb[5] = _mm_packus_epi16(B2, B3);
+ rgb0 = _mm_packus_epi16(R0, R1);
+ rgb1 = _mm_packus_epi16(R2, R3);
+ rgb2 = _mm_packus_epi16(G0, G1);
+ rgb3 = _mm_packus_epi16(G2, G3);
+ rgb4 = _mm_packus_epi16(B0, B1);
+ rgb5 = _mm_packus_epi16(B2, B3);
// Pack as RGBRGBRGBRGB.
- PlanarTo24b(rgb, dst);
+ PlanarTo24b(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst);
y += 32;
u += 16;
@@ -413,7 +391,7 @@ static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
int n;
for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) {
__m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3;
- __m128i bgr[6];
+ __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5;
YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0);
YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1);
@@ -421,15 +399,15 @@ static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v,
YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3);
// Cast to 8b and store as BBBBGGGGRRRR.
- bgr[0] = _mm_packus_epi16(B0, B1);
- bgr[1] = _mm_packus_epi16(B2, B3);
- bgr[2] = _mm_packus_epi16(G0, G1);
- bgr[3] = _mm_packus_epi16(G2, G3);
- bgr[4] = _mm_packus_epi16(R0, R1);
- bgr[5] = _mm_packus_epi16(R2, R3);
+ bgr0 = _mm_packus_epi16(B0, B1);
+ bgr1 = _mm_packus_epi16(B2, B3);
+ bgr2 = _mm_packus_epi16(G0, G1);
+ bgr3 = _mm_packus_epi16(G2, G3);
+ bgr4 = _mm_packus_epi16(R0, R1);
+ bgr5 = _mm_packus_epi16(R2, R3);
// Pack as BGRBGRBGRBGR.
- PlanarTo24b(bgr, dst);
+ PlanarTo24b(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst);
y += 32;
u += 16;
@@ -499,25 +477,19 @@ static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb,
// 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) {
+ __m128i* const rgb /*in[6]*/) {
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);
+ __m128i a0 = LOAD_16(argb + 0);
+ __m128i a1 = LOAD_16(argb + 4);
+ __m128i a2 = LOAD_16(argb + 8);
+ __m128i a3 = LOAD_16(argb + 12);
+ VP8L32bToPlanar(&a0, &a1, &a2, &a3);
+ rgb[0] = _mm_unpacklo_epi8(a1, zero);
+ rgb[1] = _mm_unpackhi_epi8(a1, zero);
+ rgb[2] = _mm_unpacklo_epi8(a2, zero);
+ rgb[3] = _mm_unpackhi_epi8(a2, zero);
+ rgb[4] = _mm_unpacklo_epi8(a3, zero);
+ rgb[5] = _mm_unpackhi_epi8(a3, zero);
}
// This macro computes (RG * MULT_RG + GB * MULT_GB + ROUNDER) >> DESCALE_FIX
@@ -649,11 +621,10 @@ 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);
+ __m128i Y0, Y1, rgb[6];
+ RGB32PackedToPlanar(&argb[i], rgb);
+ ConvertRGBToY(&rgb[0], &rgb[2], &rgb[4], &Y0);
+ ConvertRGBToY(&rgb[1], &rgb[3], &rgb[5], &Y1);
STORE_16(_mm_packus_epi16(Y0, Y1), y + i);
}
for (; i < width; ++i) { // left-over
@@ -678,20 +649,18 @@ static void ConvertARGBToUV(const uint32_t* argb, uint8_t* u, uint8_t* v,
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);
+ __m128i rgb[6], U0, V0, U1, V1;
+ RGB32PackedToPlanar(&argb[i], rgb);
+ HorizontalAddPack(&rgb[0], &rgb[1], &rgb[0]);
+ HorizontalAddPack(&rgb[2], &rgb[3], &rgb[2]);
+ HorizontalAddPack(&rgb[4], &rgb[5], &rgb[4]);
+ ConvertRGBToUV(&rgb[0], &rgb[2], &rgb[4], &U0, &V0);
+
+ RGB32PackedToPlanar(&argb[i + 16], rgb);
+ HorizontalAddPack(&rgb[0], &rgb[1], &rgb[0]);
+ HorizontalAddPack(&rgb[2], &rgb[3], &rgb[2]);
+ HorizontalAddPack(&rgb[4], &rgb[5], &rgb[4]);
+ ConvertRGBToUV(&rgb[0], &rgb[2], &rgb[4], &U1, &V1);
U0 = _mm_packus_epi16(U0, U1);
V0 = _mm_packus_epi16(V0, V1);
@@ -767,9 +736,128 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) {
WebPConvertRGBA32ToUV = ConvertRGBA32ToUV;
}
+//------------------------------------------------------------------------------
+
+#define MAX_Y ((1 << 10) - 1) // 10b precision over 16b-arithmetic
+static uint16_t clip_y(int v) {
+ return (v < 0) ? 0 : (v > MAX_Y) ? MAX_Y : (uint16_t)v;
+}
+
+static uint64_t SharpYUVUpdateY_SSE2(const uint16_t* ref, const uint16_t* src,
+ uint16_t* dst, int len) {
+ uint64_t diff = 0;
+ uint32_t tmp[4];
+ int i;
+ const __m128i zero = _mm_setzero_si128();
+ const __m128i max = _mm_set1_epi16(MAX_Y);
+ const __m128i one = _mm_set1_epi16(1);
+ __m128i sum = zero;
+
+ for (i = 0; i + 8 <= len; i += 8) {
+ const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i));
+ const __m128i B = _mm_loadu_si128((const __m128i*)(src + i));
+ const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i));
+ const __m128i D = _mm_sub_epi16(A, B); // diff_y
+ const __m128i E = _mm_cmpgt_epi16(zero, D); // sign (-1 or 0)
+ const __m128i F = _mm_add_epi16(C, D); // new_y
+ const __m128i G = _mm_or_si128(E, one); // -1 or 1
+ const __m128i H = _mm_max_epi16(_mm_min_epi16(F, max), zero);
+ const __m128i I = _mm_madd_epi16(D, G); // sum(abs(...))
+ _mm_storeu_si128((__m128i*)(dst + i), H);
+ sum = _mm_add_epi32(sum, I);
+ }
+ _mm_storeu_si128((__m128i*)tmp, sum);
+ diff = tmp[3] + tmp[2] + tmp[1] + tmp[0];
+ for (; i < len; ++i) {
+ const int diff_y = ref[i] - src[i];
+ const int new_y = (int)dst[i] + diff_y;
+ dst[i] = clip_y(new_y);
+ diff += (uint64_t)abs(diff_y);
+ }
+ return diff;
+}
+
+static void SharpYUVUpdateRGB_SSE2(const int16_t* ref, const int16_t* src,
+ int16_t* dst, int len) {
+ int i = 0;
+ for (i = 0; i + 8 <= len; i += 8) {
+ const __m128i A = _mm_loadu_si128((const __m128i*)(ref + i));
+ const __m128i B = _mm_loadu_si128((const __m128i*)(src + i));
+ const __m128i C = _mm_loadu_si128((const __m128i*)(dst + i));
+ const __m128i D = _mm_sub_epi16(A, B); // diff_uv
+ const __m128i E = _mm_add_epi16(C, D); // new_uv
+ _mm_storeu_si128((__m128i*)(dst + i), E);
+ }
+ for (; i < len; ++i) {
+ const int diff_uv = ref[i] - src[i];
+ dst[i] += diff_uv;
+ }
+}
+
+static void SharpYUVFilterRow_SSE2(const int16_t* A, const int16_t* B, int len,
+ const uint16_t* best_y, uint16_t* out) {
+ int i;
+ const __m128i kCst8 = _mm_set1_epi16(8);
+ const __m128i max = _mm_set1_epi16(MAX_Y);
+ const __m128i zero = _mm_setzero_si128();
+ for (i = 0; i + 8 <= len; i += 8) {
+ const __m128i a0 = _mm_loadu_si128((const __m128i*)(A + i + 0));
+ const __m128i a1 = _mm_loadu_si128((const __m128i*)(A + i + 1));
+ const __m128i b0 = _mm_loadu_si128((const __m128i*)(B + i + 0));
+ const __m128i b1 = _mm_loadu_si128((const __m128i*)(B + i + 1));
+ const __m128i a0b1 = _mm_add_epi16(a0, b1);
+ const __m128i a1b0 = _mm_add_epi16(a1, b0);
+ const __m128i a0a1b0b1 = _mm_add_epi16(a0b1, a1b0); // A0+A1+B0+B1
+ const __m128i a0a1b0b1_8 = _mm_add_epi16(a0a1b0b1, kCst8);
+ const __m128i a0b1_2 = _mm_add_epi16(a0b1, a0b1); // 2*(A0+B1)
+ const __m128i a1b0_2 = _mm_add_epi16(a1b0, a1b0); // 2*(A1+B0)
+ const __m128i c0 = _mm_srai_epi16(_mm_add_epi16(a0b1_2, a0a1b0b1_8), 3);
+ const __m128i c1 = _mm_srai_epi16(_mm_add_epi16(a1b0_2, a0a1b0b1_8), 3);
+ const __m128i d0 = _mm_add_epi16(c1, a0);
+ const __m128i d1 = _mm_add_epi16(c0, a1);
+ const __m128i e0 = _mm_srai_epi16(d0, 1);
+ const __m128i e1 = _mm_srai_epi16(d1, 1);
+ const __m128i f0 = _mm_unpacklo_epi16(e0, e1);
+ const __m128i f1 = _mm_unpackhi_epi16(e0, e1);
+ const __m128i g0 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 0));
+ const __m128i g1 = _mm_loadu_si128((const __m128i*)(best_y + 2 * i + 8));
+ const __m128i h0 = _mm_add_epi16(g0, f0);
+ const __m128i h1 = _mm_add_epi16(g1, f1);
+ const __m128i i0 = _mm_max_epi16(_mm_min_epi16(h0, max), zero);
+ const __m128i i1 = _mm_max_epi16(_mm_min_epi16(h1, max), zero);
+ _mm_storeu_si128((__m128i*)(out + 2 * i + 0), i0);
+ _mm_storeu_si128((__m128i*)(out + 2 * i + 8), i1);
+ }
+ for (; i < len; ++i) {
+ // (9 * A0 + 3 * A1 + 3 * B0 + B1 + 8) >> 4 =
+ // = (8 * A0 + 2 * (A1 + B0) + (A0 + A1 + B0 + B1 + 8)) >> 4
+ // We reuse the common sub-expressions.
+ const int a0b1 = A[i + 0] + B[i + 1];
+ const int a1b0 = A[i + 1] + B[i + 0];
+ const int a0a1b0b1 = a0b1 + a1b0 + 8;
+ const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4;
+ const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4;
+ out[2 * i + 0] = clip_y(best_y[2 * i + 0] + v0);
+ out[2 * i + 1] = clip_y(best_y[2 * i + 1] + v1);
+ }
+}
+
+#undef MAX_Y
+
+//------------------------------------------------------------------------------
+
+extern void WebPInitSharpYUVSSE2(void);
+
+WEBP_TSAN_IGNORE_FUNCTION void WebPInitSharpYUVSSE2(void) {
+ WebPSharpYUVUpdateY = SharpYUVUpdateY_SSE2;
+ WebPSharpYUVUpdateRGB = SharpYUVUpdateRGB_SSE2;
+ WebPSharpYUVFilterRow = SharpYUVFilterRow_SSE2;
+}
+
#else // !WEBP_USE_SSE2
WEBP_DSP_INIT_STUB(WebPInitSamplersSSE2)
WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVSSE2)
+WEBP_DSP_INIT_STUB(WebPInitSharpYUVSSE2)
#endif // WEBP_USE_SSE2
diff --git a/thirdparty/libwebp/dsp/yuv_tables_sse2.h b/thirdparty/libwebp/dsp/yuv_tables_sse2.h
deleted file mode 100644
index 2b0f057518..0000000000
--- a/thirdparty/libwebp/dsp/yuv_tables_sse2.h
+++ /dev/null
@@ -1,536 +0,0 @@
-// 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/thirdparty/libwebp/enc/alpha.c b/thirdparty/libwebp/enc/alpha.c
deleted file mode 100644
index 03e3ad07f5..0000000000
--- a/thirdparty/libwebp/enc/alpha.c
+++ /dev/null
@@ -1,433 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Alpha-plane compression.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./vp8enci.h"
-#include "../dsp/dsp.h"
-#include "../utils/filters.h"
-#include "../utils/quant_levels.h"
-#include "../utils/utils.h"
-#include "../webp/format_constants.h"
-
-// -----------------------------------------------------------------------------
-// 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
-// WebPSafeFree(*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
- VP8LBitWriter* const bw,
- WebPAuxStats* const stats) {
- int ok = 0;
- WebPConfig config;
- WebPPicture picture;
-
- 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.
- WebPDispatchAlphaToGreen(data, width, picture.width, picture.height,
- picture.argb, picture.argb_stride);
-
- WebPConfigInit(&config);
- config.lossless = 1;
- // Enable exact, or it would alter RGB values of transparent alpha, which is
- // normally OK but not here since we are not encoding the input image but an
- // internal encoding-related image containing necessary exact information in
- // RGB channels.
- config.exact = 1;
- config.method = effort_level; // impact is very small
- // 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);
-
- // TODO(urvang): Temporary fix to avoid generating images that trigger
- // a decoder bug related to alpha with color cache.
- // See: https://code.google.com/p/webp/issues/detail?id=239
- // Need to re-enable this later.
- ok = (VP8LEncodeStream(&config, &picture, bw, 0 /*use_cache*/) == VP8_ENC_OK);
- WebPPictureFree(&picture);
- ok = ok && !bw->error_;
- if (!ok) {
- VP8LBitWriterWipeOut(bw);
- return 0;
- }
- 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,
- FilterTrial* result) {
- int ok = 0;
- const uint8_t* alpha_src;
- WebPFilterFunc filter_func;
- uint8_t header;
- 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);
- assert(method >= ALPHA_NO_COMPRESSION);
- assert(method <= ALPHA_LOSSLESS_COMPRESSION);
- assert(sizeof(header) == ALPHA_HEADER_LEN);
-
- filter_func = WebPFilters[filter];
- 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) {
- 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;
-}
-
-// -----------------------------------------------------------------------------
-
-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,
- 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;
- }
-
- 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).
- 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
- // 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) {
- 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;
- }
- }
-
- 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 VP8EncStartAlpha(VP8Encoder* const enc) {
- if (enc->has_alpha_) {
- 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
- }
- }
- 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
- }
- }
- return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
-}
-
-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;
-}
diff --git a/thirdparty/libwebp/enc/alpha_enc.c b/thirdparty/libwebp/enc/alpha_enc.c
new file mode 100644
index 0000000000..5a2c931f92
--- /dev/null
+++ b/thirdparty/libwebp/enc/alpha_enc.c
@@ -0,0 +1,433 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Alpha-plane compression.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "./vp8i_enc.h"
+#include "../dsp/dsp.h"
+#include "../utils/filters_utils.h"
+#include "../utils/quant_levels_utils.h"
+#include "../utils/utils.h"
+#include "../webp/format_constants.h"
+
+// -----------------------------------------------------------------------------
+// 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
+// WebPSafeFree(*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_enc.h"
+
+static int EncodeLossless(const uint8_t* const data, int width, int height,
+ int effort_level, // in [0..6] range
+ VP8LBitWriter* const bw,
+ WebPAuxStats* const stats) {
+ int ok = 0;
+ WebPConfig config;
+ WebPPicture picture;
+
+ 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.
+ WebPDispatchAlphaToGreen(data, width, picture.width, picture.height,
+ picture.argb, picture.argb_stride);
+
+ WebPConfigInit(&config);
+ config.lossless = 1;
+ // Enable exact, or it would alter RGB values of transparent alpha, which is
+ // normally OK but not here since we are not encoding the input image but an
+ // internal encoding-related image containing necessary exact information in
+ // RGB channels.
+ config.exact = 1;
+ config.method = effort_level; // impact is very small
+ // 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);
+
+ // TODO(urvang): Temporary fix to avoid generating images that trigger
+ // a decoder bug related to alpha with color cache.
+ // See: https://code.google.com/p/webp/issues/detail?id=239
+ // Need to re-enable this later.
+ ok = (VP8LEncodeStream(&config, &picture, bw, 0 /*use_cache*/) == VP8_ENC_OK);
+ WebPPictureFree(&picture);
+ ok = ok && !bw->error_;
+ if (!ok) {
+ VP8LBitWriterWipeOut(bw);
+ return 0;
+ }
+ 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,
+ FilterTrial* result) {
+ int ok = 0;
+ const uint8_t* alpha_src;
+ WebPFilterFunc filter_func;
+ uint8_t header;
+ 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);
+ assert(method >= ALPHA_NO_COMPRESSION);
+ assert(method <= ALPHA_LOSSLESS_COMPRESSION);
+ assert(sizeof(header) == ALPHA_HEADER_LEN);
+
+ filter_func = WebPFilters[filter];
+ 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) {
+ 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;
+}
+
+// -----------------------------------------------------------------------------
+
+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,
+ 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;
+ }
+
+ 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).
+ 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
+ // 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) {
+ 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;
+ }
+ }
+
+ 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 VP8EncStartAlpha(VP8Encoder* const enc) {
+ if (enc->has_alpha_) {
+ 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
+ }
+ }
+ 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
+ }
+ }
+ return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_);
+}
+
+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;
+}
diff --git a/thirdparty/libwebp/enc/analysis.c b/thirdparty/libwebp/enc/analysis.c
deleted file mode 100644
index 136c331289..0000000000
--- a/thirdparty/libwebp/enc/analysis.c
+++ /dev/null
@@ -1,506 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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"
-
-#define MAX_ITERS_K_MEANS 6
-
-//------------------------------------------------------------------------------
-// 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(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;
- break;
- }
- }
- 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];
- }
- }
- WebPSafeFree(tmp);
-}
-
-//------------------------------------------------------------------------------
-// set segment susceptibility alpha_ / beta_
-
-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);
- }
-}
-
-//------------------------------------------------------------------------------
-// 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[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[MAX_ALPHA + 1];
- int a, n, k;
- 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 <= MAX_ALPHA && alphas[n] == 0; ++n) {}
- min_a = 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 (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
- 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 + 1 < nb && 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]]; // for the record.
- }
-
- if (nb > 1) {
- const int smooth = (enc->config_->preprocessing & 1);
- if (smooth) SmoothSegmentMap(enc);
- }
-
- 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. 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 = MAX_INTRA16_MODE;
- int mode;
- int best_alpha = DEFAULT_ALPHA;
- int best_mode = 0;
-
- VP8MakeLuma16Preds(it);
- for (mode = 0; mode < max_mode; ++mode) {
- 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;
- }
- }
- VP8SetIntra16Mode(it, best_mode);
- return best_alpha;
-}
-
-static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
- int best_alpha) {
- uint8_t modes[16];
- 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 = 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) {
- 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.
- }
- }
- // 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_ENC));
-
- i4_alpha = GetAlpha(&total_histo);
- if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) {
- VP8SetIntra4Mode(it, modes);
- best_alpha = i4_alpha;
- }
- return best_alpha;
-}
-
-static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
- int best_alpha = DEFAULT_ALPHA;
- int smallest_alpha = 0;
- int best_mode = 0;
- const int max_mode = MAX_UV_MODE;
- int mode;
-
- VP8MakeChroma8Preds(it);
- for (mode = 0; mode < max_mode; ++mode) {
- 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;
- }
- // The best prediction mode tends to be the one with the smallest alpha.
- if (mode == 0 || alpha < smallest_alpha) {
- smallest_alpha = alpha;
- best_mode = mode;
- }
- }
- VP8SetIntraUVMode(it, best_mode);
- return best_alpha;
-}
-
-static void MBAnalyze(VP8EncIterator* const it,
- int alphas[MAX_ALPHA + 1],
- int* const alpha, 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_ >= 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.
- // TODO(skal): improve criterion.
- best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha);
- }
- best_uv_alpha = MBAnalyzeBestUVMode(it);
-
- // Final susceptibility mix
- 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;
-}
-
-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;
-}
-
-//------------------------------------------------------------------------------
-// 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.
-
-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;
- 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;
-}
-
-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/thirdparty/libwebp/enc/analysis_enc.c b/thirdparty/libwebp/enc/analysis_enc.c
new file mode 100644
index 0000000000..dce159b316
--- /dev/null
+++ b/thirdparty/libwebp/enc/analysis_enc.c
@@ -0,0 +1,533 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Macroblock analysis
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "./vp8i_enc.h"
+#include "./cost_enc.h"
+#include "../utils/utils.h"
+
+#define MAX_ITERS_K_MEANS 6
+
+//------------------------------------------------------------------------------
+// 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(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;
+ break;
+ }
+ }
+ 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];
+ }
+ }
+ WebPSafeFree(tmp);
+}
+
+//------------------------------------------------------------------------------
+// set segment susceptibility alpha_ / beta_
+
+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);
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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[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[MAX_ALPHA + 1];
+ int a, n, k;
+ 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 <= MAX_ALPHA && alphas[n] == 0; ++n) {}
+ min_a = 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 (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
+ 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 + 1 < nb && 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]]; // for the record.
+ }
+
+ if (nb > 1) {
+ const int smooth = (enc->config_->preprocessing & 1);
+ if (smooth) SmoothSegmentMap(enc);
+ }
+
+ 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. 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 = MAX_INTRA16_MODE;
+ int mode;
+ int best_alpha = DEFAULT_ALPHA;
+ int best_mode = 0;
+
+ VP8MakeLuma16Preds(it);
+ for (mode = 0; mode < max_mode; ++mode) {
+ 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;
+ }
+ }
+ VP8SetIntra16Mode(it, best_mode);
+ return best_alpha;
+}
+
+static int FastMBAnalyze(VP8EncIterator* const it) {
+ // Empirical cut-off value, should be around 16 (~=block size). We use the
+ // [8-17] range and favor intra4 at high quality, intra16 for low quality.
+ const int q = (int)it->enc_->config_->quality;
+ const uint32_t kThreshold = 8 + (17 - 8) * q / 100;
+ int k;
+ uint32_t dc[16], m, m2;
+ for (k = 0; k < 16; k += 4) {
+ VP8Mean16x4(it->yuv_in_ + Y_OFF_ENC + k * BPS, &dc[k]);
+ }
+ for (m = 0, m2 = 0, k = 0; k < 16; ++k) {
+ m += dc[k];
+ m2 += dc[k] * dc[k];
+ }
+ if (kThreshold * m2 < m * m) {
+ VP8SetIntra16Mode(it, 0); // DC16
+ } else {
+ const uint8_t modes[16] = { 0 }; // DC4
+ VP8SetIntra4Mode(it, modes);
+ }
+ return 0;
+}
+
+static int MBAnalyzeBestIntra4Mode(VP8EncIterator* const it,
+ int best_alpha) {
+ uint8_t modes[16];
+ 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 = 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) {
+ 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.
+ }
+ }
+ // 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_ENC));
+
+ i4_alpha = GetAlpha(&total_histo);
+ if (IS_BETTER_ALPHA(i4_alpha, best_alpha)) {
+ VP8SetIntra4Mode(it, modes);
+ best_alpha = i4_alpha;
+ }
+ return best_alpha;
+}
+
+static int MBAnalyzeBestUVMode(VP8EncIterator* const it) {
+ int best_alpha = DEFAULT_ALPHA;
+ int smallest_alpha = 0;
+ int best_mode = 0;
+ const int max_mode = MAX_UV_MODE;
+ int mode;
+
+ VP8MakeChroma8Preds(it);
+ for (mode = 0; mode < max_mode; ++mode) {
+ 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;
+ }
+ // The best prediction mode tends to be the one with the smallest alpha.
+ if (mode == 0 || alpha < smallest_alpha) {
+ smallest_alpha = alpha;
+ best_mode = mode;
+ }
+ }
+ VP8SetIntraUVMode(it, best_mode);
+ return best_alpha;
+}
+
+static void MBAnalyze(VP8EncIterator* const it,
+ int alphas[MAX_ALPHA + 1],
+ int* const alpha, 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.
+
+ if (enc->method_ <= 1) {
+ best_alpha = FastMBAnalyze(it);
+ } else {
+ best_alpha = MBAnalyzeBestIntra16Mode(it);
+ 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.
+ // TODO(skal): improve criterion.
+ best_alpha = MBAnalyzeBestIntra4Mode(it, best_alpha);
+ }
+ }
+ best_uv_alpha = MBAnalyzeBestUVMode(it);
+
+ // Final susceptibility mix
+ 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;
+}
+
+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;
+}
+
+//------------------------------------------------------------------------------
+// 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.
+
+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;
+ 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;
+}
+
+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_ <= 1); // for method 0 - 1, 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/thirdparty/libwebp/enc/backward_references.c b/thirdparty/libwebp/enc/backward_references.c
deleted file mode 100644
index 136a24a8c3..0000000000
--- a/thirdparty/libwebp/enc/backward_references.c
+++ /dev/null
@@ -1,1715 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-
-#include <assert.h>
-#include <math.h>
-
-#include "./backward_references.h"
-#include "./histogram.h"
-#include "../dsp/lossless.h"
-#include "../dsp/dsp.h"
-#include "../utils/color_cache.h"
-#include "../utils/utils.h"
-
-#define VALUES_IN_BYTE 256
-
-#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_BITS 20
-#define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120)
-
-// Bounds for the match length.
-#define MIN_LENGTH 2
-// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it
-// is used in VP8LHashChain.
-#define MAX_LENGTH_BITS 12
-// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits.
-#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1)
-#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32
-#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32"
-#endif
-
-// -----------------------------------------------------------------------------
-
-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;
-}
-
-// Returns the exact index where array1 and array2 are different. For an index
-// inferior or equal to best_len_match, the return value just has to be strictly
-// inferior to best_len_match. The current behavior is to return 0 if this index
-// is best_len_match, and the index itself otherwise.
-// If no two elements are the same, it returns max_limit.
-static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
- const uint32_t* const array2,
- int best_len_match, int max_limit) {
- // 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;
-
- return VP8LVectorMismatch(array1, array2, max_limit);
-}
-
-// -----------------------------------------------------------------------------
-// VP8LBackwardRefs
-
-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 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;
- }
-}
-
-void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) {
- assert(refs != NULL);
- 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
-
-int VP8LHashChainInit(VP8LHashChain* const p, int size) {
- assert(p->size_ == 0);
- assert(p->offset_length_ == NULL);
- assert(size > 0);
- p->offset_length_ =
- (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_));
- if (p->offset_length_ == NULL) return 0;
- p->size_ = size;
-
- return 1;
-}
-
-void VP8LHashChainClear(VP8LHashChain* const p) {
- assert(p != NULL);
- WebPSafeFree(p->offset_length_);
-
- p->size_ = 0;
- p->offset_length_ = 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;
-}
-
-// Returns the maximum number of hash chain lookups to do for a
-// given compression quality. Return value in range [8, 86].
-static int GetMaxItersForQuality(int quality) {
- return 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;
-}
-
-int VP8LHashChainFill(VP8LHashChain* const p, int quality,
- const uint32_t* const argb, int xsize, int ysize) {
- const int size = xsize * ysize;
- const int iter_max = GetMaxItersForQuality(quality);
- const int iter_min = iter_max - quality / 10;
- const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize);
- int pos;
- uint32_t base_position;
- int32_t* hash_to_first_index;
- // Temporarily use the p->offset_length_ as a hash chain.
- int32_t* chain = (int32_t*)p->offset_length_;
- assert(p->size_ != 0);
- assert(p->offset_length_ != NULL);
-
- hash_to_first_index =
- (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index));
- if (hash_to_first_index == NULL) return 0;
-
- // Set the int32_t array to -1.
- memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index));
- // Fill the chain linking pixels with the same hash.
- for (pos = 0; pos < size - 1; ++pos) {
- const uint32_t hash_code = GetPixPairHash64(argb + pos);
- chain[pos] = hash_to_first_index[hash_code];
- hash_to_first_index[hash_code] = pos;
- }
- WebPSafeFree(hash_to_first_index);
-
- // Find the best match interval at each pixel, defined by an offset to the
- // pixel and a length. The right-most pixel cannot match anything to the right
- // (hence a best length of 0) and the left-most pixel nothing to the left
- // (hence an offset of 0).
- p->offset_length_[0] = p->offset_length_[size - 1] = 0;
- for (base_position = size - 2 < 0 ? 0 : size - 2; base_position > 0;) {
- const int max_len = MaxFindCopyLength(size - 1 - base_position);
- const uint32_t* const argb_start = argb + base_position;
- int iter = iter_max;
- int best_length = 0;
- uint32_t best_distance = 0;
- const int min_pos =
- (base_position > window_size) ? base_position - window_size : 0;
- const int length_max = (max_len < 256) ? max_len : 256;
- uint32_t max_base_position;
-
- for (pos = chain[base_position]; pos >= min_pos; pos = chain[pos]) {
- int curr_length;
- if (--iter < 0) {
- break;
- }
- assert(base_position > (uint32_t)pos);
-
- curr_length =
- FindMatchLength(argb + pos, argb_start, best_length, max_len);
- if (best_length < curr_length) {
- best_length = curr_length;
- best_distance = base_position - pos;
- // Stop if we have reached the maximum length. Otherwise, make sure
- // we have executed a minimum number of iterations depending on the
- // quality.
- if ((best_length == MAX_LENGTH) ||
- (curr_length >= length_max && iter < iter_min)) {
- break;
- }
- }
- }
- // We have the best match but in case the two intervals continue matching
- // to the left, we have the best matches for the left-extended pixels.
- max_base_position = base_position;
- while (1) {
- assert(best_length <= MAX_LENGTH);
- assert(best_distance <= WINDOW_SIZE);
- p->offset_length_[base_position] =
- (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length;
- --base_position;
- // Stop if we don't have a match or if we are out of bounds.
- if (best_distance == 0 || base_position == 0) break;
- // Stop if we cannot extend the matching intervals to the left.
- if (base_position < best_distance ||
- argb[base_position - best_distance] != argb[base_position]) {
- break;
- }
- // Stop if we are matching at its limit because there could be a closer
- // matching interval with the same maximum length. Then again, if the
- // matching interval is as close as possible (best_distance == 1), we will
- // never find anything better so let's continue.
- if (best_length == MAX_LENGTH && best_distance != 1 &&
- base_position + MAX_LENGTH < max_base_position) {
- break;
- }
- if (best_length < MAX_LENGTH) {
- ++best_length;
- max_base_position = base_position;
- }
- }
- }
- return 1;
-}
-
-static WEBP_INLINE int HashChainFindOffset(const VP8LHashChain* const p,
- const int base_position) {
- return p->offset_length_[base_position] >> MAX_LENGTH_BITS;
-}
-
-static WEBP_INLINE int HashChainFindLength(const VP8LHashChain* const p,
- const int base_position) {
- return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1);
-}
-
-static WEBP_INLINE void HashChainFindCopy(const VP8LHashChain* const p,
- int base_position,
- int* const offset_ptr,
- int* const length_ptr) {
- *offset_ptr = HashChainFindOffset(p, base_position);
- *length_ptr = HashChainFindLength(p, base_position);
-}
-
-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);
- }
- BackwardRefsCursorAdd(refs, v);
-}
-
-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 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 {
- AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
- i++;
- }
- }
- if (use_color_cache) VP8LColorCacheClear(&hashers);
- return !refs->error_;
-}
-
-static int BackwardReferencesLz77(int xsize, int ysize,
- const uint32_t* const argb, int cache_bits,
- const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs) {
- int i;
- int i_last_check = -1;
- int ok = 0;
- int cc_init = 0;
- const int use_color_cache = (cache_bits > 0);
- const int pix_count = xsize * ysize;
- VP8LColorCache hashers;
-
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) goto Error;
- }
- ClearBackwardRefs(refs);
- for (i = 0; i < pix_count;) {
- // Alternative#1: Code the pixels starting at 'i' using backward reference.
- int offset = 0;
- int len = 0;
- int j;
- HashChainFindCopy(hash_chain, i, &offset, &len);
- if (len > MIN_LENGTH + 1) {
- const int len_ini = len;
- int max_reach = 0;
- assert(i + len < pix_count);
- // Only start from what we have not checked already.
- i_last_check = (i > i_last_check) ? i : i_last_check;
- // We know the best match for the current pixel but we try to find the
- // best matches for the current pixel AND the next one combined.
- // The naive method would use the intervals:
- // [i,i+len) + [i+len, length of best match at i+len)
- // while we check if we can use:
- // [i,j) (where j<=i+len) + [j, length of best match at j)
- for (j = i_last_check + 1; j <= i + len_ini; ++j) {
- const int len_j = HashChainFindLength(hash_chain, j);
- const int reach =
- j + (len_j > MIN_LENGTH + 1 ? len_j : 1); // 1 for single literal.
- if (reach > max_reach) {
- len = j - i;
- max_reach = reach;
- }
- }
- } else {
- len = 1;
- }
- // Go with literal or backward reference.
- assert(len > 0);
- if (len == 1) {
- AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
- } else {
- BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
- if (use_color_cache) {
- for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]);
- }
- }
- i += len;
- }
-
- ok = !refs->error_;
- Error:
- if (cc_init) VP8LColorCacheClear(&hashers);
- return ok;
-}
-
-// -----------------------------------------------------------------------------
-
-typedef struct {
- double alpha_[VALUES_IN_BYTE];
- double red_[VALUES_IN_BYTE];
- double blue_[VALUES_IN_BYTE];
- double distance_[NUM_DISTANCE_CODES];
- double* literal_;
-} CostModel;
-
-static int BackwardReferencesTraceBackwards(
- int xsize, int ysize, const uint32_t* const argb, int quality,
- int cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs);
-
-static void ConvertPopulationCountTableToBitEstimates(
- 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) {
- 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 cache_bits,
- VP8LBackwardRefs* const refs) {
- int ok = 0;
- VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits);
- if (histo == NULL) goto Error;
-
- VP8LHistogramCreate(histo, refs, cache_bits);
-
- ConvertPopulationCountTableToBitEstimates(
- VP8LHistogramNumCodes(histo->palette_code_bits_),
- 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:
- VP8LFreeHistogram(histo);
- 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;
- 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;
- VP8LPrefixEncodeBits(distance, &code, &extra_bits);
- return m->distance_[code] + extra_bits;
-}
-
-static void AddSingleLiteralWithCostModel(const uint32_t* const argb,
- VP8LColorCache* const hashers,
- const CostModel* const cost_model,
- int idx, 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 (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.
- }
-}
-
-// -----------------------------------------------------------------------------
-// CostManager and interval handling
-
-// Empirical value to avoid high memory consumption but good for performance.
-#define COST_CACHE_INTERVAL_SIZE_MAX 100
-
-// To perform backward reference every pixel at index index_ is considered and
-// the cost for the MAX_LENGTH following pixels computed. Those following pixels
-// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of:
-// distance_cost_ at index_ + GetLengthCost(cost_model, k)
-// (named cost) (named cached cost)
-// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an
-// array of size MAX_LENGTH.
-// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the
-// minimal values using intervals, for which lower_ and upper_ bounds are kept.
-// An interval is defined by the index_ of the pixel that generated it and
-// is only useful in a range of indices from start_ to end_ (exclusive), i.e.
-// it contains the minimum value for pixels between start_ and end_.
-// Intervals are stored in a linked list and ordered by start_. When a new
-// interval has a better minimum, old intervals are split or removed.
-typedef struct CostInterval CostInterval;
-struct CostInterval {
- double lower_;
- double upper_;
- int start_;
- int end_;
- double distance_cost_;
- int index_;
- CostInterval* previous_;
- CostInterval* next_;
-};
-
-// The GetLengthCost(cost_model, k) part of the costs is also bounded for
-// efficiency in a set of intervals of a different type.
-// If those intervals are small enough, they are not used for comparison and
-// written into the costs right away.
-typedef struct {
- double lower_; // Lower bound of the interval.
- double upper_; // Upper bound of the interval.
- int start_;
- int end_; // Exclusive.
- int do_write_; // If !=0, the interval is saved to cost instead of being kept
- // for comparison.
-} CostCacheInterval;
-
-// This structure is in charge of managing intervals and costs.
-// It caches the different CostCacheInterval, caches the different
-// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose
-// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX).
-#define COST_MANAGER_MAX_FREE_LIST 10
-typedef struct {
- CostInterval* head_;
- int count_; // The number of stored intervals.
- CostCacheInterval* cache_intervals_;
- size_t cache_intervals_size_;
- double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k).
- double min_cost_cache_; // The minimum value in cost_cache_[1:].
- double max_cost_cache_; // The maximum value in cost_cache_[1:].
- float* costs_;
- uint16_t* dist_array_;
- // Most of the time, we only need few intervals -> use a free-list, to avoid
- // fragmentation with small allocs in most common cases.
- CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST];
- CostInterval* free_intervals_;
- // These are regularly malloc'd remains. This list can't grow larger than than
- // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note.
- CostInterval* recycled_intervals_;
- // Buffer used in BackwardReferencesHashChainDistanceOnly to store the ends
- // of the intervals that can have impacted the cost at a pixel.
- int* interval_ends_;
- int interval_ends_size_;
-} CostManager;
-
-static int IsCostCacheIntervalWritable(int start, int end) {
- // 100 is the length for which we consider an interval for comparison, and not
- // for writing.
- // The first intervals are very small and go in increasing size. This constant
- // helps merging them into one big interval (up to index 150/200 usually from
- // which intervals start getting much bigger).
- // This value is empirical.
- return (end - start + 1 < 100);
-}
-
-static void CostIntervalAddToFreeList(CostManager* const manager,
- CostInterval* const interval) {
- interval->next_ = manager->free_intervals_;
- manager->free_intervals_ = interval;
-}
-
-static int CostIntervalIsInFreeList(const CostManager* const manager,
- const CostInterval* const interval) {
- return (interval >= &manager->intervals_[0] &&
- interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]);
-}
-
-static void CostManagerInitFreeList(CostManager* const manager) {
- int i;
- manager->free_intervals_ = NULL;
- for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) {
- CostIntervalAddToFreeList(manager, &manager->intervals_[i]);
- }
-}
-
-static void DeleteIntervalList(CostManager* const manager,
- const CostInterval* interval) {
- while (interval != NULL) {
- const CostInterval* const next = interval->next_;
- if (!CostIntervalIsInFreeList(manager, interval)) {
- WebPSafeFree((void*)interval);
- } // else: do nothing
- interval = next;
- }
-}
-
-static void CostManagerClear(CostManager* const manager) {
- if (manager == NULL) return;
-
- WebPSafeFree(manager->costs_);
- WebPSafeFree(manager->cache_intervals_);
- WebPSafeFree(manager->interval_ends_);
-
- // Clear the interval lists.
- DeleteIntervalList(manager, manager->head_);
- manager->head_ = NULL;
- DeleteIntervalList(manager, manager->recycled_intervals_);
- manager->recycled_intervals_ = NULL;
-
- // Reset pointers, count_ and cache_intervals_size_.
- memset(manager, 0, sizeof(*manager));
- CostManagerInitFreeList(manager);
-}
-
-static int CostManagerInit(CostManager* const manager,
- uint16_t* const dist_array, int pix_count,
- const CostModel* const cost_model) {
- int i;
- const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count;
- // This constant is tied to the cost_model we use.
- // Empirically, differences between intervals is usually of more than 1.
- const double min_cost_diff = 0.1;
-
- manager->costs_ = NULL;
- manager->cache_intervals_ = NULL;
- manager->interval_ends_ = NULL;
- manager->head_ = NULL;
- manager->recycled_intervals_ = NULL;
- manager->count_ = 0;
- manager->dist_array_ = dist_array;
- CostManagerInitFreeList(manager);
-
- // Fill in the cost_cache_.
- manager->cache_intervals_size_ = 1;
- manager->cost_cache_[0] = 0;
- for (i = 1; i < cost_cache_size; ++i) {
- manager->cost_cache_[i] = GetLengthCost(cost_model, i);
- // Get an approximation of the number of bound intervals.
- if (fabs(manager->cost_cache_[i] - manager->cost_cache_[i - 1]) >
- min_cost_diff) {
- ++manager->cache_intervals_size_;
- }
- // Compute the minimum of cost_cache_.
- if (i == 1) {
- manager->min_cost_cache_ = manager->cost_cache_[1];
- manager->max_cost_cache_ = manager->cost_cache_[1];
- } else if (manager->cost_cache_[i] < manager->min_cost_cache_) {
- manager->min_cost_cache_ = manager->cost_cache_[i];
- } else if (manager->cost_cache_[i] > manager->max_cost_cache_) {
- manager->max_cost_cache_ = manager->cost_cache_[i];
- }
- }
-
- // With the current cost models, we have 15 intervals, so we are safe by
- // setting a maximum of COST_CACHE_INTERVAL_SIZE_MAX.
- if (manager->cache_intervals_size_ > COST_CACHE_INTERVAL_SIZE_MAX) {
- manager->cache_intervals_size_ = COST_CACHE_INTERVAL_SIZE_MAX;
- }
- manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc(
- manager->cache_intervals_size_, sizeof(*manager->cache_intervals_));
- if (manager->cache_intervals_ == NULL) {
- CostManagerClear(manager);
- return 0;
- }
-
- // Fill in the cache_intervals_.
- {
- double cost_prev = -1e38f; // unprobably low initial value
- CostCacheInterval* prev = NULL;
- CostCacheInterval* cur = manager->cache_intervals_;
- const CostCacheInterval* const end =
- manager->cache_intervals_ + manager->cache_intervals_size_;
-
- // Consecutive values in cost_cache_ are compared and if a big enough
- // difference is found, a new interval is created and bounded.
- for (i = 0; i < cost_cache_size; ++i) {
- const double cost_val = manager->cost_cache_[i];
- if (i == 0 ||
- (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end)) {
- if (i > 1) {
- const int is_writable =
- IsCostCacheIntervalWritable(cur->start_, cur->end_);
- // Merge with the previous interval if both are writable.
- if (is_writable && cur != manager->cache_intervals_ &&
- prev->do_write_) {
- // Update the previous interval.
- prev->end_ = cur->end_;
- if (cur->lower_ < prev->lower_) {
- prev->lower_ = cur->lower_;
- } else if (cur->upper_ > prev->upper_) {
- prev->upper_ = cur->upper_;
- }
- } else {
- cur->do_write_ = is_writable;
- prev = cur;
- ++cur;
- }
- }
- // Initialize an interval.
- cur->start_ = i;
- cur->do_write_ = 0;
- cur->lower_ = cost_val;
- cur->upper_ = cost_val;
- } else {
- // Update the current interval bounds.
- if (cost_val < cur->lower_) {
- cur->lower_ = cost_val;
- } else if (cost_val > cur->upper_) {
- cur->upper_ = cost_val;
- }
- }
- cur->end_ = i + 1;
- cost_prev = cost_val;
- }
- manager->cache_intervals_size_ = cur + 1 - manager->cache_intervals_;
- }
-
- manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_));
- if (manager->costs_ == NULL) {
- CostManagerClear(manager);
- return 0;
- }
- // Set the initial costs_ high for every pixel as we will keep the minimum.
- for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f;
-
- // The cost at pixel is influenced by the cost intervals from previous pixels.
- // Let us take the specific case where the offset is the same (which actually
- // happens a lot in case of uniform regions).
- // pixel i contributes to j>i a cost of: offset cost + cost_cache_[j-i]
- // pixel i+1 contributes to j>i a cost of: 2*offset cost + cost_cache_[j-i-1]
- // pixel i+2 contributes to j>i a cost of: 3*offset cost + cost_cache_[j-i-2]
- // and so on.
- // A pixel i influences the following length(j) < MAX_LENGTH pixels. What is
- // the value of j such that pixel i + j cannot influence any of those pixels?
- // This value is such that:
- // max of cost_cache_ < j*offset cost + min of cost_cache_
- // (pixel i + j 's cost cannot beat the worst cost given by pixel i).
- // This value will be used to optimize the cost computation in
- // BackwardReferencesHashChainDistanceOnly.
- {
- // The offset cost is computed in GetDistanceCost and has a minimum value of
- // the minimum in cost_model->distance_. The case where the offset cost is 0
- // will be dealt with differently later so we are only interested in the
- // minimum non-zero offset cost.
- double offset_cost_min = 0.;
- int size;
- for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
- if (cost_model->distance_[i] != 0) {
- if (offset_cost_min == 0.) {
- offset_cost_min = cost_model->distance_[i];
- } else if (cost_model->distance_[i] < offset_cost_min) {
- offset_cost_min = cost_model->distance_[i];
- }
- }
- }
- // In case all the cost_model->distance_ is 0, the next non-zero cost we
- // can have is from the extra bit in GetDistanceCost, hence 1.
- if (offset_cost_min < 1.) offset_cost_min = 1.;
-
- size = 1 + (int)ceil((manager->max_cost_cache_ - manager->min_cost_cache_) /
- offset_cost_min);
- // Empirically, we usually end up with a value below 100.
- if (size > MAX_LENGTH) size = MAX_LENGTH;
-
- manager->interval_ends_ =
- (int*)WebPSafeMalloc(size, sizeof(*manager->interval_ends_));
- if (manager->interval_ends_ == NULL) {
- CostManagerClear(manager);
- return 0;
- }
- manager->interval_ends_size_ = size;
- }
-
- return 1;
-}
-
-// Given the distance_cost for pixel 'index', update the cost at pixel 'i' if it
-// is smaller than the previously computed value.
-static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, int index,
- double distance_cost) {
- int k = i - index;
- double cost_tmp;
- assert(k >= 0 && k < MAX_LENGTH);
- cost_tmp = distance_cost + manager->cost_cache_[k];
-
- if (manager->costs_[i] > cost_tmp) {
- manager->costs_[i] = (float)cost_tmp;
- manager->dist_array_[i] = k + 1;
- }
-}
-
-// Given the distance_cost for pixel 'index', update the cost for all the pixels
-// between 'start' and 'end' excluded.
-static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager,
- int start, int end, int index,
- double distance_cost) {
- int i;
- for (i = start; i < end; ++i) UpdateCost(manager, i, index, distance_cost);
-}
-
-// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'.
-static WEBP_INLINE void ConnectIntervals(CostManager* const manager,
- CostInterval* const prev,
- CostInterval* const next) {
- if (prev != NULL) {
- prev->next_ = next;
- } else {
- manager->head_ = next;
- }
-
- if (next != NULL) next->previous_ = prev;
-}
-
-// Pop an interval in the manager.
-static WEBP_INLINE void PopInterval(CostManager* const manager,
- CostInterval* const interval) {
- CostInterval* const next = interval->next_;
-
- if (interval == NULL) return;
-
- ConnectIntervals(manager, interval->previous_, next);
- if (CostIntervalIsInFreeList(manager, interval)) {
- CostIntervalAddToFreeList(manager, interval);
- } else { // recycle regularly malloc'd intervals too
- interval->next_ = manager->recycled_intervals_;
- manager->recycled_intervals_ = interval;
- }
- --manager->count_;
- assert(manager->count_ >= 0);
-}
-
-// Update the cost at index i by going over all the stored intervals that
-// overlap with i.
-static WEBP_INLINE void UpdateCostPerIndex(CostManager* const manager, int i) {
- CostInterval* current = manager->head_;
-
- while (current != NULL && current->start_ <= i) {
- if (current->end_ <= i) {
- // We have an outdated interval, remove it.
- CostInterval* next = current->next_;
- PopInterval(manager, current);
- current = next;
- } else {
- UpdateCost(manager, i, current->index_, current->distance_cost_);
- current = current->next_;
- }
- }
-}
-
-// Given a current orphan interval and its previous interval, before
-// it was orphaned (which can be NULL), set it at the right place in the list
-// of intervals using the start_ ordering and the previous interval as a hint.
-static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager,
- CostInterval* const current,
- CostInterval* previous) {
- assert(current != NULL);
-
- if (previous == NULL) previous = manager->head_;
- while (previous != NULL && current->start_ < previous->start_) {
- previous = previous->previous_;
- }
- while (previous != NULL && previous->next_ != NULL &&
- previous->next_->start_ < current->start_) {
- previous = previous->next_;
- }
-
- if (previous != NULL) {
- ConnectIntervals(manager, current, previous->next_);
- } else {
- ConnectIntervals(manager, current, manager->head_);
- }
- ConnectIntervals(manager, previous, current);
-}
-
-// Insert an interval in the list contained in the manager by starting at
-// interval_in as a hint. The intervals are sorted by start_ value.
-static WEBP_INLINE void InsertInterval(CostManager* const manager,
- CostInterval* const interval_in,
- double distance_cost, double lower,
- double upper, int index, int start,
- int end) {
- CostInterval* interval_new;
-
- if (IsCostCacheIntervalWritable(start, end) ||
- manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) {
- // Write down the interval if it is too small.
- UpdateCostPerInterval(manager, start, end, index, distance_cost);
- return;
- }
- if (manager->free_intervals_ != NULL) {
- interval_new = manager->free_intervals_;
- manager->free_intervals_ = interval_new->next_;
- } else if (manager->recycled_intervals_ != NULL) {
- interval_new = manager->recycled_intervals_;
- manager->recycled_intervals_ = interval_new->next_;
- } else { // malloc for good
- interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new));
- if (interval_new == NULL) {
- // Write down the interval if we cannot create it.
- UpdateCostPerInterval(manager, start, end, index, distance_cost);
- return;
- }
- }
-
- interval_new->distance_cost_ = distance_cost;
- interval_new->lower_ = lower;
- interval_new->upper_ = upper;
- interval_new->index_ = index;
- interval_new->start_ = start;
- interval_new->end_ = end;
- PositionOrphanInterval(manager, interval_new, interval_in);
-
- ++manager->count_;
-}
-
-// When an interval has its start_ or end_ modified, it needs to be
-// repositioned in the linked list.
-static WEBP_INLINE void RepositionInterval(CostManager* const manager,
- CostInterval* const interval) {
- if (IsCostCacheIntervalWritable(interval->start_, interval->end_)) {
- // Maybe interval has been resized and is small enough to be removed.
- UpdateCostPerInterval(manager, interval->start_, interval->end_,
- interval->index_, interval->distance_cost_);
- PopInterval(manager, interval);
- return;
- }
-
- // Early exit if interval is at the right spot.
- if ((interval->previous_ == NULL ||
- interval->previous_->start_ <= interval->start_) &&
- (interval->next_ == NULL ||
- interval->start_ <= interval->next_->start_)) {
- return;
- }
-
- ConnectIntervals(manager, interval->previous_, interval->next_);
- PositionOrphanInterval(manager, interval, interval->previous_);
-}
-
-// Given a new cost interval defined by its start at index, its last value and
-// distance_cost, add its contributions to the previous intervals and costs.
-// If handling the interval or one of its subintervals becomes to heavy, its
-// contribution is added to the costs right away.
-static WEBP_INLINE void PushInterval(CostManager* const manager,
- double distance_cost, int index,
- int last) {
- size_t i;
- CostInterval* interval = manager->head_;
- CostInterval* interval_next;
- const CostCacheInterval* const cost_cache_intervals =
- manager->cache_intervals_;
-
- for (i = 0; i < manager->cache_intervals_size_ &&
- cost_cache_intervals[i].start_ < last;
- ++i) {
- // Define the intersection of the ith interval with the new one.
- int start = index + cost_cache_intervals[i].start_;
- const int end = index + (cost_cache_intervals[i].end_ > last
- ? last
- : cost_cache_intervals[i].end_);
- const double lower_in = cost_cache_intervals[i].lower_;
- const double upper_in = cost_cache_intervals[i].upper_;
- const double lower_full_in = distance_cost + lower_in;
- const double upper_full_in = distance_cost + upper_in;
-
- if (cost_cache_intervals[i].do_write_) {
- UpdateCostPerInterval(manager, start, end, index, distance_cost);
- continue;
- }
-
- for (; interval != NULL && interval->start_ < end && start < end;
- interval = interval_next) {
- const double lower_full_interval =
- interval->distance_cost_ + interval->lower_;
- const double upper_full_interval =
- interval->distance_cost_ + interval->upper_;
-
- interval_next = interval->next_;
-
- // Make sure we have some overlap
- if (start >= interval->end_) continue;
-
- if (lower_full_in >= upper_full_interval) {
- // When intervals are represented, the lower, the better.
- // [**********************************************************]
- // start end
- // [----------------------------------]
- // interval->start_ interval->end_
- // If we are worse than what we already have, add whatever we have so
- // far up to interval.
- const int start_new = interval->end_;
- InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
- index, start, interval->start_);
- start = start_new;
- continue;
- }
-
- // We know the two intervals intersect.
- if (upper_full_in >= lower_full_interval) {
- // There is no clear cut on which is best, so let's keep both.
- // [*********[*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*]***********]
- // start interval->start_ interval->end_ end
- // OR
- // [*********[*-*-*-*-*-*-*-*-*-*-*-]----------------------]
- // start interval->start_ end interval->end_
- const int end_new = (interval->end_ <= end) ? interval->end_ : end;
- InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
- index, start, end_new);
- start = end_new;
- } else if (start <= interval->start_ && interval->end_ <= end) {
- // [----------------------------------]
- // interval->start_ interval->end_
- // [**************************************************************]
- // start end
- // We can safely remove the old interval as it is fully included.
- PopInterval(manager, interval);
- } else {
- if (interval->start_ <= start && end <= interval->end_) {
- // [--------------------------------------------------------------]
- // interval->start_ interval->end_
- // [*****************************]
- // start end
- // We have to split the old interval as it fully contains the new one.
- const int end_original = interval->end_;
- interval->end_ = start;
- InsertInterval(manager, interval, interval->distance_cost_,
- interval->lower_, interval->upper_, interval->index_,
- end, end_original);
- } else if (interval->start_ < start) {
- // [------------------------------------]
- // interval->start_ interval->end_
- // [*****************************]
- // start end
- interval->end_ = start;
- } else {
- // [------------------------------------]
- // interval->start_ interval->end_
- // [*****************************]
- // start end
- interval->start_ = end;
- }
-
- // The interval has been modified, we need to reposition it or write it.
- RepositionInterval(manager, interval);
- }
- }
- // Insert the remaining interval from start to end.
- InsertInterval(manager, interval, distance_cost, lower_in, upper_in, index,
- start, end);
- }
-}
-
-static int BackwardReferencesHashChainDistanceOnly(
- int xsize, int ysize, const uint32_t* const argb, int quality,
- int cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs, uint16_t* const dist_array) {
- int i;
- int ok = 0;
- int cc_init = 0;
- const int pix_count = xsize * ysize;
- const int use_color_cache = (cache_bits > 0);
- 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*)WebPSafeCalloc(1ULL, cost_model_size);
- VP8LColorCache hashers;
- const int skip_length = 32 + quality;
- const int skip_min_distance_code = 2;
- CostManager* cost_manager =
- (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager));
-
- if (cost_model == NULL || cost_manager == 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, cache_bits, refs)) {
- goto Error;
- }
-
- if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) {
- goto Error;
- }
-
- // We loop one pixel at a time, but store all currently best points to
- // non-processed locations from this point.
- dist_array[0] = 0;
- // Add first pixel as literal.
- AddSingleLiteralWithCostModel(argb + 0, &hashers, cost_model, 0,
- use_color_cache, 0.0, cost_manager->costs_,
- dist_array);
-
- for (i = 1; i < pix_count - 1; ++i) {
- int offset = 0, len = 0;
- double prev_cost = cost_manager->costs_[i - 1];
- HashChainFindCopy(hash_chain, i, &offset, &len);
- if (len >= MIN_LENGTH) {
- const int code = DistanceToPlaneCode(xsize, offset);
- const double offset_cost = GetDistanceCost(cost_model, code);
- const int first_i = i;
- int j_max = 0, interval_ends_index = 0;
- const int is_offset_zero = (offset_cost == 0.);
-
- if (!is_offset_zero) {
- j_max = (int)ceil(
- (cost_manager->max_cost_cache_ - cost_manager->min_cost_cache_) /
- offset_cost);
- if (j_max < 1) {
- j_max = 1;
- } else if (j_max > cost_manager->interval_ends_size_ - 1) {
- // This could only happen in the case of MAX_LENGTH.
- j_max = cost_manager->interval_ends_size_ - 1;
- }
- } // else j_max is unused anyway.
-
- // Instead of considering all contributions from a pixel i by calling:
- // PushInterval(cost_manager, prev_cost + offset_cost, i, len);
- // we optimize these contributions in case offset_cost stays the same for
- // consecutive pixels. This describes a set of pixels similar to a
- // previous set (e.g. constant color regions).
- for (; i < pix_count - 1; ++i) {
- int offset_next, len_next;
- prev_cost = cost_manager->costs_[i - 1];
-
- if (is_offset_zero) {
- // No optimization can be made so we just push all of the
- // contributions from i.
- PushInterval(cost_manager, prev_cost, i, len);
- } else {
- // j_max is chosen as the smallest j such that:
- // max of cost_cache_ < j*offset cost + min of cost_cache_
- // Therefore, the pixel influenced by i-j_max, cannot be influenced
- // by i. Only the costs after the end of what i contributed need to be
- // updated. cost_manager->interval_ends_ is a circular buffer that
- // stores those ends.
- const double distance_cost = prev_cost + offset_cost;
- int j = cost_manager->interval_ends_[interval_ends_index];
- if (i - first_i <= j_max ||
- !IsCostCacheIntervalWritable(j, i + len)) {
- PushInterval(cost_manager, distance_cost, i, len);
- } else {
- for (; j < i + len; ++j) {
- UpdateCost(cost_manager, j, i, distance_cost);
- }
- }
- // Store the new end in the circular buffer.
- assert(interval_ends_index < cost_manager->interval_ends_size_);
- cost_manager->interval_ends_[interval_ends_index] = i + len;
- if (++interval_ends_index > j_max) interval_ends_index = 0;
- }
-
- // Check whether i is the last pixel to consider, as it is handled
- // differently.
- if (i + 1 >= pix_count - 1) break;
- HashChainFindCopy(hash_chain, i + 1, &offset_next, &len_next);
- if (offset_next != offset) break;
- len = len_next;
- UpdateCostPerIndex(cost_manager, i);
- AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
- use_color_cache, prev_cost,
- cost_manager->costs_, dist_array);
- }
- // Submit the last pixel.
- UpdateCostPerIndex(cost_manager, i + 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) {
- int k;
- for (k = 0; k < len; ++k) {
- VP8LColorCacheInsert(&hashers, argb[i + k]);
- }
- }
- // 2) jump.
- {
- const int i_next = i + len - 1; // for loop does ++i, thus -1 here.
- for (; i <= i_next; ++i) UpdateCostPerIndex(cost_manager, i + 1);
- i = i_next;
- }
- goto next_symbol;
- }
- if (len > MIN_LENGTH) {
- int code_min_length;
- double cost_total;
- offset = HashChainFindOffset(hash_chain, i);
- code_min_length = DistanceToPlaneCode(xsize, offset);
- cost_total = prev_cost +
- GetDistanceCost(cost_model, code_min_length) +
- GetLengthCost(cost_model, 1);
- if (cost_manager->costs_[i + 1] > cost_total) {
- cost_manager->costs_[i + 1] = (float)cost_total;
- dist_array[i + 1] = 2;
- }
- }
- } else { // len < MIN_LENGTH
- UpdateCostPerIndex(cost_manager, i + 1);
- }
-
- AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
- use_color_cache, prev_cost,
- cost_manager->costs_, dist_array);
-
- next_symbol: ;
- }
- // Handle the last pixel.
- if (i == (pix_count - 1)) {
- AddSingleLiteralWithCostModel(
- argb + i, &hashers, cost_model, i, use_color_cache,
- cost_manager->costs_[pix_count - 2], cost_manager->costs_, dist_array);
- }
-
- ok = !refs->error_;
- Error:
- if (cc_init) VP8LColorCacheClear(&hashers);
- CostManagerClear(cost_manager);
- WebPSafeFree(cost_model);
- WebPSafeFree(cost_manager);
- return ok;
-}
-
-// 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;
- }
- *chosen_path = path;
- *chosen_path_size = (int)(dist_array + dist_array_size - path);
-}
-
-static int BackwardReferencesHashChainFollowChosenPath(
- const uint32_t* const argb, int cache_bits,
- const uint16_t* const chosen_path, int chosen_path_size,
- const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) {
- const int use_color_cache = (cache_bits > 0);
- int ix;
- int i = 0;
- int ok = 0;
- int cc_init = 0;
- VP8LColorCache hashers;
-
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) goto Error;
- }
-
- ClearBackwardRefs(refs);
- for (ix = 0; ix < chosen_path_size; ++ix) {
- const int len = chosen_path[ix];
- if (len != 1) {
- int k;
- const int offset = HashChainFindOffset(hash_chain, i);
- BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
- if (use_color_cache) {
- for (k = 0; k < len; ++k) {
- VP8LColorCacheInsert(&hashers, argb[i + k]);
- }
- }
- 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]);
- v = PixOrCopyCreateCacheIdx(idx);
- } else {
- if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
- v = PixOrCopyCreateLiteral(argb[i]);
- }
- BackwardRefsCursorAdd(refs, v);
- ++i;
- }
- }
- ok = !refs->error_;
- Error:
- if (cc_init) VP8LColorCacheClear(&hashers);
- return ok;
-}
-
-// Returns 1 on success.
-static int BackwardReferencesTraceBackwards(
- int xsize, int ysize, const uint32_t* const argb, int quality,
- int cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs* const refs) {
- int ok = 0;
- const int dist_array_size = xsize * ysize;
- uint16_t* chosen_path = NULL;
- int chosen_path_size = 0;
- uint16_t* dist_array =
- (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array));
-
- if (dist_array == NULL) goto Error;
-
- if (!BackwardReferencesHashChainDistanceOnly(
- xsize, ysize, argb, quality, cache_bits, hash_chain,
- refs, dist_array)) {
- goto Error;
- }
- TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size);
- if (!BackwardReferencesHashChainFollowChosenPath(
- argb, cache_bits, chosen_path, chosen_path_size, hash_chain, refs)) {
- goto Error;
- }
- ok = 1;
- Error:
- WebPSafeFree(dist_array);
- return ok;
-}
-
-static void BackwardReferences2DLocality(int xsize,
- 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);
- c.cur_pos->argb_or_distance = transformed_dist;
- }
- VP8LRefsCursorNext(&c);
- }
-}
-
-// 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;
-
- if (use_color_cache) {
- cc_init = VP8LColorCacheInit(&hashers, cache_bits);
- if (!cc_init) goto Error;
- }
- if (!use_color_cache) {
- while (VP8LRefsCursorOk(&c)) {
- VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
- VP8LRefsCursorNext(&c);
- }
- } else {
- 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;
-}
-
-// 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,
- const 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;
- }
- if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, 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;
-}
-
-// 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;
- VP8LColorCache hashers;
- VP8LRefsCursor c = VP8LRefsCursorInit(refs);
- if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0;
-
- while (VP8LRefsCursorOk(&c)) {
- PixOrCopy* const v = c.cur_pos;
- if (PixOrCopyIsLiteral(v)) {
- 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 {
- VP8LColorCacheInsert(&hashers, argb_literal);
- }
- ++pixel_index;
- } else {
- // 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++]);
- }
- }
- VP8LRefsCursorNext(&c);
- }
- VP8LColorCacheClear(&hashers);
- return 1;
-}
-
-static VP8LBackwardRefs* GetBackwardReferencesLowEffort(
- int width, int height, const uint32_t* const argb,
- int* const cache_bits, const VP8LHashChain* const hash_chain,
- VP8LBackwardRefs refs_array[2]) {
- VP8LBackwardRefs* refs_lz77 = &refs_array[0];
- *cache_bits = 0;
- if (!BackwardReferencesLz77(width, height, argb, 0, 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, const 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;
- }
-
- 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, hash_chain,
- refs_lz77)) {
- goto Error;
- }
- }
-
- 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:
- VP8LFreeHistogram(histo);
- return best;
-}
-
-VP8LBackwardRefs* VP8LGetBackwardReferences(
- int width, int height, const uint32_t* const argb, int quality,
- int low_effort, int* const cache_bits,
- const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[2]) {
- if (low_effort) {
- return GetBackwardReferencesLowEffort(width, height, argb, cache_bits,
- hash_chain, refs_array);
- } else {
- return GetBackwardReferences(width, height, argb, quality, cache_bits,
- hash_chain, refs_array);
- }
-}
diff --git a/thirdparty/libwebp/enc/backward_references.h b/thirdparty/libwebp/enc/backward_references.h
deleted file mode 100644
index 0cadb11e11..0000000000
--- a/thirdparty/libwebp/enc/backward_references.h
+++ /dev/null
@@ -1,206 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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 "../webp/types.h"
-#include "../webp/format_constants.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// The maximum allowed limit is 11.
-#define MAX_COLOR_CACHE_BITS 10
-
-// -----------------------------------------------------------------------------
-// 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;
-}
-
-// -----------------------------------------------------------------------------
-// VP8LHashChain
-
-#define HASH_BITS 18
-#define HASH_SIZE (1 << HASH_BITS)
-
-typedef struct VP8LHashChain VP8LHashChain;
-struct VP8LHashChain {
- // The 20 most significant bits contain the offset at which the best match
- // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain
- // (through WINDOW_SIZE = 1<<20).
- // The lower 12 bits contain the length of the match. The 12 bit limit is
- // defined in MaxFindCopyLength with MAX_LENGTH=4096.
- uint32_t* offset_length_;
- // 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_;
-};
-
-// Must be called first, to set size.
-int VP8LHashChainInit(VP8LHashChain* const p, int size);
-// Pre-compute the best matches for argb.
-int VP8LHashChainFill(VP8LHashChain* const p, int quality,
- const uint32_t* const argb, int xsize, int ysize);
-void VP8LHashChainClear(VP8LHashChain* const p); // release memory
-
-// -----------------------------------------------------------------------------
-// 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)
-};
-
-// 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);
-
-// 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.
-// 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,
- const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // WEBP_ENC_BACKWARD_REFERENCES_H_
diff --git a/thirdparty/libwebp/enc/backward_references_enc.c b/thirdparty/libwebp/enc/backward_references_enc.c
new file mode 100644
index 0000000000..7c0559ff1e
--- /dev/null
+++ b/thirdparty/libwebp/enc/backward_references_enc.c
@@ -0,0 +1,1800 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+
+#include <assert.h>
+#include <math.h>
+
+#include "./backward_references_enc.h"
+#include "./histogram_enc.h"
+#include "../dsp/lossless.h"
+#include "../dsp/lossless_common.h"
+#include "../dsp/dsp.h"
+#include "../utils/color_cache_utils.h"
+#include "../utils/utils.h"
+
+#define VALUES_IN_BYTE 256
+
+#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_BITS 20
+#define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120)
+
+// Minimum number of pixels for which it is cheaper to encode a
+// distance + length instead of each pixel as a literal.
+#define MIN_LENGTH 4
+// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it
+// is used in VP8LHashChain.
+#define MAX_LENGTH_BITS 12
+// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits.
+#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1)
+#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32
+#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32"
+#endif
+
+// -----------------------------------------------------------------------------
+
+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;
+}
+
+// Returns the exact index where array1 and array2 are different. For an index
+// inferior or equal to best_len_match, the return value just has to be strictly
+// inferior to best_len_match. The current behavior is to return 0 if this index
+// is best_len_match, and the index itself otherwise.
+// If no two elements are the same, it returns max_limit.
+static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
+ const uint32_t* const array2,
+ int best_len_match, int max_limit) {
+ // 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;
+
+ return VP8LVectorMismatch(array1, array2, max_limit);
+}
+
+// -----------------------------------------------------------------------------
+// VP8LBackwardRefs
+
+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 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;
+ }
+}
+
+void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) {
+ assert(refs != NULL);
+ 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
+
+int VP8LHashChainInit(VP8LHashChain* const p, int size) {
+ assert(p->size_ == 0);
+ assert(p->offset_length_ == NULL);
+ assert(size > 0);
+ p->offset_length_ =
+ (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_));
+ if (p->offset_length_ == NULL) return 0;
+ p->size_ = size;
+
+ return 1;
+}
+
+void VP8LHashChainClear(VP8LHashChain* const p) {
+ assert(p != NULL);
+ WebPSafeFree(p->offset_length_);
+
+ p->size_ = 0;
+ p->offset_length_ = NULL;
+}
+
+// -----------------------------------------------------------------------------
+
+#define HASH_MULTIPLIER_HI (0xc6a4a793ULL)
+#define HASH_MULTIPLIER_LO (0x5bd1e996ULL)
+
+static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) {
+ uint32_t key;
+ key = (argb[1] * HASH_MULTIPLIER_HI) & 0xffffffffu;
+ key += (argb[0] * HASH_MULTIPLIER_LO) & 0xffffffffu;
+ key = key >> (32 - HASH_BITS);
+ return key;
+}
+
+// Returns the maximum number of hash chain lookups to do for a
+// given compression quality. Return value in range [8, 86].
+static int GetMaxItersForQuality(int quality) {
+ return 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;
+}
+
+int VP8LHashChainFill(VP8LHashChain* const p, int quality,
+ const uint32_t* const argb, int xsize, int ysize,
+ int low_effort) {
+ const int size = xsize * ysize;
+ const int iter_max = GetMaxItersForQuality(quality);
+ const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize);
+ int pos;
+ int argb_comp;
+ uint32_t base_position;
+ int32_t* hash_to_first_index;
+ // Temporarily use the p->offset_length_ as a hash chain.
+ int32_t* chain = (int32_t*)p->offset_length_;
+ assert(size > 0);
+ assert(p->size_ != 0);
+ assert(p->offset_length_ != NULL);
+
+ if (size <= 2) {
+ p->offset_length_[0] = p->offset_length_[size - 1] = 0;
+ return 1;
+ }
+
+ hash_to_first_index =
+ (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index));
+ if (hash_to_first_index == NULL) return 0;
+
+ // Set the int32_t array to -1.
+ memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index));
+ // Fill the chain linking pixels with the same hash.
+ argb_comp = (argb[0] == argb[1]);
+ for (pos = 0; pos < size - 2;) {
+ uint32_t hash_code;
+ const int argb_comp_next = (argb[pos + 1] == argb[pos + 2]);
+ if (argb_comp && argb_comp_next) {
+ // Consecutive pixels with the same color will share the same hash.
+ // We therefore use a different hash: the color and its repetition
+ // length.
+ uint32_t tmp[2];
+ uint32_t len = 1;
+ tmp[0] = argb[pos];
+ // Figure out how far the pixels are the same.
+ // The last pixel has a different 64 bit hash, as its next pixel does
+ // not have the same color, so we just need to get to the last pixel equal
+ // to its follower.
+ while (pos + (int)len + 2 < size && argb[pos + len + 2] == argb[pos]) {
+ ++len;
+ }
+ if (len > MAX_LENGTH) {
+ // Skip the pixels that match for distance=1 and length>MAX_LENGTH
+ // because they are linked to their predecessor and we automatically
+ // check that in the main for loop below. Skipping means setting no
+ // predecessor in the chain, hence -1.
+ memset(chain + pos, 0xff, (len - MAX_LENGTH) * sizeof(*chain));
+ pos += len - MAX_LENGTH;
+ len = MAX_LENGTH;
+ }
+ // Process the rest of the hash chain.
+ while (len) {
+ tmp[1] = len--;
+ hash_code = GetPixPairHash64(tmp);
+ chain[pos] = hash_to_first_index[hash_code];
+ hash_to_first_index[hash_code] = pos++;
+ }
+ argb_comp = 0;
+ } else {
+ // Just move one pixel forward.
+ hash_code = GetPixPairHash64(argb + pos);
+ chain[pos] = hash_to_first_index[hash_code];
+ hash_to_first_index[hash_code] = pos++;
+ argb_comp = argb_comp_next;
+ }
+ }
+ // Process the penultimate pixel.
+ chain[pos] = hash_to_first_index[GetPixPairHash64(argb + pos)];
+
+ WebPSafeFree(hash_to_first_index);
+
+ // Find the best match interval at each pixel, defined by an offset to the
+ // pixel and a length. The right-most pixel cannot match anything to the right
+ // (hence a best length of 0) and the left-most pixel nothing to the left
+ // (hence an offset of 0).
+ assert(size > 2);
+ p->offset_length_[0] = p->offset_length_[size - 1] = 0;
+ for (base_position = size - 2; base_position > 0;) {
+ const int max_len = MaxFindCopyLength(size - 1 - base_position);
+ const uint32_t* const argb_start = argb + base_position;
+ int iter = iter_max;
+ int best_length = 0;
+ uint32_t best_distance = 0;
+ uint32_t best_argb;
+ const int min_pos =
+ (base_position > window_size) ? base_position - window_size : 0;
+ const int length_max = (max_len < 256) ? max_len : 256;
+ uint32_t max_base_position;
+
+ pos = chain[base_position];
+ if (!low_effort) {
+ int curr_length;
+ // Heuristic: use the comparison with the above line as an initialization.
+ if (base_position >= (uint32_t)xsize) {
+ curr_length = FindMatchLength(argb_start - xsize, argb_start,
+ best_length, max_len);
+ if (curr_length > best_length) {
+ best_length = curr_length;
+ best_distance = xsize;
+ }
+ --iter;
+ }
+ // Heuristic: compare to the previous pixel.
+ curr_length =
+ FindMatchLength(argb_start - 1, argb_start, best_length, max_len);
+ if (curr_length > best_length) {
+ best_length = curr_length;
+ best_distance = 1;
+ }
+ --iter;
+ // Skip the for loop if we already have the maximum.
+ if (best_length == MAX_LENGTH) pos = min_pos - 1;
+ }
+ best_argb = argb_start[best_length];
+
+ for (; pos >= min_pos && --iter; pos = chain[pos]) {
+ int curr_length;
+ assert(base_position > (uint32_t)pos);
+
+ if (argb[pos + best_length] != best_argb) continue;
+
+ curr_length = VP8LVectorMismatch(argb + pos, argb_start, max_len);
+ if (best_length < curr_length) {
+ best_length = curr_length;
+ best_distance = base_position - pos;
+ best_argb = argb_start[best_length];
+ // Stop if we have reached a good enough length.
+ if (best_length >= length_max) break;
+ }
+ }
+ // We have the best match but in case the two intervals continue matching
+ // to the left, we have the best matches for the left-extended pixels.
+ max_base_position = base_position;
+ while (1) {
+ assert(best_length <= MAX_LENGTH);
+ assert(best_distance <= WINDOW_SIZE);
+ p->offset_length_[base_position] =
+ (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length;
+ --base_position;
+ // Stop if we don't have a match or if we are out of bounds.
+ if (best_distance == 0 || base_position == 0) break;
+ // Stop if we cannot extend the matching intervals to the left.
+ if (base_position < best_distance ||
+ argb[base_position - best_distance] != argb[base_position]) {
+ break;
+ }
+ // Stop if we are matching at its limit because there could be a closer
+ // matching interval with the same maximum length. Then again, if the
+ // matching interval is as close as possible (best_distance == 1), we will
+ // never find anything better so let's continue.
+ if (best_length == MAX_LENGTH && best_distance != 1 &&
+ base_position + MAX_LENGTH < max_base_position) {
+ break;
+ }
+ if (best_length < MAX_LENGTH) {
+ ++best_length;
+ max_base_position = base_position;
+ }
+ }
+ }
+ return 1;
+}
+
+static WEBP_INLINE int HashChainFindOffset(const VP8LHashChain* const p,
+ const int base_position) {
+ return p->offset_length_[base_position] >> MAX_LENGTH_BITS;
+}
+
+static WEBP_INLINE int HashChainFindLength(const VP8LHashChain* const p,
+ const int base_position) {
+ return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1);
+}
+
+static WEBP_INLINE void HashChainFindCopy(const VP8LHashChain* const p,
+ int base_position,
+ int* const offset_ptr,
+ int* const length_ptr) {
+ *offset_ptr = HashChainFindOffset(p, base_position);
+ *length_ptr = HashChainFindLength(p, base_position);
+}
+
+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);
+ }
+ BackwardRefsCursorAdd(refs, v);
+}
+
+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 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 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 >= MIN_LENGTH) {
+ 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 >= MIN_LENGTH) {
+ 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 {
+ AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
+ i++;
+ }
+ }
+ if (use_color_cache) VP8LColorCacheClear(&hashers);
+ return !refs->error_;
+}
+
+static int BackwardReferencesLz77(int xsize, int ysize,
+ const uint32_t* const argb, int cache_bits,
+ const VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs) {
+ int i;
+ int i_last_check = -1;
+ int ok = 0;
+ int cc_init = 0;
+ const int use_color_cache = (cache_bits > 0);
+ const int pix_count = xsize * ysize;
+ VP8LColorCache hashers;
+
+ if (use_color_cache) {
+ cc_init = VP8LColorCacheInit(&hashers, cache_bits);
+ if (!cc_init) goto Error;
+ }
+ ClearBackwardRefs(refs);
+ for (i = 0; i < pix_count;) {
+ // Alternative#1: Code the pixels starting at 'i' using backward reference.
+ int offset = 0;
+ int len = 0;
+ int j;
+ HashChainFindCopy(hash_chain, i, &offset, &len);
+ if (len >= MIN_LENGTH) {
+ const int len_ini = len;
+ int max_reach = 0;
+ assert(i + len < pix_count);
+ // Only start from what we have not checked already.
+ i_last_check = (i > i_last_check) ? i : i_last_check;
+ // We know the best match for the current pixel but we try to find the
+ // best matches for the current pixel AND the next one combined.
+ // The naive method would use the intervals:
+ // [i,i+len) + [i+len, length of best match at i+len)
+ // while we check if we can use:
+ // [i,j) (where j<=i+len) + [j, length of best match at j)
+ for (j = i_last_check + 1; j <= i + len_ini; ++j) {
+ const int len_j = HashChainFindLength(hash_chain, j);
+ const int reach =
+ j + (len_j >= MIN_LENGTH ? len_j : 1); // 1 for single literal.
+ if (reach > max_reach) {
+ len = j - i;
+ max_reach = reach;
+ }
+ }
+ } else {
+ len = 1;
+ }
+ // Go with literal or backward reference.
+ assert(len > 0);
+ if (len == 1) {
+ AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
+ } else {
+ BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
+ if (use_color_cache) {
+ for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]);
+ }
+ }
+ i += len;
+ }
+
+ ok = !refs->error_;
+ Error:
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ return ok;
+}
+
+// -----------------------------------------------------------------------------
+
+typedef struct {
+ double alpha_[VALUES_IN_BYTE];
+ double red_[VALUES_IN_BYTE];
+ double blue_[VALUES_IN_BYTE];
+ double distance_[NUM_DISTANCE_CODES];
+ double* literal_;
+} CostModel;
+
+static int BackwardReferencesTraceBackwards(
+ int xsize, int ysize, const uint32_t* const argb, int quality,
+ int cache_bits, const VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs);
+
+static void ConvertPopulationCountTableToBitEstimates(
+ 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) {
+ 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 cache_bits,
+ VP8LBackwardRefs* const refs) {
+ int ok = 0;
+ VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits);
+ if (histo == NULL) goto Error;
+
+ VP8LHistogramCreate(histo, refs, cache_bits);
+
+ ConvertPopulationCountTableToBitEstimates(
+ VP8LHistogramNumCodes(histo->palette_code_bits_),
+ 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:
+ VP8LFreeHistogram(histo);
+ 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;
+ 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;
+ VP8LPrefixEncodeBits(distance, &code, &extra_bits);
+ return m->distance_[code] + extra_bits;
+}
+
+static void AddSingleLiteralWithCostModel(const uint32_t* const argb,
+ VP8LColorCache* const hashers,
+ const CostModel* const cost_model,
+ int idx, 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];
+ const int ix = use_color_cache ? VP8LColorCacheContains(hashers, color) : -1;
+ if (ix >= 0) {
+ // use_color_cache is true and hashers contains color
+ const double mul0 = 0.68;
+ 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.
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CostManager and interval handling
+
+// Empirical value to avoid high memory consumption but good for performance.
+#define COST_CACHE_INTERVAL_SIZE_MAX 100
+
+// To perform backward reference every pixel at index index_ is considered and
+// the cost for the MAX_LENGTH following pixels computed. Those following pixels
+// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of:
+// distance_cost_ at index_ + GetLengthCost(cost_model, k)
+// (named cost) (named cached cost)
+// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an
+// array of size MAX_LENGTH.
+// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the
+// minimal values using intervals, for which lower_ and upper_ bounds are kept.
+// An interval is defined by the index_ of the pixel that generated it and
+// is only useful in a range of indices from start_ to end_ (exclusive), i.e.
+// it contains the minimum value for pixels between start_ and end_.
+// Intervals are stored in a linked list and ordered by start_. When a new
+// interval has a better minimum, old intervals are split or removed.
+typedef struct CostInterval CostInterval;
+struct CostInterval {
+ double lower_;
+ double upper_;
+ int start_;
+ int end_;
+ double distance_cost_;
+ int index_;
+ CostInterval* previous_;
+ CostInterval* next_;
+};
+
+// The GetLengthCost(cost_model, k) part of the costs is also bounded for
+// efficiency in a set of intervals of a different type.
+// If those intervals are small enough, they are not used for comparison and
+// written into the costs right away.
+typedef struct {
+ double lower_; // Lower bound of the interval.
+ double upper_; // Upper bound of the interval.
+ int start_;
+ int end_; // Exclusive.
+ int do_write_; // If !=0, the interval is saved to cost instead of being kept
+ // for comparison.
+} CostCacheInterval;
+
+// This structure is in charge of managing intervals and costs.
+// It caches the different CostCacheInterval, caches the different
+// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose
+// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX).
+#define COST_MANAGER_MAX_FREE_LIST 10
+typedef struct {
+ CostInterval* head_;
+ int count_; // The number of stored intervals.
+ CostCacheInterval* cache_intervals_;
+ size_t cache_intervals_size_;
+ double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k).
+ double min_cost_cache_; // The minimum value in cost_cache_[1:].
+ double max_cost_cache_; // The maximum value in cost_cache_[1:].
+ float* costs_;
+ uint16_t* dist_array_;
+ // Most of the time, we only need few intervals -> use a free-list, to avoid
+ // fragmentation with small allocs in most common cases.
+ CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST];
+ CostInterval* free_intervals_;
+ // These are regularly malloc'd remains. This list can't grow larger than than
+ // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note.
+ CostInterval* recycled_intervals_;
+ // Buffer used in BackwardReferencesHashChainDistanceOnly to store the ends
+ // of the intervals that can have impacted the cost at a pixel.
+ int* interval_ends_;
+ int interval_ends_size_;
+} CostManager;
+
+static int IsCostCacheIntervalWritable(int start, int end) {
+ // 100 is the length for which we consider an interval for comparison, and not
+ // for writing.
+ // The first intervals are very small and go in increasing size. This constant
+ // helps merging them into one big interval (up to index 150/200 usually from
+ // which intervals start getting much bigger).
+ // This value is empirical.
+ return (end - start + 1 < 100);
+}
+
+static void CostIntervalAddToFreeList(CostManager* const manager,
+ CostInterval* const interval) {
+ interval->next_ = manager->free_intervals_;
+ manager->free_intervals_ = interval;
+}
+
+static int CostIntervalIsInFreeList(const CostManager* const manager,
+ const CostInterval* const interval) {
+ return (interval >= &manager->intervals_[0] &&
+ interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]);
+}
+
+static void CostManagerInitFreeList(CostManager* const manager) {
+ int i;
+ manager->free_intervals_ = NULL;
+ for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) {
+ CostIntervalAddToFreeList(manager, &manager->intervals_[i]);
+ }
+}
+
+static void DeleteIntervalList(CostManager* const manager,
+ const CostInterval* interval) {
+ while (interval != NULL) {
+ const CostInterval* const next = interval->next_;
+ if (!CostIntervalIsInFreeList(manager, interval)) {
+ WebPSafeFree((void*)interval);
+ } // else: do nothing
+ interval = next;
+ }
+}
+
+static void CostManagerClear(CostManager* const manager) {
+ if (manager == NULL) return;
+
+ WebPSafeFree(manager->costs_);
+ WebPSafeFree(manager->cache_intervals_);
+ WebPSafeFree(manager->interval_ends_);
+
+ // Clear the interval lists.
+ DeleteIntervalList(manager, manager->head_);
+ manager->head_ = NULL;
+ DeleteIntervalList(manager, manager->recycled_intervals_);
+ manager->recycled_intervals_ = NULL;
+
+ // Reset pointers, count_ and cache_intervals_size_.
+ memset(manager, 0, sizeof(*manager));
+ CostManagerInitFreeList(manager);
+}
+
+static int CostManagerInit(CostManager* const manager,
+ uint16_t* const dist_array, int pix_count,
+ const CostModel* const cost_model) {
+ int i;
+ const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count;
+ // This constant is tied to the cost_model we use.
+ // Empirically, differences between intervals is usually of more than 1.
+ const double min_cost_diff = 0.1;
+
+ manager->costs_ = NULL;
+ manager->cache_intervals_ = NULL;
+ manager->interval_ends_ = NULL;
+ manager->head_ = NULL;
+ manager->recycled_intervals_ = NULL;
+ manager->count_ = 0;
+ manager->dist_array_ = dist_array;
+ CostManagerInitFreeList(manager);
+
+ // Fill in the cost_cache_.
+ manager->cache_intervals_size_ = 1;
+ manager->cost_cache_[0] = 0;
+ for (i = 1; i < cost_cache_size; ++i) {
+ manager->cost_cache_[i] = GetLengthCost(cost_model, i);
+ // Get an approximation of the number of bound intervals.
+ if (fabs(manager->cost_cache_[i] - manager->cost_cache_[i - 1]) >
+ min_cost_diff) {
+ ++manager->cache_intervals_size_;
+ }
+ // Compute the minimum of cost_cache_.
+ if (i == 1) {
+ manager->min_cost_cache_ = manager->cost_cache_[1];
+ manager->max_cost_cache_ = manager->cost_cache_[1];
+ } else if (manager->cost_cache_[i] < manager->min_cost_cache_) {
+ manager->min_cost_cache_ = manager->cost_cache_[i];
+ } else if (manager->cost_cache_[i] > manager->max_cost_cache_) {
+ manager->max_cost_cache_ = manager->cost_cache_[i];
+ }
+ }
+
+ // With the current cost models, we have 15 intervals, so we are safe by
+ // setting a maximum of COST_CACHE_INTERVAL_SIZE_MAX.
+ if (manager->cache_intervals_size_ > COST_CACHE_INTERVAL_SIZE_MAX) {
+ manager->cache_intervals_size_ = COST_CACHE_INTERVAL_SIZE_MAX;
+ }
+ manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc(
+ manager->cache_intervals_size_, sizeof(*manager->cache_intervals_));
+ if (manager->cache_intervals_ == NULL) {
+ CostManagerClear(manager);
+ return 0;
+ }
+
+ // Fill in the cache_intervals_.
+ {
+ double cost_prev = -1e38f; // unprobably low initial value
+ CostCacheInterval* prev = NULL;
+ CostCacheInterval* cur = manager->cache_intervals_;
+ const CostCacheInterval* const end =
+ manager->cache_intervals_ + manager->cache_intervals_size_;
+
+ // Consecutive values in cost_cache_ are compared and if a big enough
+ // difference is found, a new interval is created and bounded.
+ for (i = 0; i < cost_cache_size; ++i) {
+ const double cost_val = manager->cost_cache_[i];
+ if (i == 0 ||
+ (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end)) {
+ if (i > 1) {
+ const int is_writable =
+ IsCostCacheIntervalWritable(cur->start_, cur->end_);
+ // Merge with the previous interval if both are writable.
+ if (is_writable && cur != manager->cache_intervals_ &&
+ prev->do_write_) {
+ // Update the previous interval.
+ prev->end_ = cur->end_;
+ if (cur->lower_ < prev->lower_) {
+ prev->lower_ = cur->lower_;
+ } else if (cur->upper_ > prev->upper_) {
+ prev->upper_ = cur->upper_;
+ }
+ } else {
+ cur->do_write_ = is_writable;
+ prev = cur;
+ ++cur;
+ }
+ }
+ // Initialize an interval.
+ cur->start_ = i;
+ cur->do_write_ = 0;
+ cur->lower_ = cost_val;
+ cur->upper_ = cost_val;
+ } else {
+ // Update the current interval bounds.
+ if (cost_val < cur->lower_) {
+ cur->lower_ = cost_val;
+ } else if (cost_val > cur->upper_) {
+ cur->upper_ = cost_val;
+ }
+ }
+ cur->end_ = i + 1;
+ cost_prev = cost_val;
+ }
+ manager->cache_intervals_size_ = cur + 1 - manager->cache_intervals_;
+ }
+
+ manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_));
+ if (manager->costs_ == NULL) {
+ CostManagerClear(manager);
+ return 0;
+ }
+ // Set the initial costs_ high for every pixel as we will keep the minimum.
+ for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f;
+
+ // The cost at pixel is influenced by the cost intervals from previous pixels.
+ // Let us take the specific case where the offset is the same (which actually
+ // happens a lot in case of uniform regions).
+ // pixel i contributes to j>i a cost of: offset cost + cost_cache_[j-i]
+ // pixel i+1 contributes to j>i a cost of: 2*offset cost + cost_cache_[j-i-1]
+ // pixel i+2 contributes to j>i a cost of: 3*offset cost + cost_cache_[j-i-2]
+ // and so on.
+ // A pixel i influences the following length(j) < MAX_LENGTH pixels. What is
+ // the value of j such that pixel i + j cannot influence any of those pixels?
+ // This value is such that:
+ // max of cost_cache_ < j*offset cost + min of cost_cache_
+ // (pixel i + j 's cost cannot beat the worst cost given by pixel i).
+ // This value will be used to optimize the cost computation in
+ // BackwardReferencesHashChainDistanceOnly.
+ {
+ // The offset cost is computed in GetDistanceCost and has a minimum value of
+ // the minimum in cost_model->distance_. The case where the offset cost is 0
+ // will be dealt with differently later so we are only interested in the
+ // minimum non-zero offset cost.
+ double offset_cost_min = 0.;
+ int size;
+ for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
+ if (cost_model->distance_[i] != 0) {
+ if (offset_cost_min == 0.) {
+ offset_cost_min = cost_model->distance_[i];
+ } else if (cost_model->distance_[i] < offset_cost_min) {
+ offset_cost_min = cost_model->distance_[i];
+ }
+ }
+ }
+ // In case all the cost_model->distance_ is 0, the next non-zero cost we
+ // can have is from the extra bit in GetDistanceCost, hence 1.
+ if (offset_cost_min < 1.) offset_cost_min = 1.;
+
+ size = 1 + (int)ceil((manager->max_cost_cache_ - manager->min_cost_cache_) /
+ offset_cost_min);
+ // Empirically, we usually end up with a value below 100.
+ if (size > MAX_LENGTH) size = MAX_LENGTH;
+
+ manager->interval_ends_ =
+ (int*)WebPSafeMalloc(size, sizeof(*manager->interval_ends_));
+ if (manager->interval_ends_ == NULL) {
+ CostManagerClear(manager);
+ return 0;
+ }
+ manager->interval_ends_size_ = size;
+ }
+
+ return 1;
+}
+
+// Given the distance_cost for pixel 'index', update the cost at pixel 'i' if it
+// is smaller than the previously computed value.
+static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, int index,
+ double distance_cost) {
+ int k = i - index;
+ double cost_tmp;
+ assert(k >= 0 && k < MAX_LENGTH);
+ cost_tmp = distance_cost + manager->cost_cache_[k];
+
+ if (manager->costs_[i] > cost_tmp) {
+ manager->costs_[i] = (float)cost_tmp;
+ manager->dist_array_[i] = k + 1;
+ }
+}
+
+// Given the distance_cost for pixel 'index', update the cost for all the pixels
+// between 'start' and 'end' excluded.
+static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager,
+ int start, int end, int index,
+ double distance_cost) {
+ int i;
+ for (i = start; i < end; ++i) UpdateCost(manager, i, index, distance_cost);
+}
+
+// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'.
+static WEBP_INLINE void ConnectIntervals(CostManager* const manager,
+ CostInterval* const prev,
+ CostInterval* const next) {
+ if (prev != NULL) {
+ prev->next_ = next;
+ } else {
+ manager->head_ = next;
+ }
+
+ if (next != NULL) next->previous_ = prev;
+}
+
+// Pop an interval in the manager.
+static WEBP_INLINE void PopInterval(CostManager* const manager,
+ CostInterval* const interval) {
+ CostInterval* const next = interval->next_;
+
+ if (interval == NULL) return;
+
+ ConnectIntervals(manager, interval->previous_, next);
+ if (CostIntervalIsInFreeList(manager, interval)) {
+ CostIntervalAddToFreeList(manager, interval);
+ } else { // recycle regularly malloc'd intervals too
+ interval->next_ = manager->recycled_intervals_;
+ manager->recycled_intervals_ = interval;
+ }
+ --manager->count_;
+ assert(manager->count_ >= 0);
+}
+
+// Update the cost at index i by going over all the stored intervals that
+// overlap with i.
+static WEBP_INLINE void UpdateCostPerIndex(CostManager* const manager, int i) {
+ CostInterval* current = manager->head_;
+
+ while (current != NULL && current->start_ <= i) {
+ if (current->end_ <= i) {
+ // We have an outdated interval, remove it.
+ CostInterval* next = current->next_;
+ PopInterval(manager, current);
+ current = next;
+ } else {
+ UpdateCost(manager, i, current->index_, current->distance_cost_);
+ current = current->next_;
+ }
+ }
+}
+
+// Given a current orphan interval and its previous interval, before
+// it was orphaned (which can be NULL), set it at the right place in the list
+// of intervals using the start_ ordering and the previous interval as a hint.
+static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager,
+ CostInterval* const current,
+ CostInterval* previous) {
+ assert(current != NULL);
+
+ if (previous == NULL) previous = manager->head_;
+ while (previous != NULL && current->start_ < previous->start_) {
+ previous = previous->previous_;
+ }
+ while (previous != NULL && previous->next_ != NULL &&
+ previous->next_->start_ < current->start_) {
+ previous = previous->next_;
+ }
+
+ if (previous != NULL) {
+ ConnectIntervals(manager, current, previous->next_);
+ } else {
+ ConnectIntervals(manager, current, manager->head_);
+ }
+ ConnectIntervals(manager, previous, current);
+}
+
+// Insert an interval in the list contained in the manager by starting at
+// interval_in as a hint. The intervals are sorted by start_ value.
+static WEBP_INLINE void InsertInterval(CostManager* const manager,
+ CostInterval* const interval_in,
+ double distance_cost, double lower,
+ double upper, int index, int start,
+ int end) {
+ CostInterval* interval_new;
+
+ if (IsCostCacheIntervalWritable(start, end) ||
+ manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) {
+ // Write down the interval if it is too small.
+ UpdateCostPerInterval(manager, start, end, index, distance_cost);
+ return;
+ }
+ if (manager->free_intervals_ != NULL) {
+ interval_new = manager->free_intervals_;
+ manager->free_intervals_ = interval_new->next_;
+ } else if (manager->recycled_intervals_ != NULL) {
+ interval_new = manager->recycled_intervals_;
+ manager->recycled_intervals_ = interval_new->next_;
+ } else { // malloc for good
+ interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new));
+ if (interval_new == NULL) {
+ // Write down the interval if we cannot create it.
+ UpdateCostPerInterval(manager, start, end, index, distance_cost);
+ return;
+ }
+ }
+
+ interval_new->distance_cost_ = distance_cost;
+ interval_new->lower_ = lower;
+ interval_new->upper_ = upper;
+ interval_new->index_ = index;
+ interval_new->start_ = start;
+ interval_new->end_ = end;
+ PositionOrphanInterval(manager, interval_new, interval_in);
+
+ ++manager->count_;
+}
+
+// When an interval has its start_ or end_ modified, it needs to be
+// repositioned in the linked list.
+static WEBP_INLINE void RepositionInterval(CostManager* const manager,
+ CostInterval* const interval) {
+ if (IsCostCacheIntervalWritable(interval->start_, interval->end_)) {
+ // Maybe interval has been resized and is small enough to be removed.
+ UpdateCostPerInterval(manager, interval->start_, interval->end_,
+ interval->index_, interval->distance_cost_);
+ PopInterval(manager, interval);
+ return;
+ }
+
+ // Early exit if interval is at the right spot.
+ if ((interval->previous_ == NULL ||
+ interval->previous_->start_ <= interval->start_) &&
+ (interval->next_ == NULL ||
+ interval->start_ <= interval->next_->start_)) {
+ return;
+ }
+
+ ConnectIntervals(manager, interval->previous_, interval->next_);
+ PositionOrphanInterval(manager, interval, interval->previous_);
+}
+
+// Given a new cost interval defined by its start at index, its last value and
+// distance_cost, add its contributions to the previous intervals and costs.
+// If handling the interval or one of its subintervals becomes to heavy, its
+// contribution is added to the costs right away.
+static WEBP_INLINE void PushInterval(CostManager* const manager,
+ double distance_cost, int index,
+ int last) {
+ size_t i;
+ CostInterval* interval = manager->head_;
+ CostInterval* interval_next;
+ const CostCacheInterval* const cost_cache_intervals =
+ manager->cache_intervals_;
+
+ for (i = 0; i < manager->cache_intervals_size_ &&
+ cost_cache_intervals[i].start_ < last;
+ ++i) {
+ // Define the intersection of the ith interval with the new one.
+ int start = index + cost_cache_intervals[i].start_;
+ const int end = index + (cost_cache_intervals[i].end_ > last
+ ? last
+ : cost_cache_intervals[i].end_);
+ const double lower_in = cost_cache_intervals[i].lower_;
+ const double upper_in = cost_cache_intervals[i].upper_;
+ const double lower_full_in = distance_cost + lower_in;
+ const double upper_full_in = distance_cost + upper_in;
+
+ if (cost_cache_intervals[i].do_write_) {
+ UpdateCostPerInterval(manager, start, end, index, distance_cost);
+ continue;
+ }
+
+ for (; interval != NULL && interval->start_ < end && start < end;
+ interval = interval_next) {
+ const double lower_full_interval =
+ interval->distance_cost_ + interval->lower_;
+ const double upper_full_interval =
+ interval->distance_cost_ + interval->upper_;
+
+ interval_next = interval->next_;
+
+ // Make sure we have some overlap
+ if (start >= interval->end_) continue;
+
+ if (lower_full_in >= upper_full_interval) {
+ // When intervals are represented, the lower, the better.
+ // [**********************************************************]
+ // start end
+ // [----------------------------------]
+ // interval->start_ interval->end_
+ // If we are worse than what we already have, add whatever we have so
+ // far up to interval.
+ const int start_new = interval->end_;
+ InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
+ index, start, interval->start_);
+ start = start_new;
+ continue;
+ }
+
+ // We know the two intervals intersect.
+ if (upper_full_in >= lower_full_interval) {
+ // There is no clear cut on which is best, so let's keep both.
+ // [*********[*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*]***********]
+ // start interval->start_ interval->end_ end
+ // OR
+ // [*********[*-*-*-*-*-*-*-*-*-*-*-]----------------------]
+ // start interval->start_ end interval->end_
+ const int end_new = (interval->end_ <= end) ? interval->end_ : end;
+ InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
+ index, start, end_new);
+ start = end_new;
+ } else if (start <= interval->start_ && interval->end_ <= end) {
+ // [----------------------------------]
+ // interval->start_ interval->end_
+ // [**************************************************************]
+ // start end
+ // We can safely remove the old interval as it is fully included.
+ PopInterval(manager, interval);
+ } else {
+ if (interval->start_ <= start && end <= interval->end_) {
+ // [--------------------------------------------------------------]
+ // interval->start_ interval->end_
+ // [*****************************]
+ // start end
+ // We have to split the old interval as it fully contains the new one.
+ const int end_original = interval->end_;
+ interval->end_ = start;
+ InsertInterval(manager, interval, interval->distance_cost_,
+ interval->lower_, interval->upper_, interval->index_,
+ end, end_original);
+ } else if (interval->start_ < start) {
+ // [------------------------------------]
+ // interval->start_ interval->end_
+ // [*****************************]
+ // start end
+ interval->end_ = start;
+ } else {
+ // [------------------------------------]
+ // interval->start_ interval->end_
+ // [*****************************]
+ // start end
+ interval->start_ = end;
+ }
+
+ // The interval has been modified, we need to reposition it or write it.
+ RepositionInterval(manager, interval);
+ }
+ }
+ // Insert the remaining interval from start to end.
+ InsertInterval(manager, interval, distance_cost, lower_in, upper_in, index,
+ start, end);
+ }
+}
+
+static int BackwardReferencesHashChainDistanceOnly(
+ int xsize, int ysize, const uint32_t* const argb, int quality,
+ int cache_bits, const VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs, uint16_t* const dist_array) {
+ int i;
+ int ok = 0;
+ int cc_init = 0;
+ const int pix_count = xsize * ysize;
+ const int use_color_cache = (cache_bits > 0);
+ 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*)WebPSafeCalloc(1ULL, cost_model_size);
+ VP8LColorCache hashers;
+ const int skip_length = 32 + quality;
+ const int skip_min_distance_code = 2;
+ CostManager* cost_manager =
+ (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager));
+
+ if (cost_model == NULL || cost_manager == 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, cache_bits, refs)) {
+ goto Error;
+ }
+
+ if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) {
+ goto Error;
+ }
+
+ // We loop one pixel at a time, but store all currently best points to
+ // non-processed locations from this point.
+ dist_array[0] = 0;
+ // Add first pixel as literal.
+ AddSingleLiteralWithCostModel(argb + 0, &hashers, cost_model, 0,
+ use_color_cache, 0.0, cost_manager->costs_,
+ dist_array);
+
+ for (i = 1; i < pix_count - 1; ++i) {
+ int offset = 0, len = 0;
+ double prev_cost = cost_manager->costs_[i - 1];
+ HashChainFindCopy(hash_chain, i, &offset, &len);
+ if (len >= 2) {
+ // If we are dealing with a non-literal.
+ const int code = DistanceToPlaneCode(xsize, offset);
+ const double offset_cost = GetDistanceCost(cost_model, code);
+ const int first_i = i;
+ int j_max = 0, interval_ends_index = 0;
+ const int is_offset_zero = (offset_cost == 0.);
+
+ if (!is_offset_zero) {
+ j_max = (int)ceil(
+ (cost_manager->max_cost_cache_ - cost_manager->min_cost_cache_) /
+ offset_cost);
+ if (j_max < 1) {
+ j_max = 1;
+ } else if (j_max > cost_manager->interval_ends_size_ - 1) {
+ // This could only happen in the case of MAX_LENGTH.
+ j_max = cost_manager->interval_ends_size_ - 1;
+ }
+ } // else j_max is unused anyway.
+
+ // Instead of considering all contributions from a pixel i by calling:
+ // PushInterval(cost_manager, prev_cost + offset_cost, i, len);
+ // we optimize these contributions in case offset_cost stays the same for
+ // consecutive pixels. This describes a set of pixels similar to a
+ // previous set (e.g. constant color regions).
+ for (; i < pix_count - 1; ++i) {
+ int offset_next, len_next;
+ prev_cost = cost_manager->costs_[i - 1];
+
+ if (is_offset_zero) {
+ // No optimization can be made so we just push all of the
+ // contributions from i.
+ PushInterval(cost_manager, prev_cost, i, len);
+ } else {
+ // j_max is chosen as the smallest j such that:
+ // max of cost_cache_ < j*offset cost + min of cost_cache_
+ // Therefore, the pixel influenced by i-j_max, cannot be influenced
+ // by i. Only the costs after the end of what i contributed need to be
+ // updated. cost_manager->interval_ends_ is a circular buffer that
+ // stores those ends.
+ const double distance_cost = prev_cost + offset_cost;
+ int j = cost_manager->interval_ends_[interval_ends_index];
+ if (i - first_i <= j_max ||
+ !IsCostCacheIntervalWritable(j, i + len)) {
+ PushInterval(cost_manager, distance_cost, i, len);
+ } else {
+ for (; j < i + len; ++j) {
+ UpdateCost(cost_manager, j, i, distance_cost);
+ }
+ }
+ // Store the new end in the circular buffer.
+ assert(interval_ends_index < cost_manager->interval_ends_size_);
+ cost_manager->interval_ends_[interval_ends_index] = i + len;
+ if (++interval_ends_index > j_max) interval_ends_index = 0;
+ }
+
+ // Check whether i is the last pixel to consider, as it is handled
+ // differently.
+ if (i + 1 >= pix_count - 1) break;
+ HashChainFindCopy(hash_chain, i + 1, &offset_next, &len_next);
+ if (offset_next != offset) break;
+ len = len_next;
+ UpdateCostPerIndex(cost_manager, i);
+ AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
+ use_color_cache, prev_cost,
+ cost_manager->costs_, dist_array);
+ }
+ // Submit the last pixel.
+ UpdateCostPerIndex(cost_manager, i + 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) {
+ int k;
+ for (k = 0; k < len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[i + k]);
+ }
+ }
+ // 2) jump.
+ {
+ const int i_next = i + len - 1; // for loop does ++i, thus -1 here.
+ for (; i <= i_next; ++i) UpdateCostPerIndex(cost_manager, i + 1);
+ i = i_next;
+ }
+ goto next_symbol;
+ }
+ if (len > 2) {
+ // Also try the smallest interval possible (size 2).
+ double cost_total =
+ prev_cost + offset_cost + GetLengthCost(cost_model, 1);
+ if (cost_manager->costs_[i + 1] > cost_total) {
+ cost_manager->costs_[i + 1] = (float)cost_total;
+ dist_array[i + 1] = 2;
+ }
+ }
+ } else {
+ // The pixel is added as a single literal so just update the costs.
+ UpdateCostPerIndex(cost_manager, i + 1);
+ }
+
+ AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
+ use_color_cache, prev_cost,
+ cost_manager->costs_, dist_array);
+
+ next_symbol: ;
+ }
+ // Handle the last pixel.
+ if (i == (pix_count - 1)) {
+ AddSingleLiteralWithCostModel(
+ argb + i, &hashers, cost_model, i, use_color_cache,
+ cost_manager->costs_[pix_count - 2], cost_manager->costs_, dist_array);
+ }
+
+ ok = !refs->error_;
+ Error:
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ CostManagerClear(cost_manager);
+ WebPSafeFree(cost_model);
+ WebPSafeFree(cost_manager);
+ return ok;
+}
+
+// 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;
+ }
+ *chosen_path = path;
+ *chosen_path_size = (int)(dist_array + dist_array_size - path);
+}
+
+static int BackwardReferencesHashChainFollowChosenPath(
+ const uint32_t* const argb, int cache_bits,
+ const uint16_t* const chosen_path, int chosen_path_size,
+ const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) {
+ const int use_color_cache = (cache_bits > 0);
+ int ix;
+ int i = 0;
+ int ok = 0;
+ int cc_init = 0;
+ VP8LColorCache hashers;
+
+ if (use_color_cache) {
+ cc_init = VP8LColorCacheInit(&hashers, cache_bits);
+ if (!cc_init) goto Error;
+ }
+
+ ClearBackwardRefs(refs);
+ for (ix = 0; ix < chosen_path_size; ++ix) {
+ const int len = chosen_path[ix];
+ if (len != 1) {
+ int k;
+ const int offset = HashChainFindOffset(hash_chain, i);
+ BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
+ if (use_color_cache) {
+ for (k = 0; k < len; ++k) {
+ VP8LColorCacheInsert(&hashers, argb[i + k]);
+ }
+ }
+ i += len;
+ } else {
+ PixOrCopy v;
+ const int idx =
+ use_color_cache ? VP8LColorCacheContains(&hashers, argb[i]) : -1;
+ if (idx >= 0) {
+ // use_color_cache is true and hashers contains argb[i]
+ // push pixel as a color cache index
+ v = PixOrCopyCreateCacheIdx(idx);
+ } else {
+ if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
+ v = PixOrCopyCreateLiteral(argb[i]);
+ }
+ BackwardRefsCursorAdd(refs, v);
+ ++i;
+ }
+ }
+ ok = !refs->error_;
+ Error:
+ if (cc_init) VP8LColorCacheClear(&hashers);
+ return ok;
+}
+
+// Returns 1 on success.
+static int BackwardReferencesTraceBackwards(
+ int xsize, int ysize, const uint32_t* const argb, int quality,
+ int cache_bits, const VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs) {
+ int ok = 0;
+ const int dist_array_size = xsize * ysize;
+ uint16_t* chosen_path = NULL;
+ int chosen_path_size = 0;
+ uint16_t* dist_array =
+ (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array));
+
+ if (dist_array == NULL) goto Error;
+
+ if (!BackwardReferencesHashChainDistanceOnly(
+ xsize, ysize, argb, quality, cache_bits, hash_chain,
+ refs, dist_array)) {
+ goto Error;
+ }
+ TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size);
+ if (!BackwardReferencesHashChainFollowChosenPath(
+ argb, cache_bits, chosen_path, chosen_path_size, hash_chain, refs)) {
+ goto Error;
+ }
+ ok = 1;
+ Error:
+ WebPSafeFree(dist_array);
+ return ok;
+}
+
+static void BackwardReferences2DLocality(int xsize,
+ 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);
+ c.cur_pos->argb_or_distance = transformed_dist;
+ }
+ VP8LRefsCursorNext(&c);
+ }
+}
+
+// Computes the entropies for a color cache size (in bits) between 0 (unused)
+// and cache_bits_max (inclusive).
+// Returns 1 on success, 0 in case of allocation error.
+static int ComputeCacheEntropies(const uint32_t* argb,
+ const VP8LBackwardRefs* const refs,
+ int cache_bits_max, double entropies[]) {
+ int cc_init[MAX_COLOR_CACHE_BITS + 1] = { 0 };
+ VP8LColorCache hashers[MAX_COLOR_CACHE_BITS + 1];
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ VP8LHistogram* histos[MAX_COLOR_CACHE_BITS + 1] = { NULL };
+ int ok = 0;
+ int i;
+
+ for (i = 0; i <= cache_bits_max; ++i) {
+ histos[i] = VP8LAllocateHistogram(i);
+ if (histos[i] == NULL) goto Error;
+ if (i == 0) continue;
+ cc_init[i] = VP8LColorCacheInit(&hashers[i], i);
+ if (!cc_init[i]) goto Error;
+ }
+
+ assert(cache_bits_max >= 0);
+ // Do not use the color cache for cache_bits=0.
+ while (VP8LRefsCursorOk(&c)) {
+ VP8LHistogramAddSinglePixOrCopy(histos[0], c.cur_pos);
+ VP8LRefsCursorNext(&c);
+ }
+ if (cache_bits_max > 0) {
+ c = VP8LRefsCursorInit(refs);
+ while (VP8LRefsCursorOk(&c)) {
+ const PixOrCopy* const v = c.cur_pos;
+ if (PixOrCopyIsLiteral(v)) {
+ const uint32_t pix = *argb++;
+ // The keys of the caches can be derived from the longest one.
+ int key = HashPix(pix, 32 - cache_bits_max);
+ for (i = cache_bits_max; i >= 1; --i, key >>= 1) {
+ if (VP8LColorCacheLookup(&hashers[i], key) == pix) {
+ ++histos[i]->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key];
+ } else {
+ VP8LColorCacheSet(&hashers[i], key, pix);
+ ++histos[i]->blue_[pix & 0xff];
+ ++histos[i]->literal_[(pix >> 8) & 0xff];
+ ++histos[i]->red_[(pix >> 16) & 0xff];
+ ++histos[i]->alpha_[pix >> 24];
+ }
+ }
+ } else {
+ // Update the histograms for distance/length.
+ int len = PixOrCopyLength(v);
+ int code_dist, code_len, extra_bits;
+ uint32_t argb_prev = *argb ^ 0xffffffffu;
+ VP8LPrefixEncodeBits(len, &code_len, &extra_bits);
+ VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code_dist, &extra_bits);
+ for (i = 1; i <= cache_bits_max; ++i) {
+ ++histos[i]->literal_[NUM_LITERAL_CODES + code_len];
+ ++histos[i]->distance_[code_dist];
+ }
+ // Update the colors caches.
+ do {
+ if (*argb != argb_prev) {
+ // Efficiency: insert only if the color changes.
+ int key = HashPix(*argb, 32 - cache_bits_max);
+ for (i = cache_bits_max; i >= 1; --i, key >>= 1) {
+ hashers[i].colors_[key] = *argb;
+ }
+ argb_prev = *argb;
+ }
+ argb++;
+ } while (--len != 0);
+ }
+ VP8LRefsCursorNext(&c);
+ }
+ }
+ for (i = 0; i <= cache_bits_max; ++i) {
+ entropies[i] = VP8LHistogramEstimateBits(histos[i]);
+ }
+ ok = 1;
+Error:
+ for (i = 0; i <= cache_bits_max; ++i) {
+ if (cc_init[i]) VP8LColorCacheClear(&hashers[i]);
+ VP8LFreeHistogram(histos[i]);
+ }
+ return ok;
+}
+
+// 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,
+ const VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs* const refs,
+ int* const lz77_computed,
+ int* const best_cache_bits) {
+ int i;
+ int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits;
+ double entropy_min = MAX_ENTROPY;
+ double entropies[MAX_COLOR_CACHE_BITS + 1];
+
+ 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;
+ }
+ // Compute LZ77 with no cache (0 bits), as the ideal LZ77 with a color cache
+ // is not that different in practice.
+ if (!BackwardReferencesLz77(xsize, ysize, argb, 0, hash_chain, refs)) {
+ return 0;
+ }
+ // Find the cache_bits giving the lowest entropy. The search is done in a
+ // brute-force way as the function (entropy w.r.t cache_bits) can be
+ // anything in practice.
+ if (!ComputeCacheEntropies(argb, refs, cache_bits_high, entropies)) {
+ return 0;
+ }
+ for (i = 0; i <= cache_bits_high; ++i) {
+ if (i == 0 || entropies[i] < entropy_min) {
+ entropy_min = entropies[i];
+ *best_cache_bits = i;
+ }
+ }
+ return 1;
+}
+
+// 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;
+ VP8LColorCache hashers;
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0;
+
+ while (VP8LRefsCursorOk(&c)) {
+ PixOrCopy* const v = c.cur_pos;
+ if (PixOrCopyIsLiteral(v)) {
+ const uint32_t argb_literal = v->argb_or_distance;
+ const int ix = VP8LColorCacheContains(&hashers, argb_literal);
+ if (ix >= 0) {
+ // hashers contains argb_literal
+ *v = PixOrCopyCreateCacheIdx(ix);
+ } else {
+ VP8LColorCacheInsert(&hashers, argb_literal);
+ }
+ ++pixel_index;
+ } else {
+ // 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++]);
+ }
+ }
+ VP8LRefsCursorNext(&c);
+ }
+ VP8LColorCacheClear(&hashers);
+ return 1;
+}
+
+static VP8LBackwardRefs* GetBackwardReferencesLowEffort(
+ int width, int height, const uint32_t* const argb,
+ int* const cache_bits, const VP8LHashChain* const hash_chain,
+ VP8LBackwardRefs refs_array[2]) {
+ VP8LBackwardRefs* refs_lz77 = &refs_array[0];
+ *cache_bits = 0;
+ if (!BackwardReferencesLz77(width, height, argb, 0, 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, const 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;
+ }
+
+ 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, hash_chain,
+ refs_lz77)) {
+ goto Error;
+ }
+ }
+
+ 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:
+ VP8LFreeHistogram(histo);
+ return best;
+}
+
+VP8LBackwardRefs* VP8LGetBackwardReferences(
+ int width, int height, const uint32_t* const argb, int quality,
+ int low_effort, int* const cache_bits,
+ const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[2]) {
+ if (low_effort) {
+ return GetBackwardReferencesLowEffort(width, height, argb, cache_bits,
+ hash_chain, refs_array);
+ } else {
+ return GetBackwardReferences(width, height, argb, quality, cache_bits,
+ hash_chain, refs_array);
+ }
+}
diff --git a/thirdparty/libwebp/enc/backward_references_enc.h b/thirdparty/libwebp/enc/backward_references_enc.h
new file mode 100644
index 0000000000..3a19aa763e
--- /dev/null
+++ b/thirdparty/libwebp/enc/backward_references_enc.h
@@ -0,0 +1,207 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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 "../webp/types.h"
+#include "../webp/format_constants.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// The maximum allowed limit is 11.
+#define MAX_COLOR_CACHE_BITS 10
+
+// -----------------------------------------------------------------------------
+// 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;
+}
+
+// -----------------------------------------------------------------------------
+// VP8LHashChain
+
+#define HASH_BITS 18
+#define HASH_SIZE (1 << HASH_BITS)
+
+typedef struct VP8LHashChain VP8LHashChain;
+struct VP8LHashChain {
+ // The 20 most significant bits contain the offset at which the best match
+ // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain
+ // (through WINDOW_SIZE = 1<<20).
+ // The lower 12 bits contain the length of the match. The 12 bit limit is
+ // defined in MaxFindCopyLength with MAX_LENGTH=4096.
+ uint32_t* offset_length_;
+ // 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_;
+};
+
+// Must be called first, to set size.
+int VP8LHashChainInit(VP8LHashChain* const p, int size);
+// Pre-compute the best matches for argb.
+int VP8LHashChainFill(VP8LHashChain* const p, int quality,
+ const uint32_t* const argb, int xsize, int ysize,
+ int low_effort);
+void VP8LHashChainClear(VP8LHashChain* const p); // release memory
+
+// -----------------------------------------------------------------------------
+// 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)
+};
+
+// 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);
+
+// 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.
+// 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,
+ const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WEBP_ENC_BACKWARD_REFERENCES_H_
diff --git a/thirdparty/libwebp/enc/config.c b/thirdparty/libwebp/enc/config.c
deleted file mode 100644
index f9f7961d58..0000000000
--- a/thirdparty/libwebp/enc/config.c
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Coding tools configuration
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "../webp/encode.h"
-
-//------------------------------------------------------------------------------
-// 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 = 60; // mid-filtering
- config->filter_sharpness = 0;
- config->filter_type = 1; // default: strong (so U/V is filtered too)
- 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->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) {
- case WEBP_PRESET_PICTURE:
- 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;
- 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
- 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:
- 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 > 7)
- 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->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;
-}
-
-//------------------------------------------------------------------------------
-
-#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/thirdparty/libwebp/enc/config_enc.c b/thirdparty/libwebp/enc/config_enc.c
new file mode 100644
index 0000000000..4589dc0619
--- /dev/null
+++ b/thirdparty/libwebp/enc/config_enc.c
@@ -0,0 +1,152 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Coding tools configuration
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifdef HAVE_CONFIG_H
+#include "../webp/config.h"
+#endif
+
+#include "../webp/encode.h"
+
+//------------------------------------------------------------------------------
+// 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 = 60; // mid-filtering
+ config->filter_sharpness = 0;
+ config->filter_type = 1; // default: strong (so U/V is filtered too)
+ 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->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;
+ config->use_delta_palette = 0;
+ config->use_sharp_yuv = 0;
+
+ // TODO(skal): tune.
+ switch (preset) {
+ case WEBP_PRESET_PICTURE:
+ 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;
+ 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
+ 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:
+ 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 > 7) 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->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;
+ if (config->use_delta_palette < 0 || config->use_delta_palette > 1) {
+ return 0;
+ }
+ if (config->use_sharp_yuv < 0 || config->use_sharp_yuv > 1) return 0;
+
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+
+#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/thirdparty/libwebp/enc/cost.c b/thirdparty/libwebp/enc/cost.c
deleted file mode 100644
index 87f89378a7..0000000000
--- a/thirdparty/libwebp/enc/cost.c
+++ /dev/null
@@ -1,342 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Cost tables for level and modes
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./cost.h"
-
-//------------------------------------------------------------------------------
-// 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}
-};
-
-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(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) {
- const uint8_t* const p = proba->coeffs_[ctype][band][ctx];
- uint16_t* const table = proba->level_cost_[ctype][band][ctx];
- 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]) + cost0;
- 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.
- }
- }
- 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;
-}
-
-//------------------------------------------------------------------------------
-// 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] = {
- { { 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.
-
-// 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.
-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) {
- VP8RecordStats(0, s + 0);
- return 0;
- }
- while (n <= res->last) {
- int v;
- VP8RecordStats(1, s + 0); // order of record doesn't matter
- while ((v = res->coeffs[n++]) == 0) {
- VP8RecordStats(0, s + 1);
- s = res->stats[VP8EncBands[n]][0];
- }
- VP8RecordStats(1, s + 1);
- if (!VP8RecordStats(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 (!VP8RecordStats(v > 4, s + 3)) {
- if (VP8RecordStats(v != 2, s + 4))
- VP8RecordStats(v == 4, s + 5);
- } else if (!VP8RecordStats(v > 10, s + 6)) {
- VP8RecordStats(v > 6, s + 7);
- } else if (!VP8RecordStats((v >= 3 + (8 << 2)), s + 8)) {
- VP8RecordStats((v >= 3 + (8 << 1)), s + 9);
- } else {
- VP8RecordStats((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) VP8RecordStats(!!(bits & mask), s + 3 + i);
- }
- }
-#endif
- s = res->stats[VP8EncBands[n]][2];
- }
- }
- if (n < 16) VP8RecordStats(0, s + 0);
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/cost.h b/thirdparty/libwebp/enc/cost.h
deleted file mode 100644
index ad7959feb4..0000000000
--- a/thirdparty/libwebp/enc/cost.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Cost tables for level and modes.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_ENC_COST_H_
-#define WEBP_ENC_COST_H_
-
-#include <assert.h>
-#include <stdlib.h>
-#include "./vp8enci.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// 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);
-
-// Record proba context used.
-static WEBP_INLINE int VP8RecordStats(int bit, proba_t* const stats) {
- proba_t p = *stats;
- // An overflow is inbound. Note we handle this at 0xfffe0000u instead of
- // 0xffff0000u to make sure p + 1u does not overflow.
- if (p >= 0xfffe0000u) {
- 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;
-}
-
-// 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(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];
-}
-
-// 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];
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_ENC_COST_H_ */
diff --git a/thirdparty/libwebp/enc/cost_enc.c b/thirdparty/libwebp/enc/cost_enc.c
new file mode 100644
index 0000000000..c823f5a664
--- /dev/null
+++ b/thirdparty/libwebp/enc/cost_enc.c
@@ -0,0 +1,342 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Cost tables for level and modes
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./cost_enc.h"
+
+//------------------------------------------------------------------------------
+// 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}
+};
+
+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(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) {
+ const uint8_t* const p = proba->coeffs_[ctype][band][ctx];
+ uint16_t* const table = proba->level_cost_[ctype][band][ctx];
+ 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]) + cost0;
+ 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.
+ }
+ }
+ 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;
+}
+
+//------------------------------------------------------------------------------
+// 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] = {
+ { { 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.
+
+// 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.
+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) {
+ VP8RecordStats(0, s + 0);
+ return 0;
+ }
+ while (n <= res->last) {
+ int v;
+ VP8RecordStats(1, s + 0); // order of record doesn't matter
+ while ((v = res->coeffs[n++]) == 0) {
+ VP8RecordStats(0, s + 1);
+ s = res->stats[VP8EncBands[n]][0];
+ }
+ VP8RecordStats(1, s + 1);
+ if (!VP8RecordStats(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 (!VP8RecordStats(v > 4, s + 3)) {
+ if (VP8RecordStats(v != 2, s + 4))
+ VP8RecordStats(v == 4, s + 5);
+ } else if (!VP8RecordStats(v > 10, s + 6)) {
+ VP8RecordStats(v > 6, s + 7);
+ } else if (!VP8RecordStats((v >= 3 + (8 << 2)), s + 8)) {
+ VP8RecordStats((v >= 3 + (8 << 1)), s + 9);
+ } else {
+ VP8RecordStats((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) VP8RecordStats(!!(bits & mask), s + 3 + i);
+ }
+ }
+#endif
+ s = res->stats[VP8EncBands[n]][2];
+ }
+ }
+ if (n < 16) VP8RecordStats(0, s + 0);
+ return 1;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/cost_enc.h b/thirdparty/libwebp/enc/cost_enc.h
new file mode 100644
index 0000000000..99e4b37aa3
--- /dev/null
+++ b/thirdparty/libwebp/enc/cost_enc.h
@@ -0,0 +1,82 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Cost tables for level and modes.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_ENC_COST_H_
+#define WEBP_ENC_COST_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include "./vp8i_enc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 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);
+
+// Record proba context used.
+static WEBP_INLINE int VP8RecordStats(int bit, proba_t* const stats) {
+ proba_t p = *stats;
+ // An overflow is inbound. Note we handle this at 0xfffe0000u instead of
+ // 0xffff0000u to make sure p + 1u does not overflow.
+ if (p >= 0xfffe0000u) {
+ 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;
+}
+
+// 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(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];
+}
+
+// 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];
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_ENC_COST_H_ */
diff --git a/thirdparty/libwebp/enc/delta_palettization.c b/thirdparty/libwebp/enc/delta_palettization.c
deleted file mode 100644
index 062e588d79..0000000000
--- a/thirdparty/libwebp/enc/delta_palettization.c
+++ /dev/null
@@ -1,455 +0,0 @@
-// 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/thirdparty/libwebp/enc/delta_palettization.h b/thirdparty/libwebp/enc/delta_palettization.h
deleted file mode 100644
index e41c0c5ab5..0000000000
--- a/thirdparty/libwebp/enc/delta_palettization.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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/thirdparty/libwebp/enc/delta_palettization_enc.c b/thirdparty/libwebp/enc/delta_palettization_enc.c
new file mode 100644
index 0000000000..eaf0f050ea
--- /dev/null
+++ b/thirdparty/libwebp/enc/delta_palettization_enc.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_enc.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/thirdparty/libwebp/enc/delta_palettization_enc.h b/thirdparty/libwebp/enc/delta_palettization_enc.h
new file mode 100644
index 0000000000..63048ec6e8
--- /dev/null
+++ b/thirdparty/libwebp/enc/delta_palettization_enc.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_enc.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/thirdparty/libwebp/enc/filter.c b/thirdparty/libwebp/enc/filter.c
deleted file mode 100644
index e8ea8b4ff2..0000000000
--- a/thirdparty/libwebp/enc/filter.c
+++ /dev/null
@@ -1,306 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Selecting filter level
-//
-// Author: somnath@google.com (Somnath Banerjee)
-
-#include <assert.h>
-#include "./vp8enci.h"
-#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];
-}
-
-//------------------------------------------------------------------------------
-// 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_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_ENC * sizeof(uint8_t));
-
- if (enc->filter_hdr_.simple_ == 1) { // simple
- VP8SimpleHFilter16i(y_dst, BPS, limit);
- VP8SimpleVFilter16i(y_dst, BPS, limit);
- } else { // complex
- const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
- 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);
- }
-}
-
-//------------------------------------------------------------------------------
-// SSIM metric
-
-static const double kMinValue = 1.e-10; // minimal threshold
-
-void VP8SSIMAddStats(const VP8DistoStats* const src, VP8DistoStats* 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;
-}
-
-double VP8SSIMGet(const VP8DistoStats* 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 VP8DistoStats* 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;
-}
-
-#define LIMIT(A, M) ((A) > (M) ? (M) : (A))
-static void VP8SSIMAccumulateRow(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int y, int W, int H,
- VP8DistoStats* const stats) {
- int x = 0;
- const int w0 = LIMIT(VP8_SSIM_KERNEL, W);
- for (x = 0; x < w0; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
- for (; x <= W - 8 + VP8_SSIM_KERNEL; ++x) {
- VP8SSIMAccumulate(
- src1 + (y - VP8_SSIM_KERNEL) * stride1 + (x - VP8_SSIM_KERNEL), stride1,
- src2 + (y - VP8_SSIM_KERNEL) * stride2 + (x - VP8_SSIM_KERNEL), stride2,
- stats);
- }
- for (; x < W; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
-}
-
-void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int W, int H, VP8DistoStats* const stats) {
- int x, y;
- const int h0 = LIMIT(VP8_SSIM_KERNEL, H);
- const int h1 = LIMIT(VP8_SSIM_KERNEL, H - VP8_SSIM_KERNEL);
- for (y = 0; y < h0; ++y) {
- for (x = 0; x < W; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
- }
- for (; y < h1; ++y) {
- VP8SSIMAccumulateRow(src1, stride1, src2, stride2, y, W, H, stats);
- }
- for (; y < H; ++y) {
- for (x = 0; x < W; ++x) {
- VP8SSIMAccumulateClipped(src1, stride1, src2, stride2, x, y, W, H, stats);
- }
- }
-}
-#undef LIMIT
-
-static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) {
- int x, y;
- VP8DistoStats s = { .0, .0, .0, .0, .0, .0 };
-
- // compute SSIM in a 10 x 10 window
- for (y = VP8_SSIM_KERNEL; y < 16 - VP8_SSIM_KERNEL; y++) {
- for (x = VP8_SSIM_KERNEL; x < 16 - VP8_SSIM_KERNEL; x++) {
- VP8SSIMAccumulateClipped(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++) {
- VP8SSIMAccumulateClipped(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS,
- x, y, 8, 8, &s);
- VP8SSIMAccumulateClipped(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, 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) {
- 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;
- }
- }
- VP8SSIMDspInit();
- }
-}
-
-void VP8StoreFilterStats(VP8EncIterator* const it) {
- int d;
- VP8Encoder* const enc = it->enc_;
- const int s = it->mb_->segment_;
- const int level0 = enc->dqm_[s].fstrength_;
-
- // explore +/-quant range of values around level0
- 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_ == NULL) 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) {
- VP8Encoder* const enc = it->enc_;
- 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;
- }
- } 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;
- }
-}
-
-// -----------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/filter_enc.c b/thirdparty/libwebp/enc/filter_enc.c
new file mode 100644
index 0000000000..4bc367274c
--- /dev/null
+++ b/thirdparty/libwebp/enc/filter_enc.c
@@ -0,0 +1,219 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Selecting filter level
+//
+// Author: somnath@google.com (Somnath Banerjee)
+
+#include <assert.h>
+#include "./vp8i_enc.h"
+#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];
+}
+
+//------------------------------------------------------------------------------
+// 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_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_ENC * sizeof(uint8_t));
+
+ if (enc->filter_hdr_.simple_ == 1) { // simple
+ VP8SimpleHFilter16i(y_dst, BPS, limit);
+ VP8SimpleVFilter16i(y_dst, BPS, limit);
+ } else { // complex
+ const int hev_thresh = (level >= 40) ? 2 : (level >= 15) ? 1 : 0;
+ 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);
+ }
+}
+
+//------------------------------------------------------------------------------
+// SSIM metric for one macroblock
+
+static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) {
+ int x, y;
+ double sum = 0.;
+
+ // compute SSIM in a 10 x 10 window
+ for (y = VP8_SSIM_KERNEL; y < 16 - VP8_SSIM_KERNEL; y++) {
+ for (x = VP8_SSIM_KERNEL; x < 16 - VP8_SSIM_KERNEL; x++) {
+ sum += VP8SSIMGetClipped(yuv1 + Y_OFF_ENC, BPS, yuv2 + Y_OFF_ENC, BPS,
+ x, y, 16, 16);
+ }
+ }
+ for (x = 1; x < 7; x++) {
+ for (y = 1; y < 7; y++) {
+ sum += VP8SSIMGetClipped(yuv1 + U_OFF_ENC, BPS, yuv2 + U_OFF_ENC, BPS,
+ x, y, 8, 8);
+ sum += VP8SSIMGetClipped(yuv1 + V_OFF_ENC, BPS, yuv2 + V_OFF_ENC, BPS,
+ x, y, 8, 8);
+ }
+ }
+ return sum;
+}
+
+//------------------------------------------------------------------------------
+// Exposed APIs: Encoder should call the following 3 functions to adjust
+// loop filter strength
+
+void VP8InitFilter(VP8EncIterator* const it) {
+ 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;
+ }
+ }
+ VP8SSIMDspInit();
+ }
+}
+
+void VP8StoreFilterStats(VP8EncIterator* const it) {
+ int d;
+ VP8Encoder* const enc = it->enc_;
+ const int s = it->mb_->segment_;
+ const int level0 = enc->dqm_[s].fstrength_;
+
+ // explore +/-quant range of values around level0
+ 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_ == NULL) 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) {
+ VP8Encoder* const enc = it->enc_;
+ 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;
+ }
+ } 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;
+ }
+}
+
+// -----------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/frame.c b/thirdparty/libwebp/enc/frame.c
deleted file mode 100644
index 57fc471d17..0000000000
--- a/thirdparty/libwebp/enc/frame.c
+++ /dev/null
@@ -1,852 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// frame coding and analysis
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <string.h>
-#include <math.h>
-
-#include "./cost.h"
-#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
-
-//------------------------------------------------------------------------------
-// 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 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) {
- VP8EncProba* 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) {
- VP8EncProba* 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;
-}
-
-// 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 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;
- 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;
-}
-
-//------------------------------------------------------------------------------
-// Finalize Segment probability based on the coding tree
-
-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
-}
-
-static void ResetSegments(VP8Encoder* const enc) {
- int n;
- for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
- enc->mb_info_[n].segment_ = 0;
- }
-}
-
-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 != NULL) {
- 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);
- if (!enc->segment_hdr_.update_map_) ResetSegments(enc);
- 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;
- }
-}
-
-//------------------------------------------------------------------------------
-// Coefficient coding
-
-static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
- int n = res->first;
- // 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;
- }
-
- 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)) { // VP8Cat3 (3b)
- VP8PutBit(bw, 0, p[8]);
- VP8PutBit(bw, 0, p[9]);
- v -= 3 + (8 << 0);
- mask = 1 << 2;
- 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 = 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 = VP8Cat5;
- } else { // VP8Cat6 (11b)
- VP8PutBit(bw, 1, p[8]);
- VP8PutBit(bw, 1, p[10]);
- v -= 3 + (8 << 3);
- mask = 1 << 10;
- tab = VP8Cat6;
- }
- 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) {
- 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);
- VP8InitResidual(1, 0, enc, &res);
- } else {
- 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];
- 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
- 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);
- 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
- VP8InitResidual(0, 1, enc, &res);
- VP8SetResidualCoeffs(rd->y_dc_levels, &res);
- it->top_nz_[8] = it->left_nz_[8] =
- VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
- VP8InitResidual(1, 0, enc, &res);
- } else {
- 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];
- VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res);
- }
- }
-
- // U/V
- 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);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
- VP8RecordCoeffs(ctx, &res);
- }
- }
- }
-
- VP8IteratorBytesToNz(it);
-}
-
-//------------------------------------------------------------------------------
-// Token buffer
-
-#if !defined(DISABLE_TOKEN_BUFFER)
-
-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
- 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, &res, tokens);
- VP8InitResidual(1, 0, enc, &res);
- } else {
- 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];
- VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
- it->top_nz_[x] = it->left_nz_[y] =
- VP8RecordCoeffTokens(ctx, &res, tokens);
- }
- }
-
- // U/V
- 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);
- it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
- VP8RecordCoeffTokens(ctx, &res, tokens);
- }
- }
- }
- VP8IteratorBytesToNz(it);
- return !tokens->error_;
-}
-
-#endif // !DISABLE_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) {
- 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;
-}
-
-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_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;
-}
-
-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;
- }
- case 7: *info = mb->alpha_; break;
- default: *info = 0; break;
- }
- }
-#if SEGMENT_VISU // visualize segments and prediction modes
- 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
-}
-
-static double GetPSNR(uint64_t mse, uint64_t size) {
- return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99;
-}
-
-//------------------------------------------------------------------------------
-// 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.
-
-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);
- SetLoopParams(enc, s->q);
- do {
- 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_++;
- }
- 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
- 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_;
- }
- }
-
- if (ok) { // All good. Finish up.
- 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);
- }
- }
- }
- VP8AdjustFilterStrength(it); // ...and store filter stats.
- } else {
- // Something bad happened -> need to do some memory cleanup.
- VP8EncFreeBitWriters(enc);
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-// 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) {
- VP8EncIterator it;
- int ok = PreLoopInitialize(enc);
- if (!ok) return 0;
-
- StatLoop(enc); // stats-collection loop
-
- VP8IteratorInit(enc, &it);
- VP8InitFilter(&it);
- do {
- VP8ModeScore info;
- 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);
- }
- StoreSideInfo(&it);
- VP8StoreFilterStats(&it);
- VP8IteratorExport(&it);
- ok = VP8IteratorProgress(&it, 20);
- VP8IteratorSaveBoundary(&it);
- } while (ok && VP8IteratorNext(&it));
-
- return PostLoopFinalize(&it, ok);
-}
-
-//------------------------------------------------------------------------------
-// Single pass using Token Buffer.
-
-#if !defined(DISABLE_TOKEN_BUFFER)
-
-#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)
- }
- 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;
- }
- 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 (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; // done
- }
- if (do_search) {
- ComputeNextQ(&stats); // Adjust q
- }
- }
- 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
-
-//------------------------------------------------------------------------------
-
diff --git a/thirdparty/libwebp/enc/frame_enc.c b/thirdparty/libwebp/enc/frame_enc.c
new file mode 100644
index 0000000000..abef523bbf
--- /dev/null
+++ b/thirdparty/libwebp/enc/frame_enc.c
@@ -0,0 +1,854 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// frame coding and analysis
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <string.h>
+#include <math.h>
+
+#include "./cost_enc.h"
+#include "./vp8i_enc.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
+
+//------------------------------------------------------------------------------
+// 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 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) {
+ VP8EncProba* 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) {
+ VP8EncProba* 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;
+}
+
+// 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 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;
+ 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;
+}
+
+//------------------------------------------------------------------------------
+// Finalize Segment probability based on the coding tree
+
+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
+}
+
+static void ResetSegments(VP8Encoder* const enc) {
+ int n;
+ for (n = 0; n < enc->mb_w_ * enc->mb_h_; ++n) {
+ enc->mb_info_[n].segment_ = 0;
+ }
+}
+
+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 != NULL) {
+ 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);
+ if (!enc->segment_hdr_.update_map_) ResetSegments(enc);
+ 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;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Coefficient coding
+
+static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) {
+ int n = res->first;
+ // 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;
+ }
+
+ 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)) { // VP8Cat3 (3b)
+ VP8PutBit(bw, 0, p[8]);
+ VP8PutBit(bw, 0, p[9]);
+ v -= 3 + (8 << 0);
+ mask = 1 << 2;
+ 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 = 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 = VP8Cat5;
+ } else { // VP8Cat6 (11b)
+ VP8PutBit(bw, 1, p[8]);
+ VP8PutBit(bw, 1, p[10]);
+ v -= 3 + (8 << 3);
+ mask = 1 << 10;
+ tab = VP8Cat6;
+ }
+ 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) {
+ 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);
+ VP8InitResidual(1, 0, enc, &res);
+ } else {
+ 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];
+ 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
+ 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);
+ 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
+ VP8InitResidual(0, 1, enc, &res);
+ VP8SetResidualCoeffs(rd->y_dc_levels, &res);
+ it->top_nz_[8] = it->left_nz_[8] =
+ VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res);
+ VP8InitResidual(1, 0, enc, &res);
+ } else {
+ 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];
+ VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res);
+ }
+ }
+
+ // U/V
+ 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);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
+ VP8RecordCoeffs(ctx, &res);
+ }
+ }
+ }
+
+ VP8IteratorBytesToNz(it);
+}
+
+//------------------------------------------------------------------------------
+// Token buffer
+
+#if !defined(DISABLE_TOKEN_BUFFER)
+
+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
+ 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, &res, tokens);
+ VP8InitResidual(1, 0, enc, &res);
+ } else {
+ 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];
+ VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res);
+ it->top_nz_[x] = it->left_nz_[y] =
+ VP8RecordCoeffTokens(ctx, &res, tokens);
+ }
+ }
+
+ // U/V
+ 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);
+ it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] =
+ VP8RecordCoeffTokens(ctx, &res, tokens);
+ }
+ }
+ }
+ VP8IteratorBytesToNz(it);
+ return !tokens->error_;
+}
+
+#endif // !DISABLE_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) {
+ 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;
+}
+
+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_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;
+}
+
+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;
+ }
+ case 7: *info = mb->alpha_; break;
+ default: *info = 0; break;
+ }
+ }
+#if SEGMENT_VISU // visualize segments and prediction modes
+ 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
+}
+
+static double GetPSNR(uint64_t mse, uint64_t size) {
+ return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99;
+}
+
+//------------------------------------------------------------------------------
+// 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.
+
+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);
+ SetLoopParams(enc, s->q);
+ do {
+ 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_++;
+ }
+ 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
+ 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_;
+ }
+ }
+
+ if (ok) { // All good. Finish up.
+ 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);
+ }
+ }
+ }
+ VP8AdjustFilterStrength(it); // ...and store filter stats.
+ } else {
+ // Something bad happened -> need to do some memory cleanup.
+ VP8EncFreeBitWriters(enc);
+ }
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+// 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) {
+ VP8EncIterator it;
+ int ok = PreLoopInitialize(enc);
+ if (!ok) return 0;
+
+ StatLoop(enc); // stats-collection loop
+
+ VP8IteratorInit(enc, &it);
+ VP8InitFilter(&it);
+ do {
+ VP8ModeScore info;
+ 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);
+ }
+ StoreSideInfo(&it);
+ VP8StoreFilterStats(&it);
+ VP8IteratorExport(&it);
+ ok = VP8IteratorProgress(&it, 20);
+ VP8IteratorSaveBoundary(&it);
+ } while (ok && VP8IteratorNext(&it));
+
+ return PostLoopFinalize(&it, ok);
+}
+
+//------------------------------------------------------------------------------
+// Single pass using Token Buffer.
+
+#if !defined(DISABLE_TOKEN_BUFFER)
+
+#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)
+ }
+ 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;
+ }
+ 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 (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; // done
+ }
+ if (do_search) {
+ ComputeNextQ(&stats); // Adjust q
+ }
+ }
+ 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
+
+//------------------------------------------------------------------------------
+
diff --git a/thirdparty/libwebp/enc/histogram.c b/thirdparty/libwebp/enc/histogram.c
deleted file mode 100644
index 36b7f22625..0000000000
--- a/thirdparty/libwebp/enc/histogram.c
+++ /dev/null
@@ -1,938 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-//
-#ifdef HAVE_CONFIG_H
-#include "../webp/config.h"
-#endif
-
-#include <math.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) {
- 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) {
- VP8LRefsCursor c = VP8LRefsCursorInit(refs);
- while (VP8LRefsCursorOk(&c)) {
- VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
- VP8LRefsCursorNext(&c);
- }
-}
-
-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);
-}
-
-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;
- 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;
-
- set = (VP8LHistogramSet*)memory;
- memory += sizeof(*set);
- set->histograms = (VP8LHistogram**)memory;
- memory += size * sizeof(*set->histograms);
- set->max_size = size;
- set->size = size;
- for (i = 0; i < size; ++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;
-}
-
-// -----------------------------------------------------------------------------
-
-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)) {
- const int literal_ix =
- NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v);
- ++histo->literal_[literal_ix];
- } else {
- 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];
- }
-}
-
-// -----------------------------------------------------------------------------
-// Entropy-related functions.
-
-static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) {
- double mix;
- if (entropy->nonzeros < 5) {
- if (entropy->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 (entropy->nonzeros == 2) {
- return 0.99 * entropy->sum + 0.01 * entropy->entropy;
- }
- // 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 (entropy->nonzeros == 3) {
- mix = 0.95;
- } else {
- mix = 0.7; // nonzeros == 4.
- }
- } else {
- mix = 0.627;
- }
-
- {
- double min_limit = 2 * entropy->sum - entropy->max_val;
- min_limit = mix * min_limit + (1.0 - mix) * entropy->entropy;
- return (entropy->entropy < min_limit) ? min_limit : entropy->entropy;
- }
-}
-
-double VP8LBitsEntropy(const uint32_t* const array, int n,
- uint32_t* const trivial_symbol) {
- VP8LBitEntropy entropy;
- VP8LBitsEntropyUnrefined(array, n, &entropy);
- if (trivial_symbol != NULL) {
- *trivial_symbol =
- (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM;
- }
-
- return BitsEntropyRefine(&entropy);
-}
-
-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;
-}
-
-// Get the symbol entropy for the distribution 'population'.
-// Set 'trivial_sym', if there's only one symbol present in the distribution.
-static double PopulationCost(const uint32_t* const population, int length,
- uint32_t* const trivial_sym) {
- VP8LBitEntropy bit_entropy;
- VP8LStreaks stats;
- VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats);
- if (trivial_sym != NULL) {
- *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code
- : VP8L_NON_TRIVIAL_SYM;
- }
-
- return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
-}
-
-static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X,
- const uint32_t* const Y,
- int length) {
- VP8LBitEntropy bit_entropy;
- VP8LStreaks stats;
- VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
-
- return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
-}
-
-// Estimates the Entropy + Huffman + other block overhead size cost.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
- return
- PopulationCost(
- p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL)
- + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL)
- + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL)
- + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES)
- + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES);
-}
-
-// -----------------------------------------------------------------------------
-// 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 += GetCombinedEntropy(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 += GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES);
- if (*cost > cost_threshold) return 0;
-
- *cost += GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES);
- if (*cost > cost_threshold) return 0;
-
- *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES);
- if (*cost > cost_threshold) return 0;
-
- *cost += GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES);
- *cost +=
- VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES);
- if (*cost > cost_threshold) return 0;
-
- return 1;
-}
-
-// 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;
- }
-
- return cost - sum_cost;
-}
-
-// 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;
-}
-
-// -----------------------------------------------------------------------------
-
-// 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 =
- PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym);
- const double distance_cost =
- PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) +
- VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES);
- const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_);
- h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) +
- VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES,
- NUM_LENGTH_CODES);
- h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym);
- h->blue_cost_ = PopulationCost(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);
- }
-}
-
-static int GetBinIdForEntropy(double min, double max, double val) {
- const double range = max - min;
- if (range > 0.) {
- const double delta = val - min;
- return (int)((NUM_PARTITIONS - 1e-6) * delta / range);
- } else {
- return 0;
- }
-}
-
-static int GetHistoBinIndex(const VP8LHistogram* const h,
- const DominantCostRange* const c, int low_effort) {
- int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_,
- h->literal_cost_);
- assert(bin_id < NUM_PARTITIONS);
- if (!low_effort) {
- bin_id = bin_id * NUM_PARTITIONS
- + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_);
- bin_id = bin_id * NUM_PARTITIONS
- + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_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_histo->histograms;
- VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
- assert(histo_bits > 0);
- 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);
- while (x >= xsize) {
- 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) {
- const VP8LHistogram* const histo = histograms[i];
- const int bin_id = GetHistoBinIndex(histo, &cost_range, low_effort);
- 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.
- const int 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) {
- *seed *= 16807U;
- if (*seed == 0) {
- *seed = 1;
- }
- return *seed;
-}
-
-// -----------------------------------------------------------------------------
-// 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* queue;
- int size;
- int max_size;
-} HistoQueue;
-
-static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) {
- histo_queue->size = 0;
- // max_index^2 for the queue size is safe. If you look at
- // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes
- // data to the queue, you insert at most:
- // - max_index*(max_index-1)/2 (the first two for loops)
- // - max_index - 1 in the last for loop at the first iteration of the while
- // loop, max_index - 2 at the second iteration ... therefore
- // max_index*(max_index-1)/2 overall too
- histo_queue->max_size = max_index * max_index;
- // We allocate max_size + 1 because the last element at index "size" is
- // used as temporary data (and it could be up to max_size).
- histo_queue->queue = (HistogramPair*)WebPSafeMalloc(
- histo_queue->max_size + 1, sizeof(*histo_queue->queue));
- return histo_queue->queue != NULL;
-}
-
-static void HistoQueueClear(HistoQueue* const histo_queue) {
- assert(histo_queue != NULL);
- WebPSafeFree(histo_queue->queue);
-}
-
-static void SwapHistogramPairs(HistogramPair *p1,
- HistogramPair *p2) {
- const HistogramPair tmp = *p1;
- *p1 = *p2;
- *p2 = tmp;
-}
-
-// Given a valid priority queue in range [0, queue_size) this function checks
-// whether histo_queue[queue_size] should be accepted and swaps it with the
-// front if it is smaller. Otherwise, it leaves it as is.
-static void UpdateQueueFront(HistoQueue* const histo_queue) {
- if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return;
-
- if (histo_queue->queue[histo_queue->size].cost_diff <
- histo_queue->queue[0].cost_diff) {
- SwapHistogramPairs(histo_queue->queue,
- histo_queue->queue + histo_queue->size);
- }
- ++histo_queue->size;
-
- // We cannot add more elements than the capacity.
- // The allocation adds an extra element to the official capacity so that
- // histo_queue->queue[histo_queue->max_size] is read/written within bound.
- assert(histo_queue->size <= histo_queue->max_size);
-}
-
-// -----------------------------------------------------------------------------
-
-static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2,
- HistogramPair* const pair) {
- VP8LHistogram* h1;
- VP8LHistogram* h2;
- double sum_cost;
-
- if (idx1 > idx2) {
- const int tmp = idx2;
- idx2 = idx1;
- idx1 = tmp;
- }
- pair->idx1 = idx1;
- pair->idx2 = idx2;
- h1 = histograms[idx1];
- h2 = histograms[idx2];
- sum_cost = h1->bit_cost_ + h2->bit_cost_;
- pair->cost_combo = 0.;
- GetCombinedHistogramEntropy(h1, h2, sum_cost, &pair->cost_combo);
- pair->cost_diff = pair->cost_combo - sum_cost;
-}
-
-// Combines histograms by continuously choosing the one with the highest cost
-// reduction.
-static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) {
- int ok = 0;
- int image_histo_size = image_histo->size;
- int i, j;
- VP8LHistogram** const histograms = image_histo->histograms;
- // Indexes of remaining histograms.
- int* const clusters =
- (int*)WebPSafeMalloc(image_histo_size, sizeof(*clusters));
- // Priority queue of histogram pairs.
- HistoQueue histo_queue;
-
- if (!HistoQueueInit(&histo_queue, 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.
- PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size]);
- UpdateQueueFront(&histo_queue);
- }
- }
-
- while (image_histo_size > 1 && histo_queue.size > 0) {
- HistogramPair* copy_to;
- const int idx1 = histo_queue.queue[0].idx1;
- const int idx2 = histo_queue.queue[0].idx2;
- VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]);
- histograms[idx1]->bit_cost_ = histo_queue.queue[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;
-
- // Remove pairs intersecting the just combined best pair. This will
- // therefore pop the head of the queue.
- copy_to = histo_queue.queue;
- for (i = 0; i < histo_queue.size; ++i) {
- HistogramPair* const p = histo_queue.queue + i;
- if (p->idx1 == idx1 || p->idx2 == idx1 ||
- p->idx1 == idx2 || p->idx2 == idx2) {
- // Do not copy the invalid pair.
- continue;
- }
- if (p->cost_diff < histo_queue.queue[0].cost_diff) {
- // Replace the top of the queue if we found better.
- SwapHistogramPairs(histo_queue.queue, p);
- }
- SwapHistogramPairs(copy_to, p);
- ++copy_to;
- }
- histo_queue.size = (int)(copy_to - histo_queue.queue);
-
- // Push new pairs formed with combined histogram to the queue.
- for (i = 0; i < image_histo_size; ++i) {
- if (clusters[i] != idx1) {
- PreparePair(histograms, idx1, clusters[i],
- &histo_queue.queue[histo_queue.size]);
- UpdateQueueFront(&histo_queue);
- }
- }
- }
- // 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);
- HistoQueueClear(&histo_queue);
- return ok;
-}
-
-static void 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;
- 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 = -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_tries; ++j) {
- double curr_cost_diff;
- // Choose two histograms at random and try to combine them.
- 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;
- }
-
- // Calculate cost reduction on combining.
- 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_idx1 >= 0) {
- HistogramSwap(&best_combo, &histograms[best_idx1]);
- // swap best_idx2 slot with last one (which is now unused)
- --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 >= num_tries_no_success) {
- break;
- }
- }
- image_histo->size = image_histo_size;
-}
-
-// -----------------------------------------------------------------------------
-// Histogram refinement
-
-// 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;
- VP8LHistogram** const in_histo = in->histograms;
- VP8LHistogram** const out_histo = out->histograms;
- const int in_size = in->size;
- const int out_size = out->size;
- if (out_size > 1) {
- for (i = 0; i < in_size; ++i) {
- int best_out = 0;
- double best_bits = MAX_COST;
- int k;
- for (k = 0; k < out_size; ++k) {
- const double cur_bits =
- HistogramAddThresh(out_histo[k], in_histo[i], best_bits);
- if (k == 0 || cur_bits < best_bits) {
- best_bits = cur_bits;
- best_out = k;
- }
- }
- symbols[i] = best_out;
- }
- } else {
- assert(out_size == 1);
- for (i = 0; i < in_size; ++i) {
- symbols[i] = 0;
- }
- }
-
- // Recompute each out based on raw and symbols.
- for (i = 0; i < out_size; ++i) {
- HistogramClear(out_histo[i]);
- }
-
- for (i = 0; i < in_size; ++i) {
- const int idx = symbols[i];
- VP8LHistogramAdd(in_histo[i], out_histo[idx], out_histo[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 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 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));
- HistogramCombineStochastic(image_histo, tmp_histos->histograms[0],
- cur_combo, quality, threshold_size);
- if ((image_histo->size <= threshold_size) &&
- !HistogramCombineGreedy(image_histo)) {
- goto Error;
- }
- }
-
- // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also.
- // Find the optimal map from original histograms to the final ones.
- HistogramRemap(orig_histo, image_histo, histogram_symbols);
-
- ok = 1;
-
- Error:
- WebPSafeFree(bin_map);
- VP8LFreeHistogramSet(orig_histo);
- return ok;
-}
diff --git a/thirdparty/libwebp/enc/histogram.h b/thirdparty/libwebp/enc/histogram.h
deleted file mode 100644
index d303d1d58b..0000000000
--- a/thirdparty/libwebp/enc/histogram.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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 <string.h>
-
-#include "./backward_references.h"
-#include "../webp/format_constants.h"
-#include "../webp/types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Not a trivial literal symbol.
-#define VP8L_NON_TRIVIAL_SYM (0xffffffff)
-
-// A simple container for histograms of data.
-typedef struct {
- // literal_ contains green literal, palette-code and
- // copy-length-prefix histogram
- 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.
- uint32_t distance_[NUM_DISTANCE_CODES];
- int palette_code_bits_;
- 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 calling WebPSafeFree().
-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);
-
-// 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);
-
-// Collect all the references into a histogram (without reset)
-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);
-
-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 low_effort,
- int histogram_bits, int cache_bits,
- VP8LHistogramSet* const image_in,
- VP8LHistogramSet* const tmp_histos,
- uint16_t* const histogram_symbols);
-
-// 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);
-
-// Estimate how many bits the combined entropy of literals and distance
-// approximately maps to.
-double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // WEBP_ENC_HISTOGRAM_H_
diff --git a/thirdparty/libwebp/enc/histogram_enc.c b/thirdparty/libwebp/enc/histogram_enc.c
new file mode 100644
index 0000000000..808b6f78ab
--- /dev/null
+++ b/thirdparty/libwebp/enc/histogram_enc.c
@@ -0,0 +1,990 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+#ifdef HAVE_CONFIG_H
+#include "../webp/config.h"
+#endif
+
+#include <math.h>
+
+#include "./backward_references_enc.h"
+#include "./histogram_enc.h"
+#include "../dsp/lossless.h"
+#include "../dsp/lossless_common.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) {
+ 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) {
+ VP8LRefsCursor c = VP8LRefsCursorInit(refs);
+ while (VP8LRefsCursorOk(&c)) {
+ VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
+ VP8LRefsCursorNext(&c);
+ }
+}
+
+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);
+}
+
+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;
+ 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;
+
+ set = (VP8LHistogramSet*)memory;
+ memory += sizeof(*set);
+ set->histograms = (VP8LHistogram**)memory;
+ memory += size * sizeof(*set->histograms);
+ set->max_size = size;
+ set->size = size;
+ for (i = 0; i < size; ++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;
+}
+
+// -----------------------------------------------------------------------------
+
+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)) {
+ const int literal_ix =
+ NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v);
+ ++histo->literal_[literal_ix];
+ } else {
+ 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];
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Entropy-related functions.
+
+static WEBP_INLINE double BitsEntropyRefine(const VP8LBitEntropy* entropy) {
+ double mix;
+ if (entropy->nonzeros < 5) {
+ if (entropy->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 (entropy->nonzeros == 2) {
+ return 0.99 * entropy->sum + 0.01 * entropy->entropy;
+ }
+ // 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 (entropy->nonzeros == 3) {
+ mix = 0.95;
+ } else {
+ mix = 0.7; // nonzeros == 4.
+ }
+ } else {
+ mix = 0.627;
+ }
+
+ {
+ double min_limit = 2 * entropy->sum - entropy->max_val;
+ min_limit = mix * min_limit + (1.0 - mix) * entropy->entropy;
+ return (entropy->entropy < min_limit) ? min_limit : entropy->entropy;
+ }
+}
+
+double VP8LBitsEntropy(const uint32_t* const array, int n,
+ uint32_t* const trivial_symbol) {
+ VP8LBitEntropy entropy;
+ VP8LBitsEntropyUnrefined(array, n, &entropy);
+ if (trivial_symbol != NULL) {
+ *trivial_symbol =
+ (entropy.nonzeros == 1) ? entropy.nonzero_code : VP8L_NON_TRIVIAL_SYM;
+ }
+
+ return BitsEntropyRefine(&entropy);
+}
+
+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) {
+ // The constants in this function are experimental and got rounded from
+ // their original values in 1/8 when switched to 1/1024.
+ double retval = InitialHuffmanCost();
+ // Second coefficient: Many zeros in the histogram are covered efficiently
+ // by a run-length encode. Originally 2/8.
+ retval += stats->counts[0] * 1.5625 + 0.234375 * stats->streaks[0][1];
+ // Second coefficient: Constant values are encoded less efficiently, but still
+ // RLE'ed. Originally 6/8.
+ retval += stats->counts[1] * 2.578125 + 0.703125 * stats->streaks[1][1];
+ // 0s are usually encoded more efficiently than non-0s.
+ // Originally 15/8.
+ retval += 1.796875 * stats->streaks[0][0];
+ // Originally 26/8.
+ retval += 3.28125 * stats->streaks[1][0];
+ return retval;
+}
+
+// Get the symbol entropy for the distribution 'population'.
+// Set 'trivial_sym', if there's only one symbol present in the distribution.
+static double PopulationCost(const uint32_t* const population, int length,
+ uint32_t* const trivial_sym) {
+ VP8LBitEntropy bit_entropy;
+ VP8LStreaks stats;
+ VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats);
+ if (trivial_sym != NULL) {
+ *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code
+ : VP8L_NON_TRIVIAL_SYM;
+ }
+
+ return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
+}
+
+// trivial_at_end is 1 if the two histograms only have one element that is
+// non-zero: both the zero-th one, or both the last one.
+static WEBP_INLINE double GetCombinedEntropy(const uint32_t* const X,
+ const uint32_t* const Y,
+ int length, int trivial_at_end) {
+ VP8LStreaks stats;
+ if (trivial_at_end) {
+ // This configuration is due to palettization that transforms an indexed
+ // pixel into 0xff000000 | (pixel << 8) in VP8LBundleColorMap.
+ // BitsEntropyRefine is 0 for histograms with only one non-zero value.
+ // Only FinalHuffmanCost needs to be evaluated.
+ memset(&stats, 0, sizeof(stats));
+ // Deal with the non-zero value at index 0 or length-1.
+ stats.streaks[1][0] += 1;
+ // Deal with the following/previous zero streak.
+ stats.counts[0] += 1;
+ stats.streaks[0][1] += length - 1;
+ return FinalHuffmanCost(&stats);
+ } else {
+ VP8LBitEntropy bit_entropy;
+ VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
+
+ return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
+ }
+}
+
+// Estimates the Entropy + Huffman + other block overhead size cost.
+double VP8LHistogramEstimateBits(const VP8LHistogram* const p) {
+ return
+ PopulationCost(
+ p->literal_, VP8LHistogramNumCodes(p->palette_code_bits_), NULL)
+ + PopulationCost(p->red_, NUM_LITERAL_CODES, NULL)
+ + PopulationCost(p->blue_, NUM_LITERAL_CODES, NULL)
+ + PopulationCost(p->alpha_, NUM_LITERAL_CODES, NULL)
+ + PopulationCost(p->distance_, NUM_DISTANCE_CODES, NULL)
+ + VP8LExtraCost(p->literal_ + NUM_LITERAL_CODES, NUM_LENGTH_CODES)
+ + VP8LExtraCost(p->distance_, NUM_DISTANCE_CODES);
+}
+
+// -----------------------------------------------------------------------------
+// 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_;
+ int trivial_at_end = 0;
+ assert(a->palette_code_bits_ == b->palette_code_bits_);
+ *cost += GetCombinedEntropy(a->literal_, b->literal_,
+ VP8LHistogramNumCodes(palette_code_bits), 0);
+ *cost += VP8LExtraCostCombined(a->literal_ + NUM_LITERAL_CODES,
+ b->literal_ + NUM_LITERAL_CODES,
+ NUM_LENGTH_CODES);
+ if (*cost > cost_threshold) return 0;
+
+ if (a->trivial_symbol_ != VP8L_NON_TRIVIAL_SYM &&
+ a->trivial_symbol_ == b->trivial_symbol_) {
+ // A, R and B are all 0 or 0xff.
+ const uint32_t color_a = (a->trivial_symbol_ >> 24) & 0xff;
+ const uint32_t color_r = (a->trivial_symbol_ >> 16) & 0xff;
+ const uint32_t color_b = (a->trivial_symbol_ >> 0) & 0xff;
+ if ((color_a == 0 || color_a == 0xff) &&
+ (color_r == 0 || color_r == 0xff) &&
+ (color_b == 0 || color_b == 0xff)) {
+ trivial_at_end = 1;
+ }
+ }
+
+ *cost +=
+ GetCombinedEntropy(a->red_, b->red_, NUM_LITERAL_CODES, trivial_at_end);
+ if (*cost > cost_threshold) return 0;
+
+ *cost +=
+ GetCombinedEntropy(a->blue_, b->blue_, NUM_LITERAL_CODES, trivial_at_end);
+ if (*cost > cost_threshold) return 0;
+
+ *cost += GetCombinedEntropy(a->alpha_, b->alpha_, NUM_LITERAL_CODES,
+ trivial_at_end);
+ if (*cost > cost_threshold) return 0;
+
+ *cost +=
+ GetCombinedEntropy(a->distance_, b->distance_, NUM_DISTANCE_CODES, 0);
+ *cost +=
+ VP8LExtraCostCombined(a->distance_, b->distance_, NUM_DISTANCE_CODES);
+ if (*cost > cost_threshold) return 0;
+
+ return 1;
+}
+
+static WEBP_INLINE void HistogramAdd(const VP8LHistogram* const a,
+ const VP8LHistogram* const b,
+ VP8LHistogram* const out) {
+ VP8LHistogramAdd(a, b, out);
+ out->trivial_symbol_ = (a->trivial_symbol_ == b->trivial_symbol_)
+ ? a->trivial_symbol_
+ : VP8L_NON_TRIVIAL_SYM;
+}
+
+// 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)) {
+ HistogramAdd(a, b, out);
+ out->bit_cost_ = cost;
+ out->palette_code_bits_ = a->palette_code_bits_;
+ }
+
+ return cost - sum_cost;
+}
+
+// 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;
+}
+
+// -----------------------------------------------------------------------------
+
+// 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 =
+ PopulationCost(h->alpha_, NUM_LITERAL_CODES, &alpha_sym);
+ const double distance_cost =
+ PopulationCost(h->distance_, NUM_DISTANCE_CODES, NULL) +
+ VP8LExtraCost(h->distance_, NUM_DISTANCE_CODES);
+ const int num_codes = VP8LHistogramNumCodes(h->palette_code_bits_);
+ h->literal_cost_ = PopulationCost(h->literal_, num_codes, NULL) +
+ VP8LExtraCost(h->literal_ + NUM_LITERAL_CODES,
+ NUM_LENGTH_CODES);
+ h->red_cost_ = PopulationCost(h->red_, NUM_LITERAL_CODES, &red_sym);
+ h->blue_cost_ = PopulationCost(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);
+ }
+}
+
+static int GetBinIdForEntropy(double min, double max, double val) {
+ const double range = max - min;
+ if (range > 0.) {
+ const double delta = val - min;
+ return (int)((NUM_PARTITIONS - 1e-6) * delta / range);
+ } else {
+ return 0;
+ }
+}
+
+static int GetHistoBinIndex(const VP8LHistogram* const h,
+ const DominantCostRange* const c, int low_effort) {
+ int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_,
+ h->literal_cost_);
+ assert(bin_id < NUM_PARTITIONS);
+ if (!low_effort) {
+ bin_id = bin_id * NUM_PARTITIONS
+ + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_);
+ bin_id = bin_id * NUM_PARTITIONS
+ + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_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_histo->histograms;
+ VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
+ assert(histo_bits > 0);
+ 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);
+ while (x >= xsize) {
+ 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,
+ uint16_t* const bin_map,
+ int low_effort) {
+ int i;
+ VP8LHistogram** const histograms = image_histo->histograms;
+ const int histo_size = image_histo->size;
+ DominantCostRange cost_range;
+ DominantCostRangeInit(&cost_range);
+
+ // Analyze the dominant (literal, red and blue) entropy costs.
+ for (i = 0; i < histo_size; ++i) {
+ UpdateDominantCostRange(histograms[i], &cost_range);
+ }
+
+ // bin-hash histograms on three of the dominant (literal, red and blue)
+ // symbol costs and store the resulting bin_id for each histogram.
+ for (i = 0; i < histo_size; ++i) {
+ bin_map[i] = GetHistoBinIndex(histograms[i], &cost_range, low_effort);
+ }
+}
+
+// Compact image_histo[] by merging some histograms with same bin_id together if
+// it's advantageous.
+static VP8LHistogram* HistogramCombineEntropyBin(
+ VP8LHistogramSet* const image_histo,
+ VP8LHistogram* cur_combo,
+ const uint16_t* const bin_map, int bin_map_size, int num_bins,
+ double combine_cost_factor, int low_effort) {
+ VP8LHistogram** const histograms = image_histo->histograms;
+ int idx;
+ // Work in-place: processed histograms are put at the beginning of
+ // image_histo[]. At the end, we just have to truncate the array.
+ int size = 0;
+ struct {
+ int16_t first; // position of the histogram that accumulates all
+ // histograms with the same bin_id
+ uint16_t num_combine_failures; // number of combine failures per bin_id
+ } bin_info[BIN_SIZE];
+
+ assert(num_bins <= BIN_SIZE);
+ for (idx = 0; idx < num_bins; ++idx) {
+ bin_info[idx].first = -1;
+ bin_info[idx].num_combine_failures = 0;
+ }
+
+ for (idx = 0; idx < bin_map_size; ++idx) {
+ const int bin_id = bin_map[idx];
+ const int first = bin_info[bin_id].first;
+ assert(size <= idx);
+ if (first == -1) {
+ // just move histogram #idx to its final position
+ histograms[size] = histograms[idx];
+ bin_info[bin_id].first = size++;
+ } else if (low_effort) {
+ HistogramAdd(histograms[idx], histograms[first], histograms[first]);
+ } else {
+ // try to merge #idx into #first (both share the same bin_id)
+ const double bit_cost = histograms[idx]->bit_cost_;
+ const double bit_cost_thresh = -bit_cost * combine_cost_factor;
+ const double curr_cost_diff =
+ HistogramAddEval(histograms[first], histograms[idx],
+ 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[idx]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM) &&
+ (histograms[first]->trivial_symbol_ == VP8L_NON_TRIVIAL_SYM));
+ const int max_combine_failures = 32;
+ if (try_combine ||
+ bin_info[bin_id].num_combine_failures >= max_combine_failures) {
+ // move the (better) merged histogram to its final slot
+ HistogramSwap(&cur_combo, &histograms[first]);
+ } else {
+ histograms[size++] = histograms[idx];
+ ++bin_info[bin_id].num_combine_failures;
+ }
+ } else {
+ histograms[size++] = histograms[idx];
+ }
+ }
+ }
+ image_histo->size = size;
+ if (low_effort) {
+ // for low_effort case, update the final cost when everything is merged
+ for (idx = 0; idx < size; ++idx) {
+ UpdateHistogramCost(histograms[idx]);
+ }
+ }
+ return cur_combo;
+}
+
+static uint32_t MyRand(uint32_t* const seed) {
+ *seed = (*seed * 16807ull) & 0xffffffffu;
+ if (*seed == 0) {
+ *seed = 1;
+ }
+ return *seed;
+}
+
+// -----------------------------------------------------------------------------
+// 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* queue;
+ int size;
+ int max_size;
+} HistoQueue;
+
+static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) {
+ histo_queue->size = 0;
+ // max_index^2 for the queue size is safe. If you look at
+ // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes
+ // data to the queue, you insert at most:
+ // - max_index*(max_index-1)/2 (the first two for loops)
+ // - max_index - 1 in the last for loop at the first iteration of the while
+ // loop, max_index - 2 at the second iteration ... therefore
+ // max_index*(max_index-1)/2 overall too
+ histo_queue->max_size = max_index * max_index;
+ // We allocate max_size + 1 because the last element at index "size" is
+ // used as temporary data (and it could be up to max_size).
+ histo_queue->queue = (HistogramPair*)WebPSafeMalloc(
+ histo_queue->max_size + 1, sizeof(*histo_queue->queue));
+ return histo_queue->queue != NULL;
+}
+
+static void HistoQueueClear(HistoQueue* const histo_queue) {
+ assert(histo_queue != NULL);
+ WebPSafeFree(histo_queue->queue);
+}
+
+static void SwapHistogramPairs(HistogramPair *p1,
+ HistogramPair *p2) {
+ const HistogramPair tmp = *p1;
+ *p1 = *p2;
+ *p2 = tmp;
+}
+
+// Given a valid priority queue in range [0, queue_size) this function checks
+// whether histo_queue[queue_size] should be accepted and swaps it with the
+// front if it is smaller. Otherwise, it leaves it as is.
+static void UpdateQueueFront(HistoQueue* const histo_queue) {
+ if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return;
+
+ if (histo_queue->queue[histo_queue->size].cost_diff <
+ histo_queue->queue[0].cost_diff) {
+ SwapHistogramPairs(histo_queue->queue,
+ histo_queue->queue + histo_queue->size);
+ }
+ ++histo_queue->size;
+
+ // We cannot add more elements than the capacity.
+ // The allocation adds an extra element to the official capacity so that
+ // histo_queue->queue[histo_queue->max_size] is read/written within bound.
+ assert(histo_queue->size <= histo_queue->max_size);
+}
+
+// -----------------------------------------------------------------------------
+
+static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2,
+ HistogramPair* const pair) {
+ VP8LHistogram* h1;
+ VP8LHistogram* h2;
+ double sum_cost;
+
+ if (idx1 > idx2) {
+ const int tmp = idx2;
+ idx2 = idx1;
+ idx1 = tmp;
+ }
+ pair->idx1 = idx1;
+ pair->idx2 = idx2;
+ h1 = histograms[idx1];
+ h2 = histograms[idx2];
+ sum_cost = h1->bit_cost_ + h2->bit_cost_;
+ pair->cost_combo = 0.;
+ GetCombinedHistogramEntropy(h1, h2, sum_cost, &pair->cost_combo);
+ pair->cost_diff = pair->cost_combo - sum_cost;
+}
+
+// Combines histograms by continuously choosing the one with the highest cost
+// reduction.
+static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) {
+ int ok = 0;
+ int image_histo_size = image_histo->size;
+ int i, j;
+ VP8LHistogram** const histograms = image_histo->histograms;
+ // Indexes of remaining histograms.
+ int* const clusters =
+ (int*)WebPSafeMalloc(image_histo_size, sizeof(*clusters));
+ // Priority queue of histogram pairs.
+ HistoQueue histo_queue;
+
+ if (!HistoQueueInit(&histo_queue, 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.
+ PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size]);
+ UpdateQueueFront(&histo_queue);
+ }
+ }
+
+ while (image_histo_size > 1 && histo_queue.size > 0) {
+ HistogramPair* copy_to;
+ const int idx1 = histo_queue.queue[0].idx1;
+ const int idx2 = histo_queue.queue[0].idx2;
+ HistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]);
+ histograms[idx1]->bit_cost_ = histo_queue.queue[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;
+
+ // Remove pairs intersecting the just combined best pair. This will
+ // therefore pop the head of the queue.
+ copy_to = histo_queue.queue;
+ for (i = 0; i < histo_queue.size; ++i) {
+ HistogramPair* const p = histo_queue.queue + i;
+ if (p->idx1 == idx1 || p->idx2 == idx1 ||
+ p->idx1 == idx2 || p->idx2 == idx2) {
+ // Do not copy the invalid pair.
+ continue;
+ }
+ if (p->cost_diff < histo_queue.queue[0].cost_diff) {
+ // Replace the top of the queue if we found better.
+ SwapHistogramPairs(histo_queue.queue, p);
+ }
+ SwapHistogramPairs(copy_to, p);
+ ++copy_to;
+ }
+ histo_queue.size = (int)(copy_to - histo_queue.queue);
+
+ // Push new pairs formed with combined histogram to the queue.
+ for (i = 0; i < image_histo_size; ++i) {
+ if (clusters[i] != idx1) {
+ PreparePair(histograms, idx1, clusters[i],
+ &histo_queue.queue[histo_queue.size]);
+ UpdateQueueFront(&histo_queue);
+ }
+ }
+ }
+ // 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);
+ HistoQueueClear(&histo_queue);
+ return ok;
+}
+
+static void 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;
+ 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;
+ int idx2_max = image_histo_size - 1;
+ int do_brute_dorce = 0;
+ 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 = -1, best_idx2 = 1;
+ int j;
+ int num_tries =
+ (num_pairs < image_histo_size) ? num_pairs : image_histo_size;
+ // Use a brute force approach if:
+ // - stochastic has not worked for a while and
+ // - if the number of iterations for brute force is less than the number of
+ // iterations if we never find a match ever again stochastically (hence
+ // num_tries times the number of remaining outer iterations).
+ do_brute_dorce =
+ (tries_with_no_success > 10) &&
+ (idx2_max * (idx2_max + 1) < 2 * num_tries * (outer_iters - iter));
+ if (do_brute_dorce) num_tries = idx2_max;
+
+ seed += iter;
+ for (j = 0; j < num_tries; ++j) {
+ double curr_cost_diff;
+ // Choose two histograms at random and try to combine them.
+ uint32_t idx1, idx2;
+ if (do_brute_dorce) {
+ // Use a brute force approach.
+ idx1 = (uint32_t)j;
+ idx2 = (uint32_t)idx2_max;
+ } else {
+ const uint32_t tmp = (j & 7) + 1;
+ const uint32_t diff =
+ (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1);
+ idx1 = MyRand(&seed) % image_histo_size;
+ idx2 = (idx1 + diff + 1) % image_histo_size;
+ if (idx1 == idx2) {
+ continue;
+ }
+ }
+
+ // Calculate cost reduction on combining.
+ 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 (do_brute_dorce) --idx2_max;
+
+ if (best_idx1 >= 0) {
+ HistogramSwap(&best_combo, &histograms[best_idx1]);
+ // swap best_idx2 slot with last one (which is now unused)
+ --image_histo_size;
+ if (idx2_max >= image_histo_size) idx2_max = image_histo_size - 1;
+ 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 >= num_tries_no_success || idx2_max == 0) {
+ break;
+ }
+ }
+ image_histo->size = image_histo_size;
+}
+
+// -----------------------------------------------------------------------------
+// Histogram refinement
+
+// 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;
+ VP8LHistogram** const in_histo = in->histograms;
+ VP8LHistogram** const out_histo = out->histograms;
+ const int in_size = in->size;
+ const int out_size = out->size;
+ if (out_size > 1) {
+ for (i = 0; i < in_size; ++i) {
+ int best_out = 0;
+ double best_bits = MAX_COST;
+ int k;
+ for (k = 0; k < out_size; ++k) {
+ const double cur_bits =
+ HistogramAddThresh(out_histo[k], in_histo[i], best_bits);
+ if (k == 0 || cur_bits < best_bits) {
+ best_bits = cur_bits;
+ best_out = k;
+ }
+ }
+ symbols[i] = best_out;
+ }
+ } else {
+ assert(out_size == 1);
+ for (i = 0; i < in_size; ++i) {
+ symbols[i] = 0;
+ }
+ }
+
+ // Recompute each out based on raw and symbols.
+ for (i = 0; i < out_size; ++i) {
+ HistogramClear(out_histo[i]);
+ }
+
+ for (i = 0; i < in_size; ++i) {
+ const int idx = symbols[i];
+ HistogramAdd(in_histo[i], out_histo[idx], out_histo[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 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 image_histo_raw_size = histo_xsize * histo_ysize;
+ VP8LHistogramSet* const orig_histo =
+ VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits);
+ VP8LHistogram* cur_combo;
+ // 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).
+ const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE;
+ const int entropy_combine =
+ (orig_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
+
+ if (orig_histo == 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 int bin_map_size = orig_histo->size;
+ // Reuse histogram_symbols storage. By definition, it's guaranteed to be ok.
+ uint16_t* const bin_map = histogram_symbols;
+ 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_map_size,
+ 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));
+ HistogramCombineStochastic(image_histo, tmp_histos->histograms[0],
+ cur_combo, quality, threshold_size);
+ if ((image_histo->size <= threshold_size) &&
+ !HistogramCombineGreedy(image_histo)) {
+ goto Error;
+ }
+ }
+
+ // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also.
+ // Find the optimal map from original histograms to the final ones.
+ HistogramRemap(orig_histo, image_histo, histogram_symbols);
+
+ ok = 1;
+
+ Error:
+ VP8LFreeHistogramSet(orig_histo);
+ return ok;
+}
diff --git a/thirdparty/libwebp/enc/histogram_enc.h b/thirdparty/libwebp/enc/histogram_enc.h
new file mode 100644
index 0000000000..a9d258a166
--- /dev/null
+++ b/thirdparty/libwebp/enc/histogram_enc.h
@@ -0,0 +1,123 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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 <string.h>
+
+#include "./backward_references_enc.h"
+#include "../webp/format_constants.h"
+#include "../webp/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Not a trivial literal symbol.
+#define VP8L_NON_TRIVIAL_SYM (0xffffffff)
+
+// A simple container for histograms of data.
+typedef struct {
+ // literal_ contains green literal, palette-code and
+ // copy-length-prefix histogram
+ 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.
+ uint32_t distance_[NUM_DISTANCE_CODES];
+ int palette_code_bits_;
+ 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 calling WebPSafeFree().
+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);
+
+// 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);
+
+// Collect all the references into a histogram (without reset)
+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);
+
+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 low_effort,
+ int histogram_bits, int cache_bits,
+ VP8LHistogramSet* const image_in,
+ VP8LHistogramSet* const tmp_histos,
+ uint16_t* const histogram_symbols);
+
+// 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);
+
+// Estimate how many bits the combined entropy of literals and distance
+// approximately maps to.
+double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WEBP_ENC_HISTOGRAM_H_
diff --git a/thirdparty/libwebp/enc/iterator.c b/thirdparty/libwebp/enc/iterator.c
deleted file mode 100644
index 99d960a547..0000000000
--- a/thirdparty/libwebp/enc/iterator.c
+++ /dev/null
@@ -1,456 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// VP8Iterator: block iterator
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <string.h>
-
-#include "./vp8enci.h"
-
-//------------------------------------------------------------------------------
-// VP8Iterator
-//------------------------------------------------------------------------------
-
-static void InitLeft(VP8EncIterator* const it) {
- it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] =
- (it->y_ > 0) ? 129 : 127;
- memset(it->y_left_, 129, 16);
- memset(it->u_left_, 129, 8);
- memset(it->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 VP8IteratorSetRow(VP8EncIterator* const it, int y) {
- VP8Encoder* const enc = it->enc_;
- it->x_ = 0;
- 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->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;
- 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 != NULL) {
- const int done = it->count_down0_ - it->count_down_;
- const int percent = (it->count_down0_ <= 0)
- ? it->percent0_
- : it->percent0_ + delta * done / it->count_down0_;
- 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 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;
- 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;
- }
-}
-
-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 usrc = pic->u + (y * pic->uv_stride + x) * 8;
- const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 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);
- }
-}
-
-//------------------------------------------------------------------------------
-// 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_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;
- 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 bookkeeping.
-
-void VP8IteratorSaveBoundary(VP8EncIterator* const it) {
- VP8Encoder* const enc = it->enc_;
- 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];
- }
- 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);
- }
-}
-
-int VP8IteratorNext(VP8EncIterator* const it) {
- it->preds_ += 4;
- 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->count_down_);
-}
-
-//------------------------------------------------------------------------------
-// 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] = it->y_left_[15 - i];
- }
- for (i = 0; i < 16; ++i) { // top
- 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] = it->y_top_[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;
-}
-
-//------------------------------------------------------------------------------
-
diff --git a/thirdparty/libwebp/enc/iterator_enc.c b/thirdparty/libwebp/enc/iterator_enc.c
new file mode 100644
index 0000000000..e48d30bd31
--- /dev/null
+++ b/thirdparty/libwebp/enc/iterator_enc.c
@@ -0,0 +1,453 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// VP8Iterator: block iterator
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <string.h>
+
+#include "./vp8i_enc.h"
+
+//------------------------------------------------------------------------------
+// VP8Iterator
+//------------------------------------------------------------------------------
+
+static void InitLeft(VP8EncIterator* const it) {
+ it->y_left_[-1] = it->u_left_[-1] = it->v_left_[-1] =
+ (it->y_ > 0) ? 129 : 127;
+ memset(it->y_left_, 129, 16);
+ memset(it->u_left_, 129, 8);
+ memset(it->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 VP8IteratorSetRow(VP8EncIterator* const it, int y) {
+ VP8Encoder* const enc = it->enc_;
+ it->x_ = 0;
+ 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->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);
+ 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->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 != NULL) {
+ const int done = it->count_down0_ - it->count_down_;
+ const int percent = (it->count_down0_ <= 0)
+ ? it->percent0_
+ : it->percent0_ + delta * done / it->count_down0_;
+ 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 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;
+ 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;
+ }
+}
+
+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 usrc = pic->u + (y * pic->uv_stride + x) * 8;
+ const uint8_t* const vsrc = pic->v + (y * pic->uv_stride + x) * 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);
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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_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;
+ 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 bookkeeping.
+
+void VP8IteratorSaveBoundary(VP8EncIterator* const it) {
+ VP8Encoder* const enc = it->enc_;
+ 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];
+ }
+ 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);
+ }
+}
+
+int VP8IteratorNext(VP8EncIterator* const it) {
+ if (++it->x_ == it->enc_->mb_w_) {
+ VP8IteratorSetRow(it, ++it->y_);
+ } else {
+ it->preds_ += 4;
+ it->mb_ += 1;
+ it->nz_ += 1;
+ it->y_top_ += 16;
+ it->uv_top_ += 16;
+ }
+ return (0 < --it->count_down_);
+}
+
+//------------------------------------------------------------------------------
+// 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] = it->y_left_[15 - i];
+ }
+ for (i = 0; i < 16; ++i) { // top
+ 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] = it->y_top_[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;
+}
+
+//------------------------------------------------------------------------------
+
diff --git a/thirdparty/libwebp/enc/near_lossless.c b/thirdparty/libwebp/enc/near_lossless.c
deleted file mode 100644
index f4ab91f571..0000000000
--- a/thirdparty/libwebp/enc/near_lossless.c
+++ /dev/null
@@ -1,122 +0,0 @@
-// 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 <assert.h>
-#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
-
-// Quantizes the value up or down to a multiple of 1<<bits (or to 255),
-// choosing the closer one, resolving ties using bankers' rounding.
-static int FindClosestDiscretized(int a, int bits) {
- const int mask = (1 << bits) - 1;
- const int biased = a + (mask >> 1) + ((a >> bits) & 1);
- assert(bits > 0);
- if (biased > 0xff) return 0xff;
- return biased & ~mask;
-}
-
-// 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;
- }
- }
-}
-
-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 = VP8LNearLosslessBits(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/thirdparty/libwebp/enc/near_lossless_enc.c b/thirdparty/libwebp/enc/near_lossless_enc.c
new file mode 100644
index 0000000000..2bd03ab20d
--- /dev/null
+++ b/thirdparty/libwebp/enc/near_lossless_enc.c
@@ -0,0 +1,122 @@
+// 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 <assert.h>
+#include <stdlib.h>
+
+#include "../dsp/lossless_common.h"
+#include "../utils/utils.h"
+#include "./vp8i_enc.h"
+
+#define MIN_DIM_FOR_NEAR_LOSSLESS 64
+#define MAX_LIMIT_BITS 5
+
+// Quantizes the value up or down to a multiple of 1<<bits (or to 255),
+// choosing the closer one, resolving ties using bankers' rounding.
+static int FindClosestDiscretized(int a, int bits) {
+ const int mask = (1 << bits) - 1;
+ const int biased = a + (mask >> 1) + ((a >> bits) & 1);
+ assert(bits > 0);
+ if (biased > 0xff) return 0xff;
+ return biased & ~mask;
+}
+
+// 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;
+ }
+ }
+}
+
+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 = VP8LNearLosslessBits(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/thirdparty/libwebp/enc/picture.c b/thirdparty/libwebp/enc/picture.c
deleted file mode 100644
index 28c56cd6e5..0000000000
--- a/thirdparty/libwebp/enc/picture.c
+++ /dev/null
@@ -1,293 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// WebPPicture class basis
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./vp8enci.h"
-#include "../dsp/dsp.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// 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;
-}
-
-//------------------------------------------------------------------------------
-
-static void WebPPictureResetBufferARGB(WebPPicture* const picture) {
- picture->memory_argb_ = NULL;
- picture->argb = NULL;
- picture->argb_stride = 0;
-}
-
-static void WebPPictureResetBufferYUVA(WebPPicture* const picture) {
- picture->memory_ = NULL;
- picture->y = picture->u = picture->v = picture->a = NULL;
- picture->y_stride = picture->uv_stride = 0;
- picture->a_stride = 0;
-}
-
-void WebPPictureResetBuffers(WebPPicture* const picture) {
- WebPPictureResetBufferARGB(picture);
- WebPPictureResetBufferYUVA(picture);
-}
-
-int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) {
- void* memory;
- const uint64_t argb_size = (uint64_t)width * height;
-
- assert(picture != NULL);
-
- WebPSafeFree(picture->memory_argb_);
- WebPPictureResetBufferARGB(picture);
-
- if (width <= 0 || height <= 0) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
- }
- // allocate a new buffer.
- memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb));
- if (memory == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- // TODO(skal): align plane to cache line?
- picture->memory_argb_ = memory;
- picture->argb = (uint32_t*)memory;
- picture->argb_stride = width;
- return 1;
-}
-
-int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) {
- const WebPEncCSP uv_csp =
- (WebPEncCSP)((int)picture->colorspace & WEBP_CSP_UV_MASK);
- const int has_alpha = (int)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;
-
- assert(picture != NULL);
-
- WebPSafeFree(picture->memory_);
- WebPPictureResetBufferYUVA(picture);
-
- if (uv_csp != WEBP_YUV420) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
- }
-
- // 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;
-
- // 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);
- }
- // allocate a new buffer.
- mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem));
- if (mem == NULL) {
- return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
-
- // 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;
-
- // 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 > 0) {
- picture->a = mem;
- mem += a_size;
- }
- (void)mem; // makes the static analyzer happy
- return 1;
-}
-
-int WebPPictureAlloc(WebPPicture* picture) {
- if (picture != NULL) {
- const int width = picture->width;
- const int height = picture->height;
-
- WebPPictureFree(picture); // erase previous buffer
-
- if (!picture->use_argb) {
- return WebPPictureAllocYUVA(picture, width, height);
- } else {
- return WebPPictureAllocARGB(picture, width, height);
- }
- }
- return 1;
-}
-
-void WebPPictureFree(WebPPicture* picture) {
- if (picture != NULL) {
- WebPSafeFree(picture->memory_);
- WebPSafeFree(picture->memory_argb_);
- WebPPictureResetBuffers(picture);
- }
-}
-
-//------------------------------------------------------------------------------
-// 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);
- }
- WebPSafeFree(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;
-}
-
-void WebPMemoryWriterClear(WebPMemoryWriter* writer) {
- if (writer != NULL) {
- WebPSafeFree(writer->mem);
- writer->mem = NULL;
- writer->size = 0;
- writer->max_size = 0;
- }
-}
-
-//------------------------------------------------------------------------------
-// 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 (output == NULL) return 0;
-
- 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) {
- WebPMemoryWriterClear(&wrt);
- *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
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/picture_csp.c b/thirdparty/libwebp/enc/picture_csp.c
deleted file mode 100644
index 188a3ca55b..0000000000
--- a/thirdparty/libwebp/enc/picture_csp.c
+++ /dev/null
@@ -1,1192 +0,0 @@
-// 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* best_y, const fixed_t* best_uv,
- WebPPicture* const picture) {
- int i, j;
- uint8_t* dst_y = picture->y;
- uint8_t* dst_u = picture->u;
- uint8_t* dst_v = picture->v;
- const fixed_t* const best_uv_base = best_uv;
- 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 (best_uv = best_uv_base, j = 0; j < picture->height; ++j) {
- for (i = 0; i < picture->width; ++i) {
- const int off = 3 * (i >> 1);
- const int W = best_y[i];
- const int r = best_uv[off + 0] + W;
- const int g = best_uv[off + 1] + W;
- const int b = best_uv[off + 2] + W;
- dst_y[i] = ConvertRGBToY(r, g, b);
- }
- best_y += w;
- best_uv += (j & 1) * 3 * uv_w;
- dst_y += picture->y_stride;
- }
- for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) {
- for (i = 0; i < uv_w; ++i) {
- const int off = 3 * i;
- 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);
- }
- best_uv += 3 * uv_w;
- dst_u += picture->uv_stride;
- dst_v += picture->uv_stride;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
-// Main function
-
-#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T)))
-
-static int PreprocessARGB(const uint8_t* r_ptr,
- const uint8_t* g_ptr,
- const uint8_t* 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_base = SAFE_ALLOC(w, h, fixed_y_t);
- fixed_y_t* const target_y_base = 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_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
- fixed_t* const target_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
- fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t);
- fixed_y_t* best_y = best_y_base;
- fixed_y_t* target_y = target_y_base;
- fixed_t* best_uv = best_uv_base;
- fixed_t* target_uv = target_uv_base;
- 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_base == NULL || best_uv_base == NULL ||
- target_y_base == NULL || target_uv_base == 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;
-
- // prepare two rows of input
- ImportOneRow(r_ptr, g_ptr, b_ptr, step, picture->width, src1);
- if (!is_last_row) {
- ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
- step, picture->width, src2);
- } else {
- memcpy(src2, src1, 3 * w * sizeof(*src2));
- }
- UpdateW(src1, target_y, w);
- UpdateW(src2, target_y + w, w);
- diff_sum += UpdateChroma(src1, src2, target_uv, best_y, uv_w);
- memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv));
- memcpy(best_y + w, best_y, w * sizeof(*best_y));
- best_y += 2 * w;
- best_uv += 3 * uv_w;
- target_y += 2 * w;
- target_uv += 3 * uv_w;
- r_ptr += 2 * rgb_stride;
- g_ptr += 2 * rgb_stride;
- b_ptr += 2 * rgb_stride;
- }
-
- // Iterate and resolve clipping conflicts.
- for (iter = 0; iter < kNumIterations; ++iter) {
- int k;
- const fixed_t* cur_uv = best_uv_base;
- const fixed_t* prev_uv = best_uv_base;
- const int old_diff_sum = diff_sum;
- diff_sum = 0;
-
- best_y = best_y_base;
- best_uv = best_uv_base;
- target_y = target_y_base;
- target_uv = target_uv_base;
- 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, 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 diff_y = target_y[i] - best_rgb_y[i];
- const int new_y = (int)best_y[i] + diff_y;
- best_y[i] = clip_y(new_y);
- }
- for (i = 0; i < uv_w; ++i) {
- const int off = 3 * i;
- int W;
- for (k = 0; k <= 2; ++k) {
- const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[off + 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;
- }
- }
- best_y += 2 * w;
- best_uv += 3 * uv_w;
- target_y += 2 * w;
- target_uv += 3 * uv_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_base, best_uv_base, picture);
-
- End:
- WebPSafeFree(best_y_base);
- WebPSafeFree(best_uv_base);
- WebPSafeFree(target_y_base);
- WebPSafeFree(target_uv_base);
- 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* r_ptr,
- const uint8_t* g_ptr,
- const uint8_t* b_ptr,
- const uint8_t* 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;
- if (use_dsp) {
- if (is_rgb) {
- WebPConvertRGB24ToY(r_ptr, dst_y, width);
- WebPConvertRGB24ToY(r_ptr + rgb_stride,
- dst_y + picture->y_stride, width);
- } else {
- WebPConvertBGR24ToY(b_ptr, dst_y, width);
- WebPConvertBGR24ToY(b_ptr + rgb_stride,
- dst_y + picture->y_stride, width);
- }
- } else {
- ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
- ConvertRowToY(r_ptr + rgb_stride,
- g_ptr + rgb_stride,
- b_ptr + rgb_stride, step,
- dst_y + picture->y_stride, width, rg);
- }
- dst_y += 2 * picture->y_stride;
- if (has_alpha) {
- rows_have_alpha &= !WebPExtractAlpha(a_ptr, 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, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, width);
- } else {
- AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, 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;
- r_ptr += 2 * rgb_stride;
- b_ptr += 2 * rgb_stride;
- g_ptr += 2 * rgb_stride;
- if (has_alpha) a_ptr += 2 * rgb_stride;
- }
- if (height & 1) { // extra last row
- int row_has_alpha = has_alpha;
- if (use_dsp) {
- if (r_ptr < b_ptr) {
- WebPConvertRGB24ToY(r_ptr, dst_y, width);
- } else {
- WebPConvertBGR24ToY(b_ptr, dst_y, width);
- }
- } else {
- ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
- }
- if (row_has_alpha) {
- row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0);
- }
- // Collect averaged R/G/B(/A)
- if (!row_has_alpha) {
- // Collect averaged R/G/B
- AccumulateRGB(r_ptr, g_ptr, b_ptr, step, /* rgb_stride = */ 0,
- tmp_rgb, width);
- } else {
- AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /* 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* r_ptr = rgb + (swap_rb ? 2 : 0);
- const uint8_t* g_ptr = rgb + 1;
- const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2);
- const uint8_t* 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) {
- uint32_t* dst = picture->argb;
- assert(step == 4);
- for (y = 0; y < height; ++y) {
- VP8PackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst);
- a_ptr += rgb_stride;
- r_ptr += rgb_stride;
- g_ptr += rgb_stride;
- b_ptr += rgb_stride;
- dst += picture->argb_stride;
- }
- } else {
- uint32_t* dst = picture->argb;
- assert(step >= 3);
- for (y = 0; y < height; ++y) {
- VP8PackRGB(r_ptr, g_ptr, b_ptr, width, step, dst);
- r_ptr += rgb_stride;
- g_ptr += rgb_stride;
- b_ptr += rgb_stride;
- dst += picture->argb_stride;
- }
- }
- return 1;
-}
-
-// Public API
-
-int WebPPictureImportRGB(WebPPicture* picture,
- const uint8_t* rgb, int rgb_stride) {
- return (picture != NULL && rgb != NULL)
- ? Import(picture, rgb, rgb_stride, 3, 0, 0)
- : 0;
-}
-
-int WebPPictureImportBGR(WebPPicture* picture,
- const uint8_t* rgb, int rgb_stride) {
- return (picture != NULL && rgb != NULL)
- ? Import(picture, rgb, rgb_stride, 3, 1, 0)
- : 0;
-}
-
-int WebPPictureImportRGBA(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 0, 1)
- : 0;
-}
-
-int WebPPictureImportBGRA(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 1, 1)
- : 0;
-}
-
-int WebPPictureImportRGBX(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 0, 0)
- : 0;
-}
-
-int WebPPictureImportBGRX(WebPPicture* picture,
- const uint8_t* rgba, int rgba_stride) {
- return (picture != NULL && rgba != NULL)
- ? Import(picture, rgba, rgba_stride, 4, 1, 0)
- : 0;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/picture_csp_enc.c b/thirdparty/libwebp/enc/picture_csp_enc.c
new file mode 100644
index 0000000000..e5d1c75a66
--- /dev/null
+++ b/thirdparty/libwebp/enc/picture_csp_enc.c
@@ -0,0 +1,1175 @@
+// 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 "./vp8i_enc.h"
+#include "../utils/random_utils.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));
+}
+
+//------------------------------------------------------------------------------
+// Sharp RGB->YUV conversion
+
+static const int kNumIterations = 4;
+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 for the Rec709
+// transfer function.
+#define kGammaF (1./0.45)
+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;
+ const double a = 0.099;
+ const double thresh = 0.018;
+ for (v = 0; v <= MAX_Y_T; ++v) {
+ const double g = norm * v;
+ if (g <= thresh * 4.5) {
+ kGammaToLinearTabF[v] = (float)(g / 4.5);
+ } else {
+ const double a_rec = 1. / (1. + a);
+ kGammaToLinearTabF[v] = (float)pow(a_rec * (g + a), kGammaF);
+ }
+ }
+ for (v = 0; v <= kGammaTabSize; ++v) {
+ const double g = scale * v;
+ double value;
+ if (g <= thresh) {
+ value = 4.5 * g;
+ } else {
+ value = (1. + a) * pow(g, 1. / kGammaF) - a;
+ }
+ kLinearToGammaTabF[v] = (float)(MAX_Y_T * value);
+ }
+ // 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 = 13933 * r + 46871 * g + 4732 * b + YUV_HALF;
+ return (luma >> YUV_FIX);
+}
+
+static float RGBToGrayF(float r, float g, float b) {
+ return (float)(0.2126 * r + 0.7152 * g + 0.0722 * 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 w) {
+ int i;
+ for (i = 0; i < w; ++i) {
+ const float R = GammaToLinearF(src[0 * w + i]);
+ const float G = GammaToLinearF(src[1 * w + i]);
+ const float B = GammaToLinearF(src[2 * w + i]);
+ const float Y = RGBToGrayF(R, G, B);
+ dst[i] = (fixed_y_t)LinearToGammaF(Y);
+ }
+}
+
+static void UpdateChroma(const fixed_y_t* src1, const fixed_y_t* src2,
+ fixed_t* dst, int uv_w) {
+ int i;
+ for (i = 0; i < uv_w; ++i) {
+ const int r = ScaleDown(src1[0 * uv_w + 0], src1[0 * uv_w + 1],
+ src2[0 * uv_w + 0], src2[0 * uv_w + 1]);
+ const int g = ScaleDown(src1[2 * uv_w + 0], src1[2 * uv_w + 1],
+ src2[2 * uv_w + 0], src2[2 * uv_w + 1]);
+ const int b = ScaleDown(src1[4 * uv_w + 0], src1[4 * uv_w + 1],
+ src2[4 * uv_w + 0], src2[4 * uv_w + 1]);
+ const int W = RGBToGray(r, g, b);
+ dst[0 * uv_w] = (fixed_t)(r - W);
+ dst[1 * uv_w] = (fixed_t)(g - W);
+ dst[2 * uv_w] = (fixed_t)(b - W);
+ dst += 1;
+ src1 += 2;
+ src2 += 2;
+ }
+}
+
+static void StoreGray(const fixed_y_t* rgb, fixed_y_t* y, int w) {
+ int i;
+ for (i = 0; i < w; ++i) {
+ y[i] = RGBToGray(rgb[0 * w + i], rgb[1 * w + i], rgb[2 * w + i]);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+static WEBP_INLINE fixed_y_t Filter2(int A, int B, int W0) {
+ const int v0 = (A * 3 + B + 2) >> 2;
+ return clip_y(v0 + W0);
+}
+
+//------------------------------------------------------------------------------
+
+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;
+ const int w = (pic_width + 1) & ~1;
+ for (i = 0; i < pic_width; ++i) {
+ const int off = i * step;
+ dst[i + 0 * w] = UpLift(r_ptr[off]);
+ dst[i + 1 * w] = UpLift(g_ptr[off]);
+ dst[i + 2 * w] = UpLift(b_ptr[off]);
+ }
+ if (pic_width & 1) { // replicate rightmost pixel
+ dst[pic_width + 0 * w] = dst[pic_width + 0 * w - 1];
+ dst[pic_width + 1 * w] = dst[pic_width + 1 * w - 1];
+ dst[pic_width + 2 * w] = dst[pic_width + 2 * w - 1];
+ }
+}
+
+static void InterpolateTwoRows(const fixed_y_t* const best_y,
+ const fixed_t* prev_uv,
+ const fixed_t* cur_uv,
+ const fixed_t* next_uv,
+ int w,
+ fixed_y_t* out1,
+ fixed_y_t* out2) {
+ const int uv_w = w >> 1;
+ const int len = (w - 1) >> 1; // length to filter
+ int k = 3;
+ while (k-- > 0) { // process each R/G/B segments in turn
+ // special boundary case for i==0
+ out1[0] = Filter2(cur_uv[0], prev_uv[0], best_y[0]);
+ out2[0] = Filter2(cur_uv[0], next_uv[0], best_y[w]);
+
+ WebPSharpYUVFilterRow(cur_uv, prev_uv, len, best_y + 0 + 1, out1 + 1);
+ WebPSharpYUVFilterRow(cur_uv, next_uv, len, best_y + w + 1, out2 + 1);
+
+ // special boundary case for i == w - 1 when w is even
+ if (!(w & 1)) {
+ out1[w - 1] = Filter2(cur_uv[uv_w - 1], prev_uv[uv_w - 1],
+ best_y[w - 1 + 0]);
+ out2[w - 1] = Filter2(cur_uv[uv_w - 1], next_uv[uv_w - 1],
+ best_y[w - 1 + w]);
+ }
+ out1 += w;
+ out2 += w;
+ prev_uv += uv_w;
+ cur_uv += uv_w;
+ next_uv += uv_w;
+ }
+}
+
+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* best_y, const fixed_t* best_uv,
+ WebPPicture* const picture) {
+ int i, j;
+ uint8_t* dst_y = picture->y;
+ uint8_t* dst_u = picture->u;
+ uint8_t* dst_v = picture->v;
+ const fixed_t* const best_uv_base = best_uv;
+ 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 (best_uv = best_uv_base, j = 0; j < picture->height; ++j) {
+ for (i = 0; i < picture->width; ++i) {
+ const int off = (i >> 1);
+ const int W = best_y[i];
+ const int r = best_uv[off + 0 * uv_w] + W;
+ const int g = best_uv[off + 1 * uv_w] + W;
+ const int b = best_uv[off + 2 * uv_w] + W;
+ dst_y[i] = ConvertRGBToY(r, g, b);
+ }
+ best_y += w;
+ best_uv += (j & 1) * 3 * uv_w;
+ dst_y += picture->y_stride;
+ }
+ for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) {
+ for (i = 0; i < uv_w; ++i) {
+ const int off = i;
+ const int r = best_uv[off + 0 * uv_w];
+ const int g = best_uv[off + 1 * uv_w];
+ const int b = best_uv[off + 2 * uv_w];
+ dst_u[i] = ConvertRGBToU(r, g, b);
+ dst_v[i] = ConvertRGBToV(r, g, b);
+ }
+ best_uv += 3 * uv_w;
+ dst_u += picture->uv_stride;
+ dst_v += picture->uv_stride;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+// Main function
+
+#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T)))
+
+static int PreprocessARGB(const uint8_t* r_ptr,
+ const uint8_t* g_ptr,
+ const uint8_t* 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;
+ uint64_t prev_diff_y_sum = ~0;
+ int 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_base = SAFE_ALLOC(w, h, fixed_y_t);
+ fixed_y_t* const target_y_base = 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_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
+ fixed_t* const target_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
+ fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t);
+ fixed_y_t* best_y = best_y_base;
+ fixed_y_t* target_y = target_y_base;
+ fixed_t* best_uv = best_uv_base;
+ fixed_t* target_uv = target_uv_base;
+ const uint64_t diff_y_threshold = (uint64_t)(3.0 * w * h);
+ int ok;
+
+ if (best_y_base == NULL || best_uv_base == NULL ||
+ target_y_base == NULL || target_uv_base == 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);
+
+ WebPInitConvertARGBToYUV();
+
+ // 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 + 0 * w;
+ fixed_y_t* const src2 = tmp_buffer + 3 * w;
+
+ // prepare two rows of input
+ ImportOneRow(r_ptr, g_ptr, b_ptr, step, picture->width, src1);
+ if (!is_last_row) {
+ ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
+ step, picture->width, src2);
+ } else {
+ memcpy(src2, src1, 3 * w * sizeof(*src2));
+ }
+ StoreGray(src1, best_y + 0, w);
+ StoreGray(src2, best_y + w, w);
+
+ UpdateW(src1, target_y, w);
+ UpdateW(src2, target_y + w, w);
+ UpdateChroma(src1, src2, target_uv, uv_w);
+ memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv));
+ best_y += 2 * w;
+ best_uv += 3 * uv_w;
+ target_y += 2 * w;
+ target_uv += 3 * uv_w;
+ r_ptr += 2 * rgb_stride;
+ g_ptr += 2 * rgb_stride;
+ b_ptr += 2 * rgb_stride;
+ }
+
+ // Iterate and resolve clipping conflicts.
+ for (iter = 0; iter < kNumIterations; ++iter) {
+ const fixed_t* cur_uv = best_uv_base;
+ const fixed_t* prev_uv = best_uv_base;
+ uint64_t diff_y_sum = 0;
+
+ best_y = best_y_base;
+ best_uv = best_uv_base;
+ target_y = target_y_base;
+ target_uv = target_uv_base;
+ for (j = 0; j < h; j += 2) {
+ fixed_y_t* const src1 = tmp_buffer + 0 * w;
+ 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, 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);
+ UpdateChroma(src1, src2, best_rgb_uv, uv_w);
+
+ // update two rows of Y and one row of RGB
+ diff_y_sum += WebPSharpYUVUpdateY(target_y, best_rgb_y, best_y, 2 * w);
+ WebPSharpYUVUpdateRGB(target_uv, best_rgb_uv, best_uv, 3 * uv_w);
+
+ best_y += 2 * w;
+ best_uv += 3 * uv_w;
+ target_y += 2 * w;
+ target_uv += 3 * uv_w;
+ }
+ // test exit condition
+ if (iter > 0) {
+ if (diff_y_sum < diff_y_threshold) break;
+ if (diff_y_sum > prev_diff_y_sum) break;
+ }
+ prev_diff_y_sum = diff_y_sum;
+ }
+ // final reconstruction
+ ok = ConvertWRGBToYUV(best_y_base, best_uv_base, picture);
+
+ End:
+ WebPSafeFree(best_y_base);
+ WebPSafeFree(best_uv_base);
+ WebPSafeFree(target_y_base);
+ WebPSafeFree(target_uv_base);
+ 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* r_ptr,
+ const uint8_t* g_ptr,
+ const uint8_t* b_ptr,
+ const uint8_t* 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;
+ if (use_dsp) {
+ if (is_rgb) {
+ WebPConvertRGB24ToY(r_ptr, dst_y, width);
+ WebPConvertRGB24ToY(r_ptr + rgb_stride,
+ dst_y + picture->y_stride, width);
+ } else {
+ WebPConvertBGR24ToY(b_ptr, dst_y, width);
+ WebPConvertBGR24ToY(b_ptr + rgb_stride,
+ dst_y + picture->y_stride, width);
+ }
+ } else {
+ ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
+ ConvertRowToY(r_ptr + rgb_stride,
+ g_ptr + rgb_stride,
+ b_ptr + rgb_stride, step,
+ dst_y + picture->y_stride, width, rg);
+ }
+ dst_y += 2 * picture->y_stride;
+ if (has_alpha) {
+ rows_have_alpha &= !WebPExtractAlpha(a_ptr, 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, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, width);
+ } else {
+ AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, 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;
+ r_ptr += 2 * rgb_stride;
+ b_ptr += 2 * rgb_stride;
+ g_ptr += 2 * rgb_stride;
+ if (has_alpha) a_ptr += 2 * rgb_stride;
+ }
+ if (height & 1) { // extra last row
+ int row_has_alpha = has_alpha;
+ if (use_dsp) {
+ if (r_ptr < b_ptr) {
+ WebPConvertRGB24ToY(r_ptr, dst_y, width);
+ } else {
+ WebPConvertBGR24ToY(b_ptr, dst_y, width);
+ }
+ } else {
+ ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
+ }
+ if (row_has_alpha) {
+ row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0);
+ }
+ // Collect averaged R/G/B(/A)
+ if (!row_has_alpha) {
+ // Collect averaged R/G/B
+ AccumulateRGB(r_ptr, g_ptr, b_ptr, step, /* rgb_stride = */ 0,
+ tmp_rgb, width);
+ } else {
+ AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /* 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 WebPPictureSharpARGBToYUVA(WebPPicture* picture) {
+ return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1);
+}
+// for backward compatibility
+int WebPPictureSmartARGBToYUVA(WebPPicture* picture) {
+ return WebPPictureSharpARGBToYUVA(picture);
+}
+
+//------------------------------------------------------------------------------
+// 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* r_ptr = rgb + (swap_rb ? 2 : 0);
+ const uint8_t* g_ptr = rgb + 1;
+ const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2);
+ const uint8_t* 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) {
+ uint32_t* dst = picture->argb;
+ assert(step == 4);
+ for (y = 0; y < height; ++y) {
+ VP8PackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst);
+ a_ptr += rgb_stride;
+ r_ptr += rgb_stride;
+ g_ptr += rgb_stride;
+ b_ptr += rgb_stride;
+ dst += picture->argb_stride;
+ }
+ } else {
+ uint32_t* dst = picture->argb;
+ assert(step >= 3);
+ for (y = 0; y < height; ++y) {
+ VP8PackRGB(r_ptr, g_ptr, b_ptr, width, step, dst);
+ r_ptr += rgb_stride;
+ g_ptr += rgb_stride;
+ b_ptr += rgb_stride;
+ dst += picture->argb_stride;
+ }
+ }
+ return 1;
+}
+
+// Public API
+
+int WebPPictureImportRGB(WebPPicture* picture,
+ const uint8_t* rgb, int rgb_stride) {
+ return (picture != NULL && rgb != NULL)
+ ? Import(picture, rgb, rgb_stride, 3, 0, 0)
+ : 0;
+}
+
+int WebPPictureImportBGR(WebPPicture* picture,
+ const uint8_t* rgb, int rgb_stride) {
+ return (picture != NULL && rgb != NULL)
+ ? Import(picture, rgb, rgb_stride, 3, 1, 0)
+ : 0;
+}
+
+int WebPPictureImportRGBA(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL && rgba != NULL)
+ ? Import(picture, rgba, rgba_stride, 4, 0, 1)
+ : 0;
+}
+
+int WebPPictureImportBGRA(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL && rgba != NULL)
+ ? Import(picture, rgba, rgba_stride, 4, 1, 1)
+ : 0;
+}
+
+int WebPPictureImportRGBX(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL && rgba != NULL)
+ ? Import(picture, rgba, rgba_stride, 4, 0, 0)
+ : 0;
+}
+
+int WebPPictureImportBGRX(WebPPicture* picture,
+ const uint8_t* rgba, int rgba_stride) {
+ return (picture != NULL && rgba != NULL)
+ ? Import(picture, rgba, rgba_stride, 4, 1, 0)
+ : 0;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/picture_enc.c b/thirdparty/libwebp/enc/picture_enc.c
new file mode 100644
index 0000000000..dfa66510fb
--- /dev/null
+++ b/thirdparty/libwebp/enc/picture_enc.c
@@ -0,0 +1,293 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// WebPPicture class basis
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "./vp8i_enc.h"
+#include "../dsp/dsp.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+// 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;
+}
+
+//------------------------------------------------------------------------------
+
+static void WebPPictureResetBufferARGB(WebPPicture* const picture) {
+ picture->memory_argb_ = NULL;
+ picture->argb = NULL;
+ picture->argb_stride = 0;
+}
+
+static void WebPPictureResetBufferYUVA(WebPPicture* const picture) {
+ picture->memory_ = NULL;
+ picture->y = picture->u = picture->v = picture->a = NULL;
+ picture->y_stride = picture->uv_stride = 0;
+ picture->a_stride = 0;
+}
+
+void WebPPictureResetBuffers(WebPPicture* const picture) {
+ WebPPictureResetBufferARGB(picture);
+ WebPPictureResetBufferYUVA(picture);
+}
+
+int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) {
+ void* memory;
+ const uint64_t argb_size = (uint64_t)width * height;
+
+ assert(picture != NULL);
+
+ WebPSafeFree(picture->memory_argb_);
+ WebPPictureResetBufferARGB(picture);
+
+ if (width <= 0 || height <= 0) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
+ }
+ // allocate a new buffer.
+ memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb));
+ if (memory == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
+ // TODO(skal): align plane to cache line?
+ picture->memory_argb_ = memory;
+ picture->argb = (uint32_t*)memory;
+ picture->argb_stride = width;
+ return 1;
+}
+
+int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) {
+ const WebPEncCSP uv_csp =
+ (WebPEncCSP)((int)picture->colorspace & WEBP_CSP_UV_MASK);
+ const int has_alpha = (int)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;
+
+ assert(picture != NULL);
+
+ WebPSafeFree(picture->memory_);
+ WebPPictureResetBufferYUVA(picture);
+
+ if (uv_csp != WEBP_YUV420) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
+ }
+
+ // 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;
+
+ // 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);
+ }
+ // allocate a new buffer.
+ mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem));
+ if (mem == NULL) {
+ return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
+
+ // 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;
+
+ // 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 > 0) {
+ picture->a = mem;
+ mem += a_size;
+ }
+ (void)mem; // makes the static analyzer happy
+ return 1;
+}
+
+int WebPPictureAlloc(WebPPicture* picture) {
+ if (picture != NULL) {
+ const int width = picture->width;
+ const int height = picture->height;
+
+ WebPPictureFree(picture); // erase previous buffer
+
+ if (!picture->use_argb) {
+ return WebPPictureAllocYUVA(picture, width, height);
+ } else {
+ return WebPPictureAllocARGB(picture, width, height);
+ }
+ }
+ return 1;
+}
+
+void WebPPictureFree(WebPPicture* picture) {
+ if (picture != NULL) {
+ WebPSafeFree(picture->memory_);
+ WebPSafeFree(picture->memory_argb_);
+ WebPPictureResetBuffers(picture);
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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);
+ }
+ WebPSafeFree(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;
+}
+
+void WebPMemoryWriterClear(WebPMemoryWriter* writer) {
+ if (writer != NULL) {
+ WebPSafeFree(writer->mem);
+ writer->mem = NULL;
+ writer->size = 0;
+ writer->max_size = 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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 (output == NULL) return 0;
+
+ 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) {
+ WebPMemoryWriterClear(&wrt);
+ *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
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/picture_psnr.c b/thirdparty/libwebp/enc/picture_psnr.c
deleted file mode 100644
index 329757deb1..0000000000
--- a/thirdparty/libwebp/enc/picture_psnr.c
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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, VP8DistoStats* 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]) {
- VP8DistoStats stats[5];
- int w, h;
-
- memset(stats, 0, sizeof(stats));
-
- VP8SSIMDspInit();
-
- 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]);
- }
- }
- WebPSafeFree(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/thirdparty/libwebp/enc/picture_psnr_enc.c b/thirdparty/libwebp/enc/picture_psnr_enc.c
new file mode 100644
index 0000000000..9c0b229507
--- /dev/null
+++ b/thirdparty/libwebp/enc/picture_psnr_enc.c
@@ -0,0 +1,213 @@
+// 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 "./vp8i_enc.h"
+#include "../utils/utils.h"
+
+typedef double (*AccumulateFunc)(const uint8_t* src, int src_stride,
+ const uint8_t* ref, int ref_stride,
+ int w, int 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 double AccumulateLSIM(const uint8_t* src, int src_stride,
+ const uint8_t* ref, int ref_stride,
+ int w, int h) {
+ 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;
+ }
+ }
+ return total_sse;
+}
+#undef RADIUS
+
+static double AccumulateSSE(const uint8_t* src, int src_stride,
+ const uint8_t* ref, int ref_stride,
+ int w, int h) {
+ int y;
+ double total_sse = 0.;
+ for (y = 0; y < h; ++y) {
+ total_sse += VP8AccumulateSSE(src, ref, w);
+ src += src_stride;
+ ref += ref_stride;
+ }
+ return total_sse;
+}
+
+//------------------------------------------------------------------------------
+
+static double AccumulateSSIM(const uint8_t* src, int src_stride,
+ const uint8_t* ref, int ref_stride,
+ int w, int h) {
+ const int w0 = (w < VP8_SSIM_KERNEL) ? w : VP8_SSIM_KERNEL;
+ const int w1 = w - VP8_SSIM_KERNEL - 1;
+ const int h0 = (h < VP8_SSIM_KERNEL) ? h : VP8_SSIM_KERNEL;
+ const int h1 = h - VP8_SSIM_KERNEL - 1;
+ int x, y;
+ double sum = 0.;
+ for (y = 0; y < h0; ++y) {
+ for (x = 0; x < w; ++x) {
+ sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h);
+ }
+ }
+ for (; y < h1; ++y) {
+ for (x = 0; x < w0; ++x) {
+ sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h);
+ }
+ for (; x < w1; ++x) {
+ const int off1 = x - VP8_SSIM_KERNEL + (y - VP8_SSIM_KERNEL) * src_stride;
+ const int off2 = x - VP8_SSIM_KERNEL + (y - VP8_SSIM_KERNEL) * ref_stride;
+ sum += VP8SSIMGet(src + off1, src_stride, ref + off2, ref_stride);
+ }
+ for (; x < w; ++x) {
+ sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h);
+ }
+ }
+ for (; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ sum += VP8SSIMGetClipped(src, src_stride, ref, ref_stride, x, y, w, h);
+ }
+ }
+ return sum;
+}
+
+//------------------------------------------------------------------------------
+// Distortion
+
+// Max value returned in case of exact similarity.
+static const double kMinDistortion_dB = 99.;
+
+static double GetPSNR(double v, double size) {
+ return (v > 0. && size > 0.) ? -4.3429448 * log(v / (size * 255 * 255.))
+ : kMinDistortion_dB;
+}
+
+static double GetLogSSIM(double v, double size) {
+ v = (size > 0.) ? v / size : 1.;
+ return (v < 1.) ? -10.0 * log10(1. - v) : kMinDistortion_dB;
+}
+
+int WebPPlaneDistortion(const uint8_t* src, size_t src_stride,
+ const uint8_t* ref, size_t ref_stride,
+ int width, int height, size_t x_step,
+ int type, float* distortion, float* result) {
+ uint8_t* allocated = NULL;
+ const AccumulateFunc metric = (type == 0) ? AccumulateSSE :
+ (type == 1) ? AccumulateSSIM :
+ AccumulateLSIM;
+ if (src == NULL || ref == NULL ||
+ src_stride < x_step * width || ref_stride < x_step * width ||
+ result == NULL || distortion == NULL) {
+ return 0;
+ }
+
+ VP8SSIMDspInit();
+ if (x_step != 1) { // extract a packed plane if needed
+ int x, y;
+ uint8_t* tmp1;
+ uint8_t* tmp2;
+ allocated =
+ (uint8_t*)WebPSafeMalloc(2ULL * width * height, sizeof(*allocated));
+ if (allocated == NULL) return 0;
+ tmp1 = allocated;
+ tmp2 = tmp1 + (size_t)width * height;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; ++x) {
+ tmp1[x + y * width] = src[x * x_step + y * src_stride];
+ tmp2[x + y * width] = ref[x * x_step + y * ref_stride];
+ }
+ }
+ src = tmp1;
+ ref = tmp2;
+ }
+ *distortion = (float)metric(src, width, ref, width, width, height);
+ WebPSafeFree(allocated);
+
+ *result = (type == 1) ? (float)GetLogSSIM(*distortion, (double)width * height)
+ : (float)GetPSNR(*distortion, (double)width * height);
+ return 1;
+}
+
+int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref,
+ int type, float results[5]) {
+ int w, h, c;
+ int ok = 0;
+ WebPPicture p0, p1;
+ double total_size = 0., total_distortion = 0.;
+ if (src == NULL || ref == NULL ||
+ src->width != ref->width || src->height != ref->height ||
+ results == NULL) {
+ return 0;
+ }
+
+ VP8SSIMDspInit();
+ if (!WebPPictureInit(&p0) || !WebPPictureInit(&p1)) return 0;
+ w = src->width;
+ h = src->height;
+ if (!WebPPictureView(src, 0, 0, w, h, &p0)) goto Error;
+ if (!WebPPictureView(ref, 0, 0, w, h, &p1)) goto Error;
+
+ // We always measure distortion in ARGB space.
+ if (p0.use_argb == 0 && !WebPPictureYUVAToARGB(&p0)) goto Error;
+ if (p1.use_argb == 0 && !WebPPictureYUVAToARGB(&p1)) goto Error;
+ for (c = 0; c < 4; ++c) {
+ float distortion;
+ const size_t stride0 = 4 * (size_t)p0.argb_stride;
+ const size_t stride1 = 4 * (size_t)p1.argb_stride;
+ if (!WebPPlaneDistortion((const uint8_t*)p0.argb + c, stride0,
+ (const uint8_t*)p1.argb + c, stride1,
+ w, h, 4, type, &distortion, results + c)) {
+ goto Error;
+ }
+ total_distortion += distortion;
+ total_size += w * h;
+ }
+
+ results[4] = (type == 1) ? (float)GetLogSSIM(total_distortion, total_size)
+ : (float)GetPSNR(total_distortion, total_size);
+ ok = 1;
+
+ Error:
+ WebPPictureFree(&p0);
+ WebPPictureFree(&p1);
+ return ok;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/picture_rescale.c b/thirdparty/libwebp/enc/picture_rescale.c
deleted file mode 100644
index 9f19e8e80f..0000000000
--- a/thirdparty/libwebp/enc/picture_rescale.c
+++ /dev/null
@@ -1,264 +0,0 @@
-// 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/thirdparty/libwebp/enc/picture_rescale_enc.c b/thirdparty/libwebp/enc/picture_rescale_enc.c
new file mode 100644
index 0000000000..0b7181c0d7
--- /dev/null
+++ b/thirdparty/libwebp/enc/picture_rescale_enc.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 "./vp8i_enc.h"
+#include "../utils/rescaler_utils.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/thirdparty/libwebp/enc/picture_tools.c b/thirdparty/libwebp/enc/picture_tools.c
deleted file mode 100644
index bf97af8408..0000000000
--- a/thirdparty/libwebp/enc/picture_tools.c
+++ /dev/null
@@ -1,226 +0,0 @@
-// 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 <assert.h>
-
-#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
-
-void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) {
- int x, y, w, h;
- uint32_t* argb;
- assert(pic != NULL && pic->use_argb);
- w = pic->width;
- h = pic->height;
- argb = pic->argb;
-
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- if ((argb[x] & 0xff000000) == 0) {
- argb[x] = 0x00000000;
- }
- }
- argb += pic->argb_stride;
- }
-}
-
-//------------------------------------------------------------------------------
-// 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/thirdparty/libwebp/enc/picture_tools_enc.c b/thirdparty/libwebp/enc/picture_tools_enc.c
new file mode 100644
index 0000000000..895df51156
--- /dev/null
+++ b/thirdparty/libwebp/enc/picture_tools_enc.c
@@ -0,0 +1,226 @@
+// 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 <assert.h>
+
+#include "./vp8i_enc.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
+
+void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) {
+ int x, y, w, h;
+ uint32_t* argb;
+ assert(pic != NULL && pic->use_argb);
+ w = pic->width;
+ h = pic->height;
+ argb = pic->argb;
+
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ if ((argb[x] & 0xff000000) == 0) {
+ argb[x] = 0x00000000;
+ }
+ }
+ argb += pic->argb_stride;
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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/thirdparty/libwebp/enc/predictor_enc.c b/thirdparty/libwebp/enc/predictor_enc.c
new file mode 100644
index 0000000000..0639b74f1c
--- /dev/null
+++ b/thirdparty/libwebp/enc/predictor_enc.c
@@ -0,0 +1,750 @@
+// Copyright 2016 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)
+// Vincent Rabaud (vrabaud@google.com)
+
+#include "../dsp/lossless.h"
+#include "../dsp/lossless_common.h"
+#include "./vp8li_enc.h"
+
+#define MAX_DIFF_COST (1e30f)
+
+static const float kSpatialPredictorBias = 15.f;
+static const int kPredLowEffort = 11;
+static const uint32_t kMaskAlpha = 0xff000000;
+
+// Mostly used to reduce code size + readability
+static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; }
+static WEBP_INLINE int GetMax(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);
+}
+
+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 += VP8LCombinedShannonEntropy(tile[i], accumulated[i]);
+ }
+ return (float)retval;
+}
+
+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];
+}
+
+//------------------------------------------------------------------------------
+// Spatial transform functions.
+
+static WEBP_INLINE void PredictBatch(int mode, int x_start, int y,
+ int num_pixels, const uint32_t* current,
+ const uint32_t* upper, uint32_t* out) {
+ if (x_start == 0) {
+ if (y == 0) {
+ // ARGB_BLACK.
+ VP8LPredictorsSub[0](current, NULL, 1, out);
+ } else {
+ // Top one.
+ VP8LPredictorsSub[2](current, upper, 1, out);
+ }
+ ++x_start;
+ ++out;
+ --num_pixels;
+ }
+ if (y == 0) {
+ // Left one.
+ VP8LPredictorsSub[1](current + x_start, NULL, num_pixels, out);
+ } else {
+ VP8LPredictorsSub[mode](current + x_start, upper + x_start, num_pixels,
+ out);
+ }
+}
+
+static int MaxDiffBetweenPixels(uint32_t p1, uint32_t p2) {
+ const int diff_a = abs((int)(p1 >> 24) - (int)(p2 >> 24));
+ const int diff_r = abs((int)((p1 >> 16) & 0xff) - (int)((p2 >> 16) & 0xff));
+ const int diff_g = abs((int)((p1 >> 8) & 0xff) - (int)((p2 >> 8) & 0xff));
+ const int diff_b = abs((int)(p1 & 0xff) - (int)(p2 & 0xff));
+ return GetMax(GetMax(diff_a, diff_r), GetMax(diff_g, diff_b));
+}
+
+static int MaxDiffAroundPixel(uint32_t current, uint32_t up, uint32_t down,
+ uint32_t left, uint32_t right) {
+ const int diff_up = MaxDiffBetweenPixels(current, up);
+ const int diff_down = MaxDiffBetweenPixels(current, down);
+ const int diff_left = MaxDiffBetweenPixels(current, left);
+ const int diff_right = MaxDiffBetweenPixels(current, right);
+ return GetMax(GetMax(diff_up, diff_down), GetMax(diff_left, diff_right));
+}
+
+static uint32_t AddGreenToBlueAndRed(uint32_t argb) {
+ const uint32_t green = (argb >> 8) & 0xff;
+ uint32_t red_blue = argb & 0x00ff00ffu;
+ red_blue += (green << 16) | green;
+ red_blue &= 0x00ff00ffu;
+ return (argb & 0xff00ff00u) | red_blue;
+}
+
+static void MaxDiffsForRow(int width, int stride, const uint32_t* const argb,
+ uint8_t* const max_diffs, int used_subtract_green) {
+ uint32_t current, up, down, left, right;
+ int x;
+ if (width <= 2) return;
+ current = argb[0];
+ right = argb[1];
+ if (used_subtract_green) {
+ current = AddGreenToBlueAndRed(current);
+ right = AddGreenToBlueAndRed(right);
+ }
+ // max_diffs[0] and max_diffs[width - 1] are never used.
+ for (x = 1; x < width - 1; ++x) {
+ up = argb[-stride + x];
+ down = argb[stride + x];
+ left = current;
+ current = right;
+ right = argb[x + 1];
+ if (used_subtract_green) {
+ up = AddGreenToBlueAndRed(up);
+ down = AddGreenToBlueAndRed(down);
+ right = AddGreenToBlueAndRed(right);
+ }
+ max_diffs[x] = MaxDiffAroundPixel(current, up, down, left, right);
+ }
+}
+
+// Quantize the difference between the actual component value and its prediction
+// to a multiple of quantization, working modulo 256, taking care not to cross
+// a boundary (inclusive upper limit).
+static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict,
+ uint8_t boundary, int quantization) {
+ const int residual = (value - predict) & 0xff;
+ const int boundary_residual = (boundary - predict) & 0xff;
+ const int lower = residual & ~(quantization - 1);
+ const int upper = lower + quantization;
+ // Resolve ties towards a value closer to the prediction (i.e. towards lower
+ // if value comes after prediction and towards upper otherwise).
+ const int bias = ((boundary - value) & 0xff) < boundary_residual;
+ if (residual - lower < upper - residual + bias) {
+ // lower is closer to residual than upper.
+ if (residual > boundary_residual && lower <= boundary_residual) {
+ // Halve quantization step to avoid crossing boundary. This midpoint is
+ // on the same side of boundary as residual because midpoint >= residual
+ // (since lower is closer than upper) and residual is above the boundary.
+ return lower + (quantization >> 1);
+ }
+ return lower;
+ } else {
+ // upper is closer to residual than lower.
+ if (residual <= boundary_residual && upper > boundary_residual) {
+ // Halve quantization step to avoid crossing boundary. This midpoint is
+ // on the same side of boundary as residual because midpoint <= residual
+ // (since upper is closer than lower) and residual is below the boundary.
+ return lower + (quantization >> 1);
+ }
+ return upper & 0xff;
+ }
+}
+
+// Quantize every component of the difference between the actual pixel value and
+// its prediction to a multiple of a quantization (a power of 2, not larger than
+// max_quantization which is a power of 2, smaller than max_diff). Take care if
+// value and predict have undergone subtract green, which means that red and
+// blue are represented as offsets from green.
+static uint32_t NearLossless(uint32_t value, uint32_t predict,
+ int max_quantization, int max_diff,
+ int used_subtract_green) {
+ int quantization;
+ uint8_t new_green = 0;
+ uint8_t green_diff = 0;
+ uint8_t a, r, g, b;
+ if (max_diff <= 2) {
+ return VP8LSubPixels(value, predict);
+ }
+ quantization = max_quantization;
+ while (quantization >= max_diff) {
+ quantization >>= 1;
+ }
+ if ((value >> 24) == 0 || (value >> 24) == 0xff) {
+ // Preserve transparency of fully transparent or fully opaque pixels.
+ a = ((value >> 24) - (predict >> 24)) & 0xff;
+ } else {
+ a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization);
+ }
+ g = NearLosslessComponent((value >> 8) & 0xff, (predict >> 8) & 0xff, 0xff,
+ quantization);
+ if (used_subtract_green) {
+ // The green offset will be added to red and blue components during decoding
+ // to obtain the actual red and blue values.
+ new_green = ((predict >> 8) + g) & 0xff;
+ // The amount by which green has been adjusted during quantization. It is
+ // subtracted from red and blue for compensation, to avoid accumulating two
+ // quantization errors in them.
+ green_diff = (new_green - (value >> 8)) & 0xff;
+ }
+ r = NearLosslessComponent(((value >> 16) - green_diff) & 0xff,
+ (predict >> 16) & 0xff, 0xff - new_green,
+ quantization);
+ b = NearLosslessComponent((value - green_diff) & 0xff, predict & 0xff,
+ 0xff - new_green, quantization);
+ return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
+}
+
+// Stores the difference between the pixel and its prediction in "out".
+// In case of a lossy encoding, updates the source image to avoid propagating
+// the deviation further to pixels which depend on the current pixel for their
+// predictions.
+static WEBP_INLINE void GetResidual(
+ int width, int height, uint32_t* const upper_row,
+ uint32_t* const current_row, const uint8_t* const max_diffs, int mode,
+ int x_start, int x_end, int y, int max_quantization, int exact,
+ int used_subtract_green, uint32_t* const out) {
+ if (exact) {
+ PredictBatch(mode, x_start, y, x_end - x_start, current_row, upper_row,
+ out);
+ } else {
+ const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
+ int x;
+ for (x = x_start; x < x_end; ++x) {
+ uint32_t predict;
+ uint32_t residual;
+ 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);
+ }
+ if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 ||
+ x == 0 || x == width - 1) {
+ residual = VP8LSubPixels(current_row[x], predict);
+ } else {
+ residual = NearLossless(current_row[x], predict, max_quantization,
+ max_diffs[x], used_subtract_green);
+ // Update the source image.
+ current_row[x] = VP8LAddPixels(predict, residual);
+ // x is never 0 here so we do not need to update upper_row like below.
+ }
+ if ((current_row[x] & kMaskAlpha) == 0) {
+ // If alpha is 0, cleanup RGB. We can choose the RGB values of the
+ // residual for best compression. The prediction of alpha itself can be
+ // non-zero and must be kept though. We choose RGB of the residual to be
+ // 0.
+ residual &= kMaskAlpha;
+ // Update the source image.
+ current_row[x] = predict & ~kMaskAlpha;
+ // The prediction for the rightmost pixel in a row uses the leftmost
+ // pixel
+ // in that row as its top-right context pixel. Hence if we change the
+ // leftmost pixel of current_row, the corresponding change must be
+ // applied
+ // to upper_row as well where top-right context is being read from.
+ if (x == 0 && y != 0) upper_row[width] = current_row[0];
+ }
+ out[x - x_start] = residual;
+ }
+ }
+}
+
+// Returns best predictor and updates the accumulated histogram.
+// If max_quantization > 1, assumes that near lossless processing will be
+// applied, quantizing residuals to multiples of quantization levels up to
+// max_quantization (the actual quantization level depends on smoothness near
+// the given pixel).
+static int GetBestPredictorForTile(int width, int height,
+ int tile_x, int tile_y, int bits,
+ int accumulated[4][256],
+ uint32_t* const argb_scratch,
+ const uint32_t* const argb,
+ int max_quantization,
+ int exact, int used_subtract_green,
+ const uint32_t* const modes) {
+ const int kNumPredModes = 14;
+ const int start_x = tile_x << bits;
+ const int start_y = tile_y << bits;
+ const int tile_size = 1 << bits;
+ const int max_y = GetMin(tile_size, height - start_y);
+ const int max_x = GetMin(tile_size, width - start_x);
+ // Whether there exist columns just outside the tile.
+ const int have_left = (start_x > 0);
+ const int have_right = (max_x < width - start_x);
+ // Position and size of the strip covering the tile and adjacent columns if
+ // they exist.
+ const int context_start_x = start_x - have_left;
+ const int context_width = max_x + have_left + have_right;
+ const int tiles_per_row = VP8LSubSampleSize(width, bits);
+ // Prediction modes of the left and above neighbor tiles.
+ const int left_mode = (tile_x > 0) ?
+ (modes[tile_y * tiles_per_row + tile_x - 1] >> 8) & 0xff : 0xff;
+ const int above_mode = (tile_y > 0) ?
+ (modes[(tile_y - 1) * tiles_per_row + tile_x] >> 8) & 0xff : 0xff;
+ // The width of upper_row and current_row is one pixel larger than image width
+ // to allow the top right pixel to point to the leftmost pixel of the next row
+ // when at the right edge.
+ uint32_t* upper_row = argb_scratch;
+ uint32_t* current_row = upper_row + width + 1;
+ uint8_t* const max_diffs = (uint8_t*)(current_row + width + 1);
+ 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;
+ uint32_t residuals[1 << MAX_TRANSFORM_BITS];
+ assert(bits <= MAX_TRANSFORM_BITS);
+ assert(max_x <= (1 << MAX_TRANSFORM_BITS));
+
+ for (mode = 0; mode < kNumPredModes; ++mode) {
+ float cur_diff;
+ int relative_y;
+ memset(histo_argb, 0, sizeof(histo_stack_1));
+ if (start_y > 0) {
+ // Read the row above the tile which will become the first upper_row.
+ // Include a pixel to the left if it exists; include a pixel to the right
+ // in all cases (wrapping to the leftmost pixel of the next row if it does
+ // not exist).
+ memcpy(current_row + context_start_x,
+ argb + (start_y - 1) * width + context_start_x,
+ sizeof(*argb) * (max_x + have_left + 1));
+ }
+ for (relative_y = 0; relative_y < max_y; ++relative_y) {
+ const int y = start_y + relative_y;
+ int relative_x;
+ uint32_t* tmp = upper_row;
+ upper_row = current_row;
+ current_row = tmp;
+ // Read current_row. Include a pixel to the left if it exists; include a
+ // pixel to the right in all cases except at the bottom right corner of
+ // the image (wrapping to the leftmost pixel of the next row if it does
+ // not exist in the current row).
+ memcpy(current_row + context_start_x,
+ argb + y * width + context_start_x,
+ sizeof(*argb) * (max_x + have_left + (y + 1 < height)));
+ if (max_quantization > 1 && y >= 1 && y + 1 < height) {
+ MaxDiffsForRow(context_width, width, argb + y * width + context_start_x,
+ max_diffs + context_start_x, used_subtract_green);
+ }
+
+ GetResidual(width, height, upper_row, current_row, max_diffs, mode,
+ start_x, start_x + max_x, y, max_quantization, exact,
+ used_subtract_green, residuals);
+ for (relative_x = 0; relative_x < max_x; ++relative_x) {
+ UpdateHisto(histo_argb, residuals[relative_x]);
+ }
+ }
+ cur_diff = PredictionCostSpatialHistogram(
+ (const int (*)[256])accumulated, (const int (*)[256])histo_argb);
+ // Favor keeping the areas locally similar.
+ if (mode == left_mode) cur_diff -= kSpatialPredictorBias;
+ if (mode == above_mode) cur_diff -= kSpatialPredictorBias;
+
+ 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;
+}
+
+// Converts pixels of the image to residuals with respect to predictions.
+// If max_quantization > 1, applies near lossless processing, quantizing
+// residuals to multiples of quantization levels up to max_quantization
+// (the actual quantization level depends on smoothness near the given pixel).
+static void CopyImageWithPrediction(int width, int height,
+ int bits, uint32_t* const modes,
+ uint32_t* const argb_scratch,
+ uint32_t* const argb,
+ int low_effort, int max_quantization,
+ int exact, int used_subtract_green) {
+ const int tiles_per_row = VP8LSubSampleSize(width, bits);
+ // The width of upper_row and current_row is one pixel larger than image width
+ // to allow the top right pixel to point to the leftmost pixel of the next row
+ // when at the right edge.
+ uint32_t* upper_row = argb_scratch;
+ uint32_t* current_row = upper_row + width + 1;
+ uint8_t* current_max_diffs = (uint8_t*)(current_row + width + 1);
+ uint8_t* lower_max_diffs = current_max_diffs + width;
+ int y;
+
+ for (y = 0; y < height; ++y) {
+ int x;
+ uint32_t* const tmp32 = upper_row;
+ upper_row = current_row;
+ current_row = tmp32;
+ memcpy(current_row, argb + y * width,
+ sizeof(*argb) * (width + (y + 1 < height)));
+
+ if (low_effort) {
+ PredictBatch(kPredLowEffort, 0, y, width, current_row, upper_row,
+ argb + y * width);
+ } else {
+ if (max_quantization > 1) {
+ // Compute max_diffs for the lower row now, because that needs the
+ // contents of argb for the current row, which we will overwrite with
+ // residuals before proceeding with the next row.
+ uint8_t* const tmp8 = current_max_diffs;
+ current_max_diffs = lower_max_diffs;
+ lower_max_diffs = tmp8;
+ if (y + 2 < height) {
+ MaxDiffsForRow(width, width, argb + (y + 1) * width, lower_max_diffs,
+ used_subtract_green);
+ }
+ }
+ for (x = 0; x < width;) {
+ const int mode =
+ (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff;
+ int x_end = x + (1 << bits);
+ if (x_end > width) x_end = width;
+ GetResidual(width, height, upper_row, current_row, current_max_diffs,
+ mode, x, x_end, y, max_quantization, exact,
+ used_subtract_green, argb + y * width + x);
+ x = x_end;
+ }
+ }
+ }
+}
+
+// Finds the best predictor for each tile, and converts the image to residuals
+// with respect to predictions. If near_lossless_quality < 100, applies
+// near lossless processing, shaving off more bits of residuals for lower
+// qualities.
+void VP8LResidualImage(int width, int height, int bits, int low_effort,
+ uint32_t* const argb, uint32_t* const argb_scratch,
+ uint32_t* const image, int near_lossless_quality,
+ int exact, int used_subtract_green) {
+ const int tiles_per_row = VP8LSubSampleSize(width, bits);
+ const int tiles_per_col = VP8LSubSampleSize(height, bits);
+ int tile_y;
+ int histo[4][256];
+ const int max_quantization = 1 << VP8LNearLosslessBits(near_lossless_quality);
+ if (low_effort) {
+ int i;
+ for (i = 0; i < tiles_per_row * tiles_per_col; ++i) {
+ image[i] = ARGB_BLACK | (kPredLowEffort << 8);
+ }
+ } else {
+ memset(histo, 0, sizeof(histo));
+ for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
+ int tile_x;
+ for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
+ const int pred = GetBestPredictorForTile(width, height, tile_x, tile_y,
+ bits, histo, argb_scratch, argb, max_quantization, exact,
+ used_subtract_green, image);
+ image[tile_y * tiles_per_row + tile_x] = ARGB_BLACK | (pred << 8);
+ }
+ }
+ }
+
+ CopyImageWithPrediction(width, height, bits, image, argb_scratch, argb,
+ low_effort, max_quantization, exact,
+ used_subtract_green);
+}
+
+//------------------------------------------------------------------------------
+// Color transform functions.
+
+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 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_;
+}
+
+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 VP8LCombinedShannonEntropy(counts, accumulated) +
+ PredictionCostSpatial(counts, 3, kExpValue);
+}
+
+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;
+}
+
+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];
+ }
+ }
+ }
+ }
+}
diff --git a/thirdparty/libwebp/enc/quant.c b/thirdparty/libwebp/enc/quant.c
deleted file mode 100644
index 07ffaf0aeb..0000000000
--- a/thirdparty/libwebp/enc/quant.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Quantization
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <math.h>
-#include <stdlib.h> // for abs()
-
-#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 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.
-
-// 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)
-
-#define RD_DISTO_MULT 256 // distortion multiplier (equivalent of lambda)
-
-// #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);
- const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC;
- const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC;
- const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC;
- const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC;
- printf("SOURCE / OUTPUT / ABS DELTA\n");
- for (j = 0; j < 16; ++j) {
- for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 16; ++i) {
- printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS]));
- }
- printf("\n");
- }
- printf("\n"); // newline before the U/V block
- for (j = 0; j < 8; ++j) {
- for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]);
- printf(" ");
- for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]);
- printf(" ");
- for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]);
- printf(" ");
- for (i = 0; i < 8; ++i) {
- printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS]));
- }
- printf(" ");
- for (i = 8; i < 16; ++i) {
- printf("%1d ", abs(uv_out[i + j * BPS] - uv_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
-
-//------------------------------------------------------------------------------
-
-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 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.
-// 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,
- 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, 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 (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;
-}
-
-static void CheckLambdaValue(int* const v) { if (*v < 1) *v = 1; }
-
-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 q_i4, q_i16, q_uv;
- 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)];
-
- q_i4 = ExpandMatrix(&m->y1_, 0);
- q_i16 = ExpandMatrix(&m->y2_, 1);
- q_uv = ExpandMatrix(&m->uv_, 2);
-
- m->lambda_i4_ = (3 * q_i4 * q_i4) >> 7;
- m->lambda_i16_ = (3 * q_i16 * q_i16);
- m->lambda_uv_ = (3 * q_uv * q_uv) >> 6;
- m->lambda_mode_ = (1 * q_i4 * q_i4) >> 7;
- m->lambda_trellis_i4_ = (7 * q_i4 * q_i4) >> 3;
- m->lambda_trellis_i16_ = (q_i16 * q_i16) >> 2;
- m->lambda_trellis_uv_ = (q_uv * q_uv) << 1;
- m->tlambda_ = (tlambda_scale * q_i4) >> 5;
-
- // none of these constants should be < 1
- CheckLambdaValue(&m->lambda_i4_);
- CheckLambdaValue(&m->lambda_i16_);
- CheckLambdaValue(&m->lambda_uv_);
- CheckLambdaValue(&m->lambda_mode_);
- CheckLambdaValue(&m->lambda_trellis_i4_);
- CheckLambdaValue(&m->lambda_trellis_i16_);
- CheckLambdaValue(&m->lambda_trellis_uv_);
- CheckLambdaValue(&m->tlambda_);
-
- m->min_disto_ = 20 * m->y1_.q_[0]; // quantization-aware min disto
- m->max_edge_ = 0;
-
- m->i4_penalty_ = 1000 * q_i4 * q_i4;
- }
-}
-
-//------------------------------------------------------------------------------
-// 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 2
-
-static void SetupFilterStrength(VP8Encoder* const enc) {
- int i;
- // 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) {
- 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_;
- 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 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 };
- // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an
- // explicit check is needed to avoid a spurious warning about 'i' exceeding
- // array bounds of 'dqm_' with some compilers (noticed with gcc-4.9).
- const int num_segments = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS)
- ? enc->segment_hdr_.num_segments_
- : NUM_MB_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->segment_hdr_.num_segments_;
- const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.;
- 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) {
- // 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.);
- 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 unpleasant).
- 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;
-
- SetupFilterStrength(enc); // initialize segments' filtering, eventually
-
- if (num_segments > 1) SimplifySegments(enc);
-
- SetupMatrices(enc); // finalize quantization matrices
-}
-
-//------------------------------------------------------------------------------
-// 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 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 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);
-}
-
-void VP8MakeIntra4Preds(const VP8EncIterator* const it) {
- VP8EncPredLuma4(it->yuv_p_, it->i4_top_);
-}
-
-//------------------------------------------------------------------------------
-// Quantize
-
-// Layout:
-// +----+----+
-// |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
-};
-
-//------------------------------------------------------------------------------
-// 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->H = 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->H = src->H;
- 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->H += src->H;
- dst->nz |= src->nz; // here, new nz bits are accumulated.
- dst->score += src->score;
-}
-
-//------------------------------------------------------------------------------
-// Performs trellis-optimized quantization.
-
-// Trellis node
-typedef struct {
- 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)][(l) + MIN_DELTA])
-#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA])
-
-static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) {
- rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD);
-}
-
-static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate,
- score_t distortion) {
- return rate * lambda + RD_DISTO_MULT * distortion;
-}
-
-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) {
- 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[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 n, m, p, last;
-
- {
- score_t cost;
- const int thresh = mtx->q_[1] * mtx->q_[1] / 4;
- const int last_proba = probas[VP8EncBands[first]][ctx0][0];
-
- // 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];
- 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.
- 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, 0);
-
- // initialize source node.
- for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
- 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 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);
- 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;
- }
-
- // test all alternate level values around level0.
- for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
- Node* const cur = &NODE(n, m);
- int level = level0 + m;
- 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;
- }
-
- // 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) {
- // 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.
- 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;
- }
- }
- // 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
- }
- }
- }
- }
-
- // 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.
- 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);
- }
-}
-
-#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_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 += 2) {
- VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]);
- }
- VP8FTransformWHT(tmp[0], dc_tmp);
- nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &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(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 += 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
- VP8TransformWHT(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(enc, tmp, levels, ctx, 3, &dqm->y1_,
- dqm->lambda_trellis_i4_);
- } else {
- nz = VP8EncQuantizeBlock(tmp, levels, &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_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 += 2) {
- VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[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(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 += 2) {
- nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n;
- }
- }
-
- for (n = 0; n < 8; n += 2) {
- 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 + 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[2]);
- const int v2 = abs(DCs[4]);
- int max_v = (v1 > v0) ? 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;
- *a = *b;
- *b = tmp;
-}
-
-static void SwapOut(VP8EncIterator* const it) {
- SwapPtr(&it->yuv_out_, &it->yuv_out2_);
-}
-
-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_ENC;
- VP8ModeScore rd_tmp;
- VP8ModeScore* rd_cur = &rd_tmp;
- VP8ModeScore* rd_best = rd;
- int mode;
-
- rd->mode_i16 = -1;
- 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
- rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode);
-
- // Measure RD-score
- 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, 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 & 0x100ffff) == 0x1000000 && rd->D > dqm->min_disto_) {
- StoreMaxDelta(dqm, rd->y_dc_levels);
- }
-}
-
-//------------------------------------------------------------------------------
-
-// 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_ENC;
- uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC;
- int total_header_bits = 0;
- VP8ModeScore rd_best;
-
- if (enc->max_i4_header_bits_ == 0) {
- return 0;
- }
-
- InitScore(&rd_best);
- 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;
- 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.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(rd_best.y_ac_levels[it->i4_]));
- }
- }
- SetRDScore(dqm->lambda_mode_, &rd_i4);
- AddScore(&rd_best, &rd_i4);
- 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_]) {
- 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 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_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 < NUM_PRED_MODES; ++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; // not calling TDisto here: it tends to flatten areas.
- rd_uv.H = VP8FixedCostsUV[mode];
- rd_uv.R = VP8GetCostUV(it, &rd_uv);
- 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));
- SwapPtr(&dst, &tmp_dst);
- }
- }
- VP8SetIntraUVMode(it, rd->mode_uv);
- AddScore(rd, &rd_best);
- if (dst != dst0) { // copy 16x8 block if needed
- VP8Copy16x8(dst, dst0);
- }
-}
-
-//------------------------------------------------------------------------------
-// Final reconstruction and quantization.
-
-static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
- const VP8Encoder* const enc = it->enc_;
- const int is_i16 = (it->mb_->type_ == 1);
- int nz = 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_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_ENC));
- }
-
- 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 RefineUsingDistortion(VP8EncIterator* const it,
- int try_both_modes, int refine_uv_mode,
- VP8ModeScore* const rd) {
- score_t best_score = MAX_COST;
- int nz = 0;
- int mode;
- int is_i16 = try_both_modes || (it->mb_->type_ == 1);
-
- const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
- // Some empiric constants, of approximate order of magnitude.
- const int lambda_d_i16 = 106;
- const int lambda_d_i4 = 11;
- const int lambda_d_uv = 120;
- score_t score_i4 = dqm->i4_penalty_;
- score_t i4_bit_sum = 0;
- const score_t bit_limit = try_both_modes ? it->enc_->mb_header_limit_
- : MAX_COST; // no early-out allowed
-
- if (is_i16) { // First, evaluate Intra16 distortion
- int best_mode = -1;
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
- for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
- const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
- const score_t score = VP8SSE16x16(src, ref) * RD_DISTO_MULT
- + VP8FixedCostsI16[mode] * lambda_d_i16;
- if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) {
- continue;
- }
- if (score < best_score) {
- best_mode = mode;
- best_score = score;
- }
- }
- VP8SetIntra16Mode(it, best_mode);
- // we'll reconstruct later, if i16 mode actually gets selected
- }
-
- // Next, evaluate Intra4
- if (try_both_modes || !is_i16) {
- // 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).
- is_i16 = 0;
- VP8IteratorStartI4(it);
- do {
- int best_i4_mode = -1;
- score_t best_i4_score = MAX_COST;
- const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
- const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4);
-
- 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) * RD_DISTO_MULT
- + mode_costs[mode] * lambda_d_i4;
- if (score < best_i4_score) {
- best_i4_mode = mode;
- best_i4_score = score;
- }
- }
- i4_bit_sum += mode_costs[best_i4_mode];
- rd->modes_i4[it->i4_] = best_i4_mode;
- score_i4 += best_i4_score;
- if (score_i4 >= best_score || i4_bit_sum > bit_limit) {
- // Intra4 won't be better than Intra16. Bail out and pick Intra16.
- is_i16 = 1;
- break;
- } else { // reconstruct partial block inside yuv_out2_ buffer
- uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_];
- nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
- src, tmp_dst, best_i4_mode) << it->i4_;
- }
- } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC));
- }
-
- // Final reconstruction, depending on which mode is selected.
- if (!is_i16) {
- VP8SetIntra4Mode(it, rd->modes_i4);
- SwapOut(it);
- best_score = score_i4;
- } else {
- nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
- }
-
- // ... and UV!
- if (refine_uv_mode) {
- int best_mode = -1;
- score_t best_uv_score = MAX_COST;
- const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
- for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
- const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
- const score_t score = VP8SSE16x8(src, ref) * RD_DISTO_MULT
- + VP8FixedCostsUV[mode] * lambda_d_uv;
- if (score < best_uv_score) {
- best_mode = mode;
- best_uv_score = score;
- }
- }
- VP8SetIntraUVMode(it, best_mode);
- }
- nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
-
- rd->nz = nz;
- rd->score = best_score;
-}
-
-//------------------------------------------------------------------------------
-// Entry point
-
-int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd,
- VP8RDLevel rd_opt) {
- int is_skipped;
- const int method = it->enc_->method_;
-
- InitScore(rd);
-
- // We can perform predictions for Luma16x16 and Chroma8x8 already.
- // Luma4x4 predictions needs to be done as-we-go.
- VP8MakeLuma16Preds(it);
- VP8MakeChroma8Preds(it);
-
- if (rd_opt > RD_OPT_NONE) {
- it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL);
- PickBestIntra16(it, rd);
- if (method >= 2) {
- PickBestIntra4(it, rd);
- }
- PickBestUV(it, rd);
- if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now
- it->do_trellis_ = 1;
- SimpleQuantize(it, rd);
- }
- } else {
- // At this point we have heuristically decided intra16 / intra4.
- // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower).
- // For method <= 1, we don't re-examine the decision but just go ahead with
- // quantization/reconstruction.
- RefineUsingDistortion(it, (method >= 2), (method >= 1), rd);
- }
- is_skipped = (rd->nz == 0);
- VP8SetSkip(it, is_skipped);
- return is_skipped;
-}
diff --git a/thirdparty/libwebp/enc/quant_enc.c b/thirdparty/libwebp/enc/quant_enc.c
new file mode 100644
index 0000000000..b118fb2a13
--- /dev/null
+++ b/thirdparty/libwebp/enc/quant_enc.c
@@ -0,0 +1,1283 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Quantization
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h> // for abs()
+
+#include "./vp8i_enc.h"
+#include "./cost_enc.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 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.
+
+// 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)
+
+#define RD_DISTO_MULT 256 // distortion multiplier (equivalent of lambda)
+
+// #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);
+ const uint8_t* const y_in = it->yuv_in_ + Y_OFF_ENC;
+ const uint8_t* const y_out = it->yuv_out_ + Y_OFF_ENC;
+ const uint8_t* const uv_in = it->yuv_in_ + U_OFF_ENC;
+ const uint8_t* const uv_out = it->yuv_out_ + U_OFF_ENC;
+ printf("SOURCE / OUTPUT / ABS DELTA\n");
+ for (j = 0; j < 16; ++j) {
+ for (i = 0; i < 16; ++i) printf("%3d ", y_in[i + j * BPS]);
+ printf(" ");
+ for (i = 0; i < 16; ++i) printf("%3d ", y_out[i + j * BPS]);
+ printf(" ");
+ for (i = 0; i < 16; ++i) {
+ printf("%1d ", abs(y_in[i + j * BPS] - y_out[i + j * BPS]));
+ }
+ printf("\n");
+ }
+ printf("\n"); // newline before the U/V block
+ for (j = 0; j < 8; ++j) {
+ for (i = 0; i < 8; ++i) printf("%3d ", uv_in[i + j * BPS]);
+ printf(" ");
+ for (i = 8; i < 16; ++i) printf("%3d ", uv_in[i + j * BPS]);
+ printf(" ");
+ for (i = 0; i < 8; ++i) printf("%3d ", uv_out[i + j * BPS]);
+ printf(" ");
+ for (i = 8; i < 16; ++i) printf("%3d ", uv_out[i + j * BPS]);
+ printf(" ");
+ for (i = 0; i < 8; ++i) {
+ printf("%1d ", abs(uv_out[i + j * BPS] - uv_in[i + j * BPS]));
+ }
+ printf(" ");
+ for (i = 8; i < 16; ++i) {
+ printf("%1d ", abs(uv_out[i + j * BPS] - uv_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
+
+//------------------------------------------------------------------------------
+
+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 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.
+// 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,
+ 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, 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 (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;
+}
+
+static void CheckLambdaValue(int* const v) { if (*v < 1) *v = 1; }
+
+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 q_i4, q_i16, q_uv;
+ 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)];
+
+ q_i4 = ExpandMatrix(&m->y1_, 0);
+ q_i16 = ExpandMatrix(&m->y2_, 1);
+ q_uv = ExpandMatrix(&m->uv_, 2);
+
+ m->lambda_i4_ = (3 * q_i4 * q_i4) >> 7;
+ m->lambda_i16_ = (3 * q_i16 * q_i16);
+ m->lambda_uv_ = (3 * q_uv * q_uv) >> 6;
+ m->lambda_mode_ = (1 * q_i4 * q_i4) >> 7;
+ m->lambda_trellis_i4_ = (7 * q_i4 * q_i4) >> 3;
+ m->lambda_trellis_i16_ = (q_i16 * q_i16) >> 2;
+ m->lambda_trellis_uv_ = (q_uv * q_uv) << 1;
+ m->tlambda_ = (tlambda_scale * q_i4) >> 5;
+
+ // none of these constants should be < 1
+ CheckLambdaValue(&m->lambda_i4_);
+ CheckLambdaValue(&m->lambda_i16_);
+ CheckLambdaValue(&m->lambda_uv_);
+ CheckLambdaValue(&m->lambda_mode_);
+ CheckLambdaValue(&m->lambda_trellis_i4_);
+ CheckLambdaValue(&m->lambda_trellis_i16_);
+ CheckLambdaValue(&m->lambda_trellis_uv_);
+ CheckLambdaValue(&m->tlambda_);
+
+ m->min_disto_ = 20 * m->y1_.q_[0]; // quantization-aware min disto
+ m->max_edge_ = 0;
+
+ m->i4_penalty_ = 1000 * q_i4 * q_i4;
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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 2
+
+static void SetupFilterStrength(VP8Encoder* const enc) {
+ int i;
+ // 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) {
+ 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_;
+ 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 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 };
+ // 'num_segments_' is previously validated and <= NUM_MB_SEGMENTS, but an
+ // explicit check is needed to avoid a spurious warning about 'i' exceeding
+ // array bounds of 'dqm_' with some compilers (noticed with gcc-4.9).
+ const int num_segments = (enc->segment_hdr_.num_segments_ < NUM_MB_SEGMENTS)
+ ? enc->segment_hdr_.num_segments_
+ : NUM_MB_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->segment_hdr_.num_segments_;
+ const double amp = SNS_TO_DQ * enc->config_->sns_strength / 100. / 128.;
+ 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) {
+ // 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.);
+ 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 unpleasant).
+ 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;
+
+ SetupFilterStrength(enc); // initialize segments' filtering, eventually
+
+ if (num_segments > 1) SimplifySegments(enc);
+
+ SetupMatrices(enc); // finalize quantization matrices
+}
+
+//------------------------------------------------------------------------------
+// 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 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 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);
+}
+
+void VP8MakeIntra4Preds(const VP8EncIterator* const it) {
+ VP8EncPredLuma4(it->yuv_p_, it->i4_top_);
+}
+
+//------------------------------------------------------------------------------
+// Quantize
+
+// Layout:
+// +----+----+
+// |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
+};
+
+//------------------------------------------------------------------------------
+// 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->H = 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->H = src->H;
+ 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->H += src->H;
+ dst->nz |= src->nz; // here, new nz bits are accumulated.
+ dst->score += src->score;
+}
+
+//------------------------------------------------------------------------------
+// Performs trellis-optimized quantization.
+
+// Trellis node
+typedef struct {
+ 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)][(l) + MIN_DELTA])
+#define SCORE_STATE(n, l) (score_states[n][(l) + MIN_DELTA])
+
+static WEBP_INLINE void SetRDScore(int lambda, VP8ModeScore* const rd) {
+ rd->score = (rd->R + rd->H) * lambda + RD_DISTO_MULT * (rd->D + rd->SD);
+}
+
+static WEBP_INLINE score_t RDScoreTrellis(int lambda, score_t rate,
+ score_t distortion) {
+ return rate * lambda + RD_DISTO_MULT * distortion;
+}
+
+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) {
+ 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[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 n, m, p, last;
+
+ {
+ score_t cost;
+ const int thresh = mtx->q_[1] * mtx->q_[1] / 4;
+ const int last_proba = probas[VP8EncBands[first]][ctx0][0];
+
+ // 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];
+ 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.
+ 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, 0);
+
+ // initialize source node.
+ for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
+ 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 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);
+ const uint32_t coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
+ int level0 = QUANTDIV(coeff0, iQ, B);
+ int thresh_level = QUANTDIV(coeff0, iQ, BIAS(0x80));
+ if (thresh_level > MAX_LEVEL) thresh_level = MAX_LEVEL;
+ 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;
+ }
+
+ // test all alternate level values around level0.
+ for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) {
+ Node* const cur = &NODE(n, m);
+ int level = level0 + m;
+ const int ctx = (level > 2) ? 2 : level;
+ const int band = VP8EncBands[n + 1];
+ score_t base_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 < 0 || level > thresh_level) {
+ // Node is dead.
+ continue;
+ }
+
+ {
+ // 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) {
+ // 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.
+ 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;
+ }
+ }
+ // 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 last_pos_cost =
+ (n < 15) ? VP8BitCost(0, probas[band][ctx][0]) : 0;
+ const score_t last_pos_score = RDScoreTrellis(lambda, last_pos_cost, 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
+ }
+ }
+ }
+ }
+
+ // 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.
+ 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);
+ }
+}
+
+#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_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 += 2) {
+ VP8FTransform2(src + VP8Scan[n], ref + VP8Scan[n], tmp[n]);
+ }
+ VP8FTransformWHT(tmp[0], dc_tmp);
+ nz |= VP8EncQuantizeBlockWHT(dc_tmp, rd->y_dc_levels, &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(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 += 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
+ VP8TransformWHT(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(enc, tmp, levels, ctx, 3, &dqm->y1_,
+ dqm->lambda_trellis_i4_);
+ } else {
+ nz = VP8EncQuantizeBlock(tmp, levels, &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_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 += 2) {
+ VP8FTransform2(src + VP8ScanUV[n], ref + VP8ScanUV[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(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 += 2) {
+ nz |= VP8EncQuantize2Blocks(tmp[n], rd->uv_levels[n], &dqm->uv_) << n;
+ }
+ }
+
+ for (n = 0; n < 8; n += 2) {
+ 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 + 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[2]);
+ const int v2 = abs(DCs[4]);
+ int max_v = (v1 > v0) ? 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;
+ *a = *b;
+ *b = tmp;
+}
+
+static void SwapOut(VP8EncIterator* const it) {
+ SwapPtr(&it->yuv_out_, &it->yuv_out2_);
+}
+
+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_ENC;
+ VP8ModeScore rd_tmp;
+ VP8ModeScore* rd_cur = &rd_tmp;
+ VP8ModeScore* rd_best = rd;
+ int mode;
+
+ rd->mode_i16 = -1;
+ 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
+ rd_cur->nz = ReconstructIntra16(it, rd_cur, tmp_dst, mode);
+
+ // Measure RD-score
+ 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, 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 & 0x100ffff) == 0x1000000 && rd->D > dqm->min_disto_) {
+ StoreMaxDelta(dqm, rd->y_dc_levels);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+// 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_ENC;
+ uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF_ENC;
+ int total_header_bits = 0;
+ VP8ModeScore rd_best;
+
+ if (enc->max_i4_header_bits_ == 0) {
+ return 0;
+ }
+
+ InitScore(&rd_best);
+ 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;
+ 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.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(rd_best.y_ac_levels[it->i4_]));
+ }
+ }
+ SetRDScore(dqm->lambda_mode_, &rd_i4);
+ AddScore(&rd_best, &rd_i4);
+ 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_]) {
+ 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 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_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 < NUM_PRED_MODES; ++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; // not calling TDisto here: it tends to flatten areas.
+ rd_uv.H = VP8FixedCostsUV[mode];
+ rd_uv.R = VP8GetCostUV(it, &rd_uv);
+ 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));
+ SwapPtr(&dst, &tmp_dst);
+ }
+ }
+ VP8SetIntraUVMode(it, rd->mode_uv);
+ AddScore(rd, &rd_best);
+ if (dst != dst0) { // copy 16x8 block if needed
+ VP8Copy16x8(dst, dst0);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Final reconstruction and quantization.
+
+static void SimpleQuantize(VP8EncIterator* const it, VP8ModeScore* const rd) {
+ const VP8Encoder* const enc = it->enc_;
+ const int is_i16 = (it->mb_->type_ == 1);
+ int nz = 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_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_ENC));
+ }
+
+ 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 RefineUsingDistortion(VP8EncIterator* const it,
+ int try_both_modes, int refine_uv_mode,
+ VP8ModeScore* const rd) {
+ score_t best_score = MAX_COST;
+ int nz = 0;
+ int mode;
+ int is_i16 = try_both_modes || (it->mb_->type_ == 1);
+
+ const VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
+ // Some empiric constants, of approximate order of magnitude.
+ const int lambda_d_i16 = 106;
+ const int lambda_d_i4 = 11;
+ const int lambda_d_uv = 120;
+ score_t score_i4 = dqm->i4_penalty_;
+ score_t i4_bit_sum = 0;
+ const score_t bit_limit = try_both_modes ? it->enc_->mb_header_limit_
+ : MAX_COST; // no early-out allowed
+
+ if (is_i16) { // First, evaluate Intra16 distortion
+ int best_mode = -1;
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC;
+ for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
+ const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode];
+ const score_t score = VP8SSE16x16(src, ref) * RD_DISTO_MULT
+ + VP8FixedCostsI16[mode] * lambda_d_i16;
+ if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) {
+ continue;
+ }
+ if (score < best_score) {
+ best_mode = mode;
+ best_score = score;
+ }
+ }
+ VP8SetIntra16Mode(it, best_mode);
+ // we'll reconstruct later, if i16 mode actually gets selected
+ }
+
+ // Next, evaluate Intra4
+ if (try_both_modes || !is_i16) {
+ // 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).
+ is_i16 = 0;
+ VP8IteratorStartI4(it);
+ do {
+ int best_i4_mode = -1;
+ score_t best_i4_score = MAX_COST;
+ const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC + VP8Scan[it->i4_];
+ const uint16_t* const mode_costs = GetCostModeI4(it, rd->modes_i4);
+
+ 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) * RD_DISTO_MULT
+ + mode_costs[mode] * lambda_d_i4;
+ if (score < best_i4_score) {
+ best_i4_mode = mode;
+ best_i4_score = score;
+ }
+ }
+ i4_bit_sum += mode_costs[best_i4_mode];
+ rd->modes_i4[it->i4_] = best_i4_mode;
+ score_i4 += best_i4_score;
+ if (score_i4 >= best_score || i4_bit_sum > bit_limit) {
+ // Intra4 won't be better than Intra16. Bail out and pick Intra16.
+ is_i16 = 1;
+ break;
+ } else { // reconstruct partial block inside yuv_out2_ buffer
+ uint8_t* const tmp_dst = it->yuv_out2_ + Y_OFF_ENC + VP8Scan[it->i4_];
+ nz |= ReconstructIntra4(it, rd->y_ac_levels[it->i4_],
+ src, tmp_dst, best_i4_mode) << it->i4_;
+ }
+ } while (VP8IteratorRotateI4(it, it->yuv_out2_ + Y_OFF_ENC));
+ }
+
+ // Final reconstruction, depending on which mode is selected.
+ if (!is_i16) {
+ VP8SetIntra4Mode(it, rd->modes_i4);
+ SwapOut(it);
+ best_score = score_i4;
+ } else {
+ nz = ReconstructIntra16(it, rd, it->yuv_out_ + Y_OFF_ENC, it->preds_[0]);
+ }
+
+ // ... and UV!
+ if (refine_uv_mode) {
+ int best_mode = -1;
+ score_t best_uv_score = MAX_COST;
+ const uint8_t* const src = it->yuv_in_ + U_OFF_ENC;
+ for (mode = 0; mode < NUM_PRED_MODES; ++mode) {
+ const uint8_t* const ref = it->yuv_p_ + VP8UVModeOffsets[mode];
+ const score_t score = VP8SSE16x8(src, ref) * RD_DISTO_MULT
+ + VP8FixedCostsUV[mode] * lambda_d_uv;
+ if (score < best_uv_score) {
+ best_mode = mode;
+ best_uv_score = score;
+ }
+ }
+ VP8SetIntraUVMode(it, best_mode);
+ }
+ nz |= ReconstructUV(it, rd, it->yuv_out_ + U_OFF_ENC, it->mb_->uv_mode_);
+
+ rd->nz = nz;
+ rd->score = best_score;
+}
+
+//------------------------------------------------------------------------------
+// Entry point
+
+int VP8Decimate(VP8EncIterator* const it, VP8ModeScore* const rd,
+ VP8RDLevel rd_opt) {
+ int is_skipped;
+ const int method = it->enc_->method_;
+
+ InitScore(rd);
+
+ // We can perform predictions for Luma16x16 and Chroma8x8 already.
+ // Luma4x4 predictions needs to be done as-we-go.
+ VP8MakeLuma16Preds(it);
+ VP8MakeChroma8Preds(it);
+
+ if (rd_opt > RD_OPT_NONE) {
+ it->do_trellis_ = (rd_opt >= RD_OPT_TRELLIS_ALL);
+ PickBestIntra16(it, rd);
+ if (method >= 2) {
+ PickBestIntra4(it, rd);
+ }
+ PickBestUV(it, rd);
+ if (rd_opt == RD_OPT_TRELLIS) { // finish off with trellis-optim now
+ it->do_trellis_ = 1;
+ SimpleQuantize(it, rd);
+ }
+ } else {
+ // At this point we have heuristically decided intra16 / intra4.
+ // For method >= 2, pick the best intra4/intra16 based on SSE (~tad slower).
+ // For method <= 1, we don't re-examine the decision but just go ahead with
+ // quantization/reconstruction.
+ RefineUsingDistortion(it, (method >= 2), (method >= 1), rd);
+ }
+ is_skipped = (rd->nz == 0);
+ VP8SetSkip(it, is_skipped);
+ return is_skipped;
+}
diff --git a/thirdparty/libwebp/enc/syntax.c b/thirdparty/libwebp/enc/syntax.c
deleted file mode 100644
index a0e79ef404..0000000000
--- a/thirdparty/libwebp/enc/syntax.c
+++ /dev/null
@@ -1,383 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Header syntax writing
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-
-#include "../utils/utils.h"
-#include "../webp/format_constants.h" // RIFF constants
-#include "../webp/mux_types.h" // ALPHA_FLAG
-#include "./vp8enci.h"
-
-//------------------------------------------------------------------------------
-// Helper functions
-
-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;
- }
-
- 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 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;
- 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) {
- VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7);
- }
- for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
- VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6);
- }
- }
- if (hdr->update_map_) {
- for (s = 0; s < 3; ++s) {
- if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) {
- VP8PutBits(bw, proba->segments_[s], 8);
- }
- }
- }
- }
-}
-
-// Filtering parameters header
-static void PutFilterHeader(VP8BitWriter* const bw,
- const VP8EncFilterHeader* const hdr) {
- const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0);
- VP8PutBitUniform(bw, hdr->simple_);
- 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
- VP8PutBits(bw, 0, 4);
- // we use mode_lf_delta for i4x4
- VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6);
- VP8PutBits(bw, 0, 3); // all others unused
- }
- }
-}
-
-// Nominal quantization parameters
-static void PutQuant(VP8BitWriter* const bw,
- const VP8Encoder* const enc) {
- 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
-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;
-}
-
-//------------------------------------------------------------------------------
-
-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;
-
- pos1 = VP8BitWriterPos(bw);
- 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
- VP8PutBitUniform(bw, 0); // clamp type
-
- PutSegmentHeader(bw, enc);
- PutFilterHeader(bw, &enc->filter_hdr_);
- 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_);
- pos2 = VP8BitWriterPos(bw);
- VP8CodeIntraModes(enc);
- VP8BitWriterFinish(bw);
-
- 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_;
- }
- if (bw->error_) {
- return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
- }
- return 1;
-}
-
-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);
- if (!ok) return 0;
-
- // 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;
-}
-
-//------------------------------------------------------------------------------
-
diff --git a/thirdparty/libwebp/enc/syntax_enc.c b/thirdparty/libwebp/enc/syntax_enc.c
new file mode 100644
index 0000000000..90665bd7e5
--- /dev/null
+++ b/thirdparty/libwebp/enc/syntax_enc.c
@@ -0,0 +1,382 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Header syntax writing
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+
+#include "../utils/utils.h"
+#include "../webp/format_constants.h" // RIFF constants
+#include "../webp/mux_types.h" // ALPHA_FLAG
+#include "./vp8i_enc.h"
+
+//------------------------------------------------------------------------------
+// Helper functions
+
+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;
+ }
+
+ 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 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;
+ 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) {
+ VP8PutSignedBits(bw, enc->dqm_[s].quant_, 7);
+ }
+ for (s = 0; s < NUM_MB_SEGMENTS; ++s) {
+ VP8PutSignedBits(bw, enc->dqm_[s].fstrength_, 6);
+ }
+ }
+ if (hdr->update_map_) {
+ for (s = 0; s < 3; ++s) {
+ if (VP8PutBitUniform(bw, (proba->segments_[s] != 255u))) {
+ VP8PutBits(bw, proba->segments_[s], 8);
+ }
+ }
+ }
+ }
+}
+
+// Filtering parameters header
+static void PutFilterHeader(VP8BitWriter* const bw,
+ const VP8EncFilterHeader* const hdr) {
+ const int use_lf_delta = (hdr->i4x4_lf_delta_ != 0);
+ VP8PutBitUniform(bw, hdr->simple_);
+ 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
+ VP8PutBits(bw, 0, 4);
+ // we use mode_lf_delta for i4x4
+ VP8PutSignedBits(bw, hdr->i4x4_lf_delta_, 6);
+ VP8PutBits(bw, 0, 3); // all others unused
+ }
+ }
+}
+
+// Nominal quantization parameters
+static void PutQuant(VP8BitWriter* const bw,
+ const VP8Encoder* const enc) {
+ 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
+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;
+}
+
+//------------------------------------------------------------------------------
+
+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;
+
+ pos1 = VP8BitWriterPos(bw);
+ 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
+ VP8PutBitUniform(bw, 0); // clamp type
+
+ PutSegmentHeader(bw, enc);
+ PutFilterHeader(bw, &enc->filter_hdr_);
+ 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_);
+ pos2 = VP8BitWriterPos(bw);
+ VP8CodeIntraModes(enc);
+ VP8BitWriterFinish(bw);
+
+ 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_;
+ }
+ if (bw->error_) {
+ return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
+ }
+ return 1;
+}
+
+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);
+ if (!ok) return 0;
+
+ // 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;
+}
+
+//------------------------------------------------------------------------------
+
diff --git a/thirdparty/libwebp/enc/token.c b/thirdparty/libwebp/enc/token.c
deleted file mode 100644
index 087940e5ff..0000000000
--- a/thirdparty/libwebp/enc/token.c
+++ /dev/null
@@ -1,293 +0,0 @@
-// 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,
- proba_t* const stats) {
- 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;
- }
- VP8RecordStats(bit, stats);
- 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(int ctx, const struct VP8Residual* const res,
- VP8TBuffer* const tokens) {
- const int16_t* const coeffs = res->coeffs;
- const int coeff_type = res->coeff_type;
- const int last = res->last;
- int n = res->first;
- uint32_t base_id = TOKEN_ID(coeff_type, n, ctx);
- // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1
- proba_t* s = res->stats[n][ctx];
- if (!AddToken(tokens, last >= 0, base_id + 0, s + 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, s + 1)) {
- base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0
- s = res->stats[VP8EncBands[n]][0];
- continue;
- }
- if (!AddToken(tokens, v > 1, base_id + 2, s + 2)) {
- base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1
- s = res->stats[VP8EncBands[n]][1];
- } else {
- if (!AddToken(tokens, v > 4, base_id + 3, s + 3)) {
- if (AddToken(tokens, v != 2, base_id + 4, s + 4))
- AddToken(tokens, v == 4, base_id + 5, s + 5);
- } else if (!AddToken(tokens, v > 10, base_id + 6, s + 6)) {
- if (!AddToken(tokens, v > 6, base_id + 7, s + 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, s + 8);
- AddToken(tokens, 0, base_id + 9, s + 9);
- residue -= (8 << 0);
- mask = 1 << 2;
- tab = VP8Cat3;
- } else if (residue < (8 << 2)) { // VP8Cat4 (4b)
- AddToken(tokens, 0, base_id + 8, s + 8);
- AddToken(tokens, 1, base_id + 9, s + 9);
- residue -= (8 << 1);
- mask = 1 << 3;
- tab = VP8Cat4;
- } else if (residue < (8 << 3)) { // VP8Cat5 (5b)
- AddToken(tokens, 1, base_id + 8, s + 8);
- AddToken(tokens, 0, base_id + 10, s + 9);
- residue -= (8 << 2);
- mask = 1 << 4;
- tab = VP8Cat5;
- } else { // VP8Cat6 (11b)
- AddToken(tokens, 1, base_id + 8, s + 8);
- AddToken(tokens, 1, base_id + 10, s + 9);
- 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
- s = res->stats[VP8EncBands[n]][2];
- }
- AddConstantToken(tokens, sign, 128);
- if (n == 16 || !AddToken(tokens, n <= last, base_id + 0, s + 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/thirdparty/libwebp/enc/token_enc.c b/thirdparty/libwebp/enc/token_enc.c
new file mode 100644
index 0000000000..02a0d72cc6
--- /dev/null
+++ b/thirdparty/libwebp/enc/token_enc.c
@@ -0,0 +1,294 @@
+// 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_enc.h"
+#include "./vp8i_enc.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,
+ proba_t* const stats) {
+ 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;
+ }
+ VP8RecordStats(bit, stats);
+ 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(int ctx, const struct VP8Residual* const res,
+ VP8TBuffer* const tokens) {
+ const int16_t* const coeffs = res->coeffs;
+ const int coeff_type = res->coeff_type;
+ const int last = res->last;
+ int n = res->first;
+ uint32_t base_id = TOKEN_ID(coeff_type, n, ctx);
+ // should be stats[VP8EncBands[n]], but it's equivalent for n=0 or 1
+ proba_t* s = res->stats[n][ctx];
+ if (!AddToken(tokens, last >= 0, base_id + 0, s + 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, s + 1)) {
+ base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 0); // ctx=0
+ s = res->stats[VP8EncBands[n]][0];
+ continue;
+ }
+ if (!AddToken(tokens, v > 1, base_id + 2, s + 2)) {
+ base_id = TOKEN_ID(coeff_type, VP8EncBands[n], 1); // ctx=1
+ s = res->stats[VP8EncBands[n]][1];
+ } else {
+ if (!AddToken(tokens, v > 4, base_id + 3, s + 3)) {
+ if (AddToken(tokens, v != 2, base_id + 4, s + 4)) {
+ AddToken(tokens, v == 4, base_id + 5, s + 5);
+ }
+ } else if (!AddToken(tokens, v > 10, base_id + 6, s + 6)) {
+ if (!AddToken(tokens, v > 6, base_id + 7, s + 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, s + 8);
+ AddToken(tokens, 0, base_id + 9, s + 9);
+ residue -= (8 << 0);
+ mask = 1 << 2;
+ tab = VP8Cat3;
+ } else if (residue < (8 << 2)) { // VP8Cat4 (4b)
+ AddToken(tokens, 0, base_id + 8, s + 8);
+ AddToken(tokens, 1, base_id + 9, s + 9);
+ residue -= (8 << 1);
+ mask = 1 << 3;
+ tab = VP8Cat4;
+ } else if (residue < (8 << 3)) { // VP8Cat5 (5b)
+ AddToken(tokens, 1, base_id + 8, s + 8);
+ AddToken(tokens, 0, base_id + 10, s + 9);
+ residue -= (8 << 2);
+ mask = 1 << 4;
+ tab = VP8Cat5;
+ } else { // VP8Cat6 (11b)
+ AddToken(tokens, 1, base_id + 8, s + 8);
+ AddToken(tokens, 1, base_id + 10, s + 9);
+ 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
+ s = res->stats[VP8EncBands[n]][2];
+ }
+ AddConstantToken(tokens, sign, 128);
+ if (n == 16 || !AddToken(tokens, n <= last, base_id + 0, s + 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/thirdparty/libwebp/enc/tree.c b/thirdparty/libwebp/enc/tree.c
deleted file mode 100644
index f141006d19..0000000000
--- a/thirdparty/libwebp/enc/tree.c
+++ /dev/null
@@ -1,504 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Coding of token probabilities, intra modes and segments.
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include "./vp8enci.h"
-
-//------------------------------------------------------------------------------
-// Default probabilities
-
-// Paragraph 13.5
-const uint8_t
- VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
- { { { 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) {
- VP8EncProba* 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* const 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));
-}
-
-//------------------------------------------------------------------------------
-// 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 VP8EncProba* 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])) {
- VP8PutBits(bw, p0, 8);
- }
- }
- }
- }
- }
- if (VP8PutBitUniform(bw, probas->use_skip_proba_)) {
- VP8PutBits(bw, probas->skip_proba_, 8);
- }
-}
-
diff --git a/thirdparty/libwebp/enc/tree_enc.c b/thirdparty/libwebp/enc/tree_enc.c
new file mode 100644
index 0000000000..2c40fe7f3d
--- /dev/null
+++ b/thirdparty/libwebp/enc/tree_enc.c
@@ -0,0 +1,504 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Coding of token probabilities, intra modes and segments.
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include "./vp8i_enc.h"
+
+//------------------------------------------------------------------------------
+// Default probabilities
+
+// Paragraph 13.5
+const uint8_t
+ VP8CoeffsProba0[NUM_TYPES][NUM_BANDS][NUM_CTX][NUM_PROBAS] = {
+ { { { 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) {
+ VP8EncProba* 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* const 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));
+}
+
+//------------------------------------------------------------------------------
+// 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 VP8EncProba* 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])) {
+ VP8PutBits(bw, p0, 8);
+ }
+ }
+ }
+ }
+ }
+ if (VP8PutBitUniform(bw, probas->use_skip_proba_)) {
+ VP8PutBits(bw, probas->skip_proba_, 8);
+ }
+}
+
diff --git a/thirdparty/libwebp/enc/vp8enci.h b/thirdparty/libwebp/enc/vp8enci.h
deleted file mode 100644
index 5b4e162a58..0000000000
--- a/thirdparty/libwebp/enc/vp8enci.h
+++ /dev/null
@@ -1,529 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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 "../dec/common.h"
-#include "../dsp/dsp.h"
-#include "../utils/bit_writer.h"
-#include "../utils/thread.h"
-#include "../utils/utils.h"
-#include "../webp/encode.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//------------------------------------------------------------------------------
-// Various defines and enums
-
-// version numbers
-#define ENC_MAJ_VERSION 0
-#define ENC_MIN_VERSION 5
-#define ENC_REV_VERSION 2
-
-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)
- };
-
-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 (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 (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 (2 * 16 * BPS)
-#define C8TM8 (C8DC8 + 1 * 16)
-#define C8VE8 (2 * 16 * BPS + 8 * BPS)
-#define C8HE8 (C8VE8 + 1 * 16)
-// intra 4x4
-#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(uint32_t n, uint32_t iQ, uint32_t B) {
- return (int)((n * iQ + B) >> QFIX);
-}
-
-// Uncomment the following to remove token-buffer code:
-// #define DISABLE_TOKEN_BUFFER
-
-//------------------------------------------------------------------------------
-// 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 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;
-
-// 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
-} 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]; // 1056 bytes
- StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes
- 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
-} VP8EncProba;
-
-// 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
-} VP8EncFilterHeader;
-
-//------------------------------------------------------------------------------
-// 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.
- 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;
-
-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
- 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_;
-
- // lambda values for distortion-based evaluation
- score_t i4_penalty_; // penalty for using Intra4
-} VP8SegmentInfo;
-
-// Handy transient struct to accumulate score and info during RD-optimization
-// and mode evaluation.
-typedef struct {
- 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];
- 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_stride_, uv_stride_; // respective strides
- 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
- 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 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
-void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it);
-// restart a scan
-void VP8IteratorReset(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 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);
-// 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
-
-typedef struct VP8Tokens VP8Tokens; // struct details in token.c
-
-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;
-
-// initialize an empty buffer
-void VP8TBufferInit(VP8TBuffer* const b, int page_size);
-void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory
-
-#if !defined(DISABLE_TOKEN_BUFFER)
-
-// 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);
-
-// record the coding of coefficients without knowing the probabilities yet
-int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res,
- VP8TBuffer* const tokens);
-
-// Estimate the final coded size given a set of 'probas'.
-size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas);
-
-// unused for now
-void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats);
-
-#endif // !DISABLE_TOKEN_BUFFER
-
-//------------------------------------------------------------------------------
-// VP8Encoder
-
-struct VP8Encoder {
- const WebPConfig* config_; // user configuration and parameters
- WebPPicture* pic_; // input / output picture
-
- // headers
- VP8EncFilterHeader filter_hdr_; // filtering information
- VP8EncSegmentHeader 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
- VP8TBuffer tokens_; // token buffer
-
- int percent_; // for progress
-
- // transparency blob
- int has_alpha_;
- uint8_t* alpha_data_; // non-NULL if transparency is present
- uint32_t alpha_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_;
- int dq_y2_dc_, dq_y2_ac_;
- int dq_uv_dc_, dq_uv_ac_;
-
- // probabilities and statistics
- 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.
- VP8RDLevel rd_opt_level_; // Deduced from method_.
- int max_i4_header_bits_; // partition #0 safeness factor
- int mb_header_limit_; // rough limit for header bits per MB
- 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* 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)
-};
-
-//------------------------------------------------------------------------------
-// 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 VP8EncProba* 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 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
-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 coding calls
-int VP8EncLoop(VP8Encoder* const enc);
-int VP8EncTokenLoop(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,
- 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
-int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data
-
- // in filter.c
-void VP8SSIMAddStats(const VP8DistoStats* const src, VP8DistoStats* const dst);
-void VP8SSIMAccumulatePlane(const uint8_t* src1, int stride1,
- const uint8_t* src2, int stride2,
- int W, int H, VP8DistoStats* const stats);
-double VP8SSIMGet(const VP8DistoStats* const stats);
-double VP8SSIMGetSquaredError(const VP8DistoStats* const stats);
-
-// autofilter
-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);
-
-// Clean-up the RGB samples under fully transparent area, to help lossless
-// compressibility (no guarantee, though). Assumes that pic->use_argb is true.
-void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
-
- // 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);
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_ENC_VP8ENCI_H_ */
diff --git a/thirdparty/libwebp/enc/vp8i_enc.h b/thirdparty/libwebp/enc/vp8i_enc.h
new file mode 100644
index 0000000000..93c95ecbfb
--- /dev/null
+++ b/thirdparty/libwebp/enc/vp8i_enc.h
@@ -0,0 +1,520 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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 "../dec/common_dec.h"
+#include "../dsp/dsp.h"
+#include "../utils/bit_writer_utils.h"
+#include "../utils/thread_utils.h"
+#include "../utils/utils.h"
+#include "../webp/encode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------
+// Various defines and enums
+
+// version numbers
+#define ENC_MAJ_VERSION 0
+#define ENC_MIN_VERSION 6
+#define ENC_REV_VERSION 0
+
+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)
+ };
+
+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 (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 (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 (2 * 16 * BPS)
+#define C8TM8 (C8DC8 + 1 * 16)
+#define C8VE8 (2 * 16 * BPS + 8 * BPS)
+#define C8HE8 (C8VE8 + 1 * 16)
+// intra 4x4
+#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(uint32_t n, uint32_t iQ, uint32_t B) {
+ return (int)((n * iQ + B) >> QFIX);
+}
+
+// Uncomment the following to remove token-buffer code:
+// #define DISABLE_TOKEN_BUFFER
+
+//------------------------------------------------------------------------------
+// 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 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;
+
+// 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
+} 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]; // 1056 bytes
+ StatsArray stats_[NUM_TYPES][NUM_BANDS]; // 4224 bytes
+ 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
+} VP8EncProba;
+
+// 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
+} VP8EncFilterHeader;
+
+//------------------------------------------------------------------------------
+// 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.
+ 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;
+
+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
+ 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_;
+
+ // lambda values for distortion-based evaluation
+ score_t i4_penalty_; // penalty for using Intra4
+} VP8SegmentInfo;
+
+// Handy transient struct to accumulate score and info during RD-optimization
+// and mode evaluation.
+typedef struct {
+ 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];
+ 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
+ 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
+ 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 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
+void VP8IteratorInit(VP8Encoder* const enc, VP8EncIterator* const it);
+// restart a scan
+void VP8IteratorReset(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 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);
+// 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
+
+typedef struct VP8Tokens VP8Tokens; // struct details in token.c
+
+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;
+
+// initialize an empty buffer
+void VP8TBufferInit(VP8TBuffer* const b, int page_size);
+void VP8TBufferClear(VP8TBuffer* const b); // de-allocate pages memory
+
+#if !defined(DISABLE_TOKEN_BUFFER)
+
+// 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);
+
+// record the coding of coefficients without knowing the probabilities yet
+int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res,
+ VP8TBuffer* const tokens);
+
+// Estimate the final coded size given a set of 'probas'.
+size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas);
+
+// unused for now
+void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats);
+
+#endif // !DISABLE_TOKEN_BUFFER
+
+//------------------------------------------------------------------------------
+// VP8Encoder
+
+struct VP8Encoder {
+ const WebPConfig* config_; // user configuration and parameters
+ WebPPicture* pic_; // input / output picture
+
+ // headers
+ VP8EncFilterHeader filter_hdr_; // filtering information
+ VP8EncSegmentHeader 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
+ VP8TBuffer tokens_; // token buffer
+
+ int percent_; // for progress
+
+ // transparency blob
+ int has_alpha_;
+ uint8_t* alpha_data_; // non-NULL if transparency is present
+ uint32_t alpha_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_;
+ int dq_y2_dc_, dq_y2_ac_;
+ int dq_uv_dc_, dq_uv_ac_;
+
+ // probabilities and statistics
+ 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.
+ VP8RDLevel rd_opt_level_; // Deduced from method_.
+ int max_i4_header_bits_; // partition #0 safeness factor
+ int mb_header_limit_; // rough limit for header bits per MB
+ 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* 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)
+};
+
+//------------------------------------------------------------------------------
+// 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 VP8EncProba* 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 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
+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 coding calls
+int VP8EncLoop(VP8Encoder* const enc);
+int VP8EncTokenLoop(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,
+ 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
+int VP8EncDeleteAlpha(VP8Encoder* const enc); // delete compressed data
+
+// autofilter
+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);
+
+// Clean-up the RGB samples under fully transparent area, to help lossless
+// compressibility (no guarantee, though). Assumes that pic->use_argb is true.
+void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
+
+ // 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);
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_ENC_VP8ENCI_H_ */
diff --git a/thirdparty/libwebp/enc/vp8l.c b/thirdparty/libwebp/enc/vp8l.c
deleted file mode 100644
index e4ad2959b8..0000000000
--- a/thirdparty/libwebp/enc/vp8l.c
+++ /dev/null
@@ -1,1602 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// main entry for the lossless encoder.
-//
-// Author: Vikas Arora (vikaas.arora@gmail.com)
-//
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "./backward_references.h"
-#include "./histogram.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 "../webp/format_constants.h"
-
-#include "./delta_palettization.h"
-
-#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer.
-// Maximum number of histogram images (sub-blocks).
-#define MAX_HUFF_IMAGE_SIZE 2600
-
-// Palette reordering for smaller sum of deltas (and for smaller storage).
-
-static int PaletteCompareColorsForQsort(const void* p1, const void* p2) {
- const uint32_t a = WebPMemToUint32((uint8_t*)p1);
- const uint32_t b = WebPMemToUint32((uint8_t*)p2);
- 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) {
- const int num_colors = WebPGetColorPalette(pic, palette);
- if (num_colors > MAX_PALETTE_SIZE) return 0;
- *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,
- 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];
- int k;
- int 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 = (EntropyIx)k;
- }
- }
- *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.
- {
- 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;
- }
- }
- }
- }
- WebPSafeFree(histo);
- return 1;
- } else {
- return 0;
- }
-}
-
-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, 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 (!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 = 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->palette_code_bits_) :
- (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) 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;
- 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];
- 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:
- WebPSafeFree(huff_tree);
- WebPSafeFree(buf_rle);
- if (!ok) {
- WebPSafeFree(mem_buf);
- memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
- }
- 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;
- }
- }
- VP8LPutBits(bw, codes_to_store - 4, 4);
- for (i = 0; i < codes_to_store; ++i) {
- VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3);
- }
-}
-
-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;
- VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]);
- switch (ix) {
- case 16:
- VP8LPutBits(bw, extra_bits, 2);
- break;
- case 17:
- VP8LPutBits(bw, extra_bits, 3);
- break;
- case 18:
- VP8LPutBits(bw, extra_bits, 7);
- break;
- }
- }
-}
-
-// '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;
- huffman_code.num_symbols = CODE_LENGTH_CODES;
- huffman_code.code_lengths = code_length_bitdepth;
- huffman_code.codes = code_length_bitdepth_symbols;
-
- VP8LPutBits(bw, 0, 1);
- num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
- {
- 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];
- }
-
- VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code);
- }
-
- 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;
- 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;
- VP8LPutBits(bw, nbitpairs - 1, 3);
- assert(trimmed_length >= 2);
- VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2);
- }
- StoreHuffmanTreeToBitMask(bw, tokens, length, &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 };
- 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
- VP8LPutBits(bw, 0x01, 4);
- } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
- VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols.
- VP8LPutBits(bw, count - 1, 1);
- if (symbols[0] <= 1) {
- VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value.
- VP8LPutBits(bw, symbols[0], 1);
- } else {
- VP8LPutBits(bw, 1, 1);
- VP8LPutBits(bw, symbols[0], 8);
- }
- if (count == 2) {
- VP8LPutBits(bw, symbols[1], 8);
- }
- } else {
- StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code);
- }
-}
-
-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 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,
- 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;
- 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;
-
- const int distance = PixOrCopyDistance(v);
- VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
- WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_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);
- 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 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 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
- 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 (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- 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]);
-
- // 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.
- VP8LPutBits(bw, 0, 1);
-
- // Find maximum number of symbols for the huffman tree-set.
- for (i = 0; i < 5; ++i) {
- HuffmanTreeCode* const codes = &huffman_codes[i];
- 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.
- err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols,
- huffman_codes);
-
- Error:
- WebPSafeFree(tokens);
- WebPSafeFree(huff_tree);
- VP8LFreeHistogramSet(histogram_image);
- WebPSafeFree(huffman_codes[0].codes);
- return err;
-}
-
-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 use_cache, 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 = 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(histogram_image_xysize,
- sizeof(*histogram_symbols));
- assert(histogram_bits >= MIN_HUFFMAN_BITS);
- assert(histogram_bits <= MAX_HUFFMAN_BITS);
- 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 = use_cache ? MAX_COLOR_CACHE_BITS : 0;
- // '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 (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- 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, 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.
- histogram_image_size = histogram_image->size;
- 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.
- 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);
- VP8LPutBits(bw, write_histogram_image, 1);
- if (write_histogram_image) {
- uint32_t* const histogram_argb =
- (uint32_t*)WebPSafeMalloc(histogram_image_xysize,
- sizeof(*histogram_argb));
- int max_index = 0;
- uint32_t i;
- if (histogram_argb == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- for (i = 0; i < histogram_image_xysize; ++i) {
- 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;
-
- 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 (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);
- }
- }
-
- *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position);
- // Store actual literals.
- err = StoreImageToBitMask(bw, width, histogram_bits, &refs,
- histogram_symbols, huffman_codes);
- *data_size =
- (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size);
-
- Error:
- WebPSafeFree(tokens);
- WebPSafeFree(huff_tree);
- VP8LFreeHistogramSet(histogram_image);
- VP8LFreeHistogramSet(tmp_histos);
- VP8LBackwardRefsClear(&refs);
- if (huffman_codes != NULL) {
- WebPSafeFree(huffman_codes->codes);
- WebPSafeFree(huffman_codes);
- }
- WebPSafeFree(histogram_symbols);
- return err;
-}
-
-// -----------------------------------------------------------------------------
-// Transforms
-
-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 WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
- int width, int height,
- int quality, int low_effort,
- int used_subtract_green,
- 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);
- // we disable near-lossless quantization if palette is used.
- const int near_lossless_strength = enc->use_palette_ ? 100
- : enc->config_->near_lossless;
-
- VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_,
- enc->argb_scratch_, enc->transform_data_,
- near_lossless_strength, enc->config_->exact,
- used_subtract_green);
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
- assert(pred_bits >= 2);
- 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 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);
-
- VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality,
- enc->argb_, enc->transform_data_);
- VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
- VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2);
- assert(ccolor_transform_bits >= 2);
- 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 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);
-
- 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) {
- VP8LPutBits(bw, has_alpha, 1);
- VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS);
- 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;
-}
-
-// -----------------------------------------------------------------------------
-
-static void ClearTransformBuffer(VP8LEncoder* const enc) {
- WebPSafeFree(enc->transform_mem_);
- enc->transform_mem_ = NULL;
- enc->transform_mem_size_ = 0;
-}
-
-// 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 uint64_t image_size = width * height;
- // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra
- // pixel in each, plus 2 regular scanlines of bytes.
- // TODO(skal): Clean up by using arithmetic in bytes instead of words.
- const uint64_t argb_scratch_size =
- enc->use_predict_
- ? (width + 1) * 2 +
- (width * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t)
- : 0;
- const uint64_t transform_data_size =
- (enc->use_predict_ || enc->use_cross_color_)
- ? VP8LSubSampleSize(width, enc->transform_bits_) *
- VP8LSubSampleSize(height, enc->transform_bits_)
- : 0;
- const uint64_t max_alignment_in_words =
- (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t);
- const uint64_t mem_size =
- image_size + max_alignment_in_words +
- argb_scratch_size + max_alignment_in_words +
- transform_data_size;
- uint32_t* mem = enc->transform_mem_;
- if (mem == NULL || mem_size > enc->transform_mem_size_) {
- ClearTransformBuffer(enc);
- mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem));
- if (mem == NULL) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- enc->transform_mem_ = mem;
- enc->transform_mem_size_ = (size_t)mem_size;
- }
- 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;
- Error:
- return err;
-}
-
-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) {
- memcpy(enc->argb_ + y * width,
- picture->argb + y * picture->argb_stride,
- width * sizeof(*enc->argb_));
- }
- assert(enc->current_width_ == width);
- return VP8_ENC_OK;
-}
-
-// -----------------------------------------------------------------------------
-
-static int SearchColor(const uint32_t sorted[], uint32_t color, int hi) {
- int low = 0;
- if (sorted[low] == color) return low; // loop invariant: sorted[low] != color
- while (1) {
- const int mid = (low + hi) >> 1;
- if (sorted[mid] == color) {
- return mid;
- } else if (sorted[mid] < color) {
- low = mid;
- } else {
- hi = mid;
- }
- }
-}
-
-// Sort palette in increasing order and prepare an inverse mapping array.
-static void PrepareMapToPalette(const uint32_t palette[], int num_colors,
- uint32_t sorted[], int idx_map[]) {
- int i;
- memcpy(sorted, palette, num_colors * sizeof(*sorted));
- qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort);
- for (i = 0; i < num_colors; ++i) {
- idx_map[SearchColor(sorted, palette[i], num_colors)] = i;
- }
-}
-
-static void MapToPalette(const uint32_t sorted_palette[], int num_colors,
- uint32_t* const last_pix, int* const last_idx,
- const int idx_map[],
- 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) {
- prev_idx = idx_map[SearchColor(sorted_palette, pix, num_colors)];
- prev_pix = pix;
- }
- dst[x] = prev_idx;
- }
- *last_idx = prev_idx;
- *last_pix = prev_pix;
-}
-
-// 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 (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;
- int last_idx;
- uint32_t sorted[MAX_PALETTE_SIZE];
- int idx_map[MAX_PALETTE_SIZE];
- PrepareMapToPalette(palette, palette_size, sorted, idx_map);
- last_pix = palette[0];
- last_idx = 0;
- for (y = 0; y < height; ++y) {
- MapToPalette(sorted, palette_size, &last_pix, &last_idx,
- idx_map, src, tmp_row, width);
- VP8LBundleColorMap(tmp_row, width, xbits, dst);
- src += src_stride;
- dst += dst_stride;
- }
- }
- WebPSafeFree(tmp_row);
- return VP8_ENC_OK;
-}
-
-// 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 */);
-}
-
-#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 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);
- }
- }
-
- 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*)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) {
- if (enc != NULL) {
- VP8LHashChainClear(&enc->hash_chain_);
- VP8LBackwardRefsClear(&enc->refs_[0]);
- VP8LBackwardRefsClear(&enc->refs_[1]);
- ClearTransformBuffer(enc);
- WebPSafeFree(enc);
- }
-}
-
-// -----------------------------------------------------------------------------
-// Main call
-
-WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
- const WebPPicture* const picture,
- VP8LBitWriter* const bw, int use_cache) {
- 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;
- }
-
- // ---------------------------------------------------------------------------
- // Analyze image (entropy, num_palettes etc)
-
- if (!AnalyzeAndInit(enc)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
-
- // Apply near-lossless preprocessing.
- use_near_lossless =
- (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_;
- if (use_near_lossless) {
- if (!VP8ApplyNearLossless(width, height, picture->argb,
- config->near_lossless)) {
- err = VP8_ENC_ERROR_OUT_OF_MEMORY;
- goto Error;
- }
- }
-
-#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;
- 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;
- }
- }
-#endif // WEBP_EXPERIMENTAL_FEATURES
-
- // 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 (!use_delta_palettization) {
- // In case image is not packed.
- if (enc->argb_ == NULL) {
- err = MakeInputImageCopy(enc);
- if (err != VP8_ENC_OK) goto Error;
- }
-
- // -------------------------------------------------------------------------
- // Apply transforms and write transform data.
-
- if (enc->use_subtract_green_) {
- ApplySubtractGreen(enc, enc->current_width_, height, bw);
- }
-
- if (enc->use_predict_) {
- err = ApplyPredictFilter(enc, enc->current_width_, height, quality,
- low_effort, enc->use_subtract_green_, bw);
- if (err != VP8_ENC_OK) 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.
- err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_,
- enc->current_width_, height, quality, low_effort,
- use_cache, &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;
- 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);
- stats->lossless_hdr_size = hdr_size;
- stats->lossless_data_size = data_size;
- }
-
- 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;
- int initial_size;
- 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;
- // 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;
- }
-
- 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, 1 /*use_cache*/);
- 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;
- VP8LBitWriterWipeOut(&bw);
- if (err != VP8_ENC_OK) {
- WebPEncodingSetError(picture, err);
- return 0;
- }
- return 1;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/vp8l_enc.c b/thirdparty/libwebp/enc/vp8l_enc.c
new file mode 100644
index 0000000000..b1a793d956
--- /dev/null
+++ b/thirdparty/libwebp/enc/vp8l_enc.c
@@ -0,0 +1,1667 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// main entry for the lossless encoder.
+//
+// Author: Vikas Arora (vikaas.arora@gmail.com)
+//
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "./backward_references_enc.h"
+#include "./histogram_enc.h"
+#include "./vp8i_enc.h"
+#include "./vp8li_enc.h"
+#include "../dsp/lossless.h"
+#include "../dsp/lossless_common.h"
+#include "../utils/bit_writer_utils.h"
+#include "../utils/huffman_encode_utils.h"
+#include "../utils/utils.h"
+#include "../webp/format_constants.h"
+
+#include "./delta_palettization_enc.h"
+
+#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer.
+// Maximum number of histogram images (sub-blocks).
+#define MAX_HUFF_IMAGE_SIZE 2600
+
+// Palette reordering for smaller sum of deltas (and for smaller storage).
+
+static int PaletteCompareColorsForQsort(const void* p1, const void* p2) {
+ const uint32_t a = WebPMemToUint32((uint8_t*)p1);
+ const uint32_t b = WebPMemToUint32((uint8_t*)p2);
+ 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) {
+ const int num_colors = WebPGetColorPalette(pic, palette);
+ if (num_colors > MAX_PALETTE_SIZE) return 0;
+ *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(int p, uint32_t* const r, uint32_t* const b) {
+ const int green = p >> 8; // The upper bits are masked away later.
+ ++r[((p >> 16) - green) & 0xff];
+ ++b[((p >> 0) - green) & 0xff];
+}
+
+static void AddSingle(uint32_t p,
+ uint32_t* const a, uint32_t* const r,
+ uint32_t* const g, uint32_t* const b) {
+ ++a[(p >> 24) & 0xff];
+ ++r[(p >> 16) & 0xff];
+ ++g[(p >> 8) & 0xff];
+ ++b[(p >> 0) & 0xff];
+}
+
+static WEBP_INLINE uint32_t HashPix(uint32_t pix) {
+ // Note that masking with 0xffffffffu is for preventing an
+ // 'unsigned int overflow' warning. Doesn't impact the compiled code.
+ return ((((uint64_t)pix + (pix >> 19)) * 0x39c5fba7ull) & 0xffffffffu) >> 24;
+}
+
+static int AnalyzeEntropy(const uint32_t* argb,
+ int width, int height, int argb_stride,
+ 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 uint32_t hash = HashPix(pix);
+ ++histo[kHistoPalette * 256 + hash];
+ }
+ }
+ prev_row = curr_row;
+ curr_row += argb_stride;
+ }
+ {
+ double entropy_comp[kHistoTotal];
+ double entropy[kNumEntropyIx];
+ int k;
+ int 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 = (EntropyIx)k;
+ }
+ }
+ *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.
+ {
+ 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;
+ }
+ }
+ }
+ }
+ WebPSafeFree(histo);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+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;
+ const int res =
+ (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits;
+ assert(res <= MAX_TRANSFORM_BITS);
+ return res;
+}
+
+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, 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 (!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 = 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->palette_code_bits_) :
+ (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) 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;
+ 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];
+ 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:
+ WebPSafeFree(huff_tree);
+ WebPSafeFree(buf_rle);
+ if (!ok) {
+ WebPSafeFree(mem_buf);
+ memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
+ }
+ 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;
+ }
+ }
+ VP8LPutBits(bw, codes_to_store - 4, 4);
+ for (i = 0; i < codes_to_store; ++i) {
+ VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3);
+ }
+}
+
+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;
+ VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]);
+ switch (ix) {
+ case 16:
+ VP8LPutBits(bw, extra_bits, 2);
+ break;
+ case 17:
+ VP8LPutBits(bw, extra_bits, 3);
+ break;
+ case 18:
+ VP8LPutBits(bw, extra_bits, 7);
+ break;
+ }
+ }
+}
+
+// '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;
+ huffman_code.num_symbols = CODE_LENGTH_CODES;
+ huffman_code.code_lengths = code_length_bitdepth;
+ huffman_code.codes = code_length_bitdepth_symbols;
+
+ VP8LPutBits(bw, 0, 1);
+ num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
+ {
+ 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];
+ }
+
+ VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code);
+ }
+
+ 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;
+ 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;
+ VP8LPutBits(bw, nbitpairs - 1, 3);
+ assert(trimmed_length >= 2);
+ VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2);
+ }
+ StoreHuffmanTreeToBitMask(bw, tokens, length, &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 };
+ 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
+ VP8LPutBits(bw, 0x01, 4);
+ } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
+ VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols.
+ VP8LPutBits(bw, count - 1, 1);
+ if (symbols[0] <= 1) {
+ VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value.
+ VP8LPutBits(bw, symbols[0], 1);
+ } else {
+ VP8LPutBits(bw, 1, 1);
+ VP8LPutBits(bw, symbols[0], 8);
+ }
+ if (count == 2) {
+ VP8LPutBits(bw, symbols[1], 8);
+ }
+ } else {
+ StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code);
+ }
+}
+
+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 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,
+ 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;
+ 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;
+
+ const int distance = PixOrCopyDistance(v);
+ VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
+ WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_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);
+ 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 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 low_effort) {
+ int i;
+ 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
+ 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 (!VP8LHashChainFill(hash_chain, quality, argb, width, height,
+ low_effort)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ 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]);
+
+ // 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.
+ VP8LPutBits(bw, 0, 1);
+
+ // Find maximum number of symbols for the huffman tree-set.
+ for (i = 0; i < 5; ++i) {
+ HuffmanTreeCode* const codes = &huffman_codes[i];
+ 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.
+ err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols,
+ huffman_codes);
+
+ Error:
+ WebPSafeFree(tokens);
+ WebPSafeFree(huff_tree);
+ VP8LFreeHistogramSet(histogram_image);
+ WebPSafeFree(huffman_codes[0].codes);
+ return err;
+}
+
+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 use_cache, 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 = 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(histogram_image_xysize,
+ sizeof(*histogram_symbols));
+ assert(histogram_bits >= MIN_HUFFMAN_BITS);
+ assert(histogram_bits <= MAX_HUFFMAN_BITS);
+ 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;
+ }
+
+ if (use_cache) {
+ // If the value is different from zero, it has been set during the
+ // palette analysis.
+ if (*cache_bits == 0) *cache_bits = MAX_COLOR_CACHE_BITS;
+ } else {
+ *cache_bits = 0;
+ }
+ // '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 (!VP8LHashChainFill(hash_chain, quality, argb, width, height,
+ low_effort)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ 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, 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.
+ histogram_image_size = histogram_image->size;
+ 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.
+ 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);
+ VP8LPutBits(bw, write_histogram_image, 1);
+ if (write_histogram_image) {
+ uint32_t* const histogram_argb =
+ (uint32_t*)WebPSafeMalloc(histogram_image_xysize,
+ sizeof(*histogram_argb));
+ int max_index = 0;
+ uint32_t i;
+ if (histogram_argb == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ for (i = 0; i < histogram_image_xysize; ++i) {
+ 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;
+
+ VP8LPutBits(bw, histogram_bits - 2, 3);
+ err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array,
+ VP8LSubSampleSize(width, histogram_bits),
+ VP8LSubSampleSize(height, histogram_bits),
+ quality, low_effort);
+ 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 (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);
+ }
+ }
+
+ *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position);
+ // Store actual literals.
+ err = StoreImageToBitMask(bw, width, histogram_bits, &refs,
+ histogram_symbols, huffman_codes);
+ *data_size =
+ (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size);
+
+ Error:
+ WebPSafeFree(tokens);
+ WebPSafeFree(huff_tree);
+ VP8LFreeHistogramSet(histogram_image);
+ VP8LFreeHistogramSet(tmp_histos);
+ VP8LBackwardRefsClear(&refs);
+ if (huffman_codes != NULL) {
+ WebPSafeFree(huffman_codes->codes);
+ WebPSafeFree(huffman_codes);
+ }
+ WebPSafeFree(histogram_symbols);
+ return err;
+}
+
+// -----------------------------------------------------------------------------
+// Transforms
+
+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 WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
+ int width, int height,
+ int quality, int low_effort,
+ int used_subtract_green,
+ 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);
+ // we disable near-lossless quantization if palette is used.
+ const int near_lossless_strength = enc->use_palette_ ? 100
+ : enc->config_->near_lossless;
+
+ VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_,
+ enc->argb_scratch_, enc->transform_data_,
+ near_lossless_strength, enc->config_->exact,
+ used_subtract_green);
+ VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
+ VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
+ assert(pred_bits >= 2);
+ 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, low_effort);
+}
+
+static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc,
+ int width, int height,
+ int quality, int low_effort,
+ 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);
+
+ VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality,
+ enc->argb_, enc->transform_data_);
+ VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
+ VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2);
+ assert(ccolor_transform_bits >= 2);
+ 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, low_effort);
+}
+
+// -----------------------------------------------------------------------------
+
+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);
+
+ 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) {
+ VP8LPutBits(bw, has_alpha, 1);
+ VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS);
+ 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;
+}
+
+// -----------------------------------------------------------------------------
+
+static void ClearTransformBuffer(VP8LEncoder* const enc) {
+ WebPSafeFree(enc->transform_mem_);
+ enc->transform_mem_ = NULL;
+ enc->transform_mem_size_ = 0;
+}
+
+// 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 uint64_t image_size = width * height;
+ // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra
+ // pixel in each, plus 2 regular scanlines of bytes.
+ // TODO(skal): Clean up by using arithmetic in bytes instead of words.
+ const uint64_t argb_scratch_size =
+ enc->use_predict_
+ ? (width + 1) * 2 +
+ (width * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t)
+ : 0;
+ const uint64_t transform_data_size =
+ (enc->use_predict_ || enc->use_cross_color_)
+ ? VP8LSubSampleSize(width, enc->transform_bits_) *
+ VP8LSubSampleSize(height, enc->transform_bits_)
+ : 0;
+ const uint64_t max_alignment_in_words =
+ (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t);
+ const uint64_t mem_size =
+ image_size + max_alignment_in_words +
+ argb_scratch_size + max_alignment_in_words +
+ transform_data_size;
+ uint32_t* mem = enc->transform_mem_;
+ if (mem == NULL || mem_size > enc->transform_mem_size_) {
+ ClearTransformBuffer(enc);
+ mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem));
+ if (mem == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ enc->transform_mem_ = mem;
+ enc->transform_mem_size_ = (size_t)mem_size;
+ }
+ 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;
+ Error:
+ return err;
+}
+
+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) {
+ memcpy(enc->argb_ + y * width,
+ picture->argb + y * picture->argb_stride,
+ width * sizeof(*enc->argb_));
+ }
+ assert(enc->current_width_ == width);
+ return VP8_ENC_OK;
+}
+
+// -----------------------------------------------------------------------------
+
+static WEBP_INLINE int SearchColorNoIdx(const uint32_t sorted[], uint32_t color,
+ int hi) {
+ int low = 0;
+ if (sorted[low] == color) return low; // loop invariant: sorted[low] != color
+ while (1) {
+ const int mid = (low + hi) >> 1;
+ if (sorted[mid] == color) {
+ return mid;
+ } else if (sorted[mid] < color) {
+ low = mid;
+ } else {
+ hi = mid;
+ }
+ }
+}
+
+#define APPLY_PALETTE_GREEDY_MAX 4
+
+static WEBP_INLINE uint32_t SearchColorGreedy(const uint32_t palette[],
+ int palette_size,
+ uint32_t color) {
+ (void)palette_size;
+ assert(palette_size < APPLY_PALETTE_GREEDY_MAX);
+ assert(3 == APPLY_PALETTE_GREEDY_MAX - 1);
+ if (color == palette[0]) return 0;
+ if (color == palette[1]) return 1;
+ if (color == palette[2]) return 2;
+ return 3;
+}
+
+static WEBP_INLINE uint32_t ApplyPaletteHash0(uint32_t color) {
+ // Focus on the green color.
+ return (color >> 8) & 0xff;
+}
+
+#define PALETTE_INV_SIZE_BITS 11
+#define PALETTE_INV_SIZE (1 << PALETTE_INV_SIZE_BITS)
+
+static WEBP_INLINE uint32_t ApplyPaletteHash1(uint32_t color) {
+ // Forget about alpha.
+ return ((color & 0x00ffffffu) * 4222244071u) >> (32 - PALETTE_INV_SIZE_BITS);
+}
+
+static WEBP_INLINE uint32_t ApplyPaletteHash2(uint32_t color) {
+ // Forget about alpha.
+ return (color & 0x00ffffffu) * ((1u << 31) - 1) >>
+ (32 - PALETTE_INV_SIZE_BITS);
+}
+
+// Sort palette in increasing order and prepare an inverse mapping array.
+static void PrepareMapToPalette(const uint32_t palette[], int num_colors,
+ uint32_t sorted[], uint32_t idx_map[]) {
+ int i;
+ memcpy(sorted, palette, num_colors * sizeof(*sorted));
+ qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort);
+ for (i = 0; i < num_colors; ++i) {
+ idx_map[SearchColorNoIdx(sorted, palette[i], num_colors)] = i;
+ }
+}
+
+// Use 1 pixel cache for ARGB pixels.
+#define APPLY_PALETTE_FOR(COLOR_INDEX) do { \
+ uint32_t prev_pix = palette[0]; \
+ uint32_t prev_idx = 0; \
+ for (y = 0; y < height; ++y) { \
+ for (x = 0; x < width; ++x) { \
+ const uint32_t pix = src[x]; \
+ if (pix != prev_pix) { \
+ prev_idx = COLOR_INDEX; \
+ prev_pix = pix; \
+ } \
+ tmp_row[x] = prev_idx; \
+ } \
+ VP8LBundleColorMap(tmp_row, width, xbits, dst); \
+ src += src_stride; \
+ dst += dst_stride; \
+ } \
+} while (0)
+
+// 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 x, y;
+
+ if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
+
+ if (palette_size < APPLY_PALETTE_GREEDY_MAX) {
+ APPLY_PALETTE_FOR(SearchColorGreedy(palette, palette_size, pix));
+ } else {
+ int i, j;
+ uint16_t buffer[PALETTE_INV_SIZE];
+ uint32_t (*const hash_functions[])(uint32_t) = {
+ ApplyPaletteHash0, ApplyPaletteHash1, ApplyPaletteHash2
+ };
+
+ // Try to find a perfect hash function able to go from a color to an index
+ // within 1 << PALETTE_INV_SIZE_BITS in order to build a hash map to go
+ // from color to index in palette.
+ for (i = 0; i < 3; ++i) {
+ int use_LUT = 1;
+ // Set each element in buffer to max uint16_t.
+ memset(buffer, 0xff, sizeof(buffer));
+ for (j = 0; j < palette_size; ++j) {
+ const uint32_t ind = hash_functions[i](palette[j]);
+ if (buffer[ind] != 0xffffu) {
+ use_LUT = 0;
+ break;
+ } else {
+ buffer[ind] = j;
+ }
+ }
+ if (use_LUT) break;
+ }
+
+ if (i == 0) {
+ APPLY_PALETTE_FOR(buffer[ApplyPaletteHash0(pix)]);
+ } else if (i == 1) {
+ APPLY_PALETTE_FOR(buffer[ApplyPaletteHash1(pix)]);
+ } else if (i == 2) {
+ APPLY_PALETTE_FOR(buffer[ApplyPaletteHash2(pix)]);
+ } else {
+ uint32_t idx_map[MAX_PALETTE_SIZE];
+ uint32_t palette_sorted[MAX_PALETTE_SIZE];
+ PrepareMapToPalette(palette, palette_size, palette_sorted, idx_map);
+ APPLY_PALETTE_FOR(
+ idx_map[SearchColorNoIdx(palette_sorted, pix, palette_size)]);
+ }
+ }
+ WebPSafeFree(tmp_row);
+ return VP8_ENC_OK;
+}
+#undef APPLY_PALETTE_FOR
+#undef PALETTE_INV_SIZE_BITS
+#undef PALETTE_INV_SIZE
+#undef APPLY_PALETTE_GREEDY_MAX
+
+// 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, int low_effort,
+ 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 */, low_effort);
+}
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+
+static WebPEncodingError EncodeDeltaPalettePredictorImage(
+ VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality,
+ int low_effort) {
+ const WebPPicture* const pic = enc->pic_;
+ const int width = pic->width;
+ const int height = pic->height;
+
+ 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);
+ }
+ }
+
+ 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, low_effort);
+ WebPSafeFree(predictors);
+ return err;
+}
+
+#endif // WEBP_EXPERIMENTAL_FEATURES
+
+// -----------------------------------------------------------------------------
+// VP8LEncoder
+
+static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
+ const WebPPicture* const picture) {
+ 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) {
+ if (enc != NULL) {
+ VP8LHashChainClear(&enc->hash_chain_);
+ VP8LBackwardRefsClear(&enc->refs_[0]);
+ VP8LBackwardRefsClear(&enc->refs_[1]);
+ ClearTransformBuffer(enc);
+ WebPSafeFree(enc);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Main call
+
+WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
+ const WebPPicture* const picture,
+ VP8LBitWriter* const bw, int use_cache) {
+ 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_palette = 0;
+
+ if (enc == NULL) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ // ---------------------------------------------------------------------------
+ // Analyze image (entropy, num_palettes etc)
+
+ if (!AnalyzeAndInit(enc)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+
+ // Apply near-lossless preprocessing.
+ use_near_lossless =
+ (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_;
+ if (use_near_lossless) {
+ if (!VP8ApplyNearLossless(width, height, picture->argb,
+ config->near_lossless)) {
+ err = VP8_ENC_ERROR_OUT_OF_MEMORY;
+ goto Error;
+ }
+ }
+
+#ifdef WEBP_EXPERIMENTAL_FEATURES
+ if (config->use_delta_palette) {
+ 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;
+ 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, low_effort);
+ if (err != VP8_ENC_OK) goto Error;
+ use_delta_palette = 1;
+ }
+ }
+#endif // WEBP_EXPERIMENTAL_FEATURES
+
+ // Encode palette
+ if (enc->use_palette_) {
+ err = EncodePalette(bw, low_effort, enc);
+ if (err != VP8_ENC_OK) goto Error;
+ err = MapImageFromPalette(enc, use_delta_palette);
+ if (err != VP8_ENC_OK) goto Error;
+ // If using a color cache, do not have it bigger than the number of colors.
+ if (use_cache && enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) {
+ enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1;
+ }
+ }
+ if (!use_delta_palette) {
+ // In case image is not packed.
+ if (enc->argb_ == NULL) {
+ err = MakeInputImageCopy(enc);
+ if (err != VP8_ENC_OK) goto Error;
+ }
+
+ // -------------------------------------------------------------------------
+ // Apply transforms and write transform data.
+
+ if (enc->use_subtract_green_) {
+ ApplySubtractGreen(enc, enc->current_width_, height, bw);
+ }
+
+ if (enc->use_predict_) {
+ err = ApplyPredictFilter(enc, enc->current_width_, height, quality,
+ low_effort, enc->use_subtract_green_, bw);
+ if (err != VP8_ENC_OK) goto Error;
+ }
+
+ if (enc->use_cross_color_) {
+ err = ApplyCrossColorFilter(enc, enc->current_width_,
+ height, quality, low_effort, bw);
+ if (err != VP8_ENC_OK) goto Error;
+ }
+ }
+
+ VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms.
+
+ // ---------------------------------------------------------------------------
+ // Encode and write the transformed image.
+ err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_,
+ enc->current_width_, height, quality, low_effort,
+ use_cache, &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;
+ 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);
+ stats->lossless_hdr_size = hdr_size;
+ stats->lossless_data_size = data_size;
+ }
+
+ 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;
+ int initial_size;
+ 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;
+ // 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;
+ }
+
+ 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, 1 /*use_cache*/);
+ 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;
+ VP8LBitWriterWipeOut(&bw);
+ if (err != VP8_ENC_OK) {
+ WebPEncodingSetError(picture, err);
+ return 0;
+ }
+ return 1;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/enc/vp8li.h b/thirdparty/libwebp/enc/vp8li.h
deleted file mode 100644
index 371e276ee0..0000000000
--- a/thirdparty/libwebp/enc/vp8li.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Lossless encoder: internal header.
-//
-// Author: Vikas Arora (vikaas.arora@gmail.com)
-
-#ifndef WEBP_ENC_VP8LI_H_
-#define WEBP_ENC_VP8LI_H_
-
-#include "./backward_references.h"
-#include "./histogram.h"
-#include "../utils/bit_writer.h"
-#include "../webp/encode.h"
-#include "../webp/format_constants.h"
-
-#ifdef __cplusplus
-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.
- uint32_t* transform_mem_; // Currently allocated memory.
- size_t transform_mem_size_; // Currently allocated memory size.
-
- 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];
-
- // 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;
-
-//------------------------------------------------------------------------------
-// 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.
-// If 'use_cache' is false, disables the use of color cache.
-WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
- const WebPPicture* const picture,
- VP8LBitWriter* const bw, int use_cache);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_ENC_VP8LI_H_ */
diff --git a/thirdparty/libwebp/enc/vp8li_enc.h b/thirdparty/libwebp/enc/vp8li_enc.h
new file mode 100644
index 0000000000..8c5fbcbb2e
--- /dev/null
+++ b/thirdparty/libwebp/enc/vp8li_enc.h
@@ -0,0 +1,95 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Lossless encoder: internal header.
+//
+// Author: Vikas Arora (vikaas.arora@gmail.com)
+
+#ifndef WEBP_ENC_VP8LI_H_
+#define WEBP_ENC_VP8LI_H_
+
+#include "./backward_references_enc.h"
+#include "./histogram_enc.h"
+#include "../utils/bit_writer_utils.h"
+#include "../webp/encode.h"
+#include "../webp/format_constants.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// maximum value of transform_bits_ in VP8LEncoder.
+#define MAX_TRANSFORM_BITS 6
+
+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.
+ uint32_t* transform_mem_; // Currently allocated memory.
+ size_t transform_mem_size_; // Currently allocated memory size.
+
+ int current_width_; // Corresponds to packed image width.
+
+ // Encoding parameters derived from quality parameter.
+ int histo_bits_;
+ int transform_bits_; // <= MAX_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];
+
+ // 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;
+
+//------------------------------------------------------------------------------
+// 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.
+// If 'use_cache' is false, disables the use of color cache.
+WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
+ const WebPPicture* const picture,
+ VP8LBitWriter* const bw, int use_cache);
+
+//------------------------------------------------------------------------------
+// Image transforms in predictor.c.
+
+void VP8LResidualImage(int width, int height, int bits, int low_effort,
+ uint32_t* const argb, uint32_t* const argb_scratch,
+ uint32_t* const image, int near_lossless, int exact,
+ int used_subtract_green);
+
+void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
+ uint32_t* const argb, uint32_t* image);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_ENC_VP8LI_H_ */
diff --git a/thirdparty/libwebp/enc/webp_enc.c b/thirdparty/libwebp/enc/webp_enc.c
new file mode 100644
index 0000000000..f18461ef92
--- /dev/null
+++ b/thirdparty/libwebp/enc/webp_enc.c
@@ -0,0 +1,398 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// WebP encoder: main entry point
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "./cost_enc.h"
+#include "./vp8i_enc.h"
+#include "./vp8li_enc.h"
+#include "../utils/utils.h"
+
+// #define PRINT_MEMORY_INFO
+
+#ifdef PRINT_MEMORY_INFO
+#include <stdio.h>
+#endif
+
+//------------------------------------------------------------------------------
+
+int WebPGetEncoderVersion(void) {
+ return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION;
+}
+
+//------------------------------------------------------------------------------
+// VP8Encoder
+//------------------------------------------------------------------------------
+
+static void ResetSegmentHeader(VP8Encoder* const enc) {
+ 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) {
+ VP8EncFilterHeader* 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
+}
+
+// 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 | x | x |
+//-------------------+---+---+---+---+---+---+---+
+// basic rd-opt | | | | x | x | x | x |
+//-------------------+---+---+---+---+---+---+---+
+// disto-refine i4/16| x | x | x | | | | |
+//-------------------+---+---+---+---+---+---+---+
+// disto-refine uv | | x | 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 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) ? 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.
+
+ // partition0 = 512k max.
+ enc->mb_header_limit_ =
+ (score_t)256 * 510 * 8 * 1024 / (enc->mb_w_ * enc->mb_h_);
+
+ 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 (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): 419328
+
+static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
+ WebPPicture* const picture) {
+ VP8Encoder* enc;
+ 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(*enc->preds_);
+ const int top_stride = mb_w * 16;
+ const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST;
+ const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_);
+ const size_t samples_size =
+ 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v
+ + WEBP_ALIGN_CST; // align all
+ const size_t lf_stats_size =
+ config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0;
+ uint8_t* mem;
+ const uint64_t size = (uint64_t)sizeof(*enc) // main struct
+ + WEBP_ALIGN_CST // cache alignment
+ + 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"
+ " info: %ld\n"
+ " preds: %ld\n"
+ " top samples: %ld\n"
+ " non-zero: %ld\n"
+ " lf-stats: %ld\n"
+ " total: %ld\n",
+ sizeof(*enc) + WEBP_ALIGN_CST, info_size,
+ preds_size, samples_size, nz_size, lf_stats_size, size);
+ printf("Transient object sizes:\n"
+ " VP8EncIterator: %ld\n"
+ " VP8ModeScore: %ld\n"
+ " VP8SegmentInfo: %ld\n"
+ " VP8EncProba: %ld\n"
+ " LFStats: %ld\n",
+ sizeof(VP8EncIterator), sizeof(VP8ModeScore),
+ sizeof(VP8SegmentInfo), sizeof(VP8EncProba),
+ 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*)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->mb_info_ = (VP8MBInfo*)mem;
+ mem += info_size;
+ enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_;
+ mem += preds_size;
+ enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem);
+ mem += nz_size;
+ enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL;
+ mem += lf_stats_size;
+
+ // top samples (all 16-aligned)
+ mem = (uint8_t*)WEBP_ALIGN(mem);
+ enc->y_top_ = (uint8_t*)mem;
+ enc->uv_top_ = enc->y_top_ + top_stride;
+ mem += 2 * top_stride;
+ assert(mem <= (uint8_t*)enc + size);
+
+ 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);
+ VP8EncDspCostInit();
+ VP8EncInitAlpha(enc);
+
+ // 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 int DeleteVP8Encoder(VP8Encoder* enc) {
+ int ok = 1;
+ if (enc != NULL) {
+ ok = VP8EncDeleteAlpha(enc);
+ VP8TBufferClear(&enc->tokens_);
+ WebPSafeFree(enc);
+ }
+ return ok;
+}
+
+//------------------------------------------------------------------------------
+
+static double GetPSNR(uint64_t err, uint64_t size) {
+ return (err > 0 && size > 0) ? 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 = 0;
+ 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 (!config->exact) {
+ WebPCleanupTransparentArea(pic);
+ }
+
+ if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) {
+ // Make sure we have YUVA samples.
+ if (config->use_sharp_yuv || (config->preprocessing & 4)) {
+ if (!WebPPictureSharpARGBToYUVA(pic)) {
+ return 0;
+ }
+ } else {
+ 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);
+
+ // 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);
+ }
+ ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok
+ } else {
+ // Make sure we have ARGB samples.
+ if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) {
+ return 0;
+ }
+
+ if (!config->exact) {
+ WebPCleanupTransparentAreaLossless(pic);
+ }
+
+ ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
+ }
+
+ return ok;
+}
diff --git a/thirdparty/libwebp/enc/webpenc.c b/thirdparty/libwebp/enc/webpenc.c
deleted file mode 100644
index a7d04ea2ce..0000000000
--- a/thirdparty/libwebp/enc/webpenc.c
+++ /dev/null
@@ -1,395 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// WebP encoder: main entry point
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "./cost.h"
-#include "./vp8enci.h"
-#include "./vp8li.h"
-#include "../utils/utils.h"
-
-// #define PRINT_MEMORY_INFO
-
-#ifdef PRINT_MEMORY_INFO
-#include <stdio.h>
-#endif
-
-//------------------------------------------------------------------------------
-
-int WebPGetEncoderVersion(void) {
- return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION;
-}
-
-//------------------------------------------------------------------------------
-// VP8Encoder
-//------------------------------------------------------------------------------
-
-static void ResetSegmentHeader(VP8Encoder* const enc) {
- 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) {
- VP8EncFilterHeader* 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
-}
-
-// 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-refine i4/16| x | x | x | | | | |
-//-------------------+---+---+---+---+---+---+---+
-// disto-refine uv | | x | 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 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) ? 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.
-
- // partition0 = 512k max.
- enc->mb_header_limit_ =
- (score_t)256 * 510 * 8 * 1024 / (enc->mb_w_ * enc->mb_h_);
-
- 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 (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): 419328
-
-static VP8Encoder* InitVP8Encoder(const WebPConfig* const config,
- WebPPicture* const picture) {
- VP8Encoder* enc;
- 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(*enc->preds_);
- const int top_stride = mb_w * 16;
- const size_t nz_size = (mb_w + 1) * sizeof(*enc->nz_) + WEBP_ALIGN_CST;
- const size_t info_size = mb_w * mb_h * sizeof(*enc->mb_info_);
- const size_t samples_size =
- 2 * top_stride * sizeof(*enc->y_top_) // top-luma/u/v
- + WEBP_ALIGN_CST; // align all
- const size_t lf_stats_size =
- config->autofilter ? sizeof(*enc->lf_stats_) + WEBP_ALIGN_CST : 0;
- uint8_t* mem;
- const uint64_t size = (uint64_t)sizeof(*enc) // main struct
- + WEBP_ALIGN_CST // cache alignment
- + 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"
- " info: %ld\n"
- " preds: %ld\n"
- " top samples: %ld\n"
- " non-zero: %ld\n"
- " lf-stats: %ld\n"
- " total: %ld\n",
- sizeof(*enc) + WEBP_ALIGN_CST, info_size,
- preds_size, samples_size, nz_size, lf_stats_size, size);
- printf("Transient object sizes:\n"
- " VP8EncIterator: %ld\n"
- " VP8ModeScore: %ld\n"
- " VP8SegmentInfo: %ld\n"
- " VP8EncProba: %ld\n"
- " LFStats: %ld\n",
- sizeof(VP8EncIterator), sizeof(VP8ModeScore),
- sizeof(VP8SegmentInfo), sizeof(VP8EncProba),
- 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*)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->mb_info_ = (VP8MBInfo*)mem;
- mem += info_size;
- enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_;
- mem += preds_size;
- enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem);
- mem += nz_size;
- enc->lf_stats_ = lf_stats_size ? (LFStats*)WEBP_ALIGN(mem) : NULL;
- mem += lf_stats_size;
-
- // top samples (all 16-aligned)
- mem = (uint8_t*)WEBP_ALIGN(mem);
- enc->y_top_ = (uint8_t*)mem;
- enc->uv_top_ = enc->y_top_ + top_stride;
- mem += 2 * top_stride;
- assert(mem <= (uint8_t*)enc + size);
-
- 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);
- VP8EncDspCostInit();
- VP8EncInitAlpha(enc);
-
- // 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 int DeleteVP8Encoder(VP8Encoder* enc) {
- int ok = 1;
- if (enc != NULL) {
- ok = VP8EncDeleteAlpha(enc);
- VP8TBufferClear(&enc->tokens_);
- WebPSafeFree(enc);
- }
- return ok;
-}
-
-//------------------------------------------------------------------------------
-
-static double GetPSNR(uint64_t err, uint64_t size) {
- return (err > 0 && size > 0) ? 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 = 0;
-
- 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 (!config->exact) {
- WebPCleanupTransparentArea(pic);
- }
-
- 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 {
- 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);
-
- // 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);
- }
- ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok
- } else {
- // Make sure we have ARGB samples.
- if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) {
- return 0;
- }
-
- if (!config->exact) {
- WebPCleanupTransparentAreaLossless(pic);
- }
-
- ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
- }
-
- return ok;
-}
diff --git a/thirdparty/libwebp/mux/anim_encode.c b/thirdparty/libwebp/mux/anim_encode.c
index 398ba8d850..6066388727 100644
--- a/thirdparty/libwebp/mux/anim_encode.c
+++ b/thirdparty/libwebp/mux/anim_encode.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h> // for abs()
+#include "../mux/animi.h"
#include "../utils/utils.h"
#include "../webp/decode.h"
#include "../webp/encode.h"
@@ -128,14 +129,13 @@ static void SanitizeEncoderOptions(WebPAnimEncoderOptions* const enc_options) {
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.
+ if (enc_options->kmax == 1) { // All frames will be key-frames.
enc_options->kmin = 0;
enc_options->kmax = 0;
return;
+ } else if (enc_options->kmax <= 0) {
+ DisableKeyframes(enc_options);
+ print_warning = 0;
}
if (enc_options->kmin >= enc_options->kmax) {
@@ -378,10 +378,10 @@ static WEBP_INLINE int PixelsAreSimilar(uint32_t src, uint32_t dst,
const int dst_g = (dst >> 8) & 0xff;
const int dst_b = (dst >> 0) & 0xff;
- return (abs(src_r * src_a - dst_r * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_g * src_a - dst_g * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_b * src_a - dst_b * dst_a) <= (max_allowed_diff * 255)) &&
- (abs(src_a - dst_a) <= max_allowed_diff);
+ return (src_a == dst_a) &&
+ (abs(src_r - dst_r) * dst_a <= (max_allowed_diff * 255)) &&
+ (abs(src_g - dst_g) * dst_a <= (max_allowed_diff * 255)) &&
+ (abs(src_b - dst_b) * dst_a <= (max_allowed_diff * 255));
}
// Returns true if 'length' number of pixels in 'src' and 'dst' are within an
@@ -586,6 +586,39 @@ static int GetSubRects(const WebPPicture* const prev_canvas,
&params->rect_lossy_, &params->sub_frame_lossy_);
}
+static WEBP_INLINE int clip(int v, int min_v, int max_v) {
+ return (v < min_v) ? min_v : (v > max_v) ? max_v : v;
+}
+
+int WebPAnimEncoderRefineRect(
+ const WebPPicture* const prev_canvas, const WebPPicture* const curr_canvas,
+ int is_lossless, float quality, int* const x_offset, int* const y_offset,
+ int* const width, int* const height) {
+ FrameRect rect;
+ const int right = clip(*x_offset + *width, 0, curr_canvas->width);
+ const int left = clip(*x_offset, 0, curr_canvas->width - 1);
+ const int bottom = clip(*y_offset + *height, 0, curr_canvas->height);
+ const int top = clip(*y_offset, 0, curr_canvas->height - 1);
+ if (prev_canvas == NULL || curr_canvas == NULL ||
+ prev_canvas->width != curr_canvas->width ||
+ prev_canvas->height != curr_canvas->height ||
+ !prev_canvas->use_argb || !curr_canvas->use_argb) {
+ return 0;
+ }
+ rect.x_offset_ = left;
+ rect.y_offset_ = top;
+ rect.width_ = clip(right - left, 0, curr_canvas->width - rect.x_offset_);
+ rect.height_ = clip(bottom - top, 0, curr_canvas->height - rect.y_offset_);
+ MinimizeChangeRectangle(prev_canvas, curr_canvas, &rect, is_lossless,
+ quality);
+ SnapToEvenOffsets(&rect);
+ *x_offset = rect.x_offset_;
+ *y_offset = rect.y_offset_;
+ *width = rect.width_;
+ *height = rect.height_;
+ return 1;
+}
+
static void DisposeFrameRectangle(int dispose_method,
const FrameRect* const rect,
WebPPicture* const curr_canvas) {
diff --git a/thirdparty/libwebp/mux/animi.h b/thirdparty/libwebp/mux/animi.h
new file mode 100644
index 0000000000..cecaf1fee5
--- /dev/null
+++ b/thirdparty/libwebp/mux/animi.h
@@ -0,0 +1,43 @@
+// Copyright 2016 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.
+// -----------------------------------------------------------------------------
+//
+// Internal header for animation related functions.
+//
+// Author: Hui Su (huisu@google.com)
+
+#ifndef WEBP_MUX_ANIMI_H_
+#define WEBP_MUX_ANIMI_H_
+
+#include "../webp/mux.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Picks the optimal rectangle between two pictures, starting with initial
+// values of offsets and dimensions that are passed in. The initial
+// values will be clipped, if necessary, to make sure the rectangle is
+// within the canvas. "use_argb" must be true for both pictures.
+// Parameters:
+// prev_canvas, curr_canvas - (in) two input pictures to compare.
+// is_lossless, quality - (in) encoding settings.
+// x_offset, y_offset, width, height - (in/out) rectangle between the two
+// input pictures.
+// Returns true on success.
+int WebPAnimEncoderRefineRect(
+ const struct WebPPicture* const prev_canvas,
+ const struct WebPPicture* const curr_canvas,
+ int is_lossless, float quality, int* const x_offset, int* const y_offset,
+ int* const width, int* const height);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_MUX_ANIMI_H_ */
diff --git a/thirdparty/libwebp/mux/muxedit.c b/thirdparty/libwebp/mux/muxedit.c
index 9bbed42b1a..d2c5305372 100644
--- a/thirdparty/libwebp/mux/muxedit.c
+++ b/thirdparty/libwebp/mux/muxedit.c
@@ -93,34 +93,32 @@ static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
}
#undef SWITCH_ID_LIST
-// 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 given image data, offsets and duration.
+static WebPMuxError CreateFrameData(
+ int width, int height, const WebPMuxFrameInfo* const info,
+ WebPData* const frame) {
+ uint8_t* frame_bytes;
+ const size_t frame_size = kChunks[IDX_ANMF].size;
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_frgm_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_frgm_size);
- if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
+ frame_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_size);
+ if (frame_bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
- PutLE24(frame_frgm_bytes + 0, info->x_offset / 2);
- PutLE24(frame_frgm_bytes + 3, info->y_offset / 2);
+ PutLE24(frame_bytes + 0, info->x_offset / 2);
+ PutLE24(frame_bytes + 3, info->y_offset / 2);
- if (is_frame) {
- 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);
- }
+ PutLE24(frame_bytes + 6, width - 1);
+ PutLE24(frame_bytes + 9, height - 1);
+ PutLE24(frame_bytes + 12, info->duration);
+ frame_bytes[15] =
+ (info->blend_method == WEBP_MUX_NO_BLEND ? 2 : 0) |
+ (info->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? 1 : 0);
- frame_frgm->bytes = frame_frgm_bytes;
- frame_frgm->size = frame_frgm_size;
+ frame->bytes = frame_bytes;
+ frame->size = frame_size;
return WEBP_MUX_OK;
}
@@ -264,23 +262,16 @@ WebPMuxError WebPMuxSetImage(WebPMux* mux, const WebPData* bitstream,
return err;
}
-WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
+WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
int copy_data) {
WebPMuxImage wpi;
WebPMuxError err;
- int is_frame;
- const WebPData* const bitstream = &frame->bitstream;
+ const WebPData* const bitstream = &info->bitstream;
// Sanity checks.
- if (mux == NULL || frame == NULL) return WEBP_MUX_INVALID_ARGUMENT;
+ if (mux == NULL || info == 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 (frame->id == WEBP_CHUNK_FRGM) { // Dead experiment.
- return WEBP_MUX_INVALID_ARGUMENT;
- }
+ if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT;
if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
@@ -290,7 +281,7 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
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) {
+ if (image_id != info->id) {
return WEBP_MUX_INVALID_ARGUMENT; // Conflicting frame types.
}
}
@@ -301,16 +292,11 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
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;
+ WebPData frame;
+ const uint32_t tag = kChunks[IDX_ANMF].tag;
+ WebPMuxFrameInfo tmp = *info;
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) ||
@@ -318,12 +304,11 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* frame,
err = WEBP_MUX_INVALID_ARGUMENT;
goto Err;
}
- err = CreateFrameFragmentData(wpi.width_, wpi.height_, &tmp, is_frame,
- &frame_frgm);
+ err = CreateFrameData(wpi.width_, wpi.height_, &tmp, &frame);
if (err != WEBP_MUX_OK) goto Err;
- // 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.
+ // Add frame chunk (with copy_data = 1).
+ err = AddDataToChunkList(&frame, 1, tag, &wpi.header_);
+ WebPDataClear(&frame); // frame owned by wpi.header_ now.
if (err != WEBP_MUX_OK) goto Err;
}
@@ -402,21 +387,18 @@ WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth) {
//------------------------------------------------------------------------------
// Assembly of the WebP RIFF file.
-static WebPMuxError GetFrameFragmentInfo(
- const WebPChunk* const frame_frgm_chunk,
+static WebPMuxError GetFrameInfo(
+ const WebPChunk* const frame_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 ? ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
- assert(frame_frgm_chunk != NULL);
- assert(tag == kChunks[IDX_ANMF].tag || tag == kChunks[IDX_FRGM].tag);
+ const WebPData* const data = &frame_chunk->data_;
+ const size_t expected_data_size = ANMF_CHUNK_SIZE;
+ assert(frame_chunk->tag_ == kChunks[IDX_ANMF].tag);
+ assert(frame_chunk != NULL);
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);
+ *duration = GetLE24(data->bytes + 12);
return WEBP_MUX_OK;
}
@@ -424,13 +406,13 @@ 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 frame_frgm_chunk = wpi->header_;
+ const WebPChunk* const frame_chunk = wpi->header_;
WebPMuxError err;
assert(wpi != NULL);
- assert(frame_frgm_chunk != NULL);
+ assert(frame_chunk != NULL);
- // Get offsets and duration from ANMF/FRGM chunk.
- err = GetFrameFragmentInfo(frame_frgm_chunk, x_offset, y_offset, duration);
+ // Get offsets and duration from ANMF chunk.
+ err = GetFrameInfo(frame_chunk, x_offset, y_offset, duration);
if (err != WEBP_MUX_OK) return err;
// Get width and height from VP8/VP8L chunk.
@@ -441,7 +423,6 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi,
// 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);
@@ -452,12 +433,10 @@ static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
assert(wpi->img_ != NULL);
if (wpi->next_ != NULL) {
- int max_x = 0;
- int max_y = 0;
- int64_t image_area = 0;
+ int max_x = 0, max_y = 0;
// 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.
+ // Aggregate the bounding box for animation frames.
for (; wpi != NULL; wpi = wpi->next_) {
int x_offset = 0, y_offset = 0, duration = 0, w = 0, h = 0;
const WebPMuxError err = GetImageInfo(wpi, &x_offset, &y_offset,
@@ -470,19 +449,9 @@ static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux,
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
- // 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, canvas dimensions are same as image dimensions.
*width = wpi->width_;
@@ -528,10 +497,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
flags |= XMP_FLAG;
}
if (images->header_ != NULL) {
- 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) {
+ if (images->header_->tag_ == kChunks[IDX_ANMF].tag) {
// This is an image with animation.
flags |= ANIMATION_FLAG;
}
@@ -540,7 +506,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
flags |= ALPHA_FLAG; // Some images have an alpha channel.
}
- err = GetAdjustedCanvasSize(mux, flags, &width, &height);
+ err = GetAdjustedCanvasSize(mux, &width, &height);
if (err != WEBP_MUX_OK) return err;
if (width <= 0 || height <= 0) {
@@ -580,31 +546,26 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
// 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).
+ // If we have an image with a single frame, and its rectangle
+ // covers the whole canvas, convert it to a non-animated image
+ // (to avoid writing 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 &&
+ if (num_frames == 1) {
+ WebPMuxImage* frame = NULL;
+ err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame);
+ assert(err == WEBP_MUX_OK); // We know that one frame does exist.
+ assert(frame != NULL);
+ if (frame->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;
+ (frame->width_ == mux->canvas_width_ &&
+ frame->height_ == mux->canvas_height_))) {
+ assert(frame->header_->tag_ == kChunks[IDX_ANMF].tag);
+ ChunkDelete(frame->header_); // Removes ANMF chunk.
+ frame->header_ = NULL;
num_frames = 0;
- num_fragments = 0;
}
}
// Remove ANIM chunk if this is a non-animated image.
diff --git a/thirdparty/libwebp/mux/muxi.h b/thirdparty/libwebp/mux/muxi.h
index b4865fe36f..e6606aa5d1 100644
--- a/thirdparty/libwebp/mux/muxi.h
+++ b/thirdparty/libwebp/mux/muxi.h
@@ -15,8 +15,8 @@
#define WEBP_MUX_MUXI_H_
#include <stdlib.h>
-#include "../dec/vp8i.h"
-#include "../dec/vp8li.h"
+#include "../dec/vp8i_dec.h"
+#include "../dec/vp8li_dec.h"
#include "../webp/mux.h"
#ifdef __cplusplus
@@ -27,8 +27,8 @@ extern "C" {
// Defines and constants.
#define MUX_MAJ_VERSION 0
-#define MUX_MIN_VERSION 3
-#define MUX_REV_VERSION 2
+#define MUX_MIN_VERSION 4
+#define MUX_REV_VERSION 0
// Chunk object.
typedef struct WebPChunk WebPChunk;
@@ -36,16 +36,16 @@ struct WebPChunk {
uint32_t tag_;
int owner_; // True if *data_ memory is owned internally.
// VP8X, ANIM, and other internally created chunks
- // like ANMF/FRGM are always owned.
+ // like ANMF are always owned.
WebPData data_;
WebPChunk* next_;
};
-// MuxImage object. Store a full WebP image (including ANMF/FRGM chunk, ALPH
+// MuxImage object. Store a full WebP image (including ANMF chunk, ALPH
// chunk and VP8/VP8L chunk),
typedef struct WebPMuxImage WebPMuxImage;
struct WebPMuxImage {
- WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF/WEBP_CHUNK_FRGM.
+ WebPChunk* header_; // Corresponds to WEBP_CHUNK_ANMF.
WebPChunk* alpha_; // Corresponds to WEBP_CHUNK_ALPHA.
WebPChunk* img_; // Corresponds to WEBP_CHUNK_IMAGE.
WebPChunk* unknown_; // Corresponds to WEBP_CHUNK_UNKNOWN.
@@ -79,7 +79,6 @@ typedef enum {
IDX_ICCP,
IDX_ANIM,
IDX_ANMF,
- IDX_FRGM,
IDX_ALPHA,
IDX_VP8,
IDX_VP8L,
@@ -185,7 +184,6 @@ int MuxImageFinalize(WebPMuxImage* const wpi);
static WEBP_INLINE int IsWPI(WebPChunkId id) {
switch (id) {
case WEBP_CHUNK_ANMF:
- case WEBP_CHUNK_FRGM:
case WEBP_CHUNK_ALPHA:
case WEBP_CHUNK_IMAGE: return 1;
default: return 0;
diff --git a/thirdparty/libwebp/mux/muxinternal.c b/thirdparty/libwebp/mux/muxinternal.c
index 372c6a9674..387b57e8fe 100644
--- a/thirdparty/libwebp/mux/muxinternal.c
+++ b/thirdparty/libwebp/mux/muxinternal.c
@@ -23,7 +23,6 @@ const ChunkInfo kChunks[] = {
{ MKFOURCC('I', 'C', 'C', 'P'), WEBP_CHUNK_ICCP, UNDEFINED_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 },
@@ -251,8 +250,7 @@ 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_ANMF: return (WebPChunk**)&wpi->header_;
case WEBP_CHUNK_ALPHA: return (WebPChunk**)&wpi->alpha_;
case WEBP_CHUNK_IMAGE: return (WebPChunk**)&wpi->img_;
default: return NULL;
@@ -372,13 +370,12 @@ size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
return size;
}
-// Special case as ANMF/FRGM chunk encapsulates other image chunks.
+// Special case as ANMF 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);
+ assert(header->tag_ == kChunks[IDX_ANMF].tag);
PutLE32(dst + 0, header->tag_);
PutLE32(dst + TAG_SIZE, (uint32_t)offset_to_next);
assert(header_size == (uint32_t)header_size);
@@ -391,7 +388,7 @@ static uint8_t* ChunkEmitSpecial(const WebPChunk* const header,
uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
// Ordering of chunks to be emitted is strictly as follows:
- // 1. ANMF/FRGM chunk (if present).
+ // 1. ANMF chunk (if present).
// 2. ALPH chunk (if present).
// 3. VP8/VP8L chunk.
assert(wpi);
@@ -465,7 +462,6 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
int num_xmp;
int num_anim;
int num_frames;
- int num_fragments;
int num_vp8x;
int num_images;
int num_alpha;
@@ -510,10 +506,6 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
}
}
- // 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
// mux->images_.
err = ValidateChunk(mux, IDX_VP8X, NO_FLAG, flags, 1, &num_vp8x);
@@ -537,11 +529,6 @@ WebPMuxError MuxValidate(const WebPMux* const mux) {
if (flags & ALPHA_FLAG) return WEBP_MUX_INVALID_ARGUMENT;
}
- // num_fragments & num_images are consistent.
- if (num_fragments > 0 && num_images != num_fragments) {
- return WEBP_MUX_INVALID_ARGUMENT;
- }
-
return WEBP_MUX_OK;
}
diff --git a/thirdparty/libwebp/mux/muxread.c b/thirdparty/libwebp/mux/muxread.c
index 8957a1e46e..410acd9119 100644
--- a/thirdparty/libwebp/mux/muxread.c
+++ b/thirdparty/libwebp/mux/muxread.c
@@ -104,17 +104,15 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
size_t subchunk_size;
ChunkInit(&subchunk);
- assert(chunk->tag_ == kChunks[IDX_ANMF].tag ||
- chunk->tag_ == kChunks[IDX_FRGM].tag);
+ assert(chunk->tag_ == kChunks[IDX_ANMF].tag);
assert(!wpi->is_partial_);
- // ANMF/FRGM.
+ // ANMF.
{
- const size_t hdr_size = (chunk->tag_ == kChunks[IDX_ANMF].tag) ?
- ANMF_CHUNK_SIZE : FRGM_CHUNK_SIZE;
+ const size_t hdr_size = ANMF_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'.
+ // Each of ANMF chunk contain a header at the beginning. So, its size should
+ // be at least 'hdr_size'.
if (size < hdr_size) goto Fail;
ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
}
@@ -292,16 +290,15 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
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) {
+ } else if (num_images == 1 && num_frames == 0) {
// Valid case (single image).
return WEBP_MUX_OK;
} else {
- // Frame/Fragment case OR an invalid mux.
+ // Frame case OR an invalid mux.
return WEBP_MUX_INVALID_ARGUMENT;
}
}
@@ -379,7 +376,7 @@ static WebPMuxError SynthesizeBitstream(const 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 ANMF/FRGM chunk for a single image.
+ // Note: No need to output ANMF 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*)WebPSafeMalloc(1ULL, size);
@@ -436,29 +433,24 @@ static WebPMuxError MuxGetImageInternal(const WebPMuxImage* const wpi,
return SynthesizeBitstream(wpi, &info->bitstream);
}
-static WebPMuxError MuxGetFrameFragmentInternal(const WebPMuxImage* const wpi,
- WebPMuxFrameInfo* const frame) {
+static WebPMuxError MuxGetFrameInternal(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;
+ const WebPData* frame_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;
+ // Get frame chunk.
+ frame_data = &wpi->header_->data_;
+ if (frame_data->size < kChunks[IDX_ANMF].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->x_offset = 2 * GetLE24(frame_data->bytes + 0);
+ frame->y_offset = 2 * GetLE24(frame_data->bytes + 3);
+ {
+ const uint8_t bits = frame_data->bytes[15];
+ frame->duration = GetLE24(frame_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);
@@ -482,7 +474,7 @@ WebPMuxError WebPMuxGetFrame(
if (wpi->header_ == NULL) {
return MuxGetImageInternal(wpi, frame);
} else {
- return MuxGetFrameFragmentInternal(wpi, frame);
+ return MuxGetFrameInternal(wpi, frame);
}
}
diff --git a/thirdparty/libwebp/utils/bit_reader.c b/thirdparty/libwebp/utils/bit_reader.c
deleted file mode 100644
index 2eb46e0b4b..0000000000
--- a/thirdparty/libwebp/utils/bit_reader.c
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright 2010 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.
-// -----------------------------------------------------------------------------
-//
-// Boolean decoder non-inlined methods
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifdef HAVE_CONFIG_H
-#include "../webp/config.h"
-#endif
-
-#include "./bit_reader_inl.h"
-#include "../utils/utils.h"
-
-//------------------------------------------------------------------------------
-// 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, size_t size) {
- assert(br != NULL);
- assert(start != NULL);
- assert(size < (1u << 31)); // limit ensured by format and upstream checks
- br->range_ = 255 - 1;
- br->value_ = 0;
- br->bits_ = -8; // to load the very first 8bits
- br->eof_ = 0;
- VP8BitReaderSetBuffer(br, start, size);
-// -- GODOT -- begin
-#ifdef JAVASCRIPT_ENABLED // html5 required aligned reads
- while(((uintptr_t)br->buf_ & 1) != 0 && !br->eof_)
- VP8LoadFinalBytes(br);
-#else
- VP8LoadNewBytes(br);
-#endif
-// -- GODOT -- end
-}
-
-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] = {
- 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
-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
-};
-
-void VP8LoadFinalBytes(VP8BitReader* const br) {
- assert(br != NULL && br->buf_ != NULL);
- // Only read 8bits at a time
- if (br->buf_ < br->buf_end_) {
- 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.
- }
-}
-
-//------------------------------------------------------------------------------
-// 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 VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.
-
-#if defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
- defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64__) || defined(_M_X64)
-#define VP8L_USE_FAST_LOAD
-#endif
-
-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,
- 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->len_ = length;
- br->val_ = 0;
- br->bit_pos_ = 0;
- br->eos_ = 0;
-
- 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,
- 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->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_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
- ++br->pos_;
- br->bit_pos_ -= 8;
- }
- if (VP8LIsEndOfStream(br)) {
- VP8LSetEndOfStream(br);
- }
-}
-
-void VP8LDoFillBitWindow(VP8LBitReader* const br) {
- assert(br->bit_pos_ >= VP8L_WBITS);
-#if defined(VP8L_USE_FAST_LOAD)
- if (br->pos_ + sizeof(br->val_) < br->len_) {
- br->val_ >>= VP8L_WBITS;
- br->bit_pos_ -= VP8L_WBITS;
- br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) <<
- (VP8L_LBITS - VP8L_WBITS);
- br->pos_ += VP8L_LOG8_WBITS;
- return;
- }
-#endif
- ShiftBytes(br); // Slow path.
-}
-
-uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
- assert(n_bits >= 0);
- // Flag an error if end_of_stream or n_bits is more than allowed limit.
- 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 {
- VP8LSetEndOfStream(br);
- return 0;
- }
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/bit_reader_inl.h b/thirdparty/libwebp/utils/bit_reader_inl.h
deleted file mode 100644
index 99ed3137d2..0000000000
--- a/thirdparty/libwebp/utils/bit_reader_inl.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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_UBSAN_IGNORE_UNDEF 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/thirdparty/libwebp/utils/bit_reader_inl_utils.h b/thirdparty/libwebp/utils/bit_reader_inl_utils.h
new file mode 100644
index 0000000000..fd7fb0446c
--- /dev/null
+++ b/thirdparty/libwebp/utils/bit_reader_inl_utils.h
@@ -0,0 +1,190 @@
+// 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
+
+#include <string.h> // for memcpy
+
+#include "../dsp/dsp.h"
+#include "./bit_reader_utils.h"
+#include "./endian_inl_utils.h"
+#include "./utils.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_UBSAN_IGNORE_UNDEF 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_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
+ lbit_t in_bits;
+ memcpy(&in_bits, br->buf_, sizeof(in_bits));
+#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);
+ const int bit = (value > split);
+ if (bit) {
+ range -= split;
+ br->value_ -= (bit_t)(split + 1) << pos;
+ } else {
+ range = split + 1;
+ }
+ {
+ const int shift = 7 ^ BitsLog2Floor(range);
+ range <<= shift;
+ br->bits_ -= shift;
+ }
+ br->range_ = range - 1;
+ return bit;
+ }
+}
+
+// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here)
+static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW 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;
+ }
+}
+
+static WEBP_INLINE int VP8GetBitAlt(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);
+ 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;
+ }
+ if (range <= (range_t)0x7e) {
+ const int shift = kVP8Log2Range[range];
+ range = kVP8NewRange[range];
+ br->bits_ -= shift;
+ }
+ br->range_ = range;
+ return bit;
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // WEBP_UTILS_BIT_READER_INL_H_
diff --git a/thirdparty/libwebp/utils/bit_reader_utils.c b/thirdparty/libwebp/utils/bit_reader_utils.c
new file mode 100644
index 0000000000..053b710bb8
--- /dev/null
+++ b/thirdparty/libwebp/utils/bit_reader_utils.c
@@ -0,0 +1,229 @@
+// Copyright 2010 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.
+// -----------------------------------------------------------------------------
+//
+// Boolean decoder non-inlined methods
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifdef HAVE_CONFIG_H
+#include "../webp/config.h"
+#endif
+
+#include "./bit_reader_inl_utils.h"
+#include "../utils/utils.h"
+
+//------------------------------------------------------------------------------
+// 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, size_t size) {
+ assert(br != NULL);
+ assert(start != NULL);
+ assert(size < (1u << 31)); // limit ensured by format and upstream checks
+ br->range_ = 255 - 1;
+ br->value_ = 0;
+ br->bits_ = -8; // to load the very first 8bits
+ br->eof_ = 0;
+ VP8BitReaderSetBuffer(br, start, size);
+// -- GODOT -- begin
+#ifdef JAVASCRIPT_ENABLED // html5 required aligned reads
+ while(((uintptr_t)br->buf_ & 1) != 0 && !br->eof_)
+ VP8LoadFinalBytes(br);
+#else
+ VP8LoadNewBytes(br);
+#endif
+// -- GODOT -- end
+}
+
+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] = {
+ 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
+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
+};
+
+void VP8LoadFinalBytes(VP8BitReader* const br) {
+ assert(br != NULL && br->buf_ != NULL);
+ // Only read 8bits at a time
+ if (br->buf_ < br->buf_end_) {
+ 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.
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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 VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits.
+
+#if defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \
+ defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64__) || defined(_M_X64)
+#define VP8L_USE_FAST_LOAD
+#endif
+
+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,
+ 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->len_ = length;
+ br->val_ = 0;
+ br->bit_pos_ = 0;
+ br->eos_ = 0;
+
+ 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,
+ 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->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_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8);
+ ++br->pos_;
+ br->bit_pos_ -= 8;
+ }
+ if (VP8LIsEndOfStream(br)) {
+ VP8LSetEndOfStream(br);
+ }
+}
+
+void VP8LDoFillBitWindow(VP8LBitReader* const br) {
+ assert(br->bit_pos_ >= VP8L_WBITS);
+#if defined(VP8L_USE_FAST_LOAD)
+ if (br->pos_ + sizeof(br->val_) < br->len_) {
+ br->val_ >>= VP8L_WBITS;
+ br->bit_pos_ -= VP8L_WBITS;
+ br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) <<
+ (VP8L_LBITS - VP8L_WBITS);
+ br->pos_ += VP8L_LOG8_WBITS;
+ return;
+ }
+#endif
+ ShiftBytes(br); // Slow path.
+}
+
+uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) {
+ assert(n_bits >= 0);
+ // Flag an error if end_of_stream or n_bits is more than allowed limit.
+ 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 {
+ VP8LSetEndOfStream(br);
+ return 0;
+ }
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/bit_reader.h b/thirdparty/libwebp/utils/bit_reader_utils.h
index ea5c584eb4..ea5c584eb4 100644
--- a/thirdparty/libwebp/utils/bit_reader.h
+++ b/thirdparty/libwebp/utils/bit_reader_utils.h
diff --git a/thirdparty/libwebp/utils/bit_writer.c b/thirdparty/libwebp/utils/bit_writer.c
deleted file mode 100644
index 064428691b..0000000000
--- a/thirdparty/libwebp/utils/bit_writer.c
+++ /dev/null
@@ -1,319 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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"
-#include "./endian_inl.h"
-#include "./utils.h"
-
-//------------------------------------------------------------------------------
-// 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*)WebPSafeMalloc(1ULL, new_size);
- if (new_buf == NULL) {
- bw->error_ = 1;
- return 0;
- }
- 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 Flush(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) Flush(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) Flush(bw);
- }
- return bit;
-}
-
-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 VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
- if (!VP8PutBitUniform(bw, value != 0))
- return;
- if (value < 0) {
- VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
- } else {
- VP8PutBits(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) {
- VP8PutBits(bw, 0, 9 - bw->nb_bits_);
- bw->nb_bits_ = 0; // pad with zeroes
- Flush(bw);
- return bw->buf_;
-}
-
-int VP8BitWriterAppend(VP8BitWriter* const bw,
- const uint8_t* data, size_t size) {
- 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;
- return 1;
-}
-
-void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
- if (bw != NULL) {
- WebPSafeFree(bw->buf_);
- memset(bw, 0, sizeof(*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 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 (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*)WebPSafeMalloc(1ULL, allocated_size);
- if (allocated_buf == NULL) {
- bw->error_ = 1;
- return 0;
- }
- if (current_size > 0) {
- memcpy(allocated_buf, bw->buf_, current_size);
- }
- WebPSafeFree(bw->buf_);
- bw->buf_ = allocated_buf;
- bw->cur_ = bw->buf_ + current_size;
- bw->end_ = bw->buf_ + allocated_size;
- return 1;
-}
-
-int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
- memset(bw, 0, sizeof(*bw));
- return VP8LBitWriterResize(bw, expected_size);
-}
-
-void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) {
- if (bw != NULL) {
- WebPSafeFree(bw->buf_);
- memset(bw, 0, sizeof(*bw));
- }
-}
-
-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;
- }
- }
- *(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;
- }
- bw->bits_ = lbits | ((vp8l_atype_t)bits << used);
- bw->used_ = used + n_bits;
- }
-}
-
-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_;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/bit_writer.h b/thirdparty/libwebp/utils/bit_writer.h
deleted file mode 100644
index ef360d1dc6..0000000000
--- a/thirdparty/libwebp/utils/bit_writer.h
+++ /dev/null
@@ -1,145 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Bit writing and boolean coder
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#ifndef WEBP_UTILS_BIT_WRITER_H_
-#define WEBP_UTILS_BIT_WRITER_H_
-
-#include "../webp/types.h"
-
-#ifdef __cplusplus
-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 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,
- 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
-
-#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
-
-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->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3);
-}
-
-// 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);
-
-// Internal function for VP8LPutBits flushing 32 bits from the written state.
-void VP8LPutBitsFlushBits(VP8LBitWriter* const bw);
-
-// 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.
-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);
- }
-}
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* WEBP_UTILS_BIT_WRITER_H_ */
diff --git a/thirdparty/libwebp/utils/bit_writer_utils.c b/thirdparty/libwebp/utils/bit_writer_utils.c
new file mode 100644
index 0000000000..ab0c49dce8
--- /dev/null
+++ b/thirdparty/libwebp/utils/bit_writer_utils.c
@@ -0,0 +1,319 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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_utils.h"
+#include "./endian_inl_utils.h"
+#include "./utils.h"
+
+//------------------------------------------------------------------------------
+// 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*)WebPSafeMalloc(1ULL, new_size);
+ if (new_buf == NULL) {
+ bw->error_ = 1;
+ return 0;
+ }
+ 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 Flush(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) Flush(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) Flush(bw);
+ }
+ return bit;
+}
+
+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 VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
+ if (!VP8PutBitUniform(bw, value != 0)) return;
+ if (value < 0) {
+ VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
+ } else {
+ VP8PutBits(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) {
+ VP8PutBits(bw, 0, 9 - bw->nb_bits_);
+ bw->nb_bits_ = 0; // pad with zeroes
+ Flush(bw);
+ return bw->buf_;
+}
+
+int VP8BitWriterAppend(VP8BitWriter* const bw,
+ const uint8_t* data, size_t size) {
+ 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;
+ return 1;
+}
+
+void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
+ if (bw != NULL) {
+ WebPSafeFree(bw->buf_);
+ memset(bw, 0, sizeof(*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 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 (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*)WebPSafeMalloc(1ULL, allocated_size);
+ if (allocated_buf == NULL) {
+ bw->error_ = 1;
+ return 0;
+ }
+ if (current_size > 0) {
+ memcpy(allocated_buf, bw->buf_, current_size);
+ }
+ WebPSafeFree(bw->buf_);
+ bw->buf_ = allocated_buf;
+ bw->cur_ = bw->buf_ + current_size;
+ bw->end_ = bw->buf_ + allocated_size;
+ return 1;
+}
+
+int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
+ memset(bw, 0, sizeof(*bw));
+ return VP8LBitWriterResize(bw, expected_size);
+}
+
+void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) {
+ if (bw != NULL) {
+ WebPSafeFree(bw->buf_);
+ memset(bw, 0, sizeof(*bw));
+ }
+}
+
+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;
+ }
+ }
+ *(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;
+ }
+ bw->bits_ = lbits | ((vp8l_atype_t)bits << used);
+ bw->used_ = used + n_bits;
+ }
+}
+
+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_;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/bit_writer_utils.h b/thirdparty/libwebp/utils/bit_writer_utils.h
new file mode 100644
index 0000000000..9c02bbc06d
--- /dev/null
+++ b/thirdparty/libwebp/utils/bit_writer_utils.h
@@ -0,0 +1,146 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Bit writing and boolean coder
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#ifndef WEBP_UTILS_BIT_WRITER_H_
+#define WEBP_UTILS_BIT_WRITER_H_
+
+#include "../webp/types.h"
+
+#ifdef __cplusplus
+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 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,
+ const uint8_t* data, size_t size);
+
+// return approximate write position (in bits)
+static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
+ const uint64_t nb_bits = 8 + bw->nb_bits_; // bw->nb_bits_ is <= 0, note
+ return (bw->pos_ + bw->run_) * 8 + 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
+
+#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
+
+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->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3);
+}
+
+// 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);
+
+// Internal function for VP8LPutBits flushing 32 bits from the written state.
+void VP8LPutBitsFlushBits(VP8LBitWriter* const bw);
+
+// 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.
+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);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* WEBP_UTILS_BIT_WRITER_H_ */
diff --git a/thirdparty/libwebp/utils/color_cache.c b/thirdparty/libwebp/utils/color_cache.c
deleted file mode 100644
index c34b2e7f1a..0000000000
--- a/thirdparty/libwebp/utils/color_cache.c
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Color Cache for WebP Lossless
-//
-// Author: Jyrki Alakuijala (jyrki@google.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "./color_cache.h"
-#include "./utils.h"
-
-//------------------------------------------------------------------------------
-// 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;
- cc->hash_bits_ = hash_bits;
- return 1;
-}
-
-void VP8LColorCacheClear(VP8LColorCache* const cc) {
- if (cc != NULL) {
- WebPSafeFree(cc->colors_);
- cc->colors_ = NULL;
- }
-}
-
-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_));
-}
diff --git a/thirdparty/libwebp/utils/color_cache.h b/thirdparty/libwebp/utils/color_cache.h
deleted file mode 100644
index a9a9f64270..0000000000
--- a/thirdparty/libwebp/utils/color_cache.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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 "../webp/types.h"
-
-#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_bits_;
-} VP8LColorCache;
-
-static const uint32_t kHashMul = 0x1e35a7bd;
-
-static WEBP_INLINE uint32_t VP8LColorCacheLookup(
- const VP8LColorCache* const cc, uint32_t key) {
- 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_;
- 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);
-
-void VP8LColorCacheCopy(const VP8LColorCache* const src,
- VP8LColorCache* const dst);
-
-// Delete the memory associated to color cache.
-void VP8LColorCacheClear(VP8LColorCache* const color_cache);
-
-//------------------------------------------------------------------------------
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // WEBP_UTILS_COLOR_CACHE_H_
diff --git a/thirdparty/libwebp/utils/color_cache_utils.c b/thirdparty/libwebp/utils/color_cache_utils.c
new file mode 100644
index 0000000000..0172590c48
--- /dev/null
+++ b/thirdparty/libwebp/utils/color_cache_utils.c
@@ -0,0 +1,49 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Color Cache for WebP Lossless
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "./color_cache_utils.h"
+#include "./utils.h"
+
+//------------------------------------------------------------------------------
+// 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;
+ cc->hash_bits_ = hash_bits;
+ return 1;
+}
+
+void VP8LColorCacheClear(VP8LColorCache* const cc) {
+ if (cc != NULL) {
+ WebPSafeFree(cc->colors_);
+ cc->colors_ = NULL;
+ }
+}
+
+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_));
+}
diff --git a/thirdparty/libwebp/utils/color_cache_utils.h b/thirdparty/libwebp/utils/color_cache_utils.h
new file mode 100644
index 0000000000..c373e6b361
--- /dev/null
+++ b/thirdparty/libwebp/utils/color_cache_utils.h
@@ -0,0 +1,85 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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 "../webp/types.h"
+
+#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_bits_;
+} VP8LColorCache;
+
+static const uint64_t kHashMul = 0x1e35a7bdull;
+
+static WEBP_INLINE int HashPix(uint32_t argb, int shift) {
+ return (int)(((argb * kHashMul) & 0xffffffffu) >> shift);
+}
+
+static WEBP_INLINE uint32_t VP8LColorCacheLookup(
+ const VP8LColorCache* const cc, uint32_t key) {
+ 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 int key = HashPix(argb, cc->hash_shift_);
+ cc->colors_[key] = argb;
+}
+
+static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc,
+ uint32_t argb) {
+ return HashPix(argb, cc->hash_shift_);
+}
+
+// Return the key if cc contains argb, and -1 otherwise.
+static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc,
+ uint32_t argb) {
+ const int key = HashPix(argb, cc->hash_shift_);
+ return (cc->colors_[key] == argb) ? key : -1;
+}
+
+//------------------------------------------------------------------------------
+
+// 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);
+
+void VP8LColorCacheCopy(const VP8LColorCache* const src,
+ VP8LColorCache* const dst);
+
+// Delete the memory associated to color cache.
+void VP8LColorCacheClear(VP8LColorCache* const color_cache);
+
+//------------------------------------------------------------------------------
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WEBP_UTILS_COLOR_CACHE_H_
diff --git a/thirdparty/libwebp/utils/endian_inl.h b/thirdparty/libwebp/utils/endian_inl_utils.h
index e11260ff7d..e11260ff7d 100644
--- a/thirdparty/libwebp/utils/endian_inl.h
+++ b/thirdparty/libwebp/utils/endian_inl_utils.h
diff --git a/thirdparty/libwebp/utils/filters.c b/thirdparty/libwebp/utils/filters.c
deleted file mode 100644
index 15543b1271..0000000000
--- a/thirdparty/libwebp/utils/filters.c
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// filter estimation
-//
-// Author: Urvang (urvang@google.com)
-
-#include "./filters.h"
-#include <stdlib.h>
-#include <string.h>
-
-// -----------------------------------------------------------------------------
-// Quick estimate of a potentially interesting filter mode to try.
-
-#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 & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
-}
-
-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;
- 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;
- }
- }
- {
- 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;
- for (i = 0; i < SMAX; ++i) {
- if (bins[filter][i] > 0) {
- score += i;
- }
- }
- if (score < best_score) {
- best_score = score;
- best_filter = (WEBP_FILTER_TYPE)filter;
- }
- }
- return best_filter;
- }
-}
-
-#undef SMAX
-#undef SDIFF
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/filters_utils.c b/thirdparty/libwebp/utils/filters_utils.c
new file mode 100644
index 0000000000..49c1d18a22
--- /dev/null
+++ b/thirdparty/libwebp/utils/filters_utils.c
@@ -0,0 +1,76 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// filter estimation
+//
+// Author: Urvang (urvang@google.com)
+
+#include "./filters_utils.h"
+#include <stdlib.h>
+#include <string.h>
+
+// -----------------------------------------------------------------------------
+// Quick estimate of a potentially interesting filter mode to try.
+
+#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 & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit
+}
+
+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;
+ 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;
+ }
+ }
+ {
+ 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;
+ for (i = 0; i < SMAX; ++i) {
+ if (bins[filter][i] > 0) {
+ score += i;
+ }
+ }
+ if (score < best_score) {
+ best_score = score;
+ best_filter = (WEBP_FILTER_TYPE)filter;
+ }
+ }
+ return best_filter;
+ }
+}
+
+#undef SMAX
+#undef SDIFF
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/filters.h b/thirdparty/libwebp/utils/filters_utils.h
index 088b132fc5..088b132fc5 100644
--- a/thirdparty/libwebp/utils/filters.h
+++ b/thirdparty/libwebp/utils/filters_utils.h
diff --git a/thirdparty/libwebp/utils/huffman.c b/thirdparty/libwebp/utils/huffman.c
deleted file mode 100644
index 36e5502836..0000000000
--- a/thirdparty/libwebp/utils/huffman.c
+++ /dev/null
@@ -1,205 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Utilities for building and looking up Huffman trees.
-//
-// Author: Urvang Joshi (urvang@google.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "./huffman.h"
-#include "./utils.h"
-#include "../webp/format_constants.h"
-
-// Huffman data read via DecodeImageStream is represented in two (red and green)
-// bytes.
-#define MAX_HTREE_GROUPS 0x10000
-
-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;
-}
-
-void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) {
- if (htree_groups != NULL) {
- WebPSafeFree(htree_groups);
- }
-}
-
-// 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;
-}
-
-// 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);
-}
-
-// 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 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(root_table != NULL);
- assert(root_bits > 0);
-
- // Build histogram of code lengths.
- for (symbol = 0; symbol < code_lengths_size; ++symbol) {
- if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {
- return 0;
- }
- ++count[code_lengths[symbol]];
- }
-
- // Error, all code lengths are zeros.
- if (count[0] == code_lengths_size) {
- return 0;
- }
-
- // 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;
- }
- offset[len + 1] = offset[len] + count[len];
- }
-
- sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
- if (sorted == NULL) {
- return 0;
- }
-
- // 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) {
- sorted[offset[symbol_code_length]++] = symbol;
- }
- }
-
- // 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;
- }
-
- {
- 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);
- }
- }
-
- // 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);
- }
- }
-
- // Check if tree is full.
- if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
- WebPSafeFree(sorted);
- return 0;
- }
- }
-
- WebPSafeFree(sorted);
- return total_size;
-}
diff --git a/thirdparty/libwebp/utils/huffman_encode.c b/thirdparty/libwebp/utils/huffman_encode.c
deleted file mode 100644
index 4e5ef6b447..0000000000
--- a/thirdparty/libwebp/utils/huffman_encode.c
+++ /dev/null
@@ -1,417 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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.h"
-#include "../webp/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
-// 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; // 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.
- {
- // 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.
- uint32_t 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.
- {
- 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)) {
- uint32_t k;
- // The stride must end, collapse what we have, if we have enough (4).
- uint32_t 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;
- }
- }
- }
- }
-}
-
-// 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 {
- assert(t1->value_ != t2->value_);
- return (t1->value_ < t2->value_) ? -1 : 1;
- }
-}
-
-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 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;
- int tree_size_orig = 0;
- int i;
-
- for (i = 0; i < histogram_size; ++i) {
- if (histogram[i] != 0) {
- ++tree_size_orig;
- }
- }
-
- 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
- // 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 uint32_t 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.
- 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_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;
- }
- }
- }
-}
-
-// -----------------------------------------------------------------------------
-// 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
-
-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(huff_code);
-}
diff --git a/thirdparty/libwebp/utils/huffman_encode_utils.c b/thirdparty/libwebp/utils/huffman_encode_utils.c
new file mode 100644
index 0000000000..f9504658ea
--- /dev/null
+++ b/thirdparty/libwebp/utils/huffman_encode_utils.c
@@ -0,0 +1,417 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Author: Jyrki Alakuijala (jyrki@google.com)
+//
+// Entropy encoding (Huffman) for webp lossless.
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "./huffman_encode_utils.h"
+#include "./utils.h"
+#include "../webp/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
+// 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; // 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.
+ {
+ // 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.
+ uint32_t 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.
+ {
+ 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)) {
+ uint32_t k;
+ // The stride must end, collapse what we have, if we have enough (4).
+ uint32_t 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;
+ }
+ }
+ }
+ }
+}
+
+// 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 {
+ assert(t1->value_ != t2->value_);
+ return (t1->value_ < t2->value_) ? -1 : 1;
+ }
+}
+
+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 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;
+ int tree_size_orig = 0;
+ int i;
+
+ for (i = 0; i < histogram_size; ++i) {
+ if (histogram[i] != 0) {
+ ++tree_size_orig;
+ }
+ }
+
+ 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
+ // 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 uint32_t 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.
+ 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_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;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+// 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
+
+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(huff_code);
+}
diff --git a/thirdparty/libwebp/utils/huffman_encode.h b/thirdparty/libwebp/utils/huffman_encode_utils.h
index a157165148..a157165148 100644
--- a/thirdparty/libwebp/utils/huffman_encode.h
+++ b/thirdparty/libwebp/utils/huffman_encode_utils.h
diff --git a/thirdparty/libwebp/utils/huffman_utils.c b/thirdparty/libwebp/utils/huffman_utils.c
new file mode 100644
index 0000000000..008b5d746f
--- /dev/null
+++ b/thirdparty/libwebp/utils/huffman_utils.c
@@ -0,0 +1,223 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Utilities for building and looking up Huffman trees.
+//
+// Author: Urvang Joshi (urvang@google.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "./huffman_utils.h"
+#include "./utils.h"
+#include "../webp/format_constants.h"
+
+// Huffman data read via DecodeImageStream is represented in two (red and green)
+// bytes.
+#define MAX_HTREE_GROUPS 0x10000
+
+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;
+}
+
+void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) {
+ if (htree_groups != NULL) {
+ WebPSafeFree(htree_groups);
+ }
+}
+
+// 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 step ? (key & (step - 1)) + step : key;
+}
+
+// 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);
+}
+
+// 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;
+}
+
+// sorted[code_lengths_size] is a pre-allocated array for sorting symbols
+// by code length.
+static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+ const int code_lengths[], int code_lengths_size,
+ uint16_t sorted[]) {
+ HuffmanCode* table = root_table; // next available space in table
+ int total_size = 1 << root_bits; // total size root table + 2nd level table
+ 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(root_table != NULL);
+ assert(root_bits > 0);
+
+ // Build histogram of code lengths.
+ for (symbol = 0; symbol < code_lengths_size; ++symbol) {
+ if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {
+ return 0;
+ }
+ ++count[code_lengths[symbol]];
+ }
+
+ // Error, all code lengths are zeros.
+ if (count[0] == code_lengths_size) {
+ return 0;
+ }
+
+ // 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;
+ }
+ offset[len + 1] = offset[len] + count[len];
+ }
+
+ // 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) {
+ sorted[offset[symbol_code_length]++] = symbol;
+ }
+ }
+
+ // 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);
+ return total_size;
+ }
+
+ {
+ 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) {
+ 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);
+ }
+ }
+
+ // 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) {
+ 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);
+ }
+ }
+
+ // Check if tree is full.
+ if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
+ return 0;
+ }
+ }
+
+ return total_size;
+}
+
+// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits).
+// More commonly, the value is around ~280.
+#define MAX_CODE_LENGTHS_SIZE \
+ ((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
+// Cut-off value for switching between heap and stack allocation.
+#define SORTED_SIZE_CUTOFF 512
+int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+ const int code_lengths[], int code_lengths_size) {
+ int total_size;
+ assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
+ if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
+ // use local stack-allocated array.
+ uint16_t sorted[SORTED_SIZE_CUTOFF];
+ total_size = BuildHuffmanTable(root_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
+ } else { // rare case. Use heap allocation.
+ uint16_t* const sorted =
+ (uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
+ if (sorted == NULL) return 0;
+ total_size = BuildHuffmanTable(root_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
+ WebPSafeFree(sorted);
+ }
+ return total_size;
+}
diff --git a/thirdparty/libwebp/utils/huffman.h b/thirdparty/libwebp/utils/huffman_utils.h
index c6dd6aaa45..c6dd6aaa45 100644
--- a/thirdparty/libwebp/utils/huffman.h
+++ b/thirdparty/libwebp/utils/huffman_utils.h
diff --git a/thirdparty/libwebp/utils/quant_levels.c b/thirdparty/libwebp/utils/quant_levels.c
deleted file mode 100644
index d7c8aab922..0000000000
--- a/thirdparty/libwebp/utils/quant_levels.c
+++ /dev/null
@@ -1,140 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// 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"
-
-#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;
-}
-
diff --git a/thirdparty/libwebp/utils/quant_levels_dec.c b/thirdparty/libwebp/utils/quant_levels_dec.c
deleted file mode 100644
index ee0a3fe127..0000000000
--- a/thirdparty/libwebp/utils/quant_levels_dec.c
+++ /dev/null
@@ -1,284 +0,0 @@
-// 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 stride_; // stride in bytes
- 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->stride_;
- }
-}
-
-// 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_ += p->stride_; // 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(SmoothParams* const p) {
- int i, j, last_level;
- uint8_t used_levels[256] = { 0 };
- const uint8_t* data = p->src_;
- p->min_ = 255;
- p->max_ = 0;
- for (j = 0; j < p->height_; ++j) {
- for (i = 0; i < p->width_; ++i) {
- const int v = data[i];
- if (v < p->min_) p->min_ = v;
- if (v > p->max_) p->max_ = v;
- used_levels[v] = 1;
- }
- data += p->stride_;
- }
- // 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 stride,
- 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->stride_ = stride;
- 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(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 stride,
- 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, stride, 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/thirdparty/libwebp/utils/quant_levels_dec_utils.c b/thirdparty/libwebp/utils/quant_levels_dec_utils.c
new file mode 100644
index 0000000000..d4d23d3147
--- /dev/null
+++ b/thirdparty/libwebp/utils/quant_levels_dec_utils.c
@@ -0,0 +1,284 @@
+// 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_utils.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 stride_; // stride in bytes
+ 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->stride_;
+ }
+}
+
+// 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_ += p->stride_; // 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(SmoothParams* const p) {
+ int i, j, last_level;
+ uint8_t used_levels[256] = { 0 };
+ const uint8_t* data = p->src_;
+ p->min_ = 255;
+ p->max_ = 0;
+ for (j = 0; j < p->height_; ++j) {
+ for (i = 0; i < p->width_; ++i) {
+ const int v = data[i];
+ if (v < p->min_) p->min_ = v;
+ if (v > p->max_) p->max_ = v;
+ used_levels[v] = 1;
+ }
+ data += p->stride_;
+ }
+ // 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 stride,
+ 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->stride_ = stride;
+ 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(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 stride,
+ 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, stride, 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/thirdparty/libwebp/utils/quant_levels_dec.h b/thirdparty/libwebp/utils/quant_levels_dec_utils.h
index 59a13495d3..59a13495d3 100644
--- a/thirdparty/libwebp/utils/quant_levels_dec.h
+++ b/thirdparty/libwebp/utils/quant_levels_dec_utils.h
diff --git a/thirdparty/libwebp/utils/quant_levels_utils.c b/thirdparty/libwebp/utils/quant_levels_utils.c
new file mode 100644
index 0000000000..73174e8ab9
--- /dev/null
+++ b/thirdparty/libwebp/utils/quant_levels_utils.c
@@ -0,0 +1,140 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// 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_utils.h"
+
+#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;
+}
+
diff --git a/thirdparty/libwebp/utils/quant_levels.h b/thirdparty/libwebp/utils/quant_levels_utils.h
index 1cb5a32cae..1cb5a32cae 100644
--- a/thirdparty/libwebp/utils/quant_levels.h
+++ b/thirdparty/libwebp/utils/quant_levels_utils.h
diff --git a/thirdparty/libwebp/utils/random.c b/thirdparty/libwebp/utils/random.c
deleted file mode 100644
index 24e96ad648..0000000000
--- a/thirdparty/libwebp/utils/random.c
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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/thirdparty/libwebp/utils/random_utils.c b/thirdparty/libwebp/utils/random_utils.c
new file mode 100644
index 0000000000..9f1e4154a6
--- /dev/null
+++ b/thirdparty/libwebp/utils/random_utils.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_utils.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/thirdparty/libwebp/utils/random.h b/thirdparty/libwebp/utils/random_utils.h
index c392a615ca..c392a615ca 100644
--- a/thirdparty/libwebp/utils/random.h
+++ b/thirdparty/libwebp/utils/random_utils.h
diff --git a/thirdparty/libwebp/utils/rescaler.c b/thirdparty/libwebp/utils/rescaler.c
deleted file mode 100644
index d2278a52ff..0000000000
--- a/thirdparty/libwebp/utils/rescaler.c
+++ /dev/null
@@ -1,146 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Rescaling functions
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../dsp/dsp.h"
-#include "./rescaler.h"
-
-//------------------------------------------------------------------------------
-
-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, 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;
- wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub;
- 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.
- // Its value is <= WEBP_RESCALER_ONE, because dst_height <= wrk->y_add, and
- // wrk->x_add >= 1;
- const uint64_t ratio =
- (uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add);
- if (ratio != (uint32_t)ratio) {
- // When ratio == WEBP_RESCALER_ONE, we can't represent the ratio with the
- // current fixed-point precision. This happens when src_height ==
- // wrk->y_add (which == src_height), and wrk->x_add == 1.
- // => 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));
-
- WebPRescalerDspInit();
-}
-
-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;
-
- // if width is unspecified, scale original proportionally to height ratio.
- if (width == 0) {
- width = (src_width * height + src_height / 2) / src_height;
- }
- // 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;
- }
-}
-
-//------------------------------------------------------------------------------
-// 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 && !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;
- }
- return total_imported;
-}
-
-int WebPRescalerExport(WebPRescaler* const rescaler) {
- int total_exported = 0;
- while (WebPRescalerHasPendingOutput(rescaler)) {
- WebPRescalerExportRow(rescaler);
- ++total_exported;
- }
- return total_exported;
-}
-
-//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/rescaler_utils.c b/thirdparty/libwebp/utils/rescaler_utils.c
new file mode 100644
index 0000000000..0d1f80da24
--- /dev/null
+++ b/thirdparty/libwebp/utils/rescaler_utils.c
@@ -0,0 +1,146 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Rescaling functions
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../dsp/dsp.h"
+#include "./rescaler_utils.h"
+
+//------------------------------------------------------------------------------
+
+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, 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;
+ wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub;
+ 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.
+ // Its value is <= WEBP_RESCALER_ONE, because dst_height <= wrk->y_add, and
+ // wrk->x_add >= 1;
+ const uint64_t ratio =
+ (uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add);
+ if (ratio != (uint32_t)ratio) {
+ // When ratio == WEBP_RESCALER_ONE, we can't represent the ratio with the
+ // current fixed-point precision. This happens when src_height ==
+ // wrk->y_add (which == src_height), and wrk->x_add == 1.
+ // => 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));
+
+ WebPRescalerDspInit();
+}
+
+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;
+
+ // if width is unspecified, scale original proportionally to height ratio.
+ if (width == 0) {
+ width = (src_width * height + src_height / 2) / src_height;
+ }
+ // 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;
+ }
+}
+
+//------------------------------------------------------------------------------
+// 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 && !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;
+ }
+ return total_imported;
+}
+
+int WebPRescalerExport(WebPRescaler* const rescaler) {
+ int total_exported = 0;
+ while (WebPRescalerHasPendingOutput(rescaler)) {
+ WebPRescalerExportRow(rescaler);
+ ++total_exported;
+ }
+ return total_exported;
+}
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/rescaler.h b/thirdparty/libwebp/utils/rescaler_utils.h
index 98b01a76d0..98b01a76d0 100644
--- a/thirdparty/libwebp/utils/rescaler.h
+++ b/thirdparty/libwebp/utils/rescaler_utils.h
diff --git a/thirdparty/libwebp/utils/thread.c b/thirdparty/libwebp/utils/thread.c
deleted file mode 100644
index 93f7622797..0000000000
--- a/thirdparty/libwebp/utils/thread.c
+++ /dev/null
@@ -1,358 +0,0 @@
-// 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.
-// -----------------------------------------------------------------------------
-//
-// Multi-threaded worker
-//
-// Author: Skal (pascal.massimino@gmail.com)
-
-#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 _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
-
-#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)
-
-//------------------------------------------------------------------------------
-// simplistic pthread emulation layer
-
-#include <process.h>
-
-// _beginthreadex requires __stdcall
-#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;
-}
-
-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;
-#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater
- InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/);
-#else
- InitializeCriticalSection(mutex);
-#endif
- 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;
-#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);
- if (condition->waiting_sem_ == NULL ||
- condition->received_sem_ == NULL ||
- condition->signal_event_ == NULL) {
- 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_);
- // 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);
- }
-#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))
- 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);
-#endif
- return !ok;
-}
-
-#else // !_WIN32
-# define THREADFN void*
-# define THREAD_RETURN(val) val
-#endif // _WIN32
-
-//------------------------------------------------------------------------------
-
-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->impl_->mutex_);
- while (worker->status_ == OK) { // wait in idling mode
- pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
- }
- if (worker->status_ == WORK) {
- 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->impl_->condition_);
- pthread_mutex_unlock(&worker->impl_->mutex_);
- }
- return THREAD_RETURN(NULL); // Thread is finished
-}
-
-// main thread state control
-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->impl_->mutex_);
-}
-
-#endif // WEBP_USE_THREAD
-
-//------------------------------------------------------------------------------
-
-static void Init(WebPWorker* const worker) {
- memset(worker, 0, sizeof(*worker));
- worker->status_ = NOT_OK;
-}
-
-static int Sync(WebPWorker* const worker) {
-#ifdef WEBP_USE_THREAD
- ChangeState(worker, OK);
-#endif
- assert(worker->status_ <= OK);
- return !worker->had_error;
-}
-
-static int Reset(WebPWorker* const worker) {
- int ok = 1;
- worker->had_error = 0;
- if (worker->status_ < OK) {
-#ifdef WEBP_USE_THREAD
- worker->impl_ = (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(*worker->impl_));
- if (worker->impl_ == NULL) {
- return 0;
- }
- 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->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 = Sync(worker);
- }
- assert(!ok || (worker->status_ == OK));
- return ok;
-}
-
-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
- ChangeState(worker, WORK);
-#else
- Execute(worker);
-#endif
-}
-
-static void End(WebPWorker* const worker) {
-#ifdef WEBP_USE_THREAD
- 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;
- assert(worker->impl_ == NULL);
-#endif
- assert(worker->status_ == NOT_OK);
-}
-
-//------------------------------------------------------------------------------
-
-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/thirdparty/libwebp/utils/thread_utils.c b/thirdparty/libwebp/utils/thread_utils.c
new file mode 100644
index 0000000000..1729060c70
--- /dev/null
+++ b/thirdparty/libwebp/utils/thread_utils.c
@@ -0,0 +1,356 @@
+// 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.
+// -----------------------------------------------------------------------------
+//
+// Multi-threaded worker
+//
+// Author: Skal (pascal.massimino@gmail.com)
+
+#include <assert.h>
+#include <string.h> // for memset()
+#include "./thread_utils.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 _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
+
+#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)
+
+//------------------------------------------------------------------------------
+// simplistic pthread emulation layer
+
+#include <process.h>
+
+// _beginthreadex requires __stdcall
+#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;
+}
+
+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;
+#if _WIN32_WINNT >= 0x0600 // Windows Vista / Server 2008 or greater
+ InitializeCriticalSectionEx(mutex, 0 /*dwSpinCount*/, 0 /*Flags*/);
+#else
+ InitializeCriticalSection(mutex);
+#endif
+ 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;
+#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);
+ if (condition->waiting_sem_ == NULL ||
+ condition->received_sem_ == NULL ||
+ condition->signal_event_ == NULL) {
+ 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_);
+ // 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);
+ }
+#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)) 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);
+#endif
+ return !ok;
+}
+
+#else // !_WIN32
+# define THREADFN void*
+# define THREAD_RETURN(val) val
+#endif // _WIN32
+
+//------------------------------------------------------------------------------
+
+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->impl_->mutex_);
+ while (worker->status_ == OK) { // wait in idling mode
+ pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
+ }
+ if (worker->status_ == WORK) {
+ 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->impl_->condition_);
+ pthread_mutex_unlock(&worker->impl_->mutex_);
+ }
+ return THREAD_RETURN(NULL); // Thread is finished
+}
+
+// main thread state control
+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->impl_->mutex_);
+}
+
+#endif // WEBP_USE_THREAD
+
+//------------------------------------------------------------------------------
+
+static void Init(WebPWorker* const worker) {
+ memset(worker, 0, sizeof(*worker));
+ worker->status_ = NOT_OK;
+}
+
+static int Sync(WebPWorker* const worker) {
+#ifdef WEBP_USE_THREAD
+ ChangeState(worker, OK);
+#endif
+ assert(worker->status_ <= OK);
+ return !worker->had_error;
+}
+
+static int Reset(WebPWorker* const worker) {
+ int ok = 1;
+ worker->had_error = 0;
+ if (worker->status_ < OK) {
+#ifdef WEBP_USE_THREAD
+ worker->impl_ = (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(*worker->impl_));
+ if (worker->impl_ == NULL) {
+ return 0;
+ }
+ 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->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 = Sync(worker);
+ }
+ assert(!ok || (worker->status_ == OK));
+ return ok;
+}
+
+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
+ ChangeState(worker, WORK);
+#else
+ Execute(worker);
+#endif
+}
+
+static void End(WebPWorker* const worker) {
+#ifdef WEBP_USE_THREAD
+ 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;
+ assert(worker->impl_ == NULL);
+#endif
+ assert(worker->status_ == NOT_OK);
+}
+
+//------------------------------------------------------------------------------
+
+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/thirdparty/libwebp/utils/thread.h b/thirdparty/libwebp/utils/thread_utils.h
index 8408311855..8408311855 100644
--- a/thirdparty/libwebp/utils/thread.h
+++ b/thirdparty/libwebp/utils/thread_utils.h
diff --git a/thirdparty/libwebp/utils/utils.c b/thirdparty/libwebp/utils/utils.c
index 82dbf8d5e5..504d924b60 100644
--- a/thirdparty/libwebp/utils/utils.c
+++ b/thirdparty/libwebp/utils/utils.c
@@ -25,7 +25,7 @@
// 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
+ --stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc
ms_print massif.out
*/
// In addition:
@@ -243,8 +243,7 @@ void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
//------------------------------------------------------------------------------
-#define MAX_COLOR_COUNT MAX_PALETTE_SIZE
-#define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4)
+#define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 4)
#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE).
int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
@@ -253,7 +252,7 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
int num_colors = 0;
uint8_t in_use[COLOR_HASH_SIZE] = { 0 };
uint32_t colors[COLOR_HASH_SIZE];
- static const uint32_t kHashMul = 0x1e35a7bdU;
+ static const uint64_t kHashMul = 0x1e35a7bdull;
const uint32_t* argb = pic->argb;
const int width = pic->width;
const int height = pic->height;
@@ -268,14 +267,14 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
continue;
}
last_pix = argb[x];
- key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT;
+ key = ((last_pix * kHashMul) & 0xffffffffu) >> COLOR_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 + 1; // Exact count not needed.
+ if (num_colors > MAX_PALETTE_SIZE) {
+ return MAX_PALETTE_SIZE + 1; // Exact count not needed.
}
break;
} else if (colors[key] == last_pix) {
@@ -302,8 +301,30 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) {
return num_colors;
}
-#undef MAX_COLOR_COUNT
#undef COLOR_HASH_SIZE
#undef COLOR_HASH_RIGHT_SHIFT
//------------------------------------------------------------------------------
+
+#if defined(WEBP_NEED_LOG_TABLE_8BIT)
+const uint8_t WebPLogTable8bit[256] = { // 31 ^ clz(i)
+ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+#endif
+
+//------------------------------------------------------------------------------
diff --git a/thirdparty/libwebp/utils/utils.h b/thirdparty/libwebp/utils/utils.h
index 3a5d4e6a78..3ab459050a 100644
--- a/thirdparty/libwebp/utils/utils.h
+++ b/thirdparty/libwebp/utils/utils.h
@@ -62,7 +62,6 @@ WEBP_EXTERN(void) WebPSafeFree(void* const ptr);
#define WEBP_ALIGN_CST 31
#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST)
-#if defined(WEBP_FORCE_ALIGNED)
#include <string.h>
// memcpy() is the safe way of moving potentially unaligned 32b memory.
static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
@@ -73,16 +72,6 @@ static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
memcpy(ptr, &val, sizeof(val));
}
-#else
-static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE
-uint32_t WebPMemToUint32(const uint8_t* const ptr) {
- return *(const uint32_t*)ptr;
-}
-static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE
-void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
- *(uint32_t*)ptr = val;
-}
-#endif
//------------------------------------------------------------------------------
// Reading/writing data.
@@ -118,6 +107,19 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
PutLE16(data + 2, (int)(val >> 16));
}
+// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
+// based on table or not. Can be used as fallback if clz() is not available.
+#define WEBP_NEED_LOG_TABLE_8BIT
+extern const uint8_t WebPLogTable8bit[256];
+static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
+ int log = 0;
+ while (n >= 256) {
+ log += 8;
+ n >>= 8;
+ }
+ return log + WebPLogTable8bit[n];
+}
+
// Returns (int)floor(log2(n)). n must be > 0.
// use GNU builtins where available.
#if defined(__GNUC__) && \
@@ -135,22 +137,8 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
_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;
-}
+#else // default: use the C-version.
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); }
#endif
//------------------------------------------------------------------------------
@@ -172,12 +160,12 @@ WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src,
// Unique colors.
// Returns count of unique colors in 'pic', assuming pic->use_argb is true.
-// If the unique color count is more than MAX_COLOR_COUNT, returns
-// MAX_COLOR_COUNT+1.
+// If the unique color count is more than MAX_PALETTE_SIZE, returns
+// MAX_PALETTE_SIZE+1.
// If 'palette' is not NULL and number of unique colors is less than or equal to
-// MAX_COLOR_COUNT, also outputs the actual unique colors into 'palette'.
+// MAX_PALETTE_SIZE, also outputs the actual unique colors into 'palette'.
// Note: 'palette' is assumed to be an array already allocated with at least
-// MAX_COLOR_COUNT elements.
+// MAX_PALETTE_SIZE elements.
WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic,
uint32_t* const palette);
diff --git a/thirdparty/libwebp/webp/config.h b/thirdparty/libwebp/webp/config.h
deleted file mode 100644
index 0ce1c7064d..0000000000
--- a/thirdparty/libwebp/webp/config.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/* 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 */
-#undef HAVE_BUILTIN_BSWAP16
-
-/* Set to 1 if __builtin_bswap32 is available */
-#undef HAVE_BUILTIN_BSWAP32
-
-/* Set to 1 if __builtin_bswap64 is available */
-#undef HAVE_BUILTIN_BSWAP64
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* 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. */
-#undef HAVE_GL_GLUT_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the <OpenGL/glut.h> header file. */
-#undef HAVE_OPENGL_GLUT_H
-
-/* Have PTHREAD_PRIO_INHERIT. */
-#undef HAVE_PTHREAD_PRIO_INHERIT
-
-/* 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. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* 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.
- */
-#undef LT_OBJDIR
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* 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. */
-#undef STDC_HEADERS
-
-/* Version number of package */
-#undef VERSION
-
-/* 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 */
-#undef WEBP_HAVE_AVX2
-
-/* Set to 1 if GIF library is installed */
-#undef WEBP_HAVE_GIF
-
-/* Set to 1 if OpenGL is supported */
-#undef WEBP_HAVE_GL
-
-/* Set to 1 if JPEG library is installed */
-#undef WEBP_HAVE_JPEG
-
-/* Set to 1 if NEON is supported */
-#undef WEBP_HAVE_NEON
-
-/* Set to 1 if runtime detection of NEON is enabled */
-#undef WEBP_HAVE_NEON_RTCD
-
-/* Set to 1 if PNG library is installed */
-#undef WEBP_HAVE_PNG
-
-/* Set to 1 if SSE2 is supported */
-#undef WEBP_HAVE_SSE2
-
-/* Set to 1 if SSE4.1 is supported */
-#undef WEBP_HAVE_SSE41
-
-/* Set to 1 if TIFF library is installed */
-#undef WEBP_HAVE_TIFF
-
-/* Undefine this to disable thread support. */
-#undef WEBP_USE_THREAD
-
-/* 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/thirdparty/libwebp/webp/encode.h b/thirdparty/libwebp/webp/encode.h
index b65e27e7fd..35fde1d052 100644
--- a/thirdparty/libwebp/webp/encode.h
+++ b/thirdparty/libwebp/webp/encode.h
@@ -20,7 +20,7 @@
extern "C" {
#endif
-#define WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b)
+#define WEBP_ENCODER_ABI_VERSION 0x020e // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
@@ -141,12 +141,10 @@ struct WebPConfig {
// RGB information for better compression. The default
// value is 0.
-#ifdef WEBP_EXPERIMENTAL_FEATURES
- int delta_palettization;
+ int use_delta_palette; // reserved for future lossless feature
+ int use_sharp_yuv; // if needed, use sharp (and slow) RGB->YUV conversion
+
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
@@ -388,9 +386,24 @@ WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture);
// Returns false in case of memory allocation error.
WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst);
+// Compute the single distortion for packed planes of samples.
+// 'src' will be compared to 'ref', and the raw distortion stored into
+// '*distortion'. The refined metric (log(MSE), log(1 - ssim),...' will be
+// stored in '*result'.
+// 'x_step' is the horizontal stride (in bytes) between samples.
+// 'src/ref_stride' is the byte distance between rows.
+// Returns false in case of error (bad parameter, memory allocation error, ...).
+WEBP_EXTERN(int) WebPPlaneDistortion(const uint8_t* src, size_t src_stride,
+ const uint8_t* ref, size_t ref_stride,
+ int width, int height,
+ size_t x_step,
+ int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM
+ float* distortion, float* result);
+
// 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, ...)
+// are in dB, stored in result[] in the B/G/R/A/All order. The distortion is
+// always performed using ARGB samples. Hence if the input is YUV(A), the
+// picture will be internally converted to ARGB (just for the measurement).
// Warning: this function is rather CPU-intensive.
WEBP_EXTERN(int) WebPPictureDistortion(
const WebPPicture* src, const WebPPicture* ref,
@@ -473,11 +486,13 @@ WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture,
WEBP_EXTERN(int) WebPPictureARGBToYUVADithered(
WebPPicture* picture, WebPEncCSP colorspace, float dithering);
-// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion.
+// Performs 'sharp' 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.
+// and sharper YUV representation.
// Returns false in case of error.
+WEBP_EXTERN(int) WebPPictureSharpARGBToYUVA(WebPPicture* picture);
+// kept for backward compatibility:
WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture);
// Converts picture->yuv to picture->argb and sets picture->use_argb to true.
diff --git a/thirdparty/libwebp/webp/format_constants.h b/thirdparty/libwebp/webp/format_constants.h
index b6e78a643e..329fc8a3b0 100644
--- a/thirdparty/libwebp/webp/format_constants.h
+++ b/thirdparty/libwebp/webp/format_constants.h
@@ -72,14 +72,13 @@ typedef enum {
#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP").
#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 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
+#define MAX_POSITION_OFFSET (1 << 24) // maximum frame x/y offset
// Maximum chunk payload is such that adding the header and padding won't
// overflow a uint32_t.
diff --git a/thirdparty/libwebp/webp/mux.h b/thirdparty/libwebp/webp/mux.h
index b72658c741..daccc65e86 100644
--- a/thirdparty/libwebp/webp/mux.h
+++ b/thirdparty/libwebp/webp/mux.h
@@ -21,13 +21,13 @@
extern "C" {
#endif
-#define WEBP_MUX_ABI_VERSION 0x0106 // MAJOR(8b) + MINOR(8b)
+#define WEBP_MUX_ABI_VERSION 0x0108 // MAJOR(8b) + MINOR(8b)
//------------------------------------------------------------------------------
// Mux API
//
// This API allows manipulation of WebP container images containing features
-// like color profile, metadata, animation and fragmented images.
+// like color profile, metadata, animation.
//
// Code Example#1: Create a WebPMux object with image data, color profile and
// XMP metadata.
@@ -81,16 +81,16 @@ typedef enum WebPMuxError {
// IDs for different types of chunks.
typedef enum WebPChunkId {
- WEBP_CHUNK_VP8X, // VP8X
- WEBP_CHUNK_ICCP, // ICCP
- WEBP_CHUNK_ANIM, // ANIM
- WEBP_CHUNK_ANMF, // ANMF
- WEBP_CHUNK_FRGM, // FRGM
- WEBP_CHUNK_ALPHA, // ALPH
- WEBP_CHUNK_IMAGE, // VP8/VP8L
- WEBP_CHUNK_EXIF, // EXIF
- WEBP_CHUNK_XMP, // XMP
- WEBP_CHUNK_UNKNOWN, // Other chunks.
+ WEBP_CHUNK_VP8X, // VP8X
+ WEBP_CHUNK_ICCP, // ICCP
+ WEBP_CHUNK_ANIM, // ANIM
+ WEBP_CHUNK_ANMF, // ANMF
+ WEBP_CHUNK_DEPRECATED, // (deprecated from FRGM)
+ WEBP_CHUNK_ALPHA, // ALPH
+ WEBP_CHUNK_IMAGE, // VP8/VP8L
+ WEBP_CHUNK_EXIF, // EXIF
+ WEBP_CHUNK_XMP, // XMP
+ WEBP_CHUNK_UNKNOWN, // Other chunks.
WEBP_CHUNK_NIL
} WebPChunkId;
@@ -142,7 +142,7 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream,
// Non-image chunks.
// Note: Only non-image related chunks should be managed through chunk APIs.
-// (Image related chunks are: "ANMF", "FRGM", "VP8 ", "VP8L" and "ALPH").
+// (Image related chunks are: "ANMF", "VP8 ", "VP8L" and "ALPH").
// To add, get and delete images, use WebPMuxSetImage(), WebPMuxPushFrame(),
// WebPMuxGetFrame() and WebPMuxDeleteFrame().
@@ -195,7 +195,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk(
//------------------------------------------------------------------------------
// Images.
-// Encapsulates data about a single frame/fragment.
+// Encapsulates data about a single frame.
struct WebPMuxFrameInfo {
WebPData bitstream; // image data: can be a raw VP8/VP8L bitstream
// or a single-image WebP file.
@@ -203,19 +203,19 @@ struct WebPMuxFrameInfo {
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
+ WebPChunkId id; // frame type: should be one of WEBP_CHUNK_ANMF
+ // 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.
+// Sets the (non-animated) image in the mux object.
+// Note: Any existing images (including frames) will be removed.
// Parameters:
// 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)
+// WebP file (non-animated)
// 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:
@@ -226,9 +226,8 @@ 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.
+// Notes: (1) frame.id should be WEBP_CHUNK_ANMF
+// (2) For setting a non-animated 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
@@ -431,9 +430,10 @@ struct WebPAnimEncoderOptions {
// 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.
+ // and kmin >= kmax / 2 + 1. Also, if kmax <= 0, then
+ // key-frame insertion is disabled; and if kmax == 1,
+ // then all frames will be key-frames (kmin value does
+ // not matter for these special cases).
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.
diff --git a/thirdparty/libwebp/webp/mux_types.h b/thirdparty/libwebp/webp/mux_types.h
index c94043a3c0..b37e2c67aa 100644
--- a/thirdparty/libwebp/webp/mux_types.h
+++ b/thirdparty/libwebp/webp/mux_types.h
@@ -31,12 +31,13 @@ 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
+ ICCP_FLAG = 0x00000020,
+
+ ALL_VALID_FLAGS = 0x0000003e
} WebPFeatureFlags;
// Dispose method (animation only). Indicates how the area used by the current
diff --git a/tools/editor/SCsub b/tools/editor/SCsub
deleted file mode 100644
index 710dac3ea7..0000000000
--- a/tools/editor/SCsub
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/usr/bin/env python
-
-Import('env')
-env.editor_sources = []
-
-
-def make_certs_header(target, source, env):
-
- src = source[0].srcnode().abspath
- dst = target[0].srcnode().abspath
- f = open(src, "rb")
- g = open(dst, "wb")
- buf = f.read()
- decomp_size = len(buf)
- import zlib
- buf = zlib.compress(buf)
-
- g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
- g.write("#ifndef _CERTS_RAW_H\n")
- g.write("#define _CERTS_RAW_H\n")
- g.write("static const int _certs_compressed_size=" + str(len(buf)) + ";\n")
- g.write("static const int _certs_uncompressed_size=" + str(decomp_size) + ";\n")
- g.write("static const unsigned char _certs_compressed[]={\n")
- for i in range(len(buf)):
- g.write(str(ord(buf[i])) + ",\n")
- g.write("};\n")
- g.write("#endif")
-
-
-def make_doc_header(target, source, env):
-
- src = source[0].srcnode().abspath
- dst = target[0].srcnode().abspath
- f = open(src, "rb")
- g = open(dst, "wb")
- buf = f.read()
- decomp_size = len(buf)
- import zlib
- buf = zlib.compress(buf)
-
- g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
- g.write("#ifndef _DOC_DATA_RAW_H\n")
- g.write("#define _DOC_DATA_RAW_H\n")
- g.write("static const int _doc_data_compressed_size=" + str(len(buf)) + ";\n")
- g.write("static const int _doc_data_uncompressed_size=" + str(decomp_size) + ";\n")
- g.write("static const unsigned char _doc_data_compressed[]={\n")
- for i in range(len(buf)):
- g.write(str(ord(buf[i])) + ",\n")
- g.write("};\n")
- g.write("#endif")
-
-
-def make_fonts_header(target, source, env):
-
- dst = target[0].srcnode().abspath
-
- g = open(dst, "wb")
-
- g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
- g.write("#ifndef _EDITOR_FONTS_H\n")
- g.write("#define _EDITOR_FONTS_H\n")
-
- # saving uncompressed, since freetype will reference from memory pointer
- xl_names = []
- for i in range(len(source)):
- print("Appending font: " + source[i].srcnode().abspath)
- f = open(source[i].srcnode().abspath, "rb")
- buf = f.read()
- import os.path
-
- name = os.path.splitext(os.path.basename(source[i].srcnode().abspath))[0]
-
- g.write("static const int _font_" + name + "_size=" + str(len(buf)) + ";\n")
- g.write("static const unsigned char _font_" + name + "[]={\n")
- for i in range(len(buf)):
- g.write(str(ord(buf[i])) + ",\n")
-
- g.write("};\n")
-
- g.write("#endif")
-
-
-def make_translations_header(target, source, env):
-
- dst = target[0].srcnode().abspath
-
- g = open(dst, "wb")
-
- g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
- g.write("#ifndef _EDITOR_TRANSLATIONS_H\n")
- g.write("#define _EDITOR_TRANSLATIONS_H\n")
-
- import zlib
- import os.path
-
- paths = [node.srcnode().abspath for node in source]
- sorted_paths = sorted(paths, key=lambda path: os.path.splitext(os.path.basename(path))[0])
-
- xl_names = []
- for i in range(len(sorted_paths)):
- print("Appending translation: " + sorted_paths[i])
- f = open(sorted_paths[i], "rb")
- buf = f.read()
- decomp_size = len(buf)
- buf = zlib.compress(buf)
- name = os.path.splitext(os.path.basename(sorted_paths[i]))[0]
-
- #g.write("static const int _translation_"+name+"_compressed_size="+str(len(buf))+";\n")
- #g.write("static const int _translation_"+name+"_uncompressed_size="+str(decomp_size)+";\n")
- g.write("static const unsigned char _translation_" + name + "_compressed[]={\n")
- for i in range(len(buf)):
- g.write(str(ord(buf[i])) + ",\n")
-
- g.write("};\n")
-
- xl_names.append([name, len(buf), str(decomp_size)])
-
- g.write("struct EditorTranslationList {\n")
- g.write("\tconst char* lang;\n")
- g.write("\tint comp_size;\n")
- g.write("\tint uncomp_size;\n")
- g.write("\tconst unsigned char* data;\n")
- g.write("};\n\n")
- g.write("static EditorTranslationList _editor_translations[]={\n")
- for x in xl_names:
- g.write("\t{ \"" + x[0] + "\", " + str(x[1]) + ", " + str(x[2]) + ",_translation_" + x[0] + "_compressed},\n")
- g.write("\t{NULL,0,0,NULL}\n")
- g.write("};\n")
-
- g.write("#endif")
-
-
-if (env["tools"] == "yes"):
-
- # Register exporters
- reg_exporters_inc = '#include "register_exporters.h"\n'
- reg_exporters = 'void register_exporters() {\n'
- for e in env.platform_exporters:
- env.editor_sources.append("#platform/" + e + "/export/export.cpp")
- reg_exporters += '\t//register_' + e + '_exporter();\n'
- reg_exporters_inc += '#include "platform/' + e + '/export/export.h"\n'
- reg_exporters += '}\n'
- f = open("register_exporters.cpp", "wb")
- f.write(reg_exporters_inc)
- f.write(reg_exporters)
- f.close()
-
- # API documentation
- env.Depends("#tools/editor/doc_data_compressed.h", "#doc/base/classes.xml")
- env.Command("#tools/editor/doc_data_compressed.h", "#doc/base/classes.xml", make_doc_header)
-
- # Certificates
- env.Depends("#tools/editor/certs_compressed.h", "#thirdparty/certs/ca-certificates.crt")
- env.Command("#tools/editor/certs_compressed.h", "#thirdparty/certs/ca-certificates.crt", make_certs_header)
-
- import glob
- path = env.Dir('.').abspath
-
- # Translations
- tlist = glob.glob(path + "/translations/*.po")
- print("translations: ", tlist)
- env.Depends('#tools/editor/translations.h', tlist)
- env.Command('#tools/editor/translations.h', tlist, make_translations_header)
-
- # Fonts
- flist = glob.glob(path + "/../../thirdparty/fonts/*.ttf")
- flist.append(glob.glob(path + "/../../thirdparty/fonts/*.otf"))
- print("fonts: ", flist)
- env.Depends('#tools/editor/builtin_fonts.h', flist)
- env.Command('#tools/editor/builtin_fonts.h', flist, make_fonts_header)
-
-
- env.add_source_files(env.editor_sources, "*.cpp")
-
- SConscript('collada/SCsub')
- SConscript('doc/SCsub')
- SConscript('fileserver/SCsub')
- SConscript('icons/SCsub')
- SConscript('import/SCsub')
- SConscript('io_plugins/SCsub')
- SConscript('plugins/SCsub')
-
- lib = env.Library("editor", env.editor_sources)
- env.Prepend(LIBS=[lib])
-
- Export('env')
diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp
deleted file mode 100644
index f256e351ae..0000000000
--- a/tools/editor/animation_editor.cpp
+++ /dev/null
@@ -1,4331 +0,0 @@
-/*************************************************************************/
-/* animation_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "animation_editor.h"
-
-#include "editor_settings.h"
-#include "os/keyboard.h"
-#include "os/os.h"
-#include "io/resource_saver.h"
-#include "pair.h"
-#include "scene/gui/separator.h"
-#include "editor_node.h"
-#include "tools/editor/plugins/animation_player_editor_plugin.h"
-#include "scene/main/viewport.h"
-/* Missing to fix:
-
- *Set
- *Find better source for hint for edited value keys
- * + button on track to add a key
- * when clicked for first time, erase selection of not selected at first
- * automatically create discrete/continuous tracks!!
- *when create track do undo/redo
-*/
-
-
-class AnimationCurveEdit : public Control {
- GDCLASS( AnimationCurveEdit, Control );
-public:
- enum Mode {
- MODE_DISABLED,
- MODE_SINGLE,
- MODE_MULTIPLE
- };
-private:
-
- Set<float> multiples;
- float transition;
- Mode mode;
-
- void _notification(int p_what) {
-
- if (p_what==NOTIFICATION_DRAW) {
-
-
- RID ci = get_canvas_item();
-
- Size2 s = get_size();
- Rect2 r(Point2(),s);
-
- //r=r.grow(3);
- Ref<StyleBox> sb = get_stylebox("normal","LineEdit");
- sb->draw(ci,r);
- r.size-=sb->get_minimum_size();
- r.pos+=sb->get_offset();
- //VisualServer::get_singleton()->canvas_item_add
-
- Ref<Font> f = get_font("font","Label");
- r=r.grow(-2);
- Color color = get_color("font_color","Label");
-
- int points = 48;
- if (mode==MODE_MULTIPLE) {
-
- Color mcolor=color;
- mcolor.a*=0.3;
-
- Set<float>::Element *E=multiples.front();
- for(int j=0;j<16;j++) {
-
- if (!E)
- break;
-
- float prev=1.0;
- float exp=E->get();
- bool flip=false;//hint_text=="attenuation";
-
-
- for(int i=1;i<=points;i++) {
-
- float ifl = i/float(points);
- float iflp = (i-1)/float(points);
-
- float h = 1.0-Math::ease(ifl,exp);
-
- if (flip) {
- ifl=1.0-ifl;
- iflp=1.0-iflp;
- }
-
- VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),mcolor);
- prev=h;
- }
-
- E=E->next();
- }
- }
-
- float exp=transition;
- if (mode!=MODE_DISABLED) {
-
-
- float prev=1.0;
-
- bool flip=false;//hint_text=="attenuation";
-
-
- for(int i=1;i<=points;i++) {
-
- float ifl = i/float(points);
- float iflp = (i-1)/float(points);
-
- float h = 1.0-Math::ease(ifl,exp);
-
- if (flip) {
- ifl=1.0-ifl;
- iflp=1.0-iflp;
- }
-
- VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),color);
- prev=h;
- }
- }
-
- String txt=String::num(exp,2);
- if (mode==MODE_DISABLED) {
- txt=TTR("Disabled");
- } else if (mode==MODE_MULTIPLE) {
- txt+=" - "+TTR("All Selection");
- }
-
- f->draw(ci,Point2(10,10+f->get_ascent()),txt,color);
-
- }
- }
-
- void _gui_input(const InputEvent& p_ev) {
- if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
-
- if (mode==MODE_DISABLED)
- return;
-
- float rel = p_ev.mouse_motion.relative_x;
- if (rel==0)
- return;
-
- bool flip=false;
-
- if (flip)
- rel=-rel;
-
- float val = transition;
- if (val==0)
- return;
- bool sg = val < 0;
- val = Math::absf(val);
-
- val = Math::log(val)/Math::log((float)2.0);
- //logspace
- val+=rel*0.05;
- //
-
- val = Math::pow((float)2.0,val);
- if (sg)
- val=-val;
-
- transition=val;
- update();
- //emit_signal("variant_changed");
- emit_signal("transition_changed",transition);
- }
- }
-
-public:
-
- static void _bind_methods() {
-
- //ClassDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj);
- ClassDB::bind_method("_gui_input",&AnimationCurveEdit::_gui_input);
- ADD_SIGNAL(MethodInfo("transition_changed"));
- }
-
- void set_mode(Mode p_mode) {
-
- mode=p_mode;
- update();
- }
-
- void clear_multiples() { multiples.clear(); update();}
- void set_multiple(float p_transition) {
-
- multiples.insert(p_transition);
- }
-
- void set_transition(float p_transition) {
- transition=p_transition;
- update();
- }
-
- float get_transition() const {
- return transition;
- }
-
- void force_transition(float p_value) {
- if (mode==MODE_DISABLED)
- return;
- transition=p_value;
- emit_signal("transition_changed",p_value);
- update();
- }
-
- AnimationCurveEdit() {
-
- transition=1.0;
- set_default_cursor_shape(CURSOR_HSPLIT);
- mode=MODE_DISABLED;
- }
-
-};
-
-class AnimationKeyEdit : public Object {
-
- GDCLASS(AnimationKeyEdit,Object);
-public:
- bool setting;
- bool hidden;
-
- static void _bind_methods() {
-
- ClassDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj);
- ClassDB::bind_method("_key_ofs_changed",&AnimationKeyEdit::_key_ofs_changed);
- }
-
- //PopupDialog *ke_dialog;
-
- void _fix_node_path(Variant &value) {
-
-
- NodePath np=value;
-
- if (np==NodePath())
- return;
-
- Node* root = EditorNode::get_singleton()->get_tree()->get_root();
-
- Node* np_node = root->get_node(np);
- ERR_FAIL_COND(!np_node);
-
- Node* edited_node = root->get_node(base);
- ERR_FAIL_COND(!edited_node);
-
-
-
- value = edited_node->get_path_to(np_node);
- }
-
-
- void _update_obj(const Ref<Animation> &p_anim) {
- if (setting)
- return;
- if (hidden)
- return;
- if (!(animation==p_anim))
- return;
- notify_change();
- }
-
- void _key_ofs_changed(const Ref<Animation> &p_anim,float from, float to) {
- if (hidden)
- return;
- if (!(animation==p_anim))
- return;
- if (from!=key_ofs)
- return;
- key_ofs=to;
- if (setting)
- return;
- notify_change();
- }
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- int key = animation->track_find_key(track,key_ofs,true);
- ERR_FAIL_COND_V(key==-1,false);
-
- String name=p_name;
- if (name=="time") {
-
- float new_time = p_value;
- if (new_time==key_ofs)
- return true;
-
- int existing = animation->track_find_key(track,new_time,true);
-
- setting=true;
- undo_redo->create_action(TTR("Move Add Key"),UndoRedo::MERGE_ENDS);
-
- Variant val = animation->track_get_key_value(track,key);
- float trans = animation->track_get_key_transition(track,key);
-
- undo_redo->add_do_method(animation.ptr(),"track_remove_key",track,key);
- undo_redo->add_do_method(animation.ptr(),"track_insert_key",track,new_time,val,trans);
- undo_redo->add_do_method(this,"_key_ofs_changed",animation,key_ofs,new_time);
- undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",track,new_time);
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",track,key_ofs,val,trans);
- undo_redo->add_undo_method(this,"_key_ofs_changed",animation,new_time,key_ofs);
-
-
- if (existing!=-1) {
- Variant v = animation->track_get_key_value(track,existing);
- float trans = animation->track_get_key_transition(track,existing);
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",track,new_time,v,trans);
- }
-
- undo_redo->commit_action();
- setting=false;
-
- return true;
- } else if (name=="easing") {
-
- float val = p_value;
- float prev_val = animation->track_get_key_transition(track,key);
- setting=true;
- undo_redo->create_action(TTR("Anim Change Transition"),UndoRedo::MERGE_ENDS);
- undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,val);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val);
- undo_redo->add_do_method(this,"_update_obj",animation);
- undo_redo->add_undo_method(this,"_update_obj",animation);
- undo_redo->commit_action();
- setting=false;
- return true;
- }
-
-
-
- switch(animation->track_get_type(track)) {
-
-
- case Animation::TYPE_TRANSFORM: {
-
- Dictionary d_old = animation->track_get_key_value(track,key);
- Dictionary d_new = d_old;
- d_new[p_name]=p_value;
- setting=true;
- undo_redo->create_action(TTR("Anim Change Transform"));
- undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,d_new);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,d_old);
- undo_redo->add_do_method(this,"_update_obj",animation);
- undo_redo->add_undo_method(this,"_update_obj",animation);
- undo_redo->commit_action();
- setting=false;
- return true;
-
- } break;
- case Animation::TYPE_VALUE: {
-
- if (name=="value") {
-
- Variant value = p_value;
-
- if (value.get_type()==Variant::NODE_PATH) {
-
- _fix_node_path(value);
- }
-
- setting=true;
- undo_redo->create_action(TTR("Anim Change Value"),UndoRedo::MERGE_ENDS);
- Variant prev = animation->track_get_key_value(track,key);
- undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,value);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,prev);
- undo_redo->add_do_method(this,"_update_obj",animation);
- undo_redo->add_undo_method(this,"_update_obj",animation);
- undo_redo->commit_action();
- setting=false;
- return true;
- }
-
-
-
- } break;
- case Animation::TYPE_METHOD: {
-
- Dictionary d_old = animation->track_get_key_value(track,key);
- Dictionary d_new = d_old;
-
- bool change_notify_deserved=false;
- bool mergeable=false;
-
- if (name=="name") {
-
- d_new["method"]=p_value;
-
- }
-
- if (name=="arg_count") {
-
- Vector<Variant> args = d_old["args"];
- args.resize(p_value);
- d_new["args"]=args;
- change_notify_deserved=true;
- }
-
- if (name.begins_with("args/")) {
-
-
- Vector<Variant> args = d_old["args"];
- int idx = name.get_slice("/",1).to_int();
- ERR_FAIL_INDEX_V(idx,args.size(),false);
-
- String what = name.get_slice("/",2);
- if (what=="type") {
- Variant::Type t = Variant::Type(int(p_value));
-
- if (t!=args[idx].get_type()) {
- Variant::CallError err;
- if (Variant::can_convert(args[idx].get_type(),t)) {
- Variant old=args[idx];
- Variant *ptrs[1]={&old};
- args[idx]=Variant::construct(t,(const Variant**)ptrs,1,err);
- } else {
-
- args[idx]=Variant::construct(t,NULL,0,err);
- }
- change_notify_deserved=true;
- d_new["args"]=args;
- }
-
- }
- if (what=="value") {
-
- Variant value=p_value;
- if (value.get_type()==Variant::NODE_PATH) {
-
- _fix_node_path(value);
- }
-
- args[idx]=value;
- d_new["args"]=args;
- mergeable=true;
- }
- }
-
- if (mergeable)
- undo_redo->create_action(TTR("Anim Change Call"),UndoRedo::MERGE_ENDS);
- else
- undo_redo->create_action(TTR("Anim Change Call"));
-
- Variant prev = animation->track_get_key_value(track,key);
- setting=true;
- undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,d_new);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,d_old);
- undo_redo->add_do_method(this,"_update_obj",animation);
- undo_redo->add_undo_method(this,"_update_obj",animation);
- undo_redo->commit_action();
- setting=false;
- if (change_notify_deserved)
- notify_change();
- return true;
- } break;
- }
-
-
-
- return false;
-
- }
-
- bool _get(const StringName& p_name,Variant &r_ret) const {
-
- int key = animation->track_find_key(track,key_ofs,true);
- ERR_FAIL_COND_V(key==-1,false);
-
- String name=p_name;
- if (name=="time") {
- r_ret = key_ofs;
- return true;
- } else if (name=="easing") {
- r_ret = animation->track_get_key_transition(track,key);
- return true;
- }
-
-
-
- switch(animation->track_get_type(track)) {
-
-
- case Animation::TYPE_TRANSFORM: {
-
- Dictionary d = animation->track_get_key_value(track,key);
- ERR_FAIL_COND_V(!d.has(name),false);
- r_ret = d[p_name];
- return true;
-
- } break;
- case Animation::TYPE_VALUE: {
-
- if (name=="value") {
- r_ret = animation->track_get_key_value(track,key);
- return true;
- }
-
-
-
- } break;
- case Animation::TYPE_METHOD: {
-
- Dictionary d = animation->track_get_key_value(track,key);
-
- if (name=="name") {
-
- ERR_FAIL_COND_V(!d.has("method"),false);
- r_ret=d["method"];
- return true;
- }
-
- ERR_FAIL_COND_V(!d.has("args"),false);
-
- Vector<Variant> args = d["args"];
-
-
- if (name=="arg_count") {
-
- r_ret=args.size();
- return true;
- }
-
-
- if (name.begins_with("args/")) {
-
- int idx = name.get_slice("/",1).to_int();
- ERR_FAIL_INDEX_V(idx,args.size(),false);
-
- String what = name.get_slice("/",2);
- if (what=="type") {
- r_ret=args[idx].get_type();
- return true;
- }
- if (what=="value") {
- r_ret=args[idx];
- return true;
- }
- }
-
- } break;
- }
-
- return false;
- }
- void _get_property_list( List<PropertyInfo> *p_list) const {
-
- if (animation.is_null())
- return;
-
- ERR_FAIL_INDEX(track,animation->get_track_count());
- int key = animation->track_find_key(track,key_ofs,true);
- ERR_FAIL_COND(key==-1);
-
- p_list->push_back( PropertyInfo( Variant::REAL, "time", PROPERTY_HINT_RANGE,"0,"+rtos(animation->get_length())+",0.01") );
-
- switch(animation->track_get_type(track)) {
-
-
- case Animation::TYPE_TRANSFORM: {
-
- p_list->push_back( PropertyInfo( Variant::VECTOR3, "loc"));
- p_list->push_back( PropertyInfo( Variant::QUAT, "rot"));
- p_list->push_back( PropertyInfo( Variant::VECTOR3, "scale"));
-
- } break;
- case Animation::TYPE_VALUE: {
-
- Variant v = animation->track_get_key_value(track,key);
-
-
-
- if (hint.type!=Variant::NIL) {
-
- PropertyInfo pi=hint;
- pi.name="value";
- p_list->push_back( pi );
- } else {
-
- PropertyHint hint= PROPERTY_HINT_NONE;
- String hint_string;
-
- if (v.get_type()==Variant::OBJECT) {
- //could actually check the object property if exists..? yes i will!
- Ref<Resource> res = v;
- if (res.is_valid()) {
-
- hint=PROPERTY_HINT_RESOURCE_TYPE;
- hint_string=res->get_class();
- }
- }
-
- if (v.get_type()!=Variant::NIL)
- p_list->push_back( PropertyInfo( v.get_type(), "value", hint,hint_string));
- }
-
- } break;
- case Animation::TYPE_METHOD: {
-
- p_list->push_back( PropertyInfo( Variant::STRING, "name"));
- p_list->push_back( PropertyInfo( Variant::INT, "arg_count",PROPERTY_HINT_RANGE,"0,5,1"));
-
- Dictionary d = animation->track_get_key_value(track,key);
- ERR_FAIL_COND(!d.has("args"));
- Vector<Variant> args=d["args"];
- String vtypes;
- for(int i=0;i<Variant::VARIANT_MAX;i++) {
-
- if (i>0)
- vtypes+=",";
- vtypes+=Variant::get_type_name( Variant::Type(i) );
- }
-
- for(int i=0;i<args.size();i++) {
-
- p_list->push_back( PropertyInfo( Variant::INT, "args/"+itos(i)+"/type", PROPERTY_HINT_ENUM,vtypes));
- if (args[i].get_type()!=Variant::NIL)
- p_list->push_back( PropertyInfo( args[i].get_type(), "args/"+itos(i)+"/value"));
- }
-
- } break;
- }
-
- /*
- if (animation->track_get_type(track)!=Animation::TYPE_METHOD)
- p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING));
- */
- }
-
- UndoRedo *undo_redo;
- Ref<Animation> animation;
- int track;
- float key_ofs;
-
- PropertyInfo hint;
- NodePath base;
-
-
- void notify_change() {
-
- _change_notify();
- }
-
- AnimationKeyEdit() { hidden=true; key_ofs=0; track=-1; setting=false; }
-
-};
-
-
-void AnimationKeyEditor::_menu_add_track(int p_type) {
-
- ERR_FAIL_COND(!animation.is_valid());
-
-
- switch(p_type) {
-
- case ADD_TRACK_MENU_ADD_CALL_TRACK: {
- if (root) {
- call_select->popup_centered_ratio();
- break;
- }
- } break;
- case ADD_TRACK_MENU_ADD_VALUE_TRACK:
- case ADD_TRACK_MENU_ADD_TRANSFORM_TRACK: {
-
- undo_redo->create_action(TTR("Anim Add Track"));
- undo_redo->add_do_method(animation.ptr(),"add_track",p_type);
- undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),".");
- undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
- undo_redo->commit_action();
-
-
- } break;
- }
-}
-
-void AnimationKeyEditor::_anim_duplicate_keys(bool transpose) {
- //duplicait!
- if (selection.size() && animation.is_valid() && selected_track>=0 && selected_track<animation->get_track_count()) {
-
- int top_track=0x7FFFFFFF;
- float top_time = 1e10;
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- const SelectedKey &sk = E->key();
-
- float t = animation->track_get_key_time(sk.track,sk.key);
- if (t<top_time)
- top_time=t;
- if (sk.track<top_track)
- top_track=sk.track;
-
- }
- ERR_FAIL_COND( top_track == 0x7FFFFFFF || top_time==1e10 );
-
- //
-
- int start_track = transpose ? selected_track : top_track;
-
- undo_redo->create_action(TTR("Anim Duplicate Keys"));
-
- List<Pair<int,float> > new_selection_values;
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- const SelectedKey &sk = E->key();
-
- float t = animation->track_get_key_time(sk.track,sk.key);
-
- float dst_time = t+(timeline_pos - top_time);
- int dst_track = sk.track + (start_track - top_track);
-
- if (dst_track < 0 || dst_track>= animation->get_track_count())
- continue;
-
- if (animation->track_get_type(dst_track) != animation->track_get_type(sk.track))
- continue;
-
- int existing_idx = animation->track_find_key(dst_track,dst_time,true);
-
- undo_redo->add_do_method(animation.ptr(),"track_insert_key",dst_track,dst_time,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
- undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",dst_track,dst_time);
-
- Pair<int,float> p;
- p.first=dst_track;
- p.second=dst_time;
- new_selection_values.push_back( p );
-
- if (existing_idx!=-1) {
-
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",dst_track,dst_time,animation->track_get_key_value(dst_track,existing_idx),animation->track_get_key_transition(dst_track,existing_idx));
-
- }
-
- }
-
- undo_redo->commit_action();
-
- //reselect duplicated
-
- Map<SelectedKey,KeyInfo> new_selection;
- for (List<Pair<int,float> >::Element *E=new_selection_values.front();E;E=E->next()) {
-
- int track=E->get().first;
- float time = E->get().second;
-
- int existing_idx = animation->track_find_key(track,time,true);
-
- if (existing_idx==-1)
- continue;
- SelectedKey sk2;
- sk2.track=track;
- sk2.key=existing_idx;
-
- KeyInfo ki;
- ki.pos=time;
-
- new_selection[sk2]=ki;
-
- }
-
-
- selection=new_selection;
- track_editor->update();
- _edit_if_single_selection();
-
- }
-}
-
-void AnimationKeyEditor::_menu_track(int p_type) {
-
- ERR_FAIL_COND(!animation.is_valid());
-
- last_menu_track_opt=p_type;
- switch(p_type) {
-
- case TRACK_MENU_SCALE:
- case TRACK_MENU_SCALE_PIVOT: {
-
- scale_dialog->popup_centered(Size2(200,100));
- } break;
- case TRACK_MENU_MOVE_UP: {
-
- int idx=selected_track;
- if (idx>0 && idx<animation->get_track_count()) {
- undo_redo->create_action(TTR("Move Anim Track Up"));
- undo_redo->add_do_method(animation.ptr(),"track_move_down",idx);
- undo_redo->add_undo_method(animation.ptr(),"track_move_up",idx-1);
- undo_redo->commit_action();
- selected_track=idx-1;
- }
-
- } break;
- case TRACK_MENU_MOVE_DOWN: {
-
-
- int idx=selected_track;
- if (idx>=0 && idx<animation->get_track_count()-1) {
- undo_redo->create_action(TTR("Move Anim Track Down"));
- undo_redo->add_do_method(animation.ptr(),"track_move_up",idx);
- undo_redo->add_undo_method(animation.ptr(),"track_move_down",idx+1);
- undo_redo->commit_action();
- selected_track=idx+1;
- }
-
- } break;
- case TRACK_MENU_REMOVE: {
-
- int idx=selected_track;
- if (idx>=0 && idx<animation->get_track_count()) {
- undo_redo->create_action(TTR("Remove Anim Track"));
- undo_redo->add_do_method(animation.ptr(),"remove_track",idx);
- undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(idx),idx);
- undo_redo->add_undo_method(animation.ptr(),"track_set_path",idx,animation->track_get_path(idx));
- //todo interpolation
- for(int i=0;i<animation->track_get_key_count(idx);i++) {
-
- Variant v = animation->track_get_key_value(idx,i);
- float time = animation->track_get_key_time(idx,i);
- float trans = animation->track_get_key_transition(idx,i);
-
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,time,v);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",idx,i,trans);
-
- }
-
- undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",idx,animation->track_get_interpolation_type(idx));
- if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
- undo_redo->add_undo_method(animation.ptr(),"value_track_set_update_mode",idx,animation->value_track_get_update_mode(idx));
-
- }
-
- undo_redo->commit_action();
- }
-
-
- } break;
- case TRACK_MENU_DUPLICATE:
- case TRACK_MENU_DUPLICATE_TRANSPOSE: {
-
- _anim_duplicate_keys(p_type==TRACK_MENU_DUPLICATE_TRANSPOSE);
- } break;
- case TRACK_MENU_SET_ALL_TRANS_LINEAR:
- case TRACK_MENU_SET_ALL_TRANS_CONSTANT:
- case TRACK_MENU_SET_ALL_TRANS_OUT:
- case TRACK_MENU_SET_ALL_TRANS_IN:
- case TRACK_MENU_SET_ALL_TRANS_INOUT:
- case TRACK_MENU_SET_ALL_TRANS_OUTIN: {
-
- if (!selection.size() || !animation.is_valid())
- break;
-
- float t=0;
- switch(p_type) {
- case TRACK_MENU_SET_ALL_TRANS_LINEAR: t=1.0; break;
- case TRACK_MENU_SET_ALL_TRANS_CONSTANT: t=0.0; break;
- case TRACK_MENU_SET_ALL_TRANS_OUT: t=0.5; break;
- case TRACK_MENU_SET_ALL_TRANS_IN: t=2.0; break;
- case TRACK_MENU_SET_ALL_TRANS_INOUT: t=-0.5; break;
- case TRACK_MENU_SET_ALL_TRANS_OUTIN: t=-2.0; break;
- }
-
- undo_redo->create_action(TTR("Set Transitions to:")+" "+rtos(t));
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- const SelectedKey &sk = E->key();
-
- undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",sk.track,sk.key,t);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",sk.track,sk.key,animation->track_get_key_transition(sk.track,sk.key));
-
- }
-
- undo_redo->commit_action();
-
- } break;
- case TRACK_MENU_NEXT_STEP: {
-
- if (animation.is_null())
- break;
- float step = animation->get_step();
- if (step==0)
- step=1;
-
- float pos=timeline_pos;
-
- pos=Math::stepify(pos+step,step);
- if (pos>animation->get_length())
- pos=animation->get_length();
- timeline_pos=pos;
- track_pos->update();
- emit_signal("timeline_changed",pos,true);
-
- } break;
- case TRACK_MENU_PREV_STEP: {
- if (animation.is_null())
- break;
- float step = animation->get_step();
- if (step==0)
- step=1;
-
- float pos=timeline_pos;
- pos=Math::stepify(pos-step,step);
- if (pos<0)
- pos=0;
- timeline_pos=pos;
- track_pos->update();
- emit_signal("timeline_changed",pos,true);
-
-
- } break;
-
- case TRACK_MENU_OPTIMIZE: {
-
- 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);
-
- } break;
- case CURVE_SET_IN: {
-
- curve_edit->force_transition(4.0);
-
- } break;
- case CURVE_SET_OUT: {
-
- curve_edit->force_transition(0.25);
- } break;
- case CURVE_SET_INOUT: {
- curve_edit->force_transition(-4);
-
- } break;
- case CURVE_SET_OUTIN: {
-
- curve_edit->force_transition(-0.25);
- } break;
- case CURVE_SET_CONSTANT: {
-
- curve_edit->force_transition(0);
- } break;
-
- }
-
-}
-
-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() {
-
-
-
- animation->optimize(optimize_linear_error->get_value(),optimize_angular_error->get_value(),optimize_max_angle->get_value());
- track_editor->update();
- undo_redo->clear_history();
-
-}
-
-
-float AnimationKeyEditor::_get_zoom_scale() const {
-
- float zv = zoom->get_value();
- if (zv<1) {
- zv = 1.0-zv;
- return Math::pow(1.0f+zv,8.0f)*100;
- } else {
- return 1.0/Math::pow(zv,8.0f)*100;
- }
-}
-
-void AnimationKeyEditor::_track_pos_draw() {
-
- if (!animation.is_valid()) {
- return;
- }
-
-
- Ref<StyleBox> style = get_stylebox("normal","TextEdit");
- Size2 size= track_editor->get_size() - style->get_minimum_size();
- Size2 ofs = style->get_offset();
-
- int settings_limit = size.width - right_data_size_cache;
- int name_limit = settings_limit * name_column_ratio;
-
- float keys_from= h_scroll->get_value();
- float zoom_scale = _get_zoom_scale();
- float keys_to=keys_from+(settings_limit-name_limit) / zoom_scale;
-
-
-
- //will move to separate control! (for speedup)
- if (timeline_pos >= keys_from && timeline_pos<keys_to) {
- //draw position
- int pixel = (timeline_pos - h_scroll->get_value()) * zoom_scale;
- pixel+=name_limit;
- track_pos->draw_line(ofs+Point2(pixel,0),ofs+Point2(pixel,size.height),Color(1,0.3,0.3,0.8));
-
- }
-}
-
-void AnimationKeyEditor::_track_editor_draw() {
-
-
- if (animation.is_valid() && animation->get_track_count()) {
- if (selected_track < 0)
- selected_track=0;
- else if (selected_track>=animation->get_track_count())
- selected_track=animation->get_track_count()-1;
- }
-
- track_pos->update();
- Control *te=track_editor;
- Ref<StyleBox> style = get_stylebox("normal","TextEdit");
- te->draw_style_box(style,Rect2(Point2(),track_editor->get_size()));
-
- if (te->has_focus()) {
- te->draw_style_box(get_stylebox("bg_focus","Tree"),Rect2(Point2(),track_editor->get_size()));
- }
-
- if (!animation.is_valid()) {
- v_scroll->hide();
- h_scroll->hide();
- menu_add_track->set_disabled(true);
- menu_track->set_disabled(true);
- edit_button->set_disabled(true);
- key_editor_tab->hide();
- move_up_button->set_disabled(true);
- move_down_button->set_disabled(true);
- remove_button->set_disabled(true);
-
- return;
- }
-
- menu_add_track->set_disabled(false);
- menu_track->set_disabled(false);
- edit_button->set_disabled(false);
- move_up_button->set_disabled(false);
- move_down_button->set_disabled(false);
- remove_button->set_disabled(false);
- if (edit_button->is_pressed())
- key_editor_tab->show();
-
- te_drawing=true;
-
- Size2 size= te->get_size() - style->get_minimum_size();
- Size2 ofs = style->get_offset();
-
- Ref<Font> font = te->get_font("font","Tree");
- int sep = get_constant("vseparation","Tree");
- int hsep = get_constant("hseparation","Tree");
- Color color = get_color("font_color","Tree");
- Color sepcolor = get_color("guide_color","Tree");
- Color timecolor = get_color("prop_subsection","Editor");
- 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");
- Ref<Texture> move_up_icon = get_icon("MoveUp","EditorIcons");
- Ref<Texture> move_down_icon = get_icon("MoveDown","EditorIcons");
- Ref<Texture> remove_icon_hl = get_icon("RemoveHl","EditorIcons");
- Ref<Texture> move_up_icon_hl = get_icon("MoveUpHl","EditorIcons");
- Ref<Texture> move_down_icon_hl = get_icon("MoveDownHl","EditorIcons");
- Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
- Ref<Texture> add_key_icon_hl = get_icon("TrackAddKeyHl","EditorIcons");
- Ref<Texture> down_icon = get_icon("select_arrow","Tree");
-
- Ref<Texture> wrap_icon[2]={
- get_icon("InterpWrapClamp","EditorIcons"),
- get_icon("InterpWrapLoop","EditorIcons"),
- };
-
- Ref<Texture> interp_icon[3]={
- get_icon("InterpRaw","EditorIcons"),
- get_icon("InterpLinear","EditorIcons"),
- get_icon("InterpCubic","EditorIcons")
- };
- Ref<Texture> cont_icon[3]={
- get_icon("TrackContinuous","EditorIcons"),
- get_icon("TrackDiscrete","EditorIcons"),
- get_icon("TrackTrigger","EditorIcons")
- };
- Ref<Texture> type_icon[3]={
- get_icon("KeyValue","EditorIcons"),
- get_icon("KeyXform","EditorIcons"),
- 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");
- Ref<Texture> type_selected=get_icon("KeySelected","EditorIcons");
-
- int right_separator_ofs = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*9;
-
- int h = font->get_height()+sep;
-
-
- int fit = (size.height / h)-1;
- int total = animation->get_track_count();
- if (total < fit) {
- v_scroll->hide();
- v_scroll->set_max( total );
- v_scroll->set_page( fit );
- } else {
- v_scroll->show();
- v_scroll->set_max( total );
- v_scroll->set_page( fit );
- }
-
-
- int settings_limit = size.width - right_separator_ofs;
- int name_limit = settings_limit * name_column_ratio;
-
- te->draw_line(ofs+Point2(name_limit,0),ofs+Point2(name_limit,size.height),color);
- te->draw_line(ofs+Point2(settings_limit,0),ofs+Point2(settings_limit,size.height),color);
- te->draw_texture(hsize_icon,ofs+Point2(name_limit-hsize_icon->get_width()-hsep,(h-hsize_icon->get_height())/2));
-
- te->draw_line(ofs+Point2(0,h),ofs+Point2(size.width,h),color);
- // draw time
-
- float keys_from;
- float keys_to;
- float zoom_scale;
-
-
- {
-
- int zoomw = settings_limit-name_limit;
-
-
- float scale = _get_zoom_scale();
- zoom_scale=scale;
-
-
- float l = animation->get_length();
- if (l<=0)
- l=0.001; //avoid crashor
-
- int end_px = (l - h_scroll->get_value()) * scale;
- int begin_px = -h_scroll->get_value() * scale;
- Color notimecol;
- notimecol.r=timecolor.gray();
- notimecol.g=notimecol.r;
- notimecol.b=notimecol.r;
- notimecol.a=timecolor.a;
-
- {
-
- te->draw_rect(Rect2( ofs + Point2(name_limit,0), Point2(zoomw-1,h)), notimecol);
-
-
- if (begin_px < zoomw && end_px >0) {
-
- if (begin_px<0)
- begin_px=0;
- if (end_px>zoomw)
- end_px=zoomw;
-
- te->draw_rect(Rect2( ofs + Point2(name_limit+begin_px,0), Point2(end_px-begin_px-1,h)), timecolor);
- }
-
- }
-
-
-
- keys_from= h_scroll->get_value();
- keys_to=keys_from+zoomw / scale;
-
- {
- float time_min=0;
- float time_max=animation->get_length();
- for(int i=0;i<animation->get_track_count();i++) {
-
- if (animation->track_get_key_count(i)>0) {
-
- float beg = animation->track_get_key_time(i,0);
- if (beg<time_min)
- time_min=beg;
- float end = animation->track_get_key_time(i,animation->track_get_key_count(i)-1);
- if (end>time_max)
- time_max=end;
- }
- }
-
-
-
-
-
- float extra = (zoomw / scale)*0.5;
-
- if (time_min<-0.001)
- time_min-=extra;
- time_max+=extra;
- h_scroll->set_min(time_min);
- h_scroll->set_max(time_max);
-
- if (zoomw / scale < (time_max-time_min)) {
- h_scroll->show();
-
- } else {
-
- h_scroll->hide();
- }
-
-
- }
-
- h_scroll->set_page(zoomw / scale);
-
- Color color_time_sec = color;
- Color color_time_dec = color;
- color_time_dec.a*=0.5;
-#define SC_ADJ 100
- int min=30;
- int dec=1;
- int step=1;
- int decimals=2;
- bool step_found=false;
-
- while(!step_found) {
-
- static const int _multp[3]={1,2,5};
- for(int i=0;i<3;i++) {
-
- step = (_multp[i] * dec);
- if (step*scale/SC_ADJ> min) {
- step_found=true;
- break;
- }
-
- }
- if (step_found)
- break;
- dec*=10;
- decimals--;
- if (decimals<0)
- decimals=0;
- }
-
-
- for(int i=0;i<zoomw;i++) {
-
- float pos = h_scroll->get_value() + double(i)/scale;
- float prev = h_scroll->get_value() + (double(i)-1.0)/scale;
-
-
- int sc = int(Math::floor(pos*SC_ADJ));
- int prev_sc = int(Math::floor(prev*SC_ADJ));
- bool sub = (sc % SC_ADJ);
-
- if ((sc/step)!=(prev_sc/step) || (prev_sc<0 && sc>=0)) {
-
- int scd = sc < 0 ? prev_sc : sc;
- te->draw_line( ofs + Point2(name_limit+i,0), ofs+Point2(name_limit+i,h), color);
- te->draw_string( font,ofs + Point2(name_limit+i+3,(h-font->get_height())/2+font->get_ascent()).floor(),String::num((scd-(scd%step))/double(SC_ADJ),decimals),sub?color_time_dec:color_time_sec,zoomw-i);
- }
-
-
- }
- }
-
- color.a*=0.5;
-
- for(int i=0;i<fit;i++) {
-
- //this code sucks, i always forget how it works
-
- int idx = v_scroll->get_value() + i;
- if (idx>=animation->get_track_count())
- 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;
- te->draw_rect(Rect2(ofs+Point2(0,y),Size2(size.width,h-1)),sepc);
- }
-
- if (selected_track==idx) {
- Color tc = select_color;
- //tc.a*=0.7;
- te->draw_rect(Rect2(ofs+Point2(0,y),Size2(size.width-1,h-1)),tc);
- }
-
- te->draw_texture(type_icon[animation->track_get_type(idx)],ofs+Point2(0,y+(h-type_icon[0]->get_height())/2).floor());
- NodePath np = animation->track_get_path(idx);
- Node *n = root->get_node(np);
- Color ncol = color;
- if (n && editor_selection->is_selected(n))
- 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);
-
- Point2 icon_ofs = ofs + Point2( size.width, y + (h - remove_icon->get_height() )/2).floor();
- icon_ofs.y+=4;
-
-
-/* icon_ofs.x-=remove_icon->get_width();
-
- te->draw_texture((mouse_over.over==MouseOver::OVER_REMOVE && mouse_over.track==idx)?remove_icon_hl:remove_icon,icon_ofs);
- icon_ofs.x-=hsep;
- icon_ofs.x-=move_down_icon->get_width();
- te->draw_texture((mouse_over.over==MouseOver::OVER_DOWN && mouse_over.track==idx)?move_down_icon_hl:move_down_icon,icon_ofs);
- icon_ofs.x-=hsep;
- icon_ofs.x-=move_up_icon->get_width();
- te->draw_texture((mouse_over.over==MouseOver::OVER_UP && mouse_over.track==idx)?move_up_icon_hl:move_up_icon,icon_ofs);
- icon_ofs.x-=hsep;
- te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
-
- icon_ofs.x-=hsep;
- */
- track_ofs[0]=size.width-icon_ofs.x;
- icon_ofs.x-=down_icon->get_width();
- te->draw_texture(down_icon,icon_ofs);
-
- int wrap_type = animation->track_get_interpolation_loop_wrap(idx)?1:0;
- icon_ofs.x-=hsep;
- icon_ofs.x-=wrap_icon[wrap_type]->get_width();
- te->draw_texture(wrap_icon[wrap_type],icon_ofs);
-
- icon_ofs.x-=hsep;
- te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
-
- track_ofs[1]=size.width-icon_ofs.x;
-
- icon_ofs.x-=down_icon->get_width();
- te->draw_texture(down_icon,icon_ofs);
-
- int interp_type = animation->track_get_interpolation_type(idx);
- ERR_CONTINUE(interp_type<0 || interp_type>=3);
- icon_ofs.x-=hsep;
- icon_ofs.x-=interp_icon[interp_type]->get_width();
- te->draw_texture(interp_icon[interp_type],icon_ofs);
-
- icon_ofs.x-=hsep;
- te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
-
- track_ofs[2]=size.width-icon_ofs.x;
-
- if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
-
-
- int umode = animation->value_track_get_update_mode(idx);
-
- icon_ofs.x-=hsep;
- icon_ofs.x-=down_icon->get_width();
- te->draw_texture(down_icon,icon_ofs);
-
- icon_ofs.x-=hsep;
- icon_ofs.x-=cont_icon[umode]->get_width();
- te->draw_texture(cont_icon[umode],icon_ofs);
- } else {
-
- icon_ofs.x -= hsep*2 + cont_icon[0]->get_width() + down_icon->get_width();
- }
-
- icon_ofs.x-=hsep;
- te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
-
- track_ofs[3]=size.width-icon_ofs.x;
-
- icon_ofs.x-=hsep;
- icon_ofs.x-=add_key_icon->get_width();
- te->draw_texture((mouse_over.over==MouseOver::OVER_ADD_KEY && mouse_over.track==idx)?add_key_icon_hl:add_key_icon,icon_ofs);
-
- track_ofs[4]=size.width-icon_ofs.x;
-
- //draw the keys;
- int tt = animation->track_get_type(idx);
- float key_vofs = Math::floor((float)(h - type_icon[tt]->get_height())/2);
- float key_hofs = -Math::floor((float)type_icon[tt]->get_height()/2);
-
- int kc=animation->track_get_key_count(idx);
- bool first=true;
-
-
-
- for(int i=0;i<kc;i++) {
-
-
- float time = animation->track_get_key_time(idx,i);
- if (time<keys_from)
- continue;
- if (time>keys_to) {
-
- if (first && i>0 && animation->track_get_key_value(idx,i)==animation->track_get_key_value(idx,i-1)) {
- //draw whole line
- te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(settings_limit,y+h/2),color);
- }
-
- break;
- }
-
- float x = key_hofs + name_limit + (time-keys_from)*zoom_scale;
-
- Ref<Texture> tex = type_icon[tt];
-
- SelectedKey sk;
- sk.key=i;
- sk.track=idx;
- if (selection.has(sk)) {
-
- if (click.click==ClickOver::CLICK_MOVE_KEYS)
- continue;
- tex=type_selected;
- }
-
- if (mouse_over.over==MouseOver::OVER_KEY && mouse_over.track==idx && mouse_over.over_key==i)
- tex=type_hover;
-
- Variant value = animation->track_get_key_value(idx,i);
- if (first && i>0 && value==animation->track_get_key_value(idx,i-1)) {
-
- te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(x,y+h/2),color);
- }
-
- if (i<kc-1 && value==animation->track_get_key_value(idx,i+1)) {
- float x_n = key_hofs + name_limit + (animation->track_get_key_time(idx,i+1)-keys_from)*zoom_scale;
-
- x_n = MIN( x_n, settings_limit);
- te->draw_line(ofs+Point2(x_n,y+h/2),ofs+Point2(x,y+h/2),color);
-
- }
-
- 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;
- }
-
- }
-
- switch(click.click) {
- case ClickOver::CLICK_SELECT_KEYS: {
-
- te->draw_rect(Rect2(click.at,click.to-click.at),Color(0.7,0.7,1.0,0.5));
-
- } break;
- case ClickOver::CLICK_MOVE_KEYS: {
-
- float from_t = 1e20;
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
- float t = animation->track_get_key_time(E->key().track,E->key().key);
- if (t<from_t)
- from_t=t;
-
- }
-
- float motion = from_t+(click.to.x - click.at.x)/zoom_scale;
- if (step->get_value())
- motion = Math::stepify(motion,step->get_value());
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
-
-
- int idx = E->key().track;
- int i = idx-v_scroll->get_value();
- if (i<0 || i>=fit)
- continue;
- int y = h+i*h+sep;
-
- float key_vofs = Math::floor((float)(h - type_selected->get_height())/2);
- float key_hofs = -Math::floor((float)type_selected->get_height()/2);
-
- float time = animation->track_get_key_time(idx,E->key().key);
- float diff = time-from_t;
-
- float t = motion + diff;
-
- float x = (t-keys_from)*zoom_scale;
- //x+=click.to.x - click.at.x;
- if (x<0 || x>=(settings_limit-name_limit))
- continue;
-
- x+=name_limit;
-
- te->draw_texture(type_selected,ofs+Point2(x+key_hofs,y+key_vofs).floor());
-
- }
- } break;
- default: {};
- }
-
-
- te_drawing=false;
-}
-
-void AnimationKeyEditor::_track_name_changed(const String& p_name) {
-
- ERR_FAIL_COND(!animation.is_valid());
- undo_redo->create_action(TTR("Anim Track Rename"));
- undo_redo->add_do_method(animation.ptr(),"track_set_path",track_name_editing,p_name);
- undo_redo->add_undo_method(animation.ptr(),"track_set_path",track_name_editing,animation->track_get_path(track_name_editing));
- undo_redo->commit_action();
- track_name->hide();
-
-}
-
-void AnimationKeyEditor::_track_menu_selected(int p_idx) {
-
-
- ERR_FAIL_COND(!animation.is_valid());
-
- if (interp_editing!=-1) {
-
- ERR_FAIL_INDEX(interp_editing,animation->get_track_count());
- undo_redo->create_action(TTR("Anim Track Change Interpolation"));
- undo_redo->add_do_method(animation.ptr(),"track_set_interpolation_type",interp_editing,p_idx);
- undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",interp_editing,animation->track_get_interpolation_type(interp_editing));
- undo_redo->commit_action();
- } else if (cont_editing!=-1) {
-
- ERR_FAIL_INDEX(cont_editing,animation->get_track_count());
-
- undo_redo->create_action(TTR("Anim Track Change Value Mode"));
- undo_redo->add_do_method(animation.ptr(),"value_track_set_update_mode",cont_editing,p_idx);
- undo_redo->add_undo_method(animation.ptr(),"value_track_set_update_mode",cont_editing,animation->value_track_get_update_mode(cont_editing));
- undo_redo->commit_action();
- } else if (wrap_editing!=-1) {
-
- ERR_FAIL_INDEX(wrap_editing,animation->get_track_count());
-
- undo_redo->create_action(TTR("Anim Track Change Wrap Mode"));
- undo_redo->add_do_method(animation.ptr(),"track_set_interpolation_loop_wrap",wrap_editing,p_idx?true:false);
- undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_loop_wrap",wrap_editing,animation->track_get_interpolation_loop_wrap(wrap_editing));
- undo_redo->commit_action();
- } else {
- switch (p_idx) {
-
- case RIGHT_MENU_DUPLICATE:
- _anim_duplicate_keys(); break;
- case RIGHT_MENU_DUPLICATE_TRANSPOSE:
- _anim_duplicate_keys(true); break;
- case RIGHT_MENU_REMOVE:
- _anim_delete_keys(); break;
- }
- }
-
-}
-
-struct _AnimMoveRestore {
-
- int track;
- float time;
- Variant key;
- float transition;
-};
-
-void AnimationKeyEditor::_clear_selection_for_anim(const Ref<Animation>& p_anim) {
-
- if (!(animation==p_anim))
- return;
- //selection.clear();
- _clear_selection();
-
-}
-
-void AnimationKeyEditor::_select_at_anim(const Ref<Animation>& p_anim,int p_track,float p_pos){
-
- if (!(animation==p_anim))
- return;
-
- int idx = animation->track_find_key(p_track,p_pos,true);
- ERR_FAIL_COND(idx<0);
-
- SelectedKey sk;
- sk.track=p_track;
- sk.key=idx;
- KeyInfo ki;
- ki.pos=p_pos;
-
- selection.insert(sk,ki);
-
-}
-
-
-PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx,NodePath& r_base_path) {
-
- r_base_path=NodePath();
- ERR_FAIL_COND_V(!animation.is_valid(),PropertyInfo());
- ERR_FAIL_INDEX_V(p_idx,animation->get_track_count(),PropertyInfo());
-
- if (!root)
- return PropertyInfo();
-
- NodePath path = animation->track_get_path(p_idx);
-
-
- if (!root->has_node_and_resource(path))
- return PropertyInfo();
-
- RES res;
- Node *node = root->get_node_and_resource(path,res);
-
-
- if (node) {
- r_base_path=node->get_path();
- }
-
- String property = path.get_property();
- if (property=="")
- return PropertyInfo();
-
- List<PropertyInfo> pinfo;
- if (res.is_valid())
- res->get_property_list(&pinfo);
- else
- node->get_property_list(&pinfo);
-
- for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
-
- if (E->get().name==property)
- return E->get();
- }
-
- return PropertyInfo();
-}
-
-
-void AnimationKeyEditor::_curve_transition_changed(float p_what) {
-
- if (selection.size()==0)
- return;
- if (selection.size()==1)
- undo_redo->create_action(TTR("Edit Node Curve"),UndoRedo::MERGE_ENDS);
- else
- undo_redo->create_action(TTR("Edit Selection Curve"),UndoRedo::MERGE_ENDS);
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
-
- int track = E->key().track;
- int key = E->key().key;
- float prev_val = animation->track_get_key_transition(track,key);
- undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,p_what);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val);
- }
-
- undo_redo->commit_action();
-
-}
-
-void AnimationKeyEditor::_toggle_edit_curves() {
-
- if (edit_button->is_pressed())
- key_editor_tab->show();
- else
- key_editor_tab->hide();
-}
-
-
-bool AnimationKeyEditor::_edit_if_single_selection() {
-
- if (selection.size()!=1) {
-
- if (selection.size()==0) {
- curve_edit->set_mode(AnimationCurveEdit::MODE_DISABLED);
- //print_line("disable");
- } else {
-
- curve_edit->set_mode(AnimationCurveEdit::MODE_MULTIPLE);
- curve_edit->set_transition(1.0);
- curve_edit->clear_multiples();
- //add all
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
-
- curve_edit->set_multiple(animation->track_get_key_transition(E->key().track,E->key().key));
- }
- //print_line("multiple");
-
- }
- return false;
- }
- curve_edit->set_mode(AnimationCurveEdit::MODE_SINGLE);
- //print_line("regular");
-
- int idx = selection.front()->key().track;
- int key = selection.front()->key().key;
- {
-
- key_edit->animation=animation;
- key_edit->track=idx;
- key_edit->key_ofs=animation->track_get_key_time(idx,key);
- key_edit->hint=_find_hint_for_track(idx,key_edit->base);
- key_edit->notify_change();
-
- curve_edit->set_transition(animation->track_get_key_transition(idx,key));
-
- /*key_edit_dialog->set_size( Size2( 200,200) );
- key_edit_dialog->set_pos( track_editor->get_global_pos() + ofs + mpos +Point2(-100,20));
- key_edit_dialog->popup();*/
-
- }
-
- return true;
-
-}
-
-void AnimationKeyEditor::_anim_delete_keys() {
- if (selection.size()) {
- undo_redo->create_action(TTR("Anim Delete Keys"));
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- undo_redo->add_do_method(animation.ptr(),"track_remove_key",E->key().track,E->key().key);
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
-
- }
- undo_redo->add_do_method(this,"_clear_selection_for_anim",animation);
- undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation);
- undo_redo->commit_action();
- //selection.clear();
- accept_event();
- _edit_if_single_selection();
- }
-}
-
-void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
-
- Control *te=track_editor;
- Ref<StyleBox> style = get_stylebox("normal","TextEdit");
-
- if (!animation.is_valid()) {
- return;
- }
-
- Size2 size= te->get_size() - style->get_minimum_size();
- Size2 ofs = style->get_offset();
-
- Ref<Font> font = te->get_font("font","Tree");
- int sep = get_constant("vseparation","Tree");
- int hsep = get_constant("hseparation","Tree");
- Ref<Texture> remove_icon = get_icon("Remove","EditorIcons");
- Ref<Texture> move_up_icon = get_icon("MoveUp","EditorIcons");
- Ref<Texture> move_down_icon = get_icon("MoveDown","EditorIcons");
- Ref<Texture> down_icon = get_icon("select_arrow","Tree");
- Ref<Texture> hsize_icon = get_icon("Hsize","EditorIcons");
- Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
-
- Ref<Texture> wrap_icon[2]={
- get_icon("InterpWrapClamp","EditorIcons"),
- get_icon("InterpWrapLoop","EditorIcons"),
- };
- Ref<Texture> interp_icon[3]={
- get_icon("InterpRaw","EditorIcons"),
- get_icon("InterpLinear","EditorIcons"),
- get_icon("InterpCubic","EditorIcons")
- };
- Ref<Texture> cont_icon[3]={
- get_icon("TrackContinuous","EditorIcons"),
- get_icon("TrackDiscrete","EditorIcons"),
- get_icon("TrackTrigger","EditorIcons")
- };
- Ref<Texture> type_icon[3]={
- get_icon("KeyValue","EditorIcons"),
- get_icon("KeyXform","EditorIcons"),
- get_icon("KeyCall","EditorIcons")
- };
- int right_separator_ofs = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*9;
-
- int h = font->get_height()+sep;
-
- int fit = (size.height / h)-1;
- int total = animation->get_track_count();
- if (total < fit) {
- v_scroll->hide();
- } else {
- v_scroll->show();
- v_scroll->set_max( total );
- v_scroll->set_page( fit );
- }
-
- int settings_limit = size.width - right_separator_ofs;
- int name_limit = settings_limit * name_column_ratio;
-
-
- switch(p_input.type) {
-
- case InputEvent::KEY: {
-
- if (p_input.key.scancode==KEY_D && p_input.key.pressed && p_input.key.mod.command) {
-
- if (p_input.key.mod.shift)
- _menu_track(TRACK_MENU_DUPLICATE_TRANSPOSE);
- else
- _menu_track(TRACK_MENU_DUPLICATE);
-
- accept_event();
-
- } else if (p_input.key.scancode==KEY_DELETE && p_input.key.pressed && click.click==ClickOver::CLICK_NONE) {
-
- _anim_delete_keys();
- } else if (animation.is_valid() && animation->get_track_count()>0) {
-
- if (p_input.is_pressed() && (p_input.is_action("ui_up") || p_input.is_action("ui_page_up"))) {
-
- if (p_input.is_action("ui_up"))
- selected_track--;
- if (v_scroll->is_visible_in_tree() && p_input.is_action("ui_page_up"))
- selected_track--;
-
- if (selected_track<0)
- selected_track=0;
-
-
- if (v_scroll->is_visible_in_tree()) {
- if (v_scroll->get_value() > selected_track)
- v_scroll->set_value(selected_track);
-
- }
-
- track_editor->update();
- accept_event();
-
- }
-
- if (p_input.is_pressed() && (p_input.is_action("ui_down") || p_input.is_action("ui_page_down"))) {
-
- if (p_input.is_action("ui_down"))
- selected_track++;
- else if (v_scroll->is_visible_in_tree() && p_input.is_action("ui_page_down"))
- selected_track+=v_scroll->get_page();
-
- if (selected_track >= animation->get_track_count())
- selected_track=animation->get_track_count()-1;
-
- if (v_scroll->is_visible_in_tree() && v_scroll->get_page()+v_scroll->get_value() < selected_track+1) {
- v_scroll->set_value(selected_track-v_scroll->get_page()+1);
- }
-
- track_editor->update();
- accept_event();
- }
- }
-
-
- } break;
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb = p_input.mouse_button;
-
- if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) {
-
- if (mb.mod.command) {
- zoom->set_value(zoom->get_value() + zoom->get_step());
- } else {
- v_scroll->set_value( v_scroll->get_value() - v_scroll->get_page() / 8 );
- }
- }
-
- if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) {
-
- if (mb.mod.command) {
- zoom->set_value(zoom->get_value() - zoom->get_step());
- } else {
- v_scroll->set_value( v_scroll->get_value() + v_scroll->get_page() / 8 );
- }
- }
-
- if (mb.button_index==BUTTON_RIGHT && mb.pressed) {
-
- Point2 mpos = Point2(mb.x,mb.y)-ofs;
-
- if (selection.size() == 0) {
- // Auto-select on right-click if nothing is selected
- // Note: This code is pretty much duplicated from the left click code,
- // both codes could be moved into a function to avoid the duplicated code.
- Point2 mpos = Point2(mb.x,mb.y)-ofs;
-
- if (mpos.y < h ) {
- return;
- }
-
- mpos.y -= h;
-
- int idx = mpos.y / h;
- idx+=v_scroll->get_value();
- if (idx <0 || idx>=animation->get_track_count())
- break;
-
- if (mpos.x < name_limit) {
- } else if (mpos.x < settings_limit) {
- float pos = mpos.x - name_limit;
- pos/=_get_zoom_scale();
- pos+=h_scroll->get_value();
- float w_time = (type_icon[0]->get_width() / _get_zoom_scale())/2.0;
-
- int kidx = animation->track_find_key(idx,pos);
- int kidx_n = kidx+1;
- int key=-1;
-
- if (kidx>=0 && kidx<animation->track_get_key_count(idx)) {
-
- float kpos = animation->track_get_key_time(idx,kidx);
- if (ABS(pos-kpos)<=w_time) {
-
- key=kidx;
- }
- }
-
- if (key==-1 && kidx_n>=0 && kidx_n<animation->track_get_key_count(idx)) {
-
- float kpos = animation->track_get_key_time(idx,kidx_n);
- if (ABS(pos-kpos)<=w_time) {
-
- key=kidx_n;
- }
- }
-
- if (key==-1) {
-
- click.click=ClickOver::CLICK_SELECT_KEYS;
- click.at=Point2(mb.x,mb.y);
- click.to=click.at;
- click.shift=mb.mod.shift;
- selected_track=idx;
- track_editor->update();
- //drag select region
- return;
-
- }
-
-
-
- SelectedKey sk;
- sk.track=idx;
- sk.key=key;
- KeyInfo ki;
- ki.pos= animation->track_get_key_time(idx,key);
- click.shift=mb.mod.shift;
- click.selk=sk;
-
-
- if (!mb.mod.shift && !selection.has(sk))
- _clear_selection();
-
- selection.insert(sk,ki);
-
- click.click=ClickOver::CLICK_MOVE_KEYS;
- click.at=Point2(mb.x,mb.y);
- click.to=click.at;
- update();
- selected_track=idx;
- track_editor->update();
-
- if (_edit_if_single_selection() && mb.mod.command) {
- edit_button->set_pressed(true);
- key_editor_tab->show();
- }
- }
- }
-
- if (selection.size()) {
- // User has right clicked and we have a selection, show a popup menu with options
- track_menu->clear();
- track_menu->set_size(Point2(1,1));
- track_menu->add_item(TTR("Duplicate Selection"), RIGHT_MENU_DUPLICATE);
- track_menu->add_item(TTR("Duplicate Transposed"), RIGHT_MENU_DUPLICATE_TRANSPOSE);
- track_menu->add_item(TTR("Remove Selection"), RIGHT_MENU_REMOVE);
-
- track_menu->set_pos(te->get_global_pos()+mpos);
-
- interp_editing=-1;
- cont_editing=-1;
- wrap_editing=-1;
-
- track_menu->popup();
- }
- }
-
- if (mb.button_index==BUTTON_LEFT && !(mb.button_mask&~BUTTON_MASK_LEFT)) {
-
-
- if (mb.pressed) {
-
- Point2 mpos = Point2(mb.x,mb.y)-ofs;
-
- if (mpos.y < h ) {
-
-
- if (mpos.x<name_limit && mpos.x > (name_limit - hsep - hsize_icon->get_width())) {
-
-
- click.click=ClickOver::CLICK_RESIZE_NAMES;
- click.at=Point2(mb.x,mb.y);
- click.to=click.at;
- click.at.y=name_limit;
-
- }
-
- if (mpos.x>=name_limit && mpos.x<settings_limit) {
- //seek
- //int zoomw = settings_limit-name_limit;
- float scale = _get_zoom_scale();
- float pos = h_scroll->get_value() + (mpos.x-name_limit) / scale;
- if (animation->get_step())
- pos=Math::stepify(pos,animation->get_step());
-
- if (pos<0 )
- pos=0;
- if (pos>=animation->get_length())
- pos=animation->get_length();
- timeline_pos=pos;
- click.click=ClickOver::CLICK_DRAG_TIMELINE;
- click.at=Point2(mb.x,mb.y);
- click.to=click.at;
- emit_signal("timeline_changed",pos,false);
-
- }
-
- return;
- }
-
- mpos.y -= h;
-
- int idx = mpos.y / h;
- idx+=v_scroll->get_value();
- if (idx <0)
- break;
-
- if (idx>=animation->get_track_count()) {
-
- if (mpos.x >= name_limit && mpos.x<settings_limit) {
-
- click.click=ClickOver::CLICK_SELECT_KEYS;
- click.at=Point2(mb.x,mb.y);
- click.to=click.at;
- //drag select region
- }
-
- break;
- }
-
- if (mpos.x < name_limit) {
- //name column
-
- // area
- if (idx!=selected_track) {
-
- selected_track=idx;
- track_editor->update();
- break;
- }
-
- Rect2 area(ofs.x,ofs.y+((int(mpos.y)/h)+1)*h,name_limit, h );
- track_name->set_text(animation->track_get_path(idx));
- track_name->set_pos( te->get_global_pos() + area.pos);
- track_name->set_size(area.size);
- track_name->show_modal();
- track_name->grab_focus();
- track_name->select_all();
- track_name_editing=idx;
-
- } else if (mpos.x < settings_limit) {
-
- float pos = mpos.x - name_limit;
- pos/=_get_zoom_scale();
- pos+=h_scroll->get_value();
- float w_time = (type_icon[0]->get_width() / _get_zoom_scale())/2.0;
-
- int kidx = animation->track_find_key(idx,pos);
- int kidx_n = kidx+1;
- int key=-1;
-
- if (kidx>=0 && kidx<animation->track_get_key_count(idx)) {
-
- float kpos = animation->track_get_key_time(idx,kidx);
- if (ABS(pos-kpos)<=w_time) {
-
- key=kidx;
- }
- }
-
- if (key==-1 && kidx_n>=0 && kidx_n<animation->track_get_key_count(idx)) {
-
- float kpos = animation->track_get_key_time(idx,kidx_n);
- if (ABS(pos-kpos)<=w_time) {
-
- key=kidx_n;
- }
- }
-
- if (key==-1) {
-
- click.click=ClickOver::CLICK_SELECT_KEYS;
- click.at=Point2(mb.x,mb.y);
- click.to=click.at;
- click.shift=mb.mod.shift;
- selected_track=idx;
- track_editor->update();
- //drag select region
- return;
-
- }
-
-
-
- SelectedKey sk;
- sk.track=idx;
- sk.key=key;
- KeyInfo ki;
- ki.pos= animation->track_get_key_time(idx,key);
- click.shift=mb.mod.shift;
- click.selk=sk;
-
-
- if (!mb.mod.shift && !selection.has(sk))
- _clear_selection();
-
- selection.insert(sk,ki);
-
- click.click=ClickOver::CLICK_MOVE_KEYS;
- click.at=Point2(mb.x,mb.y);
- click.to=click.at;
- update();
- selected_track=idx;
- track_editor->update();
-
- if (_edit_if_single_selection() && mb.mod.command) {
- edit_button->set_pressed(true);
- key_editor_tab->show();
- }
- } else {
- //button column
- int ofsx = size.width - mpos.x;
- if (ofsx < 0)
- break;
-/*
- if (ofsx < remove_icon->get_width()) {
-
- undo_redo->create_action("Remove Anim Track");
- undo_redo->add_do_method(animation.ptr(),"remove_track",idx);
- undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(idx),idx);
- undo_redo->add_undo_method(animation.ptr(),"track_set_path",idx,animation->track_get_path(idx));
- //todo interpolation
- for(int i=0;i<animation->track_get_key_count(idx);i++) {
-
- Variant v = animation->track_get_key_value(idx,i);
- float time = animation->track_get_key_time(idx,i);
- float trans = animation->track_get_key_transition(idx,i);
-
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,time,v);
- undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",idx,i,trans);
-
- }
-
- undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",idx,animation->track_get_interpolation_type(idx));
- if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
- undo_redo->add_undo_method(animation.ptr(),"value_track_set_continuous",idx,animation->value_track_is_continuous(idx));
-
- }
-
- undo_redo->commit_action();
-
-
- return;
- }
-
- ofsx-=hsep+remove_icon->get_width();
-
- if (ofsx < move_down_icon->get_width()) {
-
- if (idx < animation->get_track_count() -1) {
- undo_redo->create_action("Move Anim Track Down");
- undo_redo->add_do_method(animation.ptr(),"track_move_up",idx);
- undo_redo->add_undo_method(animation.ptr(),"track_move_down",idx+1);
- undo_redo->commit_action();
- }
- return;
- }
-
- ofsx-=hsep+move_down_icon->get_width();
-
- if (ofsx < move_up_icon->get_width()) {
-
- if (idx >0) {
- undo_redo->create_action("Move Anim Track Up");
- undo_redo->add_do_method(animation.ptr(),"track_move_down",idx);
- undo_redo->add_undo_method(animation.ptr(),"track_move_up",idx-1);
- undo_redo->commit_action();
- }
- return;
- }
-
-
- ofsx-=hsep*3+move_up_icon->get_width();
- */
-
-
- if (ofsx < track_ofs[1]) {
-
- track_menu->clear();
- track_menu->set_size(Point2(1,1));
- static const char *interp_name[2]={"Clamp Loop Interp","Wrap Loop Interp"};
- for(int i=0;i<2;i++) {
- track_menu->add_icon_item(wrap_icon[i],interp_name[i]);
- }
-
- int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
- int popup_x = size.width-track_ofs[1];
-
- track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
-
-
- wrap_editing=idx;
- interp_editing=-1;
- cont_editing=-1;
-
- track_menu->popup();
-
- return;
- }
-
-
- if (ofsx < track_ofs[2]) {
-
- track_menu->clear();
- track_menu->set_size(Point2(1,1));
- static const char *interp_name[3]={"Nearest","Linear","Cubic"};
- for(int i=0;i<3;i++) {
- track_menu->add_icon_item(interp_icon[i],interp_name[i]);
- }
-
- int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
- int popup_x = size.width-track_ofs[2];
-
- track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
-
-
- interp_editing=idx;
- cont_editing=-1;
- wrap_editing=-1;
-
- track_menu->popup();
-
- return;
- }
-
- if (ofsx < track_ofs[3]) {
-
- track_menu->clear();
- track_menu->set_size(Point2(1,1));
- String cont_name[3]={TTR("Continuous"),TTR("Discrete"),TTR("Trigger")};
- for(int i=0;i<3;i++) {
- track_menu->add_icon_item(cont_icon[i],cont_name[i]);
- }
-
-
- int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
- int popup_x = size.width-track_ofs[3];
-
- track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
-
- interp_editing=-1;
- wrap_editing=-1;
- cont_editing=idx;
-
- track_menu->popup();
-
- return;
- }
-
- if (ofsx < track_ofs[4]) {
-
- Animation::TrackType tt = animation->track_get_type(idx);
-
- float pos = timeline_pos;
- int existing = animation->track_find_key(idx,pos,true);
-
-
-
- Variant newval;
-
- if (tt==Animation::TYPE_TRANSFORM) {
- Dictionary d;
- d["loc"]=Vector3();
- d["rot"]=Quat();
- d["scale"]=Vector3();
- newval=d;
-
- } else if (tt==Animation::TYPE_METHOD) {
-
- Dictionary d;
- d["method"]="";
- d["args"]=Vector<Variant>();
-
-
- newval=d;
- } else if (tt==Animation::TYPE_VALUE) {
-
- NodePath np;
- PropertyInfo inf = _find_hint_for_track(idx,np);
- if (inf.type!=Variant::NIL) {
-
- Variant::CallError err;
- newval=Variant::construct(inf.type,NULL,0,err);
-
- }
-
- if (newval.get_type()==Variant::NIL) {
- //popup a new type
- cvi_track=idx;
- cvi_pos=pos;
-
- type_menu->set_pos( get_global_pos() + mpos +ofs );
- type_menu->popup();
- return;
- }
-
- }
-
- undo_redo->create_action(TTR("Anim Add Key"));
-
- undo_redo->add_do_method(animation.ptr(),"track_insert_key",idx,pos,newval,1);
- undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",idx,pos);
-
- if (existing!=-1) {
- Variant v = animation->track_get_key_value(idx,existing);
- float trans = animation->track_get_key_transition(idx,existing);
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",idx,pos,v,trans);
- }
-
- undo_redo->commit_action();
-
-
- return;
- }
-
- }
-
- } else {
-
- switch(click.click) {
- case ClickOver::CLICK_SELECT_KEYS: {
-
-
- float zoom_scale=_get_zoom_scale();
- float keys_from = h_scroll->get_value();
- float keys_to = keys_from + (settings_limit-name_limit) / zoom_scale;
-
- float from_time = keys_from + ( click.at.x - (name_limit+ofs.x)) / zoom_scale;
- float to_time = keys_from + (click.to.x - (name_limit+ofs.x)) / zoom_scale;
-
-
- if (to_time < from_time)
- SWAP(from_time,to_time);
-
- if (from_time > keys_to || to_time < keys_from)
- break;
-
- if (from_time < keys_from)
- from_time = keys_from;
-
- if (to_time >= keys_to)
- to_time = keys_to;
-
-
- int from_track = int(click.at.y-ofs.y-h-sep) / h + v_scroll->get_value();
- int to_track = int(click.to.y-ofs.y-h-sep) / h + v_scroll->get_value();
- int from_mod = int(click.at.y-ofs.y-sep) % h;
- int to_mod = int(click.to.y-ofs.y-sep) % h;
-
- if (to_track < from_track) {
-
- SWAP(from_track,to_track);
- SWAP(from_mod,to_mod);
- }
-
-
-
-
- if ((from_mod > (h/2)) && ((click.at.y-ofs.y)>=(h+sep))) {
- from_track++;
- }
-
- if (to_mod < h/2) {
- to_track--;
- }
-
- if (from_track>to_track) {
- if (!click.shift)
- _clear_selection();
- _edit_if_single_selection();
- break;
- }
-
- int tracks_from = v_scroll->get_value();
- int tracks_to = v_scroll->get_value()+fit-1;
- if (tracks_to>=animation->get_track_count())
- tracks_to=animation->get_track_count()-1;
-
- tracks_from=0;
- tracks_to=animation->get_track_count()-1;
- if (to_track >tracks_to)
- to_track = tracks_to;
- if (from_track<tracks_from)
- from_track=tracks_from;
-
- if (from_track > tracks_to || to_track < tracks_from) {
- if (!click.shift)
- _clear_selection();
- _edit_if_single_selection();
- break;
- }
-
- if (!click.shift)
- _clear_selection();
-
-
- int higher_track=0x7FFFFFFF;
- for(int i=from_track;i<=to_track;i++) {
-
- int kc=animation->track_get_key_count(i);
- for(int j=0;j<kc;j++) {
-
- float t = animation->track_get_key_time(i,j);
- if (t<from_time)
- continue;
- if (t>to_time)
- break;
-
- if (i<higher_track)
- higher_track=i;
-
- SelectedKey sk;
- sk.track=i;
- sk.key=j;
- KeyInfo ki;
- ki.pos=t;
- selection[sk]=ki;
- }
- }
-
- if (higher_track!=0x7FFFFFFF) {
- selected_track=higher_track;
- track_editor->update();
- }
-
-
- _edit_if_single_selection();
-
-
- } break;
- case ClickOver::CLICK_MOVE_KEYS: {
-
- if (selection.empty())
- break;
- if (click.at==click.to) {
-
- if (!click.shift) {
-
- KeyInfo ki=selection[click.selk];
- _clear_selection();
- selection[click.selk]=ki;
- _edit_if_single_selection();
- }
-
- break;
- }
-
- float from_t = 1e20;
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
- float t = animation->track_get_key_time(E->key().track,E->key().key);
- if (t<from_t)
- from_t=t;
-
- }
-
- float motion = from_t+(click.to.x - click.at.x)/_get_zoom_scale();
- if (step->get_value())
- motion = Math::stepify(motion,step->get_value());
-
-
-
-
- undo_redo->create_action(TTR("Anim Move Keys"));
-
- List<_AnimMoveRestore> to_restore;
-
- // 1-remove the keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- undo_redo->add_do_method(animation.ptr(),"track_remove_key",E->key().track,E->key().key);
- }
- // 2- remove overlapped keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float newtime = E->get().pos-from_t+motion;
- int idx = animation->track_find_key(E->key().track,newtime,true);
- if (idx==-1)
- continue;
- SelectedKey sk;
- sk.key=idx;
- sk.track=E->key().track;
- if (selection.has(sk))
- continue; //already in selection, don't save
-
- undo_redo->add_do_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newtime);
- _AnimMoveRestore amr;
-
- amr.key=animation->track_get_key_value(E->key().track,idx);
- amr.track=E->key().track;
- amr.time=newtime;
- amr.transition=animation->track_get_key_transition(E->key().track,idx);
-
- to_restore.push_back(amr);
-
- }
-
- // 3-move the keys (re insert them)
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float newpos=E->get().pos-from_t+motion;
- /*
- if (newpos<0)
- continue; //no add at the begining
- */
- undo_redo->add_do_method(animation.ptr(),"track_insert_key",E->key().track,newpos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
-
- }
-
- // 4-(undo) remove inserted keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float newpos=E->get().pos+-from_t+motion;
- /*
- if (newpos<0)
- continue; //no remove what no inserted
- */
- undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newpos);
-
- }
-
- // 5-(undo) reinsert keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
-
- }
-
- // 6-(undo) reinsert overlapped keys
- for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
-
- _AnimMoveRestore &amr = E->get();
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
-
- }
-
- // 6-(undo) reinsert overlapped keys
- for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
-
- _AnimMoveRestore &amr = E->get();
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
-
- }
-
- undo_redo->add_do_method(this,"_clear_selection_for_anim",animation);
- undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation);
-
- // 7-reselect
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float oldpos=E->get().pos;
- float newpos=oldpos-from_t+motion;
- //if (newpos>=0)
- undo_redo->add_do_method(this,"_select_at_anim",animation,E->key().track,newpos);
- undo_redo->add_undo_method(this,"_select_at_anim",animation,E->key().track,oldpos);
-
- }
-
- undo_redo->commit_action();
- _edit_if_single_selection();
-
- } break;
- default: {}
- }
-
- //button released
- click.click=ClickOver::CLICK_NONE;
- track_editor->update();
-
-
- }
- }
-
- } break;
-
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mb = p_input.mouse_motion;
-
- mouse_over.over=MouseOver::OVER_NONE;
- mouse_over.track=-1;
- te->update();
- track_editor->set_tooltip("");
-
- if (!track_editor->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
- track_editor->call_deferred("grab_focus");
-
-
- if (click.click!=ClickOver::CLICK_NONE) {
-
- switch(click.click) {
- case ClickOver::CLICK_RESIZE_NAMES: {
-
-
- float base = click.at.y;
- float clickp = click.at.x-ofs.x;
- float dif = base - clickp;
-
- float target = mb.x+dif-ofs.x;
-
- float ratio = target / settings_limit;
-
- if (ratio>0.9)
- ratio=0.9;
- else if (ratio<0.2)
- ratio=0.2;
-
- name_column_ratio=ratio;
-
-
- } break;
- case ClickOver::CLICK_DRAG_TIMELINE: {
-
- Point2 mpos = Point2(mb.x,mb.y)-ofs;
- /*
- if (mpos.x<name_limit)
- mpos.x=name_limit;
- if (mpos.x>settings_limit)
- mpos.x=settings_limit;
- */
-
-
- //int zoomw = settings_limit-name_limit;
- float scale = _get_zoom_scale();
- float pos = h_scroll->get_value() + (mpos.x-name_limit) / scale;
- if (animation->get_step()) {
- pos=Math::stepify(pos,animation->get_step());
-
- }
- if (pos<0)
- pos=0;
- if (pos>=animation->get_length())
- pos=animation->get_length();
-
- if (pos < h_scroll->get_value()) {
- h_scroll->set_value(pos);
- } else if (pos > h_scroll->get_value() + (settings_limit - name_limit) / scale) {
- h_scroll->set_value( pos - (settings_limit - name_limit) / scale );
- }
-
- timeline_pos=pos;
- emit_signal("timeline_changed",pos,true);
-
-
-
- } break;
- case ClickOver::CLICK_SELECT_KEYS: {
-
- click.to=Point2(mb.x,mb.y);
- if (click.to.y<h && click.at.y>h && mb.relative_y<0) {
-
- float prev = v_scroll->get_value();
- v_scroll->set_value( v_scroll->get_value() -1 );
- if (prev!=v_scroll->get_value())
- click.at.y+=h;
-
-
- }
- if (click.to.y>size.height && click.at.y<size.height && mb.relative_y>0) {
-
- float prev = v_scroll->get_value();
- v_scroll->set_value( v_scroll->get_value() +1 );
- if (prev!=v_scroll->get_value())
- click.at.y-=h;
- }
-
- } break;
- case ClickOver::CLICK_MOVE_KEYS: {
-
- click.to=Point2(mb.x,mb.y);
- } break;
- default: {}
- }
-
- return;
- } else if (mb.button_mask&BUTTON_MASK_MIDDLE) {
-
- int rel = mb.relative_x;
- float relf = rel / _get_zoom_scale();
- h_scroll->set_value( h_scroll->get_value() - relf );
- }
-
- if (mb.button_mask==0) {
-
-
- Point2 mpos = Point2(mb.x,mb.y)-ofs;
-
- if (mpos.y < h ) {
-#if 0
- //seek
- //int zoomw = settings_limit-name_limit;
- float scale = _get_zoom_scale();
- float pos = h_scroll->get_val() + (mpos.y-name_limit) / scale;
- if (pos<0 )
- pos=0;
- if (pos>=animation->get_length())
- pos=animation->get_length();
- timeline->set_val(pos);
-#endif
- return;
- }
-
- mpos.y -= h;
-
- int idx = mpos.y / h;
- idx+=v_scroll->get_value();
- if (idx <0 || idx>=animation->get_track_count())
- break;
-
- mouse_over.track=idx;
-
- if (mpos.x < name_limit) {
- //name column
-
-
- mouse_over.over=MouseOver::OVER_NAME;
-
- } else if (mpos.x < settings_limit) {
-
- float pos = mpos.x - name_limit;
- pos/=_get_zoom_scale();
- pos+=h_scroll->get_value();
- float w_time = (type_icon[0]->get_width() / _get_zoom_scale())/2.0;
-
- int kidx = animation->track_find_key(idx,pos);
- int kidx_n = kidx+1;
-
- bool found = false;
-
- if (kidx>=0 && kidx<animation->track_get_key_count(idx)) {
-
- float kpos = animation->track_get_key_time(idx,kidx);
- if (ABS(pos-kpos)<=w_time) {
-
- mouse_over.over=MouseOver::OVER_KEY;
- mouse_over.track=idx;
- mouse_over.over_key=kidx;
- found=true;
- }
- }
-
- if (!found && kidx_n>=0 && kidx_n<animation->track_get_key_count(idx)) {
-
- float kpos = animation->track_get_key_time(idx,kidx_n);
- if (ABS(pos-kpos)<=w_time) {
-
- mouse_over.over=MouseOver::OVER_KEY;
- mouse_over.track=idx;
- mouse_over.over_key=kidx_n;
- found=true;
- }
- }
-
-
- if (found) {
-
- 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: {
-
- Dictionary d = animation->track_get_key_value(idx,mouse_over.over_key);
- if (d.has("loc"))
- text+="loc: "+String(d["loc"])+"\n";
- if (d.has("rot"))
- text+="rot: "+String(d["rot"])+"\n";
- if (d.has("scale"))
- text+="scale: "+String(d["scale"])+"\n";
- } break;
- case Animation::TYPE_VALUE: {
-
- 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: {
-
-
- Dictionary d = animation->track_get_key_value(idx,mouse_over.over_key);
- if (d.has("method"))
- text+=String(d["method"]);
- text+="(";
- Vector<Variant> args;
- if (d.has("args"))
- args=d["args"];
- for(int i=0;i<args.size();i++) {
-
- if (i>0)
- text+=", ";
- text+=String(args[i]);
- }
- text+=")\n";
-
- } break;
- }
- text+="easing: "+rtos(animation->track_get_key_transition(idx,mouse_over.over_key));
-
-
-
- track_editor->set_tooltip(text);
- return;
-
- }
-
- } else {
- //button column
- int ofsx = size.width - mpos.x;
- if (ofsx < 0)
- break;
-/*
- if (ofsx < remove_icon->get_width()) {
-
- mouse_over.over=MouseOver::OVER_REMOVE;
-
- return;
- }
-
- ofsx-=hsep+remove_icon->get_width();
-
- if (ofsx < move_down_icon->get_width()) {
-
- mouse_over.over=MouseOver::OVER_DOWN;
- return;
- }
-
- ofsx-=hsep+move_down_icon->get_width();
-
- if (ofsx < move_up_icon->get_width()) {
-
- mouse_over.over=MouseOver::OVER_UP;
- return;
- }
-
- ofsx-=hsep*3+move_up_icon->get_width();
-
- */
-
- if (ofsx < down_icon->get_width() + wrap_icon[0]->get_width() + hsep*3) {
-
- mouse_over.over=MouseOver::OVER_WRAP;
- return;
- }
-
- ofsx-=hsep*3+wrap_icon[0]->get_width() + down_icon->get_width();
-
- if (ofsx < down_icon->get_width() + interp_icon[0]->get_width() + hsep*3) {
-
- mouse_over.over=MouseOver::OVER_INTERP;
- return;
- }
-
-
- ofsx-=hsep*2+interp_icon[0]->get_width() + down_icon->get_width();
-
- if (ofsx < down_icon->get_width() + cont_icon[0]->get_width() +hsep*3) {
-
- mouse_over.over=MouseOver::OVER_VALUE;
- return;
- }
-
- ofsx-=hsep*3+cont_icon[0]->get_width() + down_icon->get_width();
-
- if (ofsx < add_key_icon->get_width()) {
-
- mouse_over.over=MouseOver::OVER_ADD_KEY;
- return;
- }
-
-
- }
-
- }
-
- } break;
-
- }
-}
-
-void AnimationKeyEditor::_notification(int p_what) {
-
-
- switch(p_what) {
- case NOTIFICATION_VISIBILITY_CHANGED: {
-
- EditorNode::get_singleton()->update_keying();
- emit_signal("keying_changed");
- } 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"));
- menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue","EditorIcons"),"Add Normal Track",ADD_TRACK_MENU_ADD_VALUE_TRACK);
- menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform","EditorIcons"),"Add Transform Track",ADD_TRACK_MENU_ADD_TRANSFORM_TRACK);
- menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall","EditorIcons"),"Add Call Func Track",ADD_TRACK_MENU_ADD_CALL_TRACK);
-
- menu_track->set_icon(get_icon("Tools","EditorIcons"));
- menu_track->get_popup()->add_item(TTR("Scale Selection"),TRACK_MENU_SCALE);
- menu_track->get_popup()->add_item(TTR("Scale From Cursor"),TRACK_MENU_SCALE_PIVOT);
- menu_track->get_popup()->add_separator();
- menu_track->get_popup()->add_item(TTR("Duplicate Selection"),TRACK_MENU_DUPLICATE);
- menu_track->get_popup()->add_item(TTR("Duplicate Transposed"),TRACK_MENU_DUPLICATE_TRANSPOSE);
- menu_track->get_popup()->add_separator();
- menu_track->get_popup()->add_item(TTR("Goto Next Step"),TRACK_MENU_NEXT_STEP,KEY_MASK_CMD|KEY_RIGHT);
- menu_track->get_popup()->add_item(TTR("Goto Prev Step"),TRACK_MENU_PREV_STEP,KEY_MASK_CMD|KEY_LEFT);
- menu_track->get_popup()->add_separator();
- PopupMenu *tpp = memnew( PopupMenu );
- tpp->add_item(TTR("Linear"),TRACK_MENU_SET_ALL_TRANS_LINEAR);
- tpp->add_item(TTR("Constant"),TRACK_MENU_SET_ALL_TRANS_CONSTANT);
- tpp->add_item(TTR("In"),TRACK_MENU_SET_ALL_TRANS_IN);
- tpp->add_item(TTR("Out"),TRACK_MENU_SET_ALL_TRANS_OUT);
- tpp->add_item(TTR("In-Out"),TRACK_MENU_SET_ALL_TRANS_INOUT);
- tpp->add_item(TTR("Out-In"),TRACK_MENU_SET_ALL_TRANS_OUTIN);
- tpp->set_name(TTR("Transitions"));
- tpp->connect("id_pressed",this,"_menu_track");
- optimize_dialog->connect("confirmed",this,"_animation_optimize");
-
- menu_track->get_popup()->add_child(tpp);
- //menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
- //menu_track->get_popup()->add_separator();
- menu_track->get_popup()->add_item(TTR("Optimize Animation"),TRACK_MENU_OPTIMIZE);
- menu_track->get_popup()->add_item(TTR("Clean-Up Animation"),TRACK_MENU_CLEAN_UP);
-
- curve_linear->set_icon(get_icon("CurveLinear","EditorIcons"));
- curve_in->set_icon(get_icon("CurveIn","EditorIcons"));
- curve_out->set_icon(get_icon("CurveOut","EditorIcons"));
- curve_inout->set_icon(get_icon("CurveInOut","EditorIcons"));
- curve_outin->set_icon(get_icon("CurveOutIn","EditorIcons"));
- curve_constant->set_icon(get_icon("CurveConstant","EditorIcons"));
-
- curve_linear->connect("pressed",this,"_menu_track",varray(CURVE_SET_LINEAR));
- curve_in->connect("pressed",this,"_menu_track",varray(CURVE_SET_IN));
- curve_out->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUT));
- curve_inout->connect("pressed",this,"_menu_track",varray(CURVE_SET_INOUT));
- curve_outin->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUTIN));
- curve_constant->connect("pressed",this,"_menu_track",varray(CURVE_SET_CONSTANT));
-
-
- move_up_button->set_icon(get_icon("MoveUp","EditorIcons"));
- move_down_button->set_icon(get_icon("MoveDown","EditorIcons"));
- remove_button->set_icon(get_icon("Remove","EditorIcons"));
- edit_button->set_icon(get_icon("EditKey","EditorIcons"));
- edit_button->connect("pressed",this,"_toggle_edit_curves");
-
- loop->set_icon(get_icon("Loop","EditorIcons"));
- curve_edit->connect("transition_changed",this,"_curve_transition_changed");
-
- //edit_button->add_color_override("font_color",get_color("font_color","Tree"));
- //edit_button->add_color_override("font_color_hover",get_color("font_color","Tree"));
-
- {
-
- right_data_size_cache=0;
- int hsep = get_constant("hseparation","Tree");
- Ref<Texture> remove_icon = get_icon("Remove","EditorIcons");
- Ref<Texture> move_up_icon = get_icon("MoveUp","EditorIcons");
- Ref<Texture> move_down_icon = get_icon("MoveDown","EditorIcons");
- Ref<Texture> down_icon = get_icon("select_arrow","Tree");
- Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
- Ref<Texture> interp_icon[3]={
- get_icon("InterpRaw","EditorIcons"),
- get_icon("InterpLinear","EditorIcons"),
- get_icon("InterpCubic","EditorIcons")
- };
- Ref<Texture> cont_icon[3]={
- get_icon("TrackContinuous","EditorIcons"),
- get_icon("TrackDiscrete","EditorIcons"),
- get_icon("TrackTrigger","EditorIcons")
- };
-
- Ref<Texture> wrap_icon[2]={
- get_icon("InterpWrapClamp","EditorIcons"),
- get_icon("InterpWrapLoop","EditorIcons"),
- };
-
- //right_data_size_cache = remove_icon->get_width() + move_up_icon->get_width() + move_down_icon->get_width() + down_icon->get_width() *2 + interp_icon[0]->get_width() + cont_icon[0]->get_width() + add_key_icon->get_width() + hsep*11;
- right_data_size_cache = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + wrap_icon[0]->get_width() + hsep*8;
-
-
- }
- call_select->connect("selected",this,"_add_call_track");
- //rename_anim->set_icon( get_icon("Rename","EditorIcons") );
-/*
- edit_anim->set_icon( get_icon("Edit","EditorIcons") );
- blend_anim->set_icon( get_icon("Blend","EditorIcons") );
- play->set_icon( get_icon("Play","EditorIcons") );
- stop->set_icon( get_icon("Stop","EditorIcons") );
- pause->set_icon( get_icon("Pause","EditorIcons") );
-*/
- //menu->set_icon(get_icon("Animation","EditorIcons"));
- //play->set_icon(get_icon("AnimationPlay","EditorIcons"));
- //menu->set_icon(get_icon("Animation","EditorIcons"));
- _update_menu();
-
- } break;
-
-
- }
-
-}
-
-
-
-void AnimationKeyEditor::_scroll_changed(double) {
-
- if (te_drawing)
- return;
-
- track_editor->update();
-}
-
-
-
-void AnimationKeyEditor::_update_paths() {
-
- if (animation.is_valid()) {
- //timeline->set_max(animation->get_length());
- //timeline->set_step(0.01);
- track_editor->update();
- length->set_value(animation->get_length());
- step->set_value(animation->get_step());
- }
-}
-
-
-void AnimationKeyEditor::_root_removed() {
-
- root=NULL;
-}
-
-void AnimationKeyEditor::_update_menu() {
-
-
- updating=true;
-
- if (animation.is_valid()) {
-
- length->set_value(animation->get_length());
- loop->set_pressed(animation->has_loop());
- step->set_value(animation->get_step());
- }
-
- track_editor->update();
- updating=false;
-
-}
-void AnimationKeyEditor::_clear_selection() {
-
- selection.clear();
- key_edit->animation=Ref<Animation>();
- key_edit->track=0;
- key_edit->key_ofs=0;
- key_edit->hint=PropertyInfo();
- key_edit->base=NodePath();
- key_edit->notify_change();
-
-}
-
-
-void AnimationKeyEditor::set_animation(const Ref<Animation>& p_anim) {
-
- if (animation.is_valid())
- animation->disconnect("changed",this,"_update_paths");
- animation=p_anim;
- if (animation.is_valid())
- animation->connect("changed",this,"_update_paths");
-
- timeline_pos=0;
- _clear_selection();
- _update_paths();
-
- _update_menu();
- selected_track=-1;
- _edit_if_single_selection();
-
- EditorNode::get_singleton()->update_keying();
-}
-
-void AnimationKeyEditor::set_root(Node *p_root) {
-
- if (root)
- root->disconnect("tree_exited",this,"_root_removed");
-
- root=p_root;
-
- if (root)
- root->connect("tree_exited",this,"_root_removed",make_binds(),CONNECT_ONESHOT);
-
-
-}
-
-Node *AnimationKeyEditor::get_root() const {
-
- return root;
-}
-
-
-
-
-
-
-void AnimationKeyEditor::update_keying() {
-
- bool keying_enabled=is_visible_in_tree() && animation.is_valid();
-
- if (keying_enabled==keying)
- return;
-
- keying=keying_enabled;
- _update_menu();
- emit_signal("keying_changed");
-
-}
-
-bool AnimationKeyEditor::has_keying() const {
-
- return keying;
-}
-
-void AnimationKeyEditor::_query_insert(const InsertData& p_id) {
-
-
- if (insert_frame!=Engine::get_singleton()->get_frames_drawn()) {
- //clear insert list for the frame if frame changed
- if (insert_confirm->is_visible_in_tree())
- return; //do nothing
- insert_data.clear();
- insert_query=false;
- }
- insert_frame=Engine::get_singleton()->get_frames_drawn();
-
- for (List<InsertData>::Element *E=insert_data.front();E;E=E->next()) {
- //prevent insertion of multiple tracks
- if (E->get().path==p_id.path)
- return; //already inserted a track for this on this frame
- }
-
- insert_data.push_back(p_id);
-
- if (p_id.track_idx==-1) {
- if (bool(EDITOR_DEF("editors/animation/confirm_insert_track",true))) {
- //potential new key, does not exist
- if (insert_data.size()==1)
- insert_confirm->set_text(vformat(TTR("Create NEW track for %s and insert key?"),p_id.query));
- else
- insert_confirm->set_text(vformat(TTR("Create %d NEW tracks and insert keys?"),insert_data.size()));
-
- insert_confirm->get_ok()->set_text(TTR("Create"));
- insert_confirm->popup_centered_minsize();
- insert_query=true;
- } else {
- call_deferred("_insert_delay");
- insert_queue=true;
- }
-
- } else {
- if (!insert_query && !insert_queue) {
- call_deferred("_insert_delay");
- insert_queue=true;
- }
- }
-
-}
-
-void AnimationKeyEditor::insert_transform_key(Spatial *p_node,const String& p_sub,const Transform& p_xform) {
-
- if (!keying)
- return;
- if (!animation.is_valid())
- return;
-
-
- ERR_FAIL_COND(!root);
- //let's build a node path
- String path = root->get_path_to(p_node);
- if (p_sub!="")
- path+=":"+p_sub;
-
- NodePath np=path;
-
- int track_idx=-1;
-
- for(int i=0;i<animation->get_track_count();i++) {
-
- if (animation->track_get_type(i)!=Animation::TYPE_TRANSFORM)
- continue;
- if (animation->track_get_path(i)!=np)
- continue;
-
- track_idx=i;
- break;
- }
-
- InsertData id;
- Dictionary val;
-
- id.path=np;
- id.track_idx=track_idx;
- id.value=p_xform;
- id.type=Animation::TYPE_TRANSFORM;
- id.query="node '"+p_node->get_name()+"'";
- id.advance=false;
-
- //dialog insert
-
- _query_insert(id);
-
-}
-
-
-void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_property,const Variant& p_value,bool p_only_if_exists) {
-
- ERR_FAIL_COND(!root);
- //let's build a node path
-
- Node *node = p_node;
-
- String path = root->get_path_to(node);
-
- for(int i=1;i<history->get_path_size();i++) {
-
- String prop = history->get_path_property(i);
- ERR_FAIL_COND(prop=="");
- path+=":"+prop;
- }
-
-
- path+=":"+p_property;
-
- NodePath np = path;
-
- //locate track
-
- int track_idx=-1;
-
- for(int i=0;i<animation->get_track_count();i++) {
-
- if (animation->track_get_type(i)!=Animation::TYPE_VALUE)
- continue;
- if (animation->track_get_path(i)!=np)
- continue;
-
- track_idx=i;
- break;
- }
-
- if (p_only_if_exists && track_idx==-1)
- return;
- InsertData id;
- id.path=np;
- id.track_idx=track_idx;
- id.value=p_value;
- id.type=Animation::TYPE_VALUE;
- id.query="property '"+p_property+"'";
- id.advance=false;
- //dialog insert
- _query_insert(id);
-
-
-
-}
-
-void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value,bool p_advance) {
-
- ERR_FAIL_COND(!root);
- //let's build a node path
- ERR_FAIL_COND(history->get_path_size()==0);
- Object *obj = ObjectDB::get_instance(history->get_path_object(0));
- ERR_FAIL_COND(!obj || !obj->cast_to<Node>());
-
- Node *node = obj->cast_to<Node>();
-
- String path = root->get_path_to(node);
-
- for(int i=1;i<history->get_path_size();i++) {
-
- String prop = history->get_path_property(i);
- ERR_FAIL_COND(prop=="");
- path+=":"+prop;
- }
-
-
-
- path+=":"+p_property;
-
- NodePath np = path;
-
- //locate track
-
- int track_idx=-1;
-
- for(int i=0;i<animation->get_track_count();i++) {
-
- if (animation->track_get_type(i)!=Animation::TYPE_VALUE)
- continue;
- if (animation->track_get_path(i)!=np)
- continue;
-
- track_idx=i;
- break;
- }
-
- InsertData id;
- id.path=np;
- id.track_idx=track_idx;
- id.value=p_value;
- id.type=Animation::TYPE_VALUE;
- id.query="property '"+p_property+"'";
- id.advance=p_advance;
- //dialog insert
- _query_insert(id);
-
-
-
-}
-
-void AnimationKeyEditor::_confirm_insert_list() {
-
-
- undo_redo->create_action(TTR("Anim Create & Insert"));
-
- int last_track = animation->get_track_count();
- while(insert_data.size()) {
-
- last_track=_confirm_insert(insert_data.front()->get(),last_track);
- insert_data.pop_front();
- }
-
- undo_redo->commit_action();
-}
-
-int AnimationKeyEditor::_confirm_insert(InsertData p_id,int p_last_track) {
-
- if (p_last_track==-1)
- p_last_track=animation->get_track_count();
-
- bool created=false;
- if (p_id.track_idx<0) {
-
- created=true;
- undo_redo->create_action(TTR("Anim Insert Track & Key"));
- Animation::UpdateMode update_mode=Animation::UPDATE_DISCRETE;
-
- if (p_id.type==Animation::TYPE_VALUE) {
- //wants a new tack
-
- {
- //shitty hack
- NodePath np;
- animation->add_track(p_id.type);
- animation->track_set_path(animation->get_track_count()-1,p_id.path);
- PropertyInfo h = _find_hint_for_track(animation->get_track_count()-1,np);
- animation->remove_track(animation->get_track_count()-1); //hack
-
- if ( h.type==Variant::REAL ||
- h.type==Variant::VECTOR2 ||
- h.type==Variant::RECT2 ||
- h.type==Variant::VECTOR3 ||
- h.type==Variant::RECT3 ||
- h.type==Variant::QUAT ||
- h.type==Variant::COLOR ||
- h.type==Variant::TRANSFORM ) {
-
- update_mode=Animation::UPDATE_CONTINUOUS;
- }
-
- if (h.usage&PROPERTY_USAGE_ANIMATE_AS_TRIGGER) {
- update_mode=Animation::UPDATE_TRIGGER;
- }
- }
- }
-
- p_id.track_idx=p_last_track;
-
- undo_redo->add_do_method(animation.ptr(),"add_track",p_id.type);
- undo_redo->add_do_method(animation.ptr(),"track_set_path",p_id.track_idx,p_id.path);
- if (p_id.type==Animation::TYPE_VALUE)
- undo_redo->add_do_method(animation.ptr(),"value_track_set_update_mode",p_id.track_idx,update_mode);
-
- } else {
- undo_redo->create_action(TTR("Anim Insert Key"));
- }
-
- float time = timeline_pos;
- Variant value;
-
-
- switch(p_id.type) {
-
- case Animation::TYPE_VALUE: {
-
- value = p_id.value;
-
-
- } break;
- case Animation::TYPE_TRANSFORM: {
-
-
- Transform tr = p_id.value;
- Dictionary d;
- d["loc"]=tr.origin;
- d["scale"]=tr.basis.get_scale();
- d["rot"]=Quat(tr.basis);//.orthonormalized();
- value=d;
- } break;
- default:{}
- }
-
-
-
- undo_redo->add_do_method(animation.ptr(),"track_insert_key",p_id.track_idx,time,value);
-
- if (created) {
-
- //just remove the track
- undo_redo->add_undo_method(animation.ptr(),"remove_track",p_last_track);
- p_last_track++;
- } else {
-
- undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",p_id.track_idx,time);
- int existing = animation->track_find_key(p_id.track_idx,time,true);
- if (existing!=-1) {
- Variant v = animation->track_get_key_value(p_id.track_idx,existing);
- float trans = animation->track_get_key_transition(p_id.track_idx,existing);
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",p_id.track_idx,time,v,trans);
- }
- }
-
- undo_redo->add_do_method(this,"update");
- undo_redo->add_undo_method(this,"update");
- undo_redo->add_do_method(track_editor,"update");
- undo_redo->add_undo_method(track_editor,"update");
- undo_redo->add_do_method(track_pos,"update");
- undo_redo->add_undo_method(track_pos,"update");
-
- undo_redo->commit_action();
-
- return p_last_track;
-
-}
-
-
-
-
-Ref<Animation> AnimationKeyEditor::get_current_animation() const {
-
- return animation;
-}
-
-void AnimationKeyEditor::_animation_len_changed(float p_len) {
-
-
- if (updating)
- return;
-
- if (!animation.is_null()) {
-
- undo_redo->create_action(TTR("Change Anim Len"));
- undo_redo->add_do_method(animation.ptr(),"set_length",p_len);
- undo_redo->add_undo_method(animation.ptr(),"set_length",animation->get_length());
- undo_redo->add_do_method(this,"_animation_len_update");
- undo_redo->add_undo_method(this,"_animation_len_update");
- undo_redo->commit_action();
- }
-}
-
-void AnimationKeyEditor::_animation_len_update() {
-
- if (!animation.is_null())
- emit_signal(alc,animation->get_length());
-}
-
-void AnimationKeyEditor::_animation_changed() {
- if (updating)
- return;
- _update_menu();
-
-}
-
-void AnimationKeyEditor::_animation_loop_changed() {
-
- if (updating)
- return;
-
- if (!animation.is_null()) {
-
- undo_redo->create_action(TTR("Change Anim Loop"));
- undo_redo->add_do_method(animation.ptr(),"set_loop",loop->is_pressed());
- undo_redo->add_undo_method(animation.ptr(),"set_loop",!loop->is_pressed());
- undo_redo->commit_action();
- }
-
-}
-
-
-void AnimationKeyEditor::_create_value_item(int p_type) {
-
- undo_redo->create_action(TTR("Anim Create Typed Value Key"));
-
- Variant::CallError ce;
- Variant v = Variant::construct(Variant::Type(p_type),NULL,0,ce);
- undo_redo->add_do_method(animation.ptr(),"track_insert_key",cvi_track,cvi_pos,v);
- undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",cvi_track,cvi_pos);
-
- int existing = animation->track_find_key(cvi_track,cvi_pos,true);
-
- if (existing!=-1) {
- Variant v = animation->track_get_key_value(cvi_track,existing);
- float trans = animation->track_get_key_transition(cvi_track,existing);
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",cvi_track,cvi_pos,v,trans);
- }
-
- undo_redo->commit_action();
-
-}
-
-
-void AnimationKeyEditor::set_anim_pos(float p_pos) {
-
- if (animation.is_null())
- return;
- timeline_pos=p_pos;
- update();
- track_pos->update();
- track_editor->update();
-}
-
-void AnimationKeyEditor::_pane_drag(const Point2& p_delta) {
-
- Size2 ecs = ec->get_custom_minimum_size();
- ecs.y-=p_delta.y;
- if (ecs.y<100)
- ecs.y=100;
- ec->set_custom_minimum_size(ecs);
-
-}
-
-void AnimationKeyEditor::_insert_delay() {
-
- if (insert_query) {
- //discard since it's entered into query mode
- insert_queue=false;
- return;
- }
-
- undo_redo->create_action(TTR("Anim Insert"));
-
- int last_track = animation->get_track_count();
- bool advance=false;
- while(insert_data.size()) {
-
- if (insert_data.front()->get().advance)
- advance=true;
- last_track=_confirm_insert(insert_data.front()->get(),last_track);
- insert_data.pop_front();
- }
-
- undo_redo->commit_action();
-
- if (advance) {
- float step = animation->get_step();
- if (step==0)
- step=1;
-
- float pos=timeline_pos;
-
- pos=Math::stepify(pos+step,step);
- if (pos>animation->get_length())
- pos=animation->get_length();
- timeline_pos=pos;
- track_pos->update();
- emit_signal("timeline_changed",pos,true);
- }
- insert_queue=false;
-}
-
-void AnimationKeyEditor::_step_changed(float p_len) {
-
- updating=true;
- if (!animation.is_null()) {
- animation->set_step(p_len);
- emit_signal("animation_step_changed",animation->get_step());
- }
- updating=false;
-}
-
-void AnimationKeyEditor::_scale() {
-
-
- if (selection.empty())
- return;
-
-
- float from_t = 1e20;
- float to_t = -1e20;
- float len = -1e20;
- float pivot=0;
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) {
- float t = animation->track_get_key_time(E->key().track,E->key().key);
- if (t<from_t)
- from_t=t;
- if (t>to_t)
- to_t=t;
-
- }
-
- len=to_t-from_t;
- if (last_menu_track_opt==TRACK_MENU_SCALE_PIVOT) {
- pivot = timeline_pos;
-
- } else {
-
- pivot=from_t;
-
- }
-
- float s = scale->get_value();
- if (s==0) {
- ERR_PRINT("Can't scale to 0");
- }
-
-
-
- undo_redo->create_action(TTR("Anim Scale Keys"));
-
- List<_AnimMoveRestore> to_restore;
-
- // 1-remove the keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- undo_redo->add_do_method(animation.ptr(),"track_remove_key",E->key().track,E->key().key);
- }
- // 2- remove overlapped keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float newtime = (E->get().pos-from_t)*s+from_t;
- int idx = animation->track_find_key(E->key().track,newtime,true);
- if (idx==-1)
- continue;
- SelectedKey sk;
- sk.key=idx;
- sk.track=E->key().track;
- if (selection.has(sk))
- continue; //already in selection, don't save
-
- undo_redo->add_do_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newtime);
- _AnimMoveRestore amr;
-
- amr.key=animation->track_get_key_value(E->key().track,idx);
- amr.track=E->key().track;
- amr.time=newtime;
- amr.transition=animation->track_get_key_transition(E->key().track,idx);
-
- to_restore.push_back(amr);
-
- }
-
-#define _NEW_POS(m_ofs) (((s>0)?m_ofs:from_t+(len-(m_ofs-from_t)))-pivot)*ABS(s)+from_t
- // 3-move the keys (re insert them)
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float newpos=_NEW_POS(E->get().pos);
- undo_redo->add_do_method(animation.ptr(),"track_insert_key",E->key().track,newpos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
-
- }
-
- // 4-(undo) remove inserted keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float newpos=_NEW_POS(E->get().pos);
- undo_redo->add_undo_method(animation.ptr(),"track_remove_key_at_pos",E->key().track,newpos);
-
- }
-
- // 5-(undo) reinsert keys
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key));
-
- }
-
- // 6-(undo) reinsert overlapped keys
- for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
-
- _AnimMoveRestore &amr = E->get();
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
-
- }
-
- // 6-(undo) reinsert overlapped keys
- for(List<_AnimMoveRestore>::Element *E=to_restore.front();E;E=E->next()) {
-
- _AnimMoveRestore &amr = E->get();
- undo_redo->add_undo_method(animation.ptr(),"track_insert_key",amr.track,amr.time,amr.key,amr.transition);
-
- }
-
- undo_redo->add_do_method(this,"_clear_selection_for_anim",animation);
- undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation);
-
- // 7-reselect
-
- for(Map<SelectedKey,KeyInfo>::Element *E=selection.back();E;E=E->prev()) {
-
- float oldpos=E->get().pos;
- float newpos=_NEW_POS(oldpos);
- if (newpos>=0)
- undo_redo->add_do_method(this,"_select_at_anim",animation,E->key().track,newpos);
- undo_redo->add_undo_method(this,"_select_at_anim",animation,E->key().track,oldpos);
-
- }
-#undef _NEW_POS
- undo_redo->commit_action();
-
-}
-
-
-void AnimationKeyEditor::_add_call_track(const NodePath& p_base) {
-
-
- Node* base = EditorNode::get_singleton()->get_edited_scene();
- if (!base)
- return;
- Node* from=base->get_node(p_base);
- if (!from || !root)
- return;
-
- NodePath path = root->get_path_to(from);
-
- //print_line("root: "+String(root->get_path()));
- //print_line("path: "+String(path));
-
- undo_redo->create_action(TTR("Anim Add Call Track"));
- undo_redo->add_do_method(animation.ptr(),"add_track",Animation::TYPE_METHOD);
- undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),path);
- undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
- undo_redo->commit_action();
-
-}
-
-void AnimationKeyEditor::cleanup() {
-
- set_animation(Ref<Animation>());
-}
-
-void AnimationKeyEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_root_removed"),&AnimationKeyEditor::_root_removed);
- ClassDB::bind_method(_MD("_scale"),&AnimationKeyEditor::_scale);
- ClassDB::bind_method(_MD("set_root"),&AnimationKeyEditor::set_root);
-
-
- //ClassDB::bind_method(_MD("_confirm_insert"),&AnimationKeyEditor::_confirm_insert);
- ClassDB::bind_method(_MD("_confirm_insert_list"),&AnimationKeyEditor::_confirm_insert_list);
-
-
-
- ClassDB::bind_method(_MD("_update_paths"),&AnimationKeyEditor::_update_paths);
- ClassDB::bind_method(_MD("_track_editor_draw"),&AnimationKeyEditor::_track_editor_draw);
-
-
-
-
- ClassDB::bind_method(_MD("_animation_changed"),&AnimationKeyEditor::_animation_changed);
- ClassDB::bind_method(_MD("_scroll_changed"),&AnimationKeyEditor::_scroll_changed);
- ClassDB::bind_method(_MD("_track_editor_gui_input"),&AnimationKeyEditor::_track_editor_gui_input);
- ClassDB::bind_method(_MD("_track_name_changed"),&AnimationKeyEditor::_track_name_changed);
- ClassDB::bind_method(_MD("_track_menu_selected"),&AnimationKeyEditor::_track_menu_selected);
- ClassDB::bind_method(_MD("_menu_add_track"),&AnimationKeyEditor::_menu_add_track);
- ClassDB::bind_method(_MD("_menu_track"),&AnimationKeyEditor::_menu_track);
- ClassDB::bind_method(_MD("_clear_selection_for_anim"),&AnimationKeyEditor::_clear_selection_for_anim);
- ClassDB::bind_method(_MD("_select_at_anim"),&AnimationKeyEditor::_select_at_anim);
- ClassDB::bind_method(_MD("_track_pos_draw"),&AnimationKeyEditor::_track_pos_draw);
- ClassDB::bind_method(_MD("_insert_delay"),&AnimationKeyEditor::_insert_delay);
- ClassDB::bind_method(_MD("_step_changed"),&AnimationKeyEditor::_step_changed);
-
-
- ClassDB::bind_method(_MD("_animation_loop_changed"),&AnimationKeyEditor::_animation_loop_changed);
- ClassDB::bind_method(_MD("_animation_len_changed"),&AnimationKeyEditor::_animation_len_changed);
- ClassDB::bind_method(_MD("_create_value_item"),&AnimationKeyEditor::_create_value_item);
- ClassDB::bind_method(_MD("_pane_drag"),&AnimationKeyEditor::_pane_drag);
-
- ClassDB::bind_method(_MD("_animation_len_update"),&AnimationKeyEditor::_animation_len_update);
-
- ClassDB::bind_method(_MD("set_animation"),&AnimationKeyEditor::set_animation);
- ClassDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize);
- ClassDB::bind_method(_MD("_curve_transition_changed"),&AnimationKeyEditor::_curve_transition_changed);
- ClassDB::bind_method(_MD("_toggle_edit_curves"),&AnimationKeyEditor::_toggle_edit_curves);
- ClassDB::bind_method(_MD("_add_call_track"),&AnimationKeyEditor::_add_call_track);
-
-
- ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
- ADD_SIGNAL( MethodInfo("keying_changed" ) );
- ADD_SIGNAL( MethodInfo("timeline_changed", PropertyInfo(Variant::REAL,"pos"), PropertyInfo(Variant::BOOL,"drag") ) );
- 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() {
-
- alc="animation_len_changed";
- editor_selection=EditorNode::get_singleton()->get_editor_selection();
-
- selected_track=-1;
- updating=false;
- te_drawing=false;
- 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_value(0);
-
-
- HBoxContainer *hb = memnew( HBoxContainer );
- add_child(hb);
-
-
- root=NULL;
- //menu = memnew( MenuButton );
- //menu->set_flat(true);
- //menu->set_pos(Point2());
- //add_child(menu);
-
- zoomicon = memnew( TextureRect );
- hb->add_child(zoomicon);
- zoomicon->set_tooltip(TTR("Animation zoom."));
-
- zoom = memnew( HSlider );
- //hb->add_child(zoom);
- zoom->set_step(0.01);
- zoom->set_min(0.0);
- zoom->set_max(2.0);
- zoom->set_value(1.0);
- zoom->set_h_size_flags(SIZE_EXPAND_FILL);
- zoom->set_stretch_ratio(2);
- hb->add_child(zoom);
- zoom->connect("value_changed",this,"_scroll_changed");
- zoom->set_tooltip(TTR("Animation zoom."));
-
- hb->add_child( memnew( VSeparator ) );
-
- Label *l = memnew( Label );
- l->set_text(TTR("Length (s):"));
- hb->add_child(l);
-
- length = memnew( SpinBox );
- length->set_min(0.01);
- length->set_max(10000);
- length->set_step(0.01);
- length->set_h_size_flags(SIZE_EXPAND_FILL);
- length->set_stretch_ratio(1);
- length->set_tooltip(TTR("Animation length (in seconds)."));
-
- hb->add_child(length);
- length->connect("value_changed",this,"_animation_len_changed");
-
- l = memnew( Label );
- l->set_text(TTR("Step (s):"));
- hb->add_child(l);
-
- step = memnew( SpinBox );
- step->set_min(0.00);
- step->set_max(128);
- step->set_step(0.01);
- step->set_value(0.0);
- step->set_h_size_flags(SIZE_EXPAND_FILL);
- step->set_stretch_ratio(1);
- step->set_tooltip(TTR("Cursor step snap (in seconds)."));
-
- hb->add_child(step);
- step->connect("value_changed",this,"_step_changed");
-
- loop = memnew( ToolButton );
- loop->set_toggle_mode(true);
- loop->connect("pressed",this,"_animation_loop_changed");
- hb->add_child(loop);
- loop->set_tooltip(TTR("Enable/Disable looping in animation."));
-
- hb->add_child( memnew( VSeparator ) );
-
- menu_add_track = memnew( MenuButton );
- hb->add_child(menu_add_track);
- menu_add_track->get_popup()->connect("id_pressed",this,"_menu_add_track");
- menu_add_track->set_tooltip(TTR("Add new tracks."));
-
- move_up_button = memnew( ToolButton );
- hb->add_child(move_up_button);
- move_up_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_MOVE_UP));
- move_up_button->set_focus_mode(FOCUS_NONE);
- move_up_button->set_disabled(true);
- move_up_button->set_tooltip(TTR("Move current track up."));
-
- move_down_button = memnew( ToolButton );
- hb->add_child(move_down_button);
- move_down_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_MOVE_DOWN));
- move_down_button->set_focus_mode(FOCUS_NONE);
- move_down_button->set_disabled(true);
- move_down_button->set_tooltip(TTR("Move current track down."));
-
- remove_button = memnew( ToolButton );
- hb->add_child(remove_button);
- remove_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_REMOVE));
- remove_button->set_focus_mode(FOCUS_NONE);
- remove_button->set_disabled(true);
- remove_button->set_tooltip(TTR("Remove selected track."));
-
- hb->add_child(memnew( VSeparator ));
-
- menu_track = memnew( MenuButton );
- hb->add_child(menu_track);
- menu_track->get_popup()->connect("id_pressed",this,"_menu_track");
- menu_track->set_tooltip(TTR("Track tools"));
-
- edit_button = memnew( ToolButton );
- edit_button->set_toggle_mode(true);
- edit_button->set_focus_mode(FOCUS_NONE);
- edit_button->set_disabled(true);
-
- hb->add_child(edit_button);
- edit_button->set_tooltip(TTR("Enable editing of individual keys by clicking them."));
-
- optimize_dialog = memnew( ConfirmationDialog );
- add_child(optimize_dialog);
- optimize_dialog->set_title(TTR("Anim. Optimizer"));
- VBoxContainer *optimize_vb = memnew( VBoxContainer );
- optimize_dialog->add_child(optimize_vb);
-
- optimize_linear_error = memnew( SpinBox );
- optimize_linear_error->set_max(1.0);
- optimize_linear_error->set_min(0.001);
- optimize_linear_error->set_step(0.001);
- optimize_linear_error->set_value(0.05);
- optimize_vb->add_margin_child(TTR("Max. Linear Error:"),optimize_linear_error);
- optimize_angular_error = memnew( SpinBox );
- optimize_angular_error->set_max(1.0);
- optimize_angular_error->set_min(0.001);
- optimize_angular_error->set_step(0.001);
- optimize_angular_error->set_value(0.01);
-
- optimize_vb->add_margin_child(TTR("Max. Angular Error:"),optimize_angular_error);
- optimize_max_angle = memnew( SpinBox );
- optimize_vb->add_margin_child(TTR("Max Optimizable Angle:"),optimize_max_angle);
- optimize_max_angle->set_max(360.0);
- optimize_max_angle->set_min(0.0);
- optimize_max_angle->set_step(0.1);
- optimize_max_angle->set_value(22);
-
- optimize_dialog->get_ok()->set_text(TTR("Optimize"));
-
-
-
- /*keying = memnew( Button );
- keying->set_toggle_mode(true);
- //keying->set_text("Keys");
- keying->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,60);
- keying->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,10);
- keying->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,55);
- keying->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,10);
- //add_child(keying);
- keying->connect("pressed",this,"_keying_toggled");
- */
-
-/* l = memnew( Label );
- l->set_text("Base: ");
- l->set_pos(Point2(0,3));
- //dr_panel->add_child(l);*/
-
- //menu->get_popup()->connect("id_pressed",this,"_menu_callback");
-
-
- hb = memnew( HBoxContainer);
- hb->set_area_as_parent_rect();
- ec->add_child(hb);
- hb->set_v_size_flags(SIZE_EXPAND_FILL);
-
- track_editor = memnew( Control );
- track_editor->connect("draw",this,"_track_editor_draw");
- hb->add_child(track_editor);
- track_editor->connect("gui_input",this,"_track_editor_gui_input");
- track_editor->set_focus_mode(Control::FOCUS_ALL);
- track_editor->set_h_size_flags(SIZE_EXPAND_FILL);
-
-
-
- track_pos = memnew( Control );
- track_pos->set_area_as_parent_rect();
- track_pos->set_mouse_filter(MOUSE_FILTER_IGNORE);
- track_editor->add_child(track_pos);
- track_pos->connect("draw",this,"_track_pos_draw");
-
- select_anim_warning = memnew( Label );
- track_editor->add_child(select_anim_warning);
- select_anim_warning->set_area_as_parent_rect();
- select_anim_warning->set_text(TTR("Select an AnimationPlayer from the Scene Tree to edit animations."));
- select_anim_warning->set_autowrap(true);
- select_anim_warning->set_align(Label::ALIGN_CENTER);
- select_anim_warning->set_valign(Label::VALIGN_CENTER);
-
-
-
- v_scroll = memnew( VScrollBar );
- hb->add_child(v_scroll);
- v_scroll->connect("value_changed",this,"_scroll_changed");
- v_scroll->set_value(0);
-
- key_editor_tab = memnew(TabContainer);
- hb->add_child(key_editor_tab);
- key_editor_tab->set_custom_minimum_size(Size2(200,0));
-
- key_editor = memnew( PropertyEditor );
- key_editor->set_area_as_parent_rect();
- key_editor->hide_top_label();
- key_editor->set_name(TTR("Key"));
- key_editor_tab->add_child(key_editor);
-
- key_edit = memnew( AnimationKeyEdit );
- key_edit->undo_redo=undo_redo;
- //key_edit->ke_dialog=key_edit_dialog;
-
- type_menu = memnew( PopupMenu );
- add_child(type_menu);
- for(int i=0;i<Variant::VARIANT_MAX;i++)
- type_menu->add_item(Variant::get_type_name(Variant::Type(i)),i);
- type_menu->connect("id_pressed",this,"_create_value_item");
-
- VBoxContainer *curve_vb = memnew( VBoxContainer );
- curve_vb->set_name(TTR("Transition"));
- HBoxContainer *curve_hb = memnew( HBoxContainer );
- curve_vb->add_child(curve_hb);
-
- curve_linear = memnew( ToolButton );
- curve_linear->set_focus_mode(FOCUS_NONE);
- curve_hb->add_child(curve_linear);
- curve_in = memnew( ToolButton );
- curve_in->set_focus_mode(FOCUS_NONE);
- curve_hb->add_child(curve_in);
- curve_out = memnew( ToolButton );
- curve_out->set_focus_mode(FOCUS_NONE);
- curve_hb->add_child(curve_out);
- curve_inout = memnew( ToolButton );
- curve_inout->set_focus_mode(FOCUS_NONE);
- curve_hb->add_child(curve_inout);
- curve_outin = memnew( ToolButton );
- curve_outin->set_focus_mode(FOCUS_NONE);
- curve_hb->add_child(curve_outin);
- curve_constant = memnew( ToolButton );
- curve_constant->set_focus_mode(FOCUS_NONE);
- curve_hb->add_child(curve_constant);
-
-
- curve_edit = memnew( AnimationCurveEdit );
- curve_vb->add_child(curve_edit);
- curve_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- key_editor_tab->add_child(curve_vb);
-
- track_name = memnew( LineEdit );
- track_name->set_as_toplevel(true);
- track_name->hide();
- add_child(track_name);
- track_name->connect("text_entered",this,"_track_name_changed");
- track_menu = memnew( PopupMenu );
- add_child(track_menu);
- track_menu->connect("id_pressed",this,"_track_menu_selected");
-
- key_editor_tab->hide();
-
- last_idx =1;
-
- _update_menu();
-
-
-
- insert_confirm = memnew( ConfirmationDialog );
- add_child(insert_confirm);
- insert_confirm->connect("confirmed",this,"_confirm_insert_list");
-
- click.click=ClickOver::CLICK_NONE;
-
-
- name_column_ratio=0.3;
- timeline_pos=0;
-
-
- keying=false;
- insert_frame=0;
- insert_query=false;
- insert_queue=false;
-
- editor_selection->connect("selection_changed",track_editor,"update");
-
-
- scale_dialog = memnew( ConfirmationDialog );
- VBoxContainer *vbc = memnew( VBoxContainer );
- scale_dialog->add_child(vbc);
-
- scale = memnew( SpinBox );
- scale->set_min(-99999);
- scale->set_max(99999);
- scale->set_step(0.001);
- vbc->add_margin_child(TTR("Scale Ratio:"),scale);
- scale_dialog->connect("confirmed",this,"_scale");
- add_child(scale_dialog);
-
- call_select = memnew( SceneTreeDialog );
- add_child(call_select);
- call_select->set_title(TTR("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_keys = memnew( CheckButton );
- cleanup_keys->set_text(TTR("Remove invalid keys"));
- cleanup_keys->set_pressed(true);
- cleanup_vb->add_child(cleanup_keys);
-
- cleanup_tracks = memnew( CheckButton );
- cleanup_tracks->set_text(TTR("Remove unresolved and empty tracks"));
- cleanup_tracks->set_pressed(true);
- cleanup_vb->add_child(cleanup_tracks);
-
- cleanup_all = memnew( CheckButton );
- cleanup_all->set_text(TTR("Clean-up all animations"));
- cleanup_vb->add_child(cleanup_all);
-
- cleanup_dialog->set_title(TTR("Clean-Up Animation(s) (NO UNDO!)"));
- cleanup_dialog->get_ok()->set_text(TTR("Clean-Up"));
-
- cleanup_dialog->connect("confirmed",this,"_menu_track",varray(TRACK_MENU_CLEAN_UP_CONFIRM));
-
- add_constant_override("separation",get_constant("separation","VBoxContainer"));
-
- track_editor->set_clip_contents(true);
-
-}
-
-AnimationKeyEditor::~AnimationKeyEditor() {
-
-
-
- memdelete( key_edit );
-
-}
diff --git a/tools/editor/array_property_edit.cpp b/tools/editor/array_property_edit.cpp
deleted file mode 100644
index b587c4f830..0000000000
--- a/tools/editor/array_property_edit.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*************************************************************************/
-/* array_property_edit.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "array_property_edit.h"
-
-#include "editor_node.h"
-
-#define ITEMS_PER_PAGE 100
-
-Variant ArrayPropertyEdit::get_array() const{
-
- Object*o = ObjectDB::get_instance(obj);
- if (!o)
- return Array();
- Variant arr=o->get(property);
- if (!arr.is_array()) {
- Variant::CallError ce;
- arr=Variant::construct(default_type,NULL,0,ce);
- }
- return arr;
-}
-
-void ArrayPropertyEdit::_notif_change() {
- _change_notify();
-}
-void ArrayPropertyEdit::_notif_changev(const String& p_v) {
-
- _change_notify(p_v.utf8().get_data());
-}
-
-void ArrayPropertyEdit::_set_size(int p_size) {
-
- Variant arr = get_array();
- arr.call("resize",p_size);
- Object*o = ObjectDB::get_instance(obj);
- if (!o)
- return;
-
- o->set(property,arr);
-
-}
-
-void ArrayPropertyEdit::_set_value(int p_idx,const Variant& p_value) {
-
- Variant arr = get_array();
- arr.set(p_idx,p_value);
- Object*o = ObjectDB::get_instance(obj);
- if (!o)
- return;
-
- o->set(property,arr);
-}
-
-bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){
-
- String pn=p_name;
-
- if (pn.begins_with("array/")) {
-
- if (pn=="array/size") {
-
- Variant arr = get_array();
- int size = arr.call("size");
-
- int newsize=p_value;
- if (newsize==size)
- return true;
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Resize Array"));
- ur->add_do_method(this,"_set_size",newsize);
- ur->add_undo_method(this,"_set_size",size);
- if (newsize<size) {
- for(int i=newsize;i<size;i++) {
- ur->add_undo_method(this,"_set_value",i,arr.get(i));
-
- }
- } else if (newsize>size) {
-
- Variant init;
- Variant::CallError ce;
- Variant::Type new_type = subtype;
- if(new_type==Variant::NIL && size) {
- new_type = arr.get(size-1).get_type();
- }
- if(new_type!=Variant::NIL) {
- init = Variant::construct(new_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");
- ur->commit_action();
- return true;
- }
- if (pn=="array/page") {
- page=p_value;
- _change_notify();
- return true;
- }
-
- } else if (pn.begins_with("indices")) {
-
- if (pn.find("_")!=-1) {
- //type
- int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
-
- int type = p_value;
-
- Variant arr = get_array();
-
- Variant value = arr.get(idx);
- if (value.get_type()!=type && type>=0 && type<Variant::VARIANT_MAX) {
- Variant::CallError ce;
- Variant new_value=Variant::construct(Variant::Type(type),NULL,0,ce);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-
- ur->create_action(TTR("Change Array Value Type"));
- ur->add_do_method(this,"_set_value",idx,new_value);
- ur->add_undo_method(this,"_set_value",idx,value);
- ur->add_do_method(this,"_notif_change");
- ur->add_undo_method(this,"_notif_change");
- ur->commit_action();
-
- }
- return true;
-
- } else {
- int idx=pn.get_slicec('/',1).to_int();
- Variant arr = get_array();
-
- Variant value = arr.get(idx);
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-
- ur->create_action(TTR("Change Array Value"));
- ur->add_do_method(this,"_set_value",idx,p_value);
- ur->add_undo_method(this,"_set_value",idx,value);
- ur->add_do_method(this,"_notif_changev",p_name);
- ur->add_undo_method(this,"_notif_changev",p_name);
- ur->commit_action();
- return true;
- }
- }
-
- return false;
-}
-
-bool ArrayPropertyEdit::_get(const StringName& p_name,Variant &r_ret) const {
-
- Variant arr = get_array();
- //int size = arr.call("size");
-
- String pn=p_name;
- if (pn.begins_with("array/")) {
-
- if (pn=="array/size") {
- r_ret=arr.call("size");
- return true;
- }
- if (pn=="array/page") {
- r_ret=page;
- return true;
- }
- } else if (pn.begins_with("indices")) {
-
- if (pn.find("_")!=-1) {
- //type
- int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
- bool valid;
- r_ret=arr.get(idx,&valid);
- if (valid)
- r_ret=r_ret.get_type();
- return valid;
-
- } else {
- int idx=pn.get_slicec('/',1).to_int();
- bool valid;
- r_ret=arr.get(idx,&valid);
- return valid;
- }
- }
-
- return false;
-}
-
-void ArrayPropertyEdit::_get_property_list( List<PropertyInfo> *p_list) const{
-
- Variant arr = get_array();
- int size = arr.call("size");
-
- p_list->push_back( PropertyInfo(Variant::INT,"array/size",PROPERTY_HINT_RANGE,"0,100000,1") );
- int pages = size/ITEMS_PER_PAGE;
- if (pages>0)
- p_list->push_back( PropertyInfo(Variant::INT,"array/page",PROPERTY_HINT_RANGE,"0,"+itos(pages)+",1") );
-
- int offset=page*ITEMS_PER_PAGE;
-
- int items=MIN(size-offset,ITEMS_PER_PAGE);
-
-
- for(int i=0;i<items;i++) {
-
- Variant v=arr.get(i+offset);
- bool is_typed = arr.get_type()!=Variant::ARRAY || subtype!=Variant::NIL;
-
- if (!is_typed) {
- p_list->push_back(PropertyInfo(Variant::INT,"indices/"+itos(i+offset)+"_type",PROPERTY_HINT_ENUM,vtypes));
- }
-
- if (is_typed || v.get_type()!=Variant::NIL ) {
- PropertyInfo pi(v.get_type(),"indices/"+itos(i+offset));
- if(subtype!=Variant::NIL) {
- pi.type = Variant::Type(subtype);
- pi.hint = PropertyHint(subtype_hint);
- pi.hint_string = subtype_hint_string;
- } else if (v.get_type()==Variant::OBJECT) {
- pi.hint=PROPERTY_HINT_RESOURCE_TYPE;
- pi.hint_string="Resource";
- }
-
- p_list->push_back(pi);
- }
- }
-
-}
-
-void ArrayPropertyEdit::edit(Object* p_obj,const StringName& p_prop,const String& p_hint_string,Variant::Type p_deftype) {
-
- page=0;
- property=p_prop;
- obj=p_obj->get_instance_ID();
- default_type=p_deftype;
-
- if(!p_hint_string.empty()) {
- int hint_subtype_seperator = p_hint_string.find(":");
- if(hint_subtype_seperator >= 0) {
- String subtype_string = p_hint_string.substr(0,hint_subtype_seperator);
-
- int slash_pos = subtype_string.find("/");
- if(slash_pos >= 0) {
- subtype_hint = PropertyHint(subtype_string.substr(slash_pos+1, subtype_string.size()-slash_pos-1).to_int());
- subtype_string = subtype_string.substr(0,slash_pos);
- }
-
- subtype_hint_string = p_hint_string.substr(hint_subtype_seperator+1, p_hint_string.size() - hint_subtype_seperator-1);
- subtype=Variant::Type(subtype_string.to_int());
- }
- }
-
-}
-
-Node *ArrayPropertyEdit::get_node() {
-
- Object *o = ObjectDB::get_instance(obj);
- if (!o)
- return NULL;
-
- return o->cast_to<Node>();
-}
-
-void ArrayPropertyEdit::_bind_methods() {
-
- ClassDB::bind_method(_MD("_set_size"),&ArrayPropertyEdit::_set_size);
- ClassDB::bind_method(_MD("_set_value"),&ArrayPropertyEdit::_set_value);
- ClassDB::bind_method(_MD("_notif_change"),&ArrayPropertyEdit::_notif_change);
- ClassDB::bind_method(_MD("_notif_changev"),&ArrayPropertyEdit::_notif_changev);
-}
-
-ArrayPropertyEdit::ArrayPropertyEdit()
-{
- page=0;
- for(int i=0;i<Variant::VARIANT_MAX;i++) {
-
- if (i>0)
- vtypes+=",";
- vtypes+=Variant::get_type_name( Variant::Type(i) );
- }
- default_type=Variant::NIL;
- subtype=Variant::NIL;
- subtype_hint=PROPERTY_HINT_NONE;
- subtype_hint_string="";
-}
diff --git a/tools/editor/asset_library_editor_plugin.cpp b/tools/editor/asset_library_editor_plugin.cpp
deleted file mode 100644
index 6ba7a7e79b..0000000000
--- a/tools/editor/asset_library_editor_plugin.cpp
+++ /dev/null
@@ -1,1553 +0,0 @@
-/*************************************************************************/
-/* asset_library_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "asset_library_editor_plugin.h"
-
-#include "editor_node.h"
-#include "editor_settings.h"
-#include "io/json.h"
-
-
-void EditorAssetLibraryItem::configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost) {
-
- title->set_text(p_title);
- asset_id=p_asset_id;
- category->set_text(p_category);
- category_id=p_category_id;
- author->set_text(p_author);
- author_id=p_author_id;
- price->set_text(p_cost);
-
- for(int i=0;i<5;i++) {
- if (i<p_rating)
- stars[i]->set_texture(get_icon("RatingStar","EditorIcons"));
- else
- stars[i]->set_texture(get_icon("RatingNoStar","EditorIcons"));
- }
-
-
-}
-
-void EditorAssetLibraryItem::set_image(int p_type,int p_index,const Ref<Texture>& p_image) {
-
- ERR_FAIL_COND(p_type!=EditorAssetLibrary::IMAGE_QUEUE_ICON);
- ERR_FAIL_COND(p_index!=0);
-
- icon->set_normal_texture(p_image);
-}
-
-void EditorAssetLibraryItem::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- icon->set_normal_texture(get_icon("GodotAssetDefault","EditorIcons"));
- category->add_color_override("font_color", Color(0.5,0.5,0.5) );
- author->add_color_override("font_color", Color(0.5,0.5,0.5) );
-
- }
-}
-
-void EditorAssetLibraryItem::_asset_clicked() {
-
- emit_signal("asset_selected",asset_id);
-}
-
-void EditorAssetLibraryItem::_category_clicked(){
-
- emit_signal("category_selected",category_id);
-}
-void EditorAssetLibraryItem::_author_clicked(){
-
- emit_signal("author_selected",author_id);
-
-}
-
-void EditorAssetLibraryItem::_bind_methods() {
-
- ClassDB::bind_method("set_image",&EditorAssetLibraryItem::set_image);
- ClassDB::bind_method("_asset_clicked",&EditorAssetLibraryItem::_asset_clicked);
- ClassDB::bind_method("_category_clicked",&EditorAssetLibraryItem::_category_clicked);
- ClassDB::bind_method("_author_clicked",&EditorAssetLibraryItem::_author_clicked);
- ADD_SIGNAL( MethodInfo("asset_selected"));
- ADD_SIGNAL( MethodInfo("category_selected"));
- ADD_SIGNAL( MethodInfo("author_selected"));
-
-
-}
-
-EditorAssetLibraryItem::EditorAssetLibraryItem() {
-
- Ref<StyleBoxEmpty> border;
- border.instance();
- /*border->set_default_margin(MARGIN_LEFT,5);
- border->set_default_margin(MARGIN_RIGHT,5);
- border->set_default_margin(MARGIN_BOTTOM,5);
- border->set_default_margin(MARGIN_TOP,5);*/
- add_style_override("panel",border);
-
- HBoxContainer *hb = memnew( HBoxContainer );
- add_child(hb);
-
- icon = memnew( TextureButton );
- icon->set_default_cursor_shape(CURSOR_POINTING_HAND);
- icon->connect("pressed",this,"_asset_clicked");
-
- hb->add_child(icon);
-
- VBoxContainer *vb = memnew( VBoxContainer );
-
- hb->add_child(vb);
- vb->set_h_size_flags(SIZE_EXPAND_FILL);
-
- title = memnew( LinkButton );
- title->set_text("My Awesome Addon");
- title->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- title->connect("pressed",this,"_asset_clicked");
- vb->add_child(title);
-
-
- category = memnew( LinkButton );
- category->set_text("Editor Tools");
- category->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- category->connect("pressed",this,"_category_clicked");
- vb->add_child(category);
-
- author = memnew( LinkButton );
- author->set_text("Johny Tolengo");
- author->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- author->connect("pressed",this,"_author_clicked");
- vb->add_child(author);
-
- HBoxContainer *rating_hb = memnew( HBoxContainer );
- vb->add_child(rating_hb);
-
- for(int i=0;i<5;i++) {
- stars[i]=memnew(TextureRect);
- rating_hb->add_child(stars[i]);
- }
- price = memnew( Label );
- price->set_text("Free");
- vb->add_child(price);
-
- set_custom_minimum_size(Size2(250,100));
- set_h_size_flags(SIZE_EXPAND_FILL);
-
- set_mouse_filter(MOUSE_FILTER_PASS);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-
-void EditorAssetLibraryItemDescription::set_image(int p_type,int p_index,const Ref<Texture>& p_image) {
-
- switch(p_type) {
-
- case EditorAssetLibrary::IMAGE_QUEUE_ICON: {
-
- item->call("set_image",p_type,p_index,p_image);
- icon=p_image;
- } break;
- case EditorAssetLibrary::IMAGE_QUEUE_THUMBNAIL: {
-
- for(int i=0;i<preview_images.size();i++) {
- if (preview_images[i].id==p_index) {
- preview_images[i].button->set_icon(p_image);
- break;
- }
- }
- //item->call("set_image",p_type,p_index,p_image);
- } break;
- case EditorAssetLibrary::IMAGE_QUEUE_SCREENSHOT: {
-
- for(int i=0;i<preview_images.size();i++) {
- if (preview_images[i].id==p_index) {
- preview_images[i].image = p_image;
- if(preview_images[i].button->is_pressed()) {
- _preview_click(p_index);
- }
- break;
- }
- }
- //item->call("set_image",p_type,p_index,p_image);
- } break;
- }
-}
-
-void EditorAssetLibraryItemDescription::_bind_methods() {
- ClassDB::bind_method(_MD("set_image"),&EditorAssetLibraryItemDescription::set_image);
- ClassDB::bind_method(_MD("_link_click"),&EditorAssetLibraryItemDescription::_link_click);
- ClassDB::bind_method(_MD("_preview_click"),&EditorAssetLibraryItemDescription::_preview_click);
-
-}
-
-void EditorAssetLibraryItemDescription::_link_click(const String& p_url) {
- ERR_FAIL_COND(!p_url.begins_with("http"));
- OS::get_singleton()->shell_open(p_url);
-}
-
-void EditorAssetLibraryItemDescription::_preview_click(int p_id) {
- for(int i=0;i<preview_images.size();i++) {
- if(preview_images[i].id==p_id) {
- preview_images[i].button->set_pressed(true);
- if(!preview_images[i].is_video) {
- if(preview_images[i].image.is_valid()) {
- preview->set_texture(preview_images[i].image);
- }
- } else {
- _link_click(preview_images[i].video_link);
- }
- } else {
- preview_images[i].button->set_pressed(false);
- }
- }
-}
-
-void EditorAssetLibraryItemDescription::configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost,int p_version,const String& p_version_string,const String& p_description,const String& p_download_url,const String& p_browse_url,const String& p_sha256_hash) {
-
- asset_id=p_asset_id;
- title=p_title;
- download_url=p_download_url;
- sha256=p_sha256_hash;
- item->configure(p_title,p_asset_id,p_category,p_category_id,p_author,p_author_id,p_rating,p_cost);
- description->clear();
- description->add_text("Version: "+p_version_string+"\n");
- description->add_text("Contents: ");
- description->push_meta(p_browse_url);
- description->add_text("View Files");
- description->pop();
- description->add_text("\nDescription:\n\n");
- description->append_bbcode(p_description);
- set_title(p_title);
-}
-
-void EditorAssetLibraryItemDescription::add_preview(int p_id, bool p_video,const String& p_url){
-
- Preview preview;
- preview.id=p_id;
- preview.video_link=p_url;
- preview.is_video=p_video;
- preview.button = memnew( Button );
- preview.button->set_flat(true);
- preview.button->set_icon(get_icon("ThumbnailWait","EditorIcons"));
- preview.button->set_toggle_mode(true);
- preview.button->connect("pressed", this, "_preview_click", varray(p_id));
- preview_hb->add_child(preview.button);
- if(!p_video) {
- preview.image=get_icon("ThumbnailWait","EditorIcons");
- }
- if(preview_images.size()==0 && !p_video) {
- _preview_click(p_id);
- }
- preview_images.push_back(preview);
-}
-
-EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
-
- VBoxContainer *vbox = memnew( VBoxContainer );
- add_child(vbox);
-
-
-
- HBoxContainer *hbox = memnew( HBoxContainer);
- vbox->add_child(hbox);
- vbox->add_constant_override("separation",15);
- VBoxContainer *desc_vbox = memnew( VBoxContainer );
- hbox->add_child(desc_vbox);
- hbox->add_constant_override("separation",15);
-
- item = memnew( EditorAssetLibraryItem );
-
- desc_vbox->add_child(item);
- desc_vbox->set_custom_minimum_size(Size2(300,0));
-
-
- PanelContainer * desc_bg = memnew( PanelContainer );
- desc_vbox->add_child(desc_bg);
- desc_bg->set_v_size_flags(SIZE_EXPAND_FILL);
-
- description = memnew( RichTextLabel );
- description->connect("meta_clicked",this,"_link_click");
- //desc_vbox->add_child(description);
- desc_bg->add_child(description);
- desc_bg->add_style_override("panel",get_stylebox("normal","TextEdit"));
-
- preview = memnew( TextureRect );
- preview->set_custom_minimum_size(Size2(640,345));
- hbox->add_child(preview);
-
- PanelContainer * previews_bg = memnew( PanelContainer );
- vbox->add_child(previews_bg);
- previews_bg->set_custom_minimum_size(Size2(0,85));
- previews_bg->add_style_override("panel",get_stylebox("normal","TextEdit"));
-
- previews = memnew( ScrollContainer );
- previews_bg->add_child(previews);
- previews->set_enable_v_scroll(false);
- previews->set_enable_h_scroll(true);
- preview_hb = memnew( HBoxContainer );
- preview_hb->set_v_size_flags(SIZE_EXPAND_FILL);
-
- previews->add_child(preview_hb);
- get_ok()->set_text("Install");
- get_cancel()->set_text("Close");
-
-
-
-}
-///////////////////////////////////////////////////////////////////////////////////
-
-void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int p_code, const PoolStringArray& headers, const PoolByteArray& p_data) {
-
-
- String error_text;
- print_line("COMPLETED: "+itos(p_status)+" code: "+itos(p_code)+" data size: "+itos(p_data.size()));
-
- switch(p_status) {
-
- case HTTPRequest::RESULT_CANT_RESOLVE: {
- error_text=("Can't resolve hostname: "+host);
- status->set_text("Can't resolve.");
- } break;
- case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
- case HTTPRequest::RESULT_CONNECTION_ERROR:
- case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: {
- error_text=("Connection error, please try again.");
- status->set_text("Can't connect.");
- } break;
- case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
- case HTTPRequest::RESULT_CANT_CONNECT: {
- error_text=("Can't connect to host: "+host);
- status->set_text("Can't connect.");
- } break;
- case HTTPRequest::RESULT_NO_RESPONSE: {
- error_text=("No response from host: "+host);
- status->set_text("No response.");
- } break;
- case HTTPRequest::RESULT_REQUEST_FAILED: {
- error_text=("Request failed, return code: "+itos(p_code));
- status->set_text("Req. Failed.");
- } break;
- case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
- error_text=("Request failed, too many redirects");
- status->set_text("Redirect Loop.");
- } break;
- default: {
- if (p_code!=200) {
- error_text=("Request failed, return code: "+itos(p_code));
- status->set_text("Failed: "+itos(p_code));
- } else if(sha256 != "") {
- String download_sha256 = FileAccess::get_sha256(download->get_download_file());
- if(sha256 != download_sha256) {
- error_text="Bad download hash, assuming file has been tampered with.\nExpected: " + sha256 + "\nGot: " + download_sha256;
- status->set_text("Failed sha256 hash check");
- }
- }
- } break;
-
- }
-
- if (error_text!=String()) {
- download_error->set_text("Asset Download Error:\n"+error_text);
- download_error->popup_centered_minsize();
- return;
-
- }
-
- progress->set_max( download->get_body_size() );
- progress->set_value(download->get_downloaded_bytes());
-
- print_line("max: "+itos(download->get_body_size())+" bytes: "+itos(download->get_downloaded_bytes()));
- install->set_disabled(false);
-
- progress->set_value(download->get_downloaded_bytes());
-
- status->set_text("Success! ("+String::humanize_size(download->get_downloaded_bytes())+")");
- set_process(false);
-}
-
-
-void EditorAssetLibraryItemDownload::configure(const String& p_title,int p_asset_id,const Ref<Texture>& p_preview, const String& p_download_url, const String& p_sha256_hash) {
-
- title->set_text(p_title);
- icon->set_texture(p_preview);
- asset_id=p_asset_id;
- if (!p_preview.is_valid())
- icon->set_texture(get_icon("GodotAssetDefault","EditorIcons"));
- host=p_download_url;
- sha256=p_sha256_hash;
- asset_installer->connect("confirmed",this,"_close");
- dismiss->set_normal_texture( get_icon("Close","EditorIcons"));
- _make_request();
-}
-
-
-void EditorAssetLibraryItemDownload::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_PROCESS) {
-
- progress->set_max( download->get_body_size() );
- progress->set_value(download->get_downloaded_bytes());
-
- int cstatus = download->get_http_client_status();
-
- if (cstatus==HTTPClient::STATUS_BODY)
- status->set_text("Fetching: "+String::humanize_size(download->get_downloaded_bytes()));
-
- if (cstatus!=prev_status) {
- switch(cstatus) {
-
- case HTTPClient::STATUS_RESOLVING: {
- status->set_text("Resolving..");
- } break;
- case HTTPClient::STATUS_CONNECTING: {
- status->set_text("Connecting..");
- } break;
- case HTTPClient::STATUS_REQUESTING: {
- status->set_text("Requesting..");
- } break;
- default: {}
- }
- prev_status=cstatus;
- }
-
- }
-}
-void EditorAssetLibraryItemDownload::_close() {
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->remove(download->get_download_file()); //clean up removed file
- memdelete(da);
- queue_delete();
-}
-
-void EditorAssetLibraryItemDownload::_install() {
-
- String file = download->get_download_file();
-
- if (external_install) {
- emit_signal("install_asset",file,title->get_text());
- return;
- }
-
-
- asset_installer->open(file,1);
-}
-
-void EditorAssetLibraryItemDownload::_make_request() {
- download->cancel_request();
- download->set_download_file(EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_asset_"+itos(asset_id))+".zip");
-
- Error err = download->request(host);
- if(err!=OK) {
- status->set_text("Error making request");
- } else {
- set_process(true);
- }
-}
-
-void EditorAssetLibraryItemDownload::_bind_methods() {
-
- ClassDB::bind_method("_http_download_completed",&EditorAssetLibraryItemDownload::_http_download_completed);
- ClassDB::bind_method("_install",&EditorAssetLibraryItemDownload::_install);
- ClassDB::bind_method("_close",&EditorAssetLibraryItemDownload::_close);
- ClassDB::bind_method("_make_request",&EditorAssetLibraryItemDownload::_make_request);
-
- ADD_SIGNAL(MethodInfo("install_asset",PropertyInfo(Variant::STRING,"zip_path"),PropertyInfo(Variant::STRING,"name")));
-
-}
-
-EditorAssetLibraryItemDownload::EditorAssetLibraryItemDownload() {
-
- HBoxContainer *hb = memnew( HBoxContainer);
- add_child(hb);
- icon = memnew( TextureRect );
- hb->add_child(icon);
-
- VBoxContainer *vb = memnew( VBoxContainer );
- hb->add_child(vb);
- vb->set_h_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *title_hb = memnew( HBoxContainer);
- vb->add_child(title_hb);
- title = memnew( Label );
- title_hb->add_child(title);
- title->set_h_size_flags(SIZE_EXPAND_FILL);
-
- dismiss = memnew( TextureButton );
- dismiss->connect("pressed",this,"_close");
- title_hb->add_child(dismiss);
-
- title->set_clip_text(true);
-
- vb->add_spacer();
-
- status = memnew (Label("Idle"));
- vb->add_child(status);
- status->add_color_override("font_color", Color(0.5,0.5,0.5) );
- progress = memnew( ProgressBar );
- vb->add_child(progress);
-
-
-
- HBoxContainer *hb2 = memnew( HBoxContainer );
- vb->add_child(hb2);
- hb2->add_spacer();
-
- install = memnew( Button );
- install->set_text("Install");
- install->set_disabled(true);
- install->connect("pressed",this,"_install");
-
- retry = memnew( Button );
- retry->set_text("Retry");
- retry->connect("pressed",this,"_make_request");
-
- hb2->add_child(retry);
- hb2->add_child(install);
- set_custom_minimum_size(Size2(250,0));
-
- download = memnew( HTTPRequest );
- add_child(download);
- download->connect("request_completed",this,"_http_download_completed");
-
- download_error = memnew( AcceptDialog );
- add_child(download_error);
- download_error->set_title("Download Error");
-
- asset_installer = memnew( EditorAssetInstaller );
- add_child(asset_installer);
-
- prev_status=-1;
-
- external_install=false;
-
-
-}
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-void EditorAssetLibrary::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_READY) {
- TextureRect *tf = memnew(TextureRect);
- tf->set_texture(get_icon("Error","EditorIcons"));
- reverse->set_icon(get_icon("Updown","EditorIcons"));
-
- error_hb->add_child(tf);
- error_label->raise();
- }
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
- if(is_visible()) {
- _repository_changed(0); // Update when shown for the first time
- }
- }
-
- if (p_what==NOTIFICATION_PROCESS) {
-
- HTTPClient::Status s = request->get_http_client_status();
- bool visible = s!=HTTPClient::STATUS_DISCONNECTED;
-
- if (visible != load_status->is_visible()) {
- load_status->set_visible(visible);
- }
-
- if (visible) {
- switch(s) {
-
- case HTTPClient::STATUS_RESOLVING: {
- load_status->set_value(0.1);
- } break;
- case HTTPClient::STATUS_CONNECTING: {
- load_status->set_value(0.2);
- } break;
- case HTTPClient::STATUS_REQUESTING: {
- load_status->set_value(0.3);
- } break;
- case HTTPClient::STATUS_BODY: {
- load_status->set_value(0.4);
- } break;
- default: {}
-
- }
- }
-
- bool no_downloads = downloads_hb->get_child_count()==0;
- if (no_downloads == downloads_scroll->is_visible()) {
- downloads_scroll->set_visible(!no_downloads);
- }
- }
-
-}
-
-
-void EditorAssetLibrary::_install_asset() {
-
- ERR_FAIL_COND(!description);
-
- for(int i=0;i<downloads_hb->get_child_count();i++) {
-
- EditorAssetLibraryItemDownload *d = downloads_hb->get_child(i)->cast_to<EditorAssetLibraryItemDownload>();
- if (d && d->get_asset_id() == description->get_asset_id()) {
-
- if (EditorNode::get_singleton() != NULL)
- EditorNode::get_singleton()->show_warning("Download for this asset is already in progress!");
- return;
- }
- }
-
-
- EditorAssetLibraryItemDownload * download = memnew( EditorAssetLibraryItemDownload );
- downloads_hb->add_child(download);
- download->configure(description->get_title(),description->get_asset_id(),description->get_preview_icon(),description->get_download_url(),description->get_sha256());
-
- if (templates_only) {
- download->set_external_install(true);
- download->connect("install_asset",this,"_install_external_asset");
- }
-
-}
-
-const char* EditorAssetLibrary::sort_key[SORT_MAX]={
- "rating",
- "downloads",
- "name",
- "cost",
- "updated"
-};
-
-const char* EditorAssetLibrary::sort_text[SORT_MAX]={
- "Rating",
- "Downloads",
- "Name",
- "Cost",
- "Updated"
-};
-
-const char* EditorAssetLibrary::support_key[SUPPORT_MAX]={
- "official",
- "community",
- "testing"
-};
-
-
-void EditorAssetLibrary::_select_author(int p_id) {
-
- //opemn author window
-}
-
-void EditorAssetLibrary::_select_category(int p_id){
-
- for(int i=0;i<categories->get_item_count();i++) {
-
- if (i==0)
- continue;
- int id = categories->get_item_metadata(i);
- if (id==p_id) {
- categories->select(i);
- _search();
- break;
- }
- }
-}
-void EditorAssetLibrary::_select_asset(int p_id){
-
- _api_request("asset/"+itos(p_id), REQUESTING_ASSET);
-
- /*
- if (description) {
- memdelete(description);
- }
-
-
- description = memnew( EditorAssetLibraryItemDescription );
- add_child(description);
- description->popup_centered_minsize();*/
-}
-
-void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByteArray& p_data, int p_queue_id) {
- Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
-
- if (obj) {
- bool image_set = false;
- PoolByteArray image_data = p_data;
-
- if(use_cache) {
- String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+image_queue[p_queue_id].image_url.md5_text());
-
- FileAccess* file = FileAccess::open(cache_filename_base+".data", FileAccess::READ);
-
- if(file) {
- PoolByteArray cached_data;
- int len=file->get_32();
- cached_data.resize(len);
-
- PoolByteArray::Write w=cached_data.write();
- file->get_buffer(w.ptr(), len);
-
- image_data = cached_data;
- file->close();
- }
- }
-
- int len=image_data.size();
- PoolByteArray::Read r=image_data.read();
- Image image(r.ptr(),len);
- if (!image.empty()) {
- float max_height = 10000;
- switch(image_queue[p_queue_id].image_type) {
- case IMAGE_QUEUE_ICON: max_height=80; break;
- case IMAGE_QUEUE_THUMBNAIL: max_height=80; break;
- case IMAGE_QUEUE_SCREENSHOT: max_height=345; break;
- }
- float scale_ratio = max_height / image.get_height();
- if(scale_ratio < 1) {
- image.resize(image.get_width() * scale_ratio, image.get_height() * scale_ratio, Image::INTERPOLATE_CUBIC);
- }
-
- Ref<ImageTexture> tex;
- tex.instance();
- tex->create_from_image(image);
-
- obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,tex);
- image_set = true;
- }
-
- if(!image_set && final) {
- obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,get_icon("ErrorSign","EditorIcons"));
- }
- }
-}
-
-void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, const PoolStringArray& headers, const PoolByteArray& p_data,int p_queue_id) {
-
- ERR_FAIL_COND( !image_queue.has(p_queue_id) );
-
- if (p_status==HTTPRequest::RESULT_SUCCESS) {
-
- print_line("GOT IMAGE YAY!");
-
- if(p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
- for(int i=0;i<headers.size();i++) {
- if (headers[i].findn("ETag:")==0) { // Save etag
- String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+image_queue[p_queue_id].image_url.md5_text());
- String new_etag = headers[i].substr(headers[i].find(":")+1,headers[i].length()).strip_edges();
- FileAccess* file;
-
- file = FileAccess::open(cache_filename_base+".etag", FileAccess::WRITE);
- if(file) {
- file->store_line(new_etag);
- file->close();
- }
-
- int len=p_data.size();
- PoolByteArray::Read r=p_data.read();
- file = FileAccess::open(cache_filename_base+".data", FileAccess::WRITE);
- if(file) {
- file->store_32(len);
- file->store_buffer(r.ptr(),len);
- file->close();
- }
-
- break;
- }
- }
- }
- _image_update(p_code == HTTPClient::RESPONSE_NOT_MODIFIED, true, p_data, p_queue_id);
-
- } else {
- WARN_PRINTS("Error getting PNG file for asset id "+itos(image_queue[p_queue_id].asset_id));
- Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
- if (obj) {
- obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,get_icon("ErrorSign","EditorIcons"));
- }
- }
-
- image_queue[p_queue_id].request->queue_delete();
- image_queue.erase(p_queue_id);
-
- _update_image_queue();
-
-}
-
-void EditorAssetLibrary::_update_image_queue() {
-
- int max_images=2;
- int current_images=0;
-
- List<int> to_delete;
- for (Map<int,ImageQueue>::Element *E=image_queue.front();E;E=E->next()) {
- if (!E->get().active && current_images<max_images) {
-
- String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+E->get().image_url.md5_text());
- Vector<String> headers;
-
- if(FileAccess::exists(cache_filename_base+".etag") && FileAccess::exists(cache_filename_base+".data")) {
- FileAccess* file = FileAccess::open(cache_filename_base+".etag", FileAccess::READ);
- if (file) {
- headers.push_back("If-None-Match: " + file->get_line());
- file->close();
- }
- }
-
- print_line("REQUEST ICON FOR: "+itos(E->get().asset_id));
- Error err = E->get().request->request(E->get().image_url, headers);
- if (err!=OK) {
- to_delete.push_back(E->key());
- } else {
- E->get().active=true;
- }
- current_images++;
- } else if (E->get().active) {
- current_images++;
- }
- }
-
- while(to_delete.size()) {
- image_queue[to_delete.front()->get()].request->queue_delete();
- image_queue.erase(to_delete.front()->get());
- to_delete.pop_front();
- }
-}
-
-void EditorAssetLibrary::_request_image(ObjectID p_for,String p_image_url,ImageType p_type,int p_image_index) {
-
-
- ImageQueue iq;
- iq.image_url=p_image_url;
- iq.image_index=p_image_index;
- iq.image_type=p_type;
- iq.request = memnew( HTTPRequest );
-
- iq.target=p_for;
- iq.queue_id=++last_queue_id;
- iq.active=false;
-
- iq.request->connect("request_completed",this,"_image_request_completed",varray(iq.queue_id));
-
- image_queue[iq.queue_id]=iq;
-
- add_child(iq.request);
-
- _image_update(true, false, PoolByteArray(), iq.queue_id);
- _update_image_queue();
-
-
-}
-
-void EditorAssetLibrary::_repository_changed(int p_repository_id) {
- host=repository->get_item_metadata(p_repository_id);
- print_line(".." + host);
- if(templates_only) {
- _api_request("configure", REQUESTING_CONFIG, "?type=project");
- } else {
- _api_request("configure", REQUESTING_CONFIG);
- }
-}
-
-void EditorAssetLibrary::_support_toggled(int p_support) {
- support->get_popup()->set_item_checked(p_support, !support->get_popup()->is_item_checked(p_support));
- _search();
-}
-
-void EditorAssetLibrary::_rerun_search(int p_ignore) {
- _search();
-}
-
-void EditorAssetLibrary::_search(int p_page) {
-
- String args;
-
- if(templates_only) {
- args += "?type=project&";
- } else {
- args += "?";
- }
- args+=String()+"sort="+sort_key[sort->get_selected()];
-
-
- String support_list;
- for(int i = 0; i < SUPPORT_MAX; i++) {
- if(support->get_popup()->is_item_checked(i)) {
- support_list += String(support_key[i]) + "+";
- }
- }
- if(support_list != String()) {
- args += "&support=" + support_list.substr(0, support_list.length() - 1);
- }
-
- if (categories->get_selected()>0) {
-
- args+="&category="+itos(categories->get_item_metadata(categories->get_selected()));
- }
-
- if (reverse->is_pressed()) {
-
- args+="&reverse=true";
- }
-
- if (filter->get_text()!=String()) {
- args+="&filter="+filter->get_text().http_escape();
- }
-
- if (p_page>0) {
- args+="&page="+itos(p_page);
- }
-
- _api_request("asset",REQUESTING_SEARCH,args);
-}
-
-HBoxContainer* EditorAssetLibrary::_make_pages(int p_page,int p_page_count,int p_page_len,int p_total_items,int p_current_items) {
-
- HBoxContainer * hbc = memnew( HBoxContainer );
-
- //do the mario
- int from = p_page-5;
- if (from<0)
- from=0;
- int to = from+10;
- if (to>p_page_count)
- to=p_page_count;
-
- Color gray = Color(0.65,0.65,0.65);
-
- hbc->add_spacer();
- hbc->add_constant_override("separation",10);
-
- if(p_page != 0) {
- LinkButton *first = memnew( LinkButton );
- first->set_text("first");
- first->add_color_override("font_color", gray );
- first->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- first->connect("pressed",this,"_search",varray(0));
- hbc->add_child(first);
- }
-
- if (p_page>0) {
- LinkButton *prev = memnew( LinkButton );
- prev->set_text("prev");
- prev->add_color_override("font_color", gray );
- prev->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- prev->connect("pressed",this,"_search",varray(p_page-1));
- hbc->add_child(prev);
- }
-
- for(int i=from;i<to;i++) {
-
- if (i==p_page) {
-
- Label *current = memnew(Label);
- current->set_text(itos(i+1));
- hbc->add_child(current);
- } else {
-
- LinkButton *current = memnew( LinkButton );
- current->add_color_override("font_color", gray );
- current->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- current->set_text(itos(i+1));
- current->connect("pressed",this,"_search",varray(i));
-
- hbc->add_child(current);
-
- }
- }
-
- if (p_page<p_page_count-1) {
- LinkButton *next = memnew( LinkButton );
- next->set_text("next");
- next->add_color_override("font_color", gray );
- next->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- next->connect("pressed",this,"_search",varray(p_page+1));
-
- hbc->add_child(next);
- }
-
- if(p_page != p_page_count-1) {
- LinkButton *last = memnew( LinkButton );
- last->set_text("last");
- last->add_color_override("font_color", gray );
- last->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- hbc->add_child(last);
- last->connect("pressed",this,"_search",varray(p_page_count-1));
- }
-
- Label *totals = memnew( Label );
- totals->set_text("( "+itos(from*p_page_len)+" - "+itos(from*p_page_len+p_current_items-1)+" / "+itos(p_total_items)+" )");
- hbc->add_child(totals);
-
- hbc->add_spacer();
-
- return hbc;
-}
-
-
-void EditorAssetLibrary::_api_request(const String& p_request, RequestType p_request_type, const String& p_arguments) {
-
- if (requesting!=REQUESTING_NONE) {
- request->cancel_request();
- }
-
- requesting=p_request_type;
-
- error_hb->hide();
- request->request(host+"/"+p_request+p_arguments);
-}
-
-
-
-void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const PoolStringArray& headers, const PoolByteArray& p_data) {
-
-
- String str;
-
- {
- int datalen=p_data.size();
- PoolByteArray::Read r = p_data.read();
- str.parse_utf8((const char*)r.ptr(),datalen);
- }
-
- bool error_abort=true;
-
- switch(p_status) {
-
- case HTTPRequest::RESULT_CANT_RESOLVE: {
- error_label->set_text("Can't resolve hostname: "+host);
- } break;
- case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
- case HTTPRequest::RESULT_CONNECTION_ERROR:
- case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: {
- error_label->set_text("Connection error, please try again.");
- } break;
- case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
- case HTTPRequest::RESULT_CANT_CONNECT: {
- error_label->set_text("Can't connect to host: "+host);
- } break;
- case HTTPRequest::RESULT_NO_RESPONSE: {
- error_label->set_text("No response from host: "+host);
- } break;
- case HTTPRequest::RESULT_REQUEST_FAILED: {
- error_label->set_text("Request failed, return code: "+itos(p_code));
- } break;
- case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
- error_label->set_text("Request failed, too many redirects");
-
- } break;
- default: {
- if (p_code!=200) {
- error_label->set_text("Request failed, return code: "+itos(p_code));
- } else {
-
- error_abort=false;
- }
- } break;
-
- }
-
-
- if (error_abort) {
- error_hb->show();
- return;
- }
-
- print_line("response: "+itos(p_status)+" code: "+itos(p_code));
-
- Dictionary d;
- {
- Variant js;
- String errs;
- int errl;
- JSON::parse(str,js,errs,errl);
- d=js;
- }
-
-
- print_line(Variant(d).get_construct_string());
-
- RequestType requested = requesting;
- requesting=REQUESTING_NONE;
-
- switch(requested) {
- case REQUESTING_CONFIG: {
-
- categories->clear();
- categories->add_item("All");
- categories->set_item_metadata(0,0);
- if (d.has("categories")) {
- Array clist = d["categories"];
- for(int i=0;i<clist.size();i++) {
- Dictionary cat = clist[i];
- if (!cat.has("name") || !cat.has("id"))
- continue;
- String name=cat["name"];
- int id=cat["id"];
- categories->add_item(name);
- categories->set_item_metadata( categories->get_item_count() -1, id);
- category_map[cat["id"]] = name;
- }
- }
-
- _search();
- } break;
- case REQUESTING_SEARCH: {
- if (asset_items) {
- memdelete(asset_items);
- }
-
- if (asset_top_page) {
- memdelete(asset_top_page);
- }
-
- if (asset_bottom_page) {
- memdelete(asset_bottom_page);
- }
-
- int page=0;
- int pages=1;
- int page_len=10;
- int total_items=1;
- Array result;
-
-
- if (d.has("page")) {
- page=d["page"];
- }
- if (d.has("pages")) {
- pages=d["pages"];
- }
- if (d.has("page_length")) {
- page_len=d["page_length"];
- }
- if (d.has("total")) {
- total_items=d["total"];
- }
- if (d.has("result")) {
- result=d["result"];
- }
-
- asset_top_page = _make_pages(page,pages,page_len,total_items,result.size());
- library_vb->add_child(asset_top_page);
-
- asset_items = memnew( GridContainer );
- asset_items->set_columns(2);
- asset_items->add_constant_override("hseparation",10);
- asset_items->add_constant_override("vseparation",10);
-
- library_vb->add_child(asset_items);
-
- asset_bottom_page = _make_pages(page,pages,page_len,total_items,result.size());
- library_vb->add_child(asset_bottom_page);
-
- for(int i=0;i<result.size();i++) {
-
- Dictionary r = result[i];
-
- ERR_CONTINUE(!r.has("title"));
- ERR_CONTINUE(!r.has("asset_id"));
- ERR_CONTINUE(!r.has("author"));
- ERR_CONTINUE(!r.has("author_id"));
- ERR_CONTINUE(!r.has("category_id"));
- ERR_FAIL_COND(!category_map.has(r["category_id"]));
- ERR_CONTINUE(!r.has("rating"));
- ERR_CONTINUE(!r.has("cost"));
-
-
- EditorAssetLibraryItem *item = memnew( EditorAssetLibraryItem );
- asset_items->add_child(item);
- item->configure(r["title"],r["asset_id"],category_map[r["category_id"]],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"]);
- item->connect("asset_selected",this,"_select_asset");
- item->connect("author_selected",this,"_select_author");
- item->connect("category_selected",this,"_select_category");
-
- if(r.has("icon_url") && r["icon_url"] != "") {
- _request_image(item->get_instance_ID(),r["icon_url"],IMAGE_QUEUE_ICON,0);
- }
- }
- } break;
- case REQUESTING_ASSET: {
- Dictionary r = d;
-
- ERR_FAIL_COND(!r.has("title"));
- ERR_FAIL_COND(!r.has("asset_id"));
- ERR_FAIL_COND(!r.has("author"));
- ERR_FAIL_COND(!r.has("author_id"));
- ERR_FAIL_COND(!r.has("version"));
- ERR_FAIL_COND(!r.has("version_string"));
- ERR_FAIL_COND(!r.has("category_id"));
- ERR_FAIL_COND(!category_map.has(r["category_id"]));
- ERR_FAIL_COND(!r.has("rating"));
- ERR_FAIL_COND(!r.has("cost"));
- ERR_FAIL_COND(!r.has("description"));
- ERR_FAIL_COND(!r.has("download_url"));
- ERR_FAIL_COND(!r.has("download_hash"));
- ERR_FAIL_COND(!r.has("browse_url"));
-
- if (description) {
- memdelete(description);
- }
-
- description = memnew( EditorAssetLibraryItemDescription );
- add_child(description);
- description->popup_centered_minsize();
- description->connect("confirmed",this,"_install_asset");
-
- description->configure(r["title"],r["asset_id"],category_map[r["category_id"]],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"],r["version"],r["version_string"],r["description"],r["download_url"],r["browse_url"], r["download_hash"]);
- /*item->connect("asset_selected",this,"_select_asset");
- item->connect("author_selected",this,"_select_author");
- item->connect("category_selected",this,"_category_selected");*/
-
- if(r.has("icon_url") && r["icon_url"] != "") {
- _request_image(description->get_instance_ID(),r["icon_url"],IMAGE_QUEUE_ICON,0);
- }
-
- if (d.has("previews")) {
- Array previews = d["previews"];
-
- for(int i=0;i<previews.size();i++) {
-
-
- Dictionary p=previews[i];
-
- ERR_CONTINUE(!p.has("type"));
- ERR_CONTINUE(!p.has("link"));
-
- bool is_video=p.has("type") && String(p["type"])=="video";
- String video_url;
- if (is_video && p.has("link")) {
- video_url=p["link"];
- }
-
- description->add_preview(i,is_video,video_url);
-
- if(p.has("thumbnail")) {
- _request_image(description->get_instance_ID(),p["thumbnail"],IMAGE_QUEUE_THUMBNAIL,i);
- }
- if(is_video) {
- //_request_image(description->get_instance_ID(),p["link"],IMAGE_QUEUE_SCREENSHOT,i);
- } else {
- _request_image(description->get_instance_ID(),p["link"],IMAGE_QUEUE_SCREENSHOT,i);
- }
-
- }
- }
- } break;
- default: break;
- }
-
-}
-
-
-void EditorAssetLibrary::_asset_file_selected(const String& p_file) {
-
- if (asset_installer) {
- memdelete( asset_installer );
- asset_installer=NULL;
- }
-
- asset_installer = memnew( EditorAssetInstaller );
- add_child(asset_installer);
- asset_installer->open(p_file);
-
-
-}
-
-void EditorAssetLibrary::_asset_open() {
-
- asset_open->popup_centered_ratio();
-}
-
-void EditorAssetLibrary::_manage_plugins() {
-
- ProjectSettings::get_singleton()->popup_project_settings();
- ProjectSettings::get_singleton()->set_plugins_page();
-}
-
-
-
-void EditorAssetLibrary::_install_external_asset(String p_zip_path,String p_title) {
-
- emit_signal("install_asset",p_zip_path,p_title);
-}
-
-void EditorAssetLibrary::_bind_methods() {
-
- ClassDB::bind_method("_http_request_completed",&EditorAssetLibrary::_http_request_completed);
- ClassDB::bind_method("_select_asset",&EditorAssetLibrary::_select_asset);
- ClassDB::bind_method("_select_author",&EditorAssetLibrary::_select_author);
- ClassDB::bind_method("_select_category",&EditorAssetLibrary::_select_category);
- ClassDB::bind_method("_image_request_completed",&EditorAssetLibrary::_image_request_completed);
- ClassDB::bind_method("_search",&EditorAssetLibrary::_search,DEFVAL(0));
- ClassDB::bind_method("_install_asset",&EditorAssetLibrary::_install_asset);
- ClassDB::bind_method("_manage_plugins",&EditorAssetLibrary::_manage_plugins);
- ClassDB::bind_method("_asset_open",&EditorAssetLibrary::_asset_open);
- ClassDB::bind_method("_asset_file_selected",&EditorAssetLibrary::_asset_file_selected);
- ClassDB::bind_method("_repository_changed",&EditorAssetLibrary::_repository_changed);
- ClassDB::bind_method("_support_toggled",&EditorAssetLibrary::_support_toggled);
- ClassDB::bind_method("_rerun_search",&EditorAssetLibrary::_rerun_search);
- ClassDB::bind_method("_install_external_asset",&EditorAssetLibrary::_install_external_asset);
-
-
-
- ADD_SIGNAL(MethodInfo("install_asset",PropertyInfo(Variant::STRING,"zip_path"),PropertyInfo(Variant::STRING,"name")));
-
-}
-
-EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
-
- templates_only=p_templates_only;
-
- Ref<StyleBoxEmpty> border;
- border.instance();
- border->set_default_margin(MARGIN_LEFT,15);
- border->set_default_margin(MARGIN_RIGHT,15);
- border->set_default_margin(MARGIN_BOTTOM,5);
- border->set_default_margin(MARGIN_TOP,5);
-
- add_style_override("panel",border);
-
- VBoxContainer *library_main = memnew( VBoxContainer );
-
- add_child(library_main);
-
- HBoxContainer *search_hb = memnew( HBoxContainer );
-
- library_main->add_child(search_hb);
- library_main->add_constant_override("separation",10);
-
-
-
- search_hb->add_child( memnew( Label(TTR("Search:")+" ")));
- filter =memnew( LineEdit );
- search_hb->add_child(filter);
- filter->set_h_size_flags(SIZE_EXPAND_FILL);
- filter->connect("text_entered",this,"_search");
- search = memnew( Button("Search"));
- search->connect("pressed",this,"_search");
- search_hb->add_child(search);
-
- if (!p_templates_only)
- search_hb->add_child(memnew( VSeparator ));
-
- Button * open_asset = memnew( Button );
- open_asset->set_text("Import");
- search_hb->add_child(open_asset);
- open_asset->connect("pressed",this,"_asset_open");
-
- Button * plugins = memnew( Button );
- plugins->set_text("Plugins");
- search_hb->add_child(plugins);
- plugins->connect("pressed",this,"_manage_plugins");
-
- if (p_templates_only) {
- open_asset->hide();
- plugins->hide();
- }
-
-
- HBoxContainer *search_hb2 = memnew( HBoxContainer );
- library_main->add_child(search_hb2);
-
- search_hb2->add_child( memnew( Label(TTR("Sort:")+" ")));
- sort = memnew( OptionButton );
- for(int i=0;i<SORT_MAX;i++) {
- sort->add_item(sort_text[i]);
- }
-
- search_hb2->add_child(sort);
-
- sort->set_h_size_flags(SIZE_EXPAND_FILL);
- sort->connect("item_selected", this, "_rerun_search");
-
- reverse = memnew( ToolButton );
- reverse->set_toggle_mode(true);
- reverse->connect("toggled", this, "_rerun_search");
- //reverse->set_text(TTR("Reverse"));
- search_hb2->add_child(reverse);
-
- search_hb2->add_child(memnew(VSeparator));
-
- //search_hb2->add_spacer();
-
- search_hb2->add_child( memnew( Label(TTR("Category:")+" ")));
- categories = memnew( OptionButton );
- categories->add_item(TTR("All"));
- search_hb2->add_child(categories);
- categories->set_h_size_flags(SIZE_EXPAND_FILL);
- //search_hb2->add_spacer();
- categories->connect("item_selected", this, "_rerun_search");
-
- search_hb2->add_child(memnew(VSeparator));
-
- search_hb2->add_child( memnew( Label(TTR("Site:")+" ")));
- repository = memnew( OptionButton );
-
- repository->add_item("Godot");
- repository->set_item_metadata(0, "https://godotengine.org/asset-library/api");
- repository->add_item("Localhost"); // TODO: Maybe remove?
- repository->set_item_metadata(1, "http://127.0.0.1/asset-library/api");
- repository->connect("item_selected",this,"_repository_changed");
-
- search_hb2->add_child(repository);
- repository->set_h_size_flags(SIZE_EXPAND_FILL);
-
-
- search_hb2->add_child(memnew(VSeparator));
-
- support = memnew( MenuButton );
- search_hb2->add_child(support);
- support->set_text(TTR("Support.."));
- support->get_popup()->add_check_item(TTR("Official"),SUPPORT_OFFICIAL);
- support->get_popup()->add_check_item(TTR("Community"),SUPPORT_COMMUNITY);
- support->get_popup()->add_check_item(TTR("Testing"),SUPPORT_TESTING);
- support->get_popup()->set_item_checked(SUPPORT_OFFICIAL,true);
- support->get_popup()->set_item_checked(SUPPORT_COMMUNITY,true);
- support->get_popup()->connect("id_pressed",this,"_support_toggled");
-
- /////////
-
- PanelContainer * library_scroll_bg = memnew( PanelContainer );
- library_main->add_child(library_scroll_bg);
- library_scroll_bg->add_style_override("panel",get_stylebox("normal","TextEdit"));
- library_scroll_bg->set_v_size_flags(SIZE_EXPAND_FILL);
-
- library_scroll = memnew( ScrollContainer );
- library_scroll->set_enable_v_scroll(true);
- library_scroll->set_enable_h_scroll(false);
-
- library_scroll_bg->add_child(library_scroll);
-
-
- Ref<StyleBoxEmpty> border2;
- border2.instance();
- border2->set_default_margin(MARGIN_LEFT,15);
- border2->set_default_margin(MARGIN_RIGHT,35);
- border2->set_default_margin(MARGIN_BOTTOM,15);
- border2->set_default_margin(MARGIN_TOP,15);
-
-
- PanelContainer * library_vb_border = memnew( PanelContainer );
- library_scroll->add_child(library_vb_border);
- library_vb_border->add_style_override("panel",border2);
- library_vb_border->set_h_size_flags(SIZE_EXPAND_FILL);
- library_vb_border->set_mouse_filter(MOUSE_FILTER_PASS);
-
-
-
- library_vb = memnew( VBoxContainer );
- library_vb->set_h_size_flags(SIZE_EXPAND_FILL);
-
- library_vb_border->add_child(library_vb);
- //margin_panel->set_stop_mouse(false);
-
- asset_top_page = memnew( HBoxContainer );
- library_vb->add_child(asset_top_page);
-
- asset_items = memnew( GridContainer );
- asset_items->set_columns(2);
- asset_items->add_constant_override("hseparation",10);
- asset_items->add_constant_override("vseparation",10);
-
- library_vb->add_child(asset_items);
-
- asset_bottom_page = memnew( HBoxContainer );
- library_vb->add_child(asset_bottom_page);
-
- request = memnew( HTTPRequest );
- add_child(request);
- request->set_use_threads(EDITOR_DEF("asset_library/use_threads",true));
- request->connect("request_completed",this,"_http_request_completed");
-
- last_queue_id=0;
-
- library_vb->add_constant_override("separation",20);
-
- load_status = memnew( ProgressBar );
- load_status->set_min(0);
- load_status->set_max(1);
- load_status->set_step(0.001);
- library_main->add_child(load_status);
-
- error_hb = memnew( HBoxContainer );
- library_main->add_child(error_hb);
- error_label = memnew( Label );
- error_label->add_color_override("color",Color(1,0.4,0.3));
- error_hb->add_child(error_label);
-
- description = NULL;
-
- set_process(true);
-
- downloads_scroll = memnew( ScrollContainer );
- downloads_scroll->set_enable_h_scroll(true);
- downloads_scroll->set_enable_v_scroll(false);
- library_main->add_child(downloads_scroll);
- downloads_hb = memnew( HBoxContainer );
- downloads_scroll->add_child(downloads_hb);
-
- asset_open = memnew( EditorFileDialog );
-
- asset_open->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- asset_open->add_filter("*.zip ; "+TTR("Assets ZIP File"));
- asset_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- add_child(asset_open);
- asset_open->connect("file_selected",this,"_asset_file_selected");
-
- asset_installer=NULL;
-
-}
-
-
-///////
-
-
-void AssetLibraryEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- addon_library->show();
- } else {
-
- addon_library->hide();
- }
-
-}
-
-AssetLibraryEditorPlugin::AssetLibraryEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- addon_library = memnew( EditorAssetLibrary );
- addon_library->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- editor->get_viewport()->add_child(addon_library);
- addon_library->set_area_as_parent_rect();
- addon_library->hide();
-
-}
-
-AssetLibraryEditorPlugin::~AssetLibraryEditorPlugin() {
-
-}
diff --git a/tools/editor/call_dialog.h b/tools/editor/call_dialog.h
deleted file mode 100644
index b0ebe68d86..0000000000
--- a/tools/editor/call_dialog.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*************************************************************************/
-/* call_dialog.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 CALL_DIALOG_H
-#define CALL_DIALOG_H
-
-#include "scene/gui/popup.h"
-#include "scene/gui/button.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/label.h"
-#include "scene/gui/line_edit.h"
-#include "tools/editor/property_editor.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-#if 0
-
-class CallDialogParams;
-
-class CallDialog : public Popup {
-
- GDCLASS( CallDialog, Popup );
-
-
- Label* method_label;
- Tree *tree;
- Button *call;
- Button *cancel;
-
- CallDialogParams *call_params;
- PropertyEditor *property_editor;
-
- Label *return_label;
- LineEdit *return_value;
- Object *object;
- StringName selected;
-
- Vector<MethodInfo> methods;
-
-
- void _item_selected();
- void _update_method_list();
- void _call();
- void _cancel();
-
-protected:
- static void _bind_methods();
- void _notification(int p_what);
-public:
-
- void set_object(Object *p_object,StringName p_selected="");
-
- CallDialog();
- ~CallDialog();
-
-};
-
-#endif
-#endif
diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp
deleted file mode 100644
index 0a25b43716..0000000000
--- a/tools/editor/code_editor.cpp
+++ /dev/null
@@ -1,1323 +0,0 @@
-/*************************************************************************/
-/* code_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "code_editor.h"
-
-#include "editor_settings.h"
-#include "scene/gui/margin_container.h"
-#include "scene/gui/separator.h"
-#include "scene/resources/dynamic_font.h"
-#include "os/keyboard.h"
-#include "tools/editor/editor_scale.h"
-
-void GotoLineDialog::popup_find_line(TextEdit *p_edit) {
-
- text_editor=p_edit;
-
- line->set_text(itos(text_editor->cursor_get_line()));
- line->select_all();
- popup_centered(Size2(180,80));
- line->grab_focus();
-}
-
-
-int GotoLineDialog::get_line() const {
-
- return line->get_text().to_int();
-}
-
-
-void GotoLineDialog::ok_pressed() {
-
- if (get_line()<1 || get_line()>text_editor->get_line_count())
- return;
- text_editor->cursor_set_line(get_line()-1);
- hide();
-}
-
-GotoLineDialog::GotoLineDialog() {
-
- set_title(TTR("Go to Line"));
- Label *l = memnew(Label);
- l->set_text(TTR("Line Number:"));
- l->set_pos(Point2(5,5));
- add_child(l);
-
- line = memnew( LineEdit );
- line->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- line->set_begin( Point2(15,22) );
- line->set_end( Point2(15,35) );
- add_child(line);
- register_text_enter(line);
- text_editor=NULL;
-
- set_hide_on_ok(false);
-}
-
-
-void FindReplaceBar::_notification(int p_what) {
-
- if (p_what == NOTIFICATION_READY) {
-
- find_prev->set_icon(get_icon("MoveUp", "EditorIcons"));
- find_next->set_icon(get_icon("MoveDown", "EditorIcons"));
- hide_button->set_normal_texture(get_icon("Close","EditorIcons"));
- hide_button->set_hover_texture(get_icon("CloseHover","EditorIcons"));
- hide_button->set_pressed_texture(get_icon("Close","EditorIcons"));
-
- } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
-
- set_process_unhandled_input(is_visible_in_tree());
- }
-}
-
-void FindReplaceBar::_unhandled_input(const InputEvent &p_event) {
-
- if (p_event.type == InputEvent::KEY) {
-
- const InputEventKey& k = p_event.key;
-
- if (k.pressed && (text_edit->has_focus() || text_vbc->is_a_parent_of(get_focus_owner()))) {
-
- bool accepted = true;
-
- switch (k.scancode) {
-
- case KEY_ESCAPE: {
-
- _hide_bar();
- } break;
- default: {
-
- accepted = false;
- } break;
- }
-
- if (accepted) {
- accept_event();
- }
- }
- }
-}
-
-bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) {
-
- int line, col;
- String text=get_search_text();
-
- bool found=text_edit->search(text,p_flags,p_from_line,p_from_col,line,col);
-
- if (found) {
- if (!preserve_cursor) {
- text_edit->cursor_set_line(line, false);
- text_edit->cursor_set_column(col+text.length(), false);
- text_edit->center_viewport_to_cursor();
- }
-
- text_edit->set_search_text(text);
- text_edit->set_search_flags(p_flags);
- text_edit->set_current_search_result(line,col);
-
- result_line=line;
- result_col=col;
-
- set_error("");
- } else {
- result_line=-1;
- result_col=-1;
- text_edit->set_search_text("");
- set_error(text.empty()?"":TTR("No Matches"));
- }
-
- return found;
-}
-
-void FindReplaceBar::_replace() {
-
- if (result_line!=-1 && result_col!=-1) {
- text_edit->begin_complex_operation();
-
- text_edit->select(result_line,result_col,result_line,result_col+get_search_text().length());
- text_edit->insert_text_at_cursor(get_replace_text());
-
- text_edit->end_complex_operation();
- }
-
- search_current();
-}
-
-void FindReplaceBar::_replace_all() {
-
- // line as x so it gets priority in comparison, column as y
- Point2i orig_cursor(text_edit->cursor_get_line(),text_edit->cursor_get_column());
- Point2i prev_match=Point2(-1,-1);
-
- bool selection_enabled = text_edit->is_selection_active();
- Point2i selection_begin,selection_end;
- if (selection_enabled) {
- selection_begin=Point2i(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
- selection_end=Point2i(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
- }
-
- int vsval = text_edit->get_v_scroll();
-
- text_edit->cursor_set_line(0);
- text_edit->cursor_set_column(0);
-
- String replace_text=get_replace_text();
- int search_text_len=get_search_text().length();
-
- int rc=0;
-
- replace_all_mode = true;
-
- text_edit->begin_complex_operation();
-
- while (search_next()) {
-
- // replace area
- Point2i match_from(result_line,result_col);
- Point2i match_to(result_line,result_col+search_text_len);
-
- if (match_from < prev_match)
- break; // done
-
- prev_match=Point2i(result_line,result_col+replace_text.length());
-
- text_edit->select(result_line,result_col,result_line,match_to.y);
-
- if (selection_enabled && is_selection_only()) {
-
- if (match_from<selection_begin || match_to>selection_end)
- continue;
-
- // replace but adjust selection bounds
- text_edit->insert_text_at_cursor(replace_text);
- if (match_to.x==selection_end.x)
- selection_end.y+=replace_text.length()-search_text_len;
- } else {
- // just replace
- text_edit->insert_text_at_cursor(replace_text);
- }
-
- rc++;
- }
-
- text_edit->end_complex_operation();
-
- replace_all_mode = false;
-
- // restore editor state (selection, cursor, scroll)
- text_edit->cursor_set_line(orig_cursor.x);
- text_edit->cursor_set_column(orig_cursor.y);
-
- if (selection_enabled && is_selection_only()) {
- // reselect
- text_edit->select(selection_begin.x,selection_begin.y,selection_end.x,selection_end.y);
- } else {
- text_edit->deselect();
- }
-
- text_edit->set_v_scroll(vsval);
- set_error(vformat(TTR("Replaced %d Ocurrence(s)."), rc));
-}
-
-void FindReplaceBar::_get_search_from(int& r_line, int& r_col) {
-
- r_line=text_edit->cursor_get_line();
- r_col=text_edit->cursor_get_column();
-
- if (text_edit->is_selection_active() && !replace_all_mode) {
-
- int selection_line=text_edit->get_selection_from_line();
-
- if (text_edit->get_selection_text()==get_search_text() && r_line==selection_line) {
-
- int selection_from_col=text_edit->get_selection_from_column();
-
- if (r_col>=selection_from_col && r_col<=text_edit->get_selection_to_column()) {
- r_col=selection_line;
- r_col=selection_from_col;
- }
- }
- }
-
- if (r_line==result_line && r_col>=result_col && r_col<=result_col+get_search_text().length()) {
- r_col=result_col;
- }
-}
-
-bool FindReplaceBar::search_current() {
-
- uint32_t flags=0;
-
- if (is_whole_words())
- flags|=TextEdit::SEARCH_WHOLE_WORDS;
- if (is_case_sensitive())
- flags|=TextEdit::SEARCH_MATCH_CASE;
-
- int line, col;
- _get_search_from(line, col);
-
- return _search(flags,line,col);
-}
-
-bool FindReplaceBar::search_prev() {
-
- uint32_t flags=0;
- String text = get_search_text();
-
- if (is_whole_words())
- flags|=TextEdit::SEARCH_WHOLE_WORDS;
- if (is_case_sensitive())
- flags|=TextEdit::SEARCH_MATCH_CASE;
-
- flags|=TextEdit::SEARCH_BACKWARDS;
-
- int line, col;
- _get_search_from(line, col);
-
- col-=text.length();
- if (col<0) {
- line-=1;
- if (line<0)
- line=text_edit->get_line_count()-1;
- col=text_edit->get_line(line).length();
- }
-
- return _search(flags,line,col);
-}
-
-bool FindReplaceBar::search_next() {
-
- uint32_t flags=0;
- String text = get_search_text();
-
- if (is_whole_words())
- flags|=TextEdit::SEARCH_WHOLE_WORDS;
- if (is_case_sensitive())
- flags|=TextEdit::SEARCH_MATCH_CASE;
-
- int line, col;
- _get_search_from(line, col);
-
- if (line==result_line && col==result_col) {
- col+=text.length();
- if (col>text_edit->get_line(line).length()) {
- line+=1;
- if (line>=text_edit->get_line_count())
- line=0;
- col=0;
- }
- }
-
- return _search(flags,line,col);
-}
-
-void FindReplaceBar::_hide_bar() {
-
- if (replace_text->has_focus() || search_text->has_focus())
- text_edit->grab_focus();
-
- text_edit->set_search_text("");
- result_line = -1;
- result_col = -1;
- replace_hbc->hide();
- replace_options_hbc->hide();
- hide();
-}
-
-void FindReplaceBar::_show_search() {
-
- show();
- search_text->grab_focus();
-
- if (text_edit->is_selection_active() && !selection_only->is_pressed()) {
- search_text->set_text(text_edit->get_selection_text());
- }
-
- if (!get_search_text().empty()) {
- search_text->select_all();
- search_text->set_cursor_pos(search_text->get_text().length());
- search_current();
- }
-}
-
-void FindReplaceBar::popup_search() {
-
- replace_hbc->hide();
- replace_options_hbc->hide();
- _show_search();
-}
-
-void FindReplaceBar::popup_replace() {
-
-
- if (!replace_hbc->is_visible_in_tree() || !replace_options_hbc->is_visible_in_tree()) {
- replace_text->clear();
- replace_hbc->show();
- replace_options_hbc->show();
-
- }
-
- selection_only->set_pressed( (text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line()) );
-
- _show_search();
-}
-
-void FindReplaceBar::_search_options_changed(bool p_pressed) {
-
- search_current();
-}
-
-void FindReplaceBar::_editor_text_changed() {
-
- if (is_visible_in_tree()) {
- preserve_cursor=true;
- search_current();
- preserve_cursor=false;
- }
-}
-
-void FindReplaceBar::_search_text_changed(const String& p_text) {
-
- search_current();
-}
-
-void FindReplaceBar::_search_text_entered(const String& p_text) {
-
- search_next();
-}
-
-void FindReplaceBar::_replace_text_entered(const String& p_text) {
-
- if (selection_only->is_pressed() && text_edit->is_selection_active()) {
- _replace_all();
- _hide_bar();
- }
-}
-
-String FindReplaceBar::get_search_text() const {
-
- return search_text->get_text();
-}
-
-String FindReplaceBar::get_replace_text() const {
-
- return replace_text->get_text();
-}
-
-bool FindReplaceBar::is_case_sensitive() const {
-
- return case_sensitive->is_pressed();
-}
-
-bool FindReplaceBar::is_whole_words() const {
-
- return whole_words->is_pressed();
-}
-
-bool FindReplaceBar::is_selection_only() const {
-
- return selection_only->is_pressed();
-}
-
-void FindReplaceBar::set_error(const String &p_label) {
-
- error_label->set_text(p_label);
-}
-
-void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) {
-
- text_edit = p_text_edit;
- text_edit->connect("text_changed",this,"_editor_text_changed");
-}
-
-void FindReplaceBar::_bind_methods() {
-
- ClassDB::bind_method("_unhandled_input",&FindReplaceBar::_unhandled_input);
-
- ClassDB::bind_method("_editor_text_changed",&FindReplaceBar::_editor_text_changed);
- ClassDB::bind_method("_search_text_changed",&FindReplaceBar::_search_text_changed);
- ClassDB::bind_method("_search_text_entered",&FindReplaceBar::_search_text_entered);
- ClassDB::bind_method("_replace_text_entered",&FindReplaceBar::_replace_text_entered);
- ClassDB::bind_method("_search_current",&FindReplaceBar::search_current);
- ClassDB::bind_method("_search_next",&FindReplaceBar::search_next);
- ClassDB::bind_method("_search_prev",&FindReplaceBar::search_prev);
- ClassDB::bind_method("_replace_pressed",&FindReplaceBar::_replace);
- ClassDB::bind_method("_replace_all_pressed",&FindReplaceBar::_replace_all);
- ClassDB::bind_method("_search_options_changed",&FindReplaceBar::_search_options_changed);
- ClassDB::bind_method("_hide_pressed",&FindReplaceBar::_hide_bar);
-
- ADD_SIGNAL(MethodInfo("search"));
-}
-
-FindReplaceBar::FindReplaceBar() {
-
- replace_all_mode=false;
- preserve_cursor=false;
-
- text_vbc = memnew(VBoxContainer);
- add_child(text_vbc);
-
- HBoxContainer *search_hbc = memnew(HBoxContainer);
- text_vbc->add_child(search_hbc);
-
- search_text = memnew(LineEdit);
- search_hbc->add_child(search_text);
- search_text->set_custom_minimum_size(Size2(200, 0));
- search_text->connect("text_changed",this,"_search_text_changed");
- search_text->connect("text_entered",this,"_search_text_entered");
-
- find_prev = memnew(ToolButton);
- search_hbc->add_child(find_prev);
- find_prev->set_focus_mode(FOCUS_NONE);
- find_prev->connect("pressed",this,"_search_prev");
-
- find_next = memnew(ToolButton);
- search_hbc->add_child(find_next);
- find_next->set_focus_mode(FOCUS_NONE);
- find_next->connect("pressed",this,"_search_next");
-
- replace_hbc = memnew(HBoxContainer);
- text_vbc->add_child(replace_hbc);
- replace_hbc->hide();
-
- replace_text = memnew(LineEdit);
- replace_hbc->add_child(replace_text);
- replace_text->set_custom_minimum_size(Size2(200, 0));
- replace_text->connect("text_entered",this,"_replace_text_entered");
-
-
- replace = memnew(Button);
- replace_hbc->add_child(replace);
- replace->set_text(TTR("Replace"));
- //replace->set_focus_mode(FOCUS_NONE);
- replace->connect("pressed",this,"_replace_pressed");
-
- replace_all = memnew(Button);
- replace_hbc->add_child(replace_all);
- replace_all->set_text(TTR("Replace All"));
- //replace_all->set_focus_mode(FOCUS_NONE);
- replace_all->connect("pressed",this,"_replace_all_pressed");
-
- Control *spacer_split = memnew( Control );
- spacer_split->set_custom_minimum_size(Size2(0, 1));
- text_vbc->add_child(spacer_split);
-
- VBoxContainer *options_vbc = memnew(VBoxContainer);
- add_child(options_vbc);
- options_vbc->set_h_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *search_options = memnew(HBoxContainer);
- options_vbc->add_child(search_options);
-
- case_sensitive = memnew(CheckBox);
- search_options->add_child(case_sensitive);
- case_sensitive->set_text(TTR("Match Case"));
- case_sensitive->set_focus_mode(FOCUS_NONE);
- case_sensitive->connect("toggled",this,"_search_options_changed");
-
- whole_words = memnew(CheckBox);
- search_options->add_child(whole_words);
- whole_words->set_text(TTR("Whole Words"));
- whole_words->set_focus_mode(FOCUS_NONE);
- whole_words->connect("toggled",this,"_search_options_changed");
-
- error_label = memnew(Label);
- search_options->add_child(error_label);
- error_label->add_color_override("font_color", Color(1,1,0,1));
- error_label->add_color_override("font_color_shadow", Color(0,0,0,1));
- error_label->add_constant_override("shadow_as_outline", 1);
-
- search_options->add_spacer();
-
- hide_button = memnew(TextureButton);
- search_options->add_child(hide_button);
- hide_button->set_focus_mode(FOCUS_NONE);
- hide_button->connect("pressed",this,"_hide_pressed");
-
- replace_options_hbc = memnew(HBoxContainer);
- options_vbc->add_child(replace_options_hbc);
- replace_options_hbc->hide();
-
- selection_only = memnew(CheckBox);
- replace_options_hbc->add_child(selection_only);
- selection_only->set_text(TTR("Selection Only"));
- selection_only->set_focus_mode(FOCUS_NONE);
- selection_only->connect("toggled",this,"_search_options_changed");
-}
-
-
-void FindReplaceDialog::popup_search() {
-
- set_title(TTR("Search"));
- replace_mc->hide();
- replace_label->hide();
- replace_vb->hide();
- skip->hide();
- popup_centered(Point2(300,190));
- get_ok()->set_text(TTR("Find"));
- search_text->grab_focus();
- if (text_edit->is_selection_active() && ( text_edit->get_selection_from_line() == text_edit->get_selection_to_line())) {
-
- search_text->set_text( text_edit->get_selection_text() );
- }
- search_text->select_all();
-
- error_label->set_text("");
-
-}
-
-void FindReplaceDialog::popup_replace() {
-
-
- set_title(TTR("Replace"));
- bool do_selection=(text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line());
-
- set_replace_selection_only(do_selection);
-
- if (!do_selection && text_edit->is_selection_active()) {
- search_text->set_text(text_edit->get_selection_text());
- }
-
- replace_mc->show();
- replace_label->show();
- replace_vb->show();
- popup_centered(Point2(300,300));
- if (search_text->get_text()!="" && replace_text->get_text()=="") {
- search_text->select(0,0);
- replace_text->grab_focus();
- } else {
- search_text->grab_focus();
- search_text->select_all();
- }
- error_label->set_text("");
-
- if (prompt->is_pressed()) {
- skip->show();
- get_ok()->set_text(TTR("Next"));
- selection_only->set_disabled(true);
-
- } else {
- skip->hide();
- get_ok()->set_text(TTR("Replace"));
- selection_only->set_disabled(false);
- }
-
-}
-
-void FindReplaceDialog::_search_callback() {
-
- if (is_replace_mode())
- _replace();
- else
- _search();
-
-}
-
-void FindReplaceDialog::_replace_skip_callback() {
-
- _search();
-}
-
-void FindReplaceDialog::_replace() {
-
- text_edit->begin_complex_operation();
- if (is_replace_all_mode()) {
-
- //line as x so it gets priority in comparison, column as y
- Point2i orig_cursor(text_edit->cursor_get_line(),text_edit->cursor_get_column());
- Point2i prev_match=Point2(-1,-1);
-
-
- bool selection_enabled = text_edit->is_selection_active();
- Point2i selection_begin,selection_end;
- if (selection_enabled) {
- selection_begin=Point2i(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
- selection_end=Point2i(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
- }
- int vsval = text_edit->get_v_scroll();
- //int hsval = text_edit->get_h_scroll();
-
- text_edit->cursor_set_line(0);
- text_edit->cursor_set_column(0);
-
- int rc=0;
-
- while(_search()) {
-
- if (!text_edit->is_selection_active()) {
- //search selects
- break;
- }
-
- //replace area
- Point2i match_from(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
- Point2i match_to(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
-
- if (match_from < prev_match)
- break; //done
-
- prev_match=match_to;
-
- if (selection_enabled && is_replace_selection_only()) {
-
- if (match_from<selection_begin || match_to>selection_end)
- continue;
-
- //replace but adjust selection bounds
-
- text_edit->insert_text_at_cursor(get_replace_text());
- if (match_to.x==selection_end.x)
- selection_end.y+=get_replace_text().length() - get_search_text().length();
- } else {
- //just replace
- text_edit->insert_text_at_cursor(get_replace_text());
- }
- rc++;
-
- }
- //restore editor state (selection, cursor, scroll)
- text_edit->cursor_set_line(orig_cursor.x);
- text_edit->cursor_set_column(orig_cursor.y);
-
- if (selection_enabled && is_replace_selection_only()) {
- //reselect
- text_edit->select(selection_begin.x,selection_begin.y,selection_end.x,selection_end.y);
- } else {
- text_edit->deselect();
- }
-
- text_edit->set_v_scroll(vsval);
- //text_edit->set_h_scroll(hsval);
- error_label->set_text(vformat(TTR("Replaced %d ocurrence(s)."),rc));
-
-
- //hide();
- } else {
-
- if (text_edit->get_selection_text()==get_search_text()) {
-
- text_edit->insert_text_at_cursor(get_replace_text());
- }
-
- _search();
- }
- text_edit->end_complex_operation();
-}
-
-
-
-bool FindReplaceDialog::_search() {
-
-
- String text=get_search_text();
- uint32_t flags=0;
-
- if (is_whole_words())
- flags|=TextEdit::SEARCH_WHOLE_WORDS;
- if (is_case_sensitive())
- flags|=TextEdit::SEARCH_MATCH_CASE;
- if (is_backwards())
- flags|=TextEdit::SEARCH_BACKWARDS;
-
- int line=text_edit->cursor_get_line(),col=text_edit->cursor_get_column();
-
- if (is_backwards()) {
- col-=1;
- if (col<0) {
- line-=1;
- if (line<0) {
- line=text_edit->get_line_count()-1;
- }
- col=text_edit->get_line(line).length();
- }
- }
- bool found = text_edit->search(text,flags,line,col,line,col);
-
-
- if (found) {
- // print_line("found");
- text_edit->cursor_set_line(line);
- if (is_backwards())
- text_edit->cursor_set_column(col);
- else
- text_edit->cursor_set_column(col+text.length());
- text_edit->select(line,col,line,col+text.length());
- set_error("");
- return true;
- } else {
-
- set_error(TTR("Not found!"));
- return false;
- }
-
-}
-
-void FindReplaceDialog::_prompt_changed() {
-
- if (prompt->is_pressed()) {
- skip->show();
- get_ok()->set_text(TTR("Next"));
- selection_only->set_disabled(true);
-
- } else {
- skip->hide();
- get_ok()->set_text(TTR("Replace"));
- selection_only->set_disabled(false);
- }
-}
-
-
-void FindReplaceDialog::_skip_pressed() {
-
- _replace_skip_callback();
-}
-
-bool FindReplaceDialog::is_replace_mode() const {
-
- return replace_text->is_visible_in_tree();
-}
-
-bool FindReplaceDialog::is_replace_all_mode() const {
-
- return !prompt->is_pressed();
-}
-
-bool FindReplaceDialog::is_replace_selection_only() const {
-
- return selection_only->is_pressed();
-}
-void FindReplaceDialog::set_replace_selection_only(bool p_enable){
-
- selection_only->set_pressed(p_enable);
-}
-
-
-void FindReplaceDialog::ok_pressed() {
-
- _search_callback();
-}
-
-void FindReplaceDialog::_search_text_entered(const String& p_text) {
-
- if (replace_text->is_visible_in_tree())
- return;
- emit_signal("search");
- _search();
-
-}
-
-void FindReplaceDialog::_replace_text_entered(const String& p_text) {
-
- if (!replace_text->is_visible_in_tree())
- return;
-
- emit_signal("search");
- _replace();
-
-}
-
-
-String FindReplaceDialog::get_search_text() const {
-
- return search_text->get_text();
-}
-String FindReplaceDialog::get_replace_text() const {
-
- return replace_text->get_text();
-}
-bool FindReplaceDialog::is_whole_words() const {
-
- return whole_words->is_pressed();
-}
-bool FindReplaceDialog::is_case_sensitive() const {
-
- return case_sensitive->is_pressed();
-
-}
-bool FindReplaceDialog::is_backwards() const {
-
- return backwards->is_pressed();
-
-}
-
-void FindReplaceDialog::set_error(const String& p_error) {
-
- error_label->set_text(p_error);
-}
-
-void FindReplaceDialog::set_text_edit(TextEdit *p_text_edit) {
-
- text_edit=p_text_edit;
-}
-
-void FindReplaceDialog::search_next() {
- _search();
-}
-
-
-void FindReplaceDialog::_bind_methods() {
-
- ClassDB::bind_method("_search_text_entered",&FindReplaceDialog::_search_text_entered);
- ClassDB::bind_method("_replace_text_entered",&FindReplaceDialog::_replace_text_entered);
- ClassDB::bind_method("_prompt_changed",&FindReplaceDialog::_prompt_changed);
- ClassDB::bind_method("_skip_pressed",&FindReplaceDialog::_skip_pressed);
- ADD_SIGNAL(MethodInfo("search"));
- ADD_SIGNAL(MethodInfo("skip"));
-
-}
-
-FindReplaceDialog::FindReplaceDialog() {
-
- set_self_modulate(Color(1,1,1,0.8));
-
- VBoxContainer *vb = memnew( VBoxContainer );
- add_child(vb);
-
-
-
- search_text = memnew( LineEdit );
- vb->add_margin_child(TTR("Search"),search_text);
- search_text->connect("text_entered", this,"_search_text_entered");
- //search_text->set_self_opacity(0.7);
-
-
-
- replace_label = memnew( Label);
- replace_label->set_text(TTR("Replace By"));
- vb->add_child(replace_label);
- replace_mc= memnew( MarginContainer);
- vb->add_child(replace_mc);
-
- replace_text = memnew( LineEdit );
- replace_text->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- replace_text->set_begin( Point2(15,132) );
- replace_text->set_end( Point2(15,135) );
- //replace_text->set_self_opacity(0.7);
- replace_mc->add_child(replace_text);
-
-
- replace_text->connect("text_entered", this,"_replace_text_entered");
-
-
-
- MarginContainer *opt_mg = memnew( MarginContainer );
- vb->add_child(opt_mg);
- VBoxContainer *svb = memnew( VBoxContainer);
- opt_mg->add_child(svb);
-
- svb ->add_child(memnew(Label));
-
- whole_words = memnew( CheckButton );
- whole_words->set_text(TTR("Whole Words"));
- svb->add_child(whole_words);
-
- case_sensitive = memnew( CheckButton );
- case_sensitive->set_text(TTR("Case Sensitive"));
- svb->add_child(case_sensitive);
-
- backwards = memnew( CheckButton );
- backwards->set_text(TTR("Backwards"));
- svb->add_child(backwards);
-
- opt_mg = memnew( MarginContainer );
- vb->add_child(opt_mg);
- VBoxContainer *rvb = memnew( VBoxContainer);
- opt_mg->add_child(rvb);
- replace_vb=rvb;
- //rvb ->add_child(memnew(HSeparator));
- rvb ->add_child(memnew(Label));
-
- prompt = memnew( CheckButton );
- prompt->set_text(TTR("Prompt On Replace"));
- rvb->add_child(prompt);
- prompt->connect("pressed", this,"_prompt_changed");
-
- selection_only = memnew( CheckButton );
- selection_only->set_text(TTR("Selection Only"));
- rvb->add_child(selection_only);
-
-
- int margin = get_constant("margin","Dialogs");
- int button_margin = get_constant("button_margin","Dialogs");
-
- skip = memnew( Button );
- skip->set_anchor( MARGIN_LEFT, ANCHOR_END );
- skip->set_anchor( MARGIN_TOP, ANCHOR_END );
- skip->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- skip->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- skip->set_begin( Point2( 70, button_margin ) );
- skip->set_end( Point2( 10, margin ) );
- skip->set_text(TTR("Skip"));
- add_child(skip);
- skip->connect("pressed", this,"_skip_pressed");
-
-
- error_label = memnew( Label );
- error_label->set_align(Label::ALIGN_CENTER);
- error_label->add_color_override("font_color",Color(1,0.4,0.3));
- error_label->add_color_override("font_color_shadow",Color(0,0,0,0.2));
- error_label->add_constant_override("shadow_as_outline",1);
-
- vb->add_child(error_label);
-
-
- set_hide_on_ok(false);
-
-}
-
-
-/*** CODE EDITOR ****/
-
-void CodeTextEditor::_text_editor_gui_input(const InputEvent& p_event) {
-
- if (p_event.type==InputEvent::MOUSE_BUTTON) {
-
- const InputEventMouseButton& mb=p_event.mouse_button;
-
- if (mb.pressed && mb.mod.command) {
-
- if (mb.button_index==BUTTON_WHEEL_UP) {
- _zoom_in();
- } else if (mb.button_index==BUTTON_WHEEL_DOWN) {
- _zoom_out();
- }
- }
- } else if (p_event.type==InputEvent::KEY) {
-
- if (p_event.key.pressed) {
- if (ED_IS_SHORTCUT("script_editor/zoom_in", p_event)) {
- _zoom_in();
- }
- if (ED_IS_SHORTCUT("script_editor/zoom_out", p_event)) {
- _zoom_out();
- }
- if (ED_IS_SHORTCUT("script_editor/reset_zoom", p_event)) {
- _reset_zoom();
- }
- }
- }
-}
-
-void CodeTextEditor::_zoom_in() {
- font_resize_val+=1;
-
- if (font_resize_timer->get_time_left()==0)
- font_resize_timer->start();
-}
-
-void CodeTextEditor::_zoom_out() {
- font_resize_val-=1;
-
- if (font_resize_timer->get_time_left()==0)
- font_resize_timer->start();
-}
-
-void CodeTextEditor::_reset_zoom() {
- Ref<DynamicFont> font = text_editor->get_font("font"); // reset source font size to default
-
- if (font.is_valid()) {
- EditorSettings::get_singleton()->set("interface/source_font_size",14);
- font->set_size(14);
- }
-}
-
-void CodeTextEditor::_line_col_changed() {
-
- line_nb->set_text(itos(text_editor->cursor_get_line() + 1));
- col_nb->set_text(itos(text_editor->cursor_get_column() + 1));
-}
-
-void CodeTextEditor::_text_changed() {
-
- code_complete_timer->start();
- idle->start();
-}
-
-void CodeTextEditor::_code_complete_timer_timeout() {
- if (!is_visible_in_tree())
- return;
- if (enable_complete_timer)
- text_editor->query_code_comple();
-}
-
-void CodeTextEditor::_complete_request() {
-
- List<String> entries;
- String ctext = text_editor->get_text_for_completion();
- _code_complete_script(ctext,&entries);
- if (code_complete_func) {
- code_complete_func(code_complete_ud,ctext,&entries);
- }
- // print_line("COMPLETE: "+p_request);
- if (entries.size()==0)
- return;
- Vector<String> strs;
- strs.resize(entries.size());
- int i=0;
- for(List<String>::Element *E=entries.front();E;E=E->next()) {
-
- strs[i++]=E->get();
- }
-
- text_editor->code_complete(strs);
-}
-
-void CodeTextEditor::_font_resize_timeout() {
-
- Ref<DynamicFont> font = text_editor->get_font("font");
-
- if (font.is_valid()) {
- int size=font->get_size()+font_resize_val;
-
- if (size>=8 && size<=96) {
- EditorSettings::get_singleton()->set("interface/source_font_size",size);
- font->set_size(size);
- }
-
- font_resize_val=0;
- }
-}
-
-void CodeTextEditor::update_editor_settings() {
-
- text_editor->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
- text_editor->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
- text_editor->set_tab_size(EditorSettings::get_singleton()->get("text_editor/indent/tab_size"));
- text_editor->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
- text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers"));
- text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/line_numbers/line_numbers_zero_padded"));
- text_editor->set_show_line_length_guideline(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_length_guideline"));
- text_editor->set_line_length_guideline_column(EditorSettings::get_singleton()->get("text_editor/line_numbers/line_length_guideline_column"));
- text_editor->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
- text_editor->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
- text_editor->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
- text_editor->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
- text_editor->set_draw_breakpoint_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_breakpoint_gutter"));
- text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
-}
-
-void CodeTextEditor::set_error(const String& p_error) {
-
- if (p_error!="") {
- error->set_text(p_error);
- error->show();
- } else {
- error->hide();
- }
-
-}
-
-void CodeTextEditor::_update_font() {
-
- // FONTS
- String editor_font = EDITOR_DEF("text_editor/theme/font", "");
- bool font_overridden = false;
- if (editor_font!="") {
- Ref<Font> fnt = ResourceLoader::load(editor_font);
- if (fnt.is_valid()) {
- text_editor->add_font_override("font",fnt);
- font_overridden = true;
- }
- }
- if(!font_overridden) {
-
- text_editor->add_font_override("font",get_font("source","EditorFonts"));
- }
-}
-
-void CodeTextEditor::_on_settings_change() {
-
- _update_font();
-
- // AUTO BRACE COMPLETION
- text_editor->set_auto_brace_completion(
- EDITOR_DEF("text_editor/completion/auto_brace_complete", true)
- );
-
- code_complete_timer->set_wait_time(
- EDITOR_DEF("text_editor/completion/code_complete_delay",.3f)
- );
-
- enable_complete_timer = EDITOR_DEF("text_editor/completion/enable_code_completion_delay",true);
-
- // call hint settings
- text_editor->set_callhint_settings(
- EDITOR_DEF("text_editor/completion/put_callhint_tooltip_below_current_line", true),
- EDITOR_DEF("text_editor/completion/callhint_tooltip_offset", Vector2())
- );
-}
-
-void CodeTextEditor::_text_changed_idle_timeout() {
-
-
- _validate_script();
- emit_signal("validate_script");
-}
-
-void CodeTextEditor::_notification(int p_what) {
-
-
- if (p_what==EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- _load_theme_settings();
- emit_signal("load_theme_settings");
- }
- if (p_what==NOTIFICATION_THEME_CHANGED) {
- _update_font();
- }
-}
-
-void CodeTextEditor::_bind_methods() {
-
- ClassDB::bind_method("_text_editor_gui_input",&CodeTextEditor::_text_editor_gui_input);
- ClassDB::bind_method("_line_col_changed",&CodeTextEditor::_line_col_changed);
- ClassDB::bind_method("_text_changed",&CodeTextEditor::_text_changed);
- ClassDB::bind_method("_on_settings_change",&CodeTextEditor::_on_settings_change);
- ClassDB::bind_method("_text_changed_idle_timeout",&CodeTextEditor::_text_changed_idle_timeout);
- ClassDB::bind_method("_code_complete_timer_timeout",&CodeTextEditor::_code_complete_timer_timeout);
- ClassDB::bind_method("_complete_request",&CodeTextEditor::_complete_request);
- ClassDB::bind_method("_font_resize_timeout",&CodeTextEditor::_font_resize_timeout);
-
- ADD_SIGNAL(MethodInfo("validate_script"));
- ADD_SIGNAL(MethodInfo("load_theme_settings"));
-
-}
-
-void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func,void * p_ud) {
- code_complete_func=p_code_complete_func;
- code_complete_ud=p_ud;
-}
-
-
-CodeTextEditor::CodeTextEditor() {
-
- code_complete_func=NULL;
- ED_SHORTCUT("script_editor/zoom_in", TTR("Zoom In"), KEY_MASK_CMD|KEY_EQUAL);
- ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD|KEY_MINUS);
- ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD|KEY_0);
-
- find_replace_bar = memnew( FindReplaceBar );
- add_child(find_replace_bar);
- find_replace_bar->set_h_size_flags(SIZE_EXPAND_FILL);
- find_replace_bar->hide();
-
- text_editor = memnew( TextEdit );
- add_child(text_editor);
- text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
-
- find_replace_bar->set_text_edit(text_editor);
-
- text_editor->set_show_line_numbers(true);
- text_editor->set_brace_matching(true);
- text_editor->set_auto_indent(true);
-
- MarginContainer *status_mc = memnew( MarginContainer );
- add_child(status_mc);
- status_mc->set("custom_constants/margin_left", 2);
- status_mc->set("custom_constants/margin_top", 5);
- status_mc->set("custom_constants/margin_right", 2);
- status_mc->set("custom_constants/margin_bottom", 1);
-
- HBoxContainer *status_bar = memnew( HBoxContainer );
- status_mc->add_child(status_bar);
- status_bar->set_h_size_flags(SIZE_EXPAND_FILL);
- status_bar->add_child( memnew( Label ) ); //to keep the height if the other labels are not visible
-
- idle = memnew( Timer );
- add_child(idle);
- idle->set_one_shot(true);
- idle->set_wait_time(EDITOR_DEF("text_editor/completion/idle_parse_delay",2));
-
- code_complete_timer = memnew(Timer);
- add_child(code_complete_timer);
- code_complete_timer->set_one_shot(true);
- enable_complete_timer = EDITOR_DEF("text_editor/completion/enable_code_completion_delay",true);
-
- code_complete_timer->set_wait_time(EDITOR_DEF("text_editor/completion/code_complete_delay",.3f));
-
- error = memnew( Label );
- status_bar->add_child(error);
- error->hide();
- error->set_valign(Label::VALIGN_CENTER);
- error->add_color_override("font_color",Color(1,0.7,0.6,0.9));
-
- status_bar->add_spacer();
-
- Label *line_txt = memnew( Label );
- status_bar->add_child(line_txt);
- line_txt->set_align(Label::ALIGN_RIGHT);
- line_txt->set_valign(Label::VALIGN_CENTER);
- line_txt->set_v_size_flags(SIZE_FILL);
- line_txt->set_text(TTR("Line:"));
-
- line_nb = memnew( Label );
- status_bar->add_child(line_nb);
- line_nb->set_valign(Label::VALIGN_CENTER);
- line_nb->set_v_size_flags(SIZE_FILL);
- line_nb->set_autowrap(true); // workaround to prevent resizing the label on each change
- line_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE);
-
- Label *col_txt = memnew( Label );
- status_bar->add_child(col_txt);
- col_txt->set_align(Label::ALIGN_RIGHT);
- col_txt->set_valign(Label::VALIGN_CENTER);
- col_txt->set_v_size_flags(SIZE_FILL);
- col_txt->set_text(TTR("Col:"));
-
- col_nb = memnew( Label );
- status_bar->add_child(col_nb);
- col_nb->set_valign(Label::VALIGN_CENTER);
- col_nb->set_v_size_flags(SIZE_FILL);
- col_nb->set_autowrap(true); // workaround to prevent resizing the label on each change
- col_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE);
-
- text_editor->connect("gui_input", this,"_text_editor_gui_input");
- text_editor->connect("cursor_changed", this,"_line_col_changed");
- text_editor->connect("text_changed", this,"_text_changed");
- text_editor->connect("request_completion", this,"_complete_request");
- Vector<String> cs;
- cs.push_back(".");
- cs.push_back(",");
- cs.push_back("(");
- cs.push_back("$");
- text_editor->set_completion(true,cs);
- idle->connect("timeout", this,"_text_changed_idle_timeout");
-
- code_complete_timer->connect("timeout", this,"_code_complete_timer_timeout");
-
- font_resize_val=0;
- font_resize_timer = memnew(Timer);
- add_child(font_resize_timer);
- font_resize_timer->set_one_shot(true);
- font_resize_timer->set_wait_time(0.07);
- font_resize_timer->connect("timeout", this, "_font_resize_timeout");
-
- EditorSettings::get_singleton()->connect("settings_changed",this,"_on_settings_change");
-}
diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h
deleted file mode 100644
index a000f02010..0000000000
--- a/tools/editor/code_editor.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/*************************************************************************/
-/* code_editor.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 CODE_EDITOR_H
-#define CODE_EDITOR_H
-
-#include "tools/editor/editor_plugin.h"
-#include "scene/gui/text_edit.h"
-#include "scene/gui/dialogs.h"
-#include "scene/main/timer.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/check_button.h"
-#include "scene/gui/check_box.h"
-#include "scene/gui/line_edit.h"
-
-
-
-class GotoLineDialog : public ConfirmationDialog {
-
- GDCLASS(GotoLineDialog,ConfirmationDialog);
-
- Label *line_label;
- LineEdit *line;
-
- TextEdit *text_editor;
-
- virtual void ok_pressed();
-public:
-
- void popup_find_line(TextEdit *p_edit);
- int get_line() const;
-
-
- void set_text_editor(TextEdit *p_text_editor);
- GotoLineDialog();
-};
-
-class FindReplaceBar : public HBoxContainer {
-
- GDCLASS(FindReplaceBar,HBoxContainer);
-
- LineEdit *search_text;
- ToolButton *find_prev;
- ToolButton *find_next;
- CheckBox *case_sensitive;
- CheckBox *whole_words;
- Label *error_label;
- TextureButton *hide_button;
-
- LineEdit *replace_text;
- Button *replace;
- Button *replace_all;
- CheckBox *selection_only;
-
- VBoxContainer *text_vbc;
- HBoxContainer *replace_hbc;
- HBoxContainer *replace_options_hbc;
-
- TextEdit *text_edit;
-
- int result_line;
- int result_col;
-
- bool replace_all_mode;
- bool preserve_cursor;
-
- void _get_search_from(int& r_line, int& r_col);
-
- void _show_search();
- void _hide_bar();
-
- void _editor_text_changed();
- void _search_options_changed(bool p_pressed);
- void _search_text_changed(const String& p_text);
- void _search_text_entered(const String& p_text);
- void _replace_text_entered(const String& p_text);
-
-protected:
- void _notification(int p_what);
- void _unhandled_input(const InputEvent &p_event);
-
- bool _search(uint32_t p_flags, int p_from_line, int p_from_col);
-
- void _replace();
- void _replace_all();
-
- static void _bind_methods();
-
-public:
- String get_search_text() const;
- String get_replace_text() const;
-
- bool is_case_sensitive() const;
- bool is_whole_words() const;
- bool is_selection_only() const;
- void set_error(const String& p_label);
-
- void set_text_edit(TextEdit *p_text_edit);
-
- void popup_search();
- void popup_replace();
-
- bool search_current();
- bool search_prev();
- bool search_next();
-
- FindReplaceBar();
-};
-
-class FindReplaceDialog : public ConfirmationDialog {
-
- GDCLASS(FindReplaceDialog,ConfirmationDialog);
-
- LineEdit *search_text;
- LineEdit *replace_text;
- CheckButton *whole_words;
- CheckButton *case_sensitive;
- CheckButton *backwards;
- CheckButton *prompt;
- CheckButton *selection_only;
- Button *skip;
- Label *error_label;
- MarginContainer *replace_mc;
- Label *replace_label;
- VBoxContainer *replace_vb;
-
- void _search_text_entered(const String& p_text);
- void _replace_text_entered(const String& p_text);
- void _prompt_changed();
- void _skip_pressed();
-
-
- TextEdit *text_edit;
-protected:
-
- void _search_callback();
- void _replace_skip_callback();
-
- bool _search();
- void _replace();
-
- virtual void ok_pressed();
- static void _bind_methods();
-public:
-
- String get_search_text() const;
- String get_replace_text() const;
- bool is_whole_words() const;
- bool is_case_sensitive() const;
- bool is_backwards() const;
- bool is_replace_mode() const;
- bool is_replace_all_mode() const;
- bool is_replace_selection_only() const;
- void set_replace_selection_only(bool p_enable);
-
- void set_error(const String& p_error);
-
- void popup_search();
- void popup_replace();
-
- void set_text_edit(TextEdit *p_text_edit);
-
- void search_next();
- FindReplaceDialog();
-};
-
-
-typedef void (*CodeTextEditorCodeCompleteFunc)(void* p_ud,const String& p_code, List<String>* r_options);
-
-class CodeTextEditor : public VBoxContainer {
-
- GDCLASS(CodeTextEditor,VBoxContainer);
-
- TextEdit *text_editor;
- FindReplaceBar *find_replace_bar;
-
- Label *line_nb;
- Label *col_nb;
- Label *info;
- Timer *idle;
- Timer *code_complete_timer;
- bool enable_complete_timer;
-
- Timer *font_resize_timer;
- int font_resize_val;
-
- Label *error;
-
- void _on_settings_change();
-
- void _update_font();
- void _complete_request();
- void _font_resize_timeout();
-
- void _text_editor_gui_input(const InputEvent& p_event);
- void _zoom_in();
- void _zoom_out();
- void _reset_zoom();
-
-
- CodeTextEditorCodeCompleteFunc code_complete_func;
- void *code_complete_ud;
-
-protected:
-
-
- virtual void _load_theme_settings() {}
- virtual void _validate_script() {}
- virtual void _code_complete_script(const String& p_code, List<String>* r_options) {}
-
- void _text_changed_idle_timeout();
- void _code_complete_timer_timeout();
- void _text_changed();
- void _line_col_changed();
- void _notification(int);
- static void _bind_methods();
-
-public:
-
- void update_editor_settings();
- void set_error(const String& p_error);
- void update_line_and_column() { _line_col_changed(); }
- TextEdit *get_text_edit() { return text_editor; }
- FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
- virtual void apply_code() {}
-
-
- void set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void * p_ud);
-
-
- CodeTextEditor();
-};
-
-
-
-#endif // CODE_EDITOR_H
diff --git a/tools/editor/collada/collada.cpp b/tools/editor/collada/collada.cpp
deleted file mode 100644
index a23fd84aa0..0000000000
--- a/tools/editor/collada/collada.cpp
+++ /dev/null
@@ -1,2801 +0,0 @@
-/*************************************************************************/
-/* collada.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifdef TOOLS_ENABLED
-
-#include "collada.h"
-
-#include "stdio.h"
-
-//#define DEBUG_DEFAULT_ANIMATION
-//#define DEBUG_COLLADA
-#ifdef DEBUG_COLLADA
-#define COLLADA_PRINT(m_what) print_line(m_what)
-#else
-#define COLLADA_PRINT(m_what)
-#endif
-
-#define COLLADA_IMPORT_SCALE_SCENE
-
-/* HELPERS */
-
-
-
-String Collada::Effect::get_texture_path(const String& p_source,Collada& state) const {
-
- String image=p_source;
- ERR_FAIL_COND_V(!state.state.image_map.has(image),"");
- return state.state.image_map[image].path;
-}
-
-Transform Collada::get_root_transform() const {
-
- Transform unit_scale_transform;
-#ifndef COLLADA_IMPORT_SCALE_SCENE
- unit_scale_transform.scale(Vector3(state.unit_scale,state.unit_scale,state.unit_scale));
-#endif
- return unit_scale_transform;
-}
-
-
-
-void Collada::Vertex::fix_unit_scale(Collada &state) {
-#ifdef COLLADA_IMPORT_SCALE_SCENE
- vertex*=state.state.unit_scale;
-#endif
-}
-
-static String _uri_to_id(const String& p_uri) {
-
- if (p_uri.begins_with("#"))
- return p_uri.substr(1,p_uri.size()-1);
- else
- return p_uri;
-
-}
-
-/** HELPER FUNCTIONS **/
-
-Transform Collada::fix_transform(const Transform& p_transform) {
-
- Transform tr=p_transform;
-
-#ifndef NO_UP_AXIS_SWAP
-
- if (state.up_axis!=Vector3::AXIS_Y) {
-
- for(int i=0;i<3;i++)
- SWAP(tr.basis[1][i],tr.basis[state.up_axis][i]);
- for(int i=0;i<3;i++)
- SWAP(tr.basis[i][1],tr.basis[i][state.up_axis]);
-
- SWAP(tr.origin[1],tr.origin[state.up_axis]);
-
- tr.basis[state.up_axis][0]=-tr.basis[state.up_axis][0];
- tr.basis[state.up_axis][1]=-tr.basis[state.up_axis][1];
- tr.basis[0][state.up_axis]=-tr.basis[0][state.up_axis];
- tr.basis[1][state.up_axis]=-tr.basis[1][state.up_axis];
- tr.origin[state.up_axis]=-tr.origin[state.up_axis];
- }
-#endif
-
- //tr.scale(Vector3(state.unit_scale.unit_scale.unit_scale));
- return tr;
- //return state.matrix_fix * p_transform;
-}
-
-
-static Transform _read_transform_from_array(const Vector<float>& array, int ofs=0) {
-
- Transform tr;
- // i wonder why collada matrices are transposed, given that's opposed to opengl..
- tr.basis.elements[0][0]=array[0+ofs];
- tr.basis.elements[0][1]=array[1+ofs];
- tr.basis.elements[0][2]=array[2+ofs];
- tr.basis.elements[1][0]=array[4+ofs];
- tr.basis.elements[1][1]=array[5+ofs];
- tr.basis.elements[1][2]=array[6+ofs];
- tr.basis.elements[2][0]=array[8+ofs];
- tr.basis.elements[2][1]=array[9+ofs];
- tr.basis.elements[2][2]=array[10+ofs];
- tr.origin.x=array[3+ofs];
- tr.origin.y=array[7+ofs];
- tr.origin.z=array[11+ofs];
- return tr;
-
-}
-
-/* STRUCTURES */
-
-Transform Collada::Node::compute_transform(Collada &state) const {
-
- Transform xform;
-
- for(int i=0;i<xform_list.size();i++) {
-
- Transform xform_step;
- const XForm& xf = xform_list[i];
- switch(xf.op) {
-
- case XForm::OP_ROTATE: {
- if (xf.data.size()>=4) {
-
- xform_step.rotate(Vector3(xf.data[0],xf.data[1],xf.data[2]),Math::deg2rad(xf.data[3]));
- }
- } break;
- case XForm::OP_SCALE: {
-
- if (xf.data.size()>=3) {
-
- xform_step.scale(Vector3(xf.data[0],xf.data[1],xf.data[2]));
- }
-
- } break;
- case XForm::OP_TRANSLATE: {
-
- if (xf.data.size()>=3) {
-
- xform_step.origin=Vector3(xf.data[0],xf.data[1],xf.data[2]);
- }
-
- } break;
- case XForm::OP_MATRIX: {
-
- if (xf.data.size()>=16) {
- xform_step = _read_transform_from_array(xf.data,0);
- }
-
- } break;
- default: {}
-
- }
-
- xform = xform * xform_step;
- }
-
-#ifdef COLLADA_IMPORT_SCALE_SCENE
- xform.origin*=state.state.unit_scale;
-#endif
- return xform;
-}
-
-Transform Collada::Node::get_transform() const {
-
- return default_transform;
-}
-
-Transform Collada::Node::get_global_transform() const {
-
- if (parent)
- return parent->get_global_transform() * default_transform;
- else
- return default_transform;
-
-}
-
-Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) {
-
- ERR_FAIL_COND_V(keys.size()==0,Vector<float>());
- int i=0;
-
- for(i=0;i<keys.size();i++) {
-
- if (keys[i].time>p_time)
- break;
- }
-
- if (i==0)
- return keys[0].data;
- if (i==keys.size())
- return keys[keys.size()-1].data;
-
- switch(keys[i].interp_type) {
-
- case INTERP_BEZIER: //wait for bezier
- case INTERP_LINEAR: {
-
- float c = (p_time-keys[i-1].time)/(keys[i].time-keys[i-1].time);
-
- if (keys[i].data.size()==16) {
- //interpolate a matrix
- Transform src = _read_transform_from_array(keys[i-1].data);
- Transform dst = _read_transform_from_array(keys[i].data);
-
-
- Transform interp = c<0.001 ? src : src.interpolate_with(dst,c);
-
- Vector<float> ret;
- ret.resize(16);
- Transform tr;
- // i wonder why collada matrices are transposed, given that's opposed to opengl..
- ret[0]=interp.basis.elements[0][0];
- ret[1]=interp.basis.elements[0][1];
- ret[2]=interp.basis.elements[0][2];
- ret[4]=interp.basis.elements[1][0];
- ret[5]=interp.basis.elements[1][1];
- ret[6]=interp.basis.elements[1][2];
- ret[8]=interp.basis.elements[2][0];
- ret[9]=interp.basis.elements[2][1];
- ret[10]=interp.basis.elements[2][2];
- ret[3]=interp.origin.x;
- ret[7]=interp.origin.y;
- ret[11]=interp.origin.z;
- ret[12]=0;
- ret[13]=0;
- ret[14]=0;
- ret[15]=1;
-
- return ret;
- } else {
-
- Vector<float> dest;
- dest.resize(keys[i].data.size());
- for(int j=0;j<dest.size();j++) {
-
- dest[j]=keys[i].data[j]*c+keys[i-1].data[j]*(1.0-c);
- }
- return dest;
- //interpolate one by one
- }
- } break;
- }
-
- ERR_FAIL_V(Vector<float>());
-}
-
-
-
-
-void Collada::_parse_asset(XMLParser& parser) {
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
-
- if (name=="up_axis") {
-
- parser.read();
- if (parser.get_node_data()=="X_UP")
- state.up_axis=Vector3::AXIS_X;
- if (parser.get_node_data()=="Y_UP")
- state.up_axis=Vector3::AXIS_Y;
- if (parser.get_node_data()=="Z_UP")
- state.up_axis=Vector3::AXIS_Z;
-
- COLLADA_PRINT("up axis: "+parser.get_node_data());
- } else if (name=="unit") {
-
- state.unit_scale = parser.get_attribute_value("meter").to_double();
- COLLADA_PRINT("unit scale: "+rtos(state.unit_scale));
- }
-
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="asset")
- break; //end of <asset>
- }
-}
-
-
-void Collada::_parse_image(XMLParser& parser) {
-
- String id=parser.get_attribute_value("id");
-
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
-
- Image image;
-
-
- if (state.version<State::Version(1,4,0)) {
- /* <1.4 */
- String path = parser.get_attribute_value("source").strip_edges();
- if (path.find("://")==-1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- image.path=GlobalConfig::get_singleton()->localize_path(state.local_path.get_base_dir()+"/"+path.percent_decode());
-
- }
- } else {
-
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
-
- if (name=="init_from") {
-
- parser.read();
- String path = parser.get_node_data().strip_edges().percent_decode();
-
- if (path.find("://")==-1 && path.is_rel_path()) {
- // path is relative to file being loaded, so convert to a resource path
- path=GlobalConfig::get_singleton()->localize_path(state.local_path.get_base_dir()+"/"+path);
-
- } else if (path.find("file:///")==0) {
- path=path.replace_first("file:///","");
- path=GlobalConfig::get_singleton()->localize_path(path);
- }
-
- image.path=path;
-
- } if (name=="data") {
-
- ERR_PRINT("COLLADA Embedded image data not supported!");
-
- } else if (name=="extra" && !parser.is_empty())
- parser.skip_section();
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="image")
- break; //end of <asset>
-
- }
- }
-
- state.image_map[id]=image;
-}
-
-void Collada::_parse_material(XMLParser& parser) {
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
- Material material;
-
- String id=parser.get_attribute_value("id");
- if (parser.has_attribute("name"))
- material.name=parser.get_attribute_value("name");
-
- if (state.version<State::Version(1,4,0)) {
- /* <1.4 */
- ERR_PRINT("Collada Materials < 1.4 are not supported (yet)");
- } else {
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT && parser.get_node_name()=="instance_effect") {
-
- material.instance_effect=_uri_to_id(parser.get_attribute_value("url"));
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="material")
- break; //end of <asset>
- }
- }
-
- state.material_map[id]=material;
-}
-
-//! reads floats from inside of xml element until end of xml element
-Vector<float> Collada::_read_float_array(XMLParser& parser) {
-
- if (parser.is_empty())
- return Vector<float>();
-
- Vector<String> splitters;
- splitters.push_back(" ");
- splitters.push_back("\n");
- splitters.push_back("\r");
- splitters.push_back("\t");
-
- Vector<float> array;
- while(parser.read()==OK) {
- // TODO: check for comments inside the element
- // and ignore them.
-
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- // parse float data
- String str = parser.get_node_data();
- array=str.split_floats_mk(splitters,false);
- //array=str.split_floats(" ",false);
- }
- else
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
-
- return array;
-}
-
-Vector<String> Collada::_read_string_array(XMLParser& parser) {
-
- if (parser.is_empty())
- return Vector<String>();
-
- Vector<String> array;
- while(parser.read()==OK) {
- // TODO: check for comments inside the element
- // and ignore them.
-
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- // parse String data
- String str = parser.get_node_data();
- array=str.split_spaces();
- /*
- for(int i=0;i<array.size();i++) {
- print_line(itos(i)+": "+array[i]);
- }
- */
- }
- else
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
-
- return array;
-}
-
-
-
-Transform Collada::_read_transform(XMLParser& parser) {
-
- if (parser.is_empty())
- return Transform();
-
- Vector<String> array;
- while(parser.read()==OK) {
- // TODO: check for comments inside the element
- // and ignore them.
-
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- // parse float data
- String str = parser.get_node_data();
- array=str.split_spaces();
- }
- else
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
-
- ERR_FAIL_COND_V(array.size()!=16,Transform());
- Vector<float> farr;
- farr.resize(16);
- for(int i=0;i<16;i++) {
- farr[i]=array[i].to_double();
- }
-
- return _read_transform_from_array(farr);
-}
-
-String Collada::_read_empty_draw_type(XMLParser& parser) {
-
- String empty_draw_type = "";
-
- if (parser.is_empty())
- return empty_draw_type;
-
- while (parser.read()==OK) {
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
- empty_draw_type = parser.get_node_data();
- }
- else
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
- break; // end parsing text
- }
- return empty_draw_type;
-}
-
-Variant Collada::_parse_param(XMLParser& parser) {
-
- if (parser.is_empty())
- return Variant();
-
- String from = parser.get_node_name();
- Variant data;
-
- while(parser.read()==OK) {
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name() == "float") {
-
- parser.read();
- if (parser.get_node_type()==XMLParser::NODE_TEXT) {
-
- data=parser.get_node_data().to_double();
- }
- } else if (parser.get_node_name() == "float2") {
-
- Vector<float> v2 = _read_float_array(parser);
-
- if (v2.size()>=2) {
-
- data=Vector2(v2[0],v2[1]);
- }
- } else if (parser.get_node_name() == "float3") {
-
- Vector<float> v3 = _read_float_array(parser);
-
- if (v3.size()>=3) {
-
- data=Vector3(v3[0],v3[1],v3[2]);
- }
- } else if (parser.get_node_name() == "float4") {
-
- Vector<float> v4 = _read_float_array(parser);
-
- if (v4.size()>=4) {
-
- data=Color(v4[0],v4[1],v4[2],v4[3]);
- }
- } else if (parser.get_node_name() == "sampler2D") {
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="source") {
-
- parser.read();
-
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
-
- data=parser.get_node_data();
- }
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="sampler2D")
- break;
-
- }
- } else if (parser.get_node_name() == "surface") {
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="init_from") {
-
- parser.read();
-
- if (parser.get_node_type() == XMLParser::NODE_TEXT) {
-
- data=parser.get_node_data();
- }
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="surface")
- break;
-
- }
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==from)
- break;
- }
-
- COLLADA_PRINT("newparam ending "+parser.get_node_name());
- return data;
-
-}
-
-
-
-void Collada::_parse_effect_material(XMLParser& parser,Effect &effect,String &id) {
-
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- // first come the tags we descend, but ignore the top-levels
-
- COLLADA_PRINT("node name: "+parser.get_node_name());
-
- if (!parser.is_empty() && (parser.get_node_name() == "profile_COMMON" || parser.get_node_name() == "technique" || parser.get_node_name() == "extra")) {
-
- _parse_effect_material(parser,effect,id); // try again
-
- } else if (parser.get_node_name() == "newparam") {
- String name = parser.get_attribute_value("sid");
- Variant value = _parse_param(parser);
- effect.params[name]=value;
- COLLADA_PRINT("param: "+name+" value:"+String(value));
-
- } else if (parser.get_node_name() == "constant" ||
- parser.get_node_name() == "lambert" ||
- parser.get_node_name() == "phong" ||
- parser.get_node_name() == "blinn" )
- {
-
- COLLADA_PRINT("shade model: "+parser.get_node_name());
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String what = parser.get_node_name();
-
- if ( what=="emission" ||
- what=="diffuse" ||
- what=="specular" ||
- what=="reflective") {
-
-
-
- // color or texture types
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="color") {
-
- Vector<float> colorarr = _read_float_array(parser);
- COLLADA_PRINT("colorarr size: "+rtos(colorarr.size()));
-
- if (colorarr.size()>=3) {
-
- // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
- Color color(colorarr[0],colorarr[1],colorarr[2],1.0);
- if (what=="diffuse")
- effect.diffuse.color=color;
- if (what=="specular")
- effect.specular.color=color;
- if (what=="emission")
- effect.emission.color=color;
-
- COLLADA_PRINT(what+" color: "+color);
-
- }
-
- } else if (parser.get_node_name()=="texture") {
-
- String sampler = parser.get_attribute_value("texture");
- if (!effect.params.has(sampler)) {
- ERR_PRINT(String("Couldn't find sampler: "+sampler+" in material:"+id).utf8().get_data());
- } else {
- String surface = effect.params[sampler];
-
- if (!effect.params.has(surface)) {
- ERR_PRINT(String("Couldn't find surface: "+surface+" in material:"+id).utf8().get_data());
- } else {
- String uri = effect.params[surface];
-
-
- if (what=="diffuse") {
- effect.diffuse.texture=uri;
- } else if (what=="specular") {
- effect.specular.texture=uri;
- } else if (what=="emission") {
- effect.emission.texture=uri;
- } else if (what=="bump") {
- if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype")!="NORMALMAP") {
- WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
- }
-
- effect.bump.texture=uri;
- }
-
- COLLADA_PRINT(what+" texture: "+uri);
- }
-
- }
- } else if (!parser.is_empty())
- parser.skip_section();
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == what)
- break;
- }
-
- } else if (what=="shininess") {
-#if 1
- effect.shininess=_parse_param(parser);
-#else
-
- parser.read();
- float shininess = parser.get_node_data().to_double();
- effect.shininess=shininess;
- COLLADA_PRINT("shininess: "+rtos(shininess));
-#endif
-
- }
- } if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && (
- parser.get_node_name()=="constant" ||
- parser.get_node_name()=="lambert" ||
- parser.get_node_name()=="phong" ||
- parser.get_node_name()=="blinn"))
- break;
- }
- } else if (parser.get_node_name()=="double_sided" || parser.get_node_name()=="show_double_sided") { // colladamax / google earth
-
- // 3DS Max / Google Earth double sided extension
- parser.read();
- effect.found_double_sided=true;
- effect.double_sided=parser.get_node_data().to_int();
- COLLADA_PRINT("double sided: "+itos(parser.get_node_data().to_int()));
- } else if (parser.get_node_name()=="unshaded") {
- parser.read();
- effect.unshaded=parser.get_node_data().to_int();
- } else if (parser.get_node_name()=="bump") {
-
- // color or texture types
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="texture") {
-
- String sampler = parser.get_attribute_value("texture");
- if (!effect.params.has(sampler)) {
- ERR_PRINT(String("Couldn't find sampler: "+sampler+" in material:"+id).utf8().get_data());
- } else {
- String surface = effect.params[sampler];
-
- if (!effect.params.has(surface)) {
- ERR_PRINT(String("Couldn't find surface: "+surface+" in material:"+id).utf8().get_data());
- } else {
- String uri = effect.params[surface];
-
- if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype")!="NORMALMAP") {
- WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.")
- }
-
- effect.bump.texture=uri;
- COLLADA_PRINT(" bump: "+uri);
- }
-
- }
- } else if (!parser.is_empty())
- parser.skip_section();
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "bump")
- break;
- }
-
- } else if (!parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
- (parser.get_node_name() == "effect" ||
- parser.get_node_name() == "profile_COMMON" ||
- parser.get_node_name() == "technique" ||
- parser.get_node_name() == "extra"))
- break;
- }
-
-}
-
-void Collada::_parse_effect(XMLParser& parser) {
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
- String id=parser.get_attribute_value("id");
-
- Effect effect;
- if (parser.has_attribute("name"))
- effect.name=parser.get_attribute_value("name");
- _parse_effect_material(parser,effect,id);
-
-
-
- state.effect_map[id]=effect;
-
- COLLADA_PRINT("Effect ID:"+id);
-
-}
-
-void Collada::_parse_camera(XMLParser& parser) {
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
- String id=parser.get_attribute_value("id");
-
-
- state.camera_data_map[id]=CameraData();
- CameraData &camera=state.camera_data_map[id];
-
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
-
- if (name=="perspective") {
-
- camera.mode=CameraData::MODE_PERSPECTIVE;
- } else if (name=="orthographic") {
-
- camera.mode=CameraData::MODE_ORTHOGONAL;
- } else if (name=="xfov") {
-
- parser.read();
- camera.perspective.x_fov = parser.get_node_data().to_double();
-
- } else if (name=="yfov") {
-
- parser.read();
- camera.perspective.y_fov = parser.get_node_data().to_double();
- } else if (name=="xmag") {
-
- parser.read();
- camera.orthogonal.x_mag = parser.get_node_data().to_double();
-
- } else if (name=="ymag") {
-
- parser.read();
- camera.orthogonal.y_mag = parser.get_node_data().to_double();
- } else if (name=="aspect_ratio") {
-
- parser.read();
- camera.aspect = parser.get_node_data().to_double();
-
- } else if (name=="znear") {
-
- parser.read();
- camera.z_near = parser.get_node_data().to_double();
-
- } else if (name=="zfar") {
-
- parser.read();
- camera.z_far = parser.get_node_data().to_double();
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="camera")
- break; //end of <asset>
- }
-
- COLLADA_PRINT("Camera ID:"+id);
-
-}
-
-void Collada::_parse_light(XMLParser& parser) {
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
- String id=parser.get_attribute_value("id");
-
-
- state.light_data_map[id]=LightData();
- LightData &light=state.light_data_map[id];
-
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
-
- if (name=="ambient") {
-
- light.mode=LightData::MODE_AMBIENT;
- } else if (name=="directional") {
-
- light.mode=LightData::MODE_DIRECTIONAL;
- } else if (name=="point") {
-
- light.mode=LightData::MODE_OMNI;
- } else if (name=="spot") {
-
- light.mode=LightData::MODE_SPOT;
- } else if (name=="color") {
-
- parser.read();
- Vector<float> colorarr = _read_float_array(parser);
- COLLADA_PRINT("colorarr size: "+rtos(colorarr.size()));
-
- if (colorarr.size()>=4) {
- // alpha strangely not allright? maybe it needs to be multiplied by value as a channel intensity
- Color color(colorarr[0],colorarr[1],colorarr[2],1.0);
- light.color=color;
- }
-
- } else if (name=="constant_attenuation") {
-
- parser.read();
- light.constant_att=parser.get_node_data().to_double();
- } else if (name=="linear_attenuation") {
-
- parser.read();
- light.linear_att=parser.get_node_data().to_double();
- } else if (name=="quadratic_attenuation") {
-
- parser.read();
- light.quad_att=parser.get_node_data().to_double();
- } else if (name=="falloff_angle") {
-
- parser.read();
- light.spot_angle= parser.get_node_data().to_double();
-
- } else if (name=="falloff_exponent") {
-
- parser.read();
- light.spot_exp= parser.get_node_data().to_double();
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="light")
- break; //end of <asset>
- }
-
- COLLADA_PRINT("Light ID:"+id);
-
-}
-
-
-void Collada::_parse_curve_geometry(XMLParser& parser,String p_id,String p_name) {
-
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
- //load everything into a pre dictionary
-
- state.curve_data_map[p_id]=CurveData();
-
- CurveData &curvedata = state.curve_data_map[p_id];
- curvedata.name=p_name;
-
- COLLADA_PRINT("curve name: "+p_name);
-
-
- String current_source;
- // handles geometry node and the curve childs in this loop
- // read sources with arrays and accessor for each curve
- if (parser.is_empty()) {
- return;
- }
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String section = parser.get_node_name();
-
- if (section == "source") {
-
- String id=parser.get_attribute_value("id");
- curvedata.sources[id]=CurveData::Source();
- current_source=id;
- COLLADA_PRINT("source data: "+id);
-
- } else if (section=="float_array" || section=="array") {
- // create a new array and read it.
- if (curvedata.sources.has(current_source)) {
-
- curvedata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: "+current_source+" read "+itos(curvedata.sources[current_source].array.size())+" values.");
- }
- } else if (section=="Name_array") {
- // create a new array and read it.
- if (curvedata.sources.has(current_source)) {
-
- curvedata.sources[current_source].sarray = _read_string_array(parser);
- COLLADA_PRINT("section: "+current_source+" read "+itos(curvedata.sources[current_source].array.size())+" values.");
- }
-
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
-
- if (curvedata.sources.has(current_source)) {
- curvedata.sources[current_source].stride=parser.get_attribute_value("stride").to_int();
- COLLADA_PRINT("section: "+current_source+" stride "+itos(curvedata.sources[current_source].stride));
- }
- } else if (section == "control_vertices") {
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="input") {
-
- String semantic = parser.get_attribute_value("semantic");
- String source =_uri_to_id( parser.get_attribute_value("source") );
-
- curvedata.control_vertices[semantic]=source;
-
- COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
-
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
- break;
- }
-
- } else if (!parser.is_empty()){
-
- parser.skip_section();
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="spline")
- break;
- }
-
-
-
-}
-
-
-
-void Collada::_parse_mesh_geometry(XMLParser& parser,String p_id,String p_name) {
-
-
- if (!(state.import_flags&IMPORT_FLAG_SCENE)) {
- if (!parser.is_empty())
- parser.skip_section();
- return;
- }
-
- //load everything into a pre dictionary
-
- state.mesh_data_map[p_id]=MeshData();
-
- MeshData &meshdata = state.mesh_data_map[p_id];
- meshdata.name=p_name;
-
- COLLADA_PRINT("mesh name: "+p_name);
-
-
- String current_source;
- // handles geometry node and the mesh childs in this loop
- // read sources with arrays and accessor for each mesh
- if (parser.is_empty()) {
- return;
- }
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String section = parser.get_node_name();
-
-
- if (section == "source") {
-
- String id=parser.get_attribute_value("id");
- meshdata.sources[id]=MeshData::Source();
- current_source=id;
- COLLADA_PRINT("source data: "+id);
-
- } else if (section=="float_array" || section=="array" || section=="float_array") {
- // create a new array and read it.
- if (meshdata.sources.has(current_source)) {
-
- meshdata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: "+current_source+" read "+itos(meshdata.sources[current_source].array.size())+" values.");
- }
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
-
- if (meshdata.sources.has(current_source)) {
- meshdata.sources[current_source].stride=parser.get_attribute_value("stride").to_int();
- COLLADA_PRINT("section: "+current_source+" stride "+itos(meshdata.sources[current_source].stride));
- }
- } else if (section == "vertices") {
-
- MeshData::Vertices vert;
- String id = parser.get_attribute_value("id");
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="input") {
-
- String semantic = parser.get_attribute_value("semantic");
- String source =_uri_to_id( parser.get_attribute_value("source") );
-
- vert.sources[semantic]=source;
-
- COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
-
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
- break;
- }
-
- meshdata.vertices[id]=vert;
-
- } else if (section =="triangles" || section=="polylist" || section=="polygons") {
-
- bool polygons=(section=="polygons");
- if (polygons) {
- WARN_PRINT("Primitive type \"polygons\" is not well supported (concave shapes may fail). To ensure that the geometry is properly imported, please re-export using \"triangles\" or \"polylist\".");
- }
- MeshData::Primitives prim;
-
- if (parser.has_attribute("material"))
- prim.material=parser.get_attribute_value("material");
- prim.count=parser.get_attribute_value("count").to_int();
- prim.vertex_size=0;
- int last_ref=0;
-
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="input") {
-
- String semantic = parser.get_attribute_value("semantic");
- String source =_uri_to_id( parser.get_attribute_value("source") );
-
- if (semantic=="TEXCOORD") {
- /*
- if (parser.has_attribute("set"))// a texcoord
- semantic+=parser.get_attribute_value("set");
- else
- semantic="TEXCOORD0";*/
- semantic="TEXCOORD"+itos(last_ref++);
- }
- int offset = parser.get_attribute_value("offset").to_int();
-
-
- MeshData::Primitives::SourceRef sref;
- sref.source=source;
- sref.offset=offset;
- prim.sources[semantic]=sref;
- prim.vertex_size=MAX(prim.vertex_size,offset+1);
-
- COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source+" offset: "+itos(offset));
-
-
- } else if (parser.get_node_name()=="p") { //indices
-
- Vector<float> values = _read_float_array(parser);
- if (polygons) {
-
- prim.polygons.push_back(values.size()/prim.vertex_size);
- int from = prim.indices.size();
- prim.indices.resize(from+values.size());
- for(int i=0;i<values.size();i++)
- prim.indices[from+i]=values[i];
-
- } else if (prim.vertex_size>0){
- prim.indices=values;
- }
-
- COLLADA_PRINT("read "+itos(values.size())+" index values");
-
- } else if (parser.get_node_name()=="vcount") { // primitive
-
- Vector<float> values = _read_float_array(parser);
- prim.polygons=values;
- COLLADA_PRINT("read "+itos(values.size())+" polygon values");
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
- break;
-
- }
-
- meshdata.primitives.push_back(prim);
-
- } else if (parser.get_node_name() == "double_sided") {
-
- parser.read();
- meshdata.found_double_sided=true;
- meshdata.double_sided=parser.get_node_data().to_int();
-
- } else if (parser.get_node_name() == "polygons") {
- ERR_PRINT("Primitive type \"polygons\" not supported, re-export using \"polylist\" or \"triangles\".");
- } else if (!parser.is_empty()){
-
- parser.skip_section();
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="mesh")
- break;
- }
-
-
-
-}
-
-void Collada::_parse_skin_controller(XMLParser& parser,String p_id) {
-
- state.skin_controller_data_map[p_id]=SkinControllerData();
- SkinControllerData &skindata = state.skin_controller_data_map[p_id];
-
- skindata.base=_uri_to_id(parser.get_attribute_value("source"));
-
- String current_source;
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT){
-
- String section = parser.get_node_name();
-
- if (section=="bind_shape_matrix") {
-
- skindata.bind_shape=_read_transform(parser);
-#ifdef COLLADA_IMPORT_SCALE_SCENE
- skindata.bind_shape.origin *= state.unit_scale;
-
-#endif
- COLLADA_PRINT("skeleton bind shape transform: "+skindata.bind_shape);
-
-
- } else if (section == "source") {
-
- String id=parser.get_attribute_value("id");
- skindata.sources[id]=SkinControllerData::Source();
- current_source=id;
- COLLADA_PRINT("source data: "+id);
-
- } else if (section=="float_array" || section=="array") {
- // create a new array and read it.
- if (skindata.sources.has(current_source)) {
-
- skindata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: "+current_source+" read "+itos(skindata.sources[current_source].array.size())+" values.");
- }
- } else if (section=="Name_array" || section=="IDREF_array") {
- // create a new array and read it.
-
- if (section=="IDREF_array")
- skindata.use_idrefs=true;
- if (skindata.sources.has(current_source)) {
-
- skindata.sources[current_source].sarray = _read_string_array(parser);
- if (section=="IDREF_array") {
- Vector<String> sa = skindata.sources[current_source].sarray;
- for(int i=0;i<sa.size();i++)
- state.idref_joints.insert(sa[i]);
- }
- COLLADA_PRINT("section: "+current_source+" read "+itos(skindata.sources[current_source].array.size())+" values.");
- }
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
-
- if (skindata.sources.has(current_source)) {
-
- int stride=1;
- if (parser.has_attribute("stride"))
- stride=parser.get_attribute_value("stride").to_int();
-
- skindata.sources[current_source].stride=stride;
- COLLADA_PRINT("section: "+current_source+" stride "+itos(skindata.sources[current_source].stride));
- }
-
- } else if (section == "joints") {
-
- SkinControllerData::Joints joint;
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="input") {
-
- String semantic = parser.get_attribute_value("semantic");
- String source =_uri_to_id( parser.get_attribute_value("source") );
-
- joint.sources[semantic]=source;
-
- COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
-
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
- break;
- }
-
- skindata.joints=joint;
-
- } else if (section=="vertex_weights") {
-
- SkinControllerData::Weights weights;
-
- weights.count=parser.get_attribute_value("count").to_int();
-
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="input") {
-
- String semantic = parser.get_attribute_value("semantic");
- String source =_uri_to_id( parser.get_attribute_value("source") );
-
- int offset = parser.get_attribute_value("offset").to_int();
-
- SkinControllerData::Weights::SourceRef sref;
- sref.source=source;
- sref.offset=offset;
- weights.sources[semantic]=sref;
-
- COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source+" offset: "+itos(offset));
-
- } else if (parser.get_node_name()=="v") { //indices
-
- Vector<float> values = _read_float_array(parser);
- weights.indices=values;
- COLLADA_PRINT("read "+itos(values.size())+" index values");
-
- } else if (parser.get_node_name()=="vcount") { // weightsitive
-
- Vector<float> values = _read_float_array(parser);
- weights.sets=values;
- COLLADA_PRINT("read "+itos(values.size())+" polygon values");
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
- break;
-
- }
-
- skindata.weights=weights;
-
- }
- /*
- else if (!parser.is_empty())
- parser.skip_section();
- */
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="skin")
- break;
- }
-
- /* STORE REST MATRICES */
-
- Vector<Transform> rests;
- ERR_FAIL_COND(!skindata.joints.sources.has("JOINT"));
- ERR_FAIL_COND(!skindata.joints.sources.has("INV_BIND_MATRIX"));
-
- String joint_arr = skindata.joints.sources["JOINT"];
- String ibm = skindata.joints.sources["INV_BIND_MATRIX"];
-
- ERR_FAIL_COND(!skindata.sources.has(joint_arr));
- ERR_FAIL_COND(!skindata.sources.has(ibm));
-
- SkinControllerData::Source &joint_source = skindata.sources[joint_arr];
- SkinControllerData::Source &ibm_source = skindata.sources[ibm];
-
-
-
- ERR_FAIL_COND(joint_source.sarray.size() != ibm_source.array.size()/16);
-
- for(int i=0;i<joint_source.sarray.size();i++) {
-
- String name = joint_source.sarray[i];
- Transform xform = _read_transform_from_array(ibm_source.array,i*16); //<- this is a mistake, it must be applied to vertices
- xform.affine_invert(); // inverse for rest, because it's an inverse
-#ifdef COLLADA_IMPORT_SCALE_SCENE
- xform.origin*=state.unit_scale;
-#endif
- skindata.bone_rest_map[name]=xform;
- }
-
-
-}
-
-void Collada::_parse_morph_controller(XMLParser& parser, String p_id) {
-
- state.morph_controller_data_map[p_id]=MorphControllerData();
- MorphControllerData &morphdata = state.morph_controller_data_map[p_id];
-
- print_line("morph source: "+parser.get_attribute_value("source")+" id: "+p_id);
- morphdata.mesh=_uri_to_id(parser.get_attribute_value("source"));
- print_line("morph source2: "+morphdata.mesh);
- morphdata.mode=parser.get_attribute_value("method");
- printf("JJmorph: %p\n",&morphdata);
- String current_source;
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT){
-
- String section = parser.get_node_name();
-
- if (section == "source") {
-
- String id=parser.get_attribute_value("id");
- morphdata.sources[id]=MorphControllerData::Source();
- current_source=id;
- COLLADA_PRINT("source data: "+id);
-
- } else if (section=="float_array" || section=="array") {
- // create a new array and read it.
- if (morphdata.sources.has(current_source)) {
-
- morphdata.sources[current_source].array = _read_float_array(parser);
- COLLADA_PRINT("section: "+current_source+" read "+itos(morphdata.sources[current_source].array.size())+" values.");
- }
- } else if (section=="Name_array" || section=="IDREF_array") {
- // create a new array and read it.
-
- /*
- if (section=="IDREF_array")
- morphdata.use_idrefs=true;
- */
- if (morphdata.sources.has(current_source)) {
-
- morphdata.sources[current_source].sarray = _read_string_array(parser);
- /*
- if (section=="IDREF_array") {
- Vector<String> sa = morphdata.sources[current_source].sarray;
- for(int i=0;i<sa.size();i++)
- state.idref_joints.insert(sa[i]);
- }*/
- COLLADA_PRINT("section: "+current_source+" read "+itos(morphdata.sources[current_source].array.size())+" values.");
- }
- } else if (section == "technique_common") {
- //skip it
- } else if (section == "accessor") { // child of source (below a technique tag)
-
- if (morphdata.sources.has(current_source)) {
-
- int stride=1;
- if (parser.has_attribute("stride"))
- stride=parser.get_attribute_value("stride").to_int();
-
- morphdata.sources[current_source].stride=stride;
- COLLADA_PRINT("section: "+current_source+" stride "+itos(morphdata.sources[current_source].stride));
- }
-
- } else if (section == "targets") {
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="input") {
-
- String semantic = parser.get_attribute_value("semantic");
- String source =_uri_to_id( parser.get_attribute_value("source") );
-
- morphdata.targets[semantic]=source;
-
- COLLADA_PRINT(section+" input semantic: "+semantic+" source: "+source);
-
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==section)
- break;
- }
-
-
- }
- /*
- else if (!parser.is_empty())
- parser.skip_section();
- */
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="morph")
- break;
- }
-
-
- if (morphdata.targets.has("MORPH_WEIGHT")) {
-
- state.morph_name_map[ morphdata.targets["MORPH_WEIGHT"] ] = p_id;
- }
-
-}
-
-void Collada::_parse_controller(XMLParser& parser) {
-
- String id=parser.get_attribute_value("id");
-
- if (parser.is_empty()) {
- return;
- }
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT){
-
- String section = parser.get_node_name();
-
- if (section=="skin") {
- _parse_skin_controller(parser,id);
- } else if (section == "morph") {
- _parse_morph_controller(parser,id);
- }
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="controller")
- break;
- }
-
-
-}
-
-
-Collada::Node* Collada::_parse_visual_instance_geometry(XMLParser& parser) {
-
- String type = parser.get_node_name();
- NodeGeometry *geom=memnew( NodeGeometry );
- geom->controller=type=="instance_controller";
- geom->source = _uri_to_id(parser.get_attribute_value_safe("url"));
-
-
-
- if (parser.is_empty()) //nothing else to parse...
- return geom;
- // try to find also many materials and skeletons!
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="instance_material") {
-
- String symbol=parser.get_attribute_value("symbol");
- String target=_uri_to_id(parser.get_attribute_value("target"));
-
- NodeGeometry::Material mat;
- mat.target=target;
- geom->material_map[symbol]=mat;
- COLLADA_PRINT("uses material: '"+target+"' on primitive'"+symbol+"'");
- } else if (parser.get_node_name()=="skeleton") {
-
- parser.read();
- String uri = _uri_to_id(parser.get_node_data());
- if (uri!="") {
- geom->skeletons.push_back(uri);
- }
-
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==type)
- break;
-
-
- }
-
- if (geom->controller) {
-
- if (geom->skeletons.empty()) {
- //XSI style
-
- if (state.skin_controller_data_map.has(geom->source)) {
- SkinControllerData *skin = &state.skin_controller_data_map[geom->source];
- //case where skeletons reference bones with IDREF (XSI)
- ERR_FAIL_COND_V(!skin->joints.sources.has("JOINT"),geom);
- String joint_arr = skin->joints.sources["JOINT"];
- ERR_FAIL_COND_V(!skin->sources.has(joint_arr),geom);
- Collada::SkinControllerData::Source &joint_source = skin->sources[joint_arr];
- geom->skeletons=joint_source.sarray; //quite crazy, but should work.
- }
-
- }
-
- }
-
- return geom;
-}
-
-
-Collada::Node* Collada::_parse_visual_instance_camera(XMLParser& parser) {
-
- String type = parser.get_node_name();
- NodeCamera *cam=memnew( NodeCamera );
- cam->camera= _uri_to_id(parser.get_attribute_value_safe("url"));
-
- if (state.up_axis==Vector3::AXIS_Z) //collada weirdness
- cam->post_transform.basis.rotate(Vector3(1,0,0),-Math_PI*0.5);
-
- if (parser.is_empty()) //nothing else to parse...
- return cam;
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="instance_camera")
- break;
- }
-
- return cam;
-}
-
-Collada::Node* Collada::_parse_visual_instance_light(XMLParser& parser) {
-
- String type = parser.get_node_name();
- NodeLight *cam=memnew( NodeLight );
- cam->light= _uri_to_id(parser.get_attribute_value_safe("url"));
-
- if (state.up_axis==Vector3::AXIS_Z) //collada weirdness
- cam->post_transform.basis.rotate(Vector3(1,0,0),-Math_PI*0.5);
-
- if (parser.is_empty()) //nothing else to parse...
- return cam;
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="instance_light")
- break;
- }
-
- return cam;
-}
-
-
-Collada::Node* Collada::_parse_visual_node_instance_data(XMLParser& parser) {
-
- String instance_type = parser.get_node_name();
-
-
- if (instance_type=="instance_geometry" || instance_type=="instance_controller") {
- return _parse_visual_instance_geometry(parser);
- } else if (instance_type=="instance_camera") {
-
- return _parse_visual_instance_camera(parser);
- } else if (instance_type=="instance_light") {
- return _parse_visual_instance_light(parser);
- }
-
-
- if (parser.is_empty()) //nothing else to parse...
- return NULL;
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()==instance_type)
- break;
- }
-
- return NULL;
-}
-
-Collada::Node* Collada::_parse_visual_scene_node(XMLParser& parser) {
-
- String name;
-
- String id = parser.get_attribute_value_safe("id");
-
- bool found_name=false;
-
- if (id=="") {
-
- id="%NODEID%"+itos(Math::rand());
-
- } else {
- found_name=true;
- }
-
- Vector<Node::XForm> xform_list;
- Vector<Node*> children;
-
- String empty_draw_type="";
-
- Node *node=NULL;
-
- name=parser.has_attribute("name")?parser.get_attribute_value_safe("name"):parser.get_attribute_value_safe("id");
- if (name=="") {
-
- name=id;
- } else {
- found_name=true;
- }
-
- if ((parser.has_attribute("type") && parser.get_attribute_value("type")=="JOINT") || state.idref_joints.has(name)) {
- // handle a bone
-
- NodeJoint *joint = memnew( NodeJoint );
-
- 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)) {
- 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;
- }
-
- node=joint;
-
-
- }
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String section = parser.get_node_name();
-
- if (section=="translate") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id=parser.get_attribute_value("sid");
- }
- xf.op=Node::XForm::OP_TRANSLATE;
-
- Vector<float> xlt = _read_float_array(parser);
- xf.data=xlt;
- xform_list.push_back(xf);
-
- } else if (section=="rotate") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id=parser.get_attribute_value("sid");
- }
- xf.op=Node::XForm::OP_ROTATE;
-
- Vector<float> rot = _read_float_array(parser);
- xf.data=rot;
-
- xform_list.push_back(xf);
-
- } else if (section=="scale") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id=parser.get_attribute_value("sid");
- }
-
- xf.op=Node::XForm::OP_SCALE;
-
- Vector<float> scale = _read_float_array(parser);
-
- xf.data=scale;
-
- xform_list.push_back(xf);
-
- } else if (section=="matrix") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id=parser.get_attribute_value("sid");
- }
- xf.op=Node::XForm::OP_MATRIX;
-
- Vector<float> matrix = _read_float_array(parser);
-
- xf.data=matrix;
- String mtx;
- for(int i=0;i<matrix.size();i++)
- mtx+=" "+rtos(matrix[i]);
-
- xform_list.push_back(xf);
-
- } else if (section=="visibility") {
- Node::XForm xf;
- if (parser.has_attribute("sid")) {
- xf.id=parser.get_attribute_value("sid");
- }
- xf.op=Node::XForm::OP_VISIBILITY;
-
- Vector<float> visible = _read_float_array(parser);
-
- xf.data=visible;
-
- xform_list.push_back(xf);
-
- } else if (section=="empty_draw_type") {
- empty_draw_type = _read_empty_draw_type(parser);
- } else if (section == "technique" || section=="extra") {
-
- } else if (section!="node") {
- //usually what defines the type of node
- //print_line(" dont know what to do with "+section);
- if (section.begins_with("instance_")) {
-
- if (!node) {
-
- node = _parse_visual_node_instance_data(parser);
-
- } else {
- ERR_PRINT("Multiple instance_* not supported.");
- }
-
- }
-
- } else if (section=="node") {
-
- /* Found a child node!! what to do..*/
-
- Node *child = _parse_visual_scene_node(parser);
- children.push_back(child);
-
-
-
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="node")
- break;
- }
-
- if (!node) {
-
- node = memnew( Node ); //generic node, nothing of relevance found
- }
-
- node->noname=!found_name;
- node->xform_list=xform_list;
- node->children=children;
- for(int i=0;i<children.size();i++) {
- node->children[i]->parent=node;
- }
-
- node->name=name;
- node->id=id;
- node->empty_draw_type=empty_draw_type;
-
- if (node->children.size()==1) {
- if (node->children[0]->noname && !node->noname) {
- node->children[0]->name=node->name;
- node->name=node->name+"-base";
- }
- }
-
-
-
- node->default_transform = node->compute_transform(*this);
- state.scene_map[id]=node;
-
-
- return node;
-}
-
-void Collada::_parse_visual_scene(XMLParser& parser) {
-
- String id=parser.get_attribute_value("id");
-
- if (parser.is_empty()) {
- return;
- }
-
- state.visual_scene_map[id]=VisualScene();
- VisualScene &vscene = state.visual_scene_map[id];
-
- if (parser.has_attribute("name"))
- vscene.name=parser.get_attribute_value("name");
-
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String section = parser.get_node_name();
-
- if (section=="node") {
- vscene.root_nodes.push_back(_parse_visual_scene_node(parser));
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="visual_scene")
- break;
- }
-
-
- COLLADA_PRINT("Scene ID:"+id);
-
-
-}
-
-void Collada::_parse_animation(XMLParser& parser) {
-
- if (!(state.import_flags&IMPORT_FLAG_ANIMATION)) {
- if (!parser.is_empty())
- parser.skip_section();
-
-
- return;
- }
-
- Map<String,Vector<float> > float_sources;
- Map<String,Vector<String> > string_sources;
- Map<String,int > source_strides;
- Map<String, Map<String,String> > samplers;
- Map<String,Vector<String> > source_param_names;
- Map<String,Vector<String> > source_param_types;
-
- String id="";
- if (parser.has_attribute("id"))
- id=parser.get_attribute_value("id");
-
- String current_source;
- String current_sampler;
- Vector<String> channel_sources;
- Vector<String> channel_targets;
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
- if (name=="source") {
-
- current_source=parser.get_attribute_value("id");
- source_param_names[current_source]=Vector<String>();
- source_param_types[current_source]=Vector<String>();
-
- } else if (name=="float_array") {
-
- if (current_source!="") {
- float_sources[current_source]=_read_float_array(parser);
- }
-
- } else if (name=="Name_array") {
-
- if (current_source!="") {
- string_sources[current_source]=_read_string_array(parser);
- }
- } else if (name=="accessor") {
-
- if (current_source!="" && parser.has_attribute("stride")) {
- source_strides[current_source]=parser.get_attribute_value("stride").to_int();
- }
- } else if (name=="sampler") {
-
- current_sampler=parser.get_attribute_value("id");
- samplers[current_sampler]=Map<String,String>();
- } else if (name=="param") {
-
- if (parser.has_attribute("name"))
- source_param_names[current_source].push_back(parser.get_attribute_value("name"));
- else
- source_param_names[current_source].push_back("");
-
- if (parser.has_attribute("type"))
- source_param_types[current_source].push_back(parser.get_attribute_value("type"));
- else
- source_param_types[current_source].push_back("");
-
- } else if (name=="input") {
-
- if (current_sampler!="") {
-
- samplers[current_sampler][parser.get_attribute_value("semantic")]=parser.get_attribute_value("source");
- }
-
- } else if (name=="channel") {
-
- channel_sources.push_back(parser.get_attribute_value("source"));
- channel_targets.push_back(parser.get_attribute_value("target"));
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="animation")
- break; //end of <asset>
-
-
- }
-
-
- for(int i=0;i<channel_sources.size();i++) {
-
- String source=_uri_to_id(channel_sources[i]);
- String target=channel_targets[i];
- if (!samplers.has(source)) {
- print_line("channel lacks source: "+source);
- }
- ERR_CONTINUE(!samplers.has(source));
- Map<String,String>& sampler=samplers[source];
-
- ERR_CONTINUE(!sampler.has("INPUT")); //no input semantic? wtf?
- String input_id=_uri_to_id(sampler["INPUT"]);
- COLLADA_PRINT("input id is "+input_id);
- ERR_CONTINUE(!float_sources.has(input_id));
-
- ERR_CONTINUE(!sampler.has("OUTPUT"));
- String output_id=_uri_to_id(sampler["OUTPUT"]);
- ERR_CONTINUE(!float_sources.has(output_id));
-
- ERR_CONTINUE(!source_param_names.has(output_id));
-
- Vector<String> &names = source_param_names[output_id];
-
- for(int l=0;l<names.size();l++) {
-
- String name = names[l];
-
- Vector<float> &time_keys=float_sources[input_id];
- int key_count = time_keys.size();
-
- AnimationTrack track; //begin crating track
- track.id=id;
-
- track.keys.resize(key_count);
-
- for(int j=0;j<key_count;j++) {
- track.keys[j].time=time_keys[j];
- state.animation_length = MAX(state.animation_length,time_keys[j] );
- }
-
- //now read actual values
-
- int stride=1;
-
- if (source_strides.has(output_id))
- stride=source_strides[output_id];
- int output_len=stride / names.size();
-
- ERR_CONTINUE(output_len==0);
- ERR_CONTINUE(!float_sources.has(output_id));
-
- Vector<float> &output = float_sources[output_id];
-
- ERR_EXPLAIN("Wrong number of keys in output");
- ERR_CONTINUE( (output.size()/stride) != key_count );
-
- for(int j=0;j<key_count;j++) {
- track.keys[j].data.resize(output_len);
- for(int k=0;k<output_len;k++)
- track.keys[j].data[k]=output[l+j*stride+k]; //super weird but should work
- }
-
- if(sampler.has("INTERPOLATION")) {
-
- String interp_id=_uri_to_id(sampler["INTERPOLATION"]);
- ERR_CONTINUE(!string_sources.has(interp_id));
- Vector<String> &interps=string_sources[interp_id];
- ERR_CONTINUE(interps.size()!=key_count);
-
- for(int j=0;j<key_count;j++) {
- if (interps[j]=="BEZIER")
- track.keys[j].interp_type=AnimationTrack::INTERP_BEZIER;
- else
- track.keys[j].interp_type=AnimationTrack::INTERP_LINEAR;
- }
- }
-
- if (sampler.has("IN_TANGENT") && sampler.has("OUT_TANGENT")) {
- //bezier control points..
- String intangent_id=_uri_to_id(sampler["IN_TANGENT"]);
- ERR_CONTINUE(!float_sources.has(intangent_id));
- Vector<float> &intangents=float_sources[intangent_id];
-
-
-
-
- ERR_CONTINUE(intangents.size()!=key_count*2*names.size());
-
- String outangent_id=_uri_to_id(sampler["OUT_TANGENT"]);
- ERR_CONTINUE(!float_sources.has(outangent_id));
- Vector<float> &outangents=float_sources[outangent_id];
- ERR_CONTINUE(outangents.size()!=key_count*2*names.size());
-
- for(int j=0;j<key_count;j++) {
- track.keys[j].in_tangent=Vector2( intangents[j*2*names.size()+0+l*2],intangents[j*2*names.size()+1+l*2] );
- track.keys[j].out_tangent=Vector2( outangents[j*2*names.size()+0+l*2],outangents[j*2*names.size()+1+l*2] );
- }
- }
-
- if (target.find("/")!=-1) { //transform component
- track.target=target.get_slicec('/',0);
- track.param=target.get_slicec('/',1);
- if (track.param.find(".")!=-1)
- track.component=track.param.get_slice(".",1).to_upper();
- track.param=track.param.get_slice(".",0);
- if (names.size()>1 && track.component=="") {
- //this is a guess because the collada spec is ambiguous here...
- //i suppose if you have many names (outputs) you can't use a component and i should abide to that.
- track.component=name;
-
- }
- } else {
- track.target=target;
- }
-
- print_line("TARGET: "+track.target);
-
- state.animation_tracks.push_back(track);
-
- if (!state.referenced_tracks.has(target))
- state.referenced_tracks[target]=Vector<int>();
-
- state.referenced_tracks[target].push_back(state.animation_tracks.size()-1);
-
- if (id!="") {
- if (!state.by_id_tracks.has(id))
- state.by_id_tracks[id]=Vector<int>();
-
- state.by_id_tracks[id].push_back(state.animation_tracks.size()-1);
- }
-
- COLLADA_PRINT("loaded animation with "+itos(key_count)+" keys");
- }
-
- }
-}
-
-void Collada::_parse_animation_clip(XMLParser& parser) {
-
- if (!(state.import_flags&IMPORT_FLAG_ANIMATION)) {
- if (!parser.is_empty())
- parser.skip_section();
-
-
- return;
- }
-
-
- AnimationClip clip;
-
- if (parser.has_attribute("name"))
- clip.name=parser.get_attribute_value("name");
- else if (parser.has_attribute("id"))
- clip.name=parser.get_attribute_value("id");
- if (parser.has_attribute("start"))
- clip.begin=parser.get_attribute_value("start").to_double();
- if (parser.has_attribute("end"))
- clip.end=parser.get_attribute_value("end").to_double();
-
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
- if (name=="instance_animation") {
-
- String url = _uri_to_id(parser.get_attribute_value("url"));
- clip.tracks.push_back(url);
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="animation_clip")
- break; //end of <asset>
-
- }
-
- state.animation_clips.push_back(clip);
- print_line("found anim clip: "+clip.name);
-
-}
-void Collada::_parse_scene(XMLParser& parser) {
-
- if (parser.is_empty()) {
- return;
- }
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
-
- if (name=="instance_visual_scene") {
-
- state.root_visual_scene=_uri_to_id(parser.get_attribute_value("url"));
- print_line("***ROOT VISUAL SCENE: "+state.root_visual_scene);
- } if (name=="instance_physics_scene") {
-
- state.root_physics_scene=_uri_to_id(parser.get_attribute_value("url"));
-
- }
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="scene")
- break; //end of <asset>
- }
-}
-
-void Collada::_parse_library(XMLParser& parser) {
-
-
- if (parser.is_empty()) {
- return;
- }
-
- while(parser.read()==OK) {
-
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser.get_node_name();
- COLLADA_PRINT("library name is: "+name);
- if (name=="image") {
-
- _parse_image(parser);
- } else if (name=="material") {
-
- _parse_material(parser);
- } else if (name=="effect") {
-
- _parse_effect(parser);
- } else if (name=="camera") {
-
- _parse_camera(parser);
- } else if (name=="light") {
-
- _parse_light(parser);
- } else if (name=="geometry") {
-
- String id = parser.get_attribute_value("id");
- String name = parser.get_attribute_value_safe("name");
- while(parser.read()==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name()=="mesh") {
- state.mesh_name_map[id]=(name!="")?name:id;
- _parse_mesh_geometry(parser,id,name);
- } else if (parser.get_node_name()=="spline") {
- state.mesh_name_map[id]=(name!="")?name:id;
- _parse_curve_geometry(parser,id,name);
- } else if (!parser.is_empty())
- parser.skip_section();
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name()=="geometry")
- break;
- }
-
- } else if (name=="controller") {
-
- _parse_controller(parser);
- } else if (name=="animation") {
-
- _parse_animation(parser);
- } else if (name=="animation_clip") {
-
- _parse_animation_clip(parser);
- } else if (name=="visual_scene") {
-
- COLLADA_PRINT("visual scene");
- _parse_visual_scene(parser);
- } else if (!parser.is_empty())
- parser.skip_section();
-
- } else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name().begins_with("library_"))
- break; //end of <asset>
-
-
- }
-
-}
-
-void Collada::_joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner) {
-
- if (p_node->type==Node::TYPE_JOINT) {
-
- NodeJoint *nj = static_cast<NodeJoint*>(p_node);
- nj->owner=p_owner;
-
- for(int i=0;i<nj->children.size();i++) {
-
- _joint_set_owner(nj->children[i],p_owner);
- }
- }
-}
-
-void Collada::_create_skeletons(Collada::Node **p_node,NodeSkeleton *p_skeleton) {
-
-
- Node *node = *p_node;
-
- if (node->type==Node::TYPE_JOINT) {
-
- if (!p_skeleton) {
-
- // ohohohoohoo it's a joint node, time to work!
- NodeSkeleton *sk = memnew( NodeSkeleton );
- *p_node=sk;
- sk->children.push_back(node);
- sk->parent=node->parent;
- node->parent=sk;
- p_skeleton=sk;
- }
-
- NodeJoint *nj = static_cast<NodeJoint*>(node);
- nj->owner=p_skeleton;
- } else {
- p_skeleton=NULL;
- }
-
-
- for(int i=0;i<node->children.size();i++) {
- _create_skeletons(&node->children[i],p_skeleton);
- }
-
-}
-
-bool Collada::_remove_node(Node *p_parent,Node *p_node) {
-
- for(int i=0;i<p_parent->children.size();i++) {
-
- if (p_parent->children[i]==p_node) {
- p_parent->children.remove(i);
- return true;
- }
- if (_remove_node(p_parent->children[i],p_node))
- return true;
- }
-
- return false;
-}
-
-void Collada::_remove_node(VisualScene *p_vscene,Node *p_node) {
-
- for(int i=0;i<p_vscene->root_nodes.size();i++) {
- if (p_vscene->root_nodes[i]==p_node) {
-
- p_vscene->root_nodes.remove(i);
- return;
- }
- if (_remove_node(p_vscene->root_nodes[i],p_node))
- return;
- }
-
- ERR_PRINT("ERROR: Not found node to remove?");
-
-}
-
-
-void Collada::_merge_skeletons(VisualScene *p_vscene,Node *p_node) {
-
- if (p_node->type==Node::TYPE_GEOMETRY) {
-
- NodeGeometry *gnode = static_cast<NodeGeometry*>(p_node);
- if (gnode->controller) {
-
- // recount skeletons used
- Set<NodeSkeleton*> skeletons;
-
- for(int i=0;i<gnode->skeletons.size();i++) {
-
- String nodeid = gnode->skeletons[i];
-
- ERR_CONTINUE( !state.scene_map.has( nodeid )); //weird, it should have it...
-
-
- NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
- if (!nj->owner) {
- print_line("no owner for: "+String(nodeid));
- }
- ERR_CONTINUE( !nj->owner ); //weird, node should have a skeleton owner
-
- skeletons.insert(nj->owner);
- }
-
- if (skeletons.size()>1) {
-
- //do the merger!!
- Set<NodeSkeleton*>::Element *E=skeletons.front();
- NodeSkeleton *base = E->get();
-
- for(E=E->next();E;E=E->next() ) {
-
- NodeSkeleton *merged = E->get();
- _remove_node(p_vscene,merged);
- for(int i=0;i<merged->children.size();i++) {
-
- _joint_set_owner(merged->children[i],base);
- base->children.push_back( merged->children[i] );
- merged->children[i]->parent=base;
-
-
- }
-
- merged->children.clear(); //take children from it
- memdelete( merged );
- }
-
- }
- }
- }
-
- for(int i=0;i<p_node->children.size();i++) {
- _merge_skeletons(p_vscene,p_node->children[i]);
- }
-
-}
-
-
-void Collada::_merge_skeletons2(VisualScene *p_vscene) {
-
- for (Map<String,SkinControllerData>::Element *E=state.skin_controller_data_map.front();E;E=E->next()) {
-
- SkinControllerData &cd=E->get();
-
- NodeSkeleton *skeleton=NULL;
-
- for (Map<String,Transform>::Element *F=cd.bone_rest_map.front();F;F=F->next()) {
-
- String name;
-
- if (!state.sid_to_node_map.has(F->key())) {
- continue;
- }
-
- name = state.sid_to_node_map[F->key()];
-
- if (!state.scene_map.has(name)) {
- print_line("no foundie node for: "+name);
- }
-
- ERR_CONTINUE( !state.scene_map.has(name) );
-
- Node *node=state.scene_map[name];
- ERR_CONTINUE( node->type!=Node::TYPE_JOINT );
- if (node->type!=Node::TYPE_JOINT)
- continue;
- NodeSkeleton *sk=NULL;
-
- while(node && !sk) {
-
- if (node->type==Node::TYPE_SKELETON) {
- sk=static_cast<NodeSkeleton*>(node);
- }
- node=node->parent;
- }
- ERR_CONTINUE( !sk );
-
- if (!sk)
- continue; //bleh
-
- if (!skeleton) {
- skeleton=sk;
- continue;
- }
-
- if (skeleton!=sk) {
- //whoa.. wtf, merge.
- print_line("MERGED BONES!!");
-
- //NodeSkeleton *merged = E->get();
- _remove_node(p_vscene,sk);
- for(int i=0;i<sk->children.size();i++) {
-
- _joint_set_owner(sk->children[i],skeleton);
- skeleton->children.push_back( sk->children[i] );
- sk->children[i]->parent=skeleton;
-
-
- }
-
- sk->children.clear(); //take children from it
- memdelete( sk );
- }
- }
- }
-
-
-
-}
-
-bool Collada::_optimize_skeletons(VisualScene *p_vscene,Node *p_node) {
-
- Node *node=p_node;
-
- if (node->type==Node::TYPE_SKELETON && node->parent && node->parent->type==Node::TYPE_NODE && node->parent->children.size()==1) {
- //replace parent by this...
- Node *parent = node->parent;
-
- //i wonder if this is allright.. i think it is since created skeleton (first joint) is already animated by bone..
- node->id=parent->id;
- node->name=parent->name;
- node->xform_list=parent->xform_list;
- node->default_transform=parent->default_transform;
-
- state.scene_map[node->id]=node;
- node->parent=parent->parent;
-
- if (parent->parent) {
- Node *gp = parent->parent;
- bool found=false;
- for(int i=0;i<gp->children.size();i++) {
-
- if (gp->children[i]==parent) {
- gp->children[i]=node;
- found=true;
- break;
- }
- }
- if (!found) {
- ERR_PRINT("BUG");
- }
- } else {
-
- bool found=false;
-
- for(int i=0;i<p_vscene->root_nodes.size();i++) {
-
- if (p_vscene->root_nodes[i]==parent) {
-
- p_vscene->root_nodes[i]=node;
- found=true;
- break;
- }
- }
- if (!found) {
- ERR_PRINT("BUG");
- }
-
- }
-
- parent->children.clear();
- memdelete(parent);
- return true;
- }
-
- for(int i=0;i<node->children.size();i++) {
-
- if (_optimize_skeletons(p_vscene,node->children[i]))
- return false; //stop processing, go up
- }
-
- return false;
-
-}
-
-
-bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene,Node *p_node,List<Node*> *p_mgeom) {
-
- // bind shape matrix escala los huesos y los hace gigantes, asi la matriz despues achica
- // al modelo?
- // solucion: aplicarle la bind shape matrix a los VERTICES, y si el objeto viene con escala, se la dejo me parece!
-
- if (p_node->type==Node::TYPE_GEOMETRY) {
-
- NodeGeometry *ng = static_cast<NodeGeometry*>(p_node);
- if (ng->ignore_anim)
- return false; //already made child of skeleton and processeg
-
- if (ng->controller && ng->skeletons.size()) {
-
- String nodeid = ng->skeletons[0];
-
- ERR_FAIL_COND_V( !state.scene_map.has( nodeid ), false); //weird, it should have it...
- NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
- ERR_FAIL_COND_V(!nj,false);
- if (!nj->owner) {
- print_line("Has no owner: "+nj->name);
- }
- ERR_FAIL_COND_V( !nj->owner,false ); //weird, node should have a skeleton owner
-
- NodeSkeleton *sk = nj->owner;
-
- Node *p =sk->parent;
- bool node_is_parent_of_skeleton=false;
-
- while (p) {
- if (p==p_node) {
- node_is_parent_of_skeleton=true;
- break;
- }
- p=p->parent; // try again
- }
-
- ERR_FAIL_COND_V( node_is_parent_of_skeleton, false);
-
- //this should be correct
- ERR_FAIL_COND_V( !state.skin_controller_data_map.has(ng->source), false);
- SkinControllerData &skin=state.skin_controller_data_map[ng->source];
- Transform skel_inv = sk->get_global_transform().affine_inverse();
- p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it
-
- //make rests relative to the skeleton (they seem to be always relative to world)
- for(Map<String,Transform>::Element *E=skin.bone_rest_map.front();E;E=E->next()) {
-
- E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton
- state.bone_rest_map[E->key()]=E->get(); // make it remember where the bone is globally, now that it's relative
- }
-
- //but most exporters seem to work only if i do this..
- //p_node->default_transform = p_node->get_global_transform();
-
-
-
- //p_node->default_transform=Transform(); //this seems to be correct, because bind shape makes the object local to the skeleton
- p_node->ignore_anim=true; // collada may animate this later, if it does, then this is not supported (redo your original asset and don't animate the base mesh)
- p_node->parent=sk;
- //sk->children.push_back(0,p_node); //avoid INFINIT loop
- p_mgeom->push_back(p_node);
- return true;
- }
- }
-
- for(int i=0;i<p_node->children.size();i++) {
-
- if (_move_geometry_to_skeletons(p_vscene,p_node->children[i],p_mgeom)) {
- p_node->children.remove(i);
- i--;
- }
- }
-
- return false;
-}
-
-void Collada::_find_morph_nodes(VisualScene *p_vscene,Node *p_node) {
-
- if (p_node->type==Node::TYPE_GEOMETRY) {
-
- NodeGeometry *nj = static_cast<NodeGeometry*>(p_node);
-
- if (nj->controller) {
-
- String base = nj->source;
-
- while(base!="" && !state.mesh_data_map.has(base)) {
-
- if (state.skin_controller_data_map.has(base)) {
-
- SkinControllerData &sk = state.skin_controller_data_map[base];
- base=sk.base;
- } else if (state.morph_controller_data_map.has(base)) {
-
- state.morph_ownership_map[base]=nj->id;
- break;
- } else {
- ERR_EXPLAIN("Invalid scene");
- ERR_FAIL();
- }
- }
-
- }
- }
-
- for(int i=0;i<p_node->children.size();i++) {
-
- _find_morph_nodes(p_vscene,p_node->children[i]);
- }
-
-}
-
-void Collada::_optimize() {
-
-
- for(Map<String,VisualScene>::Element *E=state.visual_scene_map.front();E;E=E->next()) {
-
- VisualScene &vs = E->get();
- for(int i=0;i<vs.root_nodes.size();i++) {
- _create_skeletons(&vs.root_nodes[i]);
-
- }
-#if 1
- for(int i=0;i<vs.root_nodes.size();i++) {
- _merge_skeletons(&vs,vs.root_nodes[i]);
- }
-
- _merge_skeletons2(&vs);
-
-
- for(int i=0;i<vs.root_nodes.size();i++) {
- _optimize_skeletons(&vs,vs.root_nodes[i]);
- }
-
- for(int i=0;i<vs.root_nodes.size();i++) {
-
- List<Node*> mgeom;
- if (_move_geometry_to_skeletons(&vs,vs.root_nodes[i],&mgeom)) {
- vs.root_nodes.remove(i);
- i--;
- }
-
- while(!mgeom.empty()) {
-
- Node * n= mgeom.front()->get();
- n->parent->children.push_back(n);
- mgeom.pop_front();
- }
-
- }
-#endif
- for(int i=0;i<vs.root_nodes.size();i++) {
- _find_morph_nodes(&vs,vs.root_nodes[i]);
- }
-
- }
-}
-
-
-int Collada::get_uv_channel(String p_name) {
-
- if (!channel_map.has(p_name)) {
-
- ERR_FAIL_COND_V(channel_map.size()==2,0);
-
- channel_map[p_name]=channel_map.size();
- }
-
- return channel_map[p_name];
-}
-
-Error Collada::load(const String& p_path, int p_flags) {
-
- Ref<XMLParser> parserr = memnew( XMLParser );
- XMLParser &parser = *parserr.ptr();
- Error err = parser.open(p_path);
- ERR_FAIL_COND_V(err,err);
-
- state.local_path = GlobalConfig::get_singleton()->localize_path(p_path);
- state.import_flags=p_flags;
- /* Skip headers */
- err=OK;
- while((err=parser.read())==OK) {
-
- if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser.get_node_name() == "COLLADA") {
- break;
- } else if (!parser.is_empty())
- parser.skip_section();// unknown section, likely headers
- }
- }
-
- ERR_FAIL_COND_V(err!=OK, ERR_FILE_CORRUPT);
-
- /* Start loading Collada */
-
- {
- //version
- String version = parser.get_attribute_value("version");
- state.version.major=version.get_slice(".",0).to_int();
- state.version.minor=version.get_slice(".",1).to_int();
- state.version.rev=version.get_slice(".",2).to_int();
- COLLADA_PRINT("Collada VERSION: "+version);
- }
-
-
-
- while((err=parser.read())==OK) {
-
- /* Read all the main sections.. */
-
- if (parser.get_node_type() != XMLParser::NODE_ELEMENT)
- continue; //no idea what this may be, but skipping anyway
-
- String section = parser.get_node_name();
-
- COLLADA_PRINT("section: "+section);
-
- if (section=="asset") {
- _parse_asset(parser);
-
- } else if (section.begins_with("library_")) {
-
- _parse_library(parser);
- } else if (section=="scene") {
-
- _parse_scene(parser);
- } else if (!parser.is_empty()) {
- parser.skip_section(); // unknown section, likely headers
- }
-
- }
-
- _optimize();
- return OK;
-}
-
-
-
-
-Collada::Collada() {
-
-
-}
-
-#endif
diff --git a/tools/editor/collada/collada.h b/tools/editor/collada/collada.h
deleted file mode 100644
index fd7ad4920d..0000000000
--- a/tools/editor/collada/collada.h
+++ /dev/null
@@ -1,663 +0,0 @@
-/*************************************************************************/
-/* collada.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifdef TOOLS_ENABLED
-
-#ifndef COLLADA_H
-#define COLLADA_H
-
-
-#include "scene/resources/material.h"
-#include "globals.h"
-#include "io/xml_parser.h"
-#include "map.h"
-
-class Collada {
-public:
-
- enum ImportFlags {
- IMPORT_FLAG_SCENE=1,
- IMPORT_FLAG_ANIMATION=2
- };
-
-
- struct Image {
-
- String path;
- };
-
- struct Material {
-
- String name;
- String instance_effect;
- };
-
-
- struct Effect {
-
- String name;
- Map<String, Variant> params;
-
- struct Channel {
-
- int uv_idx;
- String texture;
- Color color;
- Channel() { uv_idx=0; }
- };
-
- Channel diffuse,specular,emission,bump;
- float shininess;
- bool found_double_sided;
- bool double_sided;
- bool unshaded;
-
- String get_texture_path(const String& p_source,Collada& state) const;
-
- Effect() {
- diffuse.color=Color(1,1,1,1);
- double_sided=true;
- found_double_sided=false;
- shininess=40;
- unshaded=false;
- }
- };
-
- struct CameraData {
-
- enum Mode {
- MODE_PERSPECTIVE,
- MODE_ORTHOGONAL
- };
-
- Mode mode;
-
- union {
- struct {
- float x_fov;
- float y_fov;
- } perspective;
- struct {
- float x_mag;
- float y_mag;
- } orthogonal;
- };
-
- float aspect;
- float z_near;
- float z_far;
-
- CameraData() {
-
- mode=MODE_PERSPECTIVE;
- perspective.y_fov=0;
- perspective.x_fov=0;
- aspect=1;
- z_near=0.1;
- z_far=100;
- }
- };
-
- struct LightData {
-
- enum Mode {
- MODE_AMBIENT,
- MODE_DIRECTIONAL,
- MODE_OMNI,
- MODE_SPOT
- };
-
- Mode mode;
-
- Color color;
-
- float constant_att;
- float linear_att;
- float quad_att;
-
- float spot_angle;
- float spot_exp;
-
- LightData() {
-
- mode=MODE_AMBIENT;
- color=Color(1,1,1,1);
- constant_att=0;
- linear_att=0;
- quad_att=0;
-
- spot_angle=45;
- spot_exp=1;
- }
- };
-
-
- struct MeshData {
-
-
- String name;
- struct Source {
-
- Vector<float> array;
- int stride;
-
- };
-
- Map<String,Source> sources;
-
- struct Vertices {
-
- Map<String,String> sources;
- };
-
- Map<String,Vertices> vertices;
-
- struct Primitives {
-
- struct SourceRef {
-
- String source;
- int offset;
-
-
- };
-
- String material;
- Map<String,SourceRef> sources;
- Vector<float> polygons;
- Vector<float> indices;
- int count;
- int vertex_size;
- };
-
- Vector<Primitives> primitives;
-
- bool found_double_sided;
- bool double_sided;
-
- MeshData() { found_double_sided=false; double_sided=true; }
- };
-
- struct CurveData {
-
-
- String name;
- bool closed;
-
- struct Source {
-
- Vector<String> sarray;
- Vector<float> array;
- int stride;
- };
-
- Map<String,Source> sources;
-
-
- Map<String,String> control_vertices;
-
- CurveData() {
-
- closed=false;
- }
-
- };
- struct SkinControllerData {
-
- String base;
- bool use_idrefs;
-
- Transform bind_shape;
-
- struct Source {
-
- Vector<String> sarray; //maybe for names
- Vector<float> array;
- int stride;
- Source() {
- stride=1;
- }
- };
-
- Map<String,Source> sources;
-
- struct Joints {
-
- Map<String,String> sources;
- } joints;
-
- struct Weights {
-
- struct SourceRef {
-
- String source;
- int offset;
-
-
- };
-
- String material;
- Map<String,SourceRef> sources;
- Vector<float> sets;
- Vector<float> indices;
- int count;
- } weights;
-
- Map<String,Transform> bone_rest_map;
-
- SkinControllerData() { use_idrefs=false; }
- };
-
-
- struct MorphControllerData {
-
- String mesh;
- String mode;
-
- struct Source {
-
- int stride;
- Vector<String> sarray; //maybe for names
- Vector<float> array;
- Source() { stride=1; }
- };
-
- Map<String,Source> sources;
-
- Map<String,String> targets;
- MorphControllerData() { }
- };
-
-
- struct Vertex {
-
- int idx;
- Vector3 vertex;
- Vector3 normal;
- Vector3 uv;
- Vector3 uv2;
- Plane tangent;
- Color color;
- int uid;
- struct Weight {
- int bone_idx;
- float weight;
- bool operator<(const Weight w) const { return weight>w.weight; } //heaviest first
-
- };
-
- Vector<Weight> weights;
-
- void fix_weights() {
-
- weights.sort();
- if (weights.size()>4) {
- //cap to 4 and make weights add up 1
- weights.resize(4);
- float total=0;
- for(int i=0;i<4;i++)
- total+=weights[i].weight;
- if (total)
- for(int i=0;i<4;i++)
- weights[i].weight/=total;
-
- }
- }
-
- void fix_unit_scale(Collada &state);
-
- bool operator<(const Vertex& p_vert) const {
-
- if (uid==p_vert.uid) {
- if (vertex==p_vert.vertex) {
- if(normal==p_vert.normal) {
- if(uv==p_vert.uv) {
- if(uv2==p_vert.uv2) {
-
- if (!weights.empty() || !p_vert.weights.empty()) {
-
- if (weights.size()==p_vert.weights.size()) {
-
- for(int i=0;i<weights.size();i++) {
- if (weights[i].bone_idx!=p_vert.weights[i].bone_idx)
- return weights[i].bone_idx<p_vert.weights[i].bone_idx;
-
- if (weights[i].weight!=p_vert.weights[i].weight)
- return weights[i].weight<p_vert.weights[i].weight;
- }
- } else {
- return weights.size() < p_vert.weights.size();
- }
-
- }
-
- return (color<p_vert.color);
- } else
- return (uv2<p_vert.uv2);
- } else
- return (uv<p_vert.uv);
- } else
- return (normal<p_vert.normal);
- } else
- return vertex<p_vert.vertex;
- } else
- return uid < p_vert.uid;
-
- }
-
- Vertex() { uid=0; idx=0; }
- };
- struct Node {
-
- enum Type {
-
- TYPE_NODE,
- TYPE_JOINT,
- TYPE_SKELETON, //this bone is not collada, it's added afterwards as optimization
- TYPE_LIGHT,
- TYPE_CAMERA,
- TYPE_GEOMETRY
- };
-
-
- struct XForm {
-
- enum Op {
- OP_ROTATE,
- OP_SCALE,
- OP_TRANSLATE,
- OP_MATRIX,
- OP_VISIBILITY
- };
-
- String id;
- Op op;
- Vector<float> data;
- };
-
- Type type;
-
- String name;
- String id;
- String empty_draw_type;
- bool noname;
- Vector<XForm> xform_list;
- Transform default_transform;
- Transform post_transform;
- Vector<Node*> children;
-
- Node* parent;
-
- Transform compute_transform(Collada &state) const;
- Transform get_global_transform() const;
- Transform get_transform() const;
-
- bool ignore_anim;
-
-
- Node() {noname=false; type=TYPE_NODE; parent=NULL; ignore_anim=false; }
- virtual ~Node() { for(int i=0;i<children.size();i++) memdelete( children[i] ); };
-
- };
-
- struct NodeSkeleton : public Node {
-
-
- NodeSkeleton() { type=TYPE_SKELETON; }
- };
-
- struct NodeJoint : public Node {
-
- NodeSkeleton *owner;
- String sid;
- NodeJoint() { type=TYPE_JOINT; owner=NULL; }
- };
-
-
- struct NodeGeometry : public Node {
-
- bool controller;
- String source;
-
- struct Material {
- String target;
- };
-
- Map<String,Material> material_map;
- Vector<String> skeletons;
-
- NodeGeometry() { type=TYPE_GEOMETRY; }
- };
-
- struct NodeCamera : public Node {
-
- String camera;
-
- NodeCamera() { type=TYPE_CAMERA; }
- };
-
- struct NodeLight : public Node {
-
- String light;
-
- NodeLight() { type=TYPE_LIGHT; }
- };
-
-
- struct VisualScene {
-
- String name;
- Vector<Node*> root_nodes;
-
- ~VisualScene() { for(int i=0;i<root_nodes.size();i++) memdelete( root_nodes[i] ); }
- };
-
-
- struct AnimationClip {
-
- String name;
- float begin;
- float end;
- Vector<String> tracks;
-
- AnimationClip() { begin=0; end=1; }
- };
-
- struct AnimationTrack {
-
- String id;
- String target;
- String param;
- String component;
- bool property;
-
- enum InterpolationType {
- INTERP_LINEAR,
- INTERP_BEZIER
- };
-
- struct Key {
-
- enum Type {
- TYPE_FLOAT,
- TYPE_MATRIX
- };
-
- float time;
- Vector<float> data;
- Point2 in_tangent;
- Point2 out_tangent;
- InterpolationType interp_type;
-
- Key() { interp_type=INTERP_LINEAR; }
- };
-
-
- Vector<float> get_value_at_time(float p_time);
-
- Vector<Key> keys;
-
- AnimationTrack() { property=false; }
- };
-
-
- /****************/
- /* IMPORT STATE */
- /****************/
-
-
- struct State {
-
-
- int import_flags;
-
- float unit_scale;
- Vector3::Axis up_axis;
- bool z_up;
-
- struct Version {
-
- int major,minor,rev;
-
- bool operator<(const Version& p_ver) const { return (major==p_ver.major)?((minor==p_ver.minor)?(rev<p_ver.rev):minor<p_ver.minor):major<p_ver.major; }
- Version(int p_major=0,int p_minor=0,int p_rev=0) { major=p_major; minor=p_minor; rev=p_rev; }
- } version;
-
-
- Map<String,CameraData> camera_data_map;
- Map<String,MeshData> mesh_data_map;
- Map<String,LightData> light_data_map;
- Map<String,CurveData> curve_data_map;
-
-
- Map<String,String> mesh_name_map;
- Map<String,String> morph_name_map;
- Map<String,String> morph_ownership_map;
- Map<String,SkinControllerData> skin_controller_data_map;
- Map<String,MorphControllerData> morph_controller_data_map;
-
-
-
- Map<String,Image > image_map;
- Map<String,Material> material_map;
- Map<String,Effect> effect_map;
-
- Map<String,VisualScene> visual_scene_map;
- Map<String,Node*> scene_map;
- Set<String> idref_joints;
- Map<String,String> sid_to_node_map;
- //Map<String,NodeJoint*> bone_map;
-
- Map<String,Transform> bone_rest_map;
-
- String local_path;
- String root_visual_scene;
- String root_physics_scene;
-
- Vector<AnimationClip> animation_clips;
- Vector<AnimationTrack> animation_tracks;
- Map<String,Vector<int> > referenced_tracks;
- Map<String,Vector<int> > by_id_tracks;
-
- float animation_length;
-
- State() { unit_scale=1.0; up_axis=Vector3::AXIS_Y; import_flags=0; animation_length=0; }
- } state;
-
-
- Error load(const String& p_path, int p_flags=0);
-
- Collada();
-
- Transform fix_transform(const Transform& p_transform);
-
- Transform get_root_transform() const;
-
- int get_uv_channel(String p_name);
-
-private: // private stuff
-
- Map<String,int> channel_map;
-
- void _parse_asset(XMLParser& parser);
- void _parse_image(XMLParser& parser);
- void _parse_material(XMLParser& parser);
- void _parse_effect_material(XMLParser& parser,Effect &effect,String &id);
- void _parse_effect(XMLParser& parser);
- void _parse_camera(XMLParser& parser);
- void _parse_light(XMLParser& parser);
- void _parse_animation_clip(XMLParser& parser);
-
- void _parse_mesh_geometry(XMLParser& parser,String p_id,String p_name);
- void _parse_curve_geometry(XMLParser& parser,String p_id,String p_name);
-
- void _parse_skin_controller(XMLParser& parser,String p_id);
- void _parse_morph_controller(XMLParser& parser, String id);
- void _parse_controller(XMLParser& parser);
-
- Node* _parse_visual_instance_geometry(XMLParser& parser);
- Node* _parse_visual_instance_camera(XMLParser& parser);
- Node* _parse_visual_instance_light(XMLParser& parser);
-
- Node* _parse_visual_node_instance_data(XMLParser& parser);
- Node* _parse_visual_scene_node(XMLParser& parser);
- void _parse_visual_scene(XMLParser& parser);
-
- void _parse_animation(XMLParser& parser);
- void _parse_scene(XMLParser& parser);
- void _parse_library(XMLParser& parser);
-
-
- Variant _parse_param(XMLParser& parser);
- Vector<float> _read_float_array(XMLParser& parser);
- Vector<String> _read_string_array(XMLParser& parser);
- Transform _read_transform(XMLParser& parser);
- String _read_empty_draw_type(XMLParser& parser);
-
- void _joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner);
- void _create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton=NULL);
- void _find_morph_nodes(VisualScene *p_vscene,Node *p_node);
- bool _remove_node(Node *p_parent,Node *p_node);
- void _remove_node(VisualScene *p_vscene,Node *p_node);
- void _merge_skeletons2(VisualScene *p_vscene);
- void _merge_skeletons(VisualScene *p_vscene,Node *p_node);
- bool _optimize_skeletons(VisualScene *p_vscene,Node *p_node);
-
-
- bool _move_geometry_to_skeletons(VisualScene *p_vscene,Node *p_node,List<Node*> *p_mgeom);
-
-
-
- void _optimize();
-
-
-};
-
-#endif // COLLADA_H
-
-#endif
diff --git a/tools/editor/connections_dialog.h b/tools/editor/connections_dialog.h
deleted file mode 100644
index 64b292bc34..0000000000
--- a/tools/editor/connections_dialog.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*************************************************************************/
-/* connections_dialog.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 CONNECTIONS_DIALOG_H
-#define CONNECTIONS_DIALOG_H
-
-#include "scene/gui/popup.h"
-#include "scene/gui/button.h"
-#include "scene/gui/check_button.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/line_edit.h"
-#include "tools/editor/scene_tree_editor.h"
-#include "tools/editor/property_editor.h"
-#include "undo_redo.h"
-
-/**
-@author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class ConnectDialogBinds;
-
-class ConnectDialog : public ConfirmationDialog {
-
- GDCLASS( ConnectDialog, ConfirmationDialog );
-
-
- ConfirmationDialog *error;
- LineEdit *dst_path;
- LineEdit *dst_method;
- SceneTreeEditor *tree;
- //MenuButton *dst_method_list;
- OptionButton *type_list;
- CheckButton *deferred;
- CheckButton *oneshot;
- CheckButton *make_callback;
- PropertyEditor *bind_editor;
- Node *node;
- ConnectDialogBinds *cdbinds;
- void ok_pressed();
- void _cancel_pressed();
- void _tree_node_selected();
- void _dst_method_list_selected(int p_idx);
- void _add_bind();
- void _remove_bind();
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
-
- bool get_make_callback() { return make_callback->is_visible() && make_callback->is_pressed(); }
- NodePath get_dst_path() const;
- StringName get_dst_method() const;
- bool get_deferred() const;
- bool get_oneshot() const;
- Vector<Variant> get_binds() const;
- void set_dst_method(const StringName& p_method);
- void set_dst_node(Node* p_node);
-
- //Button *get_ok() { return ok; }
- //Button *get_cancel() { return cancel; }
- void edit(Node *p_node);
-
- ConnectDialog();
- ~ConnectDialog();
-
-};
-
-class ConnectionsDock : public VBoxContainer {
-
- GDCLASS( ConnectionsDock , VBoxContainer );
-
- Button *connect_button;
- EditorNode *editor;
- Node *node;
- Tree *tree;
- ConfirmationDialog *remove_confirm;
- ConnectDialog *connect_dialog;
-
- void update_tree();
-
- void _close();
- void _connect();
- void _something_selected();
- void _something_activated();
- UndoRedo *undo_redo;
-
-protected:
-
- void _connect_pressed();
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_undoredo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
-
- void set_node(Node* p_node);
- String get_selected_type();
-
- ConnectionsDock(EditorNode *p_editor=NULL);
- ~ConnectionsDock();
-
-};
-
-#endif
diff --git a/tools/editor/create_dialog.cpp b/tools/editor/create_dialog.cpp
deleted file mode 100644
index 53e968f389..0000000000
--- a/tools/editor/create_dialog.cpp
+++ /dev/null
@@ -1,961 +0,0 @@
-/*************************************************************************/
-/* create_dialog.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "create_dialog.h"
-
-#include "class_db.h"
-#include "print_string.h"
-#include "scene/gui/box_container.h"
-#include "editor_node.h"
-
-#if 1
-
-#include "os/keyboard.h"
-#include "editor_settings.h"
-#include "editor_help.h"
-
-
-void CreateDialog::popup(bool p_dontclear) {
-
- recent->clear();
-
- FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent."+base_type), FileAccess::READ );
-
- if (f) {
-
- TreeItem *root = recent->create_item();
-
- while(!f->eof_reached()) {
- String l = f->get_line().strip_edges();
-
- if (l!=String()) {
-
- TreeItem *ti = recent->create_item(root);
- ti->set_text(0,l);
- if (has_icon(l,"EditorIcons")) {
-
- ti->set_icon(0,get_icon(l,"EditorIcons"));
- } else {
- ti->set_icon(0,get_icon("Object","EditorIcons"));
- }
- }
- }
-
- memdelete(f);
- }
-
- favorites->clear();
-
- f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites."+base_type), FileAccess::READ );
-
- favorite_list.clear();
-
- if (f) {
-
-
- while(!f->eof_reached()) {
- String l = f->get_line().strip_edges();
-
- if (l!=String()) {
- favorite_list.push_back(l);
- }
- }
-
- memdelete(f);
- } else {
-#if 0
-// I think this was way too confusing
- if (base_type=="Node") {
- //harcode some favorites :D
- favorite_list.push_back("Panel");
- favorite_list.push_back("Button");
- favorite_list.push_back("Label");
- favorite_list.push_back("LineEdit");
- favorite_list.push_back("Node2D");
- favorite_list.push_back("Sprite");
- favorite_list.push_back("Camera2D");
- favorite_list.push_back("Area2D");
- favorite_list.push_back("CollisionShape2D");
- favorite_list.push_back("Spatial");
- favorite_list.push_back("Camera");
- favorite_list.push_back("Area");
- favorite_list.push_back("CollisionShape");
- favorite_list.push_back("TestCube");
- favorite_list.push_back("AnimationPlayer");
-
- }
-#endif
- }
-
- _update_favorite_list();
-
- popup_centered_ratio();
- if (p_dontclear)
- search_box->select_all();
- else {
- search_box->clear();
- }
- search_box->grab_focus();
-
- _update_search();
-
-
-}
-
-
-void CreateDialog::_text_changed(const String& p_newtext) {
-
- _update_search();
-}
-
-void CreateDialog::_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 ) ) {
-
- search_options->call("_gui_input",p_ie);
- search_box->accept_event();
- }
-
-}
-
-void CreateDialog::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root,TreeItem **to_select) {
-
- if (p_types.has(p_type))
- return;
- if (!ClassDB::is_parent_class(p_type,base_type) || p_type==base_type)
- return;
-
- String inherits=ClassDB::get_parent_class(p_type);
-
- TreeItem *parent=p_root;
-
-
- if (inherits.length()) {
-
- if (!p_types.has(inherits)) {
-
- add_type(inherits,p_types,p_root,to_select);
- }
-
- if (p_types.has(inherits) )
- parent=p_types[inherits];
- }
-
- TreeItem *item = search_options->create_item(parent);
- item->set_text(0,p_type);
- if (!ClassDB::can_instance(p_type)) {
- item->set_custom_color(0, Color(0.5,0.5,0.5) );
- item->set_selectable(0,false);
- } else {
-
- if ((!*to_select && (search_box->get_text().is_subsequence_ofi(p_type))) || search_box->get_text()==p_type) {
- *to_select=item;
- }
-
- }
-
- if (bool(EditorSettings::get_singleton()->get("docks/scene_tree/start_create_dialog_fully_expanded"))) {
- item->set_collapsed(false);
- } else {
- // don't collapse search results
- bool collapse = (search_box->get_text() == "");
- // don't collapse the root node
- collapse &= (item != p_root);
- // don't collapse abstract nodes on the first tree level
- collapse &= ((parent != p_root) || (ClassDB::can_instance(p_type)));
- item->set_collapsed(collapse);
- }
-
- const String& description = EditorHelp::get_doc_data()->class_list[p_type].brief_description;
- item->set_tooltip(0,description);
-
-
- if (has_icon(p_type,"EditorIcons")) {
-
- item->set_icon(0, get_icon(p_type,"EditorIcons"));
- }
-
-
-
- p_types[p_type]=item;
-}
-
-void CreateDialog::_update_search() {
-
-
- search_options->clear();
- favorite->set_disabled(true);
-
- help_bit->set_text("");
- /*
- TreeItem *root = search_options->create_item();
- _parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
-*/
-
- List<StringName> type_list;
- ClassDB::get_class_list(&type_list);
-
- HashMap<String,TreeItem*> types;
-
- TreeItem *root = search_options->create_item();
-
- root->set_text(0,base_type);
- if (has_icon(base_type,"EditorIcons")) {
- root->set_icon(0,get_icon(base_type,"EditorIcons"));
- }
-
- List<StringName>::Element *I=type_list.front();
- TreeItem *to_select=NULL;
-
- for(;I;I=I->next()) {
-
-
-
- String type=I->get();
-
- if (base_type=="Node" && type.begins_with("Editor"))
- continue; // do not show editor nodes
-
- if (!ClassDB::can_instance(type))
- continue; // cant create what can't be instanced
-
- if (search_box->get_text()=="") {
- add_type(type,types,root,&to_select);
- } else {
-
- bool found=false;
- String type=I->get();
- while(type!="" && ClassDB::is_parent_class(type,base_type) && type!=base_type) {
- if (search_box->get_text().is_subsequence_ofi(type)) {
-
- found=true;
- break;
- }
-
- type=ClassDB::get_parent_class(type);
- }
-
-
- if (found)
- add_type(I->get(),types,root,&to_select);
- }
-
- if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) {
- //there are custom types based on this... cool.
- //print_line("there are custom types");
-
-
- const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[type];
- for(int i=0;i<ct.size();i++) {
-
- bool show = search_box->get_text().is_subsequence_ofi(ct[i].name);
-
- if (!show)
- continue;
-
- if (!types.has(type))
- add_type(type,types,root,&to_select);
-
- TreeItem *ti;
- if (types.has(type) )
- ti=types[type];
- else
- ti=search_options->get_root();
-
-
- TreeItem *item = search_options->create_item(ti);
- item->set_metadata(0,type);
- item->set_text(0,ct[i].name);
- if (ct[i].icon.is_valid()) {
- item->set_icon(0,ct[i].icon);
-
- }
-
- if (!to_select || ct[i].name==search_box->get_text()) {
- to_select=item;
- }
-
- }
-
- }
- }
-
- if (to_select) {
- to_select->select(0);
- favorite->set_disabled(false);
- favorite->set_pressed(favorite_list.find(to_select->get_text(0))!=-1);
- }
-
- get_ok()->set_disabled(root->get_children()==NULL);
-
-}
-
-void CreateDialog::_confirmed() {
-
- TreeItem *ti = search_options->get_selected();
- if (!ti)
- return;
-
- FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent."+base_type), FileAccess::WRITE );
-
- if (f) {
- f->store_line(get_selected_type());
- TreeItem *t = recent->get_root();
- if (t)
- t=t->get_children();
- int count=0;
- while(t) {
- if (t->get_text(0)!=get_selected_type()) {
-
- f->store_line(t->get_text(0));
- }
-
- if (count>32) {
- //limit it to 32 entries..
- break;
- }
- t=t->get_next();
- count++;
- }
-
- memdelete(f);
- }
-
- emit_signal("create");
- hide();
-}
-
-void CreateDialog::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- connect("confirmed",this,"_confirmed");
- favorite->set_icon(get_icon("Favorites","EditorIcons"));
- }
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
- disconnect("confirmed",this,"_confirmed");
-
- }
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
-
- if (is_visible_in_tree()) {
-
- search_box->call_deferred("grab_focus"); // still not visible
- search_box->select_all();
- }
- }
-
-}
-
-void CreateDialog::set_base_type(const String& p_base) {
-
- base_type=p_base;
- set_title(TTR("Create New")+" "+p_base);
- _update_search();
-}
-
-String CreateDialog::get_selected_type() {
-
- TreeItem *selected = search_options->get_selected();
- if (selected)
- return selected->get_text(0);
- else
- return String();
-}
-
-Object *CreateDialog::instance_selected() {
-
- TreeItem *selected = search_options->get_selected();
-
- if (selected) {
-
- Variant md = selected->get_metadata(0);
-
- String custom;
- if (md.get_type()!=Variant::NIL)
- custom=md;
-
- if (custom!=String()) {
- if (EditorNode::get_editor_data().get_custom_types().has(custom)) {
-
- for(int i=0;i<EditorNode::get_editor_data().get_custom_types()[custom].size();i++) {
- if (EditorNode::get_editor_data().get_custom_types()[custom][i].name==selected->get_text(0)) {
- Ref<Texture> icon = EditorNode::get_editor_data().get_custom_types()[custom][i].icon;
- Ref<Script> script = EditorNode::get_editor_data().get_custom_types()[custom][i].script;
- String name = selected->get_text(0);
-
- Object *ob = ClassDB::instance(custom);
- ERR_FAIL_COND_V(!ob,NULL);
- if (ob->is_class("Node")) {
- ob->call("set_name",name);
- }
- ob->set_script(script.get_ref_ptr());
- if (icon.is_valid())
- ob->set_meta("_editor_icon",icon);
- return ob;
-
- }
- }
-
- }
- } else {
- return ClassDB::instance(selected->get_text(0));
- }
- }
-
-
- return NULL;
-}
-
-
-String CreateDialog::get_base_type() const {
-
- return base_type;
-}
-
-void CreateDialog::_item_selected() {
-
- TreeItem *item = search_options->get_selected();
- if (!item)
- return;
-
- String name = item->get_text(0);
-
- favorite->set_disabled(false);
- favorite->set_pressed(favorite_list.find(name)!=-1);
-
- if (!EditorHelp::get_doc_data()->class_list.has(name))
- return;
-
- help_bit->set_text(EditorHelp::get_doc_data()->class_list[name].brief_description);
-
-}
-
-
-void CreateDialog::_favorite_toggled() {
-
- TreeItem *item = search_options->get_selected();
- if (!item)
- return;
-
- String name = item->get_text(0);
-
- if (favorite_list.find(name)==-1) {
- favorite_list.push_back(name);
- favorite->set_pressed(true);
- } else {
- favorite_list.erase(name);
- favorite->set_pressed(false);
- }
-
- _save_favorite_list();
- _update_favorite_list();
-}
-
-void CreateDialog::_save_favorite_list() {
-
- FileAccess *f = FileAccess::open( EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites."+base_type), FileAccess::WRITE );
-
- if (f) {
-
- for(int i=0;i<favorite_list.size();i++) {
-
- f->store_line(favorite_list[i]);
- }
- memdelete(f);
- }
-}
-
-void CreateDialog::_update_favorite_list() {
-
- favorites->clear();
- TreeItem *root = favorites->create_item();
- for(int i=0;i<favorite_list.size();i++) {
- TreeItem *ti = favorites->create_item(root);
- String l = favorite_list[i];
- ti->set_text(0,l);
-
- if (has_icon(l,"EditorIcons")) {
-
- ti->set_icon(0,get_icon(l,"EditorIcons"));
- } else {
- ti->set_icon(0,get_icon("Object","EditorIcons"));
- }
- }
-}
-
-
-void CreateDialog::_history_selected() {
-
- TreeItem *item = recent->get_selected();
- if (!item)
- return;
-
- search_box->set_text(item->get_text(0));
- _update_search();
-
-}
-
-void CreateDialog::_favorite_selected(){
-
- TreeItem *item = favorites->get_selected();
- if (!item)
- return;
-
- search_box->set_text(item->get_text(0));
- _update_search();
-
-}
-
-void CreateDialog::_history_activated() {
-
- _confirmed();
-}
-
-void CreateDialog::_favorite_activated(){
-
- _confirmed();
-}
-
-Variant CreateDialog::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- TreeItem *ti = favorites->get_item_at_pos(p_point);
- if (ti) {
- Dictionary d;
- d["type"]="create_favorite_drag";
- d["class"]=ti->get_text(0);
-
- ToolButton *tb = memnew( ToolButton );
- tb->set_icon(ti->get_icon(0));
- tb->set_text(ti->get_text(0));
- set_drag_preview(tb);
-
- return d;
- }
-
- return Variant();
-}
-
-bool CreateDialog::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
-
- Dictionary d = p_data;
- if (d.has("type") && String(d["type"])=="create_favorite_drag") {
- favorites->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
- return true;
- }
-
- return false;
-}
-void CreateDialog::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
-
- Dictionary d = p_data;
-
- TreeItem *ti = favorites->get_item_at_pos(p_point);
- if (!ti)
- return;
-
- String drop_at = ti->get_text(0);
- int ds = favorites->get_drop_section_at_pos(p_point);
-
- int drop_idx = favorite_list.find(drop_at);
- if (drop_idx<0)
- return;
-
- String type = d["class"];
-
- int from_idx = favorite_list.find(type);
- if (from_idx<0)
- return;
-
- if (drop_idx==from_idx) {
- ds=-1; //cause it will be gone
- } else if (drop_idx>from_idx) {
- drop_idx--;
- }
-
- favorite_list.remove(from_idx);
-
- if (ds<0) {
- favorite_list.insert(drop_idx,type);
- } else {
- if (drop_idx>=favorite_list.size()-1) {
- favorite_list.push_back(type);
- } else {
- favorite_list.insert(drop_idx+1,type);
- }
- }
-
- _save_favorite_list();
- _update_favorite_list();
-
-
-}
-
-void CreateDialog::_bind_methods() {
-
- ClassDB::bind_method(_MD("_text_changed"),&CreateDialog::_text_changed);
- ClassDB::bind_method(_MD("_confirmed"),&CreateDialog::_confirmed);
- ClassDB::bind_method(_MD("_sbox_input"),&CreateDialog::_sbox_input);
- ClassDB::bind_method(_MD("_item_selected"),&CreateDialog::_item_selected);
- ClassDB::bind_method(_MD("_favorite_toggled"),&CreateDialog::_favorite_toggled);
- ClassDB::bind_method(_MD("_history_selected"),&CreateDialog::_history_selected);
- ClassDB::bind_method(_MD("_favorite_selected"),&CreateDialog::_favorite_selected);
- ClassDB::bind_method(_MD("_history_activated"),&CreateDialog::_history_activated);
- ClassDB::bind_method(_MD("_favorite_activated"),&CreateDialog::_favorite_activated);
-
-
- ClassDB::bind_method("get_drag_data_fw",&CreateDialog::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw",&CreateDialog::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw",&CreateDialog::drop_data_fw);
-
- ADD_SIGNAL(MethodInfo("create"));
-
-}
-
-
-CreateDialog::CreateDialog() {
-
- HSplitContainer *hbc = memnew( HSplitContainer );
-
- add_child(hbc);
-
-
- VBoxContainer *lvbc = memnew( VBoxContainer);
- hbc->add_child(lvbc);
- lvbc->set_custom_minimum_size(Size2(150,0)*EDSCALE);
-
- favorites = memnew (Tree );
- lvbc->add_margin_child(TTR("Favorites:"),favorites,true);
- favorites->set_hide_root(true);
- favorites->set_hide_folding(true);
- favorites->connect("cell_selected",this,"_favorite_selected");
- favorites->connect("item_activated",this,"_favorite_activated");
- favorites->set_drag_forwarding(this);
-
-
- recent = memnew (Tree );
- lvbc->add_margin_child(TTR("Recent:"),recent,true);
- recent->set_hide_root(true);
- recent->set_hide_folding(true);
- recent->connect("cell_selected",this,"_history_selected");
- recent->connect("item_activated",this,"_history_activated");
-
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- hbc->add_child(vbc);
- vbc->set_h_size_flags(SIZE_EXPAND_FILL);
- HBoxContainer *search_hb = memnew( HBoxContainer );
- search_box = memnew( LineEdit );
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- search_hb->add_child(search_box);
- favorite = memnew( Button );
- favorite->set_toggle_mode(true);
- search_hb->add_child(favorite);
- favorite->connect("pressed",this,"_favorite_toggled");
- vbc->add_margin_child(TTR("Search:"),search_hb);
- search_box->connect("text_changed",this,"_text_changed");
- search_box->connect("gui_input",this,"_sbox_input");
- search_options = memnew( Tree );
- vbc->add_margin_child(TTR("Matches:"),search_options,true);
- get_ok()->set_text(TTR("Create"));
- get_ok()->set_disabled(true);
- register_text_enter(search_box);
- set_hide_on_ok(false);
- search_options->connect("item_activated",this,"_confirmed");
- search_options->connect("cell_selected",this,"_item_selected");
- //search_options->set_hide_root(true);
- base_type="Object";
-
- help_bit = memnew( EditorHelpBit );
- vbc->add_margin_child(TTR("Description:"),help_bit);
- help_bit->connect("request_hide",this,"_closed");
-
-}
-
-
-#else
-
-//old create dialog, disabled
-
-void CreateDialog::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_READY) {
- connect("confirmed",this,"_create");
- update_tree();
- }
- if (p_what==NOTIFICATION_DRAW) {
-
- //RID ci = get_canvas_item();
- //get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
- }
-}
-
-
-void CreateDialog::_create() {
-
- if (tree->get_selected())
- emit_signal("create");
- hide();
-}
-
-void CreateDialog::_cancel() {
-
- hide();
-}
-
-void CreateDialog::_text_changed(String p_text) {
-
- update_tree();
-}
-
-void CreateDialog::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root) {
-
- if (p_types.has(p_type))
- return;
- if (!ClassDB::is_type(p_type,base) || p_type==base)
- return;
-
- String inherits=ClassDB::type_inherits_from(p_type);
-
- TreeItem *parent=p_root;
-
-
- if (inherits.length()) {
-
- if (!p_types.has(inherits)) {
-
- add_type(inherits,p_types,p_root);
- }
-
- if (p_types.has(inherits) )
- parent=p_types[inherits];
- }
-
- TreeItem *item = tree->create_item(parent);
- item->set_text(0,p_type);
- if (!ClassDB::can_instance(p_type)) {
- item->set_custom_color(0, Color(0.5,0.5,0.5) );
- item->set_selectable(0,false);
- }
-
-
- if (has_icon(p_type,"EditorIcons")) {
-
- item->set_icon(0, get_icon(p_type,"EditorIcons"));
- }
-
-
-
- p_types[p_type]=item;
-}
-
-void CreateDialog::update_tree() {
-
- tree->clear();
-
- List<String> type_list;
- ClassDB::get_type_list(&type_list);
-
- HashMap<String,TreeItem*> types;
-
- TreeItem *root = tree->create_item();
-
- root->set_text(0,base);
-
- List<String>::Element *I=type_list.front();
-
- for(;I;I=I->next()) {
-
-
- String type=I->get();
-
-
- if (!ClassDB::can_instance(type))
- continue; // cant create what can't be instanced
- if (filter->get_text()=="")
- add_type(type,types,root);
- else {
-
- bool found=false;
- String type=I->get();
- while(type!="" && ClassDB::is_type(type,base) && type!=base) {
- if (type.findn(filter->get_text())!=-1) {
-
- found=true;
- break;
- }
-
- type=ClassDB::type_inherits_from(type);
- }
-
-
- if (found)
- add_type(I->get(),types,root);
- }
-
- if (EditorNode::get_editor_data().get_custom_types().has(type)) {
- //there are custom types based on this... cool.
-
-
- const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[type];
- for(int i=0;i<ct.size();i++) {
-
- bool show = filter->get_text()=="" || ct[i].name.findn(filter->get_text())!=-1;
-
- if (!show)
- continue;
- if (!types.has(type))
- add_type(type,types,root);
-
- TreeItem *ti;
- if (types.has(type) )
- ti=types[type];
- else
- ti=tree->get_root();
-
-
- TreeItem *item = tree->create_item(ti);
- item->set_metadata(0,type);
- item->set_text(0,ct[i].name);
- if (ct[i].icon.is_valid()) {
- item->set_icon(0,ct[i].icon);
-
- }
- }
-
- }
- }
-
-
-}
-
-
-Object *CreateDialog::instance_selected() {
-
- if (!tree->get_selected())
- return NULL;
-
- String base = String(tree->get_selected()->get_metadata(0));
- if (base!="") {
-
-
- String name = tree->get_selected()->get_text(0);
- if (EditorNode::get_editor_data().get_custom_types().has(base)) {
-
- const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[base];
- for(int i=0;i<ct.size();i++) {
-
- if (ct[i].name==name) {
-
- Object* obj = ClassDB::instance(base);
- ERR_FAIL_COND_V(!obj,NULL);
- obj->set_script(ct[i].script.get_ref_ptr());
- if (ct[i].icon.is_valid())
- obj->set_meta("_editor_icon",ct[i].icon);
- return obj;
-
-
- }
- }
- }
-
- ERR_FAIL_V(NULL);
-
- }
-
- return ClassDB::instance(tree->get_selected()->get_text(0));
-
-}
-
-
-void CreateDialog::_bind_methods() {
-
- ClassDB::bind_method("_create",&CreateDialog::_create);
- ClassDB::bind_method("_cancel",&CreateDialog::_cancel);
- ClassDB::bind_method("_text_changed", &CreateDialog::_text_changed);
- ADD_SIGNAL( MethodInfo("create"));
-
-}
-
-
-
-
-void CreateDialog::set_base_type(const String& p_base) {
-
- set_title(vformat("Create %s Type",p_base));
-
- if (base==p_base)
- return;
- base=p_base;
- if (is_inside_scene())
- update_tree();
-}
-
-String CreateDialog::get_base_type() const {
-
- return base;
-}
-
-CreateDialog::CreateDialog() {
-
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
-
-
- get_ok()->set_text("Create");
-
- tree = memnew( Tree );
- vbc->add_margin_child("Type:",tree,true);
- //tree->set_hide_root(true);
-
- filter = memnew( LineEdit );
- vbc->add_margin_child("Filter:",filter);
-
- base="Node";
- set_as_toplevel(true);
-
-
- tree->connect("item_activated", this, "_create");
- filter->connect("text_changed", this,"_text_changed");
-
-}
-
-
-CreateDialog::~CreateDialog()
-{
-}
-
-
-#endif
diff --git a/tools/editor/dependency_editor.cpp b/tools/editor/dependency_editor.cpp
deleted file mode 100644
index a01383a868..0000000000
--- a/tools/editor/dependency_editor.cpp
+++ /dev/null
@@ -1,725 +0,0 @@
-/*************************************************************************/
-/* dependency_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "dependency_editor.h"
-
-#include "os/file_access.h"
-#include "scene/gui/margin_container.h"
-#include "io/resource_loader.h"
-#include "editor_node.h"
-
-void DependencyEditor::_notification(int p_what){
-
-
-}
-
-void DependencyEditor::_searched(const String& p_path) {
-
- Map<String,String> dep_rename;
- dep_rename[replacing]=p_path;
-
-
- ResourceLoader::rename_dependencies(editing,dep_rename);
-
- _update_list();
- _update_file();
-}
-
-void DependencyEditor::_load_pressed(Object* p_item,int p_cell,int p_button){
-
- TreeItem *ti=p_item->cast_to<TreeItem>();
- String fname = ti->get_text(0);
- replacing = ti->get_text(1);
-
- search->set_title(TTR("Search Replacement For:")+" "+replacing.get_file());
-
- search->clear_filters();
- List<String> ext;
- ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0),&ext);
- for (List<String>::Element *E=ext.front();E;E=E->next()) {
- search->add_filter("*"+E->get());
- }
- search->popup_centered_ratio();
-
-}
-
-void DependencyEditor::_fix_and_find(EditorFileSystemDirectory *efsd, Map<String,Map<String,String> >& candidates){
-
- for(int i=0;i<efsd->get_subdir_count();i++) {
- _fix_and_find(efsd->get_subdir(i),candidates);
- }
-
- for(int i=0;i<efsd->get_file_count();i++) {
-
- String file = efsd->get_file(i);
- if (!candidates.has(file))
- continue;
-
- String path = efsd->get_file_path(i);
-
- for(Map<String,String>::Element *E=candidates[file].front();E;E=E->next()) {
-
- if (E->get()==String()) {
- E->get()=path;
- continue;
- }
-
- //must match the best, using subdirs
- String existing=E->get().replace_first("res://","");
- String current=path.replace_first("res://","");
- String lost=E->key().replace_first("res://","");
-
- Vector<String> existingv=existing.split("/");
- existingv.invert();
- Vector<String> currentv=current.split("/");
- currentv.invert();
- Vector<String> lostv=lost.split("/");
- lostv.invert();
-
- int existing_score=0;
- int current_score=0;
-
- for(int j=0;j<lostv.size();j++) {
-
- if (j<existingv.size() && lostv[j]==existingv[j]) {
- existing_score++;
- }
- if (j<currentv.size() && lostv[j]==currentv[j]) {
- current_score++;
- }
- }
-
- if (current_score > existing_score) {
-
- //if it was the same, could track distance to new path but..
-
- E->get()=path; //replace by more accurate
- }
-
- }
-
- }
-
-}
-
-
-void DependencyEditor::_fix_all(){
-
- if (!EditorFileSystem::get_singleton()->get_filesystem())
- return;
-
- Map<String,Map<String,String> > candidates;
-
- for (List<String>::Element *E=missing.front();E;E=E->next()) {
-
- String base = E->get().get_file();
- if (!candidates.has(base)) {
- candidates[base]=Map<String,String>();
- }
-
- candidates[base][E->get()]="";
- }
-
- _fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(),candidates);
-
- Map<String,String> remaps;
-
- for (Map<String,Map<String,String> >::Element *E=candidates.front();E;E=E->next()) {
-
- for (Map<String,String>::Element *F=E->get().front();F;F=F->next()) {
-
- if (F->get()!=String()) {
- remaps[F->key()]=F->get();
- }
- }
-
- }
-
- if (remaps.size()) {
-
- ResourceLoader::rename_dependencies(editing,remaps);
-
- _update_list();
- _update_file();
- }
-}
-
-void DependencyEditor::_update_file() {
-
- EditorFileSystem::get_singleton()->update_file(editing);
-
-}
-
-void DependencyEditor::_update_list() {
-
- List<String> deps;
- ResourceLoader::get_dependencies(editing,&deps,true);
-
- tree->clear();
- missing.clear();
-
- TreeItem *root = tree->create_item();
-
- Ref<Texture> folder = get_icon("folder","FileDialog");
-
- bool broken=false;
-
- for(List<String>::Element *E=deps.front();E;E=E->next()) {
-
- TreeItem *item = tree->create_item(root);
-
- String n = E->get();
- String path;
- String type;
-
- if (n.find("::")!=-1) {
- path = n.get_slice("::",0);
- type = n.get_slice("::",1);
- } else {
- path=n;
- type="Resource";
- }
- String name = path.get_file();
-
- Ref<Texture> icon;
- if (has_icon(type,"EditorIcons")) {
- icon=get_icon(type,"EditorIcons");
- } else {
- icon=get_icon("Object","EditorIcons");
- }
- item->set_text(0,name);
- item->set_icon(0,icon);
- item->set_metadata(0,type);
- item->set_text(1,path);
-
- if (!FileAccess::exists(path)) {
- item->set_custom_color(1,Color(1,0.4,0.3));
- missing.push_back(path);
- broken=true;
- }
-
- item->add_button(1,folder,0);
- }
-
- fixdeps->set_disabled(!broken);
-
-}
-
-
-
-void DependencyEditor::edit(const String& p_path) {
-
-
- editing=p_path;
- set_title(TTR("Dependencies For:")+" "+p_path.get_file());
-
- _update_list();
- popup_centered_ratio();
-
- if (EditorNode::get_singleton()->is_scene_open(p_path)) {
- EditorNode::get_singleton()->show_warning(vformat(TTR("Scene '%s' is currently being edited.\nChanges will not take effect unless reloaded."),p_path.get_file()));
- } else if (ResourceCache::has(p_path)) {
- EditorNode::get_singleton()->show_warning(vformat(TTR("Resource '%s' is in use.\nChanges will take effect when reloaded."),p_path.get_file()));
- }
-}
-
-
-void DependencyEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_searched"),&DependencyEditor::_searched);
- ClassDB::bind_method(_MD("_load_pressed"),&DependencyEditor::_load_pressed);
- ClassDB::bind_method(_MD("_fix_all"),&DependencyEditor::_fix_all);
-
-}
-
-DependencyEditor::DependencyEditor() {
-
- VBoxContainer *vb = memnew( VBoxContainer );
- vb->set_name(TTR("Dependencies"));
- add_child(vb);
-
-
- tree = memnew( Tree );
- tree->set_columns(2);
- tree->set_column_titles_visible(true);
- tree->set_column_title(0,TTR("Resource"));
- tree->set_column_title(1,TTR("Path"));
- tree->set_hide_root(true);
- tree->connect("button_pressed",this,"_load_pressed");
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- Label *label = memnew( Label(TTR("Dependencies:")));
- hbc->add_child(label);
- hbc->add_spacer();
- fixdeps = memnew( Button(TTR("Fix Broken")));
- hbc->add_child(fixdeps);
- fixdeps->connect("pressed",this,"_fix_all");
-
- vb->add_child(hbc);
-
- MarginContainer *mc = memnew( MarginContainer );
- mc->set_v_size_flags(SIZE_EXPAND_FILL);
-
- mc->add_child(tree);
- vb->add_child(mc);
-
- set_title(TTR("Dependency Editor"));
- search = memnew( EditorFileDialog );
- search->connect("file_selected",this,"_searched");
- search->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- search->set_title(TTR("Search Replacement Resource:"));
- add_child(search);
-
-}
-
-/////////////////////////////////////
-
-
-
-void DependencyEditorOwners::_fill_owners(EditorFileSystemDirectory *efsd) {
-
- if (!efsd)
- return;
-
- for(int i=0;i<efsd->get_subdir_count();i++) {
- _fill_owners(efsd->get_subdir(i));
- }
-
- for(int i=0;i<efsd->get_file_count();i++) {
-
- Vector<String> deps = efsd->get_file_deps(i);
- //print_line(":::"+efsd->get_file_path(i));
- bool found=false;
- for(int j=0;j<deps.size();j++) {
- //print_line("\t"+deps[j]+" vs "+editing);
- if (deps[j]==editing) {
- //print_line("found");
- found=true;
- break;
- }
- }
- if (!found)
- continue;
-
- Ref<Texture> icon;
- String type=efsd->get_file_type(i);
- if (!has_icon(type,"EditorIcons")) {
- icon=get_icon("Object","EditorIcons");
- } else {
- icon=get_icon(type,"EditorIcons");
- }
-
- owners->add_item(efsd->get_file_path(i),icon);
- }
-
-}
-
-void DependencyEditorOwners::show(const String& p_path) {
-
- editing=p_path;
- owners->clear();
- _fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
- popup_centered_ratio();
-
- set_title(TTR("Owners Of:")+" "+p_path.get_file());
-
-}
-
-DependencyEditorOwners::DependencyEditorOwners() {
-
-
- owners = memnew( ItemList );
- add_child(owners);
-
-
-
-}
-
-///////////////////////
-
-
-void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) {
-
- if (!efsd)
- return;
-
- for(int i=0;i<efsd->get_subdir_count();i++) {
- _fill_owners(efsd->get_subdir(i));
- }
-
- for(int i=0;i<efsd->get_file_count();i++) {
-
- Vector<String> deps = efsd->get_file_deps(i);
- //print_line(":::"+efsd->get_file_path(i));
- Set<String> met;
- for(int j=0;j<deps.size();j++) {
- if (files.has(deps[j])) {
- met.insert(deps[j]);
- }
- }
- if (!met.size())
- continue;
-
- exist=true;
-
- Ref<Texture> icon;
- String type=efsd->get_file_type(i);
- if (!has_icon(type,"EditorIcons")) {
- icon=get_icon("Object","EditorIcons");
- } else {
- icon=get_icon(type,"EditorIcons");
- }
-
-
- for(Set<String>::Element *E=met.front();E;E=E->next()) {
-
- String which = E->get();
- if (!files[which]) {
- TreeItem *ti=owners->create_item(owners->get_root());
- ti->set_text(0,which.get_file());
- files[which]=ti;
-
- }
- TreeItem *ti=owners->create_item(files[which]);
- ti->set_text(0,efsd->get_file_path(i));
- ti->set_icon(0,icon);
- }
-
- }
-
-}
-
-void DependencyRemoveDialog::show(const Vector<String> &to_erase) {
-
- exist=false;
- owners->clear();
- files.clear();
- owners->create_item(); // root
- for(int i=0;i<to_erase.size();i++) {
- files[to_erase[i]]=NULL;
- }
-
- _fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
-
-
- if (exist) {
- owners->show();
- text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"));
- popup_centered_minsize(Size2(500,220));
- } else {
- owners->hide();
- text->set_text(TTR("Remove selected files from the project? (no undo)"));
- popup_centered_minsize(Size2(400,100));
- }
-
-}
-
-void DependencyRemoveDialog::ok_pressed() {
-
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- for (Map<String,TreeItem*>::Element *E=files.front();E;E=E->next()) {
-
- if (ResourceCache::has(E->key())) {
- Resource *res = ResourceCache::get(E->key());
- res->set_path(""); //clear reference to path
- }
- da->remove(E->key());
- EditorFileSystem::get_singleton()->update_file(E->key());
- }
- memdelete(da);
-
-}
-
-DependencyRemoveDialog::DependencyRemoveDialog() {
-
- VBoxContainer *vb = memnew( VBoxContainer );
- add_child(vb);
-
-
- text = memnew( Label );
- vb->add_child(text);
-
- owners = memnew( Tree );
- owners->set_hide_root(true);
- vb->add_child(owners);
- owners->set_v_size_flags(SIZE_EXPAND_FILL);
- get_ok()->set_text(TTR("Remove"));
-}
-
-
-//////////////
-
-
-void DependencyErrorDialog::show(const String& p_for_file,const Vector<String> &report) {
-
-
- for_file=p_for_file;
- set_title(TTR("Error loading:")+" "+p_for_file.get_file());
- files->clear();
-
- TreeItem *root = files->create_item(NULL);
- for(int i=0;i<report.size();i++) {
-
- String dep;
- String type="Object";
- dep=report[i].get_slice("::",0);
- if (report[i].get_slice_count("::")>0)
- type=report[i].get_slice("::",1);
-
- Ref<Texture> icon;
- if (!has_icon(type,"EditorIcons")) {
- icon=get_icon("Object","EditorIcons");
- } else {
- icon=get_icon(type,"EditorIcons");
- }
-
- TreeItem *ti=files->create_item(root);
- ti->set_text(0,dep);
- ti->set_icon(0,icon);
-
- }
-
- popup_centered_minsize(Size2(500,220));
-
-}
-
-void DependencyErrorDialog::ok_pressed() {
-
- EditorNode::get_singleton()->load_scene(for_file,true);
-}
-
-void DependencyErrorDialog::custom_action(const String&) {
-
- EditorNode::get_singleton()->fix_dependencies(for_file);
-}
-
-DependencyErrorDialog::DependencyErrorDialog() {
-
- VBoxContainer *vb = memnew( VBoxContainer );
- add_child(vb);
-
-
-
- files = memnew( Tree );
- files->set_hide_root(true);
- vb->add_margin_child(TTR("Scene failed to load due to missing dependencies:"),files,true);
- files->set_v_size_flags(SIZE_EXPAND_FILL);
- get_ok()->set_text(TTR("Open Anyway"));
-
- text = memnew( Label );
- vb->add_child(text);
- text->set_text(TTR("Which action should be taken?"));
-
-
- fdep=add_button(TTR("Fix Dependencies"),true,"fixdeps");
-
- set_title(TTR("Errors loading!"));
-
-}
-
-//////////////////////////////////////////////////////////////////////
-
-
-
-void OrphanResourcesDialog::ok_pressed() {
-
- paths.clear();
-
- _find_to_delete(files->get_root(),paths);
- if (paths.empty())
- return;
-
- delete_confirm->set_text(vformat(TTR("Permanently delete %d item(s)? (No undo!)"),paths.size()));
- delete_confirm->popup_centered_minsize();
-}
-
-bool OrphanResourcesDialog::_fill_owners(EditorFileSystemDirectory *efsd,HashMap<String,int>& refs,TreeItem* p_parent){
-
-
- if (!efsd)
- return false;
-
- bool has_childs=false;
-
- for(int i=0;i<efsd->get_subdir_count();i++) {
-
- TreeItem *dir_item=NULL;
- if (p_parent) {
- dir_item = files->create_item(p_parent);
- dir_item->set_text(0,efsd->get_subdir(i)->get_name());
- dir_item->set_icon(0,get_icon("folder","FileDialog"));
-
- }
- bool children = _fill_owners(efsd->get_subdir(i),refs,dir_item);
-
- if (p_parent) {
- if (!children) {
- memdelete(dir_item);
- } else {
- has_childs=true;
- }
- }
-
- }
-
-
- for(int i=0;i<efsd->get_file_count();i++) {
-
- if (!p_parent) {
- Vector<String> deps = efsd->get_file_deps(i);
- //print_line(":::"+efsd->get_file_path(i));
- for(int j=0;j<deps.size();j++) {
-
- if (!refs.has(deps[j])) {
- refs[deps[j]]=1;
- }
- }
- } else {
-
- String path = efsd->get_file_path(i);
- if (!refs.has(path)) {
- TreeItem *ti=files->create_item(p_parent);
- ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- ti->set_text(0,efsd->get_file(i));
- ti->set_editable(0,true);
-
- String type=efsd->get_file_type(i);
-
- Ref<Texture> icon;
- if (has_icon(type,"EditorIcons")) {
- icon=get_icon(type,"EditorIcons");
- } else {
- icon=get_icon("Object","EditorIcons");
- }
- ti->set_icon(0,icon);
- int ds = efsd->get_file_deps(i).size();
- ti->set_text(1,itos(ds));
- if (ds) {
- ti->add_button(1,get_icon("Visible","EditorIcons"));
- }
- ti->set_metadata(0,path);
- has_childs=true;
- }
- }
-
- }
-
- return has_childs;
-}
-
-
-void OrphanResourcesDialog::refresh() {
- HashMap<String,int> refs;
- _fill_owners(EditorFileSystem::get_singleton()->get_filesystem(),refs,NULL);
- files->clear();
- TreeItem *root=files->create_item();
- _fill_owners(EditorFileSystem::get_singleton()->get_filesystem(),refs,root);
-}
-
-
-void OrphanResourcesDialog::show(){
-
- refresh();
- popup_centered_ratio();
-}
-
-
-void OrphanResourcesDialog::_find_to_delete(TreeItem* p_item,List<String>& paths) {
-
- while(p_item) {
-
- if (p_item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK && p_item->is_checked(0)) {
- paths.push_back(p_item->get_metadata(0));
- }
-
- if (p_item->get_children()) {
- _find_to_delete(p_item->get_children(),paths);
- }
-
- p_item=p_item->get_next();
- }
-
-
-}
-
-void OrphanResourcesDialog::_delete_confirm() {
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- for (List<String>::Element *E=paths.front();E;E=E->next()) {
-
- da->remove(E->get());
- EditorFileSystem::get_singleton()->update_file(E->get());
- }
- memdelete(da);
- refresh();
-}
-
-void OrphanResourcesDialog::_button_pressed(Object *p_item,int p_column, int p_id) {
-
- TreeItem *ti=p_item->cast_to<TreeItem>();
-
- String path = ti->get_metadata(0);
- dep_edit->edit(path);
-
-}
-
-void OrphanResourcesDialog::_bind_methods() {
-
- ClassDB::bind_method(_MD("_delete_confirm"),&OrphanResourcesDialog::_delete_confirm);
- ClassDB::bind_method(_MD("_button_pressed"),&OrphanResourcesDialog::_button_pressed);
-
-}
-
-OrphanResourcesDialog::OrphanResourcesDialog(){
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
-
- files = memnew( Tree );
- files->set_columns(2);
- files->set_column_titles_visible(true);
- files->set_column_min_width(1,100);
- files->set_column_expand(0,true);
- files->set_column_expand(1,false);
- files->set_column_title(0,TTR("Resource"));
- files->set_column_title(1,TTR("Owns"));
- files->set_hide_root(true);
- vbc->add_margin_child(TTR("Resources Without Explicit Ownership:"),files,true);
- set_title(TTR("Orphan Resource Explorer"));
- delete_confirm = memnew( ConfirmationDialog );
- delete_confirm->set_text(TTR("Delete selected files?"));
- get_ok()->set_text(TTR("Delete"));
- add_child(delete_confirm);
- dep_edit = memnew( DependencyEditor );
- add_child(dep_edit);
- files->connect("button_pressed",this,"_button_pressed");
- delete_confirm->connect("confirmed",this,"_delete_confirm");
- set_hide_on_ok(false);
-
-}
diff --git a/tools/editor/doc/doc_data.cpp b/tools/editor/doc/doc_data.cpp
deleted file mode 100644
index d51dc886b2..0000000000
--- a/tools/editor/doc/doc_data.cpp
+++ /dev/null
@@ -1,1141 +0,0 @@
-/*************************************************************************/
-/* doc_data.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "doc_data.h"
-
-#include "version.h"
-#include "global_constants.h"
-#include "globals.h"
-#include "script_language.h"
-#include "io/marshalls.h"
-#include "io/compression.h"
-#include "scene/resources/theme.h"
-
-void DocData::merge_from(const DocData& p_data) {
-
- for( Map<String,ClassDoc>::Element *E=class_list.front();E;E=E->next()) {
-
-
- ClassDoc &c = E->get();
-
- if (!p_data.class_list.has(c.name))
- continue;
-
- const ClassDoc &cf = p_data.class_list[c.name];
-
- c.description=cf.description;
- c.brief_description=cf.brief_description;
-
- for(int i=0;i<c.methods.size();i++) {
-
- MethodDoc &m = c.methods[i];
-
- for(int j=0;j<cf.methods.size();j++) {
-
- if (cf.methods[j].name!=m.name)
- continue;
- if (cf.methods[j].arguments.size()!=m.arguments.size())
- continue;
- // since polymorphic functions are allowed we need to check the type of
- // the arguments so we make sure they are different.
- int arg_count = cf.methods[j].arguments.size();
- Vector<bool> arg_used;
- arg_used.resize(arg_count);
- for (int l = 0; l < arg_count; ++l) arg_used[l] = false;
- // also there is no guarantee that argument ordering will match, so we
- // have to check one by one so we make sure we have an exact match
- for (int k = 0; k < arg_count; ++k) {
- for (int l = 0; l < arg_count; ++l)
- if (cf.methods[j].arguments[k].type == m.arguments[l].type && !arg_used[l]) {
- arg_used[l] = true;
- break;
- }
- }
- bool not_the_same = false;
- for (int l = 0; l < arg_count; ++l)
- if (!arg_used[l]) // at least one of the arguments was different
- not_the_same = true;
- if (not_the_same)
- continue;
-
- const MethodDoc &mf = cf.methods[j];
-
- m.description=mf.description;
- break;
- }
- }
-
-
- for(int i=0;i<c.signals.size();i++) {
-
- MethodDoc &m = c.signals[i];
-
- for(int j=0;j<cf.signals.size();j++) {
-
- if (cf.signals[j].name!=m.name)
- continue;
- const MethodDoc &mf = cf.signals[j];
-
- m.description=mf.description;
- break;
- }
- }
-
- for(int i=0;i<c.constants.size();i++) {
-
- ConstantDoc &m = c.constants[i];
-
- for(int j=0;j<cf.constants.size();j++) {
-
- if (cf.constants[j].name!=m.name)
- continue;
- const ConstantDoc &mf = cf.constants[j];
-
- m.description=mf.description;
- break;
- }
- }
-
- for(int i=0;i<c.properties.size();i++) {
-
- PropertyDoc &p = c.properties[i];
-
- for(int j=0;j<cf.properties.size();j++) {
-
- if (cf.properties[j].name!=p.name)
- continue;
- const PropertyDoc &pf = cf.properties[j];
-
- p.description=pf.description;
- p.setter=pf.setter;
- p.getter=pf.getter;
-
- break;
- }
- }
-
- for(int i=0;i<c.theme_properties.size();i++) {
-
- PropertyDoc &p = c.theme_properties[i];
-
- for(int j=0;j<cf.theme_properties.size();j++) {
-
- if (cf.theme_properties[j].name!=p.name)
- continue;
- const PropertyDoc &pf = cf.theme_properties[j];
-
- p.description=pf.description;
- break;
- }
- }
-
- }
-
-}
-
-void DocData::generate(bool p_basic_types) {
-
-
- List<StringName> classes;
- ClassDB::get_class_list(&classes);
- classes.sort_custom<StringName::AlphCompare>();
-
- while(classes.size()) {
-
- String name=classes.front()->get();
- String cname=name;
- if (cname.begins_with("_")) //proxy class
- cname=cname.substr(1,name.length());
-
- class_list[cname]=ClassDoc();
- ClassDoc& c = class_list[cname];
- c.name=cname;
- c.inherits=ClassDB::get_parent_class(name);
- c.category=ClassDB::get_category(name);
-
-
- List<PropertyInfo> properties;
- ClassDB::get_property_list(name,&properties,true);
-
- for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
- if (E->get().usage& PROPERTY_USAGE_GROUP || E->get().usage& PROPERTY_USAGE_CATEGORY)
- continue;
-
- PropertyDoc prop;
- StringName setter = ClassDB::get_property_setter(name,E->get().name);
- StringName getter = ClassDB::get_property_getter(name,E->get().name);
-
- prop.name=E->get().name;
- prop.setter=setter;
- prop.getter=getter;
- if (E->get().type==Variant::OBJECT && E->get().hint==PROPERTY_HINT_RESOURCE_TYPE)
- prop.type=E->get().hint_string;
- else
- prop.type=Variant::get_type_name(E->get().type);
-
- c.properties.push_back(prop);
- }
-
-
- List<MethodInfo> method_list;
- ClassDB::get_method_list(name,&method_list,true);
- method_list.sort();
-
-
- for(List<MethodInfo>::Element *E=method_list.front();E;E=E->next()) {
-
- if (E->get().name=="" || (E->get().name[0]=='_' && !(E->get().flags&METHOD_FLAG_VIRTUAL)))
- continue; //hiden, dont count
-
- MethodDoc method;
-
- method.name=E->get().name;
-
- MethodBind *m = ClassDB::get_method(name,E->get().name);
-
-
- if (E->get().flags&METHOD_FLAG_VIRTUAL)
- method.qualifiers="virtual";
- if (E->get().flags&METHOD_FLAG_CONST) {
- if (method.qualifiers!="")
- method.qualifiers+=" ";
- method.qualifiers+="const";
-
- } else if (E->get().flags&METHOD_FLAG_VARARG) {
- if (method.qualifiers!="")
- method.qualifiers+=" ";
- method.qualifiers+="vararg";
- }
-
- for(int i=-1;i<E->get().arguments.size();i++) {
-
- PropertyInfo arginfo;
-
- if (i==-1) {
-
-
- arginfo=E->get().return_val;
-#ifdef DEBUG_METHODS_ENABLED
- if (m && m->get_return_type()!=StringName())
- method.return_type=m->get_return_type();
- else if (method.name.find(":")!=-1) {
- method.return_type=method.name.get_slice(":",1);
- method.name=method.name.get_slice(":",0);
-
- } 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 {
-
- ArgumentDoc argument;
-
- arginfo=E->get().arguments[i];
-
- String type_name;
-
- if (arginfo.name.find(":")!=-1) {
- type_name=arginfo.name.get_slice(":",1);
- arginfo.name=arginfo.name.get_slice(":",0);
-
- } else if (arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE) {
- type_name=arginfo.hint_string;
- } else if (arginfo.type==Variant::NIL)
- type_name="Variant";
- else
- type_name=Variant::get_type_name(arginfo.type);
-
- if (arginfo.type==Variant::OBJECT) {
-
- //print_line("validate: "+cname+"::"+method.name);
- }
-
- if (m && m->has_default_argument(i)) {
- Variant default_arg=m->get_default_argument(i);
- String default_arg_text=m->get_default_argument(i);
-
- switch(default_arg.get_type()) {
-
- case Variant::NIL:
- default_arg_text="NULL";
- break;
- // atomic types
- case Variant::BOOL:
- if (bool(default_arg))
- default_arg_text="true";
- else
- default_arg_text="false";
- break;
- case Variant::INT:
- case Variant::REAL:
- //keep it
- break;
- case Variant::STRING: // 15
- case Variant::NODE_PATH: // 15
- default_arg_text="\""+default_arg_text+"\"";
- break;
- case Variant::TRANSFORM:
- if (default_arg.operator Transform()==Transform()) {
- default_arg_text="";
- }
-
- default_arg_text=Variant::get_type_name(default_arg.get_type())+"("+default_arg_text+")";
- break;
-
- case Variant::RECT3: //sorry naming convention fail :( not like it's used often // 10
- case Variant::COLOR:
- case Variant::PLANE:
- case Variant::POOL_BYTE_ARRAY:
- case Variant::POOL_INT_ARRAY:
- case Variant::POOL_REAL_ARRAY:
- case Variant::POOL_STRING_ARRAY: //25
- case Variant::POOL_VECTOR2_ARRAY:
- case Variant::POOL_VECTOR3_ARRAY:
- case Variant::POOL_COLOR_ARRAY:
- default_arg_text=Variant::get_type_name(default_arg.get_type())+"("+default_arg_text+")";
- break;
- case Variant::VECTOR2: // 5
- case Variant::RECT2:
- case Variant::VECTOR3:
- case Variant::QUAT:
- case Variant::BASIS:
- default_arg_text=Variant::get_type_name(default_arg.get_type())+default_arg_text;
- break;
- case Variant::OBJECT:
- if (default_arg.is_zero()) {
- default_arg_text="NULL";
- break;
- }
- case Variant::INPUT_EVENT:
- case Variant::DICTIONARY: // 20
- case Variant::ARRAY:
- case Variant::_RID:
- case Variant::IMAGE:
- //case Variant::RESOURCE:
-
- default_arg_text=Variant::get_type_name(default_arg.get_type())+"()";
- break;
- default: {}
-
- }
-
-
- argument.type=type_name;
- argument.name=arginfo.name;
- argument.default_value=default_arg_text;
- } else {
-
- argument.type=type_name;
- argument.name=arginfo.name;
- }
-
- if (arginfo.type==Variant::OBJECT) {
-
- //print_line("validate: "+cname+"::"+method.name);
- }
-
- method.arguments.push_back(argument);
- }
-
-/*
- String hint;
- switch(arginfo.hint) {
- case PROPERTY_HINT_DIR: hint="A directory."; break;
- case PROPERTY_HINT_RANGE: hint="Range - min: "+arginfo.hint_string.get_slice(",",0)+" max: "+arginfo.hint_string.get_slice(",",1)+" step: "+arginfo.hint_string.get_slice(",",2); break;
- case PROPERTY_HINT_ENUM: hint="Values: "; for(int j=0;j<arginfo.hint_string.get_slice_count(",");j++) { if (j>0) hint+=", "; hint+=arginfo.hint_string.get_slice(",",j)+"="+itos(j); } break;
- case PROPERTY_HINT_LENGTH: hint="Length: "+arginfo.hint_string; break;
- case PROPERTY_HINT_FLAGS: hint="Values: "; for(int j=0;j<arginfo.hint_string.get_slice_count(",");j++) { if (j>0) hint+=", "; hint+=arginfo.hint_string.get_slice(",",j)+"="+itos(1<<j); } break;
- case PROPERTY_HINT_FILE: hint="A file:"; break;
- //case PROPERTY_HINT_RESOURCE_TYPE: hint="Type: "+arginfo.hint_string; break;
- };
- if (hint!="")
- _write_string(f,4,hint);
-*/
-
-
- }
-
- c.methods.push_back(method);
- }
-
- List<MethodInfo> signal_list;
- ClassDB::get_signal_list(name,&signal_list,true);
-
- if (signal_list.size()) {
-
-
- for(List<MethodInfo>::Element *EV=signal_list.front();EV;EV=EV->next()) {
-
- MethodDoc signal;
- signal.name=EV->get().name;
- for(int i=0;i<EV->get().arguments.size();i++) {
-
- PropertyInfo arginfo=EV->get().arguments[i];
- ArgumentDoc argument;
- argument.name=arginfo.name;
- argument.type=Variant::get_type_name(arginfo.type);
- signal.arguments.push_back(argument);
- }
-
- c.signals.push_back(signal);
- }
-
-
- }
-
- List<String> constant_list;
- ClassDB::get_integer_constant_list(name, &constant_list, true);
-
- for(List<String>::Element *E=constant_list.front();E;E=E->next()) {
-
- ConstantDoc constant;
- constant.name=E->get();
- constant.value=itos(ClassDB::get_integer_constant(name, E->get()));
- c.constants.push_back(constant);
- }
-
- //theme stuff
-
- {
- List<StringName> l;
- Theme::get_default()->get_constant_list(cname,&l);
- for (List<StringName>::Element*E=l.front();E;E=E->next()) {
-
- PropertyDoc pd;
- pd.name=E->get();
- pd.type="int";
- c.theme_properties.push_back(pd);
- }
-
- l.clear();
- Theme::get_default()->get_color_list(cname,&l);
- for (List<StringName>::Element*E=l.front();E;E=E->next()) {
-
- PropertyDoc pd;
- pd.name=E->get();
- pd.type="Color";
- c.theme_properties.push_back(pd);
- }
-
- l.clear();
- Theme::get_default()->get_icon_list(cname,&l);
- for (List<StringName>::Element*E=l.front();E;E=E->next()) {
-
- PropertyDoc pd;
- pd.name=E->get();
- pd.type="Texture";
- c.theme_properties.push_back(pd);
- }
- l.clear();
- Theme::get_default()->get_font_list(cname,&l);
- for (List<StringName>::Element*E=l.front();E;E=E->next()) {
-
- PropertyDoc pd;
- pd.name=E->get();
- pd.type="Font";
- c.theme_properties.push_back(pd);
- }
- l.clear();
- Theme::get_default()->get_stylebox_list(cname,&l);
- for (List<StringName>::Element*E=l.front();E;E=E->next()) {
-
- PropertyDoc pd;
- pd.name=E->get();
- pd.type="StyleBox";
- c.theme_properties.push_back(pd);
- }
-
- }
-
-
- classes.pop_front();
- }
-
-
- {
- //so it can be documented that it does not exist
- class_list["Variant"]=ClassDoc();
- class_list["Variant"].name="Variant";
- }
-
- if (!p_basic_types)
- return;
-
- for (int i=0;i<Variant::VARIANT_MAX;i++) {
-
- if (i==Variant::OBJECT)
- continue; //use the core type instead
-
- int loops=1;
-
- if (i==Variant::INPUT_EVENT)
- loops=InputEvent::TYPE_MAX;
-
- for(int j=0;j<loops;j++) {
-
- String cname=Variant::get_type_name(Variant::Type(i));
-
- if (i==Variant::INPUT_EVENT) {
- static const char* ie_type[InputEvent::TYPE_MAX]={
- "","Key","MouseMotion","MouseButton","JoypadMotion","JoypadButton","ScreenTouch","ScreenDrag","Action"
- };
- cname+=ie_type[j];
- }
-
-
- class_list[cname]=ClassDoc();
- ClassDoc& c = class_list[cname];
- c.name=cname;
- c.category="Built-In Types";
-
- Variant::CallError cerror;
- Variant v=Variant::construct(Variant::Type(i),NULL,0,cerror);
-
- if (i==Variant::INPUT_EVENT) {
- v.set("type",j);
- }
-
- List<MethodInfo> method_list;
- v.get_method_list(&method_list);
- method_list.sort();
- Variant::get_constructor_list(Variant::Type(i),&method_list);
-
-
- for(List<MethodInfo>::Element *E=method_list.front();E;E=E->next()) {
-
- MethodInfo &mi=E->get();
- MethodDoc method;
-
- method.name=mi.name;
-
- for(int i=0;i<mi.arguments.size();i++) {
-
- ArgumentDoc arg;
- PropertyInfo pi=mi.arguments[i];
-
- arg.name=pi.name;
- //print_line("arg name: "+arg.name);
- if (pi.type==Variant::NIL)
- arg.type="var";
- else
- arg.type=Variant::get_type_name(pi.type);
- int defarg = mi.default_arguments.size() - mi.arguments.size() + i;
- if (defarg >=0)
- arg.default_value=mi.default_arguments[defarg];
-
- method.arguments.push_back(arg);
- }
-
- if (mi.return_val.type==Variant::NIL) {
- if (mi.return_val.name!="")
- method.return_type="var";
-
- } else {
- method.return_type=Variant::get_type_name(mi.return_val.type);
- }
-
- c.methods.push_back(method);
- }
-
-
- List<PropertyInfo> properties;
- v.get_property_list(&properties);
- for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
-
- PropertyInfo pi=E->get();
- PropertyDoc property;
- property.name=pi.name;
- property.type=Variant::get_type_name(pi.type);
-
- c.properties.push_back(property);
- }
-
- List<StringName> constants;
- Variant::get_numeric_constants_for_type(Variant::Type(i),&constants);
-
- for(List<StringName>::Element *E=constants.front();E;E=E->next()) {
-
- ConstantDoc constant;
- constant.name=E->get();
- constant.value=itos(Variant::get_numeric_constant_value(Variant::Type(i),E->get()));
- c.constants.push_back(constant);
- }
- }
-
- }
-
- //built in constants and functions
-
- {
-
- String cname="@Global Scope";
- class_list[cname]=ClassDoc();
- ClassDoc& c = class_list[cname];
- c.name=cname;
-
-
- for(int i=0;i<GlobalConstants::get_global_constant_count();i++) {
-
- ConstantDoc cd;
- cd.name=GlobalConstants::get_global_constant_name(i);
- cd.value=itos(GlobalConstants::get_global_constant_value(i));
- c.constants.push_back(cd);
- }
-
- List<GlobalConfig::Singleton> singletons;
- GlobalConfig::get_singleton()->get_singletons(&singletons);
-
- //servers (this is kind of hackish)
- for(List<GlobalConfig::Singleton>::Element *E=singletons.front();E;E=E->next()) {
-
- PropertyDoc pd;
- GlobalConfig::Singleton &s=E->get();
- pd.name=s.name;
- pd.type=s.ptr->get_class();
- while (String(ClassDB::get_parent_class(pd.type))!="Object")
- pd.type=ClassDB::get_parent_class(pd.type);
- if (pd.type.begins_with("_"))
- pd.type=pd.type.substr(1,pd.type.length());
- c.properties.push_back(pd);
-
- }
-
- }
-
- //built in script reference
-
- {
-
-
- for(int i=0;i<ScriptServer::get_language_count();i++) {
-
-
- ScriptLanguage *lang = ScriptServer::get_language(i);
- String cname="@"+lang->get_name();
- class_list[cname]=ClassDoc();
- ClassDoc& c = class_list[cname];
- c.name=cname;
-
- List<MethodInfo> minfo;
-
- lang->get_public_functions(&minfo);
-
-
- for(List<MethodInfo>::Element *E=minfo.front();E;E=E->next()) {
-
- MethodInfo &mi=E->get();
- MethodDoc md;
- md.name=mi.name;
- if (mi.return_val.name!="")
- md.return_type=mi.return_val.name;
- 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++) {
-
- PropertyInfo &pi=mi.arguments[i];
-
- ArgumentDoc ad;
- ad.name=pi.name;
-
-
- if (pi.type==Variant::NIL)
- ad.type="Variant";
- else
- ad.type=Variant::get_type_name( pi.type );
-
- md.arguments.push_back(ad);
- }
-
- c.methods.push_back(md);
-
- }
-
- List<Pair<String,Variant> > cinfo;
- lang->get_public_constants(&cinfo);
-
-
- for(List<Pair<String,Variant> >::Element *E=cinfo.front();E;E=E->next()) {
-
- ConstantDoc cd;
- cd.name=E->get().first;
- cd.value=E->get().second;
- c.constants.push_back(cd);
- }
- }
- }
-
-
-}
-
-
-static Error _parse_methods(Ref<XMLParser>& parser,Vector<DocData::MethodDoc>& methods) {
-
- String section=parser->get_node_name();
- String element=section.substr(0,section.length()-1);
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser->get_node_name()==element) {
-
- DocData::MethodDoc method;
- ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
- method.name=parser->get_attribute_value("name");
- if (parser->has_attribute("qualifiers"))
- method.qualifiers=parser->get_attribute_value("qualifiers");
-
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name=parser->get_node_name();
- if (name=="return") {
-
- ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
- method.return_type=parser->get_attribute_value("type");
- } else if (name=="argument") {
-
- DocData::ArgumentDoc argument;
- ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
- argument.name=parser->get_attribute_value("name");
- ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
- argument.type=parser->get_attribute_value("type");
-
- method.arguments.push_back(argument);
-
- } else if (name=="description") {
-
- parser->read();
- if (parser->get_node_type()==XMLParser::NODE_TEXT)
- method.description=parser->get_node_data().strip_edges();
- }
-
- } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()==element)
- break;
- }
-
- methods.push_back(method);
-
- } else {
- ERR_EXPLAIN("Invalid tag in doc file: "+parser->get_node_name());
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()==section)
- break;
- }
-
- return OK;
-}
-
-Error DocData::load(const String& p_path) {
-
- Ref<XMLParser> parser=memnew(XMLParser);
- Error err = parser->open(p_path);
- if (err)
- return err;
- return _load(parser);
-
-}
-Error DocData::_load(Ref<XMLParser> parser) {
-
- Error err=OK;
-
- while((err=parser->read())==OK) {
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
-
- if (parser->get_node_name() == "doc") {
- break;
- } else if (!parser->is_empty())
- parser->skip_section();// unknown section, likely headers
- }
- }
-
- if (parser->has_attribute("version"))
- version=parser->get_attribute_value("version");
-
-
- while((err=parser->read())==OK) {
-
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="doc")
- break; //end of <doc>
-
- if (parser->get_node_type() != XMLParser::NODE_ELEMENT)
- continue; //no idea what this may be, but skipping anyway
-
- ERR_FAIL_COND_V( parser->get_node_name()!="class", ERR_FILE_CORRUPT );
-
- ERR_FAIL_COND_V( !parser->has_attribute("name"), ERR_FILE_CORRUPT);
- String name = parser->get_attribute_value("name");
- class_list[name]=ClassDoc();
- ClassDoc& c = class_list[name];
-
- //print_line("class: "+name);
- c.name=name;
- if (parser->has_attribute("inherits"))
- c.inherits = parser->get_attribute_value("inherits");
- if (parser->has_attribute("category"))
- c.category = parser->get_attribute_value("category");
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser->get_node_name();
-
- if (name=="brief_description") {
-
- parser->read();
- if (parser->get_node_type()==XMLParser::NODE_TEXT)
- c.brief_description=parser->get_node_data().strip_edges();
-
- } else if (name=="description") {
- parser->read();
- if (parser->get_node_type()==XMLParser::NODE_TEXT)
- c.description=parser->get_node_data().strip_edges();
- } else if (name=="methods") {
-
- Error err = _parse_methods(parser,c.methods);
- ERR_FAIL_COND_V(err,err);
-
- } else if (name=="signals") {
-
- Error err = _parse_methods(parser,c.signals);
- ERR_FAIL_COND_V(err,err);
- } else if (name=="members") {
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser->get_node_name();
-
- if (name=="member") {
-
- PropertyDoc prop;
-
- ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
- prop.name=parser->get_attribute_value("name");
- ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
- prop.type=parser->get_attribute_value("type");
- if (parser->has_attribute("setter"))
- prop.setter=parser->get_attribute_value("setter");
- if (parser->has_attribute("getter"))
- prop.getter=parser->get_attribute_value("getter");
- if (parser->has_attribute("brief"))
- prop.brief_description=parser->get_attribute_value("brief").xml_unescape();
-
- parser->read();
- if (parser->get_node_type()==XMLParser::NODE_TEXT)
- prop.description=parser->get_node_data().strip_edges();
- c.properties.push_back(prop);
- } else {
- ERR_EXPLAIN("Invalid tag in doc file: "+name);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="members")
- break; //end of <constants>
- }
-
- } else if (name=="theme_items") {
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name = parser->get_node_name();
-
- if (name=="theme_item") {
-
- PropertyDoc prop;
-
- ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
- prop.name=parser->get_attribute_value("name");
- ERR_FAIL_COND_V(!parser->has_attribute("type"),ERR_FILE_CORRUPT);
- prop.type=parser->get_attribute_value("type");
- parser->read();
- if (parser->get_node_type()==XMLParser::NODE_TEXT)
- prop.description=parser->get_node_data().strip_edges();
- c.theme_properties.push_back(prop);
- } else {
- ERR_EXPLAIN("Invalid tag in doc file: "+name);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="theme_items")
- break; //end of <constants>
- }
-
- } else if (name=="constants") {
-
- while(parser->read()==OK) {
-
- if (parser->get_node_type() == XMLParser::NODE_ELEMENT) {
-
- String name=parser->get_node_name();
-
- if (name=="constant") {
-
- ConstantDoc constant;
- ERR_FAIL_COND_V(!parser->has_attribute("name"),ERR_FILE_CORRUPT);
- constant.name=parser->get_attribute_value("name");
- ERR_FAIL_COND_V(!parser->has_attribute("value"),ERR_FILE_CORRUPT);
- constant.value=parser->get_attribute_value("value");
- parser->read();
- if (parser->get_node_type()==XMLParser::NODE_TEXT)
- constant.description=parser->get_node_data().strip_edges();
- c.constants.push_back(constant);
- } else {
- ERR_EXPLAIN("Invalid tag in doc file: "+name);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
- } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="constants")
- break; //end of <constants>
- }
-
- } else {
-
- ERR_EXPLAIN("Invalid tag in doc file: "+name);
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
-
-
- } else if (parser->get_node_type() == XMLParser::NODE_ELEMENT_END && parser->get_node_name()=="class")
- break; //end of <asset>
- }
-
-
- }
-
- return OK;
-}
-
-
-static void _write_string(FileAccess *f,int p_tablevel,const String& p_string) {
-
- String tab;
- for(int i=0;i<p_tablevel;i++) tab+="\t";
- f->store_string(tab+p_string+"\n");
-}
-
-Error DocData::save(const String& p_path) {
-
- Error err;
- FileAccess *f = FileAccess::open(p_path,FileAccess::WRITE,&err);
-
- if (err) {
- ERR_EXPLAIN("Can't write doc file: "+p_path);
-
- ERR_FAIL_V(err);
-
- }
-
- _write_string(f,0,"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
- _write_string(f,0,"<doc version=\""+String(VERSION_MKSTRING)+"\" name=\"Engine Types\">");
-
- for( Map<String,ClassDoc>::Element *E=class_list.front();E;E=E->next()) {
-
- ClassDoc &c=E->get();
-
- String header="<class name=\""+c.name+"\"";
- if (c.inherits!="")
- header+=" inherits=\""+c.inherits+"\"";
-
- String category=c.category;
- if (c.category=="")
- category="Core";
- header+=" category=\""+category+"\"";
- header+=">";
- _write_string(f,0,header);
- _write_string(f,1,"<brief_description>");
- if (c.brief_description!="")
- _write_string(f,2,c.brief_description.xml_escape());
- _write_string(f,1,"</brief_description>");
- _write_string(f,1,"<description>");
- if (c.description!="")
- _write_string(f,2,c.description.xml_escape());
- _write_string(f,1,"</description>");
- _write_string(f,1,"<methods>");
-
- c.methods.sort();
-
- for(int i=0;i<c.methods.size();i++) {
-
- MethodDoc &m=c.methods[i];
-
- String qualifiers;
- if (m.qualifiers!="")
- qualifiers+=" qualifiers=\""+m.qualifiers.xml_escape()+"\"";
-
- _write_string(f,2,"<method name=\""+m.name+"\""+qualifiers+">");
-
- if (m.return_type!="") {
-
- _write_string(f,3,"<return type=\""+m.return_type+"\">");
- _write_string(f,3,"</return>");
- }
-
- for(int j=0;j<m.arguments.size();j++) {
-
- ArgumentDoc &a = m.arguments[j];
- if (a.default_value!="")
- _write_string(f,3,"<argument index=\""+itos(j)+"\" name=\""+a.name.xml_escape()+"\" type=\""+a.type.xml_escape()+"\" default=\""+a.default_value.xml_escape(true)+"\">");
- else
- _write_string(f,3,"<argument index=\""+itos(j)+"\" name=\""+a.name.xml_escape()+"\" type=\""+a.type.xml_escape()+"\">");
-
- _write_string(f,3,"</argument>");
-
- }
-
- _write_string(f,3,"<description>");
- if (m.description!="")
- _write_string(f,4,m.description.xml_escape());
- _write_string(f,3,"</description>");
-
- _write_string(f,2,"</method>");
-
- }
-
- _write_string(f,1,"</methods>");
-
- if (c.properties.size()) {
- _write_string(f,1,"<members>");
-
- c.properties.sort();
-
- for(int i=0;i<c.properties.size();i++) {
-
-
- PropertyDoc &p=c.properties[i];
- _write_string(f,2,"<member name=\""+p.name+"\" type=\""+p.type+"\" setter=\""+p.setter+"\" getter=\""+p.getter+"\" brief=\""+p.brief_description.xml_escape(true)+"\">");
- if (p.description!="")
- _write_string(f,3,p.description.xml_escape());
- _write_string(f,2,"</member>");
-
- }
- _write_string(f,1,"</members>");
- }
-
- if (c.signals.size()) {
-
- c.signals.sort();
-
- _write_string(f,1,"<signals>");
- for(int i=0;i<c.signals.size();i++) {
-
- MethodDoc &m=c.signals[i];
- _write_string(f,2,"<signal name=\""+m.name+"\">");
- for(int j=0;j<m.arguments.size();j++) {
-
- ArgumentDoc &a = m.arguments[j];
- _write_string(f,3,"<argument index=\""+itos(j)+"\" name=\""+a.name.xml_escape()+"\" type=\""+a.type.xml_escape()+"\">");
- _write_string(f,3,"</argument>");
-
- }
-
- _write_string(f,3,"<description>");
- if (m.description!="")
- _write_string(f,4,m.description.xml_escape());
- _write_string(f,3,"</description>");
-
- _write_string(f,2,"</signal>");
- }
-
- _write_string(f,1,"</signals>");
- }
-
- _write_string(f,1,"<constants>");
-
-
- for(int i=0;i<c.constants.size();i++) {
-
- ConstantDoc &k=c.constants[i];
- _write_string(f,2,"<constant name=\""+k.name+"\" value=\""+k.value+"\">");
- if (k.description!="")
- _write_string(f,3,k.description.xml_escape());
- _write_string(f,2,"</constant>");
- }
-
- _write_string(f,1,"</constants>");
-
- if (c.theme_properties.size()) {
-
- c.theme_properties.sort();
-
- _write_string(f,1,"<theme_items>");
- for(int i=0;i<c.theme_properties.size();i++) {
-
-
- PropertyDoc &p=c.theme_properties[i];
- _write_string(f,2,"<theme_item name=\""+p.name+"\" type=\""+p.type+"\">");
- _write_string(f,2,"</theme_item>");
-
- }
- _write_string(f,1,"</theme_items>");
- }
-
- _write_string(f,0,"</class>");
-
- }
-
- _write_string(f,0,"</doc>");
- f->close();
- memdelete(f);
-
- return OK;
-}
-
-
-Error DocData::load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size) {
-
- Vector<uint8_t> data;
- data.resize(p_uncompressed_size);
- Compression::decompress(data.ptr(),p_uncompressed_size,p_data,p_compressed_size,Compression::MODE_DEFLATE);
- class_list.clear();
-
- Ref<XMLParser> parser = memnew( XMLParser );
- Error err = parser->open_buffer(data);
- if (err)
- return err;
-
- _load(parser);
-
- return OK;
-
-}
diff --git a/tools/editor/doc/doc_data.h b/tools/editor/doc/doc_data.h
deleted file mode 100644
index fead1da510..0000000000
--- a/tools/editor/doc/doc_data.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*************************************************************************/
-/* doc_data.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 DOC_DATA_H
-#define DOC_DATA_H
-
-
-#include "variant.h"
-#include "map.h"
-#include "io/xml_parser.h"
-
-class DocData {
-public:
- struct ArgumentDoc {
-
- String name;
- String type;
- String default_value;
- };
-
- struct MethodDoc {
-
- String name;
- String return_type;
- String qualifiers;
- String description;
- Vector<ArgumentDoc> arguments;
- bool operator<(const MethodDoc& p_md) const {
- return name<p_md.name;
- }
- };
-
- struct ConstantDoc {
-
- String name;
- String value;
- String description;
- };
-
- struct PropertyDoc {
-
- String name;
- String type;
- String brief_description;
- String description;
- String setter,getter;
- bool operator<(const PropertyDoc& p_prop) const {
- return name<p_prop.name;
- }
- };
-
- struct ClassDoc {
-
- String name;
- String inherits;
- String category;
- String brief_description;
- String description;
- Vector<MethodDoc> methods;
- Vector<MethodDoc> signals;
- Vector<ConstantDoc> constants;
- Vector<PropertyDoc> properties;
- Vector<PropertyDoc> theme_properties;
-
- };
-
- String version;
-
- Map<String,ClassDoc> class_list;
- Error _load(Ref<XMLParser> parser);
-
-
-public:
-
- void merge_from(const DocData& p_data);
- void generate(bool p_basic_types=false);
- Error load(const String& p_path);
- Error save(const String& p_path);
-
- Error load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size);
-
-
-};
-
-#endif // DOC_DATA_H
diff --git a/tools/editor/editor_audio_buses.cpp b/tools/editor/editor_audio_buses.cpp
deleted file mode 100644
index 6ee18f08d8..0000000000
--- a/tools/editor/editor_audio_buses.cpp
+++ /dev/null
@@ -1,1192 +0,0 @@
-#include "editor_audio_buses.h"
-#include "editor_node.h"
-#include "servers/audio_server.h"
-#include "os/keyboard.h"
-#include "io/resource_saver.h"
-#include "filesystem_dock.h"
-
-void EditorAudioBus::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_READY) {
-
- vu_l->set_under_texture(get_icon("BusVuEmpty","EditorIcons"));
- vu_l->set_progress_texture(get_icon("BusVuFull","EditorIcons"));
- vu_r->set_under_texture(get_icon("BusVuEmpty","EditorIcons"));
- vu_r->set_progress_texture(get_icon("BusVuFull","EditorIcons"));
- scale->set_texture( get_icon("BusVuDb","EditorIcons"));
-
- disabled_vu = get_icon("BusVuFrozen","EditorIcons");
-
- prev_active=true;
- update_bus();
- set_process(true);
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
- if (has_focus()) {
- draw_style_box(get_stylebox("focus","Button"),Rect2(Vector2(),get_size()));
- }
- }
-
- if (p_what==NOTIFICATION_PROCESS) {
-
- float real_peak[2]={-100,-100};
- bool activity_found=false;
-
- int cc;
- switch(AudioServer::get_singleton()->get_speaker_mode()) {
- case AudioServer::SPEAKER_MODE_STEREO: cc = 1; break;
- case AudioServer::SPEAKER_SURROUND_51: cc = 4; break;
- case AudioServer::SPEAKER_SURROUND_71: cc = 5; break;
- }
-
- for(int i=0;i<cc;i++) {
- if (AudioServer::get_singleton()->is_bus_channel_active(get_index(),i)) {
- activity_found=true;
- real_peak[0]=MAX(real_peak[0],AudioServer::get_singleton()->get_bus_peak_volume_left_db(get_index(),i));
- real_peak[1]=MAX(real_peak[1],AudioServer::get_singleton()->get_bus_peak_volume_right_db(get_index(),i));
- }
- }
-
-
- if (real_peak[0]>peak_l) {
- peak_l = real_peak[0];
- } else {
- peak_l-=get_process_delta_time()*60.0;
- }
-
- if (real_peak[1]>peak_r) {
- peak_r = real_peak[1];
- } else {
- peak_r-=get_process_delta_time()*60.0;
-
- }
-
- vu_l->set_value(peak_l);
- vu_r->set_value(peak_r);
-
- if (activity_found!=prev_active) {
- if (activity_found) {
- vu_l->set_over_texture(Ref<Texture>());
- vu_r->set_over_texture(Ref<Texture>());
- } else {
- vu_l->set_over_texture(disabled_vu);
- vu_r->set_over_texture(disabled_vu);
-
- }
-
- prev_active=activity_found;
- }
-
- }
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
-
- peak_l=-100;
- peak_r=-100;
- prev_active=true;
-
- set_process(is_visible_in_tree());
- }
-
-}
-
-void EditorAudioBus::update_send() {
-
- send->clear();
- if (get_index()==0) {
- send->set_disabled(true);
- send->set_text("Speakers");
- } else {
- send->set_disabled(false);
- StringName current_send = AudioServer::get_singleton()->get_bus_send(get_index());
- int current_send_index=0; //by default to master
-
- for(int i=0;i<get_index();i++) {
- StringName send_name = AudioServer::get_singleton()->get_bus_name(i);
- send->add_item(send_name);
- if (send_name==current_send) {
- current_send_index=i;
- }
- }
-
- send->select(current_send_index);
- }
-}
-
-void EditorAudioBus::update_bus() {
-
- if (updating_bus)
- return;
-
- updating_bus=true;
-
- int index = get_index();
-
- slider->set_value(AudioServer::get_singleton()->get_bus_volume_db(index));
- track_name->set_text(AudioServer::get_singleton()->get_bus_name(index));
- if (get_index()==0)
- track_name->set_editable(false);
-
- solo->set_pressed( AudioServer::get_singleton()->is_bus_solo(index));
- mute->set_pressed( AudioServer::get_singleton()->is_bus_mute(index));
- bypass->set_pressed( AudioServer::get_singleton()->is_bus_bypassing_effects(index));
- // effects..
- effects->clear();
-
- TreeItem *root = effects->create_item();
- for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(index);i++) {
-
- Ref<AudioEffect> afx = AudioServer::get_singleton()->get_bus_effect(index,i);
-
- TreeItem *fx = effects->create_item(root);
- fx->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- fx->set_editable(0,true);
- fx->set_checked(0,AudioServer::get_singleton()->is_bus_effect_enabled(index,i));
- fx->set_text(0,afx->get_name());
- fx->set_metadata(0,i);
-
- }
-
- TreeItem *add = effects->create_item(root);
- add->set_cell_mode(0,TreeItem::CELL_MODE_CUSTOM);
- add->set_editable(0,true);
- add->set_selectable(0,false);
- add->set_text(0,"Add Effect");
-
- update_send();
-
- updating_bus=false;
-
-}
-
-
-void EditorAudioBus::_name_changed(const String& p_new_name) {
-
- if (p_new_name==AudioServer::get_singleton()->get_bus_name(get_index()))
- return;
-
- String attempt=p_new_name;
- int attempts=1;
-
- while(true) {
-
- bool name_free=true;
- for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
-
- if (AudioServer::get_singleton()->get_bus_name(i)==attempt) {
- name_free=false;
- break;
- }
- }
-
- if (name_free) {
- break;
- }
-
- attempts++;
- attempt=p_new_name+" "+itos(attempts);
- }
- updating_bus=true;
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-
- StringName current = AudioServer::get_singleton()->get_bus_name(get_index());
- ur->create_action("Rename Audio Bus");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_name",get_index(),attempt);
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_name",get_index(),current);
-
- for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
- if (AudioServer::get_singleton()->get_bus_send(i)==current) {
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",i,attempt);
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",i,current);
- }
- }
-
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
-
-
- ur->add_do_method(buses,"_update_sends");
- ur->add_undo_method(buses,"_update_sends");
- ur->commit_action();
-
- updating_bus=false;
-
-}
-
-void EditorAudioBus::_volume_db_changed(float p_db){
-
- if (updating_bus)
- return;
-
- updating_bus=true;
-
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Change Audio Bus Volume",UndoRedo::MERGE_ENDS);
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_volume_db",get_index(),p_db);
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_volume_db",get_index(),AudioServer::get_singleton()->get_bus_volume_db(get_index()));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-
- updating_bus=false;
-
-}
-void EditorAudioBus::_solo_toggled(){
-
- updating_bus=true;
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Toggle Audio Bus Solo");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_solo",get_index(),solo->is_pressed());
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_solo",get_index(),AudioServer::get_singleton()->is_bus_solo(get_index()));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-
- updating_bus=false;
-
-}
-void EditorAudioBus::_mute_toggled(){
-
- updating_bus=true;
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Toggle Audio Bus Mute");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_mute",get_index(),mute->is_pressed());
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_mute",get_index(),AudioServer::get_singleton()->is_bus_mute(get_index()));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-
- updating_bus=false;
-
-}
-void EditorAudioBus::_bypass_toggled(){
-
- updating_bus=true;
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Toggle Audio Bus Bypass Effects");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_bypass_effects",get_index(),bypass->is_pressed());
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_bypass_effects",get_index(),AudioServer::get_singleton()->is_bus_bypassing_effects(get_index()));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-
- updating_bus=false;
-
-
-}
-
-void EditorAudioBus::_send_selected(int p_which) {
-
- updating_bus=true;
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Select Audio Bus Send");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",get_index(),send->get_item_text(p_which));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",get_index(),AudioServer::get_singleton()->get_bus_send(get_index()));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-
- updating_bus=false;
-}
-
-void EditorAudioBus::_effect_selected() {
-
- TreeItem *effect = effects->get_selected();
- if (!effect)
- return;
- updating_bus=true;
-
- if (effect->get_metadata(0)!=Variant()) {
-
- int index = effect->get_metadata(0);
- Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(get_index(),index);
- if (effect.is_valid()) {
- EditorNode::get_singleton()->push_item(effect.ptr());
- }
- }
-
- updating_bus=false;
-
-}
-
-void EditorAudioBus::_effect_edited() {
-
- if (updating_bus)
- return;
-
- TreeItem *effect = effects->get_edited();
- if (!effect)
- return;
-
- if (effect->get_metadata(0)==Variant()) {
- Rect2 area = effects->get_item_rect(effect);
-
- effect_options->set_pos(effects->get_global_pos()+area.pos+Vector2(0,area.size.y));
- effect_options->popup();
- //add effect
- } else {
- int index = effect->get_metadata(0);
- updating_bus=true;
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Select Audio Bus Send");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,effect->is_checked(0));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,AudioServer::get_singleton()->is_bus_effect_enabled(get_index(),index));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-
- updating_bus=false;
-
- }
-
-}
-
-void EditorAudioBus::_effect_add(int p_which) {
-
- if (updating_bus)
- return;
-
- StringName name = effect_options->get_item_metadata(p_which);
-
- Object *fx = ClassDB::instance(name);
- ERR_FAIL_COND(!fx);
- AudioEffect *afx = fx->cast_to<AudioEffect>();
- ERR_FAIL_COND(!afx);
- Ref<AudioEffect> afxr = Ref<AudioEffect>(afx);
-
- afxr->set_name(effect_options->get_item_text(p_which));
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Add Audio Bus Effect");
- ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),afxr,-1);
- ur->add_undo_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect_count(get_index()));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-}
-
-void EditorAudioBus::_gui_input(const InputEvent& p_event) {
-
- if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && !p_event.key.echo) {
- accept_event();
- emit_signal("delete_request");
- }
- if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==2 && p_event.mouse_button.pressed) {
-
- Vector2 pos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y);
- delete_popup->set_pos(get_global_pos()+pos);
- delete_popup->popup();
- }
-}
-
-void EditorAudioBus::_delete_pressed(int p_option) {
-
- if (p_option==1) {
- emit_signal("delete_request");
- } else if (p_option==0) {
- //duplicate
- emit_signal("duplicate_request",get_index());
- }
-
-}
-
-
-Variant EditorAudioBus::get_drag_data(const Point2& p_point) {
-
- if (get_index()==0) {
- return Variant();
- }
-
- Control *c = memnew(Control);
- Panel *p = memnew( Panel );
- c->add_child(p);
- p->add_style_override("panel",get_stylebox("focus","Button"));
- p->set_size(get_size());
- p->set_pos(-p_point);
- set_drag_preview(c);
- Dictionary d;
- d["type"]="move_audio_bus";
- d["index"]=get_index();
- emit_signal("drop_end_request");
- return d;
-}
-
-bool EditorAudioBus::can_drop_data(const Point2& p_point,const Variant& p_data) const {
-
- if (get_index()==0)
- return false;
- Dictionary d=p_data;
- if (d.has("type") && String(d["type"])=="move_audio_bus") {
- return true;
- }
-
- return false;
-}
-void EditorAudioBus::drop_data(const Point2& p_point,const Variant& p_data) {
-
- Dictionary d=p_data;
- emit_signal("dropped",d["index"],get_index());
-
-}
-
-Variant EditorAudioBus::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- print_line("drag fw");
- TreeItem *item = effects->get_item_at_pos(p_point);
- if (!item) {
- print_line("no item");
- return Variant();
- }
-
- Variant md = item->get_metadata(0);
-
- if (md.get_type()==Variant::INT) {
- Dictionary fxd;
- fxd["type"]="audio_bus_effect";
- fxd["bus"]=get_index();
- fxd["effect"]=md;
-
- Label *l = memnew( Label );
- l->set_text(item->get_text(0));
- effects->set_drag_preview(l);
-
- return fxd;
- }
-
- return Variant();
-
-}
-
-bool EditorAudioBus::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
-
- Dictionary d = p_data;
- if (!d.has("type") || String(d["type"])!="audio_bus_effect")
- return false;
-
- TreeItem *item = effects->get_item_at_pos(p_point);
- if (!item)
- return false;
-
- effects->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
-
- return true;
-}
-
-void EditorAudioBus::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
-
- Dictionary d = p_data;
-
- TreeItem *item = effects->get_item_at_pos(p_point);
- if (!item)
- return;
- int pos=effects->get_drop_section_at_pos(p_point);
- Variant md = item->get_metadata(0);
-
- int paste_at;
- int bus = d["bus"];
- int effect = d["effect"];
-
- if (md.get_type()==Variant::INT) {
- paste_at=md;
- if (pos>0)
- paste_at++;
-
- if (bus==get_index() && paste_at >effect) {
- paste_at--;
- }
- } else {
- paste_at=-1;
- }
-
-
- bool enabled = AudioServer::get_singleton()->is_bus_effect_enabled(bus,effect);
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Move Bus Effect");
- ur->add_do_method(AudioServer::get_singleton(),"remove_bus_effect",bus,effect);
- ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect(bus,effect),paste_at);
-
- if (paste_at==-1) {
- paste_at = AudioServer::get_singleton()->get_bus_effect_count(get_index());
- if (bus==get_index()) {
- paste_at--;
- }
- }
- if (!enabled) {
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),paste_at,false);
- }
-
- ur->add_undo_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),paste_at);
- ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",bus,AudioServer::get_singleton()->get_bus_effect(bus,effect),effect);
- if (!enabled) {
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",bus,effect,false);
- }
-
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- if (get_index()!=bus) {
- ur->add_do_method(buses,"_update_bus",bus);
- ur->add_undo_method(buses,"_update_bus",bus);
- }
- ur->commit_action();
-
-
-
-}
-
-void EditorAudioBus::_delete_effect_pressed(int p_option) {
-
- TreeItem * item = effects->get_selected();
- if (!item)
- return;
-
- if (item->get_metadata(0).get_type()!=Variant::INT)
- return;
-
- int index = item->get_metadata(0);
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Delete Bus Effect");
- ur->add_do_method(AudioServer::get_singleton(),"remove_bus_effect",get_index(),index);
- ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",get_index(),AudioServer::get_singleton()->get_bus_effect(get_index(),index),index);
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",get_index(),index,AudioServer::get_singleton()->is_bus_effect_enabled(get_index(),index));
- ur->add_do_method(buses,"_update_bus",get_index());
- ur->add_undo_method(buses,"_update_bus",get_index());
- ur->commit_action();
-
-
-}
-
-void EditorAudioBus::_effect_rmb(const Vector2& p_pos) {
-
- TreeItem * item = effects->get_selected();
- if (!item)
- return;
-
- if (item->get_metadata(0).get_type()!=Variant::INT)
- return;
-
- delete_effect_popup->set_pos(get_global_mouse_pos());
- delete_effect_popup->popup();
-}
-
-void EditorAudioBus::_bind_methods() {
-
- ClassDB::bind_method("update_bus",&EditorAudioBus::update_bus);
- ClassDB::bind_method("update_send",&EditorAudioBus::update_send);
- ClassDB::bind_method("_name_changed",&EditorAudioBus::_name_changed);
- ClassDB::bind_method("_volume_db_changed",&EditorAudioBus::_volume_db_changed);
- ClassDB::bind_method("_solo_toggled",&EditorAudioBus::_solo_toggled);
- ClassDB::bind_method("_mute_toggled",&EditorAudioBus::_mute_toggled);
- ClassDB::bind_method("_bypass_toggled",&EditorAudioBus::_bypass_toggled);
- ClassDB::bind_method("_name_focus_exit",&EditorAudioBus::_name_focus_exit);
- ClassDB::bind_method("_send_selected",&EditorAudioBus::_send_selected);
- ClassDB::bind_method("_effect_edited",&EditorAudioBus::_effect_edited);
- ClassDB::bind_method("_effect_selected",&EditorAudioBus::_effect_selected);
- ClassDB::bind_method("_effect_add",&EditorAudioBus::_effect_add);
- ClassDB::bind_method("_gui_input",&EditorAudioBus::_gui_input);
- ClassDB::bind_method("_delete_pressed",&EditorAudioBus::_delete_pressed);
- ClassDB::bind_method("get_drag_data_fw",&EditorAudioBus::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw",&EditorAudioBus::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw",&EditorAudioBus::drop_data_fw);
- ClassDB::bind_method("_delete_effect_pressed",&EditorAudioBus::_delete_effect_pressed);
- ClassDB::bind_method("_effect_rmb",&EditorAudioBus::_effect_rmb);
-
-
-
- ADD_SIGNAL(MethodInfo("duplicate_request"));
- ADD_SIGNAL(MethodInfo("delete_request"));
- ADD_SIGNAL(MethodInfo("drop_end_request"));
- ADD_SIGNAL(MethodInfo("dropped"));
-
-}
-
-EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
-
- buses=p_buses;
- updating_bus=false;
-
- VBoxContainer *vb = memnew( VBoxContainer );
- add_child(vb);
-
- set_v_size_flags(SIZE_EXPAND_FILL);
-
- track_name = memnew( LineEdit );
- vb->add_child(track_name);
- track_name->connect("text_entered",this,"_name_changed");
- track_name->connect("focus_exited",this,"_name_focus_exit");
-
- HBoxContainer *hbc = memnew( HBoxContainer);
- vb->add_child(hbc);
- hbc->add_spacer();
- solo = memnew( ToolButton );
- solo->set_text("S");
- solo->set_toggle_mode(true);
- solo->set_modulate(Color(0.8,1.2,0.8));
- solo->set_focus_mode(FOCUS_NONE);
- solo->connect("pressed",this,"_solo_toggled");
- hbc->add_child(solo);
- mute = memnew( ToolButton );
- mute->set_text("M");
- mute->set_toggle_mode(true);
- mute->set_modulate(Color(1.2,0.8,0.8));
- mute->set_focus_mode(FOCUS_NONE);
- mute->connect("pressed",this,"_mute_toggled");
- hbc->add_child(mute);
- bypass = memnew( ToolButton );
- bypass->set_text("B");
- bypass->set_toggle_mode(true);
- bypass->set_modulate(Color(1.1,1.1,0.8));
- bypass->set_focus_mode(FOCUS_NONE);
- bypass->connect("pressed",this,"_bypass_toggled");
- hbc->add_child(bypass);
- hbc->add_spacer();
-
- HBoxContainer *hb = memnew( HBoxContainer );
- vb->add_child(hb);
- slider = memnew( VSlider );
- slider->set_min(-80);
- slider->set_max(24);
- slider->set_step(0.1);
-
- slider->connect("value_changed",this,"_volume_db_changed");
- hb->add_child(slider);
- vu_l = memnew( TextureProgress );
- vu_l->set_fill_mode(TextureProgress::FILL_BOTTOM_TO_TOP);
- hb->add_child(vu_l);
- vu_l->set_min(-80);
- vu_l->set_max(24);
- vu_l->set_step(0.1);
-
- vu_r = memnew( TextureProgress );
- vu_r->set_fill_mode(TextureProgress::FILL_BOTTOM_TO_TOP);
- hb->add_child(vu_r);
- vu_r->set_min(-80);
- vu_r->set_max(24);
- vu_r->set_step(0.1);
-
- scale = memnew( TextureRect );
- hb->add_child(scale);
-
- //add_child(hb);
-
- effects = memnew( Tree );
- effects->set_hide_root(true);
- effects->set_custom_minimum_size(Size2(0,90)*EDSCALE);
- effects->set_hide_folding(true);
- vb->add_child(effects);
- effects->connect("item_edited",this,"_effect_edited");
- effects->connect("cell_selected",this,"_effect_selected");
- effects->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
- effects->set_drag_forwarding(this);
- effects->connect("item_rmb_selected",this,"_effect_rmb");
- effects->set_allow_rmb_select(true);
-
- send = memnew( OptionButton );
- send->set_clip_text(true);
- send->connect("item_selected",this,"_send_selected");
- vb->add_child(send);
-
- set_focus_mode(FOCUS_CLICK);
-
- effect_options = memnew( PopupMenu );
- effect_options->connect("index_pressed",this,"_effect_add");
- add_child(effect_options);
- List<StringName> effects;
- ClassDB::get_inheriters_from_class("AudioEffect",&effects);
- effects.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E=effects.front();E;E=E->next()) {
- if (!ClassDB::can_instance(E->get()))
- continue;
-
- Ref<Texture> icon;
- if (has_icon(E->get(),"EditorIcons")) {
- icon = get_icon(E->get(),"EditorIcons");
- }
- String name = E->get().operator String().replace("AudioEffect","");
- effect_options->add_item(name);
- effect_options->set_item_metadata(effect_options->get_item_count()-1,E->get());
- effect_options->set_item_icon(effect_options->get_item_count()-1,icon);
- }
-
- delete_popup = memnew( PopupMenu );
- delete_popup->add_item("Duplicate");
- delete_popup->add_item("Delete");
- add_child(delete_popup);
- delete_popup->connect("index_pressed",this,"_delete_pressed");
-
- delete_effect_popup = memnew( PopupMenu );
- delete_effect_popup->add_item("Delete Effect");
- add_child(delete_effect_popup);
- delete_effect_popup->connect("index_pressed",this,"_delete_effect_pressed");
-
-}
-
-
-
-bool EditorAudioBusDrop::can_drop_data(const Point2& p_point,const Variant& p_data) const {
-
- Dictionary d=p_data;
- if (d.has("type") && String(d["type"])=="move_audio_bus") {
- return true;
- }
-
- return false;
-}
-void EditorAudioBusDrop::drop_data(const Point2& p_point,const Variant& p_data){
-
- Dictionary d=p_data;
- emit_signal("dropped",d["index"],-1);
-
-}
-
-void EditorAudioBusDrop::_bind_methods() {
-
- ADD_SIGNAL(MethodInfo("dropped"));
-}
-
-EditorAudioBusDrop::EditorAudioBusDrop() {
-
-
-}
-
-
-void EditorAudioBuses::_update_buses() {
-
- while(bus_hb->get_child_count()>0) {
- memdelete(bus_hb->get_child(0));
- }
-
- drop_end=NULL;
-
- for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
-
- EditorAudioBus *audio_bus = memnew( EditorAudioBus(this) );
- if (i==0) {
- audio_bus->set_self_modulate(Color(1,0.9,0.9));
- }
- bus_hb->add_child(audio_bus);
- audio_bus->connect("delete_request",this,"_delete_bus",varray(audio_bus),CONNECT_DEFERRED);
- audio_bus->connect("duplicate_request",this,"_duplicate_bus",varray(),CONNECT_DEFERRED);
- audio_bus->connect("drop_end_request",this,"_request_drop_end");
- audio_bus->connect("dropped",this,"_drop_at_index",varray(),CONNECT_DEFERRED);
-
-
-
- }
-}
-
-EditorAudioBuses *EditorAudioBuses::register_editor() {
-
- EditorAudioBuses * audio_buses = memnew( EditorAudioBuses );
- EditorNode::get_singleton()->add_bottom_panel_item("Audio",audio_buses);
- return audio_buses;
-}
-
-void EditorAudioBuses::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_READY) {
- _update_buses();
- }
-
- if (p_what==NOTIFICATION_DRAG_END) {
- if (drop_end) {
- drop_end->queue_delete();
- drop_end=NULL;
- }
- }
-
- if (p_what==NOTIFICATION_PROCESS) {
-
- //check if anything was edited
- bool edited = AudioServer::get_singleton()->is_edited();
- for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
- for(int j=0;j<AudioServer::get_singleton()->get_bus_effect_count(i);j++) {
- Ref<AudioEffect> effect = AudioServer::get_singleton()->get_bus_effect(i,j);
- if (effect->is_edited()) {
- edited=true;
- effect->set_edited(false);
- }
- }
- }
-
- AudioServer::get_singleton()->set_edited(false);
-
- if (edited) {
-
- save_timer->start();
- }
- }
-
-}
-
-
-void EditorAudioBuses::_add_bus() {
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-
- //need to simulate new name, so we can undi :(
- ur->create_action("Add Audio Bus");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_count",AudioServer::get_singleton()->get_bus_count()+1);
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_count",AudioServer::get_singleton()->get_bus_count());
- ur->add_do_method(this,"_update_buses");
- ur->add_undo_method(this,"_update_buses");
- ur->commit_action();
-
-}
-
-void EditorAudioBuses::_update_bus(int p_index) {
-
- if (p_index>=bus_hb->get_child_count())
- return;
-
- bus_hb->get_child(p_index)->call("update_bus");
-}
-
-void EditorAudioBuses::_update_sends() {
-
- for(int i=0;i<bus_hb->get_child_count();i++) {
- bus_hb->get_child(i)->call("update_send");
- }
-}
-
-void EditorAudioBuses::_delete_bus(Object* p_which) {
-
- EditorAudioBus *bus = p_which->cast_to<EditorAudioBus>();
- int index = bus->get_index();
- if (index==0) {
- EditorNode::get_singleton()->show_warning("Master bus can't be deleted!");
- return;
- }
-
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-
- ur->create_action("Delete Audio Bus");
- ur->add_do_method(AudioServer::get_singleton(),"remove_bus",index);
- ur->add_undo_method(AudioServer::get_singleton(),"add_bus",index);
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_name",index,AudioServer::get_singleton()->get_bus_name(index));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_volume_db",index,AudioServer::get_singleton()->get_bus_volume_db(index));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_send",index,AudioServer::get_singleton()->get_bus_send(index));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_solo",index,AudioServer::get_singleton()->is_bus_solo(index));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_mute",index,AudioServer::get_singleton()->is_bus_mute(index));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_bypass_effects",index,AudioServer::get_singleton()->is_bus_bypassing_effects(index));
- for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(index);i++) {
-
- ur->add_undo_method(AudioServer::get_singleton(),"add_bus_effect",index,AudioServer::get_singleton()->get_bus_effect(index,i));
- ur->add_undo_method(AudioServer::get_singleton(),"set_bus_effect_enabled",index,i,AudioServer::get_singleton()->is_bus_effect_enabled(index,i));
- }
- ur->add_do_method(this,"_update_buses");
- ur->add_undo_method(this,"_update_buses");
- ur->commit_action();
-
-}
-
-
-void EditorAudioBuses::_duplicate_bus(int p_which) {
-
- int add_at_pos = p_which+1;
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Duplicate Audio Bus");
- ur->add_do_method(AudioServer::get_singleton(),"add_bus",add_at_pos);
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_name",add_at_pos,AudioServer::get_singleton()->get_bus_name(p_which)+" Copy");
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_volume_db",add_at_pos,AudioServer::get_singleton()->get_bus_volume_db(p_which));
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_send",add_at_pos,AudioServer::get_singleton()->get_bus_send(p_which));
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_solo",add_at_pos,AudioServer::get_singleton()->is_bus_solo(p_which));
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_mute",add_at_pos,AudioServer::get_singleton()->is_bus_mute(p_which));
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_bypass_effects",add_at_pos,AudioServer::get_singleton()->is_bus_bypassing_effects(p_which));
- for(int i=0;i<AudioServer::get_singleton()->get_bus_effect_count(p_which);i++) {
-
- ur->add_do_method(AudioServer::get_singleton(),"add_bus_effect",add_at_pos,AudioServer::get_singleton()->get_bus_effect(p_which,i));
- ur->add_do_method(AudioServer::get_singleton(),"set_bus_effect_enabled",add_at_pos,i,AudioServer::get_singleton()->is_bus_effect_enabled(p_which,i));
- }
- ur->add_undo_method(AudioServer::get_singleton(),"remove_bus",add_at_pos);
- ur->add_do_method(this,"_update_buses");
- ur->add_undo_method(this,"_update_buses");
- ur->commit_action();
-
-}
-
-void EditorAudioBuses::_request_drop_end() {
-
- if (!drop_end && bus_hb->get_child_count()) {
- drop_end = memnew( EditorAudioBusDrop );
-
- bus_hb->add_child(drop_end);
- drop_end->set_custom_minimum_size(bus_hb->get_child(0)->cast_to<Control>()->get_size());
- drop_end->connect("dropped",this,"_drop_at_index",varray(),CONNECT_DEFERRED);
- }
-}
-
-void EditorAudioBuses::_drop_at_index(int p_bus,int p_index) {
-
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-
- //need to simulate new name, so we can undi :(
- ur->create_action("Move Audio Bus");
- ur->add_do_method(AudioServer::get_singleton(),"move_bus",p_bus,p_index);
- int final_pos;
- if (p_index==p_bus) {
- final_pos=p_bus;
- } else if (p_index==-1) {
- final_pos = AudioServer::get_singleton()->get_bus_count()-1;
- } else if (p_index<p_bus) {
- final_pos = p_index;
- } else {
- final_pos = p_index -1;
- }
- ur->add_undo_method(AudioServer::get_singleton(),"move_bus",final_pos,p_bus);
-
- ur->add_do_method(this,"_update_buses");
- ur->add_undo_method(this,"_update_buses");
- ur->commit_action();
-}
-
-void EditorAudioBuses::_server_save() {
-
- Ref<AudioBusLayout> state = AudioServer::get_singleton()->generate_bus_layout();
- ResourceSaver::save(edited_path,state);
-
-}
-
-void EditorAudioBuses::_select_layout() {
-
- EditorNode::get_singleton()->get_filesystem_dock()->select_file(edited_path);
-}
-
-void EditorAudioBuses::_save_as_layout() {
-
- file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- file_dialog->set_title(TTR("Save Audio Bus Layout As.."));
- file_dialog->set_current_path(edited_path);
- file_dialog->popup_centered_ratio();
- new_layout=false;
-}
-
-
-void EditorAudioBuses::_new_layout() {
-
- file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- file_dialog->set_title(TTR("Location for New Layout.."));
- file_dialog->set_current_path(edited_path);
- file_dialog->popup_centered_ratio();
- new_layout=true;
-}
-
-void EditorAudioBuses::_load_layout() {
-
- file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- file_dialog->set_title(TTR("Open Audio Bus Layout"));
- file_dialog->set_current_path(edited_path);
- file_dialog->popup_centered_ratio();
- new_layout=false;
-}
-
-
-void EditorAudioBuses::_load_default_layout() {
-
-
- Ref<AudioBusLayout> state = ResourceLoader::load("res://default_bus_layout.tres");
- if (state.is_null()) {
- EditorNode::get_singleton()->show_warning("There is no 'res://default_bus_layout.tres' file.");
- return;
- }
-
- edited_path="res://default_bus_layout.tres";
- file->set_text(edited_path.get_file());
- AudioServer::get_singleton()->set_bus_layout(state);
- _update_buses();
- EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
-}
-
-void EditorAudioBuses::_file_dialog_callback(const String& p_string) {
-
- if (file_dialog->get_mode()==EditorFileDialog::MODE_OPEN_FILE) {
- Ref<AudioBusLayout> state = ResourceLoader::load(p_string);
- if (state.is_null()) {
- EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout.");
- return;
- }
-
- edited_path=p_string;
- file->set_text(p_string.get_file());
- AudioServer::get_singleton()->set_bus_layout(state);
- _update_buses();
- EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
-
- } else if (file_dialog->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
-
- if (new_layout) {
- Ref<AudioBusLayout> empty_state;
- empty_state.instance();
- AudioServer::get_singleton()->set_bus_layout(empty_state);
- }
-
- Error err = ResourceSaver::save(p_string,AudioServer::get_singleton()->generate_bus_layout());
-
- if (err!=OK) {
- EditorNode::get_singleton()->show_warning("Error saving file: "+p_string);
- return;
- }
-
- edited_path=p_string;
- file->set_text(p_string.get_file());
- _update_buses();
- EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
- }
-
-}
-
-void EditorAudioBuses::_bind_methods() {
-
- ClassDB::bind_method("_add_bus",&EditorAudioBuses::_add_bus);
- ClassDB::bind_method("_update_buses",&EditorAudioBuses::_update_buses);
- ClassDB::bind_method("_update_bus",&EditorAudioBuses::_update_bus);
- ClassDB::bind_method("_update_sends",&EditorAudioBuses::_update_sends);
- ClassDB::bind_method("_delete_bus",&EditorAudioBuses::_delete_bus);
- ClassDB::bind_method("_request_drop_end",&EditorAudioBuses::_request_drop_end);
- ClassDB::bind_method("_drop_at_index",&EditorAudioBuses::_drop_at_index);
- ClassDB::bind_method("_server_save",&EditorAudioBuses::_server_save);
- ClassDB::bind_method("_select_layout",&EditorAudioBuses::_select_layout);
- ClassDB::bind_method("_save_as_layout",&EditorAudioBuses::_save_as_layout);
- ClassDB::bind_method("_load_layout",&EditorAudioBuses::_load_layout);
- ClassDB::bind_method("_load_default_layout",&EditorAudioBuses::_load_default_layout);
- ClassDB::bind_method("_new_layout",&EditorAudioBuses::_new_layout);
- ClassDB::bind_method("_duplicate_bus",&EditorAudioBuses::_duplicate_bus);
-
- ClassDB::bind_method("_file_dialog_callback",&EditorAudioBuses::_file_dialog_callback);
-}
-
-EditorAudioBuses::EditorAudioBuses()
-{
-
- drop_end = NULL;
- top_hb = memnew( HBoxContainer );
- add_child(top_hb);
-
- add = memnew( Button );
- top_hb->add_child(add);;
- add->set_text(TTR("Add Bus"));
-
- add->connect("pressed",this,"_add_bus");
-
-
-
- top_hb->add_spacer();
-
- file = memnew( ToolButton );
- file->set_text("default_bus_layout.tres");
- top_hb->add_child(file);
- file->connect("pressed",this,"_select_layout");
-
- load = memnew( Button );
- load->set_text(TTR("Load"));
- top_hb->add_child(load);
- load->connect("pressed",this,"_load_layout");
-
- save_as = memnew( Button );
- save_as->set_text(TTR("Save As"));
- top_hb->add_child(save_as);
- save_as->connect("pressed",this,"_save_as_layout");
-
- _default = memnew( Button );
- _default->set_text(TTR("Default"));
- top_hb->add_child(_default);
- _default->connect("pressed",this,"_load_default_layout");
-
- _new = memnew( Button );
- _new->set_text(TTR("Create"));
- top_hb->add_child(_new);
- _new->connect("pressed",this,"_new_layout");
-
- bus_scroll = memnew( ScrollContainer );
- bus_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
- bus_scroll->set_enable_h_scroll(true);
- bus_scroll->set_enable_v_scroll(false);
- add_child(bus_scroll);
- bus_hb = memnew( HBoxContainer );
- bus_scroll->add_child(bus_hb);
-
- save_timer=memnew(Timer);
- save_timer->set_wait_time(0.8);
- save_timer->set_one_shot(true);
- add_child(save_timer);
- save_timer->connect("timeout",this,"_server_save");
-
- set_v_size_flags(SIZE_EXPAND_FILL);
-
-
- edited_path = "res://default_bus_layout.tres";
-
- file_dialog = memnew( EditorFileDialog );
- List<String> ext;
- ResourceLoader::get_recognized_extensions_for_type("AudioServerState",&ext);
- for (List<String>::Element *E=ext.front();E;E=E->next()) {
- file_dialog->add_filter("*."+E->get()+"; Audio Bus State");
- }
- add_child(file_dialog);
- file_dialog->connect("file_selected",this,"_file_dialog_callback");
-
- set_process(true);
-
-}
-void EditorAudioBuses::open_layout(const String& p_path) {
-
- EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
-
- Ref<AudioBusLayout> state = ResourceLoader::load(p_path);
- if (state.is_null()) {
- EditorNode::get_singleton()->show_warning("Invalid file, not an audio bus layout.");
- return;
- }
-
- edited_path=p_path;
- file->set_text(p_path.get_file());
- AudioServer::get_singleton()->set_bus_layout(state);
- _update_buses();
- EditorNode::get_singleton()->get_undo_redo()->clear_history();
- call_deferred("_select_layout");
-}
-
-void AudioBusesEditorPlugin::edit(Object *p_node) {
-
- if (p_node->cast_to<AudioBusLayout>()) {
-
- String path = p_node->cast_to<AudioBusLayout>()->get_path();
- if (path.is_resource_file()) {
- audio_bus_editor->open_layout(path);
- }
- }
-}
-
-bool AudioBusesEditorPlugin::handles(Object *p_node) const {
-
- return (p_node->cast_to<AudioBusLayout>()!=NULL);
-}
-
-void AudioBusesEditorPlugin::make_visible(bool p_visible){
-
-
-}
-
-AudioBusesEditorPlugin::AudioBusesEditorPlugin(EditorAudioBuses *p_node) {
-
- audio_bus_editor=p_node;
-}
-
-AudioBusesEditorPlugin::~AudioBusesEditorPlugin() {
-
-}
diff --git a/tools/editor/editor_audio_buses.h b/tools/editor/editor_audio_buses.h
deleted file mode 100644
index e44f8cd579..0000000000
--- a/tools/editor/editor_audio_buses.h
+++ /dev/null
@@ -1,186 +0,0 @@
-#ifndef EDITORAUDIOBUSES_H
-#define EDITORAUDIOBUSES_H
-
-
-#include "scene/gui/box_container.h"
-#include "scene/gui/button.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/scroll_container.h"
-#include "scene/gui/panel_container.h"
-#include "scene/gui/slider.h"
-#include "scene/gui/texture_progress.h"
-#include "scene/gui/texture_rect.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/panel.h"
-#include "tools/editor/editor_file_dialog.h"
-#include "editor_plugin.h"
-
-class EditorAudioBuses;
-
-class EditorAudioBus : public PanelContainer {
-
- GDCLASS( EditorAudioBus, PanelContainer )
-
- bool prev_active;
- float peak_l;
- float peak_r;
-
- Ref<Texture> disabled_vu;
- LineEdit *track_name;
- VSlider *slider;
- TextureProgress *vu_l;
- TextureProgress *vu_r;
- TextureRect *scale;
- OptionButton *send;
-
- PopupMenu *effect_options;
- PopupMenu *delete_popup;
- PopupMenu *delete_effect_popup;
-
- Button *solo;
- Button *mute;
- Button *bypass;
-
- Tree *effects;
-
- bool updating_bus;
-
- void _gui_input(const InputEvent& p_event);
- void _delete_pressed(int p_option);
-
- void _name_changed(const String& p_new_name);
- void _name_focus_exit() { _name_changed(track_name->get_text()); }
- void _volume_db_changed(float p_db);
- void _solo_toggled();
- void _mute_toggled();
- void _bypass_toggled();
- void _send_selected(int p_which);
- void _effect_edited();
- void _effect_add(int p_which);
- void _effect_selected();
- void _delete_effect_pressed(int p_option);
- void _effect_rmb(const Vector2& p_pos);
-
-
- virtual Variant get_drag_data(const Point2& p_point);
- virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
- virtual void drop_data(const Point2& p_point,const Variant& p_data);
-
-
- Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
- bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
- void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
-
-friend class EditorAudioBuses;
-
- EditorAudioBuses *buses;
-
-protected:
-
- static void _bind_methods();
- void _notification(int p_what);
-public:
-
- void update_bus();
- void update_send();
-
- EditorAudioBus(EditorAudioBuses *p_buses=NULL);
-};
-
-
-class EditorAudioBusDrop : public Panel {
-
- GDCLASS(EditorAudioBusDrop,Panel);
-
- virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
- virtual void drop_data(const Point2& p_point,const Variant& p_data);
-protected:
-
- static void _bind_methods();
-public:
-
- EditorAudioBusDrop();
-};
-
-class EditorAudioBuses : public VBoxContainer {
-
- GDCLASS(EditorAudioBuses,VBoxContainer)
-
- HBoxContainer *top_hb;
-
- Button *add;
- ScrollContainer *bus_scroll;
- HBoxContainer *bus_hb;
-
- EditorAudioBusDrop *drop_end;
-
- Button *file;
- Button *load;
- Button *save_as;
- Button *_default;
- Button *_new;
-
- Timer *save_timer;
- String edited_path;
-
- void _add_bus();
- void _update_buses();
- void _update_bus(int p_index);
- void _update_sends();
-
- void _delete_bus(Object* p_which);
- void _duplicate_bus(int p_which);
-
-
- void _request_drop_end();
- void _drop_at_index(int p_bus,int p_index);
-
- void _server_save();
-
- void _select_layout();
- void _load_layout();
- void _save_as_layout();
- void _load_default_layout();
- void _new_layout();
-
- EditorFileDialog *file_dialog;
- bool new_layout;
-
- void _file_dialog_callback(const String& p_string);
-
-protected:
-
- static void _bind_methods();
- void _notification(int p_what);
-public:
-
- void open_layout(const String& p_path);
-
- static EditorAudioBuses* register_editor();
-
- EditorAudioBuses();
-};
-
-
-
-class AudioBusesEditorPlugin : public EditorPlugin {
-
- GDCLASS( AudioBusesEditorPlugin, EditorPlugin );
-
- EditorAudioBuses *audio_bus_editor;
-public:
-
- virtual String get_name() const { return "SampleLibrary"; }
- 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);
-
- AudioBusesEditorPlugin(EditorAudioBuses *p_node);
- ~AudioBusesEditorPlugin();
-
-};
-
-#endif // EDITORAUDIOBUSES_H
diff --git a/tools/editor/editor_autoload_settings.cpp b/tools/editor/editor_autoload_settings.cpp
deleted file mode 100644
index 0038ab48d5..0000000000
--- a/tools/editor/editor_autoload_settings.cpp
+++ /dev/null
@@ -1,610 +0,0 @@
-/*************************************************************************/
-/* editor_autoload_settings.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_autoload_settings.h"
-
-#include "globals.h"
-#include "global_constants.h"
-#include "editor_node.h"
-
-#define PREVIEW_LIST_MAX_SIZE 10
-
-void EditorAutoloadSettings::_notification(int p_what) {
-
- if (p_what == NOTIFICATION_ENTER_TREE) {
-
- List<String> afn;
- ResourceLoader::get_recognized_extensions_for_type("Script", &afn);
- ResourceLoader::get_recognized_extensions_for_type("PackedScene", &afn);
-
- EditorFileDialog *file_dialog = autoload_add_path->get_file_dialog();
-
- for (List<String>::Element *E = afn.front(); E; E = E->next()) {
-
- file_dialog->add_filter("*." + E->get());
- }
- }
-}
-
-bool EditorAutoloadSettings::_autoload_name_is_valid(const String& p_name, String* r_error) {
-
- if (!p_name.is_valid_identifier()) {
- if (r_error)
- *r_error = TTR("Invalid name.") + "\n" + TTR("Valid characters:")+" a-z, A-Z, 0-9 or _";
-
- return false;
- }
-
- if (ClassDB::class_exists(p_name)) {
- if (r_error)
- *r_error = TTR("Invalid name. Must not collide with an existing engine class name.");
-
- return false;
- }
-
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- if (Variant::get_type_name( Variant::Type(i) ) == p_name) {
- if (r_error)
- *r_error = TTR("Invalid name. Must not collide with an existing buit-in type name.");
-
- return false;
- }
- }
-
- for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
- if (GlobalConstants::get_global_constant_name(i) == p_name) {
- if (r_error)
- *r_error = TTR("Invalid name. Must not collide with an existing global constant name.");
-
- return false;
- }
- }
-
- return true;
-}
-
-void EditorAutoloadSettings::_autoload_add() {
-
- String name = autoload_add_name->get_text();
-
- String error;
- if (!_autoload_name_is_valid(name, &error)) {
- EditorNode::get_singleton()->show_warning(error);
- return;
- }
-
- String path = autoload_add_path->get_line_edit()->get_text();
- if (!FileAccess::exists(path)) {
- EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n" + TTR("File does not exist."));
- return;
- }
-
- if (!path.begins_with("res://")) {
- EditorNode::get_singleton()->show_warning(TTR("Invalid Path.") + "\n"+ TTR("Not in resource path."));
- return;
- }
-
- name = "autoload/" + name;
-
- UndoRedo* undo_redo = EditorNode::get_singleton()->get_undo_redo();
-
- undo_redo->create_action(TTR("Add AutoLoad"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(), name, "*" + path);
-
- if (GlobalConfig::get_singleton()->has(name)) {
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
- } else {
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, Variant());
- }
-
- undo_redo->add_do_method(this, "update_autoload");
- undo_redo->add_undo_method(this, "update_autoload");
-
- undo_redo->add_do_method(this, "emit_signal", autoload_changed);
- undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
-
- undo_redo->commit_action();
-
- autoload_add_path->get_line_edit()->set_text("");
- autoload_add_name->set_text("");
-}
-
-void EditorAutoloadSettings::_autoload_selected() {
-
- TreeItem *ti = tree->get_selected();
-
- if (!ti)
- return;
-
- selected_autoload = "autoload/" + ti->get_text(0);
-}
-
-void EditorAutoloadSettings::_autoload_edited() {
-
- if (updating_autoload)
- return;
-
- TreeItem *ti = tree->get_edited();
- int column = tree->get_edited_column();
-
- UndoRedo *undo_redo = EditorNode::get_undo_redo();
-
- if (column == 0) {
- String name = ti->get_text(0);
- String old_name = selected_autoload.get_slice("/", 1);
-
- if (name == old_name)
- return;
-
- String error;
- if (!_autoload_name_is_valid(name, &error)) {
- ti->set_text(0, old_name);
- EditorNode::get_singleton()->show_warning(error);
- return;
- }
-
- if (GlobalConfig::get_singleton()->has("autoload/" + name)) {
- ti->set_text(0, old_name);
- EditorNode::get_singleton()->show_warning(vformat(TTR("Autoload '%s' already exists!"), name));
- return;
- }
-
- updating_autoload = true;
-
- name = "autoload/" + name;
-
- int order = GlobalConfig::get_singleton()->get_order(selected_autoload);
- String path = GlobalConfig::get_singleton()->get(selected_autoload);
-
- undo_redo->create_action(TTR("Rename Autoload"));
-
- undo_redo->add_do_property(GlobalConfig::get_singleton(), name, path);
- undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", name, order);
- undo_redo->add_do_method(GlobalConfig::get_singleton(), "clear", selected_autoload);
-
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), selected_autoload, path);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", selected_autoload, order);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(), "clear", name);
-
- undo_redo->add_do_method(this, "update_autoload");
- undo_redo->add_undo_method(this, "update_autoload");
-
- undo_redo->add_do_method(this, "emit_signal", autoload_changed);
- undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
-
- undo_redo->commit_action();
-
- selected_autoload = name;
- } else if (column == 2) {
- updating_autoload = true;
-
- bool checked = ti->is_checked(2);
- String base = "autoload/" + ti->get_text(0);
-
- int order = GlobalConfig::get_singleton()->get_order(base);
- String path = GlobalConfig::get_singleton()->get(base);
-
- if (path.begins_with("*"))
- path = path.substr(1, path.length());
-
- if (checked)
- path = "*" + path;
-
- undo_redo->create_action(TTR("Toggle AutoLoad Globals"));
-
- undo_redo->add_do_property(GlobalConfig::get_singleton(), base, path);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), base, GlobalConfig::get_singleton()->get(base));
-
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"set_order", base, order);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set_order", base, order);
-
- undo_redo->add_do_method(this, "update_autoload");
- undo_redo->add_undo_method(this, "update_autoload");
-
- undo_redo->add_do_method(this, "emit_signal", autoload_changed);
- undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
-
- undo_redo->commit_action();
- }
-
- updating_autoload = false;
-}
-
-void EditorAutoloadSettings::_autoload_button_pressed(Object *p_item, int p_column, int p_button) {
-
- TreeItem *ti = p_item->cast_to<TreeItem>();
-
- String name = "autoload/" + ti->get_text(0);
-
- UndoRedo *undo_redo = EditorNode::get_undo_redo();
-
- switch (p_button) {
-
- case BUTTON_MOVE_UP:
- case BUTTON_MOVE_DOWN: {
-
- TreeItem *swap = NULL;
-
- if (p_button == BUTTON_MOVE_UP) {
- swap = ti->get_prev();
- } else {
- swap = ti->get_next();
- }
-
- if (!swap)
- return;
-
- String swap_name = "autoload/" + swap->get_text(0);
-
- int order = GlobalConfig::get_singleton()->get_order(name);
- int swap_order = GlobalConfig::get_singleton()->get_order(swap_name);
-
- undo_redo->create_action(TTR("Move Autoload"));
-
- undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", name, swap_order);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", name, order);
-
- undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", swap_name, order);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", swap_name, swap_order);
-
- undo_redo->add_do_method(this, "update_autoload");
- undo_redo->add_undo_method(this, "update_autoload");
-
- undo_redo->add_do_method(this, "emit_signal", autoload_changed);
- undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
-
- undo_redo->commit_action();
- } break;
- case BUTTON_DELETE: {
-
- int order = GlobalConfig::get_singleton()->get_order(name);
-
- undo_redo->create_action(TTR("Remove Autoload"));
-
- undo_redo->add_do_property(GlobalConfig::get_singleton(), name, Variant());
-
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
- undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_persisting", name, true);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", order);
-
- undo_redo->add_do_method(this, "update_autoload");
- undo_redo->add_undo_method(this, "update_autoload");
-
- undo_redo->add_do_method(this, "emit_signal", autoload_changed);
- undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
-
- undo_redo->commit_action();
- } break;
- }
-}
-
-void EditorAutoloadSettings::_autoload_file_callback(const String& p_path) {
-
- autoload_add_name->set_text(p_path.get_file().get_basename());
-}
-
-void EditorAutoloadSettings::update_autoload() {
-
- if (updating_autoload)
- return;
-
- updating_autoload = true;
-
- autoload_cache.clear();
-
- tree->clear();
- TreeItem *root = tree->create_item();
-
- List<PropertyInfo> props;
- GlobalConfig::get_singleton()->get_property_list(&props);
-
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
-
- const PropertyInfo &pi = E->get();
-
- if (!pi.name.begins_with("autoload/"))
- continue;
-
- String name = pi.name.get_slice("/", 1);
- String path = GlobalConfig::get_singleton()->get(pi.name);
-
- if (name.empty())
- continue;
-
- AutoLoadInfo info;
- info.name = pi.name;
- info.order = GlobalConfig::get_singleton()->get_order(pi.name);
-
- autoload_cache.push_back(info);
-
- bool global = false;
-
- if (path.begins_with("*")) {
- global = true;
- path = path.substr(1, path.length());
- }
-
- TreeItem *item = tree->create_item(root);
- item->set_text(0, name);
- item->set_editable(0, true);
-
- item->set_text(1, path);
- item->set_selectable(1, false);
-
- item->set_cell_mode(2, TreeItem::CELL_MODE_CHECK);
- item->set_editable(2, true);
- item->set_text(2, TTR("Enable"));
- item->set_checked(2, global);
-
- item->add_button(3, get_icon("MoveUp","EditorIcons"), BUTTON_MOVE_UP);
- item->add_button(3, get_icon("MoveDown","EditorIcons"), BUTTON_MOVE_DOWN);
- item->add_button(3, get_icon("Del","EditorIcons"), BUTTON_DELETE);
- item->set_selectable(3, false);
- }
-
- updating_autoload = false;
-}
-
-Variant EditorAutoloadSettings::get_drag_data_fw(const Point2& p_point, Control *p_control) {
-
- if (autoload_cache.size() <= 1)
- return false;
-
- PoolStringArray autoloads;
-
- TreeItem *next = tree->get_next_selected(NULL);
-
- while (next) {
- autoloads.push_back(next->get_text(0));
- next = tree->get_next_selected(next);
- }
-
- if (autoloads.size() == 0 || autoloads.size() == autoload_cache.size())
- return Variant();
-
- VBoxContainer *preview = memnew( VBoxContainer );
-
- int max_size = MIN(PREVIEW_LIST_MAX_SIZE, autoloads.size());
-
- for (int i = 0; i < max_size; i++) {
- Label *label = memnew( Label(autoloads[i]) );
- label->set_self_modulate(Color(1,1,1,Math::lerp(1, 0, float(i)/PREVIEW_LIST_MAX_SIZE)));
-
- preview->add_child(label);
- }
-
- tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
- tree->set_drag_preview(preview);
-
- Dictionary drop_data;
- drop_data["type"] = "autoload";
- drop_data["autoloads"] = autoloads;
-
- return drop_data;
-}
-
-bool EditorAutoloadSettings::can_drop_data_fw(const Point2& p_point, const Variant& p_data, Control *p_control) const {
- if (updating_autoload)
- return false;
-
- Dictionary drop_data = p_data;
-
- if (!drop_data.has("type"))
- return false;
-
- if (drop_data.has("type")) {
- TreeItem *ti = tree->get_item_at_pos(p_point);
-
- if (!ti)
- return false;
-
- int section = tree->get_drop_section_at_pos(p_point);
-
- if (section < -1)
- return false;
-
- return true;
- }
-
- return false;
-}
-
-void EditorAutoloadSettings::drop_data_fw(const Point2& p_point, const Variant& p_data, Control *p_control) {
-
- TreeItem *ti = tree->get_item_at_pos(p_point);
-
- if (!ti)
- return;
-
- int section = tree->get_drop_section_at_pos(p_point);
-
- if (section < -1)
- return;
-
- String name;
- bool move_to_back = false;
-
- if (section < 0) {
- name = ti->get_text(0);
- } else if (ti->get_next()) {
- name = ti->get_next()->get_text(0);
- } else {
- name = ti->get_text(0);
- move_to_back = true;
- }
-
- int order = GlobalConfig::get_singleton()->get_order("autoload/" + name);
-
- AutoLoadInfo aux;
- List<AutoLoadInfo>::Element *E = NULL;
-
- if (!move_to_back) {
- aux.order = order;
- E = autoload_cache.find(aux);
- }
-
- Dictionary drop_data = p_data;
- PoolStringArray autoloads = drop_data["autoloads"];
-
- Vector<int> orders;
- orders.resize(autoload_cache.size());
-
- for (int i = 0; i < autoloads.size(); i++) {
- aux.order = GlobalConfig::get_singleton()->get_order("autoload/" + autoloads[i]);
-
- List<AutoLoadInfo>::Element *I = autoload_cache.find(aux);
-
- if (move_to_back) {
- autoload_cache.move_to_back(I);
- } else if (E != I) {
- autoload_cache.move_before(I, E);
- } else if (E->next()) {
- E = E->next();
- } else {
- break;
- }
- }
-
- int i = 0;
-
- for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
- orders[i++] = E->get().order;
- }
-
- orders.sort();
-
- UndoRedo *undo_redo = EditorNode::get_undo_redo();
-
- undo_redo->create_action(TTR("Rearrange Autoloads"));
-
- i = 0;
-
- for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
- undo_redo->add_do_method(GlobalConfig::get_singleton(), "set_order", E->get().name, orders[i++]);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(), "set_order", E->get().name, E->get().order);
- }
-
- orders.clear();
-
- undo_redo->add_do_method(this, "update_autoload");
- undo_redo->add_undo_method(this, "update_autoload");
-
- undo_redo->add_do_method(this, "emit_signal", autoload_changed);
- undo_redo->add_undo_method(this, "emit_signal", autoload_changed);
-
- undo_redo->commit_action();
-}
-
-void EditorAutoloadSettings::_bind_methods() {
-
- ClassDB::bind_method("_autoload_add", &EditorAutoloadSettings::_autoload_add);
- ClassDB::bind_method("_autoload_selected", &EditorAutoloadSettings::_autoload_selected);
- ClassDB::bind_method("_autoload_edited", &EditorAutoloadSettings::_autoload_edited);
- ClassDB::bind_method("_autoload_button_pressed", &EditorAutoloadSettings::_autoload_button_pressed);
- ClassDB::bind_method("_autoload_file_callback", &EditorAutoloadSettings::_autoload_file_callback);
-
- ClassDB::bind_method("get_drag_data_fw", &EditorAutoloadSettings::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw", &EditorAutoloadSettings::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw", &EditorAutoloadSettings::drop_data_fw);
-
- ClassDB::bind_method("update_autoload", &EditorAutoloadSettings::update_autoload);
-
- ADD_SIGNAL(MethodInfo("autoload_changed"));
-}
-
-EditorAutoloadSettings::EditorAutoloadSettings() {
-
- autoload_changed = "autoload_changed";
-
- updating_autoload = false;
- selected_autoload = "";
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- add_child(hbc);
-
- VBoxContainer *vbc_path = memnew( VBoxContainer );
- vbc_path->set_h_size_flags(SIZE_EXPAND_FILL);
-
- autoload_add_path = memnew( EditorLineEditFileChooser );
- autoload_add_path->set_h_size_flags(SIZE_EXPAND_FILL);
-
- autoload_add_path->get_file_dialog()->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- autoload_add_path->get_file_dialog()->connect("file_selected", this, "_autoload_file_callback");
-
- vbc_path->add_margin_child(TTR("Path:"), autoload_add_path);
- hbc->add_child(vbc_path);
-
- VBoxContainer *vbc_name = memnew( VBoxContainer );
- vbc_name->set_h_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *hbc_name = memnew( HBoxContainer );
-
- autoload_add_name = memnew( LineEdit );
- autoload_add_name->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc_name->add_child(autoload_add_name);
-
- Button *add_autoload = memnew( Button );
- add_autoload->set_text(TTR("Add"));
- hbc_name->add_child(add_autoload);
- add_autoload->connect("pressed", this, "_autoload_add");
-
- vbc_name->add_margin_child(TTR("Node Name:"), hbc_name);
- hbc->add_child(vbc_name);
-
- tree = memnew( Tree );
- tree->set_hide_root(true);
- tree->set_select_mode(Tree::SELECT_MULTI);
- tree->set_single_select_cell_editing_only_when_already_selected(true);
-
- tree->set_drag_forwarding(this);
-
- tree->set_columns(4);
- tree->set_column_titles_visible(true);
-
- tree->set_column_title(0,TTR("Name"));
- tree->set_column_expand(0,true);
- tree->set_column_min_width(0,100);
-
- tree->set_column_title(1,TTR("Path"));
- tree->set_column_expand(1,true);
- tree->set_column_min_width(1,100);
-
- tree->set_column_title(2,TTR("Singleton"));
- tree->set_column_expand(2,false);
- tree->set_column_min_width(2,80);
-
- tree->set_column_expand(3,false);
- tree->set_column_min_width(3,80);
-
- tree->connect("cell_selected", this, "_autoload_selected");
- tree->connect("item_edited", this, "_autoload_edited");
- tree->connect("button_pressed", this, "_autoload_button_pressed");
-
- add_margin_child(TTR("List:"), tree, true);
-}
-
diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp
deleted file mode 100644
index ef839d7e74..0000000000
--- a/tools/editor/editor_data.cpp
+++ /dev/null
@@ -1,979 +0,0 @@
-/*************************************************************************/
-/* editor_data.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_data.h"
-
-#include "globals.h"
-#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() {
-
- for(int i=0;i<history.size();i++) {
-
- bool fail=false;
-
- for(int j=0;j<history[i].path.size();j++) {
- if (!history[i].path[j].ref.is_null())
- continue;
-
- if (ObjectDB::get_instance(history[i].path[j].object))
- continue; //has isntance, try next
-
- if (j<=history[i].level) {
- //before or equal level, complete fail
- fail=true;
- } else {
- //after level, clip
- history[i].path.resize(j);
- }
-
- break;
- }
-
- if (fail) {
- history.remove(i);
- i--;
- }
- }
-
- if (current>=history.size())
- current=history.size()-1;
-}
-
-void EditorHistory::_add_object(ObjectID p_object,const String& p_property,int p_level_change) {
-
- Object *obj = ObjectDB::get_instance(p_object);
- ERR_FAIL_COND(!obj);
- Reference *r = obj->cast_to<Reference>();
- Obj o;
- if (r)
- o.ref=REF(r);
- o.object=p_object;
- o.property=p_property;
-
- History h;
-
- bool has_prev = current>=0 && current<history.size();
-
- if (has_prev) {
- history.resize(current+1); //clip history to next
- }
-
- if (p_property!="" && has_prev) {
- //add a sub property
- History &pr = history[current];
- h=pr;
- h.path.resize(h.level+1);
- h.path.push_back(o);
- h.level++;
- } else if (p_level_change!=-1 && has_prev) {
- //add a sub property
- History &pr = history[current];
- h=pr;
- ERR_FAIL_INDEX(p_level_change,h.path.size());
- h.level=p_level_change;
- } else {
- //add a new node
- h.path.push_back(o);
- h.level=0;
- }
-
- history.push_back(h);
- current++;
-}
-
-void EditorHistory::add_object(ObjectID p_object) {
-
- _add_object(p_object,"",-1);
-}
-
-void EditorHistory::add_object(ObjectID p_object,const String& p_subprop) {
-
- _add_object(p_object,p_subprop,-1);
-}
-
-void EditorHistory::add_object(ObjectID p_object,int p_relevel){
-
- _add_object(p_object,"",p_relevel);
-}
-
-int EditorHistory::get_history_len() {
- return history.size();
-}
-int EditorHistory::get_history_pos() {
- return current;
-}
-
-ObjectID EditorHistory::get_history_obj(int p_obj) const {
- ERR_FAIL_INDEX_V(p_obj,history.size(),0);
- ERR_FAIL_INDEX_V(history[p_obj].level,history[p_obj].path.size(),0);
- return history[p_obj].path[history[p_obj].level].object;
-}
-
-bool EditorHistory::is_at_begining() const {
- return current<=0;
-}
-bool EditorHistory::is_at_end() const {
-
- return ((current+1)>=history.size());
-}
-
-
-bool EditorHistory::next() {
-
-
- _cleanup_history();
-
- if ((current+1)<history.size())
- current++;
- else
- return false;
-
- return true;
-}
-
-bool EditorHistory::previous() {
-
-
- _cleanup_history();
-
- if (current>0)
- current--;
- else
- return false;
-
- return true;
-}
-
-ObjectID EditorHistory::get_current() {
-
-
- if (current<0 || current >=history.size())
- return 0;
-
- History &h=history[current];
- Object *obj = ObjectDB::get_instance(h.path[h.level].object);
- if (!obj)
- return 0;
-
- return obj->get_instance_ID();
-}
-
-int EditorHistory::get_path_size() const {
-
- if (current<0 || current >=history.size())
- return 0;
-
- const History &h=history[current];
- return h.path.size();
-
-}
-
-ObjectID EditorHistory::get_path_object(int p_index) const {
-
- if (current<0 || current >=history.size())
- return 0;
-
- const History &h=history[current];
-
- ERR_FAIL_INDEX_V(p_index,h.path.size(),0);
-
- Object *obj = ObjectDB::get_instance(h.path[p_index].object);
- if (!obj)
- return 0;
-
- return obj->get_instance_ID();
-}
-
-String EditorHistory::get_path_property(int p_index) const {
-
- if (current<0 || current >=history.size())
- return "";
-
- const History &h=history[current];
-
- ERR_FAIL_INDEX_V(p_index,h.path.size(),"");
-
- return h.path[p_index].property;
-
-}
-
-void EditorHistory::clear() {
-
- history.clear();
- current=-1;
-}
-
-EditorHistory::EditorHistory() {
-
- current=-1;
-}
-
-EditorPlugin* EditorData::get_editor(Object *p_object) {
-
- for (int i=0;i<editor_plugins.size();i++) {
-
- if (editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object))
- return editor_plugins[i];
- }
-
- return NULL;
-}
-
-EditorPlugin* EditorData::get_subeditor(Object *p_object) {
-
- for (int i=0;i<editor_plugins.size();i++) {
-
- if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object))
- return editor_plugins[i];
- }
-
- return NULL;
-}
-
-Vector<EditorPlugin*> EditorData::get_subeditors(Object* p_object) {
- Vector<EditorPlugin*> sub_plugins;
- for (int i = 0; i < editor_plugins.size(); i++) {
- if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object)) {
- sub_plugins.push_back(editor_plugins[i]);
- }
- }
- return sub_plugins;
-}
-
-EditorPlugin* EditorData::get_editor(String p_name) {
-
- for(int i=0;i<editor_plugins.size();i++) {
-
- if (editor_plugins[i]->get_name()==p_name)
- return editor_plugins[i];
- }
-
- return NULL;
-}
-
-void EditorData::copy_object_params(Object *p_object) {
-
- clipboard.clear();
-
- List<PropertyInfo> pinfo;
- p_object->get_property_list(&pinfo);
-
- for( List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
-
- if (!(E->get().usage&PROPERTY_USAGE_EDITOR))
- continue;
-
- PropertyData pd;
- pd.name=E->get().name;
- pd.value=p_object->get(pd.name);
- clipboard.push_back(pd);
- }
-}
-
-void EditorData::get_editor_breakpoints(List<String> *p_breakpoints) {
-
-
- for(int i=0;i<editor_plugins.size();i++) {
-
- editor_plugins[i]->get_breakpoints(p_breakpoints);
- }
-
-
-}
-
-Dictionary EditorData::get_editor_states() const {
-
- Dictionary metadata;
- for(int i=0;i<editor_plugins.size();i++) {
-
- Dictionary state=editor_plugins[i]->get_state();
- if (state.empty())
- continue;
- metadata[editor_plugins[i]->get_name()]=state;
- }
-
- return metadata;
-
-}
-
-Dictionary EditorData::get_scene_editor_states(int p_idx) const
-{
- ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),Dictionary());
- EditedScene es = edited_scene[p_idx];
- return es.editor_states;
-}
-
-void EditorData::set_editor_states(const Dictionary& p_states) {
-
- List<Variant> keys;
- p_states.get_key_list(&keys);
-
- List<Variant>::Element *E=keys.front();
- for(;E;E=E->next()) {
-
- String name = E->get();
- int idx=-1;
- for(int i=0;i<editor_plugins.size();i++) {
-
- if (editor_plugins[i]->get_name()==name) {
- idx=i;
- break;
- }
- }
-
- if (idx==-1)
- continue;
- editor_plugins[idx]->set_state(p_states[name]);
- }
-
-}
-
-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++) {
-
- editor_plugins[i]->clear();
- }
-
-}
-
-void EditorData::save_editor_external_data() {
-
- for(int i=0;i<editor_plugins.size();i++) {
-
- editor_plugins[i]->save_external_data();
- }
-}
-
-void EditorData::apply_changes_in_editors() {
-
- for(int i=0;i<editor_plugins.size();i++) {
-
- editor_plugins[i]->apply_changes();
- }
-
-}
-
-void EditorData::save_editor_global_states() {
-
- for(int i=0;i<editor_plugins.size();i++) {
-
- editor_plugins[i]->save_global_state();
- }
-}
-
-void EditorData::restore_editor_global_states(){
-
- for(int i=0;i<editor_plugins.size();i++) {
-
- editor_plugins[i]->restore_global_state();
- }
-
-}
-
-
-void EditorData::paste_object_params(Object *p_object) {
-
-
- for( List<PropertyData>::Element *E=clipboard.front();E;E=E->next()) {
-
- p_object->set( E->get().name, E->get().value);
- }
-
-}
-
-
-UndoRedo &EditorData::get_undo_redo() {
-
- return undo_redo;
-}
-
-void EditorData::remove_editor_plugin(EditorPlugin *p_plugin) {
-
- p_plugin->undo_redo=NULL;
- editor_plugins.erase(p_plugin);
-
-}
-
-void EditorData::add_editor_plugin(EditorPlugin *p_plugin) {
-
- p_plugin->undo_redo=&undo_redo;
- editor_plugins.push_back(p_plugin);
-}
-
-int EditorData::get_editor_plugin_count() const {
- return editor_plugins.size();
-}
-EditorPlugin *EditorData::get_editor_plugin(int p_idx) {
-
- ERR_FAIL_INDEX_V(p_idx,editor_plugins.size(),NULL);
- return editor_plugins[p_idx];
-}
-
-
-void EditorData::add_custom_type(const String& p_type, const String& p_inherits,const Ref<Script>& p_script,const Ref<Texture>& p_icon ) {
-
- ERR_FAIL_COND(p_script.is_null());
- CustomType ct;
- ct.name=p_type;
- ct.icon=p_icon;
- ct.script=p_script;
- if (!custom_types.has(p_inherits)) {
- custom_types[p_inherits]=Vector<CustomType>();
- }
-
- custom_types[p_inherits].push_back(ct);
-}
-
-void EditorData::remove_custom_type(const String& p_type){
-
-
- for (Map<String,Vector<CustomType> >::Element *E=custom_types.front();E;E=E->next()) {
-
- for(int i=0;i<E->get().size();i++) {
- if (E->get()[i].name==p_type) {
- E->get().remove(i);
- if (E->get().empty()) {
- custom_types.erase(E->key());
- }
- return;
- }
- }
- }
-
-}
-
-int EditorData::add_edited_scene(int p_at_pos) {
-
- if (p_at_pos<0)
- p_at_pos=edited_scene.size();
- EditedScene es;
- es.root=NULL;
- es.history_current=-1;
- es.version=0;
- es.live_edit_root=NodePath(String("/root"));
-
- if (p_at_pos==edited_scene.size())
- edited_scene.push_back(es);
- else
- edited_scene.insert(p_at_pos,es);
-
- if (current_edited_scene<0)
- current_edited_scene=0;
- return p_at_pos;
-}
-
-void EditorData::move_edited_scene_index(int p_idx,int p_to_idx){
-
- ERR_FAIL_INDEX(p_idx,edited_scene.size());
- ERR_FAIL_INDEX(p_to_idx,edited_scene.size());
- SWAP(edited_scene[p_idx],edited_scene[p_to_idx]);
-}
-void EditorData::remove_scene(int p_idx){
- ERR_FAIL_INDEX(p_idx,edited_scene.size());
- if (edited_scene[p_idx].root)
- memdelete(edited_scene[p_idx].root);
-
- if (current_edited_scene>p_idx)
- current_edited_scene--;
- else if (current_edited_scene==p_idx && current_edited_scene>0) {
- current_edited_scene--;
- }
-
- 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);
-
- print_line("MUST RELOAD? "+itos(must_reload));
-
- if (must_reload) {
- Ref<PackedScene> pscene;
- pscene.instance();
-
- EditorProgress ep("update_scene",TTR("Updating Scene"),2);
- ep.step(TTR("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(TTR("Updating scene.."),1);
- Node *new_scene = pscene->instance(PackedScene::GEN_EDIT_STATE_MAIN);
- 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;
-}
-void EditorData::set_edited_scene(int p_idx){
-
- ERR_FAIL_INDEX(p_idx,edited_scene.size());
- current_edited_scene=p_idx;
- //swap
-}
-Node* EditorData::get_edited_scene_root(int p_idx){
- if (p_idx < 0) {
- ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),NULL);
- return edited_scene[current_edited_scene].root;
- } else {
- ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),NULL);
- return edited_scene[p_idx].root;
- }
-}
-void EditorData::set_edited_scene_root(Node* p_root) {
-
- ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
- edited_scene[current_edited_scene].root=p_root;
-}
-
-int EditorData::get_edited_scene_count() const {
-
- return edited_scene.size();
-}
-
-void EditorData::set_edited_scene_version(uint64_t version, int scene_idx) {
- ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
- if (scene_idx < 0) {
- edited_scene[current_edited_scene].version=version;
- } else {
- ERR_FAIL_INDEX(scene_idx,edited_scene.size());
- edited_scene[scene_idx].version=version;
- }
-
-}
-
-uint64_t EditorData::get_edited_scene_version() const{
-
- ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),0);
- return edited_scene[current_edited_scene].version;
-
-}
-uint64_t EditorData::get_scene_version(int p_idx) const{
- ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),false);
- return edited_scene[p_idx].version;
-}
-
-String EditorData::get_scene_type(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
- if (!edited_scene[p_idx].root)
- return "";
- return edited_scene[p_idx].root->get_class();
-
-}
-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 {
-
- ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),Ref<Script>());
- if (!edited_scene[p_idx].root)
- return Ref<Script>();
- Ref<Script> s=edited_scene[p_idx].root->get_script();
- if (!s.is_valid() && edited_scene[p_idx].root->get_child_count()) {
- Node *n = edited_scene[p_idx].root->get_child(0);
- while(!s.is_valid() && n && n->get_filename()==String()) {
- s=n->get_script();
- n=n->get_parent();
- }
- }
- return s;
-}
-
-String EditorData::get_scene_title(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
- if (!edited_scene[p_idx].root)
- return "[empty]";
- if (edited_scene[p_idx].root->get_filename()=="")
- return "[unsaved]";
- return edited_scene[p_idx].root->get_filename().get_file();
-}
-
-
-String EditorData::get_scene_path(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
-
- if (!edited_scene[p_idx].root)
- return "";
- return edited_scene[p_idx].root->get_filename();
-
-}
-
-void EditorData::set_edited_scene_live_edit_root(const NodePath& p_root) {
- ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
-
- edited_scene[current_edited_scene].live_edit_root=p_root;
-
-}
-NodePath EditorData::get_edited_scene_live_edit_root() {
-
- ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),String());
-
- return edited_scene[current_edited_scene].live_edit_root;
-
-
-
-}
-
-
-void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history, const Dictionary& p_custom) {
-
- ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
-
- EditedScene &es=edited_scene[current_edited_scene];
- es.selection = p_selection->get_selected_node_list();
- es.history_current=p_history->current;
- es.history_stored=p_history->history;
- es.editor_states=get_editor_states();
- es.custom_state=p_custom;
-
-}
-
-Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history) {
- ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),Dictionary());
-
- EditedScene &es=edited_scene[current_edited_scene];
-
- p_history->current=es.history_current;
- p_history->history=es.history_stored;
-
-
- p_selection->clear();
- for(List<Node*>::Element *E=es.selection.front();E;E=E->next()) {
- p_selection->add_node(E->get());
- }
- set_editor_states(es.editor_states);
-
- return es.custom_state;
-}
-
-
-void EditorData::clear_edited_scenes() {
-
- for(int i=0;i<edited_scene.size();i++) {
- if (edited_scene[i].root) {
- memdelete( edited_scene[i].root );
- }
- }
- edited_scene.clear();
-}
-
-
-
-void EditorData::set_plugin_window_layout(Ref<ConfigFile> p_layout) {
- for(int i=0;i<editor_plugins.size();i++) {
- editor_plugins[i]->set_window_layout(p_layout);
- }
-}
-
-void EditorData::get_plugin_window_layout(Ref<ConfigFile> p_layout) {
- for(int i=0;i<editor_plugins.size();i++) {
- editor_plugins[i]->get_window_layout(p_layout);
- }
-}
-
-EditorData::EditorData() {
-
- current_edited_scene=-1;
-
- //load_imported_scenes_from_globals();
-}
-
-///////////
-void EditorSelection::_node_removed(Node *p_node) {
-
- if (!selection.has(p_node))
- return;
-
- Object *meta = selection[p_node];
- if (meta)
- memdelete(meta);
- selection.erase(p_node);
- changed=true;
- nl_changed=true;
-}
-
-void EditorSelection::add_node(Node *p_node) {
-
- ERR_FAIL_NULL(p_node);
- ERR_FAIL_COND(!p_node->is_inside_tree());
- if (selection.has(p_node))
- return;
-
- changed=true;
- nl_changed=true;
- Object *meta=NULL;
- for(List<Object*>::Element *E=editor_plugins.front();E;E=E->next()) {
-
- meta = E->get()->call("_get_editor_data",p_node);
- if (meta) {
- break;
- }
-
- }
- selection[p_node]=meta;
-
- p_node->connect("tree_exited",this,"_node_removed",varray(p_node),CONNECT_ONESHOT);
-
- //emit_signal("selection_changed");
-}
-
-void EditorSelection::remove_node(Node *p_node) {
-
- ERR_FAIL_NULL(p_node);
-
- if (!selection.has(p_node))
- return;
-
- changed=true;
- nl_changed=true;
- Object *meta = selection[p_node];
- if (meta)
- memdelete(meta);
- selection.erase(p_node);
- p_node->disconnect("tree_exited",this,"_node_removed");
- //emit_signal("selection_changed");
-}
-bool EditorSelection::is_selected(Node * p_node) const {
-
- return selection.has(p_node);
-}
-
-Array EditorSelection::_get_transformable_selected_nodes() {
-
- Array ret;
-
- for (List<Node*>::Element *E=selected_node_list.front();E;E=E->next()) {
-
- ret.push_back(E->get());
- }
-
- return ret;
-}
-
-Array EditorSelection::_get_selected_nodes() {
-
- Array ret;
-
- for (Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- ret.push_back(E->key());
- }
-
- return ret;
-}
-
-void EditorSelection::_bind_methods() {
-
- ClassDB::bind_method(_MD("_node_removed"),&EditorSelection::_node_removed);
- ClassDB::bind_method(_MD("clear"),&EditorSelection::clear);
- ClassDB::bind_method(_MD("add_node","node:Node"),&EditorSelection::add_node);
- ClassDB::bind_method(_MD("remove_node","node:Node"),&EditorSelection::remove_node);
- ClassDB::bind_method(_MD("get_selected_nodes"),&EditorSelection::_get_selected_nodes);
- ClassDB::bind_method(_MD("get_transformable_selected_nodes"),&EditorSelection::_get_transformable_selected_nodes);
- ADD_SIGNAL( MethodInfo("selection_changed") );
-
-}
-
-void EditorSelection::add_editor_plugin(Object *p_object) {
-
- editor_plugins.push_back(p_object);
-}
-
-void EditorSelection::_update_nl() {
-
- if (!nl_changed)
- return;
-
- selected_node_list.clear();
-
- for (Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
-
- Node *parent = E->key();
- parent=parent->get_parent();
- bool skip=false;
- while (parent) {
- if (selection.has(parent)) {
- skip=true;
- break;
- }
- parent=parent->get_parent();
- }
-
- if (skip)
- continue;
- selected_node_list.push_back(E->key());
- }
-
- nl_changed=true;
-}
-
-void EditorSelection::update() {
-
- _update_nl();
-
- if (!changed)
- return;
- emit_signal("selection_changed");
- changed=false;
-
-
-}
-
-List<Node*>& EditorSelection::get_selected_node_list() {
-
- if (changed)
- update();
- else
- _update_nl();
- return selected_node_list;
-}
-
-
-
-
-void EditorSelection::clear() {
-
- while( !selection.empty() ) {
-
- remove_node(selection.front()->key());
- }
-
-
- changed=true;
- nl_changed=true;
-
-}
-EditorSelection::EditorSelection() {
-
- changed=false;
- nl_changed=false;
-
-}
-
-EditorSelection::~EditorSelection() {
-
- clear();
-}
diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h
deleted file mode 100644
index fce606f722..0000000000
--- a/tools/editor/editor_data.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/*************************************************************************/
-/* editor_data.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_DATA_H
-#define EDITOR_DATA_H
-
-#include "tools/editor/editor_plugin.h"
-#include "scene/resources/texture.h"
-#include "list.h"
-#include "undo_redo.h"
-#include "pair.h"
-
-class EditorHistory {
-
- enum {
-
- HISTORY_MAX=64
- };
-
- struct Obj {
-
- REF ref;
- ObjectID object;
- String property;
- };
-
- struct History {
-
- Vector<Obj> path;
- int level;
- };
-friend class EditorData;
-
- Vector<History> history;
- int current;
-
- //Vector<EditorPlugin*> editor_plugins;
-
- struct PropertyData {
-
- String name;
- Variant value;
- };
-
-
- void _cleanup_history();
-
- void _add_object(ObjectID p_object,const String& p_property,int p_level_change);
-
-public:
-
- bool is_at_begining() const;
- bool is_at_end() const;
-
- void add_object(ObjectID p_object);
- void add_object(ObjectID p_object,const String& p_subprop);
- void add_object(ObjectID p_object,int p_relevel);
-
- int get_history_len();
- int get_history_pos();
- ObjectID get_history_obj(int p_obj) const;
-
- bool next();
- bool previous();
- ObjectID get_current();
-
- int get_path_size() const;
- ObjectID get_path_object(int p_index) const;
- String get_path_property(int p_index) const;
-
- void clear();
-
- EditorHistory();
-};
-
-class EditorSelection;
-
-class EditorData {
-
-public:
- struct CustomType {
-
- String name;
- Ref<Script> script;
- Ref<Texture> icon;
- };
-private:
-
- Vector<EditorPlugin*> editor_plugins;
-
- struct PropertyData {
-
- String name;
- Variant value;
- };
- Map<String,Vector<CustomType> > custom_types;
-
- List<PropertyData> clipboard;
- UndoRedo undo_redo;
-
-
- void _cleanup_history();
-
- struct EditedScene {
- Node* root;
- Dictionary editor_states;
- List<Node*> selection;
- Vector<EditorHistory::History> history_stored;
- int history_current;
- Dictionary custom_state;
- uint64_t version;
- NodePath live_edit_root;
-
-
- };
-
- 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);
- EditorPlugin* get_subeditor(Object *p_object);
- Vector<EditorPlugin*> get_subeditors(Object *p_object);
- EditorPlugin* get_editor(String p_name);
-
- void copy_object_params(Object *p_object);
- void paste_object_params(Object *p_object);
-
- Dictionary get_editor_states() const;
- Dictionary get_scene_editor_states(int p_idx) const;
- void set_editor_states(const Dictionary& p_states);
- void get_editor_breakpoints(List<String> *p_breakpoints);
- void clear_editor_states();
- void save_editor_external_data();
- void apply_changes_in_editors();
-
- void add_editor_plugin(EditorPlugin *p_plugin);
- void remove_editor_plugin(EditorPlugin *p_plugin);
-
- int get_editor_plugin_count() const;
- EditorPlugin *get_editor_plugin(int p_idx);
-
- UndoRedo &get_undo_redo();
-
- void save_editor_global_states();
- void restore_editor_global_states();
-
- void add_custom_type(const String& p_type, const String& p_inherits,const Ref<Script>& p_script,const Ref<Texture>& p_icon );
- void remove_custom_type(const String& p_type);
- const Map<String,Vector<CustomType> >& get_custom_types() const { return custom_types; }
-
-
- int add_edited_scene(int p_at_pos);
- void move_edited_scene_index(int p_idx,int p_to_idx);
- void remove_scene(int p_idx);
- void set_edited_scene(int p_idx);
- void set_edited_scene_root(Node* p_root);
- int get_edited_scene() const;
- Node* get_edited_scene_root(int p_idx = -1);
- int get_edited_scene_count() const;
- String get_scene_title(int p_idx) const;
- String get_scene_path(int p_idx) const;
- String get_scene_type(int p_idx) const;
- Ref<Script> get_scene_root_script(int p_idx) const;
- void set_edited_scene_version(uint64_t version, int p_scene_idx = -1);
- uint64_t get_edited_scene_version() const;
- uint64_t get_scene_version(int p_idx) const;
- 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);
- void get_plugin_window_layout(Ref<ConfigFile> p_layout);
-
- 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();
-};
-
-
-
-class EditorSelection : public Object {
-
- GDCLASS(EditorSelection,Object);
-public:
-
- Map<Node*,Object*> selection;
-
- bool changed;
- bool nl_changed;
-
- void _node_removed(Node *p_node);
-
- List<Object*> editor_plugins;
- List<Node*> selected_node_list;
-
- void _update_nl();
- Array _get_selected_nodes();
- Array _get_transformable_selected_nodes();
-
-protected:
-
- static void _bind_methods();
-public:
-
- void add_node(Node *p_node);
- void remove_node(Node *p_node);
- bool is_selected(Node *) const;
-
- template<class T>
- T* get_node_editor_data(Node *p_node) {
- if (!selection.has(p_node))
- return NULL;
- Object *obj = selection[p_node];
- if (!obj)
- return NULL;
- return obj->cast_to<T>();
- }
-
- void add_editor_plugin(Object *p_object);
-
- void update();
- void clear();
-
-
- List<Node*>& get_selected_node_list();
- Map<Node*,Object*>& get_selection() { return selection; }
-
-
- EditorSelection();
- ~EditorSelection();
-};
-
-
-#endif // EDITOR_DATA_H
diff --git a/tools/editor/editor_dir_dialog.cpp b/tools/editor/editor_dir_dialog.cpp
deleted file mode 100644
index bb9ddc2aef..0000000000
--- a/tools/editor/editor_dir_dialog.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*************************************************************************/
-/* editor_dir_dialog.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_dir_dialog.h"
-
-#include "os/os.h"
-#include "os/keyboard.h"
-#include "tools/editor/editor_settings.h"
-#include "tools/editor/editor_file_system.h"
-
-
-void EditorDirDialog::_update_dir(TreeItem* p_item) {
-
- updating=true;
- p_item->clear_children();
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- String cdir = p_item->get_metadata(0);
-
- da->change_dir(cdir);
- da->list_dir_begin();
- String p=da->get_next();
-
- List<String> dirs;
- bool ishidden;
- bool show_hidden = EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files");
-
- while(p!="") {
-
- ishidden = da->current_is_hidden();
-
- if (show_hidden || !ishidden) {
- if (da->current_is_dir() && !p.begins_with(".")) {
- dirs.push_back(p);
- }
- }
- p=da->get_next();
- }
-
- dirs.sort();
-
- for(List<String>::Element *E=dirs.front();E;E=E->next()) {
- TreeItem *ti = tree->create_item(p_item);
- ti->set_text(0,E->get());
- ti->set_icon(0,get_icon("Folder","EditorIcons"));
- ti->set_collapsed(true);
-
- }
-
- memdelete(da);
- updating=false;
-
-}
-
-
-void EditorDirDialog::reload() {
-
- if (!is_visible_in_tree()) {
- must_reload=true;
- return;
- }
-
- tree->clear();
- TreeItem *root = tree->create_item();
- root->set_metadata(0,"res://");
- root->set_icon(0,get_icon("Folder","EditorIcons"));
- root->set_text(0,"/");
- _update_dir(root);
- _item_collapsed(root);
- must_reload=false;
-
-}
-
-
-void EditorDirDialog::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- reload();
-
- if (!tree->is_connected("item_collapsed",this,"_item_collapsed")) {
- tree->connect("item_collapsed",this,"_item_collapsed",varray(),CONNECT_DEFERRED);
- }
-
- if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed",this,"reload")) {
- EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"reload");
- }
-
- }
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
- if (must_reload && is_visible_in_tree()) {
- reload();
- }
- }
-}
-
-void EditorDirDialog::_item_collapsed(Object* _p_item){
-
- TreeItem *p_item=_p_item->cast_to<TreeItem>();
-
- if (updating || p_item->is_collapsed())
- return;
-
- TreeItem *ci = p_item->get_children();
- while(ci) {
-
- String p =ci->get_metadata(0);
- if (p=="") {
- String pp = p_item->get_metadata(0);
- ci->set_metadata(0,pp.plus_file(ci->get_text(0)));
- _update_dir(ci);
- }
- ci=ci->get_next();
- }
-
-}
-
-void EditorDirDialog::set_current_path(const String& p_path) {
-
- reload();
- String p = p_path;
- if (p.begins_with("res://"))
- p = p.replace_first("res://","");
-
- Vector<String> dirs = p.split("/",false);
-
- TreeItem *r=tree->get_root();
- for(int i=0;i<dirs.size();i++) {
-
- String d = dirs[i];
- TreeItem *p = r->get_children();
- while(p) {
-
- if (p->get_text(0)==d)
- break;
- p=p->get_next();
- }
-
- ERR_FAIL_COND(!p);
- String pp = p->get_metadata(0);
- if (pp=="") {
- p->set_metadata(0,String(r->get_metadata(0)).plus_file(d));
- _update_dir(p);
- }
- updating=true;
- p->set_collapsed(false);
- updating=false;
- _item_collapsed(p);
- r=p;
- }
-
- r->select(0);
-
-}
-
-void EditorDirDialog::ok_pressed() {
-
- TreeItem *ti=tree->get_selected();
- if (!ti)
- return;
-
- String dir = ti->get_metadata(0);
- emit_signal("dir_selected",dir);
- hide();
-}
-
-
-void EditorDirDialog::_make_dir() {
-
- TreeItem *ti=tree->get_selected();
- if (!ti) {
- mkdirerr->set_text("Please select a base directory first");
- mkdirerr->popup_centered_minsize();
- return;
- }
-
- makedialog->popup_centered_minsize(Size2(250,80));
- makedirname->grab_focus();
-}
-
-void EditorDirDialog::_make_dir_confirm() {
-
- TreeItem *ti=tree->get_selected();
- if (!ti)
- return;
-
- String dir = ti->get_metadata(0);
-
- DirAccess *d = DirAccess::open(dir);
- ERR_FAIL_COND(!d);
- Error err = d->make_dir(makedirname->get_text());
-
- if (err!=OK) {
- mkdirerr->popup_centered_minsize(Size2(250,80));
- } else {
- set_current_path(dir.plus_file(makedirname->get_text()));
- }
- makedirname->set_text(""); // reset label
-}
-
-
-void EditorDirDialog::_bind_methods() {
-
- ClassDB::bind_method(_MD("_item_collapsed"),&EditorDirDialog::_item_collapsed);
- ClassDB::bind_method(_MD("_make_dir"),&EditorDirDialog::_make_dir);
- ClassDB::bind_method(_MD("_make_dir_confirm"),&EditorDirDialog::_make_dir_confirm);
- ClassDB::bind_method(_MD("reload"),&EditorDirDialog::reload);
-
- ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo(Variant::STRING,"dir")));
-}
-
-
-
-EditorDirDialog::EditorDirDialog() {
-
- updating=false;
-
- set_title(TTR("Choose a Directory"));
- set_hide_on_ok(false);
-
- tree = memnew( Tree );
- add_child(tree);
-
- tree->connect("item_activated",this,"_ok");
-
- makedir = add_button(TTR("Create Folder"),OS::get_singleton()->get_swap_ok_cancel()?true:false,"makedir");
- makedir->connect("pressed",this,"_make_dir");
-
- makedialog = memnew( ConfirmationDialog );
- makedialog->set_title(TTR("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(TTR("Name:"),makedirname);
- makedialog->register_text_enter(makedirname);
- makedialog->connect("confirmed",this,"_make_dir_confirm");
-
- mkdirerr = memnew( AcceptDialog );
- mkdirerr->set_text(TTR("Could not create folder."));
- add_child(mkdirerr);
-
- get_ok()->set_text(TTR("Choose"));
-
- must_reload=false;
-
-
-
-}
diff --git a/tools/editor/editor_file_dialog.cpp b/tools/editor/editor_file_dialog.cpp
deleted file mode 100644
index e23e2419d8..0000000000
--- a/tools/editor/editor_file_dialog.cpp
+++ /dev/null
@@ -1,1531 +0,0 @@
-/*************************************************************************/
-/* editor_file_dialog.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_file_dialog.h"
-
-#include "scene/gui/label.h"
-#include "scene/gui/center_container.h"
-#include "print_string.h"
-#include "os/keyboard.h"
-#include "editor_resource_preview.h"
-#include "editor_settings.h"
-#include "scene/gui/margin_container.h"
-#include "os/file_access.h"
-#include "editor_scale.h"
-
-EditorFileDialog::GetIconFunc EditorFileDialog::get_icon_func=NULL;
-EditorFileDialog::GetIconFunc EditorFileDialog::get_large_icon_func=NULL;
-
-EditorFileDialog::RegisterFunc EditorFileDialog::register_func=NULL;
-EditorFileDialog::RegisterFunc EditorFileDialog::unregister_func=NULL;
-
-
-VBoxContainer *EditorFileDialog::get_vbox() {
- return vbox;
-
-}
-
-void EditorFileDialog::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- mode_thumbnails->set_icon(get_icon("FileThumbnail","EditorIcons"));
- mode_list->set_icon(get_icon("FileList","EditorIcons"));
- 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"));
-
- } else if (p_what==NOTIFICATION_PROCESS) {
-
- if (preview_waiting) {
- preview_wheel_timeout-=get_process_delta_time();
- if (preview_wheel_timeout<=0) {
- preview_wheel_index++;
- if (preview_wheel_index>=8)
- preview_wheel_index=0;
- Ref<Texture> frame = get_icon("WaitPreview"+itos(preview_wheel_index+1),"EditorIcons");
- preview->set_texture(frame);
- preview_wheel_timeout=0.1;
- }
- }
- } 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("filesystem/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("filesystem/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()) {
-
- if (p_event.key.pressed) {
-
- bool handled=false;
-
- if (ED_IS_SHORTCUT("file_dialog/go_back", p_event)) {
- _go_back();
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/go_forward", p_event)) {
- _go_forward();
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/go_up", p_event)) {
- _go_up();
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/refresh", p_event)) {
- invalidate();
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/toggle_hidden_files", p_event)) {
- bool show=!show_hidden_files;
- set_show_hidden_files(show);
- EditorSettings::get_singleton()->set("filesystem/file_dialog/show_hidden_files",show);
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/toggle_favorite", p_event)) {
- _favorite_toggled(favorite->is_pressed());
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/toggle_mode", p_event)) {
- if (mode_thumbnails->is_pressed()) {
- set_display_mode(DISPLAY_LIST);
- } else {
- set_display_mode(DISPLAY_THUMBNAILS);
- }
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/create_folder", p_event)) {
- _make_dir();
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) {
- dir->grab_focus();
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/move_favorite_up", p_event)) {
- _favorite_move_up();
- handled=true;
- }
- if (ED_IS_SHORTCUT("file_dialog/move_favorite_down", p_event)) {
- _favorite_move_down();
- handled=true;
- }
-
- if (handled) {
- accept_event();
- }
- }
- }
-}
-
-void EditorFileDialog::set_enable_multiple_selection(bool p_enable) {
-
- item_list->set_select_mode(p_enable?ItemList::SELECT_MULTI:ItemList::SELECT_SINGLE);
-
-};
-
-Vector<String> EditorFileDialog::get_selected_files() const {
-
- Vector<String> list;
- for(int i=0;i<item_list->get_item_count();i++) {
- if (item_list->is_selected(i))
- list.push_back(item_list->get_item_text(i));
- }
- return list;
-
-};
-
-void EditorFileDialog::update_dir() {
-
- dir->set_text(dir_access->get_current_dir());
-}
-
-void EditorFileDialog::_dir_entered(String p_dir) {
-
-
- dir_access->change_dir(p_dir);
- file->set_text("");
- invalidate();
- update_dir();
- _push_history();
-
-
-}
-
-void EditorFileDialog::_file_entered(const String& p_file) {
-
- _action_pressed();
-}
-
-void EditorFileDialog::_save_confirm_pressed() {
- String f=dir_access->get_current_dir().plus_file(file->get_text());
- _save_to_recent();
- emit_signal("file_selected",f);
- hide();
-}
-
-void EditorFileDialog::_post_popup() {
-
- ConfirmationDialog::_post_popup();
- if (invalidated) {
- update_file_list();
- invalidated=false;
- }
- if (mode==MODE_SAVE_FILE)
- file->grab_focus();
- else
- item_list->grab_focus();
-
- if (is_visible_in_tree() && get_current_file()!="")
- _request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
-
- if (is_visible_in_tree()) {
- Ref<Texture> folder = get_icon("folder","FileDialog");
- recent->clear();
-
-
- bool res = access==ACCESS_RESOURCES;
- Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
- for(int i=0;i<recentd.size();i++) {
- bool cres = recentd[i].begins_with("res://");
- if (cres!=res)
- continue;
- String name = recentd[i];
- if (res && name=="res://") {
- name="/";
- } else {
- name=name.get_file()+"/";
- }
-
- //print_line("file: "+name);
- recent->add_item(name,folder);
- recent->set_item_metadata( recent->get_item_count()-1,recentd[i]);
- }
-
- local_history.clear();
- local_history_pos=-1;
- _push_history();
-
- _update_favorites();
- }
-
- set_process_unhandled_input(true);
-
-}
-
-void EditorFileDialog::_thumbnail_result(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
-
- if (display_mode==DISPLAY_LIST || p_preview.is_null())
- return;
-
- for(int i=0;i<item_list->get_item_count();i++) {
- Dictionary d = item_list->get_item_metadata(i);
- String pname = d["path"];
- if (pname==p_path) {
- item_list->set_item_icon(i,p_preview);
- item_list->set_item_tag_icon(i,Ref<Texture>());
- }
- }
-}
-
-void EditorFileDialog::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
-
- set_process(false);
- preview_waiting=false;
-
- if (p_preview.is_valid() && get_current_path()==p_path) {
-
-
- preview->set_texture(p_preview);
- if (display_mode==DISPLAY_THUMBNAILS) {
- preview_vb->hide();
- } else {
- preview_vb->show();
- }
-
- } else {
- preview_vb->hide();
- preview->set_texture(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);
- preview_waiting=true;
- preview_wheel_timeout=0;
-
-}
-
-void EditorFileDialog::_action_pressed() {
-
- if (mode==MODE_OPEN_FILES) {
-
-
- String fbase=dir_access->get_current_dir();
-
- PoolVector<String> files;
- for(int i=0;i<item_list->get_item_count();i++) {
- if (item_list->is_selected(i))
- files.push_back( fbase.plus_file(item_list->get_item_text(i) ));
- }
-
- if (files.size()) {
- _save_to_recent();
- emit_signal("files_selected",files);
- hide();
- }
-
- return;
- }
-
- String f=dir_access->get_current_dir().plus_file(file->get_text());
-
- if ((mode==MODE_OPEN_ANY || mode==MODE_OPEN_FILE) && dir_access->file_exists(f)) {
- _save_to_recent();
- emit_signal("file_selected",f);
- hide();
- }else if (mode==MODE_OPEN_ANY || mode==MODE_OPEN_DIR) {
-
- String path=dir_access->get_current_dir();
-
- path=path.replace("\\","/");
-
- for(int i=0;i<item_list->get_item_count();i++) {
- if (item_list->is_selected(i)) {
- Dictionary d=item_list->get_item_metadata(i);
- if (d["dir"]) {
- path=path.plus_file(d["name"]);
-
- break;
- }
- }
- }
-
- _save_to_recent();
- emit_signal("dir_selected",path);
- hide();
- }
-
- if (mode==MODE_SAVE_FILE) {
-
- bool valid=false;
-
- if (filter->get_selected()==filter->get_item_count()-1) {
- valid=true; //match none
- } else if (filters.size()>1 && filter->get_selected()==0) {
- // match all filters
- for (int i=0;i<filters.size();i++) {
-
- String flt=filters[i].get_slice(";",0);
- for (int j=0;j<flt.get_slice_count(",");j++) {
-
- String str = flt.get_slice(",",j).strip_edges();
- if (f.match(str)) {
- valid=true;
- break;
- }
- }
- if (valid)
- break;
- }
- } else {
- int idx=filter->get_selected();
- if (filters.size()>1)
- idx--;
- if (idx>=0 && idx<filters.size()) {
-
- String flt=filters[idx].get_slice(";",0);
- int filterSliceCount=flt.get_slice_count(",");
- for (int j=0;j<filterSliceCount;j++) {
-
- String str = (flt.get_slice(",",j).strip_edges());
- if (f.match(str)) {
- valid=true;
- break;
- }
- }
-
- if (!valid && filterSliceCount>0) {
- String str = (flt.get_slice(",",0).strip_edges());
- f+=str.substr(1, str.length()-1);
- _request_single_thumbnail(get_current_dir().plus_file(f.get_file()));
- file->set_text(f.get_file());
- valid=true;
- }
- } else {
- valid=true;
- }
- }
-
-
- if (!valid) {
-
- exterr->popup_centered_minsize(Size2(250,80)*EDSCALE);
- return;
-
- }
-
- if (dir_access->file_exists(f) && !disable_overwrite_warning) {
- confirm_save->set_text(TTR("File Exists, Overwrite?"));
- confirm_save->popup_centered(Size2(200,80));
- } else {
-
- _save_to_recent();
- emit_signal("file_selected",f);
- hide();
- }
- }
-}
-
-void EditorFileDialog::_cancel_pressed() {
-
- file->set_text("");
- invalidate();
- hide();
-}
-
-void EditorFileDialog::_item_selected(int p_item) {
-
- int current = p_item;
- if (current<0 || current>=item_list->get_item_count())
- return;
-
- Dictionary d=item_list->get_item_metadata(current);
-
- if (!d["dir"]) {
-
- file->set_text(d["name"]);
- _request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
- }
-}
-
-void EditorFileDialog::_push_history() {
-
- local_history.resize(local_history_pos+1);
- String new_path = dir_access->get_current_dir();
- if (local_history.size()==0 || new_path!=local_history[local_history_pos]) {
- local_history.push_back(new_path);
- local_history_pos++;
- dir_prev->set_disabled(local_history_pos==0);
- dir_next->set_disabled(true);
- }
-
-}
-void EditorFileDialog::_item_dc_selected(int p_item) {
-
-
- int current = p_item;
- if (current<0 || current>=item_list->get_item_count())
- return;
-
- Dictionary d=item_list->get_item_metadata(current);
-
- if (d["dir"]) {
-
- dir_access->change_dir(d["name"]);
- call_deferred("_update_file_list");
- call_deferred("_update_dir");
-
- _push_history();
-
-
- } else {
-
- _action_pressed();
- }
-}
-
-
-
-void EditorFileDialog::update_file_list() {
-
-
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- Ref<Texture> folder_thumbnail;
- Ref<Texture> file_thumbnail;
-
- item_list->clear();
-
- if (display_mode==DISPLAY_THUMBNAILS) {
-
- item_list->set_max_columns(0);
- item_list->set_icon_mode(ItemList::ICON_MODE_TOP);
- item_list->set_fixed_column_width(thumbnail_size*3/2);
- item_list->set_max_text_lines(2);
- item_list->set_fixed_icon_size(Size2(thumbnail_size,thumbnail_size));
-
- if (!has_icon("ResizedFolder","EditorIcons")) {
- Ref<ImageTexture> folder = get_icon("FolderBig","EditorIcons");
- Image img = folder->get_data();
- img.resize(thumbnail_size,thumbnail_size);
- Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture));
- resized_folder->create_from_image(img,0);
- Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder);
- }
-
- folder_thumbnail = get_icon("ResizedFolder","EditorIcons");
-
- if (!has_icon("ResizedFile","EditorIcons")) {
- Ref<ImageTexture> file = get_icon("FileBig","EditorIcons");
- Image img = file->get_data();
- img.resize(thumbnail_size,thumbnail_size);
- Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture));
- resized_file->create_from_image(img,0);
- Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file);
- }
-
- file_thumbnail = get_icon("ResizedFile","EditorIcons");
-
- preview_vb->hide();
-
- } else {
-
- item_list->set_icon_mode(ItemList::ICON_MODE_LEFT);
- item_list->set_max_columns(1);
- item_list->set_max_text_lines(1);
- item_list->set_fixed_column_width(0);
- item_list->set_fixed_icon_size(Size2());
- if (preview->get_texture().is_valid())
- preview_vb->show();
-
- }
-
- String cdir = dir_access->get_current_dir();
- bool skip_pp = access==ACCESS_RESOURCES && cdir=="res://";
-
- dir_access->list_dir_begin();
-
-
- Ref<Texture> folder = get_icon("folder","FileDialog");
- List<String> files;
- List<String> dirs;
-
- bool isdir;
- bool ishidden;
- bool show_hidden = show_hidden_files;
- String item;
-
- while ((item=dir_access->get_next(&isdir))!="") {
-
- ishidden = dir_access->current_is_hidden();
-
- if (show_hidden || !ishidden) {
- if (!isdir)
- files.push_back(item);
- else if (item!=".." || !skip_pp)
- dirs.push_back(item);
- }
- }
-
- if (dirs.find("..")==NULL) {
- //may happen if lacking permissions
- dirs.push_back("..");
- }
-
- dirs.sort_custom<NoCaseComparator>();
- files.sort_custom<NoCaseComparator>();
-
- while(!dirs.empty()) {
- const String& dir_name=dirs.front()->get();
-
- item_list->add_item(dir_name+"/");
-
- if (display_mode==DISPLAY_THUMBNAILS) {
-
- item_list->set_item_icon(item_list->get_item_count()-1,folder_thumbnail);
- } else {
-
- item_list->set_item_icon(item_list->get_item_count()-1,folder);
- }
-
- Dictionary d;
- d["name"]=dir_name;
- d["path"]=String();
- d["dir"]=true;
-
- item_list->set_item_metadata( item_list->get_item_count() -1, d);
-
- dirs.pop_front();
- }
-
- dirs.clear();
-
- List<String> patterns;
- // build filter
- if (filter->get_selected()==filter->get_item_count()-1) {
-
- // match all
- } else if (filters.size()>1 && filter->get_selected()==0) {
- // match all filters
- for (int i=0;i<filters.size();i++) {
-
- String f=filters[i].get_slice(";",0);
- for (int j=0;j<f.get_slice_count(",");j++) {
-
- patterns.push_back(f.get_slice(",",j).strip_edges());
- }
- }
- } else {
- int idx=filter->get_selected();
- if (filters.size()>1)
- idx--;
-
- if (idx>=0 && idx<filters.size()) {
-
- String f=filters[idx].get_slice(";",0);
- for (int j=0;j<f.get_slice_count(",");j++) {
-
- patterns.push_back(f.get_slice(",",j).strip_edges());
- }
- }
- }
-
-
- String base_dir = dir_access->get_current_dir();
-
-
- while(!files.empty()) {
-
- bool match=patterns.empty();
-
- for(List<String>::Element *E=patterns.front();E;E=E->next()) {
-
- if (files.front()->get().matchn(E->get())) {
-
- match=true;
- break;
- }
- }
-
- if (match) {
- //TreeItem *ti=tree->create_item(root);
- //ti->set_text(0,files.front()->get());
- item_list->add_item(files.front()->get());
-
- if (get_icon_func) {
-
-
- Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
- //ti->set_icon(0,icon);
- if (display_mode==DISPLAY_THUMBNAILS) {
-
- item_list->set_item_icon(item_list->get_item_count()-1,file_thumbnail);
- item_list->set_item_tag_icon(item_list->get_item_count()-1,icon);
- } else {
- item_list->set_item_icon(item_list->get_item_count()-1,icon);
- }
- }
-
- if (mode==MODE_OPEN_DIR) {
- //disabled mode?
- //ti->set_custom_color(0,get_color("files_disabled"));
- //ti->set_selectable(0,false);
- }
- Dictionary d;
- d["name"]=files.front()->get();
- d["dir"]=false;
- String fullpath = base_dir.plus_file(files.front()->get());
-
- if (display_mode==DISPLAY_THUMBNAILS) {
- EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath,this,"_thumbnail_result",fullpath);
- }
- d["path"]=base_dir.plus_file(files.front()->get());
- //ti->set_metadata(0,d);
- item_list->set_item_metadata(item_list->get_item_count()-1,d);
-
- if (file->get_text()==files.front()->get())
- item_list->set_current(item_list->get_item_count()-1);
- }
-
- files.pop_front();
- }
-
- if (favorites->get_current()>=0) {
- favorites->unselect(favorites->get_current());
- }
-
- favorite->set_pressed(false);
- fav_up->set_disabled(true);
- fav_down->set_disabled(true);
- for(int i=0;i<favorites->get_item_count();i++) {
- if (favorites->get_item_metadata(i)==base_dir) {
- favorites->select(i);
- favorite->set_pressed(true);
- if (i>0) {
- fav_up->set_disabled(false);
- }
- if (i<favorites->get_item_count()-1) {
- fav_down->set_disabled(false);
- }
- break;
- }
-
- }
- // ??
- /*
- if (tree->get_root() && tree->get_root()->get_children())
- tree->get_root()->get_children()->select(0);
- */
-
- files.clear();
-
-}
-
-void EditorFileDialog::_filter_selected(int) {
-
- update_file_list();
-}
-
-void EditorFileDialog::update_filters() {
-
- filter->clear();
-
- if (filters.size()>1) {
- String all_filters;
-
- const int max_filters=5;
-
- for(int i=0;i<MIN( max_filters, filters.size()) ;i++) {
- String flt=filters[i].get_slice(";",0);
- if (i>0)
- all_filters+=",";
- all_filters+=flt;
- }
-
- if (max_filters<filters.size())
- all_filters+=", ...";
-
- filter->add_item(TTR("All Recognized")+" ( "+all_filters+" )");
- }
- for(int i=0;i<filters.size();i++) {
-
- String flt=filters[i].get_slice(";",0).strip_edges();
- String desc=filters[i].get_slice(";",1).strip_edges();
- if (desc.length())
- filter->add_item(desc+" ( "+flt+" )");
- else
- filter->add_item("( "+flt+" )");
- }
-
- filter->add_item(TTR("All Files (*)"));
-
-}
-
-void EditorFileDialog::clear_filters() {
-
- filters.clear();
- update_filters();
- invalidate();
-}
-void EditorFileDialog::add_filter(const String& p_filter) {
-
- filters.push_back(p_filter);
- update_filters();
- invalidate();
-
-}
-
-String EditorFileDialog::get_current_dir() const {
-
- return dir->get_text();
-}
-String EditorFileDialog::get_current_file() const {
-
- return file->get_text();
-}
-String EditorFileDialog::get_current_path() const {
-
- return dir->get_text().plus_file(file->get_text());
-}
-void EditorFileDialog::set_current_dir(const String& p_dir) {
-
- dir_access->change_dir(p_dir);
- update_dir();
- invalidate();
- //_push_history();
-
-
-}
-void EditorFileDialog::set_current_file(const String& p_file) {
-
- file->set_text(p_file);
- update_dir();
- invalidate();
- int lp = p_file.find_last(".");
- if (lp!=-1) {
- file->select(0,lp);
- file->grab_focus();
- }
-
- if (is_visible_in_tree())
- _request_single_thumbnail(get_current_dir().plus_file(get_current_file()));
-
-
-}
-void EditorFileDialog::set_current_path(const String& p_path) {
-
- if (!p_path.size())
- return;
- int pos=MAX( p_path.find_last("/"), p_path.find_last("\\") );
- if (pos==-1) {
-
- set_current_file(p_path);
- } else {
-
- String dir=p_path.substr(0,pos);
- String file=p_path.substr(pos+1,p_path.length());
- set_current_dir(dir);
- set_current_file(file);
- }
-}
-
-
-void EditorFileDialog::set_mode(Mode p_mode) {
-
- mode=p_mode;
- switch(mode) {
-
- case MODE_OPEN_FILE: get_ok()->set_text(TTR("Open")); set_title("Open a File"); makedir->hide(); break;
- case MODE_OPEN_FILES: get_ok()->set_text(TTR("Open")); set_title("Open File(s)"); makedir->hide(); break;
- case MODE_OPEN_DIR: get_ok()->set_text(TTR("Open")); set_title("Open a Directory"); makedir->show(); break;
- case MODE_OPEN_ANY: get_ok()->set_text(TTR("Open")); set_title("Open a File or Directory"); makedir->show(); break;
- case MODE_SAVE_FILE: get_ok()->set_text(TTR("Save")); set_title("Save a File"); makedir->show(); break;
- }
-
- if (mode==MODE_OPEN_FILES) {
- item_list->set_select_mode(ItemList::SELECT_MULTI);
- } else {
- item_list->set_select_mode(ItemList::SELECT_SINGLE);
- }
-}
-
-EditorFileDialog::Mode EditorFileDialog::get_mode() const {
-
- return mode;
-}
-
-void EditorFileDialog::set_access(Access p_access) {
-
- ERR_FAIL_INDEX(p_access,3);
- if (access==p_access)
- return;
- memdelete( dir_access );
- switch(p_access) {
- case ACCESS_FILESYSTEM: {
-
- dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- } break;
- case ACCESS_RESOURCES: {
-
- dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- } break;
- case ACCESS_USERDATA: {
-
- dir_access = DirAccess::create(DirAccess::ACCESS_USERDATA);
- } break;
- }
- access=p_access;
- _update_drives();
- invalidate();
- update_filters();
- update_dir();
-}
-
-void EditorFileDialog::invalidate() {
-
- if (is_visible_in_tree()) {
- update_file_list();
- invalidated=false;
- } else {
- invalidated=true;
- }
-
-}
-
-EditorFileDialog::Access EditorFileDialog::get_access() const{
-
- return access;
-}
-
-void EditorFileDialog::_make_dir_confirm() {
-
- Error err = dir_access->make_dir( makedirname->get_text() );
- if (err==OK) {
- dir_access->change_dir(makedirname->get_text());
- invalidate();
- update_filters();
- update_dir();
- _push_history();
-
- } else {
- mkdirerr->popup_centered_minsize(Size2(250,50)*EDSCALE);
- }
- makedirname->set_text(""); // reset label
-}
-
-
-void EditorFileDialog::_make_dir() {
-
- makedialog->popup_centered_minsize(Size2(250,80)*EDSCALE);
- makedirname->grab_focus();
-
-}
-
-void EditorFileDialog::_select_drive(int p_idx) {
-
- String d = drives->get_item_text(p_idx);
- dir_access->change_dir(d);
- file->set_text("");
- invalidate();
- update_dir();
- _push_history();
-
-
-}
-
-void EditorFileDialog::_update_drives() {
-
-
- int dc = dir_access->get_drive_count();
- if (dc==0 || access!=ACCESS_FILESYSTEM) {
- drives->hide();
- } else {
- drives->clear();
- drives->show();
-
- for(int i=0;i<dir_access->get_drive_count();i++) {
- String d = dir_access->get_drive(i);
- drives->add_item(dir_access->get_drive(i));
- }
-
- drives->select(dir_access->get_current_drive());
-
- }
-}
-
-
-void EditorFileDialog::_favorite_selected(int p_idx) {
-
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
- ERR_FAIL_INDEX(p_idx,favorited.size());
-
- dir_access->change_dir(favorited[p_idx]);
- file->set_text("");
- invalidate();
- update_dir();
- _push_history();
-}
-
-void EditorFileDialog::_favorite_move_up(){
-
- int current = favorites->get_current();
-
- if (current>0 && current<favorites->get_item_count()) {
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
-
- int a_idx=favorited.find(String(favorites->get_item_metadata(current-1)));
- int b_idx=favorited.find(String(favorites->get_item_metadata(current)));
-
- if (a_idx==-1 || b_idx==-1)
- return;
- SWAP(favorited[a_idx],favorited[b_idx]);
-
- EditorSettings::get_singleton()->set_favorite_dirs(favorited);
-
- _update_favorites();
- update_file_list();
-
- }
-}
-void EditorFileDialog::_favorite_move_down(){
-
- int current = favorites->get_current();
-
- if (current>=0 && current<favorites->get_item_count()-1) {
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
-
- int a_idx=favorited.find(String(favorites->get_item_metadata(current+1)));
- int b_idx=favorited.find(String(favorites->get_item_metadata(current)));
-
- if (a_idx==-1 || b_idx==-1)
- return;
- SWAP(favorited[a_idx],favorited[b_idx]);
-
- EditorSettings::get_singleton()->set_favorite_dirs(favorited);
-
- _update_favorites();
- update_file_list();
-
- }
-}
-
-
-void EditorFileDialog::_update_favorites() {
-
- bool res = access==ACCESS_RESOURCES;
-
- String current = get_current_dir();
- Ref<Texture> star = get_icon("Favorites","EditorIcons");
- favorites->clear();
-
- favorite->set_pressed(false);
-
-
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
- for(int i=0;i<favorited.size();i++) {
- bool cres = favorited[i].begins_with("res://");
- if (cres!=res)
- continue;
- String name = favorited[i];
-
- bool setthis = name==current;
-
- if (res && name=="res://") {
- name="/";
- } else {
- name=name.get_file()+"/";
- }
-
-
- //print_line("file: "+name);
- favorites->add_item(name,star);
- favorites->set_item_metadata( favorites->get_item_count()-1,favorited[i]);
-
- if (setthis) {
- favorite->set_pressed(true);
- favorites->set_current(favorites->get_item_count()-1);
- }
- }
-
-
-}
-
-void EditorFileDialog::_favorite_toggled(bool p_toggle) {
- bool res = access==ACCESS_RESOURCES;
-
- String cd = get_current_dir();
-
- Vector<String> favorited = EditorSettings::get_singleton()->get_favorite_dirs();
-
- bool found = false;
- for(int i=0;i<favorited.size();i++) {
- bool cres = favorited[i].begins_with("res://");
- if (cres!=res)
- continue;
-
- if (favorited[i]==cd) {
- found=true;
- break;
- }
- }
-
- if (found) {
- favorited.erase(cd);
- favorite->set_pressed(false);
- } else {
- favorited.push_back(cd);
- favorite->set_pressed(true);
- }
-
- EditorSettings::get_singleton()->set_favorite_dirs(favorited);
-
- _update_favorites();
-
-}
-
-void EditorFileDialog::_recent_selected(int p_idx) {
-
- Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
- ERR_FAIL_INDEX(p_idx,recentd.size());
-
- dir_access->change_dir(recent->get_item_metadata(p_idx));
- update_file_list();
- update_dir();
- _push_history();
-}
-
-void EditorFileDialog::_go_up() {
-
- dir_access->change_dir("..");
- update_file_list();
- update_dir();
- _push_history();
-
-}
-
-void EditorFileDialog::_go_back(){
-
- if (local_history_pos<=0) {
- return;
- }
-
- local_history_pos--;
- dir_access->change_dir(local_history[local_history_pos]);
- update_file_list();
- update_dir();
-
- dir_prev->set_disabled(local_history_pos==0);
- dir_next->set_disabled(local_history_pos==local_history.size()-1);
-}
-void EditorFileDialog::_go_forward(){
-
- if (local_history_pos==local_history.size()-1) {
- return;
- }
-
- local_history_pos++;
- dir_access->change_dir(local_history[local_history_pos]);
- update_file_list();
- update_dir();
-
- dir_prev->set_disabled(local_history_pos==0);
- dir_next->set_disabled(local_history_pos==local_history.size()-1);
-
-}
-
-bool EditorFileDialog::default_show_hidden_files=false;
-
-EditorFileDialog::DisplayMode EditorFileDialog::default_display_mode=DISPLAY_THUMBNAILS;
-
-void EditorFileDialog::set_display_mode(DisplayMode p_mode) {
-
- if (display_mode==p_mode)
- return;
- if (p_mode==DISPLAY_THUMBNAILS) {
- mode_list->set_pressed(false);
- mode_thumbnails->set_pressed(true);
- } else {
- mode_thumbnails->set_pressed(false);
- mode_list->set_pressed(true);
- }
- display_mode=p_mode;
- invalidate();
-}
-
-EditorFileDialog::DisplayMode EditorFileDialog::get_display_mode() const{
-
- return display_mode;
-}
-
-
-
-void EditorFileDialog::_bind_methods() {
-
- ClassDB::bind_method(_MD("_unhandled_input"),&EditorFileDialog::_unhandled_input);
-
- ClassDB::bind_method(_MD("_item_selected"),&EditorFileDialog::_item_selected);
- ClassDB::bind_method(_MD("_item_db_selected"),&EditorFileDialog::_item_dc_selected);
- ClassDB::bind_method(_MD("_dir_entered"),&EditorFileDialog::_dir_entered);
- ClassDB::bind_method(_MD("_file_entered"),&EditorFileDialog::_file_entered);
- ClassDB::bind_method(_MD("_action_pressed"),&EditorFileDialog::_action_pressed);
- ClassDB::bind_method(_MD("_cancel_pressed"),&EditorFileDialog::_cancel_pressed);
- ClassDB::bind_method(_MD("_filter_selected"),&EditorFileDialog::_filter_selected);
- ClassDB::bind_method(_MD("_save_confirm_pressed"),&EditorFileDialog::_save_confirm_pressed);
-
- ClassDB::bind_method(_MD("clear_filters"),&EditorFileDialog::clear_filters);
- ClassDB::bind_method(_MD("add_filter","filter"),&EditorFileDialog::add_filter);
- ClassDB::bind_method(_MD("get_current_dir"),&EditorFileDialog::get_current_dir);
- ClassDB::bind_method(_MD("get_current_file"),&EditorFileDialog::get_current_file);
- ClassDB::bind_method(_MD("get_current_path"),&EditorFileDialog::get_current_path);
- ClassDB::bind_method(_MD("set_current_dir","dir"),&EditorFileDialog::set_current_dir);
- ClassDB::bind_method(_MD("set_current_file","file"),&EditorFileDialog::set_current_file);
- ClassDB::bind_method(_MD("set_current_path","path"),&EditorFileDialog::set_current_path);
- ClassDB::bind_method(_MD("set_mode","mode"),&EditorFileDialog::set_mode);
- ClassDB::bind_method(_MD("get_mode"),&EditorFileDialog::get_mode);
- ClassDB::bind_method(_MD("get_vbox:VBoxContainer"),&EditorFileDialog::get_vbox);
- ClassDB::bind_method(_MD("set_access","access"),&EditorFileDialog::set_access);
- ClassDB::bind_method(_MD("get_access"),&EditorFileDialog::get_access);
- ClassDB::bind_method(_MD("set_show_hidden_files","show"),&EditorFileDialog::set_show_hidden_files);
- ClassDB::bind_method(_MD("is_showing_hidden_files"),&EditorFileDialog::is_showing_hidden_files);
- ClassDB::bind_method(_MD("_select_drive"),&EditorFileDialog::_select_drive);
- ClassDB::bind_method(_MD("_make_dir"),&EditorFileDialog::_make_dir);
- ClassDB::bind_method(_MD("_make_dir_confirm"),&EditorFileDialog::_make_dir_confirm);
- ClassDB::bind_method(_MD("_update_file_list"),&EditorFileDialog::update_file_list);
- ClassDB::bind_method(_MD("_update_dir"),&EditorFileDialog::update_dir);
- ClassDB::bind_method(_MD("_thumbnail_done"),&EditorFileDialog::_thumbnail_done);
- ClassDB::bind_method(_MD("set_display_mode","mode"),&EditorFileDialog::set_display_mode);
- ClassDB::bind_method(_MD("get_display_mode"),&EditorFileDialog::get_display_mode);
- ClassDB::bind_method(_MD("_thumbnail_result"),&EditorFileDialog::_thumbnail_result);
- ClassDB::bind_method(_MD("set_disable_overwrite_warning","disable"),&EditorFileDialog::set_disable_overwrite_warning);
- ClassDB::bind_method(_MD("is_overwrite_warning_disabled"),&EditorFileDialog::is_overwrite_warning_disabled);
-
- ClassDB::bind_method(_MD("_recent_selected"),&EditorFileDialog::_recent_selected);
- ClassDB::bind_method(_MD("_go_back"),&EditorFileDialog::_go_back);
- ClassDB::bind_method(_MD("_go_forward"),&EditorFileDialog::_go_forward);
- ClassDB::bind_method(_MD("_go_up"),&EditorFileDialog::_go_up);
-
- ClassDB::bind_method(_MD("_favorite_toggled"),&EditorFileDialog::_favorite_toggled);
- ClassDB::bind_method(_MD("_favorite_selected"),&EditorFileDialog::_favorite_selected);
- ClassDB::bind_method(_MD("_favorite_move_up"),&EditorFileDialog::_favorite_move_up);
- ClassDB::bind_method(_MD("_favorite_move_down"),&EditorFileDialog::_favorite_move_down);
-
- ClassDB::bind_method(_MD("invalidate"),&EditorFileDialog::invalidate);
-
- ADD_SIGNAL(MethodInfo("file_selected",PropertyInfo( Variant::STRING,"path")));
- ADD_SIGNAL(MethodInfo("files_selected",PropertyInfo( Variant::POOL_STRING_ARRAY,"paths")));
- ADD_SIGNAL(MethodInfo("dir_selected",PropertyInfo( Variant::STRING,"dir")));
-
- BIND_CONSTANT( MODE_OPEN_FILE );
- BIND_CONSTANT( MODE_OPEN_FILES );
- BIND_CONSTANT( MODE_OPEN_DIR );
- BIND_CONSTANT( MODE_OPEN_ANY );
- BIND_CONSTANT( MODE_SAVE_FILE );
-
- BIND_CONSTANT( ACCESS_RESOURCES );
- BIND_CONSTANT( ACCESS_USERDATA );
- BIND_CONSTANT( ACCESS_FILESYSTEM );
-
-}
-
-
-void EditorFileDialog::set_show_hidden_files(bool p_show) {
- show_hidden_files=p_show;
- invalidate();
-}
-
-bool EditorFileDialog::is_showing_hidden_files() const {
- return show_hidden_files;
-}
-
-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();
- Vector<String> recent = EditorSettings::get_singleton()->get_recent_dirs();
-
- const int max=20;
- int count=0;
- bool res=dir.begins_with("res://");
-
- for(int i=0;i<recent.size();i++) {
- bool cres=recent[i].begins_with("res://");
- if (recent[i]==dir || (res==cres && count>max)) {
- recent.remove(i);
- i--;
- } else {
- count++;
- }
- }
-
- recent.insert(0,dir);
-
- EditorSettings::get_singleton()->set_recent_dirs(recent);
-
-
-}
-
-void EditorFileDialog::set_disable_overwrite_warning(bool p_disable) {
-
- disable_overwrite_warning=p_disable;
-}
-
-bool EditorFileDialog::is_overwrite_warning_disabled() const{
-
- return disable_overwrite_warning;
-}
-
-
-EditorFileDialog::EditorFileDialog() {
-
- show_hidden_files=default_show_hidden_files;
- display_mode=default_display_mode;
- local_history_pos=0;
- disable_overwrite_warning=false;
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
-
- mode=MODE_SAVE_FILE;
- set_title(TTR("Save a File"));
-
- ED_SHORTCUT("file_dialog/go_back", TTR("Go Back"), KEY_MASK_ALT|KEY_LEFT);
- ED_SHORTCUT("file_dialog/go_forward", TTR("Go Forward"), KEY_MASK_ALT|KEY_RIGHT);
- ED_SHORTCUT("file_dialog/go_up", TTR("Go Up"), KEY_MASK_ALT|KEY_UP);
- ED_SHORTCUT("file_dialog/refresh", TTR("Refresh"), KEY_F5);
- ED_SHORTCUT("file_dialog/toggle_hidden_files", TTR("Toggle Hidden Files"), KEY_MASK_CMD|KEY_H);
- ED_SHORTCUT("file_dialog/toggle_favorite", TTR("Toggle Favorite"), KEY_MASK_ALT|KEY_F);
- ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KEY_MASK_ALT|KEY_V);
- ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KEY_MASK_CMD|KEY_N);
- ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KEY_MASK_CMD|KEY_D);
- ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KEY_MASK_CMD|KEY_UP);
- ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KEY_MASK_CMD|KEY_DOWN);
-
- HBoxContainer *pathhb = memnew( HBoxContainer );
-
- dir_prev = memnew( ToolButton );
- dir_next = memnew( ToolButton );
- dir_up = memnew( ToolButton );
-
- pathhb->add_child(dir_prev);
- pathhb->add_child(dir_next);
- pathhb->add_child(dir_up);
-
- dir_prev->connect("pressed",this,"_go_back");
- dir_next->connect("pressed",this,"_go_forward");
- dir_up->connect("pressed",this,"_go_up");
-
- dir = memnew(LineEdit);
- 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");
- pathhb->add_child(favorite);
-
- 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(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 );
- pathhb->add_child(drives);
- drives->connect("item_selected",this,"_select_drive");
-
- makedir = memnew( Button );
- makedir->set_text(TTR("Create Folder"));
- makedir->connect("pressed",this,"_make_dir");
- pathhb->add_child(makedir);
-
- list_hb = memnew( HBoxContainer );
-
- vbc->add_margin_child(TTR("Path:"),pathhb);
- vbc->add_child(list_hb);
- list_hb->set_v_size_flags(SIZE_EXPAND_FILL);
-
- VBoxContainer *fav_vb = memnew( VBoxContainer );
- list_hb->add_child(fav_vb);
- HBoxContainer *fav_hb = memnew( HBoxContainer );
- fav_vb->add_child(fav_hb);
- fav_hb->add_child(memnew(Label(TTR("Favorites:"))));
- fav_hb->add_spacer();
- fav_up = memnew( ToolButton );
- fav_hb->add_child(fav_up);
- fav_up->connect("pressed",this,"_favorite_move_up");
- fav_down = memnew( ToolButton );
- fav_hb->add_child(fav_down);
- fav_down->connect("pressed",this,"_favorite_move_down");
- fav_rm = memnew( ToolButton );
- fav_hb->add_child(fav_rm);
- fav_rm->hide(); // redundant
-
- MarginContainer *fav_mv = memnew( MarginContainer );
- fav_vb->add_child(fav_mv);
- fav_mv->set_v_size_flags(SIZE_EXPAND_FILL);
- favorites = memnew( ItemList );
- fav_mv->add_child(favorites);
- favorites->connect("item_selected",this,"_favorite_selected");
-
- recent = memnew( ItemList );
- fav_vb->add_margin_child(TTR("Recent:"),recent,true);
- recent->connect("item_selected",this,"_recent_selected");
-
- VBoxContainer *item_vb = memnew( VBoxContainer );
- list_hb->add_child(item_vb);
- item_vb->set_h_size_flags(SIZE_EXPAND_FILL);
-
- item_list = memnew( ItemList );
- item_list->set_v_size_flags(SIZE_EXPAND_FILL);
- item_vb->add_margin_child(TTR("Directories & Files:"),item_list,true);
-
- HBoxContainer* filter_hb = memnew( HBoxContainer );
- item_vb->add_child(filter_hb);
-
- VBoxContainer *filter_vb = memnew( VBoxContainer );
- filter_hb->add_child(filter_vb);
- filter_vb->set_h_size_flags(SIZE_EXPAND_FILL);
-
- preview_vb = memnew( VBoxContainer );
- filter_hb->add_child(preview_vb);
- CenterContainer *prev_cc = memnew( CenterContainer );
- preview_vb->add_margin_child(TTR("Preview:"),prev_cc);
- preview = memnew( TextureRect );
- prev_cc->add_child(preview);
- preview_vb->hide();
-
-
- file = memnew(LineEdit);
- //add_child(file);
- filter_vb->add_margin_child(TTR("File:"),file);
-
-
- filter = memnew( OptionButton );
- //add_child(filter);
- filter_vb->add_margin_child(TTR("Filter:"),filter);
- filter->set_clip_text(true);//too many extensions overflow it
-
- dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- access=ACCESS_RESOURCES;
- _update_drives();
-
-
- connect("confirmed", this,"_action_pressed");
- //cancel->connect("pressed", this,"_cancel_pressed");
- item_list->connect("item_selected", this,"_item_selected",varray(),CONNECT_DEFERRED);
- item_list->connect("item_activated", this,"_item_db_selected",varray());
- dir->connect("text_entered", this,"_dir_entered");
- file->connect("text_entered", this,"_file_entered");
- filter->connect("item_selected", this,"_filter_selected");
-
-
- confirm_save = memnew( ConfirmationDialog );
- confirm_save->set_as_toplevel(true);
- add_child(confirm_save);
-
-
- confirm_save->connect("confirmed", this,"_save_confirm_pressed");
-
- makedialog = memnew( ConfirmationDialog );
- makedialog->set_title(TTR("Create Folder"));
- VBoxContainer *makevb= memnew( VBoxContainer );
- makedialog->add_child(makevb);
-
- makedirname = memnew( LineEdit );
- makevb->add_margin_child(TTR("Name:"),makedirname);
- add_child(makedialog);
- makedialog->register_text_enter(makedirname);
- makedialog->connect("confirmed",this,"_make_dir_confirm");
- mkdirerr = memnew( AcceptDialog );
- mkdirerr->set_text(TTR("Could not create folder."));
- add_child(mkdirerr);
-
- exterr = memnew( AcceptDialog );
- exterr->set_text(TTR("Must use a valid extension."));
- add_child(exterr);
-
-
- //update_file_list();
- update_filters();
- update_dir();
-
- set_hide_on_ok(false);
- vbox=vbc;
-
-
- invalidated=true;
- if (register_func)
- register_func(this);
-
- preview_wheel_timeout=0;
- preview_wheel_index=0;
- preview_waiting=false;
-
-}
-
-
-EditorFileDialog::~EditorFileDialog() {
-
- if (unregister_func)
- unregister_func(this);
- memdelete(dir_access);
-}
-
-
-void EditorLineEditFileChooser::_bind_methods() {
-
- ClassDB::bind_method(_MD("_browse"),&EditorLineEditFileChooser::_browse);
- ClassDB::bind_method(_MD("_chosen"),&EditorLineEditFileChooser::_chosen);
- ClassDB::bind_method(_MD("get_button:Button"),&EditorLineEditFileChooser::get_button);
- ClassDB::bind_method(_MD("get_line_edit:LineEdit"),&EditorLineEditFileChooser::get_line_edit);
- ClassDB::bind_method(_MD("get_file_dialog:EditorFileDialog"),&EditorLineEditFileChooser::get_file_dialog);
-
-}
-
-void EditorLineEditFileChooser::_chosen(const String& p_text){
-
- line_edit->set_text(p_text);
- line_edit->emit_signal("text_entered",p_text);
-}
-
-void EditorLineEditFileChooser::_browse() {
-
- dialog->popup_centered_ratio();
-}
-
-EditorLineEditFileChooser::EditorLineEditFileChooser() {
-
- line_edit = memnew( LineEdit );
- add_child(line_edit);
- line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
- button = memnew( Button );
- button->set_text(" .. ");
- add_child(button);
- button->connect("pressed",this,"_browse");
- dialog = memnew( EditorFileDialog);
- add_child(dialog);
- dialog->connect("file_selected",this,"_chosen");
- dialog->connect("dir_selected",this,"_chosen");
- dialog->connect("files_selected",this,"_chosen");
-
-
-}
diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp
deleted file mode 100644
index c7b50a3c09..0000000000
--- a/tools/editor/editor_file_system.cpp
+++ /dev/null
@@ -1,1550 +0,0 @@
-/*************************************************************************/
-/* editor_file_system.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_file_system.h"
-
-#include "globals.h"
-#include "io/resource_loader.h"
-#include "os/os.h"
-#include "os/file_access.h"
-#include "editor_node.h"
-#include "io/resource_saver.h"
-#include "io/resource_import.h"
-#include "editor_settings.h"
-#include "editor_resource_preview.h"
-#include "variant_parser.h"
-
-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 {
-
- return subdirs.size();
-}
-
-EditorFileSystemDirectory *EditorFileSystemDirectory::get_subdir(int p_idx){
-
- ERR_FAIL_INDEX_V(p_idx,subdirs.size(),NULL);
- return subdirs[p_idx];
-
-}
-
-int EditorFileSystemDirectory::get_file_count() const{
-
- return files.size();
-}
-
-String EditorFileSystemDirectory::get_file(int p_idx) const{
-
- ERR_FAIL_INDEX_V(p_idx,files.size(),"");
-
- return files[p_idx]->file;
-}
-
-String EditorFileSystemDirectory::get_path() const {
-
- String p;
- const EditorFileSystemDirectory *d=this;
- while(d->parent) {
- p=d->name+"/"+p;
- d=d->parent;
- }
-
- return "res://"+p;
-
-}
-
-
-String EditorFileSystemDirectory::get_file_path(int p_idx) const {
-
- String file = get_file(p_idx);
- const EditorFileSystemDirectory *d=this;
- while(d->parent) {
- file=d->name+"/"+file;
- d=d->parent;
- }
-
- return "res://"+file;
-}
-
-
-Vector<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,files.size(),Vector<String>());
- return files[p_idx]->deps;
-
-}
-
-
-StringName EditorFileSystemDirectory::get_file_type(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,files.size(),"");
- return files[p_idx]->type;
-}
-
-String EditorFileSystemDirectory::get_name() {
-
- return name;
-}
-
-EditorFileSystemDirectory *EditorFileSystemDirectory::get_parent() {
-
- return parent;
-}
-
-void EditorFileSystemDirectory::_bind_methods() {
-
- ClassDB::bind_method(_MD("get_subdir_count"),&EditorFileSystemDirectory::get_subdir_count);
- ClassDB::bind_method(_MD("get_subdir","idx"),&EditorFileSystemDirectory::get_subdir);
- ClassDB::bind_method(_MD("get_file_count"),&EditorFileSystemDirectory::get_file_count);
- ClassDB::bind_method(_MD("get_file","idx"),&EditorFileSystemDirectory::get_file);
- ClassDB::bind_method(_MD("get_file_path","idx"),&EditorFileSystemDirectory::get_file_path);
- ClassDB::bind_method(_MD("get_file_type","idx"),&EditorFileSystemDirectory::get_file_type);
- ClassDB::bind_method(_MD("get_name"),&EditorFileSystemDirectory::get_name);
- ClassDB::bind_method(_MD("get_path"),&EditorFileSystemDirectory::get_path);
- ClassDB::bind_method(_MD("get_parent:EditorFileSystemDirectory"),&EditorFileSystemDirectory::get_parent);
- ClassDB::bind_method(_MD("find_file_index","name"),&EditorFileSystemDirectory::find_file_index);
- ClassDB::bind_method(_MD("find_dir_index","name"),&EditorFileSystemDirectory::find_dir_index);
-
-
-}
-
-
-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]);
- }
-}
-
-
-
-
-
-void EditorFileSystem::_scan_filesystem() {
-
- ERR_FAIL_COND(!scanning || new_filesystem);
-
- //read .fscache
- String cpath;
-
- sources_changed.clear();
- file_cache.clear();
-
- String project=GlobalConfig::get_singleton()->get_resource_path();
-
- String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2");
- FileAccess *f =FileAccess::open(fscache,FileAccess::READ);
-
- if (f) {
- //read the disk cache
- while(!f->eof_reached()) {
-
- String l = f->get_line().strip_edges();
- if (l==String())
- continue;
-
- if (l.begins_with("::")) {
- Vector<String> split = l.split("::");
- ERR_CONTINUE( split.size() != 3);
- String name = split[1];
-
- cpath=name;
-
- } else {
- Vector<String> split = l.split("::");
- ERR_CONTINUE( split.size() != 5);
- String name = split[0];
- String file;
-
- file=name;
- name=cpath.plus_file(name);
-
- FileCache fc;
- fc.type=split[1];
- fc.modification_time=split[2].to_int64();
- fc.import_modification_time = split[3].to_int64();
-
- String deps = split[4].strip_edges();
- if (deps.length()) {
- Vector<String> dp = deps.split("<>");
- for(int i=0;i<dp.size();i++) {
- String path=dp[i];
- fc.deps.push_back(path);
- }
- }
-
- file_cache[name]=fc;
-
- }
-
- }
-
- f->close();
- memdelete(f);
- }
-
-
-
- EditorProgressBG scan_progress("efs","ScanFS",1000);
-
- ScanProgress sp;
- sp.low=0;
- sp.hi=1;
- sp.progress=&scan_progress;
-
-
- 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);
-
- file_cache.clear(); //clear caches, no longer needed
-
- 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_filesystem_cache(new_filesystem,f);
- f->close();
- memdelete(f);
-
- scanning=false;
-
-}
-
-void EditorFileSystem::_save_filesystem_cache() {
- String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2");
-
- FileAccess *f=FileAccess::open(fscache,FileAccess::WRITE);
- _save_filesystem_cache(filesystem,f);
- f->close();
- memdelete(f);
-}
-
-void EditorFileSystem::_thread_func(void *_userdata) {
-
- EditorFileSystem *sd = (EditorFileSystem*)_userdata;
- sd->_scan_filesystem();
-
-}
-
-bool EditorFileSystem::_update_scan_actions() {
-
- sources_changed.clear();
-
- bool fs_changed=false;
-
- Vector<String> reimports;
-
- 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_REIMPORT: {
-
-
- int idx = ia.dir->find_file_index(ia.file);
- ERR_CONTINUE(idx==-1);
- String full_path = ia.dir->get_file_path(idx);
- reimports.push_back(full_path);
-
- fs_changed=true;
- } break;
-
- }
- }
-
-
- if (reimports.size()) {
- reimport_files(reimports);
-
- }
- scan_actions.clear();
-
- return fs_changed;
-
-}
-
-void EditorFileSystem::scan() {
-
- if (false /*&& bool(Globals::get_singleton()->get("debug/disable_scan"))*/)
- return;
-
- if (scanning || scanning_changes|| thread)
- return;
-
- _update_extensions();
-
- abort_scan=false;
- if (!use_threads) {
- scanning=true;
- scan_total=0;
- _scan_filesystem();
- if (filesystem)
- memdelete(filesystem);
- //file_type_cache.clear();
- filesystem=new_filesystem;
- new_filesystem=NULL;
- _update_scan_actions();
- scanning=false;
- emit_signal("filesystem_changed");
- emit_signal("sources_changed",sources_changed.size()>0);
-
- } else {
-
- ERR_FAIL_COND(thread);
- 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();
- //progress->show();
-
- }
-
-
-
-}
-
-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;
-
-}
-
-bool EditorFileSystem::_check_missing_imported_files(const String& p_path) {
-
- if (!reimport_on_missing_imported_files)
- return true;
-
- Error err;
- FileAccess *f= FileAccess::open(p_path+".import",FileAccess::READ,&err);
-
- if (!f) {
- print_line("could not open import for "+p_path);
- return false;
- }
-
- VariantParser::StreamFile stream;
- stream.f=f;
-
- String assign;
- Variant value;
- VariantParser::Tag next_tag;
-
- int lines=0;
- String error_text;
-
- List<String> to_check;
-
- 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("ResourceFormatImporter::load - "+p_path+".import:"+itos(lines)+" error: "+error_text);
- memdelete(f);
- return false;
- }
-
- if (assign!=String()) {
- if (assign.begins_with("path")) {
- to_check.push_back(value);
- } else if (assign=="files") {
- Array fa = value;
- for(int i=0;i<fa.size();i++) {
- to_check.push_back(fa[i]);
- }
- }
-
- } else if (next_tag.name!="remap" && next_tag.name!="deps") {
- break;
- }
- }
-
- memdelete(f);
-
- for (List<String>::Element *E=to_check.front();E;E=E->next()) {
- if (!FileAccess::exists(E->get())) {
- print_line("missing "+E->get()+", reimport" );
- return false;
- }
- }
- return true;
-}
-
-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("godot.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) {
-
- String d = da->get_current_dir();
-
- if (d==cd || !d.begins_with(cd)) {
- da->change_dir(cd); //avoid recursion
- } else {
-
-
- 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("Cannot 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().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 (import_extensions.has(ext)) {
-
- //is imported
- uint64_t import_mt=0;
- if (FileAccess::exists(path+".import")) {
- import_mt=FileAccess::get_modified_time(path+".import");
- }
-
-
- if (fc && fc->modification_time==mt && fc->import_modification_time==import_mt && _check_missing_imported_files(path)) {
-
- fi->type=fc->type;
- fi->modified_time=fc->modification_time;
- fi->import_modified_time=fc->import_modification_time;
-
- } else {
-
- if (!fc) {
- print_line("REIMPORT BECAUSE: not previously found");
- } else if (fc->modification_time!=mt) {
- print_line("REIMPORT BECAUSE: modified resource time "+itos(fc->modification_time)+" vs "+itos(mt));
-
- } else if (fc->import_modification_time!=import_mt) {
- print_line("REIMPORT BECAUSE: modified .import time"+itos(fc->import_modification_time)+" vs "+itos(import_mt));
-
- } else {
-
- print_line("REIMPORT BECAUSE: missing imported files");
- }
-
-
- fi->type=ResourceFormatImporter::get_singleton()->get_resource_type(path);
- fi->modified_time=0;
- fi->import_modified_time=0;
-
- ItemAction ia;
- ia.action=ItemAction::ACTION_FILE_REIMPORT;
- ia.dir=p_dir;
- ia.file=E->get();
- scan_actions.push_back(ia);
- }
- } else {
- //not imported, so just update type if changed
- if (fc && fc->modification_time == mt) {
-
- fi->type=fc->type;
- fi->modified_time=fc->modification_time;
- fi->import_modified_time=0;
- } else {
- fi->type=ResourceLoader::get_resource_type(path);
- fi->modified_time=mt;
- fi->import_modified_time=0;
- }
- }
-
- 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;
- String cd = p_dir->get_path();
-
- //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);
-
- 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("godot.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.get_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->import_modified_time=0;
- 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);
-
-
- }
-
- if (import_extensions.has(ext)) {
- //if it can be imported, and it was added, it needs to be reimported
- print_line("REIMPORT: file was not found before, reimport");
- print_line("at dir: "+p_dir->get_path()+" file: "+f);
- for(int i=0;i<p_dir->files.size();i++) {
- print_line(itos(i)+": "+p_dir->files[i]->file);
- }
- ItemAction ia;
- ia.action=ItemAction::ACTION_FILE_REIMPORT;
- 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 (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 (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) {
- //check here if file must be imported or not
-
- String path = cd.plus_file(p_dir->files[i]->file);
-
- uint64_t mt = FileAccess::get_modified_time(path);
-
- bool reimport=false;
-
- if (mt!=p_dir->files[i]->modified_time) {
- print_line("REIMPORT: modified time changed, reimport");
- reimport=true; //it was modified, must be reimported.
- } else if (!FileAccess::exists(path+".import")) {
- print_line("REIMPORT: no .import exists, reimport");
- reimport=true; //no .import file, obviously reimport
- } else {
-
- uint64_t import_mt=FileAccess::get_modified_time(path+".import");
- print_line(itos(import_mt)+" vs "+itos(p_dir->files[i]->import_modified_time));
- if (import_mt!=p_dir->files[i]->import_modified_time) {
- print_line("REIMPORT: import modified changed, reimport");
- reimport=true;
- } else if (!_check_missing_imported_files(path)) {
- print_line("REIMPORT: imported files removed");
- reimport=true;
- }
- }
-
- if (reimport) {
-
- ItemAction ia;
- ia.action=ItemAction::ACTION_FILE_REIMPORT;
- ia.dir=p_dir;
- ia.file=p_dir->files[i]->file;
- scan_actions.push_back(ia);
- }
-
- }
-
- EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i));
- }
-
- for(int i=0;i<p_dir->subdirs.size();i++) {
-
- 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);
- }
-
-}
-
-void EditorFileSystem::_thread_func_sources(void *_userdata) {
-
- EditorFileSystem *efs = (EditorFileSystem*)_userdata;
- if (efs->filesystem) {
- EditorProgressBG pr("sources",TTR("ScanSources"),1000);
- ScanProgress sp;
- sp.progress=&pr;
- sp.hi=1;
- sp.low=0;
- efs->_scan_fs_changes(efs->filesystem,sp);
- }
- efs->scanning_changes_done=true;
-}
-
-void EditorFileSystem::get_changed_sources(List<String> *r_changed) {
-
- *r_changed=sources_changed;
-}
-
-void EditorFileSystem::scan_changes() {
-
- if (scanning || scanning_changes|| thread)
- return;
-
- _update_extensions();
- sources_changed.clear();
- scanning_changes=true;
- scanning_changes_done=false;
-
- abort_scan=false;
-
- if (!use_threads) {
- if (filesystem) {
- EditorProgressBG pr("sources",TTR("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_changes=false;
- scanning_changes_done=true;
- emit_signal("sources_changed",sources_changed.size()>0);
- } else {
-
- ERR_FAIL_COND(thread_sources);
- set_process(true);
- scan_total=0;
- Thread::Settings s;
- s.priority=Thread::PRIORITY_LOW;
- thread_sources = Thread::create(_thread_func_sources,this,s);
- //tree->hide();
- //print_line("SCAN BEGIN!");
- //progress->show();
- }
-
-
-
-}
-
-void EditorFileSystem::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
-
- scan();
- } break;
- case NOTIFICATION_EXIT_TREE: {
- if (use_threads && thread) {
- //abort thread if in progress
- abort_scan=true;
- while(scanning) {
- OS::get_singleton()->delay_usec(1000);
- }
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread=NULL;
- WARN_PRINTS("Scan thread aborted...");
- set_process(false);
-
- }
-
- if (filesystem)
- memdelete(filesystem);
- if (new_filesystem)
- memdelete(new_filesystem);
- filesystem=NULL;
- new_filesystem=NULL;
-
- } break;
- case NOTIFICATION_PROCESS: {
-
- if (use_threads) {
-
- if (scanning_changes) {
-
- if (scanning_changes_done) {
-
- scanning_changes=false;
-
- set_process(false);
-
- 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);
- }
- } else if (!scanning) {
-
- set_process(false);
-
- if (filesystem)
- memdelete(filesystem);
- 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()));
-
-
-
- } else {
- //progress->set_text("Scanning...\n"+itos(total*100)+"%");
- }
- }
- } break;
- }
-
-}
-
-bool EditorFileSystem::is_scanning() const {
-
- return scanning || scanning_changes;
-}
-float EditorFileSystem::get_scanning_progress() const {
-
- return scan_total;
-}
-
-EditorFileSystemDirectory *EditorFileSystem::get_filesystem() {
-
- return filesystem;
-}
-
-void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory*p_dir,FileAccess *p_file) {
-
-
- if (!p_dir)
- return; //none
- p_file->store_line("::"+p_dir->get_path()+"::"+String::num(p_dir->modified_time));
-
- for(int i=0;i<p_dir->files.size();i++) {
-
- String s=p_dir->files[i]->file+"::"+p_dir->files[i]->type+"::"+itos(p_dir->files[i]->modified_time)+"::"+itos(p_dir->files[i]->import_modified_time);
- s+="::";
- for(int j=0;j<p_dir->files[i]->deps.size();j++) {
-
- if (j>0)
- s+="<>";
- s+=p_dir->files[i]->deps[j];
- }
-
- p_file->store_line(s);
- }
-
- for(int i=0;i<p_dir->subdirs.size();i++) {
-
- _save_filesystem_cache(p_dir->subdirs[i],p_file);
- }
-
-}
-
-
-
-
-
-
-bool EditorFileSystem::_find_file(const String& p_file,EditorFileSystemDirectory ** r_d, int &r_file_pos) const {
- //todo make faster
-
- if (!filesystem || scanning)
- return false;
-
-
- String f = GlobalConfig::get_singleton()->localize_path(p_file);
-
- if (!f.begins_with("res://"))
- return false;
- f=f.substr(6,f.length());
- f=f.replace("\\","/");
-
- Vector<String> path = f.split("/");
-
- if (path.size()==0)
- return false;
- String file=path[path.size()-1];
- path.resize(path.size()-1);
-
- EditorFileSystemDirectory *fs=filesystem;
-
- for(int i=0;i<path.size();i++) {
-
- if (path[i].begins_with("."))
- return false;
-
- 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 (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 (idx2==fs->get_subdir_count())
- fs->subdirs.push_back(efsd);
- else
- fs->subdirs.insert(idx2,efsd);
- fs=efsd;
- } else {
-
- fs=fs->get_subdir(idx);
- }
- }
-
-
- int cpos=-1;
- for(int i=0;i<fs->files.size();i++) {
-
- if (fs->files[i]->file==file) {
- cpos=i;
- break;
- }
- }
-
- r_file_pos=cpos;
- *r_d=fs;
-
- if (cpos!=-1) {
-
- return true;
- } else {
-
- return false;
- }
-
-
-}
-
-String EditorFileSystem::get_file_type(const String& p_file) const {
-
- EditorFileSystemDirectory *fs=NULL;
- int cpos=-1;
-
- if (!_find_file(p_file,&fs,cpos)) {
-
- return "";
- }
-
-
- return fs->files[cpos]->type;
-
-}
-
-EditorFileSystemDirectory* EditorFileSystem::find_file(const String& p_file,int* r_index) const {
-
- if (!filesystem || scanning)
- return NULL;
-
- EditorFileSystemDirectory *fs=NULL;
- int cpos=-1;
- if (!_find_file(p_file,&fs,cpos)) {
-
- return NULL;
- }
-
-
- if (r_index)
- *r_index=cpos;
-
- return fs;
-}
-
-
-EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String& p_path) {
-
- if (!filesystem || scanning)
- return NULL;
-
-
- String f = GlobalConfig::get_singleton()->localize_path(p_path);
-
- if (!f.begins_with("res://"))
- return NULL;
-
-
- f=f.substr(6,f.length());
- f=f.replace("\\","/");
- if (f==String())
- return filesystem;
-
- if (f.ends_with("/"))
- f=f.substr(0,f.length()-1);
-
- Vector<String> path = f.split("/");
-
- if (path.size()==0)
- return NULL;
-
- EditorFileSystemDirectory *fs=filesystem;
-
- for(int i=0;i<path.size();i++) {
-
-
- 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 (idx==-1) {
- return NULL;
- } else {
-
- fs=fs->get_subdir(idx);
- }
- }
-
- return fs;
-}
-
-void EditorFileSystem::_resource_saved(const String& p_path){
-
-
- //print_line("resource saved: "+p_path);
- EditorFileSystem::get_singleton()->update_file(p_path);
-
-}
-
-
-
-
-void EditorFileSystem::update_file(const String& p_file) {
-
- EditorFileSystemDirectory *fs=NULL;
- int cpos=-1;
-
- if (!_find_file(p_file,&fs,cpos)) {
-
- if (!fs)
- return;
- }
-
- if (!FileAccess::exists(p_file)) {
- //was removed
- memdelete( fs->files[cpos] );
- fs->files.remove(cpos);
- call_deferred("emit_signal","filesystem_changed"); //update later
- return;
-
- }
-
- String type = ResourceLoader::get_resource_type(p_file);
-
- if (cpos==-1) {
-
- int idx=0;
-
- for(int i=0;i<fs->files.size();i++) {
- if (p_file<fs->files[i]->file)
- break;
- idx++;
- }
-
- EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo );
- fi->file=p_file.get_file();
- fi->import_modified_time=0;
-
- if (idx==fs->files.size()) {
- fs->files.push_back(fi);
- } else {
-
- fs->files.insert(idx,fi);
- }
- cpos=idx;
-
-
- }
-
- //print_line("UPDATING: "+p_file);
- fs->files[cpos]->type=type;
- fs->files[cpos]->modified_time=FileAccess::get_modified_time(p_file);
- //if (FileAccess::exists(p_file+".import")) {
- // fs->files[cpos]->import_modified_time=FileAccess::get_modified_time(p_file+".import");
- //}
-
- EditorResourcePreview::get_singleton()->call_deferred("check_for_invalidation",p_file);
- call_deferred("emit_signal","filesystem_changed"); //update later
-
-}
-
-
-void EditorFileSystem::_reimport_file(const String& p_file) {
-
- print_line("REIMPORTING: "+p_file);
-
- EditorFileSystemDirectory *fs=NULL;
- int cpos=-1;
- bool found = _find_file(p_file,&fs,cpos);
- ERR_FAIL_COND(!found);
-
- //try to obtain existing params
-
- Map<StringName,Variant> params;
- String importer_name;
-
- if (FileAccess::exists(p_file+".import")) {
-
- Ref<ConfigFile> cf;
- cf.instance();
- Error err = cf->load(p_file+".import");
- if (err==OK) {
- List<String> sk;
- cf->get_section_keys("params",&sk);
- for(List<String>::Element *E=sk.front();E;E=E->next()) {
- params[E->get()]=cf->get_value("params",E->get());
- }
- importer_name = cf->get_value("remap","importer");
- }
- }
-
- Ref<ResourceImporter> importer;
- //find the importer
- if (importer_name!="") {
- importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
- }
-
- if (importer.is_null()) {
- //not found by name, find by extension
- importer = ResourceFormatImporter::get_singleton()->get_importer_by_extension(p_file.get_extension());
- if (importer.is_null()) {
- ERR_PRINT("BUG: File queued for import, but can't be imported!");
- ERR_FAIL();
-
- }
- }
-
- //mix with default params, in case a parameter is missing
-
- List<ResourceImporter::ImportOption> opts;
- importer->get_import_options(&opts);
- for (List<ResourceImporter::ImportOption>::Element *E=opts.front();E;E=E->next()) {
- if (!params.has(E->get().option.name)) { //this one is not present
- params[E->get().option.name]=E->get().default_value;
- }
- }
-
- //finally, perform import!!
- String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_file);
-
- List<String> import_variants;
- List<String> gen_files;
-
- Error err = importer->import(p_file,base_path,params,&import_variants,&gen_files);
-
- if (err!=OK) {
- ERR_PRINTS("Error importing: "+p_file);
- }
-
- //as import is complete, save the .import file
-
- FileAccess *f = FileAccess::open(p_file+".import",FileAccess::WRITE);
- ERR_FAIL_COND(!f);
-
- //write manually, as order matters ([remap] has to go first for performance).
- f->store_line("[remap]");
- f->store_line("");
- f->store_line("importer=\""+importer->get_importer_name()+"\"");
- if (importer->get_resource_type()!="") {
- f->store_line("type=\""+importer->get_resource_type()+"\"");
- }
-
-
- if (importer->get_save_extension()=="") {
- //no path
- } else if (import_variants.size()) {
- //import with variants
- for(List<String>::Element *E=import_variants.front();E;E=E->next()) {
-
-
- String path = base_path.c_escape()+"."+E->get()+"."+importer->get_save_extension();
-
- f->store_line("path."+E->get()+"=\""+path+"\"");
-
- }
- } else {
-
- f->store_line("path=\""+base_path+"."+importer->get_save_extension()+"\"");
- }
-
- f->store_line("");
- if (gen_files.size()) {
- f->store_line("[gen]");
- Array genf;
- for (List<String>::Element *E=gen_files.front();E;E=E->next()) {
- genf.push_back(E->get());
- }
-
- String value;
- VariantWriter::write_to_string(genf,value);
- f->store_line("files="+value);
- f->store_line("");
- }
-
-
- f->store_line("[params]");
- f->store_line("");
-
- //store options in provided order, to avoid file changing
-
-
- for (List<ResourceImporter::ImportOption>::Element *E=opts.front();E;E=E->next()) {
-
- String base = E->get().option.name;
- String value;
- VariantWriter::write_to_string(params[base],value);
- f->store_line(base+"="+value);
-
-
- }
-
- f->close();
- memdelete(f);
-
- //update modified times, to avoid reimport
- fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
- fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file+".import");
-
- //if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it
- //to reload properly
- if (ResourceCache::has(p_file)) {
-
- Resource *r = ResourceCache::get(p_file);
-
- if (r->get_import_path()!=String()) {
-
- String dst_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_file);
- r->set_import_path(dst_path);
- r->set_import_last_modified_time(0);
- }
- }
-}
-
-void EditorFileSystem::reimport_files(const Vector<String>& p_files) {
-
- importing=true;
- EditorProgress pr("reimport",TTR("(Re)Importing Assets"),p_files.size());
- for(int i=0;i<p_files.size();i++) {
- pr.step(p_files[i].get_file(),i);
-
- _reimport_file(p_files[i]);
- }
-
- _save_filesystem_cache();
- importing=false;
- if (!is_scanning()) {
- emit_signal("filesystem_changed");
- }
-}
-
-void EditorFileSystem::_bind_methods() {
-
-
- ClassDB::bind_method(_MD("get_filesystem:EditorFileSystemDirectory"),&EditorFileSystem::get_filesystem);
- ClassDB::bind_method(_MD("is_scanning"),&EditorFileSystem::is_scanning);
- ClassDB::bind_method(_MD("get_scanning_progress"),&EditorFileSystem::get_scanning_progress);
- ClassDB::bind_method(_MD("scan"),&EditorFileSystem::scan);
- ClassDB::bind_method(_MD("scan_sources"),&EditorFileSystem::scan_changes);
- ClassDB::bind_method(_MD("update_file","path"),&EditorFileSystem::update_file);
- ClassDB::bind_method(_MD("get_filesystem_path:EditorFileSystemDirectory","path"),&EditorFileSystem::get_filesystem_path);
- ClassDB::bind_method(_MD("get_file_type","path"),&EditorFileSystem::get_file_type);
-
- ADD_SIGNAL( MethodInfo("filesystem_changed") );
- ADD_SIGNAL( MethodInfo("sources_changed",PropertyInfo(Variant::BOOL,"exist")) );
-
-}
-
-void EditorFileSystem::_update_extensions() {
-
- valid_extensions.clear();
- import_extensions.clear();
-
- 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());
- }
-
- extensionsl.clear();
- ResourceFormatImporter::get_singleton()->get_recognized_extensions(&extensionsl);
- for(List<String>::Element *E = extensionsl.front();E;E=E->next()) {
-
- import_extensions.insert(E->get());
- }
-}
-
-EditorFileSystem::EditorFileSystem() {
-
- reimport_on_missing_imported_files = GLOBAL_DEF("editor/reimport_missing_imported_files",true);
-
- singleton=this;
- filesystem=memnew( EditorFileSystemDirectory ); //like, empty
-
- thread = NULL;
- scanning=false;
- importing=false;
- use_threads=true;
- thread_sources=NULL;
- new_filesystem=NULL;
-
- scanning_changes=false;
- ResourceSaver::set_save_callback(_resource_saved);
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (da->change_dir("res://.import")!=OK) {
- da->make_dir("res://.import");
- }
- memdelete(da);
-
- scan_total=0;
-}
-
-EditorFileSystem::~EditorFileSystem() {
-
-
-}
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
deleted file mode 100644
index 03e631cbc3..0000000000
--- a/tools/editor/editor_help.cpp
+++ /dev/null
@@ -1,1929 +0,0 @@
-/*************************************************************************/
-/* editor_help.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_help.h"
-
-#include "editor_node.h"
-#include "editor_settings.h"
-#include "os/keyboard.h"
-#include "doc_data_compressed.h"
-#include "tools/editor/plugins/script_editor_plugin.h"
-
-void EditorHelpSearch::popup() {
- popup_centered_ratio(0.6);
- if (search_box->get_text()!="") {
- search_box->select_all();
- _update_search();
- }
- search_box->grab_focus();
-}
-
-void EditorHelpSearch::popup(const String& p_term) {
-
- popup_centered_ratio(0.6);
- if (p_term!="") {
- search_box->set_text(p_term);
- search_box->select_all();
- _update_search();
- } else
- search_box->clear();
- search_box->grab_focus();
-}
-
-
-void EditorHelpSearch::_text_changed(const String& p_newtext) {
-
- _update_search();
-}
-
-void EditorHelpSearch::_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 ) ) {
-
- search_options->call("_gui_input",p_ie);
- search_box->accept_event();
- }
-
-}
-
-void EditorHelpSearch::_update_search() {
-
- search_options->clear();
- search_options->set_hide_root(true);
-
- /*
- TreeItem *root = search_options->create_item();
- _parse_fs(EditorFileSystem::get_singleton()->get_filesystem());
-*/
-
- List<StringName> type_list;
- ClassDB::get_class_list(&type_list);
-
- DocData *doc=EditorHelp::get_doc_data();
- String term = search_box->get_text();
- if (term.length()<2)
- return;
-
- TreeItem *root = search_options->create_item();
-
-
-
- Ref<Texture> def_icon = get_icon("Node","EditorIcons");
- //classes first
- for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
-
- if (E->key().findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_name:"+E->key());
- item->set_text(0,E->key()+" (Class)");
- if (has_icon(E->key(),"EditorIcons"))
- item->set_icon(0,get_icon(E->key(),"EditorIcons"));
- else
- item->set_icon(0,def_icon);
-
-
- }
-
- }
-
- //class methods, etc second
- for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
-
-
- DocData::ClassDoc & c = E->get();
-
- Ref<Texture> cicon;
- if (has_icon(E->key(),"EditorIcons"))
- cicon=get_icon(E->key(),"EditorIcons");
- else
- cicon=def_icon;
-
-
- for(int i=0;i<c.methods.size();i++) {
- if( (term.begins_with(".") && c.methods[i].name.begins_with(term.right(1)))
- || (term.ends_with("(") && c.methods[i].name.ends_with(term.left(term.length()-1).strip_edges()))
- || (term.begins_with(".") && term.ends_with("(") && c.methods[i].name==term.substr(1,term.length()-2).strip_edges())
- || c.methods[i].name.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_method:"+E->key()+":"+c.methods[i].name);
- item->set_text(0,E->key()+"."+c.methods[i].name+" (Method)");
- item->set_icon(0,cicon);
- }
- }
-
- for(int i=0;i<c.signals.size();i++) {
-
- if (c.signals[i].name.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_signal:"+E->key()+":"+c.signals[i].name);
- item->set_text(0,E->key()+"."+c.signals[i].name+" (Signal)");
- item->set_icon(0,cicon);
- }
- }
-
- for(int i=0;i<c.constants.size();i++) {
-
- if (c.constants[i].name.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_constant:"+E->key()+":"+c.constants[i].name);
- item->set_text(0,E->key()+"."+c.constants[i].name+" (Constant)");
- item->set_icon(0,cicon);
- }
- }
-
- for(int i=0;i<c.properties.size();i++) {
-
- if (c.properties[i].name.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_property:"+E->key()+":"+c.properties[i].name);
- item->set_text(0,E->key()+"."+c.properties[i].name+" (Property)");
- item->set_icon(0,cicon);
- }
- }
-
- for(int i=0;i<c.theme_properties.size();i++) {
-
- if (c.theme_properties[i].name.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_theme_item:"+E->key()+":"+c.theme_properties[i].name);
- item->set_text(0,E->key()+"."+c.theme_properties[i].name+" (Theme Item)");
- item->set_icon(0,cicon);
- }
- }
-
-
- }
-
- //same but descriptions
-
- for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
-
-
- DocData::ClassDoc & c = E->get();
-
- Ref<Texture> cicon;
- if (has_icon(E->key(),"EditorIcons"))
- cicon=get_icon(E->key(),"EditorIcons");
- else
- cicon=def_icon;
-
- if (c.description.findn(term)!=-1) {
-
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_desc:"+E->key());
- item->set_text(0,E->key()+" (Class Description)");
- item->set_icon(0,cicon);
-
- }
-
- for(int i=0;i<c.methods.size();i++) {
-
- if (c.methods[i].description.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_method_desc:"+E->key()+":"+c.methods[i].name);
- item->set_text(0,E->key()+"."+c.methods[i].name+" (Method Description)");
- item->set_icon(0,cicon);
- }
- }
-
- for(int i=0;i<c.signals.size();i++) {
-
- if (c.signals[i].description.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_signal:"+E->key()+":"+c.signals[i].name);
- item->set_text(0,E->key()+"."+c.signals[i].name+" (Signal Description)");
- item->set_icon(0,cicon);
- }
- }
-
- for(int i=0;i<c.constants.size();i++) {
-
- if (c.constants[i].description.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_constant:"+E->key()+":"+c.constants[i].name);
- item->set_text(0,E->key()+"."+c.constants[i].name+" (Constant Description)");
- item->set_icon(0,cicon);
- }
- }
-
- for(int i=0;i<c.properties.size();i++) {
-
- if (c.properties[i].description.findn(term)!=-1) {
-
- TreeItem *item = search_options->create_item(root);
- item->set_metadata(0,"class_property_desc:"+E->key()+":"+c.properties[i].name);
- item->set_text(0,E->key()+"."+c.properties[i].name+" (Property Description)");
- item->set_icon(0,cicon);
- }
- }
-
- }
-
- get_ok()->set_disabled(root->get_children()==NULL);
-
-}
-
-void EditorHelpSearch::_confirmed() {
-
- TreeItem *ti = search_options->get_selected();
- if (!ti)
- return;
-
- String mdata=ti->get_metadata(0);
- emit_signal("go_to_help",mdata);
- editor->call("_editor_select",EditorNode::EDITOR_SCRIPT); // in case EditorHelpSearch beeen invoked on top of other editor window
- // go to that
- hide();
-}
-
-void EditorHelpSearch::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- connect("confirmed",this,"_confirmed");
- _update_search();
- }
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
-
- if (is_visible_in_tree()) {
-
- search_box->call_deferred("grab_focus"); // still not visible
- search_box->select_all();
- }
- }
-
-}
-
-
-void EditorHelpSearch::_bind_methods() {
-
- ClassDB::bind_method(_MD("_text_changed"),&EditorHelpSearch::_text_changed);
- ClassDB::bind_method(_MD("_confirmed"),&EditorHelpSearch::_confirmed);
- ClassDB::bind_method(_MD("_sbox_input"),&EditorHelpSearch::_sbox_input);
- ClassDB::bind_method(_MD("_update_search"),&EditorHelpSearch::_update_search);
-
- ADD_SIGNAL(MethodInfo("go_to_help"));
-
-}
-
-
-EditorHelpSearch::EditorHelpSearch() {
-
- editor=EditorNode::get_singleton();
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
-
- HBoxContainer *sb_hb = memnew( HBoxContainer);
- search_box = memnew( LineEdit );
- sb_hb->add_child(search_box);
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- Button *sb = memnew( Button(TTR("Search")));
- sb->connect("pressed",this,"_update_search");
- sb_hb->add_child(sb);
- vbc->add_margin_child(TTR("Search:"),sb_hb);
- search_box->connect("text_changed",this,"_text_changed");
- search_box->connect("gui_input",this,"_sbox_input");
- search_options = memnew( Tree );
- vbc->add_margin_child(TTR("Matches:"),search_options,true);
- get_ok()->set_text(TTR("Open"));
- get_ok()->set_disabled(true);
- register_text_enter(search_box);
- set_hide_on_ok(false);
- search_options->connect("item_activated",this,"_confirmed");
- set_title(TTR("Search Help"));
-
- //search_options->set_hide_root(true);
-
-}
-
-/////////////////////////////////
-
-////////////////////////////////////
-/// /////////////////////////////////
-
-
-
-void EditorHelpIndex::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root) {
-
- if (p_types.has(p_type))
- return;
- /*
- if (!ClassDB::is_type(p_type,base) || p_type==base)
- return;
- */
-
- String inherits=EditorHelp::get_doc_data()->class_list[p_type].inherits;
-
- TreeItem *parent=p_root;
-
-
- if (inherits.length()) {
-
- if (!p_types.has(inherits)) {
-
- add_type(inherits,p_types,p_root);
- }
-
- if (p_types.has(inherits) )
- parent=p_types[inherits];
- }
-
- TreeItem *item = class_list->create_item(parent);
- item->set_metadata(0,p_type);
- item->set_tooltip(0,EditorHelp::get_doc_data()->class_list[p_type].brief_description);
- item->set_text(0,p_type);
-
-
- if (has_icon(p_type,"EditorIcons")) {
-
- item->set_icon(0, get_icon(p_type,"EditorIcons"));
- }
-
- p_types[p_type]=item;
-}
-
-
-void EditorHelpIndex::_tree_item_selected() {
-
-
- TreeItem *s=class_list->get_selected();
- if (!s)
- return;
-
- emit_signal("open_class",s->get_text(0));
-
- hide();
-
- //_goto_desc(s->get_text(0));
-
-}
-
-void EditorHelpIndex::select_class(const String& p_class) {
-
- if (!tree_item_map.has(p_class))
- return;
- tree_item_map[p_class]->select(0);
- class_list->ensure_cursor_is_visible();
-}
-
-void EditorHelpIndex::popup() {
-
- popup_centered_ratio(0.6);
-
- search_box->set_text("");
- _update_class_list();
-}
-
-void EditorHelpIndex::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- _update_class_list();
-
- connect("confirmed",this,"_tree_item_selected");
-
- } else if (p_what==NOTIFICATION_POST_POPUP) {
-
- search_box->call_deferred("grab_focus");
- }
-}
-
-void EditorHelpIndex::_text_changed(const String& p_text) {
-
- _update_class_list();
-}
-
-void EditorHelpIndex::_update_class_list() {
-
- class_list->clear();
- tree_item_map.clear();
- TreeItem *root = class_list->create_item();
- class_list->set_hide_root(true);
-
- String filter = search_box->get_text().strip_edges();
- String to_select = "";
-
- for(Map<String,DocData::ClassDoc>::Element *E=EditorHelp::get_doc_data()->class_list.front();E;E=E->next()) {
-
- if (filter == "") {
- add_type(E->key(),tree_item_map,root);
- } else {
-
- bool found = false;
- String type = E->key();
-
- while(type != "") {
- if (filter.is_subsequence_ofi(type)) {
-
- if (to_select.empty()) {
- to_select = type;
- }
-
- found=true;
- break;
- }
-
- type = EditorHelp::get_doc_data()->class_list[type].inherits;
- }
-
- if (found) {
- add_type(E->key(),tree_item_map,root);
- }
- }
- }
-
- if (tree_item_map.has(filter)) {
- select_class(filter);
- } else if (to_select != "") {
- select_class(to_select);
- }
-}
-
-
-void EditorHelpIndex::_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 ) ) {
-
- class_list->call("_gui_input",p_ie);
- search_box->accept_event();
- }
-}
-
-void EditorHelpIndex::_bind_methods() {
-
- ClassDB::bind_method("_tree_item_selected",&EditorHelpIndex::_tree_item_selected);
- ClassDB::bind_method("_text_changed",&EditorHelpIndex::_text_changed);
- ClassDB::bind_method("_sbox_input",&EditorHelpIndex::_sbox_input);
- ClassDB::bind_method("select_class",&EditorHelpIndex::select_class);
- ADD_SIGNAL( MethodInfo("open_class"));
-}
-
-
-
-EditorHelpIndex::EditorHelpIndex() {
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
-
- search_box = memnew( LineEdit );
- vbc->add_margin_child(TTR("Search:"), search_box);
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
-
- register_text_enter(search_box);
-
- search_box->connect("text_changed", this, "_text_changed");
- search_box->connect("gui_input", this, "_sbox_input");
-
- class_list = memnew( Tree );
- vbc->add_margin_child(TTR("Class List:")+" ", class_list, true);
- class_list->set_v_size_flags(SIZE_EXPAND_FILL);
-
- class_list->connect("item_activated",this,"_tree_item_selected");
-
- get_ok()->set_text(TTR("Open"));
- set_title(TTR("Search Classes"));
-}
-
-
-
-/////////////////////////////////
-
-////////////////////////////////////
-/// /////////////////////////////////
-DocData *EditorHelp::doc=NULL;
-
-void EditorHelp::_unhandled_key_input(const InputEvent& p_ev) {
-
- if (!is_visible_in_tree())
- return;
- if ( p_ev.key.mod.control && p_ev.key.scancode==KEY_F) {
-
- search->grab_focus();
- search->select_all();
- }
-}
-
-void EditorHelp::_search(const String&) {
-
- if (search->get_text()=="")
- return;
-
-
- String stext=search->get_text();
- bool keep = prev_search==stext;
-
- bool ret = class_desc->search(stext, keep);
- if (!ret) {
- class_desc->search(stext, false);
- }
-
- prev_search=stext;
-
-
-}
-
-#if 0
-void EditorHelp::_button_pressed(int p_idx) {
-
- if (p_idx==PAGE_CLASS_LIST) {
-
- //edited_class->set_pressed(false);
- //class_list_button->set_pressed(true);
- //tabs->set_current_tab(PAGE_CLASS_LIST);
-
- } else if (p_idx==PAGE_CLASS_DESC) {
-
- //edited_class->set_pressed(true);
- //class_list_button->set_pressed(false);
- //tabs->set_current_tab(PAGE_CLASS_DESC);
-
- } else if (p_idx==PAGE_CLASS_PREV) {
-
- if (history_pos<2)
- return;
- history_pos--;
- ERR_FAIL_INDEX(history_pos-1,history.size());
- _goto_desc(history[history_pos-1].c,false,history[history_pos-1].scroll);
- _update_history_buttons();
-
-
- } else if (p_idx==PAGE_CLASS_NEXT) {
-
- if (history_pos>=history.size())
- return;
-
- history_pos++;
- ERR_FAIL_INDEX(history_pos-1,history.size());
- _goto_desc(history[history_pos-1].c,false,history[history_pos-1].scroll);
- _update_history_buttons();
-
- } else if (p_idx==PAGE_SEARCH) {
-
- _search("");
- }
-}
-
-
-#endif
-
-void EditorHelp::_class_list_select(const String& p_select) {
-
- _goto_desc(p_select);
-}
-
-void EditorHelp::_class_desc_select(const String& p_select) {
-
-
-
- //print_line("LINK: "+p_select);
- if (p_select.begins_with("#")) {
- //_goto_desc(p_select.substr(1,p_select.length()));
- emit_signal("go_to_help","class_name:"+p_select.substr(1,p_select.length()));
- return;
- } else if (p_select.begins_with("@")) {
-
- String m = p_select.substr(1,p_select.length());
-
- if (m.find(".")!=-1) {
- //must go somewhere else
-
- emit_signal("go_to_help","class_method:"+m.get_slice(".",0)+":"+m.get_slice(".",0));
- } else {
-
- if (!method_line.has(m))
- return;
- class_desc->scroll_to_line(method_line[m]);
- }
-
- }
-
-
-}
-
-void EditorHelp::_class_desc_input(const InputEvent& p_input) {
- if (p_input.type==InputEvent::MOUSE_BUTTON && p_input.mouse_button.pressed && p_input.mouse_button.button_index==1) {
- class_desc->set_selection_enabled(false);
- class_desc->set_selection_enabled(true);
- }
- set_focused();
-}
-
-void EditorHelp::_add_type(const String& p_type) {
-
- String t = p_type;
- if (t=="")
- t="void";
- bool can_ref = (t!="int" && t!="real" && t!="bool" && t!="void");
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color"));
- if (can_ref)
- class_desc->push_meta("#"+t); //class
- class_desc->add_text(t);
- if (can_ref)
- class_desc->pop();
- class_desc->pop();
-
-}
-
-void EditorHelp::_scroll_changed(double p_scroll) {
-
- if (scroll_locked)
- return;
-
- if (!class_desc->get_v_scroll()->is_visible())
- p_scroll=0;
-
- //history[p].scroll=p_scroll;
-}
-
-Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
-
- //ERR_FAIL_COND(!doc->class_list.has(p_class));
- if (!doc->class_list.has(p_class))
- return ERR_DOES_NOT_EXIST;
-
-
- //if (tree_item_map.has(p_class)) {
- select_locked = true;
- //}
-
- class_desc->show();
- //tabs->set_current_tab(PAGE_CLASS_DESC);
- description_line=0;
-
- if (p_class==edited_class)
- return OK; //already there
-
- scroll_locked=true;
-
- class_desc->clear();
- method_line.clear();
- edited_class=p_class;
- //edited_class->show();
-
-
- DocData::ClassDoc cd=doc->class_list[p_class]; //make a copy, so we can sort without worrying
-
- Color h_color;
-
- Ref<Font> doc_font = get_font("doc","EditorFonts");
- Ref<Font> doc_title_font = get_font("doc_title","EditorFonts");
- Ref<Font> doc_code_font = get_font("doc_source","EditorFonts");
-
-
- h_color=Color(1,1,1,1);
-
- class_desc->push_font(doc_title_font);
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->add_text(TTR("Class:")+" ");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color"));
- _add_text(p_class);
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
-
- if (cd.inherits!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Inherits:")+" ");
- class_desc->pop();
- class_desc->pop();
-
- String inherits = cd.inherits;
-
- class_desc->push_font(doc_font);
-
- while (inherits != "") {
- _add_type(inherits);
-
- inherits = doc->class_list[inherits].inherits;
-
- if (inherits != "") {
- class_desc->add_text(" , ");
- }
- }
-
- class_desc->pop();
- class_desc->add_newline();
- }
-
- if (ClassDB::class_exists(cd.name)) {
-
- bool found = false;
- bool prev = false;
-
- for (Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
-
- if (E->get().inherits == cd.name) {
-
- if (!found) {
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Inherited by:")+" ");
- class_desc->pop();
- class_desc->pop();
-
- found = true;
- class_desc->push_font(doc_font);
- }
-
- if (prev) {
-
- class_desc->add_text(" , ");
- prev = false;
- }
-
- _add_type(E->get().name);
- prev = true;
- }
- }
-
- if (found)
- class_desc->pop();
-
- class_desc->add_newline();
- }
-
- class_desc->add_newline();
-
- if (cd.brief_description!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Brief Description:"));
- class_desc->pop();
- class_desc->pop();
-
- //class_desc->add_newline();
- class_desc->add_newline();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->push_font( doc_font );
- class_desc->push_indent(1);
- _add_text(cd.brief_description);
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- }
-
- Set<String> skip_methods;
- bool property_descr=false;
-
- if (cd.properties.size()) {
-
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Members:"));
- class_desc->pop();
- class_desc->pop();
- //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.properties.size();i++) {
- property_line[cd.properties[i].name]=class_desc->get_line_count()-2; //gets overriden if description
-
- class_desc->push_cell();
- class_desc->push_align(RichTextLabel::ALIGN_RIGHT);
- class_desc->push_font(doc_code_font);
- _add_type(cd.properties[i].type);
- class_desc->add_text(" ");
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
-
- bool describe=false;
-
- if (cd.properties[i].setter!="") {
- skip_methods.insert(cd.properties[i].setter);
- describe=true;
-
- }
- if (cd.properties[i].getter!="") {
- skip_methods.insert(cd.properties[i].getter);
- describe=true;
- }
-
- if (cd.properties[i].description!="") {
- describe=true;
-
- }
- class_desc->push_cell();
- if (describe) {
- class_desc->push_meta("@"+cd.properties[i].name);
- }
-
- class_desc->push_font(doc_code_font);
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- _add_text(cd.properties[i].name);
-
- if (describe) {
- class_desc->pop();
- }
-
-
- if (cd.properties[i].brief_description!="") {
- class_desc->push_font(doc_font);
- class_desc->add_text(" ");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
- _add_text(cd.properties[i].description);
- class_desc->pop();
- class_desc->pop();
-
- }
-
- if (describe) {
- property_descr=true;
- }
-
-
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
-
- }
-
-
- class_desc->pop(); //table
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- }
-
-
- bool method_descr=false;
- bool sort_methods = EditorSettings::get_singleton()->get("text_editor/help/sort_functions_alphabetically");
-
- Vector<DocData::MethodDoc> methods;
-
- for(int i=0;i<cd.methods.size();i++) {
- if (skip_methods.has(cd.methods[i].name))
- continue;
- methods.push_back(cd.methods[i]);
- }
-
- if (methods.size()) {
-
- if (sort_methods)
- methods.sort();
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Public Methods:"));
- class_desc->pop();
- class_desc->pop();
-
- //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<methods.size();i++) {
-
- class_desc->push_cell();
-
-
- method_line[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(methods[i].return_type);
- //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 (methods[i].description!="") {
- method_descr=true;
- class_desc->push_meta("@"+methods[i].name);
- }
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- _add_text(methods[i].name);
- class_desc->pop();
- if (methods[i].description!="")
- class_desc->pop();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(methods[i].arguments.size()?"( ":"(");
- class_desc->pop();
- for(int j=0;j<methods[i].arguments.size();j++) {
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- if (j>0)
- class_desc->add_text(", ");
- _add_type(methods[i].arguments[j].type);
- class_desc->add_text(" ");
- _add_text(methods[i].arguments[j].name);
- if (methods[i].arguments[j].default_value!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text("=");
- class_desc->pop();
- _add_text(methods[i].arguments[j].default_value);
- }
-
- class_desc->pop();
- }
-
- if (methods[i].qualifiers.find("vararg")!=-1) {
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->add_text(",");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(" ... ");
- class_desc->pop();
- class_desc->pop();
- }
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(methods[i].arguments.size()?" )":")");
- class_desc->pop();
- if (methods[i].qualifiers!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->add_text(" ");
- _add_text(methods[i].qualifiers);
- class_desc->pop();
-
- }
- class_desc->pop();//monofont
- //class_desc->add_newline();
- class_desc->pop(); //cell
-
- }
- class_desc->pop(); //table
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
-
- }
-
-
- if (cd.theme_properties.size()) {
-
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("GUI Theme Items:"));
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
-
- class_desc->push_indent(1);
-
- //class_desc->add_newline();
-
- for(int i=0;i<cd.theme_properties.size();i++) {
-
- theme_property_line[cd.theme_properties[i].name]=class_desc->get_line_count()-2; //gets overriden if description
- class_desc->push_font(doc_code_font);
- _add_type(cd.theme_properties[i].type);
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->add_text(" ");
- _add_text(cd.theme_properties[i].name);
- class_desc->pop();
- class_desc->pop();
-
- if (cd.theme_properties[i].description!="") {
- class_desc->push_font(doc_font);
- class_desc->add_text(" ");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
- _add_text(cd.theme_properties[i].description);
- class_desc->pop();
- class_desc->pop();
-
- }
-
- class_desc->add_newline();
- }
-
- class_desc->pop();
- class_desc->add_newline();
- }
-
- if (cd.signals.size()) {
-
- if (sort_methods) {
- cd.signals.sort();
- }
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Signals:"));
- class_desc->pop();
- class_desc->pop();
-
- class_desc->add_newline();
- //class_desc->add_newline();
-
- class_desc->push_indent(1);
-
- for(int i=0;i<cd.signals.size();i++) {
-
- signal_line[cd.signals[i].name]=class_desc->get_line_count()-2; //gets overriden if description
- class_desc->push_font(doc_code_font); // monofont
- //_add_type("void");
- //class_desc->add_text(" ");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- _add_text(cd.signals[i].name);
- class_desc->pop();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(cd.signals[i].arguments.size()?"( ":"(");
- class_desc->pop();
- for(int j=0;j<cd.signals[i].arguments.size();j++) {
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- if (j>0)
- class_desc->add_text(", ");
- _add_type(cd.signals[i].arguments[j].type);
- class_desc->add_text(" ");
- _add_text(cd.signals[i].arguments[j].name);
- if (cd.signals[i].arguments[j].default_value!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text("=");
- class_desc->pop();
- _add_text(cd.signals[i].arguments[j].default_value);
- }
-
- class_desc->pop();
- }
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(cd.signals[i].arguments.size()?" )":")");
- class_desc->pop();
- class_desc->pop(); // end monofont
- if (cd.signals[i].description!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
- class_desc->add_text(" ");
- _add_text(cd.signals[i].description);
- class_desc->pop();
-
- }
- class_desc->add_newline();
-
- }
-
- class_desc->pop();
- class_desc->add_newline();
-
- }
-
- if (cd.constants.size()) {
-
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Constants:"));
- class_desc->pop();
- class_desc->pop();
- class_desc->push_indent(1);
-
- class_desc->add_newline();
- //class_desc->add_newline();
-
- for(int i=0;i<cd.constants.size();i++) {
-
- constant_line[cd.constants[i].name]=class_desc->get_line_count()-2;
- class_desc->push_font(doc_code_font);
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/base_type_color"));
- _add_text(cd.constants[i].name);
- class_desc->pop();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(" = ");
- class_desc->pop();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- _add_text(cd.constants[i].value);
- class_desc->pop();
- class_desc->pop();
- if (cd.constants[i].description!="") {
- class_desc->push_font(doc_font);
- class_desc->add_text(" ");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"));
- _add_text(cd.constants[i].description);
- class_desc->pop();
- class_desc->pop();
- }
-
- class_desc->add_newline();
- }
-
- class_desc->pop();
- class_desc->add_newline();
-
-
- }
-
- if (cd.description!="") {
-
- description_line=class_desc->get_line_count()-2;
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Description:"));
- class_desc->pop();
- class_desc->pop();
-
- class_desc->add_newline();
- class_desc->add_newline();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->push_font( doc_font );
- class_desc->push_indent(1);
- _add_text(cd.description);
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- }
-
- if (property_descr) {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Property Description:"));
- class_desc->pop();
- class_desc->pop();
-
- class_desc->add_newline();
- class_desc->add_newline();
-
-
- for(int i=0;i<cd.properties.size();i++) {
-
- method_line[cd.properties[i].name]=class_desc->get_line_count()-2;
-
- class_desc->push_font(doc_code_font);
- _add_type(cd.properties[i].type);
-
- class_desc->add_text(" ");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- _add_text(cd.properties[i].name);
- class_desc->pop(); //color
-
- class_desc->add_text(" ");
-
- class_desc->pop(); //font
-
- if (cd.properties[i].setter!="") {
-
- class_desc->push_font( doc_font );
-
- class_desc->push_indent(2);
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->add_text("Setter: ");
- class_desc->pop();
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->add_text(cd.properties[i].setter+"(value)");
- class_desc->pop(); //color
-
- class_desc->pop(); //indent
-
- class_desc->pop(); //font
-
- }
-
- if (cd.properties[i].getter!="") {
-
- class_desc->push_font( doc_font );
-
- class_desc->push_indent(2);
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->add_text("Getter: ");
- class_desc->pop();
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->add_text(cd.properties[i].getter+"()");
- class_desc->pop(); //color
-
- class_desc->pop(); //indent
-
- class_desc->pop(); //font
-
- }
-
- class_desc->add_newline();
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->push_font( doc_font );
- class_desc->push_indent(1);
- _add_text(cd.properties[i].description);
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- class_desc->add_newline();
-
- }
-
- }
-
- if (method_descr) {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->push_font(doc_title_font);
- class_desc->add_text(TTR("Method Description:"));
- class_desc->pop();
- class_desc->pop();
-
- class_desc->add_newline();
- class_desc->add_newline();
-
-
- for(int i=0;i<methods.size();i++) {
-
- method_line[methods[i].name]=class_desc->get_line_count()-2;
-
- class_desc->push_font(doc_code_font);
- _add_type(methods[i].return_type);
-
- class_desc->add_text(" ");
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- _add_text(methods[i].name);
- class_desc->pop();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(methods[i].arguments.size()?"( ":"(");
- class_desc->pop();
- for(int j=0;j<methods[i].arguments.size();j++) {
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- if (j>0)
- class_desc->add_text(", ");
- _add_type(methods[i].arguments[j].type);
- class_desc->add_text(" ");
- _add_text(methods[i].arguments[j].name);
- if (methods[i].arguments[j].default_value!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text("=");
- class_desc->pop();
- _add_text(methods[i].arguments[j].default_value);
- }
-
- class_desc->pop();
- }
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"));
- class_desc->add_text(methods[i].arguments.size()?" )":")");
- class_desc->pop();
- if (methods[i].qualifiers!="") {
-
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- class_desc->add_text(" ");
- _add_text(methods[i].qualifiers);
- class_desc->pop();
-
- }
-
- class_desc->pop();
-
- class_desc->add_newline();
- class_desc->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- class_desc->push_font( doc_font );
- class_desc->push_indent(1);
- _add_text(methods[i].description);
- class_desc->pop();
- class_desc->pop();
- class_desc->pop();
- class_desc->add_newline();
- class_desc->add_newline();
- class_desc->add_newline();
-
- }
-
-
-
-
-
- }
-
-
-
- scroll_locked=false;
-
- return OK;
-}
-
-void EditorHelp::_request_help(const String& p_string) {
- Error err = _goto_desc(p_string);
- if (err==OK) {
- editor->call("_editor_select",EditorNode::EDITOR_SCRIPT);
- }
- //100 palabras
-}
-
-
-void EditorHelp::_help_callback(const String& p_topic) {
-
- String what = p_topic.get_slice(":",0);
- String clss = p_topic.get_slice(":",1);
- String name;
- if (p_topic.get_slice_count(":")==3)
- name=p_topic.get_slice(":",2);
-
- _request_help(clss); //first go to class
-
- int line=0;
-
- if (what=="class_desc") {
- line=description_line;
- } else if (what=="class_signal") {
- if (signal_line.has(name))
- line=signal_line[name];
- } else if (what=="class_method" || what=="class_method_desc") {
- if (method_line.has(name))
- line=method_line[name];
- } else if (what=="class_property") {
-
- if (property_line.has(name))
- line=property_line[name];
- } else if (what=="class_theme_item") {
-
- if (theme_property_line.has(name))
- line=theme_property_line[name];
- } else if (what=="class_constant") {
-
- if (constant_line.has(name))
- line=constant_line[name];
- }
-
- class_desc->call_deferred("scroll_to_line", line);
-
-}
-
-
-
-static void _add_text_to_rt(const String& p_bbcode,RichTextLabel *p_rt) {
-
- DocData *doc = EditorHelp::get_doc_data();
- String base_path;
-
- /*p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"));
- p_rt->push_font( get_font("normal","Fonts") );
- p_rt->push_indent(1);*/
- int pos = 0;
-
- Ref<Font> doc_font = p_rt->get_font("doc","EditorFonts");
- Ref<Font> doc_code_font = p_rt->get_font("doc_source","EditorFonts");
-
- String bbcode=p_bbcode.replace("\t"," ").replace("\r"," ").strip_edges();
-
- //change newlines for double newlines
- for(int i=0;i<bbcode.length();i++) {
-
- //find valid newlines (double)
- if (bbcode[i]=='\n') {
- bool dnl=false;
- int j=i+1;
- for(;j<p_bbcode.length();j++) {
- if (bbcode[j]==' ')
- continue;
- if (bbcode[j]=='\n') {
- dnl=true;
- break;
- }
- break;
- }
-
- if (dnl) {
- bbcode[i]=0xFFFF;
- //keep
- i=j;
- } else {
- bbcode=bbcode.insert(i,"\n");
- i++;
- //bbcode[i]=' ';
- //i=j-1;
- }
- }
- }
-
- //remove double spaces or spaces after newlines
- for(int i=0;i<bbcode.length();i++) {
-
- if (bbcode[i]==' ' || bbcode[i]=='\n' || bbcode[i]==0xFFFF) {
-
- for(int j=i+1;j<p_bbcode.length();j++) {
- if (bbcode[j]==' ') {
- bbcode.remove(j);
- j--;
- continue;
- } else {
- break;
- }
- }
- }
- }
-
- //change newlines to double newlines
-
- CharType dnls[2]={0xFFFF,0};
- bbcode=bbcode.replace(dnls,"\n");
-
-
- List<String> tag_stack;
-
- while(pos < bbcode.length()) {
-
-
- int brk_pos = bbcode.find("[",pos);
-
- if (brk_pos<0)
- brk_pos=bbcode.length();
-
- if (brk_pos > pos) {
- p_rt->add_text(bbcode.substr(pos,brk_pos-pos));
-
- }
-
- if (brk_pos==bbcode.length())
- break; //nothing else o add
-
- int brk_end = bbcode.find("]",brk_pos+1);
-
- if (brk_end==-1) {
- //no close, add the rest
- p_rt->add_text(bbcode.substr(brk_pos,bbcode.length()-brk_pos));
-
- break;
- }
-
-
- String tag = bbcode.substr(brk_pos+1,brk_end-brk_pos-1);
-
-
- if (tag.begins_with("/")) {
- bool tag_ok = tag_stack.size() && tag_stack.front()->get()==tag.substr(1,tag.length());
- if (tag_stack.size()) {
-
-
-
- }
- if (!tag_ok) {
-
- p_rt->add_text("[");
- pos++;
- continue;
- }
-
- tag_stack.pop_front();
- pos=brk_end+1;
- if (tag!="/img")
- p_rt->pop();
-
- } else if (tag.begins_with("method ")) {
-
- String m = tag.substr(7,tag.length());
- p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- p_rt->push_meta("@"+m);
- p_rt->add_text(m+"()");
- p_rt->pop();
- p_rt->pop();
- pos=brk_end+1;
-
- } else if (doc->class_list.has(tag)) {
-
-
- p_rt->push_color(EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"));
- p_rt->push_meta("#"+tag);
- p_rt->add_text(tag);
- p_rt->pop();
- p_rt->pop();
- pos=brk_end+1;
-
- } else if (tag=="b") {
-
- //use bold font
- p_rt->push_font(doc_code_font);
- pos=brk_end+1;
- tag_stack.push_front(tag);
- } else if (tag=="i") {
-
- //use italics font
- Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
- //no italics so emphasize with color
- text_color.r*=1.1;
- text_color.g*=1.1;
- text_color.b*=1.1;
- p_rt->push_color(text_color);
- //p_rt->push_font(get_font("italic","Fonts"));
- pos=brk_end+1;
- tag_stack.push_front(tag);
- } else if (tag=="code" || tag=="codeblock") {
-
- //use monospace font
- p_rt->push_font(doc_code_font);
- pos=brk_end+1;
- tag_stack.push_front(tag);
- } else if (tag=="center") {
-
- //use monospace font
- p_rt->push_align(RichTextLabel::ALIGN_CENTER);
- pos=brk_end+1;
- tag_stack.push_front(tag);
- } else if (tag=="br") {
-
- //use monospace font
- p_rt->add_newline();
- pos=brk_end+1;
- } else if (tag=="u") {
-
- //use underline
- p_rt->push_underline();
- pos=brk_end+1;
- tag_stack.push_front(tag);
- } else if (tag=="s") {
-
- //use strikethrough (not supported underline instead)
- p_rt->push_underline();
- pos=brk_end+1;
- tag_stack.push_front(tag);
-
- } else if (tag=="url") {
-
- //use strikethrough (not supported underline instead)
- int end=bbcode.find("[",brk_end);
- if (end==-1)
- end=bbcode.length();
- String url = bbcode.substr(brk_end+1,end-brk_end-1);
- p_rt->push_meta(url);
-
- pos=brk_end+1;
- tag_stack.push_front(tag);
- } else if (tag.begins_with("url=")) {
-
- String url = tag.substr(4,tag.length());
- p_rt->push_meta(url);
- pos=brk_end+1;
- tag_stack.push_front("url");
- } else if (tag=="img") {
-
- //use strikethrough (not supported underline instead)
- int end=bbcode.find("[",brk_end);
- if (end==-1)
- end=bbcode.length();
- String image = bbcode.substr(brk_end+1,end-brk_end-1);
-
- Ref<Texture> texture = ResourceLoader::load(base_path+"/"+image,"Texture");
- if (texture.is_valid())
- p_rt->add_image(texture);
-
- pos=end;
- tag_stack.push_front(tag);
- } else if (tag.begins_with("color=")) {
-
- String col = tag.substr(6,tag.length());
- Color color;
-
- if (col.begins_with("#"))
- color=Color::html(col);
- else if (col=="aqua")
- color=Color::html("#00FFFF");
- else if (col=="black")
- color=Color::html("#000000");
- else if (col=="blue")
- color=Color::html("#0000FF");
- else if (col=="fuchsia")
- color=Color::html("#FF00FF");
- else if (col=="gray" || col=="grey")
- color=Color::html("#808080");
- else if (col=="green")
- color=Color::html("#008000");
- else if (col=="lime")
- color=Color::html("#00FF00");
- else if (col=="maroon")
- color=Color::html("#800000");
- else if (col=="navy")
- color=Color::html("#000080");
- else if (col=="olive")
- color=Color::html("#808000");
- else if (col=="purple")
- color=Color::html("#800080");
- else if (col=="red")
- color=Color::html("#FF0000");
- else if (col=="silver")
- color=Color::html("#C0C0C0");
- else if (col=="teal")
- color=Color::html("#008008");
- else if (col=="white")
- color=Color::html("#FFFFFF");
- else if (col=="yellow")
- color=Color::html("#FFFF00");
- else
- color=Color(0,0,0,1); //base_color;
-
-
-
- p_rt->push_color(color);
- pos=brk_end+1;
- tag_stack.push_front("color");
-
- } else if (tag.begins_with("font=")) {
-
- String fnt = tag.substr(5,tag.length());
-
-
- Ref<Font> font = ResourceLoader::load(base_path+"/"+fnt,"Font");
- if (font.is_valid())
- p_rt->push_font(font);
- else {
- p_rt->push_font(doc_font);
- }
-
- pos=brk_end+1;
- tag_stack.push_front("font");
-
-
- } else {
-
- p_rt->add_text("["); //ignore
- pos=brk_pos+1;
-
- }
- }
-
- /*p_rt->pop();
- p_rt->pop();
- p_rt->pop();*/
-
-}
-
-
-void EditorHelp::_add_text(const String& p_bbcode) {
-
-
- _add_text_to_rt(p_bbcode,class_desc);
-
-}
-
-
-
-
-void EditorHelp::_update_doc() {
-
-
-
-}
-
-
-void EditorHelp::generate_doc() {
-
- doc = memnew( DocData );
- doc->generate(true);
- DocData compdoc;
- compdoc.load_compressed(_doc_data_compressed,_doc_data_compressed_size,_doc_data_uncompressed_size);
- doc->merge_from(compdoc); //ensure all is up to date
-
-
-}
-
-void EditorHelp::_notification(int p_what) {
-
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
-
- //forward->set_icon(get_icon("Forward","EditorIcons"));
- //back->set_icon(get_icon("Back","EditorIcons"));
- _update_doc();
-
- } break;
- }
-}
-
-void EditorHelp::go_to_help(const String& p_help) {
-
- _help_callback(p_help);
-}
-
-void EditorHelp::go_to_class(const String& p_class,int p_scroll) {
-
- _goto_desc(p_class,p_scroll);
-}
-
-void EditorHelp::popup_search() {
-
-
- search_dialog->popup_centered(Size2(250,80));
- search->grab_focus();
-}
-
-void EditorHelp::_search_cbk() {
-
- _search(search->get_text());
-}
-
-String EditorHelp::get_class() {
-
- return edited_class;
-}
-
-void EditorHelp::search_again() {
- _search(prev_search);
-}
-
-int EditorHelp::get_scroll() const {
-
- return class_desc->get_v_scroll()->get_value();
-}
-void EditorHelp::set_scroll(int p_scroll) {
-
-
- class_desc->get_v_scroll()->set_value(p_scroll);
-
-}
-
-void EditorHelp::_bind_methods() {
-
- ClassDB::bind_method("_class_list_select",&EditorHelp::_class_list_select);
- ClassDB::bind_method("_class_desc_select",&EditorHelp::_class_desc_select);
- ClassDB::bind_method("_class_desc_input",&EditorHelp::_class_desc_input);
- //ClassDB::bind_method("_button_pressed",&EditorHelp::_button_pressed);
- ClassDB::bind_method("_scroll_changed",&EditorHelp::_scroll_changed);
- ClassDB::bind_method("_request_help",&EditorHelp::_request_help);
- ClassDB::bind_method("_unhandled_key_input",&EditorHelp::_unhandled_key_input);
- ClassDB::bind_method("_search",&EditorHelp::_search);
- ClassDB::bind_method("_search_cbk",&EditorHelp::_search_cbk);
- ClassDB::bind_method("_help_callback",&EditorHelp::_help_callback);
-
- ADD_SIGNAL(MethodInfo("go_to_help"));
-
-}
-
-EditorHelp::EditorHelp() {
-
- editor=EditorNode::get_singleton();
-
- VBoxContainer *vbc = this;
-
- EDITOR_DEF("text_editor/help/sort_functions_alphabetically",true);
-
- //class_list->connect("meta_clicked",this,"_class_list_select");
- //class_list->set_selection_enabled(true);
-
- {
- Panel *pc = memnew( Panel );
- Ref<StyleBoxFlat> style( memnew( StyleBoxFlat ) );
- style->set_bg_color( EditorSettings::get_singleton()->get("text_editor/highlighting/background_color") );
- pc->set_v_size_flags(SIZE_EXPAND_FILL);
- pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
- vbc->add_child(pc);
- class_desc = memnew( RichTextLabel );
- pc->add_child(class_desc);
- class_desc->set_area_as_parent_rect(8);
- class_desc->connect("meta_clicked",this,"_class_desc_select");
- class_desc->connect("gui_input",this,"_class_desc_input");
- }
-
- class_desc->get_v_scroll()->connect("value_changed",this,"_scroll_changed");
- class_desc->set_selection_enabled(true);
-
- scroll_locked=false;
- select_locked=false;
- set_process_unhandled_key_input(true);
- class_desc->hide();
-
- search_dialog = memnew( ConfirmationDialog );
- add_child(search_dialog);
- VBoxContainer *search_vb = memnew( VBoxContainer );
- search_dialog->add_child(search_vb);
-
- search = memnew( LineEdit );
- search_dialog->register_text_enter(search);
- search_vb->add_margin_child(TTR("Search Text"),search);
- search_dialog->get_ok()->set_text(TTR("Find"));
- search_dialog->connect("confirmed",this,"_search_cbk");
- search_dialog->set_hide_on_ok(false);
- search_dialog->set_self_modulate(Color(1,1,1,0.8));
-
-
- /*class_search = memnew( EditorHelpSearch(editor) );
- editor->get_gui_base()->add_child(class_search);
- class_search->connect("go_to_help",this,"_help_callback");*/
-
- //prev_search_page=-1;
-}
-
-EditorHelp::~EditorHelp() {
-
-}
-
-/////////////
-
-
-
-void EditorHelpBit::_go_to_help(String p_what) {
-
- EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
- ScriptEditor::get_singleton()->goto_help(p_what);
- emit_signal("request_hide");
-}
-
-void EditorHelpBit::_meta_clicked(String p_select) {
-
- //print_line("LINK: "+p_select);
- if (p_select.begins_with("#")) {
- //_goto_desc(p_select.substr(1,p_select.length()));
- _go_to_help("class_name:"+p_select.substr(1,p_select.length()));
- return;
- } else if (p_select.begins_with("@")) {
-
- String m = p_select.substr(1,p_select.length());
-
- if (m.find(".")!=-1) {
- //must go somewhere else
-
- _go_to_help("class_method:"+m.get_slice(".",0)+":"+m.get_slice(".",0));
- } else {
- /*
- if (!method_line.has(m))
- return;
- class_desc->scroll_to_line(method_line[m]);
- */
- }
-
- }
-
-
-}
-
-void EditorHelpBit::_bind_methods() {
-
- ClassDB::bind_method("_meta_clicked",&EditorHelpBit::_meta_clicked);
- ADD_SIGNAL(MethodInfo("request_hide"));
-}
-
-void EditorHelpBit::_notification(int p_what){
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- add_style_override("panel",get_stylebox("normal","TextEdit"));
- }
-}
-
-
-void EditorHelpBit::set_text(const String& p_text) {
-
- rich_text->clear();
- _add_text_to_rt(p_text,rich_text);
-}
-
-EditorHelpBit::EditorHelpBit() {
-
- rich_text = memnew( RichTextLabel );
- add_child(rich_text);
- rich_text->set_area_as_parent_rect(8*EDSCALE);
- rich_text->connect("meta_clicked",this,"_meta_clicked");
- set_custom_minimum_size(Size2(0,70*EDSCALE));
-
-}
diff --git a/tools/editor/editor_help.h b/tools/editor/editor_help.h
deleted file mode 100644
index 3c4ba1f43e..0000000000
--- a/tools/editor/editor_help.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*************************************************************************/
-/* editor_help.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_HELP_H
-#define EDITOR_HELP_H
-
-#include "tools/editor/editor_plugin.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/text_edit.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/gui/panel_container.h"
-#include "scene/gui/tree.h"
-
-#include "scene/main/timer.h"
-#include "tools/editor/code_editor.h"
-#include "tools/editor/doc/doc_data.h"
-
-
-class EditorNode;
-
-class EditorHelpSearch : public ConfirmationDialog {
-
- GDCLASS(EditorHelpSearch,ConfirmationDialog )
-
- EditorNode *editor;
- LineEdit *search_box;
- Tree *search_options;
- String base_type;
-
- void _update_search();
-
- void _sbox_input(const InputEvent& p_ie);
-
- void _confirmed();
- void _text_changed(const String& p_newtext);
-
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void popup();
- void popup(const String& p_term);
-
- EditorHelpSearch();
-};
-
-class EditorHelpIndex : public ConfirmationDialog {
- GDCLASS( EditorHelpIndex, ConfirmationDialog );
-
- LineEdit *search_box;
- Tree *class_list;
- HashMap<String,TreeItem*> tree_item_map;
-
- void _tree_item_selected();
- void _text_changed(const String& p_text);
- void _sbox_input(const InputEvent& p_ie);
-
- void _update_class_list();
-
- void add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root);
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
- void select_class(const String& p_class);
-
- void popup();
-
- EditorHelpIndex();
-};
-
-
-class EditorHelp : public VBoxContainer {
- GDCLASS( EditorHelp, VBoxContainer );
-
-
- enum Page {
-
- PAGE_CLASS_LIST,
- PAGE_CLASS_DESC,
- PAGE_CLASS_PREV,
- PAGE_CLASS_NEXT,
- PAGE_SEARCH,
- CLASS_SEARCH,
-
- };
-
-
- bool select_locked;
-
- String prev_search;
-
- String edited_class;
-
- EditorNode *editor;
- Map<String,int> method_line;
- Map<String,int> signal_line;
- Map<String,int> property_line;
- Map<String,int> theme_property_line;
- Map<String,int> constant_line;
- int description_line;
-
-
- RichTextLabel *class_desc;
- HSplitContainer *h_split;
- static DocData *doc;
-
-
- ConfirmationDialog *search_dialog;
- LineEdit *search;
-
-
- String base_path;
-
-
- void _help_callback(const String& p_topic);
-
- void _add_text(const String& p_text);
- bool scroll_locked;
-
- //void _button_pressed(int p_idx);
- void _add_type(const String& p_type);
-
- void _scroll_changed(double p_scroll);
- void _class_list_select(const String& p_select);
- void _class_desc_select(const String& p_select);
- void _class_desc_input(const InputEvent& p_input);
-
- Error _goto_desc(const String& p_class, int p_vscr=-1);
- //void _update_history_buttons();
- void _update_doc();
-
- void _request_help(const String& p_string);
- void _search(const String& p_str);
- void _search_cbk();
-
- void _unhandled_key_input(const InputEvent& p_ev);
-
-
-
-protected:
-
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- static void generate_doc();
- static DocData *get_doc_data() { return doc; }
-
- void go_to_help(const String& p_help);
- void go_to_class(const String& p_class,int p_scroll=0);
-
- void popup_search();
- void search_again();
-
- String get_class();
-
- void set_focused() { class_desc->grab_focus(); }
-
- int get_scroll() const;
- void set_scroll(int p_scroll);
-
- EditorHelp();
- ~EditorHelp();
-};
-
-
-
-class EditorHelpBit : public Panel {
-
- GDCLASS( EditorHelpBit, Panel);
-
- RichTextLabel *rich_text;
- void _go_to_help(String p_what);
- void _meta_clicked(String p_what);
-
-
-protected:
-
- static void _bind_methods();
- void _notification(int p_what);
-public:
-
- void set_text(const String& p_text);
- EditorHelpBit();
-};
-
-#endif // EDITOR_HELP_H
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp
deleted file mode 100644
index 69a004fc08..0000000000
--- a/tools/editor/editor_import_export.cpp
+++ /dev/null
@@ -1,2306 +0,0 @@
-/*************************************************************************/
-/* editor_import_export.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_import_export.h"
-
-#if 0
-#include "version.h"
-#include "script_language.h"
-#include "globals.h"
-#include "os/file_access.h"
-#include "os/dir_access.h"
-#include "tools/editor/editor_file_system.h"
-#include "io/resource_loader.h"
-#include "editor_node.h"
-#include "editor_settings.h"
-#include "io/config_file.h"
-#include "io/resource_saver.h"
-#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) {
-
- String gp = GlobalConfig::get_singleton()->globalize_path(p_path);
- String rp = GlobalConfig::get_singleton()->get_resource_path();
- if (!rp.ends_with("/"))
- rp+="/";
-
- return rp.path_to_file(gp);
-}
-
-String EditorImportPlugin::expand_source_path(const String& p_path) {
-
- if (p_path.is_rel_path()) {
- return GlobalConfig::get_singleton()->get_resource_path().plus_file(p_path).simplify_path();
- } else {
- return p_path;
- }
-}
-
-
-String EditorImportPlugin::_validate_source_path(const String& p_path) {
-
- return validate_source_path(p_path);
-}
-
-String EditorImportPlugin::_expand_source_path(const String& p_path) {
-
- return expand_source_path(p_path);
-}
-
-void EditorImportPlugin::_bind_methods() {
-
-
- ClassDB::bind_method(_MD("validate_source_path","path"),&EditorImportPlugin::_validate_source_path);
- ClassDB::bind_method(_MD("expand_source_path","path"),&EditorImportPlugin::_expand_source_path);
-
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::STRING,"get_name"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::STRING,"get_visible_name"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("import_dialog",PropertyInfo(Variant::STRING,"from")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::INT,"import",PropertyInfo(Variant::STRING,"path"),PropertyInfo(Variant::OBJECT,"from",PROPERTY_HINT_RESOURCE_TYPE,"ResourceImportMetadata")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::POOL_BYTE_ARRAY,"custom_export",PropertyInfo(Variant::STRING,"path"),PropertyInfo(Variant::OBJECT,"platform",PROPERTY_HINT_RESOURCE_TYPE,"EditorExportPlatform")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("import_from_drop",PropertyInfo(Variant::POOL_STRING_ARRAY,"files"),PropertyInfo(Variant::STRING,"dest_path")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("reimport_multiple_files",PropertyInfo(Variant::POOL_STRING_ARRAY,"files")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"can_reimport_multiple_files"));
-
- //BIND_VMETHOD( mi );
-}
-
-String EditorImportPlugin::get_name() const {
-
- if (get_script_instance() && get_script_instance()->has_method("get_name")) {
- return get_script_instance()->call("get_name");
- }
-
- ERR_FAIL_V("");
-}
-
-String EditorImportPlugin::get_visible_name() const {
-
- if (get_script_instance() && get_script_instance()->has_method("get_visible_name")) {
- return get_script_instance()->call("get_visible_name");
- }
-
- ERR_FAIL_V("");
-}
-
-
-void EditorImportPlugin::import_dialog(const String& p_from) {
-
- if (get_script_instance() && get_script_instance()->has_method("import_dialog")) {
- get_script_instance()->call("import_dialog",p_from);
- return;
- }
-
- ERR_FAIL();
-
-}
-
-Error EditorImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
-
- if (get_script_instance() && get_script_instance()->has_method("import")) {
- return Error(get_script_instance()->call("import",p_path,p_from).operator int());
- }
-
- ERR_FAIL_V(ERR_UNAVAILABLE);
-}
-
-Vector<uint8_t> EditorImportPlugin::custom_export(const String& p_path, const Ref<EditorExportPlatform> &p_platform) {
-
- if (get_script_instance() && get_script_instance()->has_method("custom_export")) {
- get_script_instance()->call("custom_export",p_path,p_platform);
- }
-
- return Vector<uint8_t>();
-}
-
-bool EditorImportPlugin::can_reimport_multiple_files() const {
-
- if (get_script_instance() && get_script_instance()->has_method("can_reimport_multiple_files")) {
- return get_script_instance()->call("can_reimport_multiple_files");
- }
-
- return false;
-}
-void EditorImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
-
- if (get_script_instance() && get_script_instance()->has_method("reimport_multiple_files")) {
- get_script_instance()->call("reimport_multiple_files",p_list);
- }
-
-}
-
-void EditorImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
-
- if (get_script_instance() && get_script_instance()->has_method("import_from_drop")) {
- get_script_instance()->call("import_from_drop",p_drop,p_dest_path);
- }
-
-}
-
-EditorImportPlugin::EditorImportPlugin() {
-
-
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-void EditorExportPlugin::_bind_methods() {
-
- MethodInfo mi = MethodInfo("custom_export:Variant",PropertyInfo(Variant::STRING,"name"),PropertyInfo(Variant::OBJECT,"platform",PROPERTY_HINT_RESOURCE_TYPE,"EditorExportPlatform"));
- mi.return_val.type=Variant::POOL_BYTE_ARRAY;
-
- BIND_VMETHOD( mi );
-}
-
-
-Vector<uint8_t> EditorExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
-
- if (get_script_instance()) {
-
- Variant d = get_script_instance()->call("custom_export",p_path,p_platform);
- if (d.get_type()==Variant::NIL)
- return Vector<uint8_t>();
- if (d.get_type()==Variant::POOL_BYTE_ARRAY)
- return d;
-
- ERR_FAIL_COND_V(d.get_type()!=Variant::DICTIONARY,Vector<uint8_t>());
- Dictionary dict=d;
- ERR_FAIL_COND_V(!dict.has("name"),Vector<uint8_t>());
- ERR_FAIL_COND_V(!dict.has("data"),Vector<uint8_t>());
- p_path=dict["name"];
- return dict["data"];
- }
-
- return Vector<uint8_t>();
-
-}
-
-
-EditorExportPlugin::EditorExportPlugin() {
-
-
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-
-static void _add_to_list(EditorFileSystemDirectory *p_efsd,Set<StringName>& r_list) {
-
- for(int i=0;i<p_efsd->get_subdir_count();i++) {
-
- _add_to_list(p_efsd->get_subdir(i),r_list);
- }
-
- for(int i=0;i<p_efsd->get_file_count();i++) {
- r_list.insert(p_efsd->get_file_path(i));
- }
-}
-
-
-struct __EESortDepCmp {
-
- _FORCE_INLINE_ bool operator()(const StringName& p_l,const StringName& p_r) const {
- return p_l.operator String() < p_r.operator String();
- }
-};
-
-
-
-
-static void _edit_files_with_filter(DirAccess *da,const List<String>& p_filters,Set<StringName>& r_list,bool exclude) {
-
-
- List<String> files;
- List<String> dirs;
-
- da->list_dir_begin();
-
- String f = da->get_next();
- while(f!="") {
-
- print_line("HOHO: "+f);
- if (da->current_is_dir())
- dirs.push_back(f);
- else
- files.push_back(f);
-
- f=da->get_next();
- }
-
- String r = da->get_current_dir().replace("\\","/");
- if (!r.ends_with("/"))
- r+="/";
-
- print_line("AT: "+r);
-
- for(List<String>::Element *E=files.front();E;E=E->next()) {
- String fullpath=r+E->get();
- for(const List<String>::Element *F=p_filters.front();F;F=F->next()) {
-
- if (fullpath.matchn(F->get())) {
- String act = TTR("Added:")+" ";
-
- if (!exclude) {
- r_list.insert(fullpath);
- } else {
- act = TTR("Removed:")+" ";
- r_list.erase(fullpath);
- }
-
-
- print_line(act+fullpath);
- }
- }
- }
-
- da->list_dir_end();
-
- for(List<String>::Element *E=dirs.front();E;E=E->next()) {
- if (E->get().begins_with("."))
- continue;
- da->change_dir(E->get());
- _edit_files_with_filter(da,p_filters,r_list,exclude);
- da->change_dir("..");
- }
-
-}
-
-static void _edit_filter_list(Set<StringName>& r_list,const String& p_filter,bool exclude) {
-
- if (p_filter=="")
- return;
- Vector<String> split = p_filter.split(",");
- List<String> filters;
- for(int i=0;i<split.size();i++) {
- String f = split[i].strip_edges();
- if (f.empty())
- continue;
- filters.push_back(f);
- }
-
- DirAccess *da = DirAccess::open("res://");
- ERR_FAIL_NULL(da);
- _edit_files_with_filter(da,filters,r_list,exclude);
- memdelete(da);
-}
-
-static void _add_filter_to_list(Set<StringName>& r_list,const String& p_filter) {
- _edit_filter_list(r_list,p_filter,false);
-}
-
-static void _remove_filter_from_list(Set<StringName>& r_list,const String& p_filter) {
- _edit_filter_list(r_list,p_filter,true);
-}
-
-bool EditorExportPlatform::_set(const StringName& p_name, const Variant& p_value) {
-
- String n = p_name;
-
- if (n=="debug/debugging_enabled") {
- set_debugging_enabled(p_value);
- } else {
- return false;
- }
-
- return true;
-
-}
-
-bool EditorExportPlatform::_get(const StringName& p_name,Variant &r_ret) const {
-
- String n = p_name;
-
- if (n=="debug/debugging_enabled") {
- r_ret=is_debugging_enabled();
- } else {
- return false;
- }
-
- return true;
-
-}
-
-void EditorExportPlatform::_get_property_list( List<PropertyInfo> *p_list) const {
-
- p_list->push_front( PropertyInfo( Variant::BOOL, "debug/debugging_enabled"));
-}
-
-Vector<uint8_t> EditorExportPlatform::get_exported_file_default(String& p_fname) const {
-
- FileAccess *f = FileAccess::open(p_fname,FileAccess::READ);
- ERR_FAIL_COND_V(!f,Vector<uint8_t>());
- Vector<uint8_t> ret;
- ret.resize(f->get_len());
- int rbs = f->get_buffer(ret.ptr(),ret.size());
- memdelete(f);
- return ret;
-}
-
-Vector<uint8_t> EditorExportPlatform::get_exported_file(String& p_fname) const {
-
- Ref<EditorExportPlatform> ep=EditorImportExport::get_singleton()->get_export_platform(get_name());
-
- for(int i=0;i<EditorImportExport::get_singleton()->get_export_plugin_count();i++) {
-
- Vector<uint8_t> data = EditorImportExport::get_singleton()->get_export_plugin(i)->custom_export(p_fname,ep);
- if (data.size())
- return data;
-
- }
-
-
- return get_exported_file_default(p_fname);
-
-
-}
-
-Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const {
-
-
- Set<StringName> exported;
-
- if (FileAccess::exists("res://godot.cfg"))
- exported.insert("res://godot.cfg");
-
- if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED) {
-
- String filter;
- if (EditorImportExport::get_singleton()->get_export_filter()==EditorImportExport::EXPORT_ALL) {
- _add_filter_to_list(exported,"*");
- } else {
- _add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported);
- String cf = EditorImportExport::get_singleton()->get_export_custom_filter();
- if (cf!="")
- cf+=",";
- cf+="*.flags";
- _add_filter_to_list(exported,cf);
-
- cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude();
- _remove_filter_from_list(exported,cf);
- }
-
-
- } else {
-
-
- Map<String,Map<String,String> > remapped_paths;
-
- Set<String> scene_extensions;
- Set<String> resource_extensions;
-
- {
-
- List<String> l;
- /*
- SceneLoader::get_recognized_extensions(&l);
- for(List<String>::Element *E=l.front();E;E=E->next()) {
- scene_extensions.insert(E->get());
- }
- */
- ResourceLoader::get_recognized_extensions_for_type("",&l);
- for(List<String>::Element *E=l.front();E;E=E->next()) {
-
- resource_extensions.insert(E->get());
- }
- }
-
-
- List<StringName> toexport;
-
- EditorImportExport::get_singleton()->get_export_file_list(&toexport);
-
- print_line("TO EXPORT: "+itos(toexport.size()));
-
-
- for (List<StringName>::Element *E=toexport.front();E;E=E->next()) {
-
- print_line("DEP: "+String(E->get()));
- exported.insert(E->get());
- if (p_bundles && EditorImportExport::get_singleton()->get_export_file_action(E->get())==EditorImportExport::ACTION_BUNDLE) {
- print_line("NO BECAUSE OF BUNDLE!");
- continue; //no dependencies needed to be copied
- }
-
- List<String> testsubs;
- testsubs.push_back(E->get());
-
- while(testsubs.size()) {
- //recursive subdep search!
- List<String> deplist;
- ResourceLoader::get_dependencies(testsubs.front()->get(),&deplist);
- testsubs.pop_front();
-
- List<String> subdeps;
-
- for (List<String>::Element *F=deplist.front();F;F=F->next()) {
-
- StringName dep = F->get();
-
- if (exported.has(dep) || EditorImportExport::get_singleton()->get_export_file_action(dep)!=EditorImportExport::ACTION_NONE)
- continue; //dependency added or to be added
- print_line(" SUBDEP: "+String(dep));
-
- exported.insert(dep);
- testsubs.push_back(dep);
- }
- }
- }
- String cf = EditorImportExport::get_singleton()->get_export_custom_filter();
- if (cf!="")
- cf+=",";
- cf+="*.flags";
- _add_filter_to_list(exported,cf);
-
- cf = EditorImportExport::get_singleton()->get_export_custom_filter_exclude();
- _remove_filter_from_list(exported,cf);
-
-
- }
-
- Vector<StringName> ret;
- ret.resize(exported.size());
-
-
- int idx=0;
- for(Set<StringName>::Element *E=exported.front();E;E=E->next()) {
-
- ret[idx++]=E->get();
-
- }
-
- SortArray<StringName,__EESortDepCmp> sort; //some platforms work better if this is sorted
- sort.sort(ret.ptr(),ret.size());
-
- return ret;
-
-}
-
-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)!="";
-}
-
-///////////////////////////////////////
-
-
-
-bool EditorExportPlatform::is_debugging_enabled() const {
-
- return debugging_enabled;
-}
-
-void EditorExportPlatform::set_debugging_enabled(bool p_enabled) {
-
- debugging_enabled = p_enabled;
-}
-
-bool EditorExportPlatformPC::_set(const StringName& p_name, const Variant& p_value) {
-
- String n = p_name;
-
- if (n=="custom_binary/release") {
-
- custom_release_binary=p_value;
- } else if (n=="custom_binary/debug") {
-
- custom_debug_binary=p_value;
- } 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;
- } else
- return false;
-
- return true;
-
-}
-
-bool EditorExportPlatformPC::_get(const StringName& p_name,Variant &r_ret) const {
-
- String n = p_name;
-
- if (n=="custom_binary/release") {
-
- r_ret=custom_release_binary;
- } else if (n=="custom_binary/debug") {
-
- r_ret=custom_debug_binary;
- } 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;
- } else
- return false;
-
- return true;
-
-}
-
-void EditorExportPlatformPC::_get_property_list( List<PropertyInfo> *p_list) const {
-
- 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,"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"));
-}
-
-
-
-static void _exp_add_dep(Map<StringName,List<StringName> > &deps,const StringName& p_path) {
-
-
- if (deps.has(p_path))
- return; //already done
-
- deps.insert(p_path,List<StringName>());
-
- List<StringName> &deplist=deps[p_path];
- Set<StringName> depset;
-
- List<String> dl;
- ResourceLoader::get_dependencies(p_path,&dl);
-
- //added in order so child dependencies are always added bfore parent dependencies
- for (List<String>::Element *E=dl.front();E;E=E->next()) {
-
-
- if (!deps.has(E->get()))
- _exp_add_dep(deps,E->get());
-
- for(List<StringName>::Element *F=deps[E->get()].front();F;F=F->next()) {
-
-
- if (!depset.has(F->get())) {
- depset.insert(F->get());
- deplist.push_back(F->get());
- }
- }
-
- if (!depset.has(E->get())) {
- depset.insert(E->get());
- deplist.push_back(E->get());
- }
-
- }
-}
-
-
-
-Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles) {
-
-/* ALL FILES AND DEPENDENCIES */
-
- Vector<StringName> files=get_dependencies(p_make_bundles);
-
- Map<StringName,List<StringName> > deps;
-
- if (false) {
- for(int i=0;i<files.size();i++) {
-
- _exp_add_dep(deps,files[i]);
-
- }
- }
-
-
-
-/* GROUP ATLAS */
-
-
- List<StringName> groups;
-
- EditorImportExport::get_singleton()->image_export_get_groups(&groups);
-
- Map<StringName,StringName> remap_files;
- Set<StringName> saved;
-
- int counter=0;
-
- for(List<StringName>::Element *E=groups.front();E;E=E->next()) {
-
- if (!EditorImportExport::get_singleton()->image_export_group_get_make_atlas(E->get()))
- continue; //uninterested, only process for atlas!
-
- List<StringName> atlas_images;
- EditorImportExport::get_singleton()->image_export_get_images_in_group(E->get(),&atlas_images);
- atlas_images.sort_custom<StringName::AlphCompare>();
-
- for (List<StringName>::Element *F=atlas_images.front();F;) {
-
- List<StringName>::Element *N=F->next();
-
- if (!FileAccess::exists(F->get())) {
- atlas_images.erase(F);
- }
-
- F=N;
-
- }
-
- if (atlas_images.size()<=1)
- continue;
-
- int group_format=0;
- float group_lossy_quality=EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(E->get());
- int group_shrink=EditorImportExport::get_singleton()->image_export_group_get_shrink(E->get());
- group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink();
-
- switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(E->get())) {
- case EditorImportExport::IMAGE_ACTION_KEEP:
- case EditorImportExport::IMAGE_ACTION_NONE: {
-
- switch(EditorImportExport::get_singleton()->get_export_image_action()) {
- case EditorImportExport::IMAGE_ACTION_NONE: {
-
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS; //?
-
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
- } break; //use default
- }
-
- group_lossy_quality=EditorImportExport::get_singleton()->get_export_image_quality();
-
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
- } break; //use default
- }
-
- String image_list_md5;
-
- {
- MD5_CTX ctx;
- MD5Init(&ctx);
- for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
-
- String p = F->get();
- MD5Update(&ctx,(unsigned char*)p.utf8().get_data(),p.utf8().length());
-
- }
-
- MD5Final(&ctx);
- image_list_md5=String::md5(ctx.digest);
- }
- //ok see if cached
- String md5;
- bool atlas_valid=true;
- String atlas_name;
-
- {
- MD5_CTX ctx;
- MD5Init(&ctx);
- String path = GlobalConfig::get_singleton()->get_resource_path()+"::"+String(E->get())+"::"+get_name();
- MD5Update(&ctx,(unsigned char*)path.utf8().get_data(),path.utf8().length());
- MD5Final(&ctx);
- md5 = String::md5(ctx.digest);
- }
-
- FileAccess *f=NULL;
-
- if (!FileAccess::exists(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5)) {
- print_line("NO MD5 INVALID");
- atlas_valid=false;
- }
-
- if (atlas_valid)
- f=FileAccess::open(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5,FileAccess::READ);
-
- if (atlas_valid) {
- //compare options
- /*Dictionary options;
- options.parse_json(f->get_line());
- if (!options.has("lossy_quality") || float(options["lossy_quality"])!=group_lossy_quality)
- atlas_valid=false;
- else if (!options.has("shrink") || int(options["shrink"])!=group_shrink)
- atlas_valid=false;
- else if (!options.has("image_format") || int(options["image_format"])!=group_format)
- atlas_valid=false;
-
- if (!atlas_valid)
- print_line("JSON INVALID");
-*/
- }
-
-
- if (atlas_valid) {
- //check md5 of list of image /names/
- if (f->get_line().strip_edges()!=image_list_md5) {
- atlas_valid=false;
- print_line("IMAGE MD5 INVALID!");
- }
-
- }
-
- Vector<Rect2> rects;
- bool resave_deps=false;
-
- if (atlas_valid) {
-
- //check if images were not modified
- for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
-
- Vector<String> slices = f->get_line().strip_edges().split("::");
-
- if (slices.size()!=10) {
- atlas_valid=false;
- print_line("CANT SLICE IN 10");
- break;
- }
- uint64_t mod_time = slices[0].to_int64();
- uint64_t file_mod_time = FileAccess::get_modified_time(F->get());
- if (mod_time!=file_mod_time) {
-
- String image_md5 = slices[1];
- String file_md5 = FileAccess::get_md5(F->get());
-
- if (image_md5!=file_md5) {
- atlas_valid=false;
- print_line("IMAGE INVALID "+slices[0]);
- break;
- } else {
- resave_deps=true;
- }
- }
-
- if (atlas_valid) {
- //push back region and margin
- rects.push_back(Rect2(slices[2].to_float(),slices[3].to_float(),slices[4].to_float(),slices[5].to_float()));
- rects.push_back(Rect2(slices[6].to_float(),slices[7].to_float(),slices[8].to_float(),slices[9].to_float()));
- }
- }
-
- }
-
- if (f) {
- memdelete(f);
- f=NULL;
- }
-
- print_line("ATLAS VALID? "+itos(atlas_valid)+" RESAVE DEPS? "+itos(resave_deps));
- if (!atlas_valid) {
- rects.clear();
- //oh well, atlas is not valid. need to make new one....
-
- String dst_file = EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5+".tex";
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
- //imd->set_editor();
-
-
- for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
-
- imd->add_source(EditorImportPlugin::validate_source_path(F->get()),FileAccess::get_md5(F->get()));
-
- }
-
-
- imd->set_option("format",group_format);
-
-
- int flags=0;
-
- if (GlobalConfig::get_singleton()->get("image_loader/filter"))
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_FILTER;
- if (!GlobalConfig::get_singleton()->get("image_loader/gen_mipmaps"))
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS;
- if (!GlobalConfig::get_singleton()->get("image_loader/repeat"))
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_REPEAT;
-
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA;
-
- imd->set_option("flags",flags);
- imd->set_option("quality",group_lossy_quality);
- imd->set_option("atlas",true);
- imd->set_option("crop",true);
- imd->set_option("shrink",group_shrink);
-
-
-
- Ref<EditorTextureImportPlugin> plugin = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture");
- Error err = plugin->import2(dst_file,imd,get_image_compression(),true);
- if (err) {
-
- EditorNode::add_io_error(TTR("Error saving atlas:")+" "+dst_file.get_file());
- return ERR_CANT_CREATE;
- }
-
- ERR_FAIL_COND_V(imd->get_option("rects")==Variant(),ERR_BUG);
-
- Array r_rects=imd->get_option("rects");
- rects.resize(r_rects.size());
- for(int i=0;i<r_rects.size();i++) {
- //get back region and margins
- rects[i]=r_rects[i];
- }
-
-
- resave_deps=true;
- }
-
-
- //atlas is valid (or it was just saved i guess), create the atex files and save them
-
- if (resave_deps) {
- f=FileAccess::open(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5,FileAccess::WRITE);
- Dictionary options;
- options["lossy_quality"]=group_lossy_quality;
- options["shrink"]=EditorImportExport::get_singleton()->image_export_group_get_shrink(E->get());
- options["image_format"]=group_format;
- //f->store_line(options.to_json());
- f->store_line(image_list_md5);
- }
-
- //go through all ATEX files
-
- {
- Ref<ImageTexture> atlas = memnew( ImageTexture ); //fake atlas!
- String atlas_path="res://atlas-"+md5+".tex";
- atlas->set_path(atlas_path);
- int idx=0;
- for (List<StringName>::Element *F=atlas_images.front();F;F=F->next()) {
-
- String p = F->get();
- Ref<AtlasTexture> atex = memnew(AtlasTexture);
- atex->set_atlas(atlas);
- Rect2 region=rects[idx++];
- Rect2 margin=rects[idx++];
- atex->set_region(region);
- atex->set_margin(margin);
-
- String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpatlas.atex";
- Error err = ResourceSaver::save(path,atex);
- if (err!=OK) {
- EditorNode::add_io_error(TTR("Could not save atlas subtexture:")+" "+path);
- return ERR_CANT_CREATE;
- }
- Vector<uint8_t> data = FileAccess::get_file_as_array(path);
- String dst_path = F->get().operator String().get_basename()+".atex";
- err = p_func(p_udata,dst_path,data,counter++,files.size());
- saved.insert(dst_path);
- if (err)
- return err;
-
- if (f) {
- //recreating deps..
- String depline;
- //depline=String(F->get())+"::"+itos(FileAccess::get_modified_time(F->get()))+"::"+FileAccess::get_md5(F->get()); name unneccesary by top md5
- depline=itos(FileAccess::get_modified_time(F->get()))+"::"+FileAccess::get_md5(F->get());
- depline+="::"+itos(region.pos.x)+"::"+itos(region.pos.y)+"::"+itos(region.size.x)+"::"+itos(region.size.y);
- depline+="::"+itos(margin.pos.x)+"::"+itos(margin.pos.y)+"::"+itos(margin.size.x)+"::"+itos(margin.size.y);
- f->store_line(depline);
- }
-
- remap_files[F->get()]=dst_path;
- }
-
- Vector<uint8_t> atlas_data = FileAccess::get_file_as_array(EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-"+md5+".tex");
- Error err = p_func(p_udata,atlas_path,atlas_data,counter,files.size());
- saved.insert(atlas_path);
- if (err)
- return err;
-
- }
-
-
- if (f) {
- memdelete(f);
- }
-
- }
-
-
- StringName engine_cfg="res://godot.cfg";
- StringName boot_splash;
- {
- String splash=GlobalConfig::get_singleton()->get("application/boot_splash"); //avoid splash from being converted
- splash=splash.strip_edges();
- if (splash!=String()) {
- if (!splash.begins_with("res://"))
- splash="res://"+splash;
- splash=splash.simplify_path();
- boot_splash=splash;
- }
- }
- StringName custom_cursor;
- {
- String splash=GlobalConfig::get_singleton()->get("display/custom_mouse_cursor"); //avoid splash from being converted
- splash=splash.strip_edges();
- if (splash!=String()) {
- if (!splash.begins_with("res://"))
- splash="res://"+splash;
- splash=splash.simplify_path();
- custom_cursor=splash;
- }
- }
-
-
-
-
- for(int i=0;i<files.size();i++) {
-
- if (remap_files.has(files[i]) || files[i]==engine_cfg) //gonna be remapped (happened before!)
- continue; //from atlas?
- String src=files[i];
- Vector<uint8_t> buf;
-
- if (src==boot_splash || src==custom_cursor)
- buf = get_exported_file_default(src); //bootsplash must be kept if used
- else
- buf = get_exported_file(src);
-
- ERR_CONTINUE( saved.has(src) );
-
- Error err = p_func(p_udata,src,buf,counter++,files.size());
- if (err)
- return err;
-
- saved.insert(src);
- if (src!=String(files[i]))
- remap_files[files[i]]=src;
-
- }
-
-
- {
-
- //make binary godot.cfg config
- Map<String,Variant> custom;
-
-
- if (remap_files.size()) {
- Vector<String> remapsprop;
- for(Map<StringName,StringName>::Element *E=remap_files.front();E;E=E->next()) {
- print_line("REMAP: "+String(E->key())+" -> "+E->get());
- remapsprop.push_back(E->key());
- remapsprop.push_back(E->get());
- }
-
- custom["remap/all"]=remapsprop;
- }
-
- //add presaved dependencies
- for(Map<StringName,List<StringName> >::Element *E=deps.front();E;E=E->next()) {
-
- if (E->get().size()==0)
- continue; //no deps
- String key;
- Vector<StringName> deps;
- //if bundle continue (when bundles supported obviously)
-
- if (remap_files.has(E->key())) {
- key=remap_files[E->key()];
- } else {
- key=E->key();
- }
-
- deps.resize(E->get().size());
- int i=0;
-
- for(List<StringName>::Element *F=E->get().front();F;F=F->next()) {
- deps[i++]=F->get();
- print_line(" -"+String(F->get()));
- }
-
- NodePath prop(deps,true,String()); //seems best to use this for performance
-
- custom["deps/"+key.md5_text()]=prop;
-
- }
-
- String remap_file="godot.cfb";
- String engine_cfb =EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp"+remap_file;
- GlobalConfig::get_singleton()->save_custom(engine_cfb,custom);
- Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb);
-
- Error err = p_func(p_udata,"res://"+remap_file,data,counter,files.size());
- if (err)
- return err;
-
- }
-
- return OK;
-}
-
-static int _get_pad(int p_alignment, int p_n) {
-
- int rest = p_n % p_alignment;
- int pad = 0;
- if (rest > 0) {
- pad = p_alignment - rest;
- };
-
- return pad;
-};
-
-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("filesystem/file_server/port");
- String passwd = EditorSettings::get_singleton()->get("filesystem/file_server/password");
- r_flags.push_back("-rfs");
- r_flags.push_back(host+":"+itos(port));
- if (passwd!="") {
- r_flags.push_back("-rfs_pass");
- r_flags.push_back(passwd);
- }
- }
-
- if (p_flags&EXPORT_REMOTE_DEBUG) {
-
- r_flags.push_back("-rdebug");
-
- r_flags.push_back(host+":"+String::num(GLOBAL_DEF("network/debug/remote_port", 6007)));
-
- List<String> breakpoints;
- ScriptEditor::get_singleton()->get_breakpoints(&breakpoints);
-
-
- if (breakpoints.size()) {
-
- r_flags.push_back("-bp");
- String bpoints;
- for(const List<String>::Element *E=breakpoints.front();E;E=E->next()) {
-
- bpoints+=E->get().replace(" ","%20");
- if (E->next())
- bpoints+=",";
- }
-
- r_flags.push_back(bpoints);
- }
-
- }
-
- if (p_flags&EXPORT_VIEW_COLLISONS) {
-
- r_flags.push_back("-debugcol");
- }
-
- if (p_flags&EXPORT_VIEW_NAVIGATION) {
-
- r_flags.push_back("-debugnav");
- }
-
-
-}
-
-Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
-
-
- PackData *pd = (PackData*)p_userdata;
-
- CharString cs=p_path.utf8();
- pd->f->store_32(cs.length());
- pd->f->store_buffer((uint8_t*)cs.get_data(),cs.length());
- TempData td;
- td.pos=pd->f->get_pos();
- td.ofs=pd->ftmp->get_pos();
- td.size=p_data.size();
- pd->file_ofs.push_back(td);
- pd->f->store_64(0); //ofs
- pd->f->store_64(0); //size
- {
- MD5_CTX ctx;
- MD5Init(&ctx);
- MD5Update(&ctx,(unsigned char*)p_data.ptr(),p_data.size());
- MD5Final(&ctx);
- pd->f->store_buffer(ctx.digest,16);
- }
- pd->ep->step(TTR("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) {
-
- int pad = _get_pad(pd->alignment, pd->ftmp->get_pos());
- for (int i=0; i<pad; i++) {
-
- pd->ftmp->store_8(0);
- };
- };
- return OK;
-
-}
-
-Error EditorExportPlatform::save_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(TTR("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",TTR("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",TTR("Packing"),102);
-
- String tmppath = EditorSettings::get_singleton()->get_settings_path()+"/tmp/packtmp";
- FileAccess *tmp = FileAccess::open(tmppath,FileAccess::WRITE);
- uint64_t ofs_begin = dst->get_pos();
-
- dst->store_32(0x43504447); //GDPK
- dst->store_32(0); //pack version
- dst->store_32(VERSION_MAJOR);
- dst->store_32(VERSION_MINOR);
- dst->store_32(0); //hmph
- for(int i=0;i<16;i++) {
- //reserved
- dst->store_32(0);
- }
-
- size_t fcountpos = dst->get_pos();
- dst->store_32(0);
-
- PackData pd;
- pd.ep=&ep;
- pd.f=dst;
- pd.ftmp=tmp;
- pd.count=0;
- pd.alignment = p_alignment;
- Error err = export_project_files(save_pack_file,&pd,p_make_bundles);
- memdelete(tmp);
- if (err)
- return err;
-
- if (p_alignment > 1) {
- int pad = _get_pad(p_alignment, dst->get_pos());
- for (int i=0; i<pad; i++) {
-
- dst->store_8(0);
- };
- };
-
- size_t ofsplus = dst->get_pos();
- //append file
-
- tmp = FileAccess::open(tmppath,FileAccess::READ);
-
- ERR_FAIL_COND_V(!tmp,ERR_CANT_OPEN;)
- const int bufsize=16384;
- uint8_t buf[bufsize];
-
- while(true) {
-
- int got = tmp->get_buffer(buf,bufsize);
- if (got<=0)
- break;
- dst->store_buffer(buf,got);
- }
-
- memdelete(tmp);
-
- dst->store_64(dst->get_pos()-ofs_begin);
- dst->store_32(0x43504447); //GDPK
-
- //fix offsets
-
- dst->seek(fcountpos);
- dst->store_32(pd.count);
- for(int i=0;i<pd.file_ofs.size();i++) {
-
- dst->seek(pd.file_ofs[i].pos);
- dst->store_64(pd.file_ofs[i].ofs+ofsplus);
- dst->store_64(pd.file_ofs[i].size);
- }
-
- return OK;
-}
-
-EditorExportPlatform::EditorExportPlatform() {
-
- debugging_enabled = true;
-}
-
-Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug, int p_flags) {
-
-
-
- EditorProgress ep("export",vformat(TTR("Exporting for %s"),get_name()),102);
-
- const int BUFSIZE = 32768;
-
-
-
- ep.step(TTR("Setting Up.."),0);
-
- String exe_path="";
-
- 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);
- if (!src_exe) {
-
- EditorNode::add_io_error("Couldn't read source executable at:\n "+exe_path);
- return ERR_FILE_CANT_READ;
- }
-
- FileAccess *dst=FileAccess::open(p_path,FileAccess::WRITE);
- if (!dst) {
-
- EditorNode::add_io_error("Can't copy executable file to:\n "+p_path);
- return ERR_FILE_CANT_WRITE;
- }
-
- uint8_t buff[32768];
-
- while(true) {
-
- int c = src_exe->get_buffer(buff,BUFSIZE);
- if (c>0) {
-
- dst->store_buffer(buff,c);
- } else {
- break;
- }
- }
-
- String dstfile = p_path.replace_first("res://","").replace("\\","/");
- if (export_mode!=EXPORT_EXE) {
-
- String dstfile_extension=export_mode==EXPORT_ZIP?".zip":".pck";
- if (dstfile.find("/")!=-1)
- dstfile=dstfile.get_base_dir()+"/data"+dstfile_extension;
- else
- dstfile="data"+dstfile_extension;
- if (export_mode==EXPORT_PACK) {
-
- memdelete(dst);
-
- 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 = export_mode==EXPORT_ZIP?save_zip(dstfile,bundle):save_pack(dst,bundle);
- memdelete(dst);
- return err;
-}
-
-void EditorExportPlatformPC::set_binary_extension(const String& p_extension) {
-
- binary_extension=p_extension;
-}
-
-bool EditorExportPlatformPC::can_export(String *r_error) const {
-
- String err;
- bool valid=true;
-
- 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 && (!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";
- }
-
- if(custom_debug_binary=="" && custom_release_binary=="") {
- if (r_error) *r_error=err;
- return valid;
- }
-
- bool dvalid = true;
- bool rvalid = true;
-
- if(!FileAccess::exists(custom_debug_binary)) {
- dvalid = false;
- err = "Custom debug binary not found.\n";
- }
-
- if(!FileAccess::exists(custom_release_binary)) {
- rvalid = false;
- err = "Custom release binary not found.\n";
- }
-
- if (dvalid || rvalid)
- valid = true;
- else
- valid = false;
-
- if (r_error)
- *r_error=err;
- return valid;
-}
-
-
-EditorExportPlatformPC::EditorExportPlatformPC() {
-
- export_mode=EXPORT_PACK;
- use64=true;
-}
-
-
-
-
-
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-EditorImportExport* EditorImportExport::singleton=NULL;
-
-void EditorImportExport::add_import_plugin(const Ref<EditorImportPlugin>& p_plugin) {
-
- // Need to make sure the name is unique if we are going to lookup by it
- ERR_FAIL_COND(by_idx.has(p_plugin->get_name()));
-
- by_idx[ p_plugin->get_name() ]=plugins.size();
- plugins.push_back(p_plugin);
-}
-
-void EditorImportExport::remove_import_plugin(const Ref<EditorImportPlugin>& p_plugin) {
-
- String plugin_name = p_plugin->get_name();
-
- // Keep the indices the same
- // Find the index of the target plugin
- ERR_FAIL_COND(!by_idx.has(plugin_name));
- int idx = by_idx[plugin_name];
- int last_idx = plugins.size() - 1;
-
- // Swap the last plugin and the target one
- SWAP(plugins[idx], plugins[last_idx]);
-
- // Update the index of the old last one
- by_idx[plugins[idx]->get_name()] = idx;
-
- // Remove the target plugin's by_idx entry
- by_idx.erase(plugin_name);
-
- // Erase the plugin
- plugins.remove(last_idx);
-}
-
-int EditorImportExport::get_import_plugin_count() const{
-
- return plugins.size();
-}
-Ref<EditorImportPlugin> EditorImportExport::get_import_plugin(int p_idx) const{
-
- ERR_FAIL_INDEX_V(p_idx,plugins.size(),Ref<EditorImportPlugin>());
- return plugins[p_idx];
-
-}
-
-
-
-Ref<EditorImportPlugin> EditorImportExport::get_import_plugin_by_name(const String& p_string) const{
-
- ERR_FAIL_COND_V( !by_idx.has(p_string), Ref<EditorImportPlugin>());
- return plugins[ by_idx[p_string] ];
-}
-
-void EditorImportExport::add_export_plugin(const Ref<EditorExportPlugin>& p_plugin) {
-
- ERR_FAIL_COND( p_plugin.is_null() );
-
- export_plugins.push_back(p_plugin);
-}
-
-void EditorImportExport::remove_export_plugin(const Ref<EditorExportPlugin>& p_plugin) {
-
- ERR_FAIL_COND( p_plugin.is_null() );
- export_plugins.erase(p_plugin);
-}
-
-int EditorImportExport::get_export_plugin_count() const{
-
- return export_plugins.size();
-}
-Ref<EditorExportPlugin> EditorImportExport::get_export_plugin(int p_idx) const{
-
- ERR_FAIL_INDEX_V(p_idx,export_plugins.size(),Ref<EditorExportPlugin>());
- return export_plugins[p_idx];
-}
-
-void EditorImportExport::set_export_file_action(const StringName& p_file, FileAction p_action) {
-
- if (p_action==ACTION_NONE) {
-
- files.erase(p_file);
- } else {
-
- files[p_file]=p_action;
- }
-
-}
-
-EditorImportExport::FileAction EditorImportExport::get_export_file_action(const StringName& p_file) const{
-
-
- if (files.has(p_file))
- return files[p_file];
-
-
- return ACTION_NONE;
-}
-
-void EditorImportExport::get_export_file_list(List<StringName> *p_files){
-
-
- for (Map<StringName,FileAction>::Element *E=files.front();E;E=E->next()) {
-
- p_files->push_back(E->key());
- }
-
-}
-
-void EditorImportExport::add_export_platform(const Ref<EditorExportPlatform>& p_export) {
-
- exporters[p_export->get_name()]=p_export;
-}
-
-
-void EditorImportExport::get_export_platforms(List<StringName> *r_platforms) {
-
- for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
-
- r_platforms->push_back(E->key());
- }
-}
-
-Ref<EditorExportPlatform> EditorImportExport::get_export_platform(const StringName& p_platform) {
-
- if (exporters.has(p_platform)) {
- return exporters[p_platform];
- } else {
- return Ref<EditorExportPlatform>();
- }
-}
-
-
-bool EditorImportExport::poll_export_platforms() {
-
- bool changed=false;
- for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
-
- if (E->get()->poll_devices())
- changed=true;
- }
-
- return changed;
-
-}
-
-void EditorImportExport::set_export_filter(ExportFilter p_enable) {
-
- export_filter=p_enable;
-}
-
-EditorImportExport::ExportFilter EditorImportExport::get_export_filter() const{
-
- return export_filter;
-}
-
-void EditorImportExport::set_export_custom_filter(const String& p_custom_filter){
- export_custom_filter=p_custom_filter;
-}
-void EditorImportExport::set_export_custom_filter_exclude(const String& p_custom_filter){
- export_custom_filter_exclude=p_custom_filter;
-}
-String EditorImportExport::get_export_custom_filter() const{
- return export_custom_filter;
-}
-String EditorImportExport::get_export_custom_filter_exclude() const{
- return export_custom_filter_exclude;
-}
-
-void EditorImportExport::set_export_image_action(ImageAction p_action) {
-
- image_action=p_action;
-}
-
-EditorImportExport::ImageAction EditorImportExport::get_export_image_action() const{
-
- return image_action;
-}
-
-void EditorImportExport::set_export_image_shrink(float p_shrink) {
-
- image_shrink=p_shrink;
-}
-
-float EditorImportExport::get_export_image_shrink() const{
-
- return image_shrink;
-}
-
-
-void EditorImportExport::set_export_image_quality(float p_quality){
-
- image_action_compress_quality=p_quality;
-}
-
-float EditorImportExport::get_export_image_quality() const{
-
- return image_action_compress_quality;
-}
-
-void EditorImportExport::image_export_group_create(const StringName& p_name) {
-
- ERR_FAIL_COND(image_groups.has(p_name));
- ImageGroup ig;
- ig.action=IMAGE_ACTION_NONE; //default
- ig.make_atlas=false;
- ig.shrink=1;
- ig.lossy_quality=0.7;
- image_groups[p_name]=ig;
-
-
-}
-
-
-bool EditorImportExport::image_export_has_group(const StringName& p_name) const {
-
- return image_groups.has(p_name);
-}
-void EditorImportExport::image_export_get_groups(List<StringName> *r_name) const {
-
- for (Map<StringName,ImageGroup>::Element *E=image_groups.front();E;E=E->next()) {
-
- r_name->push_back(E->key());
- }
-}
-
-void EditorImportExport::image_export_group_remove(const StringName& p_name){
-
- ERR_FAIL_COND(!image_groups.has(p_name));
- image_groups.erase(p_name);
-}
-void EditorImportExport::image_export_group_set_image_action(const StringName& p_export_group,ImageAction p_action){
-
- ERR_FAIL_COND(!image_groups.has(p_export_group));
- image_groups[p_export_group].action=p_action;
-
-}
-EditorImportExport::ImageAction EditorImportExport::image_export_group_get_image_action(const StringName& p_export_group) const{
-
- ERR_FAIL_COND_V(!image_groups.has(p_export_group),IMAGE_ACTION_NONE);
- return image_groups[p_export_group].action;
-
-}
-void EditorImportExport::image_export_group_set_make_atlas(const StringName& p_export_group,bool p_make){
-
- ERR_FAIL_COND(!image_groups.has(p_export_group));
- image_groups[p_export_group].make_atlas=p_make;
-
-}
-bool EditorImportExport::image_export_group_get_make_atlas(const StringName& p_export_group) const{
-
- ERR_FAIL_COND_V(!image_groups.has(p_export_group),false);
- return image_groups[p_export_group].make_atlas;
-
-}
-void EditorImportExport::image_export_group_set_shrink(const StringName& p_export_group,float p_amount){
- ERR_FAIL_COND(!image_groups.has(p_export_group));
- image_groups[p_export_group].shrink=p_amount;
-
-}
-float EditorImportExport::image_export_group_get_shrink(const StringName& p_export_group) const{
-
- ERR_FAIL_COND_V(!image_groups.has(p_export_group),1);
- return image_groups[p_export_group].shrink;
-
-}
-
-void EditorImportExport::image_export_group_set_lossy_quality(const StringName& p_export_group,float p_amount){
- ERR_FAIL_COND(!image_groups.has(p_export_group));
- image_groups[p_export_group].lossy_quality=p_amount;
-
-}
-float EditorImportExport::image_export_group_get_lossy_quality(const StringName& p_export_group) const{
-
- ERR_FAIL_COND_V(!image_groups.has(p_export_group),1);
- return image_groups[p_export_group].lossy_quality;
-
-}
-
-StringName EditorImportExport::image_get_export_group(const StringName& p_image) const {
-
- if (image_group_files.has(p_image))
- return image_group_files[p_image];
- else
- return StringName();
-
-}
-
-void EditorImportExport::image_add_to_export_group(const StringName& p_image,const StringName& p_export_group) {
-
-
- bool emptygroup = String(p_export_group)==String();
- ERR_FAIL_COND(!emptygroup && !image_groups.has(p_export_group));
-
- if (emptygroup)
- image_group_files.erase(p_image);
- else
- image_group_files[p_image]=p_export_group;
-}
-
-void EditorImportExport::image_export_get_images_in_group(const StringName& p_group,List<StringName> *r_images) const {
-
- for (Map<StringName,StringName>::Element *E=image_group_files.front();E;E=E->next()) {
-
- if (p_group==E->get())
- r_images->push_back(E->key());
- }
-}
-
-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 );
-
- Error err = cf->load("res://export.cfg");
- if (err!=OK)
- return; //no export config to be loaded!
-
-
- export_custom_filter=cf->get_value("export_filter","filter");
- export_custom_filter_exclude=cf->get_value("export_filter","filter_exclude");
- String t=cf->get_value("export_filter","type");
- if (t=="selected")
- export_filter=EXPORT_SELECTED;
- else if (t=="resources")
- export_filter=EXPORT_RESOURCES;
- else if (t=="all")
- export_filter=EXPORT_ALL;
-
- if (cf->has_section("convert_images")) {
-
- String ci = "convert_images";
- String action = cf->get_value(ci,"action");
- if (action=="none")
- image_action=IMAGE_ACTION_NONE;
- else if (action=="compress_ram")
- image_action=IMAGE_ACTION_COMPRESS_RAM;
- else if (action=="compress_disk")
- image_action=IMAGE_ACTION_COMPRESS_DISK;
-
- image_action_compress_quality = cf->get_value(ci,"compress_quality");
- if (cf->has_section_key(ci,"shrink"))
- image_shrink = cf->get_value(ci,"shrink");
- else
- image_shrink=1;
- String formats=cf->get_value(ci,"formats");
- Vector<String> f = formats.split(",");
- image_formats.clear();
- for(int i=0;i<f.size();i++) {
- image_formats.insert(f[i].strip_edges());
- }
- }
-
- if (cf->has_section("convert_scenes")) {
-
- convert_text_scenes = cf->get_value("convert_scenes","convert_text_scenes");
- }
-
-
- if (cf->has_section("export_filter_files")) {
-
-
- String eff = "export_filter_files";
- List<String> k;
- cf->get_section_keys(eff,&k);
- for(List<String>::Element *E=k.front();E;E=E->next()) {
-
- String val = cf->get_value(eff,E->get());
- if (val=="copy") {
- files[E->get()]=ACTION_COPY;
- } else if (val=="bundle") {
- files[E->get()]=ACTION_BUNDLE;
- }
- }
- }
-
- List<String> sect;
-
- cf->get_sections(&sect);
-
- for(List<String>::Element *E=sect.front();E;E=E->next()) {
-
- String s = E->get();
- if (!s.begins_with("platform:"))
- continue;
- String p = s.substr(s.find(":")+1,s.length());
-
- if (!exporters.has(p))
- continue;
-
- Ref<EditorExportPlatform> ep = exporters[p];
- if (!ep.is_valid()) {
- continue;
- }
- List<String> keys;
- cf->get_section_keys(s,&keys);
- for(List<String>::Element *F=keys.front();F;F=F->next()) {
- ep->set(F->get(),cf->get_value(s,F->get()));
- }
- }
-
- //save image groups
-
- if (cf->has_section("image_groups")) {
-
- sect.clear();
- cf->get_section_keys("image_groups",&sect);
- for(List<String>::Element *E=sect.front();E;E=E->next()) {
-
- Dictionary d = cf->get_value("image_groups",E->get());
- ImageGroup g;
- g.action=IMAGE_ACTION_NONE;
- g.make_atlas=false;
- g.lossy_quality=0.7;
- g.shrink=1;
-
- if (d.has("action")) {
- String action=d["action"];
- if (action=="compress_ram")
- g.action=IMAGE_ACTION_COMPRESS_RAM;
- else if (action=="compress_disk")
- g.action=IMAGE_ACTION_COMPRESS_DISK;
- else if (action=="keep")
- g.action=IMAGE_ACTION_KEEP;
- }
-
- if (d.has("atlas"))
- g.make_atlas=d["atlas"];
- if (d.has("lossy_quality"))
- g.lossy_quality=d["lossy_quality"];
- if (d.has("shrink")) {
-
- g.shrink=d["shrink"];
- g.shrink=CLAMP(g.shrink,1,8);
- }
-
- image_groups[E->get()]=g;
-
- }
-
- if (cf->has_section_key("image_group_files","files")) {
-
- Vector<String> sa=cf->get_value("image_group_files","files");
- if (sa.size()%2==0) {
- for(int i=0;i<sa.size();i+=2) {
- image_group_files[sa[i]]=sa[i+1];
- }
- }
- }
-
- }
-
-
- if (cf->has_section("script")) {
-
- if (cf->has_section_key("script","action")) {
-
- String action = cf->get_value("script","action");
- if (action=="compile")
- script_action=SCRIPT_ACTION_COMPILE;
- else if (action=="encrypt")
- script_action=SCRIPT_ACTION_ENCRYPT;
- else
- script_action=SCRIPT_ACTION_NONE;
-
- }
-
- if (cf->has_section_key("script","encrypt_key")) {
-
- script_key = cf->get_value("script","encrypt_key");
- }
- }
-
- 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");
-
- if (cf->has_section_key("convert_samples","trim"))
- sample_action_trim=cf->get_value("convert_samples","trim");
- }
-
-
-
-}
-
-
-
-
-
-void EditorImportExport::save_config() {
-
- Ref<ConfigFile> cf = memnew( ConfigFile );
-
- switch(export_filter) {
- case EXPORT_SELECTED: cf->set_value("export_filter","type","selected"); break;
- case EXPORT_RESOURCES: cf->set_value("export_filter","type","resources"); break;
- case EXPORT_ALL: cf->set_value("export_filter","type","all"); break;
- }
-
- cf->set_value("export_filter","filter",export_custom_filter);
- cf->set_value("export_filter", "filter_exclude",export_custom_filter_exclude);
-
- String file_action_section = "export_filter_files";
-
- for (Map<StringName,FileAction>::Element *E=files.front();E;E=E->next()) {
-
- String f=E->key();
- String a;
- switch (E->get()) {
- case ACTION_NONE: {}
- case ACTION_COPY: a="copy"; break;
- case ACTION_BUNDLE: a="bundle"; break;
- }
-
- cf->set_value(file_action_section,f,a);
- }
-
-
- for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
-
- String pname = "platform:"+String(E->key());
-
- Ref<EditorExportPlatform> ep = E->get();
-
- List<PropertyInfo> pl;
- ep->get_property_list(&pl);
-
- for (List<PropertyInfo>::Element *F=pl.front();F;F=F->next()) {
-
- cf->set_value(pname,F->get().name,ep->get(F->get().name));
- }
-
- }
-
- switch(image_action) {
- case IMAGE_ACTION_NONE: cf->set_value("convert_images","action","none"); break;
- case IMAGE_ACTION_COMPRESS_RAM: cf->set_value("convert_images","action","compress_ram"); break;
- case IMAGE_ACTION_COMPRESS_DISK: cf->set_value("convert_images","action","compress_disk"); break;
- }
-
- cf->set_value("convert_images","shrink",image_shrink);
- cf->set_value("convert_images","compress_quality",image_action_compress_quality);
-
- String formats;
- for(Set<String>::Element *E=image_formats.front();E;E=E->next()) {
-
- if (E!=image_formats.front())
- formats+=",";
- formats+=E->get();
- }
-
- cf->set_value("convert_images","formats",formats);
-
- //save image groups
-
- for(Map<StringName,ImageGroup>::Element *E=image_groups.front();E;E=E->next()) {
-
- Dictionary d;
- switch(E->get().action) {
- case IMAGE_ACTION_NONE: d["action"]="default"; break;
- case IMAGE_ACTION_COMPRESS_RAM: d["action"]="compress_ram"; break;
- case IMAGE_ACTION_COMPRESS_DISK: d["action"]="compress_disk"; break;
- case IMAGE_ACTION_KEEP: d["action"]="keep"; break;
- }
-
-
- d["atlas"]=E->get().make_atlas;
- d["shrink"]=E->get().shrink;
- d["lossy_quality"]=E->get().lossy_quality;
- cf->set_value("image_groups",E->key(),d);
-
- }
-
- if (image_groups.size() && image_group_files.size()){
-
- Vector<String> igfkeys;
- igfkeys.resize(image_group_files.size());
- int idx=0;
- for (Map<StringName,StringName>::Element *E=image_group_files.front();E;E=E->next()) {
- igfkeys[idx++]=E->key();
- }
- igfkeys.sort();
-
- Vector<String> igfsave;
- igfsave.resize(image_group_files.size()*2);
- idx=0;
- for (int i=0;i<igfkeys.size();++i) {
-
- igfsave[idx++]=igfkeys[i];
- igfsave[idx++]=image_group_files[igfkeys[i]];
- }
- cf->set_value("image_group_files","files",igfsave);
- }
-
- switch(script_action) {
- case SCRIPT_ACTION_NONE: cf->set_value("script","action","none"); break;
- case SCRIPT_ACTION_COMPILE: cf->set_value("script","action","compile"); break;
- 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) {
- case SAMPLE_ACTION_NONE: cf->set_value("convert_samples","action","none"); break;
- case SAMPLE_ACTION_COMPRESS_RAM: cf->set_value("convert_samples","action","compress_ram"); break;
- }
-
- cf->set_value("convert_samples","max_hz",sample_action_max_hz);
- cf->set_value("convert_samples","trim",sample_action_trim);
-
- cf->save("res://export.cfg");
-
-}
-
-
-void EditorImportExport::script_set_action(ScriptAction p_action) {
-
- script_action=p_action;
-}
-
-EditorImportExport::ScriptAction EditorImportExport::script_get_action() const{
-
- return script_action;
-}
-
-void EditorImportExport::script_set_encryption_key(const String& p_key){
-
- script_key=p_key;
-}
-String EditorImportExport::script_get_encryption_key() const{
-
- return script_key;
-}
-
-
-void EditorImportExport::sample_set_action(SampleAction p_action) {
-
- sample_action=p_action;
-}
-
-EditorImportExport::SampleAction EditorImportExport::sample_get_action() const{
-
- return sample_action;
-}
-
-void EditorImportExport::sample_set_max_hz(int p_hz){
-
- sample_action_max_hz=p_hz;
-}
-int EditorImportExport::sample_get_max_hz() const{
-
- return sample_action_max_hz;
-}
-
-void EditorImportExport::sample_set_trim(bool p_trim){
-
- sample_action_trim=p_trim;
-}
-bool EditorImportExport::sample_get_trim() const{
-
- return sample_action_trim;
-}
-
-PoolVector<String> EditorImportExport::_get_export_file_list() {
-
- PoolVector<String> fl;
- for (Map<StringName,FileAction>::Element *E=files.front();E;E=E->next()) {
-
- fl.push_back(E->key());
- }
-
- return fl;
-}
-
-PoolVector<String> EditorImportExport::_get_export_platforms() {
-
- PoolVector<String> ep;
- for (Map<StringName,Ref<EditorExportPlatform> >::Element *E=exporters.front();E;E=E->next()) {
-
- ep.push_back(E->key());
- }
-
- return ep;
-
-}
-
-void EditorImportExport::_bind_methods() {
-
- ClassDB::bind_method(_MD("add_import_plugin","plugin:EditorImportPlugin"),&EditorImportExport::add_import_plugin);
- ClassDB::bind_method(_MD("remove_import_plugin","plugin:EditorImportPlugin"),&EditorImportExport::remove_import_plugin);
- ClassDB::bind_method(_MD("get_import_plugin_count"),&EditorImportExport::get_import_plugin_count);
- ClassDB::bind_method(_MD("get_import_plugin:EditorImportPlugin","idx"),&EditorImportExport::get_import_plugin);
- ClassDB::bind_method(_MD("get_import_plugin_by_name:EditorImportPlugin","name"),&EditorImportExport::get_import_plugin_by_name);
-
- ClassDB::bind_method(_MD("add_export_plugin","plugin:EditorExportPlugin"),&EditorImportExport::add_export_plugin);
- ClassDB::bind_method(_MD("remove_export_plugin","plugin:EditorExportPlugin"),&EditorImportExport::remove_export_plugin);
- ClassDB::bind_method(_MD("get_export_plugin_count"),&EditorImportExport::get_export_plugin_count);
- ClassDB::bind_method(_MD("get_export_plugin:EditorExportPlugin","idx"),&EditorImportExport::get_export_plugin);
-
- ClassDB::bind_method(_MD("set_export_file_action","file","action"),&EditorImportExport::set_export_file_action);
- ClassDB::bind_method(_MD("get_export_file_action","file"),&EditorImportExport::get_export_file_action);
- ClassDB::bind_method(_MD("get_export_file_list"),&EditorImportExport::_get_export_file_list);
-
- ClassDB::bind_method(_MD("add_export_platform","platform:EditorExportplatform"),&EditorImportExport::add_export_platform);
- //ClassDB::bind_method(_MD("remove_export_platform","platform:EditorExportplatform"),&EditorImportExport::add_export_platform);
- ClassDB::bind_method(_MD("get_export_platform:EditorExportPlatform","name"),&EditorImportExport::get_export_platform);
- ClassDB::bind_method(_MD("get_export_platforms"),&EditorImportExport::_get_export_platforms);
-
- ClassDB::bind_method(_MD("set_export_filter","filter"),&EditorImportExport::set_export_filter);
- ClassDB::bind_method(_MD("get_export_filter"),&EditorImportExport::get_export_filter);
-
- ClassDB::bind_method(_MD("set_export_custom_filter","filter"),&EditorImportExport::set_export_custom_filter);
- ClassDB::bind_method(_MD("get_export_custom_filter"),&EditorImportExport::get_export_custom_filter);
-
- ClassDB::bind_method(_MD("set_export_custom_filter_exclude","filter_exclude"),&EditorImportExport::set_export_custom_filter_exclude);
- ClassDB::bind_method(_MD("get_export_custom_filter_exclude"),&EditorImportExport::get_export_custom_filter_exclude);
-
-
- ClassDB::bind_method(_MD("image_export_group_create"),&EditorImportExport::image_export_group_create);
- ClassDB::bind_method(_MD("image_export_group_remove"),&EditorImportExport::image_export_group_remove);
- ClassDB::bind_method(_MD("image_export_group_set_image_action"),&EditorImportExport::image_export_group_set_image_action);
- ClassDB::bind_method(_MD("image_export_group_set_make_atlas"),&EditorImportExport::image_export_group_set_make_atlas);
- ClassDB::bind_method(_MD("image_export_group_set_shrink"),&EditorImportExport::image_export_group_set_shrink);
- ClassDB::bind_method(_MD("image_export_group_get_image_action"),&EditorImportExport::image_export_group_get_image_action);
- ClassDB::bind_method(_MD("image_export_group_get_make_atlas"),&EditorImportExport::image_export_group_get_make_atlas);
- ClassDB::bind_method(_MD("image_export_group_get_shrink"),&EditorImportExport::image_export_group_get_shrink);
- ClassDB::bind_method(_MD("image_add_to_export_group"),&EditorImportExport::image_add_to_export_group);
- ClassDB::bind_method(_MD("script_set_action"),&EditorImportExport::script_set_action);
- ClassDB::bind_method(_MD("script_set_encryption_key"),&EditorImportExport::script_set_encryption_key);
- ClassDB::bind_method(_MD("script_get_action"),&EditorImportExport::script_get_action);
- ClassDB::bind_method(_MD("script_get_encryption_key"),&EditorImportExport::script_get_encryption_key);
-
-
-
- BIND_CONSTANT( ACTION_NONE );
- BIND_CONSTANT( ACTION_COPY );
- BIND_CONSTANT( ACTION_BUNDLE );
-
- BIND_CONSTANT( EXPORT_SELECTED );
- BIND_CONSTANT( EXPORT_RESOURCES );
- BIND_CONSTANT( EXPORT_ALL );
-
- BIND_CONSTANT( IMAGE_ACTION_NONE );
- BIND_CONSTANT( IMAGE_ACTION_COMPRESS_DISK );
- BIND_CONSTANT( IMAGE_ACTION_COMPRESS_RAM );
- BIND_CONSTANT( IMAGE_ACTION_KEEP );
-
- BIND_CONSTANT( SCRIPT_ACTION_NONE );
- BIND_CONSTANT( SCRIPT_ACTION_COMPILE );
- BIND_CONSTANT( SCRIPT_ACTION_ENCRYPT );
-};
-
-
-
-EditorImportExport::EditorImportExport() {
-
- export_filter=EXPORT_RESOURCES;
- singleton=this;
- image_action=IMAGE_ACTION_NONE;
- image_action_compress_quality=0.7;
- image_formats.insert("png");
- image_shrink=1;
-
-
- script_action=SCRIPT_ACTION_COMPILE;
-
- sample_action=SAMPLE_ACTION_NONE;
- sample_action_max_hz=44100;
- sample_action_trim=false;
-
- convert_text_scenes=true;
-
-}
-
-
-
-EditorImportExport::~EditorImportExport() {
-
-
-
-}
-#endif
diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h
deleted file mode 100644
index 2654a4ea33..0000000000
--- a/tools/editor/editor_import_export.h
+++ /dev/null
@@ -1,425 +0,0 @@
-/*************************************************************************/
-/* editor_import_export.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_IMPORT_EXPORT_H
-#define EDITOR_IMPORT_EXPORT_H
-
-#if 0
-
-#include "resource.h"
-#include "scene/main/node.h"
-#include "scene/resources/texture.h"
-
-
-class EditorExportPlatform;
-class FileAccess;
-struct EditorProgress;
-
-class EditorImportPlugin : public Reference {
-
- GDCLASS( EditorImportPlugin, Reference);
-
-protected:
-
- static void _bind_methods();
-
- String _validate_source_path(const String& p_path);
- String _expand_source_path(const String& p_path);
-
-
-public:
-
-
- static String validate_source_path(const String& p_path);
- static String expand_source_path(const String& p_path);
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
- virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
- virtual void reimport_multiple_files(const Vector<String>& p_list);
- virtual bool can_reimport_multiple_files() const;
- virtual Vector<uint8_t> custom_export(const String& p_path,const Ref<EditorExportPlatform> &p_platform);
-
- EditorImportPlugin();
-};
-
-class EditorExportPlugin : public Reference {
-
- GDCLASS( EditorExportPlugin, Reference);
-
-protected:
- static void _bind_methods();
-
-public:
-
- virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
-
- EditorExportPlugin();
-};
-
-class EditorExportPlatform : public Reference {
-
- GDCLASS( EditorExportPlatform,Reference );
-
-public:
-
- typedef Error (*EditorExportSaveFunction)(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
-
-private:
-
- bool debugging_enabled;
-
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
- 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 {
-
- uint64_t pos;
- uint64_t ofs;
- uint64_t size;
- };
-
- struct PackData {
-
- FileAccess *ftmp;
- FileAccess *f;
- Vector<TempData> file_ofs;
- EditorProgress *ep;
- int count;
- int alignment;
-
- };
-
- 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:
-
- enum ImageCompression {
-
- IMAGE_COMPRESSION_NONE,
- IMAGE_COMPRESSION_INDEXED, // used for older hardware
- IMAGE_COMPRESSION_BC, // directx compression format
- IMAGE_COMPRESSION_PVRTC, // powervr compression format
- IMAGE_COMPRESSION_PVRTC_SQUARE, // powervr compression format, square (ios)
- IMAGE_COMPRESSION_ETC1, // ericsson compression format (alpha is uncompressed)
- IMAGE_COMPRESSION_ETC2, // ericsson new compression format (can handle alpha)
- };
-
- enum ExportFlags {
- EXPORT_DUMB_CLIENT=1,
- EXPORT_REMOTE_DEBUG=2,
- EXPORT_REMOTE_DEBUG_LOCALHOST=4,
- EXPORT_VIEW_COLLISONS=8,
- EXPORT_VIEW_NAVIGATION=16,
- };
-
- bool is_debugging_enabled() const;
- void set_debugging_enabled( bool p_enabled );
-
- 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;
-
- virtual bool poll_devices() { return false; }
- virtual int get_device_count() const { return 0; }
- virtual String get_device_name(int p_device) const { return ""; }
- virtual String get_device_info(int p_device) const { return ""; }
- virtual Error run(int p_device,int p_flags) { return OK; }
-
- virtual bool can_export(String *r_error=NULL) const=0;
-
-
- virtual bool requires_password(bool p_debug) const { return false; }
- virtual String get_binary_extension() const=0;
- virtual Error export_project(const String& p_path,bool p_debug,int p_flags=0)=0;
-
- EditorExportPlatform();
-};
-
-class EditorExportPlatformPC : public EditorExportPlatform {
-
- GDCLASS( EditorExportPlatformPC,EditorExportPlatform );
-
-public:
-
- enum ExportMode {
- EXPORT_EXE,
- EXPORT_PACK,
- EXPORT_ZIP
- };
-
-
-private:
-
-
- String binary_extension;
- String platform;
-
- String custom_release_binary;
- String custom_debug_binary;
- String release_binary32;
- String debug_binary32;
- String release_binary64;
- String debug_binary64;
- String name;
- bool use64;
-
- Ref<Texture> logo;
-
- ExportMode export_mode;
- bool bundle;
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
-public:
-
- virtual String get_name() const { return name; }
- virtual Ref<Texture> get_logo() const { return logo; }
- virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_BC; }
-
- virtual String get_binary_extension() const { return binary_extension; }
- virtual Error export_project(const String& p_path, bool p_debug, int p_flags=0);
- virtual void set_release_binary32(const String& p_binary) { release_binary32=p_binary; }
- virtual void set_debug_binary32(const String& p_binary) { debug_binary32=p_binary; }
- virtual void set_release_binary64(const String& p_binary) { release_binary64=p_binary; }
- virtual void set_debug_binary64(const String& p_binary) { debug_binary64=p_binary; }
- virtual void set_name(const String& p_name) { name=p_name; }
- virtual void set_logo(const Ref<Texture>& p_logo) { logo=p_logo; }
-
- virtual bool can_export(String *r_error=NULL) const;
-
- void set_binary_extension(const String& p_extension);
-
- EditorExportPlatformPC();
-};
-
-
-class EditorImportExport : public Node {
- GDCLASS(EditorImportExport,Node);
-public:
-
- enum FileAction {
-
- ACTION_NONE,
- ACTION_COPY,
- ACTION_BUNDLE
- };
-
- enum ExportFilter {
- EXPORT_SELECTED,
- EXPORT_RESOURCES,
- EXPORT_ALL,
-
- };
-
- enum ImageAction {
- IMAGE_ACTION_NONE,
- IMAGE_ACTION_COMPRESS_DISK,
- IMAGE_ACTION_COMPRESS_RAM,
- IMAGE_ACTION_KEEP //for group
-
- };
-
- enum ScriptAction {
- SCRIPT_ACTION_NONE,
- SCRIPT_ACTION_COMPILE,
- SCRIPT_ACTION_ENCRYPT
- };
-
- enum SampleAction {
-
- SAMPLE_ACTION_NONE,
- SAMPLE_ACTION_COMPRESS_RAM,
- };
-
-protected:
-
- struct ImageGroup {
-
- ImageAction action;
- bool make_atlas;
- float lossy_quality;
- float shrink;
- };
-
- Vector<Ref<EditorExportPlugin> > export_plugins;
- Vector<Ref<EditorImportPlugin> > plugins;
- Map<String,int> by_idx;
- ImageAction image_action;
- float image_action_compress_quality;
- float image_shrink;
- Set<String> image_formats;
-
- ExportFilter export_filter;
- String export_custom_filter, export_custom_filter_exclude;
- Map<StringName,FileAction> files;
- Map<StringName,Ref<EditorExportPlatform> > exporters;
- Map<StringName,ImageGroup> image_groups;
- Map<StringName,StringName> image_group_files;
- Vector<String> diff_packs;
-
- ScriptAction script_action;
- String script_key;
-
- SampleAction sample_action;
- int sample_action_max_hz;
- bool sample_action_trim;
-
- bool convert_text_scenes;
-
- static EditorImportExport* singleton;
-
- PoolVector<String> _get_export_file_list();
- PoolVector<String> _get_export_platforms();
-
- static void _bind_methods();
-public:
-
- static EditorImportExport* get_singleton() { return singleton; }
-
- void add_import_plugin(const Ref<EditorImportPlugin>& p_plugin);
- void remove_import_plugin(const Ref<EditorImportPlugin>& p_plugin);
- int get_import_plugin_count() const;
- Ref<EditorImportPlugin> get_import_plugin(int p_idx) const;
- Ref<EditorImportPlugin> get_import_plugin_by_name(const String& p_string) const;
-
- void add_export_plugin(const Ref<EditorExportPlugin>& p_plugin);
- void remove_export_plugin(const Ref<EditorExportPlugin>& p_plugin);
- int get_export_plugin_count() const;
- Ref<EditorExportPlugin> get_export_plugin(int p_idx) const;
-
- bool poll_export_platforms();
-
- void set_export_file_action(const StringName& p_export_file, FileAction p_action);
- FileAction get_export_file_action(const StringName& p_export_file) const;
- void get_export_file_list(List<StringName> *p_export_files);
-
- void add_export_platform(const Ref<EditorExportPlatform>& p_export);
- Ref<EditorExportPlatform> get_export_platform(const StringName& p_platform);
- void get_export_platforms(List<StringName> *r_platforms);
-
- void set_export_filter(ExportFilter p_enable);
- ExportFilter get_export_filter() const;
-
- void set_export_custom_filter(const String& p_custom_filter);
- void set_export_custom_filter_exclude(const String& p_custom_filter);
- String get_export_custom_filter() const;
- String get_export_custom_filter_exclude() const;
-
- void set_export_image_action(ImageAction p_action);
- ImageAction get_export_image_action() const;
-
- void set_export_image_shrink(float p_shrink);
- float get_export_image_shrink() const;
-
- void set_export_image_quality(float p_quality);
- float get_export_image_quality() const;
-
- Vector<String>& get_diff_packs() { return diff_packs; }
-
- void image_export_group_create(const StringName& p_name);
- void image_export_group_remove(const StringName& p_name);
- bool image_export_has_group(const StringName& p_name) const;
- void image_export_get_groups(List<StringName> *r_name) const;
- void image_export_group_set_image_action(const StringName& p_export_group,ImageAction p_action);
- ImageAction image_export_group_get_image_action(const StringName& p_export_group) const;
- void image_export_group_set_make_atlas(const StringName& p_export_group,bool p_make);
- bool image_export_group_get_make_atlas(const StringName& p_export_group) const;
- void image_export_group_set_shrink(const StringName& p_export_group,float p_amount);
- float image_export_group_get_shrink(const StringName& p_export_group) const;
- void image_export_group_set_lossy_quality(const StringName& p_export_group,float p_quality);
- float image_export_group_get_lossy_quality(const StringName& p_export_group) const;
-
- void image_add_to_export_group(const StringName& p_image,const StringName& p_export_group);
- StringName image_get_export_group(const StringName& p_image) const;
- void image_export_get_images_in_group(const StringName& p_group, List<StringName> *r_images) const;
-
- Set<String>& get_image_formats() { return image_formats; }
-
- void script_set_action(ScriptAction p_action);
- ScriptAction script_get_action() const;
-
- void script_set_encryption_key(const String& p_key);
- String script_get_encryption_key() const;
-
- void sample_set_action(SampleAction p_action);
- SampleAction sample_get_action() const;
-
- void sample_set_max_hz(int p_hz);
- int sample_get_max_hz() const;
-
- 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();
-
- EditorImportExport();
- ~EditorImportExport();
-};
-
-VARIANT_ENUM_CAST(EditorImportExport::FileAction);
-VARIANT_ENUM_CAST(EditorImportExport::ExportFilter);
-VARIANT_ENUM_CAST(EditorImportExport::ImageAction);
-VARIANT_ENUM_CAST(EditorImportExport::ScriptAction);
-VARIANT_ENUM_CAST(EditorImportExport::SampleAction);
-
-#endif
-#endif // EDITOR_IMPORT_EXPORT_H
diff --git a/tools/editor/editor_log.cpp b/tools/editor/editor_log.cpp
deleted file mode 100644
index 6b6a1b9988..0000000000
--- a/tools/editor/editor_log.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/*************************************************************************/
-/* editor_log.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_log.h"
-
-#include "version.h"
-#include "scene/gui/center_container.h"
-#include "editor_node.h"
-
-void EditorLog::_error_handler(void *p_self, const char*p_func, const char*p_file,int p_line, const char*p_error,const char*p_errorexp,ErrorHandlerType p_type ) {
-
- EditorLog *self=(EditorLog *)p_self;
- if (self->current!=Thread::get_caller_ID())
- return;
-
- String err_str;
- if (p_errorexp && p_errorexp[0]) {
- err_str=p_errorexp;
- } else {
- err_str=String(p_file)+":"+itos(p_line)+" - "+String(p_error);
- }
-
- /*
- if (!self->is_visible_in_tree())
- self->emit_signal("show_request");
- */
-
- err_str=" "+err_str;
- self->log->add_newline();
-
- Ref<Texture> icon;
-
- switch(p_type) {
- case ERR_HANDLER_ERROR: {
-
- icon = self->get_icon("Error","EditorIcons");
- return; // these are confusing
- } break;
- case ERR_HANDLER_WARNING: {
-
- icon = self->get_icon("Error","EditorIcons");
-
- } break;
- case ERR_HANDLER_SCRIPT: {
-
- icon = self->get_icon("ScriptError","EditorIcons");
- } break;
- case ERR_HANDLER_SHADER: {
-
- icon = self->get_icon("Shader","EditorIcons");
- } break;
-
- }
-
- self->add_message(err_str,true);
-
-}
-
-void EditorLog::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- log->add_color_override("default_color",get_color("font_color","Tree"));
- //button->set_icon(get_icon("Console","EditorIcons"));
-
- }
-
- /*if (p_what==NOTIFICATION_DRAW) {
-
- RID ci = get_canvas_item();
- get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
- int top_ofs = 20;
- int border_ofs=4;
- Ref<StyleBox> style = get_stylebox("normal","TextEdit");
-
- style->draw(ci,Rect2( Point2(border_ofs,top_ofs),get_size()-Size2(border_ofs*2,top_ofs+border_ofs)));
- }*/
-}
-
-
-
-
-void EditorLog::_clear_request() {
-
- log->clear();
-
-}
-
-void EditorLog::clear() {
- _clear_request();
-}
-
-
-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);
- log->push_color(get_color("fg_error","Editor"));
- } else {
- //button->set_icon(Ref<Texture>());
-
- }
-
-
- log->add_newline();
- log->add_text(p_msg);
- //button->set_text(p_msg);
-
- if (p_error)
- log->pop();
-
-
-}
-
-/*
-void EditorLog::_dragged(const Point2& p_ofs) {
-
- int ofs = ec->get_minsize().height;
- ofs = ofs-p_ofs.y;
- if (ofs<50)
- ofs=50;
- if (ofs>300)
- ofs=300;
- ec->set_minsize(Size2(ec->get_minsize().width,ofs));
- minimum_size_changed();
-
-}
-*/
-
-
-
-
-void EditorLog::_undo_redo_cbk(void *p_self,const String& p_name) {
-
- EditorLog *self=(EditorLog *)p_self;
- self->add_message(p_name);
-
-}
-
-void EditorLog::_bind_methods() {
-
- ClassDB::bind_method(_MD("_clear_request"),&EditorLog::_clear_request );
- ClassDB::bind_method("_override_logger_styles",&EditorLog::_override_logger_styles );
- //ClassDB::bind_method(_MD("_dragged"),&EditorLog::_dragged );
- ADD_SIGNAL( MethodInfo("clear_request"));
-}
-
-EditorLog::EditorLog() {
-
- VBoxContainer *vb = this;
- add_constant_override("separation",get_constant("separation","VBoxContainer"));
-
- HBoxContainer *hb = memnew( HBoxContainer );
- vb->add_child(hb);
- title = memnew( Label );
- title->set_text(TTR(" Output:"));
- title->set_h_size_flags(SIZE_EXPAND_FILL);
- hb->add_child(title);
-
- //pd = memnew( PaneDrag );
- //hb->add_child(pd);
- //pd->connect("dragged",this,"_dragged");
- //pd->set_default_cursor_shape(Control::CURSOR_MOVE);
-
- clearbutton = memnew( Button );
- hb->add_child(clearbutton);
- clearbutton->set_text(TTR("Clear"));
- clearbutton->connect("pressed", this,"_clear_request");
-
- ec = memnew( Control);
- vb->add_child(ec);
- ec->set_custom_minimum_size(Size2(0,180));
- ec->set_v_size_flags(SIZE_EXPAND_FILL);
-
- pc = memnew( PanelContainer );
- ec->add_child(pc);
- pc->set_area_as_parent_rect();
- pc->connect("tree_entered", this, "_override_logger_styles");
-
- log = memnew( RichTextLabel );
- log->set_scroll_follow(true);
- log->set_selection_enabled(true);
- log->set_focus_mode(FOCUS_CLICK);
- pc->add_child(log);
- add_message(VERSION_FULL_NAME" (c) 2008-2017 Juan Linietsky, Ariel Manzur.");
- //log->add_text("Initialization Complete.\n"); //because it looks cool.
-
- eh.errfunc=_error_handler;
- eh.userdata=this;
- add_error_handler(&eh);
-
- current=Thread::get_caller_ID();
-
- EditorNode::get_undo_redo()->set_commit_notify_callback(_undo_redo_cbk,this);
-
-
-}
-
-void EditorLog::deinit() {
-
- remove_error_handler(&eh);
-
-}
-
-void EditorLog::_override_logger_styles() {
-
- pc->add_style_override("panel",get_stylebox("normal","TextEdit"));
-
-}
-
-EditorLog::~EditorLog() {
-
-
-}
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
deleted file mode 100644
index 352b0818b4..0000000000
--- a/tools/editor/editor_node.cpp
+++ /dev/null
@@ -1,6573 +0,0 @@
-/*************************************************************************/
-/* editor_node.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_node.h"
-
-#include "version.h"
-#include "print_string.h"
-#include "editor_themes.h"
-#include "editor_help.h"
-#include "core/io/resource_saver.h"
-#include "core/io/resource_loader.h"
-#include "servers/physics_2d_server.h"
-#include "scene/resources/packed_scene.h"
-#include "editor_settings.h"
-#include "globals.h"
-#include <stdio.h>
-#include "class_db.h"
-#include "os/keyboard.h"
-#include "os/os.h"
-#include "os/file_access.h"
-#include "message_queue.h"
-#include "path_remap.h"
-#include "translation.h"
-#include "pvrtc_compress.h"
-#include "editor_file_system.h"
-#include "register_exporters.h"
-#include "bind/core_bind.h"
-#include "io/zip_io.h"
-#include "io/config_file.h"
-#include "animation_editor.h"
-#include "io/stream_peer_ssl.h"
-#include "main/input_default.h"
-#include "os/input.h"
-// plugins
-#include "plugins/sprite_frames_editor_plugin.h"
-#include "plugins/texture_region_editor_plugin.h"
-#include "plugins/canvas_item_editor_plugin.h"
-#include "asset_library_editor_plugin.h"
-#include "plugins/spatial_editor_plugin.h"
-#include "plugins/sample_editor_plugin.h"
-#include "plugins/texture_editor_plugin.h"
-#include "plugins/material_editor_plugin.h"
-#include "plugins/sample_library_editor_plugin.h"
-#include "plugins/sample_player_editor_plugin.h"
-#include "plugins/camera_editor_plugin.h"
-#include "plugins/style_box_editor_plugin.h"
-#include "plugins/resource_preloader_editor_plugin.h"
-#include "plugins/item_list_editor_plugin.h"
-#include "plugins/stream_editor_plugin.h"
-#include "plugins/multimesh_editor_plugin.h"
-#include "plugins/mesh_instance_editor_plugin.h"
-#include "plugins/mesh_editor_plugin.h"
-#include "plugins/theme_editor_plugin.h"
-#include "plugins/tile_map_editor_plugin.h"
-#include "plugins/cube_grid_theme_editor_plugin.h"
-#include "plugins/shader_editor_plugin.h"
-#include "plugins/shader_graph_editor_plugin.h"
-#include "plugins/path_editor_plugin.h"
-#include "plugins/rich_text_editor_plugin.h"
-#include "plugins/collision_polygon_editor_plugin.h"
-#include "plugins/collision_polygon_2d_editor_plugin.h"
-#include "plugins/script_editor_plugin.h"
-#include "plugins/script_text_editor.h"
-#include "plugins/path_2d_editor_plugin.h"
-#include "plugins/particles_editor_plugin.h"
-#include "plugins/particles_2d_editor_plugin.h"
-#include "plugins/animation_tree_editor_plugin.h"
-#include "plugins/tile_set_editor_plugin.h"
-#include "plugins/animation_player_editor_plugin.h"
-#include "plugins/baked_light_editor_plugin.h"
-#include "plugins/polygon_2d_editor_plugin.h"
-#include "plugins/navigation_polygon_editor_plugin.h"
-#include "plugins/light_occluder_2d_editor_plugin.h"
-#include "plugins/color_ramp_editor_plugin.h"
-#include "plugins/collision_shape_2d_editor_plugin.h"
-#include "plugins/gi_probe_editor_plugin.h"
-#include "import/resource_importer_texture.h"
-#include "import/resource_importer_csv_translation.h"
-#include "import/resource_importer_wav.h"
-#include "import/resource_importer_obj.h"
-#include "import/resource_importer_scene.h"
-// end
-#include "editor_settings.h"
-#include "io_plugins/editor_texture_import_plugin.h"
-#include "io_plugins/editor_scene_import_plugin.h"
-#include "io_plugins/editor_font_import_plugin.h"
-#include "io_plugins/editor_sample_import_plugin.h"
-#include "io_plugins/editor_translation_import_plugin.h"
-#include "io_plugins/editor_bitmask_import_plugin.h"
-#include "io_plugins/editor_mesh_import_plugin.h"
-#include "io_plugins/editor_export_scene.h"
-#include "import/editor_import_collada.h"
-#include "io_plugins/editor_scene_importer_fbxconv.h"
-
-#include "plugins/editor_preview_plugins.h"
-#include "editor_initialize_ssl.h"
-#include "editor_audio_buses.h"
-#include "script_editor_debugger.h"
-
-EditorNode *EditorNode::singleton=NULL;
-
-void EditorNode::_update_scene_tabs() {
-
- bool show_rb = EditorSettings::get_singleton()->get("interface/show_script_in_scene_tabs");
-
- scene_tabs->clear_tabs();
- Ref<Texture> script_icon = gui_base->get_icon("Script","EditorIcons");
- for(int i=0;i<editor_data.get_edited_scene_count();i++) {
-
- String type=editor_data.get_scene_type(i);
- Ref<Texture> icon;
- if (type!=String()) {
-
- if (!gui_base->has_icon(type,"EditorIcons")) {
- type="Node";
- }
-
- icon=gui_base->get_icon(type,"EditorIcons");
-
- }
-
-
-
- int current = editor_data.get_edited_scene();
- bool unsaved = (i==current)?saved_version!=editor_data.get_undo_redo().get_version():editor_data.get_scene_version(i)!=0;
- scene_tabs->add_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":""),icon);
-
- if (show_rb && editor_data.get_scene_root_script(i).is_valid()) {
- scene_tabs->set_tab_right_button(i,script_icon);
- }
-
- }
-
- scene_tabs->set_current_tab(editor_data.get_edited_scene());
- scene_tabs->ensure_tab_visible(editor_data.get_edited_scene());
-
-}
-
-void EditorNode::_update_title() {
-
- String appname = GlobalConfig::get_singleton()->get("application/name");
- String title = appname.empty()?String(VERSION_FULL_NAME):String(_MKSTR(VERSION_NAME) + String(" - ") + appname);
- String edited = editor_data.get_edited_scene_root()?editor_data.get_edited_scene_root()->get_filename():String();
- if (!edited.empty())
- title+=" - " + String(edited.get_file());
- if (unsaved_cache)
- title+=" (*)";
-
- OS::get_singleton()->set_window_title(title);
-
-}
-
-void EditorNode::_unhandled_input(const InputEvent& p_event) {
-
- if (Node::get_viewport()->get_modal_stack_top())
- return; //ignore because of modal window
-
-
- if (p_event.type==InputEvent::KEY && p_event.key.pressed && !p_event.key.echo && !gui_base->get_viewport()->gui_has_modal_stack()) {
-
-
- if (ED_IS_SHORTCUT("editor/next_tab", p_event)) {
- int next_tab = editor_data.get_edited_scene() + 1;
- next_tab %= editor_data.get_edited_scene_count();
- _scene_tab_changed(next_tab);
- }
- if (ED_IS_SHORTCUT("editor/prev_tab", p_event)) {
- int next_tab = editor_data.get_edited_scene() - 1;
- next_tab = next_tab >= 0 ? next_tab : editor_data.get_edited_scene_count() - 1;
- _scene_tab_changed(next_tab);
- }
- if (ED_IS_SHORTCUT("editor/filter_files", p_event)) {
- filesystem_dock->focus_on_filter();
- }
-
- switch(p_event.key.scancode) {
-
- /*case KEY_F1:
- if (!p_event.key.mod.shift && !p_event.key.mod.command)
- _editor_select(EDITOR_SCRIPT);
- break;*/
- case KEY_F1:
- if (!p_event.key.mod.shift && !p_event.key.mod.command)
- _editor_select(EDITOR_2D);
- break;
- case KEY_F2:
- if (!p_event.key.mod.shift && !p_event.key.mod.command)
- _editor_select(EDITOR_3D);
- break;
- case KEY_F3:
- if (!p_event.key.mod.shift && !p_event.key.mod.command)
- _editor_select(EDITOR_SCRIPT);
- break;
- /* case KEY_F5: _menu_option_confirm((p_event.key.mod.control&&p_event.key.mod.shift)?RUN_PLAY_CUSTOM_SCENE:RUN_PLAY,true); break;
- case KEY_F6: _menu_option_confirm(RUN_PLAY_SCENE,true); break;
- //case KEY_F7: _menu_option_confirm(RUN_PAUSE,true); break;
- case KEY_F8: _menu_option_confirm(RUN_STOP,true); break;*/
-
- }
-
- }
-}
-
-
-
-void EditorNode::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
- editor_data.save_editor_external_data();
- FileAccess::set_file_close_fail_notify_callback(NULL);
- log->deinit(); // do not get messages anymore
- }
- if (p_what==NOTIFICATION_PROCESS) {
-
- //force the whole tree viewport
-#if 0
- {
- Rect2 grect = scene_root_base->get_global_rect();
- Rect2 grectsrp = scene_root_parent->get_global_rect();
- if (grect!=grectsrp) {
- scene_root_parent->set_pos(grect.pos);
- scene_root_parent->set_size(grect.size);
- }
- }
-
-#endif
- if (opening_prev && !confirmation->is_visible())
- opening_prev=false;
-
- if (unsaved_cache != (saved_version!=editor_data.get_undo_redo().get_version())) {
-
- unsaved_cache = (saved_version!=editor_data.get_undo_redo().get_version());
- _update_title();
- }
-
- if (last_checked_version!=editor_data.get_undo_redo().get_version()) {
- _update_scene_tabs();
- last_checked_version=editor_data.get_undo_redo().get_version();
- }
-
- //get_root_node()->set_rect(viewport->get_global_rect());
-
- //update the circle
- uint64_t frame = Engine::get_singleton()->get_frames_drawn();
- uint32_t tick = OS::get_singleton()->get_ticks_msec();
-
- if (frame!=circle_step_frame && (tick-circle_step_msec)>(1000/8)) {
-
- circle_step++;
- if (circle_step>=8)
- circle_step=0;
-
- circle_step_msec=tick;
- circle_step_frame=frame+1;
-
- // update the circle itself only when its enabled
- if (!update_menu->get_popup()->is_item_checked(3)){
- update_menu->set_icon(gui_base->get_icon("Progress"+itos(circle_step+1),"EditorIcons"));
- }
- }
-
- editor_selection->update();
-
- {
- uint32_t p32 = 0;//AudioServer::get_singleton()->read_output_peak()>>8;
-
- float peak = p32==0? -80 : Math::linear2db(p32 / 65535.0);
-
- if (peak<-80)
- peak=-80;
- float vu = audio_vu->get_value();
-
- if (peak > vu) {
- audio_vu->set_value(peak);
- } else {
- float new_vu = vu - get_process_delta_time()*70.0;
- if (new_vu<-80)
- new_vu=-80;
- if (new_vu !=-80 && vu !=-80)
- audio_vu->set_value(new_vu);
- }
-
- }
-
- ResourceImporterTexture::get_singleton()->update_imports();
-
- }
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- get_tree()->get_root()->set_disable_3d(true);
- //MessageQueue::get_singleton()->push_call(this,"_get_scene_metadata");
- get_tree()->set_editor_hint(true);
- get_tree()->get_root()->set_as_audio_listener(false);
- get_tree()->get_root()->set_as_audio_listener_2d(false);
- get_tree()->set_auto_accept_quit(false);
- get_tree()->connect("files_dropped",this,"_dropped_files");
- //VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport(),false);
-
- //import_monitor->scan_changes();
- }
-
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
-
- editor_data.clear_edited_scenes();
-
- }
- if (p_what==NOTIFICATION_READY) {
-
- VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(),true);
- VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(),true);
- VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(),true);
-
- _editor_select(EDITOR_3D);
-
-/*
- if (defer_optimize!="") {
- Error ok = save_optimized_copy(defer_optimize,defer_optimize_preset);
- defer_optimize_preset="";
- if (ok!=OK)
- OS::get_singleton()->set_exit_code(255);
- get_scene()->quit();
- }
-*/
-
- /* // moved to "_sources_changed"
- if (export_defer.platform!="") {
-
- project_export_settings->export_platform(export_defer.platform,export_defer.path,export_defer.debug,export_defer.password,true);
- export_defer.platform="";
- }
-
- */
- }
-
- if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_IN) {
-
- EditorFileSystem::get_singleton()->scan_changes();
- }
-
- if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) {
-
- _menu_option_confirm(FILE_QUIT, false);
- };
-
- if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- scene_tabs->set_tab_close_display_policy( (bool(EDITOR_DEF("interface/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY) );
- }
-
-}
-
-void EditorNode::_fs_changed() {
-
- for(Set<FileDialog*>::Element *E=file_dialogs.front();E;E=E->next()) {
-
- E->get()->invalidate();
- }
-
- for(Set<EditorFileDialog*>::Element *E=editor_file_dialogs.front();E;E=E->next()) {
-
- E->get()->invalidate();
- }
-
- if (export_defer.platform!="") {
-
- //project_export_settings->export_platform(export_defer.platform,export_defer.path,export_defer.debug,export_defer.password,true);
- export_defer.platform="";
- }
-
- {
-
- //reload changed resources
- List<Ref<Resource> > changed;
-
- List<Ref<Resource> > cached;
- ResourceCache::get_cached_resources(&cached);
- //this should probably be done in a thread..
- for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) {
-
- if (!E->get()->editor_can_reload_from_file())
- continue;
- if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path())
- continue;
- if (!FileAccess::exists(E->get()->get_path()))
- continue;
-
- if (E->get()->get_import_path()!=String()) {
- //imported resource
- uint64_t mt = FileAccess::get_modified_time(E->get()->get_import_path());
- print_line("testing modified: "+E->get()->get_import_path()+" "+itos(mt)+" vs "+itos(E->get()->get_import_last_modified_time()));
-
- if (mt!=E->get()->get_import_last_modified_time()) {
- print_line("success");
- changed.push_back(E->get());
- }
-
- } else {
- uint64_t mt = FileAccess::get_modified_time(E->get()->get_path());
-
- if (mt!=E->get()->get_last_modified_time()) {
- changed.push_back(E->get());
- }
- }
- }
-
- if (changed.size()) {
- //EditorProgress ep("reload_res","Reload Modified Resources",changed.size());
- int idx=0;
- for(List<Ref<Resource> >::Element *E=changed.front();E;E=E->next()) {
-
- //ep.step(E->get()->get_path(),idx++);
- E->get()->reload_from_file();
- }
- }
-
-
- }
-}
-
-
-void EditorNode::_sources_changed(bool p_exist) {
-
- if (waiting_for_first_scan) {
-
- if (defer_load_scene!="") {
-
- print_line("loading scene DEFERED");
- load_scene(defer_load_scene);
- defer_load_scene="";
- }
-
- waiting_for_first_scan=false;
- }
-
-
-}
-
-void EditorNode::_vp_resized() {
-
-
-}
-
-void EditorNode::_rebuild_import_menu()
-{
- PopupMenu* p = import_menu->get_popup();
- p->clear();
- //p->add_item(TTR("Node From Scene"), FILE_IMPORT_SUBSCENE);
- //p->add_separator();
-#if 0
- 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);
- }
-#endif
-}
-
-void EditorNode::_node_renamed() {
-
- if (property_editor)
- property_editor->update_tree();
-}
-
-
-Error EditorNode::load_resource(const String& p_scene) {
-
- RES res = ResourceLoader::load(p_scene);
- ERR_FAIL_COND_V(!res.is_valid(),ERR_CANT_OPEN);
-
- edit_resource(res);
-
- return OK;
-}
-
-
-void EditorNode::edit_resource(const Ref<Resource>& p_resource) {
-
- _resource_selected(p_resource,"");
-}
-
-void EditorNode::edit_node(Node *p_node) {
-
- push_item(p_node);
-}
-
-void EditorNode::open_resource(const String& p_type) {
-
-
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
-
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type(p_type,&extensions);
-
- file->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
- //file->set_current_path(current_path);
-
- file->popup_centered_ratio();
- current_option=RESOURCE_LOAD;
-}
-
-
-void EditorNode::save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path) {
-
- editor_data.apply_changes_in_editors();
- int flg=0;
- if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
- flg|=ResourceSaver::FLAG_COMPRESS;
- /*
- if (EditorSettings::get_singleton()->get("filesystem/on_save/save_paths_as_relative"))
- flg|=ResourceSaver::FLAG_RELATIVE_PATHS;
- */
-
- String path = GlobalConfig::get_singleton()->localize_path(p_path);
- Error err = ResourceSaver::save(path,p_resource,flg|ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
-
- if (err!=OK) {
- accept->set_text(TTR("Error saving resource!"));
- accept->popup_centered_minsize();
- return;
- }
- //EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
-
- ((Resource*)p_resource.ptr())->set_path(path);
- emit_signal("resource_saved",p_resource);
-
-}
-
-void EditorNode::save_resource(const Ref<Resource>& p_resource) {
-
- if (p_resource->get_path().is_resource_file()) {
- save_resource_in_path(p_resource,p_resource->get_path());
- } else {
- save_resource_as(p_resource);
- }
-}
-
-void EditorNode::save_resource_as(const Ref<Resource>& p_resource,const String& p_at_path) {
-
- file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
-
- 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_class("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);
-
- if (p_at_path!=String()) {
-
- file->set_current_dir(p_at_path);
- if (p_resource->get_path().is_resource_file()) {
- file->set_current_file(p_resource->get_path().get_file());
- } else {
- if (extensions.size()) {
- file->set_current_file("new_"+p_resource->get_class().to_lower()+"."+preferred.front()->get().to_lower());
- } else {
- file->set_current_file(String());
- }
- }
- } else if (p_resource->get_path()!="") {
-
- file->set_current_path(p_resource->get_path());
- if (extensions.size()) {
- String ext=p_resource->get_path().get_extension().to_lower();
- if (extensions.find(ext)==NULL) {
- file->set_current_path(p_resource->get_path().replacen("."+ext,"."+extensions.front()->get()));
- }
- }
- } else if (preferred.size()) {
-
- String existing;
- if (extensions.size()) {
- existing="new_"+p_resource->get_class().to_lower()+"."+preferred.front()->get().to_lower();
- }
- file->set_current_path(existing);
-
- }
- file->popup_centered_ratio();
- file->set_title(TTR("Save Resource As.."));
-}
-
-
-void EditorNode::_menu_option(int p_option) {
-
- _menu_option_confirm(p_option,false);
-}
-
-void EditorNode::_menu_confirm_current() {
-
- _menu_option_confirm(current_option,true);
-}
-
-
-void EditorNode::_dialog_display_file_error(String p_file,Error p_error) {
-
-
- if (p_error) {
-
- current_option=-1;
- //accept->"()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
-
- switch(p_error) {
-
- case ERR_FILE_CANT_WRITE: {
-
- accept->set_text(TTR("Can't open file for writing:")+" "+p_file.get_extension());
- } break;
- case ERR_FILE_UNRECOGNIZED: {
-
- accept->set_text(TTR("Requested file format unknown:")+" "+p_file.get_extension());
- } break;
- default: {
-
- accept->set_text(TTR("Error while saving."));
- }break;
- }
-
- accept->popup_centered_minsize();
- }
-
-}
-
-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");
-
- Ref<ConfigFile> cf;
- cf.instance();
-
- Error err = cf->load(path);
- if (err!=OK || !cf->has_section("editor_states"))
- return; //must not exist
-
- List<String> esl;
- cf->get_section_keys("editor_states",&esl);
-
- Dictionary md;
- for (List<String>::Element *E=esl.front();E;E=E->next()) {
-
- 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(const String& p_file, int p_idx) {
-
- Node *scene = editor_data.get_edited_scene_root(p_idx);
-
- if (!scene)
- return;
-
- scene->set_meta("__editor_run_settings__",Variant()); //clear it (no point in keeping it)
- scene->set_meta("__editor_plugin_states__",Variant());
-
- 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;
-
- if (p_idx<0 || editor_data.get_edited_scene()==p_idx) {
- md = editor_data.get_editor_states();
- } else {
- md = editor_data.get_scene_editor_states(p_idx);
- }
-
- 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);
-
-}
-
-
-bool EditorNode::_find_and_save_resource(RES res,Map<RES,bool>& processed,int32_t flags) {
-
- if (res.is_null())
- return false;
-
- if (processed.has(res)) {
-
- return processed[res];
- }
-
-
- bool changed = res->is_edited();
- res->set_edited(false);
-
- bool subchanged = _find_and_save_edited_subresources(res.ptr(),processed,flags);
-
- //print_line("checking if edited: "+res->get_type()+" :: "+res->get_name()+" :: "+res->get_path()+" :: "+itos(changed)+" :: SR "+itos(subchanged));
-
- if (res->get_path().is_resource_file()) {
- if (changed || subchanged) {
- //save
- print_line("Also saving modified external resource: "+res->get_path());
- ResourceSaver::save(res->get_path(),res,flags);
-
- }
- processed[res]=false; //because it's a file
- return false;
- } else {
-
-
- processed[res]=changed;
- return changed;
- }
-}
-
-bool EditorNode::_find_and_save_edited_subresources(Object *obj,Map<RES,bool>& processed,int32_t flags) {
-
- bool ret_changed=false;
- List<PropertyInfo> pi;
- obj->get_property_list(&pi);
- for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
-
- if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
- continue;
-
-
-
- switch(E->get().type) {
- case Variant::OBJECT: {
-
- RES res = obj->get(E->get().name);
-
- if (_find_and_save_resource(res,processed,flags))
- ret_changed=true;
-
- } break;
- case Variant::ARRAY: {
-
- Array varray= obj->get(E->get().name);
- int len=varray.size();
- for(int i=0;i<len;i++) {
-
- Variant v=varray.get(i);
- RES res=v;
- if (_find_and_save_resource(res,processed,flags))
- ret_changed=true;
-
- //_find_resources(v);
- }
-
- } break;
- case Variant::DICTIONARY: {
-
-
- Dictionary d=obj->get(E->get().name);
- List<Variant> keys;
- d.get_key_list(&keys);
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- Variant v = d[E->get()];
- RES res=v;
- if (_find_and_save_resource(res,processed,flags))
- ret_changed=true;
- }
- } break;
- default: {}
- }
-
- }
-
- return ret_changed;
-
-}
-
-void EditorNode::_save_edited_subresources(Node* scene,Map<RES,bool>& processed,int32_t flags) {
-
- _find_and_save_edited_subresources(scene,processed,flags);
-
- for(int i=0;i<scene->get_child_count();i++) {
-
- Node *n = scene->get_child(i);
- if (n->get_owner()!=editor_data.get_edited_scene_root())
- continue;
- _save_edited_subresources(n,processed,flags);
- }
-
-}
-
-void EditorNode::_find_node_types(Node* p_node, int&count_2d, int&count_3d) {
-
- if (p_node->is_class("Viewport") || (p_node!=editor_data.get_edited_scene_root() && p_node->get_owner()!=editor_data.get_edited_scene_root()))
- return;
-
- if (p_node->is_class("CanvasItem"))
- count_2d++;
- else if (p_node->is_class("Spatial"))
- count_3d++;
-
- for(int i=0;i<p_node->get_child_count();i++)
- _find_node_types(p_node->get_child(i),count_2d,count_3d);
-
-}
-
-
-void EditorNode::_save_scene_with_preview(String p_file) {
-
- int c2d=0;
- int c3d=0;
-
- EditorProgress save("save",TTR("Saving Scene"),4);
- save.step(TTR("Analyzing"),0);
- _find_node_types(editor_data.get_edited_scene_root(),c2d,c3d);
-
- RID viewport;
- bool is2d;
- if (c3d<c2d) {
- viewport=scene_root->get_viewport_rid();
- is2d=true;
- } else {
- viewport=SpatialEditor::get_singleton()->get_editor_viewport(0)->get_viewport_node()->get_viewport_rid();
- is2d=false;
-
- }
- save.step(TTR("Creating Thumbnail"),1);
- //current view?
- int screen =-1;
- for(int i=0;i<editor_table.size();i++) {
- if (editor_plugin_screen==editor_table[i]) {
- screen=i;
- break;
- }
- }
-
- _editor_select(is2d?EDITOR_2D:EDITOR_3D);
-
-
- save.step(TTR("Creating Thumbnail"),2);
- save.step(TTR("Creating Thumbnail"),3);
-#if 0
- Image img = VS::get_singleton()->viewport_texture(scree_capture(viewport);
- int preview_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- preview_size*=EDSCALE;
- int width,height;
- if (img.get_width() > preview_size && img.get_width() >= img.get_height()) {
-
- width=preview_size;
- height = img.get_height() * preview_size / img.get_width();
- } else if (img.get_height() > preview_size && img.get_height() >= img.get_width()) {
-
- height=preview_size;
- width = img.get_width() * preview_size / img.get_height();
- } else {
-
- width=img.get_width();
- height=img.get_height();
- }
-
- img.convert(Image::FORMAT_RGB8);
- img.resize(width,height);
-
- String pfile = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/last_scene_preview.png");
- img.save_png(pfile);
- Vector<uint8_t> imgdata = FileAccess::get_file_as_array(pfile);
-
- //print_line("img data is "+itos(imgdata.size()));
-
- if (editor_data.get_edited_scene_import_metadata().is_null())
- editor_data.set_edited_scene_import_metadata(Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) ) );
- editor_data.get_edited_scene_import_metadata()->set_option("thumbnail",imgdata);
-#endif
- //tamanio tel thumbnail
- if (screen!=-1) {
- _editor_select(screen);
- }
- save.step(TTR("Saving Scene"),4);
- _save_scene(p_file);
-
-}
-
-
-void EditorNode::_save_scene(String p_file, int idx) {
-
- Node *scene = editor_data.get_edited_scene_root(idx);
-
- if (!scene) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text("This operation can't be done without a tree root.");
- accept->popup_centered_minsize();
- return;
- }
-
- editor_data.apply_changes_in_editors();
-
- _set_scene_metadata(p_file,idx);
-
-
- 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);
-
-
- if (err!=OK) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Couldn't save scene. Likely dependencies (instances) couldn't be satisfied."));
- accept->popup_centered_minsize();
- return;
- }
-
- int flg=0;
- if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
- flg|=ResourceSaver::FLAG_COMPRESS;
- /*
- if (EditorSettings::get_singleton()->get("filesystem/on_save/save_paths_as_relative"))
- flg|=ResourceSaver::FLAG_RELATIVE_PATHS;
- */
- flg|=ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS;
-
-
- err = ResourceSaver::save(p_file,sdata,flg);
- Map<RES,bool> processed;
- _save_edited_subresources(scene,processed,flg);
- editor_data.save_editor_external_data();
- if (err==OK) {
- scene->set_filename( GlobalConfig::get_singleton()->localize_path(p_file) );
- //EditorFileSystem::get_singleton()->update_file(p_file,sdata->get_type());
- if (idx < 0 || idx == editor_data.get_edited_scene())
- set_current_version(editor_data.get_undo_redo().get_version());
- else
- editor_data.set_edited_scene_version(0,idx);
- _update_title();
- _update_scene_tabs();
- } else {
-
- _dialog_display_file_error(p_file,err);
- }
-
-
-};
-
-
-
-
-void EditorNode::_import_action(const String& p_action) {
-#if 0
- import_confirmation->hide();
-
- if (p_action=="re-import") {
- _import(_tmp_import_path);
- }
- if (p_action=="update") {
-
- Node *src = EditorImport::import_scene(_tmp_import_path);
-
- if (!src) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("Ugh");
- accept->set_text("Error importing scene.");
- accept->popup_centered(Size2(300,70));
- return;
- }
-
- //as soon as the scene is imported, version hashes must be generated for comparison against saved scene
- EditorImport::generate_version_hashes(src);
-
-
- Node *dst = SceneLoader::load(editor_data.get_imported_scene(GlobalConfig::get_singleton()->localize_path(_tmp_import_path)));
-
- if (!dst) {
-
- memdelete(src);
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("Ugh");
- accept->set_text("Error load scene to update.");
- accept->popup_centered(Size2(300,70));
- return;
- }
-
- List<EditorImport::Conflict> conflicts;
- EditorImport::check_conflicts(src,dst,&conflicts);
-
- bool conflicted=false;
- for (List<EditorImport::Conflict>::Element *E=conflicts.front();E;E=E->next()) {
-
-
- if (E->get().status==EditorImport::Conflict::STATUS_CONFLICT) {
-
- conflicted=true;
- break;
- }
- }
-
- if (conflicted) {
- import_conflicts_dialog->popup(src,dst,conflicts);
- return;
- }
-
- _import_with_conflicts(src,dst,conflicts);
- //not conflicted, just reimport!
-
- }
-#endif
-}
-
-void EditorNode::_import(const String &p_file) {
-
-#if 0
- Node *new_scene = EditorImport::import_scene(p_file);
-
- if (!new_scene) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("Ugh");
- accept->set_text("Error importing scene.");
- accept->popup_centered(Size2(300,70));
- return;
- }
-
- //as soon as the scene is imported, version hashes must be generated for comparison against saved scene
- EditorImport::generate_version_hashes(new_scene);
-
- Node *old_scene = edited_scene;
- _hide_top_editors();
- set_edited_scene(NULL);
- editor_data.clear_editor_states();
- if (old_scene) {
- memdelete(old_scene);
- }
-
- set_edited_scene(new_scene);
- scene_tree_dock->set_selected(new_scene);
- //_get_scene_metadata();
-
- editor_data.get_undo_redo().clear_history();
- saved_version=editor_data.get_undo_redo().get_version();
- _update_title();
-
-
-#endif
-}
-
-void EditorNode::_dialog_action(String p_file) {
-
-
- switch(current_option) {
-
- case RESOURCE_LOAD: {
-
- RES res = ResourceLoader::load(p_file);
- if (res.is_null()) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("ok :(");
- accept->set_text(TTR("Failed to load resource."));
- return;
- };
-
-
- push_item(res.operator->() );
- } break;
- case FILE_NEW_INHERITED_SCENE: {
-
-
- load_scene(p_file,false,true);
- } break;
- case FILE_OPEN_SCENE: {
-
-
- load_scene(p_file);
- } break;
- case SETTINGS_PICK_MAIN_SCENE: {
-
- GlobalConfig::get_singleton()->set("application/main_scene",p_file);
- GlobalConfig::get_singleton()->save();
- //would be nice to show the project manager opened with the hilighted field..
- } break;
- case FILE_SAVE_OPTIMIZED: {
-
-
-
- } break;
- case FILE_RUN_SCRIPT: {
-
- Ref<Script> scr = ResourceLoader::load(p_file,"Script",true);
- if (scr.is_null()) {
- add_io_error("Script Failed to Load:\n"+p_file);
- return;
- }
- if (!scr->is_tool()) {
-
- add_io_error("Script is not tool, will not be able to run:\n"+p_file);
- return;
- }
-
- Ref<EditorScript> es = memnew( EditorScript );
- es->set_script(scr.get_ref_ptr());
- es->set_editor(this);
- es->_run();
-
- get_undo_redo()->clear_history();
- } break;
- case FILE_SAVE_SCENE:
- case FILE_SAVE_AS_SCENE: {
-
- if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
-
- //_save_scene(p_file);
- _save_scene_with_preview(p_file);
-
- }
-
- } break;
-
- case FILE_SAVE_AND_RUN: {
- if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
-
- //_save_scene(p_file);
- _save_scene_with_preview(p_file);
- _call_build();
- _run(true);
- }
- } break;
-
- case FILE_EXPORT_MESH_LIBRARY: {
-
- Ref<MeshLibrary> ml;
- if (file_export_lib_merge->is_pressed() && FileAccess::exists(p_file)) {
- ml=ResourceLoader::load(p_file,"MeshLibrary");
-
- if (ml.is_null()) {
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Can't load MeshLibrary for merging!"));
- accept->popup_centered_minsize();
- return;
- }
-
- }
-
- if (ml.is_null()) {
- ml = Ref<MeshLibrary>( memnew( MeshLibrary ));
- }
-
- //MeshLibraryEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true);
-
- Error err = ResourceSaver::save(p_file,ml);
- if (err) {
-
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Error saving MeshLibrary!"));
- accept->popup_centered_minsize();
- return;
- }
-
-
- } break;
- case FILE_EXPORT_TILESET: {
-
- Ref<TileSet> ml;
- if (FileAccess::exists(p_file)) {
- ml=ResourceLoader::load(p_file,"TileSet");
-
- if (ml.is_null()) {
- if (file_export_lib_merge->is_pressed()) {
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Can't load TileSet for merging!"));
- accept->popup_centered_minsize();
- return;
- }
- } else if (!file_export_lib_merge->is_pressed()) {
- ml->clear();
- }
-
- } else {
- ml = Ref<TileSet>( memnew( TileSet ));
- }
-
- TileSetEditor::update_library_file(editor_data.get_edited_scene_root(),ml,true);
-
- Error err = ResourceSaver::save(p_file,ml);
- if (err) {
-
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Error saving TileSet!"));
- accept->popup_centered_minsize();
- return;
- }
- } break;
-
- case SETTINGS_LOAD_EXPORT_TEMPLATES: {
-
- FileAccess *fa=NULL;
- zlib_filefunc_def io = zipio_create_io_from_file(&fa);
-
- unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
- if (!pkg) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Can't open export templates zip."));
- accept->popup_centered_minsize();
- return;
-
- }
- int ret = unzGoToFirstFile(pkg);
-
- int fc=0; //count them
-
- while(ret==UNZ_OK) {
- fc++;
- ret = unzGoToNextFile(pkg);
-
- }
-
- ret = unzGoToFirstFile(pkg);
-
- EditorProgress p("ltask",TTR("Loading Export Templates"),fc);
-
- fc=0;
-
- while(ret==UNZ_OK) {
-
- //get filename
- unz_file_info info;
- char fname[16384];
- ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
-
-
- String file=fname;
-
- Vector<uint8_t> data;
- data.resize(info.uncompressed_size);
-
- //read
- ret = unzOpenCurrentFile(pkg);
- ret = unzReadCurrentFile(pkg,data.ptr(),data.size());
- unzCloseCurrentFile(pkg);
-
- print_line(fname);
- /*
- for(int i=0;i<512;i++) {
- print_line(itos(data[i]));
- }
- */
-
- file=file.get_file();
-
- p.step(TTR("Importing:")+" "+file,fc);
-
- FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_settings_path()+"/templates/"+file,FileAccess::WRITE);
-
- ERR_CONTINUE(!f);
- f->store_buffer(data.ptr(),data.size());
-
- memdelete(f);
-
- ret = unzGoToNextFile(pkg);
- fc++;
- }
-
- unzClose(pkg);
-
- } break;
-
- case RESOURCE_SAVE:
- case RESOURCE_SAVE_AS: {
-
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!current_obj->cast_to<Resource>())
-
- RES current_res = RES(current_obj->cast_to<Resource>());
-
- 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(TTR("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(TTR("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(TTR("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(TTR("Restored default layout to base settings."));
- }
-
- } break;
- default: { //save scene?
-
- if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
-
- //_save_scene(p_file);
- _save_scene_with_preview(p_file);
- }
-
- } break;
- }
-}
-
-
-
-void EditorNode::push_item(Object *p_object,const String& p_property) {
-
-
- if (!p_object) {
- property_editor->edit(NULL);
- node_dock->set_node(NULL);
- scene_tree_dock->set_selected(NULL);
- return;
- }
-
- uint32_t id = p_object->get_instance_ID();
- if (id!=editor_history.get_current()) {
-
- if (p_property=="")
- editor_history.add_object(id);
- else
- editor_history.add_object(id,p_property);
- }
-
- _edit_current();
-
-}
-
-void EditorNode::_select_history(int p_idx) {
-
- //push it to the top, it is not correct, but it's more useful
- ObjectID id=editor_history.get_history_obj(p_idx);
- Object* obj=ObjectDB::get_instance(id);
- if (!obj)
- return;
- push_item(obj);
-}
-
-void EditorNode::_prepare_history() {
-
- int history_to = MAX(0,editor_history.get_history_len()-25);
-
- editor_history_menu->get_popup()->clear();
-
- Ref<Texture> base_icon = gui_base->get_icon("Object","EditorIcons");
- Set<ObjectID> already;
- for(int i=editor_history.get_history_len()-1;i>=history_to;i--) {
-
-
- ObjectID id=editor_history.get_history_obj(i);
- Object* obj=ObjectDB::get_instance(id);
- if (!obj || already.has(id)) {
- if (history_to>0) {
- history_to--;
- }
- continue;
- }
-
- already.insert(id);
-
- Ref<Texture> icon = gui_base->get_icon("Object","EditorIcons");
- if (gui_base->has_icon(obj->get_class(),"EditorIcons"))
- icon=gui_base->get_icon(obj->get_class(),"EditorIcons");
- else
- icon=base_icon;
-
- String text;
- if (obj->cast_to<Resource>()) {
- Resource *r=obj->cast_to<Resource>();
- if (r->get_path().is_resource_file())
- text=r->get_path().get_file();
- else if (r->get_name()!=String()) {
- text=r->get_name();
- } else {
- text=r->get_class();
- }
- } else if (obj->cast_to<Node>()) {
- text=obj->cast_to<Node>()->get_name();
- } else {
- text=obj->get_class();
- }
-
- if (i==editor_history.get_history_pos()) {
- text="["+text+"]";
- }
- editor_history_menu->get_popup()->add_icon_item(icon,text,i);
- }
-}
-
-void EditorNode::_property_editor_forward() {
-
- if (editor_history.next())
- _edit_current();
-
-}
-void EditorNode::_property_editor_back() {
-
- if (editor_history.previous())
- _edit_current();
-
-}
-
-
-void EditorNode::_imported(Node *p_node) {
-
-/*
- Node *scene = editor_data.get_edited_scene_root();
- add_edited_scene(p_node);
-
- if (scene) {
- String path = scene->get_filename();
- p_node->set_filename(path);
- memdelete(scene);
- }
-*/
-
-
-}
-
-
-void EditorNode::_hide_top_editors() {
-
- _display_top_editors(false);
-
- editor_plugins_over->clear();
-}
-
-void EditorNode::_display_top_editors(bool p_display) {
- editor_plugins_over->make_visible(p_display);
-}
-
-void EditorNode::_set_top_editors(Vector<EditorPlugin*> p_editor_plugins_over) {
- editor_plugins_over->set_plugins_list(p_editor_plugins_over);
-}
-
-void EditorNode::_set_editing_top_editors(Object* p_current_object) {
- editor_plugins_over->edit(p_current_object);
-}
-
-
-
-void EditorNode::_edit_current() {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
-
- property_back->set_disabled( editor_history.is_at_begining() );
- property_forward->set_disabled( editor_history.is_at_end() );
-
- this->current=current_obj;
- editor_path->update_path();
-
-
- if (!current_obj) {
-
- scene_tree_dock->set_selected(NULL);
- property_editor->edit( NULL );
- node_dock->set_node(NULL);
- object_menu->set_disabled(true);
-
- _display_top_editors(false);
-
- return;
- }
-
- object_menu->set_disabled(true);
-
- bool is_resource = current_obj->is_class("Resource");
- bool is_node = current_obj->is_class("Node");
- resource_save_button->set_disabled(!is_resource);
-
- if (is_resource) {
-
-
- Resource *current_res = current_obj->cast_to<Resource>();
- ERR_FAIL_COND(!current_res);
- scene_tree_dock->set_selected(NULL);
- property_editor->edit( current_res );
- node_dock->set_node(NULL);
- object_menu->set_disabled(false);
-
- //resources_dock->add_resource(Ref<Resource>(current_res));
-
-
- //top_pallete->set_current_tab(1);
- } else if (is_node) {
-
- Node * current_node = current_obj->cast_to<Node>();
- ERR_FAIL_COND(!current_node);
- ERR_FAIL_COND(!current_node->is_inside_tree());
-
-
-
-
- property_editor->edit( current_node );
- node_dock->set_node( current_node );
- scene_tree_dock->set_selected(current_node);
- object_menu->get_popup()->clear();
-
- //top_pallete->set_current_tab(0);
-
- } else {
-
- property_editor->edit( current_obj );
- node_dock->set_node(NULL);
- //scene_tree_dock->set_selected(current_node);
- //object_menu->get_popup()->clear();
-
- }
-
- /* Take care of PLUGIN EDITOR */
-
-
- EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
-
- if (main_plugin) {
-
- // special case if use of external editor is true
- if (main_plugin->get_name() == "Script" && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))){
- main_plugin->edit(current_obj);
- }
-
- else if (main_plugin!=editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) {
- // update screen main_plugin
-
- if (!changing_scene) {
- if (editor_plugin_screen)
- editor_plugin_screen->make_visible(false);
- editor_plugin_screen=main_plugin;
- editor_plugin_screen->edit(current_obj);
-
- editor_plugin_screen->make_visible(true);
-
-
- for(int i=0;i<editor_table.size();i++) {
-
- main_editor_buttons[i]->set_pressed(editor_table[i]==main_plugin);
- }
- }
-
- } else {
-
- editor_plugin_screen->edit(current_obj);
- }
-
- }
-
- Vector<EditorPlugin*> sub_plugins = editor_data.get_subeditors(current_obj);
-
- if (!sub_plugins.empty()) {
- _display_top_editors(false);
-
- _set_top_editors(sub_plugins);
- _set_editing_top_editors(current_obj);
- _display_top_editors(true);
-
- } else if (!editor_plugins_over->get_plugins_list().empty()) {
-
- _hide_top_editors();
-
- }
-/*
- if (!plugin || plugin->has_main_screen()) {
- // remove the OVER plugin if exists
- if (editor_plugin_over)
- editor_plugin_over->make_visible(false);
- editor_plugin_over=NULL;
- }
-*/
- /* Take care of OBJECT MENU */
-
- object_menu->set_disabled(false);
-
- PopupMenu *p=object_menu->get_popup();
-
- p->clear();
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_params",TTR("Copy Params")),OBJECT_COPY_PARAMS);
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_params",TTR("Paste Params")),OBJECT_PASTE_PARAMS);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("property_editor/paste_resource",TTR("Paste Resource")),RESOURCE_PASTE);
- if (is_resource) {
- p->add_shortcut(ED_SHORTCUT("property_editor/copy_resource",TTR("Copy Resource")),RESOURCE_COPY);
- p->add_shortcut(ED_SHORTCUT("property_editor/unref_resource",TTR("Make Built-In")),RESOURCE_UNREF);
- }
-
- if (is_resource || is_node) {
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("property_editor/make_subresources_unique",TTR("Make Sub-Resources Unique")),OBJECT_UNIQUE_RESOURCES);
- p->add_separator();
- p->add_icon_shortcut(gui_base->get_icon("Help","EditorIcons"),ED_SHORTCUT("property_editor/open_help",TTR("Open in Help")),OBJECT_REQUEST_HELP);
- }
-
- List<MethodInfo> methods;
- current_obj->get_method_list(&methods);
-
-
- if (!methods.empty()) {
-
- bool found=false;
- List<MethodInfo>::Element *I=methods.front();
- int i=0;
- while(I) {
-
- if (I->get().flags&METHOD_FLAG_EDITOR) {
- if (!found) {
- p->add_separator();
- found=true;
- }
- p->add_item(I->get().name.capitalize(),OBJECT_METHOD_BASE+i);
- }
- i++;
- I=I->next();
- }
- }
-
- //p->add_separator();
- //p->add_item("All Methods",OBJECT_CALL_METHOD);
-
-
- update_keying();
-}
-
-void EditorNode::_resource_created() {
-
- Object *c = create_dialog->instance_selected();
-
- ERR_FAIL_COND(!c);
- Resource *r = c->cast_to<Resource>();
- ERR_FAIL_COND(!r);
-
- REF res( r );
-
- push_item(c);
-
-}
-
-void EditorNode::_resource_selected(const RES& p_res,const String& p_property) {
-
-
- if (p_res.is_null())
- return;
-
- RES r=p_res;
- push_item(r.operator->(),p_property);
-
-}
-
-
-void EditorNode::_run(bool p_current,const String& p_custom) {
-
- if (editor_run.get_status()==EditorRun::STATUS_PLAY) {
-
- play_button->set_pressed(!_playing_edited);
- play_scene_button->set_pressed(_playing_edited);
- return;
- }
-
- play_button->set_pressed(false);
- 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"));
- play_custom_scene_button->set_pressed(false);
- play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
-
- String current_filename;
- String run_filename;
- String args;
-
-
- if (p_current || (editor_data.get_edited_scene_root() && p_custom==editor_data.get_edited_scene_root()->get_filename())) {
-
- Node *scene = editor_data.get_edited_scene_root();
-
- if (!scene) {
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("There is no defined scene to run."));
- accept->popup_centered_minsize();
- return;
- }
-
- if (scene->get_filename()=="") {
- current_option=-1;
- //accept->get_cancel()->hide();
- /**/
- _menu_option_confirm(FILE_SAVE_BEFORE_RUN, false);
- return;
-
- }
-
-
-
- if (run_settings_dialog->get_run_mode()==RunSettingsDialog::RUN_LOCAL_SCENE) {
-
- run_filename=scene->get_filename();
- } else {
- current_filename=scene->get_filename();
- }
-
- } else if (p_custom!="") {
-
- run_filename=p_custom;
- }
-
- if (run_filename=="") {
-
- //evidently, run the scene
- run_filename=GLOBAL_DEF("application/main_scene","");
- if (run_filename=="") {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- pick_main_scene->set_text(TTR("No main scene has ever been defined, select one?\nYou can change it later in later in \"Project Settings\" under the 'application' category."));
- pick_main_scene->popup_centered_minsize();
- return;
- }
-
- if (!FileAccess::exists(run_filename)) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- pick_main_scene->set_text(vformat(TTR("Selected scene '%s' does not exist, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), run_filename));
- pick_main_scene->popup_centered_minsize();
- return;
-
- }
-
- if (ResourceLoader::get_resource_type(run_filename)!="PackedScene") {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- pick_main_scene->set_text(vformat(TTR("Selected scene '%s' is not a scene file, select a valid one?\nYou can change it later in \"Project Settings\" under the 'application' category."), run_filename));
- pick_main_scene->popup_centered_minsize();
- return;
-
- }
-
- }
-
-
- if (bool(EDITOR_DEF("run/auto_save/save_before_running",true))) {
-
- if (unsaved_cache) {
-
- Node *scene = editor_data.get_edited_scene_root();
-
- if (scene) { //only autosave if there is a scene obviously
-
- if (scene->get_filename()=="") {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Current scene was never saved, please save it prior to running."));
- accept->popup_centered_minsize();
- return;
- }
-
- //_save_scene(scene->get_filename());
- _save_scene_with_preview(scene->get_filename());
- }
- }
- _menu_option(FILE_SAVE_ALL_SCENES);
- editor_data.save_editor_external_data();
- }
-
- if (bool(EDITOR_DEF("run/output/always_clear_output_on_play", true))) {
- log->clear();
- }
-
- if (bool(EDITOR_DEF("run/output/always_open_output_on_play", true))) {
- make_bottom_panel_item_visible(log);
- }
-
- List<String> breakpoints;
- editor_data.get_editor_breakpoints(&breakpoints);
-
- args = GlobalConfig::get_singleton()->get("editor/main_run_args");
-
- Error error = editor_run.run(run_filename,args,breakpoints,current_filename);
-
- if (error!=OK) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Could not start subprocess!"));
- accept->popup_centered_minsize();
- return;
-
- }
-
- emit_signal("play_pressed");
- if (p_current) {
- play_scene_button->set_pressed(true);
- play_scene_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
- } else if (p_custom!="") {
- run_custom_filename=run_filename;
- play_custom_scene_button->set_pressed(true);
- play_custom_scene_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
- } else {
- play_button->set_pressed(true);
- play_button->set_icon(gui_base->get_icon("Reload","EditorIcons"));
- }
-
- _playing_edited=p_current;
-
-}
-
-void EditorNode::_cleanup_scene() {
-
-#if 0
- Node *scene = editor_data.get_edited_scene_root();
- editor_selection->clear();
- editor_data.clear_editor_states();
- editor_history.clear();
- _hide_top_editors();
- animation_editor->cleanup();
- property_editor->edit(NULL);
- resources_dock->cleanup();
- scene_import_metadata.unref();
- //set_edited_scene(NULL);
- if (scene) {
- if (scene->get_filename()!="") {
- previous_scenes.push_back(scene->get_filename());
- }
-
- memdelete(scene);
- }
- editor_data.get_undo_redo().clear_history();
- saved_version=editor_data.get_undo_redo().get_version();
- run_settings_dialog->set_run_mode(0);
- run_settings_dialog->set_custom_arguments("-l $scene");
-
- List<Ref<Resource> > cached;
- ResourceCache::get_cached_resources(&cached);
-
- for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) {
-
- String path = E->get()->get_path();
- if (path.is_resource_file()) {
- ERR_PRINT(("Stray resource not cleaned:"+path).utf8().get_data());
- }
-
- }
-
- _update_title();
-#endif
-}
-
-void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
-
- //print_line("option "+itos(p_option)+" confirm "+itos(p_confirmed));
- if (!p_confirmed) //this may be a hack..
- current_option=(MenuOptions)p_option;
-
-
- switch( p_option ) {
- case FILE_NEW_SCENE: {
-
- // TODO: Drop such obsolete commented code
- /*
- if (!p_confirmed) {
- confirmation->get_ok()->set_text("Yes");
- //confirmation->get_cancel()->show();
- confirmation->set_text("Start a New Scene? (Current will be lost)");
- confirmation->popup_centered_minsize();
- break;
- }*/
-
-
- int idx = editor_data.add_edited_scene(-1);
- _scene_tab_changed(idx);
- editor_data.clear_editor_states();
-
- //_cleanup_scene();
-
-
- } break;
- case FILE_NEW_INHERITED_SCENE:
- case FILE_OPEN_SCENE: {
-
-
- //print_tree();
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- //not for now?
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
- file->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
-
- //file->set_current_path(current_path);
- Node *scene = editor_data.get_edited_scene_root();
- if (scene) {
- file->set_current_path(scene->get_filename());
- };
- file->set_title(p_option==FILE_OPEN_SCENE?TTR("Open Scene"):TTR("Open Base Scene"));
- file->popup_centered_ratio();
-
- } break;
- case FILE_QUICK_OPEN_SCENE: {
-
- quick_open->popup("PackedScene", true);
- quick_open->set_title(TTR("Quick Open Scene.."));
-
- } break;
- case FILE_QUICK_OPEN_SCRIPT: {
-
-
- quick_open->popup("Script", true);
- quick_open->set_title(TTR("Quick Open Script.."));
-
- } break;
- case FILE_RUN_SCRIPT: {
-
- file_script->popup_centered_ratio();
- } break;
- case FILE_OPEN_PREV: {
-
- if (previous_scenes.empty())
- break;
- opening_prev=true;
- open_request(previous_scenes.back()->get());
-
- } break;
- case FILE_CLOSE: {
-
- if (!p_confirmed && unsaved_cache) {
- confirmation->get_ok()->set_text(TTR("Yes"));
- //confirmation->get_cancel()->show();
- confirmation->set_text(TTR("Close scene? (Unsaved changes will be lost)"));
- confirmation->popup_centered_minsize();
- break;
- }
-
- _remove_edited_scene();
-
-
-
- } break;
- case SCENE_TAB_CLOSE: {
- _remove_scene(tab_closing);
- _update_scene_tabs();
- current_option = -1;
- } break;
- case FILE_SAVE_SCENE: {
-
-
- Node *scene = editor_data.get_edited_scene_root();
- if (scene && scene->get_filename()!="") {
-
- // save in background if in the script editor
- if (_get_current_main_editor() == EDITOR_SCRIPT) {
- _save_scene(scene->get_filename());
- } else {
- _save_scene_with_preview(scene->get_filename());
- }
- return;
- };
- // fallthrough to save_as
- };
- case FILE_SAVE_AS_SCENE: {
-
- Node *scene = editor_data.get_edited_scene_root();
-
- if (!scene) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text("This operation can't be done without a tree root.");
- 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());
- }
-
- //file->set_current_path(current_path);
- if (scene->get_filename()!="") {
- file->set_current_path(scene->get_filename());
- if (extensions.size()) {
- String ext=scene->get_filename().get_extension().to_lower();
- if (extensions.find(ext)==NULL) {
- file->set_current_path(scene->get_filename().replacen("."+ext,"."+extensions.front()->get()));
- }
- }
- } else {
-
- String existing;
- if (extensions.size()) {
- String root_name(get_edited_scene()->get_name());
- existing=root_name+"."+extensions.front()->get().to_lower();
- }
- file->set_current_path(existing);
-
- }
- file->popup_centered_ratio();
- file->set_title(TTR("Save Scene As.."));
-
- } break;
-
- case FILE_SAVE_ALL_SCENES: {
- for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
- Node *scene = editor_data.get_edited_scene_root(i);
- if (scene && scene->get_filename()!="") {
- // save in background if in the script editor
- if (i != editor_data.get_edited_scene() || _get_current_main_editor() == EDITOR_SCRIPT) {
- _save_scene(scene->get_filename(), i);
- } else {
- _save_scene_with_preview(scene->get_filename());
- }
- }// else: ignore new scenes
- }
- } break;
- case FILE_SAVE_BEFORE_RUN: {
- if (!p_confirmed) {
- accept->get_ok()->set_text(TTR("Yes"));
- accept->set_text(TTR("This scene has never been saved. Save before running?"));
- accept->popup_centered_minsize();
- break;
- }
-
- _menu_option(FILE_SAVE_AS_SCENE);
- _menu_option_confirm(FILE_SAVE_AND_RUN, true);
- } break;
-
- case FILE_SAVE_OPTIMIZED: {
-#if 0
- 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 tree root.");
- accept->popup_centered(Size2(300,70));
- break;
- }
-
-
-
- //file->set_current_path(current_path);
-
- String cpath;
- if (scene->get_filename()!="") {
- cpath = scene->get_filename();
-
- String fn = cpath.substr(0,cpath.length() - cpath.extension().size());
- String ext=cpath.extension();
- cpath=fn+".optimized.scn";
- optimized_save->set_optimized_scene(cpath);
- optimized_save->popup_centered(Size2(500,143));
- } else {
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("Please save the scene first.");
- accept->popup_centered(Size2(300,70));
- break;
-
- }
-#endif
- } break;
-
- case FILE_EXPORT_PROJECT: {
-
- //project_export_settings->popup_export();
- /*
- String target = export_db->get_current_platform();
- Ref<EditorExporter> exporter = export_db->get_exporter(target);
- if (exporter.is_null()) {
- accept->set_text("No exporter for platform '"+target+"' yet.");
- accept->popup_centered(Size2(300,70));
- return;
- }
-
- String extension = exporter->get_binary_extension();
- print_line("for target: "+target+" extension: "+extension);
- file_export_password->set_editable( exporter->requieres_password(file_export_check->is_pressed()));
-
- file_export->clear_filters();
- if (extension!="") {
- file_export->add_filter("*."+extension);
- }
- file_export->popup_centered_ratio();*/
- } break;
-
- case FILE_EXPORT_MESH_LIBRARY: {
-
- if (!editor_data.get_edited_scene_root()) {
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text("This operation can't be done without a scene.");
- accept->popup_centered_minsize();
- break;
- }
-
- List<String> extensions;
- Ref<MeshLibrary> ml( memnew( MeshLibrary) );
- ResourceSaver::get_recognized_extensions(ml,&extensions);
- file_export_lib->clear_filters();
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
- file_export_lib->add_filter("*."+E->get());
- }
-
- file_export_lib->popup_centered_ratio();
- file_export_lib->set_title(TTR("Export Mesh Library"));
-
- } break;
- case FILE_EXPORT_TILESET: {
-
- List<String> extensions;
- Ref<TileSet> ml( memnew( TileSet) );
- ResourceSaver::get_recognized_extensions(ml,&extensions);
- file_export_lib->clear_filters();
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
- file_export_lib->add_filter("*."+E->get());
- }
-
- file_export_lib->popup_centered_ratio();
- file_export_lib->set_title(TTR("Export Tile Set"));
-
- } break;
-
- case SETTINGS_EXPORT_PREFERENCES: {
-
- //project_export_settings->popup_centered_ratio();
- } break;
- case FILE_IMPORT_SUBSCENE: {
-
- //import_subscene->popup_centered_ratio();
-
- if (!editor_data.get_edited_scene_root()) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text("This operation can't be done without a selected node.");
- accept->popup_centered_minsize();
- break;
- }
-
- scene_tree_dock->import_subscene();
-
- } break;
-
- case FILE_QUIT: {
-
-
- if (!p_confirmed) {
-
- confirmation->get_ok()->set_text(TTR("Quit"));
- //confirmation->get_cancel()->show();
- confirmation->set_text(TTR("Exit the editor?"));
- confirmation->popup_centered(Size2(180,70)*EDSCALE);
- break;
- }
-
-
- _menu_option_confirm(RUN_STOP,true);
- exiting=true;
- get_tree()->quit();
-
- } break;
- case FILE_EXTERNAL_OPEN_SCENE: {
-
- if (unsaved_cache && !p_confirmed) {
-
- confirmation->get_ok()->set_text(TTR("Open"));
- //confirmation->get_cancel()->show();
- confirmation->set_text(TTR("Current scene not saved. Open anyway?"));
- confirmation->popup_centered_minsize();
- break;
-
- }
-
- bool oprev=opening_prev;
- Error err = load_scene(external_file);
- if (err == OK && oprev) {
- previous_scenes.pop_back();
- opening_prev=false;
- }
-
- } break;
-
- case EDIT_UNDO: {
-
-
-
- if (Input::get_singleton()->get_mouse_button_mask()&0x7) {
- print_line("no because state");
- break; // can't undo while mouse buttons are pressed
- }
-
- String action = editor_data.get_undo_redo().get_current_action_name();
- if (action!="")
- log->add_message("UNDO: "+action);
-
- editor_data.get_undo_redo().undo();
- } break;
- case EDIT_REDO: {
-
- if (Input::get_singleton()->get_mouse_button_mask()&0x7)
- break; // can't redo while mouse buttons are pressed
-
- editor_data.get_undo_redo().redo();
- String action = editor_data.get_undo_redo().get_current_action_name();
- if (action!="")
- log->add_message("REDO: "+action);
-
- } break;
- case TOOLS_ORPHAN_RESOURCES: {
-
- orphan_resources->show();
- } break;
-
- case EDIT_REVERT: {
-
- Node *scene = get_edited_scene();
-
- if (!scene)
- break;
-
- String filename = scene->get_filename();
-
- if (filename==String()) {
- show_warning(TTR("Can't reload a scene that was never saved."));
- break;
- }
-
- if (unsaved_cache && !p_confirmed) {
- confirmation->get_ok()->set_text(TTR("Revert"));
- confirmation->set_text(TTR("This action cannot be undone. Revert anyway?"));
- confirmation->popup_centered_minsize();
- break;
- }
-
-
- 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;
-
-#if 0
- case NODE_EXTERNAL_INSTANCE: {
-
-
- if (!edited_scene) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("This operation can't be done without a selected node.");
- accept->popup_centered(Size2(300,70));
- break;
- }
-
- Node *parent = scene_tree_editor->get_selected();
-
- if (!parent) {
-
- 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 selected node.");
- accept->popup_centered(Size2(300,70));
- break;
- }
-
- Node*instanced_scene=SceneLoader::load(external_file,true);
-
- if (!instanced_scene) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("Ugh");
- accept->set_text("Error loading scene from "+external_file);
- accept->popup_centered(Size2(300,70));
- return;
- }
-
- instanced_scene->generate_instance_state();
- instanced_scene->set_filename( GlobalConfig::get_singleton()->localize_path(external_file) );
-
- editor_data.get_undo_redo().create_action("Instance Scene");
- editor_data.get_undo_redo().add_do_method(parent,"add_child",instanced_scene);
- editor_data.get_undo_redo().add_do_method(instanced_scene,"set_owner",edited_scene);
- editor_data.get_undo_redo().add_do_reference(instanced_scene);
- editor_data.get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene);
- editor_data.get_undo_redo().commit_action();
-
- //parent->add_child(instanced_scene);
- //instanced_scene->set_owner(edited_scene);
- _last_instanced_scene=instanced_scene;
-
- } break;
-#endif
- case RESOURCE_NEW: {
-
- create_dialog->popup(true);
- } break;
- case RESOURCE_LOAD: {
-
- open_resource();
- } break;
- case RESOURCE_SAVE: {
-
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!current_obj->cast_to<Resource>())
-
- RES current_res = RES(current_obj->cast_to<Resource>());
-
- save_resource(current_res);
-
- } break;
- case RESOURCE_SAVE_AS: {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!current_obj->cast_to<Resource>())
-
- RES current_res = RES(current_obj->cast_to<Resource>());
-
- save_resource_as(current_res);
-
- } break;
- case RESOURCE_UNREF: {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!current_obj->cast_to<Resource>())
-
- RES current_res = RES(current_obj->cast_to<Resource>());
- current_res->set_path("");
- _edit_current();
- } break;
- case RESOURCE_COPY: {
-
- uint32_t current = editor_history.get_current();
- Object *current_obj = current>0 ? ObjectDB::get_instance(current) : NULL;
-
- ERR_FAIL_COND(!current_obj->cast_to<Resource>())
-
- RES current_res = RES(current_obj->cast_to<Resource>());
-
- EditorSettings::get_singleton()->set_resource_clipboard(current_res);
-
- } break;
- case RESOURCE_PASTE: {
-
- RES r = EditorSettings::get_singleton()->get_resource_clipboard();
- if (r.is_valid()) {
- push_item(EditorSettings::get_singleton()->get_resource_clipboard().ptr(),String());
- }
-
- } break;
- case OBJECT_REQUEST_HELP: {
-
- if (current) {
- _editor_select(EDITOR_SCRIPT);
- emit_signal("request_help",current->get_class());
- }
-
-
- } break;
- case OBJECT_COPY_PARAMS: {
-
- editor_data.apply_changes_in_editors();
- if (current)
- editor_data.copy_object_params(current);
- } break;
- case OBJECT_PASTE_PARAMS: {
-
- editor_data.apply_changes_in_editors();
- if (current)
- editor_data.paste_object_params(current);
- editor_data.get_undo_redo().clear_history();
- } break;
- case OBJECT_UNIQUE_RESOURCES: {
-
- editor_data.apply_changes_in_editors();
- if (current) {
- List<PropertyInfo> props;
- current->get_property_list(&props);
- Map<RES,RES> duplicates;
- for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
-
- if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
- continue;
-
- Variant v = current->get(E->get().name);
- if (v.is_ref()) {
- REF ref = v;
- if (ref.is_valid()) {
-
- RES res = ref;
- if (res.is_valid()) {
-
- if (!duplicates.has(res)) {
- duplicates[res]=res->duplicate();
- }
- res=duplicates[res];
-
- current->set(E->get().name,res);
- }
-
- }
- }
-
- }
- }
-
- editor_data.get_undo_redo().clear_history();
-
- _set_editing_top_editors(NULL);
- _set_editing_top_editors(current);
-
- } break;
- case RUN_PLAY: {
- _menu_option_confirm(RUN_STOP,true);
- _call_build();
- _run(false);
-
- } break;
- case RUN_PLAY_CUSTOM_SCENE: {
- if (run_custom_filename.empty() || editor_run.get_status()==EditorRun::STATUS_STOP) {
- _menu_option_confirm(RUN_STOP,true);
- quick_run->popup("PackedScene",true);
- quick_run->set_title(TTR("Quick Run Scene.."));
- play_custom_scene_button->set_pressed(false);
- } else {
- String last_custom_scene=run_custom_filename;
- _menu_option_confirm(RUN_STOP,true);
- _run(false,last_custom_scene);
- }
-
- } break;
- case RUN_STOP: {
-
- if (editor_run.get_status()==EditorRun::STATUS_STOP)
- break;
-
- editor_run.stop();
- run_custom_filename.clear();
- play_button->set_pressed(false);
- 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"));
- play_custom_scene_button->set_pressed(false);
- play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
- //pause_button->set_pressed(false);
- emit_signal("stop_pressed");
-
- } break;
- case RUN_PLAY_SCENE: {
- _menu_option_confirm(RUN_STOP,true);
- _call_build();
- _run(true);
-
- } break;
- case RUN_PLAY_NATIVE: {
-
- bool autosave = EDITOR_DEF("run/auto_save/save_before_running",true);
- if (autosave) {
- _menu_option_confirm(FILE_SAVE_ALL_SCENES, false);
- }
- if (run_native->is_deploy_debug_remote_enabled()){
- _menu_option_confirm(RUN_STOP,true);
- _call_build();
- emit_signal("play_pressed");
- editor_run.run_native_notify();
- }
- } break;
- case RUN_SCENE_SETTINGS: {
-
- run_settings_dialog->popup_run_settings();
- } break;
- case RUN_SETTINGS: {
-
- project_settings->popup_project_settings();
- } break;
- case RUN_PROJECT_MANAGER: {
-
- if (!p_confirmed) {
- confirmation->get_ok()->set_text(TTR("Yes"));
- confirmation->set_text(TTR("Open Project Manager? \n(Unsaved changes will be lost)"));
- confirmation->popup_centered_minsize();
- break;
- }
-
- _menu_option_confirm(RUN_STOP,true);
- exiting=true;
- get_tree()->quit();
- String exec = OS::get_singleton()->get_executable_path();
-
- List<String> args;
- args.push_back("-path");
- args.push_back(exec.get_base_dir());
- args.push_back("-pm");
-
- OS::ProcessID pid=0;
- Error err = OS::get_singleton()->execute(exec,args,false,&pid);
- ERR_FAIL_COND(err);
- } break;
- case RUN_FILE_SERVER: {
-
- //file_server
- bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER));
-
- if (ischecked) {
- file_server->stop();
- run_native->set_deploy_dumb(false);
- //debug_button->set_icon(gui_base->get_icon("FileServer","EditorIcons"));
- //debug_button->get_popup()->set_item_text( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER),"Enable File Server");
- } else {
- file_server->start();
- run_native->set_deploy_dumb(true);
- //debug_button->set_icon(gui_base->get_icon("FileServerActive","EditorIcons"));
- //debug_button->get_popup()->set_item_text( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER),"Disable File Server");
- }
-
- debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_FILE_SERVER),!ischecked);
-
- } break;
- case RUN_LIVE_DEBUG: {
-
- bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_LIVE_DEBUG));
-
- debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_LIVE_DEBUG),!ischecked);
- ScriptEditor::get_singleton()->get_debugger()->set_live_debugging(!ischecked);
- } break;
-
- /*case RUN_DEPLOY_DUMB_CLIENTS: {
-
- bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS));
- debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),!ischecked);
- run_native->set_deploy_dumb(!ischecked);
-
- } break;*/
- case RUN_DEPLOY_REMOTE_DEBUG: {
-
- bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG));
- debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEPLOY_REMOTE_DEBUG),!ischecked);
- run_native->set_deploy_debug_remote(!ischecked);
-
- } break;
- case RUN_DEBUG_COLLISONS: {
-
- bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_COLLISONS));
- debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_COLLISONS),!ischecked);
- run_native->set_debug_collisions(!ischecked);
- editor_run.set_debug_collisions(!ischecked);
- } break;
- case RUN_DEBUG_NAVIGATION: {
-
- bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION));
- debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION),!ischecked);
- run_native->set_debug_navigation(!ischecked);
- editor_run.set_debug_navigation(!ischecked);
- } break;
- case RUN_RELOAD_SCRIPTS: {
-
-
- bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS));
- debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_RELOAD_SCRIPTS),!ischecked);
-
- ScriptEditor::get_singleton()->set_live_auto_reload_running_scripts(!ischecked);
- } break;
- case SETTINGS_UPDATE_ALWAYS: {
-
- update_menu->get_popup()->set_item_checked(0,true);
- update_menu->get_popup()->set_item_checked(1,false);
- OS::get_singleton()->set_low_processor_usage_mode(false);
- } break;
- case SETTINGS_UPDATE_CHANGES: {
-
- update_menu->get_popup()->set_item_checked(0,false);
- update_menu->get_popup()->set_item_checked(1,true);
- OS::get_singleton()->set_low_processor_usage_mode(true);
- } break;
- case SETTINGS_UPDATE_SPINNER_HIDE: {
- update_menu->set_icon(gui_base->get_icon("Collapse","EditorIcons"));
- update_menu->get_popup()->toggle_item_checked(3);
- } break;
- case SETTINGS_PREFERENCES: {
-
- settings_config_dialog->popup_edit_settings();
- } break;
- case SETTINGS_OPTIMIZED_PRESETS: {
-
- //optimized_presets->popup_centered_ratio();
- } break;
- case SETTINGS_LOAD_EXPORT_TEMPLATES: {
-
-
- file_templates->popup_centered_ratio();
-
- } break;
- case SETTINGS_TOGGLE_FULLSCREN: {
-
- OS::get_singleton()->set_window_fullscreen( !OS::get_singleton()->is_window_fullscreen() );
-
-
- } break;
- case SETTINGS_PICK_MAIN_SCENE: {
-
-
- //print_tree();
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- //not for now?
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
- file->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
-
- //file->set_current_path(current_path);
- Node *scene = editor_data.get_edited_scene_root();
- if (scene) {
- file->set_current_path(scene->get_filename());
- };
- file->set_title(TTR("Pick a Main Scene"));
- file->popup_centered_ratio();
-
- } break;
- case SETTINGS_ABOUT: {
-
- about->popup_centered_minsize(Size2(500,130)*EDSCALE);
- } break;
- case SOURCES_REIMPORT: {
-
- //reimport_dialog->popup_reimport();
- } break;
- case DEPENDENCY_LOAD_CHANGED_IMAGES: {
-
-
-
- } break;
- case DEPENDENCY_UPDATE_IMPORTED: {
-
-/*
- bool editing_changed = _find_editing_changed_scene(get_edited_scene());
-
- import_reload_fn="";
-
- if (editing_changed) {
- if (unsaved_cache && !bool(EDITOR_DEF("import/ask_save_before_reimport",false))) {
- if (!p_confirmed) {
-
-
- confirmation->get_ok()->set_text("Open");
- //confirmation->get_cancel()->show();
- confirmation->set_text("Current scene changed, save and re-import ?");
- confirmation->popup_centered(Size2(300,70));
- break;
-
- }
- }
-
- Node *scene = get_edited_scene();
-
- if (scene->get_filename()=="") {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("Can't import if edited scene was not saved."); //i dont think this code will ever run
- accept->popup_centered(Size2(300,70));
- break;
-
- }
-
-
- import_reload_fn = scene->get_filename();
- _save_scene(import_reload_fn);
- _cleanup_scene();
-
-
- }
-
-*/
-
-
- } break;
-
- default: {
-
- if (p_option>=OBJECT_METHOD_BASE) {
-
- ERR_FAIL_COND(!current);
-
- int idx=p_option-OBJECT_METHOD_BASE;
-
- List<MethodInfo> methods;
- current->get_method_list(&methods);
-
- ERR_FAIL_INDEX( idx, methods.size() );
- String name=methods[idx].name;
-
- if (current)
- current->call(name);
- } else if (p_option>=IMPORT_PLUGIN_BASE) {
-
-
- }
- }
- }
-}
-
-
-Control* EditorNode::get_viewport() {
-
- return viewport;
-}
-
-
-
-void EditorNode::_editor_select(int p_which) {
-
- static bool selecting=false;
- if (selecting || changing_scene)
- return;
-
- selecting=true;
-
-
- ERR_FAIL_INDEX(p_which,editor_table.size());
-
- for(int i=0;i<main_editor_buttons.size();i++) {
- main_editor_buttons[i]->set_pressed(i==p_which);
- }
-
- selecting=false;
-
-
- EditorPlugin *new_editor = editor_table[p_which];
- ERR_FAIL_COND(!new_editor);
-
- if (editor_plugin_screen==new_editor)
- return;
-
- if (editor_plugin_screen) {
- editor_plugin_screen->make_visible(false);
- }
-
- editor_plugin_screen=new_editor;
- editor_plugin_screen->make_visible(true);
- editor_plugin_screen->selected_notify();
-
-
-}
-
-void EditorNode::add_editor_plugin(EditorPlugin *p_editor) {
-
-
- if (p_editor->has_main_screen()) {
-
- ToolButton *tb = memnew( ToolButton );
- tb->set_toggle_mode(true);
- tb->connect("pressed",singleton,"_editor_select",varray(singleton->main_editor_buttons.size()));
- tb->set_text(p_editor->get_name());
- singleton->main_editor_buttons.push_back(tb);
- singleton->main_editor_button_vb->add_child(tb);
- singleton->editor_table.push_back(p_editor);
-
- singleton->distraction_free->raise();
- }
- singleton->editor_data.add_editor_plugin( p_editor );
- singleton->add_child(p_editor);
-}
-
-
-void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) {
-
- if (p_editor->has_main_screen()) {
-
- for(int i=0;i<singleton->main_editor_buttons.size();i++) {
-
- if (p_editor->get_name()==singleton->main_editor_buttons[i]->get_text()) {
-
- if (singleton->main_editor_buttons[i]->is_pressed()) {
- singleton->_editor_select(EDITOR_SCRIPT);
- }
-
- memdelete( singleton->main_editor_buttons[i] );
- singleton->main_editor_buttons.remove(i);
-
- break;
- }
- }
-
- //singleton->main_editor_tabs->add_tab(p_editor->get_name());
- singleton->editor_table.erase(p_editor);
- }
- p_editor->make_visible(false);
- p_editor->clear();
- singleton->editor_plugins_over->get_plugins_list().erase(p_editor);
- singleton->remove_child(p_editor);
- singleton->editor_data.remove_editor_plugin( p_editor );
-
-}
-
-
-
-void EditorNode::_update_addon_config() {
-
- if (_initializing_addons)
- return;
-
- Vector<String> enabled_addons;
-
- for(Map<String,EditorPlugin*>::Element *E=plugin_addons.front();E;E=E->next()) {
- enabled_addons.push_back(E->key());
- }
-
- if (enabled_addons.size()==0) {
- GlobalConfig::get_singleton()->set("editor_plugins/enabled",Variant());
- } else {
- GlobalConfig::get_singleton()->set("editor_plugins/enabled",enabled_addons);
- }
-
- project_settings->queue_save();
-
-}
-
-void EditorNode::set_addon_plugin_enabled(const String& p_addon,bool p_enabled) {
-
- ERR_FAIL_COND(p_enabled && plugin_addons.has(p_addon));
- ERR_FAIL_COND(!p_enabled && !plugin_addons.has(p_addon));
-
- if (!p_enabled) {
-
- EditorPlugin *addon = plugin_addons[p_addon];
- remove_editor_plugin(addon);
- memdelete(addon); //bye
- plugin_addons.erase(p_addon);
- _update_addon_config();
- return;
- }
-
-
- Ref<ConfigFile> cf;
- cf.instance();
- String addon_path = "res://addons/"+p_addon+"/plugin.cfg";
- Error err = cf->load(addon_path);
- if (err!=OK) {
- show_warning("Unable to enable addon plugin at: '"+addon_path+"' parsing of config failed.");
- return;
- }
-
- if (!cf->has_section_key("plugin","script")) {
- show_warning("Unable to find script field for addon plugin at: 'res://addons/"+p_addon+"''.");
- return;
- }
-
- String path = cf->get_value("plugin","script");
- path="res://addons/"+p_addon+"/"+path;
-
- Ref<Script> script = ResourceLoader::load(path);
-
-
- if (script.is_null()) {
- show_warning("Unable to load addon script from path: '"+path+"'.");
- return;
- }
-
- //could check inheritance..
- if (String(script->get_instance_base_type())!="EditorPlugin") {
- show_warning("Unable to load addon script from path: '"+path+"' Base type is not EditorPlugin.");
- return;
- }
-
- if (!script->is_tool()) {
- show_warning("Unable to load addon script from path: '"+path+"' Script is does not support tool mode.");
- return;
- }
-
- EditorPlugin *ep = memnew( EditorPlugin );
- ep->set_script(script.get_ref_ptr());
- plugin_addons[p_addon]=ep;
- add_editor_plugin(ep);
-
- _update_addon_config();
-
-
-}
-
-bool EditorNode::is_addon_plugin_enabled(const String& p_addon) const {
-
- return plugin_addons.has(p_addon);
-}
-
-
-void EditorNode::_remove_edited_scene() {
- int new_index = editor_data.get_edited_scene();
- int old_index=new_index;
-
- if (new_index>0) {
- new_index=new_index-1;
- } else if (editor_data.get_edited_scene_count()>1) {
- new_index=1;
- } else {
- editor_data.add_edited_scene(-1);
- new_index=1;
- }
-
-
-
- if (editor_data.get_scene_path(old_index)!=String()) {
- ScriptEditor::get_singleton()->close_builtin_scripts_from_scene(editor_data.get_scene_path(old_index));
- }
- _scene_tab_changed(new_index);
- editor_data.remove_scene(old_index);
- editor_data.get_undo_redo().clear_history();
- _update_title();
- _update_scene_tabs();
-
- /*
- if (editor_data.get_edited_scene_count()==1) {
- //make new scene appear saved
- set_current_version(editor_data.get_undo_redo().get_version());
- unsaved_cache=false;
- }
- */
-}
-
-void EditorNode::_remove_scene(int index) {
- //printf("Attempting to remove scene %d (current is %d)\n", index, editor_data.get_edited_scene());
-
- if (editor_data.get_edited_scene() == index) {
- //Scene to remove is current scene
- _remove_edited_scene();
- }
- else {
- // Scene to remove is not active scene
- editor_data.remove_scene(index);
- }
-}
-
-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());
-
- }
- get_editor_data().set_edited_scene_root(p_scene);
-
- if (p_scene && p_scene->cast_to<Popup>())
- p_scene->cast_to<Popup>()->show(); //show popups
- scene_tree_dock->set_edited_scene(p_scene);
- if (get_tree())
- get_tree()->set_edited_scene_root(p_scene);
-
- if (p_scene) {
- if (p_scene->get_parent()!=scene_root)
- scene_root->add_child(p_scene);
-
- }
-}
-
-
-
-
-int EditorNode::_get_current_main_editor() {
-
- for(int i=0;i<editor_table.size();i++) {
- if (editor_table[i]==editor_plugin_screen)
- return i;
- }
-
- return 0;
-}
-
-Dictionary EditorNode::_get_main_scene_state() {
-
- Dictionary state;
- state["main_tab"]=_get_current_main_editor();
- state["scene_tree_offset"]=scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
- state["property_edit_offset"]=get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
- state["saved_version"]=saved_version;
- state["node_filter"]=scene_tree_dock->get_filter();
- //print_line(" getting main tab: "+itos(state["main_tab"]));
- return state;
-}
-
-void EditorNode::_set_main_scene_state(Dictionary p_state,Node* p_for_scene) {
-
- if (get_edited_scene()!=p_for_scene && p_for_scene!=NULL)
- return; //not for this scene
-
- //print_line("set current 7 ");
- changing_scene=false;
-
-#if 0
- if (p_state.has("main_tab")) {
- int idx = p_state["main_tab"];
-
-
- print_line("comes with tab: "+itos(idx));
- int current=-1;
- for(int i=0;i<editor_table.size();i++) {
- if (editor_plugin_screen==editor_table[i]) {
- current=i;
- break;
- }
- }
-
-
- if (idx<2 && current<2) {
- //only set tab for 2D and 3D
- _editor_select(idx);
- //print_line(" setting main tab: "+itos(p_state["main_tab"]));
- }
- }
-#else
-
- if (get_edited_scene()) {
-
- int current=-1;
- for(int i=0;i<editor_table.size();i++) {
- if (editor_plugin_screen==editor_table[i]) {
- current=i;
- break;
- }
- }
-
- if (current<2) {
- //use heuristic instead
-
- int n2d=0,n3d=0;
- _find_node_types(get_edited_scene(),n2d,n3d);
- if (n2d>n3d) {
- _editor_select(EDITOR_2D);
- } else if (n3d>n2d) {
- _editor_select(EDITOR_3D);
-
- }
- }
-
- }
-#endif
-
-
- if (p_state.has("scene_tree_offset"))
- scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_value(p_state["scene_tree_offset"]);
- if (p_state.has("property_edit_offset"))
- get_property_editor()->get_scene_tree()->get_vscroll_bar()->set_value(p_state["property_edit_offset"]);
-
- if (p_state.has("node_filter"))
- scene_tree_dock->set_filter(p_state["node_filter"]);
- //print_line("set current 8 ");
-
- //this should only happen at the very end
-
- //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;
-
-}
-
-void EditorNode::set_current_version(uint64_t p_version) {
-
- saved_version=p_version;
- editor_data.set_edited_scene_version(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());
-
- }
-
- //print_line("set current 2 ");
-
- editor_selection->clear();
- editor_data.set_edited_scene(p_idx);
-
- Node* new_scene = editor_data.get_edited_scene_root();
-
- if (new_scene && new_scene->cast_to<Popup>())
- new_scene->cast_to<Popup>()->show(); //show popups
-
- //print_line("set current 3 ");
-
- scene_tree_dock->set_edited_scene(new_scene);
- if (get_tree())
- get_tree()->set_edited_scene_root(new_scene);
-
- if (new_scene) {
- if (new_scene->get_parent()!=scene_root)
- scene_root->add_child(new_scene);
-
- }
- //print_line("set current 4 ");
-
-
- Dictionary state = editor_data.restore_edited_scene_state(editor_selection,&editor_history);
- _edit_current();
-
- /*if (!unsaved) {
- saved_version=editor_data.get_undo_redo().get_version();
- if (p_backwards)
- saved_version--;
- else
- saved_version++;
- print_line("was saved, updating version");
- } else {
- saved_version=state["saved_version"];
- }*/
- //_set_main_scene_state(state);
-
- call_deferred("_set_main_scene_state",state,get_edited_scene()); //do after everything else is done setting up
- //print_line("set current 6 ");
-
-
-}
-
-bool EditorNode::is_scene_open(const String& p_path) {
-
- for(int i=0;i<editor_data.get_edited_scene_count();i++) {
- if (editor_data.get_scene_path(i)==p_path)
- return true;
- }
-
- return false;
-}
-
-void EditorNode::fix_dependencies(const String& p_for_file) {
- dependency_fixer->edit(p_for_file);
-}
-
-
-
-
-Error EditorNode::load_scene(const String& p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_clear_errors, bool p_force_open_imported) {
-
- if (!is_inside_tree()) {
- defer_load_scene = p_scene;
- return OK;
- }
-
-
- 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 (!p_force_open_imported && FileAccess::exists(p_scene+".import")) {
- open_imported->set_text(vformat(TTR("Scene '%s' was automatically imported, so it can't be modified.\nTo make changes to it, a new inherited scene can be created."),p_scene.get_file()));
- open_imported->popup_centered_minsize();
- new_inherited_button->grab_focus();
- open_import_request=p_scene;
- return OK;
- }
-
- }
-
-
-
- if (p_clear_errors)
- load_errors->clear();
-
- String lpath = GlobalConfig::get_singleton()->localize_path(p_scene);
-
- if (!lpath.begins_with("res://")) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(TTR("Error loading scene, it must be inside the project path. Use 'Import' to open the scene, then save it inside the project path."));
- accept->popup_centered_minsize();
- opening_prev=false;
- return ERR_FILE_NOT_FOUND;
- }
-
- int prev = editor_data.get_edited_scene();
- int idx = editor_data.add_edited_scene(-1);
- //print_line("load scene callback");
- //set_current_scene(idx);
-
- if (!editor_data.get_edited_scene_root() && editor_data.get_edited_scene_count()==2) {
- _remove_edited_scene();
- } else {
- _scene_tab_changed(idx);
- }
-
-
-
- //_cleanup_scene(); // i'm sorry but this MUST happen to avoid modified resources to not be reloaded.
-
- dependency_errors.clear();
-
- Ref<PackedScene> sdata = ResourceLoader::load(lpath,"",true);
- if (!sdata.is_valid()) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(TTR("Error loading scene."));
- accept->popup_centered_minsize();
- opening_prev=false;
-
- if (prev!=-1) {
- set_current_scene(prev);
- editor_data.remove_scene(idx);
- }
- return ERR_FILE_NOT_FOUND;
- }
-
- if (!p_ignore_broken_deps && dependency_errors.has(lpath)) {
-
- current_option=-1;
- Vector<String> errors;
- for(Set<String>::Element *E=dependency_errors[lpath].front();E;E=E->next()) {
-
- errors.push_back(E->get());
- }
- dependency_error->show(lpath,errors);
- opening_prev=false;
-
- if (prev!=-1) {
- set_current_scene(prev);
- editor_data.remove_scene(idx);
- }
- return ERR_FILE_MISSING_DEPENDENCIES;
- }
-
- dependency_errors.erase(lpath); //at least not self path
-
- for (Map<String,Set<String> >::Element *E=dependency_errors.front();E;E=E->next()) {
-
- String txt=vformat(TTR("Scene '%s' has broken dependencies:"),E->key())+"\n";
- for(Set<String>::Element *F=E->get().front();F;F=F->next()) {
- txt+="\t"+F->get()+"\n";
- }
- add_io_error(txt);
- }
-
- 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(PackedScene::GEN_EDIT_STATE_MAIN);
-
- if (!new_scene) {
-
- sdata.unref();
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(TTR("Error loading scene."));
- accept->popup_centered_minsize();
- opening_prev=false;
- if (prev!=-1) {
- set_current_scene(prev);
- editor_data.remove_scene(idx);
- }
- return ERR_FILE_NOT_FOUND;
- }
-
- //guess not needed in the end?
- //new_scene->clear_internal_tree_resource_paths(); //make sure no internal tree paths to internal resources exist
-
- /*
- Node *old_scene = edited_scene;
- _hide_top_editors();
- set_edited_scene(NULL);
- editor_data.clear_editor_states();
- if (old_scene) {
- if (!opening_prev && old_scene->get_filename()!="") {
- previous_scenes.push_back(old_scene->get_filename());
- }
- memdelete(old_scene);
- }
-*/
-
- if (p_set_inherited) {
- Ref<SceneState> state = sdata->get_state();
- state->set_path(lpath);
- new_scene->set_scene_inherited_state(state);
- new_scene->set_filename(String());
- /*
- if (new_scene->get_scene_instance_state().is_valid())
- new_scene->get_scene_instance_state()->set_path(String());
- */
- }
-
- new_scene->set_scene_instance_state(Ref<SceneState>());
-
- set_edited_scene(new_scene);
- _get_scene_metadata(p_scene);
- /*
- editor_data.set_edited_scene_root(new_scene);
-
- scene_tree_dock->set_selected(new_scene, true);
- property_editor->edit(new_scene);
- editor_data.set_edited_scene_root(new_scene);
-*/
-
- //editor_data.get_undo_redo().clear_history();
- saved_version=editor_data.get_undo_redo().get_version();
- _update_title();
- _update_scene_tabs();
- _add_to_recent_scenes(lpath);
-
- prev_scene->set_disabled(previous_scenes.size()==0);
- opening_prev=false;
-
- ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
-
- //top_pallete->set_current_tab(0); //always go to scene
-
- push_item(new_scene);
-
- return OK;
-}
-
-
-
-void EditorNode::open_request(const String& p_path) {
-
- load_scene(p_path); // as it will be opened in separate tab
- //external_file=p_path;
- //_menu_option_confirm(FILE_EXTERNAL_OPEN_SCENE,false);
-}
-
-void EditorNode::request_instance_scene(const String &p_path) {
-
- scene_tree_dock->instance(p_path);
-
-}
-
-void EditorNode::request_instance_scenes(const Vector<String>& p_files) {
-
- scene_tree_dock->instance_scenes(p_files);
-}
-
-ImportDock *EditorNode::get_import_dock() {
- return import_dock;
-}
-
-FileSystemDock *EditorNode::get_filesystem_dock() {
-
- return filesystem_dock;
-}
-SceneTreeDock *EditorNode::get_scene_tree_dock() {
-
- return scene_tree_dock;
-}
-
-void EditorNode::_instance_request(const Vector<String>& p_files) {
-
- request_instance_scenes(p_files);
-}
-
-void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool 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) {
-
- Spatial *s=sp->cast_to<Spatial>();
- if (!s)
- return;
- AnimationPlayerEditor::singleton->get_key_editor()->insert_transform_key(s,p_sub,p_key);
-}
-
-void EditorNode::update_keying() {
-
- //print_line("KR: "+itos(p_enabled));
-
- bool valid=false;
-
- if (AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
-
- if (editor_history.get_path_size()>=1) {
-
- Object *obj = ObjectDB::get_instance(editor_history.get_path_object(0));
- if (obj && obj->cast_to<Node>()) {
-
- valid=true;
- }
- }
-
- }
-
- property_editor->set_keying(valid);
-
- AnimationPlayerEditor::singleton->get_key_editor()->update_keying();
-}
-
-
-void EditorNode::_close_messages() {
-
- //left_split->set_dragger_visible(false);
- old_split_ofs = center_split->get_split_offset();
- center_split->set_split_offset(0);
- //scene_root_parent->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_END,0);
-}
-
-void EditorNode::_show_messages() {
-
- //left_split->set_dragger_visible(true);
- center_split->set_split_offset(old_split_ofs);
- //scene_root_parent->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_END,log->get_margin(MARGIN_TOP));
-
-}
-
-#if 0
-void EditorNode::animation_panel_make_visible(bool p_visible) {
-
- if (!p_visible) {
- animation_panel->hide();
- } else {
- animation_panel->show();
- }
-
- int idx = settings_menu->get_popup()->get_item_index(SETTINGS_SHOW_ANIMATION);
- settings_menu->get_popup()->set_item_checked(idx,p_visible);
-}
-
-
-void EditorNode::animation_editor_make_visible(bool p_visible) {
-
- if (p_visible) {
-
- animation_editor->show();
- animation_vb->get_parent_control()->minimum_size_changed();
- //pd_anim->show();
- top_split->set_collapsed(false);
-
- //scene_root_parent->set_margin(MARGIN_TOP,animation_editor->get_margin(MARGIN_BOTTOM));
- } else {
- //pd_anim->hide();
- animation_editor->hide();
- //scene_root_parent->set_margin(MARGIN_TOP,0);
- if (!animation_vb->get_parent_control())
- return;
- animation_vb->get_parent_control()->minimum_size_changed();
- top_split->set_collapsed(true);
- }
-
- animation_editor->set_keying(p_visible);
-
-}
-#endif
-void EditorNode::_add_to_recent_scenes(const String& p_scene) {
-
- String base="_"+GlobalConfig::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
- Vector<String> rc = EDITOR_DEF(base+"/_recent_scenes",Array());
- String name = p_scene;
- name=name.replace("res://","");
- if (rc.find(name)!=-1)
- rc.erase(name);
- rc.insert(0,name);
- if (rc.size()>10)
- rc.resize(10);
-
- EditorSettings::get_singleton()->set(base+"/_recent_scenes",rc);
- EditorSettings::get_singleton()->save();
- _update_recent_scenes();
-
-}
-
-void EditorNode::_open_recent_scene(int p_idx) {
-
- String base="_"+GlobalConfig::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
- Vector<String> rc = EDITOR_DEF(base+"/_recent_scenes",Array());
-
- ERR_FAIL_INDEX(p_idx,rc.size());
-
- String path = "res://"+rc[p_idx];
-
-
- /*if (unsaved_cache) {
- _recent_scene=rc[p_idx];
- open_recent_confirmation->set_text("Discard current scene and open:\n'"+rc[p_idx]+"'");
- open_recent_confirmation->get_label()->set_align(Label::ALIGN_CENTER);
- open_recent_confirmation->popup_centered(Size2(400,100));
- return;
- }*/
-
- load_scene(path);
-
-
-}
-
-void EditorNode::_save_optimized() {
-
-
- //save_optimized_copy(optimized_save->get_optimized_scene(),optimized_save->get_preset());
-#if 0
- String path = optimized_save->get_optimized_scene();
-
- uint32_t flags=0;
-
- String platform="all";
- Ref<EditorOptimizedSaver> saver=editor_data.get_optimized_saver(optimized_save->get_preset());
-
- if (saver->is_bundle_scenes_enabled())
- flags|=SceneSaver::FLAG_BUNDLE_INSTANCED_SCENES;
- if (saver->is_bundle_resources_enabled())
- flags|=SceneSaver::FLAG_BUNDLE_RESOURCES;
- if (saver->is_remove_editor_data_enabled())
- flags|=SceneSaver::FLAG_OMIT_EDITOR_PROPERTIES;
- if (saver->is_big_endian_data_enabled())
- flags|=SceneSaver::FLAG_SAVE_BIG_ENDIAN;
-
- platform=saver->get_target_platform();
-
- Error err = SceneSaver::save(path,get_edited_scene(),flags,saver);
-
- if (err) {
-
- //accept->"()->hide();
- accept->get_ok()->set_text("I see..");
- accept->set_text("Error saving optimized scene: "+path);
- accept->popup_centered(Size2(300,70));
- return;
-
- }
-
- project_settings->add_remapped_path(GlobalConfig::get_singleton()->localize_path(get_edited_scene()->get_filename()),GlobalConfig::get_singleton()->localize_path(path),platform);
-#endif
-}
-
-void EditorNode::_update_recent_scenes() {
-
- String base="_"+GlobalConfig::get_singleton()->get_resource_path().replace("\\","::").replace("/","::");
- Vector<String> rc = EDITOR_DEF(base+"/_recent_scenes",Array());
- recent_scenes->clear();
- for(int i=0;i<rc.size();i++) {
-
- recent_scenes->add_item(rc[i],i);
- }
-
-}
-
-void EditorNode::_quick_opened() {
-
-
- 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() {
-
- _call_build();
- _run(false,quick_run->get_selected());
-}
-
-
-void EditorNode::notify_child_process_exited() {
-
- _menu_option_confirm(RUN_STOP,false);
- stop_button->set_pressed(false);
- editor_run.stop();
-
-}
-
-
-bool EditorNode::_find_editing_changed_scene(Node *p_from) {
-/*
- if (!p_from)
- return false;
-
- if (p_from->get_filename()!="") {
-
- StringName fn = p_from->get_filename();
- for(int i=0;i<import_monitor->get_changes().size();i++) {
-
- if (fn==import_monitor->get_changes()[i])
- return true;
- }
- }
-
- for(int i=0;i<p_from->get_child_count();i++) {
-
- if (_find_editing_changed_scene(p_from->get_child(i)))
- return true;
- }
-*/
- return false;
-}
-
-
-
-
-void EditorNode::add_io_error(const String& p_error) {
- //CharString err_ut = p_error.utf8();
- //ERR_PRINT(!err_ut.get_data());
- _load_error_notify(singleton,p_error);
-}
-
-void EditorNode::_load_error_notify(void* p_ud,const String& p_text) {
-
-
- EditorNode*en=(EditorNode*)p_ud;
- en->load_errors->add_image(en->gui_base->get_icon("Error","EditorIcons"));
- en->load_errors->add_text(p_text+"\n");
- en->load_error_dialog->popup_centered_ratio(0.5);
-
-}
-
-
-bool EditorNode::_find_scene_in_use(Node* p_node,const String& p_path) const {
-
- if (p_node->get_filename()==p_path) {
- return true;
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- if (_find_scene_in_use(p_node->get_child(i),p_path)) {
- return true;
- }
- }
-
- return false;
-}
-
-
-bool EditorNode::is_scene_in_use(const String& p_path) {
-
- Node *es = get_edited_scene();
- if (es)
- return _find_scene_in_use(es,p_path);
- return false;
-
-}
-
-void EditorNode::register_editor_types() {
-
- ClassDB::register_class<EditorPlugin>();
-// ClassDB::register_class<EditorImportPlugin>();
-// ClassDB::register_class<EditorExportPlugin>();
-// ClassDB::register_class<EditorScenePostImport>();
- ClassDB::register_class<EditorScript>();
- ClassDB::register_class<EditorSelection>();
- ClassDB::register_class<EditorFileDialog>();
- //ClassDB::register_type<EditorImportExport>();
- ClassDB::register_class<EditorSettings>();
- ClassDB::register_class<EditorSpatialGizmo>();
- ClassDB::register_class<EditorResourcePreview>();
- ClassDB::register_class<EditorResourcePreviewGenerator>();
- ClassDB::register_class<EditorFileSystem>();
- ClassDB::register_class<EditorFileSystemDirectory>();
-
-
-
- //ClassDB::register_type<EditorImporter>();
- //ClassDB::register_type<EditorPostImport>();
-}
-
-void EditorNode::unregister_editor_types() {
-
- _init_callbacks.clear();
-}
-
-
-void EditorNode::stop_child_process() {
-
- _menu_option_confirm(RUN_STOP,false);
-}
-
-
-
-
-
-void EditorNode::progress_add_task(const String& p_task,const String& p_label, int p_steps) {
-
- 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,bool p_force_redraw) {
-
- singleton->progress_dialog->task_step(p_task,p_state,p_step,p_force_redraw);
-
-}
-
-void EditorNode::progress_end_task(const String& p_task) {
-
- singleton->progress_dialog->end_task(p_task);
-
-}
-
-
-void EditorNode::progress_add_task_bg(const String& p_task,const String& p_label, int p_steps) {
-
- singleton->progress_hb->add_task(p_task,p_label,p_steps);
-}
-
-void EditorNode::progress_task_step_bg(const String& p_task, int p_step) {
-
- singleton->progress_hb->task_step(p_task,p_step);
-
-}
-
-void EditorNode::progress_end_task_bg(const String& p_task) {
-
- singleton->progress_hb->end_task(p_task);
-
-}
-
-
-
-Ref<Texture> EditorNode::_file_dialog_get_icon(const String& p_path) {
-
-
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem_path(p_path.get_base_dir());
- if (efsd) {
-
- String file = p_path.get_file();
- for(int i=0;i<efsd->get_file_count();i++) {
- if (efsd->get_file(i)==file) {
-
- String type = efsd->get_file_type(i);
-
- if (singleton->icon_type_cache.has(type)) {
- return singleton->icon_type_cache[type];
- } else {
- return singleton->icon_type_cache["Object"];
- }
-
- }
- }
- }
-
- return singleton->icon_type_cache["Object"];
-}
-
-void EditorNode::_file_dialog_register(FileDialog *p_dialog) {
-
- singleton->file_dialogs.insert(p_dialog);
-}
-
-void EditorNode::_file_dialog_unregister(FileDialog *p_dialog){
-
- singleton->file_dialogs.erase(p_dialog);
-}
-
-void EditorNode::_editor_file_dialog_register(EditorFileDialog *p_dialog) {
-
- singleton->editor_file_dialogs.insert(p_dialog);
-}
-
-void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog){
-
- singleton->editor_file_dialogs.erase(p_dialog);
-}
-
-Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
-
-Error EditorNode::export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after) {
-
- export_defer.platform=p_platform;
- export_defer.path=p_path;
- export_defer.debug=p_debug;
- export_defer.password=p_password;
-
- return OK;
-}
-
-void EditorNode::show_warning(const String& p_text, const String &p_title) {
-
- warning->set_text(p_text);
- warning->set_title(p_title);
- warning->popup_centered_minsize();
-}
-
-void EditorNode::_dock_select_input(const InputEvent& p_input) {
-
- if (p_input.type==InputEvent::MOUSE_BUTTON || p_input.type==InputEvent::MOUSE_MOTION) {
-
- Vector2 point(p_input.mouse_motion.x,p_input.mouse_motion.y);
-
- int nrect = -1;
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
- if (dock_select_rect[i].has_point(point)) {
- nrect=i;
- break;
- }
- }
-
-
- if (nrect!=dock_select_rect_over) {
- dock_select->update();
- dock_select_rect_over=nrect;
-
- }
-
-
- if (nrect==-1)
- return;
-
- if (p_input.type==InputEvent::MOUSE_BUTTON && p_input.mouse_button.button_index==1 && p_input.mouse_button.pressed && dock_popup_selected!=nrect) {
- Control *dock = dock_slot[dock_popup_selected]->get_current_tab_control();
- if (dock) {
- dock_slot[dock_popup_selected]->remove_child(dock);
- }
- if (dock_slot[dock_popup_selected]->get_tab_count()==0) {
- dock_slot[dock_popup_selected]->hide();
-
- } else {
-
- dock_slot[dock_popup_selected]->set_current_tab(0);
- }
-
- dock_slot[nrect]->add_child(dock);
- dock_popup_selected=nrect;
- dock_slot[nrect]->set_current_tab(dock_slot[nrect]->get_tab_count()-1);
- dock_slot[nrect]->show();
- dock_select->update();
-
- VSplitContainer*splits[DOCK_SLOT_MAX/2]={
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
- for(int i=0;i<4;i++) {
- bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count();
- if (in_use)
- splits[i]->show();
- else
- splits[i]->hide();
- }
-
- _save_docks();
- }
- }
-}
-
-void EditorNode::_dock_popup_exit() {
-
- dock_select_rect_over=-1;
- dock_select->update();
-}
-
-void EditorNode::_dock_pre_popup(int p_which) {
-
-
- dock_popup_selected=p_which;
-}
-
-void EditorNode::_dock_move_left() {
-
- if (dock_popup_selected<0 || dock_popup_selected>=DOCK_SLOT_MAX)
- return;
- Control *current = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab() );
- Control *prev = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab()-1 );
- if (!current || !prev)
- return;
- dock_slot[dock_popup_selected]->move_child(current,prev->get_index());
- dock_slot[dock_popup_selected]->set_current_tab( dock_slot[dock_popup_selected]->get_current_tab()-1 );
- dock_select->update();
- _save_docks();
-
-
-}
-
-void EditorNode::_dock_move_right() {
-
- Control *current = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab() );
- Control *next = dock_slot[dock_popup_selected]->get_tab_control( dock_slot[dock_popup_selected]->get_current_tab()+1 );
- if (!current || !next)
- return;
- dock_slot[dock_popup_selected]->move_child(next,current->get_index());
- dock_slot[dock_popup_selected]->set_current_tab( dock_slot[dock_popup_selected]->get_current_tab()+1 );
- dock_select->update();
- _save_docks();
-}
-
-void EditorNode::_dock_select_draw(){
- Size2 s = dock_select->get_size();
- s.y/=2.0;
- s.x/=6.0;
-
- Color used=Color(0.6,0.6,0.6,0.8);
- Color used_selected=Color(0.8,0.8,0.8,0.8);
- Color tab_selected=Color(1,1,1,1);
- Color unused=used;
- unused.a=0.4;
- Color unusable=unused;
- unusable.a=0.1;
-
- Rect2 unr(s.x*2,0,s.x*2,s.y*2);
- unr.pos+=Vector2(2,5);
- unr.size-=Vector2(4,7);
-
- dock_select->draw_rect(unr,unusable);
-
- dock_tab_move_left->set_disabled(true);
- dock_tab_move_right->set_disabled(true);
-
- if (dock_popup_selected!=-1 && dock_slot[dock_popup_selected]->get_tab_count()) {
-
- dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected]->get_current_tab()==0);
- dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected]->get_current_tab()>=dock_slot[dock_popup_selected]->get_tab_count()-1);
- }
-
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
-
- Vector2 ofs;
-
- switch(i) {
- case DOCK_SLOT_LEFT_UL: {
-
- } break;
- case DOCK_SLOT_LEFT_BL: {
- ofs.y+=s.y;
- } break;
- case DOCK_SLOT_LEFT_UR: {
- ofs.x+=s.x;
- } break;
- case DOCK_SLOT_LEFT_BR: {
- ofs+=s;
- } break;
- case DOCK_SLOT_RIGHT_UL: {
- ofs.x+=s.x*4;
- } break;
- case DOCK_SLOT_RIGHT_BL: {
- ofs.x+=s.x*4;
- ofs.y+=s.y;
-
- } break;
- case DOCK_SLOT_RIGHT_UR: {
- ofs.x+=s.x*4;
- ofs.x+=s.x;
-
- } break;
- case DOCK_SLOT_RIGHT_BR: {
- ofs.x+=s.x*4;
- ofs+=s;
-
- } break;
- }
-
- Rect2 r(ofs,s);
- dock_select_rect[i]=r;
- r.pos+=Vector2(2,5);
- r.size-=Vector2(4,7);
-
-
- if (i==dock_select_rect_over) {
- dock_select->draw_rect(r,used_selected);
- } else if (dock_slot[i]->get_child_count()==0) {
- dock_select->draw_rect(r,unused);
- } else {
-
- dock_select->draw_rect(r,used);
- }
-
- for(int j=0;j<MIN(3,dock_slot[i]->get_child_count());j++) {
- int xofs = (r.size.width/3)*j;
- Color c = used;
- if (i==dock_popup_selected && (dock_slot[i]->get_current_tab()>3 || dock_slot[i]->get_current_tab()==j))
- c=tab_selected;
- dock_select->draw_rect(Rect2(2+ofs.x+xofs,ofs.y,r.size.width/3-1,3),c);
- }
-
- }
-}
-
-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++) {
- String name = dock_slot[i]->get_tab_control(j)->get_name();
- if (names!="")
- names+=",";
- names+=name;
- }
-
- if (names!="") {
- p_layout->set_value(p_section,"dock_"+itos(i+1),names);
- }
- }
-
- p_layout->set_value(p_section,"dock_filesystem_split",filesystem_dock->get_split_offset());
-
- VSplitContainer*splits[DOCK_SLOT_MAX/2]={
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
- for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
-
- if (splits[i]->is_visible_in_tree()) {
- p_layout->set_value(p_section,"dock_split_"+itos(i+1),splits[i]->get_split_offset());
- }
- }
-
-
- HSplitContainer *h_splits[4]={
- left_l_hsplit,
- left_r_hsplit,
- main_hsplit,
- right_hsplit,
- };
-
- for(int i=0;i<4;i++) {
-
- p_layout->set_value(p_section,"dock_hsplit_"+itos(i+1),h_splits[i]->get_split_offset());
- }
-
-}
-
-void EditorNode::save_layout() {
-
- dock_drag_timer->start();
-}
-
-void EditorNode::_dock_split_dragged(int ofs) {
-
- dock_drag_timer->start();
-}
-
-void EditorNode::_load_docks() {
-
- Ref<ConfigFile> config;
- config.instance();
- Error err = config->load(EditorSettings::get_singleton()->get_project_settings_path().plus_file("editor_layout.cfg"));
- if (err!=OK) {
- //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::_update_dock_slots_visibility() {
-
- VSplitContainer*splits[DOCK_SLOT_MAX/2]={
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
-
- HSplitContainer*h_splits[4]={
- left_l_hsplit,
- left_r_hsplit,
- main_hsplit,
- right_hsplit,
- };
-
- if (!docks_visible) {
-
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
- dock_slot[i]->hide();
- }
-
- for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
- splits[i]->hide();
- }
-
- right_hsplit->hide();
- bottom_panel->hide();
- } else {
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
-
- if (dock_slot[i]->get_tab_count())
- dock_slot[i]->show();
- else
- dock_slot[i]->hide();
-
- }
-
-
- for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
- bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count();
- if (in_use)
- splits[i]->show();
- else
- splits[i]->hide();
- }
-
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
-
- if (dock_slot[i]->is_visible() && dock_slot[i]->get_tab_count()) {
- dock_slot[i]->set_current_tab(0);
- }
- }
- bottom_panel->show();
- right_hsplit->show();
- }
-}
-
-void EditorNode::_update_top_menu_visibility() {
-
- return; // I think removing top menu is too much
- /*
- if (distraction_free->is_pressed()) {
- play_cc->hide();
- menu_hb->hide();
- scene_tabs->hide();
- } else {
- play_cc->show();
- menu_hb->show();
- scene_tabs->show();
- }*/
-}
-
-void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String& p_section) {
-
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
-
- if (!p_layout->has_section_key(p_section,"dock_"+itos(i+1)))
- continue;
-
- Vector<String> names = String(p_layout->get_value(p_section,"dock_"+itos(i+1))).split(",");
-
- for(int j=0;j<names.size();j++) {
-
- String name=names[j];
- //find it, in a horribly inefficient way
- int atidx=-1;
- Control *node=NULL;
- for(int k=0;k<DOCK_SLOT_MAX;k++) {
- if (!dock_slot[k]->has_node(name))
- continue;
- node=dock_slot[k]->get_node(name)->cast_to<Control>();
- if (!node)
- continue;
- atidx=k;
- break;
- }
- if (atidx==-1) //well, it's not anywhere
- continue;
-
- if (atidx==i) {
- node->raise();
- continue;
- }
-
-
- dock_slot[atidx]->remove_child(node);
-
- if (dock_slot[atidx]->get_tab_count()==0) {
- dock_slot[atidx]->hide();
-
- }
- dock_slot[i]->add_child(node);
- dock_slot[i]->show();
- }
- }
-
- int fs_split_ofs = 0;
- if (p_layout->has_section_key(p_section,"dock_filesystem_split")) {
- fs_split_ofs = p_layout->get_value(p_section,"dock_filesystem_split");
- }
- filesystem_dock->set_split_offset(fs_split_ofs);
-
- VSplitContainer*splits[DOCK_SLOT_MAX/2]={
- left_l_vsplit,
- left_r_vsplit,
- right_l_vsplit,
- right_r_vsplit,
- };
-
- for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
-
- if (!p_layout->has_section_key(p_section,"dock_split_"+itos(i+1)))
- continue;
-
- int ofs = p_layout->get_value(p_section,"dock_split_"+itos(i+1));
- splits[i]->set_split_offset(ofs);
- }
-
- HSplitContainer*h_splits[4]={
- left_l_hsplit,
- left_r_hsplit,
- main_hsplit,
- right_hsplit,
- };
-
- for(int i=0;i<4;i++) {
- if (!p_layout->has_section_key(p_section,"dock_hsplit_"+itos(i+1)))
- continue;
- int ofs = p_layout->get_value(p_section,"dock_hsplit_"+itos(i+1));
- h_splits[i]->set_split_offset(ofs);
- }
-
- for(int i=0;i<DOCK_SLOT_MAX/2;i++) {
- bool in_use = dock_slot[i*2+0]->get_tab_count() || dock_slot[i*2+1]->get_tab_count();
- if (in_use)
- splits[i]->show();
- else
- splits[i]->hide();
- }
-
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
-
- if (dock_slot[i]->is_visible() && dock_slot[i]->get_tab_count()) {
- dock_slot[i]->set_current_tab(0);
- }
- }
-}
-
-
-void EditorNode::_update_layouts_menu() {
-
- editor_layouts->clear();
- overridden_default_layout=-1;
-
- editor_layouts->set_size(Vector2());
- editor_layouts->add_shortcut(ED_SHORTCUT("layout/save",TTR("Save Layout")), SETTINGS_LAYOUT_SAVE);
- editor_layouts->add_shortcut(ED_SHORTCUT("layout/delete",TTR("Delete Layout")), SETTINGS_LAYOUT_DELETE);
- editor_layouts->add_separator();
- editor_layouts->add_shortcut(ED_SHORTCUT("layout/default",TTR("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==TTR("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(TTR("Save Layout"));
- layout_dialog->get_ok()->set_text(TTR("Save"));
- layout_dialog->popup_centered();
- } break;
- case SETTINGS_LAYOUT_DELETE: {
-
- current_option=p_id;
- layout_dialog->set_title(TTR("Delete Layout"));
- layout_dialog->get_ok()->set_text(TTR("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();
- }
- }
-
-}
-
-
-void EditorNode::_scene_tab_script_edited(int p_tab) {
-
- Ref<Script> script = editor_data.get_scene_root_script(p_tab);
- if (script.is_valid())
- edit_resource(script);
-}
-
-void EditorNode::_scene_tab_closed(int p_tab) {
- current_option = SCENE_TAB_CLOSE;
- tab_closing = p_tab;
-
- bool unsaved = (p_tab==editor_data.get_edited_scene()) ?
- saved_version!=editor_data.get_undo_redo().get_version() :
- editor_data.get_scene_version(p_tab)!=0;
- if (unsaved) {
- confirmation->get_ok()->set_text(TTR("Yes"));
-
- //confirmation->get_cancel()->show();
- confirmation->set_text(TTR("Close scene? (Unsaved changes will be lost)"));
- confirmation->popup_centered_minsize();
- }
- else {
- _remove_scene(p_tab);
- _update_scene_tabs();
- }
-
-}
-
-
-void EditorNode::_scene_tab_changed(int p_tab) {
-
-
- //print_line("set current 1 ");
- bool unsaved = (saved_version!=editor_data.get_undo_redo().get_version());
- //print_line("version: "+itos(editor_data.get_undo_redo().get_version())+", saved "+itos(saved_version));
-
- if (p_tab==editor_data.get_edited_scene())
- return; //pointless
-
- uint64_t next_scene_version = editor_data.get_scene_version(p_tab);
-
-
-
- //print_line("scene tab changed???");
- editor_data.get_undo_redo().create_action(TTR("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,"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,"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();
-
-}
-
-void EditorNode::_toggle_search_bar(bool p_pressed) {
-
- property_editor->set_use_filter(p_pressed);
-
- if (p_pressed) {
-
- search_bar->show();
- search_box->grab_focus();
- search_box->select_all();
- } else {
-
- search_bar->hide();
- }
-}
-
-void EditorNode::_clear_search_box() {
-
- if (search_box->get_text()=="")
- return;
-
- search_box->clear();
- 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;
-
-}
-
-bool EditorNode::are_bottom_panels_hidden() const {
-
- for(int i=0;i<bottom_panel_items.size();i++) {
- if (bottom_panel_items[i].button->is_pressed())
- return false;
- }
-
- return true;
-}
-
-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::remove_bottom_panel_item(Control *p_item) {
-
- for(int i=0;i<bottom_panel_items.size();i++) {
-
- if (bottom_panel_items[i].control==p_item) {
- if (p_item->is_visible_in_tree()) {
- _bottom_panel_switch(false,0);
- }
- bottom_panel_vb->remove_child(bottom_panel_items[i].control);
- bottom_panel_hb->remove_child(bottom_panel_items[i].button);
- memdelete( bottom_panel_items[i].button );
- bottom_panel_items.remove(i);
- 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_visible(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_visible(false);
- }
- center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
- center_split->set_collapsed(true);
- }
-}
-
-void EditorNode::set_docks_visible(bool p_show) {
- docks_visible = p_show;
- _update_dock_slots_visibility();
-}
-
-bool EditorNode::get_docks_visible() const {
- return docks_visible;
-}
-
-void EditorNode::_toggle_distraction_free_mode() {
-
- set_distraction_free_mode( distraction_free->is_pressed() );
-}
-
-void EditorNode::set_distraction_free_mode(bool p_enter) {
-
- distraction_free->set_pressed(p_enter);
-
- if (p_enter) {
- if (docks_visible) {
- set_docks_visible(false);
- }
- } else {
- set_docks_visible(true);
- }
- _update_top_menu_visibility();
-}
-
-bool EditorNode::get_distraction_free_mode() const {
- return distraction_free->is_pressed();
-}
-
-void EditorNode::add_control_to_dock(DockSlot p_slot,Control* p_control) {
- ERR_FAIL_INDEX(p_slot,DOCK_SLOT_MAX);
- dock_slot[p_slot]->add_child(p_control);
- _update_dock_slots_visibility();
-
-}
-
-void EditorNode::remove_control_from_dock(Control* p_control) {
-
- Control *dock=NULL;
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
- if (p_control->get_parent()==dock_slot[i]) {
- dock=dock_slot[i];
- break;
- }
- }
-
- ERR_EXPLAIN("Control was not in dock");
- ERR_FAIL_COND(!dock);
-
- dock->remove_child(p_control);
- _update_dock_slots_visibility();
-}
-
-Variant EditorNode::drag_resource(const Ref<Resource>& p_res,Control* p_from) {
-
-
- Control *drag_control = memnew( Control );
- TextureRect *drag_preview = memnew( TextureRect );
- Label* label=memnew( Label );
-
- Ref<Texture> preview;
-
- {
- //todo make proper previews
- Ref<ImageTexture> pic = gui_base->get_icon("FileBig","EditorIcons");
- Image img = pic->get_data();
- img.resize(48,48); //meh
- Ref<ImageTexture> resized_pic = Ref<ImageTexture>( memnew( ImageTexture) );
- resized_pic->create_from_image(img);
- preview=resized_pic;
- }
-
- drag_preview->set_texture(preview);
- drag_control->add_child(drag_preview);
- if (p_res->get_path().is_resource_file()) {
- label->set_text(p_res->get_path().get_file());
- } else if (p_res->get_name()!="") {
- label->set_text(p_res->get_name());
- } else {
- label->set_text(p_res->get_class());
-
- }
-
- drag_control->add_child(label);
-
- p_from->set_drag_preview(drag_control); //wait until it enters scene
-
- label->set_pos( Point2((preview->get_width()-label->get_minimum_size().width)/2,preview->get_height()) );
-
- Dictionary drag_data;
- drag_data["type"]="resource";
- drag_data["resource"]=p_res;
- drag_data["from"]=p_from;
-
-
- return drag_data;
-
-}
-
-Variant EditorNode::drag_files(const Vector<String>& p_files, Control *p_from){
-
- VBoxContainer *files = memnew( VBoxContainer );
-
- int max_files=6;
-
- for(int i=0;i<MIN(max_files,p_files.size());i++) {
-
- Label* label=memnew( Label );
- label->set_text(p_files[i].get_file());
- files->add_child(label);
- }
-
- if (p_files.size()>max_files) {
-
- Label* label=memnew( Label );
- label->set_text(vformat(TTR("%d more file(s)"), p_files.size()-max_files));
- files->add_child(label);
-
- }
- Dictionary drag_data;
- drag_data["type"]="files";
- drag_data["files"]=p_files;
- drag_data["from"]=p_from;
-
- p_from->set_drag_preview(files); //wait until it enters scene
-
- return drag_data;
-
-}
-
-Variant EditorNode::drag_files_and_dirs(const Vector<String>& p_files, Control *p_from){
-
- VBoxContainer *files = memnew( VBoxContainer );
-
- int max_files=6;
-
- for(int i=0;i<MIN(max_files,p_files.size());i++) {
-
- Label* label=memnew( Label );
- label->set_text(p_files[i].get_file());
- files->add_child(label);
- }
-
- if (p_files.size()>max_files) {
-
- Label* label=memnew( Label );
- label->set_text(vformat(TTR("%d more file(s) or folder(s)"), p_files.size()-max_files));
- files->add_child(label);
-
- }
- Dictionary drag_data;
- drag_data["type"]="files_and_dirs";
- drag_data["files"]=p_files;
- drag_data["from"]=p_from;
-
- p_from->set_drag_preview(files); //wait until it enters scene
-
- return drag_data;
-
-}
-
-
-void EditorNode::_dropped_files(const Vector<String>& p_files,int p_screen) {
-
- String cur_path = filesystem_dock->get_current_path();
-// for(int i=0;i<EditorImportExport::get_singleton()->get_import_plugin_count();i++) {
-// EditorImportExport::get_singleton()->get_import_plugin(i)->import_from_drop(p_files,cur_path);
-// }
-}
-void EditorNode::_file_access_close_error_notify(const String& p_str) {
-
- add_io_error("Unable to write to file '"+p_str+"', file in use, locked or lacking permissions.");
-}
-
-
-void EditorNode::reload_scene(const String& p_path) {
-
-
- //first of all, reload textures as they might have changed on disk
-
- List<Ref<Resource> > cached;
- ResourceCache::get_cached_resources(&cached);
- List<Ref<Resource> > to_clear; //clear internal resources from previous scene from being used
- for(List<Ref<Resource> >::Element *E=cached.front();E;E=E->next()) {
-
- if (E->get()->get_path().begins_with(p_path+"::")) //subresources of existing scene
- to_clear.push_back(E->get());
-
- if (!E->get()->cast_to<Texture>())
- continue;
- if (!E->get()->get_path().is_resource_file() && !E->get()->get_path().is_abs_path())
- continue;
- if (!FileAccess::exists(E->get()->get_path()))
- continue;
- uint64_t mt = FileAccess::get_modified_time(E->get()->get_path());
- if (mt!=E->get()->get_last_modified_time()) {
- E->get()->reload_from_file();
- }
- }
-
- //so reload reloads everything, clear subresources of previous scene
- while(to_clear.front()) {
- to_clear.front()->get()->set_path("");
- to_clear.pop_front();
- }
-
- int scene_idx=-1;
- for(int i=0;i<editor_data.get_edited_scene_count();i++) {
-
- if (editor_data.get_scene_path(i)==p_path) {
- scene_idx=i;
- break;
- }
- }
-
- int current_tab = editor_data.get_edited_scene();
-
-
- if (scene_idx==-1) {
- if (get_edited_scene()) {
- //scene is not open, so at it might be instanced, just refresh, set tab to itself and it will reload
- set_current_scene(current_tab);
- editor_data.get_undo_redo().clear_history();
- }
- return;
- }
-
-
- if (current_tab==scene_idx) {
- editor_data.apply_changes_in_editors();
- _set_scene_metadata(p_path);
-
- }
- //remove scene
- _remove_scene(scene_idx);
- //reload scene
- load_scene(p_path);
- //adjust index so tab is back a the previous position
- editor_data.move_edited_scene_to_index(scene_idx);
- get_undo_redo()->clear_history();
- //recover the tab
- scene_tabs->set_current_tab(current_tab);
- _scene_tab_changed(current_tab);
-}
-
-int EditorNode::plugin_init_callback_count=0;
-
-void EditorNode::add_plugin_init_callback(EditorPluginInitializeCallback p_callback) {
-
- ERR_FAIL_COND(plugin_init_callback_count==MAX_INIT_CALLBACKS);
-
- plugin_init_callbacks[plugin_init_callback_count++]=p_callback;
-}
-
-EditorPluginInitializeCallback EditorNode::plugin_init_callbacks[EditorNode::MAX_INIT_CALLBACKS];
-
-
-int EditorNode::build_callback_count=0;
-
-void EditorNode::add_build_callback(EditorBuildCallback p_callback) {
-
- ERR_FAIL_COND(build_callback_count==MAX_INIT_CALLBACKS);
-
- build_callbacks[build_callback_count++]=p_callback;
-}
-
-EditorPluginInitializeCallback EditorNode::build_callbacks[EditorNode::MAX_BUILD_CALLBACKS];
-
-void EditorNode::_call_build() {
-
- for(int i=0;i<build_callback_count;i++) {
- build_callbacks[i]();
- }
-}
-
-
-void EditorNode::_inherit_imported(const String& p_action) {
-
- open_imported->hide();
- load_scene(open_import_request,true,true);
-
-}
-
-void EditorNode::_open_imported() {
-
- load_scene(open_import_request,true,false,true,true);
-}
-
-void EditorNode::_bind_methods() {
-
-
- ClassDB::bind_method("_menu_option",&EditorNode::_menu_option);
- ClassDB::bind_method("_menu_confirm_current",&EditorNode::_menu_confirm_current);
- ClassDB::bind_method("_dialog_action",&EditorNode::_dialog_action);
- ClassDB::bind_method("_resource_selected",&EditorNode::_resource_selected,DEFVAL(""));
- ClassDB::bind_method("_property_editor_forward",&EditorNode::_property_editor_forward);
- ClassDB::bind_method("_property_editor_back",&EditorNode::_property_editor_back);
- ClassDB::bind_method("_editor_select",&EditorNode::_editor_select);
- ClassDB::bind_method("_node_renamed",&EditorNode::_node_renamed);
- ClassDB::bind_method("edit_node",&EditorNode::edit_node);
- ClassDB::bind_method("_imported",&EditorNode::_imported);
- ClassDB::bind_method("_unhandled_input",&EditorNode::_unhandled_input);
-
- ClassDB::bind_method("_get_scene_metadata",&EditorNode::_get_scene_metadata);
- ClassDB::bind_method("set_edited_scene",&EditorNode::set_edited_scene);
- ClassDB::bind_method("open_request",&EditorNode::open_request);
- ClassDB::bind_method("_instance_request",&EditorNode::_instance_request);
- ClassDB::bind_method("update_keying",&EditorNode::update_keying);
- ClassDB::bind_method("_property_keyed",&EditorNode::_property_keyed);
- ClassDB::bind_method("_transform_keyed",&EditorNode::_transform_keyed);
- ClassDB::bind_method("_close_messages",&EditorNode::_close_messages);
- ClassDB::bind_method("_show_messages",&EditorNode::_show_messages);
- ClassDB::bind_method("_vp_resized",&EditorNode::_vp_resized);
- ClassDB::bind_method("_quick_opened",&EditorNode::_quick_opened);
- ClassDB::bind_method("_quick_run",&EditorNode::_quick_run);
-
- ClassDB::bind_method("_resource_created",&EditorNode::_resource_created);
-
- ClassDB::bind_method("_import_action",&EditorNode::_import_action);
- //ClassDB::bind_method("_import",&EditorNode::_import);
- //ClassDB::bind_method("_import_conflicts_solved",&EditorNode::_import_conflicts_solved);
- ClassDB::bind_method("_open_recent_scene",&EditorNode::_open_recent_scene);
- //ClassDB::bind_method("_open_recent_scene_confirm",&EditorNode::_open_recent_scene_confirm);
-
- ClassDB::bind_method("_save_optimized",&EditorNode::_save_optimized);
-
- ClassDB::bind_method("stop_child_process",&EditorNode::stop_child_process);
-
- ClassDB::bind_method("_sources_changed",&EditorNode::_sources_changed);
- ClassDB::bind_method("_fs_changed",&EditorNode::_fs_changed);
- ClassDB::bind_method("_dock_select_draw",&EditorNode::_dock_select_draw);
- ClassDB::bind_method("_dock_select_input",&EditorNode::_dock_select_input);
- ClassDB::bind_method("_dock_pre_popup",&EditorNode::_dock_pre_popup);
- ClassDB::bind_method("_dock_split_dragged",&EditorNode::_dock_split_dragged);
- ClassDB::bind_method("_save_docks",&EditorNode::_save_docks);
- ClassDB::bind_method("_dock_popup_exit",&EditorNode::_dock_popup_exit);
- ClassDB::bind_method("_dock_move_left",&EditorNode::_dock_move_left);
- ClassDB::bind_method("_dock_move_right",&EditorNode::_dock_move_right);
-
- ClassDB::bind_method("_layout_menu_option",&EditorNode::_layout_menu_option);
-
- ClassDB::bind_method("set_current_scene",&EditorNode::set_current_scene);
- ClassDB::bind_method("set_current_version",&EditorNode::set_current_version);
- ClassDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed);
- ClassDB::bind_method("_scene_tab_closed",&EditorNode::_scene_tab_closed);
- ClassDB::bind_method("_scene_tab_script_edited",&EditorNode::_scene_tab_script_edited);
- ClassDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
- ClassDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
-
- ClassDB::bind_method("_prepare_history",&EditorNode::_prepare_history);
- ClassDB::bind_method("_select_history",&EditorNode::_select_history);
-
- ClassDB::bind_method("_toggle_search_bar",&EditorNode::_toggle_search_bar);
- ClassDB::bind_method("_clear_search_box",&EditorNode::_clear_search_box);
- ClassDB::bind_method("_clear_undo_history",&EditorNode::_clear_undo_history);
- ClassDB::bind_method("_dropped_files",&EditorNode::_dropped_files);
- ClassDB::bind_method("_toggle_distraction_free_mode",&EditorNode::_toggle_distraction_free_mode);
-
-
-
-// ClassDB::bind_method(_MD("add_editor_import_plugin", "plugin"), &EditorNode::add_editor_import_plugin);
- //ClassDB::bind_method(_MD("remove_editor_import_plugin", "plugin"), &EditorNode::remove_editor_import_plugin);
- ClassDB::bind_method(_MD("get_gui_base"), &EditorNode::get_gui_base);
- ClassDB::bind_method(_MD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch);
-
- ClassDB::bind_method(_MD("_open_imported"), &EditorNode::_open_imported);
- ClassDB::bind_method(_MD("_inherit_imported"), &EditorNode::_inherit_imported);
-
- 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::POOL_STRING_ARRAY,"args")) );
- ADD_SIGNAL( MethodInfo("resource_saved",PropertyInfo(Variant::OBJECT,"obj")) );
-
-
-
-}
-
-static Node* _resource_get_edited_scene() {
-
- return EditorNode::get_singleton()->get_edited_scene();
-}
-
-EditorNode::EditorNode() {
-
- Resource::_get_local_scene_func=_resource_get_edited_scene;
-
- VisualServer::get_singleton()->textures_keep_original(true);
-
- EditorHelp::generate_doc(); //before any editor classes are crated
- SceneState::set_disable_placeholders(true);
- editor_initialize_certificates(); //for asset sharing
-
- InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
-
- if (id) {
-
- if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
- //only if no touchscreen ui hint, set emulation
- id->set_emulate_touch(false); //just disable just in case
- }
- id->set_custom_mouse_cursor(RES());
- }
-
-
- singleton=this;
- exiting=false;
- last_checked_version=0;
- changing_scene=false;
- _initializing_addons=false;
- docks_visible = true;
-
-
- FileAccess::set_backup_save(true);
-
- TranslationServer::get_singleton()->set_enabled(false);
- // load settings
- if (!EditorSettings::get_singleton())
- EditorSettings::create();
-
- bool use_single_dock_column = false;
- {
- int dpi_mode = EditorSettings::get_singleton()->get("interface/hidpi_mode");
- if (dpi_mode==0) {
- editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 );
-
- use_single_dock_column = OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x<1200;
-
- } else if (dpi_mode==1) {
- editor_set_scale(0.75);
- } else if (dpi_mode==2) {
- editor_set_scale(1.0);
- } else if (dpi_mode==3) {
- editor_set_scale(1.5);
- } else if (dpi_mode==4) {
- editor_set_scale(2.0);
- }
- }
-
-
- ResourceLoader::set_abort_on_missing_resources(false);
- FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
- EditorFileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
- EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EditorSettings::get_singleton()->get("filesystem/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);
-
- ResourceLoader::set_timestamp_on_load(true);
- ResourceSaver::set_timestamp_on_save(true);
-
-
- { //register importers at the begining, so dialogs are created with the right extensions
- Ref<ResourceImporterTexture> import_texture;
- import_texture.instance();
- ResourceFormatImporter::get_singleton()->add_importer(import_texture);
-
- Ref<ResourceImporterCSVTranslation> import_csv_translation;
- import_csv_translation.instance();
- ResourceFormatImporter::get_singleton()->add_importer(import_csv_translation);
-
- Ref<ResourceImporterWAV> import_wav;
- import_wav.instance();
- ResourceFormatImporter::get_singleton()->add_importer(import_wav);
-
-
- Ref<ResourceImporterOBJ> import_obj;
- import_obj.instance();
- ResourceFormatImporter::get_singleton()->add_importer(import_obj);
-
- Ref<ResourceImporterScene> import_scene;
- import_scene.instance();
- ResourceFormatImporter::get_singleton()->add_importer(import_scene);
-
- {
- Ref<EditorSceneImporterCollada> import_collada;
- import_collada.instance();
- import_scene->add_importer(import_collada);
- }
-
- }
-
- _pvrtc_register_compressors();
-
- editor_selection = memnew( EditorSelection );
-
- EditorFileSystem *efs = memnew( EditorFileSystem );
- add_child(efs);
-
- //used for previews
- FileDialog::get_icon_func=_file_dialog_get_icon;
- FileDialog::register_func=_file_dialog_register;
- FileDialog::unregister_func=_file_dialog_unregister;
-
- EditorFileDialog::get_icon_func=_file_dialog_get_icon;
- EditorFileDialog::register_func=_editor_file_dialog_register;
- EditorFileDialog::unregister_func=_editor_file_dialog_unregister;
-
-
- register_exporters();
-
- GLOBAL_DEF("editor/main_run_args","$scene");
-
- ClassDB::set_class_enabled("CollisionShape",true);
- ClassDB::set_class_enabled("CollisionShape2D",true);
- ClassDB::set_class_enabled("CollisionPolygon2D",true);
-
- Control *theme_base = memnew( Control );
- add_child(theme_base);
- theme_base->set_area_as_parent_rect();
-
- gui_base = memnew( Panel );
- theme_base->add_child(gui_base);
- gui_base->set_area_as_parent_rect();
-
- Ref<Theme> theme = create_editor_theme();
- theme_base->set_theme( theme );
- gui_base->set_theme(create_custom_theme());
-
- resource_preview = memnew( EditorResourcePreview );
- add_child(resource_preview);
- progress_dialog = memnew( ProgressDialog );
- gui_base->add_child(progress_dialog);
-
- // take up all screen
- gui_base->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
- gui_base->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END );
- gui_base->set_end( Point2(0,0) );
-
- main_vbox = memnew( VBoxContainer );
- gui_base->add_child(main_vbox);
- main_vbox->set_area_as_parent_rect(8);
-
-#if 0
- PanelContainer *top_dark_panel = memnew( PanelContainer );
- Ref<StyleBoxTexture> top_dark_sb;
- top_dark_sb.instance();
- top_dark_sb->set_texture(theme->get_icon("PanelTop","EditorIcons"));
- for(int i=0;i<4;i++) {
- top_dark_sb->set_margin_size(Margin(i),3);
- top_dark_sb->set_default_margin(Margin(i),0);
- }
- top_dark_sb->set_expand_margin_size(MARGIN_LEFT,20);
- top_dark_sb->set_expand_margin_size(MARGIN_RIGHT,20);
-
- top_dark_panel->add_style_override("panel",top_dark_sb);
- VBoxContainer *top_dark_vb = memnew( VBoxContainer );
- main_vbox->add_child(top_dark_panel);
- top_dark_panel->add_child(top_dark_vb);
-#endif
-
-
-
- menu_hb = memnew( HBoxContainer );
- main_vbox->add_child(menu_hb);
-
- //top_dark_vb->add_child(scene_tabs);
- //left
- left_l_hsplit = memnew( HSplitContainer );
- main_vbox->add_child(left_l_hsplit);
-
- left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
- left_l_vsplit = memnew( VSplitContainer );
- left_l_hsplit->add_child(left_l_vsplit);
- dock_slot[DOCK_SLOT_LEFT_UL]=memnew( TabContainer );
- left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]);
- dock_slot[DOCK_SLOT_LEFT_BL]=memnew( TabContainer );
- left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]);
- left_l_vsplit->hide();
- dock_slot[DOCK_SLOT_LEFT_UL]->hide();
- dock_slot[DOCK_SLOT_LEFT_BL]->hide();
-
- left_r_hsplit = memnew( HSplitContainer );
- left_l_hsplit->add_child(left_r_hsplit);
- left_r_vsplit = memnew( VSplitContainer );
- left_r_hsplit->add_child(left_r_vsplit);
- dock_slot[DOCK_SLOT_LEFT_UR]=memnew( TabContainer );
- left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UR]);
- dock_slot[DOCK_SLOT_LEFT_BR]=memnew( TabContainer );
- left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BR]);
- //left_r_vsplit->hide();
- //dock_slot[DOCK_SLOT_LEFT_UR]->hide();
- //dock_slot[DOCK_SLOT_LEFT_BR]->hide();
-
-
- main_hsplit = memnew( HSplitContainer );
- left_r_hsplit->add_child(main_hsplit);
- //main_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- VBoxContainer * center_vb = memnew( VBoxContainer);
- main_hsplit->add_child(center_vb);
- center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-
- center_split = memnew( VSplitContainer );
- //main_hsplit->add_child(center_split);
- center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- center_split->set_collapsed(false);
- center_vb->add_child(center_split);
-
- right_hsplit = memnew( HSplitContainer );
- main_hsplit->add_child(right_hsplit);
-
- right_l_vsplit = memnew( VSplitContainer );
- right_hsplit->add_child(right_l_vsplit);
- dock_slot[DOCK_SLOT_RIGHT_UL]=memnew( TabContainer );
- right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UL]);
- dock_slot[DOCK_SLOT_RIGHT_BL]=memnew( TabContainer );
- right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BL]);
- //right_l_vsplit->hide();
- //dock_slot[DOCK_SLOT_RIGHT_UL]->hide();
- //dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
-
- right_r_vsplit = memnew( VSplitContainer );
- right_hsplit->add_child(right_r_vsplit);
- dock_slot[DOCK_SLOT_RIGHT_UR]=memnew( TabContainer );
- right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]);
- dock_slot[DOCK_SLOT_RIGHT_BR]=memnew( TabContainer );
- right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]);
- right_r_vsplit->hide();
- dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
- dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
-
- left_l_vsplit->connect("dragged",this,"_dock_split_dragged");
- left_r_vsplit->connect("dragged",this,"_dock_split_dragged");
- right_l_vsplit->connect("dragged",this,"_dock_split_dragged");
- right_r_vsplit->connect("dragged",this,"_dock_split_dragged");
-
- left_l_hsplit->connect("dragged",this,"_dock_split_dragged");
- left_r_hsplit->connect("dragged",this,"_dock_split_dragged");
- main_hsplit->connect("dragged",this,"_dock_split_dragged");
- right_hsplit->connect("dragged",this,"_dock_split_dragged");
-
-
-
- dock_select_popoup = memnew( PopupPanel );
- gui_base->add_child(dock_select_popoup);
- VBoxContainer *dock_vb = memnew( VBoxContainer );
- dock_select_popoup->add_child(dock_vb);
-
- HBoxContainer *dock_hb = memnew( HBoxContainer);
- dock_tab_move_left = memnew( ToolButton );
- dock_tab_move_left->set_icon(theme->get_icon("Back","EditorIcons"));
- dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
- dock_tab_move_left->connect("pressed",this,"_dock_move_left");
- //dock_tab_move_left->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- dock_hb->add_child(dock_tab_move_left);
- dock_hb->add_spacer();
- dock_tab_move_right = memnew( ToolButton );
- dock_tab_move_right->set_icon(theme->get_icon("Forward","EditorIcons"));
- dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
- dock_tab_move_right->connect("pressed",this,"_dock_move_right");
-
- //dock_tab_move_right->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- dock_hb->add_child(dock_tab_move_right);
- dock_vb->add_child(dock_hb);
-
- dock_select = memnew( Control );
- dock_select->set_custom_minimum_size(Size2(128,64)*EDSCALE);
- dock_select->connect("gui_input",this,"_dock_select_input");
- dock_select->connect("draw",this,"_dock_select_draw");
- dock_select->connect("mouse_exited",this,"_dock_popup_exit");
- dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- dock_vb->add_child(dock_select);
-
-
-
- dock_select_popoup->set_as_minsize();
- dock_select_rect_over=-1;
- dock_popup_selected=-1;
- //dock_select_popoup->set_(Size2(20,20));
-
- for(int i=0;i<DOCK_SLOT_MAX;i++) {
- dock_slot[i]->set_custom_minimum_size(Size2(230,220)*EDSCALE);
- dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- dock_slot[i]->set_popup(dock_select_popoup);
- dock_slot[i]->connect("pre_popup_pressed",this,"_dock_pre_popup",varray(i));
-
- //dock_slot[i]->set_tab_align(TabContainer::ALIGN_LEFT);
- }
-
- dock_drag_timer = memnew( Timer );
- add_child(dock_drag_timer);
- dock_drag_timer->set_wait_time(0.5);
- dock_drag_timer->set_one_shot(true);
- dock_drag_timer->connect("timeout",this,"_save_docks");
-
- top_split = memnew( VSplitContainer );
- center_split->add_child(top_split);
- top_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- top_split->set_collapsed(true);
-
- VBoxContainer *srt = memnew( VBoxContainer );
- srt->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- top_split->add_child(srt);
- srt->add_constant_override("separation",0);
-
-
-/* main_editor_tabs = memnew( Tabs );
- main_editor_tabs->connect("tab_changed",this,"_editor_select");
- main_editor_tabs->set_tab_close_display_policy(Tabs::SHOW_NEVER);
-*/
- scene_tabs=memnew( Tabs );
- scene_tabs->add_tab("unsaved");
- scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
- scene_tabs->set_tab_close_display_policy( (bool(EDITOR_DEF("interface/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : 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");
-
- srt->add_child(scene_tabs);
-
- scene_root_parent = memnew( PanelContainer );
- scene_root_parent->set_custom_minimum_size(Size2(0,80)*EDSCALE);
-
-
-
- //Ref<StyleBox> sp = scene_root_parent->get_stylebox("panel","TabContainer");
- //scene_root_parent->add_style_override("panel",sp);
-
-
- /*scene_root_parent->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
- scene_root_parent->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_END );
- scene_root_parent->set_begin( Point2( 0, 0) );
- scene_root_parent->set_end( Point2( 0,80 ) );*/
- srt->add_child(scene_root_parent);
- scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
-
- scene_root = memnew( Viewport );
- scene_root->set_disable_3d(true);
-
-
-
- //scene_root_base->add_child(scene_root);
- //scene_root->set_meta("_editor_disable_input",true);
- VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(),true);
- scene_root->set_disable_input(true);
- scene_root->set_as_audio_listener_2d(true);
- //scene_root->set_size_override(true,Size2(GlobalConfig::get_singleton()->get("display/width"),GlobalConfig::get_singleton()->get("display/height")));
-
- //scene_root->set_world_2d( Ref<World2D>( memnew( World2D )) );
-
-
- viewport = memnew( VBoxContainer );
- viewport->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- /*for(int i=0;i<4;i++) {
- viewport->set_margin(Margin(i),sp->get_margin(Margin(i)));
- }*/
- scene_root_parent->add_child(viewport);
-
-
-
- PanelContainer *top_region = memnew( PanelContainer );
- top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
- HBoxContainer *left_menu_hb = memnew( HBoxContainer );
- top_region->add_child(left_menu_hb);
- menu_hb->add_child(top_region);
-
- PopupMenu *p;
-
-
-
- file_menu = memnew( MenuButton );
- file_menu->set_text(TTR("Scene"));
- //file_menu->set_icon(gui_base->get_icon("Save","EditorIcons"));
- left_menu_hb->add_child( file_menu );
-
- prev_scene = memnew( ToolButton );
- prev_scene->set_icon(gui_base->get_icon("PrevScene","EditorIcons"));
- prev_scene->set_tooltip(TTR("Go to previously opened scene."));
- prev_scene->set_disabled(true);
- //left_menu_hb->add_child( prev_scene );
- prev_scene->connect("pressed",this,"_menu_option",make_binds(FILE_OPEN_PREV));
- gui_base->add_child(prev_scene);
- prev_scene->set_pos(Point2(3,24));
- prev_scene->hide();
-
-
-
- ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD+KEY_TAB);
- ED_SHORTCUT("editor/prev_tab", TTR("Previous tab"), KEY_MASK_CMD+KEY_MASK_SHIFT+KEY_TAB);
- ED_SHORTCUT("editor/filter_files", TTR("Filter Files.."), KEY_MASK_ALT+KEY_MASK_CMD+KEY_P);
-
-
- file_menu->set_tooltip(TTR("Operations with scene files."));
- p=file_menu->get_popup();
- p->add_shortcut(ED_SHORTCUT("editor/new_scene",TTR("New Scene")),FILE_NEW_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene",TTR("New Inherited Scene..")),FILE_NEW_INHERITED_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/open_scene",TTR("Open Scene.."),KEY_MASK_CMD+KEY_O),FILE_OPEN_SCENE);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/save_scene",TTR("Save Scene"),KEY_MASK_CMD+KEY_S),FILE_SAVE_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/save_scene_as",TTR("Save Scene As.."),KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S),FILE_SAVE_AS_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes",TTR("Save all Scenes"),KEY_MASK_ALT+KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_S),FILE_SAVE_ALL_SCENES);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/close_scene",TTR("Close Scene"),KEY_MASK_SHIFT+KEY_MASK_CTRL+KEY_W),FILE_CLOSE);
- p->add_separator();
- //p->add_shortcut(ED_SHORTCUT("editor/save_scene",TTR("Close Goto Prev. Scene")),FILE_OPEN_PREV,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_P);
- p->add_submenu_item(TTR("Open Recent"),"RecentScenes",FILE_OPEN_RECENT);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene",TTR("Quick Open Scene.."),KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_O),FILE_QUICK_OPEN_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/quick_open_script",TTR("Quick Open Script.."),KEY_MASK_ALT+KEY_MASK_CMD+KEY_O),FILE_QUICK_OPEN_SCRIPT);
- p->add_separator();
-
- PopupMenu *pm_export = memnew(PopupMenu );
- pm_export->set_name("Export");
- p->add_child(pm_export);
- p->add_submenu_item(TTR("Convert To.."),"Export");
- pm_export->add_separator();
- pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_MeshLibrary", TTR("MeshLibrary..")), FILE_EXPORT_MESH_LIBRARY);
- pm_export->add_shortcut(ED_SHORTCUT("editor/convert_to_TileSet", TTR("TileSet..")), FILE_EXPORT_TILESET);
- pm_export->connect("id_pressed",this,"_menu_option");
-
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"),KEY_MASK_CMD+KEY_Z),EDIT_UNDO,true);
- p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"),KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_Z),EDIT_REDO,true);
- p->add_separator();
- p->add_item(TTR("Run Script"),FILE_RUN_SCRIPT,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_R);
- p->add_separator();
- p->add_item(TTR("Project Settings"),RUN_SETTINGS);
- p->add_separator();
- p->add_item(TTR("Revert Scene"),EDIT_REVERT);
- p->add_separator();
-#ifdef OSX_ENABLED
- p->add_item(TTR("Quit to Project List"),RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_ALT+KEY_Q);
-#else
- p->add_item(TTR("Quit to Project List"),RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_CTRL+KEY_Q);
-#endif
- p->add_item(TTR("Quit"),FILE_QUIT,KEY_MASK_CMD+KEY_Q);
-
- recent_scenes = memnew( PopupMenu );
- recent_scenes->set_name("RecentScenes");
- p->add_child(recent_scenes);
- recent_scenes->connect("id_pressed",this,"_open_recent_scene");
-
- {
- Control *sp = memnew( Control );
- sp->set_custom_minimum_size(Size2(30,0)*EDSCALE);
- menu_hb->add_child(sp);
- }
-
- PanelContainer *editor_region = memnew( PanelContainer );
- editor_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
- main_editor_button_vb = memnew( HBoxContainer );
- editor_region->add_child(main_editor_button_vb);
- menu_hb->add_child(editor_region);
-
- distraction_free = memnew( ToolButton );
- main_editor_button_vb->add_child(distraction_free);
- distraction_free->set_shortcut( ED_SHORTCUT("editor/distraction_free_mode",TTR("Distraction Free Mode"),KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F11) );
- distraction_free->connect("pressed",this,"_toggle_distraction_free_mode");
- distraction_free->set_icon(gui_base->get_icon("DistractionFree","EditorIcons"));
- distraction_free->set_toggle_mode(true);
-
- //menu_hb->add_spacer();
-#if 0
- node_menu = memnew( MenuButton );
- node_menu->set_text("Node");
- node_menu->set_pos( Point2( 50,0) );
- menu_panel->add_child( node_menu );
-
- p=node_menu->get_popup();
- p->add_item("Create",NODE_CREATE);
- p->add_item("Instance",NODE_INSTANCE);
- p->add_separator();
- p->add_item("Reparent",NODE_REPARENT);
- p->add_item("Move Up",NODE_MOVE_UP);
- p->add_item("Move Down",NODE_MOVE_DOWN);
- p->add_separator();
- p->add_item("Duplicate",NODE_DUPLICATE);
- p->add_separator();
- p->add_item("Remove (Branch)",NODE_REMOVE_BRANCH);
- p->add_item("Remove (Element)",NODE_REMOVE_ELEMENT);
- p->add_separator();
- p->add_item("Edit Subscriptions..",NODE_CONNECTIONS);
- p->add_item("Edit Groups..",NODE_GROUPS);
-
- resource_menu = memnew( MenuButton );
- resource_menu->set_text("Resource");
- resource_menu->set_pos( Point2( 90,0) );
- menu_panel->add_child( resource_menu );
-#endif
-
- import_menu = memnew( MenuButton );
- import_menu->set_tooltip(TTR("Import assets to the project."));
- import_menu->set_text(TTR("Import"));
- //import_menu->set_icon(gui_base->get_icon("Save","EditorIcons"));
- left_menu_hb->add_child( import_menu );
-
- p=import_menu->get_popup();
- p->connect("id_pressed",this,"_menu_option");
-
- tool_menu = memnew( MenuButton );
- tool_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools."));
- tool_menu->set_text(TTR("Tools"));
-
- //tool_menu->set_icon(gui_base->get_icon("Save","EditorIcons"));
- left_menu_hb->add_child( tool_menu );
-
- p=tool_menu->get_popup();
- p->connect("id_pressed",this,"_menu_option");
- p->add_item(TTR("Orphan Resource Explorer"),TOOLS_ORPHAN_RESOURCES);
-
- export_button = memnew( ToolButton );
- export_button->set_tooltip(TTR("Export the project to many platforms."));
- export_button->set_text(TTR("Export"));
- export_button->connect("pressed",this,"_menu_option",varray(FILE_EXPORT_PROJECT));
- export_button->set_focus_mode(Control::FOCUS_NONE);
- left_menu_hb->add_child(export_button);
-
- menu_hb->add_spacer();
-
- //Separator *s1 = memnew( VSeparator );
- //menu_panel->add_child(s1);
- //s1->set_pos(Point2(210,4));
- //s1->set_size(Point2(10,15));
-
-
- play_cc = memnew( CenterContainer );
- play_cc->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
- gui_base->add_child( play_cc );
- play_cc->set_area_as_parent_rect();
- play_cc->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,10);
- play_cc->set_margin(MARGIN_TOP,5);
-
- top_region = memnew( PanelContainer );
- top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
- play_cc->add_child(top_region);
-
- HBoxContainer *play_hb = memnew( HBoxContainer );
- top_region->add_child(play_hb);
-
- play_button = memnew( ToolButton );
- play_hb->add_child(play_button);
- play_button->set_toggle_mode(true);
- play_button->set_icon(gui_base->get_icon("MainPlay","EditorIcons"));
- play_button->set_focus_mode(Control::FOCUS_NONE);
- play_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY));
- play_button->set_tooltip(TTR("Play the project."));
- play_button->set_shortcut(ED_SHORTCUT("editor/play",TTR("Play"),KEY_F5));
-
-
-
- pause_button = memnew( ToolButton );
- //menu_panel->add_child(pause_button); - not needed for now?
- pause_button->set_toggle_mode(true);
- pause_button->set_icon(gui_base->get_icon("Pause","EditorIcons"));
- pause_button->set_focus_mode(Control::FOCUS_NONE);
- //pause_button->connect("pressed", this,"_menu_option",make_binds(RUN_PAUSE));
- pause_button->set_tooltip(TTR("Pause the scene"));
- pause_button->set_disabled(true);
- play_hb->add_child(pause_button);
- pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene",TTR("Pause Scene"),KEY_F7));
-
-
- stop_button = memnew( ToolButton );
- play_hb->add_child(stop_button);
- //stop_button->set_toggle_mode(true);
- stop_button->set_focus_mode(Control::FOCUS_NONE);
- stop_button->set_icon(gui_base->get_icon("MainStop","EditorIcons"));
- stop_button->connect("pressed", this,"_menu_option",make_binds(RUN_STOP));
- stop_button->set_tooltip(TTR("Stop the scene."));
- stop_button->set_shortcut(ED_SHORTCUT("editor/stop",TTR("Stop"),KEY_F8));
-
- run_native = memnew( EditorRunNative);
- play_hb->add_child(run_native);
- native_play_button = memnew( MenuButton );
- native_play_button->set_text("NTV");
- menu_hb->add_child(native_play_button);
- native_play_button->hide();
- native_play_button->get_popup()->connect("id_pressed",this,"_run_in_device");
- run_native->connect("native_run",this,"_menu_option",varray(RUN_PLAY_NATIVE));
-
- //VSeparator *s1 = memnew( VSeparator );
- //play_hb->add_child(s1);
-
- play_scene_button = memnew( ToolButton );
- play_hb->add_child(play_scene_button);
- play_scene_button->set_toggle_mode(true);
- play_scene_button->set_focus_mode(Control::FOCUS_NONE);
- play_scene_button->set_icon(gui_base->get_icon("PlayScene","EditorIcons"));
- play_scene_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY_SCENE));
- play_scene_button->set_tooltip(TTR("Play the edited scene."));
- play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene",TTR("Play Scene"),KEY_F6));
-
- play_custom_scene_button = memnew( ToolButton );
- play_hb->add_child(play_custom_scene_button);
- play_custom_scene_button->set_toggle_mode(true);
- play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE);
- play_custom_scene_button->set_icon(gui_base->get_icon("PlayCustom","EditorIcons"));
- play_custom_scene_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY_CUSTOM_SCENE));
- play_custom_scene_button->set_tooltip(TTR("Play custom scene"));
- play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene",TTR("Play Custom Scene"),KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F5));
-
- debug_button = memnew( MenuButton );
- debug_button->set_flat(true);
- play_hb->add_child(debug_button);
- //debug_button->set_toggle_mode(true);
- debug_button->set_focus_mode(Control::FOCUS_NONE);
- debug_button->set_icon(gui_base->get_icon("Remote","EditorIcons"));
- //debug_button->connect("pressed", this,"_menu_option",make_binds(RUN_LIVE_DEBUG));
- debug_button->set_tooltip(TTR("Debug options"));
-
- p=debug_button->get_popup();
- p->set_hide_on_item_selection(false);
- p->add_check_item(TTR("Deploy with Remote Debug"),RUN_DEPLOY_REMOTE_DEBUG);
- p->set_item_tooltip(p->get_item_count()-1,TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged."));
- p->add_check_item(TTR("Small Deploy with Network FS"),RUN_FILE_SERVER);
- p->set_item_tooltip(p->get_item_count()-1,TTR("When this option is enabled, export or deploy will produce a minimal executable.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploy will use the USB cable for faster performance. This option speeds up testing for games with a large footprint."));
- p->add_separator();
- p->add_check_item(TTR("Visible Collision Shapes"),RUN_DEBUG_COLLISONS);
- p->set_item_tooltip(p->get_item_count()-1,TTR("Collision shapes and raycast nodes (for 2D and 3D) will be visible on the running game if this option is turned on."));
- p->add_check_item(TTR("Visible Navigation"),RUN_DEBUG_NAVIGATION);
- p->set_item_tooltip(p->get_item_count()-1,TTR("Navigation meshes and polygons will be visible on the running game if this option is turned on."));
- p->add_separator();
- p->add_check_item(TTR("Sync Scene Changes"),RUN_LIVE_DEBUG);
- p->set_item_tooltip(p->get_item_count()-1,TTR("When this option is turned on, any changes made to the scene in the editor will be replicated in the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
- p->add_check_item(TTR("Sync Script Changes"),RUN_RELOAD_SCRIPTS);
- p->set_item_tooltip(p->get_item_count()-1,TTR("When this option is turned on, any script that is saved will be reloaded on the running game.\nWhen used remotely on a device, this is more efficient with network filesystem."));
- p->connect("id_pressed",this,"_menu_option");
-
- /*
- run_settings_button = memnew( ToolButton );
- //menu_hb->add_child(run_settings_button);
- //run_settings_button->set_toggle_mode(true);
- run_settings_button->set_focus_mode(Control::FOCUS_NONE);
- run_settings_button->set_icon(gui_base->get_icon("Run","EditorIcons"));
- run_settings_button->connect("pressed", this,"_menu_option",make_binds(RUN_SCENE_SETTINGS));
-*/
-
- /*
- run_settings_button = memnew( ToolButton );
- menu_panel->add_child(run_settings_button);
- run_settings_button->set_pos(Point2(305,0));
- run_settings_button->set_focus_mode(Control::FOCUS_NONE);
- run_settings_button->set_icon(gui_base->get_icon("Run","EditorIcons"));
- run_settings_button->connect("pressed", this,"_menu_option",make_binds(RUN_SETTINGS));
-*/
-
-
- progress_hb = memnew( BackgroundProgress );
- menu_hb->add_child(progress_hb);
-
- {
- Control *sp = memnew( Control );
- sp->set_custom_minimum_size(Size2(30,0)*EDSCALE);
- menu_hb->add_child(sp);
- }
-
-
- PanelContainer *vu_cont = memnew( PanelContainer );
- vu_cont->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
- menu_hb->add_child(vu_cont);
-
- audio_vu = memnew( TextureProgress );
- CenterContainer *vu_cc = memnew( CenterContainer );
- vu_cc->add_child(audio_vu);
- vu_cont->add_child(vu_cc);
- audio_vu->set_under_texture(gui_base->get_icon("VuEmpty","EditorIcons"));
- audio_vu->set_progress_texture(gui_base->get_icon("VuFull","EditorIcons"));
- audio_vu->set_max(24);
- audio_vu->set_min(-80);
- audio_vu->set_step(0.01);
- audio_vu->set_value(0);
-
- {
- Control *sp = memnew( Control );
- sp->set_custom_minimum_size(Size2(30,0)*EDSCALE);
- menu_hb->add_child(sp);
- }
-
-
-
- top_region = memnew( PanelContainer );
- top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
- HBoxContainer *right_menu_hb = memnew( HBoxContainer );
- top_region->add_child(right_menu_hb);
- menu_hb->add_child(top_region);
-
-
- settings_menu = memnew( MenuButton );
- settings_menu->set_text(TTR("Settings"));
- //settings_menu->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- right_menu_hb->add_child( settings_menu );
- p=settings_menu->get_popup();
-
- //p->add_item("Export Settings",SETTINGS_EXPORT_PREFERENCES);
- p->add_item(TTR("Editor Settings"),SETTINGS_PREFERENCES);
- //p->add_item("Optimization Presets",SETTINGS_OPTIMIZED_PRESETS);
- p->add_separator();
- editor_layouts = memnew( PopupMenu );
- editor_layouts->set_name("Layouts");
- p->add_child(editor_layouts);
- editor_layouts->connect("id_pressed",this,"_layout_menu_option");
- p->add_submenu_item(TTR("Editor Layout"), "Layouts");
-
- p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode",TTR("Toggle Fullscreen"),KEY_MASK_SHIFT|KEY_F11),SETTINGS_TOGGLE_FULLSCREN);
-
- p->add_separator();
- p->add_item(TTR("Install Export Templates"),SETTINGS_LOAD_EXPORT_TEMPLATES);
- p->add_separator();
- p->add_item(TTR("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)*EDSCALE);
- layout_dialog->connect("name_confirmed", this,"_dialog_action");
-
- sources_button = memnew( ToolButton );
- right_menu_hb->add_child(sources_button);
- sources_button->set_icon(gui_base->get_icon("DependencyOk","EditorIcons"));
- sources_button->connect("pressed",this,"_menu_option",varray(SOURCES_REIMPORT));
- sources_button->set_tooltip(TTR("Alerts when an external resource has changed."));
-
- update_menu = memnew( MenuButton );
- update_menu->set_tooltip(TTR("Spins when the editor window repaints!"));
- right_menu_hb->add_child(update_menu);
- update_menu->set_icon(gui_base->get_icon("Progress1","EditorIcons"));
- p=update_menu->get_popup();
- p->add_check_item(TTR("Update Always"),SETTINGS_UPDATE_ALWAYS);
- p->add_check_item(TTR("Update Changes"),SETTINGS_UPDATE_CHANGES);
- p->add_separator();
- p->add_check_item(TTR("Disable Update Spinner"),SETTINGS_UPDATE_SPINNER_HIDE);
- p->set_item_checked(1,true);
-
- //sources_button->connect();
-
-/*
- Separator *s2 = memnew( VSeparator );
- menu_panel->add_child(s2);
- s2->set_pos(Point2(338,4));
- s2->set_size(Point2(10,15));
-*/
-
-
-
- //editor_hsplit = memnew( HSplitContainer );
- //main_split->add_child(editor_hsplit);
- //editor_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
- //editor_vsplit = memnew( VSplitContainer );
- //editor_hsplit->add_child(editor_vsplit);
-
- //top_pallete = memnew( TabContainer );
- scene_tree_dock = memnew( SceneTreeDock(this,scene_root,editor_selection,editor_data) );
- scene_tree_dock->set_name(TTR("Scene"));
- //top_pallete->add_child(scene_tree_dock);
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(scene_tree_dock);
-#if 0
- resources_dock = memnew( ResourcesDock(this) );
- resources_dock->set_name("Resources");
- //top_pallete->add_child(resources_dock);
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(resources_dock);
- //top_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-#endif
- dock_slot[DOCK_SLOT_LEFT_BR]->hide();
- /*Control *editor_spacer = memnew( Control );
- editor_spacer->set_custom_minimum_size(Size2(260,200));
- editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- editor_vsplit->add_child( editor_spacer );
- editor_spacer->add_child( top_pallete );
- top_pallete->set_area_as_parent_rect();*/
-
-
- //prop_pallete = memnew( TabContainer );
-
- //prop_pallete->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
- /*editor_spacer = memnew( Control );
- editor_spacer->set_custom_minimum_size(Size2(260,200));
- editor_spacer->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- editor_vsplit->add_child( editor_spacer );
- editor_spacer->add_child( prop_pallete );
- prop_pallete->set_area_as_parent_rect();*/
-
- VBoxContainer *prop_editor_base = memnew( VBoxContainer );
- prop_editor_base->set_name(TTR("Inspector")); // Properties?
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(prop_editor_base);
-
- HBoxContainer *prop_editor_hb = memnew( HBoxContainer );
-
- prop_editor_base->add_child(prop_editor_hb);
- prop_editor_vb=prop_editor_base;
-
- resource_new_button = memnew( ToolButton );
- resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it."));
- resource_new_button->set_icon(gui_base->get_icon("New","EditorIcons"));
- prop_editor_hb->add_child(resource_new_button);
- resource_new_button->connect("pressed",this,"_menu_option",varray(RESOURCE_NEW));
- resource_new_button->set_focus_mode(Control::FOCUS_NONE);
-
- resource_load_button = memnew( ToolButton );
- resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it."));
- resource_load_button->set_icon(gui_base->get_icon("Load","EditorIcons"));
- prop_editor_hb->add_child(resource_load_button);
- resource_load_button->connect("pressed",this,"_menu_option",varray(RESOURCE_LOAD));
- resource_load_button->set_focus_mode(Control::FOCUS_NONE);
-
- resource_save_button = memnew( MenuButton );
- resource_save_button->set_tooltip(TTR("Save the currently edited resource."));
- resource_save_button->set_icon(gui_base->get_icon("Save","EditorIcons"));
- prop_editor_hb->add_child(resource_save_button);
- resource_save_button->get_popup()->add_item(TTR("Save"),RESOURCE_SAVE);
- resource_save_button->get_popup()->add_item(TTR("Save As.."),RESOURCE_SAVE_AS);
- resource_save_button->get_popup()->connect("id_pressed",this,"_menu_option");
- resource_save_button->set_focus_mode(Control::FOCUS_NONE);
- resource_save_button->set_disabled(true);
-
- prop_editor_hb->add_spacer();
-
- property_back = memnew( ToolButton );
- property_back->set_icon( gui_base->get_icon("Back","EditorIcons") );
- property_back->set_flat(true);
- property_back->set_tooltip(TTR("Go to the previous edited object in history."));
- property_back->set_disabled(true);
-
- prop_editor_hb->add_child( property_back );
-
- property_forward = memnew( ToolButton );
- property_forward->set_icon( gui_base->get_icon("Forward","EditorIcons") );
- property_forward->set_flat(true);
- property_forward->set_tooltip(TTR("Go to the next edited object in history."));
- property_forward->set_disabled(true);
-
- prop_editor_hb->add_child( property_forward );
-
-
- editor_history_menu = memnew( MenuButton );
- editor_history_menu->set_tooltip(TTR("History of recently edited objects."));
- editor_history_menu->set_icon( gui_base->get_icon("History","EditorIcons"));
- prop_editor_hb->add_child(editor_history_menu);
- editor_history_menu->connect("about_to_show",this,"_prepare_history");
- editor_history_menu->get_popup()->connect("id_pressed",this,"_select_history");
-
-
- prop_editor_hb = memnew( HBoxContainer ); //again...
-
- prop_editor_base->add_child(prop_editor_hb);
- editor_path = memnew( EditorPath(&editor_history) );
- editor_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- prop_editor_hb->add_child(editor_path);
-
- search_button = memnew( ToolButton );
- search_button->set_toggle_mode(true);
- search_button->set_pressed(false);
- search_button->set_icon(gui_base->get_icon("Zoom","EditorIcons"));
- prop_editor_hb->add_child(search_button);
- search_button->connect("toggled",this,"_toggle_search_bar");
-
- object_menu = memnew( MenuButton );
- object_menu->set_icon(gui_base->get_icon("Tools","EditorIcons"));
- prop_editor_hb->add_child( object_menu );
- object_menu->set_tooltip(TTR("Object properties."));
-
- create_dialog = memnew( CreateDialog );
- gui_base->add_child(create_dialog);
- create_dialog->set_base_type("Resource");
- create_dialog->connect("create",this,"_resource_created");
-
- search_bar = memnew( HBoxContainer );
- search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- prop_editor_base->add_child(search_bar);
- search_bar->hide();
-
- Label *l = memnew( Label(TTR("Search:")+" ") );
- search_bar->add_child(l);
-
- search_box = memnew( LineEdit );
- search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- search_bar->add_child(search_box);
-
- ToolButton *clear_button = memnew( ToolButton );
- clear_button->set_icon(gui_base->get_icon("Close","EditorIcons"));
- search_bar->add_child(clear_button);
- clear_button->connect("pressed",this,"_clear_search_box");
-
- property_editor = memnew( PropertyEditor );
- property_editor->set_autoclear(true);
- property_editor->set_show_categories(true);
- property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- property_editor->set_use_doc_hints(true);
-
- property_editor->hide_top_label();
- property_editor->register_text_enter(search_box);
-
- prop_editor_base->add_child( property_editor );
- property_editor->set_undo_redo(&editor_data.get_undo_redo());
-
-
- import_dock = memnew( ImportDock );
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock);
- import_dock->set_name(TTR("Import"));
-
-
- node_dock = memnew( NodeDock );
- //node_dock->set_undoredo(&editor_data.get_undo_redo());
- if (use_single_dock_column) {
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
- } else {
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(node_dock);
- }
-
- filesystem_dock = memnew( FileSystemDock(this) );
- filesystem_dock->set_name(TTR("FileSystem"));
- filesystem_dock->set_display_mode(int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode")));
-
- if (use_single_dock_column) {
- dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(filesystem_dock);
- left_r_vsplit->hide();
- dock_slot[DOCK_SLOT_LEFT_UR]->hide();
- dock_slot[DOCK_SLOT_LEFT_BR]->hide();
- } else {
- dock_slot[DOCK_SLOT_LEFT_UR]->add_child(filesystem_dock);
- }
- //prop_pallete->add_child(filesystem_dock);
- filesystem_dock->connect("open",this,"open_request");
- filesystem_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", TTR("FileSystem"));
- default_layout->set_value(docks_section, "dock_5", TTR("Scene"));
- default_layout->set_value(docks_section, "dock_6", TTR("Inspector")+","+TTR("Node"));
-
- 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();
-
- 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);
-
- bottom_panel_hb = memnew( HBoxContainer );
- bottom_panel_vb->add_child(bottom_panel_hb);
-
-
-
- log = memnew( EditorLog );
-
- add_bottom_panel_item(TTR("Output"),log);
-
- //left_split->set_dragger_visible(false);
-
-
- 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);
-
-
- //progress_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-
-
-
- /*
- animation_menu = memnew( ToolButton );
- animation_menu->set_pos(Point2(500,0));
- animation_menu->set_size(Size2(20,20));
- animation_menu->set_toggle_mode(true);
- animation_menu->set_focus_mode(Control::FOCUS_NONE);
- menu_panel->add_child(animation_menu);
- animation_menu->set_icon(gui_base->get_icon("Animation","EditorIcons"));
- animation_menu->connect("pressed",this,"_animation_visibility_toggle");
-*/
-
-
-
-
-
-
-
-
-
-
-
-
- orphan_resources = memnew( OrphanResourcesDialog );
- gui_base->add_child(orphan_resources);
-
-
-
-
-
- confirmation = memnew( ConfirmationDialog );
- gui_base->add_child(confirmation);
- confirmation->connect("confirmed", this,"_menu_confirm_current");
-
- accept = memnew( AcceptDialog );
- gui_base->add_child(accept);
- accept->connect("confirmed", this,"_menu_confirm_current");
-
-
-
-
-
- //optimized_save = memnew( OptimizedSaveDialog(&editor_data) );
- //gui_base->add_child(optimized_save);
- //optimized_save->connect("confirmed",this,"_save_optimized");
-
- //project_export = memnew( ProjectExport(&editor_data) );
- //gui_base->add_child(project_export);
-
- //project_export_settings = memnew( ProjectExportDialog(this) );
- //gui_base->add_child(project_export_settings);
-
- //optimized_presets = memnew( OptimizedPresetsDialog(&editor_data) );
- //gui_base->add_child(optimized_presets);
- //optimized_presets->connect("confirmed",this,"_presets_optimized");
-
-
-
- //import_subscene = memnew( EditorSubScene );
- //gui_base->add_child(import_subscene);
-
-
-
- dependency_error = memnew( DependencyErrorDialog );
- gui_base->add_child(dependency_error);
-
- dependency_fixer = memnew( DependencyEditor );
- gui_base->add_child( dependency_fixer );
-
- settings_config_dialog = memnew( EditorSettingsDialog );
- gui_base->add_child(settings_config_dialog);
-
- project_settings = memnew( ProjectSettings(&editor_data) );
- gui_base->add_child(project_settings);
-
- import_confirmation = memnew( ConfirmationDialog );
- import_confirmation->get_ok()->set_text(TTR("Re-Import"));
- import_confirmation->add_button(TTR("Update"),!OS::get_singleton()->get_swap_ok_cancel(),"update");
- import_confirmation->get_label()->set_align(Label::ALIGN_CENTER);
- import_confirmation->connect("confirmed",this,"_import_action",make_binds("re-import"));
- import_confirmation->connect("custom_action",this,"_import_action");
- gui_base->add_child(import_confirmation);
-
- open_recent_confirmation = memnew( ConfirmationDialog );
- add_child(open_recent_confirmation);
- open_recent_confirmation->connect("confirmed",this,"_open_recent_scene_confirm");
-
-
- run_settings_dialog = memnew( RunSettingsDialog );
- gui_base->add_child( run_settings_dialog );
-
-
-
- about = memnew( AcceptDialog );
- about->set_title(TTR("Thanks from the Godot community!"));
- //about->get_cancel()->hide();
- about->get_ok()->set_text(TTR("Thanks!"));
- about->set_hide_on_ok(true);
- Label *about_text = memnew( Label );
- about_text->set_text(VERSION_FULL_NAME"\n(c) 2008-2017 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);
- TextureRect *logo = memnew( TextureRect );
- about->add_child(logo);
- logo->set_pos(Point2(20,20));
- logo->set_texture(gui_base->get_icon("Logo","EditorIcons") );
-
- warning = memnew( AcceptDialog );
- gui_base->add_child(warning);
-
-
-
- file_templates = memnew( FileDialog );
- file_templates->set_title(TTR("Import Templates From ZIP File"));
-
- gui_base->add_child( file_templates );
- file_templates->set_mode(FileDialog::MODE_OPEN_FILE);
- file_templates->set_access(FileDialog::ACCESS_FILESYSTEM);
- file_templates->clear_filters();
- file_templates->add_filter("*.tpz ; Template Package");
-
-
- file = memnew( EditorFileDialog );
- gui_base->add_child(file);
- file->set_current_dir("res://");
-
- file_export = memnew( FileDialog );
- file_export->set_access(FileDialog::ACCESS_FILESYSTEM);
- gui_base->add_child(file_export);
- file_export->set_title(TTR("Export Project"));
- file_export->connect("file_selected", this,"_dialog_action");
-
- file_export_lib = memnew( FileDialog );
- file_export_lib->set_title(TTR("Export Library"));
- file_export_lib->set_mode(FileDialog::MODE_SAVE_FILE);
- file_export_lib->connect("file_selected", this,"_dialog_action");
- file_export_lib_merge = memnew( CheckButton );
- file_export_lib_merge->set_text(TTR("Merge With Existing"));
- file_export_lib_merge->set_pressed(true);
- file_export_lib->get_vbox()->add_child(file_export_lib_merge);
- gui_base->add_child(file_export_lib);
-
-
-
-
- file_export_password = memnew( LineEdit );
- file_export_password->set_secret(true);
- file_export_password->set_editable(false);
- file_export->get_vbox()->add_margin_child(TTR("Password:"),file_export_password);
-
-
- file_script = memnew( FileDialog );
- file_script->set_title(TTR("Open & Run a Script"));
- file_script->set_access(FileDialog::ACCESS_FILESYSTEM);
- file_script->set_mode(FileDialog::MODE_OPEN_FILE);
- List<String> sexts;
- ResourceLoader::get_recognized_extensions_for_type("Script",&sexts);
- for (List<String>::Element*E=sexts.front();E;E=E->next()) {
- file_script->add_filter("*."+E->get());
- }
- gui_base->add_child(file_script);
- file_script->connect("file_selected",this,"_dialog_action");
-
- //reimport_dialog = memnew( EditorReImportDialog );
- //gui_base->add_child(reimport_dialog);
-
-
-
- property_forward->connect("pressed", this,"_property_editor_forward");
- property_back->connect("pressed", this,"_property_editor_back");
-
-
-
- file_menu->get_popup()->connect("id_pressed", this,"_menu_option");
- object_menu->get_popup()->connect("id_pressed", this,"_menu_option");
-
- update_menu->get_popup()->connect("id_pressed", this,"_menu_option");
- settings_menu->get_popup()->connect("id_pressed", this,"_menu_option");
-
-
- file->connect("file_selected", this,"_dialog_action");
- file_templates->connect("file_selected", this,"_dialog_action");
- property_editor->connect("resource_selected", this,"_resource_selected");
- property_editor->connect("property_keyed", this,"_property_keyed");
-
- //plugin stuff
-
- file_server = memnew( EditorFileServer );
-
-
-
- add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
- add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) );
- add_editor_plugin( memnew( SpatialEditorPlugin(this) ) );
- add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
-
-
- EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor();
-
- ScriptTextEditor::register_editor(); //register one for text scripts
-
- if (StreamPeerSSL::is_available()) {
- add_editor_plugin( memnew( AssetLibraryEditorPlugin(this) ) );
- } else {
- WARN_PRINT("Asset Library not available, as it requires SSL to work.");
- }
- //more visually meaningful to have this later
- raise_bottom_panel_item(AnimationPlayerEditor::singleton);
-
- add_editor_plugin( memnew( ShaderEditorPlugin(this) ) );
-/* add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,true) ) );
- add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,false) ) );
-
- add_editor_plugin( memnew( ShaderEditorPlugin(this,false) ) );*/
- add_editor_plugin( memnew( CameraEditorPlugin(this) ) );
-// add_editor_plugin( memnew( SampleEditorPlugin(this) ) );
-// add_editor_plugin( memnew( SampleLibraryEditorPlugin(this) ) );
- add_editor_plugin( memnew( ThemeEditorPlugin(this) ) );
- add_editor_plugin( memnew( MultiMeshEditorPlugin(this) ) );
- add_editor_plugin( memnew( MeshInstanceEditorPlugin(this) ) );
- add_editor_plugin( memnew( AnimationTreeEditorPlugin(this) ) );
- //add_editor_plugin( memnew( SamplePlayerEditorPlugin(this) ) ); - this is kind of useless at this point
- //add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) );
- //add_editor_plugin( memnew( StreamEditorPlugin(this) ) );
- add_editor_plugin( memnew( StyleBoxEditorPlugin(this) ) );
- //add_editor_plugin( memnew( ParticlesEditorPlugin(this) ) );
- add_editor_plugin( memnew( ResourcePreloaderEditorPlugin(this) ) );
- add_editor_plugin( memnew( ItemListEditorPlugin(this) ) );
- //add_editor_plugin( memnew( RichTextEditorPlugin(this) ) );
- //add_editor_plugin( memnew( CollisionPolygonEditorPlugin(this) ) );
- add_editor_plugin( memnew( CollisionPolygon2DEditorPlugin(this) ) );
- add_editor_plugin( memnew( TileSetEditorPlugin(this) ) );
- add_editor_plugin( memnew( TileMapEditorPlugin(this) ) );
- add_editor_plugin( memnew( SpriteFramesEditorPlugin(this) ) );
- add_editor_plugin( memnew( TextureRegionEditorPlugin(this) ) );
- add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) );
- add_editor_plugin( memnew( GIProbeEditorPlugin(this) ) );
- add_editor_plugin( memnew( Path2DEditorPlugin(this) ) );
- //add_editor_plugin( memnew( PathEditorPlugin(this) ) );
- //add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) );
- add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) );
- add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) );
- add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) );
- add_editor_plugin( memnew( ColorRampEditorPlugin(this) ) );
- add_editor_plugin( memnew( CollisionShape2DEditorPlugin(this) ) );
- add_editor_plugin( memnew( TextureEditorPlugin(this) ) );
- add_editor_plugin( memnew( AudioBusesEditorPlugin(audio_bus_editor) ) );
- //add_editor_plugin( memnew( MaterialEditorPlugin(this) ) );
- //add_editor_plugin( memnew( MeshEditorPlugin(this) ) );
-
- for(int i=0;i<EditorPlugins::get_plugin_count();i++)
- add_editor_plugin( EditorPlugins::create(i,this) );
-
- for(int i=0;i<plugin_init_callback_count;i++) {
- plugin_init_callbacks[i]();
- }
-
-
-
-
- /*resource_preview->add_preview_generator( Ref<EditorTexturePreviewPlugin>( memnew(EditorTexturePreviewPlugin )));
- resource_preview->add_preview_generator( Ref<EditorPackedScenePreviewPlugin>( memnew(EditorPackedScenePreviewPlugin )));
- resource_preview->add_preview_generator( Ref<EditorMaterialPreviewPlugin>( memnew(EditorMaterialPreviewPlugin )));
- 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=Engine::get_singleton()->get_frames_drawn();
- circle_step=0;
-
- _rebuild_import_menu();
-
- editor_plugin_screen=NULL;
- editor_plugins_over = memnew(EditorPluginList);
-
- //force_top_viewport(true);
- _edit_current();
- current=NULL;
-
- PhysicsServer::get_singleton()->set_active(false); // no physics by default if editor
- Physics2DServer::get_singleton()->set_active(false); // no physics by default if editor
- ScriptServer::set_scripting_enabled(false); // no scripting by default if editor
-
-
- //GlobalConfig::get_singleton()->set("render/room_cull_enabled",false);
-
- reference_resource_mem=true;
- save_external_resources_mem=true;
-
- set_process(true);
- OS::get_singleton()->set_low_processor_usage_mode(true);
-
-
- if (0) { //not sure if i want this to happen after all
-
- //store project name in ssettings
- String project_name;
- //figure it out from path
- project_name=GlobalConfig::get_singleton()->get_resource_path().replace("\\","/");
- print_line("path: "+project_name);
- if (project_name.length() && project_name[project_name.length()-1]=='/')
- project_name=project_name.substr(0,project_name.length()-1);
-
- project_name=project_name.replace("/","::");
-
- if (project_name!="") {
- EditorSettings::get_singleton()->set("projects/"+project_name,GlobalConfig::get_singleton()->get_resource_path());
- EditorSettings::get_singleton()->raise_order("projects/"+project_name);
- EditorSettings::get_singleton()->save();
- }
- }
-
- open_imported = memnew( ConfirmationDialog );
- open_imported->get_ok()->set_text(TTR("Open Anyway"));
- new_inherited_button=open_imported->add_button("New Inherited",!OS::get_singleton()->get_swap_ok_cancel(),"inherit");
- open_imported->connect("confirmed",this,"_open_imported");
- open_imported->connect("custom_action",this,"_inherit_imported");
- gui_base->add_child(open_imported);
-
-
-
- //edited_scene=NULL;
- saved_version=1;
- unsaved_cache=true;
- _last_instanced_scene=NULL;
-
-
- quick_open = memnew( EditorQuickOpen );
- gui_base->add_child(quick_open);
- quick_open->connect("quick_open",this,"_quick_opened");
-
- quick_run = memnew( EditorQuickOpen );
- gui_base->add_child(quick_run);
- quick_run->connect("quick_open",this,"_quick_run");
-
-
- _update_recent_scenes();
-
-
- editor_data.restore_editor_global_states();
- convert_old=false;
- opening_prev=false;
- set_process_unhandled_input(true);
- _playing_edited=false;
-
- //Panel *errors = memnew( Panel );
- load_errors = memnew( RichTextLabel );
- //load_errors->set_readonly(true);
- load_error_dialog = memnew( AcceptDialog );
- load_error_dialog->add_child(load_errors);
- load_error_dialog->set_title(TTR("Load Errors"));
- //load_error_dialog->set_child_rect(load_errors);
- gui_base->add_child(load_error_dialog);
-
-
- //EditorImport::add_importer( Ref<EditorImporterCollada>( memnew(EditorImporterCollada )));
-
- EditorFileSystem::get_singleton()->connect("sources_changed",this,"_sources_changed");
- EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_fs_changed");
-
-
- {
- List<StringName> tl;
- StringName ei = "EditorIcons";
- theme_base->get_theme()->get_icon_list(ei,&tl);
- for(List<StringName>::Element *E=tl.front();E;E=E->next()) {
-
- if (!ClassDB::class_exists(E->get()))
- continue;
- icon_type_cache[E->get()]=theme_base->get_theme()->get_icon(E->get(),ei);
- }
- }
-
-
-
- Node::set_human_readable_collision_renaming(true);
-
-
- pick_main_scene = memnew( ConfirmationDialog );
- gui_base->add_child(pick_main_scene);
- pick_main_scene->get_ok()->set_text("Select");
- pick_main_scene->connect("confirmed",this,"_menu_option",varray(SETTINGS_PICK_MAIN_SCENE));
-
- //Ref<ImageTexture> it = gui_base->get_icon("logo","Icons");
- //OS::get_singleton()->set_icon( it->get_data() );
-
- for(int i=0;i<_init_callbacks.size();i++)
- _init_callbacks[i]();
-
- editor_data.add_edited_scene(-1);
- editor_data.set_edited_scene(0);
- _update_scene_tabs();
-
- {
-
- _initializing_addons=true;
- Vector<String> addons = GlobalConfig::get_singleton()->get("editor_plugins/enabled");
-
- for(int i=0;i<addons.size();i++) {
- set_addon_plugin_enabled(addons[i],true);
- }
- _initializing_addons=false;
- }
-
-
-
- _load_docks();
-
- FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
-
- waiting_for_first_scan=true;
-
-}
-
-
-EditorNode::~EditorNode() {
-
-
- memdelete( EditorHelp::get_doc_data() );
- memdelete(editor_selection);
- memdelete(editor_plugins_over);
- memdelete(file_server);
- EditorSettings::destroy();
-}
-
-/*
- * EDITOR PLUGIN LIST
- */
-
-
-void EditorPluginList::make_visible(bool p_visible) {
-
- for (int i = 0; i < plugins_list.size(); i++) {
- plugins_list[i]->make_visible(p_visible);
- }
-
-}
-
-void EditorPluginList::edit(Object* p_object) {
-
- for (int i = 0; i < plugins_list.size(); i++) {
- plugins_list[i]->edit(p_object);
- }
-
-}
-
-bool EditorPluginList::forward_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) {
-
- bool discard = false;
-
- for (int i = 0; i < plugins_list.size(); i++) {
- if (plugins_list[i]->forward_canvas_gui_input(p_canvas_xform,p_event)) {
- discard = true;
- }
- }
-
- return discard;
-}
-
-bool EditorPluginList::forward_spatial_gui_input(Camera* p_camera, const InputEvent& p_event) {
- bool discard = false;
-
- for (int i = 0; i < plugins_list.size(); i++) {
- if (plugins_list[i]->forward_spatial_gui_input(p_camera, p_event)) {
- discard = true;
- }
- }
-
- return discard;
-}
-
-void EditorPluginList::forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control* p_canvas) {
-
- for (int i = 0; i < plugins_list.size(); i++) {
- plugins_list[i]->forward_draw_over_canvas(p_canvas_xform,p_canvas);
- }
-
-}
-
-bool EditorPluginList::empty() {
- return plugins_list.empty();
-}
-
-void EditorPluginList::clear() {
- plugins_list.clear();
-}
-
-EditorPluginList::EditorPluginList() {
-}
-
-EditorPluginList::~EditorPluginList() {
-}
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
deleted file mode 100644
index 4aca433f9c..0000000000
--- a/tools/editor/editor_node.h
+++ /dev/null
@@ -1,832 +0,0 @@
-/*************************************************************************/
-/* editor_node.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_NODE_H
-#define EDITOR_NODE_H
-
-#include "scene/gui/control.h"
-#include "scene/gui/panel.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/separator.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/panel_container.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/center_container.h"
-#include "scene/gui/texture_progress.h"
-#include "tools/editor/filesystem_dock.h"
-#include "tools/editor/scene_tree_editor.h"
-#include "tools/editor/property_editor.h"
-#include "tools/editor/create_dialog.h"
-#include "tools/editor/call_dialog.h"
-#include "tools/editor/reparent_dialog.h"
-#include "tools/editor/connections_dialog.h"
-#include "tools/editor/node_dock.h"
-#include "tools/editor/import_dock.h"
-#include "tools/editor/settings_config_dialog.h"
-#include "tools/editor/groups_editor.h"
-#include "tools/editor/editor_data.h"
-#include "tools/editor/editor_path.h"
-#include "tools/editor/editor_run.h"
-
-#include "tools/editor/pane_drag.h"
-
-#include "tools/editor/script_create_dialog.h"
-#include "tools/editor/run_settings_dialog.h"
-#include "tools/editor/project_settings.h"
-#include "tools/editor/project_export.h"
-#include "tools/editor/editor_log.h"
-#include "tools/editor/scene_tree_dock.h"
-#include "tools/editor/resources_dock.h"
-#include "tools/editor/editor_run_script.h"
-
-#include "tools/editor/editor_run_native.h"
-#include "scene/gui/tabs.h"
-#include "tools/editor/quick_open.h"
-#include "tools/editor/project_export.h"
-#include "tools/editor/editor_sub_scene.h"
-#include "editor_import_export.h"
-#include "editor_reimport_dialog.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"
-#include "scene/gui/viewport_container.h"
-
-
-#include "progress_dialog.h"
-
-#include "editor_scale.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-
-
-
-
-typedef void (*EditorNodeInitCallback)();
-typedef void (*EditorPluginInitializeCallback)();
-typedef void (*EditorBuildCallback)();
-
-class EditorPluginList;
-
-class EditorNode : public Node {
-
- GDCLASS( EditorNode, Node );
-
-public:
- enum DockSlot {
- DOCK_SLOT_LEFT_UL,
- DOCK_SLOT_LEFT_BL,
- DOCK_SLOT_LEFT_UR,
- DOCK_SLOT_LEFT_BR,
- DOCK_SLOT_RIGHT_UL,
- DOCK_SLOT_RIGHT_BL,
- DOCK_SLOT_RIGHT_UR,
- DOCK_SLOT_RIGHT_BR,
- DOCK_SLOT_MAX
- };
-private:
- enum {
- HISTORY_SIZE=64
- };
-
- enum MenuOptions {
- FILE_NEW_SCENE,
- FILE_NEW_INHERITED_SCENE,
- FILE_OPEN_SCENE,
- FILE_SAVE_SCENE,
- FILE_SAVE_AS_SCENE,
- FILE_SAVE_ALL_SCENES,
- FILE_SAVE_BEFORE_RUN,
- FILE_SAVE_AND_RUN,
- FILE_IMPORT_SUBSCENE,
- FILE_EXPORT_PROJECT,
- FILE_EXPORT_MESH_LIBRARY,
- FILE_EXPORT_TILESET,
- FILE_SAVE_OPTIMIZED,
- FILE_OPEN_RECENT,
- FILE_OPEN_OLD_SCENE,
- FILE_QUICK_OPEN_SCENE,
- FILE_QUICK_OPEN_SCRIPT,
- FILE_RUN_SCRIPT,
- FILE_OPEN_PREV,
- FILE_CLOSE,
- FILE_QUIT,
- FILE_EXTERNAL_OPEN_SCENE,
- EDIT_UNDO,
- EDIT_REDO,
- EDIT_REVERT,
- TOOLS_ORPHAN_RESOURCES,
- RESOURCE_NEW,
- RESOURCE_LOAD,
- RESOURCE_SAVE,
- RESOURCE_SAVE_AS,
- RESOURCE_UNREF,
- RESOURCE_COPY,
- RESOURCE_PASTE,
- OBJECT_COPY_PARAMS,
- OBJECT_PASTE_PARAMS,
- OBJECT_UNIQUE_RESOURCES,
- OBJECT_REQUEST_HELP,
- RUN_PLAY,
-
- RUN_STOP,
- RUN_PLAY_SCENE,
- RUN_PLAY_NATIVE,
- RUN_PLAY_CUSTOM_SCENE,
- RUN_SCENE_SETTINGS,
- RUN_SETTINGS,
- RUN_PROJECT_MANAGER,
- RUN_FILE_SERVER,
- //RUN_DEPLOY_DUMB_CLIENTS,
- RUN_LIVE_DEBUG,
- RUN_DEBUG_COLLISONS,
- RUN_DEBUG_NAVIGATION,
- RUN_DEPLOY_REMOTE_DEBUG,
- RUN_RELOAD_SCRIPTS,
- SETTINGS_UPDATE_ALWAYS,
- SETTINGS_UPDATE_CHANGES,
- SETTINGS_UPDATE_SPINNER_HIDE,
- SETTINGS_EXPORT_PREFERENCES,
- SETTINGS_PREFERENCES,
- SETTINGS_OPTIMIZED_PRESETS,
- SETTINGS_LAYOUT_SAVE,
- SETTINGS_LAYOUT_DELETE,
- SETTINGS_LAYOUT_DEFAULT,
- SETTINGS_LOAD_EXPORT_TEMPLATES,
- SETTINGS_PICK_MAIN_SCENE,
- SETTINGS_TOGGLE_FULLSCREN,
- SETTINGS_HELP,
- SETTINGS_ABOUT,
- SOURCES_REIMPORT,
- DEPENDENCY_LOAD_CHANGED_IMAGES,
- DEPENDENCY_UPDATE_IMPORTED,
- SCENE_TAB_CLOSE,
-
- IMPORT_PLUGIN_BASE=100,
-
- OBJECT_METHOD_BASE=500,
-
- TOOL_MENU_BASE=1000
- };
-
-
-
- //Node *edited_scene; //scene being edited
- Viewport *scene_root; //root of the scene being edited
-
- //Ref<ResourceImportMetadata> scene_import_metadata;
-
- PanelContainer* scene_root_parent;
- Control *gui_base;
- VBoxContainer *main_vbox;
-
- //split
-
- HSplitContainer *left_l_hsplit;
- VSplitContainer *left_l_vsplit;
- HSplitContainer *left_r_hsplit;
- VSplitContainer *left_r_vsplit;
- HSplitContainer *main_hsplit;
- HSplitContainer *right_hsplit;
- VSplitContainer *right_l_vsplit;
- VSplitContainer *right_r_vsplit;
-
- VSplitContainer *center_split;
-
- //main tabs
-
- Tabs *scene_tabs;
- int tab_closing;
-
- bool exiting;
-
- int old_split_ofs;
- VSplitContainer *top_split;
- HBoxContainer *bottom_hb;
- Control *vp_base;
- PaneDrag *pd;
- //PaneDrag *pd_anim;
- Panel *menu_panel;
-
-
- //HSplitContainer *editor_hsplit;
- //VSplitContainer *editor_vsplit;
- CenterContainer *play_cc;
- HBoxContainer *menu_hb;
- Control *viewport;
- MenuButton *file_menu;
- MenuButton *import_menu;
- MenuButton *tool_menu;
- ToolButton *export_button;
- ToolButton *prev_scene;
- MenuButton *object_menu;
- MenuButton *settings_menu;
- ToolButton *play_button;
- MenuButton *native_play_button;
- ToolButton *pause_button;
- ToolButton *stop_button;
- ToolButton *run_settings_button;
- ToolButton *play_scene_button;
- ToolButton *play_custom_scene_button;
- MenuButton *debug_button;
- ToolButton *search_button;
- TextureProgress *audio_vu;
- //MenuButton *fileserver_menu;
-
- RichTextLabel *load_errors;
- AcceptDialog *load_error_dialog;
-
- //Control *scene_root_base;
- Ref<Theme> theme;
-
- PopupMenu *recent_scenes;
- Button *property_back;
- Button *property_forward;
- SceneTreeDock *scene_tree_dock;
- //ResourcesDock *resources_dock;
- PropertyEditor *property_editor;
- NodeDock *node_dock;
- ImportDock *import_dock;
- VBoxContainer *prop_editor_vb;
- FileSystemDock *filesystem_dock;
- EditorRunNative *run_native;
-
- HBoxContainer *search_bar;
- LineEdit *search_box;
-
- CreateDialog *create_dialog;
-
- //CallDialog *call_dialog;
- ConfirmationDialog *confirmation;
- ConfirmationDialog *import_confirmation;
- ConfirmationDialog *open_recent_confirmation;
- ConfirmationDialog *pick_main_scene;
- AcceptDialog *accept;
- 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;
- ProjectSettings *project_settings;
- EditorFileDialog *file;
- FileDialog *file_templates;
- FileDialog *file_export;
- FileDialog *file_export_lib;
- FileDialog *file_script;
- CheckButton *file_export_lib_merge;
- LineEdit *file_export_password;
- String current_path;
- MenuButton *update_menu;
- ToolButton *sources_button;
- //TabContainer *prop_pallete;
- //TabContainer *top_pallete;
- String defer_load_scene;
- String defer_export;
- String defer_export_platform;
- bool defer_export_debug;
- Node *_last_instanced_scene;
- EditorPath *editor_path;
- ToolButton *resource_new_button;
- ToolButton *resource_load_button;
- MenuButton *resource_save_button;
- MenuButton *editor_history_menu;
-
- EditorLog *log;
- CenterContainer *tabs_center;
- EditorQuickOpen *quick_open;
- EditorQuickOpen *quick_run;
-
- HBoxContainer *main_editor_button_vb;
- Vector<ToolButton*> main_editor_buttons;
- Vector<EditorPlugin*> editor_table;
-
-// EditorReImportDialog *reimport_dialog;
-
- ProgressDialog *progress_dialog;
- BackgroundProgress *progress_hb;
-
- DependencyErrorDialog *dependency_error;
- DependencyEditor *dependency_fixer;
- OrphanResourcesDialog *orphan_resources;
- ConfirmationDialog *open_imported;
- Button *new_inherited_button;
- String open_import_request;
-
-
- TabContainer *dock_slot[DOCK_SLOT_MAX];
- Rect2 dock_select_rect[DOCK_SLOT_MAX];
- int dock_select_rect_over;
- PopupPanel *dock_select_popoup;
- Control *dock_select;
- ToolButton *dock_tab_move_left;
- ToolButton *dock_tab_move_right;
- int dock_popup_selected;
- Timer *dock_drag_timer;
- bool docks_visible;
- ToolButton *distraction_free;
-
- String _tmp_import_path;
-
- EditorImportExport *editor_import_export;
-
- Object *current;
-
- bool _playing_edited;
- String run_custom_filename;
- bool reference_resource_mem;
- bool save_external_resources_mem;
- uint64_t saved_version;
- uint64_t last_checked_version;
- bool unsaved_cache;
- String open_navigate;
- bool changing_scene;
- bool waiting_for_first_scan;
-
- bool waiting_for_sources_changed;
-
- uint32_t circle_step_msec;
- uint64_t circle_step_frame;
- int circle_step;
-
- Vector<EditorPlugin*> editor_plugins;
- EditorPlugin *editor_plugin_screen;
- EditorPluginList *editor_plugins_over;
-
- EditorHistory editor_history;
- EditorData editor_data;
- EditorRun editor_run;
- EditorSelection *editor_selection;
-// ProjectExport *project_export;
-// ProjectExportDialog *project_export_settings;
- EditorResourcePreview *resource_preview;
-
- 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;
-
- void _dialog_action(String p_file);
-
-
- void _edit_current();
- void _dialog_display_file_error(String p_file,Error p_error);
-
- int current_option;
- //void _animation_visibility_toggle();
- void _resource_created();
- void _resource_selected(const RES& p_res,const String& p_property="");
- void _menu_option(int p_option);
- void _menu_confirm_current();
- void _menu_option_confirm(int p_option,bool p_confirmed);
-
- void _property_editor_forward();
- void _property_editor_back();
-
- void _select_history(int p_idx);
- void _prepare_history();
-
-
- void _fs_changed();
- void _sources_changed(bool p_exist);
- void _imported(Node *p_node);
-
- void _node_renamed();
- void _editor_select(int p_which);
- void _set_scene_metadata(const String &p_file, int p_idx=-1);
- void _get_scene_metadata(const String& p_file);
- void _update_title();
- void _update_scene_tabs();
- void _close_messages();
- void _show_messages();
- void _vp_resized();
-
- void _rebuild_import_menu();
-
- void _save_scene(String p_file, int idx = -1);
-
-
- void _instance_request(const Vector<String>& p_files);
-
- 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 _hide_top_editors();
- void _display_top_editors(bool p_display);
- void _set_top_editors(Vector<EditorPlugin*> p_editor_plugins_over);
- void _set_editing_top_editors(Object * p_current_object);
-
- void _quick_opened();
- void _quick_run();
-
- void _run(bool p_current=false, const String &p_custom="");
-
- void _save_optimized();
- void _import_action(const String& p_action);
- void _import(const String &p_file);
- void _add_to_recent_scenes(const String& p_scene);
- void _update_recent_scenes();
- void _open_recent_scene(int p_idx);
- void _dropped_files(const Vector<String>& p_files,int p_screen);
- //void _open_recent_scene_confirm();
- String _recent_scene;
-
- bool convert_old;
-
- void _unhandled_input(const InputEvent& p_event);
-
- static void _load_error_notify(void* p_ud,const String& p_text);
-
- bool has_main_screen() const { return true; }
-
- bool _find_editing_changed_scene(Node *p_from);
-
- String import_reload_fn;
-
- Set<FileDialog*> file_dialogs;
- Set<EditorFileDialog*> editor_file_dialogs;
-
- Map<String,Ref<Texture> > icon_type_cache;
-
- bool _initializing_addons;
- Map<String,EditorPlugin*> plugin_addons;
-
-
- static Ref<Texture> _file_dialog_get_icon(const String& p_path);
- static void _file_dialog_register(FileDialog *p_dialog);
- static void _file_dialog_unregister(FileDialog *p_dialog);
- static void _editor_file_dialog_register(EditorFileDialog *p_dialog);
- static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog);
-
-
- void _cleanup_scene();
- void _remove_edited_scene();
- void _remove_scene(int index);
- bool _find_and_save_resource(RES p_res,Map<RES,bool>& processed,int32_t flags);
- bool _find_and_save_edited_subresources(Object *obj,Map<RES,bool>& processed,int32_t flags);
- void _save_edited_subresources(Node* scene,Map<RES,bool>& processed,int32_t flags);
-
- void _find_node_types(Node* p_node, int&count_2d, int&count_3d);
- void _save_scene_with_preview(String p_file);
-
-
- Map<String,Set<String> > dependency_errors;
-
- static void _dependency_error_report(void *ud,const String& p_path,const String& p_dep,const String& p_type) {
- EditorNode*en=(EditorNode*)ud;
- if (!en->dependency_errors.has(p_path))
- en->dependency_errors[p_path]=Set<String>();
- en->dependency_errors[p_path].insert(p_dep+"::"+p_type);
-
- }
-
- struct ExportDefer {
- String platform;
- String path;
- bool debug;
- String password;
-
- } export_defer;
-
- static EditorNode *singleton;
-
- static Vector<EditorNodeInitCallback> _init_callbacks;
-
- bool _find_scene_in_use(Node* p_node,const String& p_path) const;
-
- void _dock_select_input(const InputEvent& p_input);
- void _dock_move_left();
- void _dock_move_right();
- void _dock_select_draw();
- void _dock_pre_popup(int p_which);
- void _dock_split_dragged(int ofs);
- void _dock_popup_exit();
- void _scene_tab_changed(int p_tab);
- void _scene_tab_closed(int p_tab);
- void _scene_tab_script_edited(int p_tab);
-
- Dictionary _get_main_scene_state();
- void _set_main_scene_state(Dictionary p_state,Node* p_for_scene);
-
- int _get_current_main_editor();
-
- 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_dock_slots_visibility();
- void _update_top_menu_visibility();
-
- 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();
-
- void _update_addon_config();
-
- static void _file_access_close_error_notify(const String& p_str);
-
- void _toggle_distraction_free_mode();
-
- enum {
- MAX_INIT_CALLBACKS=128,
- MAX_BUILD_CALLBACKS=128
- };
-
- void _inherit_imported(const String &p_action);
- void _open_imported();
-
-
- static int plugin_init_callback_count;
- static EditorPluginInitializeCallback plugin_init_callbacks[MAX_INIT_CALLBACKS];
-
- void _call_build();
- static int build_callback_count;
- static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS];
-
- bool _initializing_tool_menu;
-
- struct ToolMenuItem {
- String name;
- String submenu;
- Variant ud;
- ObjectID handler;
- String callback;
- };
-
- Vector<ToolMenuItem> tool_menu_items;
-
- void _tool_menu_insert_item(const ToolMenuItem& p_item);
- void _rebuild_tool_menu() const;
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- static void add_plugin_init_callback(EditorPluginInitializeCallback p_callback);
-
- enum EditorTable {
- EDITOR_2D = 0,
- EDITOR_3D,
- EDITOR_SCRIPT
- };
-
- void set_visible_editor(EditorTable p_table) { _editor_select(p_table); }
- static EditorNode* get_singleton() { return singleton; }
-
-
- EditorPlugin *get_editor_plugin_screen() { return editor_plugin_screen; }
- EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; }
- PropertyEditor *get_property_editor() { return property_editor; }
- VBoxContainer *get_property_editor_vb() { return prop_editor_vb; }
-
- static void add_editor_plugin(EditorPlugin *p_editor);
- static void remove_editor_plugin(EditorPlugin *p_editor);
-
- void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE,false); }
-
-
- void set_docks_visible(bool p_show);
- bool get_docks_visible() const;
-
- void set_distraction_free_mode(bool p_enter);
- bool get_distraction_free_mode() const;
-
- void add_control_to_dock(DockSlot p_slot,Control* p_control);
- void remove_control_from_dock(Control* p_control);
-
- void set_addon_plugin_enabled(const String& p_addon,bool p_enabled);
- bool is_addon_plugin_enabled(const String &p_addon) const;
-
- void edit_node(Node *p_node);
- void edit_resource(const Ref<Resource>& p_resource);
- void open_resource(const String& p_type="");
-
- void save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path);
- void save_resource(const Ref<Resource>& p_resource);
- void save_resource_as(const Ref<Resource>& p_resource, const String &p_at_path=String());
-
- void merge_from_scene() { _menu_option_confirm(FILE_IMPORT_SUBSCENE,false); }
-
- static bool has_unsaved_changes() { return singleton->unsaved_cache; }
-
- static HBoxContainer *get_menu_hb() { return singleton->menu_hb; }
-
- void push_item(Object *p_object,const String& p_property="");
-
- void open_request(const String& p_path);
-
- bool is_changing_scene() const;
-
-
- static EditorLog *get_log() { return singleton->log; }
- Control* get_viewport();
-
- //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);
-
- Node *get_edited_scene() { return editor_data.get_edited_scene_root(); }
-
- Viewport *get_scene_root() { return scene_root; } //root of the scene being edited
-
- void fix_dependencies(const String& p_for_file);
- void clear_scene() { _cleanup_scene(); }
- Error load_scene(const String& p_scene, bool p_ignore_broken_deps=false, bool p_set_inherited=false, bool p_clear_errors=true,bool p_force_open_imported=false);
- Error load_resource(const String& p_scene);
-
- bool is_scene_open(const String& p_path);
-
- void set_current_version(uint64_t p_version);
- 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; }
-
- void request_instance_scene(const String &p_path);
- void request_instance_scenes(const Vector<String>& p_files);
- FileSystemDock *get_filesystem_dock();
- ImportDock *get_import_dock();
- SceneTreeDock *get_scene_tree_dock();
- static UndoRedo* get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
-
- EditorSelection *get_editor_selection() { return editor_selection; }
-
- void set_convert_old_scene(bool p_old) { convert_old=p_old; }
-
- void notify_child_process_exited();
-
- OS::ProcessID get_child_process_id() const { return editor_run.get_pid(); }
- void stop_child_process();
-
- Ref<Theme> get_editor_theme() const { return theme; }
-
-
- void show_warning(const String& p_text,const String& p_title="Warning!");
-
-
- Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false);
-
- static void register_editor_types();
- static void unregister_editor_types();
-
- Control *get_gui_base() { return gui_base; }
- Control *get_theme_base() { return gui_base->get_parent_control(); }
-
- 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,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);
- static void progress_task_step_bg(const String& p_task,int p_step=-1);
- static void progress_end_task_bg(const String& p_task);
-
- void save_scene(String p_file) { _save_scene(p_file); }
-
- bool is_scene_in_use(const String& p_path);
-
- void scan_import_changes();
-
- void save_layout();
-
- void update_keying();
-
- void reload_scene(const String& p_path);
-
- bool is_exiting() const { return exiting; }
-
- ToolButton *get_pause_button() { return pause_button; }
-
-
- ToolButton* add_bottom_panel_item(String p_text,Control *p_item);
- bool are_bottom_panels_hidden() const;
- void make_bottom_panel_item_visible(Control *p_item);
- void raise_bottom_panel_item(Control *p_item);
- void hide_bottom_panel();
- void remove_bottom_panel_item(Control *p_item);
-
- Variant drag_resource(const Ref<Resource>& p_res,Control* p_from);
- Variant drag_files(const Vector<String>& p_files,Control* p_from);
- Variant drag_files_and_dirs(const Vector<String>& p_files,Control* p_from);
-
- void add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud = Variant());
- void add_tool_submenu_item(const String& p_name, PopupMenu *p_submenu);
- void remove_tool_menu_item(const String& p_name);
-
- EditorNode();
- ~EditorNode();
- void get_singleton(const char* arg1, bool arg2);
-
- static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); }
- static void add_build_callback(EditorBuildCallback p_callback);
-
-
-
-};
-
-struct EditorProgress {
-
- String task;
- 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); }
-};
-
-class EditorPluginList : public Object {
-private:
- Vector<EditorPlugin*> plugins_list;
-
-public:
-
- void set_plugins_list(Vector<EditorPlugin*> p_plugins_list) {
- plugins_list = p_plugins_list;
- }
-
- Vector<EditorPlugin*>& get_plugins_list() {
- return plugins_list;
- }
-
- void make_visible(bool p_visible);
- void edit(Object *p_object);
- bool forward_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event);
- bool forward_spatial_gui_input(Camera* p_camera, const InputEvent& p_event);
- void forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control* p_canvas);
- void clear();
- bool empty();
-
- EditorPluginList();
- ~EditorPluginList();
-
-} ;
-
-struct EditorProgressBG {
-
- String task;
- void step(int p_step=-1) { EditorNode::progress_task_step_bg(task,p_step); }
- EditorProgressBG(const String& p_task,const String& p_label,int p_amount) { EditorNode::progress_add_task_bg(p_task,p_label,p_amount); task=p_task; }
- ~EditorProgressBG() { EditorNode::progress_end_task_bg(task); }
-};
-
-#endif
diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp
deleted file mode 100644
index 2f44b5558c..0000000000
--- a/tools/editor/editor_plugin.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-/*************************************************************************/
-/* editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_plugin.h"
-
-#include "scene/gui/popup_menu.h"
-#include "scene/3d/camera.h"
-#include "plugins/canvas_item_editor_plugin.h"
-#include "plugins/spatial_editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/editor_settings.h"
-#include "editor_resource_preview.h"
-
-void EditorPlugin::add_custom_type(const String& p_type, const String& p_base,const Ref<Script>& p_script, const Ref<Texture>& p_icon) {
-
- EditorNode::get_editor_data().add_custom_type(p_type,p_base,p_script,p_icon);
-}
-
-void EditorPlugin::remove_custom_type(const String& p_type){
-
- EditorNode::get_editor_data().remove_custom_type(p_type);
-}
-
-
-ToolButton * EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) {
-
- return EditorNode::get_singleton()->add_bottom_panel_item(p_title,p_control);
-}
-
-void EditorPlugin::add_control_to_dock(DockSlot p_slot,Control *p_control) {
-
- ERR_FAIL_NULL(p_control);
- EditorNode::get_singleton()->add_control_to_dock(EditorNode::DockSlot(p_slot),p_control);
-
-}
-
-void EditorPlugin::remove_control_from_docks(Control *p_control) {
-
- ERR_FAIL_NULL(p_control);
- EditorNode::get_singleton()->remove_control_from_dock(p_control);
-
-}
-
-void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) {
-
- ERR_FAIL_NULL(p_control);
- EditorNode::get_singleton()->remove_bottom_panel_item(p_control);
-
-}
-
-Control * EditorPlugin::get_editor_viewport() {
-
- return EditorNode::get_singleton()->get_viewport();
-}
-
-void EditorPlugin::edit_resource(const Ref<Resource>& p_resource){
-
- EditorNode::get_singleton()->edit_resource(p_resource);
-}
-
-void EditorPlugin::add_control_to_container(CustomControlContainer p_location,Control *p_control) {
-
- switch(p_location) {
-
- case CONTAINER_TOOLBAR: {
-
- EditorNode::get_menu_hb()->add_child(p_control);
- } break;
-
- case CONTAINER_SPATIAL_EDITOR_MENU: {
-
- SpatialEditor::get_singleton()->add_control_to_menu_panel(p_control);
-
- } break;
- case CONTAINER_SPATIAL_EDITOR_SIDE: {
-
- SpatialEditor::get_singleton()->get_palette_split()->add_child(p_control);
- SpatialEditor::get_singleton()->get_palette_split()->move_child(p_control,0);
-
- } break;
- case CONTAINER_SPATIAL_EDITOR_BOTTOM: {
-
- SpatialEditor::get_singleton()->get_shader_split()->add_child(p_control);
-
- } break;
- case CONTAINER_CANVAS_EDITOR_MENU: {
-
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(p_control);
-
- } break;
- case CONTAINER_CANVAS_EDITOR_SIDE: {
-
- CanvasItemEditor::get_singleton()->get_palette_split()->add_child(p_control);
- CanvasItemEditor::get_singleton()->get_palette_split()->move_child(p_control,0);
-
- } break;
- case CONTAINER_CANVAS_EDITOR_BOTTOM: {
-
- CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(p_control);
-
- } break;
- case CONTAINER_PROPERTY_EDITOR_BOTTOM: {
-
- EditorNode::get_singleton()->get_property_editor_vb()->add_child(p_control);
-
- } break;
-
-
- }
-}
-
-void EditorPlugin::add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud) {
-
- //EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud);
-}
-
-void EditorPlugin::add_tool_submenu_item(const String& p_name, Object *p_submenu) {
-
- ERR_FAIL_NULL(p_submenu);
- PopupMenu *submenu = p_submenu->cast_to<PopupMenu>();
- ERR_FAIL_NULL(submenu);
- //EditorNode::get_singleton()->add_tool_submenu_item(p_name, submenu);
-}
-
-void EditorPlugin::remove_tool_menu_item(const String& p_name) {
-
- //EditorNode::get_singleton()->remove_tool_menu_item(p_name);
-}
-
-Ref<SpatialEditorGizmo> EditorPlugin::create_spatial_gizmo(Spatial* p_spatial) {
- //??
- if (get_script_instance() && get_script_instance()->has_method("create_spatial_gizmo")) {
- return get_script_instance()->call("create_spatial_gizmo",p_spatial);
- }
-
- return Ref<SpatialEditorGizmo>();
-}
-
-bool EditorPlugin::forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) {
-
- if (get_script_instance() && get_script_instance()->has_method("forward_canvas_gui_input")) {
- return get_script_instance()->call("forward_canvas_gui_input",p_canvas_xform,p_event);
- }
- return false;
-}
-
-void EditorPlugin::forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control *p_canvas) {
-
- if (get_script_instance() && get_script_instance()->has_method("forward_draw_over_canvas")) {
- get_script_instance()->call("forward_draw_over_canvas",p_canvas_xform,p_canvas);
- }
-}
-
-void EditorPlugin::update_canvas() {
- CanvasItemEditor::get_singleton()->get_viewport_control()->update();
-}
-
-bool EditorPlugin::forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) {
-
- if (get_script_instance() && get_script_instance()->has_method("forward_spatial_gui_input")) {
- return get_script_instance()->call("forward_spatial_gui_input",p_camera,p_event);
- }
-
- return false;
-}
-String EditorPlugin::get_name() const {
-
- if (get_script_instance() && get_script_instance()->has_method("get_name")) {
- return get_script_instance()->call("get_name");
- }
-
- return String();
-
-}
-bool EditorPlugin::has_main_screen() const {
-
- if (get_script_instance() && get_script_instance()->has_method("has_main_screen")) {
- return get_script_instance()->call("has_main_screen");
- }
-
- return false;
-
-}
-void EditorPlugin::make_visible(bool p_visible) {
-
- if (get_script_instance() && get_script_instance()->has_method("make_visible")) {
- get_script_instance()->call("make_visible",p_visible);
- }
-}
-
-
-void EditorPlugin::edit(Object *p_object) {
-
- if (get_script_instance() && get_script_instance()->has_method("edit")) {
- get_script_instance()->call("edit",p_object);
- }
-
-}
-
-bool EditorPlugin::handles(Object *p_object) const {
-
- if (get_script_instance() && get_script_instance()->has_method("handles")) {
- return get_script_instance()->call("handles",p_object);
- }
-
- return false;
-}
-Dictionary EditorPlugin::get_state() const {
-
- if (get_script_instance() && get_script_instance()->has_method("get_state")) {
- return get_script_instance()->call("get_state");
- }
-
- return Dictionary();
-}
-
-void EditorPlugin::set_state(const Dictionary& p_state) {
-
- if (get_script_instance() && get_script_instance()->has_method("set_state")) {
- get_script_instance()->call("set_state",p_state);
- }
-}
-
-void EditorPlugin::clear() {
-
- if (get_script_instance() && get_script_instance()->has_method("clear")) {
- get_script_instance()->call("clear");
- }
-
-}
-
-// if editor references external resources/scenes, save them
-void EditorPlugin::save_external_data() {
-
- if (get_script_instance() && get_script_instance()->has_method("save_external_data")) {
- get_script_instance()->call("save_external_data");
- }
-}
-
-// if changes are pending in editor, apply them
-void EditorPlugin::apply_changes() {
-
- if (get_script_instance() && get_script_instance()->has_method("apply_changes")) {
- get_script_instance()->call("apply_changes");
- }
-}
-
-void EditorPlugin::get_breakpoints(List<String> *p_breakpoints) {
-
- if (get_script_instance() && get_script_instance()->has_method("get_breakpoints")) {
- PoolStringArray arr = get_script_instance()->call("get_breakpoints");
- for(int i=0;i<arr.size();i++)
- p_breakpoints->push_back(arr[i]);
- }
-
-}
-bool EditorPlugin::get_remove_list(List<Node*> *p_list) {
-
- return false;
-}
-
-void EditorPlugin::restore_global_state() {}
-void EditorPlugin::save_global_state() {}
-
-void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
-
- if (get_script_instance() && get_script_instance()->has_method("set_window_layout")) {
- get_script_instance()->call("set_window_layout", p_layout);
- }
-}
-
-void EditorPlugin::get_window_layout(Ref<ConfigFile> p_layout){
-
- if (get_script_instance() && get_script_instance()->has_method("get_window_layout")) {
- get_script_instance()->call("get_window_layout", p_layout);
- }
-}
-
-void EditorPlugin::queue_save_layout() const {
-
- EditorNode::get_singleton()->save_layout();
-}
-
-EditorSelection* EditorPlugin::get_selection() {
- return EditorNode::get_singleton()->get_editor_selection();
-}
-
-
-EditorSettings *EditorPlugin::get_editor_settings() {
- return EditorSettings::get_singleton();
-}
-
-EditorResourcePreview *EditorPlugin::get_resource_previewer() {
- return EditorResourcePreview::get_singleton();
-}
-
-Control *EditorPlugin::get_base_control() {
-
- return EditorNode::get_singleton()->get_gui_base();
-}
-
-void EditorPlugin::make_bottom_panel_item_visible(Control * p_item) {
-
- EditorNode::get_singleton()->make_bottom_panel_item_visible(p_item);
-}
-
-void EditorPlugin::hide_bottom_panel() {
-
- EditorNode::get_singleton()->hide_bottom_panel();
-}
-
-void EditorPlugin::inspect_object(Object *p_obj,const String& p_for_property) {
-
- EditorNode::get_singleton()->push_item(p_obj,p_for_property);
-}
-
-EditorFileSystem *EditorPlugin::get_resource_file_system() {
- return EditorFileSystem::get_singleton();
-}
-
-void EditorPlugin::_bind_methods() {
-
- ClassDB::bind_method(_MD("add_control_to_container","container","control:Control"),&EditorPlugin::add_control_to_container);
- ClassDB::bind_method(_MD("add_control_to_bottom_panel:ToolButton","control:Control","title"),&EditorPlugin::add_control_to_bottom_panel);
- ClassDB::bind_method(_MD("add_control_to_dock","slot","control:Control"),&EditorPlugin::add_control_to_dock);
- ClassDB::bind_method(_MD("remove_control_from_docks","control:Control"),&EditorPlugin::remove_control_from_docks);
- ClassDB::bind_method(_MD("remove_control_from_bottom_panel","control:Control"),&EditorPlugin::remove_control_from_bottom_panel);
- //ClassDB::bind_method(_MD("add_tool_menu_item", "name", "handler", "callback", "ud"),&EditorPlugin::add_tool_menu_item,DEFVAL(Variant()));
- ClassDB::bind_method(_MD("add_tool_submenu_item", "name", "submenu:PopupMenu"),&EditorPlugin::add_tool_submenu_item);
- //ClassDB::bind_method(_MD("remove_tool_menu_item", "name"),&EditorPlugin::remove_tool_menu_item);
- ClassDB::bind_method(_MD("add_custom_type","type","base","script:Script","icon:Texture"),&EditorPlugin::add_custom_type);
- ClassDB::bind_method(_MD("remove_custom_type","type"),&EditorPlugin::remove_custom_type);
- ClassDB::bind_method(_MD("get_editor_viewport:Control"), &EditorPlugin::get_editor_viewport);
-
- ClassDB::bind_method(_MD("get_resource_previewer:EditorResourcePreview"),&EditorPlugin::get_resource_previewer);
- ClassDB::bind_method(_MD("get_resource_filesystem:EditorFileSystem"),&EditorPlugin::get_resource_file_system);
-
- ClassDB::bind_method(_MD("inspect_object","object","for_property"),&EditorPlugin::inspect_object,DEFVAL(String()));
- ClassDB::bind_method(_MD("update_canvas"),&EditorPlugin::update_canvas);
-
- ClassDB::bind_method(_MD("make_bottom_panel_item_visible","item:Control"), &EditorPlugin::make_bottom_panel_item_visible);
- ClassDB::bind_method(_MD("hide_bottom_panel"), &EditorPlugin::hide_bottom_panel);
-
- ClassDB::bind_method(_MD("get_base_control:Control"),&EditorPlugin::get_base_control);
- ClassDB::bind_method(_MD("get_undo_redo:UndoRedo"),&EditorPlugin::_get_undo_redo);
- ClassDB::bind_method(_MD("get_selection:EditorSelection"),&EditorPlugin::get_selection);
- ClassDB::bind_method(_MD("get_editor_settings:EditorSettings"),&EditorPlugin::get_editor_settings);
- ClassDB::bind_method(_MD("queue_save_layout"),&EditorPlugin::queue_save_layout);
- ClassDB::bind_method(_MD("edit_resource"),&EditorPlugin::edit_resource);
-
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"forward_canvas_gui_input",PropertyInfo(Variant::TRANSFORM2D,"canvas_xform"),PropertyInfo(Variant::INPUT_EVENT,"event")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("forward_draw_over_canvas",PropertyInfo(Variant::TRANSFORM2D,"canvas_xform"),PropertyInfo(Variant::OBJECT,"canvas:Control")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"forward_spatial_gui_input",PropertyInfo(Variant::OBJECT,"camera",PROPERTY_HINT_RESOURCE_TYPE,"Camera"),PropertyInfo(Variant::INPUT_EVENT,"event")));
- MethodInfo gizmo = MethodInfo(Variant::OBJECT,"create_spatial_gizmo",PropertyInfo(Variant::OBJECT,"for_spatial:Spatial"));
- gizmo.return_val.hint=PROPERTY_HINT_RESOURCE_TYPE;
- gizmo.return_val.hint_string="EditorSpatialGizmo";
- ClassDB::add_virtual_method(get_class_static(),gizmo);
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::STRING,"get_name"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"has_main_screen"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("make_visible",PropertyInfo(Variant::BOOL,"visible")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("edit",PropertyInfo(Variant::OBJECT,"object")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"handles",PropertyInfo(Variant::OBJECT,"object")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::DICTIONARY,"get_state"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("set_state",PropertyInfo(Variant::DICTIONARY,"state")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("clear"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("save_external_data"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("apply_changes"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::POOL_STRING_ARRAY,"get_breakpoints"));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("set_window_layout",PropertyInfo(Variant::OBJECT,"layout",PROPERTY_HINT_RESOURCE_TYPE,"ConfigFile")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo("get_window_layout",PropertyInfo(Variant::OBJECT,"layout",PROPERTY_HINT_RESOURCE_TYPE,"ConfigFile")));
-
- BIND_CONSTANT( CONTAINER_TOOLBAR );
- BIND_CONSTANT( CONTAINER_SPATIAL_EDITOR_MENU );
- BIND_CONSTANT( CONTAINER_SPATIAL_EDITOR_SIDE );
- BIND_CONSTANT( CONTAINER_SPATIAL_EDITOR_BOTTOM );
- BIND_CONSTANT( CONTAINER_CANVAS_EDITOR_MENU );
- BIND_CONSTANT( CONTAINER_CANVAS_EDITOR_SIDE );
- BIND_CONSTANT( CONTAINER_PROPERTY_EDITOR_BOTTOM );
-
-
- BIND_CONSTANT( DOCK_SLOT_LEFT_UL );
- BIND_CONSTANT( DOCK_SLOT_LEFT_BL );
- BIND_CONSTANT( DOCK_SLOT_LEFT_UR );
- BIND_CONSTANT( DOCK_SLOT_LEFT_BR );
- BIND_CONSTANT( DOCK_SLOT_RIGHT_UL );
- BIND_CONSTANT( DOCK_SLOT_RIGHT_BL );
- BIND_CONSTANT( DOCK_SLOT_RIGHT_UR );
- BIND_CONSTANT( DOCK_SLOT_RIGHT_BR );
- BIND_CONSTANT( DOCK_SLOT_MAX );
-
-}
-
-EditorPlugin::EditorPlugin()
-{
- undo_redo=NULL;
-}
-
-
-EditorPlugin::~EditorPlugin()
-{
-}
-
-
-
-EditorPluginCreateFunc EditorPlugins::creation_funcs[MAX_CREATE_FUNCS];
-
-int EditorPlugins::creation_func_count=0;
diff --git a/tools/editor/editor_plugin.h b/tools/editor/editor_plugin.h
deleted file mode 100644
index cf998dd55b..0000000000
--- a/tools/editor/editor_plugin.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*************************************************************************/
-/* editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_PLUGIN_H
-#define EDITOR_PLUGIN_H
-
-#include "scene/gui/tool_button.h"
-#include "scene/main/node.h"
-#include "scene/resources/texture.h"
-#include "undo_redo.h"
-#include "io/config_file.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class EditorNode;
-class Spatial;
-class Camera;
-class EditorSelection;
-class EditorImportExport;
-class EditorSettings;
-class SpatialEditorGizmo;
-class EditorImportPlugin;
-class EditorExportPlugin;
-class EditorResourcePreview;
-class EditorFileSystem;
-
-class EditorPlugin : public Node {
-
- GDCLASS( EditorPlugin, Node );
-friend class EditorData;
- UndoRedo *undo_redo;
-
- UndoRedo* _get_undo_redo() { return undo_redo; }
-
-protected:
-
- static void _bind_methods();
- UndoRedo& get_undo_redo() { return *undo_redo; }
-
- void add_custom_type(const String& p_type, const String& p_base,const Ref<Script>& p_script, const Ref<Texture>& p_icon);
- void remove_custom_type(const String& p_type);
-
-
-public:
-
- enum CustomControlContainer {
- CONTAINER_TOOLBAR,
- CONTAINER_SPATIAL_EDITOR_MENU,
- CONTAINER_SPATIAL_EDITOR_SIDE,
- CONTAINER_SPATIAL_EDITOR_BOTTOM,
- CONTAINER_CANVAS_EDITOR_MENU,
- CONTAINER_CANVAS_EDITOR_SIDE,
- CONTAINER_CANVAS_EDITOR_BOTTOM,
- CONTAINER_PROPERTY_EDITOR_BOTTOM
- };
-
- enum DockSlot {
- DOCK_SLOT_LEFT_UL,
- DOCK_SLOT_LEFT_BL,
- DOCK_SLOT_LEFT_UR,
- DOCK_SLOT_LEFT_BR,
- DOCK_SLOT_RIGHT_UL,
- DOCK_SLOT_RIGHT_BL,
- DOCK_SLOT_RIGHT_UR,
- DOCK_SLOT_RIGHT_BR,
- DOCK_SLOT_MAX
- };
-
- //TODO: send a resoucre for editing to the editor node?
-
- void add_control_to_container(CustomControlContainer p_location, Control *p_control);
- ToolButton *add_control_to_bottom_panel(Control *p_control, const String &p_title);
- void add_control_to_dock(DockSlot p_slot,Control *p_control);
- void remove_control_from_docks(Control *p_control);
- void remove_control_from_bottom_panel(Control *p_control);
- Control* get_editor_viewport();
- void edit_resource(const Ref<Resource>& p_resource);
-
- void add_tool_menu_item(const String& p_name, Object *p_handler, const String& p_callback, const Variant& p_ud = Variant());
- void add_tool_submenu_item(const String& p_name, Object *p_submenu);
- void remove_tool_menu_item(const String& p_name);
-
- virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial* p_spatial);
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform, const InputEvent& p_event);
- virtual void forward_draw_over_canvas(const Transform2D& p_canvas_xform,Control *p_canvas);
- virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event);
- virtual String get_name() const;
- virtual bool has_main_screen() const;
- virtual void make_visible(bool p_visible);
- virtual void selected_notify() {}//notify that it was raised by the user, not the editor
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_node) const;
- virtual Dictionary get_state() const; //save editor state so it can't be reloaded when reloading scene
- virtual void set_state(const Dictionary& p_state) ; //restore editor state (likely was saved with the scene)
- virtual void clear() ; // clear any temporary data in te editor, reset it (likely new scene or load another scene)
- virtual void save_external_data() ; // if editor references external resources/scenes, save them
- virtual void apply_changes() ; // if changes are pending in editor, apply them
- virtual void get_breakpoints(List<String> *p_breakpoints);
- 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
-
- void update_canvas();
-
- virtual void inspect_object(Object *p_obj,const String& p_for_property=String());
-
- void queue_save_layout() const;
-
- Control *get_base_control();
-
- void make_bottom_panel_item_visible(Control *p_item);
- void hide_bottom_panel();
-
- EditorSelection* get_selection();
- //EditorImportExport *get_import_export();
- EditorSettings *get_editor_settings();
- EditorResourcePreview *get_resource_previewer();
- EditorFileSystem *get_resource_file_system();
-
- virtual void restore_global_state();
- virtual void save_global_state();
-
- EditorPlugin();
- virtual ~EditorPlugin();
-
-};
-
-VARIANT_ENUM_CAST( EditorPlugin::CustomControlContainer );
-VARIANT_ENUM_CAST( EditorPlugin::DockSlot );
-
-
-typedef EditorPlugin* (*EditorPluginCreateFunc)(EditorNode *);
-
-class EditorPlugins {
-
- enum {
- MAX_CREATE_FUNCS=64
- };
-
- static EditorPluginCreateFunc creation_funcs[MAX_CREATE_FUNCS];
- static int creation_func_count;
-
- template<class T>
- static EditorPlugin *creator(EditorNode *p_node) {
- return memnew( T(p_node) );
- }
-
-public:
-
- static int get_plugin_count() { return creation_func_count; }
- static EditorPlugin* create(int p_idx,EditorNode* p_editor) { ERR_FAIL_INDEX_V(p_idx,creation_func_count,NULL); return creation_funcs[p_idx](p_editor); }
-
- template<class T>
- static void add_by_type() {
- add_create_func(creator<T>);
- }
-
- static void add_create_func(EditorPluginCreateFunc p_func) {
-
- ERR_FAIL_COND(creation_func_count>=MAX_CREATE_FUNCS);
- creation_funcs[creation_func_count++]=p_func;
- }
-
-};
-
-
-
-
-
-
-
-
-#endif
diff --git a/tools/editor/editor_plugin_settings.cpp b/tools/editor/editor_plugin_settings.cpp
deleted file mode 100644
index 2b6828e82f..0000000000
--- a/tools/editor/editor_plugin_settings.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/*************************************************************************/
-/* editor_plugin_settings.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_plugin_settings.h"
-
-#include "scene/gui/margin_container.h"
-#include "io/config_file.h"
-#include "os/file_access.h"
-#include "os/main_loop.h"
-#include "globals.h"
-#include "editor_node.h"
-
-void EditorPluginSettings::_notification(int p_what) {
-
- if (p_what==MainLoop::NOTIFICATION_WM_FOCUS_IN) {
- update_plugins();
- }
-}
-
-void EditorPluginSettings::update_plugins() {
-
-
- plugin_list->clear();
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- Error err = da->change_dir("res://addons");
- if (err!=OK) {
- memdelete(da);
- return;
- }
-
- updating=true;
-
- TreeItem *root = plugin_list->create_item();
-
- da->list_dir_begin();
-
- String d = da->get_next();
-
- Vector<String> plugins;
-
- while(d!=String()) {
-
- bool dir = da->current_is_dir();
- String path = "res://addons/"+d+"/plugin.cfg";
-
- if (dir && FileAccess::exists(path)) {
-
- plugins.push_back(d);
- }
-
- d = da->get_next();
- }
-
- da->list_dir_end();
- memdelete(da);
-
- plugins.sort();
-
- Vector<String> active_plugins = GlobalConfig::get_singleton()->get("plugins/active");
-
- for(int i=0;i<plugins.size();i++) {
-
- Ref<ConfigFile> cf;
- cf.instance();
- String path = "res://addons/"+plugins[i]+"/plugin.cfg";
-
- Error err = cf->load(path);
-
- if (err!=OK) {
- WARN_PRINTS("Can't load plugin config: "+path);
- } else if (!cf->has_section_key("plugin","name")) {
- WARN_PRINTS("Plugin misses plugin/name: "+path);
- } else if (!cf->has_section_key("plugin","author")) {
- WARN_PRINTS("Plugin misses plugin/author: "+path);
- } else if (!cf->has_section_key("plugin","version")) {
- WARN_PRINTS("Plugin misses plugin/version: "+path);
- } else if (!cf->has_section_key("plugin","description")) {
- WARN_PRINTS("Plugin misses plugin/description: "+path);
- } else if (!cf->has_section_key("plugin","script")) {
- WARN_PRINTS("Plugin misses plugin/script: "+path);
- } else {
-
- String d = plugins[i];
- String name = cf->get_value("plugin","name");
- String author = cf->get_value("plugin","author");
- String version = cf->get_value("plugin","version");
- String description = cf->get_value("plugin","description");
- String script = cf->get_value("plugin","script");
-
- TreeItem *item = plugin_list->create_item(root);
- item->set_text(0,name);
- item->set_tooltip(0,"Name: "+name+"\nPath: "+path+"\nMain Script: "+script);
- item->set_metadata(0,d);
- item->set_text(1,version);
- item->set_metadata(1,script);
- item->set_text(2,author);
- item->set_metadata(2,description);
- item->set_cell_mode(3,TreeItem::CELL_MODE_RANGE);
- item->set_range_config(3,0,1,1);
- item->set_text(3,"Inactive,Active");
- item->set_editable(3,true);
-
- if (EditorNode::get_singleton()->is_addon_plugin_enabled(d)) {
- item->set_custom_color(3,Color(0.2,1,0.2));
- item->set_range(3,1);
- } else {
- item->set_custom_color(3,Color(1,0.2,0.2));
- item->set_range(3,0);
- }
- }
-
- }
-
- updating=false;
-
-}
-
-
-void EditorPluginSettings::_plugin_activity_changed() {
-
- if (updating)
- return;
-
- TreeItem *ti=plugin_list->get_edited();
- ERR_FAIL_COND(!ti);
- bool active = ti->get_range(3);
- String name = ti->get_metadata(0);
-
- EditorNode::get_singleton()->set_addon_plugin_enabled(name,active);
-
- bool is_active = EditorNode::get_singleton()->is_addon_plugin_enabled(name);
-
- if (is_active!=active) {
- updating=true;
- ti->set_range(3,is_active?1:0);
- updating=false;
- }
-
- if (is_active)
- ti->set_custom_color(3,Color(0.2,1,0.2));
- else
- ti->set_custom_color(3,Color(1,0.2,0.2));
-
-
-}
-
-void EditorPluginSettings::_bind_methods() {
-
- ClassDB::bind_method("update_plugins",&EditorPluginSettings::update_plugins);
- ClassDB::bind_method("_plugin_activity_changed",&EditorPluginSettings::_plugin_activity_changed);
-}
-
-EditorPluginSettings::EditorPluginSettings() {
-
- HBoxContainer *title_hb = memnew( HBoxContainer );
- title_hb->add_child(memnew( Label(TTR("Installed Plugins:"))));
- title_hb->add_spacer();
- update_list = memnew( Button(TTR("Update")) );
- update_list->connect("pressed",this,"update_plugins");
- title_hb->add_child(update_list);
- add_child(title_hb);
-
- plugin_list = memnew( Tree );
- plugin_list->set_v_size_flags(SIZE_EXPAND_FILL);
- plugin_list->set_columns(4);
- plugin_list->set_column_titles_visible(true);
- plugin_list->set_column_title(0,TTR("Name:"));
- plugin_list->set_column_title(1,TTR("Version:"));
- plugin_list->set_column_title(2,TTR("Author:"));
- plugin_list->set_column_title(3,TTR("Status:"));
- plugin_list->set_column_expand(0,true);
- plugin_list->set_column_expand(1,false);
- plugin_list->set_column_expand(2,false);
- plugin_list->set_column_expand(3,false);
- plugin_list->set_column_min_width(1,100);
- plugin_list->set_column_min_width(2,250);
- plugin_list->set_column_min_width(3,80);
- plugin_list->set_hide_root(true);
- plugin_list->connect("item_edited",this,"_plugin_activity_changed");
-
-
- MarginContainer *mc = memnew( MarginContainer );
- mc->add_child(plugin_list);
- mc->set_v_size_flags(SIZE_EXPAND_FILL);
-
- add_child(mc);
-
- updating=false;
-
-}
diff --git a/tools/editor/editor_profiler.cpp b/tools/editor/editor_profiler.cpp
deleted file mode 100644
index 94ec059ea7..0000000000
--- a/tools/editor/editor_profiler.cpp
+++ /dev/null
@@ -1,784 +0,0 @@
-/*************************************************************************/
-/* editor_profiler.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_profiler.h"
-
-#include "editor_settings.h"
-#include "os/os.h"
-
-void EditorProfiler::_make_metric_ptrs(Metric& m) {
-
- for(int i=0;i<m.categories.size();i++) {
- m.category_ptrs[m.categories[i].signature]=&m.categories[i];
- for(int j=0;j<m.categories[i].items.size();j++) {
- m.item_ptrs[m.categories[i].items[j].signature]=&m.categories[i].items[j];
- }
- }
-}
-
-void EditorProfiler::add_frame_metric(const Metric& p_metric,bool p_final) {
-
- ++last_metric;
- if (last_metric>=frame_metrics.size())
- last_metric=0;
-
-
- frame_metrics[last_metric]=p_metric;
- _make_metric_ptrs(frame_metrics[last_metric]);
-
- updating_frame=true;
- cursor_metric_edit->set_max(frame_metrics[last_metric].frame_number);
- cursor_metric_edit->set_min(MAX(frame_metrics[last_metric].frame_number-frame_metrics.size(),0));
-
-
- if (!seeking) {
- cursor_metric_edit->set_value(frame_metrics[last_metric].frame_number);
- if (hover_metric!=-1) {
- hover_metric++;
- if (hover_metric>=frame_metrics.size()) {
- hover_metric=0;
- }
- }
-
- }
- updating_frame=false;
-
- if (!frame_delay->is_processing()) {
-
- frame_delay->set_wait_time(p_final?0.1:1);
- frame_delay->start();
- }
-
- if (!plot_delay->is_processing()) {
- plot_delay->set_wait_time(0.1);
- plot_delay->start();
- }
-
-}
-
-
-
-void EditorProfiler::clear() {
-
- int metric_size=EditorSettings::get_singleton()->get("debugger/profiler_frame_history_size");
- metric_size = CLAMP(metric_size,60,1024);
- frame_metrics.clear();
- frame_metrics.resize(metric_size);
- last_metric=-1;
- variables->clear();
- //activate->set_pressed(false);
- plot_sigs.clear();
- plot_sigs.insert("fixed_frame_time");
- plot_sigs.insert("category_frame_time");
-
- updating_frame=true;
- cursor_metric_edit->set_min(0);
- cursor_metric_edit->set_max(0);
- cursor_metric_edit->set_value(0);
- updating_frame=false;
- hover_metric=-1;
- seeking=false;
-}
-
-static String _get_percent_txt(float p_value,float p_total) {
- if (p_total==0)
- p_total=0.00001;
- return String::num((p_value/p_total)*100,1)+"%";
-}
-
-
-String EditorProfiler::_get_time_as_text(Metric &m,float p_time,int p_calls) {
-
- int dmode = display_mode->get_selected();
-
-
- if (dmode==DISPLAY_FRAME_TIME) {
- return rtos(p_time);
- } else if (dmode==DISPLAY_AVERAGE_TIME) {
- if (p_calls==0)
- return "0";
- else
- return rtos(p_time/p_calls);
- } else if (dmode==DISPLAY_FRAME_PERCENT) {
- return _get_percent_txt(p_time,m.frame_time);
- } else if (dmode==DISPLAY_FIXED_FRAME_PERCENT) {
-
- return _get_percent_txt(p_time,m.fixed_frame_time);
- }
-
- return "err";
-}
-
-Color EditorProfiler::_get_color_from_signature(const StringName& p_signature) const {
-
- double rot = ABS(double(p_signature.hash())/double(0x7FFFFFFF));
- Color c;
- c.set_hsv(rot,1,1);
- return c;
-
-}
-
-void EditorProfiler::_item_edited() {
-
- if (updating_frame)
- return;
-
- TreeItem *item=variables->get_edited();
- if (!item)
- return;
- StringName signature=item->get_metadata(0);
- bool checked=item->is_checked(0);
-
-
- if (checked)
- plot_sigs.insert(signature);
- else
- plot_sigs.erase(signature);
-
- if (!frame_delay->is_processing()) {
- frame_delay->set_wait_time(0.1);
- frame_delay->start();
- }
-
- _update_plot();
-}
-
-void EditorProfiler::_update_plot() {
-
- int w = graph->get_size().width;
- int h = graph->get_size().height;
-
- bool reset_texture=false;
-
- int desired_len = w * h * 4;
-
- if (graph_image.size()!=desired_len) {
- reset_texture=true;
- graph_image.resize(desired_len);
- }
-
-
- PoolVector<uint8_t>::Write wr = graph_image.write();
-
-
-
- //clear
- for(int i=0;i<desired_len;i+=4) {
- wr[i+0]=0;
- wr[i+1]=0;
- wr[i+2]=0;
- wr[i+3]=255;
- }
-
-
- //find highest value
-
- bool use_self = display_time->get_selected()==DISPLAY_SELF_TIME;
- float highest=0;
-
- for(int i=0;i<frame_metrics.size();i++) {
- Metric &m = frame_metrics[i];
- if (!m.valid)
- continue;
-
- for (Set<StringName>::Element *E=plot_sigs.front();E;E=E->next()) {
-
- Map<StringName,Metric::Category*>::Element *F=m.category_ptrs.find(E->get());
- if (F) {
- highest=MAX(F->get()->total_time,highest);
- }
-
- Map<StringName,Metric::Category::Item*>::Element *G=m.item_ptrs.find(E->get());
- if (G) {
- if (use_self) {
- highest=MAX(G->get()->self,highest);
- } else {
- highest=MAX(G->get()->total,highest);
- }
- }
- }
- }
-
- if (highest>0) {
- //means some data exists..
- highest*=1.2; //leave some upper room
- graph_height=highest;
-
- Vector<int> columnv;
- columnv.resize(h*4);
-
- int *column = columnv.ptr();
-
- Map<StringName,int> plot_prev;
- //Map<StringName,int> plot_max;
-
- uint64_t time = OS::get_singleton()->get_ticks_usec();
-
- for(int i=0;i<w;i++) {
-
-
- for(int j=0;j<h*4;j++) {
- column[j]=0;
- }
-
- int current = i*frame_metrics.size()/w;
- int next = (i+1)*frame_metrics.size()/w;
- if (next>frame_metrics.size()) {
- next=frame_metrics.size();
- }
- if (next==current)
- next=current+1; //just because for loop must work
-
- for (Set<StringName>::Element *E=plot_sigs.front();E;E=E->next()) {
-
- int plot_pos=-1;
-
- for(int j=current;j<next;j++) {
-
- //wrap
- int idx = last_metric+1+j;
- while( idx >= frame_metrics.size() ) {
- idx-=frame_metrics.size();
- }
-
- //get
- Metric &m = frame_metrics[idx];
- if (m.valid==false)
- continue; //skip because invalid
-
-
- float value=0;
-
- Map<StringName,Metric::Category*>::Element *F=m.category_ptrs.find(E->get());
- if (F) {
- value=F->get()->total_time;
- }
-
- Map<StringName,Metric::Category::Item*>::Element *G=m.item_ptrs.find(E->get());
- if (G) {
- if (use_self) {
- value=G->get()->self;
- } else {
- value=G->get()->total;
- }
- }
-
-
- plot_pos = MAX( CLAMP(int(value*h/highest),0,h-1), plot_pos );
-
-
- }
-
- int prev_plot=plot_pos;
- Map<StringName,int>::Element *H=plot_prev.find(E->get());
- if (H) {
- prev_plot=H->get();
- H->get()=plot_pos;
- } else {
- plot_prev[E->get()]=plot_pos;
- }
-
- if (plot_pos==-1 && prev_plot==-1) {
- //don't bother drawing
- continue;
- }
-
- if (prev_plot!=-1 && plot_pos==-1) {
-
- plot_pos=prev_plot;
- }
-
- if (prev_plot==-1 && plot_pos!=-1) {
- prev_plot=plot_pos;
- }
-
- plot_pos = h- plot_pos -1;
- prev_plot = h- prev_plot -1;
-
- if (prev_plot > plot_pos) {
- SWAP(prev_plot,plot_pos);
- }
-
- Color col = _get_color_from_signature(E->get());
-
- for(int j=prev_plot;j<=plot_pos;j++) {
-
- column[j*4+0]+=Math::fast_ftoi(CLAMP(col.r*255,0,255));
- column[j*4+1]+=Math::fast_ftoi(CLAMP(col.g*255,0,255));
- column[j*4+2]+=Math::fast_ftoi(CLAMP(col.b*255,0,255));
- column[j*4+3]+=1;
-
- }
- }
-
-
- for(int j=0;j<h*4;j+=4) {
-
- int a = column[j+3];
- if (a>0) {
- column[j+0]/=a;
- column[j+1]/=a;
- column[j+2]/=a;
-
- }
-
- uint8_t r = uint8_t(column[j+0]);
- uint8_t g = uint8_t(column[j+1]);
- uint8_t b = uint8_t(column[j+2]);
-
- int widx = ((j>>2)*w+i)*4;
- wr[widx+0]=r;
- wr[widx+1]=g;
- wr[widx+2]=b;
- wr[widx+3]=255;
- }
- }
-
- time = OS::get_singleton()->get_ticks_usec() - time;
- //print_line("Taken: "+rtos(USEC_TO_SEC(time)));
-
- }
-
-
- wr = PoolVector<uint8_t>::Write();
-
- Image img(w,h,0,Image::FORMAT_RGBA8,graph_image);
-
- if (reset_texture) {
-
- if (graph_texture.is_null()) {
- graph_texture.instance();
- }
- graph_texture->create(img.get_width(),img.get_height(),img.get_format(),Texture::FLAG_VIDEO_SURFACE);
-
- }
-
- graph_texture->set_data(img);
-
-
- graph->set_texture(graph_texture);
- graph->update();
-
-}
-
-void EditorProfiler::_update_frame() {
-
- int cursor_metric = _get_cursor_index();
-
-
- ERR_FAIL_INDEX(cursor_metric,frame_metrics.size());
-
- updating_frame=true;
- variables->clear();
-
- TreeItem* root = variables->create_item();
- Metric &m = frame_metrics[cursor_metric];
-
-
- int dtime = display_time->get_selected();
-
-
- for(int i=0;i<m.categories.size();i++) {
-
- TreeItem *category = variables->create_item(root);
- category->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- category->set_editable(0,true);
- category->set_metadata(0,m.categories[i].signature);
- category->set_text(0,String(m.categories[i].name));
- category->set_text(1,_get_time_as_text(m,m.categories[i].total_time,1));
-
- if (plot_sigs.has(m.categories[i].signature)) {
- category->set_checked(0,true);
- category->set_custom_bg_color(0,Color(0,0,0));
- category->set_custom_color(0,_get_color_from_signature(m.categories[i].signature));
- }
-
-
- for(int j=0;j<m.categories[i].items.size();j++) {
- Metric::Category::Item &it = m.categories[i].items[j];
-
- TreeItem *item = variables->create_item(category);
- item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- item->set_editable(0,true);
- item->set_text(0,it.name);
- item->set_metadata(0,it.signature);
- item->set_metadata(1,it.script);
- item->set_metadata(2,it.line);
- item->set_tooltip(0,it.script+":"+itos(it.line));
-
- float time = dtime == DISPLAY_SELF_TIME ? it.self : it.total;
-
- item->set_text(1,_get_time_as_text(m,time,it.calls));
-
- item->set_text(2,itos(it.calls));
-
- if (plot_sigs.has(it.signature)) {
- item->set_checked(0,true);
- item->set_custom_bg_color(0,Color(0,0,0));
- item->set_custom_color(0,_get_color_from_signature(it.signature));
- }
-
- }
- }
-
- updating_frame=false;
-
-}
-
-
-void EditorProfiler::_activate_pressed() {
-
- if (activate->is_pressed()) {
- clear();
- activate->set_icon(get_icon("Stop","EditorIcons"));
- activate->set_text(TTR("Stop Profiling"));
- } else {
- activate->set_icon(get_icon("Play","EditorIcons"));
- activate->set_text(TTR("Start Profiling"));
-
-
- }
- emit_signal("enable_profiling",activate->is_pressed());
-
-}
-
-
-void EditorProfiler::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- activate->set_icon(get_icon("Play","EditorIcons"));
- }
-}
-
-void EditorProfiler::_graph_tex_draw() {
-
- if (last_metric<0)
- return;
- if (seeking) {
-
- int max_frames = frame_metrics.size();
- int frame = cursor_metric_edit->get_value() - (frame_metrics[last_metric].frame_number-max_frames+1);
- if (frame<0)
- frame=0;
-
- int cur_x = frame * graph->get_size().x / max_frames;
-
-
- graph->draw_line(Vector2(cur_x,0),Vector2(cur_x,graph->get_size().y),Color(1,1,1,0.8));
- }
-
-
- if (hover_metric!=-1 && frame_metrics[hover_metric].valid) {
-
-
-
- int max_frames = frame_metrics.size();
- int frame = frame_metrics[hover_metric].frame_number - (frame_metrics[last_metric].frame_number-max_frames+1);
- if (frame<0)
- frame=0;
-
- int cur_x = frame * graph->get_size().x / max_frames;
-
- graph->draw_line(Vector2(cur_x,0),Vector2(cur_x,graph->get_size().y),Color(1,1,1,0.4));
-
-
- }
-
-}
-
-void EditorProfiler::_graph_tex_mouse_exit() {
-
- hover_metric=-1;
- graph->update();
-}
-
-
-void EditorProfiler::_cursor_metric_changed(double) {
- if (updating_frame)
- return;
-
-
- graph->update();
- _update_frame();
-
-}
-
-void EditorProfiler::_graph_tex_input(const InputEvent& p_ev){
-
- if (last_metric<0)
- return;
-
- if (
- (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) ||
- (p_ev.type==InputEvent::MOUSE_MOTION) ) {
-
- int x = p_ev.mouse_button.x;
- x=x*frame_metrics.size()/graph->get_size().width;
-
- bool show_hover = x>=0 && x<frame_metrics.size();
-
- if (x<0) {
- x=0;
- }
-
- if (x>=frame_metrics.size()) {
- x=frame_metrics.size()-1;
- }
-
-
-
- int metric=frame_metrics.size()-x-1;
- metric = last_metric-metric;
- while(metric<0) {
- metric+=frame_metrics.size();
- }
-
-
-
- if (show_hover) {
-
- hover_metric=metric;
-
- } else {
- hover_metric=-1;
- }
-
-
- if (p_ev.type==InputEvent::MOUSE_BUTTON || p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
- //cursor_metric=x;
- updating_frame=true;
-
- //metric may be invalid, so look for closest metric that is valid, this makes snap feel better
- bool valid=false;
- for(int i=0;i<frame_metrics.size();i++) {
-
- if (frame_metrics[metric].valid) {
- valid=true;
- break;
- }
-
- metric++;
- if (metric>=frame_metrics.size())
- metric=0;
- }
-
- if (valid)
- cursor_metric_edit->set_value(frame_metrics[metric].frame_number);
-
- updating_frame=false;
-
- if (activate->is_pressed()) {
- if (!seeking) {
- emit_signal("break_request");
- }
- }
-
- seeking=true;
-
- if (!frame_delay->is_processing()) {
- frame_delay->set_wait_time(0.1);
- frame_delay->start();
- }
- }
-
- graph->update();
-
- }
-
-}
-
-int EditorProfiler::_get_cursor_index() const {
-
- if (last_metric<0)
- return 0;
- if (!frame_metrics[last_metric].valid)
- return 0;
-
- int diff = (frame_metrics[last_metric].frame_number-cursor_metric_edit->get_value());
-
- int idx = last_metric - diff;
- while (idx<0) {
- idx+=frame_metrics.size();
- }
-
-
- return idx;
-
-}
-
-void EditorProfiler::disable_seeking() {
-
- seeking=false;
- graph->update();
-
-}
-
-void EditorProfiler::_combo_changed(int) {
-
- _update_frame();
- _update_plot();
-}
-
-void EditorProfiler::_bind_methods() {
-
- ClassDB::bind_method(_MD("_update_frame"),&EditorProfiler::_update_frame);
- ClassDB::bind_method(_MD("_update_plot"),&EditorProfiler::_update_plot);
- ClassDB::bind_method(_MD("_activate_pressed"),&EditorProfiler::_activate_pressed);
- ClassDB::bind_method(_MD("_graph_tex_draw"),&EditorProfiler::_graph_tex_draw);
- ClassDB::bind_method(_MD("_graph_tex_input"),&EditorProfiler::_graph_tex_input);
- ClassDB::bind_method(_MD("_graph_tex_mouse_exit"),&EditorProfiler::_graph_tex_mouse_exit);
- ClassDB::bind_method(_MD("_cursor_metric_changed"),&EditorProfiler::_cursor_metric_changed);
- ClassDB::bind_method(_MD("_combo_changed"),&EditorProfiler::_combo_changed);
-
- ClassDB::bind_method(_MD("_item_edited"),&EditorProfiler::_item_edited);
- ADD_SIGNAL( MethodInfo("enable_profiling",PropertyInfo(Variant::BOOL,"enable")));
- ADD_SIGNAL( MethodInfo("break_request"));
-
-}
-
-void EditorProfiler::set_enabled(bool p_enable) {
-
- activate->set_disabled(!p_enable);
-}
-
-bool EditorProfiler::is_profiling() {
- return activate->is_pressed();
-}
-
-EditorProfiler::EditorProfiler()
-{
-
- HBoxContainer *hb = memnew( HBoxContainer );
- add_child(hb);
- activate = memnew( Button );
- activate->set_toggle_mode(true);
- activate->set_text(TTR("Start Profiling"));
- activate->connect("pressed",this,"_activate_pressed");
- hb->add_child(activate);
-
- hb->add_child( memnew( Label(TTR("Measure:") ) ) );
-
- display_mode = memnew( OptionButton );
- display_mode->add_item(TTR("Frame Time (sec)"));
- display_mode->add_item(TTR("Average Time (sec)"));
- display_mode->add_item(TTR("Frame %"));
- display_mode->add_item(TTR("Fixed Frame %"));
- display_mode->connect("item_selected",this,"_combo_changed");
-
- hb->add_child( display_mode );
-
- hb->add_child( memnew( Label(TTR("Time:") ) ) );
-
- display_time = memnew( OptionButton );
- display_time->add_item(TTR("Inclusive"));
- display_time->add_item(TTR("Self"));
- display_time->connect("item_selected",this,"_combo_changed");
-
- hb->add_child(display_time);
-
- hb->add_spacer();
-
- hb->add_child( memnew( Label(TTR("Frame #:") ) ) );
-
- cursor_metric_edit = memnew( SpinBox );
- cursor_metric_edit->set_h_size_flags(SIZE_FILL);
- hb->add_child(cursor_metric_edit);
- cursor_metric_edit->connect("value_changed",this,"_cursor_metric_changed");
-
- hb->add_constant_override("separation",8);
-
-
-
- h_split = memnew( HSplitContainer );
- add_child(h_split);
- h_split->set_v_size_flags(SIZE_EXPAND_FILL);
-
- variables = memnew( Tree );
- variables->set_custom_minimum_size(Size2(300,0));
- variables->set_hide_folding(true);
- h_split->add_child(variables);
- variables->set_hide_root(true);
- variables->set_columns(3);
- variables->set_column_titles_visible(true);
- variables->set_column_title(0,"Name");
- variables->set_column_expand(0,true);
- variables->set_column_min_width(0,60);
- variables->set_column_title(1,"Time");
- variables->set_column_expand(1,false);
- variables->set_column_min_width(1,60);
- variables->set_column_title(2,"Calls");
- variables->set_column_expand(2,false);
- variables->set_column_min_width(2,60);
- variables->connect("item_edited",this,"_item_edited");
-
-
- graph = memnew( TextureRect );
- graph->set_expand(true);
- graph->set_mouse_filter(MOUSE_FILTER_STOP);
- //graph->set_ignore_mouse(false);
- graph->connect("draw",this,"_graph_tex_draw");
- graph->connect("gui_input",this,"_graph_tex_input");
- graph->connect("mouse_exited",this,"_graph_tex_mouse_exit");
-
- h_split->add_child(graph);
- graph->set_h_size_flags(SIZE_EXPAND_FILL);
-
- add_constant_override("separation",3);
-
- int metric_size=CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size",600)),60,1024);
- frame_metrics.resize(metric_size);
- last_metric=-1;
- //cursor_metric=-1;
- hover_metric=-1;
-
-
- EDITOR_DEF("debugger/profiler_frame_max_functions",64);
-
- //display_mode=DISPLAY_FRAME_TIME;
-
- frame_delay = memnew( Timer );
- frame_delay->set_wait_time(0.1);
- frame_delay->set_one_shot(true);
- add_child(frame_delay);
- frame_delay->connect("timeout",this,"_update_frame");
-
- plot_delay = memnew( Timer );
- plot_delay->set_wait_time(0.1);
- plot_delay->set_one_shot(true);
- add_child(plot_delay);
- plot_delay->connect("timeout",this,"_update_plot");
-
- plot_sigs.insert("fixed_frame_time");
- plot_sigs.insert("category_frame_time");
-
- seeking=false;
- graph_height=1;
-
- //activate->set_disabled(true);
-
-}
diff --git a/tools/editor/editor_resource_preview.cpp b/tools/editor/editor_resource_preview.cpp
deleted file mode 100644
index b4c459a493..0000000000
--- a/tools/editor/editor_resource_preview.cpp
+++ /dev/null
@@ -1,439 +0,0 @@
-/*************************************************************************/
-/* editor_resource_preview.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_resource_preview.h"
-
-#include "editor_settings.h"
-#include "os/file_access.h"
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "globals.h"
-#include "editor_scale.h"
-#include "message_queue.h"
-
-bool EditorResourcePreviewGenerator::handles(const String& p_type) const {
-
- if (get_script_instance() && get_script_instance()->has_method("handles")) {
- return get_script_instance()->call("handles",p_type);
- }
- ERR_EXPLAIN("EditorResourcePreviewGenerator::handles needs to be overriden");
- ERR_FAIL_V(false);
-}
-Ref<Texture> EditorResourcePreviewGenerator::generate(const RES& p_from){
-
- if (get_script_instance() && get_script_instance()->has_method("generate")) {
- return get_script_instance()->call("generate",p_from);
- }
- ERR_EXPLAIN("EditorResourcePreviewGenerator::generate needs to be overriden");
- ERR_FAIL_V(Ref<Texture>());
-
-}
-
-
-Ref<Texture> EditorResourcePreviewGenerator::generate_from_path(const String& p_path) {
-
- if (get_script_instance() && get_script_instance()->has_method("generate_from_path")) {
- return get_script_instance()->call("generate_from_path",p_path);
- }
-
- RES res = ResourceLoader::load(p_path);
- if (!res.is_valid())
- return res;
- return generate(res);
-}
-
-
-void EditorResourcePreviewGenerator::_bind_methods() {
-
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::BOOL,"handles",PropertyInfo(Variant::STRING,"type")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::OBJECT,"generate:Texture",PropertyInfo(Variant::OBJECT,"from",PROPERTY_HINT_RESOURCE_TYPE,"Resource")));
- ClassDB::add_virtual_method(get_class_static(),MethodInfo(Variant::OBJECT,"generate_from_path:Texture",PropertyInfo(Variant::STRING,"path",PROPERTY_HINT_FILE)));
-
-}
-
-EditorResourcePreviewGenerator::EditorResourcePreviewGenerator() {
-
-
-}
-
-
-EditorResourcePreview* EditorResourcePreview::singleton=NULL;
-
-
-void EditorResourcePreview::_thread_func(void *ud) {
-
- EditorResourcePreview *erp=(EditorResourcePreview*)ud;
- erp->_thread();
-
-}
-
-
-void EditorResourcePreview::_preview_ready(const String& p_str,const Ref<Texture>& p_texture,ObjectID id,const StringName& p_func,const Variant& p_ud) {
-
- //print_line("preview is ready");
- preview_mutex->lock();
-
- String path = p_str;
- uint32_t hash=0;
- uint64_t modified_time=0;
-
- if (p_str.begins_with("ID:")) {
- hash=p_str.get_slicec(':',2).to_int();
- path="ID:"+p_str.get_slicec(':',1);
- } else {
- modified_time = FileAccess::get_modified_time(path);
- }
-
- Item item;
- item.order=order++;
- item.preview=p_texture;
- item.last_hash=hash;
- item.modified_time=modified_time;
-
- cache[path]=item;
-
- preview_mutex->unlock();
-
- MessageQueue::get_singleton()->push_call(id,p_func,path,p_texture,p_ud);
-
-}
-
-Ref<Texture> EditorResourcePreview::_generate_preview(const QueueItem& p_item,const String& cache_base) {
-
- String type;
-
- if (p_item.resource.is_valid())
- type=p_item.resource->get_class();
- else
- type=ResourceLoader::get_resource_type(p_item.path);
- //print_line("resource type is: "+type);
-
- if (type=="")
- return Ref<Texture>(); //could not guess type
-
- Ref<Texture> generated;
-
- for(int i=0;i<preview_generators.size();i++) {
-
- if (!preview_generators[i]->handles(type))
- continue;
- if (p_item.resource.is_valid()) {
- generated = preview_generators[i]->generate(p_item.resource);
- } else {
- generated = preview_generators[i]->generate_from_path(p_item.path);
- }
-
- break;
- }
-
- if (!p_item.resource.is_valid()) {
- // cache the preview in case it's a resource on disk
- if (generated.is_valid()) {
- //print_line("was generated");
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- //wow it generated a preview... save cache
- ResourceSaver::save(cache_base+".png",generated);
- FileAccess *f=FileAccess::open(cache_base+".txt",FileAccess::WRITE);
- f->store_line(itos(thumbnail_size));
- f->store_line(itos(FileAccess::get_modified_time(p_item.path)));
- f->store_line(FileAccess::get_md5(p_item.path));
- memdelete(f);
- } else {
- //print_line("was not generated");
-
- }
- }
-
- return generated;
-}
-
-void EditorResourcePreview::_thread() {
-
- //print_line("begin thread");
- while(!exit) {
-
- //print_line("wait for semaphore");
- preview_sem->wait();
- preview_mutex->lock();
-
- //print_line("blue team go");
-
- if (queue.size()) {
-
-
-
- QueueItem item = queue.front()->get();
- queue.pop_front();
-
- if (cache.has(item.path)) {
- //already has it because someone loaded it, just let it know it's ready
- if (item.resource.is_valid()) {
- item.path+=":"+itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below)
- }
-
- _preview_ready(item.path,cache[item.path].preview,item.id,item.function,item.userdata);
-
- preview_mutex->unlock();
- } else {
- preview_mutex->unlock();
-
-
- Ref<Texture> texture;
-
- //print_line("pop from queue "+item.path);
-
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
-
-
- if (item.resource.is_valid()){
-
- texture=_generate_preview(item,String());
- //adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred
- _preview_ready(item.path+":"+itos(item.resource->hash_edited_version()),texture,item.id,item.function,item.userdata);
-
- } else {
-
-
- String temp_path=EditorSettings::get_singleton()->get_settings_path().plus_file("tmp");
- String cache_base = GlobalConfig::get_singleton()->globalize_path(item.path).md5_text();
- cache_base = temp_path.plus_file("resthumb-"+cache_base);
-
- //does not have it, try to load a cached thumbnail
-
- String file = cache_base+".txt";
- //print_line("cachetxt at "+file);
- FileAccess *f=FileAccess::open(file,FileAccess::READ);
- if (!f) {
-
- //print_line("generate because not cached");
-
- //generate
- texture=_generate_preview(item,cache_base);
- } else {
-
- uint64_t modtime = FileAccess::get_modified_time(item.path);
- int tsize = f->get_line().to_int64();
- uint64_t last_modtime = f->get_line().to_int64();
-
- bool cache_valid = true;
-
- if (tsize!=thumbnail_size) {
- cache_valid=false;
- memdelete(f);
- } else if (last_modtime!=modtime) {
-
- String last_md5 = f->get_line();
- String md5 = FileAccess::get_md5(item.path);
- memdelete(f);
-
- if (last_md5!=md5) {
-
- cache_valid=false;
- } else {
- //update modified time
-
- f=FileAccess::open(file,FileAccess::WRITE);
- f->store_line(itos(modtime));
- f->store_line(md5);
- memdelete(f);
- }
- } else {
- memdelete(f);
- }
-
- cache_valid=false;
-
- if (cache_valid) {
-
- texture = ResourceLoader::load(cache_base+".png","ImageTexture",true);
- if (!texture.is_valid()) {
- //well fuck
- cache_valid=false;
- }
- }
-
- if (!cache_valid) {
-
- texture=_generate_preview(item,cache_base);
- }
-
- }
-
- //print_line("notify of preview ready");
- _preview_ready(item.path,texture,item.id,item.function,item.userdata);
-
- }
- }
-
-
- } else {
- preview_mutex->unlock();
- }
-
- }
-}
-
-
-
-void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource>& p_res, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) {
-
- ERR_FAIL_NULL(p_receiver);
- ERR_FAIL_COND(!p_res.is_valid());
-
- preview_mutex->lock();
-
- String path_id = "ID:"+itos(p_res->get_instance_ID());
-
-
- if (cache.has(path_id) && cache[path_id].last_hash==p_res->hash_edited_version()) {
-
- cache[path_id].order=order++;
- p_receiver->call_deferred(p_receiver_func,path_id,cache[path_id].preview,p_userdata);
- preview_mutex->unlock();
- return;
-
- }
-
- cache.erase(path_id); //erase if exists, since it will be regen
-
- //print_line("send to thread "+p_path);
- QueueItem item;
- item.function=p_receiver_func;
- item.id=p_receiver->get_instance_ID();
- item.resource=p_res;
- item.path=path_id;
- item.userdata=p_userdata;
-
- queue.push_back(item);
- preview_mutex->unlock();
- preview_sem->post();
-}
-
-void EditorResourcePreview::queue_resource_preview(const String& p_path, Object* p_receiver, const StringName& p_receiver_func, const Variant& p_userdata) {
-
- ERR_FAIL_NULL(p_receiver);
- preview_mutex->lock();
- if (cache.has(p_path)) {
- cache[p_path].order=order++;
- p_receiver->call_deferred(p_receiver_func,p_path,cache[p_path].preview,p_userdata);
- preview_mutex->unlock();
- return;
- }
-
- //print_line("send to thread "+p_path);
- QueueItem item;
- item.function=p_receiver_func;
- item.id=p_receiver->get_instance_ID();
- item.path=p_path;
- item.userdata=p_userdata;
-
- queue.push_back(item);
- preview_mutex->unlock();
- preview_sem->post();
-
-}
-
-void EditorResourcePreview::add_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator) {
-
- preview_generators.push_back(p_generator);
-}
-
-void EditorResourcePreview::remove_preview_generator(const Ref<EditorResourcePreviewGenerator>& p_generator) {
-
- preview_generators.erase(p_generator);
-}
-
-EditorResourcePreview* EditorResourcePreview::get_singleton() {
-
- return singleton;
-}
-
-void EditorResourcePreview::_bind_methods() {
-
- ClassDB::bind_method("_preview_ready",&EditorResourcePreview::_preview_ready);
-
- ClassDB::bind_method(_MD("queue_resource_preview","path","receiver","receiver_func","userdata:Variant"),&EditorResourcePreview::queue_resource_preview);
- ClassDB::bind_method(_MD("queue_edited_resource_preview","resource:Resource","receiver","receiver_func","userdata:Variant"),&EditorResourcePreview::queue_edited_resource_preview);
- ClassDB::bind_method(_MD("add_preview_generator","generator:EditorResourcePreviewGenerator"),&EditorResourcePreview::add_preview_generator);
- ClassDB::bind_method(_MD("remove_preview_generator","generator:EditorResourcePreviewGenerator"),&EditorResourcePreview::remove_preview_generator);
- ClassDB::bind_method(_MD("check_for_invalidation","path"),&EditorResourcePreview::check_for_invalidation);
-
-
- ADD_SIGNAL(MethodInfo("preview_invalidated",PropertyInfo(Variant::STRING,"path")));
-}
-
-void EditorResourcePreview::check_for_invalidation(const String& p_path) {
-
- preview_mutex->lock();
-
- bool call_invalidated=false;
- if (cache.has(p_path)) {
-
- uint64_t modified_time = FileAccess::get_modified_time(p_path);
- if (modified_time!=cache[p_path].modified_time) {
- cache.erase(p_path);
- call_invalidated=true;
- }
- }
-
- preview_mutex->unlock();
-
- if (call_invalidated) {//do outside mutex
- call_deferred("emit_signal","preview_invalidated",p_path);
- }
-
-
-
-}
-
-EditorResourcePreview::EditorResourcePreview() {
- singleton=this;
- preview_mutex = Mutex::create();
- preview_sem = Semaphore::create();
- order=0;
- exit=false;
-
- thread = Thread::create(_thread_func,this);
-}
-
-
-EditorResourcePreview::~EditorResourcePreview()
-{
-
- exit=true;
- preview_sem->post();
- Thread::wait_to_finish(thread);
- memdelete(thread);
- memdelete(preview_mutex);
- memdelete(preview_sem);
-
-
-}
-
diff --git a/tools/editor/editor_run.cpp b/tools/editor/editor_run.cpp
deleted file mode 100644
index 813a8ee5b7..0000000000
--- a/tools/editor/editor_run.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*************************************************************************/
-/* editor_run.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_run.h"
-
-#include "globals.h"
-#include "editor_settings.h"
-
-EditorRun::Status EditorRun::get_status() const {
-
- return status;
-}
-Error EditorRun::run(const String& p_scene,const String p_custom_args,const List<String>& p_breakpoints,const String& p_edited_scene) {
-
- List<String> args;
-
-
- String resource_path = GlobalConfig::get_singleton()->get_resource_path();
-
- if (resource_path!="") {
- args.push_back("-path");
- args.push_back(resource_path.replace(" ","%20"));
-
- }
-
- if (true) {
- args.push_back("-rdebug");
- args.push_back("localhost:"+String::num(GLOBAL_GET("network/debug/remote_port")));
- }
-
- args.push_back("-epid");
- args.push_back(String::num(OS::get_singleton()->get_process_ID()));
-
- if (debug_collisions) {
- args.push_back("-debugcol");
- }
-
- if (debug_navigation) {
- args.push_back("-debugnav");
- }
-
- int screen = EditorSettings::get_singleton()->get("run/window_placement/screen");
-
- if (screen==0) {
- screen=OS::get_singleton()->get_current_screen();
- } else {
- screen--;
- }
-
- Rect2 screen_rect;
- screen_rect.pos=OS::get_singleton()->get_screen_position(screen);
- screen_rect.size=OS::get_singleton()->get_screen_size(screen);
-
-
- Size2 desired_size;
-
- desired_size.x=GlobalConfig::get_singleton()->get("display/width");
- desired_size.y=GlobalConfig::get_singleton()->get("display/height");
-
- Size2 test_size;
- test_size.x=GlobalConfig::get_singleton()->get("display/test_width");
- test_size.y=GlobalConfig::get_singleton()->get("display/test_height");
- if (test_size.x>0 && test_size.y>0) {
-
- desired_size=test_size;
- }
-
-
- int window_placement=EditorSettings::get_singleton()->get("run/window_placement/rect");
-
- switch(window_placement) {
- case 0: { // default
-
- args.push_back("-p");
- args.push_back(itos(screen_rect.pos.x)+"x"+itos(screen_rect.pos.y));
- } break;
- case 1: { // centered
- Vector2 pos=screen_rect.pos+((screen_rect.size-desired_size)/2).floor();
- args.push_back("-p");
- args.push_back(itos(pos.x)+"x"+itos(pos.y));
- } break;
- case 2: { // custom pos
- Vector2 pos = EditorSettings::get_singleton()->get("run/window_placement/rect_custom_position");
- pos+=screen_rect.pos;
- args.push_back("-p");
- args.push_back(itos(pos.x)+"x"+itos(pos.y));
- } break;
- case 3: { // force maximized
- Vector2 pos=screen_rect.pos;
- args.push_back("-p");
- args.push_back(itos(pos.x)+"x"+itos(pos.y));
- args.push_back("-mx");
-
- } break;
- case 4: { // force fullscreen
-
- Vector2 pos=screen_rect.pos;
- args.push_back("-p");
- args.push_back(itos(pos.x)+"x"+itos(pos.y));
- args.push_back("-f");
- } break;
- }
-
-
-
- if (p_breakpoints.size()) {
-
- args.push_back("-bp");
- String bpoints;
- for(const List<String>::Element *E=p_breakpoints.front();E;E=E->next()) {
-
- bpoints+=E->get().replace(" ","%20");
- if (E->next())
- bpoints+=",";
- }
-
- args.push_back(bpoints);
- }
-
- if (p_custom_args!="") {
- Vector<String> cargs=p_custom_args.split(" ",false);
- for(int i=0;i<cargs.size();i++) {
- args.push_back(cargs[i].replace("$scene",p_scene).replace(" ","%20"));
- }
- }
-
- String exec = OS::get_singleton()->get_executable_path();
-
- printf("running: %ls", exec.c_str());
- for (List<String>::Element* E = args.front(); E ; E = E->next()) {
-
- printf(" %ls", E->get().c_str());
- };
- printf("\n");
-
- pid=0;
- Error err = OS::get_singleton()->execute(exec,args,false,&pid);
- ERR_FAIL_COND_V(err,err);
-
- status = STATUS_PLAY;
-
- return OK;
-}
-
-void EditorRun::stop() {
-
- if (status!=STATUS_STOP && pid!=0) {
-
- OS::get_singleton()->kill(pid);
- }
-
- status=STATUS_STOP;
-}
-
-void EditorRun::set_debug_collisions(bool p_debug) {
-
- debug_collisions=p_debug;
-}
-
-bool EditorRun::get_debug_collisions() const{
-
- return debug_collisions;
-}
-
-void EditorRun::set_debug_navigation(bool p_debug) {
-
- debug_navigation=p_debug;
-}
-
-bool EditorRun::get_debug_navigation() const{
-
- return debug_navigation;
-}
-
-
-EditorRun::EditorRun() {
-
- status=STATUS_STOP;
- debug_collisions=false;
- debug_navigation=false;
-
-}
diff --git a/tools/editor/editor_run.h b/tools/editor/editor_run.h
deleted file mode 100644
index 78fa892488..0000000000
--- a/tools/editor/editor_run.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*************************************************************************/
-/* editor_run.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_RUN_H
-#define EDITOR_RUN_H
-
-#include "scene/main/node.h"
-#include "os/os.h"
-class EditorRun {
-public:
- enum Status {
-
- STATUS_PLAY,
- STATUS_PAUSED,
- STATUS_STOP
- };
-
- OS::ProcessID pid;
-private:
-
- bool debug_collisions;
- bool debug_navigation;
- Status status;
-public:
-
- Status get_status() const;
- Error run(const String& p_scene,const String p_custom_args,const List<String>& p_breakpoints,const String& p_edited_scene);
- void run_native_notify() { status=STATUS_PLAY; }
- void stop();
-
- OS::ProcessID get_pid() const { return pid; }
-
- void set_debug_collisions(bool p_debug);
- bool get_debug_collisions() const;
-
- void set_debug_navigation(bool p_debug);
- bool get_debug_navigation() const;
-
- EditorRun();
-};
-
-#endif // EDITOR_RUN_H
diff --git a/tools/editor/editor_run_native.cpp b/tools/editor/editor_run_native.cpp
deleted file mode 100644
index 25cb41befc..0000000000
--- a/tools/editor/editor_run_native.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*************************************************************************/
-/* editor_run_native.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_run_native.h"
-
-#include "editor_import_export.h"
-
-void EditorRunNative::_notification(int p_what) {
-
-#if 0
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- List<StringName> ep;
- EditorImportExport::get_singleton()->get_export_platforms(&ep);
- ep.sort_custom<StringName::AlphCompare>();
- for(List<StringName>::Element *E=ep.front();E;E=E->next()) {
-
- Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(E->get());
- if (eep.is_null())
- continue;
- Ref<ImageTexture> icon = eep->get_logo();
- if (!icon.is_null()) {
- Image im = icon->get_data();
- im.clear_mipmaps();
- if (!im.empty()) {
-
- im.resize(16,16);
-
- Ref<ImageTexture> small_icon = memnew( ImageTexture);
- small_icon->create_from_image(im);
- MenuButton *mb = memnew( MenuButton );
- mb->get_popup()->connect("id_pressed",this,"_run_native",varray(E->get()));
- mb->connect("pressed",this,"_run_native",varray(-1, E->get()));
- mb->set_icon(small_icon);
- add_child(mb);
- menus[E->get()]=mb;
- }
- }
- }
- }
-
- if (p_what==NOTIFICATION_PROCESS) {
-
-
- bool changed = EditorImportExport::get_singleton()->poll_export_platforms() || first;
-
- if (changed) {
-
- for(Map<StringName,MenuButton*>::Element *E=menus.front();E;E=E->next()) {
-
- Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(E->key());
- MenuButton *mb = E->get();
- int dc = eep->get_device_count();
-
- if (dc==0) {
- mb->hide();
- } else {
- mb->get_popup()->clear();
- mb->show();
- if (dc == 1) {
- mb->set_tooltip(eep->get_device_name(0) + "\n\n" + eep->get_device_info(0).strip_edges());
- } else {
- mb->set_tooltip("Select device from the list");
- for(int i=0;i<dc;i++) {
- mb->get_popup()->add_icon_item(get_icon("Play","EditorIcons"),eep->get_device_name(i));
- mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() -1,eep->get_device_info(i).strip_edges());
- }
- }
- }
- }
-
- first=false;
- }
- }
-#endif
-}
-
-void EditorRunNative::_run_native(int p_idx,const String& p_platform) {
-
-#if 0
- Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(p_platform);
- ERR_FAIL_COND(eep.is_null());
- if (p_idx == -1) {
- if (eep->get_device_count() == 1) {
- menus[p_platform]->get_popup()->hide();
- p_idx = 0;
- } else {
- return;
- }
- }
- emit_signal("native_run");
-
- int flags=0;
- if (deploy_debug_remote)
- flags|=EditorExportPlatform::EXPORT_REMOTE_DEBUG;
- if (deploy_dumb)
- flags|=EditorExportPlatform::EXPORT_DUMB_CLIENT;
- if (debug_collisions)
- flags|=EditorExportPlatform::EXPORT_VIEW_COLLISONS;
- if (debug_navigation)
- flags|=EditorExportPlatform::EXPORT_VIEW_NAVIGATION;
-
- eep->run(p_idx,flags);
-
-#endif
-}
-
-void EditorRunNative::_bind_methods() {
-
- ClassDB::bind_method("_run_native",&EditorRunNative::_run_native);
-
- ADD_SIGNAL(MethodInfo("native_run"));
-}
-
-void EditorRunNative::set_deploy_dumb(bool p_enabled) {
-
- deploy_dumb=p_enabled;
-}
-
-bool EditorRunNative::is_deploy_dumb_enabled() const{
-
- return deploy_dumb;
-}
-
-void EditorRunNative::set_deploy_debug_remote(bool p_enabled) {
-
- deploy_debug_remote=p_enabled;
-}
-
-bool EditorRunNative::is_deploy_debug_remote_enabled() const{
-
- return deploy_debug_remote;
-}
-
-void EditorRunNative::set_debug_collisions(bool p_debug) {
-
- debug_collisions=p_debug;
-}
-
-bool EditorRunNative::get_debug_collisions() const{
-
- return debug_collisions;
-}
-
-void EditorRunNative::set_debug_navigation(bool p_debug) {
-
- debug_navigation=p_debug;
-}
-
-bool EditorRunNative::get_debug_navigation() const{
-
- return debug_navigation;
-}
-
-EditorRunNative::EditorRunNative()
-{
- set_process(true);
- first=true;
- deploy_dumb=false;
- deploy_debug_remote=false;
- debug_collisions=false;
- debug_navigation=false;
-
-}
diff --git a/tools/editor/editor_run_script.cpp b/tools/editor/editor_run_script.cpp
deleted file mode 100644
index 6a980019e4..0000000000
--- a/tools/editor/editor_run_script.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*************************************************************************/
-/* editor_run_script.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_run_script.h"
-
-#include "editor_node.h"
-
-
-void EditorScript::add_root_node(Node *p_node) {
-
- if (!editor) {
- EditorNode::add_io_error("EditorScript::add_root_node: "+TTR("Write your logic in the _run() method."));
- return;
- }
-
- if (editor->get_edited_scene()) {
- EditorNode::add_io_error("EditorScript::add_root_node: "+TTR("There is an edited scene already."));
- return;
- }
-
- //editor->set_edited_scene(p_node);
-}
-
-Node *EditorScript::get_scene() {
-
- if (!editor) {
- EditorNode::add_io_error("EditorScript::get_scene: "+TTR("Write your logic in the _run() method."));
- return NULL;
- }
-
- return editor->get_edited_scene();
-}
-
-void EditorScript::_run() {
-
- Ref<Script> s = get_script();
- ERR_FAIL_COND(!s.is_valid());
- if (!get_script_instance()) {
- EditorNode::add_io_error(TTR("Couldn't instance script:")+"\n "+s->get_path()+"\n"+TTR("Did you forget the 'tool' keyword?"));
- return;
-
- }
-
- Variant::CallError ce;
- ce.error=Variant::CallError::CALL_OK;
- get_script_instance()->call("_run",NULL,0,ce);
- if (ce.error!=Variant::CallError::CALL_OK) {
-
- EditorNode::add_io_error(TTR("Couldn't run script:")+"\n "+s->get_path()+"\n"+TTR("Did you forget the '_run' method?"));
- }
-}
-
-void EditorScript::set_editor(EditorNode *p_editor) {
-
- editor=p_editor;
-}
-
-
-void EditorScript::_bind_methods() {
-
- ClassDB::bind_method(_MD("add_root_node","node"),&EditorScript::add_root_node);
- ClassDB::bind_method(_MD("get_scene"),&EditorScript::get_scene);
- BIND_VMETHOD( MethodInfo("_run") );
-
-
-}
-
-EditorScript::EditorScript() {
-
- editor=NULL;
-}
-
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
deleted file mode 100644
index 1cdc426541..0000000000
--- a/tools/editor/editor_settings.cpp
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*************************************************************************/
-/* editor_settings.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http:/www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_settings.h"
-
-#include "os/os.h"
-#include "os/dir_access.h"
-#include "os/file_access.h"
-#include "version.h"
-#include "scene/main/scene_main_loop.h"
-#include "scene/main/node.h"
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "scene/main/viewport.h"
-#include "io/config_file.h"
-#include "editor_node.h"
-#include "globals.h"
-#include "translations.h"
-#include "io/file_access_memory.h"
-#include "io/translation_loader_po.h"
-#include "io/compression.h"
-#include "os/keyboard.h"
-
-
-
-
-Ref<EditorSettings> EditorSettings::singleton=NULL;
-
-EditorSettings *EditorSettings::get_singleton() {
-
- return singleton.ptr();
-}
-
-
-bool EditorSettings::_set(const StringName& p_name, const Variant& p_value) {
-
- _THREAD_SAFE_METHOD_
-
- if (p_name.operator String()=="shortcuts") {
-
- Array arr=p_value;
- ERR_FAIL_COND_V(arr.size() && arr.size()&1,true);
- for(int i=0;i<arr.size();i+=2) {
-
- String name = arr[i];
- InputEvent shortcut = arr[i+1];
-
- Ref<ShortCut> sc;
- sc.instance();
- sc->set_shortcut(shortcut);
- add_shortcut(name,sc);
- }
-
- return true;
- }
-
- if (p_value.get_type()==Variant::NIL)
- props.erase(p_name);
- else {
-
- if (props.has(p_name))
- props[p_name].variant=p_value;
- else
- props[p_name]=VariantContainer(p_value,last_order++);
-
- if (save_changed_setting) {
- props[p_name].save=true;
- }
- }
-
- emit_signal("settings_changed");
- return true;
-}
-bool EditorSettings::_get(const StringName& p_name,Variant &r_ret) const {
-
- _THREAD_SAFE_METHOD_
-
- if (p_name.operator String()=="shortcuts") {
-
- Array arr;
- for (const Map<String,Ref<ShortCut> >::Element *E=shortcuts.front();E;E=E->next()) {
-
- Ref<ShortCut> sc=E->get();
-
- if (optimize_save) {
- if (!sc->has_meta("original")) {
- continue; //this came from settings but is not any longer used
- }
-
- InputEvent original = sc->get_meta("original");
- if (sc->is_shortcut(original) || (original.type==InputEvent::NONE && sc->get_shortcut().type==InputEvent::NONE))
- continue; //not changed from default, don't save
- }
-
- arr.push_back(E->key());
- arr.push_back(sc->get_shortcut());
- }
- r_ret=arr;
- return true;
- }
-
- const VariantContainer *v=props.getptr(p_name);
- if (!v) {
- print_line("EditorSettings::_get - Warning, not found: "+String(p_name));
- return false;
- }
- r_ret = v->variant;
- return true;
-}
-
-struct _EVCSort {
-
- String name;
- Variant::Type type;
- int order;
- bool save;
-
- bool operator<(const _EVCSort& p_vcs) const{ return order< p_vcs.order; }
-};
-
-void EditorSettings::_get_property_list(List<PropertyInfo> *p_list) const {
-
- _THREAD_SAFE_METHOD_
-
- const String *k=NULL;
- Set<_EVCSort> vclist;
-
- while ((k=props.next(k))) {
-
- const VariantContainer *v=props.getptr(*k);
-
- if (v->hide_from_editor)
- continue;
-
- _EVCSort vc;
- vc.name=*k;
- vc.order=v->order;
- vc.type=v->variant.get_type();
- vc.save=v->save;
-
-
- vclist.insert(vc);
- }
-
- for(Set<_EVCSort>::Element *E=vclist.front();E;E=E->next()) {
-
- int pinfo = 0;
- if (E->get().save || !optimize_save) {
- pinfo|=PROPERTY_USAGE_STORAGE;
- }
-
- if (!E->get().name.begins_with("_") && !E->get().name.begins_with("projects/")) {
- pinfo|=PROPERTY_USAGE_EDITOR;
- } else {
- pinfo|=PROPERTY_USAGE_STORAGE; //hiddens must always be saved
- }
-
- PropertyInfo pi(E->get().type, E->get().name);
- pi.usage=pinfo;
- if (hints.has(E->get().name))
- pi=hints[E->get().name];
-
-
- p_list->push_back( pi );
- }
-
- p_list->push_back(PropertyInfo(Variant::ARRAY,"shortcuts",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); //do not edit
-}
-
-bool EditorSettings::has(String p_var) const {
-
- _THREAD_SAFE_METHOD_
-
- return props.has(p_var);
-}
-
-void EditorSettings::erase(String p_var) {
-
- _THREAD_SAFE_METHOD_
-
- props.erase(p_var);
-}
-
-void EditorSettings::raise_order(const String& p_name) {
- _THREAD_SAFE_METHOD_
-
- ERR_FAIL_COND(!props.has(p_name));
- props[p_name].order=++last_order;
-
-
-}
-
-
-Variant _EDITOR_DEF( const String& p_var, const Variant& p_default) {
-
- if (EditorSettings::get_singleton()->has(p_var))
- return EditorSettings::get_singleton()->get(p_var);
- EditorSettings::get_singleton()->set(p_var,p_default);
- return p_default;
-
-}
-
-
-void EditorSettings::create() {
-
-
- if (singleton.ptr())
- return; //pointless
-
- DirAccess *dir=NULL;
- Variant meta;
-
- String config_path;
- String config_dir;
- //String config_file="editor_settings.xml";
- Ref<ConfigFile> extra_config = memnew(ConfigFile);
-
- String exe_path = OS::get_singleton()->get_executable_path().get_base_dir();
- DirAccess* d = DirAccess::create_for_path(exe_path);
-
- if (d->file_exists(exe_path + "/._sc_")) {
-
- // editor is self contained
- config_path = exe_path;
- config_dir = "editor_data";
- extra_config->load(exe_path + "/._sc_");
- } else {
-
- if (OS::get_singleton()->has_environment("APPDATA")) {
- // Most likely under windows, save here
- config_path=OS::get_singleton()->get_environment("APPDATA");
- config_dir=String(_MKSTR(VERSION_SHORT_NAME)).capitalize();
- } else if (OS::get_singleton()->has_environment("HOME")) {
-
- config_path=OS::get_singleton()->get_environment("HOME");
- config_dir="."+String(_MKSTR(VERSION_SHORT_NAME)).to_lower();
- }
- };
-
- ClassDB::register_class<EditorSettings>(); //otherwise it can't be unserialized
- String config_file_path;
-
- if (config_path!=""){
-
- dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (dir->change_dir(config_path)!=OK) {
- ERR_PRINT("Cannot find path for config directory!");
- memdelete(dir);
- goto fail;
- }
-
- if (dir->change_dir(config_dir)!=OK) {
- dir->make_dir(config_dir);
- if (dir->change_dir(config_dir)!=OK) {
- ERR_PRINT("Cannot create config directory!");
- memdelete(dir);
- goto fail;
- }
- }
-
- if (dir->change_dir("templates")!=OK) {
- dir->make_dir("templates");
- } else {
-
- dir->change_dir("..");
- }
-
- if (dir->change_dir("text_editor_themes")!=OK) {
- dir->make_dir("text_editor_themes");
- } else {
- dir->change_dir("..");
- }
-
- if (dir->change_dir("tmp")!=OK) {
- dir->make_dir("tmp");
- } else {
-
- dir->change_dir("..");
- }
-
- if (dir->change_dir("config")!=OK) {
- dir->make_dir("config");
- } else {
-
- dir->change_dir("..");
- }
-
- dir->change_dir("config");
-
- String pcp=GlobalConfig::get_singleton()->get_resource_path();
- if (pcp.ends_with("/"))
- pcp=config_path.substr(0,pcp.size()-1);
- pcp=pcp.get_file()+"-"+pcp.md5_text();
-
- if (dir->change_dir(pcp)) {
- dir->make_dir(pcp);
- } else {
- dir->change_dir("..");
- }
-
- dir->change_dir("..");
-
- // path at least is validated, so validate config file
-
- String config_file_name = "editor_settings-" + String(_MKSTR(VERSION_MAJOR)) + ".tres";
- config_file_path = config_path + "/" + config_dir + "/" + config_file_name;
-
- String open_path = config_file_path;
-
- if (!dir->file_exists(config_file_name)) {
-
- goto fail;
- }
-
- memdelete(dir);
-
- singleton = ResourceLoader::load(open_path,"EditorSettings");
-
- if (singleton.is_null()) {
- WARN_PRINT("Could not open config file.");
- goto fail;
- }
-
- singleton->save_changed_setting=true;
- singleton->config_file_path=config_file_path;
- singleton->project_config_path=pcp;
- singleton->settings_path=config_path+"/"+config_dir;
-
- if (OS::get_singleton()->is_stdout_verbose()) {
-
- print_line("EditorSettings: Load OK!");
- }
-
- singleton->setup_language();
- singleton->setup_network();
- singleton->load_favorites();
- singleton->list_text_editor_themes();
-
- return;
-
- }
-
-
-
- fail:
-
- // patch init projects
- if (extra_config->has_section("init_projects")) {
- Vector<String> list = extra_config->get_value("init_projects", "list");
- for (int i=0; i<list.size(); i++) {
-
- list[i] = exe_path + "/" + list[i];
- };
- extra_config->set_value("init_projects", "list", list);
- };
-
- singleton = Ref<EditorSettings>( memnew( EditorSettings ) );
- singleton->save_changed_setting=true;
- singleton->config_file_path=config_file_path;
- singleton->settings_path=config_path+"/"+config_dir;
- singleton->_load_defaults(extra_config);
- singleton->setup_language();
- singleton->setup_network();
- singleton->list_text_editor_themes();
-
-
-}
-
-String EditorSettings::get_settings_path() const {
-
- return settings_path;
-}
-
-
-
-void EditorSettings::setup_language() {
-
- String lang = get("interface/editor_language");
- if (lang=="en")
- return;//none to do
-
- for(int i=0;i<translations.size();i++) {
- if (translations[i]->get_locale()==lang) {
- TranslationServer::get_singleton()->set_tool_translation(translations[i]);
- break;
- }
- }
-}
-
-void EditorSettings::setup_network() {
-
- List<IP_Address> local_ip;
- IP::get_singleton()->get_local_addresses(&local_ip);
- String lip;
- String hint;
- String current=get("network/debug_host");
-
- for(List<IP_Address>::Element *E=local_ip.front();E;E=E->next()) {
-
- String ip = E->get();
- if (ip=="127.0.0.1")
- continue;
-
- if (lip=="")
- lip=ip;
- if (ip==current)
- lip=current; //so it saves
- if (hint!="")
- hint+=",";
- hint+=ip;
-
- }
-
- set("network/debug_host",lip);
- add_property_hint(PropertyInfo(Variant::STRING,"network/debug_host",PROPERTY_HINT_ENUM,hint));
-
-}
-
-
-void EditorSettings::save() {
-
- //_THREAD_SAFE_METHOD_
-
- if (!singleton.ptr())
- return;
-
- if (singleton->config_file_path=="") {
- ERR_PRINT("Cannot save EditorSettings config, no valid path");
- return;
- }
-
- Error err = ResourceSaver::save(singleton->config_file_path,singleton);
-
- if (err!=OK) {
- ERR_PRINT("Can't Save!");
- return;
- }
-
- if (OS::get_singleton()->is_stdout_verbose()) {
- print_line("EditorSettings Save OK!");
- }
-
-}
-
-void EditorSettings::destroy() {
-
- if (!singleton.ptr())
- return;
- save();
- singleton=Ref<EditorSettings>();
-}
-
-void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
-
- _THREAD_SAFE_METHOD_
-
-
- {
- String lang_hint="en";
- String host_lang = OS::get_singleton()->get_locale();
-
- String best;
-
- for(int i=0;i<translations.size();i++) {
- String locale = translations[i]->get_locale();
- lang_hint+=",";
- lang_hint+=locale;
-
- if (host_lang==locale) {
- best=locale;
- }
-
- if (best==String() && host_lang.begins_with(locale)) {
- best=locale;
- }
- }
-
- if (best==String()) {
- best="en";
- }
-
- set("interface/editor_language",best);
- hints["interface/editor_language"]=PropertyInfo(Variant::STRING,"interface/editor_language",PROPERTY_HINT_ENUM,lang_hint,PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
- }
-
- set("interface/hidpi_mode",0);
- hints["interface/hidpi_mode"]=PropertyInfo(Variant::INT,"interface/hidpi_mode",PROPERTY_HINT_ENUM,"Auto,VeryLoDPI,LoDPI,MidDPI,HiDPI",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/show_script_in_scene_tabs",false);
- set("interface/font_size",14);
- hints["interface/font_size"]=PropertyInfo(Variant::INT,"interface/font_size",PROPERTY_HINT_RANGE,"10,40,1",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/source_font_size",14);
- hints["interface/source_font_size"]=PropertyInfo(Variant::INT,"interface/source_font_size",PROPERTY_HINT_RANGE,"8,96,1",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/custom_font","");
- hints["interface/custom_font"]=PropertyInfo(Variant::STRING,"interface/custom_font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/custom_theme","");
- hints["interface/custom_theme"]=PropertyInfo(Variant::STRING,"interface/custom_theme",PROPERTY_HINT_GLOBAL_FILE,"*.res,*.tres,*.theme",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
-
-
- set("filesystem/directories/autoscan_project_path","");
- hints["filesystem/directories/autoscan_project_path"]=PropertyInfo(Variant::STRING,"filesystem/directories/autoscan_project_path",PROPERTY_HINT_GLOBAL_DIR);
- set("filesystem/directories/default_project_path","");
- hints["filesystem/directories/default_project_path"]=PropertyInfo(Variant::STRING,"filesystem/directories/default_project_path",PROPERTY_HINT_GLOBAL_DIR);
- set("filesystem/directories/default_project_export_path","");
- hints["global/default_project_export_path"]=PropertyInfo(Variant::STRING,"global/default_project_export_path",PROPERTY_HINT_GLOBAL_DIR);
- set("interface/show_script_in_scene_tabs",false);
-
-
- set("text_editor/theme/color_theme","Default");
- hints["text_editor/theme/color_theme"]=PropertyInfo(Variant::STRING,"text_editor/theme/color_theme",PROPERTY_HINT_ENUM,"Default");
-
- set("text_editor/theme/line_spacing",4);
-
-
- _load_default_text_editor_theme();
-
- set("text_editor/highlighting/syntax_highlighting", true);
-
- set("text_editor/highlighting/highlight_all_occurrences", true);
- set("text_editor/cursor/scroll_past_end_of_file", false);
-
- set("text_editor/indent/tab_size", 4);
- hints["text_editor/indent/tab_size"]=PropertyInfo(Variant::INT,"text_editor/indent/tab_size",PROPERTY_HINT_RANGE,"1, 64, 1"); // size of 0 crashes.
- set("text_editor/indent/draw_tabs", true);
-
- set("text_editor/line_numbers/show_line_numbers", true);
- set("text_editor/line_numbers/line_numbers_zero_padded", false);
- set("text_editor/line_numbers/show_breakpoint_gutter", true);
- set("text_editor/line_numbers/show_line_length_guideline", false);
- set("text_editor/line_numbers/line_length_guideline_column", 80);
- hints["text_editor/line_numbers/line_length_guideline_column"]=PropertyInfo(Variant::INT,"text_editor/line_numbers/line_length_guideline_column",PROPERTY_HINT_RANGE,"20, 160, 10");
-
- set("text_editor/files/trim_trailing_whitespace_on_save", false);
- set("text_editor/completion/idle_parse_delay",2);
- set("text_editor/tools/create_signal_callbacks",true);
- set("text_editor/files/autosave_interval_secs",0);
-
- set("text_editor/cursor/block_caret", false);
- set("text_editor/cursor/caret_blink", false);
- set("text_editor/cursor/caret_blink_speed", 0.65);
- hints["text_editor/cursor/caret_blink_speed"]=PropertyInfo(Variant::REAL,"text_editor/cursor/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1, 10, 0.1");
-
- set("text_editor/theme/font","");
- hints["text_editor/theme/font"]=PropertyInfo(Variant::STRING,"text_editor/theme/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt");
- set("text_editor/completion/auto_brace_complete", false);
- set("text_editor/files/restore_scripts_on_load",true);
-
-
- //set("docks/scene_tree/display_old_action_buttons",false);
- set("docks/scene_tree/start_create_dialog_fully_expanded",false);
- set("docks/scene_tree/draw_relationship_lines",false);
- set("docks/scene_tree/relationship_line_color",Color::html("464646"));
-
- set("editors/grid_map/pick_distance", 5000.0);
-
- set("editors/3d/grid_color",Color(0,1,0,0.2));
- hints["editors/3d/grid_color"]=PropertyInfo(Variant::COLOR,"editors/3d/grid_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
-
- set("editors/3d/default_fov",45.0);
- set("editors/3d/default_z_near",0.1);
- set("editors/3d/default_z_far",500.0);
-
- set("editors/3d/navigation_scheme",0);
- hints["editors/3d/navigation_scheme"]=PropertyInfo(Variant::INT,"editors/3d/navigation_scheme",PROPERTY_HINT_ENUM,"Godot,Maya,Modo");
- set("editors/3d/zoom_style",0);
- hints["editors/3d/zoom_style"]=PropertyInfo(Variant::INT,"editors/3d/zoom_style",PROPERTY_HINT_ENUM,"Vertical, Horizontal");
- set("editors/3d/orbit_modifier",0);
- hints["editors/3d/orbit_modifier"]=PropertyInfo(Variant::INT,"editors/3d/orbit_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
- set("editors/3d/pan_modifier",1);
- hints["editors/3d/pan_modifier"]=PropertyInfo(Variant::INT,"editors/3d/pan_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
- set("editors/3d/zoom_modifier",4);
- hints["editors/3d/zoom_modifier"]=PropertyInfo(Variant::INT,"editors/3d/zoom_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl");
- set("editors/3d/emulate_numpad",false);
- set("editors/3d/emulate_3_button_mouse", false);
-
- set("editors/2d/bone_width",5);
- set("editors/2d/bone_color1",Color(1.0,1.0,1.0,0.9));
- set("editors/2d/bone_color2",Color(0.75,0.75,0.75,0.9));
- set("editors/2d/bone_selected_color",Color(0.9,0.45,0.45,0.9));
- set("editors/2d/bone_ik_color",Color(0.9,0.9,0.45,0.9));
-
- set("editors/2d/keep_margins_when_changing_anchors", false);
-
- set("run/window_placement/rect",0);
- hints["run/window_placement/rect"]=PropertyInfo(Variant::INT,"run/window_placement/rect",PROPERTY_HINT_ENUM,"Default,Centered,Custom Position,Force Maximized,Force Full Screen");
- String screen_hints=TTR("Default (Same as Editor)");
- for(int i=0;i<OS::get_singleton()->get_screen_count();i++) {
- screen_hints+=",Monitor "+itos(i+1);
- }
- set("run/window_placement/rect_custom_position",Vector2());
- set("run/window_placement/screen",0);
- hints["run/window_placement/screen"]=PropertyInfo(Variant::INT,"run/window_placement/screen",PROPERTY_HINT_ENUM,screen_hints);
-
- set("filesystem/on_save/compress_binary_resources",true);
- set("filesystem/on_save/save_modified_external_resources",true);
- //set("filesystem/on_save/save_paths_as_relative",false);
- //set("filesystem/on_save/save_paths_without_extension",false);
-
- set("text_editor/tools/create_signal_callbacks",true);
-
- set("filesystem/file_dialog/show_hidden_files", false);
- set("filesystem/file_dialog/display_mode", 0);
- hints["filesystem/file_dialog/display_mode"]=PropertyInfo(Variant::INT,"filesystem/file_dialog/display_mode",PROPERTY_HINT_ENUM,"Thumbnails,List");
- set("filesystem/file_dialog/thumbnail_size", 64);
- hints["filesystem/file_dialog/thumbnail_size"]=PropertyInfo(Variant::INT,"filesystem/file_dialog/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16");
-
- set("docks/filesystem/display_mode", 0);
- hints["docks/filesystem/display_mode"]=PropertyInfo(Variant::INT,"docks/filesystem/display_mode",PROPERTY_HINT_ENUM,"Thumbnails,List");
- set("docks/filesystem/thumbnail_size", 64);
- hints["docks/filesystem/thumbnail_size"]=PropertyInfo(Variant::INT,"docks/filesystem/thumbnail_size",PROPERTY_HINT_RANGE,"32,128,16");
-
- set("editors/animation/autorename_animation_tracks",true);
- set("editors/animation/confirm_insert_track",true);
-
- set("docks/property_editor/texture_preview_width",48);
- set("docks/property_editor/auto_refresh_interval",0.3);
- set("text_editor/help/doc_path","");
-
- set("filesystem/import/ask_save_before_reimport",false);
-
- set("filesystem/import/pvrtc_texture_tool","");
-#ifdef WINDOWS_ENABLED
- hints["filesystem/import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_GLOBAL_FILE,"*.exe");
-#else
- hints["import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_GLOBAL_FILE,"");
-#endif
- // TODO: Rename to "filesystem/import/pvrtc_fast_conversion" to match other names?
- set("filesystem/import/pvrtc_fast_conversion",false);
-
-
- set("run/auto_save/save_before_running",true);
- set("run/output/always_clear_output_on_play",true);
- set("run/output/always_open_output_on_play",true);
- set("filesystem/resources/save_compressed_resources",true);
- set("filesystem/resources/auto_reload_modified_images",true);
-
- set("filesystem/import/automatic_reimport_on_sources_changed",true);
-
- if (p_extra_config.is_valid()) {
-
- if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) {
-
- Vector<String> list = p_extra_config->get_value("init_projects", "list");
- for (int i=0; i<list.size(); i++) {
-
- String name = list[i].replace("/", "::");
- set("projects/"+name, list[i]);
- };
- };
-
- if (p_extra_config->has_section("presets")) {
-
- List<String> keys;
- p_extra_config->get_section_keys("presets", &keys);
-
- for (List<String>::Element *E=keys.front();E;E=E->next()) {
-
- String key = E->get();
- Variant val = p_extra_config->get_value("presets", key);
- set(key, val);
- };
- };
- };
-
-
-
-
-}
-
-void EditorSettings::_load_default_text_editor_theme() {
- set("text_editor/highlighting/background_color",Color::html("3b000000"));
- set("text_editor/highlighting/completion_background_color", Color::html("2C2A32"));
- set("text_editor/highlighting/completion_selected_color", Color::html("434244"));
- set("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"));
- set("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"));
- set("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"));
- set("text_editor/highlighting/caret_color",Color::html("aaaaaa"));
- set("text_editor/highlighting/caret_background_color", Color::html("000000"));
- set("text_editor/highlighting/line_number_color",Color::html("66aaaaaa"));
- set("text_editor/highlighting/text_color",Color::html("aaaaaa"));
- set("text_editor/highlighting/text_selected_color",Color::html("000000"));
- set("text_editor/highlighting/keyword_color",Color::html("ffffb3"));
- set("text_editor/highlighting/base_type_color",Color::html("a4ffd4"));
- set("text_editor/highlighting/engine_type_color",Color::html("83d3ff"));
- set("text_editor/highlighting/function_color",Color::html("66a2ce"));
- set("text_editor/highlighting/member_variable_color",Color::html("e64e59"));
- set("text_editor/highlighting/comment_color",Color::html("676767"));
- set("text_editor/highlighting/string_color",Color::html("ef6ebe"));
- set("text_editor/highlighting/number_color",Color::html("EB9532"));
- set("text_editor/highlighting/symbol_color",Color::html("badfff"));
- set("text_editor/highlighting/selection_color",Color::html("7b5dbe"));
- set("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2));
- set("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15));
- set("text_editor/highlighting/line_length_guideline_color",Color(0.3,0.5,0.8,0.1));
- set("text_editor/highlighting/mark_color", Color(1.0,0.4,0.4,0.4));
- set("text_editor/highlighting/breakpoint_color", Color(0.8,0.8,0.4,0.2));
- set("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15));
- set("text_editor/highlighting/search_result_color",Color(0.05,0.25,0.05,1));
- set("text_editor/highlighting/search_result_border_color",Color(0.1,0.45,0.1,1));
-}
-
-void EditorSettings::notify_changes() {
-
- _THREAD_SAFE_METHOD_
-
- SceneTree *sml=NULL;
-
- if (OS::get_singleton()->get_main_loop())
- sml = OS::get_singleton()->get_main_loop()->cast_to<SceneTree>();
-
- if (!sml) {
- return;
- }
-
- Node *root = sml->get_root()->get_child(0);
-
- if (!root) {
- return;
- }
- root->propagate_notification(NOTIFICATION_EDITOR_SETTINGS_CHANGED);
-
-}
-
-void EditorSettings::_add_property_info_bind(const Dictionary& p_info) {
-
- ERR_FAIL_COND(!p_info.has("name"));
- ERR_FAIL_COND(!p_info.has("type"));
-
- PropertyInfo pinfo;
- pinfo.name = p_info["name"];
- ERR_FAIL_COND(!props.has(pinfo.name));
- pinfo.type = Variant::Type(p_info["type"].operator int());
- ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX);
-
- if (p_info.has("hint"))
- pinfo.hint = PropertyHint(p_info["hint"].operator int());
- if (p_info.has("hint_string"))
- pinfo.hint_string = p_info["hint_string"];
-
- add_property_hint(pinfo);
-}
-
-void EditorSettings::add_property_hint(const PropertyInfo& p_hint) {
-
- _THREAD_SAFE_METHOD_
-
- hints[p_hint.name]=p_hint;
-}
-
-
-
-
-
-
-void EditorSettings::set_favorite_dirs(const Vector<String>& p_favorites) {
-
- favorite_dirs=p_favorites;
- FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"),FileAccess::WRITE);
- if (f) {
- for(int i=0;i<favorite_dirs.size();i++)
- f->store_line(favorite_dirs[i]);
- memdelete(f);
- }
-
-}
-
-Vector<String> EditorSettings::get_favorite_dirs() const {
-
- return favorite_dirs;
-}
-
-
-void EditorSettings::set_recent_dirs(const Vector<String>& p_recent) {
-
- recent_dirs=p_recent;
- FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"),FileAccess::WRITE);
- if (f) {
- for(int i=0;i<recent_dirs.size();i++)
- f->store_line(recent_dirs[i]);
- memdelete(f);
- }
-}
-
-Vector<String> EditorSettings::get_recent_dirs() const {
-
- return recent_dirs;
-}
-
-String EditorSettings::get_project_settings_path() const {
-
-
- return get_settings_path().plus_file("config").plus_file(project_config_path);
-}
-
-
-void EditorSettings::load_favorites() {
-
- FileAccess *f = FileAccess::open(get_project_settings_path().plus_file("favorite_dirs"),FileAccess::READ);
- if (f) {
- String line = f->get_line().strip_edges();
- while(line!="") {
- favorite_dirs.push_back(line);
- line = f->get_line().strip_edges();
- }
- memdelete(f);
- }
-
- f = FileAccess::open(get_project_settings_path().plus_file("recent_dirs"),FileAccess::READ);
- if (f) {
- String line = f->get_line().strip_edges();
- while(line!="") {
- recent_dirs.push_back(line);
- line = f->get_line().strip_edges();
- }
- memdelete(f);
- }
-
-}
-
-void EditorSettings::list_text_editor_themes() {
- String themes="Default";
- DirAccess *d = DirAccess::open(settings_path + "/text_editor_themes");
- if (d) {
- d->list_dir_begin();
- String file = d->get_next();
- while(file != String()) {
- if (file.get_extension() == "tet" && file.get_basename().to_lower() != "default") {
- themes += "," + file.get_basename();
- }
- file = d->get_next();
- }
- d->list_dir_end();
- memdelete(d);
- }
- add_property_hint(PropertyInfo(Variant::STRING,"text_editor/theme/color_theme",PROPERTY_HINT_ENUM,themes));
-}
-
-void EditorSettings::load_text_editor_theme() {
- if (get("text_editor/theme/color_theme") == "Default") {
- _load_default_text_editor_theme(); // sorry for "Settings changed" console spam
- return;
- }
-
- String theme_path = get_settings_path() + "/text_editor_themes/" + get("text_editor/theme/color_theme") + ".tet";
-
- Ref<ConfigFile> cf = memnew( ConfigFile );
- Error err = cf->load(theme_path);
-
- if (err != OK) {
- return;
- }
-
- List<String> keys;
- cf->get_section_keys("color_theme", &keys);
-
- for(List<String>::Element *E=keys.front();E;E=E->next()) {
- String key = E->get();
- String val = cf->get_value("color_theme", key);
-
- // don't load if it's not already there!
- if (has("text_editor/highlighting/" + key)) {
-
- // make sure it is actually a color
- if (val.is_valid_html_color() && key.find("color") >= 0) {
- props["text_editor/highlighting/"+key].variant = Color::html(val); // change manually to prevent "Settings changed" console spam
- }
- }
- }
- emit_signal("settings_changed");
- // if it doesn't load just use what is currently loaded
-}
-
-bool EditorSettings::import_text_editor_theme(String p_file) {
-
- if (!p_file.ends_with(".tet")) {
- return false;
- } else {
- if (p_file.get_file().to_lower() == "default.tet") {
- return false;
- }
-
- DirAccess *d = DirAccess::open(settings_path + "/text_editor_themes");
- if (d) {
- d->copy(p_file, settings_path + "/text_editor_themes/" + p_file.get_file());
- memdelete(d);
- return true;
- }
- }
- return false;
-}
-
-bool EditorSettings::save_text_editor_theme() {
-
- String p_file = get("text_editor/theme/color_theme");
-
- if (p_file.get_file().to_lower() == "default") {
- return false;
- }
- String theme_path = get_settings_path() + "/text_editor_themes/" + p_file + ".tet";
- return _save_text_editor_theme(theme_path);
-}
-
-bool EditorSettings::save_text_editor_theme_as(String p_file) {
- if (!p_file.ends_with(".tet")) {
- p_file += ".tet";
- }
-
- if (p_file.get_file().to_lower() == "default.tet") {
- return false;
- }
- if(_save_text_editor_theme(p_file)) {
-
- // switch to theme is saved in the theme directory
- list_text_editor_themes();
- String theme_name = p_file.substr(0, p_file.length() - 4).get_file();
-
- if (p_file.get_base_dir() == get_settings_path() + "/text_editor_themes") {
- set("text_editor/theme/color_theme", theme_name);
- load_text_editor_theme();
- }
- return true;
- }
- return false;
-}
-
-bool EditorSettings::_save_text_editor_theme(String p_file) {
- String theme_section = "color_theme";
- Ref<ConfigFile> cf = memnew( ConfigFile ); // hex is better?
- cf->set_value(theme_section, "background_color", ((Color)get("text_editor/highlighting/background_color")).to_html());
- cf->set_value(theme_section, "completion_background_color", ((Color)get("text_editor/highlighting/completion_background_color")).to_html());
- cf->set_value(theme_section, "completion_selected_color", ((Color)get("text_editor/highlighting/completion_selected_color")).to_html());
- cf->set_value(theme_section, "completion_existing_color", ((Color)get("text_editor/highlighting/completion_existing_color")).to_html());
- cf->set_value(theme_section, "completion_scroll_color", ((Color)get("text_editor/highlighting/completion_scroll_color")).to_html());
- cf->set_value(theme_section, "completion_font_color", ((Color)get("text_editor/highlighting/completion_font_color")).to_html());
- cf->set_value(theme_section, "caret_color", ((Color)get("text_editor/highlighting/caret_color")).to_html());
- cf->set_value(theme_section, "caret_background_color", ((Color)get("text_editor/highlighting/caret_background_color")).to_html());
- cf->set_value(theme_section, "line_number_color", ((Color)get("text_editor/highlighting/line_number_color")).to_html());
- cf->set_value(theme_section, "text_color", ((Color)get("text_editor/highlighting/text_color")).to_html());
- cf->set_value(theme_section, "text_selected_color", ((Color)get("text_editor/highlighting/text_selected_color")).to_html());
- cf->set_value(theme_section, "keyword_color", ((Color)get("text_editor/highlighting/keyword_color")).to_html());
- cf->set_value(theme_section, "base_type_color", ((Color)get("text_editor/highlighting/base_type_color")).to_html());
- cf->set_value(theme_section, "engine_type_color", ((Color)get("text_editor/highlighting/engine_type_color")).to_html());
- cf->set_value(theme_section, "function_color", ((Color)get("text_editor/highlighting/function_color")).to_html());
- cf->set_value(theme_section, "member_variable_color", ((Color)get("text_editor/highlighting/member_variable_color")).to_html());
- cf->set_value(theme_section, "comment_color", ((Color)get("text_editor/highlighting/comment_color")).to_html());
- cf->set_value(theme_section, "string_color", ((Color)get("text_editor/highlighting/string_color")).to_html());
- cf->set_value(theme_section, "number_color", ((Color)get("text_editor/highlighting/number_color")).to_html());
- cf->set_value(theme_section, "symbol_color", ((Color)get("text_editor/highlighting/symbol_color")).to_html());
- cf->set_value(theme_section, "selection_color", ((Color)get("text_editor/highlighting/selection_color")).to_html());
- cf->set_value(theme_section, "brace_mismatch_color", ((Color)get("text_editor/highlighting/brace_mismatch_color")).to_html());
- cf->set_value(theme_section, "current_line_color", ((Color)get("text_editor/highlighting/current_line_color")).to_html());
- cf->set_value(theme_section, "line_length_guideline_color", ((Color)get("text_editor/highlighting/line_length_guideline_color")).to_html());
- cf->set_value(theme_section, "mark_color", ((Color)get("text_editor/highlighting/mark_color")).to_html());
- cf->set_value(theme_section, "breakpoint_color", ((Color)get("text_editor/highlighting/breakpoint_color")).to_html());
- cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/highlighting/word_highlighted_color")).to_html());
- cf->set_value(theme_section, "search_result_color", ((Color)get("text_editor/highlighting/search_result_color")).to_html());
- cf->set_value(theme_section, "search_result_border_color", ((Color)get("text_editor/highlighting/search_result_border_color")).to_html());
-
-
- Error err = cf->save(p_file);
-
- if (err == OK) {
- return true;
- }
- return false;
-}
-
-
-void EditorSettings::add_shortcut(const String& p_name, Ref<ShortCut> &p_shortcut) {
-
- shortcuts[p_name]=p_shortcut;
-}
-
-bool EditorSettings::is_shortcut(const String&p_name, const InputEvent &p_event) const{
-
- const Map<String,Ref<ShortCut> >::Element *E=shortcuts.find(p_name);
- if (!E) {
- ERR_EXPLAIN("Unknown Shortcut: "+p_name);
- ERR_FAIL_V(false);
- }
-
- return E->get()->is_shortcut(p_event);
-
-}
-
-Ref<ShortCut> EditorSettings::get_shortcut(const String&p_name) const{
-
- const Map<String,Ref<ShortCut> >::Element *E=shortcuts.find(p_name);
- if (!E)
- return Ref<ShortCut>();
-
- return E->get();
-}
-
-void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) {
-
- for (const Map<String,Ref<ShortCut> >::Element*E=shortcuts.front();E;E=E->next()) {
-
- r_shortcuts->push_back(E->key());
- }
-}
-
-void EditorSettings::set_optimize_save(bool p_optimize) {
-
- optimize_save=p_optimize;
-}
-
-String EditorSettings::get_last_selected_language()
-{
- Ref<ConfigFile> cf = memnew( ConfigFile );
- String path = get_project_settings_path().plus_file("project_metadata.cfg");
- Error err = cf->load(path);
- if (err != OK) {
- return "";
- }
- Variant last_selected_language = cf->get_value("script_setup", "last_selected_language");
- if (last_selected_language.get_type() != Variant::STRING)
- return "";
- return static_cast<String>(last_selected_language);
-}
-
-void EditorSettings::set_last_selected_language(String p_language)
-{
- Ref<ConfigFile> cf = memnew( ConfigFile );
- String path = get_project_settings_path().plus_file("project_metadata.cfg");
- cf->load(path);
- cf->set_value("script_setup", "last_selected_language", p_language);
- cf->save(path);
-}
-
-void EditorSettings::_bind_methods() {
-
- ClassDB::bind_method(_MD("erase","property"),&EditorSettings::erase);
- ClassDB::bind_method(_MD("get_settings_path"),&EditorSettings::get_settings_path);
- ClassDB::bind_method(_MD("get_project_settings_path"),&EditorSettings::get_project_settings_path);
-
- ClassDB::bind_method(_MD("add_property_info", "info"),&EditorSettings::_add_property_info_bind);
-
- ClassDB::bind_method(_MD("set_favorite_dirs","dirs"),&EditorSettings::set_favorite_dirs);
- ClassDB::bind_method(_MD("get_favorite_dirs"),&EditorSettings::get_favorite_dirs);
-
- ClassDB::bind_method(_MD("set_recent_dirs","dirs"),&EditorSettings::set_recent_dirs);
- ClassDB::bind_method(_MD("get_recent_dirs"),&EditorSettings::get_recent_dirs);
-
- ADD_SIGNAL(MethodInfo("settings_changed"));
-
-}
-
-EditorSettings::EditorSettings() {
-
-
- //singleton=this;
- last_order=0;
- optimize_save=true;
- save_changed_setting=true;
-
- EditorTranslationList *etl=_editor_translations;
-
- while(etl->data) {
-
- Vector<uint8_t> data;
- data.resize(etl->uncomp_size);
- Compression::decompress(data.ptr(),etl->uncomp_size,etl->data,etl->comp_size,Compression::MODE_DEFLATE);
-
- FileAccessMemory *fa = memnew (FileAccessMemory);
- fa->open_custom(data.ptr(),data.size());
-
- Ref<Translation> tr = TranslationLoaderPO::load_translation(fa,NULL,"translation_"+String(etl->lang));
-
- if (tr.is_valid()) {
- tr->set_locale(etl->lang);
- translations.push_back(tr);
- }
-
- etl++;
-
- }
-
- _load_defaults();
-
-
-}
-
-
-EditorSettings::~EditorSettings() {
-
- //singleton=NULL;
-}
-
-Ref<ShortCut> ED_GET_SHORTCUT(const String& p_path) {
-
- Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
- if (!sc.is_valid()) {
- ERR_EXPLAIN("Used ED_GET_SHORTCUT with invalid shortcut: "+p_path);
- ERR_FAIL_COND_V(!sc.is_valid(),sc);
- }
-
- return sc;
-}
-
-Ref<ShortCut> ED_SHORTCUT(const String& p_path,const String& p_name,uint32_t p_keycode) {
-
- InputEvent ie;
- if (p_keycode) {
- ie.type=InputEvent::KEY;
- ie.key.unicode=p_keycode&KEY_CODE_MASK;
- ie.key.scancode=p_keycode&KEY_CODE_MASK;
- ie.key.mod.shift=bool(p_keycode&KEY_MASK_SHIFT);
- ie.key.mod.alt=bool(p_keycode&KEY_MASK_ALT);
- ie.key.mod.control=bool(p_keycode&KEY_MASK_CTRL);
- ie.key.mod.meta=bool(p_keycode&KEY_MASK_META);
-
- }
-
- Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
- if (sc.is_valid()) {
-
- sc->set_name(p_name); //keep name (the ones that come from disk have no name)
- sc->set_meta("original",ie); //to compare against changes
- return sc;
- }
-
- sc.instance();
- sc->set_name(p_name);
- sc->set_shortcut(ie);
- sc->set_meta("original",ie); //to compare against changes
- EditorSettings::get_singleton()->add_shortcut(p_path,sc);
-
- return sc;
-}
diff --git a/tools/editor/editor_settings.h b/tools/editor/editor_settings.h
deleted file mode 100644
index c11feef667..0000000000
--- a/tools/editor/editor_settings.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*************************************************************************/
-/* editor_settings.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_SETTINGS_H
-#define EDITOR_SETTINGS_H
-
-#include "object.h"
-
-#include "resource.h"
-#include "os/thread_safe.h"
-#include "core/io/config_file.h"
-#include "translation.h"
-#include "scene/gui/input_action.h"
-
-class EditorPlugin;
-
-class EditorSettings : public Resource {
-
- GDCLASS( EditorSettings, Resource );
-private:
- _THREAD_SAFE_CLASS_
-
-public:
- struct Plugin {
-
- EditorPlugin *instance;
- String path;
- String name;
- String author;
- String version;
- String description;
- bool installs;
- String script;
- Vector<String> install_files;
- };
-private:
-
- struct VariantContainer {
- int order;
- Variant variant;
- bool hide_from_editor;
- bool save;
- VariantContainer(){ order=0; hide_from_editor=false; save=false;}
- VariantContainer(const Variant& p_variant, int p_order) { variant=p_variant; order=p_order; hide_from_editor=false; }
- };
-
- HashMap<String,PropertyInfo> hints;
- int last_order;
- HashMap<String,VariantContainer> props;
- String resource_path;
-
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list(List<PropertyInfo> *p_list) const;
-
- static Ref<EditorSettings> singleton;
-
- String config_file_path;
- String settings_path;
-
- Ref<Resource> clipboard;
-
-
- bool save_changed_setting;
-
- bool optimize_save; //do not save stuff that came from config but was not set from engine
-
- void _load_defaults(Ref<ConfigFile> p_extra_config = NULL);
- void _load_default_text_editor_theme();
-
- bool _save_text_editor_theme(String p_file);
-
- String project_config_path;
-
- Vector<String> favorite_dirs;
- Vector<String> recent_dirs;
-
- Vector<Ref<Translation> > translations;
-
- Map<String,Ref<ShortCut> > shortcuts;
-
- void _add_property_info_bind(const Dictionary& p_info);
-
-protected:
-
- static void _bind_methods();
-public:
-
- enum {
- NOTIFICATION_EDITOR_SETTINGS_CHANGED=10000
- };
-
-
- bool has(String p_var) const;
- 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;
-
-
- void setup_language();
- void setup_network();
-
- void raise_order(const String& p_name);
- static void create();
- static void save();
- static void destroy();
-
- void notify_changes();
-
- void set_resource_clipboard(const Ref<Resource>& p_resource) { clipboard=p_resource; }
- Ref<Resource> get_resource_clipboard() const { return clipboard; }
-
- void add_property_hint(const PropertyInfo& p_hint);
-
- void set_favorite_dirs(const Vector<String>& p_favorite_dirs);
- Vector<String> get_favorite_dirs() const;
-
- void set_recent_dirs(const Vector<String>& p_recent_dirs);
- Vector<String> get_recent_dirs() const;
-
- void load_favorites();
-
- void list_text_editor_themes();
- void load_text_editor_theme();
- bool import_text_editor_theme(String p_file);
- bool save_text_editor_theme();
- bool save_text_editor_theme_as(String p_file);
-
- void add_shortcut(const String& p_name,Ref<ShortCut>& p_shortcut);
- bool is_shortcut(const String&p_name,const InputEvent& p_event) const;
- Ref<ShortCut> get_shortcut(const String&p_name) const;
- void get_shortcut_list(List<String> *r_shortcuts);
-
- void set_optimize_save(bool p_optimize);
-
- String get_last_selected_language();
- void set_last_selected_language(String p_language);
-
- EditorSettings();
- ~EditorSettings();
-
-};
-
-//not a macro any longer
-
-#define EDITOR_DEF(m_var,m_val) _EDITOR_DEF(m_var,Variant(m_val))
-Variant _EDITOR_DEF( const String& p_var, const Variant& p_default);
-
-#define ED_IS_SHORTCUT(p_name,p_ev) (EditorSettings::get_singleton()->is_shortcut(p_name,p_ev))
-Ref<ShortCut> ED_SHORTCUT(const String& p_path,const String& p_name,uint32_t p_keycode=0);
-Ref<ShortCut> ED_GET_SHORTCUT(const String& p_path);
-
-#endif // EDITOR_SETTINGS_H
diff --git a/tools/editor/editor_sub_scene.cpp b/tools/editor/editor_sub_scene.cpp
deleted file mode 100644
index 094cf049b3..0000000000
--- a/tools/editor/editor_sub_scene.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/*************************************************************************/
-/* editor_sub_scene.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_sub_scene.h"
-
-#include "scene/gui/margin_container.h"
-#include "scene/resources/packed_scene.h"
-
-void EditorSubScene::_path_selected(const String& p_path) {
-
- path->set_text(p_path);
- _path_changed(p_path);
-
-}
-
-void EditorSubScene::_path_changed(const String& p_path) {
-
- tree->clear();
-
-
- if (scene) {
- memdelete(scene);
- scene=NULL;
- }
-
- if (p_path=="")
- return;
-
- Ref<PackedScene> ps = ResourceLoader::load(p_path,"PackedScene");
-
- if (ps.is_null())
- return;
-
- scene = ps->instance();
- if (!scene)
- return;
-
- _fill_tree(scene,NULL);
-
-
-
-}
-
-void EditorSubScene::_path_browse() {
-
- file_dialog->popup_centered_ratio();
-}
-
-
-void EditorSubScene::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
-
- if (!is_visible_in_tree()) {
-
-
- }
- }
-}
-
-
-void EditorSubScene::_fill_tree(Node* p_node,TreeItem *p_parent) {
-
- TreeItem *it = tree->create_item(p_parent);
- it->set_metadata(0,p_node);
- it->set_text(0,p_node->get_name());
- it->set_editable(0,false);
- it->set_selectable(0,true);
- if (has_icon(p_node->get_class(),"EditorIcons")) {
- it->set_icon(0,get_icon(p_node->get_class(),"EditorIcons"));
-
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- Node *c = p_node->get_child(i);
- if (c->get_owner()!=scene)
- continue;
- _fill_tree(c,it);
- }
-
-}
-
-
-void EditorSubScene::ok_pressed() {
-
-
- TreeItem *s = tree->get_selected();
- if (!s)
- return;
- Node *selnode = s->get_metadata(0);
- if (!selnode)
- return;
- emit_signal("subscene_selected");
- hide();
- clear();
-
-
-}
-
-
-void EditorSubScene::_reown(Node* p_node,List<Node*> *p_to_reown) {
-
- if (p_node==scene) {
-
- scene->set_filename("");
- p_to_reown->push_back(p_node);
- } else if (p_node->get_owner()==scene){
-
- p_to_reown->push_back(p_node);
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
- Node *c=p_node->get_child(i);
- _reown(c,p_to_reown);
- }
-}
-
-void EditorSubScene::move(Node* p_new_parent, Node* p_new_owner) {
-
- if (!scene) {
- return;
- }
- TreeItem *s = tree->get_selected();
- if (!s) {
- return;
- }
-
- Node *selnode = s->get_metadata(0);
- if (!selnode) {
- return;
- }
-
- List<Node*> to_reown;
- _reown(selnode,&to_reown);
-
- if (selnode!=scene) {
- selnode->get_parent()->remove_child(selnode);
- }
-
- p_new_parent->add_child(selnode);
- for (List<Node*>::Element *E=to_reown.front();E;E=E->next()) {
- E->get()->set_owner(p_new_owner);
- }
-
- if (selnode!=scene) {
- memdelete(scene);
- }
- scene=NULL;
-
-
- //return selnode;
-
-
-}
-
-void EditorSubScene::clear() {
-
- path->set_text("");
- _path_changed("");
-}
-
-void EditorSubScene::_bind_methods() {
-
- ClassDB::bind_method(_MD("_path_selected"),&EditorSubScene::_path_selected);
- ClassDB::bind_method(_MD("_path_changed"),&EditorSubScene::_path_changed);
- ClassDB::bind_method(_MD("_path_browse"),&EditorSubScene::_path_browse);
- ADD_SIGNAL( MethodInfo("subscene_selected"));
-
-}
-
-
-EditorSubScene::EditorSubScene() {
-
- scene=NULL;
-
- set_title(TTR("Select Node(s) to Import"));
- set_hide_on_ok(false);
-
- VBoxContainer *vb = memnew( VBoxContainer );
- add_child(vb);
- //set_child_rect(vb);
-
- HBoxContainer *hb = memnew( HBoxContainer );
- path = memnew( LineEdit );
- path->connect("text_entered",this,"_path_changed");
- hb->add_child(path);
- path->set_h_size_flags(SIZE_EXPAND_FILL);
- Button *b = memnew( Button );
- b->set_text(" .. ");
- hb->add_child(b);
- b->connect("pressed",this,"_path_browse");
- vb->add_margin_child(TTR("Scene Path:"),hb);
-
- tree = memnew( Tree );
- tree->set_v_size_flags(SIZE_EXPAND_FILL);
- vb->add_margin_child(TTR("Import From Node:"),tree,true);
- tree->connect("item_activated",this,"_ok",make_binds(),CONNECT_DEFERRED);
-
- file_dialog = memnew( EditorFileDialog );
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
-
- for(List<String>::Element *E = extensions.front();E;E=E->next() ) {
-
- file_dialog->add_filter("*."+E->get());
- }
-
- file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- add_child(file_dialog);
- file_dialog->connect("file_selected",this,"_path_selected");
-
-}
diff --git a/tools/editor/editor_sub_scene.h b/tools/editor/editor_sub_scene.h
deleted file mode 100644
index cc9faffc77..0000000000
--- a/tools/editor/editor_sub_scene.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*************************************************************************/
-/* editor_sub_scene.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_SUB_SCENE_H
-#define EDITOR_SUB_SCENE_H
-
-#include "scene/gui/dialogs.h"
-#include "scene/gui/tree.h"
-#include "tools/editor/editor_file_dialog.h"
-
-class EditorSubScene : public ConfirmationDialog {
-
- GDCLASS(EditorSubScene,ConfirmationDialog);
-
-
- LineEdit *path;
- Tree *tree;
- Node *scene;
-
- EditorFileDialog *file_dialog;
-
- void _fill_tree(Node* p_node,TreeItem *p_parent);
- void _reown(Node* p_node,List<Node*> *p_to_reown);
-
- void ok_pressed();
-
-
-protected:
-
-
- void _notification(int p_what);
- static void _bind_methods();
- void _path_browse();
- void _path_selected(const String& p_path);
- void _path_changed(const String& p_path);
-
-public:
-
- void move(Node* p_new_parent, Node* p_new_owner);
- void clear();
- EditorSubScene();
-};
-
-#endif // EDITOR_SUB_SCENE_H
diff --git a/tools/editor/file_type_cache.cpp b/tools/editor/file_type_cache.cpp
deleted file mode 100644
index aff99fbc05..0000000000
--- a/tools/editor/file_type_cache.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************************************/
-/* file_type_cache.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "file_type_cache.h"
-
-#include "globals.h"
-#include "os/file_access.h"
-
-FileTypeCache* FileTypeCache::singleton=NULL;
-
-bool FileTypeCache::has_file(const String& p_path) const {
-
- GLOBAL_LOCK_FUNCTION
- return file_type_map.has(p_path);
-}
-
-String FileTypeCache::get_file_type(const String& p_path) const{
-
- GLOBAL_LOCK_FUNCTION
- ERR_FAIL_COND_V(!file_type_map.has(p_path),"");
- return file_type_map[p_path];
-
-}
-void FileTypeCache::set_file_type(const String& p_path,const String& p_type){
-
- GLOBAL_LOCK_FUNCTION
- file_type_map[p_path]=p_type;
-}
-
-void FileTypeCache::load() {
-
- GLOBAL_LOCK_FUNCTION
- String project=GlobalConfig::get_singleton()->get_resource_path();
- FileAccess *f =FileAccess::open(project+"/file_type_cache.cch",FileAccess::READ);
-
- if (!f) {
-
- WARN_PRINT("Can't open file_type_cache.cch.");
- return;
- }
-
- file_type_map.clear();
- while(!f->eof_reached()) {
-
- String path=f->get_line();
- if (f->eof_reached())
- break;
- String type=f->get_line();
- set_file_type(path,type);
- }
-
- memdelete(f);
-
-}
-
-void FileTypeCache::save() {
-
- GLOBAL_LOCK_FUNCTION
- String project=GlobalConfig::get_singleton()->get_resource_path();
- FileAccess *f =FileAccess::open(project+"/file_type_cache.cch",FileAccess::WRITE);
- if (!f) {
-
- ERR_EXPLAIN(TTR("Can't open file_type_cache.cch for writing, not saving file type cache!"));
- ERR_FAIL();
- }
-
- const String *K=NULL;
-
- while((K=file_type_map.next(K))) {
-
- f->store_line(*K);
- f->store_line(file_type_map[*K]);
- }
-
- memdelete(f);
-
-}
-
-FileTypeCache::FileTypeCache() {
-
- ERR_FAIL_COND(singleton);
- singleton=this;
-}
diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp
deleted file mode 100644
index 08b8307eb4..0000000000
--- a/tools/editor/filesystem_dock.cpp
+++ /dev/null
@@ -1,1858 +0,0 @@
-/*************************************************************************/
-/* filesystem_dock.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "filesystem_dock.h"
-
-#include "os/dir_access.h"
-#include "os/file_access.h"
-#include "globals.h"
-#include "io/resource_loader.h"
-#include "os/os.h"
-#include "editor_node.h"
-#include "editor_settings.h"
-#include "scene/main/viewport.h"
-
-bool FileSystemDock::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir) {
-
- TreeItem *item = tree->create_item(p_parent);
- String dname=p_dir->get_name();
- if (dname=="")
- dname="res://";
- else {
- // collapse every tree item but the root folder
- item->set_collapsed(true);
- }
-
- item->set_text(0,dname);
- item->set_icon(0,get_icon("Folder","EditorIcons"));
- item->set_selectable(0,true);
- String lpath = p_dir->get_path();
- if (lpath!="res://" && lpath.ends_with("/")) {
- lpath=lpath.substr(0,lpath.length()-1);
- }
- item->set_metadata(0,lpath);
- if (lpath==path) {
- item->select(0);
- }
-
- for(int i=0;i<p_dir->get_subdir_count();i++)
- _create_tree(item,p_dir->get_subdir(i));
-
- return true;
-}
-
-
-void FileSystemDock::_update_tree() {
-
- tree->clear();
- updating_tree=true;
- TreeItem *root = tree->create_item();
- TreeItem *favorites = tree->create_item(root);
- favorites->set_icon(0, get_icon("Favorites","EditorIcons") );
- favorites->set_text(0,TTR("Favorites:"));
- favorites->set_selectable(0,false);
- Vector<String> faves = EditorSettings::get_singleton()->get_favorite_dirs();
- for(int i=0;i<faves.size();i++) {
- if (!faves[i].begins_with("res://"))
- continue;
-
- TreeItem *ti = tree->create_item(favorites);
- String fv = faves[i];
- if (fv=="res://")
- ti->set_text(0,"/");
- else
- ti->set_text(0,faves[i].get_file());
- ti->set_icon(0,get_icon("Folder","EditorIcons"));
- ti->set_selectable(0,true);
- ti->set_metadata(0,faves[i]);
- }
-
- _create_tree(root,EditorFileSystem::get_singleton()->get_filesystem());
- updating_tree=false;
-
-}
-
-
-void FileSystemDock::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_RESIZED: {
-
-
- bool new_mode = get_size().height < get_viewport_rect().size.height*3/4;
-
- if (new_mode != split_mode ) {
-
- split_mode=new_mode;
-
- //print_line("SPLIT MODE? "+itos(split_mode));
- if (split_mode) {
-
- file_list_vb->hide();
- tree->set_custom_minimum_size(Size2(0,0));
- tree->set_v_size_flags(SIZE_EXPAND_FILL);
- button_back->show();
- } else {
-
- tree->show();
- file_list_vb->show();
- tree->set_custom_minimum_size(Size2(0,200)*EDSCALE);
- tree->set_v_size_flags(SIZE_FILL);
- button_back->hide();
- if (!EditorFileSystem::get_singleton()->is_scanning()) {
- _fs_changed();
- }
- }
- }
-
-
- } break;
- case NOTIFICATION_ENTER_TREE: {
-
- if (initialized)
- return;
- initialized=true;
-
- EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_fs_changed");
- EditorResourcePreview::get_singleton()->connect("preview_invalidated",this,"_preview_invalidated");
-
- button_reload->set_icon( get_icon("Reload","EditorIcons"));
- button_favorite->set_icon( get_icon("Favorites","EditorIcons"));
- //button_instance->set_icon( get_icon("Add","EditorIcons"));
- //button_open->set_icon( get_icon("Folder","EditorIcons"));
- button_back->set_icon( get_icon("Filesystem","EditorIcons"));
- if (display_mode == DISPLAY_THUMBNAILS) {
- button_display_mode->set_icon(get_icon("FileList","EditorIcons"));
- } else {
- button_display_mode->set_icon(get_icon("FileThumbnail","EditorIcons"));
- }
- button_display_mode->connect("pressed",this,"_change_file_display");
- //file_options->set_icon( get_icon("Tools","EditorIcons"));
- files->connect("item_activated",this,"_select_file");
- button_hist_next->connect("pressed",this,"_fw_history");
- button_hist_prev->connect("pressed",this,"_bw_history");
- search_icon->set_texture( get_icon("Zoom","EditorIcons"));
-
- button_hist_next->set_icon( get_icon("Forward","EditorIcons"));
- button_hist_prev->set_icon( get_icon("Back","EditorIcons"));
- file_options->connect("id_pressed",this,"_file_option");
- folder_options->connect("id_pressed",this,"_folder_option");
-
-
- button_back->connect("pressed",this,"_go_to_tree",varray(),CONNECT_DEFERRED);
- current_path->connect("text_entered",this,"_go_to_dir");
- _update_tree(); //maybe it finished already
-
- if (EditorFileSystem::get_singleton()->is_scanning()) {
- _set_scanning_mode();
- }
-
- } break;
- case NOTIFICATION_PROCESS: {
- if (EditorFileSystem::get_singleton()->is_scanning()) {
- scanning_progress->set_value(EditorFileSystem::get_singleton()->get_scanning_progress()*100);
- }
- } break;
- case NOTIFICATION_EXIT_TREE: {
-
- } break;
- case NOTIFICATION_DRAG_BEGIN: {
-
- Dictionary dd = get_viewport()->gui_get_drag_data();
- if (tree->is_visible_in_tree() && dd.has("type") ) {
- if ( (String(dd["type"])=="files") || (String(dd["type"])=="files_and_dirs") || (String(dd["type"])=="resource")) {
- tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
- }
- if ( (String(dd["type"])=="favorite") ) {
- tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
- }
- }
-
-
- } break;
- case NOTIFICATION_DRAG_END: {
-
- tree->set_drop_mode_flags(0);
-
- } break;
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
-
- int new_mode = int(EditorSettings::get_singleton()->get("docks/filesystem/display_mode"));
-
- if (new_mode != display_mode) {
- set_display_mode(new_mode);
- } else {
- _update_files(true);
- }
- } break;
- }
-
-}
-
-
-
-
-void FileSystemDock::_dir_selected() {
-
- TreeItem *ti = tree->get_selected();
- if (!ti)
- return;
- String dir = ti->get_metadata(0);
- bool found=false;
- Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
- for(int i=0;i<favorites.size();i++) {
-
- if (favorites[i]==dir) {
- found=true;
- break;
- }
- }
-
-
- button_favorite->set_pressed(found);
-
- if (!split_mode) {
- _open_pressed(); //go directly to dir
- }
-
-}
-
-
-void FileSystemDock::_favorites_pressed() {
-
- TreeItem *sel = tree->get_selected();
- if (!sel)
- return ;
- String dir = sel->get_metadata(0);
-
- int idx = -1;
- Vector<String> favorites = EditorSettings::get_singleton()->get_favorite_dirs();
- for(int i=0;i<favorites.size();i++) {
-
- if (favorites[i]==dir) {
- idx=i;
- break;
- }
- }
-
- if (button_favorite->is_pressed() && idx==-1) {
- favorites.push_back(dir);
- EditorSettings::get_singleton()->set_favorite_dirs(favorites);
- _update_tree();
- } else if (!button_favorite->is_pressed() && idx!=-1) {
- favorites.remove(idx);
- EditorSettings::get_singleton()->set_favorite_dirs(favorites);
- _update_tree();
- }
-
-}
-
-String FileSystemDock::get_selected_path() const {
-
- TreeItem *sel = tree->get_selected();
- if (!sel)
- return "";
- String path = sel->get_metadata(0);
- return "res://"+path;
-}
-
-String FileSystemDock::get_current_path() const {
-
- return path;
-}
-
-void FileSystemDock::_thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata) {
-
- bool valid=false;
-
- if (search_box->is_visible()) {
- valid=true;
- } else {
- valid=(path==p_path.get_base_dir());
- }
-
- if (p_preview.is_valid() && valid) {
-
- Array uarr=p_udata;
- int idx=uarr[0];
- String file=uarr[1];
- if (idx>=files->get_item_count())
- return;
- if (files->get_item_text(idx)!=file)
- return;
- String fpath = files->get_item_metadata(idx);
- if (fpath!=p_path)
- return;
- files->set_item_icon(idx,p_preview);
-
- }
-
-}
-
-void FileSystemDock::_change_file_display() {
-
- if (button_display_mode->is_pressed()) {
- display_mode = DISPLAY_LIST;
- button_display_mode->set_icon( get_icon("FileThumbnail","EditorIcons"));
- } else {
- display_mode = DISPLAY_THUMBNAILS;
- button_display_mode->set_icon( get_icon("FileList","EditorIcons"));
- }
-
- EditorSettings::get_singleton()->set("docks/filesystem/display_mode", display_mode);
-
- _update_files(true);
-}
-
-void FileSystemDock::_search(EditorFileSystemDirectory *p_path,List<FileInfo>* matches,int p_max_items) {
-
- if (matches->size()>p_max_items)
- return;
-
- for(int i=0;i<p_path->get_subdir_count();i++) {
- _search(p_path->get_subdir(i),matches,p_max_items);
-
- }
-
- String match = search_box->get_text();
-
- for(int i=0;i<p_path->get_file_count();i++) {
- String file = p_path->get_file(i);
-
- if (file.find(match)!=-1) {
-
- FileInfo fi;
- fi.name=file;
- fi.type=p_path->get_file_type(i);
- fi.path=p_path->get_file_path(i);
- fi.import_status=0;
-
-
- matches->push_back(fi);
- if (matches->size()>p_max_items)
- return;
- }
- }
-}
-
-void FileSystemDock::_update_files(bool p_keep_selection) {
-
- Set<String> cselection;
-
- if (p_keep_selection) {
-
- for(int i=0;i<files->get_item_count();i++) {
-
- if (files->is_selected(i))
- cselection.insert(files->get_item_text(i));
- }
- }
-
- files->clear();
-
- current_path->set_text(path);
-
-
- EditorFileSystemDirectory *efd = EditorFileSystem::get_singleton()->get_filesystem_path(path);
- if (!efd)
- return;
-
- int thumbnail_size = EditorSettings::get_singleton()->get("docks/filesystem/thumbnail_size");
- thumbnail_size*=EDSCALE;
- Ref<Texture> folder_thumbnail;
- Ref<Texture> file_thumbnail;
-
- bool use_thumbnails = (display_mode == DISPLAY_THUMBNAILS);
- bool use_folders = search_box->get_text().length()==0 && split_mode;
-
- if (use_thumbnails) { //thumbnails
-
- files->set_max_columns(0);
- files->set_icon_mode(ItemList::ICON_MODE_TOP);
- files->set_fixed_column_width(thumbnail_size*3/2);
- files->set_max_text_lines(2);
- files->set_fixed_icon_size(Size2(thumbnail_size,thumbnail_size));
-
- if (!has_icon("ResizedFolder","EditorIcons")) {
- Ref<ImageTexture> folder = get_icon("FolderBig","EditorIcons");
- Image img = folder->get_data();
- img.resize(thumbnail_size,thumbnail_size);
- Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture));
- resized_folder->create_from_image(img,0);
- Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder);
- }
-
- folder_thumbnail = get_icon("ResizedFolder","EditorIcons");
-
- if (!has_icon("ResizedFile","EditorIcons")) {
- Ref<ImageTexture> file = get_icon("FileBig","EditorIcons");
- Image img = file->get_data();
- img.resize(thumbnail_size,thumbnail_size);
- Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture));
- resized_file->create_from_image(img,0);
- Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file);
- }
-
- file_thumbnail = get_icon("ResizedFile","EditorIcons");
-
- } else {
-
- files->set_icon_mode(ItemList::ICON_MODE_LEFT);
- files->set_max_columns(1);
- files->set_max_text_lines(1);
- files->set_fixed_column_width(0);
- files->set_fixed_icon_size(Size2());
-
- }
-
- if (use_folders) {
-
- if (path!="res://") {
-
- if (use_thumbnails) {
- files->add_item("..",folder_thumbnail,true);
- } else {
- files->add_item("..",get_icon("folder","FileDialog"),true);
- }
-
- String bd = path.get_base_dir();
- if (bd!="res://" && !bd.ends_with("/"))
- bd+="/";
-
- files->set_item_metadata(files->get_item_count()-1,bd);
- }
-
- for(int i=0;i<efd->get_subdir_count();i++) {
-
- String dname=efd->get_subdir(i)->get_name();
-
-
- if (use_thumbnails) {
- files->add_item(dname,folder_thumbnail,true);
- } else {
- files->add_item(dname,get_icon("folder","FileDialog"),true);
- }
-
- files->set_item_metadata(files->get_item_count()-1,path.plus_file(dname)+"/");
-
- if (cselection.has(dname))
- files->select(files->get_item_count()-1,false);
- }
- }
-
-
- List<FileInfo> filelist;
-
- if (search_box->get_text().length()) {
-
- if (search_box->get_text().length()>1) {
- _search(EditorFileSystem::get_singleton()->get_filesystem(),&filelist,128);
- }
-
- filelist.sort();
- } else {
-
- for(int i=0;i<efd->get_file_count();i++) {
-
- FileInfo fi;
- fi.name=efd->get_file(i);
- fi.path=path.plus_file(fi.name);
- fi.type=efd->get_file_type(i);
- fi.import_status=0;
-
-
-
- filelist.push_back(fi);
- }
- }
-
- StringName ei="EditorIcons"; //make it faster..
- StringName oi="Object";
-
-
- for(List<FileInfo>::Element *E=filelist.front();E;E=E->next()) {
- String fname=E->get().name;
- String fp = E->get().path;
- StringName type = E->get().type;
-
- Ref<Texture> type_icon;
-
- String tooltip=fname;
-
- if (E->get().import_status==0) {
-
- if (has_icon(type,ei)) {
- type_icon=get_icon(type,ei);
- } else {
- type_icon=get_icon(oi,ei);
- }
- } else if (E->get().import_status==1) {
- type_icon=get_icon("DependencyOk","EditorIcons");
- } else if (E->get().import_status==2) {
- type_icon=get_icon("DependencyChanged","EditorIcons");
- tooltip+"\nStatus: Needs Re-Import";
- } else if (E->get().import_status==3) {
- type_icon=get_icon("ImportFail","EditorIcons");
- tooltip+"\nStatus: Missing Dependencies";
- }
-
- if (E->get().sources.size()) {
- for(int i=0;i<E->get().sources.size();i++) {
- tooltip+="\nSource: "+E->get().sources[i];
- }
- }
-
-
-
- if (use_thumbnails) {
- files->add_item(fname,file_thumbnail,true);
- files->set_item_metadata(files->get_item_count()-1,fp);
- files->set_item_tag_icon(files->get_item_count()-1,type_icon);
- Array udata;
- udata.resize(2);
- udata[0]=files->get_item_count()-1;
- udata[1]=fname;
- EditorResourcePreview::get_singleton()->queue_resource_preview(fp,this,"_thumbnail_done",udata);
- } else {
- files->add_item(fname,type_icon,true);
- files->set_item_metadata(files->get_item_count()-1,fp);
-
- }
-
- if (cselection.has(fname))
- files->select(files->get_item_count()-1,false);
-
- files->set_item_tooltip(files->get_item_count()-1,tooltip);
-
-
- }
-
-
-}
-
-void FileSystemDock::_select_file(int p_idx) {
-
- files->select(p_idx,true);
- _file_option(FILE_OPEN);
-}
-
-void FileSystemDock::_go_to_tree() {
-
- tree->show();
- file_list_vb->hide();
- _update_tree();
- tree->grab_focus();
- tree->ensure_cursor_is_visible();
- button_favorite->show();
- //button_open->hide();
- //file_options->hide();
-}
-
-void FileSystemDock::_go_to_dir(const String& p_dir){
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (da->change_dir(p_dir)==OK) {
- path=da->get_current_dir();
- _update_files(false);
- }
- current_path->set_text(path);
- memdelete(da);
-
-
-}
-
-void FileSystemDock::_preview_invalidated(const String& p_path) {
-
- if (p_path.get_base_dir()==path && search_box->get_text()==String() && file_list_vb->is_visible_in_tree()) {
-
-
- for(int i=0;i<files->get_item_count();i++) {
-
- if (files->get_item_metadata(i)==p_path) {
- //re-request preview
- Array udata;
- udata.resize(2);
- udata[0]=i;
- udata[1]=files->get_item_text(i);
- EditorResourcePreview::get_singleton()->queue_resource_preview(p_path,this,"_thumbnail_done",udata);
- break;
- }
- }
- }
-}
-
-void FileSystemDock::_fs_changed() {
-
- button_hist_prev->set_disabled(history_pos==0);
- button_hist_next->set_disabled(history_pos+1==history.size());
- scanning_vb->hide();
- split_box->show();
-
- if (tree->is_visible()) {
- button_favorite->show();
- _update_tree();
-
- }
-
- if (file_list_vb->is_visible()) {
-
- _update_files(true);
- }
-
- set_process(false);
-}
-
-void FileSystemDock::_set_scanning_mode() {
-
- split_box->hide();
- button_hist_prev->set_disabled(true);
- button_hist_next->set_disabled(true);
- scanning_vb->show();
- set_process(true);
- if (EditorFileSystem::get_singleton()->is_scanning()) {
- scanning_progress->set_value(EditorFileSystem::get_singleton()->get_scanning_progress()*100);
- } else {
- scanning_progress->set_value(0);
- }
-
-}
-
-void FileSystemDock::_fw_history() {
-
- if (history_pos<history.size()-1)
- history_pos++;
-
- path=history[history_pos];
-
- if (tree->is_visible()) {
- _update_tree();
- tree->grab_focus();
- tree->ensure_cursor_is_visible();
-
- }
-
- if (file_list_vb->is_visible()) {
- _update_files(false);
- current_path->set_text(path);
- }
-
- button_hist_prev->set_disabled(history_pos==0);
- button_hist_next->set_disabled(history_pos+1==history.size());
-
-}
-
-void FileSystemDock::_bw_history() {
-
- if (history_pos>0)
- history_pos--;
-
- path=history[history_pos];
-
-
- if (tree->is_visible()) {
- _update_tree();
- tree->grab_focus();
- tree->ensure_cursor_is_visible();
- }
-
- if (file_list_vb->is_visible()) {
- _update_files(false);
- current_path->set_text(path);
- }
-
- button_hist_prev->set_disabled(history_pos==0);
- button_hist_next->set_disabled(history_pos+1==history.size());
-
-}
-
-void FileSystemDock::_push_to_history() {
-
- history.resize(history_pos+1);
- if (history[history_pos]!=path) {
- history.push_back(path);
- history_pos++;
- }
-
- button_hist_prev->set_disabled(history_pos==0);
- button_hist_next->set_disabled(history_pos+1==history.size());
-
-}
-
-
-void FileSystemDock::_find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files) {
-
- for(int i=0;i<efsd->get_subdir_count();i++) {
- _find_inside_move_files(efsd->get_subdir(i),files);
- }
- for(int i=0;i<efsd->get_file_count();i++) {
- files.push_back(efsd->get_file_path(i));
- }
-
-}
-
-void FileSystemDock::_find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps) {
-
- for(int i=0;i<efsd->get_subdir_count();i++) {
- _find_remaps(efsd->get_subdir(i),renames,to_remaps);
- }
- for(int i=0;i<efsd->get_file_count();i++) {
- Vector<String> deps=efsd->get_file_deps(i);
- for(int j=0;j<deps.size();j++) {
- if (renames.has(deps[j])) {
- to_remaps.push_back(efsd->get_file_path(i));
- break;
- }
- }
- }
-}
-
-
-void FileSystemDock::_rename_operation(const String& p_to_path) {
-
- if (move_files[0]==p_to_path) {
- EditorNode::get_singleton()->show_warning(TTR("Same source and destination files, doing nothing."));
- return;
- }
- if (FileAccess::exists(p_to_path)) {
- EditorNode::get_singleton()->show_warning("Target file exists, can't overwrite. Delete first.");
- return;
- }
-
- Map<String,String> renames;
- renames[move_files[0]]=p_to_path;
-
- List<String> remap;
-
- _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap);
- print_line("found files to remap: "+itos(remap.size()));
-
- //perform remaps
- for(List<String>::Element *E=remap.front();E;E=E->next()) {
-
- Error err = ResourceLoader::rename_dependencies(E->get(),renames);
- print_line("remapping: "+E->get());
-
- if (err!=OK) {
- EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n");
- }
- }
-
- //finally, perform moves
-
- DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES);
-
- Error err = da->rename(move_files[0],p_to_path);
- print_line("moving file "+move_files[0]+" to "+p_to_path);
- if (err!=OK) {
- EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[0]+"\n");
- }
-
- //rescan everything
- memdelete(da);
- print_line("call rescan!");
- _rescan();
-}
-
-
-void FileSystemDock::_move_operation(const String& p_to_path) {
-
- if (p_to_path==path) {
- EditorNode::get_singleton()->show_warning(TTR("Same source and destination paths, doing nothing."));
- return;
- }
-
- //find files inside dirs to be moved
-
- Vector<String> inside_files;
-
- for(int i=0;i<move_dirs.size();i++) {
- if (p_to_path.begins_with(move_dirs[i])) {
- EditorNode::get_singleton()->show_warning(TTR("Can't move directories to within themselves."));
- return;
- }
-
- EditorFileSystemDirectory *efsd=EditorFileSystem::get_singleton()->get_filesystem_path(move_dirs[i]);
- if (!efsd)
- continue;
- _find_inside_move_files(efsd,inside_files);
- }
-
- //make list of remaps
- Map<String,String> renames;
- String repfrom=path=="res://"?path:String(path+"/");
- String repto=p_to_path=="res://"?p_to_path:String(p_to_path+"/");
-
- for(int i=0;i<move_files.size();i++) {
- renames[move_files[i]]=move_files[i].replace_first(repfrom,repto);
- print_line("move file "+move_files[i]+" -> "+renames[move_files[i]]);
- }
- for(int i=0;i<inside_files.size();i++) {
- renames[inside_files[i]]=inside_files[i].replace_first(repfrom,repto);
- print_line("inside file "+inside_files[i]+" -> "+renames[inside_files[i]]);
- }
-
- //make list of files that will be run the remapping
- List<String> remap;
-
- _find_remaps(EditorFileSystem::get_singleton()->get_filesystem(),renames,remap);
- print_line("found files to remap: "+itos(remap.size()));
-
- //perform remaps
- for(List<String>::Element *E=remap.front();E;E=E->next()) {
-
- Error err = ResourceLoader::rename_dependencies(E->get(),renames);
- print_line("remapping: "+E->get());
-
- if (err!=OK) {
- EditorNode::get_singleton()->add_io_error("Can't rename deps for:\n"+E->get()+"\n");
- }
- }
-
- //finally, perform moves
-
- DirAccess *da=DirAccess::create(DirAccess::ACCESS_RESOURCES);
-
- for(int i=0;i<move_files.size();i++) {
-
- String to = move_files[i].replace_first(repfrom,repto);
- Error err = da->rename(move_files[i],to);
- print_line("moving file "+move_files[i]+" to "+to);
- if (err!=OK) {
- EditorNode::get_singleton()->add_io_error("Error moving file:\n"+move_files[i]+"\n");
- }
- }
-
- for(int i=0;i<move_dirs.size();i++) {
-
- String mdir = move_dirs[i];
- if (mdir=="res://")
- continue;
-
- if (mdir.ends_with("/")) {
- mdir=mdir.substr(0,mdir.length()-1);
- }
-
- String to = p_to_path.plus_file(mdir.get_file());
- Error err = da->rename(mdir,to);
- print_line("moving dir "+mdir+" to "+to);
- if (err!=OK) {
- EditorNode::get_singleton()->add_io_error("Error moving dir:\n"+move_dirs[i]+"\n");
- }
- }
-
- memdelete(da);
- //rescan everything
- print_line("call rescan!");
- _rescan();
-
-}
-
-void FileSystemDock::_file_option(int p_option) {
-
- switch(p_option) {
-
-
- case FILE_SHOW_IN_EXPLORER:
- case FILE_OPEN: {
- int idx=-1;
- for(int i=0;i<files->get_item_count();i++) {
- if (files->is_selected(i)) {
- idx=i;
- break;
- }
- }
-
- if (idx<0)
- return;
-
-
-
- String path = files->get_item_metadata(idx);
- if (p_option == FILE_SHOW_IN_EXPLORER) {
- String dir = GlobalConfig::get_singleton()->globalize_path(path);
- dir = dir.substr(0, dir.find_last("/"));
- OS::get_singleton()->shell_open(String("file://")+dir);
- return;
- }
-
- if (path.ends_with("/")) {
- if (path!="res://") {
- path=path.substr(0,path.length()-1);
- }
- this->path=path;
- _update_files(false);
- current_path->set_text(path);
- _push_to_history();
- } else {
-
- if (ResourceLoader::get_resource_type(path)=="PackedScene") {
-
- editor->open_request(path);
- } else {
-
- editor->load_resource(path);
- }
- }
- } break;
- case FILE_INSTANCE: {
-
- Vector<String> paths;
-
- for (int i = 0; i<files->get_item_count(); i++) {
- if (!files->is_selected(i))
- continue;
- String path =files->get_item_metadata(i);
- if (EditorFileSystem::get_singleton()->get_file_type(path)=="PackedScene") {
- paths.push_back(path);
- }
- }
-
- if (!paths.empty()) {
- emit_signal("instance", paths);
- }
- } break;
- case FILE_DEPENDENCIES: {
-
- int idx = files->get_current();
- if (idx<0 || idx>=files->get_item_count())
- break;
- String path = files->get_item_metadata(idx);
- deps_editor->edit(path);
- } break;
- case FILE_OWNERS: {
-
- int idx = files->get_current();
- if (idx<0 || idx>=files->get_item_count())
- break;
- String path = files->get_item_metadata(idx);
- owners_editor->show(path);
- } break;
- case FILE_MOVE: {
-
- move_dirs.clear();
- move_files.clear();
-
- for(int i=0;i<files->get_item_count();i++) {
-
- String path = files->get_item_metadata(i);
- if (!files->is_selected(i))
- continue;
-
- if (files->get_item_text(i)=="..") {
- EditorNode::get_singleton()->show_warning(TTR("Can't operate on '..'"));
- return;
- }
-
- if (path.ends_with("/")) {
- move_dirs.push_back(path.substr(0,path.length()-1));
- } else {
- move_files.push_back(path);
- }
- }
-
-
- if (move_dirs.empty() && move_files.size()==1) {
-
- rename_dialog->clear_filters();
- rename_dialog->add_filter("*."+move_files[0].get_extension());
- rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- rename_dialog->set_current_path(move_files[0]);
- rename_dialog->popup_centered_ratio();
- rename_dialog->set_title(TTR("Pick New Name and Location For:")+" "+move_files[0].get_file());
-
-
- } else {
- //just move
- move_dialog->popup_centered_ratio();
- }
-
-
- } break;
- case FILE_REMOVE: {
-
- Vector<String> torem;
-
- for(int i=0;i<files->get_item_count();i++) {
-
- String path = files->get_item_metadata(i);
- if (path.ends_with("/") || !files->is_selected(i))
- continue;
- torem.push_back(path);
-
- }
-
- if (torem.empty()) {
- EditorNode::get_singleton()->show_warning(TTR("No files selected!"));
- break;
- }
-
- remove_dialog->show(torem);
- //1) find if used
- //2) warn
-
- } break;
- case FILE_INFO: {
-
- } break;
- case FILE_REIMPORT: {
-
-
- Vector<String> reimport;
- for(int i=0;i<files->get_item_count();i++) {
-
- if (!files->is_selected(i))
- continue;
-
- String path = files->get_item_metadata(i);
- reimport.push_back(path);
- }
-
- ERR_FAIL_COND(reimport.size()==0);
-/*
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(reimport[0]);
- ERR_FAIL_COND(!rimd.is_valid());
- String editor=rimd->get_editor();
-
- if (editor.begins_with("texture_")) { //compatibility fix for old texture format
- editor="texture";
- }
-
- Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(editor);
- ERR_FAIL_COND(!rimp.is_valid());
-
- if (reimport.size()==1) {
- rimp->import_dialog(reimport[0]);
- } else {
- rimp->reimport_multiple_files(reimport);
-
- }
- */
-
- } break;
- case FILE_COPY_PATH:
-
- int idx = files->get_current();
- if (idx<0 || idx>=files->get_item_count())
- break;
- String path = files->get_item_metadata(idx);
- OS::get_singleton()->set_clipboard(path);
- }
-}
-
-void FileSystemDock::_folder_option(int p_option) {
-
- TreeItem *item = tree->get_selected();
- TreeItem *child = item->get_children();
-
- switch(p_option) {
-
- case FOLDER_EXPAND_ALL:
- item->set_collapsed(false);
- while(child) {
- child->set_collapsed(false);
- child = child->get_next();
- }
- break;
-
- case FOLDER_COLLAPSE_ALL:
- while(child) {
- child->set_collapsed(true);
- child = child->get_next();
- }
- break;
- }
-}
-
-void FileSystemDock::_open_pressed(){
-
-
- TreeItem *sel = tree->get_selected();
- if (!sel) {
- return;
- }
- path = sel->get_metadata(0);
- /*if (path!="res://" && path.ends_with("/")) {
- path=path.substr(0,path.length()-1);
- }*/
-
- //tree_mode=false;
-
- if (split_mode) {
- tree->hide();
- file_list_vb->show();
- button_favorite->hide();
- }
-
- //file_options->show();
-
- _update_files(false);
- current_path->set_text(path);
- _push_to_history();
-
- //emit_signal("open",path);
-
-}
-
-void FileSystemDock::_dir_rmb_pressed(const Vector2& p_pos) {
- folder_options->clear();
- folder_options->set_size(Size2(1,1));
-
- folder_options->add_item(TTR("Expand all"),FOLDER_EXPAND_ALL);
- folder_options->add_item(TTR("Collapse all"),FOLDER_COLLAPSE_ALL);
-
- folder_options->set_pos(files->get_global_pos() + p_pos);
- folder_options->popup();
-}
-
-
-void FileSystemDock::_search_changed(const String& p_text) {
-
- if (!search_box->is_visible_in_tree())
- return; //wtf
-
- _update_files(false);
-}
-
-void FileSystemDock::_rescan() {
-
- _set_scanning_mode();
- EditorFileSystem::get_singleton()->scan();
-
-}
-
-void FileSystemDock::fix_dependencies(const String& p_for_file) {
- deps_editor->edit(p_for_file);
-}
-
-
-void FileSystemDock::focus_on_filter() {
-
- if (!search_box->is_visible_in_tree()) {
- // Tree mode, switch to files list with search box
- tree->hide();
- file_list_vb->show();
- button_favorite->hide();
- }
-
- search_box->grab_focus();
-}
-
-void FileSystemDock::set_display_mode(int p_mode) {
-
- if (p_mode == display_mode)
- return;
-
- button_display_mode->set_pressed(p_mode == DISPLAY_LIST);
- _change_file_display();
-}
-
-
-Variant FileSystemDock::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- if (p_from==tree) {
-
- TreeItem *selected = tree->get_selected();
- if (!selected)
- return Variant();
-
- String path = selected->get_metadata(0);
- if (path==String())
- return Variant();
- if (!path.ends_with("/"))
- path=path+"/";
- Vector<String> paths;
- paths.push_back(path);
- Dictionary d = EditorNode::get_singleton()->drag_files(paths,p_from);
-
- if (selected->get_parent() && tree->get_root()->get_children()==selected->get_parent()) {
- //a favorite.. treat as such
- d["type"]="favorite";
- }
-
- return d;
-
- }
-
- if (p_from==files) {
-
- List<int> seldirs;
- List<int> selfiles;
-
- for (int i = 0; i<files->get_item_count(); i++) {
- if (files->is_selected(i)) {
- String path = files->get_item_metadata(i);
- if (path.ends_with("/"))
- seldirs.push_back(i);
- else
- selfiles.push_back(i);
- }
- }
-
- if (seldirs.empty() && selfiles.empty())
- return Variant();
- /*
- if (seldirs.size() && selfiles.size())
- return Variant(); //can't really mix files and dirs (i think?) - yes you can, commenting
- */
-
- /*if (selfiles.size()==1) {
- Ref<Resource> resource = ResourceLoader::load(files->get_item_metadata(selfiles.front()->get()));
- if (resource.is_valid()) {
- return EditorNode::get_singleton()->drag_resource(resource,p_from);
- }
- }*/
-
- if (selfiles.size()>0 && seldirs.size()==0) {
- Vector<String> fnames;
- for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
- return EditorNode::get_singleton()->drag_files(fnames,p_from);
- }
-
- if (selfiles.size()>0 || seldirs.size()>0) {
- Vector<String> fnames;
- for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
- for(List<int>::Element *E=seldirs.front();E;E=E->next()) {
- fnames.push_back(files->get_item_metadata(E->get()));
- }
- return EditorNode::get_singleton()->drag_files_and_dirs(fnames,p_from);
- }
-
- }
-
- return Variant();
-}
-
-bool FileSystemDock::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
-
- Dictionary drag_data = p_data;
-
- if (drag_data.has("type") && String(drag_data["type"])=="favorite") {
-
- //moving favorite around
- TreeItem *ti = tree->get_item_at_pos(p_point);
- if (!ti)
- return false;
-
- int what = tree->get_drop_section_at_pos(p_point);
-
- if (ti==tree->get_root()->get_children()) {
- return (what==1); //the parent, first fav
- }
- if (ti->get_parent() && tree->get_root()->get_children()==ti->get_parent()) {
- return true; // a favorite
- }
-
- if (ti==tree->get_root()->get_children()->get_next()) {
- return (what==-1); //the tree, last fav
- }
-
- return false;
-
- }
-
-
- if (drag_data.has("type") && String(drag_data["type"])=="resource") {
- return true;
- }
-
- if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
-
- Vector<String> fnames = drag_data["files"];
-
- if (p_from==files) {
-
- int at_pos = files->get_item_at_pos(p_point);
- if (at_pos!=-1) {
-
- String dir = files->get_item_metadata(at_pos);
- if (dir.ends_with("/"))
- return true;
- }
- }
-
- if (p_from==tree) {
-
- TreeItem *ti = tree->get_item_at_pos(p_point);
- if (!ti)
- return false;
- String path = ti->get_metadata(0);
-
- if (path==String())
- return false;
-
- return true;
- }
-
- }
-
- return false;
-}
-
-void FileSystemDock::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
-
- if (!can_drop_data_fw(p_point,p_data,p_from))
- return;
- Dictionary drag_data = p_data;
-
- if (drag_data.has("type") && String(drag_data["type"])=="favorite") {
-
- //moving favorite around
- TreeItem *ti = tree->get_item_at_pos(p_point);
- if (!ti)
- return;
-
- Vector<String> files = drag_data["files"];
-
- ERR_FAIL_COND(files.size()!=1);
-
- String swap = files[0];
- if (swap!="res://" && swap.ends_with("/")) {
- swap=swap.substr(0,swap.length()-1);
- }
-
- int what = tree->get_drop_section_at_pos(p_point);
-
- TreeItem *swap_item=NULL;
-
- if (ti==tree->get_root()->get_children()) {
- swap_item=tree->get_root()->get_children()->get_children();
-
- } else if (ti->get_parent() && tree->get_root()->get_children()==ti->get_parent()) {
- if (what==-1) {
- swap_item=ti;
- } else {
- swap_item=ti->get_next();
- }
- }
-
- String swap_with;
-
- if (swap_item) {
- swap_with=swap_item->get_metadata(0);
- if (swap_with!="res://" && swap_with.ends_with("/")) {
- swap_with=swap_with.substr(0,swap_with.length()-1);
- }
- }
-
- if (swap==swap_with)
- return;
-
- Vector<String> dirs = EditorSettings::get_singleton()->get_favorite_dirs();
-
- ERR_FAIL_COND(dirs.find(swap)==-1);
- ERR_FAIL_COND(swap_with!=String() && dirs.find(swap_with)==-1);
-
- dirs.erase(swap);
-
- if (swap_with==String()) {
- dirs.push_back(swap);
- } else {
- int idx = dirs.find(swap_with);
- dirs.insert(idx,swap);
- }
-
- EditorSettings::get_singleton()->set_favorite_dirs(dirs);
- _update_tree();
- return;
-
- }
-
- if (drag_data.has("type") && String(drag_data["type"])=="resource") {
- Ref<Resource> res = drag_data["resource"];
-
- if (!res.is_valid()) {
- return;
- }
-
-
- if (p_from==tree) {
-
- TreeItem *ti = tree->get_item_at_pos(p_point);
- if (!ti)
- return;
- String path = ti->get_metadata(0);
-
- if (path==String())
- return;
-
- EditorNode::get_singleton()->save_resource_as(res,path);
- return;
-
- }
-
- if (p_from==files) {
- String save_path=path;
-
- int at_pos = files->get_item_at_pos(p_point);
- if (at_pos!=-1) {
- String to_dir = files->get_item_metadata(at_pos);
- if (to_dir.ends_with("/")) {
- save_path=to_dir;
- if (save_path!="res://")
- save_path=save_path.substr(0,save_path.length()-1);
- }
-
- }
-
- EditorNode::get_singleton()->save_resource_as(res,save_path);
- return;
- }
- }
-
- if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
-
- if (p_from==files || p_from==tree) {
-
- String to_dir;
-
- if (p_from==files) {
-
- int at_pos = files->get_item_at_pos(p_point);
- ERR_FAIL_COND(at_pos==-1);
- to_dir = files->get_item_metadata(at_pos);
- } else {
- TreeItem *ti = tree->get_item_at_pos(p_point);
- if (!ti)
- return;
- to_dir = ti->get_metadata(0);
- ERR_FAIL_COND(to_dir==String());
-
- }
-
- if (to_dir!="res://" && to_dir.ends_with("/")) {
- to_dir=to_dir.substr(0,to_dir.length()-1);
- }
-
- Vector<String> fnames = drag_data["files"];
- move_files.clear();
- move_dirs.clear();
-
- for(int i=0;i<fnames.size();i++) {
- if (fnames[i].ends_with("/"))
- move_dirs.push_back(fnames[i]);
- else
- move_files.push_back(fnames[i]);
- }
-
- _move_operation(to_dir);
- }
- }
-
-}
-
-void FileSystemDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) {
-
- Vector<String> filenames;
-
- bool all_scenes=true;
- bool all_can_reimport=true;
- Set<String> types;
-
- for(int i=0;i<files->get_item_count();i++) {
-
- if (!files->is_selected(i))
- continue;
-
- String path = files->get_item_metadata(i);
-
- if (files->get_item_text(i)=="..") {
- // no operate on ..
- return;
- }
-
- if (path.ends_with("/")) {
- //no operate on dirs
- return;
- }
-
-
- EditorFileSystemDirectory *efsd=NULL;
- int pos;
-
- efsd = EditorFileSystem::get_singleton()->find_file(path,&pos);
-
- if (efsd) {
-
-
- } else {
- all_can_reimport=false;
-
- }
-
- filenames.push_back(path);
- if (EditorFileSystem::get_singleton()->get_file_type(path)!="PackedScene")
- all_scenes=false;
- }
-
-
- if (filenames.size()==0)
- return;
-
- file_options->clear();
- file_options->set_size(Size2(1,1));
-
- file_options->add_item(TTR("Open"),FILE_OPEN);
- if (all_scenes) {
- file_options->add_item(TTR("Instance"),FILE_INSTANCE);
- }
-
- file_options->add_separator();
-
- if (filenames.size()==1) {
- file_options->add_item(TTR("Edit Dependencies.."),FILE_DEPENDENCIES);
- file_options->add_item(TTR("View Owners.."),FILE_OWNERS);
- file_options->add_separator();
- }
-
- if (filenames.size()==1) {
- file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH);
- file_options->add_item(TTR("Rename or Move.."),FILE_MOVE);
- } else {
- file_options->add_item(TTR("Move To.."),FILE_MOVE);
- }
-
-
- file_options->add_item(TTR("Delete"),FILE_REMOVE);
-
- //file_options->add_item(TTR("Info"),FILE_INFO);
-
- file_options->add_separator();
- file_options->add_item(TTR("Show In File Manager"),FILE_SHOW_IN_EXPLORER);
-
- if (all_can_reimport && types.size()==1) { //all can reimport and are of the same type
-
-/*
- bool valid=true;
- Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(types.front()->get());
- if (rimp.is_valid()) {
-
- if (filenames.size()>1 && !rimp->can_reimport_multiple_files()) {
- valid=false;
- }
- } else {
- valid=false;
- }
-
- if (valid) {
- file_options->add_separator();
- file_options->add_item(TTR("Re-Import.."),FILE_REIMPORT);
- }
- */
- }
-
- file_options->set_pos(files->get_global_pos() + p_pos);
- file_options->popup();
-
-}
-
-void FileSystemDock::select_file(const String& p_file) {
-
- _go_to_dir(p_file.get_base_dir());
- for(int i=0;i<files->get_item_count();i++) {
- if (files->get_item_metadata(i)==p_file) {
- files->select(i);
- files->ensure_current_is_visible();
- break;
- }
- }
-
-}
-
-void FileSystemDock::_file_multi_selected(int p_index,bool p_selected) {
-
-
- _file_selected();
-}
-
-void FileSystemDock::_file_selected() {
-
- //check import
- Vector<String> imports;
- String import_type;
-
- for(int i=0;i<files->get_item_count();i++) {
- if (!files->is_selected(i))
- continue;
-
- String p = files->get_item_metadata(i);
- if (!FileAccess::exists(p+".import")) {
- imports.clear();
- break;
- }
- Ref<ConfigFile> cf;
- cf.instance();
- Error err = cf->load(p+".import");
- if (err!=OK) {
- imports.clear();
- break;
- }
-
- String type = cf->get_value("remap","type");
- if (import_type=="") {
- import_type=type;
- } else if (import_type!=type) {
- //all should be the same type
- imports.clear();
- break;
- }
- imports.push_back(p);
- }
-
-
- if (imports.size()==0) {
- EditorNode::get_singleton()->get_import_dock()->clear();
- } else if (imports.size()==1) {
- EditorNode::get_singleton()->get_import_dock()->set_edit_path(imports[0]);
- } else {
- EditorNode::get_singleton()->get_import_dock()->set_edit_multiple_paths(imports);
- }
-}
-
-
-void FileSystemDock::_bind_methods() {
-
- ClassDB::bind_method(_MD("_update_tree"),&FileSystemDock::_update_tree);
- ClassDB::bind_method(_MD("_rescan"),&FileSystemDock::_rescan);
- ClassDB::bind_method(_MD("_favorites_pressed"),&FileSystemDock::_favorites_pressed);
- //ClassDB::bind_method(_MD("_instance_pressed"),&ScenesDock::_instance_pressed);
- ClassDB::bind_method(_MD("_open_pressed"),&FileSystemDock::_open_pressed);
- ClassDB::bind_method(_MD("_dir_rmb_pressed"),&FileSystemDock::_dir_rmb_pressed);
-
- ClassDB::bind_method(_MD("_thumbnail_done"),&FileSystemDock::_thumbnail_done);
- ClassDB::bind_method(_MD("_select_file"), &FileSystemDock::_select_file);
- ClassDB::bind_method(_MD("_go_to_tree"), &FileSystemDock::_go_to_tree);
- ClassDB::bind_method(_MD("_go_to_dir"), &FileSystemDock::_go_to_dir);
- ClassDB::bind_method(_MD("_change_file_display"), &FileSystemDock::_change_file_display);
- ClassDB::bind_method(_MD("_fw_history"), &FileSystemDock::_fw_history);
- ClassDB::bind_method(_MD("_bw_history"), &FileSystemDock::_bw_history);
- ClassDB::bind_method(_MD("_fs_changed"), &FileSystemDock::_fs_changed);
- ClassDB::bind_method(_MD("_dir_selected"), &FileSystemDock::_dir_selected);
- ClassDB::bind_method(_MD("_file_option"), &FileSystemDock::_file_option);
- ClassDB::bind_method(_MD("_folder_option"), &FileSystemDock::_folder_option);
- ClassDB::bind_method(_MD("_move_operation"), &FileSystemDock::_move_operation);
- ClassDB::bind_method(_MD("_rename_operation"), &FileSystemDock::_rename_operation);
-
- ClassDB::bind_method(_MD("_search_changed"), &FileSystemDock::_search_changed);
-
- ClassDB::bind_method(_MD("get_drag_data_fw"), &FileSystemDock::get_drag_data_fw);
- ClassDB::bind_method(_MD("can_drop_data_fw"), &FileSystemDock::can_drop_data_fw);
- ClassDB::bind_method(_MD("drop_data_fw"), &FileSystemDock::drop_data_fw);
- ClassDB::bind_method(_MD("_files_list_rmb_select"),&FileSystemDock::_files_list_rmb_select);
-
- ClassDB::bind_method(_MD("_preview_invalidated"),&FileSystemDock::_preview_invalidated);
- ClassDB::bind_method(_MD("_file_selected"),&FileSystemDock::_file_selected);
- ClassDB::bind_method(_MD("_file_multi_selected"),&FileSystemDock::_file_multi_selected);
-
-
- ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::POOL_STRING_ARRAY, "files")));
- ADD_SIGNAL(MethodInfo("open"));
-
-}
-
-FileSystemDock::FileSystemDock(EditorNode *p_editor) {
-
- editor=p_editor;
-
-
- HBoxContainer *toolbar_hbc = memnew( HBoxContainer );
- add_child(toolbar_hbc);
-
- button_hist_prev = memnew( ToolButton );
- toolbar_hbc->add_child(button_hist_prev);
- button_hist_prev->set_disabled(true);
- button_hist_prev->set_tooltip(TTR("Previous Directory"));
-
- button_hist_next = memnew( ToolButton );
- toolbar_hbc->add_child(button_hist_next);
- button_hist_next->set_disabled(true);
- button_hist_prev->set_focus_mode(FOCUS_NONE);
- button_hist_next->set_focus_mode(FOCUS_NONE);
- button_hist_next->set_tooltip(TTR("Next Directory"));
-
- current_path=memnew( LineEdit );
- current_path->set_h_size_flags(SIZE_EXPAND_FILL);
- toolbar_hbc->add_child(current_path);
-
-
- button_reload = memnew( Button );
- button_reload->set_flat(true);
- button_reload->connect("pressed",this,"_rescan");
- toolbar_hbc->add_child(button_reload);
- button_reload->set_focus_mode(FOCUS_NONE);
- button_reload->set_tooltip(TTR("Re-Scan Filesystem"));
- button_reload->hide();
-
- //toolbar_hbc->add_spacer();
-
-
- button_favorite = memnew( Button );
- button_favorite->set_flat(true);
- button_favorite->set_toggle_mode(true);
- button_favorite->connect("pressed",this,"_favorites_pressed");
- toolbar_hbc->add_child(button_favorite);
- button_favorite->set_tooltip(TTR("Toggle folder status as Favorite"));
-
- button_favorite->set_focus_mode(FOCUS_NONE);
-
- //Control *spacer = memnew( Control);
-
-
-
-/*
- button_open = memnew( Button );
- button_open->set_flat(true);
- button_open->connect("pressed",this,"_open_pressed");
- toolbar_hbc->add_child(button_open);
- button_open->hide();
- button_open->set_focus_mode(FOCUS_NONE);
- button_open->set_tooltip("Open the selected file.\nOpen as scene if a scene, or as resource otherwise.");
-
-
- button_instance = memnew( Button );
- button_instance->set_flat(true);
- button_instance->connect("pressed",this,"_instance_pressed");
- toolbar_hbc->add_child(button_instance);
- button_instance->hide();
- button_instance->set_focus_mode(FOCUS_NONE);
- button_instance->set_tooltip(TTR("Instance the selected scene(s) as child of the selected node."));
-
-*/
- file_options = memnew( PopupMenu );
- add_child(file_options);
-
- folder_options = memnew ( PopupMenu );
- add_child(folder_options);
-
- split_box = memnew( VSplitContainer );
- add_child(split_box);
- split_box->set_v_size_flags(SIZE_EXPAND_FILL);
-
- tree = memnew( Tree );
-
- tree->set_hide_root(true);
- split_box->add_child(tree);
- tree->set_drag_forwarding(this);
- tree->set_allow_rmb_select(true);
-
-
- //tree->set_v_size_flags(SIZE_EXPAND_FILL);
- tree->connect("item_edited",this,"_favorite_toggled");
- tree->connect("item_activated",this,"_open_pressed");
- tree->connect("cell_selected",this,"_dir_selected");
- tree->connect("item_rmb_selected",this,"_dir_rmb_pressed");
-
- files = memnew( ItemList );
- files->set_v_size_flags(SIZE_EXPAND_FILL);
- files->set_select_mode(ItemList::SELECT_MULTI);
- files->set_drag_forwarding(this);
- files->connect("item_rmb_selected",this,"_files_list_rmb_select");
- files->connect("item_selected",this,"_file_selected");
- files->connect("multi_selected",this,"_file_multi_selected");
- files->set_allow_rmb_select(true);
-
- file_list_vb = memnew( VBoxContainer );
- split_box->add_child(file_list_vb);
- file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL);
-
- path_hb = memnew( HBoxContainer );
- file_list_vb->add_child(path_hb);
-
- button_back = memnew( ToolButton );
- path_hb->add_child(button_back);
- button_back->hide();
-
- search_box = memnew( LineEdit );
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- path_hb->add_child(search_box);
- search_box->connect("text_changed",this,"_search_changed");
-
- search_icon = memnew( TextureRect );
- search_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
- path_hb->add_child(search_icon);
-
- button_display_mode = memnew( ToolButton );
- path_hb->add_child(button_display_mode);
- button_display_mode->set_toggle_mode(true);
-
- file_list_vb->add_child(files);
-
-
- scanning_vb = memnew( VBoxContainer );
- Label *slabel = memnew( Label );
- slabel->set_text("Scanning Files,\nPlease Wait..");
- slabel->set_align(Label::ALIGN_CENTER);
- scanning_vb->add_child(slabel);
- scanning_progress = memnew( ProgressBar );
- scanning_vb->add_child(scanning_progress);
- add_child(scanning_vb);
- scanning_vb->hide();
-
-
-
- deps_editor = memnew( DependencyEditor );
- add_child(deps_editor);
-
- owners_editor = memnew( DependencyEditorOwners);
- add_child(owners_editor);
-
- remove_dialog = memnew( DependencyRemoveDialog);
- add_child(remove_dialog);
-
- move_dialog = memnew( EditorDirDialog );
- add_child(move_dialog);
- move_dialog->connect("dir_selected",this,"_move_operation");
- move_dialog->get_ok()->set_text(TTR("Move"));
-
- rename_dialog = memnew( EditorFileDialog );
- rename_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- rename_dialog->connect("file_selected",this,"_rename_operation");
- add_child(rename_dialog);
-
- updating_tree=false;
- initialized=false;
-
- history.push_back("res://");
- history_pos=0;
-
- split_mode=false;
- display_mode = DISPLAY_THUMBNAILS;
-
- path="res://";
-
-
- add_constant_override("separation",3);
-}
-
-FileSystemDock::~FileSystemDock() {
-
-}
diff --git a/tools/editor/filesystem_dock.h b/tools/editor/filesystem_dock.h
deleted file mode 100644
index 224efe0f28..0000000000
--- a/tools/editor/filesystem_dock.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*************************************************************************/
-/* filesystem_dock.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 FILESYSTEM_DOCK_H
-#define FILESYSTEM_DOCK_H
-
-#include "scene/main/timer.h"
-#include "scene/gui/control.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/label.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/box_container.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/item_list.h"
-#include "scene/gui/progress_bar.h"
-#include "scene/gui/split_container.h"
-
-#include "os/dir_access.h"
-#include "os/thread.h"
-
-#include "editor_file_system.h"
-#include "editor_dir_dialog.h"
-#include "dependency_editor.h"
-
-class EditorNode;
-
-
-class FileSystemDock : public VBoxContainer {
- GDCLASS( FileSystemDock, VBoxContainer );
-
-public:
- enum DisplayMode {
- DISPLAY_THUMBNAILS,
- DISPLAY_LIST
- };
-private:
- enum FileMenu {
- FILE_OPEN,
- FILE_INSTANCE,
- FILE_DEPENDENCIES,
- FILE_OWNERS,
- FILE_MOVE,
- FILE_REMOVE,
- FILE_REIMPORT,
- FILE_INFO,
- FILE_SHOW_IN_EXPLORER,
- FILE_COPY_PATH
- };
-
- enum FolderMenu {
- FOLDER_EXPAND_ALL,
- FOLDER_COLLAPSE_ALL
- };
-
-
- VBoxContainer *scanning_vb;
- ProgressBar *scanning_progress;
- VSplitContainer *split_box;
- VBoxContainer *file_list_vb;
-
- EditorNode *editor;
- Set<String> favorites;
-
- Button *button_reload;
- Button *button_favorite;
- Button *button_back;
- Button *button_display_mode;
- Button *button_hist_next;
- Button *button_hist_prev;
- LineEdit *current_path;
- LineEdit *search_box;
- TextureRect *search_icon;
- HBoxContainer *path_hb;
-
- bool split_mode;
- DisplayMode display_mode;
-
- PopupMenu *file_options;
- PopupMenu *folder_options;
-
- DependencyEditor *deps_editor;
- DependencyEditorOwners *owners_editor;
- DependencyRemoveDialog *remove_dialog;
-
- EditorDirDialog *move_dialog;
- EditorFileDialog *rename_dialog;
-
- Vector<String> move_dirs;
- Vector<String> move_files;
-
-
- Vector<String> history;
- int history_pos;
-
- String path;
-
- bool initialized;
-
- bool updating_tree;
- Tree * tree; //directories
- ItemList *files;
-
-
- void _file_multi_selected(int p_index, bool p_selected);
- void _file_selected();
-
-
- void _go_to_tree();
- void _go_to_dir(const String& p_dir);
- void _select_file(int p_idx);
-
- bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir);
- void _thumbnail_done(const String& p_path,const Ref<Texture>& p_preview, const Variant& p_udata);
- void _find_inside_move_files(EditorFileSystemDirectory *efsd,Vector<String>& files);
- void _find_remaps(EditorFileSystemDirectory *efsd,Map<String,String> &renames,List<String>& to_remaps);
-
- void _rename_operation(const String& p_to_path);
- void _move_operation(const String& p_to_path);
-
-
- void _file_option(int p_option);
- void _folder_option(int p_option);
- void _update_files(bool p_keep_selection);
- void _change_file_display();
-
- void _fs_changed();
- void _fw_history();
- void _bw_history();
- void _push_to_history();
-
-
- void _dir_selected();
- void _update_tree();
- void _rescan();
- void _set_scanning_mode();
-
-
- void _favorites_pressed();
- void _open_pressed();
- void _dir_rmb_pressed(const Vector2& local_mouse_pos);
- void _search_changed(const String& p_text);
-
-
- void _files_list_rmb_select(int p_item,const Vector2& p_pos);
-
-
- struct FileInfo {
- String name;
- String path;
- StringName type;
- int import_status; //0 not imported, 1 - ok, 2- must reimport, 3- broken
- Vector<String> sources;
-
- bool operator<(const FileInfo& fi) const {
- return name < fi.name;
- }
- };
-
- void _search(EditorFileSystemDirectory *p_path, List<FileInfo>* matches, int p_max_items);
-
- Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
- bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
- void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
-
- void _preview_invalidated(const String& p_path);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- String get_selected_path() const;
-
- String get_current_path() const;
- void focus_on_filter();
-
- void fix_dependencies(const String& p_for_file);
-
- void set_display_mode(int p_mode);
-
- int get_split_offset() { return split_box->get_split_offset(); }
- void set_split_offset(int p_offset) { split_box->set_split_offset(p_offset); }
- void select_file(const String& p_file);
-
- FileSystemDock(EditorNode *p_editor);
- ~FileSystemDock();
-};
-
-
-#endif // SCENES_DOCK_H
diff --git a/tools/editor/icons/SCsub b/tools/editor/icons/SCsub
deleted file mode 100644
index 4af481d1f6..0000000000
--- a/tools/editor/icons/SCsub
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env python
-
-Import('env')
-
-
-def make_editor_icons_action(target, source, env):
-
- import os
- import cStringIO
-
- dst = target[0].srcnode().abspath
- pixmaps = source
-
- s = cStringIO.StringIO()
-
- s.write("#include \"editor_icons.h\"\n\n")
- s.write("#include \"editor_scale.h\"\n\n")
- s.write("#include \"scene/resources/theme.h\"\n\n")
-
- hidpi_list = []
-
- for x in pixmaps:
-
- x = str(x)
- var_str = os.path.basename(x)[:-4] + "_png"
- # print(var_str)
-
- s.write("static const unsigned char " + var_str + "[]={\n")
-
- pngf = open(x, "rb")
-
- b = pngf.read(1)
- while(len(b) == 1):
- s.write(hex(ord(b)))
- b = pngf.read(1)
- if (len(b) == 1):
- s.write(",")
-
- s.write("\n};\n\n")
-
- pngf.close()
- var_str = os.path.basename(x)[:-4] + "_hidpi_png"
- try:
-
- pngf = open(os.path.dirname(x) + "/2x/" + os.path.basename(x), "rb")
-
- s.write("static const unsigned char " + var_str + "[]={\n")
-
- b = pngf.read(1)
- while(len(b) == 1):
- s.write(hex(ord(b)))
- b = pngf.read(1)
- if (len(b) == 1):
- s.write(",")
-
- s.write("\n};\n\n\n")
- hidpi_list.append(x)
-
- except:
- s.write("static const unsigned char* " + var_str + "=NULL;\n\n\n")
-
- s.write("static Ref<ImageTexture> make_icon(const uint8_t* p_png,const uint8_t* p_hidpi_png) {\n")
- s.write("\tRef<ImageTexture> texture( memnew( ImageTexture ) );\n")
- s.write("\tbool use_hidpi_image=(editor_get_scale()>1.0&&p_hidpi_png);\n")
- s.write("\tImage img(use_hidpi_image?p_hidpi_png:p_png);\n")
- s.write("\tif (editor_get_scale()>1.0 && !p_hidpi_png) { img.convert(Image::FORMAT_RGBA8); img.expand_x2_hq2x(); use_hidpi_image=true;}\n")
- s.write("\timg.resize(img.get_width()*EDSCALE/(use_hidpi_image?2:1),img.get_height()*EDSCALE/(use_hidpi_image?2:1));\n")
- s.write("\ttexture->create_from_image( img,ImageTexture::FLAG_FILTER );\n")
- s.write("\treturn texture;\n")
- s.write("}\n\n")
-
- s.write("void editor_register_icons(Ref<Theme> p_theme) {\n\n")
-
- for x in pixmaps:
-
- x = os.path.basename(str(x))
- type = x[5:-4].title().replace("_", "")
- var_str = x[:-4] + "_png"
- var_str_hidpi = x[:-4] + "_hidpi_png"
- s.write("\tp_theme->set_icon(\"" + type + "\",\"EditorIcons\",make_icon(" + var_str + "," + var_str_hidpi + "));\n")
-
- s.write("\n\n}\n\n")
-
- f = open(dst, "wb")
- f.write(s.getvalue())
- f.close()
- s.close()
-
-make_editor_icons_builder = Builder(action=make_editor_icons_action,
- suffix='.cpp',
- src_suffix='.png')
-env['BUILDERS']['MakeEditorIconsBuilder'] = make_editor_icons_builder
-env.Alias('editor_icons', [env.MakeEditorIconsBuilder('#tools/editor/editor_icons.cpp', Glob("*.png"))])
-
-env.editor_sources.append("#tools/editor/editor_icons.cpp")
-Export('env')
diff --git a/tools/editor/import/editor_import_collada.cpp b/tools/editor/import/editor_import_collada.cpp
deleted file mode 100644
index a901de1faf..0000000000
--- a/tools/editor/import/editor_import_collada.cpp
+++ /dev/null
@@ -1,2508 +0,0 @@
-/*************************************************************************/
-/* editor_import_collada.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_import_collada.h"
-
-
-#include "scene/3d/spatial.h"
-#include "scene/3d/skeleton.h"
-#include "scene/3d/path.h"
-#include "scene/3d/camera.h"
-#include "scene/3d/light.h"
-#include "scene/animation/animation_player.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/resources/animation.h"
-#include "scene/resources/packed_scene.h"
-#include "os/os.h"
-#include "tools/editor/collada/collada.h"
-#include "tools/editor/editor_node.h"
-#include <iostream>
-
-
-struct ColladaImport {
-
- Collada collada;
- Spatial *scene;
-
- Vector<Ref<Animation> > animations;
-
- struct NodeMap {
- //String path;
- Spatial *node;
- int bone;
- List<int> anim_tracks;
-
- NodeMap() { node=NULL; bone=-1; }
- };
-
- bool found_ambient;
- Color ambient;
- bool found_directional;
- bool force_make_tangents;
- bool apply_mesh_xform_to_vertices;
- bool use_mesh_builtin_materials;
- float bake_fps;
-
-
-
- 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;
- Map<Collada::Node*,Skeleton*> skeleton_map;
-
- Map< Skeleton*, Map< String, int> > skeleton_bone_map;
-
- Set<String> valid_animated_nodes;
- Vector<int> valid_animated_properties;
- Map<String,bool> bones_with_animation;
-
- Error _populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_node, int &r_bone, int p_parent);
- Error _create_scene_skeletons(Collada::Node *p_node);
- Error _create_scene(Collada::Node *p_node, Spatial *p_parent);
- Error _create_resources(Collada::Node *p_node);
- Error _create_material(const String& p_material);
- Error _create_mesh_surfaces(bool p_optimize, Ref<Mesh>& p_mesh, const Map<String,Collada::NodeGeometry::Material>& p_material_map, const Collada::MeshData &meshdata, const Transform& p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data, Vector<Ref<Mesh> > p_morph_meshes=Vector<Ref<Mesh> >(), bool p_for_morph=false, bool p_use_mesh_material=false);
- Error load(const String& p_path, int p_flags, bool p_force_make_tangents=false);
- void _fix_param_animation_tracks();
- void create_animation(int p_clip,bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
- void create_animations(bool p_make_tracks_in_all_bones, bool p_import_value_tracks);
-
- Set<String> tracks_in_clips;
- Vector<String> missing_textures;
-
- void _pre_process_lights(Collada::Node *p_node);
-
- ColladaImport() {
-
- found_ambient=false;
- found_directional=false;
- force_make_tangents=false;
- apply_mesh_xform_to_vertices=true;
- bake_fps=15;
-
- }
-};
-
-
-Error ColladaImport::_populate_skeleton(Skeleton *p_skeleton,Collada::Node *p_node, int &r_bone, int p_parent) {
-
-
- if (p_node->type!=Collada::Node::TYPE_JOINT)
- return OK;
-
- Collada::NodeJoint *joint = static_cast<Collada::NodeJoint*>(p_node);
-
- print_line("populating joint "+joint->name);
- p_skeleton->add_bone(p_node->name);
- if (p_parent>=0)
- p_skeleton->set_bone_parent(r_bone,p_parent);
-
- NodeMap nm;
- 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;
-
- if (collada.state.bone_rest_map.has(joint->sid)) {
-
- p_skeleton->set_bone_rest(r_bone,collada.fix_transform(collada.state.bone_rest_map[joint->sid]));
- //should map this bone to something for animation?
- } else {
- print_line("no rest: "+joint->sid);
- WARN_PRINT("Joint has no rest..");
- }
-
-
- int id = r_bone++;
- for(int i=0;i<p_node->children.size();i++) {
-
- Error err = _populate_skeleton(p_skeleton,p_node->children[i],r_bone,id);
- if (err)
- return err;
- }
-
- return OK;
-}
-
-
-void ColladaImport::_pre_process_lights(Collada::Node *p_node) {
-
-
- if (p_node->type==Collada::Node::TYPE_LIGHT) {
-
-
- Collada::NodeLight *light=static_cast<Collada::NodeLight*>(p_node);
- if (collada.state.light_data_map.has(light->light)) {
-
- Collada::LightData &ld = collada.state.light_data_map[light->light];
- if (ld.mode==Collada::LightData::MODE_AMBIENT) {
- found_ambient=true;
- ambient=ld.color;
- }
- if (ld.mode==Collada::LightData::MODE_DIRECTIONAL) {
- found_directional=true;
- }
- }
-
- }
-
-
- for(int i=0;i<p_node->children.size();i++)
- _pre_process_lights(p_node->children[i]);
-}
-
-Error ColladaImport::_create_scene_skeletons(Collada::Node *p_node) {
-
-
- if (p_node->type==Collada::Node::TYPE_SKELETON) {
-
- Skeleton *sk = memnew( Skeleton );
- int bone = 0;
-
- for(int i=0;i<p_node->children.size();i++) {
-
- _populate_skeleton(sk,p_node->children[i],bone,-1);
- }
- sk->localize_rests(); //after creating skeleton, rests must be localized...!
- skeleton_map[p_node]=sk;
- }
-
-
- for(int i=0;i<p_node->children.size();i++) {
-
- Error err = _create_scene_skeletons(p_node->children[i]);
- if (err)
- return err;
- }
- return OK;
-
-}
-
-
-Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
-
- Spatial * node=NULL;
-
- switch(p_node->type) {
-
- case Collada::Node::TYPE_NODE: {
-
- node = memnew( Spatial );
- } break;
- case Collada::Node::TYPE_JOINT: {
-
- return OK; // do nothing
- } break;
- case Collada::Node::TYPE_LIGHT: {
-
- //node = memnew( Light)
- Collada::NodeLight *light = static_cast<Collada::NodeLight*>(p_node);
- if (collada.state.light_data_map.has(light->light)) {
-
- Collada::LightData &ld = collada.state.light_data_map[light->light];
-
- if (ld.mode==Collada::LightData::MODE_AMBIENT) {
-
- if (found_directional)
- return OK; //do nothing not needed
-
- if (!bool(GLOBAL_DEF("collada/use_ambient",false)))
- return OK;
- //well, it's an ambient light..
- Light *l = memnew( DirectionalLight );
- //l->set_color(Light::COLOR_AMBIENT,ld.color);
- //l->set_color(Light::COLOR_DIFFUSE,Color(0,0,0));
- //l->set_color(Light::COLOR_SPECULAR,Color(0,0,0));
- node = l;
-
- } else if (ld.mode==Collada::LightData::MODE_DIRECTIONAL) {
-
- //well, it's an ambient light..
- Light *l = memnew( DirectionalLight );
- /*
- if (found_ambient) //use it here
- l->set_color(Light::COLOR_AMBIENT,ambient);
-
- l->set_color(Light::COLOR_DIFFUSE,ld.color);
- l->set_color(Light::COLOR_SPECULAR,Color(1,1,1));
- */
- node = l;
- } else {
-
- Light *l;
-
- if (ld.mode==Collada::LightData::MODE_OMNI)
- l=memnew( OmniLight );
- else {
- l=memnew( SpotLight );
- //l->set_parameter(Light::PARAM_SPOT_ANGLE,ld.spot_angle);
- //l->set_parameter(Light::PARAM_SPOT_ATTENUATION,ld.spot_exp);
- }
-
- //
- //l->set_color(Light::COLOR_DIFFUSE,ld.color);
- //l->set_color(Light::COLOR_SPECULAR,Color(1,1,1));
- //l->approximate_opengl_attenuation(ld.constant_att,ld.linear_att,ld.quad_att);
- node=l;
- }
-
- } else {
-
- node = memnew( Spatial );
- }
- } break;
- case Collada::Node::TYPE_CAMERA: {
-
- Collada::NodeCamera *cam = static_cast<Collada::NodeCamera*>(p_node);
- Camera *camera = memnew( Camera );
-
- if (collada.state.camera_data_map.has(cam->camera)) {
-
- const Collada::CameraData &cd = collada.state.camera_data_map[cam->camera];
-
- switch(cd.mode) {
-
- case Collada::CameraData::MODE_ORTHOGONAL: {
-
- if (cd.orthogonal.y_mag) {
-
- camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT);
- camera->set_orthogonal(cd.orthogonal.y_mag*2.0 ,cd.z_near,cd.z_far);
-
- } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) {
-
-
- camera->set_keep_aspect_mode(Camera::KEEP_WIDTH);
- camera->set_orthogonal(cd.orthogonal.x_mag*2.0,cd.z_near,cd.z_far);
- }
-
- } break;
- case Collada::CameraData::MODE_PERSPECTIVE: {
-
- if (cd.perspective.y_fov) {
-
- camera->set_perspective(cd.perspective.y_fov,cd.z_near,cd.z_far);
-
- } else if (!cd.perspective.y_fov && cd.perspective.x_fov) {
-
- camera->set_perspective(cd.perspective.x_fov / cd.aspect,cd.z_near,cd.z_far);
- }
-
- } break;
- }
-
- }
-
- node=camera;
-
- } break;
- case Collada::Node::TYPE_GEOMETRY: {
-
- Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(p_node);
-
- if (collada.state.curve_data_map.has(ng->source)) {
-
- node = memnew( Path );
- } else {
- //mesh since nothing else
- node = memnew( MeshInstance );
- node->cast_to<MeshInstance>()->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT,true);
- }
- } break;
- case Collada::Node::TYPE_SKELETON: {
-
- ERR_FAIL_COND_V(!skeleton_map.has(p_node),ERR_CANT_CREATE);
- Skeleton *sk = skeleton_map[p_node];
- node=sk;
- } break;
-
- }
-
- if (p_node->name!="")
- node->set_name(p_node->name);
- 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;
- node->set_transform(xf);
- p_parent->add_child(node);
- node->set_owner(scene);
-
- if (p_node->empty_draw_type!="") {
- node->set_meta("empty_draw_type", Variant(p_node->empty_draw_type));
- }
-
- for(int i=0;i<p_node->children.size();i++) {
-
- Error err = _create_scene(p_node->children[i],node);
- if (err)
- return err;
- }
- return OK;
-}
-
-
-Error ColladaImport::_create_material(const String& p_target) {
-
- ERR_FAIL_COND_V(material_cache.has(p_target),ERR_ALREADY_EXISTS);
- ERR_FAIL_COND_V(!collada.state.material_map.has(p_target),ERR_INVALID_PARAMETER);
- Collada::Material &src_mat=collada.state.material_map[p_target];
- ERR_FAIL_COND_V(!collada.state.effect_map.has(src_mat.instance_effect),ERR_INVALID_PARAMETER);
- Collada::Effect &effect=collada.state.effect_map[src_mat.instance_effect];
-
- Ref<FixedSpatialMaterial> material= memnew( FixedSpatialMaterial );
-
- if (src_mat.name!="")
- material->set_name(src_mat.name);
- else if (effect.name!="")
- material->set_name(effect.name);
-
- // DIFFUSE
-
- if (effect.diffuse.texture!="") {
-
- String texfile = effect.get_texture_path(effect.diffuse.texture,collada);
- if (texfile!="") {
-
- Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
- if (texture.is_valid()) {
-
- material->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,texture);
- material->set_albedo(Color(1,1,1,1));
- //material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1,1));
- } else {
- missing_textures.push_back(texfile.get_file());
- }
- }
- } else {
- //material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,effect.diffuse.color);
- }
-
- // SPECULAR
-
- if (effect.specular.texture!="") {
-
- String texfile = effect.get_texture_path(effect.specular.texture,collada);
- if (texfile!="") {
-
- Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
- if (texture.is_valid()) {
- material->set_texture(FixedSpatialMaterial::TEXTURE_SPECULAR,texture);
- material->set_specular(Color(1,1,1,1));
-
- //material->set_texture(FixedSpatialMaterial::PARAM_SPECULAR,texture);
- //material->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR,Color(1,1,1,1));
- } else {
- missing_textures.push_back(texfile.get_file());
- }
-
- }
- } else {
- material->set_metalness(effect.specular.color.get_v());
- }
-
-
- // EMISSION
-
- if (effect.emission.texture!="") {
-
- String texfile = effect.get_texture_path(effect.emission.texture,collada);
- if (texfile!="") {
-
- Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
- if (texture.is_valid()) {
-
- material->set_feature(FixedSpatialMaterial::FEATURE_EMISSION,true);
- material->set_texture(FixedSpatialMaterial::TEXTURE_EMISSION,texture);
- material->set_emission(Color(1,1,1,1));
-
- //material->set_parameter(FixedSpatialMaterial::PARAM_EMISSION,Color(1,1,1,1));
- }else {
- missing_textures.push_back(texfile.get_file());
- }
-
- }
- } else {
- if (effect.emission.color!=Color()) {
- material->set_feature(FixedSpatialMaterial::FEATURE_EMISSION,true);
- material->set_emission(effect.emission.color);
- }
- }
-
- // NORMAL
-
- if (effect.bump.texture!="") {
-
- String texfile = effect.get_texture_path(effect.bump.texture,collada);
- if (texfile!="") {
-
- Ref<Texture> texture = ResourceLoader::load(texfile,"Texture");
- if (texture.is_valid()) {
- material->set_feature(FixedSpatialMaterial::FEATURE_NORMAL_MAPPING,true);
- material->set_texture(FixedSpatialMaterial::TEXTURE_NORMAL,texture);
- //material->set_emission(Color(1,1,1,1));
-
- //material->set_texture(FixedSpatialMaterial::PARAM_NORMAL,texture);
- }else {
- //missing_textures.push_back(texfile.get_file());
- }
-
- }
- }
-
-
- float roughness = Math::sqrt(1.0-((Math::log(effect.shininess)/Math::log(2.0))/8.0)); //not very right..
- material->set_roughness(roughness);
-
- if (effect.double_sided) {
- material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- }
- material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,effect.unshaded);
-
-
-
- material_cache[p_target]=material;
- return OK;
-}
-
-
-static void _generate_normals(const PoolVector<int>& p_indices,const PoolVector<Vector3>& p_vertices,PoolVector<Vector3>&r_normals) {
-
-
- r_normals.resize(p_vertices.size());
- PoolVector<Vector3>::Write narrayw = r_normals.write();
-
- int iacount=p_indices.size()/3;
- PoolVector<int>::Read index_arrayr = p_indices.read();
- PoolVector<Vector3>::Read vertex_arrayr = p_vertices.read();
-
- for(int idx=0;idx<iacount;idx++) {
-
- Vector3 v[3]={
- vertex_arrayr[index_arrayr[idx*3+0]],
- vertex_arrayr[index_arrayr[idx*3+1]],
- vertex_arrayr[index_arrayr[idx*3+2]]
- };
-
- Vector3 normal = Plane(v[0],v[1],v[2]).normal;
-
- narrayw[index_arrayr[idx*3+0]]+=normal;
- narrayw[index_arrayr[idx*3+1]]+=normal;
- narrayw[index_arrayr[idx*3+2]]+=normal;
- }
-
- int vlen=p_vertices.size();
-
- for(int idx=0;idx<vlen;idx++) {
- narrayw[idx].normalize();
- }
-
-}
-
-
-static void _generate_tangents_and_binormals(const PoolVector<int>& p_indices,const PoolVector<Vector3>& p_vertices,const PoolVector<Vector3>& p_uvs,const PoolVector<Vector3>& p_normals,PoolVector<real_t>&r_tangents) {
-
- int vlen=p_vertices.size();
-
- Vector<Vector3> tangents;
- tangents.resize(vlen);
- Vector<Vector3> binormals;
- binormals.resize(vlen);
-
-
- int iacount=p_indices.size()/3;
-
- PoolVector<int>::Read index_arrayr = p_indices.read();
- PoolVector<Vector3>::Read vertex_arrayr = p_vertices.read();
- PoolVector<Vector3>::Read narrayr = p_normals.read();
- PoolVector<Vector3>::Read uvarrayr = p_uvs.read();
-
-
- for(int idx=0;idx<iacount;idx++) {
-
-
- Vector3 v1 = vertex_arrayr[ index_arrayr[idx*3+0] ];
- Vector3 v2 = vertex_arrayr[ index_arrayr[idx*3+1] ];
- Vector3 v3 = vertex_arrayr[ index_arrayr[idx*3+2] ];
-
- Vector3 w1 = uvarrayr[ index_arrayr[idx*3+0] ];
- Vector3 w2 = uvarrayr[ index_arrayr[idx*3+1] ];
- Vector3 w3 = uvarrayr[ index_arrayr[idx*3+2] ];
-
- real_t x1 = v2.x - v1.x;
- real_t x2 = v3.x - v1.x;
- real_t y1 = v2.y - v1.y;
- real_t y2 = v3.y - v1.y;
- real_t z1 = v2.z - v1.z;
- real_t z2 = v3.z - v1.z;
-
- real_t s1 = w2.x - w1.x;
- real_t s2 = w3.x - w1.x;
- real_t t1 = w2.y - w1.y;
- real_t t2 = w3.y - w1.y;
-
- real_t r = (s1 * t2 - s2 * t1);
-
- Vector3 tangent;
- Vector3 binormal;
-
- if (r==0) {
-
- binormal=Vector3();
- tangent=Vector3();
- } else {
- tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
- (t2 * z1 - t1 * z2) * r).normalized();
- binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
- (s1 * z2 - s2 * z1) * r).normalized();
- }
-
- tangents[ index_arrayr[idx*3+0] ]+=tangent;
- binormals[ index_arrayr[idx*3+0] ]+=binormal;
- tangents[ index_arrayr[idx*3+1] ]+=tangent;
- binormals[ index_arrayr[idx*3+1] ]+=binormal;
- tangents[ index_arrayr[idx*3+2] ]+=tangent;
- binormals[ index_arrayr[idx*3+2] ]+=binormal;
-
- //print_line(itos(idx)+" tangent: "+tangent);
- //print_line(itos(idx)+" binormal: "+binormal);
- }
-
- r_tangents.resize(vlen*4);
- PoolVector<real_t>::Write tarrayw = r_tangents.write();
-
- for(int idx=0;idx<vlen;idx++) {
- Vector3 tangent = tangents[idx];
- Vector3 bingen = narrayr[idx].cross(tangent);
- float dir;
- if (bingen.dot(binormals[idx]) < 0 )
- dir=-1.0;
- else
- dir=+1.0;
-
- tarrayw[idx*4+0]=tangent.x;
- tarrayw[idx*4+1]=tangent.y;
- tarrayw[idx*4+2]=tangent.z;
- tarrayw[idx*4+3]=dir;
- }
-}
-
-Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > p_morph_meshes,bool p_for_morph,bool p_use_mesh_material) {
-
-
- bool local_xform_mirror=p_local_xform.basis.determinant() < 0;
-
- if (p_morph_data) {
-
- //add morphie target
- ERR_FAIL_COND_V( !p_morph_data->targets.has("MORPH_TARGET"), ERR_INVALID_DATA );
- String mt = p_morph_data->targets["MORPH_TARGET"];
- ERR_FAIL_COND_V( !p_morph_data->sources.has(mt), ERR_INVALID_DATA);
- int morph_targets = p_morph_data->sources[mt].sarray.size();
- for(int i=0;i<morph_targets;i++) {
-
- String target = p_morph_data->sources[mt].sarray[i];
- ERR_FAIL_COND_V( !collada.state.mesh_data_map.has(target), ERR_INVALID_DATA );
- String name = collada.state.mesh_data_map[target].name;
-
- p_mesh->add_blend_shape(name);
- }
- if (p_morph_data->mode=="RELATIVE")
- p_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_RELATIVE);
- else if (p_morph_data->mode=="NORMALIZED")
- p_mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
- }
-
-
- int surface=0;
- for(int p_i = 0; p_i < meshdata.primitives.size(); p_i ++ ) {
-
-
-
- const Collada::MeshData::Primitives& p = meshdata.primitives[p_i];
-
- /* VERTEX SOURCE */
- ERR_FAIL_COND_V(!p.sources.has("VERTEX"),ERR_INVALID_DATA);
-
- String vertex_src_id = p.sources["VERTEX"].source;
- int vertex_ofs=p.sources["VERTEX"].offset;
-
- ERR_FAIL_COND_V(!meshdata.vertices.has(vertex_src_id),ERR_INVALID_DATA);
-
- ERR_FAIL_COND_V(!meshdata.vertices[vertex_src_id].sources.has("POSITION"),ERR_INVALID_DATA);
- String position_src_id = meshdata.vertices[vertex_src_id].sources["POSITION"];
-
- ERR_FAIL_COND_V(!meshdata.sources.has(position_src_id),ERR_INVALID_DATA);
-
- const Collada::MeshData::Source *vertex_src=&meshdata.sources[position_src_id];
-
- /* NORMAL SOURCE */
-
- const Collada::MeshData::Source *normal_src=NULL;
- int normal_ofs=0;
-
- if (p.sources.has("NORMAL")) {
-
- String normal_source_id = p.sources["NORMAL"].source;
- normal_ofs = p.sources["NORMAL"].offset;
- ERR_FAIL_COND_V( !meshdata.sources.has(normal_source_id),ERR_INVALID_DATA);
- normal_src=&meshdata.sources[normal_source_id];
- }
-
- const Collada::MeshData::Source *binormal_src=NULL;
- int binormal_ofs=0;
-
- if (p.sources.has("TEXBINORMAL")) {
-
- String binormal_source_id = p.sources["TEXBINORMAL"].source;
- binormal_ofs = p.sources["TEXBINORMAL"].offset;
- ERR_FAIL_COND_V( !meshdata.sources.has(binormal_source_id),ERR_INVALID_DATA);
- binormal_src=&meshdata.sources[binormal_source_id];
- }
-
- const Collada::MeshData::Source *tangent_src=NULL;
- int tangent_ofs=0;
-
- if (p.sources.has("TEXTANGENT")) {
-
- String tangent_source_id = p.sources["TEXTANGENT"].source;
- tangent_ofs = p.sources["TEXTANGENT"].offset;
- ERR_FAIL_COND_V( !meshdata.sources.has(tangent_source_id),ERR_INVALID_DATA);
- tangent_src=&meshdata.sources[tangent_source_id];
- }
-
-
- const Collada::MeshData::Source *uv_src=NULL;
- int uv_ofs=0;
-
- if (p.sources.has("TEXCOORD0")) {
-
- String uv_source_id = p.sources["TEXCOORD0"].source;
- uv_ofs = p.sources["TEXCOORD0"].offset;
- ERR_FAIL_COND_V( !meshdata.sources.has(uv_source_id),ERR_INVALID_DATA);
- uv_src=&meshdata.sources[uv_source_id];
- }
-
- const Collada::MeshData::Source *uv2_src=NULL;
- int uv2_ofs=0;
-
- if (p.sources.has("TEXCOORD1")) {
-
- String uv2_source_id = p.sources["TEXCOORD1"].source;
- uv2_ofs = p.sources["TEXCOORD1"].offset;
- ERR_FAIL_COND_V( !meshdata.sources.has(uv2_source_id),ERR_INVALID_DATA);
- uv2_src=&meshdata.sources[uv2_source_id];
- }
-
-
- const Collada::MeshData::Source *color_src=NULL;
- int color_ofs=0;
-
- if (p.sources.has("COLOR")) {
-
- String color_source_id = p.sources["COLOR"].source;
- color_ofs = p.sources["COLOR"].offset;
- ERR_FAIL_COND_V( !meshdata.sources.has(color_source_id), ERR_INVALID_DATA );
- color_src=&meshdata.sources[color_source_id];
- }
-
- //find largest source..
-
- /************************/
- /* ADD WEIGHTS IF EXIST */
- /************************/
-
- Map<int,Vector<Collada::Vertex::Weight> > pre_weights;
-
- bool has_weights=false;
-
- if (skin_controller) {
-
- const Collada::SkinControllerData::Source *weight_src=NULL;
- int weight_ofs=0;
-
- if (skin_controller->weights.sources.has("WEIGHT")) {
-
- String weight_id = skin_controller->weights.sources["WEIGHT"].source;
- weight_ofs = skin_controller->weights.sources["WEIGHT"].offset;
- if (skin_controller->sources.has(weight_id)) {
-
- weight_src = &skin_controller->sources[weight_id];
-
- }
- }
-
- int joint_ofs=0;
-
- if (skin_controller->weights.sources.has("JOINT")) {
-
- joint_ofs = skin_controller->weights.sources["JOINT"].offset;
- }
-
- //should be OK, given this was pre-checked.
-
- int index_ofs=0;
- int wstride = skin_controller->weights.sources.size();
- for(int w_i=0;w_i<skin_controller->weights.sets.size();w_i++) {
-
- int amount = skin_controller->weights.sets[w_i];
-
- Vector<Collada::Vertex::Weight> weights;
-
- for (int a_i=0;a_i<amount;a_i++) {
-
- Collada::Vertex::Weight w;
-
- int read_from = index_ofs+a_i*wstride;
- ERR_FAIL_INDEX_V(read_from+wstride-1,skin_controller->weights.indices.size(),ERR_INVALID_DATA);
- int weight_index = skin_controller->weights.indices[read_from+weight_ofs];
- ERR_FAIL_INDEX_V(weight_index,weight_src->array.size(),ERR_INVALID_DATA);
-
- w.weight = weight_src->array[weight_index];
-
- int bone_index = skin_controller->weights.indices[read_from+joint_ofs];
- if (bone_index==-1)
- continue; //ignore this weight (refers to bind shape)
- ERR_FAIL_INDEX_V(bone_index,bone_remap.size(),ERR_INVALID_DATA);
-
- w.bone_idx=bone_remap[bone_index];
-
-
- weights.push_back(w);
- }
-
- /* FIX WEIGHTS */
-
-
-
- weights.sort();
-
- if (weights.size()>4) {
- //cap to 4 and make weights add up 1
- weights.resize(4);
-
- }
-
- //make sure weights allways add up to 1
- float total=0;
- for(int i=0;i<weights.size();i++)
- total+=weights[i].weight;
- if (total)
- for(int i=0;i<weights.size();i++)
- weights[i].weight/=total;
-
- if (weights.size()==0 || total==0) { //if nothing, add a weight to bone 0
- //no weights assigned
- Collada::Vertex::Weight w;
- w.bone_idx=0;
- w.weight=1.0;
- weights.clear();
- weights.push_back(w);
-
- }
-
- pre_weights[w_i]=weights;
-
- /*
- for(Set<int>::Element *E=vertex_map[w_i].front();E;E=E->next()) {
-
- int dst = E->get();
- ERR_EXPLAIN("invalid vertex index in array");
- ERR_FAIL_INDEX_V(dst,vertex_array.size(),ERR_INVALID_DATA);
- vertex_array[dst].weights=weights;
-
- }*/
-
-
-
-
- index_ofs+=wstride*amount;
-
- }
-
- //vertices need to be localized
- has_weights=true;
-
- }
-
- Set<Collada::Vertex> vertex_set; //vertex set will be the vertices
- List<int> indices_list; //indices will be the indices
- //Map<int,Set<int> > vertex_map; //map vertices (for setting skinning/morph)
-
- /**************************/
- /* CREATE PRIMITIVE ARRAY */
- /**************************/
-
- // The way collada uses indices is more optimal, and friendlier with 3D modelling sofware,
- // because it can index everything, not only vertices (similar to how the WII works).
- // This is, however, more incompatible with standard video cards, so arrays must be converted.
- // Must convert to GL/DX format.
-
- int _prim_ofs=0;
- int vertidx=0;
- for(int p_i=0;p_i<p.count;p_i++) {
-
-
- int amount;
- if (p.polygons.size()) {
-
- ERR_FAIL_INDEX_V(p_i,p.polygons.size(),ERR_INVALID_DATA);
- amount=p.polygons[p_i];
- } else {
- amount=3; //triangles;
- }
-
- //COLLADA_PRINT("amount: "+itos(amount));
-
- int prev2[2]={0,0};
-
- for(int j=0;j<amount;j++) {
-
- int src=_prim_ofs;
- //_prim_ofs+=p.sources.size()
-
- ERR_FAIL_INDEX_V(src,p.indices.size(),ERR_INVALID_DATA);
-
- Collada::Vertex vertex;
- if (!p_optimize)
- vertex.uid=vertidx++;
-
-
-
- int vertex_index=p.indices[src+vertex_ofs]; //used for index field (later used by controllers)
- int vertex_pos = (vertex_src->stride?vertex_src->stride:3) * vertex_index;
- ERR_FAIL_INDEX_V(vertex_pos,vertex_src->array.size(),ERR_INVALID_DATA);
- vertex.vertex=Vector3(vertex_src->array[vertex_pos+0],vertex_src->array[vertex_pos+1],vertex_src->array[vertex_pos+2]);
-
- if (pre_weights.has(vertex_index)) {
- vertex.weights=pre_weights[vertex_index];
- }
-
- if (normal_src) {
-
-
-
- int normal_pos = (normal_src->stride?normal_src->stride:3) * p.indices[src+normal_ofs];
- ERR_FAIL_INDEX_V(normal_pos,normal_src->array.size(),ERR_INVALID_DATA);
- vertex.normal=Vector3(normal_src->array[normal_pos+0],normal_src->array[normal_pos+1],normal_src->array[normal_pos+2]);
- vertex.normal=vertex.normal.snapped(0.001);
-
-
- if (tangent_src && binormal_src) {
-
- int binormal_pos = (binormal_src->stride?binormal_src->stride:3) * p.indices[src+binormal_ofs];
- ERR_FAIL_INDEX_V(binormal_pos,binormal_src->array.size(),ERR_INVALID_DATA);
- Vector3 binormal =Vector3(binormal_src->array[binormal_pos+0],binormal_src->array[binormal_pos+1],binormal_src->array[binormal_pos+2]);
-
- int tangent_pos = (tangent_src->stride?tangent_src->stride:3) * p.indices[src+tangent_ofs];
- ERR_FAIL_INDEX_V(tangent_pos,tangent_src->array.size(),ERR_INVALID_DATA);
- Vector3 tangent =Vector3(tangent_src->array[tangent_pos+0],tangent_src->array[tangent_pos+1],tangent_src->array[tangent_pos+2]);
-
- vertex.tangent.normal=tangent;
- vertex.tangent.d= vertex.normal.cross(tangent).dot(binormal) > 0 ? 1 : -1;
- }
-
- }
-
-
- if (uv_src) {
-
- int uv_pos = (uv_src->stride?uv_src->stride:2) * p.indices[src+uv_ofs];
- ERR_FAIL_INDEX_V(uv_pos,uv_src->array.size(),ERR_INVALID_DATA);
- vertex.uv=Vector3(uv_src->array[uv_pos+0],1.0-uv_src->array[uv_pos+1],0);
- }
-
- if (uv2_src) {
-
- int uv2_pos = (uv2_src->stride?uv2_src->stride:2) * p.indices[src+uv2_ofs];
- ERR_FAIL_INDEX_V(uv2_pos,uv2_src->array.size(),ERR_INVALID_DATA);
- vertex.uv2=Vector3(uv2_src->array[uv2_pos+0],1.0-uv2_src->array[uv2_pos+1],0);
- }
-
- if (color_src) {
-
- int color_pos = (color_src->stride?color_src->stride:3) * p.indices[src+color_ofs]; // colors are RGB in collada..
- ERR_FAIL_INDEX_V(color_pos,color_src->array.size(),ERR_INVALID_DATA);
- vertex.color=Color(color_src->array[color_pos+0],color_src->array[color_pos+1],color_src->array[color_pos+2],(color_src->stride>3)?color_src->array[color_pos+3]:1.0);
-
- }
-
-#ifndef NO_UP_AXIS_SWAP
- if (collada.state.up_axis==Vector3::AXIS_Z) {
-
- SWAP( vertex.vertex.z, vertex.vertex.y );
- vertex.vertex.z = -vertex.vertex.z;
- SWAP( vertex.normal.z, vertex.normal.y );
- vertex.normal.z = -vertex.normal.z;
- SWAP( vertex.tangent.normal.z, vertex.tangent.normal.y );
- vertex.tangent.normal.z = -vertex.tangent.normal.z;
-
- }
-
-#endif
-
- vertex.fix_unit_scale(collada);
- int index=0;
- //COLLADA_PRINT("vertex: "+vertex.vertex);
-
- if (vertex_set.has(vertex)) {
-
- index=vertex_set.find(vertex)->get().idx;
- } else {
-
- index=vertex_set.size();
- vertex.idx=index;
- vertex_set.insert(vertex);
- }
-
- /* if (!vertex_map.has(vertex_index))
- vertex_map[vertex_index]=Set<int>();
- vertex_map[vertex_index].insert(index); //should be outside..*/
- //build triangles if needed
- if (j==0)
- prev2[0]=index;
-
- if (j>=2) {
- //insert indices in reverse order (collada uses CCW as frontface)
- if (local_xform_mirror) {
-
- indices_list.push_back(prev2[0]);
- indices_list.push_back(prev2[1]);
- indices_list.push_back(index);
-
- } else {
- indices_list.push_back(prev2[0]);
- indices_list.push_back(index);
- indices_list.push_back(prev2[1]);
- }
- }
-
- prev2[1]=index;
- _prim_ofs+=p.vertex_size;
- }
-
- }
-
-
-
- Vector<Collada::Vertex> vertex_array; //there we go, vertex array
-
- vertex_array.resize(vertex_set.size());
- for(Set<Collada::Vertex>::Element *F=vertex_set.front();F;F=F->next()) {
-
- vertex_array[F->get().idx]=F->get();
- }
-
-
- if (has_weights) {
-
- //if skeleton, localize
- Transform local_xform = p_local_xform;
- for(int i=0;i<vertex_array.size();i++) {
-
- vertex_array[i].vertex=local_xform.xform(vertex_array[i].vertex);
- vertex_array[i].normal=local_xform.basis.xform(vertex_array[i].normal).normalized();
- vertex_array[i].tangent.normal=local_xform.basis.xform(vertex_array[i].tangent.normal).normalized();
- if (local_xform_mirror) {
- //i shouldn't do this? wtf?
- //vertex_array[i].normal*=-1.0;
- //vertex_array[i].tangent.normal*=-1.0;
- }
- }
- }
-
-
- PoolVector<int> index_array;
- index_array.resize(indices_list.size());
- PoolVector<int>::Write index_arrayw = index_array.write();
-
- int iidx=0;
- for(List<int>::Element *F=indices_list.front();F;F=F->next()) {
-
- index_arrayw[iidx++]=F->get();
- }
-
- index_arrayw=PoolVector<int>::Write();
-
-
- /*****************/
- /* MAKE SURFACES */
- /*****************/
-
-
- {
-
- Ref<FixedSpatialMaterial> material;
-
- //find material
- Mesh::PrimitiveType primitive=Mesh::PRIMITIVE_TRIANGLES;
-
- {
-
- if (p_material_map.has(p.material)) {
- String target=p_material_map[p.material].target;
-
- if (!material_cache.has(target)) {
- Error err = _create_material(target);
- if (!err)
- material=material_cache[target];
- } else
- material=material_cache[target];
-
- } else if (p.material!=""){
- print_line("Warning, unreferenced material in geometry instance: "+p.material);
- }
- }
-
-
-
- PoolVector<Vector3> final_vertex_array;
- PoolVector<Vector3> final_normal_array;
- PoolVector<float> final_tangent_array;
- PoolVector<Color> final_color_array;
- PoolVector<Vector3> final_uv_array;
- PoolVector<Vector3> final_uv2_array;
- PoolVector<int> final_bone_array;
- PoolVector<float> final_weight_array;
-
- uint32_t final_format=0;
-
- //create format
- final_format=Mesh::ARRAY_FORMAT_VERTEX|Mesh::ARRAY_FORMAT_INDEX;
-
- if (normal_src) {
- final_format|=Mesh::ARRAY_FORMAT_NORMAL;
- if (uv_src && binormal_src && tangent_src) {
- final_format|=Mesh::ARRAY_FORMAT_TANGENT;
- }
-
- }
-
-
-
- if (color_src)
- final_format|=Mesh::ARRAY_FORMAT_COLOR;
- if (uv_src)
- final_format|=Mesh::ARRAY_FORMAT_TEX_UV;
- if (uv2_src)
- final_format|=Mesh::ARRAY_FORMAT_TEX_UV2;
-
- if (has_weights) {
- final_format|=Mesh::ARRAY_FORMAT_WEIGHTS;
- final_format|=Mesh::ARRAY_FORMAT_BONES;
- }
-
-
- //set arrays
-
- int vlen = vertex_array.size();
- { //vertices
-
- PoolVector<Vector3> varray;
- varray.resize(vertex_array.size());
-
- PoolVector<Vector3>::Write varrayw = varray.write();
-
- for(int k=0;k<vlen;k++)
- varrayw[k]=vertex_array[k].vertex;
-
- varrayw = PoolVector<Vector3>::Write();
- final_vertex_array=varray;
-
- }
-
-
- if (uv_src) { //compute uv first, may be needed for computing tangent/bionrmal
- PoolVector<Vector3> uvarray;
- uvarray.resize(vertex_array.size());
- PoolVector<Vector3>::Write uvarrayw = uvarray.write();
-
- for(int k=0;k<vlen;k++) {
- uvarrayw[k]=vertex_array[k].uv;
- }
-
- uvarrayw = PoolVector<Vector3>::Write();
- final_uv_array=uvarray;
-
- }
-
- if (uv2_src) { //compute uv first, may be needed for computing tangent/bionrmal
- PoolVector<Vector3> uv2array;
- uv2array.resize(vertex_array.size());
- PoolVector<Vector3>::Write uv2arrayw = uv2array.write();
-
- for(int k=0;k<vlen;k++) {
- uv2arrayw[k]=vertex_array[k].uv2;
- }
-
- uv2arrayw = PoolVector<Vector3>::Write();
- final_uv2_array=uv2array;
-
- }
-
- if (normal_src) {
- PoolVector<Vector3> narray;
- narray.resize(vertex_array.size());
- PoolVector<Vector3>::Write narrayw = narray.write();
-
- for(int k=0;k<vlen;k++) {
- narrayw[k]=vertex_array[k].normal;
- }
-
- narrayw = PoolVector<Vector3>::Write();
- final_normal_array=narray;
-
- /*
- PoolVector<Vector3> altnaray;
- _generate_normals(index_array,final_vertex_array,altnaray);
-
- for(int i=0;i<altnaray.size();i++)
- print_line(rtos(altnaray[i].dot(final_normal_array[i])));
- */
-
- } else if (primitive==Mesh::PRIMITIVE_TRIANGLES) {
- //generate normals (even if unused later)
-
- _generate_normals(index_array,final_vertex_array,final_normal_array);
- if (OS::get_singleton()->is_stdout_verbose())
- print_line("Collada: Triangle mesh lacks normals, so normals were generated.");
- final_format|=Mesh::ARRAY_FORMAT_NORMAL;
-
- }
-
- if (final_normal_array.size() && uv_src && binormal_src && tangent_src && !force_make_tangents) {
-
- PoolVector<real_t> tarray;
- tarray.resize(vertex_array.size()*4);
- PoolVector<real_t>::Write tarrayw = tarray.write();
-
-
- for(int k=0;k<vlen;k++) {
- tarrayw[k*4+0]=vertex_array[k].tangent.normal.x;
- tarrayw[k*4+1]=vertex_array[k].tangent.normal.y;
- tarrayw[k*4+2]=vertex_array[k].tangent.normal.z;
- tarrayw[k*4+3]=vertex_array[k].tangent.d;
-
- }
-
- tarrayw = PoolVector<real_t>::Write();
-
- final_tangent_array=tarray;
- } else if (final_normal_array.size() && primitive==Mesh::PRIMITIVE_TRIANGLES && final_uv_array.size() && (force_make_tangents || (material.is_valid()))){
- //if this uses triangles, there are uvs and the material is using a normalmap, generate tangents and binormals, because they WILL be needed
- //generate binormals/tangents
- _generate_tangents_and_binormals(index_array,final_vertex_array,final_uv_array,final_normal_array,final_tangent_array);
- final_format|=Mesh::ARRAY_FORMAT_TANGENT;
- if (OS::get_singleton()->is_stdout_verbose())
- print_line("Collada: Triangle mesh lacks tangents (And normalmap was used), so tangents were generated.");
-
- }
-
-
- if (color_src) {
- PoolVector<Color> colorarray;
- colorarray.resize(vertex_array.size());
- PoolVector<Color>::Write colorarrayw = colorarray.write();
-
- for(int k=0;k<vlen;k++) {
- colorarrayw[k]=vertex_array[k].color;
- }
-
- colorarrayw = PoolVector<Color>::Write();
-
- final_color_array=colorarray;
- }
-
- if (has_weights) {
- PoolVector<float> weightarray;
- PoolVector<int> bonearray;
-
- weightarray.resize(vertex_array.size()*4);
- PoolVector<float>::Write weightarrayw = weightarray.write();
- bonearray.resize(vertex_array.size()*4);
- PoolVector<int>::Write bonearrayw = bonearray.write();
-
- for(int k=0;k<vlen;k++) {
- float sum=0;
-
- for(int l=0;l<VS::ARRAY_WEIGHTS_SIZE;l++) {
- if (l<vertex_array[k].weights.size()) {
- weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=vertex_array[k].weights[l].weight;
- sum+=weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l];
- bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=int(vertex_array[k].weights[l].bone_idx);
- //COLLADA_PRINT(itos(k)+": "+rtos(bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l])+":"+rtos(weightarray[k*VS::ARRAY_WEIGHTS_SIZE+l]));
- } else {
-
- weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=0;
- bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=0;
-
- }
-
-
- }
- /*
- if (sum<0.8)
- COLLADA_PRINT("ERROR SUMMING INDEX "+itos(k)+" had weights: "+itos(vertex_array[k].weights.size()));
- */
-
- }
-
- weightarrayw = PoolVector<float>::Write();
- bonearrayw = PoolVector<int>::Write();
-
- final_weight_array = weightarray;
- final_bone_array = bonearray;
- }
-
-
-
- ////////////////////////////
- // FINALLY CREATE SUFRACE //
- ////////////////////////////
-
- Array d;
- d.resize(VS::ARRAY_MAX);
-
- d[Mesh::ARRAY_INDEX]=index_array;
- d[Mesh::ARRAY_VERTEX]=final_vertex_array;
-
- if (final_normal_array.size())
- d[Mesh::ARRAY_NORMAL]=final_normal_array;
- if (final_tangent_array.size())
- d[Mesh::ARRAY_TANGENT]=final_tangent_array;
- if (final_uv_array.size())
- d[Mesh::ARRAY_TEX_UV]=final_uv_array;
- if (final_uv2_array.size())
- d[Mesh::ARRAY_TEX_UV2]=final_uv2_array;
- if (final_color_array.size())
- d[Mesh::ARRAY_COLOR]=final_color_array;
- if (final_weight_array.size())
- d[Mesh::ARRAY_WEIGHTS]=final_weight_array;
- if (final_bone_array.size())
- d[Mesh::ARRAY_BONES]=final_bone_array;
-
-
- Array mr;
-
- ////////////////////////////
- // THEN THE MORPH TARGETS //
- ////////////////////////////
-#if 0
- if (p_morph_data) {
-
- //add morphie target
- ERR_FAIL_COND_V( !p_morph_data->targets.has("MORPH_TARGET"), ERR_INVALID_DATA );
- String mt = p_morph_data->targets["MORPH_TARGET"];
- ERR_FAIL_COND_V( !p_morph_data->sources.has(mt), ERR_INVALID_DATA);
- int morph_targets = p_morph_data->sources[mt].sarray.size();
- mr.resize(morph_targets);
-
- for(int j=0;j<morph_targets;j++) {
-
- Array mrt;
- mrt.resize(VS::ARRAY_MAX);
-
- String target = p_morph_data->sources[mt].sarray[j];
- ERR_FAIL_COND_V( !collada.state.mesh_data_map.has(target), ERR_INVALID_DATA );
- String name = collada.state.mesh_data_map[target].name;
- Collada::MeshData &md = collada.state.mesh_data_map[target];
-
- // collada in itself supports morphing everything. However, the spec is unclear and no examples or exporters that
- // morph anything but "POSITIONS" seem to exit. Because of this, normals and binormals/tangents have to be regenerated here,
- // which may result in inaccurate (but most of the time good enough) results.
-
- PoolVector<Vector3> vertices;
- vertices.resize(vlen);
-
- ERR_FAIL_COND_V( md.vertices.size() != 1, ERR_INVALID_DATA);
- String vertex_src_id=md.vertices.front()->key();
- ERR_FAIL_COND_V(!md.vertices[vertex_src_id].sources.has("POSITION"),ERR_INVALID_DATA);
- String position_src_id = md.vertices[vertex_src_id].sources["POSITION"];
-
- ERR_FAIL_COND_V(!md.sources.has(position_src_id),ERR_INVALID_DATA);
-
- const Collada::MeshData::Source *m=&md.sources[position_src_id];
-
- ERR_FAIL_COND_V( m->array.size() != vertex_src->array.size(), ERR_INVALID_DATA);
- int stride=m->stride;
- if (stride==0)
- stride=3;
-
-
- //read vertices from morph target
- PoolVector<Vector3>::Write vertw = vertices.write();
-
- for(int m_i=0;m_i<m->array.size()/stride;m_i++) {
-
- int pos = m_i*stride;
- Vector3 vtx( m->array[pos+0], m->array[pos+1], m->array[pos+2] );
-
-#ifndef NO_UP_AXIS_SWAP
- if (collada.state.up_axis==Vector3::AXIS_Z) {
-
- SWAP( vtx.z, vtx.y );
- vtx.z = -vtx.z;
-
- }
-#endif
-
- Collada::Vertex vertex;
- vertex.vertex=vtx;
- vertex.fix_unit_scale(collada);
- vtx=vertex.vertex;
-
- vtx = p_local_xform.xform(vtx);
-
-
- if (vertex_map.has(m_i)) { //vertex may no longer be here, don't bother converting
-
-
- for (Set<int> ::Element *E=vertex_map[m_i].front() ; E; E=E->next() ) {
-
- vertw[E->get()]=vtx;
- }
- }
- }
-
-
- //vertices are in place, now generate everything else
- vertw = PoolVector<Vector3>::Write();
- PoolVector<Vector3> normals;
- PoolVector<float> tangents;
- print_line("vertex source id: "+vertex_src_id);
- if(md.vertices[vertex_src_id].sources.has("NORMAL")){
- //has normals
- normals.resize(vlen);
- //std::cout << "has normals" << std::endl;
- String normal_src_id = md.vertices[vertex_src_id].sources["NORMAL"];
- //std::cout << "normals source: "<< normal_src_id.utf8().get_data() <<std::endl;
- ERR_FAIL_COND_V(!md.sources.has(normal_src_id),ERR_INVALID_DATA);
-
- const Collada::MeshData::Source *m=&md.sources[normal_src_id];
-
- ERR_FAIL_COND_V( m->array.size() != vertex_src->array.size(), ERR_INVALID_DATA);
- int stride=m->stride;
- if (stride==0)
- stride=3;
-
-
- //read normals from morph target
- PoolVector<Vector3>::Write vertw = normals.write();
-
- for(int m_i=0;m_i<m->array.size()/stride;m_i++) {
-
- int pos = m_i*stride;
- Vector3 vtx( m->array[pos+0], m->array[pos+1], m->array[pos+2] );
-
- #ifndef NO_UP_AXIS_SWAP
- if (collada.state.up_axis==Vector3::AXIS_Z) {
-
- SWAP( vtx.z, vtx.y );
- vtx.z = -vtx.z;
-
- }
- #endif
-
- Collada::Vertex vertex;
- vertex.vertex=vtx;
- vertex.fix_unit_scale(collada);
- vtx=vertex.vertex;
-
- vtx = p_local_xform.xform(vtx);
-
-
- if (vertex_map.has(m_i)) { //vertex may no longer be here, don't bother converting
-
-
- for (Set<int> ::Element *E=vertex_map[m_i].front() ; E; E=E->next() ) {
-
- vertw[E->get()]=vtx;
- }
- }
- }
-
- print_line("using built-in normals");
- }else{
- print_line("generating normals");
- _generate_normals(index_array,vertices,normals);//no normals
- }
- if (final_tangent_array.size() && final_uv_array.size()) {
-
- _generate_tangents_and_binormals(index_array,vertices,final_uv_array,normals,tangents);
-
- }
-
- mrt[Mesh::ARRAY_VERTEX]=vertices;
-
- mrt[Mesh::ARRAY_NORMAL]=normals;
- if (tangents.size())
- mrt[Mesh::ARRAY_TANGENT]=tangents;
- if (final_uv_array.size())
- mrt[Mesh::ARRAY_TEX_UV]=final_uv_array;
- if (final_uv2_array.size())
- mrt[Mesh::ARRAY_TEX_UV2]=final_uv2_array;
- if (final_color_array.size())
- mrt[Mesh::ARRAY_COLOR]=final_color_array;
-
- mr[j]=mrt;
-
- }
-
- }
-
-#endif
- for(int mi=0;mi<p_morph_meshes.size();mi++) {
-
- //print_line("want surface "+itos(mi)+" has "+itos(p_morph_meshes[mi]->get_surface_count()));
- Array a = p_morph_meshes[mi]->surface_get_arrays(surface);
- //add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not)
-
- if (final_weight_array.size())
- a[Mesh::ARRAY_WEIGHTS]=final_weight_array;
- if (final_bone_array.size())
- a[Mesh::ARRAY_BONES]=final_bone_array;
-
- a[Mesh::ARRAY_INDEX]=Variant();
- //a.resize(Mesh::ARRAY_MAX); //no need for index
- mr.push_back(a);
- }
-
-
- p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,d,mr,p_for_morph?0:Mesh::ARRAY_COMPRESS_DEFAULT);
-
- if (material.is_valid()) {
- if (p_use_mesh_material) {
- p_mesh->surface_set_material(surface, material);
- }
- p_mesh->surface_set_name(surface, material->get_name());
- }
- }
-
- /*****************/
- /* FIND MATERIAL */
- /*****************/
-
- surface++;
- }
-
-
- return OK;
-
-}
-
-
-Error ColladaImport::_create_resources(Collada::Node *p_node) {
-
-
- if (p_node->type==Collada::Node::TYPE_GEOMETRY && node_map.has(p_node->id)) {
-
-
- Spatial * node=node_map[p_node->id].node;
- Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(p_node);
-
-
- if (node->cast_to<Path>()) {
-
- Path *path = node->cast_to<Path>();
-
- String curve = ng->source;
-
- if (curve_cache.has(ng->source)) {
-
- path->set_curve(curve_cache[ng->source]);
- } else {
-
- Ref<Curve3D> c = memnew( Curve3D );
-
- const Collada::CurveData &cd = collada.state.curve_data_map[ng->source];
-
- ERR_FAIL_COND_V( !cd.control_vertices.has("POSITION") , ERR_INVALID_DATA);
- ERR_FAIL_COND_V( !cd.control_vertices.has("IN_TANGENT") , ERR_INVALID_DATA);
- ERR_FAIL_COND_V( !cd.control_vertices.has("OUT_TANGENT") , ERR_INVALID_DATA);
- ERR_FAIL_COND_V( !cd.control_vertices.has("INTERPOLATION") , ERR_INVALID_DATA);
-
-
- ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["POSITION"] ) , ERR_INVALID_DATA);
- const Collada::CurveData::Source &vertices = cd.sources[ cd.control_vertices["POSITION"] ];
- ERR_FAIL_COND_V( vertices.stride!=3, ERR_INVALID_DATA );
-
- ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["IN_TANGENT"] ) , ERR_INVALID_DATA);
- const Collada::CurveData::Source &in_tangents = cd.sources[ cd.control_vertices["IN_TANGENT"] ];
- ERR_FAIL_COND_V( in_tangents.stride!=3 , ERR_INVALID_DATA);
-
- ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["OUT_TANGENT"] ), ERR_INVALID_DATA );
- const Collada::CurveData::Source &out_tangents = cd.sources[ cd.control_vertices["OUT_TANGENT"] ];
- ERR_FAIL_COND_V( out_tangents.stride!=3, ERR_INVALID_DATA );
-
- ERR_FAIL_COND_V( !cd.sources.has(cd.control_vertices["INTERPOLATION"] ), ERR_INVALID_DATA );
- const Collada::CurveData::Source &interps = cd.sources[ cd.control_vertices["INTERPOLATION"] ];
- ERR_FAIL_COND_V( interps.stride!=1, ERR_INVALID_DATA );
-
- const Collada::CurveData::Source *tilts=NULL;
- if (cd.control_vertices.has("TILT") && cd.sources.has(cd.control_vertices["TILT"]))
- tilts=&cd.sources[ cd.control_vertices["TILT"] ];
-
-
- if (tilts) {
- print_line("FOUND TILTS!!!");
- }
- int pc = vertices.array.size()/3;
- for(int i=0;i<pc;i++) {
-
- Vector3 pos( vertices.array[i*3+0], vertices.array[i*3+1], vertices.array[i*3+2] );
- Vector3 in( in_tangents.array[i*3+0], in_tangents.array[i*3+1], in_tangents.array[i*3+2] );
- Vector3 out( out_tangents.array[i*3+0], out_tangents.array[i*3+1], out_tangents.array[i*3+2] );
-
-#ifndef NO_UP_AXIS_SWAP
- if (collada.state.up_axis==Vector3::AXIS_Z) {
-
- SWAP(pos.y,pos.z);
- pos.z=-pos.z;
- SWAP(in.y,in.z);
- in.z=-in.z;
- SWAP(out.y,out.z);
- out.z=-out.z;
- }
-#endif
- pos*=collada.state.unit_scale;
- in*=collada.state.unit_scale;
- out*=collada.state.unit_scale;
-
- c->add_point(pos,in-pos,out-pos);
- if (tilts)
- c->set_point_tilt(i,tilts->array[i]);
-
- }
-
- curve_cache[ng->source]=c;
- path->set_curve(c);
-
- }
-
-
- }
-
-
- if (node->cast_to<MeshInstance>()) {
-
-
- Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(p_node);
-
- MeshInstance *mi = node->cast_to<MeshInstance>();
-
-
- ERR_FAIL_COND_V(!mi,ERR_BUG);
-
-
- Collada::SkinControllerData *skin=NULL;
- Collada::MorphControllerData *morph=NULL;
- String meshid;
- Transform apply_xform;
- Vector<int> bone_remap;
- Vector<Ref<Mesh> > morphs;
-
- print_line("mesh: "+String(mi->get_name()));
-
- if (ng->controller) {
-
- print_line("has controller");
-
- String ngsource = ng->source;
-
- if (collada.state.skin_controller_data_map.has(ngsource)) {
-
-
- ERR_FAIL_COND_V(!collada.state.skin_controller_data_map.has(ngsource),ERR_INVALID_DATA);
- skin=&collada.state.skin_controller_data_map[ngsource];
-
- Vector<String> skeletons = ng->skeletons;
-
- ERR_FAIL_COND_V( skeletons.empty(), ERR_INVALID_DATA );
-
- String skname = skeletons[0];
- if (!node_map.has(skname)) {
- print_line("no node for skeleton "+skname);
- }
- ERR_FAIL_COND_V( !node_map.has(skname), ERR_INVALID_DATA );
- NodeMap nmsk = node_map[skname];
- Skeleton *sk = nmsk.node->cast_to<Skeleton>();
- ERR_FAIL_COND_V( !sk, ERR_INVALID_DATA );
- ERR_FAIL_COND_V( !skeleton_bone_map.has(sk), ERR_INVALID_DATA );
- Map<String, int> &bone_remap_map=skeleton_bone_map[sk];
-
-
- meshid=skin->base;
-
- if (collada.state.morph_controller_data_map.has(meshid)) {
- //it's a morph!!
- morph = &collada.state.morph_controller_data_map[meshid];
- ngsource=meshid;
- meshid=morph->mesh;
- } else {
- ngsource="";
- }
-
- if (apply_mesh_xform_to_vertices) {
- apply_xform=collada.fix_transform(p_node->default_transform);
- node->set_transform(Transform());
- } else {
- apply_xform=Transform();
- }
-
- Collada::SkinControllerData::Source *joint_src=NULL;
-
- ERR_FAIL_COND_V(!skin->weights.sources.has("JOINT"),ERR_INVALID_DATA);
-
- String joint_id = skin->weights.sources["JOINT"].source;
- ERR_FAIL_COND_V(!skin->sources.has(joint_id),ERR_INVALID_DATA);
-
- joint_src = &skin->sources[joint_id];
-
- bone_remap.resize(joint_src->sarray.size());
-
- for(int i=0;i<bone_remap.size();i++) {
-
- String str = joint_src->sarray[i];
- if (!bone_remap_map.has(str)) {
- print_line("bone not found for remap: "+str);
- print_line("in skeleton: "+skname);
- }
- ERR_FAIL_COND_V( !bone_remap_map.has(str), ERR_INVALID_DATA );
- bone_remap[i]=bone_remap_map[str];
- }
- }
-
- if (collada.state.morph_controller_data_map.has(ngsource)) {
- print_line("is morph "+ngsource);
- //it's a morph!!
- morph = &collada.state.morph_controller_data_map[ngsource];
- meshid=morph->mesh;
- printf("KKmorph: %p\n",morph);
- print_line("morph mshid: "+meshid);
-
- Vector<String> targets;
-
- morph->targets.has("MORPH_TARGET");
- String target = morph->targets["MORPH_TARGET"];
- bool valid=false;
- if (morph->sources.has(target)) {
- valid=true;
- Vector<String> names = morph->sources[target].sarray;
- for(int i=0;i<names.size();i++) {
-
- String meshid=names[i];
- if (collada.state.mesh_data_map.has(meshid)) {
- Ref<Mesh> mesh=Ref<Mesh>(memnew( Mesh ));
- const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
- Error err = _create_mesh_surfaces(false,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,NULL,Vector<Ref<Mesh> >(),true);
- ERR_FAIL_COND_V(err,err);
-
- morphs.push_back(mesh);
- } else {
- valid=false;
- }
- }
- }
-
- if (!valid)
- morphs.clear();
-
- ngsource="";
- }
-
- if (ngsource!=""){
- ERR_EXPLAIN("Controller Instance Source '"+ngsource+"' is neither skin or morph!");
- ERR_FAIL_V( ERR_INVALID_DATA );
- }
-
-
-
- } else {
- meshid=ng->source;
- }
-
- Ref<Mesh> mesh;
- if (mesh_cache.has(meshid)) {
- mesh=mesh_cache[meshid];
- } else {
- if (collada.state.mesh_data_map.has(meshid)) {
- //bleh, must ignore invalid
-
- ERR_FAIL_COND_V(!collada.state.mesh_data_map.has(meshid),ERR_INVALID_DATA);
- mesh=Ref<Mesh>(memnew( Mesh ));
- const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
- mesh->set_name( meshdata.name );
- Error err = _create_mesh_surfaces(morphs.size()==0,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,morph,morphs,false,use_mesh_builtin_materials);
- ERR_FAIL_COND_V(err,err);
-
- mesh_cache[meshid]=mesh;
- } else {
-
- print_line("Warning, will not import geometry: "+meshid);
- }
- }
-
- if (!mesh.is_null()) {
-
- mi->set_mesh(mesh);
- if (!use_mesh_builtin_materials) {
- const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid];
-
- for(int i=0;i<meshdata.primitives.size();i++) {
-
- String matname=meshdata.primitives[i].material;
-
- if (ng->material_map.has(matname)) {
- String target=ng->material_map[matname].target;
-
- Ref<Material> material;
- if (!material_cache.has(target)) {
- Error err = _create_material(target);
- if (!err)
- material=material_cache[target];
- } else
- material=material_cache[target];
-
- mi->set_surface_material(i,material);
- } else if (matname!=""){
- print_line("Warning, unreferenced material in geometry instance: "+matname);
- }
-
- }
- }
- }
- }
- }
-
- for(int i=0;i<p_node->children.size();i++) {
-
- Error err = _create_resources(p_node->children[i]);
- if (err)
- return err;
- }
- return OK;
-}
-
-
-Error ColladaImport::load(const String& p_path,int p_flags,bool p_force_make_tangents) {
-
- Error err = collada.load(p_path,p_flags);
- ERR_FAIL_COND_V(err,err);
-
- force_make_tangents=p_force_make_tangents;
- ERR_FAIL_COND_V( !collada.state.visual_scene_map.has( collada.state.root_visual_scene ), ERR_INVALID_DATA );
- Collada::VisualScene &vs = collada.state.visual_scene_map[ collada.state.root_visual_scene ];
-
- scene = memnew( Spatial ); // root
-
- //determine what's going on with the lights
- for(int i=0;i<vs.root_nodes.size();i++) {
-
- _pre_process_lights(vs.root_nodes[i]);
-
- }
- //import scene
-
- for(int i=0;i<vs.root_nodes.size();i++) {
-
- Error err = _create_scene_skeletons(vs.root_nodes[i]);
- if (err!=OK) {
- memdelete(scene);
- ERR_FAIL_COND_V(err,err);
- }
- }
-
- for(int i=0;i<vs.root_nodes.size();i++) {
-
- Error err = _create_scene(vs.root_nodes[i],scene);
- if (err!=OK) {
- memdelete(scene);
- ERR_FAIL_COND_V(err,err);
- }
-
- Error err2 = _create_resources(vs.root_nodes[i]);
- if (err2!=OK) {
- memdelete(scene);
- ERR_FAIL_COND_V(err2,err2);
- }
- }
-
- //optatively, set unit scale in the root
- scene->set_transform(collada.get_root_transform());
-
-
- return OK;
-
-}
-
-void ColladaImport::_fix_param_animation_tracks() {
-
- for (Map<String,Collada::Node*>::Element *E=collada.state.scene_map.front();E;E=E->next()) {
-
- Collada::Node *n = E->get();
- switch(n->type) {
-
- case Collada::Node::TYPE_NODE: {
- // ? do nothing
- } break;
- case Collada::Node::TYPE_JOINT: {
-
- } break;
- case Collada::Node::TYPE_SKELETON: {
-
- } break;
- case Collada::Node::TYPE_LIGHT: {
-
- } break;
- case Collada::Node::TYPE_CAMERA: {
-
- } break;
- case Collada::Node::TYPE_GEOMETRY: {
-
- Collada::NodeGeometry *ng = static_cast<Collada::NodeGeometry*>(n);
- // test source(s)
- String source = ng->source;
-
- while (source!="") {
-
- if (collada.state.skin_controller_data_map.has(source)) {
-
- const Collada::SkinControllerData& skin = collada.state.skin_controller_data_map[source];
-
- //nothing to animate here i think
-
- source=skin.base;
- } else if (collada.state.morph_controller_data_map.has(source)) {
-
-
- const Collada::MorphControllerData& morph = collada.state.morph_controller_data_map[source];
-
- if (morph.targets.has("MORPH_WEIGHT") && morph.targets.has("MORPH_TARGET")) {
-
-
- String weights = morph.targets["MORPH_WEIGHT"];
- String targets = morph.targets["MORPH_TARGET"];
- //fails here
-
- if (morph.sources.has(targets) && morph.sources.has(weights)) {
- const Collada::MorphControllerData::Source &weight_src=morph.sources[weights];
- const Collada::MorphControllerData::Source &target_src=morph.sources[targets];
-
-
- ERR_FAIL_COND(weight_src.array.size() != target_src.sarray.size());
-
- for(int i=0;i<weight_src.array.size();i++) {
-
- String track_name = weights+"("+itos(i)+")";
- String mesh_name = target_src.sarray[i];
- if (collada.state.mesh_name_map.has(mesh_name) && collada.state.referenced_tracks.has(track_name)) {
-
-
- const Vector<int>&rt = collada.state.referenced_tracks[track_name];
-
- for(int rti=0;rti<rt.size();rti++) {
- Collada::AnimationTrack *at = &collada.state.animation_tracks[rt[rti]];
-
- at->target=E->key();
- at->param="morph/"+collada.state.mesh_name_map[mesh_name];
- at->property=true;
- //at->param
- }
- }
- }
- }
- }
- source=morph.mesh;
- } else {
-
- source=""; // for now nothing else supported
- }
- }
-
- } break;
-
- }
- }
-
-}
-
-void ColladaImport::create_animations(bool p_make_tracks_in_all_bones, bool p_import_value_tracks) {
-
-
- _fix_param_animation_tracks();
- for(int i=0;i<collada.state.animation_clips.size();i++) {
-
- for(int j=0;j<collada.state.animation_clips[i].tracks.size();j++)
- tracks_in_clips.insert(collada.state.animation_clips[i].tracks[j]);
- }
-
-
-
- for(int i=0;i<collada.state.animation_tracks.size();i++) {
-
- Collada::AnimationTrack &at = collada.state.animation_tracks[i];
- //print_line("CHANNEL: "+at.target+" PARAM: "+at.param);
-
- String node;
-
- if (!node_map.has(at.target)) {
-
- 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;
- }
-
-
- if (at.property) {
-
- valid_animated_properties.push_back(i);
-
- } else {
-
- node_map[node].anim_tracks.push_back(i);
- valid_animated_nodes.insert(node);
- }
-
- }
-
- create_animation(-1,p_make_tracks_in_all_bones, p_import_value_tracks);
- //print_line("clipcount: "+itos(collada.state.animation_clips.size()));
- for(int i=0;i<collada.state.animation_clips.size();i++)
- create_animation(i, p_make_tracks_in_all_bones, p_import_value_tracks);
-
-}
-
-void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks) {
-
- Ref<Animation> animation = Ref<Animation>( memnew( Animation ));
-
-
- if (p_clip==-1) {
-
- //print_line("default");
- animation->set_name("default");
- } else {
- //print_line("clip name: "+collada.state.animation_clips[p_clip].name);
- animation->set_name(collada.state.animation_clips[p_clip].name);
- }
-
- for(Map<String,NodeMap>::Element *E=node_map.front();E;E=E->next()) {
-
- if (E->get().bone<0)
- continue;
- bones_with_animation[E->key()]=false;
- }
- //store and validate tracks
-
- if (p_clip==-1) {
- //main anim
- }
-
- Set<int> track_filter;
-
-
- if (p_clip==-1) {
-
- for(int i=0;i<collada.state.animation_clips.size();i++) {
-
- int tc = collada.state.animation_clips[i].tracks.size();
- for(int j=0;j<tc;j++) {
-
- String n = collada.state.animation_clips[i].tracks[j];
- if (collada.state.by_id_tracks.has(n)) {
-
- const Vector<int>&ti = collada.state.by_id_tracks[n];
- for(int k=0;k<ti.size();k++) {
- track_filter.insert(ti[k]);
- }
- }
- }
- }
- } else {
-
- int tc = collada.state.animation_clips[p_clip].tracks.size();
- for(int j=0;j<tc;j++) {
-
- String n = collada.state.animation_clips[p_clip].tracks[j];
- if (collada.state.by_id_tracks.has(n)) {
-
- const Vector<int>&ti = collada.state.by_id_tracks[n];
- for(int k=0;k<ti.size();k++) {
- track_filter.insert(ti[k]);
- }
- }
- }
-
- }
-
- //animation->set_loop(true);
- //create animation tracks
-
- Vector<float> base_snapshots;
-
- float f=0;
- float snapshot_interval = 1.0/bake_fps; //should be customizable somewhere...
-
- float anim_length=collada.state.animation_length;
- if (p_clip>=0 && collada.state.animation_clips[p_clip].end)
- anim_length=collada.state.animation_clips[p_clip].end;
-
- while(f<anim_length) {
-
- base_snapshots.push_back(f);
-
- f+=snapshot_interval;
-
- if (f>=anim_length) {
- base_snapshots.push_back(anim_length);
-
- }
- }
-
- //print_line("anim len: "+rtos(anim_length));
- animation->set_length(anim_length);
-
- 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())) {
-
- continue;
- }
-
- NodeMap &nm = node_map[E->get()];
- String path = scene->get_path_to(nm.node);
-
- if (nm.bone>=0) {
- Skeleton *sk = static_cast<Skeleton*>(nm.node);
- String name = sk->get_bone_name(nm.bone);
- path=path+":"+name;
- }
-
- bool found_anim=false;
-
-
- Collada::Node *cn = collada.state.scene_map[E->get()];
- if (cn->ignore_anim) {
-
- continue;
- }
-
-
-
- animation->add_track(Animation::TYPE_TRANSFORM);
- int track = animation->get_track_count() -1;
- animation->track_set_path( track , path );
- animation->track_set_imported( track , true ); //helps merging later
-
- Vector<float> snapshots = base_snapshots;
-
- if (nm.anim_tracks.size()==1) {
- //use snapshot keys from anim track instead, because this was most likely exported baked
- Collada::AnimationTrack &at = collada.state.animation_tracks[nm.anim_tracks.front()->get()];
- snapshots.clear();
- for(int i=0;i<at.keys.size();i++)
- snapshots.push_back(at.keys[i].time);
-
-
- }
-
-
- 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())) {
-
- continue;
- }
- } else {
-
- if (!track_filter.has(ET->get()))
- continue;
-
- }
-
- found_anim=true;
-
- Collada::AnimationTrack &at = collada.state.animation_tracks[ET->get()];
-
- int xform_idx=-1;
- for(int j=0;j<cn->xform_list.size();j++) {
-
-
- if (cn->xform_list[j].id==at.param) {
-
- xform_idx=j;
- break;
- }
- }
-
- if (xform_idx==-1) {
- print_line("couldnt find matching node "+at.target+" xform for track "+at.param);
- continue;
- }
-
- ERR_CONTINUE(xform_idx==-1);
-
- Vector<float> data = at.get_value_at_time(snapshots[i]);
- ERR_CONTINUE(data.empty());
-
-
- Collada::Node::XForm &xf = cn->xform_list[xform_idx];
-
- if (at.component=="ANGLE") {
- ERR_CONTINUE(data.size()!=1);
- ERR_CONTINUE(xf.op!=Collada::Node::XForm::OP_ROTATE);
- ERR_CONTINUE(xf.data.size()<4);
- xf.data[3]=data[0];
- } else if (at.component=="X" || at.component=="Y" || at.component=="Z") {
- int cn=at.component[0]-'X';
- ERR_CONTINUE(cn>=xf.data.size());
- ERR_CONTINUE(data.size()>1);
- xf.data[cn]=data[0];
- } else if (data.size()==xf.data.size()) {
-
- xf.data=data;
- } else {
-
-
- if ( data.size()!=xf.data.size() ) {
- print_line("component "+at.component+" datasize "+itos(data.size())+" xfdatasize "+itos(xf.data.size()));
- }
-
- ERR_CONTINUE( data.size()!=xf.data.size() );
- }
- }
-
- Transform xform = cn->compute_transform(collada);
- xform = collada.fix_transform(xform) * cn->post_transform;
-
-
- if (nm.bone>=0) {
- //make bone transform relative to rest (in case of skeleton)
- Skeleton *sk = nm.node->cast_to<Skeleton>();
- if (sk) {
-
- xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform;
- } else {
-
- ERR_PRINT("INVALID SKELETON!!!!");
- }
- }
-
- Quat q = xform.basis;
- q.normalize();
- Vector3 s = xform.basis.get_scale();
- Vector3 l = xform.origin;
-
- animation->transform_track_insert_key(track,snapshots[i],l,q,s);
-
- }
-
-
-
- if (nm.bone>=0) {
- if (found_anim)
- bones_with_animation[E->get()]=true;
- }
-
- if (found_anim)
- tracks_found=true;
- else {
- animation->remove_track( track );
- }
-
- }
-
- if (p_make_tracks_in_all_bones) {
-
- //some bones may lack animation, but since we don't store pose as a property, we must add keyframes!
- for(Map<String,bool>::Element *E=bones_with_animation.front();E;E=E->next()) {
-
- if (E->get())
- continue;
-
- //print_line("BONE LACKS ANIM: "+E->key());
-
- NodeMap &nm = node_map[E->key()];
- String path = scene->get_path_to(nm.node);
- ERR_CONTINUE( nm.bone <0 );
- Skeleton *sk = static_cast<Skeleton*>(nm.node);
- String name = sk->get_bone_name(nm.bone);
- path=path+":"+name;
-
- Collada::Node *cn = collada.state.scene_map[E->key()];
- if (cn->ignore_anim) {
- print_line("warning, ignoring animation on node: "+path);
- continue;
- }
-
- animation->add_track(Animation::TYPE_TRANSFORM);
- int track = animation->get_track_count() -1;
- animation->track_set_path( track , path );
- animation->track_set_imported( track , true ); //helps merging later
-
-
- Transform xform = cn->compute_transform(collada);
- xform = collada.fix_transform(xform) * cn->post_transform;
-
- xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform;
-
- Quat q = xform.basis;
- q.normalize();
- Vector3 s = xform.basis.get_scale();
- Vector3 l = xform.origin;
-
- animation->transform_track_insert_key(track,0,l,q,s);
-
- tracks_found=true;
- }
- }
-
-
-
- if (p_import_value_tracks) {
- for (int i = 0; i < valid_animated_properties.size(); i++) {
-
-
- int ti = valid_animated_properties[i];
-
- if (p_clip == -1) {
-
- if (track_filter.has(ti))
- continue;
- }
- else {
-
- if (!track_filter.has(ti))
- continue;
-
- }
-
-
- Collada::AnimationTrack &at = collada.state.animation_tracks[ti];
-
- // take snapshots
- if (!collada.state.scene_map.has(at.target))
- continue;
-
- NodeMap &nm = node_map[at.target];
- String path = scene->get_path_to(nm.node);
-
- animation->add_track(Animation::TYPE_VALUE);
- int track = animation->get_track_count() - 1;
-
- path = path + ":" + at.param;
- animation->track_set_path(track, path);
- animation->track_set_imported(track, true); //helps merging later
-
-
- for (int i = 0; i < at.keys.size(); i++) {
-
- float time = at.keys[i].time;
- Variant value;
- Vector<float> data = at.keys[i].data;
- if (data.size() == 1) {
- //push a float
- value = data[0];
-
- }
- else if (data.size() == 16) {
- //matrix
- print_line("value keys for matrices not supported");
- }
- else {
-
- print_line("don't know what to do with this amount of value keys: " + itos(data.size()));
- }
-
- animation->track_insert_key(track, time, value);
- }
-
-
- tracks_found = true;
-
- }
- }
-
-
-
- if (tracks_found) {
-
- animations.push_back(animation);
- }
-
-
-
-}
-
-
-/*********************************************************************************/
-/*************************************** SCENE ***********************************/
-/*********************************************************************************/
-
-
-#define DEBUG_ANIMATION
-
-
-uint32_t EditorSceneImporterCollada::get_import_flags() const {
-
- return IMPORT_SCENE|IMPORT_ANIMATION;
-
-}
-void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) const {
-
-
- r_extensions->push_back("dae");
-}
-Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_flags,int p_bake_fps, List<String> *r_missing_deps, Error* r_err) {
-
- ColladaImport state;
- uint32_t flags=Collada::IMPORT_FLAG_SCENE;
- if (p_flags&IMPORT_ANIMATION)
- flags|=Collada::IMPORT_FLAG_ANIMATION;
-
- state.use_mesh_builtin_materials=!(p_flags&IMPORT_MATERIALS_IN_INSTANCES);
- state.bake_fps=p_bake_fps;
-
- Error err = state.load(p_path,flags,p_flags&EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
-
- ERR_FAIL_COND_V(err!=OK,NULL);
-
- if (state.missing_textures.size()) {
-
- /*
- for(int i=0;i<state.missing_textures.size();i++) {
- EditorNode::add_io_error("Texture Not Found: "+state.missing_textures[i]);
- }
- */
-
-
- if (r_missing_deps) {
-
- for(int i=0;i<state.missing_textures.size();i++) {
- //EditorNode::add_io_error("Texture Not Found: "+state.missing_textures[i]);
- r_missing_deps->push_back(state.missing_textures[i]);
- }
-
- }
- }
-
- if (p_flags&IMPORT_ANIMATION) {
-
- state.create_animations(p_flags&IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS,p_flags&EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
- AnimationPlayer *ap = memnew( AnimationPlayer );
- for(int i=0;i<state.animations.size();i++) {
- String name;
- if (state.animations[i]->get_name()=="")
- name="default";
- else
- name=state.animations[i]->get_name();
-
- if (p_flags&IMPORT_ANIMATION_DETECT_LOOP) {
-
- if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
- state.animations[i]->set_loop(true);
- }
- }
-
- ap->add_animation(name,state.animations[i]);
- }
- state.scene->add_child(ap);
- ap->set_owner(state.scene);
-
- }
-
- return state.scene;
-
-}
-
-Ref<Animation> EditorSceneImporterCollada::import_animation(const String& p_path,uint32_t p_flags) {
-
-
- ColladaImport state;
-
-
- state.use_mesh_builtin_materials=false;
-
- Error err = state.load(p_path,Collada::IMPORT_FLAG_ANIMATION,p_flags&EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
- ERR_FAIL_COND_V(err!=OK,RES());
-
-
- state.create_animations(p_flags&EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS,p_flags&EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS);
- if (state.scene)
- memdelete(state.scene);
-
- if (state.animations.size()==0)
- return Ref<Animation>();
- Ref<Animation> anim=state.animations[0];
- anim=state.animations[0];
- print_line("Anim Load OK");
- String base = p_path.get_basename().to_lower();
- if (p_flags&IMPORT_ANIMATION_DETECT_LOOP) {
-
- if (base.begins_with("loop") || base.ends_with("loop") || base.begins_with("cycle") || base.ends_with("cycle")) {
- anim->set_loop(true);
- }
- }
-
-
- return anim;
-}
-
-
-EditorSceneImporterCollada::EditorSceneImporterCollada() {
-
-
-}
-
diff --git a/tools/editor/import/editor_import_collada.h b/tools/editor/import/editor_import_collada.h
deleted file mode 100644
index cd3614bb40..0000000000
--- a/tools/editor/import/editor_import_collada.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*************************************************************************/
-/* editor_import_collada.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_IMPORT_COLLADA_H
-#define EDITOR_IMPORT_COLLADA_H
-
-#include "tools/editor/import/resource_importer_scene.h"
-
-
-
-class EditorSceneImporterCollada : public EditorSceneImporter {
-
- GDCLASS(EditorSceneImporterCollada,EditorSceneImporter );
-public:
-
- virtual uint32_t get_import_flags() const;
- virtual void get_extensions(List<String> *r_extensions) const;
- virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps=NULL,Error* r_err=NULL);
- virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
-
- EditorSceneImporterCollada();
-};
-
-
-#endif
-
diff --git a/tools/editor/import/resource_importer_csv_translation.cpp b/tools/editor/import/resource_importer_csv_translation.cpp
deleted file mode 100644
index f14c10fb99..0000000000
--- a/tools/editor/import/resource_importer_csv_translation.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-
-#include "resource_importer_csv_translation.h"
-#include "os/file_access.h"
-#include "translation.h"
-#include "io/resource_saver.h"
-#include "compressed_translation.h"
-
-String ResourceImporterCSVTranslation::get_importer_name() const {
-
- return "csv_translation";
-}
-
-String ResourceImporterCSVTranslation::get_visible_name() const{
-
- return "CSV Translation";
-}
-void ResourceImporterCSVTranslation::get_recognized_extensions(List<String> *p_extensions) const{
-
- p_extensions->push_back("csv");
-}
-
-String ResourceImporterCSVTranslation::get_save_extension() const {
- return ""; //does not save a single resoure
-}
-
-String ResourceImporterCSVTranslation::get_resource_type() const{
-
- return "StreamCSVTranslation";
-}
-
-bool ResourceImporterCSVTranslation::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
-
- return true;
-}
-
-int ResourceImporterCSVTranslation::get_preset_count() const {
- return 0;
-}
-String ResourceImporterCSVTranslation::get_preset_name(int p_idx) const {
-
- return "";
-}
-
-
-void ResourceImporterCSVTranslation::get_import_options(List<ImportOption> *r_options,int p_preset) const {
-
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"compress"),true));
-
-}
-
-
-
-Error ResourceImporterCSVTranslation::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
-
-
- bool compress = p_options["compress"];
- FileAccessRef f = FileAccess::open(p_source_file,FileAccess::READ);
-
- ERR_FAIL_COND_V( !f, ERR_INVALID_PARAMETER );
-
- Vector<String> line = f->get_csv_line();
- if (line.size()<=1) {
- return ERR_PARSE_ERROR;
- }
-
- Vector<String> locales;
- Vector<Ref<Translation> > translations;
-
- for(int i=1;i<line.size();i++) {
-
- String locale = line[i];
- if (!TranslationServer::is_locale_valid(locale)) {
- return ERR_PARSE_ERROR;
- }
-
- locales.push_back(locale);
- Ref<Translation> translation;
- translation.instance();
- translation->set_locale(locale);
- translations.push_back(translation);
- }
-
- line = f->get_csv_line();
-
- while(line.size()==locales.size()+1) {
-
- String key = line[0];
- if (key!="") {
-
- for(int i=1;i<line.size();i++) {
- translations[i-1]->add_message(key,line[i]);
- }
- }
-
- line = f->get_csv_line();
- }
-
-
- for(int i=0;i<translations.size();i++) {
- Ref<Translation> xlt = translations[i];
-
- if (compress) {
- Ref<PHashTranslation> cxl = memnew( PHashTranslation );
- cxl->generate( xlt );
- xlt=cxl;
- }
-
- String save_path = p_source_file.get_basename()+"."+translations[i]->get_locale()+".xl";
-
- ResourceSaver::save(save_path,xlt);
- if (r_gen_files) {
- r_gen_files->push_back(save_path);
- }
- }
-
-
-
- return OK;
-
-}
-
-ResourceImporterCSVTranslation::ResourceImporterCSVTranslation()
-{
-
-}
diff --git a/tools/editor/import/resource_importer_csv_translation.h b/tools/editor/import/resource_importer_csv_translation.h
deleted file mode 100644
index d08218e7d9..0000000000
--- a/tools/editor/import/resource_importer_csv_translation.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef RESOURCEIMPORTERCSVTRANSLATION_H
-#define RESOURCEIMPORTERCSVTRANSLATION_H
-
-#include "io/resource_import.h"
-
-
-class ResourceImporterCSVTranslation : public ResourceImporter {
- GDCLASS(ResourceImporterCSVTranslation,ResourceImporter)
-public:
- virtual String get_importer_name() const;
- virtual String get_visible_name() const;
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual String get_save_extension() const;
- virtual String get_resource_type() const;
-
- virtual int get_preset_count() const;
- virtual String get_preset_name(int p_idx) const;
-
- virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
- virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
-
- virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
-
- ResourceImporterCSVTranslation();
-};
-
-#endif // RESOURCEIMPORTERCSVTRANSLATION_H
diff --git a/tools/editor/import/resource_importer_obj.cpp b/tools/editor/import/resource_importer_obj.cpp
deleted file mode 100644
index e6e23366f6..0000000000
--- a/tools/editor/import/resource_importer_obj.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-#include "resource_importer_obj.h"
-
-#include "io/resource_saver.h"
-#include "scene/resources/mesh.h"
-#include "scene/resources/surface_tool.h"
-#include "scene/resources/surface_tool.h"
-#include "os/file_access.h"
-
-String ResourceImporterOBJ::get_importer_name() const {
-
- return "obj_mesh";
-}
-
-String ResourceImporterOBJ::get_visible_name() const{
-
- return "OBJ As Mesh";
-}
-void ResourceImporterOBJ::get_recognized_extensions(List<String> *p_extensions) const{
-
- p_extensions->push_back("obj");
-}
-String ResourceImporterOBJ::get_save_extension() const {
- return "msh";
-}
-
-String ResourceImporterOBJ::get_resource_type() const{
-
- return "Mesh";
-}
-
-bool ResourceImporterOBJ::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
-
- return true;
-}
-
-int ResourceImporterOBJ::get_preset_count() const {
- return 0;
-}
-String ResourceImporterOBJ::get_preset_name(int p_idx) const {
-
- return String();
-}
-
-
-void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options,int p_preset) const {
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/tangents"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"generate/normals"),true));
- //not for nowp
- //r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/materials")));
- //r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"import/textures")));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/flip_faces"),false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/smooth_shading"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/weld_vertices"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001"),0.0001));
- //r_options->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
-
-}
-
-
-
-Error ResourceImporterOBJ::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
-
- FileAccessRef f = FileAccess::open(p_source_file,FileAccess::READ);
- ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
-
- Ref<Mesh> mesh = Ref<Mesh>( memnew( Mesh ) );
- Map<String,Ref<Material> > name_map;
-
-
-
- bool generate_normals=p_options["generate/normals"];
- bool generate_tangents=p_options["generate/tangents"];
- bool flip_faces=p_options["force/flip_faces"];
- bool force_smooth=p_options["force/smooth_shading"];
- bool weld_vertices=p_options["force/weld_vertices"];
- float weld_tolerance=p_options["force/weld_tolerance"];
- Vector<Vector3> vertices;
- Vector<Vector3> normals;
- Vector<Vector2> uvs;
- String name;
-
- Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ;
- surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
- if (force_smooth)
- surf_tool->add_smooth_group(true);
- int has_index_data=false;
-
- while(true) {
-
-
- String l = f->get_line().strip_edges();
-
- if (l.begins_with("v ")) {
- //vertex
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
- Vector3 vtx;
- vtx.x=v[1].to_float();
- vtx.y=v[2].to_float();
- vtx.z=v[3].to_float();
- vertices.push_back(vtx);
- } else if (l.begins_with("vt ")) {
- //uv
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
- Vector2 uv;
- uv.x=v[1].to_float();
- uv.y=1.0-v[2].to_float();
- uvs.push_back(uv);
-
- } else if (l.begins_with("vn ")) {
- //normal
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
- Vector3 nrm;
- nrm.x=v[1].to_float();
- nrm.y=v[2].to_float();
- nrm.z=v[3].to_float();
- normals.push_back(nrm);
- } if (l.begins_with("f ")) {
- //vertex
-
- has_index_data=true;
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
-
- //not very fast, could be sped up
-
-
- Vector<String> face[3];
- face[0] = v[1].split("/");
- face[1] = v[2].split("/");
- ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR);
- ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR);
- for(int i=2;i<v.size()-1;i++) {
-
- face[2] = v[i+1].split("/");
- ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR);
- for(int j=0;j<3;j++) {
-
- int idx=j;
-
- if (!flip_faces && idx<2) {
- idx=1^idx;
- }
-
-
- if (face[idx].size()==3) {
- int norm = face[idx][2].to_int()-1;
- ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR);
- surf_tool->add_normal(normals[norm]);
- }
-
- if (face[idx].size()>=2 && face[idx][1]!=String()) {
-
- int uv = face[idx][1].to_int()-1;
- ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR);
- surf_tool->add_uv(uvs[uv]);
- }
-
- int vtx = face[idx][0].to_int()-1;
- ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR);
-
- Vector3 vertex = vertices[vtx];
- if (weld_vertices)
- vertex=vertex.snapped(weld_tolerance);
- surf_tool->add_vertex(vertex);
- }
-
- face[1]=face[2];
- }
- } else if (l.begins_with("s ") && !force_smooth) { //smoothing
- String what = l.substr(2,l.length()).strip_edges();
- if (what=="off")
- surf_tool->add_smooth_group(false);
- else
- surf_tool->add_smooth_group(true);
-
- } else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done
-
- if (has_index_data) {
- //new object/surface
- if (generate_normals || force_smooth)
- surf_tool->generate_normals();
- if (uvs.size() && (normals.size() || generate_normals) && generate_tangents)
- surf_tool->generate_tangents();
-
- surf_tool->index();
- mesh = surf_tool->commit(mesh);
- if (name=="")
- name=vformat(TTR("Surface %d"),mesh->get_surface_count()-1);
- mesh->surface_set_name(mesh->get_surface_count()-1,name);
- name="";
- surf_tool->clear();
- surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
- if (force_smooth)
- surf_tool->add_smooth_group(true);
-
- has_index_data=false;
-
- if (f->eof_reached())
- break;
- }
-
- if (l.begins_with("o ")) //name
- name=l.substr(2,l.length()).strip_edges();
- }
- }
-
-/*
- TODO, check existing materials and merge?
- //re-apply materials if exist
- for(int i=0;i<mesh->get_surface_count();i++) {
-
- String n = mesh->surface_get_name(i);
- if (name_map.has(n))
- mesh->surface_set_material(i,name_map[n]);
- }
-*/
-
- Error err = ResourceSaver::save(p_save_path+".msh",mesh);
-
- return err;
-
-}
-
-ResourceImporterOBJ::ResourceImporterOBJ()
-{
-
-}
diff --git a/tools/editor/import/resource_importer_obj.h b/tools/editor/import/resource_importer_obj.h
deleted file mode 100644
index d2a3c4fddd..0000000000
--- a/tools/editor/import/resource_importer_obj.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef RESOURCEIMPORTEROBJ_H
-#define RESOURCEIMPORTEROBJ_H
-
-
-#include "io/resource_import.h"
-
-class ResourceImporterOBJ : public ResourceImporter {
- GDCLASS(ResourceImporterOBJ,ResourceImporter)
-public:
- virtual String get_importer_name() const;
- virtual String get_visible_name() const;
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual String get_save_extension() const;
- virtual String get_resource_type() const;
-
- virtual int get_preset_count() const;
- virtual String get_preset_name(int p_idx) const;
-
- virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
- virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
-
- virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
-
- ResourceImporterOBJ();
-};
-
-
-#endif // RESOURCEIMPORTEROBJ_H
diff --git a/tools/editor/import/resource_importer_scene.cpp b/tools/editor/import/resource_importer_scene.cpp
deleted file mode 100644
index ae840e9e16..0000000000
--- a/tools/editor/import/resource_importer_scene.cpp
+++ /dev/null
@@ -1,1328 +0,0 @@
-#include "resource_importer_scene.h"
-
-#include "scene/resources/packed_scene.h"
-#include "io/resource_saver.h"
-#include "tools/editor/editor_node.h"
-
-#include "scene/3d/mesh_instance.h"
-#include "scene/3d/navigation.h"
-#include "scene/3d/room_instance.h"
-#include "scene/3d/body_shape.h"
-#include "scene/3d/physics_body.h"
-#include "scene/3d/portal.h"
-#include "scene/3d/vehicle_body.h"
-#include "scene/resources/sphere_shape.h"
-#include "scene/resources/box_shape.h"
-#include "scene/resources/ray_shape.h"
-#include "scene/resources/plane_shape.h"
-
-
-void EditorScenePostImport::_bind_methods() {
-
- BIND_VMETHOD( MethodInfo("post_import",PropertyInfo(Variant::OBJECT,"scene")) );
-
-}
-
-Node *EditorScenePostImport::post_import(Node* p_scene) {
-
- if (get_script_instance())
- return get_script_instance()->call("post_import",p_scene);
-
- return p_scene;
-}
-
-EditorScenePostImport::EditorScenePostImport() {
-
-
-}
-
-
-String ResourceImporterScene::get_importer_name() const {
-
- return "scene";
-}
-
-String ResourceImporterScene::get_visible_name() const{
-
- return "Scene";
-}
-
-void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions) const{
-
- for (Set< Ref<EditorSceneImporter> >::Element *E=importers.front();E;E=E->next()) {
- E->get()->get_extensions(p_extensions);
- }
-}
-
-String ResourceImporterScene::get_save_extension() const {
- return "scn";
-}
-
-String ResourceImporterScene::get_resource_type() const{
-
- return "PackedScene";
-}
-
-bool ResourceImporterScene::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
-
- if (p_option.begins_with("animation/")) {
- if (p_option!="animation/import" && !bool(p_options["animation/import"]))
- return false;
-
- if (p_option.begins_with("animation/optimizer/") && p_option!="animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"]))
- return false;
-
- if (p_option.begins_with("animation/clip_")) {
- int max_clip = p_options["animation/clips/amount"];
- int clip = p_option.get_slice("/",1).get_slice("_",1).to_int()-1;
- if (clip>=max_clip)
- return false;
- }
- }
-
- return true;
-
-}
-
-int ResourceImporterScene::get_preset_count() const {
- return 0;
-}
-String ResourceImporterScene::get_preset_name(int p_idx) const {
-
- return "";
-}
-
-
-static bool _teststr(const String& p_what,const String& p_str) {
-
- if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
- return true;
- if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
- return true;
- if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
- return true;
- return false;
-}
-
-static String _fixstr(const String& p_what,const String& p_str) {
-
- if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
- return p_what.replace("$"+p_str,"");
- if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
- return p_what.substr(0,p_what.length()-(p_str.length()+1));
- if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
- return p_what.substr(0,p_what.length()-(p_str.length()+1));
- return p_what;
-}
-
-
-Node* ResourceImporterScene::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map) {
-
- // children first..
- for(int i=0;i<p_node->get_child_count();i++) {
-
-
- Node *r = _fix_node(p_node->get_child(i),p_root,collision_map);
- if (!r) {
- print_line("was erased..");
- i--; //was erased
- }
- }
-
- String name = p_node->get_name();
-
- bool isroot = p_node==p_root;
-
-
- if (!isroot && _teststr(name,"noimp")) {
-
- memdelete(p_node);
- return NULL;
- }
-
-
- if (p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- bool bb=false;
-
- if ((_teststr(name,"bb"))) {
- bb=true;
- } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) {
- bb=true;
-
- }
-
- if (bb) {
- mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
- if (mi->get_mesh().is_valid()) {
-
- Ref<Mesh> m = mi->get_mesh();
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
- if (fm.is_valid()) {
- //fm->set_flag(Material::FLAG_UNSHADED,true);
- //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- }
- }
- }
- }
- }
-
-
- if (p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- Ref<Mesh> m = mi->get_mesh();
-
- if (m.is_valid()) {
-
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> mat = m->surface_get_material(i);
- if (!mat.is_valid())
- continue;
-
- if (_teststr(mat->get_name(),"alpha")) {
-
- mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
- mat->set_name(_fixstr(mat->get_name(),"alpha"));
- }
- if (_teststr(mat->get_name(),"vcol")) {
-
- mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
- mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
- mat->set_name(_fixstr(mat->get_name(),"vcol"));
- }
-
- }
- }
- }
-
- if (p_node->cast_to<AnimationPlayer>()) {
- //remove animations referencing non-importable nodes
- AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>();
-
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
-
- Ref<Animation> anim=ap->get_animation(E->get());
- ERR_CONTINUE(anim.is_null());
- for(int i=0;i<anim->get_track_count();i++) {
- NodePath path = anim->track_get_path(i);
-
- for(int j=0;j<path.get_name_count();j++) {
- String node = path.get_name(j);
- if (_teststr(node,"noimp")) {
- anim->remove_track(i);
- i--;
- break;
- }
- }
- }
-
- }
- }
-
-
- if (p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- String str;
-
- if ((_teststr(name,"imp"))) {
- str=name;
- } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) {
- str=mi->get_mesh()->get_name();
-
- }
-
-
- if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
- String d=str.substr(str.find("imp")+3,str.length());
- if (d!="") {
- if ((d[0]<'0' || d[0]>'9'))
- d=d.substr(1,d.length());
- if (d.length() && d[0]>='0' && d[0]<='9') {
- float dist = d.to_double();
- mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
- mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true);
- //mi->set_draw_range_begin(dist);
- //mi->set_draw_range_end(100000);
-
- //mip->set_draw_range_begin(0);
- //mip->set_draw_range_end(dist);
-
- if (mi->get_mesh().is_valid()) {
-
- Ref<Mesh> m = mi->get_mesh();
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
- if (fm.is_valid()) {
- //fm->set_flag(Material::FLAG_UNSHADED,true);
- //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- }
- }
- }
- }
- }
- }
- }
-#if 0
- if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- String str;
-
- if ((_teststr(name,"lod"))) {
- str=name;
- } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) {
- str=mi->get_mesh()->get_name();
-
- }
-
-
- if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
- String d=str.substr(str.find("lod")+3,str.length());
- if (d!="") {
- if ((d[0]<'0' || d[0]>'9'))
- d=d.substr(1,d.length());
- if (d.length() && d[0]>='0' && d[0]<='9') {
- float dist = d.to_double();
- /// mi->set_draw_range_begin(dist);
- // mi->set_draw_range_end(100000);
-
- // mip->set_draw_range_begin(0);
- // mip->set_draw_range_end(dist);
-
- /*if (mi->get_mesh().is_valid()) {
-
- Ref<Mesh> m = mi->get_mesh();
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
- if (fm.is_valid()) {
- fm->set_flag(Material::FLAG_UNSHADED,true);
- fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
- fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- }
- }
- }*/
- }
- }
- }
- }
-
-
- if (p_flags&SCENE_FLAG_DETECT_LIGHTMAP_LAYER && _teststr(name,"lm") && p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- String str=name;
- int layer = str.substr(str.find("lm")+3,str.length()).to_int();
- //mi->set_baked_light_texture_id(layer);
- }
-#endif
- if (_teststr(name,"colonly")) {
-
- if (isroot)
- return p_node;
-
- if (p_node->cast_to<MeshInstance>()) {
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- Node * col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col,NULL);
-
- col->set_name(_fixstr(name,"colonly"));
- col->cast_to<Spatial>()->set_transform(mi->get_transform());
- p_node->replace_by(col);
- memdelete(p_node);
- p_node=col;
-
- StaticBody *sb = col->cast_to<StaticBody>();
- CollisionShape *colshape = memnew( CollisionShape);
- colshape->set_shape(sb->get_shape(0));
- colshape->set_name("shape");
- sb->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
- } else if (p_node->has_meta("empty_draw_type")) {
- String empty_draw_type = String(p_node->get_meta("empty_draw_type"));
- print_line(empty_draw_type);
- StaticBody *sb = memnew( StaticBody);
- sb->set_name(_fixstr(name,"colonly"));
- sb->cast_to<Spatial>()->set_transform(p_node->cast_to<Spatial>()->get_transform());
- p_node->replace_by(sb);
- memdelete(p_node);
- CollisionShape *colshape = memnew( CollisionShape);
- if (empty_draw_type == "CUBE") {
- BoxShape *boxShape = memnew( BoxShape);
- boxShape->set_extents(Vector3(1, 1, 1));
- colshape->set_shape(boxShape);
- colshape->set_name("BoxShape");
- } else if (empty_draw_type == "SINGLE_ARROW") {
- RayShape *rayShape = memnew( RayShape);
- rayShape->set_length(1);
- colshape->set_shape(rayShape);
- colshape->set_name("RayShape");
- sb->cast_to<Spatial>()->rotate_x(Math_PI / 2);
- } else if (empty_draw_type == "IMAGE") {
- PlaneShape *planeShape = memnew( PlaneShape);
- colshape->set_shape(planeShape);
- colshape->set_name("PlaneShape");
- } else {
- SphereShape *sphereShape = memnew( SphereShape);
- sphereShape->set_radius(1);
- colshape->set_shape(sphereShape);
- colshape->set_name("SphereShape");
- }
- sb->add_child(colshape);
- colshape->set_owner(sb->get_owner());
- }
-
- } else if (_teststr(name,"rigid") && p_node->cast_to<MeshInstance>()) {
-
- if (isroot)
- return p_node;
-
- // get mesh instance and bounding box
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- Rect3 aabb = mi->get_aabb();
-
- // create a new rigid body collision node
- RigidBody * rigid_body = memnew( RigidBody );
- Node * col = rigid_body;
- ERR_FAIL_COND_V(!col,NULL);
-
- // remove node name postfix
- col->set_name(_fixstr(name,"rigid"));
- // get mesh instance xform matrix to the rigid body collision node
- col->cast_to<Spatial>()->set_transform(mi->get_transform());
- // save original node by duplicating it into a new instance and correcting the name
- Node * mesh = p_node->duplicate();
- mesh->set_name(_fixstr(name,"rigid"));
- // reset the xform matrix of the duplicated node so it can inherit parent node xform
- mesh->cast_to<Spatial>()->set_transform(Transform(Basis()));
- // reparent the new mesh node to the rigid body collision node
- p_node->add_child(mesh);
- mesh->set_owner(p_node->get_owner());
- // replace the original node with the rigid body collision node
- p_node->replace_by(col);
- memdelete(p_node);
- p_node=col;
-
- // create an alias for the rigid body collision node
- RigidBody *rb = col->cast_to<RigidBody>();
- // create a new Box collision shape and set the right extents
- Ref<BoxShape> shape = memnew( BoxShape );
- shape->set_extents(aabb.get_size() * 0.5);
- CollisionShape *colshape = memnew( CollisionShape);
- colshape->set_name("shape");
- colshape->set_shape(shape);
- // reparent the new collision shape to the rigid body collision node
- rb->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
-
- } else if (_teststr(name,"col") && p_node->cast_to<MeshInstance>()) {
-
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- mi->set_name(_fixstr(name,"col"));
- Node *col= mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col,NULL);
-
- col->set_name("col");
- p_node->add_child(col);
-
- StaticBody *sb=col->cast_to<StaticBody>();
- CollisionShape *colshape = memnew( CollisionShape);
- colshape->set_shape(sb->get_shape(0));
- colshape->set_name("shape");
- col->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
- sb->set_owner(p_node->get_owner());
-
- } else if (_teststr(name,"navmesh") && p_node->cast_to<MeshInstance>()) {
-
- if (isroot)
- return p_node;
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- Ref<Mesh> mesh=mi->get_mesh();
- ERR_FAIL_COND_V(mesh.is_null(),NULL);
- NavigationMeshInstance *nmi = memnew( NavigationMeshInstance );
-
-
- nmi->set_name(_fixstr(name,"navmesh"));
- Ref<NavigationMesh> nmesh = memnew( NavigationMesh);
- nmesh->create_from_mesh(mesh);
- nmi->set_navigation_mesh(nmesh);
- nmi->cast_to<Spatial>()->set_transform(mi->get_transform());
- p_node->replace_by(nmi);
- memdelete(p_node);
- p_node=nmi;
- } else if (_teststr(name,"vehicle")) {
-
- if (isroot)
- return p_node;
-
- Node *owner = p_node->get_owner();
- Spatial *s = p_node->cast_to<Spatial>();
- VehicleBody *bv = memnew( VehicleBody );
- String n = _fixstr(p_node->get_name(),"vehicle");
- bv->set_name(n);
- p_node->replace_by(bv);
- p_node->set_name(n);
- bv->add_child(p_node);
- bv->set_owner(owner);
- p_node->set_owner(owner);
- bv->set_transform(s->get_transform());
- s->set_transform(Transform());
-
- p_node=bv;
-
-
- } else if (_teststr(name,"wheel")) {
-
- if (isroot)
- return p_node;
-
- Node *owner = p_node->get_owner();
- Spatial *s = p_node->cast_to<Spatial>();
- VehicleWheel *bv = memnew( VehicleWheel );
- String n = _fixstr(p_node->get_name(),"wheel");
- bv->set_name(n);
- p_node->replace_by(bv);
- p_node->set_name(n);
- bv->add_child(p_node);
- bv->set_owner(owner);
- p_node->set_owner(owner);
- bv->set_transform(s->get_transform());
- s->set_transform(Transform());
-
- p_node=bv;
-
- } else if (_teststr(name,"room") && p_node->cast_to<MeshInstance>()) {
-
-
- if (isroot)
- return p_node;
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
-
-
- BSP_Tree bsptree(faces);
-
- Ref<RoomBounds> area = memnew( RoomBounds );
- //area->set_bounds(faces);
- //area->set_geometry_hint(faces);
-
-
- Room * room = memnew( Room );
- room->set_name(_fixstr(name,"room"));
- room->set_transform(mi->get_transform());
- room->set_room(area);
-
- p_node->replace_by(room);
- memdelete(p_node);
- p_node=room;
-
- } else if (_teststr(name,"room")) {
-
- if (isroot)
- return p_node;
-
- Spatial *dummy = p_node->cast_to<Spatial>();
- ERR_FAIL_COND_V(!dummy,NULL);
-
- Room * room = memnew( Room );
- room->set_name(_fixstr(name,"room"));
- room->set_transform(dummy->get_transform());
-
- p_node->replace_by(room);
- memdelete(p_node);
- p_node=room;
-
- //room->compute_room_from_subtree();
-
- } else if (_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) {
-
- if (isroot)
- return p_node;
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
-
- ERR_FAIL_COND_V(faces.size()==0,NULL);
- //step 1 compute the plane
- Set<Vector3> points;
- Plane plane;
-
- Vector3 center;
-
- for(int i=0;i<faces.size();i++) {
-
- Face3 f = faces.get(i);
- Plane p = f.get_plane();
- plane.normal+=p.normal;
- plane.d+=p.d;
-
- for(int i=0;i<3;i++) {
-
- Vector3 v = f.vertex[i].snapped(0.01);
- if (!points.has(v)) {
- points.insert(v);
- center+=v;
- }
- }
- }
-
- plane.normal.normalize();
- plane.d/=faces.size();
- center/=points.size();
-
- //step 2, create points
-
- Transform t;
- t.basis.from_z(plane.normal);
- t.basis.transpose();
- t.origin=center;
-
- Vector<Point2> portal_points;
-
- for(Set<Vector3>::Element *E=points.front();E;E=E->next()) {
-
- Vector3 local = t.xform_inv(E->get());
- portal_points.push_back(Point2(local.x,local.y));
- }
- // step 3 bubbly sort points
-
- int swaps=0;
-
- do {
- swaps=0;
-
- for(int i=0;i<portal_points.size()-1;i++) {
-
- float a = portal_points[i].angle();
- float b = portal_points[i+1].angle();
-
- if (a>b) {
- SWAP( portal_points[i], portal_points[i+1] );
- swaps++;
- }
-
- }
-
- } while(swaps);
-
-
- Portal *portal = memnew( Portal );
-
- portal->set_shape(portal_points);
- portal->set_transform( mi->get_transform() * t);
-
- p_node->replace_by(portal);
- memdelete(p_node);
- p_node=portal;
-
- } else if (p_node->cast_to<MeshInstance>()) {
-
- //last attempt, maybe collision insde the mesh data
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- Ref<Mesh> mesh = mi->get_mesh();
- if (!mesh.is_null()) {
-
- if (_teststr(mesh->get_name(),"col")) {
-
- mesh->set_name( _fixstr(mesh->get_name(),"col") );
- Ref<Shape> shape;
-
- if (collision_map.has(mesh)) {
- shape = collision_map[mesh];
-
- } else {
-
- shape = mesh->create_trimesh_shape();
- if (!shape.is_null())
- collision_map[mesh]=shape;
-
-
- }
-
- if (!shape.is_null()) {
-#if 0
- StaticBody* static_body = memnew( StaticBody );
- ERR_FAIL_COND_V(!static_body,NULL);
- static_body->set_name( String(mesh->get_name()) + "_col" );
- shape->set_name(static_body->get_name());
- static_body->add_shape(shape);
-
- mi->add_child(static_body);
- if (mi->get_owner())
- static_body->set_owner( mi->get_owner() );
-#endif
- }
-
- }
-
- for(int i=0;i<mesh->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = mesh->surface_get_material(i);
- if (fm.is_valid()) {
- String name = fm->get_name();
- /* if (_teststr(name,"alpha")) {
- fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- name=_fixstr(name,"alpha");
- }
-
- if (_teststr(name,"vcol")) {
- fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true);
- name=_fixstr(name,"vcol");
- }*/
- fm->set_name(name);
- }
- }
-
- }
-
- }
-
-
- return p_node;
-}
-
-
-void ResourceImporterScene::_create_clips(Node *scene, const Array& p_clips,bool p_bake_all) {
-
- if (!scene->has_node(String("AnimationPlayer")))
- return;
-
- Node* n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
- ERR_FAIL_COND(!anim);
-
- if (!anim->has_animation("default"))
- return;
-
-
- Ref<Animation> default_anim = anim->get_animation("default");
-
- for(int i=0;i<p_clips.size();i+=4) {
-
- String name = p_clips[i];
- float from=p_clips[i+1];
- float to=p_clips[i+2];
- bool loop=p_clips[i+3];
- if (from>=to)
- continue;
-
- Ref<Animation> new_anim = memnew( Animation );
-
- for(int j=0;j<default_anim->get_track_count();j++) {
-
-
- List<float> keys;
- int kc = default_anim->track_get_key_count(j);
- int dtrack=-1;
- for(int k=0;k<kc;k++) {
-
- float kt = default_anim->track_get_key_time(j,k);
- if (kt>=from && kt<to) {
-
- //found a key within range, so create track
- if (dtrack==-1) {
- new_anim->add_track(default_anim->track_get_type(j));
- dtrack = new_anim->get_track_count()-1;
- new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
-
- if (kt>(from+0.01) && k>0) {
-
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_interpolate(j,from,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,0,p,q,s);
- }
- }
-
- }
-
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_get_key(j,k,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,kt-from,p,q,s);
- }
-
- }
-
- if (dtrack!=-1 && kt>=to) {
-
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_interpolate(j,to,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
- }
- }
-
- }
-
- if (dtrack==-1 && p_bake_all) {
- new_anim->add_track(default_anim->track_get_type(j));
- dtrack = new_anim->get_track_count()-1;
- new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
-
-
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_interpolate(j,from,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,0,p,q,s);
- default_anim->transform_track_interpolate(j,to,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
- }
-
- }
- }
-
-
- new_anim->set_loop(loop);
- new_anim->set_length(to-from);
- anim->add_animation(name,new_anim);
- }
-
- anim->remove_animation("default"); //remove default (no longer needed)
-}
-
-void ResourceImporterScene::_filter_anim_tracks(Ref<Animation> anim,Set<String> &keep) {
-
- Ref<Animation> a = anim;
- ERR_FAIL_COND(!a.is_valid());
-
- print_line("From Anim "+anim->get_name()+":");
-
- for(int j=0;j<a->get_track_count();j++) {
-
- String path = a->track_get_path(j);
-
- if (!keep.has(path)) {
-
- print_line("Remove: "+path);
- a->remove_track(j);
- j--;
- }
-
- }
-}
-
-
-void ResourceImporterScene::_filter_tracks(Node *scene, const String& p_text) {
-
- if (!scene->has_node(String("AnimationPlayer")))
- return;
- Node* n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
- ERR_FAIL_COND(!anim);
-
- Vector<String> strings = p_text.split("\n");
- for(int i=0;i<strings.size();i++) {
-
- strings[i]=strings[i].strip_edges();
- }
-
- List<StringName> anim_names;
- anim->get_animation_list(&anim_names);
- for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
-
- String name = E->get();
- bool valid_for_this=false;
- bool valid=false;
-
- Set<String> keep;
- Set<String> keep_local;
-
-
- for(int i=0;i<strings.size();i++) {
-
-
- if (strings[i].begins_with("@")) {
-
- valid_for_this=false;
- for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
- keep.insert(F->get());
- }
- keep_local.clear();
-
- Vector<String> filters=strings[i].substr(1,strings[i].length()).split(",");
- for(int j=0;j<filters.size();j++) {
-
- String fname = filters[j].strip_edges();
- if (fname=="")
- continue;
- int fc = fname[0];
- bool plus;
- if (fc=='+')
- plus=true;
- else if (fc=='-')
- plus=false;
- else
- continue;
-
- String filter=fname.substr(1,fname.length()).strip_edges();
-
- if (!name.matchn(filter))
- continue;
- valid_for_this=plus;
- }
-
- if (valid_for_this)
- valid=true;
-
- } else if (valid_for_this) {
-
- Ref<Animation> a = anim->get_animation(name);
- if (!a.is_valid())
- continue;
-
- for(int j=0;j<a->get_track_count();j++) {
-
- String path = a->track_get_path(j);
-
- String tname = strings[i];
- if (tname=="")
- continue;
- int fc = tname[0];
- bool plus;
- if (fc=='+')
- plus=true;
- else if (fc=='-')
- plus=false;
- else
- continue;
-
- String filter=tname.substr(1,tname.length()).strip_edges();
-
- if (!path.matchn(filter))
- continue;
-
- if (plus)
- keep_local.insert(path);
- else if (!keep.has(path)) {
- keep_local.erase(path);
- }
- }
-
- }
-
- }
-
- if (valid) {
- for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
- keep.insert(F->get());
- }
- _filter_anim_tracks(anim->get_animation(name),keep);
- } else {
-
- }
-
- }
-
-
-
-}
-
-void ResourceImporterScene::_optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle) {
-
- if (!scene->has_node(String("AnimationPlayer")))
- return;
- Node* n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
- ERR_FAIL_COND(!anim);
-
-
- List<StringName> anim_names;
- anim->get_animation_list(&anim_names);
- for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
-
- Ref<Animation> a = anim->get_animation(E->get());
- a->optimize(p_max_lin_error,p_max_ang_error,Math::deg2rad(p_max_angle));
- }
-}
-
-
-static String _make_extname(const String& p_str) {
-
- String ext_name=p_str.replace(".","_");
- ext_name=ext_name.replace(":","_");
- ext_name=ext_name.replace("\"","_");
- ext_name=ext_name.replace("<","_");
- ext_name=ext_name.replace(">","_");
- ext_name=ext_name.replace("/","_");
- ext_name=ext_name.replace("|","_");
- ext_name=ext_name.replace("\\","_");
- ext_name=ext_name.replace("?","_");
- ext_name=ext_name.replace("*","_");
-
- return ext_name;
-}
-
-void ResourceImporterScene::_make_external_resources(Node* p_node,const String& p_base_path, bool p_make_materials, bool p_make_meshes, Map<Ref<Material>,Ref<Material> >& p_materials, Map<Ref<Mesh>,Ref<Mesh> >& p_meshes) {
-
- List<PropertyInfo> pi;
-
- p_node->get_property_list(&pi);
-
- for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
-
- if (E->get().type==Variant::OBJECT) {
-
- Ref<Material> mat = p_node->get(E->get().name);
- if (p_make_materials && mat.is_valid() && mat->get_name()!="") {
-
-
- if (!p_materials.has(mat)) {
-
- String ext_name = p_base_path+"."+_make_extname(mat->get_name())+".mtl";
- if (FileAccess::exists(ext_name)) {
- //if exists, use it
- Ref<Material> existing = ResourceLoader::load(ext_name);
- p_materials[mat]=existing;
- } else {
-
- ResourceSaver::save(ext_name,mat,ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat]=mat;
- }
- }
-
- if (p_materials[mat]!=mat) {
-
- p_node->set(E->get().name,p_materials[mat]);
- }
- } else {
-
- Ref<Mesh> mesh = p_node->get(E->get().name);
-
- if (mesh.is_valid()) {
-
- bool mesh_just_added=false;
-
- if (p_make_meshes) {
-
- if (!p_meshes.has(mesh)) {
-
- String ext_name = p_base_path+"."+_make_extname(mesh->get_name())+".msh";
- if (FileAccess::exists(ext_name)) {
- //if exists, use it
- Ref<Mesh> existing = ResourceLoader::load(ext_name);
- p_meshes[mesh]=existing;
- } else {
-
- ResourceSaver::save(ext_name,mesh,ResourceSaver::FLAG_CHANGE_PATH);
- p_meshes[mesh]=mesh;
- mesh_just_added=true;
- }
-
-
- }
- }
-
-
- if (p_make_materials){
-
- if (mesh_just_added || !p_meshes.has(mesh)) {
-
-
- for(int i=0;i<mesh->get_surface_count();i++) {
- mat=mesh->surface_get_material(i);
- if (!mat.is_valid() || mat->get_name()=="")
- continue;
-
- if (!p_materials.has(mat)) {
-
- String ext_name = p_base_path+"."+_make_extname(mat->get_name())+".mtl";
- if (FileAccess::exists(ext_name)) {
- //if exists, use it
- Ref<Material> existing = ResourceLoader::load(ext_name);
- p_materials[mat]=existing;
- } else {
-
- ResourceSaver::save(ext_name,mat,ResourceSaver::FLAG_CHANGE_PATH);
- p_materials[mat]=mat;
- }
- }
-
- if (p_materials[mat]!=mat) {
-
- mesh->surface_set_material(i,p_materials[mat]);
- }
-
- }
-
- if(!p_make_meshes) {
- p_meshes[mesh]=Ref<Mesh>(); //save it anyway, so it won't be checked again
- }
- }
- }
- }
- }
- }
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- _make_external_resources(p_node->get_child(i),p_base_path,p_make_materials,p_make_meshes,p_materials,p_meshes);
- }
-}
-
-
-void ResourceImporterScene::get_import_options(List<ImportOption> *r_options,int p_preset) const {
-
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"nodes/root_type",PROPERTY_HINT_TYPE_STRING,"Node"),"Spatial"));
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"nodes/root_name"),"Scene Root"));
-
- List<String> script_extentions;
- ResourceLoader::get_recognized_extensions_for_type("Script",&script_extentions);
-
- String script_ext_hint;
-
- for(List<String>::Element *E=script_extentions.front();E;E=E->next()) {
- if (script_ext_hint!="")
- script_ext_hint+=",";
- script_ext_hint+="*."+E->get();
- }
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"nodes/custom_script",PROPERTY_HINT_FILE,script_ext_hint),""));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"materials/location",PROPERTY_HINT_ENUM,"Node,Mesh"),0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"materials/storage",PROPERTY_HINT_ENUM,"Bult-In,Files"),0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"geometry/compress"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"geometry/ensure_tangents"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"geometry/storage",PROPERTY_HINT_ENUM,"Built-In,Files"),0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/import",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/fps",PROPERTY_HINT_RANGE,"1,120,1"),15));
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"animation/filter_script",PROPERTY_HINT_MULTILINE_TEXT),""));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/optimizer/enabled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/optimizer/max_linear_error"),0.05));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/optimizer/max_angular_error"),0.01));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"animation/optimizer/max_angle"),22));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/optimizer/remove_unused_tracks"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"animation/clips/amount",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),0));
- for(int i=0;i<256;i++) {
- r_options->push_back(ImportOption(PropertyInfo(Variant::STRING,"animation/clip_"+itos(i+1)+"/name"),""));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"animation/clip_"+itos(i+1)+"/start_frame"),0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"animation/clip_"+itos(i+1)+"/end_frame"),0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"animation/clip_"+itos(i+1)+"/loops"),false));
- }
-}
-
-Error ResourceImporterScene::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
-
- String src_path=p_source_file;
-
- Ref<EditorSceneImporter> importer;
- String ext=src_path.get_extension().to_lower();
-
-
- EditorProgress progress("import",TTR("Import Scene"),104);
- progress.step(TTR("Importing Scene.."),0);
-
- for(Set< Ref<EditorSceneImporter> >::Element *E=importers.front();E;E=E->next()) {
-
- List<String> extensions;
- E->get()->get_extensions(&extensions);
-
- for(List<String>::Element *F=extensions.front();F;F=F->next()) {
-
- if (F->get().to_lower()==ext) {
-
- importer = E->get();
- break;
- }
- }
-
- if (importer.is_valid())
- break;
- }
-
- ERR_FAIL_COND_V(!importer.is_valid(),ERR_FILE_UNRECOGNIZED);
-
- float fps=p_options["animation/fps"];
-
-
-
- int import_flags=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
- if (!bool(p_options["animation/optimizer/remove_unused_tracks"]))
- import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS;
-
- if (bool(p_options["animation/import"]))
- import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
-
- if (bool(p_options["geometry/ensure_tangents"]))
- import_flags|=EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
-
- if (int(p_options["materials/location"])==0)
- import_flags|=EditorSceneImporter::IMPORT_MATERIALS_IN_INSTANCES;
-
-
- Error err=OK;
- List<String> missing_deps; // for now, not much will be done with this
- Node *scene = importer->import_scene(src_path,import_flags,fps,&missing_deps,&err);
- if (!scene || err!=OK) {
- return err;
- }
-
- String root_type = p_options["nodes/root_type"];
-
- if (scene->get_class()!=root_type) {
- Object *base = ClassDB::instance(root_type);
- Node *base_node = NULL;
- if (base)
- base_node=base->cast_to<Node>();
-
- if (base_node) {
-
- scene->replace_by(base_node);
- memdelete(scene);
- scene=base_node;
- }
- }
-
- scene->set_name(p_options["nodes/root_name"]);
-
-
- err=OK;
-
- String animation_filter = String(p_options["animation/filter_script"]).strip_edges();
-
- bool use_optimizer = p_options["animation/optimizer/enabled"];
- float anim_optimizer_linerr=p_options["animation/optimizer/max_linear_error"];
- float anim_optimizer_angerr=p_options["animation/optimizer/max_angular_error"];
- float anim_optimizer_maxang=p_options["animation/optimizer/max_angle"];
-
- Map<Ref<Mesh>,Ref<Shape> > collision_map;
-
- scene=_fix_node(scene,scene,collision_map);
-
- if (use_optimizer) {
- _optimize_animations(scene,anim_optimizer_linerr,anim_optimizer_angerr,anim_optimizer_maxang);
- }
-
- Array animation_clips;
- {
-
-
- int clip_count = p_options["animation/clips/amount"];
-
- for(int i=0;i<clip_count;i++) {
- String name = p_options["animation/clip_"+itos(i+1)+"/name"];
- int from_frame = p_options["animation/clip_"+itos(i+1)+"/start_frame"];
- int end_frame = p_options["animation/clip_"+itos(i+1)+"/end_frame"];
- bool loop = p_options["animation/clip_"+itos(i+1)+"/loops"];
-
- animation_clips.push_back(name);
- animation_clips.push_back(from_frame/fps);
- animation_clips.push_back(end_frame/fps);
- animation_clips.push_back(loop);
- }
-
- }
- if (animation_clips.size()) {
- _create_clips(scene,animation_clips,!bool(p_options["animation/optimizer/remove_unused_tracks"]));
- }
-
- if (animation_filter!="") {
- _filter_tracks(scene,animation_filter);
- }
-
-
- bool external_materials = p_options["materials/storage"];
- bool external_meshes = p_options["geometry/storage"];
-
- if (external_materials || external_meshes) {
- Map<Ref<Material>, Ref<Material> > mat_map;
- Map<Ref<Mesh>, Ref<Mesh> > mesh_map;
- _make_external_resources(scene,p_source_file.get_basename(),external_materials,external_meshes,mat_map,mesh_map);
- }
-
- progress.step(TTR("Running Custom Script.."),2);
-
- String post_import_script_path = p_options["nodes/custom_script"];
- Ref<EditorScenePostImport> post_import_script;
-
- if (post_import_script_path!="") {
- post_import_script_path = post_import_script_path;
- Ref<Script> scr = ResourceLoader::load(post_import_script_path);
- if (!scr.is_valid()) {
- EditorNode::add_io_error(TTR("Couldn't load post-import script:")+" "+post_import_script_path);
- } else {
-
- post_import_script = Ref<EditorScenePostImport>( memnew( EditorScenePostImport ) );
- post_import_script->set_script(scr.get_ref_ptr());
- if (!post_import_script->get_script_instance()) {
- EditorNode::add_io_error(TTR("Invalid/broken script for post-import (check console):")+" "+post_import_script_path);
- post_import_script.unref();
- return ERR_CANT_CREATE;
- }
- }
- }
-
-
- if (post_import_script.is_valid()) {
- scene = post_import_script->post_import(scene);
- if (!scene) {
- EditorNode::add_io_error(TTR("Error running post-import script:")+" "+post_import_script_path);
- return err;
- }
-
-
- }
-
- progress.step(TTR("Saving.."),104);
-
- Ref<PackedScene> packer = memnew( PackedScene );
- packer->pack(scene);
- print_line("SAVING TO: "+p_save_path+".scn");
- err = ResourceSaver::save(p_save_path+".scn",packer); //do not take over, let the changed files reload themselves
-
- memdelete(scene);
-
- EditorNode::get_singleton()->reload_scene(p_source_file);
-
- return OK;
-}
-
-ResourceImporterScene *ResourceImporterScene::singleton=NULL;
-
-ResourceImporterScene::ResourceImporterScene()
-{
- singleton=this;
-}
diff --git a/tools/editor/import/resource_importer_scene.h b/tools/editor/import/resource_importer_scene.h
deleted file mode 100644
index cfa44b160a..0000000000
--- a/tools/editor/import/resource_importer_scene.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef RESOURCEIMPORTERSCENE_H
-#define RESOURCEIMPORTERSCENE_H
-
-#include "io/resource_import.h"
-#include "scene/resources/animation.h"
-#include "scene/resources/shape.h"
-
-class Material;
-
-class EditorSceneImporter : public Reference {
-
- GDCLASS(EditorSceneImporter,Reference );
-public:
-
- enum ImportFlags {
- IMPORT_SCENE=1,
- IMPORT_ANIMATION=2,
- IMPORT_ANIMATION_DETECT_LOOP=4,
- IMPORT_ANIMATION_OPTIMIZE=8,
- IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=16,
- IMPORT_ANIMATION_KEEP_VALUE_TRACKS=32,
- IMPORT_GENERATE_TANGENT_ARRAYS=256,
- IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512,
- IMPORT_MATERIALS_IN_INSTANCES=1024
-
- };
-
- virtual uint32_t get_import_flags() const=0;
- virtual void get_extensions(List<String> *r_extensions) const=0;
- virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps,Error* r_err=NULL)=0;
- virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0;
-
-
-
- EditorSceneImporter() {}
-};
-
-class EditorScenePostImport : public Reference {
-
- GDCLASS(EditorScenePostImport,Reference );
-protected:
-
- static void _bind_methods();
-public:
-
- virtual Node* post_import(Node* p_scene);
- EditorScenePostImport();
-};
-
-
-class ResourceImporterScene : public ResourceImporter {
- GDCLASS(ResourceImporterScene,ResourceImporter)
-
- Set< Ref<EditorSceneImporter> > importers;
-
- static ResourceImporterScene *singleton;
-public:
-
- static ResourceImporterScene *get_singleton() { return singleton; }
-
- const Set< Ref<EditorSceneImporter> >& get_importers() const { return importers; }
-
- void add_importer(Ref<EditorSceneImporter> p_importer) { importers.insert(p_importer); }
-
- virtual String get_importer_name() const;
- virtual String get_visible_name() const;
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual String get_save_extension() const;
- virtual String get_resource_type() const;
-
-
- virtual int get_preset_count() const;
- virtual String get_preset_name(int p_idx) const;
-
- virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
- virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
-
- void _make_external_resources(Node* p_node,const String& p_base_path, bool p_make_materials, bool p_make_meshes, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<Mesh>, Ref<Mesh> > &p_meshes);
-
- Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map);
-
- void _create_clips(Node *scene, const Array& p_clips,bool p_bake_all);
- void _filter_anim_tracks(Ref<Animation> anim,Set<String> &keep);
- void _filter_tracks(Node *scene, const String& p_text);
- void _optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle);
-
- virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
-
- ResourceImporterScene();
-};
-
-
-#endif // RESOURCEIMPORTERSCENE_H
diff --git a/tools/editor/import/resource_importer_texture.cpp b/tools/editor/import/resource_importer_texture.cpp
deleted file mode 100644
index 21e434fa11..0000000000
--- a/tools/editor/import/resource_importer_texture.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
-#include "resource_importer_texture.h"
-#include "io/image_loader.h"
-#include "scene/resources/texture.h"
-#include "tools/editor/editor_file_system.h"
-#include "io/config_file.h"
-
-
-void ResourceImporterTexture::_texture_reimport_srgb(const Ref<StreamTexture>& p_tex) {
-
- singleton->mutex->lock();
- StringName path = p_tex->get_path();
-
- if (!singleton->make_flags.has(path)) {
- singleton->make_flags[path]=0;
- }
-
- singleton->make_flags[path]|=MAKE_SRGB_FLAG;
-
- print_line("requesting srgb for "+String(path));
-
- singleton->mutex->unlock();
-
-}
-
-
-
-void ResourceImporterTexture::_texture_reimport_3d(const Ref<StreamTexture>& p_tex) {
-
-
- singleton->mutex->lock();
- StringName path = p_tex->get_path();
-
- if (!singleton->make_flags.has(path)) {
- singleton->make_flags[path]=0;
- }
-
- singleton->make_flags[path]|=MAKE_3D_FLAG;
-
- print_line("requesting 3d for "+String(path));
-
- singleton->mutex->unlock();
-
-
-}
-
-void ResourceImporterTexture::update_imports() {
-
- if (EditorFileSystem::get_singleton()->is_scanning() || EditorFileSystem::get_singleton()->is_importing()) {
- return; // do nothing for noe
- }
- mutex->lock();
-
- if (make_flags.empty()) {
- mutex->unlock();
- return;
- }
-
- Vector<String> to_reimport;
- for (Map<StringName,int>::Element *E=make_flags.front();E;E=E->next()) {
-
- print_line("checking for reimport "+String(E->key()));
-
-
- Ref<ConfigFile> cf;
- cf.instance();
- String src_path = String(E->key())+".import";
-
- Error err = cf->load(src_path);
- ERR_CONTINUE(err!=OK);
-
- bool changed=false;
- if (E->get()&MAKE_SRGB_FLAG && int(cf->get_value("params","flags/srgb"))==2) {
- cf->set_value("params","flags/srgb",1);
- changed=true;
- }
-
- if (E->get()&MAKE_3D_FLAG && bool(cf->get_value("params","detect_3d"))) {
- cf->set_value("params","detect_3d",false);
- cf->set_value("params","compress/mode",2);
- cf->set_value("params","flags/repeat",true);
- cf->set_value("params","flags/filter",true);
- cf->set_value("params","flags/mipmaps",true);
- changed=true;
- }
-
- if (changed) {
- cf->save(src_path);
- to_reimport.push_back(E->key());
- }
-
- }
-
- make_flags.clear();
-
- mutex->unlock();
-
- if (to_reimport.size()) {
- EditorFileSystem::get_singleton()->reimport_files(to_reimport);
- }
-
-}
-
-
-
-String ResourceImporterTexture::get_importer_name() const {
-
- return "texture";
-}
-
-String ResourceImporterTexture::get_visible_name() const{
-
- return "Texture";
-}
-void ResourceImporterTexture::get_recognized_extensions(List<String> *p_extensions) const{
-
- ImageLoader::get_recognized_extensions(p_extensions);
-}
-String ResourceImporterTexture::get_save_extension() const {
- return "stex";
-}
-
-String ResourceImporterTexture::get_resource_type() const{
-
- return "StreamTexture";
-}
-
-bool ResourceImporterTexture::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
-
- if (p_option=="compress/lossy_quality" && int(p_options["compress/mode"])!=COMPRESS_LOSSY)
- return false;
-
- return true;
-}
-
-int ResourceImporterTexture::get_preset_count() const {
- return 4;
-}
-String ResourceImporterTexture::get_preset_name(int p_idx) const {
-
- static const char* preset_names[]={
- "2D, Detect 3D",
- "2D",
- "2D Pixel",
- "3D"
- };
-
- return preset_names[p_idx];
-}
-
-
-void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,int p_preset) const {
-
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Lossless,Lossy,Video RAM,Uncompressed",PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED),p_preset==PRESET_3D?2:0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"compress/lossy_quality",PROPERTY_HINT_RANGE,"0,1,0.01"),0.7));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/repeat",PROPERTY_HINT_ENUM,"Disabled,Enabled,Mirrored"),p_preset==PRESET_3D?1:0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/filter"),p_preset==PRESET_2D_PIXEL?false:true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/mipmaps"),p_preset==PRESET_3D?true:false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"flags/anisotropic"),false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"flags/srgb",PROPERTY_HINT_ENUM,"Disable,Enable,Detect"),2));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/fix_alpha_border"),p_preset!=PRESET_3D?true:false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"process/premult_alpha"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"stream"),false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"size_limit",PROPERTY_HINT_RANGE,"0,4096,1"),0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"detect_3d"),p_preset==PRESET_DETECT));
-
-}
-
-
-void ResourceImporterTexture::_save_stex(const Image& p_image, const String& p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable, bool p_detect_3d, bool p_detect_srgb) {
-
-
- FileAccess *f = FileAccess::open(p_to_path,FileAccess::WRITE);
- f->store_8('G');
- f->store_8('D');
- f->store_8('S');
- f->store_8('T'); //godot streamable texture
-
- f->store_32(p_image.get_width());
- f->store_32(p_image.get_height());
- f->store_32(p_texture_flags);
-
- uint32_t format=0;
-
- if (p_streamable)
- format|=StreamTexture::FORMAT_BIT_STREAM;
- if (p_mipmaps || p_compress_mode==COMPRESS_VIDEO_RAM) //VRAM always uses mipmaps
- format|=StreamTexture::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit
- if (p_detect_3d)
- format|=StreamTexture::FORMAT_BIT_DETECT_3D;
- if (p_detect_srgb)
- format|=StreamTexture::FORMAT_BIT_DETECT_SRGB;
-
-
- switch (p_compress_mode) {
- case COMPRESS_LOSSLESS: {
-
- Image image = p_image;
- if (p_mipmaps) {
- image.generate_mipmaps();
- } else {
- image.clear_mipmaps();
- }
-
- int mmc = image.get_mipmap_count() + 1;
-
- format|=StreamTexture::FORMAT_BIT_LOSSLESS;
- f->store_32(format);
- f->store_32(mmc);
-
- for(int i=0;i<mmc;i++) {
-
- if (i>0) {
- image.shrink_x2();
- }
-
- PoolVector<uint8_t> data = Image::lossless_packer(image);
- int data_len = data.size();
- f->store_32(data_len);
-
- PoolVector<uint8_t>::Read r= data.read();
- f->store_buffer(r.ptr(),data_len);
-
- }
-
-
- } break;
- case COMPRESS_LOSSY: {
- Image image = p_image;
- if (p_mipmaps) {
- image.generate_mipmaps();
- } else {
- image.clear_mipmaps();
- }
-
- int mmc = image.get_mipmap_count() + 1;
-
- format|=StreamTexture::FORMAT_BIT_LOSSY;
- f->store_32(format);
- f->store_32(mmc);
-
- for(int i=0;i<mmc;i++) {
-
- if (i>0) {
- image.shrink_x2();
- }
-
- PoolVector<uint8_t> data = Image::lossy_packer(image,p_lossy_quality);
- int data_len = data.size();
- f->store_32(data_len);
-
- PoolVector<uint8_t>::Read r = data.read();
- f->store_buffer(r.ptr(),data_len);
-
- }
- } break;
- case COMPRESS_VIDEO_RAM: {
-
- Image image = p_image;
- image.generate_mipmaps();
- image.compress(p_vram_compression);
-
- format |= image.get_format();
-
- f->store_32(format);
-
- PoolVector<uint8_t> data=image.get_data();
- int dl = data.size();
- PoolVector<uint8_t>::Read r = data.read();
- f->store_buffer(r.ptr(),dl);
-
- } break;
- case COMPRESS_UNCOMPRESSED: {
-
- Image image = p_image;
- if (p_mipmaps) {
- image.generate_mipmaps();
- } else {
- image.clear_mipmaps();
- }
-
- format |= image.get_format();
- f->store_32(format);
-
- PoolVector<uint8_t> data=image.get_data();
- int dl = data.size();
- PoolVector<uint8_t>::Read r = data.read();
-
- f->store_buffer(r.ptr(),dl);
-
- } break;
- }
-
- memdelete(f);
-}
-
-Error ResourceImporterTexture::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
-
- int compress_mode = p_options["compress/mode"];
- float lossy= p_options["compress/lossy_quality"];
- int repeat= p_options["flags/repeat"];
- bool filter= p_options["flags/filter"];
- bool mipmaps= p_options["flags/mipmaps"];
- bool anisotropic= p_options["flags/anisotropic"];
- int srgb= p_options["flags/srgb"];
- bool fix_alpha_border= p_options["process/fix_alpha_border"];
- bool premult_alpha= p_options["process/premult_alpha"];
- bool stream = p_options["stream"];
- int size_limit = p_options["size_limit"];
-
-
- Image image;
- Error err = ImageLoader::load_image(p_source_file,&image);
- if (err!=OK)
- return err;
-
-
- int tex_flags=0;
- if (repeat>0)
- tex_flags|=Texture::FLAG_REPEAT;
- if (repeat==2)
- tex_flags|=Texture::FLAG_MIRRORED_REPEAT;
- if (filter)
- tex_flags|=Texture::FLAG_FILTER;
- if (mipmaps || compress_mode==COMPRESS_VIDEO_RAM)
- tex_flags|=Texture::FLAG_MIPMAPS;
- if (anisotropic)
- tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER;
- if (srgb==1)
- tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR;
-
- if (size_limit >0 && (image.get_width()>size_limit || image.get_height()>size_limit )) {
- //limit size
- if (image.get_width() >= image.get_height()) {
- int new_width = size_limit;
- int new_height = image.get_height() * new_width / image.get_width();
-
- image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC);
- } else {
-
- int new_height = size_limit;
- int new_width = image.get_width() * new_height / image.get_height();
-
- image.resize(new_width,new_height,Image::INTERPOLATE_CUBIC);
- }
- }
-
- if (fix_alpha_border) {
- image.fix_alpha_edges();
- }
-
- if (premult_alpha) {
- image.premultiply_alpha();
- }
-
- bool detect_3d = p_options["detect_3d"];
- bool detect_srgb = srgb==2;
-
- if (compress_mode==COMPRESS_VIDEO_RAM) {
- //must import in all formats
- //Android, GLES 2.x
- _save_stex(image,p_save_path+".etc.stex",compress_mode,lossy,Image::COMPRESS_ETC,mipmaps,tex_flags,stream,detect_3d,detect_srgb);
- r_platform_variants->push_back("etc");
- //_save_stex(image,p_save_path+".etc2.stex",compress_mode,lossy,Image::COMPRESS_ETC2,mipmaps,tex_flags,stream);
- //r_platform_variants->push_back("etc2");
- _save_stex(image,p_save_path+".s3tc.stex",compress_mode,lossy,Image::COMPRESS_S3TC,mipmaps,tex_flags,stream,detect_3d,detect_srgb);
- r_platform_variants->push_back("s3tc");
-
- } else {
- //import normally
- _save_stex(image,p_save_path+".stex",compress_mode,lossy,Image::COMPRESS_16BIT /*this is ignored */,mipmaps,tex_flags,stream,detect_3d,detect_srgb);
- }
-
- return OK;
-}
-
-ResourceImporterTexture *ResourceImporterTexture::singleton=NULL;
-
-ResourceImporterTexture::ResourceImporterTexture()
-{
-
- singleton=this;
- StreamTexture::request_3d_callback=_texture_reimport_3d;
- StreamTexture::request_srgb_callback=_texture_reimport_srgb;
- mutex = Mutex::create();
-}
-
-ResourceImporterTexture::~ResourceImporterTexture()
-{
-
- memdelete(mutex);
-}
-
diff --git a/tools/editor/import/resource_importer_texture.h b/tools/editor/import/resource_importer_texture.h
deleted file mode 100644
index 4c795e132c..0000000000
--- a/tools/editor/import/resource_importer_texture.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef RESOURCEIMPORTTEXTURE_H
-#define RESOURCEIMPORTTEXTURE_H
-
-#include "io/resource_import.h"
-class StreamTexture;
-
-class ResourceImporterTexture : public ResourceImporter {
- GDCLASS(ResourceImporterTexture,ResourceImporter)
-
-
-
-protected:
-
- enum {
- MAKE_3D_FLAG=1,
- MAKE_SRGB_FLAG=2
- };
-
- Mutex *mutex;
- Map<StringName,int> make_flags;
-
- static void _texture_reimport_srgb(const Ref<StreamTexture>& p_tex);
- static void _texture_reimport_3d(const Ref<StreamTexture>& p_tex);
-
-
-
-
- static ResourceImporterTexture *singleton;
-public:
-
- static ResourceImporterTexture *get_singleton() { return singleton; }
- virtual String get_importer_name() const;
- virtual String get_visible_name() const;
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual String get_save_extension() const;
- virtual String get_resource_type() const;
-
-
- enum Preset {
- PRESET_DETECT,
- PRESET_2D,
- PRESET_2D_PIXEL,
- PRESET_3D,
- };
-
- enum CompressMode {
- COMPRESS_LOSSLESS,
- COMPRESS_LOSSY,
- COMPRESS_VIDEO_RAM,
- COMPRESS_UNCOMPRESSED
- };
-
- virtual int get_preset_count() const;
- virtual String get_preset_name(int p_idx) const;
-
- virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
- virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
-
- void _save_stex(const Image& p_image, const String& p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable,bool p_detect_3d,bool p_detect_srgb);
-
- virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
-
-
- void update_imports();
-
- ResourceImporterTexture();
- ~ResourceImporterTexture();
-};
-
-#endif // RESOURCEIMPORTTEXTURE_H
diff --git a/tools/editor/import/resource_importer_wav.cpp b/tools/editor/import/resource_importer_wav.cpp
deleted file mode 100644
index ee53b740ca..0000000000
--- a/tools/editor/import/resource_importer_wav.cpp
+++ /dev/null
@@ -1,619 +0,0 @@
-#include "resource_importer_wav.h"
-
-#include "scene/resources/audio_stream_sample.h"
-#include "os/file_access.h"
-#include "io/marshalls.h"
-#include "io/resource_saver.h"
-
-String ResourceImporterWAV::get_importer_name() const {
-
- return "wav";
-}
-
-String ResourceImporterWAV::get_visible_name() const{
-
- return "Microsoft WAV";
-}
-void ResourceImporterWAV::get_recognized_extensions(List<String> *p_extensions) const{
-
- p_extensions->push_back("wav");
-}
-String ResourceImporterWAV::get_save_extension() const {
- return "smp";
-}
-
-String ResourceImporterWAV::get_resource_type() const{
-
- return "AudioStreamSample";
-}
-
-bool ResourceImporterWAV::get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const {
-
- return true;
-}
-
-int ResourceImporterWAV::get_preset_count() const {
- return 0;
-}
-String ResourceImporterWAV::get_preset_name(int p_idx) const {
-
- return String();
-}
-
-
-void ResourceImporterWAV::get_import_options(List<ImportOption> *r_options,int p_preset) const {
-
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/8_bit"),false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/mono"),false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"force/max_rate"),false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::REAL,"force/max_rate_hz",PROPERTY_HINT_EXP_RANGE,"11025,192000,1"),44100));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/trim"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/normalize"),true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL,"edit/loop"),false));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)"),0));
-
-}
-
-
-Error ResourceImporterWAV::import(const String& p_source_file, const String& p_save_path, const Map<StringName,Variant>& p_options, List<String>* r_platform_variants, List<String> *r_gen_files) {
-
- /* STEP 1, READ WAVE FILE */
-
- Error err;
- FileAccess *file=FileAccess::open(p_source_file, FileAccess::READ,&err);
-
- ERR_FAIL_COND_V( err!=OK, ERR_CANT_OPEN );
-
- /* CHECK RIFF */
- char riff[5];
- riff[4]=0;
- file->get_buffer((uint8_t*)&riff,4); //RIFF
-
- if (riff[0]!='R' || riff[1]!='I' || riff[2]!='F' || riff[3]!='F') {
-
- file->close();
- memdelete(file);
- ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
- }
-
-
- /* GET FILESIZE */
- uint32_t filesize=file->get_32();
-
- /* CHECK WAVE */
-
- char wave[4];
-
- file->get_buffer((uint8_t*)&wave,4); //RIFF
-
- if (wave[0]!='W' || wave[1]!='A' || wave[2]!='V' || wave[3]!='E') {
-
-
- file->close();
- memdelete(file);
- ERR_EXPLAIN("Not a WAV file (no WAVE RIFF Header)")
- ERR_FAIL_V( ERR_FILE_UNRECOGNIZED );
- }
-
- int format_bits=0;
- int format_channels=0;
-
- AudioStreamSample::LoopMode loop=AudioStreamSample::LOOP_DISABLED;
- bool format_found=false;
- bool data_found=false;
- int format_freq=0;
- int loop_begin=0;
- int loop_end=0;
- int frames;
-
- Vector<float> data;
-
- while (!file->eof_reached()) {
-
-
- /* chunk */
- char chunkID[4];
- file->get_buffer((uint8_t*)&chunkID,4); //RIFF
-
- /* chunk size */
- uint32_t chunksize=file->get_32();
- uint32_t file_pos=file->get_pos(); //save file pos, so we can skip to next chunk safely
-
- if (file->eof_reached()) {
-
- //ERR_PRINT("EOF REACH");
- break;
- }
-
- if (chunkID[0]=='f' && chunkID[1]=='m' && chunkID[2]=='t' && chunkID[3]==' ' && !format_found) {
- /* IS FORMAT CHUNK */
-
- uint16_t compression_code=file->get_16();
-
-
- if (compression_code!=1) {
- ERR_PRINT("Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM instead.");
- break;
- }
-
- format_channels=file->get_16();
- if (format_channels!=1 && format_channels !=2) {
-
- ERR_PRINT("Format not supported for WAVE file (not stereo or mono)");
- break;
-
- }
-
- format_freq=file->get_32(); //sampling rate
-
- file->get_32(); // average bits/second (unused)
- file->get_16(); // block align (unused)
- format_bits=file->get_16(); // bits per sample
-
- if (format_bits%8) {
-
- ERR_PRINT("Strange number of bits in sample (not 8,16,24,32)");
- break;
- }
-
- /* Dont need anything else, continue */
- format_found=true;
- }
-
-
- if (chunkID[0]=='d' && chunkID[1]=='a' && chunkID[2]=='t' && chunkID[3]=='a' && !data_found) {
- /* IS FORMAT CHUNK */
- data_found=true;
-
- if (!format_found) {
- ERR_PRINT("'data' chunk before 'format' chunk found.");
- break;
-
- }
-
- frames=chunksize;
-
- frames/=format_channels;
- frames/=(format_bits>>3);
-
- /*print_line("chunksize: "+itos(chunksize));
- print_line("channels: "+itos(format_channels));
- print_line("bits: "+itos(format_bits));
-*/
-
- int len=frames;
- if (format_channels==2)
- len*=2;
- if (format_bits>8)
- len*=2;
-
-
- data.resize(frames*format_channels);
-
- for (int i=0;i<frames;i++) {
-
-
- for (int c=0;c<format_channels;c++) {
-
-
- if (format_bits==8) {
- // 8 bit samples are UNSIGNED
-
- uint8_t s = file->get_8();
- s-=128;
- int8_t *sp=(int8_t*)&s;
-
- data[i*format_channels+c]=float(*sp)/128.0;
-
- } else {
- //16+ bits samples are SIGNED
- // if sample is > 16 bits, just read extra bytes
-
- uint32_t s=0;
- for (int b=0;b<(format_bits>>3);b++) {
-
- s|=((uint32_t)file->get_8())<<(b*8);
- }
- s<<=(32-format_bits);
- int32_t ss=s;
-
-
- data[i*format_channels+c]=(ss>>16)/32768.0;
- }
- }
-
- }
-
-
-
- if (file->eof_reached()) {
- file->close();
- memdelete(file);
- ERR_EXPLAIN("Premature end of file.");
- ERR_FAIL_V(ERR_FILE_CORRUPT);
- }
- }
-
- if (chunkID[0]=='s' && chunkID[1]=='m' && chunkID[2]=='p' && chunkID[3]=='l') {
- //loop point info!
-
- for(int i=0;i<10;i++)
- file->get_32(); // i wish to know why should i do this... no doc!
-
- loop=file->get_32()?AudioStreamSample::LOOP_PING_PONG:AudioStreamSample::LOOP_FORWARD;
- loop_begin=file->get_32();
- loop_end=file->get_32();
-
- }
- file->seek( file_pos+chunksize );
- }
-
- file->close();
- memdelete(file);
-
- // STEP 2, APPLY CONVERSIONS
-
-
- bool is16=format_bits!=8;
- int rate=format_freq;
-
- print_line("Input Sample: ");
- print_line("\tframes: "+itos(frames));
- print_line("\tformat_channels: "+itos(format_channels));
- print_line("\t16bits: "+itos(is16));
- print_line("\trate: "+itos(rate));
- print_line("\tloop: "+itos(loop));
- print_line("\tloop begin: "+itos(loop_begin));
- print_line("\tloop end: "+itos(loop_end));
-
-
- //apply frequency limit
-
- bool limit_rate = p_options["force/max_rate"];
- int limit_rate_hz = p_options["force/max_rate_hz"];
- if (limit_rate && rate > limit_rate_hz) {
- //resampleeee!!!
- int new_data_frames = frames * limit_rate_hz / rate;
- Vector<float> new_data;
- new_data.resize( new_data_frames * format_channels );
- for(int c=0;c<format_channels;c++) {
-
- for(int i=0;i<new_data_frames;i++) {
-
- //simple cubic interpolation should be enough.
- float pos = float(i) * frames / new_data_frames;
- float mu = pos-Math::floor(pos);
- int ipos = int(Math::floor(pos));
-
- float y0=data[MAX(0,ipos-1)*format_channels+c];
- float y1=data[ipos*format_channels+c];
- float y2=data[MIN(frames-1,ipos+1)*format_channels+c];
- float y3=data[MIN(frames-1,ipos+2)*format_channels+c];
-
- float mu2 = mu*mu;
- float a0 = y3 - y2 - y0 + y1;
- float a1 = y0 - y1 - a0;
- float a2 = y2 - y0;
- float a3 = y1;
-
- float res=(a0*mu*mu2+a1*mu2+a2*mu+a3);
-
- new_data[i*format_channels+c]=res;
- }
- }
-
- if (loop) {
-
- loop_begin=loop_begin*new_data_frames/frames;
- loop_end=loop_end*new_data_frames/frames;
- }
- data=new_data;
- rate=limit_rate_hz;
- frames=new_data_frames;
- }
-
-
- bool normalize = p_options["edit/normalize"];
-
- if (normalize) {
-
- float max=0;
- for(int i=0;i<data.size();i++) {
-
- float amp = Math::abs(data[i]);
- if (amp>max)
- max=amp;
- }
-
- if (max>0) {
-
- float mult=1.0/max;
- for(int i=0;i<data.size();i++) {
-
- data[i]*=mult;
- }
-
- }
- }
-
- bool trim = p_options["edit/trim"];
-
- if (trim && !loop) {
-
- int first=0;
- int last=(frames*format_channels)-1;
- bool found=false;
- float limit = Math::db2linear((float)-30);
- for(int i=0;i<data.size();i++) {
- float amp = Math::abs(data[i]);
-
- if (!found && amp > limit) {
- first=i;
- found=true;
- }
-
- if (found && amp > limit) {
- last=i;
- }
- }
-
- first/=format_channels;
- last/=format_channels;
-
- if (first<last) {
-
- Vector<float> new_data;
- new_data.resize((last-first+1)*format_channels);
- for(int i=first*format_channels;i<=last*format_channels;i++) {
- new_data[i-first*format_channels]=data[i];
- }
-
- data=new_data;
- frames=data.size()/format_channels;
- }
-
- }
-
- bool make_loop = p_options["edit/loop"];
-
- if (make_loop && !loop) {
-
- loop=AudioStreamSample::LOOP_FORWARD;
- loop_begin=0;
- loop_end=frames;
- }
-
- int compression = p_options["compress/mode"];
- bool force_mono = p_options["force/mono"];
-
-
- if (force_mono && format_channels==2) {
-
- Vector<float> new_data;
- new_data.resize(data.size()/2);
- for(int i=0;i<frames;i++) {
- new_data[i]=(data[i*2+0]+data[i*2+1])/2.0;
- }
-
- data=new_data;
- format_channels=1;
- }
-
- bool force_8_bit = p_options["force/8_bit"];
- if (force_8_bit) {
-
- is16=false;
- }
-
-
- PoolVector<uint8_t> dst_data;
- AudioStreamSample::Format dst_format;
-
- if ( compression == 1) {
-
- dst_format=AudioStreamSample::FORMAT_IMA_ADPCM;
- if (format_channels==1) {
- _compress_ima_adpcm(data,dst_data);
- } else {
-
- //byte interleave
- Vector<float> left;
- Vector<float> right;
-
- int tframes = data.size()/2;
- left.resize(tframes);
- right.resize(tframes);
-
- for(int i=0;i<tframes;i++) {
- left[i]=data[i*2+0];
- right[i]=data[i*2+1];
- }
-
- PoolVector<uint8_t> bleft;
- PoolVector<uint8_t> bright;
-
- _compress_ima_adpcm(left,bleft);
- _compress_ima_adpcm(right,bright);
-
- int dl = bleft.size();
- dst_data.resize( dl *2 );
-
- PoolVector<uint8_t>::Write w=dst_data.write();
- PoolVector<uint8_t>::Read rl=bleft.read();
- PoolVector<uint8_t>::Read rr=bright.read();
-
- for(int i=0;i<dl;i++) {
- w[i*2+0]=rl[i];
- w[i*2+1]=rr[i];
- }
- }
-
- //print_line("compressing ima-adpcm, resulting buffersize is "+itos(dst_data.size())+" from "+itos(data.size()));
-
- } else {
-
- dst_format=is16?AudioStreamSample::FORMAT_16_BITS:AudioStreamSample::FORMAT_8_BITS;
- dst_data.resize( data.size() * (is16?2:1));
- {
- PoolVector<uint8_t>::Write w = dst_data.write();
-
- int ds=data.size();
- for(int i=0;i<ds;i++) {
-
- if (is16) {
- int16_t v = CLAMP(data[i]*32768,-32768,32767);
- encode_uint16(v,&w[i*2]);
- } else {
- int8_t v = CLAMP(data[i]*128,-128,127);
- w[i]=v;
- }
- }
- }
- }
-
-
- Ref<AudioStreamSample> sample;
- sample.instance();
- sample->set_data(dst_data);
- sample->set_format(dst_format);
- sample->set_mix_rate(rate);
- sample->set_loop_mode(loop);
- sample->set_loop_begin(loop_begin);
- sample->set_loop_end(loop_end);
- sample->set_stereo(format_channels==2);
-
- ResourceSaver::save(p_save_path+".smp",sample);
-
-
- return OK;
-
-}
-
-void ResourceImporterWAV::_compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data) {
-
-
- /*p_sample_data->data = (void*)malloc(len);
- xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/
-
- static const int16_t _ima_adpcm_step_table[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
- };
-
- static const int8_t _ima_adpcm_index_table[16] = {
- -1, -1, -1, -1, 2, 4, 6, 8,
- -1, -1, -1, -1, 2, 4, 6, 8
- };
-
-
- int datalen = p_data.size();
- int datamax=datalen;
- if (datalen&1)
- datalen++;
-
- dst_data.resize(datalen/2+4);
- PoolVector<uint8_t>::Write w = dst_data.write();
-
-
- int i,step_idx=0,prev=0;
- uint8_t *out = w.ptr();
- //int16_t xm_prev=0;
- const float *in=p_data.ptr();
-
-
- /* initial value is zero */
- *(out++) =0;
- *(out++) =0;
- /* Table index initial value */
- *(out++) =0;
- /* unused */
- *(out++) =0;
-
- for (i=0;i<datalen;i++) {
- int step,diff,vpdiff,mask;
- uint8_t nibble;
- int16_t xm_sample;
-
- if (i>=datamax)
- xm_sample=0;
- else {
-
-
- xm_sample=CLAMP(in[i]*32767.0,-32768,32767);
- /*
- if (xm_sample==32767 || xm_sample==-32768)
- printf("clippy!\n",xm_sample);
- */
- }
-
- //xm_sample=xm_sample+xm_prev;
- //xm_prev=xm_sample;
-
- diff = (int)xm_sample - prev ;
-
- nibble=0 ;
- step = _ima_adpcm_step_table[ step_idx ];
- vpdiff = step >> 3 ;
- if (diff < 0) {
- nibble=8;
- diff=-diff ;
- }
- mask = 4 ;
- while (mask) {
-
- if (diff >= step) {
-
- nibble |= mask;
- diff -= step;
- vpdiff += step;
- }
-
- step >>= 1 ;
- mask >>= 1 ;
- };
-
- if (nibble&8)
- prev-=vpdiff ;
- else
- prev+=vpdiff ;
-
- if (prev > 32767) {
- //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev);
- prev=32767;
- } else if (prev < -32768) {
- //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev);
- prev = -32768 ;
- }
-
- step_idx += _ima_adpcm_index_table[nibble];
- if (step_idx< 0)
- step_idx= 0 ;
- else if (step_idx> 88)
- step_idx= 88 ;
-
-
- if (i&1) {
- *out|=nibble<<4;
- out++;
- } else {
- *out=nibble;
- }
- /*dataptr[i]=prev>>8;*/
- }
-
-
-
-
-}
-
-ResourceImporterWAV::ResourceImporterWAV()
-{
-
-}
diff --git a/tools/editor/import/resource_importer_wav.h b/tools/editor/import/resource_importer_wav.h
deleted file mode 100644
index 9f1bd57da7..0000000000
--- a/tools/editor/import/resource_importer_wav.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef RESOURCEIMPORTWAV_H
-#define RESOURCEIMPORTWAV_H
-
-
-#include "io/resource_import.h"
-
-class ResourceImporterWAV : public ResourceImporter {
- GDCLASS(ResourceImporterWAV,ResourceImporter)
-public:
- virtual String get_importer_name() const;
- virtual String get_visible_name() const;
- virtual void get_recognized_extensions(List<String> *p_extensions) const;
- virtual String get_save_extension() const;
- virtual String get_resource_type() const;
-
-
- virtual int get_preset_count() const;
- virtual String get_preset_name(int p_idx) const;
-
- virtual void get_import_options(List<ImportOption> *r_options,int p_preset=0) const;
- virtual bool get_option_visibility(const String& p_option,const Map<StringName,Variant>& p_options) const;
-
- void _compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data);
-
- virtual Error import(const String& p_source_file,const String& p_save_path,const Map<StringName,Variant>& p_options,List<String>* r_platform_variants,List<String>* r_gen_files=NULL);
-
- ResourceImporterWAV();
-};
-
-#endif // RESOURCEIMPORTWAV_H
diff --git a/tools/editor/import_dock.cpp b/tools/editor/import_dock.cpp
deleted file mode 100644
index b1bd698239..0000000000
--- a/tools/editor/import_dock.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-#include "import_dock.h"
-
-class ImportDockParameters : public Object {
- GDCLASS(ImportDockParameters,Object)
-public:
- Map<StringName,Variant> values;
- List<PropertyInfo> properties;
- Ref<ResourceImporter> importer;
- Vector<String> paths;
-
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- if (values.has(p_name)) {
- values[p_name]=p_value;
- return true;
- }
-
- return false;
- }
-
- bool _get(const StringName& p_name,Variant &r_ret) const {
-
- if (values.has(p_name)) {
- r_ret=values[p_name];
- return true;
- }
-
- return false;
-
- }
- void _get_property_list( List<PropertyInfo> *p_list) const {
-
- for (const List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
- if (!importer->get_option_visibility(E->get().name,values))
- continue;
- p_list->push_back(E->get());
- }
- }
-
- void update() {
- _change_notify();
- }
-};
-
-void ImportDock::set_edit_path(const String& p_path) {
-
- Ref<ConfigFile> config;
- config.instance();
- Error err = config->load(p_path+".import");
- if (err!=OK) {
- clear();
- return;
- }
-
-
- params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer"));
- if (params->importer.is_null()) {
- clear();
- return;
- }
-
- List<ResourceImporter::ImportOption> options;
- params->importer->get_import_options(&options);
-
- params->properties.clear();
- params->values.clear();
-
- for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
-
- params->properties.push_back(E->get().option);
- if (config->has_section_key("params",E->get().option.name)) {
- params->values[E->get().option.name]=config->get_value("params",E->get().option.name);
- } else {
- params->values[E->get().option.name]=E->get().default_value;
- }
- }
-
- params->update();
-
- List<Ref<ResourceImporter> > importers;
- ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(),&importers);
- List<Pair<String,String> > importer_names;
-
- for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) {
- importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name()));
- }
-
- importer_names.sort_custom<PairSort<String,String> >();
-
- import_as->clear();
-
- for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) {
- import_as->add_item(E->get().first);
- import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second);
- if (E->get().second==params->importer->get_importer_name()) {
- import_as->select(import_as->get_item_count()-1);
- }
- }
-
- preset->get_popup()->clear();
-
- if (params->importer->get_preset_count()==0) {
- preset->get_popup()->add_item(TTR("Default"));
- } else {
- for (int i=0;i<params->importer->get_preset_count();i++) {
- preset->get_popup()->add_item(params->importer->get_preset_name(i));
- }
- }
-
- params->paths.clear();
- params->paths.push_back(p_path);
- import->set_disabled(false);
- import_as->set_disabled(false);
-
- imported->set_text(p_path.get_file());
-}
-
-void ImportDock::set_edit_multiple_paths(const Vector<String>& p_paths) {
-
- clear();
-
- //use the value that is repeated the mot
- Map<String,Dictionary> value_frequency;
-
- for(int i=0;i<p_paths.size();i++) {
-
- Ref<ConfigFile> config;
- config.instance();
- Error err = config->load(p_paths[i]+".import");
- ERR_CONTINUE(err!=OK);
-
- if (i==0) {
- params->importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(config->get_value("remap","importer"));
- if (params->importer.is_null()) {
- clear();
- return;
- }
- }
-
- List<String> keys;
- config->get_section_keys("params",&keys);
-
-
- for (List<String>::Element *E=keys.front();E;E=E->next()) {
-
- if (!value_frequency.has(E->get())) {
- value_frequency[E->get()]=Dictionary();
- }
-
- Variant value = config->get_value("params",E->get());
-
- if (value_frequency[E->get()].has(value)) {
- value_frequency[E->get()][value]=int(value_frequency[E->get()][value])+1;
- } else {
- value_frequency[E->get()][value]=1;
- }
- }
-
- }
-
- ERR_FAIL_COND(params->importer.is_null());
-
- List<ResourceImporter::ImportOption> options;
- params->importer->get_import_options(&options);
-
- params->properties.clear();
- params->values.clear();
-
- for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
-
- params->properties.push_back(E->get().option);
-
- if (value_frequency.has(E->get().option.name)) {
-
- Dictionary d = value_frequency[E->get().option.name];
- int freq=0;
- List<Variant> v;
- d.get_key_list(&v);
- Variant value;
- for (List<Variant>::Element *F=v.front();F;F=F->next()) {
- int f = d[F->get()];
- if (f>freq) {
- value=F->get();
- }
- }
-
- params->values[E->get().option.name]=value;
- } else {
- params->values[E->get().option.name]=E->get().default_value;
- }
- }
-
- params->update();
-
- List<Ref<ResourceImporter> > importers;
- ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_paths[0].get_extension(),&importers);
- List<Pair<String,String> > importer_names;
-
- for (List<Ref<ResourceImporter> > ::Element *E=importers.front();E;E=E->next()) {
- importer_names.push_back(Pair<String,String>(E->get()->get_visible_name(),E->get()->get_importer_name()));
- }
-
- importer_names.sort_custom<PairSort<String,String> >();
-
- import_as->clear();
-
- for (List<Pair<String,String> >::Element *E=importer_names.front();E;E=E->next()) {
- import_as->add_item(E->get().first);
- import_as->set_item_metadata(import_as->get_item_count()-1,E->get().second);
- if (E->get().second==params->importer->get_importer_name()) {
- import_as->select(import_as->get_item_count()-1);
- }
- }
-
- preset->get_popup()->clear();
-
- if (params->importer->get_preset_count()==0) {
- preset->get_popup()->add_item(TTR("Default"));
- } else {
- for (int i=0;i<params->importer->get_preset_count();i++) {
- preset->get_popup()->add_item(params->importer->get_preset_name(i));
- }
- }
-
- params->paths=p_paths;
- import->set_disabled(false);
- import_as->set_disabled(false);
-
- imported->set_text(itos(p_paths.size())+TTR(" Files"));
-}
-
-void ImportDock::_preset_selected(int p_idx) {
-
- print_line("preset selected? "+p_idx);
- List<ResourceImporter::ImportOption> options;
-
- params->importer->get_import_options(&options,p_idx);
-
- for (List<ResourceImporter::ImportOption>::Element *E=options.front();E;E=E->next()) {
-
- params->values[E->get().option.name]=E->get().default_value;
- }
-
- params->update();
-
-}
-
-
-void ImportDock::clear() {
-
- imported->set_text("");
- import->set_disabled(true);
- import_as->clear();
- import_as->set_disabled(true);
- params->values.clear();
- params->properties.clear();
- params->update();
- preset->get_popup()->clear();
-
-}
-
-void ImportDock::_reimport() {
-
- for(int i=0;i<params->paths.size();i++) {
-
- Ref<ConfigFile> config;
- config.instance();
- Error err = config->load(params->paths[i]+".import");
- ERR_CONTINUE(err!=OK);
-
- config->erase_section("params");
-
- for (List<PropertyInfo>::Element *E=params->properties.front();E;E=E->next()) {
- config->set_value("params",E->get().name,params->values[E->get().name]);
- }
-
- config->save(params->paths[i]+".import");
- }
-
- EditorFileSystem::get_singleton()->reimport_files(params->paths);
- EditorFileSystem::get_singleton()->emit_signal("filesystem_changed"); //it changed, so force emitting the signal
-
-}
-
-void ImportDock::_bind_methods() {
-
- ClassDB::bind_method(_MD("_reimport"),&ImportDock::_reimport);
- ClassDB::bind_method(_MD("_preset_selected"),&ImportDock::_preset_selected);
-}
-
-ImportDock::ImportDock() {
-
-
- imported = memnew( LineEdit );
- imported->set_editable(false);
- add_child(imported);
- HBoxContainer *hb = memnew(HBoxContainer);
- add_margin_child(TTR("Import As:"),hb);
- import_as = memnew( OptionButton );
- hb->add_child(import_as);
- import_as->set_h_size_flags(SIZE_EXPAND_FILL);
- preset = memnew( MenuButton );
- preset->set_text(TTR("Preset.."));
- preset->get_popup()->connect("index_pressed",this,"_preset_selected");
- hb->add_child(preset);
-
- import_opts = memnew( PropertyEditor );
- add_child(import_opts);
- import_opts->set_v_size_flags(SIZE_EXPAND_FILL);
- import_opts->hide_top_label();
- import_opts->set_hide_script(true);
-
- hb = memnew( HBoxContainer );
- add_child(hb);
- import = memnew( Button );
- import->set_text(TTR("Reimport"));
- import->connect("pressed",this,"_reimport");
- hb->add_spacer();
- hb->add_child(import);
- hb->add_spacer();
-
- params = memnew( ImportDockParameters );
- import_opts->edit(params);
-
-}
-
-ImportDock::~ImportDock() {
-
- memdelete(params);
-}
diff --git a/tools/editor/import_dock.h b/tools/editor/import_dock.h
deleted file mode 100644
index bddf5480b8..0000000000
--- a/tools/editor/import_dock.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef IMPORTDOCK_H
-#define IMPORTDOCK_H
-
-#include "io/resource_import.h"
-#include "editor_file_system.h"
-#include "scene/gui/box_container.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/popup_menu.h"
-#include "property_editor.h"
-
-class ImportDockParameters;
-class ImportDock : public VBoxContainer {
- GDCLASS(ImportDock,VBoxContainer)
-
- LineEdit *imported;
- OptionButton *import_as;
- MenuButton *preset;
- PropertyEditor *import_opts;
-
- List<PropertyInfo> properties;
- Map<StringName,Variant> property_values;
-
- Button *import;
-
- ImportDockParameters *params;
-
- void _preset_selected(int p_idx);
-
- void _reimport();
-protected:
- static void _bind_methods();
-public:
-
- void set_edit_path(const String& p_path);
- void set_edit_multiple_paths(const Vector<String>& p_paths);
- void clear();
-
- ImportDock();
- ~ImportDock();
-};
-
-#endif // IMPORTDOCK_H
diff --git a/tools/editor/io_plugins/editor_bitmask_import_plugin.cpp b/tools/editor/io_plugins/editor_bitmask_import_plugin.cpp
deleted file mode 100644
index 587353fef8..0000000000
--- a/tools/editor/io_plugins/editor_bitmask_import_plugin.cpp
+++ /dev/null
@@ -1,387 +0,0 @@
-/*************************************************************************/
-/* editor_bitmask_import_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_bitmask_import_plugin.h"
-#if 0
-#include "io/image_loader.h"
-#include "tools/editor/editor_file_dialog.h"
-#include "tools/editor/editor_dir_dialog.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/property_editor.h"
-#include "io/resource_saver.h"
-#include "os/file_access.h"
-#include "io/marshalls.h"
-#include "tools/editor/editor_settings.h"
-
-class _EditorBitMaskImportOptions : public Object {
-
- GDCLASS(_EditorBitMaskImportOptions, Object);
-public:
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- return false;
- }
-
- bool _get(const StringName& p_name, Variant &r_ret) const{
-
- return false;
- }
-
- void _get_property_list(List<PropertyInfo> *p_list) const{
-
- }
-
- static void _bind_methods() {
-
- ADD_SIGNAL(MethodInfo("changed"));
- }
-
-
- _EditorBitMaskImportOptions() {
-
- }
-
-};
-
-class EditorBitMaskImportDialog : public ConfirmationDialog {
-
- GDCLASS(EditorBitMaskImportDialog, ConfirmationDialog);
-
- EditorBitMaskImportPlugin *plugin;
-
- LineEdit *import_path;
- LineEdit *save_path;
- EditorFileDialog *file_select;
- EditorDirDialog *save_select;
- ConfirmationDialog *error_dialog;
- PropertyEditor *option_editor;
-
-public:
-
- void _choose_files(const Vector<String>& p_path) {
-
- String files;
- for (int i = 0; i<p_path.size(); i++) {
-
- if (i>0)
- files += ",";
- files += p_path[i];
- }
-
- import_path->set_text(files);
-
- }
- void _choose_save_dir(const String& p_path) {
-
- save_path->set_text(p_path);
- }
-
- void _browse() {
-
- file_select->popup_centered_ratio();
- }
-
- void _browse_target() {
-
- save_select->popup_centered_ratio();
-
- }
-
-
- void popup_import(const String& p_path) {
-
- popup_centered(Size2(400, 100)*EDSCALE);
- if (p_path != "") {
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
- ERR_FAIL_COND(!rimd.is_valid());
-
- save_path->set_text(p_path.get_base_dir());
-
- String src = "";
- for (int i = 0; i<rimd->get_source_count(); i++) {
- if (i>0)
- src += ",";
- src += EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
- }
- import_path->set_text(src);
- }
- }
-
-
- void _import() {
-
- Vector<String> bitmasks = import_path->get_text().split(",");
-
- if (bitmasks.size() == 0) {
- error_dialog->set_text(TTR("No bit masks to import!"));
- error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
- }
-
- if (save_path->get_text().strip_edges() == "") {
- error_dialog->set_text(TTR("Target path is empty."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (!save_path->get_text().begins_with("res://")) {
- error_dialog->set_text(TTR("Target path must be a complete resource path."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (!DirAccess::exists(save_path->get_text())) {
- error_dialog->set_text(TTR("Target path must exist."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- for (int i = 0; i<bitmasks.size(); i++) {
-
- Ref<ResourceImportMetadata> imd = memnew(ResourceImportMetadata);
-
- imd->add_source(EditorImportPlugin::validate_source_path(bitmasks[i]));
-
- String dst = save_path->get_text();
- if (dst == "") {
- error_dialog->set_text(TTR("Save path is empty!"));
- error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
- }
-
- dst = dst.plus_file(bitmasks[i].get_file().get_basename() + ".pbm");
-
- plugin->import(dst, imd);
- }
-
- hide();
-
- }
-
-
- void _notification(int p_what) {
-
- }
-
- static void _bind_methods() {
-
-
- ClassDB::bind_method("_choose_files", &EditorBitMaskImportDialog::_choose_files);
- ClassDB::bind_method("_choose_save_dir", &EditorBitMaskImportDialog::_choose_save_dir);
- ClassDB::bind_method("_import", &EditorBitMaskImportDialog::_import);
- ClassDB::bind_method("_browse", &EditorBitMaskImportDialog::_browse);
- ClassDB::bind_method("_browse_target", &EditorBitMaskImportDialog::_browse_target);
- //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
- }
-
- EditorBitMaskImportDialog(EditorBitMaskImportPlugin *p_plugin) {
-
- plugin = p_plugin;
-
-
- set_title(TTR("Import BitMasks"));
-
- VBoxContainer *vbc = memnew(VBoxContainer);
- add_child(vbc);
- //set_child_rect(vbc);
-
-
- HBoxContainer *hbc = memnew(HBoxContainer);
- vbc->add_margin_child(TTR("Source Texture(s):"), hbc);
-
- import_path = memnew(LineEdit);
- import_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(import_path);
-
- Button * import_choose = memnew(Button);
- import_choose->set_text(" .. ");
- hbc->add_child(import_choose);
-
- import_choose->connect("pressed", this, "_browse");
-
- hbc = memnew(HBoxContainer);
- vbc->add_margin_child(TTR("Target Path:"), hbc);
-
- save_path = memnew(LineEdit);
- save_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(save_path);
-
- Button * save_choose = memnew(Button);
- save_choose->set_text(" .. ");
- hbc->add_child(save_choose);
-
- save_choose->connect("pressed", this, "_browse_target");
-
- file_select = memnew(EditorFileDialog);
- file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- add_child(file_select);
- file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
- file_select->connect("files_selected", this, "_choose_files");
-
- List<String> extensions;
- ImageLoader::get_recognized_extensions(&extensions);
- file_select->clear_filters();
- for (int i = 0; i<extensions.size(); i++) {
-
- file_select->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
- }
-
- save_select = memnew(EditorDirDialog);
- add_child(save_select);
-
- //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
- save_select->connect("dir_selected", this, "_choose_save_dir");
-
- get_ok()->connect("pressed", this, "_import");
- get_ok()->set_text(TTR("Import"));
-
-
- error_dialog = memnew(ConfirmationDialog);
- add_child(error_dialog);
- error_dialog->get_ok()->set_text(TTR("Accept"));
- //error_dialog->get_cancel()->hide();
-
- set_hide_on_ok(false);
- }
-
- ~EditorBitMaskImportDialog() {
- }
-
-};
-
-
-String EditorBitMaskImportPlugin::get_name() const {
-
- return "bitmask";
-}
-String EditorBitMaskImportPlugin::get_visible_name() const{
-
- return TTR("Bit Mask");
-}
-void EditorBitMaskImportPlugin::import_dialog(const String& p_from){
-
- dialog->popup_import(p_from);
-}
-Error EditorBitMaskImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
-
- ERR_FAIL_COND_V(p_from->get_source_count() != 1, ERR_INVALID_PARAMETER);
-
- Ref<ResourceImportMetadata> from = p_from;
-
- String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
- Ref<ImageTexture> it = ResourceLoader::load(src_path);
- ERR_FAIL_COND_V(it.is_null(), ERR_CANT_OPEN);
-
- Ref<BitMap> target = memnew(BitMap);
- target->create_from_image_alpha(it.ptr()->get_data());
-
- from->set_source_md5(0, FileAccess::get_md5(src_path));
- from->set_editor(get_name());
- target->set_import_metadata(from);
-
-
- Error err = ResourceSaver::save(p_path, target);
-
- return err;
-
-}
-
-
-EditorBitMaskImportPlugin* EditorBitMaskImportPlugin::singleton = NULL;
-
-
-void EditorBitMaskImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
-
- Vector<String> files;
-
- List<String> valid_extensions;
- ImageLoader::get_recognized_extensions(&valid_extensions);
- for(int i=0;i<p_drop.size();i++) {
-
- String extension=p_drop[i].get_extension().to_lower();
-
- for (List<String>::Element *E=valid_extensions.front();E;E=E->next()) {
-
- if (E->get()==extension) {
- files.push_back(p_drop[i]);
- break;
- }
- }
- }
-
- if (files.size()) {
- import_dialog();
- dialog->_choose_files(files);
- dialog->_choose_save_dir(p_dest_path);
- }
-}
-
-void EditorBitMaskImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
-
- if (p_list.size() == 0)
- return;
-
- Vector<String> sources;
- for (int i = 0; i<p_list.size(); i++) {
- int idx;
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i], &idx);
- if (efsd) {
- for (int j = 0; j<efsd->get_source_count(idx); j++) {
- String file = expand_source_path(efsd->get_source_file(idx, j));
- if (sources.find(file) == -1) {
- sources.push_back(file);
- }
-
- }
- }
- }
-
- if (sources.size()) {
-
- dialog->popup_import(p_list[0]);
- dialog->_choose_files(sources);
- dialog->_choose_save_dir(p_list[0].get_base_dir());
- }
-}
-
-bool EditorBitMaskImportPlugin::can_reimport_multiple_files() const {
-
- return true;
-}
-
-EditorBitMaskImportPlugin::EditorBitMaskImportPlugin(EditorNode* p_editor) {
-
- singleton = this;
- dialog = memnew(EditorBitMaskImportDialog(this));
- p_editor->get_gui_base()->add_child(dialog);
-}
-
-EditorBitMaskExportPlugin::EditorBitMaskExportPlugin() {
-
-}
-#endif
diff --git a/tools/editor/io_plugins/editor_bitmask_import_plugin.h b/tools/editor/io_plugins/editor_bitmask_import_plugin.h
deleted file mode 100644
index 89ff58ec93..0000000000
--- a/tools/editor/io_plugins/editor_bitmask_import_plugin.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*************************************************************************/
-/* editor_bitmask_import_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_BITMASK_IMPORT_PLUGIN_H
-#define EDITOR_BITMASK_IMPORT_PLUGIN_H
-#if 0
-#include "tools/editor/editor_import_export.h"
-#include "scene/resources/font.h"
-
-class EditorNode;
-class EditorBitMaskImportDialog;
-
-class EditorBitMaskImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorBitMaskImportPlugin, EditorImportPlugin);
-
- EditorBitMaskImportDialog *dialog;
-public:
-
- static EditorBitMaskImportPlugin *singleton;
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from = "");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
- void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
- virtual void reimport_multiple_files(const Vector<String>& p_list);
- virtual bool can_reimport_multiple_files() const;
-
-
- EditorBitMaskImportPlugin(EditorNode* p_editor);
-};
-
-class EditorBitMaskExportPlugin : public EditorExportPlugin {
-
- GDCLASS(EditorBitMaskExportPlugin, EditorExportPlugin);
-
-
-public:
-
- EditorBitMaskExportPlugin();
-};
-
-#endif
-#endif // EDITOR_SAMPLE_IMPORT_PLUGIN_H
diff --git a/tools/editor/io_plugins/editor_export_scene.cpp b/tools/editor/io_plugins/editor_export_scene.cpp
deleted file mode 100644
index f4ab9880ff..0000000000
--- a/tools/editor/io_plugins/editor_export_scene.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*************************************************************************/
-/* editor_export_scene.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_export_scene.h"
-#if 0
-#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.get_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 = GlobalConfig::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()
-{
-}
-#endif
diff --git a/tools/editor/io_plugins/editor_export_scene.h b/tools/editor/io_plugins/editor_export_scene.h
deleted file mode 100644
index 191029bd84..0000000000
--- a/tools/editor/io_plugins/editor_export_scene.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*************************************************************************/
-/* editor_export_scene.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_EXPORT_SCENE_H
-#define EDITOR_EXPORT_SCENE_H
-
-#include "tools/editor/editor_import_export.h"
-
-#if 0
-class EditorSceneExportPlugin : public EditorExportPlugin {
- GDCLASS( EditorSceneExportPlugin, EditorExportPlugin );
-public:
-
- virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
-
- EditorSceneExportPlugin();
-};
-#endif
-#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
deleted file mode 100644
index 417aad0db8..0000000000
--- a/tools/editor/io_plugins/editor_font_import_plugin.cpp
+++ /dev/null
@@ -1,1704 +0,0 @@
-/*************************************************************************/
-/* editor_font_import_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_font_import_plugin.h"
-#if 0
-#include "scene/gui/dialogs.h"
-#include "tools/editor/editor_file_dialog.h"
-#include "tools/editor/editor_node.h"
-#include "os/file_access.h"
-#include "editor_atlas.h"
-#include "io/image_loader.h"
-#include "io/resource_saver.h"
-
-#ifdef FREETYPE_ENABLED
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#endif
-
-
-class _EditorFontImportOptions : public Object {
-
- GDCLASS(_EditorFontImportOptions,Object);
-public:
-
- enum FontMode {
-
- FONT_BITMAP,
- FONT_DISTANCE_FIELD
- };
-
- enum ColorType {
- COLOR_WHITE,
- COLOR_CUSTOM,
- COLOR_GRADIENT_RANGE,
- COLOR_GRADIENT_IMAGE
- };
-
-
- int char_extra_spacing;
- int top_extra_spacing;
- int bottom_extra_spacing;
- int space_extra_spacing;
-
- enum CharacterSet {
-
- CHARSET_ASCII,
- CHARSET_LATIN,
- CHARSET_UNICODE,
- CHARSET_CUSTOM,
- CHARSET_CUSTOM_LATIN
- };
-
-
- FontMode font_mode;
-
- CharacterSet character_set;
- String custom_file;
-
- bool shadow;
- Vector2 shadow_offset;
- int shadow_radius;
- Color shadow_color;
- float shadow_transition;
-
- bool shadow2;
- Vector2 shadow2_offset;
- int shadow2_radius;
- Color shadow2_color;
- float shadow2_transition;
-
- ColorType color_type;
- Color color;
- Color gradient_begin;
- Color gradient_end;
- bool color_use_monochrome;
- String gradient_image;
-
- bool enable_filter;
- bool round_advance;
- bool premultiply_alpha;
-
-
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- String n = p_name;
- if (n=="mode/mode") {
- font_mode=FontMode(int(p_value));
- _change_notify();
- } else if (n=="extra_space/char")
- char_extra_spacing=p_value;
- else if (n=="extra_space/space")
- space_extra_spacing=p_value;
- else if (n=="extra_space/top")
- top_extra_spacing=p_value;
- else if (n=="extra_space/bottom")
- bottom_extra_spacing=p_value;
-
- else if (n=="character_set/mode") {
- character_set=CharacterSet(int(p_value));
- _change_notify();
- } else if (n=="character_set/custom")
- custom_file=p_value;
-
- else if (n=="shadow/enabled") {
- shadow=p_value;
- _change_notify();
- }else if (n=="shadow/radius")
- shadow_radius=p_value;
- else if (n=="shadow/offset")
- shadow_offset=p_value;
- else if (n=="shadow/color")
- shadow_color=p_value;
- else if (n=="shadow/transition")
- shadow_transition=p_value;
-
- else if (n=="shadow2/enabled") {
- shadow2=p_value;
- _change_notify();
- }else if (n=="shadow2/radius")
- shadow2_radius=p_value;
- else if (n=="shadow2/offset")
- shadow2_offset=p_value;
- else if (n=="shadow2/color")
- shadow2_color=p_value;
- else if (n=="shadow2/transition")
- shadow2_transition=p_value;
-
- else if (n=="color/mode") {
- color_type=ColorType(int(p_value));
- _change_notify();
- }else if (n=="color/color")
- color=p_value;
- else if (n=="color/begin")
- gradient_begin=p_value;
- else if (n=="color/end")
- gradient_end=p_value;
- else if (n=="color/image")
- gradient_image=p_value;
- else if (n=="color/monochrome")
- color_use_monochrome=p_value;
- else if (n=="advanced/round_advance")
- round_advance=p_value;
- else if (n=="advanced/enable_filter")
- enable_filter=p_value;
- else if (n=="advanced/premultiply_alpha")
- premultiply_alpha=p_value;
- else
- return false;
-
- emit_signal("changed");
-
-
- return true;
-
- }
-
- bool _get(const StringName& p_name,Variant &r_ret) const{
-
- String n = p_name;
- if (n=="mode/mode")
- r_ret=font_mode;
- else if (n=="extra_space/char")
- r_ret=char_extra_spacing;
- else if (n=="extra_space/space")
- r_ret=space_extra_spacing;
- else if (n=="extra_space/top")
- r_ret=top_extra_spacing;
- else if (n=="extra_space/bottom")
- r_ret=bottom_extra_spacing;
-
- else if (n=="character_set/mode")
- r_ret=character_set;
- else if (n=="character_set/custom")
- r_ret=custom_file;
-
- else if (n=="shadow/enabled")
- r_ret=shadow;
- else if (n=="shadow/radius")
- r_ret=shadow_radius;
- else if (n=="shadow/offset")
- r_ret=shadow_offset;
- else if (n=="shadow/color")
- r_ret=shadow_color;
- else if (n=="shadow/transition")
- r_ret=shadow_transition;
-
- else if (n=="shadow2/enabled")
- r_ret=shadow2;
- else if (n=="shadow2/radius")
- r_ret=shadow2_radius;
- else if (n=="shadow2/offset")
- r_ret=shadow2_offset;
- else if (n=="shadow2/color")
- r_ret=shadow2_color;
- else if (n=="shadow2/transition")
- r_ret=shadow2_transition;
-
-
- else if (n=="color/mode")
- r_ret=color_type;
- else if (n=="color/color")
- r_ret=color;
- else if (n=="color/begin")
- r_ret=gradient_begin;
- else if (n=="color/end")
- r_ret=gradient_end;
- else if (n=="color/image")
- r_ret=gradient_image;
- else if (n=="color/monochrome")
- r_ret=color_use_monochrome;
- else if (n=="advanced/round_advance")
- r_ret=round_advance;
- else if (n=="advanced/enable_filter")
- r_ret=enable_filter;
- else if (n=="advanced/premultiply_alpha")
- r_ret=premultiply_alpha;
- else
- return false;
-
- return true;
-
- }
-
- void _get_property_list( List<PropertyInfo> *p_list) const{
-
-
- p_list->push_back(PropertyInfo(Variant::INT,"mode/mode",PROPERTY_HINT_ENUM,"Bitmap,Distance Field"));
-
- p_list->push_back(PropertyInfo(Variant::INT,"extra_space/char",PROPERTY_HINT_RANGE,"-64,64,1"));
- p_list->push_back(PropertyInfo(Variant::INT,"extra_space/space",PROPERTY_HINT_RANGE,"-64,64,1"));
- p_list->push_back(PropertyInfo(Variant::INT,"extra_space/top",PROPERTY_HINT_RANGE,"-64,64,1"));
- p_list->push_back(PropertyInfo(Variant::INT,"extra_space/bottom",PROPERTY_HINT_RANGE,"-64,64,1"));
- p_list->push_back(PropertyInfo(Variant::INT,"character_set/mode",PROPERTY_HINT_ENUM,"Ascii,Latin,Unicode,Custom,Custom&Latin"));
-
- if (character_set>=CHARSET_CUSTOM)
- p_list->push_back(PropertyInfo(Variant::STRING,"character_set/custom",PROPERTY_HINT_GLOBAL_FILE));
-
- int usage = PROPERTY_USAGE_DEFAULT;
-
- if (font_mode==FONT_DISTANCE_FIELD) {
- usage = PROPERTY_USAGE_NOEDITOR;
- }
-
- {
-
- p_list->push_back(PropertyInfo(Variant::BOOL,"shadow/enabled",PROPERTY_HINT_NONE,"",usage));
- if (shadow) {
- p_list->push_back(PropertyInfo(Variant::INT,"shadow/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage));
- p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow/offset",PROPERTY_HINT_NONE,"",usage));
- p_list->push_back(PropertyInfo(Variant::COLOR,"shadow/color",PROPERTY_HINT_NONE,"",usage));
- p_list->push_back(PropertyInfo(Variant::REAL,"shadow/transition",PROPERTY_HINT_EXP_EASING,"",usage));
- }
-
- p_list->push_back(PropertyInfo(Variant::BOOL,"shadow2/enabled",PROPERTY_HINT_NONE,"",usage));
- if (shadow2) {
- p_list->push_back(PropertyInfo(Variant::INT,"shadow2/radius",PROPERTY_HINT_RANGE,"-64,64,1",usage));
- p_list->push_back(PropertyInfo(Variant::VECTOR2,"shadow2/offset",PROPERTY_HINT_NONE,"",usage));
- p_list->push_back(PropertyInfo(Variant::COLOR,"shadow2/color",PROPERTY_HINT_NONE,"",usage));
- p_list->push_back(PropertyInfo(Variant::REAL,"shadow2/transition",PROPERTY_HINT_EXP_EASING,"",usage));
- }
-
- p_list->push_back(PropertyInfo(Variant::INT,"color/mode",PROPERTY_HINT_ENUM,"White,Color,Gradient,Gradient Image",usage));
- if (color_type==COLOR_CUSTOM) {
- p_list->push_back(PropertyInfo(Variant::COLOR,"color/color",PROPERTY_HINT_NONE,"",usage));
-
- }
- if (color_type==COLOR_GRADIENT_RANGE) {
- p_list->push_back(PropertyInfo(Variant::COLOR,"color/begin",PROPERTY_HINT_NONE,"",usage));
- p_list->push_back(PropertyInfo(Variant::COLOR,"color/end",PROPERTY_HINT_NONE,"",usage));
- }
- if (color_type==COLOR_GRADIENT_IMAGE) {
- p_list->push_back(PropertyInfo(Variant::STRING,"color/image",PROPERTY_HINT_GLOBAL_FILE,"",usage));
- }
- p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome",PROPERTY_HINT_NONE,"",usage));
- }
-
- p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/round_advance"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/enable_filter"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/premultiply_alpha"));
-
- }
-
-
- static void _bind_methods() {
-
-
- ADD_SIGNAL( MethodInfo("changed"));
- }
-
-
- void reset() {
-
- char_extra_spacing=0;
- top_extra_spacing=0;
- bottom_extra_spacing=0;
- space_extra_spacing=0;
-
- character_set=CHARSET_LATIN;
-
- shadow=false;
- shadow_radius=2;
- shadow_color=Color(0,0,0,0.3);
- shadow_transition=1.0;
-
- shadow2=false;
- shadow2_radius=2;
- shadow2_color=Color(0,0,0,0.3);
- shadow2_transition=1.0;
-
- color_type=COLOR_WHITE;
- color=Color(1,1,1,1);
- gradient_begin=Color(1,1,1,1);
- gradient_end=Color(0.5,0.5,0.5,1);
- color_use_monochrome=false;
-
- font_mode=FONT_BITMAP;
- round_advance=true;
- enable_filter=true;
- premultiply_alpha=false;
-
- }
-
- _EditorFontImportOptions() {
-
- font_mode=FONT_BITMAP;
-
- char_extra_spacing=0;
- top_extra_spacing=0;
- bottom_extra_spacing=0;
- space_extra_spacing=0;
-
- character_set=CHARSET_LATIN;
-
- shadow=false;
- shadow_radius=2;
- shadow_color=Color(0,0,0,0.3);
- shadow_transition=1.0;
-
- shadow2=false;
- shadow2_radius=2;
- shadow2_color=Color(0,0,0,0.3);
- shadow2_transition=1.0;
-
- color_type=COLOR_WHITE;
- color=Color(1,1,1,1);
- gradient_begin=Color(1,1,1,1);
- gradient_end=Color(0.5,0.5,0.5,1);
- color_use_monochrome=false;
-
- round_advance=true;
- enable_filter=true;
- premultiply_alpha=false;
- }
-
-
-};
-
-
-class EditorFontImportDialog : public ConfirmationDialog {
-
- GDCLASS(EditorFontImportDialog, ConfirmationDialog);
-
-
- EditorLineEditFileChooser *source;
- EditorLineEditFileChooser *dest;
- SpinBox *font_size;
- LineEdit *test_string;
- ColorPickerButton *test_color;
- Label *test_label;
- PropertyEditor *prop_edit;
- Timer *timer;
- ConfirmationDialog *error_dialog;
-
-
- Ref<ResourceImportMetadata> get_rimd() {
-
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
- List<PropertyInfo> pl;
- options->_get_property_list(&pl);
- for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
-
- Variant v;
- String opt=E->get().name;
- options->_get(opt,v);
- if (opt=="color/image" || opt=="character_set/custom") {
- v = EditorImportPlugin::validate_source_path(v);
- }
- imd->set_option(opt,v);
- }
-
- String src_path = EditorImportPlugin::validate_source_path(source->get_line_edit()->get_text());
- //print_line("pre src path "+source->get_line_edit()->get_text());
- //print_line("src path "+src_path);
- imd->add_source(src_path);
- imd->set_option("font/size",font_size->get_value());
-
- return imd;
-
- }
-
- void _src_changed(String) {
- _prop_changed();
- }
-
- void _update_text2(String) {
- _update_text();
- }
- void _update_text3(Color) {
- _update_text();
- }
-
- void _update_text() {
-
- test_label->set_text("");
- test_label->set_text(test_string->get_text());
- test_label->add_color_override("font_color",test_color->get_pick_color());
- }
-
- void _update() {
-
- Ref<ResourceImportMetadata> imd = get_rimd();
- Ref<BitmapFont> font = plugin->generate_font(imd);
- test_label->add_font_override("font",font);
- _update_text();
- }
-
- void _font_size_changed(double) {
-
- _prop_changed();
- }
-
- void _prop_changed() {
-
- timer->start();
- }
-
- void _import_inc(String p_font) {
-
- Ref<BitmapFont> font = ResourceLoader::load(p_font);
- if (!font.is_valid())
- return;
- Ref<ImageTexture> tex = font->get_texture(0);
- if (tex.is_null())
- return;
- FileAccessRef f=FileAccess::open(p_font.get_basename()+".inc",FileAccess::WRITE);
- Vector<CharType> ck = font->get_char_keys();
-
- f->store_line("static const int _builtin_font_height="+itos(font->get_height())+";");
- f->store_line("static const int _builtin_font_ascent="+itos(font->get_ascent())+";");
- f->store_line("static const int _builtin_font_charcount="+itos(ck.size())+";");
- f->store_line("static const int _builtin_font_charrects["+itos(ck.size())+"][8]={");
- f->store_line("/* charidx , ofs_x, ofs_y, size_x, size_y, valign, halign, advance */");
-
- for(int i=0;i<ck.size();i++) {
- CharType k=ck[i];
- BitmapFont::Character c=font->get_character(k);
- f->store_line("{"+itos(k)+","+rtos(c.rect.pos.x)+","+rtos(c.rect.pos.y)+","+rtos(c.rect.size.x)+","+rtos(c.rect.size.y)+","+rtos(c.v_align)+","+rtos(c.h_align)+","+rtos(c.advance)+"},");
- }
- f->store_line("};");
-
- Vector<BitmapFont::KerningPairKey> kp=font->get_kerning_pair_keys();
- f->store_line("static const int _builtin_font_kerning_pair_count="+itos(kp.size())+";");
- f->store_line("static const int _builtin_font_kerning_pairs["+itos(kp.size())+"][3]={");
- for(int i=0;i<kp.size();i++) {
-
- int d = font->get_kerning_pair(kp[i].A,kp[i].B);
- f->store_line("{"+itos(kp[i].A)+","+itos(kp[i].B)+","+itos(d)+"},");
- }
-
- f->store_line("};");
- Image img = tex->get_data();
-
- f->store_line("static const int _builtin_font_img_width="+itos(img.get_width())+";");
- f->store_line("static const int _builtin_font_img_height="+itos(img.get_height())+";");
-
- String fname = p_font.get_basename()+".sv.png";
- ResourceSaver::save(fname,tex);
- Vector<uint8_t> data=FileAccess::get_file_as_array(fname);
-
-
- f->store_line("static const int _builtin_font_img_data_size="+itos(data.size())+";");
- f->store_line("static const unsigned char _builtin_font_img_data["+itos(data.size())+"]={");
-
-
-
- for(int i=0;i<data.size();i++) {
-
- f->store_line(itos(data[i])+",");
-
- }
- f->store_line("};");
-
- }
-
- void _import() {
-
- if (source->get_line_edit()->get_text()=="") {
- error_dialog->set_text(TTR("No source font file!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- if (dest->get_line_edit()->get_text()=="") {
- error_dialog->set_text(TTR("No target font resource!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- 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().get_basename() + ".fnt" );
- }
-
- if (dest->get_line_edit()->get_text().get_extension() == dest->get_line_edit()->get_text()) {
- dest->get_line_edit()->set_text(dest->get_line_edit()->get_text() + ".fnt");
- }
-
- if (dest->get_line_edit()->get_text().get_extension().to_lower() != "fnt") {
- error_dialog->set_text(TTR("Invalid file extension.\nPlease use .fnt."));
- error_dialog->popup_centered(Size2(200,100));
- return;
- }
-
- Ref<ResourceImportMetadata> rimd = get_rimd();
-
- if (rimd.is_null()) {
- error_dialog->set_text(TTR("Can't load/process source font."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- Error err = plugin->import(dest->get_line_edit()->get_text(),rimd);
-
- if (err!=OK) {
- error_dialog->set_text(TTR("Couldn't save font."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- _import_inc(dest->get_line_edit()->get_text());
-
- hide();
- }
-
- EditorFontImportPlugin *plugin;
- _EditorFontImportOptions *options;
-
- static void _bind_methods() {
-
- ClassDB::bind_method("_update",&EditorFontImportDialog::_update);
- ClassDB::bind_method("_update_text",&EditorFontImportDialog::_update_text);
- ClassDB::bind_method("_update_text2",&EditorFontImportDialog::_update_text2);
- ClassDB::bind_method("_update_text3",&EditorFontImportDialog::_update_text3);
- ClassDB::bind_method("_prop_changed",&EditorFontImportDialog::_prop_changed);
- ClassDB::bind_method("_src_changed",&EditorFontImportDialog::_src_changed);
- ClassDB::bind_method("_font_size_changed",&EditorFontImportDialog::_font_size_changed);
- ClassDB::bind_method("_import",&EditorFontImportDialog::_import);
-
- }
-
-public:
-
- void _notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- prop_edit->edit(options);
- _update_text();
- }
- }
-
- void popup_import(const String& p_path) {
-
- popup_centered(Size2(600,500)*EDSCALE);
-
- if (p_path!="") {
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
- ERR_FAIL_COND(!rimd.is_valid());
-
- dest->get_line_edit()->set_text(p_path);
- List<String> opts;
- rimd->get_options(&opts);
- options->reset();
- for(List<String>::Element *E=opts.front();E;E=E->next()) {
-
- options->_set(E->get(),rimd->get_option(E->get()));
- }
-
- String src = "";
- for(int i=0;i<rimd->get_source_count();i++) {
- if (i>0)
- src+=",";
- src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
- }
- source->get_line_edit()->set_text(src);
-
- font_size->set_value(rimd->get_option("font/size"));
- }
- }
-
-
- void set_source_and_dest(const String& p_font,const String& p_dest) {
- source->get_line_edit()->set_text(p_font);
- dest->get_line_edit()->set_text(p_dest);
- _prop_changed();
- }
-
- EditorFontImportDialog(EditorFontImportPlugin *p_plugin) {
- plugin=p_plugin;
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
- HBoxContainer *hbc = memnew( HBoxContainer);
- vbc->add_child(hbc);
- VBoxContainer *vbl = memnew( VBoxContainer );
- hbc->add_child(vbl);
- hbc->set_v_size_flags(SIZE_EXPAND_FILL);
- vbl->set_h_size_flags(SIZE_EXPAND_FILL);
- VBoxContainer *vbr = memnew( VBoxContainer );
- hbc->add_child(vbr);
- vbr->set_h_size_flags(SIZE_EXPAND_FILL);
-
- source = memnew( EditorLineEditFileChooser );
- source->get_file_dialog()->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- 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(TTR("Source Font:"),source);
- font_size = memnew( SpinBox );
- vbl->add_margin_child(TTR("Source Font Size:"),font_size);
- font_size->set_min(3);
- font_size->set_max(256);
- font_size->set_value(16);
- font_size->connect("value_changed",this,"_font_size_changed");
- dest = memnew( EditorLineEditFileChooser );
- //
- List<String> fl;
- Ref<BitmapFont> font= memnew(BitmapFont);
- dest->get_file_dialog()->add_filter("*.fnt ; Font" );
- /*
- ResourceSaver::get_recognized_extensions(font,&fl);
- for(List<String>::Element *E=fl.front();E;E=E->next()) {
- dest->get_file_dialog()->add_filter("*."+E->get());
- }
- */
-
- vbl->add_margin_child(TTR("Dest Resource:"),dest);
- HBoxContainer *testhb = memnew( HBoxContainer );
- test_string = memnew( LineEdit );
- test_string->set_text(TTR("The quick brown fox jumps over the lazy dog."));
- test_string->set_h_size_flags(SIZE_EXPAND_FILL);
- test_string->set_stretch_ratio(5);
-
- testhb->add_child(test_string);
- test_color = memnew( ColorPickerButton );
- test_color->set_pick_color(get_color("font_color","Label"));
- test_color->set_h_size_flags(SIZE_EXPAND_FILL);
- test_color->set_stretch_ratio(1);
- test_color->connect("color_changed",this,"_update_text3");
- testhb->add_child(test_color);
-
- vbl->add_spacer();
- vbl->add_margin_child(TTR("Test:")+" ",testhb);
- /*
- HBoxContainer *upd_hb = memnew( HBoxContainer );
- //vbl->add_child(upd_hb);
- upd_hb->add_spacer();
- Button *update = memnew( Button);
- upd_hb->add_child(update);
- update->set_text("Update");
- update->connect("pressed",this,"_update");
-*/
- options = memnew( _EditorFontImportOptions );
- prop_edit = memnew( PropertyEditor() );
- vbr->add_margin_child(TTR("Options:"),prop_edit,true);
- options->connect("changed",this,"_prop_changed");
-
- prop_edit->hide_top_label();
-
- Panel *panel = memnew( Panel );
- vbc->add_child(panel);
- test_label = memnew( Label );
- test_label->set_autowrap(true);
- panel->add_child(test_label);
- test_label->set_area_as_parent_rect();
- panel->set_v_size_flags(SIZE_EXPAND_FILL);
- test_string->connect("text_changed",this,"_update_text2");
- set_title(TTR("Font Import"));
- timer = memnew( Timer );
- add_child(timer);
- timer->connect("timeout",this,"_update");
- timer->set_wait_time(0.4);
- timer->set_one_shot(true);
-
- get_ok()->connect("pressed", this,"_import");
- get_ok()->set_text(TTR("Import"));
-
- error_dialog = memnew ( ConfirmationDialog );
- add_child(error_dialog);
- error_dialog->get_ok()->set_text(TTR("Accept"));
- set_hide_on_ok(false);
-
-
- }
-
- ~EditorFontImportDialog() {
- memdelete(options);
- }
-};
-
-
-///////////////////////////////////////
-
-
-
-struct _EditorFontData {
-
- Vector<uint8_t> bitmap;
- int width,height;
- int ofs_x; //ofset to center, from ABOVE
- int ofs_y; //ofset to begining, from LEFT
- int valign; //vertical alignment
- int halign;
- float advance;
- int character;
- int glyph;
-
- int texture;
- Image blit;
- Point2i blit_ofs;
- //bool printable;
-
-};
-
-
-struct _EditorFontDataSort {
-
- bool operator()(const _EditorFontData *p_A,const _EditorFontData *p_B) const {
- return p_A->height > p_B->height;
- };
-};
-
-struct _EditorKerningKey {
-
- CharType A,B;
- bool operator<(const _EditorKerningKey& p_k) const { return (A==p_k.A)?(B<p_k.B):(A<p_k.A); }
-
-};
-
-
-static unsigned char get_SDF_radial(
- unsigned char *fontmap,
- int w, int h,
- int x, int y,
- int max_radius )
-{
- //hideous brute force method
- float d2 = max_radius*max_radius+1.0;
- unsigned char v = fontmap[x+y*w];
- for( int radius = 1; (radius <= max_radius) && (radius*radius < d2); ++radius )
- {
- int line, lo, hi;
- //north
- line = y - radius;
- if( (line >= 0) && (line < h) )
- {
- lo = x - radius;
- hi = x + radius;
- if( lo < 0 ) { lo = 0; }
- if( hi >= w ) { hi = w-1; }
- int idx = line * w + lo;
- for( int i = lo; i <= hi; ++i )
- {
- //check this pixel
- if( fontmap[idx] != v )
- {
- float nx = i - x;
- float ny = line - y;
- float nd2 = nx*nx+ny*ny;
- if( nd2 < d2 )
- {
- d2 = nd2;
- }
- }
- //move on
- ++idx;
- }
- }
- //south
- line = y + radius;
- if( (line >= 0) && (line < h) )
- {
- lo = x - radius;
- hi = x + radius;
- if( lo < 0 ) { lo = 0; }
- if( hi >= w ) { hi = w-1; }
- int idx = line * w + lo;
- for( int i = lo; i <= hi; ++i )
- {
- //check this pixel
- if( fontmap[idx] != v )
- {
- float nx = i - x;
- float ny = line - y;
- float nd2 = nx*nx+ny*ny;
- if( nd2 < d2 )
- {
- d2 = nd2;
- }
- }
- //move on
- ++idx;
- }
- }
- //west
- line = x - radius;
- if( (line >= 0) && (line < w) )
- {
- lo = y - radius + 1;
- hi = y + radius - 1;
- if( lo < 0 ) { lo = 0; }
- if( hi >= h ) { hi = h-1; }
- int idx = lo * w + line;
- for( int i = lo; i <= hi; ++i )
- {
- //check this pixel
- if( fontmap[idx] != v )
- {
- float nx = line - x;
- float ny = i - y;
- float nd2 = nx*nx+ny*ny;
- if( nd2 < d2 )
- {
- d2 = nd2;
- }
- }
- //move on
- idx += w;
- }
- }
- //east
- line = x + radius;
- if( (line >= 0) && (line < w) )
- {
- lo = y - radius + 1;
- hi = y + radius - 1;
- if( lo < 0 ) { lo = 0; }
- if( hi >= h ) { hi = h-1; }
- int idx = lo * w + line;
- for( int i = lo; i <= hi; ++i )
- {
- //check this pixel
- if( fontmap[idx] != v )
- {
- float nx = line - x;
- float ny = i - y;
- float nd2 = nx*nx+ny*ny;
- if( nd2 < d2 )
- {
- d2 = nd2;
- }
- }
- //move on
- idx += w;
- }
- }
- }
- d2 = sqrtf( d2 );
- if( v==0 )
- {
- d2 = -d2;
- }
- d2 *= 127.5 / max_radius;
- d2 += 127.5;
- if( d2 < 0.0 ) d2 = 0.0;
- if( d2 > 255.0 ) d2 = 255.0;
- return (unsigned char)(d2 + 0.5);
-}
-
-
-Ref<BitmapFont> 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<BitmapFont>());
-
- String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
-
- if (src_path.get_extension().to_lower()=="fnt") {
-
- if (ResourceLoader::load(src_path).is_valid()) {
- EditorNode::get_singleton()->show_warning(TTR("Path:")+" "+src_path+"\n"+TTR("This file is already a Godot font file, please supply a BMFont type file instead."));
- return Ref<BitmapFont>();
- }
-
- Ref<BitmapFont> font;
- font.instance();
- Error err = font->create_from_fnt(src_path);
- if (err) {
- EditorNode::get_singleton()->show_warning(TTR("Path:")+" "+src_path+"\n"+TTR("Failed opening as BMFont file."));
- return Ref<BitmapFont>();
- }
-
- return font;
- }
-
- int size = from->get_option("font/size");
-
-#ifdef FREETYPE_ENABLED
- FT_Library library; /* handle to library */
- FT_Face face; /* handle to face object */
-
- Vector<_EditorFontData*> font_data_list;
-
- int error = FT_Init_FreeType( &library );
-
- ERR_EXPLAIN(TTR("Error initializing FreeType."));
- ERR_FAIL_COND_V( error !=0, Ref<BitmapFont>() );
-
- print_line("loadfrom: "+src_path);
- error = FT_New_Face( library, src_path.utf8().get_data(),0,&face );
-
- if ( error == FT_Err_Unknown_File_Format ) {
- ERR_EXPLAIN(TTR("Unknown font format."));
- FT_Done_FreeType( library );
- } else if ( error ) {
-
- ERR_EXPLAIN(TTR("Error loading font."));
- FT_Done_FreeType( library );
-
- }
-
- ERR_FAIL_COND_V(error,Ref<BitmapFont>());
-
-
- int height=0;
- int ascent=0;
- int font_spacing=0;
-
- error = FT_Set_Char_Size(face,0,64*size,512,512);
-
- if ( error ) {
- FT_Done_FreeType( library );
- ERR_EXPLAIN(TTR("Invalid font size."));
- ERR_FAIL_COND_V( error,Ref<BitmapFont>() );
-
- }
-
- int font_mode = from->get_option("mode/mode");
-
- int scaler=(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD)?16:1;
-
- error = FT_Set_Pixel_Sizes(face,0,size*scaler);
-
- FT_GlyphSlot slot = face->glyph;
-
- //error = FT_Set_Charmap(face,ft_encoding_unicode ); /* encoding.. */
-
-
- /* PRINT CHARACTERS TO INDIVIDUAL BITMAPS */
-
-
- //int space_size=5; //size for space, if none found.. 5!
- //int min_valign=500; //some ridiculous number
-
- FT_ULong charcode;
- FT_UInt gindex;
-
- int max_up=-1324345; ///gibberish
- int max_down=124232;
-
- Map<_EditorKerningKey,int> kerning_map;
-
- charcode = FT_Get_First_Char( face, &gindex );
-
- Set<CharType> import_chars;
-
- int import_mode = from->get_option("character_set/mode");
- bool round_advance = from->get_option("advanced/round_advance");
-
- if (import_mode>=_EditorFontImportOptions::CHARSET_CUSTOM) {
-
- //load from custom text
- String path = from->get_option("character_set/custom");
-
- FileAccess *fa = FileAccess::open(EditorImportPlugin::expand_source_path(path),FileAccess::READ);
-
- if ( !fa ) {
-
- FT_Done_FreeType( library );
- ERR_EXPLAIN(TTR("Invalid font custom source."));
- ERR_FAIL_COND_V( !fa,Ref<BitmapFont>() );
-
- }
-
-
- while(!fa->eof_reached()) {
-
- String line = fa->get_line();
- for(int i=0;i<line.length();i++) {
- import_chars.insert(line[i]);
- }
- }
-
- if (import_mode==_EditorFontImportOptions::CHARSET_CUSTOM_LATIN) {
-
- for(int i=32;i<128;i++)
- import_chars.insert(i);
- }
-
- memdelete(fa);
- }
-
- int xsize=0;
- while ( gindex != 0 )
- {
-
- bool skip=false;
- error = FT_Load_Char( face, charcode, font_mode==_EditorFontImportOptions::FONT_BITMAP?FT_LOAD_RENDER:FT_LOAD_MONOCHROME );
- if (error) skip=true;
- else error = FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono );
- if (error) {
- skip=true;
- } else if (!skip) {
-
- switch(import_mode) {
-
- case _EditorFontImportOptions::CHARSET_ASCII: skip = charcode>127; break;
- case _EditorFontImportOptions::CHARSET_LATIN: skip = charcode>255 ;break;
- case _EditorFontImportOptions::CHARSET_UNICODE: break; //none
- case _EditorFontImportOptions::CHARSET_CUSTOM:
- case _EditorFontImportOptions::CHARSET_CUSTOM_LATIN: skip = !import_chars.has(charcode); break;
-
- }
- }
-
- if (charcode<=32) //??
- skip=true;
-
- if (skip) {
- charcode=FT_Get_Next_Char(face,charcode,&gindex);
- continue;
- }
-
- _EditorFontData * fdata = memnew( _EditorFontData );
-
-
- int w = slot->bitmap.width;
- int h = slot->bitmap.rows;
- int p = slot->bitmap.pitch;
-
- //print_line("W: "+itos(w)+" P: "+itos(slot->bitmap.pitch));
-
- if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
-
- //oversize the holding buffer so I can smooth it!
- int sw = w + scaler * 4;
- int sh = h + scaler * 4;
- //do the SDF
- int sdfw = sw / scaler;
- int sdfh = sh / scaler;
-
- fdata->width=sdfw;
- fdata->height=sdfh;
- } else {
- fdata->width=w;
- fdata->height=h;
- }
-
- fdata->character=charcode;
- fdata->glyph=FT_Get_Char_Index(face,charcode);
- if (charcode=='x')
- xsize=w/scaler;
-
-
-
- fdata->valign=slot->bitmap_top;
- fdata->halign=slot->bitmap_left;
-
- if (round_advance)
- fdata->advance=(slot->advance.x+(1<<5))>>6;
- else
- fdata->advance=slot->advance.x/float(1<<6);
-
- if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
-
- fdata->halign = fdata->halign / scaler - 1.5;
- fdata->valign = fdata->valign / scaler + 1.5;
- fdata->advance/=scaler;
-
- }
-
- fdata->advance+=font_spacing;
-
-
- if (charcode<127) {
- int top = fdata->valign;
- int hmax = h/scaler;
-
- if (top>max_up) {
-
- max_up=top;
- }
-
-
- if ( (top - hmax)<max_down ) {
-
- max_down=top - hmax;
- }
- }
-
- if (font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD) {
-
-
- //oversize the holding buffer so I can smooth it!
- int sw = w + scaler * 4;
- int sh = h + scaler * 4;
-
- unsigned char *smooth_buf = new unsigned char[sw*sh];
-
- for( int i = 0; i < sw*sh; ++i ) {
- smooth_buf[i] = 0;
- }
-
- // copy the glyph into the buffer to be smoothed
- unsigned char *buf = slot->bitmap.buffer;
- for( int j = 0; j < h; ++j ) {
- for( int i = 0; i < w; ++i ) {
- smooth_buf[scaler*2+i+(j+scaler*2)*sw] = 255 * ((buf[j*p+(i>>3)] >> (7 - (i & 7))) & 1);
- }
- }
-
- // do the SDF
- int sdfw = fdata->width;
- int sdfh = fdata->height;
-
- fdata->bitmap.resize( sdfw*sdfh );
-
- for( int j = 0; j < sdfh; ++j ) {
- for( int i = 0; i < sdfw; ++i ) {
- int pd_idx = j*sdfw+i;
-
- //fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
-
- fdata->bitmap[pd_idx] =
- //get_SDF
- get_SDF_radial
- ( smooth_buf, sw, sh,
- i*scaler + (scaler >>1), j*scaler + (scaler >>1),
- 2*scaler );
-
- }
- }
-
- delete [] smooth_buf;
-
- } else {
- fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows );
- for (int i=0;i<slot->bitmap.width;i++) {
- for (int j=0;j<slot->bitmap.rows;j++) {
-
- fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
- }
- }
- }
-
- font_data_list.push_back(fdata);
- charcode=FT_Get_Next_Char(face,charcode,&gindex);
-// printf("reading char %i\n",charcode);
- }
-
- /* SPACE */
-
- _EditorFontData *spd = memnew( _EditorFontData );
- spd->advance=0;
- spd->character=' ';
- spd->halign=0;
- spd->valign=0;
- spd->width=0;
- spd->height=0;
- spd->ofs_x=0;
- spd->ofs_y=0;
-
- if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, font_mode==_EditorFontImportOptions::FONT_BITMAP?ft_render_mode_normal:ft_render_mode_mono )) {
-
- spd->advance = slot->advance.x>>6; //round to nearest or store as float
- spd->advance/=scaler;
- spd->advance+=font_spacing;
- } else {
-
- spd->advance=xsize;
- spd->advance+=font_spacing;
- }
-
- font_data_list.push_back(spd);
-
- Set<CharType> exported;
- for (int i=0; i<font_data_list.size(); i++) {
- exported.insert(font_data_list[i]->character);
- };
- int missing = 0;
- for(Set<CharType>::Element *E=import_chars.front();E;E=E->next()) {
- CharType c = E->get();
- if (!exported.has(c)) {
- CharType str[2] = {c, 0};
- printf("** Warning: character %i (%ls) not exported\n", (int)c, str);
- ++missing;
- };
- };
- print_line("total_chars: "+itos(font_data_list.size()));
-
- /* KERNING */
-
-
- for(int i=0;i<font_data_list.size();i++) {
-
- if (font_data_list[i]->character>512)
- continue;
- for(int j=0;j<font_data_list.size();j++) {
-
- if (font_data_list[j]->character>512)
- continue;
-
- FT_Vector delta;
- FT_Get_Kerning( face, font_data_list[i]->glyph,font_data_list[j]->glyph, FT_KERNING_DEFAULT, &delta );
-
- if (delta.x!=0) {
-
- _EditorKerningKey kpk;
- kpk.A = font_data_list[i]->character;
- kpk.B = font_data_list[j]->character;
- int kern = ((-delta.x)+(1<<5))>>6;
-
- if (kern==0)
- continue;
- kerning_map[kpk]=kern/scaler;
- }
- }
- }
-
- height=max_up-max_down;
- ascent=max_up;
-
- /* FIND OUT WHAT THE FONT HEIGHT FOR THIS IS */
-
- /* ADJUST THE VALIGN FOR EACH CHARACTER */
-
- for (int i=0;i<(int)font_data_list.size();i++) {
-
- font_data_list[i]->valign=max_up-font_data_list[i]->valign;
- }
-
-
-
- /* ADD THE SPACEBAR CHARACTER */
-/*
- _EditorFontData * fdata = new _EditorFontData;
-
- fdata->character=32;
- fdata->bitmap=0;
- fdata->width=xsize;
- fdata->height=1;
- fdata->valign=0;
-
- font_data_list.push_back(fdata);
-*/
- /* SORT BY HEIGHT, SO THEY FIT BETTER ON THE TEXTURE */
-
- font_data_list.sort_custom<_EditorFontDataSort>();
- Color *color=memnew_arr(Color,height);
-
- int gradient_type=from->get_option("color/mode");
- switch(gradient_type) {
- case _EditorFontImportOptions::COLOR_WHITE: {
-
- for(int i=0;i<height;i++){
- color[i]=Color(1,1,1,1);
- }
-
- } break;
- case _EditorFontImportOptions::COLOR_CUSTOM: {
-
- Color cc = from->get_option("color/color");
- for(int i=0;i<height;i++){
- color[i]=cc;
- }
-
- } break;
- case _EditorFontImportOptions::COLOR_GRADIENT_RANGE: {
-
- Color src=from->get_option("color/begin");
- Color to=from->get_option("color/end");
- for(int i=0;i<height;i++){
- color[i]=src.linear_interpolate(to,i/float(height));
- }
-
- } break;
- case _EditorFontImportOptions::COLOR_GRADIENT_IMAGE: {
-
- String fp = EditorImportPlugin::expand_source_path(from->get_option("color/image"));
- Image img;
- Error err = ImageLoader::load_image(fp,&img);
- if (err==OK) {
-
- for(int i=0;i<height;i++){
- //color[i]=img.get_pixel(0,i*img.get_height()/height);
- }
- } else {
-
- for(int i=0;i<height;i++){
- color[i]=Color(1,1,1,1);
- }
- }
-
- } break;
- }
-
-
- for(int i=0;i<font_data_list.size();i++) {
-
- if (font_data_list[i]->bitmap.size()==0)
- continue;
-
- int margin[4]={0,0,0,0};
-
- if (from->get_option("shadow/enabled").operator bool()) {
- int r=from->get_option("shadow/radius");
- Point2i ofs=Point2(from->get_option("shadow/offset"));
- margin[ MARGIN_LEFT ] = MAX( r - ofs.x, 0);
- margin[ MARGIN_RIGHT ] = MAX( r + ofs.x, 0);
- margin[ MARGIN_TOP ] = MAX( r - ofs.y, 0);
- margin[ MARGIN_BOTTOM ] = MAX( r + ofs.y, 0);
-
- }
-
- if (from->get_option("shadow2/enabled").operator bool()) {
- int r=from->get_option("shadow2/radius");
- Point2i ofs=Point2(from->get_option("shadow2/offset"));
- margin[ MARGIN_LEFT ] = MAX( r - ofs.x, margin[ MARGIN_LEFT ]);
- margin[ MARGIN_RIGHT ] = MAX( r + ofs.x, margin[ MARGIN_RIGHT ]);
- margin[ MARGIN_TOP ] = MAX( r - ofs.y, margin[ MARGIN_TOP ]);
- margin[ MARGIN_BOTTOM ] = MAX( r + ofs.y, margin[ MARGIN_BOTTOM ]);
-
- }
-
- Size2i s;
- s.width=font_data_list[i]->width+margin[MARGIN_LEFT]+margin[MARGIN_RIGHT];
- s.height=font_data_list[i]->height+margin[MARGIN_TOP]+margin[MARGIN_BOTTOM];
- Point2i o;
- o.x=margin[MARGIN_LEFT];
- o.y=margin[MARGIN_TOP];
-
- int ow=font_data_list[i]->width;
- int oh=font_data_list[i]->height;
-
- PoolVector<uint8_t> pixels;
- pixels.resize(s.x*s.y*4);
-
- PoolVector<uint8_t>::Write w = pixels.write();
- //print_line("val: "+itos(font_data_list[i]->valign));
- for(int y=0;y<s.height;y++) {
-
- int yc=CLAMP(y-o.y+font_data_list[i]->valign,0,height-1);
- Color c=color[yc];
- c.a=0;
-
- for(int x=0;x<s.width;x++) {
-
- int ofs=y*s.x+x;
- w[ofs*4+0]=c.r*255.0;
- w[ofs*4+1]=c.g*255.0;
- w[ofs*4+2]=c.b*255.0;
- w[ofs*4+3]=c.a*255.0;
- }
- }
-
-
- for(int si=0;si<2;si++) {
-
-#define S_VAR(m_v) (String(si==0?"shadow/":"shadow2/")+m_v)
- if (from->get_option(S_VAR("enabled")).operator bool()) {
- int r = from->get_option(S_VAR("radius"));
-
- Color sc = from->get_option(S_VAR("color"));
- Point2i so=Point2(from->get_option(S_VAR("offset")));
-
- float tr = from->get_option(S_VAR("transition"));
- print_line("shadow enabled: "+itos(si));
-
- Vector<uint8_t> s2buf;
- s2buf.resize(s.x*s.y);
- uint8_t *wa=s2buf.ptr();
-
- for(int j=0;j<s.x*s.y;j++){
-
- wa[j]=0;
- }
-
- // blit shadowa
- for(int x=0;x<ow;x++) {
- for(int y=0;y<oh;y++) {
- int ofs = (o.y+y+so.y)*s.x+x+o.x+so.x;
- wa[ofs]=font_data_list[i]->bitmap[y*ow+x];
- }
- }
- //blur shadow2 with separatable convolution
-
- if (r>0) {
-
- Vector<uint8_t> pixels2;
- pixels2.resize(s2buf.size());
- uint8_t *w2=pixels2.ptr();
- //vert
- for(int x=0;x<s.width;x++) {
- for(int y=0;y<s.height;y++) {
-
- int ofs = y*s.width+x;
- int sum=wa[ofs];
-
- for(int k=1;k<=r;k++) {
-
- int ofs_d=MIN(y+k,s.height-1)*s.width+x;
- int ofs_u=MAX(y-k,0)*s.width+x;
- sum+=wa[ofs_d];
- sum+=wa[ofs_u];
- }
-
- w2[ofs]=sum/(r*2+1);
-
- }
- }
- //horiz
- for(int x=0;x<s.width;x++) {
- for(int y=0;y<s.height;y++) {
-
- int ofs = y*s.width+x;
- int sum=w2[ofs];
-
- for(int k=1;k<=r;k++) {
-
- int ofs_r=MIN(x+k,s.width-1)+s.width*y;
- int ofs_l=MAX(x-k,0)+s.width*y;
- sum+=w2[ofs_r];
- sum+=w2[ofs_l];
- }
-
- wa[ofs]=Math::pow(float(sum/(r*2+1))/255.0f,tr)*255.0f;
-
- }
- }
-
- }
-
- //blend back
-
- for(int j=0;j<s.x*s.y;j++){
- Color wd(w[j*4+0]/255.0,w[j*4+1]/255.0,w[j*4+2]/255.0,w[j*4+3]/255.0);
- Color ws(sc.r,sc.g,sc.b,sc.a*(wa[j]/255.0));
- Color b = wd.blend(ws);
-
- w[j*4+0]=b.r*255.0;
- w[j*4+1]=b.g*255.0;
- w[j*4+2]=b.b*255.0;
- w[j*4+3]=b.a*255.0;
-
- }
- }
- }
-
- for(int y=0;y<oh;y++) {
- int yc=CLAMP(y+font_data_list[i]->valign,0,height-1);
- Color sc=color[yc];
- for(int x=0;x<ow;x++) {
- int ofs = (o.y+y)*s.x+x+o.x;
- float c = font_data_list[i]->bitmap[y*ow+x]/255.0;
- Color src_col=sc;
- src_col.a*=c;
- Color dst_col(w[ofs*4+0]/255.0,w[ofs*4+1]/255.0,w[ofs*4+2]/255.0,w[ofs*4+3]/255.0);
- dst_col = dst_col.blend(src_col);
- w[ofs*4+0]=dst_col.r*255.0;
- w[ofs*4+1]=dst_col.g*255.0;
- w[ofs*4+2]=dst_col.b*255.0;
- w[ofs*4+3]=dst_col.a*255.0;
- }
- }
-
-
- w=PoolVector<uint8_t>::Write();
-
- Image img(s.width,s.height,0,Image::FORMAT_RGBA8,pixels);
-
- font_data_list[i]->blit=img;
- font_data_list[i]->blit_ofs=o;
-
- }
-
- //make atlas
- int spacing=2;
- Vector<Size2i> sizes;
- sizes.resize(font_data_list.size());
- for(int i=0;i<font_data_list.size();i++) {
-
- sizes[i]=Size2(font_data_list[i]->blit.get_width()+spacing*2,font_data_list[i]->blit.get_height()+spacing*2);
-
- }
- Vector<Point2i> res;
- Size2i res_size;
- EditorAtlas::fit(sizes,res,res_size);
- res_size.x=nearest_power_of_2(res_size.x);
- res_size.y=nearest_power_of_2(res_size.y);
- print_line("Atlas size: "+res_size);
-
- Image atlas(res_size.x,res_size.y,0,Image::FORMAT_RGBA8);
-
- for(int i=0;i<font_data_list.size();i++) {
-
- if (font_data_list[i]->bitmap.size()==0)
- continue;
- atlas.blit_rect(font_data_list[i]->blit,Rect2(0,0,font_data_list[i]->blit.get_width(),font_data_list[i]->blit.get_height()),res[i]+Size2(spacing,spacing));
- font_data_list[i]->ofs_x=res[i].x+spacing;
- font_data_list[i]->ofs_y=res[i].y+spacing;
-
-
- }
-
- if (from->has_option("advanced/premultiply_alpha") && bool(from->get_option("advanced/premultiply_alpha"))) {
-
- PoolVector<uint8_t> data = atlas.get_data();
- int dl = data.size();
- {
- PoolVector<uint8_t>::Write w = data.write();
-
- for(int i=0;i<dl;i+=4) {
-
- w[i+0]= uint8_t(int(w[i+0])*int(w[i+3])/255);
- w[i+1]= uint8_t(int(w[i+1])*int(w[i+3])/255);
- w[i+2]= uint8_t(int(w[i+2])*int(w[i+3])/255);
- }
- }
-
- atlas=Image(res_size.x,res_size.y,0,Image::FORMAT_RGBA8,data);
- }
-
- if (from->has_option("color/monochrome") && bool(from->get_option("color/monochrome"))) {
-
- atlas.convert(Image::FORMAT_LA8);
- }
-
-
- if (0) {
- //debug the texture
- Ref<ImageTexture> atlast = memnew( ImageTexture );
- atlast->create_from_image(atlas);
- //atlast->create_from_image(font_data_list[5]->blit);
- TextureRect *tf = memnew( TextureRect );
- tf->set_texture(atlast);
- dialog->add_child(tf);
- }
-
-
- /* CREATE FONT */
-
- int char_space = from->get_option("extra_space/char");
- int space_space = from->get_option("extra_space/space");
- int top_space = from->get_option("extra_space/top");
- int bottom_space = from->get_option("extra_space/bottom");
- bool enable_filter = from->get_option("advanced/enable_filter");
- if (from->has_option("advanced/disable_filter")){ // this is a compatibility check for a deprecated option
- enable_filter = !from->get_option("advanced/disable_filter");
- }
-
- Ref<BitmapFont> font;
-
- if (p_existing!=String() && ResourceCache::has(p_existing)) {
-
- font = Ref<BitmapFont>( ResourceCache::get(p_existing)->cast_to<BitmapFont>());
- }
-
- if (font.is_null()) {
- font = Ref<BitmapFont>( memnew( BitmapFont ) );
- }
-
- font->clear();
- font->set_height(height+bottom_space+top_space);
- font->set_ascent(ascent+top_space);
- font->set_distance_field_hint(font_mode==_EditorFontImportOptions::FONT_DISTANCE_FIELD);
-
- //register texures
- {
- Ref<ImageTexture> t = memnew(ImageTexture);
- int flags;
- if (!enable_filter)
- flags=0;
- else
- flags=Texture::FLAG_FILTER;
- t->create_from_image(atlas,flags);
- t->set_storage( ImageTexture::STORAGE_COMPRESS_LOSSLESS );
- font->add_texture(t);
-
- }
- //register characters
-
-
- for(int i=0;i<font_data_list.size();i++) {
- _EditorFontData *fd=font_data_list[i];
- int tex_idx=0;
-
- font->add_char(fd->character,tex_idx,Rect2( fd->ofs_x, fd->ofs_y, fd->blit.get_width(), fd->blit.get_height()),Point2(fd->halign-fd->blit_ofs.x,fd->valign-fd->blit_ofs.y+top_space), fd->advance+char_space+(fd->character==' '?space_space:0));
- memdelete(fd);
- }
-
- for(Map<_EditorKerningKey,int>::Element *E=kerning_map.front();E;E=E->next()) {
-
- font->add_kerning_pair(E->key().A,E->key().B,E->get());
- }
-
- FT_Done_FreeType( library );
-
- return font;
-#else
-
- return Ref<BitmapFont>();
-#endif
-}
-
-
-String EditorFontImportPlugin::get_name() const {
-
- return "font";
-}
-String EditorFontImportPlugin::get_visible_name() const{
-
- return TTR("Font");
-}
-void EditorFontImportPlugin::import_dialog(const String& p_from){
-
- dialog->popup_import(p_from);
-}
-Error EditorFontImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
-
-
- Ref<BitmapFont> font = EditorFontImportPlugin::generate_font(p_from,p_path);
- if (!font.is_valid())
- return ERR_CANT_CREATE;
-
- Ref<ResourceImportMetadata> from=p_from;
- from->set_source_md5(0,FileAccess::get_md5(EditorImportPlugin::expand_source_path(from->get_source_path(0))));
- from->set_editor(get_name());
- font->set_import_metadata(from);
-
- return ResourceSaver::save(p_path,font);
-
-}
-
-void EditorFontImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
-
- for(int i=0;i<p_drop.size();i++) {
- String ext = p_drop[i].get_extension().to_lower();
- String file = p_drop[i].get_file();
- if (ext=="ttf" || ext=="otf" || ext=="fnt") {
-
- import_dialog();
- dialog->set_source_and_dest(p_drop[i],p_dest_path.plus_file(file.get_basename()+".fnt"));
- break;
- }
- }
-}
-
-
-EditorFontImportPlugin::EditorFontImportPlugin(EditorNode* p_editor) {
-
- dialog = memnew( EditorFontImportDialog(this) );
- p_editor->get_gui_base()->add_child(dialog);
-}
-#endif
diff --git a/tools/editor/io_plugins/editor_font_import_plugin.h b/tools/editor/io_plugins/editor_font_import_plugin.h
deleted file mode 100644
index a5b265736f..0000000000
--- a/tools/editor/io_plugins/editor_font_import_plugin.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*************************************************************************/
-/* editor_font_import_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_FONT_IMPORT_PLUGIN_H
-#define EDITOR_FONT_IMPORT_PLUGIN_H
-
-#include "tools/editor/editor_import_export.h"
-#include "scene/resources/font.h"
-#if 0
-class EditorNode;
-class EditorFontImportDialog;
-
-class EditorFontImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorFontImportPlugin,EditorImportPlugin);
-
- EditorFontImportDialog *dialog;
-public:
-
- Ref<BitmapFont> generate_font(const Ref<ResourceImportMetadata>& p_from,const String& p_existing=String()); //used by editor
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
- virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
-
-
- EditorFontImportPlugin(EditorNode* p_editor);
-};
-
-#endif // EDITOR_FONT_IMPORT_PLUGIN_H
-#endif
diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp
deleted file mode 100644
index fc3f8fd8c9..0000000000
--- a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp
+++ /dev/null
@@ -1,593 +0,0 @@
-/*************************************************************************/
-/* editor_mesh_import_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_mesh_import_plugin.h"
-
-#if 0
-
-#include "tools/editor/editor_file_dialog.h"
-#include "tools/editor/editor_dir_dialog.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/property_editor.h"
-//#include "scene/resources/sample.h"
-#include "io/resource_saver.h"
-#include "os/file_access.h"
-#include "io/marshalls.h"
-#include "scene/resources/surface_tool.h"
-
-class _EditorMeshImportOptions : public Object {
-
- GDCLASS(_EditorMeshImportOptions,Object);
-public:
-
-
- bool generate_tangents;
- bool generate_normals;
- bool flip_faces;
- bool smooth_shading;
- bool weld_vertices;
- bool import_material;
- bool import_textures;
- float weld_tolerance;
-
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- String n = p_name;
- if (n=="generate/tangents")
- generate_tangents=p_value;
- else if (n=="generate/normals")
- generate_normals=p_value;
- else if (n=="import/materials")
- import_material=p_value;
- else if (n=="import/textures")
- import_textures=p_value;
- else if (n=="force/flip_faces")
- flip_faces=p_value;
- else if (n=="force/smooth_shading")
- smooth_shading=p_value;
- else if (n=="force/weld_vertices")
- weld_vertices=p_value;
- else if (n=="force/weld_tolerance")
- weld_tolerance=p_value;
- else
- return false;
-
- return true;
-
- }
-
- bool _get(const StringName& p_name,Variant &r_ret) const{
-
- String n = p_name;
- if (n=="generate/tangents")
- r_ret=generate_tangents;
- else if (n=="generate/normals")
- r_ret=generate_normals;
- else if (n=="import/materials")
- r_ret=import_material;
- else if (n=="import/textures")
- r_ret=import_textures;
- else if (n=="force/flip_faces")
- r_ret=flip_faces;
- else if (n=="force/smooth_shading")
- r_ret=smooth_shading;
- else if (n=="force/weld_vertices")
- r_ret=weld_vertices;
- else if (n=="force/weld_tolerance")
- r_ret=weld_tolerance;
- else
- return false;
-
- return true;
-
- }
- void _get_property_list( List<PropertyInfo> *p_list) const{
-
- p_list->push_back(PropertyInfo(Variant::BOOL,"generate/tangents"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"generate/normals"));
- //not for nowp
- //p_list->push_back(PropertyInfo(Variant::BOOL,"import/materials"));
- //p_list->push_back(PropertyInfo(Variant::BOOL,"import/textures"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"force/flip_faces"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"force/smooth_shading"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"force/weld_vertices"));
- p_list->push_back(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001"));
- //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable"));
- //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
-
-
- }
-
-
- static void _bind_methods() {
-
-
- ADD_SIGNAL( MethodInfo("changed"));
- }
-
-
- _EditorMeshImportOptions() {
-
- generate_tangents=true;
- generate_normals=false;
- flip_faces=false;
- smooth_shading=false;
- weld_vertices=true;
- weld_tolerance=0.0001;
- import_material=false;
- import_textures=false;
-
- }
-
-
-};
-
-class EditorMeshImportDialog : public ConfirmationDialog {
-
- GDCLASS(EditorMeshImportDialog,ConfirmationDialog);
-
- EditorMeshImportPlugin *plugin;
-
- LineEdit *import_path;
- LineEdit *save_path;
- EditorFileDialog *file_select;
- EditorDirDialog *save_select;
- AcceptDialog *error_dialog;
- PropertyEditor *option_editor;
-
- _EditorMeshImportOptions *options;
-
-
-public:
-
- void _choose_files(const Vector<String>& p_path) {
-
- String files;
- for(int i=0;i<p_path.size();i++) {
-
- if (i>0)
- files+=",";
- files+=p_path[i];
- }
- /*
- if (p_path.size()) {
- String srctex=p_path[0];
- String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
-
- if (ipath!="")
- save_path->set_text(ipath.get_base_dir());
- }*/
- import_path->set_text(files);
-
- }
- void _choose_save_dir(const String& p_path) {
-
- save_path->set_text(p_path);
- }
-
- void _browse() {
-
- file_select->popup_centered_ratio();
- }
-
- void _browse_target() {
-
- save_select->popup_centered_ratio();
- }
-
- void popup_import(const String& p_path) {
-
- popup_centered(Size2(400,400)*EDSCALE);
-
- if (p_path!="") {
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
- ERR_FAIL_COND(!rimd.is_valid());
-
- save_path->set_text(p_path.get_base_dir());
- List<String> opts;
- rimd->get_options(&opts);
- for(List<String>::Element *E=opts.front();E;E=E->next()) {
-
- options->_set(E->get(),rimd->get_option(E->get()));
- }
-
- String src = "";
- for(int i=0;i<rimd->get_source_count();i++) {
- if (i>0)
- src+=",";
- src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
- }
- import_path->set_text(src);
- }
- }
-
- void _import() {
-
- Vector<String> meshes = import_path->get_text().split(",");
- if (meshes.size()==0) {
- error_dialog->set_text(TTR("No meshes to import!"));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- String dst = save_path->get_text();
- if (dst=="") {
- error_dialog->set_text(TTR("Save path is empty!"));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- for(int i=0;i<meshes.size();i++) {
-
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
-
- List<PropertyInfo> pl;
- options->_get_property_list(&pl);
- for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
-
- Variant v;
- String opt=E->get().name;
- options->_get(opt,v);
- imd->set_option(opt,v);
-
- }
-
- imd->add_source(EditorImportPlugin::validate_source_path(meshes[i]));
-
- String file_path = dst.plus_file(meshes[i].get_file().get_basename()+".msh");
-
- plugin->import(file_path,imd);
- }
-
- hide();
- }
-
- void _notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- option_editor->edit(options);
- }
- }
-
- static void _bind_methods() {
-
- ClassDB::bind_method("_choose_files",&EditorMeshImportDialog::_choose_files);
- ClassDB::bind_method("_choose_save_dir",&EditorMeshImportDialog::_choose_save_dir);
- ClassDB::bind_method("_import",&EditorMeshImportDialog::_import);
- ClassDB::bind_method("_browse",&EditorMeshImportDialog::_browse);
- ClassDB::bind_method("_browse_target",&EditorMeshImportDialog::_browse_target);
- }
-
- EditorMeshImportDialog(EditorMeshImportPlugin *p_plugin) {
-
- plugin=p_plugin;
-
- set_title(TTR("Single Mesh Import"));
- set_hide_on_ok(false);
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Source Mesh(es):"),hbc);
-
- import_path = memnew( LineEdit );
- import_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(import_path);
-
- Button * import_choose = memnew( Button );
- import_choose->set_text(" .. ");
- hbc->add_child(import_choose);
-
- import_choose->connect("pressed", this,"_browse");
-
- hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Target Path:"),hbc);
-
- save_path = memnew( LineEdit );
- save_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(save_path);
-
- Button * save_choose = memnew( Button );
- save_choose->set_text(" .. ");
- hbc->add_child(save_choose);
-
- save_choose->connect("pressed", this,"_browse_target");
-
- file_select = memnew( EditorFileDialog );
- file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
- file_select->add_filter("*.obj ; Wavefront OBJ");
- add_child(file_select);
- file_select->connect("files_selected", this,"_choose_files");
-
- save_select = memnew( EditorDirDialog );
- add_child(save_select);
- save_select->connect("dir_selected", this,"_choose_save_dir");
-
- get_ok()->connect("pressed", this,"_import");
- get_ok()->set_text(TTR("Import"));
-
- error_dialog = memnew( AcceptDialog );
- add_child(error_dialog);
-
- options = memnew( _EditorMeshImportOptions );
-
- option_editor = memnew( PropertyEditor );
- option_editor->hide_top_label();
- vbc->add_margin_child(TTR("Options:"),option_editor,true);
- }
-
- ~EditorMeshImportDialog() {
- memdelete(options);
- }
-
-};
-
-
-String EditorMeshImportPlugin::get_name() const {
-
- return "mesh";
-}
-String EditorMeshImportPlugin::get_visible_name() const{
-
- return TTR("Mesh");
-}
-void EditorMeshImportPlugin::import_dialog(const String& p_from){
-
- dialog->popup_import(p_from);
-}
-Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
-
-
- ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER);
-
- Ref<ResourceImportMetadata> from=p_from;
-
- String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
- FileAccessRef f = FileAccess::open(src_path,FileAccess::READ);
- ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
-
- Ref<Mesh> mesh;
- Map<String,Ref<Material> > name_map;
-
- if (FileAccess::exists(p_path)) {
- mesh=ResourceLoader::load(p_path,"Mesh");
- if (mesh.is_valid()) {
- for(int i=0;i<mesh->get_surface_count();i++) {
-
- if (!mesh->surface_get_material(i).is_valid())
- continue;
- String name;
- if (mesh->surface_get_name(i)!="")
- name=mesh->surface_get_name(i);
- else
- name=vformat(TTR("Surface %d"),i+1);
-
- name_map[name]=mesh->surface_get_material(i);
- }
-
- while(mesh->get_surface_count()) {
- mesh->surface_remove(0);
- }
- }
- }
-
- if (!mesh.is_valid())
- mesh = Ref<Mesh>( memnew( Mesh ) );
-
-
- bool generate_normals=from->get_option("generate/normals");
- bool generate_tangents=from->get_option("generate/tangents");
- bool flip_faces=from->get_option("force/flip_faces");
- bool force_smooth=from->get_option("force/smooth_shading");
- bool weld_vertices=from->get_option("force/weld_vertices");
- float weld_tolerance=from->get_option("force/weld_tolerance");
- Vector<Vector3> vertices;
- Vector<Vector3> normals;
- Vector<Vector2> uvs;
- String name;
-
- Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ;
- surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
- if (force_smooth)
- surf_tool->add_smooth_group(true);
- int has_index_data=false;
-
- while(true) {
-
-
- String l = f->get_line().strip_edges();
-
- if (l.begins_with("v ")) {
- //vertex
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
- Vector3 vtx;
- vtx.x=v[1].to_float();
- vtx.y=v[2].to_float();
- vtx.z=v[3].to_float();
- vertices.push_back(vtx);
- } else if (l.begins_with("vt ")) {
- //uv
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
- Vector2 uv;
- uv.x=v[1].to_float();
- uv.y=1.0-v[2].to_float();
- uvs.push_back(uv);
-
- } else if (l.begins_with("vn ")) {
- //normal
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
- Vector3 nrm;
- nrm.x=v[1].to_float();
- nrm.y=v[2].to_float();
- nrm.z=v[3].to_float();
- normals.push_back(nrm);
- } if (l.begins_with("f ")) {
- //vertex
-
- has_index_data=true;
- Vector<String> v = l.split(" ",false);
- ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA);
-
- //not very fast, could be sped up
-
-
- Vector<String> face[3];
- face[0] = v[1].split("/");
- face[1] = v[2].split("/");
- ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR);
- ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR);
- for(int i=2;i<v.size()-1;i++) {
-
- face[2] = v[i+1].split("/");
- ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR);
- for(int j=0;j<3;j++) {
-
- int idx=j;
-
- if (!flip_faces && idx<2) {
- idx=1^idx;
- }
-
-
- if (face[idx].size()==3) {
- int norm = face[idx][2].to_int()-1;
- ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR);
- surf_tool->add_normal(normals[norm]);
- }
-
- if (face[idx].size()>=2 && face[idx][1]!=String()) {
-
- int uv = face[idx][1].to_int()-1;
- ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR);
- surf_tool->add_uv(uvs[uv]);
- }
-
- int vtx = face[idx][0].to_int()-1;
- ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR);
-
- Vector3 vertex = vertices[vtx];
- if (weld_vertices)
- vertex=vertex.snapped(weld_tolerance);
- surf_tool->add_vertex(vertex);
- }
-
- face[1]=face[2];
- }
- } else if (l.begins_with("s ") && !force_smooth) { //smoothing
- String what = l.substr(2,l.length()).strip_edges();
- if (what=="off")
- surf_tool->add_smooth_group(false);
- else
- surf_tool->add_smooth_group(true);
-
- } else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done
-
- if (has_index_data) {
- //new object/surface
- if (generate_normals || force_smooth)
- surf_tool->generate_normals();
- if (uvs.size() && (normals.size() || generate_normals) && generate_tangents)
- surf_tool->generate_tangents();
-
- surf_tool->index();
- mesh = surf_tool->commit(mesh);
- if (name=="")
- name=vformat(TTR("Surface %d"),mesh->get_surface_count()-1);
- mesh->surface_set_name(mesh->get_surface_count()-1,name);
- name="";
- surf_tool->clear();
- surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES);
- if (force_smooth)
- surf_tool->add_smooth_group(true);
-
- has_index_data=false;
-
- if (f->eof_reached())
- break;
- }
-
- if (l.begins_with("o ")) //name
- name=l.substr(2,l.length()).strip_edges();
- }
- }
-
-
- from->set_source_md5(0,FileAccess::get_md5(src_path));
- from->set_editor(get_name());
- mesh->set_import_metadata(from);
-
- //re-apply materials if exist
- for(int i=0;i<mesh->get_surface_count();i++) {
-
- String n = mesh->surface_get_name(i);
- if (name_map.has(n))
- mesh->surface_set_material(i,name_map[n]);
- }
-
- Error err = ResourceSaver::save(p_path,mesh);
-
- return err;
-}
-
-
-void EditorMeshImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
-
-
- Vector<String> files;
- for(int i=0;i<p_drop.size();i++) {
- String ext = p_drop[i].get_extension().to_lower();
- String file = p_drop[i].get_file();
- if (ext=="obj") {
-
- files.push_back(p_drop[i]);
- }
- }
-
- if (files.size()) {
- import_dialog();
- dialog->_choose_files(files);
- dialog->_choose_save_dir(p_dest_path);
- }
-}
-
-EditorMeshImportPlugin::EditorMeshImportPlugin(EditorNode* p_editor) {
-
- dialog = memnew( EditorMeshImportDialog(this));
- p_editor->get_gui_base()->add_child(dialog);
-}
-#endif
diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.h b/tools/editor/io_plugins/editor_mesh_import_plugin.h
deleted file mode 100644
index ba8ec58191..0000000000
--- a/tools/editor/io_plugins/editor_mesh_import_plugin.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*************************************************************************/
-/* editor_mesh_import_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_MESH_IMPORT_PLUGIN_H
-#define EDITOR_MESH_IMPORT_PLUGIN_H
-
-#if 0
-#include "tools/editor/editor_import_export.h"
-#include "scene/resources/font.h"
-
-class EditorNode;
-class EditorMeshImportDialog;
-
-class EditorMeshImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorMeshImportPlugin,EditorImportPlugin);
-
- EditorMeshImportDialog *dialog;
-
-
-public:
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
- void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
-
-
- EditorMeshImportPlugin(EditorNode* p_editor);
-};
-
-#endif
-#endif // EDITOR_MESH_IMPORT_PLUGIN_H
diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp
deleted file mode 100644
index 631291ec1b..0000000000
--- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp
+++ /dev/null
@@ -1,929 +0,0 @@
-/*************************************************************************/
-/* editor_sample_import_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_sample_import_plugin.h"
-
-#include "tools/editor/editor_file_dialog.h"
-#include "tools/editor/editor_dir_dialog.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/property_editor.h"
-#include "io/resource_saver.h"
-#include "os/file_access.h"
-#include "io/marshalls.h"
-#include "tools/editor/editor_settings.h"
-
-#if 0
-
-class _EditorSampleImportOptions : public Object {
-
- GDCLASS(_EditorSampleImportOptions,Object);
-public:
-
- enum CompressMode {
- COMPRESS_MODE_DISABLED,
- COMPRESS_MODE_RAM,
- COMPRESS_MODE_DISK
- };
-
- enum CompressBitrate {
- COMPRESS_64,
- COMPRESS_96,
- COMPRESS_128,
- COMPRESS_192
- };
-
- bool force_8_bit;
- bool force_mono;
- bool force_rate;
- float force_rate_hz;
-
- bool edit_trim;
- bool edit_normalize;
- bool edit_loop;
-
- CompressMode compress_mode;
- CompressBitrate compress_bitrate;
-
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- String n = p_name;
- if (n=="force/8_bit")
- force_8_bit=p_value;
- else if (n=="force/mono")
- force_mono=p_value;
- else if (n=="force/max_rate")
- force_rate=p_value;
- else if (n=="force/max_rate_hz")
- force_rate_hz=p_value;
- else if (n=="edit/trim")
- edit_trim=p_value;
- else if (n=="edit/normalize")
- edit_normalize=p_value;
- else if (n=="edit/loop")
- edit_loop=p_value;
- else if (n=="compress/mode")
- compress_mode=CompressMode(int(p_value));
- else if (n=="compress/bitrate")
- compress_bitrate=CompressBitrate(int(p_value));
- else
- return false;
-
- return true;
-
- }
-
- bool _get(const StringName& p_name,Variant &r_ret) const{
-
- String n = p_name;
- if (n=="force/8_bit")
- r_ret=force_8_bit;
- else if (n=="force/mono")
- r_ret=force_mono;
- else if (n=="force/max_rate")
- r_ret=force_rate;
- else if (n=="force/max_rate_hz")
- r_ret=force_rate_hz;
- else if (n=="edit/trim")
- r_ret=edit_trim;
- else if (n=="edit/normalize")
- r_ret=edit_normalize;
- else if (n=="edit/loop")
- r_ret=edit_loop;
- else if (n=="compress/mode")
- r_ret=compress_mode;
- else if (n=="compress/bitrate")
- r_ret=compress_bitrate;
- else
- return false;
-
- return true;
-
- }
- void _get_property_list( List<PropertyInfo> *p_list) const{
-
- p_list->push_back(PropertyInfo(Variant::BOOL,"force/8_bit"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"force/mono"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"force/max_rate"));
- p_list->push_back(PropertyInfo(Variant::REAL,"force/max_rate_hz",PROPERTY_HINT_EXP_RANGE,"11025,192000,1"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"edit/trim"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"edit/normalize"));
- p_list->push_back(PropertyInfo(Variant::BOOL,"edit/loop"));
- p_list->push_back(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)"));
- //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192"));
-
-
- }
-
-
- static void _bind_methods() {
-
-
- ADD_SIGNAL( MethodInfo("changed"));
- }
-
-
- _EditorSampleImportOptions() {
-
- force_8_bit=false;
- force_mono=false;
- force_rate=true;
- force_rate_hz=44100;
-
- edit_trim=true;
- edit_normalize=true;
- edit_loop=false;
-
- compress_mode=COMPRESS_MODE_RAM;
- compress_bitrate=COMPRESS_128;
- }
-
-
-};
-
-class EditorSampleImportDialog : public ConfirmationDialog {
-
- GDCLASS(EditorSampleImportDialog,ConfirmationDialog);
-
- EditorSampleImportPlugin *plugin;
-
- LineEdit *import_path;
- LineEdit *save_path;
- EditorFileDialog *file_select;
- EditorDirDialog *save_select;
- ConfirmationDialog *error_dialog;
- PropertyEditor *option_editor;
-
- _EditorSampleImportOptions *options;
-
-
-public:
-
- void _choose_files(const Vector<String>& p_path) {
-
- String files;
- for(int i=0;i<p_path.size();i++) {
-
- if (i>0)
- files+=",";
- files+=p_path[i];
- }
- /*
- if (p_path.size()) {
- String srctex=p_path[0];
- String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
-
- if (ipath!="")
- save_path->set_text(ipath.get_base_dir());
- }*/
- import_path->set_text(files);
-
- }
- void _choose_save_dir(const String& p_path) {
-
- save_path->set_text(p_path);
- }
-
- void _browse() {
-
- file_select->popup_centered_ratio();
- }
-
- void _browse_target() {
-
- save_select->popup_centered_ratio();
-
- }
-
-
- void popup_import(const String& p_path) {
-
- popup_centered(Size2(400,400)*EDSCALE);
- if (p_path!="") {
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
- ERR_FAIL_COND(!rimd.is_valid());
-
- save_path->set_text(p_path.get_base_dir());
- List<String> opts;
- rimd->get_options(&opts);
- for(List<String>::Element *E=opts.front();E;E=E->next()) {
-
- options->_set(E->get(),rimd->get_option(E->get()));
- }
-
- String src = "";
- for(int i=0;i<rimd->get_source_count();i++) {
- if (i>0)
- src+=",";
- src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
- }
- import_path->set_text(src);
- }
- }
-
-
- void _import() {
-
- Vector<String> samples = import_path->get_text().split(",");
-
- if (samples.size()==0) {
- error_dialog->set_text(TTR("No samples to import!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- }
-
- if (save_path->get_text().strip_edges()=="") {
- error_dialog->set_text(TTR("Target path is empty."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (!save_path->get_text().begins_with("res://")) {
- error_dialog->set_text(TTR("Target path must be a complete resource path."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (!DirAccess::exists(save_path->get_text())) {
- error_dialog->set_text(TTR("Target path must exist."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- for(int i=0;i<samples.size();i++) {
-
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
-
- List<PropertyInfo> pl;
- options->_get_property_list(&pl);
- for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
-
- Variant v;
- String opt=E->get().name;
- options->_get(opt,v);
- imd->set_option(opt,v);
-
- }
-
- imd->add_source(EditorImportPlugin::validate_source_path(samples[i]));
-
- String dst = save_path->get_text();
- if (dst=="") {
- error_dialog->set_text(TTR("Save path is empty!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- }
-
- dst = dst.plus_file(samples[i].get_file().get_basename()+".smp");
-
- plugin->import(dst,imd);
- }
-
- hide();
-
- }
-
-
- void _notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- option_editor->edit(options);
- }
- }
-
- static void _bind_methods() {
-
-
- ClassDB::bind_method("_choose_files",&EditorSampleImportDialog::_choose_files);
- ClassDB::bind_method("_choose_save_dir",&EditorSampleImportDialog::_choose_save_dir);
- ClassDB::bind_method("_import",&EditorSampleImportDialog::_import);
- ClassDB::bind_method("_browse",&EditorSampleImportDialog::_browse);
- ClassDB::bind_method("_browse_target",&EditorSampleImportDialog::_browse_target);
- //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
- }
-
- EditorSampleImportDialog(EditorSampleImportPlugin *p_plugin) {
-
- plugin=p_plugin;
-
-
- set_title(TTR("Import Audio Samples"));
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
-
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Source Sample(s):"),hbc);
-
- import_path = memnew( LineEdit );
- import_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(import_path);
-
- Button * import_choose = memnew( Button );
- import_choose->set_text(" .. ");
- hbc->add_child(import_choose);
-
- import_choose->connect("pressed", this,"_browse");
-
- hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Target Path:"),hbc);
-
- save_path = memnew( LineEdit );
- save_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(save_path);
-
- Button * save_choose = memnew( Button );
- save_choose->set_text(" .. ");
- hbc->add_child(save_choose);
-
- save_choose->connect("pressed", this,"_browse_target");
-
- file_select = memnew(EditorFileDialog);
- file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- add_child(file_select);
- file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
- file_select->connect("files_selected", this,"_choose_files");
- file_select->add_filter("*.wav ; MS Waveform");
- save_select = memnew( EditorDirDialog );
- add_child(save_select);
-
- //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
- save_select->connect("dir_selected", this,"_choose_save_dir");
-
- get_ok()->connect("pressed", this,"_import");
- get_ok()->set_text(TTR("Import"));
-
-
- error_dialog = memnew ( ConfirmationDialog );
- add_child(error_dialog);
- error_dialog->get_ok()->set_text(TTR("Accept"));
- //error_dialog->get_cancel()->hide();
-
- set_hide_on_ok(false);
- options = memnew( _EditorSampleImportOptions );
-
- option_editor = memnew( PropertyEditor );
- option_editor->hide_top_label();
- vbc->add_margin_child(TTR("Options:"),option_editor,true);
- }
-
- ~EditorSampleImportDialog() {
- memdelete(options);
- }
-
-};
-
-
-String EditorSampleImportPlugin::get_name() const {
-
- return "sample";
-}
-String EditorSampleImportPlugin::get_visible_name() const{
-
- return TTR("Audio Sample");
-}
-void EditorSampleImportPlugin::import_dialog(const String& p_from){
-
- dialog->popup_import(p_from);
-}
-Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
-
- ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER);
-
- Ref<ResourceImportMetadata> from=p_from;
-
- String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
- Ref<Sample> smp = ResourceLoader::load(src_path);
- ERR_FAIL_COND_V(smp.is_null(),ERR_CANT_OPEN);
-
-
- float rate = smp->get_mix_rate();
- bool is16 = smp->get_format()==Sample::FORMAT_PCM16;
- int chans = smp->is_stereo()?2:1;
- int len = smp->get_length();
- Sample::LoopFormat loop= smp->get_loop_format();
- int loop_beg = smp->get_loop_begin();
- int loop_end = smp->get_loop_end();
-
- print_line("Input Sample: ");
- print_line("\tlen: "+itos(len));
- print_line("\tchans: "+itos(chans));
- print_line("\t16bits: "+itos(is16));
- print_line("\trate: "+itos(rate));
- print_line("\tloop: "+itos(loop));
- print_line("\tloop begin: "+itos(loop_beg));
- print_line("\tloop end: "+itos(loop_end));
- Vector<float> data;
- data.resize(len*chans);
-
- {
- PoolVector<uint8_t> src_data = smp->get_data();
- PoolVector<uint8_t>::Read sr = src_data.read();
-
-
- for(int i=0;i<len*chans;i++) {
-
- float s=0;
- if (is16) {
-
- int16_t i16 = decode_uint16(&sr[i*2]);
- s=i16/32767.0;
- } else {
-
- int8_t i8 = sr[i];
- s=i8/127.0;
- }
- data[i]=s;
- }
- }
-
- //apply frequency limit
-
- bool limit_rate = from->get_option("force/max_rate");
- int limit_rate_hz = from->get_option("force/max_rate_hz");
- if (limit_rate && rate > limit_rate_hz) {
- //resampleeee!!!
- int new_data_len = len * limit_rate_hz / rate;
- Vector<float> new_data;
- new_data.resize( new_data_len * chans );
- for(int c=0;c<chans;c++) {
-
- for(int i=0;i<new_data_len;i++) {
-
- //simple cubic interpolation should be enough.
- float pos = float(i) * len / new_data_len;
- float mu = pos-Math::floor(pos);
- int ipos = int(Math::floor(pos));
-
- float y0=data[MAX(0,ipos-1)*chans+c];
- float y1=data[ipos*chans+c];
- float y2=data[MIN(len-1,ipos+1)*chans+c];
- float y3=data[MIN(len-1,ipos+2)*chans+c];
-
- float mu2 = mu*mu;
- float a0 = y3 - y2 - y0 + y1;
- float a1 = y0 - y1 - a0;
- float a2 = y2 - y0;
- float a3 = y1;
-
- float res=(a0*mu*mu2+a1*mu2+a2*mu+a3);
-
- new_data[i*chans+c]=res;
- }
- }
-
- if (loop) {
-
- loop_beg=loop_beg*new_data_len/len;
- loop_end=loop_end*new_data_len/len;
- }
- data=new_data;
- rate=limit_rate_hz;
- len=new_data_len;
- }
-
-
- bool normalize = from->get_option("edit/normalize");
-
- if (normalize) {
-
- float max=0;
- for(int i=0;i<data.size();i++) {
-
- float amp = Math::abs(data[i]);
- if (amp>max)
- max=amp;
- }
-
- if (max>0) {
-
- float mult=1.0/max;
- for(int i=0;i<data.size();i++) {
-
- data[i]*=mult;
- }
-
- }
- }
-
- bool trim = from->get_option("edit/trim");
-
- if (trim && !loop) {
-
- int first=0;
- int last=(len*chans)-1;
- bool found=false;
- float limit = Math::db2linear((float)-30);
- for(int i=0;i<data.size();i++) {
- float amp = Math::abs(data[i]);
-
- if (!found && amp > limit) {
- first=i;
- found=true;
- }
-
- if (found && amp > limit) {
- last=i;
- }
- }
-
- first/=chans;
- last/=chans;
-
- if (first<last) {
-
- Vector<float> new_data;
- new_data.resize((last-first+1)*chans);
- for(int i=first*chans;i<=last*chans;i++) {
- new_data[i-first*chans]=data[i];
- }
-
- data=new_data;
- len=data.size()/chans;
- }
-
- }
-
- bool make_loop = from->get_option("edit/loop");
-
- if (make_loop && !loop) {
-
- loop=Sample::LOOP_FORWARD;
- loop_beg=0;
- loop_end=len;
- }
-
- int compression = from->get_option("compress/mode");
- bool force_mono = from->get_option("force/mono");
-
-
- if (force_mono && chans==2) {
-
- Vector<float> new_data;
- new_data.resize(data.size()/2);
- for(int i=0;i<len;i++) {
- new_data[i]=(data[i*2+0]+data[i*2+1])/2.0;
- }
-
- data=new_data;
- chans=1;
- }
-
- bool force_8_bit = from->get_option("force/8_bit");
- if (force_8_bit) {
-
- is16=false;
- }
-
-
- PoolVector<uint8_t> dst_data;
- Sample::Format dst_format;
-
- if ( compression == _EditorSampleImportOptions::COMPRESS_MODE_RAM) {
-
- dst_format=Sample::FORMAT_IMA_ADPCM;
- if (chans==1) {
- _compress_ima_adpcm(data,dst_data);
- } else {
-
- print_line("INTERLEAAVE!");
-
-
-
- //byte interleave
- Vector<float> left;
- Vector<float> right;
-
- int tlen = data.size()/2;
- left.resize(tlen);
- right.resize(tlen);
-
- for(int i=0;i<tlen;i++) {
- left[i]=data[i*2+0];
- right[i]=data[i*2+1];
- }
-
- PoolVector<uint8_t> bleft;
- PoolVector<uint8_t> bright;
-
- _compress_ima_adpcm(left,bleft);
- _compress_ima_adpcm(right,bright);
-
- int dl = bleft.size();
- dst_data.resize( dl *2 );
-
- PoolVector<uint8_t>::Write w=dst_data.write();
- PoolVector<uint8_t>::Read rl=bleft.read();
- PoolVector<uint8_t>::Read rr=bright.read();
-
- for(int i=0;i<dl;i++) {
- w[i*2+0]=rl[i];
- w[i*2+1]=rr[i];
- }
- }
-
- //print_line("compressing ima-adpcm, resulting buffersize is "+itos(dst_data.size())+" from "+itos(data.size()));
-
- } else {
-
- dst_format=is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8;
- dst_data.resize( data.size() * (is16?2:1));
- {
- PoolVector<uint8_t>::Write w = dst_data.write();
-
- int ds=data.size();
- for(int i=0;i<ds;i++) {
-
- if (is16) {
- int16_t v = CLAMP(data[i]*32767,-32768,32767);
- encode_uint16(v,&w[i*2]);
- } else {
- int8_t v = CLAMP(data[i]*127,-128,127);
- w[i]=v;
- }
- }
- }
- }
-
-
- Ref<Sample> target;
-
- if (ResourceCache::has(p_path)) {
-
- target = Ref<Sample>( ResourceCache::get(p_path)->cast_to<Sample>() );
- } else {
-
- target = smp;
- }
-
- target->create(dst_format,chans==2?true:false,len);
- target->set_data(dst_data);
- target->set_mix_rate(rate);
- target->set_loop_format(loop);
- target->set_loop_begin(loop_beg);
- target->set_loop_end(loop_end);
-
- from->set_source_md5(0,FileAccess::get_md5(src_path));
- from->set_editor(get_name());
- target->set_import_metadata(from);
-
-
- Error err = ResourceSaver::save(p_path,smp);
-
- return err;
-
-}
-
-void EditorSampleImportPlugin::_compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data) {
-
-
- /*p_sample_data->data = (void*)malloc(len);
- xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/
-
- static const int16_t _ima_adpcm_step_table[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
- };
-
- static const int8_t _ima_adpcm_index_table[16] = {
- -1, -1, -1, -1, 2, 4, 6, 8,
- -1, -1, -1, -1, 2, 4, 6, 8
- };
-
-
- int datalen = p_data.size();
- int datamax=datalen;
- if (datalen&1)
- datalen++;
-
- dst_data.resize(datalen/2+4);
- PoolVector<uint8_t>::Write w = dst_data.write();
-
-
- int i,step_idx=0,prev=0;
- uint8_t *out = w.ptr();
- //int16_t xm_prev=0;
- const float *in=p_data.ptr();
-
-
- /* initial value is zero */
- *(out++) =0;
- *(out++) =0;
- /* Table index initial value */
- *(out++) =0;
- /* unused */
- *(out++) =0;
-
- for (i=0;i<datalen;i++) {
- int step,diff,vpdiff,mask;
- uint8_t nibble;
- int16_t xm_sample;
-
- if (i>=datamax)
- xm_sample=0;
- else {
-
-
- xm_sample=CLAMP(in[i]*32767.0,-32768,32767);
- /*
- if (xm_sample==32767 || xm_sample==-32768)
- printf("clippy!\n",xm_sample);
- */
- }
-
- //xm_sample=xm_sample+xm_prev;
- //xm_prev=xm_sample;
-
- diff = (int)xm_sample - prev ;
-
- nibble=0 ;
- step = _ima_adpcm_step_table[ step_idx ];
- vpdiff = step >> 3 ;
- if (diff < 0) {
- nibble=8;
- diff=-diff ;
- }
- mask = 4 ;
- while (mask) {
-
- if (diff >= step) {
-
- nibble |= mask;
- diff -= step;
- vpdiff += step;
- }
-
- step >>= 1 ;
- mask >>= 1 ;
- };
-
- if (nibble&8)
- prev-=vpdiff ;
- else
- prev+=vpdiff ;
-
- if (prev > 32767) {
- //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev);
- prev=32767;
- } else if (prev < -32768) {
- //printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev);
- prev = -32768 ;
- }
-
- step_idx += _ima_adpcm_index_table[nibble];
- if (step_idx< 0)
- step_idx= 0 ;
- else if (step_idx> 88)
- step_idx= 88 ;
-
-
- if (i&1) {
- *out|=nibble<<4;
- out++;
- } else {
- *out=nibble;
- }
- /*dataptr[i]=prev>>8;*/
- }
-
-}
-
-
-EditorSampleImportPlugin* EditorSampleImportPlugin::singleton=NULL;
-
-
-void EditorSampleImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
-
-
- Vector<String> files;
- for(int i=0;i<p_drop.size();i++) {
- String ext = p_drop[i].get_extension().to_lower();
-
- if (ext=="wav") {
-
- files.push_back(p_drop[i]);
- }
- }
-
- if (files.size()) {
- import_dialog();
- dialog->_choose_files(files);
- dialog->_choose_save_dir(p_dest_path);
- }
-}
-
-void EditorSampleImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
-
- if (p_list.size()==0)
- return;
-
- Vector<String> sources;
- for(int i=0;i<p_list.size();i++) {
- int idx;
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i],&idx);
- if (efsd) {
- for(int j=0;j<efsd->get_source_count(idx);j++) {
- String file = expand_source_path(efsd->get_source_file(idx,j));
- if (sources.find(file)==-1) {
- sources.push_back(file);
- }
-
- }
- }
- }
-
- if (sources.size()) {
-
- dialog->popup_import(p_list[0]);
- dialog->_choose_files(sources);
- dialog->_choose_save_dir(p_list[0].get_base_dir());
- }
-}
-
-bool EditorSampleImportPlugin::can_reimport_multiple_files() const {
-
- return true;
-}
-
-EditorSampleImportPlugin::EditorSampleImportPlugin(EditorNode* p_editor) {
-
- singleton=this;
- dialog = memnew( EditorSampleImportDialog(this));
- p_editor->get_gui_base()->add_child(dialog);
-}
-
-Vector<uint8_t> EditorSampleExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
-
-
-
- if (EditorImportExport::get_singleton()->sample_get_action()==EditorImportExport::SAMPLE_ACTION_NONE || p_path.get_extension().to_lower()!="wav") {
-
- return Vector<uint8_t>();
- }
-
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
-
- imd->add_source(EditorImportPlugin::validate_source_path(p_path));
-
- imd->set_option("force/8_bit",false);
- imd->set_option("force/mono",false);
- imd->set_option("force/max_rate",true);
- imd->set_option("force/max_rate_hz",EditorImportExport::get_singleton()->sample_get_max_hz());
- imd->set_option("edit/trim",EditorImportExport::get_singleton()->sample_get_trim());
- imd->set_option("edit/normalize",false);
- imd->set_option("edit/loop",false);
- imd->set_option("compress/mode",1);
-
- String savepath = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/smpconv.smp");
- Error err = EditorSampleImportPlugin::singleton->import(savepath,imd);
-
-
- ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
-
- p_path=p_path.get_basename()+".converted.smp";
- return FileAccess::get_file_as_array(savepath);
-
-}
-
-
-
-EditorSampleExportPlugin::EditorSampleExportPlugin() {
-
-}
-
-#endif
diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.h b/tools/editor/io_plugins/editor_sample_import_plugin.h
deleted file mode 100644
index 8e02d0e11d..0000000000
--- a/tools/editor/io_plugins/editor_sample_import_plugin.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*************************************************************************/
-/* editor_sample_import_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_SAMPLE_IMPORT_PLUGIN_H
-#define EDITOR_SAMPLE_IMPORT_PLUGIN_H
-
-#if 0
-#include "tools/editor/editor_import_export.h"
-#include "scene/resources/font.h"
-
-class EditorNode;
-class EditorSampleImportDialog;
-
-class EditorSampleImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorSampleImportPlugin,EditorImportPlugin);
-
- EditorSampleImportDialog *dialog;
- void _compress_ima_adpcm(const Vector<float>& p_data,PoolVector<uint8_t>& dst_data);
-public:
-
- static EditorSampleImportPlugin *singleton;
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
- void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
- virtual void reimport_multiple_files(const Vector<String>& p_list);
- virtual bool can_reimport_multiple_files() const;
-
-
- EditorSampleImportPlugin(EditorNode* p_editor);
-};
-
-class EditorSampleExportPlugin : public EditorExportPlugin {
-
- GDCLASS( EditorSampleExportPlugin, EditorExportPlugin);
-
-
-public:
-
- virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
-
- EditorSampleExportPlugin();
-};
-
-#endif // EDITOR_SAMPLE_IMPORT_PLUGIN_H
-#endif
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
deleted file mode 100644
index bffccb9072..0000000000
--- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp
+++ /dev/null
@@ -1,2992 +0,0 @@
-/*************************************************************************/
-/* editor_scene_import_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_scene_import_plugin.h"
-#if 0
-#include "globals.h"
-#include "tools/editor/editor_node.h"
-#include "scene/resources/packed_scene.h"
-#include "scene/resources/box_shape.h"
-#include "os/file_access.h"
-#include "scene/3d/path.h"
-#include "scene/animation/animation_player.h"
-#include "io/resource_saver.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/3d/navigation.h"
-#include "scene/3d/room_instance.h"
-#include "scene/3d/body_shape.h"
-#include "scene/3d/physics_body.h"
-#include "scene/3d/portal.h"
-#include "scene/3d/vehicle_body.h"
-#include "scene/resources/sphere_shape.h"
-#include <scene/resources/box_shape.h>
-#include <scene/resources/ray_shape.h>
-#include <scene/resources/plane_shape.h>
-#include "tools/editor/create_dialog.h"
-#include "os/os.h"
-
-
-
-
-EditorSceneImporter::EditorSceneImporter() {
-
-
-}
-
-void EditorScenePostImport::_bind_methods() {
-
- BIND_VMETHOD( MethodInfo("post_import",PropertyInfo(Variant::OBJECT,"scene")) );
-
-}
-
-Node *EditorScenePostImport::post_import(Node* p_scene) {
-
- if (get_script_instance())
- return get_script_instance()->call("post_import",p_scene);
-
- return p_scene;
-}
-
-EditorScenePostImport::EditorScenePostImport() {
-
-
-}
-
-
-/////////////////////////////
-
-
-class EditorImportAnimationOptions : public VBoxContainer {
-
- GDCLASS( EditorImportAnimationOptions, VBoxContainer );
-
-
-
- TreeItem *fps;
- TreeItem* optimize_linear_error;
- TreeItem* optimize_angular_error;
- TreeItem* optimize_max_angle;
-
- TreeItem *clips_base;
-
- TextEdit *filters;
- Vector<TreeItem*> clips;
-
- Tree *flags;
- Tree *clips_tree;
- Tree *optimization_tree;
- Vector<TreeItem*> items;
-
-
- bool updating;
- bool validating;
-
-
-
- void _changed();
- void _item_edited();
- void _button_action(Object *p_obj,int p_col,int p_id);
-
-protected:
- static void _bind_methods();
- void _notification(int p_what);
-
-public:
-
- void set_flags(uint32_t p_flags);
- uint32_t get_flags() const;
-
- void set_fps(int p_fps);
- int get_fps() const;
-
- void set_optimize_linear_error(float p_error);
- float get_optimize_linear_error() const;
-
- void set_optimize_angular_error(float p_error);
- float get_optimize_angular_error() const;
-
- void set_optimize_max_angle(float p_error);
- float get_optimize_max_angle() const;
-
- void setup_clips(const Array& p_clips);
- Array get_clips() const;
-
- void set_filter(const String& p_filter);
- String get_filter() const;
-
- EditorImportAnimationOptions();
-
-
-};
-
-////////////////////////////
-
-class EditorSceneImportDialog : public ConfirmationDialog {
-
- GDCLASS(EditorSceneImportDialog,ConfirmationDialog);
-
-
- struct FlagInfo {
- int value;
- const char *category;
- const char *text;
- bool defval;
- };
-
- static const FlagInfo scene_flag_names[];
-
- EditorImportTextureOptions *texture_options;
- EditorImportAnimationOptions *animation_options;
-
- EditorSceneImportPlugin *plugin;
-
- EditorNode *editor;
-
- LineEdit *import_path;
- LineEdit *save_path;
- LineEdit *script_path;
- Tree *import_options;
- EditorFileDialog *file_select;
- EditorFileDialog *script_select;
- EditorDirDialog *save_select;
- OptionButton *texture_action;
- CreateDialog *root_type_choose;
- LineEdit *root_node_name;
-
- ConfirmationDialog *confirm_open;
-
- ConfirmationDialog *confirm_import;
- RichTextLabel *missing_files;
-
- Vector<TreeItem*> scene_flags;
-
- Map<Ref<Mesh>,Ref<Shape> > collision_map;
- ConfirmationDialog *error_dialog;
-
- Button *root_type;
- CheckBox *root_default;
-
-
- void _root_default_pressed();
- void _root_type_pressed();
- void _set_root_type();
-
- void _choose_file(const String& p_path);
- void _choose_save_file(const String& p_path);
- void _choose_script(const String& p_path);
- void _browse();
- void _browse_target();
- void _browse_script();
- void _import(bool p_and_open=false);
- void _import_confirm();
-
- Ref<ResourceImportMetadata> wip_rimd;
- Node *wip_import;
- String wip_save_file;
- bool wip_blocked;
- bool wip_open;
-
- void _dialog_hid();
- void _open_and_import();
-
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void setup_popup(const String& p_from,const String& p_to_path) {
- _choose_file(p_from);
- _choose_save_file(p_to_path);
- }
-
- Error import(const String& p_from, const String& p_to, const String& p_preset);
- void popup_import(const String& p_from);
- EditorSceneImportDialog(EditorNode *p_editor,EditorSceneImportPlugin *p_plugin);
-};
-
-///////////////////////////////////
-
-
-static const char *anim_flag_names[]={
- "Detect Loop (-loop,-cycle)",
- "Keep Value Tracks",
- "Optimize",
- "Force All Tracks in All Clips",
- NULL
-};
-
-static const char *anim_flag_descript[]={
- "Set loop flag for animation names that\ncontain 'cycle' or 'loop' in the name.",
- "When merging an existing aimation,\nkeep the user-created value-tracks.",
- "Remove redundant keyframes in\n transform tacks.",
- "Some exporters will rely on default pose for some bones.\nThis forces those bones to have at least one animation key.",
- NULL
-};
-
-
-
-void EditorImportAnimationOptions::set_flags(uint32_t p_flags){
-
- updating=true;
- for(int i=0;i<items.size();i++) {
-
- items[i]->set_checked(0,p_flags&(1<<i));
- }
- updating=false;
-
-}
-uint32_t EditorImportAnimationOptions::get_flags() const{
-
- uint32_t f=0;
- for(int i=0;i<items.size();i++) {
-
- if (items[i]->is_checked(0))
- f|=(1<<i);
- }
-
- return f;
-}
-
-
-void EditorImportAnimationOptions::_changed() {
-
- if (updating)
- return;
- emit_signal("changed");
-}
-
-
-void EditorImportAnimationOptions::_button_action(Object *p_obj,int p_col,int p_id) {
-
- memdelete(p_obj);
-
-}
-
-
-void EditorImportAnimationOptions::_item_edited() {
-
- if (validating)
- return;
-
- if (clips.size()==0)
- return;
- validating=true;
- print_line("edited");
- TreeItem *item = clips_tree->get_edited();
- if (item==clips[clips.size()-1]) {
- //add new
- print_line("islast");
- if (item->get_text(0).find("<")!=-1 || item->get_text(0).find(">")!=-1) {
- validating=false;
- return; //fuckit
- }
-
- item->set_editable(1,true);
- item->set_editable(2,true);
- item->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons"));
- item->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- item->set_range_config(1,0,3600,0.01);
- item->set_range(1,0);
- item->set_editable(1,true);
- item->set_cell_mode(2,TreeItem::CELL_MODE_RANGE);
- item->set_range_config(2,0,3600,0.01);
- item->set_range(2,0);
- item->set_cell_mode(3,TreeItem::CELL_MODE_CHECK);
- item->set_editable(3,true);
-
- TreeItem *newclip = clips_tree->create_item(clips_base);
- newclip->set_text(0,"<new clip>");
- newclip->set_editable(0,true);
- newclip->set_editable(1,false);
- newclip->set_editable(2,false);
- clips.push_back(newclip);
-
-
-
- }
-
-
- //make name unique JUST IN CASE
- String name = item->get_text(0);
- name=name.replace("/","_").replace(":","_").strip_edges();
- if (name=="")
- name=TTR("New Clip");
-
- if (clips.size()>2) {
- int index=1;
- while(true) {
- bool valid = true;
- String try_name=name;
- if (index>1)
- try_name+=" "+itos(index);
-
- for(int i=0;i<clips.size()-1;i++) {
-
- if (clips[i]==item)
- continue;
- if (clips[i]->get_text(0)==try_name) {
- index++;
- valid=false;
- break;
- }
- }
-
- if (valid) {
- name=try_name;
- break;
- }
-
- }
- }
-
- if (item->get_text(0)!=name)
- item->set_text(0,name);
-
- validating=false;
-
-}
-
-void EditorImportAnimationOptions::_bind_methods() {
-
- ClassDB::bind_method("_changed",&EditorImportAnimationOptions::_changed);
- ClassDB::bind_method("_item_edited",&EditorImportAnimationOptions::_item_edited);
- ClassDB::bind_method("_button_action",&EditorImportAnimationOptions::_button_action);
- //ClassDB::bind_method("_changedp",&EditorImportAnimationOptions::_changedp);
-
- ADD_SIGNAL(MethodInfo("changed"));
-}
-
-
-void EditorImportAnimationOptions::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- flags->connect("item_edited",this,"_changed");
- clips_tree->connect("item_edited",this,"_item_edited");
- clips_tree->connect("button_pressed",this,"_button_action",varray(),CONNECT_DEFERRED);
- //format->connect("item_selected",this,"_changedp");
- }
-}
-
-
-Array EditorImportAnimationOptions::get_clips() const {
-
- Array arr;
- for(int i=0;i<clips.size()-1;i++) {
-
- arr.push_back(clips[i]->get_text(0));
- arr.push_back(clips[i]->get_range(1));
- arr.push_back(clips[i]->get_range(2));
- arr.push_back(clips[i]->is_checked(3));
- }
-
- return arr;
-}
-
-
-void EditorImportAnimationOptions::setup_clips(const Array& p_clips) {
-
- ERR_FAIL_COND(p_clips.size()%4!=0);
- for(int i=0;i<clips.size();i++) {
-
- memdelete(clips[i]);
- }
-
-
- clips.clear();
-
- for(int i=0;i<p_clips.size();i+=4) {
-
- TreeItem *clip = clips_tree->create_item(clips_base);
- clip->set_text(0,p_clips[i]);
- clip->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons"));
- clip->set_editable(0,true);
- clip->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- clip->set_range_config(1,0,3600,0.01);
- clip->set_range(1,p_clips[i+1]);
- clip->set_editable(1,true);
- clip->set_cell_mode(2,TreeItem::CELL_MODE_RANGE);
- clip->set_range_config(2,0,3600,0.01);
- clip->set_range(2,p_clips[i+2]);
- clip->set_editable(2,true);
- clip->set_cell_mode(3,TreeItem::CELL_MODE_CHECK);
- clip->set_editable(3,true);
- clip->set_checked(3,p_clips[i+3]);
- clips.push_back(clip);
-
- }
-
- TreeItem *newclip = clips_tree->create_item(clips_base);
- newclip->set_text(0,"<new clip>");
- newclip->set_editable(0,true);
- newclip->set_editable(1,false);
- newclip->set_editable(2,false);
- newclip->set_editable(3,false);
- clips.push_back(newclip);
-
-}
-
-
-EditorImportAnimationOptions::EditorImportAnimationOptions() {
-
-
- updating=false;
- validating=false;
-
- TabContainer *tab= memnew(TabContainer);
- add_margin_child(TTR("Animation Options"),tab,true);
-
- flags = memnew( Tree );
- flags->set_hide_root(true);
- tab->add_child(flags);
- flags->set_name(TTR("Flags"));
- TreeItem *root = flags->create_item();
-
- const char ** fname=anim_flag_names;
- const char ** fdescr=anim_flag_descript;
-
- while( *fname ) {
-
- TreeItem*ti = flags->create_item(root);
- ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- ti->set_text(0,*fname);
- ti->set_editable(0,true);
- ti->set_tooltip(0,*fdescr);
- items.push_back(ti);
- fname++;
- fdescr++;
- }
-
-
- TreeItem *fps_base = flags->create_item(root);
- fps_base->set_text(0,TTR("Bake FPS:"));
- fps_base->set_editable(0,false);
- fps = flags->create_item(fps_base);
- fps->set_cell_mode(0,TreeItem::CELL_MODE_RANGE);
- fps->set_editable(0,true);
- fps->set_range_config(0,1,120,1);
- fps->set_range(0,15);
-
- optimization_tree = memnew( Tree );
- optimization_tree->set_columns(2);
- tab->add_child(optimization_tree);
- optimization_tree->set_name(TTR("Optimizer"));
- optimization_tree->set_column_expand(0,true);
- optimization_tree->set_column_expand(1,false);
- optimization_tree->set_column_min_width(1,80);
- optimization_tree->set_hide_root(true);
-
-
- TreeItem *optimize_root = optimization_tree->create_item();
-
- optimize_linear_error = optimization_tree->create_item(optimize_root);
- optimize_linear_error->set_text(0,TTR("Max Linear Error"));
- optimize_linear_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- optimize_linear_error->set_editable(1,true);
- optimize_linear_error->set_range_config(1,0,1,0.001);
- optimize_linear_error->set_range(1,0.05);
-
- optimize_angular_error = optimization_tree->create_item(optimize_root);
- optimize_angular_error->set_text(0,TTR("Max Angular Error"));
- optimize_angular_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- optimize_angular_error->set_editable(1,true);
- optimize_angular_error->set_range_config(1,0,1,0.001);
- optimize_angular_error->set_range(1,0.01);
-
- optimize_max_angle = optimization_tree->create_item(optimize_root);
- optimize_max_angle->set_text(0,TTR("Max Angle"));
- optimize_max_angle->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- optimize_max_angle->set_editable(1,true);
- optimize_max_angle->set_range_config(1,0,360,0.001);
- optimize_max_angle->set_range(1,int(180*0.125));
-
- clips_tree = memnew( Tree );
- clips_tree->set_hide_root(true);
- tab->add_child(clips_tree);
- clips_tree->set_name(TTR("Clips"));
-
- clips_tree->set_columns(4);
- clips_tree->set_column_expand(0,1);
- clips_tree->set_column_expand(1,0);
- clips_tree->set_column_expand(2,0);
- clips_tree->set_column_expand(3,0);
- clips_tree->set_column_min_width(1,60);
- clips_tree->set_column_min_width(2,60);
- clips_tree->set_column_min_width(3,40);
- clips_tree->set_column_titles_visible(true);
- clips_tree->set_column_title(0,TTR("Name"));
- clips_tree->set_column_title(1,TTR("Start(s)"));
- clips_tree->set_column_title(2,TTR("End(s)"));
- clips_tree->set_column_title(3,TTR("Loop"));
- clips_base =clips_tree->create_item(0);
-
-
- setup_clips(Array());
-
-
- filters = memnew( TextEdit );
- tab->add_child(filters);
- filters->set_name(TTR("Filters"));
-}
-
-
-
-void EditorImportAnimationOptions::set_fps(int p_fps) {
-
- fps->set_range(0,p_fps);
-}
-
-int EditorImportAnimationOptions::get_fps() const {
-
- return fps->get_range(0);
-}
-
-
-void EditorImportAnimationOptions::set_optimize_linear_error(float p_optimize_linear_error) {
-
- optimize_linear_error->set_range(1,p_optimize_linear_error);
-}
-
-float EditorImportAnimationOptions::get_optimize_linear_error() const {
-
- return optimize_linear_error->get_range(1);
-}
-
-void EditorImportAnimationOptions::set_optimize_angular_error(float p_optimize_angular_error) {
-
- optimize_angular_error->set_range(1,p_optimize_angular_error);
-}
-
-float EditorImportAnimationOptions::get_optimize_angular_error() const {
-
- return optimize_angular_error->get_range(1);
-}
-
-void EditorImportAnimationOptions::set_optimize_max_angle(float p_optimize_max_angle) {
-
- optimize_max_angle->set_range(1,p_optimize_max_angle);
-}
-
-float EditorImportAnimationOptions::get_optimize_max_angle() const {
-
- return optimize_max_angle->get_range(1);
-}
-
-
-void EditorImportAnimationOptions::set_filter(const String& p_filter) {
-
- filters->set_text(p_filter);
-}
-
-String EditorImportAnimationOptions::get_filter() const {
-
- return filters->get_text();
-}
-
-
-
-
-
-////////////////////////////////////////////////////////
-
-
-
-void EditorSceneImportDialog::_choose_file(const String& p_path) {
-#if 0
- StringName sn = EditorImportDB::get_singleton()->find_source_path(p_path);
- if (sn!=StringName()) {
-
- EditorImportDB::ImportScene isc;
- if (EditorImportDB::get_singleton()->get_scene(sn,isc)==OK) {
-
- save_path->set_text(String(sn).get_base_dir());
- texture_options->set_flags( isc.image_flags );
- texture_options->set_quality( isc.image_quality );
- texture_options->set_format( isc.image_format );
- animation_options->set_flags( isc.anim_flags );
- script_path->set_text( isc.import_script );
- uint32_t f = isc.flags;
- for(int i=0;i<scene_flags.size();i++) {
-
- scene_flags[i]->set_checked(0,f&(1<<i));
- }
- }
- } else {
-#endif
- save_path->set_text("");
- root_node_name->set_text("");
- //save_path->set_text(p_path.get_file().basename()+".scn");
-#if 0
- }
-#endif
-
- if (p_path!=String()) {
-
- String from_path = EditorFileSystem::get_singleton()->find_resource_from_source(EditorImportPlugin::validate_source_path(p_path));
- print_line("from path.."+from_path);
- if (from_path!=String()) {
- popup_import(from_path);
-
- }
- }
-
-
- import_path->set_text(p_path);
- if (root_node_name->get_text().size()==0){
- root_node_name->set_text(import_path->get_text().get_file().get_basename());
- }
-
-}
-void EditorSceneImportDialog::_choose_save_file(const String& p_path) {
-
- save_path->set_text(p_path);
-}
-
-void EditorSceneImportDialog::_choose_script(const String& p_path) {
-
- String p = GlobalConfig::get_singleton()->localize_path(p_path);
- if (!p.is_resource_file())
- p=GlobalConfig::get_singleton()->get_resource_path().path_to(p_path.get_base_dir())+p_path.get_file();
- script_path->set_text(p);
-
-}
-
-
-void EditorSceneImportDialog::_open_and_import() {
-
- bool unsaved=EditorNode::has_unsaved_changes();
-
- if (unsaved) {
-
- confirm_open->popup_centered_minsize(Size2(300,80)*EDSCALE);
- } else {
- _import(true);
- }
-}
-
-void EditorSceneImportDialog::_import(bool p_and_open) {
-
- wip_open=p_and_open;
-//' ImportMonitorBlock imb;
-
-
- if (import_path->get_text().strip_edges()=="") {
- error_dialog->set_text(TTR("Source path is empty."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (save_path->get_text().strip_edges()=="") {
- error_dialog->set_text(TTR("Target path is empty."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (!save_path->get_text().begins_with("res://")) {
- error_dialog->set_text(TTR("Target path must be a complete resource path."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (!DirAccess::exists(save_path->get_text())) {
- error_dialog->set_text(TTR("Target path must exist."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- String dst_path;
-
- if (texture_action->get_selected()==0)
- dst_path=save_path->get_text();//.get_base_dir();
- else
- dst_path=GlobalConfig::get_singleton()->get("import/shared_textures");
-
- uint32_t flags=0;
-
- for(int i=0;i<scene_flags.size();i++) {
-
- if (scene_flags[i]->is_checked(0)) {
- int md = scene_flags[i]->get_metadata(0);
- flags|=md;
- }
- }
-
-
-
-
-
- if (script_path->get_text()!="") {
- Ref<Script> scr = ResourceLoader::load(script_path->get_text());
- if (!scr.is_valid()) {
- error_dialog->set_text(TTR("Couldn't load post-import script."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- Ref<EditorScenePostImport> pi = Ref<EditorScenePostImport>( memnew( EditorScenePostImport ) );
- pi->set_script(scr.get_ref_ptr());
- if (!pi->get_script_instance()) {
-
- error_dialog->set_text(TTR("Invalid/broken script for post-import."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- }
-
-
- // Scenes should always be imported as binary format since vertex data is large and would take
- // up a lot of space and time to load if imported as text format (GH-5778)
- String save_file = save_path->get_text().plus_file(import_path->get_text().get_file().get_basename()+".scn");
- print_line("Saving to: "+save_file);
-
-
-
-
-
- Node *scene=NULL;
-
-
- Ref<ResourceImportMetadata> rim = memnew( ResourceImportMetadata );
-
- rim->add_source(EditorImportPlugin::validate_source_path(import_path->get_text()));
- rim->set_option("flags",flags);
- print_line("GET FLAGS: "+itos(texture_options->get_flags()));
- rim->set_option("texture_flags",texture_options->get_flags());
- rim->set_option("texture_format",texture_options->get_format());
- rim->set_option("texture_quality",texture_options->get_quality());
- rim->set_option("animation_flags",animation_options->get_flags());
- rim->set_option("animation_bake_fps",animation_options->get_fps());
- rim->set_option("animation_optimizer_linear_error",animation_options->get_optimize_linear_error());
- rim->set_option("animation_optimizer_angular_error",animation_options->get_optimize_angular_error());
- rim->set_option("animation_optimizer_max_angle",animation_options->get_optimize_max_angle());
- rim->set_option("animation_filters",animation_options->get_filter());
- rim->set_option("animation_clips",animation_options->get_clips());
- rim->set_option("post_import_script",script_path->get_text());
- rim->set_option("reimport",true);
- if (!root_default->is_pressed()) {
- rim->set_option("root_type",root_type->get_text());
- }
- if (root_node_name->get_text().size()==0) {
- root_node_name->set_text(import_path->get_text().get_file().get_basename());
- }
- rim->set_option("root_name",root_node_name->get_text());
-
- List<String> missing;
- Error err = plugin->import1(rim,&scene,&missing);
-
- if (err || !scene) {
-
- error_dialog->set_text(TTR("Error importing scene."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- if (missing.size()) {
-
- missing_files->clear();
- for(List<String>::Element *E=missing.front();E;E=E->next()) {
-
- missing_files->add_text(E->get());
- missing_files->add_newline();
- }
- wip_import=scene;
- wip_rimd=rim;
- wip_save_file=save_file;
- confirm_import->popup_centered_ratio();
- return;
-
- } else {
-
- err = plugin->import2(scene,save_file,rim);
-
- if (err) {
-
- error_dialog->set_text(TTR("Error importing scene."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
- if (wip_open)
- EditorNode::get_singleton()->load_scene(save_file,false,false,false);
-
- }
-
- hide();
-
- /*
- editor->clear_scene();
-
- Error err = EditorImport::import_scene(import_path->get_text(),save_file,dst_path,flags,texture_options->get_format(),compression,texture_options->get_flags(),texture_options->get_quality(),animation_options->get_flags(), &scene,pi);
-
- if (err) {
-
- error_dialog->set_text("Error importing scene.");
- error_dialog->popup_centered(Size2(200,100));
- return;
- }
-
- editor->save_import_export();
- if (scene)
- editor->set_edited_scene(scene);
-
- hide();
- */
-};
-
-
-void EditorSceneImportDialog::_import_confirm() {
-
- wip_blocked=true;
- print_line("import confirm!");
- Error err = plugin->import2(wip_import,wip_save_file,wip_rimd);
- wip_blocked=false;
- wip_import=NULL;
- wip_rimd=Ref<ResourceImportMetadata>();
- confirm_import->hide();
- if (err) {
-
- wip_save_file="";
- error_dialog->set_text(TTR("Error importing scene."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- if (wip_open)
- EditorNode::get_singleton()->load_scene(wip_save_file,false,false,false);
- wip_open=false;
- wip_save_file="";
-
- hide();
-
-}
-
-
-void EditorSceneImportDialog::_browse() {
-
- file_select->popup_centered_ratio();
-}
-
-void EditorSceneImportDialog::_browse_target() {
-
- save_select->popup_centered_ratio();
- if (save_path->get_text()!="")
- save_select->set_current_path(save_path->get_text());
-
-}
-
-void EditorSceneImportDialog::_browse_script() {
-
- script_select->popup_centered_ratio();
-
-}
-
-void EditorSceneImportDialog::popup_import(const String &p_from) {
-
- popup_centered(Size2(750,550)*EDSCALE);
- if (p_from!="") {
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
- if (rimd.is_null())
- return;
-
- int flags = rimd->get_option("flags");
-
- for(int i=0;i<scene_flags.size();i++) {
-
- int md = scene_flags[i]->get_metadata(0);
- scene_flags[i]->set_checked(0,flags&md);
- }
-
- texture_options->set_flags(rimd->get_option("texture_flags"));
- texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("texture_format"))));
- texture_options->set_quality(rimd->get_option("texture_quality"));
- animation_options->set_flags(rimd->get_option("animation_flags"));
- if (rimd->has_option("animation_clips"))
- animation_options->setup_clips(rimd->get_option("animation_clips"));
- if (rimd->has_option("animation_filters"))
- animation_options->set_filter(rimd->get_option("animation_filters"));
- if (rimd->has_option("animation_bake_fps"))
- animation_options->set_fps(rimd->get_option("animation_bake_fps"));
- if (rimd->has_option("animation_optimizer_linear_error"))
- animation_options->set_optimize_linear_error(rimd->get_option("animation_optimizer_linear_error"));
- if (rimd->has_option("animation_optimizer_angular_error"))
- animation_options->set_optimize_angular_error(rimd->get_option("animation_optimizer_angular_error"));
- if (rimd->has_option("animation_optimizer_max_angle"))
- animation_options->set_optimize_max_angle(rimd->get_option("animation_optimizer_max_angle"));
-
- if (rimd->has_option("root_type")) {
- root_default->set_pressed(false);
- String type = rimd->get_option("root_type");
- root_type->set_text(type);
- root_type->set_disabled(false);
-
- if (has_icon(type,"EditorIcons")) {
- root_type->set_icon(get_icon(type,"EditorIcons"));
- } else {
- root_type->set_icon(get_icon("Object","EditorIcons"));
- }
-
- } else {
- root_default->set_pressed(true);
- root_type->set_disabled(true);
- }
- if (rimd->has_option("root_name")) {
- root_node_name->set_text(rimd->get_option("root_name"));
- } else {
- root_node_name->set_text(root_type->get_text()); // backward compatibility for 2.1 or before
- }
- script_path->set_text(rimd->get_option("post_import_script"));
-
- save_path->set_text(p_from.get_base_dir());
- import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
-
- }
-}
-
-
-void EditorSceneImportDialog::_notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
-
- List<String> extensions;
- file_select->clear_filters();
- root_type->set_icon(get_icon("Spatial","EditorIcons"));
- root_type->set_text("Spatial");
- root_type->set_disabled(true);
-
- for(int i=0;i<plugin->get_importers().size();i++) {
- plugin->get_importers()[i]->get_extensions(&extensions);
- }
-
-
- for(int i=0;i<extensions.size();i++) {
-
- file_select->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
- extensions.clear();
-
- //EditorImport::get_import_extensions(&extensions)
- /* ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
- save_select->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- save_select->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }*/
-
-
- }
-}
-
-Error EditorSceneImportDialog::import(const String& p_from, const String& p_to, const String& p_preset) {
-
- import_path->set_text(p_from);
- save_path->set_text(p_to);
- script_path->set_text(p_preset);
-
- _import();
-
-
-
- return OK;
-}
-
-void EditorSceneImportDialog::_dialog_hid() {
-
- if (wip_blocked)
- return;
- print_line("DIALOGHID!");
- if (wip_import) {
- memdelete(wip_import);
- wip_import=NULL;
- wip_save_file="";
- wip_rimd=Ref<ResourceImportMetadata>();
- }
-}
-void EditorSceneImportDialog::_root_default_pressed() {
-
- root_type->set_disabled(root_default->is_pressed());
-}
-
-void EditorSceneImportDialog::_root_type_pressed() {
-
-
- root_type_choose->popup(false);
-}
-
-
-void EditorSceneImportDialog::_set_root_type() {
-
- String type = root_type_choose->get_selected_type();
- if (type==String())
- return;
- root_type->set_text(type);
- if (has_icon(type,"EditorIcons")) {
- root_type->set_icon(get_icon(type,"EditorIcons"));
- } else {
- root_type->set_icon(get_icon("Object","EditorIcons"));
- }
-}
-
-void EditorSceneImportDialog::_bind_methods() {
-
-
- ClassDB::bind_method("_choose_file",&EditorSceneImportDialog::_choose_file);
- ClassDB::bind_method("_choose_save_file",&EditorSceneImportDialog::_choose_save_file);
- ClassDB::bind_method("_choose_script",&EditorSceneImportDialog::_choose_script);
- ClassDB::bind_method("_import",&EditorSceneImportDialog::_import,DEFVAL(false));
- ClassDB::bind_method("_browse",&EditorSceneImportDialog::_browse);
- ClassDB::bind_method("_browse_target",&EditorSceneImportDialog::_browse_target);
- ClassDB::bind_method("_browse_script",&EditorSceneImportDialog::_browse_script);
- ClassDB::bind_method("_dialog_hid",&EditorSceneImportDialog::_dialog_hid);
- ClassDB::bind_method("_import_confirm",&EditorSceneImportDialog::_import_confirm);
- ClassDB::bind_method("_open_and_import",&EditorSceneImportDialog::_open_and_import);
- ClassDB::bind_method("_root_default_pressed",&EditorSceneImportDialog::_root_default_pressed);
- ClassDB::bind_method("_root_type_pressed",&EditorSceneImportDialog::_root_type_pressed);
- ClassDB::bind_method("_set_root_type",&EditorSceneImportDialog::_set_root_type);
-
-
- ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
-}
-
-
-
-const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_names[]={
-
- {EditorSceneImportPlugin::SCENE_FLAG_REMOVE_NOIMP,("Actions"),"Remove Nodes (-noimp)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_IMPORT_ANIMATIONS,("Actions"),"Import Animations",true},
- {EditorSceneImportPlugin::SCENE_FLAG_COMPRESS_GEOMETRY,("Actions"),"Compress Geometry",false},
- {EditorSceneImportPlugin::SCENE_FLAG_GENERATE_TANGENT_ARRAYS,("Actions"),"Force Generation of Tangent Arrays",false},
- {EditorSceneImportPlugin::SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES,("Actions"),"SRGB->Linear Of Diffuse Textures",false},
- {EditorSceneImportPlugin::SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY,("Actions"),"Convert Normal Maps to XY",true},
- {EditorSceneImportPlugin::SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS,("Actions"),"Set Material Lightmap to UV2 if Tex2Array Exists",true},
- {EditorSceneImportPlugin::SCENE_FLAG_MERGE_KEEP_MATERIALS,("Merge"),"Keep Materials after first import (delete them for re-import).",true},
- {EditorSceneImportPlugin::SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,("Merge"),"Keep user-added Animation tracks.",true},
- {EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,("Materials"),"Set Alpha in Materials (-alpha)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,("Materials"),"Set Vert. Color in Materials (-vcol)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,("Create"),"Create Collisions and/or Rigid Bodies (-col,-colonly,-rigid)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,("Create"),"Create Portals (-portal)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_ROOMS,("Create"),"Create Rooms (-room)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_SIMPLIFY_ROOMS,("Create"),"Simplify Rooms",false},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_BILLBOARDS,("Create"),"Create Billboards (-bb)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,("Create"),"Create Impostors (-imp:dist)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_LODS,("Create"),"Create LODs (-lod:dist)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,("Create"),"Create Vehicles (-vehicle)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,("Create"),"Create Vehicle Wheels (-wheel)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_CREATE_NAVMESH,("Create"),"Create Navigation Meshes (-navmesh)",true},
- {EditorSceneImportPlugin::SCENE_FLAG_DETECT_LIGHTMAP_LAYER,("Create"),"Detect LightMap Layer (-lm:<int>).",true},
- {-1,NULL,NULL,false}
-};
-
-
-EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSceneImportPlugin *p_plugin) {
-
-
- editor=p_editor;
- plugin=p_plugin;
-
- set_title(TTR("Import 3D Scene"));
- HBoxContainer *import_hb = memnew( HBoxContainer );
- add_child(import_hb);
- //set_child_rect(import_hb);
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- import_hb->add_child(vbc);
- vbc->set_h_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Source Scene:"),hbc);
-
- import_path = memnew( LineEdit );
- import_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(import_path);
-
- Button * import_choose = memnew( Button );
- import_choose->set_text(" .. ");
- hbc->add_child(import_choose);
-
- import_choose->connect("pressed", this,"_browse");
-
- hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Target Path:"),hbc);
-
- save_path = memnew( LineEdit );
- save_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(save_path);
-
- Button * save_choose = memnew( Button );
- save_choose->set_text(" .. ");
- hbc->add_child(save_choose);
-
- save_choose->connect("pressed", this,"_browse_target");
-
- texture_action = memnew( OptionButton );
- texture_action->add_item(TTR("Same as Target Scene"));
- texture_action->add_item(TTR("Shared"));
- texture_action->select(0);
- vbc->add_margin_child(TTR("Target Texture Folder:"),texture_action);
-
- import_options = memnew( Tree );
- vbc->set_v_size_flags(SIZE_EXPAND_FILL);
- vbc->add_margin_child(TTR("Options:"),import_options,true);
-
- file_select = memnew(EditorFileDialog);
- file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- add_child(file_select);
-
-
- file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
-
- file_select->connect("file_selected", this,"_choose_file");
-
- save_select = memnew(EditorDirDialog);
- add_child(save_select);
-
- //save_select->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- save_select->connect("dir_selected", this,"_choose_save_file");
-
- get_ok()->connect("pressed", this,"_import");
- get_ok()->set_text(TTR("Import"));
-
- TreeItem *root = import_options->create_item(NULL);
- import_options->set_hide_root(true);
-
- const FlagInfo* fn=scene_flag_names;
-
- Map<String,TreeItem*> categories;
-
- while(fn->text) {
-
- String cat = fn->category;
- TreeItem *parent;
- if (!categories.has(cat)) {
- parent = import_options->create_item(root);
- parent->set_text(0,cat);
- categories[cat]=parent;
- } else {
- parent=categories[cat];
- }
-
- TreeItem *opt = import_options->create_item(parent);
- opt->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- opt->set_checked(0,fn->defval);
- opt->set_editable(0,true);
- opt->set_text(0,fn->text);
- opt->set_metadata(0,fn->value);
-
- scene_flags.push_back(opt);
- fn++;
- }
-
- hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Post-Process Script:"),hbc);
-
- script_path = memnew( LineEdit );
- script_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(script_path);
-
- Button * script_choose = memnew( Button );
- script_choose->set_text(" .. ");
- hbc->add_child(script_choose);
-
- script_choose->connect("pressed", this,"_browse_script");
-
- script_select = memnew(EditorFileDialog);
- add_child(script_select);
- for(int i=0;i<ScriptServer::get_language_count();i++) {
-
- ScriptLanguage *sl=ScriptServer::get_language(i);
- String ext = sl->get_extension();
- if (ext=="")
- continue;
- script_select->add_filter("*."+ext+" ; "+sl->get_name());
- }
-
-
- script_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
-
- script_select->connect("file_selected", this,"_choose_script");
-
- error_dialog = memnew ( ConfirmationDialog );
- add_child(error_dialog);
- error_dialog->get_ok()->set_text(TTR("Accept"));
- //error_dialog->get_cancel()->hide();
-
-
- HBoxContainer *custom_root_hb = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Custom Root Node Type:"),custom_root_hb);
- root_type = memnew(Button);
- root_type->set_h_size_flags(SIZE_EXPAND_FILL);
- root_type->set_text_align(Button::ALIGN_LEFT);
- root_type->connect("pressed",this,"_root_type_pressed");
- custom_root_hb->add_child(root_type);
-
- root_default = memnew(CheckBox);
- root_default->set_text(TTR("Auto"));
- root_default->set_pressed(true);
- root_default->connect("pressed",this,"_root_default_pressed");
- custom_root_hb->add_child(root_default);
-
- root_node_name = memnew( LineEdit );
- root_node_name->set_h_size_flags(SIZE_EXPAND_FILL);
- vbc->add_margin_child(TTR("Root Node Name:"),root_node_name);
- /*
- this_import = memnew( OptionButton );
- this_import->add_item("Overwrite Existing Scene");
- this_import->add_item("Overwrite Existing, Keep Materials");
- this_import->add_item("Keep Existing, Merge with New");
- this_import->add_item("Keep Existing, Ignore New");
- vbc->add_margin_child("This Time:",this_import);
-
- next_import = memnew( OptionButton );
- next_import->add_item("Overwrite Existing Scene");
- next_import->add_item("Overwrite Existing, Keep Materials");
- next_import->add_item("Keep Existing, Merge with New");
- next_import->add_item("Keep Existing, Ignore New");
- vbc->add_margin_child("Next Time:",next_import);
-*/
- set_hide_on_ok(false);
-
- GLOBAL_DEF("import/shared_textures","res://");
- GlobalConfig::get_singleton()->set_custom_property_info("import/shared_textures",PropertyInfo(Variant::STRING,"import/shared_textures",PROPERTY_HINT_DIR));
-
- import_hb->add_constant_override("separation",30);
-
-
- VBoxContainer *ovb = memnew( VBoxContainer);
- ovb->set_h_size_flags(SIZE_EXPAND_FILL);
- import_hb->add_child(ovb);
-
- texture_options = memnew( EditorImportTextureOptions );
- ovb->add_child(texture_options);
- texture_options->set_v_size_flags(SIZE_EXPAND_FILL);
- //animation_options->set_flags(EditorImport::
- texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
- texture_options->set_flags( EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA | EditorTextureImportPlugin::IMAGE_FLAG_REPEAT | EditorTextureImportPlugin::IMAGE_FLAG_FILTER );
-
-
- animation_options = memnew( EditorImportAnimationOptions );
- ovb->add_child(animation_options);
- animation_options->set_v_size_flags(SIZE_EXPAND_FILL);
- animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
-
-
- confirm_import = memnew( ConfirmationDialog );
- add_child(confirm_import);
- VBoxContainer *cvb = memnew( VBoxContainer );
- confirm_import->add_child(cvb);
- //confirm_import->set_child_rect(cvb);
-
- PanelContainer *pc = memnew( PanelContainer );
- pc->add_style_override("panel",get_stylebox("normal","TextEdit"));
- //ec->add_child(pc);
- missing_files = memnew( RichTextLabel );
- cvb->add_margin_child(TTR("The Following Files are Missing:"),pc,true);
- pc->add_child(missing_files);
- confirm_import->get_ok()->set_text(TTR("Import Anyway"));
- confirm_import->get_cancel()->set_text(TTR("Cancel"));
- confirm_import->connect("popup_hide",this,"_dialog_hid");
- confirm_import->connect("confirmed",this,"_import_confirm");
- confirm_import->set_hide_on_ok(false);
-
- add_button(TTR("Import & Open"),!OS::get_singleton()->get_swap_ok_cancel())->connect("pressed",this,"_open_and_import");
-
- confirm_open = memnew( ConfirmationDialog );
- add_child(confirm_open);
- confirm_open->set_text(TTR("Edited scene has not been saved, open imported scene anyway?"));
- confirm_open->connect("confirmed",this,"_import",varray(true));
-
-
- wip_import=NULL;
- wip_blocked=false;
- wip_open=false;
- //texture_options->set_format(EditorImport::IMAGE_FORMAT_C);
-
- root_type_choose = memnew( CreateDialog );
- add_child(root_type_choose);
- root_type_choose->set_base_type("Node");
- root_type_choose->connect("create",this,"_set_root_type");
-}
-
-
-
-////////////////////////////////
-
-
-
-String EditorSceneImportPlugin::get_name() const {
-
- return "scene_3d";
-}
-
-String EditorSceneImportPlugin::get_visible_name() const{
-
- return TTR("Scene");
-}
-
-void EditorSceneImportPlugin::import_dialog(const String& p_from){
-
- dialog->popup_import(p_from);
-}
-
-
-//////////////////////////
-
-
-static bool _teststr(const String& p_what,const String& p_str) {
-
- if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
- return true;
- if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
- return true;
- if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
- return true;
- return false;
-}
-
-static String _fixstr(const String& p_what,const String& p_str) {
-
- if (p_what.findn("$"+p_str)!=-1) //blender and other stuff
- return p_what.replace("$"+p_str,"");
- if (p_what.to_lower().ends_with("-"+p_str)) //collada only supports "_" and "-" besides letters
- return p_what.substr(0,p_what.length()-(p_str.length()+1));
- if (p_what.to_lower().ends_with("_"+p_str)) //collada only supports "_" and "-" besides letters
- return p_what.substr(0,p_what.length()-(p_str.length()+1));
- return p_what;
-}
-
-
-
-void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<ImageTexture>, TextureRole> &image_map,int p_flags) {
-
-
- switch(p_var.get_type()) {
-
- case Variant::OBJECT: {
-
- Ref<Resource> res = p_var;
- if (res.is_valid()) {
-
- if (res->is_class("Texture") && !image_map.has(res)) {
-
- image_map.insert(res,TEXTURE_ROLE_DEFAULT);
-
-
- } else {
-
-
- List<PropertyInfo> pl;
- res->get_property_list(&pl);
- for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
-
- if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) {
- if (E->get().type==Variant::OBJECT && res->cast_to<FixedSpatialMaterial>() && (E->get().name=="textures/diffuse" || E->get().name=="textures/detail" || E->get().name=="textures/emission")) {
-
- Ref<ImageTexture> tex =res->get(E->get().name);
- if (tex.is_valid()) {
-
- image_map.insert(tex,TEXTURE_ROLE_DIFFUSE);
- }
-
- } else if (E->get().type==Variant::OBJECT && res->cast_to<FixedSpatialMaterial>() && (E->get().name=="textures/normal")) {
-
- Ref<ImageTexture> tex =res->get(E->get().name);
- if (tex.is_valid()) {
-
- image_map.insert(tex,TEXTURE_ROLE_NORMALMAP);
- /*
- if (p_flags&SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY)
- res->cast_to<FixedSpatialMaterial>()->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_XY_NORMALMAP,true);
- */
- }
-
-
- } else {
- _find_resources(res->get(E->get().name),image_map,p_flags);
- }
- }
- }
-
- }
- }
-
- } break;
- case Variant::DICTIONARY: {
-
- Dictionary d= p_var;
-
- List<Variant> keys;
- d.get_key_list(&keys);
-
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
-
- _find_resources(E->get(),image_map,p_flags);
- _find_resources(d[E->get()],image_map,p_flags);
-
- }
-
-
- } break;
- case Variant::ARRAY: {
-
- Array a = p_var;
- for(int i=0;i<a.size();i++) {
-
- _find_resources(a[i],image_map,p_flags);
- }
-
- } break;
- default: {}
-
- }
-
-}
-
-
-Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map) {
-
- // children first..
- for(int i=0;i<p_node->get_child_count();i++) {
-
-
- Node *r = _fix_node(p_node->get_child(i),p_root,collision_map,p_flags,image_map);
- if (!r) {
- print_line("was erased..");
- i--; //was erased
- }
- }
-
- String name = p_node->get_name();
-
- bool isroot = p_node==p_root;
-
-
- if (!isroot && p_flags&SCENE_FLAG_REMOVE_NOIMP && _teststr(name,"noimp")) {
-
- memdelete(p_node);
- return NULL;
- }
-
- {
-
- List<PropertyInfo> pl;
- p_node->get_property_list(&pl);
- for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {
-
- if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) {
- _find_resources(p_node->get(E->get().name),image_map,p_flags);
- }
- }
-
- }
-
-
-
-
- if (p_flags&SCENE_FLAG_CREATE_BILLBOARDS && p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- bool bb=false;
-
- if ((_teststr(name,"bb"))) {
- bb=true;
- } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) {
- bb=true;
-
- }
-
- if (bb) {
- mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
- if (mi->get_mesh().is_valid()) {
-
- Ref<Mesh> m = mi->get_mesh();
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
- if (fm.is_valid()) {
- //fm->set_flag(Material::FLAG_UNSHADED,true);
- //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- }
- }
- }
- }
- }
-
-
- if (p_flags&(SCENE_FLAG_DETECT_ALPHA|SCENE_FLAG_DETECT_VCOLOR|SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS) && p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- Ref<Mesh> m = mi->get_mesh();
-
- if (m.is_valid()) {
-
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> mat = m->surface_get_material(i);
- if (!mat.is_valid())
- continue;
-
- if (p_flags&SCENE_FLAG_DETECT_ALPHA && _teststr(mat->get_name(),"alpha")) {
-
- //mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- //mat->set_name(_fixstr(mat->get_name(),"alpha"));
- }
- if (p_flags&SCENE_FLAG_DETECT_VCOLOR && _teststr(mat->get_name(),"vcol")) {
-
- //mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true);
- //mat->set_name(_fixstr(mat->get_name(),"vcol"));
- }
-
- if (p_flags&SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS && m->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
- //mat->set_flag(Material::FLAG_LIGHTMAP_ON_UV2,true);
- }
-
- }
- }
- }
-
- if (p_flags&SCENE_FLAG_REMOVE_NOIMP && p_node->cast_to<AnimationPlayer>()) {
- //remove animations referencing non-importable nodes
- AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>();
-
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
-
- Ref<Animation> anim=ap->get_animation(E->get());
- ERR_CONTINUE(anim.is_null());
- for(int i=0;i<anim->get_track_count();i++) {
- NodePath path = anim->track_get_path(i);
-
- for(int j=0;j<path.get_name_count();j++) {
- String node = path.get_name(j);
- if (_teststr(node,"noimp")) {
- anim->remove_track(i);
- i--;
- break;
- }
- }
- }
-
- }
- }
-
-
- if (p_flags&SCENE_FLAG_CREATE_IMPOSTORS && p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- String str;
-
- if ((_teststr(name,"imp"))) {
- str=name;
- } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) {
- str=mi->get_mesh()->get_name();
-
- }
-
-
- if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
- String d=str.substr(str.find("imp")+3,str.length());
- if (d!="") {
- if ((d[0]<'0' || d[0]>'9'))
- d=d.substr(1,d.length());
- if (d.length() && d[0]>='0' && d[0]<='9') {
- float dist = d.to_double();
- mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true);
- mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true);
- //mi->set_draw_range_begin(dist);
- //mi->set_draw_range_end(100000);
-
- //mip->set_draw_range_begin(0);
- //mip->set_draw_range_end(dist);
-
- if (mi->get_mesh().is_valid()) {
-
- Ref<Mesh> m = mi->get_mesh();
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
- if (fm.is_valid()) {
- //fm->set_flag(Material::FLAG_UNSHADED,true);
- //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER);
- //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- }
- }
- }
- }
- }
- }
- }
-
- if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- String str;
-
- if ((_teststr(name,"lod"))) {
- str=name;
- } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) {
- str=mi->get_mesh()->get_name();
-
- }
-
-
- if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) {
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>();
- String d=str.substr(str.find("lod")+3,str.length());
- if (d!="") {
- if ((d[0]<'0' || d[0]>'9'))
- d=d.substr(1,d.length());
- if (d.length() && d[0]>='0' && d[0]<='9') {
- float dist = d.to_double();
- /// mi->set_draw_range_begin(dist);
- // mi->set_draw_range_end(100000);
-
- // mip->set_draw_range_begin(0);
- // mip->set_draw_range_end(dist);
-
- /*if (mi->get_mesh().is_valid()) {
-
- Ref<Mesh> m = mi->get_mesh();
- for(int i=0;i<m->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = m->surface_get_material(i);
- if (fm.is_valid()) {
- fm->set_flag(Material::FLAG_UNSHADED,true);
- fm->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true);
- fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- }
- }
- }*/
- }
- }
- }
- }
-
-
- if (p_flags&SCENE_FLAG_DETECT_LIGHTMAP_LAYER && _teststr(name,"lm") && p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- String str=name;
- int layer = str.substr(str.find("lm")+3,str.length()).to_int();
- //mi->set_baked_light_texture_id(layer);
- }
-
- if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly")) {
-
- if (isroot)
- return p_node;
-
- if (p_node->cast_to<MeshInstance>()) {
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- Node * col = mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col,NULL);
-
- col->set_name(_fixstr(name,"colonly"));
- col->cast_to<Spatial>()->set_transform(mi->get_transform());
- p_node->replace_by(col);
- memdelete(p_node);
- p_node=col;
-
- StaticBody *sb = col->cast_to<StaticBody>();
- CollisionShape *colshape = memnew( CollisionShape);
- colshape->set_shape(sb->get_shape(0));
- colshape->set_name("shape");
- sb->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
- } else if (p_node->has_meta("empty_draw_type")) {
- String empty_draw_type = String(p_node->get_meta("empty_draw_type"));
- print_line(empty_draw_type);
- StaticBody *sb = memnew( StaticBody);
- sb->set_name(_fixstr(name,"colonly"));
- sb->cast_to<Spatial>()->set_transform(p_node->cast_to<Spatial>()->get_transform());
- p_node->replace_by(sb);
- memdelete(p_node);
- CollisionShape *colshape = memnew( CollisionShape);
- if (empty_draw_type == "CUBE") {
- BoxShape *boxShape = memnew( BoxShape);
- boxShape->set_extents(Vector3(1, 1, 1));
- colshape->set_shape(boxShape);
- colshape->set_name("BoxShape");
- } else if (empty_draw_type == "SINGLE_ARROW") {
- RayShape *rayShape = memnew( RayShape);
- rayShape->set_length(1);
- colshape->set_shape(rayShape);
- colshape->set_name("RayShape");
- sb->cast_to<Spatial>()->rotate_x(Math_PI / 2);
- } else if (empty_draw_type == "IMAGE") {
- PlaneShape *planeShape = memnew( PlaneShape);
- colshape->set_shape(planeShape);
- colshape->set_name("PlaneShape");
- } else {
- SphereShape *sphereShape = memnew( SphereShape);
- sphereShape->set_radius(1);
- colshape->set_shape(sphereShape);
- colshape->set_name("SphereShape");
- }
- sb->add_child(colshape);
- colshape->set_owner(sb->get_owner());
- }
-
- } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"rigid") && p_node->cast_to<MeshInstance>()) {
-
- if (isroot)
- return p_node;
-
- // get mesh instance and bounding box
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- Rect3 aabb = mi->get_aabb();
-
- // create a new rigid body collision node
- RigidBody * rigid_body = memnew( RigidBody );
- Node * col = rigid_body;
- ERR_FAIL_COND_V(!col,NULL);
-
- // remove node name postfix
- col->set_name(_fixstr(name,"rigid"));
- // get mesh instance xform matrix to the rigid body collision node
- col->cast_to<Spatial>()->set_transform(mi->get_transform());
- // save original node by duplicating it into a new instance and correcting the name
- Node * mesh = p_node->duplicate();
- mesh->set_name(_fixstr(name,"rigid"));
- // reset the xform matrix of the duplicated node so it can inherit parent node xform
- mesh->cast_to<Spatial>()->set_transform(Transform(Basis()));
- // reparent the new mesh node to the rigid body collision node
- p_node->add_child(mesh);
- mesh->set_owner(p_node->get_owner());
- // replace the original node with the rigid body collision node
- p_node->replace_by(col);
- memdelete(p_node);
- p_node=col;
-
- // create an alias for the rigid body collision node
- RigidBody *rb = col->cast_to<RigidBody>();
- // create a new Box collision shape and set the right extents
- Ref<BoxShape> shape = memnew( BoxShape );
- shape->set_extents(aabb.get_size() * 0.5);
- CollisionShape *colshape = memnew( CollisionShape);
- colshape->set_name("shape");
- colshape->set_shape(shape);
- // reparent the new collision shape to the rigid body collision node
- rb->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
-
- } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to<MeshInstance>()) {
-
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- mi->set_name(_fixstr(name,"col"));
- Node *col= mi->create_trimesh_collision_node();
- ERR_FAIL_COND_V(!col,NULL);
-
- col->set_name("col");
- p_node->add_child(col);
-
- StaticBody *sb=col->cast_to<StaticBody>();
- CollisionShape *colshape = memnew( CollisionShape);
- colshape->set_shape(sb->get_shape(0));
- colshape->set_name("shape");
- col->add_child(colshape);
- colshape->set_owner(p_node->get_owner());
- sb->set_owner(p_node->get_owner());
-
- } else if (p_flags&SCENE_FLAG_CREATE_NAVMESH &&_teststr(name,"navmesh") && p_node->cast_to<MeshInstance>()) {
-
- if (isroot)
- return p_node;
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- Ref<Mesh> mesh=mi->get_mesh();
- ERR_FAIL_COND_V(mesh.is_null(),NULL);
- NavigationMeshInstance *nmi = memnew( NavigationMeshInstance );
-
-
- nmi->set_name(_fixstr(name,"navmesh"));
- Ref<NavigationMesh> nmesh = memnew( NavigationMesh);
- nmesh->create_from_mesh(mesh);
- nmi->set_navigation_mesh(nmesh);
- nmi->cast_to<Spatial>()->set_transform(mi->get_transform());
- p_node->replace_by(nmi);
- memdelete(p_node);
- p_node=nmi;
- } else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"vehicle")) {
-
- if (isroot)
- return p_node;
-
- Node *owner = p_node->get_owner();
- Spatial *s = p_node->cast_to<Spatial>();
- VehicleBody *bv = memnew( VehicleBody );
- String n = _fixstr(p_node->get_name(),"vehicle");
- bv->set_name(n);
- p_node->replace_by(bv);
- p_node->set_name(n);
- bv->add_child(p_node);
- bv->set_owner(owner);
- p_node->set_owner(owner);
- bv->set_transform(s->get_transform());
- s->set_transform(Transform());
-
- p_node=bv;
-
-
- } else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"wheel")) {
-
- if (isroot)
- return p_node;
-
- Node *owner = p_node->get_owner();
- Spatial *s = p_node->cast_to<Spatial>();
- VehicleWheel *bv = memnew( VehicleWheel );
- String n = _fixstr(p_node->get_name(),"wheel");
- bv->set_name(n);
- p_node->replace_by(bv);
- p_node->set_name(n);
- bv->add_child(p_node);
- bv->set_owner(owner);
- p_node->set_owner(owner);
- bv->set_transform(s->get_transform());
- s->set_transform(Transform());
-
- p_node=bv;
-
- } else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) {
-
-
- if (isroot)
- return p_node;
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
-
-
- BSP_Tree bsptree(faces);
-
- Ref<RoomBounds> area = memnew( RoomBounds );
- //area->set_bounds(faces);
- //area->set_geometry_hint(faces);
-
-
- Room * room = memnew( Room );
- room->set_name(_fixstr(name,"room"));
- room->set_transform(mi->get_transform());
- room->set_room(area);
-
- p_node->replace_by(room);
- memdelete(p_node);
- p_node=room;
-
- } else if (p_flags&SCENE_FLAG_CREATE_ROOMS &&_teststr(name,"room")) {
-
- if (isroot)
- return p_node;
-
- Spatial *dummy = p_node->cast_to<Spatial>();
- ERR_FAIL_COND_V(!dummy,NULL);
-
- Room * room = memnew( Room );
- room->set_name(_fixstr(name,"room"));
- room->set_transform(dummy->get_transform());
-
- p_node->replace_by(room);
- memdelete(p_node);
- p_node=room;
-
- //room->compute_room_from_subtree();
-
- } else if (p_flags&SCENE_FLAG_CREATE_PORTALS &&_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) {
-
- if (isroot)
- return p_node;
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
- PoolVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID);
-
- ERR_FAIL_COND_V(faces.size()==0,NULL);
- //step 1 compute the plane
- Set<Vector3> points;
- Plane plane;
-
- Vector3 center;
-
- for(int i=0;i<faces.size();i++) {
-
- Face3 f = faces.get(i);
- Plane p = f.get_plane();
- plane.normal+=p.normal;
- plane.d+=p.d;
-
- for(int i=0;i<3;i++) {
-
- Vector3 v = f.vertex[i].snapped(0.01);
- if (!points.has(v)) {
- points.insert(v);
- center+=v;
- }
- }
- }
-
- plane.normal.normalize();
- plane.d/=faces.size();
- center/=points.size();
-
- //step 2, create points
-
- Transform t;
- t.basis.from_z(plane.normal);
- t.basis.transpose();
- t.origin=center;
-
- Vector<Point2> portal_points;
-
- for(Set<Vector3>::Element *E=points.front();E;E=E->next()) {
-
- Vector3 local = t.xform_inv(E->get());
- portal_points.push_back(Point2(local.x,local.y));
- }
- // step 3 bubbly sort points
-
- int swaps=0;
-
- do {
- swaps=0;
-
- for(int i=0;i<portal_points.size()-1;i++) {
-
- float a = portal_points[i].angle();
- float b = portal_points[i+1].angle();
-
- if (a>b) {
- SWAP( portal_points[i], portal_points[i+1] );
- swaps++;
- }
-
- }
-
- } while(swaps);
-
-
- Portal *portal = memnew( Portal );
-
- portal->set_shape(portal_points);
- portal->set_transform( mi->get_transform() * t);
-
- p_node->replace_by(portal);
- memdelete(p_node);
- p_node=portal;
-
- } else if (p_node->cast_to<MeshInstance>()) {
-
- //last attempt, maybe collision insde the mesh data
-
- MeshInstance *mi = p_node->cast_to<MeshInstance>();
-
- Ref<Mesh> mesh = mi->get_mesh();
- if (!mesh.is_null()) {
-
- if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(mesh->get_name(),"col")) {
-
- mesh->set_name( _fixstr(mesh->get_name(),"col") );
- Ref<Shape> shape;
-
- if (collision_map.has(mesh)) {
- shape = collision_map[mesh];
-
- } else {
-
- shape = mesh->create_trimesh_shape();
- if (!shape.is_null())
- collision_map[mesh]=shape;
-
-
- }
-
- if (!shape.is_null()) {
-#if 0
- StaticBody* static_body = memnew( StaticBody );
- ERR_FAIL_COND_V(!static_body,NULL);
- static_body->set_name( String(mesh->get_name()) + "_col" );
- shape->set_name(static_body->get_name());
- static_body->add_shape(shape);
-
- mi->add_child(static_body);
- if (mi->get_owner())
- static_body->set_owner( mi->get_owner() );
-#endif
- }
-
- }
-
- for(int i=0;i<mesh->get_surface_count();i++) {
-
- Ref<FixedSpatialMaterial> fm = mesh->surface_get_material(i);
- if (fm.is_valid()) {
- String name = fm->get_name();
- /* if (_teststr(name,"alpha")) {
- fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true);
- name=_fixstr(name,"alpha");
- }
-
- if (_teststr(name,"vcol")) {
- fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true);
- name=_fixstr(name,"vcol");
- }*/
- fm->set_name(name);
- }
- }
-
- }
-
- }
-
-
- return p_node;
-}
-
-
-
-
-#if 0
-
-Error EditorImport::import_scene(const String& p_path,const String& p_dest_path,const String& p_resource_path,uint32_t p_flags,ImageFormat p_image_format,ImageCompression p_image_compression,uint32_t p_image_flags,float p_quality,uint32_t animation_flags,Node **r_scene,Ref<EditorPostImport> p_post_import) {
-
-
-}
-#endif
-
-void EditorSceneImportPlugin::_tag_import_paths(Node *p_scene,Node *p_node) {
-
- if (p_scene!=p_node && p_node->get_owner()!=p_scene)
- return;
-
- NodePath path = p_scene->get_path_to(p_node);
- p_node->set_import_path( path );
-
- Spatial *snode=p_node->cast_to<Spatial>();
-
- if (snode) {
-
- snode->set_import_transform(snode->get_transform());
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
- _tag_import_paths(p_scene,p_node->get_child(i));
- }
-
-}
-
-Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from,Node**r_node,List<String> *r_missing) {
-
- Ref<ResourceImportMetadata> from=p_from;
-
- ERR_FAIL_COND_V(from->get_source_count()!=1,ERR_INVALID_PARAMETER);
-
- String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
-
- Ref<EditorSceneImporter> importer;
- String ext=src_path.get_extension().to_lower();
-
-
- EditorProgress progress("import",TTR("Import Scene"),104);
- progress.step(TTR("Importing Scene.."),0);
-
- for(int i=0;i<importers.size();i++) {
-
- List<String> extensions;
- importers[i]->get_extensions(&extensions);
-
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- if (E->get().to_lower()==ext) {
-
- importer = importers[i];
- break;
- }
- }
-
- if (importer.is_valid())
- break;
- }
-
- ERR_FAIL_COND_V(!importer.is_valid(),ERR_FILE_UNRECOGNIZED);
-
- int animation_flags=p_from->get_option("animation_flags");
- int scene_flags = from->get_option("flags");
- int fps = 24;
- if (from->has_option("animation_bake_fps"))
- fps=from->get_option("animation_bake_fps");
-
-
- Array clips;
- if (from->has_option("animation_clips"))
- clips=from->get_option("animation_clips");
-
- uint32_t import_flags=0;
- if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP)
- import_flags|=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
- if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS)
- import_flags |= EditorSceneImporter::IMPORT_ANIMATION_KEEP_VALUE_TRACKS;
- if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
- import_flags|=EditorSceneImporter::IMPORT_ANIMATION_OPTIMIZE;
- if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS)
- import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS;
- if (scene_flags&SCENE_FLAG_IMPORT_ANIMATIONS)
- import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
- /*
- if (scene_flags&SCENE_FLAG_FAIL_ON_MISSING_IMAGES)
- import_flags|=EditorSceneImporter::IMPORT_FAIL_ON_MISSING_DEPENDENCIES;
- */
- if (scene_flags&SCENE_FLAG_GENERATE_TANGENT_ARRAYS)
- import_flags|=EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS;
-
-
-
-
-
- Error err=OK;
- Node *scene = importer->import_scene(src_path,import_flags,fps,r_missing,&err);
- if (!scene || err!=OK) {
- return err;
- }
-
- if (from->has_option("root_type")) {
- String type = from->get_option("root_type");
- Object *base = ClassDB::instance(type);
- Node *base_node = NULL;
- if (base)
- base_node=base->cast_to<Node>();
-
- if (base_node) {
-
- scene->replace_by(base_node);
- memdelete(scene);
- scene=base_node;
- }
- }
-
- scene->set_name(from->get_option("root_name"));
- _tag_import_paths(scene,scene);
-
- *r_node=scene;
- return OK;
-}
-
-
-void EditorSceneImportPlugin::_create_clips(Node *scene, const Array& p_clips,bool p_bake_all) {
-
- if (!scene->has_node(String("AnimationPlayer")))
- return;
-
- Node* n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
- ERR_FAIL_COND(!anim);
-
- if (!anim->has_animation("default"))
- return;
-
-
- Ref<Animation> default_anim = anim->get_animation("default");
-
- for(int i=0;i<p_clips.size();i+=4) {
-
- String name = p_clips[i];
- float from=p_clips[i+1];
- float to=p_clips[i+2];
- bool loop=p_clips[i+3];
- if (from>=to)
- continue;
-
- Ref<Animation> new_anim = memnew( Animation );
-
- for(int j=0;j<default_anim->get_track_count();j++) {
-
-
- List<float> keys;
- int kc = default_anim->track_get_key_count(j);
- int dtrack=-1;
- for(int k=0;k<kc;k++) {
-
- float kt = default_anim->track_get_key_time(j,k);
- if (kt>=from && kt<to) {
-
- //found a key within range, so create track
- if (dtrack==-1) {
- new_anim->add_track(default_anim->track_get_type(j));
- dtrack = new_anim->get_track_count()-1;
- new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
-
- if (kt>(from+0.01) && k>0) {
-
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_interpolate(j,from,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,0,p,q,s);
- }
- }
-
- }
-
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_get_key(j,k,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,kt-from,p,q,s);
- }
-
- }
-
- if (dtrack!=-1 && kt>=to) {
-
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_interpolate(j,to,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
- }
- }
-
- }
-
- if (dtrack==-1 && p_bake_all) {
- new_anim->add_track(default_anim->track_get_type(j));
- dtrack = new_anim->get_track_count()-1;
- new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
- if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
-
-
- Quat q;
- Vector3 p;
- Vector3 s;
- default_anim->transform_track_interpolate(j,from,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,0,p,q,s);
- default_anim->transform_track_interpolate(j,to,&p,&q,&s);
- new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
- }
-
- }
- }
-
-
- new_anim->set_loop(loop);
- new_anim->set_length(to-from);
- anim->add_animation(name,new_anim);
- }
-
- anim->remove_animation("default"); //remove default (no longer needed)
-}
-
-void EditorSceneImportPlugin::_filter_anim_tracks(Ref<Animation> anim,Set<String> &keep) {
-
- Ref<Animation> a = anim;
- ERR_FAIL_COND(!a.is_valid());
-
- print_line("From Anim "+anim->get_name()+":");
-
- for(int j=0;j<a->get_track_count();j++) {
-
- String path = a->track_get_path(j);
-
- if (!keep.has(path)) {
-
- print_line("Remove: "+path);
- a->remove_track(j);
- j--;
- }
-
- }
-}
-
-
-void EditorSceneImportPlugin::_filter_tracks(Node *scene, const String& p_text) {
-
- if (!scene->has_node(String("AnimationPlayer")))
- return;
- Node* n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
- ERR_FAIL_COND(!anim);
-
- Vector<String> strings = p_text.split("\n");
- for(int i=0;i<strings.size();i++) {
-
- strings[i]=strings[i].strip_edges();
- }
-
- List<StringName> anim_names;
- anim->get_animation_list(&anim_names);
- for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
-
- String name = E->get();
- bool valid_for_this=false;
- bool valid=false;
-
- Set<String> keep;
- Set<String> keep_local;
-
-
- for(int i=0;i<strings.size();i++) {
-
-
- if (strings[i].begins_with("@")) {
-
- valid_for_this=false;
- for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
- keep.insert(F->get());
- }
- keep_local.clear();
-
- Vector<String> filters=strings[i].substr(1,strings[i].length()).split(",");
- for(int j=0;j<filters.size();j++) {
-
- String fname = filters[j].strip_edges();
- if (fname=="")
- continue;
- int fc = fname[0];
- bool plus;
- if (fc=='+')
- plus=true;
- else if (fc=='-')
- plus=false;
- else
- continue;
-
- String filter=fname.substr(1,fname.length()).strip_edges();
-
- if (!name.matchn(filter))
- continue;
- valid_for_this=plus;
- }
-
- if (valid_for_this)
- valid=true;
-
- } else if (valid_for_this) {
-
- Ref<Animation> a = anim->get_animation(name);
- if (!a.is_valid())
- continue;
-
- for(int j=0;j<a->get_track_count();j++) {
-
- String path = a->track_get_path(j);
-
- String tname = strings[i];
- if (tname=="")
- continue;
- int fc = tname[0];
- bool plus;
- if (fc=='+')
- plus=true;
- else if (fc=='-')
- plus=false;
- else
- continue;
-
- String filter=tname.substr(1,tname.length()).strip_edges();
-
- if (!path.matchn(filter))
- continue;
-
- if (plus)
- keep_local.insert(path);
- else if (!keep.has(path)) {
- keep_local.erase(path);
- }
- }
-
- }
-
- }
-
- if (valid) {
- for(Set<String>::Element *F=keep_local.front();F;F=F->next()) {
- keep.insert(F->get());
- }
- print_line("FILTERING ANIM: "+String(E->get()));
- _filter_anim_tracks(anim->get_animation(name),keep);
- } else {
- print_line("NOT FILTERING ANIM: "+String(E->get()));
-
- }
-
- }
-
-
-
-}
-
-void EditorSceneImportPlugin::_optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle) {
-
- if (!scene->has_node(String("AnimationPlayer")))
- return;
- Node* n = scene->get_node(String("AnimationPlayer"));
- ERR_FAIL_COND(!n);
- AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
- ERR_FAIL_COND(!anim);
-
-
- List<StringName> anim_names;
- anim->get_animation_list(&anim_names);
- for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
-
- Ref<Animation> a = anim->get_animation(E->get());
- a->optimize(p_max_lin_error,p_max_ang_error,Math::deg2rad(p_max_angle));
- }
-}
-
-
-void EditorSceneImportPlugin::_find_resources_to_merge(Node *scene, Node *node, bool p_merge_material, Map<String, Ref<Material> > &materials, bool p_merge_anims, Map<String,Ref<Animation> >& merged_anims,Set<Ref<Mesh> > &tested_meshes) {
-
- if (node!=scene && node->get_owner()!=scene)
- return;
-
- String path = scene->get_path_to(node);
-
- if (p_merge_anims && node->cast_to<AnimationPlayer>()) {
-
- AnimationPlayer *ap = node->cast_to<AnimationPlayer>();
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for (List<StringName>::Element *E=anims.front();E;E=E->next()) {
- Ref<Animation> anim = ap->get_animation(E->get());
- Ref<Animation> clone;
-
- bool has_user_tracks=false;
-
- for(int i=0;i<anim->get_track_count();i++) {
-
- if (!anim->track_is_imported(i)) {
- has_user_tracks=true;
- break;
- }
- }
-
- if (has_user_tracks) {
-
- clone = anim->duplicate();
- for(int i=0;i<clone->get_track_count();i++) {
- if (clone->track_is_imported(i)) {
- clone->remove_track(i);
- i--;
- }
- }
-
- merged_anims[path+"::"+String(E->get())]=clone;
- }
- }
- }
-
-
-
- if (p_merge_material && node->cast_to<MeshInstance>()) {
- MeshInstance *mi=node->cast_to<MeshInstance>();
- Ref<Mesh> mesh = mi->get_mesh();
- if (mesh.is_valid() && mesh->get_name()!=String() && !tested_meshes.has(mesh)) {
-
- for(int i=0;i<mesh->get_surface_count();i++) {
- Ref<Material> material = mesh->surface_get_material(i);
-
- if (material.is_valid()) {
-
- String sname = mesh->surface_get_name(i);
- if (sname=="")
- sname="surf_"+itos(i);
-
- sname=mesh->get_name()+":surf:"+sname;
- materials[sname]=material;
- }
- }
-
- tested_meshes.insert(mesh);
- }
-
- if (mesh.is_valid()) {
-
- for(int i=0;i<mesh->get_surface_count();i++) {
- Ref<Material> material = mi->get_surface_material(i);
- if (material.is_valid()) {
- String sname = mesh->surface_get_name(i);
- if (sname=="")
- sname="surf_"+itos(i);
-
- sname=path+":inst_surf:"+sname;
- materials[sname]=material;
- }
- }
-
- }
-
- Ref<Material> override = mi->get_material_override();
-
- if (override.is_valid()) {
-
- materials[path+":override"]=override;
- }
- }
-
-
-
- for(int i=0;i<node->get_child_count();i++) {
- _find_resources_to_merge(scene,node->get_child(i),p_merge_material,materials,p_merge_anims,merged_anims,tested_meshes);
- }
-
-}
-
-
-void EditorSceneImportPlugin::_merge_found_resources(Node *scene, Node *node, bool p_merge_material, const Map<String, Ref<Material> > &materials, bool p_merge_anims, const Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes) {
-
- if (node!=scene && node->get_owner()!=scene)
- return;
-
- String path = scene->get_path_to(node);
-
- print_line("at path: "+path);
-
- if (node->cast_to<AnimationPlayer>()) {
-
- AnimationPlayer *ap = node->cast_to<AnimationPlayer>();
- List<StringName> anims;
- ap->get_animation_list(&anims);
- for (List<StringName>::Element *E=anims.front();E;E=E->next()) {
- Ref<Animation> anim = ap->get_animation(E->get());
-
- String anim_path = path+"::"+String(E->get());
-
- if (merged_anims.has(anim_path)) {
-
- Ref<Animation> user_tracks = merged_anims[anim_path];
- for(int i=0;i<user_tracks->get_track_count();i++) {
-
- int idx = anim->get_track_count();
- anim->add_track(user_tracks->track_get_type(i));
- anim->track_set_path(idx,user_tracks->track_get_path(i));
- anim->track_set_interpolation_type(idx,user_tracks->track_get_interpolation_type(i));
- for(int j=0;j<user_tracks->track_get_key_count(i);j++) {
-
- float ofs = user_tracks->track_get_key_time(i,j);
- float trans = user_tracks->track_get_key_transition(i,j);
- Variant value = user_tracks->track_get_key_value(i,j);
-
- anim->track_insert_key(idx,ofs,value,trans);
- }
- }
- }
- }
- }
-
-
-
- if (node->cast_to<MeshInstance>()) {
- MeshInstance *mi=node->cast_to<MeshInstance>();
- Ref<Mesh> mesh = mi->get_mesh();
- if (mesh.is_valid() && mesh->get_name()!=String() && !tested_meshes.has(mesh)) {
-
- for(int i=0;i<mesh->get_surface_count();i++) {
-
- String sname = mesh->surface_get_name(i);
- if (sname=="")
- sname="surf_"+itos(i);
-
- sname=mesh->get_name()+":surf:"+sname;
-
-
- if (materials.has(sname)) {
-
- mesh->surface_set_material(i,materials[sname]);
- }
- }
-
- tested_meshes.insert(mesh);
- }
-
- if (mesh.is_valid()) {
-
- for(int i=0;i<mesh->get_surface_count();i++) {
-
- String sname = mesh->surface_get_name(i);
- if (sname=="")
- sname="surf_"+itos(i);
-
- sname=path+":inst_surf:"+sname;
-
-
- if (materials.has(sname)) {
-
- mi->set_surface_material(i,materials[sname]);
- }
- }
-
- }
-
-
- String opath = path+":override";
- if (materials.has(opath)) {
- mi->set_material_override(materials[opath]);
- }
-
- }
-
-
-
- for(int i=0;i<node->get_child_count();i++) {
- _merge_found_resources(scene,node->get_child(i),p_merge_material,materials,p_merge_anims,merged_anims,tested_meshes);
- }
-
-}
-
-Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
-
- Error err=OK;
- Ref<ResourceImportMetadata> from=p_from;
- String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
- int animation_flags=p_from->get_option("animation_flags");
- Array animation_clips = p_from->get_option("animation_clips");
- String animation_filter = p_from->get_option("animation_filters");
- int scene_flags = from->get_option("flags");
- float anim_optimizer_linerr=0.05;
- float anim_optimizer_angerr=0.01;
- float anim_optimizer_maxang=22;
-
- if (from->has_option("animation_optimizer_linear_error"))
- anim_optimizer_linerr=from->get_option("animation_optimizer_linear_error");
- if (from->has_option("animation_optimizer_angular_error"))
- anim_optimizer_angerr=from->get_option("animation_optimizer_angular_error");
- if (from->has_option("animation_optimizer_max_angle"))
- anim_optimizer_maxang=from->get_option("animation_optimizer_max_angle");
-
- EditorProgress progress("import",TTR("Import Scene"),104);
- progress.step(TTR("Importing Scene.."),2);
-
-
- from->set_source_md5(0,FileAccess::get_md5(src_path));
- from->set_editor(get_name());
-
- from->set_option("reimport",false);
- String target_res_path=p_dest_path.get_base_dir();
-
- Map<Ref<Mesh>,Ref<Shape> > collision_map;
-
- Map< Ref<ImageTexture>,TextureRole > imagemap;
-
- scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
- if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
- _optimize_animations(scene,anim_optimizer_linerr,anim_optimizer_angerr,anim_optimizer_maxang);
- if (animation_clips.size())
- _create_clips(scene,animation_clips,animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
-
- _filter_tracks(scene,animation_filter);
-
-
- if (scene_flags&(SCENE_FLAG_MERGE_KEEP_MATERIALS|SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS) && FileAccess::exists(p_dest_path)) {
- //must merge!
-
- print_line("MUST MERGE");
- Ref<PackedScene> pscene = ResourceLoader::load(p_dest_path,"PackedScene",true);
- if (pscene.is_valid()) {
-
- Node *instance = pscene->instance();
- if (instance) {
- Map<String,Ref<Animation> > merged_anims;
- Map<String,Ref<Material> > merged_materials;
- Set<Ref<Mesh> > tested_meshes;
-
- _find_resources_to_merge(instance,instance,scene_flags&SCENE_FLAG_MERGE_KEEP_MATERIALS,merged_materials,scene_flags&SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,merged_anims,tested_meshes);
-
- tested_meshes.clear();
- _merge_found_resources(scene,scene,scene_flags&SCENE_FLAG_MERGE_KEEP_MATERIALS,merged_materials,scene_flags&SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS,merged_anims,tested_meshes);
-
- memdelete(instance);
- }
-
- }
-
- }
-
- /// BEFORE ANYTHING, RUN SCRIPT
-
- progress.step(TTR("Running Custom Script.."),2);
-
- String post_import_script_path = from->get_option("post_import_script");
- Ref<EditorScenePostImport> post_import_script;
-
- if (post_import_script_path!="") {
- post_import_script_path = post_import_script_path;
- Ref<Script> scr = ResourceLoader::load(post_import_script_path);
- if (!scr.is_valid()) {
- EditorNode::add_io_error(TTR("Couldn't load post-import script:")+" "+post_import_script_path);
- } else {
-
- post_import_script = Ref<EditorScenePostImport>( memnew( EditorScenePostImport ) );
- post_import_script->set_script(scr.get_ref_ptr());
- if (!post_import_script->get_script_instance()) {
- EditorNode::add_io_error(TTR("Invalid/broken script for post-import (check console):")+" "+post_import_script_path);
- post_import_script.unref();
- return ERR_CANT_CREATE;
- }
- }
- }
-
-
- if (post_import_script.is_valid()) {
- scene = post_import_script->post_import(scene);
- if (!scene) {
- EditorNode::add_io_error(TTR("Error running post-import script:")+" "+post_import_script_path);
- return err;
- }
-
-
- }
-
-
- /// IMPORT IMAGES
-
-
- int idx=0;
-
- int image_format = from->get_option("texture_format");
- int image_flags = from->get_option("texture_flags");
- float image_quality = from->get_option("texture_quality");
-
- for (Map< Ref<ImageTexture>,TextureRole >::Element *E=imagemap.front();E;E=E->next()) {
-
- //texture could be converted to something more useful for 3D, that could load individual mipmaps and stuff
- //but not yet..
-
- Ref<ImageTexture> texture = E->key();
-
- ERR_CONTINUE(!texture.is_valid());
-
- String path = texture->get_path();
- String fname= path.get_file();
- String target_path = GlobalConfig::get_singleton()->localize_path(target_res_path.plus_file(fname));
- progress.step(TTR("Import Image:")+" "+fname,3+(idx)*100/imagemap.size());
-
- idx++;
-
- if (path==target_path) {
-
- EditorNode::add_io_error(TTR("Can't import a file over itself:")+" "+target_path);
- continue;
- }
-
- if (!target_path.begins_with("res://")) {
- EditorNode::add_io_error(vformat(TTR("Couldn't localize path: %s (already local)"),target_path));
- continue;
- }
-
-
- {
-
-
- target_path=target_path.get_basename()+".tex";
-
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
-
- uint32_t flags = image_flags;
- if (E->get()==TEXTURE_ROLE_DIFFUSE && scene_flags&SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES)
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR;
-
- if (E->get()==TEXTURE_ROLE_NORMALMAP && scene_flags&SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY)
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_NORMAL_TO_XY;
-
- imd->set_option("flags",flags);
- imd->set_option("format",image_format);
- imd->set_option("quality",image_quality);
- imd->set_option("atlas",false);
- imd->add_source(EditorImportPlugin::validate_source_path(path));
-
-
- if (FileAccess::exists(target_path)) {
-
- Ref<ResourceImportMetadata> rimdex = ResourceLoader::load_import_metadata(target_path);
- if (rimdex.is_valid()) {
- //make sure the options are the same, otherwise re-import
- List<String> opts;
- imd->get_options(&opts);
- bool differ=false;
- for (List<String>::Element *E=opts.front();E;E=E->next()) {
- if (!(rimdex->get_option(E->get())==imd->get_option(E->get()))) {
- differ=true;
- break;
- }
- }
-
- if (!differ) {
- texture->set_path(target_path);
- continue; //already imported
- }
- }
- }
-
- EditorTextureImportPlugin::get_singleton()->import(target_path,imd);
-
- }
- }
-
-
-
- progress.step(TTR("Saving.."),104);
-
- Ref<PackedScene> packer = memnew( PackedScene );
- packer->pack(scene);
- //packer->set_path(p_dest_path); do not take over, let the changed files reload themselves
- packer->set_import_metadata(from);
-
- print_line("SAVING TO: "+p_dest_path);
- err = ResourceSaver::save(p_dest_path,packer); //do not take over, let the changed files reload themselves
-
- //EditorFileSystem::get_singleton()->update_resource(packer);
-
- memdelete(scene);
-
- /*
- scene->set_filename(p_dest_path);
- if (r_scene) {
- *r_scene=scene;
- } else {
- memdelete(scene);
- }
-
- String sp;
- if (p_post_import.is_valid() && !p_post_import->get_script().is_null()) {
- Ref<Script> scr = p_post_import->get_script();
- if (scr.is_valid())
- sp=scr->get_path();
- }
-
- String op=_getrelpath(p_path,p_dest_path);
-
- */
-
- EditorNode::get_singleton()->reload_scene(p_dest_path);
-
- return err;
-
-}
-
-
-Error EditorSceneImportPlugin::import(const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from){
-
-
- Node *n=NULL;
- Error err = import1(p_from,&n);
- if (err!=OK) {
- if (n) {
- memdelete(n);
- }
- return err;
- }
- return import2(n,p_dest_path,p_from);
-}
-
-void EditorSceneImportPlugin::add_importer(const Ref<EditorSceneImporter>& p_importer) {
-
- importers.push_back(p_importer);
-}
-
-void EditorSceneImportPlugin::import_from_drop(const Vector<String>& p_drop,const String& p_dest_path) {
-
- List<String> extensions;
- for(int i=0;i<importers.size();i++) {
- importers[i]->get_extensions(&extensions);
- }
- //bool warn_compatible=false;
- for(int i=0;i<p_drop.size();i++) {
-
- String extension = p_drop[i].get_extension().to_lower();
-
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- if (E->get()==extension) {
-
- dialog->popup_import(String());
- dialog->setup_popup(p_drop[i],p_dest_path);
- return;
- }
- }
- }
-
-}
-
-
-EditorSceneImportPlugin::EditorSceneImportPlugin(EditorNode* p_editor) {
-
- dialog = memnew( EditorSceneImportDialog(p_editor,this) );
- p_editor->get_gui_base()->add_child(dialog);
-}
-
-
-///////////////////////////////
-
-
-String EditorSceneAnimationImportPlugin::get_name() const {
-
- return "anim_3d";
-}
-String EditorSceneAnimationImportPlugin::get_visible_name() const{
-
-
- return TTR("3D Scene Animation");
-}
-void EditorSceneAnimationImportPlugin::import_dialog(const String& p_from){
-
-
-}
-Error EditorSceneAnimationImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
-
- return OK;
-}
-
-EditorSceneAnimationImportPlugin::EditorSceneAnimationImportPlugin(EditorNode* p_editor) {
-
-
-}
-#endif
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.h b/tools/editor/io_plugins/editor_scene_import_plugin.h
deleted file mode 100644
index bbafc126bb..0000000000
--- a/tools/editor/io_plugins/editor_scene_import_plugin.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*************************************************************************/
-/* editor_scene_import_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_SCENE_IMPORT_PLUGIN_H
-#define EDITOR_SCENE_IMPORT_PLUGIN_H
-#if 0
-#include "scene/gui/dialogs.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/label.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/progress_bar.h"
-#include "scene/gui/slider.h"
-#include "scene/gui/spin_box.h"
-#include "scene/resources/mesh.h"
-#include "tools/editor/editor_file_system.h"
-#include "tools/editor/editor_dir_dialog.h"
-#include "tools/editor/editor_import_export.h"
-#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
-#include "scene/resources/animation.h"
-
-
-class EditorNode;
-class EditorSceneImportDialog;
-
-class EditorSceneImporter : public Reference {
-
- GDCLASS(EditorSceneImporter,Reference );
-public:
-
- enum ImportFlags {
- IMPORT_SCENE=1,
- IMPORT_ANIMATION=2,
- IMPORT_ANIMATION_DETECT_LOOP=4,
- IMPORT_ANIMATION_OPTIMIZE=8,
- IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=16,
- IMPORT_ANIMATION_KEEP_VALUE_TRACKS=32,
- IMPORT_GENERATE_TANGENT_ARRAYS=256,
- IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512
-
- };
-
- virtual uint32_t get_import_flags() const=0;
- virtual void get_extensions(List<String> *r_extensions) const=0;
- virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps,Error* r_err=NULL)=0;
- virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0;
-
-
-
- EditorSceneImporter();
-};
-
-/////////////////////////////////////////
-
-
-//Plugin for post processing scenes or images
-
-class EditorScenePostImport : public Reference {
-
- GDCLASS(EditorScenePostImport,Reference );
-protected:
-
- static void _bind_methods();
-public:
-
- virtual Node* post_import(Node* p_scene);
- EditorScenePostImport();
-};
-
-
-class EditorSceneImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorSceneImportPlugin,EditorImportPlugin);
-
- EditorSceneImportDialog *dialog;
-
- Vector<Ref<EditorSceneImporter> > importers;
-
- enum TextureRole {
- TEXTURE_ROLE_DEFAULT,
- TEXTURE_ROLE_DIFFUSE,
- TEXTURE_ROLE_NORMALMAP
- };
-
- void _find_resources(const Variant& p_var,Map<Ref<ImageTexture>,TextureRole >& image_map,int p_flags);
- Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map);
- void _create_clips(Node *scene, const Array& p_clips, bool p_bake_all);
- void _filter_anim_tracks(Ref<Animation> anim,Set<String> &keep);
- void _filter_tracks(Node *scene, const String& p_text);
- void _optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle);
-
- void _tag_import_paths(Node *p_scene,Node *p_node);
-
- void _find_resources_to_merge(Node *scene, Node *node, bool p_merge_material, Map<String,Ref<Material> >&materials, bool p_merge_anims, Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
- void _merge_found_resources(Node *scene, Node *node, bool p_merge_material, const Map<String, Ref<Material> > &materials, bool p_merge_anims, const Map<String,Ref<Animation> >& merged_anims, Set<Ref<Mesh> > &tested_meshes);
-
-
-public:
-
- enum SceneFlags {
-
- SCENE_FLAG_CREATE_COLLISIONS=1<<0,
- SCENE_FLAG_CREATE_PORTALS=1<<1,
- SCENE_FLAG_CREATE_ROOMS=1<<2,
- SCENE_FLAG_SIMPLIFY_ROOMS=1<<3,
- SCENE_FLAG_CREATE_BILLBOARDS=1<<4,
- SCENE_FLAG_CREATE_IMPOSTORS=1<<5,
- SCENE_FLAG_CREATE_LODS=1<<6,
- SCENE_FLAG_CREATE_CARS=1<<8,
- SCENE_FLAG_CREATE_WHEELS=1<<9,
- SCENE_FLAG_DETECT_ALPHA=1<<15,
- SCENE_FLAG_DETECT_VCOLOR=1<<16,
- SCENE_FLAG_CREATE_NAVMESH=1<<17,
- SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
-
- SCENE_FLAG_MERGE_KEEP_MATERIALS=1<<20,
- SCENE_FLAG_MERGE_KEEP_EXTRA_ANIM_TRACKS=1<<21,
-
- SCENE_FLAG_REMOVE_NOIMP=1<<24,
- SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,
- SCENE_FLAG_COMPRESS_GEOMETRY=1<<26,
- SCENE_FLAG_GENERATE_TANGENT_ARRAYS=1<<27,
- SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES=1<<28,
- SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS=1<<29,
- SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY=1<<30,
- };
-
-
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
-
- Error import1(const Ref<ResourceImportMetadata>& p_from,Node**r_node,List<String> *r_missing=NULL);
- Error import2(Node* p_scene,const String& p_path, const Ref<ResourceImportMetadata>& p_from);
-
- void add_importer(const Ref<EditorSceneImporter>& p_importer);
- const Vector<Ref<EditorSceneImporter> >& get_importers() { return importers; }
-
- virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
-
- EditorSceneImportPlugin(EditorNode* p_editor=NULL);
-
-
-};
-
-
-class EditorSceneAnimationImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorSceneAnimationImportPlugin,EditorImportPlugin);
-public:
-
-
- enum AnimationFlags {
-
- ANIMATION_DETECT_LOOP=1,
- ANIMATION_KEEP_VALUE_TRACKS=2,
- ANIMATION_OPTIMIZE=4,
- ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=8
- };
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
-
- EditorSceneAnimationImportPlugin(EditorNode* p_editor=NULL);
-
-
-};
-
-#endif
-#endif // EDITOR_SCENE_IMPORT_PLUGIN_H
diff --git a/tools/editor/io_plugins/editor_scene_importer_fbxconv.cpp b/tools/editor/io_plugins/editor_scene_importer_fbxconv.cpp
deleted file mode 100644
index af12d85650..0000000000
--- a/tools/editor/io_plugins/editor_scene_importer_fbxconv.cpp
+++ /dev/null
@@ -1,1136 +0,0 @@
-/*************************************************************************/
-/* editor_scene_importer_fbxconv.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_scene_importer_fbxconv.h"
-
-#include "os/file_access.h"
-#include "os/os.h"
-#include "tools/editor/editor_settings.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/animation/animation_player.h"
-
-#if 0
-String EditorSceneImporterFBXConv::_id(const String& p_id) const {
-
- return p_id.replace(":","_").replace("/","_");
-}
-
-uint32_t EditorSceneImporterFBXConv::get_import_flags() const {
-
- return IMPORT_SCENE|IMPORT_ANIMATION;
-}
-void EditorSceneImporterFBXConv::get_extensions(List<String> *r_extensions) const{
-
- r_extensions->push_back("fbx");
- r_extensions->push_back("g3dj");
-}
-
-
-Color EditorSceneImporterFBXConv::_get_color(const Array& a) {
-
- if (a.size()<3)
- return Color();
- Color c;
- c.r=a[0];
- c.g=a[1];
- c.b=a[2];
- if (a.size()>=4)
- c.a=a[3];
- return c;
-
-}
-
-Transform EditorSceneImporterFBXConv::_get_transform_mixed(const Dictionary& d,const Dictionary& dbase) {
-
-
-
-
- Array translation;
-
- if (d.has("translation"))
- translation=d["translation"];
- else if (dbase.has("translation"))
- translation=dbase["translation"];
-
- Array rotation;
-
- if (d.has("rotation"))
- rotation=d["rotation"];
- else if (dbase.has("rotation"))
- rotation=dbase["rotation"];
-
- Array scale;
-
- if (d.has("scale"))
- scale=d["scale"];
- else if (dbase.has("scale"))
- scale=dbase["scale"];
-
- Transform t;
-
-
- if (translation.size()) {
- Array tr = translation;
- if (tr.size()>=3) {
- t.origin.x=tr[0];
- t.origin.y=tr[1];
- t.origin.z=tr[2];
- }
- }
-
- if (rotation.size()) {
-
- Array r = rotation;
- if (r.size()>=4) {
-
- Quat q;
- q.x = r[0];
- q.y = r[1];
- q.z = r[2];
- q.w = r[3];
- t.basis=Matrix3(q);
- }
- }
-
-
- if (scale.size()) {
-
- Array sc = scale;
- if (sc.size()>=3) {
- Vector3 s;
- s.x=sc[0];
- s.y=sc[1];
- s.z=sc[2];
- t.basis.scale(s);
- }
- }
-
- return t;
-
-
-}
-
-Transform EditorSceneImporterFBXConv::_get_transform(const Dictionary& d) {
-
-
- Transform t;
-
- if (d.has("translation")) {
- Array tr = d["translation"];
- if (tr.size()>=3) {
- t.origin.x=tr[0];
- t.origin.y=tr[1];
- t.origin.z=tr[2];
- }
- }
-
- if (d.has("rotation")) {
-
- Array r = d["rotation"];
- if (r.size()>=4) {
-
- Quat q;
- q.x = r[0];
- q.y = r[1];
- q.z = r[2];
- q.w = r[3];
- t.basis=Matrix3(q);
- }
- }
-
-
- if (d.has("scale")) {
-
- Array sc = d["scale"];
- if (sc.size()>=3) {
- Vector3 s;
- s.x=sc[0];
- s.y=sc[1];
- s.z=sc[2];
- t.basis.scale(s);
- }
- }
-
- return t;
-}
-
-
-void EditorSceneImporterFBXConv::_detect_bones_in_nodes(State& state,const Array& p_nodes) {
-
-
- for(int i=0;i<p_nodes.size();i++) {
-
- Dictionary d = p_nodes[i];
- if (d.has("isBone") && bool(d["isBone"])) {
-
- String bone_name=_id(d["id"]);
- print_line("IS BONE: "+bone_name);
- if (!state.bones.has(bone_name)) {
- state.bones.insert(bone_name,BoneInfo());
- }
-
- if (!state.bones[bone_name].has_rest) {
- state.bones[bone_name].rest=_get_transform(d).affine_inverse();
- }
-
- state.bones[bone_name].node=d;
-
- //state.bones[name].rest=_get_transform(b);
- }
-
- if (d.has("parts")) {
-
- Array parts=d["parts"];
- for(int j=0;j<parts.size();j++) {
-
- Dictionary p=parts[j];
- if (p.has("bones")) {
- Array bones=p["bones"];
- //omfg
- for(int k=0;k<bones.size();k++) {
-
- Dictionary b = bones[k];
- if (b.has("node")) {
-
- String name = _id(b["node"]);
- if (!state.bones.has(name)) {
- state.bones.insert(name,BoneInfo());
- }
-
- state.bones[name].rest=_get_transform(b);
- state.bones[name].has_rest=true;
- }
- }
- }
-
- }
- }
-
- if (d.has("children")) {
-
- _detect_bones_in_nodes(state,d["children"]);
- }
- }
-
-}
-
-void EditorSceneImporterFBXConv::_parse_skeletons(const String& p_name,State& state, const Array &p_nodes, Skeleton *p_skeleton,int p_parent) {
-
-
-
- for(int i=0;i<p_nodes.size();i++) {
-
-
- Dictionary d = p_nodes[i];
- int bone_idx=-1;
- String id;
- Skeleton* skeleton=p_skeleton;
- if (d.has("id")) {
-
- id=_id(d["id"]);
- if (state.bones.has(id)) {
- //BONER
- if (!skeleton) {
- skeleton=memnew( Skeleton );
- state.skeletons[id]=skeleton;
- }
- bone_idx = skeleton->get_bone_count();
- skeleton->add_bone(id);
- skeleton->set_bone_parent(bone_idx,p_parent);
- skeleton->set_bone_rest(bone_idx,state.bones[id].rest);
- state.bones[id].skeleton=skeleton;
- }
- }
-
- if (d.has("children")) {
-
- _parse_skeletons(id,state,d["children"],skeleton,bone_idx);
- }
- }
-
-}
-
-void EditorSceneImporterFBXConv::_detect_bones(State& state) {
- //This format should mark when a node is a bone,
- //which is the only thing that Collada does right.
- //think about others implementing a parser.
- //Just _one_ string and you avoid loads of lines of code to other people.
-
- for(int i=0;i<state.animations.size();i++) {
-
- Dictionary an = state.animations[i];
- if (an.has("bones")) {
-
- Array bo=an["bones"];
- for(int j=0;j<bo.size();j++) {
-
- Dictionary b=bo[j];
- if (b.has("boneId")) {
-
- String id = b["boneId"];
- if (!state.bones.has(id)) {
- state.bones.insert(id,BoneInfo());
- }
- state.bones[id].has_anim_chan=true; //used in anim
-
-
- }
- }
- }
- }
-
- _detect_bones_in_nodes(state,state.nodes);
- _parse_skeletons("",state,state.nodes,NULL,-1);
-
- print_line("found bones: "+itos(state.bones.size()));
- print_line("found skeletons: "+itos(state.skeletons.size()));
-}
-
-Error EditorSceneImporterFBXConv::_parse_bones(State& state,const Array &p_bones,Skeleton* p_skeleton) {
-
-
-
- return OK;
-}
-
-
-void EditorSceneImporterFBXConv::_add_surface(State& state,Ref<Mesh>& m,const Dictionary &part) {
-
- if (part.has("meshpartid")) {
-
- String id = part["meshpartid"];
- ERR_FAIL_COND(!state.surface_cache.has(id));
-
-
- Ref<Material> mat;
- if (part.has("materialid")) {
- String matid=part["materialid"];
- if (state.material_cache.has(matid)) {
- mat=state.material_cache[matid];
- }
- }
- int idx = m->get_surface_count();
-
- Array array = state.surface_cache[id].array;
- PoolVector<float> indices = array[Mesh::ARRAY_BONES];
- if (indices.size() && part.has("bones")) {
-
-
- Map<int,int> index_map;
-
- Array bones=part["bones"];
-
- for(int i=0;i<bones.size();i++) {
-
- Dictionary bone=bones[i];
- String name=_id(bone["node"]);
-
- if (state.bones.has(name)) {
- int idx=state.bones[name].skeleton->find_bone(name);
- if (idx==-1)
- idx=0;
- index_map[i]=idx;
- }
- }
-
-
-
- int ilen=indices.size();
- {
- PoolVector<float>::Write iw=indices.write();
- for(int j=0;j<ilen;j++) {
- int b = iw[j];
- ERR_CONTINUE(!index_map.has(b));
- b=index_map[b];
- iw[j]=b;
- }
- }
-
- array[Mesh::ARRAY_BONES]=indices;
-
-
- }
-
- m->add_surface(state.surface_cache[id].primitive,array);
- m->surface_set_material(idx,mat);
- m->surface_set_name(idx,id);
- }
-
-}
-
-Error EditorSceneImporterFBXConv::_parse_nodes(State& state,const Array &p_nodes,Node* p_base) {
-
- for(int i=0;i<p_nodes.size();i++) {
-
- Dictionary n = p_nodes[i];
- Spatial *node=NULL;
- bool skip=false;
-
- String id;
- if (n.has("id")) {
- id=_id(n["id"]);
- }
-
- print_line("ID: "+id);
-
- if (state.skeletons.has(id)) {
-
- Skeleton *skeleton = state.skeletons[id];
- node=skeleton;
- skeleton->localize_rests();
- print_line("IS SKELETON! ");
- } else if (state.bones.has(id)) {
- if (p_base)
- node=p_base->cast_to<Spatial>();
- if (!state.bones[id].has_anim_chan) {
- print_line("no has anim "+id);
- }
- skip=true;
- } else if (n.has("parts")) {
- //is a mesh
- MeshInstance *mesh = memnew( MeshInstance );
- node=mesh;
-
- Array parts=n["parts"];
- String long_identifier;
- for(int j=0;j<parts.size();j++) {
-
- Dictionary part=parts[j];
- if (part.has("meshpartid")) {
- String partid=part["meshpartid"];
- long_identifier+=partid;
- }
- }
-
- Ref<Mesh> m;
-
- if (state.mesh_cache.has(long_identifier)) {
- m=state.mesh_cache[long_identifier];
- } else {
- m = Ref<Mesh>( memnew( Mesh ) );
-
- //and parts are surfaces
- for(int j=0;j<parts.size();j++) {
-
- Dictionary part=parts[j];
- if (part.has("meshpartid")) {
- _add_surface(state,m,part);
- }
- }
-
-
- state.mesh_cache[long_identifier]=m;
- }
-
- mesh->set_mesh(m);
- }
-
- if (!skip) {
-
- if (!node) {
- node = memnew( Spatial );
- }
-
- node->set_name(id);
- node->set_transform(_get_transform(n));
- p_base->add_child(node);
- node->set_owner(state.scene);
- }
-
-
- if (n.has("children")) {
- Error err = _parse_nodes(state,n["children"],node);
- if (err)
- return err;
- }
- }
-
- return OK;
-}
-
-
-void EditorSceneImporterFBXConv::_parse_materials(State& state) {
-
- for(int i=0;i<state.materials.size();i++) {
-
- Dictionary material = state.materials[i];
-
- ERR_CONTINUE(!material.has("id"));
- String id = _id(material["id"]);
-
- Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
-
- if (material.has("diffuse")) {
- mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,_get_color(material["diffuse"]));
- }
-
- if (material.has("specular")) {
- mat->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR,_get_color(material["specular"]));
- }
-
- if (material.has("emissive")) {
- mat->set_parameter(FixedSpatialMaterial::PARAM_EMISSION,_get_color(material["emissive"]));
- }
-
- if (material.has("shininess")) {
- float exp = material["shininess"];
- mat->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR_EXP,exp);
- }
-
- if (material.has("opacity")) {
- Color c = mat->get_parameter(FixedSpatialMaterial::PARAM_DIFFUSE);
- c.a=material["opacity"];
- mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,c);
- }
-
-
- if (material.has("textures")) {
-
- Array textures = material["textures"];
- for(int j=0;j<textures.size();j++) {
-
- Dictionary texture=textures[j];
- Ref<Texture> tex;
- if (texture.has("filename")) {
-
-
- String filename=texture["filename"];
- String path=state.base_path+"/"+filename.replace("\\","/");
- if (state.texture_cache.has(path)) {
- tex=state.texture_cache[path];
- } else {
- tex = ResourceLoader::load(path,"ImageTexture");
- if (tex.is_null()) {
- if (state.missing_deps)
- state.missing_deps->push_back(path);
- }
- state.texture_cache[path]=tex; //add anyway
- }
- }
-
- if (tex.is_valid() && texture.has("type")) {
-
- String type=texture["type"];
- if (type=="DIFFUSE")
- mat->set_texture(FixedSpatialMaterial::PARAM_DIFFUSE,tex);
- else if (type=="SPECULAR")
- mat->set_texture(FixedSpatialMaterial::PARAM_SPECULAR,tex);
- else if (type=="SHININESS")
- mat->set_texture(FixedSpatialMaterial::PARAM_SPECULAR_EXP,tex);
- else if (type=="NORMAL")
- mat->set_texture(FixedSpatialMaterial::PARAM_NORMAL,tex);
- else if (type=="EMISSIVE")
- mat->set_texture(FixedSpatialMaterial::PARAM_EMISSION,tex);
- }
-
- }
- }
-
- state.material_cache[id]=mat;
-
- }
-
-}
-
-void EditorSceneImporterFBXConv::_parse_surfaces(State& state) {
-
- for(int i=0;i<state.meshes.size();i++) {
-
- Dictionary mesh = state.meshes[i];
-
- ERR_CONTINUE(!mesh.has("attributes"));
- ERR_CONTINUE(!mesh.has("vertices"));
- ERR_CONTINUE(!mesh.has("parts"));
-
- print_line("MESH #"+itos(i));
-
- Array attrlist=mesh["attributes"];
- Array vertices=mesh["vertices"];
- bool exists[Mesh::ARRAY_MAX];
- int ofs[Mesh::ARRAY_MAX];
- int weight_max=0;
- int binormal_ofs=-1;
- int weight_ofs[4];
-
- for(int j=0;j<Mesh::ARRAY_MAX;j++) {
- exists[j]=false;
- ofs[j]=0;
- }
- exists[Mesh::ARRAY_INDEX]=true;
- float stride=0;
-
- for(int j=0;j<attrlist.size();j++) {
-
- String attr=attrlist[j];
- if (attr=="POSITION") {
- exists[Mesh::ARRAY_VERTEX]=true;
- ofs[Mesh::ARRAY_VERTEX]=stride;
- stride+=3;
- } else if (attr=="NORMAL") {
- exists[Mesh::ARRAY_NORMAL]=true;
- ofs[Mesh::ARRAY_NORMAL]=stride;
- stride+=3;
- } else if (attr=="COLOR") {
- exists[Mesh::ARRAY_COLOR]=true;
- ofs[Mesh::ARRAY_COLOR]=stride;
- stride+=4;
- } else if (attr=="COLORPACKED") {
- stride+=1; //ignore
- } else if (attr=="TANGENT") {
- exists[Mesh::ARRAY_TANGENT]=true;
- ofs[Mesh::ARRAY_TANGENT]=stride;
- stride+=3;
- } else if (attr=="BINORMAL") {
- binormal_ofs=stride;
- stride+=3;
- } else if (attr=="TEXCOORD0") {
- exists[Mesh::ARRAY_TEX_UV]=true;
- ofs[Mesh::ARRAY_TEX_UV]=stride;
- stride+=2;
- } else if (attr=="TEXCOORD1") {
- exists[Mesh::ARRAY_TEX_UV2]=true;
- ofs[Mesh::ARRAY_TEX_UV2]=stride;
- stride+=2;
- } else if (attr.begins_with("TEXCOORD")) {
- stride+=2;
- } else if (attr.begins_with("BLENDWEIGHT")) {
- int idx=attr.replace("BLENDWEIGHT","").to_int();
- if (idx==0) {
- exists[Mesh::ARRAY_BONES]=true;
- ofs[Mesh::ARRAY_BONES]=stride;
- exists[Mesh::ARRAY_WEIGHTS]=true;
- ofs[Mesh::ARRAY_WEIGHTS]=stride+1;
- } if (idx<4) {
- weight_ofs[idx]=stride;
- weight_max=MAX(weight_max,idx+1);
- }
-
- stride+=2;
- }
-
- print_line("ATTR "+attr+" OFS: "+itos(stride));
-
- }
-
- Array parts=mesh["parts"];
-
- for(int j=0;j<parts.size();j++) {
-
-
-
- Dictionary part=parts[j];
- ERR_CONTINUE(!part.has("indices"));
- ERR_CONTINUE(!part.has("id"));
-
- print_line("PART: "+String(part["id"]));
- Array indices=part["indices"];
- Map<int,int> iarray;
- Map<int,int> array;
-
- for(int k=0;k<indices.size();k++) {
-
- int idx = indices[k];
- if (!iarray.has(idx)) {
- int map_to=array.size();
- iarray[idx]=map_to;
- array[map_to]=idx;
- }
- }
-
- print_line("indices total "+itos(indices.size())+" vertices used: "+itos(array.size()));
-
- Array arrays;
- arrays.resize(Mesh::ARRAY_MAX);
-
-
-
- for(int k=0;k<Mesh::ARRAY_MAX;k++) {
-
-
- if (!exists[k])
- continue;
- print_line("exists: "+itos(k));
- int lofs = ofs[k];
- switch(k) {
-
- case Mesh::ARRAY_VERTEX:
- case Mesh::ARRAY_NORMAL: {
-
- PoolVector<Vector3> vtx;
- vtx.resize(array.size());
- {
- int len=array.size();
- PoolVector<Vector3>::Write w = vtx.write();
- for(int l=0;l<len;l++) {
-
- int pos = array[l];
- w[l].x=vertices[pos*stride+lofs+0];
- w[l].y=vertices[pos*stride+lofs+1];
- w[l].z=vertices[pos*stride+lofs+2];
- }
- }
- arrays[k]=vtx;
-
- } break;
- case Mesh::ARRAY_TANGENT: {
-
- if (binormal_ofs<0)
- break;
-
- PoolVector<float> tangents;
- tangents.resize(array.size()*4);
- {
- int len=array.size();
-
- PoolVector<float>::Write w = tangents.write();
- for(int l=0;l<len;l++) {
-
- int pos = array[l];
- Vector3 n;
- n.x=vertices[pos*stride+ofs[Mesh::ARRAY_NORMAL]+0];
- n.y=vertices[pos*stride+ofs[Mesh::ARRAY_NORMAL]+1];
- n.z=vertices[pos*stride+ofs[Mesh::ARRAY_NORMAL]+2];
- Vector3 t;
- t.x=vertices[pos*stride+lofs+0];
- t.y=vertices[pos*stride+lofs+1];
- t.z=vertices[pos*stride+lofs+2];
- Vector3 bi;
- bi.x=vertices[pos*stride+binormal_ofs+0];
- bi.y=vertices[pos*stride+binormal_ofs+1];
- bi.z=vertices[pos*stride+binormal_ofs+2];
- float d = bi.dot(n.cross(t));
-
- w[l*4+0]=t.x;
- w[l*4+1]=t.y;
- w[l*4+2]=t.z;
- w[l*4+3]=d;
-
- }
- }
- arrays[k]=tangents;
-
- } break;
- case Mesh::ARRAY_COLOR: {
-
- PoolVector<Color> cols;
- cols.resize(array.size());
- {
- int len=array.size();
- PoolVector<Color>::Write w = cols.write();
- for(int l=0;l<len;l++) {
-
- int pos = array[l];
- w[l].r=vertices[pos*stride+lofs+0];
- w[l].g=vertices[pos*stride+lofs+1];
- w[l].b=vertices[pos*stride+lofs+2];
- w[l].a=vertices[pos*stride+lofs+3];
- }
- }
- arrays[k]=cols;
-
- } break;
- case Mesh::ARRAY_TEX_UV:
- case Mesh::ARRAY_TEX_UV2: {
-
- PoolVector<Vector2> uvs;
- uvs.resize(array.size());
- {
- int len=array.size();
- PoolVector<Vector2>::Write w = uvs.write();
- for(int l=0;l<len;l++) {
-
- int pos = array[l];
- w[l].x=vertices[pos*stride+lofs+0];
- w[l].y=vertices[pos*stride+lofs+1];
- w[l].y=1.0-w[l].y;
- }
- }
- arrays[k]=uvs;
-
- } break;
- case Mesh::ARRAY_BONES:
- case Mesh::ARRAY_WEIGHTS: {
-
- PoolVector<float> arr;
- arr.resize(array.size()*4);
- int po=k==Mesh::ARRAY_WEIGHTS?1:0;
- lofs=ofs[Mesh::ARRAY_BONES];
- {
- int len=array.size();
-
- PoolVector<float>::Write w = arr.write();
- for(int l=0;l<len;l++) {
-
- int pos = array[l];
-
- for(int m=0;m<4;m++) {
-
- float val=0;
- if (m<=weight_max)
- val=vertices[pos*stride+lofs+m*2+po];
- w[l*4+m]=val;
- }
- }
- }
-
- arrays[k]=arr;
- } break;
- case Mesh::ARRAY_INDEX: {
-
- PoolVector<int> arr;
- arr.resize(indices.size());
- {
- int len=indices.size();
-
- PoolVector<int>::Write w = arr.write();
- for(int l=0;l<len;l++) {
-
- w[l]=iarray[ indices[l] ];
- }
- }
-
- arrays[k]=arr;
-
- } break;
-
-
- }
-
-
- }
-
- Mesh::PrimitiveType pt=Mesh::PRIMITIVE_TRIANGLES;
-
- if (part.has("type")) {
- String type=part["type"];
- if (type=="LINES")
- pt=Mesh::PRIMITIVE_LINES;
- else if (type=="POINTS")
- pt=Mesh::PRIMITIVE_POINTS;
- else if (type=="TRIANGLE_STRIP")
- pt=Mesh::PRIMITIVE_TRIANGLE_STRIP;
- else if (type=="LINE_STRIP")
- pt=Mesh::PRIMITIVE_LINE_STRIP;
- }
-
- if (pt==Mesh::PRIMITIVE_TRIANGLES) {
- PoolVector<int> ia=arrays[Mesh::ARRAY_INDEX];
- int len=ia.size();
- {
- PoolVector<int>::Write w=ia.write();
- for(int l=0;l<len;l+=3) {
- SWAP(w[l+1],w[l+2]);
- }
- }
- arrays[Mesh::ARRAY_INDEX]=ia;
-
-
- }
- SurfaceInfo si;
- si.array=arrays;
- si.primitive=pt;
- state.surface_cache[_id(part["id"])]=si;
-
- }
- }
-}
-
-
-Error EditorSceneImporterFBXConv::_parse_animations(State& state) {
-
- AnimationPlayer *ap = memnew( AnimationPlayer );
-
- state.scene->add_child(ap);
- ap->set_owner(state.scene);
-
- for(int i=0;i<state.animations.size();i++) {
-
- Dictionary anim = state.animations[i];
- ERR_CONTINUE(!anim.has("id"));
- Ref<Animation> an = memnew( Animation );
- an->set_name(_id(anim["id"]));
-
-
- if (anim.has("bones")) {
-
- Array bone_tracks = anim["bones"];
- for(int j=0;j<bone_tracks.size();j++) {
- Dictionary bone_track=bone_tracks[j];
- String bone = bone_track["boneId"];
- if (!bone_track.has("keyframes"))
- continue;
- if (!state.bones.has(bone))
- continue;
-
- Skeleton *sk = state.bones[bone].skeleton;
-
- if (!sk)
- continue;
- int bone_idx=sk->find_bone(bone);
- if (bone_idx==-1)
- continue;
-
-
-
- String path = state.scene->get_path_to(sk);
- path+=":"+bone;
- an->add_track(Animation::TYPE_TRANSFORM);
- int tidx = an->get_track_count()-1;
- an->track_set_path(tidx,path);
-
-
- Dictionary parent_xform_dict;
- Dictionary xform_dict;
-
- if (state.bones.has(bone)) {
- xform_dict=state.bones[bone].node;
- }
-
-
- Array parent_keyframes;
- if (sk->get_bone_parent(bone_idx)!=-1) {
- String parent_name = sk->get_bone_name(sk->get_bone_parent(bone_idx));
- if (state.bones.has(parent_name)) {
- parent_xform_dict=state.bones[parent_name].node;
- }
-
- print_line("parent for "+bone+"? "+parent_name+" XFD: "+String(Variant(parent_xform_dict)));
- for(int k=0;k<bone_tracks.size();k++) {
- Dictionary d = bone_tracks[k];
- if (d["boneId"]==parent_name) {
- parent_keyframes=d["keyframes"];
- print_line("found keyframes");
- break;
- }
- }
-
-
- }
-
- print_line("BONE XFD "+String(Variant(xform_dict)));
-
- Array keyframes=bone_track["keyframes"];
-
- for(int k=0;k<keyframes.size();k++) {
-
- Dictionary key=keyframes[k];
- Transform xform=_get_transform_mixed(key,xform_dict);
- float time = key["keytime"];
- time=time/1000.0;
-#if 0
- if (parent_keyframes.size()) {
- //localize
- print_line(itos(k)+" localizate for: "+bone);
-
- float prev_kt=-1;
- float kt;
- int idx=0;
-
- for(int l=0;l<parent_keyframes.size();l++) {
-
- Dictionary d=parent_keyframes[l];
- kt=d["keytime"];
- kt=kt/1000.0;
- if (kt>time)
- break;
- prev_kt=kt;
- idx++;
-
- }
-
- Transform t;
- if (idx==0) {
- t=_get_transform_mixed(parent_keyframes[0],parent_xform_dict);
- } else if (idx==parent_keyframes.size()){
- t=_get_transform_mixed(parent_keyframes[idx-1],parent_xform_dict);
- } else {
- t=_get_transform_mixed(parent_keyframes[idx-1],parent_xform_dict);
- float d = (time-prev_kt)/(kt-prev_kt);
- if (d>0) {
- Transform t2=_get_transform_mixed(parent_keyframes[idx],parent_xform_dict);
- t=t.interpolate_with(t2,d);
- } else {
- print_line("exact: "+rtos(kt));
- }
- }
-
- xform = t.affine_inverse() * xform; //localize
- } else if (!parent_xform_dict.empty()) {
- Transform t = _get_transform(parent_xform_dict);
- xform = t.affine_inverse() * xform; //localize
- }
-#endif
-
- xform = sk->get_bone_rest(bone_idx).affine_inverse() * xform;
-
-
- Quat q = xform.basis;
- q.normalize();
- Vector3 s = xform.basis.get_scale();
- Vector3 l = xform.origin;
-
-
-
- an->transform_track_insert_key(tidx,time,l,q,s);
-
- }
-
- }
-
-
- }
-
-
- ap->add_animation(_id(anim["id"]),an);
-
- }
-
- return OK;
-}
-
-Error EditorSceneImporterFBXConv::_parse_json(State& state, const String &p_path) {
-
- //not the happiest....
- Vector<uint8_t> data = FileAccess::get_file_as_array(p_path);
- ERR_FAIL_COND_V(!data.size(),ERR_FILE_CANT_OPEN);
- String str;
- bool utferr = str.parse_utf8((const char*)data.ptr(),data.size());
- ERR_FAIL_COND_V(utferr,ERR_PARSE_ERROR);
-
- Dictionary dict;
- Error err = dict.parse_json(str);
- str=String(); //free mem immediately
- ERR_FAIL_COND_V(err,err);
-
- if (dict.has("meshes"))
- state.meshes=dict["meshes"];
- if (dict.has("materials"))
- state.materials=dict["materials"];
- if (dict.has("nodes"))
- state.nodes=dict["nodes"];
- if (dict.has("animations"))
- state.animations=dict["animations"];
-
-
- state.scene = memnew( Spatial );
- _detect_bones(state);
- _parse_surfaces(state);
- _parse_materials(state);
- err = _parse_nodes(state,state.nodes,state.scene);
- if (err)
- return err;
-
- if (state.import_animations) {
- err = _parse_animations(state);
- if (err)
- return err;
- }
-
- print_line("JSON PARSED O-K!");
-
- return OK;
-}
-
-Error EditorSceneImporterFBXConv::_parse_fbx(State& state,const String& p_path) {
-
- state.base_path=p_path.get_base_dir();
-
- if (p_path.to_lower().ends_with("g3dj")) {
- return _parse_json(state,p_path.basename()+".g3dj");
- }
-
- String tool = EDITOR_DEF("fbxconv/path","");
- ERR_FAIL_COND_V( !FileAccess::exists(tool),ERR_UNCONFIGURED);
- String wine = EDITOR_DEF("fbxconv/use_wine","");
-
- List<String> args;
- String path=p_path;
- if (wine!="") {
- List<String> wpargs;
- wpargs.push_back("-w");
- wpargs.push_back(p_path);
- String pipe; //winepath to convert to windows path
- int wpres;
- Error wperr = OS::get_singleton()->execute(wine+"path",wpargs,true,NULL,&pipe,&wpres);
- ERR_FAIL_COND_V(wperr!=OK,ERR_CANT_CREATE);
- ERR_FAIL_COND_V(wpres!=0,ERR_CANT_CREATE);
- path=pipe.strip_edges();
- args.push_back(tool);
- tool=wine;
- }
-
- args.push_back("-o");
- args.push_back("G3DJ");
- args.push_back(path);
-
- int res;
- Error err = OS::get_singleton()->execute(tool,args,true,NULL,NULL,&res);
- ERR_FAIL_COND_V(err!=OK,ERR_CANT_CREATE);
- ERR_FAIL_COND_V(res!=0,ERR_CANT_CREATE);
-
- return _parse_json(state,p_path.basename()+".g3dj");
-
-
-}
-
-Node* EditorSceneImporterFBXConv::import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps,Error* r_err){
-
- State state;
- state.scene=NULL;
- state.missing_deps=r_missing_deps;
- state.import_animations=p_flags&IMPORT_ANIMATION;
- Error err = _parse_fbx(state,p_path);
- if (err!=OK) {
- if (r_err)
- *r_err=err;
- return NULL;
- }
-
-
- return state.scene;
-}
-Ref<Animation> EditorSceneImporterFBXConv::import_animation(const String& p_path,uint32_t p_flags){
-
-
- return Ref<Animation>();
-}
-
-
-EditorSceneImporterFBXConv::EditorSceneImporterFBXConv() {
-
- EDITOR_DEF("fbxconv/path","");
-#ifndef WINDOWS_ENABLED
- EDITOR_DEF("fbxconv/use_wine","");
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"fbxconv/use_wine",PROPERTY_HINT_GLOBAL_FILE));
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"fbxconv/path",PROPERTY_HINT_GLOBAL_FILE));
-#else
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"fbxconv/path",PROPERTY_HINT_GLOBAL_FILE,"exe"));
-#endif
-
-}
-#endif
diff --git a/tools/editor/io_plugins/editor_scene_importer_fbxconv.h b/tools/editor/io_plugins/editor_scene_importer_fbxconv.h
deleted file mode 100644
index 1bf96ba0e5..0000000000
--- a/tools/editor/io_plugins/editor_scene_importer_fbxconv.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*************************************************************************/
-/* editor_scene_importer_fbxconv.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_SCENE_IMPORTER_FBXCONV_H
-#define EDITOR_SCENE_IMPORTER_FBXCONV_H
-
-#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
-#include "scene/3d/skeleton.h"
-
-#if 0
-
-class EditorSceneImporterFBXConv : public EditorSceneImporter {
-
- GDCLASS(EditorSceneImporterFBXConv,EditorSceneImporter );
-
-
- struct BoneInfo {
-
- Skeleton *skeleton;
- Transform rest;
- int index;
- bool has_anim_chan;
- bool has_rest;
- Dictionary node;
- BoneInfo() {
- has_rest=false;
- skeleton=NULL;
- index=-1;
- has_anim_chan=false;
- }
- };
-
- struct SurfaceInfo {
- Array array;
- Mesh::PrimitiveType primitive;
- };
-
- struct State {
-
- Node *scene;
- Array meshes;
- Array materials;
- Array nodes;
- Array animations;
- Map<String,BoneInfo > bones;
- Map<String,Skeleton*> skeletons;
- Map<String,Ref<Mesh> > mesh_cache;
- Map<String,SurfaceInfo> surface_cache;
- Map<String,Ref<Material> > material_cache;
- Map<String,Ref<Texture> > texture_cache;
- List<String> *missing_deps;
- String base_path;
- bool import_animations;
- };
-
- String _id(const String& p_id) const;
-
- Transform _get_transform_mixed(const Dictionary& d, const Dictionary& dbase);
- Transform _get_transform(const Dictionary& d);
- Color _get_color(const Array& a);
- void _detect_bones_in_nodes(State& state,const Array& p_nodes);
- void _detect_bones(State& state);
-
- Error _parse_bones(State& state,const Array &p_bones,Skeleton* p_skeleton);
- void _parse_skeletons(const String& p_name,State& state, const Array &p_nodes, Skeleton*p_skeleton=NULL, int p_parent=-1);
-
- void _add_surface(State& state,Ref<Mesh>& m,const Dictionary &part);
- Error _parse_nodes(State& state,const Array &p_nodes,Node* p_base);
- Error _parse_animations(State& state);
- void _parse_materials(State& state);
- void _parse_surfaces(State& state);
- Error _parse_json(State& state,const String& p_path);
- Error _parse_fbx(State &state, const String &p_path);
-
-public:
-
- virtual uint32_t get_import_flags() const;
- virtual void get_extensions(List<String> *r_extensions) const;
- virtual Node* import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps=NULL,Error* r_err=NULL);
- virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
-
- EditorSceneImporterFBXConv();
-};
-
-#endif // EDITOR_SCENE_IMPORTER_FBXCONV_H
-#endif
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
deleted file mode 100644
index c41199f291..0000000000
--- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp
+++ /dev/null
@@ -1,1893 +0,0 @@
-/*************************************************************************/
-/* editor_texture_import_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_texture_import_plugin.h"
-#if 0
-#include "io/image_loader.h"
-#include "tools/editor/editor_node.h"
-#include "io/resource_saver.h"
-#include "editor_atlas.h"
-#include "tools/editor/editor_settings.h"
-#include "io/md5.h"
-#include "io/marshalls.h"
-#include "globals.h"
-#include "scene/gui/check_button.h"
-#include "scene/gui/button_group.h"
-#include "scene/gui/margin_container.h"
-#include "scene/io/resource_format_image.h"
-
-static const char *flag_names[]={
- ("Streaming Format"),
- ("Fix Border Alpha"),
- ("Alpha Bit Hint"),
- ("Compress Extra (PVRTC2)"),
- ("No MipMaps"),
- ("Repeat"),
- ("Filter (Magnifying)"),
- ("Premultiply Alpha"),
- ("Convert SRGB->Linear"),
- ("Convert NormalMap to XY"),
- ("Use Anisotropy"),
- NULL
-};
-
-#if 0 // not used
-static const char *flag_short_names[]={
- "Stream",
- "FixBorder",
- "AlphBit",
- "ExtComp",
- "NoMipMap",
- "Repeat",
- "Filter",
- "PMAlpha",
- "ToLinear",
- "ToRG",
- "Anisoropic",
- NULL
-};
-#endif
-
-
-void EditorImportTextureOptions::set_format(EditorTextureImportPlugin::ImageFormat p_format) {
-
- updating=true;
- format->select(p_format);
- if (p_format==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
- quality_vb->show();
- } else {
- quality_vb->hide();
- }
-
- updating=false;
-
-}
-
-EditorTextureImportPlugin::ImageFormat EditorImportTextureOptions::get_format() const{
-
- return (EditorTextureImportPlugin::ImageFormat)format->get_selected();
-
-}
-
-void EditorImportTextureOptions::set_flags(uint32_t p_flags){
-
- updating=true;
- for(int i=0;i<items.size();i++) {
-
- items[i]->set_checked(0,p_flags&(1<<i));
- }
- updating=false;
-
-}
-
-void EditorImportTextureOptions::set_quality(float p_quality) {
-
- quality->set_value(p_quality);
-}
-
-float EditorImportTextureOptions::get_quality() const {
-
- return quality->get_value();
-}
-
-
-uint32_t EditorImportTextureOptions::get_flags() const{
-
- uint32_t f=0;
- for(int i=0;i<items.size();i++) {
-
- if (items[i]->is_checked(0))
- f|=(1<<i);
- }
-
- return f;
-}
-
-void EditorImportTextureOptions::_changedp(int p_value) {
-
- _changed();
-}
-
-void EditorImportTextureOptions::_changed() {
-
- if (updating)
- return;
- if (format->get_selected()==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
- quality_vb->show();
- } else {
- quality_vb->hide();
- }
-
- emit_signal("changed");
-}
-
-
-void EditorImportTextureOptions::_bind_methods() {
-
- ClassDB::bind_method("_changed",&EditorImportTextureOptions::_changed);
- ClassDB::bind_method("_changedp",&EditorImportTextureOptions::_changedp);
-
- ADD_SIGNAL(MethodInfo("changed"));
-}
-
-
-void EditorImportTextureOptions::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- flags->connect("item_edited",this,"_changed");
- format->connect("item_selected",this,"_changedp");
- }
-}
-
-void EditorImportTextureOptions::show_2d_notice() {
-
- //notice_for_2d->show();
-}
-
-EditorImportTextureOptions::EditorImportTextureOptions() {
-
-
- add_constant_override("separation",3);
- updating=false;
- format = memnew( OptionButton );
-
- format->add_item(TTR("Uncompressed"),EditorTextureImportPlugin::IMAGE_FORMAT_UNCOMPRESSED);
- format->add_item(TTR("Compress Lossless (PNG)"),EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS);
- format->add_item(TTR("Compress Lossy (WebP)"),EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
- format->add_item(TTR("Compress (VRAM)"),EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
-
-
- add_margin_child(TTR("Texture Format"),format);
-
- quality_vb = memnew( VBoxContainer );
-
- HBoxContainer *quality_hb = memnew(HBoxContainer);
- HSlider *hs = memnew( HSlider );
- hs->set_h_size_flags(SIZE_EXPAND_FILL);
- hs->set_stretch_ratio(0.8);
- quality_hb->add_child(hs);
- quality_hb->set_h_size_flags(SIZE_EXPAND_FILL);
- SpinBox *sb = memnew( SpinBox );
- sb->set_h_size_flags(SIZE_EXPAND_FILL);
- sb->set_stretch_ratio(0.2);
- quality_hb->add_child(sb);
- sb->share(hs);
- hs->set_min(0);
- hs->set_max(1.0);
- hs->set_step(0.01);
- hs->set_value(0.7);
- quality=hs;
- quality_vb->add_margin_child(TTR("Texture Compression Quality (WebP):"),quality_hb);
-
- add_child(quality_vb);
-
- flags = memnew( Tree );
- flags->set_hide_root(true);
- TreeItem *root = flags->create_item();
-
-
-
- const char ** fname=flag_names;
-
- while( *fname ) {
-
- TreeItem*ti = flags->create_item(root);
- ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- ti->set_text(0,*fname);
- ti->set_editable(0,true);
- items.push_back(ti);
- fname++;
- }
-
- add_margin_child(TTR("Texture Options"),flags,true);
-
-
-}
-
-///////////////////////////////////////////////////////////
-
-
-
-
-class EditorTextureImportDialog : public ConfirmationDialog {
-
- GDCLASS(EditorTextureImportDialog,ConfirmationDialog);
-
-
-
- HBoxContainer *mode_hb;
- CheckBox *mode_check[EditorTextureImportPlugin::MODE_MAX];
-
- EditorImportTextureOptions *texture_options;
-
- EditorTextureImportPlugin::Mode mode;
- //EditorNode *editor;
-
- LineEdit *import_path;
- LineEdit *save_path;
- EditorFileDialog *file_select;
- EditorFileDialog *save_file_select;
- EditorDirDialog *save_select;
- OptionButton *texture_action;
- ConfirmationDialog *error_dialog;
- CheckButton *crop_source;
- SpinBox *size;
-
- MarginContainer *size_mc;
- Label* size_label;
-
- Label* source_label;
- Label *notice_for_2d;
-
- EditorTextureImportPlugin *plugin;
-
- void _mode_changed(int p_mode);
- void _choose_files(const Vector<String>& p_path);
- void _choose_file(const String& p_path);
- void _choose_save_dir(const String& p_path);
- void _browse();
- void _browse_target();
- void _import();
-
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
-
- void setup_multiple_import_3d(const Vector<String>& p_path,const String& p_dest) {
-
- _mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_3D);
- _choose_files(p_path);
- _choose_save_dir(p_dest);
- }
-
- void add_sources_and_dest(const Vector<String>& p_path,const String& p_dest) {
-
- _choose_files(p_path);
- _choose_save_dir(p_dest);
- }
-
- Error import(const String& p_from, const String& p_to, const String& p_preset);
- void popup_import(const String &p_from=String());
- EditorTextureImportDialog(EditorTextureImportPlugin *p_plugin=NULL);
-};
-
-
-/////////////////////////////////////////////////////////
-
-
-
-
-void EditorTextureImportDialog::_choose_files(const Vector<String>& p_path) {
-
- String files;
- for(int i=0;i<p_path.size();i++) {
-
- if (i>0)
- files+=",";
- files+=p_path[i];
- }
- /*
- if (p_path.size()) {
- String srctex=p_path[0];
- String ipath = EditorImportDB::get_singleton()->find_source_path(srctex);
-
- if (ipath!="")
- save_path->set_text(ipath.get_base_dir());
- }*/
- import_path->set_text(files);
-
-}
-
-
-
-void EditorTextureImportDialog::_choose_file(const String& p_path) {
-
-
- import_path->set_text(p_path);
-
-}
-void EditorTextureImportDialog::_choose_save_dir(const String& p_path) {
-
- save_path->set_text(p_path);
-}
-
-
-void EditorTextureImportDialog::_import() {
-
-
- //ImportMonitorBlock imb;
-
- Vector<String> files=import_path->get_text().split(",");
-
- if (!files.size()) {
-
- error_dialog->set_text(TTR("Please specify some files!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
- }
-
- String dst_path=save_path->get_text();
-
- if (save_path->get_text().strip_edges()=="") {
- error_dialog->set_text(TTR("Target path is empty."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (!save_path->get_text().begins_with("res://")) {
- error_dialog->set_text(TTR("Target path must be a complete resource path."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
-
- if (mode!=EditorTextureImportPlugin::MODE_ATLAS && mode!=EditorTextureImportPlugin::MODE_LARGE && !DirAccess::exists(save_path->get_text())) {
- error_dialog->set_text(TTR("Target path must exist."));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (mode==EditorTextureImportPlugin::MODE_ATLAS) { //atlas
-
- if (files.size()==0) {
-
- error_dialog->set_text(TTR("At least one file needed for Atlas."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
-
- }
- String dst_file = dst_path;
- //dst_file=dst_file.basename()+".tex";
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
- //imd->set_editor();
- for(int i=0;i<files.size();i++) {
- imd->add_source(EditorImportPlugin::validate_source_path(files[i]));
- }
- imd->set_option("format",texture_options->get_format());
- imd->set_option("flags",texture_options->get_flags());
- imd->set_option("quality",texture_options->get_quality());
- imd->set_option("atlas",true);
- imd->set_option("atlas_size",int(size->get_value()));
- imd->set_option("large",false);
- imd->set_option("crop",crop_source->is_pressed());
- imd->set_option("mode",mode);
-
- Error err = plugin->import(dst_file,imd);
- if (err) {
-
- error_dialog->set_text(TTR("Error importing:")+" "+dst_file.get_file());
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
-
- }
- } else if (mode==EditorTextureImportPlugin::MODE_LARGE) { //large
-
- if (files.size()!=1) {
-
- error_dialog->set_text(TTR("Only one file is required for large texture."));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
-
- }
- String dst_file = dst_path;
- //dst_file=dst_file.basename()+".tex";
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
- //imd->set_editor();
- for(int i=0;i<files.size();i++) {
- imd->add_source(EditorImportPlugin::validate_source_path(files[i]));
- }
- imd->set_option("format",texture_options->get_format());
- imd->set_option("flags",texture_options->get_flags());
- imd->set_option("quality",texture_options->get_quality());
- imd->set_option("atlas",false);
- imd->set_option("large",true);
- imd->set_option("large_cell_size",int(size->get_value()));
- imd->set_option("crop",crop_source->is_pressed());
- imd->set_option("mode",mode);
-
- Error err = plugin->import(dst_file,imd);
- if (err) {
-
- error_dialog->set_text(TTR("Error importing:")+" "+dst_file.get_file());
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
-
- }
- } else {
-
-
- for(int i=0;i<files.size();i++) {
-
- String dst_file = dst_path.plus_file(files[i].get_file());
- dst_file=dst_file.get_basename()+".tex";
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
- //imd->set_editor();
- imd->add_source(EditorImportPlugin::validate_source_path(files[i]));
- imd->set_option("format",texture_options->get_format());
- imd->set_option("flags",texture_options->get_flags());
- imd->set_option("quality",texture_options->get_quality());
- imd->set_option("atlas",false);
- imd->set_option("large",false);
- imd->set_option("mode",mode);
-
- Error err = plugin->import(dst_file,imd);
- if (err) {
-
- error_dialog->set_text(TTR("Error importing:")+" "+dst_file.get_file());
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
-
- }
- }
- }
-
- hide();
-}
-
-void EditorTextureImportDialog::_browse() {
-
- file_select->popup_centered_ratio();
-}
-
-void EditorTextureImportDialog::_browse_target() {
-
- if (mode==EditorTextureImportPlugin::MODE_ATLAS || mode==EditorTextureImportPlugin::MODE_LARGE) {
- save_file_select->popup_centered_ratio();
- } else {
- save_select->popup_centered_ratio();
- }
-
-}
-
-
-void EditorTextureImportDialog::popup_import(const String& p_from) {
-
- popup_centered(Size2(600,500)*EDSCALE);
- if (p_from!="") {
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
- ERR_FAIL_COND(!rimd.is_valid());
-
- if (rimd->has_option("mode")) {
- //new imported stuff uses this option
- _mode_changed(rimd->get_option("mode"));
- } else {
- //this one is for compatibility, will have to guess it
- if (rimd->has_option("atlas") && rimd->get_option("atlas")) {
- _mode_changed(EditorTextureImportPlugin::MODE_ATLAS);
- } else if (rimd->has_option("large") && rimd->get_option("large")) {
- _mode_changed(EditorTextureImportPlugin::MODE_LARGE);
- } else {
- //guess by usage of mipmaps..?
- _mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_2D);
- }
-
- }
-
- if (mode==EditorTextureImportPlugin::MODE_ATLAS || mode==EditorTextureImportPlugin::MODE_LARGE)
- save_path->set_text(p_from);
- else
- save_path->set_text(p_from.get_base_dir());
-
- texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("format"))));
- texture_options->set_flags(rimd->get_option("flags"));
- texture_options->set_quality(rimd->get_option("quality"));
- String src = "";
- for(int i=0;i<rimd->get_source_count();i++) {
- if (i>0)
- src+=",";
- src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
- }
- import_path->set_text(src);
- }
-}
-
-
-void EditorTextureImportDialog::_notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
-
- List<String> extensions;
- ImageLoader::get_recognized_extensions(&extensions);
- //ResourceLoader::get_recognized_extensions_for_type("PackedTexture",&extensions);
- file_select->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- file_select->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
- }
-}
-
-Error EditorTextureImportDialog::import(const String& p_from, const String& p_to, const String& p_preset) {
-
-
- import_path->set_text(p_from);
- save_path->set_text(p_to);
- _import();
-
- return OK;
-}
-
-void EditorTextureImportDialog::_mode_changed(int p_mode) {
-
- mode = EditorTextureImportPlugin::Mode(p_mode);
-
- for(int i=0;i<EditorTextureImportPlugin::MODE_MAX;i++) {
- mode_check[i]->set_pressed(i==mode);
- }
-
- if (p_mode==EditorTextureImportPlugin::MODE_ATLAS) {
-
- size_label->set_text(TTR("Max Texture Size:"));
- size->set_value(2048);
- crop_source->show();
- size_label->show();
- size->show();
-
- texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
- texture_options->set_quality(0.7);
- texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
- set_title(TTR("Import Textures for Atlas (2D)"));
-
- } else {
- crop_source->hide();
- }
-
-
- if (p_mode==EditorTextureImportPlugin::MODE_LARGE) {
-
- size_label->set_text(TTR("Cell Size:"));
- size->set_value(256);
- size_label->show();
- size->show();
-
- file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- save_file_select->add_filter("*.ltex;"+TTR("Large Texture"));
-
- texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
- texture_options->set_quality(0.7);
- texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS);
- set_title(TTR("Import Large Textures (2D)"));
- source_label->set_text(TTR("Source Texture"));
-
- } else {
- file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
- save_file_select->add_filter("*.tex;"+TTR("Base Atlas Texture"));
- source_label->set_text(TTR("Source Texture(s)"));
- }
-
- if (p_mode==EditorTextureImportPlugin::MODE_TEXTURE_2D) {
-
- size_label->hide();
- size->hide();
-
- texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
- texture_options->set_quality(0.7);
- texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
- notice_for_2d->show();
- set_title(TTR("Import Textures for 2D"));
-
- } else {
- notice_for_2d->hide();
- }
-
- if (p_mode==EditorTextureImportPlugin::MODE_TEXTURE_3D) {
-
- size_label->hide();
- size->hide();
- //texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_);
- //texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS);
- texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER|EditorTextureImportPlugin::IMAGE_FLAG_REPEAT);
- texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM);
- set_title(TTR("Import Textures for 3D"));
- }
-}
-
-void EditorTextureImportDialog::_bind_methods() {
-
-
- ClassDB::bind_method("_choose_files",&EditorTextureImportDialog::_choose_files);
- ClassDB::bind_method("_choose_file",&EditorTextureImportDialog::_choose_file);
- ClassDB::bind_method("_choose_save_dir",&EditorTextureImportDialog::_choose_save_dir);
- ClassDB::bind_method("_import",&EditorTextureImportDialog::_import);
- ClassDB::bind_method("_browse",&EditorTextureImportDialog::_browse);
- ClassDB::bind_method("_browse_target",&EditorTextureImportDialog::_browse_target);
- ClassDB::bind_method("_mode_changed",&EditorTextureImportDialog::_mode_changed);
- //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
-}
-
-EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin* p_plugin) {
-
-
-
-
-
- plugin=p_plugin;
- set_title(TTR("Import Textures"));
-
- mode_hb = memnew( HBoxContainer );
- add_child(mode_hb);
- //set_child_rect(mode_hb);
-
- VBoxContainer *vbcg = memnew( VBoxContainer);
-
-
- mode_hb->add_child(vbcg);
- mode_hb->add_constant_override("separation",15);
- VBoxContainer *bg = memnew( VBoxContainer );
- vbcg->add_margin_child("Import Mode",bg);
-
- for(int i=0;i<EditorTextureImportPlugin::MODE_MAX;i++) {
- String mode_name[EditorTextureImportPlugin::MODE_MAX]={
- TTR("2D Texture"),
- TTR("3D Texture"),
- TTR("Atlas Texture"),
- TTR("Large Texture")
- };
-
-
- mode_check[i]=memnew(CheckBox);
- bg->add_child(mode_check[i]);
- mode_check[i]->set_text(mode_name[i]);
- mode_check[i]->connect("pressed",this,"_mode_changed",varray(i));
- }
-
- VBoxContainer *vbc = memnew(VBoxContainer);
- mode_hb->add_child(vbc);
- vbc->set_h_size_flags(SIZE_EXPAND_FILL);
- vbc->add_constant_override("separation",4);
-
- notice_for_2d = memnew( Label );
- notice_for_2d->set_text(TTR("NOTICE: Importing 2D textures is not mandatory. Just copy png/jpg files to the project."));
- //notice_for_2d->set_custom_minimum_size(Size2(0,50));
- notice_for_2d->set_autowrap(true);
- notice_for_2d->hide();
- vbcg->add_child(notice_for_2d);
- notice_for_2d->set_v_size_flags(SIZE_EXPAND_FILL);
- notice_for_2d->set_valign(Label::VALIGN_BOTTOM);
-
- VBoxContainer *source_vb=memnew(VBoxContainer);
- MarginContainer *source_mc = vbc->add_margin_child(TTR("Source Texture(s):"),source_vb);
-
- source_label = vbc->get_child(source_mc->get_index()-1)->cast_to<Label>();
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- source_vb->add_child(hbc);
-
- import_path = memnew( LineEdit );
- import_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(import_path);
- crop_source = memnew( CheckButton );
- crop_source->set_pressed(true);
- source_vb->add_child(crop_source);
- crop_source->set_text(TTR("Crop empty space."));
-
-
- Button * import_choose = memnew( Button );
- import_choose->set_text(" .. ");
- hbc->add_child(import_choose);
-
- import_choose->connect("pressed", this,"_browse");
-
- hbc = memnew( HBoxContainer );
- vbc->add_margin_child(TTR("Target Path:"),hbc);
-
- size = memnew( SpinBox );
- size->set_min(128);
- size->set_max(16384);
-
-
- size->set_value(256);
- size_mc=vbc->add_margin_child(TTR("Cell Size:"),size);
- size_label=vbc->get_child(size_mc->get_index()-1)->cast_to<Label>();
-
-
- save_path = memnew( LineEdit );
- save_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(save_path);
-
- Button * save_choose = memnew( Button );
- save_choose->set_text(" .. ");
- hbc->add_child(save_choose);
-
- save_choose->connect("pressed", this,"_browse_target");
-
- file_select = memnew(EditorFileDialog);
- file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- add_child(file_select);
-
- file_select->connect("files_selected", this,"_choose_files");
- file_select->connect("file_selected", this,"_choose_file");
-
- save_file_select = memnew(EditorFileDialog);
- save_file_select->set_access(EditorFileDialog::ACCESS_RESOURCES);
- add_child(save_file_select);
- save_file_select->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- save_file_select->clear_filters();
-
- save_file_select->connect("file_selected", this,"_choose_save_dir");
-
- save_select = memnew( EditorDirDialog );
- add_child(save_select);
-
- //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
- save_select->connect("dir_selected", this,"_choose_save_dir");
-
- get_ok()->connect("pressed", this,"_import");
- get_ok()->set_text(TTR("Import"));
-
- //move stuff up
- /*
- for(int i=0;i<4;i++)
- vbc->move_child( vbc->get_child( vbc->get_child_count() -1), 0);
- */
-
- error_dialog = memnew ( ConfirmationDialog );
- add_child(error_dialog);
- error_dialog->get_ok()->set_text(TTR("Accept"));
- //error_dialog->get_cancel()->hide();
-
- set_hide_on_ok(false);
-
- texture_options = memnew( EditorImportTextureOptions );
- vbc->add_child(texture_options);
- texture_options->set_v_size_flags(SIZE_EXPAND_FILL);
-
- _mode_changed(EditorTextureImportPlugin::MODE_TEXTURE_3D);
-
-
- //GLOBAL_DEF("import/shared_textures","res://");
- //Globals::get_singleton()->set_custom_property_info("import/shared_textures",PropertyInfo(Variant::STRING,"import/shared_textures",PROPERTY_HINT_DIR));
-
-
-}
-
-
-
-///////////////////////////////////////////////////////////
-
-
-String EditorTextureImportPlugin::get_name() const {
-
- return "texture";
-#if 0 //old names, kept for compatibility reference
- switch(mode) {
- case MODE_TEXTURE_2D: {
-
- return "texture_2d";
- } break;
- case MODE_TEXTURE_3D: {
-
- return "texture_3d";
-
- } break;
- case MODE_ATLAS: {
-
- return "texture_atlas";
- } break;
- case MODE_LARGE: {
-
- return "texture_large";
- } break;
-
- }
-
-
- return "";
-#endif
-}
-
-String EditorTextureImportPlugin::get_visible_name() const {
-
- return TTR("Texture");
-
-}
-void EditorTextureImportPlugin::import_dialog(const String& p_from) {
-
- dialog->popup_import(p_from);
-}
-
-void EditorTextureImportPlugin::compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller) {
-
-
- switch(p_mode) {
- case EditorExportPlatform::IMAGE_COMPRESSION_NONE: {
-
- //do absolutely nothing
-
- } break;
- case EditorExportPlatform::IMAGE_COMPRESSION_BC: {
-
-
- // for maximum compatibility, BC shall always use mipmaps and be PO2
- image.resize_to_po2();
- if (!image.has_mipmaps())
- image.generate_mipmaps();
-
- image.compress(Image::COMPRESS_S3TC);
- /*
- if (has_alpha) {
-
- if (flags&IMAGE_FLAG_ALPHA_BIT) {
- image.convert(Image::FORMAT_DXT5);
- } else {
- image.convert(Image::FORMAT_DXT3);
- }
- } else {
-
- image.convert(Image::FORMAT_DXT1);
- }*/
-
-
- } break;
- case EditorExportPlatform::IMAGE_COMPRESSION_PVRTC:
- case EditorExportPlatform::IMAGE_COMPRESSION_PVRTC_SQUARE: {
-
- // for maximum compatibility (hi apple!), PVRT shall always
- // use mipmaps, be PO2 and square
-
- if (!image.has_mipmaps())
- image.generate_mipmaps();
- image.resize_to_po2(true);
-
- if (p_smaller) {
-
- image.compress(Image::COMPRESS_PVRTC2);
- //image.convert(has_alpha ? Image::FORMAT_PVRTC2A : Image::FORMAT_PVRTC2);
- } else {
- image.compress(Image::COMPRESS_PVRTC4);
- //image.convert(has_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4);
- }
-
- } break;
- case EditorExportPlatform::IMAGE_COMPRESSION_ETC1: {
-
- image.resize_to_po2(); //square or not?
- if (!image.has_mipmaps())
- image.generate_mipmaps();
- if (!image.detect_alpha()) {
- //ETC1 is only opaque
- image.compress(Image::COMPRESS_ETC);
- }
-
- } break;
- case EditorExportPlatform::IMAGE_COMPRESSION_ETC2: {
-
-
- } break;
- }
-
-
-}
-
-Error EditorTextureImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
-
-
- return import2(p_path,p_from,EditorExportPlatform::IMAGE_COMPRESSION_BC,false);
-}
-
-
-Error EditorTextureImportPlugin::_process_texture_data(Ref<ImageTexture> &texture,int format, float quality,int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink) {
-
-
- if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
-
- Image image=texture->get_data();
- ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
-
- bool has_alpha=image.detect_alpha();
- if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
-
- image.convert(Image::FORMAT_RGB8);
-
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
-
- image.fix_alpha_edges();
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
-
- image.premultiply_alpha();
- }
-
- if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
- image.normalmap_to_xy();
- }
-
- /*
- if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
-
- image.srgb_to_linear();
- }
- */
-
- if (shrink>1) {
-
- int orig_w=image.get_width();
- int orig_h=image.get_height();
- image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC);
- texture->create_from_image(image,tex_flags);
- texture->set_size_override(Size2(orig_w,orig_h));
-
-
- } else {
-
- texture->create_from_image(image,tex_flags);
- }
-
-
- if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS) {
- texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSLESS);
- } else {
- texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
- }
-
-
-
- texture->set_lossy_storage_quality(quality);
-
-
- } else {
-
-
- Image image=texture->get_data();
- ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
-
-
- bool has_alpha=image.detect_alpha();
- if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
-
- image.convert(Image::FORMAT_RGB8);
-
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
-
- image.fix_alpha_edges();
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
-
- image.premultiply_alpha();
- }
-
- if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
- image.normalmap_to_xy();
- }
-
- /*
- if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
-
- print_line("CONVERT BECAUSE: "+itos(flags));
- image.srgb_to_linear();
- }
- */
-
- int orig_w=image.get_width();
- int orig_h=image.get_height();
-
- if (shrink>1) {
- image.resize(orig_w/shrink,orig_h/shrink,Image::INTERPOLATE_CUBIC);
- texture->create_from_image(image,tex_flags);
- texture->set_size_override(Size2(orig_w,orig_h));
- }
-
- if (!(flags&IMAGE_FLAG_NO_MIPMAPS)) {
- image.generate_mipmaps();
-
- }
-
- if (format!=IMAGE_FORMAT_UNCOMPRESSED) {
-
- compress_image(p_compr,image,flags&IMAGE_FLAG_COMPRESS_EXTRA);
- }
-
-
- texture->create_from_image(image,tex_flags);
-
-
- if (shrink>1 || (format!=IMAGE_FORMAT_UNCOMPRESSED && (image.get_width()!=orig_w || image.get_height()!=orig_h))) {
- texture->set_size_override(Size2(orig_w,orig_h));
- }
-
- //uint32_t save_flags=ResourceSaver::FLAG_COMPRESS;
- }
-
- return OK;
-}
-
-
-Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<ResourceImportMetadata>& p_from,EditorExportPlatform::ImageCompression p_compr, bool p_external){
-
-
-
- ERR_FAIL_COND_V(p_from->get_source_count()==0,ERR_INVALID_PARAMETER);
-
- Ref<ResourceImportMetadata> from=p_from;
-
- Ref<ImageTexture> texture;
- Vector<Ref<AtlasTexture> > atlases;
- bool atlas = from->get_option("atlas");
- bool large = from->get_option("large");
-
- int flags=from->get_option("flags");
- int format=from->get_option("format");
- float quality=from->get_option("quality");
-
- uint32_t tex_flags=0;
-
- if (flags&EditorTextureImportPlugin::IMAGE_FLAG_REPEAT)
- tex_flags|=Texture::FLAG_REPEAT;
- if (flags&EditorTextureImportPlugin::IMAGE_FLAG_FILTER)
- tex_flags|=Texture::FLAG_FILTER;
- if (!(flags&EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS))
- tex_flags|=Texture::FLAG_MIPMAPS;
- if (flags&EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR)
- tex_flags|=Texture::FLAG_CONVERT_TO_LINEAR;
- if (flags&EditorTextureImportPlugin::IMAGE_FLAG_USE_ANISOTROPY)
- tex_flags|=Texture::FLAG_ANISOTROPIC_FILTER;
-
- print_line("path: "+p_path+" flags: "+itos(tex_flags));
- float shrink=1;
- if (from->has_option("shrink"))
- shrink=from->get_option("shrink");
-
- if (large) {
- ERR_FAIL_COND_V(from->get_source_count()!=1,ERR_INVALID_PARAMETER);
-
- String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
-
-
- int cell_size=from->get_option("large_cell_size");
- ERR_FAIL_COND_V(cell_size<128 || cell_size>16384,ERR_CANT_OPEN);
-
- EditorProgress pg("ltex",TTR("Import Large Texture"),3);
-
- pg.step(TTR("Load Source Image"),0);
- Image img;
- Error err = ImageLoader::load_image(src_path,&img);
- if (err) {
- return err;
- }
-
- pg.step(TTR("Slicing"),1);
-
- Map<Vector2,Image> pieces;
- for(int i=0;i<img.get_width();i+=cell_size) {
- int w = MIN(img.get_width()-i,cell_size);
- for(int j=0;j<img.get_height();j+=cell_size) {
- int h = MIN(img.get_height()-j,cell_size);
-
- Image piece(w,h,0,img.get_format());
- piece.blit_rect(img,Rect2(i,j,w,h),Point2(0,0));
- if (!piece.is_invisible()) {
- pieces[Vector2(i,j)]=piece;
- //print_line("ADDING PIECE AT "+Vector2(i,j));
- }
- }
- }
-
- Ref<LargeTexture> existing;
- if (ResourceCache::has(p_path)) {
- existing = ResourceCache::get(p_path);
- }
-
- if (existing.is_valid()) {
- existing->clear();
- } else {
- existing = Ref<LargeTexture>(memnew( LargeTexture ));
- }
-
- existing->set_size(Size2(img.get_width(),img.get_height()));
- pg.step(TTR("Inserting"),2);
-
- for (Map<Vector2,Image>::Element *E=pieces.front();E;E=E->next()) {
-
- Ref<ImageTexture> imgtex = Ref<ImageTexture>( memnew( ImageTexture ) );
- imgtex->create_from_image(E->get(),tex_flags);
- _process_texture_data(imgtex,format,quality,flags,p_compr,tex_flags,shrink);
- existing->add_piece(E->key(),imgtex);
- }
-
- if (!p_external) {
- from->set_editor(get_name());
- from->set_source_md5(0,FileAccess::get_md5(src_path));
- existing->set_path(p_path);
- existing->set_import_metadata(from);
- }
- pg.step(TTR("Saving"),3);
-
- err = ResourceSaver::save(p_path,existing);
- if (err!=OK) {
- EditorNode::add_io_error(TTR("Couldn't save large texture:")+" "+p_path);
- return err;
- }
-
- return OK;
-
-
- } else if (atlas) {
-
- //prepare atlas!
- Vector< Image > sources;
- Vector< Image > tsources;
- bool alpha=false;
- bool crop = from->get_option("crop");
-
- EditorProgress ep("make_atlas",TTR("Build Atlas For:")+" "+p_path.get_file(),from->get_source_count()+3);
-
- print_line("sources: "+itos(from->get_source_count()));
-
- for(int i=0;i<from->get_source_count();i++) {
-
- String path = EditorImportPlugin::expand_source_path(from->get_source_path(i));
- String md5 = FileAccess::get_md5(path);
- from->set_source_md5(i,FileAccess::get_md5(path));
- ep.step(TTR("Loading Image:")+" "+path,i);
- print_line("source path: "+path+" md5 "+md5);
- Image src;
- Error err = ImageLoader::load_image(path,&src);
- if (err) {
- EditorNode::add_io_error(TTR("Couldn't load image:")+" "+path);
- return err;
- }
-
- if (src.detect_alpha())
- alpha=true;
-
- tsources.push_back(src);
- }
- ep.step(TTR("Converting Images"),sources.size());
-
-
- Map<uint64_t,int> source_md5;
- Map<int,List<int> > source_map;
-
- for(int i=0;i<tsources.size();i++) {
-
- Image src = tsources[i];
-
- if (alpha) {
- src.convert(Image::FORMAT_RGBA8);
- } else {
- src.convert(Image::FORMAT_RGB8);
- }
-
- PoolVector<uint8_t> data = src.get_data();
- MD5_CTX md5;
- PoolVector<uint8_t>::Read r=data.read();
- MD5Init(&md5);
- int len=data.size();
- for(int j=0;j<len;j++) {
- uint8_t b = r[j];
- b>>=2; //to aid in comparing
- MD5Update(&md5,(unsigned char*)&b,1);
- }
- MD5Final(&md5);
- uint64_t *cmp = (uint64_t*)md5.digest; //less bits, but still useful for this
-
- tsources[i]=Image(); //clear
-
- if (source_md5.has(*cmp)) {
- int sidx=source_md5[*cmp];
- source_map[sidx].push_back(i);
- print_line("REUSING "+from->get_source_path(i));
-
- } else {
- int sidx=sources.size();
- source_md5[*cmp]=sidx;
- sources.push_back(src);
- List<int> sm;
- sm.push_back(i);
- source_map[sidx]=sm;
-
- }
-
-
- }
-
- //texturepacker is not really good for optimizing, so..
- //will at some point likely replace with my own
- //first, will find the nearest to a square packing
- int border=1;
-
- Vector<Size2i> src_sizes;
- Vector<Rect2> crops;
-
- ep.step(TTR("Cropping Images"),sources.size()+1);
-
- for(int j=0;j<sources.size();j++) {
-
- Size2i s;
- if (crop) {
- Rect2 crop = sources[j].get_used_rect();
- print_line("CROP: "+crop);
- s=crop.size;
- crops.push_back(crop);
- } else {
-
- s=Size2i(sources[j].get_width(),sources[j].get_height());
- }
- s+=Size2i(border*2,border*2);
- src_sizes.push_back(s); //add a line to constraint width
- }
-
- Vector<Point2i> dst_positions;
- Size2i dst_size;
- EditorAtlas::fit(src_sizes,dst_positions,dst_size);
-
- print_line("size that worked: "+itos(dst_size.width)+","+itos(dst_size.height));
-
- ep.step(TTR("Blitting Images"),sources.size()+2);
-
- bool blit_to_po2=tex_flags&Texture::FLAG_MIPMAPS;
- int atlas_w=dst_size.width;
- int atlas_h=dst_size.height;
- if (blit_to_po2) {
- atlas_w=nearest_power_of_2(dst_size.width);
- atlas_h=nearest_power_of_2(dst_size.height);
- }
- Image atlas;
- atlas.create(atlas_w,atlas_h,0,alpha?Image::FORMAT_RGBA8:Image::FORMAT_RGB8);
-
-
- atlases.resize(from->get_source_count());
-
- for(int i=0;i<sources.size();i++) {
-
- int x=dst_positions[i].x;
- int y=dst_positions[i].y;
-
- Size2 sz = Size2(sources[i].get_width(),sources[i].get_height());
-
- Rect2 region;
- Rect2 margin;
-
- if (crop && sz!=crops[i].size) {
- Rect2 rect = crops[i];
- rect.size=sz-rect.size;
- region=Rect2(x+border,y+border,crops[i].size.width,crops[i].size.height);
- margin=rect;
- atlas.blit_rect(sources[i],crops[i],Point2(x+border,y+border));
- } else {
- region=Rect2(x+border,y+border,sz.x,sz.y);
- atlas.blit_rect(sources[i],Rect2(0,0,sources[i].get_width(),sources[i].get_height()),Point2(x+border,y+border));
- }
-
- ERR_CONTINUE( !source_map.has(i) );
- for (List<int>::Element *E=source_map[i].front();E;E=E->next()) {
-
- String apath;
- String spath = from->get_source_path(E->get()).get_file();
-
- if (p_external) {
- apath = p_path.get_base_dir().plus_file(spath.get_basename()+"."+from->get_source_path(E->get()).md5_text()+".atex");
- } else {
- apath = p_path.get_base_dir().plus_file(spath.get_basename()+".atex");
- }
-
- Ref<AtlasTexture> at;
-
- if (ResourceCache::has(apath)) {
-
- at = Ref<AtlasTexture>( ResourceCache::get(apath)->cast_to<AtlasTexture>() );
- } else {
-
- at = Ref<AtlasTexture>( memnew( AtlasTexture ) );
-
- }
- at->set_region(region);
- at->set_margin(margin);
- at->set_path(apath);
- atlases[E->get()]=at;
-
- }
- }
- if (ResourceCache::has(p_path)) {
- texture = Ref<ImageTexture> ( ResourceCache::get(p_path)->cast_to<ImageTexture>() );
- } else {
- texture = Ref<ImageTexture>( memnew( ImageTexture ) );
- }
- texture->create_from_image(atlas,tex_flags);
-
- } else {
- ERR_FAIL_COND_V(from->get_source_count()!=1,ERR_INVALID_PARAMETER);
-
- String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
-
- if (ResourceCache::has(p_path)) {
- Resource *r = ResourceCache::get(p_path);
-
- texture = Ref<ImageTexture> ( r->cast_to<ImageTexture>() );
-
- Image img;
- Error err = img.load(src_path);
- ERR_FAIL_COND_V(err!=OK,ERR_CANT_OPEN);
- texture->create_from_image(img);
- } else {
- texture=ResourceLoader::load(src_path,"ImageTexture");
- }
-
- ERR_FAIL_COND_V(texture.is_null(),ERR_CANT_OPEN);
- if (!p_external)
- from->set_source_md5(0,FileAccess::get_md5(src_path));
-
- }
-
-
-
- if (!p_external) {
- from->set_editor(get_name());
- texture->set_path(p_path);
- texture->set_import_metadata(from);
- }
-
- if (atlas) {
-
- if (p_external) {
- //used by exporter
- Array rects;
- for(int i=0;i<atlases.size();i++) {
- rects.push_back(atlases[i]->get_region());
- rects.push_back(atlases[i]->get_margin());
- }
- from->set_option("rects",rects);
-
- } else {
- //used by importer
- for(int i=0;i<atlases.size();i++) {
- String apath = atlases[i]->get_path();
- atlases[i]->set_atlas(texture);
- Error err = ResourceSaver::save(apath,atlases[i]);
- if (err) {
- EditorNode::add_io_error(TTR("Couldn't save atlas image:")+" "+apath);
- return err;
- }
- //from->set_source_md5(i,FileAccess::get_md5(apath));
- }
- }
- }
-
- bool compress=false;
-#if 1
-
- _process_texture_data(texture,format,quality,flags,p_compr,tex_flags,shrink);
-#else
- if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS || format==IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
-
- Image image=texture->get_data();
- ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
-
- bool has_alpha=image.detect_alpha();
- if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
-
- image.convert(Image::FORMAT_RGB8);
-
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
-
- image.fix_alpha_edges();
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
-
- image.premultiply_alpha();
- }
-
- if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
- image.normalmap_to_xy();
- }
-
- /*
- if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
-
- image.srgb_to_linear();
- }
- */
-
- if (shrink>1) {
-
- int orig_w=image.get_width();
- int orig_h=image.get_height();
- image.resize(orig_w/shrink,orig_h/shrink);
- texture->create_from_image(image,tex_flags);
- texture->set_size_override(Size2(orig_w,orig_h));
-
-
- } else {
-
- texture->create_from_image(image,tex_flags);
- }
-
-
- if (format==IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS) {
- texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSLESS);
- } else {
- texture->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
- }
-
-
-
- texture->set_lossy_storage_quality(quality);
-
-
- } else {
-
-
- Image image=texture->get_data();
- ERR_FAIL_COND_V(image.empty(),ERR_INVALID_DATA);
-
-
- bool has_alpha=image.detect_alpha();
- if (!has_alpha && image.get_format()==Image::FORMAT_RGBA8) {
-
- image.convert(Image::FORMAT_RGB8);
-
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_FIX_BORDER_ALPHA) {
-
- image.fix_alpha_edges();
- }
-
- if (image.get_format()==Image::FORMAT_RGBA8 && flags&IMAGE_FLAG_PREMULT_ALPHA) {
-
- image.premultiply_alpha();
- }
-
- if (flags&IMAGE_FLAG_CONVERT_NORMAL_TO_XY) {
- image.normalmap_to_xy();
- }
-
- /*
- if ((image.get_format()==Image::FORMAT_RGB8 || image.get_format()==Image::FORMAT_RGBA8) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
-
- print_line("CONVERT BECAUSE: "+itos(flags));
- image.srgb_to_linear();
- }
- */
-
- int orig_w=image.get_width();
- int orig_h=image.get_height();
-
- if (shrink>1) {
- image.resize(orig_w/shrink,orig_h/shrink);
- texture->create_from_image(image,tex_flags);
- texture->set_size_override(Size2(orig_w,orig_h));
- }
-
- if (!(flags&IMAGE_FLAG_NO_MIPMAPS)) {
- image.generate_mipmaps();
-
- }
-
- if (format!=IMAGE_FORMAT_UNCOMPRESSED) {
-
- compress_image(p_compr,image,flags&IMAGE_FLAG_COMPRESS_EXTRA);
- }
-
-
- texture->create_from_image(image,tex_flags);
-
-
- if (shrink>1 || (format!=IMAGE_FORMAT_UNCOMPRESSED && (image.get_width()!=orig_w || image.get_height()!=orig_h))) {
- texture->set_size_override(Size2(orig_w,orig_h));
- }
-
- compress=true;
-
-
- }
-#endif
- uint32_t save_flags=0;
- if (compress)
- save_flags=ResourceSaver::FLAG_COMPRESS;
-
- Error err = ResourceSaver::save(p_path,texture,save_flags);
- if (err!=OK) {
- EditorNode::add_io_error(TTR("Couldn't save converted texture:")+" "+p_path);
- return err;
- }
-
- return OK;
-}
-
-Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, const Ref<EditorExportPlatform> &p_platform) {
-
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
-
- if (rimd.is_null()) {
-
- StringName group = EditorImportExport::get_singleton()->image_get_export_group(p_path);
-
- if (group!=StringName()) {
- //handled by export group
- rimd = Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) );
-
- int group_format=0;
- float group_lossy_quality=EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(group);
- int group_shrink=EditorImportExport::get_singleton()->image_export_group_get_shrink(group);
- group_shrink*=EditorImportExport::get_singleton()->get_export_image_shrink();
-
- switch(EditorImportExport::get_singleton()->image_export_group_get_image_action(group)) {
- case EditorImportExport::IMAGE_ACTION_NONE: {
-
- switch(EditorImportExport::get_singleton()->get_export_image_action()) {
- case EditorImportExport::IMAGE_ACTION_NONE: {
-
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS; //?
-
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
- } break; //use default
- }
-
- group_lossy_quality=EditorImportExport::get_singleton()->get_export_image_quality();
-
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY;
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: {
- group_format=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM;
- } break; //use default
- case EditorImportExport::IMAGE_ACTION_KEEP: {
- return Vector<uint8_t>();
- } break; //use default
- }
-
- String validated_path=EditorImportPlugin::validate_source_path(p_path);
-
- int flags=texture_flags_to_export_flags(ResourceFormatLoaderImage::load_image_flags(validated_path));
- flags|=IMAGE_FLAG_FIX_BORDER_ALPHA;
-
- print_line("group format"+itos(group_format));
- rimd->set_option("format",group_format);
- rimd->set_option("flags",flags);
- rimd->set_option("quality",group_lossy_quality);
- rimd->set_option("atlas",false);
- rimd->set_option("shrink",group_shrink);
- rimd->add_source(validated_path,FileAccess::get_md5(p_path));
-
- } else if (EditorImportExport::get_singleton()->get_image_formats().has(p_path.get_extension().to_lower()) && EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE) {
- //handled by general image export settings
-
- rimd = Ref<ResourceImportMetadata>( memnew( ResourceImportMetadata ) );
-
- switch(EditorImportExport::get_singleton()->get_export_image_action()) {
- case EditorImportExport::IMAGE_ACTION_COMPRESS_DISK: rimd->set_option("format",IMAGE_FORMAT_COMPRESS_DISK_LOSSY); break;
- case EditorImportExport::IMAGE_ACTION_COMPRESS_RAM: rimd->set_option("format",IMAGE_FORMAT_COMPRESS_RAM); break;
- }
-
- String validated_path=EditorImportPlugin::validate_source_path(p_path);
-
- int flags=texture_flags_to_export_flags(ResourceFormatLoaderImage::load_image_flags(validated_path));
- flags|=IMAGE_FLAG_FIX_BORDER_ALPHA;
-
- rimd->set_option("shrink",EditorImportExport::get_singleton()->get_export_image_shrink());
- rimd->set_option("flags",flags);
- rimd->set_option("quality",EditorImportExport::get_singleton()->get_export_image_quality());
- rimd->set_option("atlas",false);
- rimd->add_source(validated_path,FileAccess::get_md5(p_path));
-
- } else {
- return Vector<uint8_t>();
- }
- }
-
- int fmt = rimd->get_option("format");
-
- if (fmt!=IMAGE_FORMAT_COMPRESS_RAM && fmt!=IMAGE_FORMAT_COMPRESS_DISK_LOSSY) {
- print_line("no compress ram or lossy");
- return Vector<uint8_t>(); //pointless to do anything, since no need to reconvert
- }
-
- uint32_t flags = rimd->get_option("flags");
- uint8_t shrink = rimd->has_option("shrink") ? rimd->get_option("shrink"): Variant(1);
- uint8_t format = rimd->get_option("format");
- uint8_t comp = (format==EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM)?uint8_t(p_platform->get_image_compression()):uint8_t(255);
-
- MD5_CTX ctx;
- uint8_t f4[4];
- encode_uint32(flags,&f4[0]);
- MD5Init(&ctx);
- String gp = GlobalConfig::get_singleton()->globalize_path(p_path);
- CharString cs = gp.utf8();
- MD5Update(&ctx,(unsigned char*)cs.get_data(),cs.length());
- MD5Update(&ctx,f4,4);
- MD5Update(&ctx,&format,1);
- MD5Update(&ctx,&comp,1);
- MD5Update(&ctx,&shrink,1);
- MD5Final(&ctx);
-
-
-
- uint64_t sd=0;
- String smd5;
-
- String md5 = String::md5(ctx.digest);
- print_line(p_path+" MD5: "+md5+" FLAGS: "+itos(flags));
-
- 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+"imgexp-"+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
- Error err = import2(tmp_path+"imgexp-"+md5+".tex",rimd,p_platform->get_image_compression(),true);
- ERR_FAIL_COND_V(err!=OK,Vector<uint8_t>());
- FileAccessRef f = FileAccess::open(tmp_path+"imgexp-"+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;
- FileAccessRef f = FileAccess::open(tmp_path+"imgexp-"+md5+".tex",FileAccess::READ);
- ERR_FAIL_COND_V(!f,ret);
-
- ret.resize(f->get_len());
- f->get_buffer(ret.ptr(),ret.size());
-
- return ret;
-}
-
-uint32_t EditorTextureImportPlugin::texture_flags_to_export_flags(uint32_t p_tex_flags) const {
-
- uint32_t flags=0;
-
- if (!(p_tex_flags&Texture::FLAG_MIPMAPS)) {
- flags|=IMAGE_FLAG_NO_MIPMAPS;
- }
- if (p_tex_flags&Texture::FLAG_REPEAT) {
- flags|=IMAGE_FLAG_REPEAT;
- }
- if (p_tex_flags&Texture::FLAG_FILTER) {
- flags|=IMAGE_FLAG_FILTER;
- }
- if (p_tex_flags&Texture::FLAG_ANISOTROPIC_FILTER) {
- flags|=IMAGE_FLAG_USE_ANISOTROPY;
- }
- if (p_tex_flags&Texture::FLAG_CONVERT_TO_LINEAR) {
- flags|=IMAGE_FLAG_CONVERT_TO_LINEAR;
- }
- /* // no correspondence yet
- if (p_tex_flags&Texture::TEXTURE_FLAG_MIRRORED_REPEAT) {
- flags|=;
- }*/
-
- return flags;
-}
-
-void EditorTextureImportPlugin::import_from_drop(const Vector<String>& p_drop,const String& p_dest_path) {
-
- Vector<String> valid;
-
- List<String> valid_extensions;
- ImageLoader::get_recognized_extensions(&valid_extensions);
- for(int i=0;i<p_drop.size();i++) {
-
- String extension=p_drop[i].get_extension().to_lower();
-
- for (List<String>::Element *E=valid_extensions.front();E;E=E->next()) {
-
- if (E->get()==extension) {
- valid.push_back(p_drop[i]);
- break;
- }
- }
- }
-
- if (valid.size()) {
- dialog->popup_import();
- dialog->setup_multiple_import_3d(valid,p_dest_path);
- }
-}
-
-void EditorTextureImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
-
- Vector<String> valid;
-
-
- for(int i=0;i<p_list.size();i++) {
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_list[i]);
- String type = rimd->get_editor();
- if (type=="texture" || type.begins_with("texture_")) {
-
- if ((rimd->has_option("atlas") && rimd->get_option("atlas")) || (rimd->has_option("large") && rimd->get_option("large"))) {
- continue;
- }
-
- valid.push_back(p_list[i]);
- }
- }
-
- if (valid.size()) {
-
- dialog->popup_import(valid[0]);
-
- Vector<String> sources;
- for(int i=0;i<valid.size();i++) {
- int idx;
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(valid[i],&idx);
- if (efsd) {
- for(int j=0;j<efsd->get_source_count(idx);j++) {
- String file = expand_source_path(efsd->get_source_file(idx,j));
- if (sources.find(file)==-1) {
- sources.push_back(file);
- }
-
- }
- }
- }
-
- if (sources.size()) {
-
- dialog->add_sources_and_dest(sources,valid[0].get_base_dir());
- }
- }
-}
-
-bool EditorTextureImportPlugin::can_reimport_multiple_files() const {
-
- return true;
-
-}
-
-
-
-EditorTextureImportPlugin *EditorTextureImportPlugin::singleton=NULL;
-
-EditorTextureImportPlugin::EditorTextureImportPlugin(EditorNode *p_editor) {
-
- singleton=this;
- editor=p_editor;
- dialog = memnew( EditorTextureImportDialog(this) );
- editor->get_gui_base()->add_child(dialog);
-
-}
-
-////////////////////////////
-
-
- Vector<uint8_t> EditorTextureExportPlugin::custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) {
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
-
- if (rimd.is_valid()) {
-
- if (rimd->get_editor()!="") {
- int compression = rimd->get_option("format");
- if (compression!=EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_RAM)
- return Vector<uint8_t>(); //only useful for RAM compression to reconvert
- Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name(rimd->get_editor());
- if (pl.is_valid()) {
- Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
- if (ce.size())
- return ce;
- }
- }
- } else if (EditorImportExport::get_singleton()->image_get_export_group(p_path)) {
-
-
- Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture");
- if (pl.is_valid()) {
- Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
- if (ce.size()) {
- p_path=p_path.get_basename()+".converted.tex";
- return ce;
- }
- }
-
- } else if (EditorImportExport::get_singleton()->get_export_image_action()!=EditorImportExport::IMAGE_ACTION_NONE){
-
- String xt = p_path.get_extension().to_lower();
- if (EditorImportExport::get_singleton()->get_image_formats().has(xt)) { //should check for more I guess?
-
- Ref<EditorImportPlugin> pl = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture");
- if (pl.is_valid()) {
- Vector<uint8_t> ce = pl->custom_export(p_path,p_platform);
- if (ce.size()) {
- p_path=p_path.get_basename()+".converted.tex";
- return ce;
- }
- }
- }
- }
-
- return Vector<uint8_t>();
-}
-
-EditorTextureExportPlugin::EditorTextureExportPlugin() {
-
-
-}
-#endif
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.h b/tools/editor/io_plugins/editor_texture_import_plugin.h
deleted file mode 100644
index ce15df0f18..0000000000
--- a/tools/editor/io_plugins/editor_texture_import_plugin.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*************************************************************************/
-/* editor_texture_import_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_TEXTURE_IMPORT_PLUGIN_H
-#define EDITOR_TEXTURE_IMPORT_PLUGIN_H
-
-
-
-
-
-
-#if 0
-#include "tools/editor/editor_import_export.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/label.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/progress_bar.h"
-#include "scene/gui/slider.h"
-#include "scene/gui/spin_box.h"
-#include "tools/editor/editor_file_system.h"
-#include "tools/editor/editor_dir_dialog.h"
-
-
-
-class EditorNode;
-class EditorTextureImportDialog;
-
-class EditorTextureImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorTextureImportPlugin,EditorImportPlugin);
-public:
-
-
- enum Mode {
- MODE_TEXTURE_2D,
- MODE_TEXTURE_3D,
- MODE_ATLAS,
- MODE_LARGE,
- MODE_MAX
- };
-
-
-
-private:
-
- EditorNode *editor;
- EditorTextureImportDialog *dialog;
- static EditorTextureImportPlugin *singleton;
- //used by other importers such as mesh
-
- Error _process_texture_data(Ref<ImageTexture> &texture, int format, float quality, int flags,EditorExportPlatform::ImageCompression p_compr,int tex_flags,float shrink);
- void compress_image(EditorExportPlatform::ImageCompression p_mode,Image& image,bool p_smaller);
-
- uint32_t texture_flags_to_export_flags(uint32_t p_tex_flags) const;
-public:
-
-
- static EditorTextureImportPlugin *get_singleton() { return singleton; }
-
- enum ImageFormat {
-
- IMAGE_FORMAT_UNCOMPRESSED,
- IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS,
- IMAGE_FORMAT_COMPRESS_DISK_LOSSY,
- IMAGE_FORMAT_COMPRESS_RAM,
- };
-
- enum ImageFlags {
-
- IMAGE_FLAG_STREAM_FORMAT=1,
- IMAGE_FLAG_FIX_BORDER_ALPHA=2,
- IMAGE_FLAG_ALPHA_BIT=4, //hint for compressions that use a bit for alpha
- IMAGE_FLAG_COMPRESS_EXTRA=8, // used for pvrtc2
- IMAGE_FLAG_NO_MIPMAPS=16, //normal for 2D games
- IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
- IMAGE_FLAG_FILTER=64, //almost always enabled
- IMAGE_FLAG_PREMULT_ALPHA=128,//almost always enabled
- IMAGE_FLAG_CONVERT_TO_LINEAR=256, //convert image to linear
- IMAGE_FLAG_CONVERT_NORMAL_TO_XY=512, //convert image to linear
- IMAGE_FLAG_USE_ANISOTROPY=1024, //convert image to linear
- };
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
- virtual Error import2(const String& p_path, const Ref<ResourceImportMetadata>& p_from,EditorExportPlatform::ImageCompression p_compr, bool p_external=false);
- virtual Vector<uint8_t> custom_export(const String& p_path,const Ref<EditorExportPlatform> &p_platform);
-
- virtual void import_from_drop(const Vector<String>& p_drop,const String& p_dest_path);
- virtual void reimport_multiple_files(const Vector<String>& p_list);
- virtual bool can_reimport_multiple_files() const;
-
- EditorTextureImportPlugin(EditorNode* p_editor=NULL);
-};
-
-
-class EditorTextureExportPlugin : public EditorExportPlugin {
-
- GDCLASS( EditorTextureExportPlugin, EditorExportPlugin);
-
-
-public:
-
- virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform);
- EditorTextureExportPlugin();
-};
-
-class EditorImportTextureOptions : public VBoxContainer {
-
- GDCLASS( EditorImportTextureOptions, VBoxContainer );
-
-
- OptionButton *format;
- VBoxContainer *quality_vb;
- HSlider *quality;
- Tree *flags;
- Vector<TreeItem*> items;
-
-
- bool updating;
-
- void _changedp(int p_value);
- void _changed();
-
-
-protected:
- static void _bind_methods();
- void _notification(int p_what);
-
-public:
-
-
-
- void set_format(EditorTextureImportPlugin::ImageFormat p_format);
- EditorTextureImportPlugin::ImageFormat get_format() const;
-
- void set_flags(uint32_t p_flags);
- uint32_t get_flags() const;
-
- void set_quality(float p_quality);
- float get_quality() const;
-
- void show_2d_notice();
-
- EditorImportTextureOptions();
-
-
-};
-#endif // EDITOR_TEXTURE_IMPORT_PLUGIN_H
-#endif
diff --git a/tools/editor/io_plugins/editor_translation_import_plugin.cpp b/tools/editor/io_plugins/editor_translation_import_plugin.cpp
deleted file mode 100644
index 5ecb0b1abf..0000000000
--- a/tools/editor/io_plugins/editor_translation_import_plugin.cpp
+++ /dev/null
@@ -1,479 +0,0 @@
-/*************************************************************************/
-/* editor_translation_import_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_translation_import_plugin.h"
-
-#if 0
-#include "scene/gui/file_dialog.h"
-#include "tools/editor/editor_dir_dialog.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/property_editor.h"
-//#include "scene/resources/sample.h"
-#include "io/resource_saver.h"
-#include "os/file_access.h"
-#include "translation.h"
-#include "compressed_translation.h"
-#include "tools/editor/project_settings.h"
-
-
-class EditorTranslationImportDialog : public ConfirmationDialog {
-
- GDCLASS(EditorTranslationImportDialog,ConfirmationDialog);
-
- EditorTranslationImportPlugin *plugin;
-
- LineEdit *import_path;
- LineEdit *save_path;
- EditorFileDialog *file_select;
- CheckButton *ignore_first;
- CheckButton *compress;
- CheckButton *add_to_project;
- EditorDirDialog *save_select;
- ConfirmationDialog *error_dialog;
- Vector<TreeItem*> items;
- Tree *columns;
-
-public:
-
- void _choose_file(const String& p_path) {
-
- import_path->set_text(p_path);
- FileAccess *f = FileAccess::open(p_path,FileAccess::READ);
- if (!f) {
-
- error_dialog->set_text(TTR("Invalid source!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
-
- }
-
- Vector<String> csvh = f->get_csv_line();
- memdelete(f);
-
- if (csvh.size()<2) {
-
- error_dialog->set_text(TTR("Invalid translation source!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- return;
-
- }
-
- columns->clear();
- columns->set_columns(2);
- TreeItem *root = columns->create_item();
- columns->set_hide_root(true);
- columns->set_column_titles_visible(true);
- columns->set_column_title(0,TTR("Column"));
- columns->set_column_title(1,TTR("Language"));
- Vector<String> langs = TranslationServer::get_all_locales();
- Vector<String> names = TranslationServer::get_all_locale_names();
- if (csvh[0]=="")
- ignore_first->set_pressed(true);
-
-
- items.clear();
-
- for(int i=1;i<csvh.size();i++) {
-
- TreeItem *ti = columns->create_item(root);
-
- ti->set_editable(0,true);
- ti->set_selectable(0,false);
- ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- ti->set_checked(0,true);
- ti->set_text(0,itos(i));
- items.push_back(ti);
-
- String lname = csvh[i].to_lower().strip_edges();
- int idx=-1;
- String hint;
- for(int j=0;j<langs.size();j++) {
-
- if (langs[j]==lname.substr(0,langs[j].length()).to_lower()) {
- idx=j;
- }
- if (j>0) {
- hint+=",";
- }
- hint+=names[j].replace(","," ");
- }
-
- ti->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- ti->set_text(1,hint);
- ti->set_editable(1,true);
-
-
- if (idx!=-1) {
- ignore_first->set_pressed(true);
- ti->set_range(1,idx);
- } else {
-
- //not found, maybe used stupid name
- if (lname.begins_with("br")) //brazilian
- ti->set_range(1,langs.find("pt"));
- else if (lname.begins_with("ch")) //chinese
- ti->set_range(1,langs.find("zh"));
- else if (lname.begins_with("sp")) //spanish
- ti->set_range(1,langs.find("es"));
- else if (lname.begins_with("kr"))// kprean
- ti->set_range(1,langs.find("ko"));
- else if (i==0)
- ti->set_range(1,langs.find("en"));
- else
- ti->set_range(1,langs.find("es"));
- }
-
- ti->set_metadata(1,names[ti->get_range(1)]);
- }
-
-
-
- }
- void _choose_save_dir(const String& p_path) {
-
- save_path->set_text(p_path);
- }
-
- void _browse() {
-
- file_select->popup_centered_ratio();
- }
-
- void _browse_target() {
-
- save_select->popup_centered_ratio();
-
- }
-
-
- void popup_import(const String& p_from) {
-
- popup_centered(Size2(400,400)*EDSCALE);
-
- if (p_from!="") {
-
- Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
- ERR_FAIL_COND(!rimd.is_valid());
- ERR_FAIL_COND(rimd->get_source_count()!=1);
- _choose_file(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
- _choose_save_dir(p_from.get_base_dir());
- String locale = rimd->get_option("locale");
- bool skip_first=rimd->get_option("skip_first");
- bool compressed = rimd->get_option("compress");
-
- int idx=-1;
-
- for(int i=0;i<items.size();i++) {
-
- String il = TranslationServer::get_all_locales()[items[i]->get_range(1)];
- if (il==locale) {
- idx=i;
- break;
- }
- }
-
- if (idx!=-1) {
- idx=rimd->get_option("index");
- }
-
- for(int i=0;i<items.size();i++) {
-
- if (i==idx) {
-
- Vector<String> locs = TranslationServer::get_all_locales();
- for(int j=0;j<locs.size();j++) {
- if (locs[j]==locale) {
- items[i]->set_range(1,j);
- }
-
- }
- items[i]->set_checked(0,true);
- } else {
- items[i]->set_checked(0,false);
-
- }
- }
-
- ignore_first->set_pressed(skip_first);
- compress->set_pressed(compressed);
-
-
-
- }
-
- }
-
-
- void _import() {
-
-
- if (items.size()==0) {
- error_dialog->set_text(TTR("No items to import!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- }
-
- if (!save_path->get_text().begins_with("res://")) {
- error_dialog->set_text(TTR("No target path!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- }
-
- EditorProgress progress("import_xl",TTR("Import Translations"),items.size());
- for(int i=0;i<items.size();i++) {
-
- progress.step(items[i]->get_metadata(1),i);
- if (!items[i]->is_checked(0))
- continue;
-
- String locale = TranslationServer::get_all_locales()[items[i]->get_range(1)];
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
- imd->add_source(EditorImportPlugin::validate_source_path(import_path->get_text()));
- imd->set_option("locale",locale);
- imd->set_option("index",i);
- imd->set_option("skip_first",ignore_first->is_pressed());
- imd->set_option("compress",compress->is_pressed());
-
- String savefile = save_path->get_text().plus_file(import_path->get_text().get_file().get_basename()+"."+locale+".xl");
- Error err = plugin->import(savefile,imd);
- if (err!=OK) {
- error_dialog->set_text(TTR("Couldn't import!"));
- error_dialog->popup_centered(Size2(200,100)*EDSCALE);
- } else if (add_to_project->is_pressed()) {
-
- ProjectSettings::get_singleton()->add_translation(savefile);
- }
- }
- hide();
-
- }
-
-
- void _notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
-
- }
- }
-
- static void _bind_methods() {
-
-
- ClassDB::bind_method("_choose_file",&EditorTranslationImportDialog::_choose_file);
- ClassDB::bind_method("_choose_save_dir",&EditorTranslationImportDialog::_choose_save_dir);
- ClassDB::bind_method("_import",&EditorTranslationImportDialog::_import);
- ClassDB::bind_method("_browse",&EditorTranslationImportDialog::_browse);
- ClassDB::bind_method("_browse_target",&EditorTranslationImportDialog::_browse_target);
- //ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
- }
-
- EditorTranslationImportDialog(EditorTranslationImportPlugin *p_plugin) {
-
- plugin=p_plugin;
-
-
- set_title(TTR("Import Translation"));
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
-
-
-
- VBoxContainer *csvb = memnew( VBoxContainer );
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- csvb->add_child(hbc);
- vbc->add_margin_child(TTR("Source CSV:"),csvb);
-
- import_path = memnew( LineEdit );
- import_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(import_path);
- ignore_first = memnew( CheckButton );
- ignore_first->set_text(TTR("Ignore First Row"));
- csvb->add_child(ignore_first);
-
- Button * import_choose = memnew( Button );
- import_choose->set_text(" .. ");
- hbc->add_child(import_choose);
-
- import_choose->connect("pressed", this,"_browse");
-
- VBoxContainer *tcomp = memnew( VBoxContainer);
- hbc = memnew( HBoxContainer );
- tcomp->add_child(hbc);
- vbc->add_margin_child(TTR("Target Path:"),tcomp);
-
- save_path = memnew( LineEdit );
- save_path->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(save_path);
-
- Button * save_choose = memnew( Button );
- save_choose->set_text(" .. ");
- hbc->add_child(save_choose);
-
- save_choose->connect("pressed", this,"_browse_target");
-
- compress = memnew( CheckButton);
- compress->set_pressed(true);
- compress->set_text(TTR("Compress"));
- tcomp->add_child(compress);
-
- add_to_project = memnew( CheckButton);
- add_to_project->set_pressed(true);
- add_to_project->set_text(TTR("Add to Project (godot.cfg)"));
- tcomp->add_child(add_to_project);
-
- file_select = memnew(EditorFileDialog);
- file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- add_child(file_select);
- file_select->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- file_select->connect("file_selected", this,"_choose_file");
- file_select->add_filter("*.csv ; Translation CSV");
- save_select = memnew( EditorDirDialog );
- add_child(save_select);
-
- //save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
- save_select->connect("dir_selected", this,"_choose_save_dir");
-
- get_ok()->connect("pressed", this,"_import");
- get_ok()->set_text(TTR("Import"));
-
-
- error_dialog = memnew ( ConfirmationDialog );
- add_child(error_dialog);
- error_dialog->get_ok()->set_text(TTR("Accept"));
- //error_dialog->get_cancel()->hide();
-
- set_hide_on_ok(false);
-
- columns = memnew( Tree );
- vbc->add_margin_child(TTR("Import Languages:"),columns,true);
- }
-
- ~EditorTranslationImportDialog() {
-
- }
-
-};
-
-
-String EditorTranslationImportPlugin::get_name() const {
-
- return "translation";
-}
-String EditorTranslationImportPlugin::get_visible_name() const {
-
- return TTR("Translation");
-}
-void EditorTranslationImportPlugin::import_dialog(const String& p_from) {
-
- dialog->popup_import(p_from);
-}
-
-
-
-void EditorTranslationImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
-
-
- for(int i=0;i<p_drop.size();i++) {
- String ext = p_drop[i].get_extension().to_lower();
-
- if (ext=="csv") {
-
- import_dialog();
- dialog->_choose_file(p_drop[i]);
- dialog->_choose_save_dir(p_dest_path);
- break;
- }
- }
-
-
-}
-
-Error EditorTranslationImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from) {
-
- Ref<ResourceImportMetadata> from = p_from;
- ERR_FAIL_COND_V( from->get_source_count()!=1, ERR_INVALID_PARAMETER);
-
- String source = EditorImportPlugin::expand_source_path( from->get_source_path(0) );
-
- FileAccessRef f = FileAccess::open(source,FileAccess::READ);
-
- ERR_FAIL_COND_V( !f, ERR_INVALID_PARAMETER );
-
- bool skip_first = from->get_option("skip_first");
- int index = from->get_option("index");
- index+=1;
- String locale = from->get_option("locale");
-
- Ref<Translation> translation = memnew( Translation );
-
- translation->set_locale( locale );
-
- Vector<String> line = f->get_csv_line();
-
- while(line.size()>1) {
-
- if (!skip_first) {
- ERR_FAIL_INDEX_V(index,line.size(),ERR_INVALID_DATA );
- translation->add_message(line[0].strip_edges(),line[index]);
-
- } else {
-
- skip_first=false;
- }
-
- line = f->get_csv_line();
- }
-
- from->set_source_md5(0,FileAccess::get_md5(source));
- from->set_editor(get_name());
-
- String dst_path = p_path;
-
- if (from->get_option("compress")) {
-
- Ref<PHashTranslation> cxl = memnew( PHashTranslation );
- cxl->generate( translation );
- translation=cxl;
- }
-
- translation->set_import_metadata(from);
- return ResourceSaver::save(dst_path,translation);
-
-}
-
-
-EditorTranslationImportPlugin::EditorTranslationImportPlugin(EditorNode* p_editor) {
-
- dialog = memnew(EditorTranslationImportDialog(this));
- p_editor->get_gui_base()->add_child(dialog);
-}
-
-#endif
diff --git a/tools/editor/io_plugins/editor_translation_import_plugin.h b/tools/editor/io_plugins/editor_translation_import_plugin.h
deleted file mode 100644
index 4884ea71c5..0000000000
--- a/tools/editor/io_plugins/editor_translation_import_plugin.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*************************************************************************/
-/* editor_translation_import_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#ifndef EDITOR_TRANSLATION_IMPORT_PLUGIN_H
-#define EDITOR_TRANSLATION_IMPORT_PLUGIN_H
-
-#include "tools/editor/editor_import_export.h"
-#include "scene/resources/font.h"
-#if 0
-class EditorNode;
-class EditorTranslationImportDialog;
-
-class EditorTranslationImportPlugin : public EditorImportPlugin {
-
- GDCLASS(EditorTranslationImportPlugin,EditorImportPlugin);
-
- EditorTranslationImportDialog *dialog;
-public:
-
- virtual String get_name() const;
- virtual String get_visible_name() const;
- virtual void import_dialog(const String& p_from="");
- virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
- void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
-
-
- EditorTranslationImportPlugin(EditorNode* p_editor);
-};
-
-#endif
-#endif // EDITOR_TRANSLATION_IMPORT_PLUGIN_H
diff --git a/tools/editor/multi_node_edit.cpp b/tools/editor/multi_node_edit.cpp
deleted file mode 100644
index 97a996fe48..0000000000
--- a/tools/editor/multi_node_edit.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/*************************************************************************/
-/* multi_node_edit.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "multi_node_edit.h"
-
-#include "editor_node.h"
-
-bool MultiNodeEdit::_set(const StringName& p_name, const Variant& p_value){
-
- Node *es = EditorNode::get_singleton()->get_edited_scene();
- if (!es)
- return false;
-
- String name = p_name;
-
- if (name=="scripts/script") { // script/script set is intercepted at object level (check Variant Object::get() ) ,so use a different name
- name="script/script";
- }
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
-
- ur->create_action(TTR("MultiNode Set")+" "+String(name));
- for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
-
- if (!es->has_node(E->get()))
- continue;
-
- Node*n=es->get_node(E->get());
- if (!n)
- continue;
-
- if (p_value.get_type() == Variant::NODE_PATH) {
- Node *tonode = n->get_node(p_value);
- NodePath p_path = n->get_path_to(tonode);
- ur->add_do_property(n,name,p_path);
- } else {
- ur->add_do_property(n,name,p_value);
- }
-
- ur->add_undo_property(n,name,n->get(name));
-
-
- }
- ur->add_do_method(EditorNode::get_singleton()->get_property_editor(),"refresh");
- ur->add_undo_method(EditorNode::get_singleton()->get_property_editor(),"refresh");
-
- ur->commit_action();
- return true;
-}
-
-bool MultiNodeEdit::_get(const StringName& p_name,Variant &r_ret) const {
-
- Node *es = EditorNode::get_singleton()->get_edited_scene();
- if (!es)
- return false;
-
- String name=p_name;
- if (name=="scripts/script") { // script/script set is intercepted at object level (check Variant Object::get() ) ,so use a different name
- name="script/script";
- }
-
- for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
-
- if (!es->has_node(E->get()))
- continue;
-
- const Node*n=es->get_node(E->get());
- if (!n)
- continue;
-
- bool found;
- r_ret=n->get(name,&found);
- if (found)
- return true;
-
- }
-
- return false;
-}
-
-void MultiNodeEdit::_get_property_list( List<PropertyInfo> *p_list) const{
-
- HashMap<String,PLData> usage;
-
- Node *es = EditorNode::get_singleton()->get_edited_scene();
- if (!es)
- return;
-
- int nc=0;
-
- List<PLData*> datas;
-
- for (const List<NodePath>::Element *E=nodes.front();E;E=E->next()) {
-
- if (!es->has_node(E->get()))
- continue;
-
- Node*n=es->get_node(E->get());
- if (!n)
- continue;
-
- List<PropertyInfo> plist;
- n->get_property_list(&plist,true);
-
- for(List<PropertyInfo>::Element *F=plist.front();F;F=F->next()) {
-
- if (F->get().name=="script/script")
- continue; //added later manually, since this is intercepted before being set (check Variant Object::get() )
- if (!usage.has(F->get().name)) {
- PLData pld;
- pld.uses=0;
- pld.info=F->get();
- usage[F->get().name]=pld;
- datas.push_back(usage.getptr(F->get().name));
- }
-
- usage[F->get().name].uses++;
- }
-
- nc++;
- }
-
- for (List<PLData*>::Element *E=datas.front();E;E=E->next()) {
-
- if (nc==E->get()->uses) {
- p_list->push_back(E->get()->info);
- }
- }
-
- p_list->push_back(PropertyInfo(Variant::OBJECT,"scripts/script",PROPERTY_HINT_RESOURCE_TYPE,"Script"));
-
-
-}
-
-void MultiNodeEdit::clear_nodes() {
-
- nodes.clear();
-}
-
-void MultiNodeEdit::add_node(const NodePath& p_node){
-
- nodes.push_back(p_node);
-}
-
-MultiNodeEdit::MultiNodeEdit()
-{
-}
diff --git a/tools/editor/multi_node_edit.h b/tools/editor/multi_node_edit.h
deleted file mode 100644
index 290c529d48..0000000000
--- a/tools/editor/multi_node_edit.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*************************************************************************/
-/* multi_node_edit.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 MULTI_NODE_EDIT_H
-#define MULTI_NODE_EDIT_H
-
-#include "scene/main/node.h"
-
-class MultiNodeEdit : public Reference {
-
- GDCLASS(MultiNodeEdit,Reference);
-
- List<NodePath> nodes;
- struct PLData {
- int uses;
- PropertyInfo info;
- };
-
-
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
-public:
-
-
-
- void clear_nodes();
- void add_node(const NodePath& p_node);
-
- MultiNodeEdit();
-};
-
-#endif // MULTI_NODE_EDIT_H
diff --git a/tools/editor/node_dock.cpp b/tools/editor/node_dock.cpp
deleted file mode 100644
index 3d906cf960..0000000000
--- a/tools/editor/node_dock.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*************************************************************************/
-/* node_dock.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "node_dock.h"
-
-#include "editor_node.h"
-
-void NodeDock::show_groups() {
-
- groups_button->set_pressed(true);
- connections_button->set_pressed(false);
- groups->show();
- connections->hide();
-}
-
-void NodeDock::show_connections(){
-
- groups_button->set_pressed(false);
- connections_button->set_pressed(true);
- groups->hide();
- connections->show();
-}
-
-
-void NodeDock::_bind_methods() {
-
- ClassDB::bind_method(_MD("show_groups"),&NodeDock::show_groups);
- ClassDB::bind_method(_MD("show_connections"),&NodeDock::show_connections);
-}
-
-void NodeDock::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- connections_button->set_icon(get_icon("Connect","EditorIcons"));
- groups_button->set_icon(get_icon("Groups","EditorIcons"));
- }
-}
-
-NodeDock *NodeDock::singleton=NULL;
-
-void NodeDock::set_node(Node* p_node) {
-
- connections->set_node(p_node);
- groups->set_current(p_node);
-
- if (p_node) {
- if (connections_button->is_pressed())
- connections->show();
- else
- groups->show();
-
- mode_hb->show();
- select_a_node->hide();
- } else {
- connections->hide();
- groups->hide();
- mode_hb->hide();
- select_a_node->show();
- }
-}
-
-NodeDock::NodeDock()
-{
- singleton=this;
-
- set_name(TTR("Node"));
- mode_hb = memnew( HBoxContainer );
- add_child(mode_hb);
- mode_hb->hide();
-
-
- connections_button = memnew( ToolButton );
- connections_button->set_text(TTR("Signals"));
- connections_button->set_toggle_mode(true);
- connections_button->set_pressed(true);
- connections_button->set_h_size_flags(SIZE_EXPAND_FILL);
- mode_hb->add_child(connections_button);
- connections_button->connect("pressed",this,"show_connections");
-
- groups_button = memnew( ToolButton );
- groups_button->set_text(TTR("Groups"));
- groups_button->set_toggle_mode(true);
- groups_button->set_pressed(false);
- groups_button->set_h_size_flags(SIZE_EXPAND_FILL);
- mode_hb->add_child(groups_button);
- groups_button->connect("pressed",this,"show_groups");
-
- connections = memnew( ConnectionsDock(EditorNode::get_singleton()) );
- connections->set_undoredo(EditorNode::get_singleton()->get_undo_redo());
- add_child(connections);
- connections->set_v_size_flags(SIZE_EXPAND_FILL);
- connections->hide();
-
- groups = memnew( GroupsEditor );
- groups->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
- add_child(groups);
- groups->set_v_size_flags(SIZE_EXPAND_FILL);
- groups->hide();
-
- select_a_node = memnew( Label );
- select_a_node->set_text(TTR("Select a Node to edit Signals and Groups."));
- select_a_node->set_v_size_flags(SIZE_EXPAND_FILL);
- select_a_node->set_valign(Label::VALIGN_CENTER);
- select_a_node->set_align(Label::ALIGN_CENTER);
- select_a_node->set_autowrap(true);
- add_child(select_a_node);
-
-}
diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp
deleted file mode 100644
index f10526fb77..0000000000
--- a/tools/editor/plugins/animation_player_editor_plugin.cpp
+++ /dev/null
@@ -1,1604 +0,0 @@
-/*************************************************************************/
-/* animation_player_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "animation_player_editor_plugin.h"
-
-#include "globals.h"
-#include "io/resource_loader.h"
-#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;
-
- set_process(false);
-
- key_editor->set_animation(Ref<Animation>());
- key_editor->set_root(NULL);
- key_editor->show_select_node_warning(true);
- _update_player();
- //editor->animation_editor_make_visible(false);
-
- }
-}
-
-void AnimationPlayerEditor::_gui_input(InputEvent p_event) {
-
-
-}
-
-void AnimationPlayerEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_PROCESS) {
-
- if (!player)
- return;
-
- updating = true;
-
- if (player->is_playing()) {
-
- {
- String animname=player->get_current_animation();
-
- if (player->has_animation(animname)) {
- Ref<Animation> anim = player->get_animation(animname);
- if (!anim.is_null()) {
-
- frame->set_max(anim->get_length());
- }
- }
- }
- frame->set_value(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
-
- frame->set_value(player->get_current_animation_pos());
- }
-
- last_active=player->is_playing();
- //seek->set_val(player->get_pos());
- updating = false;
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- //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") );
- autoplay->set_icon( get_icon("AutoPlay","EditorIcons") );
- load_anim->set_icon( get_icon("Folder","EditorIcons") );
- save_anim->set_icon(get_icon("Save", "EditorIcons"));
- save_anim->get_popup()->connect("id_pressed", this, "_animation_save_menu");
- remove_anim->set_icon( get_icon("Remove","EditorIcons") );
-
- blend_anim->set_icon( get_icon("Blend","EditorIcons") );
- play->set_icon( get_icon("PlayStart","EditorIcons") );
- play_from->set_icon( get_icon("Play","EditorIcons") );
- play_bw->set_icon( get_icon("PlayStartBackwards","EditorIcons") );
- play_bw_from->set_icon( get_icon("PlayBackwards","EditorIcons") );
-
- autoplay_icon=get_icon("AutoPlay","EditorIcons");
- stop->set_icon( get_icon("Stop","EditorIcons") );
- resource_edit_anim->set_icon( get_icon("EditResource","EditorIcons") );
- pin->set_icon(get_icon("Pin","EditorIcons") );
- tool_anim->set_icon(get_icon("Tools","EditorIcons"));
- tool_anim->get_popup()->connect("id_pressed",this,"_animation_tool_menu");
-
- blend_editor.next->connect("item_selected", 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"));
- anim_editor_load->set_pressed_texture( get_icon("AnimGet","EditorIcons"));
- anim_editor_store->set_pressed_texture( get_icon("AnimSet","EditorIcons"));
- anim_editor_load->set_hover_texture( get_icon("AnimGetHl","EditorIcons"));
- anim_editor_store->set_hover_texture( get_icon("AnimSetHl","EditorIcons"));
-*/
-
- get_tree()->connect("node_removed",this,"_node_removed");
- }
-}
-
-void AnimationPlayerEditor::_autoplay_pressed() {
-
- if (updating)
- return;
- if (animation->get_item_count()==0) {
- return;
- }
-
- String current = animation->get_item_text( animation->get_selected() );
- if (player->get_autoplay()==current) {
- //unset
- undo_redo->create_action(TTR("Toggle Autoplay"));
- undo_redo->add_do_method(player,"set_autoplay","");
- undo_redo->add_undo_method(player,"set_autoplay",player->get_autoplay());
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
-
-
- } else {
- //set
- undo_redo->create_action(TTR("Toggle Autoplay"));
- undo_redo->add_do_method(player,"set_autoplay",current);
- undo_redo->add_undo_method(player,"set_autoplay",player->get_autoplay());
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
- }
-
-}
-
-void AnimationPlayerEditor::_play_pressed() {
-
- String current;
- if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
-
- current = animation->get_item_text( animation->get_selected() );
- }
-
- if (current!="") {
-
- if (current==player->get_current_animation())
- player->stop(); //so it wont blend with itself
- player->play(current );
- }
-
- //unstop
- stop->set_pressed(false);
- //unpause
- //pause->set_pressed(false);
-}
-
-void AnimationPlayerEditor::_play_from_pressed() {
-
- String current;
- if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
-
- current = animation->get_item_text( animation->get_selected() );
- }
-
- if (current!="") {
-
- float time = player->get_current_animation_pos();
-
- if (current==player->get_current_animation() && player->is_playing()) {
-
- player->stop(); //so it wont blend with itself
- }
-
- player->play( current );
- player->seek(time);
- }
-
- //unstop
- stop->set_pressed(false);
- //unpause
- //pause->set_pressed(false);
-}
-
-
-void AnimationPlayerEditor::_play_bw_pressed() {
-
- String current;
- if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
-
- current = animation->get_item_text( animation->get_selected() );
- }
-
- if (current!="") {
-
- if (current==player->get_current_animation())
- player->stop(); //so it wont blend with itself
- player->play(current,-1,-1,true);
- }
-
- //unstop
- stop->set_pressed(false);
- //unpause
- //pause->set_pressed(false);
-}
-
-void AnimationPlayerEditor::_play_bw_from_pressed() {
-
- String current;
- if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
-
- current = animation->get_item_text( animation->get_selected() );
- }
-
- if (current!="") {
-
- float time = player->get_current_animation_pos();
- if (current==player->get_current_animation())
- player->stop(); //so it wont blend with itself
-
- player->play(current,-1,-1,true);
- player->seek(time);
- }
-
- //unstop
- stop->set_pressed(false);
- //unpause
- //pause->set_pressed(false);
-}
-void AnimationPlayerEditor::_stop_pressed() {
-
- player->stop(false);
- play->set_pressed(false);
- stop->set_pressed(true);
- //pause->set_pressed(false);
- //player->set_pause(false);
-}
-
-void AnimationPlayerEditor::_pause_pressed() {
-
- //player->set_pause( pause->is_pressed() );
-}
-void AnimationPlayerEditor::_animation_selected(int p_which) {
-
- if (updating)
- return;
- // when selecting an animation, the idea is that the only interesting behavior
- // ui-wise is that it should play/blend the next one if currently playing
- String current;
- if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) {
-
- current = animation->get_item_text( animation->get_selected() );
- }
-
- if (current!="") {
-
-
- player->set_current_animation( current );
-
- 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);
- }
- }
- frame->set_max(anim->get_length());
- if (anim->get_step())
- frame->set_step(anim->get_step());
- else
- frame->set_step(0.00001);
-
-
-
- } else {
- key_editor->set_animation(Ref<Animation>());
- key_editor->set_root(NULL);
-
- }
-
-
- autoplay->set_pressed(current==player->get_autoplay());
-}
-
-void AnimationPlayerEditor::_animation_new() {
-
- renaming=false;
- name_title->set_text(TTR("New Animation Name:"));
-
- int count=1;
- String base=TTR("New Anim");
- while(true) {
- String attempt = base;
- if (count>1)
- attempt+=" ("+itos(count)+")";
- if (player->has_animation(attempt)) {
- count++;
- continue;
- }
- base=attempt;
- break;
- }
-
- name->set_text(base);
- name_dialog->popup_centered(Size2(300,90));
- name->select_all();
- name->grab_focus();
-}
-void AnimationPlayerEditor::_animation_rename() {
-
- if (animation->get_item_count()==0)
- return;
- int selected = animation->get_selected();
- String selected_name = animation->get_item_text(selected);
-
- name_title->set_text(TTR("Change Animation Name:"));
- name->set_text(selected_name);
- renaming=true;
- name_dialog->popup_centered(Size2(300,90));
- name->select_all();
- name->grab_focus();
-
-}
-void AnimationPlayerEditor::_animation_load() {
- ERR_FAIL_COND(!player);
- file->set_mode( EditorFileDialog::MODE_OPEN_FILE );
- file->clear_filters();
- List<String> extensions;
-
- ResourceLoader::get_recognized_extensions_for_type("Animation",&extensions);
- for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- file->add_filter("*."+E->get()+" ; "+E->get().to_upper() );
-
- }
-
- file->popup_centered_ratio();
- current_option = RESOURCE_LOAD;
-}
-
-
-void AnimationPlayerEditor::_animation_save_in_path(const Ref<Resource>& p_resource, const String& p_path) {
-
- int flg = 0;
- if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
- flg |= ResourceSaver::FLAG_COMPRESS;
- /*
- if (EditorSettings::get_singleton()->get("filesystem/on_save/save_paths_as_relative"))
- flg |= ResourceSaver::FLAG_RELATIVE_PATHS;
- */
-
- String path = GlobalConfig::get_singleton()->localize_path(p_path);
- Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
-
- if (err != OK) {
- accept->set_text(TTR("Error saving resource!"));
- accept->popup_centered_minsize();
- return;
- }
- //EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
-
- ((Resource*)p_resource.ptr())->set_path(path);
- editor->emit_signal("resource_saved", p_resource);
-
-}
-
-void AnimationPlayerEditor::_animation_save(const Ref<Resource>& p_resource) {
-
- if (p_resource->get_path().is_resource_file()) {
- _animation_save_in_path(p_resource, p_resource->get_path());
- }
- else {
- _animation_save_as(p_resource);
- }
-}
-
-void AnimationPlayerEditor::_animation_save_as(const Ref<Resource>& p_resource) {
-
- file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
-
- List<String> extensions;
- ResourceSaver::get_recognized_extensions(p_resource, &extensions);
- file->clear_filters();
- for (int i = 0; i<extensions.size(); i++) {
-
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
- }
-
- //file->set_current_path(current_path);
- if (p_resource->get_path() != "") {
- file->set_current_path(p_resource->get_path());
- if (extensions.size()) {
- String ext = p_resource->get_path().get_extension().to_lower();
- if (extensions.find(ext) == NULL) {
- file->set_current_path(p_resource->get_path().replacen("." + ext, "." + extensions.front()->get()));
- }
- }
- }
- else {
-
- String existing;
- if (extensions.size()) {
- if( p_resource->get_name() != "" ) {
- existing = p_resource->get_name() + "." + extensions.front()->get().to_lower();
- }
- else {
- existing = "new_" + p_resource->get_class().to_lower() + "." + extensions.front()->get().to_lower();
- }
- }
- file->set_current_path(existing);
-
- }
- file->popup_centered_ratio();
- file->set_title(TTR("Save Resource As.."));
- current_option = RESOURCE_SAVE;
-}
-
-void AnimationPlayerEditor::_animation_remove() {
-
- if (animation->get_item_count() == 0)
- return;
-
- delete_dialog->set_text(TTR("Delete Animation?"));
- delete_dialog->popup_centered_minsize();
-}
-
-void AnimationPlayerEditor::_animation_remove_confirmed() {
-
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
-
- undo_redo->create_action(TTR("Remove Animation"));
- undo_redo->add_do_method(player, "remove_animation", current);
- undo_redo->add_undo_method(player, "add_animation", current, anim);
- undo_redo->add_do_method(this, "_animation_player_changed", player);
- undo_redo->add_undo_method(this, "_animation_player_changed", player);
- undo_redo->commit_action();
-}
-
-void AnimationPlayerEditor::_select_anim_by_name(const String& p_anim) {
-
- int idx=-1;
- for(int i=0;i<animation->get_item_count();i++) {
-
- if (animation->get_item_text(i)==p_anim) {
-
- idx=i;
- break;
- }
- }
-
- ERR_FAIL_COND(idx==-1);
-
-
- animation->select(idx);
-
- _animation_selected(idx);
-
-}
-
-void AnimationPlayerEditor::_animation_name_edited() {
-
- player->stop();
-
- String new_name = name->get_text();
- if (new_name=="" || new_name.find(":")!=-1 || new_name.find("/")!=-1) {
- error_dialog->set_text(TTR("ERROR: Invalid animation name!"));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (renaming && animation->get_item_count()>0 && animation->get_item_text(animation->get_selected())==new_name) {
- name_dialog->hide();
- return;
- }
-
- if (player->has_animation(new_name)) {
- error_dialog->set_text(TTR("ERROR: Animation name already exists!"));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- if (renaming) {
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
-
- undo_redo->create_action(TTR("Rename Animation"));
- undo_redo->add_do_method(player,"rename_animation",current,new_name);
- undo_redo->add_do_method(anim.ptr(),"set_name",new_name);
- undo_redo->add_undo_method(player,"rename_animation",new_name,current);
- undo_redo->add_undo_method(anim.ptr(),"set_name",current);
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
-
- _select_anim_by_name(new_name);
-
- } else {
-
- Ref<Animation> new_anim = Ref<Animation>(memnew( Animation ));
- new_anim->set_name(new_name);
-
- undo_redo->create_action(TTR("Add Animation"));
- undo_redo->add_do_method(player,"add_animation",new_name,new_anim);
- undo_redo->add_undo_method(player,"remove_animation",new_name);
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
-
- _select_anim_by_name(new_name);
-
- }
-
- name_dialog->hide();
-}
-
-
-void AnimationPlayerEditor::_blend_editor_next_changed(const int p_idx) {
-
- if (animation->get_item_count()==0)
- return;
-
- String current = animation->get_item_text(animation->get_selected());
-
- undo_redo->create_action(TTR("Blend Next Changed"));
- undo_redo->add_do_method(player,"animation_set_next",current,blend_editor.next->get_item_text(p_idx));
- undo_redo->add_undo_method(player,"animation_set_next",current,player->animation_get_next(current));
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
-}
-
-void AnimationPlayerEditor::_animation_blend() {
-
- if (updating_blends)
- return;
-
- blend_editor.tree->clear();
-
- if (animation->get_item_count()==0)
- return;
-
- String current = animation->get_item_text(animation->get_selected());
-
- blend_editor.dialog->popup_centered(Size2(400,400));
-
- blend_editor.tree->set_hide_root(true);
- blend_editor.tree->set_column_min_width(0,10);
- blend_editor.tree->set_column_min_width(1,3);
-
- List<StringName> anims;
- player->get_animation_list(&anims);
- TreeItem *root = blend_editor.tree->create_item();
- updating_blends=true;
-
- int i = 0;
- bool anim_found = false;
- blend_editor.next->clear();
- blend_editor.next->add_item("", i);
-
- for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
-
- String to=E->get();
- TreeItem *blend=blend_editor.tree->create_item(root);
- blend->set_editable(0,false);
- blend->set_editable(1,true);
- blend->set_text(0,to);
- blend->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- blend->set_range_config(1,0,3600,0.001);
- blend->set_range(1,player->get_blend_time(current,to));
-
- i++;
- blend_editor.next->add_item(to, i);
- if (to == player->animation_get_next(current)) {
- blend_editor.next->select(i);
- anim_found = true;
- }
- }
-
- // make sure we reset it else it becomes out of sync and could contain a deleted animation
- if (!anim_found) {
- blend_editor.next->select(0);
- player->animation_set_next(current, blend_editor.next->get_item_text(0));
- }
-
- updating_blends=false;
-}
-
-void AnimationPlayerEditor::_blend_edited() {
-
- if (updating_blends)
- return;
-
- if (animation->get_item_count()==0)
- return;
-
- String current = animation->get_item_text(animation->get_selected());
-
- TreeItem *selected = blend_editor.tree->get_edited();
- if (!selected)
- return;
-
- updating_blends=true;
- String to=selected->get_text(0);
- float blend_time = selected->get_range(1);
- float prev_blend_time = player->get_blend_time(current,to);
-
- undo_redo->create_action(TTR("Change Blend Time"));
- undo_redo->add_do_method(player,"set_blend_time",current,to,blend_time);
- undo_redo->add_undo_method(player,"set_blend_time",current,to,prev_blend_time);
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
- updating_blends=false;
-}
-
-void AnimationPlayerEditor::ensure_visibility() {
-
- if (player && pin->is_pressed())
- return; // another player is pinned, don't reset
-
- _animation_edit();
-}
-
-Dictionary AnimationPlayerEditor::get_state() const {
-
-
- Dictionary d;
-
- d["visible"]=is_visible_in_tree();
- if (EditorNode::get_singleton()->get_edited_scene() && is_visible_in_tree() && player) {
- d["player"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(player);
- d["animation"]=player->get_current_animation();
-
- }
-
- return d;
-
-}
-void AnimationPlayerEditor::set_state(const Dictionary& p_state) {
-
- if (p_state.has("visible") && p_state["visible"]) {
-
- if (!EditorNode::get_singleton()->get_edited_scene())
- return;
-
- Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]);
- if (n && n->cast_to<AnimationPlayer>() && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) {
- player=n->cast_to<AnimationPlayer>();
- _update_player();
- show();
- set_process(true);
- ensure_visibility();
- //EditorNode::get_singleton()->animation_panel_make_visible(true);
-
- if (p_state.has("animation")) {
- String anim = p_state["animation"];
- _select_anim_by_name(anim);
- _animation_edit();
- }
-
- }
- }
-
-}
-
-
-void AnimationPlayerEditor::_animation_resource_edit() {
-
- if (animation->get_item_count()) {
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
- editor->edit_resource(anim);
- }
-
-}
-
-void AnimationPlayerEditor::_animation_edit() {
-
- 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 {
-
- key_editor->set_animation(Ref<Animation>());
- key_editor->set_root(NULL);
-
- }
-
-}
-void AnimationPlayerEditor::_dialog_action(String p_file) {
-
- switch (current_option) {
- case RESOURCE_LOAD: {
- ERR_FAIL_COND(!player);
-
- Ref<Resource> res = ResourceLoader::load(p_file, "Animation");
- ERR_FAIL_COND(res.is_null());
- ERR_FAIL_COND(!res->is_class("Animation"));
- if (p_file.find_last("/") != -1) {
-
- p_file = p_file.substr(p_file.find_last("/") + 1, p_file.length());
-
- }
- if (p_file.find_last("\\") != -1) {
-
- p_file = p_file.substr(p_file.find_last("\\") + 1, p_file.length());
-
- }
-
- if (p_file.find(".") != -1)
- p_file = p_file.substr(0, p_file.find("."));
-
- undo_redo->create_action(TTR("Load Animation"));
- undo_redo->add_do_method(player, "add_animation", p_file, res);
- undo_redo->add_undo_method(player, "remove_animation", p_file);
- if (player->has_animation(p_file)) {
- undo_redo->add_undo_method(player, "add_animation", p_file, player->get_animation(p_file));
-
- }
- undo_redo->add_do_method(this, "_animation_player_changed", player);
- undo_redo->add_undo_method(this, "_animation_player_changed", player);
- undo_redo->commit_action();
- break;
- }
- case RESOURCE_SAVE: {
-
- String current = animation->get_item_text(animation->get_selected());
- if (current != "") {
- Ref<Animation> anim = player->get_animation(current);
-
- ERR_FAIL_COND(!anim->cast_to<Resource>())
-
- RES current_res = RES(anim->cast_to<Resource>());
-
- _animation_save_in_path(current_res, p_file);
- }
- }
- }
-}
-
-void AnimationPlayerEditor::_scale_changed(const String& p_scale) {
-
- player->set_speed_scale(p_scale.to_double());
-}
-
-void AnimationPlayerEditor::_update_animation() {
-
- // the purpose of _update_animation is to reflect the current state
- // of the animation player in the current editor..
-
- updating=true;
-
-
- if (player->is_playing()) {
-
- play->set_pressed(true);
- stop->set_pressed(false);
-
- } else {
-
- play->set_pressed(false);
- stop->set_pressed(true);
- }
-
- scale->set_text( String::num(player->get_speed_scale(),2) );
- String current=player->get_current_animation();
-
- for (int i=0;i<animation->get_item_count();i++) {
-
- if (animation->get_item_text(i)==current) {
- animation->select(i);
- break;
- }
- }
-
- updating=false;
-}
-
-void AnimationPlayerEditor::_update_player() {
-
-
- updating=true;
- List<StringName> animlist;
- if (player)
- player->get_animation_list(&animlist);
-
- animation->clear();
- 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);
- play_bw_from->set_disabled(animlist.size()==0);
- play_from->set_disabled(animlist.size()==0);
- autoplay->set_disabled(animlist.size()==0);
- duplicate_anim->set_disabled(animlist.size()==0);
- rename_anim->set_disabled(animlist.size()==0);
- blend_anim->set_disabled(animlist.size()==0);
- remove_anim->set_disabled(animlist.size()==0);
- resource_edit_anim->set_disabled(animlist.size()==0);
- save_anim->set_disabled(animlist.size() == 0);
- tool_anim->set_disabled(player==NULL);
-
-
- int active_idx=-1;
- for (List<StringName>::Element *E=animlist.front();E;E=E->next()) {
-
- if (player->get_autoplay()==E->get())
- animation->add_icon_item(autoplay_icon,E->get());
- else
- animation->add_item(E->get());
-
- if (player->get_current_animation()==E->get())
- active_idx=animation->get_item_count()-1;
-
- }
-
- if (!player)
- return;
-
- updating=false;
- if (active_idx!=-1) {
- animation->select(active_idx);
- autoplay->set_pressed(animation->get_item_text(active_idx)==player->get_autoplay());
- _animation_selected(active_idx);
-
- } else if (animation->get_item_count()>0){
-
- animation->select(0);
- autoplay->set_pressed(animation->get_item_text(0)==player->get_autoplay());
- _animation_selected(0);
- }
-
- //pause->set_pressed(player->is_paused());
-
-
- 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);
- }
-
- }
-
- _update_animation();
-}
-
-
-
-void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
-
-
- if (player && pin->is_pressed())
- return; //ignore, pinned
- player=p_player;
-
- if (player) {
- _update_player();
- key_editor->show_select_node_warning(false);
- } else {
- key_editor->show_select_node_warning(true);
-
- //hide();
-
- }
-
-}
-
-
-void AnimationPlayerEditor::_animation_duplicate() {
-
-
- if (!animation->get_item_count())
- return;
-
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
- if (!anim.is_valid())
- return;
-
- Ref<Animation> new_anim = memnew( Animation );
- List<PropertyInfo> plist;
- anim->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
-
- if (E->get().usage&PROPERTY_USAGE_STORAGE) {
-
- new_anim->set(E->get().name, anim->get(E->get().name));
- }
- }
- new_anim->set_path("");
-
- String new_name = current;
- while(player->has_animation(new_name)) {
-
- new_name=new_name+" (copy)";
- }
-
-
- undo_redo->create_action(TTR("Duplicate Animation"));
- undo_redo->add_do_method(player,"add_animation",new_name,new_anim);
- undo_redo->add_undo_method(player,"remove_animation",new_name);
- undo_redo->add_do_method(player,"animation_set_next",new_name,player->animation_get_next(current));
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
-
-
- for(int i=0;i<animation->get_item_count();i++) {
-
- if (animation->get_item_text(i)==new_name) {
-
- animation->select(i);
- _animation_selected(i);
- return;
- }
- }
-
-}
-
-void AnimationPlayerEditor::_seek_value_changed(float p_value,bool p_set) {
-
- if (updating || !player || player->is_playing()) {
- return;
- };
-
-
- updating=true;
- String current=player->get_current_animation(); //animation->get_item_text( animation->get_selected() );
- if (current == "" || !player->has_animation(current)) {
- updating=false;
- current="";
- return;
- };
-
- Ref<Animation> anim;
- anim=player->get_animation(current);
-
- float pos = anim->get_length() * (p_value / frame->get_max());
- float step = anim->get_step();
- if (step) {
- pos=Math::stepify(pos, step);
- if (pos<0)
- pos=0;
- if (pos>=anim->get_length())
- pos=anim->get_length();
- }
-
- if (player->is_valid() && !p_set) {
- float cpos = player->get_current_animation_pos();
-
- player->seek_delta(pos,pos-cpos);
- } else {
- player->seek(pos,true);
- }
-
-
- key_editor->set_anim_pos(pos);
-
- updating=true;
-};
-
-void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) {
-
- if (player==p_pl && is_visible_in_tree()) {
-
- _update_player();
- if (blend_editor.dialog->is_visible_in_tree())
- _animation_blend(); //update
- }
-}
-
-
-
-void AnimationPlayerEditor::_list_changed() {
-
- if(is_visible_in_tree())
- _update_player();
-}
-#if 0
-void AnimationPlayerEditor::_editor_store() {
-
- if (animation->get_item_count()==0)
- return;
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
-
- if (key_editor->get_current_animation()==anim)
- return; //already there
-
-
- undo_redo->create_action("Store anim in editor");
- 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 = key_editor->get_current_animation();
- if (anim.is_null())
- return;
-
- String existing = player->find_animation(anim);
- if (existing!="") {
- _select_anim_by_name(existing);
- return; //already has
- }
-
- int count=1;
- String base=anim->get_name();
- bool noname=false;
- if (base=="") {
- base="New Anim";
- noname=true;
- }
-
- while(true) {
- String attempt = base;
- if (count>1)
- attempt+=" ("+itos(count)+")";
- if (player->has_animation(attempt)) {
- count++;
- continue;
- }
- base=attempt;
- break;
- }
-
- if (noname)
- anim->set_name(base);
-
- undo_redo->create_action("Add Animation From Editor");
- undo_redo->add_do_method(player,"add_animation",base,anim);
- undo_redo->add_undo_method(player,"remove_animation",base);
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
-
- _select_anim_by_name(base);
-
-
-}
-#endif
-
-void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float 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);
-
-}
-
-
-void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos,bool p_drag) {
-
- if (!is_visible_in_tree())
- return;
- if (!player)
- return;
-
- if (player->is_playing() )
- return;
-
- updating=true;
- frame->set_value(p_pos);
- updating=false;
- _seek_value_changed(p_pos,!p_drag);
-
- EditorNode::get_singleton()->get_property_editor()->refresh();
-
-
-
- //seekit
-}
-
-void AnimationPlayerEditor::_hide_anim_editors() {
-
- player=NULL;
- hide();
- set_process(false);
-
- key_editor->set_animation(Ref<Animation>());
- key_editor->set_root(NULL);
- key_editor->show_select_node_warning(true);
- //editor->animation_editor_make_visible(false);
-
-}
-
-
-void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
-
- switch(p_option) {
-
- case TOOL_COPY_ANIM: {
-
- if (!animation->get_item_count()) {
- error_dialog->set_text(TTR("ERROR: No animation to copy!"));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
- //editor->edit_resource(anim);
- EditorSettings::get_singleton()->set_resource_clipboard(anim);
-
- } break;
- case TOOL_PASTE_ANIM: {
-
- Ref<Animation> anim = EditorSettings::get_singleton()->get_resource_clipboard();
- if (!anim.is_valid()) {
- error_dialog->set_text(TTR("ERROR: No animation resource on clipboard!"));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- String name = anim->get_name();
- if (name=="") {
- name=TTR("Pasted Animation");
- }
-
- int idx=1;
- String base = name;
- while (player->has_animation(name)) {
-
- idx++;
- name=base+" "+itos(idx);
- }
-
- undo_redo->create_action(TTR("Paste Animation"));
- undo_redo->add_do_method(player,"add_animation",name,anim);
- undo_redo->add_undo_method(player,"remove_animation",name);
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
-
- _select_anim_by_name(name);
-
-
- } break;
- case TOOL_EDIT_RESOURCE: {
-
- if (!animation->get_item_count()) {
- error_dialog->set_text(TTR("ERROR: No animation to edit!"));
- error_dialog->popup_centered_minsize();
- return;
- }
-
- String current = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim = player->get_animation(current);
- editor->edit_resource(anim);
-
- } break;
-
- }
-}
-
-void AnimationPlayerEditor::_animation_save_menu(int p_option) {
-
- String current = animation->get_item_text(animation->get_selected());
- if (current != "") {
- Ref<Animation> anim = player->get_animation(current);
-
- switch (p_option) {
- case ANIM_SAVE:
- _animation_save(anim);
- break;
- case ANIM_SAVE_AS:
- _animation_save_as(anim);
- break;
- }
- }
-}
-
-void AnimationPlayerEditor::_unhandled_key_input(const InputEvent& p_ev) {
-
- if (is_visible_in_tree() && p_ev.type==InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) {
-
- switch(p_ev.key.scancode) {
-
- case KEY_A: {
- if (!p_ev.key.mod.shift)
- _play_bw_from_pressed();
- else
- _play_bw_pressed();
- } break;
- case KEY_S: {
- _stop_pressed();
- } break;
- case KEY_D: {
- if (!p_ev.key.mod.shift)
- _play_from_pressed();
- else
- _play_pressed();
- } break;
- }
- }
-}
-
-void AnimationPlayerEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&AnimationPlayerEditor::_gui_input);
- ClassDB::bind_method(_MD("_node_removed"),&AnimationPlayerEditor::_node_removed);
- ClassDB::bind_method(_MD("_play_pressed"),&AnimationPlayerEditor::_play_pressed);
- ClassDB::bind_method(_MD("_play_from_pressed"),&AnimationPlayerEditor::_play_from_pressed);
- ClassDB::bind_method(_MD("_play_bw_pressed"),&AnimationPlayerEditor::_play_bw_pressed);
- ClassDB::bind_method(_MD("_play_bw_from_pressed"),&AnimationPlayerEditor::_play_bw_from_pressed);
- ClassDB::bind_method(_MD("_stop_pressed"),&AnimationPlayerEditor::_stop_pressed);
- ClassDB::bind_method(_MD("_autoplay_pressed"),&AnimationPlayerEditor::_autoplay_pressed);
- ClassDB::bind_method(_MD("_pause_pressed"),&AnimationPlayerEditor::_pause_pressed);
- ClassDB::bind_method(_MD("_animation_selected"),&AnimationPlayerEditor::_animation_selected);
- ClassDB::bind_method(_MD("_animation_name_edited"),&AnimationPlayerEditor::_animation_name_edited);
- ClassDB::bind_method(_MD("_animation_new"),&AnimationPlayerEditor::_animation_new);
- ClassDB::bind_method(_MD("_animation_rename"),&AnimationPlayerEditor::_animation_rename);
- ClassDB::bind_method(_MD("_animation_load"),&AnimationPlayerEditor::_animation_load);
- ClassDB::bind_method(_MD("_animation_remove"),&AnimationPlayerEditor::_animation_remove);
- ClassDB::bind_method(_MD("_animation_remove_confirmed"),&AnimationPlayerEditor::_animation_remove_confirmed);
- ClassDB::bind_method(_MD("_animation_blend"),&AnimationPlayerEditor::_animation_blend);
- ClassDB::bind_method(_MD("_animation_edit"),&AnimationPlayerEditor::_animation_edit);
- ClassDB::bind_method(_MD("_animation_resource_edit"),&AnimationPlayerEditor::_animation_resource_edit);
- ClassDB::bind_method(_MD("_dialog_action"),&AnimationPlayerEditor::_dialog_action);
- ClassDB::bind_method(_MD("_seek_value_changed"),&AnimationPlayerEditor::_seek_value_changed,DEFVAL(true));
- ClassDB::bind_method(_MD("_animation_player_changed"),&AnimationPlayerEditor::_animation_player_changed);
- ClassDB::bind_method(_MD("_blend_edited"),&AnimationPlayerEditor::_blend_edited);
- //ClassDB::bind_method(_MD("_seek_frame_changed"),&AnimationPlayerEditor::_seek_frame_changed);
- ClassDB::bind_method(_MD("_scale_changed"),&AnimationPlayerEditor::_scale_changed);
- //ClassDB::bind_method(_MD("_editor_store_all"),&AnimationPlayerEditor::_editor_store_all);
- ///jectTypeDB::bind_method(_MD("_editor_load_all"),&AnimationPlayerEditor::_editor_load_all);
- ClassDB::bind_method(_MD("_list_changed"),&AnimationPlayerEditor::_list_changed);
- ClassDB::bind_method(_MD("_animation_key_editor_seek"),&AnimationPlayerEditor::_animation_key_editor_seek);
- ClassDB::bind_method(_MD("_animation_key_editor_anim_len_changed"),&AnimationPlayerEditor::_animation_key_editor_anim_len_changed);
- ClassDB::bind_method(_MD("_animation_key_editor_anim_step_changed"),&AnimationPlayerEditor::_animation_key_editor_anim_step_changed);
- ClassDB::bind_method(_MD("_hide_anim_editors"),&AnimationPlayerEditor::_hide_anim_editors);
- ClassDB::bind_method(_MD("_animation_duplicate"),&AnimationPlayerEditor::_animation_duplicate);
- ClassDB::bind_method(_MD("_blend_editor_next_changed"),&AnimationPlayerEditor::_blend_editor_next_changed);
- ClassDB::bind_method(_MD("_unhandled_key_input"),&AnimationPlayerEditor::_unhandled_key_input);
- ClassDB::bind_method(_MD("_animation_tool_menu"),&AnimationPlayerEditor::_animation_tool_menu);
- ClassDB::bind_method(_MD("_animation_save_menu"), &AnimationPlayerEditor::_animation_save_menu);
-
-
-
-
-}
-
-AnimationPlayerEditor *AnimationPlayerEditor::singleton=NULL;
-
-AnimationPlayer *AnimationPlayerEditor::get_player() const {
-
- return player;
-}
-AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
- editor=p_editor;
- singleton=this;
-
- updating=false;
-
- set_focus_mode(FOCUS_ALL);
-
- player=NULL;
- add_style_override("panel", get_stylebox("panel","Panel"));
-
-
- Label * l;
-
- /*l= memnew( Label );
- l->set_text("Animation Player:");
- add_child(l);*/
-
- HBoxContainer *hb = memnew( HBoxContainer );
- add_child(hb);
-
-
- play_bw_from = memnew( ToolButton );
- play_bw_from->set_tooltip(TTR("Play selected animation backwards from current pos. (A)"));
- hb->add_child(play_bw_from);
-
- play_bw = memnew( ToolButton );
- play_bw->set_tooltip(TTR("Play selected animation backwards from end. (Shift+A)"));
- hb->add_child(play_bw);
-
- stop = memnew( ToolButton );
- stop->set_toggle_mode(true);
- hb->add_child(stop);
- stop->set_tooltip(TTR("Stop animation playback. (S)"));
-
- play = memnew( ToolButton );
- play->set_tooltip(TTR("Play selected animation from start. (Shift+D)"));
- hb->add_child(play);
-
-
- play_from = memnew( ToolButton );
- play_from->set_tooltip(TTR("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(60,0));
- frame->set_stretch_ratio(2);
- frame->set_tooltip(TTR("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(TTR("Scale animation playback globally for the node."));
- scale->hide();
-
-
- add_anim = memnew( ToolButton );
- ED_SHORTCUT("animation_player_editor/add_animation", TTR("Create new animation in player."));
- add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/add_animation"));
- add_anim->set_tooltip(TTR("Create new animation in player."));
-
- hb->add_child(add_anim);
-
-
- load_anim = memnew( ToolButton );
- ED_SHORTCUT("animation_player_editor/load_from_disk", TTR("Load animation from disk."));
- add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/load_from_disk"));
- load_anim->set_tooltip(TTR("Load an animation from disk."));
- hb->add_child(load_anim);
-
- save_anim = memnew(MenuButton);
- save_anim->set_tooltip(TTR("Save the current animation"));
- save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save", TTR("Save")), ANIM_SAVE);
- save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_as", TTR("Save As")), ANIM_SAVE_AS);
- save_anim->set_focus_mode(Control::FOCUS_NONE);
- hb->add_child(save_anim);
-
- accept = memnew(AcceptDialog);
- add_child(accept);
- accept->connect("confirmed", this, "_menu_confirm_current");
-
- delete_dialog = memnew(ConfirmationDialog);
- add_child(delete_dialog);
- delete_dialog->connect("confirmed", this, "_animation_remove_confirmed");
-
- duplicate_anim = memnew( ToolButton );
- hb->add_child(duplicate_anim);
- ED_SHORTCUT("animation_player_editor/duplicate_animation", TTR("Duplicate Animation"));
- duplicate_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/duplicate_animation"));
- duplicate_anim->set_tooltip(TTR("Duplicate Animation"));
-
- rename_anim = memnew( ToolButton );
- hb->add_child(rename_anim);
- ED_SHORTCUT("animation_player_editor/rename_animation", TTR("Rename Animation"));
- rename_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/rename_animation"));
- rename_anim->set_tooltip(TTR("Rename Animation"));
-
- remove_anim = memnew( ToolButton );
- hb->add_child(remove_anim);
- ED_SHORTCUT("animation_player_editor/remove_animation", TTR("Remove Animation"));
- remove_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/remove_animation"));
- remove_anim->set_tooltip(TTR("Remove Animation"));
-
-
- animation = memnew( OptionButton );
- hb->add_child(animation);
- animation->set_h_size_flags(SIZE_EXPAND_FILL);
- animation->set_tooltip(TTR("Display list of animations in player."));
- animation->set_clip_text(true);
-
- autoplay = memnew( ToolButton );
- hb->add_child(autoplay);
- autoplay->set_tooltip(TTR("Autoplay on Load"));
-
-
-
- blend_anim = memnew( ToolButton );
- hb->add_child(blend_anim);
- blend_anim->set_tooltip(TTR("Edit Target Blend Times"));
-
- tool_anim = memnew( MenuButton);
- //tool_anim->set_flat(false);
- tool_anim->set_tooltip(TTR("Animation Tools"));
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/copy_animation", TTR("Copy Animation")),TOOL_COPY_ANIM);
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/paste_animation", TTR("Paste Animation")),TOOL_PASTE_ANIM);
- //tool_anim->get_popup()->add_separator();
- //tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM);
- hb->add_child(tool_anim);
-
- nodename = memnew( Button );
- hb->add_child(nodename);
- pin = memnew( ToolButton );
- pin->set_toggle_mode(true);
- hb->add_child(pin);
-
-
-
- resource_edit_anim= memnew( Button );
- hb->add_child(resource_edit_anim);
- resource_edit_anim->hide();
-
-
- file = memnew(EditorFileDialog);
- add_child(file);
-
- name_dialog = memnew( ConfirmationDialog );
- name_dialog->set_title(TTR("Create New Animation"));
- name_dialog->set_hide_on_ok(false);
- add_child(name_dialog);
- name = memnew( LineEdit );
- name_dialog->add_child(name);
- name->set_pos(Point2(18,30));
- name->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,10);
- name_dialog->register_text_enter(name);
-
-
- l = memnew( Label );
- l->set_text(TTR("Animation Name:"));
- l->set_pos( Point2(10,10) );
-
- name_dialog->add_child(l);
- name_title=l;
-
- error_dialog = memnew( ConfirmationDialog );
- error_dialog->get_ok()->set_text(TTR("Close"));
- //error_dialog->get_cancel()->set_text("Close");
- error_dialog->set_text(TTR("Error!"));
- add_child(error_dialog);
-
- name_dialog->connect("confirmed", this,"_animation_name_edited");
-
- blend_editor.dialog = memnew( AcceptDialog );
- add_child(blend_editor.dialog);
- blend_editor.dialog->get_ok()->set_text(TTR("Close"));
- blend_editor.dialog->set_hide_on_ok(true);
- VBoxContainer *blend_vb = memnew( VBoxContainer);
- blend_editor.dialog->add_child(blend_vb);
- //blend_editor.dialog->set_child_rect(blend_vb);
- blend_editor.tree = memnew( Tree );
- blend_editor.tree->set_columns(2);
- blend_vb->add_margin_child(TTR("Blend Times:"),blend_editor.tree,true);
- blend_editor.next = memnew( OptionButton );
- blend_vb->add_margin_child(TTR("Next (Auto Queue):"),blend_editor.next);
- blend_editor.dialog->set_title(TTR("Cross-Animation Blend Times"));
- updating_blends=false;
-
- blend_editor.tree->connect("item_edited",this,"_blend_edited");
-
-
- autoplay->connect("pressed", this,"_autoplay_pressed");
- autoplay->set_toggle_mode(true);
- play->connect("pressed", this,"_play_pressed");
- play_from->connect("pressed", this,"_play_from_pressed");
- play_bw->connect("pressed", this,"_play_bw_pressed");
- play_bw_from->connect("pressed", this,"_play_bw_from_pressed");
- stop->connect("pressed", this,"_stop_pressed");
- //pause->connect("pressed", this,"_pause_pressed");
- add_anim->connect("pressed", this,"_animation_new");
- rename_anim->connect("pressed", this,"_animation_rename");
- load_anim->connect("pressed", this,"_animation_load");
- duplicate_anim->connect("pressed", this,"_animation_duplicate");
- //frame->connect("text_entered", this,"_seek_frame_changed");
-
- 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");
- frame->connect("value_changed", this, "_seek_value_changed",Vector<Variant>(),true);
- scale->connect("text_entered", this, "_scale_changed",Vector<Variant>(),true);
-
-
-
- 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();
-}
-
-
-void AnimationPlayerEditorPlugin::edit(Object *p_object) {
-
- anim_editor->set_undo_redo(&get_undo_redo());
- if (!p_object)
- return;
- anim_editor->edit(p_object->cast_to<AnimationPlayer>());
-
-
-}
-
-bool AnimationPlayerEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("AnimationPlayer");
-}
-
-void AnimationPlayerEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- editor->make_bottom_panel_item_visible(anim_editor);
- anim_editor->set_process(true);
- anim_editor->ensure_visibility();
- //editor->animation_panel_make_visible(true);
- } else {
-
- //anim_editor->hide();
- //anim_editor->set_idle_process(false);
- }
-
-}
-
-AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- anim_editor = memnew( AnimationPlayerEditor(editor) );
- anim_editor->set_undo_redo(editor->get_undo_redo());
-
- editor->add_bottom_panel_item(TTR("Animation"),anim_editor);
- /*
- editor->get_viewport()->add_child(anim_editor);
- anim_editor->set_area_as_parent_rect();
- anim_editor->set_anchor( MARGIN_TOP, Control::ANCHOR_END);
- anim_editor->set_margin( MARGIN_TOP, 75 );
- anim_editor->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END);
- anim_editor->set_margin( MARGIN_RIGHT, 0 );*/
- anim_editor->hide();
-
-
-
-}
-
-
-AnimationPlayerEditorPlugin::~AnimationPlayerEditorPlugin()
-{
-}
diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h
deleted file mode 100644
index e28600a7ab..0000000000
--- a/tools/editor/plugins/animation_player_editor_plugin.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*************************************************************************/
-/* animation_player_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 ANIMATION_PLAYER_EDITOR_PLUGIN_H
-#define ANIMATION_PLAYER_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/animation/animation_player.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/texture_button.h"
-#include "scene/gui/slider.h"
-#include "scene/gui/spin_box.h"
-
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class AnimationKeyEditor;
-class AnimationPlayerEditor : public VBoxContainer {
-
- GDCLASS(AnimationPlayerEditor, VBoxContainer );
-
- EditorNode *editor;
- AnimationPlayer *player;
-
- enum {
- TOOL_COPY_ANIM,
- TOOL_PASTE_ANIM,
- TOOL_EDIT_RESOURCE
- };
-
- enum {
- ANIM_SAVE,
- ANIM_SAVE_AS
- };
-
- enum {
- RESOURCE_LOAD,
- RESOURCE_SAVE
- };
-
-
- OptionButton *animation;
- Button *stop;
- Button *play;
- Button *play_from;
- Button *play_bw;
- Button *play_bw_from;
-
- //Button *pause;
- Button *add_anim;
- Button *autoplay;
- Button *rename_anim;
- Button *duplicate_anim;
-
- Button *resource_edit_anim;
- Button *load_anim;
- MenuButton *save_anim;
- Button *blend_anim;
- Button *remove_anim;
- MenuButton *tool_anim;
- ToolButton *pin;
- Button *nodename;
- SpinBox *frame;
- LineEdit *scale;
- LineEdit *name;
- Label *name_title;
- UndoRedo *undo_redo;
- Ref<Texture> autoplay_icon;
- bool last_active;
-
- EditorFileDialog *file;
- AcceptDialog *accept;
- ConfirmationDialog* delete_dialog;
- int current_option;
-
- struct BlendEditor {
-
- AcceptDialog * dialog;
- Tree *tree;
- OptionButton *next;
-
- } blend_editor;
-
-
- ConfirmationDialog *name_dialog;
- ConfirmationDialog *error_dialog;
- bool renaming;
-
-
- bool updating;
- bool updating_blends;
-
- AnimationKeyEditor *key_editor;
-
-
- void _select_anim_by_name(const String& p_anim);
- void _play_pressed();
- void _play_from_pressed();
- void _play_bw_pressed();
- void _play_bw_from_pressed();
- void _autoplay_pressed();
- void _stop_pressed();
- void _pause_pressed();
- void _animation_selected(int p_which);
- void _animation_new();
- void _animation_rename();
- void _animation_name_edited();
- void _animation_load();
-
- void _animation_save_in_path(const Ref<Resource>& p_resource, const String& p_path);
- void _animation_save(const Ref<Resource>& p_resource);
- void _animation_save_as(const Ref<Resource>& p_resource);
-
- void _animation_remove();
- void _animation_remove_confirmed();
- void _animation_blend();
- void _animation_edit();
- void _animation_duplicate();
- void _animation_resource_edit();
- void _scale_changed(const String& p_scale);
- void _dialog_action(String p_file);
- void _seek_frame_changed(const String& p_frame);
- void _seek_value_changed(float p_value, bool p_set=false);
- void _blend_editor_next_changed(const int p_idx);
-
- void _list_changed();
- void _update_animation();
- void _update_player();
- void _blend_edited();
-
-
- void _hide_anim_editors();
-
- void _animation_player_changed(Object *p_pl);
-
- void _animation_key_editor_seek(float p_pos, bool p_drag);
- 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:
-
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- void _node_removed(Node *p_node);
- 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);
-
-
- void ensure_visibility();
-
- void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
- void edit(AnimationPlayer *p_player);
- AnimationPlayerEditor(EditorNode *p_editor);
-};
-
-class AnimationPlayerEditorPlugin : public EditorPlugin {
-
- GDCLASS( AnimationPlayerEditorPlugin, EditorPlugin );
-
- AnimationPlayerEditor *anim_editor;
- EditorNode *editor;
-
-public:
-
- virtual Dictionary get_state() const { return anim_editor->get_state(); }
- virtual void set_state(const Dictionary& p_state) { anim_editor->set_state(p_state); }
-
- virtual String get_name() const { return "Anim"; }
- 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);
-
- AnimationPlayerEditorPlugin(EditorNode *p_node);
- ~AnimationPlayerEditorPlugin();
-
-};
-
-#endif // ANIMATION_PLAYER_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/animation_tree_editor_plugin.cpp b/tools/editor/plugins/animation_tree_editor_plugin.cpp
deleted file mode 100644
index 1ed52d2df6..0000000000
--- a/tools/editor/plugins/animation_tree_editor_plugin.cpp
+++ /dev/null
@@ -1,1536 +0,0 @@
-/*************************************************************************/
-/* animation_tree_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "animation_tree_editor_plugin.h"
-
-#include "scene/gui/menu_button.h"
-#include "scene/gui/panel.h"
-#include "scene/main/viewport.h"
-#include "core/io/resource_loader.h"
-#include "core/globals.h"
-#include "os/input.h"
-#include "os/keyboard.h"
-
-void AnimationTreeEditor::edit(AnimationTreePlayer* p_anim_tree) {
-
-
- anim_tree=p_anim_tree;
-
- if (!anim_tree) {
- hide();
- } else {
- order.clear();
- p_anim_tree->get_node_list(&order);
- /*
- for(List<StringName>::Element* E=order.front();E;E=E->next()) {
-
- if (E->get() >= (int)last_id)
- last_id=E->get()+1;
- }*/
- play_button->set_pressed(p_anim_tree->is_active());
- //read the orders
- }
-
-}
-
-Size2 AnimationTreeEditor::_get_maximum_size() {
-
- Size2 max;
-
- for(List<StringName>::Element *E=order.front();E;E=E->next()) {
-
- Point2 pos = anim_tree->node_get_pos(E->get());
-
- if (click_type==CLICK_NODE && click_node==E->get()) {
-
- pos+=click_motion-click_pos;
- }
- pos+=get_node_size(E->get());
- if (pos.x>max.x)
- max.x=pos.x;
- if (pos.y>max.y)
- max.y=pos.y;
-
- }
-
- return max;
-}
-
-
-const char* AnimationTreeEditor::_node_type_names[]={"Output","Animation","OneShot","Mix","Blend2","Blend3","Blend4","TimeScale","TimeSeek","Transition"};
-
-Size2 AnimationTreeEditor::get_node_size(const StringName& p_node) const {
-
- AnimationTreePlayer::NodeType type=anim_tree->node_get_type(p_node);
-
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Ref<Font> font = get_font("font","PopupMenu");
-
- Size2 size = style->get_minimum_size();
-
- int count=2; // title and name
- int inputs = anim_tree->node_get_input_count(p_node);
- count += inputs?inputs:1;
- String name = p_node;
-
-
- float name_w = font->get_string_size( name ).width;
- float type_w = font->get_string_size( String(_node_type_names[type]) ).width;
- float max_w=MAX(name_w,type_w);
-
-
-
- switch(type) {
- case AnimationTreePlayer::NODE_TIMESEEK:
- case AnimationTreePlayer::NODE_OUTPUT: {} break;
- case AnimationTreePlayer::NODE_ANIMATION:
- case AnimationTreePlayer::NODE_ONESHOT:
- case AnimationTreePlayer::NODE_MIX:
- case AnimationTreePlayer::NODE_BLEND2:
- case AnimationTreePlayer::NODE_BLEND3:
- case AnimationTreePlayer::NODE_BLEND4:
- case AnimationTreePlayer::NODE_TIMESCALE:
- case AnimationTreePlayer::NODE_TRANSITION: {
-
-
- size.height+=font->get_height();
- } break;
- case AnimationTreePlayer::NODE_MAX: {}
- }
-
- size.x+=max_w+20;
- size.y+=count*(font->get_height()+get_constant("vseparation","PopupMenu"));
-
- return size;
-}
-
-
-void AnimationTreeEditor::_edit_dialog_changede(String) {
-
- edit_dialog->hide();
-}
-
-void AnimationTreeEditor::_edit_dialog_changeds(String s) {
-
- _edit_dialog_changed();
-}
-
-void AnimationTreeEditor::_edit_dialog_changedf(float) {
-
- _edit_dialog_changed();
-}
-
-void AnimationTreeEditor::_edit_dialog_changed() {
-
- if (updating_edit)
- return;
-
- if (renaming_edit) {
-
- if (anim_tree->node_rename(edited_node,edit_line[0]->get_text())==OK) {
- for(List<StringName>::Element* E=order.front();E;E=E->next()) {
-
- if (E->get() == edited_node)
- E->get()=edit_line[0]->get_text();
- }
- edited_node=edit_line[0]->get_text();
- }
- update();
- return;
- }
-
- AnimationTreePlayer::NodeType type=anim_tree->node_get_type(edited_node);
-
- switch(type) {
-
- case AnimationTreePlayer::NODE_TIMESCALE:
- anim_tree->timescale_node_set_scale(edited_node,edit_line[0]->get_text().to_double());
- break;
- case AnimationTreePlayer::NODE_ONESHOT:
- anim_tree->oneshot_node_set_fadein_time(edited_node,edit_line[0]->get_text().to_double());
- anim_tree->oneshot_node_set_fadeout_time(edited_node,edit_line[1]->get_text().to_double());
- anim_tree->oneshot_node_set_autorestart_delay(edited_node,edit_line[2]->get_text().to_double());
- anim_tree->oneshot_node_set_autorestart_random_delay(edited_node,edit_line[3]->get_text().to_double());
- anim_tree->oneshot_node_set_autorestart(edited_node,edit_check->is_pressed());
- anim_tree->oneshot_node_set_mix_mode(edited_node,edit_option->get_selected());
-
- break;
-
- case AnimationTreePlayer::NODE_MIX:
-
- anim_tree->mix_node_set_amount(edited_node,edit_scroll[0]->get_value());
- break;
- case AnimationTreePlayer::NODE_BLEND2:
- anim_tree->blend2_node_set_amount(edited_node,edit_scroll[0]->get_value());
-
- break;
-
- case AnimationTreePlayer::NODE_BLEND3:
- anim_tree->blend3_node_set_amount(edited_node,edit_scroll[0]->get_value());
-
- break;
- case AnimationTreePlayer::NODE_BLEND4:
-
- anim_tree->blend4_node_set_amount(edited_node,Point2(edit_scroll[0]->get_value(),edit_scroll[1]->get_value()));
-
- break;
-
- case AnimationTreePlayer::NODE_TRANSITION: {
- anim_tree->transition_node_set_xfade_time(edited_node,edit_line[0]->get_text().to_double());
- if (anim_tree->transition_node_get_current(edited_node)!=edit_option->get_selected())
- anim_tree->transition_node_set_current(edited_node,edit_option->get_selected());
- } break;
- default: {}
- }
-
-}
-
-void AnimationTreeEditor::_edit_dialog_animation_changed() {
-
-
- Ref<Animation> anim = property_editor->get_variant().operator RefPtr();
- anim_tree->animation_node_set_animation(edited_node,anim);
- update();
-}
-
-void AnimationTreeEditor::_edit_dialog_edit_animation() {
-
- if (get_tree()->is_editor_hint()) {
- get_tree()->get_root()->get_child(0)->call("_resource_selected", property_editor->get_variant().operator RefPtr());
- };
-};
-
-void AnimationTreeEditor::_edit_oneshot_start() {
-
- anim_tree->oneshot_node_start(edited_node);
-}
-
-void AnimationTreeEditor::_play_toggled() {
-
- anim_tree->set_active(play_button->is_pressed());
-}
-
-
-void AnimationTreeEditor::_master_anim_menu_item(int p_item) {
-
- if(p_item == 0) _edit_filters();
- else {
-
- String str = master_anim_popup->get_item_text(p_item);
- anim_tree->animation_node_set_master_animation(edited_node,str);
- }
- update();
-}
-
-void AnimationTreeEditor::_popup_edit_dialog() {
-
- updating_edit=true;
-
- for(int i=0;i<2;i++)
- edit_scroll[i]->hide();
-
- for(int i=0;i<4;i++) {
-
- edit_line[i]->hide();
- edit_label[i]->hide();
- }
-
- edit_option->hide();
- edit_button->hide();
- filter_button->hide();
- edit_check->hide();
-
- Point2 pos = anim_tree->node_get_pos(edited_node)-Point2(h_scroll->get_value(),v_scroll->get_value());
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Size2 size = get_node_size(edited_node);
- Point2 popup_pos( pos.x+style->get_margin(MARGIN_LEFT), pos.y+size.y-style->get_margin(MARGIN_BOTTOM));
- popup_pos+=get_global_pos();
-
- if (renaming_edit) {
-
- edit_label[0]->set_text(TTR("New name:"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_line[0]->set_begin(Point2(15,25));
- edit_line[0]->set_text(edited_node);
- edit_line[0]->show();
- edit_dialog->set_size(Size2(150,50));
-
- } else {
-
- AnimationTreePlayer::NodeType type=anim_tree->node_get_type(edited_node);
-
-
- switch(type) {
-
- case AnimationTreePlayer::NODE_ANIMATION:
-
- if (anim_tree->get_master_player()!=NodePath() && anim_tree->has_node(anim_tree->get_master_player()) && anim_tree->get_node(anim_tree->get_master_player())->cast_to<AnimationPlayer>()) {
-
- AnimationPlayer *ap = anim_tree->get_node(anim_tree->get_master_player())->cast_to<AnimationPlayer>();
- master_anim_popup->clear();
- master_anim_popup->add_item("Edit Filters");
- master_anim_popup->add_separator();
- List<StringName> sn;
- ap->get_animation_list(&sn);
- sn.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E=sn.front();E;E=E->next()) {
- master_anim_popup->add_item(E->get());
- }
-
- master_anim_popup->set_pos(popup_pos);
- master_anim_popup->popup();
- } else {
- property_editor->edit(this,"",Variant::OBJECT,anim_tree->animation_node_get_animation(edited_node),PROPERTY_HINT_RESOURCE_TYPE,"Animation");
- property_editor->set_pos(popup_pos);
- property_editor->popup();
- updating_edit=false;
- }
- return;
- case AnimationTreePlayer::NODE_TIMESCALE:
- edit_label[0]->set_text(TTR("Scale:"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_line[0]->set_begin(Point2(15,25));
- edit_line[0]->set_text(rtos(anim_tree->timescale_node_get_scale(edited_node)));
- edit_line[0]->show();
- edit_dialog->set_size(Size2(150,50));
- break;
- case AnimationTreePlayer::NODE_ONESHOT:
- edit_label[0]->set_text(TTR("Fade In (s):"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_line[0]->set_begin(Point2(15,25));
- edit_line[0]->set_text(rtos(anim_tree->oneshot_node_get_fadein_time(edited_node)));
- edit_line[0]->show();
- edit_label[1]->set_text(TTR("Fade Out (s):"));
- edit_label[1]->set_pos(Point2(5,55));
- edit_label[1]->show();
- edit_line[1]->set_begin(Point2(15,75));
- edit_line[1]->set_text(rtos(anim_tree->oneshot_node_get_fadeout_time(edited_node)));
- edit_line[1]->show();
-
- edit_option->clear();
- edit_option->add_item(TTR("Blend"),0);
- edit_option->add_item(TTR("Mix"),1);
- edit_option->set_begin(Point2(15,105));
-
- edit_option->select( anim_tree->oneshot_node_get_mix_mode(edited_node));
- edit_option->show();
-
- edit_check->set_text(TTR("Auto Restart:"));
- edit_check->set_begin(Point2(15,125));
- edit_check->set_pressed(anim_tree->oneshot_node_has_autorestart(edited_node));
- edit_check->show();
-
- edit_label[2]->set_text(TTR("Restart (s):"));
- edit_label[2]->set_pos(Point2(5,145));
- edit_label[2]->show();
- edit_line[2]->set_begin(Point2(15,165));
- edit_line[2]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_delay(edited_node)));
- edit_line[2]->show();
- edit_label[3]->set_text(TTR("Random Restart (s):"));
- edit_label[3]->set_pos(Point2(5,195));
- edit_label[3]->show();
- edit_line[3]->set_begin(Point2(15,215));
- edit_line[3]->set_text(rtos(anim_tree->oneshot_node_get_autorestart_random_delay(edited_node)));
- edit_line[3]->show();
-
- filter_button->set_begin(Point2(10,245));
- filter_button->show();
-
- edit_button->set_begin(Point2(10,268));
- edit_button->set_text(TTR("Start!"));
-
- edit_button->show();
-
- edit_dialog->set_size(Size2(180,293));
-
- break;
-
- case AnimationTreePlayer::NODE_MIX:
-
- edit_label[0]->set_text(TTR("Amount:"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_scroll[0]->set_min(0);
- edit_scroll[0]->set_max(1);
- edit_scroll[0]->set_value(anim_tree->mix_node_get_amount(edited_node));
- edit_scroll[0]->set_begin(Point2(15,25));
- edit_scroll[0]->show();
- edit_dialog->set_size(Size2(150,50));
-
- break;
- case AnimationTreePlayer::NODE_BLEND2:
- edit_label[0]->set_text(TTR("Blend:"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_scroll[0]->set_min(0);
- edit_scroll[0]->set_max(1);
- edit_scroll[0]->set_value(anim_tree->blend2_node_get_amount(edited_node));
- edit_scroll[0]->set_begin(Point2(15,25));
- edit_scroll[0]->show();
- filter_button->set_begin(Point2(10,47));
- filter_button->show();
- edit_dialog->set_size(Size2(150,74));
-
- break;
-
- case AnimationTreePlayer::NODE_BLEND3:
- edit_label[0]->set_text(TTR("Blend:"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_scroll[0]->set_min(-1);
- edit_scroll[0]->set_max(1);
- edit_scroll[0]->set_value(anim_tree->blend3_node_get_amount(edited_node));
- edit_scroll[0]->set_begin(Point2(15,25));
- edit_scroll[0]->show();
- edit_dialog->set_size(Size2(150,50));
-
- break;
- case AnimationTreePlayer::NODE_BLEND4:
-
- edit_label[0]->set_text(TTR("Blend 0:"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_scroll[0]->set_min(0);
- edit_scroll[0]->set_max(1);
- edit_scroll[0]->set_value(anim_tree->blend4_node_get_amount(edited_node).x);
- edit_scroll[0]->set_begin(Point2(15,25));
- edit_scroll[0]->show();
- edit_label[1]->set_text(TTR("Blend 1:"));
- edit_label[1]->set_pos(Point2(5,55));
- edit_label[1]->show();
- edit_scroll[1]->set_min(0);
- edit_scroll[1]->set_max(1);
- edit_scroll[1]->set_value(anim_tree->blend4_node_get_amount(edited_node).y);
- edit_scroll[1]->set_begin(Point2(15,75));
- edit_scroll[1]->show();
- edit_dialog->set_size(Size2(150,100));
-
- break;
-
- case AnimationTreePlayer::NODE_TRANSITION: {
-
-
- edit_label[0]->set_text(TTR("X-Fade Time (s):"));
- edit_label[0]->set_pos(Point2(5,5));
- edit_label[0]->show();
- edit_line[0]->set_begin(Point2(15,25));
- edit_line[0]->set_text(rtos(anim_tree->transition_node_get_xfade_time(edited_node)));
- edit_line[0]->show();
-
- edit_label[1]->set_text(TTR("Current:"));
- edit_label[1]->set_pos(Point2(5,55));
- edit_label[1]->show();
- edit_option->set_begin(Point2(15,75));
-
- edit_option->clear();
-
- for(int i=0;i<anim_tree->transition_node_get_input_count(edited_node);i++) {
- edit_option->add_item(itos(i),i);
- }
-
- edit_option->select(anim_tree->transition_node_get_current(edited_node));
- edit_option->show();
- edit_dialog->set_size(Size2(150,100));
-
- } break;
- default: {}
-
- }
-
- }
-
-
-
- edit_dialog->set_pos(popup_pos);
- edit_dialog->popup();
-
- updating_edit=false;
-}
-
-void AnimationTreeEditor::_draw_node(const StringName& p_node) {
-
- RID ci = get_canvas_item();
- AnimationTreePlayer::NodeType type=anim_tree->node_get_type(p_node);
-
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Ref<Font> font = get_font("font","PopupMenu");
- Color font_color = get_color("font_color","PopupMenu");
- Color font_color_title = get_color("font_color_hover","PopupMenu");
- font_color_title.a*=0.8;
- Ref<Texture> slot_icon = get_icon("NodeRealSlot","EditorIcons");
-
-
- Size2 size=get_node_size(p_node);
- Point2 pos = anim_tree->node_get_pos(p_node);
- if (click_type==CLICK_NODE && click_node==p_node) {
-
- pos+=click_motion-click_pos;
- if (pos.x<5)
- pos.x=5;
- if (pos.y<5)
- pos.y=5;
-
- }
-
- pos-=Point2(h_scroll->get_value(),v_scroll->get_value());
-
- style->draw(ci,Rect2(pos,size));
-
- float w = size.width-style->get_minimum_size().width;
- float h = font->get_height()+get_constant("vseparation","PopupMenu");
-
- Point2 ofs=style->get_offset()+pos;
- Point2 ascofs(0,font->get_ascent());
-
- Color bx = font_color_title;
- bx.a*=0.1;
- draw_rect(Rect2(ofs,Size2(size.width-style->get_minimum_size().width,font->get_height())),bx);
- font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,String(_node_type_names[type]),font_color_title);
-
- ofs.y+=h;
- font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,p_node,font_color);
- ofs.y+=h;
-
- int count=2; // title and name
- int inputs = anim_tree->node_get_input_count(p_node);
- count += inputs?inputs:1;
-
- float icon_h_ofs = Math::floor(( font->get_height()-slot_icon->get_height())/2.0 )+1;
-
- if (type!=AnimationTreePlayer::NODE_OUTPUT)
- slot_icon->draw(ci,ofs+Point2(w,icon_h_ofs)); //output
-
- if (inputs) {
- for(int i=0;i<inputs;i++) {
-
- slot_icon->draw(ci,ofs+Point2(-slot_icon->get_width(),icon_h_ofs));
- String text;
- switch(type) {
-
- case AnimationTreePlayer::NODE_TIMESCALE:
- case AnimationTreePlayer::NODE_TIMESEEK: text="in"; break;
- case AnimationTreePlayer::NODE_OUTPUT: text="out"; break;
- case AnimationTreePlayer::NODE_ANIMATION: break;
- case AnimationTreePlayer::NODE_ONESHOT: text=(i==0?"in":"add"); break;
- case AnimationTreePlayer::NODE_BLEND2:
- case AnimationTreePlayer::NODE_MIX: text=(i==0?"a":"b"); break;
- case AnimationTreePlayer::NODE_BLEND3:
- switch(i) {
- case 0: text="b-"; break;
- case 1: text="a"; break;
- case 2: text="b+"; break;
-
- }
- break;
-
-
- case AnimationTreePlayer::NODE_BLEND4:
- switch(i) {
- case 0: text="a0"; break;
- case 1: text="b0"; break;
- case 2: text="a1"; break;
- case 3: text="b1"; break;
- }
- break;
-
- case AnimationTreePlayer::NODE_TRANSITION:
- text=itos(i);
- if (anim_tree->transition_node_has_input_auto_advance(p_node,i))
- text+="->";
-
- break;
- default: {}
- }
- font->draw(ci,ofs+ascofs+Point2(3,0),text,font_color);
-
- ofs.y+=h;
- }
- } else {
- ofs.y+=h;
- }
-
- Ref<StyleBox> pg_bg=get_stylebox("bg","ProgressBar");
- Ref<StyleBox> pg_fill=get_stylebox("fill","ProgressBar");
- Rect2 pg_rect(ofs,Size2(w,h));
-
- bool editable=true;
- switch(type) {
- case AnimationTreePlayer::NODE_ANIMATION: {
-
- Ref<Animation> anim = anim_tree->animation_node_get_animation(p_node);
- String text;
- if (anim_tree->animation_node_get_master_animation(p_node)!="")
- text=anim_tree->animation_node_get_master_animation(p_node);
- else if (anim.is_null())
- text="load..";
- else
- text=anim->get_name();
-
- font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,text,font_color_title);
-
- } break;
- case AnimationTreePlayer::NODE_ONESHOT:
- case AnimationTreePlayer::NODE_MIX:
- case AnimationTreePlayer::NODE_BLEND2:
- case AnimationTreePlayer::NODE_BLEND3:
- case AnimationTreePlayer::NODE_BLEND4:
- case AnimationTreePlayer::NODE_TIMESCALE:
- case AnimationTreePlayer::NODE_TRANSITION: {
-
- font->draw_halign(ci,ofs+ascofs,HALIGN_CENTER,w,"edit..",font_color_title);
- } break;
- default: editable=false;
- }
-
- if (editable) {
-
- Ref<Texture> arrow = get_icon("arrow","Tree");
- Point2 arrow_ofs( w-arrow->get_width(),Math::floor( (h-arrow->get_height())/2) );
- arrow->draw(ci,ofs+arrow_ofs);
- }
-}
-
-#if 0
-void AnimationTreeEditor::_node_param_changed() {
-
- //anim_tree->node_set_param( click_node,property_editor->get_variant() );
- //update();
- //_write_anim_tree_graph();
-}
-#endif
-
-AnimationTreeEditor::ClickType AnimationTreeEditor::_locate_click(const Point2& p_click,StringName *p_node_id,int *p_slot_index) const {
-
-
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Ref<Font> font = get_font("font","PopupMenu");
-
- float h = (font->get_height()+get_constant("vseparation","PopupMenu"));
-
- for(const List<StringName>::Element *E=order.back();E;E=E->prev()) {
-
- StringName node = E->get();
-
- AnimationTreePlayer::NodeType type=anim_tree->node_get_type(node);
-
- Point2 pos = anim_tree->node_get_pos(node);
- Size2 size = get_node_size(node);
-
- pos-=Point2(h_scroll->get_value(),v_scroll->get_value());
-
- if (!Rect2(pos,size).has_point(p_click))
- continue;
-
- if (p_node_id)
- *p_node_id=node;
-
- pos=p_click-pos;
-
- float y = pos.y-style->get_offset().height;
-
- if (y<2*h)
- return CLICK_NODE;
- y-=2*h;
-
- int inputs = anim_tree->node_get_input_count(node);
- int count = MAX(inputs,1);
-
- if (inputs==0 || (pos.x > size.width/2 && type != AnimationTreePlayer::NODE_OUTPUT)) {
-
- if (y<count*h) {
-
- if (p_slot_index)
- *p_slot_index=0;
- return CLICK_OUTPUT_SLOT;
- }
- }
-
- for(int i=0;i<count;i++) {
-
- if (y<h) {
- if (p_slot_index)
- *p_slot_index=i;
- return CLICK_INPUT_SLOT;
- }
- y-=h;
- }
-
- bool has_parameters = type!=AnimationTreePlayer::NODE_OUTPUT && type!=AnimationTreePlayer::NODE_TIMESEEK;
- return has_parameters ? CLICK_PARAMETER : CLICK_NODE;
- }
-
- return CLICK_NONE;
-}
-
-Point2 AnimationTreeEditor::_get_slot_pos(const StringName& p_node,bool p_input,int p_slot) {
-
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Ref<Font> font = get_font("font","PopupMenu");
- Ref<Texture> slot_icon = get_icon("NodeRealSlot","EditorIcons");
-
- Size2 size=get_node_size(p_node);
- Point2 pos = anim_tree->node_get_pos(p_node);
-
- if (click_type==CLICK_NODE && click_node==p_node) {
-
- pos+=click_motion-click_pos;
- if (pos.x<5)
- pos.x=5;
- if (pos.y<5)
- pos.y=5;
-
- }
-
- pos-=Point2(h_scroll->get_value(),v_scroll->get_value());
-
-
- float w = size.width-style->get_minimum_size().width;
- float h = font->get_height()+get_constant("vseparation","PopupMenu");
-
-
- pos+=style->get_offset();
-
- pos.y+=h*2;
-
- pos.y+=h*p_slot;
-
- pos+=Point2( -slot_icon->get_width()/2.0, h/2.0).floor();
-
- if(!p_input) {
- pos.x+=w+slot_icon->get_width();
-
- }
-
- return pos;
-
-}
-
-#if 0
-void AnimationTreeEditor::_node_edit_property(const StringName& p_node) {
-
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Size2 size = get_node_size(p_node);
- Point2 pos = Point2( anim_tree->node_get_pos_x(p_node), anim_tree->node_get_pos_y(p_node) )-offset;
-
- VisualServer::AnimationTreeNodeType type=anim_tree->node_get_type(p_node);
-
- PropertyInfo ph = VisualServer::get_singleton()->anim_tree_node_get_type_info(type);
- if (ph.type==Variant::NIL)
- return;
- if (ph.type==Variant::_RID)
- ph.type=Variant::RESOURCE;
-
- property_editor->edit(NULL,ph.name,ph.type,anim_tree->node_get_param(p_node),ph.hint,ph.hint_string);
-
- Point2 popup_pos=Point2( pos.x+(size.width-property_editor->get_size().width)/2.0,pos.y+(size.y-style->get_margin(MARGIN_BOTTOM))).floor();
- popup_pos+=get_global_pos();
- property_editor->set_pos(popup_pos);
-
- property_editor->popup();
-
-}
-#endif
-
-void AnimationTreeEditor::_gui_input(InputEvent p_event) {
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- if (p_event.mouse_button.pressed) {
-
-
- if (p_event.mouse_button.button_index==1) {
- click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- click_motion=click_pos;
- click_type = _locate_click(click_pos,&click_node,&click_slot);
- if( click_type!=CLICK_NONE) {
-
- order.erase(click_node);
- order.push_back(click_node);
- update();
- }
-
- switch(click_type) {
- case CLICK_INPUT_SLOT: {
- click_pos=_get_slot_pos(click_node,true,click_slot);
- } break;
- case CLICK_OUTPUT_SLOT: {
- click_pos=_get_slot_pos(click_node,false,click_slot);
- } break;
- case CLICK_PARAMETER: {
-
- edited_node=click_node;
- renaming_edit=false;
- _popup_edit_dialog();
- //open editor
- //_node_edit_property(click_node);
- } break;
- default:{}
- }
- }
- if (p_event.mouse_button.button_index==2) {
-
- if (click_type!=CLICK_NONE) {
- click_type=CLICK_NONE;
- update();
- } else {
- // try to disconnect/remove
-
- Point2 rclick_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- rclick_type = _locate_click(rclick_pos,&rclick_node,&rclick_slot);
- if (rclick_type==CLICK_INPUT_SLOT || rclick_type==CLICK_OUTPUT_SLOT) {
-
- node_popup->clear();
- node_popup->add_item(TTR("Disconnect"),NODE_DISCONNECT);
- if (anim_tree->node_get_type(rclick_node)==AnimationTreePlayer::NODE_TRANSITION) {
- node_popup->add_item(TTR("Add Input"),NODE_ADD_INPUT);
- if (rclick_type==CLICK_INPUT_SLOT) {
- if (anim_tree->transition_node_has_input_auto_advance(rclick_node,rclick_slot))
- node_popup->add_item(TTR("Clear Auto-Advance"),NODE_CLEAR_AUTOADVANCE);
- else
- node_popup->add_item(TTR("Set Auto-Advance"),NODE_SET_AUTOADVANCE);
- node_popup->add_item(TTR("Delete Input"),NODE_DELETE_INPUT);
-
- }
- }
-
- node_popup->set_pos(rclick_pos+get_global_pos());
- node_popup->popup();
-
- }
-
- if (rclick_type==CLICK_NODE) {
- node_popup->clear();
- node_popup->add_item(TTR("Rename"),NODE_RENAME);
- node_popup->add_item(TTR("Remove"),NODE_ERASE);
- if (anim_tree->node_get_type(rclick_node)==AnimationTreePlayer::NODE_TRANSITION)
- node_popup->add_item(TTR("Add Input"),NODE_ADD_INPUT);
- node_popup->set_pos(rclick_pos+get_global_pos());
- node_popup->popup();
- }
-
-
- }
- }
- } else {
-
- if (p_event.mouse_button.button_index==1 && click_type!=CLICK_NONE) {
-
- switch(click_type) {
- case CLICK_INPUT_SLOT:
- case CLICK_OUTPUT_SLOT: {
-
- Point2 dst_click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- StringName id;
- int slot;
- ClickType dst_click_type = _locate_click(dst_click_pos,&id,&slot);
-
- if (dst_click_type==CLICK_INPUT_SLOT && click_type==CLICK_OUTPUT_SLOT) {
-
- anim_tree->connect_nodes(click_node,id,slot);
-
- }
- if (click_type==CLICK_INPUT_SLOT && dst_click_type==CLICK_OUTPUT_SLOT) {
-
- anim_tree->connect_nodes(id,click_node,click_slot);
- }
-
- } break;
- case CLICK_NODE: {
- Point2 new_pos = anim_tree->node_get_pos(click_node)+(click_motion-click_pos);
- if (new_pos.x<5)
- new_pos.x=5;
- if (new_pos.y<5)
- new_pos.y=5;
- anim_tree->node_set_pos(click_node,new_pos);
-
- } break;
- default: {}
- }
-
- click_type=CLICK_NONE;
- update();
- }
- }
- }
-
- case InputEvent::MOUSE_MOTION: {
-
- if (p_event.mouse_motion.button_mask&1 && click_type!=CLICK_NONE) {
-
- click_motion=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- update();
- }
- if ((p_event.mouse_motion.button_mask&4 || Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
-
- h_scroll->set_value( h_scroll->get_value() - p_event.mouse_motion.relative_x );
- v_scroll->set_value( v_scroll->get_value() - p_event.mouse_motion.relative_y );
- update();
- }
-
- } break;
- }
-
-}
-
-
-void AnimationTreeEditor::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) {
-
- static const int steps = 20;
-
- Rect2 r;
- r.pos=p_from;
- r.expand_to(p_to);
- Vector2 sign=Vector2((p_from.x < p_to.x) ? 1 : -1,(p_from.y < p_to.y) ? 1 : -1);
- bool flip = sign.x * sign.y < 0;
-
- Vector2 prev;
- for(int i=0;i<=steps;i++) {
-
- float d = i/float(steps);
- float c=-Math::cos(d*Math_PI) * 0.5+0.5;
- if (flip)
- c=1.0-c;
- Vector2 p = r.pos+Vector2(d*r.size.width,c*r.size.height);
-
- if (i>0) {
-
- draw_line(prev,p,p_color,2);
- }
-
- prev=p;
- }
-}
-
-void AnimationTreeEditor::_notification(int p_what) {
-
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
- play_button->set_icon( get_icon("Play","EditorIcons") );
- add_menu->set_icon( get_icon("Add","EditorIcons") );
- } break;
- case NOTIFICATION_DRAW: {
-
-
- _update_scrollbars();
- //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1));
- get_stylebox("bg","Tree")->draw(get_canvas_item(),Rect2(Point2(),get_size()));
-
- for(List<StringName>::Element *E=order.front();E;E=E->next()) {
-
- _draw_node(E->get());
- }
-
- if (click_type==CLICK_INPUT_SLOT || click_type==CLICK_OUTPUT_SLOT) {
-
- _draw_cos_line(click_pos,click_motion,Color(0.5,1,0.5,0.8));
- }
-
- List<AnimationTreePlayer::Connection> connections;
- anim_tree->get_connection_list(&connections);
-
- for(List<AnimationTreePlayer::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- const AnimationTreePlayer::Connection &c=E->get();
- Point2 source = _get_slot_pos(c.src_node,false,0);
- Point2 dest = _get_slot_pos(c.dst_node,true,c.dst_input);
- Color col = Color(1,1,0.5,0.8);
-/*
- if (click_type==CLICK_NODE && click_node==c.src_node) {
-
- source+=click_motion-click_pos;
- }
-
- if (click_type==CLICK_NODE && click_node==c.dst_node) {
-
- dest+=click_motion-click_pos;
- }*/
-
- _draw_cos_line(source,dest,col);
-
- }
-
- switch(anim_tree->get_last_error()) {
-
- case AnimationTreePlayer::CONNECT_OK: {
-
- Ref<Font> f = get_font("font","Label");
- f->draw(get_canvas_item(),Point2(5,25+f->get_ascent()),TTR("Animation tree is valid."),Color(0,1,0.6,0.8));
- } break;
- default: {
-
- Ref<Font> f = get_font("font","Label");
- f->draw(get_canvas_item(),Point2(5,25+f->get_ascent()),TTR("Animation tree is invalid."),Color(1,0.6,0.0,0.8));
- } break;
- }
-
- } break;
- }
-
-}
-
-void AnimationTreeEditor::_update_scrollbars() {
-
- Size2 size = get_size();
- Size2 hmin = h_scroll->get_combined_minimum_size();
- Size2 vmin = v_scroll->get_combined_minimum_size();
-
- v_scroll->set_begin( Point2(size.width - vmin.width, 0) );
- v_scroll->set_end( Point2(size.width, size.height) );
-
- h_scroll->set_begin( Point2( 0, size.height - hmin.height) );
- h_scroll->set_end( Point2(size.width-vmin.width, size.height) );
-
-
- Size2 min = _get_maximum_size();
-
- if (min.height < size.height - hmin.height) {
-
- v_scroll->hide();
- offset.y=0;
- } else {
-
- v_scroll->show();
- v_scroll->set_max(min.height);
- v_scroll->set_page(size.height - hmin.height);
- offset.y=v_scroll->get_value();
- }
-
- if (min.width < size.width - vmin.width) {
-
- h_scroll->hide();
- offset.x=0;
- } else {
-
- h_scroll->show();
- h_scroll->set_max(min.width);
- h_scroll->set_page(size.width - vmin.width);
- offset.x=h_scroll->get_value();
- }
-}
-
-void AnimationTreeEditor::_scroll_moved(float) {
-
- offset.x=h_scroll->get_value();
- offset.y=v_scroll->get_value();
- update();
-}
-
-
-void AnimationTreeEditor::_node_menu_item(int p_item) {
-
- switch(p_item) {
-
- case NODE_DISCONNECT: {
-
- if (rclick_type==CLICK_INPUT_SLOT) {
-
- anim_tree->disconnect_nodes(rclick_node,rclick_slot);
- update();
- }
-
- if (rclick_type==CLICK_OUTPUT_SLOT) {
-
-
- List<AnimationTreePlayer::Connection> connections;
- anim_tree->get_connection_list(&connections);
-
- for(List<AnimationTreePlayer::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- const AnimationTreePlayer::Connection &c=E->get();
- if( c.dst_node==rclick_node) {
-
- anim_tree->disconnect_nodes(c.dst_node,c.dst_input);
- }
- }
- update();
- }
-
- } break;
- case NODE_RENAME: {
-
- renaming_edit=true;
- edited_node=rclick_node;
- _popup_edit_dialog();
-
- } break;
- case NODE_ADD_INPUT: {
-
- anim_tree->transition_node_set_input_count(rclick_node, anim_tree->transition_node_get_input_count(rclick_node)+1);
- update();
- } break;
- case NODE_DELETE_INPUT: {
-
- anim_tree->transition_node_delete_input(rclick_node, rclick_slot);
- update();
- } break;
- case NODE_SET_AUTOADVANCE: {
-
- anim_tree->transition_node_set_input_auto_advance(rclick_node,rclick_slot,true);
- update();
-
- } break;
- case NODE_CLEAR_AUTOADVANCE: {
-
- anim_tree->transition_node_set_input_auto_advance(rclick_node,rclick_slot,false);
- update();
-
- } break;
-
- case NODE_ERASE: {
-
- if (rclick_node=="out")
- break;
- order.erase(rclick_node);
- anim_tree->remove_node(rclick_node);
- update();
- } break;
- }
-}
-
-StringName AnimationTreeEditor::_add_node(int p_item) {
-
- static const char* bname[] = {
- "out",
- "anim",
- "oneshot",
- "mix",
- "blend2",
- "blend3",
- "blend4",
- "scale",
- "seek",
- "transition"
- };
-
- String name;
- int idx=1;
-
- while(true) {
-
- name = bname[p_item];
- if (idx>1)
- name+=" "+itos(idx);
- if (anim_tree->node_exists(name))
- idx++;
- else
- break;
- }
-
-
- anim_tree->add_node((AnimationTreePlayer::NodeType)p_item,name);
- anim_tree->node_set_pos(name,Point2(last_x,last_y));
- order.push_back(name);
- last_x+=10;
- last_y+=10;
- last_x=last_x % (int)get_size().width;
- last_y=last_y % (int)get_size().height;
- update();
-
- return name;
-};
-
-void AnimationTreeEditor::_file_dialog_selected(String p_path) {
-
- switch (file_op) {
-
- case MENU_IMPORT_ANIMATIONS: {
- Vector<String> files = file_dialog->get_selected_files();
-
- for (int i=0; i<files.size(); i++) {
-
- StringName node = _add_node(AnimationTreePlayer::NODE_ANIMATION);
-
- RES anim = ResourceLoader::load(files[i]);
- anim_tree->animation_node_set_animation(node,anim);
- //anim_tree->node_set_name(node, files[i].get_file());
- };
- } break;
-
- default:
- break;
- };
-};
-
-void AnimationTreeEditor::_add_menu_item(int p_item) {
-
- if (p_item==MENU_GRAPH_CLEAR) {
-
- //clear
- } else if (p_item == MENU_IMPORT_ANIMATIONS) {
-
- file_op = MENU_IMPORT_ANIMATIONS;
- file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- file_dialog->popup_centered_ratio();
-
- } else {
-
- _add_node(p_item);
- }
-}
-
-Size2 AnimationTreeEditor::get_minimum_size() const {
-
- return Size2(10,200);
-}
-
-void AnimationTreeEditor::_find_paths_for_filter(const StringName& p_node,Set<String>& paths) {
-
- ERR_FAIL_COND( !anim_tree->node_exists(p_node) );
-
- for(int i=0;i<anim_tree->node_get_input_count(p_node);i++) {
-
- StringName port = anim_tree->node_get_input_source(p_node,i);
- if (port==StringName())
- continue;
- _find_paths_for_filter(port,paths);
- }
-
- if (anim_tree->node_get_type(p_node)==AnimationTreePlayer::NODE_ANIMATION) {
-
- Ref<Animation> anim = anim_tree->animation_node_get_animation(p_node);
- if (anim.is_valid()) {
-
- for(int i=0;i<anim->get_track_count();i++) {
- paths.insert(anim->track_get_path(i));
- }
- }
- }
-}
-
-
-void AnimationTreeEditor::_filter_edited() {
-
-
- TreeItem *ed = filter->get_edited();
- if (!ed)
- return;
-
- if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ONESHOT) {
- anim_tree->oneshot_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0));
- } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) {
- anim_tree->blend2_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0));
- } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ANIMATION) {
- anim_tree->animation_node_set_filter_path(edited_node,ed->get_metadata(0),ed->is_checked(0));
- }
-
-}
-
-void AnimationTreeEditor::_edit_filters() {
-
- filter_dialog->popup_centered_ratio();
- filter->clear();
-
- Set<String> npb;
- _find_paths_for_filter(edited_node,npb);
-
- TreeItem *root = filter->create_item();
- filter->set_hide_root(true);
- Map<String,TreeItem*> pm;
-
- Node *base = anim_tree->get_node( anim_tree->get_base_path() );
-
- for(Set<String>::Element *E=npb.front();E;E=E->next()) {
-
- TreeItem *parent=root;
- String descr=E->get();
- if (base) {
- NodePath np = E->get();
-
- if (np.get_property()!=StringName()) {
- Node *n = base->get_node(np);
- Skeleton *s = n->cast_to<Skeleton>();
- if (s) {
-
- String skelbase = E->get().substr(0,E->get().find(":"));
-
-
- int bidx = s->find_bone(np.get_property());
-
- if (bidx!=-1) {
- int bparent = s->get_bone_parent(bidx);
- //
- if (bparent!=-1) {
-
-
- String bpn = skelbase+":"+s->get_bone_name(bparent);
- if (pm.has(bpn)) {
- parent=pm[bpn];
- descr=np.get_property();
- }
- } else {
-
- if (pm.has(skelbase)) {
- parent=pm[skelbase];
-
- }
- }
- }
- }
- }
- }
-
- TreeItem *it = filter->create_item(parent);
- it->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- it->set_text(0,descr);
- it->set_metadata(0,NodePath(E->get()));
- it->set_editable(0,true);
- if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ONESHOT) {
- it->set_checked(0, anim_tree->oneshot_node_is_path_filtered(edited_node,E->get()));
- } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) {
- it->set_checked(0, anim_tree->blend2_node_is_path_filtered(edited_node,E->get()));
- } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ANIMATION) {
- it->set_checked(0, anim_tree->animation_node_is_path_filtered(edited_node,E->get()));
- }
- pm[E->get()]=it;
- }
-
-
-}
-
-void AnimationTreeEditor::_bind_methods() {
-
- ClassDB::bind_method( "_add_menu_item", &AnimationTreeEditor::_add_menu_item );
- ClassDB::bind_method( "_node_menu_item", &AnimationTreeEditor::_node_menu_item );
- ClassDB::bind_method( "_gui_input", &AnimationTreeEditor::_gui_input );
- //ClassDB::bind_method( "_node_param_changed", &AnimationTreeEditor::_node_param_changed );
- ClassDB::bind_method( "_scroll_moved", &AnimationTreeEditor::_scroll_moved );
- ClassDB::bind_method( "_edit_dialog_changeds", &AnimationTreeEditor::_edit_dialog_changeds );
- ClassDB::bind_method( "_edit_dialog_changede", &AnimationTreeEditor::_edit_dialog_changede );
- ClassDB::bind_method( "_edit_dialog_changedf", &AnimationTreeEditor::_edit_dialog_changedf );
- ClassDB::bind_method( "_edit_dialog_changed", &AnimationTreeEditor::_edit_dialog_changed );
- ClassDB::bind_method( "_edit_dialog_animation_changed", &AnimationTreeEditor::_edit_dialog_animation_changed );
- ClassDB::bind_method( "_edit_dialog_edit_animation", &AnimationTreeEditor::_edit_dialog_edit_animation );
- ClassDB::bind_method( "_play_toggled", &AnimationTreeEditor::_play_toggled );
- ClassDB::bind_method( "_edit_oneshot_start", &AnimationTreeEditor::_edit_oneshot_start );
- ClassDB::bind_method( "_file_dialog_selected", &AnimationTreeEditor::_file_dialog_selected);
- ClassDB::bind_method( "_master_anim_menu_item", &AnimationTreeEditor::_master_anim_menu_item);
- ClassDB::bind_method( "_edit_filters", &AnimationTreeEditor::_edit_filters);
- ClassDB::bind_method( "_filter_edited", &AnimationTreeEditor::_filter_edited);
-
-}
-
-AnimationTreeEditor::AnimationTreeEditor() {
-
- set_focus_mode(FOCUS_ALL);
-
- PopupMenu *p;
- List<PropertyInfo> defaults;
-
- add_menu = memnew( MenuButton );
- //add_menu->set_
- add_menu->set_pos( Point2( 0,0) );
- add_menu->set_size( Point2( 25,15) );
- add_child( add_menu );
-
- p=add_menu->get_popup();
- p->add_item(TTR("Animation Node"),AnimationTreePlayer::NODE_ANIMATION);
- p->add_item(TTR("OneShot Node"),AnimationTreePlayer::NODE_ONESHOT);
- p->add_item(TTR("Mix Node"),AnimationTreePlayer::NODE_MIX);
- p->add_item(TTR("Blend2 Node"),AnimationTreePlayer::NODE_BLEND2);
- p->add_item(TTR("Blend3 Node"),AnimationTreePlayer::NODE_BLEND3);
- p->add_item(TTR("Blend4 Node"),AnimationTreePlayer::NODE_BLEND4);
- p->add_item(TTR("TimeScale Node"),AnimationTreePlayer::NODE_TIMESCALE);
- p->add_item(TTR("TimeSeek Node"),AnimationTreePlayer::NODE_TIMESEEK);
- p->add_item(TTR("Transition Node"),AnimationTreePlayer::NODE_TRANSITION);
- p->add_separator();
- p->add_item(TTR("Import Animations.."), MENU_IMPORT_ANIMATIONS); // wtf
- p->add_separator();
- p->add_item(TTR("Clear"),MENU_GRAPH_CLEAR);
-
- p->connect("id_pressed", this,"_add_menu_item");
-
- play_button = memnew(Button);
- play_button->set_pos(Point2(25,0));
- play_button->set_size(Point2(25,15));
- add_child(play_button);
- play_button->set_toggle_mode(true);
- play_button->connect("pressed", this,"_play_toggled");
-
-
-
-
-
- last_x=50;
- last_y=50;
-
- property_editor = memnew( CustomPropertyEditor );
- add_child(property_editor);
- property_editor->connect("variant_changed", this,"_edit_dialog_animation_changed");
- property_editor->connect("resource_edit_request", this, "_edit_dialog_edit_animation");
-
- h_scroll = memnew( HScrollBar );
- v_scroll = memnew( VScrollBar );
-
- add_child(h_scroll);
- add_child(v_scroll);
-
- h_scroll->connect("value_changed", this,"_scroll_moved");
- v_scroll->connect("value_changed", this,"_scroll_moved");
-
- node_popup= memnew(PopupMenu );
- add_child(node_popup);
- node_popup->set_as_toplevel(true);
-
- master_anim_popup = memnew( PopupMenu );
- add_child(master_anim_popup);
- master_anim_popup->connect("id_pressed",this,"_master_anim_menu_item");
-
-
- node_popup->connect("id_pressed", this,"_node_menu_item");
-
- updating_edit=false;
-
- edit_dialog = memnew( PopupPanel );
- //edit_dialog->get_ok()->hide();
- //edit_dialog->get_cancel()->hide();
- add_child(edit_dialog);
-
- edit_option = memnew( OptionButton );
- edit_option->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- edit_option->set_margin(MARGIN_RIGHT, 10);
- edit_dialog->add_child(edit_option);
- edit_option->connect("item_selected", this,"_edit_dialog_changedf");
- edit_option->hide();
-
-
- for(int i=0;i<2;i++) {
- edit_scroll[i] = memnew ( HSlider );
- edit_scroll[i]->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- edit_scroll[i]->set_margin(MARGIN_RIGHT, 10);
- edit_dialog->add_child(edit_scroll[i]);
- edit_scroll[i]->hide();
- edit_scroll[i]->connect("value_changed", this,"_edit_dialog_changedf");
- }
- for(int i=0;i<4;i++) {
- edit_line[i] = memnew ( LineEdit );
- edit_line[i]->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- edit_line[i]->set_margin(MARGIN_RIGHT, 10);
- edit_dialog->add_child(edit_line[i]);
- edit_line[i]->hide();
- edit_line[i]->connect("text_changed", this,"_edit_dialog_changeds");
- edit_line[i]->connect("text_entered", this,"_edit_dialog_changede");
- edit_label[i] = memnew ( Label );
- edit_dialog->add_child(edit_label[i]);
- edit_label[i]->hide();
- }
-
- edit_button = memnew( Button );
- edit_button->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- edit_button->set_margin(MARGIN_RIGHT, 10);
- edit_dialog->add_child(edit_button);
- edit_button->hide();
- edit_button->connect("pressed", this,"_edit_oneshot_start");
-
- edit_check = memnew( CheckButton );
- edit_check->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- edit_check->set_margin(MARGIN_RIGHT, 10);
- edit_dialog->add_child(edit_check);
- edit_check->hide();
- edit_check->connect("pressed", this,"_edit_dialog_changed");
-
- file_dialog = memnew( EditorFileDialog );
- file_dialog->set_enable_multiple_selection(true);
- file_dialog->set_current_dir(GlobalConfig::get_singleton()->get_resource_path());
- add_child(file_dialog);
- file_dialog->connect("file_selected", this, "_file_dialog_selected");
-
- filter_dialog = memnew( AcceptDialog );
- filter_dialog->set_title(TTR("Edit Node Filters"));
- add_child(filter_dialog);
-
- filter = memnew( Tree );
- filter_dialog->add_child(filter);
- //filter_dialog->set_child_rect(filter);
- filter->connect("item_edited",this,"_filter_edited");
-
- filter_button = memnew( Button );
- filter_button->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- filter_button->set_margin(MARGIN_RIGHT, 10);
- edit_dialog->add_child(filter_button);
- filter_button->hide();
- filter_button->set_text(TTR("Filters.."));
- filter_button->connect("pressed", this,"_edit_filters");
-
- set_clip_contents(true);
-}
-
-
-void AnimationTreeEditorPlugin::edit(Object *p_object) {
-
- anim_tree_editor->edit(p_object->cast_to<AnimationTreePlayer>());
-
-}
-
-bool AnimationTreeEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("AnimationTreePlayer");
-}
-
-void AnimationTreeEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- //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);
- } else {
-
- if (anim_tree_editor->is_visible_in_tree())
- editor->hide_bottom_panel();
- button->hide();
- anim_tree_editor->set_fixed_process(false);
- }
-}
-
-AnimationTreeEditorPlugin::AnimationTreeEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- anim_tree_editor = memnew( AnimationTreeEditor );
- anim_tree_editor->set_custom_minimum_size(Size2(0,300));
-
- button=editor->add_bottom_panel_item("AnimationTree",anim_tree_editor);
- button->hide();
-
-
-
-}
-
-
-AnimationTreeEditorPlugin::~AnimationTreeEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/animation_tree_editor_plugin.h b/tools/editor/plugins/animation_tree_editor_plugin.h
deleted file mode 100644
index 253ad1878d..0000000000
--- a/tools/editor/plugins/animation_tree_editor_plugin.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*************************************************************************/
-/* animation_tree_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 ANIMATION_TREE_EDITOR_PLUGIN_H
-#define ANIMATION_TREE_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/animation/animation_tree_player.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/button.h"
-#include "scene/gui/popup.h"
-#include "tools/editor/property_editor.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class AnimationTreeEditor : public Control {
-
- GDCLASS(AnimationTreeEditor, Control );
-
- static const char* _node_type_names[];
-
- enum ClickType {
- CLICK_NONE,
- CLICK_NAME,
- CLICK_NODE,
- CLICK_INPUT_SLOT,
- CLICK_OUTPUT_SLOT,
- CLICK_PARAMETER
- };
-
- enum {
-
- MENU_GRAPH_CLEAR=100,
- MENU_IMPORT_ANIMATIONS=101,
- NODE_DISCONNECT,
- NODE_RENAME,
- NODE_ERASE,
- NODE_ADD_INPUT,
- NODE_DELETE_INPUT,
- NODE_SET_AUTOADVANCE,
- NODE_CLEAR_AUTOADVANCE
- };
-
- bool renaming_edit;
- StringName edited_node;
- bool updating_edit;
- Popup *edit_dialog;
- HSlider *edit_scroll[2];
- LineEdit *edit_line[4];
- OptionButton *edit_option;
- Label *edit_label[4];
- Button *edit_button;
- Button *filter_button;
- CheckButton *edit_check;
- EditorFileDialog* file_dialog;
- int file_op;
-
- void _popup_edit_dialog();
-
-
- void _setup_edit_dialog(const StringName& p_node);
- PopupMenu *master_anim_popup;
- PopupMenu *node_popup;
- PopupMenu *add_popup;
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
- MenuButton* add_menu;
-
- CustomPropertyEditor *property_editor;
-
- AnimationTreePlayer* anim_tree;
- List<StringName> order;
- Set<StringName> active_nodes;
-
- int last_x,last_y;
-
- Point2 offset;
- ClickType click_type;
- Point2 click_pos;
- StringName click_node;
- int click_slot;
- Point2 click_motion;
- ClickType rclick_type;
- StringName rclick_node;
- int rclick_slot;
-
- Button *play_button;
-
- Size2 _get_maximum_size();
- Size2 get_node_size(const StringName &p_node) const;
- void _draw_node(const StringName& p_node);
-
- AcceptDialog *filter_dialog;
- Tree *filter;
-
-
-
- void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color);
- void _update_scrollbars();
- void _scroll_moved(float);
- void _play_toggled();
-/*
- void _node_param_changed();
- void _node_add_callback();
- void _node_add(VisualServer::AnimationTreeNodeType p_type);
- void _node_edit_property(const StringName& p_node);
-*/
-
- void _master_anim_menu_item(int p_item);
- void _node_menu_item(int p_item);
- void _add_menu_item(int p_item);
-
-
- void _filter_edited();
- void _find_paths_for_filter(const StringName& p_node,Set<String>& paths);
- void _edit_filters();
-
-
- void _edit_oneshot_start();
- void _edit_dialog_animation_changed();
- void _edit_dialog_edit_animation();
- void _edit_dialog_changeds(String);
- void _edit_dialog_changede(String);
- void _edit_dialog_changedf(float);
- void _edit_dialog_changed();
- void _dialog_changed() const;
- ClickType _locate_click(const Point2& p_click,StringName *p_node_id,int *p_slot_index) const;
- Point2 _get_slot_pos(const StringName& p_node_id,bool p_input,int p_slot);
-
- StringName _add_node(int p_item);
- void _file_dialog_selected(String p_path);
-
-
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
-
- virtual Size2 get_minimum_size() const;
- void edit(AnimationTreePlayer *p_player);
- AnimationTreeEditor();
-};
-
-class AnimationTreeEditorPlugin : public EditorPlugin {
-
- GDCLASS( AnimationTreeEditorPlugin, EditorPlugin );
-
- AnimationTreeEditor *anim_tree_editor;
- EditorNode *editor;
- Button *button;
-
-public:
-
- virtual String get_name() const { return "AnimTree"; }
- 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);
-
- AnimationTreeEditorPlugin(EditorNode *p_node);
- ~AnimationTreeEditorPlugin();
-
-};
-
-#endif // ANIMATION_TREE_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp
deleted file mode 100644
index 52220839d9..0000000000
--- a/tools/editor/plugins/baked_light_baker.cpp
+++ /dev/null
@@ -1,2731 +0,0 @@
-/*************************************************************************/
-/* baked_light_baker.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "baked_light_baker.h"
-
-#include <stdlib.h>
-#include <cmath>
-#include "io/marshalls.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/editor_settings.h"
-
-#if 0
-void baked_light_baker_add_64f(double *dst,double value);
-void baked_light_baker_add_64i(int64_t *dst,int64_t value);
-
-//-separar en 2 testuras?
-//*mejorar performance y threads
-//*modos lineales
-//*saturacion
-
-_FORCE_INLINE_ static uint64_t get_uv_normal_bit(const Vector3& p_vector) {
-
- int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*6.0/Math_PI+0.5));
-
- if (lat==0) {
- return 60;
- } else if (lat==6) {
- return 61;
- }
-
- int lon = Math::fast_ftoi(Math::floor( (Math_PI+Math::atan2(p_vector.x,p_vector.z))*12.0/(Math_PI*2.0) + 0.5))%12;
-
- return lon+(lat-1)*12;
-}
-
-
-
-_FORCE_INLINE_ static Vector3 get_bit_normal(int p_bit) {
-
- if (p_bit==61) {
- return Vector3(0,1,0);
- } else if (p_bit==62){
- return Vector3(0,-1,0);
- }
-
- float latang = ((p_bit / 12)+1)*Math_PI/6.0;
-
- Vector2 latv(Math::sin(latang),Math::cos(latang));
-
- float lonang = ((p_bit%12)*Math_PI*2.0/12.0)-Math_PI;
-
- Vector2 lonv(Math::sin(lonang),Math::cos(lonang));
-
- return Vector3(lonv.x*latv.x,latv.y,lonv.y*latv.x).normalized();
-
-}
-
-
-BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>& p_tex) {
-
- if (!tex_map.has(p_tex)) {
-
- Ref<ImageTexture> imgtex=p_tex;
- if (imgtex.is_null())
- return NULL;
- Image image=imgtex->get_data();
- if (image.empty())
- return NULL;
-
- if (image.get_format()!=Image::FORMAT_RGBA8) {
- if (image.get_format()>Image::FORMAT_INDEXED_ALPHA) {
- Error err = image.decompress();
- if (err)
- return NULL;
- }
-
- if (image.get_format()!=Image::FORMAT_RGBA8)
- image.convert(Image::FORMAT_RGBA8);
- }
-
- if (imgtex->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR) {
- Image copy = image;
- copy.srgb_to_linear();
- image=copy;
- }
-
- PoolVector<uint8_t> dvt=image.get_data();
- PoolVector<uint8_t>::Read r=dvt.read();
- MeshTexture mt;
- mt.tex_w=image.get_width();
- mt.tex_h=image.get_height();
- int len = image.get_width()*image.get_height()*4;
- mt.tex.resize(len);
- copymem(mt.tex.ptr(),r.ptr(),len);
-
- textures.push_back(mt);
- tex_map[p_tex]=&textures.back()->get();
- }
-
- return tex_map[p_tex];
-}
-
-
-void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform,int p_baked_texture) {
-
-
- for(int i=0;i<p_mesh->get_surface_count();i++) {
-
- if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES)
- continue;
- Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i);
-
- MeshMaterial *matptr=NULL;
- int baked_tex=p_baked_texture;
-
- if (mat.is_valid()) {
-
- if (!mat_map.has(mat)) {
-
- MeshMaterial mm;
-
- Ref<FixedSpatialMaterial> fm = mat;
- if (fm.is_valid()) {
- //fixed route
- mm.diffuse.color=fm->get_parameter(FixedSpatialMaterial::PARAM_DIFFUSE);
- if (linear_color)
- mm.diffuse.color=mm.diffuse.color.to_linear();
- mm.diffuse.tex=_get_mat_tex(fm->get_texture(FixedSpatialMaterial::PARAM_DIFFUSE));
- mm.specular.color=fm->get_parameter(FixedSpatialMaterial::PARAM_SPECULAR);
- if (linear_color)
- mm.specular.color=mm.specular.color.to_linear();
-
- mm.specular.tex=_get_mat_tex(fm->get_texture(FixedSpatialMaterial::PARAM_SPECULAR));
- } else {
-
- mm.diffuse.color=Color(1,1,1,1);
- mm.diffuse.tex=NULL;
- mm.specular.color=Color(0,0,0,1);
- mm.specular.tex=NULL;
- }
-
- materials.push_back(mm);
- mat_map[mat]=&materials.back()->get();
-
- }
-
- matptr=mat_map[mat];
-
- }
-
-
- int facecount=0;
-
-
- if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) {
-
- facecount=p_mesh->surface_get_array_index_len(i);
- } else {
-
- facecount=p_mesh->surface_get_array_len(i);
- }
-
- ERR_CONTINUE((facecount==0 || (facecount%3)!=0));
-
- facecount/=3;
-
- int tbase=triangles.size();
- triangles.resize(facecount+tbase);
-
-
- Array a = p_mesh->surface_get_arrays(i);
-
- PoolVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
- PoolVector<Vector3>::Read vr=vertices.read();
- PoolVector<Vector2> uv;
- PoolVector<Vector2>::Read uvr;
- PoolVector<Vector2> uv2;
- PoolVector<Vector2>::Read uv2r;
- PoolVector<Vector3> normal;
- PoolVector<Vector3>::Read normalr;
- bool read_uv=false;
- bool read_normal=false;
-
- if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV) {
-
- uv=a[Mesh::ARRAY_TEX_UV];
- uvr=uv.read();
- read_uv=true;
-
- if (mat.is_valid() && mat->get_flag(Material::FLAG_LIGHTMAP_ON_UV2) && p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
-
- uv2=a[Mesh::ARRAY_TEX_UV2];
- uv2r=uv2.read();
-
- } else {
- uv2r=uv.read();
- if (baked_light->get_transfer_lightmaps_only_to_uv2()) {
- baked_tex=-1;
- }
- }
- }
-
- if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_NORMAL) {
-
- normal=a[Mesh::ARRAY_NORMAL];
- normalr=normal.read();
- read_normal=true;
- }
-
- Matrix3 normal_xform = p_xform.basis.inverse().transposed();
-
-
- if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) {
-
- PoolVector<int> indices = a[Mesh::ARRAY_INDEX];
- PoolVector<int>::Read ir = indices.read();
-
- for(int i=0;i<facecount;i++) {
- Triangle &t=triangles[tbase+i];
- t.vertices[0]=p_xform.xform(vr[ ir[i*3+0] ]);
- t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]);
- t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]);
- t.material=matptr;
- t.baked_texture=baked_tex;
- if (read_uv) {
-
- t.uvs[0]=uvr[ ir[i*3+0] ];
- t.uvs[1]=uvr[ ir[i*3+1] ];
- t.uvs[2]=uvr[ ir[i*3+2] ];
-
- t.bake_uvs[0]=uv2r[ ir[i*3+0] ];
- t.bake_uvs[1]=uv2r[ ir[i*3+1] ];
- t.bake_uvs[2]=uv2r[ ir[i*3+2] ];
- }
- if (read_normal) {
-
- t.normals[0]=normal_xform.xform(normalr[ ir[i*3+0] ]).normalized();
- t.normals[1]=normal_xform.xform(normalr[ ir[i*3+1] ]).normalized();
- t.normals[2]=normal_xform.xform(normalr[ ir[i*3+2] ]).normalized();
- }
- }
-
- } else {
-
- for(int i=0;i<facecount;i++) {
- Triangle &t=triangles[tbase+i];
- t.vertices[0]=p_xform.xform(vr[ i*3+0 ]);
- t.vertices[1]=p_xform.xform(vr[ i*3+1 ]);
- t.vertices[2]=p_xform.xform(vr[ i*3+2 ]);
- t.material=matptr;
- t.baked_texture=baked_tex;
- if (read_uv) {
-
- t.uvs[0]=uvr[ i*3+0 ];
- t.uvs[1]=uvr[ i*3+1 ];
- t.uvs[2]=uvr[ i*3+2 ];
-
- t.bake_uvs[0]=uv2r[ i*3+0 ];
- t.bake_uvs[1]=uv2r[ i*3+1 ];
- t.bake_uvs[2]=uv2r[ i*3+2 ];
-
- }
- if (read_normal) {
-
- t.normals[0]=normal_xform.xform(normalr[ i*3+0 ]).normalized();
- t.normals[1]=normal_xform.xform(normalr[ i*3+1 ]).normalized();
- t.normals[2]=normal_xform.xform(normalr[ i*3+2 ]).normalized();
- }
- }
- }
- }
-
-}
-
-
-void BakedLightBaker::_parse_geometry(Node* p_node) {
-
- if (p_node->cast_to<MeshInstance>()) {
-
- MeshInstance *meshi=p_node->cast_to<MeshInstance>();
- Ref<Mesh> mesh=meshi->get_mesh();
- if (mesh.is_valid()) {
- _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform(),meshi->get_baked_light_texture_id());
- }
- } else if (p_node->cast_to<Light>()) {
-
- Light *dl=p_node->cast_to<Light>();
-
- if (dl->get_bake_mode()!=Light::BAKE_MODE_DISABLED) {
-
-
- LightData dirl;
- dirl.type=VS::LightType(dl->get_light_type());
- dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE);
- dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR);
- if (linear_color)
- dirl.diffuse=dirl.diffuse.to_linear();
- if (linear_color)
- dirl.specular=dirl.specular.to_linear();
-
- dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY);
- dirl.pos=dl->get_global_transform().origin;
- dirl.up=dl->get_global_transform().basis.get_axis(1).normalized();
- dirl.left=dl->get_global_transform().basis.get_axis(0).normalized();
- dirl.dir=-dl->get_global_transform().basis.get_axis(2).normalized();
- dirl.spot_angle=dl->get_parameter(DirectionalLight::PARAM_SPOT_ANGLE);
- dirl.spot_attenuation=dl->get_parameter(DirectionalLight::PARAM_SPOT_ATTENUATION);
- dirl.attenuation=dl->get_parameter(DirectionalLight::PARAM_ATTENUATION);
- dirl.darkening=dl->get_parameter(DirectionalLight::PARAM_SHADOW_DARKENING);
- dirl.radius=dl->get_parameter(DirectionalLight::PARAM_RADIUS);
- dirl.bake_direct=dl->get_bake_mode()==Light::BAKE_MODE_FULL;
- dirl.rays_thrown=0;
- dirl.bake_shadow=dl->get_bake_mode()==Light::BAKE_MODE_INDIRECT_AND_SHADOWS;
- lights.push_back(dirl);
- }
-
- } else if (p_node->cast_to<Spatial>()){
-
- Spatial *sp = p_node->cast_to<Spatial>();
-
- Array arr = p_node->call("_get_baked_light_meshes");
- for(int i=0;i<arr.size();i+=2) {
-
- Transform xform=arr[i];
- Ref<Mesh> mesh=arr[i+1];
- _add_mesh(mesh,Ref<Material>(),base_inv * (sp->get_global_transform() * xform));
- }
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- _parse_geometry(p_node->get_child(i));
- }
-}
-
-
-void BakedLightBaker::_fix_lights() {
-
-
- total_light_area=0;
- for(int i=0;i<lights.size();i++) {
-
- LightData &dl=lights[i];
-
- switch(dl.type) {
- case VS::LIGHT_DIRECTIONAL: {
-
- float up_max=-1e10;
- float dir_max=-1e10;
- float left_max=-1e10;
- float up_min=1e10;
- float dir_min=1e10;
- float left_min=1e10;
-
- for(int j=0;j<triangles.size();j++) {
-
- for(int k=0;k<3;k++) {
-
- Vector3 v = triangles[j].vertices[k];
-
- float up_d = dl.up.dot(v);
- float dir_d = dl.dir.dot(v);
- float left_d = dl.left.dot(v);
-
- if (up_d>up_max)
- up_max=up_d;
- if (up_d<up_min)
- up_min=up_d;
-
- if (left_d>left_max)
- left_max=left_d;
- if (left_d<left_min)
- left_min=left_d;
-
- if (dir_d>dir_max)
- dir_max=dir_d;
- if (dir_d<dir_min)
- dir_min=dir_d;
-
- }
- }
-
- //make a center point, then the upvector and leftvector
- dl.pos = dl.left*( left_max+left_min )*0.5 + dl.up*( up_max+up_min )*0.5 + dl.dir*(dir_min-(dir_max-dir_min));
- dl.left*=(left_max-left_min)*0.5;
- dl.up*=(up_max-up_min)*0.5;
- dl.length = (dir_max - dir_min)*10; //arbitrary number to keep it in scale
- dl.area=dl.left.length()*2*dl.up.length()*2;
- dl.constant=1.0/dl.area;
- } break;
- case VS::LIGHT_OMNI:
- case VS::LIGHT_SPOT: {
-
- dl.attenuation_table.resize(ATTENUATION_CURVE_LEN);
- for(int j=0;j<ATTENUATION_CURVE_LEN;j++) {
- dl.attenuation_table[j]=1.0-Math::pow(j/float(ATTENUATION_CURVE_LEN),dl.attenuation);
- float falloff=j*dl.radius/float(ATTENUATION_CURVE_LEN);
- if (falloff==0)
- falloff=0.000001;
- float intensity=4*Math_PI*(falloff*falloff);
- //dl.attenuation_table[j]*=falloff*falloff;
- dl.attenuation_table[j]*=1.0/(3.0/intensity);
-
- }
- if (dl.type==VS::LIGHT_OMNI) {
-
- dl.area=4.0*Math_PI*pow(dl.radius,2.0f);
- dl.constant=1.0/3.5;
- } else {
-
-
- float r = Math::tan(Math::deg2rad(dl.spot_angle))*dl.radius;
- float c = 1.0-(Math::deg2rad(dl.spot_angle)*0.5+0.5);
- dl.constant=1.0/3.5;
- dl.constant*=1.0/c;
-
- dl.area=Math_PI*r*r*c;
- }
-
- } break;
-
-
- }
-
- total_light_area+=dl.area;
- }
-}
-
-BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size, int p_depth, int &max_depth) {
-
- if (p_depth>max_depth) {
- max_depth=p_depth;
- }
-
- if (p_size==1) {
-
- return p_children[0];
- } else if (p_size==0) {
-
- return NULL;
- }
-
-
- AABB aabb;
- aabb=p_children[0]->aabb;
- for(int i=1;i<p_size;i++) {
-
- aabb.merge_with(p_children[i]->aabb);
- }
-
- int li=aabb.get_longest_axis_index();
-
- switch(li) {
-
- case Vector3::AXIS_X: {
- SortArray<BVH*,BVHCmpX> sort_x;
- sort_x.nth_element(0,p_size,p_size/2,p_children);
- //sort_x.sort(&p_bb[p_from],p_size);
- } break;
- case Vector3::AXIS_Y: {
- SortArray<BVH*,BVHCmpY> sort_y;
- sort_y.nth_element(0,p_size,p_size/2,p_children);
- //sort_y.sort(&p_bb[p_from],p_size);
- } break;
- case Vector3::AXIS_Z: {
- SortArray<BVH*,BVHCmpZ> sort_z;
- sort_z.nth_element(0,p_size,p_size/2,p_children);
- //sort_z.sort(&p_bb[p_from],p_size);
-
- } break;
- }
-
-
- BVH* left = _parse_bvh(p_children,p_size/2,p_depth+1,max_depth);
- BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth);
-
- BVH *_new = memnew(BVH);
- _new->aabb=aabb;
- _new->center=aabb.pos+aabb.size*0.5;
- _new->children[0]=left;
- _new->children[1]=right;
- _new->leaf=NULL;
-
- return _new;
-}
-
-void BakedLightBaker::_make_bvh() {
-
- Vector<BVH*> bases;
- bases.resize(triangles.size());
- int max_depth=0;
- for(int i=0;i<triangles.size();i++) {
- bases[i]=memnew( BVH );
- bases[i]->leaf=&triangles[i];
- bases[i]->aabb.pos=triangles[i].vertices[0];
- bases[i]->aabb.expand_to(triangles[i].vertices[1]);
- bases[i]->aabb.expand_to(triangles[i].vertices[2]);
- triangles[i].aabb=bases[i]->aabb;
- bases[i]->center=bases[i]->aabb.pos+bases[i]->aabb.size*0.5;
- }
-
- bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth);
-
- ray_stack = memnew_arr(uint32_t,max_depth);
- bvh_stack = memnew_arr(BVH*,max_depth);
-
- bvh_depth = max_depth;
-}
-
-void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_depth) {
-
-
-
-
- uint32_t *stack=octant_stack;
- uint32_t *ptr_stack=octantptr_stack;
- Octant *octants=octant_pool.ptr();
-
- stack[0]=0;
- ptr_stack[0]=0;
-
- int stack_pos=0;
-
-
- while(true) {
-
- Octant *octant=&octants[ptr_stack[stack_pos]];
- if (stack[stack_pos]<8) {
-
- int i = stack[stack_pos];
- stack[stack_pos]++;
-
-
-
- //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001);
-
- int child_idx =octant->children[i];
- bool encloses;
- if (!child_idx) {
-
- AABB aabb=octant->aabb;
- aabb.size*=0.5;
- if (i&1)
- aabb.pos.x+=aabb.size.x;
- if (i&2)
- aabb.pos.y+=aabb.size.y;
- if (i&4)
- aabb.pos.z+=aabb.size.z;
-
- aabb.grow_by(cell_size*octree_extra_margin);
- if (!aabb.intersects(p_triangle->aabb))
- continue;
- encloses=aabb.grow(cell_size*-octree_extra_margin*2.0).encloses(p_triangle->aabb);
- if (!encloses && !Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb2(aabb))
- continue;
- } else {
-
- Octant *child=&octants[child_idx];
- AABB aabb=child->aabb;
- aabb.grow_by(cell_size*octree_extra_margin);
- if (!aabb.intersects(p_triangle->aabb))
- continue;
- encloses=aabb.grow(cell_size*-octree_extra_margin*2.0).encloses(p_triangle->aabb);
- if (!encloses && !Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb2(aabb))
- continue;
-
- }
-
- if (encloses)
- stack[stack_pos]=8; // quick and dirty opt
-
- if (!child_idx) {
-
-
- if (octant_pool_size==octant_pool.size()) {
- octant_pool.resize(octant_pool_size+OCTANT_POOL_CHUNK);
- octants=octant_pool.ptr();
- octant=&octants[ptr_stack[stack_pos]];
- }
- child_idx=octant_pool_size++;
- octant->children[i]=child_idx;
- Octant *child=&octants[child_idx];
-
- child->aabb=octant->aabb;
- child->texture_x=0;
- child->texture_y=0;
-
- child->aabb.size*=0.5;
- if (i&1)
- child->aabb.pos.x+=child->aabb.size.x;
- if (i&2)
- child->aabb.pos.y+=child->aabb.size.y;
- if (i&4)
- child->aabb.pos.z+=child->aabb.size.z;
-
-
- child->full_accum[0]=0;
- child->full_accum[1]=0;
- child->full_accum[2]=0;
- child->sampler_ofs=0;
-
-
-
- if (stack_pos==octree_depth-1) {
- child->leaf=true;
- child->offset[0]=child->aabb.pos.x+child->aabb.size.x*0.5;
- child->offset[1]=child->aabb.pos.y+child->aabb.size.y*0.5;
- child->offset[2]=child->aabb.pos.z+child->aabb.size.z*0.5;
- child->next_leaf=leaf_list;
-
-
- for(int ci=0;ci<8;ci++) {
- child->normal_accum[ci][0]=0;
- child->normal_accum[ci][1]=0;
- child->normal_accum[ci][2]=0;
-
- }
-
- child->bake_neighbour=0;
- child->first_neighbour=true;
- leaf_list=child_idx;
- cell_count++;
-
- for(int ci=0;ci<8;ci++) {
- child->light_accum[ci][0]=0;
- child->light_accum[ci][1]=0;
- child->light_accum[ci][2]=0;
- }
-
- child->parent=ptr_stack[stack_pos];
-
- } else {
-
- child->leaf=false;
- for(int j=0;j<8;j++) {
- child->children[j]=0;
- }
- }
- }
-
- if (!octants[child_idx].leaf) {
- stack_pos++;
- stack[stack_pos]=0;
- ptr_stack[stack_pos]=child_idx;
- } else {
-
- Octant *child=&octants[child_idx];
-
- Vector3 n = Plane(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).normal;
-
-
- for(int ci=0;ci<8;ci++) {
-
- Vector3 pos = child->aabb.pos;
-
- if (ci&1)
- pos.x+=child->aabb.size.x;
- if (ci&2)
- pos.y+=child->aabb.size.y;
- if (ci&4)
- pos.z+=child->aabb.size.z;
-
-
- pos.x=floor((pos.x+cell_size*0.5)/cell_size);
- pos.y=floor((pos.y+cell_size*0.5)/cell_size);
- pos.z=floor((pos.z+cell_size*0.5)/cell_size);
-
- {
- Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
- if (!E) {
- endpoint_normal[pos]=n;
- } else {
- E->get()+=n;
- }
- }
-
- {
-
- uint64_t bit = get_uv_normal_bit(n);
-
- Map<Vector3,uint64_t>::Element *E=endpoint_normal_bits.find(pos);
- if (!E) {
- endpoint_normal_bits[pos]=(1<<bit);
- } else {
- E->get()|=(1<<bit);
- }
-
- }
-
- }
-
- }
-
-
- } else {
- stack_pos--;
- if (stack_pos<0)
- break;
- }
- }
-
-
-}
-
-
-void BakedLightBaker::_make_octree() {
-
-
- AABB base = bvh->aabb;
- float lal=base.get_longest_axis_size();
- //must be square because we want square blocks
- base.size.x=lal;
- base.size.y=lal;
- base.size.z=lal;
- base.grow_by(lal*0.001); //for precision
- octree_aabb=base;
-
- cell_size=base.size.x;
- for(int i=0;i<octree_depth;i++)
- cell_size/=2.0;
- octant_stack = memnew_arr(uint32_t,octree_depth*2 );
- octantptr_stack = memnew_arr(uint32_t,octree_depth*2 );
-
- octant_pool.resize(OCTANT_POOL_CHUNK);
- octant_pool_size=1;
- Octant *root=octant_pool.ptr();
- root->leaf=false;
- root->aabb=octree_aabb;
- root->parent=-1;
- for(int i=0;i<8;i++)
- root->children[i]=0;
-
- EditorProgress ep("bake_octree",vformat(TTR("Parsing %d Triangles:"), triangles.size()),triangles.size());
-
- for(int i=0;i<triangles.size();i++) {
-
- _octree_insert(0,&triangles[i],octree_depth-1);
- if ((i%1000)==0) {
-
- ep.step(TTR("Triangle #")+itos(i),i);
- }
- }
-
- {
- uint32_t oct_idx=leaf_list;
- Octant *octants=octant_pool.ptr();
- while(oct_idx) {
-
- BakedLightBaker::Octant *oct = &octants[oct_idx];
- for(int ci=0;ci<8;ci++) {
-
-
- Vector3 pos = oct->aabb.pos;
-
- if (ci&1)
- pos.x+=oct->aabb.size.x;
- if (ci&2)
- pos.y+=oct->aabb.size.y;
- if (ci&4)
- pos.z+=oct->aabb.size.z;
-
-
- pos.x=floor((pos.x+cell_size*0.5)/cell_size);
- pos.y=floor((pos.y+cell_size*0.5)/cell_size);
- pos.z=floor((pos.z+cell_size*0.5)/cell_size);
-
- {
- Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos);
- if (!E) {
- //?
- print_line("lolwut?");
- } else {
- Vector3 n = E->get().normalized();
- oct->normal_accum[ci][0]=n.x;
- oct->normal_accum[ci][1]=n.y;
- oct->normal_accum[ci][2]=n.z;
-
- }
-
- }
-
- {
-
- Map<Vector3,uint64_t>::Element *E=endpoint_normal_bits.find(pos);
- if (!E) {
- //?
- print_line("lolwut?");
- } else {
-
- float max_aper=0;
- for(uint64_t i=0;i<62;i++) {
-
- if (!(E->get()&(1<<i)))
- continue;
- Vector3 ang_i = get_bit_normal(i);
-
- for(uint64_t j=0;j<62;j++) {
-
- if (i==j)
- continue;
- if (!(E->get()&(1<<j)))
- continue;
- Vector3 ang_j = get_bit_normal(j);
- float ang = Math::acos(ang_i.dot(ang_j));
- if (ang>max_aper)
- max_aper=ang;
- }
- }
- if (max_aper>0.75*Math_PI) {
- //angle too wide prevent problems and forget
- oct->normal_accum[ci][0]=0;
- oct->normal_accum[ci][1]=0;
- oct->normal_accum[ci][2]=0;
- }
- }
- }
-
-
- }
-
- oct_idx=oct->next_leaf;
- }
- }
-
-
-}
-
-
-
-
-
-void BakedLightBaker::_plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light,const Color& p_tint_light,bool p_only_full, const Plane& p_plane) {
-
- //stackless version
-
- uint32_t *stack=thread_stack.octant_stack;
- uint32_t *ptr_stack=thread_stack.octantptr_stack;
- Octant *octants=octant_pool.ptr();
-
- stack[0]=0;
- ptr_stack[0]=0;
-
- int stack_pos=0;
-
-
- while(true) {
-
- Octant &octant=octants[ptr_stack[stack_pos]];
-
- if (stack[stack_pos]==0) {
-
-
- Vector3 pos = octant.aabb.pos + octant.aabb.size*0.5;
- float md = 1<<(octree_depth - stack_pos );
- float r=cell_size*plot_size*md;
- float div = 1.0/(md*md*md);
- //div=1.0;
-
-
- float d = p_plot_pos.distance_to(pos);
-
- if ((p_plane.distance_to(pos)>-cell_size*1.75*md) && d<=r) {
-
-
- float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
-
- baked_light_baker_add_64f(&octant.full_accum[0],p_tint_light.r*intensity*div);
- baked_light_baker_add_64f(&octant.full_accum[1],p_tint_light.g*intensity*div);
- baked_light_baker_add_64f(&octant.full_accum[2],p_tint_light.b*intensity*div);
- }
- }
-
- if (octant.leaf) {
-
-
-
- //if (p_plane.normal.dot(octant.aabb.get_support(p_plane.normal)) < p_plane.d-CMP_EPSILON) { //octants behind are no go
-
-
- if (!p_only_full) {
- float r=cell_size*plot_size;
- for(int i=0;i<8;i++) {
- Vector3 pos=octant.aabb.pos;
- if (i&1)
- pos.x+=octant.aabb.size.x;
- if (i&2)
- pos.y+=octant.aabb.size.y;
- if (i&4)
- pos.z+=octant.aabb.size.z;
-
-
-
- float d = p_plot_pos.distance_to(pos);
-
- if ((p_plane.distance_to(pos)>-cell_size*1.75) && d<=r) {
-
-
- float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
- if (edge_damp>0) {
- Vector3 normal = Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]);
- if (normal.x>0 || normal.y>0 || normal.z>0) {
-
- float damp = Math::abs(p_plane.normal.dot(normal));
- intensity*=pow(damp,edge_damp);
-
- }
- }
-
- //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size);
- //intensity = Math::cos(d*Math_PI*0.5/r);
-
- baked_light_baker_add_64f(&octant.light_accum[i][0],p_light.r*intensity);
- baked_light_baker_add_64f(&octant.light_accum[i][1],p_light.g*intensity);
- baked_light_baker_add_64f(&octant.light_accum[i][2],p_light.b*intensity);
-
-
- }
- }
- }
-
- stack_pos--;
- } else if (stack[stack_pos]<8) {
-
- int i = stack[stack_pos];
- stack[stack_pos]++;
-
- if (!octant.children[i]) {
- continue;
- }
-
- Octant &child=octants[octant.children[i]];
-
- if (!child.aabb.intersects(p_plot_aabb))
- continue;
-
- if (child.aabb.encloses(p_plot_aabb)) {
- stack[stack_pos]=8; //don't test the rest
- }
-
- stack_pos++;
- stack[stack_pos]=0;
- ptr_stack[stack_pos]=octant.children[i];
- } else {
- stack_pos--;
- if (stack_pos<0)
- break;
- }
- }
-
-
-}
-
-
-float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) {
-
-
- uint32_t* stack = thread_stack.ray_stack;
- BVH **bstack = thread_stack.bvh_stack;
-
- enum {
- TEST_AABB_BIT=0,
- VISIT_LEFT_BIT=1,
- VISIT_RIGHT_BIT=2,
- VISIT_DONE_BIT=3,
-
-
- };
-
- Vector3 n = (p_end-p_begin);
- float len=n.length();
- if (len==0)
- return 0;
- n/=len;
-
-
-
- real_t d=1e10;
- bool inters=false;
- Vector3 r_normal;
- Vector3 r_point;
- Vector3 end=p_end;
-
- Triangle *triangle=NULL;
-
- /*
- for(int i=0;i<max_depth;i++)
- stack[i]=0;
- */
-
- int level=0;
- //AABB ray_aabb;
- //ray_aabb.pos=p_begin;
- //ray_aabb.expand_to(p_end);
-
-
- bstack[0]=bvh;
- stack[0]=TEST_AABB_BIT;
-
-
- while(true) {
-
- uint32_t mode = stack[level];
- const BVH &b = *bstack[level];
- bool done=false;
-
- switch(mode) {
- case TEST_AABB_BIT: {
-
- if (b.leaf) {
-
-
- Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
-
-
- Vector3 res;
-
- if (f3.intersects_segment(p_begin,end,&res)) {
-
-
- float nd = n.dot(res);
- if (nd<d) {
-
- d=nd;
- r_point=res;
- end=res;
- len=(p_begin-end).length();
- r_normal=f3.get_plane().get_normal();
- triangle=b.leaf;
- inters=true;
- }
-
- }
-
- stack[level]=VISIT_DONE_BIT;
- } else {
-
-
- bool valid = b.aabb.smits_intersect_ray(p_begin,n,0,len);
- //bool valid = b.aabb.intersects_segment(p_begin,p_end);
- //bool valid = b.aabb.intersects(ray_aabb);
-
- if (!valid) {
-
- stack[level]=VISIT_DONE_BIT;
-
- } else {
-
- stack[level]=VISIT_LEFT_BIT;
- }
- }
-
- } continue;
- case VISIT_LEFT_BIT: {
-
- stack[level]=VISIT_RIGHT_BIT;
- bstack[level+1]=b.children[0];
- stack[level+1]=TEST_AABB_BIT;
- level++;
-
- } continue;
- case VISIT_RIGHT_BIT: {
-
- stack[level]=VISIT_DONE_BIT;
- bstack[level+1]=b.children[1];
- stack[level+1]=TEST_AABB_BIT;
- level++;
- } continue;
- case VISIT_DONE_BIT: {
-
- if (level==0) {
- done=true;
- break;
- } else
- level--;
-
- } continue;
- }
-
-
- if (done)
- break;
- }
-
-
-
- if (inters) {
-
- if (p_only_dist) {
-
- return p_begin.distance_to(r_point);
- }
-
-
- //should check if there is normals first
- Vector2 uv;
- if (true) {
-
- triangle->get_uv_and_normal(r_point,uv,r_normal);
-
- } else {
-
- }
-
- if (n.dot(r_normal)>0)
- return -1;
-
- if (n.dot(r_normal)>0)
- r_normal=-r_normal;
-
-
- //ok...
- Color diffuse_at_point(0.8,0.8,0.8);
- Color specular_at_point(0.0,0.0,0.0);
-
-
- float dist = p_begin.distance_to(r_point);
-
- AABB aabb;
- aabb.pos=r_point;
- aabb.pos-=Vector3(1,1,1)*cell_size*plot_size;
- aabb.size=Vector3(2,2,2)*cell_size*plot_size;
-
- Color res_light=p_light;
- float att=1.0;
- float dp=(1.0-normal_damp)*n.dot(-r_normal)+normal_damp;
-
- if (p_att_curve) {
-
- p_att_pos+=dist;
- int cpos = Math::fast_ftoi((p_att_pos/p_att_curve_len)*ATTENUATION_CURVE_LEN);
- cpos=CLAMP(cpos,0,ATTENUATION_CURVE_LEN-1);
- att=p_att_curve[cpos];
- }
-
-
- res_light.r*=dp;
- res_light.g*=dp;
- res_light.b*=dp;
-
- //light is plotted before multiplication with diffuse, this way
- //the multiplication can happen with more detail in the shader
-
-
-
- if (triangle->material) {
-
- //triangle->get_uv(r_point);
-
- diffuse_at_point=triangle->material->diffuse.get_color(uv);
- specular_at_point=triangle->material->specular.get_color(uv);
- }
-
-
- diffuse_at_point.r=res_light.r*diffuse_at_point.r;
- diffuse_at_point.g=res_light.g*diffuse_at_point.g;
- diffuse_at_point.b=res_light.b*diffuse_at_point.b;
-
- if (p_bounces>0) {
-
-
- p_rest-=dist;
- if (p_rest<CMP_EPSILON)
- return 0;
-
- if (r_normal==-n)
- return 0; //todo change a little
-
- r_point+=r_normal*0.01;
-
-
-
-
- specular_at_point.r=res_light.r*specular_at_point.r;
- specular_at_point.g=res_light.g*specular_at_point.g;
- specular_at_point.b=res_light.b*specular_at_point.b;
-
-
-
- if (use_diffuse && (diffuse_at_point.r>CMP_EPSILON || diffuse_at_point.g>CMP_EPSILON || diffuse_at_point.b>CMP_EPSILON)) {
- //diffuse bounce
-
- Vector3 c1=r_normal.cross(n).normalized();
- Vector3 c2=r_normal.cross(c1).normalized();
- double r1 = double(rand())/RAND_MAX;
- double r2 = double(rand())/RAND_MAX;
- double r3 = double(rand())/RAND_MAX;
-#if 0
- Vector3 next = - ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*(r3-0.5))).normalized()*0.5 + r_normal*0.5;
-
- if (next==Vector3())
- next=r_normal;
- Vector3 rn=next.normalized();
-
-#else
- Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.5)).normalized();
-#endif
-
-
- _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1);
- }
-
- if (use_specular && (specular_at_point.r>CMP_EPSILON || specular_at_point.g>CMP_EPSILON || specular_at_point.b>CMP_EPSILON)) {
- //specular bounce
-
- //Vector3 c1=r_normal.cross(n).normalized();
- //Vector3 c2=r_normal.cross(c1).normalized();
-
- Vector3 rn = n - r_normal *r_normal.dot(n) * 2.0;
-
- _throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1);
- }
- }
-
- //specular later
- //_plot_light_point(r_point,octree,octree_aabb,p_light);
-
-
- Color plot_light=res_light.linear_interpolate(diffuse_at_point,tint);
- plot_light.r*=att;
- plot_light.g*=att;
- plot_light.b*=att;
- Color tint_light=diffuse_at_point;
- tint_light.r*=att;
- tint_light.g*=att;
- tint_light.b*=att;
-
- bool skip=false;
-
- if (!p_first_bounce || p_bake_direct) {
-
-
- float r = plot_size * cell_size*2;
- if (dist<r) {
- //avoid accumulaiton of light on corners
- //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
- skip=true;
-
- } else {
-
-
- Vector3 c1=r_normal.cross(n).normalized();
- Vector3 c2=r_normal.cross(c1).normalized();
- double r1 = double(rand())/RAND_MAX;
- double r2 = double(rand())/RAND_MAX;
- double r3 = double(rand())/RAND_MAX;
- Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.25)).normalized();
- float d =_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1,false,true);
- r = plot_size*cell_size*ao_radius;
- if (d>0 && d<r) {
- //avoid accumulaiton of light on corners
- //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
- skip=true;
-
- } else {
- //plot_light=Color(0,0,0,0);
- }
- }
- }
-
-
- Plane plane(r_point,r_normal);
- if (!skip)
- _plot_light(thread_stack,r_point,aabb,plot_light,tint_light,!(!p_first_bounce || p_bake_direct),plane);
-
-
- return dist;
- }
-
- return -1;
-
-}
-
-
-
-
-void BakedLightBaker::_make_octree_texture() {
-
-
- BakedLightBaker::Octant *octants=octant_pool.ptr();
-
- //find neighbours first, to have a better idea of what amount of space is needed
- {
-
- Vector<OctantHash> octant_hashing;
- octant_hashing.resize(octant_pool_size);
- Vector<uint32_t> hash_table;
- int hash_table_size=Math::larger_prime(16384);
- hash_table.resize(hash_table_size);
- uint32_t*hashptr = hash_table.ptr();
- OctantHash*octhashptr = octant_hashing.ptr();
-
- for(int i=0;i<hash_table_size;i++)
- hashptr[i]=0;
-
-
- //step 1 add to hash table
-
- uint32_t oct_idx=leaf_list;
-
-
- while(oct_idx) {
-
- BakedLightBaker::Octant *oct = &octants[oct_idx];
- uint64_t base=0;
- Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive
- base=int((pos.x+cell_size*0.5)/cell_size);
- base<<=16;
- base|=int((pos.y+cell_size*0.5)/cell_size);
- base<<=16;
- base|=int((pos.z+cell_size*0.5)/cell_size);
-
- uint32_t hash = HashMapHahserDefault::hash(base);
- uint32_t idx = hash % hash_table_size;
- octhashptr[oct_idx].next=hashptr[idx];
- octhashptr[oct_idx].hash=hash;
- octhashptr[oct_idx].value=base;
- hashptr[idx]=oct_idx;
-
- oct_idx=oct->next_leaf;
-
- }
-
- //step 2 find neighbours
- oct_idx=leaf_list;
- int neighbours=0;
-
-
- while(oct_idx) {
-
- BakedLightBaker::Octant *oct = &octants[oct_idx];
- Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive
- pos.x+=cell_size;
- uint64_t base=0;
- base=int((pos.x+cell_size*0.5)/cell_size);
- base<<=16;
- base|=int((pos.y+cell_size*0.5)/cell_size);
- base<<=16;
- base|=int((pos.z+cell_size*0.5)/cell_size);
-
- uint32_t hash = HashMapHahserDefault::hash(base);
- uint32_t idx = hash % hash_table_size;
-
- uint32_t bucket = hashptr[idx];
-
- while(bucket) {
-
- if (octhashptr[bucket].value==base) {
-
- oct->bake_neighbour=bucket;
- octants[bucket].first_neighbour=false;
- neighbours++;
- break;
- }
-
- bucket = octhashptr[bucket].next;
- }
-
- oct_idx=oct->next_leaf;
-
- }
-
- print_line("octant with neighbour: "+itos(neighbours));
-
- }
-
-
- //ok let's try to just create a texture
-
- int otex_w=256;
-
- while (true) {
-
-
-
- uint32_t oct_idx=leaf_list;
-
- int row=0;
-
-
- print_line("begin at row "+itos(row));
- int longest_line_reused=0;
- int col=0;
- int processed=0;
-
- //reset
- while(oct_idx) {
-
- BakedLightBaker::Octant *oct = &octants[oct_idx];
- oct->texture_x=0;
- oct->texture_y=0;
- oct_idx=oct->next_leaf;
-
- }
-
- oct_idx=leaf_list;
- //assign
- while(oct_idx) {
-
- BakedLightBaker::Octant *oct = &octants[oct_idx];
- if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) {
- //was not processed
- uint32_t current_idx=oct_idx;
- int reused=0;
-
- while(current_idx) {
- BakedLightBaker::Octant *o = &octants[current_idx];
- if (col+1 >= otex_w) {
- col=0;
- row+=4;
- }
- o->texture_x=col;
- o->texture_y=row;
- processed++;
-
- if (o->bake_neighbour) {
- reused++;
- }
- col+=o->bake_neighbour ? 1 : 2; //reuse neighbour
- current_idx=o->bake_neighbour;
- }
-
- if (reused>longest_line_reused) {
- longest_line_reused=reused;
- }
- }
- oct_idx=oct->next_leaf;
- }
-
- row+=4;
-
- if (otex_w < row) {
-
- otex_w*=2;
- } else {
-
- baked_light_texture_w=otex_w;
- baked_light_texture_h=nearest_power_of_2(row);
- print_line("w: "+itos(otex_w));
- print_line("h: "+itos(row));
- break;
- }
-
-
- }
-
-
- {
-
- otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally
- Vector3 lattice_cell_size=octree_aabb.size;
- for(int i=0;i<lattice_size;i++) {
-
- lattice_cell_size*=0.5;
- }
-
-
-
- while(true) {
-
- //let's plot the leafs first, given the octree is not so obvious which size it will have
- int row=4+4*(1<<lattice_size);
- int col=0;
-
- col=0;
- row+=4;
- print_line("end at row "+itos(row));
-
- //put octree, no need for recursion, just loop backwards.
- int regular_octants=0;
- for(int i=octant_pool_size-1;i>=0;i--) {
-
- BakedLightBaker::Octant *oct = &octants[i];
- if (oct->leaf) //ignore leaf
- continue;
- if (oct->aabb.size.x>lattice_cell_size.x*1.1) { //bigger than latice, skip
- oct->texture_x=0;
- oct->texture_y=0;
- } else if (oct->aabb.size.x>lattice_cell_size.x*0.8) {
- //this is the initial lattice
- Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive
- int x = int((pos.x+lattice_cell_size.x*0.5)/lattice_cell_size.x);
- int y = int((pos.y+lattice_cell_size.y*0.5)/lattice_cell_size.y);
- int z = int((pos.z+lattice_cell_size.z*0.5)/lattice_cell_size.z);
- //bug net
- ERR_FAIL_INDEX(x,(1<<lattice_size));
- ERR_FAIL_INDEX(y,(1<<lattice_size));
- ERR_FAIL_INDEX(z,(1<<lattice_size));
-
- /*int ofs = z*(1<<lattice_size)*(1<<lattice_size)+y*(1<<lattice_size)+x;
- ofs*=4;
- oct->texture_x=ofs%otex_w;
- oct->texture_y=(ofs/otex_w)*4+4;
- */
-
- oct->texture_x=(x+(1<<lattice_size)*z)*2;
- oct->texture_y=4+y*4;
- //print_line("pos: "+itos(x)+","+itos(y)+","+itos(z)+" - ofs"+itos(oct->texture_x)+","+itos(oct->texture_y));
-
-
- } else {
- //an everyday regular octant
-
- if (col+2 > otex_w) {
- col=0;
- row+=4;
- }
-
- oct->texture_x=col;
- oct->texture_y=row;
- col+=2;
- regular_octants++;
-
-
- }
- }
- print_line("octants end at row "+itos(row)+" totalling"+itos(regular_octants));
-
- //ok evaluation.
-
- if (otex_w<=2048 && row>2048) { //too big upwards, try bigger texture
- otex_w*=2;
- continue;
- } else {
- baked_octree_texture_w=otex_w;
- baked_octree_texture_h=row+4;
- break;
- }
-
- }
-
-
- }
-
-
- baked_octree_texture_h=nearest_power_of_2(baked_octree_texture_h);
- print_line("RESULT! "+itos(baked_octree_texture_w)+","+itos(baked_octree_texture_h));
-
-}
-
-
-
-
-
-
-
-
-double BakedLightBaker::get_normalization(int p_light_idx) const {
-
- double nrg=0;
-
- const LightData &dl=lights[p_light_idx];
- double cell_area = cell_size*cell_size;
- //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area);
- nrg=dl.rays_thrown * cell_area;
- nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel
- nrg*=dl.constant;
- //nrg*=5;
-
-
- return nrg;
-}
-
-
-
-double BakedLightBaker::get_modifier(int p_light_idx) const {
-
- double nrg=0;
-
- const LightData &dl=lights[p_light_idx];
- double cell_area = cell_size*cell_size;
- //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area);
- nrg=cell_area;
- nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel
- nrg*=dl.constant;
- //nrg*=5;
-
-
- return nrg;
-}
-
-void BakedLightBaker::throw_rays(ThreadStack& thread_stack,int p_amount) {
-
-
-
- for(int i=0;i<lights.size();i++) {
-
- LightData &dl=lights[i];
-
-
- int amount = p_amount * total_light_area / dl.area;
- double mod = 1.0/double(get_modifier(i));
- mod*=p_amount/float(amount);
-
- switch(dl.type) {
-
- case VS::LIGHT_DIRECTIONAL: {
-
-
- for(int j=0;j<amount;j++) {
- Vector3 from = dl.pos;
- double r1 = double(rand())/RAND_MAX;
- double r2 = double(rand())/RAND_MAX;
- from+=dl.up*(r1*2.0-1.0);
- from+=dl.left*(r2*2.0-1.0);
- Vector3 to = from+dl.dir*dl.length;
- Color col=dl.diffuse;
- float m = mod*dl.energy;
- col.r*=m;
- col.g*=m;
- col.b*=m;
-
- dl.rays_thrown++;
- baked_light_baker_add_64i(&total_rays,1);
-
- _throw_ray(thread_stack,dl.bake_direct,from,to,dl.length,col,NULL,0,0,max_bounces,true);
- }
- } break;
- case VS::LIGHT_OMNI: {
-
-
- for(int j=0;j<amount;j++) {
- Vector3 from = dl.pos;
-
- double r1 = double(rand())/RAND_MAX;
- double r2 = double(rand())/RAND_MAX;
- double r3 = double(rand())/RAND_MAX;
-
-#if 0
- //crap is not uniform..
- Vector3 dir = Vector3(r1*2.0-1.0,r2*2.0-1.0,r3*2.0-1.0).normalized();
-
-#else
-
- double phi = r1*Math_PI*2.0;
- double costheta = r2*2.0-1.0;
- double u = r3;
-
- double theta = acos( costheta );
- double r = 1.0 * pow( u,1/3.0 );
-
- Vector3 dir(
- r * sin( theta) * cos( phi ),
- r * sin( theta) * sin( phi ),
- r * cos( theta )
- );
- dir.normalize();
-
-#endif
- Vector3 to = dl.pos+dir*dl.radius;
- Color col=dl.diffuse;
- float m = mod*dl.energy;
- col.r*=m;
- col.g*=m;
- col.b*=m;
-
- dl.rays_thrown++;
- baked_light_baker_add_64i(&total_rays,1);
- _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true);
- //_throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true);
- }
-
- } break;
- case VS::LIGHT_SPOT: {
-
- for(int j=0;j<amount;j++) {
- Vector3 from = dl.pos;
-
- double r1 = double(rand())/RAND_MAX;
- //double r2 = double(rand())/RAND_MAX;
- double r3 = double(rand())/RAND_MAX;
-
- float d=Math::tan(Math::deg2rad(dl.spot_angle));
-
- float x = sin(r1*Math_PI*2.0)*d;
- float y = cos(r1*Math_PI*2.0)*d;
-
- Vector3 dir = r3*(dl.dir + dl.up*y + dl.left*x) + (1.0-r3)*dl.dir;
- dir.normalize();
-
-
- Vector3 to = dl.pos+dir*dl.radius;
- Color col=dl.diffuse;
- float m = mod*dl.energy;
- col.r*=m;
- col.g*=m;
- col.b*=m;
-
- dl.rays_thrown++;
- baked_light_baker_add_64i(&total_rays,1);
- _throw_ray(thread_stack,dl.bake_direct,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true);
- //_throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true);
- }
-
- } break;
-
- }
- }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) {
-
- if (baking)
- return;
- cell_count=0;
-
- base_inv=p_node->cast_to<Spatial>()->get_global_transform().affine_inverse();
- EditorProgress ep("bake",TTR("Light Baker Setup:"),5);
- baked_light=p_light;
- lattice_size=baked_light->get_initial_lattice_subdiv();
- octree_depth=baked_light->get_cell_subdivision();
- plot_size=baked_light->get_plot_size();
- max_bounces=baked_light->get_bounces();
- use_diffuse=baked_light->get_bake_flag(BakedLight::BAKE_DIFFUSE);
- use_specular=baked_light->get_bake_flag(BakedLight::BAKE_SPECULAR);
- use_translucency=baked_light->get_bake_flag(BakedLight::BAKE_TRANSLUCENT);
-
- edge_damp=baked_light->get_edge_damp();
- normal_damp=baked_light->get_normal_damp();
- octree_extra_margin=baked_light->get_cell_extra_margin();
- tint=baked_light->get_tint();
- ao_radius=baked_light->get_ao_radius();
- ao_strength=baked_light->get_ao_strength();
- linear_color=baked_light->get_bake_flag(BakedLight::BAKE_LINEAR_COLOR);
-
- baked_textures.clear();
- for(int i=0;i<baked_light->get_lightmaps_count();i++) {
- BakeTexture bt;
- bt.width=baked_light->get_lightmap_gen_size(i).x;
- bt.height=baked_light->get_lightmap_gen_size(i).y;
- baked_textures.push_back(bt);
- }
-
-
- ep.step(TTR("Parsing Geometry"),0);
- _parse_geometry(p_node);
- mat_map.clear();
- tex_map.clear();
- print_line("\ttotal triangles: "+itos(triangles.size()));
- // no geometry
- if (triangles.size() == 0) {
- return;
- }
- ep.step(TTR("Fixing Lights"),1);
- _fix_lights();
- ep.step(TTR("Making BVH"),2);
- _make_bvh();
- ep.step(TTR("Creating Light Octree"),3);
- _make_octree();
- ep.step(TTR("Creating Octree Texture"),4);
- _make_octree_texture();
- baking=true;
- _start_thread();
-
-}
-
-
-void BakedLightBaker::update_octree_sampler(PoolVector<int> &p_sampler) {
-
- BakedLightBaker::Octant *octants=octant_pool.ptr();
- double norm = 1.0/double(total_rays);
-
-
-
- if (p_sampler.size()==0 || first_bake_to_map) {
-
- Vector<int> tmp_smp;
- tmp_smp.resize(32); //32 for header
-
- for(int i=0;i<32;i++) {
- tmp_smp[i]=0;
- }
-
- for(int i=octant_pool_size-1;i>=0;i--) {
-
- if (i==0)
- tmp_smp[1]=tmp_smp.size();
-
- Octant &octant=octants[i];
- octant.sampler_ofs = tmp_smp.size();
- int idxcol[2]={0,0};
-
- int r = CLAMP((octant.full_accum[0]*norm)*2048,0,32767);
- int g = CLAMP((octant.full_accum[1]*norm)*2048,0,32767);
- int b = CLAMP((octant.full_accum[2]*norm)*2048,0,32767);
-
- idxcol[0]|=r;
- idxcol[1]|=(g<<16)|b;
-
- if (octant.leaf) {
- tmp_smp.push_back(idxcol[0]);
- tmp_smp.push_back(idxcol[1]);
- } else {
-
- for(int j=0;j<8;j++) {
- if (octant.children[j]) {
- idxcol[0]|=(1<<(j+16));
- }
- }
- tmp_smp.push_back(idxcol[0]);
- tmp_smp.push_back(idxcol[1]);
- for(int j=0;j<8;j++) {
- if (octant.children[j]) {
- tmp_smp.push_back(octants[octant.children[j]].sampler_ofs);
- if (octants[octant.children[j]].sampler_ofs==0) {
- print_line("FUUUUUUUUCK");
- }
- }
- }
- }
-
- }
-
- p_sampler.resize(tmp_smp.size());
- PoolVector<int>::Write w = p_sampler.write();
- int ss = tmp_smp.size();
- for(int i=0;i<ss;i++) {
- w[i]=tmp_smp[i];
- }
-
- first_bake_to_map=false;
-
- }
-
- double gamma = baked_light->get_gamma_adjust();
- double mult = baked_light->get_energy_multiplier();
- float saturation = baked_light->get_saturation();
-
- PoolVector<int>::Write w = p_sampler.write();
-
- encode_uint32(octree_depth,(uint8_t*)&w[2]);
- encode_uint32(linear_color,(uint8_t*)&w[3]);
-
- encode_float(octree_aabb.pos.x,(uint8_t*)&w[4]);
- encode_float(octree_aabb.pos.y,(uint8_t*)&w[5]);
- encode_float(octree_aabb.pos.z,(uint8_t*)&w[6]);
- encode_float(octree_aabb.size.x,(uint8_t*)&w[7]);
- encode_float(octree_aabb.size.y,(uint8_t*)&w[8]);
- encode_float(octree_aabb.size.z,(uint8_t*)&w[9]);
-
- //norm*=multiplier;
-
- for(int i=octant_pool_size-1;i>=0;i--) {
-
- Octant &octant=octants[i];
- int idxcol[2]={w[octant.sampler_ofs],w[octant.sampler_ofs+1]};
-
- double rf=pow(octant.full_accum[0]*norm*mult,gamma);
- double gf=pow(octant.full_accum[1]*norm*mult,gamma);
- double bf=pow(octant.full_accum[2]*norm*mult,gamma);
-
- double gray = (rf+gf+bf)/3.0;
- rf = gray + (rf-gray)*saturation;
- gf = gray + (gf-gray)*saturation;
- bf = gray + (bf-gray)*saturation;
-
-
- int r = CLAMP((rf)*2048,0,32767);
- int g = CLAMP((gf)*2048,0,32767);
- int b = CLAMP((bf)*2048,0,32767);
-
- idxcol[0]=((idxcol[0]>>16)<<16)|r;
- idxcol[1]=(g<<16)|b;
- w[octant.sampler_ofs]=idxcol[0];
- w[octant.sampler_ofs+1]=idxcol[1];
- }
-
-}
-
-void BakedLightBaker::update_octree_images(PoolVector<uint8_t> &p_octree,PoolVector<uint8_t> &p_light) {
-
-
- int len = baked_octree_texture_w*baked_octree_texture_h*4;
- p_octree.resize(len);
-
- int ilen = baked_light_texture_w*baked_light_texture_h*4;
- p_light.resize(ilen);
-
-
- PoolVector<uint8_t>::Write w = p_octree.write();
- zeromem(w.ptr(),len);
-
- PoolVector<uint8_t>::Write iw = p_light.write();
- zeromem(iw.ptr(),ilen);
-
- float gamma = baked_light->get_gamma_adjust();
- float mult = baked_light->get_energy_multiplier();
-
- for(int i=0;i<len;i+=4) {
- w[i+0]=0xFF;
- w[i+1]=0;
- w[i+2]=0xFF;
- w[i+3]=0xFF;
- }
-
- for(int i=0;i<ilen;i+=4) {
- iw[i+0]=0xFF;
- iw[i+1]=0;
- iw[i+2]=0xFF;
- iw[i+3]=0xFF;
- }
-
- float multiplier=1.0;
-
- if (baked_light->get_format()==BakedLight::FORMAT_HDR8)
- multiplier=8;
- encode_uint32(baked_octree_texture_w,&w[0]);
- encode_uint32(baked_octree_texture_h,&w[4]);
- encode_uint32(0,&w[8]);
- encode_float(1<<lattice_size,&w[12]);
- encode_uint32(octree_depth-lattice_size,&w[16]);
- encode_uint32(multiplier,&w[20]);
- encode_uint16(baked_light_texture_w,&w[24]); //if present, use the baked light texture
- encode_uint16(baked_light_texture_h,&w[26]);
- encode_uint32(0,&w[28]); //baked light texture format
-
- encode_float(octree_aabb.pos.x,&w[32]);
- encode_float(octree_aabb.pos.y,&w[36]);
- encode_float(octree_aabb.pos.z,&w[40]);
- encode_float(octree_aabb.size.x,&w[44]);
- encode_float(octree_aabb.size.y,&w[48]);
- encode_float(octree_aabb.size.z,&w[52]);
-
-
- BakedLightBaker::Octant *octants=octant_pool.ptr();
- int octant_count=octant_pool_size;
- uint8_t *ptr = w.ptr();
- uint8_t *lptr = iw.ptr();
-
-
- int child_offsets[8]={
- 0,
- 4,
- baked_octree_texture_w*4,
- baked_octree_texture_w*4+4,
- baked_octree_texture_w*8+0,
- baked_octree_texture_w*8+4,
- baked_octree_texture_w*8+baked_octree_texture_w*4,
- baked_octree_texture_w*8+baked_octree_texture_w*4+4,
- };
-
- int lchild_offsets[8]={
- 0,
- 4,
- baked_light_texture_w*4,
- baked_light_texture_w*4+4,
- baked_light_texture_w*8+0,
- baked_light_texture_w*8+4,
- baked_light_texture_w*8+baked_light_texture_w*4,
- baked_light_texture_w*8+baked_light_texture_w*4+4,
- };
-
- /*Vector<double> norm_arr;
- norm_arr.resize(lights.size());
-
- for(int i=0;i<lights.size();i++) {
- norm_arr[i] = 1.0/get_normalization(i);
- }
-
- const double *normptr=norm_arr.ptr();
-*/
- double norm = 1.0/double(total_rays);
- mult/=multiplier;
- double saturation = baked_light->get_saturation();
-
- for(int i=0;i<octant_count;i++) {
-
- Octant &oct=octants[i];
- if (oct.texture_x==0 && oct.texture_y==0)
- continue;
-
-
- if (oct.leaf) {
-
- int ofs = (oct.texture_y * baked_light_texture_w + oct.texture_x)<<2;
- ERR_CONTINUE(ofs<0 || ofs >ilen);
- //write colors
- for(int j=0;j<8;j++) {
-
- /*
- if (!oct.children[j])
- continue;
- */
- uint8_t *iptr=&lptr[ofs+lchild_offsets[j]];
-
- float r=oct.light_accum[j][0]*norm;
- float g=oct.light_accum[j][1]*norm;
- float b=oct.light_accum[j][2]*norm;
-
- r=pow(r*mult,gamma);
- g=pow(g*mult,gamma);
- b=pow(b*mult,gamma);
-
- double gray = (r+g+b)/3.0;
- r = gray + (r-gray)*saturation;
- g = gray + (g-gray)*saturation;
- b = gray + (b-gray)*saturation;
-
- float ic[3]={
- r,
- g,
- b,
- };
- iptr[0]=CLAMP(ic[0]*255.0,0,255);
- iptr[1]=CLAMP(ic[1]*255.0,0,255);
- iptr[2]=CLAMP(ic[2]*255.0,0,255);
- iptr[3]=255;
- }
-
- } else {
-
- int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2;
- ERR_CONTINUE(ofs<0 || ofs >len);
-
- //write indices
- for(int j=0;j<8;j++) {
-
- if (!oct.children[j])
- continue;
- Octant&choct=octants[oct.children[j]];
- uint8_t *iptr=&ptr[ofs+child_offsets[j]];
-
- iptr[0]=choct.texture_x>>8;
- iptr[1]=choct.texture_x&0xFF;
- iptr[2]=choct.texture_y>>8;
- iptr[3]=choct.texture_y&0xFF;
-
- }
- }
-
- }
-
-
-}
-
-
-void BakedLightBaker::_free_bvh(BVH* p_bvh) {
-
- if (!p_bvh->leaf) {
- if (p_bvh->children[0])
- _free_bvh(p_bvh->children[0]);
- if (p_bvh->children[1])
- _free_bvh(p_bvh->children[1]);
- }
-
- memdelete(p_bvh);
-
-}
-
-
-bool BakedLightBaker::is_baking() {
-
- return baking;
-}
-
-void BakedLightBaker::set_pause(bool p_pause){
-
- if (paused==p_pause)
- return;
-
- paused=p_pause;
-
- if (paused) {
- _stop_thread();
- } else {
- _start_thread();
- }
-}
-bool BakedLightBaker::is_paused() {
-
- return paused;
-
-}
-
-void BakedLightBaker::_bake_thread_func(void *arg) {
-
- BakedLightBaker *ble = (BakedLightBaker*)arg;
-
-
-
- ThreadStack thread_stack;
-
- thread_stack.ray_stack = memnew_arr(uint32_t,ble->bvh_depth);
- thread_stack.bvh_stack = memnew_arr(BVH*,ble->bvh_depth);
- thread_stack.octant_stack = memnew_arr(uint32_t,ble->octree_depth*2 );
- thread_stack.octantptr_stack = memnew_arr(uint32_t,ble->octree_depth*2 );
-
- while(!ble->bake_thread_exit) {
-
- ble->throw_rays(thread_stack,1000);
- }
-
- memdelete_arr(thread_stack.ray_stack );
- memdelete_arr(thread_stack.bvh_stack );
- memdelete_arr(thread_stack.octant_stack );
- memdelete_arr(thread_stack.octantptr_stack );
-
-}
-
-void BakedLightBaker::_start_thread() {
-
- if (threads.size()!=0)
- return;
- bake_thread_exit=false;
-
- int thread_count = EDITOR_DEF("light_baker/custom_bake_threads",0);
- if (thread_count<=0 || thread_count>64)
- thread_count=OS::get_singleton()->get_processor_count();
-
- //thread_count=1;
- threads.resize(thread_count);
- for(int i=0;i<threads.size();i++) {
- threads[i]=Thread::create(_bake_thread_func,this);
- }
-}
-
-void BakedLightBaker::_stop_thread() {
-
- if (threads.size()==0)
- return;
- bake_thread_exit=true;
- for(int i=0;i<threads.size();i++) {
- Thread::wait_to_finish(threads[i]);
- memdelete(threads[i]);
- }
- threads.clear();
-}
-
-void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma) {
-
-
- uint8_t *ptr = &image[(y*width+x)*4];
- //int lc = lights.size();
- double norm = 1.0/double(total_rays);
-
-
- Color color;
-
- Octant *octants=octant_pool.ptr();
-
-
- int octant_idx=0;
-
-
- while(true) {
-
- Octant &octant=octants[octant_idx];
-
- if (octant.leaf) {
-
- Vector3 lpos = p_pos-octant.aabb.pos;
- lpos/=octant.aabb.size;
-
- Vector3 cols[8];
-
- for(int i=0;i<8;i++) {
-
- cols[i].x+=octant.light_accum[i][0]*norm;
- cols[i].y+=octant.light_accum[i][1]*norm;
- cols[i].z+=octant.light_accum[i][2]*norm;
- }
-
-
- /*Vector3 final = (cols[0] + (cols[1] - cols[0]) * lpos.y);
- final = final + ((cols[2] + (cols[3] - cols[2]) * lpos.y) - final)*lpos.x;
-
- Vector3 final2 = (cols[4+0] + (cols[4+1] - cols[4+0]) * lpos.y);
- final2 = final2 + ((cols[4+2] + (cols[4+3] - cols[4+2]) * lpos.y) - final2)*lpos.x;*/
-
- Vector3 finala = cols[0].linear_interpolate(cols[1],lpos.x);
- Vector3 finalb = cols[2].linear_interpolate(cols[3],lpos.x);
- Vector3 final = finala.linear_interpolate(finalb,lpos.y);
-
- Vector3 final2a = cols[4+0].linear_interpolate(cols[4+1],lpos.x);
- Vector3 final2b = cols[4+2].linear_interpolate(cols[4+3],lpos.x);
- Vector3 final2 = final2a.linear_interpolate(final2b,lpos.y);
-
- final = final.linear_interpolate(final2,lpos.z);
- if (baked_light->get_format()==BakedLight::FORMAT_HDR8)
- final*=8.0;
-
-
- color.r=pow(final.x*mult,gamma);
- color.g=pow(final.y*mult,gamma);
- color.b=pow(final.z*mult,gamma);
- color.a=1.0;
-
- int lc = lights.size();
- LightData *lv = lights.ptr();
- for(int i=0;i<lc;i++) {
- //shadow baking
- if (!lv[i].bake_shadow)
- continue;
- Vector3 from = p_pos+p_normal*0.01;
- Vector3 to;
- float att=0;
- switch(lv[i].type) {
- case VS::LIGHT_DIRECTIONAL: {
- to=from-lv[i].dir*lv[i].length;
- } break;
- case VS::LIGHT_OMNI: {
- to=lv[i].pos;
- float d = MIN(lv[i].radius,to.distance_to(from))/lv[i].radius;
- att=d;//1.0-d;
- } break;
- default: continue;
- }
-
- uint32_t* stack = ray_stack;
- BVH **bstack = bvh_stack;
-
- enum {
- TEST_RAY_BIT=0,
- VISIT_LEFT_BIT=1,
- VISIT_RIGHT_BIT=2,
- VISIT_DONE_BIT=3,
-
-
- };
-
- bool intersected=false;
-
- int level=0;
-
- Vector3 n = (to-from);
- float len=n.length();
- if (len==0)
- continue;
- n/=len;
-
- bstack[0]=bvh;
- stack[0]=TEST_RAY_BIT;
-
-
- while(!intersected) {
-
- uint32_t mode = stack[level];
- const BVH &b = *bstack[level];
- bool done=false;
-
- switch(mode) {
- case TEST_RAY_BIT: {
-
- if (b.leaf) {
-
-
- Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
-
-
- Vector3 res;
-
- if (f3.intersects_segment(from,to)) {
- intersected=true;
- done=true;
- }
-
- stack[level]=VISIT_DONE_BIT;
- } else {
-
-
- bool valid = b.aabb.smits_intersect_ray(from,n,0,len);
- //bool valid = b.aabb.intersects_segment(p_begin,p_end);
- //bool valid = b.aabb.intersects(ray_aabb);
-
- if (!valid) {
-
- stack[level]=VISIT_DONE_BIT;
-
- } else {
-
- stack[level]=VISIT_LEFT_BIT;
- }
- }
-
- } continue;
- case VISIT_LEFT_BIT: {
-
- stack[level]=VISIT_RIGHT_BIT;
- bstack[level+1]=b.children[0];
- stack[level+1]=TEST_RAY_BIT;
- level++;
-
- } continue;
- case VISIT_RIGHT_BIT: {
-
- stack[level]=VISIT_DONE_BIT;
- bstack[level+1]=b.children[1];
- stack[level+1]=TEST_RAY_BIT;
- level++;
- } continue;
- case VISIT_DONE_BIT: {
-
- if (level==0) {
- done=true;
- break;
- } else
- level--;
-
- } continue;
- }
-
-
- if (done)
- break;
- }
-
-
-
- if (intersected) {
-
- color.a=Math::lerp(MAX(0.01,lv[i].darkening),1.0,att);
- }
-
- }
-
- break;
- } else {
-
- Vector3 lpos = p_pos - octant.aabb.pos;
- Vector3 half = octant.aabb.size * 0.5;
-
- int ofs=0;
-
- if (lpos.x >= half.x)
- ofs|=1;
- if (lpos.y >= half.y)
- ofs|=2;
- if (lpos.z >= half.z)
- ofs|=4;
-
- octant_idx = octant.children[ofs];
-
- if (octant_idx==0)
- return;
-
- }
- }
-
- ptr[0]=CLAMP(color.r*255.0,0,255);
- ptr[1]=CLAMP(color.g*255.0,0,255);
- ptr[2]=CLAMP(color.b*255.0,0,255);
- ptr[3]=CLAMP(color.a*255.0,0,255);
-
-}
-
-
-Error BakedLightBaker::transfer_to_lightmaps() {
-
- if (!triangles.size() || baked_textures.size()==0)
- return ERR_UNCONFIGURED;
-
- EditorProgress ep("transfer_to_lightmaps",TTR("Transfer to Lightmaps:"),baked_textures.size()*2+triangles.size());
-
- for(int i=0;i<baked_textures.size();i++) {
-
- ERR_FAIL_COND_V( baked_textures[i].width<=0 || baked_textures[i].height<=0,ERR_UNCONFIGURED );
-
- baked_textures[i].data.resize( baked_textures[i].width*baked_textures[i].height*4 );
- zeromem(baked_textures[i].data.ptr(),baked_textures[i].data.size());
- ep.step(TTR("Allocating Texture #")+itos(i+1),i);
- }
-
- Vector<double> norm_arr;
- norm_arr.resize(lights.size());
-
- for(int i=0;i<lights.size();i++) {
- norm_arr[i] = 1.0/get_normalization(i);
- }
- float gamma = baked_light->get_gamma_adjust();
- float mult = baked_light->get_energy_multiplier();
-
- for(int i=0;i<triangles.size();i++) {
-
- if (i%200==0) {
- ep.step(TTR("Baking Triangle #")+itos(i),i+baked_textures.size());
- }
- Triangle &t=triangles[i];
- if (t.baked_texture<0 || t.baked_texture>=baked_textures.size())
- continue;
-
- BakeTexture &bt=baked_textures[t.baked_texture];
- Vector3 normal = Plane(t.vertices[0],t.vertices[1],t.vertices[2]).normal;
-
-
- int x[3];
- int y[3];
-
- Vector3 vertices[3]={
- t.vertices[0],
- t.vertices[1],
- t.vertices[2]
- };
-
- for(int j=0;j<3;j++) {
-
- x[j]=t.bake_uvs[j].x*bt.width;
- y[j]=t.bake_uvs[j].y*bt.height;
- x[j]=CLAMP(x[j],0,bt.width-1);
- y[j]=CLAMP(y[j],0,bt.height-1);
- }
-
-
- {
-
- // sort the points vertically
- if (y[1] > y[2]) {
- SWAP(x[1], x[2]);
- SWAP(y[1], y[2]);
- SWAP(vertices[1],vertices[2]);
- }
- if (y[0] > y[1]) {
- SWAP(x[0], x[1]);
- SWAP(y[0], y[1]);
- SWAP(vertices[0],vertices[1]);
- }
- if (y[1] > y[2]) {
- SWAP(x[1], x[2]);
- SWAP(y[1], y[2]);
- SWAP(vertices[1],vertices[2]);
- }
-
- double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1);
- double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1);
- double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1);
- double xf = x[0];
- double xt = x[0] + dx_upper; // if y[0] == y[1], special case
- for (int yi = y[0]; yi <= (y[2] > bt.height-1 ? bt.height-1 : y[2]); yi++)
- {
- if (yi >= 0) {
- for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < bt.width ? xt : bt.width-1) ; xi++) {
- //pixels[int(x + y * width)] = color;
-
- Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
- Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
- //vertices[2] - vertices[0];
- Vector2 v2 = Vector2(xi-x[0],yi-y[0]);
- float d00 = v0.dot( v0);
- float d01 = v0.dot( v1);
- float d11 = v1.dot( v1);
- float d20 = v2.dot( v0);
- float d21 = v2.dot( v1);
- float denom = (d00 * d11 - d01 * d01);
- Vector3 pos;
- if (denom==0) {
- pos=t.vertices[0];
- } else {
- float v = (d11 * d20 - d01 * d21) / denom;
- float w = (d00 * d21 - d01 * d20) / denom;
- float u = 1.0f - v - w;
- pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
- }
- _plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
-
- }
-
- for (int xi = (xf < bt.width ? int(xf) : bt.width-1); xi >= (xt > 0 ? xt : 0); xi--) {
- //pixels[int(x + y * width)] = color;
- Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
- Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
- //vertices[2] - vertices[0];
- Vector2 v2 = Vector2(xi-x[0],yi-y[0]);
- float d00 = v0.dot( v0);
- float d01 = v0.dot( v1);
- float d11 = v1.dot( v1);
- float d20 = v2.dot( v0);
- float d21 = v2.dot( v1);
- float denom = (d00 * d11 - d01 * d01);
- Vector3 pos;
- if (denom==0) {
- pos=t.vertices[0];
- } else {
- float v = (d11 * d20 - d01 * d21) / denom;
- float w = (d00 * d21 - d01 * d20) / denom;
- float u = 1.0f - v - w;
- pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
- }
-
- _plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
-
- }
- }
- xf += dx_far;
- if (yi < y[1])
- xt += dx_upper;
- else
- xt += dx_low;
- }
- }
-
- }
-
-
- for(int i=0;i<baked_textures.size();i++) {
-
-
- {
-
- ep.step(TTR("Post-Processing Texture #")+itos(i),i+baked_textures.size()+triangles.size());
-
- BakeTexture &bt=baked_textures[i];
-
- Vector<uint8_t> copy_data=bt.data;
- uint8_t *data=bt.data.ptr();
- const int max_radius=8;
- const int shadow_radius=2;
- const int max_dist=0x7FFFFFFF;
-
- for(int x=0;x<bt.width;x++) {
-
- for(int y=0;y<bt.height;y++) {
-
-
- uint8_t a = copy_data[(y*bt.width+x)*4+3];
-
- if (a>0) {
- //blur shadow
-
- int from_x = MAX(0,x-shadow_radius);
- int to_x = MIN(bt.width-1,x+shadow_radius);
- int from_y = MAX(0,y-shadow_radius);
- int to_y = MIN(bt.height-1,y+shadow_radius);
-
- int sum=0;
- int sumc=0;
-
- for(int k=from_y;k<=to_y;k++) {
- for(int l=from_x;l<=to_x;l++) {
-
- const uint8_t * rp = &copy_data[(k*bt.width+l)<<2];
-
- sum+=rp[3];
- sumc++;
- }
- }
-
- sum/=sumc;
- data[(y*bt.width+x)*4+3]=sum;
-
- } else {
-
- int closest_dist=max_dist;
- uint8_t closest_color[4];
-
- int from_x = MAX(0,x-max_radius);
- int to_x = MIN(bt.width-1,x+max_radius);
- int from_y = MAX(0,y-max_radius);
- int to_y = MIN(bt.height-1,y+max_radius);
-
- for(int k=from_y;k<=to_y;k++) {
- for(int l=from_x;l<=to_x;l++) {
-
- int dy = y-k;
- int dx = x-l;
- int dist = dy*dy+dx*dx;
- if (dist>=closest_dist)
- continue;
-
- const uint8_t * rp = &copy_data[(k*bt.width+l)<<2];
-
- if (rp[3]==0)
- continue;
-
- closest_dist=dist;
- closest_color[0]=rp[0];
- closest_color[1]=rp[1];
- closest_color[2]=rp[2];
- closest_color[3]=rp[3];
- }
- }
-
-
- if (closest_dist!=max_dist) {
-
- data[(y*bt.width+x)*4+0]=closest_color[0];
- data[(y*bt.width+x)*4+1]=closest_color[1];
- data[(y*bt.width+x)*4+2]=closest_color[2];
- data[(y*bt.width+x)*4+3]=closest_color[3];
- }
- }
- }
- }
- }
-
- PoolVector<uint8_t> dv;
- dv.resize(baked_textures[i].data.size());
- {
- PoolVector<uint8_t>::Write w = dv.write();
- copymem(w.ptr(),baked_textures[i].data.ptr(),baked_textures[i].data.size());
- }
-
- Image img(baked_textures[i].width,baked_textures[i].height,0,Image::FORMAT_RGBA8,dv);
- Ref<ImageTexture> tex = memnew( ImageTexture );
- tex->create_from_image(img);
- baked_light->set_lightmap_texture(i,tex);
- }
-
-
- return OK;
-}
-
-void BakedLightBaker::clear() {
-
-
-
- _stop_thread();
-
- if (bvh)
- _free_bvh(bvh);
-
- if (ray_stack)
- memdelete_arr(ray_stack);
- if (octant_stack)
- memdelete_arr(octant_stack);
- if (octantptr_stack)
- memdelete_arr(octantptr_stack);
- if (bvh_stack)
- memdelete_arr(bvh_stack);
-/*
- * ???
- for(int i=0;i<octant_pool.size();i++) {
- /*
- if (octant_pool[i].leaf) {
- memdelete_arr( octant_pool[i].light );
- }
- Vector<double> norm_arr;
- norm_arr.resize(lights.size());
- */
-
- for(int i=0;i<lights.size();i++) {
- norm_arr[i] = 1.0/get_normalization(i);
- }
-
- const double *normptr=norm_arr.ptr();
- }
-*/
- octant_pool.clear();
- octant_pool_size=0;
- bvh=NULL;
- leaf_list=0;
- cell_count=0;
- ray_stack=NULL;
- octant_stack=NULL;
- octantptr_stack=NULL;
- bvh_stack=NULL;
- materials.clear();
- materials.clear();
- textures.clear();
- lights.clear();
- triangles.clear();
- endpoint_normal.clear();
- endpoint_normal_bits.clear();
- baked_octree_texture_w=0;
- baked_octree_texture_h=0;
- paused=false;
- baking=false;
-
- bake_thread_exit=false;
- first_bake_to_map=true;
- baked_light=Ref<BakedLight>();
- total_rays=0;
-
-}
-
-BakedLightBaker::BakedLightBaker() {
- octree_depth=9;
- lattice_size=4;
- octant_pool.clear();
- octant_pool_size=0;
- bvh=NULL;
- leaf_list=0;
- cell_count=0;
- ray_stack=NULL;
- bvh_stack=NULL;
- octant_stack=NULL;
- octantptr_stack=NULL;
- plot_size=2.5;
- max_bounces=2;
- materials.clear();
- baked_octree_texture_w=0;
- baked_octree_texture_h=0;
- paused=false;
- baking=false;
-
- bake_thread_exit=false;
- total_rays=0;
- first_bake_to_map=true;
- linear_color=false;
-
-}
-
-BakedLightBaker::~BakedLightBaker() {
-
- clear();
-}
-#endif
diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h
deleted file mode 100644
index e311fe9f17..0000000000
--- a/tools/editor/plugins/baked_light_editor_plugin.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*************************************************************************/
-/* baked_light_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 BAKED_LIGHT_EDITOR_PLUGIN_H
-#define BAKED_LIGHT_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/plugins/baked_light_baker.h"
-#include "scene/gui/spin_box.h"
-
-
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-#if 0
-
-class MeshInstance;
-
-class BakedLightEditor : public Control {
-
- GDCLASS(BakedLightEditor, Control );
-
-
- float update_timeout;
- PoolVector<uint8_t> octree_texture;
- PoolVector<uint8_t> light_texture;
- PoolVector<int> octree_sampler;
-
- BakedLightBaker *baker;
- AcceptDialog *err_dialog;
-
- HBoxContainer *bake_hbox;
- Button *button_bake;
- Button *button_reset;
- Button *button_make_lightmaps;
- Label *bake_info;
-
- uint64_t last_rays_time;
-
-
-
- BakedLightInstance *node;
-
- enum Menu {
-
- MENU_OPTION_BAKE,
- MENU_OPTION_CLEAR
- };
-
- void _bake_lightmaps();
-
- void _bake_pressed();
- void _clear_pressed();
-
- void _end_baking();
- void _menu_option(int);
-
-friend class BakedLightEditorPlugin;
-protected:
- void _node_removed(Node *p_node);
- static void _bind_methods();
- void _notification(int p_what);
-public:
-
- void edit(BakedLightInstance *p_baked_light);
- BakedLightEditor();
- ~BakedLightEditor();
-};
-
-class BakedLightEditorPlugin : public EditorPlugin {
-
- GDCLASS( BakedLightEditorPlugin, EditorPlugin );
-
- BakedLightEditor *baked_light_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "BakedLight"; }
- 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);
-
- BakedLightEditorPlugin(EditorNode *p_node);
- ~BakedLightEditorPlugin();
-
-};
-
-#endif // MULTIMESH_EDITOR_PLUGIN_H
-#endif
-
diff --git a/tools/editor/plugins/camera_editor_plugin.cpp b/tools/editor/plugins/camera_editor_plugin.cpp
deleted file mode 100644
index 1e0ec2b4a0..0000000000
--- a/tools/editor/plugins/camera_editor_plugin.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*************************************************************************/
-/* camera_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "camera_editor_plugin.h"
-
-#include "spatial_editor_plugin.h"
-
-
-void CameraEditor::_notification(int p_what) {
-
- switch(p_what) {
-
-/* case NOTIFICATION_PROCESS: {
-
- if (preview->is_pressed() && node)
- node->call("make_current");
-
- } break;*/
- }
-
-}
-void CameraEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- SpatialEditor::get_singleton()->set_custom_camera(NULL);
- hide();
- }
-
-}
-
-void CameraEditor::_pressed() {
-
- Node *sn = (node && preview->is_pressed())?node:NULL;
- SpatialEditor::get_singleton()->set_custom_camera(sn);
-}
-
-void CameraEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_pressed"),&CameraEditor::_pressed);
-
-}
-
-void CameraEditor::edit(Node *p_camera) {
-
- node=p_camera;
-
- if (!node) {
- preview->set_pressed(false);
- SpatialEditor::get_singleton()->set_custom_camera(NULL);
- } else {
-
- if (preview->is_pressed())
- SpatialEditor::get_singleton()->set_custom_camera(p_camera);
- else
- SpatialEditor::get_singleton()->set_custom_camera(NULL);
- }
-}
-
-
-CameraEditor::CameraEditor() {
-
- preview = memnew( Button );
- add_child(preview);
-
- preview->set_text(TTR("Preview"));
- preview->set_toggle_mode(true);
- preview->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
- preview->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
- preview->set_margin(MARGIN_LEFT,60);
- preview->set_margin(MARGIN_RIGHT,0);
- preview->set_margin(MARGIN_TOP,0);
- preview->set_margin(MARGIN_BOTTOM,10);
- preview->connect("pressed",this,"_pressed");
-
-}
-
-
-void CameraEditorPlugin::edit(Object *p_object) {
-
- SpatialEditor::get_singleton()->set_can_preview(p_object->cast_to<Camera>());
- //camera_editor->edit(p_object->cast_to<Node>());
-}
-
-bool CameraEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Camera");
-}
-
-void CameraEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- //SpatialEditor::get_singleton()->set_can_preview(p_object->cast_to<Camera>());
- } else {
- SpatialEditor::get_singleton()->set_can_preview(NULL);
- }
-
-}
-
-CameraEditorPlugin::CameraEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
-/* camera_editor = memnew( CameraEditor );
- editor->get_viewport()->add_child(camera_editor);
-
- camera_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
- camera_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
- camera_editor->set_margin(MARGIN_LEFT,60);
- camera_editor->set_margin(MARGIN_RIGHT,0);
- camera_editor->set_margin(MARGIN_TOP,0);
- camera_editor->set_margin(MARGIN_BOTTOM,10);
-
-
- camera_editor->hide();
-*/
-
-
-}
-
-
-CameraEditorPlugin::~CameraEditorPlugin()
-{
-}
-
-
diff --git a/tools/editor/plugins/camera_editor_plugin.h b/tools/editor/plugins/camera_editor_plugin.h
deleted file mode 100644
index 7e79d0ec74..0000000000
--- a/tools/editor/plugins/camera_editor_plugin.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*************************************************************************/
-/* camera_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 CAMERA_EDITOR_PLUGIN_H
-#define CAMERA_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/camera.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class CameraEditor : public Control {
-
- GDCLASS(CameraEditor, Control );
-
- Panel *panel;
- Button * preview;
- Node *node;
-
- void _pressed();
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- void edit(Node *p_camera);
- CameraEditor();
-};
-
-class CameraEditorPlugin : public EditorPlugin {
-
- GDCLASS( CameraEditorPlugin, EditorPlugin );
-
- //CameraEditor *camera_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "Camera"; }
- 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);
-
- CameraEditorPlugin(EditorNode *p_node);
- ~CameraEditorPlugin();
-
-};
-
-#endif // CAMERA_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
deleted file mode 100644
index bec7956b8c..0000000000
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ /dev/null
@@ -1,4063 +0,0 @@
-/*************************************************************************/
-/* canvas_item_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "canvas_item_editor_plugin.h"
-
-#include "print_string.h"
-#include "tools/editor/editor_node.h"
-#include "os/keyboard.h"
-#include "scene/main/viewport.h"
-#include "scene/main/canvas_layer.h"
-#include "scene/2d/sprite.h"
-#include "scene/2d/light_2d.h"
-#include "scene/2d/particles_2d.h"
-#include "scene/2d/polygon_2d.h"
-#include "scene/2d/screen_button.h"
-#include "globals.h"
-#include "os/input.h"
-#include "tools/editor/editor_settings.h"
-#include "scene/gui/grid_container.h"
-#include "scene/gui/patch_9_rect.h"
-#include "tools/editor/animation_editor.h"
-#include "tools/editor/plugins/animation_player_editor_plugin.h"
-#include "tools/editor/script_editor_debugger.h"
-#include "tools/editor/plugins/script_editor_plugin.h"
-#include "scene/resources/packed_scene.h"
-
-
-#define MIN_ZOOM 0.01
-#define MAX_ZOOM 100
-
-
-class SnapDialog : public ConfirmationDialog {
-
- GDCLASS(SnapDialog,ConfirmationDialog);
-
-friend class CanvasItemEditor;
-
- SpinBox *grid_offset_x;
- SpinBox *grid_offset_y;
- SpinBox *grid_step_x;
- SpinBox *grid_step_y;
- SpinBox *rotation_offset;
- SpinBox *rotation_step;
-
-public:
- SnapDialog() : ConfirmationDialog() {
- const int SPIN_BOX_GRID_RANGE = 256;
- const int SPIN_BOX_ROTATION_RANGE = 360;
- Label *label;
- VBoxContainer *container;
- GridContainer *child_container;
-
- set_title(TTR("Configure Snap"));
- get_ok()->set_text(TTR("Close"));
-
- container = memnew( VBoxContainer );
- add_child(container);
- //set_child_rect(container);
-
- child_container = memnew( GridContainer );
- child_container->set_columns(3);
- container->add_child(child_container);
-
- label = memnew( Label );
- label->set_text(TTR("Grid Offset:"));
- child_container->add_child(label);
- label->set_h_size_flags(SIZE_EXPAND_FILL);
-
- grid_offset_x = memnew( SpinBox );
- grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
- grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
- grid_offset_x->set_suffix("px");
- child_container->add_child(grid_offset_x);
-
- grid_offset_y = memnew( SpinBox );
- grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
- grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
- grid_offset_y->set_suffix("px");
- child_container->add_child(grid_offset_y);
-
- label = memnew( Label );
- label->set_text(TTR("Grid Step:"));
- child_container->add_child(label);
- label->set_h_size_flags(SIZE_EXPAND_FILL);
-
- grid_step_x = memnew( SpinBox );
- grid_step_x->set_min(-SPIN_BOX_GRID_RANGE);
- grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
- grid_step_x->set_suffix("px");
- child_container->add_child(grid_step_x);
-
- grid_step_y = memnew( SpinBox );
- grid_step_y->set_min(-SPIN_BOX_GRID_RANGE);
- grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
- grid_step_y->set_suffix("px");
- child_container->add_child(grid_step_y);
-
- container->add_child( memnew( HSeparator ) );
-
- child_container = memnew( GridContainer );
- child_container->set_columns(2);
- container->add_child(child_container);
-
- label = memnew( Label );
- label->set_text(TTR("Rotation Offset:"));
- child_container->add_child(label);
- label->set_h_size_flags(SIZE_EXPAND_FILL);
-
- rotation_offset = memnew( SpinBox );
- rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
- rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
- rotation_offset->set_suffix("deg");
- child_container->add_child(rotation_offset);
-
- label = memnew( Label );
- label->set_text(TTR("Rotation Step:"));
- child_container->add_child(label);
- label->set_h_size_flags(SIZE_EXPAND_FILL);
-
- rotation_step = memnew( SpinBox );
- rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
- rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
- rotation_step->set_suffix("deg");
- child_container->add_child(rotation_step);
- }
-
- void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
- grid_offset_x->set_value(p_grid_offset.x);
- grid_offset_y->set_value(p_grid_offset.y);
- grid_step_x->set_value(p_grid_step.x);
- grid_step_y->set_value(p_grid_step.y);
- rotation_offset->set_value(p_rotation_offset * (180 / Math_PI));
- rotation_step->set_value(p_rotation_step * (180 / Math_PI));
- }
-
- void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
- p_grid_offset.x = grid_offset_x->get_value();
- p_grid_offset.y = grid_offset_y->get_value();
- p_grid_step.x = grid_step_x->get_value();
- p_grid_step.y = grid_step_y->get_value();
- p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI);
- p_rotation_step = rotation_step->get_value() / (180 / Math_PI);
- }
-};
-
-void CanvasItemEditor::_edit_set_pivot(const Vector2& mouse_pos) {
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- undo_redo->create_action(TTR("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_position();
-
- 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_position());
- undo_redo->add_undo_method(n2dc,"set_global_pos",n2dc->get_global_position());
-
- }
-
- }
-
- }
-
- undo_redo->commit_action();
-
-}
-
-void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
-
- if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
- return;
-
- if (p_ev.key.mod.control)
- return;
-
- if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode==KEY_V && drag==DRAG_NONE && can_move_pivot) {
-
- if (p_ev.key.mod.shift) {
- //move drag pivot
- drag=DRAG_PIVOT;
- } else if (!Input::get_singleton()->is_mouse_button_pressed(0)) {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- Vector2 mouse_pos = viewport->get_local_mouse_pos();
- if (selection.size() && viewport->get_rect().has_point(mouse_pos)) {
- //just in case, make it work if over viewport
- mouse_pos=transform.affine_inverse().xform(mouse_pos);
- mouse_pos=snap_point(mouse_pos);
-
- _edit_set_pivot(mouse_pos);
- }
-
- }
- }
-
-}
-
-void CanvasItemEditor::_tool_select(int p_index) {
-
-
- 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);
- }
-
-
- viewport->update();
- tool=(Tool)p_index;
-
-}
-
-Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
-
- CanvasItem *ci = p_what->cast_to<CanvasItem>();
- if (!ci)
- return NULL;
-
- return memnew( CanvasItemEditorSelectedItem );
-}
-
-inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) {
- float offset = p_snap_relative ? p_start : p_offset;
- return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target;
-}
-
-Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const {
- if (snap_grid) {
- p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x);
- p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y);
- }
- if (snap_pixel)
- p_target = p_target.snapped(Size2(1, 1));
-
- return p_target;
-}
-
-float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
- return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target;
-}
-
-Dictionary CanvasItemEditor::get_state() const {
-
- Dictionary state;
- state["zoom"]=zoom;
- state["ofs"]=Point2(h_scroll->get_value(),v_scroll->get_value());
- //state["ofs"]=-transform.get_origin();
- state["snap_offset"]=snap_offset;
- state["snap_step"]=snap_step;
- state["snap_rotation_offset"]=snap_rotation_offset;
- state["snap_rotation_step"]=snap_rotation_step;
- state["snap_grid"]=snap_grid;
- state["snap_show_grid"]=snap_show_grid;
- state["snap_rotation"]=snap_rotation;
- state["snap_relative"]=snap_relative;
- state["snap_pixel"]=snap_pixel;
- state["skeleton_show_bones"]=skeleton_show_bones;
- return state;
-}
-void CanvasItemEditor::set_state(const Dictionary& p_state){
-
- Dictionary state=p_state;
- if (state.has("zoom")) {
- zoom=p_state["zoom"];
- }
-
- if (state.has("ofs")) {
- _update_scrollbars(); // i wonder how safe is calling this here..
- Point2 ofs=p_state["ofs"];
- h_scroll->set_value(ofs.x);
- v_scroll->set_value(ofs.y);
- }
-
- if (state.has("snap_step")) {
- snap_step=state["snap_step"];
- }
-
- if (state.has("snap_offset")) {
- snap_offset=state["snap_offset"];
- }
-
- if (state.has("snap_rotation_step")) {
- snap_rotation_step=state["snap_rotation_step"];
- }
-
- if (state.has("snap_rotation_offset")) {
- snap_rotation_offset=state["snap_rotation_offset"];
- }
-
- if (state.has("snap_grid")) {
- snap_grid=state["snap_grid"];
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
- edit_menu->get_popup()->set_item_checked(idx,snap_grid);
- }
-
- if (state.has("snap_show_grid")) {
- snap_show_grid=state["snap_show_grid"];
- int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
- edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
- }
-
- if (state.has("snap_rotation")) {
- snap_rotation=state["snap_rotation"];
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
- edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
- }
-
- if (state.has("snap_relative")) {
- snap_relative=state["snap_relative"];
- int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
- edit_menu->get_popup()->set_item_checked(idx,snap_relative);
- }
-
- if (state.has("snap_pixel")) {
- snap_pixel=state["snap_pixel"];
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
- edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
- }
-
- if (state.has("skeleton_show_bones")) {
- skeleton_show_bones=state["skeleton_show_bones"];
- int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES);
- skeleton_menu->set_item_checked(idx,skeleton_show_bones);
- }
-}
-
-
-void CanvasItemEditor::_add_canvas_item(CanvasItem *p_canvas_item) {
-
- editor_selection->add_node(p_canvas_item);
-#if 0
- if (canvas_items.has(p_canvas_item))
- return;
-
- canvas_items.insert(p_canvas_item,p_info);
- p_canvas_item->connect("hide",this,"_visibility_changed",varray(p_canvas_item->get_instance_ID()),CONNECT_ONESHOT);
-#endif
-}
-
-void CanvasItemEditor::_remove_canvas_item(CanvasItem *p_canvas_item) {
-
- editor_selection->remove_node(p_canvas_item);
-#if 0
- p_canvas_item->disconnect("hide",this,"_visibility_changed");
- canvas_items.erase(p_canvas_item);
-#endif
-
-}
-void CanvasItemEditor::_clear_canvas_items() {
-
- editor_selection->clear();
-#if 0
- while(canvas_items.size())
- _remove_canvas_item(canvas_items.front()->key());
-#endif
-}
-
-void CanvasItemEditor::_visibility_changed(ObjectID p_canvas_item) {
-#if 0
- Object *c = ObjectDB::get_instance(p_canvas_item);
- if (!c)
- return;
- CanvasItem *ct = c->cast_to<CanvasItem>();
- if (!ct)
- return;
- canvas_items.erase(ct);
- //_remove_canvas_item(ct);
- update();
-#endif
-}
-
-
-void CanvasItemEditor::_node_removed(Node *p_node) {
-#if 0
- CanvasItem *canvas_item = (CanvasItem*)p_node; //not a good cast, but safe
- if (canvas_items.has(canvas_item))
- _remove_canvas_item(canvas_item);
-
- update();
-#endif
-}
-
-void CanvasItemEditor::_keying_changed() {
-
- if (AnimationPlayerEditor::singleton->get_key_editor()->is_visible_in_tree())
- animation_hb->show();
- else
- animation_hb->hide();
-}
-
-bool CanvasItemEditor::_is_part_of_subscene(CanvasItem *p_item) {
-
- Node* scene_node = get_tree()->get_edited_scene_root();
- Node* item_owner = p_item->get_owner();
-
- return item_owner && item_owner!=scene_node && p_item!=scene_node && item_owner->get_filename()!="";
-}
-
-// slow but modern computers should have no problem
-CanvasItem* CanvasItemEditor::_select_canvas_item_at_pos(const Point2& p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform) {
-
- if (!p_node)
- return NULL;
- if (p_node->cast_to<Viewport>())
- return NULL;
-
- CanvasItem *c=p_node->cast_to<CanvasItem>();
-
-
- for (int i=p_node->get_child_count()-1;i>=0;i--) {
-
- CanvasItem *r=NULL;
-
- if (c && !c->is_set_as_toplevel())
- r=_select_canvas_item_at_pos(p_pos,p_node->get_child(i),p_parent_xform * c->get_transform(),p_canvas_xform);
- else {
- CanvasLayer *cl = p_node->cast_to<CanvasLayer>();
- r=_select_canvas_item_at_pos(p_pos,p_node->get_child(i),transform ,cl ? cl->get_transform() : p_canvas_xform); //use base transform
- }
-
- if (r)
- return r;
- }
-
- if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !_is_part_of_subscene(c) && !c->cast_to<CanvasLayer>()) {
-
- Rect2 rect = c->get_item_rect();
- Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos);
-
-
- if (rect.has_point(local_pos))
- return c;
-
- }
-
- return NULL;
-}
-
-void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform, Vector<_SelectResult> &r_items) {
- if (!p_node)
- return;
- if (p_node->cast_to<Viewport>())
- return;
-
- CanvasItem *c=p_node->cast_to<CanvasItem>();
-
- for (int i=p_node->get_child_count()-1;i>=0;i--) {
-
- if (c && !c->is_set_as_toplevel())
- _find_canvas_items_at_pos(p_pos,p_node->get_child(i),p_parent_xform * c->get_transform(),p_canvas_xform, r_items);
- else {
- CanvasLayer *cl = p_node->cast_to<CanvasLayer>();
- _find_canvas_items_at_pos(p_pos,p_node->get_child(i),transform ,cl ? cl->get_transform() : p_canvas_xform, r_items); //use base transform
- }
- }
-
-
- if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !c->cast_to<CanvasLayer>()) {
-
- Rect2 rect = c->get_item_rect();
- Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos);
-
-
- if (rect.has_point(local_pos)) {
- Node2D *node=c->cast_to<Node2D>();
-
- _SelectResult res;
- res.item=c;
- res.z=node?node->get_z():0;
- res.has_z=node;
- r_items.push_back(res);
- }
-
- }
-
- return;
-}
-
-void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform,List<CanvasItem*> *r_items) {
-
- if (!p_node)
- return;
- if (p_node->cast_to<Viewport>())
- return;
-
- CanvasItem *c=p_node->cast_to<CanvasItem>();
-
-
- bool inherited=p_node!=get_tree()->get_edited_scene_root() && p_node->get_filename()!="";
- bool editable=false;
- if (inherited){
- editable=EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
- }
- bool lock_children=p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
- if (!lock_children && (!inherited || editable)) {
- for (int i=p_node->get_child_count()-1;i>=0;i--) {
-
- if (c && !c->is_set_as_toplevel())
- _find_canvas_items_at_rect(p_rect,p_node->get_child(i),p_parent_xform * c->get_transform(),p_canvas_xform,r_items);
- else {
- CanvasLayer *cl = p_node->cast_to<CanvasLayer>();
- _find_canvas_items_at_rect(p_rect,p_node->get_child(i),transform,cl?cl->get_transform():p_canvas_xform,r_items);
- }
- }
- }
-
- if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !c->cast_to<CanvasLayer>()) {
-
- Rect2 rect = c->get_item_rect();
- Transform2D xform = p_parent_xform * p_canvas_xform * c->get_transform();
-
- if ( p_rect.has_point( xform.xform( rect.pos ) ) &&
- p_rect.has_point( xform.xform( rect.pos+Vector2(rect.size.x,0) ) ) &&
- p_rect.has_point( xform.xform( rect.pos+Vector2(rect.size.x,rect.size.y) ) ) &&
- p_rect.has_point( xform.xform( rect.pos+Vector2(0,rect.size.y) ) ) ) {
-
- r_items->push_back(c);
-
- }
- }
-
-
-}
-
-bool CanvasItemEditor::_select(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag) {
-
- if (p_append) {
- //additive selection
-
- if (!item) {
-
- if (p_drag) {
- drag_from=transform.affine_inverse().xform(p_click_pos);
-
- box_selecting=true;
- box_selecting_to=drag_from;
- }
-
- return false; //nothing to add
- }
-
- if (editor_selection->is_selected(item)) {
- //already in here, erase it
- editor_selection->remove_node(item);
- //_remove_canvas_item(c);
-
- viewport->update();
- return false;
-
- }
- _append_canvas_item(item);
- viewport->update();
-
- return true;
-
- } else {
- //regular selection
-
- if (!item) {
- //clear because nothing clicked
- editor_selection->clear();
-
- if (p_drag) {
- drag_from=transform.affine_inverse().xform(p_click_pos);
-
- box_selecting=true;
- box_selecting_to=drag_from;
- }
-
- viewport->update();
- return false;
- }
-
- if (!editor_selection->is_selected(item)) {
- //select a new one and clear previous selection
- editor_selection->clear();
- editor_selection->add_node(item);
- //reselect
- if (get_tree()->is_editor_hint()) {
- editor->call("edit_node",item);
- }
-
- }
-
- if (p_drag) {
- //prepare to move!
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- se->undo_state=canvas_item->edit_get_state();
- if (canvas_item->cast_to<Node2D>())
- se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
-
- }
-
- drag=DRAG_ALL;
- drag_from=transform.affine_inverse().xform(p_click_pos);
- drag_point_from=_find_topleftmost_point();
- }
-
- viewport->update();
-
- return true;
-
- }
-}
-
-void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE p_move_mode) {
-
-
- if (drag!=DRAG_NONE)
- return;
-
- if (editor_selection->get_selected_node_list().empty())
- return;
-
- undo_redo->create_action(TTR("Move Action"),UndoRedo::MERGE_ENDS);
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- if (canvas_item->has_meta("_edit_lock_"))
- continue;
-
-
- Vector2 drag = p_dir;
- if (p_snap)
- drag*=snap_step;
-
- undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state());
-
- if (p_move_mode == MOVE_VIEW_BASE) {
-
- // drag = transform.affine_inverse().basis_xform(p_dir); // zoom sensitive
- drag = canvas_item->get_global_transform_with_canvas().affine_inverse().basis_xform(drag);
- Rect2 local_rect = canvas_item->get_item_rect();
- local_rect.pos+=drag;
- undo_redo->add_do_method(canvas_item,"edit_set_rect",local_rect);
-
- } else { // p_move_mode==MOVE_LOCAL_BASE || p_move_mode==MOVE_LOCAL_WITH_ROT
-
- if (Node2D *node_2d = canvas_item->cast_to<Node2D>()) {
-
- if (p_move_mode == MOVE_LOCAL_WITH_ROT) {
- Transform2D m;
- m.rotate( node_2d->get_rotation() );
- drag = m.xform(drag);
- }
- node_2d->set_position(node_2d->get_position() + drag);
-
- } else if (Control *control = canvas_item->cast_to<Control>()) {
-
- control->set_pos(control->get_pos()+drag);
- }
- }
- }
-
- undo_redo->commit_action();
-}
-
-Point2 CanvasItemEditor::_find_topleftmost_point() {
-
-
-
- Vector2 tl=Point2(1e10,1e10);
- Rect2 r2;
- r2.pos=tl;
-
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
-
-
-
- Rect2 rect=canvas_item->get_item_rect();
- Transform2D xform=canvas_item->get_global_transform_with_canvas();
-
- r2.expand_to(xform.xform(rect.pos));
- r2.expand_to(xform.xform(rect.pos+Vector2(rect.size.x,0)));
- r2.expand_to(xform.xform(rect.pos+rect.size));
- r2.expand_to(xform.xform(rect.pos+Vector2(0,rect.size.y)));
-
- }
-
- return r2.pos;
-}
-
-
-
-int CanvasItemEditor::get_item_count() {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- int ic=0;
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- ic++;
- };
-
- return ic;
-}
-
-CanvasItem *CanvasItemEditor::get_single_item() {
-
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- CanvasItem *single_item=NULL;
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- if (single_item)
- return NULL; //morethan one
-
- single_item=canvas_item;
- };
-
- return single_item;
-}
-
-CanvasItemEditor::DragType CanvasItemEditor::_find_drag_type(const Transform2D& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point) {
-
- CanvasItem *canvas_item = get_single_item();
-
- ERR_FAIL_COND_V(!canvas_item,DRAG_NONE);
-
- Rect2 rect=canvas_item->get_item_rect();
- Transform2D xforml=canvas_item->get_global_transform_with_canvas();
- Transform2D xform=transform * xforml;
-
- Vector2 endpoints[4]={
-
- xform.xform(rect.pos),
- xform.xform(rect.pos+Vector2(rect.size.x,0)),
- xform.xform(rect.pos+rect.size),
- xform.xform(rect.pos+Vector2(0,rect.size.y))
- };
-
- Vector2 endpointsl[4]={
-
- xforml.xform(rect.pos),
- xforml.xform(rect.pos+Vector2(rect.size.x,0)),
- xforml.xform(rect.pos+rect.size),
- xforml.xform(rect.pos+Vector2(0,rect.size.y))
- };
-
- DragType dragger[]={
- DRAG_TOP_LEFT,
- DRAG_TOP,
- DRAG_TOP_RIGHT,
- DRAG_RIGHT,
- DRAG_BOTTOM_RIGHT,
- DRAG_BOTTOM,
- DRAG_BOTTOM_LEFT,
- DRAG_LEFT
- };
-
- float radius = (select_handle->get_size().width/2)*1.5;
-
- //try draggers
-
- for(int i=0;i<4;i++) {
-
- int prev = (i+3)%4;
- int next = (i+1)%4;
-
- r_point=endpointsl[i];
-
- Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
- ofs*=1.4144*(select_handle->get_size().width/2);
-
- ofs+=endpoints[i];
-
- if (ofs.distance_to(p_click)<radius)
- return dragger[i*2];
-
- ofs = (endpoints[i]+endpoints[next])/2;
- ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2);
-
- r_point=(endpointsl[i]+endpointsl[next])/2;
-
-
- if (ofs.distance_to(p_click)<radius)
- return dragger[i*2+1];
-
- }
-
- /*
- if (rect.has_point(xform.affine_inverse().xform(p_click))) {
- r_point=_find_topleftmost_point();
- return DRAG_ALL;
- }*/
-
- //try draggers
-
- return DRAG_NONE;
-}
-
-void CanvasItemEditor::incbeg(float& beg,float &end, float inc, float minsize,bool p_symmetric) {
-
- if (minsize<0) {
-
- beg+=inc;
- if (p_symmetric)
- end-=inc;
- } else {
-
- if (p_symmetric) {
- beg+=inc;
- end-=inc;
- if (end-beg < minsize) {
- float center = (beg+end)/2.0;
- beg=center-minsize/2.0;
- end=center+minsize/2.0;
- }
-
- } else {
- if (end-(beg+inc) < minsize)
- beg=end-minsize;
- else
- beg+=inc;
- }
-
- }
-}
-
-void CanvasItemEditor::incend(float &beg,float& end, float inc, float minsize,bool p_symmetric) {
-
- if (minsize<0) {
-
- end+=inc;
- if (p_symmetric)
- beg-=inc;
- } else {
-
- if (p_symmetric) {
-
- end+=inc;
- beg-=inc;
- if (end-beg < minsize) {
- float center = (beg+end)/2.0;
- beg=center-minsize/2.0;
- end=center+minsize/2.0;
- }
-
- } else {
- if ((end+inc)-beg < minsize)
- end=beg+minsize;
- else
- end+=inc;
- }
-
- }
-}
-
-void CanvasItemEditor::_append_canvas_item(CanvasItem *c) {
-
- editor_selection->add_node(c);
-
-}
-
-
-void CanvasItemEditor::_snap_changed() {
- ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
- viewport->update();
-}
-
-void CanvasItemEditor::_dialog_value_changed(double) {
-
- if (updating_value_dialog)
- return;
-
- switch(last_option) {
-
- case ZOOM_SET: {
-
- zoom=dialog_val->get_value()/100.0;
- _update_scroll(0);
- viewport->update();
-
- } break;
- default:{}
- }
-}
-
-void CanvasItemEditor::_selection_result_pressed(int p_result) {
-
- if (selection_results.size() <= p_result)
- return;
-
- CanvasItem *item=selection_results[p_result].item;
-
- if (item)
- _select(item, Point2(), additive_selection, false);
-}
-
-void CanvasItemEditor::_selection_menu_hide() {
-
- selection_results.clear();
- selection_menu->clear();
- selection_menu->set_size(Vector2(0, 0));
-}
-
-bool CanvasItemEditor::get_remove_list(List<Node*> *p_list) {
-
-
- return false;//!p_list->empty();
-}
-
-
-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,Transform2D(), 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_class(),"EditorIcons")?item->get_class():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_class()+"\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_gui_input(const InputEvent& p_event) {
-
- {
-
- EditorNode *en = editor;
- EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
-
- if (!over_plugin_list->empty()) {
- bool discard = over_plugin_list->forward_gui_input(transform,p_event);
- if (discard) {
- accept_event();
- return;
- }
- }
- }
-
-
- if (p_event.type==InputEvent::MOUSE_BUTTON) {
-
- const InputEventMouseButton &b=p_event.mouse_button;
-
-
- if (b.button_index==BUTTON_WHEEL_DOWN) {
-
- if (zoom<MIN_ZOOM)
- return;
-
- float prev_zoom=zoom;
- zoom=zoom*0.95;
- {
- Point2 ofs(b.x,b.y);
- ofs = ofs/prev_zoom - ofs/zoom;
- h_scroll->set_value( h_scroll->get_value() + ofs.x );
- v_scroll->set_value( v_scroll->get_value() + ofs.y );
- }
- _update_scroll(0);
- viewport->update();
- return;
- }
-
- if (b.button_index==BUTTON_WHEEL_UP) {
-
- if (zoom>MAX_ZOOM)
- return;
-
- float prev_zoom=zoom;
- zoom=zoom*(1.0/0.95);
- {
- Point2 ofs(b.x,b.y);
- ofs = ofs/prev_zoom - ofs/zoom;
- h_scroll->set_value( h_scroll->get_value() + ofs.x );
- v_scroll->set_value( v_scroll->get_value() + ofs.y );
- }
-
- _update_scroll(0);
- viewport->update();
- return;
- }
-
- if (b.button_index==BUTTON_RIGHT) {
-
-
- if (b.pressed && (tool==TOOL_SELECT && b.mod.alt)) {
-
- _list_select(b);
- return;
- }
-
- if (get_item_count() > 0 && drag!=DRAG_NONE) {
- //cancel drag
-
- if (bone_ik_list.size()) {
-
- for(List<BoneIK>::Element *E=bone_ik_list.back();E;E=E->prev()) {
-
- E->get().node->edit_set_state(E->get().orig_state);
- }
-
- bone_ik_list.clear();
-
- } else {
-
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
-
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- canvas_item->edit_set_state(se->undo_state);
- if (canvas_item->cast_to<Node2D>())
- canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot);
-
- }
- }
-
- drag=DRAG_NONE;
- viewport->update();
- can_move_pivot=false;
-
- } else if (box_selecting) {
- box_selecting=false;
- viewport->update();
- } else if (b.pressed) {
-#if 0
- ref_item = NULL;
- Node* scene = get_scene()->get_root_node()->cast_to<EditorNode>()->get_edited_scene();
- if ( scene ) ref_item =_select_canvas_item_at_pos( Point2( b.x, b.y ), scene, transform );
-#endif
- //popup->set_pos(Point2(b.x,b.y));
- //popup->popup();
- }
- return;
- }
- /*
- 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;
-
- if (!b.pressed) {
-
- if (drag!=DRAG_NONE) {
-
- if (undo_redo) {
-
-
- if (bone_ik_list.size()) {
-
-
- undo_redo->create_action(TTR("Edit IK Chain"));
-
- for(List<BoneIK>::Element *E=bone_ik_list.back();E;E=E->prev()) {
-
- undo_redo->add_do_method(E->get().node,"edit_set_state",E->get().node->edit_get_state());
- undo_redo->add_undo_method(E->get().node,"edit_set_state",E->get().orig_state);
- }
-
- undo_redo->add_do_method(viewport,"update");
- undo_redo->add_undo_method(viewport,"update");
-
- bone_ik_list.clear();
-
- undo_redo->commit_action();
- } else {
-
- undo_redo->create_action(TTR("Edit CanvasItem"));
-
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- Variant state=canvas_item->edit_get_state();
- undo_redo->add_do_method(canvas_item,"edit_set_state",state);
- undo_redo->add_undo_method(canvas_item,"edit_set_state",se->undo_state);
- if (canvas_item->cast_to<Node2D>()) {
- Node2D *pvt = canvas_item->cast_to<Node2D>();
- if (pvt->edit_has_pivot()) {
- undo_redo->add_do_method(canvas_item,"edit_set_pivot",pvt->edit_get_pivot());
- undo_redo->add_undo_method(canvas_item,"edit_set_pivot",se->undo_pivot);
- }
- }
- }
- undo_redo->commit_action();
- }
- }
-
- drag=DRAG_NONE;
- viewport->update();
- can_move_pivot=false;
-
- }
-
- if (box_selecting) {
-#if 0
- if ( ! b.mod.shift ) _clear_canvas_items();
- if ( box_selection_end() ) return;
-#endif
-
- Node* scene = editor->get_edited_scene();
- if (scene) {
-
- List<CanvasItem*> selitems;
-
- Point2 bsfrom = transform.xform(drag_from);
- Point2 bsto= transform.xform(box_selecting_to);
- if (bsfrom.x>bsto.x)
- SWAP(bsfrom.x,bsto.x);
- if (bsfrom.y>bsto.y)
- SWAP(bsfrom.y,bsto.y);
-
- _find_canvas_items_at_rect(Rect2(bsfrom,bsto-bsfrom),scene,transform,Transform2D(),&selitems);
-
- for(List<CanvasItem*>::Element *E=selitems.front();E;E=E->next()) {
-
- _append_canvas_item(E->get());
- }
-
- }
-
- box_selecting=false;
- viewport->update();
-
- }
- return;
- }
-
-
- Map<ObjectID,BoneList>::Element *Cbone=NULL; //closest
-
- {
- bone_ik_list.clear();
- float closest_dist=1e20;
- int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
- for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) {
-
- if (E->get().from == E->get().to)
- continue;
- Vector2 s[2]={
- E->get().from,
- E->get().to
- };
-
- Vector2 p = Geometry::get_closest_point_to_segment_2d(Vector2(b.x,b.y),s);
- float d = p.distance_to(Vector2(b.x,b.y));
- if (d<bone_width && d<closest_dist) {
- Cbone=E;
- closest_dist=d;
- }
- }
-
- if (Cbone) {
- Node2D *b=NULL;
- Object* obj=ObjectDB::get_instance(Cbone->get().bone);
- if (obj)
- b=obj->cast_to<Node2D>();
-
- if (b) {
-
-
- bool ik_found=false;
- bool first=true;
-
-
-
- while(b) {
-
- CanvasItem *pi=b->get_parent_item();
- if (!pi)
- break;
-
- float len=pi->get_global_transform().get_origin().distance_to(b->get_global_position());
- b=pi->cast_to<Node2D>();
- if (!b)
- break;
-
- if (first) {
-
- bone_orig_xform=b->get_global_transform();
- first=false;
- }
-
- BoneIK bik;
- bik.node=b;
- bik.len=len;
- bik.orig_state=b->edit_get_state();
-
- bone_ik_list.push_back(bik);
-
- if (b->has_meta("_edit_ik_")) {
-
- ik_found=bone_ik_list.size()>1;
- break;
- }
-
- if (!pi->has_meta("_edit_bone_"))
- break;
-
- }
-
- if (!ik_found)
- bone_ik_list.clear();
-
- }
- }
- }
-
- CanvasItem *single_item = get_single_item();
-
- if (single_item) {
- //try single canvas_item edit
-
- CanvasItem *canvas_item = single_item;
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- ERR_FAIL_COND(!se);
-
-
- Point2 click(b.x,b.y);
-
- if ((b.mod.control && tool==TOOL_SELECT) || tool==TOOL_ROTATE) {
-
- drag=DRAG_ROTATE;
- drag_from=transform.affine_inverse().xform(click);
- se->undo_state=canvas_item->edit_get_state();
- if (canvas_item->cast_to<Node2D>())
- se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
- if (canvas_item->cast_to<Control>())
- se->undo_pivot=Vector2();
- return;
- }
-
- Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
- Rect2 rect=canvas_item->get_item_rect();
- //float handle_radius = handle_len * 1.4144; //magic number, guess what it means!
-
- if (tool==TOOL_SELECT) {
- drag = _find_drag_type(xform,rect,click,drag_point_from);
-
- if (b.doubleclick) {
-
- if (canvas_item->get_filename()!="" && canvas_item!=editor->get_edited_scene()) {
-
- editor->open_request(canvas_item->get_filename());
- return;
- }
- }
-
- if (drag!=DRAG_NONE && (!Cbone || drag!=DRAG_ALL)) {
- drag_from=transform.affine_inverse().xform(click);
- se->undo_state=canvas_item->edit_get_state();
- if (canvas_item->cast_to<Node2D>())
- se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
-
- return;
- }
- } else {
-
- drag=DRAG_NONE;
- }
- }
-
- //multi canvas_item edit
-
-
- Point2 click=Point2(b.x,b.y);
-
- if ((b.mod.alt || tool==TOOL_MOVE) && get_item_count()) {
-
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- se->undo_state=canvas_item->edit_get_state();
- if (canvas_item->cast_to<Node2D>())
- se->undo_pivot=canvas_item->cast_to<Node2D>()->edit_get_pivot();
-
- }
-
-
- drag=DRAG_ALL;
- drag_from=transform.affine_inverse().xform(click);
- drag_point_from=_find_topleftmost_point();
- viewport->update();
- return;
-
- }
-
- Node* scene = editor->get_edited_scene();
- if (!scene)
- return;
-
- /*
- if (current_window) {
- //no window.... ?
- click-=current_window->get_scroll();
- }*/
- CanvasItem *c=NULL;
-
- if (Cbone) {
-
- Object* obj=ObjectDB::get_instance(Cbone->get().bone);
- if (obj)
- c=obj->cast_to<CanvasItem>();
- if (c)
- c=c->get_parent_item();
-
-
- }
- if (!c) {
- c =_select_canvas_item_at_pos(click, scene,transform,Transform2D());
-
-
- CanvasItem* cn = c;
-
- while(cn) {
- if (cn->has_meta("_edit_group_")) {
- c=cn;
- }
- cn=cn->get_parent_item();
- }
- }
-
- Node* n = c;
-
- while ((n && n != scene && n->get_owner() != scene) || (n && !n->is_class("CanvasItem"))) {
- n = n->get_parent();
- };
- c = n->cast_to<CanvasItem>();
-#if 0
- if ( b.pressed ) box_selection_start( click );
-#endif
-
- additive_selection=b.mod.shift;
- if (!_select(c, click, additive_selection))
- return;
-
- }
-
- if (p_event.type==InputEvent::MOUSE_MOTION) {
-
- if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
- viewport->call_deferred("grab_focus");
-
- const InputEventMouseMotion &m=p_event.mouse_motion;
-
- if (box_selecting) {
-
- box_selecting_to=transform.affine_inverse().xform(Point2(m.x,m.y));
- viewport->update();
- return;
-
- }
-
-
- if (drag==DRAG_NONE) {
-
-
- if ( (m.button_mask&BUTTON_MASK_LEFT && tool == TOOL_PAN) || m.button_mask&BUTTON_MASK_MIDDLE || (m.button_mask&BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
- h_scroll->set_value( h_scroll->get_value() - m.relative_x/zoom);
- v_scroll->set_value( v_scroll->get_value() - m.relative_y/zoom);
- }
-
- return;
-
- }
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- bool dragging_bone = drag==DRAG_ALL && selection.size()==1 && bone_ik_list.size();
-
-
- if (!dragging_bone) {
- canvas_item->edit_set_state(se->undo_state); //reset state and reapply
- if (canvas_item->cast_to<Node2D>())
- canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot);
- }
-
-
- Vector2 dfrom = drag_from;
- Vector2 dto = transform.affine_inverse().xform(Point2(m.x,m.y));
- if (canvas_item->has_meta("_edit_lock_"))
- continue;
-
-
- if (drag==DRAG_ROTATE) {
-
- Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
- {
- Node2D *node = canvas_item->cast_to<Node2D>();
-
-
- if (node) {
- real_t angle = node->get_rotation();
- node->set_rotation(snap_angle( angle + (dfrom - center).angle_to(dto-center), angle ));
- display_rotate_to = dto;
- display_rotate_from = center;
- viewport->update();
- }
- }
-
- {
- Control *node = canvas_item->cast_to<Control>();
-
-
- if (node) {
- real_t angle = node->get_rotation();
- node->set_rotation(snap_angle( angle + (dfrom - center).angle_to(dto-center), angle ));
- display_rotate_to = dto;
- display_rotate_from = center;
- viewport->update();
- }
- }
-
- continue;
- }
-
-
- bool uniform = m.mod.shift;
- bool symmetric=m.mod.alt;
-
- dto = dto - (drag == DRAG_ALL ? drag_from - drag_point_from : Vector2(0, 0));
-
- if(uniform && drag == DRAG_ALL) {
- if(ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) {
- dto.y = drag_point_from.y;
- } else {
- dto.x = drag_point_from.x;
- }
- }
-
- dfrom = drag_point_from;
- dto = snap_point(dto, drag_point_from);
-
- Vector2 drag_vector =
- 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();
- Vector2 begin=local_rect.pos;
- Vector2 end=local_rect.pos+local_rect.size;
- Vector2 minsize = canvas_item->edit_get_minimum_size();
-
- if (uniform) {
- float aspect = local_rect.size.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: {
- begin+=drag_vector;
- end+=drag_vector;
- } break;
- case DRAG_RIGHT: {
-
- incend(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
-
- } break;
- case DRAG_BOTTOM: {
-
- incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
-
- } break;
- case DRAG_BOTTOM_RIGHT: {
-
- incend(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
- incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
- } break;
- case DRAG_TOP_LEFT: {
-
- incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
- incbeg(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
- } break;
- case DRAG_TOP: {
-
- incbeg(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
-
- } break;
- case DRAG_LEFT: {
-
- incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
-
- } break;
- case DRAG_TOP_RIGHT: {
-
- 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: {
-
- incbeg(begin.x,end.x,drag_vector.x,minsize.x,symmetric);
- incend(begin.y,end.y,drag_vector.y,minsize.y,symmetric);
- } break;
- case DRAG_PIVOT: {
-
- if (canvas_item->cast_to<Node2D>()) {
- Node2D *n2d =canvas_item->cast_to<Node2D>();
- n2d->edit_set_pivot(se->undo_pivot+drag_vector);
-
- }
- continue;
- } break;
-
- default:{}
- }
-
-
-
- if (!dragging_bone) {
-
- local_rect.pos=begin;
- local_rect.size=end-begin;
- canvas_item->edit_set_rect(local_rect);
-
- } else {
- //ok, all that had to be done was done, now solve IK
-
-
-
-
- Node2D *n2d = canvas_item->cast_to<Node2D>();
- Transform2D final_xform = bone_orig_xform;
-
-
-
- if (n2d) {
-
- float total_len = 0;
- for (List<BoneIK>::Element *E=bone_ik_list.front();E;E=E->next()) {
- if (E->prev())
- total_len+=E->get().len;
- E->get().pos = E->get().node->get_global_transform().get_origin();
- }
-
- {
-
- final_xform.elements[2]+=dto-dfrom;//final_xform.affine_inverse().basis_xform_inv(drag_vector);
- //n2d->set_global_transform(final_xform);
-
- }
-
-
- CanvasItem *last = bone_ik_list.back()->get().node;
- if (!last)
- break;
-
- Vector2 root_pos = last->get_global_transform().get_origin();
- Vector2 leaf_pos = final_xform.get_origin();
-
- if ((leaf_pos.distance_to(root_pos)) > total_len) {
- //oops dude you went too far
- //print_line("TOO FAR!");
- Vector2 rel = leaf_pos - root_pos;
- rel = rel.normalized() * total_len;
- leaf_pos=root_pos+rel;
-
- }
-
- bone_ik_list.front()->get().pos=leaf_pos;
-
- //print_line("BONE IK LIST "+itos(bone_ik_list.size()));
-
-
- if (bone_ik_list.size()>2) {
- int solver_iterations=64;
- float solver_k=0.3;
-
- for(int i=0;i<solver_iterations;i++) {
-
- for (List<BoneIK>::Element *E=bone_ik_list.front();E;E=E->next()) {
-
-
-
- if (E==bone_ik_list.back()) {
-
- break;
- }
-
- float len = E->next()->get().len;
-
- if (E->next()==bone_ik_list.back()) {
-
- //print_line("back");
-
- Vector2 rel = E->get().pos - E->next()->get().pos;
- //print_line("PREV "+E->get().pos);
- Vector2 desired = E->next()->get().pos+rel.normalized()*len;
- //print_line("DESIRED "+desired);
- E->get().pos=E->get().pos.linear_interpolate(desired,solver_k);
- //print_line("POST "+E->get().pos);
-
-
- } else if (E==bone_ik_list.front()) {
- //only adjust parent
- //print_line("front");
- Vector2 rel = E->next()->get().pos - E->get().pos;
- //print_line("PREV "+E->next()->get().pos);
- Vector2 desired = E->get().pos+rel.normalized()*len;
- //print_line("DESIRED "+desired);
- E->next()->get().pos=E->next()->get().pos.linear_interpolate(desired,solver_k);
- //print_line("POST "+E->next()->get().pos);
- } else {
-
- Vector2 rel = E->next()->get().pos - E->get().pos;
- Vector2 cen = (E->next()->get().pos + E->get().pos)*0.5;
- rel=rel.linear_interpolate(rel.normalized()*len,solver_k);
- rel*=0.5;
- E->next()->get().pos=cen+rel;
- E->get().pos=cen-rel;
- //print_line("mid");
-
- }
- }
- }
- }
- }
-
- for (List<BoneIK>::Element *E=bone_ik_list.back();E;E=E->prev()) {
-
- Node2D *n = E->get().node;
-
- if (!E->prev()) {
- //last goes to what it was
- final_xform.set_origin(n->get_global_position());
- n->set_global_transform(final_xform);
-
- } else {
- Vector2 rel = (E->prev()->get().node->get_global_position() - n->get_global_position()).normalized();
- Vector2 rel2 = (E->prev()->get().pos - E->get().pos).normalized();
- float rot = rel.angle_to(rel2);
- if (n->get_global_transform().basis_determinant()<0) {
- //mirrored, rotate the other way
- rot=-rot;
- }
-
- n->rotate(rot);
- }
-
- }
-
-
-
- break;
- }
- }
- }
-
- if (p_event.type==InputEvent::KEY) {
-
- const InputEventKey &k=p_event.key;
-
- if (k.pressed && drag==DRAG_NONE) {
-
- KeyMoveMODE move_mode = MOVE_VIEW_BASE;
- if (k.mod.alt) move_mode = MOVE_LOCAL_BASE;
- if (k.mod.control || k.mod.meta) move_mode = MOVE_LOCAL_WITH_ROT;
-
- if (k.scancode==KEY_UP)
- _key_move( Vector2(0,-1), k.mod.shift, move_mode );
- else if (k.scancode==KEY_DOWN)
- _key_move( Vector2(0,1), k.mod.shift, move_mode );
- else if (k.scancode==KEY_LEFT)
- _key_move( Vector2(-1,0), k.mod.shift, move_mode );
- else if (k.scancode==KEY_RIGHT)
- _key_move( Vector2(1,0), k.mod.shift, move_mode );
- else if (k.scancode==KEY_ESCAPE) {
- editor_selection->clear();
- viewport->update();
- }
- else
- return;
-
- accept_event();
- }
-
- }
-
-
-
-
-}
-
-void CanvasItemEditor::_viewport_draw() {
-
- // TODO fetch the viewport?
-
- Ref<Texture> pivot = get_icon("EditorPivot","EditorIcons");
- _update_scrollbars();
- RID ci=viewport->get_canvas_item();
-
- if (snap_show_grid) {
- Size2 s = viewport->get_size();
- int last_cell;
- Transform2D xform = transform.affine_inverse();
-
- if (snap_step.x!=0) {
- for(int i=0;i<s.width;i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- }
-
- if (snap_step.y!=0) {
- for(int i=0;i<s.height;i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- }
- }
-
- if (viewport->has_focus()) {
- Size2 size = viewport->get_size();
- if (v_scroll->is_visible_in_tree())
- size.width-=v_scroll->get_size().width;
- if (h_scroll->is_visible_in_tree())
- size.height-=h_scroll->get_size().height;
-
- get_stylebox("EditorFocus","EditorStyles")->draw(ci,Rect2(Point2(),size));
- }
-
- Ref<Texture> lock = get_icon("Lock","EditorIcons");
- Ref<Texture> group = get_icon("Group","EditorIcons");
-
-
- bool single = get_single_item()!=NULL;
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- bool pivot_found=false;
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
-
- CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
-
- Rect2 rect=canvas_item->get_item_rect();
-
- Transform2D xform=transform * canvas_item->get_global_transform_with_canvas();
- VisualServer::get_singleton()->canvas_item_add_set_transform(ci,xform);
-
- Vector2 endpoints[4]={
-
- xform.xform(rect.pos),
- xform.xform(rect.pos+Vector2(rect.size.x,0)),
- xform.xform(rect.pos+rect.size),
- xform.xform(rect.pos+Vector2(0,rect.size.y))
- };
-
- Color c = Color(1,0.6,0.4,0.7);
-
- VisualServer::get_singleton()->canvas_item_add_set_transform(ci,Transform2D());
-
- for(int i=0;i<4;i++) {
- viewport->draw_line(endpoints[i],endpoints[(i+1)%4],c,2);
- }
-
- if (single && (tool==TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool==TOOL_EDIT_PIVOT)) { //kind of sucks
-
- if (canvas_item->cast_to<Node2D>()) {
-
-
- 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;
- }
-
- }
-
-
- if (tool==TOOL_SELECT) {
-
-
- for(int i=0;i<4;i++) {
-
- int prev = (i+3)%4;
- int next = (i+1)%4;
-
- Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
- ofs*=1.4144*(select_handle->get_size().width/2);
-
- select_handle->draw(ci,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor());
-
- ofs = (endpoints[i]+endpoints[next])/2;
- ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2);
-
- select_handle->draw(ci,(ofs-(select_handle->get_size()/2)).floor());
-
- }
-
- }
- }
-
-
-
- //DRAW_EMPTY_RECT( Rect2( current_window->get_scroll()-Point2(1,1), get_size()+Size2(2,2)), Color(0.8,0.8,1.0,0.8) );
- //E->get().last_rect = rect;
- }
-
- pivot_button->set_disabled(!pivot_found);
- VisualServer::get_singleton()->canvas_item_add_set_transform(ci,Transform2D());
-
-
-
- Color x_axis_color(1.0,0.4,0.4,0.6);
- Color y_axis_color(0.4,1.0,0.4,0.6);
- Color area_axis_color(0.4,0.4,1.0,0.4);
- Color rotate_color(0.4,0.7,1.0,0.8);
-
- VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(h_scroll->get_min(),0)+transform.get_origin(),Point2(h_scroll->get_max(),0)+transform.get_origin(),x_axis_color);
- VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(0,v_scroll->get_min())+transform.get_origin(),Point2(0,v_scroll->get_max())+transform.get_origin(),y_axis_color);
-
-
- if (box_selecting) {
-
- Point2 bsfrom = transform.xform(drag_from);
- Point2 bsto= transform.xform(box_selecting_to);
-
-
- VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(bsfrom,bsto-bsfrom),Color(0.7,0.7,1.0,0.3));
- }
-
- if (drag==DRAG_ROTATE) {
- VisualServer::get_singleton()->canvas_item_add_line(ci,transform.xform(display_rotate_from), transform.xform(display_rotate_to),rotate_color);
- }
-
- Size2 screen_size = Size2( GlobalConfig::get_singleton()->get("display/window/width"), GlobalConfig::get_singleton()->get("display/window/height") );
-
- Vector2 screen_endpoints[4]= {
- transform.xform(Vector2(0,0)),
- transform.xform(Vector2(screen_size.width,0)),
- transform.xform(Vector2(screen_size.width,screen_size.height)),
- transform.xform(Vector2(0,screen_size.height))
- };
-
- for(int i=0;i<4;i++) {
-
- VisualServer::get_singleton()->canvas_item_add_line(ci,screen_endpoints[i], screen_endpoints[(i+1)%4],area_axis_color);
-
- }
-
- for(List<LockList>::Element*E=lock_list.front();E;E=E->next()) {
-
- Vector2 ofs = transform.xform(E->get().pos);
- if (E->get().lock) {
-
- lock->draw(ci,ofs);
- ofs.x+=lock->get_width();
- }
- if (E->get().group) {
-
- group->draw(ci,ofs);
- }
-
- }
-
- {
-
- EditorNode *en = editor;
- EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
-
- if (!over_plugin_list->empty()) {
-
- over_plugin_list->forward_draw_over_canvas(transform,viewport);
-
- }
- }
-
- if (skeleton_show_bones) {
- int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
- Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
- Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
- Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
- Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
-
- for(Map<ObjectID,BoneList>::Element*E=bone_list.front();E;E=E->next()) {
-
- E->get().from=Vector2();
- E->get().to=Vector2();
-
- Object *obj = ObjectDB::get_instance(E->get().bone);
- if (!obj)
- continue;
-
- Node2D* n2d = obj->cast_to<Node2D>();
- if (!n2d)
- continue;
-
- if (!n2d->get_parent())
- continue;
-
- CanvasItem *pi = n2d->get_parent_item();
-
-
- Node2D* pn2d=n2d->get_parent()->cast_to<Node2D>();
-
- if (!pn2d)
- continue;
-
- Vector2 from = transform.xform(pn2d->get_global_position());
- Vector2 to = transform.xform(n2d->get_global_position());
-
- E->get().from=from;
- E->get().to=to;
-
- Vector2 rel = to-from;
- Vector2 relt = rel.tangent().normalized()*bone_width;
-
-
-
- Vector<Vector2> bone_shape;
- bone_shape.push_back(from);
- bone_shape.push_back(from+rel*0.2+relt);
- bone_shape.push_back(to);
- bone_shape.push_back(from+rel*0.2-relt);
- Vector<Color> colors;
- if (pi->has_meta("_edit_ik_")) {
-
- colors.push_back(bone_ik_color);
- colors.push_back(bone_ik_color);
- colors.push_back(bone_ik_color);
- colors.push_back(bone_ik_color);
- } else {
- colors.push_back(bone_color1);
- colors.push_back(bone_color2);
- colors.push_back(bone_color1);
- colors.push_back(bone_color2);
- }
-
-
- VisualServer::get_singleton()->canvas_item_add_primitive(ci,bone_shape,colors,Vector<Vector2>(),RID());
-
- if (editor_selection->is_selected(pi)) {
- for(int i=0;i<bone_shape.size();i++) {
-
- VisualServer::get_singleton()->canvas_item_add_line(ci,bone_shape[i],bone_shape[(i+1)%bone_shape.size()],bone_selected_color,2);
- }
- }
-
- }
- }
-}
-
-void CanvasItemEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- bool all_control=true;
- bool has_control=false;
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- if (canvas_item->cast_to<Control>())
- has_control=true;
- else
- all_control=false;
-
- CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
- if (!se)
- continue;
-
- Rect2 r=canvas_item->get_item_rect();
-
- Transform2D xform = canvas_item->get_transform();
-
- if (r != se->prev_rect || xform!=se->prev_xform) {
- viewport->update();
- se->prev_rect=r;
- se->prev_xform=xform;
- }
-
- }
-
- bool show_anchor = all_control && has_control;
- if (show_anchor != anchor_menu->is_visible()) {
- if (show_anchor)
- anchor_menu->show();
- else
- anchor_menu->hide();
- }
-
- for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) {
-
- Object *b = ObjectDB::get_instance(E->get().bone);
- if (!b) {
-
- viewport->update();
- break;
- }
-
- Node2D *b2 = b->cast_to<Node2D>();
- if (!b2) {
- continue;
- }
-
- if (b2->get_global_transform()!=E->get().xform) {
-
- E->get().xform=b2->get_global_transform();
- viewport->update();
- }
- }
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- select_sb->set_texture( get_icon("EditorRect2D","EditorIcons") );
- for(int i=0;i<4;i++) {
- select_sb->set_margin_size(Margin(i),4);
- select_sb->set_default_margin(Margin(i),4);
- }
-
- 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"));
- group_button->set_icon(get_icon("Group","EditorIcons"));
- ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
- key_insert_button->set_icon(get_icon("Key","EditorIcons"));
-
-
- //anchor_menu->add_icon_override("Align Top Left");
- anchor_menu->set_icon(get_icon("Anchor","EditorIcons"));
- PopupMenu *p=anchor_menu->get_popup();
-
- p->add_icon_item(get_icon("ControlAlignTopLeft","EditorIcons"),"Top Left",ANCHOR_ALIGN_TOP_LEFT);
- p->add_icon_item(get_icon("ControlAlignTopRight","EditorIcons"),"Top Right",ANCHOR_ALIGN_TOP_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomRight","EditorIcons"),"Bottom Right",ANCHOR_ALIGN_BOTTOM_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomLeft","EditorIcons"),"Bottom Left",ANCHOR_ALIGN_BOTTOM_LEFT);
- p->add_separator();
- p->add_icon_item(get_icon("ControlAlignLeftCenter","EditorIcons"),"Center Left",ANCHOR_ALIGN_CENTER_LEFT);
- p->add_icon_item(get_icon("ControlAlignTopCenter","EditorIcons"),"Center Top",ANCHOR_ALIGN_CENTER_TOP);
- p->add_icon_item(get_icon("ControlAlignRightCenter","EditorIcons"),"Center Right",ANCHOR_ALIGN_CENTER_RIGHT);
- p->add_icon_item(get_icon("ControlAlignBottomCenter","EditorIcons"),"Center Bottom",ANCHOR_ALIGN_CENTER_BOTTOM);
- p->add_icon_item(get_icon("ControlAlignCenter","EditorIcons"),"Center",ANCHOR_ALIGN_CENTER);
- p->add_separator();
- p->add_icon_item(get_icon("ControlAlignLeftWide","EditorIcons"),"Left Wide",ANCHOR_ALIGN_LEFT_WIDE);
- p->add_icon_item(get_icon("ControlAlignTopWide","EditorIcons"),"Top Wide",ANCHOR_ALIGN_TOP_WIDE);
- p->add_icon_item(get_icon("ControlAlignRightWide","EditorIcons"),"Right Wide",ANCHOR_ALIGN_RIGHT_WIDE);
- p->add_icon_item(get_icon("ControlAlignBottomWide","EditorIcons"),"Bottom Wide",ANCHOR_ALIGN_BOTTOM_WIDE);
- p->add_icon_item(get_icon("ControlVcenterWide","EditorIcons"),"VCenter Wide ",ANCHOR_ALIGN_VCENTER_WIDE);
- p->add_icon_item(get_icon("ControlHcenterWide","EditorIcons"),"HCenter Wide ",ANCHOR_ALIGN_HCENTER_WIDE);
- p->add_separator();
- p->add_icon_item(get_icon("ControlAlignWide","EditorIcons"),"Full Rect",ANCHOR_ALIGN_WIDE);
-
-
- AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed",this,"_keying_changed");
- _keying_changed();
- }
-
- if (p_what==NOTIFICATION_READY) {
-
- get_tree()->connect("node_removed",this,"_node_removed");
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
-
-
- }
-}
-
-void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
-
- drag=DRAG_NONE;
-
- editor_selection->clear();//_clear_canvas_items();
- editor_selection->add_node(p_canvas_item);
- //_add_canvas_item(p_canvas_item);
- viewport->update();
-
-}
-
-
-void CanvasItemEditor::_find_canvas_items_span(Node *p_node, Rect2& r_rect, const Transform2D& p_xform) {
-
-
-
- if (!p_node)
- return;
-
- CanvasItem *c=p_node->cast_to<CanvasItem>();
-
-
- for (int i=p_node->get_child_count()-1;i>=0;i--) {
-
- //CanvasItem *r=NULL;
-
- if (c && !c->is_set_as_toplevel())
- _find_canvas_items_span(p_node->get_child(i),r_rect,p_xform * c->get_transform());
- else
- _find_canvas_items_span(p_node->get_child(i),r_rect,Transform2D());
- }
-
-
-
- if (c && c->is_visible_in_tree()) {
-
- Rect2 rect = c->get_item_rect();
- Transform2D xform = p_xform * c->get_transform();
-
-
- LockList lock;
- lock.lock=c->has_meta("_edit_lock_");
- lock.group=c->has_meta("_edit_group_");
-
- if (lock.group || lock.lock) {
- lock.pos=xform.xform(rect.pos);
- lock_list.push_back(lock);
- }
-
- if (c->has_meta("_edit_bone_")) {
-
- ObjectID id = c->get_instance_ID();
- if (!bone_list.has(id)) {
- BoneList bone;
- bone.bone=id;
- bone_list[id]=bone;
- }
-
- bone_list[id].last_pass=bone_last_frame;
- }
-
- r_rect.expand_to( xform.xform(rect.pos) );
- r_rect.expand_to( xform.xform(rect.pos+Point2(rect.size.x,0)) );
- r_rect.expand_to( xform.xform(rect.pos+Point2(0,rect.size.y)) );
- r_rect.expand_to( xform.xform(rect.pos+rect.size) );
-
- }
-
-}
-
-void CanvasItemEditor::_update_scrollbars() {
-
-
- updating_scroll=true;
-
- Size2 size = viewport->get_size();
- Size2 hmin = h_scroll->get_minimum_size();
- Size2 vmin = v_scroll->get_minimum_size();
-
- v_scroll->set_begin( Point2(size.width - vmin.width, 0) );
- v_scroll->set_end( Point2(size.width, size.height) );
-
- h_scroll->set_begin( Point2( 0, size.height - hmin.height) );
- h_scroll->set_end( Point2(size.width-vmin.width, size.height) );
-
-
- Size2 screen_rect = Size2( GlobalConfig::get_singleton()->get("display/window/width"), GlobalConfig::get_singleton()->get("display/window/height") );
-
-
- Rect2 local_rect = Rect2(Point2(),viewport->get_size()-Size2(vmin.width,hmin.height));
-
- Rect2 canvas_item_rect=Rect2(Point2(),screen_rect);
-
- lock_list.clear();
- bone_last_frame++;
-
-
-
- if (editor->get_edited_scene())
- _find_canvas_items_span(editor->get_edited_scene(),canvas_item_rect,Transform2D());
-
- List<Map<ObjectID,BoneList>::Element*> bone_to_erase;
-
- for(Map<ObjectID,BoneList>::Element*E=bone_list.front();E;E=E->next()) {
-
- if (E->get().last_pass!=bone_last_frame) {
- bone_to_erase.push_back(E);
- }
- }
-
- while(bone_to_erase.size()) {
- bone_list.erase(bone_to_erase.front()->get());
- bone_to_erase.pop_front();
- }
-
- //expand area so it's easier to do animations and stuff at 0,0
- canvas_item_rect.size+=screen_rect*2;
- canvas_item_rect.pos-=screen_rect;
-
- Point2 ofs;
-
-
- if (canvas_item_rect.size.height <= (local_rect.size.y/zoom)) {
-
- v_scroll->hide();
- ofs.y=canvas_item_rect.pos.y;
- } else {
-
- v_scroll->show();
- v_scroll->set_min(canvas_item_rect.pos.y);
- v_scroll->set_max(canvas_item_rect.pos.y+canvas_item_rect.size.y);
- v_scroll->set_page(local_rect.size.y/zoom);
- if (first_update) {
- //so 0,0 is visible
- v_scroll->set_value(-10);
- h_scroll->set_value(-10);
- first_update=false;
-
- }
-
- ofs.y=v_scroll->get_value();
- }
-
- if (canvas_item_rect.size.width <= (local_rect.size.x/zoom)) {
-
- h_scroll->hide();
- ofs.x=canvas_item_rect.pos.x;
- } else {
-
- h_scroll->show();
- h_scroll->set_min(canvas_item_rect.pos.x);
- h_scroll->set_max(canvas_item_rect.pos.x+canvas_item_rect.size.x);
- h_scroll->set_page(local_rect.size.x/zoom);
- ofs.x=h_scroll->get_value();
- }
-
- //transform=Matrix32();
- transform.elements[2]=-ofs*zoom;
-
- editor->get_scene_root()->set_global_canvas_transform(transform);
-
-
- updating_scroll=false;
-
- //transform.scale_basis(Vector2(zoom,zoom));
-
-
-}
-
-void CanvasItemEditor::_update_scroll(float) {
-
-
- if (updating_scroll)
- return;
-
- Point2 ofs;
- ofs.x=h_scroll->get_value();
- ofs.y=v_scroll->get_value();
-
- //current_window->set_scroll(-ofs);
-
- transform=Transform2D();
-
- transform.scale_basis(Size2(zoom,zoom));
- transform.elements[2]=-ofs;
-
- editor->get_scene_root()->set_global_canvas_transform(transform);
-
-
- viewport->update();
-
-}
-
-void CanvasItemEditor::_set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom) {
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- undo_redo->create_action(TTR("Change Anchors"));
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Control *c = E->get()->cast_to<Control>();
-
- undo_redo->add_do_method(c,"set_anchor",MARGIN_LEFT,p_left);
- undo_redo->add_do_method(c,"set_anchor",MARGIN_TOP,p_top);
- undo_redo->add_do_method(c,"set_anchor",MARGIN_RIGHT,p_right);
- undo_redo->add_do_method(c,"set_anchor",MARGIN_BOTTOM,p_bottom);
- undo_redo->add_undo_method(c,"set_anchor",MARGIN_LEFT,c->get_anchor(MARGIN_LEFT));
- undo_redo->add_undo_method(c,"set_anchor",MARGIN_TOP,c->get_anchor(MARGIN_TOP));
- undo_redo->add_undo_method(c,"set_anchor",MARGIN_RIGHT,c->get_anchor(MARGIN_RIGHT));
- undo_redo->add_undo_method(c,"set_anchor",MARGIN_BOTTOM,c->get_anchor(MARGIN_BOTTOM));
- }
-
- undo_redo->commit_action();
-
-}
-
-void CanvasItemEditor::_popup_callback(int p_op) {
-
- last_option=MenuOption(p_op);
- switch(p_op) {
-
- case SNAP_USE: {
- snap_grid = !snap_grid;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
- edit_menu->get_popup()->set_item_checked(idx,snap_grid);
- } break;
- case SNAP_SHOW_GRID: {
- snap_show_grid = !snap_show_grid;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
- edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
- viewport->update();
- } break;
- case SNAP_USE_ROTATION: {
- snap_rotation = !snap_rotation;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
- edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
- } break;
- case SNAP_RELATIVE: {
- snap_relative = !snap_relative;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
- edit_menu->get_popup()->set_item_checked(idx,snap_relative);
- } break;
- case SNAP_USE_PIXEL: {
- snap_pixel = !snap_pixel;
- int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
- edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
- } break;
- case SNAP_CONFIGURE: {
- ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
- snap_dialog->popup_centered(Size2(220,160));
- } break;
- case SKELETON_SHOW_BONES: {
- skeleton_show_bones = !skeleton_show_bones;
- int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES);
- skeleton_menu->set_item_checked(idx,skeleton_show_bones);
- viewport->update();
- } break;
- case ZOOM_IN: {
- if (zoom>MAX_ZOOM)
- return;
- zoom=zoom*(1.0/0.5);
- _update_scroll(0);
- viewport->update();
- return;
- } break;
- case ZOOM_OUT: {
- if (zoom<MIN_ZOOM)
- return;
-
- zoom=zoom*0.5;
- _update_scroll(0);
- viewport->update();
- return;
-
- } break;
- case ZOOM_RESET: {
-
- zoom=1;
- _update_scroll(0);
- viewport->update();
- return;
-
- } break;
- case ZOOM_SET: {
-
- updating_value_dialog=true;
-
- dialog_label->set_text(TTR("Zoom (%):"));
- dialog_val->set_min(0.1);
- dialog_val->set_step(0.1);
- dialog_val->set_max(800);
- dialog_val->set_value(zoom*100);
- value_dialog->popup_centered(Size2(200,85));
- updating_value_dialog=false;
-
-
- } break;
- case LOCK_SELECTED: {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- canvas_item->set_meta("_edit_lock_",true);
- emit_signal("item_lock_status_changed");
- }
- viewport->update();
- } break;
- case UNLOCK_SELECTED: {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
-
- canvas_item->set_meta("_edit_lock_",Variant());
- emit_signal("item_lock_status_changed");
- }
-
- viewport->update();
-
- } break;
- case GROUP_SELECTED: {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- canvas_item->set_meta("_edit_group_",true);
- emit_signal("item_group_status_changed");
- }
- viewport->update();
- } break;
- case UNGROUP_SELECTED: {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- canvas_item->set_meta("_edit_group_",Variant());
- emit_signal("item_group_status_changed");
- }
-
- viewport->update();
-
- } break;
-
- case EXPAND_TO_PARENT: {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
-
- Control *c = canvas_item->cast_to<Control>();
- if (!c)
- continue;
- c->set_area_as_parent_rect();
-
- }
-
- viewport->update();
-
- } break;
-
- case ALIGN_VERTICAL: {
-#if 0
- if ( ref_item && canvas_items.size() > 1 ) {
- Vector2 ref_pos = ref_item->get_global_transform().elements[2];
- Rect2 ref_r = ref_item->get_item_rect();
- for ( CanvasItemMap::Element *E = canvas_items.front(); E; E = E->next() ) {
- CanvasItem *it_curr = E->key();
- if ( it_curr == ref_item ) continue;
- Vector2 v = it_curr->get_global_transform().elements[2];
- Rect2 r = it_curr->get_item_rect();
- r.pos.x = ( ref_pos.x + ref_r.size.x / 2 ) - ( v.x + r.size.x / 2 );
- it_curr->edit_set_rect( r );
- }
- viewport->update();
- }
-#endif
- } break;
-
- case ALIGN_HORIZONTAL: {
-#if 0
- if ( ref_item && canvas_items.size() > 1 ) {
- Vector2 ref_pos = ref_item->get_global_transform().elements[2];
- Rect2 ref_r = ref_item->get_item_rect();
- for ( CanvasItemMap::Element *E = canvas_items.front(); E; E = E->next() ) {
- CanvasItem *it_curr = E->key();
- if ( it_curr == ref_item ) continue;
- Vector2 v = it_curr->get_global_transform().elements[2];
- Rect2 r = it_curr->get_item_rect();
- r.pos.y = ( ref_pos.y + ref_r.size.y / 2 ) - ( v.y + r.size.y / 2 );
- it_curr->edit_set_rect( r );
- }
- viewport->update();
- }
-#endif
- } break;
-
- case SPACE_HORIZONTAL: {
- //space_selected_items< proj_vector2_x, compare_items_x >();
- } break;
-
- case SPACE_VERTICAL: {
- //space_selected_items< proj_vector2_y, compare_items_y >();
- } break;
- case ANCHOR_ALIGN_TOP_LEFT: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN);
- } break;
- case ANCHOR_ALIGN_TOP_RIGHT: {
- _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
- } break;
- case ANCHOR_ALIGN_BOTTOM_LEFT: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END);
- } break;
- case ANCHOR_ALIGN_BOTTOM_RIGHT: {
- _set_anchor(ANCHOR_END,ANCHOR_END,ANCHOR_END,ANCHOR_END);
- } break;
- case ANCHOR_ALIGN_CENTER_LEFT: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER);
- } break;
- case ANCHOR_ALIGN_CENTER_RIGHT: {
-
- _set_anchor(ANCHOR_END,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
- } break;
- case ANCHOR_ALIGN_CENTER_TOP: {
- _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN);
- } break;
- case ANCHOR_ALIGN_CENTER_BOTTOM: {
- _set_anchor(ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER,ANCHOR_END);
- } break;
- case ANCHOR_ALIGN_CENTER: {
- _set_anchor(ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER);
- } break;
- case ANCHOR_ALIGN_TOP_WIDE: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN);
- } break;
- case ANCHOR_ALIGN_LEFT_WIDE: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END);
- } break;
- case ANCHOR_ALIGN_RIGHT_WIDE: {
- _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
- } break;
- case ANCHOR_ALIGN_BOTTOM_WIDE: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END,ANCHOR_END);
- } break;
- case ANCHOR_ALIGN_VCENTER_WIDE: {
- _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END);
- } break;
- case ANCHOR_ALIGN_HCENTER_WIDE: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER);
- } break;
- case ANCHOR_ALIGN_WIDE: {
- _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END);
- } break;
-
- case ANIM_INSERT_KEY:
- case ANIM_INSERT_KEY_EXISTING: {
-
- bool existing = p_op==ANIM_INSERT_KEY_EXISTING;
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- if (canvas_item->cast_to<Node2D>()) {
- Node2D *n2d = canvas_item->cast_to<Node2D>();
-
- if (key_pos)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d,"transform/pos",n2d->get_position(),existing);
- if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(n2d,"transform/rot",Math::rad2deg(n2d->get_rotation()),existing);
- if (key_scale)
- 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()) {
- //look for an IK chain
- List<Node2D*> ik_chain;
-
- Node2D *n = n2d->get_parent_item()->cast_to<Node2D>();
- bool has_chain=false;
-
- while(n) {
-
- ik_chain.push_back(n);
- if (n->has_meta("_edit_ik_")) {
- has_chain=true;
- break;
- }
-
- if (!n->get_parent_item())
- break;
- n=n->get_parent_item()->cast_to<Node2D>();
- }
-
- if (has_chain && ik_chain.size()) {
-
- for(List<Node2D*>::Element *F=ik_chain.front();F;F=F->next()) {
-
- if (key_pos)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/pos",F->get()->get_position(),existing);
- if (key_rot)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/rot",Math::rad2deg(F->get()->get_rotation()),existing);
- if (key_scale)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(F->get(),"transform/scale",F->get()->get_scale(),existing);
-
-
- }
- }
- }
-
- } else if (canvas_item->cast_to<Control>()) {
-
- Control *ctrl = canvas_item->cast_to<Control>();
-
- if (key_pos)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/pos",ctrl->get_pos(),existing);
- if (key_scale)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size(),existing);
- }
-
- }
-
- } break;
- case ANIM_INSERT_POS: {
-
- key_pos = key_loc_button->is_pressed();
- } break;
- case ANIM_INSERT_ROT: {
-
- key_rot = key_rot_button->is_pressed();
- } break;
- case ANIM_INSERT_SCALE: {
-
- key_scale = key_scale_button->is_pressed();
- } break;
- /*
- case ANIM_INSERT_POS_ROT
- case ANIM_INSERT_POS_SCALE:
- case ANIM_INSERT_ROT_SCALE:
- case ANIM_INSERT_POS_ROT_SCALE: {
-
- static const bool key_toggles[7][3]={
- {true,false,false},
- {false,true,false},
- {false,false,true},
- {true,true,false},
- {true,false,true},
- {false,true,true},
- {true,true,true}
- };
- key_pos=key_toggles[p_op-ANIM_INSERT_POS][0];
- key_rot=key_toggles[p_op-ANIM_INSERT_POS][1];
- key_scale=key_toggles[p_op-ANIM_INSERT_POS][2];
-
- for(int i=ANIM_INSERT_POS;i<=ANIM_INSERT_POS_ROT_SCALE;i++) {
- int idx = animation_menu->get_popup()->get_item_index(i);
- animation_menu->get_popup()->set_item_checked(idx,i==p_op);
- }
-
- } break;*/
- case ANIM_COPY_POSE: {
-
- pose_clipboard.clear();
-
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
-
- if (canvas_item->cast_to<Node2D>()) {
-
- Node2D *n2d = canvas_item->cast_to<Node2D>();
- PoseClipboard pc;
- pc.pos=n2d->get_position();
- pc.rot=n2d->get_rotation();
- pc.scale=n2d->get_scale();
- pc.id=n2d->get_instance_ID();
- pose_clipboard.push_back(pc);
- }
- }
-
-
- } break;
- case ANIM_PASTE_POSE: {
-
- if (!pose_clipboard.size())
- break;
-
- undo_redo->create_action(TTR("Paste Pose"));
- for (List<PoseClipboard>::Element *E=pose_clipboard.front();E;E=E->next()) {
-
- Object *o = ObjectDB::get_instance(E->get().id);
- if (!o)
- continue;
- Node2D *n2d = o->cast_to<Node2D>();
- if (!n2d)
- continue;
- undo_redo->add_do_method(n2d,"set_pos",E->get().pos);
- undo_redo->add_do_method(n2d,"set_rot",E->get().rot);
- undo_redo->add_do_method(n2d,"set_scale",E->get().scale);
- undo_redo->add_undo_method(n2d,"set_pos",n2d->get_position());
- undo_redo->add_undo_method(n2d,"set_rot",n2d->get_rotation());
- undo_redo->add_undo_method(n2d,"set_scale",n2d->get_scale());
- }
- undo_redo->commit_action();
-
- } break;
- case ANIM_CLEAR_POSE: {
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- if (canvas_item->cast_to<Node2D>()) {
- Node2D *n2d = canvas_item->cast_to<Node2D>();
-
- if (key_pos)
- n2d->set_position(Vector2());
- if (key_rot)
- n2d->set_rotation(0);
- if (key_scale)
- n2d->set_scale(Vector2(1,1));
- } else if (canvas_item->cast_to<Control>()) {
-
- Control *ctrl = canvas_item->cast_to<Control>();
-
- if (key_pos)
- ctrl->set_pos(Point2());
- /*
- if (key_scale)
- AnimationPlayerEditor::singleton->get_key_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
- */
- }
-
- }
-
-
- } break;
- case VIEW_CENTER_TO_SELECTION:
- case VIEW_FRAME_TO_SELECTION: {
-
- _focus_selection(p_op);
-
- } break;
- case SKELETON_MAKE_BONES: {
-
-
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- Node2D *n2d = E->key()->cast_to<Node2D>();
- if (!n2d)
- continue;
- if (!n2d->is_visible_in_tree())
- continue;
- if (!n2d->get_parent_item())
- continue;
-
- n2d->set_meta("_edit_bone_",true);
- if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
-
- }
- viewport->update();
-
- } break;
- case SKELETON_CLEAR_BONES: {
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- Node2D *n2d = E->key()->cast_to<Node2D>();
- if (!n2d)
- continue;
- if (!n2d->is_visible_in_tree())
- continue;
-
- n2d->set_meta("_edit_bone_",Variant());
- if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
-
- }
- viewport->update();
-
- } break;
- case SKELETON_SET_IK_CHAIN: {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
- if (!canvas_item || !canvas_item->is_visible_in_tree())
- continue;
-
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
- canvas_item->set_meta("_edit_ik_",true);
- if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
-
- }
-
- viewport->update();
-
- } break;
- case SKELETON_CLEAR_IK_CHAIN: {
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- CanvasItem *n2d = E->key()->cast_to<CanvasItem>();
- if (!n2d)
- continue;
- if (!n2d->is_visible_in_tree())
- continue;
-
- n2d->set_meta("_edit_ik_",Variant());
- if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
-
- }
- viewport->update();
-
- } break;
-
- }
-}
-#if 0
-template< class P, class C > void CanvasItemEditor::space_selected_items() {
- P p;
- if ( canvas_items.size() > 2 ) {
- Vector< CanvasItem * > items;
- for ( CanvasItemMap::Element *E = canvas_items.front(); E; E = E->next() ) {
- CanvasItem *it_curr = E->key();
- items.push_back( it_curr );
- }
- items.sort_custom< C >();
-
- float width_s = p.get( items[0]->get_item_rect().size );
- float width_e = p.get( items[ items.size() - 1 ]->get_item_rect().size );
- float start_x = p.get( items[0]->get_global_transform().elements[2] ) + ( width_s / 2 );
- float end_x = p.get( items[ items.size() - 1 ]->get_global_transform().elements[2] ) + ( width_e / 2 );
- float sp = ( end_x - start_x ) / ( items.size() - 1 );
-
- for ( int i = 0; i < items.size(); i++ ) {
- CanvasItem *it_curr = items[i];
- Vector2 v = it_curr->get_global_transform().elements[2];
- Rect2 r = it_curr->get_item_rect();
- p.set( r.pos, ( start_x + sp * i ) - ( p.get( v ) + p.get( r.size ) / 2 ) );
- it_curr->edit_set_rect( r );
- }
- viewport->update();
- }
-}
-#endif
-
-
-void CanvasItemEditor::_focus_selection(int p_op) {
- Vector2 center(0.f, 0.f);
- Rect2 rect;
- int count = 0;
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
- CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
- if (!canvas_item) continue;
- if (canvas_item->get_viewport()!=EditorNode::get_singleton()->get_scene_root())
- continue;
-
-
- // counting invisible items, for now
- //if (!canvas_item->is_visible_in_tree()) continue;
- ++count;
-
- Rect2 item_rect = canvas_item->get_item_rect();
-
- Vector2 pos = canvas_item->get_global_transform().get_origin();
- Vector2 scale = canvas_item->get_global_transform().get_scale();
- real_t angle = canvas_item->get_global_transform().get_rotation();
-
- Transform2D t(angle, Vector2(0.f,0.f));
- item_rect = t.xform(item_rect);
- Rect2 canvas_item_rect(pos + scale*item_rect.pos, scale*item_rect.size);
- if (count == 1) {
- rect = canvas_item_rect;
- } else {
- rect = rect.merge(canvas_item_rect);
- }
- };
- if (count==0) return;
-
- if (p_op == VIEW_CENTER_TO_SELECTION) {
-
- center = rect.pos + rect.size/2;
- Vector2 offset = viewport->get_size()/2 - editor->get_scene_root()->get_global_canvas_transform().xform(center);
- h_scroll->set_value(h_scroll->get_value() - offset.x/zoom);
- v_scroll->set_value(v_scroll->get_value() - offset.y/zoom);
-
- } else { // VIEW_FRAME_TO_SELECTION
-
- if (rect.size.x > CMP_EPSILON && rect.size.y > CMP_EPSILON) {
- float scale_x = viewport->get_size().x/rect.size.x;
- float scale_y = viewport->get_size().y/rect.size.y;
- zoom = scale_x < scale_y? scale_x:scale_y;
- zoom *= 0.90;
- _update_scroll(0);
- call_deferred("_popup_callback", VIEW_CENTER_TO_SELECTION);
- }
- }
-}
-
-
-void CanvasItemEditor::_bind_methods() {
-
- ClassDB::bind_method("_node_removed",&CanvasItemEditor::_node_removed);
- ClassDB::bind_method("_update_scroll",&CanvasItemEditor::_update_scroll);
- ClassDB::bind_method("_popup_callback",&CanvasItemEditor::_popup_callback);
- ClassDB::bind_method("_visibility_changed",&CanvasItemEditor::_visibility_changed);
- ClassDB::bind_method("_dialog_value_changed",&CanvasItemEditor::_dialog_value_changed);
- ClassDB::bind_method("_get_editor_data",&CanvasItemEditor::_get_editor_data);
- ClassDB::bind_method("_tool_select",&CanvasItemEditor::_tool_select);
- ClassDB::bind_method("_keying_changed",&CanvasItemEditor::_keying_changed);
- ClassDB::bind_method("_unhandled_key_input",&CanvasItemEditor::_unhandled_key_input);
- ClassDB::bind_method("_viewport_draw",&CanvasItemEditor::_viewport_draw);
- ClassDB::bind_method("_viewport_gui_input",&CanvasItemEditor::_viewport_gui_input);
- ClassDB::bind_method("_snap_changed",&CanvasItemEditor::_snap_changed);
- ClassDB::bind_method(_MD("_selection_result_pressed"),&CanvasItemEditor::_selection_result_pressed);
- ClassDB::bind_method(_MD("_selection_menu_hide"),&CanvasItemEditor::_selection_menu_hide);
-
- ADD_SIGNAL( MethodInfo("item_lock_status_changed") );
- ADD_SIGNAL( MethodInfo("item_group_status_changed") );
-
-}
-
-#if 0
-void CanvasItemEditor::end_drag() {
- print_line( "end drag" );
-
- if (undo_redo) {
-
- undo_redo->create_action("Edit CanvasItem");
- for(CanvasItemMap::Element *E=canvas_items.front();E;E=E->next()) {
- CanvasItem *canvas_item = E->key();
- Variant state=canvas_item->edit_get_state();
- undo_redo->add_do_method(canvas_item,"edit_set_state",state);
- undo_redo->add_undo_method(canvas_item,"edit_set_state",E->get().undo_state);
- }
- undo_redo->commit_action();
- }
-
- drag=DRAG_NONE;
- viewport->update();
-}
-
-void CanvasItemEditor::box_selection_start( Point2 &click ) {
- print_line( "box selection start" );
-
- drag_from=transform.affine_inverse().xform(click);
-
- box_selecting=true;
- box_selecting_to=drag_from;
- viewport->update();
-}
-
-bool CanvasItemEditor::box_selection_end() {
- print_line( "box selection end" );
-
- Node* scene = get_scene()->get_root_node()->cast_to<EditorNode>()->get_edited_scene();
- if (scene) {
-
- List<CanvasItem*> selitems;
-
- Point2 bsfrom = transform.xform(drag_from);
- Point2 bsto= transform.xform(box_selecting_to);
- if (bsfrom.x>bsto.x)
- SWAP(bsfrom.x,bsto.x);
- if (bsfrom.y>bsto.y)
- SWAP(bsfrom.y,bsto.y);
-
- if ( bsfrom.distance_to( bsto ) < 3 ) {
- print_line( "box selection too small" );
- box_selecting=false;
- viewport->update();
- return false;
- }
-
- _find_canvas_items_at_rect(Rect2(bsfrom,bsto-bsfrom),scene,transform,&selitems);
-
- for(List<CanvasItem*>::Element *E=selitems.front();E;E=E->next()) {
-
- _append_canvas_item(E->get());
- }
-
- }
-
- box_selecting=false;
- viewport->update();
-
- return true;
-}
-#endif
-
-void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
-
- hb->add_child(p_control);
-}
-
-HSplitContainer *CanvasItemEditor::get_palette_split() {
-
- return palette_split;
-}
-
-VSplitContainer *CanvasItemEditor::get_bottom_split() {
-
- return bottom_split;
-}
-
-
-void CanvasItemEditor::focus_selection() {
- _focus_selection(VIEW_CENTER_TO_SELECTION);
-}
-
-
-CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
-
- tool = TOOL_SELECT;
- undo_redo=p_editor->get_undo_redo();
- editor=p_editor;
- editor_selection=p_editor->get_editor_selection();
- editor_selection->add_editor_plugin(this);
- editor_selection->connect("selection_changed",this,"update");
-
-
- hb = memnew( HBoxContainer );
- add_child( hb );
- hb->set_area_as_parent_rect();
-
- bottom_split = memnew( VSplitContainer );
- bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
- add_child(bottom_split);
-
- palette_split = memnew( HSplitContainer);
- palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
- bottom_split->add_child(palette_split);
-
- Control *vp_base = memnew (Control);
- vp_base->set_v_size_flags(SIZE_EXPAND_FILL);
- palette_split->add_child(vp_base);
-
- ViewportContainer *vp = memnew (ViewportContainer);
- vp->set_stretch(true);
- vp_base->add_child(vp);
- vp->set_area_as_parent_rect();
- vp->add_child(p_editor->get_scene_root());
-
-
- viewport = memnew( CanvasItemEditorViewport(p_editor, this) );
- vp_base->add_child(viewport);
- viewport->set_area_as_parent_rect();
- viewport->set_clip_contents(true);
-
- h_scroll = memnew( HScrollBar );
- v_scroll = memnew( VScrollBar );
-
- viewport->add_child(h_scroll);
- viewport->add_child(v_scroll);
- viewport->connect("draw",this,"_viewport_draw");
- viewport->connect("gui_input",this,"_viewport_gui_input");
-
-
- h_scroll->connect("value_changed", this,"_update_scroll",Vector<Variant>(),Object::CONNECT_DEFERRED);
- v_scroll->connect("value_changed", this,"_update_scroll",Vector<Variant>(),Object::CONNECT_DEFERRED);
-
- h_scroll->hide();
- v_scroll->hide();
- updating_scroll=false;
- viewport->set_focus_mode(FOCUS_ALL);
- handle_len=10;
- first_update=true;
-
-
- select_button = memnew( ToolButton );
- select_button->set_toggle_mode(true);
- hb->add_child(select_button);
- select_button->connect("pressed",this,"_tool_select",make_binds(TOOL_SELECT));
- select_button->set_pressed(true);
- select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode",TTR("Select Mode"),KEY_Q));
- select_button->set_tooltip(TTR("Select Mode")+" $sc\n"+keycode_get_string(KEY_MASK_CMD)+TTR("Drag: Rotate")+"\n"+TTR("Alt+Drag: Move")+"\n"+TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).")+"\n"+TTR("Alt+RMB: Depth list selection"));
-
-
- move_button = memnew( ToolButton );
- move_button->set_toggle_mode(true);
- hb->add_child(move_button);
- move_button->connect("pressed",this,"_tool_select",make_binds(TOOL_MOVE));
- move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode",TTR("Move Mode"),KEY_W));
- move_button->set_tooltip(TTR("Move Mode"));
-
- rotate_button = memnew( ToolButton );
- rotate_button->set_toggle_mode(true);
- hb->add_child(rotate_button);
- rotate_button->connect("pressed",this,"_tool_select",make_binds(TOOL_ROTATE));
- rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode",TTR("Rotate Mode"),KEY_E));
- rotate_button->set_tooltip(TTR("Rotate Mode"));
-
- 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(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select 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(TTR("Click to change object's rotation pivot."));
-
- pan_button = memnew( ToolButton );
- pan_button->set_toggle_mode(true);
- hb->add_child(pan_button);
- pan_button->connect("pressed",this,"_tool_select",make_binds(TOOL_PAN));
- pan_button->set_tooltip(TTR("Pan Mode"));
-
- hb->add_child(memnew(VSeparator));
-
- lock_button = memnew( ToolButton );
- hb->add_child(lock_button);
-
- lock_button->connect("pressed",this,"_popup_callback",varray(LOCK_SELECTED));
- lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved)."));
-
- unlock_button = memnew( ToolButton );
- hb->add_child(unlock_button);
- unlock_button->connect("pressed",this,"_popup_callback",varray(UNLOCK_SELECTED));
- unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved)."));
-
- group_button = memnew( ToolButton );
- hb->add_child(group_button);
- group_button->connect("pressed",this,"_popup_callback",varray(GROUP_SELECTED));
- group_button->set_tooltip(TTR("Makes sure the object's children are not selectable."));
-
- ungroup_button = memnew( ToolButton );
- hb->add_child(ungroup_button);
- ungroup_button->connect("pressed",this,"_popup_callback",varray(UNGROUP_SELECTED));
- ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected."));
-
- hb->add_child(memnew(VSeparator));
-
- edit_menu = memnew( MenuButton );
- edit_menu->set_text(TTR("Edit"));
- hb->add_child(edit_menu);
- edit_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
-
- PopupMenu *p;
- p = edit_menu->get_popup();
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap")), SNAP_USE);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid")), SNAP_SHOW_GRID);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap..")), SNAP_CONFIGURE);
- p->add_separator();
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/expand_to_parent", TTR("Expand to Parent"), KEY_MASK_CMD | KEY_P), EXPAND_TO_PARENT);
- p->add_separator();
- p->add_submenu_item(TTR("Skeleton.."),"skeleton");
- skeleton_menu = memnew(PopupMenu);
- p->add_child(skeleton_menu);
- skeleton_menu->set_name("skeleton");
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B ),SKELETON_MAKE_BONES);
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES);
- skeleton_menu->add_separator();
- skeleton_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
- skeleton_menu->add_separator();
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
- skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
- skeleton_menu->connect("id_pressed", this,"_popup_callback");
-
-
- /*
- p->add_item("Align Horizontal",ALIGN_HORIZONTAL);
- p->add_item("Align Vertical",ALIGN_VERTICAL);
- p->add_item("Space Horizontal",SPACE_HORIZONTAL);
- p->add_item("Space Vertical",SPACE_VERTICAL);*/
-
- view_menu = memnew( MenuButton );
- view_menu->set_text(TTR("View"));
- hb->add_child(view_menu);
- view_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
-
- p = view_menu->get_popup();
-
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_in", TTR("Zoom In")), ZOOM_IN);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_out", TTR("Zoom Out")), ZOOM_OUT);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset")), ZOOM_RESET);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_set", TTR("Zoom Set..")), ZOOM_SET);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
-
- anchor_menu = memnew( MenuButton );
- anchor_menu->set_text(TTR("Anchor"));
- hb->add_child(anchor_menu);
- anchor_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
- anchor_menu->hide();
-
- //p = anchor_menu->get_popup();
-
-
-
- animation_hb = memnew( HBoxContainer );
- hb->add_child(animation_hb);
- animation_hb->add_child( memnew( VSeparator ));
- animation_hb->hide();
-
- key_loc_button = memnew( Button("loc"));
- key_loc_button->set_toggle_mode(true);
- key_loc_button->set_pressed(true);
- key_loc_button->set_focus_mode(FOCUS_NONE);
- key_loc_button->add_color_override("font_color",Color(1,0.6,0.6));
- key_loc_button->add_color_override("font_color_pressed",Color(0.6,1,0.6));
- key_loc_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_POS));
- animation_hb->add_child(key_loc_button);
- key_rot_button = memnew( Button("rot"));
- key_rot_button->set_toggle_mode(true);
- key_rot_button->set_pressed(true);
- key_rot_button->set_focus_mode(FOCUS_NONE);
- key_rot_button->add_color_override("font_color",Color(1,0.6,0.6));
- key_rot_button->add_color_override("font_color_pressed",Color(0.6,1,0.6));
- key_rot_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_ROT));
- animation_hb->add_child(key_rot_button);
- key_scale_button = memnew( Button("scl"));
- key_scale_button->set_toggle_mode(true);
- key_scale_button->set_focus_mode(FOCUS_NONE);
- key_scale_button->add_color_override("font_color",Color(1,0.6,0.6));
- key_scale_button->add_color_override("font_color_pressed",Color(0.6,1,0.6));
- key_scale_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_SCALE));
- animation_hb->add_child(key_scale_button);
- key_insert_button = memnew( Button );
- key_insert_button->set_focus_mode(FOCUS_NONE);
- key_insert_button->connect("pressed",this,"_popup_callback",varray(ANIM_INSERT_KEY));
- key_insert_button->set_tooltip(TTR("Insert Keys"));
- key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), KEY_INSERT));
-
- animation_hb->add_child(key_insert_button);
-
- animation_menu = memnew( MenuButton );
- animation_menu->set_text(TTR("Animation"));
- animation_hb->add_child(animation_menu);
- animation_menu->get_popup()->connect("id_pressed", this,"_popup_callback");
-
- p = animation_menu->get_popup();
-
- p->add_shortcut(ED_GET_SHORTCUT("canvas_item_editor/anim_insert_key"), ANIM_INSERT_KEY);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key_existing_tracks", TTR("Insert Key (Existing Tracks)"), KEY_MASK_CMD+KEY_INSERT), ANIM_INSERT_KEY_EXISTING);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_copy_pose", TTR("Copy Pose")), ANIM_COPY_POSE);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_paste_pose", TTR("Paste Pose")), ANIM_PASTE_POSE);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_clear_pose", TTR("Clear Pose"), KEY_MASK_SHIFT | KEY_K), ANIM_CLEAR_POSE);
-
- snap_dialog = memnew( SnapDialog );
- snap_dialog->connect("confirmed",this,"_snap_changed");
- add_child(snap_dialog);
-
- value_dialog = memnew( AcceptDialog );
- value_dialog->set_title(TTR("Set a Value"));
- value_dialog->get_ok()->set_text(TTR("Close"));
- add_child(value_dialog);
-
- Label *l = memnew(Label);
- l->set_text(TTR("Snap (Pixels):"));
- l->set_pos(Point2(5,5));
- value_dialog->add_child(l);
- dialog_label=l;
-
- dialog_val=memnew(SpinBox);
- dialog_val->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- dialog_val->set_begin(Point2(15,25));
- dialog_val->set_end(Point2(10,25));
- value_dialog->add_child(dialog_val);
- dialog_val->connect("value_changed",this,"_dialog_value_changed");
- select_sb = Ref<StyleBoxTexture>( memnew( StyleBoxTexture) );
-
- selection_menu = memnew( PopupMenu );
- add_child(selection_menu);
- selection_menu->set_custom_minimum_size(Vector2(100, 0));
- selection_menu->connect("id_pressed", this, "_selection_result_pressed");
- selection_menu->connect("popup_hide", this, "_selection_menu_hide");
-
- key_pos=true;
- key_rot=true;
- key_scale=false;
-
- zoom=1;
- snap_offset=Vector2(0, 0);
- snap_step=Vector2(10, 10);
- snap_rotation_offset=0;
- snap_rotation_step=15 / (180 / Math_PI);
- snap_grid=false;
- snap_show_grid=false;
- snap_rotation=false;
- snap_pixel=false;
- skeleton_show_bones=true;
- skeleton_menu->set_item_checked(skeleton_menu->get_item_index(SKELETON_SHOW_BONES),true);
- updating_value_dialog=false;
- box_selecting=false;
- //zoom=0.5;
- singleton=this;
-
- set_process_unhandled_key_input(true);
- can_move_pivot=false;
- drag=DRAG_NONE;
- bone_last_frame=0;
- additive_selection=false;
-}
-
-CanvasItemEditor *CanvasItemEditor::singleton=NULL;
-
-void CanvasItemEditorPlugin::edit(Object *p_object) {
-
- canvas_item_editor->set_undo_redo(&get_undo_redo());
- canvas_item_editor->edit(p_object->cast_to<CanvasItem>());
-}
-
-bool CanvasItemEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("CanvasItem");
-}
-
-void CanvasItemEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- canvas_item_editor->show();
- canvas_item_editor->set_fixed_process(true);
- VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(),false);
- canvas_item_editor->viewport->grab_focus();
-
- } else {
-
- canvas_item_editor->hide();
- canvas_item_editor->set_fixed_process(false);
- VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(),true);
- }
-
-}
-
-Dictionary CanvasItemEditorPlugin::get_state() const {
-
- return canvas_item_editor->get_state();
-}
-void CanvasItemEditorPlugin::set_state(const Dictionary& p_state) {
-
- canvas_item_editor->set_state(p_state);
-}
-
-CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- canvas_item_editor = memnew( CanvasItemEditor(editor) );
- canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- editor->get_viewport()->add_child(canvas_item_editor);
- canvas_item_editor->set_area_as_parent_rect();
- canvas_item_editor->hide();
-
-}
-
-
-CanvasItemEditorPlugin::~CanvasItemEditorPlugin()
-{
-}
-
-
-void CanvasItemEditorViewport::_on_mouse_exit() {
- if (!selector->is_visible()){
- _remove_preview();
- }
-}
-
-void CanvasItemEditorViewport::_on_select_type(Object* selected) {
- CheckBox* check = selected->cast_to<CheckBox>();
- String type = check->get_text();
- selector_label->set_text(vformat(TTR("Add %s"),type));
- label->set_text(vformat(TTR("Adding %s..."),type));
-}
-
-void CanvasItemEditorViewport::_on_change_type() {
- if (!button_group->get_pressed_button())
- return;
-
- CheckBox* check=button_group->get_pressed_button()->cast_to<CheckBox>();
- default_type=check->get_text();
- _perform_drop_data();
- selector->hide();
-}
-
-void CanvasItemEditorViewport::_create_preview(const Vector<String>& files) const {
- label->set_pos(get_global_pos()+Point2(14,14));
- label_desc->set_pos(label->get_pos()+Point2(0,label->get_size().height));
- for (int i=0;i<files.size();i++) {
- String path=files[i];
- RES res=ResourceLoader::load(path);
- String type=res->get_class();
- if (type=="ImageTexture" || type=="PackedScene") {
- if (type=="ImageTexture") {
- Ref<ImageTexture> texture=Ref<ImageTexture> ( ResourceCache::get(path)->cast_to<ImageTexture>() );
- Sprite* sprite=memnew(Sprite);
- sprite->set_texture(texture);
- sprite->set_modulate(Color(1,1,1,0.7f));
- preview->add_child(sprite);
- label->show();
- label_desc->show();
- } else if (type=="PackedScene") {
- Ref<PackedScene> scn=ResourceLoader::load(path);
- if (scn.is_valid()){
- Node* instance=scn->instance();
- if (instance){
- preview->add_child(instance);
- }
- }
- }
- editor->get_scene_root()->add_child(preview);
- }
- }
-}
-
-void CanvasItemEditorViewport::_remove_preview() {
- if (preview->get_parent()){
- editor->get_scene_root()->remove_child(preview);
- for (int i=preview->get_child_count()-1;i>=0;i--){
- Node* node=preview->get_child(i);
- memdelete(node);
- }
- label->hide();
- label_desc->hide();
- }
-}
-
-bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) {
- if (p_desired_node->get_filename()==p_target_scene_path) {
- return true;
- }
-
- int childCount=p_desired_node->get_child_count();
- for (int i=0;i<childCount;i++) {
- Node* child=p_desired_node->get_child(i);
- if(_cyclical_dependency_exists(p_target_scene_path,child)) {
- return true;
- }
- }
- return false;
-}
-
-void CanvasItemEditorViewport::_create_nodes(Node* parent, Node* child, String& path, const Point2& p_point) {
- child->set_name(path.get_file().get_basename());
- Ref<ImageTexture> texture=Ref<ImageTexture> ( ResourceCache::get(path)->cast_to<ImageTexture>() );
- Size2 texture_size = texture->get_size();
-
- editor_data->get_undo_redo().add_do_method(parent,"add_child",child);
- editor_data->get_undo_redo().add_do_method(child,"set_owner",editor->get_edited_scene());
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child);
-
- String new_name=parent->validate_child_name(child);
- ScriptEditorDebugger *sed=ScriptEditor::get_singleton()->get_debugger();
- editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",editor->get_edited_scene()->get_path_to(parent),child->get_class(),new_name);
- editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(editor->get_edited_scene()->get_path_to(parent))+"/"+new_name));
-
- // handle with different property for texture
- String property = "texture";
- List<PropertyInfo> props;
- child->get_property_list(&props);
- for(const List<PropertyInfo>::Element *E=props.front();E;E=E->next() ) {
- if (E->get().name=="config/texture") { // Particles2D
- property="config/texture";
- break;
- } else if (E->get().name=="texture/texture") { // Polygon2D
- property="texture/texture";
- break;
- } else if (E->get().name=="normal") { // TouchScreenButton
- property="normal";
- break;
- }
- }
- editor_data->get_undo_redo().add_do_property(child,property,texture);
-
- // make visible for certain node type
- if (default_type=="Patch9Rect") {
- editor_data->get_undo_redo().add_do_property(child,"rect/size",texture_size);
- } else if (default_type=="Polygon2D") {
- PoolVector<Vector2> list;
- list.push_back(Vector2(0,0));
- list.push_back(Vector2(texture_size.width,0));
- list.push_back(Vector2(texture_size.width,texture_size.height));
- list.push_back(Vector2(0,texture_size.height));
- editor_data->get_undo_redo().add_do_property(child,"polygon",list);
- }
-
- // locate at preview position
- Point2 pos;
- if (parent->has_method("get_global_pos")) {
- pos=parent->call("get_global_pos");
- }
- Transform2D trans=canvas->get_canvas_transform();
- Point2 target_pos = (p_point-trans.get_origin())/trans.get_scale().x-pos;
- if (default_type=="Polygon2D" || default_type=="TouchScreenButton" || default_type=="TextureRect" || default_type=="Patch9Rect") {
- target_pos -= texture_size/2;
- }
- editor_data->get_undo_redo().add_do_method(child,"set_pos",target_pos);
-}
-
-bool CanvasItemEditorViewport::_create_instance(Node* parent, String& path, const Point2& p_point) {
- Ref<PackedScene> sdata=ResourceLoader::load(path);
- if (!sdata.is_valid()) { // invalid scene
- return false;
- }
-
- Node* instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instanced_scene) { // error on instancing
- return false;
- }
-
- if (editor->get_edited_scene()->get_filename()!="") { // cyclical instancing
- if (_cyclical_dependency_exists(editor->get_edited_scene()->get_filename(), instanced_scene)) {
- memdelete(instanced_scene);
- return false;
- }
- }
-
- instanced_scene->set_filename( GlobalConfig::get_singleton()->localize_path(path) );
-
- editor_data->get_undo_redo().add_do_method(parent,"add_child",instanced_scene);
- editor_data->get_undo_redo().add_do_method(instanced_scene,"set_owner",editor->get_edited_scene());
- editor_data->get_undo_redo().add_do_reference(instanced_scene);
- editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene);
-
- String new_name=parent->validate_child_name(instanced_scene);
- ScriptEditorDebugger *sed=ScriptEditor::get_singleton()->get_debugger();
- editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",editor->get_edited_scene()->get_path_to(parent),path,new_name);
- editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(editor->get_edited_scene()->get_path_to(parent))+"/"+new_name));
-
- Point2 pos;
- Node2D* parent_node2d=parent->cast_to<Node2D>();
- if (parent_node2d) {
- pos=parent_node2d->get_global_position();
- } else {
- Control* parent_control=parent->cast_to<Control>();
- if (parent_control) {
- pos=parent_control->get_global_pos();
- }
- }
- Transform2D trans=canvas->get_canvas_transform();
- editor_data->get_undo_redo().add_do_method(instanced_scene,"set_pos",(p_point-trans.get_origin())/trans.get_scale().x-pos);
-
- return true;
-}
-
-void CanvasItemEditorViewport::_perform_drop_data(){
- _remove_preview();
-
- Vector<String> error_files;
-
- editor_data->get_undo_redo().create_action(TTR("Create Node"));
-
- for (int i=0;i<selected_files.size();i++) {
- String path=selected_files[i];
- RES res=ResourceLoader::load(path);
- if (res.is_null()) {
- continue;
- }
- String type=res->get_class();
- if (type=="ImageTexture") {
- Node* child;
- if (default_type=="Light2D") child=memnew(Light2D);
- else if (default_type=="Particles2D") child=memnew(Particles2D);
- else if (default_type=="Polygon2D") child=memnew(Polygon2D);
- else if (default_type=="TouchScreenButton") child=memnew(TouchScreenButton);
- else if (default_type=="TextureRect") child=memnew(TextureRect);
- else if (default_type=="Patch9Rect") child=memnew(NinePatchRect);
- else child=memnew(Sprite); // default
-
- _create_nodes(target_node, child, path, drop_pos);
- } else if (type=="PackedScene") {
- bool success=_create_instance(target_node, path, drop_pos);
- if (!success) {
- error_files.push_back(path);
- }
- }
- }
-
- editor_data->get_undo_redo().commit_action();
-
- if (error_files.size()>0) {
- String files_str;
- for (int i=0;i<error_files.size();i++) {
- files_str += error_files[i].get_file().get_basename() + ",";
- }
- files_str=files_str.substr(0,files_str.length()-1);
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(vformat(TTR("Error instancing scene from %s"),files_str.c_str()));
- accept->popup_centered_minsize();
- }
-}
-
-bool CanvasItemEditorViewport::can_drop_data(const Point2& p_point,const Variant& p_data) const {
- Dictionary d=p_data;
- if (d.has("type")) {
- if (String(d["type"])=="files") {
- Vector<String> files=d["files"];
- bool can_instance=false;
- for (int i=0;i<files.size();i++) { // check if dragged files contain resource or scene can be created at least one
- RES res=ResourceLoader::load(files[i]);
- if (res.is_null()) {
- continue;
- }
- String type=res->get_class();
- if (type=="PackedScene") {
- Ref<PackedScene> sdata=ResourceLoader::load(files[i]);
- Node* instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instanced_scene) {
- continue;
- }
- memdelete(instanced_scene);
- }
- can_instance=true;
- break;
- }
- if (can_instance) {
- if (!preview->get_parent()){ // create preview only once
- _create_preview(files);
- }
- Transform2D trans=canvas->get_canvas_transform();
- preview->set_position((p_point-trans.get_origin())/trans.get_scale().x);
- label->set_text(vformat(TTR("Adding %s..."),default_type));
- }
- return can_instance;
- }
- }
- label->hide();
- return false;
-}
-
-void CanvasItemEditorViewport::drop_data(const Point2& p_point,const Variant& p_data) {
- bool is_shift=Input::get_singleton()->is_key_pressed(KEY_SHIFT);
- bool is_alt=Input::get_singleton()->is_key_pressed(KEY_ALT);
-
- selected_files.clear();
- Dictionary d=p_data;
- if (d.has("type") && String(d["type"])=="files"){
- selected_files=d["files"];
- }
-
- List<Node*> list=editor->get_editor_selection()->get_selected_node_list();
- if (list.size()==0) {
- accept->get_ok()->set_text(TTR("OK :("));
- accept->set_text(TTR("No parent to instance a child at."));
- accept->popup_centered_minsize();
- _remove_preview();
- return;
- }
- if (list.size()!=1) {
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("This operation requires a single selected node."));
- accept->popup_centered_minsize();
- _remove_preview();
- return;
- }
-
- target_node=list[0];
- if (is_shift && target_node!=editor->get_edited_scene()) {
- target_node=target_node->get_parent();
- }
- drop_pos=p_point;
-
- if (is_alt) {
- List<BaseButton*> btn_list;
- button_group->get_buttons(&btn_list);
-
- for (int i=0;i<btn_list.size();i++) {
- CheckBox* check=btn_list[i]->cast_to<CheckBox>();
- check->set_pressed(check->get_text()==default_type);
- }
- selector_label->set_text(vformat(TTR("Add %s"),default_type));
- selector->popup_centered_minsize();
- } else {
- _perform_drop_data();
- }
-}
-
-void CanvasItemEditorViewport::_notification(int p_what) {
- if (p_what==NOTIFICATION_ENTER_TREE) {
- connect("mouse_exited",this,"_on_mouse_exit");
- } else if (p_what==NOTIFICATION_EXIT_TREE) {
- disconnect("mouse_exited",this,"_on_mouse_exit");
- }
-}
-
-void CanvasItemEditorViewport::_bind_methods() {
- ClassDB::bind_method(_MD("_on_select_type"),&CanvasItemEditorViewport::_on_select_type);
- ClassDB::bind_method(_MD("_on_change_type"),&CanvasItemEditorViewport::_on_change_type);
- ClassDB::bind_method(_MD("_on_mouse_exit"),&CanvasItemEditorViewport::_on_mouse_exit);
-}
-
-CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor* p_canvas) {
- default_type="Sprite";
- // Node2D
- types.push_back("Sprite");
- types.push_back("Light2D");
- types.push_back("Particles2D");
- types.push_back("Polygon2D");
- types.push_back("TouchScreenButton");
- // Control
- types.push_back("TextureRect");
- types.push_back("Patch9Rect");
-
- target_node=NULL;
- editor=p_node;
- editor_data=editor->get_scene_tree_dock()->get_editor_data();
- canvas=p_canvas;
- preview=memnew( Node2D );
- accept=memnew( AcceptDialog );
- editor->get_gui_base()->add_child(accept);
-
- selector=memnew( WindowDialog );
- selector->set_title(TTR("Change default type"));
-
- VBoxContainer* vbc=memnew(VBoxContainer);
- vbc->add_constant_override("separation",10*EDSCALE);
- vbc->set_custom_minimum_size(Size2(200,260)*EDSCALE);
-
- selector_label=memnew(Label);
- selector_label->set_align(Label::ALIGN_CENTER);
- selector_label->set_valign(Label::VALIGN_BOTTOM);
- selector_label->set_custom_minimum_size(Size2(0,30)*EDSCALE);
- vbc->add_child(selector_label);
-
- button_group.instance();
-
- btn_group=memnew( VBoxContainer );
- btn_group->set_h_size_flags(0);
- btn_group->connect("button_selected", this, "_on_select_type");
-
- for (int i=0;i<types.size();i++) {
- CheckBox* check=memnew(CheckBox);
- check->set_text(types[i]);
- btn_group->add_child(check);
- check->set_button_group(button_group);
- }
- vbc->add_child(btn_group);
-
- Button* ok=memnew(Button);
- ok->set_text(TTR("OK"));
- ok->set_h_size_flags(0);
- vbc->add_child(ok);
- ok->connect("pressed", this, "_on_change_type");
-
- selector->add_child(vbc);
- editor->get_gui_base()->add_child(selector);
-
- label=memnew(Label);
- label->add_color_override("font_color", Color(1,1,0,1));
- label->add_color_override("font_color_shadow", Color(0,0,0,1));
- label->add_constant_override("shadow_as_outline", 1*EDSCALE);
- label->hide();
- editor->get_gui_base()->add_child(label);
-
- label_desc=memnew(Label);
- label_desc->set_text(TTR("Drag & drop + Shift : Add node as sibling\nDrag & drop + Alt : Change node type"));
- label_desc->add_color_override("font_color", Color(0.6,0.6,0.6,1));
- label_desc->add_color_override("font_color_shadow", Color(0.2,0.2,0.2,1));
- label_desc->add_constant_override("shadow_as_outline", 1*EDSCALE);
- label_desc->add_constant_override("line_spacing", 0);
- label_desc->hide();
- editor->get_gui_base()->add_child(label_desc);
-}
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h
deleted file mode 100644
index dac8af5ae9..0000000000
--- a/tools/editor/plugins/canvas_item_editor_plugin.h
+++ /dev/null
@@ -1,503 +0,0 @@
-/*************************************************************************/
-/* canvas_item_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 CONTROL_EDITOR_PLUGIN_H
-#define CONTROL_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/gui/button_group.h"
-#include "scene/gui/check_box.h"
-#include "scene/gui/label.h"
-#include "scene/gui/spin_box.h"
-#include "scene/gui/panel_container.h"
-#include "scene/gui/box_container.h"
-#include "scene/2d/canvas_item.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class CanvasItemEditorViewport;
-
-class CanvasItemEditorSelectedItem : public Object {
-
- GDCLASS(CanvasItemEditorSelectedItem,Object);
-public:
- Variant undo_state;
- Vector2 undo_pivot;
-
- Transform2D prev_xform;
- float prev_rot;
- Rect2 prev_rect;
-
- CanvasItemEditorSelectedItem() { prev_rot=0; }
-};
-
-class CanvasItemEditor : public VBoxContainer {
-
- GDCLASS(CanvasItemEditor, VBoxContainer );
-
- EditorNode *editor;
-
-
- enum Tool {
-
- TOOL_SELECT,
- TOOL_LIST_SELECT,
- TOOL_MOVE,
- TOOL_ROTATE,
- TOOL_EDIT_PIVOT,
- TOOL_PAN,
- TOOL_MAX
- };
-
- enum MenuOption {
- SNAP_USE,
- SNAP_SHOW_GRID,
- SNAP_USE_ROTATION,
- SNAP_RELATIVE,
- SNAP_CONFIGURE,
- SNAP_USE_PIXEL,
- ZOOM_IN,
- ZOOM_OUT,
- ZOOM_RESET,
- ZOOM_SET,
- LOCK_SELECTED,
- UNLOCK_SELECTED,
- GROUP_SELECTED,
- UNGROUP_SELECTED,
- ALIGN_HORIZONTAL,
- ALIGN_VERTICAL,
- ANCHOR_ALIGN_TOP_LEFT,
- ANCHOR_ALIGN_TOP_RIGHT,
- ANCHOR_ALIGN_BOTTOM_LEFT,
- ANCHOR_ALIGN_BOTTOM_RIGHT,
- ANCHOR_ALIGN_CENTER_LEFT,
- ANCHOR_ALIGN_CENTER_RIGHT,
- ANCHOR_ALIGN_CENTER_TOP,
- ANCHOR_ALIGN_CENTER_BOTTOM,
- ANCHOR_ALIGN_CENTER,
- ANCHOR_ALIGN_TOP_WIDE,
- ANCHOR_ALIGN_LEFT_WIDE,
- ANCHOR_ALIGN_RIGHT_WIDE,
- ANCHOR_ALIGN_BOTTOM_WIDE,
- ANCHOR_ALIGN_VCENTER_WIDE,
- ANCHOR_ALIGN_HCENTER_WIDE,
- ANCHOR_ALIGN_WIDE,
-
- SPACE_HORIZONTAL,
- SPACE_VERTICAL,
- EXPAND_TO_PARENT,
- ANIM_INSERT_KEY,
- ANIM_INSERT_KEY_EXISTING,
- ANIM_INSERT_POS,
- ANIM_INSERT_ROT,
- ANIM_INSERT_SCALE,
- ANIM_COPY_POSE,
- ANIM_PASTE_POSE,
- ANIM_CLEAR_POSE,
- VIEW_CENTER_TO_SELECTION,
- VIEW_FRAME_TO_SELECTION,
- SKELETON_MAKE_BONES,
- SKELETON_CLEAR_BONES,
- SKELETON_SHOW_BONES,
- SKELETON_SET_IK_CHAIN,
- SKELETON_CLEAR_IK_CHAIN
-
- };
-
- enum DragType {
- DRAG_NONE,
- DRAG_LEFT,
- DRAG_TOP_LEFT,
- DRAG_TOP,
- DRAG_TOP_RIGHT,
- DRAG_RIGHT,
- DRAG_BOTTOM_RIGHT,
- DRAG_BOTTOM,
- DRAG_BOTTOM_LEFT,
- DRAG_ALL,
- DRAG_ROTATE,
- DRAG_PIVOT,
-
- };
-
- enum KeyMoveMODE {
- MOVE_VIEW_BASE,
- MOVE_LOCAL_BASE,
- MOVE_LOCAL_WITH_ROT
- };
-
- EditorSelection *editor_selection;
- bool additive_selection;
-
- Tool tool;
- bool first_update;
- Control *viewport;
-
- bool can_move_pivot;
-
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
- HBoxContainer *hb;
-
- Transform2D transform;
- float zoom;
- Vector2 snap_offset;
- Vector2 snap_step;
- float snap_rotation_step;
- float snap_rotation_offset;
- bool snap_grid;
- bool snap_show_grid;
- bool snap_rotation;
- bool snap_relative;
- bool snap_pixel;
- bool skeleton_show_bones;
- bool box_selecting;
- Point2 box_selecting_to;
- bool key_pos;
- bool key_rot;
- bool key_scale;
-
- void _tool_select(int p_index);
-
-
- MenuOption last_option;
-
- struct _SelectResult {
-
- CanvasItem* item;
- float z;
- bool has_z;
- _FORCE_INLINE_ bool operator<(const _SelectResult& p_rr) const {
- return has_z && p_rr.has_z ? p_rr.z < z : p_rr.has_z;
- }
- };
-
- Vector<_SelectResult> selection_results;
-
- struct LockList {
- Point2 pos;
- bool lock;
- bool group;
- LockList() { lock=false; group=false; }
- };
-
- List<LockList> lock_list;
-
- struct BoneList {
-
- Transform2D xform;
- Vector2 from;
- Vector2 to;
- ObjectID bone;
- uint64_t last_pass;
- };
-
- uint64_t bone_last_frame;
- Map<ObjectID,BoneList> bone_list;
-
- Transform2D bone_orig_xform;
-
- struct BoneIK {
-
- Variant orig_state;
- Vector2 pos;
- float len;
- Node2D *node;
- };
-
- List<BoneIK> bone_ik_list;
-
- struct PoseClipboard {
-
- Vector2 pos;
- Vector2 scale;
- float rot;
- ObjectID id;
- };
-
- 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;
- ToolButton *unlock_button;
-
- ToolButton *group_button;
- ToolButton *ungroup_button;
-
- MenuButton *edit_menu;
- PopupMenu *skeleton_menu;
- MenuButton *view_menu;
- HBoxContainer *animation_hb;
- MenuButton *animation_menu;
- MenuButton *anchor_menu;
-
- Button *key_loc_button;
- Button *key_rot_button;
- Button *key_scale_button;
- Button *key_insert_button;
-
- PopupMenu *selection_menu;
-
-
- //PopupMenu *popup;
- DragType drag;
- Point2 drag_from;
- Point2 drag_point_from;
- bool updating_value_dialog;
- Point2 display_rotate_from;
- Point2 display_rotate_to;
-#if 0
- struct EditInfo {
-
- Variant undo_state;
-
- Matrix32 prev_xform;
- float prev_rot;
- Rect2 prev_rect;
- EditInfo() { prev_rot=0; }
- };
-
- typedef Map<CanvasItem*,EditInfo> CanvasItemMap;
- CanvasItemMap canvas_items;
-#endif
- Ref<StyleBoxTexture> select_sb;
- Ref<Texture> select_handle;
-
-
- int handle_len;
- bool _is_part_of_subscene(CanvasItem *p_item);
- CanvasItem* _select_canvas_item_at_pos(const Point2 &p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform);
- void _find_canvas_items_at_pos(const Point2 &p_pos,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform, Vector<_SelectResult> &r_items);
- void _find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Transform2D& p_parent_xform,const Transform2D& p_canvas_xform,List<CanvasItem*> *r_items);
-
- bool _select(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag=true);
-
- ConfirmationDialog *snap_dialog;
-
- AcceptDialog *value_dialog;
- Label *dialog_label;
- SpinBox *dialog_val;
-
- 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 Transform2D& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point);
-
- void _popup_callback(int p_op);
- bool updating_scroll;
- void _update_scroll(float);
- void _update_scrollbars();
- void incbeg(float& beg,float& end, float inc, float minsize,bool p_symmetric);
- void incend(float& beg,float& end, float inc, float minsize,bool p_symmetric);
-
- void _append_canvas_item(CanvasItem *p_item);
- void _dialog_value_changed(double);
- void _snap_changed();
- void _selection_result_pressed(int);
- void _selection_menu_hide();
-
- UndoRedo *undo_redo;
-
- Point2 _find_topleftmost_point();
-
-
- void _find_canvas_items_span(Node *p_node, Rect2& r_rect, const Transform2D& p_xform);
-
-
- Object *_get_editor_data(Object *p_what);
-
- CanvasItem *get_single_item();
- int get_item_count();
- void _keying_changed();
-
- void _unhandled_key_input(const InputEvent& p_ev);
-
- void _viewport_gui_input(const InputEvent& p_event);
- void _viewport_draw();
-
- void _focus_selection(int p_op);
-
- void _set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom);
-
- HSplitContainer *palette_split;
- VSplitContainer *bottom_split;
-
-friend class CanvasItemEditorPlugin;
-protected:
-
-
- void _notification(int p_what);
-
- void _node_removed(Node *p_node);
- static void _bind_methods();
- void end_drag();
- void box_selection_start( Point2 &click );
- bool box_selection_end();
-
- HBoxContainer *get_panel_hb() { return hb; }
-
- struct compare_items_x {
- bool operator()( const CanvasItem *a, const CanvasItem *b ) const {
- return a->get_global_transform().elements[2].x < b->get_global_transform().elements[2].x;
- }
- };
-
- struct compare_items_y {
- bool operator()( const CanvasItem *a, const CanvasItem *b ) const {
- return a->get_global_transform().elements[2].y < b->get_global_transform().elements[2].y;
- }
- };
-
- struct proj_vector2_x {
- float get( const Vector2 &v ) { return v.x; }
- void set( Vector2 &v, float f ) { v.x = f; }
- };
-
- struct proj_vector2_y {
- float get( const Vector2 &v ) { return v.y; }
- void set( Vector2 &v, float f ) { v.y = f; }
- };
-
- template< class P, class C > void space_selected_items();
-
- static CanvasItemEditor *singleton;
-public:
-
- Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
- float snap_angle(float p_target, float p_start = 0) const;
-
- Transform2D get_canvas_transform() const { return transform; }
-
- static CanvasItemEditor *get_singleton() { return singleton; }
- Dictionary get_state() const;
- void set_state(const Dictionary& p_state);
-
- void add_control_to_menu_panel(Control *p_control);
-
- HSplitContainer *get_palette_split();
- VSplitContainer *get_bottom_split();
-
- Control *get_viewport_control() { return viewport; }
-
- bool get_remove_list(List<Node*> *p_list);
- void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
- void edit(CanvasItem *p_canvas_item);
-
- void focus_selection();
-
- CanvasItemEditor(EditorNode *p_editor);
-};
-
-class CanvasItemEditorPlugin : public EditorPlugin {
-
- GDCLASS( CanvasItemEditorPlugin, EditorPlugin );
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "2D"; }
- bool has_main_screen() const { return true; }
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
- virtual void make_visible(bool p_visible);
- virtual bool get_remove_list(List<Node*> *p_list) { return canvas_item_editor->get_remove_list(p_list); }
- virtual Dictionary get_state() const;
- virtual void set_state(const Dictionary& p_state);
-
- CanvasItemEditor *get_canvas_item_editor() { return canvas_item_editor; }
-
- CanvasItemEditorPlugin(EditorNode *p_node);
- ~CanvasItemEditorPlugin();
-
-};
-
-class CanvasItemEditorViewport : public Control {
- GDCLASS( CanvasItemEditorViewport, Control );
-
- String default_type;
- Vector<String> types;
-
- Vector<String> selected_files;
- Node* target_node;
- Point2 drop_pos;
-
- EditorNode* editor;
- EditorData* editor_data;
- CanvasItemEditor* canvas;
- Node2D* preview;
- AcceptDialog* accept;
- WindowDialog* selector;
- Label* selector_label;
- Label* label;
- Label* label_desc;
- VBoxContainer* btn_group;
- Ref<ButtonGroup> button_group;
-
- void _on_mouse_exit();
- void _on_select_type(Object* selected);
- void _on_change_type();
-
- void _create_preview(const Vector<String>& files) const;
- void _remove_preview();
-
- bool _cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node);
- void _create_nodes(Node* parent, Node* child, String& path, const Point2& p_point);
- bool _create_instance(Node* parent, String& path, const Point2& p_point);
- void _perform_drop_data();
-
- static void _bind_methods();
-
-protected:
- void _notification(int p_what);
-
-public:
- virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
- virtual void drop_data(const Point2& p_point,const Variant& p_data);
-
- CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor* p_canvas);
-};
-
-#endif
diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
deleted file mode 100644
index 263d96ecdf..0000000000
--- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ /dev/null
@@ -1,482 +0,0 @@
-/*************************************************************************/
-/* collision_polygon_2d_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "collision_polygon_2d_editor_plugin.h"
-
-#include "canvas_item_editor_plugin.h"
-#include "os/file_access.h"
-#include "tools/editor/editor_settings.h"
-
-
-void CollisionPolygon2DEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon( get_icon("Edit","EditorIcons"));
- button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed",this,"_node_removed");
-
- } break;
- case NOTIFICATION_FIXED_PROCESS: {
-
-
- } break;
- }
-
-}
-void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- canvas_item_editor->get_viewport_control()->update();
- }
-
-}
-
-
-void CollisionPolygon2DEditor::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case MODE_CREATE: {
-
- mode=MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode=MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
-
- }
-}
-
-void CollisionPolygon2DEditor::_wip_close() {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
- undo_redo->add_do_method(node,"set_polygon",wip);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- wip.clear();
- wip_active=false;
- mode=MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point=-1;
-}
-
-bool CollisionPolygon2DEditor::forward_gui_input(const InputEvent& p_event) {
-
-
- if (!node)
- return false;
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
-
- Vector2 gpoint = Point2(mb.x,mb.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- Vector<Vector2> poly = node->get_polygon();
-
- //first check if a point is to be added (segment split)
- real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
-
- switch(mode) {
-
-
- case MODE_CREATE: {
-
- if (mb.button_index==BUTTON_LEFT && mb.pressed) {
-
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back( cpoint );
- wip_active=true;
- edited_point_pos=cpoint;
- canvas_item_editor->get_viewport_control()->update();
- edited_point=1;
- return true;
- } else {
-
-
- if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back( cpoint );
- edited_point=wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
- _wip_close();
- }
-
-
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb.button_index==BUTTON_LEFT) {
- if (mb.pressed) {
-
- if (mb.mod.control) {
-
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 points[2] ={ xform.xform(poly[i]),
- xform.xform(poly[(i+1)%poly.size()]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
- if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
- edited_point=closest_idx+1;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- node->set_polygon(poly);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- edited_point=closest_idx;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point!=-1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
- poly[edited_point]=edited_point_pos;
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- edited_point=-1;
- return true;
- }
- }
- } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
-
-
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- }
-
-
-
- } break;
- }
-
-
-
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mm=p_event.mouse_motion;
-
- if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = Point2(mm.x,mm.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
-
- }
-
- } break;
- }
-
- return false;
-}
-void CollisionPolygon2DEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly=wip;
- else
- poly=node->get_polygon();
-
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
-
- for(int i=0;i<poly.size();i++) {
-
-
- Vector2 p,p2;
- p = i==edited_point ? edited_point_pos : poly[i];
- if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
- p2=edited_point_pos;
- else
- p2 = poly[(i+1)%poly.size()];
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col=Color(1,0.3,0.1,0.8);
- vpc->draw_line(point,next_point,col,2);
- vpc->draw_texture(handle,point-handle->get_size()*0.5);
- }
-}
-
-
-
-void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor=CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node=p_collision_polygon->cast_to<CollisionPolygon2D>();
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
- wip.clear();
- wip_active=false;
- edited_point=-1;
- canvas_item_editor->get_viewport_control()->update();
-
- } else {
- node=NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
-
- }
-
-}
-
-void CollisionPolygon2DEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_menu_option"),&CollisionPolygon2DEditor::_menu_option);
- ClassDB::bind_method(_MD("_canvas_draw"),&CollisionPolygon2DEditor::_canvas_draw);
- ClassDB::bind_method(_MD("_node_removed"),&CollisionPolygon2DEditor::_node_removed);
-
-}
-
-CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) {
-
- node=NULL;
- canvas_item_editor=NULL;
- editor=p_editor;
- undo_redo = editor->get_undo_redo();
-
- add_child( memnew( VSeparator ));
- button_create = memnew( ToolButton );
- add_child(button_create);
- button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
- button_create->set_tooltip(TTR("Create a new polygon from scratch."));
-
- button_edit = memnew( ToolButton );
- add_child(button_edit);
- button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
- button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.");
-
- //add_constant_override("separation",0);
-
-#if 0
- options = memnew( MenuButton );
- add_child(options);
- options->set_area_as_parent_rect();
- options->set_text("Polygon");
- //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
- options->get_popup()->connect("id_pressed", this,"_menu_option");
-#endif
-
- mode = MODE_EDIT;
- wip_active=false;
-
-}
-
-
-void CollisionPolygon2DEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool CollisionPolygon2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("CollisionPolygon2D");
-}
-
-void CollisionPolygon2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-
-}
-
-CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- collision_polygon_editor = memnew( CollisionPolygon2DEditor(p_node) );
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
-
-
-
-}
-
-
-CollisionPolygon2DEditorPlugin::~CollisionPolygon2DEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h b/tools/editor/plugins/collision_polygon_2d_editor_plugin.h
deleted file mode 100644
index 2c573c1dcf..0000000000
--- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*************************************************************************/
-/* collision_polygon_2d_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
-#define COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/2d/collision_polygon_2d.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/button_group.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class CanvasItemEditor;
-
-class CollisionPolygon2DEditor : public HBoxContainer {
-
- GDCLASS(CollisionPolygon2DEditor, HBoxContainer );
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
- CollisionPolygon2D *node;
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
-
- void _wip_close();
- void _canvas_draw();
- void _menu_option(int p_option);
-
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- bool forward_gui_input(const InputEvent& p_event);
- void edit(Node *p_collision_polygon);
- CollisionPolygon2DEditor(EditorNode *p_editor);
-};
-
-class CollisionPolygon2DEditorPlugin : public EditorPlugin {
-
- GDCLASS( CollisionPolygon2DEditorPlugin, EditorPlugin );
-
- CollisionPolygon2DEditor *collision_polygon_editor;
- EditorNode *editor;
-
-public:
-
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "CollisionPolygon2D"; }
- 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);
-
- CollisionPolygon2DEditorPlugin(EditorNode *p_node);
- ~CollisionPolygon2DEditorPlugin();
-
-};
-
-#endif // COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_editor_plugin.cpp
deleted file mode 100644
index c5cd15cf72..0000000000
--- a/tools/editor/plugins/collision_polygon_editor_plugin.cpp
+++ /dev/null
@@ -1,648 +0,0 @@
-/*************************************************************************/
-/* collision_polygon_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "collision_polygon_editor_plugin.h"
-
-#include "spatial_editor_plugin.h"
-#include "os/file_access.h"
-#include "tools/editor/editor_settings.h"
-#include "scene/3d/camera.h"
-#include "canvas_item_editor_plugin.h"
-
-#if 0
-
-void CollisionPolygonEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon( get_icon("Edit","EditorIcons"));
- button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed",this,"_node_removed");
-
-
- } break;
- case NOTIFICATION_PROCESS: {
-
- if (node->get_depth() != prev_depth) {
- _polygon_draw();
- prev_depth=node->get_depth();
- }
-
- } break;
- }
-
-}
-void CollisionPolygonEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- if (imgeom->get_parent()==p_node)
- p_node->remove_child(imgeom);
- hide();
- set_process(false);
- }
-
-}
-
-
-void CollisionPolygonEditor::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case MODE_CREATE: {
-
- mode=MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode=MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
-
- }
-}
-
-void CollisionPolygonEditor::_wip_close() {
-
- undo_redo->create_action(TTR("Create Poly3D"));
- undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
- undo_redo->add_do_method(node,"set_polygon",wip);
- undo_redo->add_do_method(this,"_polygon_draw");
- undo_redo->add_undo_method(this,"_polygon_draw");
- wip.clear();
- wip_active=false;
- mode=MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point=-1;
- undo_redo->commit_action();
-
-}
-
-bool CollisionPolygonEditor::forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) {
-
- if (!node)
- return false;
-
- Transform gt = node->get_global_transform();
- Transform gi = gt.affine_inverse();
- float depth = node->get_depth()*0.5;
- Vector3 n = gt.basis.get_axis(2).normalized();
- Plane p(gt.origin+n*depth,n);
-
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
-
-
-
- Vector2 gpoint=Point2(mb.x,mb.y);
- Vector3 ray_from = p_camera->project_ray_origin(gpoint);
- Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
-
- Vector3 spoint;
-
- if (!p.intersects_ray(ray_from,ray_dir,&spoint))
- break;
-
- spoint = gi.xform(spoint);
-
- Vector2 cpoint(spoint.x,spoint.y);
-
- cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
-
- Vector<Vector2> poly = node->get_polygon();
-
- //first check if a point is to be added (segment split)
- real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
-
- switch(mode) {
-
-
- case MODE_CREATE: {
-
- if (mb.button_index==BUTTON_LEFT && mb.pressed) {
-
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back( cpoint );
- wip_active=true;
- edited_point_pos=cpoint;
- _polygon_draw();
- edited_point=1;
- return true;
- } else {
-
-
- if (wip.size()>1 && p_camera->unproject_position(gt.xform(Vector3(wip[0].x,wip[0].y,depth))).distance_to(gpoint)<grab_treshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back( cpoint );
- edited_point=wip.size();
- _polygon_draw();
- return true;
-
- //add wip point
- }
- }
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
- _wip_close();
- }
-
-
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb.button_index==BUTTON_LEFT) {
- if (mb.pressed) {
-
- if (mb.mod.control) {
-
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(this,"_polygon_draw");
- undo_redo->add_undo_method(this,"_polygon_draw");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 points[2] ={
- p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth))),
- p_camera->unproject_position(gt.xform(Vector3(poly[(i+1)%poly.size()].x,poly[(i+1)%poly.size()].y,depth)))
- };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
- if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- poly.insert(closest_idx+1,cpoint);
- edited_point=closest_idx+1;
- edited_point_pos=cpoint;
- node->set_polygon(poly);
- _polygon_draw();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth)));
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- edited_point=closest_idx;
- edited_point_pos=poly[closest_idx];
- _polygon_draw();
- return true;
- }
- }
- } else {
-
- if (edited_point!=-1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
- poly[edited_point]=edited_point_pos;
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
- undo_redo->add_do_method(this,"_polygon_draw");
- undo_redo->add_undo_method(this,"_polygon_draw");
- undo_redo->commit_action();
-
- edited_point=-1;
- return true;
- }
- }
- } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
-
-
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth)));
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(this,"_polygon_draw");
- undo_redo->add_undo_method(this,"_polygon_draw");
- undo_redo->commit_action();
- return true;
- }
-
- }
-
-
-
- } break;
- }
-
-
-
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mm=p_event.mouse_motion;
-
- if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = Point2(mm.x,mm.y);
-
- Vector3 ray_from = p_camera->project_ray_origin(gpoint);
- Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
-
- Vector3 spoint;
-
- if (!p.intersects_ray(ray_from,ray_dir,&spoint))
- break;
-
- spoint = gi.xform(spoint);
-
- Vector2 cpoint(spoint.x,spoint.y);
-
- cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
- edited_point_pos = cpoint;
-
- _polygon_draw();
-
- }
-
- } break;
- }
-
- return false;
-}
-void CollisionPolygonEditor::_polygon_draw() {
-
- if (!node)
- return;
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly=wip;
- else
- poly=node->get_polygon();
-
-
- float depth = node->get_depth()*0.5;
-
- imgeom->clear();
- imgeom->set_material_override(line_material);
- imgeom->begin(Mesh::PRIMITIVE_LINES,Ref<Texture>());
-
-
- Rect2 rect;
-
- for(int i=0;i<poly.size();i++) {
-
-
- Vector2 p,p2;
- p = i==edited_point ? edited_point_pos : poly[i];
- if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
- p2=edited_point_pos;
- else
- p2 = poly[(i+1)%poly.size()];
-
- if (i==0)
- rect.pos=p;
- else
- rect.expand_to(p);
-
- Vector3 point = Vector3(p.x,p.y,depth);
- Vector3 next_point = Vector3(p2.x,p2.y,depth);
-
- imgeom->set_color(Color(1,0.3,0.1,0.8));
- imgeom->add_vertex(point);
- imgeom->set_color(Color(1,0.3,0.1,0.8));
- imgeom->add_vertex(next_point);
-
- //Color col=Color(1,0.3,0.1,0.8);
- //vpc->draw_line(point,next_point,col,2);
- //vpc->draw_texture(handle,point-handle->get_size()*0.5);
- }
-
- rect=rect.grow(1);
-
- AABB r;
- r.pos.x=rect.pos.x;
- r.pos.y=rect.pos.y;
- r.pos.z=depth;
- r.size.x=rect.size.x;
- r.size.y=rect.size.y;
- r.size.z=0;
-
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos);
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(0.3,0,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos);
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(0.0,0.3,0));
-
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)-Vector3(0.3,0,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)+Vector3(0,0.3,0));
-
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)-Vector3(0,0.3,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)+Vector3(0.3,0,0));
-
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+r.size);
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+r.size-Vector3(0.3,0,0));
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+r.size);
- imgeom->set_color(Color(0.8,0.8,0.8,0.2));
- imgeom->add_vertex(r.pos+r.size-Vector3(0.0,0.3,0));
-
- imgeom->end();
-
-
- while(m->get_surface_count()) {
- m->surface_remove(0);
- }
-
- if (poly.size()==0)
- return;
-
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- PoolVector<Vector3> va;
- {
-
- va.resize(poly.size());
- PoolVector<Vector3>::Write w=va.write();
- for(int i=0;i<poly.size();i++) {
-
-
- Vector2 p,p2;
- p = i==edited_point ? edited_point_pos : poly[i];
-
- Vector3 point = Vector3(p.x,p.y,depth);
- w[i]=point;
- }
- }
- a[Mesh::ARRAY_VERTEX]=va;
- m->add_surface(Mesh::PRIMITIVE_POINTS,a);
- m->surface_set_material(0,handle_material);
-
-}
-
-
-
-void CollisionPolygonEditor::edit(Node *p_collision_polygon) {
-
-
-
- if (p_collision_polygon) {
-
- node=p_collision_polygon->cast_to<CollisionPolygon>();
- wip.clear();
- wip_active=false;
- edited_point=-1;
- p_collision_polygon->add_child(imgeom);
- _polygon_draw();
- set_process(true);
- prev_depth=-1;
-
- } else {
- node=NULL;
-
- if (imgeom->get_parent())
- imgeom->get_parent()->remove_child(imgeom);
-
- set_process(false);
- }
-
-}
-
-void CollisionPolygonEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_menu_option"),&CollisionPolygonEditor::_menu_option);
- ClassDB::bind_method(_MD("_polygon_draw"),&CollisionPolygonEditor::_polygon_draw);
- ClassDB::bind_method(_MD("_node_removed"),&CollisionPolygonEditor::_node_removed);
-
-}
-
-CollisionPolygonEditor::CollisionPolygonEditor(EditorNode *p_editor) {
-
-
- node=NULL;
- editor=p_editor;
- undo_redo = editor->get_undo_redo();
-
- add_child( memnew( VSeparator ));
- button_create = memnew( ToolButton );
- add_child(button_create);
- button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
-
- button_edit = memnew( ToolButton );
- add_child(button_edit);
- button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
-
- //add_constant_override("separation",0);
-
-#if 0
- options = memnew( MenuButton );
- add_child(options);
- options->set_area_as_parent_rect();
- options->set_text("Polygon");
- //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
- options->get_popup()->connect("id_pressed", this,"_menu_option");
-#endif
-
- mode = MODE_EDIT;
- wip_active=false;
- imgeom = memnew( ImmediateGeometry );
- imgeom->set_transform(Transform(Matrix3(),Vector3(0,0,0.00001)));
-
-
- line_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- line_material->set_flag(Material::FLAG_UNSHADED, true);
- line_material->set_line_width(3.0);
- line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
- line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true);
- line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1));
-
-
-
-
- handle_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- handle_material->set_flag(Material::FLAG_UNSHADED, true);
- handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_POINT_SIZE, true);
- handle_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1));
- handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
- handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, false);
- Ref<Texture> handle=editor->get_gui_base()->get_icon("Editor3DHandle","EditorIcons");
- handle_material->set_point_size(handle->get_width());
- handle_material->set_texture(FixedSpatialMaterial::PARAM_DIFFUSE,handle);
-
- pointsm = memnew( MeshInstance );
- imgeom->add_child(pointsm);
- m = Ref<Mesh>( memnew( Mesh ) );
- pointsm->set_mesh(m);
- pointsm->set_transform(Transform(Matrix3(),Vector3(0,0,0.00001)));
-
-
-}
-
-CollisionPolygonEditor::~CollisionPolygonEditor() {
-
- memdelete( imgeom );
-}
-
-
-void CollisionPolygonEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool CollisionPolygonEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("CollisionPolygon");
-}
-
-void CollisionPolygonEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-
-}
-
-CollisionPolygonEditorPlugin::CollisionPolygonEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- collision_polygon_editor = memnew( CollisionPolygonEditor(p_node) );
- SpatialEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
-
-
-
-}
-
-
-CollisionPolygonEditorPlugin::~CollisionPolygonEditorPlugin()
-{
-}
-
-#endif
diff --git a/tools/editor/plugins/collision_polygon_editor_plugin.h b/tools/editor/plugins/collision_polygon_editor_plugin.h
deleted file mode 100644
index cd722048db..0000000000
--- a/tools/editor/plugins/collision_polygon_editor_plugin.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*************************************************************************/
-/* collision_polygon_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 COLLISION_POLYGON_EDITOR_PLUGIN_H
-#define COLLISION_POLYGON_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/collision_polygon.h"
-#include "scene/3d/immediate_geometry.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/button_group.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-#if 0
-class CanvasItemEditor;
-
-class CollisionPolygonEditor : public HBoxContainer {
-
- GDCLASS(CollisionPolygonEditor, HBoxContainer );
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
-
- Ref<FixedSpatialMaterial> line_material;
- Ref<FixedSpatialMaterial> handle_material;
-
- EditorNode *editor;
- Panel *panel;
- CollisionPolygon *node;
- ImmediateGeometry *imgeom;
- MeshInstance *pointsm;
- Ref<Mesh> m;
-
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
- float prev_depth;
-
- void _wip_close();
- void _polygon_draw();
- void _menu_option(int p_option);
-
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event);
- void edit(Node *p_collision_polygon);
- CollisionPolygonEditor(EditorNode *p_editor);
- ~CollisionPolygonEditor();
-};
-
-class CollisionPolygonEditorPlugin : public EditorPlugin {
-
- GDCLASS( CollisionPolygonEditorPlugin, EditorPlugin );
-
- CollisionPolygonEditor *collision_polygon_editor;
- EditorNode *editor;
-
-public:
-
- virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) { return collision_polygon_editor->forward_spatial_gui_input(p_camera,p_event); }
-
- virtual String get_name() const { return "CollisionPolygon"; }
- 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);
-
- CollisionPolygonEditorPlugin(EditorNode *p_node);
- ~CollisionPolygonEditorPlugin();
-
-};
-#endif
-#endif // COLLISION_POLYGON_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/collision_shape_2d_editor_plugin.h b/tools/editor/plugins/collision_shape_2d_editor_plugin.h
deleted file mode 100644
index 37708db5e0..0000000000
--- a/tools/editor/plugins/collision_shape_2d_editor_plugin.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*************************************************************************/
-/* collision_shape_2d_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
-#define COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-
-#include "scene/2d/collision_shape_2d.h"
-
-class CanvasItemEditor;
-
-class CollisionShape2DEditor : public Control {
- GDCLASS(CollisionShape2DEditor, Control);
-
- enum ShapeType {
- CAPSULE_SHAPE,
- CIRCLE_SHAPE,
- CONCAVE_POLYGON_SHAPE,
- CONVEX_POLYGON_SHAPE,
- LINE_SHAPE,
- RAY_SHAPE,
- RECTANGLE_SHAPE,
- SEGMENT_SHAPE
- };
-
- EditorNode* editor;
- UndoRedo* undo_redo;
- CanvasItemEditor* canvas_item_editor;
- CollisionShape2D* node;
-
- Vector<Point2> handles;
-
- int shape_type;
- int edit_handle;
- bool pressed;
- Variant original;
-
- Variant get_handle_value(int idx) const;
- void set_handle(int idx, Point2& p_point);
- void commit_handle(int idx, Variant& p_org);
-
- void _get_current_shape_type();
- void _canvas_draw();
-
-protected:
- static void _bind_methods();
-
-public:
- bool forward_gui_input(const InputEvent& p_event);
- void edit(Node* p_node);
-
- CollisionShape2DEditor(EditorNode* p_editor);
-};
-
-class CollisionShape2DEditorPlugin : public EditorPlugin {
- GDCLASS(CollisionShape2DEditorPlugin, EditorPlugin);
-
- CollisionShape2DEditor* collision_shape_2d_editor;
- EditorNode* editor;
-
-public:
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_shape_2d_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "CollisionShape2D"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object* p_obj);
- virtual bool handles(Object* p_obj) const;
- virtual void make_visible(bool visible);
-
- CollisionShape2DEditorPlugin(EditorNode* p_editor);
- ~CollisionShape2DEditorPlugin();
-};
-
-#endif //COLLISION_SHAPE_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/color_ramp_editor_plugin.cpp b/tools/editor/plugins/color_ramp_editor_plugin.cpp
deleted file mode 100644
index 9509eb1b03..0000000000
--- a/tools/editor/plugins/color_ramp_editor_plugin.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*************************************************************************/
-/* color_ramp_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "color_ramp_editor_plugin.h"
-
-#include "spatial_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
-
-ColorRampEditorPlugin::ColorRampEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- ramp_editor = memnew( ColorRampEdit );
-
-
- add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,ramp_editor);
-
- ramp_editor->set_custom_minimum_size(Size2(100, 48));
- ramp_editor->hide();
- ramp_editor->connect("ramp_changed", this, "ramp_changed");
-}
-
-void ColorRampEditorPlugin::edit(Object *p_object) {
-
- ColorRamp* color_ramp = p_object->cast_to<ColorRamp>();
- if (!color_ramp)
- return;
- color_ramp_ref = Ref<ColorRamp>(color_ramp);
- ramp_editor->set_points(color_ramp_ref->get_points());
-}
-
-bool ColorRampEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("ColorRamp");
-
-}
-
-void ColorRampEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- ramp_editor->show();
- } else {
- ramp_editor->hide();
- }
-
-}
-
-void ColorRampEditorPlugin::_ramp_changed() {
-
- if(color_ramp_ref.is_valid())
- {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
-
- //Not sure if I should convert this data to PoolVector
- Vector<float> new_offsets=ramp_editor->get_offsets();
- Vector<Color> new_colors=ramp_editor->get_colors();
- Vector<float> old_offsets=color_ramp_ref->get_offsets();
- Vector<Color> old_colors=color_ramp_ref->get_colors();
-
- if (old_offsets.size()!=new_offsets.size())
- ur->create_action(TTR("Add/Remove Color Ramp Point"));
- else
- ur->create_action(TTR("Modify Color Ramp"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(this,"undo_redo_color_ramp",new_offsets,new_colors);
- ur->add_undo_method(this,"undo_redo_color_ramp",old_offsets,old_colors);
- ur->commit_action();
-
- //color_ramp_ref->set_points(ramp_editor->get_points());
- }
-}
-
-void ColorRampEditorPlugin::_undo_redo_color_ramp(const Vector<float>& offsets,
- const Vector<Color>& colors) {
-
- color_ramp_ref->set_offsets(offsets);
- color_ramp_ref->set_colors(colors);
- ramp_editor->set_points(color_ramp_ref->get_points());
- ramp_editor->update();
-}
-
-ColorRampEditorPlugin::~ColorRampEditorPlugin(){
-}
-
-void ColorRampEditorPlugin::_bind_methods() {
- ClassDB::bind_method(_MD("ramp_changed"),&ColorRampEditorPlugin::_ramp_changed);
- ClassDB::bind_method(_MD("undo_redo_color_ramp","offsets","colors"),&ColorRampEditorPlugin::_undo_redo_color_ramp);
-}
diff --git a/tools/editor/plugins/color_ramp_editor_plugin.h b/tools/editor/plugins/color_ramp_editor_plugin.h
deleted file mode 100644
index 2f55ad65f1..0000000000
--- a/tools/editor/plugins/color_ramp_editor_plugin.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*************************************************************************/
-/* color_ramp_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
-#define TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/gui/color_ramp_edit.h"
-
-class ColorRampEditorPlugin : public EditorPlugin {
-
- GDCLASS( ColorRampEditorPlugin, EditorPlugin );
-
- bool _2d;
- Ref<ColorRamp> color_ramp_ref;
- ColorRampEdit *ramp_editor;
- EditorNode *editor;
-
-protected:
- static void _bind_methods();
- void _ramp_changed();
- void _undo_redo_color_ramp(const Vector<float>& offsets, const Vector<Color>& colors);
-
-public:
- virtual String get_name() const { return "ColorRamp"; }
- 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);
-
- ColorRampEditorPlugin(EditorNode *p_node);
- ~ColorRampEditorPlugin();
-
-};
-
-#endif /* TOOLS_EDITOR_PLUGINS_COLOR_RAMP_EDITOR_PLUGIN_H_ */
diff --git a/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp b/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp
deleted file mode 100644
index 563b8298eb..0000000000
--- a/tools/editor/plugins/cube_grid_theme_editor_plugin.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
-/*************************************************************************/
-/* cube_grid_theme_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "cube_grid_theme_editor_plugin.h"
-
-#if 0
-#include "scene/3d/mesh_instance.h"
-#include "scene/3d/physics_body.h"
-#include "scene/main/viewport.h"
-#include "scene/resources/packed_scene.h"
-#include "tools/editor/editor_node.h"
-#include "main/main.h"
-#include "tools/editor/editor_settings.h"
-#include "scene/3d/navigation_mesh.h"
-
-void MeshLibraryEditor::edit(const Ref<MeshLibrary>& p_theme) {
-
- theme=p_theme;
- if (theme.is_valid())
- menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE),!theme->has_meta("_editor_source_scene"));
-
-}
-
-void MeshLibraryEditor::_menu_confirm() {
-
-
- switch(option) {
-
- case MENU_OPTION_REMOVE_ITEM: {
-
- theme->remove_item(to_erase);
- } break;
- case MENU_OPTION_UPDATE_FROM_SCENE: {
- String existing = theme->get_meta("_editor_source_scene");
- ERR_FAIL_COND(existing=="");
- _import_scene_cbk(existing);
-
- } break;
- default: {};
- }
-
-}
-
-
-void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge) {
-
- if (!p_merge)
- p_library->clear();
-
-
- for(int i=0;i<p_scene->get_child_count();i++) {
-
-
- Node *child = p_scene->get_child(i);
-
- if (!child->cast_to<MeshInstance>()) {
- if (child->get_child_count()>0) {
- child=child->get_child(0);
- if (!child->cast_to<MeshInstance>()) {
- continue;
- }
-
- } else
- continue;
-
-
- }
-
- MeshInstance *mi = child->cast_to<MeshInstance>();
- Ref<Mesh> mesh=mi->get_mesh();
- if (mesh.is_null())
- continue;
-
- int id = p_library->find_item_name(mi->get_name());
- if (id<0) {
-
- id=p_library->get_last_unused_item_id();
- p_library->create_item(id);
- p_library->set_item_name(id,mi->get_name());
- }
-
-
- p_library->set_item_mesh(id,mesh);
-
- Ref<Shape> collision;
-
-
- for(int j=0;j<mi->get_child_count();j++) {
-#if 1
- Node *child2 = mi->get_child(j);
- if (!child2->cast_to<StaticBody>())
- continue;
- StaticBody *sb = child2->cast_to<StaticBody>();
- if (sb->get_shape_count()==0)
- continue;
- collision=sb->get_shape(0);
- if (!collision.is_null())
- break;
-#endif
- }
-
- if (!collision.is_null()) {
-
- p_library->set_item_shape(id,collision);
- }
- Ref<NavigationMesh> navmesh;
- for(int j=0;j<mi->get_child_count();j++) {
- Node *child2 = mi->get_child(j);
- if (!child2->cast_to<NavigationMeshInstance>())
- continue;
- NavigationMeshInstance *sb = child2->cast_to<NavigationMeshInstance>();
- navmesh=sb->get_navigation_mesh();
- if (!navmesh.is_null())
- break;
- }
- if(!navmesh.is_null()){
- p_library->set_item_navmesh(id, navmesh);
- }
- }
-
- //generate previews!
-
- if (1) {
- Vector<int> ids = p_library->get_item_list();
- RID vp = VS::get_singleton()->viewport_create();
- VS::ViewportRect vr;
- vr.x=0;
- vr.y=0;
- vr.width=EditorSettings::get_singleton()->get("editors/grid_map/preview_size");
- vr.height=EditorSettings::get_singleton()->get("editors/grid_map/preview_size");
- VS::get_singleton()->viewport_set_rect(vp,vr);
- VS::get_singleton()->viewport_set_as_render_target(vp,true);
- VS::get_singleton()->viewport_set_render_target_update_mode(vp,VS::RENDER_TARGET_UPDATE_ALWAYS);
- RID scen = VS::get_singleton()->scenario_create();
- VS::get_singleton()->viewport_set_scenario(vp,scen);
- RID cam = VS::get_singleton()->camera_create();
- VS::get_singleton()->camera_set_transform(cam, Transform() );
- VS::get_singleton()->viewport_attach_camera(vp,cam);
- RID light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
- RID lightinst = VS::get_singleton()->instance_create2(light,scen);
- VS::get_singleton()->camera_set_orthogonal(cam,1.0,0.01,1000.0);
-
-
- EditorProgress ep("mlib",TTR("Creating Mesh Library"),ids.size());
-
- for(int i=0;i<ids.size();i++) {
-
- int id=ids[i];
- Ref<Mesh> mesh = p_library->get_item_mesh(id);
- if (!mesh.is_valid())
- continue;
- AABB aabb= mesh->get_aabb();
- print_line("aabb: "+aabb);
- Vector3 ofs = aabb.pos + aabb.size*0.5;
- aabb.pos-=ofs;
- Transform xform;
- xform.basis=Matrix3().rotated(Vector3(0,1,0),-Math_PI*0.25);
- xform.basis = Matrix3().rotated(Vector3(1,0,0),Math_PI*0.25)*xform.basis;
- AABB rot_aabb = xform.xform(aabb);
- print_line("rot_aabb: "+rot_aabb);
- float m = MAX(rot_aabb.size.x,rot_aabb.size.y)*0.5;
- if (m==0)
- continue;
- m=1.0/m;
- m*=0.5;
- print_line("scale: "+rtos(m));
- xform.basis.scale(Vector3(m,m,m));
- xform.origin=-xform.basis.xform(ofs); //-ofs*m;
- xform.origin.z-=rot_aabb.size.z*2;
- RID inst = VS::get_singleton()->instance_create2(mesh->get_rid(),scen);
- VS::get_singleton()->instance_set_transform(inst,xform);
- ep.step(TTR("Thumbnail.."),i);
- VS::get_singleton()->viewport_queue_screen_capture(vp);
- Main::iteration();
- Image img = VS::get_singleton()->viewport_get_screen_capture(vp);
- ERR_CONTINUE(img.empty());
- Ref<ImageTexture> it( memnew( ImageTexture ));
- it->create_from_image(img);
- p_library->set_item_preview(id,it);
-
- //print_line("loaded image, size: "+rtos(m)+" dist: "+rtos(dist)+" empty?"+itos(img.empty())+" w: "+itos(it->get_width())+" h: "+itos(it->get_height()));
- VS::get_singleton()->free(inst);
- }
-
- VS::get_singleton()->free(lightinst);
- VS::get_singleton()->free(light);
- VS::get_singleton()->free(vp);
- VS::get_singleton()->free(cam);
- VS::get_singleton()->free(scen);
- }
-
-
-}
-
-
-void MeshLibraryEditor::_import_scene_cbk(const String& p_str) {
-
-
- print_line("Impot Callback!");
-
- Ref<PackedScene> ps = ResourceLoader::load(p_str,"PackedScene");
- ERR_FAIL_COND(ps.is_null());
- Node *scene = ps->instance();
-
- _import_scene(scene,theme,option==MENU_OPTION_UPDATE_FROM_SCENE);
-
- memdelete(scene);
- theme->set_meta("_editor_source_scene",p_str);
- menu->get_popup()->set_item_disabled(menu->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE),false);
-
-}
-
-Error MeshLibraryEditor::update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml,bool p_merge) {
-
- _import_scene(p_base_scene,ml,p_merge);
- return OK;
-}
-
-
-void MeshLibraryEditor::_menu_cbk(int p_option) {
-
- option=p_option;
- switch(p_option) {
-
- case MENU_OPTION_ADD_ITEM: {
-
- theme->create_item(theme->get_last_unused_item_id());
- } break;
- case MENU_OPTION_REMOVE_ITEM: {
-
- String p = editor->get_property_editor()->get_selected_path();
- if (p.begins_with("/MeshLibrary/item") && p.get_slice_count("/")>=3) {
-
- to_erase = p.get_slice("/",3).to_int();
- cd->set_text(vformat(TTR("Remove item %d?"),to_erase));
- cd->popup_centered(Size2(300,60));
- }
- } break;
- case MENU_OPTION_IMPORT_FROM_SCENE: {
-
- file->popup_centered_ratio();
- } break;
- case MENU_OPTION_UPDATE_FROM_SCENE: {
-
- cd->set_text("Update from existing scene?:\n"+String(theme->get_meta("_editor_source_scene")));
- cd->popup_centered(Size2(500,60));
- } break;
- }
-}
-
-
-void MeshLibraryEditor::_bind_methods() {
-
- ClassDB::bind_method("_menu_cbk",&MeshLibraryEditor::_menu_cbk);
- ClassDB::bind_method("_menu_confirm",&MeshLibraryEditor::_menu_confirm);
- ClassDB::bind_method("_import_scene_cbk",&MeshLibraryEditor::_import_scene_cbk);
-}
-
-MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) {
-
- file = memnew( EditorFileDialog );
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- //not for now?
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
- file->clear_filters();
- file->set_title(TTR("Import Scene"));
- for(int i=0;i<extensions.size();i++) {
-
- file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
- add_child(file);
- file->connect("file_selected",this,"_import_scene_cbk");
-
- Panel *panel = memnew( Panel );
- panel->set_area_as_parent_rect();
- add_child(panel);
- MenuButton * options = memnew( MenuButton );
- panel->add_child(options);
- options->set_pos(Point2(1,1));
- options->set_text("Theme");
- options->get_popup()->add_item(TTR("Add Item"),MENU_OPTION_ADD_ITEM);
- options->get_popup()->add_item(TTR("Remove Selected Item"),MENU_OPTION_REMOVE_ITEM);
- options->get_popup()->add_separator();
- options->get_popup()->add_item(TTR("Import from Scene"),MENU_OPTION_IMPORT_FROM_SCENE);
- options->get_popup()->add_item(TTR("Update from Scene"),MENU_OPTION_UPDATE_FROM_SCENE);
- options->get_popup()->set_item_disabled(options->get_popup()->get_item_index(MENU_OPTION_UPDATE_FROM_SCENE),true);
- options->get_popup()->connect("id_pressed", this,"_menu_cbk");
- menu=options;
- editor=p_editor;
- cd = memnew(ConfirmationDialog);
- add_child(cd);
- cd->get_ok()->connect("pressed", this,"_menu_confirm");
-
-}
-
-void MeshLibraryEditorPlugin::edit(Object *p_node) {
-
- if (p_node && p_node->cast_to<MeshLibrary>()) {
- theme_editor->edit( p_node->cast_to<MeshLibrary>() );
- theme_editor->show();
- } else
- theme_editor->hide();
-}
-
-bool MeshLibraryEditorPlugin::handles(Object *p_node) const{
-
- return p_node->is_type("MeshLibrary");
-}
-
-void MeshLibraryEditorPlugin::make_visible(bool p_visible){
-
- if (p_visible)
- theme_editor->show();
- else
- theme_editor->hide();
-}
-
-MeshLibraryEditorPlugin::MeshLibraryEditorPlugin(EditorNode *p_node) {
-
- EDITOR_DEF("editors/grid_map/preview_size",64);
- theme_editor = memnew( MeshLibraryEditor(p_node) );
-
- p_node->get_viewport()->add_child(theme_editor);
- theme_editor->set_area_as_parent_rect();
- theme_editor->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
- theme_editor->set_anchor( MARGIN_BOTTOM, Control::ANCHOR_BEGIN );
- theme_editor->set_end( Point2(0,22) );
- theme_editor->hide();
-
-}
-#endif
diff --git a/tools/editor/plugins/cube_grid_theme_editor_plugin.h b/tools/editor/plugins/cube_grid_theme_editor_plugin.h
deleted file mode 100644
index f32f601023..0000000000
--- a/tools/editor/plugins/cube_grid_theme_editor_plugin.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*************************************************************************/
-/* cube_grid_theme_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 CUBE_GRID_THEME_EDITOR_PLUGIN_H
-#define CUBE_GRID_THEME_EDITOR_PLUGIN_H
-
-#include "scene/resources/mesh_library.h"
-#include "tools/editor/editor_node.h"
-
-#if 0
-class MeshLibraryEditor : public Control {
-
- GDCLASS( MeshLibraryEditor, Control );
-
- Ref<MeshLibrary> theme;
-
- EditorNode *editor;
- MenuButton *menu;
- ConfirmationDialog *cd;
- EditorFileDialog *file;
- int to_erase;
-
- enum {
-
- MENU_OPTION_ADD_ITEM,
- MENU_OPTION_REMOVE_ITEM,
- MENU_OPTION_UPDATE_FROM_SCENE,
- MENU_OPTION_IMPORT_FROM_SCENE
- };
-
- int option;
- void _import_scene_cbk(const String& p_str);
- void _menu_cbk(int p_option);
- void _menu_confirm();
-
- static void _import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge);
-
-protected:
- static void _bind_methods();
-public:
-
- void edit(const Ref<MeshLibrary>& p_theme);
- static Error update_library_file(Node *p_base_scene, Ref<MeshLibrary> ml,bool p_merge=true);
-
- MeshLibraryEditor(EditorNode *p_editor);
-};
-
-
-
-class MeshLibraryEditorPlugin : public EditorPlugin {
-
- GDCLASS( MeshLibraryEditorPlugin, EditorPlugin );
-
- MeshLibraryEditor *theme_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "MeshLibrary"; }
- 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);
-
- MeshLibraryEditorPlugin(EditorNode *p_node);
-
-};
-
-
-#endif // CUBE_GRID_THEME_EDITOR_PLUGIN_H
-#endif
diff --git a/tools/editor/plugins/editor_preview_plugins.cpp b/tools/editor/plugins/editor_preview_plugins.cpp
deleted file mode 100644
index 5d9b281874..0000000000
--- a/tools/editor/plugins/editor_preview_plugins.cpp
+++ /dev/null
@@ -1,907 +0,0 @@
-/*************************************************************************/
-/* editor_preview_plugins.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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_preview_plugins.h"
-
-#include "io/resource_loader.h"
-#include "tools/editor/editor_settings.h"
-#include "io/file_access_memory.h"
-#include "os/os.h"
-#include "scene/resources/material.h"
-//#include "scene/resources/sample.h"
-#include "scene/resources/mesh.h"
-#include "scene/resources/bit_mask.h"
-#include "tools/editor/editor_scale.h"
-
-#if 0
-bool EditorTexturePreviewPlugin::handles(const String& p_type) const {
-
- return (ClassDB::is_type(p_type,"ImageTexture") || ClassDB::is_type(p_type, "AtlasTexture"));
-}
-
-Ref<Texture> EditorTexturePreviewPlugin::generate(const RES& p_from) {
-
- 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>();
-
- img.clear_mipmaps();
-
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- if (img.is_compressed()) {
- if (img.decompress()!=OK)
- return Ref<Texture>();
- } else if (img.get_format()!=Image::FORMAT_RGB8 && img.get_format()!=Image::FORMAT_RGBA8) {
- img.convert(Image::FORMAT_RGBA8);
- }
-
- 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;
-
-}
-
-EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
-
-
-}
-
-////////////////////////////////////////////////////////////////////////////
-
-bool EditorBitmapPreviewPlugin::handles(const String& p_type) const {
-
- return ClassDB::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>();
- }
-
- PoolVector<uint8_t> data;
-
- data.resize(bm->get_size().width*bm->get_size().height);
-
- {
- PoolVector<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_L8,data);
-
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- if (img.is_compressed()) {
- if (img.decompress()!=OK)
- return Ref<Texture>();
- } else if (img.get_format()!=Image::FORMAT_RGB8 && img.get_format()!=Image::FORMAT_RGBA8) {
- img.convert(Image::FORMAT_RGBA8);
- }
-
- 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() {
-
-
-}
-
-///////////////////////////////////////////////////////////////////////////
-
-
-Ref<Texture> EditorPackedScenePreviewPlugin::_gen_from_imd(Ref<ResourceImportMetadata> p_imd) {
-
- if (p_imd.is_null()) {
- return Ref<Texture>();
- }
-
- if (!p_imd->has_option("thumbnail"))
- return Ref<Texture>();
-
- Variant tn = p_imd->get_option("thumbnail");
- //print_line(Variant::get_type_name(tn.get_type()));
- PoolVector<uint8_t> thumbnail = tn;
-
- int len = thumbnail.size();
- if (len==0)
- return Ref<Texture>();
-
-
- PoolVector<uint8_t>::Read r = thumbnail.read();
-
- Image img(r.ptr(),len);
- if (img.empty())
- return Ref<Texture>();
-
- Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
- ptex->create_from_image(img,0);
- return ptex;
-
-}
-
-bool EditorPackedScenePreviewPlugin::handles(const String& p_type) const {
-
- return ClassDB::is_type(p_type,"PackedScene");
-}
-Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES& p_from) {
-
- Ref<ResourceImportMetadata> imd = p_from->get_import_metadata();
- return _gen_from_imd(imd);
-}
-
-Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String& p_path) {
-
- Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path);
- return _gen_from_imd(imd);
-}
-
-EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
-
-}
-
-//////////////////////////////////////////////////////////////////
-
-bool EditorMaterialPreviewPlugin::handles(const String& p_type) const {
-
- return ClassDB::is_type(p_type,"Material"); //any material
-}
-
-Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES& p_from) {
-
- Ref<Material> material = p_from;
- ERR_FAIL_COND_V(material.is_null(),Ref<Texture>());
-
- VS::get_singleton()->mesh_surface_set_material(sphere,0,material->get_rid());
-
- VS::get_singleton()->viewport_queue_screen_capture(viewport);
- VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
- //print_line("queue capture!");
- Image img;
-
- int timeout=1000;
- while(timeout) {
- //print_line("try capture?");
- OS::get_singleton()->delay_usec(10);
- img = VS::get_singleton()->viewport_get_screen_capture(viewport);
- if (!img.empty())
- break;
- timeout--;
- }
-
- //print_line("captured!");
- VS::get_singleton()->mesh_surface_set_material(sphere,0,RID());
-
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- img.resize(thumbnail_size,thumbnail_size);
-
- Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
- ptex->create_from_image(img,0);
- return ptex;
-}
-
-EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
-
- scenario = VS::get_singleton()->scenario_create();
-
- viewport = VS::get_singleton()->viewport_create();
- VS::get_singleton()->viewport_set_as_render_target(viewport,true);
- VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED);
- VS::get_singleton()->viewport_set_scenario(viewport,scenario);
- VS::ViewportRect vr;
- vr.x=0;
- vr.y=0;
- vr.width=128;
- vr.height=128;
- VS::get_singleton()->viewport_set_rect(viewport,vr);
-
- camera = VS::get_singleton()->camera_create();
- VS::get_singleton()->viewport_attach_camera(viewport,camera);
- VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3)));
- VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
-
- light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
- light_instance = VS::get_singleton()->instance_create2(light,scenario);
- VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
-
- light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
- VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7));
- VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0));
- light_instance2 = VS::get_singleton()->instance_create2(light2,scenario);
-
- VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
-
- sphere = VS::get_singleton()->mesh_create();
- sphere_instance = VS::get_singleton()->instance_create2(sphere,scenario);
-
- int lats=32;
- int lons=32;
- float radius=1.0;
-
- PoolVector<Vector3> vertices;
- PoolVector<Vector3> normals;
- PoolVector<Vector2> uvs;
- PoolVector<float> tangents;
- Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5);
-
- for(int i = 1; i <= lats; i++) {
- double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
- double z0 = Math::sin(lat0);
- double zr0 = Math::cos(lat0);
-
- double lat1 = Math_PI * (-0.5 + (double) i / lats);
- double z1 = Math::sin(lat1);
- double zr1 = Math::cos(lat1);
-
- for(int j = lons; j >= 1; j--) {
-
- double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
- double x0 = Math::cos(lng0);
- double y0 = Math::sin(lng0);
-
- double lng1 = 2 * Math_PI * (double) (j) / lons;
- double x1 = Math::cos(lng1);
- double y1 = Math::sin(lng1);
-
-
- Vector3 v[4]={
- Vector3(x1 * zr0, z0, y1 *zr0),
- Vector3(x1 * zr1, z1, y1 *zr1),
- Vector3(x0 * zr1, z1, y0 *zr1),
- Vector3(x0 * zr0, z0, y0 *zr0)
- };
-
-#define ADD_POINT(m_idx) \
- normals.push_back(v[m_idx]);\
- vertices.push_back(v[m_idx]*radius);\
- { Vector2 uv(Math::atan2(v[m_idx].x,v[m_idx].z),Math::atan2(-v[m_idx].y,v[m_idx].z));\
- uv/=Math_PI;\
- uv*=4.0;\
- uv=uv*0.5+Vector2(0.5,0.5);\
- uvs.push_back(uv);\
- }\
- { Vector3 t = tt.xform(v[m_idx]);\
- tangents.push_back(t.x);\
- tangents.push_back(t.y);\
- tangents.push_back(t.z);\
- tangents.push_back(1.0);\
- }
-
-
-
- ADD_POINT(0);
- ADD_POINT(1);
- ADD_POINT(2);
-
- ADD_POINT(2);
- ADD_POINT(3);
- ADD_POINT(0);
- }
- }
-
- Array arr;
- arr.resize(VS::ARRAY_MAX);
- arr[VS::ARRAY_VERTEX]=vertices;
- arr[VS::ARRAY_NORMAL]=normals;
- arr[VS::ARRAY_TANGENT]=tangents;
- arr[VS::ARRAY_TEX_UV]=uvs;
- VS::get_singleton()->mesh_add_surface(sphere,VS::PRIMITIVE_TRIANGLES,arr);
-
-}
-
-EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
-
- VS::get_singleton()->free(sphere);
- VS::get_singleton()->free(sphere_instance);
- VS::get_singleton()->free(viewport);
- VS::get_singleton()->free(light);
- VS::get_singleton()->free(light_instance);
- VS::get_singleton()->free(light2);
- VS::get_singleton()->free(light_instance2);
- VS::get_singleton()->free(camera);
- VS::get_singleton()->free(scenario);
-
-}
-
-///////////////////////////////////////////////////////////////////////////
-
-static bool _is_text_char(CharType c) {
-
- return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_';
-}
-
-bool EditorScriptPreviewPlugin::handles(const String& p_type) const {
-
- return ClassDB::is_type(p_type,"Script");
-}
-
-Ref<Texture> EditorScriptPreviewPlugin::generate(const RES& p_from) {
-
-
- Ref<Script> scr = p_from;
- if (scr.is_null())
- return Ref<Texture>();
-
- String code = scr->get_source_code().strip_edges();
- if (code=="")
- return Ref<Texture>();
-
- List<String> kwors;
- scr->get_language()->get_reserved_words(&kwors);
-
- Set<String> keywords;
-
- for(List<String>::Element *E=kwors.front();E;E=E->next()) {
-
- keywords.insert(E->get());
-
- }
-
-
- int line = 0;
- int col=0;
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- Image img(thumbnail_size,thumbnail_size,0,Image::FORMAT_RGBA8);
-
-
-
- Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color");
- bg_color.a=1.0;
- Color keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color");
- Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color");
- Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color");
-
-
- for(int i=0;i<thumbnail_size;i++) {
- for(int j=0;j<thumbnail_size;j++) {
- img.put_pixel(i,j,bg_color);
- }
-
- }
-
- bool prev_is_text=false;
- bool in_keyword=false;
- for(int i=0;i<code.length();i++) {
-
- CharType c = code[i];
- if (c>32) {
- if (col<thumbnail_size) {
- Color color = text_color;
-
- if (c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t')) {
- //make symbol a little visible
- color=symbol_color;
- in_keyword=false;
- } else if (!prev_is_text && _is_text_char(c)) {
- int pos = i;
-
- while(_is_text_char(code[pos])) {
- pos++;
- }
- ///print_line("from "+itos(i)+" to "+itos(pos));
- String word = code.substr(i,pos-i);
- //print_line("found word: "+word);
- if (keywords.has(word))
- in_keyword=true;
-
- } else if (!_is_text_char(c)) {
- in_keyword=false;
- }
-
- if (in_keyword)
- color=keyword_color;
-
- Color ul=color;
- ul.a*=0.5;
- img.put_pixel(col,line*2,bg_color.blend(ul));
- img.put_pixel(col,line*2+1,color);
-
- prev_is_text=_is_text_char(c);
- }
- } else {
-
- prev_is_text=false;
- in_keyword=false;
-
- if (c=='\n') {
- col=0;
- line++;
- if (line>=thumbnail_size/2)
- break;
- } else if (c=='\t') {
- col+=3;
- }
- }
- col++;
- }
-
- Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
-
- ptex->create_from_image(img,0);
- return ptex;
-
-}
-
-EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
-
-
-}
-///////////////////////////////////////////////////////////////////
-#if 0
-bool EditorSamplePreviewPlugin::handles(const String& p_type) const {
-
- return ClassDB::is_type(p_type,"Sample");
-}
-
-Ref<Texture> EditorSamplePreviewPlugin::generate(const RES& p_from) {
-
- Ref<Sample> smp =p_from;
- ERR_FAIL_COND_V(smp.is_null(),Ref<Texture>());
-
-
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- PoolVector<uint8_t> img;
- int w = thumbnail_size;
- int h = thumbnail_size;
- img.resize(w*h*3);
-
- PoolVector<uint8_t>::Write imgdata = img.write();
- uint8_t * imgw = imgdata.ptr();
- PoolVector<uint8_t> data = smp->get_data();
- PoolVector<uint8_t>::Read sampledata = data.read();
- const uint8_t *sdata=sampledata.ptr();
-
- bool stereo = smp->is_stereo();
- bool _16=smp->get_format()==Sample::FORMAT_PCM16;
- int len = smp->get_length();
-
- if (len<1)
- return Ref<Texture>();
-
- if (smp->get_format()==Sample::FORMAT_IMA_ADPCM) {
-
- struct IMA_ADPCM_State {
-
- int16_t step_index;
- int32_t predictor;
- /* values at loop point */
- int16_t loop_step_index;
- int32_t loop_predictor;
- int32_t last_nibble;
- int32_t loop_pos;
- int32_t window_ofs;
- const uint8_t *ptr;
- } ima_adpcm;
-
- ima_adpcm.step_index=0;
- ima_adpcm.predictor=0;
- ima_adpcm.loop_step_index=0;
- ima_adpcm.loop_predictor=0;
- ima_adpcm.last_nibble=-1;
- ima_adpcm.loop_pos=0x7FFFFFFF;
- ima_adpcm.window_ofs=0;
- ima_adpcm.ptr=NULL;
-
-
- for(int i=0;i<w;i++) {
-
- float max[2]={-1e10,-1e10};
- float min[2]={1e10,1e10};
- int from = i*len/w;
- int to = (i+1)*len/w;
- if (to>=len)
- to=len-1;
-
- for(int j=from;j<to;j++) {
-
- while(j>ima_adpcm.last_nibble) {
-
- static const int16_t _ima_adpcm_step_table[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
- };
-
- static const int8_t _ima_adpcm_index_table[16] = {
- -1, -1, -1, -1, 2, 4, 6, 8,
- -1, -1, -1, -1, 2, 4, 6, 8
- };
-
- int16_t nibble,diff,step;
-
- ima_adpcm.last_nibble++;
- const uint8_t *src_ptr=sdata;
-
- int ofs = ima_adpcm.last_nibble>>1;
-
- if (stereo)
- ofs*=2;
-
-
- nibble = (ima_adpcm.last_nibble&1)?
- (src_ptr[ofs]>>4):(src_ptr[ofs]&0xF);
- step=_ima_adpcm_step_table[ima_adpcm.step_index];
-
- ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
- if (ima_adpcm.step_index<0)
- ima_adpcm.step_index=0;
- if (ima_adpcm.step_index>88)
- ima_adpcm.step_index=88;
-
- diff = step >> 3 ;
- if (nibble & 1)
- diff += step >> 2 ;
- if (nibble & 2)
- diff += step >> 1 ;
- if (nibble & 4)
- diff += step ;
- if (nibble & 8)
- diff = -diff ;
-
- ima_adpcm.predictor+=diff;
- if (ima_adpcm.predictor<-0x8000)
- ima_adpcm.predictor=-0x8000;
- else if (ima_adpcm.predictor>0x7FFF)
- ima_adpcm.predictor=0x7FFF;
-
-
- /* store loop if there */
- if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {
-
- ima_adpcm.loop_step_index = ima_adpcm.step_index;
- ima_adpcm.loop_predictor = ima_adpcm.predictor;
- }
-
- }
-
- float v=ima_adpcm.predictor/32767.0;
- if (v>max[0])
- max[0]=v;
- if (v<min[0])
- min[0]=v;
- }
- max[0]*=0.8;
- min[0]*=0.8;
-
- for(int j=0;j<h;j++) {
- float v = (j/(float)h) * 2.0 - 1.0;
- uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
- if (v>min[0] && v<max[0]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
- }
- }
- }
- } else {
- for(int i=0;i<w;i++) {
- // i trust gcc will optimize this loop
- float max[2]={-1e10,-1e10};
- float min[2]={1e10,1e10};
- int c=stereo?2:1;
- int from = uint64_t(i)*len/w;
- int to = (uint64_t(i)+1)*len/w;
- if (to>=len)
- to=len-1;
-
- if (_16) {
- const int16_t*src =(const int16_t*)sdata;
-
- for(int j=0;j<c;j++) {
-
- for(int k=from;k<=to;k++) {
-
- float v = src[uint64_t(k)*c+j]/32768.0;
- if (v>max[j])
- max[j]=v;
- if (v<min[j])
- min[j]=v;
- }
-
- }
- } else {
-
- const int8_t*src =(const int8_t*)sdata;
-
- for(int j=0;j<c;j++) {
-
- for(int k=from;k<=to;k++) {
-
- float v = src[uint64_t(k)*c+j]/128.0;
- if (v>max[j])
- max[j]=v;
- if (v<min[j])
- min[j]=v;
- }
-
- }
- }
-
- max[0]*=0.8;
- max[1]*=0.8;
- min[0]*=0.8;
- min[1]*=0.8;
-
- if (!stereo) {
- for(int j=0;j<h;j++) {
- float v = (j/(float)h) * 2.0 - 1.0;
- uint8_t* imgofs = &imgw[(j*w+i)*3];
- if (v>min[0] && v<max[0]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
- }
- }
- } else {
-
- for(int j=0;j<h;j++) {
-
- int half;
- float v;
- if (j<(h/2)) {
- half=0;
- v = (j/(float)(h/2)) * 2.0 - 1.0;
- } else {
- half=1;
- if( (float)(h/2) != 0 ) {
- v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
- } else {
- v = ((j-(h/2))/(float)(1/2)) * 2.0 - 1.0;
- }
- }
-
- uint8_t* imgofs = &imgw[(j*w+i)*3];
- if (v>min[half] && v<max[half]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
- }
- }
-
- }
-
- }
- }
-
- imgdata = PoolVector<uint8_t>::Write();
-
- Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture));
- ptex->create_from_image(Image(w,h,0,Image::FORMAT_RGB8,img),0);
- return ptex;
-
-}
-
-EditorSamplePreviewPlugin::EditorSamplePreviewPlugin() {
-
-
-}
-#endif
-///////////////////////////////////////////////////////////////////////////
-
-bool EditorMeshPreviewPlugin::handles(const String& p_type) const {
-
- return ClassDB::is_type(p_type,"Mesh"); //any Mesh
-}
-
-Ref<Texture> EditorMeshPreviewPlugin::generate(const RES& p_from) {
-
- Ref<Mesh> mesh = p_from;
- ERR_FAIL_COND_V(mesh.is_null(),Ref<Texture>());
-
- VS::get_singleton()->instance_set_base(mesh_instance,mesh->get_rid());
-
- AABB aabb= mesh->get_aabb();
- Vector3 ofs = aabb.pos + aabb.size*0.5;
- aabb.pos-=ofs;
- Transform xform;
- xform.basis=Matrix3().rotated(Vector3(0,1,0),-Math_PI*0.125);
- xform.basis = Matrix3().rotated(Vector3(1,0,0),Math_PI*0.125)*xform.basis;
- AABB rot_aabb = xform.xform(aabb);
- float m = MAX(rot_aabb.size.x,rot_aabb.size.y)*0.5;
- if (m==0)
- return Ref<Texture>();
- m=1.0/m;
- m*=0.5;
- //print_line("scale: "+rtos(m));
- xform.basis.scale(Vector3(m,m,m));
- xform.origin=-xform.basis.xform(ofs); //-ofs*m;
- xform.origin.z-=rot_aabb.size.z*2;
- VS::get_singleton()->instance_set_transform(mesh_instance,xform);
-
-
-
- VS::get_singleton()->viewport_queue_screen_capture(viewport);
- VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
- //print_line("queue capture!");
- Image img;
-
- int timeout=1000;
- while(timeout) {
- //print_line("try capture?");
- OS::get_singleton()->delay_usec(10);
- img = VS::get_singleton()->viewport_get_screen_capture(viewport);
- if (!img.empty())
- break;
- timeout--;
- }
-
- //print_line("captured!");
- VS::get_singleton()->instance_set_base(mesh_instance,RID());
-
- int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size");
- thumbnail_size*=EDSCALE;
- img.resize(thumbnail_size,thumbnail_size);
-
- Ref<ImageTexture> ptex = Ref<ImageTexture>( memnew( ImageTexture ));
- ptex->create_from_image(img,0);
- return ptex;
-}
-
-EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
-
- scenario = VS::get_singleton()->scenario_create();
- viewport = VS::get_singleton()->viewport_create();
- VS::get_singleton()->viewport_set_as_render_target(viewport,true);
- VS::get_singleton()->viewport_set_render_target_update_mode(viewport,VS::RENDER_TARGET_UPDATE_DISABLED);
- VS::get_singleton()->viewport_set_scenario(viewport,scenario);
- VS::ViewportRect vr;
- vr.x=0;
- vr.y=0;
- vr.width=128;
- vr.height=128;
- VS::get_singleton()->viewport_set_rect(viewport,vr);
-
- camera = VS::get_singleton()->camera_create();
- VS::get_singleton()->viewport_attach_camera(viewport,camera);
- VS::get_singleton()->camera_set_transform(camera,Transform(Matrix3(),Vector3(0,0,3)));
- //VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
- VS::get_singleton()->camera_set_orthogonal(camera,1.0,0.01,1000.0);
-
- light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
- light_instance = VS::get_singleton()->instance_create2(light,scenario);
- VS::get_singleton()->instance_set_transform(light_instance,Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
-
- light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
- VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_DIFFUSE,Color(0.7,0.7,0.7));
- VS::get_singleton()->light_set_color(light2,VS::LIGHT_COLOR_SPECULAR,Color(0.0,0.0,0.0));
- light_instance2 = VS::get_singleton()->instance_create2(light2,scenario);
-
- VS::get_singleton()->instance_set_transform(light_instance2,Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
-
- //sphere = VS::get_singleton()->mesh_create();
- mesh_instance = VS::get_singleton()->instance_create();
- VS::get_singleton()->instance_set_scenario(mesh_instance,scenario);
-
-
-
-}
-
-
-EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
-
- //VS::get_singleton()->free(sphere);
- VS::get_singleton()->free(mesh_instance);
- VS::get_singleton()->free(viewport);
- VS::get_singleton()->free(light);
- VS::get_singleton()->free(light_instance);
- VS::get_singleton()->free(light2);
- VS::get_singleton()->free(light_instance2);
- VS::get_singleton()->free(camera);
- VS::get_singleton()->free(scenario);
-
-}
-#endif
diff --git a/tools/editor/plugins/editor_preview_plugins.h b/tools/editor/plugins/editor_preview_plugins.h
deleted file mode 100644
index 078e4cf8b5..0000000000
--- a/tools/editor/plugins/editor_preview_plugins.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*************************************************************************/
-/* editor_preview_plugins.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 EDITORPREVIEWPLUGINS_H
-#define EDITORPREVIEWPLUGINS_H
-
-#include "tools/editor/editor_resource_preview.h"
-
-#if 0
-class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
-public:
-
- virtual bool handles(const String& p_type) const;
- virtual Ref<Texture> generate(const RES& p_from);
-
- EditorTexturePreviewPlugin();
-};
-
-
-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);
-public:
-
- virtual bool handles(const String& p_type) const;
- virtual Ref<Texture> generate(const RES& p_from);
- virtual Ref<Texture> generate_from_path(const String& p_path);
-
- EditorPackedScenePreviewPlugin();
-};
-
-class EditorMaterialPreviewPlugin : public EditorResourcePreviewGenerator {
-
- RID scenario;
- RID sphere;
- RID sphere_instance;
- RID viewport;
- RID light;
- RID light_instance;
- RID light2;
- RID light_instance2;
- RID camera;
-public:
-
- virtual bool handles(const String& p_type) const;
- virtual Ref<Texture> generate(const RES& p_from);
-
- EditorMaterialPreviewPlugin();
- ~EditorMaterialPreviewPlugin();
-};
-
-class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
-public:
-
- virtual bool handles(const String& p_type) const;
- virtual Ref<Texture> generate(const RES& p_from);
-
- EditorScriptPreviewPlugin();
-};
-
-#if 0
-class EditorSamplePreviewPlugin : public EditorResourcePreviewGenerator {
-public:
-
- virtual bool handles(const String& p_type) const;
- virtual Ref<Texture> generate(const RES& p_from);
-
- EditorSamplePreviewPlugin();
-};
-
-#endif
-class EditorMeshPreviewPlugin : public EditorResourcePreviewGenerator {
-
- RID scenario;
- RID mesh_instance;
- RID viewport;
- RID light;
- RID light_instance;
- RID light2;
- RID light_instance2;
- RID camera;
-public:
-
- virtual bool handles(const String& p_type) const;
- virtual Ref<Texture> generate(const RES& p_from);
-
- EditorMeshPreviewPlugin();
- ~EditorMeshPreviewPlugin();
-};
-
-#endif
-#endif // EDITORPREVIEWPLUGINS_H
diff --git a/tools/editor/plugins/gi_probe_editor_plugin.cpp b/tools/editor/plugins/gi_probe_editor_plugin.cpp
deleted file mode 100644
index 39f32d0dc7..0000000000
--- a/tools/editor/plugins/gi_probe_editor_plugin.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*************************************************************************/
-/* gi_probe_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "gi_probe_editor_plugin.h"
-
-
-void GIProbeEditorPlugin::_bake() {
-
- if (gi_probe) {
- gi_probe->bake();
- }
-}
-
-
-void GIProbeEditorPlugin::edit(Object *p_object) {
-
- GIProbe * s = p_object->cast_to<GIProbe>();
- if (!s)
- return;
-
- gi_probe=s;
-}
-
-bool GIProbeEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("GIProbe");
-}
-
-void GIProbeEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- bake->show();
- } else {
-
- bake->hide();
- }
-
-}
-
-void GIProbeEditorPlugin::_bind_methods() {
-
- ClassDB::bind_method("_bake",&GIProbeEditorPlugin::_bake);
-}
-
-GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- bake = memnew( Button );
- bake->set_icon(editor->get_gui_base()->get_icon("BakedLight","EditorIcons"));
- bake->hide();
- bake->connect("pressed",this,"_bake");
- add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU,bake);
- gi_probe=NULL;
-}
-
-
-GIProbeEditorPlugin::~GIProbeEditorPlugin() {
-
- memdelete(bake);
-}
diff --git a/tools/editor/plugins/gi_probe_editor_plugin.h b/tools/editor/plugins/gi_probe_editor_plugin.h
deleted file mode 100644
index 35e0b93aae..0000000000
--- a/tools/editor/plugins/gi_probe_editor_plugin.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*************************************************************************/
-/* gi_probe_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 GIPROBEEDITORPLUGIN_H
-#define GIPROBEEDITORPLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/resources/material.h"
-#include "scene/3d/gi_probe.h"
-
-
-
-class GIProbeEditorPlugin : public EditorPlugin {
-
- GDCLASS( GIProbeEditorPlugin, EditorPlugin );
-
- GIProbe *gi_probe;
-
- Button *bake;
- EditorNode *editor;
-
- void _bake();
-protected:
-
- static void _bind_methods();
-public:
-
- virtual String get_name() const { return "GIProbe"; }
- 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);
-
- GIProbeEditorPlugin(EditorNode *p_node);
- ~GIProbeEditorPlugin();
-
-};
-
-#endif // GIPROBEEDITORPLUGIN_H
diff --git a/tools/editor/plugins/item_list_editor_plugin.h b/tools/editor/plugins/item_list_editor_plugin.h
deleted file mode 100644
index 74700d615e..0000000000
--- a/tools/editor/plugins/item_list_editor_plugin.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*************************************************************************/
-/* item_list_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 ITEM_LIST_EDITOR_PLUGIN_H
-#define ITEM_LIST_EDITOR_PLUGIN_H
-
-#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"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-
-class ItemListPlugin : public Object {
-
- GDCLASS(ItemListPlugin,Object);
-
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value);
- bool _get(const StringName& p_name,Variant &r_ret) const;
- void _get_property_list( List<PropertyInfo> *p_list) const;
-
-public:
-
- enum Flags {
-
- FLAG_ICON=1,
- FLAG_CHECKABLE=2,
- 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 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 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 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;
- virtual void erase(int p_idx)=0;
-
- ItemListPlugin() {}
-};
-
-///////////////////////////////////////////////////////////////
-
-class ItemListOptionButtonPlugin : public ItemListPlugin {
-
- GDCLASS(ItemListOptionButtonPlugin,ItemListPlugin);
-
- OptionButton *ob;
-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) { ob->set_item_text(p_idx,p_text); }
- virtual String get_item_text(int p_idx) const { return ob->get_item_text(p_idx); }
-
- 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); }
-
- 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 {
-
- GDCLASS(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 {
-
- GDCLASS(ItemListEditor,HBoxContainer);
-
- Node *item_list;
-
- ToolButton *toolbar_button;
-
- AcceptDialog *dialog;
- PropertyEditor *property_editor;
- Tree *tree;
- Button *add_button;
- Button *del_button;
-
- int selected_idx;
-
- Vector<ItemListPlugin*> item_plugins;
-
- 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:
-
- void edit(Node *p_item_list);
- bool handles(Object *p_object) const;
- void add_plugin(ItemListPlugin* p_plugin) { item_plugins.push_back(p_plugin); }
- ItemListEditor();
- ~ItemListEditor();
-};
-
-class ItemListEditorPlugin : public EditorPlugin {
-
- GDCLASS(ItemListEditorPlugin,EditorPlugin);
-
- ItemListEditor *item_list_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "ItemList"; }
- 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);
-
- ItemListEditorPlugin(EditorNode *p_node);
- ~ItemListEditorPlugin();
-
-};
-
-#endif // ITEM_LIST_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
deleted file mode 100644
index f6a51632a0..0000000000
--- a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp
+++ /dev/null
@@ -1,518 +0,0 @@
-/*************************************************************************/
-/* light_occluder_2d_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "light_occluder_2d_editor_plugin.h"
-
-#include "canvas_item_editor_plugin.h"
-#include "os/file_access.h"
-#include "tools/editor/editor_settings.h"
-
-void LightOccluder2DEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon( get_icon("Edit","EditorIcons"));
- button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed",this,"_node_removed");
- create_poly->connect("confirmed",this,"_create_poly");
-
- } break;
- case NOTIFICATION_FIXED_PROCESS: {
-
-
- } break;
- }
-
-}
-void LightOccluder2DEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- canvas_item_editor->get_viewport_control()->update();
- }
-
-}
-
-
-void LightOccluder2DEditor::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case MODE_CREATE: {
-
- mode=MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode=MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
-
- }
-}
-
-void LightOccluder2DEditor::_wip_close(bool p_closed) {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",node->get_occluder_polygon()->get_polygon());
- undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",wip);
- undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_closed",node->get_occluder_polygon()->is_closed());
- undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_closed",p_closed);
-
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- wip.clear();
- wip_active=false;
- mode=MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point=-1;
-}
-
-bool LightOccluder2DEditor::forward_gui_input(const InputEvent& p_event) {
-
-
- if (!node)
- return false;
-
- if (node->get_occluder_polygon().is_null()) {
- if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
- create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?");
- create_poly->popup_centered_minsize();
- }
- return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);
- }
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
-
- Vector2 gpoint = Point2(mb.x,mb.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
- Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
-
- //first check if a point is to be added (segment split)
- real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
-
- switch(mode) {
-
-
- case MODE_CREATE: {
-
- if (mb.button_index==BUTTON_LEFT && mb.pressed) {
-
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back( cpoint );
- wip_active=true;
- edited_point_pos=cpoint;
- canvas_item_editor->get_viewport_control()->update();
- edited_point=1;
- return true;
- } else {
-
-
- if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
- //wip closed
- _wip_close(true);
-
- return true;
- } else if (wip.size()>1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)<grab_treshold) {
- //wip closed
- _wip_close(false);
- return true;
-
- } else {
-
- wip.push_back( cpoint );
- edited_point=wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
- _wip_close(true);
- }
-
-
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb.button_index==BUTTON_LEFT) {
- if (mb.pressed) {
-
- if (mb.mod.control) {
-
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 points[2] ={ xform.xform(poly[i]),
- xform.xform(poly[(i+1)%poly.size()]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
- if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
- edited_point=closest_idx+1;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- node->get_occluder_polygon()->set_polygon(Variant(poly));
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- edited_point=closest_idx;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point!=-1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
- poly[edited_point]=edited_point_pos;
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
- undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- edited_point=-1;
- return true;
- }
- }
- } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
-
-
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- }
-
-
-
- } break;
- }
-
-
-
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mm=p_event.mouse_motion;
-
- if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = Point2(mm.x,mm.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
-
- }
-
- } break;
- }
-
- return false;
-}
-void LightOccluder2DEditor::_canvas_draw() {
-
- if (!node || !node->get_occluder_polygon().is_valid())
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly=wip;
- else
- poly=Variant(node->get_occluder_polygon()->get_polygon());
-
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
-
- for(int i=0;i<poly.size();i++) {
-
-
- Vector2 p,p2;
- p = i==edited_point ? edited_point_pos : poly[i];
- if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
- p2=edited_point_pos;
- else
- p2 = poly[(i+1)%poly.size()];
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col=Color(1,0.3,0.1,0.8);
-
- if (i==poly.size()-1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) {
-
- } else {
- vpc->draw_line(point,next_point,col,2);
- }
- vpc->draw_texture(handle,point-handle->get_size()*0.5);
- }
-}
-
-
-
-void LightOccluder2DEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor=CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node=p_collision_polygon->cast_to<LightOccluder2D>();
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
- wip.clear();
- wip_active=false;
- edited_point=-1;
- canvas_item_editor->get_viewport_control()->update();
- } else {
- node=NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
-
- }
-
-}
-
-void LightOccluder2DEditor::_create_poly() {
-
- if (!node)
- return;
- undo_redo->create_action(TTR("Create Occluder Polygon"));
- undo_redo->add_do_method(node,"set_occluder_polygon",Ref<OccluderPolygon2D>(memnew( OccluderPolygon2D)));
- undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF()));
- undo_redo->commit_action();
-}
-
-void LightOccluder2DEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_menu_option"),&LightOccluder2DEditor::_menu_option);
- ClassDB::bind_method(_MD("_canvas_draw"),&LightOccluder2DEditor::_canvas_draw);
- ClassDB::bind_method(_MD("_node_removed"),&LightOccluder2DEditor::_node_removed);
- ClassDB::bind_method(_MD("_create_poly"),&LightOccluder2DEditor::_create_poly);
-
-}
-
-
-LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) {
-
- node=NULL;
- canvas_item_editor=NULL;
- editor=p_editor;
- undo_redo = editor->get_undo_redo();
-
- add_child( memnew( VSeparator ));
- button_create = memnew( ToolButton );
- add_child(button_create);
- button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
- button_create->set_tooltip(TTR("Create a new polygon from scratch."));
-
- button_edit = memnew( ToolButton );
- add_child(button_edit);
- button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
- button_edit->set_tooltip(TTR("Edit existing polygon:")+"\n"+TTR("LMB: Move Point.")+"\n"+TTR("Ctrl+LMB: Split Segment.")+"\n"+TTR("RMB: Erase Point."));
-
- create_poly = memnew( ConfirmationDialog );
- add_child(create_poly);
- create_poly->get_ok()->set_text(TTR("Create"));
-
-
- //add_constant_override("separation",0);
-
-#if 0
- options = memnew( MenuButton );
- add_child(options);
- options->set_area_as_parent_rect();
- options->set_text("Polygon");
- //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
- options->get_popup()->connect("id_pressed", this,"_menu_option");
-#endif
-
- mode = MODE_EDIT;
- wip_active=false;
-
-}
-
-
-void LightOccluder2DEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool LightOccluder2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("LightOccluder2D");
-}
-
-void LightOccluder2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-
-}
-
-LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- collision_polygon_editor = memnew( LightOccluder2DEditor(p_node) );
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
-
-
-
-}
-
-
-LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.h b/tools/editor/plugins/light_occluder_2d_editor_plugin.h
deleted file mode 100644
index 431c01fe75..0000000000
--- a/tools/editor/plugins/light_occluder_2d_editor_plugin.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*************************************************************************/
-/* light_occluder_2d_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
-#define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
-
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/2d/light_occluder_2d.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/button_group.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class CanvasItemEditor;
-
-class LightOccluder2DEditor : public HBoxContainer {
-
- GDCLASS(LightOccluder2DEditor, HBoxContainer );
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
- LightOccluder2D *node;
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
- ConfirmationDialog *create_poly;
-
- void _wip_close(bool p_closed);
- void _canvas_draw();
- void _menu_option(int p_option);
- void _create_poly();
-
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- Vector2 snap_point(const Vector2& p_point) const;
- bool forward_gui_input(const InputEvent& p_event);
- void edit(Node *p_collision_polygon);
- LightOccluder2DEditor(EditorNode *p_editor);
-};
-
-class LightOccluder2DEditorPlugin : public EditorPlugin {
-
- GDCLASS( LightOccluder2DEditorPlugin, EditorPlugin );
-
- LightOccluder2DEditor *collision_polygon_editor;
- EditorNode *editor;
-
-public:
-
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "LightOccluder2D"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
- virtual void make_visible(bool p_visible);
-
- LightOccluder2DEditorPlugin(EditorNode *p_node);
- ~LightOccluder2DEditorPlugin();
-
-};
-
-#endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/material_editor_plugin.cpp b/tools/editor/plugins/material_editor_plugin.cpp
deleted file mode 100644
index 1aababa91b..0000000000
--- a/tools/editor/plugins/material_editor_plugin.cpp
+++ /dev/null
@@ -1,413 +0,0 @@
-/*************************************************************************/
-/* material_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "material_editor_plugin.h"
-
-#include "scene/main/viewport.h"
-
-#if 0
-
-void MaterialEditor::_gui_input(InputEvent p_event) {
-
-
-}
-
-void MaterialEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
- }
-
-
- if (p_what==NOTIFICATION_READY) {
-
- //get_scene()->connect("node_removed",this,"_node_removed");
-
- if (first_enter) {
- //it's in propertyeditor so.. could be moved around
-
- light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1","EditorIcons"));
- light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off","EditorIcons"));
- light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2","EditorIcons"));
- light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off","EditorIcons"));
-
- sphere_switch->set_normal_texture(get_icon("MaterialPreviewSphereOff","EditorIcons"));
- sphere_switch->set_pressed_texture(get_icon("MaterialPreviewSphere","EditorIcons"));
- box_switch->set_normal_texture(get_icon("MaterialPreviewCubeOff","EditorIcons"));
- box_switch->set_pressed_texture(get_icon("MaterialPreviewCube","EditorIcons"));
-
- first_enter=false;
- }
-
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
-
- Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons");
- Size2 size = get_size();
-
- draw_texture_rect(checkerboard,Rect2(Point2(),size),true);
-
- }
-}
-
-
-
-void MaterialEditor::edit(Ref<Material> p_material) {
-
- material=p_material;
-
- if (!material.is_null()) {
- sphere_mesh->surface_set_material(0,material);
- box_mesh->surface_set_material(0,material);
- } else {
-
- hide();
- }
-
-}
-
-
-void MaterialEditor::_button_pressed(Node* p_button) {
-
- if (p_button==light_1_switch) {
- light1->set_enabled(!light_1_switch->is_pressed());
- }
-
- if (p_button==light_2_switch) {
- light2->set_enabled(!light_2_switch->is_pressed());
- }
-
- if (p_button==box_switch) {
- box_instance->show();
- sphere_instance->hide();
- box_switch->set_pressed(true);
- sphere_switch->set_pressed(false);
- }
-
- if (p_button==sphere_switch) {
- box_instance->hide();
- sphere_instance->show();
- box_switch->set_pressed(false);
- sphere_switch->set_pressed(true);
- }
-
-}
-
-void MaterialEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&MaterialEditor::_gui_input);
- ClassDB::bind_method(_MD("_button_pressed"),&MaterialEditor::_button_pressed);
-
-}
-
-MaterialEditor::MaterialEditor() {
-
- viewport = memnew( Viewport );
- Ref<World> world;
- world.instance();
- viewport->set_world(world); //use own world
- add_child(viewport);
- viewport->set_disable_input(true);
-
- camera = memnew( Camera );
- camera->set_transform(Transform(Matrix3(),Vector3(0,0,3)));
- camera->set_perspective(45,0.1,10);
- viewport->add_child(camera);
-
- light1 = memnew( DirectionalLight );
- light1->set_transform(Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
- viewport->add_child(light1);
-
- light2 = memnew( DirectionalLight );
- light2->set_transform(Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
- light2->set_color(Light::COLOR_DIFFUSE,Color(0.7,0.7,0.7));
- light2->set_color(Light::COLOR_SPECULAR,Color(0.7,0.7,0.7));
- viewport->add_child(light2);
-
- sphere_instance = memnew( MeshInstance );
- viewport->add_child(sphere_instance);
-
- box_instance = memnew( MeshInstance );
- viewport->add_child(box_instance);
-
- Transform box_xform;
- box_xform.basis.rotate(Vector3(1,0,0),Math::deg2rad(25));
- box_xform.basis = box_xform.basis * Matrix3().rotated(Vector3(0,1,0),Math::deg2rad(25));
- box_xform.basis.scale(Vector3(0.8,0.8,0.8));
- box_instance->set_transform(box_xform);
-
- {
-
- sphere_mesh.instance();
-
-
- int lats=32;
- int lons=32;
- float radius=1.0;
-
- PoolVector<Vector3> vertices;
- PoolVector<Vector3> normals;
- PoolVector<Vector2> uvs;
- PoolVector<float> tangents;
- Matrix3 tt = Matrix3(Vector3(0,1,0),Math_PI*0.5);
-
- for(int i = 1; i <= lats; i++) {
- double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats);
- double z0 = Math::sin(lat0);
- double zr0 = Math::cos(lat0);
-
- double lat1 = Math_PI * (-0.5 + (double) i / lats);
- double z1 = Math::sin(lat1);
- double zr1 = Math::cos(lat1);
-
- for(int j = lons; j >= 1; j--) {
-
- double lng0 = 2 * Math_PI * (double) (j - 1) / lons;
- double x0 = Math::cos(lng0);
- double y0 = Math::sin(lng0);
-
- double lng1 = 2 * Math_PI * (double) (j) / lons;
- double x1 = Math::cos(lng1);
- double y1 = Math::sin(lng1);
-
-
- Vector3 v[4]={
- Vector3(x1 * zr0, z0, y1 *zr0),
- Vector3(x1 * zr1, z1, y1 *zr1),
- Vector3(x0 * zr1, z1, y0 *zr1),
- Vector3(x0 * zr0, z0, y0 *zr0)
- };
-
- #define ADD_POINT(m_idx) \
- normals.push_back(v[m_idx]);\
- vertices.push_back(v[m_idx]*radius);\
- { Vector2 uv(Math::atan2(v[m_idx].x,v[m_idx].z),Math::atan2(-v[m_idx].y,v[m_idx].z));\
- uv/=Math_PI;\
- uv*=4.0;\
- uv=uv*0.5+Vector2(0.5,0.5);\
- uvs.push_back(uv);\
- }\
- { Vector3 t = tt.xform(v[m_idx]);\
- tangents.push_back(t.x);\
- tangents.push_back(t.y);\
- tangents.push_back(t.z);\
- tangents.push_back(1.0);\
- }
-
-
-
- ADD_POINT(0);
- ADD_POINT(1);
- ADD_POINT(2);
-
- ADD_POINT(2);
- ADD_POINT(3);
- ADD_POINT(0);
- }
- }
-
- Array arr;
- arr.resize(VS::ARRAY_MAX);
- arr[VS::ARRAY_VERTEX]=vertices;
- arr[VS::ARRAY_NORMAL]=normals;
- arr[VS::ARRAY_TANGENT]=tangents;
- arr[VS::ARRAY_TEX_UV]=uvs;
-
- sphere_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr);
-
- sphere_instance->set_mesh(sphere_mesh);
-
- }
- {
-
-
- box_mesh.instance();
-
- PoolVector<Vector3> vertices;
- PoolVector<Vector3> normals;
- PoolVector<float> tangents;
- PoolVector<Vector3> uvs;
-
- int vtx_idx=0;
- #define ADD_VTX(m_idx);\
- vertices.push_back( face_points[m_idx] );\
- normals.push_back( normal_points[m_idx] );\
- tangents.push_back( normal_points[m_idx][1] );\
- tangents.push_back( normal_points[m_idx][2] );\
- tangents.push_back( normal_points[m_idx][0] );\
- tangents.push_back( 1.0 );\
- uvs.push_back( Vector3(uv_points[m_idx*2+0],uv_points[m_idx*2+1],0) );\
- vtx_idx++;\
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
- Vector3 normal_points[4];
- float uv_points[8]={0,0,0,1,1,1,1,0};
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- normal_points[j]=Vector3();
- normal_points[j][i%3]=(i>=3?-1:1);
- }
-
- //tri 1
- ADD_VTX(0);
- ADD_VTX(1);
- ADD_VTX(2);
- //tri 2
- ADD_VTX(2);
- ADD_VTX(3);
- ADD_VTX(0);
-
- }
-
-
-
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[VisualServer::ARRAY_NORMAL]= normals ;
- d[VisualServer::ARRAY_TANGENT]= tangents ;
- d[VisualServer::ARRAY_TEX_UV]= uvs ;
- d[VisualServer::ARRAY_VERTEX]= vertices ;
-
- PoolVector<int> indices;
- indices.resize(vertices.size());
- for(int i=0;i<vertices.size();i++)
- indices.set(i,i);
- d[VisualServer::ARRAY_INDEX]=indices;
-
- box_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d);
- box_instance->set_mesh(box_mesh);
- box_instance->hide();
-
-
-
- }
-
- set_custom_minimum_size(Size2(1,150)*EDSCALE);
-
- HBoxContainer *hb = memnew( HBoxContainer );
- add_child(hb);
- hb->set_area_as_parent_rect(2);
-
- VBoxContainer *vb_shape = memnew( VBoxContainer );
- hb->add_child(vb_shape);
-
- sphere_switch = memnew( TextureButton );
- sphere_switch->set_toggle_mode(true);
- sphere_switch->set_pressed(true);
- vb_shape->add_child(sphere_switch);
- sphere_switch->connect("pressed",this,"_button_pressed",varray(sphere_switch));
-
- box_switch = memnew( TextureButton );
- box_switch->set_toggle_mode(true);
- box_switch->set_pressed(false);
- vb_shape->add_child(box_switch);
- box_switch->connect("pressed",this,"_button_pressed",varray(box_switch));
-
- hb->add_spacer();
-
- VBoxContainer *vb_light = memnew( VBoxContainer );
- hb->add_child(vb_light);
-
- light_1_switch = memnew( TextureButton );
- light_1_switch->set_toggle_mode(true);
- vb_light->add_child(light_1_switch);
- light_1_switch->connect("pressed",this,"_button_pressed",varray(light_1_switch));
-
- light_2_switch = memnew( TextureButton );
- light_2_switch->set_toggle_mode(true);
- vb_light->add_child(light_2_switch);
- light_2_switch->connect("pressed",this,"_button_pressed",varray(light_2_switch));
-
- first_enter=true;
-
-}
-
-
-void MaterialEditorPlugin::edit(Object *p_object) {
-
- Material * s = p_object->cast_to<Material>();
- if (!s)
- return;
-
- material_editor->edit(Ref<Material>(s));
-}
-
-bool MaterialEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("Material");
-}
-
-void MaterialEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- material_editor->show();
- //material_editor->set_process(true);
- } else {
-
- material_editor->hide();
- //material_editor->set_process(false);
- }
-
-}
-
-MaterialEditorPlugin::MaterialEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- material_editor = memnew( MaterialEditor );
- add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,material_editor);
- material_editor->hide();
-
-
-
-}
-
-
-MaterialEditorPlugin::~MaterialEditorPlugin()
-{
-}
-
-
-#endif
diff --git a/tools/editor/plugins/material_editor_plugin.h b/tools/editor/plugins/material_editor_plugin.h
deleted file mode 100644
index 5daae124e0..0000000000
--- a/tools/editor/plugins/material_editor_plugin.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*************************************************************************/
-/* material_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 MATERIAL_EDITOR_PLUGIN_H
-#define MATERIAL_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/resources/material.h"
-#include "scene/3d/light.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/3d/camera.h"
-
-#if 0
-class MaterialEditor : public Control {
-
- GDCLASS(MaterialEditor, Control);
-
-
- Viewport *viewport;
- MeshInstance *sphere_instance;
- MeshInstance *box_instance;
- DirectionalLight *light1;
- DirectionalLight *light2;
- Camera *camera;
-
- Ref<Mesh> sphere_mesh;
- Ref<Mesh> box_mesh;
-
- TextureButton *sphere_switch;
- TextureButton *box_switch;
-
- TextureButton *light_1_switch;
- TextureButton *light_2_switch;
-
-
- Ref<Material> material;
-
-
- void _button_pressed(Node* p_button);
- bool first_enter;
-
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
- void edit(Ref<Material> p_material);
- MaterialEditor();
-};
-
-
-class MaterialEditorPlugin : public EditorPlugin {
-
- GDCLASS( MaterialEditorPlugin, EditorPlugin );
-
- MaterialEditor *material_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "Material"; }
- 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);
-
- MaterialEditorPlugin(EditorNode *p_node);
- ~MaterialEditorPlugin();
-
-};
-
-#endif // MATERIAL_EDITOR_PLUGIN_H
-#endif
diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp
deleted file mode 100644
index 49cb02c9d8..0000000000
--- a/tools/editor/plugins/mesh_editor_plugin.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-/*************************************************************************/
-/* mesh_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "mesh_editor_plugin.h"
-
-#if 0
-void MeshEditor::_gui_input(InputEvent p_event) {
-
-
- if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
-
- rot_x-=p_event.mouse_motion.relative_y*0.01;
- rot_y-=p_event.mouse_motion.relative_x*0.01;
- if (rot_x<-Math_PI/2)
- rot_x=-Math_PI/2;
- else if (rot_x>Math_PI/2) {
- rot_x=Math_PI/2;
- }
- _update_rotation();
- }
-}
-
-void MeshEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
- }
-
-
- if (p_what==NOTIFICATION_READY) {
-
- //get_scene()->connect("node_removed",this,"_node_removed");
-
- if (first_enter) {
- //it's in propertyeditor so.. could be moved around
-
- light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1","EditorIcons"));
- light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off","EditorIcons"));
- light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2","EditorIcons"));
- light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off","EditorIcons"));
- first_enter=false;
- }
-
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
-
- Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons");
- Size2 size = get_size();
-
- draw_texture_rect(checkerboard,Rect2(Point2(),size),true);
-
- }
-}
-
-void MeshEditor::_update_rotation() {
-
- Transform t;
- t.basis.rotate(Vector3(0, 1, 0), -rot_y);
- t.basis.rotate(Vector3(1, 0, 0), -rot_x);
- mesh_instance->set_transform(t);
-
-}
-
-void MeshEditor::edit(Ref<Mesh> p_mesh) {
-
- mesh=p_mesh;
- mesh_instance->set_mesh(mesh);
-
- if (mesh.is_null()) {
-
- hide();
- } else {
- rot_x=0;
- rot_y=0;
- _update_rotation();
-
- AABB aabb= mesh->get_aabb();
- Vector3 ofs = aabb.pos + aabb.size*0.5;
- aabb.pos-=ofs;
- float m = MAX(aabb.size.x,aabb.size.y)*0.5;
- if (m!=0) {
- m=1.0/m;
- m*=0.5;
- //print_line("scale: "+rtos(m));
- Transform xform;
- xform.basis.scale(Vector3(m,m,m));
- xform.origin=-xform.basis.xform(ofs); //-ofs*m;
- xform.origin.z-=aabb.size.z*2;
- mesh_instance->set_transform(xform);
- }
-
- }
-
-}
-
-
-void MeshEditor::_button_pressed(Node* p_button) {
-
- if (p_button==light_1_switch) {
- light1->set_enabled(!light_1_switch->is_pressed());
- }
-
- if (p_button==light_2_switch) {
- light2->set_enabled(!light_2_switch->is_pressed());
- }
-
-
-}
-
-void MeshEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&MeshEditor::_gui_input);
- ClassDB::bind_method(_MD("_button_pressed"),&MeshEditor::_button_pressed);
-
-}
-
-MeshEditor::MeshEditor() {
-
- viewport = memnew( Viewport );
- Ref<World> world;
- world.instance();
- viewport->set_world(world); //use own world
- add_child(viewport);
- viewport->set_disable_input(true);
-
- camera = memnew( Camera );
- camera->set_transform(Transform(Matrix3(),Vector3(0,0,3)));
- camera->set_perspective(45,0.1,10);
- viewport->add_child(camera);
-
- light1 = memnew( DirectionalLight );
- light1->set_transform(Transform().looking_at(Vector3(-1,-1,-1),Vector3(0,1,0)));
- viewport->add_child(light1);
-
- light2 = memnew( DirectionalLight );
- light2->set_transform(Transform().looking_at(Vector3(0,1,0),Vector3(0,0,1)));
- light2->set_color(Light::COLOR_DIFFUSE,Color(0.7,0.7,0.7));
- light2->set_color(Light::COLOR_SPECULAR,Color(0.7,0.7,0.7));
- viewport->add_child(light2);
-
- mesh_instance = memnew( MeshInstance );
- viewport->add_child(mesh_instance);
-
-
-
- set_custom_minimum_size(Size2(1,150)*EDSCALE);
-
- HBoxContainer *hb = memnew( HBoxContainer );
- add_child(hb);
- hb->set_area_as_parent_rect(2);
-
- hb->add_spacer();
-
- VBoxContainer *vb_light = memnew( VBoxContainer );
- hb->add_child(vb_light);
-
- light_1_switch = memnew( TextureButton );
- light_1_switch->set_toggle_mode(true);
- vb_light->add_child(light_1_switch);
- light_1_switch->connect("pressed",this,"_button_pressed",varray(light_1_switch));
-
- light_2_switch = memnew( TextureButton );
- light_2_switch->set_toggle_mode(true);
- vb_light->add_child(light_2_switch);
- light_2_switch->connect("pressed",this,"_button_pressed",varray(light_2_switch));
-
- first_enter=true;
-
- rot_x=0;
- rot_y=0;
-
-
-}
-
-
-void MeshEditorPlugin::edit(Object *p_object) {
-
- Mesh * s = p_object->cast_to<Mesh>();
- if (!s)
- return;
-
- mesh_editor->edit(Ref<Mesh>(s));
-}
-
-bool MeshEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("Mesh");
-}
-
-void MeshEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- mesh_editor->show();
- //mesh_editor->set_process(true);
- } else {
-
- mesh_editor->hide();
- //mesh_editor->set_process(false);
- }
-
-}
-
-MeshEditorPlugin::MeshEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- mesh_editor = memnew( MeshEditor );
- add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,mesh_editor);
- mesh_editor->hide();
-
-
-
-}
-
-
-MeshEditorPlugin::~MeshEditorPlugin()
-{
-}
-#endif
diff --git a/tools/editor/plugins/mesh_editor_plugin.h b/tools/editor/plugins/mesh_editor_plugin.h
deleted file mode 100644
index 136290ffd4..0000000000
--- a/tools/editor/plugins/mesh_editor_plugin.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*************************************************************************/
-/* mesh_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 MESH_EDITOR_PLUGIN_H
-#define MESH_EDITOR_PLUGIN_H
-
-#if 0
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/resources/material.h"
-#include "scene/3d/light.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/3d/camera.h"
-
-class MeshEditor : public Control {
-
- GDCLASS(MeshEditor, Control);
-
-
-
- float rot_x;
- float rot_y;
-
- Viewport *viewport;
- MeshInstance *mesh_instance;
- DirectionalLight *light1;
- DirectionalLight *light2;
- Camera *camera;
-
- Ref<Mesh> mesh;
-
-
- TextureButton *light_1_switch;
- TextureButton *light_2_switch;
-
- void _button_pressed(Node* p_button);
- bool first_enter;
-
- void _update_rotation();
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
- void edit(Ref<Mesh> p_mesh);
- MeshEditor();
-};
-
-
-class MeshEditorPlugin : public EditorPlugin {
-
- GDCLASS( MeshEditorPlugin, EditorPlugin );
-
- MeshEditor *mesh_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "Mesh"; }
- 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);
-
- MeshEditorPlugin(EditorNode *p_node);
- ~MeshEditorPlugin();
-
-};
-
-#endif // MESH_EDITOR_PLUGIN_H
-#endif
diff --git a/tools/editor/plugins/mesh_instance_editor_plugin.h b/tools/editor/plugins/mesh_instance_editor_plugin.h
deleted file mode 100644
index 441d4d1d3f..0000000000
--- a/tools/editor/plugins/mesh_instance_editor_plugin.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*************************************************************************/
-/* mesh_instance_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 MESH_INSTANCE_EDITOR_PLUGIN_H
-#define MESH_INSTANCE_EDITOR_PLUGIN_H
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/gui/spin_box.h"
-
-
-class MeshInstanceEditor : public Node {
-
- GDCLASS(MeshInstanceEditor, Node );
-
-
- enum Menu {
-
- MENU_OPTION_CREATE_STATIC_TRIMESH_BODY,
- MENU_OPTION_CREATE_STATIC_CONVEX_BODY,
- MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
- MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE,
- MENU_OPTION_CREATE_NAVMESH,
- MENU_OPTION_CREATE_OUTLINE_MESH,
- };
-
- MeshInstance *node;
-
- MenuButton *options;
-
- ConfirmationDialog *outline_dialog;
- SpinBox *outline_size;
-
- AcceptDialog *err_dialog;
-
- void _menu_option(int p_option);
- void _create_outline_mesh();
-
-friend class MeshInstanceEditorPlugin;
-
-protected:
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- void edit(MeshInstance *p_mesh);
- MeshInstanceEditor();
-};
-
-class MeshInstanceEditorPlugin : public EditorPlugin {
-
- GDCLASS( MeshInstanceEditorPlugin, EditorPlugin );
-
- MeshInstanceEditor *mesh_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "MeshInstance"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
- virtual void make_visible(bool p_visible);
-
- MeshInstanceEditorPlugin(EditorNode *p_node);
- ~MeshInstanceEditorPlugin();
-
-};
-
-#endif // MESH_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/multimesh_editor_plugin.h b/tools/editor/plugins/multimesh_editor_plugin.h
deleted file mode 100644
index e322850238..0000000000
--- a/tools/editor/plugins/multimesh_editor_plugin.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*************************************************************************/
-/* multimesh_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 MULTIMESH_EDITOR_PLUGIN_H
-#define MULTIMESH_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/multimesh_instance.h"
-#include "scene/gui/spin_box.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class MultiMeshEditor : public Control {
-
- GDCLASS(MultiMeshEditor, Control );
-
-friend class MultiMeshEditorPlugin;
-
- AcceptDialog *err_dialog;
- MenuButton * options;
- MultiMeshInstance *_last_pp_node;
- bool browsing_source;
-
- Panel *panel;
- MultiMeshInstance *node;
-
- LineEdit *surface_source;
- LineEdit *mesh_source;
-
- SceneTreeDialog *std;
-
- ConfirmationDialog *populate_dialog;
- OptionButton *populate_axis;
- HSlider *populate_rotate_random;
- HSlider *populate_tilt_random;
- SpinBox *populate_scale_random;
- SpinBox *populate_scale;
- SpinBox *populate_amount;
-
- enum Menu {
-
- MENU_OPTION_POPULATE
- };
-
- void _browsed(const NodePath& p_path);
- void _menu_option(int);
- void _populate();
- void _browse(bool p_source);
-
-protected:
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- void edit(MultiMeshInstance *p_multimesh);
- MultiMeshEditor();
-};
-
-class MultiMeshEditorPlugin : public EditorPlugin {
-
- GDCLASS( MultiMeshEditorPlugin, EditorPlugin );
-
- MultiMeshEditor *multimesh_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "MultiMesh"; }
- 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);
-
- MultiMeshEditorPlugin(EditorNode *p_node);
- ~MultiMeshEditorPlugin();
-
-};
-
-#endif // MULTIMESH_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
deleted file mode 100644
index e70f2be9fa..0000000000
--- a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ /dev/null
@@ -1,566 +0,0 @@
-/*************************************************************************/
-/* navigation_polygon_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "navigation_polygon_editor_plugin.h"
-
-#include "canvas_item_editor_plugin.h"
-#include "os/file_access.h"
-#include "tools/editor/editor_settings.h"
-
-void NavigationPolygonEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon( get_icon("Edit","EditorIcons"));
- button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
- button_edit->set_pressed(true);
- get_tree()->connect("node_removed",this,"_node_removed");
- create_nav->connect("confirmed",this,"_create_nav");
-
- } break;
- case NOTIFICATION_FIXED_PROCESS: {
-
-
- } break;
- }
-
-}
-void NavigationPolygonEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- canvas_item_editor->get_viewport_control()->update();
- }
-
-}
-
-void NavigationPolygonEditor::_create_nav() {
-
- if (!node)
- return;
-
- undo_redo->create_action(TTR("Create Navigation Polygon"));
- undo_redo->add_do_method(node,"set_navigation_polygon",Ref<NavigationPolygon>(memnew( NavigationPolygon)));
- undo_redo->add_undo_method(node,"set_navigation_polygon",Variant(REF()));
- undo_redo->commit_action();
-}
-
-void NavigationPolygonEditor::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case MODE_CREATE: {
-
- mode=MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode=MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
-
- }
-}
-
-void NavigationPolygonEditor::_wip_close() {
-
-
- if (wip.size()>=3) {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"remove_outline",node->get_navigation_polygon()->get_outline_count());
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"add_outline",wip);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- mode=MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- }
-
- wip.clear();
- wip_active=false;
- edited_point=-1;
-}
-
-bool NavigationPolygonEditor::forward_gui_input(const InputEvent& p_event) {
-
-
- if (!node)
- return false;
-
- if (node->get_navigation_polygon().is_null()) {
- if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
- create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?");
- create_nav->popup_centered_minsize();
- }
- return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);
- }
-
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
-
- Vector2 gpoint = Point2(mb.x,mb.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
-
-
- //first check if a point is to be added (segment split)
- real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
-
- switch(mode) {
-
-
- case MODE_CREATE: {
-
- if (mb.button_index==BUTTON_LEFT && mb.pressed) {
-
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back( cpoint );
- wip_active=true;
- edited_point_pos=cpoint;
- edited_outline=-1;
- canvas_item_editor->get_viewport_control()->update();
- edited_point=1;
- return true;
- } else {
-
-
- if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back( cpoint );
- edited_point=wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
- _wip_close();
- }
-
-
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb.button_index==BUTTON_LEFT) {
- if (mb.pressed) {
-
- if (mb.mod.control) {
-
-
- //search edges
- int closest_outline=-1;
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
-
- for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) {
-
-
- PoolVector<Vector2> points=node->get_navigation_polygon()->get_outline(j);
-
- int pc=points.size();
- PoolVector<Vector2>::Read poly=points.read();
-
- for(int i=0;i<pc;i++) {
-
- Vector2 points[2] ={ xform.xform(poly[i]),
- xform.xform(poly[(i+1)%pc]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
- if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_outline=j;
- closest_pos=cp;
- closest_idx=i;
- }
-
-
- }
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=node->get_navigation_polygon()->get_outline(closest_outline);
- PoolVector<Point2> poly = pre_move_edit;
- poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
- edited_point=closest_idx+1;
- edited_outline=closest_outline;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- node->get_navigation_polygon()->set_outline(closest_outline,poly);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
- int closest_outline=-1;
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
-
- for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) {
-
-
- PoolVector<Vector2> points=node->get_navigation_polygon()->get_outline(j);
-
- int pc=points.size();
- PoolVector<Vector2>::Read poly=points.read();
-
- for(int i=0;i<pc;i++) {
-
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_outline=j;
- closest_idx=i;
- }
- }
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=node->get_navigation_polygon()->get_outline(closest_outline);
- edited_point=closest_idx;
- edited_outline=closest_outline;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point!=-1) {
-
- //apply
-
- PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(edited_outline);
- ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
- poly.set(edited_point,edited_point_pos);
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"set_outline",edited_outline,poly);
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"set_outline",edited_outline,pre_move_edit);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- edited_point=-1;
- return true;
- }
- }
- } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
-
- int closest_outline=-1;
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
-
- for(int j=0;j<node->get_navigation_polygon()->get_outline_count();j++) {
-
-
- PoolVector<Vector2> points=node->get_navigation_polygon()->get_outline(j);
-
- int pc=points.size();
- PoolVector<Vector2>::Read poly=points.read();
-
- for(int i=0;i<pc;i++) {
-
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_outline=j;
- closest_idx=i;
- }
- }
- }
-
- if (closest_idx>=0) {
-
-
- PoolVector<Vector2> poly = node->get_navigation_polygon()->get_outline(closest_outline);
-
- if (poly.size()>3) {
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"set_outline",closest_outline,poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"set_outline",closest_outline,poly);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- } else {
-
- undo_redo->create_action(TTR("Remove Poly And Point"));
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"add_outline_at_index",poly,closest_outline);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"remove_outline",closest_outline);
- undo_redo->add_do_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_undo_method(node->get_navigation_polygon().ptr(),"make_polygons_from_outlines");
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- }
- return true;
- }
- }
-
-
-
- } break;
- }
-
-
-
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mm=p_event.mouse_motion;
-
- if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = Point2(mm.x,mm.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
-
- }
-
- } break;
- }
-
- return false;
-}
-void NavigationPolygonEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
- if (node->get_navigation_polygon().is_null())
- return;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
-
-
-
- for(int j=-1;j<node->get_navigation_polygon()->get_outline_count();j++) {
- Vector<Vector2> poly;
-
- if (wip_active && j==edited_outline) {
- poly=wip;
- } else {
- if (j==-1)
- continue;
- poly = Variant(node->get_navigation_polygon()->get_outline(j));
- }
-
- for(int i=0;i<poly.size();i++) {
-
-
- Vector2 p,p2;
- p = (j==edited_outline && i==edited_point) ? edited_point_pos : poly[i];
- if (j==edited_outline && ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point)))
- p2=edited_point_pos;
- else
- p2 = poly[(i+1)%poly.size()];
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col=Color(1,0.3,0.1,0.8);
- vpc->draw_line(point,next_point,col,2);
- vpc->draw_texture(handle,point-handle->get_size()*0.5);
- }
- }
-}
-
-
-
-void NavigationPolygonEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor=CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node=p_collision_polygon->cast_to<NavigationPolygonInstance>();
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
- wip.clear();
- wip_active=false;
- edited_point=-1;
- canvas_item_editor->get_viewport_control()->update();
-
- } else {
- node=NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
-
- }
-
-}
-
-void NavigationPolygonEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_menu_option"),&NavigationPolygonEditor::_menu_option);
- ClassDB::bind_method(_MD("_canvas_draw"),&NavigationPolygonEditor::_canvas_draw);
- ClassDB::bind_method(_MD("_node_removed"),&NavigationPolygonEditor::_node_removed);
- ClassDB::bind_method(_MD("_create_nav"),&NavigationPolygonEditor::_create_nav);
-
-}
-
-NavigationPolygonEditor::NavigationPolygonEditor(EditorNode *p_editor) {
- node=NULL;
- canvas_item_editor=NULL;
- editor=p_editor;
- undo_redo = editor->get_undo_redo();
-
- add_child( memnew( VSeparator ));
- button_create = memnew( ToolButton );
- add_child(button_create);
- button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
- button_create->set_tooltip(TTR("Create a new polygon from scratch."));
-
- button_edit = memnew( ToolButton );
- add_child(button_edit);
- button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
- button_edit->set_tooltip(TTR("Edit existing polygon:")+"\n"+TTR("LMB: Move Point.")+"\n"+TTR("Ctrl+LMB: Split Segment.")+"\n"+TTR("RMB: Erase Point."));
- create_nav = memnew( ConfirmationDialog );
- add_child(create_nav);
- create_nav->get_ok()->set_text(TTR("Create"));
-
-
- //add_constant_override("separation",0);
-
-#if 0
- options = memnew( MenuButton );
- add_child(options);
- options->set_area_as_parent_rect();
- options->set_text("Polygon");
- //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
- options->get_popup()->connect("id_pressed", this,"_menu_option");
-#endif
-
- mode = MODE_EDIT;
- wip_active=false;
- edited_outline=-1;
-
-}
-
-
-void NavigationPolygonEditorPlugin::edit(Object *p_object) {
-
- collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool NavigationPolygonEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("NavigationPolygonInstance");
-}
-
-void NavigationPolygonEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-
-}
-
-NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- collision_polygon_editor = memnew( NavigationPolygonEditor(p_node) );
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
-
-
-
-}
-
-
-NavigationPolygonEditorPlugin::~NavigationPolygonEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.h b/tools/editor/plugins/navigation_polygon_editor_plugin.h
deleted file mode 100644
index 50df4df744..0000000000
--- a/tools/editor/plugins/navigation_polygon_editor_plugin.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*************************************************************************/
-/* navigation_polygon_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 NAVIGATIONPOLYGONEDITORPLUGIN_H
-#define NAVIGATIONPOLYGONEDITORPLUGIN_H
-
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/2d/navigation_polygon.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/button_group.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class CanvasItemEditor;
-
-class NavigationPolygonEditor : public HBoxContainer {
-
- GDCLASS(NavigationPolygonEditor, HBoxContainer );
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
-
- };
-
- Mode mode;
-
- ToolButton *button_create;
- ToolButton *button_edit;
-
- ConfirmationDialog *create_nav;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
- NavigationPolygonInstance *node;
- MenuButton *options;
-
- int edited_outline;
- int edited_point;
- Vector2 edited_point_pos;
- PoolVector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
-
- void _wip_close();
- void _canvas_draw();
- void _create_nav();
-
- void _menu_option(int p_option);
-
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- bool forward_gui_input(const InputEvent& p_event);
- void edit(Node *p_collision_polygon);
- NavigationPolygonEditor(EditorNode *p_editor);
-};
-
-class NavigationPolygonEditorPlugin : public EditorPlugin {
-
- GDCLASS( NavigationPolygonEditorPlugin, EditorPlugin );
-
- NavigationPolygonEditor *collision_polygon_editor;
- EditorNode *editor;
-
-public:
-
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "NavigationPolygonInstance"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
- virtual void make_visible(bool p_visible);
-
- NavigationPolygonEditorPlugin(EditorNode *p_node);
- ~NavigationPolygonEditorPlugin();
-
-};
-
-
-#endif // NAVIGATIONPOLYGONEDITORPLUGIN_H
diff --git a/tools/editor/plugins/particles_2d_editor_plugin.cpp b/tools/editor/plugins/particles_2d_editor_plugin.cpp
deleted file mode 100644
index 20b1b9d1ca..0000000000
--- a/tools/editor/plugins/particles_2d_editor_plugin.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-/*************************************************************************/
-/* particles_2d_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "particles_2d_editor_plugin.h"
-
-#include "canvas_item_editor_plugin.h"
-#include "io/image_loader.h"
-#include "scene/gui/separator.h"
-
-void Particles2DEditorPlugin::edit(Object *p_object) {
-
- if (p_object) {
- particles=p_object->cast_to<Particles2D>();
- } else {
- particles=NULL;
- }
-}
-
-bool Particles2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Particles2D");
-}
-
-void Particles2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- toolbar->show();
- } else {
-
- toolbar->hide();
- }
-
-}
-
-void Particles2DEditorPlugin::_file_selected(const String& p_file) {
-
- print_line("file: "+p_file);
-
- int epc=epoints->get_value();
-
- Image img;
- Error err = ImageLoader::load_image(p_file,&img);
- ERR_EXPLAIN(TTR("Error loading image:")+" "+p_file);
- ERR_FAIL_COND(err!=OK);
-
- img.convert(Image::FORMAT_LA8);
- ERR_FAIL_COND(img.get_format()!=Image::FORMAT_LA8);
- Size2i s = Size2(img.get_width(),img.get_height());
- ERR_FAIL_COND(s.width==0 || s.height==0);
-
- PoolVector<uint8_t> data = img.get_data();
- PoolVector<uint8_t>::Read r = data.read();
-
- Vector<Point2i> valid_positions;
- valid_positions.resize(s.width*s.height);
- int vpc=0;
-
-
- for(int i=0;i<s.width*s.height;i++) {
-
- uint8_t a = r[i*2+1];
- if (a>128) {
- valid_positions[vpc++]=Point2i(i%s.width,i/s.width);
- }
- }
-
- valid_positions.resize(vpc);
-
- ERR_EXPLAIN(TTR("No pixels with transparency > 128 in image.."));
- ERR_FAIL_COND(valid_positions.size()==0);
-
- PoolVector<Point2> epoints;
- epoints.resize(epc);
- PoolVector<Point2>::Write w = epoints.write();
-
- Size2 extents = Size2(img.get_width()*0.5,img.get_height()*0.5);
-
- for(int i=0;i<epc;i++) {
-
- Point2 p = valid_positions[Math::rand()%vpc];
- p-=s/2;
- w[i]=p/extents;
- }
-
- w = PoolVector<Point2>::Write();
-
- undo_redo->create_action(TTR("Set Emission Mask"));
- undo_redo->add_do_method(particles,"set_emission_points",epoints);
- undo_redo->add_do_method(particles,"set_emission_half_extents",extents);
- undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points());
- undo_redo->add_undo_method(particles,"set_emission_half_extents",particles->get_emission_half_extents());
- undo_redo->commit_action();
-
-}
-
-void Particles2DEditorPlugin::_menu_callback(int p_idx) {
-
- switch(p_idx) {
- case MENU_LOAD_EMISSION_MASK: {
-
-
- file->popup_centered_ratio();
-
- } break;
- case MENU_CLEAR_EMISSION_MASK: {
-
- undo_redo->create_action(TTR("Clear Emission Mask"));
- undo_redo->add_do_method(particles,"set_emission_points",PoolVector<Vector2>());
- undo_redo->add_undo_method(particles,"set_emission_points",particles->get_emission_points());
- undo_redo->commit_action();
- } break;
- }
-
-}
-
-
-void Particles2DEditorPlugin::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- menu->get_popup()->connect("id_pressed",this,"_menu_callback");
- menu->set_icon(menu->get_popup()->get_icon("Particles2D","EditorIcons"));
- file->connect("file_selected",this,"_file_selected");
- }
-}
-
-void Particles2DEditorPlugin::_bind_methods() {
-
- ClassDB::bind_method(_MD("_menu_callback"),&Particles2DEditorPlugin::_menu_callback);
- ClassDB::bind_method(_MD("_file_selected"),&Particles2DEditorPlugin::_file_selected);
-}
-
-
-
-Particles2DEditorPlugin::Particles2DEditorPlugin(EditorNode *p_node) {
-
- particles=NULL;
- editor=p_node;
- undo_redo=editor->get_undo_redo();
-
- toolbar = memnew( HBoxContainer );
- add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, toolbar);
- toolbar->hide();
-
- toolbar->add_child( memnew( VSeparator ) );
-
- menu = memnew( MenuButton );
- menu->get_popup()->add_item(TTR("Load Emission Mask"),MENU_LOAD_EMISSION_MASK);
- menu->get_popup()->add_item(TTR("Clear Emission Mask"),MENU_CLEAR_EMISSION_MASK);
- menu->set_text("Particles");
- toolbar->add_child(menu);
-
- file = memnew( EditorFileDialog );
- List<String> ext;
- ImageLoader::get_recognized_extensions(&ext);
- for(List<String>::Element *E=ext.front();E;E=E->next()) {
- file->add_filter("*."+E->get()+"; "+E->get().to_upper());
- }
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- toolbar->add_child(file);
-
- epoints = memnew( SpinBox );
- epoints->set_min(1);
- epoints->set_max(8192);
- epoints->set_step(1);
- epoints->set_value(512);
- file->get_vbox()->add_margin_child(TTR("Generated Point Count:"),epoints);
-}
-
-Particles2DEditorPlugin::~Particles2DEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/particles_2d_editor_plugin.h b/tools/editor/plugins/particles_2d_editor_plugin.h
deleted file mode 100644
index c532a5fe73..0000000000
--- a/tools/editor/plugins/particles_2d_editor_plugin.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*************************************************************************/
-/* particles_2d_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PARTICLES_2D_EDITOR_PLUGIN_H
-#define PARTICLES_2D_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/2d/collision_polygon_2d.h"
-
-#include "scene/gui/box_container.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/2d/particles_2d.h"
-
-class Particles2DEditorPlugin : public EditorPlugin {
-
- GDCLASS( Particles2DEditorPlugin, EditorPlugin );
-
- enum {
-
- MENU_LOAD_EMISSION_MASK,
- MENU_CLEAR_EMISSION_MASK
- };
-
- Particles2D *particles;
-
- EditorFileDialog *file;
- EditorNode *editor;
-
- HBoxContainer *toolbar;
- MenuButton *menu;
-
- SpinBox *epoints;
-
- UndoRedo *undo_redo;
- void _file_selected(const String& p_file);
- void _menu_callback(int p_idx);
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
-
- virtual String get_name() const { return "Particles2D"; }
- 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);
-
- Particles2DEditorPlugin(EditorNode *p_node);
- ~Particles2DEditorPlugin();
-
-};
-
-
-#endif // PARTICLES_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/particles_editor_plugin.cpp b/tools/editor/plugins/particles_editor_plugin.cpp
deleted file mode 100644
index fd5ec5b5b9..0000000000
--- a/tools/editor/plugins/particles_editor_plugin.cpp
+++ /dev/null
@@ -1,461 +0,0 @@
-/*************************************************************************/
-/* particles_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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. */
-/*************************************************************************/
-
-#if 0
-#include "particles_editor_plugin.h"
-#include "io/resource_loader.h"
-#include "servers/visual/particle_system_sw.h"
-#include "tools/editor/plugins/spatial_editor_plugin.h"
-
-
-void ParticlesEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- }
-
-}
-
-
-void ParticlesEditor::_resource_seleted(const String& p_res) {
-
- //print_line("selected resource path: "+p_res);
-}
-
-void ParticlesEditor::_node_selected(const NodePath& p_path){
-
-
- Node *sel = get_node(p_path);
- if (!sel)
- return;
-
- VisualInstance *vi = sel->cast_to<VisualInstance>();
- if (!vi) {
-
- err_dialog->set_text(TTR("Node does not contain geometry."));
- err_dialog->popup_centered_minsize();
- return;
- }
-
- geometry = vi->get_faces(VisualInstance::FACES_SOLID);
-
- if (geometry.size()==0) {
-
- err_dialog->set_text(TTR("Node does not contain geometry (faces)."));
- err_dialog->popup_centered_minsize();
- return;
-
- }
-
- Transform geom_xform = node->get_global_transform().affine_inverse() * vi->get_global_transform();
-
- int gc = geometry.size();
- PoolVector<Face3>::Write w = geometry.write();
-
-
- for(int i=0;i<gc;i++) {
- for(int j=0;j<3;j++) {
- w[i].vertex[j] = geom_xform.xform( w[i].vertex[j] );
- }
- }
-
-
- w = PoolVector<Face3>::Write();
-
- emission_dialog->popup_centered(Size2(300,130));
-}
-
-
-/*
-
-void ParticlesEditor::_populate() {
-
- if(!node)
- return;
-
-
- if (node->get_particles().is_null())
- return;
-
- node->get_particles()->set_instance_count(populate_amount->get_text().to_int());
- node->populate_parent(populate_rotate_random->get_val(),populate_tilt_random->get_val(),populate_scale_random->get_text().to_double(),populate_scale->get_text().to_double());
-
-}
-*/
-
-void ParticlesEditor::_notification(int p_notification) {
-
- if (p_notification==NOTIFICATION_ENTER_TREE) {
- options->set_icon(options->get_popup()->get_icon("Particles","EditorIcons"));
-
- }
-}
-
-
-void ParticlesEditor::_menu_option(int p_option) {
-
-
- switch(p_option) {
-
- case MENU_OPTION_GENERATE_AABB: {
-
- Transform globalizer = node->get_global_transform();
- ParticleSystemSW pssw;
- for(int i=0;i<VS::PARTICLE_VAR_MAX;i++) {
-
- pssw.particle_vars[i]=node->get_variable((Particles::Variable)i);
- pssw.particle_randomness[i]=node->get_randomness((Particles::Variable)i);
- }
-
- pssw.emission_half_extents=node->get_emission_half_extents();
- pssw.emission_points=node->get_emission_points();
- pssw.emission_base_velocity=node->get_emission_base_velocity();
- pssw.amount=node->get_amount();
- pssw.gravity_normal=node->get_gravity_normal();
- pssw.emitting=true;
- pssw.height_from_velocity=node->has_height_from_velocity();
- pssw.color_phase_count=1;
-
-
- ParticleSystemProcessSW pp;
- float delta=0.01;
- float lifetime=pssw.particle_vars[VS::PARTICLE_LIFETIME];
-
-
- Transform localizer = globalizer.affine_inverse();
- AABB aabb;
- for(float t=0;t<lifetime;t+=delta) {
-
- pp.process(&pssw,globalizer,delta);
- for(int i=0;i<pp.particle_data.size();i++) {
-
- Vector3 p = localizer.xform(pp.particle_data[i].pos);
-
- if (t==0 && i==0)
- aabb.pos=p;
- else
- aabb.expand_to(p);
- }
- }
-
- aabb.grow_by( aabb.get_longest_axis_size()*0.2);
-
- node->set_visibility_aabb(aabb);
-
-
- } break;
- case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: {
-
-
- emission_file_dialog->popup_centered_ratio();
-
- } break;
-
- case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: {
-/*
- Node *root = get_scene()->get_root_node();
- ERR_FAIL_COND(!root);
- EditorNode *en = root->cast_to<EditorNode>();
- ERR_FAIL_COND(!en);
- Node * node = en->get_edited_scene();
-*/
- emission_tree_dialog->popup_centered_ratio();
-
- } break;
- }
-}
-
-
-void ParticlesEditor::edit(Particles *p_particles) {
-
- node=p_particles;
-
-}
-
-void ParticlesEditor::_generate_emission_points() {
-
- /// hacer codigo aca
- PoolVector<Vector3> points;
-
- if (emission_fill->get_selected()==0) {
-
- float area_accum=0;
- Map<float,int> triangle_area_map;
- print_line("geometry size: "+itos(geometry.size()));
-
- for(int i=0;i<geometry.size();i++) {
-
- float area = geometry[i].get_area();
- if (area<CMP_EPSILON)
- continue;
- triangle_area_map[area_accum]=i;
- area_accum+=area;
- }
-
- if (!triangle_area_map.size() || area_accum==0) {
-
- err_dialog->set_text(TTR("Faces contain no area!"));
- err_dialog->popup_centered_minsize();
- return;
- }
-
- int emissor_count=emission_amount->get_val();
-
- for(int i=0;i<emissor_count;i++) {
-
- float areapos = Math::random(0,area_accum);
-
- Map<float,int>::Element *E = triangle_area_map.find_closest(areapos);
- ERR_FAIL_COND(!E)
- int index = E->get();
- ERR_FAIL_INDEX(index,geometry.size());
-
- // ok FINALLY get face
- Face3 face = geometry[index];
- //now compute some position inside the face...
-
- Vector3 pos = face.get_random_point_inside();
-
- points.push_back(pos);
- }
- } else {
-
- int gcount = geometry.size();
-
- if (gcount==0) {
-
- err_dialog->set_text(TTR("No faces!"));
- err_dialog->popup_centered_minsize();
- return;
- }
-
- PoolVector<Face3>::Read r = geometry.read();
-
- AABB aabb;
-
- for(int i=0;i<gcount;i++) {
-
- for(int j=0;j<3;j++) {
-
- if (i==0 && j==0)
- aabb.pos=r[i].vertex[j];
- else
- aabb.expand_to(r[i].vertex[j]);
- }
- }
-
- int emissor_count=emission_amount->get_val();
-
- for(int i=0;i<emissor_count;i++) {
-
- int attempts=5;
-
- for(int j=0;j<attempts;j++) {
-
- Vector3 dir;
- dir[Math::rand()%3]=1.0;
- Vector3 ofs = Vector3(1,1,1)-dir;
- ofs=(Vector3(1,1,1)-dir)*Vector3(Math::randf(),Math::randf(),Math::randf())*aabb.size;
- ofs+=aabb.pos;
-
- Vector3 ofsv = ofs + aabb.size * dir;
-
- //space it a little
- ofs -= dir;
- ofsv += dir;
-
- float max=-1e7,min=1e7;
-
- for(int k=0;k<gcount;k++) {
-
- const Face3& f3 = r[k];
-
- Vector3 res;
- if (f3.intersects_segment(ofs,ofsv,&res)) {
-
- res-=ofs;
- float d = dir.dot(res);
-
- if (d<min)
- min=d;
- if (d>max)
- max=d;
-
- }
- }
-
-
- if (max<min)
- continue; //lost attempt
-
- float val = min + (max-min)*Math::randf();
-
- Vector3 point = ofs + dir * val;
-
- points.push_back(point);
- break;
- }
- }
- }
-
- //print_line("point count: "+itos(points.size()));
- node->set_emission_points(points);
-
-}
-
-void ParticlesEditor::_bind_methods() {
-
- ClassDB::bind_method("_menu_option",&ParticlesEditor::_menu_option);
- ClassDB::bind_method("_resource_seleted",&ParticlesEditor::_resource_seleted);
- ClassDB::bind_method("_node_selected",&ParticlesEditor::_node_selected);
- ClassDB::bind_method("_generate_emission_points",&ParticlesEditor::_generate_emission_points);
-
- //ClassDB::bind_method("_populate",&ParticlesEditor::_populate);
-
-}
-
-ParticlesEditor::ParticlesEditor() {
-
- particles_editor_hb = memnew ( HBoxContainer );
- SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb);
- options = memnew( MenuButton );
- particles_editor_hb->add_child(options);
- particles_editor_hb->hide();
-
- options->set_text("Particles");
- options->get_popup()->add_item(TTR("Generate AABB"),MENU_OPTION_GENERATE_AABB);
- options->get_popup()->add_separator();
- options->get_popup()->add_item(TTR("Create Emitter From Mesh"),MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH);
- options->get_popup()->add_item(TTR("Create Emitter From Node"),MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE);
- options->get_popup()->add_item(TTR("Clear Emitter"),MENU_OPTION_CLEAR_EMISSION_VOLUME);
-
- options->get_popup()->connect("id_pressed", this,"_menu_option");
-
- emission_dialog = memnew( ConfirmationDialog );
- emission_dialog->set_title(TTR("Create Emitter"));
- add_child(emission_dialog);
- Label *l = memnew(Label);
- l->set_pos(Point2(5,5));
- l->set_text(TTR("Emission Positions:"));
- emission_dialog->add_child(l);
-
-
- emission_amount = memnew( SpinBox );
- emission_amount->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- emission_amount->set_begin( Point2(20,23));
- emission_amount->set_end( Point2(5,25));
- emission_amount->set_min(1);
- emission_amount->set_max(65536);
- emission_amount->set_val(512);
- emission_dialog->add_child(emission_amount);
- emission_dialog->get_ok()->set_text(TTR("Create"));
- emission_dialog->connect("confirmed",this,"_generate_emission_points");
-
- l = memnew(Label);
- l->set_pos(Point2(5,50));
- l->set_text(TTR("Emission Fill:"));
- emission_dialog->add_child(l);
-
- emission_fill = memnew( OptionButton );
- emission_fill->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- emission_fill->set_begin( Point2(20,70));
- emission_fill->set_end( Point2(5,75));
- emission_fill->add_item(TTR("Surface"));
- emission_fill->add_item(TTR("Volume"));
- emission_dialog->add_child(emission_fill);
-
- err_dialog = memnew( ConfirmationDialog );
- //err_dialog->get_cancel()->hide();
- add_child(err_dialog);
-
-
- emission_file_dialog = memnew( EditorFileDialog );
- add_child(emission_file_dialog);
- emission_file_dialog->connect("file_selected",this,"_resource_seleted");
- emission_tree_dialog = memnew( SceneTreeDialog );
- add_child(emission_tree_dialog);
- emission_tree_dialog->connect("selected",this,"_node_selected");
-
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("Mesh",&extensions);
-
- emission_file_dialog->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- emission_file_dialog->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
- emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
-
- //options->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
- //options->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
-
-}
-
-
-void ParticlesEditorPlugin::edit(Object *p_object) {
-
- particles_editor->edit(p_object->cast_to<Particles>());
-}
-
-bool ParticlesEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("Particles");
-}
-
-void ParticlesEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- particles_editor->show();
- particles_editor->particles_editor_hb->show();
- } else {
- particles_editor->particles_editor_hb->hide();
- particles_editor->hide();
- particles_editor->edit(NULL);
- }
-
-}
-
-ParticlesEditorPlugin::ParticlesEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- particles_editor = memnew( ParticlesEditor );
- editor->get_viewport()->add_child(particles_editor);
-
- particles_editor->hide();
-}
-
-
-ParticlesEditorPlugin::~ParticlesEditorPlugin()
-{
-}
-
-
-#endif
diff --git a/tools/editor/plugins/particles_editor_plugin.h b/tools/editor/plugins/particles_editor_plugin.h
deleted file mode 100644
index c32fbe5ada..0000000000
--- a/tools/editor/plugins/particles_editor_plugin.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*************************************************************************/
-/* particles_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PARTICLES_EDITOR_PLUGIN_H
-#define PARTICLES_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/particles.h"
-#include "scene/gui/spin_box.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-#if 0
-class ParticlesEditor : public Control {
-
- GDCLASS(ParticlesEditor, Control );
-
- Panel *panel;
- MenuButton *options;
- HBoxContainer *particles_editor_hb;
- Particles *node;
-
-
- EditorFileDialog *emission_file_dialog;
- SceneTreeDialog *emission_tree_dialog;
-
- ConfirmationDialog *err_dialog;
-
- ConfirmationDialog *emission_dialog;
- SpinBox *emission_amount;
- OptionButton *emission_fill;
-
-
-
-
- enum Menu {
-
- MENU_OPTION_GENERATE_AABB,
- MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE,
- MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH,
- MENU_OPTION_CLEAR_EMISSION_VOLUME,
-
- };
-
- PoolVector<Face3> geometry;
-
- void _generate_emission_points();
- void _resource_seleted(const String& p_res);
- void _node_selected(const NodePath& p_path);
-
- void _menu_option(int);
-
- void _populate();
-
-friend class ParticlesEditorPlugin;
-
-protected:
-
- void _notification(int p_notification);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- void edit(Particles *p_particles);
- ParticlesEditor();
-};
-
-class ParticlesEditorPlugin : public EditorPlugin {
-
- GDCLASS( ParticlesEditorPlugin, EditorPlugin );
-
- ParticlesEditor *particles_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "Particles"; }
- 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);
-
- ParticlesEditorPlugin(EditorNode *p_node);
- ~ParticlesEditorPlugin();
-
-};
-
-#endif // PARTICLES_EDITOR_PLUGIN_H
-#endif
diff --git a/tools/editor/plugins/path_2d_editor_plugin.cpp b/tools/editor/plugins/path_2d_editor_plugin.cpp
deleted file mode 100644
index 8e475e56f7..0000000000
--- a/tools/editor/plugins/path_2d_editor_plugin.cpp
+++ /dev/null
@@ -1,718 +0,0 @@
-/*************************************************************************/
-/* path_2d_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "path_2d_editor_plugin.h"
-
-#include "canvas_item_editor_plugin.h"
-#include "os/file_access.h"
-#include "tools/editor/editor_settings.h"
-#include "os/keyboard.h"
-void Path2DEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
- //button_create->set_icon( get_icon("Edit","EditorIcons"));
- //button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
- //set_pressed_button(button_edit);
- //button_edit->set_pressed(true);
-
-
- } break;
- case NOTIFICATION_FIXED_PROCESS: {
-
-
- } break;
- }
-
-}
-void Path2DEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- }
-
-}
-
-
-bool Path2DEditor::forward_gui_input(const InputEvent& p_event) {
-
- if (!node)
- return false;
-
- if (!node->is_visible_in_tree())
- return false;
-
- if (!node->get_curve().is_valid())
- return false;
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = Point2(mb.x,mb.y);
- Vector2 cpoint = !mb.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
- : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
-
- //first check if a point is to be added (segment split)
- real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
-
-
-
- // Test move point!!
-
- if ( mb.pressed && action==ACTION_NONE ) {
-
- Ref<Curve2D> curve = node->get_curve();
-
- for(int i=0;i<curve->get_point_count();i++) {
-
- bool pointunder=false;
-
- {
- Point2 p = xform.xform( curve->get_point_pos(i) );
- if (gpoint.distance_to(p) < grab_treshold ) {
-
- if (mb.button_index==BUTTON_LEFT && !mb.mod.shift && mode==MODE_EDIT) {
-
- action=ACTION_MOVING_POINT;
- action_point=i;
- moving_from=curve->get_point_pos(i);
- moving_screen_from=gpoint;
- return true;
- } else if ((mb.button_index==BUTTON_RIGHT && mode==MODE_EDIT) || (mb.button_index==BUTTON_LEFT && mode==MODE_DELETE)) {
-
- undo_redo->create_action(TTR("Remove Point from Curve"));
- undo_redo->add_do_method(curve.ptr(),"remove_point",i);
- undo_redo->add_undo_method(curve.ptr(),"add_point",curve->get_point_pos(i),curve->get_point_in(i),curve->get_point_out(i),i);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- } else
- pointunder=true;
- }
- }
-
- if (mb.button_index==BUTTON_LEFT && i<(curve->get_point_count()-1)) {
- Point2 p = xform.xform( curve->get_point_pos(i)+curve->get_point_out(i) );
- if (gpoint.distance_to(p) < grab_treshold && (mode == MODE_EDIT || mode==MODE_EDIT_CURVE) ) {
-
- action=ACTION_MOVING_OUT;
- action_point=i;
- moving_from=curve->get_point_out(i);
- moving_screen_from=gpoint;
- return true;
- }
- }
-
- if (mb.button_index==BUTTON_LEFT && i>0) {
- Point2 p = xform.xform( curve->get_point_pos(i)+curve->get_point_in(i) );
- if (gpoint.distance_to(p) < grab_treshold && (mode == MODE_EDIT || mode==MODE_EDIT_CURVE)) {
-
- action=ACTION_MOVING_IN;
- action_point=i;
- moving_from=curve->get_point_in(i);
- moving_screen_from=gpoint;
- return true;
- }
- }
-
- if (pointunder)
- return true;
-
- }
-
- }
-
- // Test add point in empty space!
-
- if ( mb.pressed && mb.button_index==BUTTON_LEFT && ((mb.mod.command && mode == MODE_EDIT) || mode == MODE_CREATE)) {
-
- Ref<Curve2D> curve = node->get_curve();
-
- undo_redo->create_action(TTR("Add Point to Curve"));
- undo_redo->add_do_method(curve.ptr(),"add_point",cpoint);
- undo_redo->add_undo_method(curve.ptr(),"remove_point",curve->get_point_count());
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- action=ACTION_MOVING_POINT;
- action_point=curve->get_point_count()-1;
- moving_from=curve->get_point_pos(action_point);
- moving_screen_from=gpoint;
-
- canvas_item_editor->get_viewport_control()->update();
-
- return true;
- }
-
- if ( !mb.pressed && mb.button_index==BUTTON_LEFT && action!=ACTION_NONE) {
-
-
- Ref<Curve2D> curve = node->get_curve();
-
- Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
- switch(action) {
-
- case ACTION_MOVING_POINT: {
-
-
- undo_redo->create_action(TTR("Move Point in Curve"));
- undo_redo->add_do_method(curve.ptr(),"set_point_pos",action_point,cpoint);
- undo_redo->add_undo_method(curve.ptr(),"set_point_pos",action_point,moving_from);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- } break;
- case ACTION_MOVING_IN: {
-
- undo_redo->create_action(TTR("Move In-Control in Curve"));
- undo_redo->add_do_method(curve.ptr(),"set_point_in",action_point,new_pos);
- undo_redo->add_undo_method(curve.ptr(),"set_point_in",action_point,moving_from);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- } break;
- case ACTION_MOVING_OUT: {
-
- undo_redo->create_action(TTR("Move Out-Control in Curve"));
- undo_redo->add_do_method(curve.ptr(),"set_point_out",action_point,new_pos);
- undo_redo->add_undo_method(curve.ptr(),"set_point_out",action_point,moving_from);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- } break;
-
- }
-
- action=ACTION_NONE;
-
- return true;
- }
-
-
-#if 0
- switch(mode) {
-
-
- case MODE_CREATE: {
-
- if (mb.button_index==BUTTON_LEFT && mb.pressed) {
-
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back( canvas_item_editor->snap_point(cpoint) );
- wip_active=true;
- edited_point_pos=canvas_item_editor->snap_point(cpoint);
- canvas_item_editor->update();
- edited_point=1;
- return true;
- } else {
-
- if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back( canvas_item_editor->snap_point(cpoint) );
- edited_point=wip.size();
- canvas_item_editor->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
- _wip_close();
- }
-
-
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb.button_index==BUTTON_LEFT) {
- if (mb.pressed) {
-
- if (mb.mod.control) {
-
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 points[2] ={ xform.xform(poly[i]),
- xform.xform(poly[(i+1)%poly.size()]) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
- if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)));
- edited_point=closest_idx+1;
- edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos));
- node->set_polygon(poly);
- canvas_item_editor->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- edited_point=closest_idx;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->update();
- return true;
- }
- }
- } else {
-
- if (edited_point!=-1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
- poly[edited_point]=edited_point_pos;
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- edited_point=-1;
- return true;
- }
- }
- } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
-
-
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]);
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- }
-
-
-
- } break;
- }
-
-
-#endif
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mm=p_event.mouse_motion;
-
-
- if ( action!=ACTION_NONE) {
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Vector2 gpoint = Point2(mm.x,mm.y);
- Vector2 cpoint = !mm.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
- : node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
-
- Ref<Curve2D> curve = node->get_curve();
-
- Vector2 new_pos = moving_from + xform.affine_inverse().basis_xform(gpoint - moving_screen_from);
-
- switch(action) {
-
- case ACTION_MOVING_POINT: {
-
- curve->set_point_pos(action_point,cpoint);
- } break;
- case ACTION_MOVING_IN: {
-
- curve->set_point_in(action_point,new_pos);
-
- } break;
- case ACTION_MOVING_OUT: {
-
- curve->set_point_out(action_point,new_pos);
-
- } break;
- }
-
-
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
-
-#if 0
- if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
-
-
- Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
- Vector2 gpoint = Point2(mm.x,mm.y);
- edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint));
- canvas_item_editor->update();
-
- }
-#endif
- } break;
- }
-
- return false;
-}
-void Path2DEditor::_canvas_draw() {
-
- if (!node)
- return ;
-
- if (!node->is_visible_in_tree())
- return;
-
- if (!node->get_curve().is_valid())
- return ;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
- Size2 handle_size = handle->get_size();
-
- Ref<Curve2D> curve = node->get_curve();
-
- int len = curve->get_point_count();
- Control *vpc = canvas_item_editor->get_viewport_control();
-
-
- for(int i=0;i<len;i++) {
-
-
- Vector2 point = xform.xform(curve->get_point_pos(i));
- vpc->draw_texture_rect(handle,Rect2(point-handle_size*0.5,handle_size),false,Color(1,1,1,1));
-
- if (i<len-1) {
- Vector2 pointout = xform.xform(curve->get_point_pos(i)+curve->get_point_out(i));
- vpc->draw_line(point,pointout,Color(0.5,0.5,1.0,0.8),1.0);
- vpc->draw_texture_rect(handle, Rect2(pointout-handle_size*0.5,handle_size),false,Color(1,0.5,1,0.3));
- }
-
- if (i>0) {
- Vector2 pointin = xform.xform(curve->get_point_pos(i)+curve->get_point_in(i));
- vpc->draw_line(point,pointin,Color(0.5,0.5,1.0,0.8),1.0);
- vpc->draw_texture_rect(handle, Rect2(pointin-handle_size*0.5,handle_size),false,Color(1,0.5,1,0.3));
- }
-
- }
-
-}
-
-void Path2DEditor::_node_visibility_changed() {
- if (!node)
- return;
-
- canvas_item_editor->get_viewport_control()->update();
-}
-
-void Path2DEditor::edit(Node *p_path2d) {
-
- if (!canvas_item_editor) {
- canvas_item_editor=CanvasItemEditor::get_singleton();
- }
-
- if (p_path2d) {
-
- node=p_path2d->cast_to<Path2D>();
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
- 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"))
- canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
-
- // node may have been deleted at this point
- if (node && node->is_connected("visibility_changed", this, "_node_visibility_changed"))
- node->disconnect("visibility_changed", this, "_node_visibility_changed");
- node=NULL;
- }
-
-}
-
-void Path2DEditor::_bind_methods() {
-
- //ClassDB::bind_method(_MD("_menu_option"),&Path2DEditor::_menu_option);
- ClassDB::bind_method(_MD("_canvas_draw"),&Path2DEditor::_canvas_draw);
- ClassDB::bind_method(_MD("_node_visibility_changed"),&Path2DEditor::_node_visibility_changed);
- ClassDB::bind_method(_MD("_mode_selected"),&Path2DEditor::_mode_selected);
-}
-
-void Path2DEditor::_mode_selected(int p_mode) {
-
- if (p_mode==MODE_CREATE) {
-
- curve_create->set_pressed(true);
- curve_edit->set_pressed(false);
- curve_edit_curve->set_pressed(false);
- curve_del->set_pressed(false);
- } else if (p_mode==MODE_EDIT) {
-
- curve_create->set_pressed(false);
- curve_edit->set_pressed(true);
- curve_edit_curve->set_pressed(false);
- curve_del->set_pressed(false);
- } else if (p_mode==MODE_EDIT_CURVE) {
-
- curve_create->set_pressed(false);
- curve_edit->set_pressed(false);
- curve_edit_curve->set_pressed(true);
- curve_del->set_pressed(false);
- } else if (p_mode==MODE_DELETE) {
-
- curve_create->set_pressed(false);
- curve_edit->set_pressed(false);
- curve_edit_curve->set_pressed(false);
- curve_del->set_pressed(true);
- } else if (p_mode==ACTION_CLOSE) {
-
- //?
-
- if (!node->get_curve().is_valid())
- return ;
- if (node->get_curve()->get_point_count()<3)
- return;
-
- Vector2 begin = node->get_curve()->get_point_pos(0);
- Vector2 end = node->get_curve()->get_point_pos( node->get_curve()->get_point_count() -1 );
- if (begin.distance_to(end)<CMP_EPSILON)
- return;
-
- undo_redo->create_action(TTR("Remove Point from Curve"));
- undo_redo->add_do_method(node->get_curve().ptr(),"add_point",begin);
- undo_redo->add_undo_method(node->get_curve().ptr(),"remove_point",node->get_curve()->get_point_count());
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return;
- }
-
- mode=Mode(p_mode);
-
-}
-
-Path2DEditor::Path2DEditor(EditorNode *p_editor) {
-
- canvas_item_editor=NULL;
- editor=p_editor;
- undo_redo = editor->get_undo_redo();
-
- mode=MODE_EDIT;
-
- action=ACTION_NONE;
-#if 0
- options = memnew( MenuButton );
- add_child(options);
- options->set_area_as_parent_rect();
- options->set_text("Polygon");
- //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
- options->get_popup()->connect("id_pressed", this,"_menu_option");
-#endif
-
- base_hb = memnew( HBoxContainer );
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(base_hb);
-
- sep = memnew( VSeparator);
- base_hb->add_child(sep);
- curve_edit = memnew( ToolButton );
- curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit","EditorIcons"));
- curve_edit->set_toggle_mode(true);
- curve_edit->set_focus_mode(Control::FOCUS_NONE);
- curve_edit->set_tooltip(TTR("Select Points")+"\n"+TTR("Shift+Drag: Select Control Points")+"\n"+keycode_get_string(KEY_MASK_CMD)+TTR("Click: Add Point")+"\n"+TTR("Right Click: Delete Point"));
- curve_edit->connect("pressed",this,"_mode_selected",varray(MODE_EDIT));
- base_hb->add_child(curve_edit);
- curve_edit_curve = memnew( ToolButton );
- curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCurve","EditorIcons"));
- curve_edit_curve->set_toggle_mode(true);
- curve_edit_curve->set_focus_mode(Control::FOCUS_NONE);
- curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)"));
- curve_edit_curve->connect("pressed",this,"_mode_selected",varray(MODE_EDIT_CURVE));
- base_hb->add_child(curve_edit_curve);
- curve_create = memnew( ToolButton );
- curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate","EditorIcons"));
- curve_create->set_toggle_mode(true);
- curve_create->set_focus_mode(Control::FOCUS_NONE);
- curve_create->set_tooltip(TTR("Add Point (in empty space)")+"\n"+TTR("Split Segment (in curve)"));
- curve_create->connect("pressed",this,"_mode_selected",varray(MODE_CREATE));
- base_hb->add_child(curve_create);
- curve_del = memnew( ToolButton );
- curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete","EditorIcons"));
- curve_del->set_toggle_mode(true);
- curve_del->set_focus_mode(Control::FOCUS_NONE);
- curve_del->set_tooltip(TTR("Delete Point"));
- curve_del->connect("pressed",this,"_mode_selected",varray(MODE_DELETE));
- base_hb->add_child(curve_del);
- curve_close = memnew( ToolButton );
- curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveClose","EditorIcons"));
- curve_close->set_focus_mode(Control::FOCUS_NONE);
- curve_close->set_tooltip(TTR("Close Curve"));
- curve_close->connect("pressed",this,"_mode_selected",varray(ACTION_CLOSE));
- base_hb->add_child(curve_close);
- base_hb->hide();
-
-
-
- curve_edit->set_pressed(true);
-
-
-}
-
-
-void Path2DEditorPlugin::edit(Object *p_object) {
-
- path2d_editor->edit(p_object->cast_to<Node>());
-}
-
-bool Path2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Path2D");
-}
-
-void Path2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- path2d_editor->show();
- path2d_editor->base_hb->show();
-
- } else {
-
- path2d_editor->hide();
- path2d_editor->base_hb->hide();
- path2d_editor->edit(NULL);
- }
-
-}
-
-Path2DEditorPlugin::Path2DEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- path2d_editor = memnew( Path2DEditor(p_node) );
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(path2d_editor);
- path2d_editor->hide();
-
-
-}
-
-
-Path2DEditorPlugin::~Path2DEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/path_2d_editor_plugin.h b/tools/editor/plugins/path_2d_editor_plugin.h
deleted file mode 100644
index aa940e4edf..0000000000
--- a/tools/editor/plugins/path_2d_editor_plugin.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*************************************************************************/
-/* path_2d_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PATH_2D_EDITOR_PLUGIN_H
-#define PATH_2D_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/2d/path_2d.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/button_group.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class CanvasItemEditor;
-
-class Path2DEditor : public HBoxContainer {
-
- GDCLASS(Path2DEditor, HBoxContainer);
-
- UndoRedo *undo_redo;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
- Path2D *node;
-
- HBoxContainer *base_hb;
- Separator *sep;
-
- enum Mode {
- MODE_CREATE,
- MODE_EDIT,
- MODE_EDIT_CURVE,
- MODE_DELETE,
- ACTION_CLOSE
- };
-
- Mode mode;
- ToolButton *curve_create;
- ToolButton *curve_edit;
- ToolButton *curve_edit_curve;
- ToolButton *curve_del;
- ToolButton *curve_close;
-
- enum Action {
-
- ACTION_NONE,
- ACTION_MOVING_POINT,
- ACTION_MOVING_IN,
- ACTION_MOVING_OUT,
- };
-
-
- Action action;
- int action_point;
- Point2 moving_from;
- Point2 moving_screen_from;
-
- void _mode_selected(int p_mode);
-
- void _canvas_draw();
- void _node_visibility_changed();
-friend class Path2DEditorPlugin;
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- bool forward_gui_input(const InputEvent& p_event);
- void edit(Node *p_path2d);
- Path2DEditor(EditorNode *p_editor);
-};
-
-class Path2DEditorPlugin : public EditorPlugin {
-
- GDCLASS( Path2DEditorPlugin, EditorPlugin );
-
- Path2DEditor *path2d_editor;
- EditorNode *editor;
-
-public:
-
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return path2d_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "Path2D"; }
- 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);
-
- Path2DEditorPlugin(EditorNode *p_node);
- ~Path2DEditorPlugin();
-
-};
-
-
-
-#endif // PATH_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/path_editor_plugin.cpp b/tools/editor/plugins/path_editor_plugin.cpp
deleted file mode 100644
index 2e148d6486..0000000000
--- a/tools/editor/plugins/path_editor_plugin.cpp
+++ /dev/null
@@ -1,604 +0,0 @@
-/*************************************************************************/
-/* path_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "path_editor_plugin.h"
-
-#include "spatial_editor_plugin.h"
-#include "scene/resources/curve.h"
-#include "os/keyboard.h"
-
-#if 0
-String PathSpatialGizmo::get_handle_name(int p_idx) const {
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return "";
-
- if (p_idx<c->get_point_count()) {
-
- return TTR("Curve Point #")+itos(p_idx);
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
- String n = TTR("Curve Point #")+itos(idx);
- if (t==0)
- n+=" In";
- else
- n+=" Out";
-
- return n;
-
-
-}
-Variant PathSpatialGizmo::get_handle_value(int p_idx) const{
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return Variant();
-
- if (p_idx<c->get_point_count()) {
-
- original=c->get_point_pos(p_idx);
- return original;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 ofs;
- if (t==0)
- ofs=c->get_point_in(idx);
- else
- ofs= c->get_point_out(idx);
-
- original=ofs+c->get_point_pos(idx);
-
- return ofs;
-
-}
-void PathSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- Transform gt = path->get_global_transform();
- Transform gi = gt.affine_inverse();
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- if (p_idx<c->get_point_count()) {
-
- Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
-
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- if(SpatialEditor::get_singleton()->is_snap_enabled())
- {
- float snap = SpatialEditor::get_singleton()->get_translate_snap();
- inters.snap(snap);
- }
-
- Vector3 local = gi.xform(inters);
- c->set_point_pos(p_idx,local);
- }
-
- return;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 base = c->get_point_pos(idx);
-
- Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
-
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- Vector3 local = gi.xform(inters)-base;
- if (t==0) {
- c->set_point_in(idx,local);
- } else {
- c->set_point_out(idx,local);
- }
- }
-
-}
-
-void PathSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
-
- if (p_idx<c->get_point_count()) {
-
- if (p_cancel) {
-
- c->set_point_pos(p_idx,p_restore);
- return;
- }
- ur->create_action(TTR("Set Curve Point Pos"));
- ur->add_do_method(c.ptr(),"set_point_pos",p_idx,c->get_point_pos(p_idx));
- ur->add_undo_method(c.ptr(),"set_point_pos",p_idx,p_restore);
- ur->commit_action();
-
- return;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 ofs;
-
- if (p_cancel) {
-
-
-
- return;
- }
-
-
-
- if (t==0) {
-
- if (p_cancel) {
-
- c->set_point_in(p_idx,p_restore);
- return;
- }
- ur->create_action(TTR("Set Curve In Pos"));
- ur->add_do_method(c.ptr(),"set_point_in",idx,c->get_point_in(idx));
- ur->add_undo_method(c.ptr(),"set_point_in",idx,p_restore);
- ur->commit_action();
-
-
- } else {
- if (p_cancel) {
-
- c->set_point_out(idx,p_restore);
- return;
- }
- ur->create_action(TTR("Set Curve Out Pos"));
- ur->add_do_method(c.ptr(),"set_point_out",idx,c->get_point_out(idx));
- ur->add_undo_method(c.ptr(),"set_point_out",idx,p_restore);
- ur->commit_action();
-
- }
-
-}
-
-
-void PathSpatialGizmo::redraw(){
-
- clear();
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- Vector3Array v3a=c->tesselate();
- //Vector3Array v3a=c->get_baked_points();
-
- int v3s = v3a.size();
- if (v3s==0)
- return;
- Vector<Vector3> v3p;
- Vector3Array::Read r = v3a.read();
-
- for(int i=0;i<v3s-1;i++) {
-
- v3p.push_back(r[i]);
- v3p.push_back(r[i+1]);
- //v3p.push_back(r[i]);
- //v3p.push_back(r[i]+Vector3(0,0.2,0));
- }
-
- add_lines(v3p,PathEditorPlugin::singleton->path_material);
- add_collision_segments(v3p);
-
- if (PathEditorPlugin::singleton->get_edited_path()==path) {
- v3p.clear();
- Vector<Vector3> handles;
- Vector<Vector3> sec_handles;
-
- for(int i=0;i<c->get_point_count();i++) {
-
- Vector3 p = c->get_point_pos(i);
- handles.push_back(p);
- if (i>0) {
- v3p.push_back(p);
- v3p.push_back(p+c->get_point_in(i));
- sec_handles.push_back(p+c->get_point_in(i));
- }
-
- if (i<c->get_point_count()-1) {
- v3p.push_back(p);
- v3p.push_back(p+c->get_point_out(i));
- sec_handles.push_back(p+c->get_point_out(i));
- }
- }
-
- add_lines(v3p,PathEditorPlugin::singleton->path_thin_material);
- add_handles(handles);
- add_handles(sec_handles,false,true);
- }
-
-}
-
-PathSpatialGizmo::PathSpatialGizmo(Path* p_path){
-
- path=p_path;
- set_spatial_node(p_path);
-
-
-
-}
-
-Ref<SpatialEditorGizmo> PathEditorPlugin::create_spatial_gizmo(Spatial* p_spatial) {
-
-
- if (p_spatial->cast_to<Path>()) {
-
- return memnew( PathSpatialGizmo(p_spatial->cast_to<Path>()));
- }
-
- return Ref<SpatialEditorGizmo>();
-}
-
-bool PathEditorPlugin::forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event) {
-
- if (!path)
- return false;
- Ref<Curve3D> c=path->get_curve();
- if (c.is_null())
- return false;
- Transform gt = path->get_global_transform();
- Transform it = gt.affine_inverse();
-
- static const int click_dist = 10; //should make global
-
-
- if (p_event.type==InputEvent::MOUSE_BUTTON) {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
- Point2 mbpos(mb.x,mb.y);
-
- if (mb.pressed && mb.button_index==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) {
- //click into curve, break it down
- Vector3Array v3a = c->tesselate();
- int idx=0;
- int rc=v3a.size();
- int closest_seg=-1;
- Vector3 closest_seg_point;
- float closest_d=1e20;
-
- if (rc>=2) {
- Vector3Array::Read r = v3a.read();
-
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos)<click_dist)
- return false; //nope, existing
-
-
- for(int i=0;i<c->get_point_count()-1;i++) {
- //find the offset and point index of the place to break up
- int j=idx;
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(i+1))).distance_to(mbpos)<click_dist)
- return false; //nope, existing
-
-
- while(j<rc && c->get_point_pos(i+1)!=r[j]) {
-
- Vector3 from =r[j];
- Vector3 to =r[j+1];
- real_t cdist = from.distance_to(to);
- from=gt.xform(from);
- to=gt.xform(to);
- if (cdist>0) {
- Vector2 s[2];
- s[0] = p_camera->unproject_position(from);
- s[1] = p_camera->unproject_position(to);
- Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos,s);
- float d = inters.distance_to(mbpos);
-
- if (d<10 && d<closest_d) {
-
-
- closest_d=d;
- closest_seg=i;
- Vector3 ray_from=p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(ray_from,ray_from+ray_dir*4096,from,to,ra,rb);
-
- closest_seg_point=it.xform(rb);
- }
-
- }
- j++;
-
- }
- if (idx==j)
- idx++; //force next
- else
- idx=j; //swap
-
-
- if (j==rc)
- break;
- }
- }
-
- UndoRedo *ur = editor->get_undo_redo();
- if (closest_seg!=-1) {
- //subdivide
-
- ur->create_action(TTR("Split Path"));
- ur->add_do_method(c.ptr(),"add_point",closest_seg_point,Vector3(),Vector3(),closest_seg+1);
- ur->add_undo_method(c.ptr(),"remove_point",closest_seg+1);
- ur->commit_action();
- return true;
-
- } else {
-
- Vector3 org;
- if (c->get_point_count()==0)
- org=path->get_transform().get_origin();
- else
- org=gt.xform(c->get_point_pos(c->get_point_count()));
- Plane p(org,p_camera->get_transform().basis.get_axis(2));
- Vector3 ray_from=p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
-
- Vector3 inters;
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- ur->create_action(TTR("Add Point to Curve"));
- ur->add_do_method(c.ptr(),"add_point",it.xform(inters),Vector3(),Vector3(),-1);
- ur->add_undo_method(c.ptr(),"remove_point",c->get_point_count());
- ur->commit_action();
- return true;
- }
-
- //add new at pos
- }
-
- } else if (mb.pressed && ((mb.button_index==BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index==BUTTON_RIGHT && curve_edit->is_pressed()))) {
-
- int erase_idx=-1;
- for(int i=0;i<c->get_point_count();i++) {
- //find the offset and point index of the place to break up
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos)<click_dist) {
-
- erase_idx=i;
- break;
- }
- }
-
- if (erase_idx!=-1) {
-
- UndoRedo *ur = editor->get_undo_redo();
- ur->create_action(TTR("Remove Path Point"));
- ur->add_do_method(c.ptr(),"remove_point",erase_idx);
- ur->add_undo_method(c.ptr(),"add_point",c->get_point_pos(erase_idx),c->get_point_in(erase_idx),c->get_point_out(erase_idx),erase_idx);
- ur->commit_action();
- return true;
- }
- }
-
- }
-
- return false;
-}
-
-
-void PathEditorPlugin::edit(Object *p_object) {
-
- if (p_object) {
- path=p_object->cast_to<Path>();
- if (path) {
-
- if (path->get_curve().is_valid()) {
- path->get_curve()->emit_signal("changed");
- }
- }
- } else {
- Path *pre=path;
- path=NULL;
- if (pre) {
- pre->get_curve()->emit_signal("changed");
- }
- }
- //collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool PathEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("Path");
-}
-
-void PathEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- curve_create->show();
- curve_edit->show();
- curve_del->show();
- curve_close->show();
- sep->show();
- } else {
-
- curve_create->hide();
- curve_edit->hide();
- curve_del->hide();
- curve_close->hide();
- sep->hide();
-
- {
- Path *pre=path;
- path=NULL;
- if (pre && pre->get_curve().is_valid()) {
- pre->get_curve()->emit_signal("changed");
- }
- }
- }
-
-}
-
-void PathEditorPlugin::_mode_changed(int p_idx) {
-
- curve_create->set_pressed(p_idx==0);
- curve_edit->set_pressed(p_idx==1);
- curve_del->set_pressed(p_idx==2);
-}
-
-void PathEditorPlugin::_close_curve() {
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return ;
- if (c->get_point_count()<2)
- return;
- c->add_point(c->get_point_pos(0),c->get_point_in(0),c->get_point_out(0));
-
-}
-
-void PathEditorPlugin::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- curve_create->connect("pressed",this,"_mode_changed",make_binds(0));
- curve_edit->connect("pressed",this,"_mode_changed",make_binds(1));
- curve_del->connect("pressed",this,"_mode_changed",make_binds(2));
- curve_close->connect("pressed",this,"_close_curve");
- }
-}
-
-void PathEditorPlugin::_bind_methods() {
-
- ClassDB::bind_method(_MD("_mode_changed"),&PathEditorPlugin::_mode_changed);
- ClassDB::bind_method(_MD("_close_curve"),&PathEditorPlugin::_close_curve);
-}
-
-PathEditorPlugin* PathEditorPlugin::singleton=NULL;
-
-
-PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) {
-
- path=NULL;
- editor=p_node;
- singleton=this;
-
- path_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- path_material->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) );
- path_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
- path_material->set_line_width(3);
- path_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- path_material->set_flag(Material::FLAG_UNSHADED,true);
-
- path_thin_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- path_thin_material->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) );
- path_thin_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true);
- path_thin_material->set_line_width(1);
- path_thin_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- path_thin_material->set_flag(Material::FLAG_UNSHADED,true);
-
- //SpatialEditor::get_singleton()->add_gizmo_plugin(this);
-
- sep = memnew( VSeparator);
- sep->hide();
- SpatialEditor::get_singleton()->add_control_to_menu_panel(sep);
- curve_edit = memnew( ToolButton );
- curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit","EditorIcons"));
- curve_edit->set_toggle_mode(true);
- curve_edit->hide();
- curve_edit->set_focus_mode(Control::FOCUS_NONE);
- curve_edit->set_tooltip(TTR("Select Points")+"\n"+TTR("Shift+Drag: Select Control Points")+"\n"+keycode_get_string(KEY_MASK_CMD)+TTR("Click: Add Point")+"\n"+TTR("Right Click: Delete Point"));
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit);
- curve_create = memnew( ToolButton );
- curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate","EditorIcons"));
- curve_create->set_toggle_mode(true);
- curve_create->hide();
- curve_create->set_focus_mode(Control::FOCUS_NONE);
- curve_create->set_tooltip(TTR("Add Point (in empty space)")+"\n"+TTR("Split Segment (in curve)"));
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create);
- curve_del = memnew( ToolButton );
- curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveDelete","EditorIcons"));
- curve_del->set_toggle_mode(true);
- curve_del->hide();
- curve_del->set_focus_mode(Control::FOCUS_NONE);
- curve_del->set_tooltip(TTR("Delete Point"));
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del);
- curve_close = memnew( ToolButton );
- curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveClose","EditorIcons"));
- curve_close->hide();
- curve_close->set_focus_mode(Control::FOCUS_NONE);
- curve_close->set_tooltip(TTR("Close Curve"));
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close);
-
-
-
- curve_edit->set_pressed(true);
- /*
- collision_polygon_editor = memnew( PathEditor(p_node) );
- editor->get_viewport()->add_child(collision_polygon_editor);
-
- collision_polygon_editor->set_margin(MARGIN_LEFT,200);
- collision_polygon_editor->set_margin(MARGIN_RIGHT,230);
- collision_polygon_editor->set_margin(MARGIN_TOP,0);
- collision_polygon_editor->set_margin(MARGIN_BOTTOM,10);
-
-
- collision_polygon_editor->hide();
- */
-
-
-}
-
-
-PathEditorPlugin::~PathEditorPlugin()
-{
-}
-
-#endif
diff --git a/tools/editor/plugins/path_editor_plugin.h b/tools/editor/plugins/path_editor_plugin.h
deleted file mode 100644
index 79e978dc1d..0000000000
--- a/tools/editor/plugins/path_editor_plugin.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*************************************************************************/
-/* path_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PATH_EDITOR_PLUGIN_H
-#define PATH_EDITOR_PLUGIN_H
-
-
-#include "tools/editor/spatial_editor_gizmos.h"
-#include "scene/3d/path.h"
-# if 0
-class PathSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(PathSpatialGizmo,EditorSpatialGizmo);
-
- Path* path;
- mutable Vector3 original;
-
-public:
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- PathSpatialGizmo(Path* p_path=NULL);
-
-};
-
-class PathEditorPlugin : public EditorPlugin {
-
- GDCLASS( PathEditorPlugin, EditorPlugin );
-
-
- Separator *sep;
- ToolButton *curve_create;
- ToolButton *curve_edit;
- ToolButton *curve_del;
- ToolButton *curve_close;
-
- EditorNode *editor;
-
-
- Path *path;
-
- void _mode_changed(int p_idx);
- void _close_curve();
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
- Path *get_edited_path() { return path; }
-
- static PathEditorPlugin* singleton;
- Ref<FixedSpatialMaterial> path_material;
- Ref<FixedSpatialMaterial> path_thin_material;
- virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event);
-
- //virtual bool forward_gui_input(const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
- virtual Ref<SpatialEditorGizmo> create_spatial_gizmo(Spatial* p_spatial);
- virtual String get_name() const { return "Path"; }
- 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);
-
- PathEditorPlugin(EditorNode *p_node);
- ~PathEditorPlugin();
-
-};
-
-#endif
-#endif // PATH_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.cpp b/tools/editor/plugins/polygon_2d_editor_plugin.cpp
deleted file mode 100644
index 7958dce75a..0000000000
--- a/tools/editor/plugins/polygon_2d_editor_plugin.cpp
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*************************************************************************/
-/* polygon_2d_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "polygon_2d_editor_plugin.h"
-
-#include "canvas_item_editor_plugin.h"
-#include "os/file_access.h"
-#include "tools/editor/editor_settings.h"
-#include "os/keyboard.h"
-#include "os/input.h"
-
-void Polygon2DEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
- button_create->set_icon( get_icon("Edit","EditorIcons"));
- button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
- button_edit->set_pressed(true);
- button_uv->set_icon( get_icon("Uv","EditorIcons"));
-
- uv_button[UV_MODE_EDIT_POINT]->set_icon(get_icon("ToolSelect","EditorIcons"));
- uv_button[UV_MODE_MOVE]->set_icon(get_icon("ToolMove","EditorIcons"));
- uv_button[UV_MODE_ROTATE]->set_icon(get_icon("ToolRotate","EditorIcons"));
- uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale","EditorIcons"));
-
- b_snap_grid->set_icon( get_icon("Grid", "EditorIcons"));
- b_snap_enable->set_icon( get_icon("Snap", "EditorIcons"));
- uv_icon_zoom->set_texture( get_icon("Zoom", "EditorIcons"));
-
- get_tree()->connect("node_removed", this, "_node_removed");
-
- } break;
- case NOTIFICATION_FIXED_PROCESS: {
-
-
- } break;
- }
-
-}
-void Polygon2DEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- edit(NULL);
- hide();
-
- canvas_item_editor->get_viewport_control()->update();
- }
-
-}
-
-
-void Polygon2DEditor::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case MODE_CREATE: {
-
- mode=MODE_CREATE;
- button_create->set_pressed(true);
- button_edit->set_pressed(false);
- } break;
- case MODE_EDIT: {
-
- mode=MODE_EDIT;
- button_create->set_pressed(false);
- button_edit->set_pressed(true);
- } break;
- case MODE_EDIT_UV: {
-
- if (node->get_texture().is_null()) {
-
- error->set_text("No texture in this polygon.\nSet a texture to be able to edit UV.");
- error->popup_centered_minsize();
- return;
- }
-
-
- PoolVector<Vector2> points = node->get_polygon();
- PoolVector<Vector2> uvs = node->get_uv();
- if (uvs.size()!=points.size()) {
- undo_redo->create_action(TTR("Create UV Map"));
- undo_redo->add_do_method(node,"set_uv",points);
- undo_redo->add_undo_method(node,"set_uv",uvs);
- undo_redo->add_do_method(uv_edit_draw,"update");
- undo_redo->add_undo_method(uv_edit_draw,"update");
- undo_redo->commit_action();
-
- }
-
-
- uv_edit->popup_centered_ratio(0.85);
- } break;
- case UVEDIT_POLYGON_TO_UV: {
-
- PoolVector<Vector2> points = node->get_polygon();
- if (points.size()==0)
- break;
- PoolVector<Vector2> uvs = node->get_uv();
- undo_redo->create_action(TTR("Create UV Map"));
- undo_redo->add_do_method(node,"set_uv",points);
- undo_redo->add_undo_method(node,"set_uv",uvs);
- undo_redo->add_do_method(uv_edit_draw,"update");
- undo_redo->add_undo_method(uv_edit_draw,"update");
- undo_redo->commit_action();
-
-
- } break;
- case UVEDIT_UV_TO_POLYGON: {
-
- PoolVector<Vector2> points = node->get_polygon();
- PoolVector<Vector2> uvs = node->get_uv();
- if (uvs.size()==0)
- break;
-
- undo_redo->create_action(TTR("Create UV Map"));
- undo_redo->add_do_method(node,"set_polygon",uvs);
- undo_redo->add_undo_method(node,"set_polygon",points);
- undo_redo->add_do_method(uv_edit_draw,"update");
- undo_redo->add_undo_method(uv_edit_draw,"update");
- undo_redo->commit_action();
-
- } break;
- case UVEDIT_UV_CLEAR: {
-
- PoolVector<Vector2> uvs = node->get_uv();
- if (uvs.size()==0)
- break;
- undo_redo->create_action(TTR("Create UV Map"));
- undo_redo->add_do_method(node,"set_uv",PoolVector<Vector2>());
- undo_redo->add_undo_method(node,"set_uv",uvs);
- undo_redo->add_do_method(uv_edit_draw,"update");
- undo_redo->add_undo_method(uv_edit_draw,"update");
- undo_redo->commit_action();
-
- } break;
-
-
- }
-}
-
-void Polygon2DEditor::_set_use_snap(bool p_use)
-{
- use_snap=p_use;
-}
-
-void Polygon2DEditor::_set_show_grid(bool p_show)
-{
- snap_show_grid=p_show;
- uv_edit_draw->update();
-}
-
-void Polygon2DEditor::_set_snap_off_x(float p_val)
-{
- snap_offset.x=p_val;
- uv_edit_draw->update();
-}
-
-void Polygon2DEditor::_set_snap_off_y(float p_val)
-{
- snap_offset.y=p_val;
- uv_edit_draw->update();
-}
-
-void Polygon2DEditor::_set_snap_step_x(float p_val)
-{
- snap_step.x=p_val;
- uv_edit_draw->update();
-}
-
-void Polygon2DEditor::_set_snap_step_y(float p_val)
-{
- snap_step.y=p_val;
- uv_edit_draw->update();
-}
-
-void Polygon2DEditor::_wip_close() {
-
- undo_redo->create_action(TTR("Create Poly"));
- undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
- undo_redo->add_do_method(node,"set_polygon",wip);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- wip.clear();
- wip_active=false;
- mode=MODE_EDIT;
- button_edit->set_pressed(true);
- button_create->set_pressed(false);
- edited_point=-1;
-}
-
-bool Polygon2DEditor::forward_gui_input(const InputEvent& p_event) {
-
- if (node==NULL)
- return false;
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
-
-
- Vector2 gpoint = Point2(mb.x,mb.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
-
-
- Vector<Vector2> poly = Variant(node->get_polygon());
-
- //first check if a point is to be added (segment split)
- real_t grab_treshold=EDITOR_DEF("editors/poly_editor/point_grab_radius",8);
-
- switch(mode) {
-
-
- case MODE_CREATE: {
-
- if (mb.button_index==BUTTON_LEFT && mb.pressed) {
-
-
- if (!wip_active) {
-
- wip.clear();
- wip.push_back( cpoint-node->get_offset() );
- wip_active=true;
- edited_point_pos=cpoint;
- canvas_item_editor->get_viewport_control()->update();
- edited_point=1;
- return true;
- } else {
-
-
- if (wip.size()>1 && xform.xform(wip[0]+node->get_offset()).distance_to(gpoint)<grab_treshold) {
- //wip closed
- _wip_close();
-
- return true;
- } else {
-
- wip.push_back( cpoint-node->get_offset() );
- edited_point=wip.size();
- canvas_item_editor->get_viewport_control()->update();
- return true;
-
- //add wip point
- }
- }
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) {
- _wip_close();
- }
-
-
-
- } break;
-
- case MODE_EDIT: {
-
- if (mb.button_index==BUTTON_LEFT) {
- if (mb.pressed) {
-
- if (mb.mod.control) {
-
-
- if (poly.size() < 3) {
-
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.push_back(cpoint);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- //search edges
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 points[2] ={ xform.xform(poly[i]+node->get_offset()),
- xform.xform(poly[(i+1)%poly.size()]+node->get_offset()) };
-
- Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points);
- if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2)
- continue; //not valid to reuse point
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos)-node->get_offset());
- edited_point=closest_idx+1;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- node->set_polygon(Variant(poly));
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- } else {
-
- //look for points to move
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]+node->get_offset());
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
- pre_move_edit=poly;
- edited_point=closest_idx;
- edited_point_pos=xform.affine_inverse().xform(closest_pos);
- canvas_item_editor->get_viewport_control()->update();
- return true;
- }
- }
- } else {
-
- if (edited_point!=-1) {
-
- //apply
-
- ERR_FAIL_INDEX_V(edited_point,poly.size(),false);
- poly[edited_point]=edited_point_pos-node->get_offset();
- undo_redo->create_action(TTR("Edit Poly"));
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_undo_method(node,"set_polygon",pre_move_edit);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
-
- edited_point=-1;
- return true;
- }
- }
- } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) {
-
-
-
- int closest_idx=-1;
- Vector2 closest_pos;
- real_t closest_dist=1e10;
- for(int i=0;i<poly.size();i++) {
-
- Vector2 cp =xform.xform(poly[i]+node->get_offset());
-
- real_t d = cp.distance_to(gpoint);
- if (d<closest_dist && d<grab_treshold) {
- closest_dist=d;
- closest_pos=cp;
- closest_idx=i;
- }
-
- }
-
- if (closest_idx>=0) {
-
-
- undo_redo->create_action(TTR("Edit Poly (Remove Point)"));
- undo_redo->add_undo_method(node,"set_polygon",poly);
- poly.remove(closest_idx);
- undo_redo->add_do_method(node,"set_polygon",poly);
- undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update");
- undo_redo->commit_action();
- return true;
- }
-
- }
-
-
-
- } break;
- }
-
-
-
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mm=p_event.mouse_motion;
-
- if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) {
-
- Vector2 gpoint = Point2(mm.x,mm.y);
- Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
- cpoint=canvas_item_editor->snap_point(cpoint);
- edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
-
- canvas_item_editor->get_viewport_control()->update();
-
- }
-
- } break;
- }
-
- return false;
-}
-void Polygon2DEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Control *vpc = canvas_item_editor->get_viewport_control();
-
- Vector<Vector2> poly;
-
- if (wip_active)
- poly=wip;
- else
- poly=Variant(node->get_polygon());
-
-
- Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
- Ref<Texture> handle= get_icon("EditorHandle","EditorIcons");
-
- for(int i=0;i<poly.size();i++) {
-
-
- Vector2 p,p2;
- p = i==edited_point ? edited_point_pos : (poly[i]+node->get_offset());
- if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point))
- p2=edited_point_pos;
- else
- p2 = poly[(i+1)%poly.size()]+node->get_offset();
-
- Vector2 point = xform.xform(p);
- Vector2 next_point = xform.xform(p2);
-
- Color col=Color(1,0.3,0.1,0.8);
- vpc->draw_line(point,next_point,col,2);
- vpc->draw_texture(handle,point-handle->get_size()*0.5);
- }
-}
-
-
-void Polygon2DEditor::_uv_mode(int p_mode) {
-
-
- uv_mode=UVMode(p_mode);
- for(int i=0;i<UV_MODE_MAX;i++) {
- uv_button[i]->set_pressed(p_mode==i);
- }
-}
-
-
-void Polygon2DEditor::_uv_input(const InputEvent& p_input) {
-
-
- Transform2D mtx;
- mtx.elements[2]=-uv_draw_ofs;
- mtx.scale_basis(Vector2(uv_draw_zoom,uv_draw_zoom));
-
- if (p_input.type==InputEvent::MOUSE_BUTTON) {
-
-
- const InputEventMouseButton &mb=p_input.mouse_button;
-
- if (mb.button_index==BUTTON_LEFT) {
-
-
- if (mb.pressed) {
-
- uv_drag_from=Vector2(mb.x,mb.y);
- uv_drag=true;
- uv_prev=node->get_uv();
- uv_move_current=uv_mode;
- if (uv_move_current==UV_MODE_EDIT_POINT) {
-
- if (mb.mod.shift && mb.mod.command)
- uv_move_current=UV_MODE_SCALE;
- else if (mb.mod.shift)
- uv_move_current=UV_MODE_MOVE;
- else if (mb.mod.command)
- uv_move_current=UV_MODE_ROTATE;
- }
-
- if (uv_move_current==UV_MODE_EDIT_POINT) {
-
- uv_drag_index=-1;
- for(int i=0;i<uv_prev.size();i++) {
-
- Vector2 tuv=mtx.xform(uv_prev[i]);
- if (tuv.distance_to(Vector2(mb.x,mb.y))<8) {
- uv_drag_from=tuv;
- uv_drag_index=i;
- }
- }
-
- if (uv_drag_index==-1) {
- uv_drag=false;
- }
-
- }
- } else if (uv_drag) {
-
- undo_redo->create_action(TTR("Transform UV Map"));
- undo_redo->add_do_method(node,"set_uv",node->get_uv());
- undo_redo->add_undo_method(node,"set_uv",uv_prev);
- undo_redo->add_do_method(uv_edit_draw,"update");
- undo_redo->add_undo_method(uv_edit_draw,"update");
- undo_redo->commit_action();
-
- uv_drag=false;
- }
-
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed) {
-
- if (uv_drag) {
-
- uv_drag=false;
- node->set_uv(uv_prev);
- uv_edit_draw->update();
- }
-
- } else if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) {
-
- uv_zoom->set_value( uv_zoom->get_value()/0.9 );
- } else if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) {
-
- uv_zoom->set_value( uv_zoom->get_value()*0.9);
- }
-
- } else if (p_input.type==InputEvent::MOUSE_MOTION) {
-
- const InputEventMouseMotion &mm=p_input.mouse_motion;
-
- if (mm.button_mask&BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
-
- Vector2 drag(mm.relative_x,mm.relative_y);
- uv_hscroll->set_value( uv_hscroll->get_value()-drag.x );
- uv_vscroll->set_value( uv_vscroll->get_value()-drag.y );
-
- } else if (uv_drag) {
-
- Vector2 uv_drag_to=snap_point(Vector2(mm.x,mm.y));
- Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from);
-
-
- switch(uv_move_current) {
-
- case UV_MODE_EDIT_POINT: {
-
- PoolVector<Vector2> uv_new=uv_prev;
- uv_new.set( uv_drag_index, uv_new[uv_drag_index]+drag );
- node->set_uv(uv_new);
- } break;
- case UV_MODE_MOVE: {
-
- PoolVector<Vector2> uv_new=uv_prev;
- for(int i=0;i<uv_new.size();i++)
- uv_new.set( i, uv_new[i]+drag );
-
- node->set_uv(uv_new);
-
-
- } break;
- case UV_MODE_ROTATE: {
-
- Vector2 center;
- PoolVector<Vector2> uv_new=uv_prev;
-
- for(int i=0;i<uv_new.size();i++)
- center+=uv_prev[i];
- center/=uv_new.size();
-
- float angle = (uv_drag_from - mtx.xform(center)).normalized().angle_to( (uv_drag_to - mtx.xform(center)).normalized() );
-
- for(int i=0;i<uv_new.size();i++) {
- Vector2 rel = uv_prev[i] - center;
- rel=rel.rotated(angle);
- uv_new.set(i,center+rel);
- }
-
- node->set_uv(uv_new);
-
- } break;
- case UV_MODE_SCALE: {
-
- Vector2 center;
- PoolVector<Vector2> uv_new=uv_prev;
-
- for(int i=0;i<uv_new.size();i++)
- center+=uv_prev[i];
- center/=uv_new.size();
-
- float from_dist = uv_drag_from.distance_to(mtx.xform(center));
- float to_dist = uv_drag_to.distance_to(mtx.xform(center));
- if (from_dist<2)
- break;
-
- float scale = to_dist/from_dist;
-
-
- for(int i=0;i<uv_new.size();i++) {
- Vector2 rel = uv_prev[i] - center;
- rel=rel*scale;
- uv_new.set(i,center+rel);
- }
-
- node->set_uv(uv_new);
- } break;
-
-
- }
- uv_edit_draw->update();
- }
-
- }
-
-}
-
-
-void Polygon2DEditor::_uv_scroll_changed(float) {
-
- if (updating_uv_scroll)
- return;
-
- uv_draw_ofs.x=uv_hscroll->get_value();
- uv_draw_ofs.y=uv_vscroll->get_value();
- uv_draw_zoom=uv_zoom->get_value();
- uv_edit_draw->update();
-}
-
-void Polygon2DEditor::_uv_draw() {
-
- Ref<Texture> base_tex = node->get_texture();
- if (base_tex.is_null())
- return;
-
- Transform2D mtx;
- mtx.elements[2]=-uv_draw_ofs;
- mtx.scale_basis(Vector2(uv_draw_zoom,uv_draw_zoom));
-
- VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(),mtx);
- uv_edit_draw->draw_texture(base_tex,Point2());
- VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(),Transform2D());
-
- if (snap_show_grid) {
- Size2 s = uv_edit_draw->get_size();
- int last_cell;
-
- if (snap_step.x!=0) {
- for(int i=0;i<s.width;i++) {
- int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- uv_edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- }
-
- if (snap_step.y!=0) {
- for(int i=0;i<s.height;i++) {
- int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- uv_edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- }
- }
-
- PoolVector<Vector2> uvs = node->get_uv();
- Ref<Texture> handle = get_icon("EditorHandle","EditorIcons");
-
- Rect2 rect(Point2(),mtx.basis_xform(base_tex->get_size()));
- rect.expand_to(mtx.basis_xform(uv_edit_draw->get_size()));
-
- for(int i=0;i<uvs.size();i++) {
-
- int next = (i+1)%uvs.size();
- uv_edit_draw->draw_line(mtx.xform(uvs[i]),mtx.xform(uvs[next]),Color(0.9,0.5,0.5),2);
- uv_edit_draw->draw_texture(handle,mtx.xform(uvs[i])-handle->get_size()*0.5);
- rect.expand_to(mtx.basis_xform(uvs[i]));
- }
-
- rect=rect.grow(200);
- updating_uv_scroll=true;
- uv_hscroll->set_min(rect.pos.x);
- uv_hscroll->set_max(rect.pos.x+rect.size.x);
- uv_hscroll->set_page(uv_edit_draw->get_size().x);
- uv_hscroll->set_value(uv_draw_ofs.x);
- uv_hscroll->set_step(0.001);
-
- uv_vscroll->set_min(rect.pos.y);
- uv_vscroll->set_max(rect.pos.y+rect.size.y);
- uv_vscroll->set_page(uv_edit_draw->get_size().y);
- uv_vscroll->set_value(uv_draw_ofs.y);
- uv_vscroll->set_step(0.001);
- updating_uv_scroll=false;
-
-}
-
-void Polygon2DEditor::edit(Node *p_collision_polygon) {
-
- if (!canvas_item_editor) {
- canvas_item_editor=CanvasItemEditor::get_singleton();
- }
-
- if (p_collision_polygon) {
-
- node=p_collision_polygon->cast_to<Polygon2D>();
- if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
-
- wip.clear();
- wip_active=false;
- edited_point=-1;
-
- } else {
-
- node=NULL;
-
- if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw");
-
- }
-
-}
-
-void Polygon2DEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_menu_option"),&Polygon2DEditor::_menu_option);
- ClassDB::bind_method(_MD("_canvas_draw"),&Polygon2DEditor::_canvas_draw);
- ClassDB::bind_method(_MD("_uv_mode"),&Polygon2DEditor::_uv_mode);
- ClassDB::bind_method(_MD("_uv_draw"),&Polygon2DEditor::_uv_draw);
- ClassDB::bind_method(_MD("_uv_input"),&Polygon2DEditor::_uv_input);
- ClassDB::bind_method(_MD("_uv_scroll_changed"),&Polygon2DEditor::_uv_scroll_changed);
- ClassDB::bind_method(_MD("_node_removed"),&Polygon2DEditor::_node_removed);
- ClassDB::bind_method(_MD("_set_use_snap"),&Polygon2DEditor::_set_use_snap);
- ClassDB::bind_method(_MD("_set_show_grid"),&Polygon2DEditor::_set_show_grid);
- ClassDB::bind_method(_MD("_set_snap_off_x"),&Polygon2DEditor::_set_snap_off_x);
- ClassDB::bind_method(_MD("_set_snap_off_y"),&Polygon2DEditor::_set_snap_off_y);
- ClassDB::bind_method(_MD("_set_snap_step_x"),&Polygon2DEditor::_set_snap_step_x);
- ClassDB::bind_method(_MD("_set_snap_step_y"),&Polygon2DEditor::_set_snap_step_y);
-
-
-}
-
-inline float _snap_scalar(float p_offset, float p_step, float p_target) {
- return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
-}
-
-Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
- if (use_snap) {
- p_target.x = _snap_scalar(snap_offset.x*uv_draw_zoom-uv_draw_ofs.x, snap_step.x*uv_draw_zoom, p_target.x);
- p_target.y = _snap_scalar(snap_offset.y*uv_draw_zoom-uv_draw_ofs.y, snap_step.y*uv_draw_zoom, p_target.y);
- }
-
- return p_target;
-}
-
-Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) {
-
- node=NULL;
- canvas_item_editor=NULL;
- editor=p_editor;
- undo_redo = editor->get_undo_redo();
-
- snap_step=Vector2(10,10);
- use_snap=false;
- snap_show_grid=false;
-
- add_child( memnew( VSeparator ));
- button_create = memnew( ToolButton );
- add_child(button_create);
- button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
- button_create->set_toggle_mode(true);
-
- button_edit = memnew( ToolButton );
- add_child(button_edit);
- button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
- button_edit->set_toggle_mode(true);
-
- button_uv = memnew( ToolButton );
- add_child(button_uv);
- button_uv->connect("pressed",this,"_menu_option",varray(MODE_EDIT_UV));
-
- //add_constant_override("separation",0);
-
-#if 0
- options = memnew( MenuButton );
- add_child(options);
- options->set_area_as_parent_rect();
- options->set_text("Polygon");
- //options->get_popup()->add_item("Parse BBCode",PARSE_BBCODE);
- options->get_popup()->connect("id_pressed", this,"_menu_option");
-#endif
-
- mode = MODE_EDIT;
- wip_active=false;
-
- uv_mode=UV_MODE_EDIT_POINT;
- uv_edit = memnew( AcceptDialog );
- add_child(uv_edit);
- uv_edit->set_title(TTR("Polygon 2D UV Editor"));
- uv_edit->set_self_modulate(Color(1,1,1,0.9));
-
- VBoxContainer *uv_main_vb = memnew( VBoxContainer );
- uv_edit->add_child(uv_main_vb);
- //uv_edit->set_child_rect(uv_main_vb);
- HBoxContainer *uv_mode_hb = memnew( HBoxContainer );
- uv_main_vb->add_child(uv_mode_hb);
- for(int i=0;i<UV_MODE_MAX;i++) {
-
- uv_button[i]=memnew( ToolButton );
- uv_button[i]->set_toggle_mode(true);
- uv_mode_hb->add_child(uv_button[i]);
- uv_button[i]->connect("pressed",this,"_uv_mode",varray(i));
- uv_button[i]->set_focus_mode(FOCUS_NONE);
- }
-
- uv_button[0]->set_tooltip(TTR("Move Point")+"\n"+TTR("Ctrl: Rotate")+"\n"+TTR("Shift: Move All")+"\n"+TTR("Shift+Ctrl: Scale"));
- uv_button[1]->set_tooltip(TTR("Move Polygon"));
- uv_button[2]->set_tooltip(TTR("Rotate Polygon"));
- uv_button[3]->set_tooltip(TTR("Scale Polygon"));
-
- uv_button[0]->set_pressed(true);
- HBoxContainer *uv_main_hb = memnew( HBoxContainer );
- uv_main_vb->add_child(uv_main_hb);
- uv_edit_draw = memnew( Control );
- uv_main_hb->add_child(uv_edit_draw);
- uv_main_hb->set_v_size_flags(SIZE_EXPAND_FILL);
- uv_edit_draw->set_h_size_flags(SIZE_EXPAND_FILL);
- uv_menu = memnew( MenuButton );
- uv_mode_hb->add_child(uv_menu);
- uv_menu->set_text(TTR("Edit"));
- uv_menu->get_popup()->add_item(TTR("Polygon->UV"),UVEDIT_POLYGON_TO_UV);
- uv_menu->get_popup()->add_item(TTR("UV->Polygon"),UVEDIT_UV_TO_POLYGON);
- uv_menu->get_popup()->add_separator();
- uv_menu->get_popup()->add_item(TTR("Clear UV"),UVEDIT_UV_CLEAR);
- uv_menu->get_popup()->connect("id_pressed",this,"_menu_option");
-
- uv_mode_hb->add_child( memnew( VSeparator ));
-
- b_snap_enable = memnew( ToolButton );
- uv_mode_hb->add_child(b_snap_enable);
- b_snap_enable->set_text(TTR("Snap"));
- b_snap_enable->set_focus_mode(FOCUS_NONE);
- b_snap_enable->set_toggle_mode(true);
- b_snap_enable->set_pressed(use_snap);
- b_snap_enable->set_tooltip(TTR("Enable Snap"));
- b_snap_enable->connect("toggled",this,"_set_use_snap");
-
- b_snap_grid = memnew( ToolButton );
- uv_mode_hb->add_child(b_snap_grid);
- b_snap_grid->set_text(TTR("Grid"));
- b_snap_grid->set_focus_mode(FOCUS_NONE);
- b_snap_grid->set_toggle_mode(true);
- b_snap_grid->set_pressed(snap_show_grid);
- b_snap_grid->set_tooltip(TTR("Show Grid"));
- b_snap_grid->connect("toggled",this,"_set_show_grid");
-
- uv_mode_hb->add_child( memnew( VSeparator ));
- uv_mode_hb->add_child( memnew( Label(TTR("Grid Offset:")) ) );
-
- SpinBox *sb_off_x = memnew( SpinBox );
- sb_off_x->set_min(-256);
- sb_off_x->set_max(256);
- sb_off_x->set_step(1);
- sb_off_x->set_value(snap_offset.x);
- sb_off_x->set_suffix("px");
- sb_off_x->connect("value_changed", this, "_set_snap_off_x");
- uv_mode_hb->add_child(sb_off_x);
-
- SpinBox *sb_off_y = memnew( SpinBox );
- sb_off_y->set_min(-256);
- sb_off_y->set_max(256);
- sb_off_y->set_step(1);
- sb_off_y->set_value(snap_offset.y);
- sb_off_y->set_suffix("px");
- sb_off_y->connect("value_changed", this, "_set_snap_off_y");
- uv_mode_hb->add_child(sb_off_y);
-
- uv_mode_hb->add_child( memnew( VSeparator ));
- uv_mode_hb->add_child( memnew( Label(TTR("Grid Step:")) ) );
-
- SpinBox *sb_step_x = memnew( SpinBox );
- sb_step_x->set_min(-256);
- sb_step_x->set_max(256);
- sb_step_x->set_step(1);
- sb_step_x->set_value(snap_step.x);
- sb_step_x->set_suffix("px");
- sb_step_x->connect("value_changed", this, "_set_snap_step_x");
- uv_mode_hb->add_child(sb_step_x);
-
- SpinBox *sb_step_y = memnew( SpinBox );
- sb_step_y->set_min(-256);
- sb_step_y->set_max(256);
- sb_step_y->set_step(1);
- sb_step_y->set_value(snap_step.y);
- sb_step_y->set_suffix("px");
- sb_step_y->connect("value_changed", this, "_set_snap_step_y");
- uv_mode_hb->add_child(sb_step_y);
-
- uv_mode_hb->add_child( memnew( VSeparator ));
- uv_icon_zoom = memnew( TextureRect );
- uv_mode_hb->add_child( uv_icon_zoom );
- uv_zoom = memnew( HSlider );
- uv_zoom->set_min(0.01);
- uv_zoom->set_max(4);
- uv_zoom->set_value(1);
- uv_zoom->set_step(0.01);
- uv_mode_hb->add_child(uv_zoom);
- uv_zoom->set_custom_minimum_size(Size2(200,0));
- uv_zoom_value = memnew( SpinBox );
- uv_zoom->share(uv_zoom_value);
- uv_zoom_value->set_custom_minimum_size(Size2(50,0));
- uv_mode_hb->add_child(uv_zoom_value);
- uv_zoom->connect("value_changed",this,"_uv_scroll_changed");
-
-
-
- uv_vscroll = memnew( VScrollBar);
- uv_main_hb->add_child(uv_vscroll);
- uv_vscroll->connect("value_changed",this,"_uv_scroll_changed");
- uv_hscroll = memnew( HScrollBar );
- uv_main_vb->add_child(uv_hscroll);
- uv_hscroll->connect("value_changed",this,"_uv_scroll_changed");
-
- uv_edit_draw->connect("draw",this,"_uv_draw");
- uv_edit_draw->connect("gui_input",this,"_uv_input");
- uv_draw_zoom=1.0;
- uv_drag_index=-1;
- uv_drag=false;
- updating_uv_scroll=false;
-
- error = memnew( AcceptDialog);
- add_child(error);
-
- uv_edit_draw->set_clip_contents(true);
-
-}
-
-
-void Polygon2DEditorPlugin::edit(Object *p_object) {
-
-
- collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool Polygon2DEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Polygon2D");
-}
-
-void Polygon2DEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- collision_polygon_editor->show();
- } else {
-
- collision_polygon_editor->hide();
- collision_polygon_editor->edit(NULL);
- }
-
-}
-
-Polygon2DEditorPlugin::Polygon2DEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- collision_polygon_editor = memnew( Polygon2DEditor(p_node) );
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
-
- collision_polygon_editor->hide();
-
-}
-
-
-Polygon2DEditorPlugin::~Polygon2DEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.h b/tools/editor/plugins/polygon_2d_editor_plugin.h
deleted file mode 100644
index 6011ee1f87..0000000000
--- a/tools/editor/plugins/polygon_2d_editor_plugin.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*************************************************************************/
-/* polygon_2d_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 POLYGON_2D_EDITOR_PLUGIN_H
-#define POLYGON_2D_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/2d/polygon_2d.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/button_group.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class CanvasItemEditor;
-
-class Polygon2DEditor : public HBoxContainer {
-
- GDCLASS(Polygon2DEditor, HBoxContainer );
-
- UndoRedo *undo_redo;
- enum Mode {
-
- MODE_CREATE,
- MODE_EDIT,
- MODE_EDIT_UV,
- UVEDIT_POLYGON_TO_UV,
- UVEDIT_UV_TO_POLYGON,
- UVEDIT_UV_CLEAR
-
- };
-
- enum UVMode {
- UV_MODE_EDIT_POINT,
- UV_MODE_MOVE,
- UV_MODE_ROTATE,
- UV_MODE_SCALE,
- UV_MODE_MAX
- };
-
- Mode mode;
-
- UVMode uv_mode;
- AcceptDialog *uv_edit;
- ToolButton *uv_button[4];
- ToolButton *b_snap_enable;
- ToolButton *b_snap_grid;
- Control *uv_edit_draw;
- HSlider *uv_zoom;
- SpinBox *uv_zoom_value;
- HScrollBar *uv_hscroll;
- VScrollBar *uv_vscroll;
- MenuButton *uv_menu;
- TextureRect *uv_icon_zoom;
-
- Vector2 uv_draw_ofs;
- float uv_draw_zoom;
- PoolVector<Vector2> uv_prev;
- int uv_drag_index;
- bool uv_drag;
- UVMode uv_move_current;
- Vector2 uv_drag_from;
- bool updating_uv_scroll;
-
-
-
- AcceptDialog *error;
-
- ToolButton *button_create;
- ToolButton *button_edit;
- ToolButton *button_uv;
-
- CanvasItemEditor *canvas_item_editor;
- EditorNode *editor;
- Panel *panel;
- Polygon2D *node;
- MenuButton *options;
-
- int edited_point;
- Vector2 edited_point_pos;
- Vector<Vector2> pre_move_edit;
- Vector<Vector2> wip;
- bool wip_active;
-
- bool use_snap;
- bool snap_show_grid;
- Vector2 snap_offset;
- Vector2 snap_step;
-
- void _uv_scroll_changed(float);
- void _uv_input(const InputEvent& p_input);
- void _uv_draw();
- void _uv_mode(int p_mode);
- void _wip_close();
- void _canvas_draw();
- void _menu_option(int p_option);
-
- void _set_use_snap(bool p_use);
- void _set_show_grid(bool p_show);
- void _set_snap_off_x(float p_val);
- void _set_snap_off_y(float p_val);
- void _set_snap_step_x(float p_val);
- void _set_snap_step_y(float p_val);
-
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-
- Vector2 snap_point(Vector2 p_target) const;
-
-public:
-
- bool forward_gui_input(const InputEvent& p_event);
- void edit(Node *p_collision_polygon);
- Polygon2DEditor(EditorNode *p_editor);
-};
-
-class Polygon2DEditorPlugin : public EditorPlugin {
-
- GDCLASS( Polygon2DEditorPlugin, EditorPlugin );
-
- Polygon2DEditor *collision_polygon_editor;
- EditorNode *editor;
-
-public:
-
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "Polygon2D"; }
- 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);
-
- Polygon2DEditorPlugin(EditorNode *p_node);
- ~Polygon2DEditorPlugin();
-
-};
-
-#endif // POLYGON_2D_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/resource_preloader_editor_plugin.cpp b/tools/editor/plugins/resource_preloader_editor_plugin.cpp
deleted file mode 100644
index cb139cbe24..0000000000
--- a/tools/editor/plugins/resource_preloader_editor_plugin.cpp
+++ /dev/null
@@ -1,507 +0,0 @@
-/*************************************************************************/
-/* resource_preloader_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "resource_preloader_editor_plugin.h"
-
-#include "io/resource_loader.h"
-#include "globals.h"
-#include "tools/editor/editor_settings.h"
-
-
-void ResourcePreloaderEditor::_gui_input(InputEvent p_event) {
-
-
-}
-
-void ResourcePreloaderEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- load->set_icon( get_icon("Folder","EditorIcons") );
- _delete->set_icon( get_icon("Del","EditorIcons") );
- }
-
- if (p_what==NOTIFICATION_READY) {
-
- //NodePath("/root")->connect("node_removed", this,"_node_removed",Vector<Variant>(),true);
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
- }
-}
-
-void ResourcePreloaderEditor::_files_load_request(const Vector<String>& p_paths) {
-
- for(int i=0;i<p_paths.size();i++) {
-
- String path = p_paths[i];
-
- RES resource;
- resource = ResourceLoader::load(path);
-
- if (resource.is_null()) {
- dialog->set_text(TTR("ERROR: Couldn't load resource!"));
- dialog->set_title(TTR("Error!"));
- //dialog->get_cancel()->set_text("Close");
- dialog->get_ok()->set_text(TTR("Close"));
- dialog->popup_centered_minsize();
- return; ///beh should show an error i guess
- }
-
-
- String basename = path.get_file().get_basename();
- String name=basename;
- int counter=1;
- while(preloader->has_resource(name)) {
- counter++;
- name=basename+" "+itos(counter);
- }
-
- undo_redo->create_action(TTR("Add Resource"));
- undo_redo->add_do_method(preloader,"add_resource",name,resource);
- undo_redo->add_undo_method(preloader,"remove_resource",name);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
- }
-}
-
-void ResourcePreloaderEditor::_load_pressed() {
-
- loading_scene=false;
-
- file->clear_filters();
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("",&extensions);
- for(int i=0;i<extensions.size();i++)
- file->add_filter("*."+extensions[i]);
-
- file->set_mode(EditorFileDialog::MODE_OPEN_FILES);
-
- file->popup_centered_ratio();
-
-}
-
-
-void ResourcePreloaderEditor::_item_edited() {
-
- if (!tree->get_selected())
- return;
-
- TreeItem *s = tree->get_selected();
-
- if (tree->get_selected_column()==0) {
- // renamed
- String old_name=s->get_metadata(0);
- String new_name=s->get_text(0);
- if (old_name==new_name)
- return;
-
- if (new_name=="" || new_name.find("\\")!=-1 || new_name.find("/")!=-1 || preloader->has_resource(new_name)) {
-
- s->set_text(0,old_name);
- return;
- }
-
- RES samp = preloader->get_resource(old_name);
- undo_redo->create_action(TTR("Rename Resource"));
- undo_redo->add_do_method(preloader,"remove_resource",old_name);
- undo_redo->add_do_method(preloader,"add_resource",new_name,samp);
- undo_redo->add_undo_method(preloader,"remove_resource",new_name);
- undo_redo->add_undo_method(preloader,"add_resource",old_name,samp);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
- }
-
-
-}
-
-void ResourcePreloaderEditor::_delete_confirm_pressed() {
-
- if (!tree->get_selected())
- return;
-
- String to_remove = tree->get_selected()->get_text(0);
- undo_redo->create_action(TTR("Delete Resource"));
- undo_redo->add_do_method(preloader,"remove_resource",to_remove);
- undo_redo->add_undo_method(preloader,"add_resource",to_remove,preloader->get_resource(to_remove));
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-}
-
-
-void ResourcePreloaderEditor::_paste_pressed() {
-
- RES r=EditorSettings::get_singleton()->get_resource_clipboard();
- if (!r.is_valid()) {
- dialog->set_text(TTR("Resource clipboard is empty!"));
- dialog->set_title(TTR("Error!"));
- //dialog->get_cancel()->set_text("Close");
- dialog->get_ok()->set_text(TTR("Close"));
- dialog->popup_centered_minsize();
- return; ///beh should show an error i guess
- }
-
- String name = r->get_name();
- if (name=="")
- name=r->get_path().get_file();
- if (name=="")
- name=r->get_class();
-
- String basename = name;
- int counter=1;
- while(preloader->has_resource(name)) {
- counter++;
- name=basename+" "+itos(counter);
- }
-
- undo_redo->create_action(TTR("Paste Resource"));
- undo_redo->add_do_method(preloader,"add_resource",name,r);
- undo_redo->add_undo_method(preloader,"remove_resource",name);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
-}
-
-
-void ResourcePreloaderEditor::_delete_pressed() {
-
-
- if (!tree->get_selected())
- return;
-
- _delete_confirm_pressed(); //it has undo.. why bother with a dialog..
- /*
- dialog->set_title("Confirm...");
- dialog->set_text("Remove Resource '"+tree->get_selected()->get_text(0)+"' ?");
- //dialog->get_cancel()->set_text("Cancel");
- //dialog->get_ok()->show();
- dialog->get_ok()->set_text("Remove");
- dialog->popup_centered(Size2(300,60));*/
-
-}
-
-
-void ResourcePreloaderEditor::_update_library() {
-
- tree->clear();
- tree->set_hide_root(true);
- TreeItem *root = tree->create_item(NULL);
-
- List<StringName> rnames;
- preloader->get_resource_list(&rnames);
-
- List<String> names;
- for(List<StringName>::Element *E=rnames.front();E;E=E->next()) {
- names.push_back(E->get());
- }
-
- names.sort();
-
- for(List<String>::Element *E=names.front();E;E=E->next()) {
-
- 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);
- ti->set_text(0,E->get());
- ti->set_metadata(0,E->get());
-
-
-
- RES r = preloader->get_resource(E->get());
-
- ERR_CONTINUE(r.is_null());
-
- ti->set_tooltip(0,r->get_path());
- String type = r->get_class();
- ti->set_text(1,type);
- ti->set_selectable(1,false);
-
- if (has_icon(type,"EditorIcons"))
- ti->set_icon( 1, get_icon(type,"EditorIcons") );
-
- }
-
- //player->add_resource("default",resource);
-}
-
-
-
-void ResourcePreloaderEditor::edit(ResourcePreloader* p_preloader) {
-
- preloader=p_preloader;
-
-
- if (p_preloader) {
- _update_library();
- } else {
-
- hide();
- set_fixed_process(false);
- }
-
-}
-
-
-
-Variant ResourcePreloaderEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- TreeItem*ti =tree->get_item_at_pos(p_point);
- if (!ti)
- return Variant();
-
- String name = ti->get_metadata(0);
-
- RES res = preloader->get_resource(name);
- if (!res.is_valid())
- return Variant();
-
- return EditorNode::get_singleton()->drag_resource(res,p_from);
-
-}
-
-bool ResourcePreloaderEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
-
-
-
- Dictionary d = p_data;
-
- if (!d.has("type"))
- return false;
-
- if (d.has("from") && (Object*)(d["from"])==tree)
- return false;
-
- if (String(d["type"])=="resource" && d.has("resource")) {
- RES r=d["resource"];
-
- return r.is_valid();
- }
-
-
- if (String(d["type"])=="files") {
-
- Vector<String> files = d["files"];
-
- if (files.size()==0)
- return false;
-
- return true;
-
- }
- return false;
-}
-
-void ResourcePreloaderEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
-
- if (!can_drop_data_fw(p_point,p_data,p_from))
- return;
-
- Dictionary d = p_data;
-
- if (!d.has("type"))
- return;
-
-
- if (String(d["type"])=="resource" && d.has("resource")) {
- RES r=d["resource"];
-
- if (r.is_valid()) {
-
- String basename;
- if (r->get_name()!="") {
- basename=r->get_name();
- } else if (r->get_path().is_resource_file()) {
- basename = r->get_path().get_basename();
- } else {
- basename="Resource";
- }
-
- String name=basename;
- int counter=0;
- while(preloader->has_resource(name)) {
- counter++;
- name=basename+"_"+itos(counter);
- }
-
- undo_redo->create_action(TTR("Add Resource"));
- undo_redo->add_do_method(preloader,"add_resource",name,r);
- undo_redo->add_undo_method(preloader,"remove_resource",name);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
- }
- }
-
-
- if (String(d["type"])=="files") {
-
- Vector<String> files = d["files"];
-
- _files_load_request(files);
- }
-}
-
-
-
-void ResourcePreloaderEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&ResourcePreloaderEditor::_gui_input);
- ClassDB::bind_method(_MD("_load_pressed"),&ResourcePreloaderEditor::_load_pressed);
- ClassDB::bind_method(_MD("_item_edited"),&ResourcePreloaderEditor::_item_edited);
- ClassDB::bind_method(_MD("_delete_pressed"),&ResourcePreloaderEditor::_delete_pressed);
- ClassDB::bind_method(_MD("_paste_pressed"),&ResourcePreloaderEditor::_paste_pressed);
- ClassDB::bind_method(_MD("_delete_confirm_pressed"),&ResourcePreloaderEditor::_delete_confirm_pressed);
- ClassDB::bind_method(_MD("_files_load_request"),&ResourcePreloaderEditor::_files_load_request);
- ClassDB::bind_method(_MD("_update_library"),&ResourcePreloaderEditor::_update_library);
-
-
- ClassDB::bind_method(_MD("get_drag_data_fw"), &ResourcePreloaderEditor::get_drag_data_fw);
- ClassDB::bind_method(_MD("can_drop_data_fw"), &ResourcePreloaderEditor::can_drop_data_fw);
- ClassDB::bind_method(_MD("drop_data_fw"), &ResourcePreloaderEditor::drop_data_fw);
-
-
-}
-
-ResourcePreloaderEditor::ResourcePreloaderEditor() {
-
- //add_style_override("panel", get_stylebox("panel","Panel"));
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- vbc->add_child(hbc);
-
- load = memnew( Button );
- load->set_tooltip(TTR("Load Resource"));
- hbc->add_child(load);
-
-
-
- _delete = memnew( Button );
- hbc->add_child(_delete);
-
- paste = memnew( Button );
- paste->set_text(TTR("Paste"));
- hbc->add_child(paste);
-
- file = memnew( EditorFileDialog );
- add_child(file);
-
-
- tree = memnew( Tree );
- tree->set_columns(2);
- tree->set_column_min_width(0,3);
- tree->set_column_min_width(1,1);
- tree->set_column_expand(0,true);
- tree->set_column_expand(1,true);
- tree->set_v_size_flags(SIZE_EXPAND_FILL);
-
- tree->set_drag_forwarding(this);
- vbc->add_child(tree);
-
- dialog = memnew( AcceptDialog );
- add_child( dialog );
-
- load->connect("pressed", this,"_load_pressed");
- _delete->connect("pressed", this,"_delete_pressed");
- paste->connect("pressed", this,"_paste_pressed");
- file->connect("files_selected", this,"_files_load_request");
- //dialog->connect("confirmed", this,"_delete_confirm_pressed");
- tree->connect("item_edited", this,"_item_edited");
- loading_scene=false;
-
-}
-
-
-void ResourcePreloaderEditorPlugin::edit(Object *p_object) {
-
- preloader_editor->set_undo_redo(&get_undo_redo());
- ResourcePreloader * s = p_object->cast_to<ResourcePreloader>();
- if (!s)
- return;
-
- preloader_editor->edit(s);
-}
-
-bool ResourcePreloaderEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("ResourcePreloader");
-}
-
-void ResourcePreloaderEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- //preloader_editor->show();
- button->show();
- editor->make_bottom_panel_item_visible(preloader_editor);
- //preloader_editor->set_process(true);
- } else {
-
- if (preloader_editor->is_visible_in_tree())
- editor->hide_bottom_panel();
- button->hide();
- //preloader_editor->hide();
- //preloader_editor->set_process(false);
- }
-
-}
-
-ResourcePreloaderEditorPlugin::ResourcePreloaderEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- preloader_editor = memnew( ResourcePreloaderEditor );
- 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 );
-
-
-
-
-}
-
-
-ResourcePreloaderEditorPlugin::~ResourcePreloaderEditorPlugin()
-{
-}
-
-
diff --git a/tools/editor/plugins/resource_preloader_editor_plugin.h b/tools/editor/plugins/resource_preloader_editor_plugin.h
deleted file mode 100644
index 6990301ded..0000000000
--- a/tools/editor/plugins/resource_preloader_editor_plugin.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************************************/
-/* resource_preloader_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 RESOURCE_PRELOADER_EDITOR_PLUGIN_H
-#define RESOURCE_PRELOADER_EDITOR_PLUGIN_H
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/gui/tree.h"
-#include "scene/main/resource_preloader.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/dialogs.h"
-
-
-class ResourcePreloaderEditor : public PanelContainer {
-
- GDCLASS(ResourcePreloaderEditor, PanelContainer );
-
- Button *load;
- Button *_delete;
- Button *paste;
- Tree *tree;
- bool loading_scene;
-
-
- EditorFileDialog *file;
-
- AcceptDialog *dialog;
-
- ResourcePreloader *preloader;
-
-
- void _load_pressed();
- void _load_scene_pressed();
- void _files_load_request(const Vector<String>& p_paths);
- void _paste_pressed();
- void _delete_pressed();
- void _delete_confirm_pressed();
- void _update_library();
- void _item_edited();
-
- UndoRedo *undo_redo;
-
- Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
- bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
- void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
-
-
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
- void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
-
- void edit(ResourcePreloader* p_preloader);
- ResourcePreloaderEditor();
-};
-
-class ResourcePreloaderEditorPlugin : public EditorPlugin {
-
- GDCLASS( ResourcePreloaderEditorPlugin, EditorPlugin );
-
- ResourcePreloaderEditor *preloader_editor;
- EditorNode *editor;
- Button *button;
-
-public:
-
- virtual String get_name() const { return "ResourcePreloader"; }
- 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);
-
- ResourcePreloaderEditorPlugin(EditorNode *p_node);
- ~ResourcePreloaderEditorPlugin();
-
-};
-
-#endif // RESOURCE_PRELOADER_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/rich_text_editor_plugin.cpp b/tools/editor/plugins/rich_text_editor_plugin.cpp
deleted file mode 100644
index 8629d6ec8f..0000000000
--- a/tools/editor/plugins/rich_text_editor_plugin.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/*************************************************************************/
-/* rich_text_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "rich_text_editor_plugin.h"
-
-#include "os/file_access.h"
-#include "canvas_item_editor_plugin.h"
-
-void RichTextEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_FIXED_PROCESS: {
-
-
- } break;
- }
-
-}
-void RichTextEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- }
-
-}
-
-
-void RichTextEditor::_file_selected(const String& p_path) {
-
- CharString cs;
- FileAccess *fa = FileAccess::open(p_path,FileAccess::READ);
- if (!fa) {
- ERR_FAIL();
- }
-
- while(!fa->eof_reached())
- cs.push_back(fa->get_8());
- cs.push_back(0);
- memdelete(fa);
-
- String bbcode;
- bbcode.parse_utf8(&cs[0]);
- node->parse_bbcode(bbcode);
-
-}
-
-void RichTextEditor::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case PARSE_BBCODE: {
-
- file_dialog->popup_centered_ratio();
- } break;
- case CLEAR: {
-
- node->clear();
-
- } break;
-
- }
-}
-
-void RichTextEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_menu_option"),&RichTextEditor::_menu_option);
- ClassDB::bind_method(_MD("_file_selected"),&RichTextEditor::_file_selected);
-
-}
-
-void RichTextEditor::edit(Node *p_rich_text) {
-
- node=p_rich_text->cast_to<RichTextLabel>();
-
-}
-RichTextEditor::RichTextEditor() {
-
- options = memnew( MenuButton );
- //add_child(options);
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options);
- options->set_area_as_parent_rect();
-
- options->set_text("RichText");
- options->get_popup()->add_item(TTR("Parse BBCode"),PARSE_BBCODE);
- options->get_popup()->add_item(TTR("Clear"),CLEAR);
-
- options->get_popup()->connect("id_pressed", this,"_menu_option");
- file_dialog = memnew( EditorFileDialog );
- add_child(file_dialog);
- file_dialog->add_filter("*.txt");
- file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- file_dialog->connect("file_selected",this,"_file_selected");
-}
-
-
-void RichTextEditorPlugin::edit(Object *p_object) {
-
- rich_text_editor->edit(p_object->cast_to<Node>());
-}
-
-bool RichTextEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("RichTextLabel");
-}
-
-void RichTextEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- rich_text_editor->options->show();
- } else {
-
- rich_text_editor->options->hide();
- rich_text_editor->edit(NULL);
- }
-
-}
-
-RichTextEditorPlugin::RichTextEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- rich_text_editor = memnew( RichTextEditor );
- editor->get_viewport()->add_child(rich_text_editor);
-
- rich_text_editor->set_margin(MARGIN_LEFT,184);
- rich_text_editor->set_margin(MARGIN_RIGHT,230);
- rich_text_editor->set_margin(MARGIN_TOP,0);
- rich_text_editor->set_margin(MARGIN_BOTTOM,10);
-
- rich_text_editor->options->hide();
-
-}
-
-
-RichTextEditorPlugin::~RichTextEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/rich_text_editor_plugin.h b/tools/editor/plugins/rich_text_editor_plugin.h
deleted file mode 100644
index cf97d7517c..0000000000
--- a/tools/editor/plugins/rich_text_editor_plugin.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*************************************************************************/
-/* rich_text_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 RICH_TEXT_EDITOR_PLUGIN_H
-#define RICH_TEXT_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/gui/file_dialog.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class RichTextEditor : public Control {
-
- GDCLASS(RichTextEditor, Control );
-
- friend class RichTextEditorPlugin;
-
- enum {
-
- PARSE_BBCODE,
- CLEAR
- };
-
- Panel *panel;
- MenuButton *options;
- RichTextLabel *node;
- EditorFileDialog *file_dialog;
-
- void _file_selected(const String& p_path);
- void _menu_option(int p_option);
-
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- void edit(Node *p_rich_text);
- RichTextEditor();
-};
-
-class RichTextEditorPlugin : public EditorPlugin {
-
- GDCLASS( RichTextEditorPlugin, EditorPlugin );
-
- RichTextEditor *rich_text_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "RichText"; }
- 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);
-
- RichTextEditorPlugin(EditorNode *p_node);
- ~RichTextEditorPlugin();
-
-};
-
-#endif // RICH_TEXT_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/sample_editor_plugin.cpp b/tools/editor/plugins/sample_editor_plugin.cpp
deleted file mode 100644
index c333ba017f..0000000000
--- a/tools/editor/plugins/sample_editor_plugin.cpp
+++ /dev/null
@@ -1,451 +0,0 @@
-/*************************************************************************/
-/* sample_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "sample_editor_plugin.h"
-
-#if 0
-#include "io/resource_loader.h"
-#include "globals.h"
-#include "tools/editor/editor_settings.h"
-
-
-
-
-void SampleEditor::_gui_input(InputEvent p_event) {
-
-
-}
-
-void SampleEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- play->set_icon( get_icon("Play","EditorIcons") );
- stop->set_icon( get_icon("Stop","EditorIcons") );
- }
-
- if (p_what==NOTIFICATION_READY) {
-
- //get_scene()->connect("node_removed",this,"_node_removed");
-
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
- }
-}
-
-void SampleEditor::_play_pressed() {
-
- player->play("default",true);
- stop->set_pressed(false);
- play->set_pressed(true);
-}
-void SampleEditor::_stop_pressed() {
-
- player->stop_all();
- play->set_pressed(false);
-}
-
-void SampleEditor::generate_preview_texture(const Ref<Sample>& p_sample,Ref<ImageTexture> &p_texture) {
-
-
- PoolVector<uint8_t> data = p_sample->get_data();
-
- PoolVector<uint8_t> img;
- int w = p_texture->get_width();
- int h = p_texture->get_height();
- img.resize(w*h*3);
- PoolVector<uint8_t>::Write imgdata = img.write();
- uint8_t * imgw = imgdata.ptr();
- PoolVector<uint8_t>::Read sampledata = data.read();
- const uint8_t *sdata=sampledata.ptr();
-
- bool stereo = p_sample->is_stereo();
- bool _16=p_sample->get_format()==Sample::FORMAT_PCM16;
- int len = p_sample->get_length();
-
- if (len<1)
- return;
-
- if (p_sample->get_format()==Sample::FORMAT_IMA_ADPCM) {
-
-
- struct IMA_ADPCM_State {
-
- int16_t step_index;
- int32_t predictor;
- /* values at loop point */
- int16_t loop_step_index;
- int32_t loop_predictor;
- int32_t last_nibble;
- int32_t loop_pos;
- int32_t window_ofs;
- const uint8_t *ptr;
- } ima_adpcm;
-
- ima_adpcm.step_index=0;
- ima_adpcm.predictor=0;
- ima_adpcm.loop_step_index=0;
- ima_adpcm.loop_predictor=0;
- ima_adpcm.last_nibble=-1;
- ima_adpcm.loop_pos=0x7FFFFFFF;
- ima_adpcm.window_ofs=0;
- ima_adpcm.ptr=NULL;
-
-
- for(int i=0;i<w;i++) {
-
- float max[2]={-1e10,-1e10};
- float min[2]={1e10,1e10};
- int from = i*len/w;
- int to = (i+1)*len/w;
- if (to>=len)
- to=len-1;
-
- for(int j=from;j<to;j++) {
-
- while(j>ima_adpcm.last_nibble) {
-
- static const int16_t _ima_adpcm_step_table[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
- };
-
- static const int8_t _ima_adpcm_index_table[16] = {
- -1, -1, -1, -1, 2, 4, 6, 8,
- -1, -1, -1, -1, 2, 4, 6, 8
- };
-
- int16_t nibble,diff,step;
-
- ima_adpcm.last_nibble++;
- const uint8_t *src_ptr=sdata;
-
- int ofs = ima_adpcm.last_nibble>>1;
-
- if (stereo)
- ofs*=2;
-
- nibble = (ima_adpcm.last_nibble&1)?
- (src_ptr[ofs]>>4):(src_ptr[ofs]&0xF);
-
- step=_ima_adpcm_step_table[ima_adpcm.step_index];
-
- ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
- if (ima_adpcm.step_index<0)
- ima_adpcm.step_index=0;
- if (ima_adpcm.step_index>88)
- ima_adpcm.step_index=88;
-
- diff = step >> 3 ;
- if (nibble & 1)
- diff += step >> 2 ;
- if (nibble & 2)
- diff += step >> 1 ;
- if (nibble & 4)
- diff += step ;
- if (nibble & 8)
- diff = -diff ;
-
- ima_adpcm.predictor+=diff;
- if (ima_adpcm.predictor<-0x8000)
- ima_adpcm.predictor=-0x8000;
- else if (ima_adpcm.predictor>0x7FFF)
- ima_adpcm.predictor=0x7FFF;
-
-
- /* store loop if there */
- if (ima_adpcm.last_nibble==ima_adpcm.loop_pos) {
-
- ima_adpcm.loop_step_index = ima_adpcm.step_index;
- ima_adpcm.loop_predictor = ima_adpcm.predictor;
- }
-
- }
-
- float v=ima_adpcm.predictor/32767.0;
- if (v>max[0])
- max[0]=v;
- if (v<min[0])
- min[0]=v;
- }
-
- for(int j=0;j<h;j++) {
- float v = (j/(float)h) * 2.0 - 1.0;
- uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
- if (v>min[0] && v<max[0]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
- }
- }
- }
- } else {
- for(int i=0;i<w;i++) {
- // i trust gcc will optimize this loop
- float max[2]={-1e10,-1e10};
- float min[2]={1e10,1e10};
- int c=stereo?2:1;
- int from = uint64_t(i)*len/w;
- int to = (uint64_t(i)+1)*len/w;
- if (to>=len)
- to=len-1;
-
- if (_16) {
- const int16_t*src =(const int16_t*)sdata;
-
- for(int j=0;j<c;j++) {
-
- for(int k=from;k<=to;k++) {
-
- float v = src[uint64_t(k)*c+j]/32768.0;
- if (v>max[j])
- max[j]=v;
- if (v<min[j])
- min[j]=v;
- }
-
- }
- } else {
-
- const int8_t*src =(const int8_t*)sdata;
-
- for(int j=0;j<c;j++) {
-
- for(int k=from;k<=to;k++) {
-
- float v = src[uint64_t(k)*c+j]/128.0;
- if (v>max[j])
- max[j]=v;
- if (v<min[j])
- min[j]=v;
- }
-
- }
- }
-
- if (!stereo) {
- for(int j=0;j<h;j++) {
- float v = (j/(float)h) * 2.0 - 1.0;
- uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
- if (v>min[0] && v<max[0]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
- }
- }
- } else {
-
- for(int j=0;j<h;j++) {
-
- int half;
- float v;
- if (j<(h/2)) {
- half=0;
- v = (j/(float)(h/2)) * 2.0 - 1.0;
- } else {
- half=1;
- v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0;
- }
-
- uint8_t* imgofs = &imgw[(uint64_t(j)*w+i)*3];
- if (v>min[half] && v<max[half]) {
- imgofs[0]=255;
- imgofs[1]=150;
- imgofs[2]=80;
- } else {
- imgofs[0]=0;
- imgofs[1]=0;
- imgofs[2]=0;
- }
- }
-
- }
-
- }
- }
-
- imgdata = PoolVector<uint8_t>::Write();
-
-
- p_texture->set_data(Image(w,h,0,Image::FORMAT_RGB8,img));
-
-}
-
-void SampleEditor::_update_sample() {
-
- player->stop_all();
-
- generate_preview_texture(sample,peakdisplay);
- info_label->set_text(TTR("Length:")+" "+String::num(sample->get_length()/(float)sample->get_mix_rate(),2)+"s");
-
- if (library->has_sample("default"))
- library->remove_sample("default");
-
- library->add_sample("default",sample);
-}
-
-
-
-void SampleEditor::edit(Ref<Sample> p_sample) {
-
- sample=p_sample;
-
- if (!sample.is_null())
- _update_sample();
- else {
-
- hide();
- set_fixed_process(false);
- }
-
-}
-
-
-
-void SampleEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&SampleEditor::_gui_input);
- ClassDB::bind_method(_MD("_play_pressed"),&SampleEditor::_play_pressed);
- ClassDB::bind_method(_MD("_stop_pressed"),&SampleEditor::_stop_pressed);
-
-}
-
-SampleEditor::SampleEditor() {
-
- player = memnew(SamplePlayer);
- add_child(player);
- add_style_override("panel", get_stylebox("panel","Panel"));
- library = Ref<SampleLibrary>(memnew(SampleLibrary));
- player->set_sample_library(library);
- sample_texframe = memnew( TextureRect );
- add_child(sample_texframe);
- sample_texframe->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
- sample_texframe->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
- sample_texframe->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,30);
- sample_texframe->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
-
- info_label = memnew( Label );
- sample_texframe->add_child(info_label);
- info_label->set_area_as_parent_rect();
- info_label->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,15);
- info_label->set_margin(MARGIN_BOTTOM,4);
- info_label->set_margin(MARGIN_RIGHT,4);
- info_label->set_align(Label::ALIGN_RIGHT);
-
-
- play = memnew( Button );
-
- play->set_pos(Point2( 5, 5 ));
- play->set_size( Size2(1,1 ) );
- play->set_toggle_mode(true);
- add_child(play);
-
- stop = memnew( Button );
-
- stop->set_pos(Point2( 35, 5 ));
- stop->set_size( Size2(1,1 ) );
- stop->set_toggle_mode(true);
- add_child(stop);
-
- peakdisplay=Ref<ImageTexture>( memnew( ImageTexture) );
- peakdisplay->create( EDITOR_DEF("editors/sample_editor/preview_width",512),EDITOR_DEF("editors/sample_editor/preview_height",128),Image::FORMAT_RGB8);
- sample_texframe->set_expand(true);
- sample_texframe->set_texture(peakdisplay);
-
- play->connect("pressed", this,"_play_pressed");
- stop->connect("pressed", this,"_stop_pressed");
-
- set_custom_minimum_size(Size2(1,150)*EDSCALE);
-
-}
-
-
-void SampleEditorPlugin::edit(Object *p_object) {
-
- Sample * s = p_object->cast_to<Sample>();
- if (!s)
- return;
-
- sample_editor->edit(Ref<Sample>(s));
-}
-
-bool SampleEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Sample");
-}
-
-void SampleEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- sample_editor->show();
- //sample_editor->set_process(true);
- } else {
-
- sample_editor->hide();
- //sample_editor->set_process(false);
- }
-
-}
-
-SampleEditorPlugin::SampleEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- sample_editor = memnew( SampleEditor );
- add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,sample_editor);
- sample_editor->hide();
-
-
-
-}
-
-
-SampleEditorPlugin::~SampleEditorPlugin()
-{
-}
-
-#endif
diff --git a/tools/editor/plugins/sample_editor_plugin.h b/tools/editor/plugins/sample_editor_plugin.h
deleted file mode 100644
index 651cd14a84..0000000000
--- a/tools/editor/plugins/sample_editor_plugin.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*************************************************************************/
-/* sample_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SAMPLE_EDITOR_PLUGIN_H
-#define SAMPLE_EDITOR_PLUGIN_H
-
-#if 0
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/audio/sample_player.h"
-#include "scene/resources/sample.h"
-#include "scene/resources/sample_library.h"
-
-
-class SampleEditor : public Panel {
-
- GDCLASS(SampleEditor, Panel );
-
-
- SamplePlayer *player;
- Label *info_label;
- Ref<ImageTexture> peakdisplay;
- Ref<Sample> sample;
- Ref<SampleLibrary> library;
- TextureRect *sample_texframe;
- Button *stop;
- Button *play;
-
- void _play_pressed();
- void _stop_pressed();
- void _update_sample();
-
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
- static void generate_preview_texture(const Ref<Sample>& p_sample,Ref<ImageTexture> &p_texture);
- void edit(Ref<Sample> p_sample);
- SampleEditor();
-};
-
-
-class SampleEditorPlugin : public EditorPlugin {
-
- GDCLASS( SampleEditorPlugin, EditorPlugin );
-
- SampleEditor *sample_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "Sample"; }
- 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);
-
- SampleEditorPlugin(EditorNode *p_node);
- ~SampleEditorPlugin();
-
-};
-
-#endif
-
-#endif // SAMPLE_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp
deleted file mode 100644
index 116c5d11b6..0000000000
--- a/tools/editor/plugins/sample_library_editor_plugin.cpp
+++ /dev/null
@@ -1,546 +0,0 @@
-/*************************************************************************/
-/* sample_library_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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. */
-/*************************************************************************/
-
-#if 0
-#include "sample_library_editor_plugin.h"
-
-#include "io/resource_loader.h"
-#include "globals.h"
-#include "tools/editor/editor_settings.h"
-#include "scene/main/viewport.h"
-#include "sample_editor_plugin.h"
-
-
-void SampleLibraryEditor::_gui_input(InputEvent p_event) {
-
-
-}
-
-void SampleLibraryEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_PROCESS) {
- if (is_playing && !player->is_active()) {
- TreeItem *tl=last_sample_playing->cast_to<TreeItem>();
- tl->set_button(0,0,get_icon("Play","EditorIcons"));
- is_playing = false;
- set_process(false);
- }
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- load->set_icon( get_icon("Folder","EditorIcons") );
- load->set_tooltip(TTR("Open Sample File(s)"));
- }
-
- if (p_what==NOTIFICATION_READY) {
-
- //NodePath("/root")->connect("node_removed", this,"_node_removed",Vector<Variant>(),true);
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
- }
-}
-
-void SampleLibraryEditor::_file_load_request(const PoolVector<String>& p_path) {
-
-
- for(int i=0;i<p_path.size();i++) {
-
- String path = p_path[i];
- Ref<Sample> sample = ResourceLoader::load(path,"Sample");
- if (sample.is_null()) {
- dialog->set_text(TTR("ERROR: Couldn't load sample!"));
- dialog->set_title(TTR("Error!"));
- //dialog->get_cancel()->set_text("Close");
- dialog->get_ok()->set_text(TTR("Close"));
- dialog->popup_centered_minsize();
- return; ///beh should show an error i guess
- }
- String basename = path.get_file().get_basename();
- String name=basename;
- int counter=0;
- while(sample_library->has_sample(name)) {
- counter++;
- name=basename+"_"+itos(counter);
- }
-
- undo_redo->create_action(TTR("Add Sample"));
- undo_redo->add_do_method(sample_library.operator->(),"add_sample",name,sample);
- undo_redo->add_undo_method(sample_library.operator->(),"remove_sample",name);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
- }
-}
-
-void SampleLibraryEditor::_load_pressed() {
-
- file->popup_centered_ratio();
-
-}
-
-void SampleLibraryEditor::_button_pressed(Object *p_item,int p_column, int p_id) {
-
- TreeItem *ti=p_item->cast_to<TreeItem>();
- String name = ti->get_text(0);
-
- if (p_column==0) { // Play/Stop
-
- String btn_type;
- if(!is_playing) {
- is_playing = true;
- btn_type = TTR("Stop");
- player->play(name,true);
- last_sample_playing = p_item;
- set_process(true);
- } else {
- player->stop_all();
- if(last_sample_playing != p_item){
- TreeItem *tl=last_sample_playing->cast_to<TreeItem>();
- tl->set_button(p_column,0,get_icon("Play","EditorIcons"));
- btn_type = TTR("Stop");
- player->play(name,true);
- last_sample_playing = p_item;
- } else {
- btn_type = TTR("Play");
- is_playing = false;
- }
- }
- ti->set_button(p_column,0,get_icon(btn_type,"EditorIcons"));
- } else if (p_column==1) { // Edit
-
- get_tree()->get_root()->get_child(0)->call("_resource_selected",sample_library->get_sample(name));
- } else if (p_column==5) { // Delete
-
- ti->select(0);
- _delete_pressed();
- }
-
-
-}
-
-
-
-
-
-void SampleLibraryEditor::_item_edited() {
-
- if (!tree->get_selected())
- return;
-
- TreeItem *s = tree->get_selected();
-
- if (tree->get_selected_column()==0) { // Name
- // renamed
- String old_name=s->get_metadata(0);
- String new_name=s->get_text(0);
- if (old_name==new_name)
- return;
-
- if (new_name=="" || new_name.find("\\")!=-1 || new_name.find("/")!=-1 || sample_library->has_sample(new_name)) {
-
- s->set_text(0,old_name);
- return;
- }
-
- Ref<Sample> samp = sample_library->get_sample(old_name);
- undo_redo->create_action(TTR("Rename Sample"));
- undo_redo->add_do_method(sample_library.operator->(),"remove_sample",old_name);
- undo_redo->add_do_method(sample_library.operator->(),"add_sample",new_name,samp);
- undo_redo->add_undo_method(sample_library.operator->(),"remove_sample",new_name);
- undo_redo->add_undo_method(sample_library.operator->(),"add_sample",old_name,samp);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
- } else if (tree->get_selected_column()==3) { // Volume dB
-
- StringName n = s->get_text(0);
- sample_library->sample_set_volume_db(n,s->get_range(3));
-
- } else if (tree->get_selected_column()==4) { // Pitch scale
-
- StringName n = s->get_text(0);
- sample_library->sample_set_pitch_scale(n,s->get_range(4));
-
- }
-
-
-}
-
-void SampleLibraryEditor::_delete_pressed() {
-
- if (!tree->get_selected())
- return;
-
- String to_remove = tree->get_selected()->get_text(0);
- undo_redo->create_action(TTR("Delete Sample"));
- undo_redo->add_do_method(sample_library.operator->(),"remove_sample",to_remove);
- undo_redo->add_undo_method(sample_library.operator->(),"add_sample",to_remove,sample_library->get_sample(to_remove));
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-}
-
-
-void SampleLibraryEditor::_update_library() {
-
- player->stop_all();
-
- tree->clear();
- tree->set_hide_root(true);
- TreeItem *root = tree->create_item(NULL);
-
- List<StringName> names;
- sample_library->get_sample_list(&names);
- names.sort_custom<StringName::AlphCompare>();
-
- for(List<StringName>::Element *E=names.front();E;E=E->next()) {
-
- TreeItem *ti = tree->create_item(root);
-
- // Name + Play/Stop
- ti->set_cell_mode(0,TreeItem::CELL_MODE_STRING);
- ti->set_editable(0,true);
- ti->set_selectable(0,true);
- ti->set_text(0,E->get());
- ti->set_metadata(0,E->get());
- ti->add_button(0,get_icon("Play","EditorIcons"));
-
- Ref<Sample> smp = sample_library->get_sample(E->get());
-
- // Preview/edit
- Ref<ImageTexture> preview( memnew( ImageTexture ));
- preview->create(128,16,Image::FORMAT_RGB8);
- SampleEditor::generate_preview_texture(smp,preview);
- ti->set_cell_mode(1,TreeItem::CELL_MODE_ICON);
- ti->set_selectable(1,false);
- ti->set_editable(1,false);
- ti->set_icon(1,preview);
- ti->add_button(1,get_icon("Edit","EditorIcons"));
-
- // Format
- ti->set_cell_mode(2,TreeItem::CELL_MODE_STRING);
- ti->set_editable(2,false);
- ti->set_selectable(2,false);
- ti->set_text(2,String()+(smp->get_format()==Sample::FORMAT_PCM16?TTR("16 Bits")+", ":(smp->get_format()==Sample::FORMAT_PCM8?TTR("8 Bits")+", ":"IMA-ADPCM,"))+(smp->is_stereo()?TTR("Stereo"):TTR("Mono")));
-
- // Volume dB
- ti->set_cell_mode(3,TreeItem::CELL_MODE_RANGE);
- ti->set_range_config(3,-60,24,0.01);
- ti->set_selectable(3,true);
- ti->set_editable(3,true);
- ti->set_range(3,sample_library->sample_get_volume_db(E->get()));
-
- // Pitch scale
- ti->set_cell_mode(4,TreeItem::CELL_MODE_RANGE);
- ti->set_range_config(4,0.01,100,0.01);
- ti->set_selectable(4,true);
- ti->set_editable(4,true);
- ti->set_range(4,sample_library->sample_get_pitch_scale(E->get()));
-
- // Delete
- ti->set_cell_mode(5,TreeItem::CELL_MODE_STRING);
- ti->add_button(5,get_icon("Remove","EditorIcons"));
-
- }
-
- //player->add_sample("default",sample);
-}
-
-
-
-void SampleLibraryEditor::edit(Ref<SampleLibrary> p_sample_library) {
-
- sample_library=p_sample_library;
-
-
- if (!sample_library.is_null()) {
- player->set_sample_library(sample_library);
- _update_library();
- } else {
-
- hide();
- }
-
-}
-
-Variant SampleLibraryEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- TreeItem*ti =tree->get_item_at_pos(p_point);
- if (!ti)
- return Variant();
-
- String name = ti->get_metadata(0);
-
- RES res = sample_library->get_sample(name);
- if (!res.is_valid())
- return Variant();
-
- return EditorNode::get_singleton()->drag_resource(res,p_from);
-
-
-}
-
-bool SampleLibraryEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
-
-
-
- Dictionary d = p_data;
-
- if (!d.has("type"))
- return false;
-
- if (d.has("from") && (Object*)(d["from"])==tree)
- return false;
-
- if (String(d["type"])=="resource" && d.has("resource")) {
- RES r=d["resource"];
-
- Ref<Sample> sample = r;
-
- if (sample.is_valid()) {
-
- return true;
- }
- }
-
-
- if (String(d["type"])=="files") {
-
- Vector<String> files = d["files"];
-
- if (files.size()==0)
- return false;
-
- for(int i=0;i<files.size();i++) {
- String file = files[0];
- String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
-
- if (ftype!="Sample") {
- return false;
- }
-
- }
-
- return true;
-
- }
- return false;
-}
-
-void SampleLibraryEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
-
- if (!can_drop_data_fw(p_point,p_data,p_from))
- return;
-
- Dictionary d = p_data;
-
- if (!d.has("type"))
- return;
-
-
- if (String(d["type"])=="resource" && d.has("resource")) {
- RES r=d["resource"];
-
- Ref<Sample> sample = r;
-
- if (sample.is_valid()) {
-
- String basename;
- if (sample->get_name()!="") {
- basename=sample->get_name();
- } else if (sample->get_path().is_resource_file()) {
- basename = sample->get_path().get_basename();
- } else {
- basename="Sample";
- }
-
- String name=basename;
- int counter=0;
- while(sample_library->has_sample(name)) {
- counter++;
- name=basename+"_"+itos(counter);
- }
-
- undo_redo->create_action(TTR("Add Sample"));
- undo_redo->add_do_method(sample_library.operator->(),"add_sample",name,sample);
- undo_redo->add_undo_method(sample_library.operator->(),"remove_sample",name);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
- }
- }
-
-
- if (String(d["type"])=="files") {
-
- PoolVector<String> files = d["files"];
-
- _file_load_request(files);
-
- }
-
-}
-
-
-void SampleLibraryEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&SampleLibraryEditor::_gui_input);
- ClassDB::bind_method(_MD("_load_pressed"),&SampleLibraryEditor::_load_pressed);
- ClassDB::bind_method(_MD("_item_edited"),&SampleLibraryEditor::_item_edited);
- ClassDB::bind_method(_MD("_delete_pressed"),&SampleLibraryEditor::_delete_pressed);
- ClassDB::bind_method(_MD("_file_load_request"),&SampleLibraryEditor::_file_load_request);
- ClassDB::bind_method(_MD("_update_library"),&SampleLibraryEditor::_update_library);
- ClassDB::bind_method(_MD("_button_pressed"),&SampleLibraryEditor::_button_pressed);
-
- ClassDB::bind_method(_MD("get_drag_data_fw"), &SampleLibraryEditor::get_drag_data_fw);
- ClassDB::bind_method(_MD("can_drop_data_fw"), &SampleLibraryEditor::can_drop_data_fw);
- ClassDB::bind_method(_MD("drop_data_fw"), &SampleLibraryEditor::drop_data_fw);
-
-}
-
-SampleLibraryEditor::SampleLibraryEditor() {
-
- player = memnew(SamplePlayer);
- add_child(player);
- add_style_override("panel", get_stylebox("panel","Panel"));
-
-
- load = memnew( Button );
- load->set_pos(Point2( 5, 5 ));
- load->set_size( Size2(1,1 ) );
- add_child(load);
-
- file = memnew( EditorFileDialog );
- add_child(file);
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("Sample",&extensions);
- for(int i=0;i<extensions.size();i++)
- file->add_filter("*."+extensions[i]);
- file->set_mode(EditorFileDialog::MODE_OPEN_FILES);
-
- tree = memnew( Tree );
- tree->set_columns(6);
- add_child(tree);
- tree->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
- tree->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
- tree->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,30);
- tree->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
- tree->set_column_titles_visible(true);
- tree->set_column_title(0,TTR("Name"));
- tree->set_column_title(1,TTR("Preview"));
- tree->set_column_title(2,TTR("Format"));
- tree->set_column_title(3,"dB");
- tree->set_column_title(4,TTR("Pitch"));
- tree->set_column_title(5,"");
-
- tree->set_column_min_width(1,150);
- tree->set_column_min_width(2,100);
- tree->set_column_min_width(3,50);
- tree->set_column_min_width(4,50);
- tree->set_column_min_width(5,32);
- tree->set_column_expand(1,false);
- tree->set_column_expand(2,false);
- tree->set_column_expand(3,false);
- tree->set_column_expand(4,false);
- tree->set_column_expand(5,false);
-
- tree->set_drag_forwarding(this);
-
- dialog = memnew( ConfirmationDialog );
- add_child( dialog );
-
- tree->connect("button_pressed",this,"_button_pressed");
- load->connect("pressed", this,"_load_pressed");
- file->connect("files_selected", this,"_file_load_request");
- tree->connect("item_edited", this,"_item_edited");
-
- is_playing = false;
-}
-
-
-void SampleLibraryEditorPlugin::edit(Object *p_object) {
-
- sample_library_editor->set_undo_redo(&get_undo_redo());
- SampleLibrary * s = p_object->cast_to<SampleLibrary>();
- if (!s)
- return;
-
- sample_library_editor->edit(Ref<SampleLibrary>(s));
-}
-
-bool SampleLibraryEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("SampleLibrary");
-}
-
-void SampleLibraryEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- //sample_library_editor->show();
- button->show();
- editor->make_bottom_panel_item_visible(sample_library_editor);
- //sample_library_editor->set_process(true);
- } else {
-
- if (sample_library_editor->is_visible_in_tree())
- editor->hide_bottom_panel();
- button->hide();
-
- //sample_library_editor->set_process(false);
- }
-
-}
-
-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_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();
-
-
-
-}
-
-
-SampleLibraryEditorPlugin::~SampleLibraryEditorPlugin()
-{
-}
-#endif
diff --git a/tools/editor/plugins/sample_library_editor_plugin.h b/tools/editor/plugins/sample_library_editor_plugin.h
deleted file mode 100644
index 35028df859..0000000000
--- a/tools/editor/plugins/sample_library_editor_plugin.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*************************************************************************/
-/* sample_library_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SAMPLE_LIBRARY_EDITOR_PLUGIN_H
-#define SAMPLE_LIBRARY_EDITOR_PLUGIN_H
-
-
-#if 0
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/audio/sample_player.h"
-#include "scene/resources/sample.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/dialogs.h"
-
-
-class SampleLibraryEditor : public Panel {
-
- GDCLASS(SampleLibraryEditor, Panel );
-
-
-
- SamplePlayer *player;
- Ref<SampleLibrary> sample_library;
- Button *load;
- Tree *tree;
- bool is_playing;
- Object *last_sample_playing;
-
- EditorFileDialog *file;
-
- ConfirmationDialog *dialog;
-
-
- void _load_pressed();
- void _file_load_request(const PoolVector<String>& p_path);
- void _delete_pressed();
- void _update_library();
- void _item_edited();
-
- UndoRedo *undo_redo;
-
- void _button_pressed(Object *p_item,int p_column, int p_id);
-
- Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
- bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
- void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
-
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
- void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
- void edit(Ref<SampleLibrary> p_sample);
- SampleLibraryEditor();
-};
-
-class SampleLibraryEditorPlugin : public EditorPlugin {
-
- GDCLASS( SampleLibraryEditorPlugin, EditorPlugin );
-
- SampleLibraryEditor *sample_library_editor;
- EditorNode *editor;
- Button *button;
-
-public:
-
- virtual String get_name() const { return "SampleLibrary"; }
- 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);
-
- SampleLibraryEditorPlugin(EditorNode *p_node);
- ~SampleLibraryEditorPlugin();
-
-};
-
-#endif
-#endif // SAMPLE_LIBRARY_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/sample_player_editor_plugin.cpp b/tools/editor/plugins/sample_player_editor_plugin.cpp
deleted file mode 100644
index dd6450bfe7..0000000000
--- a/tools/editor/plugins/sample_player_editor_plugin.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*************************************************************************/
-/* sample_player_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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. */
-/*************************************************************************/
-
-#if 0
-#include "sample_player_editor_plugin.h"
-
-
-#include "scene/resources/sample_library.h"
-
-
-void SamplePlayerEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- play->set_icon( get_icon("Play","EditorIcons") );
- stop->set_icon( get_icon("Stop","EditorIcons") );
- }
-
-}
-
-void SamplePlayerEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- }
-
-}
-
-void SamplePlayerEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_play"),&SamplePlayerEditor::_play);
- ClassDB::bind_method(_MD("_stop"),&SamplePlayerEditor::_stop);
-
-}
-
-
-void SamplePlayerEditor::_play() {
-
- if (!node)
- return;
- if (samples->get_item_count()<=0)
- return;
-
- node->call("play",samples->get_item_text( samples->get_selected() ));
- stop->set_pressed(false);
- play->set_pressed(true);
-}
-
-void SamplePlayerEditor::_stop() {
-
- if (!node)
- return;
- if (samples->get_item_count()<=0)
- return;
-
- node->call("stop_all");
- print_line("STOP ALL!!");
- stop->set_pressed(true);
- play->set_pressed(false);
-
-}
-
-
-void SamplePlayerEditor::_update_sample_library() {
-
- samples->clear();
- Ref<SampleLibrary> sl = node->call("get_sample_library");
- if (sl.is_null()) {
- samples->add_item("<NO SAMPLE LIBRARY>");
- return; //no sample library;
- }
-
- List<StringName> samplenames;
- sl->get_sample_list(&samplenames);
- samplenames.sort_custom<StringName::AlphCompare>();
- for(List<StringName>::Element *E=samplenames.front();E;E=E->next()) {
- samples->add_item(E->get());
- }
-
-}
-
-void SamplePlayerEditor::edit(Node *p_sample_player) {
-
- node=p_sample_player;
- if (node) {
- _update_sample_library();
- }
-
-}
-SamplePlayerEditor::SamplePlayerEditor() {
-
-
- play = memnew( Button );
-
- play->set_pos(Point2( 5, 5 ));
- play->set_toggle_mode(true);
- play->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,250);
- play->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,230);
- play->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
- play->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
-
- add_child(play);
-
- stop = memnew( Button );
-
- stop->set_pos(Point2( 35, 5 ));
- stop->set_toggle_mode(true);
- stop->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,220);
- stop->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,200);
- stop->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
- stop->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
- add_child(stop);
-
- samples = memnew( OptionButton );
- samples->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,190);
- samples->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,5);
- samples->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
- samples->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
- add_child(samples);
-
- play->connect("pressed", this,"_play");
- stop->connect("pressed", this,"_stop");
-
-}
-
-
-void SamplePlayerEditorPlugin::edit(Object *p_object) {
-
- sample_player_editor->edit(p_object->cast_to<Node>());
-}
-
-bool SamplePlayerEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("SamplePlayer2D") || p_object->is_class("SamplePlayer") || p_object->is_class("SpatialSamplePlayer");
-}
-
-void SamplePlayerEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- sample_player_editor->show();
- sample_player_editor->set_fixed_process(true);
- } else {
-
- sample_player_editor->hide();
- sample_player_editor->set_fixed_process(false);
- sample_player_editor->edit(NULL);
- }
-
-}
-
-SamplePlayerEditorPlugin::SamplePlayerEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- sample_player_editor = memnew( SamplePlayerEditor );
- editor->get_viewport()->add_child(sample_player_editor);
-
- sample_player_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
- sample_player_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
- sample_player_editor->set_margin(MARGIN_LEFT,250);
- sample_player_editor->set_margin(MARGIN_RIGHT,0);
- sample_player_editor->set_margin(MARGIN_TOP,0);
- sample_player_editor->set_margin(MARGIN_BOTTOM,10);
-
-
- sample_player_editor->hide();
-
-
-
-}
-
-
-SamplePlayerEditorPlugin::~SamplePlayerEditorPlugin()
-{
-}
-
-
-#endif
diff --git a/tools/editor/plugins/sample_player_editor_plugin.h b/tools/editor/plugins/sample_player_editor_plugin.h
deleted file mode 100644
index ba1684497c..0000000000
--- a/tools/editor/plugins/sample_player_editor_plugin.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*************************************************************************/
-/* sample_player_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SAMPLE_PLAYER_EDITOR_PLUGIN_H
-#define SAMPLE_PLAYER_EDITOR_PLUGIN_H
-
-#if 0
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/spatial_sample_player.h"
-#include "scene/gui/option_button.h"
-#include "scene/audio/sample_player.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class SamplePlayerEditor : public Control {
-
- GDCLASS(SamplePlayerEditor, Control );
-
- Panel *panel;
- Button * play;
- Button * stop;
- OptionButton *samples;
- Node *node;
-
-
- void _update_sample_library();
- void _play();
- void _stop();
-
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- void edit(Node *p_sample_player);
- SamplePlayerEditor();
-};
-
-class SamplePlayerEditorPlugin : public EditorPlugin {
-
- GDCLASS( SamplePlayerEditorPlugin, EditorPlugin );
-
- SamplePlayerEditor *sample_player_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "SamplePlayer"; }
- 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);
-
- SamplePlayerEditorPlugin(EditorNode *p_node);
- ~SamplePlayerEditorPlugin();
-
-};
-
-#endif
-#endif // SAMPLE_PLAYER_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
deleted file mode 100644
index 5f97fce4e7..0000000000
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ /dev/null
@@ -1,2487 +0,0 @@
-/*************************************************************************/
-/* script_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "script_editor_plugin.h"
-
-#include "tools/editor/editor_settings.h"
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "os/keyboard.h"
-#include "os/os.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/script_editor_debugger.h"
-#include "globals.h"
-#include "os/file_access.h"
-#include "scene/main/viewport.h"
-#include "os/keyboard.h"
-#include "os/input.h"
-
-/*** SCRIPT EDITOR ****/
-
-
-
-void ScriptEditorBase::_bind_methods() {
-
- ADD_SIGNAL(MethodInfo("name_changed"));
- ADD_SIGNAL(MethodInfo("request_help_search",PropertyInfo(Variant::STRING,"topic")));
- ADD_SIGNAL(MethodInfo("request_open_script_at_line",PropertyInfo(Variant::OBJECT,"script"),PropertyInfo(Variant::INT,"line")));
- ADD_SIGNAL(MethodInfo("request_save_history"));
- ADD_SIGNAL(MethodInfo("go_to_help",PropertyInfo(Variant::STRING,"what")));
-
-}
-
-static bool _can_open_in_editor(Script* p_script) {
-
- String path = p_script->get_path();
-
- if (path.find("::")!=-1) {
- //refuse handling this if it can't be edited
-
- bool valid=false;
- for(int i=0;i<EditorNode::get_singleton()->get_editor_data().get_edited_scene_count();i++) {
- if (path.begins_with(EditorNode::get_singleton()->get_editor_data().get_scene_path(i))) {
- valid=true;
- break;
- }
- }
-
- return valid;
- }
-
- return true;
-}
-
-
-class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache {
-
-
- struct Cache {
- uint64_t time_loaded;
- RES cache;
- };
-
- Map<String,Cache> cached;
-
-
-public:
-
- uint64_t max_time_cache;
- int max_cache_size;
-
- void cleanup() {
-
- List< Map<String,Cache>::Element * > to_clean;
-
-
- Map<String,Cache>::Element *I=cached.front();
- while(I) {
- if ((OS::get_singleton()->get_ticks_msec()-I->get().time_loaded)>max_time_cache) {
- to_clean.push_back(I);
- }
- I=I->next();
- }
-
- while(to_clean.front()) {
- cached.erase(to_clean.front()->get());
- to_clean.pop_front();
- }
- }
-
- RES get_cached_resource(const String& p_path) {
-
- Map<String,Cache>::Element *E=cached.find(p_path);
- if (!E) {
-
- Cache c;
- c.cache=ResourceLoader::load(p_path);
- E=cached.insert(p_path,c);
- }
-
- E->get().time_loaded=OS::get_singleton()->get_ticks_msec();
-
- if (cached.size()>max_cache_size) {
- uint64_t older;
- Map<String,Cache>::Element *O=cached.front();
- older=O->get().time_loaded;
- Map<String,Cache>::Element *I=O;
- while(I) {
- if (I->get().time_loaded<older) {
- older = I->get().time_loaded;
- O=I;
- }
- I=I->next();
- }
-
- if (O!=E) {//should never heppane..
- cached.erase(O);
- }
- }
-
- return E->get().cache;
- }
-
-
- EditorScriptCodeCompletionCache() {
-
- max_cache_size=128;
- max_time_cache=5*60*1000; //minutes, five
- }
-
-};
-
-#define SORT_SCRIPT_LIST
-
-void ScriptEditorQuickOpen::popup(const Vector<String>& p_functions, bool p_dontclear) {
-
- popup_centered_ratio(0.6);
- if (p_dontclear)
- search_box->select_all();
- else
- search_box->clear();
- search_box->grab_focus();
- functions=p_functions;
- _update_search();
-
-
-}
-
-
-void ScriptEditorQuickOpen::_text_changed(const String& p_newtext) {
-
- _update_search();
-}
-
-void ScriptEditorQuickOpen::_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 ) ) {
-
- search_options->call("_gui_input",p_ie);
- search_box->accept_event();
- }
-
-}
-
-
-
-void ScriptEditorQuickOpen::_update_search() {
-
-
- search_options->clear();
- TreeItem *root = search_options->create_item();
-
- for(int i=0;i<functions.size();i++) {
-
- String file = functions[i];
- if ((search_box->get_text()=="" || file.findn(search_box->get_text())!=-1)) {
-
- TreeItem *ti = search_options->create_item(root);
- ti->set_text(0,file);
- if (root->get_children()==ti)
- ti->select(0);
-
- }
- }
-
- get_ok()->set_disabled(root->get_children()==NULL);
-
-}
-
-void ScriptEditorQuickOpen::_confirmed() {
-
- TreeItem *ti = search_options->get_selected();
- if (!ti)
- return;
- int line = ti->get_text(0).get_slice(":",1).to_int();
-
- emit_signal("goto_line",line-1);
- hide();
-}
-
-void ScriptEditorQuickOpen::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- connect("confirmed",this,"_confirmed");
-
-
- }
-}
-
-
-
-
-void ScriptEditorQuickOpen::_bind_methods() {
-
- ClassDB::bind_method(_MD("_text_changed"),&ScriptEditorQuickOpen::_text_changed);
- ClassDB::bind_method(_MD("_confirmed"),&ScriptEditorQuickOpen::_confirmed);
- ClassDB::bind_method(_MD("_sbox_input"),&ScriptEditorQuickOpen::_sbox_input);
-
- ADD_SIGNAL(MethodInfo("goto_line",PropertyInfo(Variant::INT,"line")));
-
-}
-
-
-ScriptEditorQuickOpen::ScriptEditorQuickOpen() {
-
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
- search_box = memnew( LineEdit );
- vbc->add_margin_child(TTR("Search:"),search_box);
- search_box->connect("text_changed",this,"_text_changed");
- search_box->connect("gui_input",this,"_sbox_input");
- search_options = memnew( Tree );
- vbc->add_margin_child(TTR("Matches:"),search_options,true);
- get_ok()->set_text(TTR("Open"));
- get_ok()->set_disabled(true);
- register_text_enter(search_box);
- set_hide_on_ok(false);
- search_options->connect("item_activated",this,"_confirmed");
- search_options->set_hide_root(true);
-}
-
-
-/////////////////////////////////
-
-ScriptEditor *ScriptEditor::script_editor=NULL;
-
-/*** SCRIPT EDITOR ******/
-
-String ScriptEditor::_get_debug_tooltip(const String&p_text,Node *_se) {
-
- //ScriptEditorBase *se=_se->cast_to<ScriptEditorBase>();
-
- String val = debugger->get_var_value(p_text);
- if (val!=String()) {
- return p_text+": "+val;
- } else {
-
- return String();
- }
-}
-
-void ScriptEditor::_breaked(bool p_breaked,bool p_can_debug) {
-
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), !(p_breaked && p_can_debug));
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), !(p_breaked && p_can_debug) );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), p_breaked );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), !p_breaked );
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se) {
-
- continue;
- }
-
- se->set_debugger_active(p_breaked);
- }
-
-}
-
-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) {
- editor->push_item(p_script.operator->());
-}
-
-
-void ScriptEditor::_goto_script_line2(int p_line) {
-
- int selected = tab_container->get_current_tab();
- if (selected<0 || selected>=tab_container->get_child_count())
- return;
-
- ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
- if (!current)
- return;
-
- current->goto_line(p_line);
-
-}
-
-void ScriptEditor::_goto_script_line(REF p_script,int p_line) {
-
-
- editor->push_item(p_script.ptr());
-
- int selected = tab_container->get_current_tab();
- if (selected<0 || selected>=tab_container->get_child_count())
- return;
-
- ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
- if (!current)
- return;
-
- current->goto_line(p_line,true);
-
-}
-
-
-void ScriptEditor::_update_history_arrows() {
-
- script_back->set_disabled( history_pos<=0 );
- script_forward->set_disabled( history_pos>=history.size()-1 );
-}
-
-void ScriptEditor::_save_history() {
-
-
- if (history_pos>=0 && history_pos<history.size() && history[history_pos].control==tab_container->get_current_tab_control()) {
-
- Node *n = tab_container->get_current_tab_control();
-
- if (n->cast_to<ScriptEditorBase>()) {
-
- history[history_pos].state=n->cast_to<ScriptEditorBase>()->get_edit_state();
- }
- if (n->cast_to<EditorHelp>()) {
-
- history[history_pos].state=n->cast_to<EditorHelp>()->get_scroll();
- }
- }
-
- history.resize(history_pos+1);
- ScriptHistory sh;
- sh.control=tab_container->get_current_tab_control();
- sh.state=Variant();
-
- history.push_back(sh);
- history_pos++;
-
- _update_history_arrows();
-}
-
-
-void ScriptEditor::_go_to_tab(int p_idx) {
-
- Node *cn = tab_container->get_child(p_idx);
- if (!cn)
- return;
- Control *c = cn->cast_to<Control>();
- if (!c)
- return;
-
- if (history_pos>=0 && history_pos<history.size() && history[history_pos].control==tab_container->get_current_tab_control()) {
-
- Node *n = tab_container->get_current_tab_control();
-
- if (n->cast_to<ScriptEditorBase>()) {
-
- history[history_pos].state=n->cast_to<ScriptEditorBase>()->get_edit_state();
- }
- if (n->cast_to<EditorHelp>()) {
-
- history[history_pos].state=n->cast_to<EditorHelp>()->get_scroll();
- }
- }
-
- history.resize(history_pos+1);
- ScriptHistory sh;
- sh.control=c;
- sh.state=Variant();
-
- history.push_back(sh);
- history_pos++;
-
-
- tab_container->set_current_tab(p_idx);
-
- c = tab_container->get_current_tab_control();
-
- if (c->cast_to<ScriptEditorBase>()) {
-
- script_name_label->set_text(c->cast_to<ScriptEditorBase>()->get_name());
- script_icon->set_texture(c->cast_to<ScriptEditorBase>()->get_icon());
- if (is_visible_in_tree())
- c->cast_to<ScriptEditorBase>()->ensure_focus();
- }
- if (c->cast_to<EditorHelp>()) {
-
- script_name_label->set_text(c->cast_to<EditorHelp>()->get_class());
- script_icon->set_texture(get_icon("Help","EditorIcons"));
- if (is_visible_in_tree())
- c->cast_to<EditorHelp>()->set_focused();
- }
-
-
-
- c->set_meta("__editor_pass",++edit_pass);
- _update_history_arrows();
- _update_script_colors();
- _update_selected_editor_menu();
-}
-
-void ScriptEditor::_close_tab(int p_idx, bool p_save) {
-
- int selected = p_idx;
- if (selected<0 || selected>=tab_container->get_child_count())
- return;
-
- Node *tselected = tab_container->get_child(selected);
- ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
- if (current) {
- if (p_save) {
- apply_scripts();
- }
- if (current->get_edit_menu()) {
- memdelete(current->get_edit_menu());
- }
- }
-
- //remove from history
- history.resize(history_pos+1);
-
- for(int i=0;i<history.size();i++) {
- if (history[i].control==tselected) {
- history.remove(i);
- i--;
- history_pos--;
- }
- }
-
- if (history_pos>=history.size()) {
- history_pos=history.size()-1;
- }
-
- int idx = tab_container->get_current_tab();
- memdelete(tselected);
- if (idx>=tab_container->get_child_count())
- idx=tab_container->get_child_count()-1;
- if (idx>=0) {
-
- if (history_pos>=0) {
- idx = history[history_pos].control->get_index();
- }
- tab_container->set_current_tab(idx);
-
- //script_list->select(idx);
- }
-
-
- _update_history_arrows();
-
-
-
- _update_script_names();
- _save_layout();
-}
-
-void ScriptEditor::_close_current_tab() {
-
- _close_tab(tab_container->get_current_tab());
-
-}
-
-void ScriptEditor::_close_discard_current_tab(const String& p_str) {
- _close_tab(tab_container->get_current_tab(), false);
- erase_tab_confirm->hide();
-}
-
-void ScriptEditor::_close_docs_tab() {
-
- int child_count = tab_container->get_child_count();
- for (int i = child_count-1; i>=0; i--) {
-
- EditorHelp *se = tab_container->get_child(i)->cast_to<EditorHelp>();
-
- if (se) {
- _close_tab(i);
- }
-
- }
-
-}
-
-void ScriptEditor::_close_all_tabs() {
-
- int child_count = tab_container->get_child_count();
- for (int i = child_count-1; i>=0; i--) {
-
- tab_container->set_current_tab(i);
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
-
- if (se) {
-
- // Maybe there are unsaved changes
- if (se->is_unsaved()) {
- _ask_close_current_unsaved_tab(se);
- continue;
- }
-
- }
-
- _close_current_tab();
- }
-
-}
-
-void ScriptEditor::_ask_close_current_unsaved_tab(ScriptEditorBase *current) {
- erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\"");
- erase_tab_confirm->popup_centered_minsize();
-}
-
-
-void ScriptEditor::_resave_scripts(const String& p_str) {
-
- apply_scripts();
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se)
- continue;
-
-
- Ref<Script> script = se->get_edited_script();
-
- if (script->get_path()=="" || script->get_path().find("local://")!=-1 || script->get_path().find("::")!=-1)
- continue; //internal script, who cares
-
- if (trim_trailing_whitespace_on_save) {
- se->trim_trailing_whitespace();
- }
- editor->save_resource(script);
- se->tag_saved_version();
- }
-
- disk_changed->hide();
-
-}
-
-void ScriptEditor::_reload_scripts(){
-
-
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se) {
-
- continue;
- }
-
-
- Ref<Script> script = se->get_edited_script();
-
- 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());
-
- //printf("last date: %lli vs date: %lli\n",last_date,date);
- if (last_date==date) {
- continue;
- }
-
-
- Ref<Script> rel_script = ResourceLoader::load(script->get_path(),script->get_class(),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->reload();
- se->reload_text();
-
-
- }
-
- disk_changed->hide();
- _update_script_names();
-
-}
-
-
-
-void ScriptEditor::_res_saved_callback(const Ref<Resource>& p_res) {
-
-
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se) {
-
- continue;
- }
-
-
- Ref<Script> script = se->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==p_res) {
-
- se->tag_saved_version();
- }
-
- }
-
- _update_script_names();
-
-
- if (!pending_auto_reload && auto_reload_running_scripts) {
- call_deferred("_live_auto_reload_running_scripts");
- pending_auto_reload=true;
- }
-}
-
-void ScriptEditor::_live_auto_reload_running_scripts() {
- pending_auto_reload=false;
- debugger->reload_scripts();
-}
-
-
-bool ScriptEditor::_test_script_times_on_disk(Ref<Script> p_for_script) {
-
-
- disk_changed_list->clear();
- TreeItem *r = disk_changed_list->create_item();
- disk_changed_list->set_hide_root(true);
-
- bool need_ask=false;
- bool need_reload=false;
- bool use_autoreload=bool(EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change",false));
-
-
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (se) {
-
- Ref<Script> script = se->get_edited_script();
-
- if (p_for_script.is_valid() && p_for_script!=script)
- continue;
-
- 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());
-
- //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());
-
- if (!use_autoreload || se->is_unsaved()) {
- need_ask=true;
- }
- need_reload=true;
- //r->set_metadata(0,);
- }
- }
- }
-
-
-
- if (need_reload) {
- if (!need_ask) {
- script_editor->_reload_scripts();
- need_reload=false;
- } else {
- disk_changed->call_deferred("popup_centered_ratio",0.5);
- }
- }
-
- return need_reload;
-}
-
-
-void ScriptEditor::_file_dialog_action(String p_file) {
-
- switch (file_dialog_option) {
- case FILE_SAVE_THEME_AS: {
- if(!EditorSettings::get_singleton()->save_text_editor_theme_as(p_file)) {
- editor->show_warning(TTR("Error while saving theme"), TTR("Error saving"));
- }
- } break;
- case FILE_IMPORT_THEME: {
- if(!EditorSettings::get_singleton()->import_text_editor_theme(p_file)) {
- editor->show_warning(TTR("Error importing theme"), TTR("Error importing"));
- }
- } break;
- }
- file_dialog_option = -1;
-}
-
-void ScriptEditor::_menu_option(int p_option) {
-
-
- switch(p_option) {
- case FILE_NEW: {
- script_create_dialog->config("Node", ".gd");
- script_create_dialog->popup_centered(Size2(300, 300)*EDSCALE);
- } break;
- case FILE_OPEN: {
-
- editor->open_resource("Script");
- return;
- } break;
- case FILE_SAVE_ALL: {
-
- if (_test_script_times_on_disk())
- return;
-
- save_all_scripts();
- } break;
- case FILE_IMPORT_THEME: {
- file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- file_dialog_option = FILE_IMPORT_THEME;
- file_dialog->clear_filters();
- file_dialog->add_filter("*.tet");
- file_dialog->popup_centered_ratio();
- file_dialog->set_title(TTR("Import Theme"));
- } break;
- case FILE_RELOAD_THEME: {
- EditorSettings::get_singleton()->load_text_editor_theme();
- } break;
- case FILE_SAVE_THEME: {
- if(!EditorSettings::get_singleton()->save_text_editor_theme()) {
- editor->show_warning(TTR("Error while saving theme"), TTR("Error saving"));
- }
- } break;
- case FILE_SAVE_THEME_AS: {
- file_dialog->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- file_dialog_option = FILE_SAVE_THEME_AS;
- file_dialog->clear_filters();
- file_dialog->add_filter("*.tet");
- file_dialog->set_current_path(EditorSettings::get_singleton()->get_settings_path() + "/text_editor_themes/" + EditorSettings::get_singleton()->get("text_editor/theme/color_theme"));
- file_dialog->popup_centered_ratio();
- file_dialog->set_title(TTR("Save Theme As.."));
- } break;
- case SEARCH_HELP: {
-
- help_search_dialog->popup();
- } break;
- case SEARCH_CLASSES: {
-
- String current;
-
- if (tab_container->get_tab_count()>0) {
- EditorHelp *eh = tab_container->get_child( tab_container->get_current_tab() )->cast_to<EditorHelp>();
- if (eh) {
- current=eh->get_class();
- }
- }
-
- help_index->popup();
-
- if (current!="") {
- help_index->call_deferred("select_class",current);
- }
- } break;
- case SEARCH_WEBSITE: {
-
- OS::get_singleton()->shell_open("http://docs.godotengine.org/");
- } break;
-
- case WINDOW_NEXT: {
-
- _history_forward();
- } break;
- 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;
- }
-
-
- int selected = tab_container->get_current_tab();
- if (selected<0 || selected>=tab_container->get_child_count())
- return;
-
- ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
- if (current) {
-
- switch(p_option) {
- case FILE_NEW: {
- script_create_dialog->config("Node", ".gd");
- script_create_dialog->popup_centered(Size2(300, 300)*EDSCALE);
- } break;
- case FILE_SAVE: {
-
- if (_test_script_times_on_disk())
- return;
-
- if (trim_trailing_whitespace_on_save)
- current->trim_trailing_whitespace();
- editor->save_resource( current->get_edited_script() );
-
- } break;
- case FILE_SAVE_AS: {
-
- current->trim_trailing_whitespace();
- editor->push_item(current->get_edited_script()->cast_to<Object>());
- editor->save_resource_as( current->get_edited_script() );
-
- } break;
-
- case FILE_TOOL_RELOAD:
- case FILE_TOOL_RELOAD_SOFT: {
-
- current->reload(p_option==FILE_TOOL_RELOAD_SOFT);
-
- } break;
-
- case FILE_CLOSE: {
- if (current->is_unsaved()) {
- _ask_close_current_unsaved_tab(current);
- } else {
- _close_current_tab();
- }
- } break;
- case CLOSE_DOCS: {
- _close_docs_tab();
- } break;
- case CLOSE_ALL: {
- _close_all_tabs();
- } break;
- case DEBUG_NEXT: {
-
- if (debugger)
- debugger->debug_next();
- } break;
- case DEBUG_STEP: {
-
- if (debugger)
- debugger->debug_step();
-
- } break;
- case DEBUG_BREAK: {
-
- if (debugger)
- debugger->debug_break();
-
- } break;
- case DEBUG_CONTINUE: {
-
- if (debugger)
- debugger->debug_continue();
-
- } break;
- case WINDOW_MOVE_LEFT: {
-
- if (tab_container->get_current_tab()>0) {
- tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()-1);
- script_list->call_deferred("select",tab_container->get_current_tab()-1);
- tab_container->move_child(current,tab_container->get_current_tab()-1);
- _update_script_names();
- }
- } break;
- case WINDOW_MOVE_RIGHT: {
-
- if (tab_container->get_current_tab()<tab_container->get_child_count()-1) {
- tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()+1);
- script_list->call_deferred("select",tab_container->get_current_tab()+1);
- tab_container->move_child(current,tab_container->get_current_tab()+1);
- _update_script_names();
- }
-
-
- } break;
-
- default: {
-
- if (p_option>=WINDOW_SELECT_BASE) {
-
- tab_container->set_current_tab(p_option-WINDOW_SELECT_BASE);
- script_list->select(p_option-WINDOW_SELECT_BASE);
-
- }
- }
- }
- }
-
- EditorHelp *help = tab_container->get_current_tab_control()->cast_to<EditorHelp>();
- if (help) {
-
- switch(p_option) {
-
- case HELP_SEARCH_FIND: {
- help->popup_search();
- } break;
- case HELP_SEARCH_FIND_NEXT: {
- help->search_again();
- } break;
- case FILE_CLOSE: {
- _close_current_tab();
- } break;
- case CLOSE_DOCS: {
- _close_docs_tab();
- } break;
- case CLOSE_ALL: {
- _close_all_tabs();
- } break;
-
-
- }
- }
-
-
-}
-
-void ScriptEditor::_tab_changed(int p_which) {
-
- ensure_select_current();
-}
-
-void ScriptEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- editor->connect("play_pressed",this,"_editor_play");
- editor->connect("pause_pressed",this,"_editor_pause");
- editor->connect("stop_pressed",this,"_editor_stop");
- editor->connect("script_add_function_request",this,"_add_callback");
- editor->connect("resource_saved",this,"_res_saved_callback");
- script_list->connect("item_selected",this,"_script_selected");
- script_split->connect("dragged",this,"_script_split_dragged");
- autosave_timer->connect("timeout",this,"_autosave_scripts");
- {
- float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
- if (autosave_time>0) {
- autosave_timer->set_wait_time(autosave_time);
- autosave_timer->start();
- } else {
- autosave_timer->stop();
- }
- }
-
- EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed");
- help_search->set_icon(get_icon("Help","EditorIcons"));
- site_search->set_icon(get_icon("Godot","EditorIcons"));
- class_search->set_icon(get_icon("ClassList","EditorIcons"));
-
- script_forward->set_icon(get_icon("Forward","EditorIcons"));
- script_back->set_icon(get_icon("Back","EditorIcons"));
-
-
-
-
- }
-
- if (p_what==NOTIFICATION_READY) {
-
- get_tree()->connect("tree_changed",this,"_tree_changed");
- editor->connect("request_help",this,"_request_help");
- }
-
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
- editor->disconnect("play_pressed",this,"_editor_play");
- editor->disconnect("pause_pressed",this,"_editor_pause");
- editor->disconnect("stop_pressed",this,"_editor_stop");
-
- }
-
- if (p_what==MainLoop::NOTIFICATION_WM_FOCUS_IN) {
-
- _test_script_times_on_disk();
- _update_modified_scripts_for_external_editor();
- }
-
- if (p_what==NOTIFICATION_PROCESS) {
-
- }
-
-}
-
-bool ScriptEditor::can_take_away_focus() const {
-
- int selected = tab_container->get_current_tab();
- if (selected<0 || selected>=tab_container->get_child_count())
- return true;
-
- ScriptEditorBase *current = tab_container->get_child(selected)->cast_to<ScriptEditorBase>();
- if (!current)
- return true;
-
-
- return current->can_lose_focus_on_node_selection();
-
-}
-
-void ScriptEditor::close_builtin_scripts_from_scene(const String& p_scene) {
-
-
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
-
- if (se) {
-
- Ref<Script> script = se->get_edited_script();
- if (!script.is_valid())
- continue;
-
- if (script->get_path().find("::")!=-1 && script->get_path().begins_with(p_scene)) { //is an internal script and belongs to scene being closed
- _close_tab(i);
- i--;
-
- }
- }
-
- }
-
-
-}
-
-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) {
-
- if (p_node->get_script()==p_script)
- return p_node;
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- const Node *result = _find_node_with_script(p_node->get_child(i),p_script);
- if (result)
- return result;
- }
-
- return NULL;
-}
-
-Dictionary ScriptEditor::get_state() const {
-
-
- //apply_scripts();
-
- Dictionary state;
-#if 0
- Array paths;
- int open=-1;
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptTextEditor *se = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
- if (!se)
- continue;
-
-
- Ref<Script> script = se->get_edited_script();
- if (script->get_path()!="" && script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) {
-
- paths.push_back(script->get_path());
- } else {
-
-
- const Node *owner = _find_node_with_script(get_tree()->get_root(),script.get_ref_ptr());
- if (owner)
- paths.push_back(owner->get_path());
-
- }
-
- if (i==tab_container->get_current_tab())
- open=i;
- }
-
- if (paths.size())
- state["sources"]=paths;
- if (open!=-1)
- state["current"]=open;
-
-#endif
- return state;
-}
-void ScriptEditor::set_state(const Dictionary& p_state) {
-
-#if 0
- print_line("attempt set state: "+String(Variant(p_state)));
-
- if (!p_state.has("sources"))
- return; //bleh
-
- Array sources = p_state["sources"];
- for(int i=0;i<sources.size();i++) {
-
- Variant source=sources[i];
-
- Ref<Script> script;
-
- if (source.get_type()==Variant::NODE_PATH) {
-
-
- Node *owner=get_tree()->get_root()->get_node(source);
- if (!owner)
- continue;
-
- script = owner->get_script();
- } else if (source.get_type()==Variant::STRING) {
-
-
- script = ResourceLoader::load(source,"Script");
- }
-
-
- if (script.is_null()) //ah well..
- continue;
-
- editor->call("_resource_selected",script);
- }
-
- if (p_state.has("current")) {
- tab_container->set_current_tab(p_state["current"]);
- }
-#endif
-
-}
-void ScriptEditor::clear() {
-#if 0
- List<ScriptTextEditor*> stes;
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptTextEditor *se = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
- if (!se)
- continue;
- stes.push_back(se);
-
- }
-
- while(stes.size()) {
-
- memdelete(stes.front()->get());
- stes.pop_front();
- }
-
- int idx = tab_container->get_current_tab();
- if (idx>=tab_container->get_child_count())
- idx=tab_container->get_child_count()-1;
- if (idx>=0) {
- tab_container->set_current_tab(idx);
- script_list->select( script_list->find_metadata(idx) );
- }
-
-#endif
-
-
-}
-
-
-void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
-
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se)
- continue;
-
- List<int> bpoints;
- se->get_breakpoints(&bpoints);
- Ref<Script> script = se->get_edited_script();
- String base = script->get_path();
- ERR_CONTINUE( base.begins_with("local://") || base=="" );
-
- for(List<int>::Element *E=bpoints.front();E;E=E->next()) {
-
- p_breakpoints->push_back(base+":"+itos(E->get()+1));
- }
- }
-
-}
-
-
-
-
-
-void ScriptEditor::ensure_focus_current() {
-
- if (!is_inside_tree())
- return;
-
- int cidx = tab_container->get_current_tab();
- if (cidx<0 || cidx>=tab_container->get_tab_count());
- Control *c = tab_container->get_child(cidx)->cast_to<Control>();
- if (!c)
- return;
- ScriptEditorBase *se = c->cast_to<ScriptEditorBase>();
- if (!se)
- return;
- se->ensure_focus();
-}
-
-void ScriptEditor::_script_selected(int p_idx) {
-
- grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(1); //amazing hack, simply amazing
-
- _go_to_tab(script_list->get_item_metadata(p_idx));
- grab_focus_block=false;
-}
-
-void ScriptEditor::ensure_select_current() {
-
-
- if (tab_container->get_child_count() && tab_container->get_current_tab()>=0) {
-
- Node *current = tab_container->get_child(tab_container->get_current_tab());
-
-
- ScriptEditorBase *se = current->cast_to<ScriptEditorBase>();
- if (se) {
-
- Ref<Script> script = se->get_edited_script();
-
- if (!grab_focus_block && is_visible_in_tree())
- se->ensure_focus();
-
-
- //edit_menu->show();
- //search_menu->show();
-
-
- }
-
- EditorHelp *eh = current->cast_to<EditorHelp>();
-
- if (eh) {
- //edit_menu->hide();
- //search_menu->hide();
- //script_search_menu->show();
-
- }
- }
-
- _update_selected_editor_menu();
-
-
-
-}
-
-void ScriptEditor::_find_scripts(Node* p_base, Node* p_current, Set<Ref<Script> > &used) {
- if (p_current!=p_base && p_current->get_owner()!=p_base)
- return;
-
- if (p_current->get_script_instance()) {
- Ref<Script> scr = p_current->get_script();
- if (scr.is_valid())
- used.insert(scr);
- }
-
- for(int i=0;i<p_current->get_child_count();i++) {
- _find_scripts(p_base,p_current->get_child(i),used);
- }
-
-}
-
-struct _ScriptEditorItemData {
-
- String name;
- String sort_key;
- Ref<Texture> icon;
- int index;
- String tooltip;
- bool used;
- int category;
-
-
- bool operator<(const _ScriptEditorItemData& id) const {
-
- return category==id.category?sort_key<id.sort_key:category<id.category;
- }
-
-};
-
-
-void ScriptEditor::_update_script_colors() {
-
- bool script_temperature_enabled = EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_enabled");
- bool highlight_current = EditorSettings::get_singleton()->get("text_editor/open_scripts/highlight_current_script");
-
- int hist_size = EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_history_size");
- Color hot_color=EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_hot_color");
- Color cold_color=EditorSettings::get_singleton()->get("text_editor/open_scripts/script_temperature_cold_color");
-
- for(int i=0;i<script_list->get_item_count();i++) {
-
- int c = script_list->get_item_metadata(i);
- Node *n = tab_container->get_child(c);
- if (!n)
- continue;
-
- script_list->set_item_custom_bg_color(i,Color(0,0,0,0));
-
- bool current = tab_container->get_current_tab() == c;
- if (current && highlight_current) {
- script_list->set_item_custom_bg_color(i, EditorSettings::get_singleton()->get("text_editor/open_scripts/current_script_background_color"));
-
- } else if (script_temperature_enabled) {
-
- if (!n->has_meta("__editor_pass")) {
- continue;
- }
-
- int pass=n->get_meta("__editor_pass");
- int h = edit_pass - pass;
- if (h>hist_size) {
- continue;
- }
- int non_zero_hist_size = ( hist_size == 0 ) ? 1 : hist_size;
- float v = Math::ease((edit_pass-pass)/float(non_zero_hist_size),0.4);
-
- script_list->set_item_custom_bg_color(i,hot_color.linear_interpolate(cold_color,v));
- }
- }
-}
-
-void ScriptEditor::_update_script_names() {
-
- if (restoring_layout)
- return;
-
- waiting_update_names=false;
- Set<Ref<Script> > used;
- Node* edited = EditorNode::get_singleton()->get_edited_scene();
- if (edited) {
- _find_scripts(edited,edited,used);
- }
-
- script_list->clear();
- bool split_script_help = EditorSettings::get_singleton()->get("text_editor/open_scripts/group_help_pages");
- ScriptSortBy sort_by = (ScriptSortBy) (int) EditorSettings::get_singleton()->get("text_editor/open_scripts/sort_scripts_by");
- ScriptListName display_as = (ScriptListName) (int) EditorSettings::get_singleton()->get("text_editor/open_scripts/list_script_names_as");
-
- Vector<_ScriptEditorItemData> sedata;
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (se) {
-
- String name = se->get_name();
- Ref<Texture> icon = se->get_icon();
- String path = se->get_edited_script()->get_path();
-
- _ScriptEditorItemData sd;
- sd.icon=icon;
- sd.name=name;
- sd.tooltip=path;
- sd.index=i;
- sd.used=used.has(se->get_edited_script());
- sd.category=0;
-
- switch (sort_by) {
- case SORT_BY_NAME: {
- sd.sort_key=name.to_lower();
- } break;
- case SORT_BY_PATH: {
- sd.sort_key=path;
- } break;
- }
-
- switch (display_as) {
- case DISPLAY_NAME: {
- sd.name=name;
- } break;
- case DISPLAY_DIR_AND_NAME: {
- if (!path.get_base_dir().get_file().empty()) {
- sd.name=path.get_base_dir().get_file() + "/" + name;
- } else {
- sd.name=name;
- }
- } break;
- case DISPLAY_FULL_PATH: {
- sd.name=path;
- } break;
- }
-
-
- sedata.push_back(sd);
- }
-
- EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
- if (eh) {
-
- String name = eh->get_class();
- Ref<Texture> icon = get_icon("Help","EditorIcons");
- String tooltip = name+" Class Reference";
-
- _ScriptEditorItemData sd;
- sd.icon=icon;
- sd.name=name;
- sd.sort_key=name;
- sd.tooltip=tooltip;
- sd.index=i;
- sd.used=false;
- sd.category=split_script_help?1:0;
- sedata.push_back(sd);
-
- }
-
- }
-
- sedata.sort();
-
- for(int i=0;i<sedata.size();i++) {
-
- script_list->add_item(sedata[i].name,sedata[i].icon);
- int index = script_list->get_item_count()-1;
- script_list->set_item_tooltip(index,sedata[i].tooltip);
- script_list->set_item_metadata(index,sedata[i].index);
- if (sedata[i].used) {
-
- script_list->set_item_custom_bg_color(index,Color(88/255.0,88/255.0,60/255.0));
- }
- if (tab_container->get_current_tab()==sedata[i].index) {
- script_list->select(index);
- script_name_label->set_text(sedata[i].name);
- script_icon->set_texture(sedata[i].icon);
-
- }
- }
-
- _update_script_colors();
-
-
-
-
-}
-
-
-
-void ScriptEditor::edit(const Ref<Script>& p_script, bool p_grab_focus) {
-
- if (p_script.is_null())
- return;
-
- // refuse to open built-in if scene is not loaded
-
-
-
-
- // see if already has it
-
- bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
-
- if (p_script->get_path().is_resource_file() && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
-
- String path = EditorSettings::get_singleton()->get("text_editor/external/exec_path");
- String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags");
- List<String> args;
- flags=flags.strip_edges();
- if (flags!=String()) {
- Vector<String> flagss = flags.split(" ",false);
- for(int i=0;i<flagss.size();i++)
- args.push_back(flagss[i]);
- }
-
- args.push_back(GlobalConfig::get_singleton()->globalize_path(p_script->get_path()));
- Error err = OS::get_singleton()->execute(path,args,false);
- if (err==OK)
- return;
- WARN_PRINT("Couldn't open external text editor, using internal");
- }
-
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se)
- continue;
-
- if (se->get_edited_script()==p_script) {
-
- if (open_dominant || !EditorNode::get_singleton()->is_changing_scene()) {
- if (tab_container->get_current_tab()!=i) {
- _go_to_tab(i);
- script_list->select( script_list->find_metadata(i) );
- }
- if (is_visible_in_tree())
- se->ensure_focus();
- }
- return;
- }
- }
-
- // doesn't have it, make a new one
-
- ScriptEditorBase *se;
-
- for(int i=script_editor_func_count-1;i>=0;i--) {
- se = script_editor_funcs[i](p_script);
- if (se)
- break;
- }
- ERR_FAIL_COND(!se);
- tab_container->add_child(se);
-
- se->set_edited_script(p_script);
- se->set_tooltip_request_func("_get_debug_tooltip",this);
- if (se->get_edit_menu()) {
- se->get_edit_menu()->hide();
- menu_hb->add_child(se->get_edit_menu());
- menu_hb->move_child(se->get_edit_menu(),1);
- }
-
-
- if (p_grab_focus) {
- _go_to_tab(tab_container->get_tab_count()-1);
- }
-
-
-
-
-
- _update_script_names();
- _save_layout();
- se->connect("name_changed",this,"_update_script_names");
- se->connect("request_help_search",this,"_help_search");
- se->connect("request_open_script_at_line",this,"_goto_script_line");
- se->connect("go_to_help",this,"_help_class_goto");
- se->connect("request_save_history",this,"_save_history");
-
-
-
-
- //test for modification, maybe the script was not edited but was loaded
-
- _test_script_times_on_disk(p_script);
- _update_modified_scripts_for_external_editor(p_script);
-
-}
-
-void ScriptEditor::save_all_scripts() {
-
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se)
- continue;
-
-
- if (!se->is_unsaved())
- continue;
-
- if (trim_trailing_whitespace_on_save) {
- se->trim_trailing_whitespace();
- }
-
- Ref<Script> script = se->get_edited_script();
- if (script.is_valid())
- se->apply_code();
-
- if (script->get_path()!="" && script->get_path().find("local://")==-1 &&script->get_path().find("::")==-1) {
- //external script, save it
-
- editor->save_resource(script);
- //ResourceSaver::save(script->get_path(),script);
-
- }
-
- }
-
- _update_script_names();
-
-}
-
-void ScriptEditor::apply_scripts() const {
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se)
- continue;
- se->apply_code();
- }
-
-}
-
-void ScriptEditor::_editor_play() {
-
- debugger->start();
- debug_menu->get_popup()->grab_focus();
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), false );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
-
- //debugger_gui->start_listening(Globals::get_singleton()->get("debug/debug_port"));
-}
-
-void ScriptEditor::_editor_pause() {
-
-
-}
-void ScriptEditor::_editor_stop() {
-
- debugger->stop();
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), true );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se) {
-
- continue;
- }
-
- se->set_debugger_active(false);
- }
-}
-
-
-void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const PoolStringArray& p_args) {
-
- //print_line("add callback! hohoho"); kinda sad to remove this
- ERR_FAIL_COND(!p_obj);
- Ref<Script> script = p_obj->get_script();
- ERR_FAIL_COND( !script.is_valid() );
-
- editor->push_item(script.ptr());
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se)
- continue;
- if (se->get_edited_script()!=script)
- continue;
-
- se->add_callback(p_function,p_args);
-
- _go_to_tab(i);
-
- script_list->select( script_list->find_metadata(i) );
-
- break;
-
- }
-
-}
-
-void ScriptEditor::_save_layout() {
-
- if (restoring_layout) {
- return;
- }
-
- editor->save_layout();
-}
-
-void ScriptEditor::_editor_settings_changed() {
-
- trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/files/trim_trailing_whitespace_on_save");
- float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs");
- if (autosave_time>0) {
- autosave_timer->set_wait_time(autosave_time);
- autosave_timer->start();
- } else {
- autosave_timer->stop();
- }
-
- if (current_theme == "") {
- current_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
- } else if (current_theme != EditorSettings::get_singleton()->get("text_editor/theme/color_theme")) {
- current_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
- EditorSettings::get_singleton()->load_text_editor_theme();
- }
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (!se)
- continue;
-
- se->update_settings();
- }
- _update_script_colors();
- _update_script_names();
-
- ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save",true));
-
-}
-
-void ScriptEditor::_autosave_scripts() {
-
- save_all_scripts();
-}
-
-void ScriptEditor::_tree_changed() {
-
- if (waiting_update_names)
- return;
-
- waiting_update_names=true;
- call_deferred("_update_script_names");
-}
-
-void ScriptEditor::_script_split_dragged(float) {
-
- _save_layout();
-}
-
-void ScriptEditor::_unhandled_input(const InputEvent& p_event) {
- if (p_event.key.pressed || !is_visible_in_tree()) return;
- if (ED_IS_SHORTCUT("script_editor/next_script", p_event)) {
- int next_tab = script_list->get_current() + 1;
- next_tab %= script_list->get_item_count();
- _go_to_tab(script_list->get_item_metadata(next_tab));
- _update_script_names();
- }
- if (ED_IS_SHORTCUT("script_editor/prev_script", p_event)) {
- int next_tab = script_list->get_current() - 1;
- next_tab = next_tab >= 0 ? next_tab : script_list->get_item_count() - 1;
- _go_to_tab(script_list->get_item_metadata(next_tab));
- _update_script_names();
- }
-}
-
-void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
-
- if (!bool(EDITOR_DEF("text_editor/files/restore_scripts_on_load",true))) {
- return;
- }
-
- if (!p_layout->has_section_key("ScriptEditor","open_scripts") && !p_layout->has_section_key("ScriptEditor","open_help"))
- return;
-
- Array scripts = p_layout->get_value("ScriptEditor","open_scripts");
- Array helps;
- if (p_layout->has_section_key("ScriptEditor","open_help"))
- helps=p_layout->get_value("ScriptEditor","open_help");
-
- restoring_layout=true;
-
- for(int i=0;i<scripts.size();i++) {
-
- String path = scripts[i];
- if (!FileAccess::exists(path))
- continue;
- Ref<Script> scr = ResourceLoader::load(path);
- if (scr.is_valid()) {
- edit(scr);
- }
- }
-
- for(int i=0;i<helps.size();i++) {
-
- String path = helps[i];
- _help_class_open(path);
- }
-
- for(int i=0;i<tab_container->get_child_count();i++) {
- tab_container->get_child(i)->set_meta("__editor_pass",Variant());
- }
-
-
- if (p_layout->has_section_key("ScriptEditor","split_offset")) {
- script_split->set_split_offset(p_layout->get_value("ScriptEditor","split_offset"));
- }
-
- restoring_layout=false;
-
- _update_script_names();
-}
-
-void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
-
- Array scripts;
- Array helps;
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (se) {
-
- String path = se->get_edited_script()->get_path();
- if (!path.is_resource_file())
- continue;
-
- scripts.push_back(path);
- }
-
- EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
-
- if (eh) {
-
- helps.push_back(eh->get_class());
- }
-
-
- }
-
- p_layout->set_value("ScriptEditor","open_scripts",scripts);
- p_layout->set_value("ScriptEditor","open_help",helps);
- p_layout->set_value("ScriptEditor","split_offset",script_split->get_split_offset());
-}
-
-
-void ScriptEditor::_help_class_open(const String& p_class) {
-
- if (p_class=="")
- return;
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
-
- if (eh && eh->get_class()==p_class) {
-
- _go_to_tab(i);
- _update_script_names();
- return;
- }
- }
-
- EditorHelp * eh = memnew( EditorHelp );
-
-
- eh->set_name(p_class);
- tab_container->add_child(eh);
- _go_to_tab(tab_container->get_tab_count()-1);
- eh->go_to_class(p_class,0);
- eh->connect("go_to_help",this,"_help_class_goto");
- _update_script_names();
- _save_layout();
-}
-
-void ScriptEditor::_help_class_goto(const String& p_desc) {
-
- String cname=p_desc.get_slice(":",1);
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
-
- if (eh && eh->get_class()==cname) {
-
- _go_to_tab(i);
- eh->go_to_help(p_desc);
- _update_script_names();
- return;
- }
- }
-
- EditorHelp * eh = memnew( EditorHelp );
-
- eh->set_name(cname);
- tab_container->add_child(eh);
- _go_to_tab(tab_container->get_tab_count()-1);
- eh->go_to_help(p_desc);
- eh->connect("go_to_help",this,"_help_class_goto");
- _update_script_names();
- _save_layout();
-}
-
-void ScriptEditor::_update_selected_editor_menu() {
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- bool current = tab_container->get_current_tab() == i;
-
- ScriptEditorBase *se = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
- if (se && se->get_edit_menu()) {
-
- if (current)
- se->get_edit_menu()->show();
- else
- se->get_edit_menu()->hide();
- }
-
- }
-
- EditorHelp *eh=tab_container->get_current_tab_control()->cast_to<EditorHelp>();
- if (eh) {
- script_search_menu->show();
- } else {
- script_search_menu->hide();
- }
-}
-
-void ScriptEditor::_update_history_pos(int p_new_pos) {
-
- Node *n = tab_container->get_current_tab_control();
-
- if (n->cast_to<ScriptEditorBase>()) {
-
- history[history_pos].state=n->cast_to<ScriptEditorBase>()->get_edit_state();
- }
- if (n->cast_to<EditorHelp>()) {
-
- history[history_pos].state=n->cast_to<EditorHelp>()->get_scroll();
- }
-
- history_pos=p_new_pos;
- tab_container->set_current_tab(history[history_pos].control->get_index());
-
- n = history[history_pos].control;
-
- if (n->cast_to<ScriptEditorBase>()) {
-
- n->cast_to<ScriptEditorBase>()->set_edit_state(history[history_pos].state);
- n->cast_to<ScriptEditorBase>()->ensure_focus();
- }
-
- if (n->cast_to<EditorHelp>()) {
-
- n->cast_to<EditorHelp>()->set_scroll(history[history_pos].state);
- n->cast_to<EditorHelp>()->set_focused();
- }
-
- n->set_meta("__editor_pass",++edit_pass);
- _update_script_names();
- _update_history_arrows();
- _update_selected_editor_menu();
-
-}
-
-void ScriptEditor::_history_forward() {
-
- if (history_pos<history.size()-1) {
- _update_history_pos(history_pos+1);
- }
-}
-
-void ScriptEditor::_history_back(){
-
- if (history_pos>0) {
- _update_history_pos(history_pos-1);
- }
-
-}
-void ScriptEditor::set_scene_root_script( Ref<Script> p_script ) {
-
- bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
-
- if (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")))
- return;
-
- if (open_dominant && p_script.is_valid() && _can_open_in_editor(p_script.ptr())) {
- edit(p_script);
- }
-}
-
-bool ScriptEditor::script_go_to_method(Ref<Script> p_script, const String& p_method) {
-
-
- for (int i=0;i<tab_container->get_child_count();i++) {
- ScriptEditorBase *current = tab_container->get_child(i)->cast_to<ScriptEditorBase>();
-
- if (current && current->get_edited_script()==p_script) {
- if (current->goto_method(p_method)) {
- edit(p_script);
- return true;
- }
- break;
- }
- }
- return false;
-}
-
-void ScriptEditor::set_live_auto_reload_running_scripts(bool p_enabled) {
-
- auto_reload_running_scripts=p_enabled;
-}
-
-void ScriptEditor::_help_search(String p_text) {
- help_search_dialog->popup(p_text);
-}
-
-void ScriptEditor::_open_script_request(const String& p_path) {
-
- Ref<Script> script = ResourceLoader::load(p_path);
- if (script.is_valid()) {
- script_editor->edit(script,false);
- }
-}
-
-int ScriptEditor::script_editor_func_count=0;
-CreateScriptEditorFunc ScriptEditor::script_editor_funcs[ScriptEditor::SCRIPT_EDITOR_FUNC_MAX];
-
-void ScriptEditor::register_create_script_editor_function(CreateScriptEditorFunc p_func) {
-
- ERR_FAIL_COND(script_editor_func_count==SCRIPT_EDITOR_FUNC_MAX);
- script_editor_funcs[script_editor_func_count++]=p_func;
-}
-
-void ScriptEditor::_bind_methods() {
-
- ClassDB::bind_method("_file_dialog_action",&ScriptEditor::_file_dialog_action);
- ClassDB::bind_method("_tab_changed",&ScriptEditor::_tab_changed);
- ClassDB::bind_method("_menu_option",&ScriptEditor::_menu_option);
- ClassDB::bind_method("_close_current_tab",&ScriptEditor::_close_current_tab);
- ClassDB::bind_method("_close_discard_current_tab", &ScriptEditor::_close_discard_current_tab);
- ClassDB::bind_method("_close_docs_tab", &ScriptEditor::_close_docs_tab);
- ClassDB::bind_method("_close_all_tabs", &ScriptEditor::_close_all_tabs);
- ClassDB::bind_method("_editor_play",&ScriptEditor::_editor_play);
- ClassDB::bind_method("_editor_pause",&ScriptEditor::_editor_pause);
- ClassDB::bind_method("_editor_stop",&ScriptEditor::_editor_stop);
- ClassDB::bind_method("_add_callback",&ScriptEditor::_add_callback);
- ClassDB::bind_method("_reload_scripts",&ScriptEditor::_reload_scripts);
- ClassDB::bind_method("_resave_scripts",&ScriptEditor::_resave_scripts);
- ClassDB::bind_method("_res_saved_callback",&ScriptEditor::_res_saved_callback);
- ClassDB::bind_method("_goto_script_line",&ScriptEditor::_goto_script_line);
- ClassDB::bind_method("_goto_script_line2",&ScriptEditor::_goto_script_line2);
- ClassDB::bind_method("_help_search",&ScriptEditor::_help_search);
- ClassDB::bind_method("_save_history",&ScriptEditor::_save_history);
-
-
-
- ClassDB::bind_method("_breaked",&ScriptEditor::_breaked);
- ClassDB::bind_method("_show_debugger",&ScriptEditor::_show_debugger);
- ClassDB::bind_method("_get_debug_tooltip",&ScriptEditor::_get_debug_tooltip);
- ClassDB::bind_method("_autosave_scripts",&ScriptEditor::_autosave_scripts);
- ClassDB::bind_method("_editor_settings_changed",&ScriptEditor::_editor_settings_changed);
- ClassDB::bind_method("_update_script_names",&ScriptEditor::_update_script_names);
- ClassDB::bind_method("_tree_changed",&ScriptEditor::_tree_changed);
- ClassDB::bind_method("_script_selected",&ScriptEditor::_script_selected);
- ClassDB::bind_method("_script_created",&ScriptEditor::_script_created);
- ClassDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged);
- ClassDB::bind_method("_help_class_open",&ScriptEditor::_help_class_open);
- ClassDB::bind_method("_help_class_goto",&ScriptEditor::_help_class_goto);
- ClassDB::bind_method("_request_help",&ScriptEditor::_help_class_open);
- ClassDB::bind_method("_history_forward",&ScriptEditor::_history_forward);
- ClassDB::bind_method("_history_back",&ScriptEditor::_history_back);
- ClassDB::bind_method("_live_auto_reload_running_scripts",&ScriptEditor::_live_auto_reload_running_scripts);
- ClassDB::bind_method("_unhandled_input",&ScriptEditor::_unhandled_input);
-
-}
-
-ScriptEditor::ScriptEditor(EditorNode *p_editor) {
-
- current_theme = "";
-
- completion_cache = memnew( EditorScriptCodeCompletionCache );
- restoring_layout=false;
- waiting_update_names=false;
- pending_auto_reload=false;
- auto_reload_running_scripts=false;
- editor=p_editor;
-
- menu_hb = memnew( HBoxContainer );
- add_child(menu_hb);
-
-
- script_split = memnew( HSplitContainer );
- 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(0,0));
- script_split->set_split_offset(140);
-
- tab_container = memnew( TabContainer );
- tab_container->set_tabs_visible(false);
- script_split->add_child(tab_container);
-
-
- tab_container->set_h_size_flags(SIZE_EXPAND_FILL);
-
- ED_SHORTCUT("script_editor/next_script", TTR("Next script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_GREATER);
- ED_SHORTCUT("script_editor/prev_script", TTR("Previous script"), KEY_MASK_CMD | KEY_LESS);
- set_process_unhandled_input(true);
-
- file_menu = memnew( MenuButton );
- menu_hb->add_child(file_menu);
- file_menu->set_text(TTR("File"));
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New")), FILE_NEW);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open")), FILE_OPEN);
- file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KEY_MASK_ALT|KEY_MASK_CMD|KEY_S), FILE_SAVE);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As..")), FILE_SAVE_AS);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_MASK_ALT|KEY_S), FILE_SAVE_ALL);
- file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_R), FILE_TOOL_RELOAD_SOFT);
- file_menu->get_popup()->add_separator();
-
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Prev"), KEY_MASK_ALT|KEY_LEFT), WINDOW_PREV);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_next", TTR("History Next"), KEY_MASK_ALT|KEY_RIGHT), WINDOW_NEXT);
- file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/import_theme", TTR("Import Theme")), FILE_IMPORT_THEME);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_theme", TTR("Reload Theme")), FILE_RELOAD_THEME);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_theme", TTR("Save Theme")), FILE_SAVE_THEME);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As")), FILE_SAVE_THEME_AS);
- file_menu->get_popup()->add_separator();
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_file", TTR("Close"), KEY_MASK_CMD | KEY_W), FILE_CLOSE);
- file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_all", TTR("Close All")), CLOSE_ALL);
- file_menu->get_popup()->connect("id_pressed", this,"_menu_option");
-
-
-
- script_search_menu = memnew( MenuButton );
- menu_hb->add_child(script_search_menu);
- script_search_menu->set_text(TTR("Search"));
- script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find.."), KEY_MASK_CMD|KEY_F), HELP_SEARCH_FIND);
- script_search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), HELP_SEARCH_FIND_NEXT);
- script_search_menu->get_popup()->connect("id_pressed", this,"_menu_option");
- script_search_menu->hide();
-
-
- debug_menu = memnew( MenuButton );
- menu_hb->add_child(debug_menu);
- debug_menu->set_text(TTR("Debug"));
- debug_menu->get_popup()->add_separator();
- debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_over", TTR("Step Over"), KEY_F10), DEBUG_NEXT);
- debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/step_into", TTR("Step Into"), KEY_F11), DEBUG_STEP);
- debug_menu->get_popup()->add_separator();
- debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/break", TTR("Break")), DEBUG_BREAK);
- debug_menu->get_popup()->add_shortcut(ED_SHORTCUT("debugger/continue", TTR("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_shortcut(ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")), DEBUG_SHOW_KEEP_OPEN);
- debug_menu->get_popup()->connect("id_pressed", this,"_menu_option");
-
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true);
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_STEP), true );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_BREAK), true );
- debug_menu->get_popup()->set_item_disabled( debug_menu->get_popup()->get_item_index(DEBUG_CONTINUE), true );
-
-
-#if 0
- window_menu = memnew( MenuButton );
- menu_hb->add_child(window_menu);
- window_menu->set_text(TTR("Window"));
- window_menu->get_popup()->add_item(TTR("Close"),WINDOW_CLOSE,KEY_MASK_CMD|KEY_W);
- window_menu->get_popup()->add_separator();
- window_menu->get_popup()->add_item(TTR("Move Left"),WINDOW_MOVE_LEFT,KEY_MASK_CMD|KEY_LEFT);
- window_menu->get_popup()->add_item(TTR("Move Right"),WINDOW_MOVE_RIGHT,KEY_MASK_CMD|KEY_RIGHT);
- window_menu->get_popup()->add_separator();
- window_menu->get_popup()->connect("id_pressed", this,"_menu_option");
-
-#endif
-
-
- menu_hb->add_spacer();
-
-
- script_icon = memnew( TextureRect );
- menu_hb->add_child(script_icon);
- script_name_label = memnew( Label );
- menu_hb->add_child(script_name_label);
-
- script_icon->hide();
- script_name_label->hide();
-
- menu_hb->add_spacer();
-
- site_search = memnew( ToolButton );
- site_search->set_text(TTR("Tutorials"));
- site_search->connect("pressed",this,"_menu_option",varray(SEARCH_WEBSITE));
- menu_hb->add_child(site_search);
- site_search->set_tooltip(TTR("Open https://godotengine.org at tutorials section."));
-
- class_search = memnew( ToolButton );
- class_search->set_text(TTR("Classes"));
- class_search->connect("pressed",this,"_menu_option",varray(SEARCH_CLASSES));
- menu_hb->add_child(class_search);
- class_search->set_tooltip(TTR("Search the class hierarchy."));
-
- help_search = memnew( ToolButton );
- help_search->set_text(TTR("Search Help"));
- help_search->connect("pressed",this,"_menu_option",varray(SEARCH_HELP));
- menu_hb->add_child(help_search);
- help_search->set_tooltip(TTR("Search the reference documentation."));
-
- menu_hb->add_child( memnew( VSeparator) );
-
- script_back = memnew( ToolButton );
- script_back->connect("pressed",this,"_history_back");
- menu_hb->add_child(script_back);
- script_back->set_disabled(true);
- script_back->set_tooltip(TTR("Go to previous edited document."));
-
- script_forward = memnew( ToolButton );
- script_forward->connect("pressed",this,"_history_forward");
- menu_hb->add_child(script_forward);
- script_forward->set_disabled(true);
- script_forward->set_tooltip(TTR("Go to next edited document."));
-
-
-
- tab_container->connect("tab_changed", this,"_tab_changed");
-
- erase_tab_confirm = memnew( ConfirmationDialog );
- erase_tab_confirm->get_ok()->set_text(TTR("Save"));
- erase_tab_confirm->add_button(TTR("Discard"), OS::get_singleton()->get_swap_ok_cancel(), "discard");
- erase_tab_confirm->connect("confirmed", this,"_close_current_tab");
- erase_tab_confirm->connect("custom_action", this, "_close_discard_current_tab");
- add_child(erase_tab_confirm);
-
- script_create_dialog = memnew(ScriptCreateDialog);
- script_create_dialog->set_title(TTR("Create Script"));
- add_child(script_create_dialog);
- script_create_dialog->connect("script_created", this, "_script_created");
-
- file_dialog_option = -1;
- file_dialog = memnew( EditorFileDialog );
- add_child(file_dialog);
- file_dialog->connect("file_selected", this,"_file_dialog_action");
-
-
- debugger = memnew( ScriptEditorDebugger(editor) );
- debugger->connect("goto_script_line",this,"_goto_script_line");
- debugger->connect("show_debugger",this,"_show_debugger");
-
- disk_changed = memnew( ConfirmationDialog );
- {
- VBoxContainer *vbc = memnew( VBoxContainer );
- disk_changed->add_child(vbc);
- //disk_changed->set_child_rect(vbc);
-
- Label *dl = memnew( Label );
- dl->set_text(TTR("The following files are newer on disk.\nWhat action should be taken?:"));
- vbc->add_child(dl);
-
- disk_changed_list = memnew( Tree );
- vbc->add_child(disk_changed_list);
- disk_changed_list->set_v_size_flags(SIZE_EXPAND_FILL);
-
- disk_changed->connect("confirmed",this,"_reload_scripts");
- disk_changed->get_ok()->set_text(TTR("Reload"));
-
- disk_changed->add_button(TTR("Resave"),!OS::get_singleton()->get_swap_ok_cancel(),"resave");
- disk_changed->connect("custom_action",this,"_resave_scripts");
-
-
- }
-
- add_child(disk_changed);
-
- script_editor=this;
-
-
- Button *db = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Debugger"),debugger);
- debugger->set_tool_button(db);
-
-
- debugger->connect("breaked",this,"_breaked");
-
- autosave_timer = memnew( Timer );
- autosave_timer->set_one_shot(false);
- add_child(autosave_timer);
-
- grab_focus_block=false;
-
- help_search_dialog = memnew( EditorHelpSearch );
- add_child(help_search_dialog);
- help_search_dialog->connect("go_to_help",this,"_help_class_goto");
-
-
- help_index = memnew( EditorHelpIndex );
- add_child(help_index);
- help_index->connect("open_class",this,"_help_class_open");
-
- history_pos=-1;
- //debugger_gui->hide();
-
- edit_pass=0;
- trim_trailing_whitespace_on_save = false;
-
- ScriptServer::edit_request_func=_open_script_request;
-}
-
-
-ScriptEditor::~ScriptEditor() {
-
- memdelete(completion_cache);
-}
-
-void ScriptEditorPlugin::edit(Object *p_object) {
-
- if (!p_object->cast_to<Script>())
- return;
-
- script_editor->edit(p_object->cast_to<Script>());
-
-}
-
-bool ScriptEditorPlugin::handles(Object *p_object) const {
-
- if (p_object->cast_to<Script>()) {
-
- bool valid = _can_open_in_editor(p_object->cast_to<Script>());
-
- if (!valid) { //user tried to open it by clicking
- EditorNode::get_singleton()->show_warning(TTR("Built-in scripts can only be edited when the scene they belong to is loaded"));
- }
- return valid;
- }
-
- return p_object->is_class("Script");
-}
-
-void ScriptEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- script_editor->show();
- script_editor->set_process(true);
- script_editor->ensure_select_current();
- } else {
-
- script_editor->hide();
- script_editor->set_process(false);
- }
-
-}
-
-void ScriptEditorPlugin::selected_notify() {
-
- script_editor->ensure_select_current();
-}
-
-Dictionary ScriptEditorPlugin::get_state() const {
-
- return script_editor->get_state();
-}
-
-void ScriptEditorPlugin::set_state(const Dictionary& p_state) {
-
- script_editor->set_state(p_state);
-}
-void ScriptEditorPlugin::clear() {
-
- script_editor->clear();
-}
-
-void ScriptEditorPlugin::save_external_data() {
-
- script_editor->save_all_scripts();
-}
-
-void ScriptEditorPlugin::apply_changes() {
-
- script_editor->apply_scripts();
-}
-
-void ScriptEditorPlugin::restore_global_state() {
-
-
-}
-
-void ScriptEditorPlugin::save_global_state() {
-
-}
-
-void ScriptEditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
-
- script_editor->set_window_layout(p_layout);
-}
-
-void ScriptEditorPlugin::get_window_layout(Ref<ConfigFile> p_layout){
-
- script_editor->get_window_layout(p_layout);
-}
-
-
-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;
- script_editor = memnew( ScriptEditor(p_node) );
- editor->get_viewport()->add_child(script_editor);
- script_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
-
- script_editor->hide();
-
- EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change",true);
- ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save",true));
- EDITOR_DEF("text_editor/files/open_dominant_script_on_scene_change",true);
- EDITOR_DEF("text_editor/external/use_external_editor",false);
- EDITOR_DEF("text_editor/external/exec_path","");
- EDITOR_DEF("text_editor/open_scripts/script_temperature_enabled",true);
- EDITOR_DEF("text_editor/open_scripts/highlight_current_script", true);
- EDITOR_DEF("text_editor/open_scripts/script_temperature_history_size",15);
- EDITOR_DEF("text_editor/open_scripts/script_temperature_hot_color",Color(1,0,0,0.3));
- EDITOR_DEF("text_editor/open_scripts/script_temperature_cold_color",Color(0,0,1,0.3));
- EDITOR_DEF("text_editor/open_scripts/current_script_background_color",Color(0.81,0.81,0.14,0.63));
- EDITOR_DEF("text_editor/open_scripts/group_help_pages",true);
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT,"text_editor/open_scripts/sort_scripts_by",PROPERTY_HINT_ENUM,"Name,Path"));
- EDITOR_DEF("text_editor/open_scripts/sort_scripts_by",0);
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT,"text_editor/open_scripts/list_script_names_as",PROPERTY_HINT_ENUM,"Name,Parent Directory And Name,Full Path"));
- EDITOR_DEF("text_editor/open_scripts/list_script_names_as",0);
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"text_editor/external/exec_path",PROPERTY_HINT_GLOBAL_FILE));
- EDITOR_DEF("text_editor/external/exec_flags","");
-
-
-}
-
-
-ScriptEditorPlugin::~ScriptEditorPlugin()
-{
-}
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
deleted file mode 100644
index 75099fc5ec..0000000000
--- a/tools/editor/plugins/script_editor_plugin.h
+++ /dev/null
@@ -1,394 +0,0 @@
-/*************************************************************************/
-/* script_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SCRIPT_EDITOR_PLUGIN_H
-#define SCRIPT_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/script_create_dialog.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/text_edit.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/tree.h"
-#include "scene/main/timer.h"
-#include "script_language.h"
-#include "tools/editor/code_editor.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/item_list.h"
-#include "tools/editor/editor_help.h"
-
-class ScriptEditorQuickOpen : public ConfirmationDialog {
-
- GDCLASS(ScriptEditorQuickOpen,ConfirmationDialog )
-
- LineEdit *search_box;
- Tree *search_options;
- String function;
-
- void _update_search();
-
- void _sbox_input(const InputEvent& p_ie);
- Vector<String> functions;
-
-
- void _confirmed();
- void _text_changed(const String& p_newtext);
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void popup(const Vector<String>& p_base,bool p_dontclear=false);
- ScriptEditorQuickOpen();
-};
-
-
-class ScriptEditorDebugger;
-
-
-
-class ScriptEditorBase : public Control {
-
- GDCLASS( ScriptEditorBase, Control );
-protected:
- static void _bind_methods();
-public:
-
- virtual void apply_code()=0;
- virtual Ref<Script> get_edited_script() const=0;
- virtual Vector<String> get_functions()=0;
- virtual void set_edited_script(const Ref<Script>& p_script)=0;
- virtual void reload_text()=0;
- virtual String get_name()=0;
- virtual Ref<Texture> get_icon()=0;
- virtual bool is_unsaved()=0;
- virtual Variant get_edit_state()=0;
- virtual void set_edit_state(const Variant& p_state)=0;
- virtual void goto_line(int p_line,bool p_with_error=false)=0;
- virtual void trim_trailing_whitespace()=0;
- virtual void ensure_focus()=0;
- virtual void tag_saved_version()=0;
- virtual void reload(bool p_soft)=0;
- virtual void get_breakpoints(List<int> *p_breakpoints)=0;
- virtual bool goto_method(const String& p_method)=0;
- virtual void add_callback(const String& p_function,PoolStringArray p_args)=0;
- virtual void update_settings()=0;
- virtual void set_debugger_active(bool p_active)=0;
- virtual bool can_lose_focus_on_node_selection() { return true; }
-
- virtual void set_tooltip_request_func(String p_method,Object* p_obj)=0;
- virtual Control *get_edit_menu()=0;
-
- ScriptEditorBase() {}
-};
-
-
-typedef ScriptEditorBase* (*CreateScriptEditorFunc)(const Ref<Script>& p_script);
-
-
-class EditorScriptCodeCompletionCache;
-
-class ScriptEditor : public VBoxContainer {
-
- GDCLASS(ScriptEditor, VBoxContainer );
-
-
- EditorNode *editor;
- enum {
- FILE_NEW,
- FILE_OPEN,
- FILE_SAVE,
- FILE_SAVE_AS,
- FILE_SAVE_ALL,
- FILE_IMPORT_THEME,
- FILE_RELOAD_THEME,
- FILE_SAVE_THEME,
- FILE_SAVE_THEME_AS,
- FILE_CLOSE,
- CLOSE_DOCS,
- CLOSE_ALL,
- FILE_TOOL_RELOAD,
- FILE_TOOL_RELOAD_SOFT,
- DEBUG_NEXT,
- DEBUG_STEP,
- DEBUG_BREAK,
- DEBUG_CONTINUE,
- DEBUG_SHOW,
- DEBUG_SHOW_KEEP_OPEN,
- SEARCH_HELP,
- SEARCH_CLASSES,
- SEARCH_WEBSITE,
- HELP_SEARCH_FIND,
- HELP_SEARCH_FIND_NEXT,
- WINDOW_MOVE_LEFT,
- WINDOW_MOVE_RIGHT,
- WINDOW_NEXT,
- WINDOW_PREV,
- WINDOW_SELECT_BASE=100
- };
-
- enum ScriptSortBy {
- SORT_BY_NAME,
- SORT_BY_PATH,
- };
-
- enum ScriptListName {
- DISPLAY_NAME,
- DISPLAY_DIR_AND_NAME,
- DISPLAY_FULL_PATH,
- };
-
- HBoxContainer *menu_hb;
- MenuButton *file_menu;
- MenuButton *edit_menu;
- MenuButton *script_search_menu;
- MenuButton *debug_menu;
- Timer *autosave_timer;
- uint64_t idle;
-
- Button *help_search;
- Button *site_search;
- Button *class_search;
- EditorHelpSearch *help_search_dialog;
-
- ItemList *script_list;
- HSplitContainer *script_split;
- TabContainer *tab_container;
- EditorFileDialog *file_dialog;
- ConfirmationDialog *erase_tab_confirm;
- ScriptCreateDialog *script_create_dialog;
- ScriptEditorDebugger* debugger;
- ToolButton *scripts_visible;
-
- String current_theme;
-
- TextureRect *script_icon;
- Label *script_name_label;
-
- ToolButton *script_back;
- ToolButton *script_forward;
-
- enum {
- SCRIPT_EDITOR_FUNC_MAX=32
- };
-
- static int script_editor_func_count;
- static CreateScriptEditorFunc script_editor_funcs[SCRIPT_EDITOR_FUNC_MAX];
-
- struct ScriptHistory {
-
- Control *control;
- Variant state;
- };
-
- Vector<ScriptHistory> history;
- int history_pos;
-
-
- EditorHelpIndex *help_index;
-
- void _tab_changed(int p_which);
- void _menu_option(int p_optin);
-
- Tree *disk_changed_list;
- ConfirmationDialog *disk_changed;
-
- bool restoring_layout;
-
- String _get_debug_tooltip(const String&p_text,Node *_ste);
-
- void _resave_scripts(const String& p_str);
- void _reload_scripts();
-
- bool _test_script_times_on_disk(Ref<Script> p_for_script=Ref<Script>());
-
- void _close_tab(int p_idx, bool p_save=true);
-
- void _close_current_tab();
- void _close_discard_current_tab(const String& p_str);
- void _close_docs_tab();
- void _close_all_tabs();
-
- void _ask_close_current_unsaved_tab(ScriptEditorBase *current);
-
- bool grab_focus_block;
-
- bool pending_auto_reload;
- bool auto_reload_running_scripts;
- void _live_auto_reload_running_scripts();
-
- void _update_selected_editor_menu();
-
- EditorScriptCodeCompletionCache *completion_cache;
-
- void _editor_play();
- void _editor_pause();
- void _editor_stop();
-
- int edit_pass;
-
- void _add_callback(Object *p_obj, const String& p_function, const PoolStringArray& p_args);
- void _res_saved_callback(const Ref<Resource>& p_res);
-
- bool trim_trailing_whitespace_on_save;
-
- void _trim_trailing_whitespace(TextEdit *tx);
-
- void _goto_script_line2(int p_line);
- void _goto_script_line(REF p_script,int p_line);
- void _breaked(bool p_breaked,bool p_can_debug);
- void _show_debugger(bool p_show);
- void _update_window_menu();
- void _script_created(Ref<Script> p_script);
-
- void _save_layout();
- void _editor_settings_changed();
- void _autosave_scripts();
-
- void _update_script_names();
-
- void _script_selected(int p_idx);
-
- void _find_scripts(Node* p_base, Node* p_current,Set<Ref<Script> >& used);
-
- void _tree_changed();
-
- void _script_split_dragged(float);
-
- void _unhandled_input(const InputEvent& p_event);
-
- void _help_search(String p_text);
-
- void _history_forward();
- void _history_back();
-
- bool waiting_update_names;
-
- void _help_class_open(const String& p_class);
- void _help_class_goto(const String& p_desc);
- void _update_history_arrows();
- void _save_history();
- 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(Ref<Script> p_for_script=Ref<Script>());
-
- int file_dialog_option;
- void _file_dialog_action(String p_file);
-
- static void _open_script_request(const String& p_path);
-
- static ScriptEditor *script_editor;
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- static ScriptEditor *get_singleton() { return script_editor; }
-
- void ensure_focus_current();
- void apply_scripts() const;
-
- void ensure_select_current();
- void edit(const Ref<Script>& p_script,bool p_grab_focus=true);
-
- Dictionary get_state() const;
- void set_state(const Dictionary& p_state);
- void clear();
-
- void get_breakpoints(List<String> *p_breakpoints);
-
- //void swap_lines(TextEdit *tx, int line1, int line2);
-
- void save_all_scripts();
-
- void set_window_layout(Ref<ConfigFile> p_layout);
- void get_window_layout(Ref<ConfigFile> p_layout);
-
- void set_scene_root_script( Ref<Script> p_script );
-
- bool script_go_to_method(Ref<Script> p_script, const String& p_method);
-
- virtual void edited_scene_changed();
-
- void close_builtin_scripts_from_scene(const String& p_scene);
-
- void goto_help(const String& p_desc) { _help_class_goto(p_desc); }
-
- bool can_take_away_focus() const;
-
- ScriptEditorDebugger *get_debugger() { return debugger; }
- void set_live_auto_reload_running_scripts(bool p_enabled);
-
- static void register_create_script_editor_function(CreateScriptEditorFunc p_func);
- ScriptEditor(EditorNode *p_editor);
- ~ScriptEditor();
-};
-
-class ScriptEditorPlugin : public EditorPlugin {
-
- GDCLASS( ScriptEditorPlugin, EditorPlugin );
-
- ScriptEditor *script_editor;
- EditorNode *editor;
-public:
-
- virtual String get_name() const { return "Script"; }
- bool has_main_screen() const { return true; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
- virtual void make_visible(bool p_visible);
- virtual void selected_notify();
-
- Dictionary get_state() const;
- virtual void set_state(const Dictionary& p_state);
- virtual void clear();
-
- virtual void save_external_data();
- virtual void apply_changes();
-
- virtual void restore_global_state();
- virtual void save_global_state();
-
- virtual void set_window_layout(Ref<ConfigFile> p_layout);
- virtual void get_window_layout(Ref<ConfigFile> p_layout);
-
- virtual void get_breakpoints(List<String> *p_breakpoints);
-
-
- virtual void edited_scene_changed();
-
- ScriptEditorPlugin(EditorNode *p_node);
- ~ScriptEditorPlugin();
-
-};
-
-#endif // SCRIPT_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/script_text_editor.cpp b/tools/editor/plugins/script_text_editor.cpp
deleted file mode 100644
index 9ec6266419..0000000000
--- a/tools/editor/plugins/script_text_editor.cpp
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*************************************************************************/
-/* script_text_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "script_text_editor.h"
-
-#include "tools/editor/editor_settings.h"
-#include "os/keyboard.h"
-#include "tools/editor/script_editor_debugger.h"
-#include "tools/editor/editor_node.h"
-
-Vector<String> ScriptTextEditor::get_functions() {
-
-
- String errortxt;
- int line=-1,col;
- TextEdit *te=code_editor->get_text_edit();
- String text = te->get_text();
- List<String> fnc;
-
- if (script->get_language()->validate(text,line,col,errortxt,script->get_path(),&fnc)) {
-
- //if valid rewrite functions to latest
- functions.clear();
- for (List<String>::Element *E=fnc.front();E;E=E->next()) {
-
- functions.push_back(E->get());
- }
-
-
- }
-
- return functions;
-}
-
-void ScriptTextEditor::apply_code() {
-
- if (script.is_null())
- return;
- //print_line("applying code");
- script->set_source_code(code_editor->get_text_edit()->get_text());
- script->update_exports();
-}
-
-Ref<Script> ScriptTextEditor::get_edited_script() const {
-
- return script;
-}
-
-bool ScriptTextEditor::goto_method(const String& p_method) {
-
-
- Vector<String> functions = get_functions();
-
- String method_search = p_method + ":";
-
- for (int i=0;i<functions.size();i++) {
- String function=functions[i];
-
- if (function.begins_with(method_search)) {
-
- int line=function.get_slice(":",1).to_int();
- goto_line(line-1);
- return true;
- }
- }
-
- return false;
-}
-
-void ScriptTextEditor::_load_theme_settings() {
-
- TextEdit *text_edit = code_editor->get_text_edit();
-
- text_edit->clear_colors();
-
- /* keyword color */
-
-
- text_edit->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color",Color(0,0,0,0)));
- text_edit->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0,0,0,0)));
- text_edit->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")));
- text_edit->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")));
- text_edit->add_color_override("completion_scroll_color", EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff")));
- text_edit->add_color_override("completion_font_color", EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa")));
- text_edit->add_color_override("font_color",EDITOR_DEF("text_editor/highlighting/text_color",Color(0,0,0)));
- text_edit->add_color_override("line_number_color",EDITOR_DEF("text_editor/highlighting/line_number_color",Color(0,0,0)));
- text_edit->add_color_override("caret_color",EDITOR_DEF("text_editor/highlighting/caret_color",Color(0,0,0)));
- text_edit->add_color_override("caret_background_color",EDITOR_DEF("text_editor/highlighting/caret_background_color",Color(0,0,0)));
- text_edit->add_color_override("font_selected_color",EDITOR_DEF("text_editor/highlighting/text_selected_color",Color(1,1,1)));
- text_edit->add_color_override("selection_color",EDITOR_DEF("text_editor/highlighting/selection_color",Color(0.2,0.2,1)));
- text_edit->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2)));
- text_edit->add_color_override("current_line_color",EDITOR_DEF("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15)));
- text_edit->add_color_override("line_length_guideline_color", EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0,0,0)));
- text_edit->add_color_override("word_highlighted_color",EDITOR_DEF("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15)));
- text_edit->add_color_override("number_color",EDITOR_DEF("text_editor/highlighting/number_color",Color(0.9,0.6,0.0,2)));
- text_edit->add_color_override("function_color",EDITOR_DEF("text_editor/highlighting/function_color",Color(0.4,0.6,0.8)));
- text_edit->add_color_override("member_variable_color",EDITOR_DEF("text_editor/highlighting/member_variable_color",Color(0.9,0.3,0.3)));
- text_edit->add_color_override("mark_color", EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0,0.4,0.4,0.4)));
- text_edit->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8,0.8,0.4,0.2)));
- text_edit->add_color_override("search_result_color",EDITOR_DEF("text_editor/highlighting/search_result_color",Color(0.05,0.25,0.05,1)));
- text_edit->add_color_override("search_result_border_color",EDITOR_DEF("text_editor/highlighting/search_result_border_color",Color(0.1,0.45,0.1,1)));
- text_edit->add_color_override("symbol_color",EDITOR_DEF("text_editor/highlighting/symbol_color",Color::hex(0x005291ff)));
- text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing",4));
-
- Color keyword_color= EDITOR_DEF("text_editor/highlighting/keyword_color",Color(0.5,0.0,0.2));
-
- List<String> keywords;
- script->get_language()->get_reserved_words(&keywords);
- for(List<String>::Element *E=keywords.front();E;E=E->next()) {
-
- text_edit->add_keyword_color(E->get(),keyword_color);
- }
-
- //colorize core types
- Color basetype_color= EDITOR_DEF("text_editor/highlighting/base_type_color",Color(0.3,0.3,0.0));
-
- text_edit->add_keyword_color("Vector2",basetype_color);
- text_edit->add_keyword_color("Vector3",basetype_color);
- text_edit->add_keyword_color("Plane",basetype_color);
- text_edit->add_keyword_color("Quat",basetype_color);
- text_edit->add_keyword_color("AABB",basetype_color);
- text_edit->add_keyword_color("Matrix3",basetype_color);
- text_edit->add_keyword_color("Transform",basetype_color);
- text_edit->add_keyword_color("Color",basetype_color);
- text_edit->add_keyword_color("Image",basetype_color);
- text_edit->add_keyword_color("InputEvent",basetype_color);
- text_edit->add_keyword_color("Rect2",basetype_color);
- text_edit->add_keyword_color("NodePath",basetype_color);
-
- //colorize engine types
- Color type_color= EDITOR_DEF("text_editor/highlighting/engine_type_color",Color(0.0,0.2,0.4));
-
- List<StringName> types;
- ClassDB::get_class_list(&types);
-
- for(List<StringName>::Element *E=types.front();E;E=E->next()) {
-
- String n = E->get();
- if (n.begins_with("_"))
- n = n.substr(1, n.length());
-
- text_edit->add_keyword_color(n,type_color);
- }
-
- //colorize comments
- Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color",Color::hex(0x797e7eff));
- List<String> comments;
- script->get_language()->get_comment_delimiters(&comments);
-
- for(List<String>::Element *E=comments.front();E;E=E->next()) {
-
- String comment = E->get();
- String beg = comment.get_slice(" ",0);
- String end = comment.get_slice_count(" ")>1?comment.get_slice(" ",1):String();
-
- text_edit->add_color_region(beg,end,comment_color,end=="");
- }
-
- //colorize strings
- Color string_color = EDITOR_DEF("text_editor/highlighting/string_color",Color::hex(0x6b6f00ff));
- List<String> strings;
- script->get_language()->get_string_delimiters(&strings);
-
- for (List<String>::Element *E=strings.front();E;E=E->next()) {
-
- String string = E->get();
- String beg = string.get_slice(" ",0);
- String end = string.get_slice_count(" ")>1?string.get_slice(" ",1):String();
- text_edit->add_color_region(beg,end,string_color,end=="");
- }
-}
-
-
-void ScriptTextEditor::reload_text() {
-
- ERR_FAIL_COND(script.is_null()) ;
-
- TextEdit *te = code_editor->get_text_edit();
- int column = te->cursor_get_column();
- int row = te->cursor_get_line();
- int h = te->get_h_scroll();
- int v = te->get_v_scroll();
-
- te->set_text(script->get_source_code());
- te->clear_undo_history();
- te->cursor_set_line(row);
- te->cursor_set_column(column);
- te->set_h_scroll(h);
- te->set_v_scroll(v);
-
- te->tag_saved_version();
-
- code_editor->update_line_and_column();
-
-}
-
-void ScriptTextEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_READY) {
-
- //emit_signal("name_changed");
- }
-}
-
-void ScriptTextEditor::add_callback(const String& p_function,PoolStringArray p_args) {
-
- String code = code_editor->get_text_edit()->get_text();
- int pos = script->get_language()->find_function(p_function,code);
- if (pos==-1) {
- //does not exist
- code_editor->get_text_edit()->deselect();
- pos=code_editor->get_text_edit()->get_line_count()+2;
- String func = script->get_language()->make_function("",p_function,p_args);
- //code=code+func;
- code_editor->get_text_edit()->cursor_set_line(pos+1);
- code_editor->get_text_edit()->cursor_set_column(1000000); //none shall be that big
- code_editor->get_text_edit()->insert_text_at_cursor("\n\n"+func);
- }
- code_editor->get_text_edit()->cursor_set_line(pos);
- code_editor->get_text_edit()->cursor_set_column(1);
-}
-
-void ScriptTextEditor::update_settings() {
-
- code_editor->update_editor_settings();
-}
-
-bool ScriptTextEditor::is_unsaved() {
-
- return code_editor->get_text_edit()->get_version()!=code_editor->get_text_edit()->get_saved_version();
-}
-
-Variant ScriptTextEditor::get_edit_state() {
-
- Dictionary state;
-
- state["scroll_pos"]=code_editor->get_text_edit()->get_v_scroll();
- state["column"]=code_editor->get_text_edit()->cursor_get_column();
- state["row"]=code_editor->get_text_edit()->cursor_get_line();
-
- return state;
-}
-
-void ScriptTextEditor::trim_trailing_whitespace() {
-
- TextEdit *tx = code_editor->get_text_edit();
-
- bool trimed_whitespace = false;
- for (int i = 0; i < tx->get_line_count(); i++) {
- String line = tx->get_line(i);
- if (line.ends_with(" ") || line.ends_with("\t")) {
-
- if (!trimed_whitespace) {
- tx->begin_complex_operation();
- trimed_whitespace = true;
- }
-
- int end = 0;
- for (int j = line.length() - 1; j > -1; j--) {
- if (line[j] != ' ' && line[j] != '\t') {
- end = j+1;
- break;
- }
- }
- tx->set_line(i, line.substr(0, end));
- }
- }
- if (trimed_whitespace) {
- tx->end_complex_operation();
- tx->update();
- }
-}
-
-void ScriptTextEditor::tag_saved_version() {
-
- code_editor->get_text_edit()->tag_saved_version();
-}
-
-void ScriptTextEditor::goto_line(int p_line, bool p_with_error) {
- code_editor->get_text_edit()->cursor_set_line(p_line);
-}
-
-void ScriptTextEditor::ensure_focus() {
-
- code_editor->get_text_edit()->grab_focus();
-}
-
-void ScriptTextEditor::set_edit_state(const Variant& p_state) {
-
- Dictionary state=p_state;
- code_editor->get_text_edit()->set_v_scroll(state["scroll_pos"]);
- code_editor->get_text_edit()->cursor_set_column( state["column"]);
- code_editor->get_text_edit()->cursor_set_line( state["row"] );
- code_editor->get_text_edit()->grab_focus();
-
- //int scroll_pos;
- //int cursor_column;
- //int cursor_row;
-}
-
-String ScriptTextEditor::get_name() {
- String name;
-
- if (script->get_path().find("local://")==-1 && script->get_path().find("::")==-1) {
- name=script->get_path().get_file();
- if (is_unsaved()) {
- name+="(*)";
- }
- } else if (script->get_name()!="")
- name=script->get_name();
- else
- name=script->get_class()+"("+itos(script->get_instance_ID())+")";
-
- return name;
-
-}
-
-Ref<Texture> ScriptTextEditor::get_icon() {
-
- if (get_parent_control() && get_parent_control()->has_icon(script->get_class(),"EditorIcons")) {
- return get_parent_control()->get_icon(script->get_class(),"EditorIcons");
- }
-
- return Ref<Texture>();
-}
-
-
-
-void ScriptTextEditor::set_edited_script(const Ref<Script>& p_script) {
-
- ERR_FAIL_COND(!script.is_null());
-
- script=p_script;
-
-
- _load_theme_settings();
-
- code_editor->get_text_edit()->set_text(script->get_source_code());
- code_editor->get_text_edit()->clear_undo_history();
- code_editor->get_text_edit()->tag_saved_version();
-
- emit_signal("name_changed");
- code_editor->update_line_and_column();
-}
-
-
-void ScriptTextEditor::_validate_script() {
-
- String errortxt;
- int line=-1,col;
- TextEdit *te=code_editor->get_text_edit();
-
- String text = te->get_text();
- List<String> fnc;
-
- if (!script->get_language()->validate(text,line,col,errortxt,script->get_path(),&fnc)) {
- String error_text="error("+itos(line)+","+itos(col)+"): "+errortxt;
- code_editor->set_error(error_text);
- } else {
- code_editor->set_error("");
- line=-1;
- if (!script->is_tool()) {
- script->set_source_code(text);
- script->update_exports();
- //script->reload(); //will update all the variables in property editors
- }
-
- functions.clear();
- for (List<String>::Element *E=fnc.front();E;E=E->next()) {
-
- functions.push_back(E->get());
- }
-
- }
-
- line--;
- for(int i=0;i<te->get_line_count();i++) {
- te->set_line_as_marked(i,line==i);
- }
-
- emit_signal("name_changed");
-}
-
-
-static Node* _find_node_for_script(Node* p_base, Node*p_current, const Ref<Script>& p_script) {
-
- if (p_current->get_owner()!=p_base && p_base!=p_current)
- return NULL;
- Ref<Script> c = p_current->get_script();
- if (c==p_script)
- return p_current;
- for(int i=0;i<p_current->get_child_count();i++) {
- Node *found = _find_node_for_script(p_base,p_current->get_child(i),p_script);
- if (found)
- return found;
- }
-
- return NULL;
-}
-
-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(Ref<Script> p_for_script) {
-
- if (!bool(EditorSettings::get_singleton()->get("text_editor/external/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 (p_for_script.is_valid() && p_for_script!=script)
- continue;
-
- 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_class(),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_scripts(void* p_ud,const String& p_code, List<String>* r_options) {
-
- ScriptTextEditor *ste = (ScriptTextEditor *)p_ud;
- ste->_code_complete_script(p_code,r_options);
-}
-
-void ScriptTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) {
-
- if (color_panel->is_visible_in_tree()) return;
- Node *base = get_tree()->get_edited_scene_root();
- if (base) {
- base = _find_node_for_script(base,base,script);
- }
- String hint;
- Error err = script->get_language()->complete_code(p_code,script->get_path().get_base_dir(),base,r_options,hint);
- if (hint!="") {
- code_editor->get_text_edit()->set_code_hint(hint);
- }
-
-}
-
-void ScriptTextEditor::_breakpoint_toggled(int p_row) {
-
- ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(script->get_path(),p_row+1,code_editor->get_text_edit()->is_line_set_as_breakpoint(p_row));
-
-}
-
-static void swap_lines(TextEdit *tx, int line1, int line2)
-{
- String tmp = tx->get_line(line1);
- String tmp2 = tx->get_line(line2);
- tx->set_line(line2, tmp);
- tx->set_line(line1, tmp2);
-
- tx->cursor_set_line(line2);
-}
-
-void ScriptTextEditor::_lookup_symbol(const String& p_symbol,int p_row, int p_column) {
-
- Node *base = get_tree()->get_edited_scene_root();
- if (base) {
- base = _find_node_for_script(base,base,script);
- }
-
-
- ScriptLanguage::LookupResult result;
- if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(),p_symbol,script->get_path().get_base_dir(),base,result)==OK) {
-
- _goto_line(p_row);
-
- switch(result.type) {
- case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: {
-
- if (result.script.is_valid()) {
- emit_signal("request_open_script_at_line",result.script,result.location-1);
- } else {
- emit_signal("request_save_history");
- _goto_line(result.location-1);
- }
- } break;
- case ScriptLanguage::LookupResult::RESULT_CLASS: {
- emit_signal("go_to_help","class_name:"+result.class_name);
- } break;
- case ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT: {
-
- StringName cname = result.class_name;
- bool success;
- while(true) {
- ClassDB::get_integer_constant(cname,result.class_member,&success);
- if (success) {
- result.class_name=cname;
- cname=ClassDB::get_parent_class(cname);
- } else {
- break;
- }
- }
-
-
- emit_signal("go_to_help","class_constant:"+result.class_name+":"+result.class_member);
-
- } break;
- case ScriptLanguage::LookupResult::RESULT_CLASS_PROPERTY: {
- emit_signal("go_to_help","class_property:"+result.class_name+":"+result.class_member);
-
- } break;
- case ScriptLanguage::LookupResult::RESULT_CLASS_METHOD: {
-
- StringName cname = result.class_name;
-
- while(true) {
- if (ClassDB::has_method(cname,result.class_member)) {
- result.class_name=cname;
- cname=ClassDB::get_parent_class(cname);
- } else {
- break;
- }
- }
-
- emit_signal("go_to_help","class_method:"+result.class_name+":"+result.class_member);
-
- } break;
- }
-
- }
-}
-
-void ScriptTextEditor::_edit_option(int p_op) {
-
- switch(p_op) {
- case EDIT_UNDO: {
- code_editor->get_text_edit()->undo();
- code_editor->get_text_edit()->call_deferred("grab_focus");
- } break;
- case EDIT_REDO: {
- code_editor->get_text_edit()->redo();
- code_editor->get_text_edit()->call_deferred("grab_focus");
- } break;
- case EDIT_CUT: {
-
- code_editor->get_text_edit()->cut();
- code_editor->get_text_edit()->call_deferred("grab_focus");
- } break;
- case EDIT_COPY: {
- code_editor->get_text_edit()->copy();
- code_editor->get_text_edit()->call_deferred("grab_focus");
-
- } break;
- case EDIT_PASTE: {
- code_editor->get_text_edit()->paste();
- code_editor->get_text_edit()->call_deferred("grab_focus");
-
- } break;
- case EDIT_SELECT_ALL: {
-
- code_editor->get_text_edit()->select_all();
- code_editor->get_text_edit()->call_deferred("grab_focus");
-
- } break;
- case EDIT_MOVE_LINE_UP: {
-
- TextEdit *tx = code_editor->get_text_edit();
- Ref<Script> scr = script;
- if (scr.is_null())
- return;
-
- tx->begin_complex_operation();
- if (tx->is_selection_active())
- {
- int from_line = tx->get_selection_from_line();
- int from_col = tx->get_selection_from_column();
- int to_line = tx->get_selection_to_line();
- int to_column = tx->get_selection_to_column();
-
- for (int i = from_line; i <= to_line; i++)
- {
- int line_id = i;
- int next_id = i - 1;
-
- if (line_id == 0 || next_id < 0)
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- int from_line_up = from_line > 0 ? from_line-1 : from_line;
- int to_line_up = to_line > 0 ? to_line-1 : to_line;
- tx->select(from_line_up, from_col, to_line_up, to_column);
- }
- else
- {
- int line_id = tx->cursor_get_line();
- int next_id = line_id - 1;
-
- if (line_id == 0 || next_id < 0)
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- tx->end_complex_operation();
- tx->update();
-
- } break;
- case EDIT_MOVE_LINE_DOWN: {
-
- TextEdit *tx = code_editor->get_text_edit();
- Ref<Script> scr = get_edited_script();
- if (scr.is_null())
- return;
-
- tx->begin_complex_operation();
- if (tx->is_selection_active())
- {
- int from_line = tx->get_selection_from_line();
- int from_col = tx->get_selection_from_column();
- int to_line = tx->get_selection_to_line();
- int to_column = tx->get_selection_to_column();
-
- for (int i = to_line; i >= from_line; i--)
- {
- int line_id = i;
- int next_id = i + 1;
-
- if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- int from_line_down = from_line < tx->get_line_count() ? from_line+1 : from_line;
- int to_line_down = to_line < tx->get_line_count() ? to_line+1 : to_line;
- tx->select(from_line_down, from_col, to_line_down, to_column);
- }
- else
- {
- int line_id = tx->cursor_get_line();
- int next_id = line_id + 1;
-
- if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- tx->end_complex_operation();
- tx->update();
-
- } break;
- case EDIT_INDENT_LEFT: {
-
- TextEdit *tx = code_editor->get_text_edit();
- Ref<Script> scr = get_edited_script();
- if (scr.is_null())
- return;
-
- tx->begin_complex_operation();
- if (tx->is_selection_active())
- {
- tx->indent_selection_left();
- }
- else
- {
- int begin = tx->cursor_get_line();
- String line_text = tx->get_line(begin);
- // begins with tab
- if (line_text.begins_with("\t"))
- {
- line_text = line_text.substr(1, line_text.length());
- tx->set_line(begin, line_text);
- }
- // begins with 4 spaces
- else if (line_text.begins_with(" "))
- {
- line_text = line_text.substr(4, line_text.length());
- tx->set_line(begin, line_text);
- }
- }
- tx->end_complex_operation();
- tx->update();
- //tx->deselect();
-
- } break;
- case EDIT_INDENT_RIGHT: {
-
- TextEdit *tx = code_editor->get_text_edit();
- Ref<Script> scr = get_edited_script();
- if (scr.is_null())
- return;
-
- tx->begin_complex_operation();
- if (tx->is_selection_active())
- {
- tx->indent_selection_right();
- }
- else
- {
- int begin = tx->cursor_get_line();
- String line_text = tx->get_line(begin);
- line_text = '\t' + line_text;
- tx->set_line(begin, line_text);
- }
- tx->end_complex_operation();
- tx->update();
- //tx->deselect();
-
- } break;
- case EDIT_CLONE_DOWN: {
-
- TextEdit *tx = code_editor->get_text_edit();
- Ref<Script> scr = get_edited_script();
- if (scr.is_null())
- return;
-
- int from_line = tx->cursor_get_line();
- int to_line = tx->cursor_get_line();
- int column = tx->cursor_get_column();
-
- if (tx->is_selection_active()) {
- from_line = tx->get_selection_from_line();
- to_line = tx->get_selection_to_line();
- column = tx->cursor_get_column();
- }
- int next_line = to_line + 1;
-
- tx->begin_complex_operation();
- for (int i = from_line; i <= to_line; i++) {
-
- if (i >= tx->get_line_count() - 1) {
- tx->set_line(i, tx->get_line(i) + "\n");
- }
- String line_clone = tx->get_line(i);
- tx->insert_at(line_clone, next_line);
- next_line++;
- }
-
- tx->cursor_set_column(column);
- if (tx->is_selection_active()) {
- tx->select(to_line + 1, tx->get_selection_from_column(), next_line - 1, tx->get_selection_to_column());
- }
-
- tx->end_complex_operation();
- tx->update();
-
- } break;
- case EDIT_TOGGLE_COMMENT: {
-
- TextEdit *tx = code_editor->get_text_edit();
- Ref<Script> scr = get_edited_script();
- if (scr.is_null())
- return;
-
-
- tx->begin_complex_operation();
- if (tx->is_selection_active())
- {
- int begin = tx->get_selection_from_line();
- int end = tx->get_selection_to_line();
-
- // End of selection ends on the first column of the last line, ignore it.
- if(tx->get_selection_to_column() == 0)
- end -= 1;
-
- for (int i = begin; i <= end; i++)
- {
- String line_text = tx->get_line(i);
-
- if (line_text.begins_with("#"))
- line_text = line_text.substr(1, line_text.length());
- else
- line_text = "#" + line_text;
- tx->set_line(i, line_text);
- }
- }
- else
- {
- int begin = tx->cursor_get_line();
- String line_text = tx->get_line(begin);
-
- if (line_text.begins_with("#"))
- line_text = line_text.substr(1, line_text.length());
- else
- line_text = "#" + line_text;
- tx->set_line(begin, line_text);
- }
- tx->end_complex_operation();
- tx->update();
- //tx->deselect();
-
- } break;
- case EDIT_COMPLETE: {
-
- code_editor->get_text_edit()->query_code_comple();
-
- } break;
- case EDIT_AUTO_INDENT: {
-
- TextEdit *te = code_editor->get_text_edit();
- String text = te->get_text();
- Ref<Script> scr = get_edited_script();
- if (scr.is_null())
- return;
- int begin,end;
- if (te->is_selection_active()) {
- begin=te->get_selection_from_line();
- end=te->get_selection_to_line();
- } else {
- begin=0;
- end=te->get_line_count()-1;
- }
- scr->get_language()->auto_indent_code(text,begin,end);
- te->set_text(text);
-
-
- } break;
- case EDIT_TRIM_TRAILING_WHITESAPCE: {
- trim_trailing_whitespace();
- } break;
- case EDIT_PICK_COLOR: {
- color_panel->popup();
- } break;
-
-
- case SEARCH_FIND: {
-
- code_editor->get_find_replace_bar()->popup_search();
- } break;
- case SEARCH_FIND_NEXT: {
-
- code_editor->get_find_replace_bar()->search_next();
- } break;
- case SEARCH_FIND_PREV: {
-
- code_editor->get_find_replace_bar()->search_prev();
- } break;
- case SEARCH_REPLACE: {
-
- code_editor->get_find_replace_bar()->popup_replace();
- } break;
- case SEARCH_LOCATE_FUNCTION: {
-
- quick_open->popup(get_functions());
- } break;
- case SEARCH_GOTO_LINE: {
-
- goto_line_dialog->popup_find_line(code_editor->get_text_edit());
- } break;
- case DEBUG_TOGGLE_BREAKPOINT: {
- int line=code_editor->get_text_edit()->cursor_get_line();
- bool dobreak = !code_editor->get_text_edit()->is_line_set_as_breakpoint(line);
- code_editor->get_text_edit()->set_line_as_breakpoint(line,dobreak);
- ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(get_edited_script()->get_path(),line+1,dobreak);
- } break;
- case DEBUG_REMOVE_ALL_BREAKPOINTS: {
- List<int> bpoints;
- code_editor->get_text_edit()->get_breakpoints(&bpoints);
-
- for(List<int>::Element *E=bpoints.front();E;E=E->next()) {
- int line = E->get();
- bool dobreak = !code_editor->get_text_edit()->is_line_set_as_breakpoint(line);
- code_editor->get_text_edit()->set_line_as_breakpoint(line,dobreak);
- ScriptEditor::get_singleton()->get_debugger()->set_breakpoint(get_edited_script()->get_path(),line+1,dobreak);
- }
- }
- case DEBUG_GOTO_NEXT_BREAKPOINT: {
- List<int> bpoints;
- code_editor->get_text_edit()->get_breakpoints(&bpoints);
- if (bpoints.size() <= 0) {
- return;
- }
-
- int line=code_editor->get_text_edit()->cursor_get_line();
- // wrap around
- if (line >= bpoints[bpoints.size() - 1]) {
- code_editor->get_text_edit()->cursor_set_line(bpoints[0]);
- } else {
- for(List<int>::Element *E=bpoints.front();E;E=E->next()) {
- int bline = E->get();
- if (bline > line) {
- code_editor->get_text_edit()->cursor_set_line(bline);
- return;
- }
- }
- }
-
- } break;
- case DEBUG_GOTO_PREV_BREAKPOINT: {
- List<int> bpoints;
- code_editor->get_text_edit()->get_breakpoints(&bpoints);
- if (bpoints.size() <= 0) {
- return;
- }
-
- int line=code_editor->get_text_edit()->cursor_get_line();
- // wrap around
- if (line <= bpoints[0]) {
- code_editor->get_text_edit()->cursor_set_line(bpoints[bpoints.size() - 1]);
- } else {
- for(List<int>::Element *E=bpoints.back();E;E=E->prev()) {
- int bline = E->get();
- if (bline < line) {
- code_editor->get_text_edit()->cursor_set_line(bline);
- return;
- }
- }
- }
-
- } break;
-
- case HELP_CONTEXTUAL: {
- String text = code_editor->get_text_edit()->get_selection_text();
- if (text == "")
- text = code_editor->get_text_edit()->get_word_under_cursor();
- if (text != "") {
- emit_signal("request_help_search",text);
- }
- } break;
- }
-}
-
-void ScriptTextEditor::_bind_methods() {
-
- ClassDB::bind_method("_validate_script",&ScriptTextEditor::_validate_script);
- ClassDB::bind_method("_load_theme_settings",&ScriptTextEditor::_load_theme_settings);
- ClassDB::bind_method("_breakpoint_toggled",&ScriptTextEditor::_breakpoint_toggled);
- ClassDB::bind_method("_edit_option",&ScriptTextEditor::_edit_option);
- ClassDB::bind_method("_goto_line",&ScriptTextEditor::_goto_line);
- ClassDB::bind_method("_lookup_symbol",&ScriptTextEditor::_lookup_symbol);
- ClassDB::bind_method("_text_edit_gui_input", &ScriptTextEditor::_text_edit_gui_input);
- ClassDB::bind_method("_color_changed", &ScriptTextEditor::_color_changed);
-
-
- ClassDB::bind_method("get_drag_data_fw",&ScriptTextEditor::get_drag_data_fw);
- ClassDB::bind_method("can_drop_data_fw",&ScriptTextEditor::can_drop_data_fw);
- ClassDB::bind_method("drop_data_fw",&ScriptTextEditor::drop_data_fw);
-
-}
-
-Control *ScriptTextEditor::get_edit_menu() {
-
- return edit_hb;
-}
-
-void ScriptTextEditor::reload(bool p_soft) {
-
- TextEdit *te = code_editor->get_text_edit();
- Ref<Script> scr = get_edited_script();
- if (scr.is_null())
- return;
- scr->set_source_code(te->get_text());
- bool soft = p_soft || scr->get_instance_base_type()=="EditorPlugin"; //always soft-reload editor plugins
-
- scr->get_language()->reload_tool_script(scr,soft);
-}
-
-void ScriptTextEditor::get_breakpoints(List<int> *p_breakpoints) {
-
- code_editor->get_text_edit()->get_breakpoints(p_breakpoints);
-
-}
-
-void ScriptTextEditor::set_tooltip_request_func(String p_method,Object* p_obj) {
-
- code_editor->get_text_edit()->set_tooltip_request_func(p_obj,p_method,this);
-}
-
-void ScriptTextEditor::set_debugger_active(bool p_active) {
-
-
-}
-
-
-Variant ScriptTextEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- return Variant();
-}
-
-bool ScriptTextEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
-
- Dictionary d = p_data;
- if (d.has("type") &&
- (
-
- String(d["type"])=="resource" ||
- String(d["type"])=="files" ||
- String(d["type"])=="nodes"
- ) ) {
-
-
- return true;
- }
-
-
- return false;
-
-}
-
-#ifdef TOOLS_ENABLED
-
-static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
-
- if (p_edited_scene!=p_current_node && p_current_node->get_owner()!=p_edited_scene)
- return NULL;
-
- Ref<Script> scr = p_current_node->get_script();
-
- if (scr.is_valid() && scr==script)
- return p_current_node;
-
- for(int i=0;i<p_current_node->get_child_count();i++) {
- Node *n = _find_script_node(p_edited_scene,p_current_node->get_child(i),script);
- if (n)
- return n;
- }
-
- return NULL;
-}
-
-#else
-
-static Node* _find_script_node(Node* p_edited_scene,Node* p_current_node,const Ref<Script> &script) {
-
- return NULL;
-}
-#endif
-
-
-
-
-void ScriptTextEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
-
- Dictionary d = p_data;
-
- if (d.has("type") && String(d["type"])=="resource") {
-
- Ref<Resource> res = d["resource"];
- if (!res.is_valid()) {
- return;
- }
-
- if (res->get_path().is_resource_file()) {
- EditorNode::get_singleton()->show_warning("Only resources from filesystem can be dropped.");
- return;
- }
-
- code_editor->get_text_edit()->insert_text_at_cursor(res->get_path());
-
- }
-
- if (d.has("type") && String(d["type"])=="files") {
-
-
- Array files = d["files"];
-
- String text_to_drop;
- for(int i=0;i<files.size();i++) {
-
- if (i>0)
- text_to_drop+=",";
- text_to_drop+="\""+String(files[i]).c_escape()+"\"";
-
- }
-
- code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop);
-
- }
-
- if (d.has("type") && String(d["type"])=="nodes") {
-
- Node* sn = _find_script_node(get_tree()->get_edited_scene_root(),get_tree()->get_edited_scene_root(),script);
-
-
- if (!sn) {
- EditorNode::get_singleton()->show_warning("Can't drop nodes because script '"+get_name()+"' is not used in this scene.");
- return;
- }
-
-
- Array nodes = d["nodes"];
- String text_to_drop;
- for(int i=0;i<nodes.size();i++) {
-
- if (i>0)
- text_to_drop+=",";
-
- NodePath np = nodes[i];
- Node *node = get_node(np);
- if (!node) {
- continue;
- }
-
-
-
- String path = sn->get_path_to(node);
- text_to_drop+="\""+path.c_escape()+"\"";
-
-
- }
-
- code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop);
-
-
- }
-
-
-
-}
-
-void ScriptTextEditor::_text_edit_gui_input(const InputEvent& ev) {
- if (ev.type == InputEvent::MOUSE_BUTTON) {
- InputEventMouseButton mb = ev.mouse_button;
- if (mb.button_index == BUTTON_RIGHT && !mb.pressed) {
-
- int col, row;
- TextEdit* tx = code_editor->get_text_edit();
- tx->_get_mouse_pos(Point2i(mb.global_x, mb.global_y)-tx->get_global_pos(), row, col);
- Vector2 mpos = Vector2(mb.global_x, mb.global_y)-tx->get_global_pos();
- bool have_selection = (tx->get_selection_text().length() > 0);
- bool have_color = (tx->get_word_at_pos(mpos) == "Color");
- if (have_color) {
-
- String line = tx->get_line(row);
- color_line = row;
- int begin = 0;
- int end = 0;
- bool valid = false;
- for (int i = col; i < line.length(); i++) {
- if (line[i] == '(') {
- begin = i;
- continue;
- }
- else if (line[i] == ')') {
- end = i+1;
- valid = true;
- break;
- }
- }
- if (valid) {
- color_args = line.substr(begin, end-begin);
- String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
- Vector<float> color = stripped.split_floats(",");
- if (color.size() > 2) {
- float alpha = color.size() > 3 ? color[3] : 1.0f;
- color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
- }
- color_panel->set_pos(get_global_transform().xform(get_local_mouse_pos()));
- Size2 ms = Size2(300, color_picker->get_combined_minimum_size().height+10);
- color_panel->set_size(ms);
- } else {
- have_color = false;
- }
- }
- _make_context_menu(have_selection, have_color);
- }
- }
-}
-
-void ScriptTextEditor::_color_changed(const Color& p_color) {
- String new_args;
- if (p_color.a == 1.0f) {
- new_args = String("("+rtos(p_color.r)+", "+rtos(p_color.g)+", "+rtos(p_color.b)+")");
- } else {
- new_args = String("("+rtos(p_color.r)+", "+rtos(p_color.g)+", "+rtos(p_color.b)+", "+rtos(p_color.a)+")");
- }
-
- String line = code_editor->get_text_edit()->get_line(color_line);
- String new_line = line.replace(color_args, new_args);
- color_args = new_args;
- code_editor->get_text_edit()->set_line(color_line, new_line);
-}
-
-void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color) {
-
- context_menu->clear();
- if (p_selection) {
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
- }
-
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
- context_menu->add_separator();
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
-
- if (p_selection) {
- context_menu->add_separator();
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
- context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
- }
- if (p_color) {
- context_menu->add_separator();
- context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR);
- }
- context_menu->set_pos(get_global_transform().xform(get_local_mouse_pos()));
- context_menu->set_size(Vector2(1, 1));
- context_menu->popup();
-}
-
-ScriptTextEditor::ScriptTextEditor() {
-
- code_editor = memnew( CodeTextEditor );
- add_child(code_editor);
- code_editor->set_area_as_parent_rect();
- code_editor->connect("validate_script",this,"_validate_script");
- code_editor->connect("load_theme_settings",this,"_load_theme_settings");
- code_editor->set_code_complete_func(_code_complete_scripts,this);
- code_editor->get_text_edit()->connect("breakpoint_toggled", this, "_breakpoint_toggled");
- code_editor->get_text_edit()->connect("symbol_lookup", this, "_lookup_symbol");
-
- update_settings();
-
- code_editor->get_text_edit()->set_callhint_settings(
- EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"),
- EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset"));
-
- code_editor->get_text_edit()->set_select_identifiers_on_hover(true);
- code_editor->get_text_edit()->set_context_menu_enabled(false);
- code_editor->get_text_edit()->connect("gui_input", this, "_text_edit_gui_input");
-
- context_menu = memnew(PopupMenu);
- add_child(context_menu);
- context_menu->connect("id_pressed", this, "_edit_option");
-
- color_panel = memnew(PopupPanel);
- add_child(color_panel);
- color_picker = memnew(ColorPicker);
- color_panel->add_child(color_picker);
- color_panel->set_child_rect(color_picker); //NOT
- color_picker->connect("color_changed", this, "_color_changed");
-
- edit_hb = memnew (HBoxContainer);
-
- edit_menu = memnew( MenuButton );
- edit_menu->set_text(TTR("Edit"));
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/undo"), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/redo"), EDIT_REDO);
- edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/cut"), EDIT_CUT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/copy"), EDIT_COPY);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/paste"), EDIT_PASTE);
- edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/select_all"), EDIT_SELECT_ALL);
- edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_up"), EDIT_MOVE_LINE_UP);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/move_down"), EDIT_MOVE_LINE_DOWN);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_left"), EDIT_INDENT_LEFT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/indent_right"), EDIT_INDENT_RIGHT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/clone_down"), EDIT_CLONE_DOWN);
- edit_menu->get_popup()->add_separator();
-#ifdef OSX_ENABLED
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
-#else
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/complete_symbol"), EDIT_COMPLETE);
-#endif
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/auto_indent"), EDIT_AUTO_INDENT);
- edit_menu->get_popup()->connect("id_pressed", this,"_edit_option");
- edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_breakpoint"), DEBUG_TOGGLE_BREAKPOINT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/remove_all_breakpoints"), DEBUG_REMOVE_ALL_BREAKPOINTS);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_breakpoint"), DEBUG_GOTO_NEXT_BREAKPOINT);
- edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_breakpoint"), DEBUG_GOTO_PREV_BREAKPOINT);
-
- search_menu = memnew( MenuButton );
- edit_hb->add_child(search_menu);
- search_menu->set_text(TTR("Search"));
- search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find"), SEARCH_FIND);
- search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_next"), SEARCH_FIND_NEXT);
- search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/find_previous"), SEARCH_FIND_PREV);
- search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/replace"), SEARCH_REPLACE);
- search_menu->get_popup()->add_separator();
- search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_function"), SEARCH_LOCATE_FUNCTION);
- search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_line"), SEARCH_GOTO_LINE);
- search_menu->get_popup()->add_separator();
- search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/contextual_help"), HELP_CONTEXTUAL);
-
- search_menu->get_popup()->connect("id_pressed", this,"_edit_option");
-
- edit_hb->add_child(edit_menu);
-
- quick_open = memnew( ScriptEditorQuickOpen );
- add_child(quick_open);
- quick_open->connect("goto_line",this,"_goto_line");
-
- goto_line_dialog = memnew(GotoLineDialog);
- add_child(goto_line_dialog);
-
-
- code_editor->get_text_edit()->set_drag_forwarding(this);
-}
-
-static ScriptEditorBase * create_editor(const Ref<Script>& p_script) {
-
- if (p_script->has_source_code()) {
- return memnew( ScriptTextEditor );
- }
-
- return NULL;
-}
-
-void ScriptTextEditor::register_editor() {
-
- ED_SHORTCUT("script_text_editor/undo", TTR("Undo"), KEY_MASK_CMD|KEY_Z);
- ED_SHORTCUT("script_text_editor/redo", TTR("Redo"), KEY_MASK_CMD|KEY_Y);
- ED_SHORTCUT("script_text_editor/cut", TTR("Cut"), KEY_MASK_CMD|KEY_X);
- ED_SHORTCUT("script_text_editor/copy", TTR("Copy"), KEY_MASK_CMD|KEY_C);
- ED_SHORTCUT("script_text_editor/paste", TTR("Paste"), KEY_MASK_CMD|KEY_V);
- ED_SHORTCUT("script_text_editor/select_all", TTR("Select All"), KEY_MASK_CMD|KEY_A);
- ED_SHORTCUT("script_text_editor/move_up", TTR("Move Up"), KEY_MASK_ALT|KEY_UP);
- ED_SHORTCUT("script_text_editor/move_down", TTR("Move Down"), KEY_MASK_ALT|KEY_DOWN);
-
- //leave these at zero, same can be accomplished with tab/shift-tab, including selection
- //the next/previous in history shortcut in this case makes a lot more sene.
-
- ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), 0);
- ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0);
- ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD|KEY_K);
- ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD|KEY_B);
-#ifdef OSX_ENABLED
- ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CTRL|KEY_SPACE);
-#else
- ED_SHORTCUT("script_text_editor/complete_symbol", TTR("Complete Symbol"), KEY_MASK_CMD|KEY_SPACE);
-#endif
- ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CTRL|KEY_MASK_ALT|KEY_T);
- ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD|KEY_I);
-
- ED_SHORTCUT("script_text_editor/toggle_breakpoint", TTR("Toggle Breakpoint"), KEY_F9);
- ED_SHORTCUT("script_text_editor/remove_all_breakpoints", TTR("Remove All Breakpoints"), KEY_MASK_CTRL|KEY_MASK_SHIFT|KEY_F9);
- ED_SHORTCUT("script_text_editor/goto_next_breakpoint", TTR("Goto Next Breakpoint"), KEY_MASK_CTRL|KEY_PERIOD);
- ED_SHORTCUT("script_text_editor/goto_previous_breakpoint", TTR("Goto Previous Breakpoint"), KEY_MASK_CTRL|KEY_COMMA);
-
- ED_SHORTCUT("script_text_editor/find", TTR("Find.."), KEY_MASK_CMD|KEY_F);
- ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3);
- ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT|KEY_F3);
- ED_SHORTCUT("script_text_editor/replace", TTR("Replace.."), KEY_MASK_CMD|KEY_R);
-
- ED_SHORTCUT("script_text_editor/goto_function", TTR("Goto Function.."), KEY_MASK_SHIFT|KEY_MASK_CMD|KEY_F);
- ED_SHORTCUT("script_text_editor/goto_line", TTR("Goto Line.."), KEY_MASK_CMD|KEY_L);
-
- ED_SHORTCUT("script_text_editor/contextual_help", TTR("Contextual Help"), KEY_MASK_SHIFT|KEY_F1);
-
- ScriptEditor::register_create_script_editor_function(create_editor);
-}
diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp
deleted file mode 100644
index 56a8fccb9c..0000000000
--- a/tools/editor/plugins/shader_editor_plugin.cpp
+++ /dev/null
@@ -1,584 +0,0 @@
-/*************************************************************************/
-/* shader_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "shader_editor_plugin.h"
-
-#include "tools/editor/editor_settings.h"
-#include "spatial_editor_plugin.h"
-#include "scene/resources/shader_graph.h"
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "os/keyboard.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/property_editor.h"
-#include "os/os.h"
-#include "servers/visual/shader_types.h"
-
-/*** SETTINGS EDITOR ****/
-
-
-
-
-/*** SCRIPT EDITOR ****/
-
-
-Ref<Shader> ShaderTextEditor::get_edited_shader() const {
-
- return shader;
-}
-void ShaderTextEditor::set_edited_shader(const Ref<Shader>& p_shader) {
-
- shader=p_shader;
-
-
- _load_theme_settings();
-
- get_text_edit()->set_text(p_shader->get_code());
-
- _line_col_changed();
-
-
-}
-
-
-void ShaderTextEditor::_load_theme_settings() {
-
- get_text_edit()->clear_colors();
-
- /* keyword color */
-
- get_text_edit()->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color",Color(0,0,0,0)));
- get_text_edit()->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0,0,0,0)));
- get_text_edit()->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")));
- get_text_edit()->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")));
- get_text_edit()->add_color_override("completion_scroll_color", EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff")));
- get_text_edit()->add_color_override("completion_font_color", EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa")));
- get_text_edit()->add_color_override("font_color",EDITOR_DEF("text_editor/highlighting/text_color",Color(0,0,0)));
- get_text_edit()->add_color_override("line_number_color",EDITOR_DEF("text_editor/highlighting/line_number_color",Color(0,0,0)));
- get_text_edit()->add_color_override("caret_color",EDITOR_DEF("text_editor/highlighting/caret_color",Color(0,0,0)));
- get_text_edit()->add_color_override("caret_background_color",EDITOR_DEF("text_editor/highlighting/caret_background_color",Color(0,0,0)));
- get_text_edit()->add_color_override("font_selected_color",EDITOR_DEF("text_editor/highlighting/text_selected_color",Color(1,1,1)));
- get_text_edit()->add_color_override("selection_color",EDITOR_DEF("text_editor/highlighting/selection_color",Color(0.2,0.2,1)));
- get_text_edit()->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/highlighting/brace_mismatch_color",Color(1,0.2,0.2)));
- get_text_edit()->add_color_override("current_line_color",EDITOR_DEF("text_editor/highlighting/current_line_color",Color(0.3,0.5,0.8,0.15)));
- get_text_edit()->add_color_override("word_highlighted_color",EDITOR_DEF("text_editor/highlighting/word_highlighted_color",Color(0.8,0.9,0.9,0.15)));
- get_text_edit()->add_color_override("number_color",EDITOR_DEF("text_editor/highlighting/number_color",Color(0.9,0.6,0.0,2)));
- get_text_edit()->add_color_override("function_color",EDITOR_DEF("text_editor/highlighting/function_color",Color(0.4,0.6,0.8)));
- get_text_edit()->add_color_override("member_variable_color",EDITOR_DEF("text_editor/highlighting/member_variable_color",Color(0.9,0.3,0.3)));
- get_text_edit()->add_color_override("mark_color", EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0,0.4,0.4,0.4)));
- get_text_edit()->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8,0.8,0.4,0.2)));
- get_text_edit()->add_color_override("search_result_color",EDITOR_DEF("text_editor/highlighting/search_result_color",Color(0.05,0.25,0.05,1)));
- get_text_edit()->add_color_override("search_result_border_color",EDITOR_DEF("text_editor/highlighting/search_result_border_color",Color(0.1,0.45,0.1,1)));
- get_text_edit()->add_color_override("symbol_color",EDITOR_DEF("text_editor/highlighting/symbol_color",Color::hex(0x005291ff)));
-
- Color keyword_color= EDITOR_DEF("text_editor/highlighting/keyword_color",Color(0.5,0.0,0.2));
-
-
- List<String> keywords;
- ShaderLanguage::get_keyword_list(&keywords);
-
- if (shader.is_valid()) {
-
-
- for(const Map< StringName, Map<StringName,ShaderLanguage::DataType> >::Element *E=ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())).front();E;E=E->next()) {
-
- for (const Map<StringName,ShaderLanguage::DataType>::Element *F=E->get().front();F;F=F->next()) {
- keywords.push_back(F->key());
- }
-
- }
-
- for(const Set<String>::Element *E =ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())).front();E;E=E->next()) {
-
- keywords.push_back(E->get());
-
- }
- }
-
-
- for(List<String>::Element *E=keywords.front();E;E=E->next()) {
-
- get_text_edit()->add_keyword_color(E->get(),keyword_color);
- }
-
- //colorize core types
- //Color basetype_color= EDITOR_DEF("text_editor/base_type_color",Color(0.3,0.3,0.0));
-
-
- //colorize comments
- Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color",Color::hex(0x797e7eff));
-
- get_text_edit()->add_color_region("/*","*/",comment_color,false);
- get_text_edit()->add_color_region("//","",comment_color,false);
-
- /*//colorize strings
- Color string_color = EDITOR_DEF("text_editor/string_color",Color::hex(0x6b6f00ff));
-
- List<String> strings;
- shader->get_shader_mode()->get_string_delimiters(&strings);
-
- for (List<String>::Element *E=strings.front();E;E=E->next()) {
-
- String string = E->get();
- String beg = string.get_slice(" ",0);
- String end = string.get_slice_count(" ")>1?string.get_slice(" ",1):String();
- get_text_edit()->add_color_region(beg,end,string_color,end=="");
- }*/
-}
-
-void ShaderTextEditor::_code_complete_script(const String& p_code, List<String>* r_options) {
-
- print_line("code complete");
-
- ShaderLanguage sl;
- String calltip;
-
- Error err = sl.complete(p_code,ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())),ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())),r_options,calltip);
-
- if (calltip!="") {
- get_text_edit()->set_code_hint(calltip);
- }
-}
-
-void ShaderTextEditor::_validate_script() {
-
- String code=get_text_edit()->get_text();
- //List<StringName> params;
- //shader->get_param_list(&params);
-
- ShaderLanguage sl;
-
- Error err = sl.compile(code,ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())),ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())));
-
- if (err!=OK) {
- String error_text="error("+itos(sl.get_error_line())+"): "+sl.get_error_text();
- set_error(error_text);
- get_text_edit()->set_line_as_marked(sl.get_error_line(),true);
-
- } else {
- for(int i=0;i<get_text_edit()->get_line_count();i++)
- get_text_edit()->set_line_as_marked(i,false);
- set_error("");
- }
-
- emit_signal("script_changed");
-}
-
-void ShaderTextEditor::_bind_methods() {
-
-
- //ADD_SIGNAL( MethodInfo("script_changed") );
-
-}
-
-ShaderTextEditor::ShaderTextEditor() {
-
-
-}
-
-/*** SCRIPT EDITOR ******/
-
-
-
-void ShaderEditor::_menu_option(int p_option) {
-
-
- ShaderTextEditor *current = shader_editor;
-
- switch(p_option) {
- case EDIT_UNDO: {
-
-
- current->get_text_edit()->undo();
- } break;
- case EDIT_REDO: {
- current->get_text_edit()->redo();
-
- } break;
- case EDIT_CUT: {
-
- current->get_text_edit()->cut();
- } break;
- case EDIT_COPY: {
- current->get_text_edit()->copy();
-
- } break;
- case EDIT_PASTE: {
- current->get_text_edit()->paste();
-
- } break;
- case EDIT_SELECT_ALL: {
-
- current->get_text_edit()->select_all();
-
- } break;
- case SEARCH_FIND: {
-
- current->get_find_replace_bar()->popup_search();
- } break;
- case SEARCH_FIND_NEXT: {
-
- current->get_find_replace_bar()->search_next();
- } break;
- case SEARCH_FIND_PREV: {
-
- current->get_find_replace_bar()->search_prev();
- } break;
- case SEARCH_REPLACE: {
-
- current->get_find_replace_bar()->popup_replace();
- } break;
- //case SEARCH_LOCATE_SYMBOL: {
-
- //} break;
- case SEARCH_GOTO_LINE: {
-
- goto_line_dialog->popup_find_line(current->get_text_edit());
- } break;
-
- }
-}
-
-
-void ShaderEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
-
- }
- if (p_what==NOTIFICATION_DRAW) {
-
- RID ci = get_canvas_item();
- Ref<StyleBox> style = get_stylebox("panel","Panel");
- style->draw( ci, Rect2( Point2(), get_size() ) );
-
- }
-
-}
-
-
-
-Dictionary ShaderEditor::get_state() const {
-#if 0
- apply_shaders();
-
- Dictionary state;
-
- Array paths;
- int open=-1;
-
- for(int i=0;i<tab_container->get_child_count();i++) {
-
- ShaderTextEditor *ste = tab_container->get_child(i)->cast_to<ShaderTextEditor>();
- if (!ste)
- continue;
-
-
- Ref<Shader> shader = ste->get_edited_shader();
- if (shader->get_path()!="" && shader->get_path().find("local://")==-1 && shader->get_path().find("::")==-1) {
-
- paths.push_back(shader->get_path());
- } else {
-
-
- const Node *owner = _find_node_with_shader(get_root_node(),shader.get_ref_ptr());
- if (owner)
- paths.push_back(owner->get_path());
-
- }
-
- if (i==tab_container->get_current_tab())
- open=i;
- }
-
- if (paths.size())
- state["sources"]=paths;
- if (open!=-1)
- state["current"]=open;
-
-
- return state;
-#endif
- return Dictionary();
-}
-void ShaderEditor::set_state(const Dictionary& p_state) {
-#if 0
- print_line("setting state..");
- if (!p_state.has("sources"))
- return; //bleh
-
- Array sources = p_state["sources"];
- for(int i=0;i<sources.size();i++) {
-
- Variant source=sources[i];
-
- Ref<Shader> shader;
-
- if (source.get_type()==Variant::NODE_PATH) {
-
- print_line("cain find owner at path "+String(source));
- Node *owner=get_root_node()->get_node(source);
- if (!owner)
- continue;
-
- shader = owner->get_shader();
- } else if (source.get_type()==Variant::STRING) {
-
- print_line("loading at path "+String(source));
- shader = ResourceLoader::load(source,"Shader");
- }
-
- print_line("found shader at "+String(source)+"? - "+itos(shader.is_null()));
- if (shader.is_null()) //ah well..
- continue;
-
- get_scene()->get_root_node()->call("_resource_selected",shader);
- }
-
- if (p_state.has("current"))
- tab_container->set_current_tab(p_state["current"]);
-#endif
-}
-void ShaderEditor::clear() {
-
-}
-
-void ShaderEditor::_params_changed() {
-
-
- shader_editor->_validate_script();
-}
-
-void ShaderEditor::_editor_settings_changed() {
-
- shader_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete"));
- shader_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file"));
- shader_editor->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/indent/tab_size"));
- shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs"));
- shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers"));
- shader_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting"));
- shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences"));
- shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink"));
- shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
- shader_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
- shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
-}
-
-void ShaderEditor::_bind_methods() {
-
- ClassDB::bind_method("_editor_settings_changed",&ShaderEditor::_editor_settings_changed);
-
- ClassDB::bind_method("_menu_option",&ShaderEditor::_menu_option);
- ClassDB::bind_method("_params_changed",&ShaderEditor::_params_changed);
- ClassDB::bind_method("apply_shaders",&ShaderEditor::apply_shaders);
- //ClassDB::bind_method("_close_current_tab",&ShaderEditor::_close_current_tab);
-}
-
-void ShaderEditor::ensure_select_current() {
-
-/*
- if (tab_container->get_child_count() && tab_container->get_current_tab()>=0) {
-
- ShaderTextEditor *ste = tab_container->get_child(tab_container->get_current_tab())->cast_to<ShaderTextEditor>();
- if (!ste)
- return;
- Ref<Shader> shader = ste->get_edited_shader();
- get_scene()->get_root_node()->call("_resource_selected",shader);
- }*/
-}
-
-void ShaderEditor::edit(const Ref<Shader>& p_shader) {
-
- if (p_shader.is_null())
- return;
-
-
- shader=p_shader;
-
- shader_editor->set_edited_shader(p_shader);
-
- //vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX);
- // see if already has it
-
-
-}
-
-void ShaderEditor::save_external_data() {
-
- if (shader.is_null())
- return;
- apply_shaders();
-
- if (shader->get_path()!="" && shader->get_path().find("local://")==-1 &&shader->get_path().find("::")==-1) {
- //external shader, save it
- ResourceSaver::save(shader->get_path(),shader);
- }
-}
-
-void ShaderEditor::apply_shaders() {
-
-
- if (shader.is_valid()) {
- shader->set_code(shader_editor->get_text_edit()->get_text());
- shader->set_edited(true);
- }
-}
-
-
-ShaderEditor::ShaderEditor() {
-
-
- HBoxContainer *hbc = memnew( HBoxContainer);
-
- add_child(hbc);
-
- edit_menu = memnew( MenuButton );
- hbc->add_child(edit_menu);
- edit_menu->set_pos(Point2(5,-1));
- edit_menu->set_text(TTR("Edit"));
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/undo", TTR("Undo"), KEY_MASK_CMD|KEY_Z), EDIT_UNDO);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/redo", TTR("Redo"), KEY_MASK_CMD|KEY_Y), EDIT_REDO);
- edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/cut", TTR("Cut"), KEY_MASK_CMD|KEY_X), EDIT_CUT);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy", TTR("Copy"), KEY_MASK_CMD|KEY_C), EDIT_COPY);
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/paste", TTR("Paste"), KEY_MASK_CMD|KEY_V), EDIT_PASTE);
- edit_menu->get_popup()->add_separator();
- edit_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/select_all", TTR("Select All"), KEY_MASK_CMD|KEY_A), EDIT_SELECT_ALL);
- edit_menu->get_popup()->connect("id_pressed", this,"_menu_option");
-
-
- search_menu = memnew( MenuButton );
- hbc->add_child(search_menu);
- search_menu->set_pos(Point2(38,-1));
- search_menu->set_text(TTR("Search"));
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find", TTR("Find.."), KEY_MASK_CMD|KEY_F), SEARCH_FIND);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_next", TTR("Find Next"), KEY_F3), SEARCH_FIND_NEXT);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT|KEY_F3), SEARCH_FIND_PREV);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/replace", TTR("Replace.."), KEY_MASK_CMD|KEY_R), SEARCH_REPLACE);
- search_menu->get_popup()->add_separator();
- //search_menu->get_popup()->add_item("Locate Symbol..",SEARCH_LOCATE_SYMBOL,KEY_MASK_CMD|KEY_K);
- search_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/goto_line", TTR("Goto Line.."), KEY_MASK_CMD|KEY_L), SEARCH_GOTO_LINE);
- search_menu->get_popup()->connect("id_pressed", this,"_menu_option");
-
-
- goto_line_dialog = memnew(GotoLineDialog);
- add_child(goto_line_dialog);
-
- shader_editor = memnew( ShaderTextEditor );
- add_child(shader_editor);
- shader_editor->set_v_size_flags(SIZE_EXPAND_FILL);
-
-
- shader_editor->connect("script_changed", this,"apply_shaders");
- EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed");
-
- _editor_settings_changed();
-}
-
-
-void ShaderEditorPlugin::edit(Object *p_object) {
-
- Shader* s = p_object->cast_to<Shader>();
- shader_editor->edit(s);
-
-}
-
-bool ShaderEditorPlugin::handles(Object *p_object) const {
-
- bool handles = true;
- Shader *shader=p_object->cast_to<Shader>();
- /*
- if (!shader || shader->cast_to<ShaderGraph>()) // Dont handle ShaderGraph's
- handles = false;
- */
-
- return shader!=NULL;
-}
-
-void ShaderEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- button->show();
- editor->make_bottom_panel_item_visible(shader_editor);
-
- } else {
-
- button->hide();
- if (shader_editor->is_visible_in_tree())
- editor->hide_bottom_panel();
- shader_editor->apply_shaders();
-
- }
-
-}
-
-void ShaderEditorPlugin::selected_notify() {
-
- shader_editor->ensure_select_current();
-}
-
-Dictionary ShaderEditorPlugin::get_state() const {
-
- return shader_editor->get_state();
-}
-
-void ShaderEditorPlugin::set_state(const Dictionary& p_state) {
-
- shader_editor->set_state(p_state);
-}
-void ShaderEditorPlugin::clear() {
-
- shader_editor->clear();
-}
-
-void ShaderEditorPlugin::save_external_data() {
-
- shader_editor->save_external_data();
-}
-
-void ShaderEditorPlugin::apply_changes() {
-
- shader_editor->apply_shaders();
-}
-
-ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) {
-
-
- editor=p_node;
- shader_editor = memnew( ShaderEditor );
-
- shader_editor->set_custom_minimum_size(Size2(0,300));
- button=editor->add_bottom_panel_item("Shader",shader_editor);
-
-}
-
-
-ShaderEditorPlugin::~ShaderEditorPlugin() {
-}
-
-
diff --git a/tools/editor/plugins/shader_editor_plugin.h b/tools/editor/plugins/shader_editor_plugin.h
deleted file mode 100644
index e94b4d9c25..0000000000
--- a/tools/editor/plugins/shader_editor_plugin.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*************************************************************************/
-/* shader_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SHADER_EDITOR_PLUGIN_H
-#define SHADER_EDITOR_PLUGIN_H
-
-#include "tools/editor/code_editor.h"
-#include "tools/editor/editor_plugin.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/text_edit.h"
-#include "scene/gui/menu_button.h"
-#include "scene/main/timer.h"
-#include "scene/resources/shader.h"
-#include "servers/visual/shader_language.h"
-
-class ShaderTextEditor : public CodeTextEditor {
-
- GDCLASS( ShaderTextEditor, CodeTextEditor );
-
- Ref<Shader> shader;
-
-protected:
-
- static void _bind_methods();
- virtual void _load_theme_settings();
-
- virtual void _code_complete_script(const String& p_code, List<String>* r_options);
-
-public:
-
- virtual void _validate_script();
-
-
- Ref<Shader> get_edited_shader() const;
- void set_edited_shader(const Ref<Shader>& p_shader);
- ShaderTextEditor();
-
-};
-
-
-class ShaderEditor : public VBoxContainer {
-
- GDCLASS(ShaderEditor, VBoxContainer );
-
- enum {
-
- EDIT_UNDO,
- EDIT_REDO,
- EDIT_CUT,
- EDIT_COPY,
- EDIT_PASTE,
- EDIT_SELECT_ALL,
- SEARCH_FIND,
- SEARCH_FIND_NEXT,
- SEARCH_FIND_PREV,
- SEARCH_REPLACE,
- //SEARCH_LOCATE_SYMBOL,
- SEARCH_GOTO_LINE,
-
- };
-
- MenuButton *edit_menu;
- MenuButton *search_menu;
- MenuButton *settings_menu;
- uint64_t idle;
-
- GotoLineDialog *goto_line_dialog;
- ConfirmationDialog *erase_tab_confirm;
-
-
- ShaderTextEditor *shader_editor;
-
-
- void _menu_option(int p_optin);
- void _params_changed();
- mutable Ref<Shader> shader;
-
-
- void _editor_settings_changed();
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void apply_shaders();
-
- void ensure_select_current();
- void edit(const Ref<Shader>& p_shader);
-
- Dictionary get_state() const;
- void set_state(const Dictionary& p_state);
- void clear();
-
- virtual Size2 get_minimum_size() const { return Size2(0,200); }
- void save_external_data();
-
- ShaderEditor();
-};
-
-class ShaderEditorPlugin : public EditorPlugin {
-
- GDCLASS( ShaderEditorPlugin, EditorPlugin );
-
- bool _2d;
- ShaderEditor *shader_editor;
- EditorNode *editor;
- Button *button;
-
-public:
-
- virtual String get_name() const { return "Shader"; }
- 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);
- virtual void selected_notify();
-
- Dictionary get_state() const;
- virtual void set_state(const Dictionary& p_state);
- virtual void clear();
-
- virtual void save_external_data();
- virtual void apply_changes();
-
- ShaderEditorPlugin(EditorNode *p_node);
- ~ShaderEditorPlugin();
-
-};
-
-#endif
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp
deleted file mode 100644
index d86fec11d8..0000000000
--- a/tools/editor/plugins/shader_graph_editor_plugin.cpp
+++ /dev/null
@@ -1,2948 +0,0 @@
-/*************************************************************************/
-/* shader_graph_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "shader_graph_editor_plugin.h"
-
-#if 0
-
-#include "scene/gui/check_box.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/panel.h"
-#include "spatial_editor_plugin.h"
-#include "os/keyboard.h"
-#include "canvas_item_editor_plugin.h"
-
-void GraphColorRampEdit::_gui_input(const InputEvent& p_event) {
-
- if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) {
-
- points.remove(grabbed);
- grabbed=-1;
- update();
- emit_signal("ramp_changed");
- accept_event();
- }
-
- if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
-
- update();
- int x = p_event.mouse_button.x;
- int total_w = get_size().width-get_size().height-3;
- if (x>total_w+3) {
-
- if (grabbed==-1)
- return;
- Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10);
- picker->set_color(points[grabbed].color);
- popup->set_pos(get_global_pos()-Size2(0,ms.height));
- popup->set_size(ms);
- popup->popup();
- return;
- }
-
-
- float ofs = CLAMP(x/float(total_w),0,1);
-
- grabbed=-1;
- grabbing=true;
- int pos=-1;
- for(int i=0;i<points.size();i++) {
-
- if (ABS(x-points[i].offset*total_w)<4) {
- grabbed=i;
- }
- if (points[i].offset<ofs)
- pos=i;
- }
-
- grabbed_at=ofs;
- //grab or select
- if (grabbed!=-1) {
- return;
- }
- //insert
-
-
- Point p;
- p.offset=ofs;
-
- Point prev;
- Point next;
-
- if (pos==-1) {
-
- prev.color=Color(0,0,0);
- prev.offset=0;
- if (points.size()) {
- next=points[0];
- } else {
- next.color=Color(1,1,1);
- next.offset=1.0;
- }
- } else {
-
- if (pos==points.size()-1) {
- next.color=Color(1,1,1);
- next.offset=1.0;
- } else {
- next=points[pos+1];
- }
- prev=points[pos];
-
- }
-
- p.color=prev.color.linear_interpolate(next.color,(p.offset-prev.offset)/(next.offset-prev.offset));
-
- points.push_back(p);
- points.sort();
- for(int i=0;i<points.size();i++) {
- if (points[i].offset==ofs) {
- grabbed=i;
- break;
- }
- }
-
- emit_signal("ramp_changed");
-
- }
-
- if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) {
-
- if (grabbing) {
- grabbing=false;
- emit_signal("ramp_changed");
- }
- update();
- }
-
- if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) {
-
- int total_w = get_size().width-get_size().height-3;
-
- int x = p_event.mouse_motion.x;
- float newofs = CLAMP(x/float(total_w),0,1);
-
- bool valid=true;
- for(int i=0;i<points.size();i++) {
-
- if (points[i].offset==newofs && i!=grabbed) {
- valid=false;
- }
- }
-
- if (!valid)
- return;
-
- points[grabbed].offset=newofs;
-
- points.sort();
- for(int i=0;i<points.size();i++) {
- if (points[i].offset==newofs) {
- grabbed=i;
- break;
- }
- }
-
- emit_signal("ramp_changed");
-
- update();
- }
-}
-
-void GraphColorRampEdit::_notification(int p_what){
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- if (!picker->is_connected("color_changed",this,"_color_changed")) {
- picker->connect("color_changed",this,"_color_changed");
- }
- }
- if (p_what==NOTIFICATION_DRAW) {
-
-
- Point prev;
- prev.offset=0;
- prev.color=Color(0,0,0);
-
- int h = get_size().y;
- int total_w = get_size().width-get_size().height-3;
-
- for(int i=-1;i<points.size();i++) {
-
- Point next;
- if (i+1==points.size()) {
- next.color=Color(1,1,1);
- next.offset=1;
- } else {
- next=points[i+1];
- }
-
- if (prev.offset==next.offset) {
- prev=next;
- continue;
- }
-
- Vector<Vector2> points;
- Vector<Color> colors;
- points.push_back(Vector2(prev.offset*total_w,h));
- points.push_back(Vector2(prev.offset*total_w,0));
- points.push_back(Vector2(next.offset*total_w,0));
- points.push_back(Vector2(next.offset*total_w,h));
- colors.push_back(prev.color);
- colors.push_back(prev.color);
- colors.push_back(next.color);
- colors.push_back(next.color);
- draw_primitive(points,colors,Vector<Point2>());
- prev=next;
- }
-
- for(int i=0;i<points.size();i++) {
-
- Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8);
-
- draw_line(Vector2(points[i].offset*total_w,0),Vector2(points[i].offset*total_w,h-1),Color(0,0,0,0.7));
- draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w-1,h-1),col);
- draw_line(Vector2(points[i].offset*total_w+1,h/2),Vector2(points[i].offset*total_w+1,h-1),col);
- draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w+1,h/2),col);
- draw_line(Vector2(points[i].offset*total_w-1,h-1),Vector2(points[i].offset*total_w+1,h-1),col);
-
- }
-
- if (grabbed!=-1) {
-
- draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color);
- }
-
- if (has_focus()) {
-
- draw_line(Vector2(-1,-1),Vector2(total_w+1,-1),Color(1,1,1,0.6));
- draw_line(Vector2(total_w+1,-1),Vector2(total_w+1,h+1),Color(1,1,1,0.6));
- draw_line(Vector2(total_w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6));
- draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6));
- }
-
- }
-}
-
-Size2 GraphColorRampEdit::get_minimum_size() const {
-
- return Vector2(0,16);
-}
-
-
-void GraphColorRampEdit::_color_changed(const Color& p_color) {
-
- if (grabbed==-1)
- return;
- points[grabbed].color=p_color;
- update();
- emit_signal("ramp_changed");
-
-}
-
-void GraphColorRampEdit::set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors) {
-
- ERR_FAIL_COND(p_offsets.size()!=p_colors.size());
- points.clear();
- for(int i=0;i<p_offsets.size();i++) {
- Point p;
- p.offset=p_offsets[i];
- p.color=p_colors[i];
- points.push_back(p);
- }
-
- points.sort();
- update();
-}
-
-Vector<float> GraphColorRampEdit::get_offsets() const{
- Vector<float> ret;
- for(int i=0;i<points.size();i++)
- ret.push_back(points[i].offset);
- return ret;
-}
-Vector<Color> GraphColorRampEdit::get_colors() const{
-
- Vector<Color> ret;
- for(int i=0;i<points.size();i++)
- ret.push_back(points[i].color);
- return ret;
-}
-
-
-void GraphColorRampEdit::_bind_methods(){
-
- ClassDB::bind_method(_MD("_gui_input"),&GraphColorRampEdit::_gui_input);
- ClassDB::bind_method(_MD("_color_changed"),&GraphColorRampEdit::_color_changed);
- ADD_SIGNAL(MethodInfo("ramp_changed"));
-}
-
-GraphColorRampEdit::GraphColorRampEdit(){
-
- grabbed=-1;
- grabbing=false;
- set_focus_mode(FOCUS_ALL);
-
- popup = memnew( PopupPanel );
- picker = memnew( ColorPicker );
- popup->add_child(picker);
- /popup->set_child_rect(picker);
- add_child(popup);
-
-}
-////////////
-
-void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
-
- if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) {
-
- points.remove(grabbed);
- grabbed=-1;
- update();
- emit_signal("curve_changed");
- accept_event();
- }
-
- if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) {
-
- update();
- Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size();
- p.y=1.0-p.y;
- grabbed=-1;
- grabbing=true;
-
- for(int i=0;i<points.size();i++) {
-
- Vector2 ps = p*get_size();
- Vector2 pt = Vector2(points[i].offset,points[i].height)*get_size();
- if (ps.distance_to(pt)<4) {
- grabbed=i;
- }
-
- }
-
-
- //grab or select
- if (grabbed!=-1) {
- return;
- }
- //insert
-
-
- Point np;
- np.offset=p.x;
- np.height=p.y;
-
- points.push_back(np);
- points.sort();
- for(int i=0;i<points.size();i++) {
- if (points[i].offset==p.x && points[i].height==p.y) {
- grabbed=i;
- break;
- }
- }
-
- emit_signal("curve_changed");
-
- }
-
- if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) {
-
- if (grabbing) {
- grabbing=false;
- emit_signal("curve_changed");
- }
- update();
- }
-
- if (p_event.type==InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) {
-
- Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size();
- p.y=1.0-p.y;
-
- p.x = CLAMP(p.x,0.0,1.0);
- p.y = CLAMP(p.y,0.0,1.0);
-
- bool valid=true;
-
- for(int i=0;i<points.size();i++) {
-
- if (points[i].offset==p.x && points[i].height==p.y && i!=grabbed) {
- valid=false;
- }
- }
-
- if (!valid)
- return;
-
- points[grabbed].offset=p.x;
- points[grabbed].height=p.y;
-
- points.sort();
- for(int i=0;i<points.size();i++) {
- if (points[i].offset==p.x && points[i].height==p.y) {
- grabbed=i;
- break;
- }
- }
-
- emit_signal("curve_changed");
-
- update();
- }
-}
-
-void GraphCurveMapEdit::_plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d) {
-
- float geometry[4][4];
- float tmp1[4][4];
- float tmp2[4][4];
- float deltas[4][4];
- double x, dx, dx2, dx3;
- double y, dy, dy2, dy3;
- double d, d2, d3;
- int lastx, lasty;
- int newx, newy;
- int ntimes;
- int i,j;
-
- int xmax=get_size().x;
- int ymax=get_size().y;
-
- /* construct the geometry matrix from the segment */
- for (i = 0; i < 4; i++) {
- geometry[i][2] = 0;
- geometry[i][3] = 0;
- }
-
- geometry[0][0] = (p_a[0] * xmax);
- geometry[1][0] = (p_b[0] * xmax);
- geometry[2][0] = (p_c[0] * xmax);
- geometry[3][0] = (p_d[0] * xmax);
-
- geometry[0][1] = (p_a[1] * ymax);
- geometry[1][1] = (p_b[1] * ymax);
- geometry[2][1] = (p_c[1] * ymax);
- geometry[3][1] = (p_d[1] * ymax);
-
- /* subdivide the curve ntimes (1000) times */
- ntimes = 4 * xmax;
- /* ntimes can be adjusted to give a finer or coarser curve */
- d = 1.0 / ntimes;
- d2 = d * d;
- d3 = d * d * d;
-
- /* construct a temporary matrix for determining the forward differencing deltas */
- tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1;
- tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0;
- tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0;
- tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0;
-
- /* compose the basis and geometry matrices */
-
- static const float CR_basis[4][4] = {
- { -0.5, 1.5, -1.5, 0.5 },
- { 1.0, -2.5, 2.0, -0.5 },
- { -0.5, 0.0, 0.5, 0.0 },
- { 0.0, 1.0, 0.0, 0.0 },
- };
-
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] +
- CR_basis[i][1] * geometry[1][j] +
- CR_basis[i][2] * geometry[2][j] +
- CR_basis[i][3] * geometry[3][j]);
- }
- }
- /* compose the above results to get the deltas matrix */
-
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- deltas[i][j] = (tmp2[i][0] * tmp1[0][j] +
- tmp2[i][1] * tmp1[1][j] +
- tmp2[i][2] * tmp1[2][j] +
- tmp2[i][3] * tmp1[3][j]);
- }
- }
-
-
- /* extract the x deltas */
- x = deltas[0][0];
- dx = deltas[1][0];
- dx2 = deltas[2][0];
- dx3 = deltas[3][0];
-
- /* extract the y deltas */
- y = deltas[0][1];
- dy = deltas[1][1];
- dy2 = deltas[2][1];
- dy3 = deltas[3][1];
-
-
- lastx = CLAMP (x, 0, xmax);
- lasty = CLAMP (y, 0, ymax);
-
- /* if (fix255)
- {
- cd->curve[cd->outline][lastx] = lasty;
- }
- else
- {
- cd->curve_ptr[cd->outline][lastx] = lasty;
- if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax);
- }
-*/
- /* loop over the curve */
- for (i = 0; i < ntimes; i++)
- {
- /* increment the x values */
- x += dx;
- dx += dx2;
- dx2 += dx3;
-
- /* increment the y values */
- y += dy;
- dy += dy2;
- dy2 += dy3;
-
- newx = CLAMP ((Math::round (x)), 0, xmax);
- newy = CLAMP ((Math::round (y)), 0, ymax);
-
- /* if this point is different than the last one...then draw it */
- if ((lastx != newx) || (lasty != newy))
- {
-#if 0
- if(fix255)
- {
- /* use fixed array size (for the curve graph) */
- cd->curve[cd->outline][newx] = newy;
- }
- else
- {
- /* use dynamic allocated curve_ptr (for the real curve) */
- cd->curve_ptr[cd->outline][newx] = newy;
-
- if(gb_debug) printf("outline: %d cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy);
- }
-#endif
- draw_line(Vector2(lastx,ymax-lasty),Vector2(newx,ymax-newy),Color(0.8,0.8,0.8,0.8),2.0);
- }
-
- lastx = newx;
- lasty = newy;
- }
-}
-
-
-void GraphCurveMapEdit::_notification(int p_what){
-
- if (p_what==NOTIFICATION_DRAW) {
-
- draw_style_box(get_stylebox("bg","Tree"),Rect2(Point2(),get_size()));
-
- int w = get_size().x;
- int h = get_size().y;
-
- Vector2 prev=Vector2(0,0);
- Vector2 prev2=Vector2(0,0);
-
- for(int i=-1;i<points.size();i++) {
-
- Vector2 next;
- Vector2 next2;
- if (i+1>=points.size()) {
- next=Vector2(1,1);
- } else {
- next=Vector2(points[i+1].offset,points[i+1].height);
- }
-
- if (i+2>=points.size()) {
- next2=Vector2(1,1);
- } else {
- next2=Vector2(points[i+2].offset,points[i+2].height);
- }
-
- /*if (i==-1 && prev.offset==next.offset) {
- prev=next;
- continue;
- }*/
-
- _plot_curve(prev2,prev,next,next2);
-
- prev2=prev;
- prev=next;
- }
-
- for(int i=0;i<points.size();i++) {
-
- Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8);
-
-
- draw_rect(Rect2( Vector2(points[i].offset,1.0-points[i].height)*get_size()-Vector2(2,2),Vector2(5,5)),col);
- }
-
- /* if (grabbed!=-1) {
-
- draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color);
- }
-*/
- if (has_focus()) {
-
- draw_line(Vector2(-1,-1),Vector2(w+1,-1),Color(1,1,1,0.6));
- draw_line(Vector2(w+1,-1),Vector2(w+1,h+1),Color(1,1,1,0.6));
- draw_line(Vector2(w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6));
- draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6));
- }
-
- }
-}
-
-Size2 GraphCurveMapEdit::get_minimum_size() const {
-
- return Vector2(64,64);
-}
-
-
-
-void GraphCurveMapEdit::set_points(const Vector<Vector2>& p_points) {
-
-
- points.clear();
- for(int i=0;i<p_points.size();i++) {
- Point p;
- p.offset=p_points[i].x;
- p.height=p_points[i].y;
- points.push_back(p);
- }
-
- points.sort();
- update();
-}
-
-Vector<Vector2> GraphCurveMapEdit::get_points() const {
- Vector<Vector2> ret;
- for(int i=0;i<points.size();i++)
- ret.push_back(Vector2(points[i].offset,points[i].height));
- return ret;
-}
-
-void GraphCurveMapEdit::_bind_methods(){
-
- ClassDB::bind_method(_MD("_gui_input"),&GraphCurveMapEdit::_gui_input);
- ADD_SIGNAL(MethodInfo("curve_changed"));
-}
-
-GraphCurveMapEdit::GraphCurveMapEdit(){
-
- grabbed=-1;
- grabbing=false;
- set_focus_mode(FOCUS_ALL);
-
-}
-
-
-////cbacks
-///
-void ShaderGraphView::_scalar_const_changed(double p_value,int p_id) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Scalar Constant"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,p_value);
- ur->add_undo_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,graph->scalar_const_node_get_value(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-
-void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){
-
- Vector3 val;
- for(int i=0;i<p_arr.size();i++) {
- val[i]=p_arr[i].call("get_val");
- }
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Vec Constant"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(graph.ptr(),"vec_const_node_set_value",type,p_id,val);
- ur->add_undo_method(graph.ptr(),"vec_const_node_set_value",type,p_id,graph->vec_const_node_get_value(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-void ShaderGraphView::_rgb_const_changed(const Color& p_color, int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change RGB Constant"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,p_color);
- ur->add_undo_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,graph->rgb_const_node_get_value(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-void ShaderGraphView::_scalar_op_changed(int p_op, int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Scalar Operator"));
- ur->add_do_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,p_op);
- ur->add_undo_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,graph->scalar_op_node_get_op(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-void ShaderGraphView::_vec_op_changed(int p_op, int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Vec Operator"));
- ur->add_do_method(graph.ptr(),"vec_op_node_set_op",type,p_id,p_op);
- ur->add_undo_method(graph.ptr(),"vec_op_node_set_op",type,p_id,graph->vec_op_node_get_op(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-void ShaderGraphView::_vec_scalar_op_changed(int p_op, int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Vec Scalar Operator"));
- ur->add_do_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,p_op);
- ur->add_undo_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,graph->vec_scalar_op_node_get_op(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-void ShaderGraphView::_rgb_op_changed(int p_op, int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change RGB Operator"));
- ur->add_do_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,p_op);
- ur->add_undo_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,graph->rgb_op_node_get_op(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-void ShaderGraphView::_xform_inv_rev_changed(bool p_enabled, int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Toggle Rot Only"));
- ur->add_do_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,p_enabled);
- ur->add_undo_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,graph->xform_vec_mult_node_get_no_translation(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-void ShaderGraphView::_scalar_func_changed(int p_func, int p_id){
-
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Scalar Function"));
- ur->add_do_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,p_func);
- ur->add_undo_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,graph->scalar_func_node_get_function(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-void ShaderGraphView::_vec_func_changed(int p_func, int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Vec Function"));
- ur->add_do_method(graph.ptr(),"vec_func_node_set_function",type,p_id,p_func);
- ur->add_undo_method(graph.ptr(),"vec_func_node_set_function",type,p_id,graph->vec_func_node_get_function(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-void ShaderGraphView::_scalar_input_changed(double p_value,int p_id){
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Scalar Uniform"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,p_value);
- ur->add_undo_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,graph->scalar_input_node_get_value(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){
-
- Vector3 val;
- for(int i=0;i<p_arr.size();i++) {
- val[i]=p_arr[i].call("get_val");
- }
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Vec Uniform"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(graph.ptr(),"vec_input_node_set_value",type,p_id,val);
- ur->add_undo_method(graph.ptr(),"vec_input_node_set_value",type,p_id,graph->vec_input_node_get_value(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){
-
-
- ToolButton *tb = p_button->cast_to<ToolButton>();
- ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
- ped_popup->set_size(tb->get_size());
- edited_id=p_id;
- edited_def=-1;
- ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_input_node_get_value(type,p_id),PROPERTY_HINT_NONE,"");
- ped_popup->popup();
-
-}
-void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){
-
- ToolButton *tb = p_button->cast_to<ToolButton>();
- ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
- ped_popup->set_size(tb->get_size());
- edited_id=p_id;
- edited_def=-1;
- ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_const_node_get_value(type,p_id),PROPERTY_HINT_NONE,"");
- ped_popup->popup();
-
-}
-
-void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){
-
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change RGB Uniform"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,p_color);
- ur->add_undo_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,graph->rgb_input_node_get_value(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-void ShaderGraphView::_tex_input_change(int p_id, Node *p_button){
-
-
-}
-void ShaderGraphView::_cube_input_change(int p_id){
-
-
-}
-
-void ShaderGraphView::_variant_edited() {
-
- if (edited_def != -1) {
-
- Variant v = ped_popup->get_variant();
- Variant v2 = graph->default_get_value(type,edited_id,edited_def);
- if (v2.get_type() == Variant::NIL)
- switch (v.get_type()) {
- case Variant::VECTOR3:
- v2=Vector3();
- break;
- case Variant::REAL:
- v2=0.0;
- break;
- case Variant::TRANSFORM:
- v2=Transform();
- break;
- case Variant::COLOR:
- v2=Color();
- break;
- default: {}
- }
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Default Value"));
- ur->add_do_method(graph.ptr(),"default_set_value",type,edited_id,edited_def, v);
- ur->add_undo_method(graph.ptr(),"default_set_value",type,edited_id,edited_def, v2);
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
- return;
- }
-
- if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change XForm Uniform"));
- ur->add_do_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,ped_popup->get_variant());
- ur->add_undo_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,graph->xform_const_node_get_value(type,edited_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
- }
-
-
- if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_INPUT) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change XForm Uniform"));
- ur->add_do_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,ped_popup->get_variant());
- ur->add_undo_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,graph->xform_input_node_get_value(type,edited_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
- }
-
- if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_TEXTURE_INPUT) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Texture Uniform"));
- ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,ped_popup->get_variant());
- ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,graph->texture_input_node_get_value(type,edited_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
- }
-
- if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_CUBEMAP_INPUT) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Cubemap Uniform"));
- ur->add_do_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,ped_popup->get_variant());
- ur->add_undo_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,graph->cubemap_input_node_get_value(type,edited_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
- }
-
-}
-
-void ShaderGraphView::_comment_edited(int p_id,Node* p_button) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- TextEdit *te=p_button->cast_to<TextEdit>();
- ur->create_action(TTR("Change Comment"),UndoRedo::MERGE_ENDS);
- ur->add_do_method(graph.ptr(),"comment_node_set_text",type,p_id,te->get_text());
- ur->add_undo_method(graph.ptr(),"comment_node_set_text",type,p_id,graph->comment_node_get_text(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-
-}
-
-void ShaderGraphView::_color_ramp_changed(int p_id,Node* p_ramp) {
-
- GraphColorRampEdit *cr=p_ramp->cast_to<GraphColorRampEdit>();
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
-
-
- Vector<float> offsets=cr->get_offsets();
- Vector<Color> colors=cr->get_colors();
-
- PoolVector<float> new_offsets;
- PoolVector<Color> new_colors;
- {
- new_offsets.resize(offsets.size());
- new_colors.resize(colors.size());
- PoolVector<float>::Write ow=new_offsets.write();
- PoolVector<Color>::Write cw=new_colors.write();
- for(int i=0;i<new_offsets.size();i++) {
- ow[i]=offsets[i];
- cw[i]=colors[i];
- }
-
- }
-
-
- PoolVector<float> old_offsets=graph->color_ramp_node_get_offsets(type,p_id);
- PoolVector<Color> old_colors=graph->color_ramp_node_get_colors(type,p_id);
-
- if (old_offsets.size()!=new_offsets.size())
- ur->create_action(TTR("Add/Remove to Color Ramp"));
- else
- ur->create_action(TTR("Modify Color Ramp"),UndoRedo::MERGE_ENDS);
-
- ur->add_do_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,new_colors,new_offsets);
- ur->add_undo_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,old_colors,old_offsets);
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-
-void ShaderGraphView::_curve_changed(int p_id,Node* p_curve) {
-
- GraphCurveMapEdit *cr=p_curve->cast_to<GraphCurveMapEdit>();
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
-
-
- Vector<Point2> points=cr->get_points();
-
- PoolVector<Vector2> new_points;
- {
- new_points.resize(points.size());
- PoolVector<Vector2>::Write ow=new_points.write();
- for(int i=0;i<new_points.size();i++) {
- ow[i]=points[i];
- }
-
- }
-
-
- PoolVector<Vector2> old_points=graph->curve_map_node_get_points(type,p_id);
-
- if (old_points.size()!=new_points.size())
- ur->create_action(TTR("Add/Remove to Curve Map"));
- else
- ur->create_action(TTR("Modify Curve Map"),UndoRedo::MERGE_ENDS);
-
- ur->add_do_method(graph.ptr(),"curve_map_node_set_points",type,p_id,new_points);
- ur->add_undo_method(graph.ptr(),"curve_map_node_set_points",type,p_id,old_points);
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
-}
-
-
-void ShaderGraphView::_input_name_changed(const String& p_name, int p_id, Node *p_line_edit) {
-
- LineEdit *le=p_line_edit->cast_to<LineEdit>();
- ERR_FAIL_COND(!le);
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Input Name"));
- ur->add_do_method(graph.ptr(),"input_node_set_name",type,p_id,p_name);
- ur->add_undo_method(graph.ptr(),"input_node_set_name",type,p_id,graph->input_node_get_name(type,p_id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- block_update=true;
- ur->commit_action();
- block_update=false;
- le->set_text(graph->input_node_get_name(type,p_id));
-}
-
-void ShaderGraphView::_tex_edited(int p_id,Node* p_button) {
-
- ToolButton *tb = p_button->cast_to<ToolButton>();
- ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
- ped_popup->set_size(tb->get_size());
- edited_id=p_id;
- edited_def=-1;
- ped_popup->edit(NULL,"",Variant::OBJECT,graph->texture_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"Texture");
-}
-
-void ShaderGraphView::_cube_edited(int p_id,Node* p_button) {
-
- ToolButton *tb = p_button->cast_to<ToolButton>();
- ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
- ped_popup->set_size(tb->get_size());
- edited_id=p_id;
- edited_def=-1;
- ped_popup->edit(NULL,"",Variant::OBJECT,graph->cubemap_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"CubeMap");
-}
-
-
-//////////////view/////////////
-
-
-void ShaderGraphView::_connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
-
- int from_idx=-1;
- int to_idx=-1;
- for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
-
- if (p_from==E->get()->get_name())
- from_idx=E->key();
- if (p_to==E->get()->get_name())
- to_idx=E->key();
- }
-
- ERR_FAIL_COND(from_idx==-1);
- ERR_FAIL_COND(to_idx==-1);
-
- ur->create_action(TTR("Connect Graph Nodes"));
-
- List<ShaderGraph::Connection> conns;
-
- graph->get_node_connections(type,&conns);
- //disconnect/reconnect dependencies
- ur->add_undo_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
- for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
-
- if (E->get().dst_id==to_idx && E->get().dst_slot==p_to_slot) {
- ur->add_do_method(graph.ptr(),"disconnect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
- ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
- }
- }
- ur->add_do_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
-
-
-}
-
-void ShaderGraphView::_disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
-
- int from_idx=-1;
- int to_idx=-1;
- for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
-
- if (p_from==E->get()->get_name())
- from_idx=E->key();
- if (p_to==E->get()->get_name())
- to_idx=E->key();
- }
-
- ERR_FAIL_COND(from_idx==-1);
- ERR_FAIL_COND(to_idx==-1);
-
- if (!graph->is_node_connected(type,from_idx,p_from_slot,to_idx,p_to_slot))
- return; //nothing to disconnect
-
- ur->create_action(TTR("Disconnect Graph Nodes"));
-
- List<ShaderGraph::Connection> conns;
-
- graph->get_node_connections(type,&conns);
- //disconnect/reconnect dependencies
- ur->add_do_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
- ur->add_undo_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
-
-
-}
-
-void ShaderGraphView::_node_removed(int p_id) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Remove Shader Graph Node"));
-
- ur->add_do_method(graph.ptr(),"node_remove",type,p_id);
- ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,p_id),p_id);
- ur->add_undo_method(graph.ptr(),"node_set_state",type,p_id,graph->node_get_state(type,p_id));
- List<ShaderGraph::Connection> conns;
-
- graph->get_node_connections(type,&conns);
- for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
-
- if (E->get().dst_id==p_id || E->get().src_id==p_id) {
- ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
- }
- }
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
-
-}
-
-void ShaderGraphView::_begin_node_move()
-{
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Move Shader Graph Node"));
-}
-
-void ShaderGraphView::_node_moved(const Vector2& p_from, const Vector2& p_to,int p_id) {
-
-
- ERR_FAIL_COND(!node_map.has(p_id));
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->add_do_method(this,"_move_node",p_id,p_to);
- ur->add_undo_method(this,"_move_node",p_id,p_from);
-}
-
-void ShaderGraphView::_end_node_move()
-{
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->commit_action();
-}
-
-void ShaderGraphView::_move_node(int p_id,const Vector2& p_to) {
-
- ERR_FAIL_COND(!node_map.has(p_id));
- node_map[p_id]->set_offset(p_to);
- graph->node_set_pos(type,p_id,p_to);
-}
-
-void ShaderGraphView::_duplicate_nodes_request()
-{
- Array s_id;
-
- for(Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
- ShaderGraph::NodeType t=graph->node_get_type(type, E->key());
- if (t==ShaderGraph::NODE_OUTPUT || t==ShaderGraph::NODE_INPUT)
- continue;
- GraphNode *gn = E->get();
- if (gn && gn->is_selected())
- s_id.push_back(E->key());
- }
-
- if (s_id.size()==0)
- return;
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Duplicate Graph Node(s)"));
- ur->add_do_method(this,"_duplicate_nodes",s_id);
- List<int> n_ids = graph->generate_ids(type, s_id.size());
- for (List<int>::Element *E=n_ids.front();E;E=E->next())
- ur->add_undo_method(graph.ptr(),"node_remove",type,E->get());
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
-
-}
-
-void ShaderGraphView::_duplicate_nodes(const Array &p_nodes)
-{
- List<int> n = List<int>();
- for (int i=0; i<p_nodes.size();i++)
- n.push_back(p_nodes.get(i));
- graph->duplicate_nodes(type, n);
- call_deferred("_update_graph");
-}
-
-void ShaderGraphView::_delete_nodes_request()
-{
- List<int> s_id=List<int>();
-
- for(Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
- ShaderGraph::NodeType t=graph->node_get_type(type, E->key());
- if (t==ShaderGraph::NODE_OUTPUT)
- continue;
- GraphNode *gn = E->get();
- if (gn && gn->is_selected())
- s_id.push_back(E->key());
- }
-
- if (s_id.size()==0)
- return;
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Delete Shader Graph Node(s)"));
-
- for (List<int>::Element *N=s_id.front();N;N=N->next()) {
- ur->add_do_method(graph.ptr(),"node_remove",type,N->get());
- ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,N->get()),N->get());
- ur->add_undo_method(graph.ptr(),"node_set_state",type,N->get(),graph->node_get_state(type,N->get()));
- List<ShaderGraph::Connection> conns;
-
- graph->get_node_connections(type,&conns);
- for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
-
- if (E->get().dst_id==N->get() || E->get().src_id==N->get()) {
- ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
- }
- }
- }
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
-
-}
-
-void ShaderGraphView::_default_changed(int p_id, Node *p_button, int p_param, int v_type, String p_hint)
-{
- ToolButton *tb = p_button->cast_to<ToolButton>();
- ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height));
- ped_popup->set_size(tb->get_size());
- edited_id=p_id;
- edited_def=p_param;
- Variant::Type vt = (Variant::Type)v_type;
- Variant v = graph->default_get_value(type,p_id,edited_def);
- int h=PROPERTY_HINT_NONE;
- if (v.get_type() == Variant::NIL)
- switch (vt) {
- case Variant::VECTOR3:
- v=Vector3();
- break;
- case Variant::REAL:
- h=PROPERTY_HINT_RANGE;
- v=0.0;
- break;
- case Variant::TRANSFORM:
- v=Transform();
- break;
- case Variant::COLOR:
- h=PROPERTY_HINT_COLOR_NO_ALPHA;
- v=Color();
- break;
- default: {}
- }
-
- ped_popup->edit(NULL,"",vt,v,h,p_hint);
-
- ped_popup->popup();
-}
-
-ToolButton *ShaderGraphView::make_label(String text, Variant::Type v_type) {
- ToolButton *l = memnew( ToolButton );
- l->set_text(text);
- l->set_text_align(ToolButton::ALIGN_LEFT);
- l->add_style_override("hover", l->get_stylebox("normal", "ToolButton"));
- l->add_style_override("pressed", l->get_stylebox("normal", "ToolButton"));
- l->add_style_override("focus", l->get_stylebox("normal", "ToolButton"));
- switch (v_type) {
- case Variant::REAL:
- l->set_icon(ped_popup->get_icon("Real", "EditorIcons"));
- break;
- case Variant::VECTOR3:
- l->set_icon(ped_popup->get_icon("Vector", "EditorIcons"));
- break;
- case Variant::TRANSFORM:
- l->set_icon(ped_popup->get_icon("Matrix", "EditorIcons"));
- break;
- case Variant::COLOR:
- l->set_icon(ped_popup->get_icon("Color", "EditorIcons"));
- break;
- default: {}
- }
- return l;
-}
-
-ToolButton *ShaderGraphView::make_editor(String text,GraphNode* gn,int p_id,int param,Variant::Type v_type, String p_hint) {
- ToolButton *edit = memnew( ToolButton );
- edit->set_text(text);
- edit->set_text_align(ToolButton::ALIGN_LEFT);
- edit->set_flat(false);
- edit->add_style_override("normal", gn->get_stylebox("defaultframe", "GraphNode"));
- edit->add_style_override("hover", gn->get_stylebox("defaultframe", "GraphNode"));
- edit->add_style_override("pressed", gn->get_stylebox("defaultframe", "GraphNode"));
- edit->add_style_override("focus", gn->get_stylebox("defaultfocus", "GraphNode"));
- edit->connect("pressed",this,"_default_changed",varray(p_id,edit,param,v_type,p_hint));
-
- switch (v_type) {
- case Variant::REAL:
- edit->set_icon(ped_popup->get_icon("Real", "EditorIcons"));
- break;
- case Variant::VECTOR3:
- edit->set_icon(ped_popup->get_icon("Vector", "EditorIcons"));
- break;
- case Variant::TRANSFORM:
- edit->set_icon(ped_popup->get_icon("Matrix", "EditorIcons"));
- break;
- case Variant::COLOR: {
- Image icon_color = Image(15,15,false,Image::FORMAT_RGB8);
- Color c = graph->default_get_value(type,p_id,param);
- for (int x=1;x<14;x++)
- for (int y=1;y<14;y++)
- icon_color.put_pixel(x,y,c);
- Ref<ImageTexture> t;
- t.instance();
- t->create_from_image(icon_color);
- edit->set_icon(t);
- } break;
- default: {}
- }
- return edit;
-}
-
-void ShaderGraphView::_create_node(int p_id) {
-
-
- GraphNode *gn = memnew( GraphNode );
- gn->set_show_close_button(true);
- Color typecol[4]={
- Color(0.9,0.4,1),
- Color(0.8,1,0.2),
- Color(1,0.2,0.2),
- Color(0,1,1)
- };
-
- const String hint_spin = "-65536,65535,0.001";
- const String hint_slider = "0.0,1.0,0.01,slider";
-
-
- switch(graph->node_get_type(type,p_id)) {
-
- case ShaderGraph::NODE_INPUT: {
-
- gn->set_title("Input");
-
- List<ShaderGraph::SlotInfo> si;
- ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si);
-
- int idx=0;
- for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) {
- ShaderGraph::SlotInfo& s=E->get();
- if (s.dir==ShaderGraph::SLOT_IN) {
-
- Label *l= memnew( Label );
- l->set_text(s.name);
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
- gn->set_slot(idx,false,0,Color(),true,s.type,typecol[s.type]);
- idx++;
- }
- }
-
- } break; // all inputs (case Shader type dependent)
- case ShaderGraph::NODE_SCALAR_CONST: {
- gn->set_title("Scalar");
- SpinBox *sb = memnew( SpinBox );
- sb->set_min(-100000);
- sb->set_max(100000);
- sb->set_step(0.001);
- sb->set_val(graph->scalar_const_node_get_value(type,p_id));
- sb->connect("value_changed",this,"_scalar_const_changed",varray(p_id));
- gn->add_child(sb);
- gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
- } break; //scalar constant
- case ShaderGraph::NODE_VEC_CONST: {
-
- gn->set_title("Vector");
- Array v3p(true);
- for(int i=0;i<3;i++) {
- HBoxContainer *hbc = memnew( HBoxContainer );
- Label *l = memnew( Label );
- l->set_text(String::chr('X'+i));
- hbc->add_child(l);
- SpinBox *sb = memnew( SpinBox );
- sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- sb->set_min(-100000);
- sb->set_max(100000);
- sb->set_step(0.001);
- sb->set_val(graph->vec_const_node_get_value(type,p_id)[i]);
- sb->connect("value_changed",this,"_vec_const_changed",varray(p_id,v3p));
- v3p.push_back(sb);
- hbc->add_child(sb);
- gn->add_child(hbc);
- }
- gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
-
- } break; //vec3 constant
- case ShaderGraph::NODE_RGB_CONST: {
-
- gn->set_title("Color");
- ColorPickerButton *cpb = memnew( ColorPickerButton );
- cpb->set_color(graph->rgb_const_node_get_value(type,p_id));
- cpb->connect("color_changed",this,"_rgb_const_changed",varray(p_id));
- gn->add_child(cpb);
- Label *l = memnew( Label );
- l->set_text("RGB");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
- l = memnew( Label );
- l->set_text("Alpha");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
-
- gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
- } break; //rgb constant (shows a color picker instead)
- case ShaderGraph::NODE_XFORM_CONST: {
- gn->set_title("XForm");
- ToolButton *edit = memnew( ToolButton );
- edit->set_text("edit..");
- edit->connect("pressed",this,"_xform_const_changed",varray(p_id,edit));
- gn->add_child(edit);
- gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
-
- } break; // 4x4 matrix constant
- case ShaderGraph::NODE_TIME: {
-
- gn->set_title("Time");
- Label *l = memnew( Label );
- l->set_text("(s)");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
- gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
- } break; // time in seconds
- case ShaderGraph::NODE_SCREEN_TEX: {
-
- gn->set_title("ScreenTex");
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (!graph->is_slot_connected(type,p_id,0)) {
- Vector3 v = graph->default_get_value(type, p_id, 0);
- hbc->add_child(make_editor("UV: " + v,gn,p_id,0,Variant::VECTOR3));
- } else {
- hbc->add_child(make_label("UV",Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("RGB")));
- gn->add_child(hbc);
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
-
- } break; // screen texture sampler (takes UV) (only usable in fragment case Shader)
- case ShaderGraph::NODE_SCALAR_OP: {
-
- gn->set_title("ScalarOp");
- static const char* op_name[ShaderGraph::SCALAR_MAX_OP]={
- ("Add"),
- ("Sub"),
- ("Mul"),
- ("Div"),
- ("Mod"),
- ("Pow"),
- ("Max"),
- ("Min"),
- ("Atan2")
- };
-
- OptionButton *ob = memnew( OptionButton );
- for(int i=0;i<ShaderGraph::SCALAR_MAX_OP;i++) {
-
- ob->add_item(op_name[i],i);
- }
-
- ob->select(graph->scalar_op_node_get_op(type,p_id));
- ob->connect("item_selected",this,"_scalar_op_changed",varray(p_id));
- gn->add_child(ob);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a",Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("a: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("out")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b",Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin));
- }
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
-
-
- } break; // scalar vs scalar op (mul: { } break; add: { } break; div: { } break; etc)
- case ShaderGraph::NODE_VEC_OP: {
-
- gn->set_title("VecOp");
- static const char* op_name[ShaderGraph::VEC_MAX_OP]={
- ("Add"),
- ("Sub"),
- ("Mul"),
- ("Div"),
- ("Mod"),
- ("Pow"),
- ("Max"),
- ("Min"),
- ("Cross")
- };
-
- OptionButton *ob = memnew( OptionButton );
- for(int i=0;i<ShaderGraph::VEC_MAX_OP;i++) {
-
- ob->add_item(op_name[i],i);
- }
-
- ob->select(graph->vec_op_node_get_op(type,p_id));
- ob->connect("item_selected",this,"_vec_op_changed",varray(p_id));
- gn->add_child(ob);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a",Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("out")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b",Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3));
- }
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
-
-
- } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc)
- case ShaderGraph::NODE_VEC_SCALAR_OP: {
-
- gn->set_title("VecScalarOp");
- static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={
- ("Mul"),
- ("Div"),
- ("Pow"),
- };
-
- OptionButton *ob = memnew( OptionButton );
- for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) {
-
- ob->add_item(op_name[i],i);
- }
-
- ob->select(graph->vec_scalar_op_node_get_op(type,p_id));
- ob->connect("item_selected",this,"_vec_scalar_op_changed",varray(p_id));
- gn->add_child(ob);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a",Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("out")));
- gn->add_child(hbc);
-
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b",Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin));
- }
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
-
-
- } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc)
- case ShaderGraph::NODE_RGB_OP: {
-
- gn->set_title("RGB Op");
- static const char* op_name[ShaderGraph::RGB_MAX_OP]={
- ("Screen"),
- ("Difference"),
- ("Darken"),
- ("Lighten"),
- ("Overlay"),
- ("Dodge"),
- ("Burn"),
- ("SoftLight"),
- ("HardLight")
- };
-
- OptionButton *ob = memnew( OptionButton );
- for(int i=0;i<ShaderGraph::RGB_MAX_OP;i++) {
-
- ob->add_item(op_name[i],i);
- }
-
- ob->select(graph->rgb_op_node_get_op(type,p_id));
- ob->connect("item_selected",this,"_rgb_op_changed",varray(p_id));
- gn->add_child(ob);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a",Variant::COLOR));
- } else {
- hbc->add_child(make_editor(String("a: "),gn,p_id,0,Variant::COLOR));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("out")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b",Variant::COLOR));
- } else {
- gn->add_child(make_editor(String("b: "),gn,p_id,1,Variant::COLOR));
- }
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
-
- } break; // vec3 vs vec3 rgb op (with scalar amount): { } break; like brighten: { } break; darken: { } break; burn: { } break; dodge: { } break; multiply: { } break; etc.
- case ShaderGraph::NODE_XFORM_MULT: {
-
- gn->set_title("XFMult");
- HBoxContainer *hbc = memnew( HBoxContainer );
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a",Variant::TRANSFORM));
- } else {
- hbc->add_child(make_editor(String("a: edit..."),gn,p_id,0,Variant::TRANSFORM));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("out")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b",Variant::TRANSFORM));
- } else {
- gn->add_child(make_editor(String("b: edit..."),gn,p_id,1,Variant::TRANSFORM));
- }
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],false,0,Color());
-
-
- } break; // mat4 x mat4
- case ShaderGraph::NODE_XFORM_VEC_MULT: {
-
- gn->set_title("XFVecMult");
-
- CheckBox *button = memnew (CheckBox("RotOnly"));
- button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id));
- button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id));
-
- gn->add_child(button);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("xf",Variant::TRANSFORM));
- } else {
- hbc->add_child(make_editor(String("xf: edit..."),gn,p_id,0,Variant::TRANSFORM));
- }
- hbc->add_spacer();
- Label *l = memnew(Label("out"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child( l);
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("a",Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("a: ")+v,gn,p_id,1,Variant::VECTOR3));
- }
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
-
- } break;
- case ShaderGraph::NODE_XFORM_VEC_INV_MULT: {
-
- gn->set_title("XFVecInvMult");
-
-
- CheckBox *button = memnew( CheckBox("RotOnly"));
- button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id));
- button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id));
-
- gn->add_child(button);
-
- if (graph->is_slot_connected(type, p_id, 0)) {
- gn->add_child(make_label("a",Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- gn->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 1)) {
- hbc->add_child(make_label("xf", Variant::TRANSFORM));
- } else {
- hbc->add_child(make_editor(String("xf: edit..."),gn,p_id,1,Variant::TRANSFORM));
- }
- hbc->add_spacer();
- Label *l = memnew(Label("out"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child( l);
- gn->add_child(hbc);
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
-
-
- } break; // mat4 x vec3 inverse mult (with no-translation option)
- case ShaderGraph::NODE_SCALAR_FUNC: {
-
- gn->set_title("ScalarFunc");
- static const char* func_name[ShaderGraph::SCALAR_MAX_FUNC]={
- ("Sin"),
- ("Cos"),
- ("Tan"),
- ("ASin"),
- ("ACos"),
- ("ATan"),
- ("SinH"),
- ("CosH"),
- ("TanH"),
- ("Log"),
- ("Exp"),
- ("Sqrt"),
- ("Abs"),
- ("Sign"),
- ("Floor"),
- ("Round"),
- ("Ceil"),
- ("Frac"),
- ("Satr"),
- ("Neg")
- };
-
- OptionButton *ob = memnew( OptionButton );
- for(int i=0;i<ShaderGraph::SCALAR_MAX_FUNC;i++) {
-
- ob->add_item(func_name[i],i);
- }
-
- ob->select(graph->scalar_func_node_get_function(type,p_id));
- ob->connect("item_selected",this,"_scalar_func_changed",varray(p_id));
- gn->add_child(ob);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("in", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("in: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("out")));
- gn->add_child(hbc);
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
-
- } break; // scalar function (sin: { } break; cos: { } break; etc)
- case ShaderGraph::NODE_VEC_FUNC: {
-
-
-
- gn->set_title("VecFunc");
- static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={
- ("Normalize"),
- ("Saturate"),
- ("Negate"),
- ("Reciprocal"),
- ("RGB to HSV"),
- ("HSV to RGB"),
- };
-
- OptionButton *ob = memnew( OptionButton );
- for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) {
-
- ob->add_item(func_name[i],i);
- }
-
- ob->select(graph->vec_func_node_get_function(type,p_id));
- ob->connect("item_selected",this,"_vec_func_changed",varray(p_id));
- gn->add_child(ob);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("in", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("in: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("out")));
- gn->add_child(hbc);
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
-
- } break; // vector function (normalize: { } break; negate: { } break; reciprocal: { } break; rgb2hsv: { } break; hsv2rgb: { } break; etc: { } break; etc)
- case ShaderGraph::NODE_VEC_LEN: {
- gn->set_title("VecLength");
- HBoxContainer *hbc = memnew( HBoxContainer );
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("in", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("in: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("len")));
- gn->add_child(hbc);
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
- } break; // vec3 length
- case ShaderGraph::NODE_DOT_PROD: {
-
- gn->set_title("DotProduct");
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("dp")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3));
- }
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
-
- } break; // vec3 . vec3 (dot product -> scalar output)
- case ShaderGraph::NODE_VEC_TO_SCALAR: {
-
- gn->set_title("Vec2Scalar");
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("vec", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("vec: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- Label *l=memnew(Label("x"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child( l);
- gn->add_child(hbc);
- l=memnew(Label("y"));
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child( l );
- l=memnew(Label("z"));
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child( l);
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
- gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
- gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
-
-
-
- } break; // 1 vec3 input: { } break; 3 scalar outputs
- case ShaderGraph::NODE_SCALAR_TO_VEC: {
-
- gn->set_title("Scalar2Vec");
- HBoxContainer *hbc = memnew( HBoxContainer );
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("x", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("x: ")+Variant(v),gn,p_id,0,Variant::REAL));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("vec")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("y", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("y: ")+Variant(v),gn,p_id,1,Variant::REAL));
- }
- if (graph->is_slot_connected(type, p_id, 2)) {
- gn->add_child(make_label("in", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,2);
- gn->add_child(make_editor(String("in: ")+Variant(v),gn,p_id,2,Variant::REAL));
- }
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
-
- } break; // 3 scalar input: { } break; 1 vec3 output
- case ShaderGraph::NODE_VEC_TO_XFORM: {
-
- gn->set_title("Vec2XForm");
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("x", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("x: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("xf")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("y", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("y: ")+v,gn,p_id,1,Variant::VECTOR3));
- }
- if (graph->is_slot_connected(type, p_id, 2)) {
- gn->add_child(make_label("z", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,2);
- gn->add_child(make_editor(String("z: ")+v,gn,p_id,2,Variant::VECTOR3));
- }
- if (graph->is_slot_connected(type, p_id, 3)) {
- gn->add_child(make_label("ofs", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,3);
- gn->add_child(make_editor(String("ofs: ")+v,gn,p_id,3,Variant::VECTOR3));
- }
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
- gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
-
- } break; // 3 vec input: { } break; 1 xform output
- case ShaderGraph::NODE_XFORM_TO_VEC: {
-
- gn->set_title("XForm2Vec");
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("fx", Variant::TRANSFORM));
- } else {
- hbc->add_child(make_editor(String("fx: edit..."),gn,p_id,0,Variant::TRANSFORM));
- }
- hbc->add_spacer();
- Label *l=memnew(Label("x"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child( l);
- gn->add_child(hbc);
- l=memnew(Label("y"));
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child( l );
- l=memnew(Label("z"));
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child( l);
- l=memnew(Label("ofs"));
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child( l);
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
-
- } break; // 3 vec input: { } break; 1 xform output
- case ShaderGraph::NODE_SCALAR_INTERP: {
-
- gn->set_title("ScalarInterp");
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("a: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("interp")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin));
- }
- if (graph->is_slot_connected(type, p_id, 2)) {
- gn->add_child(make_label("c", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,2);
- gn->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,2,Variant::REAL,hint_slider));
- }
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
-
-
- } break; // scalar interpolation (with optional curve)
- case ShaderGraph::NODE_VEC_INTERP: {
-
- gn->set_title("VecInterp");
- HBoxContainer *hbc = memnew( HBoxContainer );
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("a", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- hbc->add_child( memnew(Label("interp")));
- gn->add_child(hbc);
- if (graph->is_slot_connected(type, p_id, 1)) {
- gn->add_child(make_label("b", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,1);
- gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3));
- }
- if (graph->is_slot_connected(type, p_id, 2)) {
- gn->add_child(make_label("c", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,2);
- gn->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,2,Variant::REAL,hint_slider));
- }
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
-
- } break; // vec3 interpolation (with optional curve)
- case ShaderGraph::NODE_COLOR_RAMP: {
-
- gn->set_title("ColorRamp");
- GraphColorRampEdit * ramp = memnew( GraphColorRampEdit );
-
- PoolVector<real_t> offsets = graph->color_ramp_node_get_offsets(type,p_id);
- PoolVector<Color> colors = graph->color_ramp_node_get_colors(type,p_id);
-
- int oc = offsets.size();
-
- if (oc) {
- PoolVector<real_t>::Read rofs = offsets.read();
- PoolVector<Color>::Read rcol = colors.read();
-
- Vector<float> ofsv;
- Vector<Color> colorv;
- for(int i=0;i<oc;i++) {
- ofsv.push_back(rofs[i]);
- colorv.push_back(rcol[i]);
- }
-
- ramp->set_ramp(ofsv,colorv);
-
- }
-
- ramp->connect("ramp_changed",this,"_color_ramp_changed",varray(p_id,ramp));
- ramp->set_custom_minimum_size(Size2(128,1));
- gn->add_child(ramp);
-
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("c", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_slider));
- }
- hbc->add_spacer();
- Label *l=memnew(Label("rgb"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child( l);
- gn->add_child(hbc);
- l=memnew(Label("alpha"));
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child( l);
-
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(2,false,ShaderGraph::SLOT_MAX,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
-
- } break; // scalar interpolation (with optional curve)
- case ShaderGraph::NODE_CURVE_MAP: {
-
- gn->set_title("CurveMap");
- GraphCurveMapEdit * map = memnew( GraphCurveMapEdit );
-
- PoolVector<Vector2> points = graph->curve_map_node_get_points(type,p_id);
-
- int oc = points.size();
-
- if (oc) {
- PoolVector<Vector2>::Read rofs = points.read();
-
-
- Vector<Vector2> ofsv;
- for(int i=0;i<oc;i++) {
- ofsv.push_back(rofs[i]);
- }
-
- map->set_points(ofsv);
-
- }
- map->connect("curve_changed",this,"_curve_changed",varray(p_id,map));
-
- //map->connect("map_changed",this,"_curve_map_changed",varray(p_id,map));
- map->set_custom_minimum_size(Size2(128,64));
- gn->add_child(map);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("c", Variant::REAL));
- } else {
- float v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_slider));
- }
- hbc->add_spacer();
- Label *l=memnew(Label("cmap"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child( l);
- gn->add_child(hbc);
-
-
- gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
-
- } break; // scalar interpolation (with optional curve)
-
- case ShaderGraph::NODE_SCALAR_INPUT: {
-
- gn->set_title("ScalarUniform");
- LineEdit *le = memnew( LineEdit );
- gn->add_child(le);
- le->set_text(graph->input_node_get_name(type,p_id));
- le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
- SpinBox *sb = memnew( SpinBox );
- sb->set_min(-100000);
- sb->set_max(100000);
- sb->set_step(0.001);
- sb->set_val(graph->scalar_input_node_get_value(type,p_id));
- sb->connect("value_changed",this,"_scalar_input_changed",varray(p_id));
- gn->add_child(sb);
- gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
- } break; // scalar uniform (assignable in material)
- case ShaderGraph::NODE_VEC_INPUT: {
-
- gn->set_title("VectorUniform");
- LineEdit *le = memnew( LineEdit );
- gn->add_child(le);
- le->set_text(graph->input_node_get_name(type,p_id));
- le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
- Array v3p(true);
- for(int i=0;i<3;i++) {
- HBoxContainer *hbc = memnew( HBoxContainer );
- Label *l = memnew( Label );
- l->set_text(String::chr('X'+i));
- hbc->add_child(l);
- SpinBox *sb = memnew( SpinBox );
- sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- sb->set_min(-100000);
- sb->set_max(100000);
- sb->set_step(0.001);
- sb->set_val(graph->vec_input_node_get_value(type,p_id)[i]);
- sb->connect("value_changed",this,"_vec_input_changed",varray(p_id,v3p));
- v3p.push_back(sb);
- hbc->add_child(sb);
- gn->add_child(hbc);
- }
- gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
-
- } break; // vec3 uniform (assignable in material)
- case ShaderGraph::NODE_RGB_INPUT: {
-
- gn->set_title("ColorUniform");
- LineEdit *le = memnew( LineEdit );
- gn->add_child(le);
- le->set_text(graph->input_node_get_name(type,p_id));
- le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
- ColorPickerButton *cpb = memnew( ColorPickerButton );
- cpb->set_color(graph->rgb_input_node_get_value(type,p_id));
- cpb->connect("color_changed",this,"_rgb_input_changed",varray(p_id));
- gn->add_child(cpb);
- Label *l = memnew( Label );
- l->set_text("RGB");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
- l = memnew( Label );
- l->set_text("Alpha");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
-
- gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
-
- } break; // color uniform (assignable in material)
- case ShaderGraph::NODE_XFORM_INPUT: {
- gn->set_title("XFUniform");
- LineEdit *le = memnew( LineEdit );
- gn->add_child(le);
- le->set_text(graph->input_node_get_name(type,p_id));
- le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
- ToolButton *edit = memnew( ToolButton );
- edit->set_text("edit..");
- edit->connect("pressed",this,"_xform_input_changed",varray(p_id,edit));
- gn->add_child(edit);
- gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
-
- } break; // mat4 uniform (assignable in material)
- case ShaderGraph::NODE_TEXTURE_INPUT: {
-
- gn->set_title("TexUniform");
- LineEdit *le = memnew( LineEdit );
- gn->add_child(le);
- le->set_text(graph->input_node_get_name(type,p_id));
- le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
- TextureRect *tex = memnew( TextureRect );
- tex->set_expand(true);
- tex->set_custom_minimum_size(Size2(80,80));
- tex->set_drag_forwarding(this);
- gn->add_child(tex);
- tex->set_mouse_filter(MOUSE_FILTER_PASS);
- tex->set_texture(graph->texture_input_node_get_value(type,p_id));
- ToolButton *edit = memnew( ToolButton );
- edit->set_text("edit..");
- edit->connect("pressed",this,"_tex_edited",varray(p_id,edit));
- gn->add_child(edit);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("UV", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- Label *l=memnew(Label("RGB"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child(l);
- gn->add_child(hbc);
- l = memnew( Label );
- l->set_text("Alpha");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
-
- gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(4,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
- } break; // texture input (assignable in material)
- case ShaderGraph::NODE_CUBEMAP_INPUT: {
-
- gn->set_title("TexUniform");
- LineEdit *le = memnew( LineEdit );
- gn->add_child(le);
- le->set_text(graph->input_node_get_name(type,p_id));
- le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
-
- ToolButton *edit = memnew( ToolButton );
- edit->set_text("edit..");
- edit->connect("pressed",this,"_cube_edited",varray(p_id,edit));
- gn->add_child(edit);
-
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("UV", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- Label *l=memnew(Label("RGB"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child(l);
- gn->add_child(hbc);
- l = memnew( Label );
- l->set_text("Alpha");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
-
- gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
- } break; // cubemap input (assignable in material)
- case ShaderGraph::NODE_DEFAULT_TEXTURE: {
-
- gn->set_title("CanvasItemTex");
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->add_constant_override("separation",0);
- if (graph->is_slot_connected(type, p_id, 0)) {
- hbc->add_child(make_label("UV", Variant::VECTOR3));
- } else {
- Vector3 v = graph->default_get_value(type,p_id,0);
- hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3));
- }
- hbc->add_spacer();
- Label *l=memnew(Label("RGB"));
- l->set_align(Label::ALIGN_RIGHT);
- hbc->add_child(l);
- gn->add_child(hbc);
- l = memnew( Label );
- l->set_text("Alpha");
- l->set_align(Label::ALIGN_RIGHT);
- gn->add_child(l);
-
- gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
- gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
-
-
- } break; // screen texture sampler (takes UV) (only usable in fragment case Shader)
-
- case ShaderGraph::NODE_OUTPUT: {
- gn->set_title("Output");
- gn->set_show_close_button(false);
-
- List<ShaderGraph::SlotInfo> si;
- ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si);
-
- Array colors;
- colors.push_back("Color");
- colors.push_back("LightColor");
- colors.push_back("Light");
- colors.push_back("ShadowColor");
- colors.push_back("Diffuse");
- colors.push_back("Specular");
- colors.push_back("Emmision");
- Array reals;
- reals.push_back("Alpha");
- reals.push_back("DiffuseAlpha");
- reals.push_back("NormalMapDepth");
- reals.push_back("SpecExp");
- reals.push_back("Glow");
- reals.push_back("ShadeParam");
- reals.push_back("SpecularExp");
- reals.push_back("LightAlpha");
- reals.push_back("ShadowAlpha");
- reals.push_back("PointSize");
- reals.push_back("Discard");
-
- int idx=0;
- for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) {
- ShaderGraph::SlotInfo& s=E->get();
- if (s.dir==ShaderGraph::SLOT_OUT) {
- Variant::Type v;
- if (colors.find(s.name)>=0)
- v=Variant::COLOR;
- else if (reals.find(s.name)>=0)
- v=Variant::REAL;
- else
- v=Variant::VECTOR3;
- gn->add_child(make_label(s.name, v));
- gn->set_slot(idx,true,s.type,typecol[s.type],false,0,Color());
- idx++;
- }
- }
-
- } break; // output (case Shader type dependent)
- case ShaderGraph::NODE_COMMENT: {
- gn->set_title("Comment");
- TextEdit *te = memnew(TextEdit);
- te->set_custom_minimum_size(Size2(100,100));
- gn->add_child(te);
- te->set_text(graph->comment_node_get_text(type,p_id));
- te->connect("text_changed",this,"_comment_edited",varray(p_id,te));
-
- } break; // comment
-
-
-
- }
-
- gn->connect("dragged",this,"_node_moved",varray(p_id));
- gn->connect("close_request",this,"_node_removed",varray(p_id),CONNECT_DEFERRED);
- graph_edit->add_child(gn);
- node_map[p_id]=gn;
- gn->set_offset(graph->node_get_pos(type,p_id));
-
-
-}
-
-void ShaderGraphView::_update_graph() {
-
-
- if (block_update)
- return;
-
- for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
-
- memdelete(E->get());
- }
-
- node_map.clear();
-
- if (!graph.is_valid())
- return;
-
-
- List<int> nl;
- graph->get_node_list(type,&nl);
-
- for(List<int>::Element *E=nl.front();E;E=E->next()) {
-
- _create_node(E->get());
- }
- graph_edit->clear_connections();
-
- List<ShaderGraph::Connection> connections;
- graph->get_node_connections(type,&connections);
- for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- ERR_CONTINUE(!node_map.has(E->get().src_id) || !node_map.has(E->get().dst_id));
- graph_edit->connect_node(node_map[E->get().src_id]->get_name(),E->get().src_slot,node_map[E->get().dst_id]->get_name(),E->get().dst_slot);
- }
-
-}
-
-void ShaderGraphView::_sg_updated() {
-
- if (!graph.is_valid())
- return;
- switch(graph->get_graph_error(type)) {
- case ShaderGraph::GRAPH_OK: status->set_text(""); break;
- case ShaderGraph::GRAPH_ERROR_CYCLIC: status->set_text(TTR("Error: Cyclic Connection Link")); break;
- case ShaderGraph::GRAPH_ERROR_MISSING_CONNECTIONS: status->set_text(TTR("Error: Missing Input Connections")); break;
- }
-}
-
-Variant ShaderGraphView::get_drag_data_fw(const Point2 &p_point, Control *p_from)
-{
- TextureRect* frame = p_from->cast_to<TextureRect>();
- if (!frame)
- return Variant();
-
- if (!frame->get_texture().is_valid())
- return Variant();
-
- RES res = frame->get_texture();
- return EditorNode::get_singleton()->drag_resource(res,p_from);
-
- return Variant();
-}
-
-bool ShaderGraphView::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const
-{
- if (p_data.get_type() != Variant::DICTIONARY)
- return false;
-
- Dictionary d = p_data;
-
- if (d.has("type")){
- if (d["type"] == "resource" && d.has("resource")) {
- Variant val = d["resource"];
-
- if (val.get_type()==Variant::OBJECT) {
- RES res = val;
- if (res.is_valid() && res->cast_to<Texture>())
- return true;
- }
- }
- else if (d["type"] == "files" && d.has("files")) {
- Vector<String> files = d["files"];
- if (files.size() != 1)
- return false;
- return (ResourceLoader::get_resource_type(files[0]) == "ImageTexture");
- }
- }
-
- return false;
-}
-
-void ShaderGraphView::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from)
-{
- if (!can_drop_data_fw(p_point, p_data, p_from))
- return;
-
- TextureRect *frame = p_from->cast_to<TextureRect>();
- if (!frame)
- return;
-
- Dictionary d = p_data;
- Ref<Texture> tex;
-
- if (d.has("type")) {
- if (d["type"] == "resource" && d.has("resource")){
- Variant val = d["resource"];
-
- if (val.get_type()==Variant::OBJECT) {
- RES res = val;
- if (res.is_valid())
- tex = Ref<Texture>(res->cast_to<Texture>());
- }
- }
- else if (d["type"] == "files" && d.has("files")) {
- Vector<String> files = d["files"];
- RES res = ResourceLoader::load(files[0]);
- if (res.is_valid())
- tex = Ref<Texture>(res->cast_to<Texture>());
- }
- }
-
- if (!tex.is_valid()) return;
-
- GraphNode *gn = frame->get_parent()->cast_to<GraphNode>();
- if (!gn) return;
-
- int id = -1;
- for(Map<int,GraphNode*>::Element *E = node_map.front();E;E=E->next())
- if (E->get() == gn) {
- id = E->key();
- break;
- }
- print_line(String::num(double(id)));
- if (id < 0) return;
-
- if (graph->node_get_type(type,id)==ShaderGraph::NODE_TEXTURE_INPUT) {
-
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Texture Uniform"));
- ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,id,tex);
- ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,id,graph->texture_input_node_get_value(type,id));
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
- }
-}
-
-void ShaderGraphView::set_graph(Ref<ShaderGraph> p_graph){
-
-
- if (graph.is_valid()) {
- graph->disconnect("updated",this,"_sg_updated");
- }
- graph=p_graph;
- if (graph.is_valid()) {
- graph->connect("updated",this,"_sg_updated");
- }
- _update_graph();
- _sg_updated();
-
-}
-
-void ShaderGraphView::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- ped_popup->connect("variant_changed",this,"_variant_edited");
- }
-}
-
-void ShaderGraphView::add_node(int p_type, const Vector2 &location) {
-
- if (p_type==ShaderGraph::NODE_INPUT && graph->node_count(type, p_type)>0)
- return;
-
- List<int> existing;
- graph->get_node_list(type,&existing);
- existing.sort();
- int newid=1;
- for(List<int>::Element *E=existing.front();E;E=E->next()) {
- if (!E->next() || (E->get()+1!=E->next()->get())){
- newid=E->get()+1;
- break;
- }
- }
-
- Vector2 init_ofs = location;
- while(true) {
- bool valid=true;
- for(List<int>::Element *E=existing.front();E;E=E->next()) {
- Vector2 pos = graph->node_get_pos(type,E->get());
- if (init_ofs==pos) {
- init_ofs+=Vector2(20,20);
- valid=false;
- break;
-
- }
- }
-
- if (valid)
- break;
- }
- UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Add Shader Graph Node"));
- ur->add_do_method(graph.ptr(),"node_add",type,p_type,newid);
- ur->add_do_method(graph.ptr(),"node_set_pos",type,newid,init_ofs);
- ur->add_undo_method(graph.ptr(),"node_remove",type,newid);
- ur->add_do_method(this,"_update_graph");
- ur->add_undo_method(this,"_update_graph");
- ur->commit_action();
-
-}
-
-void ShaderGraphView::_bind_methods() {
-
- ClassDB::bind_method("_update_graph",&ShaderGraphView::_update_graph);
- ClassDB::bind_method("_begin_node_move", &ShaderGraphView::_begin_node_move);
- ClassDB::bind_method("_node_moved",&ShaderGraphView::_node_moved);
- ClassDB::bind_method("_end_node_move", &ShaderGraphView::_end_node_move);
- ClassDB::bind_method("_move_node",&ShaderGraphView::_move_node);
- ClassDB::bind_method("_node_removed",&ShaderGraphView::_node_removed);
- ClassDB::bind_method("_connection_request",&ShaderGraphView::_connection_request);
- ClassDB::bind_method("_disconnection_request",&ShaderGraphView::_disconnection_request);
- ClassDB::bind_method("_duplicate_nodes_request", &ShaderGraphView::_duplicate_nodes_request);
- ClassDB::bind_method("_duplicate_nodes", &ShaderGraphView::_duplicate_nodes);
- ClassDB::bind_method("_delete_nodes_request", &ShaderGraphView::_delete_nodes_request);
-
- ClassDB::bind_method("_default_changed",&ShaderGraphView::_default_changed);
- ClassDB::bind_method("_scalar_const_changed",&ShaderGraphView::_scalar_const_changed);
- ClassDB::bind_method("_vec_const_changed",&ShaderGraphView::_vec_const_changed);
- ClassDB::bind_method("_rgb_const_changed",&ShaderGraphView::_rgb_const_changed);
- ClassDB::bind_method("_xform_const_changed",&ShaderGraphView::_xform_const_changed);
- ClassDB::bind_method("_scalar_op_changed",&ShaderGraphView::_scalar_op_changed);
- ClassDB::bind_method("_vec_op_changed",&ShaderGraphView::_vec_op_changed);
- ClassDB::bind_method("_vec_scalar_op_changed",&ShaderGraphView::_vec_scalar_op_changed);
- ClassDB::bind_method("_rgb_op_changed",&ShaderGraphView::_rgb_op_changed);
- ClassDB::bind_method("_xform_inv_rev_changed",&ShaderGraphView::_xform_inv_rev_changed);
- ClassDB::bind_method("_scalar_func_changed",&ShaderGraphView::_scalar_func_changed);
- ClassDB::bind_method("_vec_func_changed",&ShaderGraphView::_vec_func_changed);
- ClassDB::bind_method("_scalar_input_changed",&ShaderGraphView::_scalar_input_changed);
- ClassDB::bind_method("_vec_input_changed",&ShaderGraphView::_vec_input_changed);
- ClassDB::bind_method("_xform_input_changed",&ShaderGraphView::_xform_input_changed);
- ClassDB::bind_method("_rgb_input_changed",&ShaderGraphView::_rgb_input_changed);
- ClassDB::bind_method("_tex_input_change",&ShaderGraphView::_tex_input_change);
- ClassDB::bind_method("_cube_input_change",&ShaderGraphView::_cube_input_change);
- ClassDB::bind_method("_input_name_changed",&ShaderGraphView::_input_name_changed);
- ClassDB::bind_method("_tex_edited",&ShaderGraphView::_tex_edited);
- ClassDB::bind_method("_variant_edited",&ShaderGraphView::_variant_edited);
- ClassDB::bind_method("_cube_edited",&ShaderGraphView::_cube_edited);
- ClassDB::bind_method("_comment_edited",&ShaderGraphView::_comment_edited);
- ClassDB::bind_method("_color_ramp_changed",&ShaderGraphView::_color_ramp_changed);
- ClassDB::bind_method("_curve_changed",&ShaderGraphView::_curve_changed);
-
- ClassDB::bind_method(_MD("get_drag_data_fw"), &ShaderGraphView::get_drag_data_fw);
- ClassDB::bind_method(_MD("can_drop_data_fw"), &ShaderGraphView::can_drop_data_fw);
- ClassDB::bind_method(_MD("drop_data_fw"), &ShaderGraphView::drop_data_fw);
-
- ClassDB::bind_method("_sg_updated",&ShaderGraphView::_sg_updated);
-}
-
-ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) {
-
- type=p_type;
- graph_edit = memnew( GraphEdit );
- block_update=false;
- ped_popup = memnew( CustomPropertyEditor );
- graph_edit->add_child(ped_popup);
- status = memnew( Label );
- graph_edit->get_top_layer()->add_child(status);
- graph_edit->connect("_begin_node_move", this, "_begin_node_move");
- graph_edit->connect("_end_node_move", this, "_end_node_move");
- status->set_pos(Vector2(5,5));
- status->add_color_override("font_color_shadow",Color(0,0,0));
- status->add_color_override("font_color",Color(1,0.4,0.3));
- status->add_constant_override("shadow_as_outline",1);
- status->add_constant_override("shadow_offset_x",2);
- status->add_constant_override("shadow_offset_y",2);
- status->set_text("");
-}
-
-
-//////////////edit//////////////
-void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) {
-
- for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) {
- graph_edits[i]->set_graph(p_shader);
- }
-}
-
-void ShaderGraphEditor::_add_node(int p_type) {
-
- ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab());
- graph_edits[shader_type]->add_node(p_type, next_location);
-}
-
-void ShaderGraphEditor::_popup_requested(const Vector2 &p_position)
-{
- 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();
- popup->call_deferred("grab_click_focus");
- popup->set_invalidate_click_until_motion();
-}
-
-void ShaderGraphEditor::_notification(int p_what) {
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- for(int i=0;i<ShaderGraph::NODE_TYPE_MAX;i++) {
-
- if (i==ShaderGraph::NODE_OUTPUT)
- continue;
- if (!_2d && i==ShaderGraph::NODE_DEFAULT_TEXTURE)
- continue;
-
- String nn = node_names[i];
- String ic = nn.get_slice(":",0);
- String v = nn.get_slice(":",1);
- bool addsep=false;
- if (nn.ends_with(":")) {
- addsep=true;
- }
- popup->add_icon_item(get_icon(ic,"EditorIcons"),v,i);
- if (addsep)
- popup->add_separator();
- }
- popup->connect("id_pressed",this,"_add_node");
-
-
- }
-}
-
-void ShaderGraphEditor::_bind_methods() {
-
- ClassDB::bind_method("_add_node",&ShaderGraphEditor::_add_node);
- ClassDB::bind_method("_popup_requested",&ShaderGraphEditor::_popup_requested);
-}
-
-
-const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={
- ("GraphInput:Input"), // all inputs (shader type dependent)
- ("GraphScalar:Scalar Constant"), //scalar constant
- ("GraphVector:Vector Constant"), //vec3 constant
- ("GraphRgb:RGB Constant"), //rgb constant (shows a color picker instead)
- ("GraphXform:XForm Constant"), // 4x4 matrix constant
- ("GraphTime:Time:"), // time in seconds
- ("GraphTexscreen:Screen Sample"), // screen texture sampler (takes uv) (only usable in fragment shader)
- ("GraphScalarOp:Scalar Operator"), // scalar vs scalar op (mul", add", div", etc)
- ("GraphVecOp:Vector Operator"), // vec3 vs vec3 op (mul",ad",div",crossprod",etc)
- ("GraphVecScalarOp:Scalar+Vector Operator"), // vec3 vs scalar op (mul", add", div", etc)
- ("GraphRgbOp:RGB Operator:"), // vec3 vs vec3 rgb op (with scalar amount)", like brighten", darken", burn", dodge", multiply", etc.
- ("GraphXformMult:XForm Multiply"), // mat4 x mat4
- ("GraphXformVecMult:XForm+Vector Multiply"), // mat4 x vec3 mult (with no-translation option)
- ("GraphXformVecImult:Form+Vector InvMultiply:"), // mat4 x vec3 inverse mult (with no-translation option)
- ("GraphXformScalarFunc:Scalar Function"), // scalar function (sin", cos", etc)
- ("GraphXformVecFunc:Vector Function"), // vector function (normalize", negate", reciprocal", rgb2hsv", hsv2rgb", etc", etc)
- ("GraphVecLength:Vector Length"), // vec3 length
- ("GraphVecDp:Dot Product:"), // vec3 . vec3 (dot product -> scalar output)
- ("GraphVecToScalars:Vector -> Scalars"), // 1 vec3 input", 3 scalar outputs
- ("GraphScalarsToVec:Scalars -> Vector"), // 3 scalar input", 1 vec3 output
- ("GraphXformToVecs:XForm -> Vectors"), // 3 vec input", 1 xform output
- ("GraphVecsToXform:Vectors -> XForm:"), // 3 vec input", 1 xform output
- ("GraphScalarInterp:Scalar Interpolate"), // scalar interpolation (with optional curve)
- ("GraphVecInterp:Vector Interpolate:"), // vec3 interpolation (with optional curve)
- ("GraphColorRamp:Color Ramp"), // vec3 interpolation (with optional curve)
- ("GraphCurveMap:Curve Remap:"), // vec3 interpolation (with optional curve)
- ("GraphScalarUniform:Scalar Uniform"), // scalar uniform (assignable in material)
- ("GraphVectorUniform:Vector Uniform"), // vec3 uniform (assignable in material)
- ("GraphRgbUniform:RGB Uniform"), // color uniform (assignable in material)
- ("GraphXformUniform:XForm Uniform"), // mat4 uniform (assignable in material)
- ("GraphTextureUniform:Texture Uniform"), // texture input (assignable in material)
- ("GraphCubeUniform:CubeMap Uniform:"), // cubemap input (assignable in material)
- ("GraphDefaultTexture:CanvasItem Texture:"), // cubemap input (assignable in material)
- ("Output"), // output (shader type dependent)
- ("GraphComment:Comment"), // comment
-
-
-};
-ShaderGraphEditor::ShaderGraphEditor(bool p_2d) {
- _2d=p_2d;
-
- popup = memnew( PopupMenu );
- add_child(popup);
-
-
- tabs = memnew(TabContainer);
- tabs->set_v_size_flags(SIZE_EXPAND_FILL);
- add_child(tabs);
- const char* sname[ShaderGraph::SHADER_TYPE_MAX]={
- "Vertex",
- "Fragment",
- "Light"
- };
- for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) {
-
- graph_edits[i]= memnew( ShaderGraphView(ShaderGraph::ShaderType(i)) );
- add_child(graph_edits[i]);
- graph_edits[i]->get_graph_edit()->set_name(sname[i]);
- tabs->add_child(graph_edits[i]->get_graph_edit());
- graph_edits[i]->get_graph_edit()->connect("connection_request",graph_edits[i],"_connection_request");
- graph_edits[i]->get_graph_edit()->connect("disconnection_request",graph_edits[i],"_disconnection_request");
- graph_edits[i]->get_graph_edit()->connect("duplicate_nodes_request", graph_edits[i], "_duplicate_nodes_request");
- graph_edits[i]->get_graph_edit()->connect("popup_request",this,"_popup_requested");
- graph_edits[i]->get_graph_edit()->connect("delete_nodes_request",graph_edits[i],"_delete_nodes_request");
- graph_edits[i]->get_graph_edit()->set_right_disconnects(true);
- }
-
- tabs->set_current_tab(1);
-
- set_custom_minimum_size(Size2(100,300));
-}
-
-
-void ShaderGraphEditorPlugin::edit(Object *p_object) {
-
- shader_editor->edit(p_object->cast_to<ShaderGraph>());
-}
-
-bool ShaderGraphEditorPlugin::handles(Object *p_object) const {
-
- ShaderGraph *shader=p_object->cast_to<ShaderGraph>();
- if (!shader)
- return false;
- if (_2d)
- return shader->get_mode()==Shader::MODE_CANVAS_ITEM;
- else
- return shader->get_mode()==Shader::MODE_MATERIAL;
-}
-
-void ShaderGraphEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- shader_editor->show();
- } else {
-
- shader_editor->hide();
- }
-
-}
-
-ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node, bool p_2d) {
-
- _2d=p_2d;
- editor=p_node;
- shader_editor = memnew( ShaderGraphEditor(p_2d) );
- shader_editor->hide();
- if (p_2d)
- CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(shader_editor);
- else
- SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor);
-
-
- //editor->get_viewport()->add_child(shader_editor);
- //shader_editor->set_area_as_parent_rect();
- //shader_editor->hide();
-
-}
-
-
-ShaderGraphEditorPlugin::~ShaderGraphEditorPlugin()
-{
-}
-
-
-
-#endif
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h
deleted file mode 100644
index 477a45bd1f..0000000000
--- a/tools/editor/plugins/shader_graph_editor_plugin.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*************************************************************************/
-/* shader_graph_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SHADER_GRAPH_EDITOR_PLUGIN_H
-#define SHADER_GRAPH_EDITOR_PLUGIN_H
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/resources/shader.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/button.h"
-#include "scene/gui/graph_edit.h"
-#include "scene/gui/popup.h"
-#include "tools/editor/property_editor.h"
-#include "scene/resources/shader_graph.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-#if 0
-class GraphColorRampEdit : public Control {
-
- GDCLASS(GraphColorRampEdit,Control);
-
-
- struct Point {
-
- float offset;
- Color color;
- bool operator<(const Point& p_ponit) const {
- return offset<p_ponit.offset;
- }
- };
-
- PopupPanel *popup;
- ColorPicker *picker;
-
-
- bool grabbing;
- int grabbed;
- float grabbed_at;
- Vector<Point> points;
-
- void _color_changed(const Color& p_color);
-
-protected:
- void _gui_input(const InputEvent& p_event);
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors);
- Vector<float> get_offsets() const;
- Vector<Color> get_colors() const;
- virtual Size2 get_minimum_size() const;
- GraphColorRampEdit();
-};
-
-
-class GraphCurveMapEdit : public Control {
-
- GDCLASS(GraphCurveMapEdit,Control);
-
-
- struct Point {
-
- float offset;
- float height;
- bool operator<(const Point& p_ponit) const {
- return offset<p_ponit.offset;
- }
- };
-
-
- bool grabbing;
- int grabbed;
- Vector<Point> points;
-
- void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d);
-protected:
- void _gui_input(const InputEvent& p_event);
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_points(const Vector<Vector2>& p_points);
- Vector<Vector2> get_points() const;
- virtual Size2 get_minimum_size() const;
- GraphCurveMapEdit();
-};
-
-class ShaderGraphView : public Control {
-
- GDCLASS(ShaderGraphView,Control);
-
-
-
- CustomPropertyEditor *ped_popup;
- bool block_update;
-
- Label *status;
- GraphEdit *graph_edit;
- Ref<ShaderGraph> graph;
- int edited_id;
- int edited_def;
-
- ShaderGraph::ShaderType type;
-
- void _update_graph();
- void _create_node(int p_id);
-
-
- ToolButton *make_label(String text, Variant::Type v_type = Variant::NIL);
- ToolButton *make_editor(String text, GraphNode* gn, int p_id, int param, Variant::Type type, String p_hint="");
-
- void _connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot);
- void _disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot);
-
- void _node_removed(int p_id);
- void _begin_node_move();
- void _node_moved(const Vector2& p_from, const Vector2& p_to,int p_id);
- 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 _delete_nodes_request();
-
-
- void _default_changed(int p_id, Node* p_button, int p_param, int v_type, String p_hint);
-
- void _scalar_const_changed(double p_value,int p_id);
- void _vec_const_changed(double p_value, int p_id, Array p_arr);
- void _rgb_const_changed(const Color& p_color, int p_id);
- void _xform_const_changed(int p_id,Node* p_button);
- void _scalar_op_changed(int p_op, int p_id);
- void _vec_op_changed(int p_op, int p_id);
- void _vec_scalar_op_changed(int p_op, int p_id);
- void _rgb_op_changed(int p_op, int p_id);
- void _xform_inv_rev_changed(bool p_enabled, int p_id);
- void _scalar_func_changed(int p_func, int p_id);
- void _vec_func_changed(int p_func, int p_id);
- void _scalar_input_changed(double p_value,int p_id);
- void _vec_input_changed(double p_value, int p_id, Array p_arr);
- void _xform_input_changed(int p_id,Node* p_button);
- void _rgb_input_changed(const Color& p_color, int p_id);
- void _tex_input_change(int p_id,Node* p_button);
- void _cube_input_change(int p_id);
- void _input_name_changed(const String& p_name,int p_id,Node* p_line_edit);
- void _tex_edited(int p_id,Node* p_button);
- void _cube_edited(int p_id,Node* p_button);
- void _variant_edited();
- void _comment_edited(int p_id,Node* p_button);
- void _color_ramp_changed(int p_id,Node* p_ramp);
- void _curve_changed(int p_id,Node* p_curve);
- void _sg_updated();
- Map<int,GraphNode*> node_map;
-
- Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
- bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
- void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void add_node(int p_type, const Vector2 &location);
- GraphEdit *get_graph_edit() { return graph_edit; }
- void set_graph(Ref<ShaderGraph> p_graph);
-
- ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT);
-};
-
-class ShaderGraphEditor : public VBoxContainer {
-
- GDCLASS(ShaderGraphEditor,VBoxContainer);
-
- PopupMenu *popup;
- TabContainer *tabs;
- ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX];
- static const char* node_names[ShaderGraph::NODE_TYPE_MAX];
- Vector2 next_location;
-
- bool _2d;
- void _add_node(int p_type);
- void _popup_requested(const Vector2 &p_position);
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void edit(Ref<ShaderGraph> p_shader);
- ShaderGraphEditor(bool p_2d);
-};
-
-class ShaderGraphEditorPlugin : public EditorPlugin {
-
- GDCLASS( ShaderGraphEditorPlugin, EditorPlugin );
-
- bool _2d;
- ShaderGraphEditor *shader_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "ShaderGraph"; }
- bool has_main_screen() const { return false; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
- virtual void make_visible(bool p_visible);
-
- ShaderGraphEditorPlugin(EditorNode *p_node,bool p_2d);
- ~ShaderGraphEditorPlugin();
-
-};
-#endif
-#endif
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
deleted file mode 100644
index 3ba1a2cbdc..0000000000
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ /dev/null
@@ -1,4131 +0,0 @@
-/*************************************************************************/
-/* spatial_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "spatial_editor_plugin.h"
-
-#include "print_string.h"
-#include "os/keyboard.h"
-#include "scene/3d/visual_instance.h"
-#include "scene/3d/camera.h"
-#include "camera_matrix.h"
-#include "sort.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/editor_settings.h"
-#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
-
-
-#define GIZMO_ARROW_SIZE 0.3
-#define GIZMO_RING_HALF_WIDTH 0.1
-//#define GIZMO_SCALE_DEFAULT 0.28
-#define GIZMO_SCALE_DEFAULT 0.15
-
-
-void SpatialEditorViewport::_update_camera() {
- if (orthogonal) {
- //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar());
- camera->set_orthogonal(2 * cursor.distance, 0.1, 8192);
- }
- else
- camera->set_perspective(get_fov(), get_znear(), get_zfar());
-
- Transform camera_transform;
- camera_transform.translate(cursor.pos);
- camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
- camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
-
- if (orthogonal)
- camera_transform.translate(0, 0, 4096);
- else
- camera_transform.translate(0, 0, cursor.distance);
-
- if (camera->get_global_transform() != camera_transform) {
- camera->set_global_transform(camera_transform);
- update_transform_gizmo_view();
- }
-}
-
-String SpatialEditorGizmo::get_handle_name(int p_idx) const {
-
- if (get_script_instance() && get_script_instance()->has_method("get_handle_name"))
- return get_script_instance()->call("get_handle_name", p_idx);
-
- return "";
-}
-
-Variant SpatialEditorGizmo::get_handle_value(int p_idx) const{
-
- if (get_script_instance() && get_script_instance()->has_method("get_handle_value"))
- return get_script_instance()->call("get_handle_value", p_idx);
-
- return Variant();
-}
-
-void SpatialEditorGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point) {
-
- if (get_script_instance() && get_script_instance()->has_method("set_handle"))
- get_script_instance()->call("set_handle", p_idx, p_camera, p_point);
-}
-
-void SpatialEditorGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- if (get_script_instance() && get_script_instance()->has_method("commit_handle"))
- get_script_instance()->call("commit_handle", p_idx, p_restore, p_cancel);
-}
-
-bool SpatialEditorGizmo::intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum) {
-
- return false;
-}
-
-bool SpatialEditorGizmo::intersect_ray(const Camera *p_camera, const Point2 &p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle,bool p_sec_first) {
-
- return false;
-}
-
-SpatialEditorGizmo::SpatialEditorGizmo(){
-
- selected=false;
-}
-
-
-
-int SpatialEditorViewport::get_selected_count() const {
-
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- int count=0;
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->key()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- count++;
- }
-
- return count;
-}
-
-
-
-float SpatialEditorViewport::get_znear() const {
-
- float val = spatial_editor->get_znear();
- if (val<0.001)
- val=0.001;
- return val;
-}
-float SpatialEditorViewport::get_zfar() const{
-
- float val = spatial_editor->get_zfar();
- if (val<0.001)
- val=0.001;
- return val;
-
-}
-float SpatialEditorViewport::get_fov() const{
-
- float val = spatial_editor->get_fov();
- if (val<0.001)
- val=0.001;
- if (val>89)
- val=89;
- return val;
-
-}
-
-
-
-Transform SpatialEditorViewport::_get_camera_transform() const {
-
- return camera->get_global_transform();
-}
-
-Vector3 SpatialEditorViewport::_get_camera_pos() const {
-
- return _get_camera_transform().origin;
-}
-
-Point2 SpatialEditorViewport::_point_to_screen(const Vector3& p_point) {
-
- return camera->unproject_position(p_point);
-
-}
-
-Vector3 SpatialEditorViewport::_get_ray_pos(const Vector2& p_pos) const {
-
- return camera->project_ray_origin(p_pos);
-}
-
-
-Vector3 SpatialEditorViewport::_get_camera_normal() const {
-
- return -_get_camera_transform().basis.get_axis(2);
-}
-
-Vector3 SpatialEditorViewport::_get_ray(const Vector2& p_pos) {
-
-
- return camera->project_ray_normal(p_pos);
-
-
-}
-/*
-void SpatialEditorViewport::_clear_id(Spatial *p_node) {
-
-
- editor_selection->remove_node(p_node);
-
-
-}
-*/
-void SpatialEditorViewport::_clear_selected() {
-
- editor_selection->clear();
-}
-
-
-
-void SpatialEditorViewport::_select_clicked(bool p_append,bool p_single) {
-
- if (!clicked)
- return;
-
- Object *obj = ObjectDB::get_instance(clicked);
- if (!obj)
- return;
-
-
- Spatial *sp = obj->cast_to<Spatial>();
- if (!sp)
- return;
-
- _select(sp, clicked_wants_append,true);
-}
-
-
-
-void SpatialEditorViewport::_select(Spatial *p_node, bool p_append,bool p_single) {
-
-
- if (!p_append) {
-
- // should not modify the selection..
-
- editor_selection->clear();
- editor_selection->add_node(p_node);
-
- } else {
-
- if (editor_selection->is_selected(p_node) && p_single) {
- //erase
- editor_selection->remove_node(p_node);
- } else {
-
- editor_selection->add_node(p_node);
- }
-
- }
-
-}
-
-ObjectID SpatialEditorViewport::_select_ray(const Point2& p_pos, bool p_append,bool &r_includes_current,int *r_gizmo_handle,bool p_alt_select) {
-
- if (r_gizmo_handle)
- *r_gizmo_handle=-1;
-
- Vector3 ray=_get_ray(p_pos);
- Vector3 pos=_get_ray_pos(p_pos);
-
- Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_ray(pos,ray,get_tree()->get_root()->get_world()->get_scenario() );
- Set<Ref<SpatialEditorGizmo> > found_gizmos;
-
- ObjectID closest=0;
- Spatial *item=NULL;
- float closest_dist=1e20;
- int selected_handle=-1;
-
- for (int i=0;i<instances.size();i++) {
-
- Object *obj=ObjectDB::get_instance(instances[i]);
- if (!obj)
- continue;
-
- Spatial *spat=obj->cast_to<Spatial>();
-
- if (!spat)
- continue;
-
- Ref<SpatialEditorGizmo> seg = spat->get_gizmo();
-
- if (!seg.is_valid())
- continue;
-
- if (found_gizmos.has(seg))
- continue;
-
- found_gizmos.insert(seg);
- Vector3 point;
- Vector3 normal;
-
- int handle=-1;
- bool inters = seg->intersect_ray(camera,p_pos,point,normal,NULL,p_alt_select);
-
- if (!inters)
- continue;
-
- float dist = pos.distance_to(point);
-
- if (dist<0)
- continue;
-
- if (dist < closest_dist) {
- closest=instances[i];
- closest_dist=dist;
- selected_handle=handle;
- item=spat;
- }
-
- // if (editor_selection->is_selected(spat))
- // r_includes_current=true;
-
- }
-
-
- if (!item)
- return 0;
-
- if (!editor_selection->is_selected(item) || (r_gizmo_handle && selected_handle>=0)) {
-
- if (r_gizmo_handle)
- *r_gizmo_handle=selected_handle;
-
- }
-
- return closest;
-
-}
-
-void SpatialEditorViewport::_find_items_at_pos(const Point2& p_pos,bool &r_includes_current,Vector<_RayResult> &results,bool p_alt_select) {
-
- Vector3 ray=_get_ray(p_pos);
- Vector3 pos=_get_ray_pos(p_pos);
-
- Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_ray(pos,ray,get_tree()->get_root()->get_world()->get_scenario() );
- Set<Ref<SpatialEditorGizmo> > found_gizmos;
-
- r_includes_current=false;
-
- for (int i=0;i<instances.size();i++) {
-
- Object *obj=ObjectDB::get_instance(instances[i]);
-
- if (!obj)
- continue;
-
- Spatial *spat=obj->cast_to<Spatial>();
-
- if (!spat)
- continue;
-
- Ref<SpatialEditorGizmo> seg = spat->get_gizmo();
-
- if (!seg.is_valid())
- continue;
-
- if (found_gizmos.has(seg))
- continue;
-
- found_gizmos.insert(seg);
- Vector3 point;
- Vector3 normal;
-
- int handle=-1;
- bool inters = seg->intersect_ray(camera,p_pos,point,normal,NULL,p_alt_select);
-
- if (!inters)
- continue;
-
- float dist = pos.distance_to(point);
-
- if (dist<0)
- continue;
-
-
-
- if (editor_selection->is_selected(spat))
- r_includes_current=true;
-
- _RayResult res;
- res.item=spat;
- res.depth=dist;
- res.handle=handle;
- results.push_back(res);
- }
-
-
- if (results.empty())
- return;
-
- results.sort();
-}
-
-
-Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3& p_pos) {
-
-
- CameraMatrix cm;
- cm.set_perspective(get_fov(),get_size().aspect(),get_znear(),get_zfar());
- float screen_w,screen_h;
- cm.get_viewport_size(screen_w,screen_h);
-
- Transform camera_transform;
- camera_transform.translate( cursor.pos );
- camera_transform.basis.rotate(Vector3(1,0,0),-cursor.x_rot);
- camera_transform.basis.rotate(Vector3(0,1,0),-cursor.y_rot);
- camera_transform.translate(0,0,cursor.distance);
-
- return camera_transform.xform(Vector3( ((p_pos.x/get_size().width)*2.0-1.0)*screen_w, ((1.0-(p_pos.y/get_size().height))*2.0-1.0)*screen_h,-get_znear()));
-
-}
-
-
-void SpatialEditorViewport::_select_region() {
-
- if (cursor.region_begin==cursor.region_end)
- return; //nothing really
-
- Vector3 box[4]={
- Vector3(
- MIN( cursor.region_begin.x, cursor.region_end.x),
- MIN( cursor.region_begin.y, cursor.region_end.y),
- 0
- ),
- Vector3(
- MAX( cursor.region_begin.x, cursor.region_end.x),
- MIN( cursor.region_begin.y, cursor.region_end.y),
- 0
- ),
- Vector3(
- MAX( cursor.region_begin.x, cursor.region_end.x),
- MAX( cursor.region_begin.y, cursor.region_end.y),
- 0
- ),
- Vector3(
- MIN( cursor.region_begin.x, cursor.region_end.x),
- MAX( cursor.region_begin.y, cursor.region_end.y),
- 0
- )
- };
-
- Vector<Plane> frustum;
-
- Vector3 cam_pos=_get_camera_pos();
- Set<Ref<SpatialEditorGizmo> > found_gizmos;
-
- for(int i=0;i<4;i++) {
-
- Vector3 a=_get_screen_to_space(box[i]);
- Vector3 b=_get_screen_to_space(box[(i+1)%4]);
- frustum.push_back( Plane(a,b,cam_pos) );
- }
-
- Plane near( cam_pos, -_get_camera_normal() );
- near.d-=get_znear();
-
- frustum.push_back( near );
-
- Plane far=-near;
- far.d+=500.0;
-
- frustum.push_back( far );
-
- Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_convex(frustum,get_tree()->get_root()->get_world()->get_scenario());
-
-
- for (int i=0;i<instances.size();i++) {
-
- Object *obj=ObjectDB::get_instance(instances[i]);
- if (!obj)
- continue;
- Spatial *sp = obj->cast_to<Spatial>();
- if (!sp)
- continue;
-
- Ref<SpatialEditorGizmo> seg = sp->get_gizmo();
-
- if (!seg.is_valid())
- continue;
-
- if (found_gizmos.has(seg))
- continue;
-
- if (seg->intersect_frustum(camera,frustum))
- _select(sp,true,false);
- }
-
-}
-
-void SpatialEditorViewport::_update_name() {
-
- String ortho = orthogonal?TTR("Orthogonal"):TTR("Perspective");
-
- if (name!="")
- view_menu->set_text("[ "+name+" "+ortho+" ]");
- else
- view_menu->set_text("[ "+ortho+" ]");
-}
-
-
-void SpatialEditorViewport::_compute_edit(const Point2& p_point) {
-
- _edit.click_ray=_get_ray( Vector2( p_point.x, p_point.y ) );
- _edit.click_ray_pos=_get_ray_pos( Vector2( p_point.x, p_point.y ) );
- _edit.plane=TRANSFORM_VIEW;
- spatial_editor->update_transform_gizmo();
- _edit.center=spatial_editor->get_gizmo_transform().origin;
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- //Vector3 center;
- //int nc=0;
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- se->original=se->sp->get_global_transform();
- //center+=se->original.origin;
- //nc++;
- }
-
- /*
- if (nc)
- _edit.center=center/float(nc);
- */
-}
-
-static int _get_key_modifier(const String& p_property) {
-
- switch(EditorSettings::get_singleton()->get(p_property).operator int()) {
-
- case 0: return 0;
- case 1: return KEY_SHIFT;
- case 2: return KEY_ALT;
- case 3: return KEY_META;
- case 4: return KEY_CONTROL;
- }
- return 0;
-}
-
-bool SpatialEditorViewport::_gizmo_select(const Vector2& p_screenpos,bool p_hilite_only) {
-
- if (!spatial_editor->is_gizmo_visible())
- return false;
- if (get_selected_count()==0) {
- if (p_hilite_only)
- spatial_editor->select_gizmo_hilight_axis(-1);
- return false;
- }
-
-
- Vector3 ray_pos=_get_ray_pos( Vector2( p_screenpos.x, p_screenpos.y ) );
- Vector3 ray=_get_ray( Vector2( p_screenpos.x, p_screenpos.y ) );
-
- Transform gt = spatial_editor->get_gizmo_transform();
- float gs=gizmo_scale;
-
- if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_MOVE) {
-
- int col_axis=-1;
- float col_d=1e20;
-
- for(int i=0;i<3;i++) {
-
- Vector3 grabber_pos = gt.origin+gt.basis.get_axis(i)*gs;
- float grabber_radius = gs*GIZMO_ARROW_SIZE;
-
- Vector3 r;
- if (Geometry::segment_intersects_sphere(ray_pos,ray_pos+ray*10000.0,grabber_pos,grabber_radius,&r)) {
- float d = r.distance_to(ray_pos);
- if (d<col_d) {
- col_d=d;
- col_axis=i;
- }
- }
- }
-
- if (col_axis!=-1) {
-
-
- if (p_hilite_only) {
-
- spatial_editor->select_gizmo_hilight_axis(col_axis);
-
-
- } else {
- //handle rotate
- _edit.mode=TRANSFORM_TRANSLATE;
- _compute_edit(Point2(p_screenpos.x,p_screenpos.y));
- _edit.plane=TransformPlane(TRANSFORM_X_AXIS+col_axis);
- }
- return true;
-
-
- }
-
- }
-
-
- if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_ROTATE) {
-
- int col_axis=-1;
- float col_d=1e20;
-
- for(int i=0;i<3;i++) {
-
- Plane plane(gt.origin,gt.basis.get_axis(i).normalized());
- Vector3 r;
- if (!plane.intersects_ray(ray_pos,ray,&r))
- continue;
-
- float dist = r.distance_to(gt.origin);
-
-
-
- if (dist > gs*(1-GIZMO_RING_HALF_WIDTH) && dist < gs *(1+GIZMO_RING_HALF_WIDTH)) {
-
- float d = ray_pos.distance_to(r);
- if (d<col_d) {
- col_d=d;
- col_axis=i;
- }
- }
- }
-
- if (col_axis!=-1) {
-
- if (p_hilite_only) {
-
- spatial_editor->select_gizmo_hilight_axis(col_axis+3);
- } else {
- //handle rotate
- _edit.mode=TRANSFORM_ROTATE;
- _compute_edit(Point2(p_screenpos.x,p_screenpos.y));
- _edit.plane=TransformPlane(TRANSFORM_X_AXIS+col_axis);
- }
- return true;
- }
- }
-
-
- if (p_hilite_only)
- spatial_editor->select_gizmo_hilight_axis(-1);
-
- return false;
-
-}
-
-
-void SpatialEditorViewport::_smouseenter() {
-
- if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
- 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_class(),"EditorIcons")?spat->get_class():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_class()+"\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)
- return; //do NONE
-
-
- {
-
- EditorNode *en = editor;
- EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
-
- if (!over_plugin_list->empty()) {
- bool discard = over_plugin_list->forward_spatial_gui_input(camera,p_event);
- if (discard)
- return;
- }
- }
-
- switch(p_event.type) {
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &b=p_event.mouse_button;
-
- switch(b.button_index) {
-
- case BUTTON_WHEEL_UP: {
-
-
- cursor.distance/=1.08;
- if (cursor.distance<0.001)
- cursor.distance=0.001;
-
- } break;
- case BUTTON_WHEEL_DOWN: {
-
- if (cursor.distance<0.001)
- cursor.distance=0.001;
- cursor.distance*=1.08;
-
- } break;
- case BUTTON_RIGHT: {
-
- NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
-
- if (b.pressed && _edit.gizmo.is_valid()) {
- //restore
- _edit.gizmo->commit_handle(_edit.gizmo_handle,_edit.gizmo_initial_value,true);
- _edit.gizmo=Ref<SpatialEditorGizmo>();
- }
-
- if (_edit.mode==TRANSFORM_NONE && b.pressed) {
-
- Plane cursor_plane(cursor.cursor_pos,_get_camera_normal());
-
- Vector3 ray_origin = _get_ray_pos(Vector2(b.x,b.y));
- Vector3 ray_dir = _get_ray(Vector2(b.x,b.y));
-
-
- //gizmo modify
-
- if (b.mod.control) {
-
- Vector<ObjectID> instances=VisualServer::get_singleton()->instances_cull_ray(ray_origin,ray_dir,get_tree()->get_root()->get_world()->get_scenario() );
-
- Plane p(ray_origin,_get_camera_normal());
-
- float min_d=1e10;
- bool found=false;
-
- for (int i=0;i<instances.size();i++) {
-
-
- Object *obj=ObjectDB::get_instance(instances[i]);
-
- if (!obj)
- continue;
-
- VisualInstance *vi=obj->cast_to<VisualInstance>();
- if (!vi)
- continue;
-
- //optimize by checking AABB (although should pre sort by distance)
- Rect3 aabb = vi->get_global_transform().xform(vi->get_aabb());
- if (p.distance_to(aabb.get_support(-ray_dir))>min_d)
- continue;
-
- PoolVector<Face3> faces = vi->get_faces(VisualInstance::FACES_SOLID);
- int c = faces.size();
- if (c>0) {
- PoolVector<Face3>::Read r = faces.read();
-
- for(int j=0;j<c;j++) {
-
- Vector3 inters;
- if (r[j].intersects_ray(ray_origin,ray_dir,&inters)) {
-
- float d = p.distance_to(inters);
- if (d<0)
- continue;
-
- if (d<min_d) {
- min_d=d;
- found=true;
- }
- }
-
- }
- }
-
- }
-
- if (found) {
-
- //cursor.cursor_pos=ray_origin+ray_dir*min_d;
- //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
-
- }
-
- } else {
- Vector3 new_pos;
- if (cursor_plane.intersects_ray(ray_origin,ray_dir,&new_pos)) {
-
- //cursor.cursor_pos=new_pos;
- //VisualServer::get_singleton()->instance_set_transform(cursor_instance,Transform(Matrix3(),cursor.cursor_pos));
- }
- }
-
- if (b.mod.alt) {
-
- if (nav_scheme == NAVIGATION_MAYA)
- break;
-
- _list_select(b);
- return;
-
- }
- }
-
- if (_edit.mode!=TRANSFORM_NONE && b.pressed) {
- //cancel motion
- _edit.mode=TRANSFORM_NONE;
- //_validate_selection();
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- sp->set_global_transform( se->original );
-
- }
- surface->update();
- //VisualServer::get_singleton()->poly_clear(indicators);
- set_message(TTR("Transform Aborted."),3);
- }
- } break;
- case BUTTON_MIDDLE: {
-
- if (b.pressed && _edit.mode!=TRANSFORM_NONE) {
-
- switch(_edit.plane ) {
-
- case TRANSFORM_VIEW: {
-
- _edit.plane=TRANSFORM_X_AXIS;
- set_message(TTR("X-Axis Transform."),2);
- name="";
- _update_name();
- } break;
- case TRANSFORM_X_AXIS: {
-
- _edit.plane=TRANSFORM_Y_AXIS;
- set_message(TTR("Y-Axis Transform."),2);
-
- } break;
- case TRANSFORM_Y_AXIS: {
-
- _edit.plane=TRANSFORM_Z_AXIS;
- set_message(TTR("Z-Axis Transform."),2);
-
- } break;
- case TRANSFORM_Z_AXIS: {
-
- _edit.plane=TRANSFORM_VIEW;
- set_message(TTR("View Plane Transform."),2);
-
- } break;
- }
-
- }
- } break;
- case BUTTON_LEFT: {
-
- if (b.pressed) {
-
- NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
- if ( (nav_scheme==NAVIGATION_MAYA || nav_scheme==NAVIGATION_MODO) && b.mod.alt) {
- 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;
-
-
- //gizmo has priority over everything
-
- bool can_select_gizmos=true;
-
- {
- int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
- can_select_gizmos = view_menu->get_popup()->is_item_checked( idx );
- }
-
-
-
- if (can_select_gizmos && spatial_editor->get_selected()) {
-
- Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo();
- if (seg.is_valid()) {
- int handle=-1;
- Vector3 point;
- Vector3 normal;
- bool inters = seg->intersect_ray(camera,_edit.mouse_pos,point,normal,&handle,b.mod.shift);
- if (inters && handle!=-1) {
-
- _edit.gizmo=seg;
- _edit.gizmo_handle=handle;
- //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
- _edit.gizmo_initial_value=seg->get_handle_value(handle);
- break;
-
- }
- }
- }
-
-
-
- if (_gizmo_select(_edit.mouse_pos))
- break;
-
- clicked=0;
- clicked_includes_current=false;
-
-
- if ((spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT && b.mod.control) || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_ROTATE) {
-
- /* HANDLE ROTATION */
- if (get_selected_count()==0)
- break; //bye
- //handle rotate
- _edit.mode=TRANSFORM_ROTATE;
- _compute_edit(Point2(b.x,b.y));
- break;
-
- }
-
- if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_MOVE) {
-
- if (get_selected_count()==0)
- break; //bye
- //handle rotate
- _edit.mode=TRANSFORM_TRANSLATE;
- _compute_edit(Point2(b.x,b.y));
- break;
-
-
- }
-
-
- if (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SCALE) {
-
- if (get_selected_count()==0)
- break; //bye
- //handle rotate
- _edit.mode=TRANSFORM_SCALE;
- _compute_edit(Point2(b.x,b.y));
- break;
-
-
- }
-
-
-
- // todo scale
-
- int gizmo_handle=-1;
-
- clicked=_select_ray(Vector2( b.x, b.y ),b.mod.shift,clicked_includes_current,&gizmo_handle,b.mod.shift);
-
- //clicking is always deferred to either move or release
-
- clicked_wants_append=b.mod.shift;
-
- if (!clicked) {
-
- if (!clicked_wants_append)
- _clear_selected();
-
- //default to regionselect
- cursor.region_select=true;
- cursor.region_begin=Point2(b.x,b.y);
- cursor.region_end=Point2(b.x,b.y);
- }
-
- if (clicked && gizmo_handle>=0) {
-
- Object *obj=ObjectDB::get_instance(clicked);
- if (obj) {
-
- Spatial *spa = obj->cast_to<Spatial>();
- if (spa) {
-
- Ref<SpatialEditorGizmo> seg=spa->get_gizmo();
- if (seg.is_valid()) {
-
- _edit.gizmo=seg;
- _edit.gizmo_handle=gizmo_handle;
- //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
- _edit.gizmo_initial_value=seg->get_handle_value(gizmo_handle);
- //print_line("GIZMO: "+itos(gizmo_handle)+" FROMPOS: "+_edit.orig_gizmo_pos);
- break;
-
- }
- }
-
- }
- //_compute_edit(Point2(b.x,b.y)); //in case a motion happens..
- }
-
-
-
- surface->update();
- } else {
-
-
- if (_edit.gizmo.is_valid()) {
-
- _edit.gizmo->commit_handle(_edit.gizmo_handle,_edit.gizmo_initial_value,false);
- _edit.gizmo=Ref<SpatialEditorGizmo>();
- break;
- }
- if (clicked) {
- _select_clicked(clicked_wants_append,true);
- //clickd processing was deferred
- clicked=0;
-
-
- }
-
- if (cursor.region_select) {
- _select_region();
- cursor.region_select=false;
- surface->update();
- }
-
-
- if (_edit.mode!=TRANSFORM_NONE) {
-
-
- static const char* _transform_name[4]={"None","Rotate","Translate","Scale"};
- undo_redo->create_action(_transform_name[_edit.mode]);
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- undo_redo->add_do_method(sp,"set_global_transform",sp->get_global_transform());
- undo_redo->add_undo_method(sp,"set_global_transform",se->original);
- }
- undo_redo->commit_action();
- _edit.mode=TRANSFORM_NONE;
- //VisualServer::get_singleton()->poly_clear(indicators);
- set_message("");
- }
-
-
- surface->update();
- }
- } break;
- }
- } break;
- case InputEvent::MOUSE_MOTION: {
- const InputEventMouseMotion &m=p_event.mouse_motion;
- _edit.mouse_pos=Point2(p_event.mouse_motion.x,p_event.mouse_motion.y);
-
- if (spatial_editor->get_selected()) {
-
-
- Ref<SpatialEditorGizmo> seg = spatial_editor->get_selected()->get_gizmo();
- if (seg.is_valid()) {
-
- int selected_handle=-1;
-
- int handle=-1;
- Vector3 point;
- Vector3 normal;
- bool inters = seg->intersect_ray(camera,_edit.mouse_pos,point,normal,&handle,false);
- if (inters && handle!=-1) {
-
- selected_handle=handle;
-
- }
-
- if (selected_handle!=spatial_editor->get_over_gizmo_handle()) {
- spatial_editor->set_over_gizmo_handle(selected_handle);
- spatial_editor->get_selected()->update_gizmo();
- if (selected_handle!=-1)
- spatial_editor->select_gizmo_hilight_axis(-1);
- }
- }
- }
-
- if (spatial_editor->get_over_gizmo_handle()==-1 && !(m.button_mask&1) && !_edit.gizmo.is_valid()) {
-
- _gizmo_select(_edit.mouse_pos,true);
-
- }
-
- NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
- NavigationMode nav_mode = NAVIGATION_NONE;
-
- if (_edit.gizmo.is_valid()) {
-
- _edit.gizmo->set_handle(_edit.gizmo_handle,camera,Vector2(m.x,m.y));
- Variant v = _edit.gizmo->get_handle_value(_edit.gizmo_handle);
- String n = _edit.gizmo->get_handle_name(_edit.gizmo_handle);
- set_message(n+": "+String(v));
-
- } else if (m.button_mask&1) {
-
- if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
- nav_mode = NAVIGATION_ORBIT;
- } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt && m.mod.shift) {
- nav_mode = NAVIGATION_PAN;
- } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt && m.mod.control) {
- nav_mode = NAVIGATION_ZOOM;
- } else if (nav_scheme == NAVIGATION_MODO && m.mod.alt) {
- nav_mode = NAVIGATION_ORBIT;
- } else {
- if (clicked) {
-
- if (!clicked_includes_current) {
-
- _select_clicked(clicked_wants_append,true);
- //clickd processing was deferred
- }
-
-
- _compute_edit(_edit.mouse_pos);
- clicked=0;
-
- _edit.mode=TRANSFORM_TRANSLATE;
-
- }
-
- if (cursor.region_select && nav_mode == NAVIGATION_NONE) {
-
- cursor.region_end=Point2(m.x,m.y);
- surface->update();
- return;
- }
-
- if (_edit.mode==TRANSFORM_NONE && nav_mode == NAVIGATION_NONE)
- break;
-
-
- Vector3 ray_pos=_get_ray_pos( Vector2( m.x, m.y ) );
- Vector3 ray=_get_ray( Vector2( m.x, m.y ) );
-
-
- switch(_edit.mode) {
-
- case TRANSFORM_SCALE: {
-
-
- Plane plane=Plane(_edit.center,_get_camera_normal());
-
-
- Vector3 intersection;
- if (!plane.intersects_ray(ray_pos,ray,&intersection))
- break;
-
- Vector3 click;
- if (!plane.intersects_ray(_edit.click_ray_pos,_edit.click_ray,&click))
- break;
-
- float center_click_dist = click.distance_to(_edit.center);
- float center_inters_dist = intersection.distance_to(_edit.center);
- if (center_click_dist==0)
- break;
-
- float scale = (center_inters_dist / center_click_dist)*100.0;
-
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
-
- scale = Math::stepify(scale,spatial_editor->get_scale_snap());
- }
-
- set_message(vformat(TTR("Scaling to %s%%."),String::num(scale,1)));
- scale/=100.0;
-
- Transform r;
- r.basis.scale(Vector3(scale,scale,scale));
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
-
- Transform original=se->original;
-
- Transform base=Transform( Basis(), _edit.center);
- Transform t=base * (r * (base.inverse() * original));
-
- sp->set_global_transform(t);
- }
-
- surface->update();
-
- } break;
-
- case TRANSFORM_TRANSLATE: {
-
-
- Vector3 motion_mask;
- Plane plane;
-
- switch( _edit.plane ) {
- case TRANSFORM_VIEW:
- motion_mask=Vector3(0,0,0);
- plane=Plane(_edit.center,_get_camera_normal());
- break;
- case TRANSFORM_X_AXIS:
- motion_mask=spatial_editor->get_gizmo_transform().basis.get_axis(0);
- plane=Plane(_edit.center,motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
- break;
- case TRANSFORM_Y_AXIS:
- motion_mask=spatial_editor->get_gizmo_transform().basis.get_axis(1);
- plane=Plane(_edit.center,motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
- break;
- case TRANSFORM_Z_AXIS:
- motion_mask=spatial_editor->get_gizmo_transform().basis.get_axis(2);
- plane=Plane(_edit.center,motion_mask.cross(motion_mask.cross(_get_camera_normal())).normalized());
- break;
- }
-
- Vector3 intersection;
- if (!plane.intersects_ray(ray_pos,ray,&intersection))
- break;
-
- Vector3 click;
- if (!plane.intersects_ray(_edit.click_ray_pos,_edit.click_ray,&click))
- break;
-
- //_validate_selection();
- Vector3 motion = intersection-click;
- if (motion_mask!=Vector3()) {
- motion=motion_mask.dot(motion)*motion_mask;
- }
-
- float snap=0;
-
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
-
- snap = spatial_editor->get_translate_snap();
- motion.snap(snap);
- }
-
- //set_message("Translating: "+motion);
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp) {
- continue;
- }
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se) {
- continue;
- }
-
- Transform t=se->original;
- t.origin+=motion;
- sp->set_global_transform(t);
- }
- } break;
-
- case TRANSFORM_ROTATE: {
-
-
- Plane plane;
-
- switch( _edit.plane ) {
- case TRANSFORM_VIEW:
- plane=Plane(_edit.center,_get_camera_normal());
- break;
- case TRANSFORM_X_AXIS:
- plane=Plane(_edit.center,spatial_editor->get_gizmo_transform().basis.get_axis(0));
- break;
- case TRANSFORM_Y_AXIS:
- plane=Plane(_edit.center,spatial_editor->get_gizmo_transform().basis.get_axis(1));
- break;
- case TRANSFORM_Z_AXIS:
- plane=Plane(_edit.center,spatial_editor->get_gizmo_transform().basis.get_axis(2));
- break;
- }
-
- Vector3 intersection;
- if (!plane.intersects_ray(ray_pos,ray,&intersection))
- break;
-
- Vector3 click;
- if (!plane.intersects_ray(_edit.click_ray_pos,_edit.click_ray,&click))
- break;
-
-
- Vector3 y_axis=(click-_edit.center).normalized();
- Vector3 x_axis=plane.normal.cross(y_axis).normalized();
-
- float angle=Math::atan2( x_axis.dot(intersection-_edit.center), y_axis.dot(intersection-_edit.center) );
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
-
- float snap = spatial_editor->get_rotate_snap();
-
- if (snap) {
- angle=Math::rad2deg(angle)+snap*0.5; //else it wont reach +180
- angle-=Math::fmod(angle,snap);
- set_message(vformat(TTR("Rotating %s degrees."),rtos(angle)));
- angle=Math::deg2rad(angle);
- } else
- set_message(vformat(TTR("Rotating %s degrees."),rtos(Math::rad2deg(angle))));
-
- } else {
- set_message(vformat(TTR("Rotating %s degrees."),rtos(Math::rad2deg(angle))));
- }
-
-
-
-
- Transform r;
- r.basis.rotate(plane.normal,angle);
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
-
- Transform original=se->original;
-
- Transform base=Transform( Basis(), _edit.center);
- Transform t=base * r * base.inverse() * original;
-
- sp->set_global_transform(t);
- }
-
- surface->update();
- /*
- VisualServer::get_singleton()->poly_clear(indicators);
-
- Vector<Vector3> points;
- Vector<Vector3> empty;
- Vector<Color> colors;
- points.push_back(intersection);
- points.push_back(_edit.original.origin);
- colors.push_back( Color(255,155,100) );
- colors.push_back( Color(255,155,100) );
- VisualServer::get_singleton()->poly_add_primitive(indicators,points,empty,colors,empty);
- */
- } break;
- default:{}
- }
-
- }
-
- } else if (m.button_mask&2) {
-
- if (nav_scheme == NAVIGATION_MAYA && m.mod.alt) {
- nav_mode = NAVIGATION_ZOOM;
- }
-
- } else if (m.button_mask&4) {
-
- if (nav_scheme == NAVIGATION_GODOT) {
-
- int mod = 0;
- if (m.mod.shift)
- mod=KEY_SHIFT;
- if (m.mod.alt)
- mod=KEY_ALT;
- if (m.mod.control)
- mod=KEY_CONTROL;
- if (m.mod.meta)
- mod=KEY_META;
-
- if (mod == _get_key_modifier("editors/3d/pan_modifier"))
- nav_mode = NAVIGATION_PAN;
- else if (mod == _get_key_modifier("editors/3d/zoom_modifier"))
- nav_mode = NAVIGATION_ZOOM;
- else if (mod == _get_key_modifier("editors/3d/orbit_modifier"))
- nav_mode = NAVIGATION_ORBIT;
-
- } else if (nav_scheme == NAVIGATION_MAYA) {
- if (m.mod.alt)
- nav_mode = NAVIGATION_PAN;
- }
-
- } else if (EditorSettings::get_singleton()->get("editors/3d/emulate_3_button_mouse")) {
- // Handle trackpad (no external mouse) use case
- int mod = 0;
- if (m.mod.shift)
- mod=KEY_SHIFT;
- if (m.mod.alt)
- mod=KEY_ALT;
- if (m.mod.control)
- mod=KEY_CONTROL;
- if (m.mod.meta)
- mod=KEY_META;
-
- if(mod){
- if (mod == _get_key_modifier("editors/3d/pan_modifier"))
- nav_mode = NAVIGATION_PAN;
- else if (mod == _get_key_modifier("editors/3d/zoom_modifier"))
- nav_mode = NAVIGATION_ZOOM;
- else if (mod == _get_key_modifier("editors/3d/orbit_modifier"))
- nav_mode = NAVIGATION_ORBIT;
- }
- }
-
- switch(nav_mode) {
- case NAVIGATION_PAN:{
-
- real_t pan_speed = 1/150.0;
- int pan_speed_modifier = 10;
- if (nav_scheme==NAVIGATION_MAYA && m.mod.shift)
- pan_speed *= pan_speed_modifier;
-
- Transform camera_transform;
-
- camera_transform.translate(cursor.pos);
- camera_transform.basis.rotate(Vector3(1,0,0),-cursor.x_rot);
- camera_transform.basis.rotate(Vector3(0,1,0),-cursor.y_rot);
- Vector3 translation(-m.relative_x*pan_speed,m.relative_y*pan_speed,0);
- translation*=cursor.distance/DISTANCE_DEFAULT;
- camera_transform.translate(translation);
- cursor.pos=camera_transform.origin;
-
- } break;
-
- case NAVIGATION_ZOOM: {
- real_t zoom_speed = 1/80.0;
- int zoom_speed_modifier = 10;
- if (nav_scheme==NAVIGATION_MAYA && m.mod.shift)
- zoom_speed *= zoom_speed_modifier;
-
- NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/zoom_style").operator int();
- if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
- if ( m.relative_x > 0)
- cursor.distance*=1-m.relative_x*zoom_speed;
- else if (m.relative_x < 0)
- cursor.distance/=1+m.relative_x*zoom_speed;
- }
- else {
- if ( m.relative_y > 0)
- cursor.distance*=1+m.relative_y*zoom_speed;
- else if (m.relative_y < 0)
- cursor.distance/=1-m.relative_y*zoom_speed;
- }
-
- } break;
-
- case NAVIGATION_ORBIT: {
- cursor.x_rot+=m.relative_y/80.0;
- cursor.y_rot+=m.relative_x/80.0;
- if (cursor.x_rot>Math_PI/2.0)
- cursor.x_rot=Math_PI/2.0;
- if (cursor.x_rot<-Math_PI/2.0)
- cursor.x_rot=-Math_PI/2.0;
- name="";
- _update_name();
- } break;
-
- default: {}
- }
- } break;
- case InputEvent::KEY: {
- const InputEventKey &k = p_event.key;
- if (!k.pressed)
- break;
-
- if (ED_IS_SHORTCUT("spatial_editor/snap", p_event)) {
- if (_edit.mode != TRANSFORM_NONE) {
- _edit.snap=true;
- }
- }
- if (ED_IS_SHORTCUT("spatial_editor/bottom_view", p_event)) {
- cursor.y_rot = 0;
- cursor.x_rot = -Math_PI/2.0;
- set_message(TTR("Bottom View."),2);
- name = TTR("Bottom");
- _update_name();
- }
- if (ED_IS_SHORTCUT("spatial_editor/top_view", p_event)) {
- cursor.y_rot = 0;
- cursor.x_rot = Math_PI/2.0;
- set_message(TTR("Top View."),2);
- name = TTR("Top");
- _update_name();
- }
- if (ED_IS_SHORTCUT("spatial_editor/rear_view", p_event)) {
- cursor.x_rot = 0;
- cursor.y_rot = Math_PI;
- set_message(TTR("Rear View."),2);
- name = TTR("Rear");
- _update_name();
- }
- if (ED_IS_SHORTCUT("spatial_editor/front_view", p_event)) {
- cursor.x_rot = 0;
- cursor.y_rot=0;
- set_message(TTR("Front View."),2);
- name=TTR("Front");
- _update_name();
- }
- if (ED_IS_SHORTCUT("spatial_editor/left_view", p_event)) {
- cursor.x_rot=0;
- cursor.y_rot = Math_PI/2.0;
- set_message(TTR("Left View."),2);
- name = TTR("Left");
- _update_name();
- }
- if (ED_IS_SHORTCUT("spatial_editor/right_view", p_event)) {
- cursor.x_rot=0;
- cursor.y_rot = -Math_PI/2.0;
- set_message(TTR("Right View."),2);
- name = TTR("Right");
- _update_name();
- }
- if (ED_IS_SHORTCUT("spatial_editor/switch_perspective_orthogonal", p_event)) {
- _menu_option(orthogonal?VIEW_PERSPECTIVE:VIEW_ORTHOGONAL);
- _update_name();
- }
- if (ED_IS_SHORTCUT("spatial_editor/insert_anim_key", p_event)) {
- if (!get_selected_count() || _edit.mode!=TRANSFORM_NONE)
- break;
-
- if (!AnimationPlayerEditor::singleton->get_key_editor()->has_keying()) {
- set_message(TTR("Keying is disabled (no key inserted)."));
- break;
- }
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- emit_signal("transform_key_request",sp,"",sp->get_transform());
- }
-
-
- set_message(TTR("Animation Key Inserted."));
- }
-
- if (k.scancode == KEY_SPACE) {
- if (!k.pressed) emit_signal("toggle_maximize_view", this);
- }
-
- } break;
-
- }
-
-}
-
-void SpatialEditorViewport::set_message(String p_message,float p_time) {
-
- message=p_message;
- message_time=p_time;
-
-}
-
-
-
-void SpatialEditorViewport::_notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
-
- bool visible=is_visible_in_tree();
-
- set_process(visible);
-
- if (visible)
- _update_camera();
-
- call_deferred("update_transform_gizmo_view");
- }
-
- if (p_what==NOTIFICATION_RESIZED) {
-
- call_deferred("update_transform_gizmo_view");
-
- }
-
- if (p_what==NOTIFICATION_PROCESS) {
-
-
- //force editr camera
- /*
- current_camera=get_root_node()->get_current_camera();
- if (current_camera!=camera) {
-
-
- }
- */
-
- _update_camera();
-
- Map<Node*,Object*> &selection = editor_selection->get_selection();
-
- bool changed=false;
- bool exist=false;
-
- for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->key()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
-
- VisualInstance *vi=sp->cast_to<VisualInstance>();
-
-
- if (se->aabb.has_no_surface()) {
-
- se->aabb=vi?vi->get_aabb():Rect3( Vector3(-0.2,-0.2,-0.2),Vector3(0.4,0.4,0.4));
- }
-
- Transform t=sp->get_global_transform();
- t.translate(se->aabb.pos);
- t.basis.scale( se->aabb.size );
-
- exist=true;
- if (se->last_xform==t)
- continue;
- changed=true;
- se->last_xform=t;
- VisualServer::get_singleton()->instance_set_transform(se->sbox_instance,t);
-
- }
-
- if (changed || (spatial_editor->is_gizmo_visible() && !exist)) {
- spatial_editor->update_transform_gizmo();
- }
-
- if (message_time>0) {
-
- if (message!=last_message) {
- surface->update();
- last_message=message;
- }
-
- message_time-=get_fixed_process_delta_time();
- if (message_time<0)
- surface->update();
- }
-
- //update shadow atlas if changed
-
- int shadowmap_size = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/size");
- int atlas_q0 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_0_subdiv");
- int atlas_q1 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_1_subdiv");
- int atlas_q2 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_2_subdiv");
- int atlas_q3 = GlobalConfig::get_singleton()->get("rendering/shadow_atlas/quadrant_3_subdiv");
-
-
- viewport->set_shadow_atlas_size(shadowmap_size);
- viewport->set_shadow_atlas_quadrant_subdiv(0,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
- viewport->set_shadow_atlas_quadrant_subdiv(1,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
- viewport->set_shadow_atlas_quadrant_subdiv(2,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
- viewport->set_shadow_atlas_quadrant_subdiv(3,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
-
- //update msaa if changed
-
- int msaa_mode = GlobalConfig::get_singleton()->get("rendering/quality/msaa");
- viewport->set_msaa(Viewport::MSAA(msaa_mode));
-
- bool hdr = GlobalConfig::get_singleton()->get("rendering/quality/hdr");
- viewport->set_hdr(hdr);
-
-
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- surface->connect("draw",this,"_draw");
- surface->connect("gui_input",this,"_sinput");
- surface->connect("mouse_entered",this,"_smouseenter");
- preview_camera->set_icon(get_icon("Camera","EditorIcons"));
- _init_gizmo_instance(index);
- }
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
-
- _finish_gizmo_instances();
-
- }
-
- if (p_what==NOTIFICATION_MOUSE_ENTER) {
-
-
- }
-
-
- if (p_what==NOTIFICATION_DRAW) {
-
-
-
- }
-
-}
-
-void SpatialEditorViewport::_draw() {
-
- if (surface->has_focus()) {
- Size2 size = surface->get_size();
- Rect2 r =Rect2(Point2(),size);
- get_stylebox("EditorFocus","EditorStyles")->draw(surface->get_canvas_item(),r);
- }
-
-
- RID ci=surface->get_canvas_item();
-
- if (cursor.region_select) {
-
- VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor.region_begin,cursor.region_end-cursor.region_begin),Color(0.7,0.7,1.0,0.3));
- }
-
- if (message_time>0) {
- Ref<Font> font = get_font("font","Label");
- Point2 msgpos=Point2(5,get_size().y-20);
- font->draw(ci,msgpos+Point2(1,1),message,Color(0,0,0,0.8));
- font->draw(ci,msgpos+Point2(-1,-1),message,Color(0,0,0,0.8));
- font->draw(ci,msgpos,message,Color(1,1,1,1));
- }
-
-
- if (_edit.mode==TRANSFORM_ROTATE) {
-
- Point2 center = _point_to_screen(_edit.center);
- VisualServer::get_singleton()->canvas_item_add_line(ci,_edit.mouse_pos, center, Color(0.4,0.7,1.0,0.8));
-
-
- }
-
- if (previewing) {
-
-
- Size2 ss = Size2( GlobalConfig::get_singleton()->get("display/width"), GlobalConfig::get_singleton()->get("display/height") );
- float aspect = ss.aspect();
- Size2 s = get_size();
-
- Rect2 draw_rect;
-
-
- switch(previewing->get_keep_aspect_mode()) {
- case Camera::KEEP_WIDTH: {
-
- draw_rect.size = Size2(s.width,s.width/aspect);
- draw_rect.pos.x=0;
- draw_rect.pos.y=(s.height-draw_rect.size.y)*0.5;
-
- } break;
- case Camera::KEEP_HEIGHT: {
-
- draw_rect.size = Size2(s.height*aspect,s.height);
- draw_rect.pos.y=0;
- draw_rect.pos.x=(s.width-draw_rect.size.x)*0.5;
-
- } break;
- }
-
- draw_rect = Rect2(Vector2(),s).clip(draw_rect);
-
- surface->draw_line(draw_rect.pos,draw_rect.pos+Vector2(draw_rect.size.x,0),Color(0.6,0.6,0.1,0.5),2.0);
- surface->draw_line(draw_rect.pos+Vector2(draw_rect.size.x,0),draw_rect.pos+draw_rect.size,Color(0.6,0.6,0.1,0.5),2.0);
- surface->draw_line(draw_rect.pos+draw_rect.size,draw_rect.pos+Vector2(0,draw_rect.size.y),Color(0.6,0.6,0.1,0.5),2.0);
- surface->draw_line(draw_rect.pos,draw_rect.pos+Vector2(0,draw_rect.size.y),Color(0.6,0.6,0.1,0.5),2.0);
- }
-
-}
-
-
-void SpatialEditorViewport::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case VIEW_TOP: {
-
- cursor.x_rot=Math_PI/2.0;
- cursor.y_rot=0;
- name=TTR("Top");
- _update_name();
- } break;
- case VIEW_BOTTOM: {
-
- cursor.x_rot=-Math_PI/2.0;
- cursor.y_rot=0;
- name=TTR("Bottom");
- _update_name();
-
- } break;
- case VIEW_LEFT: {
-
- cursor.y_rot=Math_PI/2.0;
- cursor.x_rot=0;
- name=TTR("Left");
- _update_name();
-
- } break;
- case VIEW_RIGHT: {
-
- cursor.y_rot=-Math_PI/2.0;
- cursor.x_rot=0;
- name=TTR("Right");
- _update_name();
-
- } break;
- case VIEW_FRONT: {
-
- cursor.y_rot=0;
- cursor.x_rot=0;
- name=TTR("Front");
- _update_name();
-
- } break;
- case VIEW_REAR: {
-
- cursor.y_rot=Math_PI;
- cursor.x_rot=0;
- name=TTR("Rear");
- _update_name();
-
- } break;
- case VIEW_CENTER_TO_ORIGIN: {
-
- cursor.pos = Vector3(0,0,0);
-
- } break;
- case VIEW_CENTER_TO_SELECTION: {
-
- focus_selection();
-
- } break;
- case VIEW_ALIGN_SELECTION_WITH_VIEW: {
-
- if (!get_selected_count())
- break;
-
- Transform camera_transform = camera->get_global_transform();
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- undo_redo->create_action(TTR("Align with view"));
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- Transform xform = camera_transform;
- xform.scale_basis(sp->get_scale());
-
- undo_redo->add_do_method(sp,"set_global_transform",xform);
- undo_redo->add_undo_method(sp,"set_global_transform",sp->get_global_transform());
- }
- undo_redo->commit_action();
- } break;
- case VIEW_ENVIRONMENT: {
-
- int idx = view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT);
- bool current = view_menu->get_popup()->is_item_checked( idx );
- current=!current;
- if (current) {
-
- camera->set_environment(RES());
- } else {
-
- camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
- }
-
- view_menu->get_popup()->set_item_checked( idx, current );
-
-
- } break;
- case VIEW_PERSPECTIVE: {
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), false );
- orthogonal=false;
- call_deferred("update_transform_gizmo_view");
- _update_name();
-
- } break;
- case VIEW_ORTHOGONAL: {
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ORTHOGONAL), true );
- orthogonal=true;
- call_deferred("update_transform_gizmo_view");
- _update_name();
-
- } break;
- case VIEW_AUDIO_LISTENER: {
-
- int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
- bool current = view_menu->get_popup()->is_item_checked( idx );
- current=!current;
- viewport->set_as_audio_listener(current);
- view_menu->get_popup()->set_item_checked( idx, current );
-
- } break;
- case VIEW_GIZMOS: {
-
- int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
- bool current = view_menu->get_popup()->is_item_checked( idx );
- current=!current;
- if (current)
- camera->set_cull_mask( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) );
- else
- camera->set_cull_mask( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+index))|(1<<GIZMO_GRID_LAYER) );
- view_menu->get_popup()->set_item_checked( idx, current );
-
- } break;
-
- }
-
-}
-
-
-void SpatialEditorViewport::_preview_exited_scene() {
-
- preview_camera->set_pressed(false);
- _toggle_camera_preview(false);
- view_menu->show();
-}
-
-
-void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
-
- uint32_t layer=1<<(GIZMO_BASE_LAYER+p_idx);//|(1<<GIZMO_GRID_LAYER);
-
- for(int i=0;i<3;i++) {
- move_gizmo_instance[i]=VS::get_singleton()->instance_create();
- VS::get_singleton()->instance_set_base(move_gizmo_instance[i],spatial_editor->get_move_gizmo(i)->get_rid());
- VS::get_singleton()->instance_set_scenario(move_gizmo_instance[i],get_tree()->get_root()->get_world()->get_scenario());
- VS::get_singleton()->instance_set_visible(move_gizmo_instance[i],false);
- //VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
- VS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
- VS::get_singleton()->instance_set_layer_mask(move_gizmo_instance[i],layer);
-
- rotate_gizmo_instance[i]=VS::get_singleton()->instance_create();
- VS::get_singleton()->instance_set_base(rotate_gizmo_instance[i],spatial_editor->get_rotate_gizmo(i)->get_rid());
- VS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i],get_tree()->get_root()->get_world()->get_scenario());
- VS::get_singleton()->instance_set_visible(rotate_gizmo_instance[i],false);
- //VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
- VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
- VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i],layer);
- }
-
-}
-
-
-void SpatialEditorViewport::_finish_gizmo_instances() {
-
-
- for(int i=0;i<3;i++) {
- VS::get_singleton()->free(move_gizmo_instance[i]);
- VS::get_singleton()->free(rotate_gizmo_instance[i]);
- }
-
-}
-void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
-
-
- ERR_FAIL_COND(p_activate && !preview);
- ERR_FAIL_COND(!p_activate && !previewing);
-
- if (!p_activate) {
-
- previewing->disconnect("tree_exited",this,"_preview_exited_scene");
- previewing=NULL;
- VS::get_singleton()->viewport_attach_camera( viewport->get_viewport_rid(), camera->get_camera() ); //restore
- if (!preview)
- preview_camera->hide();
- view_menu->show();
- surface->update();
-
- } else {
-
- previewing=preview;
- previewing->connect("tree_exited",this,"_preview_exited_scene");
- VS::get_singleton()->viewport_attach_camera( viewport->get_viewport_rid(), preview->get_camera() ); //replace
- view_menu->hide();
- surface->update();
-
- }
-}
-
-void SpatialEditorViewport::_selection_result_pressed(int p_result) {
-
- if (selection_results.size() <= p_result)
- return;
-
- clicked=selection_results[p_result].item->get_instance_ID();
-
- if (clicked) {
- _select_clicked(clicked_wants_append,true);
- clicked=0;
- }
-}
-
-void SpatialEditorViewport::_selection_menu_hide() {
-
- selection_results.clear();
- selection_menu->clear();
- selection_menu->set_size(Vector2(0, 0));
-}
-
-void SpatialEditorViewport::set_can_preview(Camera* p_preview) {
-
- preview=p_preview;
-
- if (!preview_camera->is_pressed()) {
-
- if (p_preview) {
- preview_camera->show();
- } else {
- preview_camera->hide();
- }
- }
-}
-
-void SpatialEditorViewport::update_transform_gizmo_view() {
-
- if (!is_visible_in_tree())
- return;
-
- Transform xform = spatial_editor->get_gizmo_transform();
-
-
- Transform camera_xform = camera->get_transform();
- Vector3 camz = -camera_xform.get_basis().get_axis(2).normalized();
- Vector3 camy = -camera_xform.get_basis().get_axis(1).normalized();
- Plane p(camera_xform.origin,camz);
- float gizmo_d = Math::abs( p.distance_to(xform.origin ));
- float d0 = camera->unproject_position(camera_xform.origin+camz*gizmo_d).y;
- float d1 = camera->unproject_position(camera_xform.origin+camz*gizmo_d+camy).y;
- float dd = Math::abs(d0-d1);
- if (dd==0)
- dd=0.0001;
-
- float gsize = EditorSettings::get_singleton()->get("editors/3d/manipulator_gizmo_size");
- gizmo_scale=(gsize/Math::abs(dd));
- Vector3 scale = Vector3(1,1,1) * gizmo_scale;
-
- xform.basis.scale(scale);
-
- //xform.basis.scale(GIZMO_SCALE_DEFAULT*Vector3(1,1,1));
-
-
- for(int i=0;i<3;i++) {
- VisualServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform );
- VisualServer::get_singleton()->instance_set_visible(move_gizmo_instance[i],spatial_editor->is_gizmo_visible()&& (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_MOVE) );
- VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform );
- VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i],spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode()==SpatialEditor::TOOL_MODE_ROTATE) );
- }
-
-}
-
-void SpatialEditorViewport::set_state(const Dictionary& p_state) {
-
- cursor.pos=p_state["pos"];
- cursor.x_rot=p_state["x_rot"];
- cursor.y_rot=p_state["y_rot"];
- cursor.distance=p_state["distance"];
- bool env = p_state["use_environment"];
- bool orth = p_state["use_orthogonal"];
- if (orth)
- _menu_option(VIEW_ORTHOGONAL);
- else
- _menu_option(VIEW_PERSPECTIVE);
- if (env != camera->get_environment().is_valid())
- _menu_option(VIEW_ENVIRONMENT);
- if (p_state.has("listener")) {
- bool listener = p_state["listener"];
-
- int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
- viewport->set_as_audio_listener(listener);
- view_menu->get_popup()->set_item_checked( idx, listener );
- }
-
- if (p_state.has("previewing")) {
- Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]);
- if (pv && pv->cast_to<Camera>()) {
- previewing=pv->cast_to<Camera>();
- previewing->connect("tree_exited",this,"_preview_exited_scene");
- VS::get_singleton()->viewport_attach_camera( viewport->get_viewport_rid(), previewing->get_camera() ); //replace
- view_menu->hide();
- surface->update();
- preview_camera->set_pressed(true);
- preview_camera->show();
- }
- }
-}
-
-Dictionary SpatialEditorViewport::get_state() const {
-
- Dictionary d;
- d["pos"]=cursor.pos;
- d["x_rot"]=cursor.x_rot;
- d["y_rot"]=cursor.y_rot;
- d["distance"]=cursor.distance;
- d["use_environment"]=camera->get_environment().is_valid();
- d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
- d["listener"]=viewport->is_audio_listener();
- if (previewing) {
- d["previewing"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);
- }
-
- return d;
-}
-
-
-void SpatialEditorViewport::_bind_methods(){
-
- ClassDB::bind_method(_MD("_draw"),&SpatialEditorViewport::_draw);
- ClassDB::bind_method(_MD("_smouseenter"),&SpatialEditorViewport::_smouseenter);
- ClassDB::bind_method(_MD("_sinput"),&SpatialEditorViewport::_sinput);
- ClassDB::bind_method(_MD("_menu_option"),&SpatialEditorViewport::_menu_option);
- ClassDB::bind_method(_MD("_toggle_camera_preview"),&SpatialEditorViewport::_toggle_camera_preview);
- ClassDB::bind_method(_MD("_preview_exited_scene"),&SpatialEditorViewport::_preview_exited_scene);
- ClassDB::bind_method(_MD("update_transform_gizmo_view"),&SpatialEditorViewport::update_transform_gizmo_view);
- ClassDB::bind_method(_MD("_selection_result_pressed"),&SpatialEditorViewport::_selection_result_pressed);
- ClassDB::bind_method(_MD("_selection_menu_hide"),&SpatialEditorViewport::_selection_menu_hide);
-
- ADD_SIGNAL( MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")) );
-}
-
-
-void SpatialEditorViewport::reset() {
-
- orthogonal=false;
- message_time=0;
- message="";
- last_message="";
- name="";
-
- cursor.x_rot=0.5;
- cursor.y_rot=0.5;
- cursor.distance=4;
- cursor.region_select=false;
- _update_name();
-}
-
-
-void SpatialEditorViewport::focus_selection() {
- if (!get_selected_count())
- return;
-
- Vector3 center;
- int count=0;
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- center+=sp->get_global_transform().origin;
- count++;
- }
-
- if( count != 0 ) {
- center/=float(count);
- }
-
- cursor.pos=center;
-}
-
-
-SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
-
- _edit.mode=TRANSFORM_NONE;
- _edit.plane=TRANSFORM_VIEW;
- _edit.edited_gizmo=0;
- _edit.snap=1;
- _edit.gizmo_handle=0;
-
-
-
- index=p_index;
- editor=p_editor;
- editor_selection=editor->get_editor_selection();
- undo_redo=editor->get_undo_redo();
- clicked=0;
- clicked_includes_current=false;
- orthogonal=false;
- message_time=0;
-
- spatial_editor=p_spatial_editor;
- ViewportContainer *c=memnew(ViewportContainer);
- c->set_stretch(true);
- 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);
- surface->set_area_as_parent_rect();
- camera = memnew(Camera);
- camera->set_disable_gizmo(true);
- camera->set_cull_mask( ((1<<20)-1)|(1<<(GIZMO_BASE_LAYER+p_index))|(1<<GIZMO_EDIT_LAYER)|(1<<GIZMO_GRID_LAYER) );
- //camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
- viewport->add_child(camera);
- camera->make_current();
- surface->set_focus_mode(FOCUS_ALL);
-
- view_menu = memnew( MenuButton );
- surface->add_child(view_menu);
- view_menu->set_pos( Point2(4,4));
- view_menu->set_self_modulate(Color(1,1,1,0.5));
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/top_view"), VIEW_TOP);
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/bottom_view"), VIEW_BOTTOM);
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/left_view"), VIEW_LEFT);
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/right_view"), VIEW_RIGHT);
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/front_view"), VIEW_FRONT);
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/rear_view"), VIEW_REAR);
- view_menu->get_popup()->add_separator();
- view_menu->get_popup()->add_check_item(TTR("Perspective") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_PERSPECTIVE);
- view_menu->get_popup()->add_check_item(TTR("Orthogonal") + " (" + ED_GET_SHORTCUT("spatial_editor/switch_perspective_orthogonal")->get_as_text() + ")", VIEW_ORTHOGONAL);
- view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_PERSPECTIVE),true);
- view_menu->get_popup()->add_separator();
- view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_environment", TTR("Environment")), VIEW_ENVIRONMENT);
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT),true);
- view_menu->get_popup()->add_separator();
- view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_audio_listener", TTR("Audio Listener")), VIEW_AUDIO_LISTENER);
- view_menu->get_popup()->add_separator();
- view_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_gizmos", TTR("Gizmos")),VIEW_GIZMOS);
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_GIZMOS),true);
-
- view_menu->get_popup()->add_separator();
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_origin"), VIEW_CENTER_TO_ORIGIN);
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/focus_selection"), VIEW_CENTER_TO_SELECTION);
- view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW);
- view_menu->get_popup()->connect("id_pressed",this,"_menu_option");
-
- preview_camera = memnew( Button );
- preview_camera->set_toggle_mode(true);
- preview_camera->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,90);
- preview_camera->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,10);
- preview_camera->set_text("preview");
- surface->add_child(preview_camera);
- preview_camera->hide();
- preview_camera->connect("toggled",this,"_toggle_camera_preview");
- previewing=NULL;
- preview=NULL;
- gizmo_scale=1.0;
-
- selection_menu = memnew( PopupMenu );
- add_child(selection_menu);
- selection_menu->set_custom_minimum_size(Vector2(100, 0));
- selection_menu->connect("id_pressed", this, "_selection_result_pressed");
- selection_menu->connect("popup_hide", this, "_selection_menu_hide");
-
- if (p_index==0) {
- view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER),true);
- viewport->set_as_audio_listener(true);
- }
-
-
- name=TTR("Top");
- _update_name();
-
- EditorSettings::get_singleton()->connect("settings_changed",this,"update_transform_gizmo_view");
-
-}
-
-
-
-
-
-
-
-SpatialEditor *SpatialEditor::singleton=NULL;
-
-SpatialEditorSelectedItem::~SpatialEditorSelectedItem() {
-
- if (sbox_instance.is_valid())
- VisualServer::get_singleton()->free(sbox_instance);
-}
-
-
-
-void SpatialEditor::select_gizmo_hilight_axis(int p_axis) {
-
-
- for(int i=0;i<3;i++) {
-
- move_gizmo[i]->surface_set_material(0,i==p_axis?gizmo_hl:gizmo_color[i]);
- rotate_gizmo[i]->surface_set_material(0,(i+3)==p_axis?gizmo_hl:gizmo_color[i]);
- }
-
-}
-
-void SpatialEditor::update_transform_gizmo() {
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
- Rect3 center;
- bool first=true;
-
- Basis gizmo_basis;
- bool local_gizmo_coords = transform_menu->get_popup()->is_item_checked( transform_menu->get_popup()->get_item_index(MENU_TRANSFORM_LOCAL_COORDS) );
-
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- Transform xf = se->sp->get_global_transform();
- if (first) {
- center.pos=xf.origin;
- first=false;
- if (local_gizmo_coords) {
- gizmo_basis=xf.basis;
- gizmo_basis.orthonormalize();
- }
- } else {
- center.expand_to(xf.origin);
- gizmo_basis=Basis();
- }
- //count++;
- }
-
- Vector3 pcenter = center.pos+center.size*0.5;
- gizmo.visible=!first;
- gizmo.transform.origin=pcenter;
- gizmo.transform.basis=gizmo_basis;
-
- for(int i=0;i<4;i++) {
- viewports[i]->update_transform_gizmo_view();
- }
-
-}
-
-
-Object *SpatialEditor::_get_editor_data(Object *p_what) {
-
- Spatial *sp = p_what->cast_to<Spatial>();
- if (!sp)
- return NULL;
-
-
- SpatialEditorSelectedItem *si = memnew( SpatialEditorSelectedItem );
-
- si->sp=sp;
- si->sbox_instance=VisualServer::get_singleton()->instance_create2(selection_box->get_rid(),sp->get_world()->get_scenario());
- VS::get_singleton()->instance_geometry_set_cast_shadows_setting(si->sbox_instance, VS::SHADOW_CASTING_SETTING_OFF);
-
- if (get_tree()->is_editor_hint())
- editor->call("edit_node",sp);
-
- return si;
-}
-
-void SpatialEditor::_generate_selection_box() {
-
- Rect3 aabb( Vector3(), Vector3(1,1,1) );
- aabb.grow_by( aabb.get_longest_axis_size()/20.0 );
-
- Ref<SurfaceTool> st = memnew( SurfaceTool );
-
- st->begin(Mesh::PRIMITIVE_LINES);
- for (int i=0;i<12;i++) {
-
- Vector3 a,b;
- aabb.get_edge(i,a,b);
-
- /*Vector<Vector3> points;
- Vector<Color> colors;
- points.push_back(a);
- points.push_back(b);*/
-
- st->add_color( Color(1.0,1.0,0.8,0.8) );
- st->add_vertex(a);
- st->add_color( Color(1.0,1.0,0.8,0.4) );
- st->add_vertex(a.linear_interpolate(b,0.2));
-
- st->add_color( Color(1.0,1.0,0.8,0.4) );
- st->add_vertex(a.linear_interpolate(b,0.8));
- st->add_color( Color(1.0,1.0,0.8,0.8) );
- st->add_vertex(b);
-
- }
-
- Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
- mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
- mat->set_albedo(Color(1,1,1));
- mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
- mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
- mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
- st->set_material(mat);
- selection_box = st->commit();
-}
-
-
-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) ))
- vc=1;
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS) ))
- vc=2;
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS) ))
- vc=3;
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) ))
- vc=4;
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) ))
- vc=5;
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) ))
- vc=6;
-
- d["viewport_mode"]=vc;
- Array vpdata;
- for(int i=0;i<4;i++) {
- vpdata.push_back( viewports[i]->get_state() );
- }
-
- d["viewports"]=vpdata;
-
- d["default_light"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT) );
- d["ambient_light_color"]=settings_ambient_color->get_pick_color();
-
- d["default_srgb"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB) );
- d["show_grid"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID) );
- d["show_origin"]=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN) );
- d["fov"]=get_fov();
- d["znear"]=get_znear();
- d["zfar"]=get_zfar();
- d["deflight_rot_x"]=settings_default_light_rot_x;
- d["deflight_rot_y"]=settings_default_light_rot_y;
-
- return d;
-}
-void SpatialEditor::set_state(const Dictionary& p_state) {
-
- Dictionary d = p_state;
-
- 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 );
- }
-
- if (d.has("translate_snap"))
- snap_translate->set_text(d["translate_snap"]);
-
- if (d.has("rotate_snap"))
- snap_rotate->set_text(d["rotate_snap"]);
-
- 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_value(float(d["zfar"]));
- if (d.has("znear"))
- settings_znear->set_value(float(d["znear"]));
- if (d.has("fov"))
- settings_fov->set_value(float(d["fov"]));
-
- if (d.has("default_light")) {
- bool use = d["default_light"];
-
- bool existing = light_instance.is_valid();
- if (use!=existing) {
- if (existing) {
- VisualServer::get_singleton()->free(light_instance);
- light_instance=RID();
- } else {
- light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario());
- VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform);
-
- }
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), light_instance.is_valid() );
- }
-
- }
- if (d.has("ambient_light_color")) {
- settings_ambient_color->set_pick_color(d["ambient_light_color"]);
- //viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,d["ambient_light_color"]);
- }
-
- if (d.has("default_srgb")) {
- bool use = d["default_srgb"];
-
- //viewport_environment->set_enable_fx(Environment::FX_SRGB,use);
- //view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_DEFAULT_SRGB), use );
- }
- if (d.has("show_grid")) {
- bool use = d["show_grid"];
-
- if (use!=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID))) {
- _menu_item_pressed(MENU_VIEW_GRID);
- }
- }
-
- if (d.has("show_origin")) {
- bool use = d["show_origin"];
-
- if (use!=view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN))) {
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), use );
- VisualServer::get_singleton()->instance_set_visible(origin_instance,use);
- }
- }
-
- if (d.has("deflight_rot_x"))
- settings_default_light_rot_x=d["deflight_rot_x"];
- if (d.has("deflight_rot_y"))
- settings_default_light_rot_y=d["deflight_rot_y"];
-
- _update_default_light_angle();
-
-
-}
-
-
-void SpatialEditor::edit(Spatial *p_spatial) {
-
- if (p_spatial!=selected) {
- if (selected) {
-
- Ref<SpatialEditorGizmo> seg = selected->get_gizmo();
- if (seg.is_valid()) {
- seg->set_selected(false);
- selected->update_gizmo();
- }
- }
-
- selected=p_spatial;
- over_gizmo_handle=-1;
-
- if (selected) {
-
- Ref<SpatialEditorGizmo> seg = selected->get_gizmo();
- if (seg.is_valid()) {
- seg->set_selected(true);
- selected->update_gizmo();
- }
- }
- }
-
- /*
- if (p_spatial) {
- _validate_selection();
- if (selected.has(p_spatial->get_instance_ID()) && selected.size()==1)
- return;
- _select(p_spatial->get_instance_ID(),false,true);
-
- // should become the selection
- }
- */
-}
-
-void SpatialEditor::_xform_dialog_action() {
-
- Transform t;
- //translation
- Vector3 scale;
- Vector3 rotate;
- Vector3 translate;
-
- for(int i=0;i<3;i++) {
- translate[i]=xform_translate[i]->get_text().to_double();
- rotate[i]=Math::deg2rad(xform_rotate[i]->get_text().to_double());
- scale[i]=xform_scale[i]->get_text().to_double();
- }
-
- t.basis.scale(scale);
- t.basis.rotate(rotate);
- t.origin=translate;
-
-
- undo_redo->create_action(TTR("XForm Dialog"));
-
- List<Node*> &selection = editor_selection->get_selected_node_list();
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Spatial *sp = E->get()->cast_to<Spatial>();
- if (!sp)
- continue;
-
- SpatialEditorSelectedItem *se=editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
- continue;
-
- bool post = xform_type->get_selected()>0;
-
- Transform tr = sp->get_global_transform();
- if (post)
- tr = tr * t;
- else {
-
- tr.basis = t.basis * tr.basis;
- tr.origin+=t.origin;
- }
-
- undo_redo->add_do_method(sp,"set_global_transform",tr);
- undo_redo->add_undo_method(sp,"set_global_transform",sp->get_global_transform());
- }
- undo_redo->commit_action();
-}
-
-void SpatialEditor::_menu_item_pressed(int p_option) {
-
- switch(p_option) {
-
- case MENU_TOOL_SELECT:
- case MENU_TOOL_MOVE:
- case MENU_TOOL_ROTATE:
- case MENU_TOOL_SCALE:
- case MENU_TOOL_LIST_SELECT: {
-
- 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.","List Selection Mode."};
- //set_message(_mode[p_option],3);
- update_transform_gizmo();
-
- } break;
- case MENU_TRANSFORM_USE_SNAP: {
-
- bool is_checked = transform_menu->get_popup()->is_item_checked( transform_menu->get_popup()->get_item_index(p_option) );
- snap_enabled=!is_checked;
- transform_menu->get_popup()->set_item_checked( transform_menu->get_popup()->get_item_index(p_option), snap_enabled );
- } break;
- case MENU_TRANSFORM_CONFIGURE_SNAP: {
-
- snap_dialog->popup_centered(Size2(200,180));
- } break;
- case MENU_TRANSFORM_LOCAL_COORDS: {
-
- bool is_checked = transform_menu->get_popup()->is_item_checked( transform_menu->get_popup()->get_item_index(p_option) );
- transform_menu->get_popup()->set_item_checked( transform_menu->get_popup()->get_item_index(p_option), !is_checked );
- update_transform_gizmo();
-
- } break;
- case MENU_TRANSFORM_DIALOG: {
-
- for(int i=0;i<3;i++) {
-
-
- xform_translate[i]->set_text("0");
- xform_rotate[i]->set_text("0");
- xform_scale[i]->set_text("1");
-
- }
-
- xform_dialog->popup_centered(Size2(200,200));
-
- } break;
- case MENU_VIEW_USE_DEFAULT_LIGHT: {
-
- bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
-
- if (is_checked) {
- VisualServer::get_singleton()->free(light_instance);
- light_instance=RID();
- } else {
- light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario());
- VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform);
-
- _update_default_light_angle();
- }
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), light_instance.is_valid() );
-
- } break;
- case MENU_VIEW_USE_DEFAULT_SRGB: {
-
- bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
-
- if (is_checked) {
- //viewport_environment->set_enable_fx(Environment::FX_SRGB,false);
- } else {
- //viewport_environment->set_enable_fx(Environment::FX_SRGB,true);
- }
-
- is_checked = ! is_checked;
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), is_checked );
-
-
- } break;
- case MENU_VIEW_USE_1_VIEWPORT: {
-
- for(int i=1;i<4;i++) {
-
- viewports[i]->hide();
- }
-
- viewports[0]->set_area_as_parent_rect();
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
-
- } break;
- case MENU_VIEW_USE_2_VIEWPORTS: {
-
- for(int i=1;i<4;i++) {
-
- if (i==1 || i==3)
- viewports[i]->hide();
- else
- viewports[i]->show();
-
-
- }
- viewports[0]->set_area_as_parent_rect();
- //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
- viewports[2]->set_area_as_parent_rect();
- //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
-
- } break;
- case MENU_VIEW_USE_2_VIEWPORTS_ALT: {
-
- for(int i=1;i<4;i++) {
-
- if (i==1 || i==3)
- viewports[i]->hide();
- else
- viewports[i]->show();
-
-
- }
- viewports[0]->set_area_as_parent_rect();
- //viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
- viewports[2]->set_area_as_parent_rect();
- //viewports[2]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
-
- } break;
- case MENU_VIEW_USE_3_VIEWPORTS: {
-
- for(int i=1;i<4;i++) {
-
- if (i==1)
- viewports[i]->hide();
- else
- viewports[i]->show();
- }
- viewports[0]->set_area_as_parent_rect();
- //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
- viewports[2]->set_area_as_parent_rect();
- //viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
- //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
- viewports[3]->set_area_as_parent_rect();
- //viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
- //viewports[3]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
-
- } break;
- case MENU_VIEW_USE_3_VIEWPORTS_ALT: {
-
- for(int i=1;i<4;i++) {
-
- if (i==1)
- viewports[i]->hide();
- else
- viewports[i]->show();
- }
- viewports[0]->set_area_as_parent_rect();
- //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
- //viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
- viewports[2]->set_area_as_parent_rect();
- //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
- //viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
- viewports[3]->set_area_as_parent_rect();
- //viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), true );
-
- } break;
- case MENU_VIEW_USE_4_VIEWPORTS: {
-
- for(int i=1;i<4;i++) {
-
- viewports[i]->show();
- }
- viewports[0]->set_area_as_parent_rect();
- //viewports[0]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
- //viewports[0]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
- viewports[1]->set_area_as_parent_rect();
- //viewports[1]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
- //viewports[1]->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_RATIO,0.5);
- viewports[2]->set_area_as_parent_rect();
- //viewports[2]->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
- //viewports[2]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
- viewports[3]->set_area_as_parent_rect();
- //viewports[3]->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
- //viewports[3]->set_anchor_and_margin(MARGIN_TOP,ANCHOR_RATIO,0.5);
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), false );
-
- } break;
- case MENU_VIEW_DISPLAY_NORMAL: {
-
-
- VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_DISABLED );
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false );
-
- } break;
- case MENU_VIEW_DISPLAY_WIREFRAME: {
-
- VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_WIREFRAME );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false );
-
- } break;
- case MENU_VIEW_DISPLAY_OVERDRAW: {
-
- VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_OVERDRAW );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), true );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), false );
-
- } break;
- case MENU_VIEW_DISPLAY_SHADELESS: {
-
- VisualServer::get_singleton()->scenario_set_debug( get_tree()->get_root()->get_world()->get_scenario(), VisualServer::SCENARIO_DEBUG_SHADELESS );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_NORMAL), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_OVERDRAW), false );
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_SHADELESS), true );
-
- } break;
- case MENU_VIEW_ORIGIN: {
-
- bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
-
- is_checked=!is_checked;
- VisualServer::get_singleton()->instance_set_visible(origin_instance,is_checked);
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), is_checked);
- } break;
- case MENU_VIEW_GRID: {
-
- bool is_checked = view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(p_option) );
-
- grid_enabled=!is_checked;
-
- for(int i=0;i<3;++i) {
- if (grid_enable[i]) {
- VisualServer::get_singleton()->instance_set_visible(grid_instance[i],grid_enabled);
- grid_visible[i]=grid_enabled;
- }
- }
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(p_option), grid_enabled );
-
-
- } break;
- case MENU_VIEW_CAMERA_SETTINGS: {
-
- settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size()+Size2(50,50));
- } break;
-
- }
-}
-
-
-void SpatialEditor::_init_indicators() {
-
- //make sure that the camera indicator is not selectable
- light=VisualServer::get_singleton()->light_create( VisualServer::LIGHT_DIRECTIONAL );
- //VisualServer::get_singleton()->light_set_shadow( light, true );
- light_instance=VisualServer::get_singleton()->instance_create2(light,get_tree()->get_root()->get_world()->get_scenario());
-
-
-
- light_transform.rotate(Vector3(1,0,0),-Math_PI/5.0);
- VisualServer::get_singleton()->instance_set_transform(light_instance,light_transform);
-
-
- //RID mat = VisualServer::get_singleton()->fixed_material_create();
- ///VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_ALPHA,true);
- //VisualServer::get_singleton()->fixed_material_set_flag(mat, VisualServer::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);
-
-
- {
-
- indicator_mat.instance();
- indicator_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
- //indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true);
- indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
- indicator_mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
-
- indicator_mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
-
- PoolVector<Color> grid_colors[3];
- PoolVector<Vector3> grid_points[3];
- Vector<Color> origin_colors;
- Vector<Vector3> origin_points;
-
- Color grid_color = EditorSettings::get_singleton()->get("editors/3d/grid_color");
-
- for(int i=0;i<3;i++) {
- Vector3 axis;
- axis[i]=1;
- Vector3 axis_n1;
- axis_n1[(i+1)%3]=1;
- Vector3 axis_n2;
- axis_n2[(i+2)%3]=1;
-
- origin_colors.push_back(Color(axis.x,axis.y,axis.z));
- origin_colors.push_back(Color(axis.x,axis.y,axis.z));
- origin_points.push_back(axis*4096);
- origin_points.push_back(axis*-4096);
-#define ORIGIN_GRID_SIZE 25
-
- for(int j=-ORIGIN_GRID_SIZE;j<=ORIGIN_GRID_SIZE;j++) {
-
-
- grid_colors[i].push_back(grid_color);
- grid_colors[i].push_back(grid_color);
- grid_colors[i].push_back(grid_color);
- grid_colors[i].push_back(grid_color);
- grid_points[i].push_back(axis_n1*ORIGIN_GRID_SIZE+axis_n2*j);
- grid_points[i].push_back(-axis_n1*ORIGIN_GRID_SIZE+axis_n2*j);
- grid_points[i].push_back(axis_n2*ORIGIN_GRID_SIZE+axis_n1*j);
- grid_points[i].push_back(-axis_n2*ORIGIN_GRID_SIZE+axis_n1*j);
-
- }
-
- grid[i] = VisualServer::get_singleton()->mesh_create();
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[VisualServer::ARRAY_VERTEX]=grid_points[i];
- d[VisualServer::ARRAY_COLOR]=grid_colors[i];
- VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i],VisualServer::PRIMITIVE_LINES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(grid[i],0,indicator_mat->get_rid());
- grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i],get_tree()->get_root()->get_world()->get_scenario());
-
- grid_visible[i]=false;
- grid_enable[i]=false;
- VisualServer::get_singleton()->instance_set_visible(grid_instance[i],false);
- VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
- VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << SpatialEditorViewport::GIZMO_GRID_LAYER);
-
-
- }
-
- origin = VisualServer::get_singleton()->mesh_create();
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[VisualServer::ARRAY_VERTEX]=origin_points;
- d[VisualServer::ARRAY_COLOR]=origin_colors;
-
- VisualServer::get_singleton()->mesh_add_surface_from_arrays(origin,VisualServer::PRIMITIVE_LINES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(origin,0,indicator_mat->get_rid());
-
-
- //origin = VisualServer::get_singleton()->poly_create();
- //VisualServer::get_singleton()->poly_add_primitive(origin,origin_points,Vector<Vector3>(),origin_colors,Vector<Vector3>());
- //VisualServer::get_singleton()->poly_set_material(origin,indicator_mat,true);
- origin_instance = VisualServer::get_singleton()->instance_create2(origin,get_tree()->get_root()->get_world()->get_scenario());
- VS::get_singleton()->instance_set_layer_mask(origin_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER);
-
- VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF);
-
-
-
- VisualServer::get_singleton()->instance_set_visible(grid_instance[1],true);
- grid_enable[1]=true;
- grid_visible[1]=true;
- grid_enabled=true;
- last_grid_snap=1;
-
- }
-
- {
- cursor_mesh = VisualServer::get_singleton()->mesh_create();
- PoolVector<Vector3> cursor_points;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs));
- cursor_points.push_back(Vector3(0,0,-cs));
- cursor_material.instance();
- cursor_material->set_albedo(Color(0,1,1));
- cursor_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
-
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[VS::ARRAY_VERTEX]=cursor_points;
- VisualServer::get_singleton()->mesh_add_surface_from_arrays(cursor_mesh,VS::PRIMITIVE_LINES,d);
- VisualServer::get_singleton()->mesh_surface_set_material(cursor_mesh,0,cursor_material->get_rid());
-
- cursor_instance = VisualServer::get_singleton()->instance_create2(cursor_mesh,get_tree()->get_root()->get_world()->get_scenario());
- VS::get_singleton()->instance_set_layer_mask(cursor_instance,1<<SpatialEditorViewport::GIZMO_GRID_LAYER);
-
- VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(cursor_instance, VS::SHADOW_CASTING_SETTING_OFF);
-
-
- }
-
-
- {
-
- //move gizmo
-
-
- float gizmo_alph = EditorSettings::get_singleton()->get("editors/3d/manipulator_gizmo_opacity");
-
- gizmo_hl = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ) );
- gizmo_hl->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- gizmo_hl->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true);
- gizmo_hl->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- gizmo_hl->set_albedo(Color(1,1,1,gizmo_alph+0.2f));
-
- for(int i=0;i<3;i++) {
-
- move_gizmo[i]=Ref<Mesh>( memnew( Mesh ) );
- rotate_gizmo[i]=Ref<Mesh>( memnew( Mesh ) );
-
-
- Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
- mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true);
- mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- Color col;
- col[i]=1.0;
- col.a= gizmo_alph;
- mat->set_albedo(col);
- gizmo_color[i]=mat;
-
-
-
-
- Vector3 ivec;
- ivec[i]=1;
- Vector3 nivec;
- nivec[(i+1)%3]=1;
- nivec[(i+2)%3]=1;
- Vector3 ivec2;
- ivec2[(i+1)%3]=1;
- Vector3 ivec3;
- ivec3[(i+2)%3]=1;
-
-
- {
-
- Ref<SurfaceTool> surftool = memnew( SurfaceTool );
- surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
-
- //translate
-
- const int arrow_points=5;
- Vector3 arrow[5]={
- nivec*0.0+ivec*0.0,
- nivec*0.01+ivec*0.0,
- nivec*0.01+ivec*1.0,
- nivec*0.1+ivec*1.0,
- nivec*0.0+ivec*(1+GIZMO_ARROW_SIZE),
- };
-
- int arrow_sides=6;
-
-
- for(int k = 0; k < 7 ; k++) {
-
-
- Basis ma(ivec,Math_PI*2*float(k)/arrow_sides);
- Basis mb(ivec,Math_PI*2*float(k+1)/arrow_sides);
-
-
- for(int j=0;j<arrow_points-1;j++) {
-
- Vector3 points[4]={
- ma.xform(arrow[j]),
- mb.xform(arrow[j]),
- mb.xform(arrow[j+1]),
- ma.xform(arrow[j+1]),
- };
- surftool->add_vertex(points[0]);
- surftool->add_vertex(points[1]);
- surftool->add_vertex(points[2]);
-
- surftool->add_vertex(points[0]);
- surftool->add_vertex(points[2]);
- surftool->add_vertex(points[3]);
- }
-
- }
-
- surftool->set_material(mat);
- surftool->commit(move_gizmo[i]);
- }
-
- {
-
-
- Ref<SurfaceTool> surftool = memnew( SurfaceTool );
- surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
-
- Vector3 circle[5]={
- ivec*0.02+ivec2*0.02+ivec2*1.0,
- ivec*-0.02+ivec2*0.02+ivec2*1.0,
- ivec*-0.02+ivec2*-0.02+ivec2*1.0,
- ivec*0.02+ivec2*-0.02+ivec2*1.0,
- ivec*0.02+ivec2*0.02+ivec2*1.0,
- };
-
-
- for(int k = 0; k < 33 ; k++) {
-
-
- Basis ma(ivec,Math_PI*2*float(k)/32);
- Basis mb(ivec,Math_PI*2*float(k+1)/32);
-
-
- for(int j=0;j<4;j++) {
-
- Vector3 points[4]={
- ma.xform(circle[j]),
- mb.xform(circle[j]),
- mb.xform(circle[j+1]),
- ma.xform(circle[j+1]),
- };
- surftool->add_vertex(points[0]);
- surftool->add_vertex(points[1]);
- surftool->add_vertex(points[2]);
-
- surftool->add_vertex(points[0]);
- surftool->add_vertex(points[2]);
- surftool->add_vertex(points[3]);
- }
-
- }
-
- surftool->set_material(mat);
- surftool->commit(rotate_gizmo[i]);
-
- }
-
-
- }
- }
-
- /*for(int i=0;i<4;i++) {
-
- viewports[i]->init_gizmo_instance(i);
- }*/
-
- _generate_selection_box();
-
-
- //get_scene()->get_root_node()->cast_to<EditorNode>()->get_scene_root()->add_child(camera);
-
- //current_camera=camera;
-
-}
-
-void SpatialEditor::_finish_indicators() {
-
- VisualServer::get_singleton()->free(origin_instance);
- VisualServer::get_singleton()->free(origin);
- for(int i=0;i<3;i++) {
- VisualServer::get_singleton()->free(grid_instance[i]);
- VisualServer::get_singleton()->free(grid[i]);
- }
- VisualServer::get_singleton()->free(light_instance);
- VisualServer::get_singleton()->free(light);
- //VisualServer::get_singleton()->free(poly);
- //VisualServer::get_singleton()->free(indicators_instance);
- //VisualServer::get_singleton()->free(indicators);
-
- VisualServer::get_singleton()->free(cursor_instance);
- VisualServer::get_singleton()->free(cursor_mesh);
-}
-
-void SpatialEditor::_instance_scene() {
-#if 0
- EditorNode *en = get_scene()->get_root_node()->cast_to<EditorNode>();
- ERR_FAIL_COND(!en);
- String path = en->get_filesystem_dock()->get_selected_path();
- if (path=="") {
- set_message(TTR("No scene selected to instance!"));
- return;
- }
-
- undo_redo->create_action(TTR("Instance at Cursor"));
-
- Node* scene = en->request_instance_scene(path);
-
- if (!scene) {
- set_message(TTR("Could not instance scene!"));
- undo_redo->commit_action(); //bleh
- return;
- }
-
- Spatial *s = scene->cast_to<Spatial>();
- if (s) {
-
- undo_redo->add_do_method(s,"set_global_transform",Transform(Matrix3(),cursor.cursor_pos));
- }
-
- undo_redo->commit_action();
-#endif
-}
-
-void SpatialEditor::_unhandled_key_input(InputEvent p_event) {
-
- if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
- return;
-
-#if 0
-//i don't remember this being used, why was it here?
- {
-
- EditorNode *en = editor;
- EditorPluginList *over_plugin_list = en->get_editor_plugins_over();
-
- if (!over_plugin_list->empty() && over_plugin_list->forward_gui_input(p_event)) {
-
- return; //ate the over input event
- }
-
- }
-#endif
-
- switch(p_event.type) {
-
- case InputEvent::KEY: {
-
-
- const InputEventKey &k=p_event.key;
-
- if (!k.pressed)
- break;
-
- switch(k.scancode) {
-
- case KEY_Q: _menu_item_pressed(MENU_TOOL_SELECT); break;
- case KEY_W: _menu_item_pressed(MENU_TOOL_MOVE); break;
- case KEY_E: _menu_item_pressed(MENU_TOOL_ROTATE); break;
- case KEY_R: _menu_item_pressed(MENU_TOOL_SCALE); break;
-
- case KEY_Z: {
- if (k.mod.shift || k.mod.control || k.mod.command)
- break;
-
- if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME))) {
- _menu_item_pressed(MENU_VIEW_DISPLAY_NORMAL);
- } else {
- _menu_item_pressed(MENU_VIEW_DISPLAY_WIREFRAME);
- }
- } break;
-
-#if 0
-#endif
- }
-
- } break;
- }
-}
-void SpatialEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_READY) {
-
- tool_button[SpatialEditor::TOOL_MODE_SELECT]->set_icon( get_icon("ToolSelect","EditorIcons") );
- 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();
-
-
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT),get_icon("Panels1","EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS),get_icon("Panels2","EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT),get_icon("Panels2Alt","EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS),get_icon("Panels3","EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT),get_icon("Panels3Alt","EditorIcons"));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS),get_icon("Panels4","EditorIcons"));
-
- _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
-
- get_tree()->connect("node_removed",this,"_node_removed");
- VS::get_singleton()->scenario_set_fallback_environment(get_viewport()->find_world()->get_scenario(),viewport_environment->get_rid());
-
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- gizmos = memnew( SpatialEditorGizmos );
- _init_indicators();
- _update_default_light_angle();
- }
-
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
- _finish_indicators();
- memdelete( gizmos );
-
- }
-}
-
-void SpatialEditor::add_control_to_menu_panel(Control *p_control) {
-
-
- hbc_menu->add_child(p_control);
-}
-
-void SpatialEditor::set_can_preview(Camera* p_preview) {
-
- for(int i=0;i<4;i++) {
- viewports[i]->set_can_preview(p_preview);
- }
-}
-
-VSplitContainer *SpatialEditor::get_shader_split() {
-
- return shader_split;
-}
-
-HSplitContainer *SpatialEditor::get_palette_split() {
-
- return palette_split;
-}
-
-
-void SpatialEditor::_request_gizmo(Object* p_obj) {
-
- Spatial *sp=p_obj->cast_to<Spatial>();
- if (!sp)
- return;
- if (editor->get_edited_scene() && (sp==editor->get_edited_scene() || sp->get_owner()==editor->get_edited_scene() || editor->get_edited_scene()->is_editable_instance(sp->get_owner()))) {
-
- Ref<SpatialEditorGizmo> seg;
-
- for(int i=0;i<EditorNode::get_singleton()->get_editor_data().get_editor_plugin_count();i++) {
-
- seg = EditorNode::get_singleton()->get_editor_data().get_editor_plugin(i)->create_spatial_gizmo(sp);
- if (seg.is_valid())
- break;
- }
-
- if (!seg.is_valid()) {
- seg = gizmos->get_gizmo(sp);
- }
-
- if (seg.is_valid()) {
- sp->set_gizmo(seg);
- }
-
-
- if (seg.is_valid() && sp==selected) {
- seg->set_selected(true);
- selected->update_gizmo();
- }
-
- }
-}
-
-void SpatialEditor::_toggle_maximize_view(Object* p_viewport) {
- if (!p_viewport) return;
- SpatialEditorViewport *current_viewport = p_viewport->cast_to<SpatialEditorViewport>();
- if (!current_viewport) return;
-
- int index=-1;
- bool maximized = false;
- for(int i=0;i<4;i++) {
- if (viewports[i]==current_viewport) {
- index=i;
- if ( current_viewport->get_global_rect() == viewport_base->get_global_rect() )
- maximized=true;
- break;
- }
- }
- if (index==-1) return;
-
- if (!maximized) {
-
- for(int i=0;i<4;i++) {
- if (i==index)
- viewports[i]->set_area_as_parent_rect();
- else
- viewports[i]->hide();
- }
- } else {
-
- for(int i=0;i<4;i++)
- viewports[i]->show();
-
- if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT) ))
- _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS) ))
- _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS);
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT) ))
- _menu_item_pressed(MENU_VIEW_USE_2_VIEWPORTS_ALT);
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS) ))
- _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS);
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT) ))
- _menu_item_pressed(MENU_VIEW_USE_3_VIEWPORTS_ALT);
- else if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS) ))
- _menu_item_pressed(MENU_VIEW_USE_4_VIEWPORTS);
- }
-
-}
-
-
-void SpatialEditor::_node_removed(Node* p_node) {
-
- if (p_node==selected)
- selected=NULL;
-}
-
-void SpatialEditor::_bind_methods() {
-
- //ClassDB::bind_method("_gui_input",&SpatialEditor::_gui_input);
- ClassDB::bind_method("_unhandled_key_input",&SpatialEditor::_unhandled_key_input);
- ClassDB::bind_method("_node_removed",&SpatialEditor::_node_removed);
- ClassDB::bind_method("_menu_item_pressed",&SpatialEditor::_menu_item_pressed);
- ClassDB::bind_method("_xform_dialog_action",&SpatialEditor::_xform_dialog_action);
- ClassDB::bind_method("_instance_scene",&SpatialEditor::_instance_scene);
- ClassDB::bind_method("_get_editor_data",&SpatialEditor::_get_editor_data);
- ClassDB::bind_method("_request_gizmo",&SpatialEditor::_request_gizmo);
- ClassDB::bind_method("_default_light_angle_input",&SpatialEditor::_default_light_angle_input);
- ClassDB::bind_method("_update_ambient_light_color",&SpatialEditor::_update_ambient_light_color);
- ClassDB::bind_method("_toggle_maximize_view",&SpatialEditor::_toggle_maximize_view);
-
- ADD_SIGNAL( MethodInfo("transform_key_request") );
-
-
-}
-
-void SpatialEditor::clear() {
-
- settings_fov->set_value(EDITOR_DEF("editors/3d/default_fov",60.0));
- settings_znear->set_value(EDITOR_DEF("editors/3d/default_z_near",0.1));
- settings_zfar->set_value(EDITOR_DEF("editors/3d/default_z_far",1500.0));
-
- for(int i=0;i<4;i++) {
- viewports[i]->reset();
- }
-
- _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
- _menu_item_pressed(MENU_VIEW_DISPLAY_NORMAL);
-
-
- VisualServer::get_singleton()->instance_set_visible(origin_instance,true);
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), true);
- for(int i=0;i<3;++i) {
- if (grid_enable[i]) {
- VisualServer::get_singleton()->instance_set_visible(grid_instance[i],true);
- grid_visible[i]=true;
- }
- }
-
- for(int i=0;i<4;i++) {
-
- viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER),i==0);
- viewports[i]->viewport->set_as_audio_listener(i==0);
- }
-
- view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true );
-
- settings_default_light_rot_x=Math_PI*0.3;
- settings_default_light_rot_y=Math_PI*0.2;
-
- //viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,Color(0.15,0.15,0.15));
- settings_ambient_color->set_pick_color(Color(0.15,0.15,0.15));
- if (!light_instance.is_valid())
- _menu_item_pressed(MENU_VIEW_USE_DEFAULT_LIGHT);
-
- _update_default_light_angle();
-
-
-}
-
-
-void SpatialEditor::_update_ambient_light_color(const Color& p_color) {
-
- //viewport_environment->fx_set_param(Environment::FX_PARAM_AMBIENT_LIGHT_COLOR,settings_ambient_color->get_color());
-
-}
-
-void SpatialEditor::_update_default_light_angle() {
-
- Transform t;
- t.basis.rotate(Vector3(1,0,0),-settings_default_light_rot_x);
- t.basis.rotate(Vector3(0,1,0),-settings_default_light_rot_y);
- settings_dlight->set_transform(t);
- if (light_instance.is_valid()) {
- VS::get_singleton()->instance_set_transform(light_instance,t);
- }
-
-}
-
-void SpatialEditor::_default_light_angle_input(const InputEvent& p_event) {
-
-
- if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_motion.button_mask&(0x1|0x2|0x4)) {
-
- settings_default_light_rot_y = Math::fposmod(settings_default_light_rot_y - p_event.mouse_motion.relative_x*0.01,Math_PI*2.0);
- settings_default_light_rot_x = Math::fposmod(settings_default_light_rot_x - p_event.mouse_motion.relative_y*0.01,Math_PI*2.0);
- _update_default_light_angle();
- }
-
-}
-
-
-SpatialEditor::SpatialEditor(EditorNode *p_editor) {
-
- gizmo.visible=true;
- gizmo.scale=1.0;
-
- viewport_environment = Ref<Environment>( memnew( Environment ) );
- undo_redo=p_editor->get_undo_redo();
- VBoxContainer *vbc = this;
-
- custom_camera=NULL;
- singleton=this;
- editor=p_editor;
- editor_selection=editor->get_editor_selection();
- editor_selection->add_editor_plugin(this);
-
- snap_enabled=false;
- tool_mode = TOOL_MODE_SELECT;
-
- //set_focus_mode(FOCUS_ALL);
-
- hbc_menu = memnew( HBoxContainer );
- vbc->add_child(hbc_menu);
-
-
- Vector<Variant> button_binds;
- button_binds.resize(1);
-
- tool_button[TOOL_MODE_SELECT] = memnew( ToolButton );
- hbc_menu->add_child( tool_button[TOOL_MODE_SELECT] );
- tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true);
- tool_button[TOOL_MODE_SELECT]->set_flat(true);
- 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)\n"+keycode_get_string(KEY_MASK_CMD)+"Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection");
-
-
- tool_button[TOOL_MODE_MOVE] = memnew( ToolButton );
-
- hbc_menu->add_child( tool_button[TOOL_MODE_MOVE] );
- tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true);
- tool_button[TOOL_MODE_MOVE]->set_flat(true);
- button_binds[0]=MENU_TOOL_MOVE;
- tool_button[TOOL_MODE_MOVE]->connect("pressed", this,"_menu_item_pressed",button_binds);
- tool_button[TOOL_MODE_MOVE]->set_tooltip(TTR("Move Mode (W)"));
-
- tool_button[TOOL_MODE_ROTATE] = memnew( ToolButton );
- hbc_menu->add_child( tool_button[TOOL_MODE_ROTATE] );
- tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true);
- tool_button[TOOL_MODE_ROTATE]->set_flat(true);
- button_binds[0]=MENU_TOOL_ROTATE;
- tool_button[TOOL_MODE_ROTATE]->connect("pressed", this,"_menu_item_pressed",button_binds);
- tool_button[TOOL_MODE_ROTATE]->set_tooltip(TTR("Rotate Mode (E)"));
-
- tool_button[TOOL_MODE_SCALE] = memnew( ToolButton );
- hbc_menu->add_child( tool_button[TOOL_MODE_SCALE] );
- tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true);
- tool_button[TOOL_MODE_SCALE]->set_flat(true);
- button_binds[0]=MENU_TOOL_SCALE;
- tool_button[TOOL_MODE_SCALE]->connect("pressed", this,"_menu_item_pressed",button_binds);
- tool_button[TOOL_MODE_SCALE]->set_tooltip(TTR("Scale Mode (R)"));
-
- instance_button = memnew( Button );
- 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(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
-
- vs = memnew( VSeparator );
- hbc_menu->add_child(vs);
-
-
- ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT+KEY_KP_7);
- ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), KEY_KP_7);
- ED_SHORTCUT("spatial_editor/rear_view", TTR("Rear View"), KEY_MASK_ALT+KEY_KP_1);
- ED_SHORTCUT("spatial_editor/front_view", TTR("Front View"), KEY_KP_1);
- ED_SHORTCUT("spatial_editor/left_view", TTR("Left View"), KEY_MASK_ALT+KEY_KP_3);
- ED_SHORTCUT("spatial_editor/right_view", TTR("Right View"), KEY_KP_3);
- ED_SHORTCUT("spatial_editor/switch_perspective_orthogonal", TTR("Switch Perspective/Orthogonal view"), KEY_KP_5);
- ED_SHORTCUT("spatial_editor/snap", TTR("Snap"), KEY_S);
- ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), KEY_K);
- ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), KEY_O);
- ED_SHORTCUT("spatial_editor/focus_selection", TTR("Focus Selection"), KEY_F);
- ED_SHORTCUT("spatial_editor/align_selection_with_view", TTR("Align Selection With View"), KEY_MASK_ALT+KEY_MASK_CMD+KEY_F);
-
-
- PopupMenu *p;
-
- transform_menu = memnew( MenuButton );
- transform_menu->set_text(TTR("Transform"));
- hbc_menu->add_child( transform_menu );
-
- p = transform_menu->get_popup();
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_snap", TTR("Use Snap")), MENU_TRANSFORM_USE_SNAP);
- p->add_shortcut(ED_SHORTCUT("spatial_editor/configure_snap", TTR("Configure Snap..")), MENU_TRANSFORM_CONFIGURE_SNAP);
- p->add_separator();
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Local Coords")), MENU_TRANSFORM_LOCAL_COORDS);
- //p->set_item_checked(p->get_item_count()-1,true);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("spatial_editor/transform_dialog", TTR("Transform Dialog..")), MENU_TRANSFORM_DIALOG);
-
- p->connect("id_pressed", this,"_menu_item_pressed");
-
- view_menu = memnew( MenuButton );
- view_menu->set_text(TTR("View"));
- view_menu->set_pos( Point2( 212,0) );
- hbc_menu->add_child( view_menu );
-
- p = view_menu->get_popup();
-
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_default_light", TTR("Use Default Light")), MENU_VIEW_USE_DEFAULT_LIGHT);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/use_default_srgb", TTR("Use Default sRGB")), MENU_VIEW_USE_DEFAULT_SRGB);
- p->add_separator();
-
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD+KEY_1), MENU_VIEW_USE_1_VIEWPORT);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD+KEY_2), MENU_VIEW_USE_2_VIEWPORTS);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT+KEY_MASK_CMD+KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports", TTR("3 Viewports"),KEY_MASK_CMD+KEY_3), MENU_VIEW_USE_3_VIEWPORTS);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/3_viewports_alt", TTR("3 Viewports (Alt)"), KEY_MASK_ALT+KEY_MASK_CMD+KEY_3), MENU_VIEW_USE_3_VIEWPORTS_ALT);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/4_viewports", TTR("4 Viewports"), KEY_MASK_CMD+KEY_4), MENU_VIEW_USE_4_VIEWPORTS);
- p->add_separator();
-
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_normal", TTR("Display Normal")), MENU_VIEW_DISPLAY_NORMAL);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_wireframe", TTR("Display Wireframe")), MENU_VIEW_DISPLAY_WIREFRAME);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_overdraw", TTR("Display Overdraw")), MENU_VIEW_DISPLAY_OVERDRAW);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/display_shadeless", TTR("Display Shadeless")), MENU_VIEW_DISPLAY_SHADELESS);
- p->add_separator();
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_origin", TTR("View Origin")), MENU_VIEW_ORIGIN);
- p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid")), MENU_VIEW_GRID);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings")), MENU_VIEW_CAMERA_SETTINGS);
-
-
- p->set_item_checked( p->get_item_index(MENU_VIEW_USE_DEFAULT_LIGHT), true );
- p->set_item_checked( p->get_item_index(MENU_VIEW_DISPLAY_NORMAL), true );
- p->set_item_checked( p->get_item_index(MENU_VIEW_ORIGIN), true );
- p->set_item_checked( p->get_item_index(MENU_VIEW_GRID), true );
-
-
- p->connect("id_pressed", this,"_menu_item_pressed");
-
-
- /* REST OF MENU */
-
- palette_split = memnew( HSplitContainer);
- palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
- vbc->add_child(palette_split);
-
- shader_split = memnew( VSplitContainer );
- shader_split->set_h_size_flags(SIZE_EXPAND_FILL);
- palette_split->add_child(shader_split);
- viewport_base = memnew( Control );
- shader_split->add_child(viewport_base);
- viewport_base->set_v_size_flags(SIZE_EXPAND_FILL);
- for(int i=0;i<4;i++) {
-
- viewports[i] = memnew( SpatialEditorViewport(this,editor,i) );
- viewports[i]->connect("toggle_maximize_view",this,"_toggle_maximize_view");
- viewport_base->add_child(viewports[i]);
- }
- //vbc->add_child(viewport_base);
-
-
-
-
- /* SNAP DIALOG */
-
- snap_dialog = memnew( ConfirmationDialog );
- snap_dialog->set_title(TTR("Snap Settings"));
- add_child(snap_dialog);
-
- VBoxContainer *snap_dialog_vbc = memnew( VBoxContainer );
- snap_dialog->add_child(snap_dialog_vbc);
- //snap_dialog->set_child_rect(snap_dialog_vbc);
-
- snap_translate = memnew( LineEdit );
- snap_translate->set_text("1");
- snap_dialog_vbc->add_margin_child(TTR("Translate Snap:"),snap_translate);
-
- snap_rotate = memnew( LineEdit );
- snap_rotate->set_text("5");
- snap_dialog_vbc->add_margin_child(TTR("Rotate Snap (deg.):"),snap_rotate);
-
- snap_scale = memnew( LineEdit );
- snap_scale->set_text("5");
- snap_dialog_vbc->add_margin_child(TTR("Scale Snap (%):"),snap_scale);
-
- /* SETTINGS DIALOG */
-
- settings_dialog = memnew( ConfirmationDialog );
- settings_dialog->set_title(TTR("Viewport Settings"));
- add_child(settings_dialog);
- settings_vbc = memnew( VBoxContainer );
- settings_vbc->set_custom_minimum_size(Size2(200,0));
- settings_dialog->add_child(settings_vbc);
- //settings_dialog->set_child_rect(settings_vbc);
-
-
-
- settings_light_base = memnew( ViewportContainer );
- settings_light_base->set_custom_minimum_size(Size2(128,128));
- settings_light_base->connect("gui_input",this,"_default_light_angle_input");
- settings_vbc->add_margin_child(TTR("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);
-
- settings_dlight = memnew( DirectionalLight );
- settings_light_vp->add_child(settings_dlight);
- settings_sphere = memnew( ImmediateGeometry );
- settings_sphere->begin(Mesh::PRIMITIVE_TRIANGLES,Ref<Texture>());
- settings_sphere->set_color(Color(1,1,1));
- settings_sphere->add_sphere(32,16,1);
- settings_sphere->end();
- settings_light_vp->add_child(settings_sphere);
- settings_camera = memnew( Camera );
- settings_light_vp->add_child(settings_camera);
- settings_camera->set_translation(Vector3(0,0,2));
- settings_camera->set_orthogonal(2.1,0.1,5);
-
- settings_default_light_rot_x=Math_PI*0.3;
- settings_default_light_rot_y=Math_PI*0.2;
-
-
-
- settings_ambient_color = memnew( ColorPickerButton );
- settings_vbc->add_margin_child(TTR("Ambient Light Color:"),settings_ambient_color);
- settings_ambient_color->connect("color_changed",this,"_update_ambient_light_color");
- settings_ambient_color->set_pick_color(Color(0.15,0.15,0.15));
-
-
- settings_fov = memnew( SpinBox );
- settings_fov->set_max(179);
- settings_fov->set_min(1);
- settings_fov->set_step(0.01);
- settings_fov->set_value(EDITOR_DEF("editors/3d/default_fov",60.0));
- settings_vbc->add_margin_child(TTR("Perspective FOV (deg.):"),settings_fov);
-
- settings_znear = memnew( SpinBox );
- settings_znear->set_max(10000);
- settings_znear->set_min(0.1);
- settings_znear->set_step(0.01);
- settings_znear->set_value(EDITOR_DEF("editors/3d/default_z_near",0.1));
- settings_vbc->add_margin_child(TTR("View Z-Near:"),settings_znear);
-
- settings_zfar = memnew( SpinBox );
- settings_zfar->set_max(10000);
- settings_zfar->set_min(0.1);
- settings_zfar->set_step(0.01);
- settings_zfar->set_value(EDITOR_DEF("editors/3d/default_z_far",1500));
- settings_vbc->add_margin_child(TTR("View Z-Far:"),settings_zfar);
-
- //settings_dialog->get_cancel()->hide();
- /* XFORM DIALOG */
-
- xform_dialog = memnew( ConfirmationDialog );
- xform_dialog->set_title(TTR("Transform Change"));
- add_child(xform_dialog);
- Label *l = memnew(Label);
- l->set_text(TTR("Translate:"));
- l->set_pos(Point2(5,5));
- xform_dialog->add_child(l);
-
- for(int i=0;i<3;i++) {
-
- xform_translate[i] = memnew( LineEdit );
- xform_translate[i]->set_pos( Point2(15+i*60,22) );
- xform_translate[i]->set_size( Size2(50,12 ) );
- xform_dialog->add_child( xform_translate[i] );
- }
-
- l = memnew(Label);
- l->set_text(TTR("Rotate (deg.):"));
- l->set_pos(Point2(5,45));
- xform_dialog->add_child(l);
-
- for(int i=0;i<3;i++) {
- xform_rotate[i] = memnew( LineEdit );
- xform_rotate[i]->set_pos( Point2(15+i*60,62) );
- xform_rotate[i]->set_size( Size2(50,22 ) );
- xform_dialog->add_child(xform_rotate[i]);
- }
-
- l = memnew(Label);
- l->set_text(TTR("Scale (ratio):"));
- l->set_pos(Point2(5,85));
- xform_dialog->add_child(l);
-
- for(int i=0;i<3;i++) {
- xform_scale[i] = memnew( LineEdit );
- xform_scale[i]->set_pos( Point2(15+i*60,102) );
- xform_scale[i]->set_size( Size2(50,22 ) );
- xform_dialog->add_child(xform_scale[i]);
- }
-
- l = memnew(Label);
- l->set_text(TTR("Transform Type"));
- l->set_pos(Point2(5,125));
- xform_dialog->add_child(l);
-
- xform_type = memnew( OptionButton );
- xform_type->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- xform_type->set_begin( Point2(15,142) );
- xform_type->set_end( Point2(15,75) );
- xform_type->add_item(TTR("Pre"));
- xform_type->add_item(TTR("Post"));
- xform_dialog->add_child(xform_type);
-
- xform_dialog->connect("confirmed", this,"_xform_dialog_action");
-
- scenario_debug=VisualServer::SCENARIO_DEBUG_DISABLED;
-
- selected=NULL;
-
- set_process_unhandled_key_input(true);
- add_to_group("_spatial_editor_group");
-
- EDITOR_DEF("editors/3d/manipulator_gizmo_size",80);
- EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT,"editors/3d/manipulator_gizmo_size",PROPERTY_HINT_RANGE,"16,1024,1"));
- EDITOR_DEF("editors/3d/manipulator_gizmo_opacity",0.2);
-
- over_gizmo_handle=-1;
-}
-
-SpatialEditor::~SpatialEditor() {
-
-
-}
-
-
-
-
-void SpatialEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
-
- spatial_editor->show();
- spatial_editor->set_process(true);
- //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),false);
- spatial_editor->grab_focus();
-
- } else {
-
- spatial_editor->hide();
- spatial_editor->set_process(false);
- //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),true);
-
- }
-
-}
-void SpatialEditorPlugin::edit(Object *p_object) {
-
- spatial_editor->edit(p_object->cast_to<Spatial>());
-}
-
-bool SpatialEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Spatial");
-}
-
-Dictionary SpatialEditorPlugin::get_state() const {
- return spatial_editor->get_state();
-}
-
-void SpatialEditorPlugin::set_state(const Dictionary& p_state) {
-
- spatial_editor->set_state(p_state);
-}
-
-void SpatialEditor::snap_cursor_to_plane(const Plane& p_plane) {
-
- //cursor.pos=p_plane.project(cursor.pos);
-}
-
-void SpatialEditorPlugin::_bind_methods() {
-
- ClassDB::bind_method("snap_cursor_to_plane",&SpatialEditorPlugin::snap_cursor_to_plane);
-
-}
-
-void SpatialEditorPlugin::snap_cursor_to_plane(const Plane& p_plane) {
-
-
- spatial_editor->snap_cursor_to_plane(p_plane);
-}
-
-
-
-
-SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- spatial_editor = memnew( SpatialEditor(p_node) );
- spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- editor->get_viewport()->add_child(spatial_editor);
-
- //spatial_editor->set_area_as_parent_rect();
- spatial_editor->hide();
- spatial_editor->connect("transform_key_request",editor,"_transform_keyed");
-
- //spatial_editor->set_process(true);
-}
-
-
-SpatialEditorPlugin::~SpatialEditorPlugin() {
-
-}
diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h
deleted file mode 100644
index 36f807c11f..0000000000
--- a/tools/editor/plugins/spatial_editor_plugin.h
+++ /dev/null
@@ -1,574 +0,0 @@
-/*************************************************************************/
-/* spatial_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SPATIAL_EDITOR_PLUGIN_H
-#define SPATIAL_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/visual_instance.h"
-#include "scene/3d/immediate_geometry.h"
-#include "scene/3d/light.h"
-#include "scene/gui/panel_container.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class Camera;
-class SpatialEditor;
-class SpatialEditorGizmos;
-
-class SpatialEditorGizmo : public SpatialGizmo {
-
- GDCLASS(SpatialEditorGizmo,SpatialGizmo);
-
- bool selected;
-public:
-
- void set_selected(bool p_selected) { selected=p_selected; }
- bool is_selected() const { return selected; }
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- virtual bool intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum);
- virtual bool intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle=NULL,bool p_sec_first=false);
- SpatialEditorGizmo();
-};
-
-
-class SpatialEditorViewport : public Control {
-
- GDCLASS( SpatialEditorViewport, Control );
-friend class SpatialEditor;
- enum {
-
- VIEW_TOP,
- VIEW_BOTTOM,
- VIEW_LEFT,
- VIEW_RIGHT,
- VIEW_FRONT,
- VIEW_REAR,
- VIEW_CENTER_TO_ORIGIN,
- VIEW_CENTER_TO_SELECTION,
- VIEW_ALIGN_SELECTION_WITH_VIEW,
- VIEW_PERSPECTIVE,
- VIEW_ENVIRONMENT,
- VIEW_ORTHOGONAL,
- VIEW_AUDIO_LISTENER,
- VIEW_GIZMOS,
- };
-public:
- enum {
- GIZMO_BASE_LAYER=27,
- GIZMO_EDIT_LAYER=26,
- GIZMO_GRID_LAYER=25
- };
-private:
- int index;
- String name;
- void _menu_option(int p_option);
- Size2 prev_size;
-
- EditorNode *editor;
- EditorSelection *editor_selection;
- UndoRedo *undo_redo;
-
- Button *preview_camera;
-
- MenuButton *view_menu;
-
- Control *surface;
- Viewport *viewport;
- Camera *camera;
- bool transforming;
- bool orthogonal;
- float gizmo_scale;
-
- struct _RayResult {
-
- Spatial* item;
- float depth;
- int handle;
- _FORCE_INLINE_ bool operator<(const _RayResult& p_rr) const { return depth<p_rr.depth; }
- };
-
- void _update_name();
- void _compute_edit(const Point2& p_point);
- void _clear_selected();
- void _select_clicked(bool p_append,bool p_single);
- void _select(Spatial *p_node, bool p_append,bool p_single);
- ObjectID _select_ray(const Point2& p_pos, bool p_append,bool &r_includes_current,int *r_gizmo_handle=NULL,bool p_alt_select=false);
- void _find_items_at_pos(const Point2& p_pos,bool &r_includes_current,Vector<_RayResult> &results,bool p_alt_select=false);
- Vector3 _get_ray_pos(const Vector2& p_pos) const;
- Vector3 _get_ray(const Vector2& p_pos);
- Point2 _point_to_screen(const Vector3& p_point);
- Transform _get_camera_transform() const;
- int get_selected_count() const;
-
- Vector3 _get_camera_pos() const;
- Vector3 _get_camera_normal() const;
- Vector3 _get_screen_to_space(const Vector3& p_vector3);
-
- void _select_region();
- bool _gizmo_select(const Vector2& p_screenpos,bool p_hilite_only=false);
-
- float get_znear() const;
- float get_zfar() const;
- float get_fov() const;
-
- ObjectID clicked;
- Vector<_RayResult> selection_results;
- bool clicked_includes_current;
- bool clicked_wants_append;
-
- PopupMenu *selection_menu;
-
- enum NavigationScheme {
- NAVIGATION_GODOT,
- NAVIGATION_MAYA,
- NAVIGATION_MODO,
- };
-
- enum NavigationZoomStyle {
- NAVIGATION_ZOOM_VERTICAL,
- NAVIGATION_ZOOM_HORIZONTAL
- };
-
- enum NavigationMode {
- NAVIGATION_NONE,
- NAVIGATION_PAN,
- NAVIGATION_ZOOM,
- NAVIGATION_ORBIT
- };
- enum TransformMode {
- TRANSFORM_NONE,
- TRANSFORM_ROTATE,
- TRANSFORM_TRANSLATE,
- TRANSFORM_SCALE
-
- };
- enum TransformPlane {
- TRANSFORM_VIEW,
- TRANSFORM_X_AXIS,
- TRANSFORM_Y_AXIS,
- TRANSFORM_Z_AXIS,
- };
-
- struct EditData {
- TransformMode mode;
- TransformPlane plane;
- Transform original;
- Vector3 click_ray;
- Vector3 click_ray_pos;
- Vector3 center;
- Vector3 orig_gizmo_pos;
- int edited_gizmo;
- Point2 mouse_pos;
- bool snap;
- Ref<SpatialEditorGizmo> gizmo;
- int gizmo_handle;
- Variant gizmo_initial_value;
- Vector3 gizmo_initial_pos;
- } _edit;
-
- struct Cursor {
-
- Vector3 cursor_pos;
-
- Vector3 pos;
- float x_rot,y_rot,distance;
- bool region_select;
- Point2 region_begin,region_end;
-
- Cursor() { x_rot=y_rot=0.5; distance=4; region_select=false; }
- } cursor;
-
- RID move_gizmo_instance[3], rotate_gizmo_instance[3];
-
-
- String last_message;
- String message;
- float message_time;
-
- void set_message(String p_message,float p_time=5);
-
- //
- void _update_camera();
- void _draw();
-
- void _smouseenter();
- void _sinput(const InputEvent& p_ie);
- SpatialEditor *spatial_editor;
-
- Camera* previewing;
- Camera* preview;
-
- void _preview_exited_scene();
- void _toggle_camera_preview(bool);
- void _init_gizmo_instance(int p_idx);
- void _finish_gizmo_instances();
- void _selection_result_pressed(int);
- void _selection_menu_hide();
- void _list_select(InputEventMouseButton b);
-
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void update_transform_gizmo_view();
-
- void set_can_preview(Camera* p_preview);
- void set_state(const Dictionary& p_state);
- Dictionary get_state() const;
- void reset();
-
- void focus_selection();
-
- Viewport *get_viewport_node() { return viewport; }
-
-
- SpatialEditorViewport(SpatialEditor *p_spatial_editor,EditorNode *p_editor,int p_index);
-};
-
-
-
-class SpatialEditorSelectedItem : public Object {
-
- GDCLASS(SpatialEditorSelectedItem,Object);
-
-public:
-
- Rect3 aabb;
- Transform original; // original location when moving
- Transform last_xform; // last transform
- Spatial *sp;
- RID sbox_instance;
-
- SpatialEditorSelectedItem() { sp=NULL; }
- ~SpatialEditorSelectedItem();
-};
-
-class SpatialEditor : public VBoxContainer {
-
- GDCLASS(SpatialEditor, VBoxContainer );
-public:
-
- enum ToolMode {
-
- TOOL_MODE_SELECT,
- TOOL_MODE_MOVE,
- TOOL_MODE_ROTATE,
- TOOL_MODE_SCALE,
- TOOL_MODE_LIST_SELECT,
- TOOL_MAX
-
- };
-
-
-private:
- EditorNode *editor;
- EditorSelection *editor_selection;
-
-
-
- Control *viewport_base;
- SpatialEditorViewport *viewports[4];
- VSplitContainer *shader_split;
- HSplitContainer *palette_split;
-
- /////
-
- ToolMode tool_mode;
- bool orthogonal;
-
-
- VisualServer::ScenarioDebugMode scenario_debug;
-
- RID light;
- RID light_instance;
- Transform light_transform;
-
-
- RID origin;
- RID origin_instance;
- RID grid[3];
- RID grid_instance[3];
- bool grid_visible[3]; //currently visible
- float last_grid_snap;
- bool grid_enable[3]; //should be always visible if true
- bool grid_enabled;
-
- Ref<Mesh> move_gizmo[3], rotate_gizmo[3];
- Ref<FixedSpatialMaterial> gizmo_color[3];
- Ref<FixedSpatialMaterial> gizmo_hl;
-
-
- int over_gizmo_handle;
-
-
-
- Ref<Mesh> selection_box;
- RID indicators;
- RID indicators_instance;
- RID cursor_mesh;
- RID cursor_instance;
- Ref<FixedSpatialMaterial> indicator_mat;
- Ref<FixedSpatialMaterial> cursor_material;
-
-/*
- struct Selected {
- AABB aabb;
- Transform original; // original location when moving
- Transform last_xform; // last transform
- Spatial *sp;
- RID poly_instance;
- };
-
- Map<uint32_t,Selected> selected;
-*/
- struct Gizmo {
-
- bool visible;
- float scale;
- Transform transform;
- } gizmo;
-
-
-
-
- enum MenuOption {
-
- MENU_TOOL_SELECT,
- 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,
- MENU_TRANSFORM_DIALOG,
- MENU_VIEW_USE_1_VIEWPORT,
- MENU_VIEW_USE_2_VIEWPORTS,
- MENU_VIEW_USE_2_VIEWPORTS_ALT,
- MENU_VIEW_USE_3_VIEWPORTS,
- MENU_VIEW_USE_3_VIEWPORTS_ALT,
- MENU_VIEW_USE_4_VIEWPORTS,
- MENU_VIEW_USE_DEFAULT_LIGHT,
- MENU_VIEW_USE_DEFAULT_SRGB,
- MENU_VIEW_DISPLAY_NORMAL,
- MENU_VIEW_DISPLAY_WIREFRAME,
- MENU_VIEW_DISPLAY_OVERDRAW,
- MENU_VIEW_DISPLAY_SHADELESS,
- MENU_VIEW_ORIGIN,
- MENU_VIEW_GRID,
- MENU_VIEW_CAMERA_SETTINGS,
-
- };
-
-
- Button *tool_button[TOOL_MAX];
- Button *instance_button;
-
-
- MenuButton* transform_menu;
- MenuButton* view_menu;
-
- ConfirmationDialog *snap_dialog;
- ConfirmationDialog *xform_dialog;
- ConfirmationDialog *settings_dialog;
-
- bool snap_enabled;
- LineEdit *snap_translate;
- LineEdit *snap_rotate;
- LineEdit *snap_scale;
- PanelContainer* menu_panel;
-
- LineEdit *xform_translate[3];
- LineEdit *xform_rotate[3];
- LineEdit *xform_scale[3];
- OptionButton *xform_type;
-
- VBoxContainer *settings_vbc;
- SpinBox *settings_fov;
- SpinBox *settings_znear;
- SpinBox *settings_zfar;
- DirectionalLight *settings_dlight;
- ImmediateGeometry *settings_sphere;
- Camera *settings_camera;
- float settings_default_light_rot_x;
- float settings_default_light_rot_y;
-
- ViewportContainer *settings_light_base;
- Viewport *settings_light_vp;
- ColorPickerButton *settings_ambient_color;
- Image settings_light_dir_image;
-
-
- void _xform_dialog_action();
- void _menu_item_pressed(int p_option);
-
- HBoxContainer *hbc_menu;
-
-
-
-//
-//
- void _generate_selection_box();
- UndoRedo *undo_redo;
-
- void _instance_scene();
- void _init_indicators();
- void _finish_indicators();
-
- void _toggle_maximize_view(Object* p_viewport);
-
- Node *custom_camera;
-
- Object *_get_editor_data(Object *p_what);
-
- Ref<Environment> viewport_environment;
-
- Spatial *selected;
-
- void _request_gizmo(Object* p_obj);
-
- static SpatialEditor *singleton;
-
- void _node_removed(Node* p_node);
- SpatialEditorGizmos *gizmos;
- SpatialEditor();
-
- void _update_ambient_light_color(const Color& p_color);
- void _update_default_light_angle();
- void _default_light_angle_input(const InputEvent& p_event);
-
-protected:
-
-
-
-
- void _notification(int p_what);
- //void _gui_input(InputEvent p_event);
- void _unhandled_key_input(InputEvent p_event);
-
- static void _bind_methods();
-public:
-
-
- static SpatialEditor *get_singleton() { return singleton; }
- void snap_cursor_to_plane(const Plane& p_plane);
-
- float get_znear() const { return settings_znear->get_value(); }
- float get_zfar() const { return settings_zfar->get_value(); }
- float get_fov() const { return settings_fov->get_value(); }
-
- Transform get_gizmo_transform() const { return gizmo.transform; }
- bool is_gizmo_visible() const { return gizmo.visible; }
-
- ToolMode get_tool_mode() const { return tool_mode; }
- bool is_snap_enabled() const { return snap_enabled; }
- float get_translate_snap() const { return snap_translate->get_text().to_double(); }
- float get_rotate_snap() const { return snap_rotate->get_text().to_double(); }
- float get_scale_snap() const { return snap_scale->get_text().to_double(); }
-
- Ref<Mesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
- Ref<Mesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }
-
- void update_transform_gizmo();
-
- void select_gizmo_hilight_axis(int p_axis);
- void set_custom_camera(Node *p_camera) { custom_camera=p_camera; }
-
- void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
- Dictionary get_state() const;
- void set_state(const Dictionary& p_state);
-
- Ref<Environment> get_viewport_environment() { return viewport_environment; }
-
- UndoRedo *get_undo_redo() { return undo_redo; }
-
- void add_control_to_menu_panel(Control *p_control);
-
- VSplitContainer *get_shader_split();
- HSplitContainer *get_palette_split();
-
- Spatial *get_selected() { return selected; }
-
- int get_over_gizmo_handle() const { return over_gizmo_handle; }
- void set_over_gizmo_handle(int idx) { over_gizmo_handle=idx; }
-
- void set_can_preview(Camera* p_preview);
-
- SpatialEditorViewport *get_editor_viewport(int p_idx) {
- ERR_FAIL_INDEX_V(p_idx,4,NULL);
- return viewports[p_idx];
- }
-
- Camera *get_camera() { return NULL; }
- void edit(Spatial *p_spatial);
- void clear();
- SpatialEditor(EditorNode *p_editor);
- ~SpatialEditor();
-};
-
-class SpatialEditorPlugin : public EditorPlugin {
-
- GDCLASS( SpatialEditorPlugin, EditorPlugin );
-
- SpatialEditor *spatial_editor;
- EditorNode *editor;
-protected:
- static void _bind_methods();
-public:
-
- void snap_cursor_to_plane(const Plane& p_plane);
-
- SpatialEditor *get_spatial_editor() { return spatial_editor; }
- virtual String get_name() const { return "3D"; }
- bool has_main_screen() const { return true; }
- virtual void make_visible(bool p_visible);
- virtual void edit(Object *p_object);
- virtual bool handles(Object *p_object) const;
-
- virtual Dictionary get_state() const;
- virtual void set_state(const Dictionary& p_state);
- virtual void clear() { spatial_editor->clear(); }
-
-
- SpatialEditorPlugin(EditorNode *p_node);
- ~SpatialEditorPlugin();
-
-};
-
-#endif
diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.cpp b/tools/editor/plugins/sprite_frames_editor_plugin.cpp
deleted file mode 100644
index 095b059836..0000000000
--- a/tools/editor/plugins/sprite_frames_editor_plugin.cpp
+++ /dev/null
@@ -1,969 +0,0 @@
-/*************************************************************************/
-/* sprite_frames_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "sprite_frames_editor_plugin.h"
-
-#include "io/resource_loader.h"
-#include "globals.h"
-#include "tools/editor/editor_settings.h"
-#include "scene/3d/sprite_3d.h"
-
-
-
-void SpriteFramesEditor::_gui_input(InputEvent p_event) {
-
-
-}
-
-void SpriteFramesEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
- }
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- load->set_icon( get_icon("Folder","EditorIcons") );
- _delete->set_icon( get_icon("Del","EditorIcons") );
- new_anim->set_icon( get_icon("New","EditorIcons") );
- remove_anim->set_icon( get_icon("Del","EditorIcons") );
-
- }
-
- if (p_what==NOTIFICATION_READY) {
-
- //NodePath("/root")->connect("node_removed", this,"_node_removed",Vector<Variant>(),true);
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
- }
-}
-
-void SpriteFramesEditor::_file_load_request(const PoolVector<String>& p_path,int p_at_pos) {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
-
- List< Ref<Texture> > resources;
-
- for(int i=0;i<p_path.size();i++) {
-
- Ref<Texture> resource;
- resource = ResourceLoader::load(p_path[i]);
-
- if (resource.is_null()) {
- dialog->set_text(TTR("ERROR: Couldn't load frame resource!"));
- dialog->set_title(TTR("Error!"));
- //dialog->get_cancel()->set_text("Close");
- dialog->get_ok()->set_text(TTR("Close"));
- dialog->popup_centered_minsize();
- return; ///beh should show an error i guess
- }
-
- resources.push_back(resource);
- }
-
-
- if (resources.empty()) {
- //print_line("added frames!");
- return;
- }
-
- undo_redo->create_action(TTR("Add Frame"));
- int fc=frames->get_frame_count(edited_anim);
-
- int count=0;
-
- for(List< Ref<Texture> >::Element *E=resources.front();E;E=E->next() ) {
-
- undo_redo->add_do_method(frames,"add_frame",edited_anim,E->get(),p_at_pos==-1?-1:p_at_pos+count);
- undo_redo->add_undo_method(frames,"remove_frame",edited_anim,p_at_pos==-1?fc:p_at_pos);
- count++;
-
- }
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
-
- undo_redo->commit_action();
- //print_line("added frames!");
-}
-
-void SpriteFramesEditor::_load_pressed() {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
- loading_scene=false;
-
- file->clear_filters();
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("Texture",&extensions);
- for(int i=0;i<extensions.size();i++)
- file->add_filter("*."+extensions[i]);
-
- file->set_mode(EditorFileDialog::MODE_OPEN_FILES);
-
- file->popup_centered_ratio();
-
-}
-
-
-void SpriteFramesEditor::_item_edited() {
-
-#if 0
- if (!tree->get_selected())
- return;
-
- TreeItem *s = tree->get_selected();
-
- if (tree->get_selected_column()==0) {
- // renamed
- String old_name=s->get_metadata(0);
- String new_name=s->get_text(0);
- if (old_name==new_name)
- return;
-
- if (new_name=="" || new_name.find("\\")!=-1 || new_name.find("/")!=-1 || frames->has_resource(new_name)) {
-
- s->set_text(0,old_name);
- return;
- }
-
- RES samp = frames->get_resource(old_name);
- undo_redo->create_action("Rename Resource");
- undo_redo->add_do_method(frames,"remove_resource",old_name);
- undo_redo->add_do_method(frames,"add_resource",new_name,samp);
- undo_redo->add_undo_method(frames,"remove_resource",new_name);
- undo_redo->add_undo_method(frames,"add_resource",old_name,samp);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
- }
-#endif
-
-}
-
-void SpriteFramesEditor::_delete_confirm_pressed() {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
-
- if (tree->get_current()<0)
- return;
-
- sel-=1;
- if (sel<0 && frames->get_frame_count(edited_anim))
- sel=0;
-
- int to_remove = tree->get_current();
- sel=to_remove;
- Ref<Texture> r = frames->get_frame(edited_anim,to_remove);
- undo_redo->create_action(TTR("Delete Resource"));
- undo_redo->add_do_method(frames,"remove_frame",edited_anim,to_remove);
- undo_redo->add_undo_method(frames,"add_frame",edited_anim,r,to_remove);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
-}
-
-
-void SpriteFramesEditor::_paste_pressed() {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
-
- Ref<Texture> r=EditorSettings::get_singleton()->get_resource_clipboard();
- if (!r.is_valid()) {
- dialog->set_text(TTR("Resource clipboard is empty or not a texture!"));
- dialog->set_title(TTR("Error!"));
- //dialog->get_cancel()->set_text("Close");
- dialog->get_ok()->set_text(TTR("Close"));
- dialog->popup_centered_minsize();
- return; ///beh should show an error i guess
- }
-
-
- undo_redo->create_action(TTR("Paste Frame"));
- undo_redo->add_do_method(frames,"add_frame",edited_anim,r);
- undo_redo->add_undo_method(frames,"remove_frame",edited_anim,frames->get_frame_count(edited_anim));
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
-}
-
-void SpriteFramesEditor::_empty_pressed() {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
-
- int from=-1;
-
- if (tree->get_current()>=0) {
-
- from = tree->get_current();
- sel=from;
-
- } else {
- from=frames->get_frame_count(edited_anim);
- }
-
-
-
- Ref<Texture> r;
-
- undo_redo->create_action(TTR("Add Empty"));
- undo_redo->add_do_method(frames,"add_frame",edited_anim,r,from);
- undo_redo->add_undo_method(frames,"remove_frame",edited_anim,from);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
-}
-
-void SpriteFramesEditor::_empty2_pressed() {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
-
- int from=-1;
-
- if (tree->get_current()>=0) {
-
- from = tree->get_current();
- sel=from;
-
- } else {
- from=frames->get_frame_count(edited_anim);
- }
-
-
-
- Ref<Texture> r;
-
- undo_redo->create_action(TTR("Add Empty"));
- undo_redo->add_do_method(frames,"add_frame",edited_anim,r,from+1);
- undo_redo->add_undo_method(frames,"remove_frame",edited_anim,from+1);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
-}
-
-void SpriteFramesEditor::_up_pressed() {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
-
- if (tree->get_current()<0)
- return;
-
- int to_move = tree->get_current();
- if (to_move<1)
- return;
-
- sel=to_move;
- sel-=1;
-
- Ref<Texture> r = frames->get_frame(edited_anim,to_move);
- undo_redo->create_action(TTR("Delete Resource"));
- undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move-1));
- undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move-1,frames->get_frame(edited_anim,to_move));
- undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move));
- undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move-1,frames->get_frame(edited_anim,to_move-1));
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
-}
-
-void SpriteFramesEditor::_down_pressed() {
-
- ERR_FAIL_COND(!frames->has_animation(edited_anim));
-
- if (tree->get_current()<0)
- return;
-
- int to_move = tree->get_current();
- if (to_move<0 || to_move>=frames->get_frame_count(edited_anim)-1)
- return;
-
- sel=to_move;
- sel+=1;
-
- Ref<Texture> r = frames->get_frame(edited_anim,to_move);
- undo_redo->create_action(TTR("Delete Resource"));
- undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move+1));
- undo_redo->add_do_method(frames,"set_frame",edited_anim,to_move+1,frames->get_frame(edited_anim,to_move));
- undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move,frames->get_frame(edited_anim,to_move));
- undo_redo->add_undo_method(frames,"set_frame",edited_anim,to_move+1,frames->get_frame(edited_anim,to_move+1));
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
-
-
-}
-
-
-void SpriteFramesEditor::_delete_pressed() {
-
-
- if (tree->get_current()<0)
- return;
-
- _delete_confirm_pressed(); //it has undo.. why bother with a dialog..
- /*
- dialog->set_title("Confirm...");
- dialog->set_text("Remove Resource '"+tree->get_selected()->get_text(0)+"' ?");
- //dialog->get_cancel()->set_text("Cancel");
- //dialog->get_ok()->show();
- dialog->get_ok()->set_text("Remove");
- dialog->popup_centered(Size2(300,60));*/
-
-}
-
-
-void SpriteFramesEditor::_animation_select() {
-
- if (updating)
- return;
-
- TreeItem *selected = animations->get_selected();
- ERR_FAIL_COND(!selected);
- edited_anim=selected->get_text(0);
- _update_library(true);
-
-}
-
-
-static void _find_anim_sprites(Node* p_node,List<Node*> *r_nodes,Ref<SpriteFrames> p_sfames) {
-
- Node *edited = EditorNode::get_singleton()->get_edited_scene();
- if (!edited)
- return;
- if (p_node!=edited && p_node->get_owner()!=edited)
- return;
-
- {
- AnimatedSprite *as = p_node->cast_to<AnimatedSprite>();
- if (as && as->get_sprite_frames()==p_sfames) {
- r_nodes->push_back(p_node);
- }
- }
-
- {
- AnimatedSprite3D *as = p_node->cast_to<AnimatedSprite3D>();
- if (as && as->get_sprite_frames()==p_sfames) {
- r_nodes->push_back(p_node);
- }
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
- _find_anim_sprites(p_node->get_child(i),r_nodes,p_sfames);
- }
-
-}
-
-void SpriteFramesEditor::_animation_name_edited(){
-
- if (updating)
- return;
-
- if (!frames->has_animation(edited_anim))
- return;
-
- TreeItem *edited = animations->get_edited();
- if (!edited)
- return;
-
- String new_name = edited->get_text(0);
-
- if (new_name==String(edited_anim))
- return;
-
- new_name=new_name.replace("/","_").replace(","," ");
-
- String name=new_name;
- int counter=0;
- while(frames->has_animation(name)) {
- counter++;
- name=new_name+" "+itos(counter);
- }
-
- List<Node*> nodes;
- _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(),&nodes,Ref<SpriteFrames>(frames));
-
- undo_redo->create_action(TTR("Rename Animation"));
- undo_redo->add_do_method(frames,"rename_animation",edited_anim,name);
- undo_redo->add_undo_method(frames,"rename_animation",name,edited_anim);
-
- for(List<Node*>::Element *E=nodes.front();E;E=E->next()) {
-
- String current = E->get()->call("get_animation");
- if (current!=edited_anim)
- continue;
-
- undo_redo->add_do_method(E->get(),"set_animation",name);
- undo_redo->add_undo_method(E->get(),"set_animation",edited_anim);
-
- }
-
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
-
- edited_anim=new_name;
-
- undo_redo->commit_action();
-
-
-
-}
-void SpriteFramesEditor::_animation_add(){
-
-
- String new_name = "New Anim";
-
- String name=new_name;
- int counter=0;
- while(frames->has_animation(name)) {
- counter++;
- name=new_name+" "+itos(counter);
- }
-
- List<Node*> nodes;
- _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(),&nodes,Ref<SpriteFrames>(frames));
-
-
- undo_redo->create_action(TTR("Add Animation"));
- undo_redo->add_do_method(frames,"add_animation",name);
- undo_redo->add_undo_method(frames,"remove_animation",name);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
-
-
- for(List<Node*>::Element *E=nodes.front();E;E=E->next()) {
-
- String current = E->get()->call("get_animation");
- if (frames->has_animation(current))
- continue;
-
- undo_redo->add_do_method(E->get(),"set_animation",name);
- undo_redo->add_undo_method(E->get(),"set_animation",current);
-
- }
-
- edited_anim=new_name;
-
- undo_redo->commit_action();
-
-}
-void SpriteFramesEditor::_animation_remove(){
-
- //fuck everything
- if (updating)
- return;
-
- if (!frames->has_animation(edited_anim))
- return;
-
-
- undo_redo->create_action(TTR("Remove Animation"));
- undo_redo->add_do_method(frames,"remove_animation",edited_anim);
- undo_redo->add_undo_method(frames,"add_animation",edited_anim);
- undo_redo->add_undo_method(frames,"set_animation_speed",edited_anim,frames->get_animation_speed(edited_anim));
- undo_redo->add_undo_method(frames,"set_animation_loop",edited_anim,frames->get_animation_loop(edited_anim));
- int fc = frames->get_frame_count(edited_anim);
- for(int i=0;i<fc;i++) {
- Ref<Texture> frame = frames->get_frame(edited_anim,i);
- undo_redo->add_undo_method(frames,"add_frame",edited_anim,frame);
- }
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
-
- undo_redo->commit_action();
-
-}
-
-
-void SpriteFramesEditor::_animation_loop_changed() {
-
- if (updating)
- return;
-
- undo_redo->create_action(TTR("Change Animation Loop"));
- undo_redo->add_do_method(frames,"set_animation_loop",edited_anim,anim_loop->is_pressed());
- undo_redo->add_undo_method(frames,"set_animation_loop",edited_anim,frames->get_animation_loop(edited_anim));
- undo_redo->add_do_method(this,"_update_library",true);
- undo_redo->add_undo_method(this,"_update_library",true);
- undo_redo->commit_action();
-
-}
-
-void SpriteFramesEditor::_animation_fps_changed(double p_value) {
-
- if (updating)
- return;
-
- undo_redo->create_action(TTR("Change Animation FPS"),UndoRedo::MERGE_ENDS);
- undo_redo->add_do_method(frames,"set_animation_speed",edited_anim,p_value);
- undo_redo->add_undo_method(frames,"set_animation_speed",edited_anim,frames->get_animation_speed(edited_anim));
- undo_redo->add_do_method(this,"_update_library",true);
- undo_redo->add_undo_method(this,"_update_library",true);
-
- undo_redo->commit_action();
-
-}
-
-void SpriteFramesEditor::_update_library(bool p_skip_selector) {
-
- updating=true;
-
- if (!p_skip_selector) {
- animations->clear();
-
- TreeItem *anim_root=animations->create_item();
-
- List<StringName> anim_names;
-
- anim_names.sort_custom<StringName::AlphCompare>();
-
- frames->get_animation_list(&anim_names);
-
- anim_names.sort_custom<StringName::AlphCompare>();
-
- for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
-
- String name = E->get();
-
- TreeItem *it = animations->create_item(anim_root);
-
- it->set_metadata(0,name);
-
- it->set_text(0,name);
- it->set_editable(0,true);
-
- if (E->get()==edited_anim) {
- it->select(0);
- }
- }
- }
-
-
- tree->clear();
-
- if (!frames->has_animation(edited_anim)) {
- updating=false;
- return;
- }
-
-
- if (sel>=frames->get_frame_count(edited_anim))
- sel=frames->get_frame_count(edited_anim)-1;
- else if (sel<0 && frames->get_frame_count(edited_anim))
- sel=0;
-
- for(int i=0;i<frames->get_frame_count(edited_anim);i++) {
-
-
- String name;
- Ref<Texture> icon;
-
-
- if (frames->get_frame(edited_anim,i).is_null()) {
-
- name=itos(i)+": "+TTR("(empty)");
-
- } else {
- name=itos(i)+": "+frames->get_frame(edited_anim,i)->get_name();
- icon=frames->get_frame(edited_anim,i);
- }
-
- tree->add_item(name,icon);
- if (frames->get_frame(edited_anim,i).is_valid())
- tree->set_item_tooltip(tree->get_item_count()-1,frames->get_frame(edited_anim,i)->get_path());
- if (sel==i)
- tree->select(tree->get_item_count()-1);
- }
-
- anim_speed->set_value(frames->get_animation_speed(edited_anim));
- anim_loop->set_pressed(frames->get_animation_loop(edited_anim));
-
- updating=false;
- //player->add_resource("default",resource);
-}
-
-
-
-void SpriteFramesEditor::edit(SpriteFrames* p_frames) {
-
- if (frames==p_frames)
- return;
-
- frames=p_frames;
-
-
- if (p_frames) {
-
- if (!p_frames->has_animation(edited_anim)) {
-
- List<StringName> anim_names;
- frames->get_animation_list(&anim_names);
- anim_names.sort_custom<StringName::AlphCompare>();
- if (anim_names.size()) {
- edited_anim=anim_names.front()->get();
- } else {
- edited_anim=StringName();
- }
-
- }
-
- _update_library();
- } else {
-
- hide();
- //set_fixed_process(false);
- }
-
-}
-
-
-Variant SpriteFramesEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- if (!frames->has_animation(edited_anim))
- return false;
-
- int idx = tree->get_item_at_pos(p_point,true);
-
- if (idx<0 || idx>=frames->get_frame_count(edited_anim))
- return Variant();
-
- RES frame = frames->get_frame(edited_anim,idx);
-
- if (frame.is_null())
- return Variant();
-
- return EditorNode::get_singleton()->drag_resource(frame,p_from);
-
-
-}
-
-bool SpriteFramesEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
-
- Dictionary d = p_data;
-
- if (!d.has("type"))
- return false;
-
- if (d.has("from") && (Object*)(d["from"])==tree)
- return false;
-
- if (String(d["type"])=="resource" && d.has("resource")) {
- RES r=d["resource"];
-
- Ref<Texture> texture = r;
-
- if (texture.is_valid()) {
-
- return true;
- }
- }
-
-
- if (String(d["type"])=="files") {
-
- Vector<String> files = d["files"];
-
- if (files.size()==0)
- return false;
-
- for(int i=0;i<files.size();i++) {
- String file = files[0];
- String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
-
- if (!ClassDB::is_parent_class(ftype,"Texture")) {
- return false;
- }
-
- }
-
- return true;
-
- }
- return false;
-}
-
-void SpriteFramesEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
-
- if (!can_drop_data_fw(p_point,p_data,p_from))
- return;
-
- Dictionary d = p_data;
-
- if (!d.has("type"))
- return;
-
- int at_pos = tree->get_item_at_pos(p_point,true);
-
- if (String(d["type"])=="resource" && d.has("resource")) {
- RES r=d["resource"];
-
- Ref<Texture> texture = r;
-
- if (texture.is_valid()) {
-
- undo_redo->create_action(TTR("Add Frame"));
- undo_redo->add_do_method(frames,"add_frame",edited_anim,texture,at_pos==-1?-1:at_pos);
- undo_redo->add_undo_method(frames,"remove_frame",edited_anim,at_pos==-1?frames->get_frame_count(edited_anim):at_pos);
- undo_redo->add_do_method(this,"_update_library");
- undo_redo->add_undo_method(this,"_update_library");
- undo_redo->commit_action();
-
- }
- }
-
-
- if (String(d["type"])=="files") {
-
- PoolVector<String> files = d["files"];
-
- _file_load_request(files,at_pos);
- }
-
-}
-
-
-void SpriteFramesEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&SpriteFramesEditor::_gui_input);
- ClassDB::bind_method(_MD("_load_pressed"),&SpriteFramesEditor::_load_pressed);
- ClassDB::bind_method(_MD("_empty_pressed"),&SpriteFramesEditor::_empty_pressed);
- ClassDB::bind_method(_MD("_empty2_pressed"),&SpriteFramesEditor::_empty2_pressed);
- ClassDB::bind_method(_MD("_item_edited"),&SpriteFramesEditor::_item_edited);
- ClassDB::bind_method(_MD("_delete_pressed"),&SpriteFramesEditor::_delete_pressed);
- ClassDB::bind_method(_MD("_paste_pressed"),&SpriteFramesEditor::_paste_pressed);
- ClassDB::bind_method(_MD("_delete_confirm_pressed"),&SpriteFramesEditor::_delete_confirm_pressed);
- ClassDB::bind_method(_MD("_file_load_request","files","atpos"),&SpriteFramesEditor::_file_load_request,DEFVAL(-1));
- ClassDB::bind_method(_MD("_update_library","skipsel"),&SpriteFramesEditor::_update_library,DEFVAL(false));
- ClassDB::bind_method(_MD("_up_pressed"),&SpriteFramesEditor::_up_pressed);
- ClassDB::bind_method(_MD("_down_pressed"),&SpriteFramesEditor::_down_pressed);
- ClassDB::bind_method(_MD("_animation_select"),&SpriteFramesEditor::_animation_select);
- ClassDB::bind_method(_MD("_animation_name_edited"),&SpriteFramesEditor::_animation_name_edited);
- ClassDB::bind_method(_MD("_animation_add"),&SpriteFramesEditor::_animation_add);
- ClassDB::bind_method(_MD("_animation_remove"),&SpriteFramesEditor::_animation_remove);
- ClassDB::bind_method(_MD("_animation_loop_changed"),&SpriteFramesEditor::_animation_loop_changed);
- ClassDB::bind_method(_MD("_animation_fps_changed"),&SpriteFramesEditor::_animation_fps_changed);
- ClassDB::bind_method(_MD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw);
- ClassDB::bind_method(_MD("can_drop_data_fw"), &SpriteFramesEditor::can_drop_data_fw);
- ClassDB::bind_method(_MD("drop_data_fw"), &SpriteFramesEditor::drop_data_fw);
-
-
-}
-
-
-SpriteFramesEditor::SpriteFramesEditor() {
-
- //add_style_override("panel", get_stylebox("panel","Panel"));
-
- split = memnew( HSplitContainer );
- add_child(split);
-
- VBoxContainer *vbc_animlist = memnew( VBoxContainer );
- split->add_child(vbc_animlist);
- vbc_animlist->set_custom_minimum_size(Size2(150,0));
- //vbc_animlist->set_v_size_flags(SIZE_EXPAND_FILL);
-
-
- VBoxContainer *sub_vb = memnew( VBoxContainer );
- vbc_animlist->add_margin_child(TTR("Animations"),sub_vb,true);
- sub_vb->set_v_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *hbc_animlist = memnew( HBoxContainer );
- sub_vb->add_child(hbc_animlist);
-
- new_anim = memnew( Button );
- hbc_animlist->add_child(new_anim);
- new_anim->connect("pressed",this,"_animation_add");
-
-
- hbc_animlist->add_spacer();
-
- remove_anim = memnew( Button );
- hbc_animlist->add_child(remove_anim);
- remove_anim->connect("pressed",this,"_animation_remove");
-
- animations = memnew( Tree );
- sub_vb->add_child(animations);
- animations->set_v_size_flags(SIZE_EXPAND_FILL);
- animations->set_hide_root(true);
- animations->connect("cell_selected",this,"_animation_select");
- animations->connect("item_edited",this,"_animation_name_edited");
- animations->set_single_select_cell_editing_only_when_already_selected(true);
-
-
- anim_speed = memnew( SpinBox);
- vbc_animlist->add_margin_child(TTR("Speed (FPS):"),anim_speed);
- anim_speed->set_min(0);
- anim_speed->set_max(100);
- anim_speed->set_step(0.01);
- anim_speed->connect("value_changed",this,"_animation_fps_changed");
-
- anim_loop = memnew( CheckButton );
- anim_loop->set_text(TTR("Loop"));
- vbc_animlist->add_child(anim_loop);
- anim_loop->connect("pressed",this,"_animation_loop_changed");
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- split->add_child(vbc);
- vbc->set_h_size_flags(SIZE_EXPAND_FILL);
-
- sub_vb = memnew( VBoxContainer );
- vbc->add_margin_child(TTR("Animation Frames"),sub_vb,true);
-
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- sub_vb->add_child(hbc);
-
- //animations = memnew( ItemList );
-
-
- load = memnew( Button );
- load->set_tooltip(TTR("Load Resource"));
- hbc->add_child(load);
-
- paste = memnew( Button );
- paste->set_text(TTR("Paste"));
- hbc->add_child(paste);
-
- empty = memnew( Button );
- empty->set_text(TTR("Insert Empty (Before)"));
- hbc->add_child(empty);
-
- empty2 = memnew( Button );
- empty2->set_text(TTR("Insert Empty (After)"));
- hbc->add_child(empty2);
-
- move_up = memnew( Button );
- move_up->set_text(TTR("Up"));
- hbc->add_child(move_up);
-
- move_down = memnew( Button );
- move_down->set_text(TTR("Down"));
- hbc->add_child(move_down);
-
- _delete = memnew( Button );
- hbc->add_child(_delete);
-
- file = memnew( EditorFileDialog );
- add_child(file);
-
-
- tree = memnew( ItemList );
- tree->set_v_size_flags(SIZE_EXPAND_FILL);
- tree->set_icon_mode(ItemList::ICON_MODE_TOP);
-
- int thumbnail_size = 96;
- tree->set_max_columns(0);
- tree->set_icon_mode(ItemList::ICON_MODE_TOP);
- tree->set_fixed_column_width(thumbnail_size*3/2);
- tree->set_max_text_lines(2);
- tree->set_fixed_icon_size(Size2(thumbnail_size,thumbnail_size));
- //tree->set_min_icon_size(Size2(thumbnail_size,thumbnail_size));
- tree->set_drag_forwarding(this);
-
-
-
- sub_vb->add_child(tree);
-
- dialog = memnew( AcceptDialog );
- add_child( dialog );
-
- load->connect("pressed", this,"_load_pressed");
- _delete->connect("pressed", this,"_delete_pressed");
- paste->connect("pressed", this,"_paste_pressed");
- empty->connect("pressed", this,"_empty_pressed");
- empty2->connect("pressed", this,"_empty2_pressed");
- move_up->connect("pressed", this,"_up_pressed");
- move_down->connect("pressed", this,"_down_pressed");
- file->connect("files_selected", this,"_file_load_request");
- //dialog->connect("confirmed", this,"_delete_confirm_pressed");
- //tree->connect("item_selected", this,"_item_edited");
- loading_scene=false;
- sel=-1;
-
- updating=false;
-
- edited_anim="default";
-
-}
-
-
-void SpriteFramesEditorPlugin::edit(Object *p_object) {
-
- frames_editor->set_undo_redo(&get_undo_redo());
- SpriteFrames * s = p_object->cast_to<SpriteFrames>();
- if (!s)
- return;
-
- frames_editor->edit(s);
-}
-
-bool SpriteFramesEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("SpriteFrames");
-}
-
-void SpriteFramesEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- button->show();
- editor->make_bottom_panel_item_visible(frames_editor);
- //frames_editor->set_process(true);
- } else {
-
- button->hide();
- if (frames_editor->is_visible_in_tree())
- editor->hide_bottom_panel();
-
- //frames_editor->set_process(false);
- }
-
-}
-
-SpriteFramesEditorPlugin::SpriteFramesEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- frames_editor = memnew( SpriteFramesEditor );
- frames_editor->set_custom_minimum_size(Size2(0,300));
- button=editor->add_bottom_panel_item("SpriteFrames",frames_editor);
- button->hide();
-
-
-
-}
-
-
-SpriteFramesEditorPlugin::~SpriteFramesEditorPlugin()
-{
-}
-
-
diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.h b/tools/editor/plugins/sprite_frames_editor_plugin.h
deleted file mode 100644
index 36a022b7e4..0000000000
--- a/tools/editor/plugins/sprite_frames_editor_plugin.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*************************************************************************/
-/* sprite_frames_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SPRITE_FRAMES_EDITOR_PLUGIN_H
-#define SPRITE_FRAMES_EDITOR_PLUGIN_H
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/gui/tree.h"
-#include "scene/2d/animated_sprite.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/split_container.h"
-
-
-class SpriteFramesEditor : public PanelContainer {
-
- GDCLASS(SpriteFramesEditor, PanelContainer );
-
- Button *load;
- Button *_delete;
- Button *paste;
- Button *empty;
- Button *empty2;
- Button *move_up;
- Button *move_down;
- ItemList *tree;
- bool loading_scene;
- int sel;
-
- HSplitContainer *split;
- Button *new_anim;
- Button *remove_anim;
-
-
- Tree *animations;
- SpinBox *anim_speed;
- CheckButton *anim_loop;
-
- EditorFileDialog *file;
-
- AcceptDialog *dialog;
-
- SpriteFrames *frames;
-
- StringName edited_anim;
-
- void _load_pressed();
- void _load_scene_pressed();
- void _file_load_request(const PoolVector<String>& p_path, int p_at_pos=-1);
- void _paste_pressed();
- void _empty_pressed();
- void _empty2_pressed();
- void _delete_pressed();
- void _delete_confirm_pressed();
- void _up_pressed();
- void _down_pressed();
- void _update_library(bool p_skip_selector=false);
- void _item_edited();
-
-
-
- void _animation_select();
- void _animation_name_edited();
- void _animation_add();
- void _animation_remove();
- void _animation_loop_changed();
- void _animation_fps_changed(double p_value);
-
- bool updating;
-
- UndoRedo *undo_redo;
-
- bool _is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const;
- Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
- bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
- void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
-
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
- void set_undo_redo(UndoRedo *p_undo_redo) {undo_redo=p_undo_redo; }
-
- void edit(SpriteFrames* p_frames);
- SpriteFramesEditor();
-};
-
-class SpriteFramesEditorPlugin : public EditorPlugin {
-
- GDCLASS( SpriteFramesEditorPlugin, EditorPlugin );
-
- SpriteFramesEditor *frames_editor;
- EditorNode *editor;
- Button *button;
-
-public:
-
- virtual String get_name() const { return "SpriteFrames"; }
- 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);
-
- SpriteFramesEditorPlugin(EditorNode *p_node);
- ~SpriteFramesEditorPlugin();
-
-};
-
-#endif // SPRITE_FRAMES_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/stream_editor_plugin.cpp b/tools/editor/plugins/stream_editor_plugin.cpp
deleted file mode 100644
index 991c29b6db..0000000000
--- a/tools/editor/plugins/stream_editor_plugin.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*************************************************************************/
-/* stream_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "stream_editor_plugin.h"
-
-#if 0
-
-void StreamEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- play->set_icon( get_icon("Play","EditorIcons") );
- stop->set_icon( get_icon("Stop","EditorIcons") );
- }
-
-}
-void StreamEditor::_node_removed(Node *p_node) {
-
- if(p_node==node) {
- node=NULL;
- hide();
- }
-
-}
-
-void StreamEditor::_play() {
-
- node->call("play");
-}
-
-void StreamEditor::_stop() {
-
- node->call("stop");
-}
-
-void StreamEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_play"),&StreamEditor::_play);
- ClassDB::bind_method(_MD("_stop"),&StreamEditor::_stop);
-
-}
-
-void StreamEditor::edit(Node *p_stream) {
-
- node=p_stream;
-
-}
-StreamEditor::StreamEditor() {
-
- play = memnew( Button );
-
-
- play->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,60);
- play->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,40);
- play->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
- play->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
-
- add_child(play);
-
- stop = memnew( Button );
-
- stop->set_pos(Point2( 35, 5 ));
- stop->set_anchor_and_margin(MARGIN_LEFT,Control::ANCHOR_END,30);
- stop->set_anchor_and_margin(MARGIN_RIGHT,Control::ANCHOR_END,10);
- stop->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,0);
- stop->set_anchor_and_margin(MARGIN_BOTTOM,Control::ANCHOR_BEGIN,0);
- add_child(stop);
-
-
- play->connect("pressed", this,"_play");
- stop->connect("pressed", this,"_stop");
-
-}
-
-
-void StreamEditorPlugin::edit(Object *p_object) {
-
- stream_editor->edit(p_object->cast_to<Node>());
-}
-
-bool StreamEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("StreamPlayer") || p_object->is_class("SpatialStreamPlayer");
-}
-
-void StreamEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- stream_editor->show();
- stream_editor->set_fixed_process(true);
- } else {
-
- stream_editor->hide();
- stream_editor->set_fixed_process(false);
- stream_editor->edit(NULL);
- }
-
-}
-
-StreamEditorPlugin::StreamEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- stream_editor = memnew( StreamEditor );
- editor->get_viewport()->add_child(stream_editor);
-
- stream_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
- stream_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
- stream_editor->set_margin(MARGIN_LEFT,60);
- stream_editor->set_margin(MARGIN_RIGHT,0);
- stream_editor->set_margin(MARGIN_TOP,0);
- stream_editor->set_margin(MARGIN_BOTTOM,10);
-
-
- stream_editor->hide();
-
-
-
-}
-
-
-StreamEditorPlugin::~StreamEditorPlugin()
-{
-}
-
-#endif
diff --git a/tools/editor/plugins/stream_editor_plugin.h b/tools/editor/plugins/stream_editor_plugin.h
deleted file mode 100644
index cc853d4661..0000000000
--- a/tools/editor/plugins/stream_editor_plugin.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*************************************************************************/
-/* stream_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 STREAM_EDITOR_PLUGIN_H
-#define STREAM_EDITOR_PLUGIN_H
-
-#if 0
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/audio/stream_player.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class StreamEditor : public Control {
-
- GDCLASS(StreamEditor, Control );
-
- Button * play;
- Button * stop;
-
- Panel *panel;
- Node *node;
-
- void _play();
- void _stop();
-protected:
- void _notification(int p_what);
- void _node_removed(Node *p_node);
- static void _bind_methods();
-public:
-
- void edit(Node *p_stream);
- StreamEditor();
-};
-
-class StreamEditorPlugin : public EditorPlugin {
-
- GDCLASS( StreamEditorPlugin, EditorPlugin );
-
- StreamEditor *stream_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "Stream"; }
- 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);
-
- StreamEditorPlugin(EditorNode *p_node);
- ~StreamEditorPlugin();
-
-};
-
-#endif // STREAM_EDITOR_PLUGIN_H
-#endif
diff --git a/tools/editor/plugins/style_box_editor_plugin.h b/tools/editor/plugins/style_box_editor_plugin.h
deleted file mode 100644
index 29e98efd8b..0000000000
--- a/tools/editor/plugins/style_box_editor_plugin.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*************************************************************************/
-/* style_box_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 STYLE_BOX_EDITOR_PLUGIN_H
-#define STYLE_BOX_EDITOR_PLUGIN_H
-
-#include "scene/resources/style_box.h"
-#include "scene/gui/texture_rect.h"
-#include "scene/gui/option_button.h"
-#include "tools/editor/editor_node.h"
-
-
-class StyleBoxEditor : public Control {
-
- GDCLASS( StyleBoxEditor, Control );
-
- Panel *panel;
- Panel *preview;
-
- Ref<StyleBox> stylebox;
-
- void _sb_changed();
-
-protected:
-
-
- static void _bind_methods();
-public:
-
- void edit(const Ref<StyleBox>& p_stylebox);
-
- StyleBoxEditor();
-};
-
-
-
-class StyleBoxEditorPlugin : public EditorPlugin {
-
- GDCLASS( StyleBoxEditorPlugin, EditorPlugin );
-
- StyleBoxEditor *stylebox_editor;
- EditorNode *editor;
- Button *button;
-
-public:
-
- virtual String get_name() const { return "StyleBox"; }
- 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);
-
- StyleBoxEditorPlugin(EditorNode *p_node);
-
-};
-
-
-#endif // STYLE_BOX_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/texture_editor_plugin.cpp b/tools/editor/plugins/texture_editor_plugin.cpp
deleted file mode 100644
index 82cba7ac0e..0000000000
--- a/tools/editor/plugins/texture_editor_plugin.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*************************************************************************/
-/* texture_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "texture_editor_plugin.h"
-
-#include "io/resource_loader.h"
-#include "globals.h"
-#include "tools/editor/editor_settings.h"
-
-void TextureEditor::_gui_input(InputEvent p_event) {
-
-
-}
-
-void TextureEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
- }
-
-
- if (p_what==NOTIFICATION_READY) {
-
- //get_scene()->connect("node_removed",this,"_node_removed");
-
- }
-
- if (p_what==NOTIFICATION_DRAW) {
-
-
- Ref<Texture> checkerboard = get_icon("Checkerboard","EditorIcons");
- Size2 size = get_size();
-
- draw_texture_rect(checkerboard,Rect2(Point2(),size),true);
-
- int tex_width = texture->get_width() * size.height / texture ->get_height();
- int tex_height = size.height;
-
- if (tex_width>size.width) {
- tex_width=size.width;
- tex_height=texture->get_height() * tex_width / texture->get_width();
- }
-
- int ofs_x = (size.width - tex_width)/2;
- int ofs_y = (size.height - tex_height)/2;
-
- draw_texture_rect(texture,Rect2(ofs_x,ofs_y,tex_width,tex_height));
-
- Ref<Font> font = get_font("font","Label");
-
- String format;
- if (texture->cast_to<ImageTexture>()) {
- format = Image::get_format_name(texture->cast_to<ImageTexture>()->get_format());
- } else {
- format=texture->get_class();
- }
- String text = itos(texture->get_width())+"x"+itos(texture->get_height())+" "+format;
-
- Size2 rect = font->get_string_size(text);
-
- Vector2 draw_from = size-rect+Size2(-2,font->get_ascent()-2);
- if (draw_from.x<0)
- draw_from.x=0;
-
- draw_string(font,draw_from+Vector2(2,2),text,Color(0,0,0,0.5),size.width);
- draw_string(font,draw_from-Vector2(2,2),text,Color(0,0,0,0.5),size.width);
- draw_string(font,draw_from,text,Color(1,1,1,1),size.width);
- }
-}
-
-
-
-void TextureEditor::edit(Ref<Texture> p_texture) {
-
- texture=p_texture;
-
- if (!texture.is_null())
- update();
- else {
-
- hide();
- }
-
-}
-
-
-
-void TextureEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_gui_input"),&TextureEditor::_gui_input);
-
-}
-
-TextureEditor::TextureEditor() {
-
- set_custom_minimum_size(Size2(1,150));
-
-}
-
-
-void TextureEditorPlugin::edit(Object *p_object) {
-
- Texture * s = p_object->cast_to<Texture>();
- if (!s)
- return;
-
- texture_editor->edit(Ref<Texture>(s));
-}
-
-bool TextureEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("Texture");
-}
-
-void TextureEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- texture_editor->show();
- //texture_editor->set_process(true);
- } else {
-
- texture_editor->hide();
- //texture_editor->set_process(false);
- }
-
-}
-
-TextureEditorPlugin::TextureEditorPlugin(EditorNode *p_node) {
-
- editor=p_node;
- texture_editor = memnew( TextureEditor );
- add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM,texture_editor);
- texture_editor->hide();
-
-
-
-}
-
-
-TextureEditorPlugin::~TextureEditorPlugin()
-{
-}
-
-
diff --git a/tools/editor/plugins/texture_editor_plugin.h b/tools/editor/plugins/texture_editor_plugin.h
deleted file mode 100644
index 456a5249de..0000000000
--- a/tools/editor/plugins/texture_editor_plugin.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*************************************************************************/
-/* texture_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 TEXTURE_EDITOR_PLUGIN_H
-#define TEXTURE_EDITOR_PLUGIN_H
-
-
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/resources/texture.h"
-
-
-class TextureEditor : public Control {
-
- GDCLASS(TextureEditor, Control);
-
-
- Ref<Texture> texture;
-
-protected:
- void _notification(int p_what);
- void _gui_input(InputEvent p_event);
- static void _bind_methods();
-public:
-
- void edit(Ref<Texture> p_texture);
- TextureEditor();
-};
-
-
-class TextureEditorPlugin : public EditorPlugin {
-
- GDCLASS( TextureEditorPlugin, EditorPlugin );
-
- TextureEditor *texture_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "Texture"; }
- 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);
-
- TextureEditorPlugin(EditorNode *p_node);
- ~TextureEditorPlugin();
-
-};
-
-#endif // TEXTURE_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/texture_region_editor_plugin.cpp b/tools/editor/plugins/texture_region_editor_plugin.cpp
deleted file mode 100644
index 9b0ca0a482..0000000000
--- a/tools/editor/plugins/texture_region_editor_plugin.cpp
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*************************************************************************/
-/* texture_region_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Author: Mariano Suligoy */
-/* */
-/* 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 "texture_region_editor_plugin.h"
-
-#include "core/core_string_names.h"
-#include "scene/gui/check_box.h"
-#include "os/input.h"
-#include "os/keyboard.h"
-
-void draw_margin_line(Control *edit_draw, Vector2 from, Vector2 to){
- Vector2 line = (to-from).normalized() * 10;
- while ((to - from).length_squared() > 200) {
- edit_draw->draw_line(from, from + line,Color(0.97, 0.2, 0.2),2);
- from += line*2;
- }
-}
-
-void TextureRegionEditor::_region_draw()
-{
- Ref<Texture> base_tex = NULL;
- if(node_sprite)
- base_tex = node_sprite->get_texture();
- else if(node_patch9)
- base_tex = node_patch9->get_texture();
- else if(obj_styleBox.is_valid())
- base_tex = obj_styleBox->get_texture();
- else if(atlas_tex.is_valid())
- base_tex = atlas_tex->get_atlas();
- if (base_tex.is_null())
- return;
-
- Transform2D mtx;
- mtx.elements[2]=-draw_ofs;
- mtx.scale_basis(Vector2(draw_zoom,draw_zoom));
-
- VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),mtx);
- edit_draw->draw_texture(base_tex,Point2());
- VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),Transform2D());
-
- if (snap_mode == SNAP_GRID) {
- Size2 s = edit_draw->get_size();
- int last_cell;
-
- if (snap_step.x!=0) {
- if (snap_separation.x == 0)
- for(int i=0;i<s.width;i++) {
- int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- else
- for(int i=0;i<s.width;i++) {
- int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/(snap_step.x+snap_separation.x)));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- edit_draw->draw_rect(Rect2(i-snap_separation.x*draw_zoom,0,snap_separation.x*draw_zoom,s.height),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- }
-
- if (snap_step.y!=0) {
- if (snap_separation.y == 0)
- for(int i=0;i<s.height;i++) {
- int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- else
- for(int i=0;i<s.height;i++) {
- int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/(snap_step.y+snap_separation.y)));
- if (i==0)
- last_cell=cell;
- if (last_cell!=cell)
- edit_draw->draw_rect(Rect2(0,i-snap_separation.y*draw_zoom,s.width,snap_separation.y*draw_zoom),Color(0.3,0.7,1,0.3));
- last_cell=cell;
- }
- }
- } else if (snap_mode == SNAP_AUTOSLICE) {
- for (List<Rect2>::Element *E = autoslice_cache.front();E;E=E->next()) {
- Rect2 r = E->get();
- Vector2 endpoints[4]={
- mtx.basis_xform(r.pos),
- mtx.basis_xform(r.pos+Vector2(r.size.x,0)),
- mtx.basis_xform(r.pos+r.size),
- mtx.basis_xform(r.pos+Vector2(0,r.size.y))
- };
- for(int i=0;i<4;i++) {
- int next = (i+1)%4;
- edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, Color(0.3,0.7,1,1) , 2);
- }
- }
- }
-
- Ref<Texture> select_handle = get_icon("EditorHandle","EditorIcons");
-
- Rect2 scroll_rect(Point2(),mtx.basis_xform(base_tex->get_size()));
- scroll_rect.expand_to(mtx.basis_xform(edit_draw->get_size()));
-
- Vector2 endpoints[4]={
- mtx.basis_xform(rect.pos),
- mtx.basis_xform(rect.pos+Vector2(rect.size.x,0)),
- mtx.basis_xform(rect.pos+rect.size),
- mtx.basis_xform(rect.pos+Vector2(0,rect.size.y))
- };
- Color color(0.9,0.5,0.5);
- for(int i=0;i<4;i++) {
-
- int prev = (i+3)%4;
- int next = (i+1)%4;
-
- Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
- ofs*=1.4144*(select_handle->get_size().width/2);
-
- edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, color , 2);
-
- if (snap_mode != SNAP_AUTOSLICE)
- edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs);
-
- ofs = (endpoints[next]-endpoints[i])/2;
- ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2);
-
- if (snap_mode != SNAP_AUTOSLICE)
- edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs);
-
- scroll_rect.expand_to(endpoints[i]);
- }
-
- scroll_rect=scroll_rect.grow(200);
- updating_scroll=true;
- hscroll->set_min(scroll_rect.pos.x);
- hscroll->set_max(scroll_rect.pos.x+scroll_rect.size.x);
- hscroll->set_page(edit_draw->get_size().x);
- hscroll->set_value(draw_ofs.x);
- hscroll->set_step(0.001);
-
- vscroll->set_min(scroll_rect.pos.y);
- vscroll->set_max(scroll_rect.pos.y+scroll_rect.size.y);
- vscroll->set_page(edit_draw->get_size().y);
- vscroll->set_value(draw_ofs.y);
- vscroll->set_step(0.001);
- updating_scroll=false;
-
- float margins[4];
- if (node_patch9 || obj_styleBox.is_valid()) {
- if (node_patch9) {
- margins[0] = node_patch9->get_patch_margin(MARGIN_TOP);
- margins[1] = node_patch9->get_patch_margin(MARGIN_BOTTOM);
- margins[2] = node_patch9->get_patch_margin(MARGIN_LEFT);
- margins[3] = node_patch9->get_patch_margin(MARGIN_RIGHT);
- } else if (obj_styleBox.is_valid()) {
- margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
- margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
- margins[2] = obj_styleBox->get_margin_size(MARGIN_LEFT);
- margins[3] = obj_styleBox->get_margin_size(MARGIN_RIGHT);
- }
- Vector2 pos[4] = {
- mtx.basis_xform(Vector2(0,margins[0]))+Vector2(0,endpoints[0].y-draw_ofs.y),
- -mtx.basis_xform(Vector2(0,margins[1]))+Vector2(0,endpoints[2].y-draw_ofs.y),
- mtx.basis_xform(Vector2(margins[2],0))+Vector2(endpoints[0].x-draw_ofs.x,0),
- -mtx.basis_xform(Vector2(margins[3],0))+Vector2(endpoints[2].x-draw_ofs.x,0)};
-
- draw_margin_line(edit_draw,pos[0],pos[0]+Vector2(edit_draw->get_size().x,0));
- draw_margin_line(edit_draw,pos[1],pos[1]+Vector2(edit_draw->get_size().x,0));
- draw_margin_line(edit_draw,pos[2],pos[2]+Vector2(0,edit_draw->get_size().y));
- draw_margin_line(edit_draw,pos[3],pos[3]+Vector2(0,edit_draw->get_size().y));
- }
-}
-
-void TextureRegionEditor::_region_input(const InputEvent& p_input)
-{
- Transform2D mtx;
- mtx.elements[2]=-draw_ofs;
- mtx.scale_basis(Vector2(draw_zoom,draw_zoom));
-
- Vector2 endpoints[8]={
- mtx.xform(rect.pos)+Vector2(-4,-4),
- mtx.xform(rect.pos+Vector2(rect.size.x/2,0))+Vector2(0,-4),
- mtx.xform(rect.pos+Vector2(rect.size.x,0))+Vector2(4,-4),
- mtx.xform(rect.pos+Vector2(rect.size.x,rect.size.y/2))+Vector2(4,0),
- mtx.xform(rect.pos+rect.size)+Vector2(4,4),
- mtx.xform(rect.pos+Vector2(rect.size.x/2,rect.size.y))+Vector2(0,4),
- mtx.xform(rect.pos+Vector2(0,rect.size.y))+Vector2(-4,4),
- mtx.xform(rect.pos+Vector2(0,rect.size.y/2))+Vector2(-4,0)
- };
-
- if (p_input.type==InputEvent::MOUSE_BUTTON) {
-
- const InputEventMouseButton &mb=p_input.mouse_button;
-
- if (mb.button_index==BUTTON_LEFT) {
-
- if (mb.pressed) {
- if (node_patch9 || obj_styleBox.is_valid()) {
- edited_margin = -1;
- float margins[4];
- if (node_patch9) {
- margins[0] = node_patch9->get_patch_margin(MARGIN_TOP);
- margins[1] = node_patch9->get_patch_margin(MARGIN_BOTTOM);
- margins[2] = node_patch9->get_patch_margin(MARGIN_LEFT);
- margins[3] = node_patch9->get_patch_margin(MARGIN_RIGHT);
- } else if (obj_styleBox.is_valid()) {
- margins[0] = obj_styleBox->get_margin_size(MARGIN_TOP);
- margins[1] = obj_styleBox->get_margin_size(MARGIN_BOTTOM);
- margins[2] = obj_styleBox->get_margin_size(MARGIN_LEFT);
- margins[3] = obj_styleBox->get_margin_size(MARGIN_RIGHT);
- }
- Vector2 pos[4] = {
- mtx.basis_xform(rect.pos+Vector2(0,margins[0]))-draw_ofs,
- mtx.basis_xform(rect.pos+rect.size-Vector2(0,margins[1]))-draw_ofs,
- mtx.basis_xform(rect.pos+Vector2(margins[2],0))-draw_ofs,
- mtx.basis_xform(rect.pos+rect.size-Vector2(margins[3],0))-draw_ofs};
- if (Math::abs(mb.y - pos[0].y) < 8) {
- edited_margin = 0;
- prev_margin = margins[0];
- } else if (Math::abs(mb.y - pos[1].y) < 8) {
- edited_margin = 1;
- prev_margin = margins[1];
- } else if (Math::abs(mb.x - pos[2].x) < 8) {
- edited_margin = 2;
- prev_margin = margins[2];
- } else if (Math::abs(mb.x - pos[3].x) < 8) {
- edited_margin = 3;
- prev_margin = margins[3];
- }
- if (edited_margin >= 0) {
- drag_from=Vector2(mb.x,mb.y);
- drag=true;
- }
- }
- if ( edited_margin < 0 && snap_mode == SNAP_AUTOSLICE) {
- Vector2 point = mtx.affine_inverse().xform(Vector2(mb.x,mb.y));
- for (List<Rect2>::Element *E=autoslice_cache.front();E;E=E->next()) {
- if (E->get().has_point(point)) {
- rect = E->get();
- if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)&&!(Input::get_singleton()->is_key_pressed(KEY_SHIFT|KEY_ALT))) {
- Rect2 r;
- if(node_sprite )
- r=node_sprite->get_region_rect();
- else if(node_patch9)
- r=node_patch9->get_region_rect();
- else if(obj_styleBox.is_valid())
- r=obj_styleBox->get_region_rect();
- else if(atlas_tex.is_valid())
- r =atlas_tex->get_region();
- rect.expand_to(r.pos);
- rect.expand_to(r.pos+r.size);
- }
- undo_redo->create_action("Set Region Rect");
- if(node_sprite){
- undo_redo->add_do_method(node_sprite ,"set_region_rect",rect);
- undo_redo->add_undo_method(node_sprite,"set_region_rect",node_sprite->get_region_rect());
- } else if(node_patch9){
- undo_redo->add_do_method(node_patch9 ,"set_region_rect",rect);
- undo_redo->add_undo_method(node_patch9,"set_region_rect",node_patch9->get_region_rect());
- } else if (obj_styleBox.is_valid()) {
- undo_redo->add_do_method(obj_styleBox.ptr(),"set_region_rect",rect);
- undo_redo->add_undo_method(obj_styleBox.ptr(),"set_region_rect",obj_styleBox->get_region_rect());
- } else if (atlas_tex.is_valid()) {
- undo_redo->add_do_method(atlas_tex.ptr(),"set_region",rect);
- undo_redo->add_undo_method(atlas_tex.ptr(),"set_region",atlas_tex->get_region());
- }
- undo_redo->add_do_method(edit_draw,"update");
- undo_redo->add_undo_method(edit_draw,"update");
- undo_redo->commit_action();
- break;
- }
- }
- } else if (edited_margin < 0) {
- drag_from=mtx.affine_inverse().xform(Vector2(mb.x,mb.y));
- if (snap_mode == SNAP_PIXEL)
- drag_from = drag_from.snapped(Vector2(1,1));
- else if (snap_mode == SNAP_GRID)
- drag_from=snap_point(drag_from);
- drag=true;
- if(node_sprite )
- rect_prev=node_sprite->get_region_rect();
- else if(node_patch9)
- rect_prev=node_patch9->get_region_rect();
- else if(obj_styleBox.is_valid())
- rect_prev=obj_styleBox->get_region_rect();
- else if(atlas_tex.is_valid())
- rect_prev=atlas_tex->get_region();
-
- for (int i=0; i<8;i++) {
- Vector2 tuv=endpoints[i];
- if (tuv.distance_to(Vector2(mb.x,mb.y))<8) {
- drag_index=i;
- }
- }
-
- if (drag_index==-1) {
- creating = true;
- rect = Rect2(drag_from,Size2());
- }
- }
-
- } else if (drag) {
- if (edited_margin >= 0) {
- undo_redo->create_action("Set Margin");
- static Margin m[4] = {MARGIN_TOP,MARGIN_BOTTOM,MARGIN_LEFT,MARGIN_RIGHT};
- if (node_patch9) {
- undo_redo->add_do_method(node_patch9 ,"set_patch_margin",m[edited_margin],node_patch9->get_patch_margin(m[edited_margin]));
- undo_redo->add_undo_method(node_patch9,"set_patch_margin",m[edited_margin],prev_margin);
- } else if (obj_styleBox.is_valid()) {
- undo_redo->add_do_method(obj_styleBox.ptr() ,"set_margin_size",m[edited_margin],obj_styleBox->get_margin_size(m[edited_margin]));
- undo_redo->add_undo_method(obj_styleBox.ptr(),"set_margin_size",m[edited_margin],prev_margin);
- obj_styleBox->emit_signal(CoreStringNames::get_singleton()->changed);
- }
- edited_margin = -1;
- } else {
- undo_redo->create_action("Set Region Rect");
- if(node_sprite){
- undo_redo->add_do_method(node_sprite ,"set_region_rect",node_sprite->get_region_rect());
- undo_redo->add_undo_method(node_sprite,"set_region_rect",rect_prev);
- }
- else if(atlas_tex.is_valid()){
- undo_redo->add_do_method(atlas_tex.ptr() ,"set_region",atlas_tex->get_region());
- undo_redo->add_undo_method(atlas_tex.ptr(),"set_region",rect_prev);
- }
- else if(node_patch9){
- } else if(node_patch9){
- undo_redo->add_do_method(node_patch9 ,"set_region_rect",node_patch9->get_region_rect());
- undo_redo->add_undo_method(node_patch9,"set_region_rect",rect_prev);
- } else if (obj_styleBox.is_valid()) {
- undo_redo->add_do_method(obj_styleBox.ptr() ,"set_region_rect",obj_styleBox->get_region_rect());
- undo_redo->add_undo_method(obj_styleBox.ptr(),"set_region_rect",rect_prev);
- }
- drag_index = -1;
- }
- undo_redo->add_do_method(edit_draw,"update");
- undo_redo->add_undo_method(edit_draw,"update");
- undo_redo->commit_action();
- drag=false;
- creating = false;
- }
-
- } else if (mb.button_index==BUTTON_RIGHT && mb.pressed) {
-
- if (drag) {
- drag=false;
- if (edited_margin >= 0) {
- static Margin m[4] = {MARGIN_TOP,MARGIN_BOTTOM,MARGIN_LEFT,MARGIN_RIGHT};
- if (node_patch9)
- node_patch9->set_patch_margin(m[edited_margin],prev_margin);
- if (obj_styleBox.is_valid())
- obj_styleBox->set_margin_size(m[edited_margin],prev_margin);
- edited_margin = -1;
- } else {
- apply_rect(rect_prev);
- rect=rect_prev;
- edit_draw->update();
- drag_index = -1;
- }
- }
- } else if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) {
- _zoom_in();
- } else if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) {
- _zoom_out();
- }
- } else if (p_input.type==InputEvent::MOUSE_MOTION) {
-
- const InputEventMouseMotion &mm=p_input.mouse_motion;
-
- if (mm.button_mask&BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
-
- Vector2 draged(mm.relative_x,mm.relative_y);
- hscroll->set_value( hscroll->get_value()-draged.x );
- vscroll->set_value( vscroll->get_value()-draged.y );
-
- } else if (drag) {
-
- if (edited_margin >= 0) {
- float new_margin;
- if (edited_margin == 0)
- new_margin = prev_margin + (mm.y-drag_from.y) / draw_zoom;
- else if (edited_margin == 1)
- new_margin = prev_margin - (mm.y-drag_from.y) / draw_zoom;
- else if (edited_margin == 2)
- new_margin = prev_margin + (mm.x-drag_from.x) / draw_zoom;
- else if (edited_margin == 3)
- new_margin = prev_margin - (mm.x-drag_from.x) / draw_zoom;
- if (new_margin < 0)
- new_margin = 0;
- static Margin m[4] = {MARGIN_TOP,MARGIN_BOTTOM,MARGIN_LEFT,MARGIN_RIGHT};
- if (node_patch9)
- node_patch9->set_patch_margin(m[edited_margin],new_margin);
- if (obj_styleBox.is_valid())
- obj_styleBox->set_margin_size(m[edited_margin],new_margin);
- } else {
- Vector2 new_pos = mtx.affine_inverse().xform(Vector2(mm.x,mm.y));
- if (snap_mode == SNAP_PIXEL)
- new_pos = new_pos.snapped(Vector2(1,1));
- else if (snap_mode == SNAP_GRID)
- new_pos=snap_point(new_pos);
-
- if (creating) {
- rect = Rect2(drag_from,Size2());
- rect.expand_to(new_pos);
- apply_rect(rect);
- edit_draw->update();
- return;
- }
-
- switch(drag_index) {
- case 0: {
- Vector2 p=rect_prev.pos+rect_prev.size;
- rect = Rect2(p,Size2());
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
- case 1: {
- Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
- rect = Rect2(p,Size2(rect_prev.size.x,0));
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
- case 2: {
- Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
- rect = Rect2(p,Size2());
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
- case 3: {
- Vector2 p=rect_prev.pos;
- rect = Rect2(p,Size2(0,rect_prev.size.y));
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
- case 4: {
- Vector2 p=rect_prev.pos;
- rect = Rect2(p,Size2());
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
- case 5: {
- Vector2 p=rect_prev.pos;
- rect = Rect2(p,Size2(rect_prev.size.x,0));
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
- case 6: {
- Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
- rect = Rect2(p,Size2());
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
- case 7: {
- Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
- rect = Rect2(p,Size2(0,rect_prev.size.y));
- rect.expand_to(new_pos);
- apply_rect(rect);
- } break;
-
- }
- }
- edit_draw->update();
- }
-
- }
-}
-
-void TextureRegionEditor::_scroll_changed(float)
-{
- if (updating_scroll)
- return;
-
- draw_ofs.x=hscroll->get_value();
- draw_ofs.y=vscroll->get_value();
- edit_draw->update();
-}
-
-void TextureRegionEditor::_set_snap_mode(int p_mode)
-{
- snap_mode_button->get_popup()->set_item_checked(snap_mode,false);
- snap_mode = p_mode;
- snap_mode_button->set_text(snap_mode_button->get_popup()->get_item_text(p_mode));
- snap_mode_button->get_popup()->set_item_checked(snap_mode,true);
-
- if (snap_mode == SNAP_GRID)
- hb_grid->show();
- else
- hb_grid->hide();
-
- edit_draw->update();
-}
-
-void TextureRegionEditor::_set_snap_off_x(float p_val)
-{
- snap_offset.x=p_val;
- edit_draw->update();
-}
-
-void TextureRegionEditor::_set_snap_off_y(float p_val)
-{
- snap_offset.y=p_val;
- edit_draw->update();
-}
-
-void TextureRegionEditor::_set_snap_step_x(float p_val)
-{
- snap_step.x=p_val;
- edit_draw->update();
-}
-
-void TextureRegionEditor::_set_snap_step_y(float p_val)
-{
- snap_step.y=p_val;
- edit_draw->update();
-}
-
-void TextureRegionEditor::_set_snap_sep_x(float p_val)
-{
- snap_separation.x = p_val;
- edit_draw->update();
-}
-
-void TextureRegionEditor::_set_snap_sep_y(float p_val)
-{
- snap_separation.y = p_val;
- edit_draw->update();
-}
-
-void TextureRegionEditor::_zoom_in()
-{
- if (draw_zoom < 8) {
- draw_zoom *= 2;
- edit_draw->update();
- }
-}
-
-void TextureRegionEditor::_zoom_reset()
-{
- if (draw_zoom == 1) return;
- draw_zoom = 1;
- edit_draw->update();
-}
-
-void TextureRegionEditor::_zoom_out()
-{
- if (draw_zoom > 0.25) {
- draw_zoom /= 2;
- edit_draw->update();
- }
-}
-
-void TextureRegionEditor::apply_rect(const Rect2& rect){
- if(node_sprite)
- node_sprite->set_region_rect(rect);
- else if(node_patch9)
- node_patch9->set_region_rect(rect);
- else if(obj_styleBox.is_valid())
- obj_styleBox->set_region_rect(rect);
- else if(atlas_tex.is_valid())
- atlas_tex->set_region(rect);
-}
-
-void TextureRegionEditor::_notification(int p_what)
-{
- switch(p_what) {
- case NOTIFICATION_READY: {
- zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons"));
- zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
- zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons"));
- icon_zoom->set_texture( get_icon("Zoom", "EditorIcons"));
- } break;
- }
-}
-
-void TextureRegionEditor::_node_removed(Object *p_obj)
-{
- if(p_obj == node_sprite || p_obj == node_patch9 || p_obj == obj_styleBox.ptr() || p_obj == atlas_tex.ptr()) {
- node_patch9 = NULL;
- node_sprite = NULL;
- obj_styleBox = Ref<StyleBox>(NULL);
- atlas_tex = Ref<AtlasTexture>(NULL);
- hide();
- }
-}
-
-void TextureRegionEditor::_bind_methods()
-{
- ClassDB::bind_method(_MD("_edit_region"),&TextureRegionEditor::_edit_region);
- ClassDB::bind_method(_MD("_region_draw"),&TextureRegionEditor::_region_draw);
- ClassDB::bind_method(_MD("_region_input"),&TextureRegionEditor::_region_input);
- ClassDB::bind_method(_MD("_scroll_changed"),&TextureRegionEditor::_scroll_changed);
- ClassDB::bind_method(_MD("_node_removed"),&TextureRegionEditor::_node_removed);
- ClassDB::bind_method(_MD("_set_snap_mode"),&TextureRegionEditor::_set_snap_mode);
- ClassDB::bind_method(_MD("_set_snap_off_x"),&TextureRegionEditor::_set_snap_off_x);
- ClassDB::bind_method(_MD("_set_snap_off_y"),&TextureRegionEditor::_set_snap_off_y);
- ClassDB::bind_method(_MD("_set_snap_step_x"),&TextureRegionEditor::_set_snap_step_x);
- ClassDB::bind_method(_MD("_set_snap_step_y"),&TextureRegionEditor::_set_snap_step_y);
- ClassDB::bind_method(_MD("_set_snap_sep_x"),&TextureRegionEditor::_set_snap_sep_x);
- ClassDB::bind_method(_MD("_set_snap_sep_y"),&TextureRegionEditor::_set_snap_sep_y);
- ClassDB::bind_method(_MD("_zoom_in"),&TextureRegionEditor::_zoom_in);
- ClassDB::bind_method(_MD("_zoom_reset"),&TextureRegionEditor::_zoom_reset);
- ClassDB::bind_method(_MD("_zoom_out"),&TextureRegionEditor::_zoom_out);
-}
-
-void TextureRegionEditor::edit(Object *p_obj)
-{
- if (node_sprite && node_sprite->is_connected("texture_changed",this,"_edit_region"))
- node_sprite->disconnect("texture_changed",this,"_edit_region");
- if (node_patch9 && node_patch9->is_connected("texture_changed",this,"_edit_region"))
- node_patch9->disconnect("texture_changed",this,"_edit_region");
- if (obj_styleBox.is_valid() && obj_styleBox->is_connected("texture_changed",this,"_edit_region"))
- obj_styleBox->disconnect("texture_changed",this,"_edit_region");
- if (atlas_tex.is_valid() && atlas_tex->is_connected("atlas_changed",this,"_edit_region"))
- atlas_tex->disconnect("atlas_changed",this,"_edit_region");
- if (p_obj) {
- node_sprite = p_obj->cast_to<Sprite>();
- node_patch9 = p_obj->cast_to<NinePatchRect>();
- if (p_obj->cast_to<StyleBoxTexture>())
- obj_styleBox = Ref<StyleBoxTexture>(p_obj->cast_to<StyleBoxTexture>());
- if (p_obj->cast_to<AtlasTexture>()) {
- atlas_tex = Ref<AtlasTexture>(p_obj->cast_to<AtlasTexture>());
- atlas_tex->connect("atlas_changed",this,"_edit_region");
- } else {
- p_obj->connect("texture_changed",this,"_edit_region");
- }
- p_obj->add_change_receptor(this);
- p_obj->connect("tree_exited",this,"_node_removed",varray(p_obj),CONNECT_ONESHOT);
- _edit_region();
- } else {
- if(node_sprite)
- node_sprite->disconnect("tree_exited",this,"_node_removed");
- else if(node_patch9)
- node_patch9->disconnect("tree_exited",this,"_node_removed");
- else if(obj_styleBox.is_valid())
- obj_styleBox->disconnect("tree_exited",this,"_node_removed");
- else if(atlas_tex.is_valid())
- atlas_tex->disconnect("tree_exited",this,"_node_removed");
-
- node_sprite = NULL;
- node_patch9 = NULL;
- obj_styleBox = Ref<StyleBoxTexture>(NULL);
- atlas_tex = Ref<AtlasTexture>(NULL);
- }
- edit_draw->update();
-}
-
-void TextureRegionEditor::_changed_callback(Object *p_changed, const char *p_prop) {
- if ((String)p_prop == "region_rect") {
- _edit_region();
- }
-}
-
-void TextureRegionEditor::_edit_region()
-{
- Ref<Texture> texture = NULL;
- if(node_sprite )
- texture = node_sprite->get_texture();
- else if(node_patch9 )
- texture = node_patch9->get_texture();
- else if(obj_styleBox.is_valid())
- texture = obj_styleBox->get_texture();
- else if(atlas_tex.is_valid())
- texture = atlas_tex->get_atlas();
-
- if (texture.is_null()) {
- return;
- }
-
- autoslice_cache.clear();
- Image i;
- if (i.load(texture->get_path()) == OK) {
- BitMap bm;
- bm.create_from_image_alpha(i);
- for (int y = 0; y < i.get_height(); y++) {
- for (int x = 0; x < i.get_width(); x++) {
- if (bm.get_bit(Point2(x,y))) {
- bool found = false;
- for (List<Rect2>::Element *E = autoslice_cache.front(); E; E=E->next()) {
- Rect2 grown = E->get().grow(1.5);
- if (grown.has_point(Point2(x,y))) {
- E->get().expand_to(Point2(x,y));
- E->get().expand_to(Point2(x+1,y+1));
- x = E->get().pos.x+E->get().size.x-1;
- bool merged = true;
- while (merged) {
- merged = false;
- bool queue_erase = false;
- for (List<Rect2>::Element *F = autoslice_cache.front(); F; F=F->next()) {
- if (queue_erase){
- autoslice_cache.erase(F->prev());
- queue_erase = false;
- }
- if (F==E)
- continue;
- if (E->get().grow(1).intersects(F->get())) {
- E->get().expand_to(F->get().pos);
- E->get().expand_to(F->get().pos+F->get().size);
- if (F->prev()) {
- F=F->prev();
- autoslice_cache.erase(F->next());
- } else {
- queue_erase = true;
- //Cant delete the first rect in the list.
- }
- merged = true;
- }
- }
- }
- found = true;
- break;
- }
- }
- if (!found) {
- Rect2 new_rect(x,y,1,1);
- autoslice_cache.push_back(new_rect);
- }
- }
- }
- }
- }
-
-
- if(node_sprite )
- rect = node_sprite->get_region_rect();
- else if(node_patch9 )
- rect = node_patch9->get_region_rect();
- else if(obj_styleBox.is_valid())
- rect = obj_styleBox->get_region_rect();
- else if (atlas_tex.is_valid())
- rect = atlas_tex->get_region();
-
- edit_draw->update();
-}
-
-inline float _snap_scalar(float p_offset, float p_step, float separation, float p_target) {
- if (p_step != 0) {
- float a = Math::stepify(p_target - p_offset, p_step+separation) + p_offset;
- float b = a;
- if (p_target >= 0)
- b -= separation;
- else
- b += p_step;
- return (Math::abs(p_target-a) < Math::abs(p_target-b)) ? a : b;
- }
- return p_target;
-}
-
-Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
- if (snap_mode == SNAP_GRID) {
- p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_separation.x, p_target.x);
- p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_separation.y, p_target.y);
- }
-
- return p_target;
-}
-
-TextureRegionEditor::TextureRegionEditor(EditorNode* p_editor)
-{
- node_sprite = NULL;
- node_patch9 = NULL;
- obj_styleBox = Ref<StyleBoxTexture>(NULL);
- atlas_tex = Ref<AtlasTexture>(NULL);
- editor=p_editor;
- undo_redo = editor->get_undo_redo();
-
- snap_step=Vector2(10,10);
- snap_separation = Vector2(0,0);
- edited_margin = -1;
- drag_index = -1;
- drag=false;
-
- VBoxContainer *main_vb = memnew( VBoxContainer );
- add_child(main_vb);
- main_vb->set_area_as_parent_rect(0);
- HBoxContainer *hb_tools = memnew( HBoxContainer );
- main_vb->add_child(hb_tools);
-
- hb_tools->add_child(memnew( Label(TTR("Snap Mode:")) ));
-
- snap_mode_button = memnew( MenuButton );
- hb_tools->add_child(snap_mode_button);
- snap_mode_button->set_text(TTR("<None>"));
- PopupMenu *p = snap_mode_button->get_popup();
- p->add_item(TTR("<None>"),0);
- p->add_item(TTR("Pixel Snap"),1);
- p->add_item(TTR("Grid Snap"),2);
- p->add_item(TTR("Auto Slice"),3);
- for (int i = 0; i < 4; i++)
- p->set_item_as_checkable(i,true);
- p->set_item_checked(0,true);
- p->connect("id_pressed", this, "_set_snap_mode");
- hb_grid = memnew( HBoxContainer );
- hb_tools->add_child(hb_grid);
- hb_grid->add_child( memnew( VSeparator ));
-
- hb_grid->add_child( memnew( Label(TTR("Offset:")) ) );
-
- sb_off_x = memnew( SpinBox );
- sb_off_x->set_min(-256);
- sb_off_x->set_max(256);
- sb_off_x->set_step(1);
- sb_off_x->set_value(snap_offset.x);
- sb_off_x->set_suffix("px");
- sb_off_x->connect("value_changed", this, "_set_snap_off_x");
- hb_grid->add_child(sb_off_x);
-
- sb_off_y = memnew( SpinBox );
- sb_off_y->set_min(-256);
- sb_off_y->set_max(256);
- sb_off_y->set_step(1);
- sb_off_y->set_value(snap_offset.y);
- sb_off_y->set_suffix("px");
- sb_off_y->connect("value_changed", this, "_set_snap_off_y");
- hb_grid->add_child(sb_off_y);
-
- hb_grid->add_child( memnew( VSeparator ));
- hb_grid->add_child( memnew( Label(TTR("Step:")) ) );
-
- sb_step_x = memnew( SpinBox );
- sb_step_x->set_min(-256);
- sb_step_x->set_max(256);
- sb_step_x->set_step(1);
- sb_step_x->set_value(snap_step.x);
- sb_step_x->set_suffix("px");
- sb_step_x->connect("value_changed", this, "_set_snap_step_x");
- hb_grid->add_child(sb_step_x);
-
- sb_step_y = memnew( SpinBox );
- sb_step_y->set_min(-256);
- sb_step_y->set_max(256);
- sb_step_y->set_step(1);
- sb_step_y->set_value(snap_step.y);
- sb_step_y->set_suffix("px");
- sb_step_y->connect("value_changed", this, "_set_snap_step_y");
- hb_grid->add_child(sb_step_y);
-
- hb_grid->add_child( memnew( VSeparator ));
- hb_grid->add_child( memnew( Label(TTR("Separation:")) ) );
-
- sb_sep_x = memnew( SpinBox );
- sb_sep_x->set_min(0);
- sb_sep_x->set_max(256);
- sb_sep_x->set_step(1);
- sb_sep_x->set_value(snap_separation.x);
- sb_sep_x->set_suffix("px");
- sb_sep_x->connect("value_changed", this, "_set_snap_sep_x");
- hb_grid->add_child(sb_sep_x);
-
- sb_sep_y = memnew( SpinBox );
- sb_sep_y->set_min(0);
- sb_sep_y->set_max(256);
- sb_sep_y->set_step(1);
- sb_sep_y->set_value(snap_separation.y);
- sb_sep_y->set_suffix("px");
- sb_sep_y->connect("value_changed", this, "_set_snap_sep_y");
- hb_grid->add_child(sb_sep_y);
-
- hb_grid->hide();
-
- HBoxContainer *main_hb = memnew( HBoxContainer );
- main_vb->add_child(main_hb);
- edit_draw = memnew( Control );
- main_hb->add_child(edit_draw);
- main_hb->set_v_size_flags(SIZE_EXPAND_FILL);
- edit_draw->set_h_size_flags(SIZE_EXPAND_FILL);
-
- Control * separator = memnew( Control );
- separator->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hb_tools->add_child(separator);
-
- icon_zoom = memnew( TextureRect );
- hb_tools->add_child(icon_zoom);
-
- zoom_out = memnew( ToolButton );
- zoom_out->connect("pressed", this, "_zoom_out");
- hb_tools->add_child(zoom_out);
-
- zoom_reset = memnew( ToolButton );
- zoom_reset->connect("pressed", this, "_zoom_reset");
- hb_tools->add_child(zoom_reset);
-
- zoom_in = memnew( ToolButton );
- zoom_in->connect("pressed", this, "_zoom_in");
- hb_tools->add_child(zoom_in);
-
- vscroll = memnew( VScrollBar);
- main_hb->add_child(vscroll);
- vscroll->connect("value_changed",this,"_scroll_changed");
- hscroll = memnew( HScrollBar );
- main_vb->add_child(hscroll);
- hscroll->connect("value_changed",this,"_scroll_changed");
-
- edit_draw->connect("draw",this,"_region_draw");
- edit_draw->connect("gui_input",this,"_region_input");
- draw_zoom=1.0;
- updating_scroll=false;
-
- edit_draw->set_clip_contents(true);
-
-}
-
-void TextureRegionEditorPlugin::edit(Object *p_node)
-{
- region_editor->edit(p_node);
-}
-
-bool TextureRegionEditorPlugin::handles(Object *p_obj) const
-{
- return p_obj->is_class("Sprite") || p_obj->is_class("Patch9Rect") || p_obj->is_class("StyleBoxTexture") || p_obj->is_class("AtlasTexture");
-}
-
-void TextureRegionEditorPlugin::make_visible(bool p_visible)
-{
- if (p_visible) {
- region_button->show();
- if (region_button->is_pressed())
- region_editor->show();
- } else {
- region_button->hide();
- region_editor->edit(NULL);
- region_editor->hide();
- }
-}
-
-
-Dictionary TextureRegionEditorPlugin::get_state() const {
-
- Dictionary state;
- state["zoom"]=region_editor->draw_zoom;
- state["snap_offset"]=region_editor->snap_offset;
- state["snap_step"]=region_editor->snap_step;
- state["snap_separation"]=region_editor->snap_separation;
- state["snap_mode"]=region_editor->snap_mode;
- return state;
-}
-
-void TextureRegionEditorPlugin::set_state(const Dictionary& p_state){
-
- Dictionary state=p_state;
- if (state.has("zoom")) {
- region_editor->draw_zoom = p_state["zoom"];
- }
-
- if (state.has("snap_step")) {
- Vector2 s = state["snap_step"];
- region_editor->sb_step_x->set_value(s.x);
- region_editor->sb_step_y->set_value(s.y);
- region_editor->snap_step = s;
- }
-
- if (state.has("snap_offset")) {
- Vector2 ofs = state["snap_offset"];
- region_editor->sb_off_x->set_value(ofs.x);
- region_editor->sb_off_y->set_value(ofs.y);
- region_editor->snap_offset = ofs;
- }
-
- if (state.has("snap_separation")) {
- Vector2 sep = state["snap_separation"];
- region_editor->sb_sep_x->set_value(sep.x);
- region_editor->sb_sep_y->set_value(sep.y);
- region_editor->snap_separation = sep;
- }
-
- if (state.has("snap_mode")) {
- region_editor->_set_snap_mode(state["snap_mode"]);
- }
-
-}
-
-TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node)
-{
- editor = p_node;
- region_editor = memnew ( TextureRegionEditor(p_node) );
-
- region_button = p_node->add_bottom_panel_item(TTR("Texture Region"), region_editor);
- region_button->set_tooltip(TTR("Texture Region Editor"));
-
- region_editor->set_custom_minimum_size(Size2(0,200));
- region_editor->hide();
- region_button->hide();
-}
diff --git a/tools/editor/plugins/texture_region_editor_plugin.h b/tools/editor/plugins/texture_region_editor_plugin.h
deleted file mode 100644
index da713a53d3..0000000000
--- a/tools/editor/plugins/texture_region_editor_plugin.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*************************************************************************/
-/* texture_region_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Author: Mariano Suligoy */
-/* */
-/* 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 TEXTURE_REGION_EDITOR_PLUGIN_H
-#define TEXTURE_REGION_EDITOR_PLUGIN_H
-
-#include "canvas_item_editor_plugin.h"
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/2d/sprite.h"
-#include "scene/gui/patch_9_rect.h"
-#include "scene/resources/style_box.h"
-#include "scene/resources/texture.h"
-
-class TextureRegionEditor : public Control {
-
- GDCLASS(TextureRegionEditor, Control );
-
- enum SnapMode {
- SNAP_NONE,
- SNAP_PIXEL,
- SNAP_GRID,
- SNAP_AUTOSLICE
- };
-
- friend class TextureRegionEditorPlugin;
- MenuButton *snap_mode_button;
- TextureRect *icon_zoom;
- ToolButton *zoom_in;
- ToolButton *zoom_reset;
- ToolButton *zoom_out;
- HBoxContainer * hb_grid; //For showing/hiding the grid controls when changing the SnapMode
- SpinBox *sb_step_y;
- SpinBox *sb_step_x;
- SpinBox *sb_off_y;
- SpinBox *sb_off_x;
- SpinBox *sb_sep_y;
- SpinBox *sb_sep_x;
- Control *edit_draw;
-
- VScrollBar *vscroll;
- HScrollBar *hscroll;
-
- EditorNode *editor;
- UndoRedo* undo_redo;
-
- Vector2 draw_ofs;
- float draw_zoom;
- bool updating_scroll;
-
- int snap_mode;
- Vector2 snap_offset;
- Vector2 snap_step;
- Vector2 snap_separation;
-
- NinePatchRect *node_patch9;
- Sprite *node_sprite;
- Ref<StyleBoxTexture> obj_styleBox;
- Ref<AtlasTexture> atlas_tex;
-
- Rect2 rect;
- Rect2 rect_prev;
- float prev_margin;
- int edited_margin;
- List<Rect2> autoslice_cache;
-
- bool drag;
- bool creating;
- Vector2 drag_from;
- int drag_index;
-
- void _set_snap_mode(int p_mode);
- void _set_snap_off_x(float p_val);
- void _set_snap_off_y(float p_val);
- void _set_snap_step_x(float p_val);
- void _set_snap_step_y(float p_val);
- void _set_snap_sep_x(float p_val);
- void _set_snap_sep_y(float p_val);
- void _zoom_in();
- void _zoom_reset();
- void _zoom_out();
- void apply_rect(const Rect2& rect);
-protected:
-
- void _notification(int p_what);
- void _node_removed(Object *p_obj);
- static void _bind_methods();
-
- Vector2 snap_point(Vector2 p_target) const;
-
- virtual void _changed_callback(Object *p_changed, const char *p_prop);
-
-public:
-
- void _edit_region();
- void _region_draw();
- void _region_input(const InputEvent &p_input);
- void _scroll_changed(float);
-
- void edit(Object *p_obj);
- TextureRegionEditor(EditorNode* p_editor);
-
-};
-
-class TextureRegionEditorPlugin : public EditorPlugin
-{
- GDCLASS( TextureRegionEditorPlugin, EditorPlugin );
-
- Button *region_button;
- TextureRegionEditor *region_editor;
- EditorNode *editor;
-public:
-
- virtual String get_name() const { return "TextureRegion"; }
- 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;
-
- TextureRegionEditorPlugin(EditorNode *p_node);
-};
-
-#endif // TEXTURE_REGION_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/theme_editor_plugin.h b/tools/editor/plugins/theme_editor_plugin.h
deleted file mode 100644
index 9251da8e07..0000000000
--- a/tools/editor/plugins/theme_editor_plugin.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*************************************************************************/
-/* theme_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 THEME_EDITOR_PLUGIN_H
-#define THEME_EDITOR_PLUGIN_H
-
-#include "scene/resources/theme.h"
-#include "scene/gui/texture_rect.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/check_box.h"
-#include "scene/gui/button_group.h"
-#include "scene/gui/scroll_container.h"
-
-#include "tools/editor/editor_node.h"
-
-
-
-
-class ThemeEditor : public Control {
-
- GDCLASS( ThemeEditor, Control );
-
-
- ScrollContainer *scroll;
- VBoxContainer *main_vb;
- Ref<Theme> theme;
-
- EditorFileDialog *file_dialog;
-
- double time_left;
-
- MenuButton *theme_menu;
- ConfirmationDialog *add_del_dialog;
- MenuButton *type_menu;
- LineEdit *type_edit;
- MenuButton *name_menu;
- LineEdit *name_edit;
- OptionButton *type_select;
- Label * type_select_label;
- Label * name_select_label;
- Label * dtype_select_label;
-
- enum PopupMode {
- POPUP_ADD,
- POPUP_CLASS_ADD,
- POPUP_REMOVE,
- POPUP_CLASS_REMOVE,
- POPUP_CREATE_EMPTY,
- POPUP_CREATE_EDITOR_EMPTY
- };
-
- int popup_mode;
-
- Tree *test_tree;
-
- void _save_template_cbk(String fname);
- void _dialog_cbk();
- void _type_menu_cbk(int p_option);
- void _name_menu_about_to_show();
- void _name_menu_cbk(int p_option);
- void _theme_menu_cbk(int p_option);
- void _propagate_redraw(Control *p_at);
- void _refresh_interval();
-
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void edit(const Ref<Theme>& p_theme);
-
- ThemeEditor();
-};
-
-
-
-class ThemeEditorPlugin : public EditorPlugin {
-
- GDCLASS( ThemeEditorPlugin, EditorPlugin );
-
- ThemeEditor *theme_editor;
- EditorNode *editor;
- Button *button;
-
-public:
-
- virtual String get_name() const { return "Theme"; }
- 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);
-
- ThemeEditorPlugin(EditorNode *p_node);
-
-};
-
-
-#endif // THEME_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp
deleted file mode 100644
index 7c232f0c32..0000000000
--- a/tools/editor/plugins/tile_map_editor_plugin.cpp
+++ /dev/null
@@ -1,1593 +0,0 @@
-/*************************************************************************/
-/* tile_map_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "tile_map_editor_plugin.h"
-
-#include "os/keyboard.h"
-#include "os/input.h"
-#include "canvas_item_editor_plugin.h"
-#include "tools/editor/editor_settings.h"
-#include "tools/editor/editor_scale.h"
-
-void TileMapEditor::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
- transp->set_icon(get_icon("Transpose","EditorIcons"));
- mirror_x->set_icon(get_icon("MirrorX","EditorIcons"));
- mirror_y->set_icon(get_icon("MirrorY","EditorIcons"));
- rotate_0->set_icon(get_icon("Rotate0","EditorIcons"));
- rotate_90->set_icon(get_icon("Rotate90","EditorIcons"));
- rotate_180->set_icon(get_icon("Rotate180","EditorIcons"));
- rotate_270->set_icon(get_icon("Rotate270","EditorIcons"));
-
- } break;
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
-
- if (is_visible_in_tree()) {
- _update_palette();
- }
- } break;
- }
-}
-
-void TileMapEditor::_menu_option(int p_option) {
-
- switch(p_option) {
-
- case OPTION_BUCKET: {
-
- tool=TOOL_BUCKET;
-
- canvas_item_editor->update();
- } break;
- case OPTION_PICK_TILE: {
-
- tool=TOOL_PICKING;
-
- canvas_item_editor->update();
- } break;
- case OPTION_SELECT: {
-
- tool=TOOL_SELECTING;
- selection_active=false;
-
- canvas_item_editor->update();
- } break;
- case OPTION_DUPLICATE: {
-
- _update_copydata();
-
- if (selection_active) {
- tool=TOOL_DUPLICATING;
-
- canvas_item_editor->update();
- }
- } break;
- case OPTION_ERASE_SELECTION: {
-
- if (!selection_active)
- return;
-
- undo_redo->create_action("Erase Selection");
- for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
- for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
-
- _set_cell(Point2i(j, i), TileMap::INVALID_CELL, false, false, false, true);
- }
- }
- undo_redo->commit_action();
-
- selection_active=false;
- copydata.clear();
-
- canvas_item_editor->update();
- } break;
- }
-}
-
-void TileMapEditor::_canvas_mouse_enter() {
-
- mouse_over=true;
- canvas_item_editor->update();
-}
-
-void TileMapEditor::_canvas_mouse_exit() {
-
- mouse_over=false;
- canvas_item_editor->update();
-}
-
-int TileMapEditor::get_selected_tile() const {
-
- int item = palette->get_current();
-
- if (item==-1)
- return TileMap::INVALID_CELL;
-
- return palette->get_item_metadata(item);
-}
-
-void TileMapEditor::set_selected_tile(int p_tile) {
-
- int idx = palette->find_metadata(p_tile);
-
- if (idx >= 0) {
- palette->select(idx, true);
- palette->ensure_current_is_visible();
- }
-}
-
-void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose,bool p_with_undo) {
-
- ERR_FAIL_COND(!node);
-
- int prev_val=node->get_cell(p_pos.x,p_pos.y);
-
- bool prev_flip_h=node->is_cell_x_flipped(p_pos.x,p_pos.y);
- bool prev_flip_v=node->is_cell_y_flipped(p_pos.x,p_pos.y);
- bool prev_transpose=node->is_cell_transposed(p_pos.x,p_pos.y);
-
- if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_flip_v && p_transpose==prev_transpose)
- return; //check that it's actually different
-
- if (p_with_undo) {
-
- undo_redo->add_do_method(node,"set_cellv",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose);
- undo_redo->add_undo_method(node,"set_cellv",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose);
- } else {
-
- node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose);
- }
-
-}
-
-void TileMapEditor::_text_entered(const String& p_text) {
-
- canvas_item_editor->grab_focus();
-}
-
-void TileMapEditor::_text_changed(const String& p_text) {
-
- _update_palette();
-}
-
-void TileMapEditor::_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 ) ) {
-
- palette->call("_gui_input", p_ie);
- search_box->accept_event();
- }
-}
-
-void TileMapEditor::_update_palette() {
-
- if (!node)
- return;
-
- int selected = get_selected_tile();
- palette->clear();
-
- Ref<TileSet> tileset=node->get_tileset();
- if (tileset.is_null())
- return;
-
- List<int> tiles;
- tileset->get_tile_list(&tiles);
-
- if (tiles.empty())
- return;
-
- float min_size = EDITOR_DEF("editors/tile_map/preview_size", 64);
- min_size *= EDSCALE;
- int hseparation = EDITOR_DEF("editors/tile_map/palette_item_hseparation",8);
- bool show_tile_names = bool(EDITOR_DEF("editors/tile_map/show_tile_names", true));
-
- palette->add_constant_override("hseparation", hseparation*EDSCALE);
- palette->add_constant_override("vseparation", 8*EDSCALE);
-
- palette->set_fixed_icon_size(Size2(min_size, min_size));
- palette->set_fixed_column_width(min_size * MAX(size_slider->get_value(), 1));
-
- String filter = search_box->get_text().strip_edges();
-
- for (List<int>::Element *E=tiles.front();E;E=E->next()) {
-
- String name;
-
- if (tileset->tile_get_name(E->get())!="") {
- name = itos(E->get())+" - "+tileset->tile_get_name(E->get());
- } else {
- name = "#"+itos(E->get());
- }
-
- if (filter != "" && !filter.is_subsequence_ofi(name))
- continue;
-
- if (show_tile_names) {
- palette->add_item(name);
- } else {
- palette->add_item(String());
- }
-
- Ref<Texture> tex = tileset->tile_get_texture(E->get());
-
- if (tex.is_valid()) {
- Rect2 region = tileset->tile_get_region(E->get());
-
- if (!region.has_no_area())
- palette->set_item_icon_region(palette->get_item_count()-1, region);
-
- palette->set_item_icon(palette->get_item_count()-1, tex);
- }
-
- palette->set_item_metadata(palette->get_item_count()-1, E->get());
- }
-
- palette->set_same_column_width(true);
-
- if (selected != -1)
- set_selected_tile(selected);
- else
- palette->select(0);
-}
-
-void TileMapEditor::_pick_tile(const Point2& p_pos) {
-
- int id = node->get_cell(p_pos.x, p_pos.y);
-
- if (id==TileMap::INVALID_CELL)
- return;
-
- if (search_box->get_text().strip_edges() != "") {
-
- search_box->set_text("");
- _update_palette();
- }
-
- set_selected_tile(id);
-
- mirror_x->set_pressed(node->is_cell_x_flipped(p_pos.x, p_pos.y));
- mirror_y->set_pressed(node->is_cell_y_flipped(p_pos.x, p_pos.y));
- transp->set_pressed(node->is_cell_transposed(p_pos.x, p_pos.y));
-
- _update_transform_buttons();
- canvas_item_editor->update();
-}
-
-PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i& p_start, bool erase, bool preview) {
-
- int prev_id = node->get_cell(p_start.x, p_start.y);
- int id = TileMap::INVALID_CELL;
- if (!erase) {
- id = get_selected_tile();
-
- if (id == TileMap::INVALID_CELL)
- return PoolVector<Vector2>();
- }
-
- Rect2i r = node->get_item_rect();
- r.pos = r.pos/node->get_cell_size();
- r.size = r.size/node->get_cell_size();
-
- int area = r.get_area();
- if(preview) {
- // Test if we can re-use the result from preview bucket fill
- bool invalidate_cache = false;
- // Area changed
- if(r != bucket_cache_rect)
- _clear_bucket_cache();
- // Cache grid is not initialized
- if(bucket_cache_visited == 0) {
- bucket_cache_visited = new bool[area];
- invalidate_cache = true;
- }
- // Tile ID changed or position wasn't visited by the previous fill
- int loc = (p_start.x - r.get_pos().x) + (p_start.y - r.get_pos().y) * r.get_size().x;
- if(prev_id != bucket_cache_tile || !bucket_cache_visited[loc]) {
- invalidate_cache = true;
- }
- if(invalidate_cache) {
- for(int i = 0; i < area; ++i)
- bucket_cache_visited[i] = false;
- bucket_cache = PoolVector<Vector2>();
- bucket_cache_tile = prev_id;
- bucket_cache_rect = r;
- }
- else {
- return bucket_cache;
- }
- }
-
- PoolVector<Vector2> points;
-
- List<Point2i> queue;
- queue.push_back(p_start);
-
- while (queue.size()) {
-
- Point2i n = queue.front()->get();
- queue.pop_front();
-
- if (!r.has_point(n))
- continue;
-
- if (node->get_cell(n.x, n.y) == prev_id) {
-
- if(preview) {
- int loc = (n.x - r.get_pos().x) + (n.y - r.get_pos().y) * r.get_size().x;
- if(bucket_cache_visited[loc])
- continue;
- bucket_cache_visited[loc] = true;
- bucket_cache.push_back(n);
- }
- else {
- node->set_cellv(n, id, flip_h, flip_v, transpose);
- points.push_back(n);
- }
-
- queue.push_back(n + Point2i(0, 1));
- queue.push_back(n + Point2i(0, -1));
- queue.push_back(n + Point2i(1, 0));
- queue.push_back(n + Point2i(-1, 0));
- }
- }
-
- return preview ? bucket_cache : points;
-}
-
-void TileMapEditor::_fill_points(const PoolVector<Vector2> p_points, const Dictionary& p_op) {
-
- int len = p_points.size();
- PoolVector<Vector2>::Read pr = p_points.read();
-
- int id = p_op["id"];
- bool xf = p_op["flip_h"];
- bool yf = p_op["flip_v"];
- bool tr = p_op["transpose"];
-
- for (int i=0;i<len;i++) {
-
- _set_cell(pr[i], id, xf, yf, tr);
- }
-}
-
-void TileMapEditor::_erase_points(const PoolVector<Vector2> p_points) {
-
- int len = p_points.size();
- PoolVector<Vector2>::Read pr = p_points.read();
-
- for (int i=0;i<len;i++) {
-
- _set_cell(pr[i], TileMap::INVALID_CELL);
- }
-}
-
-void TileMapEditor::_select(const Point2i& p_from, const Point2i& p_to) {
-
- Point2i begin=p_from;
- Point2i end=p_to;
-
- if (begin.x > end.x) {
-
- SWAP( begin.x, end.x);
- }
- if (begin.y > end.y) {
-
- SWAP( begin.y, end.y);
- }
-
- rectangle.pos=begin;
- rectangle.size=end-begin;
-
- canvas_item_editor->update();
-}
-
-void TileMapEditor::_draw_cell(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform) {
-
- Ref<Texture> t = node->get_tileset()->tile_get_texture(p_cell);
-
- if (t.is_null())
- return;
-
- Vector2 tile_ofs = node->get_tileset()->tile_get_texture_offset(p_cell);
-
- Rect2 r = node->get_tileset()->tile_get_region(p_cell);
- Size2 sc = p_xform.get_scale();
-
- Rect2 rect = Rect2();
- rect.pos = node->map_to_world(p_point) + node->get_cell_draw_offset();
-
- if (r.has_no_area()) {
- rect.size = t->get_size();
- } else {
- rect.size = r.size;
- }
-
- if (rect.size.y > rect.size.x) {
- if ((p_flip_h && (p_flip_v || p_transpose)) || (p_flip_v && !p_transpose))
- tile_ofs.y += rect.size.y - rect.size.x;
- } else if (rect.size.y < rect.size.x) {
- if ((p_flip_v && (p_flip_h || p_transpose)) || (p_flip_h && !p_transpose))
- tile_ofs.x += rect.size.x - rect.size.y;
- }
-
- if (p_transpose) {
- SWAP(tile_ofs.x, tile_ofs.y);
- }
- if (p_flip_h) {
- sc.x*=-1.0;
- tile_ofs.x*=-1.0;
- }
- if (p_flip_v) {
- sc.y*=-1.0;
- tile_ofs.y*=-1.0;
- }
-
- if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) {
-
- rect.pos+=tile_ofs;
- } else if (node->get_tile_origin()==TileMap::TILE_ORIGIN_BOTTOM_LEFT) {
- Size2 cell_size = node->get_cell_size();
-
- rect.pos+=tile_ofs;
-
- if(p_transpose)
- {
- if(p_flip_h)
- rect.pos.x-=cell_size.x;
- else
- rect.pos.x+=cell_size.x;
- } else {
- if(p_flip_v)
- rect.pos.y-=cell_size.y;
- else
- rect.pos.y+=cell_size.y;
- }
-
- } 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) - tile_ofs;
-
- if (p_flip_h)
- rect.pos.x-=s.x-center.x;
- else
- rect.pos.x-=center.x;
-
- if (p_flip_v)
- rect.pos.y-=s.y-center.y;
- else
- rect.pos.y-=center.y;
- }
-
- rect.pos=p_xform.xform(rect.pos);
- rect.size*=sc;
-
- if (r.has_no_area())
- canvas_item_editor->draw_texture_rect(t, rect, false, Color(1,1,1,0.5), p_transpose);
- else
- canvas_item_editor->draw_texture_rect_region(t, rect, r, Color(1,1,1,0.5), p_transpose);
-}
-
-void TileMapEditor::_draw_fill_preview(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform) {
-
- PoolVector<Vector2> points = _bucket_fill(p_point, false, true);
- PoolVector<Vector2>::Read pr = points.read();
- int len = points.size();
- int time_after = OS::get_singleton()->get_ticks_msec();
-
- for(int i = 0; i < len; ++i) {
- _draw_cell(p_cell, pr[i], p_flip_h, p_flip_v, p_transpose, p_xform);
- }
-}
-
-void TileMapEditor::_clear_bucket_cache() {
- if(bucket_cache_visited) {
- delete[] bucket_cache_visited;
- bucket_cache_visited = 0;
- }
-}
-
-void TileMapEditor::_update_copydata() {
-
- copydata.clear();
-
- if (!selection_active)
- return;
-
- for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
-
- for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
-
- TileData tcd;
-
- tcd.cell=node->get_cell(j, i);
-
- if (tcd.cell!=TileMap::INVALID_CELL) {
- tcd.pos=Point2i(j, i);
- tcd.flip_h=node->is_cell_x_flipped(j,i);
- tcd.flip_v=node->is_cell_y_flipped(j,i);
- tcd.transpose=node->is_cell_transposed(j,i);
- }
-
- copydata.push_back(tcd);
- }
- }
-}
-
-static inline Vector<Point2i> line(int x0, int x1, int y0, int y1) {
-
- Vector<Point2i> points;
-
- float dx = ABS(x1 - x0);
- float dy = ABS(y1 - y0);
-
- int x = x0;
- int y = y0;
-
- int sx = x0 > x1 ? -1 : 1;
- int sy = y0 > y1 ? -1 : 1;
-
- if (dx > dy) {
- float err = dx/2;
-
- for (; x != x1; x += sx) {
- points.push_back(Vector2(x, y));
-
- err -= dy;
- if (err < 0) {
- y += sy;
- err += dx;
- }
- }
- } else {
- float err = dy/2;
-
- for (; y != y1; y += sy) {
- points.push_back(Vector2(x, y));
-
- err -= dx;
- if (err < 0) {
- x += sx;
- err += dy;
- }
- }
- }
-
- points.push_back(Vector2(x, y));
-
- return points;
-}
-
-bool TileMapEditor::forward_gui_input(const InputEvent& p_event) {
-
- if (!node || !node->get_tileset().is_valid() || !node->is_visible_in_tree())
- return false;
-
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
- Transform2D xform_inv = xform.affine_inverse();
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
-
- if (mb.button_index==BUTTON_LEFT) {
-
- if (mb.pressed) {
-
- if (Input::get_singleton()->is_key_pressed(KEY_SPACE))
- return false; //drag
-
- if (tool==TOOL_NONE) {
-
- if (mb.mod.shift) {
-
- if (mb.mod.control)
- tool=TOOL_RECTANGLE_PAINT;
- else
- tool=TOOL_LINE_PAINT;
-
- selection_active=false;
- rectangle_begin=over_tile;
-
- return true;
- }
-
- if (mb.mod.control) {
-
- tool=TOOL_PICKING;
- _pick_tile(over_tile);
-
- return true;
- }
-
- tool=TOOL_PAINTING;
- }
-
- if (tool==TOOL_PAINTING) {
-
- int id = get_selected_tile();
-
- if (id!=TileMap::INVALID_CELL) {
-
- tool=TOOL_PAINTING;
-
- paint_undo.clear();
- paint_undo[over_tile]=_get_op_from_cell(over_tile);
-
- _set_cell(over_tile, id, flip_h, flip_v, transpose);
- }
- } else if (tool==TOOL_PICKING) {
-
- _pick_tile(over_tile);
- } else if (tool==TOOL_SELECTING) {
-
- selection_active=true;
- rectangle_begin=over_tile;
- }
-
- return true;
-
- } else {
-
- if (tool!=TOOL_NONE) {
-
- if (tool==TOOL_PAINTING) {
-
- int id=get_selected_tile();
-
- if (id!=TileMap::INVALID_CELL && paint_undo.size()) {
-
- undo_redo->create_action(TTR("Paint TileMap"));
- for (Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
-
- Point2 p=E->key();
- undo_redo->add_do_method(node,"set_cellv",p,id,flip_h,flip_v,transpose);
- undo_redo->add_undo_method(node,"set_cellv",p,E->get().idx,E->get().xf,E->get().yf,E->get().tr);
- }
- undo_redo->commit_action();
-
- paint_undo.clear();
- }
- } else if (tool==TOOL_LINE_PAINT) {
-
- int id=get_selected_tile();
-
- if (id!=TileMap::INVALID_CELL) {
-
- undo_redo->create_action("Line Draw");
- for (Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
-
- _set_cell(E->key(), id, flip_h, flip_v, transpose, true);
- }
- undo_redo->commit_action();
-
- paint_undo.clear();
-
- canvas_item_editor->update();
- }
- } else if (tool==TOOL_RECTANGLE_PAINT) {
-
- int id=get_selected_tile();
-
- if (id!=TileMap::INVALID_CELL) {
-
- undo_redo->create_action("Rectangle Paint");
- for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
- for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
-
- _set_cell(Point2i(j, i), id, flip_h, flip_v, transpose, true);
- }
- }
- undo_redo->commit_action();
-
- canvas_item_editor->update();
- }
- } else if (tool==TOOL_DUPLICATING) {
-
- Point2 ofs = over_tile-rectangle.pos;
-
- undo_redo->create_action(TTR("Duplicate"));
- for (List<TileData>::Element *E=copydata.front();E;E=E->next()) {
-
- _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,E->get().transpose,true);
- }
- undo_redo->commit_action();
-
- copydata.clear();
-
- canvas_item_editor->update();
-
- } else if (tool==TOOL_SELECTING) {
-
- canvas_item_editor->update();
-
- } else if (tool==TOOL_BUCKET) {
-
- Dictionary pop;
- pop["id"] = node->get_cell(over_tile.x, over_tile.y);
- pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
- pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
- pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
-
- PoolVector<Vector2> points = _bucket_fill(over_tile);
-
- if (points.size() == 0)
- return false;
-
- Dictionary op;
- op["id"] = get_selected_tile();
- op["flip_h"] = flip_h;
- op["flip_v"] = flip_v;
- op["transpose"] = transpose;
-
- undo_redo->create_action("Bucket Fill");
-
- undo_redo->add_do_method(this, "_fill_points", points, op);
- undo_redo->add_undo_method(this, "_fill_points", points, pop);
-
- undo_redo->commit_action();
- }
-
- tool=TOOL_NONE;
-
- return true;
- }
- }
- } else if (mb.button_index==BUTTON_RIGHT) {
-
- if (mb.pressed) {
-
- if (tool==TOOL_SELECTING || selection_active) {
-
- tool=TOOL_NONE;
- selection_active=false;
-
- canvas_item_editor->update();
-
- return true;
- }
-
- if (tool==TOOL_DUPLICATING) {
-
- tool=TOOL_NONE;
- copydata.clear();
-
- canvas_item_editor->update();
-
- return true;
- }
-
- if (tool==TOOL_NONE) {
-
- paint_undo.clear();
-
- Point2 local = node->world_to_map(xform_inv.xform(Point2(mb.x, mb.y)));
-
- if (mb.mod.shift) {
-
- if (mb.mod.control)
- tool=TOOL_RECTANGLE_ERASE;
- else
- tool=TOOL_LINE_ERASE;
-
- selection_active=false;
- rectangle_begin=local;
- } else {
-
- tool=TOOL_ERASING;
-
- paint_undo[local]=_get_op_from_cell(local);
- _set_cell(local, TileMap::INVALID_CELL);
- }
-
- return true;
- }
-
- } else {
- if (tool==TOOL_ERASING || tool==TOOL_RECTANGLE_ERASE || tool==TOOL_LINE_ERASE) {
-
- if (paint_undo.size()) {
- undo_redo->create_action(TTR("Erase TileMap"));
- for (Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
-
- Point2 p=E->key();
- undo_redo->add_do_method(node,"set_cellv",p,TileMap::INVALID_CELL,false,false,false);
- undo_redo->add_undo_method(node,"set_cellv",p,E->get().idx,E->get().xf,E->get().yf,E->get().tr);
- }
-
- undo_redo->commit_action();
- paint_undo.clear();
- }
-
- if (tool==TOOL_RECTANGLE_ERASE || tool==TOOL_LINE_ERASE) {
- canvas_item_editor->update();
- }
-
- tool=TOOL_NONE;
-
- return true;
-
- } else if (tool==TOOL_BUCKET) {
-
- Dictionary pop;
- pop["id"] = node->get_cell(over_tile.x, over_tile.y);
- pop["flip_h"] = node->is_cell_x_flipped(over_tile.x, over_tile.y);
- pop["flip_v"] = node->is_cell_y_flipped(over_tile.x, over_tile.y);
- pop["transpose"] = node->is_cell_transposed(over_tile.x, over_tile.y);
-
- PoolVector<Vector2> points = _bucket_fill(over_tile, true);
-
- if (points.size() == 0)
- return false;
-
- undo_redo->create_action("Bucket Fill");
-
- undo_redo->add_do_method(this, "_erase_points", points);
- undo_redo->add_undo_method(this, "_fill_points", points, pop);
-
- undo_redo->commit_action();
- }
- }
- }
- } break;
- case InputEvent::MOUSE_MOTION: {
-
- const InputEventMouseMotion &mm=p_event.mouse_motion;
-
- Point2i new_over_tile = node->world_to_map(xform_inv.xform(Point2(mm.x,mm.y)));
-
- if (new_over_tile!=over_tile) {
-
- over_tile=new_over_tile;
- canvas_item_editor->update();
- }
-
- int tile_under = node->get_cell(over_tile.x, over_tile.y);
- String tile_name = "none";
-
- if (node->get_tileset()->has_tile(tile_under))
- tile_name = node->get_tileset()->tile_get_name(tile_under);
- tile_info->set_text(String::num(over_tile.x)+", "+String::num(over_tile.y)+" ["+tile_name+"]");
-
- if (tool==TOOL_PAINTING) {
-
- int id = get_selected_tile();
- if (id!=TileMap::INVALID_CELL) {
-
- if (!paint_undo.has(over_tile)) {
- paint_undo[over_tile]=_get_op_from_cell(over_tile);
- }
-
- _set_cell(over_tile, id, flip_h, flip_v, transpose);
-
- return true;
- }
- }
-
- if (tool==TOOL_SELECTING) {
-
- _select(rectangle_begin, over_tile);
-
- return true;
- }
-
- if (tool==TOOL_LINE_PAINT || tool==TOOL_LINE_ERASE) {
-
- int id = get_selected_tile();
- bool erasing = (tool==TOOL_LINE_ERASE);
-
- if (erasing && paint_undo.size()) {
-
- for (Map<Point2i, CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
-
- _set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
- }
- }
-
- paint_undo.clear();
-
- if (id!=TileMap::INVALID_CELL) {
-
- Vector<Point2i> points = line(rectangle_begin.x, over_tile.x, rectangle_begin.y, over_tile.y);
-
- for (int i=0;i<points.size();i++) {
-
- paint_undo[points[i]]=_get_op_from_cell(points[i]);
-
- if (erasing)
- _set_cell(points[i], TileMap::INVALID_CELL);
- }
-
- canvas_item_editor->update();
- }
-
- return true;
- }
- if (tool==TOOL_RECTANGLE_PAINT || tool==TOOL_RECTANGLE_ERASE) {
-
- _select(rectangle_begin, over_tile);
-
- if (tool==TOOL_RECTANGLE_ERASE) {
-
- if (paint_undo.size()) {
-
- for (Map<Point2i, CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
-
- _set_cell(E->key(), E->get().idx, E->get().xf, E->get().yf, E->get().tr);
- }
- }
-
- paint_undo.clear();
-
- for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
- for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
-
- Point2i tile = Point2i(j, i);
- paint_undo[tile]=_get_op_from_cell(tile);
-
- _set_cell(tile, TileMap::INVALID_CELL);
- }
- }
- }
-
- return true;
- }
- if (tool==TOOL_ERASING) {
-
- if (!paint_undo.has(over_tile)) {
- paint_undo[over_tile]=_get_op_from_cell(over_tile);
- }
-
- _set_cell(over_tile, TileMap::INVALID_CELL);
-
- return true;
- }
- if (tool==TOOL_PICKING && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
-
- _pick_tile(over_tile);
-
- return true;
- }
- } break;
- case InputEvent::KEY: {
-
- const InputEventKey &k = p_event.key;
-
- if (!k.pressed)
- break;
-
- if (k.scancode==KEY_ESCAPE) {
-
- if (tool==TOOL_DUPLICATING)
- copydata.clear();
- else if (tool==TOOL_SELECTING || selection_active)
- selection_active=false;
-
- tool=TOOL_NONE;
-
- canvas_item_editor->update();
-
- return true;
- }
-
- if (tool!=TOOL_NONE || !mouse_over)
- return false;
-
- if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
- _menu_option(OPTION_ERASE_SELECTION);
-
- return true;
- }
- if (ED_IS_SHORTCUT("tile_map_editor/select", p_event)) {
- tool=TOOL_SELECTING;
- selection_active=false;
-
- canvas_item_editor->update();
-
- return true;
- }
- if (ED_IS_SHORTCUT("tile_map_editor/duplicate_selection", p_event)) {
- _update_copydata();
-
- if (selection_active) {
- tool=TOOL_DUPLICATING;
-
- canvas_item_editor->update();
-
- return true;
- }
- }
- if (ED_IS_SHORTCUT("tile_map_editor/find_tile", p_event)) {
- search_box->select_all();
- search_box->grab_focus();
-
- return true;
- }
- if (ED_IS_SHORTCUT("tile_map_editor/mirror_x", p_event)) {
- flip_h=!flip_h;
- mirror_x->set_pressed(flip_h);
- canvas_item_editor->update();
- return true;
- }
- if (ED_IS_SHORTCUT("tile_map_editor/mirror_y", p_event)) {
- flip_v=!flip_v;
- mirror_y->set_pressed(flip_v);
- canvas_item_editor->update();
- return true;
- }
- if (ED_IS_SHORTCUT("tile_map_editor/transpose", p_event)) {
- transpose = !transpose;
- transp->set_pressed(transpose);
- canvas_item_editor->update();
- return true;
- }
- } break;
- }
-
- return false;
-}
-
-void TileMapEditor::_canvas_draw() {
-
- if (!node)
- return;
-
- Transform2D cell_xf = node->get_cell_transform();
-
- Transform2D xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
- Transform2D xform_inv = xform.affine_inverse();
-
-
- Size2 screen_size=canvas_item_editor->get_size();
- {
- Rect2 aabb;
- aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
- aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
- aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
- aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
- Rect2i si=aabb.grow(1.0);
-
- if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) {
-
- int max_lines=2000; //avoid crash if size too smal
-
- for (int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
-
- Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y)));
- Vector2 to = xform.xform(node->map_to_world(Vector2(i,si.pos.y+si.size.y+1)));
-
- Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
- canvas_item_editor->draw_line(from,to,col,1);
- if (max_lines--==0)
- break;
- }
- } else {
-
- int max_lines=10000; //avoid crash if size too smal
-
- for (int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
-
- for (int j=(si.pos.y)-1;j<=(si.pos.y+si.size.y);j++) {
-
- Vector2 ofs;
- if (ABS(j)&1) {
- ofs=cell_xf[0]*0.5;
- }
-
- Vector2 from = xform.xform(node->map_to_world(Vector2(i,j),true)+ofs);
- Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs);
- Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
- canvas_item_editor->draw_line(from,to,col,1);
-
- if (max_lines--==0)
- break;
-
- }
-
- }
- }
-
- int max_lines=10000; //avoid crash if size too smal
-
- if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) {
-
- for (int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
-
- Vector2 from = xform.xform(node->map_to_world(Vector2(si.pos.x,i)));
- Vector2 to = xform.xform(node->map_to_world(Vector2(si.pos.x+si.size.x+1,i)));
-
- Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
- canvas_item_editor->draw_line(from,to,col,1);
-
- if (max_lines--==0)
- break;
-
- }
- } else {
-
-
- for (int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
-
- for (int j=(si.pos.x)-1;j<=(si.pos.x+si.size.x);j++) {
-
- Vector2 ofs;
- if (ABS(j)&1) {
- ofs=cell_xf[1]*0.5;
- }
-
- Vector2 from = xform.xform(node->map_to_world(Vector2(j,i),true)+ofs);
- Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs);
- Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
- canvas_item_editor->draw_line(from,to,col,1);
-
- if (max_lines--==0)
- break;
-
- }
- }
- }
- }
-
- if (selection_active) {
-
- Vector<Vector2> points;
- points.push_back( xform.xform( node->map_to_world(( rectangle.pos ) )));
- points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(rectangle.size.x+1,0)) ) ));
- points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(rectangle.size.x+1,rectangle.size.y+1)) ) ));
- points.push_back( xform.xform( node->map_to_world((rectangle.pos+Point2(0,rectangle.size.y+1)) ) ));
-
- canvas_item_editor->draw_colored_polygon(points, Color(0.2,0.8,1,0.4));
- }
-
- if (mouse_over){
-
- Vector2 endpoints[4]={
- node->map_to_world(over_tile, true),
- node->map_to_world((over_tile+Point2(1,0)), true),
- node->map_to_world((over_tile+Point2(1,1)), true),
- node->map_to_world((over_tile+Point2(0,1)), true)
- };
-
- for (int i=0;i<4;i++) {
- if (node->get_half_offset()==TileMap::HALF_OFFSET_X && ABS(over_tile.y)&1)
- endpoints[i]+=cell_xf[0]*0.5;
- if (node->get_half_offset()==TileMap::HALF_OFFSET_Y && ABS(over_tile.x)&1)
- endpoints[i]+=cell_xf[1]*0.5;
- endpoints[i]=xform.xform(endpoints[i]);
- }
- Color col;
- if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
- col=Color(0.2,0.8,1.0,0.8);
- else
- col=Color(1.0,0.4,0.2,0.8);
-
- for (int i=0;i<4;i++)
- canvas_item_editor->draw_line(endpoints[i],endpoints[(i+1)%4],col,2);
-
-
- bool bucket_preview = EditorSettings::get_singleton()->get("editors/tile_map/bucket_fill_preview");
- if (tool==TOOL_SELECTING || tool==TOOL_PICKING || !bucket_preview) {
- return;
- }
-
- if (tool==TOOL_LINE_PAINT) {
-
- if (paint_undo.empty())
- return;
-
- int id = get_selected_tile();
-
- if (id==TileMap::INVALID_CELL)
- return;
-
- for (Map<Point2i, CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
-
- _draw_cell(id, E->key(), flip_h, flip_v, transpose, xform);
- }
-
- } else if (tool==TOOL_RECTANGLE_PAINT) {
-
- int id = get_selected_tile();
-
- if (id==TileMap::INVALID_CELL)
- return;
-
- for (int i=rectangle.pos.y;i<=rectangle.pos.y+rectangle.size.y;i++) {
- for (int j=rectangle.pos.x;j<=rectangle.pos.x+rectangle.size.x;j++) {
-
- _draw_cell(id, Point2i(j, i), flip_h, flip_v, transpose, xform);
- }
- }
- } else if (tool==TOOL_DUPLICATING) {
-
- if (copydata.empty())
- return;
-
- Ref<TileSet> ts = node->get_tileset();
-
- if (ts.is_null())
- return;
-
- Point2 ofs = over_tile-rectangle.pos;
-
- for (List<TileData>::Element *E=copydata.front();E;E=E->next()) {
-
- if (!ts->has_tile(E->get().cell))
- continue;
-
- TileData tcd = E->get();
-
- _draw_cell(tcd.cell, tcd.pos+ofs, tcd.flip_h, tcd.flip_v, tcd.transpose, xform);
- }
-
- Rect2i duplicate=rectangle;
- duplicate.pos=over_tile;
-
- Vector<Vector2> points;
- points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
- points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
- points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1))) ));
- points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(0,duplicate.size.y+1))) ));
-
- canvas_item_editor->draw_colored_polygon(points, Color(0.2,1.0,0.8,0.2));
-
- } else if(tool == TOOL_BUCKET) {
-
- int tile = get_selected_tile();
- _draw_fill_preview(tile, over_tile, flip_h, flip_v, transpose, xform);
-
- } else {
-
- int st = get_selected_tile();
-
- if (st==TileMap::INVALID_CELL)
- return;
-
- _draw_cell(st, over_tile, flip_h, flip_v, transpose, xform);
- }
- }
-}
-
-void TileMapEditor::edit(Node *p_tile_map) {
-
- search_box->set_text("");
-
- if (!canvas_item_editor) {
- canvas_item_editor=CanvasItemEditor::get_singleton()->get_viewport_control();
- }
-
- if (node)
- node->disconnect("settings_changed",this,"_tileset_settings_changed");
- if (p_tile_map) {
-
- node=p_tile_map->cast_to<TileMap>();
- if (!canvas_item_editor->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->connect("draw",this,"_canvas_draw");
- if (!canvas_item_editor->is_connected("mouse_entered",this,"_canvas_mouse_enter"))
- canvas_item_editor->connect("mouse_entered",this,"_canvas_mouse_enter");
- if (!canvas_item_editor->is_connected("mouse_exited",this,"_canvas_mouse_exit"))
- canvas_item_editor->connect("mouse_exited",this,"_canvas_mouse_exit");
-
- _update_palette();
-
- } else {
- node=NULL;
-
- if (canvas_item_editor->is_connected("draw",this,"_canvas_draw"))
- canvas_item_editor->disconnect("draw",this,"_canvas_draw");
- if (canvas_item_editor->is_connected("mouse_entered",this,"_canvas_mouse_enter"))
- canvas_item_editor->disconnect("mouse_entered",this,"_canvas_mouse_enter");
- if (canvas_item_editor->is_connected("mouse_exited",this,"_canvas_mouse_exit"))
- canvas_item_editor->disconnect("mouse_exited",this,"_canvas_mouse_exit");
-
- _update_palette();
- }
-
- if (node)
- node->connect("settings_changed",this,"_tileset_settings_changed");
-
- _clear_bucket_cache();
-
-}
-
-void TileMapEditor::_tileset_settings_changed() {
-
- _update_palette();
-
- if (canvas_item_editor)
- canvas_item_editor->update();
-}
-
-void TileMapEditor::_icon_size_changed(float p_value) {
- if (node) {
- palette->set_icon_scale(p_value);
- _update_palette();
- }
-}
-
-void TileMapEditor::_bind_methods() {
-
- ClassDB::bind_method(_MD("_text_entered"),&TileMapEditor::_text_entered);
- ClassDB::bind_method(_MD("_text_changed"),&TileMapEditor::_text_changed);
- ClassDB::bind_method(_MD("_sbox_input"),&TileMapEditor::_sbox_input);
- ClassDB::bind_method(_MD("_menu_option"),&TileMapEditor::_menu_option);
- ClassDB::bind_method(_MD("_canvas_draw"),&TileMapEditor::_canvas_draw);
- ClassDB::bind_method(_MD("_canvas_mouse_enter"),&TileMapEditor::_canvas_mouse_enter);
- ClassDB::bind_method(_MD("_canvas_mouse_exit"),&TileMapEditor::_canvas_mouse_exit);
- ClassDB::bind_method(_MD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed);
- ClassDB::bind_method(_MD("_update_transform_buttons"),&TileMapEditor::_update_transform_buttons);
-
- ClassDB::bind_method(_MD("_fill_points"),&TileMapEditor::_fill_points);
- ClassDB::bind_method(_MD("_erase_points"),&TileMapEditor::_erase_points);
-
- ClassDB::bind_method(_MD("_icon_size_changed"), &TileMapEditor::_icon_size_changed);
-}
-
-TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i& p_pos)
-{
- CellOp op;
- op.idx = node->get_cell(p_pos.x,p_pos.y);
- if (op.idx!=TileMap::INVALID_CELL) {
- if (node->is_cell_x_flipped(p_pos.x,p_pos.y))
- op.xf=true;
- if (node->is_cell_y_flipped(p_pos.x,p_pos.y))
- op.yf=true;
- if (node->is_cell_transposed(p_pos.x,p_pos.y))
- op.tr=true;
- }
- return op;
-}
-
-void TileMapEditor::_update_transform_buttons(Object *p_button) {
- //ERR_FAIL_NULL(p_button);
- ToolButton *b=p_button->cast_to<ToolButton>();
- //ERR_FAIL_COND(!b);
-
- if (b == rotate_0) {
- mirror_x->set_pressed(false);
- mirror_y->set_pressed(false);
- transp->set_pressed(false);
- }
- else if (b == rotate_90) {
- mirror_x->set_pressed(true);
- mirror_y->set_pressed(false);
- transp->set_pressed(true);
- }
- else if (b == rotate_180) {
- mirror_x->set_pressed(true);
- mirror_y->set_pressed(true);
- transp->set_pressed(false);
- }
- else if (b == rotate_270) {
- mirror_x->set_pressed(false);
- mirror_y->set_pressed(true);
- transp->set_pressed(true);
- }
-
- flip_h=mirror_x->is_pressed();
- flip_v=mirror_y->is_pressed();
- transpose=transp->is_pressed();
-
- rotate_0->set_pressed(!flip_h && !flip_v && !transpose);
- rotate_90->set_pressed(flip_h && !flip_v && transpose);
- rotate_180->set_pressed(flip_h && flip_v && !transpose);
- rotate_270->set_pressed(!flip_h && flip_v && transpose);
-}
-
-TileMapEditor::TileMapEditor(EditorNode *p_editor) {
-
- node=NULL;
- canvas_item_editor=NULL;
- editor=p_editor;
- undo_redo=editor->get_undo_redo();
-
- tool=TOOL_NONE;
- selection_active=false;
- mouse_over=false;
-
- flip_h=false;
- flip_v=false;
- transpose=false;
-
- bucket_cache_tile = -1;
- bucket_cache_visited = 0;
-
- ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase selection"), KEY_DELETE);
- ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find tile"), KEY_MASK_CMD+KEY_F);
- ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose"));
- ED_SHORTCUT("tile_map_editor/mirror_x", TTR("Mirror X"), KEY_A);
- ED_SHORTCUT("tile_map_editor/mirror_y", TTR("Mirror Y"), KEY_S);
-
- search_box = memnew( LineEdit );
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- search_box->connect("text_entered", this, "_text_entered");
- search_box->connect("text_changed", this, "_text_changed");
- search_box->connect("gui_input", this, "_sbox_input");
- add_child(search_box);
-
- size_slider = memnew( HSlider );
- size_slider->set_h_size_flags(SIZE_EXPAND_FILL);
- size_slider->set_min(0.1f);
- size_slider->set_max(4.0f);
- size_slider->set_step(0.1f);
- size_slider->set_value(1.0f);
- size_slider->connect("value_changed", this, "_icon_size_changed");
- add_child(size_slider);
-
- int mw = EDITOR_DEF("editors/tile_map/palette_min_width", 80);
-
- // Add tile palette
- palette = memnew( ItemList );
- palette->set_v_size_flags(SIZE_EXPAND_FILL);
- palette->set_custom_minimum_size(Size2(mw,0));
- palette->set_max_columns(0);
- palette->set_icon_mode(ItemList::ICON_MODE_TOP);
- palette->set_max_text_lines(2);
- add_child(palette);
-
- // Add menu items
- toolbar = memnew( HBoxContainer );
- toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
- toolbar->set_alignment(BoxContainer::ALIGN_END);
- CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar);
-
- // Tile position
- tile_info = memnew( Label );
- toolbar->add_child(tile_info);
-
- options = memnew( MenuButton );
- options->set_text("Tile Map");
- options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons"));
- options->set_process_unhandled_key_input(false);
-
- PopupMenu *p = options->get_popup();
-
- p->add_item(TTR("Bucket"), OPTION_BUCKET);
- p->add_separator();
- p->add_item(TTR("Pick Tile"), OPTION_PICK_TILE, KEY_CONTROL);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_MASK_CMD+KEY_B), OPTION_SELECT);
- p->add_shortcut(ED_SHORTCUT("tile_map_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_CMD+KEY_D), OPTION_DUPLICATE);
- p->add_shortcut(ED_GET_SHORTCUT("tile_map_editor/erase_selection"), OPTION_ERASE_SELECTION);
-
- p->connect("id_pressed", this, "_menu_option");
-
- toolbar->add_child(options);
-
- toolbar->add_child( memnew( VSeparator ) );
-
- transp = memnew( ToolButton );
- transp->set_toggle_mode(true);
- transp->set_tooltip(TTR("Transpose") + " ("+ED_GET_SHORTCUT("tile_map_editor/transpose")->get_as_text()+")");
- transp->set_focus_mode(FOCUS_NONE);
- transp->connect("pressed", this, "_update_transform_buttons", make_binds(transp));
- toolbar->add_child(transp);
- mirror_x = memnew( ToolButton );
- mirror_x->set_toggle_mode(true);
- mirror_x->set_tooltip(TTR("Mirror X") + " ("+ED_GET_SHORTCUT("tile_map_editor/mirror_x")->get_as_text()+")");
- mirror_x->set_focus_mode(FOCUS_NONE);
- mirror_x->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_x));
- toolbar->add_child(mirror_x);
- mirror_y = memnew( ToolButton );
- mirror_y->set_toggle_mode(true);
- mirror_y->set_tooltip(TTR("Mirror Y") + " ("+ED_GET_SHORTCUT("tile_map_editor/mirror_y")->get_as_text()+")");
- mirror_y->set_focus_mode(FOCUS_NONE);
- mirror_y->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_y));
- toolbar->add_child(mirror_y);
-
- toolbar->add_child( memnew( VSeparator ) );
-
- rotate_0 = memnew( ToolButton );
- rotate_0->set_toggle_mode(true);
- rotate_0->set_tooltip(TTR("Rotate 0 degrees"));
- rotate_0->set_focus_mode(FOCUS_NONE);
- rotate_0->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_0));
- toolbar->add_child(rotate_0);
- rotate_90 = memnew( ToolButton );
- rotate_90->set_toggle_mode(true);
- rotate_90->set_tooltip(TTR("Rotate 90 degrees"));
- rotate_90->set_focus_mode(FOCUS_NONE);
- rotate_90->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_90));
- toolbar->add_child(rotate_90);
- rotate_180 = memnew( ToolButton );
- rotate_180->set_toggle_mode(true);
- rotate_180->set_tooltip(TTR("Rotate 180 degrees"));
- rotate_180->set_focus_mode(FOCUS_NONE);
- rotate_180->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_180));
- toolbar->add_child(rotate_180);
- rotate_270 = memnew( ToolButton );
- rotate_270->set_toggle_mode(true);
- rotate_270->set_tooltip(TTR("Rotate 270 degrees"));
- rotate_270->set_focus_mode(FOCUS_NONE);
- rotate_270->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_270));
- toolbar->add_child(rotate_270);
- toolbar->hide();
-
- rotate_0->set_pressed(true);
-}
-
-TileMapEditor::~TileMapEditor() {
- _clear_bucket_cache();
-}
-
-///////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////
-
-void TileMapEditorPlugin::edit(Object *p_object) {
-
- tile_map_editor->edit(p_object->cast_to<Node>());
-}
-
-bool TileMapEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_class("TileMap");
-}
-
-void TileMapEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- tile_map_editor->show();
- tile_map_editor->get_toolbar()->show();
- } else {
-
- tile_map_editor->hide();
- tile_map_editor->get_toolbar()->hide();
- tile_map_editor->edit(NULL);
- }
-}
-
-TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) {
-
- EDITOR_DEF("editors/tile_map/preview_size",64);
- EDITOR_DEF("editors/tile_map/palette_item_hseparation",8);
- EDITOR_DEF("editors/tile_map/show_tile_names", true);
- EDITOR_DEF("editors/tile_map/bucket_fill_preview", true);
-
- tile_map_editor = memnew( TileMapEditor(p_node) );
- add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE, tile_map_editor);
- tile_map_editor->hide();
-}
-
-TileMapEditorPlugin::~TileMapEditorPlugin()
-{
-}
-
diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h
deleted file mode 100644
index 08032d9afd..0000000000
--- a/tools/editor/plugins/tile_map_editor_plugin.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*************************************************************************/
-/* tile_map_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 TILE_MAP_EDITOR_PLUGIN_H
-#define TILE_MAP_EDITOR_PLUGIN_H
-
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-
-#include "scene/2d/tile_map.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/tool_button.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/label.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class TileMapEditor : public VBoxContainer {
-
- GDCLASS(TileMapEditor, VBoxContainer );
-
- enum Tool {
-
- TOOL_NONE,
- TOOL_PAINTING,
- TOOL_ERASING,
- TOOL_RECTANGLE_PAINT,
- TOOL_RECTANGLE_ERASE,
- TOOL_LINE_PAINT,
- TOOL_LINE_ERASE,
- TOOL_SELECTING,
- TOOL_BUCKET,
- TOOL_PICKING,
- TOOL_DUPLICATING,
- };
-
- enum Options {
-
- OPTION_BUCKET,
- OPTION_PICK_TILE,
- OPTION_SELECT,
- OPTION_DUPLICATE,
- OPTION_ERASE_SELECTION
- };
-
- TileMap *node;
-
- EditorNode *editor;
- UndoRedo *undo_redo;
- Control *canvas_item_editor;
-
- LineEdit *search_box;
- HSlider *size_slider;
- ItemList *palette;
-
- HBoxContainer *toolbar;
-
- Label *tile_info;
- MenuButton *options;
- ToolButton *transp;
- ToolButton *mirror_x;
- ToolButton *mirror_y;
- ToolButton *rotate_0;
- ToolButton *rotate_90;
- ToolButton *rotate_180;
- ToolButton *rotate_270;
-
- Tool tool;
-
- bool selection_active;
- bool mouse_over;
-
- bool flip_h;
- bool flip_v;
- bool transpose;
-
- Point2i rectangle_begin;
- Rect2i rectangle;
-
- Point2i over_tile;
-
- bool * bucket_cache_visited;
- Rect2i bucket_cache_rect;
- int bucket_cache_tile;
- PoolVector<Vector2> bucket_cache;
-
- struct CellOp {
- int idx;
- bool xf;
- bool yf;
- bool tr;
-
- CellOp() { idx=-1; xf=false; yf=false; tr=false; }
- };
-
- Map<Point2i, CellOp> paint_undo;
-
- struct TileData {
- Point2i pos;
- int cell;
- bool flip_h;
- bool flip_v;
- bool transpose;
- };
-
- List<TileData> copydata;
-
- void _pick_tile(const Point2& p_pos);
-
- PoolVector<Vector2> _bucket_fill(const Point2i& p_start, bool erase=false, bool preview=false);
-
- void _fill_points(const PoolVector<Vector2> p_points, const Dictionary& p_op);
- void _erase_points(const PoolVector<Vector2> p_points);
-
- void _select(const Point2i& p_from, const Point2i& p_to);
-
- void _draw_cell(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform);
- void _draw_fill_preview(int p_cell, const Point2i& p_point, bool p_flip_h, bool p_flip_v, bool p_transpose, const Transform2D& p_xform);
- void _clear_bucket_cache();
-
- void _update_copydata();
-
- int get_selected_tile() const;
- void set_selected_tile(int p_tile);
-
- void _text_entered(const String& p_text);
- void _text_changed(const String& p_text);
- void _sbox_input(const InputEvent& p_ie);
- void _update_palette();
- void _canvas_draw();
- void _menu_option(int p_option);
-
- void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_transpose=false, bool p_with_undo=false);
-
- void _canvas_mouse_enter();
- void _canvas_mouse_exit();
- void _tileset_settings_changed();
- void _icon_size_changed(float p_value);
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
- CellOp _get_op_from_cell(const Point2i& p_pos);
- void _update_transform_buttons(Object *p_button=NULL);
-
-public:
-
- HBoxContainer *get_toolbar() const { return toolbar; }
-
- bool forward_gui_input(const InputEvent& p_event);
- void edit(Node *p_tile_map);
-
- TileMapEditor(EditorNode *p_editor);
- ~TileMapEditor();
-};
-
-class TileMapEditorPlugin : public EditorPlugin {
-
- GDCLASS( TileMapEditorPlugin, EditorPlugin );
-
- TileMapEditor *tile_map_editor;
-
-public:
-
- virtual bool forward_canvas_gui_input(const Transform2D& p_canvas_xform,const InputEvent& p_event) { return tile_map_editor->forward_gui_input(p_event); }
-
- virtual String get_name() const { return "TileMap"; }
- 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);
-
- TileMapEditorPlugin(EditorNode *p_node);
- ~TileMapEditorPlugin();
-
-};
-
-
-#endif // TILE_MAP_EDITOR_PLUGIN_H
diff --git a/tools/editor/plugins/tile_set_editor_plugin.h b/tools/editor/plugins/tile_set_editor_plugin.h
deleted file mode 100644
index 7fec7fa162..0000000000
--- a/tools/editor/plugins/tile_set_editor_plugin.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*************************************************************************/
-/* tile_set_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 TILE_SET_EDITOR_PLUGIN_H
-#define TILE_SET_EDITOR_PLUGIN_H
-
-
-
-#include "scene/resources/tile_set.h"
-#include "tools/editor/editor_node.h"
-#include "tools/editor/editor_name_dialog.h"
-
-
-class TileSetEditor : public Control {
-
- GDCLASS( TileSetEditor, Control );
-
- Ref<TileSet> tileset;
-
- EditorNode *editor;
- MenuButton *menu;
- ConfirmationDialog *cd;
- EditorNameDialog *nd;
- AcceptDialog *err_dialog;
-
- enum {
-
- MENU_OPTION_ADD_ITEM,
- MENU_OPTION_REMOVE_ITEM,
- MENU_OPTION_CREATE_FROM_SCENE,
- MENU_OPTION_MERGE_FROM_SCENE
- };
-
- int option;
- void _menu_cbk(int p_option);
- void _menu_confirm();
- void _name_dialog_confirm(const String& name);
-
- static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge);
-
-
-protected:
- static void _bind_methods();
-public:
-
- void edit(const Ref<TileSet>& p_tileset);
- static Error update_library_file(Node *p_base_scene, Ref<TileSet> ml,bool p_merge=true);
-
- TileSetEditor(EditorNode *p_editor);
-};
-
-
-
-class TileSetEditorPlugin : public EditorPlugin {
-
- GDCLASS( TileSetEditorPlugin, EditorPlugin );
-
- TileSetEditor *tileset_editor;
- EditorNode *editor;
-
-public:
-
- virtual String get_name() const { return "TileSet"; }
- 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);
-
-
-
- TileSetEditorPlugin(EditorNode *p_node);
-
-};
-
-
-#endif // TILE_SET_EDITOR_PLUGIN_H
diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp
deleted file mode 100644
index 2fa62df5bc..0000000000
--- a/tools/editor/project_export.cpp
+++ /dev/null
@@ -1,2130 +0,0 @@
-/*************************************************************************/
-/* project_export.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "project_export.h"
-#if 0
-#include "os/dir_access.h"
-#include "os/file_access.h"
-#include "globals.h"
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "os/os.h"
-#include "scene/gui/box_container.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/scroll_container.h"
-#include "editor_data.h"
-#include "io/image_loader.h"
-#include "compressed_translation.h"
-#include "editor_node.h"
-#include "io_plugins/editor_texture_import_plugin.h"
-#include "editor_settings.h"
-
-const char *ProjectExportDialog::da_string[ProjectExportDialog::ACTION_MAX]={
- "",
- "Copy",
- "Bundle"
-};
-
-bool ProjectExportDialog::_create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir) {
-
- TreeItem *item = tree->create_item(p_parent);
- item->set_text(0,p_dir->get_name()+"/");
- item->set_icon(0,get_icon("Folder","EditorIcons"));
-
-
- bool has_items=false;
-
- for(int i=0;i<p_dir->get_subdir_count();i++) {
-
- if (_create_tree(item,p_dir->get_subdir(i)))
- has_items=true;
- }
-
- //int cc = p_options.get_slice_count(",");
-
- for (int i=0;i<p_dir->get_file_count();i++) {
-
- TreeItem *fitem = tree->create_item(item);
- //fitem->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- //fitem->set_editable(0,true);
- //fitem->set_checked(0,isfave);
- fitem->set_text(0,p_dir->get_file(i));
- String path = p_dir->get_file_path(i);
- fitem->set_tooltip(0,path);
- fitem->set_metadata(0,path);
- Ref<Texture> icon = get_icon( (has_icon(p_dir->get_file_type(i),ei)?p_dir->get_file_type(i):ot),ei);
- fitem->set_icon(0,icon);
-
- fitem->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- fitem->set_range_config(1,0,2,1);
- fitem->set_text(1,expopt);
- fitem->set_editable(1,true);
-
- EditorImportExport::FileAction fa = EditorImportExport::get_singleton()->get_export_file_action(path);
- fitem->set_range(1,fa);
-
- has_items=true;
-
- }
-
- if (!has_items) {
-
- memdelete(item);
- return false;
-
- }
-
- return true;
-}
-
-
-void ProjectExportDialog::_tree_changed() {
-
- TreeItem *t=tree->get_selected();
- if (!t)
- return;
-
- String selected = t->get_metadata(0);
-
- EditorImportExport::get_singleton()->set_export_file_action(selected,EditorImportExport::FileAction(int(t->get_range(1))));
- _save_export_cfg();
-
- //editor->save_import_export(true);
- //EditorImportDB::get_singleton()->save_settings();
-
-}
-
-void ProjectExportDialog::popup_export() {
- popup_centered_ratio();
- if (pending_update_tree) {
- _update_tree();
- _update_group_tree();
- pending_update_tree=false;
- }
-}
-
-void ProjectExportDialog::_update_tree() {
-
-
-
- updating_tree=true;
- tree->clear();
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem();
-
- if (efsd) {
- _create_tree(NULL,efsd);
- }
-
- updating_tree=false;
-}
-
-
-
-
-void ProjectExportDialog::_update_platform() {
-
- _validate_platform();
- TreeItem *selected = platforms->get_selected();
- if (!selected)
- return;
-
- String platform = selected->get_metadata(0);
- Ref<EditorExportPlatform> exporter = EditorImportExport::get_singleton()->get_export_platform(platform);
- platform_options->edit( exporter.ptr() );
-}
-
-void ProjectExportDialog::_platform_selected() {
-
- String p =platforms->get_selected()->get_metadata(0);
- _update_platform();
- //editor->save_import_export();
- //EditorFileSystem::get_singleton()->scan();
-
-}
-
-void ProjectExportDialog::_scan_finished() {
-
-/* print_line("**********SCAN DONEEE********");
- print_line("**********SCAN DONEEE********");
- print_line("**********SCAN DONEEE********");
- print_line("**********SCAN DONEEE********");*/
-
- if (!is_visible_in_tree()) {
- pending_update_tree=true;
- return;
- }
-
- _update_tree();
- _update_group_tree();
-}
-
-void ProjectExportDialog::_rescan() {
-
- EditorFileSystem::get_singleton()->scan();
-
-}
-
-void ProjectExportDialog::_update_exporter() {
-
-
-}
-
-
-void ProjectExportDialog::_save_export_cfg() {
-
- EditorImportExport::get_singleton()->save_config();
-}
-
-void ProjectExportDialog::_prop_edited(String what) {
-
- _save_export_cfg();
-
- _validate_platform();
-
-}
-
-void ProjectExportDialog::_filters_edited(String what) {
-
- EditorImportExport::get_singleton()->set_export_custom_filter(what);
- _save_export_cfg();
-}
-
-void ProjectExportDialog::_filters_exclude_edited(String what) {
- EditorImportExport::get_singleton()->set_export_custom_filter_exclude(what);
- _save_export_cfg();
-}
-
-void ProjectExportDialog::_quality_edited(float what) {
-
- EditorImportExport::get_singleton()->set_export_image_quality(what);
- _save_export_cfg();
-}
-
-void ProjectExportDialog::_shrink_edited(float what) {
-
- EditorImportExport::get_singleton()->set_export_image_shrink(what);
- _save_export_cfg();
-}
-
-void ProjectExportDialog::_image_export_edited(int what) {
-
- EditorImportExport::get_singleton()->set_export_image_action(EditorImportExport::ImageAction(what));
- _save_export_cfg();
-}
-
-void ProjectExportDialog::_format_toggled() {
-
- EditorImportExport::get_singleton()->get_image_formats().clear();
-
- for(int i=0;i<formats.size();i++) {
- if (formats[i]->is_checked(0))
- EditorImportExport::get_singleton()->get_image_formats().insert( formats[i]->get_text(0));
-
- }
- _save_export_cfg();
-}
-
-
-void ProjectExportDialog::_script_edited(Variant v) {
-
- if (updating_script)
- return;
- updating_script=true;
- EditorNode::get_undo_redo()->create_action(TTR("Edit Script Options"));
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"script_set_action",script_mode->get_selected());
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"script_set_action",EditorImportExport::get_singleton()->script_get_action());
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"script_set_encryption_key",script_key->get_text());
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"script_set_encryption_key",EditorImportExport::get_singleton()->script_get_encryption_key());
- EditorNode::get_undo_redo()->add_do_method(this,"_update_script");
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_script");
- EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->commit_action();
- updating_script=false;
-
-
-}
-
-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_value() );
- EditorImportExport::get_singleton()->sample_set_trim( sample_trim->is_pressed() );
- _save_export_cfg();
-
-}
-
-void ProjectExportDialog::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
-
- CenterContainer *cc = memnew( CenterContainer );
- TextureRect *tf = memnew( TextureRect);
- tf->set_texture(get_icon("ErrorSign","EditorIcons"));
- cc->add_child(tf);
- plat_errors->add_child(cc);
- platform_error_string->raise();
-
- TreeItem *root = platforms->create_item(NULL);
- List<StringName> ep;
- EditorImportExport::get_singleton()->get_export_platforms(&ep);
- ep.sort_custom<StringName::AlphCompare>();
-
- for(List<StringName>::Element *E=ep.front();E;E=E->next()) {
-
-
- Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(E->get());
- TreeItem *p = platforms->create_item(root);
- p->set_text(0,eep->get_name());
- p->set_icon(0,eep->get_logo());
- p->set_metadata(0,eep->get_name());
- if (eep->get_name()==OS::get_singleton()->get_name())
- p->select(0);
-
- }
-
- EditorFileSystem::get_singleton()->connect("filesystem_changed",this,"_scan_finished");
- //_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() );
- filters_exclude->set_text( EditorImportExport::get_singleton()->get_export_custom_filter_exclude() );
- if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED)
- tree_vb->hide();
- else
- tree_vb->show();
-
- image_action->select(EditorImportExport::get_singleton()->get_export_image_action());
- image_quality->set_value(EditorImportExport::get_singleton()->get_export_image_quality());
- image_shrink->set_value(EditorImportExport::get_singleton()->get_export_image_shrink());
- _update_script();
-
-
- image_quality->connect("value_changed",this,"_quality_edited");
- image_shrink->connect("value_changed",this,"_shrink_edited");
- image_action->connect("item_selected",this,"_image_export_edited");
-
- script_mode->connect("item_selected",this,"_script_edited");
- script_key->connect("text_changed",this,"_script_edited");
-
- for(int i=0;i<formats.size();i++) {
- if (EditorImportExport::get_singleton()->get_image_formats().has(formats[i]->get_text(0)))
- formats[i]->set_checked(0,true);
- }
- image_formats->connect("item_edited",this,"_format_toggled");
- group_add->set_icon(get_icon("Add","EditorIcons"));
- //group_del->set_icon(get_icon("Del","EditorIcons"));
-
- _update_group_list();
- _update_group();
- _update_group_tree();
-
- sample_mode->select( EditorImportExport::get_singleton()->sample_get_action() );
- sample_max_hz->set_value( EditorImportExport::get_singleton()->sample_get_max_hz() );
- sample_trim->set_pressed( EditorImportExport::get_singleton()->sample_get_trim() );
-
- sample_mode->connect("item_selected",this,"_sample_convert_edited");
- sample_max_hz->connect("value_changed",this,"_sample_convert_edited");
- sample_trim->connect("toggled",this,"_sample_convert_edited");
-
-
- } break;
- case NOTIFICATION_EXIT_TREE: {
-
- } break;
- case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
- //something may have changed
- _validate_platform();
-
- } break;
- case NOTIFICATION_VISIBILITY_CHANGED: {
- if (is_visible_in_tree())
- _validate_platform();
-
- } break;
- case NOTIFICATION_PROCESS: {
-
- } break;
- }
-
-}
-
-
-void ProjectExportDialog::_validate_platform() {
-
- get_ok()->set_disabled(true);
- button_export->set_disabled(true);
- TreeItem *selected = platforms->get_selected();
- plat_errors->hide();
- if (!selected) {
- return;
- }
-
- String platform = selected->get_metadata(0);
- Ref<EditorExportPlatform> exporter = EditorImportExport::get_singleton()->get_export_platform(platform);
- if (!exporter.is_valid()) {
- return;
- }
-
- String err;
- if (!exporter->can_export(&err)) {
- Vector<String> items = err.strip_edges().split("\n");
- err="";
- for(int i=0;i<items.size();i++) {
- if (i!=0)
- err+="\n";
- err+=" -"+items[i];
- }
-
- platform_error_string->set_text(err);
- plat_errors->show();
- return;
- }
-
- List<String> pl;
- EditorFileSystem::get_singleton()->get_changed_sources(&pl);
-
- if (false && pl.size()) {
- if (pl.size()==1)
- platform_error_string->set_text(" -One Resource is pending re-import.");
- else
- platform_error_string->set_text(" "+itos(pl.size())+" Resources are pending re-import.");
-
- plat_errors->show();
- return;
- }
-
- get_ok()->set_disabled(false);
- button_export->set_disabled(false);
-
-}
-
-void ProjectExportDialog::_export_mode_changed(int p_idx) {
-
- if (EditorImportExport::get_singleton()->get_export_filter()==p_idx)
- return;
- EditorImportExport::get_singleton()->set_export_filter(EditorImportExport::ExportFilter(p_idx));
-
- if (p_idx!=EditorImportExport::EXPORT_SELECTED)
- tree_vb->hide();
- else
- tree_vb->show();
-
- EditorImportExport::get_singleton()->set_convert_text_scenes( convert_text_scenes->is_pressed() );
-
- _save_export_cfg();
-
-}
-
-void ProjectExportDialog::_export_action(const String& p_file) {
-
- String location = GlobalConfig::get_singleton()->globalize_path(p_file).get_base_dir().replace("\\","/");
-
- while(true) {
-
- print_line("TESTING: "+location.plus_file("godot.cfg"));
- if (FileAccess::exists(location.plus_file("godot.cfg"))) {
-
- error->set_text(TTR("Please export outside the project folder!"));
- error->popup_centered_minsize();
- return;
- }
- String nl = (location+"/..").simplify_path();
- if (nl.find("/")==location.find_last("/"))
- break;
- location=nl;
- }
-
- /* Checked if the export location is outside the project directory,
- * now will check if a file name has been entered */
- if (p_file.ends_with("/")) {
-
- error->set_text("Please enter a file name!");
- error->popup_centered_minsize();
- return;
- }
-
- TreeItem *selected = platforms->get_selected();
- if (!selected)
- return;
-
- String platform = selected->get_metadata(0);
- bool debugging_enabled = EditorImportExport::get_singleton()->get_export_platform(platform)->is_debugging_enabled();
- Error err = export_platform(platform,p_file,debugging_enabled,file_export_password->get_text(),false);
- if (err!=OK) {
- error->set_text(TTR("Error exporting project!"));
- error->popup_centered_minsize();
- }
-
-}
-
-void ProjectExportDialog::_export_action_pck(const String& p_file) {
-
- TreeItem *selected = platforms->get_selected();
- if (!selected)
- return;
-
- Ref<EditorExportPlatform> exporter = EditorImportExport::get_singleton()->get_export_platform(selected->get_metadata(0));
- if (exporter.is_null()) {
- ERR_PRINT("Invalid platform for export of PCK");
- return;
- }
-
- if (p_file.ends_with(".pck")) {
- FileAccess *f = FileAccess::open(p_file,FileAccess::WRITE);
- if (!f) {
- error->set_text(TTR("Error writing the project PCK!"));
- error->popup_centered_minsize();
- }
- ERR_FAIL_COND(!f);
-
- Error err = exporter->save_pack(f,false);
- memdelete(f);
-
- if (err!=OK) {
- error->set_text(TTR("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(TTR("Error exporting project!"));
- error->popup_centered_minsize();
- return;
- }
- }
-}
-
-
-Error ProjectExportDialog::export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password, bool p_quit_after) {
-
- Ref<EditorExportPlatform> exporter = EditorImportExport::get_singleton()->get_export_platform(p_platform);
- if (exporter.is_null()) {
- ERR_PRINT("Invalid platform for export");
-
- List<StringName> platforms;
- EditorImportExport::get_singleton()->get_export_platforms(&platforms);
- print_line("Valid export plaftorms are:");
- for (List<StringName>::Element *E=platforms.front();E;E=E->next())
- print_line(" \""+E->get()+"\"");
-
- if (p_quit_after) {
- OS::get_singleton()->set_exit_code(255);
- get_tree()->quit();
- }
-
- return ERR_INVALID_PARAMETER;
- }
- Error err = exporter->export_project(p_path,p_debug);
- if (err!=OK) {
- error->set_text(TTR("Error exporting project!"));
- error->popup_centered_minsize();
- ERR_PRINT("Exporting failed!");
- if (p_quit_after) {
- OS::get_singleton()->set_exit_code(255);
- get_tree()->quit();
- }
- return ERR_CANT_CREATE;
- } else {
- if (p_quit_after) {
- get_tree()->quit();
- }
- }
-
- return OK;
-
-}
-
-void ProjectExportDialog::ok_pressed() {
- //export pck
- pck_export->popup_centered_ratio();
-
-}
-void ProjectExportDialog::custom_action(const String&) {
- //real export
-
- TreeItem *selected = platforms->get_selected();
- if (!selected)
- return;
-
- String platform = selected->get_metadata(0);
- Ref<EditorExportPlatform> exporter = EditorImportExport::get_singleton()->get_export_platform(platform);
-
- if (exporter.is_null()) {
- error->set_text(vformat(TTR("No exporter for platform '%s' yet."),platform));
- error->popup_centered_minsize();
- return;
- }
-
- if (platform.to_lower()=="android" && _check_android_setting(exporter)==false){
- // not filled all field for Android release
- return;
- }
-
- String extension = exporter->get_binary_extension();
-
- file_export_password->set_editable( exporter->requires_password(exporter->is_debugging_enabled()) );
-
- file_export->clear_filters();
- if (extension!="") {
- file_export->add_filter("*."+extension);
- }
- file_export->popup_centered_ratio();
-
-
-}
-
-LineEdit* ProjectExportDialog::_create_keystore_input(Control* container, const String& p_label, const String& name) {
-
- HBoxContainer* hb=memnew(HBoxContainer);
- Label* lb=memnew(Label);
- LineEdit* input=memnew(LineEdit);
-
- lb->set_text(p_label);
- lb->set_custom_minimum_size(Size2(140*EDSCALE,0));
- lb->set_align(Label::ALIGN_RIGHT);
-
- input->set_custom_minimum_size(Size2(170*EDSCALE,0));
- input->set_name(name);
-
- hb->add_constant_override("separation", 10*EDSCALE);
- hb->add_child(lb);
- hb->add_child(input);
- container->add_child(hb);
-
- return input;
-
-}
-
-void ProjectExportDialog::_create_android_keystore_window() {
-
- keystore_file_dialog = memnew( EditorFileDialog );
- add_child(keystore_file_dialog);
- keystore_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_DIR);
- keystore_file_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- keystore_file_dialog->set_current_dir( "res://" );
-
- keystore_file_dialog->set_title(TTR("Target Path:"));
- keystore_file_dialog->connect("dir_selected", this,"_keystore_dir_selected");
-
- keystore_create_dialog=memnew(ConfirmationDialog);
- VBoxContainer* vb=memnew(VBoxContainer);
- vb->set_size(Size2(340*EDSCALE,0));
- keystore_create_dialog->set_title(TTR("Create Android keystore"));
-
- _create_keystore_input(vb, TTR("Full name"), "name");
- _create_keystore_input(vb, TTR("Organizational unit"), "unit");
- _create_keystore_input(vb, TTR("Organization"), "org");
- _create_keystore_input(vb, TTR("City"), "city");
- _create_keystore_input(vb, TTR("State"), "state");
- _create_keystore_input(vb, TTR("2 letter country code"), "code");
- _create_keystore_input(vb, TTR("User alias"), "alias");
- LineEdit* pass=_create_keystore_input(vb, TTR("Password"), "pass");
- pass->set_placeholder(TTR("at least 6 characters"));
- _create_keystore_input(vb, TTR("File name"), "file");
-
- Label* lb_path=memnew(Label);
- LineEdit* path=memnew(LineEdit);
- Button* btn=memnew(Button);
- HBoxContainer* hb=memnew(HBoxContainer);
-
- lb_path->set_text(TTR("Path : (better to save outside of project)"));
- path->set_h_size_flags(SIZE_EXPAND_FILL);
- path->set_name("path");
- btn->set_text(" .. ");
- btn->connect("pressed", keystore_file_dialog, "popup_centered_ratio");
-
- vb->add_spacer();
- vb->add_child(lb_path);
- hb->add_child(path);
- hb->add_child(btn);
- vb->add_child(hb);
-
- keystore_create_dialog->add_child(vb);
- //keystore_create_dialog->set_child_rect(vb);
- add_child(keystore_create_dialog);
-
- keystore_create_dialog->connect("confirmed", this, "_create_android_keystore");
- path->connect("text_changed", this, "_check_keystore_path");
-
- confirm_keystore = memnew(ConfirmationDialog);
- confirm_keystore->connect("confirmed", keystore_create_dialog, "popup_centered_minsize");
- add_child(confirm_keystore);
-
-}
-
-void ProjectExportDialog::_keystore_dir_selected(const String& path) {
-
- LineEdit* edit=keystore_create_dialog->find_node("path", true, false)->cast_to<LineEdit>();
- edit->set_text(path.simplify_path());
-
-}
-
-void ProjectExportDialog::_keystore_created() {
-
- if (error->is_connected("popup_hide", this, "_keystore_created")){
- error->disconnect("popup_hide", this, "_keystore_created");
- }
- custom_action("export_pck");
-
-}
-
-void ProjectExportDialog::_check_keystore_path(const String& path) {
-
- LineEdit* edit=keystore_create_dialog->find_node("path", true, false)->cast_to<LineEdit>();
- bool exists = DirAccess::exists(path);
- if (!exists) {
- edit->add_color_override("font_color", Color(1,0,0,1));
- } else {
- edit->add_color_override("font_color", Color(0,1,0,1));
- }
-
-}
-
-void ProjectExportDialog::_create_android_keystore() {
-
- Vector<String> names=String("name,unit,org,city,state,code,alias,pass").split(",");
- String path=keystore_create_dialog->find_node("path", true, false)->cast_to<LineEdit>()->get_text();
- String file=keystore_create_dialog->find_node("file", true, false)->cast_to<LineEdit>()->get_text();
-
- if (file.ends_with(".keystore")==false) {
- file+=".keystore";
- }
- String fullpath=path.plus_file(file);
- String info="CN=$name, OU=$unit, O=$org, L=$city, S=$state, C=$code";
- Dictionary dic;
-
- for (int i=0;i<names.size();i++){
- LineEdit* edit = keystore_create_dialog->find_node(names[i], true, false)->cast_to<LineEdit>();
- dic[names[i]]=edit->get_text();
- info=info.replace("$"+names[i], edit->get_text());
- }
-
- String jarsigner=EditorSettings::get_singleton()->get("export/android/jarsigner");
- String keytool=jarsigner.get_base_dir().plus_file("keytool");
- String os_name=OS::get_singleton()->get_name();
- if (os_name.to_lower()=="windows") {
- keytool+=".exe";
- }
-
- bool exist=FileAccess::exists(keytool);
- if (!exist) {
- error->set_text("Can't find 'keytool'");
- error->popup_centered_minsize();
- return;
- }
-
- List<String> args;
- args.push_back("-genkey");
- args.push_back("-v");
- args.push_back("-keystore");
- args.push_back(fullpath);
- args.push_back("-alias");
- args.push_back(dic["alias"]);
- args.push_back("-storepass");
- args.push_back(dic["pass"]);
- args.push_back("-keypass");
- args.push_back(dic["pass"]);
- args.push_back("-keyalg");
- args.push_back("RSA");
- args.push_back("-keysize");
- args.push_back("2048");
- args.push_back("-validity");
- args.push_back("10000");
- args.push_back("-dname");
- args.push_back(info);
- int retval;
- OS::get_singleton()->execute(keytool,args,true,NULL,NULL,&retval);
-
- if (retval==0) { // success
- platform_options->_edit_set("keystore/release", fullpath);
- platform_options->_edit_set("keystore/release_user", dic["alias"]);
- platform_options->_edit_set("keystore/release_password", dic["pass"]);
-
- error->set_text("Android keystore created at \n"+fullpath);
- error->connect("popup_hide", this, "_keystore_created");
- error->popup_centered_minsize();
- } else { // fail
- error->set_text("Fail to create android keystore at \n"+fullpath);
- error->popup_centered_minsize();
- }
-
-}
-
-bool ProjectExportDialog::_check_android_setting(const Ref<EditorExportPlatform>& exporter) {
-
- bool is_debugging = exporter->get("debug/debugging_enabled");
- String release = exporter->get("keystore/release");
- String user = exporter->get("keystore/release_user");
- String password = exporter->get("keystore/release_password");
-
- if (!is_debugging && (release=="" || user=="" || password=="")){
- if (release==""){
- confirm_keystore->set_text(TTR("Release keystore is not set.\nDo you want to create one?"));
- confirm_keystore->popup_centered_minsize();
- } else {
- error->set_text(TTR("Fill Keystore/Release User and Release Password"));
- error->popup_centered_minsize();
- }
- return false;
- }
-
- return true;
-
-}
-
-void ProjectExportDialog::_group_selected() {
-
-
- _update_group(); //?
-
- _update_group_tree();
-}
-
-String ProjectExportDialog::_get_selected_group() {
-
- TreeItem *sel = groups->get_selected();
- if (!sel)
- return String();
-
- return sel->get_text(0);
-
-
-}
-
-void ProjectExportDialog::_update_group_list() {
-
- String current = _get_selected_group();
-
- groups->clear();
- List<StringName> grouplist;
- EditorImportExport::get_singleton()->image_export_get_groups(&grouplist);
- grouplist.sort_custom<StringName::AlphCompare>();
-
- TreeItem *r = groups->create_item();
- for (List<StringName>::Element *E=grouplist.front();E;E=E->next()) {
-
- TreeItem *ti = groups->create_item(r);
- ti->set_text(0,E->get());
- ti->add_button(0,get_icon("Remove","EditorIcons"));
- if (E->get()==current) {
- ti->select(0);
- }
- }
-
- _update_group();
-}
-
-void ProjectExportDialog::_select_group(const String& p_by_name) {
-
- TreeItem *c = groups->get_root();
- if (!c)
- return;
- c=c->get_children();
-
- if (!c)
- return;
-
- while(c) {
-
- if (c->get_text(0)==p_by_name) {
- c->select(0);
- _update_group();
- return;
- }
- c=c->get_next();
- }
-}
-
-void ProjectExportDialog::_update_group() {
-
- if (updating)
- return;
- updating=true;
-
-
- if (_get_selected_group()=="") {
- group_options->hide();
- //group_del->set_disabled(true);
-
- } else {
- group_options->show();
- //group_del->set_disabled(false);
- StringName name = _get_selected_group();
- group_image_action->select(EditorImportExport::get_singleton()->image_export_group_get_image_action(name));
- group_atlas->set_pressed(EditorImportExport::get_singleton()->image_export_group_get_make_atlas(name));
- group_shrink->set_value(EditorImportExport::get_singleton()->image_export_group_get_shrink(name));
- group_lossy_quality->set_value(EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(name));
- if (group_atlas->is_pressed())
- atlas_preview->show();
- else
- atlas_preview->hide();
-
- }
-
- _update_group_tree();
-
- updating=false;
-
-
-}
-
-bool ProjectExportDialog::_update_group_treef(TreeItem *p_parent,EditorFileSystemDirectory *p_dir,const Set<String>& p_extensions,const String& p_groups,const Map<StringName,int>& p_group_index) {
-
- TreeItem *ti = group_images->create_item(p_parent);
- ti->set_text(0,p_dir->get_name()+"/");
- bool has_child=false;
- for(int i=0;i<p_dir->get_subdir_count();i++) {
-
- if (_update_group_treef(ti,p_dir->get_subdir(i),p_extensions,p_groups,p_group_index)) {
- has_child=true;
- }
- }
-
- String filter=group_images_filter->get_text();
- StringName current_group = _get_selected_group();
- String check_text=TTR("Include");
-
- for(int i=0;i<p_dir->get_file_count();i++) {
-
- String fname = p_dir->get_file(i);
- if (p_extensions.has(fname.to_lower().get_extension())) {
- String path = p_dir->get_file_path(i);
-
- if (filter!=String() && path.find(filter)==-1)
- continue;
-
- has_child=true;
- TreeItem *file = group_images->create_item(ti);
- file->set_text(0,fname);
-
- StringName g = EditorImportExport::get_singleton()->image_get_export_group(path);
-
- if (current_group==g || g==StringName()) {
-
- file->set_cell_mode(1,TreeItem::CELL_MODE_CHECK);
- file->set_text(1,check_text);
- file->set_editable(1,true);
- file->set_checked(1,current_group==g);
- } else {
-
- file->set_text(1,g);
- file->set_editable(1,false);
- file->set_selectable(1,false);
- }
-
- file->set_metadata(0,path);
- }
- }
-
- if (!has_child) {
- memdelete(ti);
- return false;
- }
-
- return true;
-
-}
-void ProjectExportDialog::_update_group_tree() {
-
- if (updating)
- return;
-
- group_images->clear();
-
- if (_get_selected_group()=="")
- return;
-
- updating=true;
- print_line("****UGT");
- List<String> img_extensions;
- ImageLoader::get_recognized_extensions(&img_extensions);
- Set<String> extensions;
- for(List<String>::Element *E=img_extensions.front();E;E=E->next()) {
-
- extensions.insert(E->get());
- }
-
- List<StringName> grouplist;
- EditorImportExport::get_singleton()->image_export_get_groups(&grouplist);
- grouplist.sort_custom<StringName::AlphCompare>();
- Map<StringName,int> group_index;
- group_index[StringName()]=0;
- int idx=1;
- String groupenum="--";
- for(List<StringName>::Element *E=grouplist.front();E;E=E->next()) {
-
- group_index[E->get()]=idx++;
- groupenum+=","+String(E->get());
- }
-
- updating=false;
-
-
- _update_group_treef(NULL,EditorFileSystem::get_singleton()->get_filesystem(),extensions,groupenum,group_index);
-
-}
-
-void ProjectExportDialog::_group_changed(Variant v) {
-
- if (updating)
- return;
- if (_get_selected_group()=="")
- return;
- updating=true;
- StringName name = _get_selected_group();
- EditorNode::get_undo_redo()->create_action(TTR("Change Image Group"));
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_export_group_set_image_action",name,group_image_action->get_selected());
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_export_group_set_make_atlas",name,group_atlas->is_pressed());
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_export_group_set_shrink",name,group_shrink->get_value());
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_export_group_set_lossy_quality",name,group_lossy_quality->get_value());
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_image_action",name,EditorImportExport::get_singleton()->image_export_group_get_image_action(name));
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_make_atlas",name,EditorImportExport::get_singleton()->image_export_group_get_make_atlas(name));
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_shrink",name,EditorImportExport::get_singleton()->image_export_group_get_shrink(name));
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_lossy_quality",name,EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(name));
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group");
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group");
- EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->commit_action();
- updating=false;
- // update atlas preview button
- _update_group();
-}
-
-void ProjectExportDialog::_group_item_edited() {
-
- TreeItem *item = group_images->get_edited();
- if (!item)
- return;
- if (_get_selected_group()==String())
- return;
-
- StringName path = item->get_metadata(0);
- String group;
- if (item->is_checked(1)) {
- group=_get_selected_group();
- } else {
- group=String();
- }
-
- print_line("changed "+path+" to group: "+group);
- EditorNode::get_undo_redo()->create_action(TTR("Change Image Group"));
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_add_to_export_group",path,group);
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_add_to_export_group",path,EditorImportExport::get_singleton()->image_get_export_group(path));
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->commit_action();
-
-}
-
-void ProjectExportDialog::_group_add() {
-
- String name = group_new_name->get_text();
-
- if (name=="") {
- group_new_name_error->show();
- group_new_name_error->set_text(TTR("Group name can't be empty!"));
- return;
- }
- if (name.find("/")!=-1 || name.find(":")!=-1 || name.find(",")!=-1 || name.find("-")!=-1) {
- group_new_name_error->set_text(TTR("Invalid character in group name!"));
- group_new_name_error->show();
- return;
- }
-
- if (EditorImportExport::get_singleton()->image_export_has_group(name)) {
- group_new_name_error->set_text(TTR("Group name already exists!"));
- group_new_name_error->show();
- return;
- }
- group_new_name_error->hide();
-
- String current=_get_selected_group();
-
-
- EditorNode::get_undo_redo()->create_action(TTR("Add Image Group"));
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_export_group_create",name);
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_remove",name);
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group_list");
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group_list");
- EditorNode::get_undo_redo()->add_do_method(this,"_select_group",name);
- if (current!="")
- EditorNode::get_undo_redo()->add_undo_method(this,"_select_group",current);
-
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg");
-
- EditorNode::get_undo_redo()->commit_action();
-
-}
-
-
-void ProjectExportDialog::_group_del(Object *p_item, int p_column, int p_button){
-
- TreeItem *item = p_item->cast_to<TreeItem>();
- if (!item)
- return;
- String name = item->get_text(0);
-
- EditorNode::get_undo_redo()->create_action(TTR("Delete Image Group"));
- List<StringName> images_used;
- EditorImportExport::get_singleton()->image_export_get_images_in_group(name,&images_used);
- for (List<StringName>::Element*E=images_used.front();E;E=E->next()) {
-
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_add_to_export_group",E->get(),StringName());
-
- }
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_export_group_remove",name);
-
-
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_create",name);
- for (List<StringName>::Element*E=images_used.front();E;E=E->next()) {
-
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_add_to_export_group",E->get(),name);
-
- }
-
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_image_action",name,EditorImportExport::get_singleton()->image_export_group_get_image_action(name));
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_make_atlas",name,EditorImportExport::get_singleton()->image_export_group_get_make_atlas(name));
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_shrink",name,EditorImportExport::get_singleton()->image_export_group_get_shrink(name));
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_export_group_set_lossy_quality",name,EditorImportExport::get_singleton()->image_export_group_get_lossy_quality(name));
-
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group_list");
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group");
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group_list");
- EditorNode::get_undo_redo()->add_undo_method(this,"_select_group",name);
-
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->commit_action();
-
-}
-
-void ProjectExportDialog::_group_select_all() {
-
-
- String group = _get_selected_group();
- if (group=="")
- return;
-
- TreeItem *item = group_images->get_root();
- if (!item)
- return;
-
- List<StringName> items;
- while(item) {
-
- if (item->get_cell_mode(1)==TreeItem::CELL_MODE_CHECK && !item->is_checked(1))
- items.push_back(item->get_metadata(0));
- item=item->get_next_visible();
- }
-
-
- if (items.size()==0)
- return;
-
- EditorNode::get_undo_redo()->create_action(TTR("Select All"));
-
- for (List<StringName>::Element *E=items.front();E;E=E->next()) {
-
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_add_to_export_group",E->get(),group);
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_add_to_export_group",E->get(),String());
-
- }
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg");
-
- EditorNode::get_undo_redo()->commit_action();
-
-}
-
-void ProjectExportDialog::_group_select_none(){
-
- String group = _get_selected_group();
- if (group=="")
- return;
-
- TreeItem *item = group_images->get_root();
- if (!item)
- return;
-
- List<StringName> items;
- while(item) {
-
- if (item->get_cell_mode(1)==TreeItem::CELL_MODE_CHECK && item->is_checked(1))
- items.push_back(item->get_metadata(0));
- item=item->get_next_visible();
- }
-
-
- if (items.size()==0)
- return;
-
- EditorNode::get_undo_redo()->create_action(TTR("Select All"));
-
- for (List<StringName>::Element *E=items.front();E;E=E->next()) {
-
- EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_add_to_export_group",E->get(),String());
- EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"image_add_to_export_group",E->get(),group);
-
- }
- EditorNode::get_undo_redo()->add_do_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_undo_method(this,"_update_group_tree");
- EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg");
- EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg");
-
- EditorNode::get_undo_redo()->commit_action();
-
-}
-
-void ProjectExportDialog::_group_atlas_preview() {
-
- StringName group = _get_selected_group();
- if (!group)
- return;
-
- atlas_preview_frame->set_texture(Ref<Texture>()); //clear previous
-
- List<StringName> images;
- EditorImportExport::get_singleton()->image_export_get_images_in_group(group,&images);
- images.sort_custom<StringName::AlphCompare>();
-
- String dst_file = EditorSettings::get_singleton()->get_settings_path()+"/tmp/atlas-preview.tex";
- Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
- //imd->set_editor();
-
- for (List<StringName>::Element *F=images.front();F;F=F->next()) {
-
- imd->add_source(EditorImportPlugin::validate_source_path(F->get()));
- }
-
-
- int flags=0;
-
- if (GlobalConfig::get_singleton()->get("image_loader/filter"))
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_FILTER;
- if (!GlobalConfig::get_singleton()->get("image_loader/gen_mipmaps"))
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS;
- if (!GlobalConfig::get_singleton()->get("image_loader/repeat"))
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_REPEAT;
-
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA;
-
- imd->set_option("format",EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSLESS);
- imd->set_option("flags",flags);
- imd->set_option("quality",0.7);
- imd->set_option("atlas",true);
- imd->set_option("crop",true);
-
- Ref<EditorTextureImportPlugin> plugin = EditorImportExport::get_singleton()->get_import_plugin_by_name("texture");
- Error err = plugin->import2(dst_file,imd,EditorExportPlatform::IMAGE_COMPRESSION_NONE,true);
- if (err) {
-
- EditorNode::add_io_error(TTR("Error saving atlas:")+" "+dst_file.get_file());
- return;
- }
-
- Ref<Texture> tex = ResourceLoader::load(dst_file);
- atlas_preview_frame->set_texture(tex); //clear previous
- atlas_preview_dialog->set_title(TTR("Atlas Preview")+" ("+itos(tex->get_width())+"x"+itos(tex->get_height())+")");
- atlas_preview_dialog->popup_centered_ratio(0.9);
-
-}
-
-void ProjectExportDialog::_update_script() {
-
- if (updating_script)
- return;
- updating_script=true;
- script_mode->select(EditorImportExport::get_singleton()->script_get_action());
- script_key->set_text(EditorImportExport::get_singleton()->script_get_encryption_key());
- updating_script=false;
-
-}
-
-void ProjectExportDialog::_image_filter_changed(String) {
-
- _update_group_tree();
-}
-
-void ProjectExportDialog::_bind_methods() {
-
-
- ClassDB::bind_method(_MD("_rescan"),&ProjectExportDialog::_rescan);
- ClassDB::bind_method(_MD("_tree_changed"),&ProjectExportDialog::_tree_changed);
- ClassDB::bind_method(_MD("_scan_finished"),&ProjectExportDialog::_scan_finished);
- ClassDB::bind_method(_MD("_platform_selected"),&ProjectExportDialog::_platform_selected);
- ClassDB::bind_method(_MD("_prop_edited"),&ProjectExportDialog::_prop_edited);
- ClassDB::bind_method(_MD("_export_mode_changed"),&ProjectExportDialog::_export_mode_changed);
- ClassDB::bind_method(_MD("_filters_edited"),&ProjectExportDialog::_filters_edited);
- ClassDB::bind_method(_MD("_filters_exclude_edited"),&ProjectExportDialog::_filters_exclude_edited);
- ClassDB::bind_method(_MD("_export_action"),&ProjectExportDialog::_export_action);
- ClassDB::bind_method(_MD("_export_action_pck"),&ProjectExportDialog::_export_action_pck);
- ClassDB::bind_method(_MD("_quality_edited"),&ProjectExportDialog::_quality_edited);
- ClassDB::bind_method(_MD("_shrink_edited"),&ProjectExportDialog::_shrink_edited);
- ClassDB::bind_method(_MD("_image_export_edited"),&ProjectExportDialog::_image_export_edited);
- ClassDB::bind_method(_MD("_format_toggled"),&ProjectExportDialog::_format_toggled);
- ClassDB::bind_method(_MD("_group_changed"),&ProjectExportDialog::_group_changed);
- ClassDB::bind_method(_MD("_group_add"),&ProjectExportDialog::_group_add);
- ClassDB::bind_method(_MD("_group_del"),&ProjectExportDialog::_group_del);
- ClassDB::bind_method(_MD("_group_selected"),&ProjectExportDialog::_group_selected);
- ClassDB::bind_method(_MD("_update_group"),&ProjectExportDialog::_update_group);
- ClassDB::bind_method(_MD("_update_group_list"),&ProjectExportDialog::_update_group_list);
- ClassDB::bind_method(_MD("_select_group"),&ProjectExportDialog::_select_group);
- ClassDB::bind_method(_MD("_update_group_tree"),&ProjectExportDialog::_update_group_tree);
- ClassDB::bind_method(_MD("_group_item_edited"),&ProjectExportDialog::_group_item_edited);
- ClassDB::bind_method(_MD("_save_export_cfg"),&ProjectExportDialog::_save_export_cfg);
- ClassDB::bind_method(_MD("_image_filter_changed"),&ProjectExportDialog::_image_filter_changed);
- ClassDB::bind_method(_MD("_group_atlas_preview"),&ProjectExportDialog::_group_atlas_preview);
- ClassDB::bind_method(_MD("_group_select_all"),&ProjectExportDialog::_group_select_all);
- ClassDB::bind_method(_MD("_group_select_none"),&ProjectExportDialog::_group_select_none);
- ClassDB::bind_method(_MD("_script_edited"),&ProjectExportDialog::_script_edited);
- ClassDB::bind_method(_MD("_update_script"),&ProjectExportDialog::_update_script);
- ClassDB::bind_method(_MD("_sample_convert_edited"),&ProjectExportDialog::_sample_convert_edited);
-
-
- ClassDB::bind_method(_MD("export_platform"),&ProjectExportDialog::export_platform);
- ClassDB::bind_method(_MD("_create_android_keystore"),&ProjectExportDialog::_create_android_keystore);
- ClassDB::bind_method(_MD("_check_keystore_path"),&ProjectExportDialog::_check_keystore_path);
- ClassDB::bind_method(_MD("_keystore_dir_selected"),&ProjectExportDialog::_keystore_dir_selected);
- ClassDB::bind_method(_MD("_keystore_created"),&ProjectExportDialog::_keystore_created);
-
-
- //ADD_SIGNAL(MethodInfo("instance"));
- //ADD_SIGNAL(MethodInfo("open"));
-
-}
-
-
-ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
-
- editor=p_editor;
- set_title(TTR("Project Export Settings"));
-
- sections = memnew( TabContainer );
- add_child(sections);
- //set_child_rect(sections);
-
- VBoxContainer *pvbox = memnew( VBoxContainer );
- sections->add_child(pvbox);
- pvbox->set_name(TTR("Target"));
-
- HBoxContainer *phbox = memnew( HBoxContainer );
- pvbox->add_child(phbox);
- phbox->set_v_size_flags(SIZE_EXPAND_FILL);
-
- plat_errors = memnew( HBoxContainer );
- pvbox->add_child(plat_errors);
- platform_error_string = memnew( Label );
- platform_error_string->set_h_size_flags(SIZE_EXPAND_FILL);
- plat_errors->add_child(platform_error_string);
-
- VBoxContainer *vb = memnew( VBoxContainer );
- vb->set_h_size_flags(SIZE_EXPAND_FILL);
- vb->set_v_size_flags(SIZE_EXPAND_FILL);
- phbox->add_child(vb);
- platforms = memnew( Tree );
- platforms->set_hide_root(true);
- vb->add_margin_child(TTR("Export to Platform"),platforms,true);
-
- platforms->connect("cell_selected",this,"_platform_selected");
-
-
- vb = memnew(VBoxContainer );
- phbox->add_child(vb);
- vb->set_h_size_flags(SIZE_EXPAND_FILL);
- vb->set_v_size_flags(SIZE_EXPAND_FILL);
- platform_options = memnew( PropertyEditor() );
- platform_options->hide_top_label();
- vb->add_margin_child(TTR("Options"),platform_options,true);
- platform_options->connect("property_edited",this,"_prop_edited");
-
-
-
- //////////////////
-
- vb = memnew( VBoxContainer );
- vb->set_name(TTR("Resources"));
- sections->add_child(vb);
-
- export_mode = memnew( OptionButton );
- export_mode->add_item(TTR("Export selected resources (including dependencies)."));
- export_mode->add_item(TTR("Export all resources in the project."));
- export_mode->add_item(TTR("Export all files in the project directory."));
- export_mode->connect("item_selected",this,"_export_mode_changed");
-
- vb->add_margin_child(TTR("Export Mode:"),export_mode);
-
-
-
- tree_vb = memnew( VBoxContainer );
- vb->add_child(tree_vb);
- tree_vb->set_v_size_flags(SIZE_EXPAND_FILL);
-
- tree = memnew( Tree );
- tree_vb->add_margin_child(TTR("Resources to Export:"),tree,true);
-
- tree->set_v_size_flags(SIZE_EXPAND_FILL);
- tree->connect("item_edited",this,"_tree_changed");
- tree->set_columns(2);
- tree->set_column_titles_visible(true);
- tree->set_column_title(0,TTR("File"));
- tree->set_column_title(1,TTR("Action"));
- tree->set_column_expand(1,false);
- tree->set_column_min_width(1,90);
-
- filters = memnew( LineEdit );
- vb->add_margin_child(TTR("Filters to export non-resource files (comma-separated, e.g.: *.json, *.txt):"),filters);
- filters->connect("text_changed",this,"_filters_edited");
- filters_exclude = memnew( LineEdit );
- vb->add_margin_child(TTR("Filters to exclude from export (comma-separated, e.g.: *.json, *.txt):"),filters_exclude);
- filters_exclude->connect("text_changed",this,"_filters_exclude_edited");
-
- convert_text_scenes = memnew( CheckButton );
- convert_text_scenes->set_text(TTR("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(TTR("Images"));
- image_action = memnew( OptionButton );
- image_action->add_item(TTR("Keep Original"));
- image_action->add_item(TTR("Compress for Disk (Lossy, WebP)"));
- image_action->add_item(TTR("Compress for RAM (BC/PVRTC/ETC)"));
- image_vb->add_margin_child(TTR("Convert Images (*.png):"),image_action);
- HBoxContainer *qhb = memnew( HBoxContainer );
- image_quality = memnew( HSlider );
- qhb->add_child(image_quality);
- image_quality->set_h_size_flags(SIZE_EXPAND_FILL);
- SpinBox *qspin = memnew( SpinBox );
- image_quality->share(qspin);
- qhb->add_child(qspin);
- image_quality->set_min(0);
- image_quality->set_max(1);
- image_quality->set_step(0.01);
- image_vb->add_margin_child(TTR("Compress for Disk (Lossy) Quality:"),qhb);
- image_shrink = memnew( SpinBox );
- image_shrink->set_min(1);
- image_shrink->set_max(8);
- image_shrink->set_step(0.1);
- image_vb->add_margin_child(TTR("Shrink All Images:"),image_shrink);
- sections->add_child(image_vb);
-
- image_formats=memnew(Tree);
- image_formats->set_hide_root(true);
- TreeItem *root = image_formats->create_item(NULL);
- List<String> fmts;
- ImageLoader::get_recognized_extensions(&fmts);
- for(List<String>::Element *E=fmts.front();E;E=E->next()) {
-
- TreeItem *fmt = image_formats->create_item(root);
- fmt->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- fmt->set_text(0,E->get());
- fmt->set_editable(0,true);
- formats.push_back(fmt);
- }
- image_vb->add_margin_child(TTR("Compress Formats:")+" ",image_formats,true);
-
- /// groups
- HBoxContainer *group_hb = memnew( HBoxContainer );
- group_hb->set_name(TTR("Image Groups"));
- sections->add_child(group_hb);
- VBoxContainer *group_vb_left = memnew( VBoxContainer);
- group_hb->add_child(group_vb_left);
-
- VBoxContainer *gvb = memnew(VBoxContainer);
- HBoxContainer *ghb = memnew(HBoxContainer);
- gvb->add_child(ghb);
-
- group_new_name = memnew( LineEdit );
- group_new_name->set_h_size_flags(SIZE_EXPAND_FILL);
- ghb->add_child(group_new_name);
-
- group_add = memnew(ToolButton);
- group_add->connect("pressed",this,"_group_add");
- ghb->add_child(group_add);
-
- group_new_name_error = memnew( Label );
- group_new_name_error->add_color_override("font_color",Color(1,0.4,0.4));
- gvb->add_child(group_new_name_error);
- group_new_name_error->hide();
-
- groups=memnew(Tree);
- groups->set_v_size_flags(SIZE_EXPAND_FILL);
- groups->connect("cell_selected",this,"_group_selected",varray(),CONNECT_DEFERRED);
- groups->connect("button_pressed",this,"_group_del",varray(),CONNECT_DEFERRED);
- groups->set_hide_root(true);
- gvb->add_child(groups);
-
- group_vb_left->add_margin_child(TTR("Groups:"),gvb,true);
- //group_vb_left->add_child( memnew( HSeparator));
- group_options = memnew(VBoxContainer);
- group_vb_left->add_child(group_options);
-
-
- group_image_action = memnew(OptionButton);
- group_image_action->add_item(TTR("Default"));
- group_image_action->add_item(TTR("Compress Disk"));
- group_image_action->add_item(TTR("Compress RAM"));
- group_image_action->add_item(TTR("Keep Original"));
- group_options->add_margin_child(TTR("Compress Mode:"),group_image_action);
- group_image_action->connect("item_selected",this,"_group_changed");
-
- group_lossy_quality = memnew( HSlider );
- group_lossy_quality->set_min(0.1);
- group_lossy_quality->set_max(1.0);
- group_lossy_quality->set_step(0.01);
- group_lossy_quality->set_value(0.7);
- group_lossy_quality->connect("value_changed",this,"_quality_edited");
-
- HBoxContainer *gqhb = memnew( HBoxContainer );
- SpinBox *gqspin = memnew( SpinBox );
- group_lossy_quality->share(gqspin);
- group_lossy_quality->set_h_size_flags(SIZE_EXPAND_FILL);
- gqhb->add_child(group_lossy_quality);
- gqhb->add_child(gqspin);
- group_options->add_margin_child(TTR("Lossy Quality:"),gqhb);
-
- group_atlas = memnew(CheckButton);
- group_atlas->set_pressed(true);
- group_options->add_margin_child(TTR("Atlas:"),group_atlas);
- group_atlas->connect("toggled",this,"_group_changed");
-
- group_shrink = memnew(SpinBox);
- group_shrink->set_min(1);
- group_shrink->set_max(8);
- group_shrink->set_value(1);
- group_shrink->set_step(0.001);
- group_options->add_margin_child(TTR("Shrink By:"),group_shrink);
- group_shrink->connect("value_changed",this,"_group_changed");
-
- atlas_preview = memnew( Button );
- atlas_preview->set_text(TTR("Preview Atlas"));
- group_options->add_child(atlas_preview);
- atlas_preview->show();
- atlas_preview->connect("pressed",this,"_group_atlas_preview");
- Control *ec = memnew(Control );
- ec->set_custom_minimum_size(Size2(150,1));
- gvb->add_child(ec);
-
- VBoxContainer *group_vb_right = memnew( VBoxContainer );
- group_hb->add_child(group_vb_right);
- group_vb_right->set_h_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *filter_hb = memnew (HBoxContainer);
-
- group_images_filter = memnew( LineEdit );
- group_vb_right->add_margin_child(TTR("Image Filter:"),filter_hb);
- filter_hb->add_child(group_images_filter);
- group_images_filter->set_h_size_flags(SIZE_EXPAND_FILL);
- group_images_filter->connect("text_changed",this,"_image_filter_changed");
- group_images = memnew( Tree );
- group_images->set_v_size_flags(SIZE_EXPAND_FILL);
- group_vb_right->add_margin_child(TTR("Images:"),group_images,true);
-
- Button *filt_select_all = memnew( Button );
- filt_select_all->set_text(TTR("Select All"));
- filter_hb->add_child(filt_select_all);
- filt_select_all->connect("pressed",this,"_group_select_all");
-
- Button *filt_select_none = memnew( Button );
- filt_select_none->set_text(TTR("Select None"));
- filter_hb->add_child(filt_select_none);
- filt_select_none->connect("pressed",this,"_group_select_none");
-
- atlas_preview_dialog = memnew( AcceptDialog );
- ScrollContainer *scroll = memnew( ScrollContainer );
- atlas_preview_dialog->add_child(scroll);
- //atlas_preview_dialog->set_child_rect(scroll);
- atlas_preview_frame = memnew( TextureRect );
- scroll->add_child(atlas_preview_frame);
- add_child(atlas_preview_dialog);
-
-
- group_images->set_hide_root(true);
- group_images->set_columns(2);
- group_images->set_column_expand(0,true);
- group_images->set_column_expand(1,false);
- group_images->set_column_min_width(1,100);
- group_images->set_column_titles_visible(true);
- group_images->set_column_title(0,TTR("Images"));
- group_images->set_column_title(1,TTR("Group"));
- group_images->connect("item_edited",this,"_group_item_edited",varray(),CONNECT_DEFERRED);
-
-/* SpinBox *group_shrink;
- CheckButton *group_atlas;
- OptionButton *group_image_action;*/
-
-
-/* progress = memnew( Label );
- add_child(progress);
- progress->set_area_as_parent_rect();
- progress->set_anchor_and_margin(MARGIN_TOP,Control::ANCHOR_BEGIN,25);
- progress->hide();
- progress->set_align(Label::ALIGN_CENTER);*/
-
-/*
- button_reload = memnew( Button );
- button_reload->set_pos(Point2(3,2));
- button_reload->set_size(Point2(20,5));
- button_reload->set_flat(true);
- //add_child(button_reload);
- button_reload->connect("pressed",this,"_rescan");
- hbc->add_child(button_reload);
-*/
-
-
- sample_vbox = memnew( VBoxContainer );
- sample_vbox->set_name(TTR("Samples"));
- sections->add_child(sample_vbox);
- sample_mode = memnew( OptionButton );
- sample_vbox->add_margin_child(TTR("Sample Conversion Mode: (.wav files):"),sample_mode);
- sample_mode->add_item(TTR("Keep"));
- sample_mode->add_item(TTR("Compress (RAM - IMA-ADPCM)"));
- sample_max_hz = memnew( SpinBox );
- sample_max_hz->set_max(192000);
- sample_max_hz->set_min(8000);
- sample_vbox->add_margin_child(TTR("Sampling Rate Limit (Hz):"),sample_max_hz);
- sample_trim = memnew( CheckButton );
- sample_trim->set_text(TTR("Trim"));
- sample_vbox->add_margin_child(TTR("Trailing Silence:"),sample_trim);
-
- script_vbox = memnew( VBoxContainer );
- script_vbox->set_name(TTR("Script"));
- sections->add_child(script_vbox);
- script_mode = memnew( OptionButton );
- script_vbox->add_margin_child(TTR("Script Export Mode:"),script_mode);
- script_mode->add_item(TTR("Text"));
- script_mode->add_item(TTR("Compiled"));
- script_mode->add_item(TTR("Encrypted (Provide Key Below)"));
- script_key = memnew( LineEdit );
- script_vbox->add_margin_child(TTR("Script Encryption Key (256-bits as hex):"),script_key);
-
-
-
- updating=false;
-
- error = memnew( AcceptDialog );
- add_child(error);
-
- confirm = memnew( ConfirmationDialog );
- add_child(confirm);
- confirm->connect("confirmed",this,"_confirmed");
-
- get_ok()->set_text(TTR("Export PCK/Zip"));
-
-
- expopt="--,Export,Bundle";
-
- file_export = memnew( EditorFileDialog );
- add_child(file_export);
- file_export->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- file_export->set_current_dir( EditorSettings::get_singleton()->get("filesystem/directories/default_project_export_path") );
-
- file_export->set_title(TTR("Export Project"));
- file_export->connect("file_selected", this,"_export_action");
-
- file_export_password = memnew( LineEdit );
- file_export_password->set_secret(true);
- file_export_password->set_editable(false);
- file_export->get_vbox()->add_margin_child(TTR("Password:"),file_export_password);
-
- pck_export = memnew( EditorFileDialog );
- pck_export->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- pck_export->set_current_dir( EditorSettings::get_singleton()->get("filesystem/directories/default_project_export_path") );
- pck_export->set_title(TTR("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(TTR("Export.."),!OS::get_singleton()->get_swap_ok_cancel(),"export_pck");
- updating_script=false;
-
- ei="EditorIcons";
- ot="Object";
- pending_update_tree=true;
-
- _create_android_keystore_window();
-}
-
-
-ProjectExportDialog::~ProjectExportDialog() {
-
-
-}
-
-void ProjectExport::popup_export() {
-
- Set<String> presets;
- presets.insert("default");
-
- List<PropertyInfo> pi;
- GlobalConfig::get_singleton()->get_property_list(&pi);
- export_preset->clear();
-
- for (List<PropertyInfo>::Element *E=pi.front();E;E=E->next()) {
-
- if (!E->get().name.begins_with("export_presets/"))
- continue;
- presets.insert(E->get().name.get_slice("/",1));
- }
-
- for(Set<String>::Element *E=presets.front();E;E=E->next()) {
-
- export_preset->add_item(E->get());
- }
-
-
-
- popup_centered(Size2(300,100));
-
-
-
-}
-Error ProjectExport::export_project(const String& p_preset) {
-
- return OK;
-
-#if 0
-
- String selected=p_preset;
-
- PoolVector<String> preset_settings = GlobalConfig::get_singleton()->get("export_presets/"+selected);
- String preset_path=GlobalConfig::get_singleton()->get("export_presets_path/"+selected);
- if (preset_path=="") {
-
- error->set_text("Export path empty, see export options");
- error->popup_centered_minsize(Size2(300,100));
- ERR_FAIL_V(ERR_INVALID_DATA);
- }
-
- int pc=preset_settings.size();
-
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (d->change_dir(preset_path)!=OK) {
-
- memdelete(d);
- error->set_text("Can't access to export path:\n "+preset_path);
- error->popup_centered_minsize(Size2(300,100));
- ERR_FAIL_V(ERR_INVALID_DATA);
- }
-
- if (pc==0) {
- memdelete(d);
- return OK;
- }
- if (pc%3 != 0 ) {
- memdelete(d);
- error->set_text("Corrupted export data..");
- error->popup_centered_minsize(Size2(300,100));
- ERR_EXPLAIN("Corrupted export data...");
- ERR_FAIL_V(ERR_INVALID_DATA);
- }
-
- Map<String,ProjectExportSettings::ItemData> export_action;
-
-
- Map<String,Map<String,String> > remapped_paths;
-
- Set<String> scene_extensions;
- Set<String> resource_extensions;
-
- {
-
- List<String> l;
- /*
- SceneLoader::get_recognized_extensions(&l);
- for(List<String>::Element *E=l.front();E;E=E->next()) {
-
- scene_extensions.insert(E->get());
- }
- */
- ResourceLoader::get_recognized_extensions_for_type("",&l);
- for(List<String>::Element *E=l.front();E;E=E->next()) {
-
- resource_extensions.insert(E->get());
- }
- }
-
- Vector<String> names = GlobalConfig::get_singleton()->get_optimizer_presets();
-
- //prepare base paths
-
- for(int i=0;i<pc;i+=3) {
-
-
- String name = preset_settings[i+0];
- String pname=preset_settings[i+1];
- String deps=preset_settings[i+2];
- int idx=1;
- if (pname=="") {
- pname="copy";
- } else {
-
- for(int j=0;j<names.size();j++) {
- if (pname==names[j]) {
- idx=j+2;
- break;
- }
- }
- }
-
- int dep_idx=0;
-
- for(int j=0;j<ProjectExportSettings::DA_MAX;j++) {
- if (ProjectExportSettings::da_string[j]==deps) {
- dep_idx=j;
- break;
- }
- }
-
- if (idx>=0) {
- export_action[name].action=idx;
- export_action[name].depaction=dep_idx;
- }
-
- }
-
-
- Set<String> bundle_exceptions;
- for (Map<String,ProjectExportSettings::ItemData>::Element *E=export_action.front();E;E=E->next()) {
- bundle_exceptions.insert(E->key());
- }
-
-
- {
-
- // find dependencies and add them to export
-
- Map<String,ProjectExportSettings::ItemData> dependencies;
-
- for (Map<String,ProjectExportSettings::ItemData>::Element *E=export_action.front();E;E=E->next()) {
-
- ProjectExportSettings::ItemData &id=E->get();
-
- if (id.depaction!=ProjectExportSettings::DA_COPY && id.depaction!=ProjectExportSettings::DA_OPTIMIZE)
- continue; //no copy or optimize, go on
- List<String> deplist;
- ResourceLoader::get_dependencies(E->key(),&deplist);
-
- while (deplist.size()) {
-
- String dependency = deplist.front()->get();
- deplist.pop_front();
- if (export_action.has(dependency))
- continue; //taged to export, will not override
- if (dependencies.has(dependency)) {
-
- if (id.action <= dependencies[dependency].action )
- continue;
- }
-
- ProjectExportSettings::ItemData depid;
- if (id.depaction==ProjectExportSettings::DA_COPY || id.action==ProjectExportSettings::DA_COPY)
- depid.action=ProjectExportSettings::DA_COPY;
- else if (id.depaction==ProjectExportSettings::DA_OPTIMIZE)
- depid.action=id.action;
- depid.depaction=0;
-
- dependencies[dependency]=depid;
-
- ResourceLoader::get_dependencies(dependency,&deplist);
- }
-
-
- }
-
- for (Map<String,ProjectExportSettings::ItemData>::Element *E=dependencies.front();E;E=E->next()) {
- export_action[E->key()]=E->get();
- }
- }
-
-
-
- int idx=0;
- for (Map<String,ProjectExportSettings::ItemData>::Element *E=export_action.front();E;E=E->next(),idx++) {
-
-
- String path=E->key();
- if (E->get().action==0)
- continue; //nothing to do here
- String preset;
- if (E->get().action==1)
- preset="";
- else
- preset=names[E->get().action-2];
-
- print_line("Exporting "+itos(idx)+"/"+itos(export_action.size())+": "+path);
-
- String base_dir = GlobalConfig::get_singleton()->localize_path(path.get_base_dir()).replace("\\","/").replace("res://","");
- DirAccess *da=DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- String cwd = d->get_current_dir();
- da->change_dir(cwd);
- print_line("base dir: "+base_dir);
- String remap_platform="all";
-
- for(int j=0;j<base_dir.get_slice_count("/");j++) {
-
- String p = base_dir.get_slice("/",j);
- if (da->change_dir(p)!=OK) {
-
- Error err = da->make_dir(p);
- if (err!=OK) {
- memdelete(da);
- memdelete(d);
- ERR_EXPLAIN("Cannot make dir: "+cwd+"/"+p);
- ERR_FAIL_V(ERR_CANT_CREATE);
- }
-
- if (da->change_dir(p)!=OK) {
-
- memdelete(da);
- memdelete(d);
- ERR_EXPLAIN("Cannot change to dir: "+cwd+"/"+p);
- ERR_FAIL_V(ERR_CANT_CREATE);
- }
-
- }
-
- cwd=da->get_current_dir();
- }
-
- memdelete(da);
- //cwd is the target dir
-
- String source_file;
-
- print_line("Exporting: "+source_file);
- bool delete_source=false;
- if (preset=="") {
- //just copy!
-
- source_file=path;
- delete_source=false;
- } else {
-
- delete_source=true;
- //create an optimized source file
-
- if (!GlobalConfig::get_singleton()->has("optimizer_presets/"+preset)) {
- memdelete(d);
- ERR_EXPLAIN("Unknown optimizer preset: "+preset);
- ERR_FAIL_V(ERR_INVALID_DATA);
- }
-
-
- Dictionary dc = GlobalConfig::get_singleton()->get("optimizer_presets/"+preset);
-
- ERR_FAIL_COND_V(!dc.has("__type__"),ERR_INVALID_DATA);
- String type=dc["__type__"];
-
- Ref<EditorOptimizedSaver> saver;
-
- for(int i=0;i<editor_data->get_optimized_saver_count();i++) {
-
- if (editor_data->get_optimized_saver(i)->get_target_name()==type) {
- saver=editor_data->get_optimized_saver(i);
- }
- }
-
- if (saver.is_null()) {
- memdelete(d);
- ERR_EXPLAIN("Preset '"+preset+"' references nonexistent saver: "+type);
- ERR_FAIL_COND_V(saver.is_null(),ERR_INVALID_DATA);
- }
-
- List<Variant> keys;
- dc.get_key_list(&keys);
-
- saver->clear();
-
- for(List<Variant>::Element *E=keys.front();E;E=E->next()) {
-
- saver->set(E->get(),dc[E->get()]);
- }
-
-
- remap_platform=saver->get_target_platform();
- if (remap_platform=="")
- remap_platform="all";
-
-
- if (resource_extensions.has(path.extension().to_lower())) {
-
- uint32_t flags=0;
-
- /*
- if (saver->is_bundle_scenes_enabled())
- flags|=Reso::FLAG_BUNDLE_INSTANCED_SCENES;
- */
- saver->set_bundle_exceptions(NULL);
- if (E->get().depaction>=ProjectExportSettings::DA_BUNDLE) {
- flags|=ResourceSaver::FLAG_BUNDLE_RESOURCES;
- if (E->get().depaction==ProjectExportSettings::DA_BUNDLE)
- saver->set_bundle_exceptions(&bundle_exceptions);
-
- }
-
- if (saver->is_remove_editor_data_enabled())
- flags|=ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
- if (saver->is_big_endian_data_enabled())
- flags|=ResourceSaver::FLAG_SAVE_BIG_ENDIAN;
-
- RES res = ResourceLoader::load(path);
-
- if (res.is_null()) {
-
- memdelete(d);
- ERR_EXPLAIN("Error loading resource to optimize: "+path);
- ERR_FAIL_V(ERR_INVALID_DATA);
- }
-
- if (saver->is_compress_translations_enabled() && res->get_type()=="Translation") {
-
- Ref<PHashTranslation> ct = Ref<PHashTranslation>( memnew( PHashTranslation ) );
- ct->generate(res);
- res=ct;
- }
-
-
- //dst_file=path.get_file();
- //dst_file = cwd+"/"+dst_file.substr(0,dst_file.length()-dst_file.extension().length())+"opt.scn";
-
- //String write_file = path.substr(0,path.length()-path.extension().length())+"optimized.res";
- String write_file = path+".opt.res";
-
-
- print_line("DST RES FILE: "+write_file);
- Error err = ResourceSaver::save(write_file,res,flags,saver);
- if (err) {
- memdelete(d);
- ERR_EXPLAIN("Error saving optimized resource: "+write_file);
- ERR_FAIL_COND_V(err,ERR_CANT_OPEN);
- }
- source_file=write_file;
- //project_settings->add_remapped_path(src_scene,path,platform);
-
- }
-
-
- }
-
- String dst_file;
- dst_file=cwd+"/"+source_file.get_file();
- print_line("copying from: "+source_file);
- print_line("copying to: "+dst_file);
- Error err = d->copy(source_file,dst_file);
-
- if (delete_source)
- d->remove(source_file);
-
- if (err) {
-
-
- ERR_EXPLAIN("Error copying from: "+source_file+" to "+dst_file+".");
- ERR_FAIL_COND_V(err,err);
- }
-
- String src_remap=path;
- String dst_remap=source_file;
- print_line("remap from: "+src_remap);
- print_line("remap to: "+dst_remap);
- if (src_remap!=dst_remap) {
-
-
- remapped_paths[remap_platform][src_remap]=dst_remap;
- }
-
- //do the copy man...
-
- }
-
- Map<String,Variant> added_settings;
-
-
- for (Map<String,Map<String,String> >::Element *E=remapped_paths.front();E;E=E->next()) {
-
- String platform=E->key();
- PoolVector<String> remaps;
- for(Map<String,String>::Element *F=E->get().front();F;F=F->next() ) {
-
- remaps.push_back(F->key());
- remaps.push_back(F->get());
- }
-
-
-
- //added_settings["remap/"+platform]=remaps;`
- added_settings["remap/"+platform]=Variant(remaps).operator Array();
- }
-
- String engine_cfg_path=d->get_current_dir()+"/godot.cfg";
- print_line("enginecfg: "+engine_cfg_path);
- GlobalConfig::get_singleton()->save_custom(engine_cfg_path,added_settings);
-
- memdelete(d);
- return OK;
-#endif
-}
-
-ProjectExport::ProjectExport(EditorData* p_data) {
-
- editor_data=p_data;
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
- set_title(TTR("Project Export"));
- label = memnew( Label );
- label->set_text(TTR("Export Preset:"));
- vbc->add_child(label);
- export_preset = memnew (OptionButton);
- vbc->add_child(export_preset);
- get_ok()->set_text(TTR("Export"));
- set_hide_on_ok(false);
- error = memnew( AcceptDialog );
- add_child(error);
-
-
-}
-#endif
diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h
deleted file mode 100644
index c528a23121..0000000000
--- a/tools/editor/project_export.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*************************************************************************/
-/* project_export.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PROJECT_EXPORT_SETTINGS_H
-#define PROJECT_EXPORT_SETTINGS_H
-
-#include "scene/main/timer.h"
-#include "scene/gui/control.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/label.h"
-#include "tools/editor/editor_file_dialog.h"
-#include "scene/gui/button.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/tab_container.h"
-#include "os/dir_access.h"
-#include "os/thread.h"
-#include "scene/gui/option_button.h"
-
-#include "scene/gui/slider.h"
-#include "tools/editor/editor_file_system.h"
-#include "property_editor.h"
-#include "editor_import_export.h"
-
-#if 0
-class EditorNode;
-
-class ProjectExportDialog : public ConfirmationDialog {
- GDCLASS( ProjectExportDialog, ConfirmationDialog );
-
-public:
- enum ExportAction {
- ACTION_NONE,
- ACTION_COPY,
- ACTION_BUNDLE,
- ACTION_MAX
-
- };
-
- static const char *da_string[ACTION_MAX];
-
-private:
-
-
- EditorNode *editor;
- String expopt;
-
- TabContainer *sections;
- bool updating_tree;
- bool pending_update_tree;
- AcceptDialog *error;
- ConfirmationDialog *confirm;
- ConfirmationDialog *confirm_keystore;
-
- Button *button_reload;
- LineEdit *filters, *filters_exclude;
- HBoxContainer *plat_errors;
- Label *platform_error_string;
-
- StringName ei;
- StringName ot;
-
- Tree * tree;
-
- EditorFileDialog *pck_export;
- EditorFileDialog *file_export;
- LineEdit *file_export_password;
-
- Button *button_export;
- String _delete_attempt;
-
- bool updating;
-
- void _tree_changed();
- void _update_tree();
-
- bool _create_tree(TreeItem *p_parent,EditorFileSystemDirectory *p_dir);
- void _rescan();
- //void _confirmed();
- void _scan_finished();
-
- void _validate_platform();
- ///////////////////
-
- Tree * platforms;
- PropertyEditor *platform_options;
-
- OptionButton *export_mode;
- CheckButton *convert_text_scenes;
- VBoxContainer *tree_vb;
-
- VBoxContainer *image_vb;
- OptionButton *image_action;
- HSlider *image_quality;
- SpinBox *image_shrink;
- Tree *image_formats;
- Vector<TreeItem*> formats;
-
- LineEdit *group_new_name;
- HSlider *group_lossy_quality;
- Label *group_new_name_error;
- VBoxContainer *group_options;
- Tree *groups;
- SpinBox *group_shrink;
- CheckButton *group_atlas;
- OptionButton *group_image_action;
- Button *group_add;
- Tree *group_images;
- LineEdit *group_images_filter;
- Button *atlas_preview;
-
-
- AcceptDialog *atlas_preview_dialog;
- TextureRect *atlas_preview_frame;
-
-
- VBoxContainer *script_vbox;
- OptionButton *script_mode;
- LineEdit *script_key;
-
- VBoxContainer *sample_vbox;
- OptionButton *sample_mode;
- SpinBox *sample_max_hz;
- CheckButton *sample_trim;
-
- ConfirmationDialog* keystore_create_dialog;
- EditorFileDialog* keystore_file_dialog;
-
-
- void _export_mode_changed(int p_idx);
- void _prop_edited(String what);
-
- void _update_platform();
- void _update_exporter();
- void _platform_selected();
-
- void _filters_edited(String what);
- void _filters_exclude_edited(String what);
- void _update_group_tree();
-
- void _image_filter_changed(String);
- bool _update_group_treef(TreeItem *p_parent,EditorFileSystemDirectory *p_dir,const Set<String>& p_extensions,const String& p_groups,const Map<StringName,int>& p_group_index);
- void _group_item_edited();
- void _group_atlas_preview();
-
-
-
- void _quality_edited(float what);
- void _image_export_edited(int what);
- void _shrink_edited(float what);
-
- void _sample_convert_edited(int what);
-
- void _update_group_list();
- void _select_group(const String& p_by_name);
-
-
- String _get_selected_group();
- void _update_group();
- void _group_changed(Variant v);
- void _group_selected();
- void _group_add();
- void _group_select_all();
- void _group_select_none();
- void _group_del(Object *item,int p_column, int p_button);
-
- bool updating_script;
- void _update_script();
- void _script_edited(Variant v);
- void _export_action(const String& p_file);
- void _export_action_pck(const String& p_file);
- void ok_pressed();
- void custom_action(const String&);
- LineEdit* _create_keystore_input(Control* container, const String& p_label, const String& name);
- void _create_android_keystore_window();
- void _create_android_keystore();
- bool _check_android_setting(const Ref<EditorExportPlatform>& exporter);
- void _check_keystore_path(const String& path);
- void _keystore_dir_selected(const String& path);
- void _keystore_created();
-
- void _save_export_cfg();
- void _format_toggled();
-
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- String get_selected_path() const;
-
- Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false);
-
- void popup_export();
- ProjectExportDialog(EditorNode *p_editor);
- ~ProjectExportDialog();
-};
-
-class EditorData;
-
-class ProjectExport : public ConfirmationDialog {
- GDCLASS( ProjectExport, ConfirmationDialog );
-
- EditorData *editor_data;
-
- AcceptDialog *error;
- Label *label;
- OptionButton *export_preset;
-public:
-
- Error export_project(const String& p_preset);
- void popup_export();
-
-
- ProjectExport(EditorData* p_data);
-
-};
-
-
-#endif // PROJECT_EXPORT_SETTINGS_H
-#endif
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
deleted file mode 100644
index af73414ab0..0000000000
--- a/tools/editor/project_manager.cpp
+++ /dev/null
@@ -1,1516 +0,0 @@
-/*************************************************************************/
-/* project_manager.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "project_manager.h"
-
-#include "version.h"
-#include "os/os.h"
-#include "os/dir_access.h"
-#include "os/file_access.h"
-#include "os/keyboard.h"
-#include "editor_settings.h"
-#include "scene/gui/separator.h"
-#include "scene/gui/tool_button.h"
-#include "io/config_file.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/panel_container.h"
-#include "scene/gui/center_container.h"
-#include "io/stream_peer_ssl.h"
-#include "scene/gui/texture_rect.h"
-#include "scene/gui/margin_container.h"
-#include "io/resource_saver.h"
-#include "editor_themes.h"
-#include "editor_initialize_ssl.h"
-#include "editor_scale.h"
-#include "io/zip_io.h"
-
-class NewProjectDialog : public ConfirmationDialog {
-
- GDCLASS(NewProjectDialog,ConfirmationDialog);
-
-public:
-
- enum Mode {
- MODE_NEW,
- MODE_IMPORT,
- MODE_INSTALL
- };
-private:
-
- Mode mode;
- Label *pp,*pn;
- Label *error;
- LineEdit *project_path;
- LineEdit *project_name;
- FileDialog *fdialog;
- String zip_path;
- String zip_title;
- AcceptDialog *dialog_error;
-
- String _test_path() {
-
- error->set_text("");
- get_ok()->set_disabled(true);
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- String valid_path;
- if (d->change_dir(project_path->get_text())==OK){
- valid_path=project_path->get_text();
- } else if (d->change_dir(project_path->get_text().strip_edges())==OK) {
- valid_path=project_path->get_text().strip_edges();
- }
-
- if (valid_path == "") {
- error->set_text(TTR("Invalid project path, the path must exist!"));
- memdelete(d);
- return "";
- }
-
- if (mode!=MODE_IMPORT) {
-
- if (d->file_exists("godot.cfg")) {
-
- error->set_text(TTR("Invalid project path, godot.cfg must not exist."));
- memdelete(d);
- return "";
- }
-
- } else {
-
- if (valid_path != "" && !d->file_exists("godot.cfg")) {
-
- error->set_text(TTR("Invalid project path, godot.cfg must exist."));
- memdelete(d);
- return "";
- }
- }
-
- memdelete(d);
- get_ok()->set_disabled(false);
- return valid_path;
-
- }
-
- void _path_text_changed(const String& p_path) {
-
- String sp=_test_path();
- if ( sp!="" ) {
-
- sp=sp.replace("\\","/");
- int lidx=sp.find_last("/");
-
- if (lidx!=-1) {
- sp=sp.substr(lidx+1,sp.length());
- }
- if (sp=="" && mode==MODE_IMPORT )
- sp=TTR("Imported Project");
-
- project_name->set_text(sp);
- }
- }
-
- void _file_selected(const String& p_path) {
-
- String p = p_path;
- if (mode==MODE_IMPORT) {
- if (p.ends_with("godot.cfg")) {
-
- p=p.get_base_dir();
- }
- }
- String sp = p.simplify_path();
- project_path->set_text(sp);
- _path_text_changed(sp);
- get_ok()->call_deferred("grab_focus");
- }
-
- void _path_selected(const String& p_path) {
-
- String p = p_path;
- String sp = p.simplify_path();
- project_path->set_text(sp);
- _path_text_changed(sp);
- get_ok()->call_deferred("grab_focus");
- }
-
- void _browse_path() {
-
- if (mode==MODE_IMPORT) {
-
- fdialog->set_mode(FileDialog::MODE_OPEN_FILE);
- fdialog->clear_filters();
- fdialog->add_filter("godot.cfg ; " _MKSTR(VERSION_NAME) " Project");
- } else {
- fdialog->set_mode(FileDialog::MODE_OPEN_DIR);
- }
- fdialog->popup_centered_ratio();
- }
-
- void _text_changed(const String& p_text) {
- _test_path();
- }
-
- void ok_pressed() {
-
- String dir=_test_path();
- if (dir=="") {
- error->set_text(TTR("Invalid project path (changed anything?)."));
- return;
- }
-
- if (mode==MODE_IMPORT) {
- // nothing to do
- } else {
- if (mode==MODE_NEW) {
-
-
-
-
- FileAccess *f = FileAccess::open(dir.plus_file("/godot.cfg"),FileAccess::WRITE);
- if (!f) {
- error->set_text(TTR("Couldn't create godot.cfg in project path."));
- } else {
-
- f->store_line("; Engine configuration file.");
- f->store_line("; It's best edited using the editor UI and not directly,");
- f->store_line("; since the parameters that go here are not all obvious.");
- f->store_line("; ");
- f->store_line("; Format: ");
- f->store_line("; [section] ; section goes between []");
- f->store_line("; param=value ; assign values to parameters");
- f->store_line("\n");
- f->store_line("[application]");
- f->store_line("\n");
- f->store_line("name=\""+project_name->get_text()+"\"");
- f->store_line("icon=\"res://icon.png\"");
-
- memdelete(f);
-
- ResourceSaver::save(dir.plus_file("/icon.png"),get_icon("DefaultProjectIcon","EditorIcons"));
- }
-
- } else if (mode==MODE_INSTALL) {
-
-
- FileAccess *src_f=NULL;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
-
- unzFile pkg = unzOpen2(zip_path.utf8().get_data(), &io);
- if (!pkg) {
-
- dialog_error->set_text("Error opening package file, not in zip format.");
- return;
- }
-
- int ret = unzGoToFirstFile(pkg);
-
- Vector<String> failed_files;
-
- int idx=0;
- while(ret==UNZ_OK) {
-
- //get filename
- unz_file_info info;
- char fname[16384];
- ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
-
- String path=fname;
-
- int depth=1; //stuff from github comes with tag
- bool skip=false;
- while(depth>0) {
- int pp = path.find("/");
- if (pp==-1) {
- skip=true;
- break;
- }
- path=path.substr(pp+1,path.length());
- depth--;
- }
-
-
- if (skip || path==String()) {
- //
- } else if (path.ends_with("/")) { // a dir
-
- path=path.substr(0,path.length()-1);
-
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->make_dir(dir.plus_file(path));
- memdelete(da);
-
- } else {
-
- Vector<uint8_t> data;
- data.resize(info.uncompressed_size);
-
- //read
- unzOpenCurrentFile(pkg);
- unzReadCurrentFile(pkg,data.ptr(),data.size());
- unzCloseCurrentFile(pkg);
-
- FileAccess *f=FileAccess::open(dir.plus_file(path),FileAccess::WRITE);
-
- if (f) {
- f->store_buffer(data.ptr(),data.size());
- memdelete(f);
- } else {
- failed_files.push_back(path);
- }
-
-
- }
-
- idx++;
- ret = unzGoToNextFile(pkg);
- }
-
- unzClose(pkg);
-
- if (failed_files.size()) {
- String msg=TTR("The following files failed extraction from package:")+"\n\n";
- for(int i=0;i<failed_files.size();i++) {
-
- if (i>15) {
- msg+="\nAnd "+itos(failed_files.size()-i)+" more files.";
- break;
- }
- msg+=failed_files[i]+"\n";
- }
-
- dialog_error->set_text(msg);
- dialog_error->popup_centered_minsize();
-
- } else {
- dialog_error->set_text(TTR("Package Installed Successfully!"));
- dialog_error->popup_centered_minsize();
- }
-
- }
-
- }
-
- dir=dir.replace("\\","/");
- if (dir.ends_with("/"))
- dir=dir.substr(0,dir.length()-1);
- String proj=dir.replace("/","::");
- EditorSettings::get_singleton()->set("projects/"+proj,dir);
- EditorSettings::get_singleton()->save();
-
-
-
- hide();
- emit_signal("project_created", dir);
-
- }
-
-protected:
-
- static void _bind_methods() {
-
- ClassDB::bind_method("_browse_path",&NewProjectDialog::_browse_path);
- ClassDB::bind_method("_text_changed",&NewProjectDialog::_text_changed);
- ClassDB::bind_method("_path_text_changed",&NewProjectDialog::_path_text_changed);
- ClassDB::bind_method("_path_selected",&NewProjectDialog::_path_selected);
- ClassDB::bind_method("_file_selected",&NewProjectDialog::_file_selected);
- ADD_SIGNAL( MethodInfo("project_created") );
- }
-
-public:
-
- void set_zip_path(const String& p_path) {
- zip_path=p_path;
- }
- void set_zip_title(const String& p_title) {
- zip_title=p_title;
- }
-
- void set_mode(Mode p_mode) {
-
- mode=p_mode;
- }
-
- void show_dialog() {
-
-
- project_path->clear();
- project_name->clear();
-
- if (mode==MODE_IMPORT) {
- set_title(TTR("Import Existing Project"));
- get_ok()->set_text(TTR("Import"));
- pp->set_text(TTR("Project Path (Must Exist):"));
- pn->set_text(TTR("Project Name:"));
- pn->hide();
- project_name->hide();
-
- popup_centered(Size2(500,125)*EDSCALE);
-
- } else if (mode==MODE_NEW){
-
- set_title(TTR("Create New Project"));
- get_ok()->set_text(TTR("Create"));
- pp->set_text(TTR("Project Path:"));
- pn->set_text(TTR("Project Name:"));
- pn->show();
- project_name->show();
-
- popup_centered(Size2(500,145)*EDSCALE);
- } else if (mode==MODE_INSTALL){
-
- set_title(TTR("Install Project:")+" "+zip_title);
- get_ok()->set_text(TTR("Install"));
- pp->set_text(TTR("Project Path:"));
- pn->hide();
- project_name->hide();
-
- popup_centered(Size2(500,125)*EDSCALE);
-
- }
- project_path->grab_focus();
-
- _test_path();
- }
-
- NewProjectDialog() {
-
-
- VBoxContainer *vb = memnew( VBoxContainer );
- add_child(vb);
- //set_child_rect(vb);
-
- Label* l = memnew(Label);
- l->set_text(TTR("Project Path:"));
- vb->add_child(l);
- pp=l;
-
- project_path = memnew( LineEdit );
- MarginContainer *mc = memnew( MarginContainer );
- vb->add_child(mc);
- HBoxContainer *pphb = memnew( HBoxContainer );
- mc->add_child(pphb);
- pphb->add_child(project_path);
- project_path->set_h_size_flags(SIZE_EXPAND_FILL);
-
- Button* browse = memnew( Button );
- pphb->add_child(browse);
- browse->set_text(TTR("Browse"));
- browse->connect("pressed", this,"_browse_path");
-
- l = memnew(Label);
- l->set_text(TTR("Project Name:"));
- l->set_pos(Point2(5,50));
- vb->add_child(l);
- pn=l;
-
- project_name = memnew( LineEdit );
- mc = memnew( MarginContainer );
- vb->add_child(mc);
- mc->add_child(project_name);
- project_name->set_text(TTR("New Game Project"));
-
-
- l = memnew(Label);
- l->set_text(TTR("That's a BINGO!"));
- vb->add_child(l);
- error=l;
- l->add_color_override("font_color",Color(1,0.4,0.3,0.8));
- l->set_align(Label::ALIGN_CENTER);
-
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- project_path->set_text(d->get_current_dir());
- memdelete(d);
-
- fdialog = memnew( FileDialog );
- add_child(fdialog);
- fdialog->set_access(FileDialog::ACCESS_FILESYSTEM);
- fdialog->set_current_dir( EditorSettings::get_singleton()->get("filesystem/directories/default_project_path") );
- project_name->connect("text_changed", this,"_text_changed");
- project_path->connect("text_changed", this,"_path_text_changed");
- fdialog->connect("dir_selected", this,"_path_selected");
- fdialog->connect("file_selected", this,"_file_selected");
- set_hide_on_ok(false);
- mode=MODE_NEW;
-
- dialog_error = memnew( AcceptDialog );
- add_child(dialog_error);
- }
-
-
-};
-
-struct ProjectItem {
- String project;
- String path;
- String conf;
- uint64_t last_modified;
- bool favorite;
- ProjectItem() {}
- ProjectItem(const String &p_project, const String &p_path, const String &p_conf, uint64_t p_last_modified, bool p_favorite=false) {
- project = p_project; path = p_path; conf = p_conf; last_modified = p_last_modified; favorite=p_favorite;
- }
- _FORCE_INLINE_ bool operator <(const ProjectItem& l) const { return last_modified > l.last_modified; }
- _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);
-
- } else if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
-
- set_process_unhandled_input(is_visible_in_tree());
- }
-}
-
-void ProjectManager::_panel_draw(Node *p_hb) {
-
- HBoxContainer *hb = p_hb->cast_to<HBoxContainer>();
-
- hb->draw_line(Point2(0,hb->get_size().y+1),Point2(hb->get_size().x-10,hb->get_size().y+1),get_color("guide_color","Tree"));
-
- if (selected_list.has(hb->get_meta("name"))) {
- hb->draw_style_box( gui_base->get_stylebox("selected","Tree"),Rect2(Point2(),hb->get_size()-Size2(10,0)));
- }
-}
-
-void ProjectManager::_update_project_buttons()
-{
- for(int i=0;i<scroll_childs->get_child_count();i++) {
-
- CanvasItem *item = scroll_childs->get_child(i)->cast_to<CanvasItem>();
- item->update();
- }
-
- bool has_runnable_scene = false;
- for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
- const String &selected_main = E->get();
- if (selected_main == "") continue;
- has_runnable_scene = true;
- break;
- }
-
- erase_btn->set_disabled(selected_list.size()<1);
- open_btn->set_disabled(selected_list.size()<1);
- run_btn->set_disabled(!has_runnable_scene);
-}
-
-void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) {
-
- if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
-
- String clicked = p_hb->get_meta("name");
- String clicked_main_scene = p_hb->get_meta("main_scene");
-
- if (p_ev.key.mod.shift && selected_list.size()>0 && last_clicked!="" && clicked != last_clicked) {
-
- int clicked_id = -1;
- int last_clicked_id = -1;
- for(int i=0;i<scroll_childs->get_child_count();i++) {
- HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- if (!hb) continue;
- if (hb->get_meta("name") == clicked) clicked_id = i;
- if (hb->get_meta("name") == last_clicked) last_clicked_id = i;
- }
-
- if (last_clicked_id!=-1 && clicked_id!=-1) {
- int min = clicked_id < last_clicked_id? clicked_id : last_clicked_id;
- int max = clicked_id > last_clicked_id? clicked_id : last_clicked_id;
- for(int i=0; i<scroll_childs->get_child_count(); ++i) {
- HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- if (!hb) continue;
- if (i!=clicked_id && (i<min || i>max) && !p_ev.key.mod.control) {
- selected_list.erase(hb->get_meta("name"));
- } else if (i>=min && i<=max) {
- selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
- }
- }
- }
-
- } else if (selected_list.has(clicked) && p_ev.key.mod.control) {
-
- selected_list.erase(clicked);
-
- } else {
-
- last_clicked = clicked;
- if (p_ev.key.mod.control || selected_list.size()==0) {
- selected_list.insert(clicked, clicked_main_scene);
- } else {
- selected_list.clear();
- selected_list.insert(clicked, clicked_main_scene);
- }
- }
-
- _update_project_buttons();
-
- if (p_ev.mouse_button.doubleclick)
- _open_project(); //open if doubleclicked
-
- }
-}
-
-void ProjectManager::_unhandled_input(const InputEvent& p_ev) {
-
- if (p_ev.type==InputEvent::KEY) {
-
- const InputEventKey &k = p_ev.key;
-
- if (!k.pressed)
- return;
-
- bool scancode_handled = true;
-
- switch (k.scancode) {
-
- case KEY_RETURN: {
-
- _open_project();
- } break;
- case KEY_HOME: {
-
- for (int i=0; i<scroll_childs->get_child_count(); i++) {
-
- HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- if (hb) {
- selected_list.clear();
- selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
- scroll->set_v_scroll(0);
- _update_project_buttons();
- break;
- }
- }
-
- } break;
- case KEY_END: {
-
- for (int i=scroll_childs->get_child_count()-1; i>=0; i--) {
-
- HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- if (hb) {
- selected_list.clear();
- selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
- scroll->set_v_scroll(scroll_childs->get_size().y);
- _update_project_buttons();
- break;
- }
- }
-
- } break;
- case KEY_UP: {
-
- if (k.mod.shift)
- break;
-
- if (selected_list.size()) {
-
- bool found = false;
-
- for (int i=scroll_childs->get_child_count()-1; i>=0; i--) {
-
- HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- if (!hb) continue;
-
- String current = hb->get_meta("name");
-
- if (found) {
- selected_list.clear();
- selected_list.insert(current, hb->get_meta("main_scene"));
-
- int offset_diff = scroll->get_v_scroll() - hb->get_pos().y;
-
- if (offset_diff > 0)
- scroll->set_v_scroll(scroll->get_v_scroll() - offset_diff);
-
- _update_project_buttons();
-
- break;
-
- } else if (current==selected_list.back()->key()) {
-
- found = true;
- }
- }
-
- break;
- }
- // else fallthrough to key_down
- }
- case KEY_DOWN: {
-
- if (k.mod.shift)
- break;
-
- bool found = selected_list.empty();
-
- for (int i=0; i<scroll_childs->get_child_count(); i++) {
-
- HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- if (!hb) continue;
-
- String current = hb->get_meta("name");
-
- if (found) {
- selected_list.clear();
- selected_list.insert(current, hb->get_meta("main_scene"));
-
- int last_y_visible = scroll->get_v_scroll() + scroll->get_size().y;
- int offset_diff = (hb->get_pos().y + hb->get_size().y) - last_y_visible;
-
- if (offset_diff > 0)
- scroll->set_v_scroll(scroll->get_v_scroll() + offset_diff);
-
- _update_project_buttons();
-
- break;
-
- } else if (current==selected_list.back()->key()) {
-
- found = true;
- }
- }
-
- } break;
- case KEY_F: {
- if (k.mod.command) this->project_filter->search_box->grab_focus();
- else scancode_handled = false;
- } break;
- default: {
- scancode_handled = false;
- } break;
- }
-
- if (scancode_handled) {
- accept_event();
- }
- }
-}
-
-void ProjectManager::_favorite_pressed(Node *p_hb) {
-
- String clicked = p_hb->get_meta("name");
- bool favorite = !p_hb->get_meta("favorite");
- String proj=clicked.replace(":::",":/");
- proj=proj.replace("::","/");
-
- if (favorite) {
- EditorSettings::get_singleton()->set("favorite_projects/"+clicked,proj);
- } else {
- EditorSettings::get_singleton()->erase("favorite_projects/"+clicked);
- }
- EditorSettings::get_singleton()->save();
- call_deferred("_load_recent_projects");
-}
-
-
-void ProjectManager::_load_recent_projects() {
-
- ProjectListFilter::FilterOption filter_option = project_filter->get_filter_option();
- String search_term = project_filter->get_search_term();
-
- while(scroll_childs->get_child_count()>0) {
- memdelete( scroll_childs->get_child(0));
- }
-
- Map<String, String> selected_list_copy = selected_list;
-
- List<PropertyInfo> properties;
- EditorSettings::get_singleton()->get_property_list(&properties);
-
- Color font_color = gui_base->get_color("font_color","Tree");
-
- List<ProjectItem> projects;
- List<ProjectItem> favorite_projects;
-
- for(List<PropertyInfo>::Element *E=properties.front();E;E=E->next()) {
-
- String _name = E->get().name;
- if (!_name.begins_with("projects/") && !_name.begins_with("favorite_projects/"))
- continue;
-
- String path = EditorSettings::get_singleton()->get(_name);
- if (filter_option == ProjectListFilter::FILTER_PATH && search_term!="" && path.findn(search_term)==-1)
- continue;
-
- String project = _name.get_slice("/",1);
- String conf=path.plus_file("godot.cfg");
- bool favorite = (_name.begins_with("favorite_projects/"))?true:false;
-
- uint64_t last_modified = 0;
- if (FileAccess::exists(conf)) {
- last_modified = FileAccess::get_modified_time(conf);
-
- String fscache = path.plus_file(".fscache");
- if (FileAccess::exists(fscache)) {
- uint64_t cache_modified = FileAccess::get_modified_time(fscache);
- if ( cache_modified > last_modified )
- last_modified = cache_modified;
- }
-
- ProjectItem item(project, path, conf, last_modified, favorite);
- if (favorite)
- favorite_projects.push_back(item);
- else
- projects.push_back(item);
- } else {
- //project doesn't exist on disk but it's in the XML settings file
- EditorSettings::get_singleton()->erase(_name); //remove it
- }
- }
-
- projects.sort();
- favorite_projects.sort();
-
- for(List<ProjectItem>::Element *E=projects.front();E;) {
- List<ProjectItem>::Element *next = E->next();
- if (favorite_projects.find(E->get()) != NULL)
- projects.erase(E->get());
- E=next;
- }
- for(List<ProjectItem>::Element *E=favorite_projects.back();E;E=E->prev()) {
- projects.push_front(E->get());
- }
-
- Ref<Texture> favorite_icon = get_icon("Favorites","EditorIcons");
-
- for(List<ProjectItem>::Element *E=projects.front();E;E=E->next()) {
-
- ProjectItem &item = E->get();
- String project = item.project;
- String path = item.path;
- String conf = item.conf;
- bool is_favorite = item.favorite;
-
- Ref<ConfigFile> cf = memnew( ConfigFile );
- Error err = cf->load(conf);
- ERR_CONTINUE(err!=OK);
-
-
- String project_name=TTR("Unnamed Project");
-
- if (cf->has_section_key("application","name")) {
- project_name = static_cast<String>(cf->get_value("application","name")).xml_unescape();
- }
-
- if (filter_option==ProjectListFilter::FILTER_NAME && search_term!="" && project_name.findn(search_term)==-1)
- continue;
-
- Ref<Texture> icon;
- if (cf->has_section_key("application","icon")) {
- String appicon = cf->get_value("application","icon");
- if (appicon!="") {
- Image img;
- Error err = img.load(appicon.replace_first("res://",path+"/"));
- if (err==OK) {
-
- img.resize(64,64);
- Ref<ImageTexture> it = memnew( ImageTexture );
- it->create_from_image(img);
- icon=it;
- }
- }
- }
-
- if (icon.is_null()) {
- icon=get_icon("DefaultProjectIcon","EditorIcons");
- }
-
- String main_scene;
- if (cf->has_section_key("application","main_scene")) {
- main_scene = cf->get_value("application","main_scene");
- }
-
- selected_list_copy.erase(project);
-
- HBoxContainer *hb = memnew( HBoxContainer );
- hb->set_meta("name",project);
- hb->set_meta("main_scene",main_scene);
- hb->set_meta("favorite",is_favorite);
- hb->connect("draw",this,"_panel_draw",varray(hb));
- hb->connect("gui_input",this,"_panel_input",varray(hb));
- hb->add_constant_override("separation",10*EDSCALE);
-
- VBoxContainer *favorite_box = memnew( VBoxContainer );
- TextureButton *favorite = memnew( TextureButton );
- favorite->set_normal_texture(favorite_icon);
- if (!is_favorite)
- favorite->set_modulate(Color(1,1,1,0.2));
- favorite->set_v_size_flags(SIZE_EXPAND);
- favorite->connect("pressed",this,"_favorite_pressed",varray(hb));
- favorite_box->add_child(favorite);
- hb->add_child(favorite_box);
-
- TextureRect *tf = memnew( TextureRect );
- tf->set_texture(icon);
- hb->add_child(tf);
-
- VBoxContainer *vb = memnew(VBoxContainer);
- vb->set_name("project");
- hb->add_child(vb);
- Control *ec = memnew( Control );
- ec->set_custom_minimum_size(Size2(0,1));
- vb->add_child(ec);
- Label *title = memnew( Label(project_name) );
- title->add_font_override("font", gui_base->get_font("large","Fonts"));
- title->add_color_override("font_color",font_color);
- vb->add_child(title);
- Label *fpath = memnew( Label(path) );
- fpath->set_name("path");
- vb->add_child(fpath);
- fpath->set_modulate(Color(1,1,1,0.5));
- fpath->add_color_override("font_color",font_color);
-
- scroll_childs->add_child(hb);
- }
-
- for (Map<String,String>::Element *E = selected_list_copy.front();E;E = E->next()) {
- String key = E->key();
- selected_list.erase(key);
- }
-
- scroll->set_v_scroll(0);
-
- _update_project_buttons();
-
- EditorSettings::get_singleton()->save();
-
- tabs->set_current_tab(0);
-}
-
-void ProjectManager::_on_project_created(const String& dir) {
- bool has_already=false;
- for (int i=0;i<scroll_childs->get_child_count();i++) {
- HBoxContainer *hb=scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- Label *fpath=hb->get_node(NodePath("project/path"))->cast_to<Label>();
- if (fpath->get_text()==dir) {
- has_already=true;
- break;
- }
- }
- if (has_already) {
- _update_scroll_pos(dir);
- } else {
- _load_recent_projects();
- scroll->connect("draw", this, "_update_scroll_pos", varray(dir), CONNECT_ONESHOT);
- }
-}
-
-void ProjectManager::_update_scroll_pos(const String& dir) {
- for (int i=0;i<scroll_childs->get_child_count();i++) {
- HBoxContainer *hb=scroll_childs->get_child(i)->cast_to<HBoxContainer>();
- Label *fpath=hb->get_node(NodePath("project/path"))->cast_to<Label>();
- if (fpath->get_text()==dir) {
- last_clicked=hb->get_meta("name");
- selected_list.clear();
- selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
- _update_project_buttons();
- int last_y_visible=scroll->get_v_scroll()+scroll->get_size().y;
- int offset_diff=(hb->get_pos().y + hb->get_size().y)-last_y_visible;
-
- if (offset_diff>0)
- scroll->set_v_scroll(scroll->get_v_scroll()+offset_diff);
- break;
- }
- }
-}
-
-void ProjectManager::_open_project_confirm() {
-
- for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
- const String &selected = E->key();
- String path = EditorSettings::get_singleton()->get("projects/"+selected);
- print_line("OPENING: "+path+" ("+selected+")");
-
- List<String> args;
-
- args.push_back("-path");
- args.push_back(path);
-
- args.push_back("-editor");
-
- String exec = OS::get_singleton()->get_executable_path();
-
- OS::ProcessID pid=0;
- Error err = OS::get_singleton()->execute(exec,args,false,&pid);
- ERR_FAIL_COND(err);
- }
-
- get_tree()->quit();
-}
-
-void ProjectManager::_open_project() {
-
- if (selected_list.size()<1) {
- return;
- }
-
- if (selected_list.size()>1) {
- multi_open_ask->set_text(TTR("Are you sure to open more than one project?"));
- multi_open_ask->popup_centered_minsize();
- } else {
- _open_project_confirm();
- }
-}
-
-void ProjectManager::_run_project_confirm() {
-
- for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
-
- const String &selected_main = E->get();
- if (selected_main == "") continue;
-
- const String &selected = E->key();
- String path = EditorSettings::get_singleton()->get("projects/"+selected);
- print_line("OPENING: "+path+" ("+selected+")");
-
- List<String> args;
-
- args.push_back("-path");
- args.push_back(path);
-
- String exec = OS::get_singleton()->get_executable_path();
-
- OS::ProcessID pid=0;
- Error err = OS::get_singleton()->execute(exec,args,false,&pid);
- ERR_FAIL_COND(err);
- }
- //get_scene()->quit(); do not quit
-}
-
-void ProjectManager::_run_project() {
-
-
- if (selected_list.size()<1) {
- return;
- }
-
- if (selected_list.size()>1) {
- multi_run_ask->set_text(TTR("Are you sure to run more than one project?"));
- multi_run_ask->popup_centered_minsize();
- } else {
- _run_project_confirm();
- }
-}
-
-void ProjectManager::_scan_dir(DirAccess *da,float pos, float total,List<String> *r_projects) {
-
-
- List<String> subdirs;
- da->list_dir_begin();
- String n = da->get_next();
- while(n!=String()) {
- if (da->current_is_dir() && !n.begins_with(".")) {
- subdirs.push_front(n);
- } else if (n=="godot.cfg") {
- r_projects->push_back(da->get_current_dir());
- }
- n=da->get_next();
- }
- da->list_dir_end();
- int m=0;
- for(List<String>::Element *E=subdirs.front();E;E=E->next()) {
-
- da->change_dir(E->get());
-
- float slice=total/subdirs.size();
- _scan_dir(da,pos+slice*m,slice,r_projects);
- da->change_dir("..");
- m++;
- }
-
-
-}
-
-
-void ProjectManager::_scan_begin(const String& p_base) {
-
- print_line("SCAN PROJECTS AT: "+p_base);
- List<String> projects;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->change_dir(p_base);
- _scan_dir(da,0,1,&projects);
- memdelete(da);
- print_line("found: "+itos(projects.size())+" projects.");
-
- for(List<String>::Element *E=projects.front();E;E=E->next()) {
- String proj=E->get().replace("/","::");
- EditorSettings::get_singleton()->set("projects/"+proj,E->get());
-
- }
- EditorSettings::get_singleton()->save();
- _load_recent_projects();
-
-}
-
-void ProjectManager::_scan_projects() {
-
- scan_dir->popup_centered_ratio();
-
-}
-
-
-void ProjectManager::_new_project() {
-
- npdialog->set_mode(NewProjectDialog::MODE_NEW);
- npdialog->show_dialog();
-}
-
-
-void ProjectManager::_import_project() {
-
- npdialog->set_mode(NewProjectDialog::MODE_IMPORT);
- npdialog->show_dialog();
-}
-
-void ProjectManager::_erase_project_confirm() {
-
- if (selected_list.size()==0) {
- return;
- }
- for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
- EditorSettings::get_singleton()->erase("projects/"+E->key());
- EditorSettings::get_singleton()->erase("favorite_projects/"+E->key());
- }
- EditorSettings::get_singleton()->save();
- selected_list.clear();
- last_clicked = "";
- _load_recent_projects();
-
-}
-
-void ProjectManager::_erase_project() {
-
- if (selected_list.size()==0)
- return;
-
-
- erase_ask->set_text(TTR("Remove project from the list? (Folder contents will not be modified)"));
- erase_ask->popup_centered_minsize();
-
-}
-
-
-void ProjectManager::_exit_dialog() {
-
- get_tree()->quit();
-}
-
-
-void ProjectManager::_install_project(const String& p_zip_path,const String& p_title) {
-
- npdialog->set_mode(NewProjectDialog::MODE_INSTALL);
- npdialog->set_zip_path(p_zip_path);
- npdialog->set_zip_title(p_title);
- npdialog->show_dialog();
-}
-
-void ProjectManager::_files_dropped(PoolStringArray p_files, int p_screen) {
- Set<String> folders_set;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- for (int i = 0; i < p_files.size(); i++) {
- String file = p_files[i];
- folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
- }
- memdelete(da);
- if (folders_set.size()>0) {
- PoolStringArray folders;
- for (Set<String>::Element *E=folders_set.front();E;E=E->next()) {
- folders.append(E->get());
- }
-
- bool confirm = true;
- if (folders.size()==1) {
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (dir->change_dir(folders[0])==OK) {
- dir->list_dir_begin();
- String file = dir->get_next();
- while(confirm && file!=String()) {
- if (!dir->current_is_dir() && file.ends_with("godot.cfg")) {
- confirm = false;
- }
- file = dir->get_next();
- }
- dir->list_dir_end();
- }
- memdelete(dir);
- }
- if (confirm) {
- multi_scan_ask->get_ok()->disconnect("pressed", this, "_scan_multiple_folders");
- multi_scan_ask->get_ok()->connect("pressed", this, "_scan_multiple_folders", varray(folders));
- multi_scan_ask->set_text(vformat(TTR("You are about the scan %s folders for existing Godot projects. Do you confirm?"), folders.size()));
- multi_scan_ask->popup_centered_minsize();
- } else {
- _scan_multiple_folders(folders);
- }
- }
-}
-
-void ProjectManager::_scan_multiple_folders(PoolStringArray p_files)
-{
- for (int i = 0; i < p_files.size(); i++) {
- _scan_begin(p_files.get(i));
- }
-}
-
-void ProjectManager::_bind_methods() {
-
- ClassDB::bind_method("_open_project",&ProjectManager::_open_project);
- ClassDB::bind_method("_open_project_confirm",&ProjectManager::_open_project_confirm);
- ClassDB::bind_method("_run_project",&ProjectManager::_run_project);
- ClassDB::bind_method("_run_project_confirm",&ProjectManager::_run_project_confirm);
- ClassDB::bind_method("_scan_projects",&ProjectManager::_scan_projects);
- ClassDB::bind_method("_scan_begin",&ProjectManager::_scan_begin);
- ClassDB::bind_method("_import_project",&ProjectManager::_import_project);
- ClassDB::bind_method("_new_project",&ProjectManager::_new_project);
- ClassDB::bind_method("_erase_project",&ProjectManager::_erase_project);
- ClassDB::bind_method("_erase_project_confirm",&ProjectManager::_erase_project_confirm);
- ClassDB::bind_method("_exit_dialog",&ProjectManager::_exit_dialog);
- ClassDB::bind_method("_load_recent_projects",&ProjectManager::_load_recent_projects);
- ClassDB::bind_method("_on_project_created",&ProjectManager::_on_project_created);
- ClassDB::bind_method("_update_scroll_pos",&ProjectManager::_update_scroll_pos);
- ClassDB::bind_method("_panel_draw",&ProjectManager::_panel_draw);
- ClassDB::bind_method("_panel_input",&ProjectManager::_panel_input);
- ClassDB::bind_method("_unhandled_input",&ProjectManager::_unhandled_input);
- ClassDB::bind_method("_favorite_pressed",&ProjectManager::_favorite_pressed);
- ClassDB::bind_method("_install_project",&ProjectManager::_install_project);
- ClassDB::bind_method("_files_dropped",&ProjectManager::_files_dropped);
- ClassDB::bind_method(_MD("_scan_multiple_folders", "files"),&ProjectManager::_scan_multiple_folders);
-
-
-}
-
-ProjectManager::ProjectManager() {
-
- // load settings
- if (!EditorSettings::get_singleton())
- EditorSettings::create();
-
-
- EditorSettings::get_singleton()->set_optimize_save(false); //just write settings as they came
-
- {
- int dpi_mode = EditorSettings::get_singleton()->get("interface/hidpi_mode");
- if (dpi_mode==0) {
- editor_set_scale( OS::get_singleton()->get_screen_dpi(0) > 150 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x>2000 ? 2.0 : 1.0 );
- } else if (dpi_mode==1) {
- editor_set_scale(0.75);
- } else if (dpi_mode==2) {
- editor_set_scale(1.0);
- } else if (dpi_mode==3) {
- editor_set_scale(1.5);
- } else if (dpi_mode==4) {
- editor_set_scale(2.0);
- }
- }
-
- FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesytem/file_dialog/show_hidden_files"));
-
- set_area_as_parent_rect();
- set_theme(create_editor_theme());
-
- gui_base = memnew( Control );
- add_child(gui_base);
- gui_base->set_area_as_parent_rect();
- gui_base->set_theme(create_custom_theme());
-
- Panel *panel = memnew( Panel );
- gui_base->add_child(panel);
- panel->set_area_as_parent_rect();
-
- VBoxContainer *vb = memnew( VBoxContainer );
- panel->add_child(vb);
- vb->set_area_as_parent_rect(20*EDSCALE);
- vb->set_margin(MARGIN_TOP,4*EDSCALE);
- vb->set_margin(MARGIN_BOTTOM,4*EDSCALE);
- vb->add_constant_override("separation",15*EDSCALE);
-
- String cp;
- cp.push_back(0xA9);
- cp.push_back(0);
- OS::get_singleton()->set_window_title(_MKSTR(VERSION_NAME)+String(" - ")+TTR("Project Manager")+" - "+cp+" 2008-2017 Juan Linietsky, Ariel Manzur.");
-
- HBoxContainer *top_hb = memnew( HBoxContainer);
- vb->add_child(top_hb);
- CenterContainer *ccl = memnew( CenterContainer );
- Label *l = memnew( Label );
- l->set_text(_MKSTR(VERSION_NAME)+String(" - ")+TTR("Project Manager"));
- l->add_font_override("font", gui_base->get_font("doc","EditorFonts"));
- ccl->add_child(l);
- top_hb->add_child(ccl);
- top_hb->add_spacer();
- l = memnew( Label );
- l->set_text("v" VERSION_MKSTRING);
- //l->add_font_override("font",get_font("bold","Fonts"));
- l->set_align(Label::ALIGN_CENTER);
- top_hb->add_child(l);
- //vb->add_child(memnew(HSeparator));
- //vb->add_margin_child("\n",memnew(Control));
-
- tabs = memnew( TabContainer );
- vb->add_child(tabs);
- tabs->set_v_size_flags(SIZE_EXPAND_FILL);
-
- HBoxContainer *tree_hb = memnew( HBoxContainer);
- projects_hb = tree_hb;
-
- projects_hb->set_name(TTR("Project List"));
-
- tabs->add_child(tree_hb);
-
- VBoxContainer *search_tree_vb = memnew(VBoxContainer);
- search_tree_vb->set_h_size_flags(SIZE_EXPAND_FILL);
- tree_hb->add_child(search_tree_vb);
-
- HBoxContainer *search_box = memnew(HBoxContainer);
- search_box->add_spacer(true);
- project_filter = memnew(ProjectListFilter);
- search_box->add_child(project_filter);
- project_filter->connect("filter_changed", this, "_load_recent_projects");
- project_filter->set_custom_minimum_size(Size2(250,10));
- search_tree_vb->add_child(search_box);
-
- PanelContainer *pc = memnew( PanelContainer);
- pc->add_style_override("panel", gui_base->get_stylebox("bg","Tree"));
- search_tree_vb->add_child(pc);
- pc->set_v_size_flags(SIZE_EXPAND_FILL);
-
- scroll = memnew( ScrollContainer );
- pc->add_child(scroll);
- scroll->set_enable_h_scroll(false);
-
- VBoxContainer *tree_vb = memnew( VBoxContainer);
- tree_hb->add_child(tree_vb);
- scroll_childs = memnew( VBoxContainer );
- scroll_childs->set_h_size_flags(SIZE_EXPAND_FILL);
- scroll->add_child(scroll_childs);
-
- //HBoxContainer *hb = memnew( HBoxContainer );
- //vb->add_child(hb);
-
- Button *open = memnew( Button );
- open->set_text(TTR("Edit"));
- tree_vb->add_child(open);
- open->connect("pressed", this,"_open_project");
- open_btn=open;
-
- Button *run = memnew( Button );
- run->set_text(TTR("Run"));
- tree_vb->add_child(run);
- run->connect("pressed", this,"_run_project");
- run_btn=run;
-
- tree_vb->add_child(memnew( HSeparator ));
-
- Button *scan = memnew( Button );
- scan->set_text(TTR("Scan"));
- tree_vb->add_child(scan);
- scan->connect("pressed", this,"_scan_projects");
-
- tree_vb->add_child(memnew( HSeparator ));
-
- scan_dir = memnew( FileDialog );
- scan_dir->set_access(FileDialog::ACCESS_FILESYSTEM);
- scan_dir->set_mode(FileDialog::MODE_OPEN_DIR);
- scan_dir->set_title(TTR("Select a Folder to Scan")); // must be after mode or it's overridden
- scan_dir->set_current_dir( EditorSettings::get_singleton()->get("filesystem/directories/default_project_path") );
- gui_base->add_child(scan_dir);
- scan_dir->connect("dir_selected",this,"_scan_begin");
-
-
- Button* create = memnew( Button );
- create->set_text(TTR("New Project"));
- tree_vb->add_child(create);
- create->connect("pressed", this,"_new_project");
-
- Button* import = memnew( Button );
- import->set_text(TTR("Import"));
- tree_vb->add_child(import);
- import->connect("pressed", this,"_import_project");
-
-
- Button* erase = memnew( Button );
- erase->set_text(TTR("Remove"));
- tree_vb->add_child(erase);
- erase->connect("pressed", this,"_erase_project");
- erase_btn=erase;
-
-
- tree_vb->add_spacer();
-
-
- if (StreamPeerSSL::is_available()) {
- asset_library = memnew( EditorAssetLibrary(true) );
- asset_library->set_name("Templates");
- tabs->add_child(asset_library);
- asset_library->connect("install_asset",this,"_install_project");
- } else {
- WARN_PRINT("Asset Library not available, as it requires SSL to work.");
- }
-
-
- CenterContainer *cc = memnew( CenterContainer );
- Button * cancel = memnew( Button );
- cancel->set_text(TTR("Exit"));
- cancel->set_custom_minimum_size(Size2(100,1)*EDSCALE);
- cc->add_child(cancel);
- cancel->connect("pressed", this,"_exit_dialog");
- vb->add_child(cc);
-
- //
-
- erase_ask = memnew( ConfirmationDialog );
- erase_ask->get_ok()->set_text(TTR("Remove"));
- erase_ask->get_ok()->connect("pressed", this,"_erase_project_confirm");
-
- gui_base->add_child(erase_ask);
-
- multi_open_ask = memnew( ConfirmationDialog );
- multi_open_ask->get_ok()->set_text(TTR("Edit"));
- multi_open_ask->get_ok()->connect("pressed", this, "_open_project_confirm");
-
- gui_base->add_child(multi_open_ask);
-
- multi_run_ask = memnew( ConfirmationDialog );
- multi_run_ask->get_ok()->set_text(TTR("Run"));
- multi_run_ask->get_ok()->connect("pressed", this, "_run_project_confirm");
-
- gui_base->add_child(multi_run_ask);
-
- multi_scan_ask = memnew( ConfirmationDialog );
- multi_scan_ask->get_ok()->set_text(TTR("Scan"));
-
- gui_base->add_child(multi_scan_ask);
-
- OS::get_singleton()->set_low_processor_usage_mode(true);
-
- npdialog = memnew( NewProjectDialog );
- gui_base->add_child(npdialog);
-
- npdialog->connect("project_created", this,"_on_project_created");
- _load_recent_projects();
-
- if ( EditorSettings::get_singleton()->get("filesystem/directories/autoscan_project_path") ) {
- _scan_begin( EditorSettings::get_singleton()->get("filesystem/directories/autoscan_project_path") );
- }
-
- //get_ok()->set_text("Open");
- //get_ok()->set_text("Exit");
-
- last_clicked = "";
-
- SceneTree::get_singleton()->connect("files_dropped", this, "_files_dropped");
-}
-
-
-ProjectManager::~ProjectManager() {
-
- if (EditorSettings::get_singleton())
- EditorSettings::destroy();
-}
-
-void ProjectListFilter::_setup_filters() {
-
- filter_option->clear();
- filter_option->add_item(TTR("Name"));
- filter_option->add_item(TTR("Path"));
-}
-
-void ProjectListFilter::_command(int p_command) {
- switch (p_command) {
-
- case CMD_CLEAR_FILTER: {
- if (search_box->get_text()!="") {
- search_box->clear();
- emit_signal("filter_changed");
- }
- }break;
- }
-}
-
-void ProjectListFilter::_search_text_changed(const String &p_newtext) {
- emit_signal("filter_changed");
-}
-
-String ProjectListFilter::get_search_term() {
- return search_box->get_text().strip_edges();
-}
-
-ProjectListFilter::FilterOption ProjectListFilter::get_filter_option() {
- return _current_filter;
-}
-
-void ProjectListFilter::_filter_option_selected(int p_idx) {
- FilterOption selected = (FilterOption)(filter_option->get_selected());
- if (_current_filter != selected ) {
- _current_filter = selected;
- emit_signal("filter_changed");
- }
-}
-
-void ProjectListFilter::_notification(int p_what) {
- switch(p_what) {
- case NOTIFICATION_ENTER_TREE: {
- clear_search_button->set_icon(get_icon("CloseHover","EditorIcons"));
- } break;
- }
-}
-
-void ProjectListFilter::_bind_methods() {
-
- ClassDB::bind_method(_MD("_command"),&ProjectListFilter::_command);
- ClassDB::bind_method(_MD("_search_text_changed"), &ProjectListFilter::_search_text_changed);
- ClassDB::bind_method(_MD("_filter_option_selected"), &ProjectListFilter::_filter_option_selected);
-
- ADD_SIGNAL( MethodInfo("filter_changed") );
-}
-
-ProjectListFilter::ProjectListFilter() {
-
- editor_initialize_certificates(); //for asset sharing
-
- _current_filter = FILTER_NAME;
-
- filter_option = memnew(OptionButton);
- filter_option->set_custom_minimum_size(Size2(80,10));
- filter_option->set_clip_text(true);
- filter_option->connect("item_selected", this, "_filter_option_selected");
- add_child(filter_option);
-
- _setup_filters();
-
- search_box = memnew( LineEdit );
- search_box->connect("text_changed",this,"_search_text_changed");
- search_box->set_h_size_flags(SIZE_EXPAND_FILL);
- add_child(search_box);
-
- clear_search_button = memnew( ToolButton );
- clear_search_button->connect("pressed",this,"_command",make_binds(CMD_CLEAR_FILTER));
- add_child(clear_search_button);
-
-}
diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h
deleted file mode 100644
index 1fd8a301ea..0000000000
--- a/tools/editor/project_manager.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*************************************************************************/
-/* project_manager.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PROJECT_MANAGER_H
-#define PROJECT_MANAGER_H
-
-#include "scene/gui/dialogs.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/scroll_container.h"
-#include "scene/gui/file_dialog.h"
-#include "scene/gui/tool_button.h"
-#include "tools/editor/asset_library_editor_plugin.h"
-
-class NewProjectDialog;
-class ProjectListFilter;
-
-class ProjectManager : public Control {
- GDCLASS( ProjectManager, Control );
-
- Button *erase_btn;
- Button *open_btn;
- Button *run_btn;
-
- FileDialog *scan_dir;
-
- EditorAssetLibrary *asset_library;
-
- ProjectListFilter *project_filter;
-
- ConfirmationDialog *erase_ask;
- ConfirmationDialog *multi_open_ask;
- ConfirmationDialog *multi_run_ask;
- ConfirmationDialog *multi_scan_ask;
- NewProjectDialog *npdialog;
- ScrollContainer *scroll;
- VBoxContainer *scroll_childs;
- Map<String, String> selected_list; // name -> main_scene
- String last_clicked;
- bool importing;
-
- HBoxContainer *projects_hb;
-
- TabContainer *tabs;
-
- Control *gui_base;
-
-
-
- void _scan_projects();
- void _run_project();
- void _run_project_confirm();
- void _open_project();
- void _open_project_confirm();
- void _import_project();
- void _new_project();
- void _erase_project();
- void _erase_project_confirm();
- void _update_project_buttons();
- void _exit_dialog();
- void _scan_begin(const String& p_base);
-
- void _load_recent_projects();
- void _on_project_created(const String& dir);
- void _update_scroll_pos(const String& dir);
- void _scan_dir(DirAccess *da,float pos, float total,List<String> *r_projects);
-
- void _install_project(const String& p_zip_path,const String& p_title);
-
- void _panel_draw(Node *p_hb);
- void _panel_input(const InputEvent& p_ev,Node *p_hb);
- void _unhandled_input(const InputEvent& p_ev);
- void _favorite_pressed(Node *p_hb);
- void _files_dropped(PoolStringArray p_files, int p_screen);
- void _scan_multiple_folders(PoolStringArray p_files);
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
- ProjectManager();
- ~ProjectManager();
-};
-
-class ProjectListFilter : public HBoxContainer {
-
- GDCLASS( ProjectListFilter, HBoxContainer );
-
-private:
-
- friend class ProjectManager;
-
- enum Command {
- CMD_CLEAR_FILTER,
- };
-
- OptionButton *filter_option;
- LineEdit *search_box;
- ToolButton *clear_search_button;
-
- enum FilterOption {
- FILTER_NAME,
- FILTER_PATH,
- };
- FilterOption _current_filter;
-
- void _command(int p_command);
- void _search_text_changed(const String& p_newtext);
- void _setup_filters();
- void _filter_option_selected(int p_idx);
-
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
- String get_search_term();
- FilterOption get_filter_option();
- ProjectListFilter();
-};
-
-#endif // PROJECT_MANAGER_H
diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp
deleted file mode 100644
index e725786f94..0000000000
--- a/tools/editor/project_settings.cpp
+++ /dev/null
@@ -1,1588 +0,0 @@
-/*************************************************************************/
-/* project_settings.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "project_settings.h"
-
-#include "scene/gui/tab_container.h"
-#include "globals.h"
-#include "os/keyboard.h"
-#include "editor_node.h"
-#include "scene/gui/margin_container.h"
-#include "translation.h"
-#include "global_constants.h"
-
-ProjectSettings *ProjectSettings::singleton=NULL;
-
-static const char* _button_names[JOY_BUTTON_MAX]={
-"PS X, XBox A, Nintendo B",
-"PS Circle, XBox B, Nintendo A",
-"PS Square, XBox X, Nintendo Y",
-"PS Triangle, XBox Y, Nintendo X",
-"L, L1",
-"R, R1",
-"L2",
-"R2",
-"L3",
-"R3",
-"Select, Nintendo -",
-"Start, Nintendo +",
-"D-Pad Up",
-"D-Pad Down",
-"D-Pad Left",
-"D-Pad Right"
-};
-
-static const char* _axis_names[JOY_AXIS_MAX*2] = {
- " (Left Stick Left)",
- " (Left Stick Right)",
- " (Left Stick Up)",
- " (Left Stick Down)",
- " (Right Stick Left)",
- " (Right Stick Right)",
- " (Right Stick Up)",
- " (Right Stick Down)",
- "","","","",
- "", " (L2)",
- "", " (R2)"
-};
-
-void ProjectSettings::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- globals_editor->edit(GlobalConfig::get_singleton());
-
- search_button->set_icon(get_icon("Zoom","EditorIcons"));
- clear_button->set_icon(get_icon("Close","EditorIcons"));
-
- translation_list->connect("button_pressed",this,"_translation_delete");
- _update_actions();
- popup_add->add_icon_item(get_icon("Keyboard","EditorIcons"),TTR("Key "),InputEvent::KEY);//"Key " - because the word 'key' has already been used as a key animation
- popup_add->add_icon_item(get_icon("JoyButton","EditorIcons"),TTR("Joy Button"),InputEvent::JOYPAD_BUTTON);
- popup_add->add_icon_item(get_icon("JoyAxis","EditorIcons"),TTR("Joy Axis"),InputEvent::JOYPAD_MOTION);
- popup_add->add_icon_item(get_icon("Mouse","EditorIcons"),TTR("Mouse Button"),InputEvent::MOUSE_BUTTON);
-
- List<String> tfn;
- ResourceLoader::get_recognized_extensions_for_type("Translation",&tfn);
- for (List<String>::Element *E=tfn.front();E;E=E->next()) {
-
- translation_file_open->add_filter("*."+E->get());
- }
-
- List<String> rfn;
- ResourceLoader::get_recognized_extensions_for_type("Resource",&rfn);
- for (List<String>::Element *E=rfn.front();E;E=E->next()) {
-
- translation_res_file_open->add_filter("*."+E->get());
- translation_res_option_file_open->add_filter("*."+E->get());
- }
- }
-}
-
-void ProjectSettings::_action_selected() {
-
- TreeItem *ti=input_editor->get_selected();
- if (!ti || !ti->is_editable(0))
- return;
-
- add_at="input/"+ti->get_text(0);
-}
-
-void ProjectSettings::_action_edited() {
-
- TreeItem *ti=input_editor->get_selected();
- if (!ti)
- return;
-
- String new_name=ti->get_text(0);
- String old_name=add_at.substr(add_at.find("/")+1,add_at.length());
-
- if (new_name==old_name)
- return;
-
- if (new_name.find("/")!=-1 || new_name.find(":")!=-1 || new_name=="") {
-
- ti->set_text(0,old_name);
- add_at="input/"+old_name;
-
- message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
- message->popup_centered(Size2(300,100));
- return;
- }
-
- String action_prop="input/"+new_name;
-
- if (GlobalConfig::get_singleton()->has(action_prop)) {
-
- ti->set_text(0,old_name);
- add_at="input/"+old_name;
-
- message->set_text(vformat(TTR("Action '%s' already exists!"),new_name));
- message->popup_centered(Size2(300,100));
- return;
- }
-
- int order = GlobalConfig::get_singleton()->get_order(add_at);
- Array va = GlobalConfig::get_singleton()->get(add_at);
-
- setting=true;
- undo_redo->create_action(TTR("Rename Input Action Event"));
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"clear",add_at);
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",action_prop,va);
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"set_order",action_prop,order);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"clear",action_prop);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",add_at,va);
- undo_redo->add_undo_method(GlobalConfig::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();
- setting=false;
-
- add_at=action_prop;
-
-}
-
-
-void ProjectSettings::_device_input_add() {
-
-
-
-
- InputEvent ie;
- String name=add_at;
- Variant old_val = GlobalConfig::get_singleton()->get(name);
- Array arr=old_val;
- ie.device=device_id->get_value();
-
- ie.type=add_type;
-
- switch(add_type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
-
- ie.mouse_button.button_index=device_index->get_selected()+1;
-
- for(int i=0;i<arr.size();i++) {
-
- InputEvent aie=arr[i];
- if (aie.device == ie.device && aie.type==InputEvent::MOUSE_BUTTON && aie.mouse_button.button_index==ie.mouse_button.button_index) {
- return;
- }
- }
-
- } break;
- case InputEvent::JOYPAD_MOTION: {
-
- 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::JOYPAD_MOTION && aie.joy_motion.axis==ie.joy_motion.axis && aie.joy_motion.axis_value==ie.joy_motion.axis_value) {
- return;
- }
- }
-
- } break;
- case InputEvent::JOYPAD_BUTTON: {
-
- ie.joy_button.button_index=device_index->get_selected();
-
- for(int i=0;i<arr.size();i++) {
-
- InputEvent aie=arr[i];
- if (aie.device == ie.device && aie.type==InputEvent::JOYPAD_BUTTON && aie.joy_button.button_index==ie.joy_button.button_index) {
- return;
- }
- }
-
- } break;
- default:{}
- }
-
-
- arr.push_back(ie);
-
- undo_redo->create_action(TTR("Add Input Action Event"));
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,arr);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
- 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();
-
- _show_last_added(ie);
-}
-
-
-void ProjectSettings::_press_a_key_confirm() {
-
- if (last_wait_for_key.type!=InputEvent::KEY)
- return;
-
- InputEvent ie;
- ie.type=InputEvent::KEY;
- ie.key.scancode=last_wait_for_key.key.scancode;
- ie.key.mod=last_wait_for_key.key.mod;
- String name=add_at;
-
- Variant old_val = GlobalConfig::get_singleton()->get(name);
- Array arr=old_val;
-
- for(int i=0;i<arr.size();i++) {
-
- InputEvent aie=arr[i];
- if (aie.type==InputEvent::KEY && aie.key.scancode==ie.key.scancode && aie.key.mod==ie.key.mod) {
- return;
- }
- }
-
- arr.push_back(ie);
-
- undo_redo->create_action(TTR("Add Input Action Event"));
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,arr);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
- 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();
-
- _show_last_added(ie);
-}
-
-void ProjectSettings::_show_last_added(const InputEvent& p_event) {
- TreeItem *r = input_editor->get_root();
-
- if (!r)
- return;
- r=r->get_children();
- if (!r)
- return;
- bool found = false;
- while(r){
- TreeItem *child = r->get_children();
- while(child){
- Variant input = child->get_meta("__input");
- if (p_event==input){
- child->select(0);
- found = true;
- break;
- }
- child=child->get_next();
- }
- if (found) break;
- r=r->get_next();
- }
-
- if (found) input_editor->ensure_cursor_is_visible();
-}
-
-void ProjectSettings::_wait_for_key(const InputEvent& p_event) {
-
-
- if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode!=0) {
-
- last_wait_for_key=p_event;
- String str=keycode_get_string(p_event.key.scancode).capitalize();
- if (p_event.key.mod.meta)
- str=TTR("Meta+")+str;
- if (p_event.key.mod.shift)
- str=TTR("Shift+")+str;
- if (p_event.key.mod.alt)
- str=TTR("Alt+")+str;
- if (p_event.key.mod.control)
- str=TTR("Control+")+str;
-
-
- press_a_key_label->set_text(str);
- press_a_key->accept_event();
-
- }
-}
-
-
-void ProjectSettings::_add_item(int p_item){
-
- add_type=InputEvent::Type(p_item);
-
- switch(add_type) {
-
- case InputEvent::KEY: {
-
- press_a_key_label->set_text(TTR("Press a Key.."));
- last_wait_for_key=InputEvent();
- press_a_key->popup_centered(Size2(250,80)*EDSCALE);
- press_a_key->grab_focus();
- } break;
- case InputEvent::MOUSE_BUTTON: {
-
- device_id->set_value(0);
- device_index_label->set_text(TTR("Mouse Button Index:"));
- device_index->clear();
- device_index->add_item(TTR("Left Button"));
- device_index->add_item(TTR("Right Button"));
- device_index->add_item(TTR("Middle Button"));
- device_index->add_item(TTR("Wheel Up Button"));
- device_index->add_item(TTR("Wheel Down Button"));
- device_index->add_item(TTR("Button 6"));
- device_index->add_item(TTR("Button 7"));
- device_index->add_item(TTR("Button 8"));
- device_index->add_item(TTR("Button 9"));
- device_input->popup_centered_minsize(Size2(350,95));
- } break;
- case InputEvent::JOYPAD_MOTION: {
-
- device_id->set_value(0);
- device_index_label->set_text(TTR("Joypad Axis Index:"));
- device_index->clear();
- for(int i=0;i<JOY_AXIS_MAX*2;i++) {
-
- String desc = _axis_names[i];
- device_index->add_item(TTR("Axis")+" "+itos(i/2)+" "+(i&1?"+":"-")+desc);
- }
- device_input->popup_centered_minsize(Size2(350,95));
-
- } break;
- case InputEvent::JOYPAD_BUTTON: {
-
- device_id->set_value(3);
- device_index_label->set_text(TTR("Joypad Button Index:"));
- device_index->clear();
-
- for(int i=0;i<JOY_BUTTON_MAX;i++) {
-
- device_index->add_item(itos(i)+": "+String(_button_names[i]));
- }
- device_input->popup_centered_minsize(Size2(350,95));
-
- } break;
- default:{}
- }
-}
-
-
-
-
-void ProjectSettings::_action_button_pressed(Object* p_obj, int p_column,int p_id) {
-
- TreeItem *ti=p_obj->cast_to<TreeItem>();
-
- ERR_FAIL_COND(!ti);
-
- if (p_id==1) {
- Point2 ofs = input_editor->get_global_pos();
- Rect2 ir=input_editor->get_item_rect(ti);
- ir.pos.y-=input_editor->get_scroll().y;
- ofs+=ir.pos+ir.size;
- ofs.x-=100;
- popup_add->set_pos(ofs);
- popup_add->popup();
- add_at="input/"+ti->get_text(0);
-
- } else if (p_id==2) {
- //remove
-
- if (ti->get_parent()==input_editor->get_root()) {
-
- //remove main thing
-
- String name="input/"+ti->get_text(0);
- Variant old_val = GlobalConfig::get_singleton()->get(name);
- int order=GlobalConfig::get_singleton()->get_order(name);
-
- undo_redo->create_action(TTR("Add Input Action"));
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"clear",name);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set_order",name,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();
-
- } else {
- //remove action
- String name="input/"+ti->get_parent()->get_text(0);
- Variant old_val = GlobalConfig::get_singleton()->get(name);
- int idx = ti->get_metadata(0);
-
- Array va = old_val;
-
- ERR_FAIL_INDEX(idx,va.size());
-
- for(int i=idx;i<va.size()-1;i++) {
-
- va[i]=va[i+1];
- }
-
- va.resize(va.size()-1);
-
-
- undo_redo->create_action(TTR("Erase Input Action Event"));
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,va);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"set",name,old_val);
- 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();
-
- }
- }
-
-}
-
-
-void ProjectSettings::_update_actions() {
-
- if (setting)
- return;
-
- input_editor->clear();
- TreeItem *root = input_editor->create_item();
- input_editor->set_hide_root(true);
-
- List<PropertyInfo> props;
- GlobalConfig::get_singleton()->get_property_list(&props);
-
- for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
-
- const PropertyInfo &pi=E->get();
- if (!pi.name.begins_with("input/"))
- continue;
-
- String name = pi.name.get_slice("/",1);
- if (name=="")
- continue;
-
- TreeItem *item=input_editor->create_item(root);
- //item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- item->set_text(0,name);
- item->add_button(0,get_icon("Add","EditorIcons"),1);
- if (!GlobalConfig::get_singleton()->get_input_presets().find(pi.name)) {
- item->add_button(0,get_icon("Remove","EditorIcons"),2);
- item->set_editable(0,true);
- }
- item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
- //item->set_checked(0,pi.usage&PROPERTY_USAGE_CHECKED);
-
-
- Array actions=GlobalConfig::get_singleton()->get(pi.name);
-
- for(int i=0;i<actions.size();i++) {
-
- if (actions[i].get_type()!=Variant::INPUT_EVENT)
- continue;
- InputEvent ie = actions[i];
-
- TreeItem *action = input_editor->create_item(item);
-
- switch(ie.type) {
-
- case InputEvent::KEY: {
-
- String str=keycode_get_string(ie.key.scancode).capitalize();
- if (ie.key.mod.meta)
- str=TTR("Meta+")+str;
- if (ie.key.mod.shift)
- str=TTR("Shift+")+str;
- if (ie.key.mod.alt)
- str=TTR("Alt+")+str;
- if (ie.key.mod.control)
- str=TTR("Control+")+str;
-
- action->set_text(0,str);
- action->set_icon(0,get_icon("Keyboard","EditorIcons"));
-
- } break;
- case InputEvent::JOYPAD_BUTTON: {
-
- String str = TTR("Device")+" "+itos(ie.device)+", "+TTR("Button")+" "+itos(ie.joy_button.button_index);
- if (ie.joy_button.button_index>=0 && ie.joy_button.button_index<JOY_BUTTON_MAX)
- str+=String()+" ("+_button_names[ie.joy_button.button_index]+").";
- else
- str+=".";
-
- action->set_text(0,str);
- action->set_icon(0,get_icon("JoyButton","EditorIcons"));
- } break;
- case InputEvent::MOUSE_BUTTON: {
-
- String str = TTR("Device")+" "+itos(ie.device)+", ";
- switch (ie.mouse_button.button_index) {
- case BUTTON_LEFT: str+=TTR("Left Button."); break;
- case BUTTON_RIGHT: str+=TTR("Right Button."); break;
- case BUTTON_MIDDLE: str+=TTR("Middle Button."); break;
- case BUTTON_WHEEL_UP: str+=TTR("Wheel Up."); break;
- case BUTTON_WHEEL_DOWN: str+=TTR("Wheel Down."); break;
- default: str+=TTR("Button")+" "+itos(ie.mouse_button.button_index)+".";
- }
-
- action->set_text(0,str);
- action->set_icon(0,get_icon("Mouse","EditorIcons"));
- } break;
- case InputEvent::JOYPAD_MOTION: {
-
- int ax = ie.joy_motion.axis;
- int n = 2*ax + (ie.joy_motion.axis_value<0 ? 0:1);
- String desc = _axis_names[n];
- String str = TTR("Device")+" "+itos(ie.device)+", "+TTR("Axis")+" "+itos(ax)+" "+(ie.joy_motion.axis_value<0?"-":"+")+desc +".";
- action->set_text(0,str);
- action->set_icon(0,get_icon("JoyAxis","EditorIcons"));
- } break;
- }
- action->add_button(0,get_icon("Remove","EditorIcons"),2);
- action->set_metadata(0,i);
- action->set_meta("__input", ie);
- }
- }
-}
-
-
-void ProjectSettings::popup_project_settings() {
-
- //popup_centered(Size2(500,400));
- popup_centered_ratio();
- globals_editor->update_category_list();
- _update_translations();
- autoload_settings->update_autoload();
- plugin_settings->update_plugins();
-}
-
-
-void ProjectSettings::_item_selected() {
-
-
- TreeItem *ti = globals_editor->get_property_editor()->get_scene_tree()->get_selected();
- if (!ti)
- return;
- if (!ti->get_parent())
- return;
- category->set_text(globals_editor->get_current_section());
- property->set_text(ti->get_text(0));
- popup_platform->set_disabled(false);
-
-
-}
-
-
-void ProjectSettings::_item_adds(String) {
-
- _item_add();
-}
-
-void ProjectSettings::_item_add() {
-
- Variant value;
- switch(type->get_selected()) {
- case 0: value=false; break;
- case 1: value=0; break;
- case 2: value=0.0; break;
- case 3: value=""; break;
- }
-
- String catname = category->get_text().strip_edges();
- /*if (!catname.is_valid_identifier()) {
- message->set_text("Invalid Category.\nValid characters: a-z,A-Z,0-9 or _");
- message->popup_centered(Size2(300,100));
- return;
- }*/
-
- String propname = property->get_text().strip_edges();
- /*if (!propname.is_valid_identifier()) {
- message->set_text("Invalid Property.\nValid characters: a-z,A-Z,0-9 or _");
- message->popup_centered(Size2(300,100));
- return;
- }*/
-
- String name = catname!="" ? catname+"/"+propname : propname;
-
- undo_redo->create_action("Add Global Property");
-
- undo_redo->add_do_property(GlobalConfig::get_singleton(), name, value);
-
- if (GlobalConfig::get_singleton()->has(name)) {
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
- } else {
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, Variant());
- }
-
- undo_redo->add_do_method(globals_editor, "update_category_list");
- undo_redo->add_undo_method(globals_editor, "update_category_list");
-
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
-
- undo_redo->commit_action();
-
- globals_editor->set_current_section(catname);
-
- _settings_changed();
-}
-
-void ProjectSettings::_item_del() {
-
- String catname = category->get_text().strip_edges();
- //ERR_FAIL_COND(!catname.is_valid_identifier());
- String propname = property->get_text().strip_edges();
- //ERR_FAIL_COND(!propname.is_valid_identifier());
-
- String name = catname!="" ? catname+"/"+propname : propname;
-
- undo_redo->create_action("Delete Global Property");
-
- undo_redo->add_do_property(GlobalConfig::get_singleton(), name, Variant());
-
- undo_redo->add_undo_property(GlobalConfig::get_singleton(), name, GlobalConfig::get_singleton()->get(name));
-
- undo_redo->add_do_method(globals_editor, "update_category_list");
- undo_redo->add_undo_method(globals_editor, "update_category_list");
-
- undo_redo->add_do_method(this, "_settings_changed");
- undo_redo->add_undo_method(this, "_settings_changed");
-
- undo_redo->commit_action();
-
- _settings_changed();
-}
-
-void ProjectSettings::_action_adds(String) {
-
- _action_add();
-}
-
-void ProjectSettings::_action_add() {
-
- String action = action_name->get_text();
- if (action.find("/")!=-1 || action.find(":")!=-1 || action=="") {
- message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
- message->popup_centered(Size2(300,100));
- return;
- }
-
- if (GlobalConfig::get_singleton()->has("input/"+action)) {
- message->set_text(vformat(TTR("Action '%s' already exists!"),action));
- message->popup_centered(Size2(300,100));
- return;
- }
-
- Array va;
- String name = "input/"+action;
- undo_redo->create_action(TTR("Add Input Action Event"));
- undo_redo->add_do_method(GlobalConfig::get_singleton(),"set",name,va);
- undo_redo->add_undo_method(GlobalConfig::get_singleton(),"clear",name);
- 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();
-
- TreeItem *r = input_editor->get_root();
-
- if (!r)
- return;
- r=r->get_children();
- if (!r)
- return;
- while(r->get_next())
- r=r->get_next();
-
- if (!r)
- return;
- r->select(0);
- input_editor->ensure_cursor_is_visible();
-
-}
-
-
-void ProjectSettings::_item_checked(const String& p_item, bool p_check) {
-
-
-
-}
-
-
-void ProjectSettings::_save() {
-
- Error err = GlobalConfig::get_singleton()->save();
- message->set_text(err!=OK?TTR("Error saving settings."):TTR("Settings saved OK."));
- message->popup_centered(Size2(300,100));
-}
-
-
-
-void ProjectSettings::_settings_prop_edited(const String& p_name) {
-
- String full_item = globals_editor->get_full_item_path(p_name);
-
- _settings_changed();
-}
-
-void ProjectSettings::_settings_changed() {
-
- timer->start();
-}
-
-void ProjectSettings::queue_save() {
- _settings_changed();
-}
-
-
-void ProjectSettings::_copy_to_platform(int p_which) {
-
- String catname = category->get_text();
- if (!catname.is_valid_identifier()) {
- message->set_text("Invalid Category.\nValid characters: a-z,A-Z,0-9 or _");
- message->popup_centered(Size2(300,100));
- return;
- }
-
-
- String propname = property->get_text();
- if (!propname.is_valid_identifier()) {
- message->set_text("Invalid Property.\nValid characters: a-z,A-Z,0-9 or _");
- message->popup_centered(Size2(300,100));
- return;
- }
-
- String name = catname+"/"+propname;
- Variant value=GlobalConfig::get_singleton()->get(name);
-
- catname+="."+popup_platform->get_popup()->get_item_text(p_which);
- name = catname+"/"+propname;
-
- GlobalConfig::get_singleton()->set(name,value);
- globals_editor->get_property_editor()->update_tree();
-
-}
-
-
-void ProjectSettings::add_translation(const String& p_translation) {
-
- _translation_add(p_translation);
-}
-
-void ProjectSettings::_translation_add(const String& p_path) {
-
- PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
-
-
- for(int i=0;i<translations.size();i++) {
-
- if (translations[i]==p_path)
- return; //exists
- }
-
- translations.push_back(p_path);
- undo_redo->create_action(TTR("Add Translation"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translations",translations);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translations",GlobalConfig::get_singleton()->get("locale/translations"));
- undo_redo->add_do_method(this,"_update_translations");
- undo_redo->add_undo_method(this,"_update_translations");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
-
-}
-
-void ProjectSettings::_translation_file_open() {
-
- translation_file_open->popup_centered_ratio();
-}
-
-void ProjectSettings::_translation_delete(Object *p_item,int p_column, int p_button) {
-
- TreeItem *ti = p_item->cast_to<TreeItem>();
- ERR_FAIL_COND(!ti);
-
- int idx=ti->get_metadata(0);
-
- PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
-
- ERR_FAIL_INDEX(idx,translations.size());
-
- translations.remove(idx);
-
- undo_redo->create_action(TTR("Remove Translation"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translations",translations);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translations",GlobalConfig::get_singleton()->get("locale/translations"));
- undo_redo->add_do_method(this,"_update_translations");
- undo_redo->add_undo_method(this,"_update_translations");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
-
-
-}
-
-void ProjectSettings::_translation_res_file_open() {
-
- translation_res_file_open->popup_centered_ratio();
-
-}
-
-void ProjectSettings::_translation_res_add(const String& p_path){
-
- Variant prev;
- Dictionary remaps;
-
- if (GlobalConfig::get_singleton()->has("locale/translation_remaps")) {
- remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
- prev=remaps;
- }
-
- if (remaps.has(p_path))
- return; //pointless already has it
-
- remaps[p_path]=PoolStringArray();
-
- undo_redo->create_action(TTR("Add Remapped Path"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",prev);
- undo_redo->add_do_method(this,"_update_translations");
- undo_redo->add_undo_method(this,"_update_translations");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
-
-}
-
-void ProjectSettings::_translation_res_option_file_open(){
-
- translation_res_option_file_open->popup_centered_ratio();
-
-}
-void ProjectSettings::_translation_res_option_add(const String& p_path) {
-
- ERR_FAIL_COND(!GlobalConfig::get_singleton()->has("locale/translation_remaps"));
-
- Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
-
- TreeItem *k = translation_remap->get_selected();
- ERR_FAIL_COND(!k);
-
- String key = k->get_metadata(0);
-
- ERR_FAIL_COND(!remaps.has(key));
- PoolStringArray r = remaps[key];
- r.push_back(p_path+":"+"en");
- remaps[key]=r;
-
-
- undo_redo->create_action(TTR("Resource Remap Add Remap"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
- undo_redo->add_do_method(this,"_update_translations");
- undo_redo->add_undo_method(this,"_update_translations");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
-
-}
-
-
-
-void ProjectSettings::_translation_res_select() {
-
- if (updating_translations)
- return;
-
-
- call_deferred("_update_translations");
-}
-
-void ProjectSettings::_translation_res_option_changed() {
-
- if (updating_translations)
- return;
-
- if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
- return;
-
- Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
-
- TreeItem *k = translation_remap->get_selected();
- ERR_FAIL_COND(!k);
- TreeItem *ed = translation_remap_options->get_edited();
- ERR_FAIL_COND(!ed);
-
- String key = k->get_metadata(0);
- int idx = ed->get_metadata(0);
- String path = ed->get_metadata(1);
- int which = ed->get_range(1);
-
- Vector<String> langs = TranslationServer::get_all_locales();
-
- ERR_FAIL_INDEX(which,langs.size());
-
-
- ERR_FAIL_COND(!remaps.has(key));
- PoolStringArray r = remaps[key];
- ERR_FAIL_INDEX(idx,r.size());
- r.set(idx,path+":"+langs[which]);
- remaps[key]=r;
-
- updating_translations=true;
- undo_redo->create_action(TTR("Change Resource Remap Language"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
- undo_redo->add_do_method(this,"_update_translations");
- undo_redo->add_undo_method(this,"_update_translations");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
- updating_translations=false;
-
-}
-
-
-void ProjectSettings::_translation_res_delete(Object *p_item,int p_column, int p_button) {
-
-
- if (updating_translations)
- return;
-
- if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
- return;
-
- Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
-
- TreeItem *k = p_item->cast_to<TreeItem>();
-
- String key = k->get_metadata(0);
- ERR_FAIL_COND(!remaps.has(key));
-
- remaps.erase(key);
-
- undo_redo->create_action(TTR("Remove Resource Remap"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
- undo_redo->add_do_method(this,"_update_translations");
- undo_redo->add_undo_method(this,"_update_translations");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
-}
-
-void ProjectSettings::_translation_res_option_delete(Object *p_item,int p_column, int p_button) {
-
- if (updating_translations)
- return;
-
- if (!GlobalConfig::get_singleton()->has("locale/translation_remaps"))
- return;
-
- Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
-
- TreeItem *k = translation_remap->get_selected();
- ERR_FAIL_COND(!k);
- TreeItem *ed = p_item->cast_to<TreeItem>();
- ERR_FAIL_COND(!ed);
-
- String key = k->get_metadata(0);
- int idx = ed->get_metadata(0);
-
- ERR_FAIL_COND(!remaps.has(key));
- PoolStringArray r = remaps[key];
- ERR_FAIL_INDEX(idx,remaps.size());
- r.remove(idx);
- remaps[key]=r;
-
-
- undo_redo->create_action(TTR("Remove Resource Remap Option"));
- undo_redo->add_do_property(GlobalConfig::get_singleton(),"locale/translation_remaps",remaps);
- undo_redo->add_undo_property(GlobalConfig::get_singleton(),"locale/translation_remaps",GlobalConfig::get_singleton()->get("locale/translation_remaps"));
- undo_redo->add_do_method(this,"_update_translations");
- undo_redo->add_undo_method(this,"_update_translations");
- undo_redo->add_do_method(this,"_settings_changed");
- undo_redo->add_undo_method(this,"_settings_changed");
- undo_redo->commit_action();
-
-}
-
-void ProjectSettings::_update_translations() {
-
- //update translations
-
- if (updating_translations)
- return;
-
- updating_translations=true;
-
- translation_list->clear();
- TreeItem *root = translation_list->create_item(NULL);
- translation_list->set_hide_root(true);
- if (GlobalConfig::get_singleton()->has("locale/translations")) {
-
- PoolStringArray translations = GlobalConfig::get_singleton()->get("locale/translations");
- for(int i=0;i<translations.size();i++) {
-
- TreeItem *t = translation_list->create_item(root);
- t->set_editable(0,false);
- t->set_text(0,translations[i].replace_first("res://",""));
- t->set_tooltip(0,translations[i]);
- t->set_metadata(0,i);
- t->add_button(0,get_icon("Del","EditorIcons"),0);
- }
- }
-
-
- //update translation remaps
-
- String remap_selected;
- if (translation_remap->get_selected()) {
- remap_selected = translation_remap->get_selected()->get_metadata(0);
- }
-
- translation_remap->clear();
- translation_remap_options->clear();
- root = translation_remap->create_item(NULL);
- TreeItem *root2 = translation_remap_options->create_item(NULL);
- translation_remap->set_hide_root(true);
- translation_remap_options->set_hide_root(true);
- translation_res_option_add_button->set_disabled(true);
-
- Vector<String> langs = TranslationServer::get_all_locales();
- Vector<String> names = TranslationServer::get_all_locale_names();
- String langnames;
- for(int i=0;i<names.size();i++) {
- if (i>0)
- langnames+=",";
- langnames+=names[i];
- }
-
- if (GlobalConfig::get_singleton()->has("locale/translation_remaps")) {
-
- Dictionary remaps = GlobalConfig::get_singleton()->get("locale/translation_remaps");
- List<Variant> rk;
- remaps.get_key_list(&rk);
- Vector<String> keys;
- for(List<Variant>::Element *E=rk.front();E;E=E->next()) {
- keys.push_back(E->get());
- }
- keys.sort();
-
- for(int i=0;i<keys.size();i++) {
-
- TreeItem *t = translation_remap->create_item(root);
- t->set_editable(0,false);
- t->set_text(0,keys[i].replace_first("res://",""));
- t->set_tooltip(0,keys[i]);
- t->set_metadata(0,keys[i]);
- t->add_button(0,get_icon("Del","EditorIcons"),0);
- if (keys[i]==remap_selected) {
- t->select(0);
- translation_res_option_add_button->set_disabled(false);
-
- PoolStringArray selected = remaps[keys[i]];
- for(int j=0;j<selected.size();j++) {
-
- String s = selected[j];
- int qp = s.find_last(":");
- String path = s.substr(0,qp);
- String locale = s.substr(qp+1,s.length());
-
- TreeItem *t2 = translation_remap_options->create_item(root2);
- t2->set_editable(0,false);
- t2->set_text(0,path.replace_first("res://",""));
- t2->set_tooltip(0,path);
- t2->set_metadata(0,j);
- t2->add_button(0,get_icon("Del","EditorIcons"),0);
- t2->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- t2->set_text(1,langnames);
- t2->set_editable(1,true);
- t2->set_metadata(1,path);
- int idx = langs.find(locale);
- print_line("find "+locale+" at "+itos(idx));
- if (idx<0)
- idx=0;
-
- t2->set_range(1,idx);
- }
- }
-
-
- }
- }
-
-
- updating_translations=false;
-
-}
-
-void ProjectSettings::_toggle_search_bar(bool p_pressed) {
-
- globals_editor->get_property_editor()->set_use_filter(p_pressed);
-
- if (p_pressed) {
-
- search_bar->show();
- add_prop_bar->hide();
- search_box->grab_focus();
- search_box->select_all();
- } else {
-
- search_bar->hide();
- add_prop_bar->show();
- }
-}
-
-void ProjectSettings::_clear_search_box() {
-
- if (search_box->get_text()=="")
- return;
-
- search_box->clear();
- globals_editor->get_property_editor()->update_tree();
-}
-
-void ProjectSettings::set_plugins_page() {
-
- tab_container->set_current_tab( plugin_settings->get_index() );
-}
-
-void ProjectSettings::_bind_methods() {
-
- ClassDB::bind_method(_MD("_item_selected"),&ProjectSettings::_item_selected);
- ClassDB::bind_method(_MD("_item_add"),&ProjectSettings::_item_add);
- ClassDB::bind_method(_MD("_item_adds"),&ProjectSettings::_item_adds);
- ClassDB::bind_method(_MD("_item_del"),&ProjectSettings::_item_del);
- ClassDB::bind_method(_MD("_item_checked"),&ProjectSettings::_item_checked);
- ClassDB::bind_method(_MD("_save"),&ProjectSettings::_save);
- ClassDB::bind_method(_MD("_action_add"),&ProjectSettings::_action_add);
- ClassDB::bind_method(_MD("_action_adds"),&ProjectSettings::_action_adds);
- ClassDB::bind_method(_MD("_action_selected"),&ProjectSettings::_action_selected);
- ClassDB::bind_method(_MD("_action_edited"),&ProjectSettings::_action_edited);
- ClassDB::bind_method(_MD("_action_button_pressed"),&ProjectSettings::_action_button_pressed);
- ClassDB::bind_method(_MD("_update_actions"),&ProjectSettings::_update_actions);
- ClassDB::bind_method(_MD("_wait_for_key"),&ProjectSettings::_wait_for_key);
- ClassDB::bind_method(_MD("_add_item"),&ProjectSettings::_add_item);
- ClassDB::bind_method(_MD("_device_input_add"),&ProjectSettings::_device_input_add);
- ClassDB::bind_method(_MD("_press_a_key_confirm"),&ProjectSettings::_press_a_key_confirm);
- ClassDB::bind_method(_MD("_settings_prop_edited"),&ProjectSettings::_settings_prop_edited);
- ClassDB::bind_method(_MD("_copy_to_platform"),&ProjectSettings::_copy_to_platform);
- ClassDB::bind_method(_MD("_update_translations"),&ProjectSettings::_update_translations);
- ClassDB::bind_method(_MD("_translation_delete"),&ProjectSettings::_translation_delete);
- ClassDB::bind_method(_MD("_settings_changed"),&ProjectSettings::_settings_changed);
- ClassDB::bind_method(_MD("_translation_add"),&ProjectSettings::_translation_add);
- ClassDB::bind_method(_MD("_translation_file_open"),&ProjectSettings::_translation_file_open);
-
- ClassDB::bind_method(_MD("_translation_res_add"),&ProjectSettings::_translation_res_add);
- ClassDB::bind_method(_MD("_translation_res_file_open"),&ProjectSettings::_translation_res_file_open);
- ClassDB::bind_method(_MD("_translation_res_option_add"),&ProjectSettings::_translation_res_option_add);
- ClassDB::bind_method(_MD("_translation_res_option_file_open"),&ProjectSettings::_translation_res_option_file_open);
- ClassDB::bind_method(_MD("_translation_res_select"),&ProjectSettings::_translation_res_select);
- ClassDB::bind_method(_MD("_translation_res_option_changed"),&ProjectSettings::_translation_res_option_changed);
- ClassDB::bind_method(_MD("_translation_res_delete"),&ProjectSettings::_translation_res_delete);
- ClassDB::bind_method(_MD("_translation_res_option_delete"),&ProjectSettings::_translation_res_option_delete);
-
- ClassDB::bind_method(_MD("_clear_search_box"),&ProjectSettings::_clear_search_box);
- ClassDB::bind_method(_MD("_toggle_search_bar"),&ProjectSettings::_toggle_search_bar);
-
-}
-
-ProjectSettings::ProjectSettings(EditorData *p_data) {
-
-
- singleton=this;
- set_title(TTR("Project Settings (godot.cfg)"));
- undo_redo=&p_data->get_undo_redo();
- data=p_data;
-
-
- tab_container = memnew( TabContainer );
- add_child(tab_container);
- //set_child_rect(tab_container);
-
- //tab_container->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 15 );
- //tab_container->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 15 );
- //tab_container->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 15 );
- //tab_container->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
-
- VBoxContainer *props_base = memnew( VBoxContainer );
- props_base->set_alignment(BoxContainer::ALIGN_BEGIN);
- props_base->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- tab_container->add_child(props_base);
- props_base->set_name(TTR("General"));
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- props_base->add_child(hbc);
-
- search_button = memnew( ToolButton );
- search_button->set_toggle_mode(true);
- search_button->set_pressed(false);
- search_button->set_text(TTR("Search"));
- hbc->add_child(search_button);
- search_button->connect("toggled",this,"_toggle_search_bar");
-
- hbc->add_child( memnew( VSeparator ) );
-
- add_prop_bar = memnew( HBoxContainer );
- add_prop_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hbc->add_child(add_prop_bar);
-
- Label *l = memnew( Label );
- add_prop_bar->add_child(l);
- l->set_text(TTR("Category:"));
-
- category = memnew( LineEdit );
- category->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- add_prop_bar->add_child(category);
- category->connect("text_entered",this,"_item_adds");
-
- l = memnew( Label );
- add_prop_bar->add_child(l);
- l->set_text(TTR("Property:"));
-
- property = memnew( LineEdit );
- property->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- add_prop_bar->add_child(property);
- property->connect("text_entered",this,"_item_adds");
-
- l = memnew( Label );
- add_prop_bar->add_child(l);
- l->set_text(TTR("Type:"));
-
- type = memnew( OptionButton );
- type->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- add_prop_bar->add_child(type);
- type->add_item("bool");
- type->add_item("int");
- type->add_item("float");
- type->add_item("string");
-
- Button *add = memnew( Button );
- add_prop_bar->add_child(add);
- add->set_text(TTR("Add"));
- add->connect("pressed",this,"_item_add");
-
- Button *del = memnew( Button );
- add_prop_bar->add_child(del);
- del->set_text(TTR("Del"));
- del->connect("pressed",this,"_item_del");
-
- search_bar = memnew( HBoxContainer );
- search_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hbc->add_child(search_bar);
- search_bar->hide();
-
- search_box = memnew( LineEdit );
- search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- search_bar->add_child(search_box);
-
- clear_button = memnew( ToolButton );
- search_bar->add_child(clear_button);
- clear_button->connect("pressed",this,"_clear_search_box");
-
- globals_editor = memnew( SectionedPropertyEditor );
- props_base->add_child(globals_editor);
- globals_editor->get_property_editor()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
- //globals_editor->hide_top_label();
- globals_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- 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 );
- props_base->add_child(save);
-
- save->set_anchor(MARGIN_LEFT,ANCHOR_END);
- save->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- save->set_anchor(MARGIN_TOP,ANCHOR_END);
- save->set_anchor(MARGIN_BOTTOM,ANCHOR_END);
- save->set_begin( Point2(80,28) );
- save->set_end( Point2(10,20) );
- save->set_text("Save");
- save->connect("pressed",this,"_save");
-*/
-
- hbc = memnew( HBoxContainer );
- props_base->add_child(hbc);
-
- popup_platform = memnew( MenuButton );
- popup_platform->set_text(TTR("Copy To Platform.."));
- popup_platform->set_disabled(true);
- hbc->add_child(popup_platform);
-
- hbc->add_spacer();
-
- /*List<StringName> ep;
- EditorImportExport::get_singleton()->get_export_platforms(&ep);
- ep.sort_custom<StringName::AlphCompare>();
-
- for(List<StringName>::Element *E=ep.front();E;E=E->next()) {
-
- popup_platform->get_popup()->add_item( E->get() );
-
- }*/
-
- popup_platform->get_popup()->connect("id_pressed",this,"_copy_to_platform");
- get_ok()->set_text(TTR("Close"));
- set_hide_on_ok(true);
-
- message = memnew( ConfirmationDialog );
- add_child(message);
- //message->get_cancel()->hide();
- message->set_hide_on_ok(true);
-
- Control *input_base = memnew( Control );
- input_base->set_name(TTR("Input Map"));
- input_base->set_area_as_parent_rect();
- tab_container->add_child(input_base);
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- input_base->add_child(vbc);
- vbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 5 );
- vbc->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 5 );
- vbc->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 );
- vbc->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 );
-
- l = memnew( Label );
- vbc->add_child(l);
- l->set_pos(Point2(6,5));
- l->set_text(TTR("Action:"));
-
- hbc = memnew( HBoxContainer );
- vbc->add_child(hbc);
-
- action_name = memnew( LineEdit );
- action_name->set_h_size_flags(SIZE_EXPAND_FILL);
- hbc->add_child(action_name);
- action_name->connect("text_entered",this,"_action_adds");
-
- add = memnew( Button );
- hbc->add_child(add);
- add->set_custom_minimum_size(Size2(150, 0));
- add->set_text(TTR("Add"));
- add->connect("pressed",this,"_action_add");
-
- input_editor = memnew( Tree );
- vbc->add_child(input_editor);
- input_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- input_editor->connect("item_edited",this,"_action_edited");
- input_editor->connect("cell_selected",this,"_action_selected");
- input_editor->connect("button_pressed",this,"_action_button_pressed");
- popup_add = memnew( PopupMenu );
- add_child(popup_add);
- popup_add->connect("id_pressed",this,"_add_item");
-
- press_a_key = memnew( ConfirmationDialog );
- press_a_key->set_focus_mode(FOCUS_ALL);
- add_child(press_a_key);
-
- l = memnew( Label );
- l->set_text(TTR("Press a Key.."));
- l->set_area_as_parent_rect();
- l->set_align(Label::ALIGN_CENTER);
- l->set_margin(MARGIN_TOP,20);
- l->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,30);
- press_a_key_label=l;
- press_a_key->add_child(l);
- press_a_key->connect("gui_input",this,"_wait_for_key");
- press_a_key->connect("confirmed",this,"_press_a_key_confirm");
-
-
- device_input=memnew( ConfirmationDialog );
- add_child(device_input);
- device_input->get_ok()->set_text(TTR("Add"));
- device_input->connect("confirmed",this,"_device_input_add");
-
- hbc = memnew( HBoxContainer );
- device_input->add_child(hbc);
- //device_input->set_child_rect(hbc);
-
- VBoxContainer *vbc_left = memnew( VBoxContainer );
- hbc->add_child(vbc_left);
-
- l = memnew( Label );
- l->set_text(TTR("Device:"));
- vbc_left->add_child(l);
-
- device_id = memnew( SpinBox );
- device_id->set_value(0);
- vbc_left->add_child(device_id);
-
- VBoxContainer *vbc_right = memnew( VBoxContainer );
- hbc->add_child(vbc_right);
- vbc_right->set_h_size_flags(SIZE_EXPAND_FILL);
-
- l = memnew( Label );
- l->set_text(TTR("Index:"));
- vbc_right->add_child(l);
- device_index_label=l;
-
- device_index = memnew( OptionButton );
- vbc_right->add_child(device_index);
-
- /*
- save = memnew( Button );
- input_base->add_child(save);
- save->set_anchor(MARGIN_LEFT,ANCHOR_END);
- save->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- save->set_anchor(MARGIN_TOP,ANCHOR_END);
- save->set_anchor(MARGIN_BOTTOM,ANCHOR_END);
- save->set_begin( Point2(80,28) );
- save->set_end( Point2(10,20) );
- save->set_text("Save");
- save->connect("pressed",this,"_save");
-*/
- setting=false;
-
- //translations
- TabContainer *translations = memnew( TabContainer );
- translations->set_name(TTR("Localization"));
- tab_container->add_child(translations);
-
- {
-
- VBoxContainer *tvb = memnew( VBoxContainer );
- translations->add_child(tvb);
- tvb->set_name(TTR("Translations"));
- HBoxContainer *thb = memnew( HBoxContainer);
- tvb->add_child(thb);
- thb->add_child( memnew( Label(TTR("Translations:"))));
- thb->add_spacer();
- Button *addtr = memnew( Button(TTR("Add..")) );
- addtr->connect("pressed",this,"_translation_file_open");
- thb->add_child(addtr);
- MarginContainer *tmc = memnew( MarginContainer );
- tvb->add_child(tmc);
- tmc->set_v_size_flags(SIZE_EXPAND_FILL);
- translation_list = memnew( Tree );
- translation_list->set_v_size_flags(SIZE_EXPAND_FILL);
- tmc->add_child(translation_list);
-
- translation_file_open=memnew( EditorFileDialog );
- add_child(translation_file_open);
- translation_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- translation_file_open->connect("file_selected",this,"_translation_add");
-
- }
-
- {
- VBoxContainer *tvb = memnew( VBoxContainer );
- translations->add_child(tvb);
- tvb->set_name(TTR("Remaps"));
- HBoxContainer *thb = memnew( HBoxContainer);
- tvb->add_child(thb);
- thb->add_child( memnew( Label(TTR("Resources:"))));
- thb->add_spacer();
- Button *addtr = memnew( Button(TTR("Add..")) );
- addtr->connect("pressed",this,"_translation_res_file_open");
- thb->add_child(addtr);
- MarginContainer *tmc = memnew( MarginContainer );
- tvb->add_child(tmc);
- tmc->set_v_size_flags(SIZE_EXPAND_FILL);
- translation_remap = memnew( Tree );
- translation_remap->set_v_size_flags(SIZE_EXPAND_FILL);
- translation_remap->connect("cell_selected",this,"_translation_res_select");
- tmc->add_child(translation_remap);
- translation_remap->connect("button_pressed",this,"_translation_res_delete");
-
- translation_res_file_open=memnew( EditorFileDialog );
- add_child(translation_res_file_open);
- translation_res_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- translation_res_file_open->connect("file_selected",this,"_translation_res_add");
-
- thb = memnew( HBoxContainer);
- tvb->add_child(thb);
- thb->add_child( memnew( Label(TTR("Remaps by Locale:"))));
- thb->add_spacer();
- addtr = memnew( Button(TTR("Add..")) );
- addtr->connect("pressed",this,"_translation_res_option_file_open");
- translation_res_option_add_button=addtr;
- thb->add_child(addtr);
- tmc = memnew( MarginContainer );
- tvb->add_child(tmc);
- tmc->set_v_size_flags(SIZE_EXPAND_FILL);
- translation_remap_options = memnew( Tree );
- translation_remap_options->set_v_size_flags(SIZE_EXPAND_FILL);
- tmc->add_child(translation_remap_options);
-
- translation_remap_options->set_columns(2);
- translation_remap_options->set_column_title(0,TTR("Path"));
- translation_remap_options->set_column_title(1,TTR("Locale"));
- translation_remap_options->set_column_titles_visible(true);
- translation_remap_options->set_column_expand(0,true);
- translation_remap_options->set_column_expand(1,false);
- translation_remap_options->set_column_min_width(1,200);
- translation_remap_options->connect("item_edited",this,"_translation_res_option_changed");
- translation_remap_options->connect("button_pressed",this,"_translation_res_option_delete");
-
- translation_res_option_file_open=memnew( EditorFileDialog );
- add_child(translation_res_option_file_open);
- translation_res_option_file_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- translation_res_option_file_open->connect("file_selected",this,"_translation_res_option_add");
-
- }
-
-
- {
- autoload_settings = memnew( EditorAutoloadSettings );
- autoload_settings->set_name(TTR("AutoLoad"));
- tab_container->add_child(autoload_settings);
- autoload_settings->connect("autoload_changed", this, "_settings_changed");
- }
-
- {
-
- plugin_settings = memnew( EditorPluginSettings );
- plugin_settings->set_name(TTR("Plugins"));
- tab_container->add_child(plugin_settings);
- }
-
- timer = memnew( Timer );
- timer->set_wait_time(1.5);
- timer->connect("timeout",GlobalConfig::get_singleton(),"save");
- timer->set_one_shot(true);
- add_child(timer);
-
- updating_translations=false;
-
-
- /*
- Control * es = memnew( Control );
- es->set_name("Export");
- tab_container->add_child(es);
- export_settings = memnew( ProjectExportSettings );
- es->add_child(export_settings);
- export_settings->set_area_as_parent_rect();
- export_settings->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
-*/
-}
diff --git a/tools/editor/project_settings.h b/tools/editor/project_settings.h
deleted file mode 100644
index bb925a5fd9..0000000000
--- a/tools/editor/project_settings.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*************************************************************************/
-/* project_settings.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PROJECT_SETTINGS_H
-#define PROJECT_SETTINGS_H
-
-#include "scene/gui/dialogs.h"
-#include "property_editor.h"
-#include "undo_redo.h"
-#include "editor_data.h"
-#include "scene/gui/tab_container.h"
-#include "editor_autoload_settings.h"
-#include "editor_plugin_settings.h"
-
-//#include "project_export_settings.h"
-
-class ProjectSettings : public AcceptDialog {
- GDCLASS( ProjectSettings, AcceptDialog );
-
-
- TabContainer *tab_container;
-
- Timer *timer;
- InputEvent::Type add_type;
- String add_at;
-
- EditorData *data;
- UndoRedo *undo_redo;
- SectionedPropertyEditor *globals_editor;
-
- HBoxContainer *search_bar;
- ToolButton *search_button;
- LineEdit *search_box;
- ToolButton *clear_button;
-
- HBoxContainer *add_prop_bar;
- ConfirmationDialog *message;
- LineEdit *category;
- LineEdit *property;
- OptionButton *type;
- PopupMenu *popup_add;
- ConfirmationDialog *press_a_key;
- Label*press_a_key_label;
- ConfirmationDialog *device_input;
- SpinBox *device_id;
- OptionButton *device_index;
- Label *device_index_label;
- MenuButton *popup_platform;
-
- LineEdit *action_name;
- Tree *input_editor;
- bool setting;
- bool updating_translations;
-
- InputEvent last_wait_for_key;
-
- EditorFileDialog *translation_file_open;
- Tree *translation_list;
-
-
- Button *translation_res_option_add_button;
- EditorFileDialog *translation_res_file_open;
- EditorFileDialog *translation_res_option_file_open;
- Tree *translation_remap;
- Tree *translation_remap_options;
-
- EditorAutoloadSettings *autoload_settings;
-
- EditorPluginSettings *plugin_settings;
-
- void _item_selected();
- void _item_adds(String);
- void _item_add();
- void _item_del();
- void _update_actions();
- void _save();
- void _add_item(int p_item);
-
- void _action_adds(String);
- void _action_add();
- void _device_input_add();
-
- void _item_checked(const String& p_item, bool p_check);
- void _action_selected();
- void _action_edited();
- void _action_button_pressed(Object* p_obj, int p_column,int p_id);
- void _wait_for_key(const InputEvent& p_event);
- void _press_a_key_confirm();
- void _show_last_added(const InputEvent& p_event);
-
- void _settings_prop_edited(const String& p_name);
- void _settings_changed();
-
- //ProjectExportSettings *export_settings;
- void _copy_to_platform(int p_which);
-
-
- void _translation_file_open();
- void _translation_add(const String& p_path);
- void _translation_delete(Object *p_item,int p_column, int p_button);
- void _update_translations();
-
- void _translation_res_file_open();
- void _translation_res_add(const String& p_path);
- void _translation_res_delete(Object *p_item,int p_column, int p_button);
- void _translation_res_select();
- void _translation_res_option_file_open();
- void _translation_res_option_add(const String& p_path);
- void _translation_res_option_changed();
- void _translation_res_option_delete(Object *p_item,int p_column, int p_button);
-
- void _toggle_search_bar(bool p_pressed);
- void _clear_search_box();
-
-
-
- ProjectSettings();
-
-
- static ProjectSettings *singleton;
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
- void add_translation(const String& p_translation);
- static ProjectSettings *get_singleton() { return singleton; }
- void popup_project_settings();
- void set_plugins_page();
-
- void queue_save();
-
-
- ProjectSettings(EditorData *p_data);
-};
-
-#endif // PROJECT_SETTINGS_H
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
deleted file mode 100644
index 8e3791eb8d..0000000000
--- a/tools/editor/property_editor.cpp
+++ /dev/null
@@ -1,4916 +0,0 @@
-/*************************************************************************/
-/* property_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "property_editor.h"
-
-#include "scene/gui/label.h"
-#include "io/resource_loader.h"
-#include "io/image_loader.h"
-#include "class_db.h"
-#include "print_string.h"
-#include "globals.h"
-#include "scene/resources/font.h"
-#include "pair.h"
-#include "scene/scene_string_names.h"
-#include "editor_settings.h"
-#include "editor_import_export.h"
-#include "editor_node.h"
-#include "multi_node_edit.h"
-#include "array_property_edit.h"
-#include "editor_help.h"
-#include "scene/resources/packed_scene.h"
-#include "scene/main/viewport.h"
-#include "editor_file_system.h"
-#include "create_dialog.h"
-#include "property_selector.h"
-#include "globals.h"
-
-void CustomPropertyEditor::_notification(int p_what) {
-
-
- if (p_what==NOTIFICATION_DRAW) {
-
- RID ci = get_canvas_item();
- get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
- /*
- if (v.get_type()==Variant::COLOR) {
-
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2( 10,10,60, get_size().height-20 ), v );
- }*/
- }
-}
-
-
-void CustomPropertyEditor::_menu_option(int p_which) {
-
-
- switch(type) {
-
- case Variant::INT: {
-
- if (hint==PROPERTY_HINT_FLAGS) {
-
- int val = v;
-
- if (val&(1<<p_which)) {
-
- val&=~(1<<p_which);
- } else {
- val|=(1<<p_which);
- }
-
- v=val;
- emit_signal("variant_changed");
- } else if (hint==PROPERTY_HINT_ENUM) {
-
- v=p_which;
- emit_signal("variant_changed");
-
- }
- } break;
- case Variant::STRING: {
-
- if (hint==PROPERTY_HINT_ENUM) {
-
- v=hint_text.get_slice(",",p_which);
- emit_signal("variant_changed");
-
- }
- } break;
- case Variant::OBJECT: {
-
- switch(p_which) {
- case OBJ_MENU_LOAD: {
-
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- String type=(hint==PROPERTY_HINT_RESOURCE_TYPE)?hint_text:String();
-
- 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()) {
- print_line("found: "+E->get());
- 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() );
-
- }
-
- file->popup_centered_ratio();
- } break;
-
- case OBJ_MENU_EDIT: {
-
- RefPtr RefPtr=v;
-
- if (!RefPtr.is_null()) {
-
- emit_signal("resource_edit_request");
- hide();
- }
- } break;
- case OBJ_MENU_CLEAR: {
-
-
- v=Variant();
- emit_signal("variant_changed");
- hide();
- } break;
-
- case OBJ_MENU_MAKE_UNIQUE: {
-
-
- RefPtr RefPtr=v;
- Ref<Resource> res_orig = RefPtr;
- if (res_orig.is_null())
- return;
-
- List<PropertyInfo> property_list;
- res_orig->get_property_list(&property_list);
- List< Pair<String,Variant> > propvalues;
-
- for(List<PropertyInfo>::Element *E=property_list.front();E;E=E->next()) {
-
- Pair<String,Variant> p;
- PropertyInfo &pi = E->get();
- if (pi.usage&PROPERTY_USAGE_STORAGE) {
-
- p.first=pi.name;
- p.second=res_orig->get(pi.name);
- }
-
- propvalues.push_back(p);
- }
-
- String orig_type = res_orig->get_class();
-
- Object *inst = ClassDB::instance( orig_type );
-
- Ref<Resource> res = Ref<Resource>( inst->cast_to<Resource>() );
-
- ERR_FAIL_COND(res.is_null());
-
- for(List< Pair<String,Variant> >::Element *E=propvalues.front();E;E=E->next()) {
-
- Pair<String,Variant> &p=E->get();
- res->set(p.first,p.second);
- }
-
- v=res.get_ref_ptr();
- emit_signal("variant_changed");
- hide();
- } break;
-
- case OBJ_MENU_COPY: {
-
- EditorSettings::get_singleton()->set_resource_clipboard(v);
-
- } break;
- case OBJ_MENU_PASTE: {
-
- v=EditorSettings::get_singleton()->get_resource_clipboard();
- emit_signal("variant_changed");
-
- } break;
- case OBJ_MENU_REIMPORT: {
-
- RES r=v;
-/* if (r.is_valid() && r->get_import_metadata().is_valid()) {
- Ref<ResourceImportMetadata> rimd = r->get_import_metadata();
- Ref<EditorImportPlugin> eip = EditorImportExport::get_singleton()->get_import_plugin_by_name(rimd->get_editor());
- if (eip.is_valid()) {
- eip->import_dialog(r->get_path());
- }
- }*/
- } break;
- case OBJ_MENU_NEW_SCRIPT: {
-
- if (owner->cast_to<Node>())
- EditorNode::get_singleton()->get_scene_tree_dock()->open_script_dialog(owner->cast_to<Node>());
-
- } break;
- default: {
-
-
- ERR_FAIL_COND( inheritors_array.empty() );
-
-
-
-
- String intype=inheritors_array[p_which-TYPE_BASE_ID];
-
- if (intype=="ViewportTexture") {
-
- scene_tree->set_title(TTR("Pick a Viewport"));
- scene_tree->popup_centered_ratio();
- picking_viewport=true;
- return;
-
- }
-
- Object *obj = ClassDB::instance(intype);
- ERR_BREAK( !obj );
- Resource *res=obj->cast_to<Resource>();
- ERR_BREAK( !res );
- if (owner && hint==PROPERTY_HINT_RESOURCE_TYPE && hint_text=="Script") {
- //make visual script the right type
- res->call("set_instance_base_type",owner->get_class());
- }
-
- v=Ref<Resource>(res).get_ref_ptr();
- emit_signal("variant_changed");
-
- } break;
- }
-
-
- } break;
- default:{}
- }
-
-
-}
-
-void CustomPropertyEditor::hide_menu() {
- menu->hide();
-}
-
-Variant CustomPropertyEditor::get_variant() const {
-
- return v;
-}
-String CustomPropertyEditor::get_name() const {
-
- return name;
-}
-
-bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Type p_type, const Variant& p_variant,int p_hint,String p_hint_text) {
-
- owner=p_owner;
- updating=true;
- name=p_name;
- v=p_variant;
- hint=p_hint;
- hint_text=p_hint_text;
- type_button->hide();
- if (color_picker)
- color_picker->hide();
- texture_preview->hide();
- inheritors_array.clear();
- text_edit->hide();
- easing_draw->hide();
- spinbox->hide();
- slider->hide();
-
- for (int i=0;i<MAX_VALUE_EDITORS;i++) {
-
- value_editor[i]->hide();
- value_label[i]->hide();
- if (i<4)
- scroll[i]->hide();
- }
-
- for (int i=0;i<MAX_ACTION_BUTTONS;i++) {
-
- action_buttons[i]->hide();
- }
-
- checks20gc->hide();
- for(int i=0;i<20;i++)
- checks20[i]->hide();
-
- type = (p_variant.get_type()!=Variant::NIL && p_variant.get_type()!=Variant::_RID && p_type!=Variant::OBJECT)? p_variant.get_type() : p_type;
-
-
- switch(type) {
-
- case Variant::BOOL: {
-
- checks20gc->show();
-
- CheckBox *c=checks20[0];
- c->set_text("True");
- checks20gc->set_pos(Vector2(4,4));
- c->set_pressed(v);
- c->show();
-
- checks20gc->set_size(checks20gc->get_minimum_size());
- set_size(checks20gc->get_pos()+checks20gc->get_size()+Vector2(4,4)*EDSCALE);
-
- } break;
- case Variant::INT:
- case Variant::REAL: {
-
- if (hint==PROPERTY_HINT_RANGE) {
-
- int c = hint_text.get_slice_count(",");
- float min=0,max=100,step=1;
- if (c>=1) {
-
- if (!hint_text.get_slice(",",0).empty())
- min=hint_text.get_slice(",",0).to_double();
- }
- if (c>=2) {
-
- if (!hint_text.get_slice(",",1).empty())
- max=hint_text.get_slice(",",1).to_double();
- }
-
- if (c>=3) {
-
- if (!hint_text.get_slice(",",2).empty())
- step= hint_text.get_slice(",",2).to_double();
- }
-
- if (c>=4 && hint_text.get_slice(",",3)=="slider") {
- slider->set_min(min);
- slider->set_max(max);
- slider->set_step(step);
- slider->set_value(v);
- slider->show();
- set_size(Size2(110,30)*EDSCALE);
- } else {
- spinbox->set_min(min);
- spinbox->set_max(max);
- spinbox->set_step(step);
- spinbox->set_value(v);
- spinbox->show();
- set_size(Size2(70,35)*EDSCALE);
- }
-
- } else if (hint==PROPERTY_HINT_ENUM) {
-
- menu->clear();
- Vector<String> options = hint_text.split(",");
- for(int i=0;i<options.size();i++) {
- menu->add_item(options[i],i);
- }
- menu->set_pos(get_pos());
- menu->popup();
- hide();
- updating=false;
- return false;
-
-
- } else if (hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || hint==PROPERTY_HINT_LAYERS_2D_RENDER || hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
-
-
- String title;
- String basename;
- switch (hint) {
- case PROPERTY_HINT_LAYERS_2D_RENDER: basename="layer_names/2d_render"; title="2D Render Layers"; break;
- case PROPERTY_HINT_LAYERS_2D_PHYSICS: basename="layer_names/2d_physics"; title="2D Physics Layers"; break;
- case PROPERTY_HINT_LAYERS_3D_RENDER: basename="layer_names/3d_render"; title="3D Render Layers"; break;
- case PROPERTY_HINT_LAYERS_3D_PHYSICS: basename="layer_names/3d_physics";title="3D Physics Layers"; break;
- }
-
- checks20gc->show();
- uint32_t flgs = v;
- for(int i=0;i<2;i++) {
-
- Point2 ofs(4,4);
- ofs.y+=22*i;
- for(int j=0;j<10;j++) {
-
- int idx = i*10+j;
- CheckBox *c=checks20[idx];
- c->set_text(GlobalConfig::get_singleton()->get(basename+"/layer_"+itos(idx+1)));
- c->set_pressed( flgs & (1<<(i*10+j)) );
- c->show();
- }
-
-
- }
-
- show();
-
- value_label[0]->set_text(title);
- value_label[0]->show();
- value_label[0]->set_pos(Vector2(4,4)*EDSCALE);
-
- checks20gc->set_pos(Vector2(4,4)*EDSCALE+Vector2(0,value_label[0]->get_size().height+4*EDSCALE));
- checks20gc->set_size(checks20gc->get_minimum_size());
-
- set_size(Vector2(4,4)*EDSCALE+checks20gc->get_pos()+checks20gc->get_size());
-
-
- } else if (hint==PROPERTY_HINT_EXP_EASING) {
-
- easing_draw->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
- easing_draw->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
- easing_draw->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,5);
- easing_draw->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,30);
- type_button->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,3);
- type_button->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,3);
- type_button->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,25);
- type_button->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,7);
- type_button->set_text(TTR("Preset.."));
- type_button->get_popup()->clear();
- type_button->get_popup()->add_item(TTR("Linear"),EASING_LINEAR);
- type_button->get_popup()->add_item(TTR("Ease In"),EASING_EASE_IN);
- type_button->get_popup()->add_item(TTR("Ease Out"),EASING_EASE_OUT);
- if (hint_text!="attenuation") {
- type_button->get_popup()->add_item(TTR("Zero"),EASING_ZERO);
- type_button->get_popup()->add_item(TTR("Easing In-Out"),EASING_IN_OUT);
- type_button->get_popup()->add_item(TTR("Easing Out-In"),EASING_OUT_IN);
- }
-
- type_button->show();
- easing_draw->show();
- set_size(Size2(200,150)*EDSCALE);
- } else if (hint==PROPERTY_HINT_FLAGS) {
- menu->clear();
- Vector<String> flags = hint_text.split(",");
- for(int i=0;i<flags.size();i++) {
- String flag = flags[i];
- if (flag=="")
- continue;
- menu->add_check_item(flag,i);
- int f = v;
- if (f&(1<<i))
- menu->set_item_checked(menu->get_item_index(i),true);
- }
- menu->set_pos(get_pos());
- menu->popup();
- hide();
- updating=false;
- return false;
-
- } else {
- List<String> names;
- names.push_back("value:");
- config_value_editors(1,1,50,names);
- value_editor[0]->set_text( String::num(v) );
- }
-
- } break;
- case Variant::STRING: {
-
- if (hint==PROPERTY_HINT_FILE || hint==PROPERTY_HINT_GLOBAL_FILE) {
-
- List<String> names;
- names.push_back(TTR("File.."));
- names.push_back(TTR("Clear"));
- config_action_buttons(names);
-
- } else if (hint==PROPERTY_HINT_DIR || hint==PROPERTY_HINT_GLOBAL_DIR) {
-
- List<String> names;
- names.push_back(TTR("Dir.."));
- names.push_back(TTR("Clear"));
- config_action_buttons(names);
- } else if (hint==PROPERTY_HINT_ENUM) {
-
- menu->clear();
- Vector<String> options = hint_text.split(",");
- for(int i=0;i<options.size();i++) {
- menu->add_item(options[i],i);
- }
- menu->set_pos(get_pos());
- menu->popup();
- hide();
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_MULTILINE_TEXT) {
-
- text_edit->show();
- text_edit->set_text(v);
-
- //action_buttons[0];
-
- int button_margin = get_constant("button_margin","Dialogs");
- int margin = get_constant("margin","Dialogs");
-
- action_buttons[0]->set_anchor( MARGIN_LEFT, ANCHOR_END );
- action_buttons[0]->set_anchor( MARGIN_TOP, ANCHOR_END );
- action_buttons[0]->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- action_buttons[0]->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- action_buttons[0]->set_begin( Point2( 70, button_margin-5 ) );
- action_buttons[0]->set_end( Point2( margin, margin ) );
- action_buttons[0]->set_text(TTR("Close"));
- action_buttons[0]->show();
-
- } else if (hint==PROPERTY_HINT_TYPE_STRING) {
-
-
- if (!create_dialog) {
- create_dialog = memnew( CreateDialog );
- create_dialog->connect("create",this,"_create_dialog_callback");
- add_child(create_dialog);
- }
-
- if (hint_text!=String()) {
- create_dialog->set_base_type(hint_text);
- } else {
- create_dialog->set_base_type("Object");
- }
-
- create_dialog->popup(false);
- hide();
- updating=false;
- return false;
-
-
- } else if (hint==PROPERTY_HINT_METHOD_OF_VARIANT_TYPE) {
-#define MAKE_PROPSELECT if (!property_select) { property_select = memnew(PropertySelector); property_select->connect("selected",this,"_create_selected_property"); add_child(property_select); } hide();
-
- MAKE_PROPSELECT;
-
- Variant::Type type=Variant::NIL;
- for(int i=0;i<Variant::VARIANT_MAX;i++) {
- if (hint_text==Variant::get_type_name(Variant::Type(i))) {
- type=Variant::Type(i);
- }
- }
- if (type)
- property_select->select_method_from_basic_type(type,v);
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_METHOD_OF_BASE_TYPE) {
- MAKE_PROPSELECT
-
- property_select->select_method_from_base_type(hint_text,v);
-
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_METHOD_OF_INSTANCE) {
-
- MAKE_PROPSELECT
-
- Object *instance = ObjectDB::get_instance(hint_text.to_int64());
- if (instance)
- property_select->select_method_from_instance(instance,v);
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_METHOD_OF_SCRIPT) {
- MAKE_PROPSELECT
-
- Object *obj = ObjectDB::get_instance(hint_text.to_int64());
- if (obj && obj->cast_to<Script>()) {
- property_select->select_method_from_script(obj->cast_to<Script>(),v);
- }
-
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE) {
-
- MAKE_PROPSELECT
- Variant::Type type=Variant::NIL;
- String tname=hint_text;
- if (tname.find(".")!=-1)
- tname=tname.get_slice(".",0);
- for(int i=0;i<Variant::VARIANT_MAX;i++) {
- if (tname==Variant::get_type_name(Variant::Type(i))) {
- type=Variant::Type(Variant::Type(i));
- }
- }
- InputEvent::Type iet = InputEvent::NONE;
- if (hint_text.find(".")!=-1) {
- iet=InputEvent::Type(int(hint_text.get_slice(".",1).to_int()));
- }
- if (type)
- property_select->select_property_from_basic_type(type,iet,v);
-
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_PROPERTY_OF_BASE_TYPE) {
-
- MAKE_PROPSELECT
-
- property_select->select_property_from_base_type(hint_text,v);
-
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_PROPERTY_OF_INSTANCE) {
-
- Object *instance = ObjectDB::get_instance(hint_text.to_int64());
- if (instance)
- property_select->select_property_from_instance(instance,v);
-
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_PROPERTY_OF_SCRIPT) {
- MAKE_PROPSELECT
-
- Object *obj = ObjectDB::get_instance(hint_text.to_int64());
- if (obj && obj->cast_to<Script>()) {
- property_select->select_property_from_script(obj->cast_to<Script>(),v);
- }
-
- updating=false;
- return false;
-
- } else if (hint==PROPERTY_HINT_TYPE_STRING) {
- if (!create_dialog) {
- create_dialog = memnew( CreateDialog );
- create_dialog->connect("create",this,"_create_dialog_callback");
- add_child(create_dialog);
- }
-
- } else {
- List<String> names;
- names.push_back("string:");
- config_value_editors(1,1,50,names);
- value_editor[0]->set_text( v );
- }
-
- } break;
- case Variant::VECTOR2: {
-
- List<String> names;
- names.push_back("x");
- names.push_back("y");
- config_value_editors(2,2,10,names);
- Vector2 vec=v;
- value_editor[0]->set_text( String::num( vec.x) );
- value_editor[1]->set_text( String::num( vec.y) );
- } break;
- case Variant::RECT2: {
-
- List<String> names;
- names.push_back("x");
- names.push_back("y");
- names.push_back("w");
- names.push_back("h");
- config_value_editors(4,4,10,names);
- Rect2 r=v;
- value_editor[0]->set_text( String::num( r.pos.x) );
- value_editor[1]->set_text( String::num( r.pos.y) );
- value_editor[2]->set_text( String::num( r.size.x) );
- value_editor[3]->set_text( String::num( r.size.y) );
- } break;
- case Variant::VECTOR3: {
-
- List<String> names;
- names.push_back("x");
- names.push_back("y");
- names.push_back("z");
- config_value_editors(3,3,10,names);
- Vector3 vec=v;
- value_editor[0]->set_text( String::num( vec.x) );
- value_editor[1]->set_text( String::num( vec.y) );
- value_editor[2]->set_text( String::num( vec.z) );
- } break;
- case Variant::PLANE: {
-
- List<String> names;
- names.push_back("x");
- names.push_back("y");
- names.push_back("z");
- names.push_back("d");
- config_value_editors(4,4,10,names);
- Plane plane=v;
- value_editor[0]->set_text( String::num( plane.normal.x ) );
- value_editor[1]->set_text( String::num( plane.normal.y ) );
- value_editor[2]->set_text( String::num( plane.normal.z ) );
- value_editor[3]->set_text( String::num( plane.d ) );
-
- } break;
- case Variant::QUAT: {
-
- List<String> names;
- names.push_back("x");
- names.push_back("y");
- names.push_back("z");
- names.push_back("w");
- config_value_editors(4,4,10,names);
- Quat q=v;
- value_editor[0]->set_text( String::num( q.x ) );
- value_editor[1]->set_text( String::num( q.y ) );
- value_editor[2]->set_text( String::num( q.z ) );
- value_editor[3]->set_text( String::num( q.w ) );
-
- } break;
- case Variant::RECT3: {
-
- List<String> names;
- names.push_back("px");
- names.push_back("py");
- names.push_back("pz");
- names.push_back("sx");
- names.push_back("sy");
- names.push_back("sz");
- config_value_editors(6,3,16,names);
-
- Rect3 aabb=v;
- value_editor[0]->set_text( String::num( aabb.pos.x ) );
- value_editor[1]->set_text( String::num( aabb.pos.y ) );
- value_editor[2]->set_text( String::num( aabb.pos.z ) );
- value_editor[3]->set_text( String::num( aabb.size.x ) );
- value_editor[4]->set_text( String::num( aabb.size.y ) );
- value_editor[5]->set_text( String::num( aabb.size.z ) );
-
- } break;
- case Variant::TRANSFORM2D: {
-
- List<String> names;
- names.push_back("xx");
- names.push_back("xy");
- names.push_back("yx");
- names.push_back("yy");
- names.push_back("ox");
- names.push_back("oy");
- config_value_editors(6,2,16,names);
-
- Transform2D basis=v;
- for(int i=0;i<6;i++) {
-
- value_editor[i]->set_text( String::num( basis.elements[i/2][i%2] ) );
- }
-
- } break;
- case Variant::BASIS: {
-
- List<String> names;
- names.push_back("xx");
- names.push_back("xy");
- names.push_back("xz");
- names.push_back("yx");
- names.push_back("yy");
- names.push_back("yz");
- names.push_back("zx");
- names.push_back("zy");
- names.push_back("zz");
- config_value_editors(9,3,16,names);
-
- Basis basis=v;
- for(int i=0;i<9;i++) {
-
- value_editor[i]->set_text( String::num( basis.elements[i/3][i%3] ) );
- }
-
- } break;
- case Variant::TRANSFORM: {
-
-
- List<String> names;
- names.push_back("xx");
- names.push_back("xy");
- names.push_back("xz");
- names.push_back("xo");
- names.push_back("yx");
- names.push_back("yy");
- names.push_back("yz");
- names.push_back("yo");
- names.push_back("zx");
- names.push_back("zy");
- names.push_back("zz");
- names.push_back("zo");
- config_value_editors(12,4,16,names);
-
- Transform tr=v;
- for(int i=0;i<9;i++) {
-
- value_editor[(i/3)*4+i%3]->set_text( String::num( tr.basis.elements[i/3][i%3] ) );
- }
-
- value_editor[3]->set_text( String::num( tr.origin.x ) );
- value_editor[7]->set_text( String::num( tr.origin.y ) );
- value_editor[11]->set_text( String::num( tr.origin.z ) );
-
- } break;
- case Variant::COLOR: {
-
- if (!color_picker) {
- //late init for performance
- color_picker = memnew( ColorPicker );
- add_child(color_picker);
- color_picker->hide();
- color_picker->set_area_as_parent_rect();
- for(int i=0;i<4;i++)
- color_picker->set_margin((Margin)i,5);
- color_picker->connect("color_changed",this,"_color_changed");
- }
-
- color_picker->show();
- color_picker->set_edit_alpha(hint!=PROPERTY_HINT_COLOR_NO_ALPHA);
- color_picker->set_pick_color(v);
- set_size( Size2(300*EDSCALE, color_picker->get_combined_minimum_size().height+10*EDSCALE));
- color_picker->set_focus_on_line_edit();
- /*
- int ofs=80;
- int m=10;
- int h=20;
- Color c=v;
- float values[4]={c.r,c.g,c.b,c.a};
- for (int i=0;i<4;i++) {
- int y=m+i*h;
-
- value_editor[i]->show();
- value_label[i]->show();
- value_label[i]->set_pos(Point2(ofs,y));
- scroll[i]->set_min(0);
- scroll[i]->set_max(1.0);
- scroll[i]->set_page(0);
- scroll[i]->set_pos(Point2(ofs+15,y+Math::floor((h-scroll[i]->get_minimum_size().height)/2.0)));
- scroll[i]->set_val(values[i]);
- scroll[i]->set_size(Size2(120,1));
- scroll[i]->show();
- value_editor[i]->set_pos(Point2(ofs+140,y));
- value_editor[i]->set_size(Size2(40,h));
- value_editor[i]->set_text( String::num(values[i],2 ));
-
- }
-
- value_label[0]->set_text("R");
- value_label[1]->set_text("G");
- value_label[2]->set_text("B");
- value_label[3]->set_text("A");
-
- Size2 new_size = value_editor[3]->get_pos() + value_editor[3]->get_size() + Point2(10,10);
- set_size( new_size );
- */
-
- } break;
- case Variant::IMAGE: {
-
- List<String> names;
- names.push_back(TTR("New"));
- names.push_back(TTR("Load"));
- names.push_back(TTR("Clear"));
- config_action_buttons(names);
-
- } break;
- case Variant::NODE_PATH: {
-
- List<String> names;
- names.push_back(TTR("Assign"));
- names.push_back(TTR("Clear"));
- config_action_buttons(names);
-
- } break;
- case Variant::OBJECT: {
-
- if (hint!=PROPERTY_HINT_RESOURCE_TYPE)
- break;
-
-
- menu->clear();
- menu->set_size(Size2(1,1));
-
- if (p_name=="script/script" && hint_text=="Script" && owner->cast_to<Node>()) {
- menu->add_icon_item(get_icon("Script","EditorIcons"),TTR("New Script"),OBJ_MENU_NEW_SCRIPT);
- menu->add_separator();
- } else if (hint_text!="") {
- int idx=0;
-
- for(int i=0;i<hint_text.get_slice_count(",");i++) {
-
-
-
- String base=hint_text.get_slice(",",i);
-
- Set<String> valid_inheritors;
- valid_inheritors.insert(base);
- List<StringName> inheritors;
- ClassDB::get_inheriters_from_class(base.strip_edges(),&inheritors);
- List<StringName>::Element *E=inheritors.front();
- while(E) {
- valid_inheritors.insert(E->get());
- E=E->next();
- }
-
- for(Set<String>::Element *E=valid_inheritors.front();E;E=E->next()) {
- String t = E->get();
- if (!ClassDB::can_instance(t))
- continue;
- inheritors_array.push_back(t);
-
- int id = TYPE_BASE_ID+idx;
- if (has_icon(t,"EditorIcons")) {
-
- menu->add_icon_item(get_icon(t,"EditorIcons"),TTR("New")+" "+t,id);
- } else {
-
- menu->add_item(TTR("New")+" "+t,id);
- }
-
- idx++;
- }
-
-
- }
-
- if (menu->get_item_count())
- menu->add_separator();
- }
-
- menu->add_icon_item(get_icon("Load","EditorIcons"),"Load",OBJ_MENU_LOAD);
-
- if (!RES(v).is_null()) {
-
-
-
- menu->add_icon_item(get_icon("EditResource","EditorIcons"),"Edit",OBJ_MENU_EDIT);
- menu->add_icon_item(get_icon("Del","EditorIcons"),"Clear",OBJ_MENU_CLEAR);
- menu->add_icon_item(get_icon("Duplicate","EditorIcons"),"Make Unique",OBJ_MENU_MAKE_UNIQUE);
- /*RES r = v;
- if (r.is_valid() && r->get_path().is_resource_file() && r->get_import_metadata().is_valid()) {
- menu->add_separator();
- menu->add_icon_item(get_icon("ReloadSmall","EditorIcons"),"Re-Import",OBJ_MENU_REIMPORT);
- }*/
- /*if (r.is_valid() && r->get_path().is_resource_file()) {
- menu->set_item_tooltip(1,r->get_path());
- } else if (r.is_valid()) {
- menu->set_item_tooltip(1,r->get_name()+" ("+r->get_type()+")");
- }*/
- } else {
-
- }
-
-
- RES cb=EditorSettings::get_singleton()->get_resource_clipboard();
- 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 (ClassDB::is_parent_class(cb->get_class(),hint_text.get_slice(",",i))) {
- paste_valid=true;
- break;
- }
- }
-
- if (!RES(v).is_null() || paste_valid) {
- menu->add_separator();
-
-
- if (!RES(v).is_null()) {
-
- menu->add_item(TTR("Copy"),OBJ_MENU_COPY);
- }
-
- if (paste_valid) {
-
- menu->add_item(TTR("Paste"),OBJ_MENU_PASTE);
- }
- }
-
-
-
- menu->set_pos(get_pos());
- menu->popup();
- hide();
- updating=false;
- return false;
-
-
- } break;
- case Variant::INPUT_EVENT: {
-
-
- } break;
- case Variant::DICTIONARY: {
-
-
- } break;
- case Variant::POOL_BYTE_ARRAY: {
-
-
- } break;
- case Variant::POOL_INT_ARRAY: {
-
-
- } break;
- case Variant::POOL_REAL_ARRAY: {
-
-
- } break;
- case Variant::POOL_STRING_ARRAY: {
-
-
- } break;
- case Variant::POOL_VECTOR3_ARRAY: {
-
-
- } break;
- case Variant::POOL_COLOR_ARRAY: {
-
-
- } break;
- default: {}
- }
-
- updating=false;
- return true;
-}
-
-void CustomPropertyEditor::_file_selected(String p_file) {
-
- switch(type) {
-
- case Variant::STRING: {
-
- if (hint==PROPERTY_HINT_FILE || hint==PROPERTY_HINT_DIR) {
-
- v=GlobalConfig::get_singleton()->localize_path(p_file);
- emit_signal("variant_changed");
- hide();
- }
-
- if (hint==PROPERTY_HINT_GLOBAL_FILE || hint==PROPERTY_HINT_GLOBAL_DIR) {
-
- v=p_file;
- emit_signal("variant_changed");
- hide();
- }
-
- } break;
- case Variant::OBJECT: {
-
- String type=(hint==PROPERTY_HINT_RESOURCE_TYPE)?hint_text:String();
-
- RES res = ResourceLoader::load(p_file,type);
- if (res.is_null()) {
- error->set_text(TTR("Error loading file: Not a resource!"));
- error->popup_centered_minsize();
- break;
- }
- v=res.get_ref_ptr();
- emit_signal("variant_changed");
- hide();
- } break;
- case Variant::IMAGE: {
-
- Image image;
- Error err = ImageLoader::load_image(p_file,&image);
- ERR_EXPLAIN(TTR("Couldn't load image"));
- ERR_FAIL_COND(err);
- v=image;
- emit_signal("variant_changed");
- hide();
- } break;
- default: {}
- }
-}
-
-void CustomPropertyEditor::_type_create_selected(int p_idx) {
-
-
- if (type==Variant::INT || type==Variant::REAL) {
-
-
- float newval=0;
- switch(p_idx) {
-
- case EASING_LINEAR: {
-
- newval=1;
- } break;
- case EASING_EASE_IN: {
-
- newval=2.0;
- } break;
- case EASING_EASE_OUT: {
- newval=0.5;
- } break;
- case EASING_ZERO: {
-
- newval=0;
- } break;
- case EASING_IN_OUT: {
-
- newval=-0.5;
- } break;
- case EASING_OUT_IN: {
- newval=-2.0;
- } break;
- }
-
- v=newval;
- emit_signal("variant_changed");
- easing_draw->update();
-
- } else if (type==Variant::OBJECT) {
-
- ERR_FAIL_INDEX(p_idx,inheritors_array.size());
-
- //List<String> inheritors;
- //ClassDB::get_inheriters_from(hint_text,&inheritors);
- //inheritors.push_front(hint_text);
-
- //ERR_FAIL_INDEX( p_idx, inheritors.size() );
- String intype=inheritors_array[p_idx];
-
- Object *obj = ClassDB::instance(intype);
-
- ERR_FAIL_COND( !obj );
-
-
- Resource *res=obj->cast_to<Resource>();
- ERR_FAIL_COND( !res );
-
- v=Ref<Resource>(res).get_ref_ptr();
- emit_signal("variant_changed");
- hide();
- }
-
-}
-
-
-void CustomPropertyEditor::_color_changed(const Color& p_color) {
-
- v=p_color;
- emit_signal("variant_changed");
-
-}
-
-void CustomPropertyEditor::_node_path_selected(NodePath p_path) {
-
- if (picking_viewport) {
-
- Node* to_node=get_node(p_path);
- if (!to_node->cast_to<Viewport>()) {
- EditorNode::get_singleton()->show_warning("Selected node is not a Viewport!");
- return;
- }
-
- Ref<ViewportTexture> vt;
- vt.instance();
- vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node));
- vt->setup_local_to_scene();
- v=vt;
- emit_signal("variant_changed");
- return;
- }
-
- if (hint==PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE && hint_text!=String()) {
-
- Node* node=get_node(hint_text);
- if (node) {
-
- Node *tonode=node->get_node(p_path);
- if (tonode) {
- p_path=node->get_path_to(tonode);
- }
- }
-
- } else if (owner) {
-
- Node *node=NULL;
-
- if (owner->is_class("Node"))
- node = owner->cast_to<Node>();
- else if (owner->is_class("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 *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
-
-}
-
-void CustomPropertyEditor::_action_pressed(int p_which) {
-
-
- if (updating)
- return;
-
- switch(type) {
- case Variant::BOOL: {
- v=checks20[0]->is_pressed();
- emit_signal("variant_changed");
- } break;
- case Variant::INT: {
-
- if (hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || hint==PROPERTY_HINT_LAYERS_2D_RENDER || hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
-
- uint32_t f = v;
- if (checks20[p_which]->is_pressed())
- f|=(1<<p_which);
- else
- f&=~(1<<p_which);
-
- v=f;
- emit_signal("variant_changed");
- }
-
- } break;
- case Variant::STRING: {
-
- if (hint==PROPERTY_HINT_MULTILINE_TEXT) {
-
- hide();
-
- } else if (hint==PROPERTY_HINT_FILE || hint==PROPERTY_HINT_GLOBAL_FILE) {
- if (p_which==0) {
-
- if (hint==PROPERTY_HINT_FILE)
- file->set_access(EditorFileDialog::ACCESS_RESOURCES);
- else
- file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
-
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- file->clear_filters();
-
- file->clear_filters();
-
-
- if (hint_text!="") {
- Vector<String> extensions=hint_text.split(",");
- for(int i=0;i<extensions.size();i++) {
-
- String filter = extensions[i];
- if (filter.begins_with("."))
- filter="*"+extensions[i];
- else if (!filter.begins_with("*"))
- filter="*."+extensions[i];
-
-
- file->add_filter(filter+" ; "+extensions[i].to_upper() );
-
- }
- }
- file->popup_centered_ratio();
- } else {
-
- v="";
- emit_signal("variant_changed");
- hide();
-
- }
-
- } else if (hint==PROPERTY_HINT_DIR || hint==PROPERTY_HINT_GLOBAL_DIR) {
-
- if (p_which==0) {
-
- if (hint==PROPERTY_HINT_DIR)
- file->set_access(EditorFileDialog::ACCESS_RESOURCES);
- else
- file->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- file->set_mode(EditorFileDialog::MODE_OPEN_DIR);
- file->clear_filters();
- file->popup_centered_ratio();
- } else {
-
- v="";
- emit_signal("variant_changed");
- hide();
-
- }
-
- }
-
- } break;
- case Variant::NODE_PATH: {
-
- if (p_which==0) {
-
- picking_viewport=false;
- scene_tree->set_title(TTR("Pick a Node"));
- scene_tree->popup_centered_ratio();
-
- } else if (p_which==1) {
-
-
- v=NodePath();
- emit_signal("variant_changed");
- hide();
- }
- } break;
- case Variant::OBJECT: {
-
- if (p_which==0) {
-
-
- ERR_FAIL_COND( inheritors_array.empty() );
-
- String intype=inheritors_array[0];
-
-
- if (hint==PROPERTY_HINT_RESOURCE_TYPE) {
-
- Object *obj = ClassDB::instance(intype);
- ERR_BREAK( !obj );
- Resource *res=obj->cast_to<Resource>();
- ERR_BREAK( !res );
-
- v=Ref<Resource>(res).get_ref_ptr();
- emit_signal("variant_changed");
- hide();
-
- }
- } else if (p_which==1) {
-
- file->set_access(EditorFileDialog::ACCESS_RESOURCES);
- 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();
- for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- file->add_filter("*."+E->get()+" ; "+E->get().to_upper() );
-
- }
-
- file->popup_centered_ratio();
-
- } else if (p_which==2) {
-
- RefPtr RefPtr=v;
-
- if (!RefPtr.is_null()) {
-
- emit_signal("resource_edit_request");
- hide();
- }
-
- } else if (p_which==3) {
-
-
- v=Variant();
- emit_signal("variant_changed");
- hide();
- } else if (p_which==4) {
-
-
- RefPtr RefPtr=v;
- Ref<Resource> res_orig = RefPtr;
- if (res_orig.is_null())
- return;
-
- List<PropertyInfo> property_list;
- res_orig->get_property_list(&property_list);
- List< Pair<String,Variant> > propvalues;
-
- for(List<PropertyInfo>::Element *E=property_list.front();E;E=E->next()) {
-
- Pair<String,Variant> p;
- PropertyInfo &pi = E->get();
- if (pi.usage&PROPERTY_USAGE_STORAGE) {
-
- p.first=pi.name;
- p.second=res_orig->get(pi.name);
- }
-
- propvalues.push_back(p);
- }
-
- Ref<Resource> res = Ref<Resource>( ClassDB::instance( res_orig->get_class() ));
-
- ERR_FAIL_COND(res.is_null());
-
- for(List< Pair<String,Variant> >::Element *E=propvalues.front();E;E=E->next()) {
-
- Pair<String,Variant> &p=E->get();
- res->set(p.first,p.second);
- }
-
- v=res.get_ref_ptr();
- emit_signal("variant_changed");
- hide();
- }
-
- } break;
- case Variant::IMAGE: {
-
- if (p_which==0) {
- //new image too difficult
- ERR_PRINT("New Image Unimplemented");
-
- } else if (p_which==1) {
-
- file->set_access(EditorFileDialog::ACCESS_RESOURCES);
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- List<String> extensions;
- ImageLoader::get_recognized_extensions(&extensions);
-
- file->clear_filters();
-
- for (List<String>::Element *E=extensions.front();E;E=E->next()) {
-
- file->add_filter("*."+E->get()+" ; "+E->get().to_upper() );
-
- }
-
- file->popup_centered_ratio();
-
- } else if (p_which==2) {
-
- v=Image();
- emit_signal("variant_changed");
- hide();
- }
-
- } break;
- default: {};
- }
-
-}
-
-void CustomPropertyEditor::_scroll_modified(double p_value) {
-
- if (updating)
- return;
- /*
- switch(type) {
-
- case Variant::COLOR: {
-
- for (int i=0;i<4;i++) {
-
- value_editor[i]->set_text( String::num(scroll[i]->get_val(),2) );
- }
- Color c;
- c.r=scroll[0]->get_val();
- c.g=scroll[1]->get_val();
- c.b=scroll[2]->get_val();
- c.a=scroll[3]->get_val();
- v=c;
- update();
- emit_signal("variant_changed");
- } break;
- default: {}
- }
- */
-}
-
-
-void CustomPropertyEditor::_drag_easing(const InputEvent& p_ev) {
-
-
- if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
-
- float rel = p_ev.mouse_motion.relative_x;
- if (rel==0)
- return;
-
- bool flip=hint_text=="attenuation";
-
- if (flip)
- rel=-rel;
-
- float val = v;
- if (val==0)
- return;
- bool sg = val < 0;
- val = Math::absf(val);
-
- val = Math::log(val)/Math::log((float)2.0);
- //logspace
- val+=rel*0.05;
- //
-
- val = Math::pow(2.0f,val);
- if (sg)
- val=-val;
-
- v=val;
- easing_draw->update();
- //emit_signal("variant_changed");
- emit_signal("variant_changed");
- }
- if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT) {
-
-
- }
-
-}
-
-
-void CustomPropertyEditor::_draw_easing() {
-
-
- RID ci = easing_draw->get_canvas_item();
-
- Size2 s = easing_draw->get_size();
- Rect2 r(Point2(),s);
- r=r.grow(3);
- get_stylebox("normal","LineEdit")->draw(ci,r);
- //VisualServer::get_singleton()->canvas_item_add
-
-
- int points = 48;
-
- float prev=1.0;
- float exp=v;
- bool flip=hint_text=="attenuation";
-
- Ref<Font> f = get_font("font","Label");
- Color color = get_color("font_color","Label");
-
- for(int i=1;i<=points;i++) {
-
- float ifl = i/float(points);
- float iflp = (i-1)/float(points);
-
- float h = 1.0-Math::ease(ifl,exp);
-
- if (flip) {
- ifl=1.0-ifl;
- iflp=1.0-iflp;
- }
-
- VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(iflp*s.width,prev*s.height),Point2(ifl*s.width,h*s.height),color);
- prev=h;
- }
-
- f->draw(ci,Point2(10,10+f->get_ascent()),String::num(exp,2),color);
-}
-
-void CustomPropertyEditor::_text_edit_changed() {
-
- v=text_edit->get_text();
- emit_signal("variant_changed");
-
-}
-
-void CustomPropertyEditor::_create_dialog_callback() {
-
-
- v=create_dialog->get_selected_type();
- emit_signal("variant_changed");
-}
-
-void CustomPropertyEditor::_create_selected_property(const String& p_prop) {
-
-
- v=p_prop;
- emit_signal("variant_changed");
-}
-
-void CustomPropertyEditor::_modified(String p_string) {
-
- if (updating)
- return;
- updating=true;
- switch(type) {
- case Variant::INT: {
-
- if (evaluator)
- v=evaluator->eval(value_editor[0]->get_text());
- else
- v=value_editor[0]->get_text().to_int();
- emit_signal("variant_changed");
-
-
- } break;
- case Variant::REAL: {
-
- if (hint!=PROPERTY_HINT_EXP_EASING) {
- if (evaluator)
- v=evaluator->eval(value_editor[0]->get_text());
- else
- v=value_editor[0]->get_text().to_double();
- emit_signal("variant_changed");
-
- }
-
- } break;
- case Variant::STRING: {
-
- v=value_editor[0]->get_text();
- emit_signal("variant_changed");
- } break;
- case Variant::VECTOR2: {
-
- Vector2 vec;
- if (evaluator) {
- vec.x=evaluator->eval(value_editor[0]->get_text());
- vec.y=evaluator->eval(value_editor[1]->get_text());
- } else {
- vec.x=value_editor[0]->get_text().to_double();
- vec.y=value_editor[1]->get_text().to_double();
- }
- v=vec;
- emit_signal("variant_changed");
-
- } break;
- case Variant::RECT2: {
-
- Rect2 r2;
- if (evaluator) {
- r2.pos.x=evaluator->eval(value_editor[0]->get_text());
- r2.pos.y=evaluator->eval(value_editor[1]->get_text());
- r2.size.x=evaluator->eval(value_editor[2]->get_text());
- r2.size.y=evaluator->eval(value_editor[3]->get_text());
- } else {
- r2.pos.x=value_editor[0]->get_text().to_double();
- r2.pos.y=value_editor[1]->get_text().to_double();
- r2.size.x=value_editor[2]->get_text().to_double();
- r2.size.y=value_editor[3]->get_text().to_double();
- }
- v=r2;
- emit_signal("variant_changed");
-
- } break;
-
- case Variant::VECTOR3: {
-
- Vector3 vec;
- if (evaluator) {
- vec.x=evaluator->eval(value_editor[0]->get_text());
- vec.y=evaluator->eval(value_editor[1]->get_text());
- vec.z=evaluator->eval(value_editor[2]->get_text());
- } else {
- vec.x=value_editor[0]->get_text().to_double();
- vec.y=value_editor[1]->get_text().to_double();
- vec.z=value_editor[2]->get_text().to_double();
- }
- v=vec;
- emit_signal("variant_changed");
-
- } break;
- case Variant::PLANE: {
-
- Plane pl;
- if (evaluator) {
- pl.normal.x=evaluator->eval(value_editor[0]->get_text());
- pl.normal.y=evaluator->eval(value_editor[1]->get_text());
- pl.normal.z=evaluator->eval(value_editor[2]->get_text());
- pl.d=evaluator->eval(value_editor[3]->get_text());
- } else {
- pl.normal.x=value_editor[0]->get_text().to_double();
- pl.normal.y=value_editor[1]->get_text().to_double();
- pl.normal.z=value_editor[2]->get_text().to_double();
- pl.d=value_editor[3]->get_text().to_double();
- }
- v=pl;
- emit_signal("variant_changed");
-
- } break;
- case Variant::QUAT: {
-
- Quat q;
- if (evaluator) {
- q.x=evaluator->eval(value_editor[0]->get_text());
- q.y=evaluator->eval(value_editor[1]->get_text());
- q.z=evaluator->eval(value_editor[2]->get_text());
- q.w=evaluator->eval(value_editor[3]->get_text());
- } else {
- q.x=value_editor[0]->get_text().to_double();
- q.y=value_editor[1]->get_text().to_double();
- q.z=value_editor[2]->get_text().to_double();
- q.w=value_editor[3]->get_text().to_double();
- }
- v=q;
- emit_signal("variant_changed");
-
- } break;
- case Variant::RECT3: {
-
- Vector3 pos;
- Vector3 size;
-
- if (evaluator) {
- pos.x=evaluator->eval(value_editor[0]->get_text());
- pos.y=evaluator->eval(value_editor[1]->get_text());
- pos.z=evaluator->eval(value_editor[2]->get_text());
- size.x=evaluator->eval(value_editor[3]->get_text());
- size.y=evaluator->eval(value_editor[4]->get_text());
- size.z=evaluator->eval(value_editor[5]->get_text());
- } else {
- pos.x=value_editor[0]->get_text().to_double();
- pos.y=value_editor[1]->get_text().to_double();
- pos.z=value_editor[2]->get_text().to_double();
- size.x=value_editor[3]->get_text().to_double();
- size.y=value_editor[4]->get_text().to_double();
- size.z=value_editor[5]->get_text().to_double();
- }
- v=Rect3(pos,size);
- emit_signal("variant_changed");
-
- } break;
- case Variant::TRANSFORM2D: {
-
- Transform2D m;
- for(int i=0;i<6;i++) {
- if (evaluator) {
- m.elements[i/2][i%2]=evaluator->eval(value_editor[i]->get_text());
- } else {
- m.elements[i/2][i%2]=value_editor[i]->get_text().to_double();
- }
- }
-
- v=m;
- emit_signal("variant_changed");
-
- } break;
- case Variant::BASIS: {
-
- Basis m;
- for(int i=0;i<9;i++) {
-
- if (evaluator) {
- m.elements[i/3][i%3]=evaluator->eval(value_editor[i]->get_text());
- } else {
- m.elements[i/3][i%3]=value_editor[i]->get_text().to_double();
- }
- }
-
- v=m;
- emit_signal("variant_changed");
-
- } break;
- case Variant::TRANSFORM: {
-
- Basis basis;
- for(int i=0;i<9;i++) {
-
- if (evaluator) {
- basis.elements[i/3][i%3]=evaluator->eval(value_editor[(i/3)*4+i%3]->get_text());
- } else {
- basis.elements[i/3][i%3]=value_editor[(i/3)*4+i%3]->get_text().to_double();
- }
- }
-
- Vector3 origin;
-
- if (evaluator) {
- origin.x=evaluator->eval(value_editor[3]->get_text());
- origin.y=evaluator->eval(value_editor[7]->get_text());
- origin.z=evaluator->eval(value_editor[11]->get_text());
- } else {
- origin.x=value_editor[3]->get_text().to_double();
- origin.y=value_editor[7]->get_text().to_double();
- origin.z=value_editor[11]->get_text().to_double();
- }
-
- v=Transform(basis,origin);
- emit_signal("variant_changed");
-
-
- } break;
- case Variant::COLOR: {
- /*
- for (int i=0;i<4;i++) {
-
- scroll[i]->set_val( value_editor[i]->get_text().to_double() );
- }
- Color c;
- c.r=value_editor[0]->get_text().to_double();
- c.g=value_editor[1]->get_text().to_double();
- c.b=value_editor[2]->get_text().to_double();
- c.a=value_editor[3]->get_text().to_double();
- v=c;
- update();
- emit_signal("variant_changed");
- */
- } break;
- case Variant::IMAGE: {
-
-
- } break;
- case Variant::NODE_PATH: {
-
- v=NodePath(value_editor[0]->get_text());
- emit_signal("variant_changed");
- } break;
- case Variant::INPUT_EVENT: {
-
-
- } break;
- case Variant::DICTIONARY: {
-
-
- } break;
- case Variant::POOL_BYTE_ARRAY: {
-
-
- } break;
- case Variant::POOL_INT_ARRAY: {
-
-
- } break;
- case Variant::POOL_REAL_ARRAY: {
-
-
- } break;
- case Variant::POOL_STRING_ARRAY: {
-
-
- } break;
- case Variant::POOL_VECTOR3_ARRAY: {
-
-
- } break;
- case Variant::POOL_COLOR_ARRAY: {
-
-
- } break;
- default: {}
- }
-
- updating=false;
-}
-
-void CustomPropertyEditor::_range_modified(double p_value)
-{
- v=p_value;
- emit_signal("variant_changed");
-}
-
-void CustomPropertyEditor::_focus_enter() {
- switch(type) {
- case Variant::REAL:
- case Variant::STRING:
- case Variant::VECTOR2:
- case Variant::RECT2:
- case Variant::VECTOR3:
- case Variant::PLANE:
- case Variant::QUAT:
- case Variant::RECT3:
- case Variant::TRANSFORM2D:
- case Variant::BASIS:
- case Variant::TRANSFORM: {
- for (int i=0;i<MAX_VALUE_EDITORS;++i) {
- if (value_editor[i]->has_focus()) {
- value_editor[i]->select_all();
- break;
- }
- }
- } break;
- default: {}
- }
-
-}
-
-void CustomPropertyEditor::_focus_exit() {
- switch(type) {
- case Variant::REAL:
- case Variant::STRING:
- case Variant::VECTOR2:
- case Variant::RECT2:
- case Variant::VECTOR3:
- case Variant::PLANE:
- case Variant::QUAT:
- case Variant::RECT3:
- case Variant::TRANSFORM2D:
- case Variant::BASIS:
- case Variant::TRANSFORM: {
- for (int i=0;i<MAX_VALUE_EDITORS;++i) {
- value_editor[i]->select(0, 0);
- }
- } break;
- default: {}
- }
-
-}
-
-void CustomPropertyEditor::config_action_buttons(const List<String>& p_strings) {
-
- int w=100;
- int h=18;
- int m=5;
-
- set_size( Size2( w, m*2+(h+m)*p_strings.size() ) );
-
- for (int i=0;i<MAX_ACTION_BUTTONS;i++) {
-
- if (i<p_strings.size()) {
- action_buttons[i]->show();
- action_buttons[i]->set_text(p_strings[i]);
- action_buttons[i]->set_pos( Point2( m, m+i*(h+m) ));
- action_buttons[i]->set_size( Size2( w-m*2, h ) );
- action_buttons[i]->set_flat(true);
- } else {
- action_buttons[i]->hide();
- }
- }
-
-
-}
-
-void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns,int p_label_w,const List<String>& p_strings) {
-
- int w=80;
- int h=20;
- int m=10;
-
- int rows=((p_amount-1)/p_columns)+1;
-
- set_size( Size2( m*(1+p_columns)+(w+p_label_w)*p_columns, m*(1+rows)+h*rows ) );
-
- for (int i=0;i<MAX_VALUE_EDITORS;i++) {
-
- int c=i%p_columns;
- int r=i/p_columns;
-
- if (i<p_amount) {
- value_editor[i]->show();
- value_label[i]->show();
- value_label[i]->set_text(i<p_strings.size()?p_strings[i]:String(""));
- value_editor[i]->set_pos( Point2( m+p_label_w+c*(w+m+p_label_w), m+r*(h+m) ));
- value_editor[i]->set_size( Size2( w, h ) );
- value_label[i]->set_pos( Point2( m+c*(w+m+p_label_w), m+r*(h+m) ) );
- value_editor[i]->set_editable(!read_only);
- } else {
- value_editor[i]->hide();
- value_label[i]->hide();
- }
- }
-
-
-
-}
-
-
-void CustomPropertyEditor::_bind_methods() {
-
- ClassDB::bind_method("_focus_enter", &CustomPropertyEditor::_focus_enter);
- ClassDB::bind_method("_focus_exit", &CustomPropertyEditor::_focus_exit);
- ClassDB::bind_method("_modified",&CustomPropertyEditor::_modified);
- ClassDB::bind_method("_range_modified", &CustomPropertyEditor::_range_modified);
- ClassDB::bind_method("_scroll_modified",&CustomPropertyEditor::_scroll_modified);
- ClassDB::bind_method("_action_pressed",&CustomPropertyEditor::_action_pressed);
- ClassDB::bind_method("_file_selected",&CustomPropertyEditor::_file_selected);
- ClassDB::bind_method("_type_create_selected",&CustomPropertyEditor::_type_create_selected);
- ClassDB::bind_method("_node_path_selected",&CustomPropertyEditor::_node_path_selected);
- ClassDB::bind_method("_color_changed",&CustomPropertyEditor::_color_changed);
- ClassDB::bind_method("_draw_easing",&CustomPropertyEditor::_draw_easing);
- ClassDB::bind_method("_drag_easing",&CustomPropertyEditor::_drag_easing);
- ClassDB::bind_method( "_text_edit_changed",&CustomPropertyEditor::_text_edit_changed);
- ClassDB::bind_method( "_menu_option",&CustomPropertyEditor::_menu_option);
- ClassDB::bind_method( "_create_dialog_callback",&CustomPropertyEditor::_create_dialog_callback);
- ClassDB::bind_method( "_create_selected_property",&CustomPropertyEditor::_create_selected_property);
-
-
-
- ADD_SIGNAL( MethodInfo("variant_changed") );
- ADD_SIGNAL( MethodInfo("resource_edit_request") );
-}
-CustomPropertyEditor::CustomPropertyEditor() {
-
-
- read_only=false;
- updating=false;
-
- for (int i=0;i<MAX_VALUE_EDITORS;i++) {
-
- value_editor[i]=memnew( LineEdit );
- add_child( value_editor[i] );
- value_label[i]=memnew( Label );
- add_child( value_label[i] );
- value_editor[i]->hide();
- value_label[i]->hide();
- value_editor[i]->connect("text_entered", this,"_modified");
- value_editor[i]->connect("focus_entered", this, "_focus_enter");
- value_editor[i]->connect("focus_exited", this, "_focus_exit");
- }
-
- for(int i=0;i<4;i++) {
-
- scroll[i] = memnew( HScrollBar );
- scroll[i]->hide();
- scroll[i]->set_min(0);
- scroll[i]->set_max(1.0);
- scroll[i]->set_step(0.01);
- add_child(scroll[i]);
- scroll[i]->connect("value_changed", this,"_scroll_modified");
-
- }
-
- checks20gc = memnew( GridContainer );
- add_child(checks20gc);
- checks20gc->set_columns(11);
-
- for(int i=0;i<20;i++) {
- if (i==5 || i==15) {
- Control *space = memnew( Control );
- space->set_custom_minimum_size(Size2(20,0)*EDSCALE);
- checks20gc->add_child(space);
- }
-
- checks20[i]=memnew( CheckBox );
- checks20[i]->set_toggle_mode(true);
- checks20[i]->set_focus_mode(FOCUS_NONE);
- checks20gc->add_child(checks20[i]);
- checks20[i]->hide();
- checks20[i]->connect("pressed",this,"_action_pressed",make_binds(i));
- checks20[i]->set_tooltip(vformat(TTR("Bit %d, val %d."), i, 1<<i));
- }
-
- text_edit = memnew( TextEdit );
- add_child(text_edit);
- text_edit->set_area_as_parent_rect();
- for(int i=0;i<4;i++)
- text_edit->set_margin((Margin)i,5);
- text_edit->set_margin(MARGIN_BOTTOM,30);
-
- text_edit->hide();
- text_edit->connect("text_changed",this,"_text_edit_changed");
-
- for (int i=0;i<MAX_ACTION_BUTTONS;i++) {
-
- action_buttons[i]=memnew(Button);
- action_buttons[i]->hide();
- add_child(action_buttons[i]);
- Vector<Variant> binds;
- binds.push_back(i);
- action_buttons[i]->connect("pressed", this,"_action_pressed",binds);
- }
-
- color_picker=NULL;
-
-
-
- set_as_toplevel(true);
- file = memnew ( EditorFileDialog );
- add_child(file);
- file->hide();
-
- file->connect("file_selected", this,"_file_selected");
- file->connect("dir_selected", this,"_file_selected");
-
- error = memnew( ConfirmationDialog );
- error->set_title(TTR("Error!"));
- add_child(error);
- //error->get_cancel()->hide();
-
- type_button = memnew( MenuButton );
- add_child(type_button);
- type_button->hide();
- type_button->get_popup()->connect("id_pressed", this,"_type_create_selected");
-
-
- scene_tree = memnew( SceneTreeDialog );
- add_child(scene_tree);
- scene_tree->connect("selected", this,"_node_path_selected");
- scene_tree->get_scene_tree()->set_show_enabled_subscene(true);
-
- texture_preview = memnew( TextureRect );
- add_child( texture_preview);
- texture_preview->hide();
-
- easing_draw=memnew( Control );
- add_child(easing_draw);
- easing_draw->hide();
- easing_draw->connect("draw",this,"_draw_easing");
- easing_draw->connect("gui_input",this,"_drag_easing");
- //easing_draw->emit_signal(SceneStringNames::get_singleton()->input_event,InputEvent());
- easing_draw->set_default_cursor_shape(Control::CURSOR_MOVE);
-
- menu = memnew(PopupMenu);
- add_child(menu);
- menu->connect("id_pressed",this,"_menu_option");
-
- evaluator = NULL;
-
- spinbox = memnew ( SpinBox );
- add_child(spinbox);
- spinbox->set_area_as_parent_rect(5);
- spinbox->connect("value_changed",this,"_range_modified");
-
- slider = memnew ( HSlider );
- add_child(slider);
- slider->set_area_as_parent_rect(5);
- slider->connect("value_changed",this,"_range_modified");
-
- create_dialog = NULL;
- property_select = NULL;
-}
-
-bool PropertyEditor::_might_be_in_instance() {
-
- if (!obj)
- return false;
-
- Node *node = obj->cast_to<Node>();
-
- Node* edited_scene =EditorNode::get_singleton()->get_edited_scene();
-
- bool might_be=false;
-
- while(node) {
-
- if (node->get_scene_instance_state().is_valid()) {
- might_be=true;
- break;
- }
- if (node==edited_scene) {
- if (node->get_scene_inherited_state().is_valid()) {
- might_be=true;
- break;
- }
- might_be=false;
- break;
- }
- node=node->get_owner();
- }
-
- return might_be;
-
-}
-
-bool PropertyEditor::_get_instanced_node_original_property(const StringName& p_prop, Variant& value) {
-
- Node *node = obj->cast_to<Node>();
-
- if (!node)
- return false;
-
- Node *orig=node;
-
- Node* edited_scene =EditorNode::get_singleton()->get_edited_scene();
-
- bool found=false;
-
- //print_line("for prop - "+String(p_prop));
-
-
- while(node) {
-
- Ref<SceneState> ss;
-
- if (node==edited_scene) {
- ss=node->get_scene_inherited_state();
-
- } else {
- ss=node->get_scene_instance_state();
- }
- //print_line("at - "+String(edited_scene->get_path_to(node)));
-
- if (ss.is_valid()) {
-
- NodePath np = node->get_path_to(orig);
- int node_idx = ss->find_node_by_path(np);
- //print_line("\t valid, nodeidx "+itos(node_idx));
- if (node_idx>=0) {
- bool lfound=false;
- Variant lvar;
- lvar=ss->get_property_value(node_idx,p_prop,lfound);
- if (lfound) {
-
- found=true;
- value=lvar;
- //print_line("\t found value "+String(value));
- }
- }
- }
- if (node==edited_scene) {
- //just in case
- break;
- }
- node=node->get_owner();
-
- }
-
- return found;
-}
-
-bool PropertyEditor::_is_property_different(const Variant& p_current, const Variant& p_orig,int p_usage) {
-
-
- {
- Node *node = obj->cast_to<Node>();
- if (!node)
- return false;
-
- Node* edited_scene =EditorNode::get_singleton()->get_edited_scene();
- bool found_state=false;
-
- //print_line("for prop - "+String(p_prop));
-
-
- while(node) {
-
- Ref<SceneState> ss;
-
- if (node==edited_scene) {
- ss=node->get_scene_inherited_state();
-
- } else {
- ss=node->get_scene_instance_state();
- }
-
- if (ss.is_valid()) {
- found_state=true;
- }
- if (node==edited_scene) {
- //just in case
- break;
- }
- node=node->get_owner();
- }
-
- if (!found_state)
- return false; //pointless to check if we are not comparing against anything.
- }
-
- if (p_orig.get_type()==Variant::NIL) {
-
-
-
- //special cases
- if (p_current.is_zero() && p_usage&PROPERTY_USAGE_STORE_IF_NONZERO)
- return false;
- if (p_current.is_one() && p_usage&PROPERTY_USAGE_STORE_IF_NONONE)
- return false;
- }
-
- if (p_current.get_type()==Variant::REAL && p_orig.get_type()==Variant::REAL) {
- float a = p_current;
- float b = p_orig;
-
- return Math::abs(a-b)>CMP_EPSILON; //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error
- }
-
- return bool(Variant::evaluate(Variant::OP_NOT_EQUAL,p_current,p_orig));
-}
-
-TreeItem *PropertyEditor::find_item(TreeItem *p_item,const String& p_name) {
-
-
- if (!p_item)
- return NULL;
-
- String name = p_item->get_metadata(1);
-
- if (name==p_name) {
-
- return p_item;
- }
-
- TreeItem *c=p_item->get_children();
-
- while (c) {
-
- TreeItem *found = find_item(c,p_name);
- if (found)
- return found;
- c=c->get_next();
- }
-
- return NULL;
-}
-
-
-void PropertyEditor::_changed_callback(Object *p_changed,const char * p_prop) {
-
-
- _changed_callbacks(p_changed,p_prop);
-}
-
-void PropertyEditor::_changed_callbacks(Object *p_changed,const String& p_prop) {
-
-
- if (p_changed!=obj)
- return;
-
- if (changing)
- return;
-
- if (p_prop==String())
- update_tree_pending=true;
- else {
-
- pending[p_prop]=p_prop;
-
- }
-}
-
-void PropertyEditor::update_property(const String& p_prop) {
-
- if (obj)
- _changed_callbacks(obj,p_prop);
-}
-
-
-void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p_name, int p_hint, const String& p_hint_text) {
-
- switch( p_type ) {
-
- case Variant::BOOL: {
-
- p_item->set_checked( 1, obj->get( p_name ) );
- } break;
- case Variant::REAL:
- case Variant::INT: {
-
- if (p_hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || p_hint==PROPERTY_HINT_LAYERS_2D_RENDER || p_hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || p_hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
- tree->update();
- break;
- }
-
- if (p_hint==PROPERTY_HINT_FLAGS) {
- Vector<String> values = p_hint_text.split(",");
- String flags;
- int val = obj->get(p_name);
- for(int i=0;i<values.size();i++) {
-
- String v = values[i];
- if (v=="")
- continue;
- if (!(val&(1<<i)))
- continue;
-
- if (flags!="")
- flags+=", ";
- flags+=v;
- }
- p_item->set_text(1, flags );
- break;
- }
-
- if (p_hint==PROPERTY_HINT_EXP_EASING) {
-
- p_item->set_text(1, String::num(obj->get( p_name ),2) );
- break;
- }
-
-
- //p_item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
-
- if (p_type==Variant::REAL) {
- p_item->set_range(1, obj->get( p_name ) );
-
- } else {
- p_item->set_range(1, obj->get( p_name ) );
- }
-
-
- p_item->set_editable(1,!read_only);
-
-
- } break;
- case Variant::STRING:
-
-
- if (p_hint==PROPERTY_HINT_TYPE_STRING) {
-
- p_item->set_text(1,obj->get(p_name));
- }
-
- if ( p_hint==PROPERTY_HINT_METHOD_OF_VARIANT_TYPE ||
- p_hint==PROPERTY_HINT_METHOD_OF_BASE_TYPE ||
- p_hint==PROPERTY_HINT_METHOD_OF_INSTANCE ||
- p_hint==PROPERTY_HINT_METHOD_OF_SCRIPT ||
- p_hint==PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE ||
- p_hint==PROPERTY_HINT_PROPERTY_OF_BASE_TYPE ||
- p_hint==PROPERTY_HINT_PROPERTY_OF_INSTANCE ||
- p_hint==PROPERTY_HINT_PROPERTY_OF_SCRIPT ) {
-
- p_item->set_text(1,obj->get(p_name));
- }
-
-
- if (p_hint==PROPERTY_HINT_ENUM) {
-
- Vector<String> strings = p_hint_text.split(",");
- String current = obj->get(p_name);
- int idx=0;
- for(int x=0;x<strings.size();x++) {
- if (strings[x]==current) {
- idx=x;
- break;
- }
- }
- p_item->set_text(1, p_hint_text);
- p_item->set_range(1,idx);
- break;
- }
-
- case Variant::VECTOR3:
- case Variant::QUAT:
- case Variant::VECTOR2:
- case Variant::RECT3:
- case Variant::RECT2:
- case Variant::TRANSFORM2D:
- case Variant::BASIS:
- case Variant::TRANSFORM: {
-
- p_item->set_text(1,obj->get(p_name));
-
- } break;
- case Variant::COLOR: {
-
- tree->update();
- //p_item->set_text(1,obj->get(p_name));
-
- } break;
- case Variant::IMAGE: {
-
- Image img = obj->get( p_name );
- 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())+"-"+String(Image::get_format_name(img.get_format()))+"]");
-
- } break;
- case Variant::NODE_PATH: {
-
- p_item->set_text(1,obj->get(p_name));
- } break;
- case Variant::OBJECT: {
-
-
- if (obj->get( p_name ).get_type() == Variant::NIL || obj->get( p_name ).operator RefPtr().is_null()) {
- p_item->set_text(1,"<null>");
- p_item->set_icon(1,Ref<Texture>());
-
- Dictionary d = p_item->get_metadata(0);
- int hint=d.has("hint")?d["hint"].operator int():-1;
- String hint_text=d.has("hint_text")?d["hint_text"]:"";
- if (hint==PROPERTY_HINT_RESOURCE_TYPE && hint_text == "Texture") {
- p_item->set_icon(1,NULL);
- }
-
- } else {
- RES res = obj->get( p_name ).operator RefPtr();
- if (res->is_class("Texture")) {
- int tw = EditorSettings::get_singleton()->get("docks/property_editor/texture_preview_width");
- p_item->set_icon_max_width(1,tw);
- p_item->set_icon(1,res);
- p_item->set_text(1,"");
-
- } else if (res->get_name() != "") {
-
- p_item->set_text(1, res->get_name());
- } else if (res->get_path()!="" && !res->get_path().begins_with("local://")) {
- p_item->set_text(1, res->get_path().get_file());
- } else {
- p_item->set_text(1,"<"+res->get_class()+">");
- };
-
-
- if (res.is_valid() && res->get_path().is_resource_file()) {
- p_item->set_tooltip(1,res->get_path());
- } else if (res.is_valid()) {
- p_item->set_tooltip(1,res->get_name()+" ("+res->get_class()+")");
- }
-
-
- if (has_icon(res->get_class(),"EditorIcons")) {
-
- p_item->set_icon(0,get_icon(res->get_class(),"EditorIcons"));
- } else {
-
- Dictionary d = p_item->get_metadata(0);
- int hint=d.has("hint")?d["hint"].operator int():-1;
- String hint_text=d.has("hint_text")?d["hint_text"]:"";
- if (hint==PROPERTY_HINT_RESOURCE_TYPE) {
-
- if (has_icon(hint_text,"EditorIcons")) {
-
- p_item->set_icon(0,get_icon(hint_text,"EditorIcons"));
-
- } else {
- p_item->set_icon(0,get_icon("Object","EditorIcons"));
-
- }
- }
- }
-
- if (!res->is_class("Texture")) {
- //texture already previews via itself
- EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res,this,"_resource_preview_done",p_item->get_instance_ID());
- }
-
-
-
- }
-
-
- } break;
- default: {};
- }
-
-}
-
-
-void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
-
- bool has_reload=false;
- int found=-1;
- bool is_disabled=false;
-
- for(int i=0;i<item->get_button_count(1);i++) {
-
- if (item->get_button_id(1,i)==3) {
- found=i;
- is_disabled=item->is_button_disabled(1,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 && !is_disabled)!=changed) {
-
- if (changed) {
-
- has_reload=true;
- } else {
-
- }
-
- //}
-
- }
-
- }
-
- if (obj->call("property_can_revert",p_name).operator bool()) {
-
- 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)) {
- has_reload=true;
- }
- }
- }
-
- //print_line("found: "+itos(found)+" has reload: "+itos(has_reload)+" is_disabled "+itos(is_disabled));
- if (found!=-1 && !has_reload) {
-
- if (!is_disabled) {
- item->erase_button(1,found);
- if (item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) {
- item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true);
- }
- }
- } else if (found==-1 && has_reload) {
- item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
- } else if (found!=-1 && has_reload && is_disabled) {
- item->erase_button(1,found);
- item->add_button(1,get_icon("ReloadSmall","EditorIcons"),3);
- }
-}
-
-
-
-bool PropertyEditor::_is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const {
-
- Dictionary d = p_item_data;
-
- if (d.has("type")) {
-
- int type = d["type"];
- if (type==Variant::OBJECT && d.has("hint") && d.has("hint_text") && int(d["hint"])==PROPERTY_HINT_RESOURCE_TYPE) {
-
-
- String allowed_type=d["hint_text"];
-
- Dictionary drag_data = p_drag_data;
- if (drag_data.has("type") && String(drag_data["type"])=="resource") {
- Ref<Resource> res = drag_data["resource"];
- for(int i=0;i<allowed_type.get_slice_count(",");i++) {
- String at = allowed_type.get_slice(",",i).strip_edges();
- if (res.is_valid() && ClassDB::is_parent_class(res->get_class(),at)) {
- return true;
- }
- }
-
- }
-
- if (drag_data.has("type") && String(drag_data["type"])=="files") {
-
- Vector<String> files = drag_data["files"];
-
- if (files.size()==1) {
- String file = files[0];
- String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
- if (ftype!="") {
-
- for(int i=0;i<allowed_type.get_slice_count(",");i++) {
- String at = allowed_type.get_slice(",",i).strip_edges();
- if (ClassDB::is_parent_class(ftype,at)) {
- return true;
- }
- }
- }
- }
- }
- }
- }
-
-
- return false;
-
-}
-void PropertyEditor::_mark_drop_fields(TreeItem* p_at) {
-
- if (_is_drop_valid(get_viewport()->gui_get_drag_data(),p_at->get_metadata(0)))
- p_at->set_custom_bg_color(1,Color(0.7,0.5,0.2),true);
-
- if (p_at->get_children()) {
- _mark_drop_fields(p_at->get_children());
- }
-
- if (p_at->get_next()) {
- _mark_drop_fields(p_at->get_next());
- }
-}
-
-Variant PropertyEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
-
- TreeItem *item = tree->get_item_at_pos(p_point);
- if (!item)
- return Variant();
-
- Dictionary d = item->get_metadata(0);
- if (!d.has("name"))
- return Variant();
-
- int col = tree->get_column_at_pos(p_point);
- if (col==0) {
-
- Dictionary dp;
- dp["type"]="obj_property";
- dp["object"]=obj;
- dp["property"]=d["name"];
- dp["value"]=obj->get(d["name"]);
-
- Label *label =memnew( Label );
- label->set_text(d["name"]);
- set_drag_preview(label);
- return dp;
- }
-
-
-
- Variant val = obj->get(d["name"]);
-
- if (val.get_type()==Variant::OBJECT) {
- RES res = val;
- if (res.is_valid()) {
-
- custom_editor->hide_menu();
- return EditorNode::get_singleton()->drag_resource(res,p_from);
- }
- }
-
- return Variant();
-}
-
-bool PropertyEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
-
- TreeItem *item = tree->get_item_at_pos(p_point);
- if (!item)
- return false;
-
- int col = tree->get_column_at_pos(p_point);
- if (col!=1)
- return false;
-
- return _is_drop_valid(p_data,item->get_metadata(0));
-
-}
-void PropertyEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
-
- TreeItem *item = tree->get_item_at_pos(p_point);
- if (!item)
- return;
-
- int col = tree->get_column_at_pos(p_point);
- if (col!=1)
- return;
-
- if (!_is_drop_valid(p_data,item->get_metadata(0)))
- return;
-
- Dictionary d = item->get_metadata(0);
-
- if (!d.has("name"))
- return;
-
- String name=d["name"];
-
- Dictionary drag_data = p_data;
- if (drag_data.has("type") && String(drag_data["type"])=="resource") {
- Ref<Resource> res = drag_data["resource"];
- if (res.is_valid()) {
- _edit_set(name,res);
- return;
- }
- }
-
- if (drag_data.has("type") && String(drag_data["type"])=="files") {
-
- Vector<String> files = drag_data["files"];
-
- if (files.size()==1) {
- String file = files[0];
- RES res = ResourceLoader::load(file);
- if (res.is_valid()) {
- _edit_set(name,res);
- return;
- }
- }
- }
-}
-
-
-void PropertyEditor::_clear_drop_fields(TreeItem* p_at) {
-
- Dictionary d = p_at->get_metadata(0);
-
- if (d.has("type")) {
-
- int type = d["type"];
- if (type==Variant::OBJECT) {
- p_at->clear_custom_bg_color(1);
- }
-
- }
-
- if (p_at->get_children()) {
- _clear_drop_fields(p_at->get_children());
- }
-
- if (p_at->get_next()) {
- _clear_drop_fields(p_at->get_next());
- }
-}
-
-void PropertyEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- get_tree()->connect("node_removed",this,"_node_removed");
- }
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
- get_tree()->disconnect("node_removed",this,"_node_removed");
- edit(NULL);
- }
-
-
- if (p_what==NOTIFICATION_DRAG_BEGIN) {
-
- if (is_visible_in_tree() && tree->get_root()) {
- _mark_drop_fields(tree->get_root());
- }
- }
-
- if (p_what==NOTIFICATION_DRAG_END) {
- if (is_visible_in_tree() && tree->get_root()) {
- _clear_drop_fields(tree->get_root());
- }
-
- }
-
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
-
-
- if (refresh_countdown>0) {
- refresh_countdown-=get_fixed_process_delta_time();
- if (refresh_countdown<=0) {
- TreeItem *root = tree->get_root();
- _refresh_item(root);
- }
- }
-
- changing=true;
-
- if (update_tree_pending) {
-
- update_tree();
- update_tree_pending=false;
-
- } else {
-
- const String *k=NULL;
- while ((k=pending.next(k))) {
-
- TreeItem * item = find_item(tree->get_root(),*k);
- if (!item)
- continue;
-
- _check_reload_status(*k,item);
-
- Dictionary d=item->get_metadata(0);
- set_item_text(item,d["type"],d["name"],d["hint"],d["hint_text"]);
- }
- }
-
- pending.clear();
-
- changing=false;
-
- }
-}
-
-TreeItem *PropertyEditor::get_parent_node(String p_path,HashMap<String,TreeItem*>& item_paths,TreeItem *root) {
-
- TreeItem *item=NULL;
-
- if (p_path=="") {
-
- item = root;
- } else if (item_paths.has(p_path)) {
-
- item = item_paths.get(p_path);
- } else {
-
- //printf("path %s parent path %s - item name %s\n",p_path.ascii().get_data(),p_path.left( p_path.find_last("/") ).ascii().get_data(),p_path.right( p_path.find_last("/") ).ascii().get_data() );
- TreeItem *parent = get_parent_node( p_path.left( p_path.find_last("/") ),item_paths,root );
- item = tree->create_item( parent );
-
- String name = (p_path.find("/")!=-1)?p_path.right( p_path.find_last("/")+1 ):p_path;
- if (capitalize_paths)
- item->set_text(0, name.capitalize() );
- else
- item->set_text(0, name );
- item->set_tooltip(0, p_path);
- if (item->get_parent()!=root) {
- item->set_icon( 0, get_icon("Folder","EditorIcons"));
- }
-
- item->set_editable(0,false);
- item->set_selectable(0,subsection_selectable);
- item->set_editable(1,false);
- item->set_selectable(1,subsection_selectable);
-
- if (item->get_parent()==root) {
-
- item->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
- item->set_custom_bg_color(1,get_color("prop_subsection","Editor"));
- }
-
- item_paths[p_path]=item;
- }
-
- return item;
-
-}
-
-
-void PropertyEditor::_refresh_item(TreeItem *p_item) {
-
- if (!p_item)
- return;
-
- String name = p_item->get_metadata(1);
-
- 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);
-
-
- bool changed = _is_property_different(v,vorig,usage);
-
- if ((found!=-1)!=changed) {
-
- if (changed) {
-
- has_reload=true;
-
- } else {
-
- //p_item->erase_button(1,found);
- }
-
- }
-
- }
-
- }
-
- 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("ReloadSmall","EditorIcons"),3);
- }
-#endif
- Dictionary d=p_item->get_metadata(0);
- set_item_text(p_item,d["type"],d["name"],d["hint"],d["hint_text"]);
- }
-
- TreeItem *c=p_item->get_children();
-
- while (c) {
-
- _refresh_item(c);
-
- c=c->get_next();
- }
-
-}
-
-void PropertyEditor::refresh() {
-
- if (refresh_countdown>0)
- return;
- refresh_countdown=EditorSettings::get_singleton()->get("docks/property_editor/auto_refresh_interval");
-
-}
-
-void PropertyEditor::update_tree() {
-
-
- tree->clear();
-
- if (!obj)
- return;
-
- HashMap<String,TreeItem*> item_path;
-
- TreeItem *root = tree->create_item(NULL);
- tree->set_hide_root(true);
-
- /*
- TreeItem *title = tree->create_item(root);
-
- title->set_custom_bg_color(0,get_color("prop_section","Editor"));
- title->set_text(0,"Property"); // todo, fetch name if ID exists in database
- title->set_editable(0,false);
- title->set_selectable(0,false);
- title->set_custom_bg_color(1,get_color("prop_section","Editor"));
- title->set_text(1,"Value"); // todo, fetch name if ID exists in database
- title->set_editable(1,false);
- title->set_selectable(1,false);
-*/
-
- /*
- if (obj->cast_to<Node>() || obj->cast_to<Resource>()) {
- TreeItem *type = tree->create_item(root);
-
- type->set_text(0,"Type"); // todo, fetch name if ID exists in database
- type->set_text(1,obj->get_type()); // todo, fetch name if ID exists in database
- if (has_icon(obj->get_type(),"EditorIcons"))
- type->set_icon(1,get_icon(obj->get_type(),"EditorIcons") );
- else
- type->set_icon(1,get_icon("Object","EditorIcons") );
-
- type->set_selectable(0,false);
- type->set_selectable(1,false);
-
-
- TreeItem *name = tree->create_item(root);
-
- name->set_text(0,"Name"); // todo, fetch name if ID exists in database
- if (obj->is_type("Resource"))
- name->set_text(1,obj->cast_to<Resource>()->get_name());
- else if (obj->is_type("Node"))
- name->set_text(1,obj->cast_to<Node>()->get_name());
- name->set_selectable(0,false);
- name->set_selectable(1,false);
- }
-*/
- List<PropertyInfo> plist;
- obj->get_property_list(&plist,true);
-
- bool draw_red=false;
-
- {
- Node *nod = obj->cast_to<Node>();
- Node *es = EditorNode::get_singleton()->get_edited_scene();
- if (nod && es!=nod && nod->get_owner()!=es) {
- draw_red=true;
- }
- }
-
-
- Color sscolor=get_color("prop_subsection","Editor");
-
- TreeItem * current_category=NULL;
-
- String filter = search_box ? search_box->get_text() : "";
- String group;
- String group_base;
-
- for (List<PropertyInfo>::Element *I=plist.front() ; I ; I=I->next()) {
-
- PropertyInfo& p = I->get();
-
- //make sure the property can be edited
-
- if (p.usage&PROPERTY_USAGE_GROUP) {
-
- group=p.name;
- group_base=p.hint_string;
-
- continue;
-
- } else if (p.usage&PROPERTY_USAGE_CATEGORY) {
-
- group="";
- group_base="";
-
- if (!show_categories)
- continue;
-
- List<PropertyInfo>::Element *N=I->next();
- bool valid=true;
- //if no properties in category, skip
- while(N) {
- if (N->get().usage&PROPERTY_USAGE_EDITOR)
- break;
- if (N->get().usage&PROPERTY_USAGE_CATEGORY) {
- valid=false;
- break;
- }
- N=N->next();
- }
- if (!valid)
- continue; //empty, ignore
- TreeItem * sep = tree->create_item(root);
- current_category=sep;
- String type=p.name;
- /*if (has_icon(type,"EditorIcons"))
- sep->set_icon(0,get_icon(type,"EditorIcons") );
- else
- sep->set_icon(0,get_icon("Object","EditorIcons") );
- print_line("CATEGORY: "+type);
- */
- sep->set_text(0,type);
- sep->set_selectable(0,false);
- sep->set_selectable(1,false);
- sep->set_custom_bg_color(0,get_color("prop_category","Editor"));
- sep->set_custom_bg_color(1,get_color("prop_category","Editor"));
-
- if (use_doc_hints) {
- StringName type=p.name;
- if (!class_descr_cache.has(type)) {
-
- String descr;
- DocData *dd=EditorHelp::get_doc_data();
- Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
- if (E) {
- descr=E->get().brief_description;
- }
- class_descr_cache[type]=descr.word_wrap(80);
-
- }
-
- sep->set_tooltip(0,TTR("Class:")+" "+p.name+":\n\n"+class_descr_cache[type]);
- }
- //sep->set_custom_color(0,Color(1,1,1));
-
-
- continue;
- } else if ( ! (p.usage&PROPERTY_USAGE_EDITOR ) )
- continue;
-
-
- if (hide_script && p.name=="script/script")
- continue;
-
- String basename=p.name;
- if (group!="") {
- if (group_base!="") {
- if (basename.begins_with(group_base)) {
- basename=basename.replace_first(group_base,"");
- } else {
- group=""; //no longer using group base, clear
- }
- }
- }
-
- if (group!="") {
- basename=group+"/"+basename;
- }
-
- String name = (basename.find("/")!=-1)?basename.right( basename.find_last("/")+1 ):basename;
-
- if (capitalize_paths)
- name = name.camelcase_to_underscore().capitalize();
-
- String path=basename.left( basename.find_last("/") ) ;
-
- if (use_filter && filter!="") {
-
- String cat = path;
-
- if (capitalize_paths)
- cat = cat.capitalize();
-
- if (!filter.is_subsequence_ofi(cat) && !filter.is_subsequence_ofi(name))
- continue;
- }
-
- //printf("property %s\n",basename.ascii().get_data());
- TreeItem * parent = get_parent_node(path,item_path,current_category?current_category:root );
- /*
- if (parent->get_parent()==root)
- parent=root;
- */
- int level = 0;
- if (parent!=root) {
- level++;
- TreeItem *parent_lev=parent;
- while(parent_lev->get_parent()!=root) {
- parent_lev=parent_lev->get_parent();
- level++;
- }
- }
- if (level>4)
- level=4;
-
- Color col = sscolor;
- col.a=(level/4.0)*0.7;
-
- TreeItem * item = tree->create_item( parent );
-
- if (level>0) {
- item->set_custom_bg_color(0,col);
- //item->set_custom_bg_color(1,col);
- }
- item->set_editable(0,false);
- item->set_selectable(0,false);
-
- if (p.usage&PROPERTY_USAGE_CHECKABLE) {
-
- item->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
- item->set_selectable(0,true);
- item->set_editable(0,true);
- item->set_checked(0,p.usage&PROPERTY_USAGE_CHECKED);
- }
-
- item->set_text(0, name);
- item->set_tooltip(0, p.name);
-
- if (use_doc_hints) {
- StringName setter;
- StringName type;
- if (ClassDB::get_setter_and_type_for_property(obj->get_class_name(),p.name,type,setter)) {
-
- String descr;
- bool found=false;
- Map<StringName,Map<StringName,String> >::Element *E=descr_cache.find(type);
- if (E) {
-
- Map<StringName,String>::Element *F=E->get().find(setter);
- if (F) {
- found=true;
- descr=F->get();
- }
- }
- if (!found) {
-
- DocData *dd=EditorHelp::get_doc_data();
- Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
- if (E) {
- for(int i=0;i<E->get().methods.size();i++) {
- if (E->get().methods[i].name==setter.operator String()) {
- descr=E->get().methods[i].description.strip_edges().word_wrap(80);
- }
- }
- }
-
- descr_cache[type][setter]=descr;
- }
-
- item->set_tooltip(0, TTR("Property:")+" "+p.name+"\n\n"+descr);
- }
- }
- //EditorHelp::get_doc_data();
-
- Dictionary d;
- d["name"]=p.name;
- d["type"]=(int)p.type;
- d["hint"]=(int)p.hint;
- d["hint_text"]=p.hint_string;
- d["usage"]=(int)p.usage;
-
- item->set_metadata( 0, d );
- item->set_metadata( 1, p.name );
-
- if (draw_red)
- item->set_custom_color(0,Color(0.8,0.4,0.20));
-
-
- if (p.name==selected_property) {
-
- item->select(1);
- }
-
-
- //printf("property %s type %i\n",p.name.ascii().get_data(),p.type);
- switch( p.type ) {
-
- case Variant::BOOL: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CHECK );
- item->set_text(1,TTR("On"));
- item->set_tooltip(1, obj->get(p.name) ? "True" : "False");
- item->set_checked( 1, obj->get( p.name ) );
- if (show_type_icons)
- item->set_icon( 0, get_icon("Bool","EditorIcons") );
- item->set_editable(1,!read_only);
-
- } break;
- case Variant::REAL:
- case Variant::INT: {
-
- if (p.hint==PROPERTY_HINT_EXP_EASING) {
-
- 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);
- if (show_type_icons)
- item->set_icon( 0, get_icon("Curve","EditorIcons"));
-
- break;
-
- }
-
- if (p.hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || p.hint==PROPERTY_HINT_LAYERS_2D_RENDER || p.hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || p.hint==PROPERTY_HINT_LAYERS_3D_RENDER) {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable(1,!read_only);
- item->set_custom_draw(1,this,"_draw_flags");
- break;
- }
-
- if (p.hint==PROPERTY_HINT_FLAGS) {
-
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable(1,!read_only);
- //item->set_icon( 0, get_icon("Curve","EditorIcons"));
-
- Vector<String> values = p.hint_string.split(",");
- String flags;
- int val = obj->get(p.name);
- for(int i=0;i<values.size();i++) {
-
- String v = values[i];
- if (v=="")
- continue;
- if (!(val&(1<<i)))
- continue;
-
- if (flags!="")
- flags+=", ";
- flags+=v;
- }
- item->set_text(1, flags );
- break;
-
- }
-
- if (p.hint==PROPERTY_HINT_ENUM)
- item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
- else
- item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE_EXPRESSION );
-
-
- if (p.hint==PROPERTY_HINT_SPRITE_FRAME || p.hint==PROPERTY_HINT_RANGE || p.hint==PROPERTY_HINT_EXP_RANGE) {
-
- int c = p.hint_string.get_slice_count(",");
- float min=0,max=100,step=1;
- if (c>=1) {
-
- min=p.hint_string.get_slice(",",0).to_double();
- }
- if (c>=2) {
-
- max=p.hint_string.get_slice(",",1).to_double();
- }
-
- if (p.hint!=PROPERTY_HINT_SPRITE_FRAME && c>=3) {
-
- step= p.hint_string.get_slice(",",2).to_double();
- }
-
-
- item->set_range_config(1,min,max,step,p.hint==PROPERTY_HINT_EXP_RANGE);
- } else if (p.hint==PROPERTY_HINT_ENUM) {
-
- //int c = p.hint_string.get_slice_count(",");
- item->set_text(1,p.hint_string);
- 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;
- } else if (p.hint==PROPERTY_HINT_OBJECT_ID) {
-
- //int c = p.hint_string.get_slice_count(",");
- item->set_cell_mode(1,TreeItem::CELL_MODE_CUSTOM);
-
- String type=p.hint_string;
- if (type=="")
- type="Object";
-
- ObjectID id = obj->get( p.name );
- if (id!=0) {
- item->set_text(1,type+" ID: "+itos(id));
- item->add_button(1,get_icon("EditResource","EditorIcons"));
- } else {
- item->set_text(1,"[Empty]");
- }
-
- if (has_icon(p.hint_string,"EditorIcons")) {
- type=p.hint_string;
- } else {
- type="Object";
- }
-
- item->set_icon(0,get_icon(type,"EditorIcons"));
-
- break;
-
- } else {
- if (p.type == Variant::REAL) {
-
- item->set_range_config(1, -16777216, 16777216, 0.001);
- } else {
-
- item->set_range_config(1, -2147483647, 2147483647, 1);
- }
- };
-
- if (p.type==Variant::REAL) {
- if (show_type_icons)
- item->set_icon( 0, get_icon("Real","EditorIcons"));
- item->set_range(1, obj->get( p.name ) );
-
- } else {
- if (show_type_icons)
- item->set_icon( 0,get_icon("Integer","EditorIcons") );
- item->set_range(1, obj->get( p.name ) );
- }
-
-
- item->set_editable(1,!read_only);
-
-
- } break;
- case Variant::STRING: {
-
- switch (p.hint) {
-
- case PROPERTY_HINT_DIR:
- case PROPERTY_HINT_FILE:
- case PROPERTY_HINT_GLOBAL_DIR:
- case PROPERTY_HINT_GLOBAL_FILE: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_STRING );
- item->set_editable(1,!read_only);
- 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"));
-
- } break;
- case PROPERTY_HINT_ENUM: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
- Vector<String> strings = p.hint_string.split(",");
- String current = obj->get(p.name);
- int idx=0;
- for(int x=0;x<strings.size();x++) {
- if (strings[x]==current) {
- idx=x;
- break;
- }
- }
- item->set_text(1, p.hint_string);
- item->set_range(1,idx);
- item->set_editable( 1, !read_only );
- if (show_type_icons)
- item->set_icon( 0,get_icon("Enum","EditorIcons") );
-
-
- } break;
- case PROPERTY_HINT_METHOD_OF_VARIANT_TYPE: ///< a property of a type
- case PROPERTY_HINT_METHOD_OF_BASE_TYPE: ///< a method of a base type
- case PROPERTY_HINT_METHOD_OF_INSTANCE: ///< a method of an instance
- case PROPERTY_HINT_METHOD_OF_SCRIPT: ///< a method of a script & base
- case PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE: ///< a property of a type
- case PROPERTY_HINT_PROPERTY_OF_BASE_TYPE: ///< a property of a base type
- case PROPERTY_HINT_PROPERTY_OF_INSTANCE: ///< a property of an instance
- case PROPERTY_HINT_PROPERTY_OF_SCRIPT: ///< a property of a script & base
- case PROPERTY_HINT_TYPE_STRING: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM);
- item->set_editable(1,!read_only);
- if (show_type_icons)
- item->set_icon( 0, get_icon("String","EditorIcons") );
- item->set_text(1,obj->get(p.name));
-
- } break;
-
- default: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_STRING );
- item->set_editable(1,!read_only);
- 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") );
-
- } break;
- }
-
- } break;
- case Variant::ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
-
- Variant v = obj->get(p.name);
- String type_name = "Array";
- String type_name_suffix = "";
-
- String hint = p.hint_string;
- while(hint.begins_with(itos(Variant::ARRAY)+":")) {
- type_name += "<Array";
- type_name_suffix += ">";
- hint = hint.substr(2, hint.size()-2);
- }
- if(hint.find(":") >= 0) {
- hint = hint.substr(0,hint.find(":"));
- if(hint.find("/") >= 0) {
- hint = hint.substr(0,hint.find("/"));
- }
- type_name += "<" + Variant::get_type_name(Variant::Type(hint.to_int()));
- type_name_suffix += ">";
- }
- type_name += type_name_suffix;
-
- if (v.is_array())
- item->set_text(1,type_name+"["+itos(v.call("size"))+"]");
- else
- item->set_text(1,type_name+"[]");
-
- if (show_type_icons)
- item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
-
-
- } break;
-
- case Variant::POOL_INT_ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
- Variant v = obj->get(p.name);
- if (v.is_array())
- item->set_text(1,"IntArray["+itos(v.call("size"))+"]");
- else
- item->set_text(1,"IntArray[]");
- if (show_type_icons)
- item->set_icon( 0, get_icon("ArrayInt","EditorIcons") );
-
-
- } break;
- case Variant::POOL_REAL_ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
- Variant v = obj->get(p.name);
- if (v.is_array())
- item->set_text(1,"FloatArray["+itos(v.call("size"))+"]");
- else
- item->set_text(1,"FloatArray[]");
- if (show_type_icons)
- item->set_icon( 0, get_icon("ArrayReal","EditorIcons") );
-
-
- } break;
- case Variant::POOL_STRING_ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
- Variant v = obj->get(p.name);
- if (v.is_array())
- item->set_text(1,"String["+itos(v.call("size"))+"]");
- else
- item->set_text(1,"String[]");
- if (show_type_icons)
- item->set_icon( 0, get_icon("ArrayString","EditorIcons") );
-
-
- } break;
- case Variant::POOL_BYTE_ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
- Variant v = obj->get(p.name);
- if (v.is_array())
- item->set_text(1,"Byte["+itos(v.call("size"))+"]");
- else
- item->set_text(1,"Byte[]");
- if (show_type_icons)
- item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
-
-
- } break;
- case Variant::POOL_VECTOR2_ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
- Variant v = obj->get(p.name);
- if (v.is_array())
- item->set_text(1,"Vector2["+itos(v.call("size"))+"]");
- else
- item->set_text(1,"Vector2[]");
- if (show_type_icons)
- item->set_icon( 0, get_icon("Vector2","EditorIcons") );
-
-
- } break;
- case Variant::POOL_VECTOR3_ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
- Variant v = obj->get(p.name);
- if (v.is_array())
- item->set_text(1,"Vector3["+itos(v.call("size"))+"]");
- else
- item->set_text(1,"Vector3[]");
- if (show_type_icons)
- item->set_icon( 0, get_icon("Vector","EditorIcons") );
-
-
- } break;
- case Variant::POOL_COLOR_ARRAY: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
-
- Variant v = obj->get(p.name);
- if (v.is_array())
- item->set_text(1,"Color["+itos(v.call("size"))+"]");
- else
- item->set_text(1,"Color[]");
- if (show_type_icons)
- item->set_icon( 0, get_icon("Color","EditorIcons") );
-
-
- } break;
- case Variant::VECTOR2: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1,obj->get(p.name));
- if (show_type_icons)
- item->set_icon( 0,get_icon("Vector2","EditorIcons") );
-
- } break;
- case Variant::RECT2: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1,obj->get(p.name));
- if (show_type_icons)
- item->set_icon( 0,get_icon("Rect2","EditorIcons") );
-
- } break;
- case Variant::VECTOR3: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1,obj->get(p.name));
- if (show_type_icons)
- item->set_icon( 0,get_icon("Vector","EditorIcons") );
-
- } break;
- case Variant::TRANSFORM2D:
- case Variant::BASIS: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1, obj->get(p.name));
- } break;
- case Variant::TRANSFORM: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1,obj->get(p.name));
- if (show_type_icons)
- item->set_icon( 0,get_icon("Matrix","EditorIcons") );
-
- } break;
- case Variant::PLANE: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1,obj->get(p.name));
- if (show_type_icons)
- item->set_icon( 0,get_icon("Plane","EditorIcons") );
-
- } break;
- case Variant::RECT3: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1,"Rect3");
- if (show_type_icons)
- item->set_icon( 0,get_icon("Rect3","EditorIcons") );
- } break;
-
- case Variant::QUAT: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, true );
- item->set_text(1,obj->get(p.name));
- if (show_type_icons)
- item->set_icon( 0,get_icon("Quat","EditorIcons") );
-
- } break;
- case Variant::COLOR: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, !read_only );
- //item->set_text(1,obj->get(p.name));
- item->set_custom_draw(1,this,"_draw_transparency");
- if (show_type_icons)
- item->set_icon( 0,get_icon("Color","EditorIcons") );
-
- } break;
- case Variant::IMAGE: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, !read_only );
- Image img = obj->get( p.name );
- if (img.empty())
- item->set_text(1,"[Image (empty)]");
- else
- 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: {
-
- item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
- item->set_editable( 1, !read_only );
- item->set_text(1,obj->get(p.name));
- item->add_button(1, get_icon("CopyNodePath", "EditorIcons"));
-
- } break;
- case Variant::OBJECT: {
-
- item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
- item->set_editable( 1, !read_only );
- item->add_button(1,get_icon("EditResource","EditorIcons"));
- String type;
- if (p.hint==PROPERTY_HINT_RESOURCE_TYPE)
- type=p.hint_string;
-
- if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) {
- item->set_text(1,"<null>");
- item->set_icon(1,Ref<Texture>());
-
- } else {
- RES res = obj->get( p.name ).operator RefPtr();
-
- if (res->is_class("Texture")) {
- int tw = EditorSettings::get_singleton()->get("docks/property_editor/texture_preview_width");
- item->set_icon_max_width(1,tw);
- item->set_icon(1,res);
- item->set_text(1,"");
-
- } else if (res->get_name() != "") {
-
- item->set_text(1, res->get_name());
- } else if (res->get_path()!="" && !res->get_path().begins_with("local://")) {
- item->set_text(1, res->get_path().get_file());
-
- } else {
- item->set_text(1,"<"+res->get_class()+">");
- }
-
- if (has_icon(res->get_class(),"EditorIcons")) {
- type=res->get_class();
- }
-
- if (res.is_valid() && res->get_path().is_resource_file()) {
- item->set_tooltip(1,res->get_path());
- } else if (res.is_valid()) {
- item->set_tooltip(1,res->get_name()+" ("+res->get_class()+")");
- }
- if (!res->is_class("Texture")) {
- //texture already previews via itself
- EditorResourcePreview::get_singleton()->queue_edited_resource_preview(res,this,"_resource_preview_done",item->get_instance_ID());
- }
-
- }
-
-
- if (type!=String()) {
- if (type.find(",")!=-1)
- type=type.get_slice(",",0);
- //printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data());
- if (has_icon(type,"EditorIcons"))
- item->set_icon( 0, get_icon(type,"EditorIcons") );
- else
- item->set_icon( 0, get_icon("Object","EditorIcons") );
- }
-
- //item->double_click_signal.connect( Method1<int>( Method2<int,String>( this, &Editoritem_obj_edited ), p.name ) );
-
- } break;
- default: {};
- }
-
- if (keying) {
-
- if (p.hint==PROPERTY_HINT_SPRITE_FRAME) {
-
- item->add_button(1,get_icon("KeyNext","EditorIcons"),5);
- } else {
- item->add_button(1,get_icon("Key","EditorIcons"),2);
- }
- }
-
- bool has_reload=false;
-
- bool mbi = _might_be_in_instance();
- if (mbi) {
-
- 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);
-
-
- 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("ReloadSmall","EditorIcons"),3);
- has_reload=true;
- }
- }
-
- }
-
- if (obj->call("property_can_revert",p.name).operator bool()) {
-
- item->add_button(1,get_icon("ReloadSmall","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("ReloadSmall","EditorIcons"),3);
- has_reload=true;
- }
- }
- }
-
- if (mbi && !has_reload && item->get_cell_mode(1)==TreeItem::CELL_MODE_RANGE && item->get_text(1)==String()) {
- item->add_button(1,get_icon("ReloadEmpty","EditorIcons"),3,true);
- }
-
-
-
- }
-}
-
-void PropertyEditor::_draw_transparency(Object *t, const Rect2& p_rect) {
-
- TreeItem *ti=t->cast_to<TreeItem>();
- if (!ti)
- return;
-
- Color color=obj->get(ti->get_metadata(1));
- Ref<Texture> arrow=tree->get_icon("select_arrow");
-
- // make a little space between consecutive color fields
- Rect2 area=p_rect;
- area.pos.y+=1;
- area.size.height-=2;
- area.size.width-=arrow->get_size().width+5;
- tree->draw_texture_rect(get_icon("Transparent", "EditorIcons"), area, true);
- tree->draw_rect(area, color);
-
-}
-
-
-void PropertyEditor::_item_selected() {
-
-
- TreeItem *item = tree->get_selected();
- ERR_FAIL_COND(!item);
- selected_property=item->get_metadata(1);
-
-}
-
-
-void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value, bool p_refresh_all) {
-
- if (autoclear) {
- TreeItem *item = tree->get_selected();
- if (item && item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK) {
-
- item->set_checked(0,true);
- }
- }
-
- if (!undo_redo || obj->cast_to<MultiNodeEdit>() || obj->cast_to<ArrayPropertyEdit>()) { //kind of hacky
-
- obj->set(p_name,p_value);
- if (p_refresh_all)
- _changed_callbacks(obj,"");
- else
- _changed_callbacks(obj,p_name);
-
- emit_signal(_prop_edited,p_name);
-
-
- } else {
-
- undo_redo->create_action(TTR("Set")+" "+p_name,UndoRedo::MERGE_ENDS);
- undo_redo->add_do_property(obj,p_name,p_value);
- undo_redo->add_undo_property(obj,p_name,obj->get(p_name));
-
- if (p_refresh_all) {
- undo_redo->add_do_method(this,"_changed_callback",obj,"");
- undo_redo->add_undo_method(this,"_changed_callback",obj,"");
- } else {
-
- undo_redo->add_do_method(this,"_changed_callback",obj,p_name);
- undo_redo->add_undo_method(this,"_changed_callback",obj,p_name);
- }
-
- Resource *r = obj->cast_to<Resource>();
- if (r) {
- if (!r->is_edited() && String(p_name)!="resource/edited") {
- undo_redo->add_do_method(r,"set_edited",true);
- undo_redo->add_undo_method(r,"set_edited",false);
- }
-
- if (String(p_name)=="resource_local_to_scene") {
- bool prev = obj->get(p_name);
- bool next = p_value;
- if (next) {
- undo_redo->add_do_method(this,"setup_local_to_scene");
- }
- if (prev) {
- undo_redo->add_undo_method(this,"setup_local_to_scene");
- }
- }
- }
- undo_redo->add_do_method(this,"emit_signal",_prop_edited,p_name);
- undo_redo->add_undo_method(this,"emit_signal",_prop_edited,p_name);
- undo_redo->commit_action();
- }
-}
-
-
-void PropertyEditor::_item_edited() {
-
-
- TreeItem * item = tree->get_edited();
- if (!item)
- return; //it all happened too fast..
-
- Dictionary d = item->get_metadata(0);
-
- String name=d["name"];
-
- if (tree->get_edited_column()==0) {
- //property checked
- if (autoclear) {
- if (!item->is_checked(0)) {
- obj->set(name,Variant());
- update_property(name);
- } else {
- Variant::CallError ce;
- obj->set(name,Variant::construct(Variant::Type(int(d["type"])),NULL,0,ce));
- }
- } else {
- emit_signal("property_toggled",name,item->is_checked(0));
- }
- return;
- }
-
- if (autoclear && item->get_cell_mode(0)==TreeItem::CELL_MODE_CHECK && item->get_cell_mode(1)!=TreeItem::CELL_MODE_CUSTOM) {
- item->set_checked(0,true);
-
- }
-
-
- int type=d["type"];
- int hint= d["hint"];
- int usage = d["usage"];
- bool refresh_all = usage&PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED;
-
- String hint_text=d["hint_text"];
- switch(type) {
-
- case Variant::NIL: {
-
- } break;
- case Variant::BOOL: {
-
- _edit_set(name,item->is_checked(1),refresh_all);
- item->set_tooltip(1, item->is_checked(1) ? "True" : "False");
- } break;
- case Variant::INT:
- case Variant::REAL: {
-
- if (hint==PROPERTY_HINT_LAYERS_2D_PHYSICS || hint==PROPERTY_HINT_LAYERS_2D_RENDER || hint==PROPERTY_HINT_LAYERS_3D_PHYSICS || hint==PROPERTY_HINT_LAYERS_3D_RENDER)
- break;
- if (hint==PROPERTY_HINT_EXP_EASING)
- break;
- if (hint==PROPERTY_HINT_FLAGS)
- break;
-
- if (type==Variant::INT)
- _edit_set(name,int(item->get_range(1)),refresh_all);
- else
- _edit_set(name,item->get_range(1),refresh_all);
- } break;
- case Variant::STRING: {
-
- if (hint==PROPERTY_HINT_ENUM) {
-
- int idx= item->get_range(1);
-
- Vector<String> strings = hint_text.split(",");
- String txt;
- if (idx>=0 && idx<strings.size()) {
-
- txt=strings[idx];
- }
-
- _edit_set(name,txt,refresh_all);
- } else {
- _edit_set(name,item->get_text(1),refresh_all);
- }
- } break;
- // math types
-
- case Variant::VECTOR3: {
-
- } break;
- case Variant::PLANE: {
-
- } break;
- case Variant::QUAT: {
-
- } break;
- case Variant::RECT3: {
-
- } break;
- case Variant::BASIS: {
-
- } break;
- case Variant::TRANSFORM: {
-
- } break;
-
- case Variant::COLOR: {
- //_edit_set(name,item->get_custom_bg_color(0));
- } break;
- case Variant::IMAGE: {
-
- } break;
- case Variant::NODE_PATH: {
- _edit_set(name, NodePath(item->get_text(1)),refresh_all);
-
- } break;
-
- case Variant::INPUT_EVENT: {
-
- } break;
- case Variant::DICTIONARY: {
-
- } break;
-
- // arrays
- case Variant::POOL_BYTE_ARRAY: {
-
- } break;
- case Variant::POOL_INT_ARRAY: {
-
- } break;
- case Variant::POOL_REAL_ARRAY: {
-
- } break;
- case Variant::POOL_STRING_ARRAY: {
-
- } break;
- case Variant::POOL_VECTOR3_ARRAY: {
-
- } break;
- case Variant::POOL_COLOR_ARRAY: {
-
- } break;
-
-
- };
-}
-
-
-void PropertyEditor::_resource_edit_request() {
-
- RES res=custom_editor->get_variant();
- if (res.is_null())
- return;
-
- String name=custom_editor->get_name();
-
-
- emit_signal("resource_selected",res.get_ref_ptr(),name);
-}
-
-void PropertyEditor::_custom_editor_edited() {
-
-
- if (!obj)
- return;
-
-
- _edit_set(custom_editor->get_name(), custom_editor->get_variant());
-}
-
-void PropertyEditor::_custom_editor_request(bool p_arrow) {
-
- TreeItem * item = tree->get_edited();
- ERR_FAIL_COND(!item);
- Dictionary d = item->get_metadata(0);
-
- //int type=d["type"];
- String name=d["name"];
- Variant::Type type=Variant::NIL;
- if (d.has("type"))
- type=(Variant::Type)((int)(d["type"]));
-
- Variant v=obj->get(name);
- int hint=d.has("hint")?d["hint"].operator int():-1;
- String hint_text=d.has("hint_text")?d["hint_text"]:"";
- Rect2 where=tree->get_custom_popup_rect();
- custom_editor->set_pos(where.pos);
-
- if (custom_editor->edit(obj,name,type,v,hint,hint_text)) {
- custom_editor->popup();
- }
-}
-
-void PropertyEditor::edit(Object* p_object) {
-
-
- if (obj==p_object)
- return;
- if (obj) {
-
- obj->remove_change_receptor(this);
- }
-
- obj=p_object;
-
- evaluator->edit(p_object);
-
- update_tree();
-
- if (obj) {
-
- obj->add_change_receptor(this);
- }
-
-
-}
-
-void PropertyEditor::_set_range_def(Object *p_item, String prop,float p_frame) {
-
- TreeItem *ti = p_item->cast_to<TreeItem>();
- ERR_FAIL_COND(!ti);
-
- ti->call_deferred("set_range",1, p_frame);
- obj->call_deferred("set",prop,p_frame);
-
-}
-
-void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
- TreeItem *ti = p_item->cast_to<TreeItem>();
- ERR_FAIL_COND(!ti);
-
- Dictionary d = ti->get_metadata(0);
-
- if (p_button==2) {
-
- if (!d.has("name"))
- return;
- String prop=d["name"];
- emit_signal("property_keyed",prop,obj->get(prop),false);
- } else if (p_button==5) {
- print_line("PB5");
- if (!d.has("name"))
- return;
- String prop=d["name"];
- emit_signal("property_keyed",prop,obj->get(prop),true);
- //set_range(p_column, ti->get_range(p_column)+1.0 );
- call_deferred("_set_range_def",ti,prop,ti->get_range(p_column)+1.0);
- } else if (p_button==3) {
-
- if (!d.has("name"))
- return;
-
- String prop=d["name"];
-
- Variant vorig;
-
- if (_might_be_in_instance() && _get_instanced_node_original_property(prop,vorig)) {
-
- _edit_set(prop,vorig);
- return;
- }
-
- if (obj->call("property_can_revert",prop).operator bool()) {
- Variant rev = obj->call("property_get_revert",prop);
- _edit_set(prop,rev);
- }
-
- 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);
- if (!d.has("type"))
- return;
- if (!d.has("hint"))
- return;
- if (!d.has("name"))
- return;
- if (!d.has("hint_text"))
- return;
-
- int t = d["type"];
- int h = d["hint"];
- String n = d["name"];
- String ht = d["hint_text"];
-
- if(t == Variant::NODE_PATH) {
-
- Variant v = obj->get(n);
- custom_editor->edit(obj, n, (Variant::Type)t, v, h, ht);
- Rect2 where = tree->get_item_rect(ti, 1);
- where.pos -= tree->get_scroll();
- where.pos += tree->get_global_pos();
- custom_editor->set_pos(where.pos);
- custom_editor->popup();
-
- } else if (t==Variant::STRING) {
-
-
- Variant v = obj->get(n);
- custom_editor->edit(obj,n,(Variant::Type)t,v,h,ht);
- //Rect2 where=tree->get_custom_popup_rect();
- if (h==PROPERTY_HINT_FILE || h==PROPERTY_HINT_DIR || h==PROPERTY_HINT_GLOBAL_DIR || h==PROPERTY_HINT_GLOBAL_FILE) {
-
- Rect2 where=tree->get_item_rect(ti,1);
- where.pos-=tree->get_scroll();
- where.pos+=tree->get_global_pos();
- custom_editor->set_pos(where.pos);
- custom_editor->popup();
- } else {
- custom_editor->popup_centered_ratio();
- }
-
- } else if (t==Variant::OBJECT) {
-
- RES r = obj->get(n);
- if (r.is_valid()) {
-
- emit_signal("resource_selected",r,n);
- }
- } else if (t==Variant::INT && h==PROPERTY_HINT_OBJECT_ID) {
-
- emit_signal("object_id_selected",obj->get(n));
- print_line("OBJ ID SELECTED");
-
- } else if (t==Variant::ARRAY || t==Variant::POOL_INT_ARRAY || t==Variant::POOL_REAL_ARRAY || t==Variant::POOL_STRING_ARRAY || t==Variant::POOL_VECTOR2_ARRAY || t==Variant::POOL_VECTOR3_ARRAY || t==Variant::POOL_COLOR_ARRAY || t==Variant::POOL_BYTE_ARRAY) {
-
- Variant v = obj->get(n);
-
- if (v.get_type()!=t) {
- Variant::CallError ce;
- v=Variant::construct(Variant::Type(t),NULL,0,ce);
- }
-
- Ref<ArrayPropertyEdit> ape = memnew( ArrayPropertyEdit );
- ape->edit(obj,n,ht,Variant::Type(t));
-
- EditorNode::get_singleton()->push_item(ape.ptr());
- }
- }
-}
-
-
-void PropertyEditor::_node_removed(Node *p_node) {
-
- if (p_node==obj) {
-
- edit(NULL);
- }
-}
-
-
-void PropertyEditor::set_keying(bool p_active) {
-
- if (keying==p_active)
- return;
-
- keying=p_active;
- update_tree();
-}
-
-void PropertyEditor::_draw_flags(Object *t,const Rect2& p_rect) {
-
- TreeItem *ti = t->cast_to<TreeItem>();
- if (!ti)
- return;
-
- Dictionary d = ti->get_metadata(0);
-
- if (!d.has("name"))
- return;
-
- uint32_t f = obj->get(d["name"]);
-
- int bsize = (p_rect.size.height*80/100)/2;
-
- int h = bsize*2+1;
- int vofs = (p_rect.size.height-h)/2;
-
- for(int i=0;i<2;i++) {
-
- Point2 ofs(4,vofs);
- if (i==1)
- ofs.y+=bsize+1;
-
- ofs+=p_rect.pos;
- for(int j=0;j<10;j++) {
-
- Point2 o = ofs+Point2(j*(bsize+1),0);
- if (j>=5)
- o.x+=1;
-
- uint32_t idx=i*10+j;
- bool on=f&(1<<idx);
- tree->draw_rect(Rect2(o,Size2(bsize,bsize)),Color(0,0,0,on?0.8:0.3));
- }
- }
-
-
-}
-
-void PropertyEditor::_filter_changed(const String& p_text) {
-
- update_tree();
-}
-
-
-
-void PropertyEditor::_resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud) {
-
- if (p_preview.is_null())
- return; //don't bother with empty preview
-
- ObjectID id = p_ud;
- Object *obj = ObjectDB::get_instance(id);
-
- if (!obj)
- return;
-
- TreeItem *ti = obj->cast_to<TreeItem>();
-
- ERR_FAIL_COND(!ti);
-
- int tw = EditorSettings::get_singleton()->get("docks/property_editor/texture_preview_width");
-
- ti->set_icon(1,p_preview); //should be scaled I think?
- ti->set_icon_max_width(1,tw);
- ti->set_text(1,"");
-}
-void PropertyEditor::_bind_methods() {
-
- ClassDB::bind_method( "_item_edited",&PropertyEditor::_item_edited);
- ClassDB::bind_method( "_item_selected",&PropertyEditor::_item_selected);
- ClassDB::bind_method( "_custom_editor_request",&PropertyEditor::_custom_editor_request);
- ClassDB::bind_method( "_custom_editor_edited",&PropertyEditor::_custom_editor_edited);
- ClassDB::bind_method( "_resource_edit_request",&PropertyEditor::_resource_edit_request);
- ClassDB::bind_method( "_node_removed",&PropertyEditor::_node_removed);
- ClassDB::bind_method( "_edit_button",&PropertyEditor::_edit_button);
- ClassDB::bind_method( "_changed_callback",&PropertyEditor::_changed_callbacks);
- ClassDB::bind_method( "_draw_flags",&PropertyEditor::_draw_flags);
- ClassDB::bind_method( "_set_range_def",&PropertyEditor::_set_range_def);
- ClassDB::bind_method( "_filter_changed",&PropertyEditor::_filter_changed);
- ClassDB::bind_method( "update_tree",&PropertyEditor::update_tree);
- ClassDB::bind_method( "_resource_preview_done",&PropertyEditor::_resource_preview_done);
- ClassDB::bind_method( "refresh",&PropertyEditor::refresh);
- ClassDB::bind_method( "_draw_transparency",&PropertyEditor::_draw_transparency);
-
- ClassDB::bind_method(_MD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw);
- ClassDB::bind_method(_MD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw);
- ClassDB::bind_method(_MD("drop_data_fw"), &PropertyEditor::drop_data_fw);
-
- 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") ) );
- ADD_SIGNAL( MethodInfo("object_id_selected", PropertyInfo( Variant::INT, "id")) );
- ADD_SIGNAL( MethodInfo("property_keyed",PropertyInfo( Variant::STRING, "property")));
- ADD_SIGNAL( MethodInfo("property_edited",PropertyInfo( Variant::STRING, "property")));
-}
-
-Tree *PropertyEditor::get_scene_tree() {
-
- return tree;
-}
-
-Label* PropertyEditor::get_top_label() {
-
- return top_label;
-}
-
-void PropertyEditor::hide_top_label() {
-
- top_label->hide();
- tree->set_begin( Point2(0,0 ));
-}
-
-String PropertyEditor::get_selected_path() const {
-
-
- TreeItem *ti = tree->get_selected();
- if (!ti)
- return "";
-
- Dictionary d = ti->get_metadata(0);
-
- if (d.has("name"))
- return d["name"];
- else
- return "";
-}
-
-void PropertyEditor::set_capitalize_paths(bool p_capitalize) {
-
- capitalize_paths=p_capitalize;
-}
-
-void PropertyEditor::set_autoclear(bool p_enable) {
-
- autoclear=p_enable;
-}
-
-void PropertyEditor::set_show_categories(bool p_show) {
-
- show_categories=p_show;
- update_tree();
-}
-
-void PropertyEditor::set_use_filter(bool p_use) {
-
- if (p_use==use_filter)
- return;
-
- use_filter=p_use;
- update_tree();
-}
-
-void PropertyEditor::register_text_enter(Node* p_line_edit) {
-
- ERR_FAIL_NULL(p_line_edit);
- search_box=p_line_edit->cast_to<LineEdit>();
-
- 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() {
-
- _prop_edited="property_edited";
-
- hide_script=false;
-
- undo_redo=NULL;
- obj=NULL;
- search_box=NULL;
- changing=false;
- update_tree_pending=false;
-
- top_label = memnew( Label );
- top_label->set_text(TTR("Properties:"));
- top_label->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- top_label->set_begin( Point2( 10,0) );
- top_label->set_end( Point2( 0,12) );
-
- add_child(top_label);
-
-
- tree = memnew( Tree );
- tree->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- tree->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- tree->set_begin( Point2(0,19 ));
- tree->set_end( Point2(0,0 ));
-
- tree->set_columns(2);
- tree->set_column_expand(0,true);
- tree->set_column_min_width(0,30);
- tree->set_column_expand(1,true);
- tree->set_column_min_width(1,18);
-
- //tree->set_hide_root(true);
- add_child( tree );
-
- tree->connect("item_edited", this,"_item_edited",varray(),CONNECT_DEFERRED);
- tree->connect("cell_selected", this,"_item_selected");
-
- tree->set_drag_forwarding(this);
-
- set_fixed_process(true);
-
- custom_editor = memnew( CustomPropertyEditor );
- add_child(custom_editor);
-
- tree->connect("custom_popup_edited", this,"_custom_editor_request");
- tree->connect("button_pressed", this,"_edit_button");
- custom_editor->connect("variant_changed", this,"_custom_editor_edited");
- custom_editor->connect("resource_edit_request", this,"_resource_edit_request",make_binds(),CONNECT_DEFERRED);
- tree->set_hide_folding(true);
-
- evaluator = memnew (PropertyValueEvaluator);
- tree->set_value_evaluator(evaluator);
- custom_editor->set_value_evaluator(evaluator);
-
- capitalize_paths=true;
- autoclear=false;
- tree->set_column_titles_visible(false);
-
- keying=false;
- read_only=false;
- show_categories=false;
- refresh_countdown=0;
- use_doc_hints=false;
- use_filter=false;
- subsection_selectable=false;
- show_type_icons=EDITOR_DEF("interface/show_type_icons",false);
-
-}
-
-
-PropertyEditor::~PropertyEditor()
-{
- memdelete(evaluator);
-}
-
-
-/////////////////////////////
-
-
-
-
-
-class SectionedPropertyEditorFilter : public Object {
-
- GDCLASS( SectionedPropertyEditorFilter, Object );
-
- Object *edited;
- String section;
- bool allow_sub;
-
- 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);
- //_change_notify(p_name.operator String().utf8().get_data());
- 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 (pi.name=="resource_path" || pi.name=="resource_name" || pi.name.begins_with("script/")) //skip resource stuff
- continue;
-
- if (sp==-1) {
- pi.name="Global/"+pi.name;
-
- }
-
- if (pi.name.begins_with(section+"/")) {
- pi.name=pi.name.replace_first(section+"/","");
- if (!allow_sub && pi.name.find("/")!=-1)
- continue;
- p_list->push_back(pi);
- }
- }
-
- }
-
- bool property_can_revert(const String& p_name) {
-
- return edited->call("property_can_revert",section+"/"+p_name);
- }
-
- Variant property_get_revert(const String& p_name) {
-
- return edited->call("property_get_revert",section+"/"+p_name);
- }
-
-protected:
- static void _bind_methods() {
-
- ClassDB::bind_method("property_can_revert",&SectionedPropertyEditorFilter::property_can_revert);
- ClassDB::bind_method("property_get_revert",&SectionedPropertyEditorFilter::property_get_revert);
- }
-
-public:
-
- void set_section(const String& p_section,bool p_allow_sub) {
-
- section=p_section;
- allow_sub=p_allow_sub;
- _change_notify();
- }
-
- void set_edited(Object* p_edited) {
- edited=p_edited;
- _change_notify();
- }
-
- SectionedPropertyEditorFilter() {
- edited=NULL;
- }
-
-};
-
-
-void SectionedPropertyEditor::_bind_methods() {
-
- ClassDB::bind_method("_section_selected",&SectionedPropertyEditor::_section_selected);
-
- ClassDB::bind_method("update_category_list", &SectionedPropertyEditor::update_category_list);
-}
-
-void SectionedPropertyEditor::_section_selected() {
-
- if (!sections->get_selected())
- return;
-
- filter->set_section( sections->get_selected()->get_metadata(0), sections->get_selected()->get_children()==NULL);
-}
-
-void SectionedPropertyEditor::set_current_section(const String& p_section) {
-
- if (section_map.has(p_section)) {
- section_map[p_section]->select(0);
- }
-}
-
-String SectionedPropertyEditor::get_current_section() const {
-
- if (sections->get_selected())
- return sections->get_selected()->get_metadata(0);
- else
- return "";
-}
-
-String SectionedPropertyEditor::get_full_item_path(const String& p_item) {
-
- String base = get_current_section();
-
- if (base!="")
- return base+"/"+p_item;
- else
- return p_item;
-}
-
-void SectionedPropertyEditor::edit(Object* p_object) {
-
- if (!p_object) {
- obj = -1;
- sections->clear();
-
- filter->set_edited(NULL);
- editor->edit(NULL);
-
- return;
- }
-
- ObjectID id = p_object->get_instance_ID();
-
- if (obj != id) {
-
- obj = id;
- update_category_list();
-
- filter->set_edited(p_object);
- editor->edit(filter);
-
- if (sections->get_root()->get_children()) {
- sections->get_root()->get_children()->select(0);
- }
- } else {
-
- update_category_list();
- }
-}
-
-void SectionedPropertyEditor::update_category_list() {
-
- String selected_category=get_current_section();
- sections->clear();
-
- Object *o = ObjectDB::get_instance(obj);
-
- if (!o)
- return;
-
- List<PropertyInfo> pinfo;
- o->get_property_list(&pinfo);
-
- section_map.clear();
-
- TreeItem *root = sections->create_item();
- section_map[""]=root;
-
-
- for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
-
- PropertyInfo pi=E->get();
-
- if (pi.usage&PROPERTY_USAGE_CATEGORY)
- continue;
- else if ( !(pi.usage&PROPERTY_USAGE_EDITOR) )
- continue;
-
- if (pi.name.find(":")!=-1 || pi.name=="script/script" || pi.name=="resource_name" || pi.name=="resource_path")
- continue;
- int sp = pi.name.find("/");
- if (sp==-1)
- pi.name="Global/"+pi.name;
-
- Vector<String> sectionarr = pi.name.split("/");
- String metasection;
-
-
- for(int i=0;i<MIN(2,sectionarr.size()-1);i++) {
-
- TreeItem *parent = section_map[metasection];
-
- if (i>0) {
- metasection+="/"+sectionarr[i];
- } else {
- metasection=sectionarr[i];
- }
-
-
- if (!section_map.has(metasection)) {
- TreeItem *ms = sections->create_item(parent);
- section_map[metasection]=ms;
- ms->set_text(0,sectionarr[i].capitalize());
- ms->set_metadata(0,metasection);
-
- }
- }
-
- }
-
- if (section_map.has(selected_category)) {
- section_map[selected_category]->select(0);
- }
-}
-
-PropertyEditor *SectionedPropertyEditor::get_property_editor() {
-
- return editor;
-}
-
-SectionedPropertyEditor::SectionedPropertyEditor() {
-
- obj = -1;
-
- VBoxContainer *left_vb = memnew( VBoxContainer);
- left_vb->set_custom_minimum_size(Size2(160,0)*EDSCALE);
- add_child(left_vb);
-
- sections = memnew( Tree );
- sections->set_v_size_flags(SIZE_EXPAND_FILL);
- sections->set_hide_root(true);
-
- left_vb->add_margin_child(TTR("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(TTR("Properties:"),editor,true);
-
- editor->get_scene_tree()->set_column_titles_visible(false);
-
-
- editor->hide_top_label();
-
- sections->connect("cell_selected",this,"_section_selected");
-
-}
-
-SectionedPropertyEditor::~SectionedPropertyEditor() {
-
- memdelete(filter);
-}
-
-double PropertyValueEvaluator::eval(const String& p_text) {
-
- if (!obj || !script_language)
- return _default_eval(p_text);
-
- Ref<Script> script= Ref<Script>(script_language ->create_script());
- script->set_source_code(_build_script(p_text));
- Error err = script->reload();
- if (err) {
- print_line("[PropertyValueEvaluator] Error loading script for expression: " + p_text);
- return _default_eval(p_text);
- }
-
- ScriptInstance *script_instance = script->instance_create(this);
- if (!script_instance)
- return _default_eval(p_text);
-
- Variant::CallError call_err;
- script_instance->call("set_this",obj);
- double result = script_instance->call("e", NULL, 0, call_err );
- if (call_err.error == Variant::CallError::CALL_OK) {
- return result;
- }
- print_line("[PropertyValueEvaluator]: Error eval! Error code: " + itos(call_err.error));
-
- memdelete(script_instance);
-
- return _default_eval(p_text);
-}
-
-
-void PropertyValueEvaluator::edit(Object *p_obj) {
- obj = p_obj;
-}
-
-String PropertyValueEvaluator::_build_script(const String& p_text) {
- String script_text = "tool\nvar this\nfunc set_this(p_this):\n\tthis=p_this\nfunc e():\n\treturn ";
- script_text += p_text.strip_edges();
- script_text += "\n";
- return script_text;
-}
-
-PropertyValueEvaluator::PropertyValueEvaluator() {
- script_language=NULL;
-
- for(int i=0;i<ScriptServer::get_language_count();i++) {
- if (ScriptServer::get_language(i)->get_name()=="GDScript") {
- script_language=ScriptServer::get_language(i);
- }
- }
-}
-
-PropertyValueEvaluator::~PropertyValueEvaluator() {
-
-}
diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h
deleted file mode 100644
index 969340d5a2..0000000000
--- a/tools/editor/property_editor.h
+++ /dev/null
@@ -1,347 +0,0 @@
-/*************************************************************************/
-/* property_editor.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PROPERTY_EDITOR_H
-#define PROPERTY_EDITOR_H
-
-#include "scene/gui/tree.h"
-#include "scene/gui/button.h"
-#include "scene/gui/check_box.h"
-#include "scene/gui/label.h"
-#include "tools/editor/editor_file_dialog.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/color_picker.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/texture_rect.h"
-#include "scene/gui/text_edit.h"
-#include "scene/gui/check_button.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/grid_container.h"
-#include "scene_tree_editor.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-class PropertyValueEvaluator;
-class CreateDialog;
-class PropertySelector;
-
-class CustomPropertyEditor : public Popup {
-
- GDCLASS( CustomPropertyEditor, Popup );
-
- enum {
- MAX_VALUE_EDITORS=12,
- MAX_ACTION_BUTTONS=5,
- OBJ_MENU_LOAD=0,
- OBJ_MENU_EDIT=1,
- OBJ_MENU_CLEAR=2,
- OBJ_MENU_MAKE_UNIQUE=3,
- OBJ_MENU_COPY=4,
- OBJ_MENU_PASTE=5,
- OBJ_MENU_REIMPORT=6,
- OBJ_MENU_NEW_SCRIPT=7,
- TYPE_BASE_ID=100
-
- };
-
- enum {
- EASING_LINEAR,
- EASING_EASE_IN,
- EASING_EASE_OUT,
- EASING_ZERO,
- EASING_IN_OUT,
- EASING_OUT_IN
- };
-
-
- PopupMenu *menu;
- SceneTreeDialog *scene_tree;
- EditorFileDialog *file;
- ConfirmationDialog *error;
- String name;
- Variant::Type type;
- Variant v;
- int hint;
- String hint_text;
- LineEdit *value_editor[MAX_VALUE_EDITORS];
- Label *value_label[MAX_VALUE_EDITORS];
- HScrollBar *scroll[4];
- Button *action_buttons[MAX_ACTION_BUTTONS];
- MenuButton *type_button;
- Vector<String> inheritors_array;
- TextureRect *texture_preview;
- ColorPicker *color_picker;
- TextEdit *text_edit;
- bool read_only;
- bool picking_viewport;
- GridContainer *checks20gc;
- CheckBox *checks20[20];
- SpinBox *spinbox;
- HSlider *slider;
-
-
- Control *easing_draw;
- CreateDialog *create_dialog;
- PropertySelector *property_select;
-
- Object* owner;
-
- bool updating;
-
- PropertyValueEvaluator *evaluator;
-
- void _text_edit_changed();
- void _file_selected(String p_file);
- void _scroll_modified(double p_value);
- void _modified(String p_string);
- void _range_modified(double p_value);
- void _focus_enter();
- void _focus_exit();
- void _action_pressed(int p_which);
- void _type_create_selected(int p_idx);
- void _create_dialog_callback();
- void _create_selected_property(const String &p_prop);
-
-
- void _color_changed(const Color& p_color);
- void _draw_easing();
- void _menu_option(int p_which);
-
- void _drag_easing(const InputEvent& p_ev);
-
- void _node_path_selected(NodePath p_path);
- void show_value_editors(int p_amount);
- void config_value_editors(int p_amount, int p_columns,int p_label_w,const List<String>& p_strings);
- void config_action_buttons(const List<String>& p_strings);
-
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
-
-
- void hide_menu();
-
- Variant get_variant() const;
- String get_name() const;
-
- void set_read_only(bool p_read_only) { read_only=p_read_only; }
-
- void set_value_evaluator( PropertyValueEvaluator *p_evaluator) { evaluator=p_evaluator; }
-
- bool edit(Object* p_owner,const String& p_name,Variant::Type p_type, const Variant& p_variant,int p_hint,String p_hint_text);
-
- CustomPropertyEditor();
-};
-
-class PropertyEditor : public Control {
-
- GDCLASS( PropertyEditor, Control );
-
- Tree *tree;
- Label *top_label;
- //Object *object;
- LineEdit *search_box;
-
- PropertyValueEvaluator *evaluator;
-
- Object* obj;
-
-
- StringName _prop_edited;
-
- bool capitalize_paths;
- bool changing;
- bool update_tree_pending;
- bool autoclear;
- 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;
- bool hide_script;
-
- HashMap<String,String> pending;
- String selected_property;
-
- Map<StringName,Map<StringName,String> > descr_cache;
- Map<StringName,String > class_descr_cache;
-
- CustomPropertyEditor *custom_editor;
-
- void _resource_edit_request();
- void _custom_editor_edited();
- void _custom_editor_request(bool p_arrow);
-
- void _item_selected();
- void _item_edited();
- TreeItem *get_parent_node(String p_path,HashMap<String,TreeItem*>& item_paths,TreeItem *root);
-
- void set_item_text(TreeItem *p_item, int p_type, const String& p_name, int p_hint=PROPERTY_HINT_NONE, const String& p_hint_text="");
-
- TreeItem *find_item(TreeItem *p_item,const String& p_name);
-
-
- 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);
-
- void _node_removed(Node *p_node);
-
-friend class ProjectExportDialog;
- void _edit_set(const String& p_name, const Variant& p_value,bool p_refresh_all=false);
- void _draw_flags(Object *ti,const Rect2& p_rect);
-
- bool _might_be_in_instance();
- bool _get_instanced_node_original_property(const StringName& p_prop,Variant& value);
- bool _is_property_different(const Variant& p_current, const Variant& p_orig,int p_usage=0);
-
- void _refresh_item(TreeItem *p_item);
- void _set_range_def(Object *p_item, String prop, float p_frame);
-
- void _filter_changed(const String& p_text);
-
- void _mark_drop_fields(TreeItem* p_at);
- void _clear_drop_fields(TreeItem* p_at);
-
- bool _is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const;
- Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
- bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
- void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
-
- void _resource_preview_done(const String& p_path,const Ref<Texture>& p_preview,Variant p_ud);
- void _draw_transparency(Object *t, const Rect2& p_rect);
-
- UndoRedo *undo_redo;
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
-
- String get_selected_path() const;
-
- Tree *get_scene_tree();
- Label* get_top_label();
- void hide_top_label();
- void update_tree();
- void update_property(const String& p_prop);
-
- void refresh();
-
- void edit(Object* p_object);
-
- void set_keying(bool p_active);
- void set_read_only(bool p_read_only) { read_only=p_read_only; custom_editor->set_read_only(p_read_only);}
-
- void set_capitalize_paths(bool p_capitalize);
- void set_autoclear(bool p_enable);
-
- void set_show_categories(bool p_show);
- void set_use_doc_hints(bool p_enable) { use_doc_hints=p_enable; }
- void set_hide_script(bool p_hide) { hide_script=p_hide; }
-
- 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 {
-
-
- GDCLASS(SectionedPropertyEditor,HBoxContainer);
-
- ObjectID obj;
-
- Tree *sections;
- SectionedPropertyEditorFilter *filter;
-
- Map<String,TreeItem*> section_map;
- PropertyEditor *editor;
-
-
- static void _bind_methods();
- void _section_selected();
-
-public:
-
- PropertyEditor *get_property_editor();
- void edit(Object* p_object);
- String get_full_item_path(const String& p_item);
-
- void set_current_section(const String& p_section);
- String get_current_section() const;
-
- void update_category_list();
-
- SectionedPropertyEditor();
- ~SectionedPropertyEditor();
-};
-
-class PropertyValueEvaluator : public ValueEvaluator {
- GDCLASS( PropertyValueEvaluator, ValueEvaluator );
-
- Object *obj;
- ScriptLanguage *script_language;
- String _build_script(const String& p_text);
-
- _FORCE_INLINE_ double _default_eval(const String& p_text) {
- return p_text.to_double();
- }
-
-public:
-
- void edit(Object *p_obj);
- double eval(const String& p_text);
-
- PropertyValueEvaluator();
- ~PropertyValueEvaluator();
-};
-
-#endif
diff --git a/tools/editor/property_selector.cpp b/tools/editor/property_selector.cpp
deleted file mode 100644
index 3eeec1634d..0000000000
--- a/tools/editor/property_selector.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-/*************************************************************************/
-/* property_selector.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "property_selector.h"
-
-#include "editor_scale.h"
-#include "os/keyboard.h"
-
-void PropertySelector::_text_changed(const String& p_newtext) {
-
- _update_search();
-}
-
-void PropertySelector::_sbox_input(const InputEvent& p_ie) {
-
- if (p_ie.type==InputEvent::KEY) {
-
- switch(p_ie.key.scancode) {
- case KEY_UP:
- case KEY_DOWN:
- case KEY_PAGEUP:
- case KEY_PAGEDOWN: {
-
- search_options->call("_gui_input", 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;
- }
- }
-}
-
-
-void PropertySelector::_update_search() {
-
-
- if (properties)
- set_title(TTR("Select Property"));
- else
- set_title(TTR("Select Method"));
-
- search_options->clear();
- help_bit->set_text("");
-
-
- TreeItem *root = search_options->create_item();
-
-
- if (properties) {
-
- List<PropertyInfo> props;
-
- if (instance) {
- instance->get_property_list(&props,true);
- } else if (type!=Variant::NIL) {
- Variant v;
- if (type==Variant::INPUT_EVENT) {
- InputEvent ie;
- ie.type=event_type;
- v=ie;
- } else {
- Variant::CallError ce;
- v=Variant::construct(type,NULL,0,ce);
- }
-
- v.get_property_list(&props);
- } else {
-
-
- Object *obj = ObjectDB::get_instance(script);
- if (obj && obj->cast_to<Script>()) {
-
- props.push_back(PropertyInfo(Variant::NIL,"Script Variables",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_CATEGORY));
- obj->cast_to<Script>()->get_script_property_list(&props);
- }
-
- StringName base=base_type;
- while(base) {
- props.push_back(PropertyInfo(Variant::NIL,base,PROPERTY_HINT_NONE,"",PROPERTY_USAGE_CATEGORY));
- ClassDB::get_property_list(base,&props,true);
- base=ClassDB::get_parent_class(base);
- }
-
- }
-
- TreeItem *category=NULL;
-
- bool found=false;
-
- Ref<Texture> type_icons[Variant::VARIANT_MAX]={
- Control::get_icon("MiniVariant","EditorIcons"),
- Control::get_icon("MiniBoolean","EditorIcons"),
- Control::get_icon("MiniInteger","EditorIcons"),
- Control::get_icon("MiniFloat","EditorIcons"),
- Control::get_icon("MiniString","EditorIcons"),
- Control::get_icon("MiniVector2","EditorIcons"),
- Control::get_icon("MiniRect2","EditorIcons"),
- Control::get_icon("MiniVector3","EditorIcons"),
- Control::get_icon("MiniMatrix2","EditorIcons"),
- Control::get_icon("MiniPlane","EditorIcons"),
- Control::get_icon("MiniQuat","EditorIcons"),
- Control::get_icon("MiniAabb","EditorIcons"),
- Control::get_icon("MiniMatrix3","EditorIcons"),
- Control::get_icon("MiniTransform","EditorIcons"),
- Control::get_icon("MiniColor","EditorIcons"),
- Control::get_icon("MiniImage","EditorIcons"),
- Control::get_icon("MiniPath","EditorIcons"),
- Control::get_icon("MiniRid","EditorIcons"),
- Control::get_icon("MiniObject","EditorIcons"),
- Control::get_icon("MiniInput","EditorIcons"),
- Control::get_icon("MiniDictionary","EditorIcons"),
- Control::get_icon("MiniArray","EditorIcons"),
- Control::get_icon("MiniRawArray","EditorIcons"),
- Control::get_icon("MiniIntArray","EditorIcons"),
- Control::get_icon("MiniFloatArray","EditorIcons"),
- Control::get_icon("MiniStringArray","EditorIcons"),
- Control::get_icon("MiniVector2Array","EditorIcons"),
- Control::get_icon("MiniVector3Array","EditorIcons"),
- Control::get_icon("MiniColorArray","EditorIcons")
- };
-
-
- for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
- if (E->get().usage==PROPERTY_USAGE_CATEGORY) {
- if (category && category->get_children()==NULL) {
- memdelete(category); //old category was unused
- }
- category = search_options->create_item(root);
- category->set_text(0,E->get().name);
- category->set_selectable(0,false);
-
- Ref<Texture> icon;
- if (E->get().name=="Script Variables") {
- icon=get_icon("Script","EditorIcons");
- } else if (has_icon(E->get().name,"EditorIcons")) {
- icon=get_icon(E->get().name,"EditorIcons");
- } else {
- icon=get_icon("Object","EditorIcons");
- }
- category->set_icon(0,icon);
- continue;
- }
-
- if (!(E->get().usage&PROPERTY_USAGE_EDITOR))
- continue;
-
- if (search_box->get_text()!=String() && E->get().name.find(search_box->get_text())==-1)
- continue;
- TreeItem *item = search_options->create_item(category?category:root);
- item->set_text(0,E->get().name);
- item->set_metadata(0,E->get().name);
- item->set_icon(0,type_icons[E->get().type]);
-
- if (!found && search_box->get_text()!=String() && E->get().name.find(search_box->get_text())!=-1) {
- item->select(0);
- found=true;
- }
-
- item->set_selectable(0,true);
- }
-
- if (category && category->get_children()==NULL) {
- memdelete(category); //old category was unused
- }
- } else {
-
- List<MethodInfo> methods;
-
- if (type!=Variant::NIL) {
- Variant v;
- Variant::CallError ce;
- v=Variant::construct(type,NULL,0,ce);
- v.get_method_list(&methods);
- } else {
-
-
- Object *obj = ObjectDB::get_instance(script);
- if (obj && obj->cast_to<Script>()) {
-
- methods.push_back(MethodInfo("*Script Methods"));
- obj->cast_to<Script>()->get_script_method_list(&methods);
- }
-
- StringName base=base_type;
- while(base) {
- methods.push_back(MethodInfo("*"+String(base)));
- ClassDB::get_method_list(base,&methods,true);
- base=ClassDB::get_parent_class(base);
- }
-
- }
-
- TreeItem *category=NULL;
-
- bool found=false;
- bool script_methods=false;
-
- for (List<MethodInfo>::Element *E=methods.front();E;E=E->next()) {
- if (E->get().name.begins_with("*")) {
- if (category && category->get_children()==NULL) {
- memdelete(category); //old category was unused
- }
- category = search_options->create_item(root);
- category->set_text(0,E->get().name.replace_first("*",""));
- category->set_selectable(0,false);
-
- Ref<Texture> icon;
- script_methods=false;
- if (E->get().name=="*Script Methods") {
- icon=get_icon("Script","EditorIcons");
- script_methods=true;
- } else if (has_icon(E->get().name,"EditorIcons")) {
- icon=get_icon(E->get().name,"EditorIcons");
- } else {
- icon=get_icon("Object","EditorIcons");
- }
- category->set_icon(0,icon);
-
- continue;
- }
-
- String name = E->get().name.get_slice(":",0);
- if (!script_methods && name.begins_with("_") && !(E->get().flags&METHOD_FLAG_VIRTUAL))
- continue;
-
- if (search_box->get_text()!=String() && name.find(search_box->get_text())==-1)
- continue;
-
- TreeItem *item = search_options->create_item(category?category:root);
-
- MethodInfo mi=E->get();
-
- String desc;
- if (mi.name.find(":")!=-1) {
- desc=mi.name.get_slice(":",1)+" ";
- mi.name=mi.name.get_slice(":",0);
- } else if (mi.return_val.type!=Variant::NIL)
- desc=Variant::get_type_name(mi.return_val.type);
- else
- desc="void ";
-
-
-
- desc+=" "+mi.name+" ( ";
-
- for(int i=0;i<mi.arguments.size();i++) {
-
- if (i>0)
- desc+=", ";
-
- if (mi.arguments[i].type==Variant::NIL)
- desc+="var ";
- else if (mi.arguments[i].name.find(":")!=-1) {
- desc+=mi.arguments[i].name.get_slice(":",1)+" ";
- mi.arguments[i].name=mi.arguments[i].name.get_slice(":",0);
- } else
- desc+=Variant::get_type_name(mi.arguments[i].type)+" ";
-
- desc+=mi.arguments[i].name;
-
- }
-
- desc+=" )";
-
- item->set_text(0,desc);
- item->set_metadata(0,name);
- item->set_selectable(0,true);
-
- if (!found && search_box->get_text()!=String() && name.find(search_box->get_text())!=-1) {
- item->select(0);
- found=true;
- }
-
- }
-
- if (category && category->get_children()==NULL) {
- memdelete(category); //old category was unused
- }
-
- }
-
- get_ok()->set_disabled(root->get_children()==NULL);
-
-}
-
-
-
-void PropertySelector::_confirmed() {
-
- TreeItem *ti = search_options->get_selected();
- if (!ti)
- return;
- emit_signal("selected",ti->get_metadata(0));
- hide();
-}
-
-void PropertySelector::_item_selected() {
-
- help_bit->set_text("");
-
- TreeItem *item=search_options->get_selected();
- if (!item)
- return;
- String name = item->get_metadata(0);
-
- String class_type;
- if (properties && type==Variant::INPUT_EVENT) {
-
- switch(event_type) {
- case InputEvent::NONE: class_type="InputEvent"; break;
- case InputEvent::KEY: class_type="InputEventKey"; break;
- case InputEvent::MOUSE_MOTION: class_type="InputEventMouseMotion"; break;
- case InputEvent::MOUSE_BUTTON: class_type="InputEventMouseButton"; break;
- case InputEvent::JOYPAD_MOTION: class_type="InputEventJoypadMotion"; break;
- case InputEvent::JOYPAD_BUTTON: class_type="InputEventJoypadButton"; break;
- case InputEvent::SCREEN_TOUCH: class_type="InputEventScreenTouch"; break;
- case InputEvent::SCREEN_DRAG: class_type="InputEventScreenDrag"; break;
- case InputEvent::ACTION: class_type="InputEventAction"; break;
- default: {}
- }
-
- } else if (type) {
- class_type=Variant::get_type_name(type);
-
- } else {
- class_type=base_type;
- }
-
- DocData *dd=EditorHelp::get_doc_data();
- String text;
-
-
- if (properties) {
-
- String at_class=class_type;
-
-
-
- while(at_class!=String()) {
-
-
- Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(at_class);
- if (E) {
- for(int i=0;i<E->get().properties.size();i++) {
- if (E->get().properties[i].name==name) {
- text=E->get().properties[i].description;
- }
- }
- }
-
- at_class=ClassDB::get_parent_class(at_class);
- }
-
- if (text==String()) {
-
- StringName setter;
- StringName type;
- if (ClassDB::get_setter_and_type_for_property(class_type,name,type,setter)) {
- Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
- if (E) {
- for(int i=0;i<E->get().methods.size();i++) {
- if (E->get().methods[i].name==setter.operator String()) {
- text=E->get().methods[i].description;
- }
- }
- }
-
-
- }
- }
-
- } else {
-
-
- String at_class=class_type;
-
- while(at_class!=String()) {
-
- Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(at_class);
- if (E) {
- for(int i=0;i<E->get().methods.size();i++) {
- if (E->get().methods[i].name==name) {
- text=E->get().methods[i].description;
- }
- }
- }
-
- at_class=ClassDB::get_parent_class(at_class);
- }
- }
-
-
- if (text==String())
- return;
-
- help_bit->set_text(text);
-
-}
-
-
-void PropertySelector::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- connect("confirmed",this,"_confirmed");
-
- }
-}
-
-
-
-void PropertySelector::select_method_from_base_type(const String& p_base,const String& p_current) {
-
- base_type=p_base;
- selected=p_current;
- type=Variant::NIL;
- script=0;
- properties=false;
- instance=NULL;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-}
-
-void PropertySelector::select_method_from_script(const Ref<Script>& p_script,const String& p_current){
-
- ERR_FAIL_COND( p_script.is_null() );
- base_type=p_script->get_instance_base_type();
- selected=p_current;
- type=Variant::NIL;
- script=p_script->get_instance_ID();
- properties=false;
- instance=NULL;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-
-}
-void PropertySelector::select_method_from_basic_type(Variant::Type p_type, const String &p_current){
-
- ERR_FAIL_COND(p_type==Variant::NIL);
- base_type="";
- selected=p_current;
- type=p_type;
- script=0;
- properties=false;
- instance=NULL;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-
-}
-
-void PropertySelector::select_method_from_instance(Object* p_instance, const String &p_current){
-
-
- base_type=p_instance->get_class();
- selected=p_current;
- type=Variant::NIL;
- script=0;
- {
- Ref<Script> scr = p_instance->get_script();
- if (scr.is_valid())
- script=scr->get_instance_ID();
- }
- properties=false;
- instance=NULL;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-
-}
-
-
-void PropertySelector::select_property_from_base_type(const String& p_base,const String& p_current) {
-
- base_type=p_base;
- selected=p_current;
- type=Variant::NIL;
- script=0;
- properties=true;
- instance=NULL;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-}
-
-void PropertySelector::select_property_from_script(const Ref<Script>& p_script,const String& p_current){
-
- ERR_FAIL_COND( p_script.is_null() );
-
- base_type=p_script->get_instance_base_type();
- selected=p_current;
- type=Variant::NIL;
- script=p_script->get_instance_ID();
- properties=true;
- instance=NULL;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-
-}
-void PropertySelector::select_property_from_basic_type(Variant::Type p_type, InputEvent::Type p_event_type, const String &p_current){
-
- ERR_FAIL_COND(p_type==Variant::NIL);
- base_type="";
- selected=p_current;
- type=p_type;
- event_type=p_event_type;
- script=0;
- properties=true;
- instance=NULL;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-
-}
-
-void PropertySelector::select_property_from_instance(Object* p_instance, const String &p_current){
-
-
- base_type="";
- selected=p_current;
- type=Variant::NIL;
- script=0;
- properties=true;
- instance=p_instance;
-
- popup_centered_ratio(0.6);
- search_box->set_text("");
- search_box->grab_focus();
- _update_search();
-
-}
-
-void PropertySelector::_bind_methods() {
-
- ClassDB::bind_method(_MD("_text_changed"),&PropertySelector::_text_changed);
- ClassDB::bind_method(_MD("_confirmed"),&PropertySelector::_confirmed);
- ClassDB::bind_method(_MD("_sbox_input"),&PropertySelector::_sbox_input);
- ClassDB::bind_method(_MD("_item_selected"),&PropertySelector::_item_selected);
-
- ADD_SIGNAL(MethodInfo("selected",PropertyInfo(Variant::STRING,"name")));
-
-}
-
-
-PropertySelector::PropertySelector() {
-
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
- search_box = memnew( LineEdit );
- vbc->add_margin_child(TTR("Search:"),search_box);
- search_box->connect("text_changed",this,"_text_changed");
- search_box->connect("gui_input",this,"_sbox_input");
- search_options = memnew( Tree );
- vbc->add_margin_child(TTR("Matches:"),search_options,true);
- get_ok()->set_text(TTR("Open"));
- get_ok()->set_disabled(true);
- register_text_enter(search_box);
- set_hide_on_ok(false);
- search_options->connect("item_activated",this,"_confirmed");
- search_options->connect("cell_selected",this,"_item_selected");
- search_options->set_hide_root(true);
- search_options->set_hide_folding(true);
-
- help_bit = memnew( EditorHelpBit );
- vbc->add_margin_child(TTR("Description:"),help_bit);
- help_bit->connect("request_hide",this,"_closed");
-
-
-}
diff --git a/tools/editor/property_selector.h b/tools/editor/property_selector.h
deleted file mode 100644
index d29183f85e..0000000000
--- a/tools/editor/property_selector.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*************************************************************************/
-/* property_selector.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 PROPERTYSELECTOR_H
-#define PROPERTYSELECTOR_H
-
-#include "tools/editor/property_editor.h"
-#include "scene/gui/rich_text_label.h"
-#include "editor_help.h"
-
-class PropertySelector : public ConfirmationDialog {
- GDCLASS(PropertySelector,ConfirmationDialog )
-
-
- LineEdit *search_box;
- Tree *search_options;
-
- void _update_search();
-
- void _sbox_input(const InputEvent& p_ie);
-
- void _confirmed();
- void _text_changed(const String& p_newtext);
-
- EditorHelpBit *help_bit;
-
- bool properties;
- String selected;
- Variant::Type type;
- InputEvent::Type event_type;
- String base_type;
- ObjectID script;
- Object *instance;
-
- void _item_selected();
-protected:
- void _notification(int p_what);
- static void _bind_methods();
-
-
-
-public:
-
-
- void select_method_from_base_type(const String& p_base,const String& p_current="");
- void select_method_from_script(const Ref<Script>& p_script,const String& p_current="");
- void select_method_from_basic_type(Variant::Type p_type,const String& p_current="");
- void select_method_from_instance(Object* p_instance, const String &p_current="");
-
- void select_property_from_base_type(const String& p_base,const String& p_current="");
- void select_property_from_script(const Ref<Script>& p_script,const String& p_current="");
- void select_property_from_basic_type(Variant::Type p_type,InputEvent::Type p_event_type,const String& p_current="");
- void select_property_from_instance(Object* p_instance, const String &p_current="");
-
- PropertySelector();
-};
-
-#endif // PROPERTYSELECTOR_H
diff --git a/tools/editor/quick_open.cpp b/tools/editor/quick_open.cpp
deleted file mode 100644
index 615b42b411..0000000000
--- a/tools/editor/quick_open.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/*************************************************************************/
-/* quick_open.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "quick_open.h"
-
-#include "os/keyboard.h"
-
-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);
- if (p_dontclear)
- 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) {
-
- _update_search();
-}
-
-void EditorQuickOpen::_sbox_input(const InputEvent& p_ie) {
-
- if (p_ie.type==InputEvent::KEY) {
-
- switch(p_ie.key.scancode) {
- case KEY_UP:
- case KEY_DOWN:
- case KEY_PAGEUP:
- case KEY_PAGEDOWN: {
-
- search_options->call("_gui_input", 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;
- }
- }
-
-}
-
-float EditorQuickOpen::_path_cmp(String search, String path) const {
-
- if (search == path) {
- return 1.2f;
- }
- if (path.findn(search) != -1) {
- return 1.1f;
- }
- return path.to_lower().similarity(search.to_lower());
-}
-
-void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector< Pair< String, Ref<Texture> > > &list) {
-
- if (!add_directories) {
- for(int i=0;i<efsd->get_subdir_count();i++) {
-
- _parse_fs(efsd->get_subdir(i), list);
- }
- }
-
- String search_text = search_box->get_text();
-
- if (add_directories) {
- String path = efsd->get_path();
- if (!path.ends_with("/"))
- path+="/";
- if (path!="res://") {
- path=path.substr(6,path.length());
- if (search_text.is_subsequence_ofi(path)) {
- Pair< String, Ref<Texture> > pair;
- pair.first = path;
- pair.second = get_icon("folder", "FileDialog");
-
- if (search_text != String() && list.size() > 0) {
-
- float this_sim = _path_cmp(search_text, path);
- float other_sim = _path_cmp(list[0].first, path);
- int pos = 1;
-
- while (pos < list.size() && this_sim <= other_sim) {
- other_sim = _path_cmp(list[pos++].first, path);
- }
-
- pos = this_sim >= other_sim ? pos - 1 : pos;
- list.insert(pos, pair);
-
- } else {
- list.push_back(pair);
- }
- }
- }
- }
- for(int i=0;i<efsd->get_file_count();i++) {
-
- String file = efsd->get_file_path(i);
- file=file.substr(6,file.length());
-
- if (ClassDB::is_parent_class(efsd->get_file_type(i),base_type) && (search_text.is_subsequence_ofi(file))) {
- Pair< String, Ref<Texture> > pair;
- pair.first = file;
- pair.second = get_icon((has_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei);
-
- if (search_text != String() && list.size() > 0) {
-
- float this_sim = _path_cmp(search_text, file);
- float other_sim = _path_cmp(list[0].first, file);
- int pos = 1;
-
- while (pos < list.size() && this_sim <= other_sim) {
- other_sim = _path_cmp(list[pos++].first, file);
- }
-
- pos = this_sim >= other_sim ? pos - 1 : pos;
- list.insert(pos, pair);
-
- } else {
-
- list.push_back(pair);
- }
- }
- }
-
-
- if (add_directories) {
- for(int i=0;i<efsd->get_subdir_count();i++) {
-
- _parse_fs(efsd->get_subdir(i), list);
- }
- }
-
-}
-
-void EditorQuickOpen::_update_search() {
-
- search_options->clear();
- TreeItem *root = search_options->create_item();
- EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem();
- Vector< Pair< String, Ref<Texture> > > list;
-
- _parse_fs(efsd, list);
-
- for (int i = 0; i < list.size(); i++) {
- TreeItem *ti = search_options->create_item(root);
- ti->set_text(0, list[i].first);
- ti->set_icon(0, list[i].second);
- }
-
- 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);
-
-}
-
-void EditorQuickOpen::_confirmed() {
-
- TreeItem *ti = search_options->get_selected();
- if (!ti)
- return;
- emit_signal("quick_open");
- hide();
-}
-
-void EditorQuickOpen::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- connect("confirmed",this,"_confirmed");
- }
-}
-
-
-StringName EditorQuickOpen::get_base_type() const {
-
- return base_type;
-}
-
-void EditorQuickOpen::_bind_methods() {
-
- ClassDB::bind_method(_MD("_text_changed"),&EditorQuickOpen::_text_changed);
- ClassDB::bind_method(_MD("_confirmed"),&EditorQuickOpen::_confirmed);
- ClassDB::bind_method(_MD("_sbox_input"),&EditorQuickOpen::_sbox_input);
-
- ADD_SIGNAL(MethodInfo("quick_open"));
-
-}
-
-
-EditorQuickOpen::EditorQuickOpen() {
-
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- add_child(vbc);
- //set_child_rect(vbc);
- search_box = memnew( LineEdit );
- vbc->add_margin_child(TTR("Search:"),search_box);
- search_box->connect("text_changed",this,"_text_changed");
- search_box->connect("gui_input",this,"_sbox_input");
- search_options = memnew( Tree );
- vbc->add_margin_child(TTR("Matches:"),search_options,true);
- get_ok()->set_text(TTR("Open"));
- get_ok()->set_disabled(true);
- register_text_enter(search_box);
- set_hide_on_ok(false);
- search_options->connect("item_activated",this,"_confirmed");
- search_options->set_hide_root(true);
- ei="EditorIcons";
- ot="Object";
- add_directories=false;
-}
diff --git a/tools/editor/reparent_dialog.h b/tools/editor/reparent_dialog.h
deleted file mode 100644
index 5e21f84581..0000000000
--- a/tools/editor/reparent_dialog.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*************************************************************************/
-/* reparent_dialog.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 REPARENT_DIALOG_H
-#define REPARENT_DIALOG_H
-
-#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"
-/**
-@author Juan Linietsky <reduzio@gmail.com>
-*/
-class ReparentDialog : public ConfirmationDialog {
-
- GDCLASS( ReparentDialog, ConfirmationDialog );
-
- SceneTreeEditor *tree;
- CheckBox *keep_transform;
-
-
- void update_tree();
- void _reparent();
- void _cancel();
-
-
-protected:
-
- void _notification(int p_what);
- static void _bind_methods();
-public:
-
- void set_current(const Set<Node*>& p_selection);
- String get_selected_type();
-
- ReparentDialog();
- ~ReparentDialog();
-
-};
-
-#endif
diff --git a/tools/editor/resources_dock.cpp b/tools/editor/resources_dock.cpp
deleted file mode 100644
index e89262db25..0000000000
--- a/tools/editor/resources_dock.cpp
+++ /dev/null
@@ -1,409 +0,0 @@
-/*************************************************************************/
-/* resources_dock.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "resources_dock.h"
-
-#include "editor_node.h"
-#include "io/resource_loader.h"
-#include "io/resource_saver.h"
-#include "editor_settings.h"
-#include "project_settings.h"
-#include "globals.h"
-#include "editor_file_system.h"
-
-
-void ResourcesDock::_tool_selected(int p_tool) {
-
- current_action=p_tool;
-
- switch(p_tool) {
-
- case TOOL_NEW: {
-
- create_dialog->popup_centered_ratio();
- } break;
- case TOOL_OPEN: {
- editor->open_resource();
-
- } break;
- case TOOL_SAVE: {
-
- TreeItem *ti = resources->get_selected();
- if (!ti)
- break;
- Ref<Resource> current_res = ti->get_metadata(0);
-
-
- if (current_res->get_path()!="" && current_res->get_path().find("::")==-1) {
- _file_action(current_res->get_path());
- break;
- };
-
- }; /* fallthrough */
- case TOOL_SAVE_AS: {
-
- TreeItem *ti = resources->get_selected();
- if (!ti)
- break;
-
- save_resource_as(ti->get_metadata(0));
-
-
- } break;
- case TOOL_MAKE_LOCAL: {
-
- TreeItem *ti = resources->get_selected();
- if (!ti)
- break;
- Ref<Resource> current_res = ti->get_metadata(0);
- current_res->set_path("");
- _update_name(ti);
- } break;
- case TOOL_COPY: {
-
- TreeItem *ti = resources->get_selected();
- if (!ti)
- break;
- Ref<Resource> current_res = ti->get_metadata(0);
- EditorSettings::get_singleton()->set_resource_clipboard(current_res);
-
- } break;
- case TOOL_PASTE: {
-
- add_resource(EditorSettings::get_singleton()->get_resource_clipboard());
- } break;
-
- }
-}
-
-
-
-void ResourcesDock::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
- button_new->set_icon(get_icon("New","EditorIcons"));
- button_open->set_icon(get_icon("Folder","EditorIcons"));
- button_save->set_icon(get_icon("Save","EditorIcons"));
- button_tools->set_icon(get_icon("Tools","EditorIcons"));
-
-
- } break;
- }
-
-}
-
-
-void ResourcesDock::save_resource(const String& p_path,const Ref<Resource>& p_resource) {
-
- editor->get_editor_data().apply_changes_in_editors();
- 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;
- */
-
- String path = GlobalConfig::get_singleton()->localize_path(p_path);
- Error err = ResourceSaver::save(path,p_resource,flg|ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
-
- if (err!=OK) {
- accept->set_text(TTR("Error saving resource!"));
- accept->popup_centered_minsize();
- return;
- }
- //EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
-
- ((Resource*)p_resource.ptr())->set_path(path);
- editor->emit_signal("resource_saved",p_resource);
-
-}
-
-void ResourcesDock::save_resource_as(const Ref<Resource>& p_resource) {
-
- current_action=TOOL_SAVE_AS;
-
- RES res(p_resource);
-
- List<String> extensions;
- ResourceSaver::get_recognized_extensions(res,&extensions);
- file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
-
- if (p_resource->get_path()!="" && p_resource->get_path().find("::")==-1) {
-
- file->set_current_path(p_resource->get_path());
- } else {
-
- String existing;
- if (extensions.size()) {
- existing="new_"+res->get_class().to_lower()+"."+extensions.front()->get().to_lower();
- }
-
- file->set_current_file(existing);
- }
-
- file->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
- file->popup_centered_ratio();
-
-}
-
-void ResourcesDock::_file_action(const String& p_path) {
-
-
- switch(current_action) {
-
- case TOOL_OPEN: {
-
- } break;
- case TOOL_SAVE:
- case TOOL_SAVE_AS: {
-
- TreeItem *ti = resources->get_selected();
- if (!ti)
- break;
- Ref<Resource> current_res = ti->get_metadata(0);
-
- RES res(current_res);
-
- save_resource(p_path,res);
-
- _update_name(ti);
-
- } break;
-
- }
-}
-
-void ResourcesDock::_update_name(TreeItem *item) {
-
- Ref<Resource> res = item->get_metadata(0);
-
-
- if (res->get_name()!="")
- item->set_text(0,res->get_name());
- else if (res->get_path()!="" && res->get_path().find("::")==-1)
- item->set_text(0,res->get_path().get_file());
- else
- item->set_text(0,res->get_class()+" ("+itos(res->get_instance_ID())+")");
-
-}
-
-
-void ResourcesDock::remove_resource(const Ref<Resource>& p_resource) {
-
- TreeItem *root = resources->get_root();
- ERR_FAIL_COND(!root);
-
- TreeItem *existing=root->get_children();
-
- while(existing) {
-
- Ref<Resource> r = existing->get_metadata(0);
- if (r==p_resource) {
- //existing->move_to_top();
- memdelete(existing);
- return;
- }
- existing=existing->get_next();
- }
-
-
-}
-
-void ResourcesDock::add_resource(const Ref<Resource>& p_resource) {
-
- if (block_add)
- return;
- if (!p_resource.is_valid())
- return;
-
- TreeItem *root = resources->get_root();
- ERR_FAIL_COND(!root);
-
- TreeItem *existing=root->get_children();
-
- while(existing) {
-
- Ref<Resource> r = existing->get_metadata(0);
- if (r==p_resource) {
- //existing->move_to_top();
- existing->select(0);
- resources->ensure_cursor_is_visible();
- return; // existing
- }
- existing=existing->get_next();
- }
-
- TreeItem *res = resources->create_item(root);
- res->set_metadata(0,p_resource);
-
- if (has_icon(p_resource->get_class(),"EditorIcons")) {
- res->set_icon(0,get_icon(p_resource->get_class(),"EditorIcons"));
- }
-
- _update_name(res);
- res->add_button(0,get_icon("Del","EditorIcons"));
- res->move_to_top();
- res->select(0);
- resources->ensure_cursor_is_visible();
-
-}
-
-void ResourcesDock::_resource_selected() {
-
- TreeItem *sel = resources->get_selected();
- ERR_FAIL_COND(!sel);
-
-
- Ref<Resource> r = sel->get_metadata(0);
- if (r.is_null())
- return;
- block_add=true;
- editor->push_item(r.ptr());
- block_add=false;
-}
-
-void ResourcesDock::_delete(Object* p_item, int p_column, int p_id) {
-
- TreeItem *ti = p_item->cast_to<TreeItem>();
- ERR_FAIL_COND(!ti);
-
-
- call_deferred("remove_resource",ti->get_metadata(0));
-
-}
-
-void ResourcesDock::_create() {
-
- Object *c = create_dialog->instance_selected();
-
- ERR_FAIL_COND(!c);
- Resource *r = c->cast_to<Resource>();
- ERR_FAIL_COND(!r);
-
- REF res( r );
-
- editor->push_item(c);
-
-}
-
-void ResourcesDock::_bind_methods() {
-
- ClassDB::bind_method(_MD("_tool_selected"),&ResourcesDock::_tool_selected);
- ClassDB::bind_method(_MD("_create"),&ResourcesDock::_create);
- ClassDB::bind_method(_MD("_resource_selected"),&ResourcesDock::_resource_selected);
- ClassDB::bind_method(_MD("_delete"),&ResourcesDock::_delete);
- ClassDB::bind_method(_MD("remove_resource"),&ResourcesDock::remove_resource);
- ClassDB::bind_method(_MD("_file_action"),&ResourcesDock::_file_action);
-
-
-
-}
-
-void ResourcesDock::cleanup() {
-
-
- resources->clear();
- resources->create_item(); //root
-
-}
-
-
-ResourcesDock::ResourcesDock(EditorNode *p_editor) {
-
- editor=p_editor;
-
- VBoxContainer *vbc = this;
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- vbc->add_child(hbc);
-
-
- Button *b;
- b = memnew( ToolButton );
- b->set_tooltip(TTR("Create New Resource"));
- b->connect("pressed",this,"_tool_selected",make_binds(TOOL_NEW));
- hbc->add_child( b );
- button_new=b;
-
- b = memnew( ToolButton );
- b->set_tooltip(TTR("Open Resource"));
- b->connect("pressed",this,"_tool_selected",make_binds(TOOL_OPEN));
- hbc->add_child( b );
- button_open=b;
-
- MenuButton *mb = memnew( MenuButton );
- mb->set_tooltip(TTR("Save Resource"));
- mb->get_popup()->add_item(TTR("Save Resource"),TOOL_SAVE);
- mb->get_popup()->add_item(TTR("Save Resource As.."),TOOL_SAVE_AS);
- mb->get_popup()->connect("id_pressed",this,"_tool_selected" );
- hbc->add_child( mb );
- button_save=mb;
-
- hbc->add_spacer();
-
- mb = memnew( MenuButton );
- mb->set_tooltip(TTR("Resource Tools"));
- mb->get_popup()->add_item(TTR("Make Local"),TOOL_MAKE_LOCAL);
- mb->get_popup()->add_item(TTR("Copy"),TOOL_COPY);
- mb->get_popup()->add_item(TTR("Paste"),TOOL_PASTE);
- mb->get_popup()->connect("id_pressed",this,"_tool_selected" );
- hbc->add_child( mb );
- button_tools=mb;
-
- resources = memnew( Tree );
- vbc->add_child(resources);
- resources->set_v_size_flags(SIZE_EXPAND_FILL);
- resources->create_item(); //root
- resources->set_hide_root(true);
- resources->connect("cell_selected",this,"_resource_selected");
- resources->connect("button_pressed",this,"_delete");
-
- create_dialog = memnew( CreateDialog );
- add_child(create_dialog);
- create_dialog->set_base_type("Resource");
- create_dialog->connect("create",this,"_create");
- accept = memnew (AcceptDialog);
- add_child(accept);
-
- file = memnew( EditorFileDialog );
- add_child(file);
- file->connect("file_selected",this,"_file_action");
-
-
- block_add=false;
-}
-
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
deleted file mode 100644
index ae7a80377d..0000000000
--- a/tools/editor/scene_tree_dock.cpp
+++ /dev/null
@@ -1,2057 +0,0 @@
-/*************************************************************************/
-/* scene_tree_dock.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "scene_tree_dock.h"
-
-#include "editor_node.h"
-#include "globals.h"
-#include "os/keyboard.h"
-#include "scene/resources/packed_scene.h"
-#include "editor_settings.h"
-#include "tools/editor/plugins/canvas_item_editor_plugin.h"
-#include "tools/editor/plugins/spatial_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"
-#include "scene/main/viewport.h"
-
-
-void SceneTreeDock::_nodes_drag_begin() {
-
-
- if (restore_script_editor_on_drag) {
- EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
- restore_script_editor_on_drag=false;
- }
-
-}
-
-void SceneTreeDock::_input(InputEvent p_event) {
-
- if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==BUTTON_LEFT) {
- restore_script_editor_on_drag=false; //lost chance
- }
-}
-
-void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
-
- if (get_viewport()->get_modal_stack_top())
- return; //ignore because of modal window
-
- if (!p_event.key.pressed || p_event.key.echo)
- return;
-
- if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
- _tool_selected(TOOL_NEW);
- }
- else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) {
- _tool_selected(TOOL_INSTANCE);
- }
- else if (ED_IS_SHORTCUT("scene_tree/change_node_type", p_event)) {
- _tool_selected(TOOL_REPLACE);
- }
- else if (ED_IS_SHORTCUT("scene_tree/duplicate", p_event)) {
- _tool_selected(TOOL_DUPLICATE);
- }
- else if (ED_IS_SHORTCUT("scene_tree/attach_script", p_event)) {
- _tool_selected(TOOL_ATTACH_SCRIPT);
- }
- else if(ED_IS_SHORTCUT("scene_tree/clear_script", p_event)) {
- _tool_selected(TOOL_CLEAR_SCRIPT);
- }
- else if (ED_IS_SHORTCUT("scene_tree/move_up", p_event)) {
- _tool_selected(TOOL_MOVE_UP);
- }
- else if (ED_IS_SHORTCUT("scene_tree/move_down", p_event)) {
- _tool_selected(TOOL_MOVE_DOWN);
- }
- else if (ED_IS_SHORTCUT("scene_tree/reparent", p_event)) {
- _tool_selected(TOOL_REPARENT);
- }
- else if (ED_IS_SHORTCUT("scene_tree/merge_from_scene", p_event)) {
- _tool_selected(TOOL_MERGE_FROM_SCENE);
- }
- else if (ED_IS_SHORTCUT("scene_tree/save_branch_as_scene", p_event)) {
- _tool_selected(TOOL_NEW_SCENE_FROM);
- }
- else if (ED_IS_SHORTCUT("scene_tree/delete_no_confirm", p_event)) {
- _tool_selected(TOOL_ERASE, true);
- }
- else if(ED_IS_SHORTCUT("scene_tree/copy_node_path", p_event)) {
- _tool_selected(TOOL_COPY_NODE_PATH);
- }
- else if (ED_IS_SHORTCUT("scene_tree/delete", p_event)) {
- _tool_selected(TOOL_ERASE);
- }
-}
-
-void SceneTreeDock::instance(const String& p_file) {
-
- Node *parent = scene_tree->get_selected();
- if (!parent || !edited_scene) {
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("OK :("));
- accept->set_text(TTR("No parent to instance a child at."));
- accept->popup_centered_minsize();
- return;
- };
-
- ERR_FAIL_COND(!parent);
-
- Vector<String> scenes;
- scenes.push_back(p_file);
- _perform_instance_scenes(scenes,parent,-1);
-
-}
-
-void SceneTreeDock::instance_scenes(const Vector<String>& p_files, Node *p_parent) {
-
- Node *parent = p_parent;
-
- if (!parent) {
- parent = scene_tree->get_selected();
- }
-
- if (!parent || !edited_scene) {
-
- accept->get_ok()->set_text(TTR("OK"));
- accept->set_text(TTR("No parent to instance the scenes at."));
- accept->popup_centered_minsize();
- return;
- };
-
- _perform_instance_scenes(p_files, parent, -1);
-}
-
-void SceneTreeDock::_perform_instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos) {
-
-
-
- ERR_FAIL_COND(!parent);
-
-
- Vector<Node*> instances;
-
- bool error=false;
-
- for(int i=0;i<p_files.size();i++) {
-
- Ref<PackedScene> sdata = ResourceLoader::load(p_files[i]);
- if (!sdata.is_valid()) {
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(vformat(TTR("Error loading scene from %s"),p_files[i]));
- accept->popup_centered_minsize();
- error=true;
- break;
-
- }
-
- Node*instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instanced_scene) {
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(vformat(TTR("Error instancing scene from %s"),p_files[i]));
- accept->popup_centered_minsize();
- error=true;
- break;
-
- }
-
- if (edited_scene->get_filename()!="") {
-
- if (_cyclical_dependency_exists(edited_scene->get_filename(), instanced_scene)) {
-
- accept->get_ok()->set_text(TTR("Ok"));
- accept->set_text(vformat(TTR("Cannot instance the scene '%s' because the current scene exists within one of its nodes."),p_files[i]));
- accept->popup_centered_minsize();
- error=true;
- break;
- }
- }
-
- instanced_scene->set_filename( GlobalConfig::get_singleton()->localize_path(p_files[i]) );
-
- instances.push_back(instanced_scene);
- }
-
- if (error) {
- for(int i=0;i<instances.size();i++) {
- memdelete(instances[i]);
- }
- return;
- }
-
-
-
- //instanced_scene->generate_instance_state();
-
- editor_data->get_undo_redo().create_action(TTR("Instance Scene(s)"));
-
- for(int i=0;i<instances.size();i++) {
-
- Node* instanced_scene=instances[i];
-
- editor_data->get_undo_redo().add_do_method(parent,"add_child",instanced_scene);
- if (p_pos>=0) {
- editor_data->get_undo_redo().add_do_method(parent,"move_child",instanced_scene,p_pos+i);
- }
- editor_data->get_undo_redo().add_do_method(instanced_scene,"set_owner",edited_scene);
- editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
- editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",instanced_scene);
- editor_data->get_undo_redo().add_do_reference(instanced_scene);
- editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene);
-
- String new_name = parent->validate_child_name(instanced_scene);
- ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
- editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",edited_scene->get_path_to(parent),p_files[i],new_name);
- editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name));
- }
-
- editor_data->get_undo_redo().commit_action();
-
-
-}
-
-void SceneTreeDock::_replace_with_branch_scene(const String& p_file,Node* base) {
- Ref<PackedScene> sdata = ResourceLoader::load(p_file);
- if (!sdata.is_valid()) {
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(vformat(TTR("Error loading scene from %s"),p_file));
- accept->popup_centered_minsize();
- return;
- }
-
- Node *instanced_scene=sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instanced_scene) {
- accept->get_ok()->set_text(TTR("Ugh"));
- accept->set_text(vformat(TTR("Error instancing scene from %s"),p_file));
- accept->popup_centered_minsize();
- return;
- }
-
- Node *parent = base->get_parent();
- int pos = base->get_index();
- memdelete(base);
- parent->add_child(instanced_scene);
- parent->move_child(instanced_scene, pos);
- instanced_scene->set_owner(edited_scene);
- editor_selection->clear();
- editor_selection->add_node(instanced_scene);
- scene_tree->set_selected(instanced_scene);
-}
-
-bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) {
- int childCount = p_desired_node->get_child_count();
-
- if (p_desired_node->get_filename()==p_target_scene_path) {
- return true;
- }
-
- for (int i=0;i<childCount;i++) {
- Node* child=p_desired_node->get_child(i);
-
- if(_cyclical_dependency_exists(p_target_scene_path,child)) {
- return true;
- }
- }
-
- return false;
-}
-
-
-void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
-
- current_option=p_tool;
-
- switch(p_tool) {
-
- case TOOL_NEW: {
- /*
- if (!_validate_no_foreign())
- break;
- */
- create_dialog->popup(true);
- } break;
- case TOOL_INSTANCE: {
-
- Node *scene = edited_scene;
-
- if (!scene) {
-
- EditorNode::get_singleton()->new_inherited_scene();
-
- /* should be legal now
- 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 tree root.");
- accept->popup_centered_minsize();
- */
- break;
- }
-
- /*
- if (!_validate_no_foreign())
- break;
- */
-
- file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
- List<String> extensions;
- ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);
- file->clear_filters();
- for(int i=0;i<extensions.size();i++) {
-
- file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper());
- }
-
- //file->set_current_path(current_path);
- file->popup_centered_ratio();
-
- } break;
- case TOOL_REPLACE: {
-
- create_dialog->popup(false);
- } break;
- case TOOL_CONNECT: {
-
- Node *current = scene_tree->get_selected();
- if (!current)
- break;
-
- /*
- if (!_validate_no_foreign())
- break;
- connect_dialog->popup_centered_ratio();
- connect_dialog->set_node(current);
- */
-
- } break;
- case TOOL_GROUP: {
-
- Node *current = scene_tree->get_selected();
- if (!current)
- break;
- /*
- if (!_validate_no_foreign())
- break;
- groups_editor->set_current(current);
- groups_editor->popup_centered_ratio();
- */
- } break;
- case TOOL_ATTACH_SCRIPT: {
-
- Node *selected = scene_tree->get_selected();
- if (!selected)
- break;
-
- /*
- if (!_validate_no_foreign())
- break;
- */
-
- Ref<Script> existing = selected->get_script();
- if (existing.is_valid())
- editor->push_item(existing.ptr());
- else {
- String path = selected->get_filename();
- script_create_dialog->config(selected->get_class(),path);
- script_create_dialog->popup_centered(Size2(300,290));
- //script_create_dialog->popup_centered_minsize();
-
- }
-
- } break;
- case TOOL_CLEAR_SCRIPT: {
- Node *selected = scene_tree->get_selected();
- if(!selected)
- break;
-
- Ref<Script> existing = selected->get_script();
- if(existing.is_valid()) {
- const RefPtr empty;
- selected->set_script(empty);
- }
-
- } break;
- case TOOL_MOVE_UP:
- case TOOL_MOVE_DOWN: {
-
- if (!scene_tree->get_selected())
- break;
-
-
- if (scene_tree->get_selected()==edited_scene) {
-
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("This operation can't be done on the tree root."));
- accept->popup_centered_minsize();
- break;
- }
-
-
- if (!_validate_no_foreign())
- break;
-
- bool MOVING_DOWN = (p_tool == TOOL_MOVE_DOWN);
- bool MOVING_UP = !MOVING_DOWN;
-
- Node *common_parent = scene_tree->get_selected()->get_parent();
- List<Node*> selection = editor_selection->get_selected_node_list();
- selection.sort_custom<Node::Comparator>(); // sort by index
- if (MOVING_DOWN)
- selection.invert();
-
- int lowest_id = common_parent->get_child_count() - 1;
- int highest_id = 0;
- for (List<Node*>::Element *E = selection.front(); E; E = E->next()) {
- int index = E->get()->get_index();
-
- if (index > highest_id) highest_id = index;
- if (index < lowest_id) lowest_id = index;
-
- if (E->get()->get_parent() != common_parent)
- common_parent = NULL;
- }
-
- if (!common_parent || (MOVING_DOWN && highest_id >= common_parent->get_child_count() - MOVING_DOWN) || (MOVING_UP && lowest_id == 0))
- break; // one or more nodes can not be moved
-
- if (selection.size() == 1) editor_data->get_undo_redo().create_action(TTR("Move Node In Parent"));
- if (selection.size() > 1) editor_data->get_undo_redo().create_action(TTR("Move Nodes In Parent"));
-
- for (int i = 0; i < selection.size(); i++) {
- Node *top_node = selection[i];
- Node *bottom_node = selection[selection.size() - 1 - i];
-
- ERR_FAIL_COND(!top_node->get_parent());
- ERR_FAIL_COND(!bottom_node->get_parent());
-
- int bottom_node_pos = bottom_node->get_index();
- int top_node_pos_next = top_node->get_index() + (MOVING_DOWN ? 1 : -1);
-
- editor_data->get_undo_redo().add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next);
- editor_data->get_undo_redo().add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos);
- }
-
- editor_data->get_undo_redo().commit_action();
-
- } break;
- case TOOL_DUPLICATE: {
-
- if (!edited_scene)
- break;
-
-
- if (editor_selection->is_selected(edited_scene)) {
-
-
- current_option=-1;
- //accept->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("This operation can't be done on the tree root."));
- accept->popup_centered_minsize();
- break;
- }
-
- if (!_validate_no_foreign())
- break;
-
- List<Node*> selection = editor_selection->get_selected_node_list();
- if (selection.size()==0)
- break;
-
- List<Node*> reselect;
-
- editor_data->get_undo_redo().create_action(TTR("Duplicate Node(s)"));
- editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
-
- Node *dupsingle=NULL;
-
-
- for (List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- Node *node = E->get();
- Node *parent = node->get_parent();
-
- List<Node*> owned;
- node->get_owned_by(node->get_owner(),&owned);
-
- Map<Node*,Node*> duplimap;
- Node * dup = _duplicate(node,duplimap);
-
- ERR_CONTINUE(!dup);
-
- if (selection.size()==1)
- dupsingle=dup;
-
- dup->set_name(parent->validate_child_name(dup));
-
- editor_data->get_undo_redo().add_do_method(parent,"_add_child_below_node",node, dup);
- for (List<Node*>::Element *F=owned.front();F;F=F->next()) {
-
- if (!duplimap.has(F->get())) {
-
- continue;
- }
- Node *d=duplimap[F->get()];
- 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_do_reference(dup);
-
- ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
-
- editor_data->get_undo_redo().add_do_method(sed,"live_debug_duplicate_node",edited_scene->get_path_to(node),dup->get_name());
- editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+dup->get_name()));
-
- //parent->add_child(dup);
- //reselect.push_back(dup);
- }
-
- editor_data->get_undo_redo().commit_action();
-
- if (dupsingle)
- editor->push_item(dupsingle);
-
-
-
-
-
- } break;
- case TOOL_REPARENT: {
-
-
- if (!scene_tree->get_selected())
- break;
-
-
- if (editor_selection->is_selected(edited_scene)) {
-
-
- current_option=-1;
- //confirmation->get_cancel()->hide();
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("This operation can't be done on the tree root."));
- accept->popup_centered_minsize();
- break;
- }
-
- if (!_validate_no_foreign())
- break;
-
- List<Node*> nodes = editor_selection->get_selected_node_list();
- Set<Node*> nodeset;
- for(List<Node*>::Element *E=nodes.front();E;E=E->next()) {
-
- nodeset.insert(E->get());
- }
- reparent_dialog->popup_centered_ratio();
- reparent_dialog->set_current( nodeset );
-
- } break;
- case TOOL_MULTI_EDIT: {
-
- Node*root=EditorNode::get_singleton()->get_edited_scene();
- if (!root)
- break;
- Ref<MultiNodeEdit> mne = memnew( MultiNodeEdit );
- for (const Map<Node*,Object*>::Element *E=EditorNode::get_singleton()->get_editor_selection()->get_selection().front();E;E=E->next()) {
- mne->add_node(root->get_path_to(E->key()));
- }
-
- EditorNode::get_singleton()->push_item(mne.ptr());
-
- } break;
-
- case TOOL_ERASE: {
-
- List<Node*> remove_list = editor_selection->get_selected_node_list();
-
- if (remove_list.empty())
- return;
-
- if (!_validate_no_foreign())
- break;
-
- if (p_confirm_override) {
- _delete_confirm();
-
- // hack, force 2d editor viewport to refresh after deletion
- if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton())
- editor->get_viewport_control()->update();
-
- } else {
- delete_dialog->set_text(TTR("Delete Node(s)?"));
- delete_dialog->popup_centered_minsize();
- }
-
- } break;
- case TOOL_MERGE_FROM_SCENE: {
-
- EditorNode::get_singleton()->merge_from_scene();
- } break;
- case TOOL_NEW_SCENE_FROM: {
-
- Node *scene = editor_data->get_edited_scene_root();
-
- if (!scene) {
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("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(TTR("I see.."));
- accept->set_text(TTR("This operation requires a single selected node."));
- accept->popup_centered_minsize();
- break;
- }
-
- Node *tocopy = selection.front()->get();
-
- if (tocopy==scene){
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Can not perform with the root node."));
- accept->popup_centered_minsize();
- break;
- }
-
- if (tocopy!=editor_data->get_edited_scene_root() && tocopy->get_filename()!="") {
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("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()) {
- String root_name(tocopy->get_name());
- existing=root_name+"."+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(TTR("Save New Scene As.."));
-
- } break;
- case TOOL_COPY_NODE_PATH: {
- List<Node*> selection = editor_selection->get_selected_node_list();
-
- if(List<Node*>::Element *e = selection.front()) {
- if(Node *node = e->get()) {
- Node *root = EditorNode::get_singleton()->get_edited_scene();
- NodePath path = root->get_path().rel_path_to(node->get_path());
- OS::get_singleton()->set_clipboard(path);
- }
- }
- } break;
- }
-
-}
-
-void SceneTreeDock::_notification(int p_what) {
-
- switch(p_what) {
-
- case NOTIFICATION_READY: {
-
- if (!first_enter)
- break;
- first_enter=false;
-
- CanvasItemEditorPlugin *canvas_item_plugin = editor_data->get_editor("2D")->cast_to<CanvasItemEditorPlugin>();
- if (canvas_item_plugin) {
- canvas_item_plugin->get_canvas_item_editor()->connect("item_lock_status_changed", scene_tree, "_update_tree");
- canvas_item_plugin->get_canvas_item_editor()->connect("item_group_status_changed", scene_tree, "_update_tree");
- scene_tree->connect("node_changed", canvas_item_plugin->get_canvas_item_editor()->get_viewport_control(), "update");
- }
- button_add->set_icon(get_icon("Add","EditorIcons"));
- button_instance->set_icon(get_icon("Instance","EditorIcons"));
- button_create_script->set_icon(get_icon("ScriptCreate","EditorIcons"));
- button_clear_script->set_icon(get_icon("ScriptRemove", "EditorIcons"));
-
-
- filter_icon->set_texture(get_icon("Zoom","EditorIcons"));
-
- EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed",this,"_selection_changed");
-
- } break;
- }
-}
-
-
-void SceneTreeDock::_load_request(const String& p_path) {
-
- editor->open_request(p_path);
-}
-
-void SceneTreeDock::_script_open_request(const Ref<Script>& p_script) {
-
- editor->edit_resource(p_script);
-}
-
-void SceneTreeDock::_node_selected() {
-
-
- Node *node=scene_tree->get_selected();
-
- if (!node) {
-
- editor->push_item(NULL);
- return;
- }
-
- if (ScriptEditor::get_singleton()->is_visible_in_tree()) {
- restore_script_editor_on_drag=true;
- }
-
- editor->push_item(node);
-
-
-}
-
-void SceneTreeDock::_node_renamed() {
-
- _node_selected();
-}
-
-Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node*,Node*> &duplimap) {
-
- Node *node=NULL;
-
- if (p_node->get_filename()!="") { //an instance
-
- Ref<PackedScene> sd = ResourceLoader::load( p_node->get_filename() );
- ERR_FAIL_COND_V(!sd.is_valid(),NULL);
- node = sd->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- ERR_FAIL_COND_V(!node,NULL);
- node->set_scene_instance_load_placeholder(p_node->get_scene_instance_load_placeholder());
- //node->generate_instance_state();
- } else {
- Object *obj = ClassDB::instance(p_node->get_class());
- ERR_FAIL_COND_V(!obj,NULL);
- node = obj->cast_to<Node>();
- if (!node)
- memdelete(obj);
- ERR_FAIL_COND_V(!node,NULL);
-
- }
-
- List<PropertyInfo> plist;
-
- p_node->get_property_list(&plist);
-
- for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
-
- if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
- continue;
- String name = E->get().name;
- node->set( name, p_node->get(name) );
-
- }
-
-
- List<Node::GroupInfo> group_info;
- p_node->get_groups(&group_info);
- for (List<Node::GroupInfo>::Element *E=group_info.front();E;E=E->next()) {
-
- if (E->get().persistent)
- node->add_to_group(E->get().name,true);
- }
-
-
- node->set_name(p_node->get_name());
- duplimap[p_node]=node;
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- Node *child = p_node->get_child(i);
- if (p_node->get_owner()!=child->get_owner())
- continue; //don't bother with not in-scene nodes.
-
- Node *dup = _duplicate(child,duplimap);
- if (!dup) {
- memdelete(node);
- return NULL;
- }
-
- node->add_child(dup);
- }
-
- return node;
-
-}
-
-
-void SceneTreeDock::_set_owners(Node *p_owner, const Array& p_nodes) {
-
- for(int i=0;i<p_nodes.size();i++) {
-
- Object *obj=p_nodes[i];
- if (!obj)
- continue;
-
- Node *n=obj->cast_to<Node>();
- if (!n)
- continue;
- n->set_owner(p_owner);
- }
-}
-
-
-void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path,Vector<StringName> new_base_path,Node * p_node, List<Pair<NodePath,NodePath> > *p_renames) {
-
- base_path.push_back(p_node->get_name());
- if (new_base_path.size())
- new_base_path.push_back(p_node->get_name());
-
- NodePath from( base_path,true );
- NodePath to;
- if (new_base_path.size())
- to=NodePath( new_base_path,true );
-
- Pair<NodePath,NodePath> npp;
- npp.first=from;
- npp.second=to;
-
- p_renames->push_back(npp);
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- _fill_path_renames(base_path,new_base_path,p_node->get_child(i),p_renames);
- }
-
-
-}
-
-void SceneTreeDock::fill_path_renames(Node* p_node, Node *p_new_parent, List<Pair<NodePath,NodePath> > *p_renames) {
-
- if (!bool(EDITOR_DEF("editors/animation/autorename_animation_tracks",true)))
- return;
-
-
- Vector<StringName> base_path;
- Node *n = p_node->get_parent();
- while(n) {
- base_path.push_back(n->get_name());
- n=n->get_parent();
- }
- base_path.invert();
-
- Vector<StringName> new_base_path;
- if (p_new_parent) {
- n = p_new_parent;
- while(n) {
- new_base_path.push_back(n->get_name());
- n=n->get_parent();
- }
-
- new_base_path.invert();
- }
-
- _fill_path_renames(base_path,new_base_path,p_node,p_renames);
-}
-
-void SceneTreeDock::perform_node_renames(Node* p_base,List<Pair<NodePath,NodePath> > *p_renames, Map<Ref<Animation>, Set<int> > *r_rem_anims) {
-
- Map<Ref<Animation>, Set<int> > rem_anims;
-
- if (!r_rem_anims)
- r_rem_anims=&rem_anims;
-
- if (!bool(EDITOR_DEF("editors/animation/autorename_animation_tracks",true)))
- return;
-
- if (!p_base) {
-
- p_base=edited_scene;
- }
-
- if (!p_base)
- return;
-
-
- if (p_base->cast_to<AnimationPlayer>()) {
-
- AnimationPlayer *ap=p_base->cast_to<AnimationPlayer>();
- List<StringName> anims;
- ap->get_animation_list(&anims);
- Node *root = ap->get_node(ap->get_root());
-
-
- if (root) {
-
-
- NodePath root_path=root->get_path();
- NodePath new_root_path=root_path;
-
-
- for(List<Pair<NodePath,NodePath> >::Element* E=p_renames->front();E;E=E->next()) {
-
- if (E->get().first==root_path) {
- new_root_path=E->get().second;
- break;
- }
- }
-
- if (new_root_path!=NodePath()) {
- //will not be erased
-
- for(List<StringName>::Element *E=anims.front();E;E=E->next()) {
-
- Ref<Animation> anim=ap->get_animation(E->get());
- if (!r_rem_anims->has(anim)) {
- r_rem_anims->insert(anim,Set<int>());
- Set<int> &ran = r_rem_anims->find(anim)->get();
- for(int i=0;i<anim->get_track_count();i++)
- ran.insert(i);
- }
-
- Set<int> &ran = r_rem_anims->find(anim)->get();
-
- if (anim.is_null())
- continue;
-
- for(int i=0;i<anim->get_track_count();i++) {
-
- NodePath track_np=anim->track_get_path(i);
- Node *n = root->get_node(track_np);
- if (!n) {
- continue;
- }
-
- NodePath old_np = n->get_path();
-
- if (!ran.has(i))
- continue; //channel was removed
-
- for(List<Pair<NodePath,NodePath> >::Element* E=p_renames->front();E;E=E->next()) {
-
- if (E->get().first==old_np) {
-
-
- if (E->get().second==NodePath()) {
- //will be erased
-
- int idx=0;
- Set<int>::Element *EI=ran.front();
- ERR_FAIL_COND(!EI); //bug
- while(EI->get()!=i) {
- idx++;
- EI=EI->next();
- ERR_FAIL_COND(!EI); //another bug
-
- }
-
- editor_data->get_undo_redo().add_do_method(anim.ptr(),"remove_track",idx);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(),"add_track",anim->track_get_type(i),idx);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_path",idx,track_np);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_interpolation_type",idx,anim->track_get_interpolation_type(i));
- for(int j=0;j<anim->track_get_key_count(i);j++) {
-
- editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_insert_key",idx,anim->track_get_key_time(i,j),anim->track_get_key_value(i,j),anim->track_get_key_transition(i,j));
- }
-
- ran.erase(i); //byebye channel
-
- } else {
- //will be renamed
- NodePath rel_path = new_root_path.rel_path_to(E->get().second);
-
- NodePath new_path = NodePath( rel_path.get_names(), track_np.get_subnames(), false, track_np.get_property() );
- if (new_path==track_np)
- continue; //bleh
- editor_data->get_undo_redo().add_do_method(anim.ptr(),"track_set_path",i,new_path);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_path",i,track_np);
- }
- }
- }
- }
- }
- }
- }
- }
-
-
- for(int i=0;i<p_base->get_child_count();i++)
- perform_node_renames(p_base->get_child(i),p_renames,r_rem_anims);
-
-}
-
-
-void SceneTreeDock::_node_prerenamed(Node* p_node, const String& p_new_name) {
-
-
- List<Pair<NodePath,NodePath> > path_renames;
-
- Vector<StringName> base_path;
- Node *n = p_node->get_parent();
- while(n) {
- base_path.push_back(n->get_name());
- n=n->get_parent();
- }
- base_path.invert();
-
-
- Vector<StringName> new_base_path=base_path;
- base_path.push_back(p_node->get_name());
-
- new_base_path.push_back(p_new_name);
-
- Pair<NodePath,NodePath> npp;
- npp.first = NodePath(base_path,true);
- npp.second = NodePath(new_base_path,true);
- path_renames.push_back(npp);
-
-
- for(int i=0;i<p_node->get_child_count();i++)
- _fill_path_renames(base_path,new_base_path,p_node->get_child(i),&path_renames);
-
- perform_node_renames(NULL,&path_renames);
-
-}
-
-bool SceneTreeDock::_validate_no_foreign() {
-
- List<Node*> selection = editor_selection->get_selected_node_list();
-
- for (List<Node*>::Element *E=selection.front();E;E=E->next()) {
-
- if (E->get()!=edited_scene && E->get()->get_owner()!=edited_scene) {
-
- accept->get_ok()->set_text(TTR("Makes Sense!"));
- accept->set_text(TTR("Can't operate on nodes from a foreign scene!"));
- accept->popup_centered_minsize();
- return false;
-
- }
-
- 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(TTR("Makes Sense!"));
- accept->set_text(TTR("Can't operate on nodes the current scene inherits from!"));
- accept->popup_centered_minsize();
- return false;
-
- }
-
- }
-
- return true;
-}
-
-void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
-
-
- Node *new_parent = scene_root->get_node(p_path);
- ERR_FAIL_COND(!new_parent);
-
- //ok all valid
-
- List<Node*> selection = editor_selection->get_selected_node_list();
-
- if (selection.empty())
- return; //nothing to reparent
-
- Vector<Node*> nodes;
-
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
- nodes.push_back(E->get());
- }
-
- _do_reparent(new_parent,-1,nodes,p_keep_global_xform);
-
-}
-
-
-void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vector<Node*> p_nodes,bool p_keep_global_xform) {
-
-
- Node *new_parent = p_new_parent;
- ERR_FAIL_COND(!new_parent);
-
- Node *validate=new_parent;
- while(validate) {
-
- if (p_nodes.find(validate)!=-1) {
- ERR_EXPLAIN("Selection changed at some point.. can't reparent");
- ERR_FAIL();
- return;
- }
- validate=validate->get_parent();
- }
-
- //ok all valid
-
- List<Node*> selection = editor_selection->get_selected_node_list();
-
- if (p_nodes.size()==0)
- return; //nothing to reparent
-
- //sort by tree order, so re-adding is easy
- p_nodes.sort_custom<Node::Comparator>();
-
- editor_data->get_undo_redo().create_action(TTR("Reparent Node"));
-
- List<Pair<NodePath,NodePath> > path_renames;
- Vector<StringName> former_names;
-
- int inc=0;
-
- for(int ni=0;ni<p_nodes.size();ni++) {
-
- //no undo for now, sorry
- Node *node = p_nodes[ni];
-
- fill_path_renames(node,new_parent,&path_renames);
- former_names.push_back(node->get_name());
-
- List<Node*> owned;
- node->get_owned_by(node->get_owner(),&owned);
- Array owners;
- for(List<Node*>::Element *E=owned.front();E;E=E->next()) {
-
- owners.push_back(E->get());
- }
-
-
- if (new_parent==node->get_parent() && node->get_index() < p_position_in_parent+ni) {
- //if child will generate a gap when moved, adjust
- inc--;
- }
-
- editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node);
- editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node);
-
- if (p_position_in_parent>=0)
- editor_data->get_undo_redo().add_do_method(new_parent,"move_child",node,p_position_in_parent+inc);
-
- ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
- String new_name = new_parent->validate_child_name(node);
- 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>())
- 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 (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);
- editor_data->get_undo_redo().add_undo_method(node,"set_name",former_names[ni]);
-
- inc++;
-
- }
-
- //add and move in a second step.. (so old order is preserved)
-
-
-
- for(int ni=0;ni<p_nodes.size();ni++) {
-
- Node *node = p_nodes[ni];
-
- List<Node*> owned;
- node->get_owned_by(node->get_owner(),&owned);
- Array owners;
- for(List<Node*>::Element *E=owned.front();E;E=E->next()) {
-
- owners.push_back(E->get());
- }
-
- int child_pos = node->get_position_in_parent();
-
- 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 (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>())
- editor_data->get_undo_redo().add_undo_method(node,"set_pos",node->cast_to<Control>()->get_pos());
- }
-
-
-
- }
-
- perform_node_renames(NULL,&path_renames);
-
- editor_data->get_undo_redo().commit_action();
- //node->set_owner(owner);
-}
-
-void SceneTreeDock::_script_created(Ref<Script> p_script) {
-
- Node *selected = scene_tree->get_selected();
- if (!selected)
- return;
- selected->set_script(p_script.get_ref_ptr());
- editor->push_item(p_script.operator->());
-
-}
-
-
-void SceneTreeDock::_delete_confirm() {
-
- List<Node*> remove_list = editor_selection->get_selected_node_list();
-
- if (remove_list.empty())
- return;
-
-
- editor->get_editor_plugins_over()->make_visible(false);
-
- editor_data->get_undo_redo().create_action(TTR("Remove Node(s)"));
-
- bool entire_scene=false;
-
- for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
-
- if (E->get()==edited_scene) {
- entire_scene=true;
- }
- }
-
- if (entire_scene) {
-
- editor_data->get_undo_redo().add_do_method(editor,"set_edited_scene",(Object*)NULL);
- editor_data->get_undo_redo().add_undo_method(editor,"set_edited_scene",edited_scene);
- editor_data->get_undo_redo().add_undo_method(edited_scene,"set_owner",edited_scene->get_owner());
- editor_data->get_undo_redo().add_undo_reference(edited_scene);
-
- } else {
-
- remove_list.sort_custom<Node::Comparator>(); //sort nodes to keep positions
- List<Pair<NodePath,NodePath> > path_renames;
-
-
- //delete from animation
- for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
- Node *n = E->get();
- if (!n->is_inside_tree() || !n->get_parent())
- continue;
-
- fill_path_renames(n,NULL,&path_renames);
-
- }
-
- perform_node_renames(NULL,&path_renames);
- //delete for read
- for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) {
- Node *n = E->get();
- if (!n->is_inside_tree() || !n->get_parent())
- continue;
-
- List<Node*> owned;
- n->get_owned_by(n->get_owner(),&owned);
- Array owners;
- for(List<Node*>::Element *E=owned.front();E;E=E->next()) {
-
- owners.push_back(E->get());
- }
-
-
- 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 (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);
-
- ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
- editor_data->get_undo_redo().add_do_method(sed,"live_debug_remove_and_keep_node",edited_scene->get_path_to(n),n->get_instance_ID());
- editor_data->get_undo_redo().add_undo_method(sed,"live_debug_restore_node",n->get_instance_ID(),edited_scene->get_path_to(n->get_parent()),n->get_index());
-
- }
-
-
- }
- editor_data->get_undo_redo().commit_action();
-
-
-}
-
-
-
-
-void SceneTreeDock::_selection_changed() {
-
- int selection_size = EditorNode::get_singleton()->get_editor_selection()->get_selection().size();
- if (selection_size>1) {
- //automatically turn on multi-edit
- _tool_selected(TOOL_MULTI_EDIT);
- }
-
- if (selection_size==1) {
- if(EditorNode::get_singleton()->get_editor_selection()->get_selection().front()->key()->get_script().is_null()) {
- button_create_script->show();
- button_clear_script->hide();
- }
- else {
- button_create_script->hide();
- button_clear_script->show();
- }
- } else {
- button_create_script->hide();
- button_clear_script->hide();
- }
-
- //tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2);
-
-}
-
-
-void SceneTreeDock::_create() {
-
-
- if (current_option==TOOL_NEW) {
-
- Node *parent=NULL;
-
-
- if (edited_scene) {
- // If root exists in edited scene
- parent = scene_tree->get_selected();
- if( !parent )
- parent = edited_scene;
-
- } else {
- // If no root exist in edited scene
- parent = scene_root;
- ERR_FAIL_COND(!parent);
- }
-
- Object *c = create_dialog->instance_selected();
-
- ERR_FAIL_COND(!c);
- Node *child=c->cast_to<Node>();
- ERR_FAIL_COND(!child);
-
- editor_data->get_undo_redo().create_action(TTR("Create Node"));
-
- if (edited_scene) {
-
- editor_data->get_undo_redo().add_do_method(parent,"add_child",child);
- editor_data->get_undo_redo().add_do_method(child,"set_owner",edited_scene);
- editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
- editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",child);
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child);
-
-
- String new_name = parent->validate_child_name(child);
- ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
- editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",edited_scene->get_path_to(parent),child->get_class(),new_name);
- editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name));
-
- } else {
-
- editor_data->get_undo_redo().add_do_method(editor,"set_edited_scene",child);
- editor_data->get_undo_redo().add_do_reference(child);
- editor_data->get_undo_redo().add_undo_method(editor,"set_edited_scene",(Object*)NULL);
-
- }
-
- editor_data->get_undo_redo().commit_action();
- editor->push_item(c);
-
- if (c->cast_to<Control>()) {
- //make editor more comfortable, so some controls don't appear super shrunk
- Control *ct = c->cast_to<Control>();
-
- Size2 ms = ct->get_minimum_size();
- if (ms.width<4)
- ms.width=40;
- if (ms.height<4)
- ms.height=40;
- ct->set_size(ms);
- }
-
-
- } else if (current_option==TOOL_REPLACE) {
- Node * n = scene_tree->get_selected();
- ERR_FAIL_COND(!n);
-
- Object *c = create_dialog->instance_selected();
-
- ERR_FAIL_COND(!c);
- Node *newnode=c->cast_to<Node>();
- ERR_FAIL_COND(!newnode);
-
- List<PropertyInfo> pinfo;
- n->get_property_list(&pinfo);
-
- for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
- if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
- continue;
- newnode->set(E->get().name,n->get(E->get().name));
- }
-
- editor->push_item(NULL);
-
- //reconnect signals
- List<MethodInfo> sl;
-
- n->get_signal_list(&sl);
- for (List<MethodInfo>::Element *E=sl.front();E;E=E->next()) {
-
- List<Object::Connection> cl;
- n->get_signal_connection_list(E->get().name,&cl);
-
- for(List<Object::Connection>::Element *F=cl.front();F;F=F->next()) {
-
- Object::Connection &c=F->get();
- if (!(c.flags&Object::CONNECT_PERSIST))
- continue;
- newnode->connect(c.signal,c.target,c.method,varray(),Object::CONNECT_PERSIST);
- }
-
- }
-
- String newname=n->get_name();
-
- List<Node*> to_erase;
- for(int i=0;i<n->get_child_count();i++) {
- if (n->get_child(i)->get_owner()==NULL && n->is_owned_by_parent()) {
- to_erase.push_back(n->get_child(i));
- }
- }
- n->replace_by(newnode,true);
-
- if (n==edited_scene) {
- edited_scene=newnode;
- editor->set_edited_scene(newnode);
- newnode->set_editable_instances(n->get_editable_instances());
- }
-
- //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);
-
- while(to_erase.front()) {
- memdelete(to_erase.front()->get());
- to_erase.pop_front();
- }
-
-
-
- }
-
-}
-
-
-void SceneTreeDock::set_edited_scene(Node* p_scene) {
-
- edited_scene=p_scene;
-}
-
-void SceneTreeDock::set_selected(Node *p_node, bool p_emit_selected ) {
-
- scene_tree->set_selected(p_node,p_emit_selected);
-
-}
-
-void SceneTreeDock::import_subscene() {
-
- import_subscene_dialog->popup_centered_ratio();
-}
-
-void SceneTreeDock::_import_subscene() {
-
- Node* parent = scene_tree->get_selected();
- if (!parent) {
- parent = editor_data->get_edited_scene_root();
- ERR_FAIL_COND(!parent);
- }
-
- import_subscene_dialog->move(parent,edited_scene);
- editor_data->get_undo_redo().clear_history(); //no undo for now..
-
-
-/*
- editor_data->get_undo_redo().create_action("Import Subscene");
- editor_data->get_undo_redo().add_do_method(parent,"add_child",ss);
- //editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
- //editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",child);
- editor_data->get_undo_redo().add_do_reference(ss);
- editor_data->get_undo_redo().add_undo_method(parent,"remove_child",ss);
- editor_data->get_undo_redo().commit_action();
-*/
-}
-
-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(TTR("I see.."));
- accept->set_text(TTR("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(TTR("I see.."));
- accept->set_text(TTR("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("filesystem/on_save/compress_binary_resources"))
- flg|=ResourceSaver::FLAG_COMPRESS;
- /*
- if (EditorSettings::get_singleton()->get("filesystem/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(TTR("I see.."));
- accept->set_text(TTR("Error saving scene."));
- accept->popup_centered_minsize();
- return;
- }
- _replace_with_branch_scene(p_file, base);
- } else {
- accept->get_ok()->set_text(TTR("I see.."));
- accept->set_text(TTR("Error duplicating scene to save it."));
- accept->popup_centered_minsize();
- return;
- }
-
-}
-
-static bool _is_node_visible(Node* p_node) {
-
- if (!p_node->get_owner())
- return false;
- if (p_node->get_owner()!=EditorNode::get_singleton()->get_edited_scene() && !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node->get_owner()))
- return false;
-
- return true;
-
-}
-
-static bool _has_visible_children(Node* p_node) {
-
- bool collapsed = p_node->is_displayed_folded();
- if (collapsed)
- return false;
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- Node* child = p_node->get_child(i);
- if (!_is_node_visible(child))
- continue;
-
- return true;
- }
-
- return false;
-
-}
-
-
-
-static Node* _find_last_visible(Node* p_node) {
-
- Node* last=NULL;
-
- bool collapsed = p_node->is_displayed_folded();
-
- if (!collapsed) {
- for(int i=0;i<p_node->get_child_count();i++) {
- if (_is_node_visible(p_node->get_child(i))) {
- last=p_node->get_child(i);
- }
- }
- }
-
- if (last) {
- Node* lastc=_find_last_visible(last);
- if (lastc)
- last=lastc;
-
-
- } else {
- last=p_node;
- }
-
- return last;
-}
-
-
-void SceneTreeDock::_normalize_drop(Node*& to_node, int &to_pos, int p_type) {
-
- to_pos=-1;
-
- if (p_type==-1) {
- //drop at above selected node
- if (to_node==EditorNode::get_singleton()->get_edited_scene()) {
- to_node=NULL;
- ERR_EXPLAIN("Cannot perform drop above the root node!");
- ERR_FAIL();
- }
-
- to_pos=to_node->get_index();
- to_node=to_node->get_parent();
-
- } else if (p_type==1) {
- //drop at below selected node
- if (to_node==EditorNode::get_singleton()->get_edited_scene()) {
- //if at lower sibling of root node
- to_pos=0; //just insert at begining of root node
- return;
- }
-
-
- Node* lower_sibling=NULL;
-
-
-
- if (_has_visible_children(to_node) ) {
- to_pos=0;
- } else {
-
-
- for(int i=to_node->get_index()+1;i<to_node->get_parent()->get_child_count();i++) {
- Node *c =to_node->get_parent()->get_child(i);
- if (_is_node_visible(c)) {
- lower_sibling=c;
- break;
- }
- }
- if (lower_sibling) {
- to_pos=lower_sibling->get_index();
- }
-
- to_node=to_node->get_parent();
-
-
- }
-#if 0
- //quite complicated, look for next visible in tree
- upper_sibling=_find_last_visible(upper_sibling);
-
- if (upper_sibling->get_parent()==to_node->get_parent()) {
- //just insert over this node because nothing is above at an upper level
- to_pos=to_node->get_index();
- to_node=to_node->get_parent();
- } else {
- to_pos=-1; //insert last in whathever is up
- to_node=upper_sibling->get_parent(); //insert at a parent of whathever is up
- }
-
-
- } else {
- //just insert over this node because nothing is above at the same level
- to_pos=to_node->get_index();
- to_node=to_node->get_parent();
- }
-#endif
-
- }
-
-}
-
-void SceneTreeDock::_files_dropped(Vector<String> p_files,NodePath p_to,int p_type) {
-
- Node *node = get_node(p_to);
- ERR_FAIL_COND(!node);
-
- int to_pos=-1;
- _normalize_drop(node,to_pos,p_type);
- _perform_instance_scenes(p_files,node,to_pos);
-}
-
-void SceneTreeDock::_script_dropped(String p_file, NodePath p_to) {
- Ref<Script> scr = ResourceLoader::load(p_file);
- ERR_FAIL_COND(!scr.is_valid());
- Node *n = get_node(p_to);
- if (n) {
- n->set_script(scr.get_ref_ptr());
- }
-}
-
-void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) {
-
- Vector<Node*> nodes;
- Node *to_node;
-
- for(int i=0;i<p_nodes.size();i++) {
- Node *n=get_node((p_nodes[i]));
- if (n) {
- nodes.push_back(n);
- }
- }
-
- if (nodes.size()==0)
- return;
-
- to_node=get_node(p_to);
- if (!to_node)
- return;
-
- int to_pos=-1;
-
- _normalize_drop(to_node,to_pos,p_type);
- _do_reparent(to_node,to_pos,nodes,true);
-
-}
-
-void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) {
- if (!EditorNode::get_singleton()->get_edited_scene()) {
-
- menu->clear();
- menu->add_icon_shortcut(get_icon("Add","EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_icon("Instance","EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
-
- menu->set_size(Size2(1,1));
- menu->set_pos(p_menu_pos);
- menu->popup();
- return;
- }
-
- List<Node*> selection = editor_selection->get_selected_node_list();
-
- if (selection.size()==0)
- return;
-
- menu->clear();
-
-
- if (selection.size()==1) {
- menu->add_icon_shortcut(get_icon("Add","EditorIcons"), ED_GET_SHORTCUT("scene_tree/add_child_node"), TOOL_NEW);
- menu->add_icon_shortcut(get_icon("Instance","EditorIcons"), ED_GET_SHORTCUT("scene_tree/instance_scene"), TOOL_INSTANCE);
- menu->add_separator();
- menu->add_icon_shortcut(get_icon("Reload","EditorIcons"),ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE);
- //menu->add_separator(); moved to their own dock
- //menu->add_icon_item(get_icon("Groups","EditorIcons"),TTR("Edit Groups"),TOOL_GROUP);
- //menu->add_icon_item(get_icon("Connect","EditorIcons"),TTR("Edit Connections"),TOOL_CONNECT);
- menu->add_separator();
- menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT);
- menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT);
- menu->add_separator();
- }
-
- menu->add_icon_shortcut(get_icon("Up","EditorIcons"),ED_GET_SHORTCUT("scene_tree/move_up"), TOOL_MOVE_UP);
- menu->add_icon_shortcut(get_icon("Down","EditorIcons"),ED_GET_SHORTCUT("scene_tree/move_down"), TOOL_MOVE_DOWN);
- menu->add_icon_shortcut(get_icon("Duplicate","EditorIcons"),ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE);
- menu->add_icon_shortcut(get_icon("Reparent","EditorIcons"),ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT);
-
- if (selection.size()==1) {
- menu->add_separator();
- menu->add_icon_shortcut(get_icon("Blend","EditorIcons"),ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE);
- menu->add_icon_shortcut(get_icon("CreateNewSceneFrom","EditorIcons"),ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
- menu->add_separator();
- menu->add_icon_shortcut(get_icon("CopyNodePath","EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
- }
- menu->add_separator();
- menu->add_icon_shortcut(get_icon("Remove","EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
- menu->set_size(Size2(1,1));
- menu->set_pos(p_menu_pos);
- menu->popup();
-
-}
-
-
-void SceneTreeDock::_filter_changed(const String& p_filter) {
-
- scene_tree->set_filter(p_filter);
-}
-
-String SceneTreeDock::get_filter() {
-
- return filter->get_text();
-}
-
-void SceneTreeDock::set_filter(const String& p_filter){
-
- filter->set_text(p_filter);
- scene_tree->set_filter(p_filter);
-}
-
-
-void SceneTreeDock::_focus_node() {
-
- Node *node = scene_tree->get_selected();
- ERR_FAIL_COND(!node);
-
- if (node->is_class("CanvasItem")) {
- CanvasItemEditorPlugin *editor = editor_data->get_editor("2D")->cast_to<CanvasItemEditorPlugin>();
- editor->get_canvas_item_editor()->focus_selection();
- } else {
- SpatialEditorPlugin *editor = editor_data->get_editor("3D")->cast_to<SpatialEditorPlugin>();
- editor->get_spatial_editor()->get_editor_viewport(0)->focus_selection();
- }
-}
-
-void SceneTreeDock::open_script_dialog(Node* p_for_node) {
-
- scene_tree->set_selected(p_for_node,false);
- _tool_selected(TOOL_ATTACH_SCRIPT);
-}
-
-void SceneTreeDock::_bind_methods() {
-
- ClassDB::bind_method(_MD("_tool_selected"),&SceneTreeDock::_tool_selected,DEFVAL(false));
- ClassDB::bind_method(_MD("_create"),&SceneTreeDock::_create);
- //ClassDB::bind_method(_MD("_script_created"),&SceneTreeDock::_script_created);
- ClassDB::bind_method(_MD("_node_reparent"),&SceneTreeDock::_node_reparent);
- ClassDB::bind_method(_MD("_set_owners"),&SceneTreeDock::_set_owners);
- ClassDB::bind_method(_MD("_node_selected"),&SceneTreeDock::_node_selected);
- ClassDB::bind_method(_MD("_node_renamed"),&SceneTreeDock::_node_renamed);
- ClassDB::bind_method(_MD("_script_created"),&SceneTreeDock::_script_created);
- ClassDB::bind_method(_MD("_load_request"),&SceneTreeDock::_load_request);
- ClassDB::bind_method(_MD("_script_open_request"),&SceneTreeDock::_script_open_request);
- ClassDB::bind_method(_MD("_unhandled_key_input"),&SceneTreeDock::_unhandled_key_input);
- ClassDB::bind_method(_MD("_input"),&SceneTreeDock::_input);
- ClassDB::bind_method(_MD("_nodes_drag_begin"),&SceneTreeDock::_nodes_drag_begin);
- ClassDB::bind_method(_MD("_delete_confirm"),&SceneTreeDock::_delete_confirm);
- ClassDB::bind_method(_MD("_node_prerenamed"),&SceneTreeDock::_node_prerenamed);
- ClassDB::bind_method(_MD("_import_subscene"),&SceneTreeDock::_import_subscene);
- ClassDB::bind_method(_MD("_selection_changed"),&SceneTreeDock::_selection_changed);
- ClassDB::bind_method(_MD("_new_scene_from"),&SceneTreeDock::_new_scene_from);
- ClassDB::bind_method(_MD("_nodes_dragged"),&SceneTreeDock::_nodes_dragged);
- ClassDB::bind_method(_MD("_files_dropped"),&SceneTreeDock::_files_dropped);
- ClassDB::bind_method(_MD("_script_dropped"),&SceneTreeDock::_script_dropped);
- ClassDB::bind_method(_MD("_tree_rmb"),&SceneTreeDock::_tree_rmb);
- ClassDB::bind_method(_MD("_filter_changed"),&SceneTreeDock::_filter_changed);
- ClassDB::bind_method(_MD("_focus_node"),&SceneTreeDock::_focus_node);
-
-
- ClassDB::bind_method(_MD("instance"),&SceneTreeDock::instance);
-}
-
-
-
-SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelection *p_editor_selection,EditorData &p_editor_data) {
-
- editor=p_editor;
- edited_scene=NULL;
- editor_data=&p_editor_data;
- editor_selection=p_editor_selection;
- scene_root=p_scene_root;
-
- VBoxContainer *vbc = this;
-
- HBoxContainer *filter_hbc = memnew( HBoxContainer );
- ToolButton *tb;
-
- ED_SHORTCUT("scene_tree/add_child_node",TTR("Add Child Node"), KEY_MASK_CMD|KEY_A);
- ED_SHORTCUT("scene_tree/instance_scene",TTR("Instance Child Scene"));
- ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type"));
- ED_SHORTCUT("scene_tree/attach_script", TTR("Attach Script"));
- ED_SHORTCUT("scene_tree/clear_script", TTR("Clear Script"));
- ED_SHORTCUT("scene_tree/move_up", TTR("Move Up"), KEY_MASK_CMD | KEY_UP);
- ED_SHORTCUT("scene_tree/move_down", TTR("Move Down"), KEY_MASK_CMD | KEY_DOWN);
- ED_SHORTCUT("scene_tree/duplicate", TTR("Duplicate"),KEY_MASK_CMD | KEY_D);
- ED_SHORTCUT("scene_tree/reparent", TTR("Reparent"));
- ED_SHORTCUT("scene_tree/merge_from_scene", TTR("Merge From Scene"));
- ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene"));
- ED_SHORTCUT("scene_tree/copy_node_path", TTR("Copy Node Path"), KEY_MASK_CMD|KEY_C);
- ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KEY_MASK_SHIFT|KEY_DELETE);
- ED_SHORTCUT("scene_tree/delete", TTR("Delete"), KEY_DELETE);
-
- tb = memnew( ToolButton );
- tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_NEW, false));
- tb->set_tooltip(TTR("Add/Create a New Node"));
- tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_child_node"));
- filter_hbc->add_child(tb);
- button_add=tb;
-
- tb = memnew( ToolButton );
- tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_INSTANCE, false));
- tb->set_tooltip(TTR("Instance a scene file as a Node. Creates an inherited scene if no root node exists."));
- tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/instance_scene"));
- filter_hbc->add_child(tb);
- button_instance=tb;
-
-
-
- vbc->add_child(filter_hbc);
- filter = memnew( LineEdit );
- filter->set_h_size_flags(SIZE_EXPAND_FILL);
- filter_hbc->add_child(filter);
- filter_icon = memnew( TextureRect );
- filter_hbc->add_child(filter_icon);
- filter_icon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
- filter->connect("text_changed",this,"_filter_changed");
-
-
- tb = memnew( ToolButton );
- tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_ATTACH_SCRIPT, false));
- tb->set_tooltip(TTR("Attach a new or existing script for the selected node."));
- tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script"));
- filter_hbc->add_child(tb);
- button_create_script=tb;
-
- tb = memnew(ToolButton);
- tb->connect("pressed", this, "_tool_selected", make_binds(TOOL_CLEAR_SCRIPT, false));
- tb->set_tooltip(TTR("Clear a script for the selected node."));
- tb->set_shortcut(ED_GET_SHORTCUT("scene_tree/clear_script"));
- filter_hbc->add_child(tb);
- button_clear_script = tb;
-
-
- scene_tree = memnew( SceneTreeEditor(false,true,true ));
- vbc->add_child(scene_tree);
- scene_tree->set_v_size_flags(SIZE_EXPAND|SIZE_FILL);
- scene_tree->connect("rmb_pressed",this,"_tree_rmb");
-
- scene_tree->connect("node_selected", this,"_node_selected",varray(),CONNECT_DEFERRED);
- scene_tree->connect("node_renamed", this,"_node_renamed",varray(),CONNECT_DEFERRED);
- scene_tree->connect("node_prerename", this,"_node_prerenamed");
- scene_tree->connect("open",this,"_load_request");
- scene_tree->connect("open_script",this,"_script_open_request");
- scene_tree->connect("nodes_rearranged",this,"_nodes_dragged");
- scene_tree->connect("files_dropped",this,"_files_dropped");
- scene_tree->connect("script_dropped",this,"_script_dropped");
- scene_tree->connect("nodes_dragged",this,"_nodes_drag_begin");
-
- scene_tree->get_scene_tree()->connect("item_double_clicked", this, "_focus_node");
-
- scene_tree->set_undo_redo(&editor_data->get_undo_redo());
- scene_tree->set_editor_selection(editor_selection);
-
-
- create_dialog = memnew( CreateDialog );
- create_dialog->set_base_type("Node");
- add_child(create_dialog);
- create_dialog->connect("create",this,"_create");
-
- //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");
-
- accept = memnew( AcceptDialog );
- add_child(accept);
-
- file = memnew( EditorFileDialog );
- add_child(file);
- file->connect("file_selected",this,"instance");
- set_process_unhandled_key_input(true);
-
- 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");
-
-
- menu = memnew( PopupMenu );
- add_child(menu);
- menu->connect("id_pressed",this,"_tool_selected");
- first_enter=true;
- restore_script_editor_on_drag=false;
-
- vbc->add_constant_override("separation",4);
- set_process_input(true);
-}
diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp
deleted file mode 100644
index dd1fdeb400..0000000000
--- a/tools/editor/scene_tree_editor.cpp
+++ /dev/null
@@ -1,1316 +0,0 @@
-/*************************************************************************/
-/* scene_tree_editor.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "scene_tree_editor.h"
-
-#include "scene/gui/label.h"
-#include "editor_node.h"
-#include "print_string.h"
-#include "message_queue.h"
-#include "scene/main/viewport.h"
-#include "tools/editor/plugins/canvas_item_editor_plugin.h"
-#include "scene/resources/packed_scene.h"
-
-Node *SceneTreeEditor::get_scene_node() {
-
- ERR_FAIL_COND_V(!is_inside_tree(),NULL);
-
- return get_tree()->get_edited_scene_root();
-}
-
-
-void SceneTreeEditor::_subscene_option(int p_idx) {
-
- Object *obj = ObjectDB::get_instance(instance_node);
- if (!obj)
- return;
- Node *node = obj->cast_to<Node>();
- if (!node)
- return;
-
- switch(p_idx) {
-
- case SCENE_MENU_EDITABLE_CHILDREN: {
-
- bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node);
- editable = !editable;
-
- //node->set_instance_children_editable(editable);
- EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node,editable);
- instance_menu->set_item_checked(0,editable);
- if (editable) {
- node->set_scene_instance_load_placeholder(false);
- instance_menu->set_item_checked(1,false);
- }
-
- _update_tree();
-
- } break;
- case SCENE_MENU_USE_PLACEHOLDER: {
-
- bool placeholder = node->get_scene_instance_load_placeholder();
- placeholder = !placeholder;
-
- //node->set_instance_children_editable(editable);
- if (placeholder) {
- EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node,false);
- }
- node->set_scene_instance_load_placeholder(placeholder);
- instance_menu->set_item_checked(0,false);
- instance_menu->set_item_checked(1,placeholder);
-
- _update_tree();
-
- } break;
- case SCENE_MENU_OPEN: {
-
- emit_signal("open",node->get_filename());
- } break;
- case SCENE_MENU_CLEAR_INHERITANCE: {
- clear_inherit_confirm->popup_centered_minsize();
- } break;
- case SCENE_MENU_CLEAR_INSTANCING: {
-
- Node*root=EditorNode::get_singleton()->get_edited_scene();
- if (!root)
- break;
-
-
- ERR_FAIL_COND(node->get_filename()==String());
-
- undo_redo->create_action("Discard Instancing");
-
- undo_redo->add_do_method(node,"set_filename","");
- undo_redo->add_undo_method(node,"set_filename",node->get_filename());
-
- _node_replace_owner(node,node,root);
-
- undo_redo->add_do_method(this,"update_tree");
- undo_redo->add_undo_method(this,"update_tree");
-
- undo_redo->commit_action();
-
-
- } break;
- case SCENE_MENU_OPEN_INHERITED: {
- if (node && node->get_scene_inherited_state().is_valid()) {
- emit_signal("open",node->get_scene_inherited_state()->get_path());
- }
- } break;
- case SCENE_MENU_CLEAR_INHERITANCE_CONFIRM: {
- if (node && node->get_scene_inherited_state().is_valid()) {
- node->set_scene_inherited_state(Ref<SceneState>());
- update_tree();
- EditorNode::get_singleton()->get_property_editor()->update_tree();
- }
-
- } break;
-
-
- }
-
-}
-
-
-void SceneTreeEditor::_node_replace_owner(Node* p_base,Node* p_node,Node* p_root) {
-
- if (p_base!=p_node) {
-
- if (p_node->get_owner()==p_base) {
-
- undo_redo->add_do_method(p_node,"set_owner",p_root);
- undo_redo->add_undo_method(p_node,"set_owner",p_base);
- }
- }
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- _node_replace_owner(p_base,p_node->get_child(i),p_root);
- }
-}
-
-
-void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id) {
-
- TreeItem *item=p_item->cast_to<TreeItem>();
- ERR_FAIL_COND(!item);
-
- NodePath np = item->get_metadata(0);
-
- Node *n=get_node(np);
- ERR_FAIL_COND(!n);
-
- if (p_id==BUTTON_SUBSCENE) {
- //open scene request
- Rect2 item_rect = tree->get_item_rect(item,0);
- item_rect.pos.y-=tree->get_scroll().y;
- item_rect.pos+=tree->get_global_pos();
-
- if (n==get_scene_node()) {
- inheritance_menu->set_pos(item_rect.pos+Vector2(0,item_rect.size.y));
- inheritance_menu->set_size(Vector2(item_rect.size.x,0));
- inheritance_menu->popup();
- instance_node=n->get_instance_ID();
-
- } else {
- instance_menu->set_pos(item_rect.pos+Vector2(0,item_rect.size.y));
- instance_menu->set_size(Vector2(item_rect.size.x,0));
- if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(n))
- instance_menu->set_item_checked(0,true);
- else
- instance_menu->set_item_checked(0,false);
-
- if (n->get_owner()==get_scene_node()) {
- instance_menu->set_item_checked(1,n->get_scene_instance_load_placeholder());
- instance_menu->set_item_disabled(1,false);
- } else {
-
- instance_menu->set_item_checked(1,false);
- instance_menu->set_item_disabled(1,true);
- }
-
- instance_menu->popup();
- instance_node=n->get_instance_ID();
- }
- //emit_signal("open",n->get_filename());
- } else if (p_id==BUTTON_SCRIPT) {
- RefPtr script=n->get_script();
- if (!script.is_null())
- emit_signal("open_script",script);
-
- } else if (p_id==BUTTON_VISIBILITY) {
-
-
- if (n->is_class("Spatial")) {
-
- bool v = bool(n->call("is_visible"));
- undo_redo->create_action(TTR("Toggle Spatial Visible"));
- undo_redo->add_do_method(n,"set_visible",!v);
- undo_redo->add_undo_method(n,"set_visible",v);
- undo_redo->commit_action();
-
- } else if (n->is_class("CanvasItem")) {
-
- bool v = bool(n->call("is_visible"));
- undo_redo->create_action(TTR("Toggle CanvasItem Visible"));
- undo_redo->add_do_method(n,v?"hide":"show");
- undo_redo->add_undo_method(n,v?"show":"hide");
- undo_redo->commit_action();
- }
-
- } else if (p_id==BUTTON_LOCK) {
-
- if (n->is_class("CanvasItem")) {
- n->set_meta("_edit_lock_", Variant());
- _update_tree();
- emit_signal("node_changed");
- }
-
- } else if (p_id==BUTTON_GROUP) {
- if (n->is_class("CanvasItem")) {
- n->set_meta("_edit_group_", Variant());
- _update_tree();
- emit_signal("node_changed");
- }
- } else if (p_id==BUTTON_WARNING) {
-
- String config_err = n->get_configuration_warning();
- if (config_err==String())
- return;
- config_err=config_err.word_wrap(80);
- warning->set_text(config_err);
- warning->popup_centered_minsize();
-
- } else if (p_id==BUTTON_SIGNALS) {
-
- editor_selection->clear();
- editor_selection->add_node(n);
-
- set_selected(n);
-
- NodeDock::singleton->get_parent()->call("set_current_tab",NodeDock::singleton->get_index());
- NodeDock::singleton->show_connections();
-
- } else if (p_id==BUTTON_GROUPS) {
-
- editor_selection->clear();
- editor_selection->add_node(n);
-
- set_selected(n);
-
- NodeDock::singleton->get_parent()->call("set_current_tab",NodeDock::singleton->get_index());
- NodeDock::singleton->show_groups();
- }
-}
-
-bool SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
-
- if (!p_node)
- return false;
-
- // only owned nodes are editable, since nodes can create their own (manually owned) child nodes,
- // which the editor needs not to know about.
-
- bool part_of_subscene=false;
-
- if (!display_foreign && p_node->get_owner()!=get_scene_node() && p_node!=get_scene_node()) {
-
- if ((show_enabled_subscene || can_open_instance) && p_node->get_owner() && (get_scene_node()->is_editable_instance(p_node->get_owner()))) {
-
- part_of_subscene=true;
- //allow
- } else {
- return false;
- }
- } else {
- part_of_subscene = p_node!=get_scene_node() && get_scene_node()->get_scene_inherited_state().is_valid() && get_scene_node()->get_scene_inherited_state()->find_node_by_path(get_scene_node()->get_path_to(p_node))>=0;
- }
-
- TreeItem *item = tree->create_item(p_parent);
- item->set_text(0, p_node->get_name() );
- if (can_rename && !part_of_subscene /*(p_node->get_owner() == get_scene_node() || p_node==get_scene_node())*/)
- item->set_editable(0, true);
-
- item->set_selectable(0,true);
- if (can_rename) {
-#ifdef ENABLE_DEPRECATED
- if (p_node->has_meta("_editor_collapsed")) {
- //remove previous way of storing folding, which did not get along with scene inheritance and instancing
- if ((bool)p_node->get_meta("_editor_collapsed"))
- p_node->set_display_folded(true);
- p_node->set_meta("_editor_collapsed",Variant());
- }
-#endif
- bool collapsed = p_node->is_displayed_folded();
- if (collapsed)
- item->set_collapsed(true);
- }
-
- Ref<Texture> icon;
- if (p_node->has_meta("_editor_icon"))
- icon=p_node->get_meta("_editor_icon");
- else
- icon=get_icon( (has_icon(p_node->get_class(),"EditorIcons")?p_node->get_class():String("Object")),"EditorIcons");
- item->set_icon(0, icon );
- item->set_metadata( 0,p_node->get_path() );
-
- if (part_of_subscene) {
-
- //item->set_selectable(0,marked_selectable);
- item->set_custom_color(0,Color(0.8,0.4,0.20));
-
- } else if (marked.has(p_node)) {
-
- item->set_selectable(0,marked_selectable);
- item->set_custom_color(0,Color(0.8,0.1,0.10));
- } else if (!marked_selectable && !marked_children_selectable) {
-
- Node *node=p_node;
- while(node) {
- if (marked.has(node)) {
- item->set_selectable(0,false);
- item->set_custom_color(0,Color(0.8,0.1,0.10));
- break;
- }
- node=node->get_parent();
- }
- }
-
-
-
- if (can_rename) { //should be can edit..
-
- String warning = p_node->get_configuration_warning();
- if (warning!=String()) {
- item->add_button(0,get_icon("NodeWarning","EditorIcons"),BUTTON_WARNING);
- }
-
- bool has_connections = p_node->has_persistent_signal_connections();
- bool has_groups = p_node->has_persistent_groups();
-
- if (has_connections && has_groups) {
- item->add_button(0,get_icon("ConnectionAndGroups","EditorIcons"),BUTTON_SIGNALS);
- } else if (has_connections) {
- item->add_button(0,get_icon("Connect","EditorIcons"),BUTTON_SIGNALS);
- } else if (has_groups) {
- item->add_button(0,get_icon("Groups","EditorIcons"),BUTTON_GROUPS);
- }
- }
-
- if (p_node==get_scene_node() && p_node->get_scene_inherited_state().is_valid()) {
- item->add_button(0,get_icon("InstanceOptions","EditorIcons"),BUTTON_SUBSCENE);
- item->set_tooltip(0,TTR("Inherits:")+" "+p_node->get_scene_inherited_state()->get_path()+"\n"+TTR("Type:")+" "+p_node->get_class());
- } else if (p_node!=get_scene_node() && p_node->get_filename()!="" && can_open_instance) {
-
- item->add_button(0,get_icon("InstanceOptions","EditorIcons"),BUTTON_SUBSCENE);
- item->set_tooltip(0,TTR("Instance:")+" "+p_node->get_filename()+"\n"+TTR("Type:")+" "+p_node->get_class());
- } else {
- item->set_tooltip(0,String(p_node->get_name())+"\n"+TTR("Type:")+" "+p_node->get_class());
- }
-
- if (can_open_instance) {
-
- if (!p_node->is_connected("script_changed",this,"_node_script_changed"))
- p_node->connect("script_changed",this,"_node_script_changed",varray(p_node));
-
-
- if (!p_node->get_script().is_null()) {
-
- item->add_button(0,get_icon("Script","EditorIcons"),BUTTON_SCRIPT);
- }
-
- if (p_node->is_class("CanvasItem")) {
-
- bool is_locked = p_node->has_meta("_edit_lock_");//_edit_group_
- if (is_locked)
- item->add_button(0,get_icon("Lock", "EditorIcons"), BUTTON_LOCK);
-
- bool is_grouped = p_node->has_meta("_edit_group_");
- if (is_grouped)
- item->add_button(0,get_icon("Group", "EditorIcons"), BUTTON_GROUP);
-
- bool v = p_node->call("is_visible");
- if (v)
- item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY);
- else
- item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
-
- if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
- p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
-
- _update_visibility_color(p_node, item);
- } else if (p_node->is_class("Spatial")) {
-
- bool v = p_node->call("is_visible");
- if (v)
- item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY);
- else
- item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
-
- if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
- p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
-
- _update_visibility_color(p_node, item);
- }
-
- }
-
- if (editor_selection) {
- if (editor_selection->is_selected(p_node)) {
-
- item->select(0);
- }
- }
-
- if (selected==p_node) {
- if (!editor_selection)
- item->select(0);
- item->set_as_cursor(0);
- }
-
- bool keep= (filter.is_subsequence_ofi(String(p_node->get_name())));
-
- for (int i=0;i<p_node->get_child_count();i++) {
-
- bool child_keep = _add_nodes(p_node->get_child(i),item);
-
- keep = keep || child_keep;
-
- }
-
- if (!keep) {
- memdelete(item);
- return false;
- } else {
- return true;
- }
-
-}
-
-
-void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
-
-
- if (p_node!=get_scene_node() && !p_node->get_owner()) {
-
- return;
- }
- TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
- if (!item) {
-
- return;
- }
- int idx=item->get_button_by_id(0,BUTTON_VISIBILITY);
- ERR_FAIL_COND(idx==-1);
-
- bool visible=false;
-
- if (p_node->is_class("CanvasItem")) {
- visible = p_node->call("is_visible");
- CanvasItemEditor::get_singleton()->get_viewport_control()->update();
- } else if (p_node->is_class("Spatial")) {
- visible = p_node->call("is_visible");
- }
-
- if (visible)
- item->set_button(0,idx,get_icon("Visible","EditorIcons"));
- else
- item->set_button(0,idx,get_icon("Hidden","EditorIcons"));
-
- _update_visibility_color(p_node, item);
-}
-
-void SceneTreeEditor::_update_visibility_color(Node *p_node, TreeItem *p_item) {
- if (p_node->is_class("CanvasItem") || p_node->is_class("Spatial")) {
- Color color(1,1,1,1);
- bool visible_on_screen = p_node->call("is_visible");
- if (!visible_on_screen) {
- color = Color(0.6,0.6,0.6,1);
- }
- int idx=p_item->get_button_by_id(0,BUTTON_VISIBILITY);
- p_item->set_button_color(0,idx,color);
- }
-}
-
-void SceneTreeEditor::_node_script_changed(Node *p_node) {
-
- _update_tree();
- /*
- changes the order :|
- TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
- if (p_node->get_script().is_null()) {
-
- int idx=item->get_button_by_id(0,2);
- if (idx>=0)
- item->erase_button(0,idx);
- } else {
-
- int idx=item->get_button_by_id(0,2);
- if (idx<0)
- item->add_button(0,get_icon("Script","EditorIcons"),2);
-
- }*/
-
-}
-
-void SceneTreeEditor::_node_removed(Node *p_node) {
-
- if (EditorNode::get_singleton()->is_exiting())
- return; //speed up exit
-
- if (p_node->is_connected("script_changed",this,"_node_script_changed"))
- p_node->disconnect("script_changed",this,"_node_script_changed");
-
- if (p_node->is_class("Spatial") || p_node->is_class("CanvasItem")) {
- if (p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
- p_node->disconnect("visibility_changed",this,"_node_visibility_changed");
- }
-
- if (p_node==selected) {
- selected=NULL;
- emit_signal("node_selected");
- }
-
-
-}
-void SceneTreeEditor::_update_tree() {
-
-
- if (!is_inside_tree()) {
- tree_dirty=false;
- return;
- }
-
- updating_tree=true;
- tree->clear();
- if (get_scene_node()) {
- _add_nodes( get_scene_node(), NULL );
- last_hash = hash_djb2_one_64(0);
- _compute_hash(get_scene_node(),last_hash);
-
- }
- updating_tree=false;
-
- tree_dirty=false;
-
-}
-
-void SceneTreeEditor::_compute_hash(Node *p_node,uint64_t &hash) {
-
- hash=hash_djb2_one_64(p_node->get_instance_ID(),hash);
- if (p_node->get_parent())
- hash=hash_djb2_one_64(p_node->get_parent()->get_instance_ID(),hash); //so a reparent still produces a different hash
-
-
- for(int i=0;i<p_node->get_child_count();i++) {
-
- _compute_hash(p_node->get_child(i),hash);
- }
-}
-
-void SceneTreeEditor::_test_update_tree() {
-
- pending_test_update=false;
-
- if (!is_inside_tree())
- return;
-
- if(tree_dirty)
- return; // don't even bother
-
- uint64_t hash = hash_djb2_one_64(0);
- if (get_scene_node())
- _compute_hash(get_scene_node(),hash);
- //test hash
- if (hash==last_hash)
- return; // did not change
-
- MessageQueue::get_singleton()->push_call(this,"_update_tree");
- tree_dirty=true;
-}
-
-void SceneTreeEditor::_tree_changed() {
-
- if (EditorNode::get_singleton()->is_exiting())
- return; //speed up exit
- if (pending_test_update)
- return;
- if (tree_dirty)
- return;
-
- MessageQueue::get_singleton()->push_call(this,"_test_update_tree");
- pending_test_update=true;
-
-}
-
-void SceneTreeEditor::_selected_changed() {
-
-
- TreeItem *s = tree->get_selected();
- ERR_FAIL_COND(!s);
- NodePath np = s->get_metadata(0);
-
- Node *n=get_node(np);
-
-
- if (n==selected)
- return;
-
-
- selected = get_node(np);
-
- blocked++;
- emit_signal("node_selected");
- blocked--;
-
-
-}
-
-
-void SceneTreeEditor::_cell_multi_selected(Object *p_object,int p_cell,bool p_selected) {
-
- TreeItem *item = p_object->cast_to<TreeItem>();
- ERR_FAIL_COND(!item);
-
- NodePath np = item->get_metadata(0);
-
- Node *n=get_node(np);
-
- if (!n)
- return;
-
- if (!editor_selection)
- return;
-
- if (p_selected) {
- editor_selection->add_node(n);
-
- } else {
- editor_selection->remove_node(n);
-
- }
-
-}
-
-void SceneTreeEditor::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- get_tree()->connect("tree_changed",this,"_tree_changed");
- get_tree()->connect("node_removed",this,"_node_removed");
- get_tree()->connect("node_configuration_warning_changed",this,"_warning_changed");
-
- instance_menu->set_item_icon(5,get_icon("Load","EditorIcons"));
- tree->connect("item_collapsed",this,"_cell_collapsed");
- inheritance_menu->set_item_icon(2,get_icon("Load","EditorIcons"));
- clear_inherit_confirm->connect("confirmed",this,"_subscene_option",varray(SCENE_MENU_CLEAR_INHERITANCE_CONFIRM));
-
- EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed");
-
-
- //get_scene()->connect("tree_changed",this,"_tree_changed",Vector<Variant>(),CONNECT_DEFERRED);
- //get_scene()->connect("node_removed",this,"_node_removed",Vector<Variant>(),CONNECT_DEFERRED);
- _update_tree();
- }
- if (p_what==NOTIFICATION_EXIT_TREE) {
-
- get_tree()->disconnect("tree_changed",this,"_tree_changed");
- get_tree()->disconnect("node_removed",this,"_node_removed");
- tree->disconnect("item_collapsed",this,"_cell_collapsed");
- clear_inherit_confirm->disconnect("confirmed",this,"_subscene_option");
- get_tree()->disconnect("node_configuration_warning_changed",this,"_warning_changed");
- EditorSettings::get_singleton()->disconnect("settings_changed",this,"_editor_settings_changed");
- }
-
-}
-
-
-TreeItem* SceneTreeEditor::_find(TreeItem *p_node,const NodePath& p_path) {
-
- if (!p_node)
- return NULL;
-
- NodePath np=p_node->get_metadata(0);
- if (np==p_path)
- return p_node;
-
- TreeItem *children=p_node->get_children();
- while(children) {
-
- TreeItem *n=_find(children,p_path);
- if (n)
- return n;
- children=children->get_next();
- }
-
- return NULL;
-}
-
-void SceneTreeEditor::set_selected(Node *p_node,bool p_emit_selected) {
-
- ERR_FAIL_COND(blocked>0);
-
- if (pending_test_update)
- _test_update_tree();
- if (tree_dirty)
- _update_tree();
-
- if (selected==p_node)
- return;
-
-
- TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
-
- if (item) {
- // make visible when it's collapsed
- TreeItem* node=item->get_parent();
- while (node && node!=tree->get_root()) {
- node->set_collapsed(false);
- node=node->get_parent();
- }
- item->select(0);
- item->set_as_cursor(0);
- selected=p_node;
- tree->ensure_cursor_is_visible();
- } else {
- if (!p_node)
- selected=NULL;
- _update_tree();
- selected=p_node;
- if (p_emit_selected)
- emit_signal("node_selected");
- }
-
-}
-
-void SceneTreeEditor::_rename_node(ObjectID p_node,const String& p_name) {
-
- Object *o = ObjectDB::get_instance(p_node);
- ERR_FAIL_COND(!o);
- Node *n = o->cast_to<Node>();
- ERR_FAIL_COND(!n);
- TreeItem* item=_find(tree->get_root(),n->get_path());
- ERR_FAIL_COND(!item);
-
- n->set_name( p_name );
- item->set_metadata(0,n->get_path());
- item->set_text(0,p_name);
- emit_signal("node_renamed");
-
- if (!tree_dirty) {
- MessageQueue::get_singleton()->push_call(this,"_update_tree");
- tree_dirty=true;
- }
-
-
-}
-
-
-void SceneTreeEditor::_renamed() {
-
- TreeItem *which=tree->get_edited();
-
- ERR_FAIL_COND(!which);
- NodePath np = which->get_metadata(0);
- Node *n=get_node(np);
- ERR_FAIL_COND(!n);
-
- String new_name=which->get_text(0);
- if (new_name.find(".") != -1 || new_name.find("/") != -1) {
-
- error->set_text(TTR("Invalid node name, the following characters are not allowed:")+"\n \".\", \"/\"");
- error->popup_centered_minsize();
- new_name=n->get_name();
- }
-
- if (new_name==n->get_name())
- return;
-
- if (!undo_redo) {
- n->set_name( new_name );
- which->set_metadata(0,n->get_path());
- emit_signal("node_renamed");
- } else {
- undo_redo->create_action(TTR("Rename Node"));
- emit_signal("node_prerename",n,new_name);
- undo_redo->add_do_method(this,"_rename_node",n->get_instance_ID(),new_name);
- undo_redo->add_undo_method(this,"_rename_node",n->get_instance_ID(),n->get_name());
- undo_redo->commit_action();
- }
-}
-
-
-Node *SceneTreeEditor::get_selected() {
-
- return selected;
-}
-
-void SceneTreeEditor::set_marked(const Set<Node*>& p_marked,bool p_selectable,bool p_children_selectable) {
-
- if (tree_dirty)
- _update_tree();
- marked=p_marked;
- marked_selectable=p_selectable;
- marked_children_selectable=p_children_selectable;
- _update_tree();
-}
-
-void SceneTreeEditor::set_marked(Node *p_marked,bool p_selectable,bool p_children_selectable) {
-
- Set<Node*> s;
- if (p_marked)
- s.insert(p_marked);
- set_marked(s,p_selectable,p_children_selectable);
-
-
-}
-
-void SceneTreeEditor::set_filter(const String& p_filter) {
-
- filter=p_filter;
- _update_tree();
-}
-
-String SceneTreeEditor::get_filter() const {
-
- return filter;
-}
-
-
-void SceneTreeEditor::set_display_foreign_nodes(bool p_display) {
-
- display_foreign=p_display;
- _update_tree();
-}
-bool SceneTreeEditor::get_display_foreign_nodes() const {
-
- return display_foreign;
-}
-
-void SceneTreeEditor::set_editor_selection(EditorSelection *p_selection) {
-
- editor_selection=p_selection;
- tree->set_select_mode(Tree::SELECT_MULTI);
- tree->set_cursor_can_exit_tree(false);
- editor_selection->connect("selection_changed",this,"_selection_changed");
-}
-
-void SceneTreeEditor::_update_selection(TreeItem *item) {
-
- ERR_FAIL_COND(!item);
-
- NodePath np = item->get_metadata(0);
-
- if (!has_node(np))
- return;
-
- Node *n=get_node(np);
-
- if (!n)
- return;
-
- if (editor_selection->is_selected(n))
- item->select(0);
- else
- item->deselect(0);
-
- TreeItem *c=item->get_children();
-
-
- while(c) {
-
- _update_selection(c);
- c=c->get_next();
- }
-}
-
-void SceneTreeEditor::_selection_changed() {
-
- if (!editor_selection)
- return;
-
- TreeItem *root=tree->get_root();
-
- if (!root)
- return;
- _update_selection(root);
-}
-
-void SceneTreeEditor::_cell_collapsed(Object *p_obj) {
-
- if (updating_tree)
- return;
- if (!can_rename)
- return;
-
- TreeItem *ti=p_obj->cast_to<TreeItem>();
- if (!ti)
- return;
-
- bool collapsed=ti->is_collapsed();
-
- NodePath np = ti->get_metadata(0);
-
- Node *n=get_node(np);
- ERR_FAIL_COND(!n);
-
- n->set_display_folded(collapsed);
-
-}
-
-Variant SceneTreeEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
- if (!can_rename)
- return Variant(); //not editable tree
-
- Vector<Node*> selected;
- Vector<Ref<Texture> > icons;
- TreeItem *next=tree->get_next_selected(NULL);
- while (next) {
-
- NodePath np = next->get_metadata(0);
-
- Node *n=get_node(np);
- if (n) {
-
- selected.push_back(n);
- icons.push_back(next->get_icon(0));
- }
- next=tree->get_next_selected(next);
- }
-
- if (selected.empty())
- return Variant();
-
- VBoxContainer *vb = memnew( VBoxContainer );
- Array objs;
- int list_max = 10;
- float opacity_step = 1.0f / list_max;
- float opacity_item = 1.0f;
- for(int i=0;i<selected.size();i++) {
-
- if (i<list_max){
- HBoxContainer *hb = memnew( HBoxContainer );
- TextureRect *tf = memnew(TextureRect);
- tf->set_texture(icons[i]);
- hb->add_child(tf);
- Label *label = memnew( Label( selected[i]->get_name() ) );
- hb->add_child(label);
- vb->add_child(hb);
- hb->set_modulate(Color(1,1,1,opacity_item));
- opacity_item -= opacity_step;
- }
- NodePath p = selected[i]->get_path();
- objs.push_back(p);
- }
-
- set_drag_preview(vb);
- Dictionary drag_data;
- drag_data["type"]="nodes";
- drag_data["nodes"]=objs;
-
- tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN|Tree::DROP_MODE_ON_ITEM);
- emit_signal("nodes_dragged");
-
- return drag_data;
-}
-
-bool SceneTreeEditor::_is_script_type(const StringName &p_type) const {
- return (script_types->find(p_type));
-}
-
-bool SceneTreeEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
-
- if (!can_rename)
- return false; //not editable tree
- if (filter!=String())
- return false; //can't rearrange tree with filter turned on
-
-
- Dictionary d=p_data;
- if (!d.has("type"))
- return false;
-
- TreeItem *item = tree->get_item_at_pos(p_point);
- if (!item)
- return false;
-
- int section = tree->get_drop_section_at_pos(p_point);
- if (section<-1 || (section==-1 && !item->get_parent()))
- return false;
-
- if (String(d["type"])=="files") {
-
- Vector<String> files = d["files"];
-
- if (files.size()==0)
- return false; //weird
-
- if (_is_script_type(EditorFileSystem::get_singleton()->get_file_type(files[0]))) {
- tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
- return true;
- }
-
- for(int i=0;i<files.size();i++) {
- String file = files[i];
- String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
- if (ftype!="PackedScene")
- return false;
- }
-
- tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN|Tree::DROP_MODE_ON_ITEM); //so it works..
-
- return true;
- }
-
-
- if (String(d["type"])=="nodes") {
- return true;
- }
-
- return false;
-}
-void SceneTreeEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
-
- if (!can_drop_data_fw(p_point,p_data,p_from))
- return;
-
- TreeItem *item = tree->get_item_at_pos(p_point);
- if (!item)
- return;
- int section = tree->get_drop_section_at_pos(p_point);
- if (section<-1)
- return;
-
- NodePath np = item->get_metadata(0);
- Node *n=get_node(np);
- if (!n)
- return;
-
- Dictionary d=p_data;
-
- if (String(d["type"])=="nodes") {
- Array nodes=d["nodes"];
- emit_signal("nodes_rearranged",nodes,np,section);
- }
-
- if (String(d["type"])=="files") {
-
- Vector<String> files = d["files"];
-
-
- String ftype = EditorFileSystem::get_singleton()->get_file_type(files[0]);
- if (_is_script_type(ftype)) {
- emit_signal("script_dropped", files[0],np);
- } else {
- emit_signal("files_dropped",files,np,section);
- }
- }
-
-}
-
-void SceneTreeEditor::_rmb_select(const Vector2& p_pos) {
-
- emit_signal("rmb_pressed",tree->get_global_transform().xform(p_pos));
-}
-
-
-void SceneTreeEditor::_warning_changed(Node* p_for_node) {
-
- //should use a timer
- update_timer->start();
- //print_line("WARNING CHANGED "+String(p_for_node->get_name()));
-
-}
-
-
-void SceneTreeEditor::_editor_settings_changed() {
- bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines");
- Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color");
-
- if (enable_rl) {
- tree->add_constant_override("draw_relationship_lines",1);
- tree->add_color_override("relationship_line_color", rl_color);
- }
- else
- tree->add_constant_override("draw_relationship_lines",0);
-
-}
-
-
-void SceneTreeEditor::_bind_methods() {
-
- ClassDB::bind_method("_tree_changed",&SceneTreeEditor::_tree_changed);
- ClassDB::bind_method("_update_tree",&SceneTreeEditor::_update_tree);
- ClassDB::bind_method("_node_removed",&SceneTreeEditor::_node_removed);
- ClassDB::bind_method("_selected_changed",&SceneTreeEditor::_selected_changed);
- ClassDB::bind_method("_renamed",&SceneTreeEditor::_renamed);
- ClassDB::bind_method("_rename_node",&SceneTreeEditor::_rename_node);
- ClassDB::bind_method("_test_update_tree",&SceneTreeEditor::_test_update_tree);
- ClassDB::bind_method("_cell_multi_selected",&SceneTreeEditor::_cell_multi_selected);
- ClassDB::bind_method("_selection_changed",&SceneTreeEditor::_selection_changed);
- ClassDB::bind_method("_cell_button_pressed",&SceneTreeEditor::_cell_button_pressed);
- ClassDB::bind_method("_cell_collapsed",&SceneTreeEditor::_cell_collapsed);
- ClassDB::bind_method("_subscene_option",&SceneTreeEditor::_subscene_option);
- ClassDB::bind_method("_rmb_select",&SceneTreeEditor::_rmb_select);
- ClassDB::bind_method("_warning_changed",&SceneTreeEditor::_warning_changed);
-
- ClassDB::bind_method("_node_script_changed",&SceneTreeEditor::_node_script_changed);
- ClassDB::bind_method("_node_visibility_changed",&SceneTreeEditor::_node_visibility_changed);
-
- ClassDB::bind_method("_editor_settings_changed", &SceneTreeEditor::_editor_settings_changed);
-
- ClassDB::bind_method(_MD("get_drag_data_fw"), &SceneTreeEditor::get_drag_data_fw);
- ClassDB::bind_method(_MD("can_drop_data_fw"), &SceneTreeEditor::can_drop_data_fw);
- ClassDB::bind_method(_MD("drop_data_fw"), &SceneTreeEditor::drop_data_fw);
-
- ClassDB::bind_method(_MD("update_tree"), &SceneTreeEditor::update_tree);
-
- ADD_SIGNAL( MethodInfo("node_selected") );
- ADD_SIGNAL( MethodInfo("node_renamed") );
- ADD_SIGNAL( MethodInfo("node_prerename") );
- ADD_SIGNAL( MethodInfo("node_changed") );
- ADD_SIGNAL( MethodInfo("nodes_dragged") );
- ADD_SIGNAL( MethodInfo("nodes_rearranged",PropertyInfo(Variant::ARRAY,"paths"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) );
- ADD_SIGNAL( MethodInfo("files_dropped",PropertyInfo(Variant::POOL_STRING_ARRAY,"files"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) );
- ADD_SIGNAL( MethodInfo("script_dropped",PropertyInfo(Variant::STRING,"file"),PropertyInfo(Variant::NODE_PATH,"to_path")));
- ADD_SIGNAL( MethodInfo("rmb_pressed",PropertyInfo(Variant::VECTOR2,"pos")) ) ;
-
- ADD_SIGNAL( MethodInfo("open") );
- ADD_SIGNAL( MethodInfo("open_script") );
-
-
-}
-
-
-SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open_instance) {
-
-
- undo_redo=NULL;
- tree_dirty=true;
- selected=NULL;
-
- marked_selectable=false;
- marked_children_selectable=false;
- can_rename=p_can_rename;
- can_open_instance=p_can_open_instance;
- display_foreign=false;
- editor_selection=NULL;
-
- if (p_label) {
- Label *label = memnew( Label );
- label->set_pos( Point2(10, 0));
- label->set_text(TTR("Scene Tree (Nodes):"));
-
- add_child(label);
- }
-
- tree = memnew( Tree );
- tree->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- tree->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- tree->set_begin( Point2(0,p_label?18:0 ));
- tree->set_end( Point2(0,0 ));
-
- add_child( tree );
-
- tree->set_drag_forwarding(this);
- if (p_can_rename) {
- tree->set_allow_rmb_select(true);
- tree->connect("item_rmb_selected",this,"_rmb_select");
- tree->connect("empty_tree_rmb_selected",this,"_rmb_select");
- }
-
- tree->connect("cell_selected", this,"_selected_changed");
- tree->connect("item_edited", this,"_renamed",varray(),CONNECT_DEFERRED);
- tree->connect("multi_selected",this,"_cell_multi_selected");
- tree->connect("button_pressed",this,"_cell_button_pressed");
- //tree->connect("item_edited", this,"_renamed",Vector<Variant>(),true);
-
- error = memnew( AcceptDialog );
- add_child(error);
-
- warning = memnew( AcceptDialog );
- add_child(warning);
- warning->set_title("Node Configuration Warning!");
-
-
- show_enabled_subscene=false;
-
- last_hash=0;
- pending_test_update=false;
- updating_tree=false;
- blocked=0;
-
- instance_menu = memnew( PopupMenu );
- instance_menu->add_check_item(TTR("Editable Children"),SCENE_MENU_EDITABLE_CHILDREN);
- instance_menu->add_check_item(TTR("Load As Placeholder"),SCENE_MENU_USE_PLACEHOLDER);
- instance_menu->add_separator();
- instance_menu->add_item(TTR("Discard Instancing"),SCENE_MENU_CLEAR_INSTANCING);
- instance_menu->add_separator();
- instance_menu->add_item(TTR("Open in Editor"),SCENE_MENU_OPEN);
- instance_menu->connect("id_pressed",this,"_subscene_option");
- add_child(instance_menu);
-
- inheritance_menu = memnew( PopupMenu );
- inheritance_menu->add_item(TTR("Clear Inheritance"),SCENE_MENU_CLEAR_INHERITANCE);
- inheritance_menu->add_separator();
- inheritance_menu->add_item(TTR("Open in Editor"),SCENE_MENU_OPEN_INHERITED);
- inheritance_menu->connect("id_pressed",this,"_subscene_option");
-
- add_child(inheritance_menu);
-
- clear_inherit_confirm = memnew( ConfirmationDialog );
- clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)"));
- clear_inherit_confirm->get_ok()->set_text(TTR("Clear!"));
- add_child(clear_inherit_confirm);
-
- update_timer = memnew(Timer);
- update_timer->connect("timeout",this,"_update_tree");
- update_timer->set_one_shot(true);
- update_timer->set_wait_time(0.5);
- add_child(update_timer);
-
- script_types = memnew(List<StringName>);
- ClassDB::get_inheriters_from_class("Script", script_types);
-
-}
-
-
-
-SceneTreeEditor::~SceneTreeEditor() {
-
- memdelete(script_types);
-}
-
-
-/******** DIALOG *********/
-
-void SceneTreeDialog::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
- connect("confirmed", this,"_select");
-
- }
-
- if (p_what==NOTIFICATION_EXIT_TREE) {
- disconnect("confirmed", this,"_select");
-
- }
- if (p_what==NOTIFICATION_DRAW) {
-
- RID ci = get_canvas_item();
- get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
- }
-
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED && is_visible_in_tree()) {
-
- tree->update_tree();
- }
-
-
-}
-
-void SceneTreeDialog::_cancel() {
-
- hide();
-
-
-
-}
-void SceneTreeDialog::_select() {
-
- if (tree->get_selected()) {
- emit_signal("selected",tree->get_selected()->get_path());
- hide();
- }
-}
-
-void SceneTreeDialog::_bind_methods() {
-
- ClassDB::bind_method("_select",&SceneTreeDialog::_select);
- ClassDB::bind_method("_cancel",&SceneTreeDialog::_cancel);
- ADD_SIGNAL( MethodInfo("selected",PropertyInfo(Variant::NODE_PATH,"path")));
-
-}
-
-
-SceneTreeDialog::SceneTreeDialog() {
-
- set_title(TTR("Select a Node"));
-
- tree = memnew( SceneTreeEditor(false,false) );
- add_child(tree);
- //set_child_rect(tree);
-
- tree->get_scene_tree()->connect("item_activated",this,"_select");
-
-}
-
-
-SceneTreeDialog::~SceneTreeDialog()
-{
-}
diff --git a/tools/editor/script_create_dialog.cpp b/tools/editor/script_create_dialog.cpp
deleted file mode 100644
index da01cdefe5..0000000000
--- a/tools/editor/script_create_dialog.cpp
+++ /dev/null
@@ -1,437 +0,0 @@
-/*************************************************************************/
-/* script_create_dialog.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "script_create_dialog.h"
-
-#include "script_language.h"
-#include "globals.h"
-#include "io/resource_saver.h"
-#include "os/file_access.h"
-#include "editor_file_system.h"
-
-void ScriptCreateDialog::config(const String& p_base_name,const String&p_base_path) {
-
- class_name->set_text("");
- parent_name->set_text(p_base_name);
- if (p_base_path!="") {
- initial_bp=p_base_path.get_basename();
- file_path->set_text(initial_bp+"."+ScriptServer::get_language( language_menu->get_selected() )->get_extension());
- } else {
- initial_bp="";
- file_path->set_text("");
- }
- _class_name_changed("");
- _path_changed(file_path->get_text());
-}
-
-bool ScriptCreateDialog::_validate(const String& p_string) {
-
- if (p_string.length()==0)
- return false;
-
-
- for(int i=0;i<p_string.length();i++) {
-
- if (i==0) {
- if (p_string[0]>='0' && p_string[0]<='9')
- return false; // no start with number plz
- }
-
- bool valid_char = (p_string[i]>='0' && p_string[i]<='9') || (p_string[i]>='a' && p_string[i]<='z') || (p_string[i]>='A' && p_string[i]<='Z') || p_string[i]=='_';
-
- if (!valid_char)
- return false;
-
- }
-
- return true;
-}
-
-void ScriptCreateDialog::_class_name_changed(const String& p_name) {
-
- if (!_validate(parent_name->get_text())) {
- error_label->set_text(TTR("Invalid parent class name"));
- error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
- } else if (class_name->is_editable()) {
- if (class_name->get_text()=="") {
- error_label->set_text(TTR("Valid chars:")+" a-z A-Z 0-9 _");
- error_label->add_color_override("font_color",Color(1,1,1,0.6));
- } else if (!_validate(class_name->get_text())) {
- error_label->set_text(TTR("Invalid class name"));
- error_label->add_color_override("font_color",Color(1,0.2,0.2,0.8));
- } else {
- error_label->set_text(TTR("Valid name"));
- error_label->add_color_override("font_color",Color(0,1.0,0.8,0.8));
- }
- } else {
-
- error_label->set_text(TTR("N/A"));
- error_label->add_color_override("font_color",Color(0,1.0,0.8,0.8));
- }
-}
-
-void ScriptCreateDialog::ok_pressed() {
-
- if (create_new){
- _create_new();
- } else {
- _load_exist();
- }
-
- create_new=true;
- _update_controls();
-
-}
-
-void ScriptCreateDialog::_create_new() {
-
- if (class_name->is_editable() && !_validate(class_name->get_text())) {
- alert->set_text(TTR("Class name is invalid!"));
- alert->popup_centered_minsize();
- return;
- }
- if (!_validate(parent_name->get_text())) {
- alert->set_text(TTR("Parent class name is invalid!"));
- alert->popup_centered_minsize();
- return;
- }
-
- String cname;
- if (class_name->is_editable())
- cname=class_name->get_text();
-
- Ref<Script> scr = ScriptServer::get_language( language_menu->get_selected() )->get_template(cname,parent_name->get_text());
-
- String selected_language = language_menu->get_item_text(language_menu->get_selected());
- editor_settings->set_last_selected_language(selected_language);
-
- if (cname!="")
- scr->set_name(cname);
-
- if (!internal->is_pressed()) {
- String lpath = GlobalConfig::get_singleton()->localize_path(file_path->get_text());
- scr->set_path(lpath);
- if (!path_valid) {
- alert->set_text(TTR("Invalid path!"));
- alert->popup_centered_minsize();
- return;
- }
- Error err = ResourceSaver::save(lpath,scr,ResourceSaver::FLAG_CHANGE_PATH);
- if (err!=OK) {
- alert->set_text(TTR("Could not create script in filesystem."));
- alert->popup_centered_minsize();
- return;
- }
- }
-
- hide();
- emit_signal("script_created",scr);
-
-}
-
-void ScriptCreateDialog::_load_exist() {
-
- String path=file_path->get_text();
- RES p_script = ResourceLoader::load(path, "Script");
- if (p_script.is_null()) {
- alert->get_ok()->set_text(TTR("Ugh"));
- alert->set_text(vformat(TTR("Error loading script from %s"), path));
- alert->popup_centered_minsize();
- return;
- }
-
- hide();
- emit_signal("script_created",p_script.get_ref_ptr());
-
-}
-
-void ScriptCreateDialog::_lang_changed(int l) {
-
- l=language_menu->get_selected();
- if (ScriptServer::get_language( l )->has_named_classes()) {
- class_name->set_editable(true);
- } else {
- class_name->set_editable(false);
- }
-
- String selected_ext="."+ScriptServer::get_language( l )->get_extension();
- String path=file_path->get_text();
- String extension="";
- if (path.find(".")>=0) {
- extension=path.get_extension();
- }
-
- if (extension.length()==0) {
- // add extension if none
- path+=selected_ext;
- _path_changed(path);
- } else {
- // change extension by selected language
- List<String> extensions;
- // get all possible extensions for script
- for (int l=0;l<language_menu->get_item_count();l++) {
- ScriptServer::get_language( l )->get_recognized_extensions(&extensions);
- }
-
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
- if (E->get().nocasecmp_to(extension)==0) {
- path=path.get_basename()+selected_ext;
- _path_changed(path);
- break;
- }
- }
- }
- file_path->set_text(path);
- _class_name_changed(class_name->get_text());
-
-}
-
-void ScriptCreateDialog::_built_in_pressed() {
-
- if (internal->is_pressed()) {
- path_vb->hide();
- } else {
- path_vb->show();
- }
-
-}
-
-void ScriptCreateDialog::_browse_path() {
-
- file_browse->set_mode(EditorFileDialog::MODE_SAVE_FILE);
- file_browse->set_disable_overwrite_warning(true);
- file_browse->clear_filters();
- List<String> extensions;
-
- // get all possible extensions for script
- for (int l=0;l<language_menu->get_item_count();l++) {
- ScriptServer::get_language( l )->get_recognized_extensions(&extensions);
- }
-
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
- file_browse->add_filter("*."+E->get());
- }
-
- file_browse->set_current_path(file_path->get_text());
- file_browse->popup_centered_ratio();
-
-}
-
-void ScriptCreateDialog::_file_selected(const String& p_file) {
-
- String p = GlobalConfig::get_singleton()->localize_path(p_file);
- file_path->set_text(p);
- _path_changed(p);
-
-}
-
-void ScriptCreateDialog::_path_changed(const String& p_path) {
-
- path_valid=false;
- String p =p_path;
-
- if (p=="") {
-
- path_error_label->set_text(TTR("Path is empty"));
- path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
- return;
-
- }
-
- p = GlobalConfig::get_singleton()->localize_path(p);
- if (!p.begins_with("res://")) {
-
- path_error_label->set_text(TTR("Path is not local"));
- path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
- return;
- }
-
- if (p.find("/") || p.find("\\")) {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-
- if (d->change_dir(p.get_base_dir())!=OK) {
-
- path_error_label->set_text(TTR("Invalid base path"));
- path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
- memdelete(d);
- return;
-
- }
- memdelete(d);
- }
-
- FileAccess *f = FileAccess::create(FileAccess::ACCESS_RESOURCES);
- create_new=!f->file_exists(p);
- memdelete(f);
-
- String extension=p.get_extension();
- List<String> extensions;
-
- // get all possible extensions for script
- for (int l=0;l<language_menu->get_item_count();l++) {
- ScriptServer::get_language( l )->get_recognized_extensions(&extensions);
- }
-
- bool found=false;
- int index=0;
- for(List<String>::Element *E=extensions.front();E;E=E->next()) {
- if (E->get().nocasecmp_to(extension)==0) {
- language_menu->select(index); // change Language option by extension
- found=true;
- break;
- }
- index++;
- }
-
- if (!found) {
- path_error_label->set_text(TTR("Invalid extension"));
- path_error_label->add_color_override("font_color",Color(1,0.4,0.0,0.8));
- return;
- }
-
- _update_controls();
-
- path_error_label->add_color_override("font_color",Color(0,1.0,0.8,0.8));
-
- path_valid=true;
-
-}
-
-void ScriptCreateDialog::_update_controls() {
-
- if (create_new) {
- path_error_label->set_text(TTR("Create new script"));
- get_ok()->set_text(TTR("Create"));
- } else {
- path_error_label->set_text(TTR("Load existing script"));
- get_ok()->set_text(TTR("Load"));
- }
- parent_name->set_editable(create_new);
- internal->set_disabled(!create_new);
-
-}
-
-
-void ScriptCreateDialog::_bind_methods() {
-
- ClassDB::bind_method("_class_name_changed",&ScriptCreateDialog::_class_name_changed);
- ClassDB::bind_method("_lang_changed",&ScriptCreateDialog::_lang_changed);
- ClassDB::bind_method("_built_in_pressed",&ScriptCreateDialog::_built_in_pressed);
- ClassDB::bind_method("_browse_path",&ScriptCreateDialog::_browse_path);
- ClassDB::bind_method("_file_selected",&ScriptCreateDialog::_file_selected);
- ClassDB::bind_method("_path_changed",&ScriptCreateDialog::_path_changed);
- ADD_SIGNAL(MethodInfo("script_created",PropertyInfo(Variant::OBJECT,"script",PROPERTY_HINT_RESOURCE_TYPE,"Script")));
-}
-
-ScriptCreateDialog::ScriptCreateDialog() {
-
- /* SNAP DIALOG */
-
- VBoxContainer *vb = memnew( VBoxContainer );
- add_child(vb);
- //set_child_rect(vb);
-
-
- class_name = memnew( LineEdit );
- VBoxContainer *vb2 = memnew( VBoxContainer );
- vb2->add_child(class_name);
- class_name->connect("text_changed", this,"_class_name_changed");
- error_label = memnew(Label);
- error_label->set_text("valid chars: a-z A-Z 0-9 _");
- error_label->set_align(Label::ALIGN_CENTER);
- vb2->add_child(error_label);
- vb->add_margin_child(TTR("Class Name:"),vb2);
-
- parent_name = memnew( LineEdit );
- vb->add_margin_child(TTR("Inherits:"),parent_name);
- parent_name->connect("text_changed", this,"_class_name_changed");
-
- language_menu = memnew( OptionButton );
- vb->add_margin_child(TTR("Language"),language_menu);
-
- for(int i=0;i<ScriptServer::get_language_count();i++) {
-
- language_menu->add_item(ScriptServer::get_language(i)->get_name());
- }
-
- editor_settings = EditorSettings::get_singleton();
- String last_selected_language = editor_settings->get_last_selected_language();
- if (last_selected_language != "")
- for (int i = 0; i < language_menu->get_item_count(); i++)
- if (language_menu->get_item_text(i) == last_selected_language)
- {
- language_menu->select(i);
- break;
- }
- else language_menu->select(0);
-
- language_menu->connect("item_selected",this,"_lang_changed");
-
- //parent_name->set_text();
-
- vb2 = memnew( VBoxContainer );
- path_vb = memnew( VBoxContainer );
- vb2->add_child(path_vb);
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- file_path = memnew( LineEdit );
- file_path->connect("text_changed",this,"_path_changed");
- hbc->add_child(file_path);
- file_path->set_h_size_flags(SIZE_EXPAND_FILL);
- Button *b = memnew( Button );
- b->set_text(" .. ");
- b->connect("pressed",this,"_browse_path");
- hbc->add_child(b);
- path_vb->add_child(hbc);
- path_error_label = memnew( Label );
- path_vb->add_child( path_error_label );
- path_error_label->set_text(TTR("Error!"));
- path_error_label->set_align(Label::ALIGN_CENTER);
-
-
- internal = memnew( CheckButton );
- internal->set_text(TTR("Built-In Script"));
- vb2->add_child(internal);
- internal->connect("pressed",this,"_built_in_pressed");
-
- vb->add_margin_child(TTR("Path:"),vb2);
-
- set_size(Size2(200,150));
- set_hide_on_ok(false);
- set_title(TTR("Attach Node Script"));
-
- file_browse = memnew( EditorFileDialog );
- file_browse->connect("file_selected",this,"_file_selected");
- add_child(file_browse);
- get_ok()->set_text(TTR("Create"));
- alert = memnew( AcceptDialog );
- add_child(alert);
- _lang_changed(0);
-
- create_new=true;
-}
diff --git a/tools/editor/script_create_dialog.h b/tools/editor/script_create_dialog.h
deleted file mode 100644
index df16efc73c..0000000000
--- a/tools/editor/script_create_dialog.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*************************************************************************/
-/* script_create_dialog.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SCRIPT_CREATE_DIALOG_H
-#define SCRIPT_CREATE_DIALOG_H
-
-#include "scene/gui/dialogs.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/option_button.h"
-#include "tools/editor/editor_file_dialog.h"
-#include "tools/editor/editor_settings.h"
-#include "scene/gui/check_button.h"
-
-class ScriptCreateDialog : public ConfirmationDialog {
- GDCLASS(ScriptCreateDialog,ConfirmationDialog);
-
- LineEdit *class_name;
- Label *error_label;
- Label *path_error_label;
- LineEdit *parent_name;
- OptionButton *language_menu;
- LineEdit *file_path;
- EditorFileDialog *file_browse;
- CheckButton *internal;
- VBoxContainer *path_vb;
- AcceptDialog *alert;
- bool path_valid;
- bool create_new;
- String initial_bp;
- EditorSettings *editor_settings;
-
-
- void _path_changed(const String& p_path=String());
- void _lang_changed(int l=0);
- void _built_in_pressed();
- bool _validate(const String& p_strin);
- void _class_name_changed(const String& p_name);
- void _browse_path();
- void _file_selected(const String& p_file);
- virtual void ok_pressed();
- void _create_new();
- void _load_exist();
- void _update_controls();
-protected:
-
- static void _bind_methods();
-public:
-
- void config(const String& p_base_name,const String&p_base_path);
-
- ScriptCreateDialog();
-};
-
-#endif // SCRIPT_CREATE_DIALOG_H
diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp
deleted file mode 100644
index d5cca06820..0000000000
--- a/tools/editor/script_editor_debugger.cpp
+++ /dev/null
@@ -1,1998 +0,0 @@
-/*************************************************************************/
-/* script_editor_debugger.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "script_editor_debugger.h"
-
-#include "scene/gui/separator.h"
-#include "scene/gui/label.h"
-#include "scene/gui/split_container.h"
-#include "scene/gui/tree.h"
-#include "scene/gui/texture_button.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/dialogs.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/gui/margin_container.h"
-#include "property_editor.h"
-#include "globals.h"
-#include "editor_node.h"
-#include "main/performance.h"
-#include "editor_profiler.h"
-#include "editor_settings.h"
-
-class ScriptEditorDebuggerVariables : public Object {
-
- GDCLASS( ScriptEditorDebuggerVariables, Object );
-
- List<PropertyInfo> props;
- Map<StringName,Variant> values;
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- return false;
- }
-
- bool _get(const StringName& p_name,Variant &r_ret) const {
-
- if (!values.has(p_name))
- return false;
- r_ret=values[p_name];
- return true;
- }
- void _get_property_list( List<PropertyInfo> *p_list) const {
-
- for(const List<PropertyInfo>::Element *E=props.front();E;E=E->next() )
- p_list->push_back(E->get());
- }
-
-
-public:
-
-
- void clear() {
-
- props.clear();
- values.clear();
- }
-
- String get_var_value(const String& p_var) const {
-
- for(Map<StringName,Variant>::Element *E=values.front();E;E=E->next()) {
- String v = E->key().operator String().get_slice("/",1);
- if (v==p_var)
- return E->get();
- }
-
- return "";
- }
-
- void add_property(const String &p_name, const Variant& p_value) {
-
- PropertyInfo pinfo;
- pinfo.name=p_name;
- pinfo.type=p_value.get_type();
- props.push_back(pinfo);
- values[p_name]=p_value;
-
- }
-
- void update() {
- _change_notify();
- }
-
-
- ScriptEditorDebuggerVariables() {
-
- }
-};
-
-
-class ScriptEditorDebuggerInspectedObject : public Object {
-
- GDCLASS( ScriptEditorDebuggerInspectedObject, Object);
-
-
-
-
-protected:
-
- bool _set(const StringName& p_name, const Variant& p_value) {
-
- if (!prop_values.has(p_name))
- return false;
-
- emit_signal("value_edited",p_name,p_value);
- prop_values[p_name]=p_value;
- return true;
- }
-
- bool _get(const StringName& p_name,Variant &r_ret) const {
-
- if (!prop_values.has(p_name))
- return false;
-
- r_ret=prop_values[p_name];
- return true;
-
- }
- void _get_property_list( List<PropertyInfo> *p_list) const {
-
- p_list->clear(); //sorry, no want category
- for (const List<PropertyInfo>::Element *E=prop_list.front();E;E=E->next()) {
- p_list->push_back(E->get());
- }
- }
-
-
- static void _bind_methods() {
-
- ADD_SIGNAL(MethodInfo("value_edited"));
- }
-
-public:
-
- ObjectID last_edited_id;
- List<PropertyInfo> prop_list;
- Map<StringName,Variant> prop_values;
-
- void update() {
- _change_notify();
- }
-
- void update_single(const char* p_prop) {
- _change_notify(p_prop);
- }
-
- ScriptEditorDebuggerInspectedObject() { last_edited_id=0; }
-
-
-};
-
-void ScriptEditorDebugger::debug_next() {
-
- ERR_FAIL_COND(!breaked);
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
- Array msg;
- msg.push_back("next");
- ppeer->put_var(msg);
- stack_dump->clear();
- inspector->edit(NULL);
-
-}
-void ScriptEditorDebugger::debug_step() {
-
- ERR_FAIL_COND(!breaked);
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
-
- Array msg;
- msg.push_back("step");
- ppeer->put_var(msg);
- stack_dump->clear();
- inspector->edit(NULL);
-}
-
-void ScriptEditorDebugger::debug_break() {
-
- ERR_FAIL_COND(breaked);
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
-
- Array msg;
- msg.push_back("break");
- ppeer->put_var(msg);
-
-}
-
-void ScriptEditorDebugger::debug_continue() {
-
- ERR_FAIL_COND(!breaked);
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
-
- OS::get_singleton()->enable_for_stealing_focus(EditorNode::get_singleton()->get_child_process_id());
-
- Array msg;
- msg.push_back("continue");
- ppeer->put_var(msg);
-
-
-}
-
-void ScriptEditorDebugger::_scene_tree_folded(Object* obj) {
-
-
- if (updating_scene_tree) {
-
- return;
- }
- TreeItem *item=obj->cast_to<TreeItem>();
-
- if (!item)
- return;
-
- ObjectID id = item->get_metadata(0);
- if (item->is_collapsed()) {
- unfold_cache.erase(id);
- } else {
- unfold_cache.insert(id);
- }
-
-
-}
-
-void ScriptEditorDebugger::_scene_tree_selected() {
-
-
- if (updating_scene_tree) {
-
- return;
- }
- TreeItem *item = inspect_scene_tree->get_selected();
- if (!item) {
-
- return;
- }
-
- inspected_object_id = item->get_metadata(0);
-
- Array msg;
- msg.push_back("inspect_object");
- msg.push_back(inspected_object_id);
- ppeer->put_var(msg);
-
-}
-
-void ScriptEditorDebugger::_scene_tree_property_value_edited(const String& p_prop,const Variant& p_value) {
-
-
- Array msg;
- msg.push_back("set_object_property");
- msg.push_back(inspected_object_id);
- msg.push_back(p_prop);
- msg.push_back(p_value);
- ppeer->put_var(msg);
- inspect_edited_object_timeout=0.7; //avoid annoyance, don't request soon after editing
-}
-
-void ScriptEditorDebugger::_scene_tree_property_select_object(ObjectID p_object) {
-
- inspected_object_id=p_object;
- Array msg;
- msg.push_back("inspect_object");
- msg.push_back(inspected_object_id);
- ppeer->put_var(msg);
-
-}
-
-void ScriptEditorDebugger::_scene_tree_request() {
-
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
-
- Array msg;
- msg.push_back("request_scene_tree");
- ppeer->put_var(msg);
-
-}
-
-void ScriptEditorDebugger::_video_mem_request() {
-
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
-
- Array msg;
- msg.push_back("request_video_mem");
- ppeer->put_var(msg);
-
-}
-
-Size2 ScriptEditorDebugger::get_minimum_size() const {
-
- Size2 ms = Control::get_minimum_size();
- ms.y = MAX(ms.y , 250 );
- return ms;
-
-}
-void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_data) {
-
-
-
- if (p_msg=="debug_enter") {
-
- Array msg;
- msg.push_back("get_stack_dump");
- ppeer->put_var(msg);
- ERR_FAIL_COND(p_data.size()!=2);
- bool can_continue=p_data[0];
- String error = p_data[1];
- step->set_disabled(!can_continue);
- next->set_disabled(!can_continue);
- reason->set_text(error);
- reason->set_tooltip(error);
- breaked=true;
- dobreak->set_disabled(true);
- docontinue->set_disabled(false);
- emit_signal("breaked",true,can_continue);
- OS::get_singleton()->move_window_to_foreground();
- if (error!="") {
- tabs->set_current_tab(0);
- }
-
- profiler->set_enabled(false);
-
- EditorNode::get_singleton()->get_pause_button()->set_pressed(true);
-
-
- EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
-
- } else if (p_msg=="debug_exit") {
-
- breaked=false;
- step->set_disabled(true);
- next->set_disabled(true);
- reason->set_text("");
- reason->set_tooltip("");
- back->set_disabled(true);
- forward->set_disabled(true);
- dobreak->set_disabled(false);
- docontinue->set_disabled(true);
- emit_signal("breaked",false,false,Variant());
- //tabs->set_current_tab(0);
- profiler->set_enabled(true);
- profiler->disable_seeking();
-
- EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
-
-
- } else if (p_msg=="message:click_ctrl") {
-
- clicked_ctrl->set_text(p_data[0]);
- clicked_ctrl_type->set_text(p_data[1]);
-
- } else if (p_msg=="message:scene_tree") {
-
- inspect_scene_tree->clear();
- Map<int,TreeItem*> lv;
-
- updating_scene_tree=true;
-
- for(int i=0;i<p_data.size();i+=4) {
-
- TreeItem *p;
- int level = p_data[i];
- if (level==0) {
- p = NULL;
- } else {
- ERR_CONTINUE(!lv.has(level-1));
- p=lv[level-1];
- }
-
-
- TreeItem *it = inspect_scene_tree->create_item(p);
-
- ObjectID id = ObjectID(p_data[i+3]);
-
- it->set_text(0,p_data[i+1]);
- if (has_icon(p_data[i+2],"EditorIcons"))
- it->set_icon(0,get_icon(p_data[i+2],"EditorIcons"));
- it->set_metadata(0,id);
- if (id==inspected_object_id) {
- it->select(0);
- }
-
- if (p) {
- if (!unfold_cache.has(id)) {
- it->set_collapsed(true);
- }
- } else {
- if (unfold_cache.has(id)) { //reverse for root
- it->set_collapsed(true);
- }
- }
- lv[level]=it;
- }
- updating_scene_tree=false;
-
- le_clear->set_disabled(false);
- le_set->set_disabled(false);
- } else if (p_msg=="message:inspect_object") {
-
-
- ObjectID id = p_data[0];
- String type = p_data[1];
- Variant path = p_data[2]; //what to do yet, i don't know
- int prop_count=p_data[3];
-
- int idx=4;
-
-
- if (inspected_object->last_edited_id!=id) {
- inspected_object->prop_list.clear();
- inspected_object->prop_values.clear();
- }
-
- for(int i=0;i<prop_count;i++) {
-
- PropertyInfo pinfo;
- pinfo.name=p_data[idx++];
- pinfo.type=Variant::Type(int(p_data[idx++]));
- pinfo.hint=PropertyHint(int(p_data[idx++]));
- pinfo.hint_string=p_data[idx++];
- if (pinfo.name.begins_with("*")) {
- pinfo.name=pinfo.name.substr(1,pinfo.name.length());
- pinfo.usage=PROPERTY_USAGE_CATEGORY;
- } else {
- pinfo.usage=PROPERTY_USAGE_EDITOR;
- }
-
- if (inspected_object->last_edited_id!=id) {
- //don't update.. it's the same, instead refresh
- inspected_object->prop_list.push_back(pinfo);
- }
-
-
- inspected_object->prop_values[pinfo.name]=p_data[idx++];
-
- if (inspected_object->last_edited_id==id) {
- //same, just update value, don't rebuild
- inspected_object->update_single(pinfo.name.ascii().get_data());
- }
-
- }
-
-
-
- if (inspected_object->last_edited_id!=id) {
- //only if different
- inspected_object->update();
- }
-
- inspected_object->last_edited_id=id;
-
-
- inspect_properties->edit(inspected_object);
-
- } else if (p_msg=="message:video_mem") {
-
- vmem_tree->clear();
- TreeItem* root=vmem_tree->create_item();
-
- int total=0;
-
- for(int i=0;i<p_data.size();i+=4) {
-
- TreeItem *it = vmem_tree->create_item(root);
- String type=p_data[i+1];
- int bytes=p_data[i+3].operator int();
- it->set_text(0,p_data[i+0]); //path
- it->set_text(1,type); //type
- it->set_text(2,p_data[i+2]); //type
- it->set_text(3,String::humanize_size(bytes)); //type
- total+=bytes;
-
- if (has_icon(type,"EditorIcons"))
- it->set_icon(0,get_icon(type,"EditorIcons"));
- }
-
- vmem_total->set_tooltip(TTR("Bytes:")+" "+itos(total));
- vmem_total->set_text(String::humanize_size(total));
-
- } else if (p_msg=="stack_dump") {
-
- stack_dump->clear();
- TreeItem *r = stack_dump->create_item();
-
- for(int i=0;i<p_data.size();i++) {
-
- Dictionary d = p_data[i];
- ERR_CONTINUE(!d.has("function"));
- ERR_CONTINUE(!d.has("file"));
- ERR_CONTINUE(!d.has("line"));
- ERR_CONTINUE(!d.has("id"));
- TreeItem *s = stack_dump->create_item(r);
- d["frame"]=i;
- s->set_metadata(0,d);
-
- //String line = itos(i)+" - "+String(d["file"])+":"+itos(d["line"])+" - at func: "+d["function"];
- String line = itos(i)+" - "+String(d["file"])+":"+itos(d["line"]);
- s->set_text(0,line);
-
- if (i==0)
- s->select(0);
- }
- } else if (p_msg=="stack_frame_vars") {
-
-
- variables->clear();
-
-
-
- int ofs =0;
- int mcount = p_data[ofs];
-
- ofs++;
- for(int i=0;i<mcount;i++) {
-
- String n = p_data[ofs+i*2+0];
- Variant v = p_data[ofs+i*2+1];
-
- if (n.begins_with("*")) {
-
- n=n.substr(1,n.length());
- }
-
- variables->add_property("members/"+n,v);
- }
- ofs+=mcount*2;
-
- mcount = p_data[ofs];
-
- ofs++;
- for(int i=0;i<mcount;i++) {
-
- String n = p_data[ofs+i*2+0];
- Variant v = p_data[ofs+i*2+1];
-
- if (n.begins_with("*")) {
-
- n=n.substr(1,n.length());
- }
-
-
- variables->add_property("locals/"+n,v);
- }
-
- variables->update();
- inspector->edit(variables);
-
- } else if (p_msg=="output") {
-
- //OUT
- for(int i=0;i<p_data.size();i++) {
-
- String t = p_data[i];
- //LOG
-
- if (!EditorNode::get_log()->is_visible()) {
- if (EditorNode::get_singleton()->are_bottom_panels_hidden()) {
- EditorNode::get_singleton()->make_bottom_panel_item_visible(EditorNode::get_log());
- }
- }
- EditorNode::get_log()->add_message(t);
-
- }
-
- } else if (p_msg=="performance") {
- Array arr = p_data[0];
- Vector<float> p;
- p.resize(arr.size());
- for(int i=0;i<arr.size();i++) {
- p[i]=arr[i];
- if (i<perf_items.size()) {
- perf_items[i]->set_text(1,rtos(p[i]));
- if (p[i]>perf_max[i])
- perf_max[i]=p[i];
- }
-
- }
- perf_history.push_front(p);
- perf_draw->update();
-
- } else if (p_msg=="error") {
-
- Array err = p_data[0];
-
- Array vals;
- vals.push_back(err[0]);
- vals.push_back(err[1]);
- vals.push_back(err[2]);
- vals.push_back(err[3]);
-
- bool warning = err[9];
- bool e;
- String time = String("%d:%02d:%02d:%04d").sprintf(vals,&e);
- String txt=time+" - "+(err[8].is_zero()?String(err[7]):String(err[8]));
-
- String tooltip=TTR("Type:")+String(warning?TTR("Warning"):TTR("Error"));
- tooltip+="\n"+TTR("Description:")+" "+String(err[8]);
- tooltip+="\n"+TTR("Time:")+" "+time;
- tooltip+="\nC "+TTR("Error:")+" "+String(err[7]);
- tooltip+="\nC "+TTR("Source:")+" "+String(err[5])+":"+String(err[6]);
- tooltip+="\nC "+TTR("Function:")+" "+String(err[4]);
-
-
-
- error_list->add_item(txt,EditorNode::get_singleton()->get_gui_base()->get_icon(warning?"Warning":"Error","EditorIcons"));
- error_list->set_item_tooltip( error_list->get_item_count() -1,tooltip );
-
- int scc = p_data[1];
-
- Array stack;
- stack.resize(scc);
- for(int i=0;i<scc;i++) {
- stack[i]=p_data[2+i];
- }
-
- error_list->set_item_metadata( error_list->get_item_count() -1,stack );
-
- error_count++;
- /*
- int count = p_data[1];
-
- Array cstack;
-
- OutputError oe = errors.front()->get();
-
- packet_peer_stream->put_var(oe.hr);
- packet_peer_stream->put_var(oe.min);
- packet_peer_stream->put_var(oe.sec);
- packet_peer_stream->put_var(oe.msec);
- packet_peer_stream->put_var(oe.source_func);
- packet_peer_stream->put_var(oe.source_file);
- packet_peer_stream->put_var(oe.source_line);
- packet_peer_stream->put_var(oe.error);
- packet_peer_stream->put_var(oe.error_descr);
- packet_peer_stream->put_var(oe.warning);
- packet_peer_stream->put_var(oe.callstack);
- */
-
- } else if (p_msg=="profile_sig") {
- //cache a signature
- print_line("SIG: "+String(Variant(p_data)));
- profiler_signature[p_data[1]]=p_data[0];
-
- } else if (p_msg=="profile_frame" || p_msg=="profile_total") {
-
- EditorProfiler::Metric metric;
- metric.valid=true;
- metric.frame_number=p_data[0];
- metric.frame_time=p_data[1];
- metric.idle_time=p_data[2];
- metric.fixed_time=p_data[3];
- metric.fixed_frame_time=p_data[4];
- int frame_data_amount = p_data[6];
- int frame_function_amount = p_data[7];
-
-
- if (frame_data_amount) {
- EditorProfiler::Metric::Category frame_time;
- frame_time.signature="category_frame_time";
- frame_time.name="Frame Time";
- frame_time.total_time=metric.frame_time;
-
- EditorProfiler::Metric::Category::Item item;
- item.calls=1;
- item.line=0;
- item.name="Fixed Time";
- item.total=metric.fixed_time;
- item.self=item.total;
- item.signature="fixed_time";
-
-
- frame_time.items.push_back(item);
-
- item.name="Idle Time";
- item.total=metric.idle_time;
- item.self=item.total;
- item.signature="idle_time";
-
- frame_time.items.push_back(item);
-
- item.name="Fixed Frame Time";
- item.total=metric.fixed_frame_time;
- item.self=item.total;
- item.signature="fixed_frame_time";
-
- frame_time.items.push_back(item);
-
- metric.categories.push_back(frame_time);
-
- }
-
-
-
- int idx=8;
- for(int i=0;i<frame_data_amount;i++) {
-
- EditorProfiler::Metric::Category c;
- String name=p_data[idx++];
- Array values=p_data[idx++];
- c.name=name.capitalize();
- c.items.resize(values.size()/2);
- c.total_time=0;
- c.signature="categ::"+name;
- for(int i=0;i<values.size();i+=2) {
-
- EditorProfiler::Metric::Category::Item item;
- item.name=values[i];
- item.calls=1;
- item.self=values[i+1];
- item.total=item.self;
- item.signature="categ::"+name+"::"+item.name;
- item.name=item.name.capitalize();
- c.total_time+=item.total;
- c.items[i/2]=item;
-
-
- }
- metric.categories.push_back(c);
- }
-
- EditorProfiler::Metric::Category funcs;
- funcs.total_time=p_data[5]; //script time
- funcs.items.resize(frame_function_amount);
- funcs.name="Script Functions";
- funcs.signature="script_functions";
- for(int i=0;i<frame_function_amount;i++) {
-
- int signature = p_data[idx++];
- int calls = p_data[idx++];
- float total = p_data[idx++];
- float self = p_data[idx++];
-
-
-
- EditorProfiler::Metric::Category::Item item;
- if (profiler_signature.has(signature)) {
-
- item.signature=profiler_signature[signature];
-
- String name = profiler_signature[signature];
- Vector<String> strings = name.split("::");
- if (strings.size()==3) {
- item.name=strings[2];
- item.script=strings[0];
- item.line=strings[1].to_int();
- }
-
- } else {
- item.name="SigErr "+itos(signature);
- }
-
-
-
-
- item.calls=calls;
- item.self=self;
- item.total=total;
- funcs.items[i]=item;
-
- }
-
- metric.categories.push_back(funcs);
-
- if (p_msg=="profile_frame")
- profiler->add_frame_metric(metric,false);
- else
- profiler->add_frame_metric(metric,true);
-
- } else if (p_msg=="kill_me") {
-
- editor->call_deferred("stop_child_process");
- }
-
-}
-
-
-void ScriptEditorDebugger::_performance_select(Object*,int,bool) {
-
- perf_draw->update();
-
-}
-
-void ScriptEditorDebugger::_performance_draw() {
-
-
- Vector<int> which;
- for(int i=0;i<perf_items.size();i++) {
-
-
- if (perf_items[i]->is_selected(0))
- which.push_back(i);
- }
-
-
- if(which.empty())
- return;
-
- Ref<StyleBox> graph_sb = get_stylebox("normal","TextEdit");
- Ref<Font> graph_font = get_font("font","TextEdit");
-
- int cols = Math::ceil(Math::sqrt((float)which.size()));
- int rows = (which.size()+1)/cols;
- if (which.size()==1)
- rows=1;
-
-
- int margin =3;
- int point_sep=5;
- Size2i s = Size2i(perf_draw->get_size())/Size2i(cols,rows);
- for(int i=0;i<which.size();i++) {
-
- Point2i p(i%cols,i/cols);
- Rect2i r(p*s,s);
- r.pos+=Point2(margin,margin);
- r.size-=Point2(margin,margin)*2.0;
- perf_draw->draw_style_box(graph_sb,r);
- r.pos+=graph_sb->get_offset();
- r.size-=graph_sb->get_minimum_size();
- int pi=which[i];
- Color c = Color(0.7,0.9,0.5);
- c.set_hsv(Math::fmod(c.get_h()+pi*0.7654,1),c.get_s(),c.get_v());
-
- c.a=0.8;
- perf_draw->draw_string(graph_font,r.pos+Point2(0,graph_font->get_ascent()),perf_items[pi]->get_text(0),c,r.size.x);
- c.a=0.6;
- perf_draw->draw_string(graph_font,r.pos+Point2(graph_font->get_char_size('X').width,graph_font->get_ascent()+graph_font->get_height()),perf_items[pi]->get_text(1),c,r.size.y);
-
- float spacing=point_sep/float(cols);
- float from = r.size.width;
-
- List<Vector<float> >::Element *E=perf_history.front();
- float prev=-1;
- while(from>=0 && E) {
-
- float m = perf_max[pi];
- if (m==0)
- m=0.00001;
- float h = E->get()[pi]/m;
- h=(1.0-h)*r.size.y;
-
- c.a=0.7;
- if (E!=perf_history.front())
- perf_draw->draw_line(r.pos+Point2(from,h),r.pos+Point2(from+spacing,prev),c,2.0);
- prev=h;
- E=E->next();
- from-=spacing;
- }
-
- }
-
-}
-
-void ScriptEditorDebugger::_notification(int p_what) {
-
- switch(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"));
- forward->set_icon( get_icon("Forward","EditorIcons"));
- dobreak->set_icon( get_icon("Pause","EditorIcons"));
- docontinue->set_icon( get_icon("DebugContinue","EditorIcons"));
- //scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons"));
- le_set->connect("pressed",this,"_live_edit_set");
- le_clear->connect("pressed",this,"_live_edit_clear");
- error_list->connect("item_selected",this,"_error_selected");
- error_stack->connect("item_selected",this,"_error_stack_selected");
- vmem_refresh->set_icon( get_icon("Reload","EditorIcons"));
-
- } break;
- case NOTIFICATION_PROCESS: {
-
- if (connection.is_valid()) {
- inspect_scene_tree_timeout-=get_process_delta_time();
- if (inspect_scene_tree_timeout<0) {
- inspect_scene_tree_timeout=EditorSettings::get_singleton()->get("debugger/scene_tree_refresh_interval");
- if (inspect_scene_tree->is_visible_in_tree()) {
- _scene_tree_request();
-
- if (inspected_object_id!=0) {
- //take the chance and re-inspect selected object
- Array msg;
- msg.push_back("inspect_object");
- msg.push_back(inspected_object_id);
- ppeer->put_var(msg);
- }
- }
- }
-
- inspect_edited_object_timeout-=get_process_delta_time();
- if (inspect_edited_object_timeout<0) {
- inspect_edited_object_timeout=EditorSettings::get_singleton()->get("debugger/remote_inspect_refresh_interval");
- if (inspect_scene_tree->is_visible_in_tree() && inspected_object_id) {
- //take the chance and re-inspect selected object
- Array msg;
- msg.push_back("inspect_object");
- msg.push_back(inspected_object_id);
- ppeer->put_var(msg);
- }
- }
- }
-
- if (error_count!=last_error_count) {
-
- if (error_count==0) {
- error_split->set_name(TTR("Errors"));
- debugger_button->set_text(TTR("Debugger"));
- debugger_button->set_icon(Ref<Texture>());
- tabs->set_tab_icon(error_split->get_index(),Ref<Texture>());
- } else {
- error_split->set_name(TTR("Errors")+" ("+itos(error_count)+")");
- debugger_button->set_text(TTR("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;
- }
-
- if (connection.is_null()) {
-
- if (server->is_connection_available()) {
-
- connection = server->take_connection();
- if (connection.is_null())
- break;
-
- EditorNode::get_log()->add_message("** Debug Process Started **");
-
- ppeer->set_stream_peer(connection);
-
- //EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
- //emit_signal("show_debugger",true);
-
- dobreak->set_disabled(false);
- tabs->set_current_tab(0);
-
- reason->set_text(TTR("Child Process Connected"));
- reason->set_tooltip(TTR("Child Process Connected"));
- profiler->clear();
-
- inspect_scene_tree->clear();
- le_set->set_disabled(true);
- le_clear->set_disabled(false);
- error_list->clear();
- error_stack->clear();
- error_count=0;
- profiler_signature.clear();
- //live_edit_root->set_text("/root");
-
- EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
- EditorNode::get_singleton()->get_pause_button()->set_disabled(false);
-
- update_live_edit_root();
- if (profiler->is_profiling()) {
- _profiler_activate(true);
- }
-
-
- } else {
-
- break;
- }
- };
-
- if (!connection->is_connected_to_host()) {
- stop();
- editor->notify_child_process_exited(); //somehow, exited
- break;
- };
-
- if (ppeer->get_available_packet_count() <= 0) {
- break;
- };
-
- while(ppeer->get_available_packet_count() > 0) {
-
- if (pending_in_queue) {
-
- int todo = MIN( ppeer->get_available_packet_count(), pending_in_queue );
-
- for(int i=0;i<todo;i++) {
-
- Variant cmd;
- Error ret = ppeer->get_var(cmd);
- if (ret!=OK) {
- stop();
- ERR_FAIL_COND(ret!=OK);
- }
-
- message.push_back(cmd);
- pending_in_queue--;
- }
-
-
- if (pending_in_queue==0) {
- _parse_message(message_type,message);
- message.clear();
-
- }
-
-
- } else {
-
- if (ppeer->get_available_packet_count()>=2) {
-
-
- Variant cmd;
- Error ret = ppeer->get_var(cmd);
- if (ret!=OK) {
- stop();
- ERR_FAIL_COND(ret!=OK);
- }
- if (cmd.get_type()!=Variant::STRING) {
- stop();
- ERR_FAIL_COND(cmd.get_type()!=Variant::STRING);
- }
-
- message_type=cmd;
- //print_line("GOT: "+message_type);
-
- ret = ppeer->get_var(cmd);
- if (ret!=OK) {
- stop();
- ERR_FAIL_COND(ret!=OK);
- }
- if (cmd.get_type()!=Variant::INT) {
- stop();
- ERR_FAIL_COND(cmd.get_type()!=Variant::INT);
- }
-
- pending_in_queue=cmd;
-
- if (pending_in_queue==0) {
- _parse_message(message_type,Array());
- message.clear();
- }
-
- } else {
-
-
- break;
- }
-
- }
- }
-
-
-
- } break;
- }
-
-}
-
-
-void ScriptEditorDebugger::start() {
-
- stop();
-
- if (is_visible_in_tree()) {
- EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
- }
-
- uint16_t port = GLOBAL_GET("network/debug/remote_port");
- perf_history.clear();
- for(int i=0;i<Performance::MONITOR_MAX;i++) {
-
- perf_max[i]=0;
- }
-
- server->listen(port);
- set_process(true);
-
-}
-
-void ScriptEditorDebugger::pause(){
-
-
-}
-
-void ScriptEditorDebugger::unpause(){
-
-
-}
-
-void ScriptEditorDebugger::stop(){
-
-
- set_process(false);
-
- server->stop();
-
- ppeer->set_stream_peer(Ref<StreamPeer>());
-
- if (connection.is_valid()) {
- EditorNode::get_log()->add_message("** Debug Process Stopped **");
- connection.unref();
- }
-
- pending_in_queue=0;
- message.clear();
-
- node_path_cache.clear();
- res_path_cache.clear();
- profiler_signature.clear();
- le_clear->set_disabled(false);
- le_set->set_disabled(true);
- profiler->set_enabled(true);
-
- inspect_properties->edit(NULL);
- inspect_scene_tree->clear();
-
- EditorNode::get_singleton()->get_pause_button()->set_pressed(false);
- EditorNode::get_singleton()->get_pause_button()->set_disabled(true);
-
-
-
- if (hide_on_stop) {
- if (is_visible_in_tree())
- EditorNode::get_singleton()->hide_bottom_panel();
- emit_signal("show_debugger",false);
- }
-
-}
-
-void ScriptEditorDebugger::_profiler_activate(bool p_enable) {
-
- if (!connection.is_valid())
- return;
-
-
- if (p_enable) {
- profiler_signature.clear();
- Array msg;
- msg.push_back("start_profiling");
- int max_funcs = EditorSettings::get_singleton()->get("debugger/profiler_frame_max_functions");
- max_funcs = CLAMP(max_funcs,16,512);
- msg.push_back(max_funcs);
- ppeer->put_var(msg);
-
- print_line("BEGIN PROFILING!");
-
- } else {
- Array msg;
- msg.push_back("stop_profiling");
- ppeer->put_var(msg);
-
- print_line("END PROFILING!");
-
- }
-
-}
-
-void ScriptEditorDebugger::_profiler_seeked() {
-
- if (!connection.is_valid() || !connection->is_connected_to_host())
- return;
-
- if (breaked)
- return;
- debug_break();
-}
-
-
-void ScriptEditorDebugger::_stack_dump_frame_selected() {
-
- TreeItem *ti = stack_dump->get_selected();
- if (!ti)
- return;
-
-
- Dictionary d = ti->get_metadata(0);
-
- Ref<Script> s = ResourceLoader::load(d["file"]);
- emit_signal("goto_script_line",s,int(d["line"])-1);
-
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
- ///
-
- Array msg;
- msg.push_back("get_stack_frame_vars");
- msg.push_back(d["frame"]);
- ppeer->put_var(msg);
-
-}
-
-void ScriptEditorDebugger::_output_clear() {
-
- //output->clear();
- //output->push_color(Color(0,0,0));
-
-}
-
-String ScriptEditorDebugger::get_var_value(const String& p_var) const {
- if (!breaked)
- return String();
- return variables->get_var_value(p_var);
-}
-
-int ScriptEditorDebugger::_get_node_path_cache(const NodePath& p_path) {
-
- const int *r = node_path_cache.getptr(p_path);
- if (r)
- return *r;
-
- last_path_id++;
-
- node_path_cache[p_path]=last_path_id;
- Array msg;
- msg.push_back("live_node_path");
- msg.push_back(p_path);
- msg.push_back(last_path_id);
- ppeer->put_var(msg);
-
-
- return last_path_id;
-}
-
-int ScriptEditorDebugger::_get_res_path_cache(const String& p_path) {
-
- Map<String,int>::Element *E=res_path_cache.find(p_path);
-
- if (E)
- return E->get();
-
- last_path_id++;
-
- res_path_cache[p_path]=last_path_id;
- Array msg;
- msg.push_back("live_res_path");
- msg.push_back(p_path);
- msg.push_back(last_path_id);
- ppeer->put_var(msg);
-
-
- return last_path_id;
-}
-
-void ScriptEditorDebugger::_method_changed(Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) {
-
- if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene())
- return;
-
- Node *node = p_base->cast_to<Node>();
-
- VARIANT_ARGPTRS
-
- for(int i=0;i<VARIANT_ARG_MAX;i++) {
- //no pointers, sorry
- if (argptr[i] && (argptr[i]->get_type()==Variant::OBJECT || argptr[i]->get_type()==Variant::_RID))
- return;
- }
-
- if (node) {
-
- NodePath path = editor->get_edited_scene()->get_path_to(node);
- int pathid = _get_node_path_cache(path);
-
-
-
- Array msg;
- msg.push_back("live_node_call");
- msg.push_back(pathid);
- msg.push_back(p_name);
- for(int i=0;i<VARIANT_ARG_MAX;i++) {
- //no pointers, sorry
- msg.push_back(*argptr[i]);
- }
- ppeer->put_var(msg);
-
- return;
-
- }
-
- Resource *res = p_base->cast_to<Resource>();
-
- if (res && res->get_path()!=String()) {
-
- String respath = res->get_path();
- int pathid = _get_res_path_cache(respath);
-
- Array msg;
- msg.push_back("live_res_call");
- msg.push_back(pathid);
- msg.push_back(p_name);
- for(int i=0;i<VARIANT_ARG_MAX;i++) {
- //no pointers, sorry
- msg.push_back(*argptr[i]);
- }
- ppeer->put_var(msg);
-
- return;
- }
-
- //print_line("method");
-}
-
-void ScriptEditorDebugger::_property_changed(Object*p_base,const StringName& p_property,const Variant& p_value){
-
- if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene())
- return;
-
- Node *node = p_base->cast_to<Node>();
-
- if (node) {
-
- NodePath path = editor->get_edited_scene()->get_path_to(node);
- int pathid = _get_node_path_cache(path);
-
-
- if (p_value.is_ref()) {
- Ref<Resource> res = p_value;
- if (res.is_valid() && res->get_path()!=String()) {
-
- Array msg;
- msg.push_back("live_node_prop_res");
- msg.push_back(pathid);
- msg.push_back(p_property);
- msg.push_back(res->get_path());
- ppeer->put_var(msg);
- }
- } else {
-
- Array msg;
- msg.push_back("live_node_prop");
- msg.push_back(pathid);
- msg.push_back(p_property);
- msg.push_back(p_value);
- ppeer->put_var(msg);
- }
-
-
- return;
-
- }
-
- Resource *res = p_base->cast_to<Resource>();
-
- if (res && res->get_path()!=String()) {
-
- String respath = res->get_path();
- int pathid = _get_res_path_cache(respath);
-
-
- if (p_value.is_ref()) {
- Ref<Resource> res = p_value;
- if (res.is_valid() && res->get_path()!=String()) {
-
- Array msg;
- msg.push_back("live_res_prop_res");
- msg.push_back(pathid);
- msg.push_back(p_property);
- msg.push_back(res->get_path());
- ppeer->put_var(msg);
- }
- } else {
-
- Array msg;
- msg.push_back("live_res_prop");
- msg.push_back(pathid);
- msg.push_back(p_property);
- msg.push_back(p_value);
- ppeer->put_var(msg);
- }
-
-
- return;
- }
-
-
- //print_line("prop");
-}
-
-void ScriptEditorDebugger::_method_changeds(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) {
-
- ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud;
- sed->_method_changed(p_base,p_name,VARIANT_ARG_PASS);
-
-
-}
-
-void ScriptEditorDebugger::_property_changeds(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value){
-
- ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud;
- sed->_property_changed(p_base,p_property,p_value);
-
-}
-
-void ScriptEditorDebugger::set_live_debugging(bool p_enable) {
-
- live_debug=p_enable;
-}
-
-void ScriptEditorDebugger::_live_edit_set() {
-
- if (!connection.is_valid())
- return;
-
- TreeItem* ti = inspect_scene_tree->get_selected();
- if (!ti)
- return;
- String path;
-
- while(ti) {
- String lp=ti->get_text(0);
- path="/"+lp+path;
- ti=ti->get_parent();
-
- }
-
- NodePath np = path;
-
- editor->get_editor_data().set_edited_scene_live_edit_root(np);
-
- update_live_edit_root();
-
-
-}
-
-void ScriptEditorDebugger::_live_edit_clear() {
-
- NodePath np = NodePath("/root");
- editor->get_editor_data().set_edited_scene_live_edit_root(np);
-
- update_live_edit_root();
-
-}
-
-void ScriptEditorDebugger::update_live_edit_root() {
-
- NodePath np = editor->get_editor_data().get_edited_scene_live_edit_root();
-
- if (connection.is_valid()) {
- Array msg;
- msg.push_back("live_set_root");
- msg.push_back(np);
- if (editor->get_edited_scene())
- msg.push_back(editor->get_edited_scene()->get_filename());
- else
- msg.push_back("");
- ppeer->put_var(msg);
- }
- live_edit_root->set_text(np);
-
-}
-
-void ScriptEditorDebugger::live_debug_create_node(const NodePath& p_parent,const String& p_type,const String& p_name) {
-
- if (live_debug && connection.is_valid()) {
- Array msg;
- msg.push_back("live_create_node");
- msg.push_back(p_parent);
- msg.push_back(p_type);
- msg.push_back(p_name);
- ppeer->put_var(msg);
- }
-}
-
-void ScriptEditorDebugger::live_debug_instance_node(const NodePath& p_parent,const String& p_path,const String& p_name){
-
- if (live_debug && connection.is_valid()) {
- Array msg;
- msg.push_back("live_instance_node");
- msg.push_back(p_parent);
- msg.push_back(p_path);
- msg.push_back(p_name);
- ppeer->put_var(msg);
- }
-
-}
-void ScriptEditorDebugger::live_debug_remove_node(const NodePath& p_at){
-
- if (live_debug && connection.is_valid()) {
- Array msg;
- msg.push_back("live_remove_node");
- msg.push_back(p_at);
- ppeer->put_var(msg);
- }
-
-}
-void ScriptEditorDebugger::live_debug_remove_and_keep_node(const NodePath& p_at,ObjectID p_keep_id) {
-
- if (live_debug && connection.is_valid()) {
- Array msg;
- msg.push_back("live_remove_and_keep_node");
- msg.push_back(p_at);
- msg.push_back(p_keep_id);
- ppeer->put_var(msg);
- }
-
-}
-void ScriptEditorDebugger::live_debug_restore_node(ObjectID p_id, const NodePath& p_at, int p_at_pos){
-
- if (live_debug && connection.is_valid()) {
- Array msg;
- msg.push_back("live_restore_node");
- msg.push_back(p_id);
- msg.push_back(p_at);
- msg.push_back(p_at_pos);
- ppeer->put_var(msg);
- }
-
-}
-void ScriptEditorDebugger::live_debug_duplicate_node(const NodePath& p_at,const String& p_new_name){
-
- if (live_debug && connection.is_valid()) {
- Array msg;
- msg.push_back("live_duplicate_node");
- msg.push_back(p_at);
- msg.push_back(p_new_name);
- ppeer->put_var(msg);
- }
-
-}
-void ScriptEditorDebugger::live_debug_reparent_node(const NodePath& p_at, const NodePath& p_new_place, const String &p_new_name, int p_at_pos){
-
- if (live_debug && connection.is_valid()) {
- Array msg;
- msg.push_back("live_reparent_node");
- msg.push_back(p_at);
- msg.push_back(p_new_place);
- msg.push_back(p_new_name);
- msg.push_back(p_at_pos);
- ppeer->put_var(msg);
- }
-
-}
-
-void ScriptEditorDebugger::set_breakpoint(const String& p_path,int p_line,bool p_enabled) {
-
- if (connection.is_valid()) {
- Array msg;
- msg.push_back("breakpoint");
- msg.push_back(p_path);
- msg.push_back(p_line);
- msg.push_back(p_enabled);
- ppeer->put_var(msg);
- }
-}
-
-
-void ScriptEditorDebugger::reload_scripts() {
-
- if (connection.is_valid()) {
- Array msg;
- msg.push_back("reload_scripts");
- ppeer->put_var(msg);
- }
-}
-
-
-void ScriptEditorDebugger::_error_selected(int p_idx) {
-
- error_stack->clear();
- Array st=error_list->get_item_metadata(p_idx);
- for(int i=0;i<st.size();i+=2) {
-
- String script=st[i];
- int line=st[i+1];
- Array md;
- md.push_back(st[i]);
- md.push_back(st[i+1]);
-
- String str = script.get_file()+":"+itos(line);
-
- error_stack->add_item(str);
- error_stack->set_item_metadata(error_stack->get_item_count()-1,md);
- error_stack->set_item_tooltip(error_stack->get_item_count()-1,TTR("File:")+" "+String(st[i])+"\n"+TTR("Line:")+" "+itos(line));
- }
-}
-
-void ScriptEditorDebugger:: _error_stack_selected(int p_idx){
-
- Array arr = error_stack->get_item_metadata(p_idx);
- if (arr.size()!=2)
- return;
-
-
- Ref<Script> s = ResourceLoader::load(arr[0]);
- emit_signal("goto_script_line",s,int(arr[1])-1);
-
-}
-
-void ScriptEditorDebugger::set_hide_on_stop(bool p_hide) {
-
- hide_on_stop=p_hide;
-}
-
-void ScriptEditorDebugger::_paused() {
-
- ERR_FAIL_COND(connection.is_null());
- ERR_FAIL_COND(!connection->is_connected_to_host());
-
- if (!breaked && EditorNode::get_singleton()->get_pause_button()->is_pressed()) {
- debug_break();
- }
-
- if (breaked && !EditorNode::get_singleton()->get_pause_button()->is_pressed()) {
- debug_continue();
- }
-
-}
-
-void ScriptEditorDebugger::_bind_methods() {
-
- ClassDB::bind_method(_MD("_stack_dump_frame_selected"),&ScriptEditorDebugger::_stack_dump_frame_selected);
- ClassDB::bind_method(_MD("debug_next"),&ScriptEditorDebugger::debug_next);
- ClassDB::bind_method(_MD("debug_step"),&ScriptEditorDebugger::debug_step);
- ClassDB::bind_method(_MD("debug_break"),&ScriptEditorDebugger::debug_break);
- ClassDB::bind_method(_MD("debug_continue"),&ScriptEditorDebugger::debug_continue);
- ClassDB::bind_method(_MD("_output_clear"),&ScriptEditorDebugger::_output_clear);
- ClassDB::bind_method(_MD("_performance_draw"),&ScriptEditorDebugger::_performance_draw);
- ClassDB::bind_method(_MD("_performance_select"),&ScriptEditorDebugger::_performance_select);
- ClassDB::bind_method(_MD("_scene_tree_request"),&ScriptEditorDebugger::_scene_tree_request);
- ClassDB::bind_method(_MD("_video_mem_request"),&ScriptEditorDebugger::_video_mem_request);
- ClassDB::bind_method(_MD("_live_edit_set"),&ScriptEditorDebugger::_live_edit_set);
- ClassDB::bind_method(_MD("_live_edit_clear"),&ScriptEditorDebugger::_live_edit_clear);
-
- ClassDB::bind_method(_MD("_error_selected"),&ScriptEditorDebugger::_error_selected);
- ClassDB::bind_method(_MD("_error_stack_selected"),&ScriptEditorDebugger::_error_stack_selected);
- ClassDB::bind_method(_MD("_profiler_activate"),&ScriptEditorDebugger::_profiler_activate);
- ClassDB::bind_method(_MD("_profiler_seeked"),&ScriptEditorDebugger::_profiler_seeked);
-
- ClassDB::bind_method(_MD("_paused"),&ScriptEditorDebugger::_paused);
-
- ClassDB::bind_method(_MD("_scene_tree_selected"),&ScriptEditorDebugger::_scene_tree_selected);
- ClassDB::bind_method(_MD("_scene_tree_folded"),&ScriptEditorDebugger::_scene_tree_folded);
-
-
- ClassDB::bind_method(_MD("live_debug_create_node"),&ScriptEditorDebugger::live_debug_create_node);
- ClassDB::bind_method(_MD("live_debug_instance_node"),&ScriptEditorDebugger::live_debug_instance_node);
- ClassDB::bind_method(_MD("live_debug_remove_node"),&ScriptEditorDebugger::live_debug_remove_node);
- ClassDB::bind_method(_MD("live_debug_remove_and_keep_node"),&ScriptEditorDebugger::live_debug_remove_and_keep_node);
- ClassDB::bind_method(_MD("live_debug_restore_node"),&ScriptEditorDebugger::live_debug_restore_node);
- ClassDB::bind_method(_MD("live_debug_duplicate_node"),&ScriptEditorDebugger::live_debug_duplicate_node);
- ClassDB::bind_method(_MD("live_debug_reparent_node"),&ScriptEditorDebugger::live_debug_reparent_node);
- ClassDB::bind_method(_MD("_scene_tree_property_select_object"),&ScriptEditorDebugger::_scene_tree_property_select_object);
- ClassDB::bind_method(_MD("_scene_tree_property_value_edited"),&ScriptEditorDebugger::_scene_tree_property_value_edited);
-
- ADD_SIGNAL(MethodInfo("goto_script_line"));
- ADD_SIGNAL(MethodInfo("breaked",PropertyInfo(Variant::BOOL,"reallydid"),PropertyInfo(Variant::BOOL,"can_debug")));
- ADD_SIGNAL(MethodInfo("show_debugger",PropertyInfo(Variant::BOOL,"reallydid")));
-}
-
-ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
-
-
-
- ppeer = Ref<PacketPeerStream>( memnew( PacketPeerStream ) );
- editor=p_editor;
-
- tabs = memnew( TabContainer );
- tabs->set_v_size_flags(SIZE_EXPAND_FILL);
- tabs->set_area_as_parent_rect();
- add_child(tabs);
-
-
- { //debugger
- VBoxContainer *vbc = memnew( VBoxContainer );
- vbc->set_name(TTR("Debugger"));
- //tabs->add_child(vbc);
- Control *dbg=vbc;
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- vbc->add_child(hbc);
-
-
- 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);
-
- hbc->add_child( memnew( VSeparator) );
-
- step = memnew( Button );
- hbc->add_child(step);
- step->set_tooltip(TTR("Step Into"));
- step->connect("pressed",this,"debug_step");
-
- next = memnew( Button );
- hbc->add_child(next);
- next->set_tooltip(TTR("Step Over"));
- next->connect("pressed",this,"debug_next");
-
- hbc->add_child( memnew( VSeparator) );
-
- dobreak = memnew( Button );
- hbc->add_child(dobreak);
- dobreak->set_tooltip(TTR("Break"));
- dobreak->connect("pressed",this,"debug_break");
-
- docontinue = memnew( Button );
- hbc->add_child(docontinue);
- docontinue->set_tooltip(TTR("Continue"));
- docontinue->connect("pressed",this,"debug_continue");
-
- //hbc->add_child( memnew( VSeparator) );
-
- back = memnew( Button );
- hbc->add_child(back);
- back->set_tooltip(TTR("Inspect Previous Instance"));
- back->hide();
-
- forward = memnew( Button );
- hbc->add_child(forward);
- forward->set_tooltip(TTR("Inspect Next Instance"));
- forward->hide();
-
-
- HSplitContainer *sc = memnew( HSplitContainer );
- vbc->add_child(sc);
- sc->set_v_size_flags(SIZE_EXPAND_FILL);
-
- stack_dump = memnew( Tree );
- stack_dump->set_columns(1);
- stack_dump->set_column_titles_visible(true);
- stack_dump->set_column_title(0,TTR("Stack Frames"));
- stack_dump->set_h_size_flags(SIZE_EXPAND_FILL);
- stack_dump->set_hide_root(true);
- stack_dump->connect("cell_selected",this,"_stack_dump_frame_selected");
- sc->add_child(stack_dump);
-
- inspector = memnew( PropertyEditor );
- inspector->set_h_size_flags(SIZE_EXPAND_FILL);
- inspector->hide_top_label();
- inspector->get_scene_tree()->set_column_title(0,TTR("Variable"));
- inspector->set_capitalize_paths(false);
- inspector->set_read_only(true);
- sc->add_child(inspector);
-
- server = TCP_Server::create_ref();
-
- pending_in_queue=0;
-
- variables = memnew( ScriptEditorDebuggerVariables );
-
- breaked=false;
-
- tabs->add_child(dbg);
- //tabs->move_child(vbc,0);
-
- hbc = memnew( HBoxContainer );
- vbc->add_child(hbc);
-
- }
-
- { //errors
-
-
- error_split = memnew( HSplitContainer );
- VBoxContainer *errvb = memnew( VBoxContainer );
- errvb->set_h_size_flags(SIZE_EXPAND_FILL);
- error_list = memnew( ItemList );
- errvb->add_margin_child(TTR("Errors:"),error_list,true);
- error_split->add_child(errvb);
-
- errvb = memnew( VBoxContainer );
- errvb->set_h_size_flags(SIZE_EXPAND_FILL);
- error_stack = memnew( ItemList );
- errvb->add_margin_child(TTR("Stack Trace (if applicable):"),error_stack,true);
- error_split->add_child(errvb);
-
- error_split->set_name(TTR("Errors"));
- tabs->add_child(error_split);
- }
-
-
- { // inquire
-
-
- inspect_info = memnew( HSplitContainer );
- inspect_info->set_name(TTR("Remote Inspector"));
- tabs->add_child(inspect_info);
-
- VBoxContainer *info_left = memnew(VBoxContainer);
- info_left->set_h_size_flags(SIZE_EXPAND_FILL);
- inspect_info->add_child(info_left);
-
- inspect_scene_tree = memnew( Tree );
- info_left->add_margin_child(TTR("Live Scene Tree:"),inspect_scene_tree,true);
- inspect_scene_tree->connect("cell_selected",this,"_scene_tree_selected");
- inspect_scene_tree->connect("item_collapsed",this,"_scene_tree_folded");
-
- //
-
- VBoxContainer *info_right = memnew(VBoxContainer);
- info_right->set_h_size_flags(SIZE_EXPAND_FILL);
- inspect_info->add_child(info_right);
-
- inspect_properties = memnew( PropertyEditor );
- inspect_properties->hide_top_label();
- inspect_properties->set_show_categories(true);
- inspect_properties->connect("object_id_selected",this,"_scene_tree_property_select_object");
-
- info_right->add_margin_child(TTR("Remote Object Properties: "),inspect_properties,true);
-
- inspect_scene_tree_timeout=EDITOR_DEF("debugger/scene_tree_refresh_interval",1.0);
- inspect_edited_object_timeout=EDITOR_DEF("debugger/remote_inspect_refresh_interval",0.2);
- inspected_object_id=0;
- updating_scene_tree=false;
-
- inspected_object = memnew( ScriptEditorDebuggerInspectedObject );
- inspected_object->connect("value_edited",this,"_scene_tree_property_value_edited");
- }
-
- { //profiler
- profiler = memnew( EditorProfiler );
- profiler->set_name(TTR("Profiler"));
- tabs->add_child(profiler);
- profiler->connect("enable_profiling",this,"_profiler_activate");
- profiler->connect("break_request",this,"_profiler_seeked");
- }
-
-
- { //monitors
-
- HSplitContainer *hsp = memnew( HSplitContainer );
-
- perf_monitors = memnew(Tree);
- perf_monitors->set_columns(2);
- perf_monitors->set_column_title(0,TTR("Monitor"));
- perf_monitors->set_column_title(1,TTR("Value"));
- perf_monitors->set_column_titles_visible(true);
- hsp->add_child(perf_monitors);
- perf_monitors->set_select_mode(Tree::SELECT_MULTI);
- perf_monitors->connect("multi_selected",this,"_performance_select");
- perf_draw = memnew( Control );
- perf_draw->connect("draw",this,"_performance_draw");
- hsp->add_child(perf_draw);
- hsp->set_name(TTR("Monitors"));
- hsp->set_split_offset(300);
- tabs->add_child(hsp);
- perf_max.resize(Performance::MONITOR_MAX);
-
- Map<String,TreeItem*> bases;
- TreeItem *root=perf_monitors->create_item();
- perf_monitors->set_hide_root(true);
- for(int i=0;i<Performance::MONITOR_MAX;i++) {
-
- String n = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i));
- String base = n.get_slice("/",0);
- String name = n.get_slice("/",1);
- if (!bases.has(base)) {
- TreeItem *b = perf_monitors->create_item(root);
- b->set_text(0,base.capitalize());
- b->set_editable(0,false);
- b->set_selectable(0,false);
- bases[base]=b;
- }
-
- TreeItem *it = perf_monitors->create_item(bases[base]);
- it->set_editable(0,false);
- it->set_selectable(0,true);
- it->set_text(0,name.capitalize());
- perf_items.push_back(it);
- perf_max[i]=0;
-
- }
- }
-
- { //vmem inspect
- VBoxContainer *vmem_vb = memnew( VBoxContainer );
- HBoxContainer *vmem_hb = memnew( HBoxContainer );
- Label *vmlb = memnew(Label(TTR("List of Video Memory Usage by Resource:")+" ") );
- vmlb->set_h_size_flags(SIZE_EXPAND_FILL);
- vmem_hb->add_child( vmlb );
- vmem_hb->add_child( memnew(Label(TTR("Total:")+" ")) );
- vmem_total = memnew( LineEdit );
- vmem_total->set_editable(false);
- vmem_total->set_custom_minimum_size(Size2(100,1)*EDSCALE);
- vmem_hb->add_child(vmem_total);
- vmem_refresh = memnew( Button );
- vmem_hb->add_child(vmem_refresh);
- vmem_vb->add_child(vmem_hb);
- vmem_refresh->connect("pressed",this,"_video_mem_request");
-
- MarginContainer *vmmc = memnew( MarginContainer );
- vmem_tree = memnew( Tree );
- vmem_tree->set_v_size_flags(SIZE_EXPAND_FILL);
- vmem_tree->set_h_size_flags(SIZE_EXPAND_FILL);
- vmmc->add_child(vmem_tree);
- vmmc->set_v_size_flags(SIZE_EXPAND_FILL);
- vmem_vb->add_child(vmmc);
-
- vmem_vb->set_name(TTR("Video Mem"));
- vmem_tree->set_columns(4);
- vmem_tree->set_column_titles_visible(true);
- vmem_tree->set_column_title(0,TTR("Resource Path"));
- vmem_tree->set_column_expand(0,true);
- vmem_tree->set_column_expand(1,false);
- vmem_tree->set_column_title(1,TTR("Type"));
- vmem_tree->set_column_min_width(1,100);
- vmem_tree->set_column_expand(2,false);
- vmem_tree->set_column_title(2,TTR("Format"));
- vmem_tree->set_column_min_width(2,150);
- vmem_tree->set_column_expand(3,false);
- vmem_tree->set_column_title(3,TTR("Usage"));
- vmem_tree->set_column_min_width(3,80);
- vmem_tree->set_hide_root(true);
-
- tabs->add_child(vmem_vb);
- }
-
- { // misc
- VBoxContainer *info_left = memnew( VBoxContainer );
- info_left->set_h_size_flags(SIZE_EXPAND_FILL);
- info_left->set_name(TTR("Misc"));
- tabs->add_child(info_left);
- clicked_ctrl = memnew( LineEdit );
- info_left->add_margin_child(TTR("Clicked Control:"),clicked_ctrl);
- clicked_ctrl_type = memnew( LineEdit );
- info_left->add_margin_child(TTR("Clicked Control Type:"),clicked_ctrl_type);
-
- live_edit_root = memnew( LineEdit );
-
- {
- HBoxContainer *lehb = memnew( HBoxContainer );
- Label *l = memnew( Label(TTR("Live Edit Root:")) );
- lehb->add_child(l);
- l->set_h_size_flags(SIZE_EXPAND_FILL);
- le_set = memnew( Button(TTR("Set From Tree")) );
- lehb->add_child(le_set);
- le_clear = memnew( Button(TTR("Clear")) );
- lehb->add_child(le_clear);
- info_left->add_child(lehb);
- MarginContainer *mc = memnew( MarginContainer );
- mc->add_child(live_edit_root);
- info_left->add_child(mc);
- le_set->set_disabled(true);
- le_clear->set_disabled(true);
- }
-
- }
-
-
-
- msgdialog = memnew( AcceptDialog );
- add_child(msgdialog);
-
- p_editor->get_undo_redo()->set_method_notify_callback(_method_changeds,this);
- p_editor->get_undo_redo()->set_property_notify_callback(_property_changeds,this);
- live_debug=false;
- last_path_id=false;
- error_count=0;
- hide_on_stop=true;
- last_error_count=0;
-
- EditorNode::get_singleton()->get_pause_button()->connect("pressed",this,"_paused");
-
-
-}
-
-ScriptEditorDebugger::~ScriptEditorDebugger() {
-
- //inspector->edit(NULL);
- memdelete(variables);
-
- ppeer->set_stream_peer(Ref<StreamPeer>());
-
- server->stop();
- memdelete(inspected_object);
-
-}
diff --git a/tools/editor/settings_config_dialog.cpp b/tools/editor/settings_config_dialog.cpp
deleted file mode 100644
index 31cbcee5ae..0000000000
--- a/tools/editor/settings_config_dialog.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-/*************************************************************************/
-/* settings_config_dialog.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "settings_config_dialog.h"
-
-#include "editor_settings.h"
-#include "scene/gui/margin_container.h"
-#include "globals.h"
-#include "editor_file_system.h"
-#include "editor_node.h"
-#include "os/keyboard.h"
-
-void EditorSettingsDialog::ok_pressed() {
-
- if (!EditorSettings::get_singleton())
- return;
-
- _settings_save();
- timer->stop();
-
-}
-
-void EditorSettingsDialog::_settings_changed() {
-
- timer->start();
-}
-
-void EditorSettingsDialog::_settings_property_edited(const String& p_name) {
-
- String full_name = property_editor->get_full_item_path(p_name);
-
- // Small usability workaround to update the text color settings when the
- // color theme is changed
- if (full_name == "text_editor/theme/color_theme") {
- property_editor->get_property_editor()->update_tree();
- }
-}
-
-void EditorSettingsDialog::_settings_save() {
-
-
- EditorSettings::get_singleton()->notify_changes();
- EditorSettings::get_singleton()->save();
-
-}
-
-void EditorSettingsDialog::cancel_pressed() {
-
- if (!EditorSettings::get_singleton())
- return;
-
- EditorSettings::get_singleton()->notify_changes();
-
-}
-
-
-void EditorSettingsDialog::popup_edit_settings() {
-
- if (!EditorSettings::get_singleton())
- return;
-
- EditorSettings::get_singleton()->list_text_editor_themes(); // make sure we have an up to date list of themes
-
- property_editor->edit(EditorSettings::get_singleton());
- property_editor->get_property_editor()->update_tree();
-
- search_box->select_all();
- search_box->grab_focus();
-
- _update_shortcuts();
- popup_centered_ratio(0.7);
-}
-
-
-
-void EditorSettingsDialog::_clear_search_box() {
-
- if (search_box->get_text()=="")
- return;
-
- search_box->clear();
- property_editor->get_property_editor()->update_tree();
-}
-
-void EditorSettingsDialog::_clear_shortcut_search_box() {
- if (shortcut_search_box->get_text()=="")
- return;
-
- shortcut_search_box->clear();
-}
-
-void EditorSettingsDialog::_filter_shortcuts(const String& p_filter) {
- shortcut_filter = p_filter;
- _update_shortcuts();
-}
-
-void EditorSettingsDialog::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- clear_button->set_icon(get_icon("Close","EditorIcons"));
- shortcut_clear_button->set_icon(get_icon("Close","EditorIcons"));
- }
-}
-
-
-void EditorSettingsDialog::_update_shortcuts() {
-
- shortcuts->clear();
-
- List<String> slist;
- EditorSettings::get_singleton()->get_shortcut_list(&slist);
- TreeItem *root = shortcuts->create_item();
-
- Map<String,TreeItem*> sections;
-
- for(List<String>::Element *E=slist.front();E;E=E->next()) {
-
- Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(E->get());
- if (!sc->has_meta("original"))
- continue;
-
- InputEvent original = sc->get_meta("original");
-
- String section_name = E->get().get_slice("/",0);
-
- TreeItem *section;
-
- if (sections.has(section_name)) {
- section=sections[section_name];
- } else {
- section = shortcuts->create_item(root);
- section->set_text(0,section_name.capitalize());
-
- sections[section_name]=section;
- section->set_custom_bg_color(0,get_color("prop_subsection","Editor"));
- section->set_custom_bg_color(1,get_color("prop_subsection","Editor"));
- }
-
- if (shortcut_filter.is_subsequence_ofi(sc->get_name())) {
- TreeItem *item = shortcuts->create_item(section);
-
- item->set_text(0,sc->get_name());
- item->set_text(1,sc->get_as_text());
- if (!sc->is_shortcut(original) && !(sc->get_shortcut().type==InputEvent::NONE && original.type==InputEvent::NONE)) {
- item->add_button(1,get_icon("Reload","EditorIcons"),2);
- }
- item->add_button(1,get_icon("Edit","EditorIcons"),0);
- item->add_button(1,get_icon("Close","EditorIcons"),1);
- item->set_tooltip(0,E->get());
- item->set_metadata(0,E->get());
- }
- }
-
- // remove sections with no shortcuts
- for(Map<String,TreeItem*>::Element *E=sections.front();E;E=E->next()) {
- TreeItem *section = E->get();
- if (section->get_children() == NULL) {
- root->remove_child(section);
- }
- }
-}
-
-void EditorSettingsDialog::_shortcut_button_pressed(Object* p_item,int p_column,int p_idx) {
-
- TreeItem *ti=p_item->cast_to<TreeItem>();
- ERR_FAIL_COND(!ti);
-
- String item = ti->get_metadata(0);
- Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(item);
-
- if (p_idx==0) {
- press_a_key_label->set_text(TTR("Press a Key.."));
- last_wait_for_key=InputEvent();
- press_a_key->popup_centered(Size2(250,80)*EDSCALE);
- press_a_key->grab_focus();
- press_a_key->get_ok()->set_focus_mode(FOCUS_NONE);
- press_a_key->get_cancel()->set_focus_mode(FOCUS_NONE);
- shortcut_configured=item;
-
- } else if (p_idx==1) {//erase
- if (!sc.is_valid())
- return; //pointless, there is nothing
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Erase Shortcut");
- ur->add_do_method(sc.ptr(),"set_shortcut",InputEvent());
- ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut());
- ur->add_do_method(this,"_update_shortcuts");
- ur->add_undo_method(this,"_update_shortcuts");
- ur->add_do_method(this,"_settings_changed");
- ur->add_undo_method(this,"_settings_changed");
- ur->commit_action();
- } else if (p_idx==2) {//revert to original
- if (!sc.is_valid())
- return; //pointless, there is nothing
-
- InputEvent original = sc->get_meta("original");
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Restore Shortcut");
- ur->add_do_method(sc.ptr(),"set_shortcut",original);
- ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut());
- ur->add_do_method(this,"_update_shortcuts");
- ur->add_undo_method(this,"_update_shortcuts");
- ur->add_do_method(this,"_settings_changed");
- ur->add_undo_method(this,"_settings_changed");
- ur->commit_action();
- }
-}
-
-
-void EditorSettingsDialog::_wait_for_key(const InputEvent& p_event) {
-
-
- if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode!=0) {
-
- last_wait_for_key=p_event;
- String str=keycode_get_string(p_event.key.scancode).capitalize();
- if (p_event.key.mod.meta)
- str=TTR("Meta+")+str;
- if (p_event.key.mod.shift)
- str=TTR("Shift+")+str;
- if (p_event.key.mod.alt)
- str=TTR("Alt+")+str;
- if (p_event.key.mod.control)
- str=TTR("Control+")+str;
-
-
- press_a_key_label->set_text(str);
- press_a_key->accept_event();
-
- }
-}
-
-
-
-
-void EditorSettingsDialog::_press_a_key_confirm() {
-
- if (last_wait_for_key.type!=InputEvent::KEY)
- return;
-
- InputEvent ie;
- ie.type=InputEvent::KEY;
- ie.key.scancode=last_wait_for_key.key.scancode;
- ie.key.mod=last_wait_for_key.key.mod;
-
- Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured);
-
- UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
- ur->create_action("Change Shortcut '"+shortcut_configured+"'");
- ur->add_do_method(sc.ptr(),"set_shortcut",ie);
- ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut());
- ur->add_do_method(this,"_update_shortcuts");
- ur->add_undo_method(this,"_update_shortcuts");
- ur->add_do_method(this,"_settings_changed");
- ur->add_undo_method(this,"_settings_changed");
- ur->commit_action();
-
-
-
-}
-
-void EditorSettingsDialog::_bind_methods() {
-
- ClassDB::bind_method(_MD("_settings_save"),&EditorSettingsDialog::_settings_save);
- ClassDB::bind_method(_MD("_settings_changed"),&EditorSettingsDialog::_settings_changed);
- ClassDB::bind_method(_MD("_settings_property_edited"),&EditorSettingsDialog::_settings_property_edited);
- ClassDB::bind_method(_MD("_clear_search_box"),&EditorSettingsDialog::_clear_search_box);
- ClassDB::bind_method(_MD("_clear_shortcut_search_box"),&EditorSettingsDialog::_clear_shortcut_search_box);
- ClassDB::bind_method(_MD("_shortcut_button_pressed"),&EditorSettingsDialog::_shortcut_button_pressed);
- ClassDB::bind_method(_MD("_filter_shortcuts"),&EditorSettingsDialog::_filter_shortcuts);
- ClassDB::bind_method(_MD("_update_shortcuts"),&EditorSettingsDialog::_update_shortcuts);
- ClassDB::bind_method(_MD("_press_a_key_confirm"),&EditorSettingsDialog::_press_a_key_confirm);
- ClassDB::bind_method(_MD("_wait_for_key"),&EditorSettingsDialog::_wait_for_key);
-
-}
-
-EditorSettingsDialog::EditorSettingsDialog() {
-
- set_title(TTR("Editor Settings"));
-
- tabs = memnew( TabContainer );
- add_child(tabs);
- //set_child_rect(tabs);
-
- VBoxContainer *vbc = memnew( VBoxContainer );
- tabs->add_child(vbc);
- vbc->set_name(TTR("General"));
-
- HBoxContainer *hbc = memnew( HBoxContainer );
- hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- vbc->add_child(hbc);
-
- Label *l = memnew( Label );
- l->set_text(TTR("Search:")+" ");
- hbc->add_child(l);
-
- search_box = memnew( LineEdit );
- search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hbc->add_child(search_box);
-
- clear_button = memnew( ToolButton );
- hbc->add_child(clear_button);
- clear_button->connect("pressed",this,"_clear_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);
- property_editor->get_property_editor()->connect("property_edited", this, "_settings_property_edited");
-
- vbc = memnew( VBoxContainer );
- tabs->add_child(vbc);
- vbc->set_name(TTR("Shortcuts"));
-
- hbc = memnew( HBoxContainer );
- hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- vbc->add_child(hbc);
-
- l = memnew( Label );
- l->set_text(TTR("Search:")+" ");
- hbc->add_child(l);
-
- shortcut_search_box = memnew( LineEdit );
- shortcut_search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- hbc->add_child(shortcut_search_box);
- shortcut_search_box->connect("text_changed", this, "_filter_shortcuts");
-
- shortcut_clear_button = memnew( ToolButton );
- hbc->add_child(shortcut_clear_button);
- shortcut_clear_button->connect("pressed",this,"_clear_shortcut_search_box");
-
- shortcuts = memnew( Tree );
- vbc->add_margin_child("Shortcut List:",shortcuts,true);
- shortcuts->set_columns(2);
- shortcuts->set_hide_root(true);
- //shortcuts->set_hide_folding(true);
- shortcuts->set_column_titles_visible(true);
- shortcuts->set_column_title(0,"Name");
- shortcuts->set_column_title(1,"Binding");
- shortcuts->connect("button_pressed",this,"_shortcut_button_pressed");
-
- press_a_key = memnew( ConfirmationDialog );
- press_a_key->set_focus_mode(FOCUS_ALL);
- add_child(press_a_key);
-
- l = memnew( Label );
- l->set_text(TTR("Press a Key.."));
- l->set_area_as_parent_rect();
- l->set_align(Label::ALIGN_CENTER);
- l->set_margin(MARGIN_TOP,20);
- l->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,30);
- press_a_key_label=l;
- press_a_key->add_child(l);
- press_a_key->connect("gui_input",this,"_wait_for_key");
- press_a_key->connect("confirmed",this,"_press_a_key_confirm");
- //Button *load = memnew( Button );
-
- //load->set_text("Load..");
- //hbc->add_child(load);
-
-
- //get_ok()->set_text("Apply");
- set_hide_on_ok(true);
- //get_cancel()->set_text("Close");
-
- timer = memnew( Timer );
- timer->set_wait_time(1.5);
- timer->connect("timeout",this,"_settings_save");
- timer->set_one_shot(true);
- add_child(timer);
- EditorSettings::get_singleton()->connect("settings_changed",this,"_settings_changed");
- get_ok()->set_text(TTR("Close"));
-
- updating=false;
-
-}
diff --git a/tools/editor/spatial_editor_gizmos.cpp b/tools/editor/spatial_editor_gizmos.cpp
deleted file mode 100644
index 3ed101cdd6..0000000000
--- a/tools/editor/spatial_editor_gizmos.cpp
+++ /dev/null
@@ -1,3483 +0,0 @@
-/*************************************************************************/
-/* spatial_editor_gizmos.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 "spatial_editor_gizmos.h"
-
-#include "geometry.h"
-#include "scene/3d/camera.h"
-#include "scene/resources/surface_tool.h"
-#include "scene/resources/sphere_shape.h"
-#include "scene/resources/box_shape.h"
-#include "scene/resources/capsule_shape.h"
-#include "scene/resources/ray_shape.h"
-#include "scene/resources/convex_polygon_shape.h"
-#include "scene/resources/plane_shape.h"
-#include "quick_hull.h"
-
-// Keep small children away from this file.
-// It's so ugly it will eat them alive
-
-
-
-#define HANDLE_HALF_SIZE 0.05
-
-void EditorSpatialGizmo::clear() {
-
- for(int i=0;i<instances.size();i++) {
-
- if (instances[i].instance.is_valid())
- VS::get_singleton()->free(instances[i].instance);
-
-
- }
-
- billboard_handle=false;
- collision_segments.clear();
- collision_mesh=Ref<TriangleMesh>();
- instances.clear();
- handles.clear();
- secondary_handles.clear();
-}
-
-void EditorSpatialGizmo::redraw() {
-
- if (get_script_instance() && get_script_instance()->has_method("redraw"))
- get_script_instance()->call("redraw");
-
-
-}
-
-void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) {
-
- instance = VS::get_singleton()->instance_create2(mesh->get_rid(),p_base->get_world()->get_scenario());
- VS::get_singleton()->instance_attach_object_instance_ID(instance,p_base->get_instance_ID());
- if (billboard)
- VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_BILLBOARD,true);
- if (unscaled)
- VS::get_singleton()->instance_geometry_set_flag(instance,VS::INSTANCE_FLAG_DEPH_SCALE,true);
- if (skeleton.is_valid())
- VS::get_singleton()->instance_attach_skeleton(instance,skeleton);
- if (extra_margin)
- VS::get_singleton()->instance_set_extra_visibility_margin(instance,1);
- VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance,VS::SHADOW_CASTING_SETTING_OFF);
- VS::get_singleton()->instance_set_layer_mask(instance,1<<SpatialEditorViewport::GIZMO_EDIT_LAYER); //gizmos are 26
-}
-
-
-
-void EditorSpatialGizmo::add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard, const RID &p_skeleton) {
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
- ins.billboard=p_billboard;
- ins.mesh=p_mesh;
- ins.skeleton=p_skeleton;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
-
- instances.push_back(ins);
-
-}
-
-void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material,bool p_billboard){
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
- Ref<Mesh> mesh = memnew( Mesh );
- Array a;
- a.resize(Mesh::ARRAY_MAX);
-
- a[Mesh::ARRAY_VERTEX]=p_lines;
-
- PoolVector<Color> color;
- color.resize(p_lines.size());
- {
- PoolVector<Color>::Write w = color.write();
- for(int i=0;i<p_lines.size();i++) {
- if (is_selected())
- w[i]=Color(1,1,1,0.6);
- else
- w[i]=Color(1,1,1,0.25);
- }
-
- }
-
- a[Mesh::ARRAY_COLOR]=color;
-
-
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,a);
- mesh->surface_set_material(0,p_material);
-
- if (p_billboard) {
- float md=0;
- for(int i=0;i<p_lines.size();i++) {
-
- md=MAX(0,p_lines[i].length());
-
- }
- if (md) {
- mesh->set_custom_aabb(Rect3(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
- }
- }
-
- ins.billboard=p_billboard;
- ins.mesh=mesh;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
-
- instances.push_back(ins);
-
-}
-
-void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material>& p_material,float p_scale) {
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
- Vector<Vector3 > vs;
- Vector<Vector2 > uv;
-
- vs.push_back(Vector3(-p_scale,p_scale,0));
- vs.push_back(Vector3(p_scale,p_scale,0));
- vs.push_back(Vector3(p_scale,-p_scale,0));
- vs.push_back(Vector3(-p_scale,-p_scale,0));
-
- uv.push_back(Vector2(1,0));
- uv.push_back(Vector2(0,0));
- uv.push_back(Vector2(0,1));
- uv.push_back(Vector2(1,1));
-
- Ref<Mesh> mesh = memnew( Mesh );
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- a[Mesh::ARRAY_VERTEX]=vs;
- a[Mesh::ARRAY_TEX_UV]=uv;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLE_FAN,a);
- mesh->surface_set_material(0,p_material);
-
- if (true) {
- float md=0;
- for(int i=0;i<vs.size();i++) {
-
- md=MAX(0,vs[i].length());
-
- }
- if (md) {
- mesh->set_custom_aabb(Rect3(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
- }
- }
-
- ins.mesh=mesh;
- ins.unscaled=true;
- ins.billboard=true;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
-
- instances.push_back(ins);
-
-
-}
-
-void EditorSpatialGizmo::add_collision_triangles(const Ref<TriangleMesh>& p_tmesh) {
-
- collision_mesh=p_tmesh;
-}
-
-void EditorSpatialGizmo::add_collision_segments(const Vector<Vector3> &p_lines) {
-
- int from=collision_segments.size();
- collision_segments.resize(from+p_lines.size());
- for(int i=0;i<p_lines.size();i++) {
-
- collision_segments[from+i]=p_lines[i];
- }
-}
-
-
-void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_billboard,bool p_secondary){
-
- billboard_handle=p_billboard;
-
- if (!is_selected())
- return;
-
- ERR_FAIL_COND(!spatial_node);
-
- ERR_FAIL_COND(!spatial_node);
- Instance ins;
-
-
- Ref<Mesh> mesh = memnew( Mesh );
-#if 1
-
- Array a;
- a.resize(VS::ARRAY_MAX);
- a[VS::ARRAY_VERTEX]=p_handles;
- print_line("handles?: "+itos(p_handles.size()));
- PoolVector<Color> colors;
- {
- colors.resize(p_handles.size());
- PoolVector<Color>::Write w=colors.write();
- for(int i=0;i<p_handles.size();i++) {
-
- Color col(1,1,1,1);
- if (SpatialEditor::get_singleton()->get_over_gizmo_handle()!=i)
- col=Color(0.9,0.9,0.9,0.9);
- w[i]=col;
- }
-
- }
- a[VS::ARRAY_COLOR]=colors;
- mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS,a);
- mesh->surface_set_material(0,SpatialEditorGizmos::singleton->handle2_material);
-
- if (p_billboard) {
- float md=0;
- for(int i=0;i<p_handles.size();i++) {
-
- md=MAX(0,p_handles[i].length());
-
- }
- if (md) {
- mesh->set_custom_aabb(Rect3(Vector3(-md,-md,-md),Vector3(md,md,md)*2.0));
- }
- }
-
-
-
-#else
- for(int ih=0;ih<p_handles.size();ih++) {
-
-
- Vector<Vector3> vertices;
- Vector<Vector3> normals;
-
- int vtx_idx=0;
-
-#define ADD_VTX(m_idx) \
- vertices.push_back( (face_points[m_idx]*HANDLE_HALF_SIZE+p_handles[ih]) );\
- normals.push_back( normal_points[m_idx] );\
- vtx_idx++;\
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
- Vector3 normal_points[4];
- float uv_points[8]={0,0,0,1,1,1,1,0};
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- normal_points[j]=Vector3();
- normal_points[j][i%3]=(i>=3?-1:1);
- }
- //tri 1
- ADD_VTX(0);
- ADD_VTX(1);
- ADD_VTX(2);
- //tri 2
- ADD_VTX(2);
- ADD_VTX(3);
- ADD_VTX(0);
-
- }
-
-
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[VisualServer::ARRAY_NORMAL]= normals ;
- d[VisualServer::ARRAY_VERTEX]= vertices ;
-
- mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d);
- mesh->surface_set_material(ih,SpatialEditorGizmos::singleton->handle_material);
-
-
- }
-#endif
- ins.mesh=mesh;
- ins.billboard=p_billboard;
- ins.extra_margin=true;
- if (valid) {
- ins.create_instance(spatial_node);
- VS::get_singleton()->instance_set_transform(ins.instance,spatial_node->get_global_transform());
- }
- instances.push_back(ins);
- if (!p_secondary) {
- int chs=handles.size();
- handles.resize(chs+p_handles.size());
- for(int i=0;i<p_handles.size();i++) {
- handles[i+chs]=p_handles[i];
- }
- } else {
-
- int chs=secondary_handles.size();
- secondary_handles.resize(chs+p_handles.size());
- for(int i=0;i<p_handles.size();i++) {
- secondary_handles[i+chs]=p_handles[i];
- }
-
- }
-
-}
-
-
-void EditorSpatialGizmo::set_spatial_node(Spatial *p_node){
-
- ERR_FAIL_NULL(p_node);
- spatial_node=p_node;
-
-}
-
-bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum) {
-
- ERR_FAIL_COND_V(!spatial_node,false);
- ERR_FAIL_COND_V(!valid,false);
-
- if (collision_segments.size()) {
-
- const Plane *p=p_frustum.ptr();
- int fc=p_frustum.size();
-
- int vc=collision_segments.size();
- const Vector3* vptr=collision_segments.ptr();
- Transform t = spatial_node->get_global_transform();
-
- for(int i=0;i<vc/2;i++) {
-
-
- Vector3 a=t.xform(vptr[i*2+0]);
- Vector3 b=t.xform(vptr[i*2+1]);
-
- bool any_out=false;
- for(int j=0;j<fc;j++) {
-
- if (p[j].distance_to(a) > 0 && p[j].distance_to(b) >0) {
-
- any_out=true;
- break;
- }
- }
-
- if (!any_out)
- return true;
- }
-
- return false;
- }
-
- return false;
-}
-
-
-bool EditorSpatialGizmo::intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle,bool p_sec_first) {
-
- ERR_FAIL_COND_V(!spatial_node,false);
- ERR_FAIL_COND_V(!valid,false);
-
- if (r_gizmo_handle) {
-
- Transform t = spatial_node->get_global_transform();
- t.orthonormalize();
- if (billboard_handle) {
- t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
- }
-
- float min_d=1e20;
- int idx=-1;
-
- for(int i=0;i<secondary_handles.size();i++) {
-
- Vector3 hpos = t.xform(secondary_handles[i]);
- Vector2 p = p_camera->unproject_position(hpos);
- if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) {
-
-
- real_t dp = p_camera->get_transform().origin.distance_to(hpos);
- if (dp<min_d) {
-
- r_pos=t.xform(hpos);
- r_normal=p_camera->get_transform().basis.get_axis(2);
- min_d=dp;
- idx=i+handles.size();
-
- }
- }
- }
-
- if (p_sec_first && idx!=-1) {
-
- *r_gizmo_handle=idx;
- return true;
- }
-
- min_d=1e20;
-
- for(int i=0;i<handles.size();i++) {
-
- Vector3 hpos = t.xform(handles[i]);
- Vector2 p = p_camera->unproject_position(hpos);
- if (p.distance_to(p_point)<SpatialEditorGizmos::singleton->handle_t->get_width()*0.6) {
-
-
- real_t dp = p_camera->get_transform().origin.distance_to(hpos);
- if (dp<min_d) {
-
- r_pos=t.xform(hpos);
- r_normal=p_camera->get_transform().basis.get_axis(2);
- min_d=dp;
- idx=i;
-
- }
- }
- }
-
- if (idx>=0) {
- *r_gizmo_handle=idx;
- return true;
- }
-
-
- }
-
- if (collision_segments.size()) {
-
- Plane camp(p_camera->get_transform().origin,(-p_camera->get_transform().basis.get_axis(2)).normalized());
-
- int vc=collision_segments.size();
- const Vector3* vptr=collision_segments.ptr();
- Transform t = spatial_node->get_global_transform();
- if (billboard_handle) {
- t.set_look_at(t.origin,t.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
- }
-
- Vector3 cp;
- float cpd=1e20;
-
- for(int i=0;i<vc/2;i++) {
-
-
- Vector3 a=t.xform(vptr[i*2+0]);
- Vector3 b=t.xform(vptr[i*2+1]);
- Vector2 s[2];
- s[0] = p_camera->unproject_position(a);
- s[1] = p_camera->unproject_position(b);
-
-
- Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point,s);
-
- float pd = p.distance_to(p_point);
-
- if (pd<cpd) {
-
-
- float d = s[0].distance_to(s[1]);
- Vector3 tcp;
- if (d>0) {
-
- float d2=s[0].distance_to(p)/d;
- tcp = a+(b-a)*d2;
-
- } else {
- tcp=a;
-
- }
-
- if (camp.distance_to(tcp)<p_camera->get_znear())
- continue;
- cp=tcp;
- cpd=pd;
- }
- }
-
- if (cpd<8) {
-
- r_pos=cp;
- r_normal=-p_camera->project_ray_normal(p_point);
- return true;
- }
-
- return false;
- }
-
-
- if (collision_mesh.is_valid()) {
- Transform gt = spatial_node->get_global_transform();
-
- if (billboard_handle) {
- gt.set_look_at(gt.origin,gt.origin+p_camera->get_transform().basis.get_axis(2),p_camera->get_transform().basis.get_axis(1));
- }
-
- Transform ai=gt.affine_inverse();
- Vector3 ray_from = ai.xform(p_camera->project_ray_origin(p_point));
- Vector3 ray_dir=ai.basis.xform(p_camera->project_ray_normal(p_point)).normalized();
- Vector3 rpos,rnorm;
-
-
- if (collision_mesh->intersect_ray(ray_from,ray_dir,rpos,rnorm)) {
-
- r_pos=gt.xform(rpos);
- r_normal=gt.basis.xform(rnorm).normalized();
- return true;
- }
- }
-
- return false;
-
-}
-
-
-
-void EditorSpatialGizmo::create() {
-
- ERR_FAIL_COND(!spatial_node);
- ERR_FAIL_COND(valid);
- valid=true;
-
- for(int i=0;i<instances.size();i++) {
-
- instances[i].create_instance(spatial_node);
- }
-
- transform();
-
-}
-
-void EditorSpatialGizmo::transform(){
-
- ERR_FAIL_COND(!spatial_node);
- ERR_FAIL_COND(!valid);
- for(int i=0;i<instances.size();i++) {
- VS::get_singleton()->instance_set_transform(instances[i].instance,spatial_node->get_global_transform());
- }
-
-}
-
-
-void EditorSpatialGizmo::free(){
-
- ERR_FAIL_COND(!spatial_node);
- ERR_FAIL_COND(!valid);
-
- for(int i=0;i<instances.size();i++) {
-
- if (instances[i].instance.is_valid())
- VS::get_singleton()->free(instances[i].instance);
- instances[i].instance=RID();
- }
-
- valid=false;
-
-
-}
-
-
-void EditorSpatialGizmo::_bind_methods() {
-
- ClassDB::bind_method(_MD("add_lines","lines","material:Material","billboard"),&EditorSpatialGizmo::add_lines,DEFVAL(false));
- ClassDB::bind_method(_MD("add_mesh","mesh:Mesh","billboard","skeleton"),&EditorSpatialGizmo::add_mesh,DEFVAL(false),DEFVAL(RID()));
- ClassDB::bind_method(_MD("add_collision_segments","segments"),&EditorSpatialGizmo::add_collision_segments);
- ClassDB::bind_method(_MD("add_collision_triangles","triangles:TriangleMesh"),&EditorSpatialGizmo::add_collision_triangles);
- ClassDB::bind_method(_MD("add_unscaled_billboard","material:Material","default_scale"),&EditorSpatialGizmo::add_unscaled_billboard,DEFVAL(1));
- ClassDB::bind_method(_MD("add_handles","handles","billboard","secondary"),&EditorSpatialGizmo::add_handles,DEFVAL(false),DEFVAL(false));
- ClassDB::bind_method(_MD("set_spatial_node","node:Spatial"),&EditorSpatialGizmo::_set_spatial_node);
- ClassDB::bind_method(_MD("clear"),&EditorSpatialGizmo::clear);
-
- BIND_VMETHOD( MethodInfo("redraw"));
- BIND_VMETHOD( MethodInfo(Variant::STRING,"get_handle_name",PropertyInfo(Variant::INT,"index")));
- BIND_VMETHOD( MethodInfo("get_handle_value:Variant",PropertyInfo(Variant::INT,"index")));
- BIND_VMETHOD( MethodInfo("set_handle",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::OBJECT,"camera:Camera"),PropertyInfo(Variant::VECTOR2,"point")));
- MethodInfo cm = MethodInfo("commit_handle",PropertyInfo(Variant::INT,"index"),PropertyInfo(Variant::NIL,"restore:Variant"),PropertyInfo(Variant::BOOL,"cancel"));
- cm.default_arguments.push_back(false);
- BIND_VMETHOD( cm );
-}
-
-EditorSpatialGizmo::EditorSpatialGizmo() {
- valid=false;
- billboard_handle=false;
- base=NULL;
- spatial_node=NULL;
-}
-
-EditorSpatialGizmo::~EditorSpatialGizmo(){
-
- clear();
-}
-
-Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const {
-
- ERR_FAIL_INDEX_V(p_idx,handles.size(),Vector3());
-
- return handles[p_idx];
-
-}
-
-//// light gizmo
-
-
-String LightSpatialGizmo::get_handle_name(int p_idx) const {
-
- if (p_idx==0)
- return "Radius";
- else
- return "Aperture";
-}
-
-
-Variant LightSpatialGizmo::get_handle_value(int p_idx) const{
-
- if (p_idx==0)
- return light->get_param(Light::PARAM_RANGE);
- if (p_idx==1)
- return light->get_param(Light::PARAM_SPOT_ANGLE);
-
- return Variant();
-}
-
-
-static float _find_closest_angle_to_half_pi_arc(const Vector3& p_from, const Vector3& p_to, float p_arc_radius,const Transform& p_arc_xform) {
-
- //bleh, discrete is simpler
- static const int arc_test_points=64;
- float min_d = 1e20;
- Vector3 min_p;
-
-
- for(int i=0;i<arc_test_points;i++) {
-
- float a = i*Math_PI*0.5/arc_test_points;
- float an = (i+1)*Math_PI*0.5/arc_test_points;
- Vector3 p=Vector3( Math::cos(a), 0, -Math::sin(a) )*p_arc_radius;
- Vector3 n=Vector3( Math::cos(an), 0,- Math::sin(an) )*p_arc_radius;
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(p,n,p_from,p_to,ra,rb);
-
- float d = ra.distance_to(rb);
- if (d<min_d) {
- min_d=d;
- min_p=ra;
- }
-
- }
-
- //min_p = p_arc_xform.affine_inverse().xform(min_p);
- float a = Vector2(min_p.x,-min_p.z).angle();
- return a*180.0/Math_PI;
-}
-
-
-void LightSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point) {
-
- Transform gt = light->get_global_transform();
- gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
- if (p_idx==0) {
-
- if (light->cast_to<SpotLight>()) {
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,-4096),s[0],s[1],ra,rb);
-
- float d = -ra.z;
- if (d<0)
- d=0;
-
- light->set_param(Light::PARAM_RANGE,d);
- } else if (light->cast_to<OmniLight>()) {
-
- Plane cp=Plane( gt.origin, p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
- if (cp.intersects_ray(ray_from,ray_dir,&inters)) {
-
- float r = inters.distance_to(gt.origin);
- light->set_param(Light::PARAM_RANGE,r);
- }
-
- }
-
- } else if (p_idx==1) {
-
- float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],light->get_param(Light::PARAM_RANGE),gt);
- light->set_param(Light::PARAM_SPOT_ANGLE,CLAMP(a,0.01,89.99));
- }
-}
-
-void LightSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- if (p_cancel) {
-
- light->set_param(p_idx==0?Light::PARAM_RANGE:Light::PARAM_SPOT_ANGLE,p_restore);
-
- } else if (p_idx==0) {
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Light Radius"));
- ur->add_do_method(light,"set_param",Light::PARAM_RANGE,light->get_param(Light::PARAM_RANGE));
- ur->add_undo_method(light,"set_param",Light::PARAM_RANGE,p_restore);
- ur->commit_action();
- } else if (p_idx==1) {
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Light Radius"));
- ur->add_do_method(light,"set_param",Light::PARAM_SPOT_ANGLE,light->get_param(Light::PARAM_SPOT_ANGLE));
- ur->add_undo_method(light,"set_param",Light::PARAM_SPOT_ANGLE,p_restore);
- ur->commit_action();
-
- }
-}
-
-
-
-void LightSpatialGizmo::redraw() {
-
-
- if (light->cast_to<DirectionalLight>()) {
-
-
-
- const int arrow_points=5;
- Vector3 arrow[arrow_points]={
- Vector3(0,0,2),
- Vector3(1,1,2),
- Vector3(1,1,-1),
- Vector3(2,2,-1),
- Vector3(0,0,-3)
- };
-
- int arrow_sides=4;
-
- Vector<Vector3> lines;
-
-
- for(int i = 0; i < arrow_sides ; i++) {
-
-
- Basis ma(Vector3(0,0,1),Math_PI*2*float(i)/arrow_sides);
- Basis mb(Vector3(0,0,1),Math_PI*2*float(i+1)/arrow_sides);
-
-
- for(int j=1;j<arrow_points-1;j++) {
-
- if (j!=2) {
- lines.push_back(ma.xform(arrow[j]));
- lines.push_back(ma.xform(arrow[j+1]));
- }
- if (j<arrow_points-1) {
- lines.push_back(ma.xform(arrow[j]));
- lines.push_back(mb.xform(arrow[j]));
- }
-
- }
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->light_material);
- add_collision_segments(lines);
- add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_directional_icon,0.05);
-
- }
-
- if (light->cast_to<OmniLight>()) {
-
- clear();
-
-
- OmniLight *on = light->cast_to<OmniLight>();
-
- float r = on->get_param(Light::PARAM_RANGE);
-
- Vector<Vector3> points;
-
- for(int i=0;i<=360;i++) {
-
- float ra=Math::deg2rad((float)i);
- float rb=Math::deg2rad((float)i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
- points.push_back(Vector3(a.x,a.y,0));
- points.push_back(Vector3(b.x,b.y,0));
-
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->light_material,true);
- add_collision_segments(points);
-
- add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05);
-
- Vector<Vector3> handles;
- handles.push_back(Vector3(r,0,0));
- add_handles(handles,true);
-
-
- }
-
-
- if (light->cast_to<SpotLight>()) {
-
- clear();
-
- Vector<Vector3> points;
- SpotLight *on = light->cast_to<SpotLight>();
-
- float r = on->get_param(Light::PARAM_RANGE);
- float w = r*Math::sin(Math::deg2rad(on->get_param(Light::PARAM_SPOT_ANGLE)));
- float d = r*Math::cos(Math::deg2rad(on->get_param(Light::PARAM_SPOT_ANGLE)));
-
-
-
- for(int i=0;i<360;i++) {
-
- float ra=Math::deg2rad((float)i);
- float rb=Math::deg2rad((float)i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
- points.push_back(Vector3(a.x,a.y,-d));
- points.push_back(Vector3(b.x,b.y,-d));
-
- if (i%90==0) {
-
- points.push_back(Vector3(a.x,a.y,-d));
- points.push_back(Vector3());
-
- }
-
-
- }
-
- points.push_back(Vector3(0,0,-r));
- points.push_back(Vector3());
-
- add_lines(points,SpatialEditorGizmos::singleton->light_material);
-
- Vector<Vector3> handles;
- handles.push_back(Vector3(0,0,-r));
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
-
- collision_segments.push_back(Vector3(a.x,a.y,-d));
- collision_segments.push_back(Vector3(b.x,b.y,-d));
-
- if (i%16==0) {
-
- collision_segments.push_back(Vector3(a.x,a.y,-d));
- collision_segments.push_back(Vector3());
-
- }
-
- if (i==16) {
-
- handles.push_back(Vector3(a.x,a.y,-d));
- }
-
- }
-
- collision_segments.push_back(Vector3(0,0,-r));
- collision_segments.push_back(Vector3());
-
-
- add_handles(handles);
- add_collision_segments(collision_segments);
- add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon,0.05);
-
- }
-
-}
-
-LightSpatialGizmo::LightSpatialGizmo(Light* p_light){
-
- light=p_light;
- set_spatial_node(p_light);
-
-}
-
-//////
-
-String CameraSpatialGizmo::get_handle_name(int p_idx) const {
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
- return "FOV";
- } else {
- return "Size";
- }
-}
-Variant CameraSpatialGizmo::get_handle_value(int p_idx) const{
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
- return camera->get_fov();
- } else {
-
- return camera->get_size();
- }
-}
-void CameraSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Transform gt = camera->get_global_transform();
- gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 s[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
- Transform gt=camera->get_global_transform();
- float a = _find_closest_angle_to_half_pi_arc(s[0],s[1],1.0,gt);
- camera->set("fov",a);
- } else {
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(0,0,-1),Vector3(4096,0,-1),s[0],s[1],ra,rb);
- float d = ra.x * 2.0;
- if (d<0)
- d=0;
-
- camera->set("size",d);
- }
-
-}
-void CameraSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- if (camera->get_projection()==Camera::PROJECTION_PERSPECTIVE) {
-
- if (p_cancel) {
-
- camera->set("fov",p_restore);
- } else {
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Camera FOV"));
- ur->add_do_property(camera,"fov",camera->get_fov());
- ur->add_undo_property(camera,"fov",p_restore);
- ur->commit_action();
- }
-
- } else {
-
- if (p_cancel) {
-
- camera->set("size",p_restore);
- } else {
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Camera Size"));
- ur->add_do_property(camera,"size",camera->get_size());
- ur->add_undo_property(camera,"size",p_restore);
- ur->commit_action();
- }
-
- }
-
-}
-
-void CameraSpatialGizmo::redraw(){
-
- clear();
-
- Vector<Vector3> lines;
- Vector<Vector3> handles;
-
-
- switch(camera->get_projection()) {
-
- case Camera::PROJECTION_PERSPECTIVE: {
-
- float fov = camera->get_fov();
-
- Vector3 side=Vector3( Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov)) );
- Vector3 nside=side;
- nside.x=-nside.x;
- Vector3 up=Vector3(0,side.x,0);
-
-
-#define ADD_TRIANGLE( m_a, m_b, m_c)\
-{\
- lines.push_back(m_a);\
- lines.push_back(m_b);\
- lines.push_back(m_b);\
- lines.push_back(m_c);\
- lines.push_back(m_c);\
- lines.push_back(m_a);\
-}
-
- ADD_TRIANGLE( Vector3(), side+up, side-up );
- ADD_TRIANGLE( Vector3(), nside+up, nside-up );
- ADD_TRIANGLE( Vector3(), side+up, nside+up );
- ADD_TRIANGLE( Vector3(), side-up, nside-up );
-
- handles.push_back(side);
- side.x*=0.25;
- nside.x*=0.25;
- Vector3 tup( 0, up.y*3/2,side.z);
- ADD_TRIANGLE( tup, side+up, nside+up );
-
- } break;
- case Camera::PROJECTION_ORTHOGONAL: {
-
-#define ADD_QUAD( m_a, m_b, m_c, m_d)\
-{\
- lines.push_back(m_a);\
- lines.push_back(m_b);\
- lines.push_back(m_b);\
- lines.push_back(m_c);\
- lines.push_back(m_c);\
- lines.push_back(m_d);\
- lines.push_back(m_d);\
- lines.push_back(m_a);\
-}
- float size = camera->get_size();
-
- float hsize=size*0.5;
- Vector3 right(hsize,0,0);
- Vector3 up(0,hsize,0);
- Vector3 back(0,0,-1.0);
- Vector3 front(0,0,0);
-
- ADD_QUAD( -up-right,-up+right,up+right,up-right);
- ADD_QUAD( -up-right+back,-up+right+back,up+right+back,up-right+back);
- ADD_QUAD( up+right,up+right+back,up-right+back,up-right);
- ADD_QUAD( -up+right,-up+right+back,-up-right+back,-up-right);
- handles.push_back(right+back);
-
- right.x*=0.25;
- Vector3 tup( 0, up.y*3/2,back.z );
- ADD_TRIANGLE( tup, right+up+back, -right+up+back );
-
- } break;
-
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->camera_material);
- add_collision_segments(lines);
- add_handles(handles);
-}
-
-
-CameraSpatialGizmo::CameraSpatialGizmo(Camera* p_camera){
-
- camera=p_camera;
- set_spatial_node(camera);
-}
-
-
-
-
-//////
-
-void MeshInstanceSpatialGizmo::redraw() {
-
- Ref<Mesh> m = mesh->get_mesh();
- if (!m.is_valid())
- return; //none
-
- Ref<TriangleMesh> tm = m->generate_triangle_mesh();
- if (tm.is_valid())
- add_collision_triangles(tm);
-}
-
-MeshInstanceSpatialGizmo::MeshInstanceSpatialGizmo(MeshInstance* p_mesh) {
-
- mesh=p_mesh;
- set_spatial_node(p_mesh);
-}
-
-/////
-
-
-void Position3DSpatialGizmo::redraw() {
-
- clear();
- add_mesh(SpatialEditorGizmos::singleton->pos3d_mesh);
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs));
- cursor_points.push_back(Vector3(0,0,-cs));
- add_collision_segments(cursor_points);
-
-}
-
-
-Position3DSpatialGizmo::Position3DSpatialGizmo(Position3D* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-
-/////
-
-void SkeletonSpatialGizmo::redraw() {
-
- clear();
-
- Ref<SurfaceTool> surface_tool( memnew( SurfaceTool ));
-
-
- surface_tool->begin(Mesh::PRIMITIVE_LINES);
- surface_tool->set_material(SpatialEditorGizmos::singleton->skeleton_material);
- Vector<Transform> grests;
- grests.resize(skel->get_bone_count());
-
- Vector<int> bones;
- Vector<float> weights;
- bones.resize(4);
- weights.resize(4);
-
- for(int i=0;i<4;i++) {
- bones[i]=0;
- weights[i]=0;
- }
-
- weights[0]=1;
-
-
- Rect3 aabb;
-
- Color bonecolor = Color(1.0,0.4,0.4,0.3);
- Color rootcolor = Color(0.4,1.0,0.4,0.1);
-
- for (int i=0;i<skel->get_bone_count();i++) {
-
- int parent = skel->get_bone_parent(i);
-
- if (parent>=0) {
- grests[i]=grests[parent] * skel->get_bone_rest(i);
-
- Vector3 v0 = grests[parent].origin;
- Vector3 v1 = grests[i].origin;
- Vector3 d = (v1-v0).normalized();
- float dist = v0.distance_to(v1);
-
- //find closest axis
- int closest=-1;
- float closest_d = 0.0;
-
- for(int j=0;j<3;j++) {
- float dp = Math::abs(grests[parent].basis[j].normalized().dot(d));
- if (j==0 || dp>closest_d)
- closest=j;
- }
-
- //find closest other
- Vector3 first;
- Vector3 points[4];
- int pointidx=0;
- for(int j=0;j<3;j++) {
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(rootcolor);
- surface_tool->add_vertex(v0-grests[parent].basis[j].normalized()*dist*0.05);
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(rootcolor);
- surface_tool->add_vertex(v0+grests[parent].basis[j].normalized()*dist*0.05);
-
- if (j==closest)
- continue;
-
- Vector3 axis;
- if (first==Vector3()) {
- axis = d.cross(d.cross(grests[parent].basis[j])).normalized();
- first=axis;
- } else {
- axis = d.cross(first).normalized();
- }
-
- for(int k=0;k<2;k++) {
-
- if (k==1)
- axis=-axis;
- Vector3 point = v0+d*dist*0.2;
- point+=axis*dist*0.1;
-
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(v0);
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(point);
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(point);
- bones[0]=i;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(v1);
- points[pointidx++]=point;
-
- }
-
- }
-
- SWAP( points[1],points[2] );
- for(int j=0;j<4;j++) {
-
-
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(points[j]);
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(bonecolor);
- surface_tool->add_vertex(points[(j+1)%4]);
- }
-
-
-/*
- bones[0]=parent;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(0.4,1,0.4,0.4));
- surface_tool->add_vertex(v0);
- bones[0]=i;
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(0.4,1,0.4,0.4));
- surface_tool->add_vertex(v1);
-*/
- } else {
-
- grests[i]=skel->get_bone_rest(i);
- bones[0]=i;
- }
-/*
- Transform t = grests[i];
- t.orthonormalize();
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- }
-
- for(int j=0;j<4;j++) {
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
- surface_tool->add_vertex(t.xform(face_points[j]*0.04));
- surface_tool->add_bones(bones);
- surface_tool->add_weights(weights);
- surface_tool->add_color(Color(1.0,0.4,0.4,0.4));
- surface_tool->add_vertex(t.xform(face_points[(j+1)%4]*0.04));
- }
-
- }
- */
- }
-
- Ref<Mesh> m = surface_tool->commit();
- add_mesh(m,false,skel->get_skeleton());
-
-}
-
-SkeletonSpatialGizmo::SkeletonSpatialGizmo(Skeleton* p_skel) {
-
- skel=p_skel;
- set_spatial_node(p_skel);
-}
-
-
-
-void RoomSpatialGizmo::redraw() {
-
- clear();
- Ref<RoomBounds> roomie = room->get_room();
- if (roomie.is_null())
- return;
- PoolVector<Face3> faces = roomie->get_geometry_hint();
-
- Vector<Vector3> lines;
- int fc=faces.size();
- PoolVector<Face3>::Read r =faces.read();
-
- Map<_EdgeKey,Vector3> edge_map;
-
- for(int i=0;i<fc;i++) {
-
- Vector3 fn = r[i].get_plane().normal;
-
- for(int j=0;j<3;j++) {
-
- _EdgeKey ek;
- ek.from=r[i].vertex[j].snapped(CMP_EPSILON);
- ek.to=r[i].vertex[(j+1)%3].snapped(CMP_EPSILON);
- if (ek.from<ek.to)
- SWAP(ek.from,ek.to);
-
- Map<_EdgeKey,Vector3>::Element *E=edge_map.find(ek);
-
- if (E) {
-
- if (E->get().dot(fn) >0.9) {
-
- E->get()=Vector3();
- }
-
- } else {
-
- edge_map[ek]=fn;
- }
-
- }
- }
-
- for(Map<_EdgeKey,Vector3>::Element *E=edge_map.front();E;E=E->next()) {
-
- if (E->get()!=Vector3()) {
- lines.push_back(E->key().from);
- lines.push_back(E->key().to);
- }
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->room_material);
- add_collision_segments(lines);
-
-}
-
-RoomSpatialGizmo::RoomSpatialGizmo(Room* p_room){
-
- set_spatial_node(p_room);
- room=p_room;
-}
-
-/////
-
-
-void PortalSpatialGizmo::redraw() {
-
- clear();
-
- Vector<Point2> points = portal->get_shape();
- if (points.size()==0) {
- return;
- }
-
- Vector<Vector3> lines;
-
- Vector3 center;
- for(int i=0;i<points.size();i++) {
-
- Vector3 f;
- f.x=points[i].x;
- f.y=points[i].y;
- Vector3 fn;
- fn.x=points[(i+1)%points.size()].x;
- fn.y=points[(i+1)%points.size()].y;
- center+=f;
-
- lines.push_back(f);
- lines.push_back(fn);
- }
-
- center/=points.size();
- lines.push_back(center);
- lines.push_back(center+Vector3(0,0,1));
-
- add_lines(lines,SpatialEditorGizmos::singleton->portal_material);
- add_collision_segments(lines);
-
-}
-
-PortalSpatialGizmo::PortalSpatialGizmo(Portal* p_portal){
-
- set_spatial_node(p_portal);
- portal=p_portal;
-}
-
-/////
-
-
-void RayCastSpatialGizmo::redraw() {
-
- clear();
-
-
- Vector<Vector3> lines;
-
- lines.push_back(Vector3());
- lines.push_back(raycast->get_cast_to());
-
- add_lines(lines,SpatialEditorGizmos::singleton->raycast_material);
- add_collision_segments(lines);
-
-}
-
-RayCastSpatialGizmo::RayCastSpatialGizmo(RayCast* p_raycast) {
-
- set_spatial_node(p_raycast);
- raycast=p_raycast;
-}
-
-
-
-/////
-
-
-void VehicleWheelSpatialGizmo::redraw() {
-
- clear();
-
-
- Vector<Vector3> points;
-
- float r = car_wheel->get_radius();
- const int skip=10;
- for(int i=0;i<=360;i+=skip) {
-
- float ra=Math::deg2rad((float)i);
- float rb=Math::deg2rad((float)i+skip);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));
-
- const int springsec=4;
-
- for(int j=0;j<springsec;j++) {
- float t = car_wheel->get_suspension_rest_length()*5;
- points.push_back(Vector3(a.x,i/360.0*t/springsec+j*(t/springsec),a.y)*0.2);
- points.push_back(Vector3(b.x,(i+skip)/360.0*t/springsec+j*(t/springsec),b.y)*0.2);
- }
-
-
- }
-
- //travel
- points.push_back(Vector3(0,0,0));
- points.push_back(Vector3(0,car_wheel->get_suspension_rest_length(),0));
-
- //axis
- points.push_back(Vector3(r*0.2,car_wheel->get_suspension_rest_length(),0));
- points.push_back(Vector3(-r*0.2,car_wheel->get_suspension_rest_length(),0));
- //axis
- points.push_back(Vector3(r*0.2,0,0));
- points.push_back(Vector3(-r*0.2,0,0));
-
- //forward line
- points.push_back(Vector3(0,-r,0));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(r*2*0.2,-r,r*2*0.8));
- points.push_back(Vector3(0,-r,r*2));
- points.push_back(Vector3(-r*2*0.2,-r,r*2*0.8));
-
- add_lines(points,SpatialEditorGizmos::singleton->car_wheel_material);
- add_collision_segments(points);
-
-}
-
-VehicleWheelSpatialGizmo::VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel){
-
- set_spatial_node(p_car_wheel);
- car_wheel=p_car_wheel;
-}
-
-
-
-///
-
-void TestCubeSpatialGizmo::redraw() {
-
- clear();
- add_collision_triangles(SpatialEditorGizmos::singleton->test_cube_tm);
-}
-
-TestCubeSpatialGizmo::TestCubeSpatialGizmo(TestCube* p_tc) {
-
- tc=p_tc;
- set_spatial_node(p_tc);
-}
-
-
-///////////
-
-
-
-
-
-
-String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const {
-
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return "";
-
- if (s->cast_to<SphereShape>()) {
-
- return "Radius";
- }
-
- if (s->cast_to<BoxShape>()) {
-
- return "Extents";
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- return p_idx==0?"Radius":"Height";
- }
-
- if (s->cast_to<RayShape>()) {
-
- return "Length";
- }
-
- return "";
-}
-Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const{
-
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return Variant();
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> ss = s;
- return ss->get_radius();
- }
-
- if (s->cast_to<BoxShape>()) {
-
- Ref<BoxShape> bs = s;
- return bs->get_extents();
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Ref<CapsuleShape> cs = s;
- return p_idx==0?cs->get_radius():cs->get_height();
- }
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> cs = s;
- return cs->get_length();
- }
-
- return Variant();
-}
-void CollisionShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return;
-
- Transform gt = cs->get_global_transform();
- gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> ss = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(4096,0,0),sg[0],sg[1],ra,rb);
- float d = ra.x;
- if (d<0.001)
- d=0.001;
-
- ss->set_radius(d);
- }
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> rs = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),Vector3(0,0,4096),sg[0],sg[1],ra,rb);
- float d = ra.z;
- if (d<0.001)
- d=0.001;
-
- rs->set_length(d);
- }
-
-
- if (s->cast_to<BoxShape>()) {
-
- Vector3 axis;
- axis[p_idx]=1.0;
- Ref<BoxShape> bs = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (d<0.001)
- d=0.001;
-
- Vector3 he = bs->get_extents();
- he[p_idx]=d;
- bs->set_extents(he);
-
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Vector3 axis;
- axis[p_idx==0?0:2]=1.0;
- Ref<CapsuleShape> cs = s;
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
- float d = axis.dot(ra);
- if (p_idx==1)
- d-=cs->get_radius();
- if (d<0.001)
- d=0.001;
-
- if (p_idx==0)
- cs->set_radius(d);
- else if (p_idx==1)
- cs->set_height(d*2.0);
-
- }
-
-}
-void CollisionShapeSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return;
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> ss=s;
- if (p_cancel) {
- ss->set_radius(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Sphere Shape Radius"));
- ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius());
- ur->add_undo_method(ss.ptr(),"set_radius",p_restore);
- ur->commit_action();
-
- }
-
- if (s->cast_to<BoxShape>()) {
-
- Ref<BoxShape> ss=s;
- if (p_cancel) {
- ss->set_extents(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Box Shape Extents"));
- ur->add_do_method(ss.ptr(),"set_extents",ss->get_extents());
- ur->add_undo_method(ss.ptr(),"set_extents",p_restore);
- ur->commit_action();
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Ref<CapsuleShape> ss=s;
- if (p_cancel) {
- if (p_idx==0)
- ss->set_radius(p_restore);
- else
- ss->set_height(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- if (p_idx==0) {
- ur->create_action(TTR("Change Capsule Shape Radius"));
- ur->add_do_method(ss.ptr(),"set_radius",ss->get_radius());
- ur->add_undo_method(ss.ptr(),"set_radius",p_restore);
- } else {
- ur->create_action(TTR("Change Capsule Shape Height"));
- ur->add_do_method(ss.ptr(),"set_height",ss->get_height());
- ur->add_undo_method(ss.ptr(),"set_height",p_restore);
-
- }
-
- ur->commit_action();
-
- }
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> ss=s;
- if (p_cancel) {
- ss->set_length(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Ray Shape Length"));
- ur->add_do_method(ss.ptr(),"set_length",ss->get_length());
- ur->add_undo_method(ss.ptr(),"set_length",p_restore);
- ur->commit_action();
-
- }
-
-}
-void CollisionShapeSpatialGizmo::redraw(){
-
- clear();
-
- Ref<Shape> s = cs->get_shape();
- if (s.is_null())
- return;
-
- if (s->cast_to<SphereShape>()) {
-
- Ref<SphereShape> sp= s;
- float r=sp->get_radius();
-
- Vector<Vector3> points;
-
- for(int i=0;i<=360;i++) {
-
- float ra=Math::deg2rad((float)i);
- float rb=Math::deg2rad((float)i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));
- points.push_back(Vector3(a.x,a.y,0));
- points.push_back(Vector3(b.x,b.y,0));
-
- }
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r;
-
- collision_segments.push_back(Vector3(a.x,0,a.y));
- collision_segments.push_back(Vector3(b.x,0,b.y));
- collision_segments.push_back(Vector3(0,a.x,a.y));
- collision_segments.push_back(Vector3(0,b.x,b.y));
- collision_segments.push_back(Vector3(a.x,a.y,0));
- collision_segments.push_back(Vector3(b.x,b.y,0));
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(collision_segments);
- Vector<Vector3> handles;
- handles.push_back(Vector3(r,0,0));
- add_handles(handles);
-
- }
-
- if (s->cast_to<BoxShape>()) {
-
- Ref<BoxShape> bs=s;
- Vector<Vector3> lines;
- Rect3 aabb;
- aabb.pos=-bs->get_extents();
- aabb.size=aabb.pos*-2;
-
- for(int i=0;i<12;i++) {
- Vector3 a,b;
- aabb.get_edge(i,a,b);
- lines.push_back(a);
- lines.push_back(b);
- }
-
- Vector<Vector3> handles;
-
- for(int i=0;i<3;i++) {
-
- Vector3 ax;
- ax[i]=bs->get_extents()[i];
- handles.push_back(ax);
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(lines);
- add_handles(handles);
-
- }
-
- if (s->cast_to<CapsuleShape>()) {
-
- Ref<CapsuleShape> cs=s;
- float radius = cs->get_radius();
- float height = cs->get_height();
-
-
- Vector<Vector3> points;
-
- Vector3 d(0,0,height*0.5);
- for(int i=0;i<360;i++) {
-
- float ra=Math::deg2rad((float)i);
- float rb=Math::deg2rad((float)i+1);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
-
- points.push_back(Vector3(a.x,a.y,0)+d);
- points.push_back(Vector3(b.x,b.y,0)+d);
-
- points.push_back(Vector3(a.x,a.y,0)-d);
- points.push_back(Vector3(b.x,b.y,0)-d);
-
- if (i%90==0) {
-
- points.push_back(Vector3(a.x,a.y,0)+d);
- points.push_back(Vector3(a.x,a.y,0)-d);
- }
-
- Vector3 dud = i<180?d:-d;
-
- points.push_back(Vector3(0,a.y,a.x)+dud);
- points.push_back(Vector3(0,b.y,b.x)+dud);
- points.push_back(Vector3(a.y,0,a.x)+dud);
- points.push_back(Vector3(b.y,0,b.x)+dud);
-
- }
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
-
- Vector<Vector3> collision_segments;
-
- for(int i=0;i<64;i++) {
-
- float ra=i*Math_PI*2.0/64.0;
- float rb=(i+1)*Math_PI*2.0/64.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius;
-
- collision_segments.push_back(Vector3(a.x,a.y,0)+d);
- collision_segments.push_back(Vector3(b.x,b.y,0)+d);
-
- collision_segments.push_back(Vector3(a.x,a.y,0)-d);
- collision_segments.push_back(Vector3(b.x,b.y,0)-d);
-
- if (i%16==0) {
-
- collision_segments.push_back(Vector3(a.x,a.y,0)+d);
- collision_segments.push_back(Vector3(a.x,a.y,0)-d);
- }
-
- Vector3 dud = i<32?d:-d;
-
- collision_segments.push_back(Vector3(0,a.y,a.x)+dud);
- collision_segments.push_back(Vector3(0,b.y,b.x)+dud);
- collision_segments.push_back(Vector3(a.y,0,a.x)+dud);
- collision_segments.push_back(Vector3(b.y,0,b.x)+dud);
-
- }
-
- add_collision_segments(collision_segments);
-
- Vector<Vector3> handles;
- handles.push_back(Vector3(cs->get_radius(),0,0));
- handles.push_back(Vector3(0,0,cs->get_height()*0.5+cs->get_radius()));
- add_handles(handles);
-
-
- }
-
- if (s->cast_to<PlaneShape>()) {
-
- Ref<PlaneShape> ps=s;
- Plane p = ps->get_plane();
- Vector<Vector3> points;
-
- Vector3 n1 = p.get_any_perpendicular_normal();
- Vector3 n2 = p.normal.cross(n1).normalized();
-
- Vector3 pface[4]={
- p.normal*p.d+n1*10.0+n2*10.0,
- p.normal*p.d+n1*10.0+n2*-10.0,
- p.normal*p.d+n1*-10.0+n2*-10.0,
- p.normal*p.d+n1*-10.0+n2*10.0,
- };
-
- points.push_back(pface[0]);
- points.push_back(pface[1]);
- points.push_back(pface[1]);
- points.push_back(pface[2]);
- points.push_back(pface[2]);
- points.push_back(pface[3]);
- points.push_back(pface[3]);
- points.push_back(pface[0]);
- points.push_back(p.normal*p.d);
- points.push_back(p.normal*p.d+p.normal*3);
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
-
- }
-
-
- if (s->cast_to<ConvexPolygonShape>()) {
-
- PoolVector<Vector3> points = s->cast_to<ConvexPolygonShape>()->get_points();
-
- if (points.size()>3) {
-
- QuickHull qh;
- Vector<Vector3> varr = Variant(points);
- Geometry::MeshData md;
- Error err = qh.build(varr,md);
- if (err==OK) {
- Vector<Vector3> points;
- points.resize(md.edges.size()*2);
- for(int i=0;i<md.edges.size();i++) {
- points[i*2+0]=md.vertices[md.edges[i].a];
- points[i*2+1]=md.vertices[md.edges[i].b];
- }
-
-
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
-
- }
- }
-
- }
-
-
- if (s->cast_to<RayShape>()) {
-
- Ref<RayShape> rs=s;
-
- Vector<Vector3> points;
- points.push_back(Vector3());
- points.push_back(Vector3(0,0,rs->get_length()));
- add_lines(points,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(points);
- Vector<Vector3> handles;
- handles.push_back(Vector3(0,0,rs->get_length()));
- add_handles(handles);
-
-
- }
-
-}
-CollisionShapeSpatialGizmo::CollisionShapeSpatialGizmo(CollisionShape* p_cs) {
-
- cs=p_cs;
- set_spatial_node(p_cs);
-}
-
-
-
-/////
-
-
-void CollisionPolygonSpatialGizmo::redraw() {
-
- clear();
-
- Vector<Vector2> points = polygon->get_polygon();
- float depth = polygon->get_depth()*0.5;
-
- Vector<Vector3> lines;
- for(int i=0;i<points.size();i++) {
-
- int n = (i+1)%points.size();
- lines.push_back(Vector3(points[i].x,points[i].y,depth));
- lines.push_back(Vector3(points[n].x,points[n].y,depth));
- lines.push_back(Vector3(points[i].x,points[i].y,-depth));
- lines.push_back(Vector3(points[n].x,points[n].y,-depth));
- lines.push_back(Vector3(points[i].x,points[i].y,depth));
- lines.push_back(Vector3(points[i].x,points[i].y,-depth));
-
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
- add_collision_segments(lines);
-}
-
-CollisionPolygonSpatialGizmo::CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon){
-
- set_spatial_node(p_polygon);
- polygon=p_polygon;
-}
-///
-
-
-String VisibilityNotifierGizmo::get_handle_name(int p_idx) const {
-
- switch(p_idx) {
- case 0: return "X";
- case 1: return "Y";
- case 2: return "Z";
- }
-
- return "";
-}
-Variant VisibilityNotifierGizmo::get_handle_value(int p_idx) const{
-
- return notifier->get_aabb();
-}
-void VisibilityNotifierGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
-
- Transform gt = notifier->get_global_transform();
- //gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
- Rect3 aabb = notifier->get_aabb();
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*4096)};
- Vector3 ofs = aabb.pos+aabb.size*0.5;
-
- Vector3 axis;
- axis[p_idx]=1.0;
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(ofs,ofs+axis*4096,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (d<0.001)
- d=0.001;
-
- aabb.pos[p_idx]=(aabb.pos[p_idx]+aabb.size[p_idx]*0.5)-d;
- aabb.size[p_idx]=d*2;
- notifier->set_aabb(aabb);
-}
-
-void VisibilityNotifierGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
-
- if (p_cancel) {
- notifier->set_aabb(p_restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Notifier Extents"));
- ur->add_do_method(notifier,"set_aabb",notifier->get_aabb());
- ur->add_undo_method(notifier,"set_aabb",p_restore);
- ur->commit_action();
-
-}
-
-void VisibilityNotifierGizmo::redraw(){
-
- clear();
-
- Vector<Vector3> lines;
- Rect3 aabb = notifier->get_aabb();
-
- for(int i=0;i<12;i++) {
- Vector3 a,b;
- aabb.get_edge(i,a,b);
- lines.push_back(a);
- lines.push_back(b);
- }
-
- Vector<Vector3> handles;
-
-
- for(int i=0;i<3;i++) {
-
- Vector3 ax;
- ax[i]=aabb.pos[i]+aabb.size[i];
- handles.push_back(ax);
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->visibility_notifier_material);
- //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
- add_collision_segments(lines);
- add_handles(handles);
-
-}
-VisibilityNotifierGizmo::VisibilityNotifierGizmo(VisibilityNotifier* p_notifier){
-
- notifier=p_notifier;
- set_spatial_node(p_notifier);
-}
-
-////////
-
-
-///
-
-
-String ReflectionProbeGizmo::get_handle_name(int p_idx) const {
-
- switch(p_idx) {
- case 0: return "Extents X";
- case 1: return "Extents Y";
- case 2: return "Extents Z";
- case 3: return "Origin X";
- case 4: return "Origin Y";
- case 5: return "Origin Z";
- }
-
- return "";
-}
-Variant ReflectionProbeGizmo::get_handle_value(int p_idx) const{
-
- return Rect3(probe->get_extents(),probe->get_origin_offset());
-}
-void ReflectionProbeGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Transform gt = probe->get_global_transform();
- //gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
-
- if (p_idx<3) {
- Vector3 extents = probe->get_extents();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*16384)};
-
- Vector3 axis;
- axis[p_idx]=1.0;
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*16384,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (d<0.001)
- d=0.001;
-
- extents[p_idx]=d;
- probe->set_extents(extents);
- } else {
-
- p_idx-=3;
-
- Vector3 origin = probe->get_origin_offset();
- origin[p_idx]=0;
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*16384)};
-
- Vector3 axis;
- axis[p_idx]=1.0;
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(origin-axis*16384,origin+axis*16384,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- d+=0.25;
-
- origin[p_idx]=d;
- probe->set_origin_offset(origin);
-
- }
-}
-
-void ReflectionProbeGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- Rect3 restore = p_restore;
-
- if (p_cancel) {
- probe->set_extents(restore.pos);
- probe->set_origin_offset(restore.size);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Probe Extents"));
- ur->add_do_method(probe,"set_extents",probe->get_extents());
- ur->add_do_method(probe,"set_origin_offset",probe->get_origin_offset());
- ur->add_undo_method(probe,"set_extents",restore.pos);
- ur->add_undo_method(probe,"set_origin_offset",restore.size);
- ur->commit_action();
-
-}
-
-void ReflectionProbeGizmo::redraw(){
-
- clear();
-
- Vector<Vector3> lines;
- Vector<Vector3> internal_lines;
- Vector3 extents = probe->get_extents();
-
- Rect3 aabb;
- aabb.pos=-extents;
- aabb.size=extents*2;
-
- for(int i=0;i<12;i++) {
- Vector3 a,b;
- aabb.get_edge(i,a,b);
- lines.push_back(a);
- lines.push_back(b);
- }
-
- for(int i=0;i<8;i++) {
- Vector3 ep = aabb.get_endpoint(i);
- internal_lines.push_back(probe->get_origin_offset());
- internal_lines.push_back(ep);
-
-
- }
-
- Vector<Vector3> handles;
-
-
- for(int i=0;i<3;i++) {
-
- Vector3 ax;
- ax[i]=aabb.pos[i]+aabb.size[i];
- handles.push_back(ax);
- }
-
- for(int i=0;i<3;i++) {
-
-
- Vector3 orig_handle=probe->get_origin_offset();
- orig_handle[i]-=0.25;
- lines.push_back(orig_handle);
- handles.push_back(orig_handle);
-
- orig_handle[i]+=0.5;
- lines.push_back(orig_handle);
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->reflection_probe_material);
- add_lines(internal_lines,SpatialEditorGizmos::singleton->reflection_probe_material_internal);
- //add_unscaled_billboard(SpatialEditorGizmos::singleton->visi,0.05);
- add_collision_segments(lines);
- add_handles(handles);
-
-}
-ReflectionProbeGizmo::ReflectionProbeGizmo(ReflectionProbe* p_probe){
-
- probe=p_probe;
- set_spatial_node(p_probe);
-}
-
-////////
-
-
-
-///
-
-
-String GIProbeGizmo::get_handle_name(int p_idx) const {
-
- switch(p_idx) {
- case 0: return "Extents X";
- case 1: return "Extents Y";
- case 2: return "Extents Z";
- }
-
- return "";
-}
-Variant GIProbeGizmo::get_handle_value(int p_idx) const{
-
- return probe->get_extents();
-}
-void GIProbeGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Transform gt = probe->get_global_transform();
- //gt.orthonormalize();
- Transform gi = gt.affine_inverse();
-
-
- Vector3 extents = probe->get_extents();
-
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- Vector3 sg[2]={gi.xform(ray_from),gi.xform(ray_from+ray_dir*16384)};
-
- Vector3 axis;
- axis[p_idx]=1.0;
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(Vector3(),axis*16384,sg[0],sg[1],ra,rb);
- float d = ra[p_idx];
- if (d<0.001)
- d=0.001;
-
- extents[p_idx]=d;
- probe->set_extents(extents);
-
-}
-
-void GIProbeGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- Vector3 restore = p_restore;
-
- if (p_cancel) {
- probe->set_extents(restore);
- return;
- }
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
- ur->create_action(TTR("Change Probe Extents"));
- ur->add_do_method(probe,"set_extents",probe->get_extents());
- ur->add_undo_method(probe,"set_extents",restore);
- ur->commit_action();
-
-}
-
-void GIProbeGizmo::redraw(){
-
- clear();
-
- Vector<Vector3> lines;
- Vector3 extents = probe->get_extents();
-
- static const int subdivs[GIProbe::SUBDIV_MAX]={64,128,256,512};
-
- Rect3 aabb = Rect3(-extents,extents*2);
- int subdiv = subdivs[probe->get_subdiv()];
- float cell_size = aabb.get_longest_axis_size()/subdiv;
-
-
- for(int i=0;i<12;i++) {
- Vector3 a,b;
- aabb.get_edge(i,a,b);
- lines.push_back(a);
- lines.push_back(b);
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->gi_probe_material);
- add_collision_segments(lines);
-
- lines.clear();
-
- for(int i=1;i<subdiv;i++) {
-
- for(int j=0;j<3;j++) {
-
-
-
- if (cell_size*i>aabb.size[j]) {
- continue;
- }
-
- Vector2 dir;
- dir[j]=1.0;
- Vector2 ta,tb;
- int j_n1=(j+1)%3;
- int j_n2=(j+2)%3;
- ta[j_n1]=1.0;
- tb[j_n2]=1.0;
-
-
- for(int k=0;k<4;k++) {
-
- Vector3 from=aabb.pos,to=aabb.pos;
- from[j]+= cell_size*i;
- to[j]+=cell_size*i;
-
- if (k&1) {
- to[j_n1]+=aabb.size[j_n1];
- } else {
-
- to[j_n2]+=aabb.size[j_n2];
- }
-
- if (k&2) {
- from[j_n1]+=aabb.size[j_n1];
- from[j_n2]+=aabb.size[j_n2];
- }
-
- lines.push_back(from);
- lines.push_back(to);
- }
-
- }
-
- }
-
- add_lines(lines,SpatialEditorGizmos::singleton->gi_probe_material_internal);
-
- Vector<Vector3> handles;
-
-
- for(int i=0;i<3;i++) {
-
- Vector3 ax;
- ax[i]=aabb.pos[i]+aabb.size[i];
- handles.push_back(ax);
- }
-
-
- add_handles(handles);
-
-}
-GIProbeGizmo::GIProbeGizmo(GIProbe* p_probe){
-
- probe=p_probe;
- set_spatial_node(p_probe);
-}
-
-////////
-
-
-void NavigationMeshSpatialGizmo::redraw() {
-
- clear();
- Ref<NavigationMesh> navmeshie = navmesh->get_navigation_mesh();
- if (navmeshie.is_null())
- return;
-
- PoolVector<Vector3> vertices = navmeshie->get_vertices();
- PoolVector<Vector3>::Read vr=vertices.read();
- List<Face3> faces;
- for(int i=0;i<navmeshie->get_polygon_count();i++) {
- Vector<int> p = navmeshie->get_polygon(i);
-
- for(int j=2;j<p.size();j++) {
- Face3 f;
- f.vertex[0]=vr[p[0]];
- f.vertex[1]=vr[p[j-1]];
- f.vertex[2]=vr[p[j]];
-
- faces.push_back(f);
- }
- }
-
- if (faces.empty())
- return;
-
- Map<_EdgeKey,bool> edge_map;
- PoolVector<Vector3> tmeshfaces;
- tmeshfaces.resize(faces.size()*3);
-
- {
- PoolVector<Vector3>::Write tw=tmeshfaces.write();
- int tidx=0;
-
-
- for(List<Face3>::Element *E=faces.front();E;E=E->next()) {
-
- const Face3 &f = E->get();
-
- for(int j=0;j<3;j++) {
-
- tw[tidx++]=f.vertex[j];
- _EdgeKey ek;
- ek.from=f.vertex[j].snapped(CMP_EPSILON);
- ek.to=f.vertex[(j+1)%3].snapped(CMP_EPSILON);
- if (ek.from<ek.to)
- SWAP(ek.from,ek.to);
-
- Map<_EdgeKey,bool>::Element *E=edge_map.find(ek);
-
- if (E) {
-
- E->get()=false;
-
- } else {
-
- edge_map[ek]=true;
- }
-
- }
- }
- }
- Vector<Vector3> lines;
-
- for(Map<_EdgeKey,bool>::Element *E=edge_map.front();E;E=E->next()) {
-
- if (E->get()) {
- lines.push_back(E->key().from);
- lines.push_back(E->key().to);
- }
- }
-
- Ref<TriangleMesh> tmesh = memnew( TriangleMesh );
- tmesh->create(tmeshfaces);
-
- if (lines.size())
- add_lines(lines,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_edge_material:SpatialEditorGizmos::singleton->navmesh_edge_material_disabled);
- add_collision_triangles(tmesh);
- Ref<Mesh> m = memnew( Mesh );
- Array a;
- a.resize(Mesh::ARRAY_MAX);
- a[0]=tmeshfaces;
- m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,a);
- m->surface_set_material(0,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_solid_material:SpatialEditorGizmos::singleton->navmesh_solid_material_disabled);
- add_mesh(m);
- add_collision_segments(lines);
-
-}
-
-NavigationMeshSpatialGizmo::NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh){
-
- set_spatial_node(p_navmesh);
- navmesh=p_navmesh;
-}
-
-//////
-///
-///
-
-
-
-void PinJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs));
- cursor_points.push_back(Vector3(0,0,-cs));
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-////
-
-void HingeJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));*/
- cursor_points.push_back(Vector3(0,0,+cs*2));
- cursor_points.push_back(Vector3(0,0,-cs*2));
-
- float ll = p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER);
- float ul = p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER);
-
- if (p3d->get_flag(HingeJoint::FLAG_USE_LIMIT) && ll<ul) {
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(ul-ll)/points;
- float n = ll+(i+1)*(ul-ll)/points;
-
- Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs;
- Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs;
-
- if (i==points-1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i==0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
-
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
-
- }
-
- cursor_points.push_back(Vector3(0,cs*1.5,0));
- cursor_points.push_back(Vector3());
-
- } else {
-
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(Math_PI*2.0)/points;
- float n = ll+(i+1)*(Math_PI*2.0)/points;
-
- Vector3 from=Vector3( -Math::sin(s),Math::cos(s), 0 )*cs;
- Vector3 to=Vector3( -Math::sin(n),Math::cos(n), 0 )*cs;
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
- }
-
- }
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-///////
-///
-////
-
-void SliderJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));*/
- cursor_points.push_back(Vector3(0,0,+cs*2));
- cursor_points.push_back(Vector3(0,0,-cs*2));
-
- float ll = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER);
- float ul = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER);
- float lll = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER);
- float lul = -p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER);
-
- if (lll>lul) {
-
- cursor_points.push_back(Vector3(lul,0,0));
- cursor_points.push_back(Vector3(lll,0,0));
-
- cursor_points.push_back(Vector3(lul,-cs,-cs));
- cursor_points.push_back(Vector3(lul,-cs,cs));
- cursor_points.push_back(Vector3(lul,-cs,cs));
- cursor_points.push_back(Vector3(lul,cs,cs));
- cursor_points.push_back(Vector3(lul,cs,cs));
- cursor_points.push_back(Vector3(lul,cs,-cs));
- cursor_points.push_back(Vector3(lul,cs,-cs));
- cursor_points.push_back(Vector3(lul,-cs,-cs));
-
-
- cursor_points.push_back(Vector3(lll,-cs,-cs));
- cursor_points.push_back(Vector3(lll,-cs,cs));
- cursor_points.push_back(Vector3(lll,-cs,cs));
- cursor_points.push_back(Vector3(lll,cs,cs));
- cursor_points.push_back(Vector3(lll,cs,cs));
- cursor_points.push_back(Vector3(lll,cs,-cs));
- cursor_points.push_back(Vector3(lll,cs,-cs));
- cursor_points.push_back(Vector3(lll,-cs,-cs));
-
-
- } else {
-
- cursor_points.push_back(Vector3(+cs*2,0,0));
- cursor_points.push_back(Vector3(-cs*2,0,0));
-
- }
-
- if (ll<ul) {
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(ul-ll)/points;
- float n = ll+(i+1)*(ul-ll)/points;
-
- Vector3 from=Vector3(0, Math::cos(s), -Math::sin(s) )*cs;
- Vector3 to=Vector3(0,Math::cos(n), -Math::sin(n) )*cs;
-
- if (i==points-1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i==0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
-
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
-
- }
-
- cursor_points.push_back(Vector3(0,cs*1.5,0));
- cursor_points.push_back(Vector3());
-
- } else {
-
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(Math_PI*2.0)/points;
- float n = ll+(i+1)*(Math_PI*2.0)/points;
-
- Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
- Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
- }
-
- }
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-///////
-///
-////
-
-void ConeTwistJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> points;
-
- float r = 1.0;
- float w = r*Math::sin(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
- float d = r*Math::cos(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
-
-
- //swing
- for(int i=0;i<360;i+=10) {
-
- float ra=Math::deg2rad((float)i);
- float rb=Math::deg2rad((float)i+10);
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
- points.push_back(Vector3(d,a.x,a.y));
- points.push_back(Vector3(d,b.x,b.y));
-
- if (i%90==0) {
-
- points.push_back(Vector3(d,a.x,a.y));
- points.push_back(Vector3());
-
- }
- }
-
- points.push_back(Vector3());
- points.push_back(Vector3(1,0,0));
-
- //twist
- /*
- */
- float ts=Math::rad2deg(p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN));
- ts=MIN(ts,720);
-
-
- for(int i=0;i<int(ts);i+=5) {
-
- float ra=Math::deg2rad((float)i);
- float rb=Math::deg2rad((float)i+5);
- float c = i/720.0;
- float cn = (i+5)/720.0;
- Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*w*c;
- Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*w*cn;
-
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
-
- points.push_back(Vector3(c,a.x,a.y));
- points.push_back(Vector3(cn,b.x,b.y));
-
- }
-
-
- add_collision_segments(points);
- add_lines(points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-////////
-/// \brief SpatialEditorGizmos::singleton
-///
-///////
-///
-////
-
-void Generic6DOFJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
-
- for(int ax=0;ax<3;ax++) {
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs*2));
- cursor_points.push_back(Vector3(0,0,-cs*2)); */
-
- float ll;
- float ul;
- float lll;
- float lul;
-
- int a1,a2,a3;
- bool enable_ang;
- bool enable_lin;
-
- switch(ax) {
- case 0:
- ll = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = -p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
- a1=0;
- a2=1;
- a3=2;
- break;
- case 1:
- ll = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = -p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
- a1=2;
- a2=0;
- a3=1;
- break;
- case 2:
- ll = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = -p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
-
- a1=1;
- a2=2;
- a3=0;
- break;
- }
-
-#define ADD_VTX(x,y,z)\
- {\
- Vector3 v;\
- v[a1]=(x);\
- v[a2]=(y);\
- v[a3]=(z);\
- cursor_points.push_back(v);\
- }
-
-#define SET_VTX(what,x,y,z)\
- {\
- Vector3 v;\
- v[a1]=(x);\
- v[a2]=(y);\
- v[a3]=(z);\
- what=v;\
- }
-
-
-
-
- if (enable_lin && lll>=lul) {
-
- ADD_VTX(lul,0,0);
- ADD_VTX(lll,0,0);
-
- ADD_VTX(lul,-cs,-cs);
- ADD_VTX(lul,-cs,cs);
- ADD_VTX(lul,-cs,cs);
- ADD_VTX(lul,cs,cs);
- ADD_VTX(lul,cs,cs);
- ADD_VTX(lul,cs,-cs);
- ADD_VTX(lul,cs,-cs);
- ADD_VTX(lul,-cs,-cs);
-
-
- ADD_VTX(lll,-cs,-cs);
- ADD_VTX(lll,-cs,cs);
- ADD_VTX(lll,-cs,cs);
- ADD_VTX(lll,cs,cs);
- ADD_VTX(lll,cs,cs);
- ADD_VTX(lll,cs,-cs);
- ADD_VTX(lll,cs,-cs);
- ADD_VTX(lll,-cs,-cs);
-
-
- } else {
-
- ADD_VTX(+cs*2,0,0);
- ADD_VTX(-cs*2,0,0);
-
- }
-
- if (enable_ang && ll<=ul) {
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(ul-ll)/points;
- float n = ll+(i+1)*(ul-ll)/points;
-
- Vector3 from;
- SET_VTX(from,0, Math::cos(s), -Math::sin(s) );
- from*=cs;
- Vector3 to;
- SET_VTX(to,0,Math::cos(n), -Math::sin(n));
- to*=cs;
-
- if (i==points-1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i==0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
-
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
-
- }
-
- ADD_VTX(0,cs*1.5,0);
- cursor_points.push_back(Vector3());
-
- } else {
-
-
- const int points = 32;
-
- for(int i=0;i<points;i++) {
-
- float s = ll+i*(Math_PI*2.0)/points;
- float n = ll+(i+1)*(Math_PI*2.0)/points;
-
- //Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
- //Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
-
- Vector3 from;
- SET_VTX(from,0, Math::cos(s), -Math::sin(s) );
- from*=cs;
- Vector3 to;
- SET_VTX(to,0,Math::cos(n), -Math::sin(n));
- to*=cs;
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
-
- }
-
- }
- }
-
-#undef ADD_VTX
-#undef SET_VTX
-
- add_collision_segments(cursor_points);
- add_lines(cursor_points,SpatialEditorGizmos::singleton->joint_material);
-
-}
-
-
-Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d) {
-
- p3d=p_p3d;
- set_spatial_node(p3d);
-}
-
-///////
-///
-////
-
-
-SpatialEditorGizmos *SpatialEditorGizmos::singleton=NULL;
-
-Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) {
-
- if (p_spatial->cast_to<Light>()) {
-
- Ref<LightSpatialGizmo> lsg = memnew( LightSpatialGizmo(p_spatial->cast_to<Light>()) );
- return lsg;
- }
-
-
-
- if (p_spatial->cast_to<Camera>()) {
-
- Ref<CameraSpatialGizmo> lsg = memnew( CameraSpatialGizmo(p_spatial->cast_to<Camera>()) );
- return lsg;
- }
-
- if (p_spatial->cast_to<Skeleton>()) {
-
- Ref<SkeletonSpatialGizmo> lsg = memnew( SkeletonSpatialGizmo(p_spatial->cast_to<Skeleton>()) );
- return lsg;
- }
-
-
- if (p_spatial->cast_to<Position3D>()) {
-
- Ref<Position3DSpatialGizmo> lsg = memnew( Position3DSpatialGizmo(p_spatial->cast_to<Position3D>()) );
- return lsg;
- }
-
- if (p_spatial->cast_to<MeshInstance>()) {
-
- Ref<MeshInstanceSpatialGizmo> misg = memnew( MeshInstanceSpatialGizmo(p_spatial->cast_to<MeshInstance>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<Room>()) {
-
- Ref<RoomSpatialGizmo> misg = memnew( RoomSpatialGizmo(p_spatial->cast_to<Room>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<NavigationMeshInstance>()) {
-
- Ref<NavigationMeshSpatialGizmo> misg = memnew( NavigationMeshSpatialGizmo(p_spatial->cast_to<NavigationMeshInstance>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<RayCast>()) {
-
- Ref<RayCastSpatialGizmo> misg = memnew( RayCastSpatialGizmo(p_spatial->cast_to<RayCast>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<Portal>()) {
-
- Ref<PortalSpatialGizmo> misg = memnew( PortalSpatialGizmo(p_spatial->cast_to<Portal>()) );
- return misg;
- }
-
-
- if (p_spatial->cast_to<TestCube>()) {
-
- Ref<TestCubeSpatialGizmo> misg = memnew( TestCubeSpatialGizmo(p_spatial->cast_to<TestCube>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<CollisionShape>()) {
-
- Ref<CollisionShapeSpatialGizmo> misg = memnew( CollisionShapeSpatialGizmo(p_spatial->cast_to<CollisionShape>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<VisibilityNotifier>()) {
-
- Ref<VisibilityNotifierGizmo> misg = memnew( VisibilityNotifierGizmo(p_spatial->cast_to<VisibilityNotifier>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<ReflectionProbe>()) {
-
- Ref<ReflectionProbeGizmo> misg = memnew( ReflectionProbeGizmo(p_spatial->cast_to<ReflectionProbe>()) );
- return misg;
- }
- if (p_spatial->cast_to<GIProbe>()) {
-
- Ref<GIProbeGizmo> misg = memnew( GIProbeGizmo(p_spatial->cast_to<GIProbe>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<VehicleWheel>()) {
-
- Ref<VehicleWheelSpatialGizmo> misg = memnew( VehicleWheelSpatialGizmo(p_spatial->cast_to<VehicleWheel>()) );
- return misg;
- }
- if (p_spatial->cast_to<PinJoint>()) {
-
- Ref<PinJointSpatialGizmo> misg = memnew( PinJointSpatialGizmo(p_spatial->cast_to<PinJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<HingeJoint>()) {
-
- Ref<HingeJointSpatialGizmo> misg = memnew( HingeJointSpatialGizmo(p_spatial->cast_to<HingeJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<SliderJoint>()) {
-
- Ref<SliderJointSpatialGizmo> misg = memnew( SliderJointSpatialGizmo(p_spatial->cast_to<SliderJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<ConeTwistJoint>()) {
-
- Ref<ConeTwistJointSpatialGizmo> misg = memnew( ConeTwistJointSpatialGizmo(p_spatial->cast_to<ConeTwistJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<Generic6DOFJoint>()) {
-
- Ref<Generic6DOFJointSpatialGizmo> misg = memnew( Generic6DOFJointSpatialGizmo(p_spatial->cast_to<Generic6DOFJoint>()) );
- return misg;
- }
-
- if (p_spatial->cast_to<CollisionPolygon>()) {
-
- Ref<CollisionPolygonSpatialGizmo> misg = memnew( CollisionPolygonSpatialGizmo(p_spatial->cast_to<CollisionPolygon>()) );
- return misg;
- }
-
-
- return Ref<SpatialEditorGizmo>();
-}
-
-
-Ref<FixedSpatialMaterial> SpatialEditorGizmos::create_line_material(const Color& p_base_color) {
-
- Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- line_material->set_line_width(3.0);
- line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- //line_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- //->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
- line_material->set_albedo(p_base_color);
-
- return line_material;
-
-}
-
-Ref<FixedSpatialMaterial> SpatialEditorGizmos::create_solid_material(const Color& p_base_color) {
-
- Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- line_material->set_albedo(p_base_color);
-
- return line_material;
-
-}
-
-SpatialEditorGizmos::SpatialEditorGizmos() {
-
- singleton=this;
-
- handle_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- handle_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- handle_material->set_albedo(Color(0.8,0.8,0.8));
-
- handle2_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- handle2_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- handle2_material->set_flag(FixedSpatialMaterial::FLAG_USE_POINT_SIZE, true);
- handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle","EditorIcons");
- handle2_material->set_point_size(handle_t->get_width());
- handle2_material->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,handle_t);
- handle2_material->set_albedo(Color(1,1,1));
- handle2_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- handle2_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- handle2_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
-
- light_material = create_line_material(Color(1,1,0.2));
-
- light_material_omni_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- light_material_omni_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- light_material_omni_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- light_material_omni_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
- light_material_omni_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- light_material_omni_icon->set_albedo(Color(1,1,1,0.9));
- light_material_omni_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoLight","EditorIcons"));
-
-
- light_material_directional_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- light_material_directional_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- light_material_directional_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- light_material_directional_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
- light_material_directional_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- light_material_directional_icon->set_albedo(Color(1,1,1,0.9));
- light_material_directional_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight","EditorIcons"));
-
- camera_material = create_line_material(Color(1.0,0.5,1.0));
-
-
- navmesh_edge_material = create_line_material(Color(0.1,0.8,1.0));
- navmesh_solid_material = create_solid_material(Color(0.1,0.8,1.0,0.4));
- navmesh_edge_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false);
- navmesh_edge_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false);
- navmesh_solid_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
-
- navmesh_edge_material_disabled = create_line_material(Color(1.0,0.8,0.1));
- navmesh_solid_material_disabled = create_solid_material(Color(1.0,0.8,0.1,0.4));
- navmesh_edge_material_disabled->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false);
- navmesh_edge_material_disabled->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false);
- navmesh_solid_material_disabled->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
-
- skeleton_material = create_line_material(Color(0.6,1.0,0.3));
- skeleton_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- skeleton_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
- skeleton_material->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true);
- skeleton_material->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
-
- //position 3D Shared mesh
-
- pos3d_mesh = Ref<Mesh>( memnew( Mesh ) );
- {
-
- PoolVector<Vector3> cursor_points;
- PoolVector<Color> cursor_colors;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs));
- cursor_points.push_back(Vector3(0,0,-cs));
- cursor_colors.push_back(Color(1,0.5,0.5,0.7));
- cursor_colors.push_back(Color(1,0.5,0.5,0.7));
- cursor_colors.push_back(Color(0.5,1,0.5,0.7));
- cursor_colors.push_back(Color(0.5,1,0.5,0.7));
- cursor_colors.push_back(Color(0.5,0.5,1,0.7));
- cursor_colors.push_back(Color(0.5,0.5,1,0.7));
-
- Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial );
- mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED,true);
- mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR,true);
- mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR,true);
- mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT,true);
- mat->set_line_width(3);
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[Mesh::ARRAY_VERTEX]=cursor_points;
- d[Mesh::ARRAY_COLOR]=cursor_colors;
- pos3d_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,d);
- pos3d_mesh->surface_set_material(0,mat);
- }
-
- listener_line_mesh = Ref<Mesh>(memnew(Mesh));
- {
-
- PoolVector<Vector3> cursor_points;
- PoolVector<Color> cursor_colors;
- cursor_points.push_back(Vector3(0, 0, 0));
- cursor_points.push_back(Vector3(0, 0, -1.0));
- cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7));
- cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7));
-
- Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial);
- mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
- mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- mat->set_line_width(3);
- Array d;
- d.resize(VS::ARRAY_MAX);
- d[Mesh::ARRAY_VERTEX] = cursor_points;
- d[Mesh::ARRAY_COLOR] = cursor_colors;
- listener_line_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d);
- listener_line_mesh->surface_set_material(0, mat);
- }
-
-
- sample_player_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- sample_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- sample_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- sample_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
- sample_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- sample_player_icon->set_albedo(Color(1,1,1,0.9));
- sample_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer","EditorIcons"));
-
- room_material = create_line_material(Color(1.0,0.6,0.9));
- portal_material = create_line_material(Color(1.0,0.8,0.6));
- raycast_material = create_line_material(Color(1.0,0.8,0.6));
- car_wheel_material = create_line_material(Color(0.6,0.8,1.0));
- visibility_notifier_material = create_line_material(Color(1.0,0.5,1.0));
- reflection_probe_material = create_line_material(Color(0.5,1.0,0.7));
- reflection_probe_material_internal = create_line_material(Color(0.3,0.8,0.5,0.15));
- gi_probe_material = create_line_material(Color(0.7,1.0,0.5));
- gi_probe_material_internal = create_line_material(Color(0.5,0.8,0.3,0.1));
- joint_material = create_line_material(Color(0.6,0.8,1.0));
-
- stream_player_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- stream_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- stream_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- stream_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
- stream_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- stream_player_icon->set_albedo(Color(1,1,1,0.9));
- stream_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer","EditorIcons"));
-
- visibility_notifier_icon = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial ));
- visibility_notifier_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- visibility_notifier_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- visibility_notifier_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
- visibility_notifier_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- visibility_notifier_icon->set_albedo(Color(1,1,1,0.9));
- visibility_notifier_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO,SpatialEditor::get_singleton()->get_icon("Visible","EditorIcons"));
-
- listener_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial));
- listener_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true);
- listener_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED);
- listener_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED);
- listener_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true);
- listener_icon->set_albedo( Color(1, 1, 1, 0.9));
- listener_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoListener", "EditorIcons"));
-
- {
-
- PoolVector<Vector3> vertices;
-
-#undef ADD_VTX
-#define ADD_VTX(m_idx) \
- vertices.push_back( face_points[m_idx] );
-
- for (int i=0;i<6;i++) {
-
-
- Vector3 face_points[4];
-
- for (int j=0;j<4;j++) {
-
- float v[3];
- v[0]=1.0;
- v[1]=1-2*((j>>1)&1);
- v[2]=v[1]*(1-2*(j&1));
-
- for (int k=0;k<3;k++) {
-
- if (i<3)
- face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1);
- else
- face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1);
- }
- }
- //tri 1
- ADD_VTX(0);
- ADD_VTX(1);
- ADD_VTX(2);
- //tri 2
- ADD_VTX(2);
- ADD_VTX(3);
- ADD_VTX(0);
-
- }
-
- test_cube_tm = Ref<TriangleMesh>( memnew( TriangleMesh ) );
- test_cube_tm->create(vertices);
- }
-
- shape_material = create_line_material(Color(0.2,1,1.0));
-
-
-}
-
diff --git a/tools/editor/spatial_editor_gizmos.h b/tools/editor/spatial_editor_gizmos.h
deleted file mode 100644
index 8a63d4f81e..0000000000
--- a/tools/editor/spatial_editor_gizmos.h
+++ /dev/null
@@ -1,521 +0,0 @@
-/*************************************************************************/
-/* spatial_editor_gizmos.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan 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 SPATIAL_EDITOR_GIZMOS_H
-#define SPATIAL_EDITOR_GIZMOS_H
-
-
-#include "tools/editor/plugins/spatial_editor_plugin.h"
-#include "scene/3d/light.h"
-#include "scene/3d/listener.h"
-#include "scene/3d/camera.h"
-#include "scene/3d/position_3d.h"
-#include "scene/3d/test_cube.h"
-#include "scene/3d/mesh_instance.h"
-#include "scene/3d/body_shape.h"
-#include "scene/3d/room_instance.h"
-#include "scene/3d/visibility_notifier.h"
-#include "scene/3d/portal.h"
-#include "scene/3d/ray_cast.h"
-#include "scene/3d/navigation_mesh.h"
-#include "scene/3d/reflection_probe.h"
-#include "scene/3d/gi_probe.h"
-
-#include "scene/3d/vehicle_body.h"
-#include "scene/3d/collision_polygon.h"
-#include "scene/3d/physics_joint.h"
-
-
-class Camera;
-
-class EditorSpatialGizmo : public SpatialEditorGizmo {
-
- GDCLASS(EditorSpatialGizmo,SpatialGizmo);
-
- struct Instance{
-
- RID instance;
- Ref<Mesh> mesh;
- RID skeleton;
- bool billboard;
- bool unscaled;
- bool can_intersect;
- bool extra_margin;
- Instance() {
-
- billboard=false;
- unscaled=false;
- can_intersect=false;
- extra_margin=false;
- }
-
- void create_instance(Spatial *p_base);
-
- };
-
- Vector<Vector3> collision_segments;
- Ref<TriangleMesh> collision_mesh;
-
- struct Handle {
- Vector3 pos;
- bool billboard;
- };
-
- Vector<Vector3> handles;
- Vector<Vector3> secondary_handles;
- bool billboard_handle;
-
- bool valid;
- Spatial *base;
- Vector<Instance> instances;
- Spatial *spatial_node;
-
- void _set_spatial_node(Node *p_node) { set_spatial_node(p_node->cast_to<Spatial>()); }
-protected:
- void add_lines(const Vector<Vector3> &p_lines,const Ref<Material>& p_material,bool p_billboard=false);
- void add_mesh(const Ref<Mesh>& p_mesh,bool p_billboard=false,const RID& p_skeleton=RID());
- void add_collision_segments(const Vector<Vector3> &p_lines);
- void add_collision_triangles(const Ref<TriangleMesh>& p_tmesh);
- void add_unscaled_billboard(const Ref<Material>& p_material,float p_scale=1);
- void add_handles(const Vector<Vector3> &p_handles,bool p_billboard=false,bool p_secondary=false);
-
- void set_spatial_node(Spatial *p_node);
-
- static void _bind_methods();
-public:
-
- virtual Vector3 get_handle_pos(int p_idx) const;
- virtual bool intersect_frustum(const Camera *p_camera,const Vector<Plane> &p_frustum);
- virtual bool intersect_ray(const Camera *p_camera,const Point2& p_point, Vector3& r_pos, Vector3& r_normal,int *r_gizmo_handle=NULL,bool p_sec_first=false);
-
- void clear();
- void create();
- void transform();
- virtual void redraw();
- void free();
-
- EditorSpatialGizmo();
- ~EditorSpatialGizmo();
-};
-
-
-
-class LightSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(LightSpatialGizmo,EditorSpatialGizmo);
-
- Light* light;
-
-public:
-
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- LightSpatialGizmo(Light* p_light=NULL);
-
-};
-
-class CameraSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(CameraSpatialGizmo,EditorSpatialGizmo);
-
- Camera* camera;
-
-public:
-
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- CameraSpatialGizmo(Camera* p_camera=NULL);
-
-};
-
-
-
-class MeshInstanceSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(MeshInstanceSpatialGizmo,EditorSpatialGizmo);
-
- MeshInstance* mesh;
-
-public:
-
- void redraw();
- MeshInstanceSpatialGizmo(MeshInstance* p_mesh=NULL);
-
-};
-
-class Position3DSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(Position3DSpatialGizmo,EditorSpatialGizmo);
-
- Position3D* p3d;
-
-public:
-
- void redraw();
- Position3DSpatialGizmo(Position3D* p_p3d=NULL);
-
-};
-
-class SkeletonSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(SkeletonSpatialGizmo,EditorSpatialGizmo);
-
- Skeleton* skel;
-
-public:
-
- void redraw();
- SkeletonSpatialGizmo(Skeleton* p_skel=NULL);
-
-};
-
-
-class TestCubeSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(TestCubeSpatialGizmo,EditorSpatialGizmo);
-
- TestCube* tc;
-
-public:
- void redraw();
- TestCubeSpatialGizmo(TestCube* p_tc=NULL);
-
-};
-
-
-class RoomSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(RoomSpatialGizmo,EditorSpatialGizmo);
-
-
- struct _EdgeKey {
-
- Vector3 from;
- Vector3 to;
-
- bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; }
- };
-
-
-
- Room* room;
-
-public:
-
- void redraw();
- RoomSpatialGizmo(Room* p_room=NULL);
-
-};
-
-
-class PortalSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(PortalSpatialGizmo,EditorSpatialGizmo);
-
- Portal* portal;
-
-public:
-
- void redraw();
- PortalSpatialGizmo(Portal* p_portal=NULL);
-
-};
-
-
-class VisibilityNotifierGizmo : public EditorSpatialGizmo {
-
- GDCLASS(VisibilityNotifierGizmo ,EditorSpatialGizmo);
-
-
- VisibilityNotifier* notifier;
-
-public:
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- VisibilityNotifierGizmo(VisibilityNotifier* p_notifier=NULL);
-
-};
-
-
-class ReflectionProbeGizmo : public EditorSpatialGizmo {
-
- GDCLASS(ReflectionProbeGizmo ,EditorSpatialGizmo);
-
-
- ReflectionProbe* probe;
-
-public:
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- ReflectionProbeGizmo(ReflectionProbe* p_notifier=NULL);
-
-};
-
-class GIProbeGizmo : public EditorSpatialGizmo {
-
- GDCLASS(GIProbeGizmo ,EditorSpatialGizmo);
-
-
- GIProbe* probe;
-
-public:
-
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
-
- void redraw();
- GIProbeGizmo(GIProbe* p_notifier=NULL);
-
-};
-
-
-class CollisionShapeSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(CollisionShapeSpatialGizmo,EditorSpatialGizmo);
-
- CollisionShape* cs;
-
-public:
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx) const;
- virtual void set_handle(int p_idx,Camera *p_camera, const Point2& p_point);
- virtual void commit_handle(int p_idx,const Variant& p_restore,bool p_cancel=false);
- void redraw();
- CollisionShapeSpatialGizmo(CollisionShape* p_cs=NULL);
-
-};
-
-
-class CollisionPolygonSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(CollisionPolygonSpatialGizmo,EditorSpatialGizmo);
-
- CollisionPolygon* polygon;
-
-public:
-
- void redraw();
- CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon=NULL);
-
-};
-
-
-
-class RayCastSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(RayCastSpatialGizmo,EditorSpatialGizmo);
-
- RayCast* raycast;
-
-public:
-
- void redraw();
- RayCastSpatialGizmo(RayCast* p_raycast=NULL);
-
-};
-
-
-
-class VehicleWheelSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(VehicleWheelSpatialGizmo,EditorSpatialGizmo);
-
- VehicleWheel* car_wheel;
-
-public:
-
- void redraw();
- VehicleWheelSpatialGizmo(VehicleWheel* p_car_wheel=NULL);
-
-};
-
-
-class NavigationMeshSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(NavigationMeshSpatialGizmo,EditorSpatialGizmo);
-
-
- struct _EdgeKey {
-
- Vector3 from;
- Vector3 to;
-
- bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; }
- };
-
-
-
- NavigationMeshInstance* navmesh;
-
-public:
-
- void redraw();
- NavigationMeshSpatialGizmo(NavigationMeshInstance* p_navmesh=NULL);
-
-};
-
-
-class PinJointSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(PinJointSpatialGizmo,EditorSpatialGizmo);
-
- PinJoint* p3d;
-
-public:
-
- void redraw();
- PinJointSpatialGizmo(PinJoint* p_p3d=NULL);
-
-};
-
-
-class HingeJointSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(HingeJointSpatialGizmo,EditorSpatialGizmo);
-
- HingeJoint* p3d;
-
-public:
-
- void redraw();
- HingeJointSpatialGizmo(HingeJoint* p_p3d=NULL);
-
-};
-
-class SliderJointSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(SliderJointSpatialGizmo,EditorSpatialGizmo);
-
- SliderJoint* p3d;
-
-public:
-
- void redraw();
- SliderJointSpatialGizmo(SliderJoint* p_p3d=NULL);
-
-};
-
-class ConeTwistJointSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(ConeTwistJointSpatialGizmo,EditorSpatialGizmo);
-
- ConeTwistJoint* p3d;
-
-public:
-
- void redraw();
- ConeTwistJointSpatialGizmo(ConeTwistJoint* p_p3d=NULL);
-
-};
-
-
-class Generic6DOFJointSpatialGizmo : public EditorSpatialGizmo {
-
- GDCLASS(Generic6DOFJointSpatialGizmo,EditorSpatialGizmo);
-
- Generic6DOFJoint* p3d;
-
-public:
-
- void redraw();
- Generic6DOFJointSpatialGizmo(Generic6DOFJoint* p_p3d=NULL);
-
-};
-
-
-class SpatialEditorGizmos {
-public:
-
- Ref<FixedSpatialMaterial> create_line_material(const Color& p_base_color);
- Ref<FixedSpatialMaterial> create_solid_material(const Color& p_base_color);
- Ref<FixedSpatialMaterial> handle2_material;
- Ref<FixedSpatialMaterial> handle_material;
- Ref<FixedSpatialMaterial> light_material;
- Ref<FixedSpatialMaterial> light_material_omni_icon;
- Ref<FixedSpatialMaterial> light_material_directional_icon;
- Ref<FixedSpatialMaterial> camera_material;
- Ref<FixedSpatialMaterial> skeleton_material;
- Ref<FixedSpatialMaterial> reflection_probe_material;
- Ref<FixedSpatialMaterial> reflection_probe_material_internal;
- Ref<FixedSpatialMaterial> gi_probe_material;
- Ref<FixedSpatialMaterial> gi_probe_material_internal;
- Ref<FixedSpatialMaterial> room_material;
- Ref<FixedSpatialMaterial> portal_material;
- Ref<FixedSpatialMaterial> raycast_material;
- Ref<FixedSpatialMaterial> visibility_notifier_material;
- Ref<FixedSpatialMaterial> car_wheel_material;
- Ref<FixedSpatialMaterial> joint_material;
-
- Ref<FixedSpatialMaterial> navmesh_edge_material;
- Ref<FixedSpatialMaterial> navmesh_solid_material;
- Ref<FixedSpatialMaterial> navmesh_edge_material_disabled;
- Ref<FixedSpatialMaterial> navmesh_solid_material_disabled;
-
- Ref<FixedSpatialMaterial> listener_icon;
-
- Ref<FixedSpatialMaterial> sample_player_icon;
- Ref<FixedSpatialMaterial> stream_player_icon;
- Ref<FixedSpatialMaterial> visibility_notifier_icon;
-
- Ref<FixedSpatialMaterial> shape_material;
- Ref<Texture> handle_t;
-
- Ref<Mesh> pos3d_mesh;
- Ref<Mesh> listener_line_mesh;
- static SpatialEditorGizmos *singleton;
-
- Ref<TriangleMesh> test_cube_tm;
-
-
- Ref<SpatialEditorGizmo> get_gizmo(Spatial *p_spatial);
-
- SpatialEditorGizmos();
-};
-#endif // SPATIAL_EDITOR_GIZMOS_H
diff --git a/tools/editor/translations/Makefile b/tools/editor/translations/Makefile
deleted file mode 100644
index bea20e877d..0000000000
--- a/tools/editor/translations/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# Makefile providing various facilities to manage translations
-
-TEMPLATE = tools.pot
-POFILES = $(wildcard *.po)
-LANGS = $(POFILES:%.po=%)
-
-all: update merge
-
-update:
- @cd ../..; python2 tools/translations/extract.py
-
-merge:
- @for po in $(POFILES); do \
- echo -e "\nMerging $$po..."; \
- msgmerge -w 79 -C $$po $$po $(TEMPLATE) > "$$po".new; \
- mv -f "$$po".new $$po; \
- done
-
-check:
- @for po in $(POFILES); do msgfmt -c $$po -o /dev/null; done
diff --git a/tools/editor/translations/extract.py b/tools/editor/translations/extract.py
deleted file mode 100755
index 1192c19011..0000000000
--- a/tools/editor/translations/extract.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/bin/python
-
-import fnmatch
-import os
-import shutil
-import subprocess
-import sys
-
-
-line_nb = False
-
-for arg in sys.argv[1:]:
- if (arg == "--with-line-nb"):
- print("Enabling line numbers in the context locations.")
- line_nb = True
- else:
- os.sys.exit("Non supported argument '" + arg + "'. Aborting.")
-
-
-if (not os.path.exists("tools")):
- os.sys.exit("ERROR: This script should be started from the root of the git repo.")
-
-
-matches = []
-for root, dirnames, filenames in os.walk('.'):
- for filename in fnmatch.filter(filenames, '*.cpp'):
- if (filename.find("collada") != -1):
- continue
- matches.append(os.path.join(root, filename))
- for filename in fnmatch.filter(filenames, '*.h'):
- if (filename.find("collada") != -1):
- continue
- matches.append(os.path.join(root, filename))
-matches.sort()
-
-
-unique_str = []
-unique_loc = {}
-main_po = """
-# LANGUAGE translation of the Godot Engine editor
-# Copyright (C) 2016-2017 Juan Linietsky, Ariel Manzur and the Godot community
-# This file is distributed under the same license as the Godot source code.
-#
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: Godot Engine editor\\n"
-"Content-Type: text/plain; charset=UTF-8\\n"
-"Content-Transfer-Encoding: 8-bit\\n"
-"""
-
-print("Updating the tools.pot template...")
-
-for fname in matches:
-
- f = open(fname, "rb")
-
- l = f.readline()
- lc = 1
- while (l):
-
- patterns = ['RTR(\"', 'TTR(\"']
- idx = 0
- pos = 0
- while (pos >= 0):
- pos = l.find(patterns[idx], pos)
- if (pos == -1):
- if (idx < len(patterns) - 1):
- idx += 1
- pos = 0
- continue
- pos += 5
-
- msg = ""
- while (pos < len(l) and (l[pos] != '"' or l[pos - 1] == '\\')):
- msg += l[pos]
- pos += 1
-
- location = os.path.relpath(fname).replace('\\', '/')
- if (line_nb):
- location += ":" + str(lc)
-
- if (not msg in unique_str):
- main_po += "\n#: " + location + "\n"
- main_po += 'msgid "' + msg + '"\n'
- main_po += 'msgstr ""\n'
- unique_str.append(msg)
- unique_loc[msg] = [location]
- elif (not location in unique_loc[msg]):
- # Add additional location to previous occurence too
- msg_pos = main_po.find('\nmsgid "' + msg + '"')
- if (msg_pos == -1):
- print("Someone apparently thought writing Python was as easy as GDScript. Ping Akien.")
- main_po = main_po[:msg_pos] + ' ' + location + main_po[msg_pos:]
- unique_loc[msg].append(location)
-
- l = f.readline()
- lc += 1
-
- f.close()
-
-
-f = open("tools.pot", "wb")
-f.write(main_po)
-f.close()
-
-if (os.name == "posix"):
- print("Wrapping template at 79 characters for compatibility with Weblate.")
- os.system("msgmerge -w79 tools.pot tools.pot > tools.pot.wrap")
- shutil.move("tools.pot.wrap", "tools.pot")
-
-shutil.move("tools.pot", "tools/translations/tools.pot")
-
-# TODO: Make that in a portable way, if we care; if not, kudos to Unix users
-if (os.name == "posix"):
- added = subprocess.check_output("git diff tools/translations/tools.pot | grep \+msgid | wc -l", shell=True)
- removed = subprocess.check_output("git diff tools/translations/tools.pot | grep \\\-msgid | wc -l", shell=True)
- print("\n# Template changes compared to the staged status:")
- print("# Additions: %s msgids.\n# Deletions: %s msgids." % (int(added), int(removed)))